typia 14.0.6 → 15.0.0
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/README.md +3 -0
- package/lib/internal/_createLlmEvaluation.d.ts +1 -0
- package/lib/internal/_createLlmEvaluation.js +486 -0
- package/lib/internal/_createLlmEvaluation.js.map +1 -0
- package/lib/internal/_createLlmEvaluation.mjs +382 -0
- package/lib/internal/_createLlmEvaluation.mjs.map +1 -0
- package/lib/internal/_stringLengthGte.d.ts +1 -0
- package/lib/internal/_stringLengthGte.js +14 -0
- package/lib/internal/_stringLengthGte.js.map +1 -0
- package/lib/internal/_stringLengthGte.mjs +11 -0
- package/lib/internal/_stringLengthGte.mjs.map +1 -0
- package/lib/internal/_stringLengthLte.d.ts +1 -0
- package/lib/internal/_stringLengthLte.js +14 -0
- package/lib/internal/_stringLengthLte.js.map +1 -0
- package/lib/internal/_stringLengthLte.mjs +11 -0
- package/lib/internal/_stringLengthLte.mjs.map +1 -0
- package/lib/llm.d.ts +54 -1
- package/lib/llm.js +5 -0
- package/lib/llm.js.map +1 -1
- package/lib/llm.mjs +6 -1
- package/lib/llm.mjs.map +1 -1
- package/lib/re-exports.d.ts +1 -1
- package/lib/re-exports.js.map +1 -1
- package/native/cmd/ttsc-typia/build.go +2 -0
- package/native/cmd/ttsc-typia/dynamic_key_tags_transform_test.go +1 -1
- package/native/cmd/ttsc-typia/llm_evaluation_accepts_property_probability_test.go +27 -0
- package/native/cmd/ttsc-typia/llm_evaluation_accepts_unselected_source_probability_test.go +26 -0
- package/native/cmd/ttsc-typia/llm_evaluation_complete_object_shape_test.go +96 -0
- package/native/cmd/ttsc-typia/llm_evaluation_ignores_declaration_probability_without_call_test.go +18 -0
- package/native/cmd/ttsc-typia/llm_evaluation_plan_emission_transform_test.go +90 -0
- package/native/cmd/ttsc-typia/llm_evaluation_program_scan_dependencies_test.go +69 -0
- package/native/cmd/ttsc-typia/llm_evaluation_rejects_alias_comment_test.go +44 -0
- package/native/cmd/ttsc-typia/llm_evaluation_rejects_alias_refinement_test.go +45 -0
- package/native/cmd/ttsc-typia/llm_evaluation_rejects_computed_method_probability_test.go +30 -0
- package/native/cmd/ttsc-typia/llm_evaluation_rejects_imported_declaration_probability_test.go +48 -0
- package/native/cmd/ttsc-typia/llm_evaluation_rejects_invalid_probability_test.go +199 -0
- package/native/cmd/ttsc-typia/llm_evaluation_rejects_refinements_test.go +94 -0
- package/native/cmd/ttsc-typia/llm_evaluation_rejects_undecidable_types_test.go +232 -0
- package/native/cmd/ttsc-typia/metadata_type_tag_sole_malformed_diagnostic_test.go +94 -0
- package/native/cmd/ttsc-typia/template_literal_type_tags_transform_test.go +3 -2
- package/native/cmd/ttsc-typia/transform.go +2 -0
- package/native/cmd/ttsc-typia/transform_helpers_test.go +17 -3
- package/native/core/context/ITypiaContext.go +4 -0
- package/native/core/factories/IdentifierFactory.go +10 -0
- package/native/core/factories/LiteralFactory.go +16 -0
- package/native/core/factories/MetadataCommentTagFactory.go +12 -10
- package/native/core/factories/MetadataTypeTagFactory.go +97 -24
- package/native/core/factories/MetadataTypeTagSchemaFactory.go +5 -0
- package/native/core/factories/internal/metadata/IMetadataIteratorProps.go +6 -2
- package/native/core/factories/internal/metadata/emplace_metadata_object.go +49 -15
- package/native/core/factories/literal_factory_null_survives_objects_test.go +43 -0
- package/native/core/factories/metadata_comment_tag_factory_string_length_helpers_test.go +55 -0
- package/native/core/factories/metadata_type_tag_factory_reports_all_invalid_candidates_test.go +73 -0
- package/native/core/programmers/llm/LlmApplicationProgrammer.go +1 -0
- package/native/core/programmers/llm/LlmEvaluationProgrammer.go +555 -0
- package/native/core/programmers/llm/LlmParametersProgrammer.go +6 -5
- package/native/core/programmers/llm/LlmReferenceDescription.go +113 -0
- package/native/core/programmers/llm/llm_reference_description_test.go +134 -0
- package/native/core/schemas/metadata/MetadataDependency.go +9 -0
- package/native/transform/CallExpressionTransformer.go +1 -0
- package/native/transform/FileTransformer.go +5 -0
- package/native/transform/features/llm/LlmEvaluationProbabilityDeclarations.go +94 -0
- package/native/transform/features/llm/LlmEvaluationProbabilityDeclarations_test.go +50 -0
- package/native/transform/features/llm/LlmEvaluationTransformer.go +59 -0
- package/native/transform/features/llm/LlmSchemaTransformer.go +14 -11
- package/native/transform/features/llm/llm_transformer_entry_coverage_test.go +29 -27
- package/package.json +3 -3
- package/src/internal/_createLlmEvaluation.ts +678 -0
- package/src/internal/_stringLengthGte.ts +6 -0
- package/src/internal/_stringLengthLte.ts +6 -0
- package/src/llm.ts +64 -0
- package/src/re-exports.ts +1 -0
package/lib/llm.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"llm.mjs","names":[],"sources":["../src/llm.ts"],"sourcesContent":["import {\n IJsonParseResult,\n ILlmApplication,\n ILlmController,\n ILlmSchema,\n ILlmStructuredOutput,\n} from \"@typia/interface\";\n\nimport { NoTransformConfigurationError } from \"./transformers/NoTransformConfigurationError\";\n\n/* -----------------------------------------------------------\n FUNCTION CALLING\n----------------------------------------------------------- */\n/**\n * Creates LLM function calling controller.\n *\n * @danger You must configure the generic argument `Class`\n */\nexport function controller(\n name: string,\n execute: object,\n config?: Partial<Pick<ILlmApplication.IConfig<any>, \"validate\">>,\n): never;\n\n/**\n * Creates LLM function calling controller from class/interface.\n *\n * Generates {@link ILlmController} from a TypeScript class or interface,\n * containing both function calling schemas ({@link ILlmFunction}) and an\n * executor ({@link ILlmController.execute}).\n *\n * Each {@link ILlmFunction} includes a built-in {@link ILlmFunction.validate}\n * function that validates LLM-generated arguments before execution. When\n * validation fails, use `LlmJson.stringify()` from `@typia/utils` to format\n * errors for LLM feedback, enabling auto-correction.\n *\n * When passed to LLM providers (ChatGPT, Claude, Gemini, etc.), the LLM\n * automatically selects functions and fills arguments from conversation.\n * Execute the selected function via {@link ILlmController.execute}.\n *\n * Related functions:\n *\n * - {@link application} — Schemas only, without executor\n * - {@link parameters} — Single parameters schema for structured output\n * - {@link schema} — Single type schema\n *\n * @template Class Target class or interface type\n * @template Config LLM schema configuration\n * @param name Controller identifier name\n * @param execute Executor instance\n * @param config LLM application options\n * @returns LLM function calling controller\n */\nexport function controller<\n Class extends Record<string, any>,\n Config extends Partial<\n ILlmSchema.IConfig & {\n /**\n * Whether to disallow superfluous properties or not.\n *\n * If configure as `true`, {@link validateEquals} function would be used\n * for validation feedback, which is more strict than {@link validate}\n * function.\n *\n * @default false\n */\n equals: boolean;\n }\n > = {},\n>(\n name: string,\n execute: Class,\n config?: Partial<Pick<ILlmApplication.IConfig<Class>, \"validate\">>,\n): ILlmController<Class>;\n\n/** @internal */\nexport function controller(..._args: any[]): never {\n NoTransformConfigurationError(\"llm.controller\");\n}\n\n/**\n * Creates LLM function calling application.\n *\n * @danger You must configure the generic argument `Class`\n */\nexport function application(\n config?: Partial<Pick<ILlmApplication.IConfig<any>, \"validate\">>,\n): never;\n\n/**\n * Creates LLM function calling application from class/interface.\n *\n * Generates {@link ILlmApplication} from a TypeScript class or interface,\n * containing function calling schemas ({@link ILlmFunction}). Does not include\n * an executor—use {@link controller} if you need execution capability.\n *\n * Each {@link ILlmFunction} includes a built-in {@link ILlmFunction.validate}\n * function that validates LLM-generated arguments before execution. When\n * validation fails, use `LlmJson.stringify()` from `@typia/utils` to format\n * errors for LLM feedback, enabling auto-correction.\n *\n * When passed to LLM providers (ChatGPT, Claude, Gemini, etc.), the LLM\n * automatically selects functions and fills arguments from conversation. You\n * execute the function manually with the LLM-prepared arguments.\n *\n * Related functions:\n *\n * - {@link controller} — Includes executor alongside schemas\n * - {@link parameters} — Single parameters schema for structured output\n * - {@link schema} — Single type schema\n *\n * @template Class Target class or interface type\n * @template Config LLM schema configuration\n * @param config LLM application options\n * @returns LLM function calling application\n */\nexport function application<\n Class extends Record<string, any>,\n Config extends Partial<\n ILlmSchema.IConfig & {\n /**\n * Whether to disallow superfluous properties or not.\n *\n * If configure as `true`, {@link validateEquals} function would be used\n * for validation feedback, which is more strict than {@link validate}\n * function.\n *\n * @default false\n */\n equals: boolean;\n }\n > = {},\n>(\n config?: Partial<Pick<ILlmApplication.IConfig<Class>, \"validate\">>,\n): ILlmApplication<Class>;\n\n/** @internal */\nexport function application(): never {\n NoTransformConfigurationError(\"llm.application\");\n}\n\n/**\n * Creates LLM structured output interface.\n *\n * @danger You must configure the generic argument `T`\n */\nexport function structuredOutput(): never;\n\n/**\n * Creates LLM structured output interface from TypeScript object type.\n *\n * Generates {@link ILlmStructuredOutput} containing everything needed for\n * handling LLM structured outputs: the JSON schema for prompting, and functions\n * for parsing, coercing, and validating responses.\n *\n * Structured outputs allow LLMs to generate data conforming to a predefined\n * schema instead of free-form text. This is useful for:\n *\n * - Extracting structured data from conversations\n * - Generating typed responses for downstream processing\n * - Ensuring consistent output formats across LLM calls\n *\n * Workflow:\n *\n * 1. Pass {@link ILlmStructuredOutput.parameters} schema to LLM provider\n * 2. Receive LLM response (JSON string or pre-parsed object)\n * 3. Use {@link ILlmStructuredOutput.parse} for raw strings or\n * {@link ILlmStructuredOutput.coerce} for pre-parsed objects\n * 4. Use {@link ILlmStructuredOutput.validate} to check the result\n *\n * Related functions:\n *\n * - {@link parameters} — Schema only, without parse/coerce/validate\n * - {@link application} — Multiple function schemas from class/interface\n * - {@link controller} — Application with executor\n *\n * @template T Target output type (object with static properties)\n * @template Config LLM schema configuration\n * @returns LLM structured output interface\n */\nexport function structuredOutput<\n T extends Record<string, any>,\n Config extends Partial<\n ILlmSchema.IConfig & {\n /**\n * Whether to disallow superfluous properties or not.\n *\n * If configure as `true`, {@link validateEquals} function would be used\n * for validation feedback, which is more strict than {@link validate}\n * function.\n *\n * @default false\n */\n equals: boolean;\n }\n > = {},\n>(): ILlmStructuredOutput<T>;\n\n/** @internal */\nexport function structuredOutput(): never {\n NoTransformConfigurationError(\"llm.structuredOutput\");\n}\n\n/* -----------------------------------------------------------\n RAW SCHEMAS\n----------------------------------------------------------- */\n/**\n * Creates LLM parameters schema.\n *\n * @danger You must configure the generic argument `Parameters`\n */\nexport function parameters(): never;\n\n/**\n * Creates LLM parameters schema from TypeScript object type.\n *\n * Generates {@link ILlmSchema.IParameters} for LLM function calling or\n * structured outputs. LLMs use keyworded arguments only, so the type must be an\n * object with static properties (no dynamic properties allowed).\n *\n * Use cases:\n *\n * - Function calling: LLM fills parameters from conversation\n * - Structured outputs: LLM generates structured data, not plain text\n *\n * Related functions:\n *\n * - {@link application} — Multiple function schemas from class/interface\n * - {@link controller} — Application with executor\n * - {@link schema} — Single type schema (not parameters-specific)\n *\n * @template Parameters Target parameters type (object with static properties)\n * @template Config LLM schema configuration\n * @returns LLM parameters schema\n */\nexport function parameters<\n Parameters extends Record<string, any>,\n Config extends Partial<ILlmSchema.IConfig> = {},\n>(): ILlmSchema.IParameters;\n\n/** @internal */\nexport function parameters(): never {\n NoTransformConfigurationError(\"llm.parameters\");\n}\n\n/**\n * Creates LLM type schema.\n *\n * @danger You must configure the generic argument `T`\n */\nexport function schema(): never;\n\n/**\n * Creates LLM type schema from TypeScript type.\n *\n * Generates {@link ILlmSchema} for use in LLM function calling. For actual\n * function calling with TypeScript functions, use {@link application}. For\n * structured output generation, use {@link parameters}.\n *\n * LLM function calling flow:\n *\n * 1. LLM selects function and fills arguments from conversation\n * 2. You execute the function with LLM-prepared arguments\n * 3. Return value is passed back to LLM via system prompt\n * 4. LLM continues conversation based on return value\n *\n * Related functions:\n *\n * - {@link application} — Multiple function schemas from class/interface\n * - {@link controller} — Application with executor\n * - {@link parameters} — Parameters schema for structured output\n *\n * @template T Target type\n * @template Config LLM schema configuration\n * @param $defs Shared schema definitions for `$ref` referencing\n * @returns LLM type schema\n */\nexport function schema<T, Config = {}>(\n $defs: Record<string, ILlmSchema>,\n): ILlmSchema;\n\n/** @internal */\nexport function schema(): never {\n NoTransformConfigurationError(\"llm.schema\");\n}\n\n/* -----------------------------------------------------------\n UTILITY FUNCTIONS\n----------------------------------------------------------- */\n/**\n * Parse LLM response JSON with type coercion.\n *\n * @danger You must configure the generic argument `Parameters`\n */\nexport function parse(input: string): never;\n\n/**\n * Parse lenient JSON with schema-based type coercion.\n *\n * Handles incomplete or malformed JSON commonly produced by LLMs:\n *\n * - Unclosed brackets, strings, trailing commas\n * - JavaScript-style comments (`//` and multi-line)\n * - Unquoted object keys, incomplete keywords (`tru`, `fal`, `nul`)\n * - Markdown code block extraction, junk prefix skipping\n *\n * Also coerces double-stringified values based on the `Parameters` schema:\n *\n * - `\"42\"` → `42` (when schema expects number)\n * - `\"true\"` → `true` (when schema expects boolean)\n * - `\"null\"` → `null` (when schema expects null)\n * - `\"{...}\"` → `{...}` (when schema expects object)\n * - `\"[...]\"` → `[...]` (when schema expects array)\n *\n * Type validation is NOT performed—use {@link ILlmFunction.validate} or\n * `typia.validate()` for that.\n *\n * For repeated parsing, use {@link createParse} to avoid regenerating the schema\n * each time.\n *\n * Related functions:\n *\n * - {@link createParse} — Create reusable parser function\n * - {@link coerce} — Type coercion for already-parsed objects\n * - {@link parameters} — Generate parameters schema from type\n *\n * @template Parameters Target parameters type (object with static properties)\n * @template Config LLM schema configuration\n * @param input Raw JSON string (potentially incomplete or malformed)\n * @returns Parse result with typed data on success, or partial data with errors\n */\nexport function parse<\n Parameters extends Record<string, any>,\n Config extends Partial<ILlmSchema.IConfig> = {},\n>(input: string): IJsonParseResult<Parameters>;\n\n/** @internal */\nexport function parse(): never {\n NoTransformConfigurationError(\"llm.parse\");\n}\n\n/**\n * Coerce LLM arguments to match expected schema types.\n *\n * LLMs often return values with incorrect types (e.g., numbers as strings).\n * This function recursively coerces values based on the `Parameters` schema:\n *\n * - `\"42\"` → `42` (when schema expects number)\n * - `\"true\"` → `true` (when schema expects boolean)\n * - `\"null\"` → `null` (when schema expects null)\n * - `\"{...}\"` → `{...}` (when schema expects object)\n * - `\"[...]\"` → `[...]` (when schema expects array)\n *\n * Use this when your SDK provides already-parsed objects but values may have\n * wrong types. For raw JSON strings, use {@link parse} instead.\n *\n * For repeated coercion, use {@link createCoerce} to avoid regenerating the\n * schema each time.\n *\n * Type validation is NOT performed—use {@link ILlmFunction.validate} or\n * `typia.validate()` for that.\n *\n * Related functions:\n *\n * - {@link createCoerce} — Create reusable coercer function\n * - {@link parse} — Parse and coerce raw JSON strings\n * - {@link parameters} — Generate parameters schema from type\n *\n * @template Parameters Target parameters type (object with static properties)\n * @template Config LLM schema configuration\n * @param input Parsed arguments object from LLM (with potentially wrong types)\n * @returns Coerced arguments with corrected types\n */\nexport function coerce<\n Parameters extends Record<string, any>,\n Config extends Partial<ILlmSchema.IConfig> = {},\n>(input: Parameters): Parameters;\n\n/** @internal */\nexport function coerce(): never {\n NoTransformConfigurationError(\"llm.coerce\");\n}\n\n/**\n * Create reusable LLM JSON parser with type coercion.\n *\n * @danger You must configure the generic argument `Parameters`\n */\nexport function createParse(): never;\n\n/**\n * Create reusable lenient JSON parser with schema-based type coercion.\n *\n * Returns a parser function that handles incomplete or malformed JSON commonly\n * produced by LLMs:\n *\n * - Unclosed brackets, strings, trailing commas\n * - JavaScript-style comments (`//` and multi-line)\n * - Unquoted object keys, incomplete keywords (`tru`, `fal`, `nul`)\n * - Markdown code block extraction, junk prefix skipping\n *\n * Also coerces double-stringified values based on the `Parameters` schema:\n *\n * - `\"42\"` → `42` (when schema expects number)\n * - `\"true\"` → `true` (when schema expects boolean)\n * - `\"null\"` → `null` (when schema expects null)\n * - `\"{...}\"` → `{...}` (when schema expects object)\n * - `\"[...]\"` → `[...]` (when schema expects array)\n *\n * Use this instead of {@link parse} when parsing multiple inputs to avoid\n * regenerating the schema each time.\n *\n * Type validation is NOT performed—use {@link ILlmFunction.validate} or\n * `typia.validate()` for that.\n *\n * Related functions:\n *\n * - {@link parse} — One-shot parsing (regenerates schema each call)\n * - {@link createCoerce} — Create reusable coercer function\n * - {@link parameters} — Generate parameters schema from type\n *\n * @template Parameters Target parameters type (object with static properties)\n * @template Config LLM schema configuration\n * @returns Reusable parser function\n */\nexport function createParse<\n Parameters extends Record<string, any>,\n Config extends Partial<ILlmSchema.IConfig> = {},\n>(): (input: string) => IJsonParseResult<Parameters>;\n\n/** @internal */\nexport function createParse(): never {\n NoTransformConfigurationError(\"llm.createParse\");\n}\n\n/**\n * Create reusable LLM arguments coercer.\n *\n * @danger You must configure the generic argument `Parameters`\n */\nexport function createCoerce(): never;\n\n/**\n * Create reusable coercer for LLM arguments.\n *\n * Returns a coercer function that fixes incorrect types commonly returned by\n * LLMs (e.g., numbers as strings). Coerces values based on the `Parameters`\n * schema:\n *\n * - `\"42\"` → `42` (when schema expects number)\n * - `\"true\"` → `true` (when schema expects boolean)\n * - `\"null\"` → `null` (when schema expects null)\n * - `\"{...}\"` → `{...}` (when schema expects object)\n * - `\"[...]\"` → `[...]` (when schema expects array)\n *\n * Use this instead of {@link coerce} when coercing multiple inputs to avoid\n * regenerating the schema each time.\n *\n * Type validation is NOT performed—use {@link ILlmFunction.validate} or\n * `typia.validate()` for that.\n *\n * Related functions:\n *\n * - {@link coerce} — One-shot coercion (regenerates schema each call)\n * - {@link createParse} — Create reusable parser function\n * - {@link parameters} — Generate parameters schema from type\n *\n * @template Parameters Target parameters type (object with static properties)\n * @template Config LLM schema configuration\n * @returns Reusable coercer function\n */\nexport function createCoerce<\n Parameters extends Record<string, any>,\n Config extends Partial<ILlmSchema.IConfig> = {},\n>(): (input: Parameters) => Parameters;\n\n/** @internal */\nexport function createCoerce(): never {\n NoTransformConfigurationError(\"llm.createCoerce\");\n}\n"],"mappings":";;;;;;;;;;;;;;;AA4EA,SAAgB,WAAW,GAAG,OAAqB;CACjD,8BAA8B,gBAAgB;AAChD;;AA2DA,SAAgB,cAAqB;CACnC,8BAA8B,iBAAiB;AACjD;;AA4DA,SAAgB,mBAA0B;CACxC,8BAA8B,sBAAsB;AACtD;;AAwCA,SAAgB,aAAoB;CAClC,8BAA8B,gBAAgB;AAChD;;AAuCA,SAAgB,SAAgB;CAC9B,8BAA8B,YAAY;AAC5C;;AAqDA,SAAgB,QAAe;CAC7B,8BAA8B,WAAW;AAC3C;;AAwCA,SAAgB,SAAgB;CAC9B,8BAA8B,YAAY;AAC5C;;AAkDA,SAAgB,cAAqB;CACnC,8BAA8B,iBAAiB;AACjD;;AA4CA,SAAgB,eAAsB;CACpC,8BAA8B,kBAAkB;AAClD"}
|
|
1
|
+
{"version":3,"file":"llm.mjs","names":[],"sources":["../src/llm.ts"],"sourcesContent":["import {\n IJsonParseResult,\n ILlmApplication,\n ILlmController,\n ILlmEvaluation,\n ILlmSchema,\n ILlmStructuredOutput,\n} from \"@typia/interface\";\n\nimport { NoTransformConfigurationError } from \"./transformers/NoTransformConfigurationError\";\n\n/* -----------------------------------------------------------\n FUNCTION CALLING\n----------------------------------------------------------- */\n/**\n * Creates LLM function calling controller.\n *\n * @danger You must configure the generic argument `Class`\n */\nexport function controller(\n name: string,\n execute: object,\n config?: Partial<Pick<ILlmApplication.IConfig<any>, \"validate\">>,\n): never;\n\n/**\n * Creates LLM function calling controller from class/interface.\n *\n * Generates {@link ILlmController} from a TypeScript class or interface,\n * containing both function calling schemas ({@link ILlmFunction}) and an\n * executor ({@link ILlmController.execute}).\n *\n * Each {@link ILlmFunction} includes a built-in {@link ILlmFunction.validate}\n * function that validates LLM-generated arguments before execution. When\n * validation fails, use `LlmJson.stringify()` from `@typia/utils` to format\n * errors for LLM feedback, enabling auto-correction.\n *\n * When passed to LLM providers (ChatGPT, Claude, Gemini, etc.), the LLM\n * automatically selects functions and fills arguments from conversation.\n * Execute the selected function via {@link ILlmController.execute}.\n *\n * Related functions:\n *\n * - {@link application} — Schemas only, without executor\n * - {@link parameters} — Single parameters schema for structured output\n * - {@link schema} — Single type schema\n *\n * @template Class Target class or interface type\n * @template Config LLM schema configuration\n * @param name Controller identifier name\n * @param execute Executor instance\n * @param config LLM application options\n * @returns LLM function calling controller\n */\nexport function controller<\n Class extends Record<string, any>,\n Config extends Partial<\n ILlmSchema.IConfig & {\n /**\n * Whether to disallow superfluous properties or not.\n *\n * If configure as `true`, {@link validateEquals} function would be used\n * for validation feedback, which is more strict than {@link validate}\n * function.\n *\n * @default false\n */\n equals: boolean;\n }\n > = {},\n>(\n name: string,\n execute: Class,\n config?: Partial<Pick<ILlmApplication.IConfig<Class>, \"validate\">>,\n): ILlmController<Class>;\n\n/** @internal */\nexport function controller(..._args: any[]): never {\n NoTransformConfigurationError(\"llm.controller\");\n}\n\n/**\n * Creates LLM function calling application.\n *\n * @danger You must configure the generic argument `Class`\n */\nexport function application(\n config?: Partial<Pick<ILlmApplication.IConfig<any>, \"validate\">>,\n): never;\n\n/**\n * Creates LLM function calling application from class/interface.\n *\n * Generates {@link ILlmApplication} from a TypeScript class or interface,\n * containing function calling schemas ({@link ILlmFunction}). Does not include\n * an executor—use {@link controller} if you need execution capability.\n *\n * Each {@link ILlmFunction} includes a built-in {@link ILlmFunction.validate}\n * function that validates LLM-generated arguments before execution. When\n * validation fails, use `LlmJson.stringify()` from `@typia/utils` to format\n * errors for LLM feedback, enabling auto-correction.\n *\n * When passed to LLM providers (ChatGPT, Claude, Gemini, etc.), the LLM\n * automatically selects functions and fills arguments from conversation. You\n * execute the function manually with the LLM-prepared arguments.\n *\n * Related functions:\n *\n * - {@link controller} — Includes executor alongside schemas\n * - {@link parameters} — Single parameters schema for structured output\n * - {@link schema} — Single type schema\n *\n * @template Class Target class or interface type\n * @template Config LLM schema configuration\n * @param config LLM application options\n * @returns LLM function calling application\n */\nexport function application<\n Class extends Record<string, any>,\n Config extends Partial<\n ILlmSchema.IConfig & {\n /**\n * Whether to disallow superfluous properties or not.\n *\n * If configure as `true`, {@link validateEquals} function would be used\n * for validation feedback, which is more strict than {@link validate}\n * function.\n *\n * @default false\n */\n equals: boolean;\n }\n > = {},\n>(\n config?: Partial<Pick<ILlmApplication.IConfig<Class>, \"validate\">>,\n): ILlmApplication<Class>;\n\n/** @internal */\nexport function application(): never {\n NoTransformConfigurationError(\"llm.application\");\n}\n\n/**\n * Creates LLM structured output interface.\n *\n * @danger You must configure the generic argument `T`\n */\nexport function structuredOutput(): never;\n\n/**\n * Creates LLM structured output interface from TypeScript object type.\n *\n * Generates {@link ILlmStructuredOutput} containing everything needed for\n * handling LLM structured outputs: the JSON schema for prompting, and functions\n * for parsing, coercing, and validating responses.\n *\n * Structured outputs allow LLMs to generate data conforming to a predefined\n * schema instead of free-form text. This is useful for:\n *\n * - Extracting structured data from conversations\n * - Generating typed responses for downstream processing\n * - Ensuring consistent output formats across LLM calls\n *\n * Workflow:\n *\n * 1. Pass {@link ILlmStructuredOutput.parameters} schema to LLM provider\n * 2. Receive LLM response (JSON string or pre-parsed object)\n * 3. Use {@link ILlmStructuredOutput.parse} for raw strings or\n * {@link ILlmStructuredOutput.coerce} for pre-parsed objects\n * 4. Use {@link ILlmStructuredOutput.validate} to check the result\n *\n * Related functions:\n *\n * - {@link parameters} — Schema only, without parse/coerce/validate\n * - {@link application} — Multiple function schemas from class/interface\n * - {@link controller} — Application with executor\n *\n * @template T Target output type (object with static properties)\n * @template Config LLM schema configuration\n * @returns LLM structured output interface\n */\nexport function structuredOutput<\n T extends Record<string, any>,\n Config extends Partial<\n ILlmSchema.IConfig & {\n /**\n * Whether to disallow superfluous properties or not.\n *\n * If configure as `true`, {@link validateEquals} function would be used\n * for validation feedback, which is more strict than {@link validate}\n * function.\n *\n * @default false\n */\n equals: boolean;\n }\n > = {},\n>(): ILlmStructuredOutput<T>;\n\n/** @internal */\nexport function structuredOutput(): never {\n NoTransformConfigurationError(\"llm.structuredOutput\");\n}\n\n/* -----------------------------------------------------------\n EVALUATION\n----------------------------------------------------------- */\n/**\n * Creates LLM evaluation questions.\n *\n * @danger You must configure the generic argument `T`\n */\nexport function evaluation(): never;\n\n/**\n * Creates LLM evaluation questions from TypeScript object type.\n *\n * Generates {@link ILlmEvaluation} for evaluation models, which answer typed\n * questions about a shared state with probabilities instead of generating text:\n * TypeSafe's Jev natively, and OpenAI, Anthropic, and Google through Vercel AI\n * SDK's `experimental_evaluate()`.\n *\n * Every leaf property of `T` becomes one question, and its JSDoc description\n * becomes the question text:\n *\n * - `boolean` → boolean question\n * - String enum or string literal union → choice question\n * - Numeric enum or numeric literal union → score question\n * - Array of a string literal union or string enum → one boolean question per\n * member\n * - Nested object → flattened, one question per leaf\n *\n * Types an evaluation model cannot answer, such as `string`, `number`, optional\n * properties, or a leaf without a JSDoc description, are compile errors. Use\n * `tags.Probability<N>` or `@probability N` to set decision thresholds and\n * acceptance minimums. Once one choice, score, or set member declares a\n * requirement, every member must declare one or inherit the property's\n * `@probability` default. A nested object's own JSDoc description is not sent\n * to the model; only the leaves' descriptions become question text. Other\n * validation refinements that the answer decoder cannot enforce are compile\n * errors.\n *\n * This feature is experimental. It follows Vercel AI SDK's evaluation model\n * specification, which is itself experimental and may change in patch\n * releases.\n *\n * Workflow:\n *\n * 1. Pass {@link ILlmEvaluation.questions} to the evaluation model\n * 2. Receive the answer map keyed by the same question IDs\n * 3. Use {@link ILlmEvaluation.decode} to fold the answers back into `T`; pass the\n * model's declared rounding precision when available\n *\n * Related functions:\n *\n * - {@link structuredOutput} — Structured output generated as text by an LLM\n *\n * @template T Target decision type (object with static properties)\n * @returns LLM evaluation questions with a checked answer decoder\n */\nexport function evaluation<T extends Record<string, any>>(): ILlmEvaluation<T>;\n\n/** @internal */\nexport function evaluation(): never {\n NoTransformConfigurationError(\"llm.evaluation\");\n}\n\n/* -----------------------------------------------------------\n RAW SCHEMAS\n----------------------------------------------------------- */\n/**\n * Creates LLM parameters schema.\n *\n * @danger You must configure the generic argument `Parameters`\n */\nexport function parameters(): never;\n\n/**\n * Creates LLM parameters schema from TypeScript object type.\n *\n * Generates {@link ILlmSchema.IParameters} for LLM function calling or\n * structured outputs. LLMs use keyworded arguments only, so the type must be an\n * object with static properties (no dynamic properties allowed).\n *\n * Use cases:\n *\n * - Function calling: LLM fills parameters from conversation\n * - Structured outputs: LLM generates structured data, not plain text\n *\n * Related functions:\n *\n * - {@link application} — Multiple function schemas from class/interface\n * - {@link controller} — Application with executor\n * - {@link schema} — Single type schema (not parameters-specific)\n *\n * @template Parameters Target parameters type (object with static properties)\n * @template Config LLM schema configuration\n * @returns LLM parameters schema\n */\nexport function parameters<\n Parameters extends Record<string, any>,\n Config extends Partial<ILlmSchema.IConfig> = {},\n>(): ILlmSchema.IParameters;\n\n/** @internal */\nexport function parameters(): never {\n NoTransformConfigurationError(\"llm.parameters\");\n}\n\n/**\n * Creates LLM type schema.\n *\n * @danger You must configure the generic argument `T`\n */\nexport function schema(): never;\n\n/**\n * Creates LLM type schema from TypeScript type.\n *\n * Generates {@link ILlmSchema} for use in LLM function calling. For actual\n * function calling with TypeScript functions, use {@link application}. For\n * structured output generation, use {@link parameters}.\n *\n * LLM function calling flow:\n *\n * 1. LLM selects function and fills arguments from conversation\n * 2. You execute the function with LLM-prepared arguments\n * 3. Return value is passed back to LLM via system prompt\n * 4. LLM continues conversation based on return value\n *\n * Related functions:\n *\n * - {@link application} — Multiple function schemas from class/interface\n * - {@link controller} — Application with executor\n * - {@link parameters} — Parameters schema for structured output\n *\n * @template T Target type\n * @template Config LLM schema configuration\n * @param $defs Shared schema definitions for `$ref` referencing\n * @returns LLM type schema\n */\nexport function schema<T, Config = {}>(\n $defs: Record<string, ILlmSchema>,\n): ILlmSchema;\n\n/** @internal */\nexport function schema(): never {\n NoTransformConfigurationError(\"llm.schema\");\n}\n\n/* -----------------------------------------------------------\n UTILITY FUNCTIONS\n----------------------------------------------------------- */\n/**\n * Parse LLM response JSON with type coercion.\n *\n * @danger You must configure the generic argument `Parameters`\n */\nexport function parse(input: string): never;\n\n/**\n * Parse lenient JSON with schema-based type coercion.\n *\n * Handles incomplete or malformed JSON commonly produced by LLMs:\n *\n * - Unclosed brackets, strings, trailing commas\n * - JavaScript-style comments (`//` and multi-line)\n * - Unquoted object keys, incomplete keywords (`tru`, `fal`, `nul`)\n * - Markdown code block extraction, junk prefix skipping\n *\n * Also coerces double-stringified values based on the `Parameters` schema:\n *\n * - `\"42\"` → `42` (when schema expects number)\n * - `\"true\"` → `true` (when schema expects boolean)\n * - `\"null\"` → `null` (when schema expects null)\n * - `\"{...}\"` → `{...}` (when schema expects object)\n * - `\"[...]\"` → `[...]` (when schema expects array)\n *\n * Type validation is NOT performed—use {@link ILlmFunction.validate} or\n * `typia.validate()` for that.\n *\n * For repeated parsing, use {@link createParse} to avoid regenerating the schema\n * each time.\n *\n * Related functions:\n *\n * - {@link createParse} — Create reusable parser function\n * - {@link coerce} — Type coercion for already-parsed objects\n * - {@link parameters} — Generate parameters schema from type\n *\n * @template Parameters Target parameters type (object with static properties)\n * @template Config LLM schema configuration\n * @param input Raw JSON string (potentially incomplete or malformed)\n * @returns Parse result with typed data on success, or partial data with errors\n */\nexport function parse<\n Parameters extends Record<string, any>,\n Config extends Partial<ILlmSchema.IConfig> = {},\n>(input: string): IJsonParseResult<Parameters>;\n\n/** @internal */\nexport function parse(): never {\n NoTransformConfigurationError(\"llm.parse\");\n}\n\n/**\n * Coerce LLM arguments to match expected schema types.\n *\n * LLMs often return values with incorrect types (e.g., numbers as strings).\n * This function recursively coerces values based on the `Parameters` schema:\n *\n * - `\"42\"` → `42` (when schema expects number)\n * - `\"true\"` → `true` (when schema expects boolean)\n * - `\"null\"` → `null` (when schema expects null)\n * - `\"{...}\"` → `{...}` (when schema expects object)\n * - `\"[...]\"` → `[...]` (when schema expects array)\n *\n * Use this when your SDK provides already-parsed objects but values may have\n * wrong types. For raw JSON strings, use {@link parse} instead.\n *\n * For repeated coercion, use {@link createCoerce} to avoid regenerating the\n * schema each time.\n *\n * Type validation is NOT performed—use {@link ILlmFunction.validate} or\n * `typia.validate()` for that.\n *\n * Related functions:\n *\n * - {@link createCoerce} — Create reusable coercer function\n * - {@link parse} — Parse and coerce raw JSON strings\n * - {@link parameters} — Generate parameters schema from type\n *\n * @template Parameters Target parameters type (object with static properties)\n * @template Config LLM schema configuration\n * @param input Parsed arguments object from LLM (with potentially wrong types)\n * @returns Coerced arguments with corrected types\n */\nexport function coerce<\n Parameters extends Record<string, any>,\n Config extends Partial<ILlmSchema.IConfig> = {},\n>(input: Parameters): Parameters;\n\n/** @internal */\nexport function coerce(): never {\n NoTransformConfigurationError(\"llm.coerce\");\n}\n\n/**\n * Create reusable LLM JSON parser with type coercion.\n *\n * @danger You must configure the generic argument `Parameters`\n */\nexport function createParse(): never;\n\n/**\n * Create reusable lenient JSON parser with schema-based type coercion.\n *\n * Returns a parser function that handles incomplete or malformed JSON commonly\n * produced by LLMs:\n *\n * - Unclosed brackets, strings, trailing commas\n * - JavaScript-style comments (`//` and multi-line)\n * - Unquoted object keys, incomplete keywords (`tru`, `fal`, `nul`)\n * - Markdown code block extraction, junk prefix skipping\n *\n * Also coerces double-stringified values based on the `Parameters` schema:\n *\n * - `\"42\"` → `42` (when schema expects number)\n * - `\"true\"` → `true` (when schema expects boolean)\n * - `\"null\"` → `null` (when schema expects null)\n * - `\"{...}\"` → `{...}` (when schema expects object)\n * - `\"[...]\"` → `[...]` (when schema expects array)\n *\n * Use this instead of {@link parse} when parsing multiple inputs to avoid\n * regenerating the schema each time.\n *\n * Type validation is NOT performed—use {@link ILlmFunction.validate} or\n * `typia.validate()` for that.\n *\n * Related functions:\n *\n * - {@link parse} — One-shot parsing (regenerates schema each call)\n * - {@link createCoerce} — Create reusable coercer function\n * - {@link parameters} — Generate parameters schema from type\n *\n * @template Parameters Target parameters type (object with static properties)\n * @template Config LLM schema configuration\n * @returns Reusable parser function\n */\nexport function createParse<\n Parameters extends Record<string, any>,\n Config extends Partial<ILlmSchema.IConfig> = {},\n>(): (input: string) => IJsonParseResult<Parameters>;\n\n/** @internal */\nexport function createParse(): never {\n NoTransformConfigurationError(\"llm.createParse\");\n}\n\n/**\n * Create reusable LLM arguments coercer.\n *\n * @danger You must configure the generic argument `Parameters`\n */\nexport function createCoerce(): never;\n\n/**\n * Create reusable coercer for LLM arguments.\n *\n * Returns a coercer function that fixes incorrect types commonly returned by\n * LLMs (e.g., numbers as strings). Coerces values based on the `Parameters`\n * schema:\n *\n * - `\"42\"` → `42` (when schema expects number)\n * - `\"true\"` → `true` (when schema expects boolean)\n * - `\"null\"` → `null` (when schema expects null)\n * - `\"{...}\"` → `{...}` (when schema expects object)\n * - `\"[...]\"` → `[...]` (when schema expects array)\n *\n * Use this instead of {@link coerce} when coercing multiple inputs to avoid\n * regenerating the schema each time.\n *\n * Type validation is NOT performed—use {@link ILlmFunction.validate} or\n * `typia.validate()` for that.\n *\n * Related functions:\n *\n * - {@link coerce} — One-shot coercion (regenerates schema each call)\n * - {@link createParse} — Create reusable parser function\n * - {@link parameters} — Generate parameters schema from type\n *\n * @template Parameters Target parameters type (object with static properties)\n * @template Config LLM schema configuration\n * @returns Reusable coercer function\n */\nexport function createCoerce<\n Parameters extends Record<string, any>,\n Config extends Partial<ILlmSchema.IConfig> = {},\n>(): (input: Parameters) => Parameters;\n\n/** @internal */\nexport function createCoerce(): never {\n NoTransformConfigurationError(\"llm.createCoerce\");\n}\n"],"mappings":";;;;;;;;;;;;;;;;AA6EA,SAAgB,WAAW,GAAG,OAAqB;CACjD,8BAA8B,gBAAgB;AAChD;;AA2DA,SAAgB,cAAqB;CACnC,8BAA8B,iBAAiB;AACjD;;AA4DA,SAAgB,mBAA0B;CACxC,8BAA8B,sBAAsB;AACtD;;AA6DA,SAAgB,aAAoB;CAClC,8BAA8B,gBAAgB;AAChD;;AAwCA,SAAgB,aAAoB;CAClC,8BAA8B,gBAAgB;AAChD;;AAuCA,SAAgB,SAAgB;CAC9B,8BAA8B,YAAY;AAC5C;;AAqDA,SAAgB,QAAe;CAC7B,8BAA8B,WAAW;AAC3C;;AAwCA,SAAgB,SAAgB;CAC9B,8BAA8B,YAAY;AAC5C;;AAkDA,SAAgB,cAAqB;CACnC,8BAA8B,iBAAiB;AACjD;;AA4CA,SAAgB,eAAsB;CACpC,8BAA8B,kBAAkB;AAClD"}
|
package/lib/re-exports.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export type { AssertionGuard, IJsonParseResult, IValidation, IRandomGenerator, StandardSchemaV1, OpenApi, IJsonSchemaApplication, IJsonSchemaCollection, IJsonSchemaUnit, ILlmController, ILlmApplication, ILlmFunction, ILlmStructuredOutput, ILlmSchema, IMetadataSchema, IMetadataSchemaCollection, IMetadataSchemaUnit, IMetadataComponents, IMetadataTypeTag, IJsDocTagInfo, Atomic, Classifiable, ClassifyResult, Primitive, Resolved, CamelCase, KebabCase, PascalCase, SnakeCase, IReadableURLSearchParams, } from "@typia/interface";
|
|
1
|
+
export type { AssertionGuard, IJsonParseResult, IValidation, IRandomGenerator, StandardSchemaV1, OpenApi, IJsonSchemaApplication, IJsonSchemaCollection, IJsonSchemaUnit, ILlmController, ILlmApplication, ILlmFunction, ILlmStructuredOutput, ILlmEvaluation, ILlmSchema, IMetadataSchema, IMetadataSchemaCollection, IMetadataSchemaUnit, IMetadataComponents, IMetadataTypeTag, IJsDocTagInfo, Atomic, Classifiable, ClassifyResult, Primitive, Resolved, CamelCase, KebabCase, PascalCase, SnakeCase, IReadableURLSearchParams, } from "@typia/interface";
|
|
2
2
|
export { tags } from "@typia/interface";
|
package/lib/re-exports.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"re-exports.js","sourceRoot":"","sources":["../src/re-exports.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"re-exports.js","sourceRoot":"","sources":["../src/re-exports.ts"],"names":[],"mappings":";;;AAkDA,0EAA0E;AAC1E,sEAAsE;AACtE,0EAA0E;AAC1E,mEAAmE;AACnE,sBAAsB;AACtB,8CAAwC;AAA/B,iGAAA,IAAI,OAAA"}
|
|
@@ -7,6 +7,7 @@ import (
|
|
|
7
7
|
"io"
|
|
8
8
|
"os"
|
|
9
9
|
"path/filepath"
|
|
10
|
+
"sync"
|
|
10
11
|
|
|
11
12
|
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
12
13
|
shimcompiler "github.com/microsoft/typescript-go/shim/compiler"
|
|
@@ -114,6 +115,7 @@ func runBuild(args []string) int {
|
|
|
114
115
|
transformDiags := []typiaTransformDiagnostic{}
|
|
115
116
|
transformOptions := pluginOptions.TransformOptions()
|
|
116
117
|
extras := nativecontext.ITypiaContext_Extras{
|
|
118
|
+
Shared: &sync.Map{},
|
|
117
119
|
AddDiagnostic: func(diag *nativecontext.ITypiaDiagnostic) int {
|
|
118
120
|
transformDiags = append(transformDiags, typiaTransformDiagnosticFrom(diag))
|
|
119
121
|
return len(transformDiags)
|
|
@@ -54,7 +54,7 @@ func TestDynamicKeyTagsTransform(t *testing.T) {
|
|
|
54
54
|
}
|
|
55
55
|
// The key is read into a local before it is tested, so its predicate is the
|
|
56
56
|
// one place the emitted text can show the check exists at all.
|
|
57
|
-
if !strings.Contains(out, "RegExp(") || !strings.Contains(out, "
|
|
57
|
+
if !strings.Contains(out, "RegExp(") || !strings.Contains(out, "_stringLengthGte") {
|
|
58
58
|
t.Fatalf("emitted checker should test the dynamic key, not only its value:\n%s", out)
|
|
59
59
|
}
|
|
60
60
|
dynamicKeyTagsRunRuntimeCases(t, project, out)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import "testing"
|
|
4
|
+
|
|
5
|
+
// TestLlmEvaluationAcceptsPropertyAndEnumMemberProbability verifies both
|
|
6
|
+
// supported JSDoc placements compile with the upper probability boundary.
|
|
7
|
+
//
|
|
8
|
+
// Primitive aliases may erase their name, but a final decision property's
|
|
9
|
+
// comment and enum members' comments remain attached to their declarations.
|
|
10
|
+
//
|
|
11
|
+
// 1. Declare an aliased boolean and a probability-annotated enum.
|
|
12
|
+
// 2. Put probability one on the final boolean decision property.
|
|
13
|
+
// 3. Require successful compilation.
|
|
14
|
+
func TestLlmEvaluationAcceptsPropertyAndEnumMemberProbability(t *testing.T) {
|
|
15
|
+
llmEvaluationAccepts(t, "property-probability-valid", `import typia from "typia";
|
|
16
|
+
|
|
17
|
+
type Urgency = boolean;
|
|
18
|
+
enum Choice {
|
|
19
|
+
/** @probability 1 */ yes = "yes",
|
|
20
|
+
/** @probability 0.2 */ no = "no",
|
|
21
|
+
}
|
|
22
|
+
typia.llm.evaluation<{
|
|
23
|
+
/** Urgent? @probability 1 */ urgent: Urgency;
|
|
24
|
+
/** Choice? */ choice: Choice;
|
|
25
|
+
}>();
|
|
26
|
+
`)
|
|
27
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import "testing"
|
|
4
|
+
|
|
5
|
+
// TestLlmEvaluationAcceptsUnselectedSourceProbability verifies a comment on
|
|
6
|
+
// an unrelated property does not constrain an indexed-access decision.
|
|
7
|
+
//
|
|
8
|
+
// Indexed access extracts a property type, not its JSDoc. An annotation on a
|
|
9
|
+
// different source property must not reject an otherwise valid evaluation.
|
|
10
|
+
//
|
|
11
|
+
// 1. Declare an annotated and an unannotated source property.
|
|
12
|
+
// 2. Extract the unannotated property's type for an evaluation decision.
|
|
13
|
+
// 3. Require successful compilation.
|
|
14
|
+
func TestLlmEvaluationAcceptsUnselectedSourceProbability(t *testing.T) {
|
|
15
|
+
llmEvaluationAccepts(t, "unselected-source-probability", `import typia from "typia";
|
|
16
|
+
interface Source {
|
|
17
|
+
/** @probability 0.8 */ ignored: boolean;
|
|
18
|
+
selected: boolean;
|
|
19
|
+
}
|
|
20
|
+
type Value = Source["selected"];
|
|
21
|
+
typia.llm.evaluation<{
|
|
22
|
+
/** Is it urgent? */
|
|
23
|
+
urgent: Value;
|
|
24
|
+
}>();
|
|
25
|
+
`)
|
|
26
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"strings"
|
|
5
|
+
"testing"
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
// Evaluation promises to decode the entire T. Every required member must
|
|
9
|
+
// become a question or fail compilation, including inherited/nested members.
|
|
10
|
+
func TestLlmEvaluationCompleteObjectShape(t *testing.T) {
|
|
11
|
+
accepted := map[string]string{
|
|
12
|
+
"getter only": `class Decision {
|
|
13
|
+
/** Is it urgent? @probability 1 */ get urgent(): boolean { return true; }
|
|
14
|
+
}`,
|
|
15
|
+
"class getter": `class Decision {
|
|
16
|
+
/** Is it active? */ active!: boolean;
|
|
17
|
+
/** Is it urgent? @probability 1 */ get urgent(): boolean { return true; }
|
|
18
|
+
}`,
|
|
19
|
+
"inherited getter": `class Base {
|
|
20
|
+
/** Is it urgent? @probability 1 */ get urgent(): boolean { return true; }
|
|
21
|
+
}
|
|
22
|
+
class Decision extends Base {
|
|
23
|
+
/** Is it active? */
|
|
24
|
+
active!: boolean;
|
|
25
|
+
}`,
|
|
26
|
+
"interface getter": `interface Decision {
|
|
27
|
+
/** Is it active? */ active: boolean;
|
|
28
|
+
/** Is it urgent? @probability 1 */ get urgent(): boolean;
|
|
29
|
+
}`,
|
|
30
|
+
"nested getter": `class Child {
|
|
31
|
+
/** Is it urgent? @probability 1 */ get urgent(): boolean { return true; }
|
|
32
|
+
}
|
|
33
|
+
interface Decision { child: Child; }`,
|
|
34
|
+
"setter": `class Decision {
|
|
35
|
+
/** Is it active? */ active!: boolean;
|
|
36
|
+
/** Is it urgent? @probability 1 */ set urgent(value: boolean) {}
|
|
37
|
+
}`,
|
|
38
|
+
}
|
|
39
|
+
for name, declaration := range accepted {
|
|
40
|
+
t.Run(name, func(t *testing.T) {
|
|
41
|
+
source := `import typia from "typia";` + declaration + `
|
|
42
|
+
export const evaluation = typia.llm.evaluation<Decision>();`
|
|
43
|
+
project := llmEvaluationProject(t, "complete-"+strings.ReplaceAll(name, " ", "-"), source)
|
|
44
|
+
out, diagnostic, code := ttscTypiaTestCapture(func() int {
|
|
45
|
+
return runTransform([]string{"--cwd", project, "--tsconfig", "tsconfig.json", "--file", "src/main.ts", "--output", "js"})
|
|
46
|
+
})
|
|
47
|
+
if code != 0 || !strings.Contains(out, "threshold: 1") || !strings.Contains(out, `"urgent"`) {
|
|
48
|
+
t.Fatalf("getter is not in the plan: code=%d threshold=%t urgent=%t diagnostic=%s", code, strings.Contains(out, "threshold: 1"), strings.Contains(out, `"urgent"`), diagnostic)
|
|
49
|
+
}
|
|
50
|
+
})
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
rejected := map[string]struct{ declaration, diagnostic string }{
|
|
54
|
+
"method": {`interface Decision { /** Is it active? */ active: boolean; execute(): void; }`, "function"},
|
|
55
|
+
"private": {`class Decision { /** Is it active? */ active!: boolean; private token = 1; }`, "private"},
|
|
56
|
+
"protected": {`class Decision { /** Is it active? */ active!: boolean; protected token = 1; }`, "protected"},
|
|
57
|
+
"sharp private": {`class Decision { /** Is it active? */ active!: boolean; #token = 1; }`, "private"},
|
|
58
|
+
"symbol": {`declare const token: unique symbol; interface Decision { /** Is it active? */ active: boolean; [token]: boolean; }`, "symbol-keyed"},
|
|
59
|
+
"symbol index": {`interface Decision { /** Is it active? */ active: boolean; [key: symbol]: boolean; }`, "symbol-keyed"},
|
|
60
|
+
"call": {`interface Decision { /** Is it active? */ active: boolean; (): void; }`, "callable"},
|
|
61
|
+
"construct": {`interface Decision { /** Is it active? */ active: boolean; new(): Decision; }`, "constructable"},
|
|
62
|
+
"nested method": {`interface Child { /** Is it urgent? */ urgent: boolean; execute(): void; }
|
|
63
|
+
interface Decision { child: Child; }`, "function"},
|
|
64
|
+
"inherited private": {`class Base { private token = 1; }
|
|
65
|
+
class Decision extends Base { /** Is it active? */ active!: boolean; }`, "private"},
|
|
66
|
+
"generic private": {`class Base<T> { private token!: T; }
|
|
67
|
+
class Decision extends Base<boolean> { /** Is it active? */ active!: boolean; }`, "private"},
|
|
68
|
+
"generic sharp private": {`class Base<T> { #token!: T; }
|
|
69
|
+
class Decision extends Base<boolean> { /** Is it active? */ active!: boolean; }`, "private"},
|
|
70
|
+
"interface extends private class": {`class Base { private token!: boolean; }
|
|
71
|
+
interface Decision extends Base { active: boolean; }`, "private"},
|
|
72
|
+
"internal": {`interface Decision {
|
|
73
|
+
/** Is it active? */ active: boolean;
|
|
74
|
+
/** @internal */ secret: boolean;
|
|
75
|
+
}`, "hidden properties"},
|
|
76
|
+
"intersection internal": {`type Decision = {
|
|
77
|
+
/** Is it active? */ active: boolean;
|
|
78
|
+
} & {
|
|
79
|
+
/** @internal */ secret: boolean;
|
|
80
|
+
};`, "hidden properties"},
|
|
81
|
+
"overlapping intersection internal": {`type Decision = {
|
|
82
|
+
/** Is it active? */ active: boolean;
|
|
83
|
+
/** @internal */ secret: boolean;
|
|
84
|
+
} & { secret: boolean };`, "hidden properties"},
|
|
85
|
+
}
|
|
86
|
+
for name, testcase := range rejected {
|
|
87
|
+
t.Run(name, func(t *testing.T) {
|
|
88
|
+
source := `import typia from "typia";` + testcase.declaration + `
|
|
89
|
+
export const evaluation = typia.llm.evaluation<Decision>();`
|
|
90
|
+
diagnostic := llmEvaluationDiagnosticsBuild(t, "complete-"+strings.ReplaceAll(name, " ", "-"), source)
|
|
91
|
+
if !strings.Contains(diagnostic, testcase.diagnostic) {
|
|
92
|
+
t.Fatalf("missing %q diagnostic: %s", testcase.diagnostic, diagnostic)
|
|
93
|
+
}
|
|
94
|
+
})
|
|
95
|
+
}
|
|
96
|
+
}
|
package/native/cmd/ttsc-typia/llm_evaluation_ignores_declaration_probability_without_call_test.go
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import "testing"
|
|
4
|
+
|
|
5
|
+
// TestLlmEvaluationIgnoresDeclarationProbabilityWithoutCall verifies a
|
|
6
|
+
// program without evaluation calls does not trigger JEV-specific diagnostics.
|
|
7
|
+
//
|
|
8
|
+
// The placement scanner is owned by the evaluation transformer, so merely
|
|
9
|
+
// declaring a JSDoc tag must not alter ordinary TypeScript compilation.
|
|
10
|
+
//
|
|
11
|
+
// 1. Declare a tagged primitive alias.
|
|
12
|
+
// 2. Omit every evaluation call.
|
|
13
|
+
// 3. Require successful compilation.
|
|
14
|
+
func TestLlmEvaluationIgnoresDeclarationProbabilityWithoutCall(t *testing.T) {
|
|
15
|
+
llmEvaluationAccepts(t, "no-evaluation-call", `/** @probability 0.8 */
|
|
16
|
+
export type Urgency = boolean;
|
|
17
|
+
`)
|
|
18
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"strings"
|
|
5
|
+
"testing"
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
// TestLlmEvaluationPlanEmissionTransform verifies typia.llm.evaluation emits
|
|
9
|
+
// one deterministic plan call with the documented description sources.
|
|
10
|
+
//
|
|
11
|
+
// The transform replaces the call with `_createLlmEvaluation(plan)`, whose
|
|
12
|
+
// plan carries every question's text. A property or enum member `@description`
|
|
13
|
+
// tag overrides its summary, as it does in typia's JSON schemas, and repository
|
|
14
|
+
// formatting rewrites that tag in TypeScript sources, so this fixture pins it
|
|
15
|
+
// here. The same source must also emit byte-identical output on every run,
|
|
16
|
+
// because the plan feeds build caches and published bundles.
|
|
17
|
+
//
|
|
18
|
+
// 1. Transform a decision type with `@description` overrides on a property and
|
|
19
|
+
// an enum member, a threshold, and a member minimum.
|
|
20
|
+
// 2. Transform the same project again.
|
|
21
|
+
// 3. Assert the runtime helper call, the overridden texts, the requirements,
|
|
22
|
+
// and identical output across runs.
|
|
23
|
+
func TestLlmEvaluationPlanEmissionTransform(t *testing.T) {
|
|
24
|
+
project := llmEvaluationProject(t, "emission", llmEvaluationEmissionSource)
|
|
25
|
+
transform := func() string {
|
|
26
|
+
out, errText, code := ttscTypiaTestCapture(func() int {
|
|
27
|
+
return runTransform([]string{
|
|
28
|
+
"--cwd", project,
|
|
29
|
+
"--tsconfig", "tsconfig.json",
|
|
30
|
+
"--file", "src/main.ts",
|
|
31
|
+
"--output", "js",
|
|
32
|
+
})
|
|
33
|
+
})
|
|
34
|
+
if code != 0 {
|
|
35
|
+
t.Fatalf("llm.evaluation transform failed: code=%d stderr=\n%s", code, errText)
|
|
36
|
+
}
|
|
37
|
+
return out
|
|
38
|
+
}
|
|
39
|
+
first := transform()
|
|
40
|
+
for _, expected := range []string{
|
|
41
|
+
"_createLlmEvaluation",
|
|
42
|
+
`instructions: "Overridden question"`,
|
|
43
|
+
`description: "Overridden member"`,
|
|
44
|
+
`description: "Plain member"`,
|
|
45
|
+
"threshold: 0.8",
|
|
46
|
+
"minimum: 0.75",
|
|
47
|
+
} {
|
|
48
|
+
if !strings.Contains(first, expected) {
|
|
49
|
+
t.Fatalf("llm.evaluation emission missing %q:\n%s", expected, first)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
for _, unexpected := range []string{`instructions: "Summary`, `description: "Summary`, "typia.llm.evaluation"} {
|
|
53
|
+
if strings.Contains(first, unexpected) {
|
|
54
|
+
t.Fatalf("llm.evaluation emission must not contain %q:\n%s", unexpected, first)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
if second := transform(); second != first {
|
|
58
|
+
t.Fatalf("llm.evaluation emission is not deterministic:\n--- first\n%s\n--- second\n%s", first, second)
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const llmEvaluationEmissionSource = `import typia, { tags } from "typia";
|
|
63
|
+
|
|
64
|
+
enum Team {
|
|
65
|
+
/**
|
|
66
|
+
* Plain member
|
|
67
|
+
*
|
|
68
|
+
* @probability 0.5
|
|
69
|
+
*/
|
|
70
|
+
billing = "billing",
|
|
71
|
+
/**
|
|
72
|
+
* Summary to be overridden
|
|
73
|
+
*
|
|
74
|
+
* @description Overridden member
|
|
75
|
+
* @probability 0.75
|
|
76
|
+
*/
|
|
77
|
+
technical = "technical",
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export const evaluation = typia.llm.evaluation<{
|
|
81
|
+
/**
|
|
82
|
+
* Summary to be overridden
|
|
83
|
+
*
|
|
84
|
+
* @description Overridden question
|
|
85
|
+
*/
|
|
86
|
+
team: Team;
|
|
87
|
+
/** Is a refund requested? */
|
|
88
|
+
refund: boolean & tags.Probability<0.8>;
|
|
89
|
+
}>();
|
|
90
|
+
`
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"encoding/json"
|
|
5
|
+
"os"
|
|
6
|
+
"path/filepath"
|
|
7
|
+
"slices"
|
|
8
|
+
"strings"
|
|
9
|
+
"testing"
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
// TestLlmEvaluationProgramScanDependencies verifies a successful evaluation
|
|
13
|
+
// transform watches source files used by its program-wide placement check.
|
|
14
|
+
//
|
|
15
|
+
// An unrelated source has no tag today but may gain an illegal declaration
|
|
16
|
+
// tag tomorrow. A complete dependency list must then invalidate the old emit.
|
|
17
|
+
//
|
|
18
|
+
// 1. Transform a decision beside an unrelated, untagged source module.
|
|
19
|
+
// 2. Require the decision's complete dependency list to include that module.
|
|
20
|
+
// 3. Add an illegal tag in that module and require a new diagnostic.
|
|
21
|
+
func TestLlmEvaluationProgramScanDependencies(t *testing.T) {
|
|
22
|
+
dir := llmEvaluationProject(t, "program-scan-dependencies", `import typia from "typia";
|
|
23
|
+
interface IDecision {
|
|
24
|
+
/** Is it urgent? */
|
|
25
|
+
urgent: boolean;
|
|
26
|
+
}
|
|
27
|
+
typia.llm.evaluation<IDecision>();
|
|
28
|
+
`)
|
|
29
|
+
unused := `export type Unused = boolean;
|
|
30
|
+
`
|
|
31
|
+
if err := os.WriteFile(filepath.Join(dir, "src", "unused.ts"), []byte(unused), 0o644); err != nil {
|
|
32
|
+
t.Fatal(err)
|
|
33
|
+
}
|
|
34
|
+
output, diagnostics, code := ttscTypiaTestCapture(func() int {
|
|
35
|
+
return runTransform([]string{"--cwd", dir, "--tsconfig", "tsconfig.json"})
|
|
36
|
+
})
|
|
37
|
+
var result transformProjectOutput
|
|
38
|
+
if err := json.Unmarshal([]byte(output), &result); err != nil {
|
|
39
|
+
t.Fatal(err)
|
|
40
|
+
}
|
|
41
|
+
if code != 0 {
|
|
42
|
+
t.Fatalf("valid project must transform: code=%d\ndiagnostics=%+v\nstderr=%s", code, result.Diagnostics, diagnostics)
|
|
43
|
+
}
|
|
44
|
+
if !slices.Contains(result.DependenciesComplete, "src/main.ts") {
|
|
45
|
+
t.Fatalf("decision transform unexpectedly lacks complete dependencies: %+v", result.DependenciesComplete)
|
|
46
|
+
}
|
|
47
|
+
if !slices.Contains(result.Dependencies["src/main.ts"], "src/unused.ts") {
|
|
48
|
+
t.Fatalf("program-wide scan dependency is missing: %+v", result.Dependencies["src/main.ts"])
|
|
49
|
+
}
|
|
50
|
+
tagged := `/** @probability 0.8 */
|
|
51
|
+
export type Unused = boolean;
|
|
52
|
+
`
|
|
53
|
+
if err := os.WriteFile(filepath.Join(dir, "src", "unused.ts"), []byte(tagged), 0o644); err != nil {
|
|
54
|
+
t.Fatal(err)
|
|
55
|
+
}
|
|
56
|
+
output, diagnostics, code = ttscTypiaTestCapture(func() int {
|
|
57
|
+
return runTransform([]string{"--cwd", dir, "--tsconfig", "tsconfig.json"})
|
|
58
|
+
})
|
|
59
|
+
if code != 3 {
|
|
60
|
+
t.Fatalf("new invalid tag must fail: code=%d\nstderr=%s", code, diagnostics)
|
|
61
|
+
}
|
|
62
|
+
result = transformProjectOutput{}
|
|
63
|
+
if err := json.Unmarshal([]byte(output), &result); err != nil {
|
|
64
|
+
t.Fatal(err)
|
|
65
|
+
}
|
|
66
|
+
if len(result.Diagnostics) != 1 || !strings.Contains(result.Diagnostics[0].MessageText, "type alias Unused") {
|
|
67
|
+
t.Fatalf("changed source must affect evaluation diagnostic: %+v", result.Diagnostics)
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"strings"
|
|
5
|
+
"testing"
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
// TestLlmEvaluationRejectsDeclarationProbability verifies JSDoc on a type
|
|
9
|
+
// declaration cannot silently become a decision requirement.
|
|
10
|
+
//
|
|
11
|
+
// A primitive alias resolves to the same primitive as an unannotated alias,
|
|
12
|
+
// so the compiler must reject unsupported declaration-level placements.
|
|
13
|
+
//
|
|
14
|
+
// 1. Annotate several declaration kinds, including unused declarations.
|
|
15
|
+
// 2. Compile a neighboring evaluation call.
|
|
16
|
+
// 3. Require a normal diagnostic for every invalid placement.
|
|
17
|
+
func TestLlmEvaluationRejectsDeclarationProbability(t *testing.T) {
|
|
18
|
+
diagnostics := llmEvaluationDiagnosticsBuild(t, "declaration-probability", `import typia from "typia";
|
|
19
|
+
|
|
20
|
+
/** @probability 0.8 */
|
|
21
|
+
type Urgency = boolean;
|
|
22
|
+
/** @probability invalid */
|
|
23
|
+
type Unused = boolean;
|
|
24
|
+
/** @probability 0.6 */
|
|
25
|
+
interface Nested { /** Answer? */ answer: boolean }
|
|
26
|
+
/** @probability 0.7 */
|
|
27
|
+
enum Choice { yes = "yes", no = "no" }
|
|
28
|
+
/** @probability 0.4 */
|
|
29
|
+
class Container { /** Answer? */ answer = true; }
|
|
30
|
+
/** @probability 0.3 */
|
|
31
|
+
function unrelated(): boolean { return true; }
|
|
32
|
+
|
|
33
|
+
typia.llm.evaluation<{
|
|
34
|
+
/** Urgent? */ urgent: Urgency;
|
|
35
|
+
/** Nested? */ nested: Nested;
|
|
36
|
+
/** Choice? */ choice: Choice;
|
|
37
|
+
}>();
|
|
38
|
+
`)
|
|
39
|
+
for _, name := range []string{"type alias Urgency", "type alias Unused", "interface Nested", "enum Choice", "class Container", "declaration unrelated"} {
|
|
40
|
+
if !strings.Contains(diagnostics, name) {
|
|
41
|
+
t.Fatalf("misplaced declaration tag %q was not diagnosed:\n%s", name, diagnostics)
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"strings"
|
|
5
|
+
"testing"
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
// TestLlmEvaluationRejectsAliasRefinement verifies a named alias cannot hide
|
|
9
|
+
// a validation tag from the evaluation compiler.
|
|
10
|
+
//
|
|
11
|
+
// An alias of a boolean refinement still denotes a constrained boolean. The
|
|
12
|
+
// decoder does not enforce that constraint, while an annotation-only alias is
|
|
13
|
+
// safe and must remain accepted.
|
|
14
|
+
//
|
|
15
|
+
// 1. Declare a validation refinement behind a named alias.
|
|
16
|
+
// 2. Require a decision-path diagnostic.
|
|
17
|
+
// 3. Accept a neighboring annotation-only alias.
|
|
18
|
+
func TestLlmEvaluationRejectsAliasRefinement(t *testing.T) {
|
|
19
|
+
errText := llmEvaluationDiagnosticsBuild(t, "alias-refinement", `import typia, { tags } from "typia";
|
|
20
|
+
|
|
21
|
+
type TrueOnly = tags.TagBase<{
|
|
22
|
+
target: "boolean";
|
|
23
|
+
kind: "trueOnly";
|
|
24
|
+
value: undefined;
|
|
25
|
+
validate: "$input === true";
|
|
26
|
+
}>;
|
|
27
|
+
type Guarded = boolean & TrueOnly;
|
|
28
|
+
typia.llm.evaluation<{
|
|
29
|
+
/** Is it allowed? */
|
|
30
|
+
allowed: Guarded;
|
|
31
|
+
}>();
|
|
32
|
+
`)
|
|
33
|
+
expected := "- $input.allowed\n - LLM evaluation does not support type tag \"trueOnly\", because decode() cannot enforce its constraint."
|
|
34
|
+
if !strings.Contains(errText, expected) {
|
|
35
|
+
t.Fatalf("missing aliased refinement diagnostic:\n%s", errText)
|
|
36
|
+
}
|
|
37
|
+
llmEvaluationAccepts(t, "alias-refinement-control", `import typia, { tags } from "typia";
|
|
38
|
+
|
|
39
|
+
type Annotated = boolean & tags.Default<true>;
|
|
40
|
+
typia.llm.evaluation<{
|
|
41
|
+
/** Is it allowed? */
|
|
42
|
+
allowed: Annotated;
|
|
43
|
+
}>();
|
|
44
|
+
`)
|
|
45
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"strings"
|
|
5
|
+
"testing"
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
// TestLlmEvaluationRejectsComputedMethodProbability verifies an unsupported
|
|
9
|
+
// computed method annotation produces a diagnostic instead of a panic.
|
|
10
|
+
//
|
|
11
|
+
// A computed property name is not a text-bearing identifier in the parser.
|
|
12
|
+
// Reading its name as plain text used to crash the compiler's diagnostic path.
|
|
13
|
+
//
|
|
14
|
+
// 1. Annotate a computed class method with @probability.
|
|
15
|
+
// 2. Build an otherwise valid evaluation call.
|
|
16
|
+
// 3. Require a normal transform diagnostic.
|
|
17
|
+
func TestLlmEvaluationRejectsComputedMethodProbability(t *testing.T) {
|
|
18
|
+
diagnostics := llmEvaluationDiagnosticsBuild(t, "computed-method-probability", `import typia from "typia";
|
|
19
|
+
class Source {
|
|
20
|
+
/** @probability 0.8 */ [Symbol.iterator]() { return []; }
|
|
21
|
+
}
|
|
22
|
+
typia.llm.evaluation<{
|
|
23
|
+
/** Is it urgent? */
|
|
24
|
+
urgent: boolean;
|
|
25
|
+
}>();
|
|
26
|
+
`)
|
|
27
|
+
if !strings.Contains(diagnostics, "@probability") {
|
|
28
|
+
t.Fatalf("computed method tag must produce a diagnostic:\n%s", diagnostics)
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"os"
|
|
5
|
+
"path/filepath"
|
|
6
|
+
"strings"
|
|
7
|
+
"testing"
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
// TestLlmEvaluationRejectsImportedDeclarationProbability verifies the
|
|
11
|
+
// placement diagnostic crosses an imported source-file boundary.
|
|
12
|
+
//
|
|
13
|
+
// A local-only syntax scan would miss an alias declared in another file while
|
|
14
|
+
// the checker still resolves that alias at the evaluation decision.
|
|
15
|
+
//
|
|
16
|
+
// 1. Define an annotated primitive alias in an imported module.
|
|
17
|
+
// 2. Use it in evaluation calls in two source files.
|
|
18
|
+
// 3. Require the imported declaration's diagnostic from both CLI paths.
|
|
19
|
+
func TestLlmEvaluationRejectsImportedDeclarationProbability(t *testing.T) {
|
|
20
|
+
dir := llmEvaluationProject(t, "imported-declaration-probability", `import typia from "typia";
|
|
21
|
+
import type { Urgency } from "./urgency";
|
|
22
|
+
typia.llm.evaluation<{ /** Urgent? */ urgent: Urgency }>();
|
|
23
|
+
`)
|
|
24
|
+
source := `/** @probability 0.8 */
|
|
25
|
+
export type Urgency = boolean;
|
|
26
|
+
`
|
|
27
|
+
if err := os.WriteFile(filepath.Join(dir, "src", "urgency.ts"), []byte(source), 0o644); err != nil {
|
|
28
|
+
t.Fatal(err)
|
|
29
|
+
}
|
|
30
|
+
second := `import typia from "typia";
|
|
31
|
+
typia.llm.evaluation<{ /** Is it urgent? */ urgent: boolean }>();
|
|
32
|
+
`
|
|
33
|
+
if err := os.WriteFile(filepath.Join(dir, "src", "second.ts"), []byte(second), 0o644); err != nil {
|
|
34
|
+
t.Fatal(err)
|
|
35
|
+
}
|
|
36
|
+
_, diagnostics, code := ttscTypiaTestCapture(func() int {
|
|
37
|
+
return runBuild([]string{"--cwd", dir, "--tsconfig", "tsconfig.json", "--emit", "--outDir", filepath.Join(dir, "dist")})
|
|
38
|
+
})
|
|
39
|
+
if code != 3 || strings.Count(diagnostics, "type alias Urgency") != 2 {
|
|
40
|
+
t.Fatalf("imported declaration tag must fail in both files: code=%d\n%s", code, diagnostics)
|
|
41
|
+
}
|
|
42
|
+
output, errText, code := ttscTypiaTestCapture(func() int {
|
|
43
|
+
return runTransform([]string{"--cwd", dir, "--tsconfig", "tsconfig.json"})
|
|
44
|
+
})
|
|
45
|
+
if code != 3 || strings.Count(output, "type alias Urgency") != 2 {
|
|
46
|
+
t.Fatalf("transform path must diagnose both files: code=%d\nstdout=%s\nstderr=%s", code, output, errText)
|
|
47
|
+
}
|
|
48
|
+
}
|