Files
chenlin f3a8a38acd
web-platform-ci / Standalone decision service (no cloud credentials) (push) Has been cancelled
web-platform-ci / TypeScript, lint, unit, build (push) Has been cancelled
web-platform-ci / Playwright E2E (push) Has been cancelled
lekiwi-compatibility / cpu-compatibility (push) Has been cancelled
web-platform-ci / Standalone decision service (no cloud credentials) (pull_request) Has been cancelled
web-platform-ci / TypeScript, lint, unit, build (pull_request) Has been cancelled
web-platform-ci / Playwright E2E (pull_request) Has been cancelled
lekiwi-compatibility / cpu-compatibility (pull_request) Has been cancelled
feat: release v1.0.1 CADWorld 网站与 LeKiwi 智能抓放
集成同源 BYOK 会话隔离、精简模型设置、官方订阅入口和 HTTPS 发布运维;保留本地训练/调参与控制能力。同步 npm 版本及 CHANGELOG,记录公网真实 API 验收仍待用户凭据。
2026-09-24 09:57:41 +08:00

99 lines
3.4 KiB
Python

"""Website configuration: explicit provider catalog, atomic in-memory credentials."""
from urllib.parse import urlsplit
from .connections import Connections
from .credentials import OPENROUTER_ENDPOINT, OPENROUTER_JEV
from .protocol import DecisionError, fields
DEEPSEEK_MODELS = ("deepseek-flash",)
COOKIE = "__Host-cadworld-session"
def website_origin(value, *, development=False):
url = urlsplit(value)
if (
url.scheme != "https"
and not (
development and url.scheme == "http" and url.hostname in ("localhost", "127.0.0.1")
)
) or (
not url.hostname or url.username or url.password or url.path or url.query or url.fragment
):
raise DecisionError("invalid_website_origin")
return url.netloc
class MemoryConnections(Connections):
def __init__(self):
self.values = {}
def set(self, data):
raise DecisionError("website_configuration_required")
def configure(values, data, openrouter_models, codex_models=()):
"""Return new values without mutation. Omitted key retains it only at the same provider."""
fields(data, ["llm", "jev"])
llm = fields(data["llm"], ["provider", "model"], ["apiKey"])
jev = fields(data["jev"], [], ["apiKey"])
provider, model = llm["provider"], llm["model"]
if not isinstance(provider, str) or not isinstance(model, str):
raise DecisionError("invalid_provider")
choices = {
"deepseek": ("responses", "https://api.deepseek.com", DEEPSEEK_MODELS),
"openrouter": ("chat-completions", "https://openrouter.ai/api/v1", openrouter_models),
"codex": ("codex", "", codex_models),
}
if provider not in choices:
raise DecisionError("invalid_provider")
protocol, url, models = choices[provider]
if model not in models:
raise DecisionError("model_unavailable", 409)
def connection(role, protocol, url, model, draft):
old = values.get(role)
key = draft.get("apiKey")
if key is None and "apiKey" not in draft:
key = old.key if old and old.protocol == protocol and old.base_url == url else ""
if protocol != "codex" and not key:
raise DecisionError("api_key_required", 409)
return Connections.parse(
{
"role": role,
"protocol": protocol,
"baseUrl": url,
"model": model,
"apiKey": key or "",
}
)
result = {
"llm": connection("llm", protocol, url, model, llm),
"jev": connection("jev", "openrouter-decisions", OPENROUTER_ENDPOINT, OPENROUTER_JEV, jev),
}
# Do not allow a credential to escape through any other role's public metadata.
metadata = str(public_config(result))
if any(c.key and c.key in metadata for c in [*values.values(), *result.values()]):
raise DecisionError("credential_in_metadata")
return result
def public_config(values):
llm, jev = values.get("llm"), values.get("jev")
provider = (
"codex"
if llm and llm.protocol == "codex"
else "openrouter"
if llm and llm.protocol == "chat-completions"
else "deepseek"
)
return {
"llm": {
"provider": provider,
"model": llm.model if llm else DEEPSEEK_MODELS[0],
"hasKey": bool(llm and llm.key),
},
"jev": {"hasKey": bool(jev and jev.key), "model": OPENROUTER_JEV},
}