gpt-5.2 · cursor
cursor
- config
- gpt-5.2--cli--cursor--dev
- batch
- 2026-07-19--unified
- transport
- cursor-agent-cli-isolated-home
- protocol
- cli · plan
- served model
- gpt-5.2
- 采集于
- 2026年7月18日 11:54 · N=2
variant
live
slot 0 · P-q · sandboxed iframe

截图是 similarity 通道测量时的原始像素。运行 live 会在 sandboxed iframe 中重新执行原始输出;渲染结果取决于你的浏览器和字体,不保证与测量像素一致。
similarity 邻居
最近
gpt-5.2 @high · cursor0.76gpt-5.2 · cursor-xl0.75gpt-5.2 @low · cursor-xl0.74gpt-5.2 @xhigh · cursor-xl0.74gpt-5.2 @low · cursor0.73最远
north-mini-code-free · api0.50claude-sonnet-4 · cursor0.50claude-sonnet-4 · kiro0.50claude-sonnet-4-5-thinking · cursor-xl0.51claude-haiku-4-5 @high · CC0.51限于 session 2026-07-19--unified
similarity 衡量本 session 内的趋同程度 —— 不是质量。
Fidelity —— 卡片展示的数据对不对?
- namematch
- conditionmatch
- datematch
- max tempmatch展示值:25.3
- min tempmatch展示值:16
- hourlymismatchcoverage 0/24 · 0 命中 · 3 不符 · 21 未展示
- request sidematch0 处违规
extractor fidelity-extractor-v1+Berlin-2026-07-15
源码 —— 原始模型输出,一字节未改
下载 card.html<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=1280, initial-scale=1" />
<title>Weather Card</title>
<style>
:root{
--bg0:#070A12;
--bg1:#0A1430;
--card:#0b1020cc;
--stroke:#ffffff1a;
--stroke2:#ffffff24;
--text:#EAF0FF;
--muted:#B9C5E6;
--muted2:#93A3C8;
--accent:#7CF6FF;
--accent2:#8B5CFF;
--good:#62F6A6;
--warn:#FFD36B;
--bad:#FF6B8B;
--shadow: 0 20px 60px rgba(0,0,0,.55);
--shadow2: 0 8px 30px rgba(0,0,0,.35);
--r1: 22px;
--r2: 16px;
--mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
--sans: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, "Apple Color Emoji", "Segoe UI Emoji";
}
html, body { height:100%; }
body{
margin:0;
font-family: var(--sans);
color: var(--text);
background:
radial-gradient(1200px 900px at 20% 15%, rgba(124,246,255,.18), transparent 60%),
radial-gradient(1100px 900px at 80% 20%, rgba(139,92,255,.18), transparent 65%),
radial-gradient(900px 700px at 55% 85%, rgba(98,246,166,.10), transparent 60%),
linear-gradient(180deg, var(--bg0), var(--bg1));
overflow:hidden;
}
.frame{
width:1280px;
height:800px;
margin:0 auto;
position:relative;
display:flex;
align-items:center;
justify-content:center;
padding:42px;
box-sizing:border-box;
}
.grain{
pointer-events:none;
position:absolute;
inset:-40px;
background:
radial-gradient(1px 1px at 10% 10%, rgba(255,255,255,.08), transparent 35%),
radial-gradient(1px 1px at 40% 70%, rgba(255,255,255,.06), transparent 35%),
radial-gradient(1px 1px at 70% 30%, rgba(255,255,255,.06), transparent 35%),
radial-gradient(1px 1px at 85% 80%, rgba(255,255,255,.06), transparent 35%),
radial-gradient(1px 1px at 25% 55%, rgba(255,255,255,.05), transparent 35%),
radial-gradient(1px 1px at 55% 25%, rgba(255,255,255,.05), transparent 35%);
mix-blend-mode: overlay;
opacity:.22;
filter: blur(.2px);
transform: translateZ(0);
}
.card{
width:min(980px, 100%);
border-radius: var(--r1);
background: linear-gradient(180deg, rgba(255,255,255,.08), rgba(255,255,255,.04));
box-shadow: var(--shadow);
border: 1px solid var(--stroke);
overflow:hidden;
position:relative;
backdrop-filter: blur(14px);
-webkit-backdrop-filter: blur(14px);
}
.card::before{
content:"";
position:absolute;
inset:-2px;
background:
radial-gradient(600px 420px at 18% 20%, rgba(124,246,255,.22), transparent 55%),
radial-gradient(520px 380px at 82% 28%, rgba(139,92,255,.20), transparent 60%),
radial-gradient(520px 420px at 60% 110%, rgba(98,246,166,.12), transparent 60%);
opacity:.9;
pointer-events:none;
}
.inner{
position:relative;
display:grid;
grid-template-columns: 1.1fr .9fr;
gap:0;
}
.left, .right{
padding:26px 26px 22px 26px;
box-sizing:border-box;
}
.left{
border-right:1px solid var(--stroke);
}
.top{
display:flex;
align-items:flex-start;
justify-content:space-between;
gap:18px;
margin-bottom:14px;
}
.titleWrap{
min-width:0;
}
.kicker{
font-size:12px;
letter-spacing:.12em;
text-transform:uppercase;
color: rgba(234,240,255,.78);
display:flex;
align-items:center;
gap:10px;
margin-bottom:8px;
}
.pill{
display:inline-flex;
align-items:center;
gap:8px;
padding:7px 10px;
border-radius:999px;
border:1px solid var(--stroke);
background: rgba(0,0,0,.18);
box-shadow: var(--shadow2);
font-size:12px;
color: rgba(234,240,255,.84);
user-select:none;
white-space:nowrap;
}
.pill code{
font-family: var(--mono);
font-size:11px;
color: rgba(234,240,255,.9);
}
.title{
font-size:34px;
line-height:1.12;
letter-spacing:-0.02em;
font-weight:720;
margin:0 0 6px 0;
white-space:nowrap;
overflow:hidden;
text-overflow:ellipsis;
}
.sub{
display:flex;
align-items:center;
flex-wrap:wrap;
gap:10px;
color: var(--muted);
font-size:14px;
}
.sub .dot{
width:4px; height:4px; border-radius:99px;
background: rgba(234,240,255,.35);
}
.hero{
display:grid;
grid-template-columns: 1fr;
gap:14px;
margin-top:14px;
}
.metrics{
display:grid;
grid-template-columns: 1fr 1fr;
gap:14px;
}
.metric{
border-radius: var(--r2);
border:1px solid var(--stroke);
background: rgba(0,0,0,.16);
padding:14px 14px 12px 14px;
box-shadow: var(--shadow2);
position:relative;
overflow:hidden;
}
.metric::before{
content:"";
position:absolute;
inset:-1px;
background: radial-gradient(360px 140px at 10% 10%, rgba(255,255,255,.10), transparent 60%);
opacity:.6;
pointer-events:none;
}
.metricLabel{
position:relative;
display:flex;
align-items:center;
justify-content:space-between;
gap:10px;
color: rgba(234,240,255,.72);
font-size:12px;
letter-spacing:.10em;
text-transform:uppercase;
margin-bottom:10px;
}
.metricValue{
position:relative;
display:flex;
align-items:baseline;
gap:8px;
}
.big{
font-size:34px;
line-height:1;
font-weight:760;
letter-spacing:-0.03em;
}
.unit{
font-size:14px;
color: rgba(234,240,255,.78);
margin-left:2px;
}
.range{
font-size:12px;
color: rgba(234,240,255,.70);
font-family: var(--mono);
white-space:nowrap;
}
.cond{
display:flex;
align-items:center;
gap:14px;
border-radius: var(--r2);
border:1px solid var(--stroke);
background: rgba(0,0,0,.14);
padding:14px 14px;
box-shadow: var(--shadow2);
}
.condText{
min-width:0;
}
.condName{
font-size:16px;
font-weight:670;
letter-spacing:-0.01em;
margin:0 0 2px 0;
white-space:nowrap;
overflow:hidden;
text-overflow:ellipsis;
}
.condMeta{
margin:0;
color: rgba(234,240,255,.70);
font-size:12px;
font-family: var(--mono);
display:flex;
gap:10px;
flex-wrap:wrap;
}
.icon{
width:46px;
height:46px;
flex:0 0 auto;
filter: drop-shadow(0 10px 18px rgba(0,0,0,.35));
}
.rightHeader{
display:flex;
align-items:flex-start;
justify-content:space-between;
gap:16px;
margin-bottom:10px;
}
.hTitle{
font-size:14px;
letter-spacing:.10em;
text-transform:uppercase;
color: rgba(234,240,255,.72);
margin:0;
}
.sparkWrap{
margin-top:10px;
border-radius: var(--r2);
border:1px solid var(--stroke);
background: rgba(0,0,0,.14);
padding:12px 12px 10px 12px;
box-shadow: var(--shadow2);
overflow:hidden;
}
.sparkTop{
display:flex;
align-items:center;
justify-content:space-between;
gap:10px;
margin-bottom:10px;
}
.legend{
display:flex;
align-items:center;
gap:10px;
color: rgba(234,240,255,.70);
font-size:12px;
font-family: var(--mono);
white-space:nowrap;
}
.swatch{
width:10px;
height:10px;
border-radius:3px;
background: linear-gradient(135deg, rgba(124,246,255,.95), rgba(139,92,255,.9));
box-shadow: 0 0 0 1px rgba(255,255,255,.18) inset;
}
.spark{
width:100%;
height:156px;
display:block;
}
.hours{
margin-top:14px;
display:grid;
grid-template-columns: repeat(6, minmax(0, 1fr));
gap:10px;
}
.hour{
border-radius: 14px;
border:1px solid var(--stroke);
background: rgba(0,0,0,.14);
padding:10px 10px 9px 10px;
box-shadow: var(--shadow2);
min-width:0;
}
.hourT{
color: rgba(234,240,255,.70);
font-size:11px;
letter-spacing:.10em;
text-transform:uppercase;
font-family: var(--mono);
margin-bottom:6px;
white-space:nowrap;
overflow:hidden;
text-overflow:ellipsis;
}
.hourV{
display:flex;
align-items:baseline;
justify-content:space-between;
gap:8px;
}
.hourVal{
font-size:16px;
font-weight:720;
letter-spacing:-0.02em;
white-space:nowrap;
}
.hourDot{
width:10px;height:10px;border-radius:999px;
background: rgba(124,246,255,.35);
box-shadow: 0 0 0 1px rgba(255,255,255,.18) inset;
flex:0 0 auto;
}
.footer{
padding:14px 26px 18px 26px;
border-top:1px solid var(--stroke);
display:flex;
align-items:center;
justify-content:space-between;
gap:10px;
color: rgba(234,240,255,.62);
font-size:12px;
}
.footer code{
font-family: var(--mono);
font-size:11px;
color: rgba(234,240,255,.72);
}
.status{
display:flex;
align-items:center;
gap:10px;
min-width:0;
}
.status .badge{
flex:0 0 auto;
width:10px;height:10px;border-radius:999px;
background: rgba(255,255,255,.25);
box-shadow: 0 0 0 1px rgba(255,255,255,.12) inset;
}
.status.ok .badge{ background: rgba(98,246,166,.78); }
.status.loading .badge{
background: rgba(124,246,255,.75);
animation: pulse 1.05s ease-in-out infinite;
}
.status.err .badge{ background: rgba(255,107,139,.78); }
.statusText{
min-width:0;
white-space:nowrap;
overflow:hidden;
text-overflow:ellipsis;
}
@keyframes pulse{
0%{ transform: scale(1); opacity:.6; }
50%{ transform: scale(1.22); opacity:1; }
100%{ transform: scale(1); opacity:.6; }
}
.skeleton{
background: linear-gradient(90deg, rgba(255,255,255,.06), rgba(255,255,255,.12), rgba(255,255,255,.06));
background-size: 220% 100%;
animation: shimmer 1.1s ease-in-out infinite;
border-radius: 10px;
height: 14px;
width: 160px;
}
.skeleton.big{ height: 30px; width: 260px; border-radius: 12px; }
@keyframes shimmer{
0%{ background-position: 0% 0; }
100%{ background-position: 200% 0; }
}
.hidden{ display:none !important; }
/* Make it look crisp on typical desktop */
*{ -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
</style>
</head>
<body>
<div class="frame">
<div class="grain"></div>
<div class="card" role="application" aria-label="Weather card">
<div class="inner">
<section class="left">
<div class="top">
<div class="titleWrap">
<div class="kicker">
<span class="pill" title="Location label from URL query parameter `name`">
<span style="opacity:.8;">Location</span>
<code id="pillName">Berlin</code>
</span>
<span class="pill" title="Coordinates from URL query parameters `lat` and `lon`">
<span style="opacity:.8;">Coords</span>
<code id="pillCoords">52.52, 13.405</code>
</span>
</div>
<h1 class="title" id="titleName">Berlin</h1>
<div class="sub">
<span class="pill" title="Requested date (UTC)">
<span style="opacity:.8;">Date</span>
<code id="titleDate">—</code>
</span>
<span class="dot" aria-hidden="true"></span>
<span style="color: rgba(234,240,255,.75); font-family: var(--mono); font-size:12px;" id="whichApi">—</span>
</div>
</div>
<div class="pill" title="All times in UTC">
<span style="opacity:.8;">Timezone</span>
<code>UTC</code>
</div>
</div>
<div class="hero">
<div class="metrics">
<div class="metric">
<div class="metricLabel">
<span>Daily Max</span>
<span class="range" id="maxRange">—</span>
</div>
<div class="metricValue">
<div class="big" id="tMax">—</div>
<div class="unit">°C</div>
</div>
</div>
<div class="metric">
<div class="metricLabel">
<span>Daily Min</span>
<span class="range" id="minRange">—</span>
</div>
<div class="metricValue">
<div class="big" id="tMin">—</div>
<div class="unit">°C</div>
</div>
</div>
</div>
<div class="cond">
<svg class="icon" id="condIcon" viewBox="0 0 64 64" fill="none" aria-hidden="true">
<defs>
<linearGradient id="g1" x1="8" y1="10" x2="58" y2="54" gradientUnits="userSpaceOnUse">
<stop stop-color="rgba(124,246,255,.95)"/>
<stop offset="1" stop-color="rgba(139,92,255,.92)"/>
</linearGradient>
</defs>
<circle cx="32" cy="32" r="18" stroke="url(#g1)" stroke-width="3" opacity=".9"/>
<path d="M22 36c2.2-4.5 5.8-7 10-7s7.8 2.5 10 7" stroke="url(#g1)" stroke-width="3" stroke-linecap="round" opacity=".9"/>
<path d="M24 26h0" stroke="url(#g1)" stroke-width="6" stroke-linecap="round" opacity=".7"/>
<path d="M40 26h0" stroke="url(#g1)" stroke-width="6" stroke-linecap="round" opacity=".7"/>
</svg>
<div class="condText">
<p class="condName" id="condName">—</p>
<p class="condMeta">
<span>Weather code:</span><span id="condCode">—</span>
<span style="opacity:.5;">·</span>
<span>Hourly temps:</span><span id="hourCount">—</span>
</p>
</div>
</div>
</div>
</section>
<section class="right">
<div class="rightHeader">
<p class="hTitle">Hourly temperature</p>
<span class="pill" title="Hourly temperature range for the requested day">
<span style="opacity:.8;">Range</span>
<code id="hourRange">—</code>
</span>
</div>
<div class="sparkWrap" aria-label="Hourly temperature chart">
<div class="sparkTop">
<div class="legend">
<span class="swatch" aria-hidden="true"></span>
<span id="sparkCaption">—</span>
</div>
<div class="legend">
<span style="opacity:.75;">Min/Max</span>
<span id="sparkMinMax">—</span>
</div>
</div>
<svg class="spark" id="spark" viewBox="0 0 720 156" preserveAspectRatio="none">
<defs>
<linearGradient id="lineGrad" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="rgba(124,246,255,.95)"/>
<stop offset="55%" stop-color="rgba(124,246,255,.65)"/>
<stop offset="100%" stop-color="rgba(139,92,255,.90)"/>
</linearGradient>
<linearGradient id="fillGrad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="rgba(124,246,255,.24)"/>
<stop offset="65%" stop-color="rgba(139,92,255,.14)"/>
<stop offset="100%" stop-color="rgba(0,0,0,0)"/>
</linearGradient>
</defs>
<rect x="0" y="0" width="720" height="156" fill="rgba(0,0,0,.10)" opacity=".2"/>
<g id="grid" opacity=".55"></g>
<path id="area" d="" fill="url(#fillGrad)"></path>
<path id="line" d="" stroke="url(#lineGrad)" stroke-width="3.2" stroke-linecap="round" stroke-linejoin="round" fill="none"></path>
<g id="markers"></g>
</svg>
</div>
<div class="hours" id="hours" aria-label="Hourly temperatures list"></div>
</section>
</div>
<div class="footer">
<div class="status loading" id="status">
<span class="badge" aria-hidden="true"></span>
<span class="statusText" id="statusText">Loading weather…</span>
</div>
<div>
<span style="opacity:.8;">API:</span>
<code id="apiHint">/api/om/forecast</code>
</div>
</div>
</div>
</div>
<script>
(function () {
const $ = (id) => document.getElementById(id);
function clamp(n, a, b){ return Math.max(a, Math.min(b, n)); }
function isFiniteNumber(x){ return typeof x === "number" && Number.isFinite(x); }
function todayUTC() {
return new Date().toISOString().slice(0, 10);
}
function parseQuery() {
const u = new URL(window.location.href);
const q = u.searchParams;
const lat = Number(q.get("lat") ?? "52.52");
const lon = Number(q.get("lon") ?? "13.405");
const name = (q.get("name") ?? "Berlin").trim() || "Berlin";
const date = (q.get("date") ?? todayUTC()).trim() || todayUTC();
const safeLat = isFiniteNumber(lat) ? clamp(lat, -90, 90) : 52.52;
const safeLon = isFiniteNumber(lon) ? clamp(lon, -180, 180) : 13.405;
// Basic YYYY-MM-DD validation (fallback to today UTC)
const dateOk = /^\d{4}-\d{2}-\d{2}$/.test(date) ? date : todayUTC();
return { lat: safeLat, lon: safeLon, name, date: dateOk };
}
function endpointForDate(dateStr) {
// Lexicographic compare works for YYYY-MM-DD
const t = todayUTC();
return (dateStr < t) ? "/api/om/archive" : "/api/om/forecast";
}
function weatherCodeInfo(code) {
// Open-Meteo weather codes
const c = Number(code);
const map = new Map([
[0, ["Clear sky", "clear"]],
[1, ["Mainly clear", "partly"]],
[2, ["Partly cloudy", "partly"]],
[3, ["Overcast", "cloudy"]],
[45, ["Fog", "fog"]],
[48, ["Depositing rime fog", "fog"]],
[51, ["Light drizzle", "drizzle"]],
[53, ["Moderate drizzle", "drizzle"]],
[55, ["Dense drizzle", "drizzle"]],
[56, ["Light freezing drizzle", "drizzle"]],
[57, ["Dense freezing drizzle", "drizzle"]],
[61, ["Slight rain", "rain"]],
[63, ["Moderate rain", "rain"]],
[65, ["Heavy rain", "rain"]],
[66, ["Light freezing rain", "rain"]],
[67, ["Heavy freezing rain", "rain"]],
[71, ["Slight snow fall", "snow"]],
[73, ["Moderate snow fall", "snow"]],
[75, ["Heavy snow fall", "snow"]],
[77, ["Snow grains", "snow"]],
[80, ["Slight rain showers", "rain"]],
[81, ["Moderate rain showers", "rain"]],
[82, ["Violent rain showers", "rain"]],
[85, ["Slight snow showers", "snow"]],
[86, ["Heavy snow showers", "snow"]],
[95, ["Thunderstorm", "thunder"]],
[96, ["Thunderstorm with slight hail", "thunder"]],
[99, ["Thunderstorm with heavy hail", "thunder"]],
]);
if (map.has(c)) {
const [label, kind] = map.get(c);
return { label, kind };
}
return { label: "Unknown conditions", kind: "unknown" };
}
function iconSVG(kind) {
const common = `
<defs>
<linearGradient id="ig" x1="6" y1="8" x2="58" y2="56" gradientUnits="userSpaceOnUse">
<stop stop-color="rgba(124,246,255,.98)"/>
<stop offset="1" stop-color="rgba(139,92,255,.94)"/>
</linearGradient>
<linearGradient id="iy" x1="14" y1="14" x2="52" y2="52" gradientUnits="userSpaceOnUse">
<stop stop-color="rgba(255,211,107,.98)"/>
<stop offset="1" stop-color="rgba(124,246,255,.78)"/>
</linearGradient>
</defs>
`;
if (kind === "clear") {
return `
${common}
<circle cx="32" cy="32" r="12" fill="none" stroke="url(#iy)" stroke-width="3.2" opacity=".95"/>
<g stroke="url(#iy)" stroke-linecap="round" stroke-width="3.2" opacity=".9">
<path d="M32 8v8"/><path d="M32 48v8"/>
<path d="M8 32h8"/><path d="M48 32h8"/>
<path d="M14.9 14.9l5.6 5.6"/><path d="M43.5 43.5l5.6 5.6"/>
<path d="M49.1 14.9l-5.6 5.6"/><path d="M20.5 43.5l-5.6 5.6"/>
</g>
`;
}
if (kind === "partly") {
return `
${common}
<circle cx="24" cy="24" r="10" fill="none" stroke="url(#iy)" stroke-width="3.0" opacity=".95"/>
<path d="M22 46h24a10 10 0 0 0 0-20c-1 0-2 .1-3 .3A14 14 0 0 0 17 30a9 9 0 0 0 5 16z"
fill="rgba(255,255,255,.10)" stroke="url(#ig)" stroke-width="3" stroke-linejoin="round" opacity=".95"/>
`;
}
if (kind === "cloudy") {
return `
${common}
<path d="M18 46h30a11 11 0 0 0 0-22c-1 0-2 .1-3 .3A16 16 0 0 0 15 30a10 10 0 0 0 3 16z"
fill="rgba(255,255,255,.10)" stroke="url(#ig)" stroke-width="3.2" stroke-linejoin="round" opacity=".95"/>
`;
}
if (kind === "fog") {
return `
${common}
<path d="M18 38h30a11 11 0 0 0 0-22c-1 0-2 .1-3 .3A16 16 0 0 0 15 22a10 10 0 0 0 3 16z"
fill="rgba(255,255,255,.08)" stroke="url(#ig)" stroke-width="3.2" stroke-linejoin="round" opacity=".9"/>
<g stroke="rgba(234,240,255,.55)" stroke-linecap="round" stroke-width="3.2">
<path d="M14 46h36"/>
<path d="M18 52h28" opacity=".85"/>
</g>
`;
}
if (kind === "drizzle") {
return `
${common}
<path d="M18 40h30a11 11 0 0 0 0-22c-1 0-2 .1-3 .3A16 16 0 0 0 15 24a10 10 0 0 0 3 16z"
fill="rgba(255,255,255,.09)" stroke="url(#ig)" stroke-width="3.2" stroke-linejoin="round" opacity=".95"/>
<g stroke="rgba(124,246,255,.75)" stroke-linecap="round" stroke-width="3">
<path d="M24 46v6" />
<path d="M32 46v6" opacity=".85"/>
<path d="M40 46v6" opacity=".7"/>
</g>
`;
}
if (kind === "rain") {
return `
${common}
<path d="M18 40h30a11 11 0 0 0 0-22c-1 0-2 .1-3 .3A16 16 0 0 0 15 24a10 10 0 0 0 3 16z"
fill="rgba(255,255,255,.09)" stroke="url(#ig)" stroke-width="3.2" stroke-linejoin="round" opacity=".95"/>
<g stroke="rgba(124,246,255,.85)" stroke-linecap="round" stroke-width="3.4">
<path d="M24 46l-2 8" />
<path d="M32 46l-2 8" opacity=".9"/>
<path d="M40 46l-2 8" opacity=".78"/>
</g>
`;
}
if (kind === "snow") {
return `
${common}
<path d="M18 40h30a11 11 0 0 0 0-22c-1 0-2 .1-3 .3A16 16 0 0 0 15 24a10 10 0 0 0 3 16z"
fill="rgba(255,255,255,.09)" stroke="url(#ig)" stroke-width="3.2" stroke-linejoin="round" opacity=".95"/>
<g stroke="rgba(234,240,255,.78)" stroke-linecap="round" stroke-width="2.6">
<path d="M26 48h0" />
<path d="M32 50h0" />
<path d="M38 48h0" />
<path d="M29 54h0" opacity=".85"/>
<path d="M35 54h0" opacity=".85"/>
</g>
`;
}
if (kind === "thunder") {
return `
${common}
<path d="M18 40h30a11 11 0 0 0 0-22c-1 0-2 .1-3 .3A16 16 0 0 0 15 24a10 10 0 0 0 3 16z"
fill="rgba(255,255,255,.09)" stroke="url(#ig)" stroke-width="3.2" stroke-linejoin="round" opacity=".95"/>
<path d="M31 44l-6 10h7l-3 8 10-14h-7l3-4z"
fill="rgba(255,211,107,.95)" opacity=".95"/>
`;
}
return `
${common}
<circle cx="32" cy="32" r="16" fill="none" stroke="url(#ig)" stroke-width="3.2" opacity=".95"/>
<path d="M24 34c2-4 5-6 8-6s6 2 8 6" stroke="url(#ig)" stroke-width="3.2" stroke-linecap="round" opacity=".9"/>
<path d="M24 26h0" stroke="url(#ig)" stroke-width="6" stroke-linecap="round" opacity=".65"/>
<path d="M40 26h0" stroke="url(#ig)" stroke-width="6" stroke-linecap="round" opacity=".65"/>
`;
}
function setStatus(kind, text) {
const s = $("status");
s.classList.remove("ok", "loading", "err");
s.classList.add(kind);
$("statusText").textContent = text;
}
function fmt1(x) {
if (!isFiniteNumber(x)) return "—";
const r = Math.round(x * 10) / 10;
const isInt = Math.abs(r - Math.round(r)) < 1e-9;
return isInt ? String(Math.round(r)) : String(r);
}
function buildGridLines() {
const g = $("grid");
const w = 720, h = 156;
const lines = [];
// Vertical lines at 0, 6, 12, 18, 24 hours (5 segments)
for (let i = 0; i <= 24; i += 6) {
const x = (i / 24) * w;
lines.push(`<line x1="${x.toFixed(2)}" y1="0" x2="${x.toFixed(2)}" y2="${h}" stroke="rgba(234,240,255,.12)" stroke-width="1"/>`);
}
// Horizontal subtle lines
for (let j = 1; j <= 3; j++) {
const y = (j / 4) * h;
lines.push(`<line x1="0" y1="${y.toFixed(2)}" x2="${w}" y2="${y.toFixed(2)}" stroke="rgba(234,240,255,.10)" stroke-width="1"/>`);
}
g.innerHTML = lines.join("");
}
function drawSpark(hours) {
// hours: [{h:0..23, t:number}]
const svgW = 720, svgH = 156;
const padX = 10, padY = 16;
const innerW = svgW - padX * 2;
const innerH = svgH - padY * 2;
const temps = hours.map(o => o.t).filter(isFiniteNumber);
if (!temps.length) {
$("line").setAttribute("d", "");
$("area").setAttribute("d", "");
$("markers").innerHTML = "";
return { min: null, max: null };
}
const tMin = Math.min(...temps);
const tMax = Math.max(...temps);
// Add a little padding so the line breathes.
const span = Math.max(1, (tMax - tMin));
const lo = tMin - span * 0.15;
const hi = tMax + span * 0.15;
const X = (i) => padX + (i / 23) * innerW;
const Y = (t) => padY + (1 - ((t - lo) / (hi - lo))) * innerH;
const pts = hours.map((o, i) => ({ x: X(i), y: Y(o.t), t: o.t, h: o.h }));
const d = pts.map((p, i) => (i ? "L" : "M") + p.x.toFixed(2) + " " + p.y.toFixed(2)).join(" ");
$("line").setAttribute("d", d);
// Area fill down to baseline
const baseY = padY + innerH;
const area = `${d} L ${pts[pts.length-1].x.toFixed(2)} ${baseY.toFixed(2)} L ${pts[0].x.toFixed(2)} ${baseY.toFixed(2)} Z`;
$("area").setAttribute("d", area);
// Markers: highlight min and max
const minIdx = pts.reduce((bi, p, i) => (p.t < pts[bi].t ? i : bi), 0);
const maxIdx = pts.reduce((bi, p, i) => (p.t > pts[bi].t ? i : bi), 0);
function marker(i, label, color) {
const p = pts[i];
return `
<g>
<circle cx="${p.x.toFixed(2)}" cy="${p.y.toFixed(2)}" r="5.2" fill="${color}" opacity=".92"></circle>
<circle cx="${p.x.toFixed(2)}" cy="${p.y.toFixed(2)}" r="9.5" fill="${color}" opacity=".10"></circle>
<text x="${(p.x + 10).toFixed(2)}" y="${(p.y - 10).toFixed(2)}" fill="rgba(234,240,255,.78)" font-size="11" font-family="var(--mono)">
${label}
</text>
</g>
`;
}
const minColor = "rgba(124,246,255,.95)";
const maxColor = "rgba(255,211,107,.95)";
$("markers").innerHTML = marker(minIdx, `min ${fmt1(pts[minIdx].t)}°`, minColor) + marker(maxIdx, `max ${fmt1(pts[maxIdx].t)}°`, maxColor);
return { min: tMin, max: tMax };
}
function renderHours(hours) {
const wrap = $("hours");
wrap.innerHTML = "";
const temps = hours.map(o => o.t).filter(isFiniteNumber);
const dayMin = temps.length ? Math.min(...temps) : null;
const dayMax = temps.length ? Math.max(...temps) : null;
function dotColor(t) {
if (!isFiniteNumber(t) || dayMin === null || dayMax === null) return "rgba(124,246,255,.35)";
const p = (t - dayMin) / Math.max(1e-9, (dayMax - dayMin));
const a = 0.25 + p * 0.60;
return `rgba(124,246,255,${a.toFixed(3)})`;
}
for (const o of hours) {
const hh = String(o.h).padStart(2, "0") + ":00";
const temp = fmt1(o.t);
const node = document.createElement("div");
node.className = "hour";
node.innerHTML = `
<div class="hourT">${hh}</div>
<div class="hourV">
<div class="hourVal">${temp}<span style="opacity:.75;">°C</span></div>
<div class="hourDot" style="background:${dotColor(o.t)}"></div>
</div>
`;
wrap.appendChild(node);
}
}
function setHeaderInfo({lat, lon, name, date, endpoint}) {
$("pillName").textContent = name;
$("titleName").textContent = name;
$("pillCoords").textContent = `${fmt1(lat)}, ${fmt1(lon)}`;
$("titleDate").textContent = date;
$("apiHint").textContent = endpoint;
$("whichApi").textContent = endpoint.endsWith("archive") ? "Using archive (past dates)" : "Using forecast (today & future)";
}
function safeGet(obj, path) {
try {
return path.split(".").reduce((o, k) => (o && (k in o)) ? o[k] : undefined, obj);
} catch {
return undefined;
}
}
async function loadAndRender() {
buildGridLines();
const { lat, lon, name, date } = parseQuery();
const endpoint = endpointForDate(date);
setHeaderInfo({ lat, lon, name, date, endpoint });
const params = new URLSearchParams({
latitude: String(lat),
longitude: String(lon),
daily: "temperature_2m_max,temperature_2m_min,weather_code",
hourly: "temperature_2m",
timezone: "UTC",
temperature_unit: "celsius",
start_date: date,
end_date: date
});
const url = endpoint + "?" + params.toString();
setStatus("loading", "Loading weather…");
let data;
try {
const res = await fetch(url, { method: "GET", headers: { "Accept": "application/json" } });
if (!res.ok) throw new Error(`HTTP ${res.status}`);
data = await res.json();
} catch (e) {
setStatus("err", "Weather data could not be loaded.");
$("condName").textContent = "Unable to load data";
$("condCode").textContent = "—";
$("hourCount").textContent = "—";
$("tMax").textContent = "—";
$("tMin").textContent = "—";
$("hourRange").textContent = "—";
$("sparkCaption").textContent = "No data";
$("sparkMinMax").textContent = "—";
$("hours").innerHTML = "";
return;
}
// Daily
const tMaxArr = safeGet(data, "daily.temperature_2m_max");
const tMinArr = safeGet(data, "daily.temperature_2m_min");
const wcArr = safeGet(data, "daily.weather_code");
if (!Array.isArray(tMaxArr) || !Array.isArray(tMinArr) || !Array.isArray(wcArr) || tMaxArr.length < 1 || tMinArr.length < 1 || wcArr.length < 1) {
setStatus("err", "Weather data could not be loaded.");
$("condName").textContent = "Missing daily data";
return;
}
const dMax = Number(tMaxArr[0]);
const dMin = Number(tMinArr[0]);
const wCode = Number(wcArr[0]);
$("tMax").textContent = fmt1(dMax);
$("tMin").textContent = fmt1(dMin);
$("maxRange").textContent = "°C";
$("minRange").textContent = "°C";
const info = weatherCodeInfo(wCode);
$("condName").textContent = info.label;
$("condCode").textContent = String(wCode);
$("condIcon").innerHTML = iconSVG(info.kind);
// Hourly
const hTime = safeGet(data, "hourly.time");
const hTemp = safeGet(data, "hourly.temperature_2m");
if (!Array.isArray(hTime) || !Array.isArray(hTemp) || hTime.length !== hTemp.length) {
setStatus("err", "Weather data could not be loaded.");
$("hourCount").textContent = "0/24";
$("sparkCaption").textContent = "Hourly data unavailable";
return;
}
// Extract the requested day in UTC
const hours = [];
for (let i = 0; i < hTime.length; i++) {
const ts = String(hTime[i] ?? "");
if (!ts.startsWith(date)) continue;
const hh = Number(ts.slice(11, 13));
const tt = Number(hTemp[i]);
if (!Number.isFinite(hh) || hh < 0 || hh > 23) continue;
hours.push({ h: hh, t: Number.isFinite(tt) ? tt : NaN });
}
// Ensure ordering and fill missing hours (if any) with NaN
const byHour = new Map(hours.map(o => [o.h, o.t]));
const full = [];
for (let h = 0; h < 24; h++) full.push({ h, t: byHour.has(h) ? byHour.get(h) : NaN });
const haveCount = full.filter(o => isFiniteNumber(o.t)).length;
$("hourCount").textContent = `${haveCount}/24`;
const temps = full.map(o => o.t).filter(isFiniteNumber);
if (!temps.length) {
setStatus("err", "Weather data could not be loaded.");
$("hourRange").textContent = "—";
$("sparkCaption").textContent = "No hourly data";
$("sparkMinMax").textContent = "—";
$("hours").innerHTML = "";
return;
}
const hMin = Math.min(...temps);
const hMax = Math.max(...temps);
$("hourRange").textContent = `${fmt1(hMin)}…${fmt1(hMax)}°C`;
$("sparkCaption").textContent = "Temperature by hour (UTC)";
$("sparkMinMax").textContent = `${fmt1(hMin)}°C / ${fmt1(hMax)}°C`;
const spark = drawSpark(full);
if (spark.min === null || spark.max === null) {
$("sparkMinMax").textContent = "—";
}
renderHours(full);
setStatus("ok", "Weather loaded.");
}
loadAndRender();
})();
</script>
</body>
</html>L1 —— 廉价的确定性描述量
| bytes 总计 | 35,453 | html / css / js | 6,444 / 10,873 / 18,136 |
|---|---|---|---|
| dom 节点 | 103 | dom 深度 | 11 |
| css 规则 | 64 | 含 js | 是 |
| brightness | 41.3 | contrast | 18.6 |
| colorfulness | 19.7 | 留白 | 62.9% |
该 slot 的 telemetry
| prompt tokens | 12,136 | completion tokens | 11,080 |
|---|---|---|---|
| total tokens | 23,216 | wall | 132.3 s |
| cost | — | request id | — |
config.json540 B
{
"N": 2,
"auth": {
"credential_ref": "WCB_NONE",
"method": "oauth-login"
},
"billing": "plan",
"config_id": "gpt-5.2--cli--cursor--dev",
"effort": null,
"family": "gpt",
"m": {
"min": 2,
"q": 2
},
"model_id": "gpt-5.2",
"protocol": "cli",
"served_model": "gpt-5.2",
"telemetry": {
"completion_tokens": 45923,
"cost_usd": null,
"prompt_tokens": 54026,
"total_tokens": 99949,
"wall_ms": 579943
},
"transport": "cursor-agent-cli-isolated-home",
"vendor_sanction_ref": null
}send-log2.4 KB
{
"N": 2,
"batch_id": "2026-08-13--cursor-s0",
"config_id": "gpt-5.2--cli--cursor--dev",
"positions": [
{
"attempts": [
{
"attempt_index": 0,
"backoff_ms": null,
"charged": true,
"ended_at": "2026-08-12T16:58:39.867457+00:00",
"http_status": null,
"outcome": "valid",
"reached_model": true,
"reason": "ok",
"request_id": null,
"started_at": "2026-08-12T16:56:27.583087+00:00"
}
],
"block_index": 0,
"model_reaching_attempt_index": 0,
"slot_index": 0,
"terminal_state": "valid",
"variant": "P-q"
},
{
"attempts": [
{
"attempt_index": 0,
"backoff_ms": null,
"charged": true,
"ended_at": "2026-08-12T17:00:26.830671+00:00",
"http_status": null,
"outcome": "valid",
"reached_model": true,
"reason": "ok",
"request_id": null,
"started_at": "2026-08-12T16:58:44.491023+00:00"
}
],
"block_index": 0,
"model_reaching_attempt_index": 0,
"slot_index": 0,
"terminal_state": "valid",
"variant": "P-min"
},
{
"attempts": [
{
"attempt_index": 0,
"backoff_ms": null,
"charged": true,
"ended_at": "2026-08-12T17:03:09.764707+00:00",
"http_status": null,
"outcome": "valid",
"reached_model": true,
"reason": "ok",
"request_id": null,
"started_at": "2026-08-12T17:00:29.999513+00:00"
}
],
"block_index": 1,
"model_reaching_attempt_index": 0,
"slot_index": 1,
"terminal_state": "valid",
"variant": "P-min"
},
{
"attempts": [
{
"attempt_index": 0,
"backoff_ms": null,
"charged": true,
"ended_at": "2026-08-12T17:06:19.294457+00:00",
"http_status": null,
"outcome": "valid",
"reached_model": true,
"reason": "ok",
"request_id": null,
"started_at": "2026-08-12T17:03:13.725661+00:00"
}
],
"block_index": 1,
"model_reaching_attempt_index": 0,
"slot_index": 1,
"terminal_state": "valid",
"variant": "P-q"
}
],
"retry_policy": {
"max_unreachable_retries": 5,
"rate_limit_backoff": {
"max_attempts": 4,
"max_total_ms": 60000
}
}
}