148 lines
4.7 KiB
TypeScript
148 lines
4.7 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import {
|
|
createGrokAdapters,
|
|
createGrokImageModelAdapter,
|
|
createGrokStructuredModelAdapter,
|
|
createGrokTextModelAdapter,
|
|
} from '../src';
|
|
|
|
describe('Grok adapters', () => {
|
|
it('creates a text adapter that calls xAI chat completions', async () => {
|
|
const calls: Array<{ url: string; init?: RequestInit }> = [];
|
|
const adapter = createGrokTextModelAdapter({
|
|
apiKey: 'test-key',
|
|
model: 'grok-4.3-mini',
|
|
fetch: async (url, init) => {
|
|
calls.push({ url: String(url), ...(init ? { init } : {}) });
|
|
return new Response(JSON.stringify({
|
|
choices: [
|
|
{
|
|
message: {
|
|
content: 'hello from grok',
|
|
},
|
|
},
|
|
],
|
|
}), {
|
|
status: 200,
|
|
headers: { 'content-type': 'application/json' },
|
|
});
|
|
},
|
|
});
|
|
|
|
await expect(adapter.generateText({
|
|
system: 'You are a helpful persona engine.',
|
|
prompt: 'Say hi.',
|
|
temperature: 0.3,
|
|
})).resolves.toBe('hello from grok');
|
|
|
|
expect(calls).toHaveLength(1);
|
|
expect(calls[0]?.url).toBe('https://api.x.ai/v1/chat/completions');
|
|
expect(calls[0]?.init?.method).toBe('POST');
|
|
expect(calls[0]?.init?.headers).toMatchObject({
|
|
authorization: 'Bearer test-key',
|
|
'content-type': 'application/json',
|
|
});
|
|
|
|
const body = JSON.parse(String(calls[0]?.init?.body));
|
|
expect(body.model).toBe('grok-4.3-mini');
|
|
expect(body.temperature).toBe(0.3);
|
|
expect(body.messages).toEqual([
|
|
{ role: 'system', content: 'You are a helpful persona engine.' },
|
|
{ role: 'user', content: 'Say hi.' },
|
|
]);
|
|
});
|
|
|
|
it('creates a structured adapter that sends json_schema response_format and parses JSON', async () => {
|
|
const calls: Array<{ url: string; init?: RequestInit }> = [];
|
|
const adapter = createGrokStructuredModelAdapter({
|
|
apiKey: 'test-key',
|
|
model: 'grok-4.3',
|
|
fetch: async (url, init) => {
|
|
calls.push({ url: String(url), ...(init ? { init } : {}) });
|
|
return new Response(JSON.stringify({
|
|
choices: [
|
|
{
|
|
message: {
|
|
content: JSON.stringify({ biography: 'Born in Busan.' }),
|
|
},
|
|
},
|
|
],
|
|
}), {
|
|
status: 200,
|
|
headers: { 'content-type': 'application/json' },
|
|
});
|
|
},
|
|
});
|
|
|
|
const schema = {
|
|
type: 'object',
|
|
required: ['biography'],
|
|
properties: { biography: { type: 'string' } },
|
|
};
|
|
|
|
await expect(adapter.generateObject<{ biography: string }>({
|
|
prompt: 'Write a biography.',
|
|
system: 'Return only JSON.',
|
|
schema,
|
|
})).resolves.toEqual({ biography: 'Born in Busan.' });
|
|
|
|
const body = JSON.parse(String(calls[0]?.init?.body));
|
|
expect(body.response_format).toEqual({
|
|
type: 'json_schema',
|
|
json_schema: {
|
|
name: 'boxbrain_structured_output',
|
|
schema,
|
|
},
|
|
});
|
|
});
|
|
|
|
it('creates an image adapter that calls xAI image generation with mapped aspect ratios', async () => {
|
|
const calls: Array<{ url: string; init?: RequestInit }> = [];
|
|
const adapter = createGrokImageModelAdapter({
|
|
apiKey: 'test-key',
|
|
model: 'grok-imagine-image-quality',
|
|
fetch: async (url, init) => {
|
|
calls.push({ url: String(url), ...(init ? { init } : {}) });
|
|
return new Response(JSON.stringify({
|
|
data: [{ url: 'https://cdn.x.ai/generated.png', revised_prompt: 'revised prompt' }],
|
|
}), {
|
|
status: 200,
|
|
headers: { 'content-type': 'application/json' },
|
|
});
|
|
},
|
|
});
|
|
|
|
await expect(adapter.generateImage({
|
|
prompt: 'A quiet portrait photo.',
|
|
aspectRatio: 'portrait',
|
|
})).resolves.toEqual({
|
|
url: 'https://cdn.x.ai/generated.png',
|
|
revisedPrompt: 'revised prompt',
|
|
});
|
|
|
|
expect(calls[0]?.url).toBe('https://api.x.ai/v1/images/generations');
|
|
const body = JSON.parse(String(calls[0]?.init?.body));
|
|
expect(body.aspect_ratio).toBe('3:4');
|
|
expect(body.model).toBe('grok-imagine-image-quality');
|
|
});
|
|
|
|
it('can create a bundled Grok adapter set with shared defaults', async () => {
|
|
const adapters = createGrokAdapters({
|
|
apiKey: 'bundle-key',
|
|
textModel: 'grok-4.3-mini',
|
|
structuredModel: 'grok-4.3',
|
|
imageModel: 'grok-imagine-image-quality',
|
|
fetch: async (_url, _init) => new Response(JSON.stringify({
|
|
choices: [{ message: { content: 'ok' } }],
|
|
}), {
|
|
status: 200,
|
|
headers: { 'content-type': 'application/json' },
|
|
}),
|
|
});
|
|
|
|
expect(adapters.text.provider).toBe('xai-grok');
|
|
expect(adapters.structured.model).toBe('grok-4.3');
|
|
expect(adapters.image.model).toBe('grok-imagine-image-quality');
|
|
});
|
|
});
|