refactor(app): DRY pass — split large files, extract shared utils
S1: delete page.new.js (1724L abandoned) + remove dead getAntigravityProjectId
S2: split large files by natural seams
- usage.js → usage/{github,google,claude,codex,kiro,minimax,misc,shared}.js
- media-providers page → components/{Embedding,Tts,Generic,Stt}ExampleCard.js
- EndpointPageClient → endpointConstants.js + endpointPing.js + components/
- tokenRefresh.js → tokenRefresh/{dedup,providers}.js
- ProviderLimits/index.js: 16 pure fn + 9 constants → utils.js
- oauth/providers.js: 7 pure helpers → providerHelpers.js
S3: shared utils
- getModelKind(m, fallback) → shared/constants/models.js (replaces 20× m.kind||m.type)
- getStatusVariant → shared/utils/connectionStatus.js (dedup ConnectionRow/ConnectionsCard)
- sseChunk → open-sse/utils/sse.js (dedup grok-web/perplexity-web)
- fetchWithTimeout → usage/shared.js (replace 4× AbortController pattern in google.js)
fix: enableObservability2 field name in requestDetailsRepo
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -16,8 +16,8 @@ async function getObservabilityConfig() {
|
||||
const { getSettings } = await import("./settingsRepo.js");
|
||||
const settings = await getSettings();
|
||||
const envEnabled = process.env.OBSERVABILITY_ENABLED !== "false";
|
||||
const enabled = typeof settings.enableObservability === "boolean"
|
||||
? settings.enableObservability
|
||||
const enabled = typeof settings.enableObservability2 === "boolean"
|
||||
? settings.enableObservability2
|
||||
: envEnabled;
|
||||
cachedConfig = {
|
||||
enabled,
|
||||
|
||||
90
src/lib/oauth/providerHelpers.js
Normal file
90
src/lib/oauth/providerHelpers.js
Normal file
@@ -0,0 +1,90 @@
|
||||
const BASE64_BLOCK_SIZE = 4;
|
||||
|
||||
function validateXaiOAuthEndpoint(rawUrl, field) {
|
||||
const value = String(rawUrl || "").trim();
|
||||
if (!value) throw new Error(`xai discovery ${field} is empty`);
|
||||
let parsed;
|
||||
try { parsed = new URL(value); } catch (err) {
|
||||
throw new Error(`xai discovery ${field} is invalid: ${err.message}`);
|
||||
}
|
||||
if (parsed.protocol !== "https:") throw new Error(`xai discovery ${field} must use https: ${value}`);
|
||||
const host = parsed.hostname.toLowerCase().trim();
|
||||
if (host !== "x.ai" && !host.endsWith(".x.ai")) {
|
||||
throw new Error(`xai discovery ${field} host ${host} is not on x.ai`);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
function decodeXaiIdTokenEmail(idToken) {
|
||||
if (!idToken || typeof idToken !== "string") return undefined;
|
||||
const parts = idToken.split(".");
|
||||
if (parts.length !== 3) return undefined;
|
||||
try {
|
||||
const base64 = parts[1].replace(/-/g, "+").replace(/_/g, "/");
|
||||
const padding = (BASE64_BLOCK_SIZE - (base64.length % BASE64_BLOCK_SIZE)) % BASE64_BLOCK_SIZE;
|
||||
const json = Buffer.from(base64 + "=".repeat(padding), "base64").toString("utf8");
|
||||
const payload = JSON.parse(json);
|
||||
return payload.email || payload.preferred_username || payload.sub || undefined;
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function decodeJwtPayload(jwt) {
|
||||
try {
|
||||
if (!jwt || typeof jwt !== "string") return null;
|
||||
const parts = jwt.split(".");
|
||||
if (parts.length !== 3) return null;
|
||||
const base64 = parts[1].replace(/-/g, "+").replace(/_/g, "/");
|
||||
const missingPadding = (BASE64_BLOCK_SIZE - (base64.length % BASE64_BLOCK_SIZE)) % BASE64_BLOCK_SIZE;
|
||||
const padded = base64 + "=".repeat(missingPadding);
|
||||
return JSON.parse(Buffer.from(padded, "base64").toString("utf8"));
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function extractEmailFromAccessToken(accessToken) {
|
||||
const payload = decodeJwtPayload(accessToken);
|
||||
if (!payload) return undefined;
|
||||
return payload.email || payload.preferred_username || payload.sub || undefined;
|
||||
}
|
||||
|
||||
export async function fetchKiroProfileArn(accessToken) {
|
||||
if (!accessToken) return null;
|
||||
try {
|
||||
const response = await fetch("https://codewhisperer.us-east-1.amazonaws.com/ListAvailableProfiles", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Accept: "application/json",
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
body: JSON.stringify({ maxResults: 10 }),
|
||||
});
|
||||
if (!response.ok) return null;
|
||||
const data = await response.json();
|
||||
return data.profiles?.find((p) => p.arn?.trim())?.arn?.trim() || null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export function extractCodexAccountInfo(idToken) {
|
||||
const payload = decodeJwtPayload(idToken);
|
||||
if (!payload) return {};
|
||||
const chatgpt = payload["https://api.openai.com/auth"] || {};
|
||||
return {
|
||||
email: payload.email,
|
||||
chatgptAccountId: chatgpt.chatgpt_account_id || payload.account_id,
|
||||
chatgptPlanType: chatgpt.chatgpt_plan_type || payload.plan_type,
|
||||
};
|
||||
}
|
||||
|
||||
export {
|
||||
BASE64_BLOCK_SIZE,
|
||||
validateXaiOAuthEndpoint,
|
||||
decodeXaiIdTokenEmail,
|
||||
decodeJwtPayload,
|
||||
extractEmailFromAccessToken,
|
||||
};
|
||||
@@ -27,25 +27,19 @@ import {
|
||||
getOAuthClientMetadata,
|
||||
} from "./constants/oauth";
|
||||
import { XAI_CONFIG, XAI_PKCE_VERIFIER_BYTES } from "./constants/xai";
|
||||
import {
|
||||
validateXaiOAuthEndpoint,
|
||||
decodeXaiIdTokenEmail,
|
||||
extractEmailFromAccessToken,
|
||||
extractCodexAccountInfo,
|
||||
fetchKiroProfileArn,
|
||||
} from "./providerHelpers";
|
||||
|
||||
export { extractCodexAccountInfo, fetchKiroProfileArn };
|
||||
|
||||
// Inlined from services/xai.js to keep web route bundle free of `open` (CLI-only) package
|
||||
let cachedXaiDiscovery = null;
|
||||
|
||||
function validateXaiOAuthEndpoint(rawUrl, field) {
|
||||
const value = String(rawUrl || "").trim();
|
||||
if (!value) throw new Error(`xai discovery ${field} is empty`);
|
||||
let parsed;
|
||||
try { parsed = new URL(value); } catch (err) {
|
||||
throw new Error(`xai discovery ${field} is invalid: ${err.message}`);
|
||||
}
|
||||
if (parsed.protocol !== "https:") throw new Error(`xai discovery ${field} must use https: ${value}`);
|
||||
const host = parsed.hostname.toLowerCase().trim();
|
||||
if (host !== "x.ai" && !host.endsWith(".x.ai")) {
|
||||
throw new Error(`xai discovery ${field} host ${host} is not on x.ai`);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
async function discoverXaiEndpoints() {
|
||||
if (cachedXaiDiscovery) return cachedXaiDiscovery;
|
||||
try {
|
||||
@@ -63,81 +57,6 @@ async function discoverXaiEndpoints() {
|
||||
return cachedXaiDiscovery;
|
||||
}
|
||||
|
||||
function decodeXaiIdTokenEmail(idToken) {
|
||||
if (!idToken || typeof idToken !== "string") return undefined;
|
||||
const parts = idToken.split(".");
|
||||
if (parts.length !== 3) return undefined;
|
||||
try {
|
||||
const base64 = parts[1].replace(/-/g, "+").replace(/_/g, "/");
|
||||
const padding = (BASE64_BLOCK_SIZE - (base64.length % BASE64_BLOCK_SIZE)) % BASE64_BLOCK_SIZE;
|
||||
const json = Buffer.from(base64 + "=".repeat(padding), "base64").toString("utf8");
|
||||
const payload = JSON.parse(json);
|
||||
return payload.email || payload.preferred_username || payload.sub || undefined;
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
const BASE64_BLOCK_SIZE = 4;
|
||||
|
||||
/**
|
||||
* Decode JWT access token and extract a stable account identifier for display/upsert.
|
||||
* @param {string} accessToken
|
||||
* @returns {string|undefined}
|
||||
*/
|
||||
function decodeJwtPayload(jwt) {
|
||||
try {
|
||||
if (!jwt || typeof jwt !== "string") return null;
|
||||
const parts = jwt.split(".");
|
||||
if (parts.length !== 3) return null;
|
||||
const base64 = parts[1].replace(/-/g, "+").replace(/_/g, "/");
|
||||
const missingPadding = (BASE64_BLOCK_SIZE - (base64.length % BASE64_BLOCK_SIZE)) % BASE64_BLOCK_SIZE;
|
||||
const padded = base64 + "=".repeat(missingPadding);
|
||||
return JSON.parse(Buffer.from(padded, "base64").toString("utf8"));
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function extractEmailFromAccessToken(accessToken) {
|
||||
const payload = decodeJwtPayload(accessToken);
|
||||
if (!payload) return undefined;
|
||||
return payload.email || payload.preferred_username || payload.sub || undefined;
|
||||
}
|
||||
|
||||
// Resolve Kiro profileArn via CodeWhisperer (IDC/Builder-ID tokens omit it, causing 403)
|
||||
export async function fetchKiroProfileArn(accessToken) {
|
||||
if (!accessToken) return null;
|
||||
try {
|
||||
const response = await fetch("https://codewhisperer.us-east-1.amazonaws.com/ListAvailableProfiles", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Accept: "application/json",
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
body: JSON.stringify({ maxResults: 10 }),
|
||||
});
|
||||
if (!response.ok) return null;
|
||||
const data = await response.json();
|
||||
return data.profiles?.find((p) => p.arn?.trim())?.arn?.trim() || null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Extract codex account info from id_token or access token
|
||||
export function extractCodexAccountInfo(idToken) {
|
||||
const payload = decodeJwtPayload(idToken);
|
||||
if (!payload) return {};
|
||||
const chatgpt = payload["https://api.openai.com/auth"] || {};
|
||||
return {
|
||||
email: payload.email,
|
||||
chatgptAccountId: chatgpt.chatgpt_account_id || payload.account_id,
|
||||
chatgptPlanType: chatgpt.chatgpt_plan_type || payload.plan_type,
|
||||
};
|
||||
}
|
||||
|
||||
// Provider configurations
|
||||
const PROVIDERS = {
|
||||
claude: {
|
||||
|
||||
Reference in New Issue
Block a user