10xgraph-api 0.7.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 10xgraph_api-0.7.0.dist-info/METADATA +618 -0
- 10xgraph_api-0.7.0.dist-info/RECORD +203 -0
- 10xgraph_api-0.7.0.dist-info/WHEEL +5 -0
- 10xgraph_api-0.7.0.dist-info/entry_points.txt +3 -0
- 10xgraph_api-0.7.0.dist-info/licenses/LICENSE +21 -0
- 10xgraph_api-0.7.0.dist-info/top_level.txt +2 -0
- agentflow_cli/__init__.py +69 -0
- tenxgraph_api/__init__.py +23 -0
- tenxgraph_api/cli/__init__.py +6 -0
- tenxgraph_api/cli/capabilities.py +127 -0
- tenxgraph_api/cli/commands/__init__.py +49 -0
- tenxgraph_api/cli/commands/api.py +262 -0
- tenxgraph_api/cli/commands/audit.py +213 -0
- tenxgraph_api/cli/commands/build.py +305 -0
- tenxgraph_api/cli/commands/config.py +71 -0
- tenxgraph_api/cli/commands/demo.py +93 -0
- tenxgraph_api/cli/commands/eval.py +909 -0
- tenxgraph_api/cli/commands/init.py +531 -0
- tenxgraph_api/cli/commands/skills.py +532 -0
- tenxgraph_api/cli/commands/test.py +113 -0
- tenxgraph_api/cli/commands/version.py +47 -0
- tenxgraph_api/cli/config_editor/__init__.py +15 -0
- tenxgraph_api/cli/config_editor/schema.py +566 -0
- tenxgraph_api/cli/config_editor/server.py +240 -0
- tenxgraph_api/cli/config_editor/static/app.css +2 -0
- tenxgraph_api/cli/config_editor/static/app.js +3 -0
- tenxgraph_api/cli/config_editor/static/favicon.svg +11 -0
- tenxgraph_api/cli/config_editor/static/index.html +20 -0
- tenxgraph_api/cli/config_editor/store.py +120 -0
- tenxgraph_api/cli/config_editor/validation.py +377 -0
- tenxgraph_api/cli/constants.py +112 -0
- tenxgraph_api/cli/context.py +46 -0
- tenxgraph_api/cli/core/__init__.py +0 -0
- tenxgraph_api/cli/core/animations.py +550 -0
- tenxgraph_api/cli/core/config.py +279 -0
- tenxgraph_api/cli/core/output.py +625 -0
- tenxgraph_api/cli/core/prompts.py +220 -0
- tenxgraph_api/cli/core/screen.py +287 -0
- tenxgraph_api/cli/core/steps.py +621 -0
- tenxgraph_api/cli/core/theme.py +242 -0
- tenxgraph_api/cli/core/validation.py +251 -0
- tenxgraph_api/cli/exceptions.py +129 -0
- tenxgraph_api/cli/logger.py +84 -0
- tenxgraph_api/cli/main.py +936 -0
- tenxgraph_api/cli/templates/__init__.py +0 -0
- tenxgraph_api/cli/templates/defaults.py +844 -0
- tenxgraph_api/cli/templates/dev/.env.example +1 -0
- tenxgraph_api/cli/templates/dev/10xgraph.json +16 -0
- tenxgraph_api/cli/templates/dev/graph/__init__.py +0 -0
- tenxgraph_api/cli/templates/dev/graph/agent.py +63 -0
- tenxgraph_api/cli/templates/prod/.env.example +75 -0
- tenxgraph_api/cli/templates/prod/.pre-commit-config.yaml +50 -0
- tenxgraph_api/cli/templates/prod/.python-version +1 -0
- tenxgraph_api/cli/templates/prod/10xgraph.json +42 -0
- tenxgraph_api/cli/templates/prod/auth/__init__.py +0 -0
- tenxgraph_api/cli/templates/prod/auth/agent_auth.py +46 -0
- tenxgraph_api/cli/templates/prod/evals/__init__.py +0 -0
- tenxgraph_api/cli/templates/prod/evals/user_simulator_eval.py +76 -0
- tenxgraph_api/cli/templates/prod/evals/weather_agents_eval.py +53 -0
- tenxgraph_api/cli/templates/prod/graph/__init__.py +0 -0
- tenxgraph_api/cli/templates/prod/graph/agent.py +50 -0
- tenxgraph_api/cli/templates/prod/graph/state.py +5 -0
- tenxgraph_api/cli/templates/prod/graph/thread_name_generator.py +7 -0
- tenxgraph_api/cli/templates/prod/graph/tools/__init__.py +0 -0
- tenxgraph_api/cli/templates/prod/graph/tools/weather_tool.py +43 -0
- tenxgraph_api/cli/templates/prod/graph/validators/__init__.py +0 -0
- tenxgraph_api/cli/templates/prod/graph/validators/lifecyle.py +107 -0
- tenxgraph_api/cli/templates/prod/graph/validators/manager.py +9 -0
- tenxgraph_api/cli/templates/prod/graph/validators/validators.py +21 -0
- tenxgraph_api/cli/templates/prod/pyproject.toml +79 -0
- tenxgraph_api/cli/templates/prod/tests/__init__.py +0 -0
- tenxgraph_api/cli/templates/prod/tests/conftest.py +6 -0
- tenxgraph_api/cli/templates/prod/tests/test_agent_eval.py +78 -0
- tenxgraph_api/cli/templates/prod/tests/test_catalog_tools.py +47 -0
- tenxgraph_api/cli/templates/prod/tests/test_graph_nodes.py +57 -0
- tenxgraph_api/cli/templates/skills/10xgraph/SKILL.md +92 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/agents-and-tools.md +389 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/api-client.md +61 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/api-configuration.md +75 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/api-settings-and-middleware.md +89 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/architecture.md +91 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/auth-and-authorization.md +149 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/callbacks-and-command.md +283 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/checkpointing-and-threads.md +63 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/cli-commands.md +73 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/client-auth-and-errors.md +94 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/client-messages-invoke-stream.md +115 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/client-threads-memory-files.md +80 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/context-id-background.md +80 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/dependency-injection.md +58 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/evaluation.md +500 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/id-and-thread-name-generators.md +69 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/media-and-files.md +66 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/memory-and-store.md +70 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/prebuilt-agents-and-tools.md +394 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/production-runtime.md +56 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/providers-and-adapters.md +89 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/publishers-and-runtime-protocols.md +84 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/rate-limiting.md +194 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/realtime.md +172 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/remote-tools.md +55 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/rest-api-and-errors.md +97 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/security-and-validators.md +86 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/state-and-messages.md +68 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/state-graph.md +232 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/stream-emitter.md +144 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/streaming.md +53 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/testing-and-evaluation.md +64 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/unit-testing.md +202 -0
- tenxgraph_api/cli/templates/skills/copilot/10xgraph.instructions.md +108 -0
- tenxgraph_api/py.typed +0 -0
- tenxgraph_api/src/__init__.py +0 -0
- tenxgraph_api/src/app/__init__.py +13 -0
- tenxgraph_api/src/app/core/__init__.py +15 -0
- tenxgraph_api/src/app/core/auth/__init__.py +0 -0
- tenxgraph_api/src/app/core/auth/auth_backend.py +38 -0
- tenxgraph_api/src/app/core/auth/authorization.py +379 -0
- tenxgraph_api/src/app/core/auth/base_auth.py +27 -0
- tenxgraph_api/src/app/core/auth/jwt_auth.py +122 -0
- tenxgraph_api/src/app/core/auth/ownership_resolver.py +170 -0
- tenxgraph_api/src/app/core/auth/permissions.py +354 -0
- tenxgraph_api/src/app/core/auth/request_config.py +130 -0
- tenxgraph_api/src/app/core/auth/route_guard.py +105 -0
- tenxgraph_api/src/app/core/config/__init__.py +0 -0
- tenxgraph_api/src/app/core/config/graph_config.py +532 -0
- tenxgraph_api/src/app/core/config/media_settings.py +72 -0
- tenxgraph_api/src/app/core/config/sentry_config.py +60 -0
- tenxgraph_api/src/app/core/config/settings.py +202 -0
- tenxgraph_api/src/app/core/config/setup_logs.py +65 -0
- tenxgraph_api/src/app/core/config/setup_middleware.py +483 -0
- tenxgraph_api/src/app/core/config/worker_middleware.py +99 -0
- tenxgraph_api/src/app/core/exceptions/__init__.py +17 -0
- tenxgraph_api/src/app/core/exceptions/general_exception.py +58 -0
- tenxgraph_api/src/app/core/exceptions/handle_errors.py +363 -0
- tenxgraph_api/src/app/core/exceptions/resources_exceptions.py +72 -0
- tenxgraph_api/src/app/core/exceptions/user_exception.py +58 -0
- tenxgraph_api/src/app/core/middleware/__init__.py +25 -0
- tenxgraph_api/src/app/core/middleware/rate_limit/__init__.py +15 -0
- tenxgraph_api/src/app/core/middleware/rate_limit/base.py +27 -0
- tenxgraph_api/src/app/core/middleware/rate_limit/factory.py +98 -0
- tenxgraph_api/src/app/core/middleware/rate_limit/keying.py +133 -0
- tenxgraph_api/src/app/core/middleware/rate_limit/memory.py +98 -0
- tenxgraph_api/src/app/core/middleware/rate_limit/middleware.py +90 -0
- tenxgraph_api/src/app/core/middleware/rate_limit/redis.py +115 -0
- tenxgraph_api/src/app/core/middleware/request_limits.py +154 -0
- tenxgraph_api/src/app/core/middleware/security_headers.py +239 -0
- tenxgraph_api/src/app/core/utils/__init__.py +14 -0
- tenxgraph_api/src/app/core/utils/log_sanitizer.py +216 -0
- tenxgraph_api/src/app/loader.py +516 -0
- tenxgraph_api/src/app/main.py +180 -0
- tenxgraph_api/src/app/routers/__init__.py +4 -0
- tenxgraph_api/src/app/routers/ag_ui/__init__.py +10 -0
- tenxgraph_api/src/app/routers/ag_ui/converter.py +195 -0
- tenxgraph_api/src/app/routers/ag_ui/event_mapper.py +353 -0
- tenxgraph_api/src/app/routers/ag_ui/router.py +90 -0
- tenxgraph_api/src/app/routers/ag_ui/service.py +193 -0
- tenxgraph_api/src/app/routers/checkpointer/__init__.py +1 -0
- tenxgraph_api/src/app/routers/checkpointer/router.py +482 -0
- tenxgraph_api/src/app/routers/checkpointer/schemas/__init__.py +1 -0
- tenxgraph_api/src/app/routers/checkpointer/schemas/checkpointer_schemas.py +121 -0
- tenxgraph_api/src/app/routers/checkpointer/services/__init__.py +1 -0
- tenxgraph_api/src/app/routers/checkpointer/services/checkpointer_service.py +300 -0
- tenxgraph_api/src/app/routers/evals/__init__.py +6 -0
- tenxgraph_api/src/app/routers/evals/router.py +38 -0
- tenxgraph_api/src/app/routers/evals/services/__init__.py +1 -0
- tenxgraph_api/src/app/routers/evals/services/eval_report_service.py +354 -0
- tenxgraph_api/src/app/routers/graph/__init__.py +6 -0
- tenxgraph_api/src/app/routers/graph/realtime_guard.py +161 -0
- tenxgraph_api/src/app/routers/graph/router.py +821 -0
- tenxgraph_api/src/app/routers/graph/schemas/__init__.py +1 -0
- tenxgraph_api/src/app/routers/graph/schemas/graph_schemas.py +386 -0
- tenxgraph_api/src/app/routers/graph/services/__init__.py +1 -0
- tenxgraph_api/src/app/routers/graph/services/graph_service.py +1219 -0
- tenxgraph_api/src/app/routers/graph/services/multimodal_preprocessor.py +164 -0
- tenxgraph_api/src/app/routers/media/__init__.py +506 -0
- tenxgraph_api/src/app/routers/media/router.py +242 -0
- tenxgraph_api/src/app/routers/media/schemas.py +39 -0
- tenxgraph_api/src/app/routers/ping/__init__.py +4 -0
- tenxgraph_api/src/app/routers/ping/router.py +28 -0
- tenxgraph_api/src/app/routers/setup_router.py +60 -0
- tenxgraph_api/src/app/routers/store/__init__.py +4 -0
- tenxgraph_api/src/app/routers/store/router.py +200 -0
- tenxgraph_api/src/app/routers/store/schemas/__init__.py +28 -0
- tenxgraph_api/src/app/routers/store/schemas/store_schemas.py +200 -0
- tenxgraph_api/src/app/routers/store/services/__init__.py +4 -0
- tenxgraph_api/src/app/routers/store/services/store_service.py +203 -0
- tenxgraph_api/src/app/tasks/__init__.py +0 -0
- tenxgraph_api/src/app/tasks/user_tasks.py +38 -0
- tenxgraph_api/src/app/utils/__init__.py +12 -0
- tenxgraph_api/src/app/utils/callable_helper.py +26 -0
- tenxgraph_api/src/app/utils/media/__init__.py +15 -0
- tenxgraph_api/src/app/utils/media/extractor.py +172 -0
- tenxgraph_api/src/app/utils/media/pipeline.py +83 -0
- tenxgraph_api/src/app/utils/parse_output.py +17 -0
- tenxgraph_api/src/app/utils/response_helper.py +129 -0
- tenxgraph_api/src/app/utils/schemas/__init__.py +11 -0
- tenxgraph_api/src/app/utils/schemas/output_schemas.py +28 -0
- tenxgraph_api/src/app/utils/schemas/user_schemas.py +13 -0
- tenxgraph_api/src/app/utils/snowflake_id_generator.py +90 -0
- tenxgraph_api/src/app/utils/swagger_helper.py +160 -0
- tenxgraph_api/src/app/utils/telemetry_store.py +123 -0
- tenxgraph_api/src/app/utils/thread_name_generator.py +304 -0
- tenxgraph_api/src/app/worker.py +91 -0
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
"""Loopback-only HTTP server behind ``10xgraph config``.
|
|
2
|
+
|
|
3
|
+
Routes:
|
|
4
|
+
GET / the editor page
|
|
5
|
+
GET /app.js the page's bundled script (built from config-editor-ui/)
|
|
6
|
+
GET /app.css the page's compiled Tailwind stylesheet
|
|
7
|
+
GET /favicon.svg the 10xGraph icon (copied from agentflow-docs/public/favicon.svg)
|
|
8
|
+
GET /api/state current file, schema, and validation issues
|
|
9
|
+
POST /api/validate validate a config without saving it
|
|
10
|
+
POST /api/save validate, then write the config file
|
|
11
|
+
|
|
12
|
+
Every ``/api`` call must carry the per-run token (sent by the page from the URL
|
|
13
|
+
fragment) and a loopback ``Host`` header. That keeps other sites open in the same
|
|
14
|
+
browser from reading or overwriting the file, including via DNS rebinding.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
import hmac
|
|
20
|
+
import json
|
|
21
|
+
import secrets
|
|
22
|
+
import threading
|
|
23
|
+
from http import HTTPStatus
|
|
24
|
+
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
|
|
25
|
+
from importlib.resources import files
|
|
26
|
+
from pathlib import Path
|
|
27
|
+
from typing import Any
|
|
28
|
+
|
|
29
|
+
from tenxgraph_api.cli.config_editor.schema import build_schema
|
|
30
|
+
from tenxgraph_api.cli.config_editor.store import ConfigConflictError, ConfigFileStore
|
|
31
|
+
from tenxgraph_api.cli.config_editor.validation import has_errors, validate_config
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
LOOPBACK_HOST = "127.0.0.1"
|
|
35
|
+
TOKEN_HEADER = "X-10xGraph-Token" # noqa: S105 - a header name, not a secret # nosec B105
|
|
36
|
+
MAX_BODY_BYTES = 1_000_000
|
|
37
|
+
NEW_FILE_TEMPLATE: dict[str, Any] = {"agent": "graph.agent:app", "env": ".env"}
|
|
38
|
+
|
|
39
|
+
# Static files the page loads: route -> (file under static/, content type).
|
|
40
|
+
_STATIC_FILES: dict[str, tuple[str, str]] = {
|
|
41
|
+
"/": ("index.html", "text/html; charset=utf-8"),
|
|
42
|
+
"/index.html": ("index.html", "text/html; charset=utf-8"),
|
|
43
|
+
"/app.js": ("app.js", "text/javascript; charset=utf-8"),
|
|
44
|
+
"/app.css": ("app.css", "text/css; charset=utf-8"),
|
|
45
|
+
# Same file as agentflow-docs/public/favicon.svg, so every 10xGraph surface shares one icon.
|
|
46
|
+
"/favicon.svg": ("favicon.svg", "image/svg+xml"),
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
_CSP = (
|
|
50
|
+
"default-src 'self'; "
|
|
51
|
+
"script-src 'self'; "
|
|
52
|
+
"style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; "
|
|
53
|
+
"font-src https://fonts.gstatic.com; "
|
|
54
|
+
"img-src 'self' data:; "
|
|
55
|
+
"connect-src 'self'; "
|
|
56
|
+
"frame-ancestors 'none'"
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class ConfigEditorServer:
|
|
61
|
+
"""Serve the editor for one config file on an ephemeral loopback port."""
|
|
62
|
+
|
|
63
|
+
def __init__(
|
|
64
|
+
self,
|
|
65
|
+
config_path: Path,
|
|
66
|
+
port: int = 0,
|
|
67
|
+
token: str | None = None,
|
|
68
|
+
seed_path: Path | None = None,
|
|
69
|
+
) -> None:
|
|
70
|
+
self.store = ConfigFileStore(config_path, seed_path=seed_path)
|
|
71
|
+
self.token = token or secrets.token_urlsafe(24)
|
|
72
|
+
self._httpd = ThreadingHTTPServer((LOOPBACK_HOST, port), _Handler)
|
|
73
|
+
self._httpd.daemon_threads = True
|
|
74
|
+
self._httpd.editor = self # type: ignore[attr-defined]
|
|
75
|
+
self._thread: threading.Thread | None = None
|
|
76
|
+
|
|
77
|
+
@property
|
|
78
|
+
def port(self) -> int:
|
|
79
|
+
return int(self._httpd.server_address[1])
|
|
80
|
+
|
|
81
|
+
@property
|
|
82
|
+
def url(self) -> str:
|
|
83
|
+
return f"http://{LOOPBACK_HOST}:{self.port}/#token={self.token}"
|
|
84
|
+
|
|
85
|
+
def serve_forever(self) -> None:
|
|
86
|
+
self._httpd.serve_forever()
|
|
87
|
+
|
|
88
|
+
def start_in_background(self) -> None:
|
|
89
|
+
self._thread = threading.Thread(
|
|
90
|
+
target=self._httpd.serve_forever, name="10xgraph-config-editor", daemon=True
|
|
91
|
+
)
|
|
92
|
+
self._thread.start()
|
|
93
|
+
|
|
94
|
+
def shutdown(self) -> None:
|
|
95
|
+
if self._thread is not None:
|
|
96
|
+
self._httpd.shutdown()
|
|
97
|
+
self._thread.join(timeout=5)
|
|
98
|
+
self._thread = None
|
|
99
|
+
self._httpd.server_close()
|
|
100
|
+
|
|
101
|
+
# -- request handling ---------------------------------------------------
|
|
102
|
+
|
|
103
|
+
def state(self) -> dict[str, Any]:
|
|
104
|
+
loaded = self.store.load()
|
|
105
|
+
config = loaded.config
|
|
106
|
+
issues = validate_config(config, self.store.path.parent) if config is not None else []
|
|
107
|
+
return {
|
|
108
|
+
"path": str(self.store.path),
|
|
109
|
+
"exists": loaded.version is not None,
|
|
110
|
+
"version": loaded.version,
|
|
111
|
+
"parse_error": loaded.parse_error,
|
|
112
|
+
"config": config if config is not None else dict(NEW_FILE_TEMPLATE),
|
|
113
|
+
"schema": build_schema(),
|
|
114
|
+
"issues": issues,
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
def validate(self, config: Any) -> dict[str, Any]:
|
|
118
|
+
return {"issues": validate_config(config, self.store.path.parent)}
|
|
119
|
+
|
|
120
|
+
def save(self, config: Any, version: str | None) -> tuple[HTTPStatus, dict[str, Any]]:
|
|
121
|
+
issues = validate_config(config, self.store.path.parent)
|
|
122
|
+
if has_errors(issues):
|
|
123
|
+
return HTTPStatus.UNPROCESSABLE_ENTITY, {
|
|
124
|
+
"error": "Fix the errors before saving.",
|
|
125
|
+
"issues": issues,
|
|
126
|
+
}
|
|
127
|
+
try:
|
|
128
|
+
new_version = self.store.save(config, version)
|
|
129
|
+
except ConfigConflictError as exc:
|
|
130
|
+
return HTTPStatus.CONFLICT, {"error": str(exc), "issues": issues}
|
|
131
|
+
except OSError as exc:
|
|
132
|
+
return HTTPStatus.INTERNAL_SERVER_ERROR, {
|
|
133
|
+
"error": f"Could not write {self.store.path}: {exc}",
|
|
134
|
+
"issues": issues,
|
|
135
|
+
}
|
|
136
|
+
backup = self.store.backup_path
|
|
137
|
+
return HTTPStatus.OK, {
|
|
138
|
+
"version": new_version,
|
|
139
|
+
"config": self.store.load().config, # as written, in the file's key order
|
|
140
|
+
"path": str(self.store.path),
|
|
141
|
+
"backup": str(backup) if backup.exists() else None,
|
|
142
|
+
"issues": issues,
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
def allowed_hosts(self) -> set[str]:
|
|
146
|
+
return {f"{LOOPBACK_HOST}:{self.port}", f"localhost:{self.port}"}
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
class _Handler(BaseHTTPRequestHandler):
|
|
150
|
+
server_version = "10xGraphConfig"
|
|
151
|
+
|
|
152
|
+
@property
|
|
153
|
+
def editor(self) -> ConfigEditorServer:
|
|
154
|
+
return self.server.editor # type: ignore[attr-defined]
|
|
155
|
+
|
|
156
|
+
def log_message(self, format: str, *args: Any) -> None: # noqa: A002
|
|
157
|
+
"""Keep the terminal quiet; the CLI prints its own status."""
|
|
158
|
+
|
|
159
|
+
def do_GET(self) -> None:
|
|
160
|
+
if not self._host_allowed():
|
|
161
|
+
return
|
|
162
|
+
route = self.path.split("?", 1)[0]
|
|
163
|
+
if route in _STATIC_FILES:
|
|
164
|
+
name, content_type = _STATIC_FILES[route]
|
|
165
|
+
asset = files("tenxgraph_api.cli.config_editor").joinpath("static", name)
|
|
166
|
+
self._send(HTTPStatus.OK, asset.read_bytes(), content_type)
|
|
167
|
+
elif route == "/api/state":
|
|
168
|
+
if self._authorized():
|
|
169
|
+
self._send_json(HTTPStatus.OK, self.editor.state())
|
|
170
|
+
else:
|
|
171
|
+
self._send_json(HTTPStatus.NOT_FOUND, {"error": "Not found"})
|
|
172
|
+
|
|
173
|
+
def do_POST(self) -> None:
|
|
174
|
+
if not self._host_allowed() or not self._authorized():
|
|
175
|
+
return
|
|
176
|
+
body = self._read_json()
|
|
177
|
+
if body is None:
|
|
178
|
+
return
|
|
179
|
+
route = self.path.split("?", 1)[0]
|
|
180
|
+
if route == "/api/validate":
|
|
181
|
+
self._send_json(HTTPStatus.OK, self.editor.validate(body.get("config")))
|
|
182
|
+
elif route == "/api/save":
|
|
183
|
+
status, payload = self.editor.save(body.get("config"), body.get("version"))
|
|
184
|
+
self._send_json(status, payload)
|
|
185
|
+
else:
|
|
186
|
+
self._send_json(HTTPStatus.NOT_FOUND, {"error": "Not found"})
|
|
187
|
+
|
|
188
|
+
# -- guards ---------------------------------------------------------------
|
|
189
|
+
|
|
190
|
+
def _host_allowed(self) -> bool:
|
|
191
|
+
if self.headers.get("Host", "") in self.editor.allowed_hosts():
|
|
192
|
+
return True
|
|
193
|
+
self._send_json(HTTPStatus.FORBIDDEN, {"error": "Unexpected Host header"})
|
|
194
|
+
return False
|
|
195
|
+
|
|
196
|
+
def _authorized(self) -> bool:
|
|
197
|
+
supplied = self.headers.get(TOKEN_HEADER, "")
|
|
198
|
+
if hmac.compare_digest(supplied.encode(), self.editor.token.encode()):
|
|
199
|
+
return True
|
|
200
|
+
self._send_json(HTTPStatus.FORBIDDEN, {"error": "Missing or invalid session token"})
|
|
201
|
+
return False
|
|
202
|
+
|
|
203
|
+
def _read_json(self) -> dict[str, Any] | None:
|
|
204
|
+
content_type = self.headers.get("Content-Type", "").split(";", 1)[0].strip()
|
|
205
|
+
if content_type != "application/json":
|
|
206
|
+
self._send_json(HTTPStatus.UNSUPPORTED_MEDIA_TYPE, {"error": "Expected JSON"})
|
|
207
|
+
return None
|
|
208
|
+
try:
|
|
209
|
+
length = int(self.headers.get("Content-Length", "0"))
|
|
210
|
+
except ValueError:
|
|
211
|
+
length = -1
|
|
212
|
+
if length < 0 or length > MAX_BODY_BYTES:
|
|
213
|
+
self._send_json(HTTPStatus.REQUEST_ENTITY_TOO_LARGE, {"error": "Body too large"})
|
|
214
|
+
return None
|
|
215
|
+
try:
|
|
216
|
+
body = json.loads(self.rfile.read(length) or b"{}")
|
|
217
|
+
except json.JSONDecodeError as exc:
|
|
218
|
+
self._send_json(HTTPStatus.BAD_REQUEST, {"error": f"Invalid JSON: {exc}"})
|
|
219
|
+
return None
|
|
220
|
+
if not isinstance(body, dict):
|
|
221
|
+
self._send_json(HTTPStatus.BAD_REQUEST, {"error": "Expected a JSON object"})
|
|
222
|
+
return None
|
|
223
|
+
return body
|
|
224
|
+
|
|
225
|
+
# -- responses ------------------------------------------------------------
|
|
226
|
+
|
|
227
|
+
def _send_json(self, status: HTTPStatus, payload: dict[str, Any]) -> None:
|
|
228
|
+
body = json.dumps(payload, ensure_ascii=False).encode("utf-8")
|
|
229
|
+
self._send(status, body, "application/json; charset=utf-8")
|
|
230
|
+
|
|
231
|
+
def _send(self, status: HTTPStatus, body: bytes, content_type: str) -> None:
|
|
232
|
+
self.send_response(status)
|
|
233
|
+
self.send_header("Content-Type", content_type)
|
|
234
|
+
self.send_header("Content-Length", str(len(body)))
|
|
235
|
+
self.send_header("Cache-Control", "no-store")
|
|
236
|
+
self.send_header("X-Content-Type-Options", "nosniff")
|
|
237
|
+
self.send_header("Referrer-Policy", "no-referrer")
|
|
238
|
+
self.send_header("Content-Security-Policy", _CSP)
|
|
239
|
+
self.end_headers()
|
|
240
|
+
self.wfile.write(body)
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
|
|
2
|
+
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-space-y-reverse:0;--tw-divide-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-ease:initial;--tw-content:""}}}@layer theme{:root,:host{--font-sans:"Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;--font-mono:"JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-xs:20rem;--container-sm:24rem;--container-4xl:56rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height:calc(1.5 / 1);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-tight:-.025em;--tracking-wide:.025em;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--ease-out:cubic-bezier(0, 0, .2, 1);--animate-spin:spin 1s linear infinite;--animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-canvas:var(--af-canvas);--color-surface:var(--af-surface);--color-raised:var(--af-raised);--color-hover:var(--af-hover);--color-sunken:var(--af-sunken);--color-line:var(--af-line);--color-line-strong:var(--af-line-strong);--color-ink:var(--af-ink);--color-body:var(--af-body);--color-muted:var(--af-muted);--color-faint:var(--af-faint);--color-brand:var(--af-brand);--color-brand-solid:var(--af-brand-solid);--color-brand-solid-hover:var(--af-brand-solid-hover);--color-brand-soft:var(--af-brand-soft);--color-brand-ring:var(--af-brand-ring);--color-brand-amber:var(--af-brand-amber);--color-ok:var(--af-ok);--color-ok-soft:var(--af-ok-soft);--color-warn:var(--af-warn);--color-warn-soft:var(--af-warn-soft);--color-danger:var(--af-danger);--color-danger-soft:var(--af-danger-soft)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}html{scrollbar-gutter:stable}body{background-color:var(--color-canvas);font-family:var(--font-sans);color:var(--color-body);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}*{scrollbar-width:thin;scrollbar-color:var(--af-scrollbar) transparent}::-webkit-scrollbar{width:10px;height:10px}::-webkit-scrollbar-track{background:0 0}::-webkit-scrollbar-thumb{background:var(--af-scrollbar) padding-box;border:3px solid #0000;border-radius:9999px}::-webkit-scrollbar-thumb:hover{background:var(--af-scrollbar-hover) padding-box}::-webkit-scrollbar-corner{background:0 0}}@layer components{.input{height:calc(var(--spacing) * 10);border-radius:var(--radius-lg);border-style:var(--tw-border-style);border-width:1px;border-color:var(--color-line-strong);background-color:var(--color-sunken);width:100%;padding-inline:calc(var(--spacing) * 3);font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height));color:var(--color-ink);transition-property:border-color,box-shadow;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));--tw-duration:.15s;transition-duration:.15s;display:block}.input::placeholder{color:var(--color-faint)}@media (hover:hover){.input:hover{border-color:var(--color-faint)}@supports (color:color-mix(in lab, red, red)){.input:hover{border-color:color-mix(in oklab, var(--color-faint) 60%, transparent)}}}.input:focus{border-color:var(--color-brand);--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);--tw-ring-color:var(--color-brand-ring);--tw-outline-style:none;outline-style:none}@media (min-width:40rem){.input{height:calc(var(--spacing) * 9);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}}.input-invalid{border-color:var(--color-danger)}.input-invalid:focus{border-color:var(--color-danger);--tw-ring-color:var(--color-danger-soft)}.btn{height:calc(var(--spacing) * 10);cursor:pointer;justify-content:center;align-items:center;gap:calc(var(--spacing) * 2);border-radius:var(--radius-lg);padding-inline:calc(var(--spacing) * 3.5);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium);white-space:nowrap;transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));--tw-duration:.15s;flex-shrink:0;transition-duration:.15s;display:inline-flex}.btn:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);--tw-ring-color:var(--color-brand-ring);--tw-outline-style:none;outline-style:none}.btn:disabled{cursor:not-allowed;opacity:.45}@media (min-width:40rem){.btn{height:calc(var(--spacing) * 9)}}.btn-primary{background-color:var(--color-brand-solid);color:var(--color-white);--tw-shadow:var(--af-shadow);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}@media (hover:hover){.btn-primary:hover{background-color:var(--color-brand-solid-hover)}}.btn-outline{border-style:var(--tw-border-style);border-width:1px;border-color:var(--color-line-strong);background-color:var(--color-surface);color:var(--color-body)}@media (hover:hover){.btn-outline:hover{background-color:var(--color-raised)}}.btn-ghost{color:var(--color-muted)}@media (hover:hover){.btn-ghost:hover{background-color:var(--color-raised);color:var(--color-ink)}}.icon-btn{width:calc(var(--spacing) * 10);height:calc(var(--spacing) * 10);cursor:pointer;border-radius:var(--radius-lg);color:var(--color-muted);transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));--tw-duration:.15s;flex-shrink:0;justify-content:center;align-items:center;transition-duration:.15s;display:inline-flex}@media (hover:hover){.icon-btn:hover{background-color:var(--color-raised);color:var(--color-ink)}}.icon-btn:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);--tw-ring-color:var(--color-brand-ring);--tw-outline-style:none;outline-style:none}@media (min-width:40rem){.icon-btn{width:calc(var(--spacing) * 9);height:calc(var(--spacing) * 9)}}.panel{border-radius:var(--radius-xl);border-style:var(--tw-border-style);border-width:1px;border-color:var(--color-line);background-color:var(--color-surface);--tw-shadow:var(--af-shadow);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.kbd{height:calc(var(--spacing) * 5);border-style:var(--tw-border-style);border-width:1px;border-color:#ffffff40;border-radius:.25rem;align-items:center;display:inline-flex}@supports (color:color-mix(in lab, red, red)){.kbd{border-color:color-mix(in oklab, var(--color-white) 25%, transparent)}}.kbd{padding-inline:calc(var(--spacing) * 1.5);font-family:var(--font-mono);--tw-font-weight:var(--font-weight-medium);font-size:11px;font-weight:var(--font-weight-medium);color:#fffc}@supports (color:color-mix(in lab, red, red)){.kbd{color:color-mix(in oklab, var(--color-white) 80%, transparent)}}.eyebrow{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height));--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold);--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide);color:var(--color-faint);text-transform:uppercase}.focus-ring:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);--tw-ring-color:var(--color-brand-ring);--tw-outline-style:none;outline-style:none}}@layer utilities{.pointer-events-auto{pointer-events:auto}.pointer-events-none{pointer-events:none}.collapse{visibility:collapse}.sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.inset-y-0{inset-block:0}.top-0{top:0}.top-1{top:var(--spacing)}.top-1\/2{top:50%}.top-14{top:calc(var(--spacing) * 14)}.right-0{right:0}.right-1{right:var(--spacing)}.right-3{right:calc(var(--spacing) * 3)}.right-4{right:calc(var(--spacing) * 4)}.bottom-4{bottom:calc(var(--spacing) * 4)}.left-4{left:calc(var(--spacing) * 4)}.z-20{z-index:20}.z-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.-mx-4{margin-inline:calc(var(--spacing) * -4)}.mx-4{margin-inline:calc(var(--spacing) * 4)}.mx-auto{margin-inline:auto}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:var(--spacing)}.mt-1\.5{margin-top:calc(var(--spacing) * 1.5)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mt-5{margin-top:calc(var(--spacing) * 5)}.mt-6{margin-top:calc(var(--spacing) * 6)}.mt-10{margin-top:calc(var(--spacing) * 10)}.-mr-1{margin-right:calc(var(--spacing) * -1)}.mr-1\.5{margin-right:calc(var(--spacing) * 1.5)}.mb-1\.5{margin-bottom:calc(var(--spacing) * 1.5)}.mb-2\.5{margin-bottom:calc(var(--spacing) * 2.5)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.-ml-2\.5{margin-left:calc(var(--spacing) * -2.5)}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.size-1\.5{width:calc(var(--spacing) * 1.5);height:calc(var(--spacing) * 1.5)}.size-3{width:calc(var(--spacing) * 3);height:calc(var(--spacing) * 3)}.size-3\.5{width:calc(var(--spacing) * 3.5);height:calc(var(--spacing) * 3.5)}.size-4{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.size-5{width:calc(var(--spacing) * 5);height:calc(var(--spacing) * 5)}.size-6{width:calc(var(--spacing) * 6);height:calc(var(--spacing) * 6)}.size-7{width:calc(var(--spacing) * 7);height:calc(var(--spacing) * 7)}.size-9{width:calc(var(--spacing) * 9);height:calc(var(--spacing) * 9)}.size-11{width:calc(var(--spacing) * 11);height:calc(var(--spacing) * 11)}.size-\[18px\]{width:18px;height:18px}.size-full{width:100%;height:100%}.h-4{height:calc(var(--spacing) * 4)}.h-5{height:calc(var(--spacing) * 5)}.h-6{height:calc(var(--spacing) * 6)}.h-7{height:calc(var(--spacing) * 7)}.h-8{height:calc(var(--spacing) * 8)}.h-9{height:calc(var(--spacing) * 9)}.h-12{height:calc(var(--spacing) * 12)}.h-14{height:calc(var(--spacing) * 14)}.h-16{height:calc(var(--spacing) * 16)}.h-auto{height:auto}.min-h-0{min-height:0}.min-h-10{min-height:calc(var(--spacing) * 10)}.w-6{width:calc(var(--spacing) * 6)}.w-9{width:calc(var(--spacing) * 9)}.w-10{width:calc(var(--spacing) * 10)}.w-48{width:calc(var(--spacing) * 48)}.w-80{width:calc(var(--spacing) * 80)}.w-\[min\(100vw\,400px\)\]{width:min(100vw,400px)}.w-full{width:100%}.w-px{width:1px}.max-w-4xl{max-width:var(--container-4xl)}.max-w-full{max-width:100%}.max-w-prose{max-width:65ch}.max-w-sm{max-width:var(--container-sm)}.max-w-xs{max-width:var(--container-xs)}.min-w-0{min-width:0}.min-w-5{min-width:calc(var(--spacing) * 5)}.min-w-\[7rem\]{min-width:7rem}.flex-1{flex:1}.shrink-0{flex-shrink:0}.translate-x-0{--tw-translate-x:0px;translate:var(--tw-translate-x) var(--tw-translate-y)}.translate-x-0\.5{--tw-translate-x:calc(var(--spacing) * .5);translate:var(--tw-translate-x) var(--tw-translate-y)}.translate-x-\[18px\]{--tw-translate-x:18px;translate:var(--tw-translate-x) var(--tw-translate-y)}.translate-x-full{--tw-translate-x:100%;translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-y-1\/2{--tw-translate-y:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.-rotate-90{rotate:-90deg}.animate-pulse{animation:var(--animate-pulse)}.animate-spin{animation:var(--animate-spin)}.cursor-pointer{cursor:pointer}.cursor-text{cursor:text}.scroll-mt-28{scroll-margin-top:calc(var(--spacing) * 28)}.scroll-mt-32{scroll-margin-top:calc(var(--spacing) * 32)}.\[scrollbar-width\:none\]{scrollbar-width:none}.appearance-none{appearance:none}.grid-cols-\[10rem_minmax\(0\,1fr\)_auto\]{grid-template-columns:10rem minmax(0,1fr) auto}.grid-rows-\[0fr\]{grid-template-rows:0fr}.grid-rows-\[1fr\]{grid-template-rows:1fr}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-0\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:var(--spacing)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-2\.5{gap:calc(var(--spacing) * 2.5)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-6{gap:calc(var(--spacing) * 6)}:where(.space-y-0\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * .5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * .5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(var(--spacing) * var(--tw-space-y-reverse));margin-block-end:calc(var(--spacing) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 6) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-y-reverse)))}.gap-x-2{column-gap:calc(var(--spacing) * 2)}.gap-y-0\.5{row-gap:calc(var(--spacing) * .5)}:where(.divide-y>:not(:last-child)){--tw-divide-y-reverse:0;border-bottom-style:var(--tw-border-style);border-top-style:var(--tw-border-style);border-top-width:calc(1px * var(--tw-divide-y-reverse));border-bottom-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)))}:where(.divide-line>:not(:last-child)){border-color:var(--color-line)}.justify-self-end{justify-self:flex-end}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.overscroll-contain{overscroll-behavior:contain}.rounded{border-radius:.25rem}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-xl{border-radius:var(--radius-xl)}.rounded-b-xl{border-bottom-right-radius:var(--radius-xl);border-bottom-left-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-brand{border-color:var(--color-brand)}.border-brand-solid{border-color:var(--color-brand-solid)}.border-brand\/20{border-color:var(--color-brand)}@supports (color:color-mix(in lab, red, red)){.border-brand\/20{border-color:color-mix(in oklab, var(--color-brand) 20%, transparent)}}.border-danger\/25{border-color:var(--color-danger)}@supports (color:color-mix(in lab, red, red)){.border-danger\/25{border-color:color-mix(in oklab, var(--color-danger) 25%, transparent)}}.border-danger\/40{border-color:var(--color-danger)}@supports (color:color-mix(in lab, red, red)){.border-danger\/40{border-color:color-mix(in oklab, var(--color-danger) 40%, transparent)}}.border-line{border-color:var(--color-line)}.border-line-strong{border-color:var(--color-line-strong)}.border-warn\/25{border-color:var(--color-warn)}@supports (color:color-mix(in lab, red, red)){.border-warn\/25{border-color:color-mix(in oklab, var(--color-warn) 25%, transparent)}}.bg-black\/50{background-color:#00000080}@supports (color:color-mix(in lab, red, red)){.bg-black\/50{background-color:color-mix(in oklab, var(--color-black) 50%, transparent)}}.bg-brand-soft{background-color:var(--color-brand-soft)}.bg-brand-solid{background-color:var(--color-brand-solid)}.bg-canvas\/60{background-color:var(--color-canvas)}@supports (color:color-mix(in lab, red, red)){.bg-canvas\/60{background-color:color-mix(in oklab, var(--color-canvas) 60%, transparent)}}.bg-canvas\/90{background-color:var(--color-canvas)}@supports (color:color-mix(in lab, red, red)){.bg-canvas\/90{background-color:color-mix(in oklab, var(--color-canvas) 90%, transparent)}}.bg-danger{background-color:var(--color-danger)}.bg-danger-soft{background-color:var(--color-danger-soft)}.bg-line{background-color:var(--color-line)}.bg-line-strong{background-color:var(--color-line-strong)}.bg-ok-soft{background-color:var(--color-ok-soft)}.bg-raised{background-color:var(--color-raised)}.bg-sunken{background-color:var(--color-sunken)}.bg-surface,.bg-surface\/95{background-color:var(--color-surface)}@supports (color:color-mix(in lab, red, red)){.bg-surface\/95{background-color:color-mix(in oklab, var(--color-surface) 95%, transparent)}}.bg-transparent{background-color:#0000}.bg-warn{background-color:var(--color-warn)}.bg-warn-soft{background-color:var(--color-warn-soft)}.bg-white{background-color:var(--color-white)}.fill-brand-amber{fill:var(--color-brand-amber)}.p-4{padding:calc(var(--spacing) * 4)}.px-1{padding-inline:var(--spacing)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-5{padding-inline:calc(var(--spacing) * 5)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-3\.5{padding-block:calc(var(--spacing) * 3.5)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-5{padding-block:calc(var(--spacing) * 5)}.py-6{padding-block:calc(var(--spacing) * 6)}.py-10{padding-block:calc(var(--spacing) * 10)}.py-14{padding-block:calc(var(--spacing) * 14)}.pt-0\.5{padding-top:calc(var(--spacing) * .5)}.pt-8{padding-top:calc(var(--spacing) * 8)}.pr-0\.5{padding-right:calc(var(--spacing) * .5)}.pr-3{padding-right:calc(var(--spacing) * 3)}.pr-4{padding-right:calc(var(--spacing) * 4)}.pr-9{padding-right:calc(var(--spacing) * 9)}.pb-24{padding-bottom:calc(var(--spacing) * 24)}.pl-2{padding-left:calc(var(--spacing) * 2)}.pl-3{padding-left:calc(var(--spacing) * 3)}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.font-mono{font-family:var(--font-mono)}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[12\.5px\]{font-size:12.5px}.text-\[13px\]{font-size:13px}.text-\[15px\]{font-size:15px}.leading-4{--tw-leading:calc(var(--spacing) * 4);line-height:calc(var(--spacing) * 4)}.leading-5{--tw-leading:calc(var(--spacing) * 5);line-height:calc(var(--spacing) * 5)}.leading-6{--tw-leading:calc(var(--spacing) * 6);line-height:calc(var(--spacing) * 6)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.break-all{word-break:break-all}.whitespace-pre-wrap{white-space:pre-wrap}.text-body{color:var(--color-body)}.text-brand{color:var(--color-brand)}.text-danger{color:var(--color-danger)}.text-faint,.text-faint\/70{color:var(--color-faint)}@supports (color:color-mix(in lab, red, red)){.text-faint\/70{color:color-mix(in oklab, var(--color-faint) 70%, transparent)}}.text-ink{color:var(--color-ink)}.text-muted{color:var(--color-muted)}.text-ok{color:var(--color-ok)}.text-warn{color:var(--color-warn)}.text-white{color:var(--color-white)}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.shadow-card{--tw-shadow:var(--af-shadow);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-pop{--tw-shadow:var(--af-shadow-pop);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-1{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-black\/5{--tw-ring-color:#0000000d}@supports (color:color-mix(in lab, red, red)){.ring-black\/5{--tw-ring-color:color-mix(in oklab, var(--color-black) 5%, transparent)}}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.backdrop-blur{--tw-backdrop-blur:blur(8px);-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.transition-\[border-color\,box-shadow\]{transition-property:border-color,box-shadow;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[grid-template-rows\]{transition-property:grid-template-rows;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-150{--tw-duration:.15s;transition-duration:.15s}.duration-200{--tw-duration:.2s;transition-duration:.2s}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}.placeholder\:text-faint::placeholder{color:var(--color-faint)}.before\:absolute:before{content:var(--tw-content);position:absolute}.before\:-inset-2\.5:before{content:var(--tw-content);inset:calc(var(--spacing) * -2.5)}.before\:content-\[\'\'\]:before{--tw-content:"";content:var(--tw-content)}.focus-within\:border-brand:focus-within{border-color:var(--color-brand)}.focus-within\:ring-4:focus-within{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus-within\:ring-brand-ring:focus-within{--tw-ring-color:var(--color-brand-ring)}@media (hover:hover){.hover\:border-brand:hover{border-color:var(--color-brand)}.hover\:border-line-strong:hover{border-color:var(--color-line-strong)}.hover\:bg-hover:hover{background-color:var(--color-hover)}.hover\:bg-raised:hover{background-color:var(--color-raised)}.hover\:text-brand:hover{color:var(--color-brand)}.hover\:text-danger:hover{color:var(--color-danger)}.hover\:text-ink:hover{color:var(--color-ink)}.hover\:underline:hover{text-decoration-line:underline}}.focus\:not-sr-only:focus{clip-path:none;white-space:normal;width:auto;height:auto;margin:0;padding:0;position:static;overflow:visible}.focus\:fixed:focus{position:fixed}.focus\:top-3:focus{top:calc(var(--spacing) * 3)}.focus\:left-3:focus{left:calc(var(--spacing) * 3)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}@media (min-width:40rem){.sm\:left-auto{left:auto}.sm\:-mx-8{margin-inline:calc(var(--spacing) * -8)}.sm\:grid{display:grid}.sm\:inline{display:inline}.sm\:size-5{width:calc(var(--spacing) * 5);height:calc(var(--spacing) * 5)}.sm\:h-6{height:calc(var(--spacing) * 6)}.sm\:min-h-9{min-height:calc(var(--spacing) * 9)}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:grid-cols-\[10rem_minmax\(0\,1fr\)_auto\]{grid-template-columns:10rem minmax(0,1fr) auto}.sm\:grid-cols-\[minmax\(0\,1fr\)_minmax\(0\,1\.1fr\)\]{grid-template-columns:minmax(0,1fr) minmax(0,1.1fr)}.sm\:flex-row{flex-direction:row}.sm\:items-center{align-items:center}.sm\:items-start{align-items:flex-start}.sm\:justify-between{justify-content:space-between}.sm\:gap-3{gap:calc(var(--spacing) * 3)}.sm\:gap-6{gap:calc(var(--spacing) * 6)}.sm\:gap-8{gap:calc(var(--spacing) * 8)}.sm\:px-4{padding-inline:calc(var(--spacing) * 4)}.sm\:px-5{padding-inline:calc(var(--spacing) * 5)}.sm\:px-8{padding-inline:calc(var(--spacing) * 8)}.sm\:py-1{padding-block:var(--spacing)}.sm\:pt-0\.5{padding-top:calc(var(--spacing) * .5)}.sm\:pr-5{padding-right:calc(var(--spacing) * 5)}.sm\:pl-4{padding-left:calc(var(--spacing) * 4)}.sm\:text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}}@media (min-width:48rem){.md\:block{display:block}.md\:flex{display:flex}}@media (min-width:64rem){.lg\:block{display:block}.lg\:inline-flex{display:inline-flex}}@media (min-width:80rem){.xl\:sticky{position:sticky}.xl\:top-14{top:calc(var(--spacing) * 14)}.xl\:bottom-auto{bottom:auto}.xl\:z-auto{z-index:auto}.xl\:hidden{display:none}.xl\:h-\[calc\(100dvh-3\.5rem\)\]{height:calc(100dvh - 3.5rem)}.xl\:w-\[380px\]{width:380px}.xl\:shrink-0{flex-shrink:0}.xl\:translate-x-0{--tw-translate-x:0px;translate:var(--tw-translate-x) var(--tw-translate-y)}.xl\:self-start{align-self:flex-start}}.\[\&\:\:-webkit-scrollbar\]\:hidden::-webkit-scrollbar{display:none}}:root{color-scheme:light;--af-canvas:#f5f7fb;--af-surface:#fff;--af-raised:#f1f5f9;--af-hover:#e8eef6;--af-sunken:#fff;--af-line:#0f172a17;--af-line-strong:#0f172a2b;--af-ink:#0b1220;--af-body:#1e293b;--af-muted:#475569;--af-faint:#64748b;--af-brand:#2563eb;--af-brand-solid:#2563eb;--af-brand-solid-hover:#1d4ed8;--af-brand-soft:#2563eb14;--af-brand-ring:#2563eb38;--af-brand-amber:#c8692f;--af-ok:#047857;--af-ok-soft:#10b9811a;--af-warn:#b45309;--af-warn-soft:#f59e0b1f;--af-danger:#dc2626;--af-danger-soft:#ef444417;--af-shadow:0 1px 2px #0f172a0a, 0 1px 3px #0f172a0a;--af-shadow-pop:0 12px 32px #0f172a24;--af-scrollbar:#0f172a33;--af-scrollbar-hover:#0f172a59;--af-json-key:#1d4ed8;--af-json-string:#047857;--af-json-number:#b45309;--af-json-literal:#7c3aed}@media (prefers-color-scheme:dark){:root{color-scheme:dark;--af-canvas:#08111f;--af-surface:#0c1727;--af-raised:#131e33;--af-hover:#1a2741;--af-sunken:#07101d;--af-line:#94a3b824;--af-line-strong:#94a3b842;--af-ink:#f8fafc;--af-body:#e2e8f0;--af-muted:#a3b1c6;--af-faint:#8391a7;--af-brand:#60a5fa;--af-brand-solid:#2563eb;--af-brand-solid-hover:#3b82f6;--af-brand-soft:#3b82f624;--af-brand-ring:#3b82f659;--af-brand-amber:#e9a57c;--af-ok:#34d399;--af-ok-soft:#10b98124;--af-warn:#fbbf24;--af-warn-soft:#f59e0b21;--af-danger:#f87171;--af-danger-soft:#ef444421;--af-shadow:0 1px 2px #02061766;--af-shadow-pop:0 16px 40px #0206178c;--af-scrollbar:#94a3b838;--af-scrollbar-hover:#94a3b866;--af-json-key:#93c5fd;--af-json-string:#6ee7b7;--af-json-number:#fcd34d;--af-json-literal:#c4b5fd}}@media (prefers-reduced-motion:reduce){*,:before,:after{scroll-behavior:auto!important;transition-duration:0s!important;animation-duration:0s!important}}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-divide-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@property --tw-content{syntax:"*";inherits:false;initial-value:""}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse{50%{opacity:.5}}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
var pe,b,et,Kt,D,Ze,tt,nt,Ae,ae,K,ot,Ee,ze,Me,Zt,ce={},ue=[],Yt=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i,fe=Array.isArray;function E(e,t){for(var n in t)e[n]=t[n];return e}function Oe(e){e&&e.parentNode&&e.parentNode.removeChild(e)}function Xt(e,t,n){var r,s,a,i={};for(a in t)a=="key"?r=t[a]:a=="ref"?s=t[a]:i[a]=t[a];if(arguments.length>2&&(i.children=arguments.length>3?pe.call(arguments,2):n),typeof e=="function"&&e.defaultProps!=null)for(a in e.defaultProps)i[a]===void 0&&(i[a]=e.defaultProps[a]);return ie(e,i,r,s,null)}function ie(e,t,n,r,s){var a={type:e,props:t,key:n,ref:r,__k:null,__:null,__b:0,__e:null,__c:null,constructor:void 0,__v:s??++et,__i:-1,__u:0};return s==null&&b.vnode!=null&&b.vnode(a),a}function S(e){return e.children}function le(e,t){this.props=e,this.context=t}function L(e,t){if(t==null)return e.__?L(e.__,e.__i+1):null;for(var n;t<e.__k.length;t++)if((n=e.__k[t])!=null&&n.__e!=null)return n.__e;return typeof e.type=="function"?L(e):null}function Qt(e){if(e.__P&&e.__d){var t=e.__v,n=t.__e,r=[],s=[],a=E({},t);a.__v=t.__v+1,b.vnode&&b.vnode(a),Pe(e.__P,a,t,e.__n,e.__P.namespaceURI,32&t.__u?[n]:null,r,n??L(t),!!(32&t.__u),s),a.__v=t.__v,a.__.__k[a.__i]=a,lt(r,a,s),t.__e=t.__=null,a.__e!=n&&rt(a)}}function rt(e){if((e=e.__)!=null&&e.__c!=null)return e.__e=e.__c.base=null,e.__k.some(function(t){if(t!=null&&t.__e!=null)return e.__e=e.__c.base=t.__e}),rt(e)}function Ye(e){(!e.__d&&(e.__d=!0)&&D.push(e)&&!de.__r++||Ze!=b.debounceRendering)&&((Ze=b.debounceRendering)||tt)(de)}function de(){try{for(var e,t=1;D.length;)D.length>t&&D.sort(nt),e=D.shift(),t=D.length,Qt(e)}finally{D.length=de.__r=0}}function st(e,t,n,r,s,a,i,c,u,p,_){var m,l,f,g,$,C,w=r&&r.__k||ue,v=t.length;for(u=en(n,t,w,u,v),m=0;m<v;m++)(f=n.__k[m])!=null&&(l=f.__i!=-1&&w[f.__i]||ce,f.__i=m,C=Pe(e,f,l,s,a,i,c,u,p,_),g=f.__e,f.ref&&l.ref!=f.ref&&(l.ref&&je(l.ref,null,f),_.push(f.ref,f.__c||g,f)),$==null&&g!=null&&($=g),4&f.__u?(u=at(f,u,e),l.__e&&(l.__e=null)):typeof f.type=="function"&&C!==void 0?u=C:g&&(u=g.nextSibling),f.__u&=-7);return n.__e=$,u}function en(e,t,n,r,s){var a,i,c,u,p,_=n.length,m=_,l=0;for(e.__k=new Array(s),a=0;a<s;a++)(i=t[a])!=null&&typeof i!="boolean"&&typeof i!="function"?(typeof i=="string"||typeof i=="number"||typeof i=="bigint"||i.constructor==String?i=e.__k[a]=ie(null,i,null,null,null):fe(i)?i=e.__k[a]=ie(S,{children:i},null,null,null):i.constructor===void 0&&i.__b>0?i=e.__k[a]=ie(i.type,i.props,i.key,i.ref?i.ref:null,i.__v):e.__k[a]=i,u=a+l,i.__=e,i.__b=e.__b+1,c=null,(p=i.__i=tn(i,n,u,m))!=-1&&(m--,(c=n[p])&&(c.__u|=2)),c==null||c.__v==null?(p==-1&&(s>_?l--:s<_&&l++),typeof i.type!="function"&&(i.__u|=4)):p!=u&&(p==u-1?l--:p==u+1?l++:(p>u?l--:l++,i.__u|=4))):e.__k[a]=null;if(m)for(a=0;a<_;a++)(c=n[a])!=null&&(2&c.__u)==0&&(c.__e==r&&(r=L(c)),ut(c,c));return r}function at(e,t,n){var r,s;if(typeof e.type=="function"){for(r=e.__k,s=0;r&&s<r.length;s++)r[s]&&(r[s].__=e,t=at(r[s],t,n));return t}e.__e!=t&&(t&&e.type&&!t.parentNode&&(t=L(e)),t=n.insertBefore(e.__e,t||null));do t=t&&t.nextSibling;while(t!=null&&t.nodeType==8);return t}function tn(e,t,n,r){var s,a,i,c=e.key,u=e.type,p=t[n],_=p!=null&&(2&p.__u)==0;if(p===null&&c==null||_&&c==p.key&&u==p.type)return n;if(r>(_?1:0)){for(s=n-1,a=n+1;s>=0||a<t.length;)if((p=t[i=s>=0?s--:a++])!=null&&(2&p.__u)==0&&c==p.key&&u==p.type)return i}return-1}function Xe(e,t,n){t[0]=="-"?e.setProperty(t,n??""):e[t]=n==null?"":typeof n!="number"||Yt.test(t)?n:n+"px"}function se(e,t,n,r,s){var a,i;e:if(t=="style")if(typeof n=="string")e.style.cssText=n;else{if(typeof r=="string"&&(e.style.cssText=r=""),r)for(t in r)n&&t in n||Xe(e.style,t,"");if(n)for(t in n)r&&n[t]==r[t]||Xe(e.style,t,n[t])}else if(t[0]=="o"&&t[1]=="n")a=t!=(t=t.replace(ot,"$1")),i=t.toLowerCase(),t=i in e||t=="onFocusOut"||t=="onFocusIn"?i.slice(2):t.slice(2),e.l||(e.l={}),e.l[t+a]=n,n?r?n[K]=r[K]:(n[K]=Ee,e.addEventListener(t,a?Me:ze,a)):e.removeEventListener(t,a?Me:ze,a);else{if(s=="http://www.w3.org/2000/svg")t=t.replace(/xlink(H|:h)/,"h").replace(/sName$/,"s");else if(t!="width"&&t!="height"&&t!="href"&&t!="list"&&t!="form"&&t!="tabIndex"&&t!="download"&&t!="rowSpan"&&t!="colSpan"&&t!="role"&&t!="popover"&&t in e)try{e[t]=n??"";break e}catch{}typeof n=="function"||(n==null||n===!1&&t[4]!="-"?e.removeAttribute(t):e.setAttribute(t,t=="popover"&&n==1?"":n))}}function Qe(e){return function(t){if(this.l){var n=this.l[t.type+e];if(t[ae]==null)t[ae]=Ee++;else if(t[ae]<n[K])return;return n(b.event?b.event(t):t)}}}function Pe(e,t,n,r,s,a,i,c,u,p){var _,m,l,f,g,$,C,w,v,A,J,H,q,Ke,re,Ie,z=t.type;if(t.constructor!==void 0)return null;128&n.__u&&(u=!!(32&n.__u),a=[c=t.__e=n.__e]),(_=b.__b)&&_(t);e:if(typeof z=="function"){m=i.length;try{if(v=t.props,A=z.prototype&&z.prototype.render,J=(_=z.contextType)&&r[_.__c],H=_?J?J.props.value:_.__:r,n.__c?w=(l=t.__c=n.__c).__=l.__E:(A?t.__c=l=new z(v,H):(t.__c=l=new le(v,H),l.constructor=z,l.render=on),J&&J.sub(l),l.state||(l.state={}),l.__n=r,f=l.__d=!0,l.__h=[],l._sb=[]),A&&l.__s==null&&(l.__s=l.state),A&&z.getDerivedStateFromProps!=null&&(l.__s==l.state&&(l.__s=E({},l.__s)),E(l.__s,z.getDerivedStateFromProps(v,l.__s))),g=l.props,$=l.state,l.__v=t,f)A&&z.getDerivedStateFromProps==null&&l.componentWillMount!=null&&l.componentWillMount(),A&&l.componentDidMount!=null&&l.__h.push(l.componentDidMount);else{if(A&&z.getDerivedStateFromProps==null&&v!==g&&l.componentWillReceiveProps!=null&&l.componentWillReceiveProps(v,H),t.__v==n.__v||!l.__e&&l.shouldComponentUpdate!=null&&l.shouldComponentUpdate(v,l.__s,H)===!1){t.__v!=n.__v&&(l.props=v,l.state=l.__s,l.__d=!1),t.__e=n.__e,t.__k=n.__k,t.__k.some(function(U){U&&(U.__=t)}),ue.push.apply(l.__h,l._sb),l._sb=[],l.__h.length&&i.push(l),c=L(n);break e}l.componentWillUpdate!=null&&l.componentWillUpdate(v,l.__s,H),A&&l.componentDidUpdate!=null&&l.__h.push(function(){l.componentDidUpdate(g,$,C)})}if(l.context=H,l.props=v,l.__P=e,l.__e=!1,q=b.__r,Ke=0,A)l.state=l.__s,l.__d=!1,q&&q(t),_=l.render(l.props,l.state,l.context),ue.push.apply(l.__h,l._sb),l._sb=[];else do l.__d=!1,q&&q(t),_=l.render(l.props,l.state,l.context),l.state=l.__s;while(l.__d&&++Ke<25);l.state=l.__s,l.getChildContext!=null&&(r=E(E({},r),l.getChildContext())),A&&!f&&l.getSnapshotBeforeUpdate!=null&&(C=l.getSnapshotBeforeUpdate(g,$)),re=_!=null&&_.type===S&&_.key==null?ct(_.props.children):_,c=st(e,fe(re)?re:[re],t,n,r,s,a,i,c,u,p),l.base=t.__e,t.__u&=-161,l.__h.length&&i.push(l),w&&(l.__E=l.__=null)}catch(U){if(i.length=m,t.__v=null,u||a!=null){if(U.then){for(t.__u|=u?160:128;c&&c.nodeType==8&&c.nextSibling;)c=c.nextSibling;a!=null&&(a[a.indexOf(c)]=null),t.__e=c}else if(a!=null)for(Ie=a.length;Ie--;)Oe(a[Ie])}else t.__e=n.__e;t.__k==null&&(t.__k=n.__k||[]),U.then||it(t),b.__e(U,t,n)}}else a==null&&t.__v==n.__v?(t.__k=n.__k,t.__e=n.__e):c=t.__e=nn(n.__e,t,n,r,s,a,i,u,p);return(_=b.diffed)&&_(t),128&t.__u?void 0:c}function it(e){e&&(e.__c&&(e.__c.__e=!0),e.__k&&e.__k.some(it))}function lt(e,t,n){for(var r=0;r<n.length;r++)je(n[r],n[++r],n[++r]);b.__c&&b.__c(t,e),e.some(function(s){try{e=s.__h,s.__h=[],e.some(function(a){a.call(s)})}catch(a){b.__e(a,s.__v)}})}function ct(e){return typeof e!="object"||e==null||e.__b>0?e:fe(e)?e.map(ct):e.constructor!==void 0?null:E({},e)}function nn(e,t,n,r,s,a,i,c,u){var p,_,m,l,f,g,$,C=n.props||ce,w=t.props,v=t.type;if(v=="svg"?s="http://www.w3.org/2000/svg":v=="math"?s="http://www.w3.org/1998/Math/MathML":s||(s="http://www.w3.org/1999/xhtml"),a!=null){for(p=0;p<a.length;p++)if((f=a[p])&&"setAttribute"in f==!!v&&(v?f.localName==v:f.nodeType==3)){e=f,a[p]=null;break}}if(e==null){if(v==null)return document.createTextNode(w);e=document.createElementNS(s,v,w.is&&w),c&&(b.__m&&b.__m(t,a),c=!1),a=null}if(v==null)C===w||c&&e.data==w||(e.data=w);else{if(a=v=="textarea"&&w.defaultValue!=null?null:a&&pe.call(e.childNodes),!c&&a!=null)for(C={},p=0;p<e.attributes.length;p++)C[(f=e.attributes[p]).name]=f.value;for(p in C)f=C[p],p=="dangerouslySetInnerHTML"?m=f:p=="children"||p in w||p=="value"&&"defaultValue"in w||p=="checked"&&"defaultChecked"in w||se(e,p,null,f,s);for(p in w)f=w[p],p=="children"?l=f:p=="dangerouslySetInnerHTML"?_=f:p=="value"?g=f:p=="checked"?$=f:c&&typeof f!="function"||C[p]===f||se(e,p,f,C[p],s);if(_)c||m&&(_.__html==m.__html||_.__html==e.innerHTML)||(e.innerHTML=_.__html),t.__k=[];else if(m&&(e.innerHTML=""),st(t.type=="template"?e.content:e,fe(l)?l:[l],t,n,r,v=="foreignObject"?"http://www.w3.org/1999/xhtml":s,a,i,a?a[0]:n.__k&&L(n,0),c,u),a!=null)for(p=a.length;p--;)Oe(a[p]);c&&v!="textarea"||(p="value",v=="progress"&&g==null?e.removeAttribute("value"):g!=null&&(g!==e[p]||v=="progress"&&!g||v=="option"&&g!=C[p])&&se(e,p,g,C[p],s),p="checked",$!=null&&$!=e[p]&&se(e,p,$,C[p],s))}return e}function je(e,t,n){try{if(typeof e=="function"){var r=typeof e.__u=="function";r&&e.__u(),r&&t==null||(e.__u=e(t))}else e.current=t}catch(s){b.__e(s,n)}}function ut(e,t,n){var r,s;if(b.unmount&&b.unmount(e),(r=e.ref)&&(r.current&&r.current!=e.__e||je(r,null,t)),(r=e.__c)!=null){if(r.componentWillUnmount)try{r.componentWillUnmount()}catch(a){b.__e(a,t)}r.base=r.__P=r.__n=null}if(r=e.__k)for(s=0;s<r.length;s++)r[s]&&ut(r[s],t,n||typeof e.type!="function");n||Oe(e.__e),e.__c=e.__=e.__e=void 0}function on(e,t,n){return this.constructor(e,n)}function dt(e,t,n){var r,s,a,i;t==document&&(t=document.documentElement),b.__&&b.__(e,t),s=(r=typeof n=="function")?null:n&&n.__k||t.__k,a=[],i=[],Pe(t,e=(!r&&n||t).__k=Xt(S,null,[e]),s||ce,ce,t.namespaceURI,!r&&n?[n]:s?null:t.firstChild?pe.call(t.childNodes):null,a,!r&&n?n:s?s.__e:t.firstChild,r,i),lt(a,e,i),e.props.children=null}pe=ue.slice,b={__e:function(e,t,n,r){for(var s,a,i;t=t.__;)if((s=t.__c)&&!s.__)try{if((a=s.constructor)&&a.getDerivedStateFromError!=null&&(s.setState(a.getDerivedStateFromError(e)),i=s.__d),s.componentDidCatch!=null&&(s.componentDidCatch(e,r||{}),i=s.__d),i)return s.__E=s}catch(c){e=c}throw e}},et=0,Kt=function(e){return e!=null&&e.constructor===void 0},le.prototype.setState=function(e,t){var n;n=this.__s!=null&&this.__s!=this.state?this.__s:this.__s=E({},this.state),typeof e=="function"&&(e=e(E({},n),this.props)),e&&E(n,e),e!=null&&this.__v&&(t&&this._sb.push(t),Ye(this))},le.prototype.forceUpdate=function(e){this.__v&&(this.__e=!0,e&&this.__h.push(e),Ye(this))},le.prototype.render=S,D=[],tt=typeof Promise=="function"?Promise.prototype.then.bind(Promise.resolve()):setTimeout,nt=function(e,t){return e.__v.__b-t.__v.__b},de.__r=0,Ae=Math.random().toString(8),ae="__d"+Ae,K="__a"+Ae,ot=/(PointerCapture)$|Capture$/i,Ee=0,ze=Qe(!1),Me=Qe(!0),Zt=0;var Z,y,Ne,pt,he=0,gt=[],k=b,ft=k.__b,_t=k.__r,ht=k.diffed,mt=k.__c,xt=k.unmount,bt=k.__;function De(e,t){k.__h&&k.__h(y,e,he||t),he=0;var n=y.__H||(y.__H={__:[],__h:[]});return e>=n.__.length&&n.__.push({}),n.__[e]}function me(e){return he=1,He(wt,e)}function He(e,t,n){var r=De(Z++,2);if(r.t=e,!r.__c&&(r.__=[n?n(t):wt(void 0,t),function(c){var u=r.__N?r.__N[0]:r.__[0],p=r.t(u,c);u!==p&&(r.__N=[p,r.__[1]],r.__c.setState({}))}],r.__c=y,!y.__f)){var s=function(c,u,p){if(!r.__c.__H)return!0;var _=!1,m=r.__c.props!==c;if(r.__c.__H.__.some(function(f){if(f.__N){_=!0;var g=f.__[0];f.__=f.__N,f.__N=void 0,g!==f.__[0]&&(m=!0)}}),a){var l=a.call(this,c,u,p);return _?l||m:l}return!_||m};y.__f=!0;var a=y.shouldComponentUpdate,i=y.componentWillUpdate;y.componentWillUpdate=function(c,u,p){if(this.__e){var _=a;a=void 0,s(c,u,p),a=_}i&&i.call(this,c,u,p)},y.shouldComponentUpdate=s}return r.__N||r.__}function W(e,t){var n=De(Z++,3);!k.__s&&kt(n.__H,t)&&(n.__=e,n.u=t,y.__H.__h.push(n))}function yt(e){return he=5,rn(function(){return{current:e}},[])}function rn(e,t){var n=De(Z++,7);return kt(n.__H,t)&&(n.__=e(),n.__H=t,n.__h=e),n.__}function sn(){for(var e;e=gt.shift();){var t=e.__H;if(e.__P&&t)try{t.__h.some(_e),t.__h.some(Re),t.__h=[]}catch(n){t.__h=[],k.__e(n,e.__v)}}}k.__b=function(e){y=null,ft&&ft(e)},k.__=function(e,t){e&&t.__k&&t.__k.__m&&(e.__m=t.__k.__m),bt&&bt(e,t)},k.__r=function(e){_t&&_t(e),Z=0;var t=(y=e.__c).__H;t&&(Ne===y?(t.__h=[],y.__h=[],t.__.some(function(n){n.__N&&(n.__=n.__N),n.u=n.__N=void 0})):(t.__h.some(_e),t.__h.some(Re),t.__h=[],Z=0)),Ne=y},k.diffed=function(e){ht&&ht(e);var t=e.__c;t&&t.__H&&(t.__H.__h.length&&(gt.push(t)!==1&&pt===k.requestAnimationFrame||((pt=k.requestAnimationFrame)||an)(sn)),t.__H.__.some(function(n){n.u&&(n.__H=n.u,n.u=void 0)})),Ne=y=null},k.__c=function(e,t){t.some(function(n){try{n.__h.some(_e),n.__h=n.__h.filter(function(r){return!r.__||Re(r)})}catch(r){t.some(function(s){s.__h&&(s.__h=[])}),t=[],k.__e(r,n.__v)}}),mt&&mt(e,t)},k.unmount=function(e){xt&&xt(e);var t,n=e.__c;n&&n.__H&&(n.__H.__.some(function(r){try{_e(r)}catch(s){t=s}}),n.__H=void 0,t&&k.__e(t,n.__v))};var vt=typeof requestAnimationFrame=="function";function an(e){var t,n=function(){clearTimeout(r),vt&&cancelAnimationFrame(t),setTimeout(e)},r=setTimeout(n,35);vt&&(t=requestAnimationFrame(n))}function _e(e){var t=y,n=e.__c;typeof n=="function"&&(e.__c=void 0,n()),y=t}function Re(e){var t=y;e.__c=e.__(),y=t}function kt(e,t){return!e||e.length!==t.length||t.some(function(n,r){return n!==e[r]})}function wt(e,t){return typeof t=="function"?t(e):t}var Le=[{id:"essential",title:"Essentials",tagline:"What the server needs to boot. Start here.",sections:["core","plugins"]},{id:"recommended",title:"Recommended",tagline:"Lock down access and see what your agents do before you ship.",sections:["auth","authorization","rate_limit","observability"]},{id:"advanced",title:"Advanced",tagline:"Tune connection limits, client-side tools, and your test loop.",sections:["websocket","ag_ui","remote_tools","test","evaluation"]}],Fe={"auth.path":"auth-path",authorization:"authz-path"},xe=new URLSearchParams(location.hash.slice(1)).get("token")||"",d={schema:null,sections:[],tiers:[],fields:new Map,config:{},version:null,exists:!1,path:"",parseError:null,saved:"",validated:null,issues:[],open:new Set,tab:"problems",inspectorOpen:!1,busy:null,toolParams:{},toasts:[],fatal:null},Ct=()=>{},Tt=e=>{Ct=e};function x(e){e&&e(d),Ct()}var St=e=>JSON.parse(JSON.stringify(e)),P=()=>JSON.stringify(d.config),O=e=>e!==null&&typeof e=="object"&&!Array.isArray(e),Ue=(e,t)=>t.reduce((n,r)=>O(n)?n[r]:void 0,e),I=(e,t)=>`${e} ${t}${e===1?"":"s"}`;function $t(e,t,n){let r=e;for(let s of t.slice(0,-1))O(r[s])||(r[s]={}),r=r[s];r[t[t.length-1]]=n}function It(e,t){let n=[],r=e;for(let s of t.slice(0,-1)){if(!O(r))return;n.push([r,s]),r=r[s]}O(r)&&delete r[t[t.length-1]];for(let s=n.length-1;s>=1;s--){let[a,i]=n[s];if(O(a[i])&&Object.keys(a[i]).length===0)delete a[i];else break}}function At(e){let t=Ue(d.config,e);return t!==void 0?t:d.fields.get(e.join("."))?.default}var be=e=>d.sections.find(t=>t.id===e),j=()=>P()!==d.saved,V=e=>!e.optional||e.key in d.config&&d.config[e.key]!==null,Y=e=>d.issues.filter(t=>t.section===e),X=e=>d.issues.find(t=>t.path===e),zt=()=>d.validated!==null&&d.validated!==P();function M(e=d.issues){let t=e.filter(n=>n.level==="error").length;return{errors:t,warnings:e.length-t}}var Mt=e=>Fe[e]||`f-${e.replaceAll(".","-")}`;async function Be(e,t,n){let r={"X-10xGraph-Token":xe};n!==void 0&&(r["Content-Type"]="application/json");let s=await fetch(t,{method:e,headers:r,body:n===void 0?void 0:JSON.stringify(n)}),a={};try{a=await s.json()}catch{}return{ok:s.ok,status:s.status,data:a}}var We=(e,t)=>x(n=>{n.fatal={title:e,text:t}});function Et(e,t){let n=e.indexOf(t);return n===-1?e.length:n}function Ge(){for(let e of d.issues)be(e.section)&&d.open.add(e.section)}async function Ot(){if(!xe)return We("Open the link printed by 10xgraph config","This page needs the session token included in that link.");let e;try{e=await Be("GET","/api/state")}catch{return We("Cannot reach the config server","Check that 10xgraph config is still running in your terminal, then reload.")}if(!e.ok)return We("This link has expired",e.data.error||"Restart 10xgraph config and open the new link it prints.");let t=e.data;x(r=>{r.schema=t.schema;let s=Le.flatMap(i=>i.sections);r.sections=[...t.schema.sections].sort((i,c)=>Et(s,i.id)-Et(s,c.id)),r.tiers=Le.map(i=>({...i,list:i.sections.map(be).filter(Boolean)})),r.tiers[r.tiers.length-1].list.push(...r.sections.filter(i=>!s.includes(i.id)));for(let i of r.sections)for(let c of i.fields)r.fields.set(c.path.join("."),c);r.config=t.config,r.version=t.version,r.exists=t.exists,r.path=t.path,r.parseError=t.parse_error,r.issues=t.issues;let a=t.exists&&!t.parse_error;r.saved=a?P():"",r.validated=a?P():null;for(let i of r.sections)(!i.optional||V(i))&&r.open.add(i.id);Ge()});let n=new URLSearchParams(location.hash.slice(1)).get("section");n&&be(n)&&ge(n)}async function Q(){if(!(d.busy||!Pt())){x(e=>{e.busy="validate"});try{let e=await Be("POST","/api/validate",{config:d.config});if(!e.ok)return T("error",e.data.error||"Validation failed.");d.issues=e.data.issues,d.validated=P(),Ge();let{errors:t,warnings:n}=M(),r={label:"Show",run:()=>ye("problems")};t?T("error",`${I(t,"error")} to fix before saving.`,r):n?T("warning",`Valid, with ${I(n,"warning")}.`,r):T("success","Configuration is valid.")}catch{T("error","Cannot reach the config server.")}finally{x(e=>{e.busy=null})}}}async function ve(){if(!(d.busy||!d.schema)){if(d.exists&&!j()&&!d.parseError)return T("success","No changes to save.");if(Pt()){x(e=>{e.busy="save"});try{let e=await Be("POST","/api/save",{config:d.config,version:d.version});if(e.data.issues&&(d.issues=e.data.issues,d.validated=P(),Ge()),e.ok){d.version=e.data.version,d.config=e.data.config,d.toolParams={},d.validated=P(),d.saved=P(),d.exists=!0,d.parseError=null;let t=e.data.path.split(/[\\/]/).pop();T("success",e.data.backup?`Saved ${t}. The previous version is in ${t}.bak.`:`Created ${t}.`)}else if(e.status===409)T("error",e.data.error,{label:"Reload",run:()=>location.reload()});else if(e.status===422){let{errors:t}=M();T("error",`Not saved: ${I(t,"error")} to fix first.`,{label:"Show",run:()=>ye("problems")})}else T("error",e.data.error||"Save failed.")}catch{T("error","Cannot reach the config server.")}finally{x(e=>{e.busy=null})}}}}function Pt(){let e=Object.values(d.toolParams).some(t=>t.error);return e&&(ge("remote_tools"),T("error","A remote tool has invalid parameters JSON.")),!e}function Je(e,t){x(n=>{t?(n.config[e.key]=St(e.default),n.open.add(e.id)):delete n.config[e.key],e.key==="remote_tools"&&(n.toolParams={})})}function jt(e){x(t=>{t.open.has(e)?t.open.delete(e):t.open.add(e)})}function Nt(e){x(t=>{t.open=e?new Set(t.sections.map(n=>n.id)):new Set})}var Ve=()=>window.matchMedia("(prefers-reduced-motion: reduce)").matches?"auto":"smooth";function ge(e,t){x(n=>{n.open.add(e),n.inspectorOpen=!1}),history.replaceState(null,"",`#token=${encodeURIComponent(xe)}§ion=${e}`),requestAnimationFrame(()=>{let n=t?document.getElementById(t):null;if(n){n.scrollIntoView({block:"center",behavior:Ve()}),n.focus({preventScroll:!0});return}document.getElementById(`sec-${e}`)?.scrollIntoView({block:"start",behavior:Ve()}),document.getElementById(`acc-${e}`)?.focus({preventScroll:!0})})}function Rt(e){document.getElementById(`tier-${e}`)?.scrollIntoView({block:"start",behavior:Ve()})}function ye(e){x(t=>{e&&(t.tab=e),t.inspectorOpen=!window.matchMedia("(min-width: 1280px)").matches})}var ee=()=>x(e=>{e.inspectorOpen=!1});async function Dt(){try{await navigator.clipboard.writeText(JSON.stringify(d.config,null,2)+`
|
|
2
|
+
`),T("success","Copied 10xgraph.json to the clipboard.")}catch{T("error","The clipboard is not available here.")}}var ln=0;function T(e,t,n){let r=++ln;x(s=>{s.toasts=[...s.toasts,{id:r,kind:e,message:t,action:n}]}),setTimeout(()=>ke(r),n?8e3:4e3)}function ke(e){x(t=>{t.toasts=t.toasts.filter(n=>n.id!==e)})}var Ht={box:'<path d="M21 8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16Z"/><path d="m3.3 7 8.7 5 8.7-5"/><path d="M12 22V12"/>',key:'<path d="M2.586 17.414A2 2 0 0 0 2 18.828V21a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h1a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h.172a2 2 0 0 0 1.414-.586l.814-.814a6.5 6.5 0 1 0-4-4z"/><circle cx="16.5" cy="7.5" r=".5" fill="currentColor"/>',shield:'<path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"/><path d="m9 12 2 2 4-4"/>',gauge:'<path d="m12 14 4-4"/><path d="M3.34 19a10 10 0 1 1 17.32 0"/>',arrows:'<path d="M8 3 4 7l4 4"/><path d="M4 7h16"/><path d="m16 21 4-4-4-4"/><path d="M20 17H4"/>',activity:'<path d="M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2"/>',layers:'<path d="M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83Z"/><path d="m22 17.65-9.17 4.16a2 2 0 0 1-1.66 0L2 17.65"/><path d="m22 12.65-9.17 4.16a2 2 0 0 1-1.66 0L2 12.65"/>',wrench:'<path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"/>',flask:'<path d="M10 2v7.527a2 2 0 0 1-.211.896L4.72 20.55a1 1 0 0 0 .9 1.45h12.76a1 1 0 0 0 .9-1.45l-5.069-10.127A2 2 0 0 1 14 9.527V2"/><path d="M8.5 2h7"/><path d="M7 16h10"/>',target:'<circle cx="12" cy="12" r="10"/><circle cx="12" cy="12" r="6"/><circle cx="12" cy="12" r="2"/>',checkCircle:'<circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/>',xCircle:'<circle cx="12" cy="12" r="10"/><path d="m15 9-6 6"/><path d="m9 9 6 6"/>',alert:'<path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"/><path d="M12 9v4"/><path d="M12 17h.01"/>',info:'<circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/>',file:'<path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/><path d="M10 12a1 1 0 0 0-1 1v1a1 1 0 0 1-1 1 1 1 0 0 1 1 1v1a1 1 0 0 0 1 1"/><path d="M14 18a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1 1 1 0 0 1-1-1v-1a1 1 0 0 0-1-1"/>',copy:'<rect width="14" height="14" x="8" y="8" rx="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/>',x:'<path d="M18 6 6 18"/><path d="m6 6 12 12"/>',plus:'<path d="M5 12h14"/><path d="M12 5v14"/>',trash:'<path d="M3 6h18"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/>',panel:'<rect width="18" height="18" x="3" y="3" rx="2"/><path d="M15 3v18"/>',chevronDown:'<path d="m6 9 6 6 6-6"/>',expand:'<path d="m7 15 5 5 5-5"/><path d="m7 9 5-5 5 5"/>',collapse:'<path d="m7 20 5-5 5 5"/><path d="m7 4 5 5 5-5"/>',power:'<path d="M12 2v10"/><path d="M18.4 6.6a9 9 0 1 1-12.77.04"/>',spinner:'<path d="M21 12a9 9 0 1 1-6.219-8.56"/>',book:'<path d="M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"/>',external:'<path d="M15 3h6v6"/><path d="M10 14 21 3"/><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>'},we={core:"box",auth:"key",authorization:"shield",rate_limit:"gauge",websocket:"arrows",ag_ui:"external",observability:"activity",plugins:"layers",remote_tools:"wrench",test:"flask",evaluation:"target"};var cn=0;function o(e,t,n,r,s,a){t||(t={});var i,c,u=t;if("ref"in u)for(c in u={},t)c=="ref"?i=t[c]:u[c]=t[c];var p={type:e,props:u,key:n,ref:i,__k:null,__:null,__b:0,__e:null,__c:null,constructor:void 0,__v:--cn,__i:-1,__u:0,__source:s,__self:a};if(typeof e=="function"&&(i=e.defaultProps))for(c in i)u[c]===void 0&&(u[c]=i[c]);return b.vnode&&b.vnode(p),p}function h({name:e,class:t="size-4"}){return o("span",{class:`inline-flex shrink-0 ${t}`,"aria-hidden":"true",children:o("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"1.75","stroke-linecap":"round","stroke-linejoin":"round",class:"size-full",dangerouslySetInnerHTML:{__html:Ht[e]}})})}function Ce({class:e,children:t}){return o("span",{class:`inline-flex h-5 shrink-0 items-center rounded-full px-2 text-[11px] font-semibold ${e}`,children:t})}function Te({id:e,on:t,label:n,onChange:r}){return o("button",{id:e,type:"button",role:"switch","aria-checked":t?"true":"false","aria-label":n,class:`focus-ring relative inline-flex h-6 w-10 shrink-0 cursor-pointer items-center rounded-full transition-colors duration-200 before:absolute before:-inset-2.5 before:content-[''] ${t?"bg-brand-solid":"bg-line-strong"}`,onClick:()=>r(!t),children:o("span",{class:`pointer-events-none inline-block size-5 rounded-full bg-white shadow-sm ring-1 ring-black/5 transition-transform duration-200 ease-out ${t?"translate-x-[18px]":"translate-x-0.5"}`})})}function Se({id:e,options:t,value:n,invalid:r,onChange:s}){return o("div",{class:"relative",children:[o("select",{id:e,value:n,class:`input cursor-pointer appearance-none pr-9 font-mono ${r?"input-invalid":""}`,onChange:a=>s(a.currentTarget.value),children:t.map(([a,i])=>o("option",{value:a,children:i},a))}),o(h,{name:"chevronDown",class:"pointer-events-none absolute top-1/2 right-3 size-4 -translate-y-1/2 text-faint"})]})}function te({id:e,values:t,placeholder:n,suggestions:r,onChange:s}){let a=yt(null),i=u=>{let p=u.trim();a.current&&(a.current.value=""),p&&!t.includes(p)&&s([...t,p])},c=r?`${e}-options`:void 0;return o("div",{class:"flex min-h-10 cursor-text flex-wrap items-center gap-1.5 rounded-lg border border-line-strong bg-sunken px-1.5 py-1.5 transition-[border-color,box-shadow] duration-150 focus-within:border-brand focus-within:ring-4 focus-within:ring-brand-ring sm:min-h-9 sm:py-1",onClick:u=>{u.target===u.currentTarget&&a.current?.focus()},children:[t.map((u,p)=>o("span",{class:"inline-flex h-7 items-center gap-0.5 rounded-md border border-line bg-raised pr-0.5 pl-2 font-mono text-xs text-body sm:h-6",children:[u,o("button",{type:"button","aria-label":`Remove ${u}`,class:"inline-flex size-6 cursor-pointer items-center justify-center rounded text-faint transition-colors hover:bg-hover hover:text-ink sm:size-5",onClick:()=>s(t.filter((_,m)=>m!==p)),children:o(h,{name:"x",class:"size-3"})})]},u)),o("input",{ref:a,id:e,type:"text",list:c,placeholder:t.length?"Add...":n,autocomplete:"off",spellcheck:!1,autocapitalize:"off",class:"h-7 min-w-[7rem] flex-1 bg-transparent px-1 font-mono text-base text-ink outline-none placeholder:text-faint sm:text-sm",onKeyDown:u=>{let p=u.currentTarget;(u.key==="Enter"||u.key===",")&&p.value.trim()?(u.preventDefault(),i(p.value)):u.key==="Backspace"&&!p.value&&t.length&&s(t.slice(0,-1))},onChange:u=>{r?.includes(u.currentTarget.value.trim())&&i(u.currentTarget.value)},onBlur:u=>i(u.currentTarget.value)}),r?o("datalist",{id:c,children:r.filter(u=>!t.includes(u)).map(u=>o("option",{value:u},u))}):null]})}function N({label:e,path:t,help:n,id:r,required:s}){return o("div",{class:"min-w-0",children:[o("label",{for:r,class:"block text-sm font-medium text-ink",children:[e,s?o("span",{class:"text-danger",children:" *"}):null]}),o("div",{class:"mt-0.5 font-mono text-xs text-faint",children:t}),n?o("p",{class:"mt-1.5 text-[13px] leading-5 text-muted",children:n}):null]})}function F({issue:e}){if(!e)return null;let t=e.level==="error";return o("p",{class:`mt-2 flex gap-1.5 text-[13px] leading-5 ${t?"text-danger":"text-warn"}`,role:t?"alert":void 0,children:[o(h,{name:t?"xCircle":"alert",class:"mt-0.5 size-3.5"}),o("span",{children:e.message})]})}function ne({children:e}){return o("div",{class:"grid gap-3 px-5 py-4 sm:grid-cols-[minmax(0,1fr)_minmax(0,1.1fr)] sm:gap-8",children:e})}function B({id:e,label:t,path:n,value:r,placeholder:s,onInput:a,issue:i,help:c}){return o(ne,{children:[o(N,{label:t,path:n,help:c,id:e}),o("div",{class:"min-w-0 sm:pt-0.5",children:[o("input",{id:e,type:"text",value:r??"",placeholder:s,autocomplete:"off",spellcheck:!1,autocapitalize:"off",class:`input font-mono ${i?.level==="error"?"input-invalid":""}`,onInput:u=>a(u.currentTarget.value)}),o(F,{issue:i})]})]})}function qe({name:e,label:t,options:n,value:r,onPick:s}){return o("div",{role:"radiogroup","aria-label":t,class:"grid gap-3 sm:grid-cols-2",children:n.map(([a,i,c])=>{let u=a===r;return o("button",{type:"button",role:"radio","aria-checked":u?"true":"false",id:`${e}-${a}`,class:`focus-ring flex cursor-pointer items-start gap-3 rounded-xl border p-4 text-left transition-colors duration-150 ${u?"border-brand bg-brand-soft":"border-line bg-surface shadow-card hover:border-line-strong"}`,onClick:()=>{u||s(a)},children:[o("span",{class:`mt-0.5 flex size-4 shrink-0 items-center justify-center rounded-full border ${u?"border-brand-solid bg-brand-solid":"border-line-strong"}`,children:u?o("span",{class:"size-1.5 rounded-full bg-white"}):null}),o("span",{class:"min-w-0",children:[o("span",{class:"block text-sm font-medium text-ink",children:i}),o("span",{class:"mt-0.5 block text-[13px] leading-5 text-muted",children:c})]})]},a)})})}function R({title:e,children:t}){return o("section",{children:[e?o("h4",{class:"eyebrow mb-2.5",children:e}):null,t]})}var un={info:["info","border-brand/20 bg-brand-soft","text-brand"],warn:["alert","border-warn/25 bg-warn-soft","text-warn"],error:["xCircle","border-danger/25 bg-danger-soft","text-danger"]};function $e({kind:e,title:t,lines:n}){let[r,s,a]=un[e];return o("div",{class:`flex gap-3 rounded-xl border px-4 py-3 ${s}`,role:e==="error"?"alert":void 0,children:[o(h,{name:r,class:`mt-0.5 size-4 ${a}`}),o("div",{class:"min-w-0 space-y-1 text-[13px] leading-5 text-body",children:[t?o("p",{class:"font-medium text-ink",children:t}):null,n.map((i,c)=>o("p",{children:i},c))]})]})}function Lt({issue:e}){return o($e,{kind:e.level==="error"?"error":"warn",lines:[o("span",{children:[e.path?o("code",{class:"mr-1.5 font-mono text-xs text-muted",children:e.path}):null,e.message]})]})}function oe({icon:e,tint:t,title:n,text:r,children:s}){return o("div",{class:"px-6 py-14 text-center",children:[o("div",{class:`mx-auto flex size-11 items-center justify-center rounded-full bg-raised ${t}`,children:o(h,{name:e,class:"size-5"})}),o("p",{class:"mt-4 text-sm font-semibold text-ink",children:n}),o("p",{class:"mx-auto mt-1 max-w-xs text-sm leading-6 text-muted",children:r}),s]})}function Ft(){let{errors:e,warnings:t}=M(),n=e+t,r=(s,a,i)=>o("button",{type:"button",role:"tab",id:`tab-${s}`,"aria-selected":d.tab===s?"true":"false",class:`focus-ring inline-flex h-9 cursor-pointer items-center gap-2 rounded-lg px-3 text-sm font-medium transition-colors duration-150 ${d.tab===s?"bg-raised text-ink":"text-muted hover:text-ink"}`,onClick:()=>x(c=>{c.tab=s}),children:[a,i]});return o("aside",{"aria-label":"Inspector",class:`fixed inset-y-0 right-0 z-40 flex w-[min(100vw,400px)] flex-col border-l border-line bg-surface transition-transform duration-200 ease-out xl:sticky xl:top-14 xl:bottom-auto xl:z-auto xl:self-start xl:h-[calc(100dvh-3.5rem)] xl:w-[380px] xl:shrink-0 xl:translate-x-0 ${d.inspectorOpen?"translate-x-0":"translate-x-full"}`,children:[o("div",{class:"flex h-14 shrink-0 items-center gap-1 border-b border-line px-3",children:[o("div",{role:"tablist",class:"flex flex-1 gap-1",children:[r("problems","Problems",d.validated!==null&&n?o("span",{class:`inline-flex h-5 min-w-5 items-center justify-center rounded-full px-1.5 text-[11px] font-semibold ${e?"bg-danger-soft text-danger":"bg-warn-soft text-warn"}`,children:n}):null),r("json","10xgraph.json",null)]}),o("button",{type:"button",class:"icon-btn xl:hidden","aria-label":"Close inspector",onClick:ee,children:o(h,{name:"x",class:"size-5"})})]}),o("div",{class:"min-h-0 flex-1 overflow-y-auto overscroll-contain",children:d.tab==="problems"?o(dn,{}):o(fn,{})})]})}function dn(){if(!d.schema)return null;if(d.validated===null)return o(oe,{icon:"checkCircle",tint:"text-faint",title:"Not checked yet",text:"Validate runs the same rules 10xgraph api applies when it starts.",children:o("button",{type:"button",class:"btn btn-outline mt-5",disabled:!!d.busy,onClick:Q,children:"Validate now"})});let{errors:e,warnings:t}=M(),n=zt(),r=d.sections.map(s=>[s,Y(s.id)]).filter(([,s])=>s.length);return o("div",{children:[o("div",{class:"flex items-center justify-between gap-3 border-b border-line px-4 py-3",children:[o("p",{class:"text-sm text-muted",children:[o("span",{class:e?"font-medium text-danger":"",children:I(e,"error")})," \xB7 ",o("span",{class:t?"font-medium text-warn":"",children:I(t,"warning")})]}),n?o("button",{type:"button",class:"text-sm font-medium text-brand hover:underline",onClick:Q,children:"Re-check"}):null]}),n?o("div",{class:"mx-4 mt-3 flex gap-2 rounded-lg bg-raised px-3 py-2 text-[13px] text-muted",children:[o(h,{name:"info",class:"mt-0.5 size-3.5 text-faint"}),"You changed the form since this check."]}):null,d.issues.length?o("div",{class:"space-y-5 px-3 py-4",children:r.map(([s,a])=>o("div",{children:[o("p",{class:"eyebrow mb-1.5 flex items-center gap-2 px-2",children:[o(h,{name:we[s.id]||"box",class:"size-3.5"}),s.title]}),o("ul",{class:"space-y-0.5",children:a.map((i,c)=>{let u=i.level==="error";return o("li",{children:o("button",{type:"button",onClick:()=>ge(s.id,Mt(i.path)),class:"focus-ring flex w-full cursor-pointer gap-2.5 rounded-lg px-2 py-2 text-left transition-colors duration-150 hover:bg-raised",children:[o(h,{name:u?"xCircle":"alert",class:`mt-0.5 size-4 ${u?"text-danger":"text-warn"}`}),o("span",{class:"min-w-0",children:[o("span",{class:"block text-[13px] leading-5 text-body",children:i.message}),i.path?o("span",{class:"mt-0.5 block truncate font-mono text-xs text-faint",children:i.path}):null]})]})},c)})})]},s.id))}):o(oe,{icon:"checkCircle",tint:"text-ok",title:"No problems found",text:"This configuration passes every check."})]})}function pn(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/("(\\u[a-fA-F0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+-]?\d+)?)/g,n=>{let r="var(--af-json-number)";return n.startsWith('"')?r=n.endsWith(":")?"var(--af-json-key)":"var(--af-json-string)":(n==="true"||n==="false"||n==="null")&&(r="var(--af-json-literal)"),`<span style="color:${r}">${n}</span>`})}function fn(){let e=JSON.stringify(d.config,null,2).split(`
|
|
3
|
+
`);return o("div",{children:[o("div",{class:"sticky top-0 flex items-center justify-between gap-3 border-b border-line bg-surface px-4 py-2.5",children:[o("p",{class:"text-xs text-faint",children:j()||!d.exists?"Preview of what Save will write":"Matches the file on disk"}),o("button",{type:"button",class:"btn btn-ghost h-8 px-2.5 text-xs",onClick:Dt,children:[o(h,{name:"copy",class:"size-3.5"}),"Copy"]})]}),o("div",{class:"py-3 pr-4 font-mono text-[12.5px] leading-5",children:e.map((t,n)=>o("div",{class:"flex",children:[o("span",{class:"w-10 shrink-0 pr-3 text-right text-faint/70 select-none",children:n+1}),o("span",{class:"min-w-0 flex-1 break-all whitespace-pre-wrap",dangerouslySetInnerHTML:{__html:pn(t)}})]},n))})]})}function Ut(e){let t=[];for(let n of e.fields){if(n.show_if&&At(n.show_if.path)!==n.show_if.equals)continue;let r=n.group||"",s=t.find(a=>a.name===r);s||t.push(s={name:r,fields:[]}),s.fields.push(n)}return t}var G=(e,t)=>x(n=>{t===void 0?It(n.config,e):$t(n.config,e,t)});function _n({id:e,value:t,field:n,invalid:r}){let[s,a]=me(String(t??""));return W(()=>{(s===""?t!==void 0:Number(s)!==t)&&a(String(t??""))},[t]),o("input",{id:e,type:"number",inputmode:"decimal",value:s,min:n.min,step:n.step,placeholder:n.placeholder??n.default??"",class:`input font-mono tabular-nums ${r?"input-invalid":""}`,onInput:i=>{let c=i.currentTarget.value;a(c),c===""?G(n.path,void 0):Number.isNaN(Number(c))||G(n.path,Number(c))}})}function Wt({field:e}){let t=e.path.join("."),n=`f-${e.path.join("-")}`,r=Ue(d.config,e.path),s=X(t),a=s?.level==="error";if(e.type==="bool")return o("div",{class:"flex items-start justify-between gap-6 px-5 py-4",children:[o("div",{class:"min-w-0",children:[o(N,{label:e.label,path:t,help:e.help,id:n}),o(F,{issue:s})]}),o("div",{class:"pt-0.5",children:o(Te,{id:n,on:(r??e.default??!1)===!0,label:e.label,onChange:c=>G(e.path,c)})})]});if(e.type==="list")return o("div",{class:"px-5 py-4",children:[o(N,{label:e.label,path:t,help:e.help,id:n,required:e.required}),o("div",{class:"mt-3",children:[o(te,{id:n,values:Array.isArray(r)?r:[],placeholder:e.placeholder,onChange:c=>G(e.path,c.length?c:void 0)}),o(F,{issue:s})]})]});let i;return e.type==="select"?i=o(Se,{id:n,options:e.options.map(c=>[c,c]),value:r??e.default??e.options[0],invalid:a,onChange:c=>G(e.path,c)}):e.type==="number"?i=o(_n,{id:n,value:r,field:e,invalid:a}):i=o("input",{id:n,type:"text",value:r??"",placeholder:e.placeholder,autocomplete:"off",spellcheck:!1,autocapitalize:"off",class:`input font-mono ${a?"input-invalid":""}`,onInput:c=>G(e.path,c.currentTarget.value===""?void 0:c.currentTarget.value)}),o(ne,{children:[o(N,{label:e.label,path:t,help:e.help,id:n,required:e.required}),o("div",{class:"min-w-0 sm:pt-0.5",children:[i,o(F,{issue:s})]})]})}function Vt(){let e=d.config.auth,t=O(e)?"custom":"jwt";return o("div",{class:"space-y-6",children:[o(R,{title:"Method",children:o(qe,{name:"auth",label:"Authentication method",value:t,options:[["jwt","JWT","Verify bearer tokens signed with JWT_SECRET_KEY."],["custom","Custom backend","Your own BaseAuth subclass decides who is calling."]],onPick:n=>x(r=>{r.config.auth=n==="jwt"?"jwt":{method:"custom",path:""}})})}),t==="custom"?o(R,{title:"Backend",children:o("div",{class:"panel",children:o(B,{id:"auth-path",label:"Auth class",path:"auth.path",value:e.path,placeholder:"auth.custom:MyAuth",help:"Import path of a BaseAuth subclass, as module:attribute.",issue:X("auth.path"),onInput:n=>x(r=>{r.config.auth={...r.config.auth,method:"custom",path:n}})})})}):null]})}function hn(e){if(O(e))return"rbac";if(typeof e=="string"){let t=e.trim().toLowerCase();if(t==="ownership")return"ownership";if(["allow_all","default","none"].includes(t))return"allow_all"}return e==null?null:"custom"}var mn={ownership:()=>"ownership",allow_all:()=>"allow_all",custom:()=>"",rbac:()=>({backend:"rbac",roles:{admin:["*"],member:["graph:invoke","graph:stream","graph:read","checkpointer:read"]},default_scopes:[],isolation:"owner"})};function Bt({sec:e}){let t=d.config.authorization,n=hn(t)??"ownership";return o("div",{class:"space-y-6",children:[o(R,{title:"Policy",children:o(qe,{name:"authz",label:"Authorization policy",value:n,options:[["ownership","Ownership","Users can only reach threads they created."],["allow_all","Allow all","Any authenticated user can do anything."],["rbac","Roles and scopes","Map roles to scopes, on top of owner isolation."],["custom","Custom backend","Your own AuthorizationBackend class."]],onPick:r=>x(s=>{s.config.authorization=mn[r]()})})}),n==="custom"?o(R,{title:"Backend",children:o("div",{class:"panel",children:o(B,{id:"authz-path",label:"Backend class",path:"authorization",placeholder:"auth.permissions:MyBackend",value:typeof t=="string"?t:"",issue:X("authorization"),help:"Import path of an AuthorizationBackend, as module:attribute.",onInput:r=>x(s=>{s.config.authorization=r})})})}):null,n==="rbac"?o(bn,{sec:e,value:t}):null]})}function xn({id:e,name:t,onRename:n}){let[r,s]=me(t);return W(()=>s(t),[t]),o("div",{children:[o("label",{for:e,class:"sr-only",children:"Role name"}),o("input",{id:e,type:"text",value:r,class:"input font-mono",autocomplete:"off",spellcheck:!1,onInput:a=>s(a.currentTarget.value),onChange:a=>{n(a.currentTarget.value.trim())||s(t)}})]})}function bn({sec:e,value:t}){let n="roles"in t||!("role_scopes"in t)?"roles":"role_scopes",r=O(t[n])?t[n]:{},s=["*",...e.scopes||[]],a=Object.entries(r),i=u=>x(()=>{t[n]=u}),c=()=>{let u=a.length+1;for(;`role${u}`in r;)u++;i({...r,[`role${u}`]:[]})};return o(S,{children:[o(R,{title:"Roles",children:o("div",{class:"panel",children:[o("div",{class:"hidden grid-cols-[10rem_minmax(0,1fr)_auto] gap-3 border-b border-line px-5 py-2.5 sm:grid",children:[o("span",{class:"text-xs font-medium text-faint",children:"Role"}),o("span",{class:"text-xs font-medium text-faint",children:"Scopes"}),o("span",{class:"w-9"})]}),a.length?o("div",{class:"divide-y divide-line",children:a.map(([u,p],_)=>o("div",{class:"grid gap-3 px-5 py-4 sm:grid-cols-[10rem_minmax(0,1fr)_auto] sm:items-start",children:[o(xn,{id:`role-name-${_}`,name:u,onRename:m=>!m||m!==u&&m in r?!1:(i(Object.fromEntries(Object.entries(r).map(([l,f])=>[l===u?m:l,f]))),!0)}),o(te,{id:`role-scopes-${_}`,values:Array.isArray(p)?p:[],placeholder:"Add a scope",suggestions:s,onChange:m=>i({...r,[u]:m})}),o("button",{type:"button",class:"icon-btn justify-self-end hover:text-danger","aria-label":`Remove role ${u}`,onClick:()=>i(Object.fromEntries(Object.entries(r).filter(([m])=>m!==u))),children:o(h,{name:"trash"})})]},_))}):o("p",{class:"px-5 py-6 text-center text-sm text-muted",children:"No roles yet. Users only get the default scopes."}),o("div",{class:"flex items-center justify-between gap-4 border-t border-line px-5 py-3",children:[o("p",{class:"text-[13px] text-muted",children:["Read from the user's roles (or role) claim. ",o("code",{class:"font-mono",children:"*"})," grants every scope."]}),o("button",{type:"button",class:"btn btn-ghost",onClick:c,children:[o(h,{name:"plus"}),"Add role"]})]})]})}),o(R,{title:"Defaults",children:o("div",{class:"panel divide-y divide-line",children:[o("div",{class:"px-5 py-4",children:[o(N,{label:"Default scopes",path:"authorization.default_scopes",id:"rbac-default-scopes",help:"Granted to every authenticated user, even without a role."}),o("div",{class:"mt-3",children:o(te,{id:"rbac-default-scopes",values:Array.isArray(t.default_scopes)?t.default_scopes:[],placeholder:"graph:read",suggestions:s,onChange:u=>x(()=>{t.default_scopes=u})})})]}),o(ne,{children:[o(N,{label:"Thread isolation",path:"authorization.isolation",id:"rbac-isolation",help:"owner keeps each user's threads private; none shares them."}),o("div",{class:"min-w-0 sm:pt-0.5",children:o(Se,{id:"rbac-isolation",options:[["owner","owner"],["none","none"]],value:t.isolation??"owner",onChange:u=>x(()=>{t.isolation=u})})})]})]})})]})}function Gt(){let e=Array.isArray(d.config.remote_tools)?d.config.remote_tools:[],t=()=>{x(n=>{e.push({node:"",name:"",description:"",parameters:{type:"object",properties:{},required:[]}}),n.config.remote_tools=e}),requestAnimationFrame(()=>document.getElementById(`tool-${e.length-1}-name`)?.focus())};return e.length?o("div",{class:"space-y-4",children:[e.map((n,r)=>o(vn,{tools:e,tool:n,index:r},r)),o("button",{type:"button",onClick:t,class:"focus-ring flex h-12 w-full cursor-pointer items-center justify-center gap-2 rounded-xl border border-dashed border-line-strong text-sm font-medium text-muted transition-colors duration-150 hover:border-brand hover:text-brand",children:[o(h,{name:"plus"}),"Add remote tool"]})]}):o("div",{class:"rounded-xl border border-dashed border-line-strong bg-surface px-6 py-10 text-center",children:[o("div",{class:"mx-auto flex size-11 items-center justify-center rounded-full bg-raised text-faint",children:o(h,{name:"wrench",class:"size-5"})}),o("p",{class:"mt-4 text-sm font-semibold text-ink",children:"No remote tools yet"}),o("p",{class:"mx-auto mt-1 max-w-sm text-sm leading-6 text-muted",children:"Declare a tool here and the client that calls the API runs it, for example to read the user's location."}),o("button",{type:"button",class:"btn btn-outline mt-5",onClick:t,children:[o(h,{name:"plus"}),"Add remote tool"]})]})}function vn({tools:e,tool:t,index:n}){let r=d.toolParams[n]??{text:JSON.stringify(t.parameters??{},null,2),error:null},s=i=>x(()=>{e[n]={...e[n],...i}}),a=i=>`remote_tools[${n}].${i}`;return o("section",{class:"panel",children:[o("div",{class:"flex items-center gap-3 border-b border-line px-5 py-3",children:[o(h,{name:"wrench",class:"size-4 text-faint"}),o("span",{class:"min-w-0 flex-1 truncate font-mono text-sm font-medium text-ink",children:t.name||`tool_${n+1}`}),t.node?o("span",{class:"rounded-md border border-line bg-raised px-1.5 py-0.5 font-mono text-xs text-muted",children:t.node}):null,o("button",{type:"button",class:"icon-btn hover:text-danger","aria-label":`Remove ${t.name||"tool"}`,onClick:()=>x(i=>{e.splice(n,1),i.toolParams={}}),children:o(h,{name:"trash"})})]}),o("div",{class:"divide-y divide-line",children:[o(B,{id:`tool-${n}-name`,label:"Tool name",path:a("name"),value:t.name,placeholder:"get_location",onInput:i=>s({name:i})}),o(B,{id:`tool-${n}-node`,label:"Graph node",path:a("node"),value:t.node,placeholder:"MAIN",help:"The node whose model may call this tool.",onInput:i=>s({node:i})}),o(B,{id:`tool-${n}-description`,label:"Description",path:a("description"),value:t.description,placeholder:"Returns the user's current city",help:"What the model reads when deciding to call it.",onInput:i=>s({description:i})}),o("div",{class:"px-5 py-4",children:[o(N,{label:"Parameters",path:a("parameters"),help:"JSON schema of the arguments. type must be object.",id:`tool-${n}-params`}),o("textarea",{id:`tool-${n}-params`,rows:7,spellcheck:!1,value:r.text,class:`input mt-3 h-auto py-2.5 font-mono text-[13px] leading-5 ${r.error?"input-invalid":""}`,onInput:i=>{let c=i.currentTarget.value;x(u=>{try{e[n]={...e[n],parameters:JSON.parse(c)},u.toolParams[n]={text:c,error:null}}catch(p){u.toolParams[n]={text:c,error:p.message}}})}}),o(F,{issue:r.error?{level:"error",message:r.error}:null})]})]})]})}function gn(){let e=d.path.split(/[\\/]/).pop()||"10xgraph.json",t=d.path.slice(0,d.path.length-e.length),n=null;return d.schema?d.exists?j()?n=o(Ce,{class:"bg-warn-soft text-warn",children:"Unsaved"}):n=o(Ce,{class:"bg-ok-soft text-ok",children:"Saved"}):n=o(Ce,{class:"bg-brand-soft text-brand",children:"New"}):n=null,o("div",{class:"flex min-w-0 flex-1 items-center gap-2",title:d.path||void 0,children:[o(h,{name:"file",class:"size-4 text-faint"}),o("span",{class:"truncate font-mono text-[13px] font-medium text-ink",children:e}),n,t?o("span",{class:"hidden min-w-0 truncate font-mono text-xs text-faint lg:block",dir:"rtl",children:o("bdi",{children:t})}):null]})}function Jt(){let{errors:e,warnings:t}=M(),n=!!d.schema&&!d.fatal,r=d.busy==="validate";return o("header",{class:"sticky top-0 z-30 flex h-14 items-center gap-2 border-b border-line bg-surface/95 px-3 backdrop-blur sm:gap-3 sm:px-4",children:[o("div",{class:"flex shrink-0 items-center gap-2.5",children:[o("svg",{viewBox:"0 0 48 48",class:"size-7 shrink-0 text-ink","aria-hidden":"true",children:[o("rect",{x:"4",y:"4",width:"40",height:"40",rx:"11",fill:"none",stroke:"currentColor","stroke-width":"4.4"}),o("path",{d:"M13 33L21 23L34 15L34 31L21 23",fill:"none",stroke:"currentColor","stroke-width":"3","stroke-linecap":"round","stroke-linejoin":"round"}),o("g",{fill:"currentColor",children:[o("circle",{cx:"21",cy:"23",r:"4"}),o("circle",{cx:"34",cy:"15",r:"4"}),o("circle",{cx:"34",cy:"31",r:"4"})]}),o("circle",{cx:"13",cy:"33",r:"4.6",class:"fill-brand-amber"})]}),o("div",{class:"hidden items-baseline gap-1.5 md:flex",children:[o("span",{class:"text-[15px] font-semibold tracking-tight text-ink",children:"10xGraph"}),o("span",{class:"text-[15px] text-faint",children:"Config"})]})]}),o("span",{class:"hidden h-6 w-px shrink-0 bg-line md:block","aria-hidden":"true"}),o(gn,{}),o("button",{type:"button",class:"icon-btn relative xl:hidden","aria-label":"Open problems and JSON preview",onClick:()=>ye(),children:[o(h,{name:"panel",class:"size-[18px]"}),e||t?o("span",{class:`absolute top-1 right-1 flex size-4 items-center justify-center rounded-full text-[10px] font-bold text-white ${e?"bg-danger":"bg-warn"}`,children:e||t}):null]}),o("button",{type:"button",class:"btn btn-outline","aria-label":"Validate configuration",disabled:!n||!!d.busy,onClick:Q,children:[o(h,{name:r?"spinner":"checkCircle",class:`size-4 ${r?"animate-spin":""}`}),o("span",{class:"hidden sm:inline",children:"Validate"})]}),o("button",{type:"button",class:"btn btn-primary",onClick:ve,disabled:!n||!!d.busy||d.exists&&!j()&&!d.parseError,children:[d.busy==="save"?o(h,{name:"spinner",class:"size-4 animate-spin"}):null,d.exists?"Save":"Create file",o("span",{class:"kbd hidden lg:inline-flex",children:"Ctrl S"})]})]})}function qt(){return d.fatal?o("div",{class:"panel mt-10",children:o(oe,{icon:"xCircle",tint:"text-danger",title:d.fatal.title,text:d.fatal.text})}):d.schema?o(S,{children:[o("div",{class:"pt-8",children:[o("h1",{class:"text-xl font-semibold tracking-tight text-ink",children:"Server configuration"}),o("p",{class:"mt-1 max-w-prose text-sm leading-6 text-muted",children:"Every 10xgraph.json option on one page. Fill in the essentials to get running, then switch on what you need on the way to production."})]}),o(yn,{}),d.parseError?o("div",{class:"mt-6",children:o($e,{kind:"warn",title:"The existing file is not valid JSON",lines:[`${d.parseError}. The form starts from defaults; saving replaces the file and keeps the old one as 10xgraph.json.bak.`]})}):null,d.tiers.map(e=>o(wn,{tier:e},e.id))]}):o("div",{class:"animate-pulse space-y-4 pt-8","aria-label":"Loading",children:[o("div",{class:"h-7 w-48 rounded-md bg-raised"}),o("div",{class:"h-4 w-80 max-w-full rounded-md bg-raised"}),[0,1,2,3].map(e=>o("div",{class:"h-16 rounded-xl bg-raised"},e))]})}function yn(){let e=d.sections.every(t=>d.open.has(t.id));return o("div",{class:"sticky top-14 z-20 -mx-4 mt-6 flex items-center gap-2 border-b border-line bg-canvas/90 px-4 py-2 backdrop-blur sm:-mx-8 sm:px-8",children:[o("nav",{class:"-ml-2.5 flex min-w-0 flex-1 gap-1 overflow-x-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden","aria-label":"Jump to a tier",children:d.tiers.map(t=>o(kn,{tier:t},t.id))}),o("button",{type:"button",class:"btn btn-ghost","aria-label":e?"Collapse all sections":"Expand all sections",onClick:()=>Nt(!e),children:[o(h,{name:e?"collapse":"expand"}),o("span",{class:"hidden sm:inline",children:e?"Collapse all":"Expand all"})]}),o("a",{href:d.schema.docs_url,target:"_blank",rel:"noopener",class:"btn btn-ghost","aria-label":"Configuration reference",children:[o(h,{name:"book"}),o("span",{class:"hidden sm:inline",children:"Reference"})]})]})}function kn({tier:e}){let t=e.list.filter(V).length,{errors:n,warnings:r}=M(d.issues.filter(s=>e.list.some(a=>a.id===s.section)));return o("a",{href:`#tier-${e.id}`,title:`${t} of ${I(e.list.length,"section")} on`,class:"focus-ring inline-flex h-9 shrink-0 items-center gap-2 rounded-lg px-2.5 text-sm text-muted transition-colors duration-150 hover:bg-raised hover:text-ink",onClick:s=>{s.preventDefault(),Rt(e.id)},children:[o("span",{class:"font-medium",children:e.title}),o("span",{class:"font-mono text-xs text-faint tabular-nums",children:[t,"/",e.list.length]}),n||r?o("span",{class:`size-1.5 rounded-full ${n?"bg-danger":"bg-warn"}`}):null]})}function wn({tier:e}){let t=e.list.filter(V).length;return o("section",{id:`tier-${e.id}`,class:"mt-10 scroll-mt-28","aria-labelledby":`tier-${e.id}-title`,children:[o("div",{class:"mb-3",children:[o("div",{class:"flex items-baseline gap-3",children:[o("h2",{id:`tier-${e.id}-title`,class:"text-base font-semibold tracking-tight text-ink",children:e.title}),o("span",{class:"text-xs text-faint",children:[t," of ",e.list.length," on"]})]}),o("p",{class:"mt-0.5 text-sm text-muted",children:e.tagline})]}),o("div",{class:"space-y-3",children:e.list.map(n=>o(Cn,{sec:n},n.id))})]})}function Cn({sec:e}){let t=V(e),n=d.open.has(e.id),{errors:r,warnings:s}=M(Y(e.id)),a=`body-${e.id}`,i=null;return r?i=o("span",{class:"inline-flex shrink-0 items-center gap-1 text-xs font-medium text-danger",title:I(r,"error"),children:[o(h,{name:"xCircle",class:"size-3.5"}),r]}):s&&(i=o("span",{class:"inline-flex shrink-0 items-center gap-1 text-xs font-medium text-warn",title:I(s,"warning"),children:[o(h,{name:"alert",class:"size-3.5"}),s]})),o("section",{id:`sec-${e.id}`,class:`panel scroll-mt-32 ${r?"border-danger/40":""}`,children:[o("div",{class:"flex items-center gap-3 pr-4 sm:pr-5",children:[o("h3",{class:"min-w-0 flex-1",children:o("button",{type:"button",id:`acc-${e.id}`,"aria-expanded":n?"true":"false","aria-controls":a,class:"focus-ring flex w-full cursor-pointer items-center gap-3 rounded-xl py-3.5 pl-3 text-left sm:pl-4",onClick:()=>jt(e.id),children:[o(h,{name:"chevronDown",class:`size-4 text-faint transition-transform duration-200 ${n?"":"-rotate-90"}`}),o("span",{class:`flex size-9 shrink-0 items-center justify-center rounded-lg border border-line ${t?"bg-brand-soft text-brand":"bg-raised text-faint"}`,children:o(h,{name:we[e.id]||"box",class:"size-[18px]"})}),o("span",{class:"min-w-0 flex-1",children:[o("span",{class:"flex flex-wrap items-center gap-x-2 gap-y-0.5",children:[o("span",{class:`text-sm font-semibold ${t?"text-ink":"text-muted"}`,children:e.title}),e.key?o("code",{class:"hidden rounded border border-line bg-raised px-1.5 font-mono text-[11px] leading-4 text-faint sm:inline",children:e.key}):null]}),o("span",{class:"mt-0.5 block text-[13px] leading-5 text-muted",children:e.description})]}),i]})}),e.optional?o("div",{class:"flex shrink-0 items-center gap-2.5",children:[o("span",{class:"hidden w-6 text-xs font-medium text-faint sm:inline",children:t?"On":"Off"}),o(Te,{id:`toggle-${e.id}`,on:t,label:`${t?"Turn off":"Turn on"} ${e.title}`,onChange:c=>Je(e,c)})]}):null]}),o("div",{id:a,role:"region","aria-labelledby":`acc-${e.id}`,inert:!n,class:`grid transition-[grid-template-rows] duration-200 ease-out ${n?"grid-rows-[1fr]":"grid-rows-[0fr]"}`,children:o("div",{class:"min-h-0 overflow-hidden",children:o("div",{class:"space-y-6 rounded-b-xl border-t border-line bg-canvas/60 px-4 py-5 sm:px-5",children:o(Tn,{sec:e,on:t})})})})]})}function Tn({sec:e,on:t}){if(!t)return o("div",{class:"flex flex-col items-start gap-3 sm:flex-row sm:items-center sm:justify-between sm:gap-6",children:[o("p",{class:"text-sm leading-6 text-muted",children:[o("code",{class:"font-mono text-[13px] text-body",children:e.key})," is not in 10xgraph.json. ",e.off_summary||""]}),o("button",{type:"button",class:"btn btn-outline",onClick:()=>Je(e,!0),children:[o(h,{name:"power"}),"Turn on ",e.title.toLowerCase()]})]});let n=new Set([...e.fields.map(s=>s.path.join(".")),...Object.keys(Fe)]),r=Y(e.id).filter(s=>!n.has(s.path));return o(S,{children:[r.length?o("div",{class:"space-y-2",children:r.map((s,a)=>o(Lt,{issue:s},a))}):null,e.notes?.length?o($e,{kind:"info",lines:e.notes}):null,e.widget==="auth"?o(Vt,{}):null,e.widget==="authorization"?o(Bt,{sec:e}):null,e.widget==="remote_tools"?o(Gt,{}):null,Ut(e).map(s=>o(R,{title:s.name,children:o("div",{class:"panel divide-y divide-line",children:s.fields.map(a=>o(Wt,{field:a},a.path.join(".")))})},s.name))]})}var Sn={success:["checkCircle","text-ok"],warning:["alert","text-warn"],error:["xCircle","text-danger"]};function $n(){return o("div",{class:"pointer-events-none fixed right-4 bottom-4 left-4 z-50 flex flex-col items-end gap-2 sm:left-auto","aria-live":"polite",children:d.toasts.map(e=>{let[t,n]=Sn[e.kind];return o("div",{role:e.kind==="error"?"alert":"status",class:"pointer-events-auto flex w-full max-w-sm items-start gap-3 rounded-xl border border-line bg-surface px-4 py-3 text-sm shadow-pop",children:[o(h,{name:t,class:`mt-0.5 size-4 ${n}`}),o("p",{class:"min-w-0 flex-1 leading-5 text-body",children:e.message}),e.action?o("button",{type:"button",class:"shrink-0 font-medium text-brand hover:underline",onClick:()=>{ke(e.id),e.action.run()},children:e.action.label}):null,o("button",{type:"button",class:"-mr-1 shrink-0 cursor-pointer rounded text-faint hover:text-ink","aria-label":"Dismiss",onClick:()=>ke(e.id),children:o(h,{name:"x"})})]},e.id)})})}function In(){let[,e]=He(t=>t+1,0);return W(()=>{Tt(e);let t=r=>{(r.ctrlKey||r.metaKey)&&r.key.toLowerCase()==="s"?(r.preventDefault(),ve()):r.key==="Escape"&&d.inspectorOpen&&ee()},n=r=>{d.schema&&j()&&r.preventDefault()};return document.addEventListener("keydown",t),window.addEventListener("beforeunload",n),Ot(),()=>{document.removeEventListener("keydown",t),window.removeEventListener("beforeunload",n)}},[]),o(S,{children:[o("a",{href:"#main",class:"sr-only z-50 rounded-md bg-brand-solid px-3 py-2 text-white focus:not-sr-only focus:fixed focus:top-3 focus:left-3",children:"Skip to content"}),o(Jt,{}),o("div",{class:"flex",children:[o("main",{id:"main",tabindex:-1,class:"min-w-0 flex-1 focus:outline-none",children:o("div",{class:"mx-auto w-full max-w-4xl px-4 pb-24 sm:px-8",children:o(qt,{})})}),o(Ft,{})]}),d.inspectorOpen?o("div",{class:"fixed inset-0 z-30 bg-black/50 xl:hidden",onClick:ee}):null,o($n,{})]})}dt(o(In,{}),document.getElementById("app"));
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
|
|
2
|
+
<title>10xGraph</title>
|
|
3
|
+
<style>
|
|
4
|
+
.ink { stroke: #0B0E13; fill: #0B0E13; } .amb { fill: #C8692F; }
|
|
5
|
+
@media (prefers-color-scheme: dark) { .ink { stroke: #F2F4F7; fill: #F2F4F7; } .amb { fill: #E9A57C; } }
|
|
6
|
+
</style>
|
|
7
|
+
<rect class="ink" x="4" y="4" width="40" height="40" rx="11" fill="none" style="fill:none" stroke-width="4.4"/>
|
|
8
|
+
<path class="ink" d="M13 33L21 23L34 15L34 31L21 23" style="fill:none" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
|
|
9
|
+
<g class="ink" stroke="none"><circle cx="21" cy="23" r="4"/><circle cx="34" cy="15" r="4"/><circle cx="34" cy="31" r="4"/></g>
|
|
10
|
+
<circle class="amb" cx="13" cy="33" r="4.6"/>
|
|
11
|
+
</svg>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
+
<title>10xGraph Config</title>
|
|
7
|
+
<meta name="description" content="Browser editor for 10xgraph.json">
|
|
8
|
+
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
|
|
9
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
10
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
11
|
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
|
|
12
|
+
<!-- Built from 10xgraph-api/config-editor-ui (npm run build). Do not edit app.css or app.js by hand. -->
|
|
13
|
+
<link rel="stylesheet" href="/app.css">
|
|
14
|
+
<script type="module" src="/app.js"></script>
|
|
15
|
+
</head>
|
|
16
|
+
<body>
|
|
17
|
+
<div id="app"></div>
|
|
18
|
+
<noscript>The 10xgraph.json editor needs JavaScript.</noscript>
|
|
19
|
+
</body>
|
|
20
|
+
</html>
|