Files
OmniRoute/src/lib/tokenHealthCheckCopilot.ts
Webman 2463781e00 fix(barrel): migrate src/lib/ off the localDb barrel to direct db imports (#59) (#12052)
Boarded together with Phases 2, 4, 5 (#12051, #12053, #12055) and validated in one combined worktree: typecheck:core, check:file-size, check:changelog-integrity, check:complexity, check:cognitive-complexity, check:cycles, check-db-rules all green. Mechanical import-path migration only, no behavior change. Thanks for the phased, well-tested cleanup.
2026-08-30 02:27:25 -03:00

93 lines
3.4 KiB
TypeScript

// @ts-nocheck
/**
* GitHub Copilot sub-token refresh helper for the proactive token health check.
*
* GitHub Copilot issues a short-lived (~30 min) API token separate from the
* GitHub OAuth token. After a successful OAuth refresh, the health check must
* also refresh this sub-token before it expires mid-session. The Copilot
* token expiry is stored in providerSpecificData.copilotTokenExpiresAt (Unix
* seconds). Extracted out of tokenHealthCheck.ts to keep that file under the
* frozen file-size budget (see config/quality/file-size-baseline.json).
*/
import { getProviderConnectionById, updateProviderConnection } from "@/lib/db/providers";
import { refreshCopilotToken } from "@omniroute/open-sse/services/tokenRefresh.ts";
type HealthCheckLogger = {
info: (tag: string, msg: string) => void;
warn: (tag: string, msg: string) => void;
error: (tag: string, msg: string, extra?: Record<string, unknown>) => void;
};
export async function refreshGithubCopilotSubTokenIfNeeded(params: {
conn: any;
result: { accessToken?: string };
proxyConfig: unknown;
healthCheckLog: HealthCheckLogger;
log: (message: string, ...args: any[]) => void;
logWarn: (message: string, ...args: any[]) => void;
logError: (message: string, ...args: any[]) => void;
getConnectionLogLabel: (conn: { name?: string; email?: string; id?: string }) => string;
logPrefix: string;
}): Promise<void> {
const {
conn,
result,
proxyConfig,
healthCheckLog,
log,
logWarn,
logError,
getConnectionLogLabel,
logPrefix,
} = params;
if (String(conn.provider || "").toLowerCase() !== "github") return;
// Re-read the latest connection after the OAuth refresh (onPersist may have updated it).
const latestConn = (await getProviderConnectionById(conn.id).catch(() => null)) || conn;
const accessTokenForCopilot = result.accessToken || latestConn.accessToken;
if (!accessTokenForCopilot) return;
const copilotExpiresAtRaw =
latestConn.providerSpecificData?.copilotTokenExpiresAt ??
conn.providerSpecificData?.copilotTokenExpiresAt;
const copilotExpiresAtMs =
typeof copilotExpiresAtRaw === "number" && copilotExpiresAtRaw < 1e12
? copilotExpiresAtRaw * 1000 // Unix seconds → ms
: typeof copilotExpiresAtRaw === "string"
? new Date(copilotExpiresAtRaw).getTime()
: typeof copilotExpiresAtRaw === "number"
? copilotExpiresAtRaw
: 0;
const copilotAboutToExpire =
!copilotExpiresAtMs || copilotExpiresAtMs - Date.now() < 5 * 60 * 1000;
if (!copilotAboutToExpire) return;
log(`${logPrefix} Refreshing GitHub Copilot sub-token for ${getConnectionLogLabel(conn)}`);
try {
const copilotResult = await refreshCopilotToken(
accessTokenForCopilot,
healthCheckLog,
proxyConfig
);
if (copilotResult?.token) {
await updateProviderConnection(conn.id, {
providerSpecificData: {
...(latestConn.providerSpecificData || {}),
copilotToken: copilotResult.token,
copilotTokenExpiresAt: copilotResult.expiresAt,
},
});
log(`${logPrefix} ✓ GitHub Copilot sub-token refreshed for ${getConnectionLogLabel(conn)}`);
} else {
logWarn(
`${logPrefix} ✗ GitHub Copilot sub-token refresh failed for ${getConnectionLogLabel(conn)}`
);
}
} catch (copilotErr) {
logError(`${logPrefix} Error refreshing Copilot sub-token:`, copilotErr?.message || copilotErr);
}
}