{"version":3,"file":"index.mjs","names":[],"sources":["../index.ts"],"sourcesContent":["import type { ExtensionAPI, ExtensionContext } from \"@earendil-works/pi-coding-agent\";\nimport { Key, matchesKey, truncateToWidth } from \"@earendil-works/pi-tui\";\n\n/**\n * Base URL for the Codex usage backend API.\n * Override with CODEX_BASE_URL when testing against a proxy/mock server.\n */\nconst CODEX_BASE_URL = (process.env.CODEX_BASE_URL || \"https://chatgpt.com/backend-api\").replace(\n  /\\/+$/,\n  \"\",\n);\nconst USAGE_ENDPOINT = `${CODEX_BASE_URL}/wham/usage`;\nconst USAGE_DASHBOARD_URL = \"https://chatgpt.com/codex/settings/usage\";\nconst OPEN_DASHBOARD_OPTION = `Open usage dashboard: ${USAGE_DASHBOARD_URL}`;\nconst OPENAI_AUTH_CLAIM = \"https://api.openai.com/auth\";\nconst OPENAI_PROFILE_CLAIM = \"https://api.openai.com/profile\";\nconst CODEX_ACCOUNT_ID_CLAIM = \"https://api.openai.com/auth.chatgpt_account_id\";\nconst FIVE_HOUR_SECONDS = 5 * 60 * 60;\nconst WEEK_SECONDS = 7 * 24 * 60 * 60;\nconst WIDGET_KEY = \"codex-limit-render-hook\";\nconst STATUS_KEY = \"codex-limit-usage\";\nconst GLOBAL_USAGE_KEY = \"piCodexLimit\";\n\n/** A normalized rate-limit window from Codex's usage endpoint. */\ntype UsageWindow = {\n  /** Used percentage reported by Codex, usually 0-100. */\n  usedPercent?: number;\n  /** Window duration in seconds, used to identify 5-hour vs weekly buckets. */\n  windowSeconds?: number;\n  /** Unix timestamp in seconds for when this limit resets. */\n  resetAt?: number;\n};\n\n/** Cached, normalized snapshot used by both the footer widget and command. */\ntype UsageSnapshot = {\n  planType?: string;\n  email?: string;\n  fiveHour?: UsageWindow;\n  weekly?: UsageWindow;\n  /** Local timestamp in milliseconds when the snapshot was fetched. */\n  fetchedAt: number;\n};\n\n/** Metadata extracted from the OAuth JWT when the API response omits it. */\ntype JwtMetadata = {\n  accountId?: string;\n  planType?: string;\n  email?: string;\n};\n\ntype GlobalCodexLimit = {\n  provider?: string;\n  fiveHour?: UsageWindow;\n  weekly?: UsageWindow;\n  fetchedAt?: number;\n};\n\ndeclare global {\n  // eslint-disable-next-line no-var\n  var piCodexLimit: GlobalCodexLimit | undefined;\n}\n\n/** Module-level cache; cleared on failed fetches to avoid showing stale data. */\nlet usageSnapshot: UsageSnapshot | undefined;\n/** Updated by the render-hook widget so async refreshes can trigger a repaint. */\nlet requestRender = () => {};\n\n/** Matches Codex subscription-backed providers only. */\nfunction isOpenAICodexProvider(provider: string | undefined): boolean {\n  return /^openai-codex(-\\d+)?$/.test(provider ?? \"\");\n}\n\n/** Safely narrow unknown JSON values to plain objects. */\nfunction asRecord(value: unknown): Record<string, unknown> | undefined {\n  return value && typeof value === \"object\" && !Array.isArray(value)\n    ? (value as Record<string, unknown>)\n    : undefined;\n}\n\nfunction nestedRecord(record: Record<string, unknown> | undefined, key: string) {\n  return asRecord(record?.[key]);\n}\n\n/** Decode the payload portion of an OAuth JWT without validating the signature. */\nfunction decodeJwtPayload(token: string): Record<string, unknown> {\n  const parts = token.split(\".\");\n  if (parts.length < 2) return {};\n\n  try {\n    return JSON.parse(Buffer.from(parts[1], \"base64url\").toString(\"utf8\")) as Record<\n      string,\n      unknown\n    >;\n  } catch {\n    return {};\n  }\n}\n\n/** Extract account id, plan, and email hints embedded in Codex OAuth tokens. */\nfunction getTokenMetadata(token: string): JwtMetadata {\n  const payload = decodeJwtPayload(token);\n  const auth = nestedRecord(payload, OPENAI_AUTH_CLAIM);\n  const profile = nestedRecord(payload, OPENAI_PROFILE_CLAIM);\n\n  return {\n    accountId:\n      (typeof payload[CODEX_ACCOUNT_ID_CLAIM] === \"string\"\n        ? payload[CODEX_ACCOUNT_ID_CLAIM]\n        : undefined) ??\n      (typeof auth?.chatgpt_account_id === \"string\" ? auth.chatgpt_account_id : undefined),\n    planType: typeof auth?.chatgpt_plan_type === \"string\" ? auth.chatgpt_plan_type : undefined,\n    email: typeof profile?.email === \"string\" ? profile.email : undefined,\n  };\n}\n\n/** Convert a raw `rate_limit.*_window` object into our internal shape. */\nfunction normalizeWindow(value: unknown): UsageWindow | undefined {\n  const record = asRecord(value);\n  if (!record) return undefined;\n\n  return {\n    usedPercent: typeof record.used_percent === \"number\" ? record.used_percent : undefined,\n    windowSeconds:\n      typeof record.limit_window_seconds === \"number\" ? record.limit_window_seconds : undefined,\n    resetAt: typeof record.reset_at === \"number\" ? record.reset_at : undefined,\n  };\n}\n\n/** Parse Codex's `/wham/usage` response and identify 5-hour and weekly windows. */\nfunction parseUsageSnapshot(data: unknown): UsageSnapshot {\n  const raw = asRecord(data);\n  const rateLimit = nestedRecord(raw, \"rate_limit\");\n  const windows = [\n    normalizeWindow(rateLimit?.primary_window),\n    normalizeWindow(rateLimit?.secondary_window),\n  ].filter((window): window is UsageWindow => Boolean(window));\n\n  return {\n    planType: typeof raw?.plan_type === \"string\" ? raw.plan_type : undefined,\n    email: typeof raw?.email === \"string\" ? raw.email : undefined,\n    fiveHour: windows.find(\n      (window) => Math.abs((window.windowSeconds ?? 0) - FIVE_HOUR_SECONDS) <= 120,\n    ),\n    weekly: windows.find((window) => Math.abs((window.windowSeconds ?? 0) - WEEK_SECONDS) <= 120),\n    fetchedAt: Date.now(),\n  };\n}\n\nfunction clampPercent(value: number | undefined): number | undefined {\n  return value === undefined ? undefined : Math.max(0, Math.min(100, value));\n}\n\nfunction formatUsedPercent(window: UsageWindow | undefined): string {\n  const used = clampPercent(window?.usedPercent);\n  return used === undefined ? \"?%\" : `${Math.round(used)}%`;\n}\n\nfunction formatRemainingPercent(window: UsageWindow | undefined): string {\n  const used = clampPercent(window?.usedPercent);\n  return used === undefined ? \"?%\" : `${Math.round(100 - used)}%`;\n}\n\n/** Mask account email for command output while keeping it recognizable. */\nfunction maskEmail(email: string): string {\n  const [rawLocal, rawDomain] = email.split(\"@\");\n  if (!rawLocal || !rawDomain) return \"***\";\n\n  const local = rawLocal.length <= 2 ? `${rawLocal[0] ?? \"\"}***` : `${rawLocal.slice(0, 2)}***`;\n  const [domainName, ...domainRest] = rawDomain.split(\".\");\n  const maskedDomain = domainName\n    ? `${domainName[0] ?? \"\"}***${domainName.length > 1 ? domainName.slice(-1) : \"\"}`\n    : \"***\";\n  return `${local}@${maskedDomain}${domainRest.length > 0 ? `.${domainRest.join(\".\")}` : \"\"}`;\n}\n\nfunction formatFetchedAt(fetchedAt: number): string {\n  return new Date(fetchedAt).toLocaleString();\n}\n\n/** Format reset timestamps for compact human-readable UI text. */\nfunction formatResetLong(resetAt: number | undefined): string {\n  if (!resetAt) return \"unknown\";\n\n  const minutes = Math.max(0, Math.round((resetAt * 1000 - Date.now()) / 60000));\n  const days = Math.floor(minutes / (60 * 24));\n  const hours = Math.floor((minutes % (60 * 24)) / 60);\n  const mins = minutes % 60;\n\n  if (days > 0) return `in ${days}d ${hours}h`;\n  if (hours > 0) return `in ${hours}h ${mins}m`;\n  return `in ${mins}m`;\n}\n\nfunction publishSnapshot(ctx: ExtensionContext, snapshot: UsageSnapshot | undefined) {\n  globalThis[GLOBAL_USAGE_KEY] = snapshot\n    ? {\n        provider: ctx.model?.provider,\n        fiveHour: snapshot.fiveHour,\n        weekly: snapshot.weekly,\n        fetchedAt: snapshot.fetchedAt,\n      }\n    : undefined;\n}\n\n/** Update pi's built-in footer status so users without a custom footer still see usage. */\nfunction publishFooterStatus(ctx: ExtensionContext, snapshot: UsageSnapshot | undefined) {\n  if (!ctx.hasUI) return;\n\n  if (!isOpenAICodexProvider(ctx.model?.provider)) {\n    ctx.ui.setStatus(STATUS_KEY, undefined);\n    return;\n  }\n\n  const used = clampPercent(snapshot?.fiveHour?.usedPercent);\n  if (used === undefined) {\n    ctx.ui.setStatus(STATUS_KEY, undefined);\n    return;\n  }\n\n  const label = `Codex usage limit: ${Math.round(used)}%`;\n  const color = used >= 90 ? \"error\" : used >= 70 ? \"warning\" : \"success\";\n  ctx.ui.setStatus(STATUS_KEY, ctx.ui.theme.fg(color, label));\n}\n\n/**\n * Fetch and cache the current Codex usage snapshot.\n *\n * This only runs for OAuth-backed openai-codex models. Failures clear the cache so\n * the footer never displays stale limits.\n */\nasync function updateUsage(ctx: ExtensionContext): Promise<UsageSnapshot | undefined> {\n  const model = ctx.model;\n  if (!model || !isOpenAICodexProvider(model.provider) || !ctx.modelRegistry.isUsingOAuth(model)) {\n    usageSnapshot = undefined;\n    publishSnapshot(ctx, undefined);\n    publishFooterStatus(ctx, undefined);\n    requestRender();\n    return undefined;\n  }\n\n  const auth = await ctx.modelRegistry.getApiKeyAndHeaders(model);\n  if (!auth.ok || !auth.apiKey) {\n    usageSnapshot = undefined;\n    publishSnapshot(ctx, undefined);\n    publishFooterStatus(ctx, undefined);\n    requestRender();\n    return undefined;\n  }\n\n  const metadata = getTokenMetadata(auth.apiKey);\n  const headers = {\n    Authorization: `Bearer ${auth.apiKey}`,\n    Accept: \"application/json\",\n    \"User-Agent\": \"pi-codex-limit\",\n    ...(metadata.accountId ? { \"chatgpt-account-id\": metadata.accountId } : {}),\n  };\n\n  try {\n    const response = await fetch(USAGE_ENDPOINT, { headers, signal: AbortSignal.timeout(15000) });\n    if (!response.ok) {\n      usageSnapshot = undefined;\n      publishSnapshot(ctx, undefined);\n      publishFooterStatus(ctx, undefined);\n      requestRender();\n      return undefined;\n    }\n\n    const snapshot = parseUsageSnapshot(await response.json());\n    usageSnapshot = {\n      ...snapshot,\n      email: snapshot.email ?? metadata.email,\n      planType: snapshot.planType ?? metadata.planType,\n    };\n    publishSnapshot(ctx, usageSnapshot);\n    publishFooterStatus(ctx, usageSnapshot);\n    requestRender();\n    return usageSnapshot;\n  } catch {\n    usageSnapshot = undefined;\n    publishSnapshot(ctx, undefined);\n    publishFooterStatus(ctx, undefined);\n    requestRender();\n    return undefined;\n  }\n}\n\n/** Build the selectable detail rows shown by `/codex-limit`. */\nfunction buildUsageDetails(snapshot: UsageSnapshot): string[] {\n  return [\n    `plan: ${snapshot.planType ?? \"unknown\"}`,\n    ...(snapshot.email ? [`email: ${maskEmail(snapshot.email)}`] : []),\n    `5-hour: ${formatUsedPercent(snapshot.fiveHour)} used, ${formatRemainingPercent(snapshot.fiveHour)} left, resets ${formatResetLong(snapshot.fiveHour?.resetAt)}`,\n    `weekly: ${formatUsedPercent(snapshot.weekly)} used, ${formatRemainingPercent(snapshot.weekly)} left, resets ${formatResetLong(snapshot.weekly?.resetAt)}`,\n    OPEN_DASHBOARD_OPTION,\n  ];\n}\n\nfunction getOpenCommand(url: string): { command: string; args: string[] } {\n  if (process.platform === \"darwin\") return { command: \"open\", args: [url] };\n  if (process.platform === \"win32\") return { command: \"cmd\", args: [\"/c\", \"start\", \"\", url] };\n  return { command: \"xdg-open\", args: [url] };\n}\n\nasync function openUsageDashboard(pi: ExtensionAPI, ctx: ExtensionContext) {\n  const { command, args } = getOpenCommand(USAGE_DASHBOARD_URL);\n  const result = await pi.exec(command, args).catch(() => undefined);\n  if (result) {\n    ctx.ui.notify(\"Opened Codex usage dashboard in your browser.\", \"info\");\n  } else {\n    ctx.ui.notify(`Could not open browser. Visit: ${USAGE_DASHBOARD_URL}`, \"warning\");\n  }\n}\n\nfunction buildUsageTitle(ctx: ExtensionContext, snapshot: UsageSnapshot): string {\n  return `Codex usage limits ${ctx.ui.theme.fg(\"dim\", `(fetched: ${formatFetchedAt(snapshot.fetchedAt)})`)}`;\n}\n\nasync function showUsageDetails(ctx: ExtensionContext, snapshot: UsageSnapshot) {\n  const title = buildUsageTitle(ctx, snapshot);\n  const details = buildUsageDetails(snapshot);\n  const actionIndex = details.indexOf(OPEN_DASHBOARD_OPTION);\n\n  return ctx.ui.custom<string | undefined>((tui, theme, _keybindings, done) => {\n    let selectedIndex = 0;\n    let cachedLines: string[] | undefined;\n\n    const refresh = () => {\n      cachedLines = undefined;\n      tui.requestRender();\n    };\n\n    const handleInput = (data: string) => {\n      if (matchesKey(data, Key.up) || data === \"k\") {\n        selectedIndex = Math.max(0, selectedIndex - 1);\n        refresh();\n        return;\n      }\n\n      if (matchesKey(data, Key.down) || data === \"j\") {\n        selectedIndex = Math.min(details.length - 1, selectedIndex + 1);\n        refresh();\n        return;\n      }\n\n      if (matchesKey(data, Key.enter) && selectedIndex === actionIndex) {\n        done(OPEN_DASHBOARD_OPTION);\n        return;\n      }\n\n      if (matchesKey(data, Key.escape) || matchesKey(data, Key.ctrl(\"c\"))) {\n        done(undefined);\n      }\n    };\n\n    const render = (width: number): string[] => {\n      if (cachedLines) return cachedLines;\n\n      const lines: string[] = [];\n      const add = (line: string) => lines.push(truncateToWidth(line, width));\n      const selectedAction = selectedIndex === actionIndex;\n\n      add(theme.fg(\"accent\", \"─\".repeat(width)));\n      add(theme.fg(\"accent\", theme.bold(` ${title}`)));\n      lines.push(\"\");\n\n      for (let i = 0; i < details.length; i++) {\n        const selected = i === selectedIndex;\n        const actionable = i === actionIndex;\n        const prefix = selected ? theme.fg(\"accent\", \"→ \") : \"  \";\n        const color = selected ? \"accent\" : actionable ? \"text\" : \"muted\";\n        add(prefix + theme.fg(color, details[i]));\n      }\n\n      lines.push(\"\");\n      add(\n        theme.fg(\n          \"dim\",\n          selectedAction\n            ? \"↑↓ navigate • Enter to open usage dashboard • Esc/Ctrl+C cancel\"\n            : \"↑↓ navigate • Esc/Ctrl+C cancel\",\n        ),\n      );\n      add(theme.fg(\"accent\", \"─\".repeat(width)));\n\n      cachedLines = lines;\n      return lines;\n    };\n\n    return {\n      invalidate() {\n        cachedLines = undefined;\n      },\n      handleInput,\n      render,\n    };\n  });\n}\n\n/** Install an invisible render hook so async refreshes repaint the footer-mode widget. */\nfunction installWidget(ctx: ExtensionContext) {\n  if (!ctx.hasUI) return;\n\n  ctx.ui.setWidget(\n    WIDGET_KEY,\n    (tui) => {\n      requestRender = () => tui.requestRender();\n      return {\n        invalidate() {},\n        render(): string[] {\n          return [];\n        },\n      };\n    },\n    { placement: \"belowEditor\" },\n  );\n}\n\n/** Register lifecycle hooks and the `/codex-limit` command. */\nexport default function (pi: ExtensionAPI): void {\n  let inFlight: Promise<UsageSnapshot | undefined> = Promise.resolve(undefined);\n\n  /** Serialize refreshes so model changes and agent_end cannot fetch concurrently. */\n  const queueUpdate = (ctx: ExtensionContext) => {\n    inFlight = inFlight.catch(() => undefined).then(() => updateUsage(ctx));\n    return inFlight;\n  };\n\n  pi.on(\"session_start\", (_event, ctx) => {\n    installWidget(ctx);\n    void queueUpdate(ctx);\n  });\n\n  pi.on(\"model_select\", (_event, ctx) => {\n    void queueUpdate(ctx);\n  });\n\n  pi.on(\"agent_end\", (_event, ctx) => {\n    void queueUpdate(ctx);\n  });\n\n  pi.on(\"session_shutdown\", () => {\n    usageSnapshot = undefined;\n    globalThis[GLOBAL_USAGE_KEY] = undefined;\n    requestRender = () => {};\n  });\n\n  pi.registerCommand(\"codex-limit\", {\n    description: \"Show Codex 5-hour and weekly usage limits\",\n    handler: async (_args, ctx) => {\n      if (!isOpenAICodexProvider(ctx.model?.provider)) {\n        ctx.ui.notify(\"Codex limits are only available for openai-codex models.\", \"info\");\n        return;\n      }\n\n      const snapshot = await queueUpdate(ctx);\n      if (!snapshot) {\n        ctx.ui.notify(\"Could not load Codex usage limits.\", \"warning\");\n        return;\n      }\n\n      const selected = await showUsageDetails(ctx, snapshot);\n      if (selected === OPEN_DASHBOARD_OPTION) await openUsageDashboard(pi, ctx);\n    },\n  });\n}\n"],"mappings":"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"}