Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/platform/endpoint/test/node/chatModelCapabilities.spec.ts
13405 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { describe, expect, test } from 'vitest';
7
import { ConfigKey, IConfigurationService } from '../../../configuration/common/configurationService';
8
import type { IChatEndpoint } from '../../../networking/common/networking';
9
import { IExperimentationService } from '../../../telemetry/common/nullExperimentationService';
10
import { modelSupportsPDFDocuments, modelSupportsToolSearch } from '../../common/chatModelCapabilities';
11
12
function fakeModel(family: string) {
13
return { family } as unknown as IChatEndpoint;
14
}
15
16
describe('modelSupportsPDFDocuments', () => {
17
test('returns true for claude family', () => {
18
expect(modelSupportsPDFDocuments(fakeModel('claude-3.5-sonnet'))).toBe(true);
19
expect(modelSupportsPDFDocuments(fakeModel('claude-3-opus'))).toBe(true);
20
expect(modelSupportsPDFDocuments(fakeModel('claude-4-sonnet'))).toBe(true);
21
});
22
23
test('returns true for Anthropic family', () => {
24
expect(modelSupportsPDFDocuments(fakeModel('Anthropic'))).toBe(true);
25
expect(modelSupportsPDFDocuments(fakeModel('Anthropic-custom'))).toBe(true);
26
});
27
28
test('returns false for non-Anthropic families', () => {
29
expect(modelSupportsPDFDocuments(fakeModel('gpt-4'))).toBe(false);
30
expect(modelSupportsPDFDocuments(fakeModel('gpt-5.1'))).toBe(false);
31
expect(modelSupportsPDFDocuments(fakeModel('gemini-2.0-flash'))).toBe(false);
32
expect(modelSupportsPDFDocuments(fakeModel('o4-mini'))).toBe(false);
33
});
34
});
35
36
describe('modelSupportsToolSearch', () => {
37
test('supports Claude Sonnet/Opus 4.5 and up', () => {
38
expect(modelSupportsToolSearch('claude-sonnet-4-5')).toBe(true);
39
expect(modelSupportsToolSearch('claude-sonnet-4.5')).toBe(true);
40
expect(modelSupportsToolSearch('claude-sonnet-4-5-20250929')).toBe(true);
41
expect(modelSupportsToolSearch('claude-sonnet-4-6')).toBe(true);
42
expect(modelSupportsToolSearch('claude-sonnet-4.6')).toBe(true);
43
expect(modelSupportsToolSearch('claude-opus-4-5')).toBe(true);
44
expect(modelSupportsToolSearch('claude-opus-4.5')).toBe(true);
45
expect(modelSupportsToolSearch('claude-opus-4-5-20251101')).toBe(true);
46
expect(modelSupportsToolSearch('claude-opus-4-6')).toBe(true);
47
expect(modelSupportsToolSearch('claude-opus-4.6')).toBe(true);
48
expect(modelSupportsToolSearch('claude-opus-4.7')).toBe(true);
49
expect(modelSupportsToolSearch('[email protected]')).toBe(true);
50
expect(modelSupportsToolSearch('[email protected]')).toBe(true);
51
});
52
53
test('rejects pre-4.5 models, including date-suffixed ones', () => {
54
// Regression guard: the datestamp must not be read as the minor version.
55
expect(modelSupportsToolSearch('claude-sonnet-4-20250514')).toBe(false);
56
expect(modelSupportsToolSearch('claude-sonnet-4')).toBe(false);
57
expect(modelSupportsToolSearch('claude-opus-4')).toBe(false);
58
expect(modelSupportsToolSearch('claude-opus-4-1')).toBe(false);
59
expect(modelSupportsToolSearch('claude-opus-4.1')).toBe(false);
60
expect(modelSupportsToolSearch('claude-opus-4-1-20250805')).toBe(false);
61
});
62
63
test('rejects non-Sonnet/Opus Claude families', () => {
64
expect(modelSupportsToolSearch('claude-haiku-4-5')).toBe(false);
65
expect(modelSupportsToolSearch('claude-3-5-sonnet-20241022')).toBe(false);
66
expect(modelSupportsToolSearch('claude-3-opus')).toBe(false);
67
});
68
69
test('supports OpenAI gpt-5.4 and gpt-5.5 models when the setting is enabled', () => {
70
const configurationService = {
71
getExperimentBasedConfig: (key: unknown) => key === ConfigKey.ResponsesApiToolSearchEnabled,
72
} as unknown as IConfigurationService;
73
const experimentationService = {} as IExperimentationService;
74
75
expect(modelSupportsToolSearch('gpt-5.4', configurationService, experimentationService)).toBe(true);
76
expect(modelSupportsToolSearch('gpt-5.5', configurationService, experimentationService)).toBe(true);
77
expect(modelSupportsToolSearch('gpt-5.4')).toBe(false);
78
expect(modelSupportsToolSearch('gpt-5.5')).toBe(false);
79
});
80
81
test('rejects suffixed gpt-5.4/5.5 variants (exact match only)', () => {
82
const configurationService = {
83
getExperimentBasedConfig: (key: unknown) => key === ConfigKey.ResponsesApiToolSearchEnabled,
84
} as unknown as IConfigurationService;
85
const experimentationService = {} as IExperimentationService;
86
87
expect(modelSupportsToolSearch('gpt-5.4-mini', configurationService, experimentationService)).toBe(false);
88
expect(modelSupportsToolSearch('gpt-5.4-preview', configurationService, experimentationService)).toBe(false);
89
expect(modelSupportsToolSearch('gpt-5.5-preview', configurationService, experimentationService)).toBe(false);
90
expect(modelSupportsToolSearch('gpt5.5-preview', configurationService, experimentationService)).toBe(false);
91
});
92
93
test('rejects other non-Claude models', () => {
94
expect(modelSupportsToolSearch('gpt-5')).toBe(false);
95
expect(modelSupportsToolSearch('gemini-2.5-pro')).toBe(false);
96
expect(modelSupportsToolSearch('o4-mini')).toBe(false);
97
});
98
});
99
100