lmjtfy.git / apps / lmjtfy / wrangler.toml
1name = "lmjtfy"
2main = "build/index.js"
3compatibility_date = "2026-09-01"
4# The site is https://lmjtfy.fun, bare (the owner's domain, on Cloudflare,
5# 2026-10-03). It began at https://lmjtfy.deizel.workers.dev, which stays on,
6# and www.lmjtfy.fun is attached, only so the Worker can send their
7# visitors, link previews and clones on with a permanent redirect (`moved` in
8# src/lib.rs). No per-version preview addresses beside them.
9workers_dev = true
10preview_urls = false
11routes = [
12  { pattern = "lmjtfy.fun", custom_domain = true },
13  { pattern = "www.lmjtfy.fun", custom_domain = true },
14]
15
16[build]
17command = "worker-build --release"
18
19[vars]
20# A pinned model: jev-protocol refuses aliases, because the answers behind an
21# alias change without a change here.
22JEV_MODEL = "jev-1.13.0"
23# The LLM that writes Jev's questions: the cheapest candidate that passed
24# every case of tools/eval (2026-10-02: 14/14, about 16 neurons a call; the
25# one cheaper model, granite-4.0-h-micro, passed 11). Rerun the eval before
26# changing it.
27LLM_MODEL = "@cf/qwen/qwen3-30b-a3b-fp8"
28# The most all visitors together may spend on Jev in a UTC day, in dollars.
29# The LLM's own budget is not set here: it is Workers AI's free allocation
30# (llm::FREE_NEURONS_PER_DAY). A dollar is about 25,000 requests at
31# $0.00004 each (the owner, 2026-10-02: "they will never hit it anyway").
32JEV_DOLLARS_PER_DAY = "1"
33
34# Workers AI. There is no local emulation: `wrangler dev` calls the real
35# models on the real account, so it needs the account's token
36# (`lmjtfy-wrangler`, from the devshell).
37[ai]
38binding = "AI"
39
40# The day's budgets, shared by every visitor (src/meter.rs).
41[[durable_objects.bindings]]
42name = "BUDGET"
43class_name = "Budget"
44
45# Every request that was answered, and what people asked (src/archive.rs).
46# It also makes the calls, so the same request is never sent twice.
47[[durable_objects.bindings]]
48name = "ARCHIVE"
49class_name = "Archive"
50
51[[migrations]]
52tag = "v1"
53new_sqlite_classes = ["Budget"]
54
55[[migrations]]
56tag = "v2"
57new_sqlite_classes = ["Archive"]
58
59# The key is a secret, not a var. Declaring it makes `wrangler dev` read it
60# from the process environment (op-env-run puts it there) and makes
61# `wrangler deploy` refuse if the deployed Worker lacks it.
62[secrets]
63required = [
64  "LMJTFY_TYPESAFE_API_KEY",
65  # For the account's real Workers AI usage (src/meter.rs): a token that can
66  # read analytics and nothing else, and the account it reads. A dev server
67  # without them counts only itself, and says so on the page.
68  "CLOUDFLARE_ANALYTICS_TOKEN",
69  "CLOUDFLARE_ACCOUNT_ID",
70  # For `git clone <site>/lmjtfy.git` (src/clone.rs): a GitHub fine-grained
71  # token with Contents: read on deizel/lmjtfy and deizel/jevcrates and no
72  # other permission. A dev server without it answers clones with 503.
73  "LMJTFY_GITHUB_TOKEN",
74]
75
76# Cloudflare's own record of what the Worker did (the owner, 2026-10-02):
77# every invocation logged, with what it logged, and every request traced
78# (fetches, Durable Object calls, the handler). Kept in the account's
79# dashboard: logs 3 days (Workers Free: 200,000 events a day), traces 7 days.
80# Traces count towards Cloudflare Observability billing from 2026-12-01;
81# lower `head_sampling_rate` before then if they would.
82[observability]
83enabled = true
84
85[observability.logs]
86enabled = true
87invocation_logs = true
88head_sampling_rate = 1
89
90[observability.traces]
91enabled = true
92head_sampling_rate = 1