mirror of
https://github.com/THU-MAIC/OpenMAIC.git
synced 2026-10-16 05:19:50 +08:00
* fix(ssrf): keep cloud metadata endpoints blocked under ALLOW_LOCAL_NETWORKS ALLOW_LOCAL_NETWORKS=true exists so self-hosted deployments can point providers at loopback, RFC1918 and split-horizon targets. It also returned early from validateUrlForSSRF before any classification, so a client-supplied base URL of 169.254.169.254 (or metadata.google.internal, 100.100.100.200, fd00:ec2::254) was accepted on such deployments. Cloud instance-metadata endpoints are now rejected regardless of the flag: literal hosts and IPv4-mapped forms are classified directly, and non-IP hostnames are resolved so an answer that lands on a metadata address is rejected too. DNS failure under the flag still fails open, as before, because split-horizon DNS is an explicit use case of the flag. Without the flag the DNS path now also rejects answers on metadata addresses that are not RFC1918 (100.100.100.200). The route tests that used the metadata address as their example of a target the flag allows now use a private-network address instead. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GRaNc5E88r41GUWt2Y3uiQ * fix(ssrf): widen the metadata set and bound the flagged DNS lookup Review follow-up. Add the AWS ECS task credential and EKS Pod Identity endpoints (169.254.170.2, 169.254.170.23, fd00:ec2::23), the Azure WireServer address (168.63.129.16) and the legacy OCI IMDS address (192.0.0.192) to the blocked set; the last two are neither RFC1918 nor link-local, so they were reachable even without the flag. Recognise the metadata addresses when carried inside 6to4, Teredo, ISATAP and NAT64 literals. Bound the DNS lookup done under the flag to three seconds and fail open on expiry, matching the existing fail-open on error. Say in .env.example that the set is a fixed list and that DNS failure is allowed through. Use the same private-network fixture for the reject and allow cases of the four route guard tests so a partial NODE_ENV re-gate of the guard goes red again. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GRaNc5E88r41GUWt2Y3uiQ * fix(ssrf): share the tunnel decoder between the private and metadata checks Review follow-up. assertSafeIp now classifies metadata addresses through isCloudMetadataAddress, so an ISATAP identifier under a globally routable prefix that carries 168.63.129.16, 192.0.0.192 or 100.100.100.200 is rejected on the strict-fetch path too. isPrivateIP uses the same tunnelEmbeddedIPv4 helper instead of its own copies of the 6to4, Teredo and ISATAP decoders, which also gives it NAT64. Tests cover the globally-routable ISATAP forms, the NAT64 private case, and the false-positive direction (tunnel literals carrying public or RFC1918 addresses stay allowed under the flag). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GRaNc5E88r41GUWt2Y3uiQ * fix(ssrf): reject metadata hostnames before the flag branch Review follow-up. The metadata hostname and address check now runs before the ALLOW_LOCAL_NETWORKS branch, so metadata.google.internal is rejected by name in both flag states (previously only under the flag), and metadata literals get the metadata message rather than the one that suggests setting the flag. Pin the tunnel decoder boundaries in tests (2001:db8 is not Teredo, 64:ff9b:1 is not NAT64, 2003 is not 6to4). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GRaNc5E88r41GUWt2Y3uiQ --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
538 lines
22 KiB
Bash
538 lines
22 KiB
Bash
# =============================================================================
|
|
# OpenMAIC Environment Variables
|
|
# Copy this file to .env.local and fill in the values you need.
|
|
# All variables are optional — only configure the providers you want to use.
|
|
# You can also use server-providers.yml for configuration (see docs).
|
|
# =============================================================================
|
|
|
|
# --- LLM Providers -----------------------------------------------------------
|
|
# Format: {PROVIDER}_API_KEY, {PROVIDER}_BASE_URL (optional), {PROVIDER}_MODELS (optional, comma-separated)
|
|
|
|
OPENAI_API_KEY=
|
|
OPENAI_BASE_URL=
|
|
OPENAI_MODELS=
|
|
# For relays whose non-streaming Chat Completions response is incompatible.
|
|
# Forces custom OpenAI base URLs to use Chat Completions and buffers SSE responses.
|
|
# Has no effect on the official OpenAI base URL. Disabled by default.
|
|
# OPENAI_COMPAT_USE_STREAMING_CHAT=true
|
|
|
|
# Azure uses deployment names as model IDs.
|
|
AZURE_OPENAI_API_KEY=
|
|
AZURE_OPENAI_BASE_URL=https://YOUR-RESOURCE.openai.azure.com/openai
|
|
AZURE_OPENAI_MODELS=
|
|
|
|
ATLASCLOUD_API_KEY=
|
|
ATLASCLOUD_BASE_URL=https://api.atlascloud.ai/v1
|
|
# Example: qwen/qwen3.5-flash,deepseek-ai/deepseek-v4-pro
|
|
ATLASCLOUD_MODELS=
|
|
|
|
ANTHROPIC_API_KEY=
|
|
ANTHROPIC_BASE_URL=
|
|
ANTHROPIC_MODELS=
|
|
|
|
GOOGLE_API_KEY=
|
|
GOOGLE_BASE_URL=
|
|
GOOGLE_MODELS=
|
|
|
|
DEEPSEEK_API_KEY=
|
|
DEEPSEEK_BASE_URL=
|
|
# Example: deepseek-v4-pro,deepseek-v4-flash,deepseek-v4-flash-vision-exp
|
|
DEEPSEEK_MODELS=
|
|
|
|
QWEN_API_KEY=
|
|
QWEN_BASE_URL=
|
|
QWEN_MODELS=
|
|
|
|
KIMI_API_KEY=
|
|
KIMI_BASE_URL=
|
|
KIMI_MODELS=
|
|
|
|
MINIMAX_API_KEY=
|
|
# MiniMax Anthropic-compatible endpoint for the built-in Anthropic SDK integration
|
|
MINIMAX_BASE_URL=https://api.minimaxi.com/anthropic/v1
|
|
# Example: MiniMax-M2.7-highspeed,MiniMax-M2.7,MiniMax-M2.5-highspeed,MiniMax-M2.5
|
|
MINIMAX_MODELS=
|
|
|
|
GLM_API_KEY=
|
|
GLM_BASE_URL=
|
|
GLM_MODELS=
|
|
|
|
SILICONFLOW_API_KEY=
|
|
SILICONFLOW_BASE_URL=
|
|
SILICONFLOW_MODELS=
|
|
|
|
DOUBAO_API_KEY=
|
|
DOUBAO_BASE_URL=
|
|
DOUBAO_MODELS=
|
|
|
|
OPENROUTER_API_KEY=
|
|
OPENROUTER_BASE_URL=https://openrouter.ai/api/v1
|
|
# Example: deepseek/deepseek-v4-pro,deepseek/deepseek-v4-flash
|
|
OPENROUTER_MODELS=
|
|
|
|
GROK_API_KEY=
|
|
GROK_BASE_URL=
|
|
# Example: grok-4.6,grok-4.5
|
|
GROK_MODELS=
|
|
|
|
TENCENT_API_KEY=
|
|
# Tencent TokenHub OpenAI-compatible endpoint. Hy3 is a model ID, not an env prefix.
|
|
# TENCENT_HUNYUAN_* is also accepted as an alias.
|
|
TENCENT_BASE_URL=https://tokenhub.tencentmaas.com/v1
|
|
# Example: hy3-preview,hunyuan-2.0-thinking-20251109,hunyuan-2.0-instruct-20251111
|
|
TENCENT_MODELS=
|
|
|
|
XIAOMI_API_KEY=
|
|
# MIMO_* is also accepted as an alias. Use tp-... keys only with Token Plan URLs.
|
|
XIAOMI_BASE_URL=https://api.xiaomimimo.com/v1
|
|
# Token Plan regional examples:
|
|
# XIAOMI_BASE_URL=https://token-plan-cn.xiaomimimo.com/v1
|
|
# XIAOMI_BASE_URL=https://token-plan-sgp.xiaomimimo.com/v1
|
|
# XIAOMI_BASE_URL=https://token-plan-ams.xiaomimimo.com/v1
|
|
# Example: mimo-v2.5-pro,mimo-v2-pro,mimo-v2.5,mimo-v2-omni,mimo-v2-flash
|
|
XIAOMI_MODELS=
|
|
|
|
# --- Ollama (Local Models) ---------------------------------------------------
|
|
# No API key needed. Configure BASE_URL here (server-side) so it bypasses SSRF
|
|
# protection automatically. Client-supplied localhost URLs are blocked in production.
|
|
# OLLAMA_BASE_URL=http://localhost:11434/v1
|
|
# OLLAMA_MODELS=llama3.3,llama3.2,qwen2.5,mistral,gemma3
|
|
|
|
# Lemonade local server (OpenAI-compatible, no API key required)
|
|
# LEMONADE_BASE_URL=http://localhost:13305/v1
|
|
# LEMONADE_MODELS=Qwen3-0.6B-GGUF,Llama-3.2-1B-Instruct-Hybrid,Qwen2.5-VL-7B-Instruct
|
|
|
|
# Amazon Bedrock LLMs (no OpenAI-style API key required)
|
|
# Set BEDROCK_REGION to enable Bedrock server-side provider config.
|
|
# AWS credentials are resolved from the standard AWS environment / credential chain.
|
|
# BEDROCK_REGION=us-east-1
|
|
# BEDROCK_MODELS=us.anthropic.claude-sonnet-5,us.anthropic.claude-opus-4-8
|
|
# Optional bearer-token authentication or custom Bedrock-compatible endpoint.
|
|
# AWS_BEARER_TOKEN_BEDROCK=
|
|
# BEDROCK_API_KEY=
|
|
# BEDROCK_BASE_URL=
|
|
# DEFAULT_MODEL=bedrock:us.anthropic.claude-sonnet-5
|
|
|
|
# --- TTS (Text-to-Speech) ----------------------------------------------------
|
|
|
|
TTS_OPENAI_API_KEY=
|
|
TTS_OPENAI_BASE_URL=
|
|
|
|
TTS_AZURE_API_KEY=
|
|
TTS_AZURE_BASE_URL=
|
|
|
|
TTS_GLM_API_KEY=
|
|
TTS_GLM_BASE_URL=
|
|
|
|
TTS_QWEN_API_KEY=
|
|
TTS_QWEN_BASE_URL=
|
|
# Qwen voice cloning reuses TTS_QWEN_API_KEY. Override the target model if needed.
|
|
# TTS_QWEN_VOICE_CLONE_MODEL=qwen3-tts-vc-2026-01-22
|
|
|
|
TTS_DOUBAO_API_KEY=
|
|
TTS_DOUBAO_BASE_URL=
|
|
|
|
TTS_MINIMAX_API_KEY=
|
|
# MiniMax TTS endpoint (speech-2.8 / 2.6 / 02 / 01 series)
|
|
TTS_MINIMAX_BASE_URL=https://api.minimaxi.com
|
|
TTS_ELEVENLABS_API_KEY=
|
|
TTS_ELEVENLABS_BASE_URL=
|
|
|
|
# VoxCPM2 TTS (local, OpenAI-compatible; API key is optional)
|
|
# TTS_VOXCPM_API_KEY=
|
|
# TTS_VOXCPM_BASE_URL=http://localhost:8000/v1
|
|
|
|
# Lemonade TTS (local, no API key required)
|
|
# TTS_LEMONADE_BASE_URL=http://localhost:13305/v1
|
|
|
|
# Operators can force-disable any built-in TTS provider. Examples:
|
|
# TTS_OPENAI_ENABLED=false
|
|
# TTS_BROWSER_NATIVE_ENABLED=false
|
|
|
|
# --- ASR (Automatic Speech Recognition) --------------------------------------
|
|
|
|
ASR_OPENAI_API_KEY=
|
|
ASR_OPENAI_BASE_URL=
|
|
|
|
ASR_QWEN_API_KEY=
|
|
ASR_QWEN_BASE_URL=
|
|
|
|
ASR_AZURE_API_KEY=
|
|
ASR_AZURE_BASE_URL=https://{region}.api.cognitive.microsoft.com
|
|
|
|
# FunASR (local, WAV input only, no API key required)
|
|
# ASR_FUNASR_BASE_URL=http://localhost:8000/v1
|
|
|
|
# Lemonade ASR (local, WAV input only, no API key required)
|
|
# ASR_LEMONADE_BASE_URL=http://localhost:13305/v1
|
|
|
|
# Operators can force-disable any built-in ASR provider. Examples:
|
|
# ASR_OPENAI_ENABLED=false
|
|
# ASR_BROWSER_NATIVE_ENABLED=false
|
|
|
|
# Optional local audio/video material extraction uses the first enabled server
|
|
# ASR provider above. It also requires the system `ffmpeg` and `ffprobe`
|
|
# executables on PATH; no bundled binary or npm dependency is installed.
|
|
# Without both executables, OpenMAIC skips the local extractor and uses a
|
|
# configured AliDocMind cloud extractor when available. With neither path
|
|
# enabled, media materials fail cleanly with setup guidance.
|
|
|
|
# --- PDF Processing -----------------------------------------------------------
|
|
|
|
PDF_UNPDF_API_KEY=
|
|
PDF_UNPDF_BASE_URL=
|
|
|
|
PDF_MINERU_API_KEY=
|
|
PDF_MINERU_BASE_URL=
|
|
# Optional. Defaults to "pipeline"; use "hybrid-auto-engine" only when your MinerU
|
|
# service has the required GPU/device configuration.
|
|
PDF_MINERU_BACKEND=
|
|
|
|
PDF_MINERU_CLOUD_API_KEY=
|
|
PDF_MINERU_CLOUD_BASE_URL=https://mineru.net/api/v4
|
|
# Self-hosted MinerU never falls back to MinerU Cloud implicitly: a request that
|
|
# selects self-hosted MinerU without a configured base URL fails loudly. Set this
|
|
# to "true" to explicitly opt in to MinerU Cloud as a fallback (documents then
|
|
# leave your infrastructure). Default: off.
|
|
ALLOW_MINERU_CLOUD_FALLBACK=
|
|
|
|
# AliDocMind uses an Alibaba Cloud AccessKey pair instead of a single API key.
|
|
ALIDOCMIND_ACCESS_KEY_ID=
|
|
ALIDOCMIND_ACCESS_KEY_SECRET=
|
|
ALIDOCMIND_BASE_URL=
|
|
|
|
# --- Image Generation ---------------------------------------------------------
|
|
|
|
IMAGE_OPENAI_API_KEY=
|
|
IMAGE_OPENAI_BASE_URL=https://api.openai.com/v1
|
|
|
|
IMAGE_SEEDREAM_API_KEY=
|
|
IMAGE_SEEDREAM_BASE_URL=
|
|
|
|
IMAGE_QWEN_IMAGE_API_KEY=
|
|
IMAGE_QWEN_IMAGE_BASE_URL=
|
|
|
|
IMAGE_NANO_BANANA_API_KEY=
|
|
IMAGE_NANO_BANANA_BASE_URL=
|
|
|
|
IMAGE_MINIMAX_API_KEY=
|
|
# Example models: image-01, image-01-live
|
|
IMAGE_MINIMAX_BASE_URL=https://api.minimaxi.com
|
|
|
|
IMAGE_GROK_API_KEY=
|
|
IMAGE_GROK_BASE_URL=
|
|
|
|
# Lemonade image generation (local, no API key required)
|
|
# IMAGE_LEMONADE_BASE_URL=http://localhost:13305/v1
|
|
|
|
# Operators can force-disable any built-in image provider, including the
|
|
# client-only ComfyUI provider (it has no credential env). Examples:
|
|
# IMAGE_OPENAI_ENABLED=false
|
|
# IMAGE_COMFYUI_ENABLED=false
|
|
|
|
# --- Video Generation ---------------------------------------------------------
|
|
|
|
VIDEO_SEEDANCE_API_KEY=
|
|
VIDEO_SEEDANCE_BASE_URL=
|
|
|
|
VIDEO_KLING_API_KEY=
|
|
VIDEO_KLING_BASE_URL=
|
|
|
|
VIDEO_VEO_API_KEY=
|
|
VIDEO_VEO_BASE_URL=
|
|
|
|
VIDEO_SORA_API_KEY=
|
|
VIDEO_SORA_BASE_URL=
|
|
|
|
VIDEO_MINIMAX_API_KEY=
|
|
# Example models: MiniMax-Hailuo-2.3, MiniMax-Hailuo-2.3-Fast, MiniMax-Hailuo-02
|
|
VIDEO_MINIMAX_BASE_URL=https://api.minimaxi.com
|
|
|
|
VIDEO_GROK_API_KEY=
|
|
VIDEO_GROK_BASE_URL=
|
|
|
|
VIDEO_HAPPYHORSE_API_KEY=
|
|
VIDEO_HAPPYHORSE_BASE_URL=https://dashscope.aliyuncs.com
|
|
|
|
# Operators can force-disable any built-in video provider. Examples:
|
|
# VIDEO_GROK_ENABLED=false
|
|
# VIDEO_KLING_ENABLED=false
|
|
|
|
# --- Web Search ---------------------------------------------------------------
|
|
# Note: Grok (xAI) web search is available via chat completions + search tools,
|
|
# not as a standalone search API. Use Grok LLM provider with search_parameters
|
|
# in chat requests. See: https://docs.x.ai/docs/guides/tools/search-tools
|
|
|
|
TAVILY_API_KEY=
|
|
TAVILY_BASE_URL=
|
|
EXA_API_KEY=
|
|
EXA_BASE_URL=https://api.exa.ai
|
|
BOCHA_API_KEY=
|
|
BOCHA_BASE_URL=https://api.bocha.cn
|
|
BRAVE_API_KEY=
|
|
BRAVE_BASE_URL=
|
|
BAIDU_API_KEY=
|
|
BAIDU_BASE_URL=https://qianfan.baidubce.com
|
|
# Self-hosted SearXNG instance (no API key required)
|
|
SEARXNG_BASE_URL=
|
|
# Dedicated MiniMax web-search vars avoid conflicting with the LLM MINIMAX_* endpoint.
|
|
WEB_SEARCH_MINIMAX_API_KEY=
|
|
WEB_SEARCH_MINIMAX_BASE_URL=https://api.minimaxi.com
|
|
# Dedicated Doubao web-search vars avoid conflicting with the Doubao LLM provider.
|
|
WEB_SEARCH_DOUBAO_API_KEY=
|
|
WEB_SEARCH_DOUBAO_BASE_URL=https://open.feedcoopapi.com
|
|
# Claude (Anthropic) native web search. Dedicated vars avoid conflicting with
|
|
# ANTHROPIC_* LLM provider vars. Optional WEB_SEARCH_CLAUDE_MODELS pins the
|
|
# search model server-side (first entry wins), e.g. claude-sonnet-5.
|
|
WEB_SEARCH_CLAUDE_API_KEY=
|
|
WEB_SEARCH_CLAUDE_BASE_URL=https://api.anthropic.com/v1
|
|
WEB_SEARCH_CLAUDE_MODELS=
|
|
|
|
# Operators can force-disable any built-in web search provider. Examples:
|
|
# TAVILY_ENABLED=false
|
|
# EXA_ENABLED=false
|
|
# WEB_SEARCH_DOUBAO_ENABLED=false
|
|
# SEARXNG_ENABLED=false
|
|
|
|
# Server-only, default-OFF selector for the Native Child execution harness.
|
|
# OPENMAIC_ENABLE_PI_NATIVE_CHILD_RUNTIME=true
|
|
# Server-only, default-OFF Native Spotlight capability; does not select the runtime.
|
|
# OPENMAIC_ENABLE_PI_NATIVE_CHILD_SPOTLIGHT=true
|
|
|
|
# --- Experimental Features ---------------------------------------------------
|
|
|
|
# Boolean feature flags accept "true" or "1". NEXT_PUBLIC_* values are compiled
|
|
# into the browser bundle at build time, so changing them requires a rebuild.
|
|
|
|
# Enable the Pro workbench entry (the workbench also requires the agent
|
|
# runtime to be configured server-side; see the Agent Runtime section).
|
|
# Implies the MAIC Editor gate below — Pro mode always ships with the editor.
|
|
# NEXT_PUBLIC_PRO_WORKBENCH_ENABLED=true
|
|
|
|
# Master gate for the MAIC Editor Pro-mode entry point. Implied by
|
|
# NEXT_PUBLIC_PRO_WORKBENCH_ENABLED; set it alone to enable the classroom
|
|
# editor on a deployment without the workbench.
|
|
# NEXT_PUBLIC_MAIC_EDITOR_ENABLED=true
|
|
|
|
# Select @openmaic/editor inside Pro mode. This does not enable Pro mode by itself.
|
|
# NEXT_PUBLIC_MAIC_EDITOR_RENDERER_ENABLED=true
|
|
|
|
# Use @openmaic/renderer for the classroom playback canvas.
|
|
# NEXT_PUBLIC_MAIC_PLAYBACK_RENDERER_ENABLED=true
|
|
|
|
# Use the experimental Pi-based classroom chat runtime. Disabled by default.
|
|
# NEXT_PUBLIC_PI_CHAT_ENABLED=true
|
|
|
|
# Enable the server-side vocational task-engine generation path.
|
|
# OPENMAIC_ENABLE_VOCATIONAL=true
|
|
|
|
# Show the experimental vocational task-engine control in the client.
|
|
# NEXT_PUBLIC_SHOW_VOCATIONAL_TEST_UI=true
|
|
|
|
# Show the video export and PPTX import entry points.
|
|
# NEXT_PUBLIC_ENABLE_VIDEO_EXPORT=true
|
|
# NEXT_PUBLIC_ENABLE_PPTX_IMPORT=true
|
|
|
|
# Informational destination shown on exported Quiz/PBL cover cards. Unset or
|
|
# blank defaults to open.maic.chat; set to "off" to omit it.
|
|
# NEXT_PUBLIC_VIDEO_EXPORT_CTA_DESTINATION=open.maic.chat
|
|
|
|
# --- Agent Runtime (experimental) ---------------------------------------------
|
|
|
|
# Server-only gate for durable background agent sessions: the /api/agent
|
|
# session and owner-event control-plane routes plus the in-process session
|
|
# runner. Default OFF — while disabled, every /api/agent/sessions* and
|
|
# /api/agent/owner-events route answers 404. Truthy values are "true" or "1";
|
|
# anything else (including unset) is treated as disabled.
|
|
# OPENMAIC_AGENT_RUNTIME_ENABLED=true
|
|
|
|
# The runtime is server-backed and requires the PostgreSQL connection from the
|
|
# "Server-backed Persistence" section below: without a non-empty DATABASE_URL
|
|
# the runner never starts and the session store rejects requests, even with the
|
|
# flag above enabled.
|
|
# DATABASE_URL=postgres://openmaic:password@postgres:5432/openmaic
|
|
|
|
# REQUIRED while the runtime is enabled: MODEL_ROUTES must explicitly route the
|
|
# "maic-agent-driver" stage to a provider-prefixed model id. There is
|
|
# intentionally no fallback — without this route every agent session fails at
|
|
# run start. The route object must set api (or its alias dialect) to
|
|
# "openai-completions" or "openai-responses"; any other value is rejected, and
|
|
# a bare model id without a provider prefix is rejected too. Optional fields:
|
|
# contextWindow pins the effective context window below the provider catalog
|
|
# value (used by compaction thresholds), and thinking must never set effort
|
|
# (the tool-using driver cannot combine reasoning_effort with function tools on
|
|
# this transport).
|
|
# MODEL_ROUTES='{"maic-agent-driver":{"model":"openai:gpt-5.5","api":"openai-completions"}}'
|
|
|
|
# Runner tuning. Defaults are shown; only relevant once the runtime is enabled.
|
|
# OPENMAIC_AGENT_RUNTIME_SCAN_INTERVAL_MS=1000
|
|
# OPENMAIC_AGENT_RUNTIME_HEARTBEAT_MS=2000
|
|
# OPENMAIC_AGENT_RUNTIME_LEASE_TTL_MS=10000
|
|
# OPENMAIC_AGENT_RUNTIME_MAX_CONCURRENT=2
|
|
# OPENMAIC_AGENT_RUNTIME_MAX_ATTEMPTS=5
|
|
|
|
# Global per-tool-call execution bound for every agent run (ms). A tool call
|
|
# that neither resolves nor rejects within the budget is aborted and settles as
|
|
# an error tool-result the agent can retry or proceed from; the session does
|
|
# not die. Default 600000 (10 minutes). Tools with known longer budgets (media
|
|
# synthesis, material extraction) carry their own explicit bounds in code.
|
|
# OPENMAIC_AGENT_TOOL_TIMEOUT_MS=600000
|
|
|
|
# Conversation compaction is reserved and OFF by default. The reusable
|
|
# compaction runtime is not implemented yet — it lands in a later slice of
|
|
# work — and until then the runner runs without context transformation, so
|
|
# these knobs are inert placeholders.
|
|
# OPENMAIC_AGENT_COMPACTION_ENABLED=true
|
|
# OPENMAIC_AGENT_COMPACTION_RESERVE_TOKENS=0
|
|
# OPENMAIC_AGENT_COMPACTION_KEEP_RECENT_TOKENS=0
|
|
|
|
# Session prompts and follow-up messages are capped server-side at a fixed
|
|
# 100,000 characters; this limit is a constant and is not configurable.
|
|
|
|
# --- Proxy (optional) --------------------------------------------------------
|
|
|
|
# HTTP_PROXY=
|
|
# HTTPS_PROXY=
|
|
# Comma-separated hosts that bypass the proxy. Supports domain suffixes and *.
|
|
# NO_PROXY=localhost,127.0.0.1,.internal.example.com
|
|
|
|
# --- Misc ---------------------------------------------------------------------
|
|
|
|
# Server-side default model for API routes like /api/generate-classroom.
|
|
# Required for server-side stages (those that don't receive a client x-model):
|
|
# resolveModel throws if a stage resolves to no model (no MODEL_ROUTES entry, no
|
|
# x-model, no DEFAULT_MODEL) — there is intentionally no hardcoded vendor fallback.
|
|
# Example: anthropic:claude-3-5-haiku-20241022 or google:gemini-3-flash-preview
|
|
# OpenAI example: openai:gpt-5.5
|
|
# MiniMax example: minimax:MiniMax-M2.7-highspeed
|
|
# Bedrock example: bedrock:us.anthropic.claude-sonnet-5
|
|
DEFAULT_MODEL=
|
|
|
|
# Optional per-stage model routing (#745). A JSON object mapping a generation
|
|
# stage to a model string (`provider:model`). For most stages, resolution order
|
|
# is stage route > x-model (client) > DEFAULT_MODEL. A configured route is the
|
|
# operator's deliberate choice and wins even when the browser sends its saved
|
|
# model as x-model. `conversation-title` is the exception: when unconfigured it
|
|
# reuses the exact `maic-agent-driver` connection, never x-model or DEFAULT_MODEL,
|
|
# and keeps thinking disabled unless its own route explicitly enables it.
|
|
# At boot the server validates MODEL_ROUTES / DEFAULT_MODEL / <PREFIX>_MODELS
|
|
# and prints [config] warnings for unknown stages, unregistered providers,
|
|
# providers with no API key, and bare model ids (which still default to openai
|
|
# but are deprecated — write provider:model). Warnings only: the server starts
|
|
# regardless, so a bad value is caught here instead of at request time.
|
|
# Routable stages: scene-outlines-stream, scene-content, scene-actions,
|
|
# agent-profiles, quiz-grade, pbl-chat, pbl-v2-runtime, chat-adapter,
|
|
# generate-classroom, web-search-query-rewrite, maic-agent,
|
|
# maic-agent-driver, conversation-title.
|
|
# scene-content can also be routed per scene type with composite keys:
|
|
# scene-content:slide, scene-content:quiz, scene-content:interactive,
|
|
# scene-content:pbl. A type falls back to the base scene-content route when it
|
|
# has no key of its own (so scene-content:<type> > scene-content > x-model >
|
|
# DEFAULT_MODEL).
|
|
# pbl-v2-runtime follows the same composite fallback pattern with
|
|
# pbl-v2-runtime:instructor, pbl-v2-runtime:open-task, pbl-v2-runtime:evaluate
|
|
# and pbl-v2-runtime:simulator, falling back to the base pbl-v2-runtime route.
|
|
# maic-agent-driver is REQUIRED when the agent runtime is enabled; see the
|
|
# "Agent runtime (experimental)" section for its api/dialect constraints.
|
|
# A route value can be a model string, OR an object {"model","thinking"} where
|
|
# `thinking` is the full ThinkingConfig: mode (default|disabled|enabled|auto),
|
|
# effort (none|minimal|low|medium|high|xhigh|max), level (minimal|low|medium|
|
|
# high, Gemini), enabled (bool), budgetTokens (number), excludeReasoningOutput
|
|
# (bool). It is normalized per the model's capability. When a stage is routed:
|
|
# a set `thinking` wins over the client's thinking; with no `thinking` the routed
|
|
# model uses its own default and the client's thinking is dropped. Unrouted
|
|
# stages keep the client thinking.
|
|
# Example: cheap default, stronger model only for the heavy/conversational stages:
|
|
# MODEL_ROUTES='{"scene-content":"openai:gpt-5.4","scene-actions":"openai:gpt-5.4","pbl-chat":"anthropic:claude-sonnet-4","chat-adapter":"anthropic:claude-sonnet-4"}'
|
|
# Example: per scene type + pinned thinking (qwen budget, deepseek off):
|
|
# MODEL_ROUTES='{"scene-content:interactive":{"model":"qwen:qwen3.7-plus","thinking":{"enabled":true,"budgetTokens":8000}},"scene-content:quiz":{"model":"deepseek:deepseek-v4-pro","thinking":{"enabled":false}}}'
|
|
# MODEL_ROUTES=
|
|
|
|
# LOG_LEVEL=info
|
|
# LOG_FORMAT=pretty
|
|
# LLM_THINKING_DISABLED=false
|
|
|
|
# Opt-in parallel scene-content generation (#572). 0/unset = serial (default).
|
|
# A value > 1 fetches scene content concurrently (capped at 10); actions + TTS
|
|
# stay serial. Leave off if your API key has a low per-key concurrency quota.
|
|
# PARALLEL_SCENE_CONCURRENCY=3
|
|
|
|
# --- Local/Self-hosted Deployment ---------------------------------------------
|
|
# Set to "true" to allow private/local network URLs (e.g. localhost, 192.168.x.x).
|
|
# Required for self-hosted models like Ollama. Do NOT enable on public deployments.
|
|
# The known cloud instance-metadata and credential endpoints (169.254.169.254,
|
|
# 169.254.170.2, 169.254.170.23, 100.100.100.200, 168.63.129.16, 192.0.0.192,
|
|
# fd00:ec2::254, fd00:ec2::23, metadata.google.internal) are blocked with or
|
|
# without this flag. That is a fixed address list, not a general link-local
|
|
# block, and under the flag a hostname whose DNS lookup fails, times out or
|
|
# returns no answer is still allowed through.
|
|
# ALLOW_LOCAL_NETWORKS=true
|
|
|
|
# Build-time, space-separated CSP frame-ancestor sources in addition to 'self'.
|
|
# Configure only origins you trust to embed OpenMAIC, then rebuild the app. The
|
|
# Docker and Compose builds also accept this value as a build argument.
|
|
# ALLOWED_FRAME_ANCESTORS=https://partner.example.com
|
|
|
|
# Optional MP4 render service (issue #866). When set, the in-app "Export Video"
|
|
# menu offers one-click MP4 rendering; when unset, it degrades to downloading a
|
|
# project ZIP for local CLI rendering. Point this at the isolated render-service
|
|
# container (see render-service/ and the "video-export" docker-compose profile).
|
|
# This is operator-supplied trusted config: the app forwards uploads to it
|
|
# without the SSRF guard, so a private/compose-network target works WITHOUT
|
|
# setting ALLOW_LOCAL_NETWORKS.
|
|
# RENDER_SERVICE_URL=http://render-service:9000
|
|
|
|
# Render-service-only opt-in for bounded local chunk execution. These variables
|
|
# are read at runtime by the isolated render-service container; the public HTTP
|
|
# API is unchanged. Defaults keep the existing in-process renderer.
|
|
# RENDER_CHUNK_EXECUTION=false
|
|
# RENDER_CHUNK_COUNT=1
|
|
# RENDER_CHUNK_WORKERS=1
|
|
# RENDER_MAX_PARALLEL_CHUNKS=1
|
|
# RENDER_CHUNK_SIZE_FRAMES=0
|
|
# RENDER_TARGET_CHUNK_FRAMES=0
|
|
|
|
# Honor x-forwarded-for / x-real-ip when deriving render-service client identity.
|
|
# Enable only behind a trusted reverse proxy that overwrites these headers.
|
|
# TRUST_PROXY_HEADERS=true
|
|
|
|
# --- Server-backed Persistence ------------------------------------------------
|
|
|
|
# Build-time client switch and shared development token. The public token must
|
|
# match PERSISTENCE_DEV_TOKEN. This development-only scheme provides no user
|
|
# isolation and must not be used as public-production authentication.
|
|
# NEXT_PUBLIC_PERSISTENCE=1
|
|
# NEXT_PUBLIC_PERSISTENCE_TOKEN=
|
|
|
|
# Runtime PostgreSQL connection and matching development token.
|
|
# DATABASE_URL=postgres://openmaic:password@postgres:5432/openmaic
|
|
# PERSISTENCE_DEV_TOKEN=
|
|
|
|
# The development authenticator above is refused when NODE_ENV=production
|
|
# unless this explicit opt-in is set. It provides no user isolation (the
|
|
# learner key is client-supplied), so enabling it in production is only safe
|
|
# on a trusted-network, single-user deployment.
|
|
# PERSISTENCE_ALLOW_INSECURE_DEV_AUTH=true
|
|
|
|
# Store asset bytes in S3 instead of PostgreSQL. Region, endpoint, and credentials
|
|
# are resolved through the standard AWS SDK environment / credential chain.
|
|
# ASSET_S3_BUCKET=
|
|
|
|
# Opt into indirect asset byte egress: answer asset byte GETs with a short-lived
|
|
# signed S3 URL (a 302, or a JSON descriptor for the packaged client) instead of
|
|
# the bytes. Unset or "direct" keeps direct egress (the safe default). Requires
|
|
# the object store's CORS to admit this app's origin and expose Content-Type, and
|
|
# the signing identity to hold s3:ListBucket on the bucket so a missing key
|
|
# answers 404 NoSuchKey rather than 403.
|
|
# ASSET_BYTE_EGRESS=redirect
|
|
|
|
# The asset collector is enabled by default when DATABASE_URL is configured.
|
|
# ASSET_COLLECTION_ENABLED=true
|
|
# ASSET_COLLECTION_INTERVAL_MS=900000
|
|
# ASSET_COLLECTION_GRACE_MS=3600000
|
|
|
|
# --- Access Control -----------------------------------------------------------
|
|
# Set a password to restrict site access. When set, users must enter this code
|
|
# before using the app. Leave empty or remove to disable access control.
|
|
# ACCESS_CODE=your-secret-code
|