110 lines
3.1 KiB
JavaScript
110 lines
3.1 KiB
JavaScript
|
|
/**
|
||
|
|
* Google Provider - Transforms
|
||
|
|
*
|
||
|
|
* Data transformation functions for Google quota responses.
|
||
|
|
* @module quota/providers/google/transforms
|
||
|
|
*/
|
||
|
|
|
||
|
|
import {
|
||
|
|
asNonEmptyString,
|
||
|
|
toNumber,
|
||
|
|
toTimestamp,
|
||
|
|
toUsageWindow
|
||
|
|
} from '../../utils/index.js';
|
||
|
|
|
||
|
|
const GOOGLE_FIVE_HOUR_WINDOW_SECONDS = 5 * 60 * 60;
|
||
|
|
const GOOGLE_DAILY_WINDOW_SECONDS = 24 * 60 * 60;
|
||
|
|
|
||
|
|
export const parseGoogleRefreshToken = (rawRefreshToken) => {
|
||
|
|
const refreshToken = asNonEmptyString(rawRefreshToken);
|
||
|
|
if (!refreshToken) {
|
||
|
|
return { refreshToken: null, projectId: null, managedProjectId: null };
|
||
|
|
}
|
||
|
|
|
||
|
|
const [rawToken = '', rawProject = '', rawManagedProject = ''] = refreshToken.split('|');
|
||
|
|
return {
|
||
|
|
refreshToken: asNonEmptyString(rawToken),
|
||
|
|
projectId: asNonEmptyString(rawProject),
|
||
|
|
managedProjectId: asNonEmptyString(rawManagedProject)
|
||
|
|
};
|
||
|
|
};
|
||
|
|
|
||
|
|
export const resolveGoogleWindow = (sourceId, resetAt) => {
|
||
|
|
if (sourceId === 'gemini') {
|
||
|
|
return { label: 'daily', seconds: GOOGLE_DAILY_WINDOW_SECONDS };
|
||
|
|
}
|
||
|
|
|
||
|
|
if (sourceId === 'antigravity') {
|
||
|
|
const remainingSeconds = typeof resetAt === 'number'
|
||
|
|
? Math.max(0, Math.round((resetAt - Date.now()) / 1000))
|
||
|
|
: null;
|
||
|
|
|
||
|
|
if (remainingSeconds !== null && remainingSeconds > 10 * 60 * 60) {
|
||
|
|
return { label: 'daily', seconds: GOOGLE_DAILY_WINDOW_SECONDS };
|
||
|
|
}
|
||
|
|
|
||
|
|
return { label: '5h', seconds: GOOGLE_FIVE_HOUR_WINDOW_SECONDS };
|
||
|
|
}
|
||
|
|
|
||
|
|
return { label: 'daily', seconds: GOOGLE_DAILY_WINDOW_SECONDS };
|
||
|
|
};
|
||
|
|
|
||
|
|
export const transformQuotaBucket = (bucket, sourceId) => {
|
||
|
|
const modelId = asNonEmptyString(bucket?.modelId);
|
||
|
|
if (!modelId) {
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
const scopedName = modelId.startsWith(`${sourceId}/`)
|
||
|
|
? modelId
|
||
|
|
: `${sourceId}/${modelId}`;
|
||
|
|
|
||
|
|
const remainingFraction = toNumber(bucket?.remainingFraction);
|
||
|
|
const remainingPercent = remainingFraction !== null
|
||
|
|
? Math.round(remainingFraction * 100)
|
||
|
|
: null;
|
||
|
|
const usedPercent = remainingPercent !== null ? Math.max(0, 100 - remainingPercent) : null;
|
||
|
|
const resetAt = toTimestamp(bucket?.resetTime);
|
||
|
|
const window = resolveGoogleWindow(sourceId, resetAt);
|
||
|
|
|
||
|
|
return {
|
||
|
|
[scopedName]: {
|
||
|
|
windows: {
|
||
|
|
[window.label]: toUsageWindow({
|
||
|
|
usedPercent,
|
||
|
|
windowSeconds: window.seconds,
|
||
|
|
resetAt
|
||
|
|
})
|
||
|
|
}
|
||
|
|
}
|
||
|
|
};
|
||
|
|
};
|
||
|
|
|
||
|
|
export const transformModelData = (modelName, modelData, sourceId) => {
|
||
|
|
const scopedName = modelName.startsWith(`${sourceId}/`)
|
||
|
|
? modelName
|
||
|
|
: `${sourceId}/${modelName}`;
|
||
|
|
|
||
|
|
const remainingFraction = modelData?.quotaInfo?.remainingFraction;
|
||
|
|
const remainingPercent = typeof remainingFraction === 'number'
|
||
|
|
? Math.round(remainingFraction * 100)
|
||
|
|
: null;
|
||
|
|
const usedPercent = remainingPercent !== null ? Math.max(0, 100 - remainingPercent) : null;
|
||
|
|
const resetAt = modelData?.quotaInfo?.resetTime
|
||
|
|
? new Date(modelData.quotaInfo.resetTime).getTime()
|
||
|
|
: null;
|
||
|
|
const window = resolveGoogleWindow(sourceId, resetAt);
|
||
|
|
|
||
|
|
return {
|
||
|
|
[scopedName]: {
|
||
|
|
windows: {
|
||
|
|
[window.label]: toUsageWindow({
|
||
|
|
usedPercent,
|
||
|
|
windowSeconds: window.seconds,
|
||
|
|
resetAt
|
||
|
|
})
|
||
|
|
}
|
||
|
|
}
|
||
|
|
};
|
||
|
|
};
|