feat: add api key auth, devii agent, openai gateway, and admin service management
This commit introduces a comprehensive set of new features including API key authentication with CLI management commands (get, reset, backfill), a Devii agentic assistant with WebSocket terminal and session bootstrap, an OpenAI-compatible LLM gateway service, and an admin service management panel. It also adds Playwright browser automation for bot support, configures internal gateway URLs, refactors content editing/deletion to support JSON API responses, and updates documentation across AGENTS.md, README.md, and the developer docs site.
This commit is contained in:
@@ -0,0 +1,149 @@
|
||||
# retoor <retoor@molodetz.nl>
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import uuid
|
||||
from dataclasses import dataclass
|
||||
|
||||
from devplacepy.config import INTERNAL_GATEWAY_URL, INTERNAL_MODEL
|
||||
|
||||
|
||||
DEFAULT_AI_URL = INTERNAL_GATEWAY_URL
|
||||
DEFAULT_AI_MODEL = INTERNAL_MODEL
|
||||
DEFAULT_BASE_URL = "http://127.0.0.1:10500"
|
||||
DEFAULT_TIMEOUT_SECONDS = 45.0
|
||||
DEFAULT_MAX_RESPONSE_CHARS = 12000
|
||||
DEFAULT_MAX_TOOL_ITERATIONS = 40
|
||||
DEFAULT_DELEGATE_MAX_ITERATIONS = 25
|
||||
DEFAULT_CONTEXT_COMPACT_THRESHOLD = 220_000
|
||||
DEFAULT_CONTEXT_KEEP_TAIL = 12
|
||||
DEFAULT_RECALL_TOP_K = 3
|
||||
DEFAULT_FETCH_MAX_CHARS = 24_000
|
||||
DEFAULT_FETCH_TIMEOUT_SECONDS = 30.0
|
||||
DEFAULT_FETCH_MAX_BYTES = 5_000_000
|
||||
DEFAULT_RSEARCH_URL = "https://rsearch.app.molodetz.nl"
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Settings:
|
||||
ai_url: str
|
||||
ai_key: str
|
||||
ai_model: str
|
||||
base_url: str
|
||||
timeout_seconds: float
|
||||
max_response_chars: int
|
||||
max_tool_iterations: int
|
||||
log_level: str
|
||||
log_path: str
|
||||
tasks_db_path: str
|
||||
scheduler_tick_seconds: float
|
||||
lessons_db_path: str
|
||||
delegate_max_iterations: int
|
||||
context_compact_threshold: int
|
||||
context_keep_tail: int
|
||||
recall_top_k: int
|
||||
plan_required: bool
|
||||
verify_required: bool
|
||||
platform_api_key: str
|
||||
login_email: str
|
||||
login_password: str
|
||||
fetch_max_chars: int
|
||||
fetch_timeout_seconds: float
|
||||
fetch_max_bytes: int
|
||||
fetch_allow_private: bool
|
||||
allow_eval: bool
|
||||
rsearch_enabled: bool
|
||||
rsearch_url: str
|
||||
|
||||
|
||||
def load_settings() -> Settings:
|
||||
return Settings(
|
||||
ai_url=os.environ.get("DEVII_AI_URL", DEFAULT_AI_URL),
|
||||
ai_key=os.environ.get("DEVII_AI_KEY", str(uuid.uuid4())),
|
||||
ai_model=os.environ.get("DEVII_AI_MODEL", DEFAULT_AI_MODEL),
|
||||
base_url=os.environ.get("DEVII_BASE_URL", DEFAULT_BASE_URL).rstrip("/"),
|
||||
timeout_seconds=float(os.environ.get("DEVII_TIMEOUT", DEFAULT_TIMEOUT_SECONDS)),
|
||||
max_response_chars=int(os.environ.get("DEVII_MAX_RESPONSE", DEFAULT_MAX_RESPONSE_CHARS)),
|
||||
max_tool_iterations=int(os.environ.get("DEVII_MAX_TOOL_ITERATIONS", DEFAULT_MAX_TOOL_ITERATIONS)),
|
||||
log_level=os.environ.get("DEVII_LOG_LEVEL", "WARNING").upper(),
|
||||
log_path=os.environ.get("DEVII_LOG_PATH", "devii.log"),
|
||||
tasks_db_path=os.environ.get("DEVII_TASKS_DB", "devii_tasks.db"),
|
||||
scheduler_tick_seconds=float(os.environ.get("DEVII_SCHEDULER_TICK", "1.0")),
|
||||
lessons_db_path=os.environ.get("DEVII_LESSONS_DB", "devii_lessons.db"),
|
||||
delegate_max_iterations=int(
|
||||
os.environ.get("DEVII_DELEGATE_MAX_ITERATIONS", DEFAULT_DELEGATE_MAX_ITERATIONS)
|
||||
),
|
||||
context_compact_threshold=int(
|
||||
os.environ.get("DEVII_CONTEXT_COMPACT_THRESHOLD", DEFAULT_CONTEXT_COMPACT_THRESHOLD)
|
||||
),
|
||||
context_keep_tail=int(os.environ.get("DEVII_CONTEXT_KEEP_TAIL", DEFAULT_CONTEXT_KEEP_TAIL)),
|
||||
recall_top_k=int(os.environ.get("DEVII_RECALL_TOP_K", DEFAULT_RECALL_TOP_K)),
|
||||
plan_required=os.environ.get("DEVII_PLAN_REQUIRED", "1").lower() not in ("0", "false", "no"),
|
||||
verify_required=os.environ.get("DEVII_VERIFY_REQUIRED", "1").lower() not in ("0", "false", "no"),
|
||||
platform_api_key=os.environ.get("DEVII_PLATFORM_API_KEY", ""),
|
||||
login_email=os.environ.get("DEVII_LOGIN_EMAIL", ""),
|
||||
login_password=os.environ.get("DEVII_LOGIN_PASSWORD", ""),
|
||||
fetch_max_chars=int(os.environ.get("DEVII_FETCH_MAX_CHARS", DEFAULT_FETCH_MAX_CHARS)),
|
||||
fetch_timeout_seconds=float(
|
||||
os.environ.get("DEVII_FETCH_TIMEOUT", DEFAULT_FETCH_TIMEOUT_SECONDS)
|
||||
),
|
||||
fetch_max_bytes=int(os.environ.get("DEVII_FETCH_MAX_BYTES", DEFAULT_FETCH_MAX_BYTES)),
|
||||
fetch_allow_private=os.environ.get("DEVII_FETCH_ALLOW_PRIVATE", "0").lower()
|
||||
in ("1", "true", "yes", "on"),
|
||||
allow_eval=os.environ.get("DEVII_ALLOW_EVAL", "1").lower() in ("1", "true", "yes", "on"),
|
||||
rsearch_enabled=os.environ.get("DEVII_RSEARCH_ENABLED", "1").lower() in ("1", "true", "yes", "on"),
|
||||
rsearch_url=os.environ.get("DEVII_RSEARCH_URL", DEFAULT_RSEARCH_URL).rstrip("/"),
|
||||
)
|
||||
|
||||
|
||||
FIELD_AI_URL = "devii_ai_url"
|
||||
FIELD_AI_MODEL = "devii_ai_model"
|
||||
FIELD_AI_KEY = "devii_ai_key"
|
||||
FIELD_PLAN_REQUIRED = "devii_plan_required"
|
||||
FIELD_VERIFY_REQUIRED = "devii_verify_required"
|
||||
FIELD_MAX_ITERATIONS = "devii_max_iterations"
|
||||
FIELD_USER_DAILY_USD = "devii_user_daily_usd"
|
||||
FIELD_GUEST_DAILY_USD = "devii_guest_daily_usd"
|
||||
FIELD_GUESTS_ENABLED = "devii_guests_enabled"
|
||||
FIELD_PRICE_CACHE_HIT = "devii_price_cache_hit"
|
||||
FIELD_PRICE_CACHE_MISS = "devii_price_cache_miss"
|
||||
FIELD_PRICE_OUTPUT = "devii_price_output"
|
||||
FIELD_ALLOW_EVAL = "devii_allow_eval"
|
||||
FIELD_RSEARCH_ENABLED = "devii_rsearch_enabled"
|
||||
FIELD_RSEARCH_URL = "devii_rsearch_url"
|
||||
|
||||
LESSONS_DB_PATH = os.environ.get("DEVII_LESSONS_DB", "devii_lessons.db")
|
||||
|
||||
|
||||
def build_settings(config: dict, base_url: str, api_key: str) -> Settings:
|
||||
return Settings(
|
||||
ai_url=config[FIELD_AI_URL] or DEFAULT_AI_URL,
|
||||
ai_key=config[FIELD_AI_KEY] or str(uuid.uuid4()),
|
||||
ai_model=config[FIELD_AI_MODEL] or DEFAULT_AI_MODEL,
|
||||
base_url=(base_url or DEFAULT_BASE_URL).rstrip("/"),
|
||||
timeout_seconds=DEFAULT_TIMEOUT_SECONDS,
|
||||
max_response_chars=DEFAULT_MAX_RESPONSE_CHARS,
|
||||
max_tool_iterations=int(config[FIELD_MAX_ITERATIONS]),
|
||||
log_level="INFO",
|
||||
log_path="devii.log",
|
||||
tasks_db_path="",
|
||||
scheduler_tick_seconds=1.0,
|
||||
lessons_db_path=LESSONS_DB_PATH,
|
||||
delegate_max_iterations=DEFAULT_DELEGATE_MAX_ITERATIONS,
|
||||
context_compact_threshold=DEFAULT_CONTEXT_COMPACT_THRESHOLD,
|
||||
context_keep_tail=DEFAULT_CONTEXT_KEEP_TAIL,
|
||||
recall_top_k=DEFAULT_RECALL_TOP_K,
|
||||
plan_required=bool(config[FIELD_PLAN_REQUIRED]),
|
||||
verify_required=bool(config[FIELD_VERIFY_REQUIRED]),
|
||||
platform_api_key=api_key,
|
||||
login_email="",
|
||||
login_password="",
|
||||
fetch_max_chars=DEFAULT_FETCH_MAX_CHARS,
|
||||
fetch_timeout_seconds=DEFAULT_FETCH_TIMEOUT_SECONDS,
|
||||
fetch_max_bytes=DEFAULT_FETCH_MAX_BYTES,
|
||||
fetch_allow_private=False,
|
||||
allow_eval=bool(config.get(FIELD_ALLOW_EVAL, True)),
|
||||
rsearch_enabled=bool(config.get(FIELD_RSEARCH_ENABLED, True)),
|
||||
rsearch_url=(config.get(FIELD_RSEARCH_URL) or DEFAULT_RSEARCH_URL).rstrip("/"),
|
||||
)
|
||||
Reference in New Issue
Block a user