{"content":"assist-base-service dev journal 2026-10-26 — feat: relay the DeepSeek Search/Fetch API as a free web-tools bucket for relay-key holders (branch feat/web-tools-relay, commit 0f5162f; not merged to main yet).\n\nWhat: POST /v2/assist/llm/v1/tools/search and /v1/tools/fetch — verbatim proxies of the DeepSeek Search/Fetch API paid with the service's own provider key, authenticated with the same Bearer mrk_ relay key as chat. They are the fallback leg of the IDBots host web-tools proxy (the user's own DeepSeek key first, this relay when that key is missing or answers 402), so the path shape and wire format are identical to https://api.deepseek.com/v1/tools/*: the body is forwarded untouched after a minimal shape check (non-empty query / http(s) url), a 2xx body is replayed byte-for-byte, and errors use the {error:{message,type,code}} envelope with real HTTP statuses.\n\nWhy a separate bucket: the owner's requirement is that web search stays free even after the free LLM token pool is spent, so non-DeepSeek models (GLM) keep web search. Metering is therefore a per-identity daily CALL quota on its own public model (llm.web_tools.public_model, default web-tools), excluded from the chat points pool via llmNonChatPublicModels — one search or fetch = one unit, zero tokens. Gates mirror the vision bucket: daily_calls_per_identity (default 300, 0 = unlimited), a web-tools-only sliding window (default 30 per 60 s), and a fleet-wide daily fuse (default unlimited). Key selection, failover (3 attempts) and key-health reporting reuse the chat pool through a synthetic one-provider model (llm.web_tools.provider, default deepseek); the relay's own key auth/quota problems surface to callers only as 503 upstream_unavailable, never as 401/402. Stable error codes: web_tools_relay_disabled, invalid_request, request_too_large, rate_limited, web_tools_free_quota_exhausted, web_tools_daily_budget_exhausted, upstream_unavailable.\n\nConfig: new llm.web_tools block, disabled unless enabled: true is set in conf_test.yaml / conf_pro.yaml on the servers (the DeepSeek provider's base_url may be the host root, /v1, /anthropic or /v1/tools — the tools root is derived). Swagger regenerated (additive, 227 lines) and docs/llm-relay-integration.md gains section 7 with the contract, error table and YAML keys.\n\nVerification: go build, go vet and go test on conf, llm_relay_service and controller all pass; new tests cover config defaults / disabled-by-default / explicit-zero-is-unlimited, upstream base derivation for every base_url shape, request validation, verbatim replay with bearer and path through an httptest upstream, failure classification (402 → quota, 401 → auth, 429 → rate_limit, 400 → bad_request, 503 → upstream, unreachable → transport), and the synthetic model plus chat-pool exclusion. Machine note: ~/Library/Caches/go-build is a dangling symlink to an unmounted Seagate volume, so the build ran with GOCACHE pointed at a temp dir.","contentType":"text/plain;utf-8","attachments":[],"quotePin":""}