import { RequestMetadata } from '@vscode/copilot-api'; import { Raw } from '@vscode/prompt-tsx'; import type { CancellationToken } from 'vscode'; import { ITokenizer, TokenizerType } from '../../../util/common/tokenizer'; import { AsyncIterableObject } from '../../../util/vs/base/common/async'; import { ServicesAccessor } from '../../../util/vs/platform/instantiation/common/instantiation'; import { Source } from '../../chat/common/chatMLFetcher'; import type { ChatLocation, ChatResponse } from '../../chat/common/commonTypes'; import { CustomModel, EndpointEditToolName } from '../../endpoint/common/endpointProvider'; import { ILogService } from '../../log/common/logService'; import { ITelemetryService, TelemetryProperties } from '../../telemetry/common/telemetry'; import { TelemetryData } from '../../telemetry/common/telemetryData'; import { AnthropicMessagesTool, ContextManagement } from './anthropic'; import { FinishedCallback, OpenAiFunctionTool, OpenAiResponsesFunctionTool, OpenAiToolSearchTool, OptionalChatRequestParams, Prediction } from './fetch'; import { FetcherId, FetchOptions, IAbortController, PaginationOptions, Response } from './fetcherService'; import { ChatCompletion, OpenAIContextManagement, RawMessageConversionCallback } from './openai'; /** * Encapsulates all the functionality related to making GET/POST requests using * different libraries (and in the future, different environments like web vs * node). */ export interface IFetcher { getUserAgentLibrary(): string; fetch(url: string, options: FetchOptions): Promise; disconnectAll(): Promise; makeAbortController(): IAbortController; isAbortError(e: any): boolean; isInternetDisconnectedError(e: any): boolean; isFetcherError(err: any): boolean; isNetworkProcessCrashedError(err: any): boolean; getUserMessageForFetcherError(err: any): string; fetchWithPagination(baseUrl: string, options: PaginationOptions): Promise; } export declare const userAgentLibraryHeader = "X-VSCode-User-Agent-Library-Version"; export type ReqHeaders = { [key: string]: string; }; /** * The HeaderContributor provides the interface which allows implmentors * to decorate a request's `headers` object with additional key / value pairs. */ export interface HeaderContributor { contributeHeaderValues(headers: ReqHeaders): void; } /** * Rough shape of an endpoint body. A superset of the parameters of any request, * but provided to at least have rough typings. */ export interface IEndpointBody { /** General or completions: */ tools?: (OpenAiFunctionTool | OpenAiResponsesFunctionTool | AnthropicMessagesTool | OpenAiToolSearchTool)[]; model?: string; previous_response_id?: string; max_tokens?: number; max_output_tokens?: number; max_completion_tokens?: number; temperature?: number; top_p?: number; stream?: boolean; context_management?: ContextManagement | OpenAIContextManagement[]; prediction?: Prediction; messages?: any[]; n?: number; reasoning?: { effort?: string; summary?: string; }; tool_choice?: OptionalChatRequestParams['tool_choice'] | { type: 'function'; name: string; } | string; top_logprobs?: number; intent?: boolean; intent_threshold?: number; state?: 'enabled'; snippy?: { enabled: boolean; }; stream_options?: { include_usage?: boolean; }; prompt?: string; /** OpenAI Chat Completions API top-level reasoning effort (BYOK chat-completions shape). Mirrors the nested `reasoning.effort` used by the Responses API. */ reasoning_effort?: string; /** Embeddings endpoints only: */ dimensions?: number; embed?: boolean; /** Chunking endpoints: */ qos?: any; content?: string; path?: string; local_hashes?: string[]; language_id?: number; /** docs search */ query?: string; scopingQuery?: string; limit?: number; similarity?: number; /** Code search: */ scoping_query?: string; /** Responses API: */ input?: readonly any[]; truncation?: 'auto' | 'disabled'; prompt_cache_key?: string; prompt_cache_options?: { mode: 'implicit' | 'explicit'; }; include?: ['reasoning.encrypted_content']; store?: boolean; text?: { verbosity?: 'low' | 'medium' | 'high'; }; /** Messages API */ thinking?: { type: 'enabled' | 'disabled' | 'adaptive'; budget_tokens?: number; }; output_config?: { /** Validated against the endpoint's declared `reasoning_effort` levels, not a hardcoded set. */ effort?: string; }; /** ChatCompletions API for Anthropic models */ thinking_budget?: number; } export interface IEndpointFetchOptions { suppressIntegrationId?: boolean; } export interface IEndpoint { readonly urlOrRequestMetadata: string | RequestMetadata; getExtraHeaders?(location?: ChatLocation, interactionTypeOverride?: InteractionTypeOverride): Record; getEndpointFetchOptions?(): IEndpointFetchOptions; interceptBody?(body: IEndpointBody | undefined): void; acquireTokenizer(): ITokenizer; readonly modelMaxPromptTokens: number; readonly name: string; readonly version: string; readonly family: string; readonly tokenizer: TokenizerType; } export declare function stringifyUrlOrRequestMetadata(urlOrRequestMetadata: string | RequestMetadata): string; /** * Whether the given value is {@link RequestMetadata} (routed through CAPI) rather * than a literal URL string (fetched directly, e.g. BYOK / custom endpoints). * * This is the exact discriminant used by `networkRequest`: a `RequestMetadata` * object is dispatched via {@link ICAPIClientService.makeRequest}, whereas a * `string` URL is sent straight to {@link IFetcherService.fetch}. */ export declare function isCAPIRequestMetadata(urlOrRequestMetadata: string | RequestMetadata): urlOrRequestMetadata is RequestMetadata; /** * Whether requests for this endpoint are routed through CAPI (the Copilot proxy) * rather than fetched directly from a literal URL (BYOK / custom endpoints). */ export declare function isCAPIEndpoint(endpoint: IEndpoint): boolean; export interface IEmbeddingsEndpoint extends IEndpoint { readonly maxBatchSize: number; } /** Per-request model capability opt-ins. All off by default. */ export interface IModelCapabilityOptions { /** Explicitly enable thinking for this request. */ enableThinking?: boolean; /** Reasoning effort level (e.g. 'low', 'medium', 'high'). Only used when enableThinking is true or when the model supports reasoning effort. */ reasoningEffort?: string; /** Enable the tool search tool for this request. */ enableToolSearch?: boolean; /** Enable context editing for this request. */ enableContextEditing?: boolean; } export interface IMakeChatRequestOptions { /** The debug name for this request */ debugName: string; /** The array of chat messages to send */ messages: Raw.ChatMessage[]; /** Enable WebSocket transport for this request when supported. */ useWebSocket?: boolean; /** Disable Responses API stateful marker reuse, preventing previous_response_id-based history slicing. */ ignoreStatefulMarker?: boolean; /** Indicates whether the request's mode instructions changed from the previous turn. */ modeChanged?: boolean; /** Streaming callback for each response part. */ finishedCb: FinishedCallback | undefined; /** Location where the chat message is being sent. */ location: ChatLocation; /** Optional source of the chat request */ source?: Source; /** Conversation identifier used for request-scoped state (for example WebSocket connection reuse). */ conversationId?: string; /** Optional identifier for an independent WebSocket connection within a conversation. */ webSocketConnectionId?: string; /** Identifier for a single tool-calling turn within a conversation. */ turnId?: string; /** Additional request options */ requestOptions?: Omit; /** Indicates if the request was user-initiated */ userInitiatedRequest?: boolean; /** Indicate whether this is a conversation request or a non-conversation utility request (like model list fetch or title generation) */ isConversationRequest?: boolean; /** (CAPI-only) Optional telemetry properties for analytics */ telemetryProperties?: IChatRequestTelemetryProperties; /** Enable retrying the request when it was filtered due to snippy. Note- if using finishedCb, requires supporting delta.retryReason, eg with clearToPreviousToolInvocation */ enableRetryOnFilter?: boolean; /** Enable retrying the request when it failed. Defaults to enableRetryOnFilter. Note- if using finishedCb, requires supporting delta.retryReason, eg with clearToPreviousToolInvocation */ enableRetryOnError?: boolean; /** Which fetcher to use, overrides the default. */ useFetcher?: FetcherId; /** Per-request model capability opt-ins (thinking, tool search, context editing). */ modelCapabilities?: IModelCapabilityOptions; /** * The round ID at which the most recent client-side summarization occurred. * Used to detect when the WebSocket stateful marker predates a summary. */ summarizedAtRoundId?: string; /** Enable retrying once on simple network errors like ECONNRESET. */ canRetryOnceWithoutRollback?: boolean; /** Custom metadata to be displayed in the log document */ customMetadata?: Record; /** Top-level turn ID for credit accumulation. When set, copilot_usage costs * are attributed to this ID instead of turnId. Used so that all LLM calls * in a turn (including subagents) aggregate under one key. */ topLevelTurnId?: string; /** * Override for the `X-Interaction-Type` header (and matching `requestKind` * telemetry value). When unset, the value is derived from {@link ChatLocation} * via `locationToIntent` (e.g. panel → `conversation-panel`). * * Set this for callers whose surface isn't captured by the location alone: * - `'conversation-subagent'` — search/exec subagents inside an agent turn. * - `'conversation-background'` — utility calls not tied to an active user * turn (e.g. chat title generation, conversation summarization, branch * name suggestion, prompt categorization). */ interactionTypeOverride?: InteractionTypeOverride; } export type IChatRequestTelemetryProperties = { requestId?: string; messageId?: string; conversationId?: string; messageSource?: string; associatedRequestId?: string; retryAfterError?: string; retryAfterErrorGitHubRequestId?: string; connectivityTestError?: string; connectivityTestErrorGitHubRequestId?: string; retryAfterFilterCategory?: string; /** A subtype for categorizing the request with a messageSource- eg subagent */ subType?: string; /** For a subagent: The request ID of the parent request that invoked this subagent. */ parentRequestId?: string; /** For a subagent: The tool_call_id from the parent agent's LLM response that triggered this subagent invocation. */ parentToolCallId?: string; /** For a subagent: The headerRequestId from the parent agent's fetch response that triggered this subagent invocation. */ parentHeaderRequestId?: string; /** For a subagent: The modelCallId from the parent agent's model call that triggered this subagent invocation. */ parentModelCallId?: string; /** The conversation turn index, matching the panel.request turn measurement. */ turnIndex?: string; /** The 0-based iteration number of the tool-calling loop that produced this request. */ iterationNumber?: string; }; export interface ICreateEndpointBodyOptions extends IMakeChatRequestOptions { requestId: string; postOptions: OptionalChatRequestParams; } /** * A single tier of normalized token pricing in AICs per million tokens. */ export interface ITokenPriceTier { /** Cost in AICs per million input tokens */ readonly inputPrice: number; /** Cost in AICs per million output tokens */ readonly outputPrice: number; /** Cost in AICs per million cached (read) tokens */ readonly cacheReadTokenPrice: number | undefined; /** Cost in AICs per million cache-write tokens */ readonly cacheWriteTokenPrice: number | undefined; /** * The largest prompt size (in tokens) billed at this tier's rates. * Derived from CAPI `billing.token_prices..max_prompt_tokens`. * Present only when CAPI provides a `long_context` tier. */ readonly contextMax?: number; } /** * Normalized token pricing in AICs per million tokens, mirroring the CAPI * tiered structure with explicit `default` and optional `longContext` tiers. */ export interface IChatEndpointTokenPricing { /** Default-context tier pricing. */ readonly default: ITokenPriceTier; /** * Long-context tier pricing, present only when its rates differ from the * default tier. When absent the model either has no long-context tier or * its prices match the default tier. */ readonly longContext?: ITokenPriceTier; } export interface IChatEndpoint extends IEndpoint { readonly maxOutputTokens: number; /** The model ID- this may change and will be `copilot-utility` for the utility (fallback) model. Use `family` to switch behavior based on model type. */ readonly model: string; readonly modelProvider: string; readonly apiType?: string; readonly supportsThinkingContentInHistory?: boolean; readonly supportsAdaptiveThinking?: boolean; readonly minThinkingBudget?: number; readonly maxThinkingBudget?: number; readonly supportsReasoningEffort?: string[]; readonly supportsToolSearch?: boolean; readonly supportsContextEditing?: boolean; readonly supportsToolCalls: boolean; readonly supportsVision: boolean; readonly supportsPrediction: boolean; readonly supportedEditTools?: readonly EndpointEditToolName[]; readonly showInModelPicker: boolean; readonly isPremium?: boolean; readonly degradationReason?: string; readonly warningText?: Record; readonly promo?: { id: string; discountPercent: number; endsAt?: string; message: string; }; readonly multiplier?: number; readonly restrictedToSkus?: string[]; /** * Discount applied when this model is reached through Auto, as a fraction * (e.g. `0.1` for 10% off). Only set on models Auto can route to. */ readonly autoDiscount?: number; /** * Normalized token pricing in AICs per million tokens. * Computed from the raw billing token_prices and normalized * to per-million-token rates based on batch_size. */ readonly tokenPricing?: IChatEndpointTokenPricing; readonly priceCategory?: string; readonly modelPickerCategory?: string; readonly isFallback: boolean; readonly customModel?: CustomModel; readonly isExtensionContributed?: boolean; readonly maxPromptImages?: number; /** * When true, this endpoint owns its own credentials via {@link IEndpoint.getExtraHeaders} * (e.g. a BYOK target with a user-supplied `api-key`, `x-api-key`, or `Authorization`) and * the chat fetcher must not fall back to the CAPI Copilot token for the `Authorization` * header. Prevents leaking the user's CAPI bearer token to third-party endpoints, and * avoids over-sending an unintended `Authorization: Bearer …` to gateways (strict * APIM policies, etc.) that validate the header. */ readonly ownsAuthorization?: boolean; /** * Handles processing of responses from a chat endpoint. Each endpoint can have different response formats. * @param telemetryService The telemetry service * @param logService The log service * @param response The response from the chat endpoint * @param expectedNumChoices The expected number of choices in the response * @param finishCallback A finish callback to indicate when the response should be complete * @param telemetryData GH telemetry data from the originating request, will be extended with request information * @param cancellationToken A cancellation tokenf for cancelling the request * @returns An async iterable object of chat completions */ processResponseFromChatEndpoint(telemetryService: ITelemetryService, logService: ILogService, response: Response, expectedNumChoices: number, finishCallback: FinishedCallback, telemetryData: TelemetryData, cancellationToken?: CancellationToken, location?: ChatLocation): Promise>; /** * Flights a request from the chat endpoint returning a chat response. * Most of the time this is ChatMLFetcher#fetchOne, but it can be overridden for special cases. * TODO @lramos15 - Support multiple completions in the future, we don't use this at the moment. * * @param userInitiatedRequest Is only applicable to CAPI requests * @param telemetryProperties An object containing various properties for telemetry, e.g., can contain a field `requestId` that sets the header request ID */ makeChatRequest(debugName: string, messages: Raw.ChatMessage[], finishedCb: FinishedCallback | undefined, token: CancellationToken, location: ChatLocation, source?: Source, requestOptions?: Omit, userInitiatedRequest?: boolean, telemetryProperties?: TelemetryProperties): Promise; /** * Flights a request from the chat endpoint returning a chat response. * Most of the time this is ChatMLFetcher#fetchOne, but it can be overridden for special cases. */ makeChatRequest2(options: IMakeChatRequestOptions, token: CancellationToken): Promise; /** * Creates the request body to be sent to the endpoint based on the request. */ createRequestBody(options: ICreateEndpointBodyOptions): IEndpointBody; cloneWithTokenOverride(modelMaxPromptTokens: number): IChatEndpoint; } /** Function to create a standard request body for CAPI completions */ export declare function createCapiRequestBody(options: ICreateEndpointBodyOptions, model: string, callback?: RawMessageConversionCallback): IEndpointBody; export interface INetworkRequestOptions { readonly requestType: 'GET' | 'POST'; readonly endpointOrUrl: IEndpoint | string | RequestMetadata; readonly secretKey: string | undefined; readonly intent: string; readonly requestId: string; readonly body?: IEndpointBody; readonly additionalHeaders?: Record; readonly cancelToken?: CancellationToken; readonly useFetcher?: FetcherId; readonly canRetryOnce?: boolean; readonly location?: ChatLocation; readonly interactionTypeOverride?: InteractionTypeOverride; } /** * Override values for the `X-Interaction-Type` header (and matching `requestKind` * telemetry value). Mirrors the server's documented vocabulary; only used when the * location-derived intent isn't accurate. * * - `'conversation-subagent'` — nested LLM calls made by a subagent inside an * agent turn (search/exec subagents). * - `'conversation-compaction'` — mid-agent-turn history compaction (user is * waiting; runs on the same model as the agent loop). Distinct from background * summarization, which uses a cheap model and is not tied to an active turn. * - `'conversation-background'` — utility calls not tied to an active user turn * (e.g. chat title generation, conversation summarization, prompt categorization, * branch name suggestion, background todo processing). */ export type InteractionTypeOverride = 'conversation-subagent' | 'conversation-compaction' | 'conversation-background'; export declare function canRetryOnceNetworkError(reason: any): boolean; export declare function postRequest(accessor: ServicesAccessor, options: Omit): Promise; export declare function getRequest(accessor: ServicesAccessor, options: Omit): Promise; export declare const IHeaderContributors: import("../../../util/common/services").ServiceIdentifier; export interface IHeaderContributors { readonly _serviceBrand: undefined; add(contributor: HeaderContributor): void; remove(contributor: HeaderContributor): void; contributeHeaders(headers: ReqHeaders): void; size(): number; } export declare class HeaderContributors implements IHeaderContributors { readonly _serviceBrand: undefined; private readonly contributors; add(contributor: HeaderContributor): void; remove(contributor: HeaderContributor): void; contributeHeaders(headers: ReqHeaders): void; size(): number; } //# sourceMappingURL=networking.d.ts.map