This commit is contained in:
Pascal Garber 2026-04-05 01:42:14 +00:00 committed by GitHub
commit 2f439cfbb0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 95 additions and 1 deletions

View file

@ -29,6 +29,72 @@ describe('formatToolContent', () => {
expect(content).toBe('(No response)');
expect(artifacts).toBeUndefined();
});
it('should return string for known non-OpenAI providers', () => {
const result: t.MCPToolCallResponse = {
content: [{ type: 'text', text: 'Test content' }],
};
const [content] = formatToolContent(result, 'google' as t.Provider);
// Google is recognized but uses array format, so this should be an array
expect(Array.isArray(content)).toBe(true);
});
});
describe('automatic detection of OpenAI-compatible custom endpoints', () => {
it('should automatically recognize new OpenAI-compatible custom endpoints', () => {
const result: t.MCPToolCallResponse = {
content: [
{ type: 'text', text: 'First text' },
{ type: 'text', text: 'Second text' },
],
};
// Test with a custom endpoint that's not explicitly listed
const [content, artifacts] = formatToolContent(result, 'scaleway' as t.Provider);
// Should be recognized and use array format (OpenAI-compatible)
expect(Array.isArray(content)).toBe(true);
expect(content).toEqual([{ type: 'text', text: 'First text\n\nSecond text' }]);
expect(artifacts).toBeUndefined();
});
it('should use array format for unknown OpenAI-compatible endpoints', () => {
const result: t.MCPToolCallResponse = {
content: [
{ type: 'text', text: 'Before image' },
{ type: 'image', data: 'base64data', mimeType: 'image/png' },
{ type: 'text', text: 'After image' },
],
};
// Test with another custom endpoint (e.g., together, perplexity, anyscale)
const [content, artifacts] = formatToolContent(result, 'together' as t.Provider);
// Should use array format like OpenAI
expect(Array.isArray(content)).toBe(true);
expect(content).toEqual([
{ type: 'text', text: 'Before image' },
{ type: 'text', text: 'After image' },
]);
expect(artifacts).toEqual({
content: [
{
type: 'image_url',
image_url: { url: 'data:image/png;base64,base64data' },
},
],
});
});
it('should NOT recognize known non-OpenAI providers', () => {
const result: t.MCPToolCallResponse = {
content: [{ type: 'text', text: 'Test content' }],
};
// Non-OpenAI providers should return string format
const [content, artifacts] = formatToolContent(result, 'bedrock' as t.Provider);
expect(typeof content).toBe('string');
expect(content).toBe('Test content');
expect(artifacts).toBeUndefined();
});
});
describe('recognized providers', () => {

View file

@ -7,6 +7,10 @@ function generateResourceId(text: string): string {
return crypto.createHash('sha256').update(text).digest('hex').substring(0, 10);
}
// Known providers that are NOT OpenAI-compatible
// This is a small, stable list that rarely changes
const NON_OPENAI_PROVIDERS = new Set(['google', 'anthropic', 'bedrock', 'ollama']);
const RECOGNIZED_PROVIDERS = new Set([
'google',
'anthropic',
@ -17,8 +21,32 @@ const RECOGNIZED_PROVIDERS = new Set([
'deepseek',
'ollama',
'bedrock',
// Note: Custom OpenAI-compatible endpoints (like scaleway, together, perplexity, etc.)
// are automatically recognized if they're not in NON_OPENAI_PROVIDERS
]);
/**
* Check if a provider should receive structured content formatting for MCP tool responses.
*
* Recognizes:
* 1. Explicitly listed providers in RECOGNIZED_PROVIDERS
* 2. Custom OpenAI-compatible endpoints (any provider not in NON_OPENAI_PROVIDERS)
*
* Custom endpoints are passed with their endpoint name (not "openai"), so we automatically
* detect them rather than requiring explicit additions for each new provider.
*/
function isRecognizedProvider(provider: t.Provider): boolean {
if (RECOGNIZED_PROVIDERS.has(provider)) {
return true;
}
if (!NON_OPENAI_PROVIDERS.has(provider)) {
return true;
}
return false;
}
const imageFormatters: Record<string, undefined | t.ImageFormatter> = {
// google: (item) => ({
// type: 'image',
@ -92,7 +120,7 @@ export function formatToolContent(
result: t.MCPToolCallResponse,
provider: t.Provider,
): t.FormattedContentResult {
if (!RECOGNIZED_PROVIDERS.has(provider)) {
if (!isRecognizedProvider(provider)) {
return [parseAsString(result), undefined];
}