openclaw/src/infra/provider-usage.load.ts

122 lines
3.1 KiB
TypeScript

import { loadConfig, type OpenClawConfig } from "../config/config.js";
import { resolveProviderUsageSnapshotWithPlugin } from "../plugins/provider-runtime.js";
import { resolveFetch } from "./fetch.js";
import { type ProviderAuth, resolveProviderAuths } from "./provider-usage.auth.js";
import {
DEFAULT_TIMEOUT_MS,
ignoredErrors,
PROVIDER_LABELS,
usageProviders,
withTimeout,
} from "./provider-usage.shared.js";
import type {
ProviderUsageSnapshot,
UsageProviderId,
UsageSummary,
} from "./provider-usage.types.js";
type UsageSummaryOptions = {
now?: number;
timeoutMs?: number;
providers?: UsageProviderId[];
auth?: ProviderAuth[];
agentDir?: string;
workspaceDir?: string;
config?: OpenClawConfig;
env?: NodeJS.ProcessEnv;
fetch?: typeof fetch;
};
async function fetchProviderUsageSnapshot(params: {
auth: ProviderAuth;
config: OpenClawConfig;
env: NodeJS.ProcessEnv;
agentDir?: string;
workspaceDir?: string;
timeoutMs: number;
fetchFn: typeof fetch;
}): Promise<ProviderUsageSnapshot> {
const pluginSnapshot = await resolveProviderUsageSnapshotWithPlugin({
provider: params.auth.provider,
config: params.config,
workspaceDir: params.workspaceDir,
env: params.env,
context: {
config: params.config,
agentDir: params.agentDir,
workspaceDir: params.workspaceDir,
env: params.env,
provider: params.auth.provider,
token: params.auth.token,
accountId: params.auth.accountId,
timeoutMs: params.timeoutMs,
fetchFn: params.fetchFn,
},
});
if (pluginSnapshot) {
return pluginSnapshot;
}
return {
provider: params.auth.provider,
displayName: PROVIDER_LABELS[params.auth.provider],
windows: [],
error: "Unsupported provider",
};
}
export async function loadProviderUsageSummary(
opts: UsageSummaryOptions = {},
): Promise<UsageSummary> {
const now = opts.now ?? Date.now();
const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
const config = opts.config ?? loadConfig();
const env = opts.env ?? process.env;
const fetchFn = resolveFetch(opts.fetch);
if (!fetchFn) {
throw new Error("fetch is not available");
}
const auths = await resolveProviderAuths({
providers: opts.providers ?? usageProviders,
auth: opts.auth,
agentDir: opts.agentDir,
});
if (auths.length === 0) {
return { updatedAt: now, providers: [] };
}
const tasks = auths.map((auth) =>
withTimeout(
fetchProviderUsageSnapshot({
auth,
config,
env,
agentDir: opts.agentDir,
workspaceDir: opts.workspaceDir,
timeoutMs,
fetchFn,
}),
timeoutMs + 1000,
{
provider: auth.provider,
displayName: PROVIDER_LABELS[auth.provider],
windows: [],
error: "Timeout",
},
),
);
const snapshots = await Promise.all(tasks);
const providers = snapshots.filter((entry) => {
if (entry.windows.length > 0) {
return true;
}
if (!entry.error) {
return true;
}
return !ignoredErrors.has(entry.error);
});
return { updatedAt: now, providers };
}