Download distinct_server/render.py from User1342/distinct: direct link, hf CLI and curl.
- Browser
- Download file 115 kB
-
https://huggingface.co/spaces/User1342/distinct/resolve/main/distinct_server/render.py
- Command line
-
hf download hf://spaces/User1342/distinct/distinct_server/render.py
-
curl -L -o render.py https://huggingface.co/spaces/User1342/distinct/resolve/main/distinct_server/render.py
115 kB
| """Server-rendered markup. Every HTML string in the product is built here. | |
| Two reasons this module exists. | |
| **Control.** Gradio's generated DOM is not a design system, and styling it is a | |
| fight you lose slowly. Anything static or read-only is authored here as plain | |
| HTML and handed to a ``gr.HTML``; real Gradio components are kept to the small | |
| set that genuinely needs Python event wiring — the prompt box, the model | |
| selector, submit, cancel, consent, and the conversation picker. | |
| **Safety.** The moment markup is built by string concatenation, worker-supplied | |
| text becomes an XSS vector, and the agent operator is explicitly *not* trusted | |
| (see the community-worker warning this module renders). Agent display names, | |
| hostnames, OS and architecture strings, RAM figures, model ids, tool refs and | |
| energy provider names all originate on a remote machine controlled by someone | |
| else. | |
| So there is exactly one rule here, and it is enforced by construction: | |
| Every interpolated value goes through :func:`esc`. No exceptions. | |
| The only strings that reach the output without escaping are literals written in | |
| this file. Helpers that accept caller-supplied HTML are named ``*_raw`` and | |
| there are only two of them, both fed by :mod:`distinct_server.ui` from text it | |
| generated itself. ``tests/test_presentation.py`` asserts that hostile input at | |
| every injection point comes out inert. | |
| """ | |
| from __future__ import annotations | |
| import re | |
| import secrets as _secrets | |
| from collections.abc import Iterable, Mapping, Sequence | |
| from dataclasses import dataclass | |
| from html import escape | |
| from pathlib import Path | |
| from typing import Optional | |
| from . import comparators as _comparators | |
| __all__ = [ | |
| "activity", | |
| "assessment_legend", | |
| "assessment_section", | |
| "chip", | |
| "comparator", | |
| "credit", | |
| "duration", | |
| "empty_state", | |
| "energy_headline", | |
| "energy_panel", | |
| "esc", | |
| "figure_token", | |
| "footer", | |
| "format_joules", | |
| "header", | |
| "join_this_server", | |
| "library_help", | |
| "library_summary", | |
| "live_steps", | |
| "model_evidence_card", | |
| "no_tools_note", | |
| "notice", | |
| "run_receipts", | |
| "section_heading", | |
| "spinner", | |
| "splash_copy", | |
| "splash_figure", | |
| "splash_meta", | |
| "usage_summary", | |
| "worker_cards", | |
| "worker_energy_line", | |
| ] | |
| def esc(value: object) -> str: | |
| """Escape any value for inclusion in HTML text or a quoted attribute. | |
| ``quote=True`` matters: several call sites interpolate into attributes, and | |
| a helper that only escapes ``<>&`` would leave those open. | |
| """ | |
| return escape("" if value is None else str(value), quote=True) | |
| # -------------------------------------------------------------------------- | |
| # Header | |
| # -------------------------------------------------------------------------- | |
| def header(identity: str, *, tagline: str, sign_in: str = "") -> str: | |
| """One row: wordmark left, identity right. | |
| ``sign_in`` makes the identity a link to the sign-in route rather than a | |
| label. It is passed only when nobody is signed in, so the control and the | |
| state cannot disagree: a permanent "Sign in" link beside "Signed in as | |
| Bob" is two things on screen contradicting each other, and this interface | |
| had exactly that for one afternoon. | |
| """ | |
| if sign_in: | |
| right = f'<a class="c-identity c-identity--link" href="{esc(sign_in)}">{esc(identity)}</a>' | |
| else: | |
| right = f'<span class="c-identity">{esc(identity)}</span>' | |
| return ( | |
| '<header class="c-header">' | |
| '<div class="c-header__brand">' | |
| '<span class="c-wordmark">distinct<span class="c-wordmark__dot">.</span></span>' | |
| f'<span class="c-tagline">{esc(tagline)}</span>' | |
| "</div>" | |
| + right | |
| + "</header>" | |
| ) | |
| # -------------------------------------------------------------------------- | |
| # Notice | |
| # -------------------------------------------------------------------------- | |
| def notice() -> str: | |
| """The community-worker warning, compact with the detail one click away.""" | |
| return ( | |
| '<details class="c-notice">' | |
| '<summary class="c-notice__summary">' | |
| '<span class="c-notice__mark" aria-hidden="true">!</span>' | |
| '<span><strong>The operator of the agent you choose can read your prompts and ' | |
| "its answers.</strong> Output, model identity and energy telemetry are " | |
| "self-reported and unverified.</span>" | |
| '<span class="c-notice__toggle">What is kept</span>' | |
| "</summary>" | |
| '<p class="c-notice__body">Do not send secrets or sensitive personal data. ' | |
| "This server erases your prompt when the run finishes, and the answer once your " | |
| "browser has it. The transcript then lives only in this tab and is lost on " | |
| "reload. The worker erases its copy when the job leaves its queue. Neither side " | |
| "keeps prompt text for a finished run.</p>" | |
| "</details>" | |
| ) | |
| # -------------------------------------------------------------------------- | |
| # Small pieces | |
| # -------------------------------------------------------------------------- | |
| def section_heading(text: str, *, note: str = "") -> str: | |
| suffix = f'<span class="c-eyebrow__note">{esc(note)}</span>' if note else "" | |
| return f'<p class="c-eyebrow">{esc(text)}{suffix}</p>' | |
| def chip(text: str, *, tone: str = "neutral", glyph: str = "") -> str: | |
| """One chip style, one height, one radius. | |
| ``tone`` only ever picks a background. The status word is always inside the | |
| chip, so no meaning is carried by colour alone. | |
| """ | |
| mark = f'<span class="c-chip__glyph" aria-hidden="true">{esc(glyph)}</span>' if glyph else "" | |
| return f'<span class="c-chip c-chip--{esc(tone)}">{mark}{esc(text)}</span>' | |
| def empty_state(*, glyph: str, title: str, body: str, compact: bool = False) -> str: | |
| modifier = " c-empty--compact" if compact else "" | |
| return ( | |
| f'<div class="c-empty{modifier}">' | |
| f'<span class="c-empty__glyph" aria-hidden="true">{esc(glyph)}</span>' | |
| f'<p class="c-empty__title">{esc(title)}</p>' | |
| f'<p class="c-empty__body">{esc(body)}</p>' | |
| "</div>" | |
| ) | |
| def no_tools_note(notice_text: str) -> str: | |
| return ( | |
| '<p class="c-note">' | |
| + chip("no tools installed", tone="outline") | |
| + f'<span class="c-note__text">{esc(notice_text)}</span></p>' | |
| ) | |
| _PLATFORM_LABELS = {"win": "Windows", "nix": "macOS or Linux"} | |
| def _command_block(command: str, *, platform: str = "") -> str: | |
| """One command, drawn as its own block with its own copy button. | |
| Two commands used to share a ``<pre>``. A block holding two lines can only | |
| be copied whole, and on a phone it cannot even be dragged apart, so | |
| somebody following the panel had to retype half of it. A block now holds | |
| one command and nothing else, and the button beside it copies that one. | |
| The button carries no copy of the text. The handler in | |
| :data:`distinct_server.presentation.HEAD` reads it out of the ``<pre>`` at | |
| click time, which makes the clipboard equal to the screen by construction. | |
| A second copy of the command in a ``data-`` attribute would be a second | |
| string to escape and a second string to get wrong. | |
| ``platform`` labels a command that differs between Windows and everything | |
| else. The label sits on the block, not only on the switch above it, | |
| because the switch starts on neither platform: nobody is shown a command | |
| for a machine that may not be theirs without the block saying whose it is. | |
| """ | |
| label = _PLATFORM_LABELS.get(platform, "") | |
| tag = f'<span class="c-cmd__for">{esc(label)}</span>' if label else "" | |
| variant = f" c-cmd--{esc(platform)}" if label else "" | |
| whose = f'<span class="c-visually-hidden"> the {esc(label)} command</span>' if label else "" | |
| return ( | |
| f'<div class="c-cmd{variant}">' | |
| f'<div class="c-cmd__bar">{tag}' | |
| '<button type="button" class="c-cmd__copy">' | |
| f'<span class="c-cmd__word">Copy</span>{whose}</button></div>' | |
| f'<pre class="c-join__cmd">{esc(command)}</pre>' | |
| "</div>" | |
| ) | |
| # WHICH MACHINE, ASKED BEFORE THE COMMANDS RATHER THAN AFTER THEM. | |
| # | |
| # Neither radio is checked, so both platforms' commands are on screen until | |
| # somebody picks one. That is deliberate: a default would be right for one | |
| # half of the readers and silently wrong for the other, and being silently | |
| # wrong is the whole failure this panel is being rebuilt to stop. Picking | |
| # hides the other platform; picking nothing costs a few extra lines, each of | |
| # them labelled. | |
| # | |
| # The switch is two radios and CSS, with no script behind it, because this | |
| # function returns a plain HTML string that has to work wherever it is | |
| # rendered. The copy buttons need JavaScript and cannot avoid it; the choice | |
| # of what a person reads should not. | |
| _OS_SWITCH = ( | |
| '<input class="c-os__radio" type="radio" name="distinct-os" id="distinct-os-win">' | |
| '<input class="c-os__radio" type="radio" name="distinct-os" id="distinct-os-nix">' | |
| '<div class="c-os">' | |
| '<span class="c-os__ask">Which machine are you on?</span>' | |
| '<label class="c-os__tab" for="distinct-os-win">Windows</label>' | |
| '<label class="c-os__tab" for="distinct-os-nix">macOS or Linux</label>' | |
| "</div>" | |
| ) | |
| def join_this_server( | |
| *, addresses, code: str, qr: str = "", tools: str = "local", source: str = "" | |
| ) -> str: | |
| """The whole path from nothing to a running worker, in the order it happens. | |
| This panel used to be an address, a code and one command, sitting beside a | |
| "Download agent" button that pointed at release artifacts nobody builds. | |
| The button could only ever fail, and the command it accompanied assumed | |
| the code was already on the machine. What a volunteer actually needs is | |
| the three steps in between, so those are what this says: get the code, | |
| install it, run it. | |
| THE COMMANDS ARE PER-PLATFORM BECAUSE THE FOOTNOTE VERSION DID NOT WORK. | |
| The install step used to read ``python -m pip install -e .`` with | |
| a line underneath saying to use something else on Windows. People paste | |
| the command; they do not paste the footnote. On Windows the bare | |
| ``python`` is routinely an old interpreter that arrived with some other | |
| program, and the first volunteer to follow this panel got two failures in | |
| a row from it: pip 20.2.3 refusing an editable install of a project with | |
| no ``setup.py``, then the worker refusing to start on Python 3.9. Both | |
| were the panel's fault, not theirs. So the command a person copies is now | |
| the correct one for the machine they say they are on, and the caveat that | |
| used to live underneath is spelled ``py -3`` inside the command itself. | |
| ``py -3`` and not ``py -3.12``: the launcher picks the newest installed | |
| Python 3, and naming a minor version asserts something about a machine | |
| this server has never seen. | |
| ``source`` is where the code lives — this Space's own repository when the | |
| server knows it. Absent, the step says so plainly instead of guessing at | |
| a URL, because sending somebody to a repository that may not exist is | |
| worse than admitting the server cannot name one. | |
| ``addresses`` empty is a real state and is reported as one: a server bound | |
| to loopback is reachable by this machine and nothing else, and an agent on | |
| a phone will never see it. Inventing an address there would send somebody | |
| to debug their network over a decision this server made at start-up. | |
| """ | |
| if not addresses: | |
| return ( | |
| '<div class="c-join">' | |
| '<p class="c-join__lead">This server is bound to this machine only, so ' | |
| "nothing else on your network can reach it. Restart it with " | |
| "<code>DISTINCT_BIND_HOST=0.0.0.0</code> to let an agent connect, and read " | |
| "what that exposes.</p></div>" | |
| ) | |
| first = str(addresses[0]) | |
| others = "".join( | |
| f'<li class="c-join__alt">{esc(url)}</li>' for url in list(addresses)[1:] | |
| ) | |
| alternates = ( | |
| f'<p class="c-join__note">Also reachable at {", ".join(esc(str(u)) for u in list(addresses)[1:])}.</p>' | |
| if others | |
| else "" | |
| ) | |
| # STEP ONE: the code. A git clone, because a Space is a git repository and | |
| # a clone is the one form that also updates later with `git pull`. Same | |
| # command everywhere, so it carries no platform label. | |
| if source: | |
| get_it = ( | |
| _command_block(f"git clone {source} distinct") | |
| + '<p class="c-join__note">Or use "Download repository" on the Files tab ' | |
| "and unzip it.</p>" | |
| ) | |
| else: | |
| get_it = ( | |
| '<p class="c-join__note">This server does not know its own repository ' | |
| "address. Ask whoever runs it.</p>" | |
| ) | |
| # STEP TWO: the install. `-e` so the worker runs from the folder that was | |
| # cloned, which is also the folder `git pull` updates. | |
| # | |
| # THE PIP UPGRADE IS A STEP, NOT ADVICE. `py -3` fixes the interpreter and | |
| # not the pip inside it: Python 3.10.0 shipped pip 21.2, PEP 660 editable | |
| # installs landed in pip 21.3, and an old pip meeting a project with no | |
| # `setup.py` stops with a message about setup.py that reads as though the | |
| # repository is broken. One line ahead of the install turns that into a | |
| # non-event, so it is a line people can copy rather than a warning they | |
| # get to read after it has already failed. | |
| install = ( | |
| _command_block("cd distinct") | |
| + _command_block("py -3 -m pip install --upgrade pip", platform="win") | |
| + _command_block("python3 -m pip install --upgrade pip", platform="nix") | |
| + _command_block('py -3 -m pip install -e .', platform="win") | |
| + _command_block('python3 -m pip install -e .', platform="nix") | |
| + '<p class="c-join__note">Needs Python 3.10 or newer. On Windows use ' | |
| "<code>py -3</code>, not <code>python</code>: the bare command is often an " | |
| "older version left by another program. Run the pip line even if pip looks " | |
| "current, because pip below 21.3 cannot do this install and fails with a " | |
| "confusing message about <code>setup.py</code>.</p>" | |
| ) | |
| # STEP THREE IS NOT "GO AND FETCH A DEPENDENCY". | |
| # | |
| # It was, briefly, and that was a bad answer to a fair complaint. The panel | |
| # first said nothing about llama.cpp at all, so a volunteer got through | |
| # every step and then met "this worker has no llama.cpp to run a model | |
| # with" -- a requirement the page had never named. The fix for that was a | |
| # step telling them to go to another project's releases page, pick the | |
| # right build out of a dozen, unzip it and edit their PATH, and the | |
| # reaction to that was the right one: *why do I have to provide this, it | |
| # should be baked into the repo*. | |
| # | |
| # It cannot be in the repository -- a llama.cpp release is around a hundred | |
| # megabytes per platform per accelerator, and a Space clone would carry all | |
| # of them -- but "not in the repository" was never the same thing as "your | |
| # problem". The worker now fetches the pinned build itself and verifies it | |
| # against a recorded SHA-256 before installing it, exactly as it already | |
| # did for model weights. See distinct_agent/runtime.py. | |
| # | |
| # So this step is no longer an instruction. It is a description of what the | |
| # command in the next step will do, which is here because a worker that | |
| # quietly downloads twenty megabytes should say so first. | |
| runner = ( | |
| '<p class="c-join__note">Nothing to install by hand. Models run on ' | |
| "<strong>llama.cpp</strong>, and the worker fetches it on first start " | |
| "(about 20 MB), checking it against a recorded SHA-256. If the bytes do " | |
| "not match, nothing is installed.</p>" | |
| '<p class="c-join__note">Already have a build, or want CUDA or Metal? ' | |
| "Pass <code>--llama-server /path/to/llama-server</code>. " | |
| "<code>--no-fetch-runtime</code> downloads nothing. " | |
| "<code>--demo-runner</code> runs with no model at all: the worker still " | |
| "joins and still runs every tool and skill.</p>" | |
| ) | |
| # STEP FOUR: the run, with this server's address and this browser's own | |
| # library defaults already in it. | |
| # NOTHING IS COPIED OUT OF THIS PAGE ANY MORE. | |
| # | |
| # This used to show a server-minted pairing code and a command with a | |
| # `--pair YOUR-CODE` placeholder in it, and ask the volunteer to carry the | |
| # one into the other. What people did instead -- reasonably, reading a | |
| # placeholder as a thing to fill in however they liked -- was invent a | |
| # value, and find out one program later that "your code wasn't valid", | |
| # which reads as the server rejecting them rather than as a copy that never | |
| # happened. Signed out, there was not even a code on the page to copy. | |
| # | |
| # The code now travels the other way: the worker invents one, prints it, | |
| # and waits, and it is typed into the box on this page. There is nothing | |
| # here to transcribe, so there is nothing to transcribe wrongly, and the | |
| # command is complete for everybody whether they are signed in or not. | |
| code_note = ( | |
| '<p class="c-join__note">Nothing to fill in. Run it as it is.</p>' | |
| ) | |
| # One line on purpose. The previous form used backslash continuations, | |
| # which are bash syntax: pasted into PowerShell they became stray | |
| # arguments and the command half-ran. A single line pastes correctly | |
| # into every shell anybody actually uses. | |
| arguments = ( | |
| f"-m distinct_agent --server {first} " | |
| f"--models olmoe-1b-7b-0924-instruct --tools {tools or 'local'}" | |
| ) | |
| run_it = _command_block(f"py -3 {arguments}", platform="win") + _command_block( | |
| f"python3 {arguments}", platform="nix" | |
| ) | |
| picture = f'<div class="c-join__qr">{qr}</div>' if qr else "" | |
| return ( | |
| '<div class="c-join">' | |
| f"{_OS_SWITCH}" | |
| '<ol class="c-steps-num">' | |
| '<li class="c-step-num"><span class="c-step-num__n">1</span>' | |
| '<div class="c-step-num__body"><p class="c-step-num__head">Get the code</p>' | |
| f"{get_it}</div></li>" | |
| '<li class="c-step-num"><span class="c-step-num__n">2</span>' | |
| '<div class="c-step-num__body"><p class="c-step-num__head">Install it</p>' | |
| f"{install}</div></li>" | |
| '<li class="c-step-num"><span class="c-step-num__n">3</span>' | |
| '<div class="c-step-num__body">' | |
| '<p class="c-step-num__head">Running models</p>' | |
| f"{runner}</div></li>" | |
| '<li class="c-step-num"><span class="c-step-num__n">4</span>' | |
| '<div class="c-step-num__body"><p class="c-step-num__head">Run it and claim it</p>' | |
| f'<code class="c-join__address">{esc(first)}</code>{alternates}{code_note}' | |
| f"{run_it}" | |
| '<p class="c-join__note">The worker prints a code and waits. Sign in, put ' | |
| "that code into <em>Add a worker</em> on this page, and the machine is yours. " | |
| "Until then nobody can see it and nothing can be sent to it.</p>" | |
| f"{picture}</div></li>" | |
| # THE LAST STEP EXISTS BECAUSE PEOPLE ASK FOR IT AFTER READING THE ONE | |
| # BEFORE IT. | |
| # | |
| # Sharing was one clause at the end of the previous step, and the | |
| # question "how do several people use my machine?" kept coming back, | |
| # which is what a clause at the end of a step gets you. It is the | |
| # point of running a worker at all, so it is a step of its own, and | |
| # it says the non-obvious part out loud: the code is not spent by | |
| # the first person who enters it. | |
| '<li class="c-step-num"><span class="c-step-num__n">5</span>' | |
| '<div class="c-step-num__body">' | |
| '<p class="c-step-num__head">Share it</p>' | |
| '<p class="c-join__note">Once claimed, the worker prints an <strong>access ' | |
| "code</strong>. Send it to anyone who should use your machine. They sign in at " | |
| f"{esc(first)} and paste it into <em>Add a worker</em>.</p>" | |
| '<p class="c-join__note">The same code works for everyone you give it to and is ' | |
| "not used up. Nobody else can see your worker, but anyone holding the code can " | |
| "send it requests, so treat it like a key.</p>" | |
| "</div></li>" | |
| "</ol>" | |
| "</div>" | |
| ) | |
| def library_summary(*, shown: int, matched: int, total: int, chosen: int) -> str: | |
| """What the library page is currently showing, and what has been kept. | |
| Written out because a filtered list with no count is a list you cannot | |
| trust: a search that matched nothing and a search that matched everything | |
| look identical if all you can see is the rows. The kept count is separate | |
| from the shown count on purpose, since the two diverge the moment anyone | |
| searches, and the number people will want to check is how many they have | |
| chosen overall. | |
| """ | |
| if not total: | |
| return ( | |
| '<p class="c-note"><span class="c-note__text">' | |
| "This server knows of no library members.</span></p>" | |
| ) | |
| if matched == 0: | |
| body = f"No member matches that. {total} in the library." | |
| elif shown < matched: | |
| body = f"Showing {shown} of {matched} matches, out of {total} in the library." | |
| elif matched < total: | |
| body = f"{matched} of {total} members match." | |
| else: | |
| body = f"All {total} members." | |
| kept = ( | |
| "Tap a card to make it a default. It saves at once." | |
| if not chosen | |
| else f"<strong>{chosen}</strong> saved as {'a default' if chosen == 1 else 'defaults'}." | |
| ) | |
| return ( | |
| '<div class="c-libsave"><span class="c-libsave__count">' | |
| f"{esc(body)} {kept}</span></div>" | |
| ) | |
| def library_help(rows: Sequence[Mapping[str, object]]) -> str: | |
| """One line per offered library member: what it is called, what it does. | |
| A reference like ``create_pdf@1`` names a member and describes nothing. | |
| The picker shows the readable name; this shows the sentence, so choosing | |
| is not a guess. The exact ref is here too, in a code span, because it is | |
| what the allowlist and the run log will show and a person should be able | |
| to connect the two. | |
| """ | |
| if not rows: | |
| return "" | |
| items = "".join( | |
| '<li class="c-libhelp__item">' | |
| f'<span class="c-libhelp__name">{esc(row.get("name", ""))}</span>' | |
| f'<span class="c-libhelp__kind">{esc(row.get("kind", ""))}</span>' | |
| f'<code class="c-libhelp__ref">{esc(row.get("ref", ""))}</code>' | |
| f'<span class="c-libhelp__what">{esc(row.get("description", ""))}</span>' | |
| "</li>" | |
| for row in rows | |
| ) | |
| return ( | |
| '<details class="c-libhelp">' | |
| '<summary class="c-libhelp__toggle">What these do</summary>' | |
| f'<ul class="c-libhelp__list">{items}</ul>' | |
| '<p class="c-libhelp__note">Selection resets after every run. A skill ' | |
| "returns its file to this session, where you can download it.</p>" | |
| "</details>" | |
| ) | |
| # -------------------------------------------------------------------------- | |
| # Live activity: what the run is doing, and why it is not doing it yet | |
| # -------------------------------------------------------------------------- | |
| def spinner(*, label: str = "") -> str: | |
| """A CSS spinner with an accessible label. | |
| ``aria-hidden`` on the visual mark and a visually-hidden label beside it, | |
| so a screen reader hears "working" once rather than reading a decoration. | |
| """ | |
| hidden = f'<span class="c-visually-hidden">{esc(label)}</span>' if label else "" | |
| return f'<span class="c-spin" aria-hidden="true"></span>{hidden}' | |
| def _step_mark(kind: str, ok: object) -> tuple[str, str]: | |
| """Geometric mark and tone for one live step. No emojis, house style.""" | |
| if kind == "tool-call": | |
| return "▸", "work" | |
| if kind == "tool-result": | |
| return ("●", "ok") if ok else ("■", "warn") | |
| if kind == "model": | |
| return "◇", "neutral" | |
| return "·", "neutral" | |
| def live_steps(steps: Sequence[Mapping[str, object]]) -> str: | |
| """The run's own trace, as it happens. | |
| **Every field is worker-supplied.** Tool names, argument previews and | |
| result previews come from a machine someone else operates, so all of them | |
| are escaped, and the structure is fixed here rather than taken from the | |
| wire. A worker can decide what its run says; it cannot decide what the | |
| markup is. | |
| """ | |
| if not steps: | |
| return "" | |
| items: list[str] = [] | |
| for step in steps: | |
| kind = str(step.get("kind") or "phase") | |
| mark, tone = _step_mark(kind, step.get("ok", True)) | |
| tool = str(step.get("tool") or "") | |
| text = str(step.get("text") or "") | |
| elapsed = step.get("elapsed_ms") | |
| timing = ( | |
| f'<span class="c-step__timing">{esc(elapsed)} ms</span>' | |
| if isinstance(elapsed, int) and not isinstance(elapsed, bool) | |
| else "" | |
| ) | |
| name = f'<code class="c-step__tool">{esc(tool)}</code>' if tool else "" | |
| body = f'<span class="c-step__text">{esc(text)}</span>' if text else "" | |
| items.append( | |
| f'<li class="c-step c-step--{esc(tone)}">' | |
| f'<span class="c-step__mark" aria-hidden="true">{esc(mark)}</span>' | |
| f'<span class="c-step__body">{name}{body}</span>' | |
| f"{timing}</li>" | |
| ) | |
| return f'<ol class="c-steps">{"".join(items)}</ol>' | |
| def activity( | |
| *, | |
| headline: str, | |
| detail: str = "", | |
| steps: Sequence[Mapping[str, object]] = (), | |
| elapsed_seconds: float | None = None, | |
| estimate_seconds: float | None = None, | |
| estimate_note: str = "", | |
| working: bool = True, | |
| tone: str = "work", | |
| ) -> str: | |
| """The in-flight run panel: what is happening, and how long it may take. | |
| ``headline`` is copy this server wrote, chosen from a closed phase | |
| vocabulary. ``detail`` may be worker-supplied and is escaped. The estimate | |
| is rendered only when one exists, and it always says what it is based on: | |
| an estimate with no stated provenance is a promise, and this project does | |
| not make promises about someone else's machine. | |
| """ | |
| mark = spinner(label="Working") if working else '<span class="c-activity__dot" aria-hidden="true">●</span>' | |
| detail_html = f'<p class="c-activity__detail">{esc(detail)}</p>' if detail else "" | |
| bar = "" | |
| timing = "" | |
| if elapsed_seconds is not None: | |
| parts = [f"{duration(elapsed_seconds)} elapsed"] | |
| if estimate_seconds is not None and estimate_seconds > 0: | |
| parts.append(f"about {duration(estimate_seconds)} expected") | |
| fraction = max(0.0, min(1.0, elapsed_seconds / estimate_seconds)) | |
| # aria-valuenow on a real progressbar role: the bar is information, | |
| # not decoration, so it is exposed rather than hidden. | |
| bar = ( | |
| '<div class="c-activity__bar" role="progressbar" aria-valuemin="0" ' | |
| f'aria-valuemax="100" aria-valuenow="{int(fraction * 100)}">' | |
| f'<span class="c-activity__fill" style="width:{fraction * 100:.1f}%"></span>' | |
| "</div>" | |
| ) | |
| timing = f'<p class="c-activity__timing">{esc(" · ".join(parts))}</p>' | |
| note = ( | |
| f'<p class="c-activity__note">{esc(estimate_note)}</p>' if estimate_note else "" | |
| ) | |
| return ( | |
| f'<section class="c-activity c-activity--{esc(tone)}" aria-live="polite">' | |
| '<p class="c-activity__head">' | |
| f"{mark}" | |
| f'<span class="c-activity__headline">{esc(headline)}</span>' | |
| "</p>" | |
| f"{detail_html}{bar}{timing}{note}" | |
| f"{live_steps(steps)}" | |
| "</section>" | |
| ) | |
| def duration(seconds: float) -> str: | |
| """Human duration. Seconds below a minute, minutes and seconds above.""" | |
| value = max(0, int(round(seconds))) | |
| if value < 60: | |
| return f"{value}s" | |
| minutes, remainder = divmod(value, 60) | |
| if minutes < 60: | |
| return f"{minutes}m {remainder:02d}s" | |
| hours, minutes = divmod(minutes, 60) | |
| return f"{hours}h {minutes:02d}m" | |
| # -------------------------------------------------------------------------- | |
| # Worker cards — the main untrusted-input surface | |
| # -------------------------------------------------------------------------- | |
| _STATUS_TONE: Mapping[str, tuple[str, str]] = { | |
| "free": ("ok", "●"), | |
| "busy": ("work", "◐"), | |
| "overloaded": ("warn", "■"), | |
| "draining": ("warn", "◑"), | |
| "offline": ("off", "○"), | |
| # Connected, polling, and useless: it approved nothing, so it advertises | |
| # nothing and matches no model. It has to be visible, because from the | |
| # user's side the symptom is "no compatible worker" while a worker is | |
| # plainly running, which reads as the server being broken. | |
| "unapproved": ("warn", "◌"), | |
| } | |
| #: Extra sentence shown under a card whose status needs one. Keyed by status | |
| #: so a card can never acquire an explanation that does not match its state. | |
| _STATUS_NOTE: Mapping[str, str] = { | |
| "unapproved": ( | |
| "This worker is connected but approved no models, so it can accept no " | |
| "work. Its operator restarts it and approves a set, or passes --approve." | |
| ), | |
| } | |
| def worker_energy_line( | |
| *, | |
| joules: float | None, | |
| runs: int, | |
| measured_runs: int, | |
| uptime_seconds: float, | |
| ) -> str: | |
| """What this machine has cost, and what it costs per answer. | |
| Two numbers, because they answer two different questions a person actually | |
| has when picking a worker: what will my run cost here, and how much has | |
| this machine spent altogether. Both carry a comparator, and both are | |
| self-reported by a machine nobody here can audit, which the card says. | |
| The average is over *measured* runs only. Dividing a partial total by the | |
| full run count would quietly understate the per-run figure by exactly the | |
| proportion that was never measured. | |
| """ | |
| if joules is None or measured_runs <= 0: | |
| return ( | |
| '<p class="c-worker__energy c-worker__energy--absent">' | |
| "No electricity measurement from this worker. Not zero: it has no " | |
| "usable meter, or none of its runs returned one." | |
| "</p>" | |
| ) | |
| average = joules / measured_runs | |
| floor = "" if measured_runs == runs else f" (a floor: {measured_runs} of {runs} runs measured)" | |
| return ( | |
| '<p class="c-worker__energy">' | |
| f'<span class="c-worker__energy-figure">{esc(format_joules(average))} per run</span>' | |
| f'<span class="c-worker__energy-means">{esc(comparator(average))}</span>' | |
| f'<span class="c-worker__energy-total">' | |
| f"{esc(format_joules(joules))} in total since it started " | |
| f"{esc(duration(uptime_seconds))} ago, {esc(comparator(joules))}" | |
| f"{esc(floor)}</span>" | |
| '<span class="c-worker__energy-note">Self-reported by the worker.</span>' | |
| "</p>" | |
| ) | |
| def worker_cards(rows: Sequence[Sequence[object]], *, narrowed_by: str = "") -> str: | |
| """Render agent rows as calm metadata. | |
| **Every field below is worker-controlled** and therefore escaped. The row | |
| shape is the one ``DistinctUI._agent_components`` already produces, so the | |
| data contract is unchanged. | |
| """ | |
| if not rows: | |
| return '<div class="c-noworker-hook">' + empty_state( | |
| glyph="○", | |
| title="No compatible worker", | |
| # Which of the choices above emptied the list. Without this the | |
| # panel said the same thing whether no worker existed at all or | |
| # whether one was sitting right there offering the other agent | |
| # mode, and the user had no way to tell those apart or to know | |
| # that changing one control would fix it. | |
| body=( | |
| ( | |
| f"A worker is available, but none of them runs the {narrowed_by} " | |
| "mode. Change the mode above, or start a worker that offers " | |
| "it." | |
| ) | |
| if narrowed_by | |
| else ( | |
| "Nothing can run until a community agent pairs with this server " | |
| "and advertises this model. Open “Run a community agent” to " | |
| "start one." | |
| ) | |
| ), | |
| compact=True, | |
| ) + "</div>" | |
| cards: list[str] = [] | |
| for row in rows: | |
| values = [str(item) for item in row[:8]] | |
| values += [""] * (8 - len(values)) | |
| name, status, os_arch, ram, queue, wait, energy, tools = values[:8] | |
| display_name, _, agent_id = name.partition(" · ") | |
| tone, glyph = _STATUS_TONE.get(status, ("neutral", "○")) | |
| meta = [chip(status, tone=tone, glyph=glyph)] | |
| if queue: | |
| meta.append(chip(f"{queue} queued")) | |
| if wait: | |
| meta.append(chip(f"~{wait} wait")) | |
| if os_arch: | |
| meta.append(chip(os_arch)) | |
| if ram: | |
| meta.append(chip(ram)) | |
| # "unavailable" is a real answer and must not read as a blank or a zero. | |
| if energy and energy.lower() not in {"unavailable", "none", ""}: | |
| meta.append(chip("energy metered")) | |
| else: | |
| meta.append(chip("energy not measured", tone="outline")) | |
| meta.append(chip(tools if tools and tools != "none" else "no tools", tone="outline")) | |
| # Position 8 onwards is the energy block, absent on older row shapes. | |
| energy_html = "" | |
| if len(row) > 8 and isinstance(row[8], Mapping): | |
| energy_html = worker_energy_line( | |
| joules=row[8].get("joules"), | |
| runs=int(row[8].get("runs") or 0), | |
| measured_runs=int(row[8].get("measured_runs") or 0), | |
| uptime_seconds=float(row[8].get("uptime_seconds") or 0.0), | |
| ) | |
| offline = " c-worker--offline" if status == "offline" else "" | |
| note = _STATUS_NOTE.get(status, "") | |
| note_html = f'<p class="c-worker__note">{esc(note)}</p>' if note else "" | |
| cards.append( | |
| f'<article class="c-worker{offline}">' | |
| f'<p class="c-worker__name">{esc(display_name)}' | |
| f'<span class="c-worker__id">{esc(agent_id)}</span></p>' | |
| f'<div class="c-chips">{"".join(meta)}</div>' | |
| f"{energy_html}{note_html}" | |
| "</article>" | |
| ) | |
| return f'<div class="c-workers">{"".join(cards)}</div>' | |
| # -------------------------------------------------------------------------- | |
| # Energy — the honesty-critical surface | |
| # -------------------------------------------------------------------------- | |
| #: The visual half of "a missing measurement is never a zero". Defined once so | |
| #: the two energy renderers cannot drift apart, and so the glyph appears in | |
| #: exactly one place in this file. | |
| ABSENCE_MARK = '<span class="c-energy__dash" aria-hidden="true">\u2013</span>' | |
| #: Everyday appliances, with the power rating each figure assumes stated on | |
| #: its face. Ordered small to large; the first whose duration lands in a | |
| #: readable range wins. | |
| #: | |
| #: WHY THIS IS ALLOWED WHEN CO2e IS NOT. The rubric forbids converting | |
| #: use-phase energy into carbon, water, land or materials, because every one of | |
| #: those needs a factor the assessor chose, and the choice would be invisible | |
| #: in the result. This is not that. It is the same joules divided by a stated | |
| #: wattage, so it is arithmetic the reader can check and reverse, and the | |
| #: wattage is always printed beside it. "12 seconds of a 10 W bulb" tells you | |
| #: nothing about the world that "120 J" did not; it just tells it in a unit | |
| #: people have a body for. | |
| #: Everyday things that draw power, with the rating each comparison assumes. | |
| #: | |
| #: **Why there are so many.** One comparator repeated on every figure stops | |
| #: being read after the third time: it becomes a fixed suffix on the number, | |
| #: which is the opposite of what it is for. A wide table means the appliance | |
| #: changes from figure to figure, so the sentence has to be read again, and | |
| #: reading it again is the entire mechanism by which a number in joules turns | |
| #: into something a person has a feel for. | |
| #: | |
| #: **Why every entry carries its wattage.** This is what separates a | |
| #: comparison from a conversion. "23 seconds of a 60 W laptop charger" hands | |
| #: the reader the divisor and they can check it or ignore it; "0.03 kg of | |
| #: CO2e" hides a factor they did not choose and cannot see. The rubric forbids | |
| #: the second kind, and the wattage in every name is how this table stays on | |
| #: the right side of that line. | |
| #: | |
| #: Figures are nominal ratings for the everyday version of each thing, which | |
| #: is what a reader is picturing. Anything genuinely variable is described at | |
| #: the draw it is being compared against, so a heat pump appears at its | |
| #: running draw rather than at a seasonal average nobody would recognise. | |
| COMPARATORS: tuple[tuple[str, float], ...] = ( | |
| ("a 1 W smoke alarm", 1.0), | |
| ("a 2 W phone on standby", 2.0), | |
| ("a 3 W fairy-light string", 3.0), | |
| ("a 4 W bedside clock", 4.0), | |
| ("a 5 W phone charger", 5.0), | |
| ("a 6 W wifi router", 6.0), | |
| ("an 8 W set-top box", 8.0), | |
| ("a 10 W LED bulb", 10.0), | |
| ("a 12 W bicycle light", 12.0), | |
| ("a 15 W desk lamp", 15.0), | |
| ("an 18 W tablet charging", 18.0), | |
| ("a 20 W games controller charging", 20.0), | |
| ("a 25 W ceiling fan", 25.0), | |
| ("a 30 W laptop idling", 30.0), | |
| ("a 35 W broadband modem", 35.0), | |
| ("a 40 W old filament bulb", 40.0), | |
| ("a 45 W electric blanket", 45.0), | |
| ("a 50 W car headlamp", 50.0), | |
| ("a 60 W laptop charger", 60.0), | |
| ("a 70 W sewing machine", 70.0), | |
| ("an 80 W fridge running", 80.0), | |
| ("a 90 W desktop idling", 90.0), | |
| ("a 100 W standing person", 100.0), | |
| ("a 120 W television", 120.0), | |
| ("a 140 W games console", 140.0), | |
| ("a 160 W blender", 160.0), | |
| ("a 180 W electric fan heater on low", 180.0), | |
| ("a 200 W desktop under load", 200.0), | |
| ("a 250 W electric drill", 250.0), | |
| ("a 300 W graphics card", 300.0), | |
| ("a 350 W treadmill", 350.0), | |
| ("a 400 W chest freezer starting", 400.0), | |
| ("a 450 W food mixer", 450.0), | |
| ("a 500 W soldering station", 500.0), | |
| ("a 600 W microwave", 600.0), | |
| ("a 700 W slow cooker on high", 700.0), | |
| ("an 800 W coffee machine", 800.0), | |
| ("a 900 W dishwasher heating", 900.0), | |
| ("a 1 kW toaster", 1_000.0), | |
| ("a 1.2 kW hairdryer", 1_200.0), | |
| ("a 1.4 kW iron", 1_400.0), | |
| ("a 1.5 kW space heater", 1_500.0), | |
| ("a 1.6 kW vacuum cleaner", 1_600.0), | |
| ("a 1.8 kW washing machine heating", 1_800.0), | |
| ("a 2 kW kettle", 2_000.0), | |
| ("a 2.2 kW immersion heater", 2_200.0), | |
| ("a 2.4 kW patio heater", 2_400.0), | |
| ("a 2.6 kW tumble dryer", 2_600.0), | |
| ("a 3 kW oven element", 3_000.0), | |
| ("a 3.5 kW shower pump", 3_500.0), | |
| ("a 4 kW hob at full", 4_000.0), | |
| ("a 5 kW electric shower", 5_000.0), | |
| ("a 7 kW car charger", 7_000.0), | |
| ("an 11 kW three-phase car charger", 11_000.0), | |
| ) | |
| #: How wide a window of appliances a figure may be described by. The window is | |
| #: what creates the variety: rather than always taking the largest appliance a | |
| #: figure covers, any appliance giving a duration between one second and a few | |
| #: minutes is a fair description of it, and one of those is chosen. | |
| _COMPARATOR_MIN_SECONDS = 1.0 | |
| _COMPARATOR_MAX_SECONDS = 400.0 | |
| def _comparator_candidates(joules: float) -> tuple[tuple[str, float], ...]: | |
| return tuple( | |
| entry | |
| for entry in COMPARATORS | |
| if _COMPARATOR_MIN_SECONDS <= joules / entry[1] <= _COMPARATOR_MAX_SECONDS | |
| ) | |
| def comparator(joules: float) -> str: | |
| """"about 12 seconds of a 10 W LED bulb", or an empty string. | |
| Picks from the appliances that describe this figure in a readable span of | |
| time, rather than always the same one, so the same number seen twice in a | |
| session is not accompanied by the same sentence twice. The choice is | |
| derived from the figure itself, which matters more than it looks: this is | |
| re-rendered every two seconds while a run is in flight, and a comparator | |
| that rolled a die on each render would flicker between appliances beside a | |
| number that had not changed. The same figure always yields the same | |
| sentence; a different figure usually yields a different one. | |
| Below a second of the smallest thing in the table there is no honest | |
| comparison to draw, and this says so rather than reaching for a unit | |
| nobody has an intuition for. | |
| """ | |
| if not isinstance(joules, (int, float)) or isinstance(joules, bool): | |
| return "" | |
| if joules <= 0: | |
| return "" | |
| candidates = _comparator_candidates(float(joules)) | |
| if not candidates: | |
| # Above the window: every appliance would give a duration too long to | |
| # picture, so take the largest and let the duration speak. | |
| if joules / COMPARATORS[-1][1] > _COMPARATOR_MAX_SECONDS: | |
| name, watts = COMPARATORS[-1] | |
| return f"about {duration(joules / watts)} of {name}" | |
| # Below it: under a second of the smallest thing here. | |
| return f"less than a second of {COMPARATORS[0][0]}" | |
| # Derived from the figure, not from a random source: stable across the | |
| # re-renders of one number, varied across different numbers. | |
| # | |
| # Mixed rather than taken modulo directly. Energy figures are not evenly | |
| # distributed in their low digits: they arrive rounded, and a plain | |
| # ``value % len`` therefore landed on the first candidate far more often | |
| # than any other, which produced a table of fifty-four appliances that | |
| # mostly said "smoke alarm". Multiplying by a large odd constant and | |
| # taking the high bits spreads the low-order regularity out. | |
| mixed = (int(round(float(joules) * 1000)) * 2_654_435_761) & 0xFFFFFFFF | |
| index = (mixed >> 8) % len(candidates) | |
| name, watts = candidates[index] | |
| return f"about {duration(joules / watts)} of {name}" | |
| def energy_headline( | |
| joules: float | None, | |
| *, | |
| label: str, | |
| detail: str = "", | |
| absent_reason: str = "", | |
| ) -> str: | |
| """One energy figure, in the order a person reads it. | |
| The figure, then what it equates to, then the small print. That order is | |
| the whole change: this panel used to lead with "scope: cpu-package, | |
| boundary 1 of 2, measured across 3 of 3 completed runs", which is every | |
| true thing about the number arranged so that the number came last. | |
| Nothing was dropped to achieve it. The scope, the provider and the run | |
| counts are still on the page, one disclosure away, because they are what | |
| make the figure checkable. They are simply no longer the first thing | |
| between a user and their own answer. | |
| """ | |
| if joules is None: | |
| return ( | |
| f'<div class="c-usage c-usage--absent">' | |
| f'<p class="c-usage__label">{esc(label)}</p>' | |
| f'<p class="c-usage__figure">No data</p>' | |
| f'<p class="c-usage__means">{esc(absent_reason or "not measured, and not counted as zero")}</p>' | |
| "</div>" | |
| ) | |
| # TWO COMPARISONS, BECAUSE THEY ANSWER DIFFERENT QUESTIONS. | |
| # | |
| # "about 1.4 mugs of tea boiled" is the one people actually read: a whole | |
| # familiar thing, and how much of it this is. "about 12 seconds of a 10 W | |
| # bulb" is exact and stays underneath it, because for very small figures a | |
| # fraction of a mug of tea means nothing and a span of time still does. | |
| equals = _comparators.describe(joules) | |
| span = comparator(joules) | |
| means_html = f'<p class="c-usage__means">{esc(equals)}</p>' if equals else "" | |
| if span and span != equals: | |
| basis = _comparators.basis(joules) | |
| # The working travels with the comparison. Somebody who wants to check | |
| # "one mug of tea is 105 kJ" can, without leaving the page. | |
| title = f' title="{esc(basis)}"' if basis else "" | |
| means_html += f'<p class="c-usage__span"{title}>{esc(span)}</p>' | |
| detail_html = f'<p class="c-usage__detail">{esc(detail)}</p>' if detail else "" | |
| return ( | |
| '<div class="c-usage">' | |
| f'<p class="c-usage__label">{esc(label)}</p>' | |
| f'<p class="c-usage__figure">{esc(format_joules(joules))}</p>' | |
| f"{means_html}{detail_html}" | |
| "</div>" | |
| ) | |
| def format_joules_per_token(value: float) -> str: | |
| """Joules per token at a scale people can read. | |
| A small model's figure is millijoules; a big machine's is joules. Two | |
| decades of unit, chosen by size, so neither reads as zero. | |
| """ | |
| if value >= 1.0: | |
| return f"{value:.2f} J/tok" | |
| return f"{value * 1000:.1f} mJ/tok" | |
| def format_joules(joules: float) -> str: | |
| """A figure with a unit people read without converting. | |
| Every three decades gets its own prefix. This used to stop at kilojoules, | |
| so a worker's lifetime total rendered as "870000.00 kJ" -- six digits and a | |
| prefix, which is the exact thing a prefix exists to prevent. A session | |
| figure and a fleet figure are decades apart and both have to be readable. | |
| Watt-hours are not used as the headline: one run costs hundredths of one, | |
| and a number that starts 0.00 reads as zero however it is labelled. | |
| """ | |
| if joules >= 1_000_000_000: | |
| return f"{joules / 1_000_000_000:.2f} GJ" | |
| if joules >= 1_000_000: | |
| return f"{joules / 1_000_000:.2f} MJ" | |
| if joules >= 1_000: | |
| return f"{joules / 1_000:.2f} kJ" | |
| if joules >= 10: | |
| return f"{joules:.1f} J" | |
| return f"{joules:.2f} J" | |
| def usage_summary(sections: Sequence[Mapping[str, object]], *, detail: str = "") -> str: | |
| """The energy surface: figures first, measurement detail behind a toggle.""" | |
| body = "".join( | |
| energy_headline( | |
| section.get("joules"), | |
| label=str(section.get("label") or ""), | |
| detail=str(section.get("detail") or ""), | |
| absent_reason=str(section.get("absent_reason") or ""), | |
| ) | |
| for section in sections | |
| ) | |
| small_print = ( | |
| '<details class="c-usage__more">' | |
| '<summary class="c-usage__moretoggle">How this is measured</summary>' | |
| f'<div class="c-usage__morebody">{esc(detail)}</div>' | |
| "</details>" | |
| if detail | |
| else "" | |
| ) | |
| return f'<section class="c-usage-panel">{body}{small_print}</section>' | |
| #: How each kind of step is introduced. The worker names the kind from a | |
| #: closed vocabulary and this file owns the sentence, which is the same | |
| #: division the phase copy uses: a worker can say what happened, never how it | |
| #: is described. | |
| STEP_LEAD = { | |
| "model": ("◇", "Model"), | |
| "tool-call": ("→", "Called"), | |
| "tool-result": ("●", "Returned"), | |
| "phase": ("·", ""), | |
| } | |
| # -------------------------------------------------------------------------- | |
| # What the run made: the artifact's own content, in the answer | |
| # -------------------------------------------------------------------------- | |
| # | |
| # A run that produced a file used to say so with a count in the receipt and a | |
| # row in the Outputs panel. Both are true and neither shows the thing. These | |
| # two functions close that gap: `artifact_preview_data` reads the stored file | |
| # once, at the moment the answer is claimed, and reduces it to a small plain | |
| # record; `made_things` renders those records as the kind of object each one | |
| # is — a document page, a sheet of cells, a fan of slides, the text itself. | |
| # | |
| # The split matters. Derivation happens once and the record rides in browser | |
| # state beside the answer, so the transcript can re-render every two seconds | |
| # without re-opening zip files. And because the record is data assembled here | |
| # from bytes the worker sent, rendering it is the same trust exercise as the | |
| # rest of this file: every string is escaped, structure comes from this | |
| # module, and a file that cannot be parsed degrades to its name and size | |
| # rather than to an error. | |
| #: Reading cap per artifact. Files are small (the job budget bounds them); | |
| #: this is the backstop that keeps a surprise out of the render path. | |
| _PREVIEW_READ_CAP = 400_000 | |
| #: How much a compressed member may be allowed to become, and how much of a | |
| #: whole file may be inflated across all its members. | |
| #: | |
| #: THE FILE ON THE WIRE IS NOT THE FILE IN MEMORY. A worker is somebody | |
| #: else's machine, and the protocol caps what it may send, not what that | |
| #: expands to: a 300 KB archive of compressible bytes inflates to 300 MB, and | |
| #: a run may carry eight of them. Read whole, that is 2.4 GB and half a minute | |
| #: of CPU inside the one process every viewer of this server shares — a worker | |
| #: could stop the service for everybody by answering a question. | |
| #: | |
| #: A preview needs the first few paragraphs, rows or slides, so these are | |
| #: generous by the standard of what is actually read and mean the arithmetic | |
| #: cannot run away. | |
| _MAX_INFLATED_MEMBER = 2 * 1024 * 1024 | |
| _MAX_INFLATED_TOTAL = 8 * 1024 * 1024 | |
| class _InflationRefused(Exception): | |
| """A member claimed, or turned out to be, more than a preview may inflate.""" | |
| def _read_member(archive, name: str, budget: list[int]) -> bytes: | |
| """One zip member, refused rather than inflated when it is too large. | |
| Two checks, because either alone is defeated. The header's ``file_size`` | |
| is what the archive claims and can simply lie; reading one byte past the | |
| limit is what actually happened. ``budget`` is the file's remaining total, | |
| mutated as members are read, so many merely-large members cannot add up to | |
| the same attack that one huge one would. | |
| """ | |
| try: | |
| info = archive.getinfo(name) | |
| except KeyError as exc: | |
| raise _InflationRefused(f"no member {name!r}") from exc | |
| allowed = min(_MAX_INFLATED_MEMBER, budget[0]) | |
| if info.file_size > allowed: | |
| raise _InflationRefused(f"{name} declares {info.file_size} bytes") | |
| with archive.open(name) as handle: | |
| data = handle.read(allowed + 1) | |
| if len(data) > allowed: | |
| raise _InflationRefused(f"{name} is larger than it declared") | |
| budget[0] -= len(data) | |
| return data | |
| _TEXT_SUFFIXES = { | |
| ".txt", ".css", ".json", ".mermaid", ".py", ".js", ".html", ".svg", | |
| ".yaml", ".yml", ".toml", ".xml", | |
| } | |
| def _xml_texts(blob: bytes, pattern: str) -> list[str]: | |
| import re as _re | |
| return [ | |
| escape_entities(match) | |
| for match in _re.findall(pattern, blob.decode("utf-8", "replace"), _re.S) | |
| ] | |
| def escape_entities(text: str) -> str: | |
| """Resolve the five XML entities OOXML writes; nothing else.""" | |
| return ( | |
| text.replace("<", "<").replace(">", ">").replace(""", '"') | |
| .replace("'", "'").replace("&", "&") | |
| ) | |
| def _docx_preview(blob: bytes) -> Optional[Mapping[str, object]]: | |
| import io as _io | |
| import re as _re | |
| import zipfile as _zipfile | |
| try: | |
| with _zipfile.ZipFile(_io.BytesIO(blob)) as archive: | |
| document = _read_member(archive, "word/document.xml", [_MAX_INFLATED_TOTAL]) | |
| except Exception: | |
| return None | |
| paragraphs: list[str] = [] | |
| for paragraph in _re.findall(rb"<w:p[ >].*?</w:p>", document, _re.S): | |
| runs = _xml_texts(paragraph, r"<w:t[^>]*>(.*?)</w:t>") | |
| text = "".join(runs).strip() | |
| if text: | |
| paragraphs.append(text) | |
| if not paragraphs: | |
| return None | |
| return {"kind": "doc", "title": paragraphs[0][:160], "paras": paragraphs[1:5]} | |
| def _xlsx_preview(blob: bytes) -> Optional[Mapping[str, object]]: | |
| import io as _io | |
| import re as _re | |
| import zipfile as _zipfile | |
| budget = [_MAX_INFLATED_TOTAL] | |
| try: | |
| with _zipfile.ZipFile(_io.BytesIO(blob)) as archive: | |
| sheet = _read_member(archive, "xl/worksheets/sheet1.xml", budget) | |
| try: | |
| shared = _read_member(archive, "xl/sharedStrings.xml", budget) | |
| except (KeyError, _InflationRefused): | |
| shared = b"" | |
| except Exception: | |
| return None | |
| strings = _xml_texts(shared, r"<t[^>]*>(.*?)</t>") if shared else [] | |
| rows: list[list[str]] = [] | |
| # CELLS IN DOCUMENT ORDER, WHATEVER KIND THEY ARE. | |
| # | |
| # The first version of this pulled the numbers out with one pattern and | |
| # the inline strings with another, then concatenated the two lists. Every | |
| # mixed row came out rotated — "Widget | 4 | 9.50" rendered as | |
| # "4 | 9.50 | Widget" — because the text cells were appended after the | |
| # numeric ones rather than kept in their columns. A preview that reorders | |
| # somebody's spreadsheet is worse than no preview, so the cells are now | |
| # walked once, in order, and each is read according to its own type. | |
| for row in _re.findall(rb"<row[ >].*?</row>", sheet, _re.S)[:8]: | |
| cells: list[str] = [] | |
| for cell in _re.findall(rb"<c[ >].*?(?:</c>|/>)", row, _re.S): | |
| kind = _re.search(rb'\st="(\w+)"', cell) | |
| kind = kind.group(1).decode() if kind else "n" | |
| inline = _xml_texts(cell, r"<t[^>]*>(.*?)</t>") | |
| if inline: | |
| cells.append(inline[0]) | |
| continue | |
| value = _re.search(rb"<v>(.*?)</v>", cell, _re.S) | |
| if value is None: | |
| cells.append("") | |
| continue | |
| raw = escape_entities(value.group(1).decode("utf-8", "replace")) | |
| if kind == "s": | |
| try: | |
| raw = strings[int(raw)] | |
| except (ValueError, IndexError): | |
| pass | |
| cells.append(raw) | |
| while cells and cells[-1] == "": | |
| cells.pop() | |
| if cells: | |
| rows.append(cells[:8]) | |
| if not rows: | |
| return None | |
| return {"kind": "sheet", "rows": rows} | |
| def _pptx_preview(blob: bytes) -> Optional[Mapping[str, object]]: | |
| import io as _io | |
| import re as _re | |
| import zipfile as _zipfile | |
| try: | |
| with _zipfile.ZipFile(_io.BytesIO(blob)) as archive: | |
| names = sorted( | |
| name | |
| for name in archive.namelist() | |
| if _re.fullmatch(r"ppt/slides/slide\d+\.xml", name) | |
| ) | |
| slides: list[Mapping[str, str]] = [] | |
| budget = [_MAX_INFLATED_TOTAL] | |
| for name in names[:8]: | |
| try: | |
| member = _read_member(archive, name, budget) | |
| except _InflationRefused: | |
| continue | |
| texts = _xml_texts(member, r"<a:t>(.*?)</a:t>") | |
| texts = [text for text in (t.strip() for t in texts) if text] | |
| if texts: | |
| slides.append({"title": texts[0][:120]}) | |
| except Exception: | |
| return None | |
| if not slides: | |
| return None | |
| return {"kind": "deck", "slides": slides} | |
| def _pdf_preview(blob: bytes) -> Optional[Mapping[str, object]]: | |
| import re as _re | |
| import zlib as _zlib | |
| pages = len(_re.findall(rb"/Type\s*/Page\b(?!s)", blob)) | |
| # Content streams are flate-compressed (the PDF this product writes says so | |
| # in its own builder), so the text operators only exist after inflating. | |
| # Streams that will not inflate are skipped rather than guessed at, and a | |
| # PDF nobody can read still reports its page count, which is a fact. | |
| chunks = [blob] | |
| budget = _MAX_INFLATED_TOTAL | |
| for raw in _re.findall(rb"stream\r?\n(.*?)\r?\nendstream", blob, _re.S): | |
| if budget <= 0: | |
| break | |
| try: | |
| # Bounded inflation: `decompress(data, max_length)` stops at the | |
| # limit instead of returning however many gigabytes the stream | |
| # encodes. What is left in the decompressor is dropped with it. | |
| allowed = min(_MAX_INFLATED_MEMBER, budget) | |
| piece = _zlib.decompressobj().decompress(raw, allowed) | |
| except Exception: | |
| continue | |
| budget -= len(piece) | |
| chunks.append(piece) | |
| lines: list[str] = [] | |
| seen: set[str] = set() | |
| for chunk in chunks: | |
| for raw in _re.findall(rb"\(((?:[^()\\]|\\.)*)\)\s*Tj", chunk): | |
| text = raw.decode("latin-1", "replace") | |
| text = _re.sub(r"\\([()\\])", r"\1", text).strip() | |
| if text and text not in seen: | |
| seen.add(text) | |
| lines.append(text) | |
| if len(lines) >= 14: | |
| break | |
| lines = lines[:14] | |
| if not lines and not pages: | |
| return None | |
| record: dict[str, object] = {"kind": "doc", "note": f"{pages or 1} page PDF"} | |
| if lines: | |
| record["title"] = lines[0][:160] | |
| record["paras"] = lines[1:5] | |
| else: | |
| record["title"] = "PDF document" | |
| record["paras"] = [] | |
| return record | |
| def _markdown_preview(text: str) -> Optional[Mapping[str, object]]: | |
| """Markdown as the page it describes, not as its source. | |
| A guide rendered as a wall of hashes and asterisks demonstrates nothing: | |
| the person is looking at the thing the run made, and the thing the run | |
| made is a document. Headings become the title, bullets keep their bullet, | |
| and everything else is a paragraph. | |
| """ | |
| lines = [line.rstrip() for line in text.splitlines()] | |
| title = "" | |
| paras: list[str] = [] | |
| for line in lines: | |
| stripped = line.strip() | |
| if not stripped: | |
| continue | |
| if stripped.startswith("#"): | |
| heading = stripped.lstrip("#").strip() | |
| if not title: | |
| title = heading[:160] | |
| elif len(paras) < 4: | |
| paras.append(heading[:200]) | |
| continue | |
| if stripped.startswith(("-", "*", "+")) and len(stripped) > 1: | |
| stripped = "• " + stripped[1:].strip() | |
| cleaned = stripped.replace("**", "").replace("`", "") | |
| if not title: | |
| title = cleaned[:160] | |
| elif len(paras) < 4: | |
| paras.append(cleaned[:200]) | |
| if len(paras) >= 4: | |
| break | |
| if not title: | |
| return None | |
| return {"kind": "doc", "title": title, "paras": paras} | |
| def _table_preview(text: str) -> Optional[Mapping[str, object]]: | |
| rows = [line for line in text.splitlines() if line.strip()][:8] | |
| if not rows: | |
| return None | |
| split = [row.split(",") if "," in rows[0] else row.split("|") for row in rows] | |
| return {"kind": "sheet", "rows": [[cell.strip() for cell in row][:8] for row in split]} | |
| def artifact_preview_data(paths: Sequence[str]) -> list[Mapping[str, object]]: | |
| """Small, renderable records of what a run's files contain. | |
| Read once per file, capped, every failure downgraded to name-and-size. | |
| The records are plain data so they can live in browser state beside the | |
| answer they belong to. | |
| """ | |
| records: list[Mapping[str, object]] = [] | |
| for item in paths: | |
| path = Path(str(item)) | |
| try: | |
| size = path.stat().st_size | |
| blob = path.read_bytes()[:_PREVIEW_READ_CAP] | |
| except OSError: | |
| continue | |
| suffix = path.suffix.lower() | |
| parsed: Optional[Mapping[str, object]] = None | |
| if suffix == ".docx": | |
| parsed = _docx_preview(blob) | |
| elif suffix == ".xlsx": | |
| parsed = _xlsx_preview(blob) | |
| elif suffix == ".pptx": | |
| parsed = _pptx_preview(blob) | |
| elif suffix == ".pdf": | |
| parsed = _pdf_preview(blob) | |
| elif suffix == ".csv": | |
| parsed = _table_preview(blob.decode("utf-8", "replace")) | |
| elif suffix == ".md": | |
| parsed = _markdown_preview(blob.decode("utf-8", "replace")) | |
| elif suffix in _TEXT_SUFFIXES: | |
| text = blob.decode("utf-8", "replace").strip() | |
| parsed = {"kind": "text", "text": text[:1400]} if text else None | |
| record: dict[str, object] = { | |
| "name": path.name, | |
| "size": size, | |
| "kind": "file", | |
| } | |
| if parsed: | |
| record.update(parsed) | |
| records.append(record) | |
| return records | |
| def _human_size(size: object) -> str: | |
| try: | |
| value = float(size) # type: ignore[arg-type] | |
| except (TypeError, ValueError): | |
| return "" | |
| if value >= 1_048_576: | |
| return f"{value / 1_048_576:.1f} MB" | |
| if value >= 1024: | |
| return f"{value / 1024:.1f} KB" | |
| return f"{int(value)} B" | |
| _MADE_KIND_WORDS = { | |
| "doc": "document", | |
| "sheet": "spreadsheet", | |
| "deck": "slides", | |
| "text": "text", | |
| "file": "file", | |
| } | |
| def made_things(previews: Sequence[Mapping[str, object]]) -> str: | |
| """The artifacts a run produced, rendered as the things they are. | |
| Structure is fixed here; every string is escaped; a record whose kind is | |
| unknown renders as a plain file card. The block sits inside the answer, | |
| after the model's words, because "make me a PDF" is answered by the PDF. | |
| """ | |
| if not previews: | |
| return "" | |
| cards: list[str] = [] | |
| for record in previews: | |
| if not isinstance(record, Mapping): | |
| continue | |
| name = esc(str(record.get("name") or "file")) | |
| kind = str(record.get("kind") or "file") | |
| kind_word = _MADE_KIND_WORDS.get(kind, "file") | |
| body = "" | |
| if kind == "doc": | |
| title = esc(str(record.get("title") or "")) | |
| paras = "".join( | |
| f"<p>{esc(str(para))}</p>" for para in record.get("paras") or () | |
| if isinstance(para, str) | |
| ) | |
| body = f"<h4>{title}</h4>{paras}" if title else paras | |
| elif kind == "sheet": | |
| rows = [row for row in record.get("rows") or () if isinstance(row, (list, tuple))] | |
| if rows: | |
| head = "".join(f"<th>{esc(str(cell))}</th>" for cell in rows[0]) | |
| rest = "".join( | |
| "<tr>" + "".join(f"<td>{esc(str(cell))}</td>" for cell in row) + "</tr>" | |
| for row in rows[1:] | |
| ) | |
| body = f'<table class="c-madegrid"><tr>{head}</tr>{rest}</table>' | |
| elif kind == "deck": | |
| slides = [ | |
| slide for slide in record.get("slides") or () if isinstance(slide, Mapping) | |
| ] | |
| body = '<div class="c-madeslides">' + "".join( | |
| f'<div class="c-madeslide"><span class="c-madeslide__no">{index}</span>' | |
| f'<span class="c-madeslide__title">{esc(str(slide.get("title") or ""))}</span>' | |
| '<span class="c-madeslide__line"></span><span class="c-madeslide__line"></span>' | |
| "</div>" | |
| for index, slide in enumerate(slides, start=1) | |
| ) + "</div>" | |
| elif kind == "text": | |
| body = f"<pre>{esc(str(record.get('text') or ''))}</pre>" | |
| note = str(record.get("note") or "") | |
| size = _human_size(record.get("size")) | |
| foot_parts = [part for part in (note, size, "in Outputs, left panel") if part] | |
| modifier = kind if kind in ("doc", "sheet", "deck", "text") else "file" | |
| cards.append( | |
| f'<figure class="c-madecard c-made--{modifier}">' | |
| '<div class="c-madecard__bar">' | |
| '<span class="c-madecard__dot" aria-hidden="true"></span>' | |
| f'<span class="c-madecard__name">{name}</span>' | |
| f'<span class="c-madecard__kind">{esc(kind_word)}</span>' | |
| "</div>" | |
| + (f'<div class="c-madecard__body">{body}</div>' if body else "") | |
| + f'<figcaption class="c-made__foot">{esc(" · ".join(foot_parts))}</figcaption>' | |
| "</figure>" | |
| ) | |
| if not cards: | |
| return "" | |
| return '<div class="c-made">' + "".join(cards) + "</div>" | |
| def run_steps(steps: Sequence[Mapping[str, object]]) -> str: | |
| """The agent's turns, in order, kept after the run that took them. | |
| Until this existed a completed turn could show what the model finally | |
| said and nothing about how it got there: which tools it considered, what | |
| it passed them, what came back. That is most of the work, and on a small | |
| model it is most of what there is to judge. | |
| Every field is worker-supplied and escaped. The mark and the lead word | |
| come from the table above rather than from the wire. | |
| """ | |
| if not steps: | |
| return "" | |
| items: list[str] = [] | |
| for step in steps: | |
| if not isinstance(step, Mapping): | |
| continue | |
| kind = str(step.get("kind") or "phase") | |
| mark, lead = STEP_LEAD.get(kind, STEP_LEAD["phase"]) | |
| tone = "work" | |
| if kind == "tool-result": | |
| tone = "ok" if step.get("ok") else "warn" | |
| elif kind == "tool-call": | |
| tone = "work" | |
| tool = str(step.get("tool") or "") | |
| tool_html = f'<code class="c-step__tool">{esc(tool)}</code>' if tool else "" | |
| lead_html = f'<span class="c-step__lead">{esc(lead)}</span>' if lead else "" | |
| items.append( | |
| f'<li class="c-step c-step--{tone}">' | |
| f'<span class="c-step__mark" aria-hidden="true">{esc(mark)}</span>' | |
| f'<span class="c-step__body">{lead_html}{tool_html}' | |
| f'<span class="c-step__text">{esc(str(step.get("text") or ""))}</span>' | |
| "</span></li>" | |
| ) | |
| if not items: | |
| return "" | |
| return ( | |
| '<details class="c-turns"><summary class="c-turns__toggle">' | |
| f"What the agent did ({len(items)} steps)</summary>" | |
| f'<ol class="c-steps">{"".join(items)}</ol></details>' | |
| ) | |
| #: The wash each conversation state gets in the rail. Faint on purpose: see | |
| #: the note in presentation.py. A state with no entry gets no wash, which is | |
| #: how "idle" and "completed" are drawn. Warm washes over the ivory canvas: | |
| #: the only saturated green on the page stays the accent. | |
| CONVERSATION_TONES = { | |
| "waiting": "#F7F1E1", | |
| "generating": "#E8F0EA", | |
| "failed": "#F7ECE7", | |
| } | |
| def conversation_tones(states: Mapping[str, str]) -> str: | |
| """A style block colouring each conversation row by its state. | |
| The list is a radio group, and a radio group gives no per-option hook to | |
| hang a class on, so the rule is written against the option's own value. | |
| That value is a conversation id this server generated, but it is read back | |
| out of browser state before it arrives here, so it is filtered to the | |
| characters an id can contain rather than trusted. An id that does not | |
| match is dropped: a missing wash is a cosmetic loss, and a selector built | |
| from unfiltered text is a way into the stylesheet. | |
| """ | |
| rules: list[str] = [] | |
| for conversation_id, state in (states or {}).items(): | |
| tone = CONVERSATION_TONES.get(str(state)) | |
| if not tone: | |
| continue | |
| safe = "".join( | |
| character | |
| for character in str(conversation_id) | |
| if character.isalnum() or character in "-_" | |
| )[:80] | |
| if not safe or safe != str(conversation_id): | |
| continue | |
| rules.append( | |
| f'.c-convlist label:has(input[value="{safe}"]):not(:has(input:checked))' | |
| f"{{background:{tone} !important;}}" | |
| ) | |
| if not rules: | |
| return '<div class="c-railtones"></div>' | |
| return f'<div class="c-railtones"><style>{"".join(rules)}</style></div>' | |
| def run_outcomes(entries: Sequence[Mapping[str, object]]) -> str: | |
| """Runs that ended without an answer, reported beside the conversation. | |
| These used to be bubbles in the transcript, which put the server's own | |
| account of a failure in the same place and the same shape as something a | |
| person said. A failure is still a fact the user has to see, so it is here, | |
| attached to the turn it belongs to, and it is the only thing in this file | |
| that reports an absence of an answer. | |
| """ | |
| if not entries: | |
| return "" | |
| rows = "".join( | |
| f'<li class="c-outcome"><span class="c-outcome__turn">Run ' | |
| f'{esc(str(entry.get("turn", "")))}</span>' | |
| f'<span class="c-outcome__text">{esc(str(entry.get("text", "")))}</span></li>' | |
| for entry in entries | |
| if isinstance(entry, Mapping) | |
| ) | |
| return f'<ul class="c-outcomes">{rows}</ul>' if rows else "" | |
| def run_receipts(entries: Sequence[Mapping[str, object]]) -> str: | |
| """What each answer cost and did, beside the conversation. | |
| This is the material that used to be appended to the model's own reply. | |
| Moving it out was not a matter of tidiness: a receipt inside the bubble is | |
| read as part of the answer, and the answer is the only thing in the | |
| transcript the user asked for. | |
| Every field here is worker-supplied and escaped, and the structure is | |
| fixed in this function rather than taken from the wire. | |
| """ | |
| if not entries: | |
| return "" | |
| rows: list[str] = [] | |
| previous_worker = "" | |
| for entry in entries: | |
| chips: list[str] = [] | |
| cost = str(entry.get("cost") or "") | |
| means = str(entry.get("means") or "") | |
| calls = entry.get("calls") | |
| files = entry.get("files") | |
| if calls: | |
| chips.append(chip(f"{calls} tool call" + ("s" if int(calls) != 1 else ""))) | |
| if files: | |
| chips.append(chip(f"{files} file" + ("s" if int(files) != 1 else ""), tone="ok")) | |
| worker = str(entry.get("worker") or "") | |
| # Named when it changes, and then not again. A session usually runs on | |
| # one worker, so repeating its name on every receipt added a line of | |
| # chrome per answer that carried no information after the first. A | |
| # change of worker between two answers is worth seeing, and it is the | |
| # only time this appears. | |
| if worker and worker != previous_worker: | |
| chips.append(chip(worker, tone="outline")) | |
| if worker: | |
| previous_worker = worker | |
| trace_items = entry.get("trace") | |
| trace_html = "" | |
| if isinstance(trace_items, (list, tuple)) and trace_items: | |
| steps = "".join( | |
| f'<li class="c-step c-step--{"ok" if item.get("ok") else "warn"}">' | |
| f'<span class="c-step__mark" aria-hidden="true">' | |
| f'{"●" if item.get("ok") else "■"}</span>' | |
| f'<span class="c-step__body">' | |
| f'<code class="c-step__tool">{esc(item.get("tool", "?"))}</code>' | |
| f'<span class="c-step__text">{esc(item.get("summary", ""))}</span>' | |
| "</span></li>" | |
| for item in trace_items | |
| if isinstance(item, Mapping) | |
| ) | |
| trace_html = f'<ol class="c-steps">{steps}</ol>' | |
| # The trace above is the summary: which tools ran and what they made. | |
| # This is the whole sequence, including the model's own turns, folded | |
| # away because most of the time the summary is enough and the run is | |
| # over. | |
| turns_html = run_steps(entry.get("steps") or ()) | |
| rows.append( | |
| '<article class="c-receipt">' | |
| f'<p class="c-receipt__head">' | |
| f'<span class="c-receipt__turn">{esc(entry.get("turn", ""))}</span>' | |
| f'<span class="c-receipt__cost">{esc(cost)}</span>' | |
| f'<span class="c-receipt__means">{esc(means)}</span></p>' | |
| # Omitted rather than emitted empty: an empty chip row still | |
| # reserves its height, so every receipt carried a blank strip. | |
| + (f'<div class="c-chips">{"".join(chips)}</div>' if chips else "") | |
| + f"{trace_html}{turns_html}" | |
| "</article>" | |
| ) | |
| return ( | |
| '<section class="c-receipts">' | |
| '<p class="c-eyebrow">What each answer cost' | |
| '<span class="c-eyebrow__note">use phase, self-reported</span></p>' | |
| f'{"".join(rows)}' | |
| "</section>" | |
| ) | |
| def energy_panel( | |
| *, | |
| title: str, | |
| boundary: str, | |
| lines: Iterable[str], | |
| caveat: str, | |
| never_sum: str, | |
| measured: bool, | |
| sections: Iterable[Mapping[str, object]] = (), | |
| headlines: Iterable[Mapping[str, object]] = (), | |
| small_print: str = "", | |
| ) -> str: | |
| """One rubric boundary, on its own surface, that never sums with the other. | |
| ``measured=False`` renders an em dash beside the value. An absence must be | |
| visually as well as semantically distinct from a measured zero — a tidy | |
| ``0`` in the same slot is exactly the misreading the rubric forbids. | |
| """ | |
| headlines = list(headlines) | |
| if headlines: | |
| # The readable form: figure, then what it equates to, then the | |
| # measurement detail one disclosure away. The boundary line and the | |
| # never-added line stay on the face of the panel, because those are | |
| # claims about what the number *is* rather than notes about how it was | |
| # taken, and a reader who misses them misreads the figure itself. | |
| body = "".join( | |
| energy_headline( | |
| item.get("joules"), | |
| label=str(item.get("label") or ""), | |
| detail=str(item.get("detail") or ""), | |
| absent_reason=str(item.get("absent_reason") or ""), | |
| ) | |
| for item in headlines | |
| ) | |
| more = ( | |
| '<details class="c-usage__more">' | |
| '<summary class="c-usage__moretoggle">How this is measured</summary>' | |
| f'<div class="c-usage__morebody">{esc(small_print)}</div>' | |
| "</details>" | |
| if small_print | |
| else "" | |
| ) | |
| boundary_html = ( | |
| f'<span class="c-panel__boundary">{esc(boundary)}</span>' if boundary else "" | |
| ) | |
| never_html = ( | |
| f'<p class="c-panel__never">{esc(never_sum)}</p>' if never_sum else "" | |
| ) | |
| return ( | |
| '<section class="c-panel">' | |
| f'<p class="c-panel__head"><span class="c-panel__title">{esc(title)}</span>' | |
| f"{boundary_html}</p>" | |
| f'<div class="c-usage-panel">{body}</div>' | |
| f"{more}{never_html}" | |
| "</section>" | |
| ) | |
| sections = list(sections) | |
| if sections: | |
| # Several scopes of the same boundary, stacked. Each keeps its own | |
| # headline value and its own absence marker, because "no data for this | |
| # conversation" and "no data for this worker" are different facts and | |
| # one must never stand in for the other. | |
| blocks: list[str] = [] | |
| for section in sections: | |
| heading = str(section.get("heading") or "") | |
| block = _energy_block( | |
| [str(line) for line in section.get("lines") or ()], | |
| measured=bool(section.get("measured")), | |
| quiet=bool(section.get("quiet")), | |
| ) | |
| head = ( | |
| f'<p class="c-energy__scope">{esc(heading)}</p>' if heading else "" | |
| ) | |
| blocks.append(head + block) | |
| return ( | |
| '<section class="c-panel">' | |
| f'<p class="c-panel__head"><span class="c-panel__title">{esc(title)}</span>' | |
| f'<span class="c-panel__boundary">{esc(boundary)}</span></p>' | |
| f'<div class="c-energy">{"".join(blocks)}</div>' | |
| f'<p class="c-panel__caveat">{esc(caveat)}</p>' | |
| f'<p class="c-panel__never">{esc(never_sum)}</p>' | |
| "</section>" | |
| ) | |
| body: list[str] = [] | |
| for index, line in enumerate(lines): | |
| if index == 0: | |
| # The dash marks an *absent measurement*. With no runs at all there | |
| # is nothing to have measured, so marking it would overstate the | |
| # case and the line is ordinary copy rather than a headline value. | |
| nothing_yet = "no completed runs" in line.casefold() | |
| if nothing_yet: | |
| body.append(f'<p class="c-energy__line">{esc(line)}</p>') | |
| continue | |
| mark = ABSENCE_MARK if not measured else "" | |
| state = " c-energy__value--absent" if not measured else "" | |
| body.append(f'<p class="c-energy__value{state}">{mark}{esc(line)}</p>') | |
| else: | |
| body.append(f'<p class="c-energy__line">{esc(line)}</p>') | |
| return ( | |
| '<section class="c-panel">' | |
| f'<p class="c-panel__head"><span class="c-panel__title">{esc(title)}</span>' | |
| f'<span class="c-panel__boundary">{esc(boundary)}</span></p>' | |
| f'<div class="c-energy">{"".join(body)}</div>' | |
| f'<p class="c-panel__caveat">{esc(caveat)}</p>' | |
| f'<p class="c-panel__never">{esc(never_sum)}</p>' | |
| "</section>" | |
| ) | |
| def _energy_block(lines: Sequence[str], *, measured: bool, quiet: bool = False) -> str: | |
| """One scope's figure and its supporting lines. | |
| ``quiet`` renders every line in the supporting weight and adds no absence | |
| marker. It exists for the worker-lifetime block, which is real context but | |
| is not this session's headline number: it is self-reported by a machine | |
| nobody here can check, and giving it the same visual weight as a figure | |
| this session watched arrive would flatten exactly the difference the panel | |
| is trying to preserve. The dash is reserved for a *missing* measurement, | |
| so it must not appear beside a figure that is present but unverifiable. | |
| """ | |
| body: list[str] = [] | |
| for index, line in enumerate(lines): | |
| if index == 0 and not quiet: | |
| nothing_yet = "no completed runs" in line.casefold() | |
| if nothing_yet: | |
| body.append(f'<p class="c-energy__line">{esc(line)}</p>') | |
| continue | |
| mark = ABSENCE_MARK if not measured else "" | |
| state = " c-energy__value--absent" if not measured else "" | |
| body.append(f'<p class="c-energy__value{state}">{mark}{esc(line)}</p>') | |
| else: | |
| body.append(f'<p class="c-energy__line">{esc(line)}</p>') | |
| return "".join(body) | |
| # -------------------------------------------------------------------------- | |
| # Footer | |
| # -------------------------------------------------------------------------- | |
| # -------------------------------------------------------------------------- | |
| # Library cards | |
| # -------------------------------------------------------------------------- | |
| #: What a member leaves behind, keyed by reference. Drawn on its card as a | |
| #: small picture of that kind of thing. | |
| #: | |
| #: A RECORDING WAS THE WRONG ANSWER TO "WHAT IS THIS FOR". | |
| #: | |
| #: These cards used to carry a filmed demonstration: a GIF per member, with a | |
| #: still of the run's own output underneath, 2.5 MB of them in the repository. | |
| #: They were honest — every frame was a real run — and they answered the wrong | |
| #: question. Somebody scanning a shelf of thirty members wants to know what | |
| #: each one *makes*, at a glance, before deciding which to look at closely; a | |
| #: recording only answers that after it has played, one card at a time, and | |
| #: not at all on a phone where nothing hovers. | |
| #: | |
| #: A drawing of the artifact answers it instantly and identically for every | |
| #: member, weighs a few hundred bytes, needs no recording pass to stay true | |
| #: when a skill changes, and reads the same on any screen. | |
| _MEMBER_OUTPUT: Mapping[str, str] = { | |
| "create_pdf": "page", | |
| "create_docx": "page", | |
| "create_deck": "deck", | |
| "create_xlsx": "sheet", | |
| "csv_table": "sheet", | |
| "frontend_design": "web", | |
| "theme_factory": "palette", | |
| "make_plan": "list", | |
| "todo": "list", | |
| "review_checklist": "list", | |
| "skill_scaffold": "note", | |
| "status_update": "note", | |
| "scratchpad": "note", | |
| "search_document": "find", | |
| "extract_from_text": "find", | |
| "verify_quote": "find", | |
| "calculate": "value", | |
| "calculate_date": "value", | |
| "convert_units": "value", | |
| } | |
| #: Everything driven by ``tailored_guide`` writes a guide in markdown, so it | |
| #: is one shape rather than nineteen near-identical entries above. | |
| _GUIDE_OUTPUT = "guide" | |
| #: The palette the drawings use. Deliberately the page's own tokens rather | |
| #: than fixed colours, so a card follows the theme instead of sitting in a | |
| #: little rectangle of last year's palette. | |
| _MOCK_INK = "var(--c-text-2)" | |
| _MOCK_FAINT = "var(--c-hairline)" | |
| _MOCK_ACCENT = "var(--c-accent)" | |
| def _member_output(ref: str) -> str: | |
| """Which drawing belongs to a member, from its reference.""" | |
| tool_id = ref.split("@", 1)[0] | |
| if tool_id in _MEMBER_OUTPUT: | |
| return _MEMBER_OUTPUT[tool_id] | |
| try: | |
| from distinct_tools.skills import REPOSITORY_SKILLS | |
| for skill in REPOSITORY_SKILLS: | |
| if skill.tool_id == tool_id and getattr(skill, "handler", "") == "tailored_guide": | |
| return _GUIDE_OUTPUT | |
| except Exception: | |
| pass | |
| return "generic" | |
| def _rows(count: int, *, x: float, y: float, gap: float, width: float, short: int = -1) -> str: | |
| """Horizontal rules standing in for lines of text. | |
| ``short`` is the index drawn at two thirds width. A block of identical | |
| full-width bars reads as a barcode; one ragged edge is what makes it read | |
| as writing. | |
| """ | |
| bars = [] | |
| for index in range(count): | |
| length = width * (0.62 if index == short else 1.0) | |
| bars.append( | |
| f'<rect x="{x}" y="{y + index * gap:.1f}" width="{length:.1f}" height="2" ' | |
| f'rx="1" fill="{_MOCK_FAINT}"/>' | |
| ) | |
| return "".join(bars) | |
| def _mockup(kind: str) -> str: | |
| """One small drawing of the thing a member produces. | |
| Inline SVG rather than an image file: it is a few hundred bytes, it is | |
| sharp at any size, it takes the page's colours, and there is no asset to | |
| fetch, cache, forget to ship, or let drift out of date. | |
| """ | |
| body = { | |
| # A page of writing: a heading, a rule, and paragraphs. | |
| "page": ( | |
| f'<rect x="34" y="8" width="92" height="88" rx="3" fill="var(--c-surface)" ' | |
| f'stroke="{_MOCK_FAINT}"/>' | |
| f'<rect x="44" y="20" width="46" height="5" rx="2" fill="{_MOCK_ACCENT}"/>' | |
| + _rows(6, x=44, y=34, gap=9, width=72, short=5) | |
| ), | |
| # Slides: one wide frame, two beneath it. | |
| "deck": ( | |
| f'<rect x="26" y="10" width="108" height="46" rx="3" fill="var(--c-surface)" ' | |
| f'stroke="{_MOCK_FAINT}"/>' | |
| f'<rect x="36" y="22" width="42" height="5" rx="2" fill="{_MOCK_ACCENT}"/>' | |
| f'<rect x="36" y="34" width="66" height="2" rx="1" fill="{_MOCK_FAINT}"/>' | |
| f'<rect x="26" y="62" width="50" height="32" rx="3" fill="var(--c-surface)" ' | |
| f'stroke="{_MOCK_FAINT}"/>' | |
| f'<rect x="84" y="62" width="50" height="32" rx="3" fill="var(--c-surface)" ' | |
| f'stroke="{_MOCK_FAINT}"/>' | |
| ), | |
| # A grid, with the header row filled in. | |
| "sheet": ( | |
| f'<rect x="26" y="16" width="108" height="72" rx="3" fill="var(--c-surface)" ' | |
| f'stroke="{_MOCK_FAINT}"/>' | |
| f'<rect x="26" y="16" width="108" height="16" fill="var(--c-fill)"/>' | |
| + "".join( | |
| f'<line x1="{26 + column * 36}" y1="16" x2="{26 + column * 36}" y2="88" ' | |
| f'stroke="{_MOCK_FAINT}"/>' | |
| for column in (1, 2) | |
| ) | |
| + "".join( | |
| f'<line x1="26" y1="{16 + row * 18}" x2="134" y2="{16 + row * 18}" ' | |
| f'stroke="{_MOCK_FAINT}"/>' | |
| for row in (1, 2, 3) | |
| ) | |
| + "".join( | |
| f'<rect x="{34 + column * 36}" y="22" width="18" height="4" rx="2" ' | |
| f'fill="{_MOCK_ACCENT}"/>' | |
| for column in (0, 1, 2) | |
| ) | |
| ), | |
| # A browser: chrome, a hero block, two columns. | |
| "web": ( | |
| f'<rect x="20" y="14" width="120" height="76" rx="4" fill="var(--c-surface)" ' | |
| f'stroke="{_MOCK_FAINT}"/>' | |
| f'<rect x="20" y="14" width="120" height="14" rx="4" fill="var(--c-fill)"/>' | |
| + "".join( | |
| f'<circle cx="{30 + dot * 9}" cy="21" r="2.4" fill="{_MOCK_FAINT}"/>' | |
| for dot in range(3) | |
| ) | |
| + f'<rect x="30" y="38" width="54" height="6" rx="3" fill="{_MOCK_ACCENT}"/>' | |
| + _rows(2, x=30, y=52, gap=8, width=80, short=1) | |
| + '<rect x="30" y="72" width="46" height="10" rx="3" fill="var(--c-mint)"/>' | |
| + '<rect x="84" y="72" width="46" height="10" rx="3" fill="var(--c-fill)"/>' | |
| ), | |
| # A set of colours, which is what a theme is. | |
| "palette": ( | |
| "".join( | |
| f'<rect x="{24 + column * 30}" y="{22 + row * 30}" width="24" height="24" ' | |
| f'rx="4" fill="{fill}" stroke="{_MOCK_FAINT}"/>' | |
| for row, fills in enumerate( | |
| ( | |
| (_MOCK_ACCENT, "var(--c-sage)", "var(--c-mint)", "var(--c-fill)"), | |
| ("var(--c-text)", "var(--c-text-2)", "var(--c-muted)", "var(--c-surface)"), | |
| ) | |
| ) | |
| for column, fill in enumerate(fills) | |
| ) | |
| ), | |
| # Numbered steps. | |
| "list": ( | |
| f'<rect x="30" y="10" width="100" height="84" rx="3" fill="var(--c-surface)" ' | |
| f'stroke="{_MOCK_FAINT}"/>' | |
| + "".join( | |
| f'<circle cx="44" cy="{26 + row * 20}" r="5" fill="none" ' | |
| f'stroke="{_MOCK_ACCENT}" stroke-width="1.5"/>' | |
| f'<rect x="56" y="{24 + row * 20}" width="{58 - row * 10}" height="3" rx="1.5" ' | |
| f'fill="{_MOCK_FAINT}"/>' | |
| for row in range(4) | |
| ) | |
| ), | |
| # A short note, torn from a pad. | |
| "note": ( | |
| f'<path d="M40 12 h80 v66 l-12 12 h-68 z" fill="var(--c-surface)" ' | |
| f'stroke="{_MOCK_FAINT}"/>' | |
| f'<path d="M120 78 h-12 v12 z" fill="var(--c-fill)" stroke="{_MOCK_FAINT}"/>' | |
| f'<rect x="50" y="26" width="38" height="5" rx="2" fill="{_MOCK_ACCENT}"/>' | |
| + _rows(4, x=50, y=40, gap=9, width=60, short=3) | |
| ), | |
| # A guide: a heading and bulleted method. | |
| "guide": ( | |
| f'<rect x="32" y="8" width="96" height="88" rx="3" fill="var(--c-surface)" ' | |
| f'stroke="{_MOCK_FAINT}"/>' | |
| f'<rect x="42" y="20" width="52" height="5" rx="2" fill="{_MOCK_ACCENT}"/>' | |
| + "".join( | |
| f'<circle cx="45" cy="{40 + row * 14}" r="2" fill="{_MOCK_ACCENT}"/>' | |
| f'<rect x="53" y="{38 + row * 14}" width="{62 - row * 8}" height="3" rx="1.5" ' | |
| f'fill="{_MOCK_FAINT}"/>' | |
| for row in range(4) | |
| ) | |
| ), | |
| # Looking through a document for something. | |
| "find": ( | |
| f'<rect x="30" y="10" width="86" height="80" rx="3" fill="var(--c-surface)" ' | |
| f'stroke="{_MOCK_FAINT}"/>' | |
| + _rows(5, x=40, y=26, gap=12, width=62, short=4) | |
| + '<rect x="40" y="48" width="40" height="7" rx="2" fill="var(--c-mint)"/>' | |
| + f'<circle cx="112" cy="70" r="17" fill="var(--c-surface)" stroke="{_MOCK_ACCENT}" ' | |
| f'stroke-width="2.5"/>' | |
| + f'<line x1="124" y1="82" x2="134" y2="92" stroke="{_MOCK_ACCENT}" ' | |
| f'stroke-width="2.5" stroke-linecap="round"/>' | |
| ), | |
| # An answer, which is what a calculation gives back. | |
| "value": ( | |
| f'<rect x="34" y="24" width="92" height="52" rx="6" fill="var(--c-surface)" ' | |
| f'stroke="{_MOCK_FAINT}"/>' | |
| f'<rect x="46" y="36" width="26" height="4" rx="2" fill="{_MOCK_FAINT}"/>' | |
| f'<rect x="46" y="48" width="52" height="12" rx="3" fill="{_MOCK_ACCENT}"/>' | |
| ), | |
| "generic": ( | |
| f'<rect x="38" y="12" width="84" height="80" rx="3" fill="var(--c-surface)" ' | |
| f'stroke="{_MOCK_FAINT}"/>' + _rows(5, x=50, y=30, gap=11, width=60, short=4) | |
| ), | |
| }.get(kind) | |
| if body is None: | |
| body = "" | |
| return ( | |
| '<svg class="c-libcard__mock" viewBox="0 0 160 104" role="img" ' | |
| 'aria-hidden="true" preserveAspectRatio="xMidYMid meet">' | |
| f"{body}</svg>" | |
| ) | |
| #: Tails that belong to the model rather than the reader. A library member's | |
| #: description is written for tool selection, so it carries the argument list | |
| #: and the provenance note; a card is read by a person deciding whether they | |
| #: want the thing at all. | |
| _CARD_TAILS = re.compile( | |
| r"\s*(?:Arguments?|Args|Parameters?)\s*:.*|\s*Adapted from\b.*|\s*Use it (?:when|for|before)\b.*", | |
| re.S | re.I, | |
| ) | |
| def card_summary(description: str, *, limit: int = 150) -> str: | |
| """One sentence a person can scan, from a description written for a model. | |
| THE CARD AND THE MODEL WANT DIFFERENT THINGS FROM THE SAME STRING. | |
| A member's description is the text a model reads to decide whether to call | |
| it, so it is complete on purpose: what the member does, every argument, the | |
| formats each one accepts, and where the skill came from. That is right for | |
| tool selection and wrong for a card. Nine hundred characters clamped to | |
| four lines gives a person a paragraph cut off mid-word, which tells them | |
| less than one clear sentence would. | |
| So the card gets the first sentence with the model's tail removed, and the | |
| description itself is left exactly as it is. Shortening the source would | |
| have made the page tidier by making the tool worse, which is the wrong | |
| trade in a project whose members are the point. | |
| """ | |
| text = " ".join(str(description or "").split()) | |
| text = _CARD_TAILS.sub("", text).strip() | |
| if not text: | |
| return "" | |
| # First sentence, but only where a full stop really ends one. "e.g." and | |
| # a version number are not sentence boundaries; a trailing capital is, so | |
| # "written as YYYY-MM-DD." ends the sentence it looks like it ends. | |
| match = re.search(r"(?<!\be\.g)(?<!\bi\.e)(?<!\d)\.(?:\s|$)", text) | |
| if match and match.start() >= 40: | |
| text = text[: match.start() + 1] | |
| if len(text) > limit: | |
| cut = text.rfind(" ", 0, limit) | |
| text = text[: cut if cut > 40 else limit].rstrip(" ,;:") + "…" | |
| return text | |
| def library_cards(rows: Sequence[Mapping[str, object]], chosen: Sequence[str]) -> str: | |
| """The library as cards a person reads, not a list of tick boxes. | |
| Every field is escaped: descriptions come from tool specs, which workers | |
| and third-party repositories can influence. The demo image is attached as | |
| ``data-gif`` and only swapped in by the page's own hover script, so a | |
| card with no recording is simply a card, not a broken image. | |
| """ | |
| if not rows: | |
| return empty_state( | |
| glyph="◇", | |
| title="Nothing matches", | |
| body="No library member matches that search. Clear it to see the shelf.", | |
| ) | |
| picked = set(chosen) | |
| cards = [] | |
| for row in rows: | |
| ref = str(row.get("ref", "")) | |
| kind = str(row.get("kind", "tool")) | |
| name = str(row.get("name", ref)) | |
| author = str(row.get("author", "distinct")) | |
| description = str(row.get("description", "")) | |
| # Every card carries one, because a shelf where some members have a | |
| # picture and some do not reads as a shelf where some are broken. | |
| output = _member_output(ref) | |
| media = ( | |
| f'<figure class="c-libcard__media c-libcard__media--{esc(output)}">' | |
| f"{_mockup(output)}" | |
| f'<figcaption class="c-visually-hidden">Makes a {esc(output)}</figcaption>' | |
| "</figure>" | |
| ) | |
| on = ref in picked | |
| # The card itself is the control: role, state and keyboard focus are | |
| # its own, and the check mark is drawn by the stylesheet from the | |
| # ``is-on`` class so the page script and this renderer cannot | |
| # disagree about what selected looks like. | |
| cards.append( | |
| f'<article class="c-libcard c-libcard--{esc(kind)}{" is-on" if on else ""}"' | |
| f' data-ref="{esc(ref)}" role="button" tabindex="0"' | |
| f' aria-pressed="{"true" if on else "false"}"' | |
| f' aria-label="{esc(name)}: use as a default">' | |
| f'<span class="c-libcard__check" aria-hidden="true"></span>' | |
| f"{media}" | |
| '<div class="c-libcard__head">' | |
| f'<span class="c-libcard__kind c-libcard__kind--{esc(kind)}">{esc(kind)}</span>' | |
| "</div>" | |
| f'<h3 class="c-libcard__name">{esc(name)}</h3>' | |
| f'<p class="c-libcard__author">by {esc(author)}</p>' | |
| f'<p class="c-libcard__desc">{esc(card_summary(description))}</p>' | |
| f'<code class="c-libcard__ref">{esc(ref)}</code>' | |
| "</article>" | |
| ) | |
| return '<div class="c-libgrid">' + "".join(cards) + "</div>" | |
| # -------------------------------------------------------------------------- | |
| # Better Images of AI: the artwork set, and attribution that cannot drift | |
| # -------------------------------------------------------------------------- | |
| # | |
| # THE SET. Lone Thomasky and Bits&Baeume's collection for Better Images of AI: | |
| # photographs of landscapes overwritten with digital distortion, made to show | |
| # the extraction, water use and land use that sit behind AI infrastructure. It | |
| # is the right set for this product because the product's only claim is about | |
| # physical cost, and because the collection contains no robot, no brain, no | |
| # wireframe head and no blue glow. The distortion is also an unusually apt | |
| # metaphor for what this network is for: the landscape is still legible, but | |
| # something has been done to it that you can see if you look. | |
| # | |
| # LICENSING, AND WHY IT IS STRUCTURAL RATHER THAN CAREFUL. CC BY 4.0 requires | |
| # the artist, a link to the library, a link to the licence deed, and a statement | |
| # of changes, shown every time the image is shown. Failing to attribute | |
| # terminates the licence, and showing artwork A beside artwork B's credit would | |
| # be exactly that failure. | |
| # | |
| # So image and credit are not two values that a caller keeps in step. They are | |
| # one frozen record, and every function that renders an image takes the whole | |
| # record and reads both fields off it. There is no signature anywhere in this | |
| # module that accepts a source without its credit, which is why the two cannot | |
| # separate. ``tests/test_presentation.py`` pins it for every artwork in the set. | |
| # | |
| # The artist and licence half of the credit is identical across the collection | |
| # and is the form the artist's own publisher uses. The title is what makes each | |
| # credit specific, so it is carried per record and rendered first. | |
| class Artwork: | |
| """One artwork, with everything its licence requires, in one object.""" | |
| slug: str | |
| title: str | |
| alt: str | |
| #: Intrinsic dimensions of the served asset, so the browser reserves the | |
| #: right box before the bytes arrive and the splash never reflows. | |
| width: int | |
| height: int | |
| def src(self) -> str: | |
| return f"{_ASSET_BASE}/{self.slug}-1040.webp" | |
| def thumb(self) -> str: | |
| return f"{_ASSET_BASE}/{self.slug}-96.webp" | |
| def plate_available(self) -> bool: | |
| """Whether the splash plate file actually exists on disk.""" | |
| return (_ASSET_DIR / f"{self.slug}-1040.webp").is_file() | |
| def thumb_available(self) -> bool: | |
| return (_ASSET_DIR / f"{self.slug}-96.webp").is_file() | |
| def credit_html(self) -> str: | |
| """The exact credit line for *this* artwork. | |
| Built from the record rather than stored as prose so a new artwork | |
| cannot be added with another artwork's credit pasted onto it. | |
| """ | |
| return ( | |
| f"{escape(self.title, quote=True)}. Lone Thomasky & Bits&Bäume / " | |
| '<a href="https://betterimagesofai.org" target="_blank" ' | |
| 'rel="noopener noreferrer">Better Images of AI</a> / ' | |
| '<a href="https://creativecommons.org/licenses/by/4.0/" target="_blank" ' | |
| 'rel="noopener noreferrer">CC BY 4.0</a>. Resized for display; no artistic ' | |
| "modification." | |
| ) | |
| #: Served from this repository rather than hotlinked. Redistribution is | |
| #: permitted by CC BY 4.0 with attribution, and self-hosting is what lets the | |
| #: payload be honest: each file is resized to the box it is displayed in and | |
| #: converted to WebP, so the landing page of a product about energy does not | |
| #: quietly ship six full-resolution PNGs from someone else's bandwidth. | |
| #: | |
| #: The directory the files actually live in, resolved absolutely for the same | |
| #: reason ``gr.set_static_paths`` is given an absolute path in ui.py: a | |
| #: relative URL path resolves against the process working directory, which is | |
| #: the repository root under app.py but not under pytest or scripts run from | |
| #: elsewhere. The two halves previously disagreed (absolute registration, | |
| #: relative URL), so the images broke whenever the server was started from any | |
| #: other directory even with the files present. | |
| _ASSET_DIR = (Path(__file__).resolve().parent.parent / "assets" / "artwork") | |
| _ASSET_BASE = f"/gradio_api/file={_ASSET_DIR.as_posix()}" | |
| ARTWORKS: tuple[Artwork, ...] = ( | |
| Artwork( | |
| slug="distorted-forest-path", | |
| title="Distorted Forest Path", | |
| alt=( | |
| "Aerial photograph of a small hut and a concrete path through dense green " | |
| "forest, broken up by bands of digital distortion." | |
| ), | |
| width=1280, | |
| height=1806, | |
| ), | |
| Artwork( | |
| slug="distorted-lake-trees", | |
| title="Distorted Lake Trees", | |
| alt=( | |
| "Aerial photograph of a small yellow aeroplane over a lake threaded with trees " | |
| "and cloud, broken up by bands of digital distortion." | |
| ), | |
| width=1280, | |
| height=1806, | |
| ), | |
| Artwork( | |
| slug="distorted-fish-school", | |
| title="Distorted Fish School", | |
| alt=( | |
| "Underwater photograph looking up through blue water at a circling school of " | |
| "fish, broken up by bands of digital distortion." | |
| ), | |
| width=1280, | |
| height=1806, | |
| ), | |
| Artwork( | |
| slug="distorted-dandelions", | |
| title="Distorted Dandelions", | |
| alt=( | |
| "Close photograph of dandelion seed heads, broken up by bands of digital " | |
| "distortion." | |
| ), | |
| width=1280, | |
| height=1806, | |
| ), | |
| Artwork( | |
| slug="distorted-sand-mine", | |
| title="Distorted Sand Mine", | |
| alt=( | |
| "Aerial photograph of an orange sand mine with transport lorries, broken up by " | |
| "bands of digital distortion." | |
| ), | |
| width=1280, | |
| height=1806, | |
| ), | |
| Artwork( | |
| slug="distorted-lava-flow", | |
| title="Distorted Lava Flow", | |
| alt="Photograph of a lava flow, broken up by bands of digital distortion.", | |
| width=1280, | |
| height=1806, | |
| ), | |
| ) | |
| def choose_artwork(seed: object = None) -> Artwork: | |
| """Pick one artwork for one page load. | |
| ROTATION MECHANISM, AND WHY THIS ONE. Selection happens once per load and | |
| the chosen image then sits still. There is no timer and no carousel. | |
| A timed crossfade would mean an animation running for as long as the landing | |
| page is open, on a product whose entire claim is that compute costs energy | |
| and that the cost should be stated. A landing page that burns cycles | |
| redrawing itself to look calm is arguing against the thing it is selling. | |
| Per-load selection also makes "only fetch what you show" true by | |
| construction rather than by configuration: exactly one artwork reaches the | |
| markup, so exactly one is requested. A crossfade needs at least two decoded | |
| before the first frame; a carousel needs all six. | |
| The set is still seen, just across visits rather than within one. | |
| Only artworks whose plate file exists on disk are rotated. A checkout that | |
| has not run ``scripts/fetch_artwork.py`` (or has fetched only some of the | |
| set) must never emit an ``<img>`` that resolves to nothing beside a credit | |
| for a work that is not being displayed; :func:`splash_figure` carries the | |
| same guard for the case where nothing at all is available. | |
| """ | |
| candidates = tuple(art for art in ARTWORKS if art.plate_available) or ARTWORKS | |
| if seed is None: | |
| return _secrets.choice(candidates) | |
| return candidates[hash(str(seed)) % len(candidates)] | |
| def credit(artwork: Artwork, *, compact: bool = False) -> str: | |
| """Thumbnail and required credit for ``artwork``, read from one record. | |
| When the thumbnail file is absent the credit is not rendered at all: | |
| publishing an attribution for a work that is not being displayed is the | |
| licence failure this module exists to prevent, in the other direction. | |
| """ | |
| if not artwork.thumb_available: | |
| return "" | |
| modifier = " c-credit--compact" if compact else "" | |
| return ( | |
| f'<figure class="c-credit{modifier}">' | |
| f'<img class="c-credit__img" src="{esc(artwork.thumb)}" alt="{esc(artwork.alt)}" ' | |
| 'width="96" height="60" loading="lazy" decoding="async" />' | |
| f'<figcaption class="c-credit__text">{artwork.credit_html}</figcaption>' | |
| "</figure>" | |
| ) | |
| def footer(artwork: Optional[Artwork] = None) -> str: | |
| """Attribution, anchored to the page rather than floating mid-layout.""" | |
| return f'<footer class="c-footer">{credit(artwork or ARTWORKS[0], compact=True)}</footer>' | |
| # -------------------------------------------------------------------------- | |
| # Splash | |
| # -------------------------------------------------------------------------- | |
| def _safe_url(value: object) -> str: | |
| """Return ``value`` only if it is an ordinary https URL, else empty. | |
| The first URL in this module that comes from data rather than from a | |
| literal. :func:`esc` makes a string safe to *place* in an attribute but does | |
| not make its scheme safe, so ``javascript:`` would survive escaping intact. | |
| Validating the scheme here is what keeps that out of an ``href``, and the | |
| parser-based test in ``tests/test_presentation.py`` checks the result. | |
| """ | |
| text = "" if value is None else str(value).strip() | |
| return text if text.lower().startswith("https://") else "" | |
| # -------------------------------------------------------------------------- | |
| # Environmental rubric: grades, and the absences that are not grades | |
| # -------------------------------------------------------------------------- | |
| # | |
| # One rule governs this whole surface, and it is the same rule as the energy | |
| # panel: a missing assessment is not a bad assessment. Rendering "no published | |
| # evidence" as an F or a D would state a measured poor result where none exists, | |
| # which is the grade-sheet equivalent of counting an unmeasured run as zero. | |
| # | |
| # So the not-assessed marker differs from a grade in shape, fill, case and | |
| # wording, not in colour: a dashed lozenge carrying the words "not assessed", | |
| # never a letter. Every grade letter, meanwhile, renders identically to every | |
| # other. There is no green A and no red D, partly because the palette has one | |
| # hue and partly because colour-coding the letters would imply the very reading | |
| # the legend exists to prevent, that a high letter means a low impact. | |
| #: The two scales. They are different questions with different answers and a | |
| #: reader who conflates them draws exactly the wrong conclusion, so each token | |
| #: carries its own scale name inside it rather than relying on a column header | |
| #: that may be scrolled away, screenshotted off, or read past. | |
| #: Method words this surface knows, and the modifier each one paints with. | |
| #: A word outside this map is rendered verbatim but styled as unknown rather | |
| #: than silently promoted into one of the confident states. | |
| _METHOD_SLUGS: Mapping[str, str] = { | |
| "Measured": "measured", | |
| "Modelled": "modelled", | |
| "Proxy-based": "proxy", | |
| } | |
| def figure_token( | |
| *, | |
| value: str = "", | |
| unit: str = "", | |
| status: str = "", | |
| absent_word: str = "Missing", | |
| ) -> str: | |
| """One published figure, or one explicit absence, as one indivisible unit. | |
| This replaces the letter grade that used to sit here, and the replacement is | |
| the point rather than a restyling. A letter was this catalogue's ranking of | |
| somebody else's number; a figure is the number. Three rules survive from the | |
| grade token because they were never about letters: | |
| **An absence is never a low value.** Missing is a dashed lozenge carrying a | |
| word, differing from a figure in shape, fill and content. Nobody measured it, | |
| so nothing may be drawn that looks like a small result. | |
| **A figure never appears without its method.** "54 MWh" measured at the | |
| socket and "54 MWh" inferred from a chip's rated wattage are different | |
| claims, and a method printed as a caption beside the number can be cropped, | |
| skimmed, or read as belonging to the next row. One token, one border. | |
| **Nothing is computed here.** Value, unit and method are passed straight | |
| through. There is no code path that could derive one from the others. | |
| """ | |
| text = str(value).strip() | |
| if not text: | |
| word = esc(str(absent_word).strip() or "Missing") | |
| return ( | |
| '<span class="c-fig c-fig--none">' | |
| f'<span class="c-fig__word">{word}</span></span>' | |
| ) | |
| method = str(status).strip() | |
| slug = _METHOD_SLUGS.get(method, "unknown") | |
| shown = f"{text} {unit}".strip() if str(unit).strip() else text | |
| return ( | |
| f'<span class="c-fig c-fig--{esc(slug)}">' | |
| f'<span class="c-fig__value">{esc(shown)}</span>' | |
| f'<span class="c-fig__method">{esc(method or "method not stated")}</span>' | |
| "</span>" | |
| ) | |
| def _source_row(entry: Mapping[str, object]) -> str: | |
| """One area's working: what the note says, and where the number came from.""" | |
| label = esc(str(entry.get("label") or "")) | |
| note = str(entry.get("note") or "") | |
| href = _safe_url(entry.get("source_url")) | |
| cite = ( | |
| f'<a class="c-source__link" href="{esc(href)}" target="_blank" ' | |
| 'rel="noopener noreferrer">primary source</a>' | |
| if href | |
| else "" | |
| ) | |
| body = esc(note) if note else "No note recorded." | |
| return ( | |
| '<p class="c-source"><span class="c-source__label">' | |
| f"{label}</span><span class=\"c-source__body\">{body} {cite}</span></p>" | |
| ) | |
| def model_evidence_card( | |
| *, | |
| name: str, | |
| coverage: str = "", | |
| summary: str = "", | |
| covers: str = "", | |
| categories: Sequence[Mapping[str, object]] = (), | |
| links: Sequence[Mapping[str, str]] = (), | |
| note: str = "", | |
| ) -> str: | |
| """One model release, showing what was published about it and nothing else. | |
| Every area is always present. An area with no published result renders the | |
| word rather than being dropped, because a six-row card missing three rows | |
| reads as a model with three areas rather than a model with three unknowns. | |
| The workings sit behind a disclosure rather than on the face of the card: | |
| six notes and six citations inline would bury the figures, and hiding them | |
| entirely would make the figures unverifiable. Complete, one click away. | |
| """ | |
| rows = "".join( | |
| '<p class="c-grade-row">' | |
| f'<span class="c-grade-row__label">{esc(str(entry.get("label") or ""))}</span>' | |
| + figure_token( | |
| value=str(entry.get("value") or ""), | |
| unit=str(entry.get("unit") or ""), | |
| status=str(entry.get("status") or ""), | |
| ) | |
| + "</p>" | |
| for entry in categories | |
| ) | |
| link_html = "".join( | |
| f'<a class="c-grade-card__link" href="{esc(href)}" target="_blank" ' | |
| f'rel="noopener noreferrer">{esc(str(link.get("label") or "Source"))}</a>' | |
| for link in links | |
| if (href := _safe_url(link.get("url"))) | |
| ) | |
| sources = "".join(_source_row(entry) for entry in categories) | |
| workings = ( | |
| "<details class=\"c-sources\"><summary class=\"c-sources__summary\">" | |
| "Where these figures come from</summary>" | |
| f'<div class="c-sources__body">{sources}</div></details>' | |
| if sources | |
| else "" | |
| ) | |
| head_coverage = ( | |
| f'<span class="c-grade-card__coverage">{esc(coverage)}</span>' if coverage else "" | |
| ) | |
| return ( | |
| '<article class="c-grade-card">' | |
| '<p class="c-grade-card__head">' | |
| f'<span class="c-grade-card__name">{esc(name)}</span>{head_coverage}</p>' | |
| + (f'<p class="c-grade-card__summary">{esc(summary)}</p>' if summary else "") | |
| + (f'<div class="c-grade-rows">{rows}</div>' if rows else "") | |
| + (f'<p class="c-grade-card__covers"><strong>Covers.</strong> {esc(covers)}</p>' if covers else "") | |
| + workings | |
| + (f'<p class="c-grade-card__note">{esc(note)}</p>' if note else "") | |
| + (f'<p class="c-grade-card__links">{link_html}</p>' if link_html else "") | |
| + "</article>" | |
| ) | |
| def assessment_legend() -> str: | |
| """What the words mean, and the two readings this surface has to prevent. | |
| The legend used to explain two letter scales and the case where they | |
| disagree. There are no letters now, so it explains the two things a reader | |
| can still get wrong: that Missing is a result, and that a small number is | |
| a good model. | |
| """ | |
| return ( | |
| '<section class="c-legend">' | |
| '<p class="c-legend__title">How to read these</p>' | |
| '<div class="c-legend__pair">' | |
| '<div class="c-legend__scale">' | |
| + figure_token(value="54", unit="MWh", status="Measured") | |
| + '<p class="c-legend__scale-body"><strong>A figure and its method.</strong> ' | |
| "Measured means somebody metered the hardware. Modelled means they calculated " | |
| "it. Numbers are reproduced exactly as published: nothing is converted, scaled " | |
| "or combined.</p>" | |
| "</div>" | |
| '<div class="c-legend__scale">' | |
| + figure_token() | |
| + '<p class="c-legend__scale-body"><strong>Missing is not zero.</strong> ' | |
| "Nobody published a usable result for that area. It is not a low score and not " | |
| "evidence the impact was small. Every area is shown for every model, so an " | |
| "absence is stated rather than quietly omitted.</p>" | |
| "</div>" | |
| "</div>" | |
| '<p class="c-legend__example"><span class="c-legend__example-mark" ' | |
| 'aria-hidden="true">?</span><span><strong>A smaller number is not automatically ' | |
| "a better model.</strong> One OLMo 7B shows zero carbon and zero water because it " | |
| "trained on Finnish hydroelectric power, while still drawing more electricity " | |
| "than any other 7B in its cohort. Another used four times the water of its " | |
| "sibling purely because of where the data centre stood. Read each figure with " | |
| "its area, and both with where the run happened.</span></p>" | |
| '<p class="c-legend__never">Cradle to release. Never added to, and never compared ' | |
| "with, the use-phase energy this network measures per run.</p>" | |
| "</section>" | |
| ) | |
| def assessment_section( | |
| cards: Iterable[str], | |
| *, | |
| warning: str = "", | |
| further_reading: Sequence[Mapping[str, str]] = (), | |
| ) -> str: | |
| """The legend, the assessment set's own caveat, the cards, and the reading. | |
| ``warning`` is the data file's caveat and renders **before** the figures, as | |
| its display contract requires, never in a footnote. | |
| """ | |
| body = "".join(cards) | |
| if not body: | |
| body = empty_state( | |
| glyph="\u25cb", | |
| title="No assessed releases", | |
| body=( | |
| "No model in this catalogue has a published, model-specific assessment " | |
| "recorded here yet. Nothing is shown until one exists." | |
| ), | |
| ) | |
| caution = f'<p class="c-rubric__warning">{esc(warning)}</p>' if warning else "" | |
| reading = "".join( | |
| f'<a class="c-reading__link" href="{esc(href)}" target="_blank" ' | |
| f'rel="noopener noreferrer">{esc(str(item.get("label") or "Source"))}</a>' | |
| for item in further_reading | |
| if (href := _safe_url(item.get("url"))) | |
| ) | |
| tail = ( | |
| '<section class="c-reading"><p class="c-reading__title">Further reading</p>' | |
| f'<p class="c-reading__links">{reading}</p></section>' | |
| if reading | |
| else "" | |
| ) | |
| return ( | |
| '<div class="c-rubric">' | |
| + assessment_legend() | |
| + caution | |
| + f'<div class="c-grade-cards">{body}</div>' | |
| + tail | |
| + "</div>" | |
| ) | |
| def splash_copy() -> str: | |
| """The landing screen's left column, above the button. | |
| The display line is set in a variable font at a ``clamp()`` size with | |
| ``font-optical-sizing:auto``, so the browser redraws the letterforms for the | |
| size it lands on rather than scaling one master photographically. That is | |
| the whole of the "dynamic type": the only motion is a single settle on load, | |
| dropped under ``prefers-reduced-motion``. | |
| Type never sits on the photograph. Six images with wildly different colour | |
| would make legibility a per-image gamble, so the copy stays on the canvas | |
| and the plate stays beside it. Constraint first, composition second. | |
| """ | |
| return ( | |
| '<div class="c-splash__head">' | |
| '<p class="c-splash__mark">distinct<span class="c-wordmark__dot">.</span></p>' | |
| '<h1 class="c-splash__display">Small models,<br />' | |
| '<span class="c-splash__display-2">measured energy.</span></h1>' | |
| '<p class="c-splash__lede">Open-weight models run on machines people lend, ' | |
| "with the energy read off a meter on the machine that ran them.</p>" | |
| "</div>" | |
| ) | |
| def splash_meta() -> str: | |
| """The line under the button. Facts, not adjectives.""" | |
| return ( | |
| '<p class="c-splash__meta">Open weights. Session memory only. ' | |
| "Nothing estimated.</p>" | |
| ) | |
| def splash_figure(artwork: Artwork) -> str: | |
| """The plate and its credit, both read off one record. | |
| ``loading="eager"`` because this is the only image on the page and it is | |
| above the fold; deferring it would trade bytes for a visible gap. Intrinsic | |
| dimensions are declared so the box is reserved before the bytes land and the | |
| display line never reflows under the reader. | |
| """ | |
| if not artwork.plate_available: | |
| # No file, no <img>, and critically no credit: a page must never carry | |
| # an attribution for an image it is not showing. The plate becomes a | |
| # plain coloured surface and the checkout instruction takes its place. | |
| return ( | |
| '<figure class="c-splash__figure c-splash__figure--empty">' | |
| '<figcaption class="c-splash__credit">Artwork not fetched on this ' | |
| "checkout. Run scripts/fetch_artwork.py to add the Better Images of AI " | |
| "collection.</figcaption>" | |
| "</figure>" | |
| ) | |
| return ( | |
| '<figure class="c-splash__figure">' | |
| f'<img class="c-splash__img" src="{esc(artwork.src)}" alt="{esc(artwork.alt)}" ' | |
| f'width="{esc(artwork.width)}" height="{esc(artwork.height)}" ' | |
| 'loading="eager" decoding="async" />' | |
| f'<figcaption class="c-splash__credit">{artwork.credit_html}</figcaption>' | |
| "</figure>" | |
| ) | |