"use strict";
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.CanceledResult = exports.CanceledMessage = exports.RESPONSE_CONTAINED_NO_CHOICES = exports.ChatFetchResponseType = exports.ChatLocation = void 0;
exports.getQuotaMessageForPlan = getQuotaMessageForPlan;
exports.getErrorDetailsFromChatFetchError = getErrorDetailsFromChatFetchError;
exports.getFilteredMessage = getFilteredMessage;
const l10n = __importStar(require("@vscode/l10n"));
const time_1 = require("../../../util/common/time");
const vscodeTypesShim_1 = require("../../../util/common/test/shims/vscodeTypesShim");
const openai_1 = require("../../networking/common/openai");
/**
 * The location of a chat request.
 */
var ChatLocation;
(function (ChatLocation) {
    /**
     * The chat panel
     */
    ChatLocation[ChatLocation["Panel"] = 1] = "Panel";
    /**
     * Terminal inline chat
     */
    ChatLocation[ChatLocation["Terminal"] = 2] = "Terminal";
    /**
     * Notebook inline chat
     */
    ChatLocation[ChatLocation["Notebook"] = 3] = "Notebook";
    /**
     * Code editor inline chat
     */
    ChatLocation[ChatLocation["Editor"] = 4] = "Editor";
    /**
     * Chat is happening in an editing session.
     * This location doesn't exist in vscode API, but is still used to compute the location sent for some intents.
     */
    ChatLocation[ChatLocation["EditingSession"] = 5] = "EditingSession";
    /**
     * The chat request does not correspond directly to a user chat request.
     */
    ChatLocation[ChatLocation["Other"] = 6] = "Other";
    /**
     * The chat is an agent mode edit session.
     */
    ChatLocation[ChatLocation["Agent"] = 7] = "Agent";
    /**
     * A request coming through the OpenAILanguageModelServer
     */
    ChatLocation[ChatLocation["ResponsesProxy"] = 8] = "ResponsesProxy";
    /**
     * A request coming through the ClaudeLanguageModelServer (Messages API)
     */
    ChatLocation[ChatLocation["MessagesProxy"] = 9] = "MessagesProxy";
})(ChatLocation || (exports.ChatLocation = ChatLocation = {}));
(function (ChatLocation) {
    /**
     * Use this for passing uiKind to github telemetry, which we don't want to impact.
     * Also known as UIKind in the telemetry data.
     */
    function toString(chatLocation) {
        switch (chatLocation) {
            case ChatLocation.Editor:
                return 'conversationInline';
            case ChatLocation.Panel:
                return 'conversationPanel';
            case ChatLocation.EditingSession:
                return 'editingSession';
            case ChatLocation.Agent:
                return 'editingSessionAgent';
            default:
                return 'none';
        }
    }
    ChatLocation.toString = toString;
    /**
     * This goes to logs and msft telemetry and is ok to change
     */
    function toStringShorter(chatLocation) {
        switch (chatLocation) {
            case ChatLocation.Editor:
            case ChatLocation.Notebook:
                return 'inline';
            case ChatLocation.Panel:
                return 'panel';
            case ChatLocation.EditingSession:
                return 'editingSession';
            default:
                return 'none';
        }
    }
    ChatLocation.toStringShorter = toStringShorter;
})(ChatLocation || (exports.ChatLocation = ChatLocation = {}));
var ChatFetchResponseType;
(function (ChatFetchResponseType) {
    ChatFetchResponseType["OffTopic"] = "offTopic";
    ChatFetchResponseType["Canceled"] = "canceled";
    ChatFetchResponseType["Filtered"] = "filtered";
    ChatFetchResponseType["FilteredRetry"] = "filteredRetry";
    ChatFetchResponseType["PromptFiltered"] = "promptFiltered";
    ChatFetchResponseType["Length"] = "length";
    ChatFetchResponseType["RateLimited"] = "rateLimited";
    ChatFetchResponseType["QuotaExceeded"] = "quotaExceeded";
    ChatFetchResponseType["ExtensionBlocked"] = "extensionBlocked";
    ChatFetchResponseType["BadRequest"] = "badRequest";
    ChatFetchResponseType["NotFound"] = "notFound";
    ChatFetchResponseType["Failed"] = "failed";
    ChatFetchResponseType["Unknown"] = "unknown";
    ChatFetchResponseType["NetworkError"] = "networkError";
    ChatFetchResponseType["AgentUnauthorized"] = "agent_unauthorized";
    ChatFetchResponseType["AgentFailedDependency"] = "agent_failed_dependency";
    ChatFetchResponseType["InvalidStatefulMarker"] = "invalid_stateful_marker";
    ChatFetchResponseType["Success"] = "success";
})(ChatFetchResponseType || (exports.ChatFetchResponseType = ChatFetchResponseType = {}));
exports.RESPONSE_CONTAINED_NO_CHOICES = 'Response contained no choices.';
function getRateLimitMessage(fetchResult, copilotPlan) {
    if (fetchResult.type !== ChatFetchResponseType.RateLimited) {
        throw new Error('Expected RateLimited error');
    }
    const retryAfterString = fetchResult.retryAfter ? (0, time_1.secondsToHumanReadableTime)(fetchResult.retryAfter) : 'a moment';
    if (fetchResult.capiError?.code?.startsWith('agent_mode_limit_exceeded')) { // Rate limited in agent mode
        return l10n.t({
            message: 'Sorry, you have exceeded the agent mode rate limit. Please switch to ask mode and try again in {0}. [Learn More]({1})',
            args: [retryAfterString, 'https://aka.ms/github-copilot-rate-limit-error'],
            comment: [`{Locked=']({'}`]
        });
    }
    if (fetchResult.capiError?.code?.startsWith('model_overloaded') || fetchResult.capiError?.code?.startsWith('upstream_provider_rate_limit')) {
        if (fetchResult.isAuto) {
            return l10n.t({
                message: 'Sorry, the upstream model provider is currently experiencing high demand. Please try again in {0}. [Learn More]({1})',
                args: [retryAfterString, 'https://aka.ms/github-copilot-rate-limit-error'],
                comment: [`{Locked=']({'}`]
            });
        }
        return l10n.t({
            message: 'Sorry, the upstream model provider is currently experiencing high demand. Please try again in {0} or consider switching to Auto. [Learn More]({1})',
            args: [retryAfterString, 'https://aka.ms/github-copilot-rate-limit-error'],
            comment: [`{Locked=']({'}`]
        });
    }
    if (fetchResult.capiError?.code?.startsWith('user_global_rate_limited')) {
        if (copilotPlan === 'free' || copilotPlan === 'individual' || copilotPlan === 'individual_pro') {
            return l10n.t({
                message: 'You\'ve hit your session rate limit. Please upgrade your plan or wait {0} for your limit to reset. [Learn More]({1})',
                args: [retryAfterString, 'https://aka.ms/github-copilot-rate-limit-error'],
                comment: [`{Locked=']({'}`]
            });
        }
        return l10n.t({
            message: 'You\'ve hit your session rate limit. Please wait {0} for your limit to reset. [Learn More]({1})',
            args: [retryAfterString, 'https://aka.ms/github-copilot-rate-limit-error'],
            comment: [`{Locked=']({'}`]
        });
    }
    if (fetchResult.capiError?.code?.startsWith('user_weekly_rate_limited')) {
        if (fetchResult.retryAfter) {
            const resetDate = new Date(Date.now() + fetchResult.retryAfter * 1000);
            const resetDateString = resetDate.toLocaleString(undefined, { year: 'numeric', month: 'long', day: 'numeric', hour: 'numeric', minute: '2-digit' });
            if (fetchResult.isAuto) {
                return l10n.t({
                    message: 'You\'ve reached your weekly rate limit. Please wait for your limit to reset on {0}. [Learn More]({1})',
                    args: [resetDateString, 'https://aka.ms/github-copilot-rate-limit-error'],
                    comment: [`{Locked=']({'}`]
                });
            }
            return l10n.t({
                message: 'You\'ve reached your weekly rate limit. Please switch to the Auto model to continue working or wait for your limit to reset on {0}. [Learn More]({1})',
                args: [resetDateString, 'https://aka.ms/github-copilot-rate-limit-error'],
                comment: [`{Locked=']({'}`]
            });
        }
        if (fetchResult.isAuto) {
            return l10n.t({
                message: 'You\'ve reached your weekly rate limit. Please wait {0} for your limit to reset. [Learn More]({1})',
                args: [retryAfterString, 'https://aka.ms/github-copilot-rate-limit-error'],
                comment: [`{Locked=']({'}`]
            });
        }
        return l10n.t({
            message: 'You\'ve reached your weekly rate limit. Please switch to the Auto model to continue working or wait {0} for your limit to reset. [Learn More]({1})',
            args: [retryAfterString, 'https://aka.ms/github-copilot-rate-limit-error'],
            comment: [`{Locked=']({'}`]
        });
    }
    if (fetchResult.capiError?.code?.startsWith('user_model_rate_limited')) {
        if (fetchResult.isAuto) {
            return l10n.t({
                message: 'You\'ve hit the rate limit for this model. Please try again in {0}. [Learn More]({1})',
                args: [retryAfterString, 'https://aka.ms/github-copilot-rate-limit-error'],
                comment: [`{Locked=']({'}`]
            });
        }
        return l10n.t({
            message: 'You\'ve hit the rate limit for this model. Please try switching to Auto or try again in {0}. [Learn More]({1})',
            args: [retryAfterString, 'https://aka.ms/github-copilot-rate-limit-error'],
            comment: [`{Locked=']({'}`]
        });
    }
    if (fetchResult.capiError?.code?.startsWith('integration_rate_limited')) {
        return l10n.t({
            message: 'Sorry, GitHub Copilot Chat is currently experiencing high demand. Please try again in {0}. [Learn More]({1})',
            args: [retryAfterString, 'https://aka.ms/github-copilot-rate-limit-error'],
            comment: [`{Locked=']({'}`]
        });
    }
    if (fetchResult?.capiError?.code && fetchResult?.capiError?.message) {
        if (fetchResult.isAuto) {
            return l10n.t({
                message: 'Sorry, you have been rate-limited. Please wait {0} before trying again. [Learn More]({1})\n\nServer Error: {2}\nError Code: {3}',
                args: [retryAfterString, 'https://aka.ms/github-copilot-rate-limit-error', fetchResult.capiError.message, fetchResult.capiError.code],
                comment: [`{Locked=']({'}`]
            });
        }
        return l10n.t({
            message: 'Sorry, you have been rate-limited. Please wait {0} before trying again or consider switching to Auto. [Learn More]({1})\n\nServer Error: {2}\nError Code: {3}',
            args: [retryAfterString, 'https://aka.ms/github-copilot-rate-limit-error', fetchResult.capiError.message, fetchResult.capiError.code],
            comment: [`{Locked=']({'}`]
        });
    }
    if (fetchResult.isAuto) {
        return l10n.t({
            message: 'Sorry, your request was rate-limited. Please wait {0} before trying again. [Learn More]({1})',
            args: [retryAfterString, 'https://aka.ms/github-copilot-rate-limit-error'],
            comment: [`{Locked=']({'}`]
        });
    }
    return l10n.t({
        message: 'Sorry, your request was rate-limited. Please wait {0} before trying again or consider switching to Auto. [Learn More]({1})',
        args: [retryAfterString, 'https://aka.ms/github-copilot-rate-limit-error'],
        comment: [`{Locked=']({'}`]
    });
}
function getQuotaMessageForPlan(copilotPlan, isUsageBasedBilling, quotaResetDate) {
    const resetDateString = quotaResetDate
        ? new Date(quotaResetDate).toLocaleString(undefined, { year: 'numeric', month: 'long', day: 'numeric', hour: 'numeric', minute: '2-digit' })
        : undefined;
    if (isUsageBasedBilling) {
        switch (copilotPlan) {
            case 'free':
                return resetDateString
                    ? l10n.t(`You've reached your monthly credit limit. Upgrade to Copilot Pro or wait until your credits reset on {0}.`, resetDateString)
                    : l10n.t(`You've reached your monthly credit limit. Upgrade to Copilot Pro or wait for your credits to reset.`);
            case 'individual':
                return resetDateString
                    ? l10n.t(`You've reached your monthly credit limit. Please enable additional paid credits, upgrade to Copilot Pro+, or wait until your credits reset on {0}.`, resetDateString)
                    : l10n.t(`You've reached your monthly credit limit. Please enable additional paid credits, upgrade to Copilot Pro+, or wait for your credits to reset.`);
            case 'individual_pro':
            case 'individual_max':
                return resetDateString
                    ? l10n.t(`You've reached your monthly credit limit. Please enable additional paid credits or wait until your credits reset on {0}.`, resetDateString)
                    : l10n.t(`You've reached your monthly credit limit. Please enable additional paid credits or wait for your credits to reset.`);
            case 'business':
            case 'enterprise':
                return resetDateString
                    ? l10n.t(`You've reached your credit limit. To continue working, please contact your organization's Copilot admin or wait until your credits reset on {0}.`, resetDateString)
                    : l10n.t(`You've reached your credit limit. To continue working, please contact your organization's Copilot admin or wait for your credits to reset.`);
            default:
                return resetDateString
                    ? l10n.t(`You've reached your credit limit. To continue working, switch to Auto. For additional paid credits, please reach out to your organization's Copilot admin or wait until your credits reset on {0}.`, resetDateString)
                    : l10n.t(`You've reached your credit limit. To continue working, switch to Auto. For additional paid credits, please reach out to your organization's Copilot admin or wait for your credits to reset.`);
        }
    }
    switch (copilotPlan) {
        case 'free':
            return l10n.t(`You've reached your monthly chat messages quota. Upgrade to Copilot Pro or wait for your allowance to renew.`);
        case 'individual':
            return l10n.t(`You've exhausted your premium model quota. Please enable additional paid premium requests, upgrade to Copilot Pro+, or wait for your allowance to renew.`);
        case 'individual_pro':
        case 'individual_max':
            return l10n.t(`You've exhausted your premium model quota. Please enable additional paid premium requests or wait for your allowance to renew.`);
        case 'business':
        case 'enterprise':
            return l10n.t(`You've exhausted your credits. To continue working, please contact your organization's Copilot admin or wait for your allowance to renew.`);
        default:
            return l10n.t(`You've exhausted your premium model quota. To continue working, switch to Auto. For additional paid premium requests, please reach out to your organization's Copilot admin or wait for your allowance to renew.`);
    }
}
function getQuotaHitMessage(fetchResult, copilotPlan, isUsageBasedBilling, quotaResetDate) {
    if (fetchResult.type !== ChatFetchResponseType.QuotaExceeded) {
        throw new Error('Expected QuotaExceeded error');
    }
    if (fetchResult.capiError?.code === 'free_quota_exceeded') {
        fetchResult.capiError.code = 'quota_exceeded'; // Remap this to the generic quota code so we get per plan handling
    }
    if (fetchResult.capiError?.code === 'quota_exceeded') {
        return getQuotaMessageForPlan(copilotPlan, isUsageBasedBilling, quotaResetDate);
    }
    else if (fetchResult.capiError?.code === 'overage_limit_reached') {
        return l10n.t({
            message: 'You cannot accrue additional premium requests at this time. Please contact [GitHub Support]({0}) to continue using Copilot.',
            args: ['https://support.github.com/contact'],
            comment: [`{Locked=']({'}`]
        });
    }
    else if (fetchResult.capiError?.code === 'billing_not_configured' && fetchResult.capiError?.message) {
        return fetchResult.capiError.message;
    }
    else if (fetchResult.capiError?.code && fetchResult.capiError?.message) {
        return l10n.t({
            message: 'Quota Exceeded\n\nServer Error: {0}\nError Code: {1}',
            args: [fetchResult.capiError.message, fetchResult.capiError.code],
            comment: ''
        });
    }
    else {
        return l10n.t('Quota Exceeded');
    }
}
function getErrorDetailsFromChatFetchError(fetchResult, copilotPlan, gitHubOutageStatus, isUsageBasedBilling, quotaResetDate) {
    return { code: fetchResult.type, ...getErrorDetailsFromChatFetchErrorInner(fetchResult, copilotPlan, gitHubOutageStatus, isUsageBasedBilling, quotaResetDate) };
}
function getErrorDetailsFromChatFetchErrorInner(fetchResult, copilotPlan, gitHubOutageStatus, isUsageBasedBilling, quotaResetDate) {
    let details;
    switch (fetchResult.type) {
        case ChatFetchResponseType.OffTopic:
            details = { message: l10n.t('Sorry, but I can only assist with programming related questions.') };
            break;
        case ChatFetchResponseType.Canceled:
            details = exports.CanceledMessage;
            break;
        case ChatFetchResponseType.RateLimited:
            details = {
                message: getRateLimitMessage(fetchResult, copilotPlan),
                level: vscodeTypesShim_1.ChatErrorLevel.Info,
                isRateLimited: true
            };
            break;
        case ChatFetchResponseType.QuotaExceeded:
            details = {
                message: getQuotaHitMessage(fetchResult, copilotPlan, isUsageBasedBilling, quotaResetDate),
                isQuotaExceeded: true
            };
            break;
        case ChatFetchResponseType.BadRequest:
        case ChatFetchResponseType.Failed:
            details = fetchResult.serverRequestId
                ? { message: l10n.t(`Sorry, your request failed. Please try again.\n\nCopilot Request id: {0}\n\nGH Request Id: {1}\n\nReason: {2}`, fetchResult.requestId, fetchResult.serverRequestId, fetchResult.reason) }
                : { message: l10n.t(`Sorry, your request failed. Please try again.\n\nCopilot Request id: {0}\n\nReason: {1}`, fetchResult.requestId, fetchResult.reason) };
            break;
        case ChatFetchResponseType.NetworkError:
            details = { message: l10n.t(`Sorry, there was a network error. Please try again later. Request id: {0}\n\nReason: {1}`, fetchResult.requestId, fetchResult.reason) };
            break;
        case ChatFetchResponseType.Filtered:
        case ChatFetchResponseType.PromptFiltered:
            details = {
                message: getFilteredMessage(fetchResult.category),
                responseIsFiltered: true,
                level: vscodeTypesShim_1.ChatErrorLevel.Info,
            };
            break;
        case ChatFetchResponseType.AgentUnauthorized:
            details = { message: l10n.t(`Sorry, something went wrong.`) };
            break;
        case ChatFetchResponseType.AgentFailedDependency:
            details = { message: fetchResult.reason };
            break;
        case ChatFetchResponseType.Length:
            details = { message: l10n.t(`Sorry, the response hit the length limit. Please rephrase your prompt.`) };
            break;
        case ChatFetchResponseType.NotFound:
            details = { message: l10n.t('Sorry, the resource was not found.') };
            break;
        case ChatFetchResponseType.Unknown:
            details = { message: l10n.t(`Sorry, no response was returned.`) };
            break;
        case ChatFetchResponseType.ExtensionBlocked:
            details = { message: l10n.t(`Sorry, something went wrong.`) };
            break;
        case ChatFetchResponseType.InvalidStatefulMarker:
            // should be unreachable, retried within the endpoint
            details = { message: l10n.t(`Your chat session state is invalid, please start a new chat.`) };
            break;
    }
    if (gitHubOutageStatus !== 0 /* GitHubOutageStatus.None */) {
        const outageMsg = l10n.t({
            message: 'Note: GitHub is currently experiencing a service disruption. This may be affecting Copilot. Check [GitHub Status]({0}) for details.',
            args: ['https://www.githubstatus.com'],
            comment: [`{Locked=']({'}`]
        });
        details = { ...details, message: `${details.message}\n\n${outageMsg}` };
    }
    return details;
}
function getFilteredMessage(category, supportsMarkdown = true) {
    switch (category) {
        case openai_1.FilterReason.Copyright:
            if (supportsMarkdown) {
                return l10n.t({
                    message: `Sorry, the response matched public code so it was blocked. Please rephrase your prompt. [Learn more](https://aka.ms/copilot-chat-filtered-docs).`,
                    comment: [`{Locked='](https://aka.ms/copilot-chat-filtered-docs)'}`]
                });
            }
            else {
                return l10n.t(`Sorry, the response matched public code so it was blocked. Please rephrase your prompt.`);
            }
        case openai_1.FilterReason.Prompt:
            if (supportsMarkdown) {
                return l10n.t({
                    message: `Sorry, your prompt was filtered by the Responsible AI Service. Please rephrase your prompt and try again. [Learn more](https://aka.ms/copilot-chat-filtered-docs).`,
                    comment: [`{Locked='](https://aka.ms/copilot-chat-filtered-docs)'}`]
                });
            }
            else {
                return l10n.t(`Sorry, your prompt was filtered by the Responsible AI Service. Please rephrase your prompt and try again.`);
            }
        default:
            if (supportsMarkdown) {
                return l10n.t({
                    message: `Sorry, the response was filtered by the Responsible AI Service. Please rephrase your prompt and try again. [Learn more](https://aka.ms/copilot-chat-filtered-docs).`,
                    comment: [`{Locked='](https://aka.ms/copilot-chat-filtered-docs)'}`]
                });
            }
            else {
                return l10n.t(`Sorry, the response was filtered by the Responsible AI Service. Please rephrase your prompt and try again.`);
            }
    }
}
/**
 * Not localized because it's used in the same way that the CancellationError name is used.
 */
exports.CanceledMessage = { message: 'Canceled' };
exports.CanceledResult = { errorDetails: exports.CanceledMessage, };
//# sourceMappingURL=commonTypes.js.map