@mastra/schema-compat 0.0.0-ai-v5-20250801192614 → 0.0.0-consolidate-changesets-20250904042643
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/CHANGELOG.md +133 -2
- package/README.md +0 -4
- package/dist/chunk-F4D2N3FC.js +28 -0
- package/dist/chunk-F4D2N3FC.js.map +1 -0
- package/dist/chunk-WRGSGOLQ.cjs +34 -0
- package/dist/chunk-WRGSGOLQ.cjs.map +1 -0
- package/dist/index.cjs +845 -92
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +844 -93
- package/dist/index.js.map +1 -1
- package/dist/provider-compats/anthropic.d.ts +6 -4
- package/dist/provider-compats/anthropic.d.ts.map +1 -1
- package/dist/provider-compats/deepseek.d.ts +6 -4
- package/dist/provider-compats/deepseek.d.ts.map +1 -1
- package/dist/provider-compats/google.d.ts +6 -4
- package/dist/provider-compats/google.d.ts.map +1 -1
- package/dist/provider-compats/meta.d.ts +6 -4
- package/dist/provider-compats/meta.d.ts.map +1 -1
- package/dist/provider-compats/openai-reasoning.d.ts +6 -4
- package/dist/provider-compats/openai-reasoning.d.ts.map +1 -1
- package/dist/provider-compats/openai.d.ts +6 -4
- package/dist/provider-compats/openai.d.ts.map +1 -1
- package/dist/schema-compatibility-v3.d.ts +319 -0
- package/dist/schema-compatibility-v3.d.ts.map +1 -0
- package/dist/schema-compatibility-v4.d.ts +310 -0
- package/dist/schema-compatibility-v4.d.ts.map +1 -0
- package/dist/schema-compatibility.d.ts +79 -132
- package/dist/schema-compatibility.d.ts.map +1 -1
- package/dist/types.d.ts +6 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/utils-test-suite.d.ts +2 -0
- package/dist/utils-test-suite.d.ts.map +1 -0
- package/dist/utils.d.ts +16 -4
- package/dist/utils.d.ts.map +1 -1
- package/dist/zod-to-json.cjs +12 -0
- package/dist/zod-to-json.cjs.map +1 -0
- package/dist/zod-to-json.d.ts +6 -0
- package/dist/zod-to-json.d.ts.map +1 -0
- package/dist/zod-to-json.js +3 -0
- package/dist/zod-to-json.js.map +1 -0
- package/dist/zodTypes.d.ts +21 -0
- package/dist/zodTypes.d.ts.map +1 -0
- package/package.json +33 -9
- package/.turbo/turbo-build.log +0 -4
- package/eslint.config.js +0 -6
- package/src/index.ts +0 -39
- package/src/provider-compats/anthropic.ts +0 -43
- package/src/provider-compats/deepseek.ts +0 -35
- package/src/provider-compats/google.ts +0 -63
- package/src/provider-compats/meta.ts +0 -36
- package/src/provider-compats/openai-reasoning.ts +0 -88
- package/src/provider-compats/openai.ts +0 -56
- package/src/provider-compats.test.ts +0 -312
- package/src/schema-compatibility.test.ts +0 -479
- package/src/schema-compatibility.ts +0 -590
- package/src/utils.test.ts +0 -442
- package/src/utils.ts +0 -205
- package/tsconfig.build.json +0 -9
- package/tsconfig.json +0 -5
- package/tsup.config.ts +0 -22
- package/vitest.config.ts +0 -7
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import type { ZodTypeAny } from 'zod';
|
|
2
|
-
import type { Targets } from 'zod-to-json-schema';
|
|
3
|
-
import { SchemaCompatLayer, isArr, isObj, isOptional, isString, isUnion } from '../schema-compatibility';
|
|
4
|
-
import type { AllZodType, SchemaCompatModel } from '../schema-compatibility';
|
|
5
|
-
|
|
6
|
-
export class AnthropicSchemaCompatLayer extends SchemaCompatLayer {
|
|
7
|
-
constructor(model: SchemaCompatModel) {
|
|
8
|
-
super(model);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
getSchemaTarget(): Targets | undefined {
|
|
12
|
-
return 'jsonSchema7';
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
shouldApply(): boolean {
|
|
16
|
-
return this.getModel().modelId.includes('claude');
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
processZodType(value: ZodTypeAny): ZodTypeAny {
|
|
20
|
-
if (isOptional(value)) {
|
|
21
|
-
const handleTypes: AllZodType[] = ['ZodObject', 'ZodArray', 'ZodUnion', 'ZodNever', 'ZodUndefined', 'ZodTuple'];
|
|
22
|
-
if (this.getModel().modelId.includes('claude-3.5-haiku')) handleTypes.push('ZodString');
|
|
23
|
-
return this.defaultZodOptionalHandler(value, handleTypes);
|
|
24
|
-
} else if (isObj(value)) {
|
|
25
|
-
return this.defaultZodObjectHandler(value);
|
|
26
|
-
} else if (isArr(value)) {
|
|
27
|
-
return this.defaultZodArrayHandler(value, []);
|
|
28
|
-
} else if (isUnion(value)) {
|
|
29
|
-
return this.defaultZodUnionHandler(value);
|
|
30
|
-
} else if (isString(value)) {
|
|
31
|
-
// the claude-3.5-haiku model support these properties but the model doesn't respect them, but it respects them when they're
|
|
32
|
-
// added to the tool description
|
|
33
|
-
|
|
34
|
-
if (this.getModel().modelId.includes('claude-3.5-haiku')) {
|
|
35
|
-
return this.defaultZodStringHandler(value, ['max', 'min']);
|
|
36
|
-
} else {
|
|
37
|
-
return value;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
return this.defaultUnsupportedZodTypeHandler(value, ['ZodNever', 'ZodTuple', 'ZodUndefined']);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import type { ZodTypeAny } from 'zod';
|
|
2
|
-
import type { Targets } from 'zod-to-json-schema';
|
|
3
|
-
import { SchemaCompatLayer, isArr, isObj, isOptional, isString, isUnion } from '../schema-compatibility';
|
|
4
|
-
import type { SchemaCompatModel } from '../schema-compatibility';
|
|
5
|
-
|
|
6
|
-
export class DeepSeekSchemaCompatLayer extends SchemaCompatLayer {
|
|
7
|
-
constructor(model: SchemaCompatModel) {
|
|
8
|
-
super(model);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
getSchemaTarget(): Targets | undefined {
|
|
12
|
-
return 'jsonSchema7';
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
shouldApply(): boolean {
|
|
16
|
-
// Deepseek R1 performs perfectly without this compat layer
|
|
17
|
-
return this.getModel().modelId.includes('deepseek') && !this.getModel().modelId.includes('r1');
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
processZodType(value: ZodTypeAny): ZodTypeAny {
|
|
21
|
-
if (isOptional(value)) {
|
|
22
|
-
return this.defaultZodOptionalHandler(value, ['ZodObject', 'ZodArray', 'ZodUnion', 'ZodString', 'ZodNumber']);
|
|
23
|
-
} else if (isObj(value)) {
|
|
24
|
-
return this.defaultZodObjectHandler(value);
|
|
25
|
-
} else if (isArr(value)) {
|
|
26
|
-
return this.defaultZodArrayHandler(value, ['min', 'max']);
|
|
27
|
-
} else if (isUnion(value)) {
|
|
28
|
-
return this.defaultZodUnionHandler(value);
|
|
29
|
-
} else if (isString(value)) {
|
|
30
|
-
return this.defaultZodStringHandler(value);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return value;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import type { ZodTypeAny } from 'zod';
|
|
2
|
-
import { z } from 'zod';
|
|
3
|
-
import type { Targets } from 'zod-to-json-schema';
|
|
4
|
-
import {
|
|
5
|
-
SchemaCompatLayer,
|
|
6
|
-
UNSUPPORTED_ZOD_TYPES,
|
|
7
|
-
isArr,
|
|
8
|
-
isNull,
|
|
9
|
-
isNumber,
|
|
10
|
-
isObj,
|
|
11
|
-
isOptional,
|
|
12
|
-
isString,
|
|
13
|
-
isUnion,
|
|
14
|
-
} from '../schema-compatibility';
|
|
15
|
-
import type { SchemaCompatModel } from '../schema-compatibility';
|
|
16
|
-
|
|
17
|
-
export class GoogleSchemaCompatLayer extends SchemaCompatLayer {
|
|
18
|
-
constructor(model: SchemaCompatModel) {
|
|
19
|
-
super(model);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
getSchemaTarget(): Targets | undefined {
|
|
23
|
-
return 'jsonSchema7';
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
shouldApply(): boolean {
|
|
27
|
-
return this.getModel().provider.includes('google') || this.getModel().modelId.includes('google');
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
processZodType(value: ZodTypeAny): ZodTypeAny {
|
|
31
|
-
if (isOptional(value)) {
|
|
32
|
-
return this.defaultZodOptionalHandler(value, [
|
|
33
|
-
'ZodObject',
|
|
34
|
-
'ZodArray',
|
|
35
|
-
'ZodUnion',
|
|
36
|
-
'ZodString',
|
|
37
|
-
'ZodNumber',
|
|
38
|
-
...UNSUPPORTED_ZOD_TYPES,
|
|
39
|
-
]);
|
|
40
|
-
} else if (isNull(value)) {
|
|
41
|
-
// Google models don't support null, so we need to convert it to any and then refine it to null
|
|
42
|
-
return z
|
|
43
|
-
.any()
|
|
44
|
-
.refine(v => v === null, { message: 'must be null' })
|
|
45
|
-
.describe(value._def.description || 'must be null');
|
|
46
|
-
} else if (isObj(value)) {
|
|
47
|
-
return this.defaultZodObjectHandler(value);
|
|
48
|
-
} else if (isArr(value)) {
|
|
49
|
-
return this.defaultZodArrayHandler(value, []);
|
|
50
|
-
} else if (isUnion(value)) {
|
|
51
|
-
return this.defaultZodUnionHandler(value);
|
|
52
|
-
} else if (isString(value)) {
|
|
53
|
-
// Google models support these properties but the model doesn't respect them, but it respects them when they're
|
|
54
|
-
// added to the tool description
|
|
55
|
-
return this.defaultZodStringHandler(value);
|
|
56
|
-
} else if (isNumber(value)) {
|
|
57
|
-
// Google models support these properties but the model doesn't respect them, but it respects them when they're
|
|
58
|
-
// added to the tool description
|
|
59
|
-
return this.defaultZodNumberHandler(value);
|
|
60
|
-
}
|
|
61
|
-
return this.defaultUnsupportedZodTypeHandler(value);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import type { ZodTypeAny } from 'zod';
|
|
2
|
-
import type { Targets } from 'zod-to-json-schema';
|
|
3
|
-
import { SchemaCompatLayer, isArr, isNumber, isObj, isOptional, isString, isUnion } from '../schema-compatibility';
|
|
4
|
-
import type { SchemaCompatModel } from '../schema-compatibility';
|
|
5
|
-
|
|
6
|
-
export class MetaSchemaCompatLayer extends SchemaCompatLayer {
|
|
7
|
-
constructor(model: SchemaCompatModel) {
|
|
8
|
-
super(model);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
getSchemaTarget(): Targets | undefined {
|
|
12
|
-
return 'jsonSchema7';
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
shouldApply(): boolean {
|
|
16
|
-
return this.getModel().modelId.includes('meta');
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
processZodType(value: ZodTypeAny): ZodTypeAny {
|
|
20
|
-
if (isOptional(value)) {
|
|
21
|
-
return this.defaultZodOptionalHandler(value, ['ZodObject', 'ZodArray', 'ZodUnion', 'ZodString', 'ZodNumber']);
|
|
22
|
-
} else if (isObj(value)) {
|
|
23
|
-
return this.defaultZodObjectHandler(value);
|
|
24
|
-
} else if (isArr(value)) {
|
|
25
|
-
return this.defaultZodArrayHandler(value, ['min', 'max']);
|
|
26
|
-
} else if (isUnion(value)) {
|
|
27
|
-
return this.defaultZodUnionHandler(value);
|
|
28
|
-
} else if (isNumber(value)) {
|
|
29
|
-
return this.defaultZodNumberHandler(value);
|
|
30
|
-
} else if (isString(value)) {
|
|
31
|
-
return this.defaultZodStringHandler(value);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
return value;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
import type { ZodTypeAny } from 'zod';
|
|
3
|
-
import type { Targets } from 'zod-to-json-schema';
|
|
4
|
-
import {
|
|
5
|
-
SchemaCompatLayer,
|
|
6
|
-
isArr,
|
|
7
|
-
isDate,
|
|
8
|
-
isDefault,
|
|
9
|
-
isNumber,
|
|
10
|
-
isObj,
|
|
11
|
-
isOptional,
|
|
12
|
-
isString,
|
|
13
|
-
isUnion,
|
|
14
|
-
} from '../schema-compatibility';
|
|
15
|
-
import type { SchemaCompatModel } from '../schema-compatibility';
|
|
16
|
-
|
|
17
|
-
export class OpenAIReasoningSchemaCompatLayer extends SchemaCompatLayer {
|
|
18
|
-
constructor(model: SchemaCompatModel) {
|
|
19
|
-
super(model);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
getSchemaTarget(): Targets | undefined {
|
|
23
|
-
return `openApi3`;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
isReasoningModel(): boolean {
|
|
27
|
-
// there isn't a good way to automatically detect reasoning models besides doing this.
|
|
28
|
-
// in the future when o5 is released this compat wont apply and we'll want to come back and update this class + our tests
|
|
29
|
-
return this.getModel().modelId.includes(`o3`) || this.getModel().modelId.includes(`o4`);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
shouldApply(): boolean {
|
|
33
|
-
if (
|
|
34
|
-
// (this.getModel().supportsStructuredOutputs || this.isReasoningModel()) && // <- supportsStructuredOutputs no longer exists
|
|
35
|
-
this.isReasoningModel() &&
|
|
36
|
-
(this.getModel().provider.includes(`openai`) || this.getModel().modelId.includes(`openai`))
|
|
37
|
-
) {
|
|
38
|
-
return true;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
return false;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
processZodType(value: ZodTypeAny): ZodTypeAny {
|
|
45
|
-
if (isOptional(value)) {
|
|
46
|
-
const innerZodType = this.processZodType(value._def.innerType);
|
|
47
|
-
return innerZodType.nullable();
|
|
48
|
-
} else if (isObj(value)) {
|
|
49
|
-
return this.defaultZodObjectHandler(value, { passthrough: false });
|
|
50
|
-
} else if (isArr(value)) {
|
|
51
|
-
return this.defaultZodArrayHandler(value);
|
|
52
|
-
} else if (isUnion(value)) {
|
|
53
|
-
return this.defaultZodUnionHandler(value);
|
|
54
|
-
} else if (isDefault(value)) {
|
|
55
|
-
const defaultDef = value._def;
|
|
56
|
-
const innerType = defaultDef.innerType;
|
|
57
|
-
const defaultValue = defaultDef.defaultValue();
|
|
58
|
-
const constraints: { defaultValue?: unknown } = {};
|
|
59
|
-
if (defaultValue !== undefined) {
|
|
60
|
-
constraints.defaultValue = defaultValue;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const description = this.mergeParameterDescription(value.description, constraints);
|
|
64
|
-
let result = this.processZodType(innerType);
|
|
65
|
-
if (description) {
|
|
66
|
-
result = result.describe(description);
|
|
67
|
-
}
|
|
68
|
-
return result;
|
|
69
|
-
} else if (isNumber(value)) {
|
|
70
|
-
return this.defaultZodNumberHandler(value);
|
|
71
|
-
} else if (isString(value)) {
|
|
72
|
-
return this.defaultZodStringHandler(value);
|
|
73
|
-
} else if (isDate(value)) {
|
|
74
|
-
return this.defaultZodDateHandler(value);
|
|
75
|
-
} else if (value._def.typeName === 'ZodAny') {
|
|
76
|
-
// It's bad practice in the tool to use any, it's not reasonable for models that don't support that OOTB, to cast every single possible type
|
|
77
|
-
// in the schema. Usually when it's "any" it could be a json object or a union of specific types.
|
|
78
|
-
return z
|
|
79
|
-
.string()
|
|
80
|
-
.describe(
|
|
81
|
-
(value.description ?? '') +
|
|
82
|
-
`\nArgument was an "any" type, but you (the LLM) do not support "any", so it was cast to a "string" type`,
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
return this.defaultUnsupportedZodTypeHandler(value);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import type { ZodTypeAny } from 'zod';
|
|
2
|
-
import type { Targets } from 'zod-to-json-schema';
|
|
3
|
-
import { SchemaCompatLayer, isArr, isObj, isOptional, isString, isUnion } from '../schema-compatibility';
|
|
4
|
-
import type { SchemaCompatModel, StringCheckType } from '../schema-compatibility';
|
|
5
|
-
|
|
6
|
-
export class OpenAISchemaCompatLayer extends SchemaCompatLayer {
|
|
7
|
-
constructor(model: SchemaCompatModel) {
|
|
8
|
-
super(model);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
getSchemaTarget(): Targets | undefined {
|
|
12
|
-
return `jsonSchema7`;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
shouldApply(): boolean {
|
|
16
|
-
if (
|
|
17
|
-
// !this.getModel().supportsStructuredOutputs && // <- TODO: this no longer exists, do we need it?
|
|
18
|
-
this.getModel().provider.includes(`openai`) ||
|
|
19
|
-
this.getModel().modelId.includes(`openai`)
|
|
20
|
-
) {
|
|
21
|
-
return true;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
return false;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
processZodType(value: ZodTypeAny): ZodTypeAny {
|
|
28
|
-
if (isOptional(value)) {
|
|
29
|
-
return this.defaultZodOptionalHandler(value, [
|
|
30
|
-
'ZodObject',
|
|
31
|
-
'ZodArray',
|
|
32
|
-
'ZodUnion',
|
|
33
|
-
'ZodString',
|
|
34
|
-
'ZodNever',
|
|
35
|
-
'ZodUndefined',
|
|
36
|
-
'ZodTuple',
|
|
37
|
-
]);
|
|
38
|
-
} else if (isObj(value)) {
|
|
39
|
-
return this.defaultZodObjectHandler(value);
|
|
40
|
-
} else if (isUnion(value)) {
|
|
41
|
-
return this.defaultZodUnionHandler(value);
|
|
42
|
-
} else if (isArr(value)) {
|
|
43
|
-
return this.defaultZodArrayHandler(value);
|
|
44
|
-
} else if (isString(value)) {
|
|
45
|
-
const model = this.getModel();
|
|
46
|
-
const checks: StringCheckType[] = ['emoji'];
|
|
47
|
-
|
|
48
|
-
if (model.modelId.includes('gpt-4o-mini')) {
|
|
49
|
-
checks.push('regex');
|
|
50
|
-
}
|
|
51
|
-
return this.defaultZodStringHandler(value, checks);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return this.defaultUnsupportedZodTypeHandler(value, ['ZodNever', 'ZodUndefined', 'ZodTuple']);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
@@ -1,312 +0,0 @@
|
|
|
1
|
-
import { MockLanguageModelV2 } from 'ai/test';
|
|
2
|
-
import { describe, it, expect } from 'vitest';
|
|
3
|
-
import { z } from 'zod';
|
|
4
|
-
import {
|
|
5
|
-
AnthropicSchemaCompatLayer,
|
|
6
|
-
OpenAISchemaCompatLayer,
|
|
7
|
-
OpenAIReasoningSchemaCompatLayer,
|
|
8
|
-
GoogleSchemaCompatLayer,
|
|
9
|
-
DeepSeekSchemaCompatLayer,
|
|
10
|
-
MetaSchemaCompatLayer,
|
|
11
|
-
} from './index';
|
|
12
|
-
|
|
13
|
-
describe('Provider Compatibility Classes', () => {
|
|
14
|
-
const mockModels = {
|
|
15
|
-
anthropic: new MockLanguageModelV2({
|
|
16
|
-
modelId: 'claude-3-sonnet-20240229',
|
|
17
|
-
doGenerate: async () => ({ response: { id: 'test' } }) as any,
|
|
18
|
-
}),
|
|
19
|
-
openai: new MockLanguageModelV2({
|
|
20
|
-
modelId: 'openai/gpt-4',
|
|
21
|
-
doGenerate: async () => ({ response: { id: 'test' } }) as any,
|
|
22
|
-
}),
|
|
23
|
-
openaiReasoning: new MockLanguageModelV2({
|
|
24
|
-
modelId: 'openai/o3-mini',
|
|
25
|
-
doGenerate: async () => ({ response: { id: 'test' } }) as any,
|
|
26
|
-
}),
|
|
27
|
-
google: new MockLanguageModelV2({
|
|
28
|
-
modelId: 'gemini-pro',
|
|
29
|
-
doGenerate: async () => ({ response: { id: 'test' } }) as any,
|
|
30
|
-
}),
|
|
31
|
-
deepseek: new MockLanguageModelV2({
|
|
32
|
-
modelId: 'deepseek-chat',
|
|
33
|
-
doGenerate: async () => ({ response: { id: 'test' } }) as any,
|
|
34
|
-
}),
|
|
35
|
-
meta: new MockLanguageModelV2({
|
|
36
|
-
modelId: 'llama-3.1-405b-instruct',
|
|
37
|
-
doGenerate: async () => ({ response: { id: 'test' } }) as any,
|
|
38
|
-
}),
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
describe('AnthropicSchemaCompatLayer', () => {
|
|
42
|
-
it('should apply for Anthropic models', () => {
|
|
43
|
-
const compat = new AnthropicSchemaCompatLayer(mockModels.anthropic);
|
|
44
|
-
expect(compat.shouldApply()).toBe(true);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it('should not apply for non-Anthropic models', () => {
|
|
48
|
-
const compat = new AnthropicSchemaCompatLayer(mockModels.openai);
|
|
49
|
-
expect(compat.shouldApply()).toBe(false);
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
it('should return correct schema target', () => {
|
|
53
|
-
const compat = new AnthropicSchemaCompatLayer(mockModels.anthropic);
|
|
54
|
-
expect(compat.getSchemaTarget()).toBe('jsonSchema7');
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
it('should process schemas correctly', () => {
|
|
58
|
-
const compat = new AnthropicSchemaCompatLayer(mockModels.anthropic);
|
|
59
|
-
const schema = z.object({
|
|
60
|
-
text: z.string().min(1).max(100),
|
|
61
|
-
count: z.number().min(1),
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
const result = compat.processToAISDKSchema(schema);
|
|
65
|
-
|
|
66
|
-
expect(result).toHaveProperty('jsonSchema');
|
|
67
|
-
expect(result).toHaveProperty('validate');
|
|
68
|
-
|
|
69
|
-
const validData = {
|
|
70
|
-
text: 'Hello, world!',
|
|
71
|
-
count: 10,
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
const validationResult = result.validate!(validData);
|
|
75
|
-
expect(typeof validationResult).toBe('object');
|
|
76
|
-
expect(validationResult).toHaveProperty('success');
|
|
77
|
-
});
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
describe('OpenAISchemaCompatLayer', () => {
|
|
81
|
-
it('should apply for OpenAI models without structured outputs support', () => {
|
|
82
|
-
const compat = new OpenAISchemaCompatLayer(mockModels.openai);
|
|
83
|
-
expect(compat.shouldApply()).toBe(true);
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
it('should return correct schema target', () => {
|
|
87
|
-
const compat = new OpenAISchemaCompatLayer(mockModels.openai);
|
|
88
|
-
expect(compat.getSchemaTarget()).toBe('jsonSchema7');
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
it('should process complex schemas', () => {
|
|
92
|
-
const compat = new OpenAISchemaCompatLayer(mockModels.openai);
|
|
93
|
-
const schema = z.object({
|
|
94
|
-
user: z.object({
|
|
95
|
-
name: z.string().email(),
|
|
96
|
-
preferences: z.array(z.enum(['dark', 'light'])),
|
|
97
|
-
}),
|
|
98
|
-
settings: z.record(z.boolean()),
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
const result = compat.processToAISDKSchema(schema);
|
|
102
|
-
|
|
103
|
-
const validData = {
|
|
104
|
-
user: {
|
|
105
|
-
name: 'John Doe',
|
|
106
|
-
preferences: ['dark'],
|
|
107
|
-
},
|
|
108
|
-
settings: {
|
|
109
|
-
public: true,
|
|
110
|
-
featured: false,
|
|
111
|
-
},
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
expect(result).toHaveProperty('jsonSchema');
|
|
115
|
-
expect(result).toHaveProperty('validate');
|
|
116
|
-
|
|
117
|
-
const validationResult = result.validate!(validData);
|
|
118
|
-
expect(typeof validationResult).toBe('object');
|
|
119
|
-
expect(validationResult).toHaveProperty('success');
|
|
120
|
-
});
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
describe('OpenAIReasoningSchemaCompatLayer', () => {
|
|
124
|
-
it('should have consistent behavior', () => {
|
|
125
|
-
const compat = new OpenAIReasoningSchemaCompatLayer(mockModels.openaiReasoning);
|
|
126
|
-
expect(compat.shouldApply()).toBe(true);
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
it('should return correct schema target', () => {
|
|
130
|
-
const compat = new OpenAIReasoningSchemaCompatLayer(mockModels.openaiReasoning);
|
|
131
|
-
expect(compat.getSchemaTarget()).toBe('openApi3');
|
|
132
|
-
});
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
describe('GoogleSchemaCompatLayer', () => {
|
|
136
|
-
it('should have consistent behavior', () => {
|
|
137
|
-
const compat = new GoogleSchemaCompatLayer(mockModels.google);
|
|
138
|
-
expect(typeof compat.shouldApply()).toBe('boolean');
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
it('should return correct schema target', () => {
|
|
142
|
-
const compat = new GoogleSchemaCompatLayer(mockModels.google);
|
|
143
|
-
expect(compat.getSchemaTarget()).toBe('jsonSchema7');
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
it('should handle date types correctly', () => {
|
|
147
|
-
const compat = new GoogleSchemaCompatLayer(mockModels.google);
|
|
148
|
-
const schema = z.object({
|
|
149
|
-
startDate: z.date(),
|
|
150
|
-
endDate: z.date().optional(),
|
|
151
|
-
title: z.string(),
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
const result = compat.processToAISDKSchema(schema);
|
|
155
|
-
|
|
156
|
-
expect(result).toHaveProperty('jsonSchema');
|
|
157
|
-
expect(result).toHaveProperty('validate');
|
|
158
|
-
|
|
159
|
-
const validData = {
|
|
160
|
-
startDate: new Date(),
|
|
161
|
-
title: 'Hello, world!',
|
|
162
|
-
};
|
|
163
|
-
|
|
164
|
-
const validationResult = result.validate!(validData);
|
|
165
|
-
expect(typeof validationResult).toBe('object');
|
|
166
|
-
expect(validationResult).toHaveProperty('success');
|
|
167
|
-
});
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
describe('DeepSeekSchemaCompatLayer', () => {
|
|
171
|
-
it('should apply for DeepSeek models', () => {
|
|
172
|
-
const compat = new DeepSeekSchemaCompatLayer(mockModels.deepseek);
|
|
173
|
-
expect(compat.shouldApply()).toBe(true);
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
it('should not apply for non-DeepSeek models', () => {
|
|
177
|
-
const compat = new DeepSeekSchemaCompatLayer(mockModels.openai);
|
|
178
|
-
expect(compat.shouldApply()).toBe(false);
|
|
179
|
-
});
|
|
180
|
-
|
|
181
|
-
it('should return correct schema target', () => {
|
|
182
|
-
const compat = new DeepSeekSchemaCompatLayer(mockModels.deepseek);
|
|
183
|
-
expect(compat.getSchemaTarget()).toBe('jsonSchema7');
|
|
184
|
-
});
|
|
185
|
-
|
|
186
|
-
it('should handle string constraints', () => {
|
|
187
|
-
const compat = new DeepSeekSchemaCompatLayer(mockModels.deepseek);
|
|
188
|
-
const schema = z.object({
|
|
189
|
-
email: z.string().email(),
|
|
190
|
-
url: z.string().url(),
|
|
191
|
-
uuid: z.string().uuid(),
|
|
192
|
-
text: z.string().min(10).max(1000),
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
const result = compat.processToAISDKSchema(schema);
|
|
196
|
-
|
|
197
|
-
expect(result).toHaveProperty('jsonSchema');
|
|
198
|
-
expect(result).toHaveProperty('validate');
|
|
199
|
-
|
|
200
|
-
const validData = {
|
|
201
|
-
email: 'john@example.com',
|
|
202
|
-
url: 'https://example.com',
|
|
203
|
-
uuid: '123e4567-e89b-12d3-a456-426614174000',
|
|
204
|
-
text: 'Hello, world!',
|
|
205
|
-
};
|
|
206
|
-
|
|
207
|
-
const validationResult = result.validate!(validData);
|
|
208
|
-
expect(typeof validationResult).toBe('object');
|
|
209
|
-
expect(validationResult).toHaveProperty('success');
|
|
210
|
-
});
|
|
211
|
-
});
|
|
212
|
-
|
|
213
|
-
describe('MetaSchemaCompatLayer', () => {
|
|
214
|
-
it('should have consistent behavior', () => {
|
|
215
|
-
const compat = new MetaSchemaCompatLayer(mockModels.meta);
|
|
216
|
-
expect(typeof compat.shouldApply()).toBe('boolean');
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
it('should return correct schema target', () => {
|
|
220
|
-
const compat = new MetaSchemaCompatLayer(mockModels.meta);
|
|
221
|
-
expect(compat.getSchemaTarget()).toBe('jsonSchema7');
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
it('should handle array and union types', () => {
|
|
225
|
-
const compat = new MetaSchemaCompatLayer(mockModels.meta);
|
|
226
|
-
const schema = z.object({
|
|
227
|
-
tags: z.array(z.string()).min(1).max(10),
|
|
228
|
-
status: z.union([z.literal('active'), z.literal('inactive')]),
|
|
229
|
-
priority: z.enum(['low', 'medium', 'high']),
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
const result = compat.processToAISDKSchema(schema);
|
|
233
|
-
|
|
234
|
-
expect(result).toHaveProperty('jsonSchema');
|
|
235
|
-
expect(result).toHaveProperty('validate');
|
|
236
|
-
|
|
237
|
-
const validData = {
|
|
238
|
-
tags: ['tag1'],
|
|
239
|
-
status: 'active',
|
|
240
|
-
priority: 'high',
|
|
241
|
-
};
|
|
242
|
-
|
|
243
|
-
const validationResult = result.validate!(validData);
|
|
244
|
-
expect(typeof validationResult).toBe('object');
|
|
245
|
-
expect(validationResult).toHaveProperty('success');
|
|
246
|
-
});
|
|
247
|
-
});
|
|
248
|
-
|
|
249
|
-
describe('Integration tests', () => {
|
|
250
|
-
it('should handle schema processing across providers', () => {
|
|
251
|
-
const complexSchema = z.object({
|
|
252
|
-
user: z.object({
|
|
253
|
-
name: z.string().min(1).max(100),
|
|
254
|
-
email: z.string().email(),
|
|
255
|
-
age: z.number().min(0).max(120).optional(),
|
|
256
|
-
}),
|
|
257
|
-
preferences: z.object({
|
|
258
|
-
theme: z.enum(['light', 'dark']),
|
|
259
|
-
notifications: z.boolean(),
|
|
260
|
-
language: z.string().regex(/^[a-z]{2}$/),
|
|
261
|
-
}),
|
|
262
|
-
tags: z.array(z.string()).min(1).max(5),
|
|
263
|
-
metadata: z.record(z.union([z.string(), z.number(), z.boolean()])),
|
|
264
|
-
createdAt: z.date(),
|
|
265
|
-
settings: z
|
|
266
|
-
.object({
|
|
267
|
-
public: z.boolean(),
|
|
268
|
-
featured: z.boolean().optional(),
|
|
269
|
-
})
|
|
270
|
-
.optional(),
|
|
271
|
-
});
|
|
272
|
-
|
|
273
|
-
const providers = [
|
|
274
|
-
new AnthropicSchemaCompatLayer(mockModels.anthropic),
|
|
275
|
-
new OpenAISchemaCompatLayer(mockModels.openai),
|
|
276
|
-
new OpenAIReasoningSchemaCompatLayer(mockModels.openaiReasoning),
|
|
277
|
-
new GoogleSchemaCompatLayer(mockModels.google),
|
|
278
|
-
new DeepSeekSchemaCompatLayer(mockModels.deepseek),
|
|
279
|
-
new MetaSchemaCompatLayer(mockModels.meta),
|
|
280
|
-
];
|
|
281
|
-
|
|
282
|
-
providers.forEach(provider => {
|
|
283
|
-
const result = provider.processToAISDKSchema(complexSchema);
|
|
284
|
-
|
|
285
|
-
expect(result).toHaveProperty('jsonSchema');
|
|
286
|
-
expect(result).toHaveProperty('validate');
|
|
287
|
-
expect(typeof result.validate).toBe('function');
|
|
288
|
-
|
|
289
|
-
const validData = {
|
|
290
|
-
user: {
|
|
291
|
-
name: 'John Doe',
|
|
292
|
-
email: 'john@example.com',
|
|
293
|
-
},
|
|
294
|
-
preferences: {
|
|
295
|
-
theme: 'dark' as const,
|
|
296
|
-
notifications: true,
|
|
297
|
-
language: 'en',
|
|
298
|
-
},
|
|
299
|
-
tags: ['tag1'],
|
|
300
|
-
metadata: {
|
|
301
|
-
key1: 'value1',
|
|
302
|
-
},
|
|
303
|
-
createdAt: new Date(),
|
|
304
|
-
};
|
|
305
|
-
|
|
306
|
-
const validationResult = result.validate!(validData);
|
|
307
|
-
expect(typeof validationResult).toBe('object');
|
|
308
|
-
expect(validationResult).toHaveProperty('success');
|
|
309
|
-
});
|
|
310
|
-
});
|
|
311
|
-
});
|
|
312
|
-
});
|