In automatic mode the scheduler now only summarizes videos published within TAPIR_AUTO_SUMMARIZE_WINDOW (default ~7d). Older videos are still discovered and listed — they keep the manual "Summarize" affordance — but are not auto-processed, so a large back-catalogue (the maintainer's ~256-deep queue) stops self-inflicting 429s against the per-IP caption gate each cycle (UX review B1, recency design). - runner.WithAutoWindow + Stats.SkippedTooOld; tooOld() treats a zero window as disabled and an undated video as never-aged-out (processed, not stranded). - An explicit manual request bypasses the bound even in auto mode (requested videos are loaded in auto mode when a window is active). - Wired through cmdRun, the scheduler's per-user runner, sumStats, and pass logging. config: TAPIR_AUTO_SUMMARIZE_WINDOW (default 168h), .env.example. - Account copy (A7) updated to match: "Automatic summarizes new videos from about the last week; older videos stay browsable — summarize on demand." The rate gate is untouched; the manual path still serialises through it. This bounds auto LOAD, it does not fetch harder. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
77 lines
4.0 KiB
Bash
77 lines
4.0 KiB
Bash
# Tapir — Stage-0 demo configuration. Copy to .env, fill in, and:
|
|
# set -a && . ./.env && set +a
|
|
# No secrets are committed. At demo time, source secret values from op
|
|
# (e.g. `op run -- ./bin/tapir run`) rather than pasting them here.
|
|
#
|
|
# Required-by-command:
|
|
# tapir auth : TAPIR_YT_CLIENT_ID, TAPIR_YT_CLIENT_SECRET, TAPIR_YT_TOKEN_REF, TAPIR_SECRETS_FILE
|
|
# tapir run : the above + TAPIR_USER_ID, TAPIR_GATEWAY_URL, TAPIR_SUMMARIZER_MODEL, TAPIR_DB_DSN
|
|
|
|
# --- identity -------------------------------------------------------------
|
|
# The Tapir user this run operates as. MUST be a UUID (keys the user_id columns).
|
|
TAPIR_USER_ID=
|
|
|
|
# --- local AI gateway (LiteLLM) -------------------------------------------
|
|
# OpenAI-compatible base URL (".../v1"). Default targets the koala NodePort.
|
|
TAPIR_GATEWAY_URL=http://koala:30401/v1
|
|
# Gateway key — sk-local-123 is STALE (401s); resolve LITELLM_MASTER_KEY from op.
|
|
TAPIR_GATEWAY_KEY=
|
|
# Summarization model alias, host/name form. Overridable; pick the final alias
|
|
# when the gateway is reachable. Thinking models (qwen3/deepseek-r1) are viable —
|
|
# the llm client now sends max_tokens=8192.
|
|
TAPIR_SUMMARIZER_MODEL=koala/phi4-mini
|
|
# Bounds a single completion call (Go duration). Generous for slow thinking models.
|
|
TAPIR_SUMMARIZER_TIMEOUT=5m
|
|
|
|
# --- Postgres store -------------------------------------------------------
|
|
# DSN for the store sink; migrations apply on first connect. At demo time:
|
|
# kubectl port-forward the postgres18 service, create a tapir db/role, point here.
|
|
TAPIR_DB_DSN=postgres://tapir:PASSWORD@localhost:5432/tapir?sslmode=disable
|
|
|
|
# --- YouTube OAuth (your registered client) -------------------------------
|
|
# From Google Cloud console; YouTube Data API enabled; your account a test user.
|
|
# The authorized redirect URI must match TAPIR_OAUTH_REDIRECT_ADDR + /callback.
|
|
TAPIR_YT_CLIENT_ID=
|
|
TAPIR_YT_CLIENT_SECRET=
|
|
# Opaque SecretStore reference the refresh token is stored/resolved under.
|
|
TAPIR_YT_TOKEN_REF=youtube/refresh_token
|
|
# host:port the `auth` command binds for the local OAuth redirect listener.
|
|
TAPIR_OAUTH_REDIRECT_ADDR=localhost:8080
|
|
|
|
# --- secret store (Stage-0 stand-in for op/ESO) ---------------------------
|
|
# Path to the 0600 file-backed SecretStore. Defaults to
|
|
# <user-config-dir>/tapir/secrets.json if unset.
|
|
TAPIR_SECRETS_FILE=
|
|
|
|
# --- run loop -------------------------------------------------------------
|
|
# Empty/0 = single pass. Set (e.g. 15m) to poll on that cadence.
|
|
TAPIR_POLL_INTERVAL=
|
|
# How long to wait before re-fetching a transcript that returned HTTP 429
|
|
# (rate_limited). Inside the window the video is skipped without hitting the
|
|
# caption endpoint; after it expires the video is retried. 0 = always retry.
|
|
# Go duration; default 1h.
|
|
TAPIR_FETCH_BACKOFF=
|
|
# Recency bound for AUTO summarization: in automatic mode only videos published
|
|
# within this window of now are summarized; older ones are discovered + listed
|
|
# but wait for a manual "Summarize" (so a back-catalogue doesn't self-inflict
|
|
# 429s). An explicit request bypasses it. Go duration; default 168h (~7d).
|
|
# 0 = no bound (summarize every unseen video).
|
|
TAPIR_AUTO_SUMMARIZE_WINDOW=
|
|
# Minimum interval between outbound caption fetches across the WHOLE process —
|
|
# the shared per-egress-IP rate gate (ADR-014). Scheduler runners and the web
|
|
# "Summarize" click-path serialise through it so they cannot collectively trip
|
|
# 429s. Go duration; default 2s. 0 = unlimited (dev/tests).
|
|
TAPIR_FETCH_RATE=
|
|
|
|
# --- scheduled discovery (tapir serve, ADR-018) ---------------------------
|
|
# When > 0, `serve` runs in-process discovery for ALL users on this cadence
|
|
# (e.g. 2h): one runner pass per user per tick, run-once-on-startup then ticked.
|
|
# Empty/0 = disabled (dev/tests never auto-fetch). SINGLE-REPLICA assumption —
|
|
# >1 replica double-runs discovery. Go duration.
|
|
TAPIR_DISCOVERY_INTERVAL=
|
|
|
|
# --- invitations (tapir invite) -------------------------------------------
|
|
# Public base URL used to build the invite link `tapir invite <email>` prints.
|
|
# Default https://tapir.d-ma.be; no trailing slash needed.
|
|
TAPIR_PUBLIC_URL=
|