@nyte-ai/ai 0.0.0-stage → 0.0.18
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/LICENSE +21 -0
- package/README.md +170 -2
- package/THIRD-PARTY-NOTICES.md +800 -0
- package/dist/chunks/account-limits-cache-031vfpt3.js +37 -0
- package/dist/chunks/account-limits-cache-09vs98g6.js +41 -0
- package/dist/chunks/account-limits-cache-0af5gqeg.js +15 -0
- package/dist/chunks/account-limits-cache-0yd6bde8.js +103 -0
- package/dist/chunks/account-limits-cache-1jv43fhh.js +22 -0
- package/dist/chunks/account-limits-cache-3ykqmnj5.js +88 -0
- package/dist/chunks/account-limits-cache-4b8ckwqw.js +293 -0
- package/dist/chunks/account-limits-cache-4fn5w63p.js +295 -0
- package/dist/chunks/account-limits-cache-4hptgd2h.js +49 -0
- package/dist/chunks/account-limits-cache-53e64mhx.js +417 -0
- package/dist/chunks/account-limits-cache-5jdhn0e1.js +562 -0
- package/dist/chunks/account-limits-cache-5rx2pfm5.js +8 -0
- package/dist/chunks/account-limits-cache-5ygxyyss.js +19 -0
- package/dist/chunks/account-limits-cache-6250ykn6.js +21 -0
- package/dist/chunks/account-limits-cache-6x05n06z.js +49 -0
- package/dist/chunks/account-limits-cache-736tdyme.js +6 -0
- package/dist/chunks/account-limits-cache-75smws02.js +213 -0
- package/dist/chunks/account-limits-cache-7z9s8j16.js +139 -0
- package/dist/chunks/account-limits-cache-8137j3zp.js +37 -0
- package/dist/chunks/account-limits-cache-8qzk56vj.js +160 -0
- package/dist/chunks/account-limits-cache-8s8bz4dr.js +36 -0
- package/dist/chunks/account-limits-cache-8vzx8k6r.js +166 -0
- package/dist/chunks/account-limits-cache-8wfqg73s.js +135 -0
- package/dist/chunks/account-limits-cache-90c9c2eb.js +50 -0
- package/dist/chunks/account-limits-cache-9wqk28n5.js +25 -0
- package/dist/chunks/account-limits-cache-a1jyaq00.js +56 -0
- package/dist/chunks/account-limits-cache-a558rjbg.js +138 -0
- package/dist/chunks/account-limits-cache-a55e14fr.js +70 -0
- package/dist/chunks/account-limits-cache-a6cgeagz.js +77 -0
- package/dist/chunks/account-limits-cache-ag5b8dja.js +38 -0
- package/dist/chunks/account-limits-cache-b0x2sfya.js +45 -0
- package/dist/chunks/account-limits-cache-b23sbrke.js +26 -0
- package/dist/chunks/account-limits-cache-b4edaybk.js +8 -0
- package/dist/chunks/account-limits-cache-bsknrh6t.js +74 -0
- package/dist/chunks/account-limits-cache-c7v93krb.js +235 -0
- package/dist/chunks/account-limits-cache-csbxvam7.js +12 -0
- package/dist/chunks/account-limits-cache-cw7q7vfy.js +293 -0
- package/dist/chunks/account-limits-cache-d1ypzqzp.js +27 -0
- package/dist/chunks/account-limits-cache-d2a51dka.js +17 -0
- package/dist/chunks/account-limits-cache-dejeygdt.js +114 -0
- package/dist/chunks/account-limits-cache-eejm0vth.js +11 -0
- package/dist/chunks/account-limits-cache-ehy0ze2b.js +33 -0
- package/dist/chunks/account-limits-cache-emg5b4hj.js +53 -0
- package/dist/chunks/account-limits-cache-eqwweapz.js +6 -0
- package/dist/chunks/account-limits-cache-eyx1jcxc.js +8 -0
- package/dist/chunks/account-limits-cache-f9z00x8c.js +36 -0
- package/dist/chunks/account-limits-cache-fbkaq46e.js +113 -0
- package/dist/chunks/account-limits-cache-fdwad56n.js +399 -0
- package/dist/chunks/account-limits-cache-fht68jp2.js +22 -0
- package/dist/chunks/account-limits-cache-fp03ztsw.js +17 -0
- package/dist/chunks/account-limits-cache-fsktnetm.js +69 -0
- package/dist/chunks/account-limits-cache-fvadc36m.js +110 -0
- package/dist/chunks/account-limits-cache-ghe9ne4j.js +69 -0
- package/dist/chunks/account-limits-cache-gknnm1kv.js +13 -0
- package/dist/chunks/account-limits-cache-gqsrbky9.js +40 -0
- package/dist/chunks/account-limits-cache-gr671dr2.js +0 -0
- package/dist/chunks/account-limits-cache-gs8a3fhw.js +32 -0
- package/dist/chunks/account-limits-cache-gsa5tzck.js +37 -0
- package/dist/chunks/account-limits-cache-h92bzz1j.js +235 -0
- package/dist/chunks/account-limits-cache-hemxtapd.js +142 -0
- package/dist/chunks/account-limits-cache-hj1h48sc.js +92 -0
- package/dist/chunks/account-limits-cache-hj3ek3ty.js +128 -0
- package/dist/chunks/account-limits-cache-hwehc67r.js +509 -0
- package/dist/chunks/account-limits-cache-hyzn1jmk.js +46 -0
- package/dist/chunks/account-limits-cache-j2bt392s.js +63 -0
- package/dist/chunks/account-limits-cache-k0pkzhbx.js +74 -0
- package/dist/chunks/account-limits-cache-kjx405q0.js +277 -0
- package/dist/chunks/account-limits-cache-ks1sjym9.js +37 -0
- package/dist/chunks/account-limits-cache-me1x57bs.js +89 -0
- package/dist/chunks/account-limits-cache-n3yk6g5c.js +314 -0
- package/dist/chunks/account-limits-cache-nbhht7xz.js +72 -0
- package/dist/chunks/account-limits-cache-nbkyhs6v.js +42 -0
- package/dist/chunks/account-limits-cache-nn9jebsj.js +26 -0
- package/dist/chunks/account-limits-cache-nxkprk3g.js +13 -0
- package/dist/chunks/account-limits-cache-nyy770yd.js +38 -0
- package/dist/chunks/account-limits-cache-pfa86y8e.js +45 -0
- package/dist/chunks/account-limits-cache-pfr14mcn.js +59 -0
- package/dist/chunks/account-limits-cache-q1ebtvet.js +8 -0
- package/dist/chunks/account-limits-cache-q63mc41j.js +51 -0
- package/dist/chunks/account-limits-cache-re8hpzwn.js +104 -0
- package/dist/chunks/account-limits-cache-rz8p1g5y.js +9 -0
- package/dist/chunks/account-limits-cache-skbfmzqe.js +7 -0
- package/dist/chunks/account-limits-cache-tc38g0ca.js +20 -0
- package/dist/chunks/account-limits-cache-v4n30az2.js +24 -0
- package/dist/chunks/account-limits-cache-vwgfz727.js +281 -0
- package/dist/chunks/account-limits-cache-x9fvb3s5.js +8 -0
- package/dist/chunks/account-limits-cache-xds88kxd.js +209 -0
- package/dist/chunks/account-limits-cache-xz65wyd1.js +428 -0
- package/dist/chunks/account-limits-cache-ydq8p8qp.js +39 -0
- package/dist/chunks/account-limits-cache-ykbqsvv6.js +134 -0
- package/dist/chunks/account-limits-cache-za42x8a3.js +25 -0
- package/dist/chunks/account-limits-cache-zcbkmrvy.js +79 -0
- package/dist/chunks/account-limits-cache-zgzptd0z.js +62 -0
- package/dist/chunks/account-limits-cache-zn01kscn.js +252 -0
- package/dist/chunks/account-limits-cache-zpjmeyt0.js +113 -0
- package/dist/chunks/account-limits-cache-zqdb4yh4.js +8 -0
- package/dist/src/account-limits-cache.d.ts +16 -0
- package/dist/src/account-limits-cache.js +7 -0
- package/dist/src/api/anthropic-client.d.ts +25 -0
- package/dist/src/api/anthropic-client.js +30 -0
- package/dist/src/api/anthropic-convert.d.ts +17 -0
- package/dist/src/api/anthropic-convert.js +14 -0
- package/dist/src/api/anthropic-events.d.ts +101 -0
- package/dist/src/api/anthropic-events.js +11 -0
- package/dist/src/api/anthropic-messages.d.ts +88 -0
- package/dist/src/api/anthropic-messages.js +578 -0
- package/dist/src/api/anthropic-messages.lazy.d.ts +2 -0
- package/dist/src/api/anthropic-messages.lazy.js +11 -0
- package/dist/src/api/assistant-stream.d.ts +23 -0
- package/dist/src/api/assistant-stream.js +15 -0
- package/dist/src/api/claude-code.d.ts +12 -0
- package/dist/src/api/claude-code.js +12 -0
- package/dist/src/api/cloudflare.d.ts +8 -0
- package/dist/src/api/cloudflare.js +11 -0
- package/dist/src/api/constrained-sampling.d.ts +24 -0
- package/dist/src/api/constrained-sampling.js +16 -0
- package/dist/src/api/deferred.d.ts +7 -0
- package/dist/src/api/deferred.js +10 -0
- package/dist/src/api/github-copilot-headers.d.ts +15 -0
- package/dist/src/api/github-copilot-headers.js +12 -0
- package/dist/src/api/google-generative-ai.d.ts +22 -0
- package/dist/src/api/google-generative-ai.js +583 -0
- package/dist/src/api/google-generative-ai.lazy.d.ts +2 -0
- package/dist/src/api/google-generative-ai.lazy.js +11 -0
- package/dist/src/api/lazy.d.ts +18 -0
- package/dist/src/api/lazy.js +12 -0
- package/dist/src/api/openai-codex-compact.d.ts +14 -0
- package/dist/src/api/openai-codex-compact.js +389 -0
- package/dist/src/api/openai-codex-compaction-error.d.ts +7 -0
- package/dist/src/api/openai-codex-compaction-error.js +6 -0
- package/dist/src/api/openai-codex-protocol.d.ts +125 -0
- package/dist/src/api/openai-codex-protocol.js +48 -0
- package/dist/src/api/openai-codex-responses.d.ts +4 -0
- package/dist/src/api/openai-codex-responses.js +175 -0
- package/dist/src/api/openai-codex-responses.lazy.d.ts +2 -0
- package/dist/src/api/openai-codex-responses.lazy.js +11 -0
- package/dist/src/api/openai-codex-websocket.d.ts +13 -0
- package/dist/src/api/openai-codex-websocket.js +37 -0
- package/dist/src/api/openai-codex-wire.d.ts +44 -0
- package/dist/src/api/openai-codex-wire.js +34 -0
- package/dist/src/api/openai-compact.d.ts +9 -0
- package/dist/src/api/openai-compact.js +12 -0
- package/dist/src/api/openai-completions-convert.d.ts +58 -0
- package/dist/src/api/openai-completions-convert.js +21 -0
- package/dist/src/api/openai-completions-params.d.ts +29 -0
- package/dist/src/api/openai-completions-params.js +20 -0
- package/dist/src/api/openai-completions-reasoning.d.ts +54 -0
- package/dist/src/api/openai-completions-reasoning.js +22 -0
- package/dist/src/api/openai-completions.d.ts +22 -0
- package/dist/src/api/openai-completions.js +484 -0
- package/dist/src/api/openai-completions.lazy.d.ts +5 -0
- package/dist/src/api/openai-completions.lazy.js +11 -0
- package/dist/src/api/openai-prompt-cache.d.ts +1 -0
- package/dist/src/api/openai-prompt-cache.js +6 -0
- package/dist/src/api/openai-responses-convert.d.ts +58 -0
- package/dist/src/api/openai-responses-convert.js +16 -0
- package/dist/src/api/openai-responses-events.d.ts +379 -0
- package/dist/src/api/openai-responses-events.js +12 -0
- package/dist/src/api/openai-responses-stream.d.ts +36 -0
- package/dist/src/api/openai-responses-stream.js +25 -0
- package/dist/src/api/openai-responses.d.ts +18 -0
- package/dist/src/api/openai-responses.js +276 -0
- package/dist/src/api/openai-responses.lazy.d.ts +2 -0
- package/dist/src/api/openai-responses.lazy.js +11 -0
- package/dist/src/api/simple-options.d.ts +17 -0
- package/dist/src/api/simple-options.js +18 -0
- package/dist/src/api/token-count.d.ts +5 -0
- package/dist/src/api/token-count.js +8 -0
- package/dist/src/api/transform-messages.d.ts +9 -0
- package/dist/src/api/transform-messages.js +6 -0
- package/dist/src/api-options.d.ts +27 -0
- package/dist/src/api-options.js +0 -0
- package/dist/src/auth/context.d.ts +11 -0
- package/dist/src/auth/context.js +6 -0
- package/dist/src/auth/credential-store.d.ts +17 -0
- package/dist/src/auth/credential-store.js +7 -0
- package/dist/src/auth/helpers.d.ts +24 -0
- package/dist/src/auth/helpers.js +8 -0
- package/dist/src/auth/oauth/anthropic.d.ts +7 -0
- package/dist/src/auth/oauth/anthropic.js +12 -0
- package/dist/src/auth/oauth/authorization-input.d.ts +14 -0
- package/dist/src/auth/oauth/authorization-input.js +6 -0
- package/dist/src/auth/oauth/device-code.d.ts +29 -0
- package/dist/src/auth/oauth/device-code.js +9 -0
- package/dist/src/auth/oauth/github-copilot.d.ts +23 -0
- package/dist/src/auth/oauth/github-copilot.js +12 -0
- package/dist/src/auth/oauth/load.d.ts +14 -0
- package/dist/src/auth/oauth/load.js +10 -0
- package/dist/src/auth/oauth/oauth-page.d.ts +13 -0
- package/dist/src/auth/oauth/oauth-page.js +8 -0
- package/dist/src/auth/oauth/openai-codex.d.ts +10 -0
- package/dist/src/auth/oauth/openai-codex.js +18 -0
- package/dist/src/auth/oauth/pkce.d.ts +12 -0
- package/dist/src/auth/oauth/pkce.js +6 -0
- package/dist/src/auth/resolve.d.ts +38 -0
- package/dist/src/auth/resolve.js +12 -0
- package/dist/src/auth/store.d.ts +29 -0
- package/dist/src/auth/store.js +10 -0
- package/dist/src/auth/types.d.ts +291 -0
- package/dist/src/auth/types.js +8 -0
- package/dist/src/auth/verify.d.ts +13 -0
- package/dist/src/auth/verify.js +7 -0
- package/dist/src/bun-oauth.d.ts +2 -0
- package/dist/src/bun-oauth.js +25 -0
- package/dist/src/env-api-keys.d.ts +32 -0
- package/dist/src/env-api-keys.js +27 -0
- package/dist/src/file-models-store.d.ts +18 -0
- package/dist/src/file-models-store.js +9 -0
- package/dist/src/index.d.ts +62 -0
- package/dist/src/index.js +372 -0
- package/dist/src/model-capabilities.d.ts +21 -0
- package/dist/src/model-capabilities.js +14 -0
- package/dist/src/model-pricing.d.ts +6 -0
- package/dist/src/model-pricing.js +10 -0
- package/dist/src/model-variants.d.ts +21 -0
- package/dist/src/model-variants.js +19 -0
- package/dist/src/models-refresh.d.ts +27 -0
- package/dist/src/models-refresh.js +9 -0
- package/dist/src/models-store.d.ts +31 -0
- package/dist/src/models-store.js +6 -0
- package/dist/src/models-types.d.ts +206 -0
- package/dist/src/models-types.js +0 -0
- package/dist/src/models.d.ts +7 -0
- package/dist/src/models.js +44 -0
- package/dist/src/prompt-cache.d.ts +5 -0
- package/dist/src/prompt-cache.js +9 -0
- package/dist/src/provider.d.ts +23 -0
- package/dist/src/provider.js +14 -0
- package/dist/src/providers/account-limits.d.ts +13 -0
- package/dist/src/providers/account-limits.js +8 -0
- package/dist/src/providers/anthropic-limits.d.ts +9 -0
- package/dist/src/providers/anthropic-limits.js +10 -0
- package/dist/src/providers/anthropic.d.ts +2 -0
- package/dist/src/providers/anthropic.js +25 -0
- package/dist/src/providers/github-copilot-catalog.d.ts +5 -0
- package/dist/src/providers/github-copilot-catalog.js +7 -0
- package/dist/src/providers/github-copilot.d.ts +2 -0
- package/dist/src/providers/github-copilot.js +23 -0
- package/dist/src/providers/nyte-catalog.d.ts +15 -0
- package/dist/src/providers/nyte-catalog.js +63 -0
- package/dist/src/providers/openai-codex-limits.d.ts +8 -0
- package/dist/src/providers/openai-codex-limits.js +14 -0
- package/dist/src/providers/openai-codex.d.ts +2 -0
- package/dist/src/providers/openai-codex.js +23 -0
- package/dist/src/providers/openai.d.ts +2 -0
- package/dist/src/providers/openai.js +19 -0
- package/dist/src/providers/opencode-go.d.ts +5 -0
- package/dist/src/providers/opencode-go.js +22 -0
- package/dist/src/providers/opencode-headers.d.ts +5 -0
- package/dist/src/providers/opencode-headers.js +6 -0
- package/dist/src/providers/opencode.d.ts +14 -0
- package/dist/src/providers/opencode.js +23 -0
- package/dist/src/providers/openrouter.d.ts +2 -0
- package/dist/src/providers/openrouter.js +19 -0
- package/dist/src/providers/vercel-ai-gateway.d.ts +3 -0
- package/dist/src/providers/vercel-ai-gateway.js +19 -0
- package/dist/src/session-resources.d.ts +9 -0
- package/dist/src/session-resources.js +10 -0
- package/dist/src/types.d.ts +210 -0
- package/dist/src/types.js +1 -0
- package/dist/src/utils/abort.d.ts +12 -0
- package/dist/src/utils/abort.js +10 -0
- package/dist/src/utils/deferred-tools.d.ts +11 -0
- package/dist/src/utils/deferred-tools.js +6 -0
- package/dist/src/utils/diagnostics.d.ts +11 -0
- package/dist/src/utils/diagnostics.js +12 -0
- package/dist/src/utils/error-body.d.ts +26 -0
- package/dist/src/utils/error-body.js +10 -0
- package/dist/src/utils/estimate.d.ts +20 -0
- package/dist/src/utils/estimate.js +14 -0
- package/dist/src/utils/event-stream.d.ts +22 -0
- package/dist/src/utils/event-stream.js +11 -0
- package/dist/src/utils/failure.d.ts +49 -0
- package/dist/src/utils/failure.js +10 -0
- package/dist/src/utils/fifo-queue.d.ts +11 -0
- package/dist/src/utils/fifo-queue.js +6 -0
- package/dist/src/utils/hash.d.ts +5 -0
- package/dist/src/utils/hash.js +6 -0
- package/dist/src/utils/headers.d.ts +12 -0
- package/dist/src/utils/headers.js +14 -0
- package/dist/src/utils/json-parse.d.ts +33 -0
- package/dist/src/utils/json-parse.js +12 -0
- package/dist/src/utils/node-http-proxy.d.ts +6 -0
- package/dist/src/utils/node-http-proxy.js +9 -0
- package/dist/src/utils/nyte-home.d.ts +2 -0
- package/dist/src/utils/nyte-home.js +6 -0
- package/dist/src/utils/nyte-user-agent.d.ts +1 -0
- package/dist/src/utils/nyte-user-agent.js +6 -0
- package/dist/src/utils/overflow.d.ts +18 -0
- package/dist/src/utils/overflow.js +9 -0
- package/dist/src/utils/provider-env.d.ts +9 -0
- package/dist/src/utils/provider-env.js +6 -0
- package/dist/src/utils/provider-retry.d.ts +22 -0
- package/dist/src/utils/provider-retry.js +9 -0
- package/dist/src/utils/retry.d.ts +66 -0
- package/dist/src/utils/retry.js +18 -0
- package/dist/src/utils/sanitize-unicode.d.ts +24 -0
- package/dist/src/utils/sanitize-unicode.js +6 -0
- package/dist/src/utils/sse.d.ts +21 -0
- package/dist/src/utils/sse.js +6 -0
- package/dist/src/utils/text.d.ts +5 -0
- package/dist/src/utils/text.js +10 -0
- package/dist/src/utils/transcript.d.ts +5 -0
- package/dist/src/utils/transcript.js +36 -0
- package/dist/src/utils/typebox-helpers.d.ts +19 -0
- package/dist/src/utils/typebox-helpers.js +6 -0
- package/dist/src/utils/uuid.d.ts +2 -0
- package/dist/src/utils/uuid.js +6 -0
- package/dist/src/utils/validation.d.ts +13 -0
- package/dist/src/utils/validation.js +8 -0
- package/package.json +152 -3
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getProviderEnvValue2
|
|
3
|
+
} from "./account-limits-cache-b23sbrke.js";
|
|
4
|
+
import {
|
|
5
|
+
OAuthTokenResponseSchema2
|
|
6
|
+
} from "./account-limits-cache-b0x2sfya.js";
|
|
7
|
+
import {
|
|
8
|
+
parseAuthorizationInput2
|
|
9
|
+
} from "./account-limits-cache-d1ypzqzp.js";
|
|
10
|
+
import {
|
|
11
|
+
pollOAuthDeviceCodeFlow2
|
|
12
|
+
} from "./account-limits-cache-4hptgd2h.js";
|
|
13
|
+
import {
|
|
14
|
+
oauthSuccessHtml2,
|
|
15
|
+
oauthErrorHtml2
|
|
16
|
+
} from "./account-limits-cache-8vzx8k6r.js";
|
|
17
|
+
import {
|
|
18
|
+
registerOAuthFlow2
|
|
19
|
+
} from "./account-limits-cache-v4n30az2.js";
|
|
20
|
+
import {
|
|
21
|
+
generatePKCE2
|
|
22
|
+
} from "./account-limits-cache-tc38g0ca.js";
|
|
23
|
+
|
|
24
|
+
// src/auth/oauth/openai-codex.ts
|
|
25
|
+
import { Type } from "typebox";
|
|
26
|
+
import { Value } from "typebox/value";
|
|
27
|
+
var CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann";
|
|
28
|
+
var AUTH_BASE_URL = "https://auth.openai.com";
|
|
29
|
+
var AUTHORIZE_URL = `${AUTH_BASE_URL}/oauth/authorize`;
|
|
30
|
+
var TOKEN_URL = `${AUTH_BASE_URL}/oauth/token`;
|
|
31
|
+
var REDIRECT_URI = "http://localhost:1455/auth/callback";
|
|
32
|
+
var DEVICE_USER_CODE_URL = `${AUTH_BASE_URL}/api/accounts/deviceauth/usercode`;
|
|
33
|
+
var DEVICE_TOKEN_URL = `${AUTH_BASE_URL}/api/accounts/deviceauth/token`;
|
|
34
|
+
var DEVICE_VERIFICATION_URI = `${AUTH_BASE_URL}/codex/device`;
|
|
35
|
+
var DEVICE_REDIRECT_URI = `${AUTH_BASE_URL}/deviceauth/callback`;
|
|
36
|
+
var DEVICE_CODE_TIMEOUT_SECONDS = 15 * 60;
|
|
37
|
+
var OPENAI_CODEX_BROWSER_LOGIN_METHOD = "browser";
|
|
38
|
+
var OPENAI_CODEX_DEVICE_CODE_LOGIN_METHOD = "device_code";
|
|
39
|
+
var SCOPE = "openid profile email offline_access";
|
|
40
|
+
var JWT_CLAIM_PATH = "https://api.openai.com/auth";
|
|
41
|
+
var ORIGINATOR2 = "nyte";
|
|
42
|
+
function getCallbackHost() {
|
|
43
|
+
return getProviderEnvValue2("NYTE_OAUTH_CALLBACK_HOST") || "127.0.0.1";
|
|
44
|
+
}
|
|
45
|
+
var DeviceCodeResponse = Type.Object({
|
|
46
|
+
device_auth_id: Type.String({ minLength: 1 }),
|
|
47
|
+
user_code: Type.String({ minLength: 1 }),
|
|
48
|
+
interval: Type.Union([Type.Number(), Type.String()])
|
|
49
|
+
});
|
|
50
|
+
var DeviceTokenResponse = Type.Object({
|
|
51
|
+
authorization_code: Type.String({ minLength: 1 }),
|
|
52
|
+
code_verifier: Type.String({ minLength: 1 })
|
|
53
|
+
});
|
|
54
|
+
var DeviceErrorCode = Type.Object({ error: Type.String() });
|
|
55
|
+
var NestedDeviceErrorCode = Type.Object({ error: Type.Object({ code: Type.String() }) });
|
|
56
|
+
var JwtClaims = Type.Object({
|
|
57
|
+
[JWT_CLAIM_PATH]: Type.Optional(Type.Object({ chatgpt_account_id: Type.Optional(Type.String()) }))
|
|
58
|
+
});
|
|
59
|
+
function assertNodeRuntime() {
|
|
60
|
+
if (typeof process === "undefined" || !(process.versions?.node || process.versions?.bun)) {
|
|
61
|
+
throw new Error("OpenAI Codex OAuth is only available in Node.js environments");
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function createState() {
|
|
65
|
+
assertNodeRuntime();
|
|
66
|
+
return process.getBuiltinModule("node:crypto").randomBytes(16).toString("hex");
|
|
67
|
+
}
|
|
68
|
+
function decodeJwt(token) {
|
|
69
|
+
try {
|
|
70
|
+
const parts = token.split(".");
|
|
71
|
+
if (parts.length !== 3)
|
|
72
|
+
return null;
|
|
73
|
+
const payload = parts[1] ?? "";
|
|
74
|
+
const claims = JSON.parse(atob(payload));
|
|
75
|
+
return Value.Check(JwtClaims, claims) ? claims : null;
|
|
76
|
+
} catch {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
async function fetchWithLoginCancellation(input, init) {
|
|
81
|
+
try {
|
|
82
|
+
return await fetch(input, init);
|
|
83
|
+
} catch (error) {
|
|
84
|
+
if (init.signal?.aborted) {
|
|
85
|
+
throw new Error("Login cancelled");
|
|
86
|
+
}
|
|
87
|
+
throw error;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
async function readTokenResponse(response, operation) {
|
|
91
|
+
if (!response.ok) {
|
|
92
|
+
const text = await response.text().catch(() => "");
|
|
93
|
+
throw new Error(`OpenAI Codex token ${operation} failed (${response.status}): ${text || response.statusText}`);
|
|
94
|
+
}
|
|
95
|
+
const json = await response.json();
|
|
96
|
+
if (!Value.Check(OAuthTokenResponseSchema2, json)) {
|
|
97
|
+
throw new Error(`OpenAI Codex token ${operation} response missing fields: ${JSON.stringify(json)}`);
|
|
98
|
+
}
|
|
99
|
+
return {
|
|
100
|
+
access: json.access_token,
|
|
101
|
+
refresh: json.refresh_token,
|
|
102
|
+
expires: Date.now() + json.expires_in * 1000
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
async function exchangeAuthorizationCode(code, verifier, redirectUri, signal) {
|
|
106
|
+
const response = await fetchWithLoginCancellation(TOKEN_URL, {
|
|
107
|
+
method: "POST",
|
|
108
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
109
|
+
body: new URLSearchParams({
|
|
110
|
+
grant_type: "authorization_code",
|
|
111
|
+
client_id: CLIENT_ID,
|
|
112
|
+
code,
|
|
113
|
+
code_verifier: verifier,
|
|
114
|
+
redirect_uri: redirectUri
|
|
115
|
+
}),
|
|
116
|
+
signal
|
|
117
|
+
});
|
|
118
|
+
return readTokenResponse(response, "exchange");
|
|
119
|
+
}
|
|
120
|
+
async function refreshAccessToken(refreshToken, signal) {
|
|
121
|
+
let response;
|
|
122
|
+
try {
|
|
123
|
+
response = await fetch(TOKEN_URL, {
|
|
124
|
+
method: "POST",
|
|
125
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
126
|
+
body: new URLSearchParams({
|
|
127
|
+
grant_type: "refresh_token",
|
|
128
|
+
refresh_token: refreshToken,
|
|
129
|
+
client_id: CLIENT_ID
|
|
130
|
+
}),
|
|
131
|
+
signal
|
|
132
|
+
});
|
|
133
|
+
} catch (error) {
|
|
134
|
+
throw new Error(`OpenAI Codex token refresh error: ${error instanceof Error ? error.message : String(error)}`);
|
|
135
|
+
}
|
|
136
|
+
return readTokenResponse(response, "refresh");
|
|
137
|
+
}
|
|
138
|
+
async function startOpenAICodexDeviceAuth(signal) {
|
|
139
|
+
const response = await fetchWithLoginCancellation(DEVICE_USER_CODE_URL, {
|
|
140
|
+
method: "POST",
|
|
141
|
+
headers: { "Content-Type": "application/json" },
|
|
142
|
+
body: JSON.stringify({ client_id: CLIENT_ID }),
|
|
143
|
+
signal
|
|
144
|
+
});
|
|
145
|
+
if (!response.ok) {
|
|
146
|
+
if (response.status === 404) {
|
|
147
|
+
throw new Error("OpenAI Codex device code login is not enabled for this server. Use browser login or verify the server URL.");
|
|
148
|
+
}
|
|
149
|
+
const responseBody = await response.text().catch(() => "");
|
|
150
|
+
throw new Error(`OpenAI Codex device code request failed with status ${response.status}${responseBody ? `: ${responseBody}` : ""}`);
|
|
151
|
+
}
|
|
152
|
+
const json = await response.json();
|
|
153
|
+
const invalid = new Error(`Invalid OpenAI Codex device code response: ${JSON.stringify(json)}`);
|
|
154
|
+
if (!Value.Check(DeviceCodeResponse, json))
|
|
155
|
+
throw invalid;
|
|
156
|
+
const intervalSeconds = Number(json.interval);
|
|
157
|
+
if (!Number.isFinite(intervalSeconds) || intervalSeconds < 0)
|
|
158
|
+
throw invalid;
|
|
159
|
+
return {
|
|
160
|
+
deviceAuthId: json.device_auth_id,
|
|
161
|
+
userCode: json.user_code,
|
|
162
|
+
intervalSeconds
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
async function pollOpenAICodexDeviceAuth(device, signal) {
|
|
166
|
+
return pollOAuthDeviceCodeFlow2({
|
|
167
|
+
intervalSeconds: device.intervalSeconds,
|
|
168
|
+
expiresInSeconds: DEVICE_CODE_TIMEOUT_SECONDS,
|
|
169
|
+
signal,
|
|
170
|
+
poll: async () => {
|
|
171
|
+
const response = await fetchWithLoginCancellation(DEVICE_TOKEN_URL, {
|
|
172
|
+
method: "POST",
|
|
173
|
+
headers: { "Content-Type": "application/json" },
|
|
174
|
+
body: JSON.stringify({
|
|
175
|
+
device_auth_id: device.deviceAuthId,
|
|
176
|
+
user_code: device.userCode
|
|
177
|
+
}),
|
|
178
|
+
signal
|
|
179
|
+
});
|
|
180
|
+
if (response.ok) {
|
|
181
|
+
const json = await response.json();
|
|
182
|
+
if (!Value.Check(DeviceTokenResponse, json)) {
|
|
183
|
+
return {
|
|
184
|
+
status: "failed",
|
|
185
|
+
message: `Invalid OpenAI Codex device auth token response: ${JSON.stringify(json)}`
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
return {
|
|
189
|
+
status: "complete",
|
|
190
|
+
value: { authorizationCode: json.authorization_code, codeVerifier: json.code_verifier }
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
if (response.status === 403 || response.status === 404) {
|
|
194
|
+
return { status: "pending" };
|
|
195
|
+
}
|
|
196
|
+
const responseBody = await response.text().catch(() => "");
|
|
197
|
+
let errorCode;
|
|
198
|
+
try {
|
|
199
|
+
const json = JSON.parse(responseBody);
|
|
200
|
+
if (Value.Check(DeviceErrorCode, json))
|
|
201
|
+
errorCode = json.error;
|
|
202
|
+
else if (Value.Check(NestedDeviceErrorCode, json))
|
|
203
|
+
errorCode = json.error.code;
|
|
204
|
+
} catch {}
|
|
205
|
+
if (errorCode === "deviceauth_authorization_pending") {
|
|
206
|
+
return { status: "pending" };
|
|
207
|
+
}
|
|
208
|
+
if (errorCode === "slow_down") {
|
|
209
|
+
return { status: "slow_down" };
|
|
210
|
+
}
|
|
211
|
+
return {
|
|
212
|
+
status: "failed",
|
|
213
|
+
message: `OpenAI Codex device auth failed with status ${response.status}${responseBody ? `: ${responseBody}` : ""}`
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
async function createAuthorizationFlow(originator = ORIGINATOR2) {
|
|
219
|
+
const { verifier, challenge } = await generatePKCE2();
|
|
220
|
+
const state = createState();
|
|
221
|
+
const url = new URL(AUTHORIZE_URL);
|
|
222
|
+
url.searchParams.set("response_type", "code");
|
|
223
|
+
url.searchParams.set("client_id", CLIENT_ID);
|
|
224
|
+
url.searchParams.set("redirect_uri", REDIRECT_URI);
|
|
225
|
+
url.searchParams.set("scope", SCOPE);
|
|
226
|
+
url.searchParams.set("code_challenge", challenge);
|
|
227
|
+
url.searchParams.set("code_challenge_method", "S256");
|
|
228
|
+
url.searchParams.set("state", state);
|
|
229
|
+
url.searchParams.set("id_token_add_organizations", "true");
|
|
230
|
+
url.searchParams.set("codex_cli_simplified_flow", "true");
|
|
231
|
+
url.searchParams.set("originator", originator);
|
|
232
|
+
return { verifier, state, url: url.toString() };
|
|
233
|
+
}
|
|
234
|
+
function startLocalOAuthServer(state) {
|
|
235
|
+
assertNodeRuntime();
|
|
236
|
+
let settleWait;
|
|
237
|
+
const waitForCodePromise = new Promise((resolve) => {
|
|
238
|
+
let settled = false;
|
|
239
|
+
settleWait = (value) => {
|
|
240
|
+
if (settled)
|
|
241
|
+
return;
|
|
242
|
+
settled = true;
|
|
243
|
+
resolve(value);
|
|
244
|
+
};
|
|
245
|
+
});
|
|
246
|
+
const server = process.getBuiltinModule("node:http").createServer((req, res) => {
|
|
247
|
+
try {
|
|
248
|
+
const url = new URL(req.url || "", "http://localhost");
|
|
249
|
+
if (url.pathname !== "/auth/callback") {
|
|
250
|
+
res.statusCode = 404;
|
|
251
|
+
res.setHeader("Content-Type", "text/html; charset=utf-8");
|
|
252
|
+
res.end(oauthErrorHtml2("Nyte is not listening on this path. Run the login command again to retry."));
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
if (url.searchParams.get("state") !== state) {
|
|
256
|
+
res.statusCode = 400;
|
|
257
|
+
res.setHeader("Content-Type", "text/html; charset=utf-8");
|
|
258
|
+
res.end(oauthErrorHtml2("The callback's state did not match this login attempt, so Nyte ignored it."));
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
const code = url.searchParams.get("code");
|
|
262
|
+
if (!code) {
|
|
263
|
+
res.statusCode = 400;
|
|
264
|
+
res.setHeader("Content-Type", "text/html; charset=utf-8");
|
|
265
|
+
res.end(oauthErrorHtml2("The callback arrived without an authorization code, so Nyte could not finish sign-in."));
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
res.statusCode = 200;
|
|
269
|
+
res.setHeader("Content-Type", "text/html; charset=utf-8");
|
|
270
|
+
res.end(oauthSuccessHtml2({ provider: "OpenAI" }));
|
|
271
|
+
settleWait?.({ code });
|
|
272
|
+
} catch {
|
|
273
|
+
res.statusCode = 500;
|
|
274
|
+
res.setHeader("Content-Type", "text/html; charset=utf-8");
|
|
275
|
+
res.end(oauthErrorHtml2("Nyte hit an internal error while handling the callback. Run the login command again to retry."));
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
return new Promise((resolve) => {
|
|
279
|
+
server.listen(1455, getCallbackHost(), () => {
|
|
280
|
+
resolve({
|
|
281
|
+
close: () => server.close(),
|
|
282
|
+
cancelWait: () => {
|
|
283
|
+
settleWait?.(null);
|
|
284
|
+
},
|
|
285
|
+
waitForCode: () => waitForCodePromise
|
|
286
|
+
});
|
|
287
|
+
}).on("error", (_err) => {
|
|
288
|
+
settleWait?.(null);
|
|
289
|
+
resolve({
|
|
290
|
+
close: () => {
|
|
291
|
+
try {
|
|
292
|
+
server.close();
|
|
293
|
+
} catch {}
|
|
294
|
+
},
|
|
295
|
+
cancelWait: () => {},
|
|
296
|
+
waitForCode: async () => null
|
|
297
|
+
});
|
|
298
|
+
});
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
function getAccountId2(accessToken) {
|
|
302
|
+
return decodeJwt(accessToken)?.[JWT_CLAIM_PATH]?.chatgpt_account_id || null;
|
|
303
|
+
}
|
|
304
|
+
function credentialsFromToken(token) {
|
|
305
|
+
const accountId = getAccountId2(token.access);
|
|
306
|
+
if (!accountId) {
|
|
307
|
+
throw new Error("Failed to extract accountId from token");
|
|
308
|
+
}
|
|
309
|
+
return {
|
|
310
|
+
type: "oauth",
|
|
311
|
+
access: token.access,
|
|
312
|
+
refresh: token.refresh,
|
|
313
|
+
expires: token.expires,
|
|
314
|
+
accountId
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
async function exchangeAuthorizationCodeForCredentials(code, verifier, redirectUri, signal) {
|
|
318
|
+
return credentialsFromToken(await exchangeAuthorizationCode(code, verifier, redirectUri, signal));
|
|
319
|
+
}
|
|
320
|
+
async function loginOpenAICodexDeviceCode(interaction) {
|
|
321
|
+
const device = await startOpenAICodexDeviceAuth(interaction.signal);
|
|
322
|
+
interaction.notify({
|
|
323
|
+
type: "device_code",
|
|
324
|
+
userCode: device.userCode,
|
|
325
|
+
verificationUri: DEVICE_VERIFICATION_URI,
|
|
326
|
+
intervalSeconds: device.intervalSeconds,
|
|
327
|
+
expiresInSeconds: DEVICE_CODE_TIMEOUT_SECONDS
|
|
328
|
+
});
|
|
329
|
+
const code = await pollOpenAICodexDeviceAuth(device, interaction.signal);
|
|
330
|
+
return exchangeAuthorizationCodeForCredentials(code.authorizationCode, code.codeVerifier, DEVICE_REDIRECT_URI, interaction.signal);
|
|
331
|
+
}
|
|
332
|
+
async function loginOpenAICodex(interaction) {
|
|
333
|
+
const { verifier, state, url } = await createAuthorizationFlow();
|
|
334
|
+
const server = await startLocalOAuthServer(state);
|
|
335
|
+
const manualAbort = new AbortController;
|
|
336
|
+
const onAbort = () => server.cancelWait();
|
|
337
|
+
interaction.signal.addEventListener("abort", onAbort, { once: true });
|
|
338
|
+
if (interaction.signal.aborted)
|
|
339
|
+
onAbort();
|
|
340
|
+
let code;
|
|
341
|
+
let manualCode;
|
|
342
|
+
let manualError;
|
|
343
|
+
interaction.notify({
|
|
344
|
+
type: "auth_url",
|
|
345
|
+
url,
|
|
346
|
+
instructions: "A browser window should open. Complete login to finish."
|
|
347
|
+
});
|
|
348
|
+
try {
|
|
349
|
+
const manualPromise = interaction.prompt({
|
|
350
|
+
type: "manual_code",
|
|
351
|
+
message: "Complete login in your browser, or paste the authorization code / redirect URL here:",
|
|
352
|
+
placeholder: REDIRECT_URI,
|
|
353
|
+
signal: manualAbort.signal
|
|
354
|
+
}).then((input) => {
|
|
355
|
+
manualCode = input;
|
|
356
|
+
server.cancelWait();
|
|
357
|
+
}).catch((error) => {
|
|
358
|
+
manualError = error instanceof Error ? error : new Error(String(error));
|
|
359
|
+
server.cancelWait();
|
|
360
|
+
});
|
|
361
|
+
const result = await server.waitForCode();
|
|
362
|
+
if (manualError)
|
|
363
|
+
throw manualError;
|
|
364
|
+
if (result?.code) {
|
|
365
|
+
code = result.code;
|
|
366
|
+
} else if (manualCode) {
|
|
367
|
+
const parsed = parseAuthorizationInput2(manualCode);
|
|
368
|
+
if (parsed.state && parsed.state !== state)
|
|
369
|
+
throw new Error("State mismatch");
|
|
370
|
+
code = parsed.code;
|
|
371
|
+
}
|
|
372
|
+
if (!code) {
|
|
373
|
+
await manualPromise;
|
|
374
|
+
if (manualError)
|
|
375
|
+
throw manualError;
|
|
376
|
+
if (manualCode) {
|
|
377
|
+
const parsed = parseAuthorizationInput2(manualCode);
|
|
378
|
+
if (parsed.state && parsed.state !== state)
|
|
379
|
+
throw new Error("State mismatch");
|
|
380
|
+
code = parsed.code;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
if (!code)
|
|
384
|
+
throw new Error("Missing authorization code");
|
|
385
|
+
return exchangeAuthorizationCodeForCredentials(code, verifier, REDIRECT_URI, interaction.signal);
|
|
386
|
+
} finally {
|
|
387
|
+
interaction.signal.removeEventListener("abort", onAbort);
|
|
388
|
+
manualAbort.abort();
|
|
389
|
+
server.close();
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
async function refreshOpenAICodexToken(refreshToken, signal) {
|
|
393
|
+
return credentialsFromToken(await refreshAccessToken(refreshToken, signal));
|
|
394
|
+
}
|
|
395
|
+
var openaiCodexOAuth2 = {
|
|
396
|
+
name: "OpenAI (ChatGPT Plus/Pro)",
|
|
397
|
+
isSubscription: true,
|
|
398
|
+
async login(interaction) {
|
|
399
|
+
const method = interaction.browser === "host" ? OPENAI_CODEX_BROWSER_LOGIN_METHOD : interaction.browser === "elsewhere" ? OPENAI_CODEX_DEVICE_CODE_LOGIN_METHOD : await interaction.prompt({
|
|
400
|
+
type: "select",
|
|
401
|
+
message: "Select OpenAI Codex login method:",
|
|
402
|
+
options: [
|
|
403
|
+
{ id: OPENAI_CODEX_BROWSER_LOGIN_METHOD, label: "Browser login (default)" },
|
|
404
|
+
{
|
|
405
|
+
id: OPENAI_CODEX_DEVICE_CODE_LOGIN_METHOD,
|
|
406
|
+
label: "Device code login (headless)"
|
|
407
|
+
}
|
|
408
|
+
]
|
|
409
|
+
});
|
|
410
|
+
if (method === OPENAI_CODEX_DEVICE_CODE_LOGIN_METHOD) {
|
|
411
|
+
return loginOpenAICodexDeviceCode(interaction);
|
|
412
|
+
}
|
|
413
|
+
if (method !== OPENAI_CODEX_BROWSER_LOGIN_METHOD) {
|
|
414
|
+
throw new Error(`Unknown OpenAI Codex login method: ${method}`);
|
|
415
|
+
}
|
|
416
|
+
return loginOpenAICodex(interaction);
|
|
417
|
+
},
|
|
418
|
+
refresh: (credential, signal) => refreshOpenAICodexToken(credential.refresh, signal),
|
|
419
|
+
async toAuth(credential) {
|
|
420
|
+
const accountId = getAccountId2(credential.access);
|
|
421
|
+
if (!accountId)
|
|
422
|
+
throw new Error("OpenAI Codex credential missing account id");
|
|
423
|
+
return { apiKey: credential.access, headers: { "chatgpt-account-id": accountId } };
|
|
424
|
+
}
|
|
425
|
+
};
|
|
426
|
+
registerOAuthFlow2("openaiCodex", openaiCodexOAuth2);
|
|
427
|
+
|
|
428
|
+
export { ORIGINATOR2, getAccountId2, openaiCodexOAuth2 };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import {
|
|
2
|
+
providerHeadersToRecord2
|
|
3
|
+
} from "./account-limits-cache-ag5b8dja.js";
|
|
4
|
+
|
|
5
|
+
// src/auth/verify.ts
|
|
6
|
+
async function verifyWithRequest2(input) {
|
|
7
|
+
const response = await globalThis.fetch(input.url, {
|
|
8
|
+
headers: providerHeadersToRecord2(input.headers),
|
|
9
|
+
signal: input.signal,
|
|
10
|
+
redirect: "error"
|
|
11
|
+
});
|
|
12
|
+
if (response.status === 401 || response.status === 403) {
|
|
13
|
+
await response.body?.cancel();
|
|
14
|
+
return {
|
|
15
|
+
ok: false,
|
|
16
|
+
reason: "rejected",
|
|
17
|
+
message: `${input.provider} rejected the credential (HTTP ${String(response.status)})`
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
if (!response.ok) {
|
|
21
|
+
await response.body?.cancel();
|
|
22
|
+
return {
|
|
23
|
+
ok: false,
|
|
24
|
+
reason: "unreachable",
|
|
25
|
+
message: `${input.provider} could not verify the credential (HTTP ${String(response.status)})`
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
if (!input.detail) {
|
|
29
|
+
await response.body?.cancel();
|
|
30
|
+
return { ok: true };
|
|
31
|
+
}
|
|
32
|
+
const body = await response.json().catch(() => {
|
|
33
|
+
return;
|
|
34
|
+
});
|
|
35
|
+
const detail = input.detail(body);
|
|
36
|
+
return detail === undefined ? { ok: true } : { ok: true, detail };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export { verifyWithRequest2 };
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import {
|
|
2
|
+
lazyStream2
|
|
3
|
+
} from "./account-limits-cache-90c9c2eb.js";
|
|
4
|
+
import {
|
|
5
|
+
ModelsError2
|
|
6
|
+
} from "./account-limits-cache-7z9s8j16.js";
|
|
7
|
+
|
|
8
|
+
// src/provider.ts
|
|
9
|
+
import { ModelSchema } from "@nyte-ai/schema/model";
|
|
10
|
+
import { Value } from "typebox/value";
|
|
11
|
+
var CATALOG_FRESHNESS_WINDOW_MS = 4 * 60 * 60 * 1000;
|
|
12
|
+
function createProvider2(input) {
|
|
13
|
+
let catalogModels = [];
|
|
14
|
+
const api = input.api;
|
|
15
|
+
const single = "streamSimple" in api ? api : undefined;
|
|
16
|
+
const byApi = new Map("streamSimple" in api ? [] : Object.entries(api));
|
|
17
|
+
const apiFor = (model) => single ?? byApi.get(model.api);
|
|
18
|
+
const usableModels = (catalog) => catalog.filter((model) => Value.Check(ModelSchema, model) && model.provider === input.id && apiFor(model) !== undefined);
|
|
19
|
+
const dispatch = (model, run) => {
|
|
20
|
+
const streams = apiFor(model);
|
|
21
|
+
if (!streams) {
|
|
22
|
+
return lazyStream2(model, async () => {
|
|
23
|
+
throw new ModelsError2("stream", `Provider ${input.id} has no API implementation for "${model.api}"`);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
return run(streams);
|
|
27
|
+
};
|
|
28
|
+
const provider = {
|
|
29
|
+
id: input.id,
|
|
30
|
+
name: input.name ?? input.id,
|
|
31
|
+
baseUrl: input.baseUrl,
|
|
32
|
+
headers: input.headers,
|
|
33
|
+
promptCache: input.promptCache,
|
|
34
|
+
auth: input.auth,
|
|
35
|
+
fetchAccountLimits: input.fetchAccountLimits,
|
|
36
|
+
getModels: () => catalogModels,
|
|
37
|
+
refreshModels: async (context) => {
|
|
38
|
+
if (context.stored) {
|
|
39
|
+
const restored = usableModels(context.stored.models);
|
|
40
|
+
if (!await context.publish({
|
|
41
|
+
update: () => {
|
|
42
|
+
catalogModels = restored;
|
|
43
|
+
}
|
|
44
|
+
})) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (!context.allowNetwork || context.signal.aborted)
|
|
49
|
+
return;
|
|
50
|
+
if (context.force !== true && context.stored?.checkedAt !== undefined && Date.now() - context.stored.checkedAt < CATALOG_FRESHNESS_WINDOW_MS) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const headers = new Headers({ Accept: "application/json" });
|
|
54
|
+
if (context.stored?.etag !== undefined) {
|
|
55
|
+
headers.set("If-None-Match", context.stored.etag);
|
|
56
|
+
}
|
|
57
|
+
let response;
|
|
58
|
+
try {
|
|
59
|
+
response = await context.catalog.fetch(`${context.catalog.url.replace(/\/+$/u, "")}/${input.id}.json`, {
|
|
60
|
+
headers,
|
|
61
|
+
signal: context.signal,
|
|
62
|
+
redirect: "error"
|
|
63
|
+
});
|
|
64
|
+
} catch (error) {
|
|
65
|
+
context.signal.throwIfAborted();
|
|
66
|
+
throw new ModelsError2("model_source", `Model catalog request failed for ${input.id}`, {
|
|
67
|
+
cause: error
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
const checkedAt = Date.now();
|
|
71
|
+
if (response.status === 304) {
|
|
72
|
+
if (!context.stored) {
|
|
73
|
+
throw new ModelsError2("model_source", `Model catalog request failed for ${input.id} (HTTP 304 without cached models)`);
|
|
74
|
+
}
|
|
75
|
+
await context.publish({ persist: { ...context.stored, checkedAt } });
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
if (response.status !== 200) {
|
|
79
|
+
throw new ModelsError2("model_source", `Model catalog request failed for ${input.id} (HTTP ${String(response.status)})`);
|
|
80
|
+
}
|
|
81
|
+
let value;
|
|
82
|
+
try {
|
|
83
|
+
value = await response.json();
|
|
84
|
+
} catch {
|
|
85
|
+
throw new ModelsError2("model_source", `Model catalog request failed for ${input.id} (HTTP 200, invalid JSON)`);
|
|
86
|
+
}
|
|
87
|
+
if (!Array.isArray(value)) {
|
|
88
|
+
throw new ModelsError2("model_source", `Model catalog request failed for ${input.id} (HTTP 200, expected an array)`);
|
|
89
|
+
}
|
|
90
|
+
const refreshed = usableModels(value);
|
|
91
|
+
const lastModifiedHeader = response.headers.get("Last-Modified");
|
|
92
|
+
const parsedLastModified = lastModifiedHeader === null ? undefined : Date.parse(lastModifiedHeader);
|
|
93
|
+
const lastModified = parsedLastModified === undefined || Number.isNaN(parsedLastModified) ? undefined : parsedLastModified;
|
|
94
|
+
if (context.signal.aborted)
|
|
95
|
+
return;
|
|
96
|
+
await context.publish({
|
|
97
|
+
persist: {
|
|
98
|
+
models: value,
|
|
99
|
+
etag: response.headers.get("ETag") ?? undefined,
|
|
100
|
+
lastModified,
|
|
101
|
+
checkedAt
|
|
102
|
+
},
|
|
103
|
+
update: () => {
|
|
104
|
+
catalogModels = refreshed;
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
},
|
|
108
|
+
filterModels: input.filterModels,
|
|
109
|
+
stream: (model, context, options) => dispatch(model, (streams) => streams.stream(model, context, options)),
|
|
110
|
+
streamSimple: (model, context, options) => dispatch(model, (streams) => streams.streamSimple(model, context, options))
|
|
111
|
+
};
|
|
112
|
+
const streams = single ? [single] : [...byApi.values()].filter((entry) => entry !== undefined);
|
|
113
|
+
if (streams.some((entry) => entry.fetchDeferred !== undefined)) {
|
|
114
|
+
provider.fetchDeferred = (model, handle, options) => lazyStream2(model, async () => {
|
|
115
|
+
const implementation = apiFor(model);
|
|
116
|
+
if (!implementation?.fetchDeferred) {
|
|
117
|
+
throw new ModelsError2("provider", `Provider ${input.id} does not support deferred responses for "${model.api}"`);
|
|
118
|
+
}
|
|
119
|
+
return implementation.fetchDeferred(model, handle, options);
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
if (streams.some((entry) => entry.cancelDeferred !== undefined)) {
|
|
123
|
+
provider.cancelDeferred = async (model, handle, options) => {
|
|
124
|
+
const implementation = apiFor(model);
|
|
125
|
+
if (!implementation?.cancelDeferred) {
|
|
126
|
+
throw new ModelsError2("provider", `Provider ${input.id} cannot cancel deferred responses for "${model.api}"`);
|
|
127
|
+
}
|
|
128
|
+
await implementation.cancelDeferred(model, handle, options);
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
return provider;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export { createProvider2 };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// src/api/github-copilot-headers.ts
|
|
2
|
+
var GITHUB_COPILOT_API_VERSION2 = "2026-06-01";
|
|
3
|
+
var GITHUB_COPILOT_DEFAULT_ORIGIN2 = "https://api.individual.githubcopilot.com";
|
|
4
|
+
var GITHUB_COPILOT_HEADERS2 = {
|
|
5
|
+
"User-Agent": "GitHubCopilotChat/0.35.0",
|
|
6
|
+
"Editor-Version": "vscode/1.107.0",
|
|
7
|
+
"Editor-Plugin-Version": "copilot-chat/0.35.0",
|
|
8
|
+
"Copilot-Integration-Id": "vscode-chat"
|
|
9
|
+
};
|
|
10
|
+
function buildCopilotDynamicHeaders2(input) {
|
|
11
|
+
const last = input.messages.at(-1);
|
|
12
|
+
const headers = {
|
|
13
|
+
"X-GitHub-Api-Version": GITHUB_COPILOT_API_VERSION2,
|
|
14
|
+
"X-Initiator": last && last.role !== "user" ? "agent" : "user",
|
|
15
|
+
"Openai-Intent": "conversation-edits",
|
|
16
|
+
"X-Interaction-Type": "conversation-agent"
|
|
17
|
+
};
|
|
18
|
+
if (input.sessionId)
|
|
19
|
+
headers["X-Interaction-Id"] = input.sessionId;
|
|
20
|
+
if (input.messages.some((message) => (message.role === "user" || message.role === "toolResult") && Array.isArray(message.content) && message.content.some((part) => part.type === "image")))
|
|
21
|
+
headers["Copilot-Vision-Request"] = "true";
|
|
22
|
+
return headers;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export { GITHUB_COPILOT_API_VERSION2, GITHUB_COPILOT_DEFAULT_ORIGIN2, GITHUB_COPILOT_HEADERS2, buildCopilotDynamicHeaders2 };
|