smarter: factual-model routing (beh-10), fetch_url main-content extraction + 8k cap (url-08), get_weather via met.no (spec-016)

This commit is contained in:
Oleksandr Kozachuk
2026-07-17 19:15:18 +02:00
parent f8b9bc75ee
commit e0b97363c9
11 changed files with 404 additions and 6 deletions
+9
View File
@@ -73,3 +73,12 @@ plain names keep matching exactly as before. DMs are never ignored.
the ignore check sat only in `respond()`, after the classifier —
emoji reactions leaked into ignored channels, and matching was
exact-name only.)
### BEH-10 — Factual questions may use a stronger model (coverage: test)
With `factual-model` configured, a message the classifier tagged
`factual` (BEH-05) is answered by that model instead of `model`
opening hours, release dates, news lookups get the stronger tier
while small talk stays on the cheap default. Unset = no change. The
`retry-model` override still wins on retry, and vision inputs keep
using `model-vision`.
+11
View File
@@ -58,3 +58,14 @@ Each fetch increments a per-user daily counter; over
`url-daily-per-user` (default 20) `fetch_url` refuses with an error
result. The budget gate (SAF-04) still applies to the surrounding
model calls.
### URL-08 — Main-content extraction (coverage: test)
`fetch_url` text drops page chrome: content inside
`nav`/`header`/`footer`/`aside`/`form`/`select`/`button` is skipped
like scripts, and text blocks dominated by link text (over 60 % of a
block's characters inside `<a>` and the block shorter than 200 chars
— menus, related-article lists, tag clouds) are treated as
boilerplate and removed. Body paragraphs with inline links survive.
The default `url-max-chars` cap rises to 8000 now that the budget is
spent on content, not chrome.
+35
View File
@@ -0,0 +1,35 @@
# SPEC-016 — Weather tool (get_weather)
Both personas talk about weather (the sea over the skerries, rain on
patch day) but had to guess it. `get_weather` grounds that in the
free MET Norway Locationforecast API (api.met.no, User-Agent
required, no key). Locations are host-configured coordinates — the
model picks by name, it never supplies raw URLs, so there is no SSRF
surface (one fixed API host).
### WEA-01 — Tool offered only when configured (coverage: test)
The chat call's tools include `get_weather` only when
`enable-weather` is true AND `weather-locations` (a list of
`[name, lat, lon]` entries) is non-empty. Otherwise it is absent.
### WEA-02 — Compact sanitized forecast (coverage: test)
The tool reduces the MET compact timeseries to: the named location,
current conditions (temperature °C, wind m/s, symbol), and a small
set of forecast points (next hours / tomorrow) with temperature,
symbol and precipitation. Location names pass
`sanitize_external_text`; numbers are numbers. Nothing else from the
API response reaches the prompt.
### WEA-03 — Location matched by name, defaults to first (coverage: test)
The `location` argument matches configured entries
case-insensitively by substring; no or unknown location = the first
configured entry. Coordinates never come from the model.
### WEA-04 — Errors return, never raise; calls are metered (coverage: test)
API/network failures return an `{error}` dict (the responder keeps
running). Each call counts against a per-user daily cap
(`weather-daily-per-user`, default 30) like the other tools.