@@ -131,7 +131,7 @@ def validate_request(req):
131131 if not isinstance(it, dict):
132132 raise Fail("BAD_REQUEST", f"item {n} is not an object")
133133 clean.append({"i": n, "title": _trim(it.get("title"), 120), "url": _trim(it.get("url"), 300),
134− "description": _trim(it.get("description"), 300)})
134+ "description": _trim(it.get("description"), 500)})
135135 payload["items"] = clean
136136 for key in ("siblingTitles", "mustDifferFrom"):
137137 payload[key] = [_trim(t, 60) for t in payload.get(key) or [] if isinstance(t, str)][:20]
@@ -186,6 +186,20 @@ def schema_path(name):
186186 return path if os.path.isfile(path) and os.path.getsize(path) > 0 else None
187187
188188
189+# How much of each page's text to send, most first: when a batch doesn't fit the budget, the pages' text
190+# is shortened, then dropped, before the host gives up and asks for a smaller batch.
191+DESC_CAPS = (500, 200, 0)
192+
193+
194+def fit(build, n_items):
195+ for cap in DESC_CAPS:
196+ prompt = build(cap)
197+ if prompts.size(prompt) <= CHAR_BUDGET:
198+ return prompt
199+ check_budget(prompt, n_items) # raises OVER_BUDGET with how many items would fit
200+ return prompt
201+
202+
189203def check_budget(prompt, n_items):
190204 size = prompts.size(prompt)
191205 if size > CHAR_BUDGET:
@@ -324,8 +338,7 @@ def op_name(payload, opts):
324338 schema = schema_path("name.json")
325339 if not schema:
326340 raise Fail("SCHEMA_MISSING", f"fm could not write {os.path.join(SCHEMAS, 'name.json')}")
327− prompt = prompts.build_name_prompt(payload, strict=opts.get("strict", False))
328− check_budget(prompt, len(payload["items"]))
341+ prompt = fit(lambda cap: prompts.build_name_prompt(payload, strict=opts.get("strict", False), desc_cap=cap), len(payload["items"]))
329342 try:
330343 out = run_fm(prompt, schema, opts["model"], opts["timeout_s"])
331344 except Fail as f:
@@ -341,8 +354,7 @@ def op_organize(payload, opts):
341354 schema = schema_path("topics.json")
342355 if not schema:
343356 raise Fail("SCHEMA_MISSING", f"fm could not write {os.path.join(SCHEMAS, 'topics.json')}")
344− prompt = prompts.build_topics_prompt(payload, strict=opts.get("strict", False))
345− check_budget(prompt, len(payload["items"]))
357+ prompt = fit(lambda cap: prompts.build_topics_prompt(payload, strict=opts.get("strict", False), desc_cap=cap), len(payload["items"]))
346358 try:
347359 out = run_fm(prompt, schema, opts["model"], opts["timeout_s"])
348360 except Fail as f: