@typia/utils 12.0.0-dev.20260307-2 → 12.0.0-dev.20260310
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 +2 -2
- package/lib/http/internal/HttpLlmApplicationComposer.js +1 -0
- package/lib/http/internal/HttpLlmApplicationComposer.js.map +1 -1
- package/lib/http/internal/HttpLlmApplicationComposer.mjs +1 -0
- package/lib/http/internal/HttpLlmApplicationComposer.mjs.map +1 -1
- package/lib/utils/LlmJson.d.ts +3 -3
- package/lib/utils/LlmJson.js +2 -2
- package/lib/utils/LlmJson.js.map +1 -1
- package/lib/utils/LlmJson.mjs +2 -2
- package/lib/utils/LlmJson.mjs.map +1 -1
- package/lib/utils/internal/coerceLlmArguments.js +17 -1
- package/lib/utils/internal/coerceLlmArguments.js.map +1 -1
- package/lib/utils/internal/coerceLlmArguments.mjs +17 -1
- package/lib/utils/internal/coerceLlmArguments.mjs.map +1 -1
- package/lib/utils/internal/parseLenientJson.js +236 -96
- package/lib/utils/internal/parseLenientJson.js.map +1 -1
- package/lib/utils/internal/parseLenientJson.mjs +236 -96
- package/lib/utils/internal/parseLenientJson.mjs.map +1 -1
- package/lib/utils/internal/stringifyValidationFailure.js +17 -15
- package/lib/utils/internal/stringifyValidationFailure.js.map +1 -1
- package/lib/utils/internal/stringifyValidationFailure.mjs +17 -15
- package/lib/utils/internal/stringifyValidationFailure.mjs.map +1 -1
- package/package.json +2 -2
- package/src/converters/LlmSchemaConverter.ts +647 -647
- package/src/converters/OpenApiConverter.ts +285 -285
- package/src/converters/index.ts +5 -5
- package/src/converters/internal/LlmDescriptionInverter.ts +178 -178
- package/src/converters/internal/LlmParametersComposer.ts +52 -52
- package/src/converters/internal/OpenApiConstraintShifter.ts +154 -154
- package/src/converters/internal/OpenApiExclusiveEmender.ts +46 -46
- package/src/converters/internal/OpenApiV3Downgrader.ts +355 -355
- package/src/converters/internal/OpenApiV3Upgrader.ts +470 -470
- package/src/converters/internal/OpenApiV3_1Upgrader.ts +685 -685
- package/src/converters/internal/SwaggerV2Downgrader.ts +424 -424
- package/src/converters/internal/SwaggerV2Upgrader.ts +523 -523
- package/src/http/HttpError.ts +107 -107
- package/src/http/HttpLlm.ts +167 -167
- package/src/http/HttpMigration.ts +92 -92
- package/src/http/index.ts +3 -3
- package/src/http/internal/HttpLlmApplicationComposer.ts +361 -360
- package/src/http/internal/HttpLlmFunctionFetcher.ts +37 -37
- package/src/http/internal/HttpMigrateApplicationComposer.ts +56 -56
- package/src/http/internal/HttpMigrateRouteAccessor.ts +135 -135
- package/src/http/internal/HttpMigrateRouteComposer.ts +505 -505
- package/src/http/internal/HttpMigrateRouteFetcher.ts +203 -203
- package/src/index.ts +4 -4
- package/src/utils/ArrayUtil.ts +42 -42
- package/src/utils/LlmJson.ts +141 -141
- package/src/utils/MapUtil.ts +15 -15
- package/src/utils/NamingConvention.ts +205 -205
- package/src/utils/Singleton.ts +17 -17
- package/src/utils/StringUtil.ts +14 -14
- package/src/utils/dedent.ts +57 -57
- package/src/utils/index.ts +8 -8
- package/src/utils/internal/EndpointUtil.ts +44 -44
- package/src/utils/internal/JsonDescriptor.ts +70 -70
- package/src/utils/internal/OpenApiTypeCheckerBase.ts +822 -822
- package/src/utils/internal/coerceLlmArguments.ts +314 -297
- package/src/utils/internal/parseLenientJson.ts +894 -731
- package/src/utils/internal/stringifyValidationFailure.ts +415 -411
- package/src/validators/LlmTypeChecker.ts +402 -402
- package/src/validators/OpenApiTypeChecker.ts +297 -297
- package/src/validators/OpenApiV3TypeChecker.ts +70 -70
- package/src/validators/OpenApiV3_1TypeChecker.ts +86 -86
- package/src/validators/OpenApiValidator.ts +94 -94
- package/src/validators/SwaggerV2TypeChecker.ts +71 -71
- package/src/validators/functional/_isBigintString.ts +8 -8
- package/src/validators/functional/_isFormatByte.ts +7 -7
- package/src/validators/functional/_isFormatDate.ts +3 -3
- package/src/validators/functional/_isFormatDateTime.ts +4 -4
- package/src/validators/functional/_isFormatDuration.ts +4 -4
- package/src/validators/functional/_isFormatEmail.ts +4 -4
- package/src/validators/functional/_isFormatHostname.ts +4 -4
- package/src/validators/functional/_isFormatIdnEmail.ts +4 -4
- package/src/validators/functional/_isFormatIdnHostname.ts +4 -4
- package/src/validators/functional/_isFormatIpv4.ts +4 -4
- package/src/validators/functional/_isFormatIpv6.ts +4 -4
- package/src/validators/functional/_isFormatIri.ts +3 -3
- package/src/validators/functional/_isFormatIriReference.ts +4 -4
- package/src/validators/functional/_isFormatJsonPointer.ts +3 -3
- package/src/validators/functional/_isFormatPassword.ts +1 -1
- package/src/validators/functional/_isFormatRegex.ts +8 -8
- package/src/validators/functional/_isFormatRelativeJsonPointer.ts +4 -4
- package/src/validators/functional/_isFormatTime.ts +4 -4
- package/src/validators/functional/_isFormatUri.ts +6 -6
- package/src/validators/functional/_isFormatUriReference.ts +5 -5
- package/src/validators/functional/_isFormatUriTemplate.ts +4 -4
- package/src/validators/functional/_isFormatUrl.ts +4 -4
- package/src/validators/functional/_isFormatUuid.ts +3 -3
- package/src/validators/functional/_isUniqueItems.ts +159 -159
- package/src/validators/index.ts +14 -14
- package/src/validators/internal/IOpenApiValidatorContext.ts +17 -17
- package/src/validators/internal/OpenApiArrayValidator.ts +49 -49
- package/src/validators/internal/OpenApiBooleanValidator.ts +11 -11
- package/src/validators/internal/OpenApiConstantValidator.ts +11 -11
- package/src/validators/internal/OpenApiIntegerValidator.ts +49 -49
- package/src/validators/internal/OpenApiNumberValidator.ts +48 -48
- package/src/validators/internal/OpenApiObjectValidator.ts +83 -83
- package/src/validators/internal/OpenApiOneOfValidator.ts +309 -309
- package/src/validators/internal/OpenApiSchemaNamingRule.ts +124 -124
- package/src/validators/internal/OpenApiStationValidator.ts +115 -115
- package/src/validators/internal/OpenApiStringValidator.ts +88 -88
- package/src/validators/internal/OpenApiTupleValidator.ts +55 -55
|
@@ -1,402 +1,402 @@
|
|
|
1
|
-
import { ILlmSchema } from "@typia/interface";
|
|
2
|
-
|
|
3
|
-
import { MapUtil } from "../utils/MapUtil";
|
|
4
|
-
import { OpenApiTypeCheckerBase } from "../utils/internal/OpenApiTypeCheckerBase";
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Type checker for LLM function calling schema.
|
|
8
|
-
*
|
|
9
|
-
* `LlmTypeChecker` is a type checker of {@link ILlmSchema}, the type schema for
|
|
10
|
-
* LLM (Large Language Model) function calling.
|
|
11
|
-
*
|
|
12
|
-
* This checker provides type guard functions for validating schema types, and
|
|
13
|
-
* operators for traversing and comparing schemas.
|
|
14
|
-
*
|
|
15
|
-
* @author Jeongho Nam - https://github.com/samchon
|
|
16
|
-
*/
|
|
17
|
-
export namespace LlmTypeChecker {
|
|
18
|
-
/* -----------------------------------------------------------
|
|
19
|
-
TYPE CHECKERS
|
|
20
|
-
----------------------------------------------------------- */
|
|
21
|
-
/**
|
|
22
|
-
* Test whether the schema is a null type.
|
|
23
|
-
*
|
|
24
|
-
* @param schema Target schema
|
|
25
|
-
* @returns Whether null type or not
|
|
26
|
-
*/
|
|
27
|
-
export const isNull = (schema: ILlmSchema): schema is ILlmSchema.INull =>
|
|
28
|
-
(schema as ILlmSchema.INull).type === "null";
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Test whether the schema is an unknown type.
|
|
32
|
-
*
|
|
33
|
-
* @param schema Target schema
|
|
34
|
-
* @returns Whether unknown type or not
|
|
35
|
-
*/
|
|
36
|
-
export const isUnknown = (
|
|
37
|
-
schema: ILlmSchema,
|
|
38
|
-
): schema is ILlmSchema.IUnknown =>
|
|
39
|
-
(schema as ILlmSchema.IUnknown).type === undefined &&
|
|
40
|
-
!isAnyOf(schema) &&
|
|
41
|
-
!isReference(schema);
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Test whether the schema is a boolean type.
|
|
45
|
-
*
|
|
46
|
-
* @param schema Target schema
|
|
47
|
-
* @returns Whether boolean type or not
|
|
48
|
-
*/
|
|
49
|
-
export const isBoolean = (
|
|
50
|
-
schema: ILlmSchema,
|
|
51
|
-
): schema is ILlmSchema.IBoolean =>
|
|
52
|
-
(schema as ILlmSchema.IBoolean).type === "boolean";
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Test whether the schema is an integer type.
|
|
56
|
-
*
|
|
57
|
-
* @param schema Target schema
|
|
58
|
-
* @returns Whether integer type or not
|
|
59
|
-
*/
|
|
60
|
-
export const isInteger = (
|
|
61
|
-
schema: ILlmSchema,
|
|
62
|
-
): schema is ILlmSchema.IInteger =>
|
|
63
|
-
(schema as ILlmSchema.IInteger).type === "integer";
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Test whether the schema is a number type.
|
|
67
|
-
*
|
|
68
|
-
* @param schema Target schema
|
|
69
|
-
* @returns Whether number type or not
|
|
70
|
-
*/
|
|
71
|
-
export const isNumber = (schema: ILlmSchema): schema is ILlmSchema.INumber =>
|
|
72
|
-
(schema as ILlmSchema.INumber).type === "number";
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Test whether the schema is a string type.
|
|
76
|
-
*
|
|
77
|
-
* @param schema Target schema
|
|
78
|
-
* @returns Whether string type or not
|
|
79
|
-
*/
|
|
80
|
-
export const isString = (schema: ILlmSchema): schema is ILlmSchema.IString =>
|
|
81
|
-
(schema as ILlmSchema.IString).type === "string";
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Test whether the schema is an array type.
|
|
85
|
-
*
|
|
86
|
-
* @param schema Target schema
|
|
87
|
-
* @returns Whether array type or not
|
|
88
|
-
*/
|
|
89
|
-
export const isArray = (schema: ILlmSchema): schema is ILlmSchema.IArray =>
|
|
90
|
-
(schema as ILlmSchema.IArray).type === "array" &&
|
|
91
|
-
(schema as ILlmSchema.IArray).items !== undefined;
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Test whether the schema is an object type.
|
|
95
|
-
*
|
|
96
|
-
* @param schema Target schema
|
|
97
|
-
* @returns Whether object type or not
|
|
98
|
-
*/
|
|
99
|
-
export const isObject = (schema: ILlmSchema): schema is ILlmSchema.IObject =>
|
|
100
|
-
(schema as ILlmSchema.IObject).type === "object";
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Test whether the schema is a reference type.
|
|
104
|
-
*
|
|
105
|
-
* @param schema Target schema
|
|
106
|
-
* @returns Whether reference type or not
|
|
107
|
-
*/
|
|
108
|
-
export const isReference = (
|
|
109
|
-
schema: ILlmSchema,
|
|
110
|
-
): schema is ILlmSchema.IReference => (schema as any).$ref !== undefined;
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Test whether the schema is a union type.
|
|
114
|
-
*
|
|
115
|
-
* @param schema Target schema
|
|
116
|
-
* @returns Whether union type or not
|
|
117
|
-
*/
|
|
118
|
-
export const isAnyOf = (schema: ILlmSchema): schema is ILlmSchema.IAnyOf =>
|
|
119
|
-
(schema as ILlmSchema.IAnyOf).anyOf !== undefined;
|
|
120
|
-
|
|
121
|
-
/* -----------------------------------------------------------
|
|
122
|
-
OPERATORS
|
|
123
|
-
----------------------------------------------------------- */
|
|
124
|
-
/**
|
|
125
|
-
* Visit every nested schemas.
|
|
126
|
-
*
|
|
127
|
-
* Visit every nested schemas of the target, and apply the `props.closure`
|
|
128
|
-
* function.
|
|
129
|
-
*
|
|
130
|
-
* Here is the list of occurring nested visitings:
|
|
131
|
-
*
|
|
132
|
-
* - {@link ILlmSchema.IAnyOf.anyOf}
|
|
133
|
-
* - {@link ILlmSchema.IReference}
|
|
134
|
-
* - {@link ILlmSchema.IObject.properties}
|
|
135
|
-
* - {@link ILlmSchema.IArray.items}
|
|
136
|
-
*
|
|
137
|
-
* @param props Properties for visiting
|
|
138
|
-
*/
|
|
139
|
-
export const visit = (props: {
|
|
140
|
-
closure: (schema: ILlmSchema, accessor: string) => void;
|
|
141
|
-
$defs?: Record<string, ILlmSchema> | undefined;
|
|
142
|
-
schema: ILlmSchema;
|
|
143
|
-
accessor?: string;
|
|
144
|
-
refAccessor?: string;
|
|
145
|
-
}): void => {
|
|
146
|
-
const already: Set<string> = new Set();
|
|
147
|
-
const refAccessor: string = props.refAccessor ?? "$input.$defs";
|
|
148
|
-
const next = (schema: ILlmSchema, accessor: string): void => {
|
|
149
|
-
props.closure(schema, accessor);
|
|
150
|
-
if (LlmTypeChecker.isReference(schema)) {
|
|
151
|
-
const key: string = schema.$ref.split("#/$defs/").pop()!;
|
|
152
|
-
if (already.has(key) === true) return;
|
|
153
|
-
already.add(key);
|
|
154
|
-
const found: ILlmSchema | undefined = props.$defs?.[key];
|
|
155
|
-
if (found !== undefined) next(found, `${refAccessor}[${key}]`);
|
|
156
|
-
} else if (LlmTypeChecker.isAnyOf(schema))
|
|
157
|
-
schema.anyOf.forEach((s, i) => next(s, `${accessor}.anyOf[${i}]`));
|
|
158
|
-
else if (LlmTypeChecker.isObject(schema)) {
|
|
159
|
-
for (const [key, value] of Object.entries(schema.properties))
|
|
160
|
-
next(value, `${accessor}.properties[${JSON.stringify(key)}]`);
|
|
161
|
-
if (
|
|
162
|
-
typeof schema.additionalProperties === "object" &&
|
|
163
|
-
schema.additionalProperties !== null
|
|
164
|
-
)
|
|
165
|
-
next(schema.additionalProperties, `${accessor}.additionalProperties`);
|
|
166
|
-
} else if (LlmTypeChecker.isArray(schema))
|
|
167
|
-
next(schema.items, `${accessor}.items`);
|
|
168
|
-
};
|
|
169
|
-
next(props.schema, props.accessor ?? "$input.schemas");
|
|
170
|
-
};
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* Test whether the `x` schema covers the `y` schema.
|
|
174
|
-
*
|
|
175
|
-
* @param props Properties for testing
|
|
176
|
-
* @returns Whether the `x` schema covers the `y` schema
|
|
177
|
-
*/
|
|
178
|
-
export const covers = (props: {
|
|
179
|
-
$defs?: Record<string, ILlmSchema> | undefined;
|
|
180
|
-
x: ILlmSchema;
|
|
181
|
-
y: ILlmSchema;
|
|
182
|
-
}): boolean =>
|
|
183
|
-
coverStation({
|
|
184
|
-
$defs: props.$defs,
|
|
185
|
-
x: props.x,
|
|
186
|
-
y: props.y,
|
|
187
|
-
visited: new Map(),
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
const coverStation = (p: {
|
|
191
|
-
$defs?: Record<string, ILlmSchema> | undefined;
|
|
192
|
-
visited: Map<ILlmSchema, Map<ILlmSchema, boolean>>;
|
|
193
|
-
x: ILlmSchema;
|
|
194
|
-
y: ILlmSchema;
|
|
195
|
-
}): boolean => {
|
|
196
|
-
const cache: boolean | undefined = p.visited.get(p.x)?.get(p.y);
|
|
197
|
-
if (cache !== undefined) return cache;
|
|
198
|
-
|
|
199
|
-
// FOR RECURSIVE CASE
|
|
200
|
-
const nested: Map<ILlmSchema, boolean> = MapUtil.take(
|
|
201
|
-
p.visited,
|
|
202
|
-
p.x,
|
|
203
|
-
() => new Map(),
|
|
204
|
-
);
|
|
205
|
-
nested.set(p.y, true);
|
|
206
|
-
|
|
207
|
-
// COMPUTE IT
|
|
208
|
-
const result: boolean = coverSchema(p);
|
|
209
|
-
nested.set(p.y, result);
|
|
210
|
-
return result;
|
|
211
|
-
};
|
|
212
|
-
|
|
213
|
-
const coverSchema = (p: {
|
|
214
|
-
$defs?: Record<string, ILlmSchema> | undefined;
|
|
215
|
-
visited: Map<ILlmSchema, Map<ILlmSchema, boolean>>;
|
|
216
|
-
x: ILlmSchema;
|
|
217
|
-
y: ILlmSchema;
|
|
218
|
-
}): boolean => {
|
|
219
|
-
// CHECK EQUALITY
|
|
220
|
-
if (p.x === p.y) return true;
|
|
221
|
-
else if (isReference(p.x) && isReference(p.y) && p.x.$ref === p.y.$ref)
|
|
222
|
-
return true;
|
|
223
|
-
|
|
224
|
-
// COMPARE WITH FLATTENING
|
|
225
|
-
const alpha: ILlmSchema[] = flatSchema(p.$defs, p.x);
|
|
226
|
-
const beta: ILlmSchema[] = flatSchema(p.$defs, p.y);
|
|
227
|
-
if (alpha.some((x) => isUnknown(x))) return true;
|
|
228
|
-
else if (beta.some((x) => isUnknown(x))) return false;
|
|
229
|
-
return beta.every((b) =>
|
|
230
|
-
alpha.some((a) =>
|
|
231
|
-
coverEscapedSchema({
|
|
232
|
-
$defs: p.$defs,
|
|
233
|
-
visited: p.visited,
|
|
234
|
-
x: a,
|
|
235
|
-
y: b,
|
|
236
|
-
}),
|
|
237
|
-
),
|
|
238
|
-
);
|
|
239
|
-
};
|
|
240
|
-
|
|
241
|
-
const coverEscapedSchema = (p: {
|
|
242
|
-
$defs?: Record<string, ILlmSchema> | undefined;
|
|
243
|
-
visited: Map<ILlmSchema, Map<ILlmSchema, boolean>>;
|
|
244
|
-
x: ILlmSchema;
|
|
245
|
-
y: ILlmSchema;
|
|
246
|
-
}): boolean => {
|
|
247
|
-
// CHECK EQUALITY
|
|
248
|
-
if (p.x === p.y) return true;
|
|
249
|
-
else if (isUnknown(p.x)) return true;
|
|
250
|
-
else if (isUnknown(p.y)) return false;
|
|
251
|
-
else if (isNull(p.x)) return isNull(p.y);
|
|
252
|
-
// ATOMIC CASE
|
|
253
|
-
else if (isBoolean(p.x)) return isBoolean(p.y) && coverBoolean(p.x, p.y);
|
|
254
|
-
else if (isInteger(p.x)) return isInteger(p.y) && coverInteger(p.x, p.y);
|
|
255
|
-
else if (isNumber(p.x)) return isNumber(p.y) && coverNumber(p.x, p.y);
|
|
256
|
-
else if (isString(p.x)) return isString(p.y) && coverString(p.x, p.y);
|
|
257
|
-
// INSTANCE CASE
|
|
258
|
-
else if (isArray(p.x))
|
|
259
|
-
return (
|
|
260
|
-
isArray(p.y) &&
|
|
261
|
-
coverArray({
|
|
262
|
-
$defs: p.$defs,
|
|
263
|
-
visited: p.visited,
|
|
264
|
-
x: p.x,
|
|
265
|
-
y: p.y,
|
|
266
|
-
})
|
|
267
|
-
);
|
|
268
|
-
else if (isObject(p.x))
|
|
269
|
-
return (
|
|
270
|
-
isObject(p.y) &&
|
|
271
|
-
coverObject({
|
|
272
|
-
$defs: p.$defs,
|
|
273
|
-
visited: p.visited,
|
|
274
|
-
x: p.x,
|
|
275
|
-
y: p.y,
|
|
276
|
-
})
|
|
277
|
-
);
|
|
278
|
-
else if (isReference(p.x)) return isReference(p.y) && p.x.$ref === p.y.$ref;
|
|
279
|
-
return false;
|
|
280
|
-
};
|
|
281
|
-
|
|
282
|
-
const coverArray = (p: {
|
|
283
|
-
$defs?: Record<string, ILlmSchema> | undefined;
|
|
284
|
-
visited: Map<ILlmSchema, Map<ILlmSchema, boolean>>;
|
|
285
|
-
x: ILlmSchema.IArray;
|
|
286
|
-
y: ILlmSchema.IArray;
|
|
287
|
-
}): boolean => {
|
|
288
|
-
if (
|
|
289
|
-
!(
|
|
290
|
-
p.x.minItems === undefined ||
|
|
291
|
-
(p.y.minItems !== undefined && p.x.minItems <= p.y.minItems)
|
|
292
|
-
)
|
|
293
|
-
)
|
|
294
|
-
return false;
|
|
295
|
-
else if (
|
|
296
|
-
!(
|
|
297
|
-
p.x.maxItems === undefined ||
|
|
298
|
-
(p.y.maxItems !== undefined && p.x.maxItems >= p.y.maxItems)
|
|
299
|
-
)
|
|
300
|
-
)
|
|
301
|
-
return false;
|
|
302
|
-
return coverStation({
|
|
303
|
-
$defs: p.$defs,
|
|
304
|
-
visited: p.visited,
|
|
305
|
-
x: p.x.items,
|
|
306
|
-
y: p.y.items,
|
|
307
|
-
});
|
|
308
|
-
};
|
|
309
|
-
|
|
310
|
-
const coverObject = (p: {
|
|
311
|
-
$defs?: Record<string, ILlmSchema> | undefined;
|
|
312
|
-
visited: Map<ILlmSchema, Map<ILlmSchema, boolean>>;
|
|
313
|
-
x: ILlmSchema.IObject;
|
|
314
|
-
y: ILlmSchema.IObject;
|
|
315
|
-
}): boolean => {
|
|
316
|
-
if (!p.x.additionalProperties && !!p.y.additionalProperties) return false;
|
|
317
|
-
else if (
|
|
318
|
-
!!p.x.additionalProperties &&
|
|
319
|
-
!!p.y.additionalProperties &&
|
|
320
|
-
((typeof p.x.additionalProperties === "object" &&
|
|
321
|
-
p.y.additionalProperties === true) ||
|
|
322
|
-
(typeof p.x.additionalProperties === "object" &&
|
|
323
|
-
typeof p.y.additionalProperties === "object" &&
|
|
324
|
-
!coverStation({
|
|
325
|
-
$defs: p.$defs,
|
|
326
|
-
visited: p.visited,
|
|
327
|
-
x: p.x.additionalProperties,
|
|
328
|
-
y: p.y.additionalProperties,
|
|
329
|
-
})))
|
|
330
|
-
)
|
|
331
|
-
return false;
|
|
332
|
-
return Object.entries(p.y.properties ?? {}).every(([key, b]) => {
|
|
333
|
-
const a: ILlmSchema | undefined = p.x.properties?.[key];
|
|
334
|
-
if (a === undefined) return false;
|
|
335
|
-
else if (
|
|
336
|
-
(p.x.required?.includes(key) ?? false) === true &&
|
|
337
|
-
(p.y.required?.includes(key) ?? false) === false
|
|
338
|
-
)
|
|
339
|
-
return false;
|
|
340
|
-
return coverStation({
|
|
341
|
-
$defs: p.$defs,
|
|
342
|
-
visited: p.visited,
|
|
343
|
-
x: a,
|
|
344
|
-
y: b,
|
|
345
|
-
});
|
|
346
|
-
});
|
|
347
|
-
};
|
|
348
|
-
|
|
349
|
-
const coverBoolean = (
|
|
350
|
-
x: ILlmSchema.IBoolean,
|
|
351
|
-
y: ILlmSchema.IBoolean,
|
|
352
|
-
): boolean => {
|
|
353
|
-
if (!!x.enum?.length)
|
|
354
|
-
return !!y.enum?.length && y.enum.every((v) => x.enum!.includes(v));
|
|
355
|
-
return true;
|
|
356
|
-
};
|
|
357
|
-
|
|
358
|
-
const coverInteger = (
|
|
359
|
-
x: ILlmSchema.IInteger,
|
|
360
|
-
y: ILlmSchema.IInteger,
|
|
361
|
-
): boolean => {
|
|
362
|
-
if (!!x.enum?.length)
|
|
363
|
-
return !!y.enum?.length && y.enum.every((v) => x.enum!.includes(v));
|
|
364
|
-
return OpenApiTypeCheckerBase.coverInteger(x, y);
|
|
365
|
-
};
|
|
366
|
-
|
|
367
|
-
const coverNumber = (
|
|
368
|
-
x: ILlmSchema.INumber,
|
|
369
|
-
y: ILlmSchema.IInteger | ILlmSchema.INumber,
|
|
370
|
-
): boolean => {
|
|
371
|
-
if (!!x.enum?.length)
|
|
372
|
-
return !!y.enum?.length && y.enum.every((v) => x.enum!.includes(v));
|
|
373
|
-
return OpenApiTypeCheckerBase.coverNumber(x, y);
|
|
374
|
-
};
|
|
375
|
-
|
|
376
|
-
const coverString = (
|
|
377
|
-
x: ILlmSchema.IString,
|
|
378
|
-
y: ILlmSchema.IString,
|
|
379
|
-
): boolean => {
|
|
380
|
-
if (!!x.enum?.length)
|
|
381
|
-
return !!y.enum?.length && y.enum.every((v) => x.enum!.includes(v));
|
|
382
|
-
return OpenApiTypeCheckerBase.coverString(x, y);
|
|
383
|
-
};
|
|
384
|
-
|
|
385
|
-
const flatSchema = (
|
|
386
|
-
$defs: Record<string, ILlmSchema> | undefined,
|
|
387
|
-
schema: ILlmSchema,
|
|
388
|
-
): ILlmSchema[] => {
|
|
389
|
-
schema = escapeReference($defs, schema);
|
|
390
|
-
if (isAnyOf(schema))
|
|
391
|
-
return schema.anyOf.map((v) => flatSchema($defs, v)).flat();
|
|
392
|
-
return [schema];
|
|
393
|
-
};
|
|
394
|
-
|
|
395
|
-
const escapeReference = (
|
|
396
|
-
$defs: Record<string, ILlmSchema> | undefined,
|
|
397
|
-
schema: ILlmSchema,
|
|
398
|
-
): Exclude<ILlmSchema, ILlmSchema.IReference> =>
|
|
399
|
-
isReference(schema)
|
|
400
|
-
? escapeReference($defs, $defs![schema.$ref.replace("#/$defs/", "")]!)
|
|
401
|
-
: schema;
|
|
402
|
-
}
|
|
1
|
+
import { ILlmSchema } from "@typia/interface";
|
|
2
|
+
|
|
3
|
+
import { MapUtil } from "../utils/MapUtil";
|
|
4
|
+
import { OpenApiTypeCheckerBase } from "../utils/internal/OpenApiTypeCheckerBase";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Type checker for LLM function calling schema.
|
|
8
|
+
*
|
|
9
|
+
* `LlmTypeChecker` is a type checker of {@link ILlmSchema}, the type schema for
|
|
10
|
+
* LLM (Large Language Model) function calling.
|
|
11
|
+
*
|
|
12
|
+
* This checker provides type guard functions for validating schema types, and
|
|
13
|
+
* operators for traversing and comparing schemas.
|
|
14
|
+
*
|
|
15
|
+
* @author Jeongho Nam - https://github.com/samchon
|
|
16
|
+
*/
|
|
17
|
+
export namespace LlmTypeChecker {
|
|
18
|
+
/* -----------------------------------------------------------
|
|
19
|
+
TYPE CHECKERS
|
|
20
|
+
----------------------------------------------------------- */
|
|
21
|
+
/**
|
|
22
|
+
* Test whether the schema is a null type.
|
|
23
|
+
*
|
|
24
|
+
* @param schema Target schema
|
|
25
|
+
* @returns Whether null type or not
|
|
26
|
+
*/
|
|
27
|
+
export const isNull = (schema: ILlmSchema): schema is ILlmSchema.INull =>
|
|
28
|
+
(schema as ILlmSchema.INull).type === "null";
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Test whether the schema is an unknown type.
|
|
32
|
+
*
|
|
33
|
+
* @param schema Target schema
|
|
34
|
+
* @returns Whether unknown type or not
|
|
35
|
+
*/
|
|
36
|
+
export const isUnknown = (
|
|
37
|
+
schema: ILlmSchema,
|
|
38
|
+
): schema is ILlmSchema.IUnknown =>
|
|
39
|
+
(schema as ILlmSchema.IUnknown).type === undefined &&
|
|
40
|
+
!isAnyOf(schema) &&
|
|
41
|
+
!isReference(schema);
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Test whether the schema is a boolean type.
|
|
45
|
+
*
|
|
46
|
+
* @param schema Target schema
|
|
47
|
+
* @returns Whether boolean type or not
|
|
48
|
+
*/
|
|
49
|
+
export const isBoolean = (
|
|
50
|
+
schema: ILlmSchema,
|
|
51
|
+
): schema is ILlmSchema.IBoolean =>
|
|
52
|
+
(schema as ILlmSchema.IBoolean).type === "boolean";
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Test whether the schema is an integer type.
|
|
56
|
+
*
|
|
57
|
+
* @param schema Target schema
|
|
58
|
+
* @returns Whether integer type or not
|
|
59
|
+
*/
|
|
60
|
+
export const isInteger = (
|
|
61
|
+
schema: ILlmSchema,
|
|
62
|
+
): schema is ILlmSchema.IInteger =>
|
|
63
|
+
(schema as ILlmSchema.IInteger).type === "integer";
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Test whether the schema is a number type.
|
|
67
|
+
*
|
|
68
|
+
* @param schema Target schema
|
|
69
|
+
* @returns Whether number type or not
|
|
70
|
+
*/
|
|
71
|
+
export const isNumber = (schema: ILlmSchema): schema is ILlmSchema.INumber =>
|
|
72
|
+
(schema as ILlmSchema.INumber).type === "number";
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Test whether the schema is a string type.
|
|
76
|
+
*
|
|
77
|
+
* @param schema Target schema
|
|
78
|
+
* @returns Whether string type or not
|
|
79
|
+
*/
|
|
80
|
+
export const isString = (schema: ILlmSchema): schema is ILlmSchema.IString =>
|
|
81
|
+
(schema as ILlmSchema.IString).type === "string";
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Test whether the schema is an array type.
|
|
85
|
+
*
|
|
86
|
+
* @param schema Target schema
|
|
87
|
+
* @returns Whether array type or not
|
|
88
|
+
*/
|
|
89
|
+
export const isArray = (schema: ILlmSchema): schema is ILlmSchema.IArray =>
|
|
90
|
+
(schema as ILlmSchema.IArray).type === "array" &&
|
|
91
|
+
(schema as ILlmSchema.IArray).items !== undefined;
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Test whether the schema is an object type.
|
|
95
|
+
*
|
|
96
|
+
* @param schema Target schema
|
|
97
|
+
* @returns Whether object type or not
|
|
98
|
+
*/
|
|
99
|
+
export const isObject = (schema: ILlmSchema): schema is ILlmSchema.IObject =>
|
|
100
|
+
(schema as ILlmSchema.IObject).type === "object";
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Test whether the schema is a reference type.
|
|
104
|
+
*
|
|
105
|
+
* @param schema Target schema
|
|
106
|
+
* @returns Whether reference type or not
|
|
107
|
+
*/
|
|
108
|
+
export const isReference = (
|
|
109
|
+
schema: ILlmSchema,
|
|
110
|
+
): schema is ILlmSchema.IReference => (schema as any).$ref !== undefined;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Test whether the schema is a union type.
|
|
114
|
+
*
|
|
115
|
+
* @param schema Target schema
|
|
116
|
+
* @returns Whether union type or not
|
|
117
|
+
*/
|
|
118
|
+
export const isAnyOf = (schema: ILlmSchema): schema is ILlmSchema.IAnyOf =>
|
|
119
|
+
(schema as ILlmSchema.IAnyOf).anyOf !== undefined;
|
|
120
|
+
|
|
121
|
+
/* -----------------------------------------------------------
|
|
122
|
+
OPERATORS
|
|
123
|
+
----------------------------------------------------------- */
|
|
124
|
+
/**
|
|
125
|
+
* Visit every nested schemas.
|
|
126
|
+
*
|
|
127
|
+
* Visit every nested schemas of the target, and apply the `props.closure`
|
|
128
|
+
* function.
|
|
129
|
+
*
|
|
130
|
+
* Here is the list of occurring nested visitings:
|
|
131
|
+
*
|
|
132
|
+
* - {@link ILlmSchema.IAnyOf.anyOf}
|
|
133
|
+
* - {@link ILlmSchema.IReference}
|
|
134
|
+
* - {@link ILlmSchema.IObject.properties}
|
|
135
|
+
* - {@link ILlmSchema.IArray.items}
|
|
136
|
+
*
|
|
137
|
+
* @param props Properties for visiting
|
|
138
|
+
*/
|
|
139
|
+
export const visit = (props: {
|
|
140
|
+
closure: (schema: ILlmSchema, accessor: string) => void;
|
|
141
|
+
$defs?: Record<string, ILlmSchema> | undefined;
|
|
142
|
+
schema: ILlmSchema;
|
|
143
|
+
accessor?: string;
|
|
144
|
+
refAccessor?: string;
|
|
145
|
+
}): void => {
|
|
146
|
+
const already: Set<string> = new Set();
|
|
147
|
+
const refAccessor: string = props.refAccessor ?? "$input.$defs";
|
|
148
|
+
const next = (schema: ILlmSchema, accessor: string): void => {
|
|
149
|
+
props.closure(schema, accessor);
|
|
150
|
+
if (LlmTypeChecker.isReference(schema)) {
|
|
151
|
+
const key: string = schema.$ref.split("#/$defs/").pop()!;
|
|
152
|
+
if (already.has(key) === true) return;
|
|
153
|
+
already.add(key);
|
|
154
|
+
const found: ILlmSchema | undefined = props.$defs?.[key];
|
|
155
|
+
if (found !== undefined) next(found, `${refAccessor}[${key}]`);
|
|
156
|
+
} else if (LlmTypeChecker.isAnyOf(schema))
|
|
157
|
+
schema.anyOf.forEach((s, i) => next(s, `${accessor}.anyOf[${i}]`));
|
|
158
|
+
else if (LlmTypeChecker.isObject(schema)) {
|
|
159
|
+
for (const [key, value] of Object.entries(schema.properties))
|
|
160
|
+
next(value, `${accessor}.properties[${JSON.stringify(key)}]`);
|
|
161
|
+
if (
|
|
162
|
+
typeof schema.additionalProperties === "object" &&
|
|
163
|
+
schema.additionalProperties !== null
|
|
164
|
+
)
|
|
165
|
+
next(schema.additionalProperties, `${accessor}.additionalProperties`);
|
|
166
|
+
} else if (LlmTypeChecker.isArray(schema))
|
|
167
|
+
next(schema.items, `${accessor}.items`);
|
|
168
|
+
};
|
|
169
|
+
next(props.schema, props.accessor ?? "$input.schemas");
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Test whether the `x` schema covers the `y` schema.
|
|
174
|
+
*
|
|
175
|
+
* @param props Properties for testing
|
|
176
|
+
* @returns Whether the `x` schema covers the `y` schema
|
|
177
|
+
*/
|
|
178
|
+
export const covers = (props: {
|
|
179
|
+
$defs?: Record<string, ILlmSchema> | undefined;
|
|
180
|
+
x: ILlmSchema;
|
|
181
|
+
y: ILlmSchema;
|
|
182
|
+
}): boolean =>
|
|
183
|
+
coverStation({
|
|
184
|
+
$defs: props.$defs,
|
|
185
|
+
x: props.x,
|
|
186
|
+
y: props.y,
|
|
187
|
+
visited: new Map(),
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
const coverStation = (p: {
|
|
191
|
+
$defs?: Record<string, ILlmSchema> | undefined;
|
|
192
|
+
visited: Map<ILlmSchema, Map<ILlmSchema, boolean>>;
|
|
193
|
+
x: ILlmSchema;
|
|
194
|
+
y: ILlmSchema;
|
|
195
|
+
}): boolean => {
|
|
196
|
+
const cache: boolean | undefined = p.visited.get(p.x)?.get(p.y);
|
|
197
|
+
if (cache !== undefined) return cache;
|
|
198
|
+
|
|
199
|
+
// FOR RECURSIVE CASE
|
|
200
|
+
const nested: Map<ILlmSchema, boolean> = MapUtil.take(
|
|
201
|
+
p.visited,
|
|
202
|
+
p.x,
|
|
203
|
+
() => new Map(),
|
|
204
|
+
);
|
|
205
|
+
nested.set(p.y, true);
|
|
206
|
+
|
|
207
|
+
// COMPUTE IT
|
|
208
|
+
const result: boolean = coverSchema(p);
|
|
209
|
+
nested.set(p.y, result);
|
|
210
|
+
return result;
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
const coverSchema = (p: {
|
|
214
|
+
$defs?: Record<string, ILlmSchema> | undefined;
|
|
215
|
+
visited: Map<ILlmSchema, Map<ILlmSchema, boolean>>;
|
|
216
|
+
x: ILlmSchema;
|
|
217
|
+
y: ILlmSchema;
|
|
218
|
+
}): boolean => {
|
|
219
|
+
// CHECK EQUALITY
|
|
220
|
+
if (p.x === p.y) return true;
|
|
221
|
+
else if (isReference(p.x) && isReference(p.y) && p.x.$ref === p.y.$ref)
|
|
222
|
+
return true;
|
|
223
|
+
|
|
224
|
+
// COMPARE WITH FLATTENING
|
|
225
|
+
const alpha: ILlmSchema[] = flatSchema(p.$defs, p.x);
|
|
226
|
+
const beta: ILlmSchema[] = flatSchema(p.$defs, p.y);
|
|
227
|
+
if (alpha.some((x) => isUnknown(x))) return true;
|
|
228
|
+
else if (beta.some((x) => isUnknown(x))) return false;
|
|
229
|
+
return beta.every((b) =>
|
|
230
|
+
alpha.some((a) =>
|
|
231
|
+
coverEscapedSchema({
|
|
232
|
+
$defs: p.$defs,
|
|
233
|
+
visited: p.visited,
|
|
234
|
+
x: a,
|
|
235
|
+
y: b,
|
|
236
|
+
}),
|
|
237
|
+
),
|
|
238
|
+
);
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
const coverEscapedSchema = (p: {
|
|
242
|
+
$defs?: Record<string, ILlmSchema> | undefined;
|
|
243
|
+
visited: Map<ILlmSchema, Map<ILlmSchema, boolean>>;
|
|
244
|
+
x: ILlmSchema;
|
|
245
|
+
y: ILlmSchema;
|
|
246
|
+
}): boolean => {
|
|
247
|
+
// CHECK EQUALITY
|
|
248
|
+
if (p.x === p.y) return true;
|
|
249
|
+
else if (isUnknown(p.x)) return true;
|
|
250
|
+
else if (isUnknown(p.y)) return false;
|
|
251
|
+
else if (isNull(p.x)) return isNull(p.y);
|
|
252
|
+
// ATOMIC CASE
|
|
253
|
+
else if (isBoolean(p.x)) return isBoolean(p.y) && coverBoolean(p.x, p.y);
|
|
254
|
+
else if (isInteger(p.x)) return isInteger(p.y) && coverInteger(p.x, p.y);
|
|
255
|
+
else if (isNumber(p.x)) return isNumber(p.y) && coverNumber(p.x, p.y);
|
|
256
|
+
else if (isString(p.x)) return isString(p.y) && coverString(p.x, p.y);
|
|
257
|
+
// INSTANCE CASE
|
|
258
|
+
else if (isArray(p.x))
|
|
259
|
+
return (
|
|
260
|
+
isArray(p.y) &&
|
|
261
|
+
coverArray({
|
|
262
|
+
$defs: p.$defs,
|
|
263
|
+
visited: p.visited,
|
|
264
|
+
x: p.x,
|
|
265
|
+
y: p.y,
|
|
266
|
+
})
|
|
267
|
+
);
|
|
268
|
+
else if (isObject(p.x))
|
|
269
|
+
return (
|
|
270
|
+
isObject(p.y) &&
|
|
271
|
+
coverObject({
|
|
272
|
+
$defs: p.$defs,
|
|
273
|
+
visited: p.visited,
|
|
274
|
+
x: p.x,
|
|
275
|
+
y: p.y,
|
|
276
|
+
})
|
|
277
|
+
);
|
|
278
|
+
else if (isReference(p.x)) return isReference(p.y) && p.x.$ref === p.y.$ref;
|
|
279
|
+
return false;
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
const coverArray = (p: {
|
|
283
|
+
$defs?: Record<string, ILlmSchema> | undefined;
|
|
284
|
+
visited: Map<ILlmSchema, Map<ILlmSchema, boolean>>;
|
|
285
|
+
x: ILlmSchema.IArray;
|
|
286
|
+
y: ILlmSchema.IArray;
|
|
287
|
+
}): boolean => {
|
|
288
|
+
if (
|
|
289
|
+
!(
|
|
290
|
+
p.x.minItems === undefined ||
|
|
291
|
+
(p.y.minItems !== undefined && p.x.minItems <= p.y.minItems)
|
|
292
|
+
)
|
|
293
|
+
)
|
|
294
|
+
return false;
|
|
295
|
+
else if (
|
|
296
|
+
!(
|
|
297
|
+
p.x.maxItems === undefined ||
|
|
298
|
+
(p.y.maxItems !== undefined && p.x.maxItems >= p.y.maxItems)
|
|
299
|
+
)
|
|
300
|
+
)
|
|
301
|
+
return false;
|
|
302
|
+
return coverStation({
|
|
303
|
+
$defs: p.$defs,
|
|
304
|
+
visited: p.visited,
|
|
305
|
+
x: p.x.items,
|
|
306
|
+
y: p.y.items,
|
|
307
|
+
});
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
const coverObject = (p: {
|
|
311
|
+
$defs?: Record<string, ILlmSchema> | undefined;
|
|
312
|
+
visited: Map<ILlmSchema, Map<ILlmSchema, boolean>>;
|
|
313
|
+
x: ILlmSchema.IObject;
|
|
314
|
+
y: ILlmSchema.IObject;
|
|
315
|
+
}): boolean => {
|
|
316
|
+
if (!p.x.additionalProperties && !!p.y.additionalProperties) return false;
|
|
317
|
+
else if (
|
|
318
|
+
!!p.x.additionalProperties &&
|
|
319
|
+
!!p.y.additionalProperties &&
|
|
320
|
+
((typeof p.x.additionalProperties === "object" &&
|
|
321
|
+
p.y.additionalProperties === true) ||
|
|
322
|
+
(typeof p.x.additionalProperties === "object" &&
|
|
323
|
+
typeof p.y.additionalProperties === "object" &&
|
|
324
|
+
!coverStation({
|
|
325
|
+
$defs: p.$defs,
|
|
326
|
+
visited: p.visited,
|
|
327
|
+
x: p.x.additionalProperties,
|
|
328
|
+
y: p.y.additionalProperties,
|
|
329
|
+
})))
|
|
330
|
+
)
|
|
331
|
+
return false;
|
|
332
|
+
return Object.entries(p.y.properties ?? {}).every(([key, b]) => {
|
|
333
|
+
const a: ILlmSchema | undefined = p.x.properties?.[key];
|
|
334
|
+
if (a === undefined) return false;
|
|
335
|
+
else if (
|
|
336
|
+
(p.x.required?.includes(key) ?? false) === true &&
|
|
337
|
+
(p.y.required?.includes(key) ?? false) === false
|
|
338
|
+
)
|
|
339
|
+
return false;
|
|
340
|
+
return coverStation({
|
|
341
|
+
$defs: p.$defs,
|
|
342
|
+
visited: p.visited,
|
|
343
|
+
x: a,
|
|
344
|
+
y: b,
|
|
345
|
+
});
|
|
346
|
+
});
|
|
347
|
+
};
|
|
348
|
+
|
|
349
|
+
const coverBoolean = (
|
|
350
|
+
x: ILlmSchema.IBoolean,
|
|
351
|
+
y: ILlmSchema.IBoolean,
|
|
352
|
+
): boolean => {
|
|
353
|
+
if (!!x.enum?.length)
|
|
354
|
+
return !!y.enum?.length && y.enum.every((v) => x.enum!.includes(v));
|
|
355
|
+
return true;
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
const coverInteger = (
|
|
359
|
+
x: ILlmSchema.IInteger,
|
|
360
|
+
y: ILlmSchema.IInteger,
|
|
361
|
+
): boolean => {
|
|
362
|
+
if (!!x.enum?.length)
|
|
363
|
+
return !!y.enum?.length && y.enum.every((v) => x.enum!.includes(v));
|
|
364
|
+
return OpenApiTypeCheckerBase.coverInteger(x, y);
|
|
365
|
+
};
|
|
366
|
+
|
|
367
|
+
const coverNumber = (
|
|
368
|
+
x: ILlmSchema.INumber,
|
|
369
|
+
y: ILlmSchema.IInteger | ILlmSchema.INumber,
|
|
370
|
+
): boolean => {
|
|
371
|
+
if (!!x.enum?.length)
|
|
372
|
+
return !!y.enum?.length && y.enum.every((v) => x.enum!.includes(v));
|
|
373
|
+
return OpenApiTypeCheckerBase.coverNumber(x, y);
|
|
374
|
+
};
|
|
375
|
+
|
|
376
|
+
const coverString = (
|
|
377
|
+
x: ILlmSchema.IString,
|
|
378
|
+
y: ILlmSchema.IString,
|
|
379
|
+
): boolean => {
|
|
380
|
+
if (!!x.enum?.length)
|
|
381
|
+
return !!y.enum?.length && y.enum.every((v) => x.enum!.includes(v));
|
|
382
|
+
return OpenApiTypeCheckerBase.coverString(x, y);
|
|
383
|
+
};
|
|
384
|
+
|
|
385
|
+
const flatSchema = (
|
|
386
|
+
$defs: Record<string, ILlmSchema> | undefined,
|
|
387
|
+
schema: ILlmSchema,
|
|
388
|
+
): ILlmSchema[] => {
|
|
389
|
+
schema = escapeReference($defs, schema);
|
|
390
|
+
if (isAnyOf(schema))
|
|
391
|
+
return schema.anyOf.map((v) => flatSchema($defs, v)).flat();
|
|
392
|
+
return [schema];
|
|
393
|
+
};
|
|
394
|
+
|
|
395
|
+
const escapeReference = (
|
|
396
|
+
$defs: Record<string, ILlmSchema> | undefined,
|
|
397
|
+
schema: ILlmSchema,
|
|
398
|
+
): Exclude<ILlmSchema, ILlmSchema.IReference> =>
|
|
399
|
+
isReference(schema)
|
|
400
|
+
? escapeReference($defs, $defs![schema.$ref.replace("#/$defs/", "")]!)
|
|
401
|
+
: schema;
|
|
402
|
+
}
|