feat: add OpenAI OAuth, strict model overrides, and Gmail pull mode

This commit is contained in:
William Valentin
2026-02-13 14:55:40 -08:00
parent 8f644d5e25
commit 955b9e28e0
50 changed files with 5955 additions and 160 deletions
+38
View File
@@ -140,6 +140,44 @@ describe('LlamaCppClient', () => {
}]);
});
it('sanitizes web_search tool schema for llama.cpp', async () => {
mockFetch.mockResolvedValue({
ok: true,
json: () => Promise.resolve({
choices: [{ message: { content: 'ok' } }],
usage: { prompt_tokens: 1, completion_tokens: 1 },
}),
});
const client = new LlamaCppClient({
endpoint: 'http://localhost:8080',
model: 'test-model',
});
await client.chat({
messages: [{ role: 'user', content: 'search' }],
tools: [{
name: 'web_search',
description: 'Search',
input_schema: {
type: 'object',
properties: {
query: { type: 'string' },
count: { type: 'number' },
},
required: ['query'],
},
}],
});
const requestBody = JSON.parse(mockFetch.mock.calls[0][1].body);
expect(requestBody.tools[0].function.parameters).toEqual({
type: 'object',
properties: { query: { type: 'string' } },
required: ['query'],
});
});
it('parses tool_calls from response', async () => {
mockFetch.mockResolvedValue({
ok: true,
+32 -2
View File
@@ -48,6 +48,36 @@ interface LlamaCppStreamChunk {
usage?: { prompt_tokens: number; completion_tokens: number };
}
function sanitizeToolParametersForLlamaCpp(toolName: string, parameters: unknown): unknown {
// llama.cpp is stricter than most tool-call APIs about JSON schema.
// In particular, some builds reject extra optional properties for common tools.
// Keep the full schema for most tools, but reduce known-problematic ones.
if (toolName !== 'web_search') {
return parameters;
}
if (!parameters || typeof parameters !== 'object') {
return parameters;
}
const schema = parameters as {
type?: unknown;
properties?: Record<string, unknown>;
required?: unknown;
};
const querySchema = schema.properties?.query;
if (!querySchema) {
return parameters;
}
return {
type: 'object',
properties: { query: querySchema },
required: ['query'],
};
}
/** Message format for OpenAI-compatible chat completions API. */
interface LlamaCppChatMessage {
role: 'system' | 'user' | 'assistant' | 'tool';
@@ -211,7 +241,7 @@ export class LlamaCppClient implements ModelClient {
function: {
name: t.name,
description: t.description,
parameters: t.input_schema,
parameters: sanitizeToolParametersForLlamaCpp(t.name, t.input_schema),
},
}));
}
@@ -292,7 +322,7 @@ export class LlamaCppClient implements ModelClient {
function: {
name: t.name,
description: t.description,
parameters: t.input_schema,
parameters: sanitizeToolParametersForLlamaCpp(t.name, t.input_schema),
},
}));
}