@layer-ai/core 2.0.11 → 2.0.13

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.
Files changed (23) hide show
  1. package/dist/routes/tests/test-chat-structured-output.d.ts +7 -0
  2. package/dist/routes/tests/test-chat-structured-output.d.ts.map +1 -0
  3. package/dist/routes/tests/test-chat-structured-output.js +320 -0
  4. package/dist/routes/v1/gates.d.ts.map +1 -1
  5. package/dist/routes/v1/gates.js +11 -2
  6. package/dist/routes/v3/chat.d.ts +2 -0
  7. package/dist/routes/v3/chat.d.ts.map +1 -1
  8. package/dist/routes/v3/chat.js +8 -9
  9. package/dist/services/providers/tests/test-json-response-format-anthropic.d.ts +7 -0
  10. package/dist/services/providers/tests/test-json-response-format-anthropic.d.ts.map +1 -0
  11. package/dist/services/providers/tests/test-json-response-format-anthropic.js +179 -0
  12. package/dist/services/providers/tests/test-json-response-format-google.d.ts +7 -0
  13. package/dist/services/providers/tests/test-json-response-format-google.d.ts.map +1 -0
  14. package/dist/services/providers/tests/test-json-response-format-google.js +179 -0
  15. package/dist/services/providers/tests/test-json-response-format-mistral.d.ts +7 -0
  16. package/dist/services/providers/tests/test-json-response-format-mistral.d.ts.map +1 -0
  17. package/dist/services/providers/tests/test-json-response-format-mistral.js +179 -0
  18. package/dist/services/providers/tests/test-json-response-format-openai.d.ts +7 -0
  19. package/dist/services/providers/tests/test-json-response-format-openai.d.ts.map +1 -0
  20. package/dist/services/providers/tests/test-json-response-format-openai.js +175 -0
  21. package/dist/services/providers/tests/test-openai-adapter.js +76 -0
  22. package/package.json +10 -10
  23. package/LICENSE +0 -21
