@code-yeongyu/senpi 2026.9.28-4 → 2026.9.28-6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +35 -0
- package/dist/bundle/chunks/{anthropic-messages-W2XLZZ35.js → anthropic-messages-QOQJCY3F.js} +2 -2
- package/dist/bundle/chunks/{app-server-command-7LBMB34E.js → app-server-command-5WCSZ4A5.js} +1 -1
- package/dist/bundle/chunks/{azure-openai-responses-WNELC744.js → azure-openai-responses-ZAJSIEAV.js} +1 -1
- package/dist/bundle/chunks/{chunk-C5FRNOUP.js → chunk-3HCYHGK2.js} +1 -1
- package/dist/bundle/chunks/{chunk-UTGOAXS6.js → chunk-4BDFNRBE.js} +1 -1
- package/dist/bundle/chunks/chunk-7X4ZMME4.js +2 -0
- package/dist/bundle/chunks/{chunk-7FIDRH2I.js → chunk-AIM2YESB.js} +1 -1
- package/dist/bundle/chunks/{chunk-RKIAHDIB.js → chunk-AWPLVQ4K.js} +17 -16
- package/dist/bundle/chunks/chunk-BTMM2C5X.js +2 -0
- package/dist/bundle/chunks/{chunk-3JX3X45G.js → chunk-CXVI2YV7.js} +1 -1
- package/dist/bundle/chunks/{chunk-O3D7S64D.js → chunk-DKP4BUY5.js} +1 -1
- package/dist/bundle/chunks/{chunk-4BK43Q6Z.js → chunk-DOEV7ITR.js} +1 -1
- package/dist/bundle/chunks/chunk-E5F5SVZF.js +5 -0
- package/dist/bundle/chunks/chunk-FILEUW2D.js +3 -0
- package/dist/bundle/chunks/{chunk-OLQI7DUR.js → chunk-HS2LJYBI.js} +1 -1
- package/dist/bundle/chunks/chunk-J5TMX734.js +2 -0
- package/dist/bundle/chunks/{chunk-TYN6XEJL.js → chunk-JCMOKXWG.js} +1 -1
- package/dist/bundle/chunks/{chunk-KAFTHZWC.js → chunk-JK5LVAOU.js} +1 -1
- package/dist/bundle/chunks/{chunk-YHT3LLIA.js → chunk-K3SEG6TJ.js} +1 -1
- package/dist/bundle/chunks/{chunk-ZORNIKXN.js → chunk-KDZAVHA7.js} +1 -1
- package/dist/bundle/chunks/{chunk-HVFSRIJI.js → chunk-KR2TJOGO.js} +1 -1
- package/dist/bundle/chunks/chunk-KRNXUTZJ.js +2 -0
- package/dist/bundle/chunks/chunk-SQUUL72H.js +2 -0
- package/dist/bundle/chunks/chunk-TJV2LFKM.js +2 -0
- package/dist/bundle/chunks/{chunk-OH4ONX6R.js → chunk-TOCWAEQB.js} +4 -4
- package/dist/bundle/chunks/{chunk-6WDC7AEV.js → chunk-UDTWLXSQ.js} +1 -1
- package/dist/bundle/chunks/{chunk-WQO75X37.js → chunk-VGJESQOS.js} +1 -1
- package/dist/bundle/chunks/{chunk-3JR7GC6P.js → chunk-VW3QZSX3.js} +1 -1
- package/dist/bundle/chunks/chunk-WXN35RD7.js +8 -0
- package/dist/bundle/chunks/cli-main-IBG7ONGV.js +3 -0
- package/dist/bundle/chunks/github-copilot.js +1 -1
- package/dist/bundle/chunks/{google-generative-ai-FUULH4UE.js → google-generative-ai-C4YRAMFN.js} +1 -1
- package/dist/bundle/chunks/{google-vertex-PLXS45T4.js → google-vertex-4ZM6HGYI.js} +1 -1
- package/dist/bundle/chunks/help-fast-path-MWSJXPH6.js +2 -0
- package/dist/bundle/chunks/host-command-MTK5WOPH.js +2 -0
- package/dist/bundle/chunks/host-lifecycle-7IJCAHHL.js +3 -0
- package/dist/bundle/chunks/host-lifecycle.js +3 -3
- package/dist/bundle/chunks/interactive-host-runtime-FWMZWK6G.js +4 -0
- package/dist/bundle/chunks/interactive-mode-XUJM4MCN.js +2 -0
- package/dist/bundle/chunks/{mistral-conversations-G5CGRCMV.js → mistral-conversations-7SROSYOE.js} +1 -1
- package/dist/bundle/chunks/{multi-session-host-GJCSLVES.js → multi-session-host-7KCH3HUA.js} +1 -1
- package/dist/bundle/chunks/{openai-codex-responses-4JOIWFJF.js → openai-codex-responses-2ZNOPGE4.js} +1 -1
- package/dist/bundle/chunks/{openai-completions-XDHNDF3Z.js → openai-completions-BHE6TMUP.js} +1 -1
- package/dist/bundle/chunks/{openai-images-I7DR7ERP.js → openai-images-AEFVNUTL.js} +1 -1
- package/dist/bundle/chunks/openai-responses-OGQ5QORF.js +2 -0
- package/dist/bundle/chunks/{openrouter-images-IPNDRK6C.js → openrouter-images-N4NZJKSF.js} +1 -1
- package/dist/bundle/chunks/{package-manager-cli-E2SGFMXL.js → package-manager-cli-SNVT3VKW.js} +1 -1
- package/dist/bundle/chunks/rotation-stream-Q2EVDMUU.js +2 -0
- package/dist/bundle/chunks/rpc-mode-VYB2Q43O.js +2 -0
- package/dist/bundle/chunks/{schedule-command-UKBZQK3Y.js → schedule-command-JQ65HF2K.js} +1 -1
- package/dist/bundle/chunks/session-picker-DRM7AGPY.js +2 -0
- package/dist/bundle/chunks/session-worker.js +180 -178
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/core/credential-pool/rejected-token-retry.d.ts +24 -0
- package/dist/core/credential-pool/rejected-token-retry.d.ts.map +1 -0
- package/dist/core/credential-pool/rejected-token-retry.js +76 -0
- package/dist/core/credential-pool/rejected-token-retry.js.map +1 -0
- package/dist/core/credential-pool/rotation-events.d.ts +1 -0
- package/dist/core/credential-pool/rotation-events.d.ts.map +1 -1
- package/dist/core/credential-pool/rotation-events.js +4 -2
- package/dist/core/credential-pool/rotation-events.js.map +1 -1
- package/dist/core/extensions/builtin/btw/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/btw/index.js +3 -1
- package/dist/core/extensions/builtin/btw/index.js.map +1 -1
- package/dist/core/extensions/builtin/goal/agent-end-continuation.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/agent-end-continuation.js +13 -1
- package/dist/core/extensions/builtin/goal/agent-end-continuation.js.map +1 -1
- package/dist/core/extensions/builtin/goal/continuation-recovery.d.ts +8 -0
- package/dist/core/extensions/builtin/goal/continuation-recovery.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/continuation-recovery.js +22 -0
- package/dist/core/extensions/builtin/goal/continuation-recovery.js.map +1 -1
- package/dist/core/extensions/builtin/goal/terminal-provider-error.d.ts +11 -0
- package/dist/core/extensions/builtin/goal/terminal-provider-error.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/terminal-provider-error.js +31 -0
- package/dist/core/extensions/builtin/goal/terminal-provider-error.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/presets.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/presets.js +2 -1
- package/dist/core/extensions/builtin/prompt-preset/presets.js.map +1 -1
- package/dist/core/extensions/builtin/websearch/websearch/native.d.ts +1 -0
- package/dist/core/extensions/builtin/websearch/websearch/native.d.ts.map +1 -1
- package/dist/core/extensions/builtin/websearch/websearch/native.js +8 -1
- package/dist/core/extensions/builtin/websearch/websearch/native.js.map +1 -1
- package/dist/core/model-resolver.js +1 -1
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/model-runtime.d.ts +7 -0
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +34 -19
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/retry-fallback/cooldown.d.ts.map +1 -1
- package/dist/core/retry-fallback/cooldown.js +2 -1
- package/dist/core/retry-fallback/cooldown.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +13 -0
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/rpc/host-identity-env.d.ts +20 -0
- package/dist/modes/rpc/host-identity-env.d.ts.map +1 -0
- package/dist/modes/rpc/host-identity-env.js +20 -0
- package/dist/modes/rpc/host-identity-env.js.map +1 -0
- package/dist/modes/rpc/host-lifecycle.js +1 -1
- package/dist/modes/rpc/host-lifecycle.js.map +1 -1
- package/dist/modes/rpc/host-spawn-environment.js +1 -1
- package/dist/modes/rpc/host-spawn-environment.js.map +1 -1
- package/dist/modes/rpc/protocol-identity.d.ts +2 -11
- package/dist/modes/rpc/protocol-identity.d.ts.map +1 -1
- package/dist/modes/rpc/protocol-identity.js +2 -11
- package/dist/modes/rpc/protocol-identity.js.map +1 -1
- package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +24 -0
- package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
- package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
- package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js +8 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/github-copilot-endpoint.d.ts +19 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/github-copilot-endpoint.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/github-copilot-endpoint.js +48 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/github-copilot-endpoint.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/github-copilot-errors.d.ts +9 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/github-copilot-errors.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/github-copilot-errors.js +78 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/github-copilot-errors.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/github-copilot-headers.d.ts +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/github-copilot-headers.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/github-copilot-headers.js +3 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/github-copilot-headers.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js +8 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js +21 -2
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/helpers.d.ts +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/helpers.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/helpers.js +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/helpers.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/github-copilot-model-catalog.d.ts +7 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/github-copilot-model-catalog.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/github-copilot-model-catalog.js +46 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/github-copilot-model-catalog.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/github-copilot.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/github-copilot.js +24 -77
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/github-copilot.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/resolve.d.ts +6 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/resolve.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/resolve.js +6 -5
- package/node_modules/@earendil-works/pi-ai/dist/auth/resolve.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/types.d.ts +7 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/types.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/types.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/devin.models.d.ts +5 -3
- package/node_modules/@earendil-works/pi-ai/dist/providers/devin.models.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/devin.models.js +6 -5
- package/node_modules/@earendil-works/pi-ai/dist/providers/devin.models.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/github-copilot-limits.d.ts +11 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/github-copilot-limits.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/github-copilot-limits.js +65 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/github-copilot-limits.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/github-copilot.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/github-copilot.js +24 -3
- package/node_modules/@earendil-works/pi-ai/dist/providers/github-copilot.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/github-copilot-tool-limit.d.ts +10 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/github-copilot-tool-limit.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/github-copilot-tool-limit.js +75 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/github-copilot-tool-limit.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.js +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/retry.d.ts +3 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/retry.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js +15 -3
- package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/package.json +2 -2
- package/node_modules/@earendil-works/pi-pty/package.json +1 -1
- package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
- package/node_modules/@earendil-works/pi-tui/package.json +1 -1
- package/package.json +7 -7
- package/dist/bundle/chunks/chunk-2E2FN2VJ.js +0 -2
- package/dist/bundle/chunks/chunk-5LYDQMQY.js +0 -5
- package/dist/bundle/chunks/chunk-DM3AVOKA.js +0 -2
- package/dist/bundle/chunks/chunk-EDU27GXU.js +0 -2
- package/dist/bundle/chunks/chunk-HH3KJDWA.js +0 -2
- package/dist/bundle/chunks/chunk-NAIMNKNG.js +0 -2
- package/dist/bundle/chunks/chunk-PUWVIQW6.js +0 -2
- package/dist/bundle/chunks/chunk-S5Q3WPVR.js +0 -8
- package/dist/bundle/chunks/cli-main-LVTTAX7I.js +0 -3
- package/dist/bundle/chunks/help-fast-path-PCN7D4UN.js +0 -2
- package/dist/bundle/chunks/host-command-FETBGITW.js +0 -2
- package/dist/bundle/chunks/host-lifecycle-FW6LQ6SW.js +0 -3
- package/dist/bundle/chunks/interactive-host-runtime-7RUBGCMP.js +0 -4
- package/dist/bundle/chunks/interactive-mode-FDQ4N3JQ.js +0 -2
- package/dist/bundle/chunks/openai-responses-MQUMRQVY.js +0 -2
- package/dist/bundle/chunks/rotation-stream-3KJLEXQQ.js +0 -2
- package/dist/bundle/chunks/rpc-mode-435L7DOL.js +0 -2
- package/dist/bundle/chunks/session-picker-JHFPLMON.js +0 -2
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export declare const GITHUB_COPILOT_INDIVIDUAL_BASE_URL = "https://api.individual.githubcopilot.com";
|
|
2
|
+
export interface GitHubCopilotApiEndpoint {
|
|
3
|
+
readonly tid: string;
|
|
4
|
+
readonly url: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function githubCopilotTokenField(token: string, key: string): string | undefined;
|
|
7
|
+
export declare function githubCopilotBaseUrlFromToken(token: string): string | undefined;
|
|
8
|
+
export declare function parseGitHubCopilotApiEndpoint(value: unknown): string | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* The account's Copilot API base URL, in order: the token response's `endpoints.api` recorded for
|
|
11
|
+
* this exact token (matched by `tid`, so a pooled sibling account never borrows it), the token's
|
|
12
|
+
* `proxy-ep`, the GitHub Enterprise Server domain, then the individual host.
|
|
13
|
+
*/
|
|
14
|
+
export declare function resolveGitHubCopilotBaseUrl(input: {
|
|
15
|
+
token?: string;
|
|
16
|
+
apiEndpoint?: unknown;
|
|
17
|
+
enterpriseDomain?: string;
|
|
18
|
+
}): string;
|
|
19
|
+
//# sourceMappingURL=github-copilot-endpoint.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-copilot-endpoint.d.ts","sourceRoot":"","sources":["../../src/api/github-copilot-endpoint.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,kCAAkC,6CAA6C,CAAC;AAE7F,MAAM,WAAW,wBAAwB;IACxC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAMtF;AAED,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAG/E;AAED,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAShF;AASD;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC1B,GAAG,MAAM,CAOT"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// The Copilot API host is per account plan (individual, business, enterprise, data-residency
|
|
2
|
+
// tenants). A request sent to another plan's host is refused with `421 Misdirected Request`,
|
|
3
|
+
// so the host always comes from the account's own token; the individual host is a last resort.
|
|
4
|
+
export const GITHUB_COPILOT_INDIVIDUAL_BASE_URL = "https://api.individual.githubcopilot.com";
|
|
5
|
+
export function githubCopilotTokenField(token, key) {
|
|
6
|
+
for (const part of token.split(";")) {
|
|
7
|
+
const separator = part.indexOf("=");
|
|
8
|
+
if (separator > 0 && part.slice(0, separator) === key)
|
|
9
|
+
return part.slice(separator + 1) || undefined;
|
|
10
|
+
}
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
export function githubCopilotBaseUrlFromToken(token) {
|
|
14
|
+
const proxyHost = githubCopilotTokenField(token, "proxy-ep");
|
|
15
|
+
return proxyHost ? `https://${proxyHost.replace(/^proxy\./, "api.")}` : undefined;
|
|
16
|
+
}
|
|
17
|
+
export function parseGitHubCopilotApiEndpoint(value) {
|
|
18
|
+
if (typeof value !== "string")
|
|
19
|
+
return undefined;
|
|
20
|
+
try {
|
|
21
|
+
const url = new URL(value.trim());
|
|
22
|
+
if (url.protocol !== "https:" || !url.hostname || url.username || url.password)
|
|
23
|
+
return undefined;
|
|
24
|
+
return `${url.origin}${url.pathname.replace(/\/+$/, "")}`;
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function endpointForToken(endpoint, token) {
|
|
31
|
+
if (!token || typeof endpoint !== "object" || endpoint === null)
|
|
32
|
+
return undefined;
|
|
33
|
+
const tid = Reflect.get(endpoint, "tid");
|
|
34
|
+
const url = parseGitHubCopilotApiEndpoint(Reflect.get(endpoint, "url"));
|
|
35
|
+
return typeof tid === "string" && tid === githubCopilotTokenField(token, "tid") ? url : undefined;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* The account's Copilot API base URL, in order: the token response's `endpoints.api` recorded for
|
|
39
|
+
* this exact token (matched by `tid`, so a pooled sibling account never borrows it), the token's
|
|
40
|
+
* `proxy-ep`, the GitHub Enterprise Server domain, then the individual host.
|
|
41
|
+
*/
|
|
42
|
+
export function resolveGitHubCopilotBaseUrl(input) {
|
|
43
|
+
return (endpointForToken(input.apiEndpoint, input.token) ??
|
|
44
|
+
(input.token ? githubCopilotBaseUrlFromToken(input.token) : undefined) ??
|
|
45
|
+
(input.enterpriseDomain ? `https://copilot-api.${input.enterpriseDomain}` : undefined) ??
|
|
46
|
+
GITHUB_COPILOT_INDIVIDUAL_BASE_URL);
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=github-copilot-endpoint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-copilot-endpoint.js","sourceRoot":"","sources":["../../src/api/github-copilot-endpoint.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAC7F,6FAA6F;AAC7F,+FAA+F;AAE/F,MAAM,CAAC,MAAM,kCAAkC,GAAG,0CAA0C,CAAC;AAO7F,MAAM,UAAU,uBAAuB,CAAC,KAAa,EAAE,GAAW;IACjE,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACrC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACpC,IAAI,SAAS,GAAG,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,KAAK,GAAG;YAAE,OAAO,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,IAAI,SAAS,CAAC;IACtG,CAAC;IACD,OAAO,SAAS,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,6BAA6B,CAAC,KAAa;IAC1D,MAAM,SAAS,GAAG,uBAAuB,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;IAC7D,OAAO,SAAS,CAAC,CAAC,CAAC,WAAW,SAAS,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AACnF,CAAC;AAED,MAAM,UAAU,6BAA6B,CAAC,KAAc;IAC3D,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAChD,IAAI,CAAC;QACJ,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QAClC,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ;YAAE,OAAO,SAAS,CAAC;QACjG,OAAO,GAAG,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC;IAC3D,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,SAAS,CAAC;IAClB,CAAC;AACF,CAAC;AAED,SAAS,gBAAgB,CAAC,QAAiB,EAAE,KAAyB;IACrE,IAAI,CAAC,KAAK,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IAClF,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IACzC,MAAM,GAAG,GAAG,6BAA6B,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;IACxE,OAAO,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,uBAAuB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;AACnG,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,2BAA2B,CAAC,KAI3C;IACA,OAAO,CACN,gBAAgB,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,KAAK,CAAC;QAChD,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,6BAA6B,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACtE,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,uBAAuB,KAAK,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;QACtF,kCAAkC,CAClC,CAAC;AACH,CAAC","sourcesContent":["// The Copilot API host is per account plan (individual, business, enterprise, data-residency\n// tenants). A request sent to another plan's host is refused with `421 Misdirected Request`,\n// so the host always comes from the account's own token; the individual host is a last resort.\n\nexport const GITHUB_COPILOT_INDIVIDUAL_BASE_URL = \"https://api.individual.githubcopilot.com\";\n\nexport interface GitHubCopilotApiEndpoint {\n\treadonly tid: string;\n\treadonly url: string;\n}\n\nexport function githubCopilotTokenField(token: string, key: string): string | undefined {\n\tfor (const part of token.split(\";\")) {\n\t\tconst separator = part.indexOf(\"=\");\n\t\tif (separator > 0 && part.slice(0, separator) === key) return part.slice(separator + 1) || undefined;\n\t}\n\treturn undefined;\n}\n\nexport function githubCopilotBaseUrlFromToken(token: string): string | undefined {\n\tconst proxyHost = githubCopilotTokenField(token, \"proxy-ep\");\n\treturn proxyHost ? `https://${proxyHost.replace(/^proxy\\./, \"api.\")}` : undefined;\n}\n\nexport function parseGitHubCopilotApiEndpoint(value: unknown): string | undefined {\n\tif (typeof value !== \"string\") return undefined;\n\ttry {\n\t\tconst url = new URL(value.trim());\n\t\tif (url.protocol !== \"https:\" || !url.hostname || url.username || url.password) return undefined;\n\t\treturn `${url.origin}${url.pathname.replace(/\\/+$/, \"\")}`;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction endpointForToken(endpoint: unknown, token: string | undefined): string | undefined {\n\tif (!token || typeof endpoint !== \"object\" || endpoint === null) return undefined;\n\tconst tid = Reflect.get(endpoint, \"tid\");\n\tconst url = parseGitHubCopilotApiEndpoint(Reflect.get(endpoint, \"url\"));\n\treturn typeof tid === \"string\" && tid === githubCopilotTokenField(token, \"tid\") ? url : undefined;\n}\n\n/**\n * The account's Copilot API base URL, in order: the token response's `endpoints.api` recorded for\n * this exact token (matched by `tid`, so a pooled sibling account never borrows it), the token's\n * `proxy-ep`, the GitHub Enterprise Server domain, then the individual host.\n */\nexport function resolveGitHubCopilotBaseUrl(input: {\n\ttoken?: string;\n\tapiEndpoint?: unknown;\n\tenterpriseDomain?: string;\n}): string {\n\treturn (\n\t\tendpointForToken(input.apiEndpoint, input.token) ??\n\t\t(input.token ? githubCopilotBaseUrlFromToken(input.token) : undefined) ??\n\t\t(input.enterpriseDomain ? `https://copilot-api.${input.enterpriseDomain}` : undefined) ??\n\t\tGITHUB_COPILOT_INDIVIDUAL_BASE_URL\n\t);\n}\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A plain-language note for a GitHub Copilot HTTP failure that the SDK message alone
|
|
3
|
+
* leaves opaque (`403 status code (no body)`): which refusal it is, where to look, and
|
|
4
|
+
* the GitHub request id support needs. `undefined` for failures the message already
|
|
5
|
+
* explains. The wording avoids credential words so pool classification is unchanged.
|
|
6
|
+
*/
|
|
7
|
+
export declare function describeGitHubCopilotFailure(error: unknown): string | undefined;
|
|
8
|
+
export declare function withGitHubCopilotFailureNote(message: string, provider: string, error: unknown): string;
|
|
9
|
+
//# sourceMappingURL=github-copilot-errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-copilot-errors.d.ts","sourceRoot":"","sources":["../../src/api/github-copilot-errors.ts"],"names":[],"mappings":"AA0CA;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAkB/E;AAED,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAItG"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { normalizeProviderError } from "../utils/error-body.js";
|
|
2
|
+
import { formatProviderRequestId } from "../utils/retry.js";
|
|
3
|
+
// Codes VS Code Copilot Chat treats as quota exhaustion (extensions/copilot chatMLFetcher.ts).
|
|
4
|
+
const QUOTA_CODES = new Set([
|
|
5
|
+
"quota_exceeded",
|
|
6
|
+
"free_quota_exceeded",
|
|
7
|
+
"overage_limit_reached",
|
|
8
|
+
"billing_not_configured",
|
|
9
|
+
"additional_spend_limit_reached",
|
|
10
|
+
]);
|
|
11
|
+
function headerValue(headers, name) {
|
|
12
|
+
if (headers instanceof Headers)
|
|
13
|
+
return headers.get(name) ?? undefined;
|
|
14
|
+
if (typeof headers !== "object" || headers === null)
|
|
15
|
+
return undefined;
|
|
16
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
17
|
+
if (key.toLowerCase() === name && typeof value === "string")
|
|
18
|
+
return value;
|
|
19
|
+
}
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
function errorCode(body) {
|
|
23
|
+
if (body === undefined)
|
|
24
|
+
return undefined;
|
|
25
|
+
try {
|
|
26
|
+
const parsed = JSON.parse(body);
|
|
27
|
+
if (typeof parsed !== "object" || parsed === null)
|
|
28
|
+
return undefined;
|
|
29
|
+
const nested = Reflect.get(parsed, "error");
|
|
30
|
+
const code = typeof nested === "object" && nested !== null ? Reflect.get(nested, "code") : Reflect.get(parsed, "code");
|
|
31
|
+
return typeof code === "string" ? code : undefined;
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function isQuotaFailure(status, body, limitKey) {
|
|
38
|
+
const code = errorCode(body);
|
|
39
|
+
if (code !== undefined && QUOTA_CODES.has(code))
|
|
40
|
+
return true;
|
|
41
|
+
if (status === 402)
|
|
42
|
+
return true;
|
|
43
|
+
return status === 429 && (limitKey?.includes("quota") === true || /quota exceeded/i.test(body ?? ""));
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* A plain-language note for a GitHub Copilot HTTP failure that the SDK message alone
|
|
47
|
+
* leaves opaque (`403 status code (no body)`): which refusal it is, where to look, and
|
|
48
|
+
* the GitHub request id support needs. `undefined` for failures the message already
|
|
49
|
+
* explains. The wording avoids credential words so pool classification is unchanged.
|
|
50
|
+
*/
|
|
51
|
+
export function describeGitHubCopilotFailure(error) {
|
|
52
|
+
if (!(error instanceof Error))
|
|
53
|
+
return undefined;
|
|
54
|
+
const { status, body } = normalizeProviderError(error);
|
|
55
|
+
if (status === undefined)
|
|
56
|
+
return undefined;
|
|
57
|
+
const headers = Reflect.get(error, "headers");
|
|
58
|
+
const requestId = headerValue(headers, "x-github-request-id");
|
|
59
|
+
const reference = requestId === undefined ? "" : ` ${formatProviderRequestId("GitHub", requestId)}.`;
|
|
60
|
+
if (isQuotaFailure(status, body, headerValue(headers, "x-ratelimit-exceeded"))) {
|
|
61
|
+
return `GitHub Copilot quota exceeded (HTTP ${status}): the plan's included usage or its additional-usage limit is used up, so premium models are refused until it resets or the limit is raised. Usage is shown at https://github.com/settings/copilot.${reference}`;
|
|
62
|
+
}
|
|
63
|
+
if (status === 421) {
|
|
64
|
+
return `GitHub Copilot sent this account to a different API host (HTTP 421 Misdirected Request): Business and Enterprise accounts are served from their own host, which senpi reads from the Copilot token. Run /login github-copilot so senpi stores the account's endpoint, and report it with the GitHub request id if it persists.${reference}`;
|
|
65
|
+
}
|
|
66
|
+
if (status === 403) {
|
|
67
|
+
const reason = body === undefined ? " with an empty body" : "";
|
|
68
|
+
return `GitHub Copilot refused the request (HTTP 403${reason}). Copilot checks access per model and per client; if a fresh /login github-copilot does not help, report it with the GitHub request id.${reference}`;
|
|
69
|
+
}
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
export function withGitHubCopilotFailureNote(message, provider, error) {
|
|
73
|
+
if (provider !== "github-copilot")
|
|
74
|
+
return message;
|
|
75
|
+
const note = describeGitHubCopilotFailure(error);
|
|
76
|
+
return note === undefined ? message : `${message}\n${note}`;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=github-copilot-errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-copilot-errors.js","sourceRoot":"","sources":["../../src/api/github-copilot-errors.ts"],"names":[],"mappings":"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","sourcesContent":["import { normalizeProviderError } from \"../utils/error-body.ts\";\nimport { formatProviderRequestId } from \"../utils/retry.ts\";\n\n// Codes VS Code Copilot Chat treats as quota exhaustion (extensions/copilot chatMLFetcher.ts).\nconst QUOTA_CODES = new Set([\n\t\"quota_exceeded\",\n\t\"free_quota_exceeded\",\n\t\"overage_limit_reached\",\n\t\"billing_not_configured\",\n\t\"additional_spend_limit_reached\",\n]);\n\nfunction headerValue(headers: unknown, name: string): string | undefined {\n\tif (headers instanceof Headers) return headers.get(name) ?? undefined;\n\tif (typeof headers !== \"object\" || headers === null) return undefined;\n\tfor (const [key, value] of Object.entries(headers)) {\n\t\tif (key.toLowerCase() === name && typeof value === \"string\") return value;\n\t}\n\treturn undefined;\n}\n\nfunction errorCode(body: string | undefined): string | undefined {\n\tif (body === undefined) return undefined;\n\ttry {\n\t\tconst parsed: unknown = JSON.parse(body);\n\t\tif (typeof parsed !== \"object\" || parsed === null) return undefined;\n\t\tconst nested = Reflect.get(parsed, \"error\");\n\t\tconst code =\n\t\t\ttypeof nested === \"object\" && nested !== null ? Reflect.get(nested, \"code\") : Reflect.get(parsed, \"code\");\n\t\treturn typeof code === \"string\" ? code : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction isQuotaFailure(status: number, body: string | undefined, limitKey: string | undefined): boolean {\n\tconst code = errorCode(body);\n\tif (code !== undefined && QUOTA_CODES.has(code)) return true;\n\tif (status === 402) return true;\n\treturn status === 429 && (limitKey?.includes(\"quota\") === true || /quota exceeded/i.test(body ?? \"\"));\n}\n\n/**\n * A plain-language note for a GitHub Copilot HTTP failure that the SDK message alone\n * leaves opaque (`403 status code (no body)`): which refusal it is, where to look, and\n * the GitHub request id support needs. `undefined` for failures the message already\n * explains. The wording avoids credential words so pool classification is unchanged.\n */\nexport function describeGitHubCopilotFailure(error: unknown): string | undefined {\n\tif (!(error instanceof Error)) return undefined;\n\tconst { status, body } = normalizeProviderError(error);\n\tif (status === undefined) return undefined;\n\tconst headers = Reflect.get(error, \"headers\");\n\tconst requestId = headerValue(headers, \"x-github-request-id\");\n\tconst reference = requestId === undefined ? \"\" : ` ${formatProviderRequestId(\"GitHub\", requestId)}.`;\n\tif (isQuotaFailure(status, body, headerValue(headers, \"x-ratelimit-exceeded\"))) {\n\t\treturn `GitHub Copilot quota exceeded (HTTP ${status}): the plan's included usage or its additional-usage limit is used up, so premium models are refused until it resets or the limit is raised. Usage is shown at https://github.com/settings/copilot.${reference}`;\n\t}\n\tif (status === 421) {\n\t\treturn `GitHub Copilot sent this account to a different API host (HTTP 421 Misdirected Request): Business and Enterprise accounts are served from their own host, which senpi reads from the Copilot token. Run /login github-copilot so senpi stores the account's endpoint, and report it with the GitHub request id if it persists.${reference}`;\n\t}\n\tif (status === 403) {\n\t\tconst reason = body === undefined ? \" with an empty body\" : \"\";\n\t\treturn `GitHub Copilot refused the request (HTTP 403${reason}). Copilot checks access per model and per client; if a fresh /login github-copilot does not help, report it with the GitHub request id.${reference}`;\n\t}\n\treturn undefined;\n}\n\nexport function withGitHubCopilotFailureNote(message: string, provider: string, error: unknown): string {\n\tif (provider !== \"github-copilot\") return message;\n\tconst note = describeGitHubCopilotFailure(error);\n\treturn note === undefined ? message : `${message}\\n${note}`;\n}\n"]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Message } from "../types.ts";
|
|
2
|
+
export declare const GITHUB_COPILOT_REJECTED_TOKEN_STATUSES: readonly number[];
|
|
2
3
|
export declare function inferCopilotInitiator(messages: Message[]): "user" | "agent";
|
|
3
4
|
export declare function hasCopilotVisionInput(messages: Message[]): boolean;
|
|
4
5
|
export declare function buildCopilotDynamicHeaders(params: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"github-copilot-headers.d.ts","sourceRoot":"","sources":["../../src/api/github-copilot-headers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAI3C,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,MAAM,GAAG,OAAO,CAG3E;AAGD,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,CAUlE;AAED,wBAAgB,0BAA0B,CAAC,MAAM,EAAE;IAClD,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;CACnB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAWzB"}
|
|
1
|
+
{"version":3,"file":"github-copilot-headers.d.ts","sourceRoot":"","sources":["../../src/api/github-copilot-headers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAI3C,eAAO,MAAM,sCAAsC,EAAE,SAAS,MAAM,EAAe,CAAC;AAIpF,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,MAAM,GAAG,OAAO,CAG3E;AAGD,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,CAUlE;AAED,wBAAgB,0BAA0B,CAAC,MAAM,EAAE;IAClD,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;CACnB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAWzB"}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// VS Code Copilot Chat drops its Copilot token on 401/403 and fetches a new one; a
|
|
2
|
+
// revoked token otherwise stays in use until its own 24h expiry.
|
|
3
|
+
export const GITHUB_COPILOT_REJECTED_TOKEN_STATUSES = [401, 403];
|
|
1
4
|
// Copilot expects X-Initiator to indicate whether the request is user-initiated
|
|
2
5
|
// or agent-initiated (e.g. follow-up after assistant/tool messages).
|
|
3
6
|
export function inferCopilotInitiator(messages) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"github-copilot-headers.js","sourceRoot":"","sources":["../../src/api/github-copilot-headers.ts"],"names":[],"mappings":"AAEA,gFAAgF;AAChF,qEAAqE;AACrE,MAAM,UAAU,qBAAqB,CAAC,QAAmB;IACxD,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC3C,OAAO,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;AACxD,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,qBAAqB,CAAC,QAAmB;IACxD,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE;QAC5B,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YACvD,OAAO,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;QACpD,CAAC;QACD,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YAC7D,OAAO,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;QACpD,CAAC;QACD,OAAO,KAAK,CAAC;IACd,CAAC,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,MAG1C;IACA,MAAM,OAAO,GAA2B;QACvC,aAAa,EAAE,qBAAqB,CAAC,MAAM,CAAC,QAAQ,CAAC;QACrD,eAAe,EAAE,oBAAoB;KACrC,CAAC;IAEF,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;QACtB,OAAO,CAAC,wBAAwB,CAAC,GAAG,MAAM,CAAC;IAC5C,CAAC;IAED,OAAO,OAAO,CAAC;AAChB,CAAC","sourcesContent":["import type { Message } from \"../types.ts\";\n\n// Copilot expects X-Initiator to indicate whether the request is user-initiated\n// or agent-initiated (e.g. follow-up after assistant/tool messages).\nexport function inferCopilotInitiator(messages: Message[]): \"user\" | \"agent\" {\n\tconst last = messages[messages.length - 1];\n\treturn last && last.role !== \"user\" ? \"agent\" : \"user\";\n}\n\n// Copilot requires Copilot-Vision-Request header when sending images\nexport function hasCopilotVisionInput(messages: Message[]): boolean {\n\treturn messages.some((msg) => {\n\t\tif (msg.role === \"user\" && Array.isArray(msg.content)) {\n\t\t\treturn msg.content.some((c) => c.type === \"image\");\n\t\t}\n\t\tif (msg.role === \"toolResult\" && Array.isArray(msg.content)) {\n\t\t\treturn msg.content.some((c) => c.type === \"image\");\n\t\t}\n\t\treturn false;\n\t});\n}\n\nexport function buildCopilotDynamicHeaders(params: {\n\tmessages: Message[];\n\thasImages: boolean;\n}): Record<string, string> {\n\tconst headers: Record<string, string> = {\n\t\t\"X-Initiator\": inferCopilotInitiator(params.messages),\n\t\t\"Openai-Intent\": \"conversation-edits\",\n\t};\n\n\tif (params.hasImages) {\n\t\theaders[\"Copilot-Vision-Request\"] = \"true\";\n\t}\n\n\treturn headers;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"github-copilot-headers.js","sourceRoot":"","sources":["../../src/api/github-copilot-headers.ts"],"names":[],"mappings":"AAEA,mFAAmF;AACnF,iEAAiE;AACjE,MAAM,CAAC,MAAM,sCAAsC,GAAsB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AAEpF,gFAAgF;AAChF,qEAAqE;AACrE,MAAM,UAAU,qBAAqB,CAAC,QAAmB;IACxD,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC3C,OAAO,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;AACxD,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,qBAAqB,CAAC,QAAmB;IACxD,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE;QAC5B,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YACvD,OAAO,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;QACpD,CAAC;QACD,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YAC7D,OAAO,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;QACpD,CAAC;QACD,OAAO,KAAK,CAAC;IACd,CAAC,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,MAG1C;IACA,MAAM,OAAO,GAA2B;QACvC,aAAa,EAAE,qBAAqB,CAAC,MAAM,CAAC,QAAQ,CAAC;QACrD,eAAe,EAAE,oBAAoB;KACrC,CAAC;IAEF,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;QACtB,OAAO,CAAC,wBAAwB,CAAC,GAAG,MAAM,CAAC;IAC5C,CAAC;IAED,OAAO,OAAO,CAAC;AAChB,CAAC","sourcesContent":["import type { Message } from \"../types.ts\";\n\n// VS Code Copilot Chat drops its Copilot token on 401/403 and fetches a new one; a\n// revoked token otherwise stays in use until its own 24h expiry.\nexport const GITHUB_COPILOT_REJECTED_TOKEN_STATUSES: readonly number[] = [401, 403];\n\n// Copilot expects X-Initiator to indicate whether the request is user-initiated\n// or agent-initiated (e.g. follow-up after assistant/tool messages).\nexport function inferCopilotInitiator(messages: Message[]): \"user\" | \"agent\" {\n\tconst last = messages[messages.length - 1];\n\treturn last && last.role !== \"user\" ? \"agent\" : \"user\";\n}\n\n// Copilot requires Copilot-Vision-Request header when sending images\nexport function hasCopilotVisionInput(messages: Message[]): boolean {\n\treturn messages.some((msg) => {\n\t\tif (msg.role === \"user\" && Array.isArray(msg.content)) {\n\t\t\treturn msg.content.some((c) => c.type === \"image\");\n\t\t}\n\t\tif (msg.role === \"toolResult\" && Array.isArray(msg.content)) {\n\t\t\treturn msg.content.some((c) => c.type === \"image\");\n\t\t}\n\t\treturn false;\n\t});\n}\n\nexport function buildCopilotDynamicHeaders(params: {\n\tmessages: Message[];\n\thasImages: boolean;\n}): Record<string, string> {\n\tconst headers: Record<string, string> = {\n\t\t\"X-Initiator\": inferCopilotInitiator(params.messages),\n\t\t\"Openai-Intent\": \"conversation-edits\",\n\t};\n\n\tif (params.hasImages) {\n\t\theaders[\"Copilot-Vision-Request\"] = \"true\";\n\t}\n\n\treturn headers;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openai-completions.d.ts","sourceRoot":"","sources":["../../src/api/openai-completions.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,KAAK,EAOX,0BAA0B,EAI1B,MAAM,sCAAsC,CAAC;AAU9C,OAAO,KAAK,EAIX,OAAO,EAIP,KAAK,EAIL,mBAAmB,EAEnB,cAAc,EACd,aAAa,EAEb,eAAe,EAMf,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"openai-completions.d.ts","sourceRoot":"","sources":["../../src/api/openai-completions.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,KAAK,EAOX,0BAA0B,EAI1B,MAAM,sCAAsC,CAAC;AAU9C,OAAO,KAAK,EAIX,OAAO,EAIP,KAAK,EAIL,mBAAmB,EAEnB,cAAc,EACd,aAAa,EAEb,eAAe,EAMf,MAAM,aAAa,CAAC;AAYrB,OAAO,EAEN,KAAK,+BAA+B,EACpC,MAAM,8BAA8B,CAAC;AAqCtC,OAAO,EACN,0BAA0B,IAAI,SAAS,EACvC,KAAK,+BAA+B,GACpC,MAAM,8BAA8B,CAAC;AA8NtC,MAAM,WAAW,wBAAyB,SAAQ,aAAa;IAC9D,UAAU,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,8BAA8B,CAAC;IACpE,eAAe,CAAC,EAAE,SAAS,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC;IAC1E,2KAA2K;IAC3K,eAAe,CAAC,EAAE,eAAe,CAAC;CAClC;AAED,MAAM,WAAW,iCAAiC;IACjD,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,0BAA0B,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACzD;AAwKD,eAAO,MAAM,MAAM,EAAE,cAAc,CAAC,oBAAoB,EAAE,wBAAwB,CAohBjF,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,cAAc,CAAC,oBAAoB,EAAE,mBAAmB,CAqClF,CAAC;AAkeF,wBAAgB,eAAe,CAC9B,KAAK,EAAE,KAAK,CAAC,oBAAoB,CAAC,EAClC,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,+BAA+B,EACvC,OAAO,GAAE,iCAAsC,GAC7C,0BAA0B,EAAE,CAwS9B"}
|
|
@@ -3,6 +3,7 @@ import { calculateCost, clampThinkingLevel, inferOpenAIThinkingLevelMap, support
|
|
|
3
3
|
import { readProviderDiagnostic } from "../provider-diagnostic.js";
|
|
4
4
|
import { formatProviderError, normalizeProviderError } from "../utils/error-body.js";
|
|
5
5
|
import { AssistantMessageEventStream } from "../utils/event-stream.js";
|
|
6
|
+
import { formatGitHubCopilotToolLimitError, limitGitHubCopilotTools, recordGitHubCopilotToolLimit, } from "../utils/github-copilot-tool-limit.js";
|
|
6
7
|
import { shortHash } from "../utils/hash.js";
|
|
7
8
|
import { headersToRecord } from "../utils/headers.js";
|
|
8
9
|
import { parseStreamingJson } from "../utils/json-parse.js";
|
|
@@ -15,6 +16,7 @@ import { sanitizeSurrogates } from "../utils/sanitize-unicode.js";
|
|
|
15
16
|
import { sendWithForcedToolChoiceFallback } from "../utils/tool-choice-fallback.js";
|
|
16
17
|
import { normalizeToolParametersForMoonshot, normalizeToolParametersForOpenAICompat, } from "../utils/tool-schema-compat.js";
|
|
17
18
|
import { appendGrammarToolInputJsonDelta, createGrammarToolInputProperties, getGrammarToolInput, getJsonSchemaToolParameters, resolveGrammarConstrainedSampling, resolveJsonSchemaStrictSampling, } from "./constrained-sampling.js";
|
|
19
|
+
import { withGitHubCopilotFailureNote } from "./github-copilot-errors.js";
|
|
18
20
|
import { buildCopilotDynamicHeaders, hasCopilotVisionInput } from "./github-copilot-headers.js";
|
|
19
21
|
import { resolveOpenAIClientAuth } from "./openai-client-auth.js";
|
|
20
22
|
import { clampOpenAIPromptCacheKey } from "./openai-prompt-cache.js";
|
|
@@ -334,6 +336,11 @@ export const stream = (model, context, options) => {
|
|
|
334
336
|
params = nextParams;
|
|
335
337
|
}
|
|
336
338
|
params = normalizeRequestToolSchemas(params, compat);
|
|
339
|
+
const limitedTools = limitGitHubCopilotTools(model.provider, params.tools, params.tool_choice);
|
|
340
|
+
if (limitedTools.omittedCount > 0) {
|
|
341
|
+
params = { ...params, tools: limitedTools.tools };
|
|
342
|
+
recordGitHubCopilotToolLimit(output, limitedTools.omittedCount);
|
|
343
|
+
}
|
|
337
344
|
const requestOptions = {
|
|
338
345
|
...(options?.signal ? { signal: options.signal } : {}),
|
|
339
346
|
...(options?.timeoutMs !== undefined ? { timeout: options.timeoutMs } : {}),
|
|
@@ -746,7 +753,7 @@ export const stream = (model, context, options) => {
|
|
|
746
753
|
const providerDiagnostic = output.stopReason === "error" ? readProviderDiagnostic(error) : undefined;
|
|
747
754
|
if (providerDiagnostic !== undefined)
|
|
748
755
|
output.providerDiagnostic = providerDiagnostic;
|
|
749
|
-
output.errorMessage = formatProviderError(normalizeProviderError(error));
|
|
756
|
+
output.errorMessage = withGitHubCopilotFailureNote(formatGitHubCopilotToolLimitError(output, formatProviderError(normalizeProviderError(error))), model.provider, error);
|
|
750
757
|
// Some providers via OpenRouter give additional information in this field.
|
|
751
758
|
// normalizeProviderError already stringifies the parsed body (error.error)
|
|
752
759
|
// into errorMessage, so only append the raw metadata when it is not already
|