Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/platform/networking/common/anthropic.ts
13401 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 { ConfigKey, IConfigurationService } from '../../configuration/common/configurationService';
7
import { modelSupportsContextEditing } from '../../endpoint/common/chatModelCapabilities';
8
import { IExperimentationService } from '../../telemetry/common/nullExperimentationService';
9
import { IChatEndpoint } from './networking';
10
11
/**
12
* Types for Anthropic Messages API
13
* Based on https://platform.claude.com/docs/en/api/messages
14
*
15
* This interface supports both regular tools and server tools (web search, tool search):
16
* - Regular tools: require name, description, and input_schema
17
* - Tool search tools: require only type and name
18
*/
19
export interface AnthropicMessagesTool {
20
name: string;
21
type?: string;
22
description?: string;
23
input_schema?: {
24
type: 'object';
25
properties?: Record<string, unknown>;
26
required?: string[];
27
};
28
defer_loading?: boolean;
29
cache_control?: { type: 'ephemeral' };
30
}
31
32
/** Name for the custom client-side embeddings-based tool search tool. Must not use copilot_/vscode_ prefix — those are reserved for static package.json declarations and will be rejected by vscode.lm.registerToolDefinition. */
33
export const CUSTOM_TOOL_SEARCH_NAME = 'tool_search';
34
35
/**
36
* Context management types for Anthropic Messages API
37
* Based on https://platform.claude.com/docs/en/build-with-claude/context-editing
38
*/
39
export type ContextManagementTrigger =
40
| { type: 'input_tokens'; value: number }
41
| { type: 'tool_uses'; value: number };
42
43
export type ContextManagementKeep =
44
| { type: 'tool_uses'; value: number }
45
| { type: 'thinking_turns'; value: number }
46
| 'all';
47
48
export type ContextManagementClearAtLeast = {
49
type: 'input_tokens';
50
value: number;
51
};
52
53
export interface ClearToolUsesEdit {
54
type: 'clear_tool_uses_20250919';
55
trigger?: ContextManagementTrigger;
56
keep?: ContextManagementKeep;
57
clear_at_least?: ContextManagementClearAtLeast;
58
exclude_tools?: string[];
59
clear_tool_inputs?: boolean;
60
}
61
62
export interface ClearThinkingEdit {
63
type: 'clear_thinking_20251015';
64
keep?: ContextManagementKeep;
65
}
66
67
export type ContextManagementEdit = ClearToolUsesEdit | ClearThinkingEdit;
68
69
export interface ContextManagement {
70
edits: ContextManagementEdit[];
71
}
72
73
export interface AppliedContextEdit {
74
type: 'clear_thinking_20251015' | 'clear_tool_uses_20250919';
75
cleared_thinking_turns?: number;
76
cleared_tool_uses?: number;
77
cleared_input_tokens?: number;
78
}
79
80
export interface ContextManagementResponse {
81
applied_edits: AppliedContextEdit[];
82
}
83
84
/**
85
* Interleaved thinking is supported by:
86
* - Claude Sonnet 4.5 (claude-sonnet-4-5-* or claude-sonnet-4.5-*)
87
* - Claude Sonnet 4 (claude-sonnet-4-*)
88
* - Claude Haiku 4.5 (claude-haiku-4-5-* or claude-haiku-4.5-*)
89
* - Claude Opus 4.5 (claude-opus-4-5-* or claude-opus-4.5-*)
90
* @param modelId The model ID to check
91
* @returns true if the model supports interleaved thinking
92
*/
93
export function modelSupportsInterleavedThinking(modelId: string): boolean {
94
// Normalize: lowercase and replace dots with dashes so "4.5" matches "4-5"
95
const normalized = modelId.toLowerCase().replace(/\./g, '-');
96
return normalized.startsWith('claude-sonnet-4-5') ||
97
normalized.startsWith('claude-sonnet-4') ||
98
normalized.startsWith('claude-haiku-4-5') ||
99
normalized.startsWith('claude-opus-4-5');
100
}
101
102
/**
103
* Memory is supported by:
104
* - Claude Haiku 4.5 (claude-haiku-4-5-* or claude-haiku-4.5-*)
105
* - Claude Sonnet 4.6 (claude-sonnet-4-6-* or claude-sonnet-4.6-*)
106
* - Claude Sonnet 4.5 (claude-sonnet-4-5-* or claude-sonnet-4.5-*)
107
* - Claude Sonnet 4 (claude-sonnet-4-*)
108
* - Claude Opus 4.6 (claude-opus-4-6-* or claude-opus-4.6-*)
109
* - Claude Opus 4.5 (claude-opus-4-5-* or claude-opus-4.5-*)
110
* - Claude Opus 4.1 (claude-opus-4-1-* or claude-opus-4.1-*)
111
* - Claude Opus 4 (claude-opus-4-*)
112
* @param modelId The model ID to check
113
* @returns true if the model supports memory
114
*/
115
export function modelSupportsMemory(modelId: string): boolean {
116
const normalized = modelId.toLowerCase().replace(/\./g, '-');
117
return normalized.startsWith('claude-haiku-4-5') ||
118
normalized.startsWith('claude-sonnet-4-6') ||
119
normalized.startsWith('claude-sonnet-4-5') ||
120
normalized.startsWith('claude-sonnet-4') ||
121
normalized.startsWith('claude-opus-4-6') ||
122
normalized.startsWith('claude-opus-4-5') ||
123
normalized.startsWith('claude-opus-4-1') ||
124
normalized.startsWith('claude-opus-4');
125
}
126
127
export function isAnthropicContextEditingEnabled(
128
endpoint: IChatEndpoint | string,
129
configurationService: IConfigurationService,
130
experimentationService: IExperimentationService,
131
): boolean {
132
const supportsIt = typeof endpoint === 'string'
133
? modelSupportsContextEditing(endpoint)
134
: endpoint.supportsContextEditing ?? modelSupportsContextEditing(endpoint.model);
135
if (!supportsIt) {
136
return false;
137
}
138
const mode = configurationService.getExperimentBasedConfig(ConfigKey.AnthropicContextEditingMode, experimentationService);
139
return mode !== 'off';
140
}
141
142
export function isAnthropicMemoryToolEnabled(
143
endpoint: IChatEndpoint | string,
144
configurationService: IConfigurationService,
145
experimentationService: IExperimentationService,
146
): boolean {
147
const effectiveModelId = typeof endpoint === 'string' ? endpoint : endpoint.model;
148
if (!modelSupportsMemory(effectiveModelId)) {
149
return false;
150
}
151
return configurationService.getExperimentBasedConfig(ConfigKey.MemoryToolEnabled, experimentationService);
152
}
153
154
export type ContextEditingMode = 'off' | 'clear-thinking' | 'clear-tooluse' | 'clear-both';
155
156
/**
157
* Builds the context_management configuration object for the Messages API request.
158
* @param mode The context editing mode
159
* @param thinkingEnabled Whether extended thinking is enabled
160
* @returns The context_management object to include in the request, or undefined if off or no edits
161
*/
162
export function buildContextManagement(
163
mode: ContextEditingMode,
164
thinkingEnabled: boolean
165
): ContextManagement | undefined {
166
if (mode === 'off') {
167
return undefined;
168
}
169
170
const edits: ContextManagementEdit[] = [];
171
172
// Add thinking block clearing for clear-thinking and clear-both modes
173
if ((mode === 'clear-thinking' || mode === 'clear-both') && thinkingEnabled) {
174
edits.push({
175
type: 'clear_thinking_20251015',
176
keep: { type: 'thinking_turns', value: 1 },
177
});
178
}
179
180
// Add tool result clearing for clear-tooluse and clear-both modes
181
if (mode === 'clear-tooluse' || mode === 'clear-both') {
182
edits.push({
183
type: 'clear_tool_uses_20250919',
184
trigger: { type: 'input_tokens', value: 100000 },
185
keep: { type: 'tool_uses', value: 3 },
186
});
187
}
188
189
return edits.length > 0 ? { edits } : undefined;
190
}
191
192
/**
193
* Reads context editing mode from settings and builds the context_management object.
194
* @param configurationService The configuration service to read settings from
195
* @param experimentationService The experimentation service
196
* @param thinkingEnabled Whether extended thinking is enabled
197
* @returns The context_management object to include in the request, or undefined if disabled
198
*/
199
export function getContextManagementFromConfig(
200
configurationService: IConfigurationService,
201
experimentationService: IExperimentationService,
202
thinkingEnabled: boolean,
203
): ContextManagement | undefined {
204
const mode = configurationService.getExperimentBasedConfig(ConfigKey.AnthropicContextEditingMode, experimentationService);
205
return buildContextManagement(mode, thinkingEnabled);
206
}
207
208