@output.ai/llm 0.2.13 → 0.3.0-dev.pr341-daa6878
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/package.json +7 -7
- package/src/ai_model.js +24 -6
- package/src/ai_model.spec.js +65 -1
- package/src/ai_sdk.js +66 -43
- package/src/ai_sdk.spec.js +168 -114
- package/src/index.d.ts +109 -30
- package/src/index.js +2 -1
- package/src/prompt_loader_validation.spec.js +9 -88
- package/src/prompt_validations.js +25 -42
- package/src/prompt_validations.spec.js +124 -8
- package/src/validations.js +3 -13
package/src/ai_sdk.spec.js
CHANGED
|
@@ -15,9 +15,15 @@ vi.mock( './ai_model.js', () => ( {
|
|
|
15
15
|
loadTools: ( ...values ) => loadToolsImpl( ...values )
|
|
16
16
|
} ) );
|
|
17
17
|
|
|
18
|
+
const OutputMock = {
|
|
19
|
+
object: vi.fn( opts => ( { _type: 'object', ...opts } ) ),
|
|
20
|
+
array: vi.fn( opts => ( { _type: 'array', ...opts } ) ),
|
|
21
|
+
choice: vi.fn( opts => ( { _type: 'choice', ...opts } ) )
|
|
22
|
+
};
|
|
23
|
+
|
|
18
24
|
const aiFns = {
|
|
19
25
|
generateText: vi.fn(),
|
|
20
|
-
|
|
26
|
+
Output: OutputMock
|
|
21
27
|
};
|
|
22
28
|
vi.mock( 'ai', () => ( aiFns ) );
|
|
23
29
|
|
|
@@ -47,10 +53,6 @@ const basePrompt = {
|
|
|
47
53
|
};
|
|
48
54
|
|
|
49
55
|
beforeEach( () => {
|
|
50
|
-
tracingSpies.addEventStart.mockClear();
|
|
51
|
-
tracingSpies.addEventEnd.mockClear();
|
|
52
|
-
tracingSpies.addEventError.mockClear();
|
|
53
|
-
|
|
54
56
|
loadModelImpl.mockReset().mockReturnValue( 'MODEL' );
|
|
55
57
|
loadPromptImpl.mockReset().mockReturnValue( basePrompt );
|
|
56
58
|
|
|
@@ -60,16 +62,6 @@ beforeEach( () => {
|
|
|
60
62
|
usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 },
|
|
61
63
|
finishReason: 'stop'
|
|
62
64
|
} );
|
|
63
|
-
aiFns.generateObject.mockReset().mockResolvedValue( {
|
|
64
|
-
object: 'OBJECT',
|
|
65
|
-
usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 },
|
|
66
|
-
finishReason: 'stop'
|
|
67
|
-
} );
|
|
68
|
-
|
|
69
|
-
validators.validateGenerateTextArgs.mockClear();
|
|
70
|
-
validators.validateGenerateObjectArgs.mockClear();
|
|
71
|
-
validators.validateGenerateArrayArgs.mockClear();
|
|
72
|
-
validators.validateGenerateEnumArgs.mockClear();
|
|
73
65
|
} );
|
|
74
66
|
|
|
75
67
|
afterEach( async () => {
|
|
@@ -100,10 +92,11 @@ describe( 'ai_sdk', () => {
|
|
|
100
92
|
expect( result.finishReason ).toBe( 'stop' );
|
|
101
93
|
} );
|
|
102
94
|
|
|
103
|
-
it( 'generateObject: validates, traces, calls
|
|
95
|
+
it( 'generateObject: validates, traces, calls generateText with Output.object', async () => {
|
|
104
96
|
const { generateObject } = await importSut();
|
|
105
|
-
aiFns.
|
|
106
|
-
|
|
97
|
+
aiFns.generateText.mockResolvedValueOnce( {
|
|
98
|
+
output: { a: 1 },
|
|
99
|
+
text: '',
|
|
107
100
|
usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 },
|
|
108
101
|
finishReason: 'stop'
|
|
109
102
|
} );
|
|
@@ -121,23 +114,30 @@ describe( 'ai_sdk', () => {
|
|
|
121
114
|
expect( tracingSpies.addEventStart ).toHaveBeenCalledTimes( 1 );
|
|
122
115
|
expect( tracingSpies.addEventEnd ).toHaveBeenCalledTimes( 1 );
|
|
123
116
|
|
|
124
|
-
expect(
|
|
125
|
-
output: 'object',
|
|
117
|
+
expect( OutputMock.object ).toHaveBeenCalledWith( {
|
|
126
118
|
schema,
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
model: 'MODEL',
|
|
130
|
-
messages: basePrompt.messages,
|
|
131
|
-
temperature: 0.3,
|
|
132
|
-
providerOptions: basePrompt.config.providerOptions
|
|
119
|
+
name: 'Thing',
|
|
120
|
+
description: 'A thing'
|
|
133
121
|
} );
|
|
122
|
+
expect( aiFns.generateText ).toHaveBeenCalledWith(
|
|
123
|
+
expect.objectContaining( {
|
|
124
|
+
output: expect.objectContaining( { _type: 'object' } ),
|
|
125
|
+
model: 'MODEL',
|
|
126
|
+
messages: basePrompt.messages,
|
|
127
|
+
temperature: 0.3,
|
|
128
|
+
providerOptions: basePrompt.config.providerOptions
|
|
129
|
+
} )
|
|
130
|
+
);
|
|
131
|
+
expect( result.output ).toEqual( { a: 1 } );
|
|
132
|
+
// Backward compat: .object still works via Proxy
|
|
134
133
|
expect( result.object ).toEqual( { a: 1 } );
|
|
135
134
|
} );
|
|
136
135
|
|
|
137
|
-
it( 'generateArray: validates, traces, calls
|
|
136
|
+
it( 'generateArray: validates, traces, calls generateText with Output.array', async () => {
|
|
138
137
|
const { generateArray } = await importSut();
|
|
139
|
-
aiFns.
|
|
140
|
-
|
|
138
|
+
aiFns.generateText.mockResolvedValueOnce( {
|
|
139
|
+
output: [ 1, 2 ],
|
|
140
|
+
text: '',
|
|
141
141
|
usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 },
|
|
142
142
|
finishReason: 'stop'
|
|
143
143
|
} );
|
|
@@ -155,23 +155,30 @@ describe( 'ai_sdk', () => {
|
|
|
155
155
|
expect( tracingSpies.addEventStart ).toHaveBeenCalledTimes( 1 );
|
|
156
156
|
expect( tracingSpies.addEventEnd ).toHaveBeenCalledTimes( 1 );
|
|
157
157
|
|
|
158
|
-
expect(
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
schemaDescription: 'Two numbers',
|
|
163
|
-
model: 'MODEL',
|
|
164
|
-
messages: basePrompt.messages,
|
|
165
|
-
temperature: 0.3,
|
|
166
|
-
providerOptions: basePrompt.config.providerOptions
|
|
158
|
+
expect( OutputMock.array ).toHaveBeenCalledWith( {
|
|
159
|
+
element: schema,
|
|
160
|
+
name: 'Numbers',
|
|
161
|
+
description: 'Two numbers'
|
|
167
162
|
} );
|
|
163
|
+
expect( aiFns.generateText ).toHaveBeenCalledWith(
|
|
164
|
+
expect.objectContaining( {
|
|
165
|
+
output: expect.objectContaining( { _type: 'array' } ),
|
|
166
|
+
model: 'MODEL',
|
|
167
|
+
messages: basePrompt.messages,
|
|
168
|
+
temperature: 0.3,
|
|
169
|
+
providerOptions: basePrompt.config.providerOptions
|
|
170
|
+
} )
|
|
171
|
+
);
|
|
172
|
+
expect( result.output ).toEqual( [ 1, 2 ] );
|
|
173
|
+
// Backward compat: .object still works via Proxy
|
|
168
174
|
expect( result.object ).toEqual( [ 1, 2 ] );
|
|
169
175
|
} );
|
|
170
176
|
|
|
171
|
-
it( 'generateEnum: validates, traces, calls
|
|
177
|
+
it( 'generateEnum: validates, traces, calls generateText with Output.choice', async () => {
|
|
172
178
|
const { generateEnum } = await importSut();
|
|
173
|
-
aiFns.
|
|
174
|
-
|
|
179
|
+
aiFns.generateText.mockResolvedValueOnce( {
|
|
180
|
+
output: 'B',
|
|
181
|
+
text: '',
|
|
175
182
|
usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 },
|
|
176
183
|
finishReason: 'stop'
|
|
177
184
|
} );
|
|
@@ -183,14 +190,20 @@ describe( 'ai_sdk', () => {
|
|
|
183
190
|
expect( tracingSpies.addEventStart ).toHaveBeenCalledTimes( 1 );
|
|
184
191
|
expect( tracingSpies.addEventEnd ).toHaveBeenCalledTimes( 1 );
|
|
185
192
|
|
|
186
|
-
expect(
|
|
187
|
-
|
|
188
|
-
enum: [ 'A', 'B', 'C' ],
|
|
189
|
-
model: 'MODEL',
|
|
190
|
-
messages: basePrompt.messages,
|
|
191
|
-
temperature: 0.3,
|
|
192
|
-
providerOptions: basePrompt.config.providerOptions
|
|
193
|
+
expect( OutputMock.choice ).toHaveBeenCalledWith( {
|
|
194
|
+
options: [ 'A', 'B', 'C' ]
|
|
193
195
|
} );
|
|
196
|
+
expect( aiFns.generateText ).toHaveBeenCalledWith(
|
|
197
|
+
expect.objectContaining( {
|
|
198
|
+
output: expect.objectContaining( { _type: 'choice' } ),
|
|
199
|
+
model: 'MODEL',
|
|
200
|
+
messages: basePrompt.messages,
|
|
201
|
+
temperature: 0.3,
|
|
202
|
+
providerOptions: basePrompt.config.providerOptions
|
|
203
|
+
} )
|
|
204
|
+
);
|
|
205
|
+
expect( result.output ).toBe( 'B' );
|
|
206
|
+
// Backward compat: .object still works via Proxy
|
|
194
207
|
expect( result.object ).toBe( 'B' );
|
|
195
208
|
} );
|
|
196
209
|
|
|
@@ -257,21 +270,20 @@ describe( 'ai_sdk', () => {
|
|
|
257
270
|
const schema = z.object( { result: z.string() } );
|
|
258
271
|
await generateObject( { prompt: 'test_prompt@v1', schema } );
|
|
259
272
|
|
|
260
|
-
expect( aiFns.
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
reasoningSummary: 'detailed'
|
|
273
|
+
expect( aiFns.generateText ).toHaveBeenCalledWith(
|
|
274
|
+
expect.objectContaining( {
|
|
275
|
+
output: expect.objectContaining( { _type: 'object' } ),
|
|
276
|
+
model: 'MODEL',
|
|
277
|
+
messages: promptWithOpenAIOptions.messages,
|
|
278
|
+
temperature: 0.8,
|
|
279
|
+
providerOptions: {
|
|
280
|
+
openai: {
|
|
281
|
+
reasoningEffort: 'high',
|
|
282
|
+
reasoningSummary: 'detailed'
|
|
283
|
+
}
|
|
272
284
|
}
|
|
273
|
-
}
|
|
274
|
-
|
|
285
|
+
} )
|
|
286
|
+
);
|
|
275
287
|
} );
|
|
276
288
|
|
|
277
289
|
it( 'generateArray: passes azure-specific options to AI SDK', async () => {
|
|
@@ -295,21 +307,20 @@ describe( 'ai_sdk', () => {
|
|
|
295
307
|
const schema = z.string();
|
|
296
308
|
await generateArray( { prompt: 'test_prompt@v1', schema } );
|
|
297
309
|
|
|
298
|
-
expect( aiFns.
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
apiVersion: '2023-12-01-preview'
|
|
310
|
+
expect( aiFns.generateText ).toHaveBeenCalledWith(
|
|
311
|
+
expect.objectContaining( {
|
|
312
|
+
output: expect.objectContaining( { _type: 'array' } ),
|
|
313
|
+
model: 'MODEL',
|
|
314
|
+
messages: promptWithAzureOptions.messages,
|
|
315
|
+
maxOutputTokens: 2000,
|
|
316
|
+
providerOptions: {
|
|
317
|
+
azure: {
|
|
318
|
+
deploymentName: 'my-deployment',
|
|
319
|
+
apiVersion: '2023-12-01-preview'
|
|
320
|
+
}
|
|
310
321
|
}
|
|
311
|
-
}
|
|
312
|
-
|
|
322
|
+
} )
|
|
323
|
+
);
|
|
313
324
|
} );
|
|
314
325
|
|
|
315
326
|
it( 'generateEnum: passes mixed provider options to AI SDK', async () => {
|
|
@@ -335,23 +346,24 @@ describe( 'ai_sdk', () => {
|
|
|
335
346
|
const { generateEnum } = await importSut();
|
|
336
347
|
await generateEnum( { prompt: 'test_prompt@v1', enum: [ 'A', 'B', 'C' ] } );
|
|
337
348
|
|
|
338
|
-
expect( aiFns.
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
349
|
+
expect( aiFns.generateText ).toHaveBeenCalledWith(
|
|
350
|
+
expect.objectContaining( {
|
|
351
|
+
output: expect.objectContaining( { _type: 'choice' } ),
|
|
352
|
+
model: 'MODEL',
|
|
353
|
+
messages: promptWithMixedOptions.messages,
|
|
354
|
+
maxOutputTokens: 64000,
|
|
355
|
+
providerOptions: {
|
|
356
|
+
thinking: {
|
|
357
|
+
type: 'enabled',
|
|
358
|
+
budgetTokens: 3000
|
|
359
|
+
},
|
|
360
|
+
anthropic: {
|
|
361
|
+
effort: 'high'
|
|
362
|
+
},
|
|
363
|
+
customField: { nested: 'value' }
|
|
364
|
+
}
|
|
365
|
+
} )
|
|
366
|
+
);
|
|
355
367
|
} );
|
|
356
368
|
|
|
357
369
|
it( 'generateText: passes through providerMetadata', async () => {
|
|
@@ -394,10 +406,11 @@ describe( 'ai_sdk', () => {
|
|
|
394
406
|
expect( response.result ).toBe( response.text );
|
|
395
407
|
} );
|
|
396
408
|
|
|
397
|
-
it( 'generateObject: includes unified result field that matches
|
|
409
|
+
it( 'generateObject: includes unified result field that matches output', async () => {
|
|
398
410
|
const { generateObject } = await importSut();
|
|
399
|
-
aiFns.
|
|
400
|
-
|
|
411
|
+
aiFns.generateText.mockResolvedValueOnce( {
|
|
412
|
+
output: { a: 1, b: 'test' },
|
|
413
|
+
text: '',
|
|
401
414
|
usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 },
|
|
402
415
|
finishReason: 'stop'
|
|
403
416
|
} );
|
|
@@ -406,13 +419,16 @@ describe( 'ai_sdk', () => {
|
|
|
406
419
|
const response = await generateObject( { prompt: 'test_prompt@v1', schema } );
|
|
407
420
|
|
|
408
421
|
expect( response.result ).toEqual( { a: 1, b: 'test' } );
|
|
409
|
-
expect( response.result ).toEqual( response.
|
|
422
|
+
expect( response.result ).toEqual( response.output );
|
|
423
|
+
// Backward compat
|
|
424
|
+
expect( response.object ).toEqual( response.output );
|
|
410
425
|
} );
|
|
411
426
|
|
|
412
|
-
it( 'generateArray: includes unified result field that matches
|
|
427
|
+
it( 'generateArray: includes unified result field that matches output', async () => {
|
|
413
428
|
const { generateArray } = await importSut();
|
|
414
|
-
aiFns.
|
|
415
|
-
|
|
429
|
+
aiFns.generateText.mockResolvedValueOnce( {
|
|
430
|
+
output: [ 'item1', 'item2', 'item3' ],
|
|
431
|
+
text: '',
|
|
416
432
|
usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 },
|
|
417
433
|
finishReason: 'stop'
|
|
418
434
|
} );
|
|
@@ -421,13 +437,16 @@ describe( 'ai_sdk', () => {
|
|
|
421
437
|
const response = await generateArray( { prompt: 'test_prompt@v1', schema } );
|
|
422
438
|
|
|
423
439
|
expect( response.result ).toEqual( [ 'item1', 'item2', 'item3' ] );
|
|
424
|
-
expect( response.result ).toEqual( response.
|
|
440
|
+
expect( response.result ).toEqual( response.output );
|
|
441
|
+
// Backward compat
|
|
442
|
+
expect( response.object ).toEqual( response.output );
|
|
425
443
|
} );
|
|
426
444
|
|
|
427
|
-
it( 'generateEnum: includes unified result field that matches
|
|
445
|
+
it( 'generateEnum: includes unified result field that matches output', async () => {
|
|
428
446
|
const { generateEnum } = await importSut();
|
|
429
|
-
aiFns.
|
|
430
|
-
|
|
447
|
+
aiFns.generateText.mockResolvedValueOnce( {
|
|
448
|
+
output: 'yes',
|
|
449
|
+
text: '',
|
|
431
450
|
usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 },
|
|
432
451
|
finishReason: 'stop'
|
|
433
452
|
} );
|
|
@@ -435,7 +454,9 @@ describe( 'ai_sdk', () => {
|
|
|
435
454
|
const response = await generateEnum( { prompt: 'test_prompt@v1', enum: [ 'yes', 'no' ] } );
|
|
436
455
|
|
|
437
456
|
expect( response.result ).toBe( 'yes' );
|
|
438
|
-
expect( response.result ).toBe( response.
|
|
457
|
+
expect( response.result ).toBe( response.output );
|
|
458
|
+
// Backward compat
|
|
459
|
+
expect( response.object ).toBe( response.output );
|
|
439
460
|
} );
|
|
440
461
|
|
|
441
462
|
it( 'generateText: traces error and rethrows when AI SDK fails', async () => {
|
|
@@ -451,7 +472,7 @@ describe( 'ai_sdk', () => {
|
|
|
451
472
|
|
|
452
473
|
it( 'generateObject: traces error and rethrows when AI SDK fails', async () => {
|
|
453
474
|
const error = new Error( 'Invalid schema' );
|
|
454
|
-
aiFns.
|
|
475
|
+
aiFns.generateText.mockRejectedValueOnce( error );
|
|
455
476
|
const { generateObject } = await importSut();
|
|
456
477
|
|
|
457
478
|
const schema = z.object( { a: z.number() } );
|
|
@@ -482,21 +503,24 @@ describe( 'ai_sdk', () => {
|
|
|
482
503
|
|
|
483
504
|
it( 'generateObject: Proxy correctly handles AI SDK response with getter', async () => {
|
|
484
505
|
const responseWithGetter = {
|
|
485
|
-
|
|
486
|
-
get
|
|
487
|
-
return this.
|
|
506
|
+
_internalOutput: { value: 42 },
|
|
507
|
+
get output() {
|
|
508
|
+
return this._internalOutput;
|
|
488
509
|
},
|
|
510
|
+
text: '',
|
|
489
511
|
usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 },
|
|
490
512
|
finishReason: 'stop'
|
|
491
513
|
};
|
|
492
|
-
aiFns.
|
|
514
|
+
aiFns.generateText.mockResolvedValueOnce( responseWithGetter );
|
|
493
515
|
|
|
494
516
|
const { generateObject } = await importSut();
|
|
495
517
|
const schema = z.object( { value: z.number() } );
|
|
496
518
|
const response = await generateObject( { prompt: 'test_prompt@v1', schema } );
|
|
497
519
|
|
|
498
|
-
expect( response.
|
|
520
|
+
expect( response.output ).toEqual( { value: 42 } );
|
|
499
521
|
expect( response.result ).toEqual( { value: 42 } );
|
|
522
|
+
// Backward compat via Proxy
|
|
523
|
+
expect( response.object ).toEqual( { value: 42 } );
|
|
500
524
|
} );
|
|
501
525
|
|
|
502
526
|
it( 'generateText: passes through AI SDK options like tools and maxRetries', async () => {
|
|
@@ -561,6 +585,13 @@ describe( 'ai_sdk', () => {
|
|
|
561
585
|
const { generateObject } = await importSut();
|
|
562
586
|
const schema = z.object( { a: z.number() } );
|
|
563
587
|
|
|
588
|
+
aiFns.generateText.mockResolvedValueOnce( {
|
|
589
|
+
output: { a: 1 },
|
|
590
|
+
text: '',
|
|
591
|
+
usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 },
|
|
592
|
+
finishReason: 'stop'
|
|
593
|
+
} );
|
|
594
|
+
|
|
564
595
|
await generateObject( {
|
|
565
596
|
prompt: 'test_prompt@v1',
|
|
566
597
|
schema,
|
|
@@ -569,7 +600,7 @@ describe( 'ai_sdk', () => {
|
|
|
569
600
|
topP: 0.9
|
|
570
601
|
} );
|
|
571
602
|
|
|
572
|
-
expect( aiFns.
|
|
603
|
+
expect( aiFns.generateText ).toHaveBeenCalledWith(
|
|
573
604
|
expect.objectContaining( {
|
|
574
605
|
maxRetries: 3,
|
|
575
606
|
seed: 123,
|
|
@@ -583,6 +614,13 @@ describe( 'ai_sdk', () => {
|
|
|
583
614
|
const schema = z.string();
|
|
584
615
|
const controller = new AbortController();
|
|
585
616
|
|
|
617
|
+
aiFns.generateText.mockResolvedValueOnce( {
|
|
618
|
+
output: [ 'a' ],
|
|
619
|
+
text: '',
|
|
620
|
+
usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 },
|
|
621
|
+
finishReason: 'stop'
|
|
622
|
+
} );
|
|
623
|
+
|
|
586
624
|
await generateArray( {
|
|
587
625
|
prompt: 'test_prompt@v1',
|
|
588
626
|
schema,
|
|
@@ -590,7 +628,7 @@ describe( 'ai_sdk', () => {
|
|
|
590
628
|
headers: { 'X-Custom': 'value' }
|
|
591
629
|
} );
|
|
592
630
|
|
|
593
|
-
expect( aiFns.
|
|
631
|
+
expect( aiFns.generateText ).toHaveBeenCalledWith(
|
|
594
632
|
expect.objectContaining( {
|
|
595
633
|
abortSignal: controller.signal,
|
|
596
634
|
headers: { 'X-Custom': 'value' }
|
|
@@ -601,6 +639,13 @@ describe( 'ai_sdk', () => {
|
|
|
601
639
|
it( 'generateEnum: passes through AI SDK options', async () => {
|
|
602
640
|
const { generateEnum } = await importSut();
|
|
603
641
|
|
|
642
|
+
aiFns.generateText.mockResolvedValueOnce( {
|
|
643
|
+
output: 'A',
|
|
644
|
+
text: '',
|
|
645
|
+
usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 },
|
|
646
|
+
finishReason: 'stop'
|
|
647
|
+
} );
|
|
648
|
+
|
|
604
649
|
await generateEnum( {
|
|
605
650
|
prompt: 'test_prompt@v1',
|
|
606
651
|
enum: [ 'A', 'B' ],
|
|
@@ -608,7 +653,7 @@ describe( 'ai_sdk', () => {
|
|
|
608
653
|
presencePenalty: 0.5
|
|
609
654
|
} );
|
|
610
655
|
|
|
611
|
-
expect( aiFns.
|
|
656
|
+
expect( aiFns.generateText ).toHaveBeenCalledWith(
|
|
612
657
|
expect.objectContaining( {
|
|
613
658
|
stopSequences: [ 'END' ],
|
|
614
659
|
presencePenalty: 0.5
|
|
@@ -616,6 +661,15 @@ describe( 'ai_sdk', () => {
|
|
|
616
661
|
);
|
|
617
662
|
} );
|
|
618
663
|
|
|
664
|
+
it( 'generateText: .object returns undefined instead of leaking text', async () => {
|
|
665
|
+
const { generateText } = await importSut();
|
|
666
|
+
const result = await generateText( { prompt: 'test_prompt@v1' } );
|
|
667
|
+
|
|
668
|
+
expect( result.object ).toBeUndefined();
|
|
669
|
+
expect( result.text ).toBe( 'TEXT' );
|
|
670
|
+
expect( result.result ).toBe( 'TEXT' );
|
|
671
|
+
} );
|
|
672
|
+
|
|
619
673
|
it( 'generateText: passes through unknown future options for forward compatibility', async () => {
|
|
620
674
|
const { generateText } = await importSut();
|
|
621
675
|
|