fix(auth): migrate to current pi credential API

This commit is contained in:
2026-07-19 20:56:59 -04:00
parent 461773c677
commit 930cae2e3a
4 changed files with 1558 additions and 3374 deletions
+10 -34
View File
@@ -1,4 +1,4 @@
import { AuthStorage, type AuthCredential, type ExtensionAPI, type ExtensionContext, type ExtensionCommandContext, type ReadonlyFooterDataProvider, type SessionStartEvent, type SessionShutdownEvent, type AgentEndEvent } from "@mariozechner/pi-coding-agent"; import { readStoredCredential, type ExtensionAPI, type ExtensionContext, type ExtensionCommandContext, type ReadonlyFooterDataProvider, type SessionStartEvent, type SessionShutdownEvent, type AgentEndEvent } from "@earendil-works/pi-coding-agent";
import { statusbarConfig } from "./config"; import { statusbarConfig } from "./config";
import { contextModule, costModule, directoryModule, modelModule, thinkingModule } from "./modules/basic"; import { contextModule, costModule, directoryModule, modelModule, thinkingModule } from "./modules/basic";
import { usageModule } from "./modules/usage"; import { usageModule } from "./modules/usage";
@@ -31,7 +31,7 @@ function credentialString(raw: unknown, key: string): string | undefined {
return isRecord(raw) && typeof raw[key] === "string" ? raw[key] : undefined; return isRecord(raw) && typeof raw[key] === "string" ? raw[key] : undefined;
} }
function buildUsageCredential(raw: AuthCredential | undefined, apiKey: string): UsageCredential { function buildUsageCredential(raw: ReturnType<typeof readStoredCredential>, apiKey: string): UsageCredential {
if (raw?.type === "oauth") { if (raw?.type === "oauth") {
return { return {
type: "oauth", type: "oauth",
@@ -49,27 +49,14 @@ function buildUsageCredential(raw: AuthCredential | undefined, apiKey: string):
apiKey, apiKey,
accountId: credentialString(raw, "accountId"), accountId: credentialString(raw, "accountId"),
email: credentialString(raw, "email"), email: credentialString(raw, "email"),
metadata: raw, metadata: raw ? { ...raw } : undefined,
}; };
} }
async function readPiCredential(authStorage: AuthStorage, provider: Provider): Promise<UsageCredential | undefined> { async function readPiCredential(ctx: ExtensionContext, provider: Provider): Promise<UsageCredential | undefined> {
authStorage.reload(); const apiKey = await ctx.modelRegistry.getApiKeyForProvider(provider);
const apiKey = await authStorage.getApiKey(provider);
if (!apiKey) return undefined; if (!apiKey) return undefined;
return buildUsageCredential(authStorage.get(provider), apiKey); return buildUsageCredential(readStoredCredential(provider), apiKey);
}
async function forceRefreshPiCredential(authStorage: AuthStorage, provider: Provider): Promise<UsageCredential> {
authStorage.reload();
const raw = authStorage.get(provider);
const oauthProvider = authStorage.getOAuthProviders().find(candidate => candidate.id === provider);
if (raw?.type !== "oauth" || !oauthProvider) throw new Error("login expired");
// Refresh Provider OAuth Token
const refreshed = await oauthProvider.refreshToken(raw);
authStorage.set(provider, { type: "oauth", ...refreshed });
return buildUsageCredential(authStorage.get(provider), oauthProvider.getApiKey(refreshed));
} }
function renderModule(moduleCtx: ModuleContext, spec: ModuleSpec): RenderedModule { function renderModule(moduleCtx: ModuleContext, spec: ModuleSpec): RenderedModule {
@@ -113,7 +100,6 @@ export default function piStatusbarExtension(pi: ExtensionAPI) {
let latestCtx: ExtensionContext | undefined; let latestCtx: ExtensionContext | undefined;
let requestRender: (() => void) | undefined; let requestRender: (() => void) | undefined;
const statusbarState: StatusbarState = {}; const statusbarState: StatusbarState = {};
const authStorage = AuthStorage.create();
function updateThinkingLevel() { function updateThinkingLevel() {
try { try {
@@ -172,7 +158,7 @@ export default function piStatusbarExtension(pi: ExtensionAPI) {
return; return;
} }
const credential = await readPiCredential(authStorage, provider); const credential = await readPiCredential(ctx, provider);
if (!credential) { if (!credential) {
statusbarState.report = { provider, fetchedAt: Date.now(), limits: [] }; statusbarState.report = { provider, fetchedAt: Date.now(), limits: [] };
statusbarState.error = "not logged in"; statusbarState.error = "not logged in";
@@ -185,7 +171,6 @@ export default function piStatusbarExtension(pi: ExtensionAPI) {
inFlight = controller; inFlight = controller;
try { try {
let activeCredential = credential;
const usageCtx = { const usageCtx = {
fetch: globalThis.fetch.bind(globalThis), fetch: globalThis.fetch.bind(globalThis),
logger: { logger: {
@@ -193,21 +178,12 @@ export default function piStatusbarExtension(pi: ExtensionAPI) {
warn: () => undefined, warn: () => undefined,
}, },
}; };
const fetchParams = () => ({ const report = await usageProviders[provider].fetchUsage({
provider, provider,
credential: activeCredential, credential,
baseUrl: ctx.model?.baseUrl, baseUrl: ctx.model?.baseUrl,
signal: controller.signal, signal: controller.signal,
}); }, usageCtx);
let report: UsageReport | null;
try {
report = await usageProviders[provider].fetchUsage(fetchParams(), usageCtx);
} catch (error) {
if (!(error instanceof Error) || error.message !== "unauthorized") throw error;
activeCredential = await forceRefreshPiCredential(authStorage, provider);
report = await usageProviders[provider].fetchUsage(fetchParams(), usageCtx);
}
statusbarState.report = report ?? { provider, fetchedAt: Date.now(), limits: [] }; statusbarState.report = report ?? { provider, fetchedAt: Date.now(), limits: [] };
statusbarState.error = report ? undefined : "unavailable"; statusbarState.error = report ? undefined : "unavailable";
+1546 -3338
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -13,7 +13,7 @@
] ]
}, },
"devDependencies": { "devDependencies": {
"@mariozechner/pi-coding-agent": "^0.72.1", "@earendil-works/pi-coding-agent": "^0.80.10",
"@types/node": "^25.6.0", "@types/node": "^25.6.0",
"oxlint": "^1.62.0", "oxlint": "^1.62.0",
"typescript": "^6.0.3" "typescript": "^6.0.3"
+1 -1
View File
@@ -1,4 +1,4 @@
import type { ExtensionContext, ReadonlyFooterDataProvider } from "@mariozechner/pi-coding-agent"; import type { ExtensionContext, ReadonlyFooterDataProvider } from "@earendil-works/pi-coding-agent";
import type { UsageLimit, UsageReport } from "./usage"; import type { UsageLimit, UsageReport } from "./usage";
export type ModuleName = "directory" | "context" | "model" | "thinking" | "cost" | "usage"; export type ModuleName = "directory" | "context" | "model" | "thinking" | "cost" | "usage";