refactor: move all server config to startup env vars; drop plugin settings
This commit is contained in:
+23
-16
@@ -1,18 +1,25 @@
|
||||
"""Configuration resolution for the opencode-bridge extension.
|
||||
|
||||
Priority order (highest to lowest):
|
||||
1. jupyter settings dict (from schema/plugin.json)
|
||||
2. Environment variables (OPENCODE_BRIDGE_URL, _USER, _PASSWORD)
|
||||
3. Built-in defaults
|
||||
All connection fields (URL / user / password / request timeout) are resolved
|
||||
exclusively from environment variables + built-in defaults at server startup.
|
||||
They are NOT stored in the JupyterLab plugin settings.
|
||||
|
||||
Env vars:
|
||||
OPENCODE_BRIDGE_URL — OpenCode Serve base URL (default http://127.0.0.1:4096)
|
||||
OPENCODE_BRIDGE_USER — HTTP Basic Auth username (default 'opencode')
|
||||
OPENCODE_BRIDGE_PASSWORD — HTTP Basic Auth password (default '' = no auth)
|
||||
OPENCODE_BRIDGE_TIMEOUT — request timeout in seconds (default 120)
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from typing import NamedTuple, Optional, Tuple
|
||||
|
||||
|
||||
ENV_URL = "OPENCODE_BRIDGE_URL"
|
||||
ENV_USER = "OPENCODE_BRIDGE_USER"
|
||||
ENV_PASSWORD = "OPENCODE_BRIDGE_PASSWORD"
|
||||
ENV_TIMEOUT = "OPENCODE_BRIDGE_TIMEOUT"
|
||||
|
||||
DEFAULT_URL = "http://127.0.0.1:4096"
|
||||
DEFAULT_USER = "opencode"
|
||||
@@ -23,7 +30,7 @@ class OpenCodeConfig(NamedTuple):
|
||||
url: str
|
||||
user: str
|
||||
password: str
|
||||
request_timeout_seconds: int = DEFAULT_REQUEST_TIMEOUT
|
||||
request_timeout_seconds: int
|
||||
|
||||
@property
|
||||
def auth(self) -> Optional[Tuple[str, str]]:
|
||||
@@ -34,18 +41,18 @@ class OpenCodeConfig(NamedTuple):
|
||||
|
||||
|
||||
def resolve_config(jupyter_settings: dict) -> OpenCodeConfig:
|
||||
"""Resolve OpenCode connection config from jupyter settings + env + defaults."""
|
||||
bridge = jupyter_settings.get("opencode_bridge", {}) or {}
|
||||
"""Resolve OpenCode connection config from environment variables + defaults.
|
||||
|
||||
The `jupyter_settings` argument is accepted for API compatibility but no
|
||||
fields are read from it — all connection config is now startup-only
|
||||
(environment variables).
|
||||
"""
|
||||
_ = jupyter_settings # intentionally unused; see module docstring
|
||||
return OpenCodeConfig(
|
||||
url=bridge.get("opencodeServerUrl") or os.environ.get(ENV_URL) or DEFAULT_URL,
|
||||
user=bridge.get("opencodeServerUser") or os.environ.get(ENV_USER) or DEFAULT_USER,
|
||||
password=(
|
||||
bridge.get("opencodeServerPassword")
|
||||
or os.environ.get(ENV_PASSWORD)
|
||||
or ""
|
||||
),
|
||||
url=os.environ.get(ENV_URL) or DEFAULT_URL,
|
||||
user=os.environ.get(ENV_USER) or DEFAULT_USER,
|
||||
password=os.environ.get(ENV_PASSWORD) or "",
|
||||
request_timeout_seconds=int(
|
||||
bridge.get("requestTimeoutSeconds", DEFAULT_REQUEST_TIMEOUT)
|
||||
),
|
||||
os.environ.get(ENV_TIMEOUT) or DEFAULT_REQUEST_TIMEOUT
|
||||
)
|
||||
)
|
||||
|
||||
@@ -118,7 +118,9 @@ async def test_send_message_sync_omits_model_when_provider_or_model_missing(
|
||||
@pytest.mark.asyncio
|
||||
async def test_send_message_sync_includes_system_when_provided() -> None:
|
||||
"""system param is forwarded into the request body when not None."""
|
||||
config = OpenCodeConfig(url="http://x:1", user="u", password="")
|
||||
config = OpenCodeConfig(
|
||||
url="http://x:1", user="u", password="", request_timeout_seconds=120
|
||||
)
|
||||
mock = MockHTTPClient()
|
||||
mock.responses.append((200, {"info": {}, "parts": []}))
|
||||
client = OpenCodeClient(config, http_client=mock)
|
||||
|
||||
@@ -17,21 +17,23 @@ def test_env_url_overrides_default(monkeypatch) -> None:
|
||||
assert config.url == "http://x:1"
|
||||
|
||||
|
||||
def test_jupyter_settings_override_env(monkeypatch) -> None:
|
||||
def test_jupyter_settings_are_ignored(monkeypatch) -> None:
|
||||
monkeypatch.setenv("OPENCODE_BRIDGE_URL", "http://x:1")
|
||||
settings = {"opencode_bridge": {"opencodeServerUrl": "http://y:2"}}
|
||||
config = resolve_config(settings)
|
||||
assert config.url == "http://y:2"
|
||||
assert config.url == "http://x:1"
|
||||
|
||||
|
||||
def test_all_env_vars(monkeypatch) -> None:
|
||||
monkeypatch.setenv("OPENCODE_BRIDGE_URL", "http://x:1")
|
||||
monkeypatch.setenv("OPENCODE_BRIDGE_USER", "u")
|
||||
monkeypatch.setenv("OPENCODE_BRIDGE_PASSWORD", "p")
|
||||
monkeypatch.setenv("OPENCODE_BRIDGE_TIMEOUT", "300")
|
||||
config = resolve_config({})
|
||||
assert config.url == "http://x:1"
|
||||
assert config.user == "u"
|
||||
assert config.password == "p"
|
||||
assert config.request_timeout_seconds == 300
|
||||
|
||||
|
||||
def test_auth_none_when_password_empty() -> None:
|
||||
@@ -44,11 +46,12 @@ def test_auth_when_password_set() -> None:
|
||||
url="http://127.0.0.1:4096",
|
||||
user="opencode",
|
||||
password="secret",
|
||||
request_timeout_seconds=120,
|
||||
)
|
||||
assert config.auth == ("opencode", "secret")
|
||||
|
||||
|
||||
def test_request_timeout_from_settings() -> None:
|
||||
settings = {"opencode_bridge": {"requestTimeoutSeconds": 300}}
|
||||
config = resolve_config(settings)
|
||||
def test_request_timeout_from_env(monkeypatch) -> None:
|
||||
monkeypatch.setenv("OPENCODE_BRIDGE_TIMEOUT", "300")
|
||||
config = resolve_config({})
|
||||
assert config.request_timeout_seconds == 300
|
||||
|
||||
Reference in New Issue
Block a user