mirror of
https://github.com/usestrix/strix.git
synced 2026-08-21 18:52:47 +02:00
Some OpenAI-compatible gateways don't support Server-Sent Events (or deliver them unreliably), but the SDK run loop Strix uses only issues streamed requests, so such a gateway fails every turn. Add an opt-in LLM_DISABLE_STREAMING setting that wraps the resolved model in _NonStreamingModel: each turn makes one non-streaming get_response and replays the completed result as a single terminal stream event, so tool calls, usage, and the rest of the agent loop are unchanged. Subscription (ChatGPT) models are always streamed and are not wrapped.
142 lines
5.0 KiB
Python
142 lines
5.0 KiB
Python
"""Strix application settings — pydantic-settings powered."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Literal
|
|
|
|
from pydantic import AliasChoices, Field
|
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
|
|
|
|
ReasoningEffort = Literal["none", "minimal", "low", "medium", "high", "xhigh"]
|
|
|
|
_BASE_CONFIG = SettingsConfigDict(
|
|
case_sensitive=False,
|
|
populate_by_name=True,
|
|
extra="ignore",
|
|
)
|
|
|
|
|
|
class LlmSettings(BaseSettings):
|
|
model_config = _BASE_CONFIG
|
|
|
|
model: str | None = Field(default=None, alias="STRIX_LLM")
|
|
api_key: str | None = Field(
|
|
default=None,
|
|
validation_alias=AliasChoices("LLM_API_KEY", "OPENAI_API_KEY"),
|
|
)
|
|
api_base: str | None = Field(
|
|
default=None,
|
|
validation_alias=AliasChoices(
|
|
"LLM_API_BASE",
|
|
"OPENAI_API_BASE",
|
|
"OPENAI_BASE_URL",
|
|
"LITELLM_BASE_URL",
|
|
"OLLAMA_API_BASE",
|
|
),
|
|
)
|
|
extra_headers: dict[str, str] | None = Field(
|
|
default=None,
|
|
alias="LLM_EXTRA_HEADERS",
|
|
)
|
|
reasoning_effort: ReasoningEffort = Field(default="high", alias="STRIX_REASONING_EFFORT")
|
|
force_required_tool_choice: bool = Field(
|
|
default=False,
|
|
alias="STRIX_FORCE_REQUIRED_TOOL_CHOICE",
|
|
)
|
|
prompt_cache: bool = Field(
|
|
default=True,
|
|
alias="STRIX_PROMPT_CACHE",
|
|
)
|
|
disable_streaming: bool = Field(
|
|
default=False,
|
|
alias="LLM_DISABLE_STREAMING",
|
|
)
|
|
timeout: int = Field(default=300, alias="LLM_TIMEOUT")
|
|
|
|
|
|
class DedupeSettings(BaseSettings):
|
|
model_config = _BASE_CONFIG
|
|
|
|
model: str | None = Field(default=None, alias="STRIX_DEDUPE_MODEL")
|
|
reasoning_effort: ReasoningEffort | None = Field(
|
|
default=None,
|
|
alias="STRIX_DEDUPE_REASONING_EFFORT",
|
|
)
|
|
api_key: str | None = Field(default=None, alias="DEDUPE_LLM_API_KEY")
|
|
api_base: str | None = Field(default=None, alias="DEDUPE_LLM_API_BASE")
|
|
extra_headers: dict[str, str] | None = Field(
|
|
default=None,
|
|
alias="DEDUPE_LLM_EXTRA_HEADERS",
|
|
)
|
|
|
|
|
|
class ContextSettings(BaseSettings):
|
|
"""Context-window management: per-tool-output caps and history compaction."""
|
|
|
|
model_config = _BASE_CONFIG
|
|
|
|
auto_compact: bool = Field(default=True, alias="STRIX_CONTEXT_AUTO_COMPACT")
|
|
compact_buffer_tokens: int = Field(default=20_000, gt=0, alias="STRIX_CONTEXT_BUFFER_TOKENS")
|
|
keep_tokens: int = Field(default=8_000, gt=0, alias="STRIX_CONTEXT_KEEP_TOKENS")
|
|
fallback_context_tokens: int = Field(
|
|
default=200_000, gt=0, alias="STRIX_CONTEXT_FALLBACK_TOKENS"
|
|
)
|
|
summary_max_tokens: int = Field(default=4_096, gt=0, alias="STRIX_CONTEXT_SUMMARY_TOKENS")
|
|
tool_output_max_tokens: int = Field(default=8_000, gt=0, alias="STRIX_TOOL_OUTPUT_MAX_TOKENS")
|
|
tool_output_max_lines: int = Field(default=2_000, gt=0, alias="STRIX_TOOL_OUTPUT_MAX_LINES")
|
|
# Floor above the truncation-notice size so a preview always fits.
|
|
tool_output_max_bytes: int = Field(
|
|
default=50 * 1024, ge=1024, alias="STRIX_TOOL_OUTPUT_MAX_BYTES"
|
|
)
|
|
|
|
|
|
class RuntimeSettings(BaseSettings):
|
|
model_config = _BASE_CONFIG
|
|
|
|
image: str = Field(
|
|
default="ghcr.io/usestrix/strix-sandbox:1.1.0",
|
|
alias="STRIX_IMAGE",
|
|
)
|
|
backend: str = Field(default="docker", alias="STRIX_RUNTIME_BACKEND")
|
|
# Hard cap on a local target's size before we refuse to stream it into the
|
|
# sandbox file-by-file (the SDK copies every file individually, which stalls
|
|
# on large repos). Above this, the user must bind-mount via ``--mount``.
|
|
# Set to 0 (or less) to disable the pre-flight check entirely.
|
|
max_local_copy_mb: int = Field(default=1024, alias="STRIX_MAX_LOCAL_COPY_MB")
|
|
# Max screenshot/image tool outputs kept live per agent context (0 = none).
|
|
max_context_images: int = Field(default=3, ge=0, alias="STRIX_MAX_CONTEXT_IMAGES")
|
|
|
|
|
|
class TelemetrySettings(BaseSettings):
|
|
model_config = _BASE_CONFIG
|
|
|
|
enabled: bool = Field(default=True, alias="STRIX_TELEMETRY")
|
|
|
|
|
|
class IntegrationSettings(BaseSettings):
|
|
model_config = _BASE_CONFIG
|
|
|
|
perplexity_api_key: str | None = Field(default=None, alias="PERPLEXITY_API_KEY")
|
|
|
|
|
|
class ViewerSettings(BaseSettings):
|
|
model_config = _BASE_CONFIG
|
|
|
|
# Base URL of the Strix relay the local viewer proxies to for email
|
|
# verification and encrypted report delivery. The browser never talks to
|
|
# the relay directly; the local server is the only caller.
|
|
app_url: str = Field(default="https://app.strix.ai", alias="STRIX_APP_URL")
|
|
|
|
|
|
class Settings(BaseSettings):
|
|
model_config = _BASE_CONFIG
|
|
|
|
llm: LlmSettings = Field(default_factory=LlmSettings)
|
|
dedupe: DedupeSettings = Field(default_factory=DedupeSettings)
|
|
runtime: RuntimeSettings = Field(default_factory=RuntimeSettings)
|
|
context: ContextSettings = Field(default_factory=ContextSettings)
|
|
telemetry: TelemetrySettings = Field(default_factory=TelemetrySettings)
|
|
integrations: IntegrationSettings = Field(default_factory=IntegrationSettings)
|
|
viewer: ViewerSettings = Field(default_factory=ViewerSettings)
|