/** * SuperGrok OAuth Provider for pi * ================================ * * Adds a `supergrok` provider that logs in with your SuperGrok (grok.com) or * X Premium+ subscription via xAI's OAuth 2.0 + PKCE flow. No XAI_API_KEY is * needed — you log in once and pi refreshes the token in the background. * * Models are discovered dynamically from `GET https://api.x.ai/v1/models` when * an OAuth token or `XAI_API_KEY` is available, so new grok-* ids show up * without editing this package. A static fallback catalog is used when discovery * fails (no credentials, offline, 403, etc.). * * Usage: * pi -e /path/to/pi-xai-supergrok * # then inside pi: * /login supergrok * # pick a grok-* model and chat * * Login methods offered: * - Browser (loopback): opens accounts.x.ai, captures the code on * 127.0.0.1:56121. Best on your own machine. * - Device code: for headless / SSH / container hosts. Open the printed URL * on any device and enter the short code. * * Notes: * - We reuse the public Grok-CLI client_id because xAI's auth server only * accepts loopback OAuth from allowlisted clients. * - xAI's /v1 surface is OpenAI-compatible, so we use `openai-completions`. * - xAI may gate OAuth API access by subscription tier; a 403 after a * successful login means your tier isn't allowlisted for the OAuth API * surface (fall back to an XAI_API_KEY provider in that case). */ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; import { fetchLiveModels, loadModels, resolveAccessToken } from "./models.ts"; import { registerSupergrok } from "./provider.ts"; export default async function (pi: ExtensionAPI) { const { models, source, error } = await loadModels(); const refreshFromToken = async (token: string) => { try { const live = await fetchLiveModels(token); registerSupergrok(pi, live, { onLoggedIn: (c) => refreshFromToken(c.access) }); return { ok: true as const, count: live.length }; } catch (e) { return { ok: false as const, error: (e as Error).message ?? String(e) }; } }; registerSupergrok(pi, models, { onLoggedIn: async (credentials) => { // Pull the live catalog now that we have a fresh token (first login // or re-login after the fallback catalog was used). await refreshFromToken(credentials.access); }, }); pi.registerCommand("supergrok-refresh-models", { description: "Re-fetch SuperGrok models from xAI /v1/models", handler: async (_args, ctx) => { const token = await resolveAccessToken(); if (!token) { ctx.ui.notify( "Not logged in — run /login supergrok first (or set XAI_API_KEY).", "warning", ); return; } const result = await refreshFromToken(token); if (result.ok) { ctx.ui.notify(`SuperGrok: loaded ${result.count} models from xAI.`, "info"); } else { ctx.ui.notify(`SuperGrok: model refresh failed — ${result.error}`, "error"); } }, }); // Quiet diagnostic so users can tell whether discovery worked. if (source === "fallback" && error && error !== "no credentials") { // Only surface non-obvious failures; "no credentials" is expected pre-login. console.error(`[supergrok] using fallback model catalog (${error})`); } }