dsh-coding-subscription-oauth 0.6.4 → 0.7.0
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 +291 -255
- package/CONTRIBUTING.md +138 -129
- package/INSTALL.md +261 -256
- package/LICENSE +19 -19
- package/NOTICE +11 -11
- package/README.de.md +303 -303
- package/README.es.md +304 -304
- package/README.fr.md +304 -304
- package/README.ja.md +304 -304
- package/README.ko.md +304 -304
- package/README.md +321 -320
- package/README.pt-BR.md +304 -304
- package/README.ru.md +304 -304
- package/README.zh-CN.md +319 -318
- package/compatibility/dsh-bom.json +36 -30
- package/cordis.patch.yml +13 -13
- package/docs/00-project-rules.md +213 -212
- package/docs/02-architecture.md +142 -138
- package/docs/02-architecture.zh-CN.md +142 -138
- package/lib/auth-routes.d.ts +10 -1
- package/lib/auth-routes.d.ts.map +1 -1
- package/lib/bin.js +483 -50
- package/lib/bin.js.map +4 -4
- package/lib/client.js +5 -5
- package/lib/client.js.map +4 -4
- package/lib/compatibility.d.ts +0 -1
- package/lib/compatibility.d.ts.map +1 -1
- package/lib/gateway-protocol.d.ts +3 -46
- package/lib/gateway-protocol.d.ts.map +1 -1
- package/lib/gateway-routes.d.ts.map +1 -1
- package/lib/grok-errors.d.ts +2 -12
- package/lib/grok-errors.d.ts.map +1 -1
- package/lib/grok-imagine/client.d.ts +73 -0
- package/lib/grok-imagine/client.d.ts.map +1 -0
- package/lib/grok-imagine/index.d.ts +8 -0
- package/lib/grok-imagine/index.d.ts.map +1 -0
- package/lib/grok-imagine/net.d.ts +10 -0
- package/lib/grok-imagine/net.d.ts.map +1 -0
- package/lib/grok-imagine/parse.d.ts +20 -0
- package/lib/grok-imagine/parse.d.ts.map +1 -0
- package/lib/grok-imagine/types.d.ts +191 -0
- package/lib/grok-imagine/types.d.ts.map +1 -0
- package/lib/grok-imagine.d.ts +3 -263
- package/lib/grok-imagine.d.ts.map +1 -1
- package/lib/http-json.d.ts +2 -9
- package/lib/http-json.d.ts.map +1 -1
- package/lib/ids.d.ts +4 -0
- package/lib/ids.d.ts.map +1 -1
- package/lib/index.d.ts +2 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +730 -196
- package/lib/index.js.map +4 -4
- package/lib/invariant.js.map +1 -1
- package/lib/kimi-errors.d.ts +2 -12
- package/lib/kimi-errors.d.ts.map +1 -1
- package/lib/oauth-session.d.ts +2 -0
- package/lib/oauth-session.d.ts.map +1 -1
- package/lib/session.d.ts +2 -0
- package/lib/session.d.ts.map +1 -1
- package/lib/store.d.ts +73 -1
- package/lib/store.d.ts.map +1 -1
- package/media/en/settings_accounts.png +0 -0
- package/media/en/settings_capabilities.png +0 -0
- package/media/en/settings_gateway.png +0 -0
- package/media/settings_accounts.png +0 -0
- package/media/settings_capabilities.png +0 -0
- package/media/settings_gateway.png +0 -0
- package/media/settings_overview.png +0 -0
- package/media/zh-CN/settings_accounts.png +0 -0
- package/media/zh-CN/settings_capabilities.png +0 -0
- package/media/zh-CN/settings_gateway.png +0 -0
- package/package.json +224 -221
- package/patches/dsh-agy@0.1.2.patch +25 -25
- package/scripts/release.mjs +187 -186
- package/scripts/smoke-deployed-routes.mjs +146 -146
- package/scripts/verify-deployed-catalog.mjs +87 -87
- package/src/adapter.ts +0 -348
- package/src/alias-adapter.ts +0 -147
- package/src/auth-routes.ts +0 -921
- package/src/auth.ts +0 -67
- package/src/bin.ts +0 -350
- package/src/capability-routes.ts +0 -279
- package/src/capability-runtime.ts +0 -314
- package/src/capability-settings.ts +0 -671
- package/src/capability-tools.ts +0 -685
- package/src/catalog.ts +0 -271
- package/src/client/GrokBuildSettings.tsx +0 -771
- package/src/client/api.ts +0 -88
- package/src/client/components/AboutTab.tsx +0 -30
- package/src/client/components/AccountsTab.tsx +0 -241
- package/src/client/components/Badge.tsx +0 -33
- package/src/client/components/CapabilitiesTab.tsx +0 -265
- package/src/client/components/CliPullPreview.tsx +0 -116
- package/src/client/components/CopyButton.tsx +0 -57
- package/src/client/components/GatewayTab.tsx +0 -469
- package/src/client/components/NoticeBanner.tsx +0 -46
- package/src/client/components/ProgressBar.tsx +0 -53
- package/src/client/components/ProviderCard.tsx +0 -606
- package/src/client/components/SettingsTabs.tsx +0 -75
- package/src/client/components/ToggleSwitch.tsx +0 -71
- package/src/client/constants.ts +0 -230
- package/src/client/display.ts +0 -61
- package/src/client/dshClientAdapter.ts +0 -127
- package/src/client/gatewaySnippets.ts +0 -37
- package/src/client/index.tsx +0 -156
- package/src/client/locales.ts +0 -540
- package/src/client/microStyles.ts +0 -52
- package/src/client/parsers.ts +0 -398
- package/src/client/styles.ts +0 -325
- package/src/client/types.ts +0 -199
- package/src/codex-http.ts +0 -447
- package/src/codex-images.ts +0 -503
- package/src/codex-model-capabilities.ts +0 -320
- package/src/codex-search.ts +0 -245
- package/src/codex-usage.ts +0 -263
- package/src/compatibility.ts +0 -55
- package/src/dsh-host-adapter.ts +0 -173
- package/src/gateway-anthropic-messages.ts +0 -84
- package/src/gateway-auth.ts +0 -102
- package/src/gateway-backend.ts +0 -274
- package/src/gateway-body.ts +0 -49
- package/src/gateway-config.ts +0 -76
- package/src/gateway-http.ts +0 -104
- package/src/gateway-openai-chat.ts +0 -124
- package/src/gateway-openai-responses.ts +0 -53
- package/src/gateway-parse.ts +0 -224
- package/src/gateway-protocol.ts +0 -52
- package/src/gateway-routes.ts +0 -158
- package/src/gateway.ts +0 -258
- package/src/grok-errors.ts +0 -24
- package/src/grok-imagine.ts +0 -1627
- package/src/grok-import.ts +0 -151
- package/src/http-json.ts +0 -82
- package/src/ids.ts +0 -59
- package/src/imagine-routes.ts +0 -463
- package/src/index.ts +0 -735
- package/src/invariant.ts +0 -17
- package/src/kimi-errors.ts +0 -26
- package/src/media-store.ts +0 -927
- package/src/oauth-import-routes.ts +0 -324
- package/src/oauth-providers.ts +0 -152
- package/src/oauth-session.ts +0 -183
- package/src/oauth-sources.ts +0 -1104
- package/src/oauth.ts +0 -620
- package/src/provider.ts +0 -128
- package/src/proxy.ts +0 -11
- package/src/redact.ts +0 -72
- package/src/session.ts +0 -218
- package/src/store.ts +0 -217
- package/src/web-origin.ts +0 -296
- package/src/web-routes.ts +0 -38
package/lib/bin.js
CHANGED
|
@@ -25620,7 +25620,7 @@ import { readFile, stat } from "node:fs/promises";
|
|
|
25620
25620
|
import { homedir } from "node:os";
|
|
25621
25621
|
import { join, resolve } from "node:path";
|
|
25622
25622
|
|
|
25623
|
-
// node_modules/.pnpm/dsh-coding-oauth-core@0.1.1/node_modules/dsh-coding-oauth-core/lib/proxy.js
|
|
25623
|
+
// node_modules/.pnpm/dsh-coding-oauth-core@0.1.2_@deepseek-ai+dsh-llm@0.1.1-rc.2_@deepseek-ai+cordis@4.0.1_@_82bbdc1424db474a5d3f648945c0fadb/node_modules/dsh-coding-oauth-core/lib/proxy.js
|
|
25624
25624
|
var import_undici = __toESM(require_undici(), 1);
|
|
25625
25625
|
var DEFAULT_PROXIED_HOSTS = [
|
|
25626
25626
|
"auth.x.ai",
|
|
@@ -25749,7 +25749,7 @@ function codingOAuthProxyUnreachableHint() {
|
|
|
25749
25749
|
return codingOAuthProxyInEffect() === void 0 ? "" : "; check that CODING_OAUTH_PROXY is reachable";
|
|
25750
25750
|
}
|
|
25751
25751
|
|
|
25752
|
-
// node_modules/.pnpm/dsh-coding-oauth-core@0.1.1/node_modules/dsh-coding-oauth-core/lib/ids.js
|
|
25752
|
+
// node_modules/.pnpm/dsh-coding-oauth-core@0.1.2_@deepseek-ai+dsh-llm@0.1.1-rc.2_@deepseek-ai+cordis@4.0.1_@_82bbdc1424db474a5d3f648945c0fadb/node_modules/dsh-coding-oauth-core/lib/ids.js
|
|
25753
25753
|
var XAI_PI_PROVIDER = "xai";
|
|
25754
25754
|
var CODEX_PI_PROVIDER = "openai-codex";
|
|
25755
25755
|
var KIMI_PI_PROVIDER = "kimi-coding";
|
|
@@ -25768,7 +25768,7 @@ var KIMI_CODE_OAUTH_MODELS_CACHE_FILENAME = ".kimi-code-oauth-models.json";
|
|
|
25768
25768
|
var CLAUDE_CODE_OAUTH_MODELS_CACHE_FILENAME = ".claude-code-oauth-models.json";
|
|
25769
25769
|
var DEFAULT_GROK_BUILD_MODEL = "grok-4.6";
|
|
25770
25770
|
|
|
25771
|
-
// node_modules/.pnpm/dsh-coding-oauth-core@0.1.1/node_modules/dsh-coding-oauth-core/lib/state-contract.js
|
|
25771
|
+
// node_modules/.pnpm/dsh-coding-oauth-core@0.1.2_@deepseek-ai+dsh-llm@0.1.1-rc.2_@deepseek-ai+cordis@4.0.1_@_82bbdc1424db474a5d3f648945c0fadb/node_modules/dsh-coding-oauth-core/lib/state-contract.js
|
|
25772
25772
|
var GROK_BUILD_AUTH_STATUS_PATH = "/plugins/dsh-grok-build/auth/status";
|
|
25773
25773
|
var GROK_BUILD_AUTH_LOGIN_PATH = "/plugins/dsh-grok-build/auth/login";
|
|
25774
25774
|
var GROK_BUILD_AUTH_LOGIN_CODE_PATH = "/plugins/dsh-grok-build/auth/login/code";
|
|
@@ -25818,6 +25818,17 @@ var CODING_OAUTH_MANAGEMENT_PATHS = Object.freeze([
|
|
|
25818
25818
|
GATEWAY_ROTATE_PATH
|
|
25819
25819
|
]);
|
|
25820
25820
|
|
|
25821
|
+
// node_modules/.pnpm/dsh-coding-oauth-core@0.1.2_@deepseek-ai+dsh-llm@0.1.1-rc.2_@deepseek-ai+cordis@4.0.1_@_82bbdc1424db474a5d3f648945c0fadb/node_modules/dsh-coding-oauth-core/lib/http-json.js
|
|
25822
|
+
var JSON_BODY_LIMIT_BYTES = 64 * 1024;
|
|
25823
|
+
|
|
25824
|
+
// node_modules/.pnpm/dsh-coding-oauth-core@0.1.2_@deepseek-ai+dsh-llm@0.1.1-rc.2_@deepseek-ai+cordis@4.0.1_@_82bbdc1424db474a5d3f648945c0fadb/node_modules/dsh-coding-oauth-core/lib/kimi-errors.js
|
|
25825
|
+
import { CONTEXT_WINDOW_EXCEEDED_CODE, isContextWindowExceededError } from "@deepseek-ai/dsh-llm";
|
|
25826
|
+
|
|
25827
|
+
// src/ids.ts
|
|
25828
|
+
var CODING_OAUTH_API_BASE = "/plugins/dsh-grok-build";
|
|
25829
|
+
var CODING_OAUTH_ACCOUNTS_SET_ACTIVE_PATH = `${CODING_OAUTH_API_BASE}/oauth/accounts/set-active`;
|
|
25830
|
+
var CODING_OAUTH_ACCOUNTS_REMOVE_PATH = `${CODING_OAUTH_API_BASE}/oauth/accounts/remove`;
|
|
25831
|
+
|
|
25821
25832
|
// src/grok-import.ts
|
|
25822
25833
|
var DEFAULT_TOKEN_LIFETIME_MS = 60 * 60 * 1e3;
|
|
25823
25834
|
function isENOENT(error) {
|
|
@@ -25919,6 +25930,7 @@ async function importGrokAuth(store, filename = grokAuthPath()) {
|
|
|
25919
25930
|
}
|
|
25920
25931
|
|
|
25921
25932
|
// src/store.ts
|
|
25933
|
+
import { randomBytes } from "node:crypto";
|
|
25922
25934
|
import { mkdir, rm } from "node:fs/promises";
|
|
25923
25935
|
import { dirname, join as join3, resolve as resolve3 } from "node:path";
|
|
25924
25936
|
import { withFileLock, writeFileAtomic } from "@deepseek-ai/dsh-atomic-write";
|
|
@@ -26078,25 +26090,17 @@ function currentUid() {
|
|
|
26078
26090
|
}
|
|
26079
26091
|
|
|
26080
26092
|
// src/store.ts
|
|
26081
|
-
var AUTH_FORMAT_VERSION =
|
|
26082
|
-
|
|
26083
|
-
|
|
26084
|
-
|
|
26085
|
-
|
|
26086
|
-
|
|
26087
|
-
|
|
26088
|
-
|
|
26089
|
-
|
|
26090
|
-
|
|
26091
|
-
|
|
26092
|
-
const document = value;
|
|
26093
|
-
if (document["version"] !== AUTH_FORMAT_VERSION) {
|
|
26094
|
-
throw new Error(`${label}: ${filename} has unsupported auth format version ${String(document["version"])}`);
|
|
26095
|
-
}
|
|
26096
|
-
if (Object.keys(document).some((key) => key !== "version" && key !== "credential")) {
|
|
26097
|
-
throw new Error(`${label}: ${filename} contains an unknown top-level field`);
|
|
26098
|
-
}
|
|
26099
|
-
const raw = document["credential"];
|
|
26093
|
+
var AUTH_FORMAT_VERSION = 2;
|
|
26094
|
+
var AUTH_FORMAT_VERSION_V1 = 1;
|
|
26095
|
+
var OAUTH_MAX_ACCOUNTS = 8;
|
|
26096
|
+
var MAX_ACCOUNTS = OAUTH_MAX_ACCOUNTS;
|
|
26097
|
+
var LEGACY_ACCOUNT_ID = "legacy";
|
|
26098
|
+
var ACCOUNT_ID_PATTERN = /^[A-Za-z0-9._:@+-]+$/u;
|
|
26099
|
+
var UNCHANGED = /* @__PURE__ */ Symbol("unchanged");
|
|
26100
|
+
function isValidAccountId(value) {
|
|
26101
|
+
return typeof value === "string" && value.length > 0 && value.length <= 128 && ACCOUNT_ID_PATTERN.test(value);
|
|
26102
|
+
}
|
|
26103
|
+
function parseOAuthCredential(raw, filename, label) {
|
|
26100
26104
|
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
|
|
26101
26105
|
throw new Error(`${label}: ${filename} credential must be an object`);
|
|
26102
26106
|
}
|
|
@@ -26105,23 +26109,178 @@ function parseDocument(text, filename, label) {
|
|
|
26105
26109
|
if (Object.keys(credential).some((key) => !allowed.has(key))) {
|
|
26106
26110
|
throw new Error(`${label}: ${filename} credential contains an unknown field`);
|
|
26107
26111
|
}
|
|
26108
|
-
if (credential
|
|
26112
|
+
if (credential.type !== "oauth") throw new Error(`${label}: ${filename} credential type must be oauth`);
|
|
26109
26113
|
for (const key of ["access", "refresh"]) {
|
|
26110
26114
|
if (typeof credential[key] !== "string" || credential[key].length === 0) {
|
|
26111
26115
|
throw new Error(`${label}: ${filename} credential ${key} must be a non-empty string`);
|
|
26112
26116
|
}
|
|
26113
26117
|
}
|
|
26114
|
-
if (credential
|
|
26118
|
+
if (credential.accountId !== void 0 && (typeof credential.accountId !== "string" || credential.accountId.length === 0)) {
|
|
26115
26119
|
throw new Error(`${label}: ${filename} credential accountId must be a non-empty string when present`);
|
|
26116
26120
|
}
|
|
26117
|
-
if (typeof credential
|
|
26121
|
+
if (typeof credential.expires !== "number" || !Number.isFinite(credential.expires) || credential.expires <= 0) {
|
|
26118
26122
|
throw new Error(`${label}: ${filename} credential expires must be a positive finite number`);
|
|
26119
26123
|
}
|
|
26120
|
-
return
|
|
26124
|
+
return credential;
|
|
26125
|
+
}
|
|
26126
|
+
function parseAccountRecord(raw, filename, label, index) {
|
|
26127
|
+
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
|
|
26128
|
+
throw new Error(`${label}: ${filename} accounts[${String(index)}] must be an object`);
|
|
26129
|
+
}
|
|
26130
|
+
const record = raw;
|
|
26131
|
+
const allowed = /* @__PURE__ */ new Set(["id", "label", "credential", "createdAt"]);
|
|
26132
|
+
if (Object.keys(record).some((key) => !allowed.has(key))) {
|
|
26133
|
+
throw new Error(`${label}: ${filename} accounts[${String(index)}] contains an unknown field`);
|
|
26134
|
+
}
|
|
26135
|
+
if (!isValidAccountId(record.id)) {
|
|
26136
|
+
throw new Error(`${label}: ${filename} accounts[${String(index)}].id is not a valid account id`);
|
|
26137
|
+
}
|
|
26138
|
+
if (record.label !== void 0 && (typeof record.label !== "string" || record.label.length === 0)) {
|
|
26139
|
+
throw new Error(`${label}: ${filename} accounts[${String(index)}].label must be a non-empty string when present`);
|
|
26140
|
+
}
|
|
26141
|
+
if (typeof record.createdAt !== "number" || !Number.isFinite(record.createdAt) || record.createdAt <= 0) {
|
|
26142
|
+
throw new Error(`${label}: ${filename} accounts[${String(index)}].createdAt must be a positive finite number`);
|
|
26143
|
+
}
|
|
26144
|
+
const credential = parseOAuthCredential(record.credential, filename, label);
|
|
26145
|
+
return {
|
|
26146
|
+
id: record.id,
|
|
26147
|
+
...record.label === void 0 ? {} : { label: record.label },
|
|
26148
|
+
credential,
|
|
26149
|
+
createdAt: record.createdAt
|
|
26150
|
+
};
|
|
26151
|
+
}
|
|
26152
|
+
function parseDocumentV2(document, filename, label) {
|
|
26153
|
+
if (Object.keys(document).some((key) => key !== "version" && key !== "activeAccountId" && key !== "accounts")) {
|
|
26154
|
+
throw new Error(`${label}: ${filename} contains an unknown top-level field`);
|
|
26155
|
+
}
|
|
26156
|
+
if (!isValidAccountId(document.activeAccountId)) {
|
|
26157
|
+
throw new Error(`${label}: ${filename} activeAccountId is not a valid account id`);
|
|
26158
|
+
}
|
|
26159
|
+
if (!Array.isArray(document.accounts)) {
|
|
26160
|
+
throw new Error(`${label}: ${filename} accounts must be an array`);
|
|
26161
|
+
}
|
|
26162
|
+
if (document.accounts.length < 1 || document.accounts.length > MAX_ACCOUNTS) {
|
|
26163
|
+
throw new Error(`${label}: ${filename} accounts must contain between 1 and ${String(MAX_ACCOUNTS)} entries`);
|
|
26164
|
+
}
|
|
26165
|
+
const accounts = document.accounts.map((entry, index) => parseAccountRecord(entry, filename, label, index));
|
|
26166
|
+
const ids = /* @__PURE__ */ new Set();
|
|
26167
|
+
for (const account of accounts) {
|
|
26168
|
+
if (ids.has(account.id)) {
|
|
26169
|
+
throw new Error(`${label}: ${filename} accounts contains a duplicate id`);
|
|
26170
|
+
}
|
|
26171
|
+
ids.add(account.id);
|
|
26172
|
+
}
|
|
26173
|
+
if (!ids.has(document.activeAccountId)) {
|
|
26174
|
+
throw new Error(`${label}: ${filename} activeAccountId does not match any account`);
|
|
26175
|
+
}
|
|
26176
|
+
return {
|
|
26177
|
+
version: AUTH_FORMAT_VERSION,
|
|
26178
|
+
activeAccountId: document.activeAccountId,
|
|
26179
|
+
accounts
|
|
26180
|
+
};
|
|
26181
|
+
}
|
|
26182
|
+
function parseDocumentV1(document, filename, label) {
|
|
26183
|
+
if (Object.keys(document).some((key) => key !== "version" && key !== "credential")) {
|
|
26184
|
+
throw new Error(`${label}: ${filename} contains an unknown top-level field`);
|
|
26185
|
+
}
|
|
26186
|
+
return parseOAuthCredential(document.credential, filename, label);
|
|
26187
|
+
}
|
|
26188
|
+
function parseDocument(text, filename, label) {
|
|
26189
|
+
let value;
|
|
26190
|
+
try {
|
|
26191
|
+
value = JSON.parse(text);
|
|
26192
|
+
} catch {
|
|
26193
|
+
throw new Error(`${label}: ${filename} is not valid JSON`);
|
|
26194
|
+
}
|
|
26195
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
26196
|
+
throw new Error(`${label}: ${filename} must contain an object`);
|
|
26197
|
+
}
|
|
26198
|
+
const document = value;
|
|
26199
|
+
if (document.version === AUTH_FORMAT_VERSION_V1) {
|
|
26200
|
+
return { document: migrateV1Credential(parseDocumentV1(document, filename, label)), migratedFromV1: true };
|
|
26201
|
+
}
|
|
26202
|
+
if (document.version === AUTH_FORMAT_VERSION) {
|
|
26203
|
+
return { document: parseDocumentV2(document, filename, label), migratedFromV1: false };
|
|
26204
|
+
}
|
|
26205
|
+
throw new Error(`${label}: ${filename} has unsupported auth format version ${String(document.version)}`);
|
|
26206
|
+
}
|
|
26207
|
+
function migrateV1Credential(credential) {
|
|
26208
|
+
const accountIdField = credential.accountId;
|
|
26209
|
+
const id = isValidAccountId(accountIdField) ? accountIdField : LEGACY_ACCOUNT_ID;
|
|
26210
|
+
return {
|
|
26211
|
+
version: AUTH_FORMAT_VERSION,
|
|
26212
|
+
activeAccountId: id,
|
|
26213
|
+
accounts: [
|
|
26214
|
+
{
|
|
26215
|
+
id,
|
|
26216
|
+
credential: cloneCredential(credential),
|
|
26217
|
+
createdAt: Date.now()
|
|
26218
|
+
}
|
|
26219
|
+
]
|
|
26220
|
+
};
|
|
26121
26221
|
}
|
|
26122
26222
|
function cloneCredential(credential) {
|
|
26123
26223
|
return structuredClone(credential);
|
|
26124
26224
|
}
|
|
26225
|
+
function cloneDocument(document) {
|
|
26226
|
+
return structuredClone(document);
|
|
26227
|
+
}
|
|
26228
|
+
function activeCredential(document) {
|
|
26229
|
+
const active = document.accounts.find((account) => account.id === document.activeAccountId);
|
|
26230
|
+
if (active === void 0) {
|
|
26231
|
+
throw new Error("active account missing from document");
|
|
26232
|
+
}
|
|
26233
|
+
return cloneCredential(active.credential);
|
|
26234
|
+
}
|
|
26235
|
+
function resolveAccountIdForCredential(credential) {
|
|
26236
|
+
const accountIdField = credential.accountId;
|
|
26237
|
+
if (isValidAccountId(accountIdField)) return accountIdField;
|
|
26238
|
+
return `acct-${randomBytes(8).toString("hex")}`;
|
|
26239
|
+
}
|
|
26240
|
+
function documentFromCredential(credential) {
|
|
26241
|
+
const id = resolveAccountIdForCredential(credential);
|
|
26242
|
+
return {
|
|
26243
|
+
version: AUTH_FORMAT_VERSION,
|
|
26244
|
+
activeAccountId: id,
|
|
26245
|
+
accounts: [
|
|
26246
|
+
{
|
|
26247
|
+
id,
|
|
26248
|
+
credential: cloneCredential(credential),
|
|
26249
|
+
createdAt: Date.now()
|
|
26250
|
+
}
|
|
26251
|
+
]
|
|
26252
|
+
};
|
|
26253
|
+
}
|
|
26254
|
+
function withUpdatedActiveCredential(document, credential) {
|
|
26255
|
+
const accounts = document.accounts.map(
|
|
26256
|
+
(account) => account.id === document.activeAccountId ? { ...account, credential: cloneCredential(credential) } : cloneAccount(account)
|
|
26257
|
+
);
|
|
26258
|
+
return {
|
|
26259
|
+
version: AUTH_FORMAT_VERSION,
|
|
26260
|
+
activeAccountId: document.activeAccountId,
|
|
26261
|
+
accounts
|
|
26262
|
+
};
|
|
26263
|
+
}
|
|
26264
|
+
function cloneAccount(account) {
|
|
26265
|
+
return {
|
|
26266
|
+
id: account.id,
|
|
26267
|
+
...account.label === void 0 ? {} : { label: account.label },
|
|
26268
|
+
credential: cloneCredential(account.credential),
|
|
26269
|
+
createdAt: account.createdAt
|
|
26270
|
+
};
|
|
26271
|
+
}
|
|
26272
|
+
function summarizeAccount(account) {
|
|
26273
|
+
const accountIdField = account.credential.accountId;
|
|
26274
|
+
return {
|
|
26275
|
+
id: account.id,
|
|
26276
|
+
...account.label === void 0 ? {} : { label: account.label },
|
|
26277
|
+
expires: account.credential.expires,
|
|
26278
|
+
...typeof accountIdField === "string" && accountIdField.length > 0 ? { accountId: accountIdField } : {}
|
|
26279
|
+
};
|
|
26280
|
+
}
|
|
26281
|
+
function validatedDocument(document, filename, label) {
|
|
26282
|
+
return parseDocument(JSON.stringify(document), filename, label).document;
|
|
26283
|
+
}
|
|
26125
26284
|
function oauthCredentialPath(basename, dshHome) {
|
|
26126
26285
|
if (basename.length === 0 || basename.length > 128 || basename === "." || basename === ".." || !/^\.?[A-Za-z0-9][A-Za-z0-9._-]*$/u.test(basename)) {
|
|
26127
26286
|
throw new TypeError("OAuth credential basename must be a safe local filename");
|
|
@@ -26140,6 +26299,7 @@ var OAuthCredentialFileStore = class {
|
|
|
26140
26299
|
providerId;
|
|
26141
26300
|
label;
|
|
26142
26301
|
filename;
|
|
26302
|
+
loginPersist;
|
|
26143
26303
|
async readCurrent() {
|
|
26144
26304
|
return this.loadCurrent({ allowUnreadable: false });
|
|
26145
26305
|
}
|
|
@@ -26149,6 +26309,10 @@ var OAuthCredentialFileStore = class {
|
|
|
26149
26309
|
* Unsafe/symlink/wrong-owner/too-large files still throw.
|
|
26150
26310
|
*/
|
|
26151
26311
|
async loadCurrent(options) {
|
|
26312
|
+
const loaded = await this.loadDocument({ allowUnreadable: options.allowUnreadable, persistMigration: false });
|
|
26313
|
+
return loaded === void 0 ? void 0 : activeCredential(loaded.document);
|
|
26314
|
+
}
|
|
26315
|
+
async loadDocument(options) {
|
|
26152
26316
|
let text;
|
|
26153
26317
|
try {
|
|
26154
26318
|
text = (await readHardenedOAuthSourceFile(this.filename)).text;
|
|
@@ -26160,7 +26324,11 @@ var OAuthCredentialFileStore = class {
|
|
|
26160
26324
|
throw error;
|
|
26161
26325
|
}
|
|
26162
26326
|
try {
|
|
26163
|
-
|
|
26327
|
+
const parsed = parseDocument(text, this.filename, this.label);
|
|
26328
|
+
if (options.persistMigration && parsed.migratedFromV1) {
|
|
26329
|
+
await this.writeDocument(parsed.document);
|
|
26330
|
+
}
|
|
26331
|
+
return parsed;
|
|
26164
26332
|
} catch (error) {
|
|
26165
26333
|
if (options.allowUnreadable) return void 0;
|
|
26166
26334
|
throw error;
|
|
@@ -26178,6 +26346,91 @@ var OAuthCredentialFileStore = class {
|
|
|
26178
26346
|
throw error;
|
|
26179
26347
|
}
|
|
26180
26348
|
}
|
|
26349
|
+
async writeDocument(document) {
|
|
26350
|
+
const validated = validatedDocument(document, this.filename, this.label);
|
|
26351
|
+
await this.assertDestinationReplaceable();
|
|
26352
|
+
await writeFileAtomic(this.filename, `${JSON.stringify(validated, null, 2)}
|
|
26353
|
+
`, {
|
|
26354
|
+
mode: 384,
|
|
26355
|
+
dirMode: 448
|
|
26356
|
+
});
|
|
26357
|
+
return cloneDocument(validated);
|
|
26358
|
+
}
|
|
26359
|
+
nextDocumentAfterLogin(current, credential, options) {
|
|
26360
|
+
const parsed = parseOAuthCredential(credential, this.filename, this.label);
|
|
26361
|
+
if (options.mode === "overwrite-active") {
|
|
26362
|
+
if (current === void 0) return documentFromCredential(parsed);
|
|
26363
|
+
if (options.confirmOverwrite !== true) {
|
|
26364
|
+
throw new Error(`${this.label}: confirmOverwrite is required to replace the active account`);
|
|
26365
|
+
}
|
|
26366
|
+
return withUpdatedActiveCredential(current, parsed);
|
|
26367
|
+
}
|
|
26368
|
+
const id = resolveAccountIdForCredential(parsed);
|
|
26369
|
+
if (current === void 0) {
|
|
26370
|
+
return {
|
|
26371
|
+
version: AUTH_FORMAT_VERSION,
|
|
26372
|
+
activeAccountId: id,
|
|
26373
|
+
accounts: [
|
|
26374
|
+
{
|
|
26375
|
+
id,
|
|
26376
|
+
credential: cloneCredential(parsed),
|
|
26377
|
+
createdAt: Date.now()
|
|
26378
|
+
}
|
|
26379
|
+
]
|
|
26380
|
+
};
|
|
26381
|
+
}
|
|
26382
|
+
const existingIndex = current.accounts.findIndex((account) => account.id === id);
|
|
26383
|
+
if (existingIndex < 0 && current.accounts.length >= MAX_ACCOUNTS) {
|
|
26384
|
+
throw new Error(`${this.label}: at most ${String(MAX_ACCOUNTS)} accounts may be stored`);
|
|
26385
|
+
}
|
|
26386
|
+
const accounts = current.accounts.map(cloneAccount);
|
|
26387
|
+
if (existingIndex >= 0) {
|
|
26388
|
+
const existing = accounts[existingIndex];
|
|
26389
|
+
if (existing === void 0) {
|
|
26390
|
+
throw new Error(`${this.label}: account "${id}" is not stored`);
|
|
26391
|
+
}
|
|
26392
|
+
accounts[existingIndex] = {
|
|
26393
|
+
id,
|
|
26394
|
+
...existing.label === void 0 ? {} : { label: existing.label },
|
|
26395
|
+
credential: cloneCredential(parsed),
|
|
26396
|
+
createdAt: existing.createdAt
|
|
26397
|
+
};
|
|
26398
|
+
} else {
|
|
26399
|
+
accounts.push({
|
|
26400
|
+
id,
|
|
26401
|
+
credential: cloneCredential(parsed),
|
|
26402
|
+
createdAt: Date.now()
|
|
26403
|
+
});
|
|
26404
|
+
}
|
|
26405
|
+
return {
|
|
26406
|
+
version: AUTH_FORMAT_VERSION,
|
|
26407
|
+
activeAccountId: id,
|
|
26408
|
+
accounts
|
|
26409
|
+
};
|
|
26410
|
+
}
|
|
26411
|
+
async mutateDocument(options, fn) {
|
|
26412
|
+
await mkdir(dirname(this.filename), { recursive: true, mode: 448 });
|
|
26413
|
+
return withFileLock(this.filename, async () => {
|
|
26414
|
+
const loaded = await this.loadDocument({
|
|
26415
|
+
allowUnreadable: options.allowUnreadable,
|
|
26416
|
+
persistMigration: false
|
|
26417
|
+
});
|
|
26418
|
+
const current = loaded === void 0 ? void 0 : loaded.document;
|
|
26419
|
+
const migratedFromV1 = loaded?.migratedFromV1 === true;
|
|
26420
|
+
const next = await fn(current === void 0 ? void 0 : cloneDocument(current));
|
|
26421
|
+
if (next === UNCHANGED) {
|
|
26422
|
+
if (migratedFromV1 && current !== void 0) {
|
|
26423
|
+
return this.writeDocument(current);
|
|
26424
|
+
}
|
|
26425
|
+
return current === void 0 ? void 0 : cloneDocument(current);
|
|
26426
|
+
}
|
|
26427
|
+
if (next === void 0) {
|
|
26428
|
+
await rm(this.filename, { force: true });
|
|
26429
|
+
return void 0;
|
|
26430
|
+
}
|
|
26431
|
+
return this.writeDocument(next);
|
|
26432
|
+
});
|
|
26433
|
+
}
|
|
26181
26434
|
async read(providerId) {
|
|
26182
26435
|
return providerId === this.providerId ? this.readCurrent() : void 0;
|
|
26183
26436
|
}
|
|
@@ -26188,27 +26441,42 @@ var OAuthCredentialFileStore = class {
|
|
|
26188
26441
|
if (providerId !== this.providerId) {
|
|
26189
26442
|
throw new Error(`${this.label}: credential store does not own provider "${providerId}"`);
|
|
26190
26443
|
}
|
|
26191
|
-
await
|
|
26192
|
-
|
|
26193
|
-
const
|
|
26194
|
-
|
|
26195
|
-
if (candidate
|
|
26196
|
-
|
|
26197
|
-
|
|
26198
|
-
|
|
26199
|
-
|
|
26200
|
-
|
|
26201
|
-
|
|
26202
|
-
|
|
26203
|
-
);
|
|
26204
|
-
await this.assertDestinationReplaceable();
|
|
26205
|
-
await writeFileAtomic(this.filename, `${JSON.stringify(document, null, 2)}
|
|
26206
|
-
`, {
|
|
26207
|
-
mode: 384,
|
|
26208
|
-
dirMode: 448
|
|
26209
|
-
});
|
|
26210
|
-
return cloneCredential(document.credential);
|
|
26444
|
+
const document = await this.mutateDocument({ allowUnreadable: true }, async (current) => {
|
|
26445
|
+
const active = current === void 0 ? void 0 : activeCredential(current);
|
|
26446
|
+
const candidate = await fn(active);
|
|
26447
|
+
if (candidate === void 0) return UNCHANGED;
|
|
26448
|
+
if (candidate.type !== "oauth") {
|
|
26449
|
+
throw new Error(`${this.label}: ${this.filename} credential type must be oauth`);
|
|
26450
|
+
}
|
|
26451
|
+
if (this.loginPersist !== void 0) {
|
|
26452
|
+
return this.nextDocumentAfterLogin(current, candidate, this.loginPersist);
|
|
26453
|
+
}
|
|
26454
|
+
if (current === void 0) return documentFromCredential(candidate);
|
|
26455
|
+
return withUpdatedActiveCredential(current, candidate);
|
|
26211
26456
|
});
|
|
26457
|
+
return document === void 0 ? void 0 : activeCredential(document);
|
|
26458
|
+
}
|
|
26459
|
+
/**
|
|
26460
|
+
* Redirect `modify` writes (pi-ai `models.login`) through multi-account upsert
|
|
26461
|
+
* semantics for the duration of `fn`.
|
|
26462
|
+
*/
|
|
26463
|
+
async runLoginPersist(options, fn) {
|
|
26464
|
+
if (this.loginPersist !== void 0) {
|
|
26465
|
+
throw new Error(`${this.label}: login persist already in progress`);
|
|
26466
|
+
}
|
|
26467
|
+
this.loginPersist = options;
|
|
26468
|
+
try {
|
|
26469
|
+
return await fn();
|
|
26470
|
+
} finally {
|
|
26471
|
+
this.loginPersist = void 0;
|
|
26472
|
+
}
|
|
26473
|
+
}
|
|
26474
|
+
/** Persist a login/import credential without going through pi-ai `modify`. */
|
|
26475
|
+
async persistLoginCredential(credential, options) {
|
|
26476
|
+
await this.mutateDocument(
|
|
26477
|
+
{ allowUnreadable: true },
|
|
26478
|
+
async (current) => this.nextDocumentAfterLogin(current, credential, options)
|
|
26479
|
+
);
|
|
26212
26480
|
}
|
|
26213
26481
|
/**
|
|
26214
26482
|
* Force the next `getAuth()` to refresh by backdating `expires` into the past.
|
|
@@ -26233,6 +26501,163 @@ var OAuthCredentialFileStore = class {
|
|
|
26233
26501
|
await mkdir(dirname(this.filename), { recursive: true, mode: 448 });
|
|
26234
26502
|
await withFileLock(this.filename, () => rm(this.filename, { force: true }));
|
|
26235
26503
|
}
|
|
26504
|
+
/** Read-only account list for Settings / API. Never includes tokens. */
|
|
26505
|
+
async listAccounts() {
|
|
26506
|
+
const document = await this.mutateDocument({ allowUnreadable: false }, async (current) => {
|
|
26507
|
+
if (current === void 0) return UNCHANGED;
|
|
26508
|
+
return UNCHANGED;
|
|
26509
|
+
});
|
|
26510
|
+
if (document === void 0) return [];
|
|
26511
|
+
return document.accounts.map(summarizeAccount);
|
|
26512
|
+
}
|
|
26513
|
+
async getActiveAccountId() {
|
|
26514
|
+
const document = await this.mutateDocument({ allowUnreadable: false }, async (current) => {
|
|
26515
|
+
if (current === void 0) return UNCHANGED;
|
|
26516
|
+
return UNCHANGED;
|
|
26517
|
+
});
|
|
26518
|
+
return document?.activeAccountId;
|
|
26519
|
+
}
|
|
26520
|
+
/**
|
|
26521
|
+
* Read one account's credential without changing activeAccountId.
|
|
26522
|
+
* Used by the optional quota-aware pool proxy for sticky per-request routing.
|
|
26523
|
+
*/
|
|
26524
|
+
async readAccount(id) {
|
|
26525
|
+
if (!isValidAccountId(id)) return void 0;
|
|
26526
|
+
const document = await this.mutateDocument({ allowUnreadable: false }, async (current) => {
|
|
26527
|
+
if (current === void 0) return UNCHANGED;
|
|
26528
|
+
return UNCHANGED;
|
|
26529
|
+
});
|
|
26530
|
+
const account = document?.accounts.find((entry) => entry.id === id);
|
|
26531
|
+
return account === void 0 ? void 0 : cloneCredential(account.credential);
|
|
26532
|
+
}
|
|
26533
|
+
/**
|
|
26534
|
+
* Serialized refresh/write for one account id. Does not move activeAccountId.
|
|
26535
|
+
* Returns undefined when the account is absent (caller treats as missing credential).
|
|
26536
|
+
*/
|
|
26537
|
+
async modifyAccount(id, fn) {
|
|
26538
|
+
if (!isValidAccountId(id)) {
|
|
26539
|
+
throw new TypeError(`${this.label}: account id is invalid`);
|
|
26540
|
+
}
|
|
26541
|
+
const document = await this.mutateDocument({ allowUnreadable: true }, async (current) => {
|
|
26542
|
+
if (current === void 0) return UNCHANGED;
|
|
26543
|
+
const index = current.accounts.findIndex((account2) => account2.id === id);
|
|
26544
|
+
if (index < 0) return UNCHANGED;
|
|
26545
|
+
const existing = current.accounts[index];
|
|
26546
|
+
if (existing === void 0) return UNCHANGED;
|
|
26547
|
+
const candidate = await fn(cloneCredential(existing.credential));
|
|
26548
|
+
if (candidate === void 0) return UNCHANGED;
|
|
26549
|
+
if (candidate.type !== "oauth") {
|
|
26550
|
+
throw new Error(`${this.label}: ${this.filename} credential type must be oauth`);
|
|
26551
|
+
}
|
|
26552
|
+
const accounts = current.accounts.map(cloneAccount);
|
|
26553
|
+
const target = accounts[index];
|
|
26554
|
+
if (target === void 0) return UNCHANGED;
|
|
26555
|
+
accounts[index] = {
|
|
26556
|
+
...target,
|
|
26557
|
+
credential: cloneCredential(candidate)
|
|
26558
|
+
};
|
|
26559
|
+
return {
|
|
26560
|
+
version: AUTH_FORMAT_VERSION,
|
|
26561
|
+
activeAccountId: current.activeAccountId,
|
|
26562
|
+
accounts
|
|
26563
|
+
};
|
|
26564
|
+
});
|
|
26565
|
+
if (document === void 0) return void 0;
|
|
26566
|
+
const account = document.accounts.find((entry) => entry.id === id);
|
|
26567
|
+
return account === void 0 ? void 0 : cloneCredential(account.credential);
|
|
26568
|
+
}
|
|
26569
|
+
async setActiveAccount(id) {
|
|
26570
|
+
if (!isValidAccountId(id)) {
|
|
26571
|
+
throw new TypeError(`${this.label}: account id is invalid`);
|
|
26572
|
+
}
|
|
26573
|
+
await this.mutateDocument({ allowUnreadable: false }, async (current) => {
|
|
26574
|
+
if (current === void 0) {
|
|
26575
|
+
throw new Error(`${this.label}: no credential accounts are stored`);
|
|
26576
|
+
}
|
|
26577
|
+
if (!current.accounts.some((account) => account.id === id)) {
|
|
26578
|
+
throw new Error(`${this.label}: account "${id}" is not stored`);
|
|
26579
|
+
}
|
|
26580
|
+
if (current.activeAccountId === id) return UNCHANGED;
|
|
26581
|
+
return {
|
|
26582
|
+
version: AUTH_FORMAT_VERSION,
|
|
26583
|
+
activeAccountId: id,
|
|
26584
|
+
accounts: current.accounts.map(cloneAccount)
|
|
26585
|
+
};
|
|
26586
|
+
});
|
|
26587
|
+
}
|
|
26588
|
+
async upsertAccount(input) {
|
|
26589
|
+
if (!isValidAccountId(input.id)) {
|
|
26590
|
+
throw new TypeError(`${this.label}: account id is invalid`);
|
|
26591
|
+
}
|
|
26592
|
+
if (input.label !== void 0 && (typeof input.label !== "string" || input.label.length === 0)) {
|
|
26593
|
+
throw new TypeError(`${this.label}: account label must be a non-empty string when present`);
|
|
26594
|
+
}
|
|
26595
|
+
const credential = parseOAuthCredential(input.credential, this.filename, this.label);
|
|
26596
|
+
await this.mutateDocument({ allowUnreadable: false }, async (current) => {
|
|
26597
|
+
if (current === void 0) {
|
|
26598
|
+
return {
|
|
26599
|
+
version: AUTH_FORMAT_VERSION,
|
|
26600
|
+
activeAccountId: input.id,
|
|
26601
|
+
accounts: [
|
|
26602
|
+
{
|
|
26603
|
+
id: input.id,
|
|
26604
|
+
...input.label === void 0 ? {} : { label: input.label },
|
|
26605
|
+
credential: cloneCredential(credential),
|
|
26606
|
+
createdAt: Date.now()
|
|
26607
|
+
}
|
|
26608
|
+
]
|
|
26609
|
+
};
|
|
26610
|
+
}
|
|
26611
|
+
const existingIndex = current.accounts.findIndex((account) => account.id === input.id);
|
|
26612
|
+
if (existingIndex < 0 && current.accounts.length >= MAX_ACCOUNTS) {
|
|
26613
|
+
throw new Error(`${this.label}: at most ${String(MAX_ACCOUNTS)} accounts may be stored`);
|
|
26614
|
+
}
|
|
26615
|
+
const accounts = current.accounts.map(cloneAccount);
|
|
26616
|
+
if (existingIndex >= 0) {
|
|
26617
|
+
const existing = accounts[existingIndex];
|
|
26618
|
+
if (existing === void 0) {
|
|
26619
|
+
throw new Error(`${this.label}: account "${input.id}" is not stored`);
|
|
26620
|
+
}
|
|
26621
|
+
accounts[existingIndex] = {
|
|
26622
|
+
id: input.id,
|
|
26623
|
+
...input.label !== void 0 ? { label: input.label } : existing.label === void 0 ? {} : { label: existing.label },
|
|
26624
|
+
credential: cloneCredential(credential),
|
|
26625
|
+
createdAt: existing.createdAt
|
|
26626
|
+
};
|
|
26627
|
+
} else {
|
|
26628
|
+
accounts.push({
|
|
26629
|
+
id: input.id,
|
|
26630
|
+
...input.label === void 0 ? {} : { label: input.label },
|
|
26631
|
+
credential: cloneCredential(credential),
|
|
26632
|
+
createdAt: Date.now()
|
|
26633
|
+
});
|
|
26634
|
+
}
|
|
26635
|
+
return {
|
|
26636
|
+
version: AUTH_FORMAT_VERSION,
|
|
26637
|
+
activeAccountId: input.makeActive === true ? input.id : current.activeAccountId,
|
|
26638
|
+
accounts
|
|
26639
|
+
};
|
|
26640
|
+
});
|
|
26641
|
+
}
|
|
26642
|
+
async removeAccount(id) {
|
|
26643
|
+
if (!isValidAccountId(id)) {
|
|
26644
|
+
throw new TypeError(`${this.label}: account id is invalid`);
|
|
26645
|
+
}
|
|
26646
|
+
await this.mutateDocument({ allowUnreadable: false }, async (current) => {
|
|
26647
|
+
if (current === void 0) return UNCHANGED;
|
|
26648
|
+
const accounts = current.accounts.filter((account) => account.id !== id).map(cloneAccount);
|
|
26649
|
+
if (accounts.length === current.accounts.length) return UNCHANGED;
|
|
26650
|
+
if (accounts.length === 0) return void 0;
|
|
26651
|
+
const fallback = accounts[0];
|
|
26652
|
+
if (fallback === void 0) return void 0;
|
|
26653
|
+
const activeAccountId = current.activeAccountId === id ? fallback.id : current.activeAccountId;
|
|
26654
|
+
return {
|
|
26655
|
+
version: AUTH_FORMAT_VERSION,
|
|
26656
|
+
activeAccountId,
|
|
26657
|
+
accounts
|
|
26658
|
+
};
|
|
26659
|
+
});
|
|
26660
|
+
}
|
|
26236
26661
|
};
|
|
26237
26662
|
var GrokBuildCredentialStore = class extends OAuthCredentialFileStore {
|
|
26238
26663
|
constructor(filename = grokBuildAuthPath()) {
|
|
@@ -26325,7 +26750,7 @@ var GATEWAY_TOS_WARNING = "local API gateway is enabled; exposing a subscription
|
|
|
26325
26750
|
|
|
26326
26751
|
// src/oauth.ts
|
|
26327
26752
|
import { Buffer as Buffer2 } from "node:buffer";
|
|
26328
|
-
import { createHash, randomBytes } from "node:crypto";
|
|
26753
|
+
import { createHash, randomBytes as randomBytes2 } from "node:crypto";
|
|
26329
26754
|
import { createServer } from "node:http";
|
|
26330
26755
|
var GROK_BUILD_OAUTH_ISSUER = "https://auth.x.ai";
|
|
26331
26756
|
var APPROVED_GROK_ISSUER_ORIGIN2 = "https://auth.x.ai";
|
|
@@ -26492,12 +26917,12 @@ async function discoverOAuthEndpoints(issuer, signal, options = {}) {
|
|
|
26492
26917
|
return parsed;
|
|
26493
26918
|
}
|
|
26494
26919
|
function generatePkce() {
|
|
26495
|
-
const verifier =
|
|
26920
|
+
const verifier = randomBytes2(32).toString("base64url");
|
|
26496
26921
|
const challenge = createHash("sha256").update(verifier).digest("base64url");
|
|
26497
26922
|
return { verifier, challenge };
|
|
26498
26923
|
}
|
|
26499
26924
|
function randomToken() {
|
|
26500
|
-
return
|
|
26925
|
+
return randomBytes2(16).toString("base64url");
|
|
26501
26926
|
}
|
|
26502
26927
|
function buildAuthorizeUrl(endpoints, params, redirectUri, challenge, state, nonce) {
|
|
26503
26928
|
const url = new URL(endpoints.authorization_endpoint);
|
|
@@ -26931,6 +27356,10 @@ var OAuthProviderSession = class {
|
|
|
26931
27356
|
async invalidateAccessToken() {
|
|
26932
27357
|
await this.store.invalidate(this.definition.nativeProviderId);
|
|
26933
27358
|
}
|
|
27359
|
+
/** Refresh host discovery after an account switch/remove without a full logout. */
|
|
27360
|
+
notifyCredentialChange() {
|
|
27361
|
+
this.onCatalogChange?.();
|
|
27362
|
+
}
|
|
26934
27363
|
async storedCredential() {
|
|
26935
27364
|
const credential = await this.store.read(this.definition.nativeProviderId);
|
|
26936
27365
|
return credential?.type === "oauth" ? credential : void 0;
|
|
@@ -27363,6 +27792,10 @@ var GrokBuildSession = class {
|
|
|
27363
27792
|
async invalidateAccessToken() {
|
|
27364
27793
|
await this.store.invalidate(XAI_PI_PROVIDER);
|
|
27365
27794
|
}
|
|
27795
|
+
/** Refresh host discovery after an account switch/remove without a full logout. */
|
|
27796
|
+
notifyCredentialChange() {
|
|
27797
|
+
this.onCatalogChange?.();
|
|
27798
|
+
}
|
|
27366
27799
|
async logout() {
|
|
27367
27800
|
try {
|
|
27368
27801
|
await this.store.delete(XAI_PI_PROVIDER);
|