typia 14.0.6 → 15.0.1
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/http.d.ts +49 -24
- package/lib/http.js.map +1 -1
- package/lib/http.mjs.map +1 -1
- 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/_httpFormDataReadBigint.js +7 -5
- package/lib/internal/_httpFormDataReadBigint.js.map +1 -1
- package/lib/internal/_httpFormDataReadBigint.mjs +1 -1
- package/lib/internal/_httpFormDataReadBigint.mjs.map +1 -1
- package/lib/internal/_httpFormDataReadBoolean.js +12 -10
- package/lib/internal/_httpFormDataReadBoolean.js.map +1 -1
- package/lib/internal/_httpFormDataReadBoolean.mjs +1 -1
- package/lib/internal/_httpFormDataReadBoolean.mjs.map +1 -1
- package/lib/internal/_httpFormDataReadNumber.js +7 -5
- package/lib/internal/_httpFormDataReadNumber.js.map +1 -1
- package/lib/internal/_httpFormDataReadNumber.mjs +1 -1
- package/lib/internal/_httpFormDataReadNumber.mjs.map +1 -1
- package/lib/internal/_httpFormDataReadString.d.ts +9 -1
- package/lib/internal/_httpFormDataReadString.js +10 -2
- package/lib/internal/_httpFormDataReadString.js.map +1 -1
- package/lib/internal/_httpFormDataReadString.mjs +9 -1
- package/lib/internal/_httpFormDataReadString.mjs.map +1 -1
- package/lib/internal/_httpHeaderReadBigint.js +5 -1
- package/lib/internal/_httpHeaderReadBigint.js.map +1 -1
- package/lib/internal/_httpHeaderReadBigint.mjs +2 -1
- package/lib/internal/_httpHeaderReadBigint.mjs.map +1 -1
- package/lib/internal/_httpHeaderReadNumber.js +5 -1
- package/lib/internal/_httpHeaderReadNumber.js.map +1 -1
- package/lib/internal/_httpHeaderReadNumber.mjs +2 -1
- package/lib/internal/_httpHeaderReadNumber.mjs.map +1 -1
- package/lib/internal/_httpParameterReadBigint.js +4 -0
- package/lib/internal/_httpParameterReadBigint.js.map +1 -1
- package/lib/internal/_httpParameterReadBigint.mjs +1 -0
- package/lib/internal/_httpParameterReadBigint.mjs.map +1 -1
- package/lib/internal/_httpParameterReadNumber.js +4 -0
- package/lib/internal/_httpParameterReadNumber.js.map +1 -1
- package/lib/internal/_httpParameterReadNumber.mjs +1 -0
- package/lib/internal/_httpParameterReadNumber.mjs.map +1 -1
- package/lib/internal/_httpParameterReadString.d.ts +9 -1
- package/lib/internal/_httpParameterReadString.js +9 -1
- package/lib/internal/_httpParameterReadString.js.map +1 -1
- package/lib/internal/_httpParameterReadString.mjs +9 -1
- package/lib/internal/_httpParameterReadString.mjs.map +1 -1
- package/lib/internal/_httpQueryReadBigint.js +8 -1
- package/lib/internal/_httpQueryReadBigint.js.map +1 -1
- package/lib/internal/_httpQueryReadBigint.mjs +1 -1
- package/lib/internal/_httpQueryReadBigint.mjs.map +1 -1
- package/lib/internal/_httpQueryReadBoolean.js +4 -1
- package/lib/internal/_httpQueryReadBoolean.js.map +1 -1
- package/lib/internal/_httpQueryReadBoolean.mjs +1 -1
- package/lib/internal/_httpQueryReadBoolean.mjs.map +1 -1
- package/lib/internal/_httpQueryReadNumber.js +8 -1
- package/lib/internal/_httpQueryReadNumber.js.map +1 -1
- package/lib/internal/_httpQueryReadNumber.mjs +1 -1
- package/lib/internal/_httpQueryReadNumber.mjs.map +1 -1
- package/lib/internal/_httpQueryReadString.d.ts +9 -1
- package/lib/internal/_httpQueryReadString.js +9 -1
- package/lib/internal/_httpQueryReadString.js.map +1 -1
- package/lib/internal/_httpQueryReadString.mjs +9 -1
- package/lib/internal/_httpQueryReadString.mjs.map +1 -1
- package/lib/internal/_randomBigint.d.ts +12 -1
- package/lib/internal/_randomBigint.js +90 -2
- package/lib/internal/_randomBigint.js.map +1 -1
- package/lib/internal/_randomBigint.mjs +70 -2
- package/lib/internal/_randomBigint.mjs.map +1 -1
- package/lib/internal/_randomInteger.js +21 -12
- package/lib/internal/_randomInteger.js.map +1 -1
- package/lib/internal/_randomInteger.mjs +21 -16
- package/lib/internal/_randomInteger.mjs.map +1 -1
- package/lib/internal/_randomNumber.js +19 -10
- package/lib/internal/_randomNumber.js.map +1 -1
- package/lib/internal/_randomNumber.mjs +19 -14
- package/lib/internal/_randomNumber.mjs.map +1 -1
- 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 +208 -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/random_recursive_min_items_diagnostic_test.go +18 -1
- 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/ExpressionFactory.go +16 -1
- package/native/core/factories/IdentifierFactory.go +10 -0
- package/native/core/factories/LiteralFactory.go +16 -0
- package/native/core/factories/MetadataCommentTagFactory.go +185 -35
- package/native/core/factories/MetadataTypeTagFactory.go +97 -24
- package/native/core/factories/MetadataTypeTagSchemaFactory.go +5 -0
- package/native/core/factories/expression_factory_number_spells_non_finite_values_test.go +69 -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_holds_bigint_tags_exact_test.go +168 -0
- package/native/core/factories/metadata_comment_tag_factory_reads_javascript_numbers_test.go +158 -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/functional/FunctionalAssertParametersProgrammer.go +1 -3
- package/native/core/programmers/functional/FunctionalIsParametersProgrammer.go +107 -9
- package/native/core/programmers/functional/FunctionalValidateParametersProgrammer.go +1 -3
- package/native/core/programmers/http/HttpFormDataProgrammer.go +41 -2
- package/native/core/programmers/http/HttpHeadersProgrammer.go +56 -4
- package/native/core/programmers/http/HttpParameterProgrammer.go +1 -3
- package/native/core/programmers/http/HttpQueryProgrammer.go +26 -43
- package/native/core/programmers/iterate/json_schema_jsDocTags.go +10 -3
- package/native/core/programmers/iterate/json_schema_jsdoc_tags_cast_reads_javascript_numbers_test.go +64 -0
- package/native/core/programmers/llm/LlmApplicationProgrammer.go +1 -0
- package/native/core/programmers/llm/LlmEvaluationProgrammer.go +559 -0
- package/native/core/programmers/llm/LlmParametersProgrammer.go +6 -5
- package/native/core/programmers/llm/LlmReferenceDescription.go +113 -0
- package/native/core/programmers/llm/LlmSchemaProgrammer.go +34 -4
- package/native/core/programmers/llm/llm_reference_description_test.go +134 -0
- package/native/core/schemas/metadata/MetadataDependency.go +9 -0
- package/native/core/utils/NumberUtil.go +195 -0
- package/native/core/utils/number_util_rational_keeps_written_value_test.go +62 -0
- package/native/core/utils/number_util_reads_javascript_number_grammar_test.go +147 -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/http.ts +61 -34
- package/src/internal/_createLlmEvaluation.ts +678 -0
- package/src/internal/_httpFormDataReadBigint.ts +3 -1
- package/src/internal/_httpFormDataReadBoolean.ts +3 -1
- package/src/internal/_httpFormDataReadNumber.ts +3 -1
- package/src/internal/_httpFormDataReadString.ts +10 -1
- package/src/internal/_httpHeaderReadBigint.ts +6 -1
- package/src/internal/_httpHeaderReadNumber.ts +6 -1
- package/src/internal/_httpParameterReadBigint.ts +3 -0
- package/src/internal/_httpParameterReadNumber.ts +3 -0
- package/src/internal/_httpParameterReadString.ts +12 -2
- package/src/internal/_httpQueryReadBigint.ts +7 -1
- package/src/internal/_httpQueryReadBoolean.ts +3 -1
- package/src/internal/_httpQueryReadNumber.ts +7 -1
- package/src/internal/_httpQueryReadString.ts +10 -1
- package/src/internal/_randomBigint.ts +111 -3
- package/src/internal/_randomInteger.ts +31 -16
- package/src/internal/_randomNumber.ts +23 -12
- 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
|
@@ -1,10 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reads one form field as a string.
|
|
3
|
+
*
|
|
4
|
+
* The text `"null"` spells `null` only where the property's type admits `null`;
|
|
5
|
+
* elsewhere it is the string `"null"` (#2450). The emitter passes `false` for a
|
|
6
|
+
* string whose type does not admit `null` and omits the argument otherwise, so
|
|
7
|
+
* code emitted before the parameter existed keeps its reading.
|
|
8
|
+
*/
|
|
1
9
|
export const _httpFormDataReadString = (
|
|
2
10
|
input: string | File | null,
|
|
11
|
+
nullable: boolean = true,
|
|
3
12
|
): string | null | undefined =>
|
|
4
13
|
input instanceof File
|
|
5
14
|
? (input as any)
|
|
6
15
|
: input === null
|
|
7
16
|
? undefined
|
|
8
|
-
: input === "null"
|
|
17
|
+
: nullable === true && input === "null"
|
|
9
18
|
? null
|
|
10
19
|
: input;
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
export const _httpHeaderReadBigint = (value: string | undefined) =>
|
|
2
|
-
|
|
2
|
+
// A blank header, or a blank element of a header list, is absent: `BigInt("")`
|
|
3
|
+
// is 0n, which let validators accept an empty header as a real zero (#2448).
|
|
4
|
+
value !== undefined && isBlank(value) === false ? toBigint(value) : undefined;
|
|
5
|
+
|
|
6
|
+
const isBlank = (value: string): boolean =>
|
|
7
|
+
typeof value === "string" && value.trim().length === 0;
|
|
3
8
|
|
|
4
9
|
const toBigint = (str: string): bigint | string => {
|
|
5
10
|
try {
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
export const _httpHeaderReadNumber = (value: string | undefined) =>
|
|
2
|
-
|
|
2
|
+
// A blank header, or a blank element of a header list, is absent: `Number("")`
|
|
3
|
+
// is 0, which let validators accept an empty header as a real zero (#2448).
|
|
4
|
+
value !== undefined && isBlank(value) === false ? toNumber(value) : undefined;
|
|
5
|
+
|
|
6
|
+
const isBlank = (value: string): boolean =>
|
|
7
|
+
typeof value === "string" && value.trim().length === 0;
|
|
3
8
|
|
|
4
9
|
const toNumber = (str: string): number | string => {
|
|
5
10
|
const value: number = Number(str);
|
|
@@ -2,6 +2,9 @@ export const _httpParameterReadBigint = (value: string) =>
|
|
|
2
2
|
value !== "null" ? toBigint(value) : null;
|
|
3
3
|
|
|
4
4
|
const toBigint = (str: string): bigint | string => {
|
|
5
|
+
// Blank text stays text, so the assertion rejects it: `BigInt(" ")` is 0n,
|
|
6
|
+
// which read a blank path segment as a real zero (#2448).
|
|
7
|
+
if (str.trim().length === 0) return str;
|
|
5
8
|
try {
|
|
6
9
|
return BigInt(str);
|
|
7
10
|
} catch {
|
|
@@ -2,6 +2,9 @@ export const _httpParameterReadNumber = (value: string) =>
|
|
|
2
2
|
value !== "null" ? toNumber(value) : null;
|
|
3
3
|
|
|
4
4
|
const toNumber = (str: string): number | string => {
|
|
5
|
+
// Blank text stays text, so the assertion rejects it: `Number(" ")` is 0,
|
|
6
|
+
// which read a blank path segment as a real zero (#2448).
|
|
7
|
+
if (str.trim().length === 0) return str;
|
|
5
8
|
const value: number = Number(str);
|
|
6
9
|
return isNaN(value) ? str : value;
|
|
7
10
|
};
|
|
@@ -1,2 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Reads one path parameter as a string.
|
|
3
|
+
*
|
|
4
|
+
* The text `"null"` spells `null` only where the parameter's type admits
|
|
5
|
+
* `null`; elsewhere it is the string `"null"` (#2450). The emitter passes
|
|
6
|
+
* `false` for a string whose type does not admit `null` and omits the argument
|
|
7
|
+
* otherwise, so code emitted before the parameter existed keeps its reading.
|
|
8
|
+
*/
|
|
9
|
+
export const _httpParameterReadString = (
|
|
10
|
+
value: string,
|
|
11
|
+
nullable: boolean = true,
|
|
12
|
+
) => (nullable === true && value === "null" ? null : value);
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
export const _httpQueryReadBigint = (
|
|
2
2
|
str: string | null,
|
|
3
3
|
): bigint | null | undefined =>
|
|
4
|
-
|
|
4
|
+
// Blank text is absent, as the empty string always was: `BigInt(" ")` is 0n,
|
|
5
|
+
// which would read a whitespace value as a real zero (#2448).
|
|
6
|
+
typeof str === "string" && str.trim().length !== 0
|
|
7
|
+
? str === "null"
|
|
8
|
+
? null
|
|
9
|
+
: (toBigint(str) as any)
|
|
10
|
+
: undefined;
|
|
5
11
|
|
|
6
12
|
const toBigint = (str: string): bigint | string => {
|
|
7
13
|
try {
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
export const _httpQueryReadBoolean = (
|
|
2
2
|
str: string | null,
|
|
3
3
|
): boolean | null | undefined =>
|
|
4
|
-
|
|
4
|
+
// `undefined` is as absent as `null`, which the contract returns; a
|
|
5
|
+
// stand-in reader that answers `undefined` must not throw on `.length`.
|
|
6
|
+
str === null || str === undefined
|
|
5
7
|
? undefined
|
|
6
8
|
: str === "null"
|
|
7
9
|
? null
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
export const _httpQueryReadNumber = (
|
|
2
2
|
str: string | null,
|
|
3
3
|
): number | null | undefined =>
|
|
4
|
-
|
|
4
|
+
// Blank text is absent, as the empty string always was: `Number(" ")` is 0,
|
|
5
|
+
// which would read a whitespace value as a real zero (#2448).
|
|
6
|
+
typeof str === "string" && str.trim().length !== 0
|
|
7
|
+
? str === "null"
|
|
8
|
+
? null
|
|
9
|
+
: (toNumber(str) as any)
|
|
10
|
+
: undefined;
|
|
5
11
|
|
|
6
12
|
const toNumber = (str: string): number | string => {
|
|
7
13
|
const value: number = Number(str);
|
|
@@ -1,4 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reads one query value as a string.
|
|
3
|
+
*
|
|
4
|
+
* The text `"null"` spells `null` only where the property's type admits `null`;
|
|
5
|
+
* elsewhere it is the string `"null"` (#2450). The emitter passes `false` for a
|
|
6
|
+
* string whose type does not admit `null` and omits the argument otherwise, so
|
|
7
|
+
* code emitted before the parameter existed keeps its reading.
|
|
8
|
+
*/
|
|
1
9
|
export const _httpQueryReadString = (
|
|
2
10
|
str: string | null,
|
|
11
|
+
nullable: boolean = true,
|
|
3
12
|
): string | null | undefined =>
|
|
4
|
-
str === null ? undefined : str === "null" ? null : str;
|
|
13
|
+
str === null ? undefined : nullable === true && str === "null" ? null : str;
|
|
@@ -1,6 +1,114 @@
|
|
|
1
1
|
import { OpenApi } from "@typia/interface";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { _decimalIntegerStep } from "./_decimal";
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Generates a random `bigint` satisfying an integer schema.
|
|
7
|
+
*
|
|
8
|
+
* The schema carries its bounds and step as numbers, but the value is a
|
|
9
|
+
* `bigint`, so the draw runs on integers. Drawing through doubles rounded every
|
|
10
|
+
* value past 2^53, and it checked `multipleOf` against a double's shortest
|
|
11
|
+
* decimal text rather than the integer `BigInt` makes of it, so `random`
|
|
12
|
+
* returned values the validator rejects, or gave up on a range that holds one
|
|
13
|
+
* (#2457). An integral bound or step is read as the integer the double holds,
|
|
14
|
+
* which is the integer the validator compares with.
|
|
15
|
+
*/
|
|
16
|
+
export const _randomBigint = (schema: OpenApi.IJsonSchema.IInteger): bigint => {
|
|
17
|
+
const lower: bigint | null = boundary(
|
|
18
|
+
schema.minimum,
|
|
19
|
+
schema.exclusiveMinimum,
|
|
20
|
+
"lower",
|
|
21
|
+
);
|
|
22
|
+
const upper: bigint | null = boundary(
|
|
23
|
+
schema.maximum,
|
|
24
|
+
schema.exclusiveMaximum,
|
|
25
|
+
"upper",
|
|
26
|
+
);
|
|
27
|
+
const minimum: bigint =
|
|
28
|
+
lower ?? (upper === null ? BigInt(0) : upper - BigInt(100));
|
|
29
|
+
const maximum: bigint =
|
|
30
|
+
upper ?? (lower === null ? BigInt(100) : lower + BigInt(100));
|
|
31
|
+
if (minimum > maximum)
|
|
32
|
+
throw new Error("Minimum value is greater than maximum value.");
|
|
33
|
+
if (schema.multipleOf === undefined) return between(minimum, maximum);
|
|
34
|
+
|
|
35
|
+
const step: bigint | null = integerStep(schema.multipleOf);
|
|
36
|
+
if (step === null || step <= BigInt(0))
|
|
37
|
+
throw new Error("The multipleOf value must be a positive finite number.");
|
|
38
|
+
const first: bigint = ceilDivide(minimum, step);
|
|
39
|
+
const last: bigint = floorDivide(maximum, step);
|
|
40
|
+
if (first > last)
|
|
41
|
+
throw new Error("The range does not contain a multipleOf value.");
|
|
42
|
+
return between(first, last) * step;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Reads one side's inclusive integer bound.
|
|
47
|
+
*
|
|
48
|
+
* `-Infinity` below or `Infinity` above excludes no integer, so it is no bound
|
|
49
|
+
* at all; `Infinity` below or `-Infinity` above excludes every integer.
|
|
50
|
+
*/
|
|
51
|
+
const boundary = (
|
|
52
|
+
inclusive: number | undefined,
|
|
53
|
+
exclusive: number | undefined,
|
|
54
|
+
side: "lower" | "upper",
|
|
55
|
+
): bigint | null => {
|
|
56
|
+
const candidates: bigint[] = [];
|
|
57
|
+
for (const [value, open] of [
|
|
58
|
+
[inclusive, false],
|
|
59
|
+
[exclusive, true],
|
|
60
|
+
] as const) {
|
|
61
|
+
if (value === undefined) continue;
|
|
62
|
+
if (Number.isFinite(value) === false) {
|
|
63
|
+
if (value === (side === "lower" ? -Infinity : Infinity)) continue;
|
|
64
|
+
throw new Error("Numeric range has no finite value.");
|
|
65
|
+
}
|
|
66
|
+
candidates.push(
|
|
67
|
+
side === "lower"
|
|
68
|
+
? open
|
|
69
|
+
? BigInt(Math.floor(value)) + BigInt(1)
|
|
70
|
+
: BigInt(Math.ceil(value))
|
|
71
|
+
: open
|
|
72
|
+
? BigInt(Math.ceil(value)) - BigInt(1)
|
|
73
|
+
: BigInt(Math.floor(value)),
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
if (candidates.length === 0) return null;
|
|
77
|
+
return candidates.reduce((x, y) =>
|
|
78
|
+
side === "lower" ? (x > y ? x : y) : x < y ? x : y,
|
|
79
|
+
);
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* The smallest positive integer a `multipleOf` divides.
|
|
84
|
+
*
|
|
85
|
+
* An integral step is the integer its double holds; a fractional one, such as
|
|
86
|
+
* `1.5`, steps by its smallest integer multiple (`3`).
|
|
87
|
+
*/
|
|
88
|
+
const integerStep = (multipleOf: number): bigint | null => {
|
|
89
|
+
if (Number.isFinite(multipleOf) === false) return null;
|
|
90
|
+
if (Number.isInteger(multipleOf)) return BigInt(multipleOf);
|
|
91
|
+
return _decimalIntegerStep(multipleOf)?.coefficient ?? null;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const ceilDivide = (x: bigint, y: bigint): bigint => {
|
|
95
|
+
const quotient: bigint = x / y;
|
|
96
|
+
return x % y > BigInt(0) ? quotient + BigInt(1) : quotient;
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const floorDivide = (x: bigint, y: bigint): bigint => {
|
|
100
|
+
const quotient: bigint = x / y;
|
|
101
|
+
return x % y < BigInt(0) ? quotient - BigInt(1) : quotient;
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
/** Draws an integer in `[minimum, maximum]`, scaling one 53-bit sample. */
|
|
105
|
+
const between = (minimum: bigint, maximum: bigint): bigint => {
|
|
106
|
+
const scale: bigint = BigInt(1) << BigInt(53);
|
|
107
|
+
const sample: bigint = BigInt(
|
|
108
|
+
Math.min(
|
|
109
|
+
Number(scale - BigInt(1)),
|
|
110
|
+
Math.floor(Math.max(0, Math.random()) * Number(scale)),
|
|
111
|
+
),
|
|
112
|
+
);
|
|
113
|
+
return minimum + ((maximum - minimum + BigInt(1)) * sample) / scale;
|
|
114
|
+
};
|
|
@@ -35,14 +35,12 @@ const scalar = (props: { minimum: number; maximum: number }): number => {
|
|
|
35
35
|
const getLowerBoundary = (
|
|
36
36
|
schema: OpenApi.IJsonSchema.IInteger,
|
|
37
37
|
): IBoundary | null => {
|
|
38
|
-
const inclusive: IBoundary | null =
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
? null
|
|
45
|
-
: { value: schema.exclusiveMinimum, exclusive: true };
|
|
38
|
+
const inclusive: IBoundary | null = boundary(schema.minimum, false, "lower");
|
|
39
|
+
const exclusive: IBoundary | null = boundary(
|
|
40
|
+
schema.exclusiveMinimum,
|
|
41
|
+
true,
|
|
42
|
+
"lower",
|
|
43
|
+
);
|
|
46
44
|
const selected: IBoundary | null = selectBoundary(
|
|
47
45
|
inclusive,
|
|
48
46
|
exclusive,
|
|
@@ -60,14 +58,12 @@ const getLowerBoundary = (
|
|
|
60
58
|
const getUpperBoundary = (
|
|
61
59
|
schema: OpenApi.IJsonSchema.IInteger,
|
|
62
60
|
): IBoundary | null => {
|
|
63
|
-
const inclusive: IBoundary | null =
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
? null
|
|
70
|
-
: { value: schema.exclusiveMaximum, exclusive: true };
|
|
61
|
+
const inclusive: IBoundary | null = boundary(schema.maximum, false, "upper");
|
|
62
|
+
const exclusive: IBoundary | null = boundary(
|
|
63
|
+
schema.exclusiveMaximum,
|
|
64
|
+
true,
|
|
65
|
+
"upper",
|
|
66
|
+
);
|
|
71
67
|
const selected: IBoundary | null = selectBoundary(
|
|
72
68
|
inclusive,
|
|
73
69
|
exclusive,
|
|
@@ -82,6 +78,25 @@ const getUpperBoundary = (
|
|
|
82
78
|
};
|
|
83
79
|
};
|
|
84
80
|
|
|
81
|
+
/**
|
|
82
|
+
* Reads one bound, which may be infinite.
|
|
83
|
+
*
|
|
84
|
+
* A type tag built from an overflowing literal (`Maximum<1e400>`) carries an
|
|
85
|
+
* infinite bound (#2452). `-Infinity` below or `Infinity` above excludes no
|
|
86
|
+
* finite number, so it is no bound at all; `Infinity` below or `-Infinity`
|
|
87
|
+
* above excludes every finite number, so no value can be generated.
|
|
88
|
+
*/
|
|
89
|
+
const boundary = (
|
|
90
|
+
value: number | undefined,
|
|
91
|
+
exclusive: boolean,
|
|
92
|
+
side: "lower" | "upper",
|
|
93
|
+
): IBoundary | null => {
|
|
94
|
+
if (value === undefined) return null;
|
|
95
|
+
if (Number.isFinite(value)) return { value, exclusive };
|
|
96
|
+
if (value === (side === "lower" ? -Infinity : Infinity)) return null;
|
|
97
|
+
throw new Error("Numeric range has no finite value.");
|
|
98
|
+
};
|
|
99
|
+
|
|
85
100
|
const selectBoundary = (
|
|
86
101
|
x: IBoundary | null,
|
|
87
102
|
y: IBoundary | null,
|
|
@@ -57,12 +57,8 @@ const getLowerBoundary = (
|
|
|
57
57
|
schema: OpenApi.IJsonSchema.INumber,
|
|
58
58
|
): IBoundary | null =>
|
|
59
59
|
selectBoundary(
|
|
60
|
-
schema.minimum
|
|
61
|
-
|
|
62
|
-
: { value: schema.minimum, exclusive: false },
|
|
63
|
-
schema.exclusiveMinimum === undefined
|
|
64
|
-
? null
|
|
65
|
-
: { value: schema.exclusiveMinimum, exclusive: true },
|
|
60
|
+
boundary(schema.minimum, false, "lower"),
|
|
61
|
+
boundary(schema.exclusiveMinimum, true, "lower"),
|
|
66
62
|
Math.max,
|
|
67
63
|
);
|
|
68
64
|
|
|
@@ -70,15 +66,30 @@ const getUpperBoundary = (
|
|
|
70
66
|
schema: OpenApi.IJsonSchema.INumber,
|
|
71
67
|
): IBoundary | null =>
|
|
72
68
|
selectBoundary(
|
|
73
|
-
schema.maximum
|
|
74
|
-
|
|
75
|
-
: { value: schema.maximum, exclusive: false },
|
|
76
|
-
schema.exclusiveMaximum === undefined
|
|
77
|
-
? null
|
|
78
|
-
: { value: schema.exclusiveMaximum, exclusive: true },
|
|
69
|
+
boundary(schema.maximum, false, "upper"),
|
|
70
|
+
boundary(schema.exclusiveMaximum, true, "upper"),
|
|
79
71
|
Math.min,
|
|
80
72
|
);
|
|
81
73
|
|
|
74
|
+
/**
|
|
75
|
+
* Reads one bound, which may be infinite.
|
|
76
|
+
*
|
|
77
|
+
* A type tag built from an overflowing literal (`Maximum<1e400>`) carries an
|
|
78
|
+
* infinite bound (#2452). `-Infinity` below or `Infinity` above excludes no
|
|
79
|
+
* finite number, so it is no bound at all; `Infinity` below or `-Infinity`
|
|
80
|
+
* above excludes every finite number, so no value can be generated.
|
|
81
|
+
*/
|
|
82
|
+
const boundary = (
|
|
83
|
+
value: number | undefined,
|
|
84
|
+
exclusive: boolean,
|
|
85
|
+
side: "lower" | "upper",
|
|
86
|
+
): IBoundary | null => {
|
|
87
|
+
if (value === undefined) return null;
|
|
88
|
+
if (Number.isFinite(value)) return { value, exclusive };
|
|
89
|
+
if (value === (side === "lower" ? -Infinity : Infinity)) return null;
|
|
90
|
+
throw new Error("Numeric range has no finite value.");
|
|
91
|
+
};
|
|
92
|
+
|
|
82
93
|
const selectBoundary = (
|
|
83
94
|
x: IBoundary | null,
|
|
84
95
|
y: IBoundary | null,
|
package/src/llm.ts
CHANGED
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
IJsonParseResult,
|
|
3
3
|
ILlmApplication,
|
|
4
4
|
ILlmController,
|
|
5
|
+
ILlmEvaluation,
|
|
5
6
|
ILlmSchema,
|
|
6
7
|
ILlmStructuredOutput,
|
|
7
8
|
} from "@typia/interface";
|
|
@@ -201,6 +202,69 @@ export function structuredOutput(): never {
|
|
|
201
202
|
NoTransformConfigurationError("llm.structuredOutput");
|
|
202
203
|
}
|
|
203
204
|
|
|
205
|
+
/* -----------------------------------------------------------
|
|
206
|
+
EVALUATION
|
|
207
|
+
----------------------------------------------------------- */
|
|
208
|
+
/**
|
|
209
|
+
* Creates LLM evaluation questions.
|
|
210
|
+
*
|
|
211
|
+
* @danger You must configure the generic argument `T`
|
|
212
|
+
*/
|
|
213
|
+
export function evaluation(): never;
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Creates LLM evaluation questions from TypeScript object type.
|
|
217
|
+
*
|
|
218
|
+
* Generates {@link ILlmEvaluation} for evaluation models, which answer typed
|
|
219
|
+
* questions about a shared state with probabilities instead of generating text:
|
|
220
|
+
* TypeSafe's Jev natively, and OpenAI, Anthropic, and Google through Vercel AI
|
|
221
|
+
* SDK's `experimental_evaluate()`.
|
|
222
|
+
*
|
|
223
|
+
* Every leaf property of `T` becomes one question, and its JSDoc description
|
|
224
|
+
* becomes the question text:
|
|
225
|
+
*
|
|
226
|
+
* - `boolean` → boolean question
|
|
227
|
+
* - String enum or string literal union → choice question
|
|
228
|
+
* - Numeric enum or numeric literal union → score question
|
|
229
|
+
* - Array of a string literal union or string enum → one boolean question per
|
|
230
|
+
* member
|
|
231
|
+
* - Nested object → flattened, one question per leaf
|
|
232
|
+
*
|
|
233
|
+
* Types an evaluation model cannot answer, such as `string`, `number`, optional
|
|
234
|
+
* properties, or a leaf without a JSDoc description, are compile errors. Use
|
|
235
|
+
* `tags.Probability<N>` or `@probability N` to set decision thresholds and
|
|
236
|
+
* acceptance minimums. Once one choice, score, or set member declares a
|
|
237
|
+
* requirement, every member must declare one or inherit the property's
|
|
238
|
+
* `@probability` default. A nested object's own JSDoc description is not sent
|
|
239
|
+
* to the model; only the leaves' descriptions become question text. Other
|
|
240
|
+
* validation refinements that the answer decoder cannot enforce are compile
|
|
241
|
+
* errors.
|
|
242
|
+
*
|
|
243
|
+
* This feature is experimental. It follows Vercel AI SDK's evaluation model
|
|
244
|
+
* specification, which is itself experimental and may change in patch
|
|
245
|
+
* releases.
|
|
246
|
+
*
|
|
247
|
+
* Workflow:
|
|
248
|
+
*
|
|
249
|
+
* 1. Pass {@link ILlmEvaluation.questions} to the evaluation model
|
|
250
|
+
* 2. Receive the answer map keyed by the same question IDs
|
|
251
|
+
* 3. Use {@link ILlmEvaluation.decode} to fold the answers back into `T`; pass the
|
|
252
|
+
* model's declared rounding precision when available
|
|
253
|
+
*
|
|
254
|
+
* Related functions:
|
|
255
|
+
*
|
|
256
|
+
* - {@link structuredOutput} — Structured output generated as text by an LLM
|
|
257
|
+
*
|
|
258
|
+
* @template T Target decision type (object with static properties)
|
|
259
|
+
* @returns LLM evaluation questions with a checked answer decoder
|
|
260
|
+
*/
|
|
261
|
+
export function evaluation<T extends Record<string, any>>(): ILlmEvaluation<T>;
|
|
262
|
+
|
|
263
|
+
/** @internal */
|
|
264
|
+
export function evaluation(): never {
|
|
265
|
+
NoTransformConfigurationError("llm.evaluation");
|
|
266
|
+
}
|
|
267
|
+
|
|
204
268
|
/* -----------------------------------------------------------
|
|
205
269
|
RAW SCHEMAS
|
|
206
270
|
----------------------------------------------------------- */
|