v0.24.0: Claude Haiku tag suggestions on propose-RFC (roadmap #27)
The §9.1 Slice-2 AI-suggested tag chips, deferred since the propose modal landed, now wired up. As the propose-RFC draft fills in, the backend asks Claude Haiku for tags drawn ONLY from the corpus's existing tag set (the de-facto taxonomy — v1 tags are free-form chip input, there is no curated list), surfaced as clickable suggestion chips. Nothing auto-applies; the user clicks to add. Backend: - tag_suggest.py: universe gather (distinct corpus tags, most-common first), Haiku prompt + tolerant reply parser (drops invented tags, dedupes, clamps confidence), in-process per-user rate limit. - providers.construct_haiku(): dedicated Haiku provider from the operator key, independent of ENABLED_MODELS — tag suggestion always uses the cheap+fast model. No RFC slug at propose time, so the §6.7 funder path does not apply. - POST /api/rfcs/suggest-tags: contributor-gated, rate-limited. Degrades to an empty list (never an error) when no Anthropic key is bound, the corpus has no tags, or the draft is empty. Frontend: - ProposeModal: debounced suggestion fetch (700ms, stale-response guarded), clickable suggestion chips, and the required inline disclosure that the draft text is sent to Anthropic. - api.suggestTags(): forgiving — any non-OK resolves to []. Tests: 11 new (vertical contributor-gating / filtering / no-key / empty-corpus / 429, plus units for gather, parser tolerance, max, short-circuit, provider-failure). Full suite 351 green. New secret on deploy: ANTHROPIC_API_KEY (see CHANGELOG Upgrade steps). Disclosure copy wants a counsel pass before deploy, per #22 discipline. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -184,6 +184,21 @@ def load_providers(env: dict) -> dict[str, BaseProvider]:
|
||||
return providers
|
||||
|
||||
|
||||
def construct_haiku(api_key: str) -> AnthropicProvider:
|
||||
"""A dedicated Claude Haiku provider, independent of the
|
||||
`ENABLED_MODELS` chat-picker universe.
|
||||
|
||||
The §9.1 tag-suggestion surface (roadmap #27) always wants the
|
||||
cheap + fast model regardless of which models the operator surfaces
|
||||
in the §8.12 picker, so it constructs Haiku directly from the
|
||||
operator's Anthropic key rather than going through `load_providers`.
|
||||
The model id is sourced from the same `_CLAUDE_VARIANTS` table the
|
||||
picker uses, so a model-string bump lands in one place.
|
||||
"""
|
||||
model, name = _CLAUDE_VARIANTS["claude-haiku"]
|
||||
return AnthropicProvider(api_key=api_key, model=model, display_name=name)
|
||||
|
||||
|
||||
def load_from_config(config) -> dict[str, BaseProvider]:
|
||||
"""Convenience adapter so callers can pass our Config dataclass directly."""
|
||||
env = {
|
||||
|
||||
Reference in New Issue
Block a user