import { ExternalLink } from 'lucide-react';
import { EntityLink } from '@/components/ui/entity';
import { DataTable, EmptyRow, Td, Th } from '@/components/ui/data-table';
import { Note } from '@/components/ui/section';
import { fmtDateTime, fmtAgo, fmtUsdPerM, num } from '@/lib/format';
import type { ChangeEvent } from '@/lib/types';
type PriceValue = { input_per_mtok?: unknown; output_per_mtok?: unknown } | null | undefined;
function pv(v: unknown): { input: number | null; output: number | null } {
const o = (v && typeof v === 'object' ? v : {}) as PriceValue;
return { input: num(o?.input_per_mtok), output: num(o?.output_per_mtok) };
}
function host(url: string): string {
try {
return new URL(url).hostname.replace(/^www\./, '');
} catch {
return 'source';
}
}
/** Old → new price cell: strike-through old, bold new, direction sign. Amber = money. */
function Move({ from, to }: { from: number | null; to: number | null }) {
if (from === null && to === null) return —;
const dir = from !== null && to !== null ? (to < from ? '↓' : to > from ? '↑' : '=') : '';
return (
{fmtUsdPerM(from)}→{fmtUsdPerM(to)}
{dir && dir !== '=' && {dir}}
);
}
/** PRICE_CHANGED events as a dense table: model · provider · input move · output move · when · source. */
export function PriceMovers({ movers }: { movers: ChangeEvent[] }) {
const rows = movers.filter((e) => e.event_type === 'PRICE_CHANGED' || e.category === 'price');
return (
<>
Model
Provider
Input / 1M
Output / 1M
Observed
Source
{rows.length === 0 && No price change recorded in this window. The first observation of a price is not a change.}
{rows.map((e) => {
const o = pv(e.old_value);
const n = pv(e.new_value);
const provider = typeof e.meta?.provider === 'string' ? e.meta.provider : null;
return (
);
})}
{rows.length > 0 && Movers are PRICE_CHANGED events emitted when a provider's published price for a model differs from the previous observation. Green arrow = cheaper, red = dearer.}
>
);
}