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<IChatWebSocketManager>;
export interface IChatWebSocketManager {
    readonly _serviceBrand: undefined;
    /**
     * Gets or creates a WebSocket connection for the given conversation.
     * The connection is shared across turns and tool call rounds within
     * the same conversation, keeping server-side context alive.
     */
    getOrCreateConnection(conversationId: string, headers: Record<string, string>, initiatingRequestId: string): IChatWebSocketConnection;
    /**
     * Returns true if there is an open WebSocket connection for the given
     * conversation. Used to decide whether the server already has context
     * from earlier requests in this conversation.
     */
    hasActiveConnection(conversationId: string): 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(conversationId: string): string | undefined;
    /**
     * Returns the round ID at which the last client-side summarization
     * occurred for this connection, or undefined if none.
     */
    getSummarizedAtRoundId(conversationId: string): string | undefined;
    /**
     * Closes and removes the connection for a specific conversation.
     */
    closeConnection(conversationId: 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(_conversationId: string, _headers?: Record<string, string>, _initiatingRequestId?: string): IChatWebSocketConnection;
    hasActiveConnection(_conversationId: string): boolean;
    getStatefulMarker(_conversationId: string): string | undefined;
    getSummarizedAtRoundId(_conversationId: string): string | undefined;
    closeConnection(_conversationId: string): void;
    closeAll(): void;
}
export interface IChatWebSocketRequestOptions {
    userInitiated: boolean;
    turnId: string;
    requestId: string;
    model: string;
    countTokens: () => Promise<number>;
    tokenCountMax: number;
    modelMaxPromptTokens: number;
    summarizedAtRoundId?: string;
    modeChanged?: boolean;
}
export interface IChatWebSocketConnection extends IDisposable {
    /** Opens the WebSocket connection. Must be called before sendRequest. */
    connect(): Promise<void>;
    /** 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<OpenAI.Responses.ResponseStreamEvent>;
    /** Fires when a CAPI WebSocket error is received (nested error shape). */
    readonly onCAPIError: Event<CAPIWebSocketErrorEvent>;
    /** Fires when a transport-level error occurs (connection lost, etc.). */
    readonly onError: Event<Error>;
    /**
     * 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<OpenAI.Responses.ResponseStreamEvent | CAPIWebSocketErrorEvent>;
    /** Resolves when the request has finished (completed or errored). */
    readonly done: Promise<void>;
}
/**
 * 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(conversationId: string, headers: Record<string, string>, initiatingRequestId: string): IChatWebSocketConnection;
    hasActiveConnection(conversationId: string): boolean;
    getStatefulMarker(conversationId: string): string | undefined;
    getSummarizedAtRoundId(conversationId: string): string | undefined;
    closeConnection(conversationId: string): void;
    closeAll(): void;
    dispose(): void;
}
//# sourceMappingURL=chatWebSocketManager.d.ts.map