chatErrorMessages.ts ×10

Frontier kind: Code frontier

unlabeled · c_a7d02b062062

18 tests · 20717 LOC · 110 files · introduces 0 tests · 149 LOC · 1 file

Introduces — evidence that enters the hierarchy at this concept

Code
10 ranges149 lines · 1 files
Tests
0 tests

Contains — complete concept membership

All code (extent)
2371 ranges20717 lines · 110 files · Browse complete extent
All tests (intent)
18 testsBrowse complete intent

Neighbourhood graph

The orange circle is the focus. Violet and green circles are every ancestor and descendant, broader and narrower, at any distance; blue squares and pink diamonds are the introduced files and exact introduced tests of every visible concept, not only the focus's. Arrows point from broader to narrower concepts and bridge only concepts omitted from this view. Undirected links show source or test introduction. Concept and file size follows LOC; exact test nodes use test-count units.

Introduced files, introduced tests, and structurally relevant concept specialization

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the native relationship evidence on this page.

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the native relationship evidence on this page while the interactive map is unavailable.

Native relationship evidence

Every exact file and test below is linked only from the concept that introduces it.

Introduced tests

Every collected test enters the hierarchy at exactly one concept.

No tests are introduced at this concept. Its intent tests are introduced by other concepts.

Introduced code

Every collected source range enters the hierarchy at exactly one concept.

1 file ranked by introduced lines: 149 introduced LOC across 10 ranges. Expand a file to inspect source; the > gutter marks introduced lines.

src/vs/workbench/contrib/chat/common/chatErrorMessages.ts 149 introduced LOC · 10 ranges

Open complete file

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) {
115 return localize('chatError.duration.hours', "{0} hours", hours);
116 }
118 function getRateLimitMessage(fetchError: IChatFetchErrorPayload, copilotPlan: string | undefined): string {
119 const retryAfterString = fetchError.retryAfter ? secondsToHumanReadableTime(fetchError.retryAfter) : localize('chatError.aMoment', "a moment");
170 return localize({ key: 'chatError.rateLimit.generic', comment: [`{Locked=']({'}`] }, "Sorry, your request was rate-limited. Please wait {0} before trying again or consider switching to Auto. [Learn More]({1})", retryAfterString, RATE_LIMIT_LEARN_MORE_URL);
171 }
173 > export function getQuotaMessageForPlan(copilotPlan: string | undefined, isUsageBasedBilling?: boolean, quotaResetDate?: string): string {
174 const resetDateString = quotaResetDate
175 ? new Date(quotaResetDate).toLocaleString(undefined, { year: 'numeric', month: 'long', day: 'numeric', hour: 'numeric', minute: '2-digit' })
224 }
225 }
227 function getQuotaHitMessage(fetchError: IChatFetchErrorPayload, copilotPlan: string | undefined, isUsageBasedBilling?: boolean, quotaResetDate?: string): string {
228 let code = fetchError.capiError?.code;
244 }
245 }
247 > export function getFilteredMessage(category: FilterReason | string, supportsMarkdown: boolean = true): string {
248 switch (category) {
249 case FilterReason.Copyright:
264 }
265 }
267 > /**
268 > * Builds the user-facing {@link IChatResponseErrorDetails} from a forwarded raw
269 > * chat fetch error. This is the core analog of the Copilot extension's
270 > * `getErrorDetailsFromChatFetchError`. Unlike the extension, core has no
271 > * access to the GitHub outage status, so the outage note is never appended
272 > * (assume no outage).
273 > */
274 > export function getChatErrorDetailsFromFetchError(fetchError: IChatFetchErrorPayload, copilotPlan: string | undefined, isUsageBasedBilling?: boolean, quotaResetDate?: string): IChatResponseErrorDetails {
275 return { code: fetchError.type, ...getChatErrorDetailsInner(fetchError, copilotPlan, isUsageBasedBilling, quotaResetDate) };
276 }
278 function getChatErrorDetailsInner(fetchError: IChatFetchErrorPayload, copilotPlan: string | undefined, isUsageBasedBilling?: boolean, quotaResetDate?: string): IChatResponseErrorDetails {
279 const requestId = fetchError.requestId ?? '';
329 }
330 }
332 > /**
333 > * Type guard for the forwarded chat error payload placed at `_meta.chatError`
334 > * by the agent host harnesses.
335 > */
336 function isForwardedChatError(value: unknown): value is IForwardedChatError {
337 return !!value
342 && typeof (value as IForwardedChatError).fetchError.type === 'string';
343 }
345 > /**
346 > * Extracts and formats {@link IChatResponseErrorDetails} from the `_meta`
347 > * forwarded by an agent host harness, if present. Returns `undefined` when no
348 > * forwarded chat error is found so callers can fall back to their existing
349 > * error handling.
350 > *
351 > * The agent host does not know the signed-in user's plan, so callers in core
352 > * pass an {@link IChatErrorContext} (resolved from `IChatEntitlementService`)
353 > * whose fields take precedence over the values forwarded in `_meta`.
354 > */
355 > export function getChatErrorDetailsFromMeta(error: ErrorInfo | undefined, context?: IChatErrorContext): IChatResponseErrorDetails | undefined {
356 const meta = error?._meta;
357 const chatError = meta?.chatError;
366 );
367 }
369 > /**
370 > * User-context overrides for {@link getChatErrorDetailsFromMeta}. When a field
371 > * is set it takes precedence over the value forwarded by the agent host. Core
372 > * resolves these from `IChatEntitlementService`.
373 > */
374 > export interface IChatErrorContext {
375 > readonly copilotPlan?: string;
376 > readonly isUsageBasedBilling?: boolean;
377 > readonly quotaResetDate?: string;
378 > }
379 >
380 > /**
381 > * Maps a core {@link ChatEntitlement} to the Copilot plan string understood by
382 > * the quota/rate-limit message helpers (mirrors the Copilot extension's
383 > * `CopilotToken.copilotPlan` values).
384 > */
385 > export function getCopilotPlanFromEntitlement(entitlement: ChatEntitlement): string | undefined {
386 switch (entitlement) {
387 case ChatEntitlement.Free: