7Shared runtime configuration for OC Chat.
11Provider-specific settings (DeepSeek's API key env var, base URL,
12model registry, default model, summariser-tier model) used to live
13here but moved into ``providers/deepseek/`` during Phase C. This
14module now holds only neutral concerns: context-compression
15heuristics, ANSI styles, ReAct caps, the ``OC_CHAT_*`` env vars, and
16shared default fallbacks.
20- Read environment overrides (``OC_CHAT_CONTEXT_FILE``,
21 ``OC_CHAT_PROVIDER``, ``NO_COLOR``) at import time via
22 ``python-dotenv`` if available.
23- Export the canonical defaults: ``DEFAULT_MAX_REACT_ITERATIONS``,
24 ``CONTEXT_COMPRESS_THRESHOLD``, ``CONTEXT_KEEP_RECENT_TURNS``,
25 ``REASONING_EFFORT_LEVELS``, ``TOKEN_PROFILES``,
27- :func:`get_max_context_tokens` — provider-aware lookup with fallback
28 to ``MODEL_MAX_TOKENS``.
40- All values are module-level constants resolved at import time.
41- Missing env vars fall back to the documented defaults; never raise.
42- ``python-dotenv`` is an optional dependency; absence is silently
47- oc_diagnostics (structured debug logging via _dbg)
48- oc_chat._env_guard (load_dotenv_guarded - loads .env at import, refusing the security-authority vars)
49- oc_chat.core.defaults (default, ceiling, shipped - the shipped defaults and the lower-only output ceiling)
50- oc_chat.core.provider_plugin (lazy; registry - the active provider's model context windows)
54from oc_diagnostics
import _dbg
66_dbg(
"OC_CHAT.MAIN",
"module",
"loaded", 4)
69OC_CHAT_CONTEXT_FILE = os.getenv(
"OC_CHAT_CONTEXT_FILE",
"AGENT_CONTEXT.md")
71DEFAULT_REASONING_EFFORT = default(
"reasoning_effort")
72REASONING_EFFORT_LEVELS = [
"low",
"medium",
"high"]
75CONTEXT_COMPRESS_THRESHOLD = default(
"context_compress_threshold")
76MODEL_MAX_TOKENS = default(
"model_max_tokens")
82DEFAULT_CONTEXT_WINDOW_SIZE = default(
"context_window_size")
83CONTEXT_KEEP_RECENT = default(
"context_keep_recent")
85CONTEXT_KEEP_RECENT_TURNS = default(
"context_keep_recent_turns")
88DEFAULT_MAX_REACT_ITERATIONS = default(
"max_react_iterations")
91TOKEN_PROFILES = (
"cheap",
"balanced",
"deep")
108OUTPUT_TOKENS_CEILING = shipped(
"output_tokens")
114UNDECLARED_OUTPUT_TOKENS = default(
"undeclared_output_tokens")
118 """Return the effective completion ceiling.
120 :data:`OUTPUT_TOKENS_CEILING` unless the workspace settings file specifies
121 a smaller ``max_output_tokens``. A settings value at or above the code
122 default is ignored, so a model that talks a human into a settings write
123 cannot widen its own output budget. Degrades to the code default when
124 settings are unavailable or unparseable — the generalised lower-only rule in
125 :func:`oc_chat.core.defaults.ceiling` (plan 238), unchanged in behaviour.
127 return ceiling(
"output_tokens")
139 """Return True iff ANSI styles should be emitted."""
140 if os.getenv(
"FORCE_COLOR"):
142 if os.getenv(
"NO_COLOR")
is not None:
149STYLE_RESET =
"\033[0m" if _COLOR
else ""
150STYLE_DIM =
"\033[2m" if _COLOR
else ""
151STYLE_ITALIC =
"\033[3m" if _COLOR
else ""
152STYLE_BOLD =
"\033[1m" if _COLOR
else ""
153STYLE_CYAN =
"\033[36m" if _COLOR
else ""
154STYLE_YELLOW =
"\033[33m" if _COLOR
else ""
155STYLE_GREEN =
"\033[32m" if _COLOR
else ""
156STYLE_RED =
"\033[31m" if _COLOR
else ""
160 """Return the max context window tokens for *model_name*.
162 Looks up the active provider's curated model registry. Falls back to
163 :data:`MODEL_MAX_TOKENS` for unknown models or when no provider is
164 registered yet (rare — only happens in early test setup).
166 func =
"get_max_context_tokens"
169 provider_name = os.environ.get(
"OC_CHAT_PROVIDER",
"deepseek")
171 caps = registry.get(provider_name).models().get(model_name)
173 return caps.max_context_tokens
174 except (KeyError, AttributeError)
as e:
176 _dbg(
"OC_CHAT.MAIN", func, f
"VALIDATION_ERROR: {type(e).__name__}: {e}", 3)
177 return MODEL_MAX_TOKENS
int get_output_tokens_ceiling()
int get_max_context_tokens(str model_name)