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.
Files changed (203) hide show
  1. 10xgraph_api-0.7.0.dist-info/METADATA +618 -0
  2. 10xgraph_api-0.7.0.dist-info/RECORD +203 -0
  3. 10xgraph_api-0.7.0.dist-info/WHEEL +5 -0
  4. 10xgraph_api-0.7.0.dist-info/entry_points.txt +3 -0
  5. 10xgraph_api-0.7.0.dist-info/licenses/LICENSE +21 -0
  6. 10xgraph_api-0.7.0.dist-info/top_level.txt +2 -0
  7. agentflow_cli/__init__.py +69 -0
  8. tenxgraph_api/__init__.py +23 -0
  9. tenxgraph_api/cli/__init__.py +6 -0
  10. tenxgraph_api/cli/capabilities.py +127 -0
  11. tenxgraph_api/cli/commands/__init__.py +49 -0
  12. tenxgraph_api/cli/commands/api.py +262 -0
  13. tenxgraph_api/cli/commands/audit.py +213 -0
  14. tenxgraph_api/cli/commands/build.py +305 -0
  15. tenxgraph_api/cli/commands/config.py +71 -0
  16. tenxgraph_api/cli/commands/demo.py +93 -0
  17. tenxgraph_api/cli/commands/eval.py +909 -0
  18. tenxgraph_api/cli/commands/init.py +531 -0
  19. tenxgraph_api/cli/commands/skills.py +532 -0
  20. tenxgraph_api/cli/commands/test.py +113 -0
  21. tenxgraph_api/cli/commands/version.py +47 -0
  22. tenxgraph_api/cli/config_editor/__init__.py +15 -0
  23. tenxgraph_api/cli/config_editor/schema.py +566 -0
  24. tenxgraph_api/cli/config_editor/server.py +240 -0
  25. tenxgraph_api/cli/config_editor/static/app.css +2 -0
  26. tenxgraph_api/cli/config_editor/static/app.js +3 -0
  27. tenxgraph_api/cli/config_editor/static/favicon.svg +11 -0
  28. tenxgraph_api/cli/config_editor/static/index.html +20 -0
  29. tenxgraph_api/cli/config_editor/store.py +120 -0
  30. tenxgraph_api/cli/config_editor/validation.py +377 -0
  31. tenxgraph_api/cli/constants.py +112 -0
  32. tenxgraph_api/cli/context.py +46 -0
  33. tenxgraph_api/cli/core/__init__.py +0 -0
  34. tenxgraph_api/cli/core/animations.py +550 -0
  35. tenxgraph_api/cli/core/config.py +279 -0
  36. tenxgraph_api/cli/core/output.py +625 -0
  37. tenxgraph_api/cli/core/prompts.py +220 -0
  38. tenxgraph_api/cli/core/screen.py +287 -0
  39. tenxgraph_api/cli/core/steps.py +621 -0
  40. tenxgraph_api/cli/core/theme.py +242 -0
  41. tenxgraph_api/cli/core/validation.py +251 -0
  42. tenxgraph_api/cli/exceptions.py +129 -0
  43. tenxgraph_api/cli/logger.py +84 -0
  44. tenxgraph_api/cli/main.py +936 -0
  45. tenxgraph_api/cli/templates/__init__.py +0 -0
  46. tenxgraph_api/cli/templates/defaults.py +844 -0
  47. tenxgraph_api/cli/templates/dev/.env.example +1 -0
  48. tenxgraph_api/cli/templates/dev/10xgraph.json +16 -0
  49. tenxgraph_api/cli/templates/dev/graph/__init__.py +0 -0
  50. tenxgraph_api/cli/templates/dev/graph/agent.py +63 -0
  51. tenxgraph_api/cli/templates/prod/.env.example +75 -0
  52. tenxgraph_api/cli/templates/prod/.pre-commit-config.yaml +50 -0
  53. tenxgraph_api/cli/templates/prod/.python-version +1 -0
  54. tenxgraph_api/cli/templates/prod/10xgraph.json +42 -0
  55. tenxgraph_api/cli/templates/prod/auth/__init__.py +0 -0
  56. tenxgraph_api/cli/templates/prod/auth/agent_auth.py +46 -0
  57. tenxgraph_api/cli/templates/prod/evals/__init__.py +0 -0
  58. tenxgraph_api/cli/templates/prod/evals/user_simulator_eval.py +76 -0
  59. tenxgraph_api/cli/templates/prod/evals/weather_agents_eval.py +53 -0
  60. tenxgraph_api/cli/templates/prod/graph/__init__.py +0 -0
  61. tenxgraph_api/cli/templates/prod/graph/agent.py +50 -0
  62. tenxgraph_api/cli/templates/prod/graph/state.py +5 -0
  63. tenxgraph_api/cli/templates/prod/graph/thread_name_generator.py +7 -0
  64. tenxgraph_api/cli/templates/prod/graph/tools/__init__.py +0 -0
  65. tenxgraph_api/cli/templates/prod/graph/tools/weather_tool.py +43 -0
  66. tenxgraph_api/cli/templates/prod/graph/validators/__init__.py +0 -0
  67. tenxgraph_api/cli/templates/prod/graph/validators/lifecyle.py +107 -0
  68. tenxgraph_api/cli/templates/prod/graph/validators/manager.py +9 -0
  69. tenxgraph_api/cli/templates/prod/graph/validators/validators.py +21 -0
  70. tenxgraph_api/cli/templates/prod/pyproject.toml +79 -0
  71. tenxgraph_api/cli/templates/prod/tests/__init__.py +0 -0
  72. tenxgraph_api/cli/templates/prod/tests/conftest.py +6 -0
  73. tenxgraph_api/cli/templates/prod/tests/test_agent_eval.py +78 -0
  74. tenxgraph_api/cli/templates/prod/tests/test_catalog_tools.py +47 -0
  75. tenxgraph_api/cli/templates/prod/tests/test_graph_nodes.py +57 -0
  76. tenxgraph_api/cli/templates/skills/10xgraph/SKILL.md +92 -0
  77. tenxgraph_api/cli/templates/skills/10xgraph/references/agents-and-tools.md +389 -0
  78. tenxgraph_api/cli/templates/skills/10xgraph/references/api-client.md +61 -0
  79. tenxgraph_api/cli/templates/skills/10xgraph/references/api-configuration.md +75 -0
  80. tenxgraph_api/cli/templates/skills/10xgraph/references/api-settings-and-middleware.md +89 -0
  81. tenxgraph_api/cli/templates/skills/10xgraph/references/architecture.md +91 -0
  82. tenxgraph_api/cli/templates/skills/10xgraph/references/auth-and-authorization.md +149 -0
  83. tenxgraph_api/cli/templates/skills/10xgraph/references/callbacks-and-command.md +283 -0
  84. tenxgraph_api/cli/templates/skills/10xgraph/references/checkpointing-and-threads.md +63 -0
  85. tenxgraph_api/cli/templates/skills/10xgraph/references/cli-commands.md +73 -0
  86. tenxgraph_api/cli/templates/skills/10xgraph/references/client-auth-and-errors.md +94 -0
  87. tenxgraph_api/cli/templates/skills/10xgraph/references/client-messages-invoke-stream.md +115 -0
  88. tenxgraph_api/cli/templates/skills/10xgraph/references/client-threads-memory-files.md +80 -0
  89. tenxgraph_api/cli/templates/skills/10xgraph/references/context-id-background.md +80 -0
  90. tenxgraph_api/cli/templates/skills/10xgraph/references/dependency-injection.md +58 -0
  91. tenxgraph_api/cli/templates/skills/10xgraph/references/evaluation.md +500 -0
  92. tenxgraph_api/cli/templates/skills/10xgraph/references/id-and-thread-name-generators.md +69 -0
  93. tenxgraph_api/cli/templates/skills/10xgraph/references/media-and-files.md +66 -0
  94. tenxgraph_api/cli/templates/skills/10xgraph/references/memory-and-store.md +70 -0
  95. tenxgraph_api/cli/templates/skills/10xgraph/references/prebuilt-agents-and-tools.md +394 -0
  96. tenxgraph_api/cli/templates/skills/10xgraph/references/production-runtime.md +56 -0
  97. tenxgraph_api/cli/templates/skills/10xgraph/references/providers-and-adapters.md +89 -0
  98. tenxgraph_api/cli/templates/skills/10xgraph/references/publishers-and-runtime-protocols.md +84 -0
  99. tenxgraph_api/cli/templates/skills/10xgraph/references/rate-limiting.md +194 -0
  100. tenxgraph_api/cli/templates/skills/10xgraph/references/realtime.md +172 -0
  101. tenxgraph_api/cli/templates/skills/10xgraph/references/remote-tools.md +55 -0
  102. tenxgraph_api/cli/templates/skills/10xgraph/references/rest-api-and-errors.md +97 -0
  103. tenxgraph_api/cli/templates/skills/10xgraph/references/security-and-validators.md +86 -0
  104. tenxgraph_api/cli/templates/skills/10xgraph/references/state-and-messages.md +68 -0
  105. tenxgraph_api/cli/templates/skills/10xgraph/references/state-graph.md +232 -0
  106. tenxgraph_api/cli/templates/skills/10xgraph/references/stream-emitter.md +144 -0
  107. tenxgraph_api/cli/templates/skills/10xgraph/references/streaming.md +53 -0
  108. tenxgraph_api/cli/templates/skills/10xgraph/references/testing-and-evaluation.md +64 -0
  109. tenxgraph_api/cli/templates/skills/10xgraph/references/unit-testing.md +202 -0
  110. tenxgraph_api/cli/templates/skills/copilot/10xgraph.instructions.md +108 -0
  111. tenxgraph_api/py.typed +0 -0
  112. tenxgraph_api/src/__init__.py +0 -0
  113. tenxgraph_api/src/app/__init__.py +13 -0
  114. tenxgraph_api/src/app/core/__init__.py +15 -0
  115. tenxgraph_api/src/app/core/auth/__init__.py +0 -0
  116. tenxgraph_api/src/app/core/auth/auth_backend.py +38 -0
  117. tenxgraph_api/src/app/core/auth/authorization.py +379 -0
  118. tenxgraph_api/src/app/core/auth/base_auth.py +27 -0
  119. tenxgraph_api/src/app/core/auth/jwt_auth.py +122 -0
  120. tenxgraph_api/src/app/core/auth/ownership_resolver.py +170 -0
  121. tenxgraph_api/src/app/core/auth/permissions.py +354 -0
  122. tenxgraph_api/src/app/core/auth/request_config.py +130 -0
  123. tenxgraph_api/src/app/core/auth/route_guard.py +105 -0
  124. tenxgraph_api/src/app/core/config/__init__.py +0 -0
  125. tenxgraph_api/src/app/core/config/graph_config.py +532 -0
  126. tenxgraph_api/src/app/core/config/media_settings.py +72 -0
  127. tenxgraph_api/src/app/core/config/sentry_config.py +60 -0
  128. tenxgraph_api/src/app/core/config/settings.py +202 -0
  129. tenxgraph_api/src/app/core/config/setup_logs.py +65 -0
  130. tenxgraph_api/src/app/core/config/setup_middleware.py +483 -0
  131. tenxgraph_api/src/app/core/config/worker_middleware.py +99 -0
  132. tenxgraph_api/src/app/core/exceptions/__init__.py +17 -0
  133. tenxgraph_api/src/app/core/exceptions/general_exception.py +58 -0
  134. tenxgraph_api/src/app/core/exceptions/handle_errors.py +363 -0
  135. tenxgraph_api/src/app/core/exceptions/resources_exceptions.py +72 -0
  136. tenxgraph_api/src/app/core/exceptions/user_exception.py +58 -0
  137. tenxgraph_api/src/app/core/middleware/__init__.py +25 -0
  138. tenxgraph_api/src/app/core/middleware/rate_limit/__init__.py +15 -0
  139. tenxgraph_api/src/app/core/middleware/rate_limit/base.py +27 -0
  140. tenxgraph_api/src/app/core/middleware/rate_limit/factory.py +98 -0
  141. tenxgraph_api/src/app/core/middleware/rate_limit/keying.py +133 -0
  142. tenxgraph_api/src/app/core/middleware/rate_limit/memory.py +98 -0
  143. tenxgraph_api/src/app/core/middleware/rate_limit/middleware.py +90 -0
  144. tenxgraph_api/src/app/core/middleware/rate_limit/redis.py +115 -0
  145. tenxgraph_api/src/app/core/middleware/request_limits.py +154 -0
  146. tenxgraph_api/src/app/core/middleware/security_headers.py +239 -0
  147. tenxgraph_api/src/app/core/utils/__init__.py +14 -0
  148. tenxgraph_api/src/app/core/utils/log_sanitizer.py +216 -0
  149. tenxgraph_api/src/app/loader.py +516 -0
  150. tenxgraph_api/src/app/main.py +180 -0
  151. tenxgraph_api/src/app/routers/__init__.py +4 -0
  152. tenxgraph_api/src/app/routers/ag_ui/__init__.py +10 -0
  153. tenxgraph_api/src/app/routers/ag_ui/converter.py +195 -0
  154. tenxgraph_api/src/app/routers/ag_ui/event_mapper.py +353 -0
  155. tenxgraph_api/src/app/routers/ag_ui/router.py +90 -0
  156. tenxgraph_api/src/app/routers/ag_ui/service.py +193 -0
  157. tenxgraph_api/src/app/routers/checkpointer/__init__.py +1 -0
  158. tenxgraph_api/src/app/routers/checkpointer/router.py +482 -0
  159. tenxgraph_api/src/app/routers/checkpointer/schemas/__init__.py +1 -0
  160. tenxgraph_api/src/app/routers/checkpointer/schemas/checkpointer_schemas.py +121 -0
  161. tenxgraph_api/src/app/routers/checkpointer/services/__init__.py +1 -0
  162. tenxgraph_api/src/app/routers/checkpointer/services/checkpointer_service.py +300 -0
  163. tenxgraph_api/src/app/routers/evals/__init__.py +6 -0
  164. tenxgraph_api/src/app/routers/evals/router.py +38 -0
  165. tenxgraph_api/src/app/routers/evals/services/__init__.py +1 -0
  166. tenxgraph_api/src/app/routers/evals/services/eval_report_service.py +354 -0
  167. tenxgraph_api/src/app/routers/graph/__init__.py +6 -0
  168. tenxgraph_api/src/app/routers/graph/realtime_guard.py +161 -0
  169. tenxgraph_api/src/app/routers/graph/router.py +821 -0
  170. tenxgraph_api/src/app/routers/graph/schemas/__init__.py +1 -0
  171. tenxgraph_api/src/app/routers/graph/schemas/graph_schemas.py +386 -0
  172. tenxgraph_api/src/app/routers/graph/services/__init__.py +1 -0
  173. tenxgraph_api/src/app/routers/graph/services/graph_service.py +1219 -0
  174. tenxgraph_api/src/app/routers/graph/services/multimodal_preprocessor.py +164 -0
  175. tenxgraph_api/src/app/routers/media/__init__.py +506 -0
  176. tenxgraph_api/src/app/routers/media/router.py +242 -0
  177. tenxgraph_api/src/app/routers/media/schemas.py +39 -0
  178. tenxgraph_api/src/app/routers/ping/__init__.py +4 -0
  179. tenxgraph_api/src/app/routers/ping/router.py +28 -0
  180. tenxgraph_api/src/app/routers/setup_router.py +60 -0
  181. tenxgraph_api/src/app/routers/store/__init__.py +4 -0
  182. tenxgraph_api/src/app/routers/store/router.py +200 -0
  183. tenxgraph_api/src/app/routers/store/schemas/__init__.py +28 -0
  184. tenxgraph_api/src/app/routers/store/schemas/store_schemas.py +200 -0
  185. tenxgraph_api/src/app/routers/store/services/__init__.py +4 -0
  186. tenxgraph_api/src/app/routers/store/services/store_service.py +203 -0
  187. tenxgraph_api/src/app/tasks/__init__.py +0 -0
  188. tenxgraph_api/src/app/tasks/user_tasks.py +38 -0
  189. tenxgraph_api/src/app/utils/__init__.py +12 -0
  190. tenxgraph_api/src/app/utils/callable_helper.py +26 -0
  191. tenxgraph_api/src/app/utils/media/__init__.py +15 -0
  192. tenxgraph_api/src/app/utils/media/extractor.py +172 -0
  193. tenxgraph_api/src/app/utils/media/pipeline.py +83 -0
  194. tenxgraph_api/src/app/utils/parse_output.py +17 -0
  195. tenxgraph_api/src/app/utils/response_helper.py +129 -0
  196. tenxgraph_api/src/app/utils/schemas/__init__.py +11 -0
  197. tenxgraph_api/src/app/utils/schemas/output_schemas.py +28 -0
  198. tenxgraph_api/src/app/utils/schemas/user_schemas.py +13 -0
  199. tenxgraph_api/src/app/utils/snowflake_id_generator.py +90 -0
  200. tenxgraph_api/src/app/utils/swagger_helper.py +160 -0
  201. tenxgraph_api/src/app/utils/telemetry_store.py +123 -0
  202. tenxgraph_api/src/app/utils/thread_name_generator.py +304 -0
  203. 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)}&section=${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,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").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>