@@ -0,0 +1,179 @@
1
+ #!/usr/bin/env npx tsx
2
+ /**
3
+ * Focused tests for JSON response format structure - Google Provider
4
+ * Tests structured output with prompt engineering (beta mode)
5
+ */
6
+ import { GoogleAdapter } from '../google-adapter.js';
7
+ const adapter = new GoogleAdapter();
8
+ console.log('='.repeat(80));
9
+ console.log('STRUCTURED OUTPUT - GOOGLE ADAPTER TESTS (BETA MODE)');
10
+ console.log('='.repeat(80));
11
+ console.log('');
12
+ // Helper to extract JSON from markdown or plain text
13
+ function extractJSON(content) {
14
+ const codeBlockMatch = content.match(/```(?:json)?\s*\n?([\s\S]*?)\n?```/);
15
+ if (codeBlockMatch) {
16
+ return JSON.parse(codeBlockMatch[1].trim());
17
+ }
18
+ return JSON.parse(content.trim());
19
+ }
20
+ async function testJsonObjectModeBeta() {
21
+ console.log('Test 1: JSON Object Mode (Beta - Prompt Engineering)');
22
+ console.log('-'.repeat(80));
23
+ const request = {
24
+ gateId: 'test-gate',
25
+ model: 'gemini-2.0-flash',
26
+ type: 'chat',
27
+ data: {
28
+ messages: [
29
+ { role: 'user', content: 'Generate a user profile with name, age, and city fields' }
30
+ ],
31
+ systemPrompt: 'You MUST respond with ONLY a valid JSON object. Do not include ANY text before or after the JSON. Do not wrap it in markdown code blocks. Do not add explanations. ONLY output the raw JSON object.',
32
+ maxTokens: 150,
33
+ }
34
+ };
35
+ try {
36
+ const response = await adapter.call(request);
37
+ console.log('✓ Request completed');
38
+ console.log('');
39
+ console.log('Raw response content:');
40
+ console.log(response.content);
41
+ console.log('');
42
+ // Try to parse as JSON (with markdown extraction fallback)
43
+ const parsed = extractJSON(response.content || '');
44
+ console.log('✓ Successfully parsed as JSON');
45
+ console.log('');
46
+ console.log('Parsed structure:');
47
+ console.log(JSON.stringify(parsed, null, 2));
48
+ console.log('');
49
+ console.log('✅ JSON Object Mode (Beta): PASSED');
50
+ console.log('');
51
+ return true;
52
+ }
53
+ catch (error) {
54
+ console.log('❌ JSON Object Mode (Beta): FAILED');
55
+ console.log('Error:', error.message);
56
+ console.log('');
57
+ return false;
58
+ }
59
+ }
60
+ async function testJsonSchemaModeBeta() {
61
+ console.log('Test 2: JSON Schema Mode (Beta - Prompt Engineering)');
62
+ console.log('-'.repeat(80));
63
+ const schema = {
64
+ type: 'object',
65
+ properties: {
66
+ name: { type: 'string' },
67
+ age: { type: 'number' },
68
+ city: { type: 'string' },
69
+ },
70
+ required: ['name', 'age', 'city'],
71
+ additionalProperties: false,
72
+ };
73
+ const systemPrompt = `You MUST respond with ONLY a valid JSON object matching this schema. Do not include ANY text before or after the JSON. Do not wrap it in markdown code blocks. Do not add explanations. ONLY output the raw JSON object.
74
+
75
+ Required JSON Schema:
76
+ ${JSON.stringify(schema, null, 2)}`;
77
+ const request = {
78
+ gateId: 'test-gate',
79
+ model: 'gemini-2.0-flash',
80
+ type: 'chat',
81
+ data: {
82
+ messages: [
83
+ { role: 'user', content: 'Create data for: name=Alice Johnson, age=28, city=Tokyo' }
84
+ ],
85
+ systemPrompt,
86
+ maxTokens: 150,
87
+ }
88
+ };
89
+ try {
90
+ const response = await adapter.call(request);
91
+ console.log('✓ Request completed');
92
+ console.log('');
93
+ console.log('Raw response content:');
94
+ console.log(response.content);
95
+ console.log('');
96
+ // Try to parse as JSON (with markdown extraction fallback)
97
+ const parsed = extractJSON(response.content || '');
98
+ console.log('✓ Successfully parsed as JSON');
99
+ console.log('');
100
+ console.log('Parsed structure:');
101
+ console.log(JSON.stringify(parsed, null, 2));
102
+ console.log('');
103
+ // Validate schema fields
104
+ const hasRequiredFields = parsed.name && typeof parsed.age === 'number' && parsed.city;
105
+ if (!hasRequiredFields) {
106
+ throw new Error('Missing required fields from schema');
107
+ }
108
+ console.log('✓ Schema validation passed');
109
+ console.log('');
110
+ console.log('✅ JSON Schema Mode (Beta): PASSED');
111
+ console.log('');
112
+ return true;
113
+ }
114
+ catch (error) {
115
+ console.log('❌ JSON Schema Mode (Beta): FAILED');
116
+ console.log('Error:', error.message);
117
+ console.log('');
118
+ return false;
119
+ }
120
+ }
121
+ async function testTextMode() {
122
+ console.log('Test 3: Text Mode (Control Test)');
123
+ console.log('-'.repeat(80));
124
+ const request = {
125
+ gateId: 'test-gate',
126
+ model: 'gemini-2.0-flash',
127
+ type: 'chat',
128
+ data: {
129
+ messages: [
130
+ { role: 'user', content: 'Say hello' }
131
+ ],
132
+ maxTokens: 50,
133
+ }
134
+ };
135
+ try {
136
+ const response = await adapter.call(request);
137
+ console.log('✓ Request completed');
138
+ console.log('');
139
+ console.log('Response content:');
140
+ console.log(response.content);
141
+ console.log('');
142
+ console.log('✅ Text Mode: PASSED');
143
+ console.log('');
144
+ return true;
145
+ }
146
+ catch (error) {
147
+ console.log('❌ Text Mode: FAILED');
148
+ console.log('Error:', error.message);
149
+ console.log('');
150
+ return false;
151
+ }
152
+ }
153
+ async function runTests() {
154
+ const results = [];
155
+ results.push(await testJsonObjectModeBeta());
156
+ results.push(await testJsonSchemaModeBeta());
157
+ results.push(await testTextMode());
158
+ console.log('='.repeat(80));
159
+ console.log('RESULTS SUMMARY');
160
+ console.log('='.repeat(80));
161
+ console.log('');
162
+ const passed = results.filter(r => r).length;
163
+ const failed = results.filter(r => !r).length;
164
+ console.log(`Total Tests: ${results.length}`);
165
+ console.log(`Passed: ${passed}`);
166
+ console.log(`Failed: ${failed}`);
167
+ console.log('');
168
+ if (failed > 0) {
169
+ console.log('❌ Some tests failed');
170
+ process.exit(1);
171
+ }
172
+ else {
173
+ console.log('✅ All tests passed!');
174
+ }
175
+ }
176
+ runTests().catch(error => {
177
+ console.error('Test suite failed:', error);
178
+ process.exit(1);
179
+ });
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env npx tsx
2
+ /**
3
+ * Focused tests for JSON response format structure - Mistral Provider
4
+ * Tests structured output with prompt engineering (beta mode)
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=test-json-response-format-mistral.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-json-response-format-mistral.d.ts","sourceRoot":"","sources":["../../../../src/services/providers/tests/test-json-response-format-mistral.ts"],"names":[],"mappings":";AACA;;;GAGG"}
@@ -0,0 +1,179 @@
1
+ #!/usr/bin/env npx tsx
2
+ /**
3
+ * Focused tests for JSON response format structure - Mistral Provider
4
+ * Tests structured output with prompt engineering (beta mode)
5
+ */
6
+ import { MistralAdapter } from '../mistral-adapter.js';
7
+ const adapter = new MistralAdapter();
8
+ console.log('='.repeat(80));
9
+ console.log('STRUCTURED OUTPUT - MISTRAL ADAPTER TESTS (BETA MODE)');
10
+ console.log('='.repeat(80));
11
+ console.log('');
12
+ // Helper to extract JSON from markdown or plain text
13
+ function extractJSON(content) {
14
+ const codeBlockMatch = content.match(/```(?:json)?\s*\n?([\s\S]*?)\n?```/);
15
+ if (codeBlockMatch) {
16
+ return JSON.parse(codeBlockMatch[1].trim());
17
+ }
18
+ return JSON.parse(content.trim());
19
+ }
20
+ async function testJsonObjectModeBeta() {
21
+ console.log('Test 1: JSON Object Mode (Beta - Prompt Engineering)');
22
+ console.log('-'.repeat(80));
23
+ const request = {
24
+ gateId: 'test-gate',
25
+ model: 'mistral-medium-2508',
26
+ type: 'chat',
27
+ data: {
28
+ messages: [
29
+ { role: 'user', content: 'Generate a user profile with name, age, and city fields' }
30
+ ],
31
+ systemPrompt: 'You MUST respond with ONLY a valid JSON object. Do not include ANY text before or after the JSON. Do not wrap it in markdown code blocks. Do not add explanations. ONLY output the raw JSON object.',
32
+ maxTokens: 150,
33
+ }
34
+ };
35
+ try {
36
+ const response = await adapter.call(request);
37
+ console.log('✓ Request completed');
38
+ console.log('');
39
+ console.log('Raw response content:');
40
+ console.log(response.content);
41
+ console.log('');
42
+ // Try to parse as JSON (with markdown extraction fallback)
43
+ const parsed = extractJSON(response.content || '');
44
+ console.log('✓ Successfully parsed as JSON');
45
+ console.log('');
46
+ console.log('Parsed structure:');
47
+ console.log(JSON.stringify(parsed, null, 2));
48
+ console.log('');
49
+ console.log('✅ JSON Object Mode (Beta): PASSED');
50
+ console.log('');
51
+ return true;
52
+ }
53
+ catch (error) {
54
+ console.log('❌ JSON Object Mode (Beta): FAILED');
55
+ console.log('Error:', error.message);
56
+ console.log('');
57
+ return false;
58
+ }
59
+ }
60
+ async function testJsonSchemaModeBeta() {
61
+ console.log('Test 2: JSON Schema Mode (Beta - Prompt Engineering)');
62
+ console.log('-'.repeat(80));
63
+ const schema = {
64
+ type: 'object',
65
+ properties: {
66
+ name: { type: 'string' },
67
+ age: { type: 'number' },
68
+ city: { type: 'string' },
69
+ },
70
+ required: ['name', 'age', 'city'],
71
+ additionalProperties: false,
72
+ };
73
+ const systemPrompt = `You MUST respond with ONLY a valid JSON object matching this schema. Do not include ANY text before or after the JSON. Do not wrap it in markdown code blocks. Do not add explanations. ONLY output the raw JSON object.
74
+
75
+ Required JSON Schema:
76
+ ${JSON.stringify(schema, null, 2)}`;
77
+ const request = {
78
+ gateId: 'test-gate',
79
+ model: 'mistral-medium-2508',
80
+ type: 'chat',
81
+ data: {
82
+ messages: [
83
+ { role: 'user', content: 'Create data for: name=Bob Williams, age=35, city=Paris' }
84
+ ],
85
+ systemPrompt,
86
+ maxTokens: 150,
87
+ }
88
+ };
89
+ try {
90
+ const response = await adapter.call(request);
91
+ console.log('✓ Request completed');
92
+ console.log('');
93
+ console.log('Raw response content:');
94
+ console.log(response.content);
95
+ console.log('');
96
+ // Try to parse as JSON (with markdown extraction fallback)
97
+ const parsed = extractJSON(response.content || '');
98
+ console.log('✓ Successfully parsed as JSON');
99
+ console.log('');
100
+ console.log('Parsed structure:');
101
+ console.log(JSON.stringify(parsed, null, 2));
102
+ console.log('');
103
+ // Validate schema fields
104
+ const hasRequiredFields = parsed.name && typeof parsed.age === 'number' && parsed.city;
105
+ if (!hasRequiredFields) {
106
+ throw new Error('Missing required fields from schema');
107
+ }
108
+ console.log('✓ Schema validation passed');
109
+ console.log('');
110
+ console.log('✅ JSON Schema Mode (Beta): PASSED');
111
+ console.log('');
112
+ return true;
113
+ }
114
+ catch (error) {
115
+ console.log('❌ JSON Schema Mode (Beta): FAILED');
116
+ console.log('Error:', error.message);
117
+ console.log('');
118
+ return false;
119
+ }
120
+ }
121
+ async function testTextMode() {
122
+ console.log('Test 3: Text Mode (Control Test)');
123
+ console.log('-'.repeat(80));
124
+ const request = {
125
+ gateId: 'test-gate',
126
+ model: 'mistral-medium-2508',
127
+ type: 'chat',
128
+ data: {
129
+ messages: [
130
+ { role: 'user', content: 'Say hello' }
131
+ ],
132
+ maxTokens: 50,
133
+ }
134
+ };
135
+ try {
136
+ const response = await adapter.call(request);
137
+ console.log('✓ Request completed');
138
+ console.log('');
139
+ console.log('Response content:');
140
+ console.log(response.content);
141
+ console.log('');
142
+ console.log('✅ Text Mode: PASSED');
143
+ console.log('');
144
+ return true;
145
+ }
146
+ catch (error) {
147
+ console.log('❌ Text Mode: FAILED');
148
+ console.log('Error:', error.message);
149
+ console.log('');
150
+ return false;
151
+ }
152
+ }
153
+ async function runTests() {
154
+ const results = [];
155
+ results.push(await testJsonObjectModeBeta());
156
+ results.push(await testJsonSchemaModeBeta());
157
+ results.push(await testTextMode());
158
+ console.log('='.repeat(80));
159
+ console.log('RESULTS SUMMARY');
160
+ console.log('='.repeat(80));
161
+ console.log('');
162
+ const passed = results.filter(r => r).length;
163
+ const failed = results.filter(r => !r).length;
164
+ console.log(`Total Tests: ${results.length}`);
165
+ console.log(`Passed: ${passed}`);
166
+ console.log(`Failed: ${failed}`);
167
+ console.log('');
168
+ if (failed > 0) {
169
+ console.log('❌ Some tests failed');
170
+ process.exit(1);
171
+ }
172
+ else {
173
+ console.log('✅ All tests passed!');
174
+ }
175
+ }
176
+ runTests().catch(error => {
177
+ console.error('Test suite failed:', error);
178
+ process.exit(1);
179
+ });
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env npx tsx
2
+ /**
3
+ * Focused tests for JSON response format structure
4
+ * Tests ONLY the structured output feature at the adapter level
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=test-json-response-format-openai.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-json-response-format-openai.d.ts","sourceRoot":"","sources":["../../../../src/services/providers/tests/test-json-response-format-openai.ts"],"names":[],"mappings":";AACA;;;GAGG"}
@@ -0,0 +1,175 @@
1
+ #!/usr/bin/env npx tsx
2
+ /**
3
+ * Focused tests for JSON response format structure
4
+ * Tests ONLY the structured output feature at the adapter level
5
+ */
6
+ import { OpenAIAdapter } from '../openai-adapter.js';
7
+ const adapter = new OpenAIAdapter();
8
+ console.log('='.repeat(80));
9
+ console.log('STRUCTURED OUTPUT - ADAPTER LEVEL TESTS');
10
+ console.log('='.repeat(80));
11
+ console.log('');
12
+ async function testJsonObjectMode() {
13
+ console.log('Test 1: JSON Object Mode');
14
+ console.log('-'.repeat(80));
15
+ const request = {
16
+ gateId: 'test-gate',
17
+ model: 'gpt-4o-mini',
18
+ type: 'chat',
19
+ data: {
20
+ messages: [
21
+ { role: 'user', content: 'Generate a JSON user profile with name, age, and city fields' }
22
+ ],
23
+ responseFormat: 'json_object',
24
+ maxTokens: 100,
25
+ }
26
+ };
27
+ try {
28
+ const response = await adapter.call(request);
29
+ console.log('✓ Request completed');
30
+ console.log('');
31
+ console.log('Raw response content:');
32
+ console.log(response.content);
33
+ console.log('');
34
+ // Try to parse as JSON
35
+ const parsed = JSON.parse(response.content || '');
36
+ console.log('✓ Successfully parsed as JSON');
37
+ console.log('');
38
+ console.log('Parsed structure:');
39
+ console.log(JSON.stringify(parsed, null, 2));
40
+ console.log('');
41
+ console.log('✅ JSON Object Mode: PASSED');
42
+ console.log('');
43
+ return true;
44
+ }
45
+ catch (error) {
46
+ console.log('❌ JSON Object Mode: FAILED');
47
+ console.log('Error:', error.message);
48
+ console.log('');
49
+ return false;
50
+ }
51
+ }
52
+ async function testJsonSchemaMode() {
53
+ console.log('Test 2: JSON Schema Mode');
54
+ console.log('-'.repeat(80));
55
+ const schema = {
56
+ type: 'json_schema',
57
+ json_schema: {
58
+ name: 'user_profile',
59
+ strict: true,
60
+ schema: {
61
+ type: 'object',
62
+ properties: {
63
+ name: { type: 'string' },
64
+ age: { type: 'number' },
65
+ city: { type: 'string' },
66
+ },
67
+ required: ['name', 'age', 'city'],
68
+ additionalProperties: false,
69
+ },
70
+ },
71
+ };
72
+ const request = {
73
+ gateId: 'test-gate',
74
+ model: 'gpt-4o',
75
+ type: 'chat',
76
+ data: {
77
+ messages: [
78
+ { role: 'user', content: 'Create a profile for John Doe, age 30, from New York' }
79
+ ],
80
+ responseFormat: schema,
81
+ maxTokens: 100,
82
+ }
83
+ };
84
+ try {
85
+ const response = await adapter.call(request);
86
+ console.log('✓ Request completed');
87
+ console.log('');
88
+ console.log('Raw response content:');
89
+ console.log(response.content);
90
+ console.log('');
91
+ // Try to parse as JSON
92
+ const parsed = JSON.parse(response.content || '');
93
+ console.log('✓ Successfully parsed as JSON');
94
+ console.log('');
95
+ console.log('Parsed structure:');
96
+ console.log(JSON.stringify(parsed, null, 2));
97
+ console.log('');
98
+ // Validate schema fields
99
+ const hasRequiredFields = parsed.name && typeof parsed.age === 'number' && parsed.city;
100
+ if (!hasRequiredFields) {
101
+ throw new Error('Missing required fields from schema');
102
+ }
103
+ console.log('✓ Schema validation passed');
104
+ console.log('');
105
+ console.log('✅ JSON Schema Mode: PASSED');
106
+ console.log('');
107
+ return true;
108
+ }
109
+ catch (error) {
110
+ console.log('❌ JSON Schema Mode: FAILED');
111
+ console.log('Error:', error.message);
112
+ console.log('');
113
+ return false;
114
+ }
115
+ }
116
+ async function testTextMode() {
117
+ console.log('Test 3: Text Mode (Control Test)');
118
+ console.log('-'.repeat(80));
119
+ const request = {
120
+ gateId: 'test-gate',
121
+ model: 'gpt-4o-mini',
122
+ type: 'chat',
123
+ data: {
124
+ messages: [
125
+ { role: 'user', content: 'Say hello' }
126
+ ],
127
+ responseFormat: 'text',
128
+ maxTokens: 50,
129
+ }
130
+ };
131
+ try {
132
+ const response = await adapter.call(request);
133
+ console.log('✓ Request completed');
134
+ console.log('');
135
+ console.log('Response content:');
136
+ console.log(response.content);
137
+ console.log('');
138
+ console.log('✅ Text Mode: PASSED');
139
+ console.log('');
140
+ return true;
141
+ }
142
+ catch (error) {
143
+ console.log('❌ Text Mode: FAILED');
144
+ console.log('Error:', error.message);
145
+ console.log('');
146
+ return false;
147
+ }
148
+ }
149
+ async function runTests() {
150
+ const results = [];
151
+ results.push(await testJsonObjectMode());
152
+ results.push(await testJsonSchemaMode());
153
+ results.push(await testTextMode());
154
+ console.log('='.repeat(80));
155
+ console.log('RESULTS SUMMARY');
156
+ console.log('='.repeat(80));
157
+ console.log('');
158
+ const passed = results.filter(r => r).length;
159
+ const failed = results.filter(r => !r).length;
160
+ console.log(`Total Tests: ${results.length}`);
161
+ console.log(`Passed: ${passed}`);
162
+ console.log(`Failed: ${failed}`);
163
+ console.log('');
164
+ if (failed > 0) {
165
+ console.log('❌ Some tests failed');
166
+ process.exit(1);
167
+ }
168
+ else {
169
+ console.log('✅ All tests passed!');
170
+ }
171
+ }
172
+ runTests().catch(error => {
173
+ console.error('Test suite failed:', error);
174
+ process.exit(1);
175
+ });
@@ -209,6 +209,79 @@ async function testContentAndToolCalls() {
209
209
  }
