glm-5.1 · go

go
config
glm-5.1--opencode-go--dev
batch
2026-07-19--unified
transport
opencode-go-gateway
protocol
api · plan
served model
glm-5.1
采集于
2026年7月18日 11:54 · N=2
variant
live
slot 0 · P-q · sandboxed iframe
glm-5.1 · go P-q slot 0 截图

截图是 similarity 通道测量时的原始像素。运行 live 会在 sandboxed iframe 中重新执行原始输出;渲染结果取决于你的浏览器和字体,不保证与测量像素一致。

similarity 邻居

限于 session 2026-07-19--unified

similarity 衡量本 session 内的趋同程度 —— 不是质量。

Fidelity —— 卡片展示的数据对不对?

  • namematch
  • conditionmatch
  • datematch
  • max tempmatch展示值:25
  • min tempmatch展示值:16
  • hourlymismatchcoverage 0/24 · 0 命中 · 5 不符 · 19 未展示
  • request sidematch0 处违规

extractor fidelity-extractor-v1+Berlin-2026-07-15

源码 —— 原始模型输出,一字节未改

下载 card.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Weather</title>
<style>
  * { margin: 0; padding: 0; box-sizing: border-box; }
  html, body {
    width: 1280px;
    height: 800px;
    overflow: hidden;
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    color: #fff;
  }
  body {
    background: #0b1020;
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  #bg {
    position: absolute; inset: 0;
    background: linear-gradient(135deg, #1a2a4f 0%, #2d1b4e 50%, #4a1942 100%);
    transition: background 1.2s ease;
  }
  #bg::before {
    content: '';
    position: absolute; inset: 0;
    background:
      radial-gradient(circle at 20% 20%, rgba(255,200,120,0.15), transparent 40%),
      radial-gradient(circle at 80% 70%, rgba(120,180,255,0.15), transparent 45%);
    animation: drift 20s ease-in-out infinite alternate;
  }
  @keyframes drift {
    0% { transform: translate(0,0); }
    100% { transform: translate(-30px, 20px); }
  }

  .stars {
    position: absolute; inset: 0;
    background-image:
      radial-gradient(1px 1px at 12% 18%, rgba(255,255,255,0.7), transparent),
      radial-gradient(1px 1px at 28% 65%, rgba(255,255,255,0.5), transparent),
      radial-gradient(1px 1px at 47% 32%, rgba(255,255,255,0.6), transparent),
      radial-gradient(1px 1px at 68% 78%, rgba(255,255,255,0.5), transparent),
      radial-gradient(1.5px 1.5px at 82% 22%, rgba(255,255,255,0.8), transparent),
      radial-gradient(1px 1px at 92% 55%, rgba(255,255,255,0.4), transparent),
      radial-gradient(1px 1px at 38% 88%, rgba(255,255,255,0.5), transparent),
      radial-gradient(1.5px 1.5px at 58% 12%, rgba(255,255,255,0.6), transparent);
    animation: twinkle 6s ease-in-out infinite alternate;
  }
  @keyframes twinkle {
    0% { opacity: 0.6; }
    100% { opacity: 1; }
  }

  .card {
    position: relative;
    width: 1100px;
    height: 640px;
    border-radius: 28px;
    background: rgba(255,255,255,0.06);
    backdrop-filter: blur(30px) saturate(140%);
    -webkit-backdrop-filter: blur(30px) saturate(140%);
    border: 1px solid rgba(255,255,255,0.12);
    box-shadow: 0 30px 80px rgba(0,0,0,0.5), inset 0 1px 0 rgba(255,255,255,0.15);
    padding: 48px 56px;
    display: grid;
    grid-template-rows: auto 1fr;
    gap: 28px;
    overflow: hidden;
  }
  .card::after {
    content: '';
    position: absolute; top: 0; left: 0; right: 0; height: 1px;
    background: linear-gradient(90deg, transparent, rgba(255,255,255,0.4), transparent);
  }

  .header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
  }
  .location {
    font-size: 13px;
    letter-spacing: 4px;
    text-transform: uppercase;
    color: rgba(255,255,255,0.6);
    margin-bottom: 8px;
  }
  .place {
    font-size: 44px;
    font-weight: 200;
    letter-spacing: -0.5px;
    color: #fff;
  }
  .date-block {
    text-align: right;
  }
  .date {
    font-size: 28px;
    font-weight: 300;
    letter-spacing: 0.5px;
  }
  .weekday {
    font-size: 13px;
    letter-spacing: 3px;
    text-transform: uppercase;
    color: rgba(255,255,255,0.6);
    margin-top: 6px;
  }

  .main {
    display: grid;
    grid-template-columns: 1.1fr 1fr;
    gap: 40px;
    align-items: center;
  }

  .left {
    display: flex;
    flex-direction: column;
    gap: 24px;
  }
  .condition-row {
    display: flex;
    align-items: center;
    gap: 18px;
  }
  .icon-wrap {
    width: 84px; height: 84px;
    display: flex; align-items: center; justify-content: center;
    border-radius: 50%;
    background: rgba(255,255,255,0.08);
    border: 1px solid rgba(255,255,255,0.15);
  }
  .icon-wrap svg { width: 52px; height: 52px; }
  .condition {
    font-size: 26px;
    font-weight: 300;
    letter-spacing: 0.3px;
  }
  .condition-sub {
    font-size: 13px;
    color: rgba(255,255,255,0.55);
    margin-top: 4px;
    letter-spacing: 0.5px;
  }

  .temps {
    display: flex;
    align-items: baseline;
    gap: 30px;
  }
  .big-temp {
    font-size: 120px;
    font-weight: 100;
    line-height: 1;
    letter-spacing: -4px;
    background: linear-gradient(180deg, #fff 0%, rgba(255,255,255,0.7) 100%);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
  }
  .big-temp .deg {
    font-size: 60px;
    font-weight: 200;
    vertical-align: top;
    margin-left: 4px;
  }
  .hi-lo {
    display: flex;
    flex-direction: column;
    gap: 6px;
  }
  .hi-lo .row {
    display: flex; align-items: center; gap: 10px;
    font-size: 18px; font-weight: 300;
  }
  .hi-lo .label {
    font-size: 11px; letter-spacing: 2px; text-transform: uppercase;
    color: rgba(255,255,255,0.5);
    width: 28px;
  }
  .arrow { font-size: 14px; opacity: 0.7; }

  .right {
    height: 100%;
    display: flex;
    flex-direction: column;
    gap: 14px;
  }
  .right-title {
    font-size: 12px;
    letter-spacing: 3px;
    text-transform: uppercase;
    color: rgba(255,255,255,0.55);
    display: flex;
    justify-content: space-between;
    align-items: center;
  }
  .chart {
    flex: 1;
    position: relative;
    min-height: 0;
  }
  .chart svg { width: 100%; height: 100%; display: block; }

  .x-axis {
    display: flex;
    justify-content: space-between;
    padding: 0 4px;
    font-size: 11px;
    color: rgba(255,255,255,0.45);
    letter-spacing: 1px;
  }

  .error {
    text-align: center;
    padding: 80px 20px;
  }
  .error h2 {
    font-size: 32px;
    font-weight: 300;
    margin-bottom: 12px;
  }
  .error p {
    color: rgba(255,255,255,0.6);
    font-size: 15px;
    letter-spacing: 0.5px;
  }

  .loading {
    position: absolute; inset: 0;
    display: flex; align-items: center; justify-content: center;
    flex-direction: column; gap: 20px;
  }
  .spinner {
    width: 44px; height: 44px;
    border: 2px solid rgba(255,255,255,0.15);
    border-top-color: rgba(255,255,255,0.9);
    border-radius: 50%;
    animation: spin 0.9s linear infinite;
  }
  @keyframes spin { to { transform: rotate(360deg); } }
  .loading-text {
    font-size: 13px; letter-spacing: 4px; text-transform: uppercase;
    color: rgba(255,255,255,0.6);
  }

  .fade-in { animation: fadeIn 0.7s ease both; }
  @keyframes fadeIn { from { opacity: 0; transform: translateY(10px);} to { opacity: 1; transform: none; } }

  .meta {
    position: absolute;
    bottom: 18px; left: 0; right: 0;
    text-align: center;
    font-size: 10px; letter-spacing: 3px;
    text-transform: uppercase;
    color: rgba(255,255,255,0.3);
  }
</style>
</head>
<body>
  <div id="bg"></div>
  <div class="stars"></div>

  <div class="card" id="card">
    <div class="loading" id="loading">
      <div class="spinner"></div>
      <div class="loading-text">Reading the sky…</div>
    </div>
  </div>

  <div class="meta">Open-Meteo · UTC · Celsius</div>

<script>
  // --- Parse parameters ---
  const params = new URLSearchParams(location.search);
  const lat = parseFloat(params.get('lat')) || 52.52;
  const lon = parseFloat(params.get('lon')) || 13.405;
  const name = params.get('name') || 'Berlin';

  function todayUTC() {
    const d = new Date();
    return new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate()));
  }
  function parseDate(s) {
    if (!s) return todayUTC();
    const m = /^(\d{4})-(\d{2})-(\d{2})$/.exec(s);
    if (!m) return todayUTC();
    return new Date(Date.UTC(+m[1], +m[2]-1, +m[3]));
  }
  const dateObj = parseDate(params.get('date'));
  const yyyy = dateObj.getUTCFullYear();
  const mm = String(dateObj.getUTCMonth()+1).padStart(2,'0');
  const dd = String(dateObj.getUTCDate()).padStart(2,'0');
  const dateStr = `${yyyy}-${mm}-${dd}`;

  const todayStr = (() => {
    const t = todayUTC();
    return `${t.getUTCFullYear()}-${String(t.getUTCMonth()+1).padStart(2,'0')}-${String(t.getUTCDate()).padStart(2,'0')}`;
  })();

  const isPast = dateStr < todayStr;
  const endpoint = isPast ? '/api/om/archive' : '/api/om/forecast';

  // --- Weather code mapping ---
  const WMO = {
    0:  { label: 'Clear sky',          bg: 'linear-gradient(135deg, #1a3a5f 0%, #2d5a8f 50%, #4a7fb5 100%)', icon: 'sun' },
    1:  { label: 'Mainly clear',       bg: 'linear-gradient(135deg, #243a5f 0%, #436a9f 50%, #6a8fb5 100%)', icon: 'sun-cloud' },
    2:  { label: 'Partly cloudy',      bg: 'linear-gradient(135deg, #2a3550 0%, #475575 50%, #6a7590 100%)', icon: 'sun-cloud' },
    3:  { label: 'Overcast',           bg: 'linear-gradient(135deg, #2a2d3a 0%, #454858 50%, #606578 100%)', icon: 'cloud' },
    45: { label: 'Fog',                bg: 'linear-gradient(135deg, #3a3f4a 0%, #5a606f 50%, #7a8090 100%)', icon: 'fog' },
    48: { label: 'Depositing rime fog',bg: 'linear-gradient(135deg, #3a3f4a 0%, #5a606f 50%, #7a8090 100%)', icon: 'fog' },
    51: { label: 'Light drizzle',      bg: 'linear-gradient(135deg, #2a3550 0%, #3a5575 50%, #5a7595 100%)', icon: 'rain' },
    53: { label: 'Moderate drizzle',  bg: 'linear-gradient(135deg, #2a3550 0%, #3a5575 50%, #5a7595 100%)', icon: 'rain' },
    55: { label: 'Dense drizzle',      bg: 'linear-gradient(135deg, #2a3550 0%, #3a5575 50%, #5a7595 100%)', icon: 'rain' },
    61: { label: 'Slight rain',        bg: 'linear-gradient(135deg, #1f2a45 0%, #2f4570 50%, #4a6595 100%)', icon: 'rain' },
    63: { label: 'Moderate rain',      bg: 'linear-gradient(135deg, #1f2a45 0%, #2f4570 50%, #4a6595 100%)', icon: 'rain' },
    65: { label: 'Heavy rain',         bg: 'linear-gradient(135deg, #1a2438 0%, #283a58 50%, #3a5575 100%)', icon: 'rain' },
    66: { label: 'Freezing rain',      bg: 'linear-gradient(135deg, #2a4055 0%, #456075 50%, #6080a0 100%)', icon: 'rain' },
    67: { label: 'Freezing rain',      bg: 'linear-gradient(135deg, #2a4055 0%, #456075 50%, #6080a0 100%)', icon: 'rain' },
    71: { label: 'Slight snow',        bg: 'linear-gradient(135deg, #3a4a6a 0%, #5a6f8f 50%, #8090b0 100%)', icon: 'snow' },
    73: { label: 'Moderate snow',      bg: 'linear-gradient(135deg, #3a4a6a 0%, #5a6f8f 50%, #8090b0 100%)', icon: 'snow' },
    75: { label: 'Heavy snow',         bg: 'linear-gradient(135deg, #3a4a6a 0%, #5a6f8f 50%, #8090b0 100%)', icon: 'snow' },
    77: { label: 'Snow grains',        bg: 'linear-gradient(135deg, #3a4a6a 0%, #5a6f8f 50%, #8090b0 100%)', icon: 'snow' },
    80: { label: 'Slight showers',     bg: 'linear-gradient(135deg, #1f2a45 0%, #2f4570 50%, #4a6595 100%)', icon: 'rain' },
    81: { label: 'Moderate showers',   bg: 'linear-gradient(135deg, #1f2a45 0%, #2f4570 50%, #4a6595 100%)', icon: 'rain' },
    82: { label: 'Violent showers',    bg: 'linear-gradient(135deg, #1a2438 0%, #283a58 50%, #3a5575 100%)', icon: 'rain' },
    85: { label: 'Snow showers',       bg: 'linear-gradient(135deg, #3a4a6a 0%, #5a6f8f 50%, #8090b0 100%)', icon: 'snow' },
    86: { label: 'Snow showers',       bg: 'linear-gradient(135deg, #3a4a6a 0%, #5a6f8f 50%, #8090b0 100%)', icon: 'snow' },
    95: { label: 'Thunderstorm',       bg: 'linear-gradient(135deg, #1a1830 0%, #2f2848 50%, #4a3f6a 100%)', icon: 'storm' },
    96: { label: 'Storm with hail',    bg: 'linear-gradient(135deg, #1a1830 0%, #2f2848 50%, #4a3f6a 100%)', icon: 'storm' },
    99: { label: 'Storm with hail',    bg: 'linear-gradient(135deg, #1a1830 0%, #2f2848 50%, #4a3f6a 100%)', icon: 'storm' },
  };
  function codeInfo(c) { return WMO[c] || { label: '—', bg: 'linear-gradient(135deg, #2a3550 0%, #455575 100%)', icon: 'cloud' }; }

  // --- Icons ---
  function iconSVG(kind) {
    const stroke = '#fff';
    const sun = `<circle cx="32" cy="32" r="12" fill="url(#sun)"/><g stroke="${stroke}" stroke-width="2" stroke-linecap="round">
      <line x1="32" y1="6" x2="32" y2="12"/><line x1="32" y1="52" x2="32" y2="58"/>
      <line x1="6" y1="32" x2="12" y2="32"/><line x1="52" y1="32" x2="58" y2="32"/>
      <line x1="13" y1="13" x2="17" y2="17"/><line x1="47" y1="47" x2="51" y2="51"/>
      <line x1="13" y1="51" x2="17" y2="47"/><line x1="47" y1="17" x2="51" y2="13"/></g>`;
    const cloud = `<path d="M20 44 Q10 44 10 34 Q10 26 18 26 Q20 16 30 16 Q40 16 42 26 Q50 26 50 34 Q50 44 42 44 Z" fill="rgba(255,255,255,0.85)"/>`;
    const rain = `<path d="M18 36 Q10 36 10 28 Q10 20 18 20 Q20 12 28 12 Q38 12 40 20 Q48 20 48 28 Q48 36 42 36 Z" fill="rgba(255,255,255,0.85)"/>
      <g stroke="#9fd0ff" stroke-width="2.5" stroke-linecap="round">
      <line x1="20" y1="42" x2="17" y2="52"/>
      <line x1="30" y1="42" x2="27" y2="54"/>
      <line x1="40" y1="42" x2="37" y2="52"/></g>`;
    const snow = `<path d="M18 36 Q10 36 10 28 Q10 20 18 20 Q20 12 28 12 Q38 12 40 20 Q48 20 48 28 Q48 36 42 36 Z" fill="rgba(255,255,255,0.9)"/>
      <g fill="#fff">
      <circle cx="20" cy="48" r="2.5"/><circle cx="30" cy="52" r="2.5"/><circle cx="40" cy="48" r="2.5"/></g>`;
    const fog = `<g stroke="rgba(255,255,255,0.7)" stroke-width="3" stroke-linecap="round">
      <line x1="10" y1="20" x2="54" y2="20"/>
      <line x1="14" y1="30" x2="50" y2="30"/>
      <line x1="8" y1="40" x2="56" y2="40"/>
      <line x1="16" y1="50" x2="48" y2="50"/></g>`;
    const storm = `<path d="M18 32 Q10 32 10 24 Q10 16 18 16 Q20 8 28 8 Q38 8 40 16 Q48 16 48 24 Q48 32 42 32 Z" fill="rgba(255,255,255,0.8)"/>
      <path d="M30 32 L24 46 L32 46 L26 58 L36 42 L30 42 Z" fill="#ffd24a"/>`;
    const suncloud = `<circle cx="22" cy="22" r="8" fill="url(#sun)"/>
      <g stroke="#fff" stroke-width="1.6" stroke-linecap="round">
      <line x1="22" y1="8" x2="22" y2="11"/><line x1="8" y1="22" x2="11" y2="22"/>
      <line x1="11.5" y1="11.5" x2="13.5" y2="13.5"/><line x1="32.5" y1="11.5" x2="30.5" y2="13.5"/></g>
      <path d="M24 46 Q16 46 16 38 Q16 30 24 30 Q26 24 34 24 Q44 24 46 32 Q54 32 54 40 Q54 46 48 46 Z" fill="rgba(255,255,255,0.9)"/>`;

    let body = '';
    if (kind === 'sun') body = sun;
    else if (kind === 'cloud') body = cloud;
    else if (kind === 'rain') body = rain;
    else if (kind === 'snow') body = snow;
    else if (kind === 'fog') body = fog;
    else if (kind === 'storm') body = storm;
    else if (kind === 'sun-cloud') body = suncloud;
    else body = cloud;

    return `<svg viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
      <defs>
        <radialGradient id="sun" cx="50%" cy="50%" r="50%">
          <stop offset="0%" stop-color="#ffe27a"/><stop offset="100%" stop-color="#ff9d4a"/>
        </radialGradient>
      </defs>
      ${body}
    </svg>`;
  }

  // --- Date formatting ---
  const MONTHS = ['January','February','March','April','May','June','July','August','September','October','November','December'];
  const DAYS = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];

  // --- Build hourly chart ---
  function buildChart(hourlyTemps) {
    // hourlyTemps: array of 24 numbers (00:00 .. 23:00)
    const W = 500, H = 260, P = 20;
    const min = Math.min(...hourlyTemps);
    const max = Math.max(...hourlyTemps);
    const range = max - min || 1;
    const pad = range * 0.15;
    const lo = min - pad, hi = max + pad;
    const xStep = (W - P*2) / (hourlyTemps.length - 1);
    const y = t => P + (1 - (t - lo)/(hi - lo)) * (H - P*2);
    const x = i => P + i * xStep;

    const pts = hourlyTemps.map((t,i) => `${x(i).toFixed(1)},${y(t).toFixed(1)}`).join(' ');
    const areaPts = `${x(0).toFixed(1)},${(H-P).toFixed(1)} ${pts} ${x(hourlyTemps.length-1).toFixed(1)},${(H-P).toFixed(1)}`;

    // Find max & min points
    const maxIdx = hourlyTemps.indexOf(max);
    const minIdx = hourlyTemps.indexOf(min);

    let labels = '';
    hourlyTemps.forEach((t, i) => {
      if (i % 3 === 0) {
        labels += `<text x="${x(i)}" y="${y(t) - 12}" fill="rgba(255,255,255,0.55)" font-size="11" text-anchor="middle" font-family="Inter, sans-serif">${Math.round(t)}°</text>`;
      }
    });

    return `<svg viewBox="0 0 ${W} ${H}" preserveAspectRatio="none">
      <defs>
        <linearGradient id="area" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stop-color="rgba(255,210,140,0.5)"/>
          <stop offset="100%" stop-color="rgba(255,210,140,0)"/>
        </linearGradient>
        <linearGradient id="line" x1="0" y1="0" x2="1" y2="0">
          <stop offset="0%" stop-color="#7fd0ff"/>
          <stop offset="100%" stop-color="#ffd28a"/>
        </linearGradient>
      </defs>
      <polygon points="${areaPts}" fill="url(#area)"/>
      <polyline points="${pts}" fill="none" stroke="url(#line)" stroke-width="2.5" stroke-linejoin="round" stroke-linecap="round"/>
      <circle cx="${x(maxIdx)}" cy="${y(max)}" r="5" fill="#ffd28a" stroke="rgba(0,0,0,0.2)" stroke-width="1"/>
      <circle cx="${x(minIdx)}" cy="${y(min)}" r="5" fill="#7fd0ff" stroke="rgba(0,0,0,0.2)" stroke-width="1"/>
      ${labels}
    </svg>`;
  }

  function xAxisLabels() {
    const hours = ['00','06','12','18','23'];
    return hours.map(h => `<span>${h}:00</span>`).join('');
  }

  // --- Render ---
  function render(data) {
    const daily = data.daily;
    const hourly = data.hourly;
    if (!daily || !daily.time || daily.time.length === 0 || !hourly || !hourly.time) {
      renderError('No data available for this date.');
      return;
    }
    // daily might return multiple or single — find matching date index
    let dIdx = daily.time.indexOf(dateStr);
    if (dIdx < 0) dIdx = 0;
    const tMax = daily.temperature_2m_max[dIdx];
    const tMin = daily.temperature_2m_min[dIdx];
    const code = daily.weather_code[dIdx];
    const info = codeInfo(code);

    // Build hourly array for our date (24 entries)
    let temps24 = [];
    for (let h = 0; h < 24; h++) {
      const hh = String(h).padStart(2,'0');
      const ts = `${dateStr}T${hh}:00`;
      const idx = hourly.time.indexOf(ts);
      if (idx >= 0) {
        temps24.push(hourly.temperature_2m[idx]);
      } else {
        // Try ISO with Z
        const ts2 = `${dateStr}T${hh}:00Z`;
        const idx2 = hourly.time.indexOf(ts2);
        if (idx2 >= 0) temps24.push(hourly.temperature_2m[idx2]);
        else temps24.push(null);
      }
    }
    if (temps24.every(v => v === null)) {
      renderError('Hourly data unavailable for this date.');
      return;
    }
    // Interpolate nulls
    for (let i = 0; i < 24; i++) {
      if (temps24[i] === null) {
        let prev = null, next = null;
        for (let j = i-1; j >= 0 && prev === null; j--) if (temps24[j] !== null) prev = temps24[j];
        for (let j = i+1; j < 24 && next === null; j++) if (temps24[j] !== null) next = temps24[j];
        if (prev !== null && next !== null) temps24[i] = (prev+next)/2;
        else if (prev !== null) temps24[i] = prev;
        else if (next !== null) temps24[i] = next;
        else temps24[i] = tMax;
      }
    }

    // Set background
    document.getElementById('bg').style.background = info.bg;

    // Average for big display
    const avg = temps24.reduce((a,b)=>a+b,0)/24;
    const displayTemp = Math.round(avg);

    const placeDate = new Date(dateObj);
    const wd = DAYS[placeDate.getUTCDay()];
    const dateLabel = `${placeDate.getUTCDate()} ${MONTHS[placeDate.getUTCMonth()]} ${placeDate.getUTCFullYear()}`;

    let scenario = '';
    if (tMax - tMin > 10) scenario = 'Large swing day';
    else if (tMax < 0) scenario = 'Below freezing';
    else if (tMax < 10) scenario = 'Cold';
    else if (tMax < 20) scenario = 'Mild';
    else if (tMax < 28) scenario = 'Warm';
    else scenario = 'Hot';

    const html = `
      <div class="header fade-in">
        <div>
          <div class="location">Location</div>
          <div class="place">${escapeHtml(name)}</div>
          <div style="font-size:13px; color:rgba(255,255,255,0.45); margin-top:6px; letter-spacing:0.5px;">${Math.abs(lat).toFixed(2)}°${lat>=0?'N':'S'}, ${Math.abs(lon).toFixed(2)}°${lon>=0?'E':'W'}</div>
        </div>
        <div class="date-block">
          <div class="date">${dateLabel}</div>
          <div class="weekday">${wd}</div>
        </div>
      </div>

      <div class="main fade-in">
        <div class="left">
          <div class="condition-row">
            <div class="icon-wrap">${iconSVG(info.icon)}</div>
            <div>
              <div class="condition">${info.label}</div>
              <div class="condition-sub">${scenario} · ${isPast ? 'Archived' : 'Forecast'} data</div>
            </div>
          </div>
          <div class="temps">
            <div class="big-temp">${displayTemp}<span class="deg">°</span></div>
            <div class="hi-lo">
              <div class="row"><span class="label">High</span><span>${Math.round(tMax)}°</span><span class="arrow">▲</span></div>
              <div class="row"><span class="label">Low</span><span>${Math.round(tMin)}°</span><span class="arrow">▼</span></div>
              <div style="height:1px; background:rgba(255,255,255,0.12); margin:6px 0;"></div>
              <div class="row"><span class="label">Avg</span><span>${Math.round(avg)}°</span></div>
            </div>
          </div>
        </div>
        <div class="right">
          <div class="right-title">
            <span>Hourly Temperature</span>
            <span>${dateStr}</span>
          </div>
          <div class="chart">${buildChart(temps24)}</div>
          <div class="x-axis">${xAxisLabels()}</div>
        </div>
      </div>
    `;
    document.getElementById('card').innerHTML = html;
  }

  function renderError(msg) {
    document.getElementById('card').innerHTML = `
      <div class="error fade-in">
        <div style="font-size:60px; margin-bottom:10px; opacity:0.4;">⛨</div>
        <h2>Weather unavailable</h2>
        <p>${escapeHtml(msg)}</p>
        <p style="margin-top:14px; font-size:12px; letter-spacing:2px; text-transform:uppercase; color:rgba(255,255,255,0.4);">${escapeHtml(name)} · ${dateStr}</p>
      </div>
    `;
  }

  function escapeHtml(s) {
    return String(s).replace(/[&<>"']/g, c => ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));
  }

  // --- Fetch ---
  async function load() {
    const qs = new URLSearchParams({
      latitude: lat,
      longitude: lon,
      daily: 'temperature_2m_max,temperature_2m_min,weather_code',
      hourly: 'temperature_2m',
      timezone: 'UTC',
      temperature_unit: 'celsius',
      start_date: dateStr,
      end_date: dateStr
    });
    const url = `${endpoint}?${qs.toString()}`;
    try {
      const res = await fetch(url);
      if (!res.ok) throw new Error('HTTP ' + res.status);
      const data = await res.json();
      render(data);
    } catch (e) {
      renderError('Could not load weather data. ' + (e.message || ''));
    }
  }
  load();
</script>
</body>
</html>

L1 —— 廉价的确定性描述量

bytes 总计22,637html / css / js439 / 6,481 / 15,717
dom 节点14dom 深度5
css 规则52含 js
brightness93.9contrast18.5
colorfulness34.0留白41.1%

该 slot 的 telemetry

prompt tokens319completion tokens8,215
total tokens8,534wall43.2 s
costrequest id
config.json530 B
{
  "N": 2,
  "auth": {
    "credential_ref": "WCB_OPENCODE_KEY",
    "method": "oauth"
  },
  "billing": "plan",
  "config_id": "glm-5.1--opencode-go--dev",
  "effort": null,
  "family": "glm",
  "m": {
    "min": 2,
    "q": 2
  },
  "model_id": "glm-5.1",
  "protocol": "api",
  "served_model": "glm-5.1",
  "telemetry": {
    "completion_tokens": 26768,
    "cost_usd": null,
    "prompt_tokens": 1260,
    "total_tokens": 28028,
    "wall_ms": 158017
  },
  "transport": "opencode-go-gateway",
  "vendor_sanction_ref": null
}
send-log2.4 KB
{
  "N": 2,
  "batch_id": "2026-07-19--go-requeue2",
  "config_id": "glm-5.1--opencode-go--dev",
  "positions": [
    {
      "attempts": [
        {
          "attempt_index": 0,
          "backoff_ms": null,
          "charged": true,
          "ended_at": "2026-07-18T19:50:25.586916+00:00",
          "http_status": 200,
          "outcome": "valid",
          "reached_model": true,
          "reason": "ok",
          "request_id": null,
          "started_at": "2026-07-18T19:49:53.412958+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-07-18T19:51:12.341008+00:00",
          "http_status": 200,
          "outcome": "valid",
          "reached_model": true,
          "reason": "ok",
          "request_id": null,
          "started_at": "2026-07-18T19:50:29.098934+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-07-18T19:52:25.633215+00:00",
          "http_status": 200,
          "outcome": "valid",
          "reached_model": true,
          "reason": "ok",
          "request_id": null,
          "started_at": "2026-07-18T19:51:15.984052+00:00"
        }
      ],
      "block_index": 1,
      "model_reaching_attempt_index": 0,
      "slot_index": 1,
      "terminal_state": "valid",
      "variant": "P-q"
    },
    {
      "attempts": [
        {
          "attempt_index": 0,
          "backoff_ms": null,
          "charged": true,
          "ended_at": "2026-07-18T19:53:25.346035+00:00",
          "http_status": 200,
          "outcome": "valid",
          "reached_model": true,
          "reason": "ok",
          "request_id": null,
          "started_at": "2026-07-18T19:53:12.390936+00:00"
        }
      ],
      "block_index": 1,
      "model_reaching_attempt_index": 0,
      "slot_index": 1,
      "terminal_state": "valid",
      "variant": "P-min"
    }
  ],
  "retry_policy": {
    "max_unreachable_retries": 5,
    "rate_limit_backoff": {
      "max_attempts": 4,
      "max_total_ms": 60000
    }
  }
}