Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.
| Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens | 1 | /** |
| 2 | * How the AI Gateway page speaks of its requests. Pure, so it can be tested. | |
| 3 | */ | |
| 4 | ||
| 5 | import type { GatewayRequest } from "@g1t/contracts"; | |
| 6 | ||
| 7 | /** Where the AI Gateway is documented. */ | |
| 8 | export const GATEWAY_DOCS = "https://docs.g1t.sh/guides/ai-gateway/"; | |
| 9 | ||
| 10 | /** The base URL an Anthropic SDK or Claude Code is pointed at. */ | |
| 11 | export const GATEWAY_BASE_URL = "https://models.g1t.sh/anthropic"; | |
| 12 | ||
| AI Gateway: OpenAI's format, open models, and your own providers | 13 | /** The base URL an OpenAI SDK, or any tool that speaks OpenAI's API, is pointed at. */ |
| 14 | export const GATEWAY_OPENAI_BASE_URL = "https://models.g1t.sh/openai/v1"; | |
| 15 | ||
| 16 | /** How a request's format reads. */ | |
| 17 | export function formatLabel(format: GatewayRequest["format"] | undefined): string { | |
| 18 | return format === "openai" ? "OpenAI" : "Anthropic"; | |
| 19 | } | |
| 20 | ||
| 21 | /** Who served a request, as people read it, and a longer line for its hint. */ | |
| 22 | export function servedBy(request: Pick<GatewayRequest, "ownKey" | "provider" | "connection">): { label: string; hint: string } { | |
| 23 | if (request.ownKey) { | |
| 24 | const name = request.connection || "Your provider"; | |
| 25 | return { label: name, hint: `${name}, the workspace's own ${providerName(request.provider)}: counted, not charged.` }; | |
| 26 | } | |
| 27 | if (!request.provider) return { label: "None", hint: "Refused before it reached a model." }; | |
| 28 | return { label: `g1t · ${providerName(request.provider)}`, hint: `g1t's account at ${providerName(request.provider)}, charged at the model's price.` }; | |
| 29 | } | |
| 30 | ||
| 31 | const PROVIDER_NAMES: Record<string, string> = { | |
| 32 | anthropic: "Anthropic", | |
| 33 | "workers-ai": "Workers AI", | |
| 34 | openai: "OpenAI", | |
| 35 | openai_endpoint: "OpenAI-compatible endpoint", | |
| 36 | anthropic_endpoint: "Anthropic-compatible endpoint", | |
| 37 | azure_openai: "Azure OpenAI", | |
| 38 | gemini: "Google Gemini", | |
| 39 | openrouter: "OpenRouter", | |
| 40 | }; | |
| 41 | ||
| 42 | /** A provider's name, as people know it. */ | |
| 43 | export function providerName(provider: string): string { | |
| 44 | return PROVIDER_NAMES[provider] ?? (provider || "provider"); | |
| 45 | } | |
| 46 | ||
| 47 | /** A connection's AI Gateway models, as a field shows them, from what was typed. */ | |
| 48 | export function parseGatewayModels(text: string): string[] { | |
| 49 | return text | |
| 50 | .split(/[\s,]+/) | |
| 51 | .map((model) => model.trim()) | |
| 52 | .filter(Boolean); | |
| 53 | } | |
| 54 | ||
| Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens | 55 | /** A count of tokens, short: `812`, `12.4K`, `3.1M`. */ |
| 56 | export function shortCount(n: number): string { | |
| 57 | if (n < 1_000) return String(n); | |
| 58 | if (n < 1_000_000) return `${trim(n / 1_000)}K`; | |
| 59 | return `${trim(n / 1_000_000)}M`; | |
| 60 | } | |
| 61 | ||
| 62 | function trim(value: number): string { | |
| 63 | return value >= 100 ? String(Math.round(value)) : value.toFixed(1).replace(/\.0$/, ""); | |
| 64 | } | |
| 65 | ||
| 66 | /** Every token a request used. */ | |
| 67 | export function totalTokens(request: Pick<GatewayRequest, "input" | "output" | "cacheRead" | "cacheWrite">): number { | |
| 68 | return request.input + request.output + request.cacheRead + request.cacheWrite; | |
| 69 | } | |
| 70 | ||
| 71 | /** The tokens of each kind, in words, for a hint. */ | |
| 72 | export function tokenKinds(request: Pick<GatewayRequest, "input" | "output" | "cacheRead" | "cacheWrite">): string { | |
| 73 | const n = (v: number) => v.toLocaleString("en-US"); | |
| 74 | return `${n(request.input)} input, ${n(request.output)} output, ${n(request.cacheRead)} cache read, ${n(request.cacheWrite)} cache write`; | |
| 75 | } | |
| 76 | ||
| AI Gateway: OpenAI's format, open models, and your own providers | 77 | /** A request's cache tokens in words, for a hint: read, written, and how many of the writes last an hour. */ |
| 78 | export function cacheKinds(request: Pick<GatewayRequest, "cacheRead" | "cacheWrite" | "cacheWriteHour">): string { | |
| 79 | const n = (v: number) => v.toLocaleString("en-US"); | |
| 80 | const hour = request.cacheWriteHour ? `, ${n(request.cacheWriteHour)} of them to the hour-long cache` : ""; | |
| 81 | return `${n(request.cacheRead)} read from the cache, ${n(request.cacheWrite)} written${hour}`; | |
| 82 | } | |
| 83 | ||
| Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens | 84 | /** How a status reads, and how much it matters. */ |
| 85 | export function statusTone(status: number): { label: string; tone: "success" | "warn" | "danger" | "neutral" } { | |
| 86 | if (status >= 200 && status < 300) return { label: String(status), tone: "success" }; | |
| 87 | if (status === 402 || status === 429) return { label: String(status), tone: "warn" }; | |
| 88 | if (status >= 400) return { label: String(status), tone: "danger" }; | |
| 89 | return { label: String(status), tone: "neutral" }; | |
| 90 | } | |
| 91 | ||
| 92 | /** A request's duration: `840 ms`, `4.2 s`, `2 min 5 s`. */ | |
| 93 | export function duration(ms: number): string { | |
| 94 | if (ms < 1_000) return `${Math.round(ms)} ms`; | |
| 95 | if (ms < 60_000) return `${(ms / 1_000).toFixed(1).replace(/\.0$/, "")} s`; | |
| 96 | const seconds = Math.round(ms / 1_000); | |
| 97 | return `${Math.floor(seconds / 60)} min ${seconds % 60} s`; | |
| 98 | } |
This file's history is long; its oldest lines are credited to the oldest commit read.