210
210
  console.log('✅ Content + tool calls test passed\n');
211
211
  }
212
+ async function testStructuredOutputJsonObject() {
213
+ console.log('Testing structured output - JSON Object mode...');
214
+ const request = {
215
+ gateId: 'test-gate',
216
+ model: 'gpt-4o',
217
+ type: 'chat',
218
+ data: {
219
+ messages: [
220
+ { role: 'user', content: 'Generate a JSON user profile with name, age, and city fields' }
221
+ ],
222
+ responseFormat: 'json_object',
223
+ maxTokens: 100,
224
+ }
225
+ };
226
+ const response = await adapter.call(request);
227
+ console.log('Response:', response.content);
228
+ // Try to parse as JSON
229
+ try {
230
+ const parsed = JSON.parse(response.content || '');
231
+ console.log('Parsed JSON:', parsed);
232
+ console.log('✅ JSON Object mode test passed\n');
233
+ }
234
+ catch (error) {
235
+ throw new Error(`Response was not valid JSON: ${response.content}`);
236
+ }
237
+ }
238
+ async function testStructuredOutputJsonSchema() {
239
+ console.log('Testing structured output - JSON Schema mode...');
240
+ const schema = {
241
+ type: 'json_schema',
242
+ json_schema: {
243
+ name: 'user_profile',
244
+ strict: true,
245
+ schema: {
246
+ type: 'object',
247
+ properties: {
248
+ name: { type: 'string' },
249
+ age: { type: 'number' },
250
+ city: { type: 'string' },
251
+ },
252
+ required: ['name', 'age', 'city'],
253
+ additionalProperties: false,
254
+ },
255
+ },
256
+ };
257
+ const request = {
258
+ gateId: 'test-gate',
259
+ model: 'gpt-4o',
260
+ type: 'chat',
261
+ data: {
262
+ messages: [
263
+ { role: 'user', content: 'Create a profile for John Doe, age 30, from New York' }
264
+ ],
265
+ responseFormat: schema,
266
+ maxTokens: 100,
267
+ }
268
+ };
269
+ const response = await adapter.call(request);
270
+ console.log('Response:', response.content);
271
+ // Try to parse as JSON and validate schema
272
+ try {
273
+ const parsed = JSON.parse(response.content || '');
274
+ console.log('Parsed JSON:', parsed);
275
+ // Validate required fields
276
+ if (!parsed.name || typeof parsed.age !== 'number' || !parsed.city) {
277
+ throw new Error('Response does not match schema');
278
+ }
279
+ console.log('✅ JSON Schema mode test passed\n');
280
+ }
281
+ catch (error) {
282
+ throw new Error(`Schema validation failed: ${error}`);
283
+ }
284
+ }
212
285
  async function runTests() {
213
286
  try {
214
287
  await testChatCompletion();
@@ -218,6 +291,9 @@ async function runTests() {
218
291
  await testToolCalling();
219
292
  console.log('Testing content + tool calls...');
220
293
  await testContentAndToolCalls();
294
+ console.log('Testing structured output...');
295
+ await testStructuredOutputJsonObject();
296
+ await testStructuredOutputJsonSchema();
221
297
  await testImageGeneration();
222
298
  await testEmbeddings();
223
299
  await testTextToSpeech();