mirror of
https://github.com/vectorize-io/hindsight.git
synced 2026-09-14 19:31:49 +08:00
a08ec8ddfe
fix(embeddings): send each Gemini input as its own Content Passing a plain `list[str]` to the Google GenAI SDK's `models.embed_content()` reaches the API as several Parts of ONE Content, and the multimodal models (`gemini-embedding-2`+) fuse those into a single vector — the whole batch collapses to one embedding. Verified against the live Gemini API: three texts sent as a `list[str]` come back as 1 vector on `gemini-embedding-2` and `gemini-embedding-2-preview`, and as 3 when each text is its own `Content`. We worked around the fusion by forcing `batch_size = 1` for those models, which kept 1:1 alignment at the cost of one request per text. Since #4039 those requests fan out concurrently through `_encode_batched`, so this was never the ~30s serial stall the original report described — but it still burns one upstream request per fact, which is what runs into per-minute rate limits. Wrapping each text in its own `Content` fixes the cause instead of the symptom: every model returns one vector per input, so the whole batch travels in a single request and the `batch_size = 1` special case (and the model-name sniffing that drove it) goes away. Vectors are byte-identical on `gemini-embedding-001`, so existing embeddings do not need regenerating. - Wrap each input text in a distinct `Content` in `_embed_batch()`. - Drop the forced `batch_size = 1` and `_gemini_model_aggregates_inputs()`. - Add `HINDSIGHT_API_EMBEDDINGS_GEMINI_BATCH_SIZE` (default 100), matching the other providers' configurable batch size. The live `test_gemini_embedding_2_vertexai_one_vector_per_input` test now covers the batched case directly — all three texts go out in one request, which is exactly the shape that used to aggregate. A mocked client cannot prove this; the behaviour lives in the API.
590 lines
39 KiB
Bash
590 lines
39 KiB
Bash
# Hindsight Environment Variables
|
|
# Copy this file to .env and fill in your values
|
|
|
|
# LLM Configuration (Required)
|
|
# Supported providers: openai, openai-responses, groq, ollama, gemini, anthropic, lmstudio, vertexai, minimax, deepseek, zai, atlas, meta, volcano, openai-codex, claude-code, github-copilot
|
|
HINDSIGHT_API_LLM_PROVIDER=openai
|
|
HINDSIGHT_API_LLM_API_KEY=your-api-key-here
|
|
HINDSIGHT_API_LLM_MODEL=gpt-4o-mini
|
|
# HINDSIGHT_API_LLM_BASE_URL=https://api.openai.com/v1
|
|
|
|
# Vision slot — the model used for retain chunks that carry an inline attachment.
|
|
# Only those chunks use it; every text-only chunk stays on the retain LLM, so a
|
|
# bank ingesting the occasional screenshot need not run (or pay for) a vision
|
|
# model on all of its text. Unset, attachments go to the retain LLM as before.
|
|
# HINDSIGHT_API_VLM_PROVIDER=gemini
|
|
# HINDSIGHT_API_VLM_API_KEY=your-vision-api-key
|
|
# HINDSIGHT_API_VLM_MODEL=gemini-2.5-flash
|
|
# HINDSIGHT_API_VLM_BASE_URL=
|
|
# Reasoning effort for providers/models that support it. Examples: none, low, medium, high, xhigh.
|
|
# Set it and the value is sent as given, whatever the model is called — use `none` to stop a
|
|
# self-hosted reasoning model (vLLM, Ollama, llama.cpp, TGI) emitting thinking blocks. Unset,
|
|
# no reasoning parameter is sent at all and each model runs at its own default effort.
|
|
# HINDSIGHT_API_LLM_REASONING_EFFORT=low
|
|
|
|
# Sampling temperature for internal LLM calls. Set a number in [0.0, 2.0], or `none`
|
|
# to omit the temperature parameter entirely (required for models that reject explicit
|
|
# temperatures, e.g. Azure gpt-5.5). The global override below applies to every operation;
|
|
# per-operation overrides (defaults: verification=0.0, retain=0.1, reflect=0.9,
|
|
# consolidation=0.0) take precedence.
|
|
# HINDSIGHT_API_LLM_TEMPERATURE=none
|
|
# HINDSIGHT_API_LLM_TEMPERATURE_VERIFICATION=0.0
|
|
# HINDSIGHT_API_LLM_TEMPERATURE_RETAIN=0.1
|
|
# HINDSIGHT_API_LLM_TEMPERATURE_REFLECT=0.9
|
|
# HINDSIGHT_API_LLM_TEMPERATURE_CONSOLIDATION=0.0
|
|
|
|
# Grammar-enforce structured output (json_schema strict) instead of the soft
|
|
# schema-in-prompt path. Helps weaker self-hosted models that emit prose preambles
|
|
# or invalid JSON. The global override below applies to every operation;
|
|
# per-operation overrides take precedence, in both directions -- set one to false
|
|
# to opt that operation out while the global flag is on.
|
|
# HINDSIGHT_API_LLM_STRICT_SCHEMA=false
|
|
# HINDSIGHT_API_LLM_STRICT_SCHEMA_RETAIN=true
|
|
# HINDSIGHT_API_LLM_STRICT_SCHEMA_REFLECT=true
|
|
# HINDSIGHT_API_LLM_STRICT_SCHEMA_CONSOLIDATION=true
|
|
|
|
# Ceiling on the connect phase (TCP + TLS handshake) of an LLM request, in seconds.
|
|
# Read, write and pool keep the full HINDSIGHT_API_LLM_TIMEOUT budget, so an unreachable
|
|
# endpoint fails fast instead of burning the whole request timeout. 0 disables the cap.
|
|
# HINDSIGHT_API_LLM_CONNECT_TIMEOUT=10
|
|
|
|
# Log level for the httpx/httpcore loggers. DEBUG traces every LLM request through its
|
|
# transport phases (connect_tcp, send_request_headers, receive_response_headers), which
|
|
# is how you tell a request that stalled before being sent from one never answered.
|
|
# HINDSIGHT_API_LLM_HTTP_LOG_LEVEL=WARNING
|
|
|
|
# Some backends, including Bedrock Converse, reject JSON Schema maxItems.
|
|
# Disable it only for those backends; consolidation still enforces the cap.
|
|
# HINDSIGHT_API_LLM_SUPPORTS_MAX_ITEMS=true
|
|
|
|
# Constrain retain's occurred_start/occurred_end to an ISO timestamp with a JSON
|
|
# Schema pattern. Stops grammar-constrained models reasoning inside the timestamp
|
|
# string and burning the whole completion budget. Off by default: backends that
|
|
# validate schemas against an allowlist (Bedrock) reject the keyword with a 400.
|
|
# HINDSIGHT_API_LLM_SUPPORTS_STRING_PATTERN=false
|
|
|
|
# Pin a conversation to one backend prompt cache (OpenAI-compatible providers only).
|
|
# Server-side prompt caches are per backend server, so the same conversation has to
|
|
# reach the same one to hit. Values: auto (default), xai_conv_id (sends xAI's
|
|
# x-grok-conv-id header), openai_prompt_cache_key (sends OpenAI's prompt_cache_key
|
|
# field), none (sends nothing). "auto" picks from the base URL host and is an
|
|
# allowlist: x.ai / grok.com get the header, native OpenAI / openai.com / Azure
|
|
# OpenAI get the field, and every other backend gets nothing. Per-operation
|
|
# overrides take precedence. Set to none to disable entirely.
|
|
# HINDSIGHT_API_LLM_CACHE_AFFINITY=auto
|
|
# HINDSIGHT_API_RETAIN_LLM_CACHE_AFFINITY=none
|
|
# HINDSIGHT_API_REFLECT_LLM_CACHE_AFFINITY=xai_conv_id
|
|
# HINDSIGHT_API_CONSOLIDATION_LLM_CACHE_AFFINITY=none
|
|
|
|
# Ask litellm/litellmrouter/bedrock for structured output via a forced tool call
|
|
# instead of response_format. Enable it for backends that reject response_format
|
|
# outright -- e.g. Bedrock Claude in ap-southeast-2 ("Extra inputs are not permitted");
|
|
# the same model in us-east-1 accepts response_format and needs nothing here.
|
|
# HINDSIGHT_API_LLM_STRUCTURED_OUTPUT_FORCED_TOOL=false
|
|
|
|
# Transport-level output cap for reflect's final synthesis call. Unset = uncapped:
|
|
# the model runs to a natural stop and the reflect/mental-model max_tokens governs
|
|
# visible length via a prompt directive + a post-hoc rewrite (not by truncating the
|
|
# provider call, which on thinking models is eaten by reasoning tokens and cuts pages
|
|
# off mid-word). Set an integer only to enforce a hard cost ceiling on the call.
|
|
# HINDSIGHT_API_REFLECT_MAX_COMPLETION_TOKENS=16000
|
|
|
|
# Diagnostic: on any LLM 4xx, log the exact assembled request ([LLM_4XX_DUMP]) --
|
|
# serialized request config (message bodies stripped) + capped per-message previews.
|
|
# For debugging otherwise-unreproducible rejected calls. Off by default.
|
|
# HINDSIGHT_API_LLM_DEBUG_DUMP_4XX=false
|
|
|
|
# Example: Anthropic Claude configuration
|
|
# HINDSIGHT_API_LLM_PROVIDER=anthropic
|
|
# HINDSIGHT_API_LLM_API_KEY=your-anthropic-api-key
|
|
# HINDSIGHT_API_LLM_MODEL=claude-sonnet-4-20250514
|
|
|
|
# Example: GitHub Copilot subscription via the official Copilot SDK
|
|
# Sign in with Copilot CLI first; no HINDSIGHT_API_LLM_API_KEY is needed.
|
|
# HINDSIGHT_API_LLM_PROVIDER=github-copilot
|
|
# HINDSIGHT_API_LLM_MODEL=gpt-5.6-terra
|
|
|
|
# Example: Google Vertex AI configuration
|
|
# HINDSIGHT_API_LLM_PROVIDER=vertexai
|
|
# HINDSIGHT_API_LLM_MODEL=google/gemini-2.0-flash-001
|
|
# HINDSIGHT_API_LLM_VERTEXAI_PROJECT_ID=your-gcp-project-id
|
|
# HINDSIGHT_API_LLM_VERTEXAI_REGION=us-central1
|
|
# HINDSIGHT_API_LLM_VERTEXAI_SERVICE_ACCOUNT_KEY=/path/to/service-account-key.json # Optional, uses ADC if not set
|
|
|
|
# Example: MiniMax configuration (1M context window)
|
|
# HINDSIGHT_API_LLM_PROVIDER=minimax
|
|
# HINDSIGHT_API_LLM_API_KEY=your-minimax-api-key
|
|
# HINDSIGHT_API_LLM_MODEL=MiniMax-M3 # or MiniMax-M2.7 for the previous generation
|
|
|
|
# Example: OpenAI Responses API (/v1/responses) — reasoning + function tools together
|
|
# HINDSIGHT_API_LLM_PROVIDER=openai-responses
|
|
# HINDSIGHT_API_LLM_API_KEY=your-openai-api-key
|
|
# HINDSIGHT_API_LLM_MODEL=gpt-5.6 # reasoning model (gpt-5.x / o-series); e.g. gpt-5.6-terra
|
|
# HINDSIGHT_API_LLM_REASONING_EFFORT=high # sent alongside tools, unlike chat/completions
|
|
|
|
# Example: DeepSeek configuration (https://api.deepseek.com)
|
|
# HINDSIGHT_API_LLM_PROVIDER=deepseek
|
|
# HINDSIGHT_API_LLM_API_KEY=your-deepseek-api-key
|
|
# HINDSIGHT_API_LLM_MODEL=deepseek-v4-flash # or deepseek-v4-pro / deepseek-chat / deepseek-reasoner
|
|
|
|
# Example: z.ai configuration (Zhipu GLM series, https://z.ai)
|
|
# HINDSIGHT_API_LLM_PROVIDER=zai
|
|
# HINDSIGHT_API_LLM_API_KEY=your-zai-api-key
|
|
# HINDSIGHT_API_LLM_MODEL=glm-4.5-flash # or glm-4.5-air for the paid tier
|
|
|
|
# Example: Atlas Cloud configuration (OpenAI-compatible, https://www.atlascloud.ai)
|
|
# HINDSIGHT_API_LLM_PROVIDER=atlas
|
|
# HINDSIGHT_API_LLM_API_KEY=your-atlascloud-api-key
|
|
# HINDSIGHT_API_LLM_MODEL=deepseek-ai/deepseek-v4-pro # reasoning model; also Qwen / GLM / Kimi / MiniMax, etc.
|
|
|
|
# Example: Meta Model API configuration (Muse Spark, OpenAI-compatible, https://ai.developer.meta.com)
|
|
# HINDSIGHT_API_LLM_PROVIDER=meta
|
|
# HINDSIGHT_API_LLM_API_KEY=your-meta-model-api-key # base_url defaults to https://api.meta.ai/v1
|
|
# HINDSIGHT_API_LLM_MODEL=muse-spark-1.3 # always-reasoning model; reasoning_effort "none" is rejected
|
|
|
|
# Example: LM Studio local configuration (Qwen 2.5 32B recommended)
|
|
# HINDSIGHT_API_LLM_PROVIDER=lmstudio
|
|
# HINDSIGHT_API_LLM_API_KEY=lmstudio
|
|
# HINDSIGHT_API_LLM_BASE_URL=http://localhost:1234/v1
|
|
# HINDSIGHT_API_LLM_MODEL=qwen2.5-32b-instruct
|
|
|
|
# Example: Ollama local configuration (native provider)
|
|
# HINDSIGHT_API_LLM_PROVIDER=ollama
|
|
# HINDSIGHT_API_LLM_BASE_URL=http://localhost:11434/v1
|
|
# HINDSIGHT_API_LLM_MODEL=gemma3:12b
|
|
# Native Ollama context-window override (num_ctx). Leave unset to let Ollama use
|
|
# the model Modelfile / server default; set a positive integer only to force a
|
|
# specific context size (e.g. 16384 to keep the previous request behavior).
|
|
# Setting it also routes free-form calls through Ollama's native /api/chat API,
|
|
# the only endpoint that can carry a context size.
|
|
# HINDSIGHT_API_LLM_OLLAMA_NUM_CTX=16384
|
|
|
|
# Example: OpenAI Codex (ChatGPT Plus/Pro OAuth, no API key)
|
|
# HINDSIGHT_API_LLM_PROVIDER=openai-codex
|
|
# Credentials directory for this provider (the dir holding auth.json). Overrides the
|
|
# process-wide CODEX_HOME. Set it, plus the indexed HINDSIGHT_API_LLM_<n>_CODEX_HOME
|
|
# below, to run two independently authorized ChatGPT profiles in one process.
|
|
# HINDSIGHT_API_LLM_CODEX_HOME=/var/lib/hindsight/codex-a
|
|
|
|
# Multi-LLM strategies: configure extra LLMs by index alongside the primary above,
|
|
# then pick a routing strategy. Unset = single primary LLM (default). Members are
|
|
# numbered from 1; indices must be contiguous. Each operation can override with a
|
|
# RETAIN_/REFLECT_/CONSOLIDATION_ prefix (e.g. HINDSIGHT_API_RETAIN_LLM_1_PROVIDER).
|
|
# HINDSIGHT_API_LLM_1_PROVIDER=groq
|
|
# HINDSIGHT_API_LLM_1_API_KEY=your-groq-api-key
|
|
# HINDSIGHT_API_LLM_1_MODEL=openai/gpt-oss-120b
|
|
# HINDSIGHT_API_LLM_2_PROVIDER=anthropic
|
|
# HINDSIGHT_API_LLM_2_API_KEY=your-anthropic-api-key
|
|
# An openai-codex member can point at its own credentials directory, so a chain of
|
|
# two Codex members fails over between two ChatGPT accounts instead of retrying one.
|
|
# HINDSIGHT_API_LLM_1_PROVIDER=openai-codex
|
|
# HINDSIGHT_API_LLM_1_CODEX_HOME=/var/lib/hindsight/codex-b
|
|
# Strategy JSON: {"mode": "failover"}, {"mode": "round-robin"}, or
|
|
# {"mode": "metadata", "routes": [{"key": "classification", "value": "sensitive", "member": 1}]}.
|
|
# Round-robin accepts optional positive-int "weights" (one per member, primary first).
|
|
# Metadata mode is RETAIN ONLY: each retained item picks a member from its own
|
|
# metadata (first matching route wins; no match uses the primary). It chooses which
|
|
# model extracts a document, not where that document's data can end up -- recall,
|
|
# reflect, consolidation and mental models all keep using the primary.
|
|
# HINDSIGHT_API_LLM_STRATEGY={"mode": "failover"}
|
|
|
|
# API Configuration (Optional)
|
|
HINDSIGHT_API_HOST=0.0.0.0
|
|
HINDSIGHT_API_PORT=8888
|
|
HINDSIGHT_API_LOG_LEVEL=info
|
|
# Vocabulary used for every token count and chunk boundary (recall budgets, chunk
|
|
# sizes, prompt fitting, embedding truncation). o200k_base matches current OpenAI
|
|
# models; set cl100k_base to reproduce the counts Hindsight produced before this
|
|
# default changed. Also bundled: o200k_harmony.
|
|
# HINDSIGHT_API_TOKENIZER_ENCODING=o200k_base
|
|
# Optional retain chunking override for structured logs/transcripts.
|
|
# Unset uses HINDSIGHT_API_RETAIN_CHUNK_SIZE as the structured-chunk limit.
|
|
# HINDSIGHT_API_RETAIN_STRUCTURED_CHUNK_SIZE=
|
|
|
|
# Inline attachments in retain content (content as a list of text/image/file blocks).
|
|
# Whether the configured LLM can read images/files. Unset lets each provider answer for
|
|
# itself; a retain carrying images is refused when the answer is no or unknown.
|
|
# Set true for a vision model behind a gateway Hindsight cannot identify
|
|
# (litellm, ollama, lmstudio, an OpenAI-compatible proxy).
|
|
# HINDSIGHT_API_LLM_VISION=
|
|
# Max decoded size of a single inline attachment, in MB. Default 20.
|
|
# HINDSIGHT_API_RETAIN_ATTACHMENT_MAX_SIZE_MB=20
|
|
# Max inline attachments in one retain item. Default 50.
|
|
# HINDSIGHT_API_RETAIN_ATTACHMENT_MAX_COUNT=50
|
|
# Max attachments in one extraction chunk. retain_chunk_size budgets text only;
|
|
# this is what bounds attachments, matching a provider's per-request limit.
|
|
# Default 8.
|
|
# HINDSIGHT_API_RETAIN_MAX_ATTACHMENTS_PER_CHUNK=8
|
|
|
|
# When true, a retain operation that hit any fact-extraction errors is marked
|
|
# 'failed' (not 'completed'), surfacing silently-dropped facts. Default false.
|
|
# HINDSIGHT_API_FAIL_ON_EXTRACTION_ERRORS=false
|
|
|
|
# Wall-clock ceiling (seconds) for one retain task in the worker. A retain that
|
|
# blocks indefinitely is cancelled and marked 'failed' — and so becomes
|
|
# retryable — instead of holding its worker slot until the process restarts.
|
|
# Set well above your slowest healthy retain; 0 disables. Default 3600.
|
|
# HINDSIGHT_API_RETAIN_WALL_TIMEOUT=3600
|
|
|
|
# Ceiling (seconds) on how long one consolidation task in the worker may run
|
|
# WITHOUT making progress. Every batch that commits restarts the clock, so a large
|
|
# backlog is never cut short — only a stalled job is. A stalled consolidation is
|
|
# cancelled and marked 'failed' — and so becomes retryable, and the reconcile sweep
|
|
# can re-schedule the bank — instead of holding its reserved worker slot until the
|
|
# process restarts. 0 disables. Default 7200.
|
|
# HINDSIGHT_API_CONSOLIDATION_WALL_TIMEOUT=7200
|
|
|
|
# Megabytes of extracted-but-unwritten state ONE retain operation may hold. The chunk
|
|
# batch size bounds how many chunks are in flight, not what they weigh, so this is the
|
|
# figure to size a worker against: peak per retain is roughly this, whatever the document.
|
|
# Budget for HINDSIGHT_API_WORKER_MAX_SLOTS concurrent retains. Over budget, extraction
|
|
# waits for the write path instead of growing. 0 disables. Default 128.
|
|
# HINDSIGHT_API_RETAIN_MEMORY_BUDGET_MB=128
|
|
|
|
# Dry-run extraction preview endpoint (POST /memories/dry-run-extract). Enabled by default; it makes
|
|
# a real LLM call but stores nothing. Set to false to remove the endpoint (returns 404).
|
|
# HINDSIGHT_API_ENABLE_DRY_RUN_EXTRACT=true
|
|
|
|
# Base Path / Reverse Proxy Support (Optional)
|
|
# Set these when deploying behind a reverse proxy with path-based routing
|
|
# Example: To deploy at example.com/hindsight/, set both to "/hindsight"
|
|
# HINDSIGHT_API_BASE_PATH=/hindsight
|
|
# NEXT_PUBLIC_BASE_PATH=/hindsight
|
|
|
|
# Database (Optional - uses embedded pg0 by default)
|
|
# HINDSIGHT_API_DATABASE_URL=postgresql://user:pass@host:5432/db
|
|
# HINDSIGHT_API_READ_DATABASE_URL= # Optional read-replica URL. When set, recall queries (semantic, BM25, graph, temporal) flow through a separate pool against this URL, offloading the primary. Typically points to a read-only endpoint (CNPG's <cluster>-ro service or Aurora reader endpoint).
|
|
# HINDSIGHT_API_MIGRATION_DATABASE_URL= # Direct PostgreSQL URL for migrations (bypasses PgBouncer). Falls back to DATABASE_URL.
|
|
# HINDSIGHT_API_DATABASE_SCHEMA=public # PostgreSQL schema name (default: public)
|
|
# HINDSIGHT_API_DB_MAX_PARALLEL_WORKERS_PER_GATHER= # Optional cap on Postgres planner parallelism for this process's pool connections. Unset leaves the server default; 0 makes background/bulk queries run serially (useful on worker processes sharing a primary with latency-sensitive traffic).
|
|
# HINDSIGHT_API_DB_SESSION_SETUP_ON_ACQUIRE=true # Re-apply the per-connection session settings (statement_timeout, planner parallelism, trigram threshold, vector-search tuning, and the vchord search path) every time a connection is taken from the pool, not just when it is opened. Releasing a connection resets it to the server defaults, so turn this off only when the same settings are pinned on the role/database (ALTER ROLE ... SET) — then it is a pure round trip per acquire, worth reclaiming behind a transaction-mode pooler. On the vchord text-search backend the search path is in that set and losing it fails recall outright, so pin it too. application_name is always re-applied regardless.
|
|
# HINDSIGHT_API_ENTITY_TRGM_SIMILARITY_THRESHOLD=0.15 # Postgres pg_trgm.similarity_threshold applied on every pool connection, used by entity resolution's % trigram match. Must be in (0, 1]. Lower catches more substring-ish matches at higher CPU cost on large entity sets; higher is stricter and cheaper.
|
|
# HINDSIGHT_API_ENTITY_INTRABATCH_MERGE_SIMILARITY=0.5 # Trigram similarity (pg_trgm-equivalent, computed in-memory) at/above which two new names created by the SAME retain are merged into one entity (in-batch dedup of surface-form variants). Must be in (0, 1]. A merge cutoff, stricter than the recall threshold above; raise toward 1.0 to merge only near-identical forms.
|
|
# HINDSIGHT_API_ENTITY_MERGE_MIN_SIMILARITY=0.3 # Minimum trigram similarity a name must have with an EXISTING entity before that entity can be reused for it, whatever the other resolution signals (co-occurrence, recency) say. Must be in (0, 1]. Sits between the recall threshold (0.15) and the in-batch cutoff (0.5). Lower it for corpora of very short names; raise it to merge only clear surface variants.
|
|
# HINDSIGHT_API_RETAIN_ENTITY_RESOLUTION_MAX_CANDIDATES=200 # Max candidates scored per entity mention during retain. The fuzzy lookup keeps only this many best matches per name (ranked by trigram/Jaro-Winkler similarity) before scoring them one by one. On banks holding thousands of near-identical names an uncapped set turns one retain into minutes of CPU that stall the worker's health checks. Raise only if entities that should merge are being duplicated.
|
|
# HINDSIGHT_API_EXTERNALLY_OWNED_ROUTINES= # Comma-separated maintenance discovery routines this deployment installs itself, e.g. mental_models_with_cron,banks_needing_consolidation,schemas_with_expired_rows,schemas_with_expired_operations. Migrations skip anything named here and leave your CREATE OR REPLACE in place; without it the next migration that reinstalls the routine silently overwrites it. Empty (the default) installs every routine as usual. Naming a routine you have not installed leaves it missing, and the maintenance loop then fails loudly on it.
|
|
# HINDSIGHT_API_MIGRATION_CONCURRENCY=1 # Tenant schemas to migrate concurrently (PG only, each in its own process; per-schema work stays sequential). Each worker has ~1-2s startup cost + uses ~3 DB connections, so it only pays off with many schemas (tens+) or slow migrations; keep concurrency*3 <= spare max_connections. Default: 1 (sequential).
|
|
# HINDSIGHT_API_MIGRATION_ISOLATION=auto # Run migrations in a subprocess instead of in the calling process: auto | true | false. auto isolates only on a free-threaded interpreter, where alembic's psycopg2 would otherwise re-enable the GIL for the life of the server process. Default: auto.
|
|
# HINDSIGHT_API_OPERATION_RETENTION_DAYS=30 # Prune terminal operation rows, payloads, and metadata after this many days; 0 (the default) keeps them forever.
|
|
# HINDSIGHT_API_OPERATION_CLEANUP_BATCH_SIZE=1000 # Maximum expired terminal rows deleted per tenant schema in each cleanup cycle; must be positive.
|
|
|
|
# Background maintenance cadences (Optional)
|
|
# Each sweep begins with one cross-tenant discovery call that probes every schema holding the relevant
|
|
# table, in every API/worker process — so its cost scales with tenant count while the work it finds does
|
|
# not. On deployments with thousands of tenants these intervals are the knob to raise.
|
|
# HINDSIGHT_API_RETENTION_SWEEP_INTERVAL_SECONDS=3600 # How often expired audit_log / llm_requests rows are deleted across all tenant schemas. Retention is counted in days, so this only sets how promptly they disappear; 0 disables the sweeps.
|
|
# HINDSIGHT_API_OPERATION_CLEANUP_INTERVAL_SECONDS=900 # How often expired terminal operation rows are pruned; with the batch size above this sets the drain rate for a backlog. 0 disables the job.
|
|
# HINDSIGHT_API_MAINTENANCE_START_JITTER_SECONDS=60 # Upper bound on a random delay before a process runs its FIRST maintenance tick. Every job is due on that tick, so without an offset a fleet started together runs every sweep in every process at once. 0 disables the jitter.
|
|
|
|
# Vector Extension (Optional - uses pgvector by default)
|
|
# Options: "pgvector" (default), "vchord", "pgvectorscale" (DiskANN)
|
|
# HINDSIGHT_API_VECTOR_EXTENSION=pgvector
|
|
|
|
# Let a vector index scan resume until the query's LIMIT is satisfied, instead of
|
|
# stopping when its first candidate list drains (pgvector: hnsw.ef_search, 200) — with
|
|
# it off, a larger recall budget cannot retrieve more rows. Needs pgvector 0.8.0+;
|
|
# older servers reject it and it is dropped automatically. Set false and restart as a
|
|
# quick revert to the previous retrieval depth, with no code change.
|
|
# HINDSIGHT_API_ANN_ITERATIVE_SCAN=true
|
|
# Ceiling on tuples one resumed scan may visit. Bounds the CPU and memory a selective
|
|
# query can spend resuming (filters are applied after the scan, so it resumes often).
|
|
# Lower it to trade depth back for latency. pgvector's own default is 20000.
|
|
# HINDSIGHT_API_ANN_MAX_SCAN_TUPLES=4000
|
|
# For Azure PostgreSQL with DiskANN:
|
|
# HINDSIGHT_API_VECTOR_EXTENSION=pgvectorscale # Auto-detects pg_diskann on Azure
|
|
|
|
# Per-bank vector indexes (pgvector / pgvectorscale / vchord only; ScaNN and Oracle use one global index)
|
|
# HINDSIGHT_API_VECTOR_INDEX_MIN_ROWS=0 # Memories a bank needs in one fact type before that fact type gets its own vector index. 0 (default) turns the threshold OFF: every bank is indexed when it is created, and no background maintenance runs. Set ~10000 on deployments with thousands of banks: every index lives on the shared memory_units table and is planned against by every OTHER bank's queries, so unconditional per-bank indexes put a ceiling on bank count. Smaller banks then use exact search, which is faster AND exact.
|
|
# HINDSIGHT_API_VECTOR_INDEX_MAINTENANCE_MIN_INTERVAL_SECONDS=900 # Shortest gap between two index-maintenance runs for one bank, so a bank hovering at the threshold cannot build and drop the same index repeatedly. Unused while the threshold is off.
|
|
|
|
# Text Search Extension (Optional - uses native PostgreSQL full-text search by default)
|
|
# Unused by a bank with HINDSIGHT_API_ENABLE_TEXT_SEARCH=false (see Recall pipeline stages).
|
|
# Backend options: "native" (default), "vchord", "pg_textsearch", "pgroonga", "pg_search"
|
|
# HINDSIGHT_API_TEXT_SEARCH_EXTENSION=native
|
|
# Native backend dictionary (only used by HINDSIGHT_API_TEXT_SEARCH_EXTENSION=native)
|
|
# HINDSIGHT_API_TEXT_SEARCH_EXTENSION_NATIVE_LANGUAGE=english
|
|
# ParadeDB pg_search tokenizer (only used when creating pg_search BM25 indexes).
|
|
# Empty uses ParadeDB's default tokenizer: unicode_words.
|
|
# Supported values: unicode_words, simple, whitespace, literal, literal_normalized,
|
|
# chinese_compatible, icu, jieba, source_code,
|
|
# chinese_lindera/lindera(chinese), japanese_lindera/lindera(japanese),
|
|
# korean_lindera/lindera(korean), ngram(min,max), edge_ngram(min,max)
|
|
# HINDSIGHT_API_TEXT_SEARCH_EXTENSION_PG_SEARCH_TOKENIZER=
|
|
# ParadeDB pg_search function schema (default: paradedb).
|
|
# Certain managed PostgreSQL distributions install pg_search functions under pgsearch.
|
|
# HINDSIGHT_API_TEXT_SEARCH_EXTENSION_PG_SEARCH_FUNCTION_SCHEMA=paradedb
|
|
# Cap on the number of terms in the native PostgreSQL BM25 tsquery. Long queries
|
|
# OR-join every normalized token, and native ranking (no IDF, re-ranks every
|
|
# match) can then scan a large fraction of the bank and time out. Over the cap,
|
|
# the most selective terms are kept — lowest tenant-wide document frequency, read
|
|
# for free from pg_stats (no reindex). 0 restores the uncapped behavior; the cap
|
|
# bounds only the native backend (other BM25 backends get the raw query).
|
|
# HINDSIGHT_API_BM25_MAX_QUERY_TERMS=16
|
|
# When the cap above trims a query, keep the most selective terms (lowest
|
|
# document frequency, from pg_stats) instead of the first N. true is strictly
|
|
# better for recall at no extra cost when stats exist; set false to opt out of
|
|
# the catalog read and cap by position. Ignored when the cap is 0.
|
|
# HINDSIGHT_API_BM25_SELECTIVE_TERMS=true
|
|
|
|
# File Parser (Optional - uses markitdown by default)
|
|
# HINDSIGHT_API_FILE_PARSER=markitdown
|
|
# Enable image OCR for MarkItDown using an OpenAI-compatible OCR/vision endpoint.
|
|
# These OCR settings are independent from HINDSIGHT_API_LLM_* because MarkItDown
|
|
# uses the OpenAI SDK directly and requires Chat Completions image input support.
|
|
# When OCR is enabled, API_KEY, BASE_URL, and MODEL are required.
|
|
# HINDSIGHT_API_FILE_PARSER_MARKITDOWN_OCR_ENABLED=false
|
|
# HINDSIGHT_API_FILE_PARSER_MARKITDOWN_OCR_API_KEY=
|
|
# HINDSIGHT_API_FILE_PARSER_MARKITDOWN_OCR_BASE_URL=
|
|
# HINDSIGHT_API_FILE_PARSER_MARKITDOWN_OCR_MODEL=
|
|
# HINDSIGHT_API_FILE_PARSER_MARKITDOWN_OCR_PROMPT=
|
|
# Optional JSON dict of custom headers for the OCR OpenAI client (e.g. proxies / request tracing).
|
|
# HINDSIGHT_API_FILE_PARSER_MARKITDOWN_OCR_DEFAULT_HEADERS=
|
|
|
|
# Embeddings Configuration (Optional - uses local by default)
|
|
# Provider: "local" (default), "onnx", "tei", "openai", "cohere", "google", "openrouter", "zeroentropy", "litellm", or "litellm-sdk"
|
|
# HINDSIGHT_API_EMBEDDINGS_PROVIDER=local
|
|
# For local provider:
|
|
# HINDSIGHT_API_EMBEDDINGS_LOCAL_MODEL=BAAI/bge-small-en-v1.5
|
|
# Force CPU if local embeddings hit MPS/XPC instability on macOS:
|
|
# HINDSIGHT_API_EMBEDDINGS_LOCAL_FORCE_CPU=false
|
|
# Opt in to the Apple Silicon MPS GPU (off by default: MPS leaks memory under
|
|
# variable-length workloads). CUDA/XPU still auto-select regardless:
|
|
# HINDSIGHT_API_EMBEDDINGS_LOCAL_ALLOW_MPS=false
|
|
# For ONNX provider (local CPU embeddings without an Ollama/TEI sidecar):
|
|
# HINDSIGHT_API_EMBEDDINGS_PROVIDER=onnx
|
|
# HINDSIGHT_API_EMBEDDINGS_ONNX_MODEL_ID=intfloat/multilingual-e5-small
|
|
# HINDSIGHT_API_EMBEDDINGS_ONNX_FILE=onnx/model.onnx
|
|
# HINDSIGHT_API_EMBEDDINGS_ONNX_DIMENSIONS=384
|
|
# HINDSIGHT_API_EMBEDDINGS_ONNX_MAX_TOKENS=512
|
|
# HINDSIGHT_API_EMBEDDINGS_ONNX_POOLING=mean
|
|
# HINDSIGHT_API_EMBEDDINGS_ONNX_NORMALIZE=true
|
|
# HINDSIGHT_API_EMBEDDINGS_ONNX_QUERY_PREFIX="query: "
|
|
# HINDSIGHT_API_EMBEDDINGS_ONNX_PASSAGE_PREFIX="passage: "
|
|
# HINDSIGHT_API_EMBEDDINGS_ONNX_BATCH_SIZE=32 # Texts per forward pass; bounds peak memory
|
|
# HINDSIGHT_API_EMBEDDINGS_ONNX_CPU_MEM_ARENA=false # ONNX CPU memory arena; true lets RSS ratchet up
|
|
# Optional for local model paths or pre-downloaded artifacts:
|
|
# HINDSIGHT_API_EMBEDDINGS_ONNX_MODEL_PATH=/models/multilingual-e5-small/onnx/model.onnx
|
|
# HINDSIGHT_API_EMBEDDINGS_ONNX_TOKENIZER_NAME_OR_PATH=/models/multilingual-e5-small
|
|
# Optional for China network / restricted HF access:
|
|
# HF_ENDPOINT=https://hf-mirror.com
|
|
# Applies to any provider: cap each input at this many tokens before embedding, so
|
|
# oversized content is truncated instead of failing the embed call permanently.
|
|
# Defaults to 8192, the input limit of essentially every remote embedding model
|
|
# (OpenAI text-embedding-3-*, Bedrock Titan V2, Cohere v3, a stock llama.cpp
|
|
# context); raise or lower it to match your model, or set 0 to send text uncapped.
|
|
# (Deprecated alias: HINDSIGHT_API_EMBEDDINGS_LITELLM_SDK_MAX_INPUT_TOKENS)
|
|
# HINDSIGHT_API_EMBEDDINGS_MAX_INPUT_TOKENS=8192
|
|
# Asymmetric models (E5, google/embeddinggemma-300m, ...) expect a different instruction
|
|
# in front of a search than in front of stored text. Providers that only accept plain text
|
|
# (tei, openai-compatible, litellm) need it applied client-side; local/zeroentropy handle it
|
|
# themselves and ignore these. Unset = text sent as-is.
|
|
# HINDSIGHT_API_EMBEDDINGS_QUERY_PREFIX="task: search result | query: "
|
|
# HINDSIGHT_API_EMBEDDINGS_PASSAGE_PREFIX="title: none | text: "
|
|
# Embedding requests a remote provider keeps in flight for one encode() call. Concurrency,
|
|
# not bigger requests, is what saturates an embedding service (applies to every remote
|
|
# provider; the in-process local/onnx backends are unaffected).
|
|
# HINDSIGHT_API_EMBEDDINGS_MAX_CONCURRENT_REQUESTS=8
|
|
# For TEI provider:
|
|
# HINDSIGHT_API_EMBEDDINGS_TEI_URL=http://localhost:8080
|
|
# Max texts per TEI /embed request, and the unit the client fans out over (see the
|
|
# concurrency setting above). TEI's --max-client-batch-size (32 by default) rejects
|
|
# anything larger outright rather than clamping it.
|
|
# HINDSIGHT_API_EMBEDDINGS_TEI_BATCH_SIZE=32
|
|
# For Gemini/Vertex AI embeddings:
|
|
# Max texts per embed_content request, and the unit the client fans out over (see
|
|
# the concurrency setting above).
|
|
# HINDSIGHT_API_EMBEDDINGS_GEMINI_BATCH_SIZE=100
|
|
# For OpenAI-compatible embeddings:
|
|
# HINDSIGHT_API_EMBEDDINGS_OPENAI_API_KEY=sk-xxxx
|
|
# HINDSIGHT_API_EMBEDDINGS_OPENAI_MODEL=text-embedding-3-small
|
|
# HINDSIGHT_API_EMBEDDINGS_OPENAI_BASE_URL=https://api.openai.com/v1
|
|
# For LiteLLM proxy embeddings:
|
|
# HINDSIGHT_API_EMBEDDINGS_PROVIDER=litellm
|
|
# HINDSIGHT_API_EMBEDDINGS_LITELLM_API_BASE=http://localhost:4000
|
|
# HINDSIGHT_API_EMBEDDINGS_LITELLM_API_KEY=your-litellm-key
|
|
# HINDSIGHT_API_EMBEDDINGS_LITELLM_MODEL=text-embedding-3-small
|
|
# HINDSIGHT_API_EMBEDDINGS_LITELLM_DIMENSIONS=1536 # declare the vector width to skip the startup probe
|
|
# For LiteLLM SDK embeddings (no proxy; provider credentials read from the environment):
|
|
# HINDSIGHT_API_EMBEDDINGS_PROVIDER=litellm-sdk
|
|
# HINDSIGHT_API_EMBEDDINGS_LITELLM_SDK_MODEL=bedrock/amazon.titan-embed-text-v2:0
|
|
# Bedrock only: invoke this target instead of the model above (e.g. an application
|
|
# inference profile ARN, when a Service Control Policy denies the bare model id).
|
|
# LiteLLM picks the Bedrock payload shape from _MODEL, which must stay a recognizable
|
|
# id, so the opaque ARN goes here.
|
|
# HINDSIGHT_API_EMBEDDINGS_LITELLM_SDK_MODEL_ID=arn:aws:bedrock:eu-west-1:123456789012:application-inference-profile/abc123
|
|
# For ZeroEntropy zembed-1:
|
|
# HINDSIGHT_API_EMBEDDINGS_PROVIDER=zeroentropy
|
|
# HINDSIGHT_API_EMBEDDINGS_ZEROENTROPY_API_KEY=ze-xxxx
|
|
# HINDSIGHT_API_EMBEDDINGS_ZEROENTROPY_MODEL=zembed-1
|
|
# HINDSIGHT_API_EMBEDDINGS_ZEROENTROPY_DIMENSIONS=1280
|
|
# HINDSIGHT_API_EMBEDDINGS_ZEROENTROPY_ENCODING_FORMAT=float
|
|
# HINDSIGHT_API_EMBEDDINGS_ZEROENTROPY_LATENCY=fast
|
|
#
|
|
# IMPORTANT: Embedding keys require provider-specific names:
|
|
# HINDSIGHT_API_EMBEDDINGS_{PROVIDER}_{PARAMETER}
|
|
# (for example, HINDSIGHT_API_EMBEDDINGS_OPENAI_MODEL).
|
|
#
|
|
# DeepSeek note: DeepSeek is supported for LLM calls, but not for embeddings.
|
|
# If using DeepSeek as LLM provider, keep embeddings on local/openai/cohere/google/etc.
|
|
|
|
# Retry policy for remote embedding calls (litellm / litellm-sdk providers).
|
|
# Transient upstream failures (5xx, timeouts, connection errors) are retried with
|
|
# jittered exponential backoff; 4xx auth/validation errors are never retried.
|
|
# HINDSIGHT_API_EMBEDDINGS_MAX_RETRIES=4 # retries after the first attempt; 0 disables
|
|
# HINDSIGHT_API_EMBEDDINGS_INITIAL_BACKOFF=0.5 # seconds; doubles per attempt, with jitter
|
|
# HINDSIGHT_API_EMBEDDINGS_MAX_BACKOFF=4.0 # cap on per-retry backoff, seconds
|
|
# HINDSIGHT_API_EMBEDDINGS_RETRY_BUDGET=15.0 # wall-clock ceiling per encode() spent retrying
|
|
|
|
# Embedding similarity thresholds. These defaults preserve the behavior calibrated
|
|
# for BAAI/bge-small-en-v1.5. Recalibrate each threshold independently when changing
|
|
# embedding models because cosine-similarity distributions are model-dependent.
|
|
# HINDSIGHT_API_SEMANTIC_MIN_SIMILARITY=0.3
|
|
# HINDSIGHT_API_GRAPH_SEED_MIN_SIMILARITY=0.3
|
|
# HINDSIGHT_API_TEMPORAL_SEMANTIC_MIN_SIMILARITY=0.1
|
|
# HINDSIGHT_API_SEMANTIC_LINK_MIN_SIMILARITY=0.7
|
|
# HINDSIGHT_API_CONSOLIDATION_DEDUP_THRESHOLD=0.97
|
|
|
|
# Floor on how often an automatic mental-model refresh (after-consolidation or cron)
|
|
# may run, in seconds. A trigger that fires sooner is queued and parked until the
|
|
# window closes, and further triggers fold into it, so a burst of small retains costs
|
|
# one refresh instead of one per retain. 0 = no floor (the historical behaviour).
|
|
# Hierarchical, and overridable per model via the trigger's min_refresh_interval_seconds.
|
|
# Explicit refreshes always run immediately.
|
|
# HINDSIGHT_API_MENTAL_MODEL_MIN_REFRESH_INTERVAL_SECONDS=0
|
|
|
|
# Recall pipeline stages (all on by default). Each is hierarchical, so a single
|
|
# bank can switch a stage off via the config API without changing the server
|
|
# default. Turning all four off reduces recall to a single vector query, the
|
|
# lowest-latency recall path.
|
|
# Keyword (BM25) arm. false leaves pure vector search: the arm is left out of the
|
|
# query entirely rather than filtered to nothing, so its SQL, its query tokenization
|
|
# and its pg_stats term-selection lookup are all skipped. Also drops the keyword arm
|
|
# from knowledge-page search:
|
|
# HINDSIGHT_API_ENABLE_TEXT_SEARCH=true
|
|
# Temporal retrieval arm, plus the date-aware query analysis that feeds it:
|
|
# HINDSIGHT_API_ENABLE_TEMPORAL_RETRIEVAL=true
|
|
# Entity/link graph traversal arm:
|
|
# HINDSIGHT_API_ENABLE_GRAPH_RETRIEVAL=true
|
|
# Cross-encoder rerank of the fused candidates (false = use the RRF order):
|
|
# HINDSIGHT_API_ENABLE_RERANKING=true
|
|
|
|
# Reranker Configuration (Optional - uses local by default)
|
|
# Provider: "local" (default) or "tei" (HuggingFace Text Embeddings Inference)
|
|
# HINDSIGHT_API_RERANKER_PROVIDER=local
|
|
# Trusted gateway attribution (disabled by default). When enabled, remote
|
|
# reranker requests include X-Hindsight-Bank-Id with the current bank ID.
|
|
# HINDSIGHT_API_RERANKER_SEND_BANK_AS_HEADER=false
|
|
# Transient upstream failures (5xx, timeouts, connection errors, 429 quota) are
|
|
# retried with jittered exponential backoff; 4xx auth/validation errors are never
|
|
# retried. Applies to every remote provider except "tei", which retries on its own.
|
|
# HINDSIGHT_API_RERANKER_MAX_RETRIES=3 # retries after the first attempt; 0 disables
|
|
# HINDSIGHT_API_RERANKER_INITIAL_BACKOFF=0.5 # seconds; doubles per attempt, with jitter
|
|
# HINDSIGHT_API_RERANKER_MAX_BACKOFF=4.0 # cap on per-retry backoff, seconds
|
|
# HINDSIGHT_API_RERANKER_RETRY_BUDGET=10.0 # wall-clock ceiling per rerank spent retrying
|
|
# For local provider:
|
|
# HINDSIGHT_API_RERANKER_LOCAL_MODEL=cross-encoder/ms-marco-MiniLM-L-6-v2
|
|
# Force CPU if the local reranker hits MPS/XPC instability on macOS:
|
|
# HINDSIGHT_API_RERANKER_LOCAL_FORCE_CPU=false
|
|
# Opt in to the Apple Silicon MPS GPU (off by default: MPS leaks memory under
|
|
# variable-length workloads). CUDA/XPU still auto-select regardless:
|
|
# HINDSIGHT_API_RERANKER_LOCAL_ALLOW_MPS=false
|
|
# For TEI provider:
|
|
# HINDSIGHT_API_RERANKER_TEI_URL=http://localhost:8081
|
|
# For flashrank provider: passages scored per ONNX forward pass. Each pass
|
|
# allocates attention tensors sized batch * heads * seq^2, so raising this
|
|
# raises peak memory quadratically in passage length:
|
|
# HINDSIGHT_API_RERANKER_FLASHRANK_BATCH_SIZE=32
|
|
# Max candidates the cross-encoder reranks per recall (RRF pre-filters the rest):
|
|
# HINDSIGHT_API_RERANKER_MAX_CANDIDATES=300
|
|
# Optionally scale that cap by the recall budget level (the cross-encoder dominates
|
|
# a large recall's latency). 0 = fall back to the flat cap above; fully backwards-compatible.
|
|
# HINDSIGHT_API_RERANKER_MAX_CANDIDATES_LOW=0
|
|
# HINDSIGHT_API_RERANKER_MAX_CANDIDATES_MID=0
|
|
# HINDSIGHT_API_RERANKER_MAX_CANDIDATES_HIGH=0
|
|
|
|
# Reranker failover chain: extra rerankers tried, in order, when the one above
|
|
# fails. Members are numbered from 1 (indices must be contiguous) and every
|
|
# setting of member n carries the same index. A member inherits nothing from the
|
|
# primary, so spell out everything it needs. Unset = no fallback (default): a
|
|
# failing reranker fails the recall. End the chain with "rrf" to fail open and
|
|
# keep the retrieval order instead.
|
|
# HINDSIGHT_API_RERANKER_1_PROVIDER=cohere
|
|
# HINDSIGHT_API_RERANKER_1_COHERE_API_KEY=your-cohere-api-key
|
|
# HINDSIGHT_API_RERANKER_2_PROVIDER=rrf
|
|
|
|
# Observability & Tracing (Optional - disabled by default)
|
|
# Enable OpenTelemetry tracing for LLM calls (GenAI semantic conventions)
|
|
# HINDSIGHT_API_OTEL_TRACES_ENABLED=true
|
|
#
|
|
# Local development with Grafana LGTM stack (recommended - see scripts/dev/grafana/README.md)
|
|
# HINDSIGHT_API_OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
|
|
#
|
|
# Cloud backends (Grafana Cloud, Langfuse, DataDog, etc.)
|
|
# HINDSIGHT_API_OTEL_EXPORTER_OTLP_ENDPOINT=https://your-backend-url
|
|
# HINDSIGHT_API_OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer your-token"
|
|
#
|
|
# Custom service name and environment (optional, defaults: hindsight-api, development)
|
|
# HINDSIGHT_API_OTEL_SERVICE_NAME=hindsight-production
|
|
# HINDSIGHT_API_OTEL_DEPLOYMENT_ENVIRONMENT=production
|
|
#
|
|
# Expose async-operation queue + consolidation-backlog gauges on /metrics.
|
|
# Runs periodic per-schema COUNT queries on a background task (disabled by default).
|
|
# HINDSIGHT_API_METRICS_BACKLOG_ENABLED=true
|
|
#
|
|
# Runtime-stall observability (enabled by default). When a liveness probe fails,
|
|
# these tell you WHY: a blocked event loop vs DB connection-pool exhaustion.
|
|
# The loop watchdog logs the offending stack when the loop is unresponsive; the
|
|
# DB-pool acquire timing logs (and exposes hindsight.db.pool.waiting) when
|
|
# callers queue for a connection. Both are cheap; tune or disable if needed.
|
|
# HINDSIGHT_API_LOOP_WATCHDOG_ENABLED=false
|
|
# HINDSIGHT_API_LOOP_WATCHDOG_STALL_THRESHOLD_MS=1000
|
|
# HINDSIGHT_API_LOOP_WATCHDOG_POLL_INTERVAL_MS=250
|
|
# HINDSIGHT_API_DB_ACQUIRE_WARN_THRESHOLD_MS=1000
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Extensions (Optional)
|
|
# -----------------------------------------------------------------------------
|
|
|
|
# Request headers copied into RequestContext.extra_headers so a custom
|
|
# TenantExtension / OperationValidatorExtension can read them. Comma-separated,
|
|
# matched case-insensitively. Unset by default: extensions see only the
|
|
# Authorization header. Use this when the bearer token identifies a proxy rather
|
|
# than the caller, and per-caller identity arrives in a separate header. A listed
|
|
# header that arrives more than once is dropped, so only list headers the proxy
|
|
# in front of Hindsight sets itself (stripping any client-supplied copy).
|
|
# HINDSIGHT_API_EXTENSION_PASSTHROUGH_HEADERS=x-user-assertion
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Webhooks (Optional)
|
|
# -----------------------------------------------------------------------------
|
|
|
|
# Outbound webhook delivery targets caller-supplied URLs. To prevent SSRF, the
|
|
# delivery worker blocks private, loopback, and link-local destinations
|
|
# (including the cloud metadata address 169.254.169.254) by default. List hosts
|
|
# or IP/CIDR ranges here (comma-separated) to re-permit specific internal
|
|
# destinations — e.g. 127.0.0.1 for local testing, or an internal receiver.
|
|
# HINDSIGHT_API_WEBHOOK_ALLOWED_HOSTS=127.0.0.1,internal-receiver.svc,10.0.0.0/8
|
|
|
|
# Whether the webhook delivery-history API returns the raw upstream response
|
|
# body. Off by default: returning arbitrary response bodies to callers is an
|
|
# information-exfiltration primitive. The delivery status code is always
|
|
# returned regardless. Enable only if you trust your webhook destinations.
|
|
# HINDSIGHT_API_WEBHOOK_EXPOSE_RESPONSE_BODY=false
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Control Plane (Optional)
|
|
# -----------------------------------------------------------------------------
|
|
|
|
# Dataplane API URL - where the CP proxies requests to
|
|
# HINDSIGHT_CP_DATAPLANE_API_URL=http://localhost:8888
|
|
|
|
# Optional: Bearer token the CP sends as `Authorization: Bearer <key>` to the
|
|
# dataplane API. Required when the API service is auth-protected; omit for a
|
|
# public/unauthenticated API.
|
|
# HINDSIGHT_CP_DATAPLANE_API_KEY=your-dataplane-bearer-token
|
|
|
|
# Optional: Require a shared access key to view the Control Plane UI.
|
|
# When set, visitors see a login page and must enter the key before
|
|
# accessing the dashboard or any /api/* routes (except /api/health).
|
|
# HINDSIGHT_CP_ACCESS_KEY=your-shared-secret-key
|