adding better exporting
This commit is contained in:
+14
-1
@@ -1,5 +1,5 @@
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
import { createRequestLogger, ensureSchema, insertRequest } from '../src/db.js';
|
||||
import { createRequestLogger, ensureSchema, insertRequest, removeNonChatCompletionRequests } from '../src/db.js';
|
||||
|
||||
describe('request database', () => {
|
||||
it('creates the requests table, compatible columns, and recent-request index', async () => {
|
||||
@@ -37,6 +37,19 @@ describe('request database', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it('removes requests that are not for the chat completions endpoint', async () => {
|
||||
const pool = { query: vi.fn().mockResolvedValue({ rowCount: 4 }) };
|
||||
|
||||
await expect(removeNonChatCompletionRequests(pool)).resolves.toBe(4);
|
||||
|
||||
expect(pool.query).toHaveBeenCalledOnce();
|
||||
expect(pool.query.mock.calls[0][0]).toContain("split_part(endpoint, '?', 1) <> ALL($1::text[])");
|
||||
expect(pool.query.mock.calls[0][1]).toEqual([[
|
||||
'/oai/v1/chat/completions', '/oai/v1/responses',
|
||||
'/ant/v1/messages', '/ant/v1/v1/messages',
|
||||
]]);
|
||||
});
|
||||
|
||||
it('reports storage failures without rejecting request handling', async () => {
|
||||
const onError = vi.fn();
|
||||
const logger = createRequestLogger({ query: vi.fn().mockRejectedValue(new Error('database offline')) }, { onError });
|
||||
|
||||
+27
-7
@@ -126,17 +126,37 @@ describe('proxy', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('collects error and not-found responses too', async () => {
|
||||
it('does not collect requests to non-chat-completion endpoints', async () => {
|
||||
const fetchImpl = vi.fn().mockResolvedValue(response('{"object":"list","data":[]}'));
|
||||
const requestLogger = { log: vi.fn() };
|
||||
const app = createProxyApp({ keys: ['key'], requestLogger });
|
||||
const app = createProxyApp({ keys: ['key'], fetchImpl, requestLogger });
|
||||
|
||||
await request(app).get('/missing').expect(404);
|
||||
await request(app).get('/oai/v1/models').expect(200);
|
||||
|
||||
expect(requestLogger.log).toHaveBeenCalledOnce();
|
||||
expect(requestLogger.log.mock.calls[0][0]).toMatchObject({
|
||||
method: 'GET', endpoint: '/missing', requestBody: null, responseStatus: 404,
|
||||
});
|
||||
expect(requestLogger.log.mock.calls[0][0].responseBody).toContain('Cannot GET /missing');
|
||||
expect(requestLogger.log).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('collects OpenAI Responses and Anthropic Messages requests', async () => {
|
||||
const cases = [
|
||||
{ endpoint: '/oai/v1/responses', body: { model: 'm', input: 'Hi' } },
|
||||
{ endpoint: '/ant/v1/messages', body: { model: 'm', max_tokens: 10, messages: [{ role: 'user', content: 'Hi' }] } },
|
||||
{ endpoint: '/ant/v1/v1/messages', body: { model: 'm', max_tokens: 10, messages: [{ role: 'user', content: 'Hi' }] } },
|
||||
];
|
||||
|
||||
for (const { endpoint, body } of cases) {
|
||||
const fetchImpl = vi.fn().mockResolvedValue(response(JSON.stringify({
|
||||
id: 'chatcmpl-response', model: 'm',
|
||||
choices: [{ message: { role: 'assistant', content: 'Hello' }, finish_reason: 'stop' }],
|
||||
})));
|
||||
const requestLogger = { log: vi.fn() };
|
||||
const app = createProxyApp({ keys: ['key'], fetchImpl, requestLogger });
|
||||
|
||||
await request(app).post(endpoint).send(body).expect(200);
|
||||
|
||||
expect(requestLogger.log).toHaveBeenCalledOnce();
|
||||
expect(requestLogger.log.mock.calls[0][0]).toMatchObject({ method: 'POST', endpoint, requestBody: body });
|
||||
}
|
||||
});
|
||||
|
||||
it('translates Responses requests and returns a Responses object', async () => {
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { createFullTraceSelector } from '../src/traces.js';
|
||||
|
||||
const message = (role, content, extra = {}) => ({ role, content, ...extra });
|
||||
const example = (...messages) => ({ messages });
|
||||
|
||||
describe('full trace selection', () => {
|
||||
it('keeps only the maximal snapshot of a growing conversation', () => {
|
||||
const user = message('user', 'Start');
|
||||
const first = message('assistant', 'First');
|
||||
const next = message('user', 'Continue');
|
||||
const last = message('assistant', 'Done');
|
||||
const examples = [
|
||||
example(user, first, next, last),
|
||||
example(user, first),
|
||||
];
|
||||
|
||||
expect(examples.filter(createFullTraceSelector())).toEqual([examples[0]]);
|
||||
});
|
||||
|
||||
it('keeps every leaf when a conversation is rewound and branched', () => {
|
||||
const shared = [message('user', 'Start'), message('assistant', 'Shared')];
|
||||
const branchC = example(...shared, message('user', 'Choose C'), message('assistant', 'C'));
|
||||
const branchD = example(...shared, message('user', 'Choose D'), message('assistant', 'D'));
|
||||
const intermediate = example(...shared);
|
||||
|
||||
const examples = [branchD, branchC, intermediate];
|
||||
expect(examples.filter(createFullTraceSelector())).toEqual([branchD, branchC]);
|
||||
});
|
||||
|
||||
it('matches JSON tool arguments despite provider whitespace changes', () => {
|
||||
const requestToolCall = message('assistant', null, {
|
||||
tool_calls: [{ id: 'call_1', type: 'function', function: { name: 'run', arguments: '{ "path": "a" }' } }],
|
||||
});
|
||||
const echoedToolCall = message('assistant', null, {
|
||||
tool_calls: [{ type: 'function', function: { arguments: '{"path":"a"}', name: 'run' }, id: 'call_1' }],
|
||||
});
|
||||
const newest = example(
|
||||
message('user', 'Run it'), echoedToolCall,
|
||||
message('tool', 'ok', { tool_call_id: 'call_1' }), message('assistant', 'Done'),
|
||||
);
|
||||
const intermediate = example(message('user', 'Run it'), requestToolCall);
|
||||
|
||||
const examples = [newest, intermediate];
|
||||
expect(examples.filter(createFullTraceSelector())).toEqual([newest]);
|
||||
});
|
||||
|
||||
it('does not combine unrelated conversations', () => {
|
||||
const examples = [
|
||||
example(message('user', 'One'), message('assistant', '1')),
|
||||
example(message('user', 'Two'), message('assistant', '2')),
|
||||
];
|
||||
expect(examples.filter(createFullTraceSelector())).toEqual(examples);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user