1
>
/*---------------------------------------------------------------------------------------------
chatErrorMessages.ts
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 { localize } from '../../../../nls.js';
7
>
import type { ErrorInfo } from '../../../../platform/agentHost/common/state/protocol/state.js';
8
>
import { ChatEntitlement } from '../../../services/chat/common/chatEntitlementService.js';
9
>
import { ChatErrorLevel, IChatResponseErrorDetails } from './chatService/chatService.js';
10
>
11
>
/**
12
>
* Mirror of the Copilot extension's `ChatFetchResponseType` (see
13
>
* `extensions/copilot/src/platform/chat/common/commonTypes.ts`). These string
14
>
* values are forwarded verbatim from the agent host harnesses (Copilot CLI,
15
>
* Claude, Codex) over `_meta`, so they MUST stay in sync with the extension.
16
>
*/
17
>
export const enum ChatFetchResponseType {
18
>
OffTopic = 'offTopic',
19
>
Canceled = 'canceled',
20
>
Filtered = 'filtered',
21
>
FilteredRetry = 'filteredRetry',
22
>
PromptFiltered = 'promptFiltered',
23
>
Length = 'length',
24
>
RateLimited = 'rateLimited',
25
>
QuotaExceeded = 'quotaExceeded',
26
>
ExtensionBlocked = 'extensionBlocked',
27
>
BadRequest = 'badRequest',
28
>
NotFound = 'notFound',
29
>
Failed = 'failed',
30
>
Unknown = 'unknown',
31
>
NetworkError = 'networkError',
32
>
AgentUnauthorized = 'agent_unauthorized',
33
>
AgentFailedDependency = 'agent_failed_dependency',
34
>
InvalidStatefulMarker = 'invalid_stateful_marker',
35
>
Success = 'success'
36
>
}
37
>
38
>
/**
39
>
* Mirror of the Copilot extension's `FilterReason` (see
40
>
* `extensions/copilot/src/platform/networking/common/openai.ts`).
41
>
*/
42
>
export const enum FilterReason {
43
>
Hate = 'hate',
44
>
SelfHarm = 'self_harm',
45
>
Sexual = 'sexual',
46
>
Violence = 'violence',
47
>
Copyright = 'snippy',
48
>
Prompt = 'prompt'
49
>
}
50
>
51
>
/**
52
>
* Raw error payload forwarded from an agent host harness. This is the
53
>
* serialized `ChatFetchError` from the Copilot extension. Because it crosses
54
>
* the extension/core boundary as untyped JSON inside `_meta`, every field is
55
>
* optional and consumers type-cast based on `type`.
56
>
*/
57
>
export interface IChatFetchErrorPayload {
58
>
readonly type: ChatFetchResponseType | string;
59
>
readonly reason?: string;
60
>
readonly reasonDetail?: string;
61
>
readonly requestId?: string;
62
>
readonly serverRequestId?: string | undefined;
63
>
readonly category?: FilterReason | string;
64
>
readonly retryAfter?: number;
65
>
readonly rateLimitKey?: string;
66
>
readonly isAuto?: boolean;
67
>
readonly capiError?: { code?: string; message?: string };
68
>
}
69
>
70
>
/**
71
>
* The full forwarded chat error payload, including the user-context fields that
72
>
* the extension would normally read from the Copilot token. This is the value
73
>
* placed at `_meta.chatError` by the harnesses.
74
>
*/
75
>
export interface IForwardedChatError {
76
>
readonly fetchError: IChatFetchErrorPayload;
77
>
readonly copilotPlan?: string;
78
>
readonly isUsageBasedBilling?: boolean;
79
>
readonly quotaResetDate?: string;
80
>
}
81
>
82
>
const RATE_LIMIT_LEARN_MORE_URL = 'https://aka.ms/github-copilot-rate-limit-error';
83
>
const FILTERED_DOCS_URL = 'https://aka.ms/copilot-chat-filtered-docs';
84
>
const GITHUB_SUPPORT_URL = 'https://support.github.com/contact';
85
>
86
>
/**
87
>
* Localized "canceled" message. Mirrors the extension's `CanceledMessage`,
88
>
* which is intentionally not localized there; we localize it in core.
89
>
*/
90
>
const CanceledMessage: IChatResponseErrorDetails = { message: localize('chatError.canceled', "Canceled") };
91
>
92
>
/**
93
>
* Converts a number of seconds into a human readable, localized string like
94
>
* "6 hours 50 minutes". Based on the Copilot extension's
95
>
* `secondsToHumanReadableTime` (`extensions/copilot/src/util/common/time.ts`),
96
>
* but the unit fragments are externalized so they translate in non-English
97
>
* locales.
98
>
*/
99
function secondsToHumanReadableTime(seconds: number): string {
100
if (seconds < 90) {