import type { OpenAI } from 'openai'; import { CancellationToken } from '../../../util/vs/base/common/cancellation'; import { Event } from '../../../util/vs/base/common/event'; import { Disposable, IDisposable } from '../../../util/vs/base/common/lifecycle'; import { QuotaSnapshots } from '../../chat/common/chatQuotaService'; import { IConfigurationService } from '../../configuration/common/configurationService'; import { ICAPIClientService } from '../../endpoint/common/capiClient'; import { ILogService } from '../../log/common/logService'; import { ITelemetryService } from '../../telemetry/common/telemetry'; import { IHeaders } from '../common/fetcherService'; import { IEndpointBody } from '../common/networking'; export declare const IChatWebSocketManager: import("../../../util/common/services").ServiceIdentifier; export interface IChatWebSocketConnectionKey { readonly conversationId: string; readonly modelId: string; readonly connectionId?: string; } export interface IChatWebSocketManager { readonly _serviceBrand: undefined; /** * Gets or creates a WebSocket connection for the given conversation lane and model. * The connection is shared across turns and tool call rounds within * the same lane, keeping server-side context alive. */ getOrCreateConnection(key: IChatWebSocketConnectionKey, headers: Record, initiatingRequestId: string): IChatWebSocketConnection; /** * Returns true if there is an idle, open WebSocket connection for the given * conversation lane and model. Used to decide whether the server already has * context from earlier requests in this conversation. */ hasActiveConnection(key: IChatWebSocketConnectionKey): boolean; /** * Returns the stateful marker (last completed response ID) for the given * conversation's active WebSocket connection, or undefined if there is * no active connection or no marker yet. */ getStatefulMarker(key: IChatWebSocketConnectionKey): string | undefined; /** * Returns the round ID at which the last client-side summarization * occurred for this connection, or undefined if none. */ getSummarizedAtRoundId(key: IChatWebSocketConnectionKey): string | undefined; /** * Closes and removes the connection for a specific conversation. */ closeConnection(conversationId: string, connectionId?: string): void; /** * Closes all active connections. */ closeAll(): void; } /** * No-op implementation for contexts where WebSocket is not available (web, tests, chat-lib). */ export declare class NullChatWebSocketManager implements IChatWebSocketManager { readonly _serviceBrand: undefined; getOrCreateConnection(_key: IChatWebSocketConnectionKey, _headers?: Record, _initiatingRequestId?: string): IChatWebSocketConnection; hasActiveConnection(_key: IChatWebSocketConnectionKey): boolean; getStatefulMarker(_key: IChatWebSocketConnectionKey): string | undefined; getSummarizedAtRoundId(_key: IChatWebSocketConnectionKey): string | undefined; closeConnection(_conversationId: string, _connectionId?: string): void; closeAll(): void; } export interface IChatWebSocketRequestOptions { userInitiated: boolean; turnId: string; requestId: string; model: string; countTokens: () => Promise; tokenCountMax: number; modelMaxPromptTokens: number; summarizedAtRoundId?: string; modeChanged?: boolean; } export interface IChatWebSocketConnection extends IDisposable { /** Opens the WebSocket connection. Must be called before sendRequest. */ connect(): Promise; /** Sends a response.create request and returns an async iterable of response events. */ sendRequest(body: IEndpointBody, options: IChatWebSocketRequestOptions, token: CancellationToken): IChatWebSocketRequestHandle; /** Whether the connection is currently open and usable. */ readonly isOpen: boolean; /** Response headers from the WebSocket connection handshake. */ readonly responseHeaders: IHeaders; /** Response status code from the WebSocket connection handshake. */ readonly responseStatusCode: number | undefined; /** Response status text from the WebSocket connection handshake. */ readonly responseStatusText: string | undefined; /** The GitHub request ID from response headers. */ readonly gitHubRequestId: string; /** * The response.id from the last completed response on this connection. * Used as `previous_response_id` on subsequent requests to avoid * re-sending the full message history. */ readonly statefulMarker: string | undefined; } export interface IChatWebSocketRequestHandle { /** Fires for each OpenAI stream event received from the server. */ readonly onEvent: Event; /** Fires when a CAPI WebSocket error is received (nested error shape). */ readonly onCAPIError: Event; /** Fires when a transport-level error occurs (connection lost, etc.). */ readonly onError: Event; /** * Resolves with the first event received from the server, or rejects * if the connection errors/closes before any event arrives. * Consumers can inspect the event type to decide the response kind * (success stream vs. CAPI error) before processing remaining events. */ readonly firstEvent: Promise; /** Resolves when the request has finished (completed or errored). */ readonly done: Promise; } /** * CAPI WebSocket error shape. Unlike the OpenAI SDK's flat `ResponseErrorEvent` * (`{ type: "error", code, message }`), CAPI wraps the error details in a * nested `error` object: `{ type: "error", error: { code, message } }`. * * Non-recoverable errors (rate limits, quota, upstream failures) also include * `copilot_quota_snapshots` with per-model quota state. */ export interface CAPIWebSocketErrorEvent { readonly type: 'error'; readonly error: { readonly code: string; readonly message: string; }; readonly copilot_quota_snapshots?: QuotaSnapshots; } export declare function isCAPIWebSocketError(event: OpenAI.Responses.ResponseStreamEvent | CAPIWebSocketErrorEvent): event is CAPIWebSocketErrorEvent; export declare class ChatWebSocketManager extends Disposable implements IChatWebSocketManager { private readonly _logService; private readonly _capiClientService; private readonly _telemetryService; private readonly _configurationService; readonly _serviceBrand: undefined; private readonly _connections; constructor(_logService: ILogService, _capiClientService: ICAPIClientService, _telemetryService: ITelemetryService, _configurationService: IConfigurationService); getOrCreateConnection(key: IChatWebSocketConnectionKey, headers: Record, initiatingRequestId: string): IChatWebSocketConnection; hasActiveConnection(key: IChatWebSocketConnectionKey): boolean; getStatefulMarker(key: IChatWebSocketConnectionKey): string | undefined; getSummarizedAtRoundId(key: IChatWebSocketConnectionKey): string | undefined; closeConnection(conversationId: string, connectionId?: string): void; private _getConnection; private _getConnectionKey; closeAll(): void; dispose(): void; } //# sourceMappingURL=chatWebSocketManager.d.ts.map