chore: migrate to oxlint and oxfmt

Co-authored-by: Christoph Nakazawa <christoph.pojer@gmail.com>
This commit is contained in:
Peter Steinberger
2026-01-14 14:31:43 +00:00
parent 912ebffc63
commit c379191f80
1480 changed files with 28608 additions and 43547 deletions

View File

@@ -11,9 +11,7 @@ export function resolveAuthProfileDisplayLabel(params: {
const configEmail = cfg?.auth?.profiles?.[profileId]?.email?.trim();
const email =
configEmail ||
(profile && "email" in profile
? (profile.email as string | undefined)?.trim()
: undefined);
(profile && "email" in profile ? (profile.email as string | undefined)?.trim() : undefined);
if (email) return `${profileId} (${email})`;
return profileId;
}

View File

@@ -33,9 +33,7 @@ export function formatAuthDoctorHint(params: {
"Doctor hint (for GitHub issue):",
`- provider: ${providerKey}`,
`- config: ${legacyProfileId}${
cfgProvider || cfgMode
? ` (provider=${cfgProvider ?? "?"}, mode=${cfgMode ?? "?"})`
: ""
cfgProvider || cfgMode ? ` (provider=${cfgProvider ?? "?"}, mode=${cfgMode ?? "?"})` : ""
}`,
`- auth store oauth profiles: ${storeOauthProfiles || "(none)"}`,
`- suggested profile: ${suggested}`,

View File

@@ -16,10 +16,7 @@ import type {
TokenCredential,
} from "./types.js";
function shallowEqualOAuthCredentials(
a: OAuthCredential | undefined,
b: OAuthCredential,
): boolean {
function shallowEqualOAuthCredentials(a: OAuthCredential | undefined, b: OAuthCredential): boolean {
if (!a) return false;
if (a.type !== "oauth") return false;
return (
@@ -34,10 +31,7 @@ function shallowEqualOAuthCredentials(
);
}
function shallowEqualTokenCredentials(
a: TokenCredential | undefined,
b: TokenCredential,
): boolean {
function shallowEqualTokenCredentials(a: TokenCredential | undefined, b: TokenCredential): boolean {
if (!a) return false;
if (a.type !== "token") return false;
return (
@@ -48,10 +42,7 @@ function shallowEqualTokenCredentials(
);
}
function isExternalProfileFresh(
cred: AuthProfileCredential | undefined,
now: number,
): boolean {
function isExternalProfileFresh(cred: AuthProfileCredential | undefined, now: number): boolean {
if (!cred) return false;
if (cred.type !== "oauth" && cred.type !== "token") return false;
if (cred.provider !== "anthropic" && cred.provider !== "openai-codex") {
@@ -104,8 +95,7 @@ export function syncExternalCliCredentials(
!existingOAuth ||
existingOAuth.provider !== "anthropic" ||
existingOAuth.expires <= now ||
(claudeCredsExpires > now &&
claudeCredsExpires > existingOAuth.expires);
(claudeCredsExpires > now && claudeCredsExpires > existingOAuth.expires);
} else {
const existingToken = existing?.type === "token" ? existing : undefined;
isEqual = shallowEqualTokenCredentials(existingToken, claudeCreds);
@@ -114,8 +104,7 @@ export function syncExternalCliCredentials(
!existingToken ||
existingToken.provider !== "anthropic" ||
(existingToken.expires ?? 0) <= now ||
(claudeCredsExpires > now &&
claudeCredsExpires > (existingToken.expires ?? 0));
(claudeCredsExpires > now && claudeCredsExpires > (existingToken.expires ?? 0));
}
// Also update if credential type changed (token -> oauth upgrade)
@@ -166,10 +155,7 @@ export function syncExternalCliCredentials(
existingOAuth.expires <= now ||
codexCreds.expires > existingOAuth.expires;
if (
shouldUpdate &&
!shallowEqualOAuthCredentials(existingOAuth, codexCreds)
) {
if (shouldUpdate && !shallowEqualOAuthCredentials(existingOAuth, codexCreds)) {
store.profiles[CODEX_CLI_PROFILE_ID] = codexCreds;
mutated = true;
log.info("synced openai-codex credentials from codex cli", {

View File

@@ -1,8 +1,4 @@
import {
getOAuthApiKey,
type OAuthCredentials,
type OAuthProvider,
} from "@mariozechner/pi-ai";
import { getOAuthApiKey, type OAuthCredentials, type OAuthProvider } from "@mariozechner/pi-ai";
import lockfile from "proper-lockfile";
import type { ClawdbotConfig } from "../../config/config.js";
@@ -15,12 +11,8 @@ import { suggestOAuthProfileIdForLegacyDefault } from "./repair.js";
import { ensureAuthProfileStore, saveAuthProfileStore } from "./store.js";
import type { AuthProfileStore } from "./types.js";
function buildOAuthApiKey(
provider: string,
credentials: OAuthCredentials,
): string {
const needsProjectId =
provider === "google-gemini-cli" || provider === "google-antigravity";
function buildOAuthApiKey(provider: string, credentials: OAuthCredentials): string {
const needsProjectId = provider === "google-gemini-cli" || provider === "google-antigravity";
return needsProjectId
? JSON.stringify({
token: credentials.access,
@@ -76,10 +68,7 @@ async function refreshOAuthTokenWithLock(params: {
// Sync refreshed credentials back to Claude CLI if this is the claude-cli profile
// This ensures Claude Code continues to work after ClawdBot refreshes the token
if (
params.profileId === CLAUDE_CLI_PROFILE_ID &&
cred.provider === "anthropic"
) {
if (params.profileId === CLAUDE_CLI_PROFILE_ID && cred.provider === "anthropic") {
writeClaudeCliCredentials(result.newCredentials);
}

View File

@@ -43,17 +43,12 @@ export function resolveAuthProfileOrder(params: {
const explicitOrder = storedOrder ?? configuredOrder;
const explicitProfiles = cfg?.auth?.profiles
? Object.entries(cfg.auth.profiles)
.filter(
([, profile]) =>
normalizeProviderId(profile.provider) === providerKey,
)
.filter(([, profile]) => normalizeProviderId(profile.provider) === providerKey)
.map(([profileId]) => profileId)
: [];
const baseOrder =
explicitOrder ??
(explicitProfiles.length > 0
? explicitProfiles
: listProfilesForProvider(store, providerKey));
(explicitProfiles.length > 0 ? explicitProfiles : listProfilesForProvider(store, providerKey));
if (baseOrder.length === 0) return [];
const filtered = baseOrder.filter((profileId) => {
@@ -66,8 +61,7 @@ export function resolveAuthProfileOrder(params: {
return false;
}
if (profileConfig.mode !== cred.type) {
const oauthCompatible =
profileConfig.mode === "oauth" && cred.type === "token";
const oauthCompatible = profileConfig.mode === "oauth" && cred.type === "token";
if (!oauthCompatible) return false;
}
}
@@ -104,8 +98,7 @@ export function resolveAuthProfileOrder(params: {
const inCooldown: Array<{ profileId: string; cooldownUntil: number }> = [];
for (const profileId of deduped) {
const cooldownUntil =
resolveProfileUnusableUntil(store.usageStats?.[profileId] ?? {}) ?? 0;
const cooldownUntil = resolveProfileUnusableUntil(store.usageStats?.[profileId] ?? {}) ?? 0;
if (
typeof cooldownUntil === "number" &&
Number.isFinite(cooldownUntil) &&
@@ -126,10 +119,7 @@ export function resolveAuthProfileOrder(params: {
// Still put preferredProfile first if specified
if (preferredProfile && ordered.includes(preferredProfile)) {
return [
preferredProfile,
...ordered.filter((e) => e !== preferredProfile),
];
return [preferredProfile, ...ordered.filter((e) => e !== preferredProfile)];
}
return ordered;
}
@@ -146,10 +136,7 @@ export function resolveAuthProfileOrder(params: {
return sorted;
}
function orderProfilesByMode(
order: string[],
store: AuthProfileStore,
): string[] {
function orderProfilesByMode(order: string[], store: AuthProfileStore): string[] {
const now = Date.now();
// Partition into available and in-cooldown
@@ -168,8 +155,7 @@ function orderProfilesByMode(
// Then by lastUsed (oldest first = round-robin within type)
const scored = available.map((profileId) => {
const type = store.profiles[profileId]?.type;
const typeScore =
type === "oauth" ? 0 : type === "token" ? 1 : type === "api_key" ? 2 : 3;
const typeScore = type === "oauth" ? 0 : type === "token" ? 1 : type === "api_key" ? 2 : 3;
const lastUsed = store.usageStats?.[profileId]?.lastUsed ?? 0;
return { profileId, typeScore, lastUsed };
});
@@ -189,8 +175,7 @@ function orderProfilesByMode(
const cooldownSorted = inCooldown
.map((profileId) => ({
profileId,
cooldownUntil:
resolveProfileUnusableUntil(store.usageStats?.[profileId] ?? {}) ?? now,
cooldownUntil: resolveProfileUnusableUntil(store.usageStats?.[profileId] ?? {}) ?? now,
}))
.sort((a, b) => a.cooldownUntil - b.cooldownUntil)
.map((entry) => entry.profileId);

View File

@@ -4,11 +4,7 @@ import path from "node:path";
import { saveJsonFile } from "../../infra/json-file.js";
import { resolveUserPath } from "../../utils.js";
import { resolveClawdbotAgentDir } from "../agent-paths.js";
import {
AUTH_PROFILE_FILENAME,
AUTH_STORE_VERSION,
LEGACY_AUTH_FILENAME,
} from "./constants.js";
import { AUTH_PROFILE_FILENAME, AUTH_STORE_VERSION, LEGACY_AUTH_FILENAME } from "./constants.js";
import type { AuthProfileStore } from "./types.js";
export function resolveAuthStorePath(agentDir?: string): string {

View File

@@ -50,10 +50,7 @@ export function upsertAuthProfile(params: {
saveAuthProfileStore(store, params.agentDir);
}
export function listProfilesForProvider(
store: AuthProfileStore,
provider: string,
): string[] {
export function listProfilesForProvider(store: AuthProfileStore, provider: string): string[] {
const providerKey = normalizeProviderId(provider);
return Object.entries(store.profiles)
.filter(([, cred]) => normalizeProviderId(cred.provider) === providerKey)

View File

@@ -35,10 +35,9 @@ export function suggestOAuthProfileIdForLegacyDefault(params: {
return null;
}
const oauthProfiles = listProfilesForProvider(
params.store,
providerKey,
).filter((id) => params.store.profiles[id]?.type === "oauth");
const oauthProfiles = listProfilesForProvider(params.store, providerKey).filter(
(id) => params.store.profiles[id]?.type === "oauth",
);
if (oauthProfiles.length === 0) return null;
const configuredEmail = legacyCfg?.email?.trim();
@@ -47,16 +46,12 @@ export function suggestOAuthProfileIdForLegacyDefault(params: {
const cred = params.store.profiles[id];
if (!cred || cred.type !== "oauth") return false;
const email = (cred.email as string | undefined)?.trim();
return (
email === configuredEmail || id === `${providerKey}:${configuredEmail}`
);
return email === configuredEmail || id === `${providerKey}:${configuredEmail}`;
});
if (byEmail) return byEmail;
}
const lastGood =
params.store.lastGood?.[providerKey] ??
params.store.lastGood?.[params.provider];
const lastGood = params.store.lastGood?.[providerKey] ?? params.store.lastGood?.[params.provider];
if (lastGood && oauthProfiles.includes(lastGood)) return lastGood;
const nonLegacy = oauthProfiles.filter((id) => id !== params.legacyProfileId);
@@ -83,10 +78,7 @@ export function repairOAuthProfileIdMismatch(params: {
if (legacyCfg.mode !== "oauth") {
return { config: params.cfg, changes: [], migrated: false };
}
if (
normalizeProviderId(legacyCfg.provider) !==
normalizeProviderId(params.provider)
) {
if (normalizeProviderId(legacyCfg.provider) !== normalizeProviderId(params.provider)) {
return { config: params.cfg, changes: [], migrated: false };
}
@@ -102,14 +94,10 @@ export function repairOAuthProfileIdMismatch(params: {
const toCred = params.store.profiles[toProfileId];
const toEmail =
toCred?.type === "oauth"
? (toCred.email as string | undefined)?.trim()
: undefined;
toCred?.type === "oauth" ? (toCred.email as string | undefined)?.trim() : undefined;
const nextProfiles = {
...(params.cfg.auth?.profiles as
| Record<string, AuthProfileConfig>
| undefined),
...(params.cfg.auth?.profiles as Record<string, AuthProfileConfig> | undefined),
} as Record<string, AuthProfileConfig>;
delete nextProfiles[legacyProfileId];
nextProfiles[toProfileId] = {
@@ -121,17 +109,13 @@ export function repairOAuthProfileIdMismatch(params: {
const nextOrder = (() => {
const order = params.cfg.auth?.order;
if (!order) return undefined;
const resolvedKey = Object.keys(order).find(
(key) => normalizeProviderId(key) === providerKey,
);
const resolvedKey = Object.keys(order).find((key) => normalizeProviderId(key) === providerKey);
if (!resolvedKey) return order;
const existing = order[resolvedKey];
if (!Array.isArray(existing)) return order;
const replaced = existing
.map((id) => (id === legacyProfileId ? toProfileId : id))
.filter(
(id): id is string => typeof id === "string" && id.trim().length > 0,
);
.filter((id): id is string => typeof id === "string" && id.trim().length > 0);
const deduped: string[] = [];
for (const entry of replaced) {
if (!deduped.includes(entry)) deduped.push(entry);
@@ -148,9 +132,7 @@ export function repairOAuthProfileIdMismatch(params: {
},
};
const changes = [
`Auth: migrate ${legacyProfileId}${toProfileId} (OAuth profile id)`,
];
const changes = [`Auth: migrate ${legacyProfileId}${toProfileId} (OAuth profile id)`];
return {
config: nextCfg,

View File

@@ -3,29 +3,14 @@ import type { OAuthCredentials } from "@mariozechner/pi-ai";
import lockfile from "proper-lockfile";
import { resolveOAuthPath } from "../../config/paths.js";
import { loadJsonFile, saveJsonFile } from "../../infra/json-file.js";
import {
AUTH_STORE_LOCK_OPTIONS,
AUTH_STORE_VERSION,
log,
} from "./constants.js";
import { AUTH_STORE_LOCK_OPTIONS, AUTH_STORE_VERSION, log } from "./constants.js";
import { syncExternalCliCredentials } from "./external-cli-sync.js";
import {
ensureAuthStoreFile,
resolveAuthStorePath,
resolveLegacyAuthStorePath,
} from "./paths.js";
import type {
AuthProfileCredential,
AuthProfileStore,
ProfileUsageStats,
} from "./types.js";
import { ensureAuthStoreFile, resolveAuthStorePath, resolveLegacyAuthStorePath } from "./paths.js";
import type { AuthProfileCredential, AuthProfileStore, ProfileUsageStats } from "./types.js";
type LegacyAuthStore = Record<string, AuthProfileCredential>;
function _syncAuthProfileStore(
target: AuthProfileStore,
source: AuthProfileStore,
): void {
function _syncAuthProfileStore(target: AuthProfileStore, source: AuthProfileStore): void {
target.version = source.version;
target.profiles = source.profiles;
target.order = source.order;
@@ -70,11 +55,7 @@ function coerceLegacyStore(raw: unknown): LegacyAuthStore | null {
for (const [key, value] of Object.entries(record)) {
if (!value || typeof value !== "object") continue;
const typed = value as Partial<AuthProfileCredential>;
if (
typed.type !== "api_key" &&
typed.type !== "oauth" &&
typed.type !== "token"
) {
if (typed.type !== "api_key" && typed.type !== "oauth" && typed.type !== "token") {
continue;
}
entries[key] = {
@@ -94,11 +75,7 @@ function coerceAuthStore(raw: unknown): AuthProfileStore | null {
for (const [key, value] of Object.entries(profiles)) {
if (!value || typeof value !== "object") continue;
const typed = value as Partial<AuthProfileCredential>;
if (
typed.type !== "api_key" &&
typed.type !== "oauth" &&
typed.type !== "token"
) {
if (typed.type !== "api_key" && typed.type !== "oauth" && typed.type !== "token") {
continue;
}
if (!typed.provider) continue;
@@ -188,9 +165,7 @@ export function loadAuthProfileStore(): AuthProfileStore {
type: "token",
provider: String(cred.provider ?? provider),
token: cred.token,
...(typeof cred.expires === "number"
? { expires: cred.expires }
: {}),
...(typeof cred.expires === "number" ? { expires: cred.expires } : {}),
...(cred.email ? { email: cred.email } : {}),
};
} else {
@@ -253,9 +228,7 @@ export function ensureAuthProfileStore(
type: "token",
provider: String(cred.provider ?? provider),
token: cred.token,
...(typeof cred.expires === "number"
? { expires: cred.expires }
: {}),
...(typeof cred.expires === "number" ? { expires: cred.expires } : {}),
...(cred.email ? { email: cred.email } : {}),
};
} else {
@@ -301,10 +274,7 @@ export function ensureAuthProfileStore(
return store;
}
export function saveAuthProfileStore(
store: AuthProfileStore,
agentDir?: string,
): void {
export function saveAuthProfileStore(store: AuthProfileStore, agentDir?: string): void {
const authPath = resolveAuthStorePath(agentDir);
const payload = {
version: AUTH_STORE_VERSION,

View File

@@ -29,10 +29,7 @@ export type OAuthCredential = OAuthCredentials & {
email?: string;
};
export type AuthProfileCredential =
| ApiKeyCredential
| TokenCredential
| OAuthCredential;
export type AuthProfileCredential = ApiKeyCredential | TokenCredential | OAuthCredential;
export type AuthProfileFailureReason =
| "auth"

View File

@@ -1,14 +1,7 @@
import type { ClawdbotConfig } from "../../config/config.js";
import { normalizeProviderId } from "../model-selection.js";
import {
saveAuthProfileStore,
updateAuthProfileStoreWithLock,
} from "./store.js";
import type {
AuthProfileFailureReason,
AuthProfileStore,
ProfileUsageStats,
} from "./types.js";
import { saveAuthProfileStore, updateAuthProfileStoreWithLock } from "./store.js";
import type { AuthProfileFailureReason, AuthProfileStore, ProfileUsageStats } from "./types.js";
function resolveProfileUnusableUntil(stats: ProfileUsageStats): number | null {
const values = [stats.cooldownUntil, stats.disabledUntil]
@@ -21,10 +14,7 @@ function resolveProfileUnusableUntil(stats: ProfileUsageStats): number | null {
/**
* Check if a profile is currently in cooldown (due to rate limiting or errors).
*/
export function isProfileInCooldown(
store: AuthProfileStore,
profileId: string,
): boolean {
export function isProfileInCooldown(store: AuthProfileStore, profileId: string): boolean {
const stats = store.usageStats?.[profileId];
if (!stats) return false;
const unusableUntil = resolveProfileUnusableUntil(stats);
@@ -102,9 +92,7 @@ function resolveAuthCooldownConfig(params: {
} as const;
const resolveHours = (value: unknown, fallback: number) =>
typeof value === "number" && Number.isFinite(value) && value > 0
? value
: fallback;
typeof value === "number" && Number.isFinite(value) && value > 0 ? value : fallback;
const cooldowns = params.cfg?.auth?.cooldowns;
const billingOverride = (() => {
@@ -120,10 +108,7 @@ function resolveAuthCooldownConfig(params: {
billingOverride ?? cooldowns?.billingBackoffHours,
defaults.billingBackoffHours,
);
const billingMaxHours = resolveHours(
cooldowns?.billingMaxHours,
defaults.billingMaxHours,
);
const billingMaxHours = resolveHours(cooldowns?.billingMaxHours, defaults.billingMaxHours);
const failureWindowHours = resolveHours(
cooldowns?.failureWindowHours,
defaults.failureWindowHours,
@@ -172,9 +157,7 @@ function computeNextProfileUsageStats(params: {
const baseErrorCount = windowExpired ? 0 : (params.existing.errorCount ?? 0);
const nextErrorCount = baseErrorCount + 1;
const failureCounts = windowExpired
? {}
: { ...params.existing.failureCounts };
const failureCounts = windowExpired ? {} : { ...params.existing.failureCounts };
failureCounts[params.reason] = (failureCounts[params.reason] ?? 0) + 1;
const updatedStats: ProfileUsageStats = {
@@ -246,9 +229,7 @@ export async function markAuthProfileFailure(params: {
store.usageStats = store.usageStats ?? {};
const existing = store.usageStats[profileId] ?? {};
const now = Date.now();
const providerKey = normalizeProviderId(
store.profiles[profileId]?.provider ?? "",
);
const providerKey = normalizeProviderId(store.profiles[profileId]?.provider ?? "");
const cfgResolved = resolveAuthCooldownConfig({
cfg,
providerId: providerKey,