Compare commits

...
Author SHA1 Message Date
Ahmed Allam 10376b412b refactor(context): trim verbose comments 2026-07-26 19:26:51 +00:00
Ahmed Allam 95046a6cea fix(context): reject tool-output byte ceilings below the notice size
A configured tool_output_max_bytes smaller than the truncation notice
itself can't fit a bounded preview, so a persisted result could exceed the
ceiling. Enforce a config floor (ge=1024) so nonsensical values are
rejected at load time instead of being worked around at runtime.
2026-07-25 23:46:11 +00:00
Ahmed Allam aac59de1e5 fix(context): reserve notice budget so bounded output honors max_bytes
The head+tail slices could each take half of max_bytes, then the
truncation notice and its separators were appended on top, so the value
persisted to history could exceed the configured maximum. Reserve an
upper bound for the notice (and separators) out of the byte budget before
slicing so the whole joined result stays within max_bytes.
2026-07-25 23:06:40 +00:00
Ahmed Allam ce358aa879 fix(context): bound native filesystem tool output in Responses mode
Chat-completions mode converts filesystem CustomTools to FunctionTools
(which bounds their result), but the Responses-API path kept them native
and unbounded, so a large read_file could still exhaust the context
window. Always configure the Filesystem capability to head+tail bound
tool output in both modes.
2026-07-25 22:50:50 +00:00
Ahmed Allam dab93bcc12 fix(context): clamp shell output cap and count byte-trimmed dropped lines
Treat tool_output_max_tokens as a ceiling so an explicit model-supplied
cap can't exceed it, and derive the truncation notice's dropped-line
count from the lines actually kept after the byte-trim pass. Also cast
the pygments fallback lexer so it satisfies the resolve_lexer return
type under the pre-commit mypy hook.
2026-07-25 22:32:56 +00:00
Ahmed Allam 3b8980c47b feat(context): bound per-tool output before it enters agent history
Cap the size of every tool result so a single verbose command (recursive
find, noisy scanner, full page dump) can't pin the conversation near the
model's context window for the rest of a scan.

- New ContextSettings config group with env-tunable caps.
- Default the SDK shell tools' max_output_tokens so exec_command /
  write_stdin truncate head+tail instead of returning unbounded output.
- Bound Strix's own FunctionTool/CustomTool results (line + UTF-8 byte
  head+tail preview with a truncation notice) and cap error strings.
2026-07-25 22:31:31 +00:00
Ahmed Allam 8157ccba27 refactor(reports): fold fence helpers into report writer 2026-07-25 13:09:57 -07:00
Ahmed Allam 95d2e5fba9 fix(reports): safe-fence code-location snippets in markdown copy 2026-07-25 13:09:57 -07:00
Ahmed Allam 21243486e2 fix(reports): safe-fence markdown PoC export and share fence helpers 2026-07-25 13:09:57 -07:00
Ahmed Allam 97ed7e79a1 fix(reports): auto-detect PoC language with Python fallback 2026-07-25 13:09:57 -07:00
Ahmed Allam 31c18f8f75 fix(reports): strip markdown code fence from poc_script_code before rendering 2026-07-25 13:09:57 -07:00
Ahmed Allam f23fadfbff Rename root agent to Strix 2026-07-25 11:40:05 -07:00
08126eb518 feat(dedupe): add dedicated deduplication model (#823)
Co-authored-by: oyasumi <[email protected]>
Co-authored-by: Ahmed Allam <[email protected]>
2026-07-25 06:29:39 -07:00
Utku Tugrul d4f4697533 runtime: resolve staged local-dir path to avoid symlink rejection on macOS (#857) 2026-07-25 05:45:31 -07:00
dvir arad 57304b0084 docs(cli): document exit code 1 and clarify exit 0 semantics
The Exit Codes table in the CLI reference only listed 0 and 2, but the
CLI also exits with 1 on fatal errors (missing environment variables,
Docker unavailable, invalid config file, diff-scope resolution failure,
or an unhandled exception). It also implied exit 0 means no
vulnerabilities were found, which is only true in headless mode -
interactive runs always exit 0 regardless of findings.

Document exit code 1 and clarify the two cases for exit 0.
2026-07-25 05:29:13 -07:00
cd8270c98b Sign in with a ChatGPT subscription for inference (#854)
Co-authored-by: Jonathan Singer <[email protected]>
Co-authored-by: Jonathan Singer <[email protected]>
Co-authored-by: Ahmed Allam <[email protected]>
2026-07-24 15:41:19 -07:00
Ahmed Allam 93af2b94a2 chore(deps): bump setuptools to 83.0.0 (GHSA-h35f-9h28-mq5c) 2026-07-24 07:08:50 -07:00
Tim HainesandClaude Opus 4.8 960caf86aa Pin release-workflow actions to commit SHAs + least-privilege token (#862)
Every `uses:` in build-release.yml was a mutable tag; the `release` job has
`contents: write` and publishes the binaries users install, so a compromised
action could tamper the release. Action tag-hijacking keeps recurring
(aquasecurity/trivy-action, 75 tags, Mar 2026 TeamPCP; tj-actions, 2025;
codfish/semantic-release-action, Jun 2026) and SHA-pinned workflows were immune
each time. Pin all six actions to the commit each @major resolves to today
(concrete version in a trailing comment; setup-uv's annotated tag dereferenced
to its commit, not the tag object, so Dependabot tracks it). Also add a
top-level `permissions: contents: read` (the release job keeps its explicit
write) and `persist-credentials: false` on the build checkout.

actionlint passes. Pairs with #860 (Dependabot github-actions keeps the pins
current).

Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
2026-07-23 15:22:28 -04:00
yoni 7e02b8d8da Quit after scan instead of hosting local viewer
Remove the post-scan local viewer hosting step so the run exits directly
instead of blocking with 'Hosting the local viewer. Press Ctrl-C to stop.'
Drop the 'View in web' link (and 'Reopen' variant) from the completion
panel, which now always shows 'View  strix view <run_name>'.
2026-07-22 14:29:11 -07:00
alex s 137a42c3e3 fix(deps): cap cryptography <49 to keep Intel macOS universal2 wheel (#859)
cryptography 49.x ships arm64-only macOS wheels (no universal2), forcing the
Intel macOS (macos-x86_64) release runner to build from sdist under
`uv sync --frozen`. Pin to 48.0.1, which still clears GHSA-537c-gmf6-5ccf
(fixed in 48.0.1) and provides a macosx_10_9_universal2 wheel.
2026-07-22 16:56:15 -04:00
alex s 473b3c4af1 chore(deps): bump cryptography to 49.0.0 and pyasn1 to 0.6.4 (#856)
Resolves GHSA-537c-gmf6-5ccf (vulnerable OpenSSL in cryptography wheels,
fixed in 48.0.1) and CVE-2026-59885 / CVE-2026-59886 (pyasn1 DoS via
OBJECT IDENTIFIER / REAL decoding, fixed in 0.6.4).
2026-07-22 16:33:06 -04:00
alex s d1a73a24f8 feat(cli): update notifications + self-update (strix --update) (#807)
* feat(cli): update notifications + self-update (strix --update)

* fix(update): verify release checksum, clean up staged binary, roll back Windows rename on failure

* feat(update): 3-way pre-scan prompt (update now / not now / skip this version) + package-manager upgrade

* fix(update): never show update prompt/notice in non-interactive runs
2026-07-22 16:29:03 -04:00
Ahmed Allam a2f5e3acb6 chore: release v1.3.1 2026-07-22 11:47:02 -07:00
Ahmed Allam e8c2564595 sandbox: bump install.sh pre-pull tag to 1.1.0 (match runtime default) 2026-07-22 11:40:23 -07:00
Ahmed Allam 78594e1645 sandbox: bump default inner-sandbox image to 1.1.0 2026-07-22 11:40:23 -07:00
59 changed files with 3532 additions and 404 deletions

No files matched your search

+11 -6
View File
@@ -6,6 +6,9 @@ on:
- 'v*'
workflow_dispatch:
permissions:
contents: read
jobs:
build:
strategy:
@@ -24,13 +27,15 @@ jobs:
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
with:
persist-credentials: false
- uses: actions/setup-python@v5
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: '3.12'
- uses: astral-sh/setup-uv@v5
- uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2
- name: Build
shell: bash
@@ -50,7 +55,7 @@ jobs:
tar -C dist/release -czvf "dist/release/strix-${VERSION}-${{ matrix.target }}.tar.gz" "strix-${VERSION}-${{ matrix.target }}"
fi
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: strix-${{ matrix.target }}
path: |
@@ -65,13 +70,13 @@ jobs:
contents: write
steps:
- uses: actions/download-artifact@v4
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
path: release
merge-multiple: true
- name: Create Release
uses: softprops/action-gh-release@v2
uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.2
with:
prerelease: ${{ !startsWith(github.ref, 'refs/tags/') }}
generate_release_notes: true
+14
View File
@@ -267,6 +267,20 @@ export STRIX_REASONING_EFFORT="high" # control thinking effort (default: high,
> [!NOTE]
> Strix automatically saves your configuration to `~/.strix/cli-config.json`, so you don't have to re-enter it on every run.
#### Sign in with a ChatGPT subscription
Instead of a metered API key, you can run Strix on your ChatGPT Plus/Pro subscription:
```bash
strix auth login chatgpt # sign in with your ChatGPT account
export STRIX_LLM="chatgpt/gpt-5.4" # chatgpt/<model> runs on the subscription
strix --target ./app-directory
strix auth status # show the active sign-in
strix auth logout # forget the sign-in
```
**Recommended models for best results:**
- [OpenAI GPT-5.4](https://openai.com/api/) - `openai/gpt-5.4`
+25
View File
@@ -35,6 +35,31 @@ Configure Strix using environment variables or a config file.
Timeout in seconds for memory compression operations (context summarization).
</ParamField>
### Dedicated deduplication model
Finding deduplication is a cheap, structured classification task. By default it
runs on the main model, but you can route it to a smaller/cheaper model without
affecting the agents that do the actual testing.
<ParamField path="STRIX_DEDUPE_MODEL" type="string">
Model used to judge whether a candidate finding duplicates an existing report.
Falls back to `STRIX_LLM` when unset.
</ParamField>
<ParamField path="DEDUPE_LLM_API_KEY" type="string">
Optional provider key for the deduplication model.
</ParamField>
<ParamField path="DEDUPE_LLM_API_BASE" type="string">
Optional custom API base URL for the deduplication model. Use when the dedupe
model runs on a different endpoint than the main model.
</ParamField>
<ParamField path="STRIX_DEDUPE_REASONING_EFFORT" type="string">
Reasoning effort for the deduplication model. Defaults to the model's own
baseline when unset.
</ParamField>
## Optional Features
<ParamField path="PERPLEXITY_API_KEY" type="string">
+2 -1
View File
@@ -116,5 +116,6 @@ strix --mount ./huge-monorepo
| Code | Meaning |
|------|---------|
| 0 | Scan completed, no vulnerabilities found |
| 0 | Scan completed successfully (interactive mode always exits `0`; in headless mode, `0` means no vulnerabilities were found) |
| 1 | A fatal error occurred before or during the scan (e.g. missing environment variables, Docker unavailable, invalid config file, diff-scope resolution failure, or an unhandled error) |
| 2 | Vulnerabilities found (headless mode only) |
+17 -3
View File
@@ -1,6 +1,6 @@
[project]
name = "strix-agent"
version = "1.3.0"
version = "1.3.1"
description = "Open-source AI Hackers for your apps"
readme = "README.md"
license = "Apache-2.0"
@@ -46,7 +46,9 @@ dependencies = [
"caido-sdk-client>=0.2.0",
"reportlab>=4.0",
"pypdf>=5.0",
"cryptography>=42",
# Cap <49: 49.x drops the universal2 macOS wheel (arm64-only), which breaks
# the Intel macOS (macos-x86_64) release build's `uv sync --frozen`.
"cryptography>=48.0.1,<49",
]
[project.optional-dependencies]
@@ -120,6 +122,7 @@ module = [
"pydantic_settings.*",
"reportlab.*",
"pypdf.*",
"pygments.*",
]
ignore_missing_imports = true
disable_error_code = ["import-untyped"]
@@ -213,6 +216,10 @@ ignore = [
# Test doubles use fixture tokens/passwords and match a callee signature whose
# args they intentionally ignore.
"tests/test_viewer_auth.py" = ["S105", "S106", "ARG001"]
"tests/test_codex_auth.py" = ["S105", "S106", "SLF001"]
# Stdlib HTTP handler overrides (do_GET/do_POST).
"strix/interface/auth_cli.py" = ["N802"]
"tests/test_codex_streaming.py" = ["N802"]
"tests/test_report_pdf.py" = ["S105", "S106"]
# Stdlib HTTP handler overrides (do_GET/do_POST) and lazy imports that avoid a
# circular dependency with strix.telemetry / strix.viewer.report_pdf.
@@ -251,9 +258,16 @@ ignore = [
"strix/core/runner.py" = ["TC003", "PLR0912", "PLR0915", "PLC0415"]
# ReportState carries scan artifact/report fields and
# a runtime ``Callable`` annotation on ``vulnerability_found_callback``.
"strix/report/state.py" = ["TC003", "PLR0912", "PLR0915", "E501", "PERF401"]
"strix/report/state.py" = ["TC003", "PLR0912", "PLR0915", "E501", "PERF401", "PLC0415"]
"strix/report/usage.py" = ["PLC0415"]
# Lazy import of strix.config.models avoids a circular dependency between the
# report pipeline and the config layer.
"strix/report/dedupe.py" = ["PLC0415"]
"strix/telemetry/logging.py" = ["PLC0415"]
"strix/config/models.py" = ["PLC0415"]
# Heavy inference deps (httpx, openai) imported lazily so auth-status checks
# don't pull them in.
"strix/config/codex.py" = ["PLC0415"]
# Interface utility branches per scope-mode / target-type combination;
# splitting would obscure the decision tree without simplifying it.
"strix/interface/utils.py" = ["PLR0912", "BLE001", "PLC0415"]
+1 -1
View File
@@ -4,7 +4,7 @@ set -euo pipefail
APP=strix
REPO="usestrix/strix"
STRIX_IMAGE="ghcr.io/usestrix/strix-sandbox:1.0.0"
STRIX_IMAGE="ghcr.io/usestrix/strix-sandbox:1.1.0"
MUTED='\033[0;2m'
RED='\033[0;31m'
+83 -13
View File
@@ -16,6 +16,7 @@ from agents.tool import CustomTool, FunctionTool, Tool
from pydantic import ValidationError
from strix.agents.prompt import render_system_prompt
from strix.config import load_settings
from strix.tools.agents_graph.tools import (
agent_finish,
create_agent,
@@ -33,6 +34,7 @@ from strix.tools.notes.tools import (
list_notes,
update_note,
)
from strix.tools.output_store import bound_text
from strix.tools.proxy.tools import (
list_requests,
list_sitemap,
@@ -103,8 +105,36 @@ def _extract_custom_input(tool: CustomTool, raw_input: str | dict[str, Any]) ->
return value if isinstance(value, str) else ""
def _tool_output_limits() -> tuple[int, int]:
context = load_settings().context
return context.tool_output_max_lines, context.tool_output_max_bytes
def _bound_result(result: Any) -> Any:
if not isinstance(result, str):
return result
max_lines, max_bytes = _tool_output_limits()
return bound_text(result, max_lines=max_lines, max_bytes=max_bytes)
def _format_tool_error(exc: Exception) -> str:
return str(exc) or exc.__class__.__name__
message = str(exc) or exc.__class__.__name__
max_lines, max_bytes = _tool_output_limits()
return bound_text(message, max_lines=max_lines, max_bytes=max_bytes)
def _with_bounded_result(tool: FunctionTool) -> FunctionTool:
"""Cap a tool's result size before it enters history (idempotent)."""
if getattr(tool, "_strix_bounded", False):
return tool
invoke_tool = tool.on_invoke_tool
async def invoke(ctx: Any, raw_input: str) -> Any:
return _bound_result(await invoke_tool(ctx, raw_input))
tool.on_invoke_tool = invoke
tool._strix_bounded = True # type: ignore[attr-defined]
return tool
def _function_tool_with_error_result(tool: FunctionTool) -> FunctionTool:
@@ -112,7 +142,7 @@ def _function_tool_with_error_result(tool: FunctionTool) -> FunctionTool:
async def invoke(ctx: Any, raw_input: str) -> Any:
try:
return await invoke_tool(ctx, raw_input)
return _bound_result(await invoke_tool(ctx, raw_input))
except Exception as exc: # noqa: BLE001 - tool errors should be model-visible results.
logger.debug("Tool %s failed; returning error as result", tool.name, exc_info=True)
return _format_tool_error(exc)
@@ -127,7 +157,7 @@ def _custom_tool_as_function_tool(tool: CustomTool) -> FunctionTool:
if not custom_input:
return f"`{_custom_tool_input_field(tool)}` must be a non-empty string."
try:
return await tool.on_invoke_tool(ctx, custom_input)
return _bound_result(await tool.on_invoke_tool(ctx, custom_input))
except Exception as exc: # noqa: BLE001 - matches SDK CustomTool error-as-result behavior.
logger.debug("Tool %s failed; returning error as result", tool.name, exc_info=True)
return _format_tool_error(exc)
@@ -159,12 +189,35 @@ def _custom_tool_as_function_tool(tool: CustomTool) -> FunctionTool:
)
def _configure_chat_completions_filesystem_tools(toolset: Any) -> None:
def _bound_custom_tool(tool: CustomTool) -> CustomTool:
"""Bound a native ``CustomTool`` result in place (Responses path)."""
invoke_tool = tool.on_invoke_tool
async def invoke(ctx: Any, raw_input: str) -> Any:
return _bound_result(await invoke_tool(ctx, raw_input))
tool.on_invoke_tool = invoke
return tool
def _configure_filesystem_tools(toolset: Any, *, chat_completions: bool) -> None:
for name, tool in vars(toolset).items():
if isinstance(tool, CustomTool):
setattr(toolset, name, _custom_tool_as_function_tool(tool))
if chat_completions:
if isinstance(tool, CustomTool):
setattr(toolset, name, _custom_tool_as_function_tool(tool))
elif isinstance(tool, FunctionTool):
setattr(toolset, name, _function_tool_with_error_result(tool))
elif isinstance(tool, CustomTool):
setattr(toolset, name, _bound_custom_tool(tool))
elif isinstance(tool, FunctionTool):
setattr(toolset, name, _function_tool_with_error_result(tool))
setattr(toolset, name, _with_bounded_result(tool))
def _make_filesystem_configurator(*, chat_completions: bool) -> Any:
def configure(toolset: Any) -> None:
_configure_filesystem_tools(toolset, chat_completions=chat_completions)
return configure
_CHARS_ESCAPE_RE = re.compile(r"\\(?:u[0-9a-fA-F]{4}|x[0-9a-fA-F]{2}|[0abtnvfr\\])")
@@ -205,6 +258,16 @@ def _format_validation_error(tool_name: str, exc: ValidationError) -> str:
return f"{tool_name}: invalid arguments — " + "; ".join(parts)
def _apply_shell_output_cap(parsed: dict[str, Any]) -> None:
"""Clamp the SDK shell tools' ``max_output_tokens`` to the configured
ceiling; a smaller explicit value is respected."""
ceiling = load_settings().context.tool_output_max_tokens
requested = parsed.get("max_output_tokens")
parsed["max_output_tokens"] = (
ceiling if not isinstance(requested, int) or requested > ceiling else requested
)
def _wrap_exec_command(tool: FunctionTool) -> FunctionTool:
invoke_tool = tool.on_invoke_tool
@@ -213,8 +276,10 @@ def _wrap_exec_command(tool: FunctionTool) -> FunctionTool:
parsed = json.loads(raw_input)
except (json.JSONDecodeError, TypeError):
parsed = None
if isinstance(parsed, dict) and "shell" not in parsed:
parsed["shell"] = "bash"
if isinstance(parsed, dict):
if "shell" not in parsed:
parsed["shell"] = "bash"
_apply_shell_output_cap(parsed)
raw_input = json.dumps(parsed)
try:
return await invoke_tool(ctx, raw_input)
@@ -240,8 +305,10 @@ def _wrap_write_stdin(tool: FunctionTool) -> FunctionTool:
parsed = json.loads(raw_input)
except json.JSONDecodeError:
parsed = None
if isinstance(parsed, dict) and isinstance(parsed.get("chars"), str):
parsed["chars"] = _decode_chars_escape(parsed["chars"])
if isinstance(parsed, dict):
if isinstance(parsed.get("chars"), str):
parsed["chars"] = _decode_chars_escape(parsed["chars"])
_apply_shell_output_cap(parsed)
raw_input = json.dumps(parsed)
try:
return await invoke_tool(ctx, raw_input)
@@ -440,6 +507,9 @@ def build_strix_agent(
else:
tools = [*_BASE_TOOLS, *agent_tools, agent_finish]
_ensure_unique_tool_names(tools)
tools = [
_with_bounded_result(tool) if isinstance(tool, FunctionTool) else tool for tool in tools
]
logger.info(
"Built %s agent '%s' (skills=%d, tools=%d, scan_mode=%s, whitebox=%s)",
@@ -459,8 +529,8 @@ def build_strix_agent(
model=None,
capabilities=[
Filesystem(
configure_tools=(
_configure_chat_completions_filesystem_tools if chat_completions_tools else None
configure_tools=_make_filesystem_configurator(
chat_completions=chat_completions_tools,
),
),
Shell(
+4
View File
@@ -17,6 +17,8 @@ from strix.config.loader import (
persist_current,
)
from strix.config.settings import (
ContextSettings,
DedupeSettings,
IntegrationSettings,
LlmSettings,
RuntimeSettings,
@@ -26,6 +28,8 @@ from strix.config.settings import (
__all__ = [
"ContextSettings",
"DedupeSettings",
"IntegrationSettings",
"LlmSettings",
"RuntimeSettings",
+411
View File
@@ -0,0 +1,411 @@
"""ChatGPT (Codex) subscription auth: OAuth login, token refresh, and the OpenAI
client that routes inference through the ChatGPT backend.
Mirrors OpenAI's Codex CLI: OAuth 2.0 + PKCE against ``auth.openai.com``, with the
access token sent as a ``Bearer`` token to ``chatgpt.com/backend-api/codex``. Using
a ChatGPT subscription outside OpenAI's own products is not officially supported by
OpenAI; the user chooses this path knowingly. The OAuth constants are OpenAI's own
Codex CLI values (the backend only accepts that client).
"""
from __future__ import annotations
import base64
import contextlib
import hashlib
import json
import logging
import secrets
import threading
import time
import urllib.error
import urllib.parse
import urllib.request
from pathlib import Path
from typing import TYPE_CHECKING, Any
if TYPE_CHECKING:
from collections.abc import Iterator
from openai import AsyncOpenAI
logger = logging.getLogger(__name__)
PROVIDER = "codex"
CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann"
AUTHORIZE_URL = "https://auth.openai.com/oauth/authorize"
TOKEN_URL = "https://auth.openai.com/oauth/token" # noqa: S105 # nosec B105 - URL, not a secret
CALLBACK_HOST = "localhost"
CALLBACK_PORT = 1455
CALLBACK_PATH = "/auth/callback"
REDIRECT_URI = f"http://{CALLBACK_HOST}:{CALLBACK_PORT}{CALLBACK_PATH}"
SCOPE = "openid profile email offline_access"
CODEX_BASE_URL = "https://chatgpt.com/backend-api/codex"
ORIGINATOR = "codex_cli_rs"
_ACCOUNT_CLAIM = "https://api.openai.com/auth"
_TOKEN_TIMEOUT = 30
_EXPIRY_SKEW_S = 300
_refresh_lock = threading.Lock()
# Kept separate from cli-config.json so OAuth tokens never land in the env-var config.
AUTH_PATH = Path.home() / ".strix" / "subscription-auth.json"
def _read_store() -> dict[str, Any]:
try:
data = json.loads(AUTH_PATH.read_text(encoding="utf-8"))
except (OSError, json.JSONDecodeError):
return {}
return data if isinstance(data, dict) else {}
def _write_store(data: dict[str, Any]) -> None:
AUTH_PATH.parent.mkdir(parents=True, exist_ok=True)
tmp = AUTH_PATH.with_suffix(".json.tmp")
tmp.write_text(json.dumps(data, indent=2), encoding="utf-8")
with contextlib.suppress(OSError):
tmp.chmod(0o600)
tmp.replace(AUTH_PATH)
with contextlib.suppress(OSError):
AUTH_PATH.chmod(0o600)
def read_record() -> dict[str, Any] | None:
record = _read_store().get(PROVIDER)
if not isinstance(record, dict) or record.get("type") != "oauth":
return None
if not (record.get("access") and record.get("refresh") and record.get("account_id")):
return None
return record
def is_authenticated() -> bool:
return read_record() is not None
def save_record(record: dict[str, Any]) -> None:
data = _read_store()
data[PROVIDER] = record
_write_store(data)
def logout() -> None:
data = _read_store()
if PROVIDER not in data:
return
del data[PROVIDER]
if data:
_write_store(data)
return
with contextlib.suppress(OSError):
AUTH_PATH.unlink()
@contextlib.contextmanager
def _refresh_guard() -> Iterator[None]:
"""Serialize token refresh within (lock) and across (flock) Strix processes,
so concurrent runs can't both spend the single-use refresh token."""
with _refresh_lock:
try:
import fcntl
lock_path = AUTH_PATH.with_suffix(".lock")
lock_path.parent.mkdir(parents=True, exist_ok=True)
handle = lock_path.open("w")
except (ImportError, OSError):
yield
return
try:
with contextlib.suppress(OSError):
fcntl.flock(handle.fileno(), fcntl.LOCK_EX)
yield
finally:
with contextlib.suppress(OSError):
fcntl.flock(handle.fileno(), fcntl.LOCK_UN)
handle.close()
class CodexAuthError(Exception):
def __init__(self, code: str, message: str | None = None) -> None:
self.code = code
super().__init__(message or code)
class CodexContentGuardrailError(Exception):
"""The ChatGPT backend refused a request via its content guardrail.
Terminal — retrying identical content never clears the block."""
def __init__(self, model: str, original: BaseException | None = None) -> None:
self.model = model
self.original = original
super().__init__(
f"'{model}' was blocked by ChatGPT's content guardrails "
f"(flagged as a possible cybersecurity risk). "
f"Set STRIX_LLM to a model that isn't blocked and re-run."
)
_GUARDRAIL_MARKERS = (
"flagged for possible cybersecurity risk",
"trusted access for cyber",
)
def is_content_guardrail_error(exc: BaseException) -> bool:
if isinstance(exc, CodexContentGuardrailError):
return True
text = str(exc).lower()
return any(marker in text for marker in _GUARDRAIL_MARKERS)
def _b64url(raw: bytes) -> str:
return base64.urlsafe_b64encode(raw).rstrip(b"=").decode("ascii")
def generate_pkce() -> tuple[str, str]:
verifier = _b64url(secrets.token_bytes(64))
challenge = _b64url(hashlib.sha256(verifier.encode("ascii")).digest())
return verifier, challenge
def create_state() -> str:
return secrets.token_hex(16)
def build_authorize_url(challenge: str, state: str) -> str:
params = {
"response_type": "code",
"client_id": CLIENT_ID,
"redirect_uri": REDIRECT_URI,
"scope": SCOPE,
"code_challenge": challenge,
"code_challenge_method": "S256",
"state": state,
"id_token_add_organizations": "true",
"codex_cli_simplified_flow": "true",
"originator": ORIGINATOR,
}
return f"{AUTHORIZE_URL}?{urllib.parse.urlencode(params)}"
def parse_redirect_input(value: str) -> tuple[str | None, str | None]:
"""Extract ``(code, state)`` from a pasted redirect URL, ``code#state``,
query string, or bare code."""
value = (value or "").strip()
if not value:
return None, None
with contextlib.suppress(ValueError):
parsed = urllib.parse.urlparse(value)
if parsed.scheme and parsed.query:
query = urllib.parse.parse_qs(parsed.query)
return _first(query, "code"), _first(query, "state")
if "#" in value:
code, _, state = value.partition("#")
return code or None, state or None
if "code=" in value:
query = urllib.parse.parse_qs(value)
return _first(query, "code"), _first(query, "state")
return value, None
def _first(query: dict[str, list[str]], key: str) -> str | None:
values = query.get(key)
return values[0] if values else None
def _post_form(payload: dict[str, str]) -> dict[str, Any]:
body = urllib.parse.urlencode(payload).encode("ascii")
request = urllib.request.Request( # noqa: S310 - fixed https OAuth endpoint
TOKEN_URL,
data=body,
headers={
"Content-Type": "application/x-www-form-urlencoded",
"Accept": "application/json",
},
method="POST",
)
try:
with urllib.request.urlopen( # noqa: S310 # nosec B310 - fixed https endpoint
request, timeout=_TOKEN_TIMEOUT
) as response:
data = json.loads(response.read() or b"{}")
except urllib.error.HTTPError as exc:
detail = exc.read().decode("utf-8", "replace")[:300]
raise CodexAuthError("token_http_error", f"HTTP {exc.code}: {detail}") from exc
except (urllib.error.URLError, TimeoutError, OSError) as exc:
raise CodexAuthError("unavailable", str(exc)) from exc
if not isinstance(data, dict):
raise CodexAuthError("bad_response", "token endpoint returned non-object")
return data
def _record_from_token_response(
data: dict[str, Any], refresh_fallback: str | None = None
) -> dict[str, Any]:
access = data.get("access_token")
# A refresh response may omit refresh_token when it isn't rotated; keep the old one.
refresh = data.get("refresh_token") or refresh_fallback
expires_in = data.get("expires_in")
if not isinstance(access, str) or not access:
raise CodexAuthError("bad_response", "token response missing access_token")
if not isinstance(refresh, str) or not refresh:
raise CodexAuthError("bad_response", "token response missing refresh_token")
account_id = _account_id_from_jwt(access) or _account_id_from_jwt(
data.get("id_token") if isinstance(data.get("id_token"), str) else ""
)
if not account_id:
raise CodexAuthError("no_account_id", "could not read chatgpt_account_id from token")
ttl = expires_in if isinstance(expires_in, int | float) else 3600
return {
"type": "oauth",
"provider": PROVIDER,
"access": access,
"refresh": refresh,
"account_id": account_id,
"expires_at": time.time() + ttl,
}
def exchange_code(code: str, verifier: str) -> dict[str, Any]:
data = _post_form(
{
"grant_type": "authorization_code",
"client_id": CLIENT_ID,
"code": code,
"code_verifier": verifier,
"redirect_uri": REDIRECT_URI,
}
)
return _record_from_token_response(data)
def refresh_tokens(refresh_token: str) -> dict[str, Any]:
data = _post_form(
{
"grant_type": "refresh_token",
"client_id": CLIENT_ID,
"refresh_token": refresh_token,
}
)
return _record_from_token_response(data, refresh_fallback=refresh_token)
def _account_id_from_jwt(token: str | None) -> str | None:
"""Read the account id claim without verifying the JWT (the server enforces
authenticity on use); it feeds the ``chatgpt-account-id`` header."""
if not token or token.count(".") != 2:
return None
payload_b64 = token.split(".")[1]
padding = "=" * (-len(payload_b64) % 4)
try:
payload = json.loads(base64.urlsafe_b64decode(payload_b64 + padding))
except (ValueError, json.JSONDecodeError):
return None
if not isinstance(payload, dict):
return None
auth = payload.get(_ACCOUNT_CLAIM)
if isinstance(auth, dict):
account_id = auth.get("chatgpt_account_id")
if isinstance(account_id, str) and account_id:
return account_id
organizations = payload.get("organizations")
if isinstance(organizations, list) and organizations and isinstance(organizations[0], dict):
org_id = organizations[0].get("id")
if isinstance(org_id, str) and org_id:
return org_id
return None
def _near_expiry(record: dict[str, Any]) -> bool:
expires_at = record.get("expires_at")
if not isinstance(expires_at, int | float):
return True
return expires_at - _EXPIRY_SKEW_S <= time.time()
def get_valid_token() -> tuple[str, str]:
"""Return ``(access_token, account_id)``, refreshing under the cross-process
guard if near expiry."""
record = read_record()
if record is None:
raise CodexAuthError("not_authenticated", "not signed in; run: strix auth login")
if not _near_expiry(record):
return record["access"], record["account_id"]
with _refresh_guard():
record = read_record()
if record is None:
raise CodexAuthError("not_authenticated", "not signed in; run: strix auth login")
if not _near_expiry(record):
return record["access"], record["account_id"]
try:
refreshed = refresh_tokens(record["refresh"])
except CodexAuthError:
# A peer process may have already spent this single-use refresh token.
latest = read_record()
if latest and latest["refresh"] != record["refresh"] and not _near_expiry(latest):
return latest["access"], latest["account_id"]
raise
save_record(refreshed)
return refreshed["access"], refreshed["account_id"]
def build_openai_client() -> AsyncOpenAI:
"""An ``AsyncOpenAI`` for the ChatGPT backend. A per-request hook re-stamps a
fresh bearer token so long scans survive token expiry."""
import asyncio
import httpx
from openai import AsyncOpenAI
get_valid_token() # fail fast at configure time if the sign-in is dead
async def _auth_hook(request: httpx.Request) -> None:
access, account_id = await asyncio.to_thread(get_valid_token)
request.headers["Authorization"] = f"Bearer {access}"
request.headers["chatgpt-account-id"] = account_id
http_client = httpx.AsyncClient(
timeout=httpx.Timeout(600.0, connect=30.0),
event_hooks={"request": [_auth_hook]},
)
return AsyncOpenAI(
api_key="strix-codex-oauth", # placeholder; the hook overwrites Authorization
base_url=CODEX_BASE_URL,
http_client=http_client,
default_headers={
"OpenAI-Beta": "responses=experimental",
"originator": ORIGINATOR,
},
)
_subscription_client: AsyncOpenAI | None = None
def get_subscription_client() -> AsyncOpenAI:
global _subscription_client # noqa: PLW0603
if _subscription_client is None:
_subscription_client = build_openai_client()
return _subscription_client
SUBSCRIPTION_PREFIX = "chatgpt/"
def subscription_model(model_name: str | None) -> str | None:
"""The model slug behind a ``chatgpt/<model>`` STRIX_LLM, or None."""
name = (model_name or "").strip()
if not name.lower().startswith(SUBSCRIPTION_PREFIX):
return None
return name[len(SUBSCRIPTION_PREFIX) :] or None
def auth_mode(model_name: str | None) -> str:
return "subscription" if subscription_model(model_name) else "api_key"
+128 -12
View File
@@ -2,23 +2,38 @@
from __future__ import annotations
import contextlib
import inspect
import os
from typing import TYPE_CHECKING
from typing import TYPE_CHECKING, Any
from agents import set_default_openai_api, set_default_openai_key, set_tracing_disabled
from agents import (
set_default_openai_api,
set_default_openai_key,
set_tracing_disabled,
)
from agents.model_settings import ModelSettings
from agents.models.multi_provider import MultiProvider
from agents.models.openai_responses import OpenAIResponsesModel
from agents.retry import (
ModelRetryBackoffSettings,
ModelRetrySettings,
RetryPolicyContext,
retry_policies,
)
from openai.types.shared import Reasoning
from strix.config import codex
from strix.config.loader import load_settings
if TYPE_CHECKING:
from agents.models.interface import ModelProvider
from collections.abc import AsyncIterator
from strix.config.settings import Settings
from agents.models.interface import Model, ModelProvider
from openai import AsyncOpenAI
from strix.config.settings import ReasoningEffort, Settings
def request_timeout_extra_args(timeout_s: float | None) -> dict[str, float] | None:
@@ -33,9 +48,93 @@ def _retry_statusless_provider_errors(context: RetryPolicyContext) -> bool:
normalized = context.normalized
if normalized.is_abort:
return False
if codex.is_content_guardrail_error(context.error):
return False
return normalized.status_code is None
class _CodexResponsesModel(OpenAIResponsesModel):
"""Responses model for the ChatGPT subscription backend (always streamed, stateless)."""
def __init__(
self,
model: str,
openai_client: AsyncOpenAI,
*,
reasoning_effort: ReasoningEffort | None = None,
) -> None:
super().__init__(model, openai_client)
self._reasoning_effort = reasoning_effort
def _codex_settings(self, model_settings: ModelSettings) -> ModelSettings:
overrides = ModelSettings(store=False, response_include=["reasoning.encrypted_content"])
effort = self._reasoning_effort
if effort and effort != "none":
# Clamp to efforts the backend accepts.
if effort == "minimal":
effort = "low"
elif effort == "xhigh":
effort = "high"
overrides = overrides.resolve(ModelSettings(reasoning=Reasoning(effort=effort)))
return model_settings.resolve(overrides)
async def _fetch_response(self, *args: Any, stream: bool = False, **kwargs: Any) -> Any:
if len(args) >= 3: # model_settings is positional arg 2
args = (*args[:2], self._codex_settings(args[2]), *args[3:])
try:
events = await super()._fetch_response(*args, stream=True, **kwargs) # type: ignore[call-overload]
except Exception as exc:
guardrail = self._as_guardrail(exc)
if guardrail is not None:
raise guardrail from exc
raise
guarded = self._guarded(events)
if stream:
return guarded
final_response = None
async for event in guarded:
if getattr(event, "type", None) == "response.completed":
final_response = event.response
if final_response is None:
msg = "ChatGPT backend stream ended without a completed response"
raise RuntimeError(msg)
return final_response
def _as_guardrail(self, exc: BaseException) -> codex.CodexContentGuardrailError | None:
if isinstance(exc, codex.CodexContentGuardrailError):
return exc
if codex.is_content_guardrail_error(exc):
return codex.CodexContentGuardrailError(self.model, exc)
return None
async def _guarded(self, events: Any) -> AsyncIterator[Any]:
"""Convert mid-stream guardrail rejections and close the stream on exit."""
try:
async for event in events:
yield event
except Exception as exc:
guardrail = self._as_guardrail(exc)
if guardrail is not None:
raise guardrail from exc
raise
finally:
await self._aclose(events)
@staticmethod
async def _aclose(events: Any) -> None:
aclose = getattr(events, "aclose", None)
if callable(aclose):
with contextlib.suppress(Exception):
await aclose()
return
close = getattr(events, "close", None)
if callable(close):
with contextlib.suppress(Exception):
result = close()
if inspect.isawaitable(result):
await result
class StrixProvider(MultiProvider):
"""Route any non-OpenAI prefix through LiteLLM with the prefix preserved,
so users type ``deepseek/deepseek-chat`` rather than
@@ -59,6 +158,16 @@ class StrixProvider(MultiProvider):
return self._get_fallback_provider("litellm"), f"ollama_chat/{stripped_model_name}"
return self._get_fallback_provider("litellm"), original_model_name
def get_model(self, model_name: str | None) -> Model:
slug = codex.subscription_model(model_name)
if slug:
return _CodexResponsesModel(
slug,
codex.get_subscription_client(),
reasoning_effort=load_settings().llm.reasoning_effort,
)
return super().get_model(model_name)
DEFAULT_MODEL_RETRY = ModelRetrySettings(
max_retries=5,
@@ -77,39 +186,42 @@ DEFAULT_MODEL_RETRY = ModelRetrySettings(
)
RECOMMENDED_MODEL_NAMES = (
"openai/gpt-5.6",
"openai/gpt-5.6-sol",
"openai/gpt-5.6-terra",
"openai/gpt-5.5",
"openai/gpt-5.6-luna",
"openai/gpt-5.6",
"openai/gpt-5.5-pro",
"openai/gpt-5.5",
"openai/gpt-5.4",
"openai/gpt-5.3-codex",
"anthropic/claude-fable-5",
"anthropic/claude-opus-5",
"anthropic/claude-opus-4-8",
"anthropic/claude-opus-4-7",
"anthropic/claude-sonnet-5",
"anthropic/claude-sonnet-4-6",
"vertex_ai/gemini-3.1-pro-preview",
"gemini/gemini-3.1-pro-preview",
"gemini/gemini-3.6-flash",
"deepseek/deepseek-v4-pro",
"deepseek/deepseek-v4-flash",
"dashscope/qwen3.8-max",
"dashscope/qwen3.7-max-2026-06-08",
"moonshot/kimi-k3",
"moonshot/kimi-k2.7-code",
"moonshot/kimi-k2.6",
)
_RECOMMENDED_MODEL_NAME_SET = frozenset(name.lower() for name in RECOMMENDED_MODEL_NAMES)
FRONTIER_MODEL_FAMILIES = (
(("azure", "azure_ai", "bedrock_mantle", "openai"), ("gpt-5",)),
(("azure", "azure_ai", "bedrock_mantle", "chatgpt", "openai"), ("gpt-5",)),
(
("anthropic", "azure_ai", "bedrock", "claude", "databricks", "snowflake", "vertex_ai"),
("claude-fable-5", "claude-opus-4", "claude-sonnet-5", "claude-sonnet-4"),
("claude-fable-5", "claude-opus-5", "claude-opus-4", "claude-sonnet-5", "claude-sonnet-4"),
),
(("google", "gemini", "vertex_ai"), ("gemini-3",)),
(("deepseek",), ("deepseek-v4", "deepseek-r1", "deepseek-reasoner")),
(("alibaba", "dashscope", "qwen"), ("qwen3.7", "qwen3.5", "qwen3-max")),
(("moonshot", "moonshotai", "kimi"), ("kimi-k2.7", "kimi-k2.6", "kimi-k2.5")),
(("alibaba", "dashscope", "qwen"), ("qwen3.8", "qwen3.7", "qwen3-max")),
(("moonshot", "moonshotai", "kimi"), ("kimi-k3", "kimi-k2.7", "kimi-k2.6")),
)
@@ -117,6 +229,8 @@ def configure_sdk_model_defaults(settings: Settings) -> None:
"""Apply Strix config to SDK-native defaults."""
llm = settings.llm
set_tracing_disabled(True)
if codex.subscription_model(llm.model):
return
_configure_litellm_compatibility()
_configure_openrouter_attribution(llm.model)
if llm.api_key:
@@ -211,6 +325,8 @@ def _configure_litellm_default(name: str, value: str) -> None:
def uses_chat_completions_tool_schema(model_name: str, settings: Settings) -> bool:
"""Return whether the resolved SDK route can only receive JSON function tools."""
if codex.subscription_model(model_name):
return False
model = model_name.strip().lower()
if "/" in model and not model.startswith("openai/"):
return True
+35 -1
View File
@@ -43,11 +43,43 @@ class LlmSettings(BaseSettings):
timeout: int = Field(default=300, alias="LLM_TIMEOUT")
class DedupeSettings(BaseSettings):
model_config = _BASE_CONFIG
model: str | None = Field(default=None, alias="STRIX_DEDUPE_MODEL")
reasoning_effort: ReasoningEffort | None = Field(
default=None,
alias="STRIX_DEDUPE_REASONING_EFFORT",
)
api_key: str | None = Field(default=None, alias="DEDUPE_LLM_API_KEY")
api_base: str | None = Field(default=None, alias="DEDUPE_LLM_API_BASE")
class ContextSettings(BaseSettings):
"""Context-window management: per-tool-output caps and history compaction."""
model_config = _BASE_CONFIG
auto_compact: bool = Field(default=True, alias="STRIX_CONTEXT_AUTO_COMPACT")
compact_buffer_tokens: int = Field(default=20_000, gt=0, alias="STRIX_CONTEXT_BUFFER_TOKENS")
keep_tokens: int = Field(default=8_000, gt=0, alias="STRIX_CONTEXT_KEEP_TOKENS")
fallback_context_tokens: int = Field(
default=200_000, gt=0, alias="STRIX_CONTEXT_FALLBACK_TOKENS"
)
summary_max_tokens: int = Field(default=4_096, gt=0, alias="STRIX_CONTEXT_SUMMARY_TOKENS")
tool_output_max_tokens: int = Field(default=8_000, gt=0, alias="STRIX_TOOL_OUTPUT_MAX_TOKENS")
tool_output_max_lines: int = Field(default=2_000, gt=0, alias="STRIX_TOOL_OUTPUT_MAX_LINES")
# Floor above the truncation-notice size so a preview always fits.
tool_output_max_bytes: int = Field(
default=50 * 1024, ge=1024, alias="STRIX_TOOL_OUTPUT_MAX_BYTES"
)
class RuntimeSettings(BaseSettings):
model_config = _BASE_CONFIG
image: str = Field(
default="ghcr.io/usestrix/strix-sandbox:1.0.0",
default="ghcr.io/usestrix/strix-sandbox:1.1.0",
alias="STRIX_IMAGE",
)
backend: str = Field(default="docker", alias="STRIX_RUNTIME_BACKEND")
@@ -85,7 +117,9 @@ class Settings(BaseSettings):
model_config = _BASE_CONFIG
llm: LlmSettings = Field(default_factory=LlmSettings)
dedupe: DedupeSettings = Field(default_factory=DedupeSettings)
runtime: RuntimeSettings = Field(default_factory=RuntimeSettings)
context: ContextSettings = Field(default_factory=ContextSettings)
telemetry: TelemetrySettings = Field(default_factory=TelemetrySettings)
integrations: IntegrationSettings = Field(default_factory=IntegrationSettings)
viewer: ViewerSettings = Field(default_factory=ViewerSettings)
+18 -3
View File
@@ -41,6 +41,7 @@ class AgentCoordinator:
self.names: dict[str, str] = {}
self.metadata: dict[str, dict[str, Any]] = {}
self.pending_counts: dict[str, int] = {}
self.errors: dict[str, str] = {}
self.runtimes: dict[str, AgentRuntime] = {}
self._lock = asyncio.Lock()
self._snapshot_path: Path | None = None
@@ -107,16 +108,23 @@ class AgentCoordinator:
async with self._lock:
if agent_id in self.statuses:
self.statuses[agent_id] = "running"
self.errors.pop(agent_id, None)
await self._maybe_snapshot()
async def park_waiting(self, agent_id: str) -> None:
await self.set_status(agent_id, "waiting")
async def set_status(self, agent_id: str, status: Status | str) -> None:
async def set_status(
self, agent_id: str, status: Status | str, *, error: str | None = None
) -> None:
async with self._lock:
if agent_id not in self.statuses:
return
self.statuses[agent_id] = status # type: ignore[assignment]
if error is not None:
self.errors[agent_id] = error
elif status == "running":
self.errors.pop(agent_id, None)
runtime = self.runtimes.setdefault(agent_id, AgentRuntime())
runtime.wake.set()
logger.info("agent.status %s=%s", agent_id, status)
@@ -246,9 +254,14 @@ class AgentCoordinator:
async def graph_snapshot(
self,
) -> tuple[dict[str, str | None], dict[str, Status], dict[str, str]]:
) -> tuple[dict[str, str | None], dict[str, Status], dict[str, str], dict[str, str]]:
async with self._lock:
return dict(self.parent_of), dict(self.statuses), dict(self.names)
return (
dict(self.parent_of),
dict(self.statuses),
dict(self.names),
dict(self.errors),
)
def _message_to_session_item(self, message: dict[str, Any]) -> TResponseInputItem:
sender = str(message.get("from", "unknown"))
@@ -286,6 +299,7 @@ class AgentCoordinator:
"names": dict(self.names),
"metadata": {aid: dict(md) for aid, md in self.metadata.items()},
"pending_counts": dict(self.pending_counts),
"errors": dict(self.errors),
}
async def restore(self, snap: dict[str, Any]) -> None:
@@ -295,6 +309,7 @@ class AgentCoordinator:
self.names = dict(snap.get("names", {}))
self.metadata = {aid: dict(md) for aid, md in snap.get("metadata", {}).items()}
self.pending_counts = dict(snap.get("pending_counts", {}))
self.errors = dict(snap.get("errors", {}))
for aid in self.statuses:
self.runtimes.setdefault(aid, AgentRuntime())
+1 -3
View File
@@ -437,10 +437,8 @@ async def _run_cycle( # noqa: PLR0912, PLR0915
else:
status = "crashed"
logger.exception("agent run failed for %s; parking as %s", agent_id, status)
await coordinator.set_status(agent_id, status)
await coordinator.set_status(agent_id, status, error=str(exc) or type(exc).__name__)
await _notify_parent_on_crash(coordinator, agent_id, status)
if context.get("parent_id") is None and status in {"failed", "crashed"}:
raise
return None
else:
await _settle_run_result(coordinator, agent_id, interactive)
+2 -2
View File
@@ -238,7 +238,7 @@ async def run_strix_scan(
)
root_agent = build_strix_agent(
name="strix",
name="Strix",
skills=skills,
is_root=True,
scan_mode=scan_mode,
@@ -252,7 +252,7 @@ async def run_strix_scan(
if not is_resume:
await coordinator.register(
root_id,
"strix",
"Strix",
parent_id=None,
task=root_task,
skills=skills,
+419
View File
@@ -0,0 +1,419 @@
"""`strix auth` — ChatGPT subscription sign-in (login / status / logout).
Signing in only stores OAuth tokens (``~/.strix/subscription-auth.json``); model
selection stays with ``STRIX_LLM``. A ``chatgpt/<model>`` STRIX_LLM runs on the
subscription.
"""
from __future__ import annotations
import argparse
import base64
import logging
import threading
import webbrowser
from http.server import BaseHTTPRequestHandler, HTTPServer
from pathlib import Path
from typing import TYPE_CHECKING, Any
from urllib.parse import parse_qs, urlparse
from rich.console import Console
from rich.panel import Panel
from rich.text import Text
from strix.config import codex, load_settings
if TYPE_CHECKING:
from collections.abc import Callable
logger = logging.getLogger(__name__)
_CALLBACK_TIMEOUT_S = 300
# CLI-facing name for the login provider. Internally this is the Codex OAuth
# flow (``codex.PROVIDER``), but users know it as ChatGPT, so that's what the
# command and messaging say. ``codex`` is accepted as an alias.
LOGIN_PROVIDER = "chatgpt"
_ACCEPTED_PROVIDERS = frozenset({LOGIN_PROVIDER, codex.PROVIDER})
_USAGE = "Usage:\n strix auth login chatgpt [--manual]\n strix auth status\n strix auth logout"
def run_auth(argv: list[str]) -> int:
"""Entry point for ``strix auth …``. Returns a process exit code."""
console = Console()
# Bare `strix auth` (no subcommand) defaults to login.
subcommand = argv[0] if argv else "login"
rest = argv[1:]
if subcommand in ("-h", "--help", "help"):
console.print(_USAGE)
return 0
handlers: dict[str, Callable[[], int]] = {
"login": lambda: _login(console, rest),
"status": lambda: _status(console),
"logout": lambda: _logout(console),
}
handler = handlers.get(subcommand)
if handler is not None:
return handler()
console.print(f"[red]Unknown auth command:[/] {subcommand}\n")
console.print(_USAGE)
return 2
def _login(console: Console, argv: list[str]) -> int:
parser = argparse.ArgumentParser(prog="strix auth login", add_help=True)
parser.add_argument(
"provider",
nargs="?",
default=LOGIN_PROVIDER,
help="Model provider to sign in with (default: chatgpt).",
)
parser.add_argument(
"--manual",
action="store_true",
help="Skip the local callback server and paste the redirect URL by hand.",
)
try:
args = parser.parse_args(argv)
except SystemExit as exc: # argparse already printed the message
return int(exc.code or 2)
if args.provider.lower() not in _ACCEPTED_PROVIDERS:
console.print(
f"[red]Unsupported provider:[/] {args.provider}. "
f"Only '{LOGIN_PROVIDER}' (ChatGPT subscription) is supported."
)
return 2
verifier, challenge = codex.generate_pkce()
state = codex.create_state()
authorize_url = codex.build_authorize_url(challenge, state)
console.print()
console.print("[bold]Signing in with ChatGPT[/] [dim](provider: chatgpt)[/]")
console.print(
"[dim]This uses your ChatGPT Plus/Pro plan for inference instead of a metered API key.[/]"
)
console.print()
try:
record = _run_oauth_flow(console, authorize_url, verifier, state, manual=args.manual)
except codex.CodexAuthError as exc:
return _fail(console, exc)
except KeyboardInterrupt:
console.print("\n[yellow]Sign-in cancelled.[/]")
return 130
codex.save_record(record)
_print_success(console)
return 0
def _run_oauth_flow(
console: Console,
authorize_url: str,
verifier: str,
state: str,
*,
manual: bool,
) -> dict[str, Any]:
"""Drive the browser (or manual) OAuth flow and return a token record."""
server = None if manual else _try_start_callback_server()
console.print("Open this URL in your browser to authorize:")
console.print(f"[cyan]{authorize_url}[/]")
console.print()
if not manual:
try:
webbrowser.open(authorize_url)
except Exception: # noqa: BLE001 - opening a browser is best-effort
logger.debug("could not open browser", exc_info=True)
if server is not None:
console.print("[dim]Waiting for you to finish signing in…[/]")
result = server.wait(_CALLBACK_TIMEOUT_S)
server.shutdown()
if result is not None:
code, returned_state, error = result
if error:
raise codex.CodexAuthError("oauth_error", error)
return _finish(code, returned_state, verifier, state, require_state=True)
console.print("[yellow]Timed out waiting for the browser. Falling back to manual paste.[/]")
# Manual fallback: the user completes sign-in and pastes the redirect URL
# (the browser lands on a localhost page that won't load if no server is up;
# the address bar still holds the code+state).
console.print()
try:
pasted = console.input("Paste the full redirect URL (or code#state): ").strip()
except EOFError as exc:
raise codex.CodexAuthError("no_input", "no redirect URL provided") from exc
code, returned_state = codex.parse_redirect_input(pasted)
return _finish(code, returned_state, verifier, state, require_state=False)
def _finish(
code: str | None,
returned_state: str | None,
verifier: str,
expected_state: str,
*,
require_state: bool,
) -> dict[str, Any]:
if not code:
raise codex.CodexAuthError("no_code", "no authorization code found in the redirect")
# The loopback callback from OpenAI always carries state, so a missing or
# mismatched value there is forged (CSRF) and must be rejected. Manual paste
# is user-initiated (the user copies their own redirect), so state is only
# validated when the pasted value includes it.
if require_state and returned_state is None:
raise codex.CodexAuthError("state_mismatch", "missing state in callback; possible CSRF")
if returned_state is not None and returned_state != expected_state:
raise codex.CodexAuthError("state_mismatch", "state did not match; possible CSRF")
return codex.exchange_code(code, verifier)
class _CallbackServer:
"""A one-shot local HTTP server that catches the OAuth redirect."""
def __init__(self, httpd: HTTPServer, event: threading.Event, holder: dict[str, Any]) -> None:
self._httpd = httpd
self._event = event
self._holder = holder
self._thread = threading.Thread(target=httpd.serve_forever, daemon=True)
self._thread.start()
def wait(self, timeout: float) -> tuple[str | None, str | None, str | None] | None:
if not self._event.wait(timeout):
return None
return (
self._holder.get("code"),
self._holder.get("state"),
self._holder.get("error"),
)
def shutdown(self) -> None:
self._httpd.shutdown()
self._httpd.server_close()
def _try_start_callback_server() -> _CallbackServer | None:
event = threading.Event()
holder: dict[str, Any] = {}
class Handler(BaseHTTPRequestHandler):
def log_message(self, *args: Any) -> None: # silence default stderr logging
pass
def do_GET(self) -> None:
parsed = urlparse(self.path)
if parsed.path != codex.CALLBACK_PATH:
self.send_response(404)
self.end_headers()
return
query = parse_qs(parsed.query)
holder["code"] = _first(query, "code")
holder["state"] = _first(query, "state")
holder["error"] = _first(query, "error_description") or _first(query, "error")
body = _render_callback_html().encode("utf-8")
self.send_response(200)
self.send_header("Content-Type", "text/html; charset=utf-8")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
event.set()
try:
httpd = HTTPServer(("127.0.0.1", codex.CALLBACK_PORT), Handler)
except OSError:
logger.debug("could not bind callback port %d", codex.CALLBACK_PORT, exc_info=True)
return None
return _CallbackServer(httpd, event, holder)
def _first(query: dict[str, list[str]], key: str) -> str | None:
values = query.get(key)
return values[0] if values else None
def _status(console: Console) -> int:
record = codex.read_record()
if record is None:
console.print("[yellow]Not signed in.[/] Run [cyan]strix auth login chatgpt[/] to sign in.")
return 1
settings = load_settings()
console.print("[green]Signed in[/] with a ChatGPT subscription.")
console.print(f" Account: [bold]{record.get('account_id')}[/]")
if codex.subscription_model(settings.llm.model):
console.print(f" Runs use the subscription (STRIX_LLM=[bold]{settings.llm.model}[/]).")
else:
console.print(
" [yellow]Note:[/] set [cyan]STRIX_LLM[/] to e.g. [cyan]chatgpt/gpt-5.4[/] "
"to run on the subscription."
)
return 0
def _logout(console: Console) -> int:
codex.logout()
console.print("[green]Signed out.[/] Stored subscription credentials removed.")
return 0
def _fail(console: Console, exc: codex.CodexAuthError) -> int:
error_text = Text()
error_text.append("SIGN-IN FAILED", style="bold red")
error_text.append("\n\n", style="white")
error_text.append(f"{exc}", style="white")
console.print()
console.print(
Panel(
error_text,
title="[bold white]STRIX",
title_align="left",
border_style="red",
padding=(1, 2),
)
)
return 1
def _print_success(console: Console) -> None:
text = Text()
text.append("Signed in with your ChatGPT subscription", style="bold #22c55e")
text.append("\n\n", style="white")
text.append("Set ", style="white")
text.append("STRIX_LLM", style="bold white")
text.append(" to a ", style="white")
text.append("chatgpt/", style="bold cyan")
text.append(" model (e.g. ", style="white")
text.append("chatgpt/gpt-5.4", style="bold cyan")
text.append(") — runs are billed to your ChatGPT plan.", style="white")
text.append("\n\n", style="white")
text.append("Run a scan as usual, e.g. ", style="white")
text.append("strix --target https://example.com", style="bold cyan")
console.print()
console.print(
Panel(
text,
title="[bold white]STRIX",
title_align="left",
border_style="#22c55e",
padding=(1, 2),
)
)
console.print()
_LOGO_PATH = Path(__file__).resolve().parent.parent / "viewer" / "static" / "logo.png"
def _logo_img_tag() -> str:
"""Return an ``<img>`` for the Strix logo as an inline data URI, or "".
The callback page is served offline by the local OAuth server, so the logo
is embedded rather than linked. Missing/unreadable file degrades to just the
"Strix" wordmark.
"""
try:
data = _LOGO_PATH.read_bytes()
except OSError:
return ""
encoded = base64.b64encode(data).decode("ascii")
return f'<img class="logo" src="data:image/png;base64,{encoded}" alt="" />'
def _render_callback_html() -> str:
return _CALLBACK_HTML.replace("<!--LOGO-->", _logo_img_tag())
_CALLBACK_HTML = """<!doctype html>
<html lang="en"><head><meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Strix — signed in</title>
<style>
:root { color-scheme: dark; }
* { box-sizing: border-box; }
body {
margin: 0; min-height: 100vh; padding: 24px;
font-family: 'Geist', 'Geist Sans', ui-sans-serif, system-ui, -apple-system,
"Segoe UI", Roboto, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
background: #000; color: #ededed;
display: flex; flex-direction: column; align-items: center; justify-content: center;
}
.topbar {
position: absolute; top: 20px; left: 22px;
display: flex; align-items: center; gap: 6px; text-decoration: none;
}
.topbar .logo { width: 40px; height: 40px; display: block; }
.topbar span {
font-size: 1.1rem; font-weight: 600; letter-spacing: -.01em; color: #fff;
transition: color .15s ease;
}
.topbar:hover span { color: #c9c9c9; }
.brand {
font-size: 2.1rem; font-weight: 700; letter-spacing: -.02em; color: #fff;
text-align: center; margin: 0 0 10px;
}
h1 {
font-size: 1.35rem; font-weight: 600; letter-spacing: -.01em; color: #f5f5f5;
text-align: center; margin: 0 0 28px;
}
.card {
width: 100%; max-width: 430px; text-align: center;
background: #171717; border: 1px solid rgba(255, 255, 255, .06);
border-radius: 24px; padding: 40px 40px 34px;
}
.badge {
margin: 0 auto 22px; width: 52px; height: 52px; border-radius: 50%;
display: flex; align-items: center; justify-content: center; font-size: 23px; color: #fff;
background: rgba(255, 255, 255, .05); border: 1px solid rgba(255, 255, 255, .14);
}
.msg { margin: 0 auto; max-width: 34ch; color: #b5b5b5; line-height: 1.6; font-size: .98rem; }
.rule { height: 1px; background: rgba(255, 255, 255, .07); margin: 26px 0 0; }
.tagline { margin: 22px 0 0; color: #7c7c7c; font-size: .9rem; line-height: 1.55; }
.tagline b { color: #ededed; font-weight: 500; }
.links {
margin-top: 18px; display: flex; gap: 8px; justify-content: center;
align-items: center; flex-wrap: wrap; font-size: .84rem;
}
.links a { color: #a3a3a3; text-decoration: none; transition: color .15s ease; }
.links a:hover { color: #fff; }
.links .dot { color: #3a3a3a; }
.close { margin: 24px 0 0; color: #5a5a5a; font-size: .78rem; text-align: center; }
</style></head>
<body>
<a class="topbar" href="https://strix.ai" target="_blank" rel="noopener"
aria-label="Strix — strix.ai">
<!--LOGO-->
<span>Strix</span>
</a>
<div class="brand">Strix</div>
<h1>You're signed in</h1>
<main class="card">
<div class="badge">✓</div>
<p class="msg">Strix is connected to your ChatGPT subscription. Head back to your
terminal — your security test runs there.</p>
<div class="rule"></div>
<p class="tagline">Autonomous AI hackers that <b>find and fix</b> your app's
vulnerabilities.</p>
<nav class="links">
<a href="https://strix.ai" target="_blank" rel="noopener">strix.ai</a>
<span class="dot">·</span>
<a href="https://docs.strix.ai" target="_blank" rel="noopener">docs</a>
<span class="dot">·</span>
<a href="https://discord.gg/strix-ai" target="_blank" rel="noopener">community</a>
</nav>
</main>
<p class="close">You can close this tab.</p>
</body></html>"""
__all__ = ["run_auth"]
+128 -69
View File
@@ -5,9 +5,9 @@ Strix Agent Interface
import argparse
import asyncio
import os
import shutil
import sys
import time
from datetime import UTC, datetime
from pathlib import Path
@@ -20,6 +20,7 @@ from rich.text import Text
from strix.config import (
apply_config_override,
codex,
load_settings,
persist_current,
)
@@ -33,6 +34,13 @@ from strix.config.models import (
from strix.core.paths import run_dir_for, runtime_state_dir
from strix.interface.cli import run_cli
from strix.interface.tui import run_tui
from strix.interface.update_check import (
is_binary_install,
notify_update,
prompt_update_if_available,
self_update,
start_background_check,
)
from strix.interface.utils import (
assign_workspace_subdirs,
build_final_stats_text,
@@ -85,6 +93,16 @@ def validate_environment() -> None:
settings = load_settings()
if codex.subscription_model(settings.llm.model):
if not codex.is_authenticated():
console.print(
f"[red]STRIX_LLM={settings.llm.model} uses your ChatGPT subscription, "
"but you're not signed in.[/] Run [cyan]strix auth login chatgpt[/] first."
)
sys.exit(1)
logger.info("Environment OK (ChatGPT subscription)")
return
if not settings.llm.model:
missing_required_vars.append("STRIX_LLM")
@@ -267,6 +285,29 @@ def _provider_import_hint(exc: BaseException, model: str) -> str | None:
return None
def _subscription_error_hint(exc: BaseException) -> str | None:
"""Return an actionable hint for a known ChatGPT-subscription error, or None."""
if not codex.subscription_model(load_settings().llm.model):
return None
joined = " ".join(_exception_messages(exc)).lower()
if "not supported when using codex with a chatgpt account" in joined:
return (
"This model isn't available on your ChatGPT subscription. "
"Set STRIX_LLM to a model your plan includes (e.g. chatgpt/gpt-5.4)."
)
if (
"error code: 401" in joined
or "http 401" in joined
or "unauthorized" in joined
or "invalid_grant" in joined
):
return (
"Your ChatGPT sign-in has expired or was revoked. Sign in again:\n"
" strix auth login chatgpt"
)
return None
async def warm_up_llm(show_model_warning: bool = True) -> None:
console = Console()
logger.info("Warming up LLM connection")
@@ -276,8 +317,8 @@ async def warm_up_llm(show_model_warning: bool = True) -> None:
settings = load_settings()
configure_sdk_model_defaults(settings)
llm = settings.llm
raw_model = (llm.model or "").strip()
if (
raw_model
and "/" not in raw_model
@@ -353,23 +394,63 @@ async def warm_up_llm(show_model_warning: bool = True) -> None:
)
logger.info("LLM warm-up succeeded for model %s", (llm.model or "").strip())
if settings.dedupe.model:
from strix.report.dedupe import _dedupe_extra_args
dedupe_model = settings.dedupe.model.strip()
raw_model = dedupe_model
deduper = StrixProvider().get_model(dedupe_model)
# Match the runtime path: send the dedupe key/endpoint per call so a
# separate-provider dedupe model authenticates during warm-up too.
deduper_extra = _dedupe_extra_args(settings.dedupe)
deduper_settings = ModelSettings(extra_args=deduper_extra or None)
await asyncio.wait_for(
deduper.get_response(
system_instructions="You are a helpful assistant.",
input="Reply with just 'OK'.",
model_settings=deduper_settings,
tools=[],
output_schema=None,
handoffs=[],
tracing=ModelTracing.DISABLED,
previous_response_id=None,
conversation_id=None,
prompt=None,
),
timeout=llm.timeout,
)
logger.info("LLM warm-up succeeded for dedupe model %s", dedupe_model)
except Exception as e:
logger.exception("LLM warm-up failed")
error_text = Text()
error_text.append("LLM CONNECTION FAILED", style="bold red")
error_text.append("\n\n", style="white")
error_text.append("Could not establish connection to the language model.\n", style="white")
error_text.append("Please check your configuration and try again.\n", style="white")
hint = _provider_import_hint(e, raw_model)
if hint is not None:
error_text.append(f"\n{hint}\n", style="bold yellow")
error_text.append(f"\nError: {e}", style="dim white")
sub_hint = _subscription_error_hint(e)
if sub_hint is not None:
# The model/backend answered with a clear, actionable rejection —
# show that instead of a generic "connection failed".
border_style = "yellow"
error_text.append("MODEL NOT AVAILABLE ON SUBSCRIPTION", style="bold yellow")
error_text.append("\n\n", style="white")
error_text.append(f"{sub_hint}\n", style="white")
error_text.append(f"\nDetails: {e}", style="dim white")
else:
border_style = "red"
error_text.append("LLM CONNECTION FAILED", style="bold red")
error_text.append("\n\n", style="white")
error_text.append(
"Could not establish connection to the language model.\n", style="white"
)
error_text.append("Please check your configuration and try again.\n", style="white")
hint = _provider_import_hint(e, raw_model)
if hint is not None:
error_text.append(f"\n{hint}\n", style="bold yellow")
error_text.append(f"\nError: {e}", style="dim white")
panel = Panel(
error_text,
title="[bold white]STRIX",
title_align="left",
border_style="red",
border_style=border_style,
padding=(1, 2),
)
@@ -448,6 +529,14 @@ Examples:
version=f"strix {get_version()}",
)
parser.add_argument(
"--update",
action="store_true",
help="Update strix to the latest version and exit. Self-updates the "
"standalone binary install; for pip/pipx/uv installs, prints the "
"matching upgrade command instead.",
)
parser.add_argument(
"-t",
"--target",
@@ -566,6 +655,9 @@ Examples:
args = parser.parse_args()
if args.update:
sys.exit(0 if self_update() else 1)
if args.instruction and args.instruction_file:
parser.error(
"Cannot specify both --instruction and --instruction-file. Use one or the other."
@@ -664,6 +756,7 @@ def _persist_run_record(args: argparse.Namespace) -> None:
"status": "running",
"start_time": datetime.now(UTC).isoformat(),
"end_time": None,
"auth_mode": codex.auth_mode(load_settings().llm.model),
"targets_info": args.targets_info,
"scan_mode": args.scan_mode,
"instruction": args.instruction,
@@ -721,9 +814,7 @@ def _load_resume_state(args: argparse.Namespace, parser: argparse.ArgumentParser
args.scan_mode = persisted_scan_mode
def display_completion_message(
args: argparse.Namespace, results_path: Path, web_url: str | None = None
) -> None:
def display_completion_message(args: argparse.Namespace, results_path: Path) -> None:
console = Console()
report_state = get_global_report_state()
@@ -762,28 +853,12 @@ def display_completion_message(
results_text.append(str(results_path), style="#60a5fa")
panel_parts.extend(["\n", results_text])
if web_url:
web_text = Text()
web_text.append("\n")
web_text.append("View in web", style="dim")
web_text.append(" ")
# OSC-8 hyperlink: clickable in modern terminals, falls back to the URL.
web_text.append(web_url, style=f"#60a5fa link {web_url}")
panel_parts.extend(["\n", web_text])
reopen_text = Text()
reopen_text.append("\n")
reopen_text.append("Reopen", style="dim")
reopen_text.append(" ")
reopen_text.append(f"strix view {args.run_name}", style="#22c55e")
panel_parts.extend(["\n", reopen_text])
else:
view_text = Text()
view_text.append("\n")
view_text.append("View", style="dim")
view_text.append(" ")
view_text.append(f"strix view {args.run_name}", style="#22c55e")
panel_parts.extend(["\n", view_text])
view_text = Text()
view_text.append("\n")
view_text.append("View", style="dim")
view_text.append(" ")
view_text.append(f"strix view {args.run_name}", style="#22c55e")
panel_parts.extend(["\n", view_text])
if not scan_completed:
resume_text = Text()
@@ -814,6 +889,8 @@ def display_completion_message(
"[#60a5fa]discord.gg/strix-ai[/]"
)
console.print()
if not args.non_interactive:
notify_update(console)
def pull_docker_image() -> None:
@@ -880,11 +957,24 @@ def main() -> None:
run_view(sys.argv[2:])
return
# `strix auth …` manages model-subscription sign-in and exits; it needs no
# target, Docker, or scan setup.
if len(sys.argv) > 1 and sys.argv[1] == "auth":
from strix.interface.auth_cli import run_auth
sys.exit(run_auth(sys.argv[2:]))
args = parse_arguments()
if args.config:
apply_config_override(validate_config_file(args.config))
start_background_check()
if not args.non_interactive and prompt_update_if_available(Console()):
if is_binary_install() and sys.platform != "win32":
os.execv(sys.executable, sys.argv) # noqa: S606 # nosec B606
sys.exit(0)
check_docker_installed()
pull_docker_image()
@@ -941,6 +1031,7 @@ def main() -> None:
_telemetry_start_kwargs = {
"model": load_settings().llm.model,
"auth_mode": codex.auth_mode(load_settings().llm.model),
"scan_mode": args.scan_mode,
"is_whitebox": is_whitebox_scan(args.targets_info),
"interactive": not args.non_interactive,
@@ -975,39 +1066,7 @@ def main() -> None:
results_path = run_dir_for(args.run_name)
# For an interactive run, host the local viewer so the completion panel can
# show a clickable "View in web" link. Skipped in non-interactive/CI runs
# (no TTY to serve and it would block the process).
viewer_httpd = None
web_url = None
if not args.non_interactive and sys.stdout.isatty():
from strix.viewer.server import authorized_url, bundle_is_built, serve
if bundle_is_built():
try:
viewer_httpd, base_url, token = serve(results_path, open_browser=False)
# The completion panel's "View in web" link must authorize the
# browser, so hand it the tokened URL rather than the bare host.
web_url = authorized_url(base_url, token)
posthog.viewer_opened(source="post_scan", live=False)
except Exception:
logger.debug("could not start local viewer", exc_info=True)
viewer_httpd, web_url = None, None
display_completion_message(args, results_path, web_url=web_url)
if viewer_httpd is not None:
console = Console()
console.print("[dim]Hosting the local viewer. Press Ctrl-C to stop.[/]")
console.print()
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
console.print("\n[dim]Viewer stopped.[/]")
finally:
viewer_httpd.shutdown()
viewer_httpd.server_close()
display_completion_message(args, results_path)
if args.non_interactive:
report_state = get_global_report_state()
+39 -15
View File
@@ -42,6 +42,12 @@ from strix.interface.tui.renderers.agent_message_renderer import AgentMessageRen
from strix.interface.tui.renderers.user_message_renderer import UserMessageRenderer
from strix.interface.utils import build_tui_stats_text
from strix.report.state import ReportState, set_global_report_state
from strix.report.writer import (
guess_language_name,
parse_fenced_code,
resolve_lexer,
safe_fence,
)
from strix.runtime import session_manager
@@ -330,12 +336,11 @@ class VulnerabilityDetailScreen(ModalScreen): # type: ignore[misc]
return "#65a30d"
return "#6b7280"
def _highlight_python(self, code: str) -> Text:
def _highlight_python(self, code: str, language: str | None = None) -> Text:
try:
from pygments.lexers import PythonLexer
from pygments.styles import get_style_by_name
lexer = PythonLexer()
lexer = resolve_lexer(language, code)
style = get_style_by_name("native")
colors = {
token: f"#{style_def['color']}" for token, style_def in style if style_def["color"]
@@ -501,10 +506,11 @@ class VulnerabilityDetailScreen(ModalScreen): # type: ignore[misc]
poc_script_code = vuln.get("poc_script_code", "")
if poc_script_code:
poc_language, poc_code = parse_fenced_code(poc_script_code)
text.append("\n\n")
text.append("PoC Code", style=self.FIELD_STYLE)
text.append("\n")
text.append_text(self._highlight_python(poc_script_code))
text.append_text(self._highlight_python(poc_code, poc_language))
remediation_steps = vuln.get("remediation_steps", "")
if remediation_steps:
@@ -601,9 +607,12 @@ class VulnerabilityDetailScreen(ModalScreen): # type: ignore[misc]
lines.append(vuln["poc_description"])
lines.append("")
if vuln.get("poc_script_code"):
lines.append("```python")
lines.append(vuln["poc_script_code"])
lines.append("```")
poc_language, poc_code = parse_fenced_code(vuln["poc_script_code"])
fence_lang = poc_language or guess_language_name(poc_code)
fence = safe_fence(poc_code)
lines.append(f"{fence}{fence_lang}")
lines.append(poc_code)
lines.append(fence)
if vuln.get("code_locations"):
lines.extend(["", "## Code Analysis", ""])
@@ -619,7 +628,9 @@ class VulnerabilityDetailScreen(ModalScreen): # type: ignore[misc]
if loc.get("label"):
lines.append(f" {loc['label']}")
if loc.get("snippet"):
lines.append(f"```\n{loc['snippet']}\n```")
snippet = str(loc["snippet"])
snippet_fence = safe_fence(snippet)
lines.append(f"{snippet_fence}\n{snippet}\n{snippet_fence}")
if loc.get("fix_before") or loc.get("fix_after"):
lines.append("**Suggested Fix:**")
lines.append("```diff")
@@ -802,6 +813,7 @@ class StrixTUIApp(App): # type: ignore[misc]
self._scan_stop_event = threading.Event()
self._scan_completed = threading.Event()
self._scan_error: BaseException | None = None
self._error_noted_agents: set[str] = set()
self._spinner_frame_index: int = 0
self._sweep_num_squares: int = 6
@@ -1015,22 +1027,32 @@ class StrixTUIApp(App): # type: ignore[misc]
else:
self._agent_graph_sync_future = None
try:
parent_of, statuses, names = future.result()
parent_of, statuses, names, errors = future.result()
except Exception:
logger.exception("TUI agent graph sync failed")
else:
for agent_id, status in statuses.items():
error = errors.get(agent_id)
self.live_view.upsert_agent(
agent_id,
name=names.get(agent_id, agent_id),
parent_id=parent_of.get(agent_id),
status=status,
error_message=error,
)
if status in {"failed", "crashed"} and error:
if agent_id not in self._error_noted_agents:
self._error_noted_agents.add(agent_id)
self.live_view.record_agent_error(agent_id, error)
else:
self._error_noted_agents.discard(agent_id)
if self._scan_loop is None or self._scan_loop.is_closed():
return
async def collect() -> tuple[dict[str, str | None], dict[str, Any], dict[str, str]]:
async def collect() -> tuple[
dict[str, str | None], dict[str, Any], dict[str, str], dict[str, str]
]:
return await self.coordinator.graph_snapshot()
self._agent_graph_sync_future = asyncio.run_coroutine_threadsafe(collect(), self._scan_loop)
@@ -1049,6 +1071,7 @@ class StrixTUIApp(App): # type: ignore[misc]
"waiting": "⏸",
"completed": "🟢",
"failed": "🔴",
"crashed": "🔴",
"stopped": "■",
}
@@ -1234,13 +1257,12 @@ class StrixTUIApp(App): # type: ignore[misc]
text.append(msg)
return (text, Text(), False)
if status == "failed":
if status in {"failed", "crashed"}:
error_msg = agent_data.get("error_message", "")
text = Text()
if error_msg:
text.append(error_msg, style="red")
else:
text.append("Scan failed", style="red")
text.append(error_msg or "Agent failed", style="red")
text.append(" · ", style="dim")
text.append("Send message to resume", style="dim")
self._stop_dot_animation()
return (text, Text(), False)
@@ -1539,6 +1561,7 @@ class StrixTUIApp(App): # type: ignore[misc]
"waiting": "⏸",
"completed": "🟢",
"failed": "🔴",
"crashed": "🔴",
"stopped": "■",
}
@@ -1584,6 +1607,7 @@ class StrixTUIApp(App): # type: ignore[misc]
"waiting": "⏸",
"completed": "🟢",
"failed": "🔴",
"crashed": "🔴",
"stopped": "■",
}
+11
View File
@@ -86,6 +86,17 @@ class TuiLiveView:
current["error_message"] = error_message
current["updated_at"] = now
def record_agent_error(self, agent_id: str, error: str) -> None:
self._append_event(
agent_id,
"chat",
{
"role": "assistant",
"content": (f"An error occurred: {error}\nI'm now waiting for new instructions."),
"metadata": {"source": "agent_error"},
},
)
def record_user_message(self, agent_id: str, content: str) -> None:
self._append_event(
agent_id,
@@ -1,11 +1,12 @@
from functools import cache
from typing import Any, ClassVar
from pygments.lexers import PythonLexer
from pygments.styles import get_style_by_name
from rich.text import Text
from textual.widgets import Static
from strix.report.writer import parse_fenced_code, resolve_lexer
from .base_renderer import BaseToolRenderer
from .registry import register_tool_renderer
@@ -61,8 +62,8 @@ class CreateVulnerabilityReportRenderer(BaseToolRenderer):
return None
@classmethod
def _highlight_python(cls, code: str) -> Text:
lexer = PythonLexer()
def _highlight_code(cls, code: str, language: str | None) -> Text:
lexer = resolve_lexer(language, code)
text = Text()
for token_type, token_value in lexer.get_tokens(code):
@@ -234,10 +235,11 @@ class CreateVulnerabilityReportRenderer(BaseToolRenderer):
text.append(poc_description)
if poc_script_code:
poc_language, poc_code = parse_fenced_code(poc_script_code)
text.append("\n\n")
text.append("PoC Code", style=FIELD_STYLE)
text.append("\n")
text.append_text(cls._highlight_python(poc_script_code))
text.append_text(cls._highlight_code(poc_code, poc_language))
if remediation_steps:
text.append("\n\n")
+389
View File
@@ -0,0 +1,389 @@
"""Update notifications and self-update for the strix CLI.
Follows the pattern used by tools like gh, uv, and pip: a background,
rate-limited (once per 24h) check against the release source, a cached
result in ``~/.strix``, a non-intrusive notice with the upgrade command
for the detected install method, and a ``strix --update`` self-update
path for the standalone binary install.
"""
from __future__ import annotations
import hashlib
import json
import logging
import os
import platform
import shutil
import stat
import subprocess
import sys
import tarfile
import tempfile
import threading
import time
import zipfile
from pathlib import Path
from typing import cast
import requests
from rich.console import Console
from rich.prompt import Prompt
from strix.telemetry._common import get_version
logger = logging.getLogger(__name__)
GITHUB_REPO = "usestrix/strix"
PYPI_PACKAGE = "strix-agent"
CHECK_INTERVAL_SECONDS = 24 * 60 * 60
REQUEST_TIMEOUT_SECONDS = 5
_CACHE_PATH = Path.home() / ".strix" / "update-check.json"
_background_thread: threading.Thread | None = None
def _is_disabled() -> bool:
return bool(os.environ.get("STRIX_NO_UPDATE_CHECK")) or any(
os.environ.get(key)
for key in ("CI", "GITHUB_ACTIONS", "GITLAB_CI", "JENKINS_URL", "BUILDKITE", "CIRCLECI")
)
def is_binary_install() -> bool:
return bool(getattr(sys, "frozen", False))
def get_install_method() -> str:
if is_binary_install():
return "binary"
prefix = str(Path(sys.prefix)).replace("\\", "/")
if "/pipx/" in prefix or prefix.endswith("/pipx"):
return "pipx"
if "/uv/tools/" in prefix:
return "uv"
return "pip"
def get_upgrade_command(method: str | None = None) -> str:
method = method or get_install_method()
commands = {
"binary": "strix --update",
"pipx": "pipx upgrade strix-agent",
"uv": "uv tool upgrade strix-agent",
"pip": "pip install --upgrade strix-agent",
}
return commands[method]
def _parse_version(value: str) -> tuple[int, ...] | None:
parts = value.strip().lstrip("v").split(".")
try:
return tuple(int(part) for part in parts)
except ValueError:
return None
def _is_newer(latest: str, current: str) -> bool:
latest_parts = _parse_version(latest)
current_parts = _parse_version(current)
if latest_parts is None or current_parts is None:
return False
return latest_parts > current_parts
def _fetch_latest_version() -> str | None:
try:
if is_binary_install():
response = requests.get(
f"https://api.github.com/repos/{GITHUB_REPO}/releases/latest",
timeout=REQUEST_TIMEOUT_SECONDS,
)
response.raise_for_status()
tag = response.json().get("tag_name", "")
return tag.lstrip("v") or None
response = requests.get(
f"https://pypi.org/pypi/{PYPI_PACKAGE}/json",
timeout=REQUEST_TIMEOUT_SECONDS,
)
response.raise_for_status()
version = response.json().get("info", {}).get("version")
return str(version) if version else None
except Exception: # noqa: BLE001
logger.debug("update check failed", exc_info=True)
return None
def _fetch_asset_digest(version: str, filename: str) -> str | None:
"""Return the expected sha256 (hex) for a release asset, if the API provides one."""
try:
response = requests.get(
f"https://api.github.com/repos/{GITHUB_REPO}/releases/tags/v{version}",
timeout=REQUEST_TIMEOUT_SECONDS,
)
response.raise_for_status()
for asset in response.json().get("assets", []):
if asset.get("name") == filename:
digest = asset.get("digest") or ""
if digest.startswith("sha256:"):
return digest.removeprefix("sha256:")
except Exception: # noqa: BLE001
logger.debug("release asset digest lookup failed", exc_info=True)
return None
def _sha256_file(path: Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as f:
for chunk in iter(lambda: f.read(1 << 20), b""):
digest.update(chunk)
return digest.hexdigest()
def _read_cache() -> dict[str, object]:
try:
with _CACHE_PATH.open(encoding="utf-8") as f:
data = json.load(f)
if isinstance(data, dict):
return cast("dict[str, object]", data)
except Exception: # noqa: BLE001, S110
pass # nosec B110
return {}
def _write_cache(**fields: object) -> None:
try:
cache = _read_cache()
cache.update(fields)
_CACHE_PATH.parent.mkdir(parents=True, exist_ok=True)
_CACHE_PATH.write_text(json.dumps(cache), encoding="utf-8")
except Exception: # noqa: BLE001, S110
pass # nosec B110
def skip_version(version: str) -> None:
"""Remember not to prompt again for this version (newer releases still notify)."""
_write_cache(skipped_version=version)
def _refresh_cache() -> None:
latest = _fetch_latest_version()
if latest:
_write_cache(latest_version=latest, checked_at=time.time())
def start_background_check() -> None:
"""Refresh the cached latest-version info in a daemon thread (at most once per 24h)."""
global _background_thread # noqa: PLW0603
if _is_disabled():
return
cache = _read_cache()
checked_at = cache.get("checked_at")
if isinstance(checked_at, int | float) and time.time() - checked_at < CHECK_INTERVAL_SECONDS:
return
_background_thread = threading.Thread(target=_refresh_cache, daemon=True)
_background_thread.start()
def get_available_update(*, respect_skip: bool = True) -> str | None:
"""Return the newer version from the cache, or None if up to date / unknown."""
if _is_disabled():
return None
if _background_thread is not None:
_background_thread.join(timeout=0.2)
cache = _read_cache()
latest = cache.get("latest_version")
current = get_version()
if not isinstance(latest, str) or current == "unknown" or not _is_newer(latest, current):
return None
if respect_skip and cache.get("skipped_version") == latest:
return None
return latest
def notify_update(console: Console) -> None:
latest = get_available_update()
if not latest:
return
console.print(
f"[#eab308]A new version of strix is available:[/] "
f"[dim]{get_version()}[/] [dim]→[/] [bold #22c55e]{latest}[/]"
f" [dim]·[/] [#60a5fa]{get_upgrade_command()}[/]"
)
console.print()
def run_package_upgrade(console: Console, method: str) -> bool:
"""Upgrade a package-manager install by running its upgrade command."""
command = get_upgrade_command(method).split()
console.print(f"[dim]Running[/] [#60a5fa]{' '.join(command)}[/]")
try:
result = subprocess.run(command, check=False) # noqa: S603
except OSError as e:
console.print(f"[bold red]Update failed:[/] {e}")
return False
if result.returncode != 0:
console.print(
f"[bold red]Update failed[/] [dim](exit code {result.returncode}).[/] "
f"Run it manually: [#60a5fa]{get_upgrade_command(method)}[/]"
)
return False
console.print("[#22c55e]✓ strix updated — restart the scan to use the new version[/]")
return True
def prompt_update_if_available(console: Console) -> bool:
"""Offer an interactive update before a scan starts.
Returns True if strix was updated (caller should re-exec / exit).
"""
latest = get_available_update()
if not latest or not sys.stdin.isatty() or not sys.stdout.isatty():
return False
console.print()
console.print(
f"[#eab308]A new version of strix is available:[/] "
f"[dim]{get_version()}[/] [dim]→[/] [bold #22c55e]{latest}[/]"
)
console.print(
"[dim] y — update now n — not now (ask again next run) s — skip this version[/]"
)
choice = Prompt.ask("Update strix?", choices=["y", "n", "s"], default="n")
console.print()
if choice == "s":
skip_version(latest)
return False
if choice != "y":
return False
method = get_install_method()
if method == "binary":
return self_update(console, version=latest)
return run_package_upgrade(console, method)
def _release_target() -> str | None:
raw_os = platform.system().lower()
os_name = {"darwin": "macos", "linux": "linux", "windows": "windows"}.get(raw_os)
arch = platform.machine().lower()
arch = {"aarch64": "arm64", "amd64": "x86_64"}.get(arch, arch)
if os_name is None:
return None
target = f"{os_name}-{arch}"
supported = {"linux-x86_64", "macos-x86_64", "macos-arm64", "windows-x86_64"}
return target if target in supported else None
def _download_and_replace(version: str, target: str, console: Console) -> bool:
is_windows = target.startswith("windows")
archive_ext = ".zip" if is_windows else ".tar.gz"
filename = f"strix-{version}-{target}{archive_ext}"
url = f"https://github.com/{GITHUB_REPO}/releases/download/v{version}/{filename}"
binary_name = f"strix-{version}-{target}" + (".exe" if is_windows else "")
current_exe = Path(sys.executable).resolve()
with tempfile.TemporaryDirectory() as tmp:
tmp_dir = Path(tmp)
archive_path = tmp_dir / filename
console.print(f"[dim]Downloading[/] {url}")
with requests.get( # nosec B113
url,
stream=True,
timeout=REQUEST_TIMEOUT_SECONDS * 12,
) as response:
response.raise_for_status()
with archive_path.open("wb") as f:
for chunk in response.iter_content(chunk_size=1 << 20):
f.write(chunk)
expected_digest = _fetch_asset_digest(version, filename)
if expected_digest:
actual_digest = _sha256_file(archive_path)
if actual_digest != expected_digest:
raise RuntimeError(
f"checksum mismatch for {filename}: "
f"expected sha256 {expected_digest}, got {actual_digest}"
)
else:
console.print("[dim yellow]No published checksum available; skipping verification[/]")
if is_windows:
with zipfile.ZipFile(archive_path) as zf:
zf.extract(binary_name, tmp_dir)
else:
with tarfile.open(archive_path, "r:gz") as tf:
tf.extract(binary_name, tmp_dir, filter="data")
new_binary = tmp_dir / binary_name
new_binary.chmod(new_binary.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
staged = current_exe.with_name(current_exe.name + ".new")
try:
shutil.copy2(new_binary, staged)
if is_windows:
# Windows can't replace a running executable in place; move it aside first.
old = current_exe.with_name(current_exe.name + ".old")
old.unlink(missing_ok=True)
current_exe.rename(old)
try:
staged.replace(current_exe)
except Exception:
old.rename(current_exe)
raise
else:
staged.replace(current_exe)
except Exception:
staged.unlink(missing_ok=True)
raise
return True
def self_update(console: Console | None = None, version: str | None = None) -> bool:
"""Replace the running standalone binary with the latest release.
Returns True on success. For package-manager installs this only
prints the right upgrade command and returns False.
"""
console = console or Console()
if not is_binary_install():
method = get_install_method()
console.print(
f"[#eab308]This strix was installed via {method};[/] "
f"upgrade it with: [#60a5fa]{get_upgrade_command(method)}[/]"
)
return False
latest = version or _fetch_latest_version()
if not latest:
console.print("[bold red]Could not determine the latest strix version.[/]")
return False
current = get_version()
if current != "unknown" and not _is_newer(latest, current):
console.print(f"[#22c55e]strix {current} is already the latest version.[/]")
return True
target = _release_target()
if not target:
console.print(
f"[bold red]No prebuilt binary for this platform "
f"({platform.system()}/{platform.machine()}).[/]"
)
return False
try:
_download_and_replace(latest, target, console)
except Exception as e: # noqa: BLE001
logger.debug("self-update failed", exc_info=True)
console.print(f"[bold red]Update failed:[/] {e}")
console.print(
"[dim]You can reinstall manually with:[/] "
"[#60a5fa]curl -sSL https://strix.ai/install | bash[/]"
)
return False
_write_cache(latest_version=latest, checked_at=time.time())
console.print(f"[#22c55e]✓ Updated strix to {latest}[/]")
return True
+38 -6
View File
@@ -253,6 +253,20 @@ def _llm_usage(report_state: Any) -> dict[str, Any]:
return usage if isinstance(usage, dict) else {}
def _is_subscription(report_state: Any) -> bool:
"""Whether this run uses a model subscription (no metered cost).
Prefers the run record so it's correct for hydrated/resumed runs; falls back
to current settings.
"""
record = getattr(report_state, "run_record", None)
if isinstance(record, dict) and record.get("auth_mode"):
return record.get("auth_mode") == "subscription"
from strix.config import codex
return codex.auth_mode(load_settings().llm.model) == "subscription"
def _int_stat(usage: dict[str, Any], key: str) -> int:
try:
return max(0, int(usage.get(key) or 0))
@@ -283,11 +297,16 @@ def _build_llm_usage_stats(
*,
live: bool = False,
) -> None:
subscription = _is_subscription(report_state)
usage = _llm_usage(report_state)
if not usage or _int_stat(usage, "requests") <= 0:
stats_text.append("\n")
stats_text.append("Cost ", style="dim")
stats_text.append("$0.0000 ", style="#fbbf24")
if subscription:
stats_text.append("$0.00 ", style="#22c55e")
stats_text.append("(subscription) ", style="dim")
else:
stats_text.append("$0.0000 ", style="#fbbf24")
stats_text.append("· ", style="dim white")
stats_text.append("Tokens ", style="dim")
stats_text.append("0", style="white")
@@ -312,7 +331,12 @@ def _build_llm_usage_stats(
stats_text.append("Output Tokens ", style="dim")
stats_text.append(format_token_count(output_tokens), style="white")
if live or cost > 0:
if subscription:
stats_text.append(" · ", style="dim white")
stats_text.append("Cost ", style="dim")
stats_text.append("$0.00", style="#22c55e")
stats_text.append(" (subscription)", style="dim")
elif live or cost > 0:
stats_text.append(" · ", style="dim white")
stats_text.append("Cost ", style="dim")
stats_text.append(f"${cost:.4f}", style="#fbbf24")
@@ -337,6 +361,9 @@ def build_live_stats_text(report_state: Any) -> Text:
model = load_settings().llm.model or "unknown"
stats_text.append("Model ", style="dim")
stats_text.append(str(model), style="white")
if _is_subscription(report_state):
stats_text.append(" · ", style="dim white")
stats_text.append("ChatGPT subscription", style="#22c55e")
stats_text.append("\n")
vuln_count = len(report_state.vulnerability_reports)
@@ -379,6 +406,10 @@ def build_tui_stats_text(report_state: Any) -> Text:
model = load_settings().llm.model or "unknown"
stats_text.append(str(model), style="white")
subscription = _is_subscription(report_state)
if subscription:
stats_text.append("\n")
stats_text.append("ChatGPT subscription", style="#22c55e")
usage = _llm_usage(report_state)
if usage and _int_stat(usage, "total_tokens") > 0:
@@ -388,7 +419,10 @@ def build_tui_stats_text(report_state: Any) -> Text:
style="white",
)
cost = _float_stat(usage, "cost")
if cost > 0:
if subscription:
stats_text.append(" · ", style="white")
stats_text.append("$0.00", style="white")
elif cost > 0:
stats_text.append(" · ", style="white")
stats_text.append(f"${cost:.2f}", style="white")
@@ -1147,9 +1181,7 @@ def read_target_list_file(path_str: str) -> list[str]:
if (target := line.strip()) and not target.startswith("#")
]
except UnicodeDecodeError as e:
raise ValueError(
f"Target list file '{path_str}' must be valid UTF-8 text: {e!s}"
) from e
raise ValueError(f"Target list file '{path_str}' must be valid UTF-8 text: {e!s}") from e
except OSError as e:
raise ValueError(f"Failed to read target list file '{path_str}': {e!s}") from e
+42 -8
View File
@@ -13,20 +13,55 @@ from openai.types.responses import ResponseOutputMessage
from strix.config import load_settings
from strix.config.models import (
DEFAULT_MODEL_RETRY,
StrixProvider,
configure_sdk_model_defaults,
request_timeout_extra_args,
)
from strix.core.inputs import make_model_settings
from strix.report.state import get_global_report_state
if TYPE_CHECKING:
from agents.items import ModelResponse
from strix.config.settings import DedupeSettings
logger = logging.getLogger(__name__)
def _dedupe_extra_args(dedupe: DedupeSettings) -> dict[str, str]:
"""Per-call credential + endpoint for the dedupe model.
Provider env vars and the global base URL are process-wide, so a
shared-provider dedupe key or a distinct dedupe endpoint can't be installed
globally without clobbering (or being clobbered by) the main model's
config. Passing them per call keeps the two apart. Only applies when a
dedicated dedupe model is configured.
"""
if not dedupe.model:
return {}
extra: dict[str, str] = {}
if dedupe.api_key and dedupe.api_key.strip():
extra["api_key"] = dedupe.api_key.strip()
if dedupe.api_base and dedupe.api_base.strip():
extra["api_base"] = dedupe.api_base.strip()
return extra
def _dedupe_model_settings(
dedupe: DedupeSettings, model_name: str, request_timeout: float | None
) -> ModelSettings:
settings = make_model_settings(
dedupe.reasoning_effort,
model_name=model_name,
force_required_tool_choice=False,
request_timeout=request_timeout,
)
extra = _dedupe_extra_args(dedupe)
if extra:
settings = settings.resolve(ModelSettings(extra_args=extra))
return settings
DEDUPE_SYSTEM_PROMPT = """You are an expert vulnerability report deduplication judge.
Your task is to determine if a candidate vulnerability report describes the SAME vulnerability
as any existing report.
@@ -286,13 +321,14 @@ async def check_duplicate(
try:
settings = load_settings()
model_name = settings.llm.model
dedupe = settings.dedupe
model_name = (dedupe.model or "").strip() or settings.llm.model
if not model_name:
return {
"is_duplicate": False,
"duplicate_id": "",
"confidence": 0.0,
"reason": "STRIX_LLM not configured; skipping dedupe check",
"reason": "No LLM model configured; skipping dedupe check",
}
candidate_cleaned = _prepare_report_for_comparison(candidate)
@@ -311,10 +347,8 @@ async def check_duplicate(
response = await model.get_response(
system_instructions=DEDUPE_SYSTEM_PROMPT,
input=user_msg,
model_settings=ModelSettings(
retry=DEFAULT_MODEL_RETRY,
include_usage=True,
extra_args=request_timeout_extra_args(settings.llm.timeout),
model_settings=_dedupe_model_settings(
dedupe, resolved_model, settings.llm.timeout
),
tools=[],
output_schema=None,
+5
View File
@@ -10,6 +10,8 @@ from uuid import uuid4
from agents.usage import Usage
from strix.config import codex
from strix.config.loader import load_settings
from strix.core.paths import run_dir_for
from strix.report.sarif import write_sarif
from strix.report.usage import LLMUsageLedger
@@ -117,12 +119,15 @@ class ReportState:
self.scan_results: dict[str, Any] | None = None
self.scan_config: dict[str, Any] | None = None
self._llm_usage = LLMUsageLedger()
auth_mode = codex.auth_mode(load_settings().llm.model)
self._llm_usage.zero_cost = auth_mode == "subscription"
self.run_record: dict[str, Any] = {
"run_id": self.run_id,
"run_name": self.run_name,
"start_time": self.start_time,
"end_time": None,
"status": "running",
"auth_mode": auth_mode,
"targets_info": [],
"llm_usage": self._build_llm_usage_record(),
}
+6 -1
View File
@@ -19,6 +19,9 @@ class LLMUsageLedger:
self._agent_usage: dict[str, Usage] = {}
self._agent_metadata: dict[str, dict[str, str]] = {}
self._total_cost = 0.0
# When True, tokens are still tracked but cost stays $0 — the run is on a
# model subscription, so there is no metered per-token charge to report.
self.zero_cost = False
def record(
self,
@@ -41,7 +44,7 @@ class LLMUsageLedger:
if model:
metadata["model"] = model
if not _is_litellm_routed(model):
if not self.zero_cost and not _is_litellm_routed(model):
estimated = _estimate_litellm_cost(usage, model)
if estimated:
self._total_cost += estimated
@@ -49,6 +52,8 @@ class LLMUsageLedger:
return True
def record_observed_cost(self, cost: float) -> None:
if self.zero_cost:
return
if isinstance(cost, int | float) and cost > 0:
self._total_cost += float(cost)
+65 -6
View File
@@ -10,19 +10,27 @@ import re
import tempfile
from datetime import UTC, datetime
from pathlib import Path
from typing import Any
from typing import TYPE_CHECKING, Any, cast
from pygments.lexers import PythonLexer, get_lexer_by_name, guess_lexer
from pygments.lexers.special import TextLexer
from pygments.util import ClassNotFound
from strix.core.paths import run_record_path
if TYPE_CHECKING:
from pygments.lexer import Lexer
logger = logging.getLogger(__name__)
_SEVERITY_ORDER = {"critical": 0, "high": 1, "medium": 2, "low": 3, "info": 4}
_FENCE_RE = re.compile(r"^```([^\n`]*)\r?\n(.*?)\r?\n?```$", re.DOTALL)
_BACKTICK_RUN = re.compile(r"`+")
def _safe_fence(content: str) -> str:
def safe_fence(content: str) -> str:
"""Return a backtick fence that ``content`` cannot break out of.
Per CommonMark a fenced code block is closed only by a run of backticks at
@@ -35,6 +43,56 @@ def _safe_fence(content: str) -> str:
return "`" * max(3, longest + 1)
def parse_fenced_code(raw: str) -> tuple[str | None, str]:
"""Split an optionally fenced code string into ``(language, code)``.
Agent-generated code fields (e.g. ``poc_script_code``) are stored wrapped in
a markdown fence carrying the language, like ``` ```python\n...\n``` ```.
Return the fence's language tag and the inner code, or ``(None, raw)`` when
the value isn't fenced.
"""
match = _FENCE_RE.match(raw.strip())
if not match:
return None, raw
info = match.group(1).strip()
language = info.split()[0] if info else None
return (language or None), match.group(2)
def resolve_lexer(language: str | None, code: str) -> Lexer:
"""Pick a pygments lexer for ``code``.
Prefer the explicit fence ``language`` when it names a known lexer, otherwise
auto-detect from the source. Fall back to Python when detection is
inconclusive, since legacy (unfenced) PoC scripts are Python.
"""
if language:
try:
return get_lexer_by_name(language)
except ClassNotFound:
pass
try:
lexer = guess_lexer(code)
except ClassNotFound:
return cast("Lexer", PythonLexer())
# ``guess_lexer`` returns the plain-text lexer when it can't detect anything.
if isinstance(lexer, TextLexer):
return cast("Lexer", PythonLexer())
return lexer
def guess_language_name(code: str) -> str:
"""Return a markdown fence tag for ``code``, defaulting to ``python`` when
auto-detection is inconclusive."""
try:
lexer = guess_lexer(code)
except ClassNotFound:
return "python"
if isinstance(lexer, TextLexer) or not lexer.aliases:
return "python"
return str(lexer.aliases[0])
def read_run_record(run_dir: Path) -> dict[str, Any]:
path = run_record_path(run_dir)
if not path.exists():
@@ -187,9 +245,10 @@ def render_vulnerability_md(report: dict[str, Any]) -> str: # noqa: PLR0912, PL
lines.append(str(report["poc_description"]))
lines.append("")
if report.get("poc_script_code"):
code = str(report["poc_script_code"])
fence = _safe_fence(code)
lines.append(fence)
language, code = parse_fenced_code(str(report["poc_script_code"]))
fence_lang = language or guess_language_name(code)
fence = safe_fence(code)
lines.append(f"{fence}{fence_lang}")
lines.append(code)
lines.append(fence)
lines.append("")
@@ -209,7 +268,7 @@ def render_vulnerability_md(report: dict[str, Any]) -> str: # noqa: PLR0912, PL
lines.append(f" {loc['label']}")
if loc.get("snippet"):
snippet = str(loc["snippet"])
fence = _safe_fence(snippet)
fence = safe_fence(snippet)
lines.append(f" {fence}")
lines.extend(f" {ln}" for ln in snippet.splitlines())
lines.append(f" {fence}")
+1 -1
View File
@@ -110,7 +110,7 @@ def stage_symlink_safe_dir(src_root: Path) -> tuple[Path, Path | None]:
if not tree_has_symlink(root):
return root, None
staged = Path(tempfile.mkdtemp(prefix=_STAGING_PREFIX))
staged = Path(tempfile.mkdtemp(prefix=_STAGING_PREFIX)).resolve()
try:
_stage_dir(root, staged, root, frozenset({root}))
except OSError:
+1 -1
View File
@@ -15,7 +15,7 @@ We collect only very **basic** usage data including:
**Session Errors:** Duration and error types (not messages or stack traces)\
**System Context:** OS type, architecture, Strix version\
**Scan Context:** Scan mode (quick/standard/deep), scan type (whitebox/blackbox)\
**Model Usage:** Which LLM model is being used (not prompts or responses)\
**Model Usage:** Which LLM model is being used and whether it runs via an API key or a model subscription (not prompts or responses)\
**Feature Usage:** Which built-in skills are loaded\
**Aggregate Metrics:** Vulnerability counts by severity and weakness category (CWE)
+3
View File
@@ -58,12 +58,14 @@ def start(
is_whitebox: bool,
interactive: bool,
has_instructions: bool,
auth_mode: str | None = None,
) -> None:
_send(
"scan_started",
{
**base_props(),
"model": model or "unknown",
"auth_mode": auth_mode or "api_key",
"scan_mode": scan_mode or "unknown",
"scan_type": "whitebox" if is_whitebox else "blackbox",
"interactive": interactive,
@@ -133,6 +135,7 @@ def end(report_state: "ReportState", exit_reason: str = "completed") -> None:
"scan_ended",
{
**base_props(),
"auth_mode": report_state.run_record.get("auth_mode") or "api_key",
"exit_reason": report_state.scan_ended_exit_reason,
"duration_seconds": round(duration),
"vulnerabilities_total": len(report_state.vulnerability_reports),
+3
View File
@@ -59,6 +59,7 @@ def start(
is_whitebox: bool,
interactive: bool,
has_instructions: bool,
auth_mode: str | None = None,
) -> None:
_send(
"scan_started",
@@ -66,6 +67,7 @@ def start(
**base_props(),
"session": SESSION_ID,
"model": model or "unknown",
"auth_mode": auth_mode or "api_key",
"scan_mode": scan_mode or "unknown",
"scan_type": "whitebox" if is_whitebox else "blackbox",
"interactive": interactive,
@@ -140,6 +142,7 @@ def end(report_state: ReportState, exit_reason: str = "completed") -> None:
{
**base_props(),
"session": SESSION_ID,
"auth_mode": report_state.run_record.get("auth_mode") or "api_key",
"exit_reason": report_state.scan_ended_exit_reason,
"duration_seconds": round(duration),
"vulnerabilities_total": len(report_state.vulnerability_reports),
+2 -2
View File
@@ -87,7 +87,7 @@ async def view_agent_graph(ctx: RunContextWrapper) -> str:
default=str,
)
parent_of, statuses, names = await coordinator.graph_snapshot()
parent_of, statuses, names, _ = await coordinator.graph_snapshot()
lines: list[str] = []
@@ -635,7 +635,7 @@ async def stop_agent(
ensure_ascii=False,
default=str,
)
_, statuses, _ = await coordinator.graph_snapshot()
_, statuses, _, _ = await coordinator.graph_snapshot()
if target_agent_id not in statuses:
return json.dumps(
{"success": False, "error": f"Unknown agent_id: {target_agent_id}"},
+74
View File
@@ -0,0 +1,74 @@
"""Bound oversized tool results before they enter agent history.
Keeps a head + tail slice and drops the middle, replacing it with a notice of
how much was removed.
"""
from __future__ import annotations
_TRUNCATION_NOTICE = "[... {lines} lines ({bytes} bytes) truncated ...]"
def _byte_len(text: str) -> int:
return len(text.encode("utf-8"))
def _take_prefix(text: str, max_bytes: int) -> str:
budget = 0
out: list[str] = []
for char in text:
size = len(char.encode("utf-8"))
if budget + size > max_bytes:
break
out.append(char)
budget += size
return "".join(out)
def _take_suffix(text: str, max_bytes: int) -> str:
budget = 0
out: list[str] = []
for char in reversed(text):
size = len(char.encode("utf-8"))
if budget + size > max_bytes:
break
out.append(char)
budget += size
out.reverse()
return "".join(out)
def bound_text(text: str, *, max_lines: int, max_bytes: int) -> str:
"""Return ``text`` unchanged when small, else a head+tail preview.
Truncates on whichever limit is hit first (line count or UTF-8 byte size).
``max_bytes`` bounds the entire joined result, notice and separators
included.
"""
lines = text.split("\n")
total_bytes = _byte_len(text)
if len(lines) <= max_lines and total_bytes <= max_bytes:
return text
# Reserve notice + separator bytes up front; ``+ 4`` covers the two "\n\n".
notice_overhead = _byte_len(_TRUNCATION_NOTICE.format(lines=len(lines), bytes=total_bytes)) + 4
byte_budget = max(2, max_bytes - notice_overhead)
head_lines = max(1, max_lines // 2)
tail_lines = max_lines - head_lines
head = "\n".join(lines[:head_lines])
tail = "\n".join(lines[len(lines) - tail_lines :]) if tail_lines > 0 else ""
half_bytes = max(1, byte_budget // 2)
if _byte_len(head) > half_bytes:
head = _take_prefix(head, half_bytes)
if tail and _byte_len(tail) > half_bytes:
tail = _take_suffix(tail, half_bytes)
# Count from the final slices; the byte pass may have dropped whole lines.
kept_lines = len(head.split("\n")) + (len(tail.split("\n")) if tail else 0)
dropped_lines = max(0, len(lines) - kept_lines)
dropped_bytes = max(0, total_bytes - _byte_len(head) - _byte_len(tail))
notice = _TRUNCATION_NOTICE.format(lines=dropped_lines, bytes=dropped_bytes)
return f"{head}\n\n{notice}\n\n{tail}" if tail else f"{head}\n\n{notice}"
-9
View File
@@ -63,7 +63,6 @@
"integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/code-frame": "^7.29.7",
"@babel/generator": "^7.29.7",
@@ -1605,7 +1604,6 @@
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.17.tgz",
"integrity": "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==",
"license": "MIT",
"peer": true,
"dependencies": {
"csstype": "^3.2.2"
}
@@ -1616,7 +1614,6 @@
"integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
"devOptional": true,
"license": "MIT",
"peer": true,
"peerDependencies": {
"@types/react": "^19.2.0"
}
@@ -1739,7 +1736,6 @@
}
],
"license": "MIT",
"peer": true,
"dependencies": {
"baseline-browser-mapping": "^2.10.42",
"caniuse-lite": "^1.0.30001803",
@@ -1920,7 +1916,6 @@
"resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz",
"integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==",
"license": "ISC",
"peer": true,
"engines": {
"node": ">=12"
}
@@ -3571,7 +3566,6 @@
"integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==",
"dev": true,
"license": "MIT",
"peer": true,
"engines": {
"node": ">=12"
},
@@ -3623,7 +3617,6 @@
"resolved": "https://registry.npmjs.org/react/-/react-19.2.7.tgz",
"integrity": "sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==",
"license": "MIT",
"peer": true,
"engines": {
"node": ">=0.10.0"
}
@@ -3633,7 +3626,6 @@
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.7.tgz",
"integrity": "sha512-t0BRVXvbiE/o20Hfw669rLbMCDWtYZLvmJigy2f0MxsXF+71pxhR3xOkspmsO8h3ZlNzyibAmtCa3l4lYKk6gQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"scheduler": "^0.27.0"
},
@@ -4109,7 +4101,6 @@
"integrity": "sha512-NTKlcQjlAK7MlQoyb6LgaqHc8sso/pVyUJYWMws3jg21uTJw/LddqIFPcPqP6PzpgbIcZyKI85sFE4HBrQDA8A==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"esbuild": "^0.25.0",
"fdir": "^6.4.4",
@@ -100,6 +100,7 @@ export function RunDetails({
const reasoning = num(rec(arr(usage.output_tokens_details)[0]).reasoning_tokens);
const totalTokens = num(usage.total_tokens);
const cost = num(usage.cost);
const subscription = str(raw.auth_mode) === "subscription";
const sub = (n: number, word: string) => (
<span className="text-[#666]"> ({formatNumber(n)} {word})</span>
@@ -175,6 +176,15 @@ export function RunDetails({
{hasUsage ? (
<dl className="space-y-2.5 tabular-nums">
<Field label="Model">{models.length ? models.join(", ") : "n/a"}</Field>
{subscription && (
<Field label="Provider">
<span className="inline-flex items-center gap-1.5">
<span className="rounded-full border border-[#22c55e]/40 bg-[#22c55e]/10 px-2 py-0.5 text-[11px] text-[#22c55e]">
ChatGPT subscription
</span>
</span>
</Field>
)}
<Field label="Run time">{fmtDuration(durationSeconds)}</Field>
{requests != null && <Field label="Requests">{formatNumber(requests)}</Field>}
{inputTokens != null && (
@@ -190,7 +200,14 @@ export function RunDetails({
</Field>
)}
{totalTokens != null && <Field label="Total tokens">{formatNumber(totalTokens)}</Field>}
{cost != null && <Field label="Cost">${cost.toFixed(2)}</Field>}
{subscription ? (
<Field label="Cost">
<span className="text-[#22c55e]">$0.00</span>
<span className="text-[#666]"> (subscription)</span>
</Field>
) : (
cost != null && <Field label="Cost">${cost.toFixed(2)}</Field>
)}
{agents.length > 0 && <Field label="Agents">{formatNumber(agents.length)}</Field>}
</dl>
) : (
@@ -3,6 +3,7 @@
import type { ToolRendererProps } from "@/types/events";
import { TruncatedText } from "./ToolCard";
import { MdCodeBlock } from "@/components/vulnerability/MdCodeBlock";
import { parseFencedCode } from "@/lib/fenced-code";
import Markdown from "./Markdown";
const SEVERITY_COLORS: Record<string, string> = {
@@ -19,7 +20,7 @@ export default function VulnReportRenderer({ args, result }: ToolRendererProps)
const method = (args.method as string) ?? "";
const technicalAnalysis = (args.technical_analysis as string) ?? "";
const pocDescription = (args.poc_description as string) ?? "";
const pocCode = (args.poc_script_code as string) ?? "";
const { language: pocLang, code: pocCode } = parseFencedCode((args.poc_script_code as string) ?? "");
const remediation = (args.remediation_steps as string) ?? "";
const cve = (args.cve as string) ?? "";
const cwe = (args.cwe as string) ?? "";
@@ -59,7 +60,7 @@ export default function VulnReportRenderer({ args, result }: ToolRendererProps)
<div>
<span className="text-emerald-400/60 text-sm font-semibold">Proof of Concept</span>
{pocDescription && <div className="mt-1"><Markdown text={pocDescription} /></div>}
{pocCode && <MdCodeBlock>{pocCode}</MdCodeBlock>}
{pocCode && <MdCodeBlock className={pocLang ? `language-${pocLang}` : undefined}>{pocCode}</MdCodeBlock>}
</div>
)}
{remediation && (
@@ -1,7 +1,7 @@
"use client";
import { useState } from "react";
import hljs from "@/lib/hljs";
import { highlightCode } from "@/lib/hljs";
import "highlight.js/styles/github-dark.css";
import { Copy, Check } from "lucide-react";
import { copyToClipboard } from "@/lib/vulnerability-utils";
@@ -17,7 +17,7 @@ export function MdCodeBlock({
}) {
const [copied, setCopied] = useState(false);
const raw = String(children).replace(/\n$/, "");
const match = /language-(\w+)/.exec(className || "");
const match = /language-(\S+)/.exec(className || "");
const isBlock = raw.includes("\n") || match;
if (!isBlock) {
@@ -35,16 +35,7 @@ export function MdCodeBlock({
: fileName
: null;
let highlighted: string;
if (match) {
try {
highlighted = hljs.highlight(raw, { language: match[1], ignoreIllegals: true }).value;
} catch {
highlighted = hljs.highlightAuto(raw).value;
}
} else {
highlighted = hljs.highlightAuto(raw).value;
}
const highlighted = highlightCode(raw, match?.[1]);
const lines = highlighted.split("\n");
@@ -1,12 +1,13 @@
"use client";
import { useState } from "react";
import hljs from "@/lib/hljs";
import { highlightCode } from "@/lib/hljs";
import "highlight.js/styles/github-dark.css";
import ReactMarkdown from "react-markdown";
import remarkGfm from "remark-gfm";
import { Copy, Check } from "lucide-react";
import { copyToClipboard } from "@/lib/vulnerability-utils";
import { parseFencedCode } from "@/lib/fenced-code";
import { rehypeCodeMeta, mdComponents } from "./MdCodeBlock";
interface PocBlockProps {
@@ -20,9 +21,12 @@ export function PocBlock({ description, scriptCode, onCopy }: PocBlockProps) {
if (!description && !scriptCode) return null;
const { language, code } = parseFencedCode(scriptCode);
const highlighted = highlightCode(code, language);
const copy = () => {
if (!scriptCode) return;
copyToClipboard(scriptCode);
if (!code) return;
copyToClipboard(code);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
onCopy?.();
@@ -43,7 +47,7 @@ export function PocBlock({ description, scriptCode, onCopy }: PocBlockProps) {
</ReactMarkdown>
</div>
)}
{scriptCode && (
{code && (
<div className="group/poc relative rounded-md border border-[#2a2a2a] overflow-hidden">
<div className="flex items-stretch">
<span className="relative flex items-center text-[13px] text-[#999] font-mono px-4 py-2 border-r border-[#2a2a2a]">PoC Script<span className="absolute top-0 inset-x-0 h-0.5 bg-white/60 rounded-full" /></span>
@@ -64,7 +68,7 @@ export function PocBlock({ description, scriptCode, onCopy }: PocBlockProps) {
<pre className="font-mono text-[12px] leading-[22px] whitespace-pre [font-variant-ligatures:none]">
<code
dangerouslySetInnerHTML={{
__html: hljs.highlight(scriptCode, { language: "python" }).value,
__html: highlighted,
}}
/>
</pre>
@@ -0,0 +1,27 @@
export interface ParsedFencedCode {
language?: string;
code: string;
}
const FENCE_RE = /^```([^\n`]*)\r?\n([\s\S]*?)\r?\n?```$/;
/**
* Agent-generated `poc_script_code` is stored wrapped in a markdown code fence
* that carries the language, e.g.
*
* ```python
* import requests
* ```
*
* Renderers that show the value as bare code must not display the fence lines
* literally. This extracts the inner code and the fence's language tag. Returns
* the input unchanged (no language) when it isn't fenced.
*/
export function parseFencedCode(raw: string | null | undefined): ParsedFencedCode {
if (!raw) return { code: "" };
const match = FENCE_RE.exec(raw.trim());
if (!match) return { code: raw };
const info = match[1].trim();
const language = info ? info.split(/\s+/)[0] : undefined;
return { language: language || undefined, code: match[2] };
}
+18
View File
@@ -11,4 +11,22 @@ hljs.registerLanguage("apache", apache);
hljs.registerLanguage("dockerfile", dockerfile);
hljs.registerLanguage("properties", properties);
/**
* Highlight code, preferring an explicit language when it's recognized,
* otherwise auto-detecting. Falls back to Python when auto-detection is
* inconclusive, since legacy (unfenced) PoC scripts are Python.
*/
export function highlightCode(code: string, language?: string | null): string {
try {
if (language && hljs.getLanguage(language)) {
return hljs.highlight(code, { language, ignoreIllegals: true }).value;
}
const auto = hljs.highlightAuto(code);
if (auto.language) return auto.value;
return hljs.highlight(code, { language: "python", ignoreIllegals: true }).value;
} catch {
return hljs.highlight(code, { language: "python", ignoreIllegals: true }).value;
}
}
export default hljs;
+72 -18
View File
@@ -151,19 +151,35 @@ def _styles() -> dict[str, ParagraphStyle]:
"Finding", fontName=_SANS_BOLD, fontSize=13, leading=17, textColor=_INK, spaceBefore=6
)
styles["field_label"] = ParagraphStyle(
"FieldLabel", fontName=_SANS_BOLD, fontSize=8.5, leading=12, textColor=_MUTED,
spaceBefore=10, spaceAfter=2,
"FieldLabel",
fontName=_SANS_BOLD,
fontSize=8.5,
leading=12,
textColor=_MUTED,
spaceBefore=10,
spaceAfter=2,
)
styles["body"] = ParagraphStyle(
"Body", fontName=_SANS, fontSize=10, leading=15, textColor=_TEXT, spaceAfter=8
)
styles["md_heading"] = ParagraphStyle(
"MdHeading", fontName=_SANS_BOLD, fontSize=11, leading=15, textColor=_INK,
spaceBefore=10, spaceAfter=4,
"MdHeading",
fontName=_SANS_BOLD,
fontSize=11,
leading=15,
textColor=_INK,
spaceBefore=10,
spaceAfter=4,
)
styles["bullet"] = ParagraphStyle(
"Bullet", fontName=_SANS, fontSize=10, leading=15, textColor=_TEXT,
leftIndent=16, firstLineIndent=-11, spaceAfter=3,
"Bullet",
fontName=_SANS,
fontSize=10,
leading=15,
textColor=_TEXT,
leftIndent=16,
firstLineIndent=-11,
spaceAfter=3,
)
styles["meta_inline"] = ParagraphStyle(
"MetaInline", fontName=_SANS, fontSize=9, leading=13, textColor=_MUTED, spaceBefore=4
@@ -172,23 +188,44 @@ def _styles() -> dict[str, ParagraphStyle]:
# a bordered paragraph's top padding, so too small a gap lets the background
# box bleed up over the field label above it.
styles["code"] = ParagraphStyle(
"Code", fontName=_MONO, fontSize=8, leading=11, textColor=_TEXT,
backColor=_LIGHT_BG, borderColor=_BORDER, borderWidth=0.5, borderPadding=8,
spaceBefore=12, spaceAfter=12,
"Code",
fontName=_MONO,
fontSize=8,
leading=11,
textColor=_TEXT,
backColor=_LIGHT_BG,
borderColor=_BORDER,
borderWidth=0.5,
borderPadding=8,
spaceBefore=12,
spaceAfter=12,
)
styles["count"] = ParagraphStyle(
"Count", fontName=_SANS_BOLD, fontSize=30, leading=32, alignment=TA_CENTER
)
styles["count_label"] = ParagraphStyle(
"CountLabel", fontName=_SANS_BOLD, fontSize=8, leading=12, textColor=_MUTED,
alignment=TA_CENTER, spaceBefore=4,
"CountLabel",
fontName=_SANS_BOLD,
fontSize=8,
leading=12,
textColor=_MUTED,
alignment=TA_CENTER,
spaceBefore=4,
)
styles["badge"] = ParagraphStyle(
"Badge", fontName=_SANS_BOLD, fontSize=9, leading=11, textColor=colors.white,
"Badge",
fontName=_SANS_BOLD,
fontSize=9,
leading=11,
textColor=colors.white,
alignment=TA_CENTER,
)
styles["confidential"] = ParagraphStyle(
"Confidential", fontName=_SANS_BOLD, fontSize=9, leading=12, textColor=colors.white,
"Confidential",
fontName=_SANS_BOLD,
fontSize=9,
leading=12,
textColor=colors.white,
alignment=TA_CENTER,
)
return styles
@@ -256,8 +293,10 @@ def _severity_grid(styles: dict[str, ParagraphStyle], counts: dict[str, int]) ->
color = _SEVERITY_COLORS[name]
count_style = ParagraphStyle(f"Count{name}", parent=styles["count"], textColor=color)
cells.append(
[Paragraph(str(counts.get(name, 0)), count_style),
Paragraph(name.upper(), styles["count_label"])]
[
Paragraph(str(counts.get(name, 0)), count_style),
Paragraph(name.upper(), styles["count_label"]),
]
)
col = (_PAGE_W - 40 * mm) / 4
table = Table([cells], colWidths=[col] * 4)
@@ -320,8 +359,10 @@ def _cover(
("DURATION", _duration(record.get("start_time"), record.get("end_time"))),
]
meta_table = Table(
[[Paragraph(label, styles["meta_label"]), Paragraph(_esc(value), styles["meta_value"])]
for label, value in meta_rows],
[
[Paragraph(label, styles["meta_label"]), Paragraph(_esc(value), styles["meta_value"])]
for label, value in meta_rows
],
colWidths=[38 * mm, _PAGE_W - 40 * mm - 38 * mm],
)
meta_table.setStyle(
@@ -462,6 +503,18 @@ def _markdown_flowables( # noqa: PLR0915 - cohesive block parser, splitting hur
return flow
_FENCE_RE = re.compile(r"^```([^\n`]*)\n(.*?)\n?```$", re.DOTALL)
def _strip_code_fence(value: Any) -> Any:
"""Drop a wrapping markdown code fence so raw-code fields don't show the
``` ```lang ``` marker lines literally in the PDF."""
if not isinstance(value, str):
return value
match = _FENCE_RE.match(value.strip())
return match.group(2) if match else value
def _field_block(
styles: dict[str, ParagraphStyle], label: str, value: Any, *, code: bool = False
) -> list[Flowable]:
@@ -503,7 +556,8 @@ def _finding_flowables(
story.extend(_field_block(styles, "Impact", vuln.get("impact")))
story.extend(_field_block(styles, "Technical analysis", vuln.get("technical_analysis")))
story.extend(_field_block(styles, "Proof of concept", vuln.get("poc_description")))
story.extend(_field_block(styles, "PoC script", vuln.get("poc_script_code"), code=True))
poc_script = _strip_code_fence(vuln.get("poc_script_code"))
story.extend(_field_block(styles, "PoC script", poc_script, code=True))
story.extend(_field_block(styles, "Evidence", vuln.get("evidence"), code=True))
remediation = vuln.get("remediation_steps")
@@ -1,10 +0,0 @@
pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}/*!
Theme: GitHub Dark
Description: Dark theme as seen on github.com
Author: github.com
Maintainer: @Hirse
Updated: 2021-05-15
Outdated base version: https://github.com/primer/github-syntax-dark
Current colors taken from GitHub's CSS
*/.hljs{color:#c9d1d9;background:#0d1117}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#ff7b72}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#d2a8ff}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-variable,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id{color:#79c0ff}.hljs-regexp,.hljs-string,.hljs-meta .hljs-string{color:#a5d6ff}.hljs-built_in,.hljs-symbol{color:#ffa657}.hljs-comment,.hljs-code,.hljs-formula{color:#8b949e}.hljs-name,.hljs-quote,.hljs-selector-tag,.hljs-selector-pseudo{color:#7ee787}.hljs-subst{color:#c9d1d9}.hljs-section{color:#1f6feb;font-weight:700}.hljs-bullet{color:#f2cc60}.hljs-emphasis{color:#c9d1d9;font-style:italic}.hljs-strong{color:#c9d1d9;font-weight:700}.hljs-addition{color:#aff5b4;background-color:#033a16}.hljs-deletion{color:#ffdcd7;background-color:#67060c}.react-flow{direction:ltr;--xy-edge-stroke-default: #b1b1b7;--xy-edge-stroke-width-default: 1;--xy-edge-stroke-selected-default: #555;--xy-connectionline-stroke-default: #b1b1b7;--xy-connectionline-stroke-width-default: 1;--xy-attribution-background-color-default: rgba(255, 255, 255, .5);--xy-minimap-background-color-default: #fff;--xy-minimap-mask-background-color-default: rgba(240, 240, 240, .6);--xy-minimap-mask-stroke-color-default: transparent;--xy-minimap-mask-stroke-width-default: 1;--xy-minimap-node-background-color-default: #e2e2e2;--xy-minimap-node-stroke-color-default: transparent;--xy-minimap-node-stroke-width-default: 2;--xy-background-color-default: transparent;--xy-background-pattern-dots-color-default: #91919a;--xy-background-pattern-lines-color-default: #eee;--xy-background-pattern-cross-color-default: #e2e2e2;background-color:var(--xy-background-color, var(--xy-background-color-default));--xy-node-color-default: inherit;--xy-node-border-default: 1px solid #1a192b;--xy-node-background-color-default: #fff;--xy-node-group-background-color-default: rgba(240, 240, 240, .25);--xy-node-boxshadow-hover-default: 0 1px 4px 1px rgba(0, 0, 0, .08);--xy-node-boxshadow-selected-default: 0 0 0 .5px #1a192b;--xy-node-border-radius-default: 3px;--xy-handle-background-color-default: #1a192b;--xy-handle-border-color-default: #fff;--xy-selection-background-color-default: rgba(0, 89, 220, .08);--xy-selection-border-default: 1px dotted rgba(0, 89, 220, .8);--xy-controls-button-background-color-default: #fefefe;--xy-controls-button-background-color-hover-default: #f4f4f4;--xy-controls-button-color-default: inherit;--xy-controls-button-color-hover-default: inherit;--xy-controls-button-border-color-default: #eee;--xy-controls-box-shadow-default: 0 0 2px 1px rgba(0, 0, 0, .08);--xy-edge-label-background-color-default: #ffffff;--xy-edge-label-color-default: inherit;--xy-resize-background-color-default: #3367d9}.react-flow.dark{--xy-edge-stroke-default: #3e3e3e;--xy-edge-stroke-width-default: 1;--xy-edge-stroke-selected-default: #727272;--xy-connectionline-stroke-default: #b1b1b7;--xy-connectionline-stroke-width-default: 1;--xy-attribution-background-color-default: rgba(150, 150, 150, .25);--xy-minimap-background-color-default: #141414;--xy-minimap-mask-background-color-default: rgba(60, 60, 60, .6);--xy-minimap-mask-stroke-color-default: transparent;--xy-minimap-mask-stroke-width-default: 1;--xy-minimap-node-background-color-default: #2b2b2b;--xy-minimap-node-stroke-color-default: transparent;--xy-minimap-node-stroke-width-default: 2;--xy-background-color-default: #141414;--xy-background-pattern-dots-color-default: #555;--xy-background-pattern-lines-color-default: #333;--xy-background-pattern-cross-color-default: #333;--xy-node-color-default: #f8f8f8;--xy-node-border-default: 1px solid #3c3c3c;--xy-node-background-color-default: #1e1e1e;--xy-node-group-background-color-default: rgba(240, 240, 240, .25);--xy-node-boxshadow-hover-default: 0 1px 4px 1px rgba(255, 255, 255, .08);--xy-node-boxshadow-selected-default: 0 0 0 .5px #999;--xy-handle-background-color-default: #bebebe;--xy-handle-border-color-default: #1e1e1e;--xy-selection-background-color-default: rgba(200, 200, 220, .08);--xy-selection-border-default: 1px dotted rgba(200, 200, 220, .8);--xy-controls-button-background-color-default: #2b2b2b;--xy-controls-button-background-color-hover-default: #3e3e3e;--xy-controls-button-color-default: #f8f8f8;--xy-controls-button-color-hover-default: #fff;--xy-controls-button-border-color-default: #5b5b5b;--xy-controls-box-shadow-default: 0 0 2px 1px rgba(0, 0, 0, .08);--xy-edge-label-background-color-default: #141414;--xy-edge-label-color-default: #f8f8f8}.react-flow__background{background-color:var(--xy-background-color-props, var(--xy-background-color, var(--xy-background-color-default)));pointer-events:none;z-index:-1}.react-flow__container{position:absolute;width:100%;height:100%;top:0;left:0}.react-flow__pane{z-index:1;touch-action:none}.react-flow__panLine truncated
@@ -1,4 +1,4 @@
(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const s of document.querySelectorAll('link[rel="modulepreload"]'))a(s);new MutationObserver(s=>{for(const o of s)if(o.type==="childList")for(const c of o.addedNodes)c.tagName==="LINK"&&c.rel==="modulepreload"&&a(c)}).observe(document,{childList:!0,subtree:!0});function r(s){const o={};return s.integrity&&(o.integrity=s.integrity),s.referrerPolicy&&(o.referrerPolicy=s.referrerPolicy),s.crossOrigin==="use-credentials"?o.credentials="include":s.crossOrigin==="anonymous"?o.credentials="omit":o.credentials="same-origin",o}function a(s){if(s.ep)return;s.ep=!0;const o=r(s);fetch(s.href,o)}})();function To(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var oh={exports:{}},Yl={};/**
(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const s of document.querySelectorAll('link[rel="modulepreload"]'))a(s);new MutationObserver(s=>{for(const o of s)if(o.type==="childList")for(const c of o.addedNodes)c.tagName==="LINK"&&c.rel==="modulepreload"&&a(c)}).observe(document,{childList:!0,subtree:!0});function r(s){const o={};return s.integrity&&(o.integrity=s.integrity),s.referrerPolicy&&(o.referrerPolicy=s.referrerPolicy),s.crossOrigin==="use-credentials"?o.credentials="include":s.crossOrigin==="anonymous"?o.credentials="omit":o.credentials="same-origin",o}function a(s){if(s.ep)return;s.ep=!0;const o=r(s);fetch(s.href,o)}})();function Co(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var oh={exports:{}},Yl={};/**
* @license React
* react-jsx-runtime.production.js
*
@@ -6,7 +6,7 @@
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/var F0;function pk(){if(F0)return Yl;F0=1;var e=Symbol.for("react.transitional.element"),t=Symbol.for("react.fragment");function r(a,s,o){var c=null;if(o!==void 0&&(c=""+o),s.key!==void 0&&(c=""+s.key),"key"in s){o={};for(var d in s)d!=="key"&&(o[d]=s[d])}else o=s;return s=o.ref,{$$typeof:e,type:a,key:c,ref:s!==void 0?s:null,props:o}}return Yl.Fragment=t,Yl.jsx=r,Yl.jsxs=r,Yl}var G0;function gk(){return G0||(G0=1,oh.exports=pk()),oh.exports}var g=gk(),ch={exports:{}},Ve={};/**
*/var F0;function bk(){if(F0)return Yl;F0=1;var e=Symbol.for("react.transitional.element"),t=Symbol.for("react.fragment");function r(a,s,o){var c=null;if(o!==void 0&&(c=""+o),s.key!==void 0&&(c=""+s.key),"key"in s){o={};for(var d in s)d!=="key"&&(o[d]=s[d])}else o=s;return s=o.ref,{$$typeof:e,type:a,key:c,ref:s!==void 0?s:null,props:o}}return Yl.Fragment=t,Yl.jsx=r,Yl.jsxs=r,Yl}var G0;function xk(){return G0||(G0=1,oh.exports=bk()),oh.exports}var g=xk(),ch={exports:{}},Ve={};/**
* @license React
* react.production.js
*
@@ -14,7 +14,7 @@
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/var V0;function bk(){if(V0)return Ve;V0=1;var e=Symbol.for("react.transitional.element"),t=Symbol.for("react.portal"),r=Symbol.for("react.fragment"),a=Symbol.for("react.strict_mode"),s=Symbol.for("react.profiler"),o=Symbol.for("react.consumer"),c=Symbol.for("react.context"),d=Symbol.for("react.forward_ref"),f=Symbol.for("react.suspense"),h=Symbol.for("react.memo"),m=Symbol.for("react.lazy"),p=Symbol.for("react.activity"),y=Symbol.iterator;function x(j){return j===null||typeof j!="object"?null:(j=y&&j[y]||j["@@iterator"],typeof j=="function"?j:null)}var _={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},N=Object.assign,S={};function w(j,Y,L){this.props=j,this.context=Y,this.refs=S,this.updater=L||_}w.prototype.isReactComponent={},w.prototype.setState=function(j,Y){if(typeof j!="object"&&typeof j!="function"&&j!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,j,Y,"setState")},w.prototype.forceUpdate=function(j){this.updater.enqueueForceUpdate(this,j,"forceUpdate")};function k(){}k.prototype=w.prototype;function E(j,Y,L){this.props=j,this.context=Y,this.refs=S,this.updater=L||_}var M=E.prototype=new k;M.constructor=E,N(M,w.prototype),M.isPureReactComponent=!0;var I=Array.isArray;function R(){}var U={H:null,A:null,T:null,S:null},B=Object.prototype.hasOwnProperty;function Z(j,Y,L){var G=L.ref;return{$$typeof:e,type:j,key:Y,ref:G!==void 0?G:null,props:L}}function D(j,Y){return Z(j.type,Y,j.props)}function z(j){return typeof j=="object"&&j!==null&&j.$$typeof===e}function P(j){var Y={"=":"=0",":":"=2"};return"$"+j.replace(/[=:]/g,function(L){return Y[L]})}var V=/\/+/g;function A(j,Y){return typeof j=="object"&&j!==null&&j.key!=null?P(""+j.key):Y.toString(36)}function $(j){switch(j.status){case"fulfilled":return j.value;case"rejected":throw j.reason;default:switch(typeof j.status=="string"?j.then(R,R):(j.status="pending",j.then(function(Y){j.status==="pending"&&(j.status="fulfilled",j.value=Y)},function(Y){j.status==="pending"&&(j.status="rejected",j.reason=Y)})),j.status){case"fulfilled":return j.value;case"rejected":throw j.reason}}throw j}function O(j,Y,L,G,q){var Q=typeof j;(Q==="undefined"||Q==="boolean")&&(j=null);var J=!1;if(j===null)J=!0;else switch(Q){case"bigint":case"string":case"number":J=!0;break;case"object":switch(j.$$typeof){case e:case t:J=!0;break;case m:return J=j._init,O(J(j._payload),Y,L,G,q)}}if(J)return q=q(j),J=G===""?"."+A(j,0):G,I(q)?(L="",J!=null&&(L=J.replace(V,"$&/")+"/"),O(q,Y,L,"",function(ce){return ce})):q!=null&&(z(q)&&(q=D(q,L+(q.key==null||j&&j.key===q.key?"":(""+q.key).replace(V,"$&/")+"/")+J)),Y.push(q)),1;J=0;var W=G===""?".":G+":";if(I(j))for(var te=0;te<j.length;te++)G=j[te],Q=W+A(G,te),J+=O(G,Y,L,Q,q);else if(te=x(j),typeof te=="function")for(j=te.call(j),te=0;!(G=j.next()).done;)G=G.value,Q=W+A(G,te++),J+=O(G,Y,L,Q,q);else if(Q==="object"){if(typeof j.then=="function")return O($(j),Y,L,G,q);throw Y=String(j),Error("Objects are not valid as a React child (found: "+(Y==="[object Object]"?"object with keys {"+Object.keys(j).join(", ")+"}":Y)+"). If you meant to render a collection of children, use an array instead.")}return J}function H(j,Y,L){if(j==null)return j;var G=[],q=0;return O(j,G,"","",function(Q){return Y.call(L,Q,q++)}),G}function X(j){if(j._status===-1){var Y=j._result;Y=Y(),Y.then(function(L){(j._status===0||j._status===-1)&&(j._status=1,j._result=L)},function(L){(j._status===0||j._status===-1)&&(j._status=2,j._result=L)}),j._status===-1&&(j._status=0,j._result=Y)}if(j._status===1)return j._result.default;throw j._result}var K=typeof reportError=="function"?reportError:function(j){if(typeof window=="object"&&typeof window.ErrorEvent=="function"){var Y=new window.ErrorEvent("error",{bubbles:!0,cancelable:!0,message:typeof j=="object"&&j!==null&&typeof j.message=="string"?String(j.message):String(j),error:j});if(!window.dispatchEvent(Y))return}else if(typeof process=="object"&&typeof process.emit=="function"){process.emit("uncaughtException",j);return}console.error(j)},T={map:H,forEach:function(j,Y,L){H(j,function(){Y.apply(this,arguments)},L)},count:function(j){var Y=0;return H(j,function(){Y++}),Y},toArray:function(j){return H(j,function(Y){return Y})||[]},only:function(j){if(!z(j))throw Error("React.Children.only expected to receive a single React element child.");return j}};return Ve.Activity=p,Ve.Children=T,Ve.Component=w,Ve.Fragment=r,Ve.Profiler=s,Ve.PureComponent=E,Ve.StrictMode=a,Ve.Suspense=f,Ve.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE=U,Ve.__COMPILER_RUNTIME={__proto__:null,c:function(j){return U.H.useMemoCache(j)}},Ve.cache=function(j){return function(){return j.apply(null,arguments)}},Ve.cacheSignal=function(){return null},Ve.cloneElement=function(j,Y,L){if(j==null)throw Error("The argument must be a React element, but you passed "+j+".");var Line truncated
*/var V0;function yk(){if(V0)return Ve;V0=1;var e=Symbol.for("react.transitional.element"),t=Symbol.for("react.portal"),r=Symbol.for("react.fragment"),a=Symbol.for("react.strict_mode"),s=Symbol.for("react.profiler"),o=Symbol.for("react.consumer"),c=Symbol.for("react.context"),d=Symbol.for("react.forward_ref"),f=Symbol.for("react.suspense"),h=Symbol.for("react.memo"),m=Symbol.for("react.lazy"),p=Symbol.for("react.activity"),y=Symbol.iterator;function x(j){return j===null||typeof j!="object"?null:(j=y&&j[y]||j["@@iterator"],typeof j=="function"?j:null)}var _={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},N=Object.assign,S={};function w(j,Y,L){this.props=j,this.context=Y,this.refs=S,this.updater=L||_}w.prototype.isReactComponent={},w.prototype.setState=function(j,Y){if(typeof j!="object"&&typeof j!="function"&&j!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,j,Y,"setState")},w.prototype.forceUpdate=function(j){this.updater.enqueueForceUpdate(this,j,"forceUpdate")};function k(){}k.prototype=w.prototype;function E(j,Y,L){this.props=j,this.context=Y,this.refs=S,this.updater=L||_}var M=E.prototype=new k;M.constructor=E,N(M,w.prototype),M.isPureReactComponent=!0;var I=Array.isArray;function R(){}var U={H:null,A:null,T:null,S:null},B=Object.prototype.hasOwnProperty;function Z(j,Y,L){var G=L.ref;return{$$typeof:e,type:j,key:Y,ref:G!==void 0?G:null,props:L}}function D(j,Y){return Z(j.type,Y,j.props)}function z(j){return typeof j=="object"&&j!==null&&j.$$typeof===e}function V(j){var Y={"=":"=0",":":"=2"};return"$"+j.replace(/[=:]/g,function(L){return Y[L]})}var P=/\/+/g;function T(j,Y){return typeof j=="object"&&j!==null&&j.key!=null?V(""+j.key):Y.toString(36)}function $(j){switch(j.status){case"fulfilled":return j.value;case"rejected":throw j.reason;default:switch(typeof j.status=="string"?j.then(R,R):(j.status="pending",j.then(function(Y){j.status==="pending"&&(j.status="fulfilled",j.value=Y)},function(Y){j.status==="pending"&&(j.status="rejected",j.reason=Y)})),j.status){case"fulfilled":return j.value;case"rejected":throw j.reason}}throw j}function O(j,Y,L,G,q){var Q=typeof j;(Q==="undefined"||Q==="boolean")&&(j=null);var J=!1;if(j===null)J=!0;else switch(Q){case"bigint":case"string":case"number":J=!0;break;case"object":switch(j.$$typeof){case e:case t:J=!0;break;case m:return J=j._init,O(J(j._payload),Y,L,G,q)}}if(J)return q=q(j),J=G===""?"."+T(j,0):G,I(q)?(L="",J!=null&&(L=J.replace(P,"$&/")+"/"),O(q,Y,L,"",function(ce){return ce})):q!=null&&(z(q)&&(q=D(q,L+(q.key==null||j&&j.key===q.key?"":(""+q.key).replace(P,"$&/")+"/")+J)),Y.push(q)),1;J=0;var W=G===""?".":G+":";if(I(j))for(var te=0;te<j.length;te++)G=j[te],Q=W+T(G,te),J+=O(G,Y,L,Q,q);else if(te=x(j),typeof te=="function")for(j=te.call(j),te=0;!(G=j.next()).done;)G=G.value,Q=W+T(G,te++),J+=O(G,Y,L,Q,q);else if(Q==="object"){if(typeof j.then=="function")return O($(j),Y,L,G,q);throw Y=String(j),Error("Objects are not valid as a React child (found: "+(Y==="[object Object]"?"object with keys {"+Object.keys(j).join(", ")+"}":Y)+"). If you meant to render a collection of children, use an array instead.")}return J}function H(j,Y,L){if(j==null)return j;var G=[],q=0;return O(j,G,"","",function(Q){return Y.call(L,Q,q++)}),G}function X(j){if(j._status===-1){var Y=j._result;Y=Y(),Y.then(function(L){(j._status===0||j._status===-1)&&(j._status=1,j._result=L)},function(L){(j._status===0||j._status===-1)&&(j._status=2,j._result=L)}),j._status===-1&&(j._status=0,j._result=Y)}if(j._status===1)return j._result.default;throw j._result}var K=typeof reportError=="function"?reportError:function(j){if(typeof window=="object"&&typeof window.ErrorEvent=="function"){var Y=new window.ErrorEvent("error",{bubbles:!0,cancelable:!0,message:typeof j=="object"&&j!==null&&typeof j.message=="string"?String(j.message):String(j),error:j});if(!window.dispatchEvent(Y))return}else if(typeof process=="object"&&typeof process.emit=="function"){process.emit("uncaughtException",j);return}console.error(j)},C={map:H,forEach:function(j,Y,L){H(j,function(){Y.apply(this,arguments)},L)},count:function(j){var Y=0;return H(j,function(){Y++}),Y},toArray:function(j){return H(j,function(Y){return Y})||[]},only:function(j){if(!z(j))throw Error("React.Children.only expected to receive a single React element child.");return j}};return Ve.Activity=p,Ve.Children=C,Ve.Component=w,Ve.Fragment=r,Ve.Profiler=s,Ve.PureComponent=E,Ve.StrictMode=a,Ve.Suspense=f,Ve.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE=U,Ve.__COMPILER_RUNTIME={__proto__:null,c:function(j){return U.H.useMemoCache(j)}},Ve.cache=function(j){return function(){return j.apply(null,arguments)}},Ve.cacheSignal=function(){return null},Ve.cloneElement=function(j,Y,L){if(j==null)throw Error("The argument must be a React element, but you passed "+j+".");var Line truncated
* @license React
* scheduler.production.js
*
@@ -22,7 +22,7 @@
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/var X0;function xk(){return X0||(X0=1,(function(e){function t(O,H){var X=O.length;O.push(H);e:for(;0<X;){var K=X-1>>>1,T=O[K];if(0<s(T,H))O[K]=H,O[X]=T,X=K;else break e}}function r(O){return O.length===0?null:O[0]}function a(O){if(O.length===0)return null;var H=O[0],X=O.pop();if(X!==H){O[0]=X;e:for(var K=0,T=O.length,j=T>>>1;K<j;){var Y=2*(K+1)-1,L=O[Y],G=Y+1,q=O[G];if(0>s(L,X))G<T&&0>s(q,L)?(O[K]=q,O[G]=X,K=G):(O[K]=L,O[Y]=X,K=Y);else if(G<T&&0>s(q,X))O[K]=q,O[G]=X,K=G;else break e}}return H}function s(O,H){var X=O.sortIndex-H.sortIndex;return X!==0?X:O.id-H.id}if(e.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var o=performance;e.unstable_now=function(){return o.now()}}else{var c=Date,d=c.now();e.unstable_now=function(){return c.now()-d}}var f=[],h=[],m=1,p=null,y=3,x=!1,_=!1,N=!1,S=!1,w=typeof setTimeout=="function"?setTimeout:null,k=typeof clearTimeout=="function"?clearTimeout:null,E=typeof setImmediate<"u"?setImmediate:null;function M(O){for(var H=r(h);H!==null;){if(H.callback===null)a(h);else if(H.startTime<=O)a(h),H.sortIndex=H.expirationTime,t(f,H);else break;H=r(h)}}function I(O){if(N=!1,M(O),!_)if(r(f)!==null)_=!0,R||(R=!0,P());else{var H=r(h);H!==null&&$(I,H.startTime-O)}}var R=!1,U=-1,B=5,Z=-1;function D(){return S?!0:!(e.unstable_now()-Z<B)}function z(){if(S=!1,R){var O=e.unstable_now();Z=O;var H=!0;try{e:{_=!1,N&&(N=!1,k(U),U=-1),x=!0;var X=y;try{t:{for(M(O),p=r(f);p!==null&&!(p.expirationTime>O&&D());){var K=p.callback;if(typeof K=="function"){p.callback=null,y=p.priorityLevel;var T=K(p.expirationTime<=O);if(O=e.unstable_now(),typeof T=="function"){p.callback=T,M(O),H=!0;break t}p===r(f)&&a(f),M(O)}else a(f);p=r(f)}if(p!==null)H=!0;else{var j=r(h);j!==null&&$(I,j.startTime-O),H=!1}}break e}finally{p=null,y=X,x=!1}H=void 0}}finally{H?P():R=!1}}}var P;if(typeof E=="function")P=function(){E(z)};else if(typeof MessageChannel<"u"){var V=new MessageChannel,A=V.port2;V.port1.onmessage=z,P=function(){A.postMessage(null)}}else P=function(){w(z,0)};function $(O,H){U=w(function(){O(e.unstable_now())},H)}e.unstable_IdlePriority=5,e.unstable_ImmediatePriority=1,e.unstable_LowPriority=4,e.unstable_NormalPriority=3,e.unstable_Profiling=null,e.unstable_UserBlockingPriority=2,e.unstable_cancelCallback=function(O){O.callback=null},e.unstable_forceFrameRate=function(O){0>O||125<O?console.error("forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported"):B=0<O?Math.floor(1e3/O):5},e.unstable_getCurrentPriorityLevel=function(){return y},e.unstable_next=function(O){switch(y){case 1:case 2:case 3:var H=3;break;default:H=y}var X=y;y=H;try{return O()}finally{y=X}},e.unstable_requestPaint=function(){S=!0},e.unstable_runWithPriority=function(O,H){switch(O){case 1:case 2:case 3:case 4:case 5:break;default:O=3}var X=y;y=O;try{return H()}finally{y=X}},e.unstable_scheduleCallback=function(O,H,X){var K=e.unstable_now();switch(typeof X=="object"&&X!==null?(X=X.delay,X=typeof X=="number"&&0<X?K+X:K):X=K,O){case 1:var T=-1;break;case 2:T=250;break;case 5:T=1073741823;break;case 4:T=1e4;break;default:T=5e3}return T=X+T,O={id:m++,callback:H,priorityLevel:O,startTime:X,expirationTime:T,sortIndex:-1},X>K?(O.sortIndex=X,t(h,O),r(f)===null&&O===r(h)&&(N?(k(U),U=-1):N=!0,$(I,X-K))):(O.sortIndex=T,t(f,O),_||x||(_=!0,R||(R=!0,P()))),O},e.unstable_shouldYield=D,e.unstable_wrapCallback=function(O){var H=y;return function(){var X=y;y=H;try{return O.apply(this,arguments)}finally{y=X}}}})(fh)),fh}var K0;function yk(){return K0||(K0=1,dh.exports=xk()),dh.exports}var hh={exports:{}},kn={};/**
*/var X0;function vk(){return X0||(X0=1,(function(e){function t(O,H){var X=O.length;O.push(H);e:for(;0<X;){var K=X-1>>>1,C=O[K];if(0<s(C,H))O[K]=H,O[X]=C,X=K;else break e}}function r(O){return O.length===0?null:O[0]}function a(O){if(O.length===0)return null;var H=O[0],X=O.pop();if(X!==H){O[0]=X;e:for(var K=0,C=O.length,j=C>>>1;K<j;){var Y=2*(K+1)-1,L=O[Y],G=Y+1,q=O[G];if(0>s(L,X))G<C&&0>s(q,L)?(O[K]=q,O[G]=X,K=G):(O[K]=L,O[Y]=X,K=Y);else if(G<C&&0>s(q,X))O[K]=q,O[G]=X,K=G;else break e}}return H}function s(O,H){var X=O.sortIndex-H.sortIndex;return X!==0?X:O.id-H.id}if(e.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var o=performance;e.unstable_now=function(){return o.now()}}else{var c=Date,d=c.now();e.unstable_now=function(){return c.now()-d}}var f=[],h=[],m=1,p=null,y=3,x=!1,_=!1,N=!1,S=!1,w=typeof setTimeout=="function"?setTimeout:null,k=typeof clearTimeout=="function"?clearTimeout:null,E=typeof setImmediate<"u"?setImmediate:null;function M(O){for(var H=r(h);H!==null;){if(H.callback===null)a(h);else if(H.startTime<=O)a(h),H.sortIndex=H.expirationTime,t(f,H);else break;H=r(h)}}function I(O){if(N=!1,M(O),!_)if(r(f)!==null)_=!0,R||(R=!0,V());else{var H=r(h);H!==null&&$(I,H.startTime-O)}}var R=!1,U=-1,B=5,Z=-1;function D(){return S?!0:!(e.unstable_now()-Z<B)}function z(){if(S=!1,R){var O=e.unstable_now();Z=O;var H=!0;try{e:{_=!1,N&&(N=!1,k(U),U=-1),x=!0;var X=y;try{t:{for(M(O),p=r(f);p!==null&&!(p.expirationTime>O&&D());){var K=p.callback;if(typeof K=="function"){p.callback=null,y=p.priorityLevel;var C=K(p.expirationTime<=O);if(O=e.unstable_now(),typeof C=="function"){p.callback=C,M(O),H=!0;break t}p===r(f)&&a(f),M(O)}else a(f);p=r(f)}if(p!==null)H=!0;else{var j=r(h);j!==null&&$(I,j.startTime-O),H=!1}}break e}finally{p=null,y=X,x=!1}H=void 0}}finally{H?V():R=!1}}}var V;if(typeof E=="function")V=function(){E(z)};else if(typeof MessageChannel<"u"){var P=new MessageChannel,T=P.port2;P.port1.onmessage=z,V=function(){T.postMessage(null)}}else V=function(){w(z,0)};function $(O,H){U=w(function(){O(e.unstable_now())},H)}e.unstable_IdlePriority=5,e.unstable_ImmediatePriority=1,e.unstable_LowPriority=4,e.unstable_NormalPriority=3,e.unstable_Profiling=null,e.unstable_UserBlockingPriority=2,e.unstable_cancelCallback=function(O){O.callback=null},e.unstable_forceFrameRate=function(O){0>O||125<O?console.error("forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported"):B=0<O?Math.floor(1e3/O):5},e.unstable_getCurrentPriorityLevel=function(){return y},e.unstable_next=function(O){switch(y){case 1:case 2:case 3:var H=3;break;default:H=y}var X=y;y=H;try{return O()}finally{y=X}},e.unstable_requestPaint=function(){S=!0},e.unstable_runWithPriority=function(O,H){switch(O){case 1:case 2:case 3:case 4:case 5:break;default:O=3}var X=y;y=O;try{return H()}finally{y=X}},e.unstable_scheduleCallback=function(O,H,X){var K=e.unstable_now();switch(typeof X=="object"&&X!==null?(X=X.delay,X=typeof X=="number"&&0<X?K+X:K):X=K,O){case 1:var C=-1;break;case 2:C=250;break;case 5:C=1073741823;break;case 4:C=1e4;break;default:C=5e3}return C=X+C,O={id:m++,callback:H,priorityLevel:O,startTime:X,expirationTime:C,sortIndex:-1},X>K?(O.sortIndex=X,t(h,O),r(f)===null&&O===r(h)&&(N?(k(U),U=-1):N=!0,$(I,X-K))):(O.sortIndex=C,t(f,O),_||x||(_=!0,R||(R=!0,V()))),O},e.unstable_shouldYield=D,e.unstable_wrapCallback=function(O){var H=y;return function(){var X=y;y=H;try{return O.apply(this,arguments)}finally{y=X}}}})(fh)),fh}var K0;function _k(){return K0||(K0=1,dh.exports=vk()),dh.exports}var hh={exports:{}},Cn={};/**
* @license React
* react-dom.production.js
*
@@ -30,7 +30,7 @@
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/var Z0;function vk(){if(Z0)return kn;Z0=1;var e=Co();function t(f){var h="https://react.dev/errors/"+f;if(1<arguments.length){h+="?args[]="+encodeURIComponent(arguments[1]);for(var m=2;m<arguments.length;m++)h+="&args[]="+encodeURIComponent(arguments[m])}return"Minified React error #"+f+"; visit "+h+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}function r(){}var a={d:{f:r,r:function(){throw Error(t(522))},D:r,C:r,L:r,m:r,X:r,S:r,M:r},p:0,findDOMNode:null},s=Symbol.for("react.portal");function o(f,h,m){var p=3<arguments.length&&arguments[3]!==void 0?arguments[3]:null;return{$$typeof:s,key:p==null?null:""+p,children:f,containerInfo:h,implementation:m}}var c=e.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;function d(f,h){if(f==="font")return"";if(typeof h=="string")return h==="use-credentials"?h:""}return kn.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE=a,kn.createPortal=function(f,h){var m=2<arguments.length&&arguments[2]!==void 0?arguments[2]:null;if(!h||h.nodeType!==1&&h.nodeType!==9&&h.nodeType!==11)throw Error(t(299));return o(f,h,null,m)},kn.flushSync=function(f){var h=c.T,m=a.p;try{if(c.T=null,a.p=2,f)return f()}finally{c.T=h,a.p=m,a.d.f()}},kn.preconnect=function(f,h){typeof f=="string"&&(h?(h=h.crossOrigin,h=typeof h=="string"?h==="use-credentials"?h:"":void 0):h=null,a.d.C(f,h))},kn.prefetchDNS=function(f){typeof f=="string"&&a.d.D(f)},kn.preinit=function(f,h){if(typeof f=="string"&&h&&typeof h.as=="string"){var m=h.as,p=d(m,h.crossOrigin),y=typeof h.integrity=="string"?h.integrity:void 0,x=typeof h.fetchPriority=="string"?h.fetchPriority:void 0;m==="style"?a.d.S(f,typeof h.precedence=="string"?h.precedence:void 0,{crossOrigin:p,integrity:y,fetchPriority:x}):m==="script"&&a.d.X(f,{crossOrigin:p,integrity:y,fetchPriority:x,nonce:typeof h.nonce=="string"?h.nonce:void 0})}},kn.preinitModule=function(f,h){if(typeof f=="string")if(typeof h=="object"&&h!==null){if(h.as==null||h.as==="script"){var m=d(h.as,h.crossOrigin);a.d.M(f,{crossOrigin:m,integrity:typeof h.integrity=="string"?h.integrity:void 0,nonce:typeof h.nonce=="string"?h.nonce:void 0})}}else h==null&&a.d.M(f)},kn.preload=function(f,h){if(typeof f=="string"&&typeof h=="object"&&h!==null&&typeof h.as=="string"){var m=h.as,p=d(m,h.crossOrigin);a.d.L(f,m,{crossOrigin:p,integrity:typeof h.integrity=="string"?h.integrity:void 0,nonce:typeof h.nonce=="string"?h.nonce:void 0,type:typeof h.type=="string"?h.type:void 0,fetchPriority:typeof h.fetchPriority=="string"?h.fetchPriority:void 0,referrerPolicy:typeof h.referrerPolicy=="string"?h.referrerPolicy:void 0,imageSrcSet:typeof h.imageSrcSet=="string"?h.imageSrcSet:void 0,imageSizes:typeof h.imageSizes=="string"?h.imageSizes:void 0,media:typeof h.media=="string"?h.media:void 0})}},kn.preloadModule=function(f,h){if(typeof f=="string")if(h){var m=d(h.as,h.crossOrigin);a.d.m(f,{as:typeof h.as=="string"&&h.as!=="script"?h.as:void 0,crossOrigin:m,integrity:typeof h.integrity=="string"?h.integrity:void 0})}else a.d.m(f)},kn.requestFormReset=function(f){a.d.r(f)},kn.unstable_batchedUpdates=function(f,h){return f(h)},kn.useFormState=function(f,h,m){return c.H.useFormState(f,h,m)},kn.useFormStatus=function(){return c.H.useHostTransitionStatus()},kn.version="19.2.7",kn}var Q0;function N_(){if(Q0)return hh.exports;Q0=1;function e(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(t){console.error(t)}}return e(),hh.exports=vk(),hh.exports}/**
*/var Z0;function wk(){if(Z0)return Cn;Z0=1;var e=To();function t(f){var h="https://react.dev/errors/"+f;if(1<arguments.length){h+="?args[]="+encodeURIComponent(arguments[1]);for(var m=2;m<arguments.length;m++)h+="&args[]="+encodeURIComponent(arguments[m])}return"Minified React error #"+f+"; visit "+h+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}function r(){}var a={d:{f:r,r:function(){throw Error(t(522))},D:r,C:r,L:r,m:r,X:r,S:r,M:r},p:0,findDOMNode:null},s=Symbol.for("react.portal");function o(f,h,m){var p=3<arguments.length&&arguments[3]!==void 0?arguments[3]:null;return{$$typeof:s,key:p==null?null:""+p,children:f,containerInfo:h,implementation:m}}var c=e.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;function d(f,h){if(f==="font")return"";if(typeof h=="string")return h==="use-credentials"?h:""}return Cn.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE=a,Cn.createPortal=function(f,h){var m=2<arguments.length&&arguments[2]!==void 0?arguments[2]:null;if(!h||h.nodeType!==1&&h.nodeType!==9&&h.nodeType!==11)throw Error(t(299));return o(f,h,null,m)},Cn.flushSync=function(f){var h=c.T,m=a.p;try{if(c.T=null,a.p=2,f)return f()}finally{c.T=h,a.p=m,a.d.f()}},Cn.preconnect=function(f,h){typeof f=="string"&&(h?(h=h.crossOrigin,h=typeof h=="string"?h==="use-credentials"?h:"":void 0):h=null,a.d.C(f,h))},Cn.prefetchDNS=function(f){typeof f=="string"&&a.d.D(f)},Cn.preinit=function(f,h){if(typeof f=="string"&&h&&typeof h.as=="string"){var m=h.as,p=d(m,h.crossOrigin),y=typeof h.integrity=="string"?h.integrity:void 0,x=typeof h.fetchPriority=="string"?h.fetchPriority:void 0;m==="style"?a.d.S(f,typeof h.precedence=="string"?h.precedence:void 0,{crossOrigin:p,integrity:y,fetchPriority:x}):m==="script"&&a.d.X(f,{crossOrigin:p,integrity:y,fetchPriority:x,nonce:typeof h.nonce=="string"?h.nonce:void 0})}},Cn.preinitModule=function(f,h){if(typeof f=="string")if(typeof h=="object"&&h!==null){if(h.as==null||h.as==="script"){var m=d(h.as,h.crossOrigin);a.d.M(f,{crossOrigin:m,integrity:typeof h.integrity=="string"?h.integrity:void 0,nonce:typeof h.nonce=="string"?h.nonce:void 0})}}else h==null&&a.d.M(f)},Cn.preload=function(f,h){if(typeof f=="string"&&typeof h=="object"&&h!==null&&typeof h.as=="string"){var m=h.as,p=d(m,h.crossOrigin);a.d.L(f,m,{crossOrigin:p,integrity:typeof h.integrity=="string"?h.integrity:void 0,nonce:typeof h.nonce=="string"?h.nonce:void 0,type:typeof h.type=="string"?h.type:void 0,fetchPriority:typeof h.fetchPriority=="string"?h.fetchPriority:void 0,referrerPolicy:typeof h.referrerPolicy=="string"?h.referrerPolicy:void 0,imageSrcSet:typeof h.imageSrcSet=="string"?h.imageSrcSet:void 0,imageSizes:typeof h.imageSizes=="string"?h.imageSizes:void 0,media:typeof h.media=="string"?h.media:void 0})}},Cn.preloadModule=function(f,h){if(typeof f=="string")if(h){var m=d(h.as,h.crossOrigin);a.d.m(f,{as:typeof h.as=="string"&&h.as!=="script"?h.as:void 0,crossOrigin:m,integrity:typeof h.integrity=="string"?h.integrity:void 0})}else a.d.m(f)},Cn.requestFormReset=function(f){a.d.r(f)},Cn.unstable_batchedUpdates=function(f,h){return f(h)},Cn.useFormState=function(f,h,m){return c.H.useFormState(f,h,m)},Cn.useFormStatus=function(){return c.H.useHostTransitionStatus()},Cn.version="19.2.7",Cn}var Q0;function N_(){if(Q0)return hh.exports;Q0=1;function e(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(t){console.error(t)}}return e(),hh.exports=wk(),hh.exports}/**
* @license React
* react-dom-client.production.js
*
@@ -38,15 +38,15 @@
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/var W0;function _k(){if(W0)return Xl;W0=1;var e=yk(),t=Co(),r=N_();function a(n){var i="https://react.dev/errors/"+n;if(1<arguments.length){i+="?args[]="+encodeURIComponent(arguments[1]);for(var l=2;l<arguments.length;l++)i+="&args[]="+encodeURIComponent(arguments[l])}return"Minified React error #"+n+"; visit "+i+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}function s(n){return!(!n||n.nodeType!==1&&n.nodeType!==9&&n.nodeType!==11)}function o(n){var i=n,l=n;if(n.alternate)for(;i.return;)i=i.return;else{n=i;do i=n,(i.flags&4098)!==0&&(l=i.return),n=i.return;while(n)}return i.tag===3?l:null}function c(n){if(n.tag===13){var i=n.memoizedState;if(i===null&&(n=n.alternate,n!==null&&(i=n.memoizedState)),i!==null)return i.dehydrated}return null}function d(n){if(n.tag===31){var i=n.memoizedState;if(i===null&&(n=n.alternate,n!==null&&(i=n.memoizedState)),i!==null)return i.dehydrated}return null}function f(n){if(o(n)!==n)throw Error(a(188))}function h(n){var i=n.alternate;if(!i){if(i=o(n),i===null)throw Error(a(188));return i!==n?null:n}for(var l=n,u=i;;){var b=l.return;if(b===null)break;var v=b.alternate;if(v===null){if(u=b.return,u!==null){l=u;continue}break}if(b.child===v.child){for(v=b.child;v;){if(v===l)return f(b),n;if(v===u)return f(b),i;v=v.sibling}throw Error(a(188))}if(l.return!==u.return)l=b,u=v;else{for(var C=!1,F=b.child;F;){if(F===l){C=!0,l=b,u=v;break}if(F===u){C=!0,u=b,l=v;break}F=F.sibling}if(!C){for(F=v.child;F;){if(F===l){C=!0,l=v,u=b;break}if(F===u){C=!0,u=v,l=b;break}F=F.sibling}if(!C)throw Error(a(189))}}if(l.alternate!==u)throw Error(a(190))}if(l.tag!==3)throw Error(a(188));return l.stateNode.current===l?n:i}function m(n){var i=n.tag;if(i===5||i===26||i===27||i===6)return n;for(n=n.child;n!==null;){if(i=m(n),i!==null)return i;n=n.sibling}return null}var p=Object.assign,y=Symbol.for("react.element"),x=Symbol.for("react.transitional.element"),_=Symbol.for("react.portal"),N=Symbol.for("react.fragment"),S=Symbol.for("react.strict_mode"),w=Symbol.for("react.profiler"),k=Symbol.for("react.consumer"),E=Symbol.for("react.context"),M=Symbol.for("react.forward_ref"),I=Symbol.for("react.suspense"),R=Symbol.for("react.suspense_list"),U=Symbol.for("react.memo"),B=Symbol.for("react.lazy"),Z=Symbol.for("react.activity"),D=Symbol.for("react.memo_cache_sentinel"),z=Symbol.iterator;function P(n){return n===null||typeof n!="object"?null:(n=z&&n[z]||n["@@iterator"],typeof n=="function"?n:null)}var V=Symbol.for("react.client.reference");function A(n){if(n==null)return null;if(typeof n=="function")return n.$$typeof===V?null:n.displayName||n.name||null;if(typeof n=="string")return n;switch(n){case N:return"Fragment";case w:return"Profiler";case S:return"StrictMode";case I:return"Suspense";case R:return"SuspenseList";case Z:return"Activity"}if(typeof n=="object")switch(n.$$typeof){case _:return"Portal";case E:return n.displayName||"Context";case k:return(n._context.displayName||"Context")+".Consumer";case M:var i=n.render;return n=n.displayName,n||(n=i.displayName||i.name||"",n=n!==""?"ForwardRef("+n+")":"ForwardRef"),n;case U:return i=n.displayName||null,i!==null?i:A(n.type)||"Memo";case B:i=n._payload,n=n._init;try{return A(n(i))}catch{}}return null}var $=Array.isArray,O=t.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,H=r.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,X={pending:!1,data:null,method:null,action:null},K=[],T=-1;function j(n){return{current:n}}function Y(n){0>T||(n.current=K[T],K[T]=null,T--)}function L(n,i){T++,K[T]=n.current,n.current=i}var G=j(null),q=j(null),Q=j(null),J=j(null);function W(n,i){switch(L(Q,i),L(q,n),L(G,null),i.nodeType){case 9:case 11:n=(n=i.documentElement)&&(n=n.namespaceURI)?h0(n):0;break;default:if(n=i.tagName,i=i.namespaceURI)i=h0(i),n=m0(i,n);else switch(n){case"svg":n=1;break;case"math":n=2;break;default:n=0}}Y(G),L(G,n)}function te(){Y(G),Y(q),Y(Q)}function ce(n){n.memoizedState!==null&&L(J,n);var i=G.current,l=m0(i,n.type);i!==l&&(L(q,n),L(G,l))}function fe(n){q.current===n&&(Y(G),Y(q)),J.current===n&&(Y(J),Pl._currentValue=X)}var be,we;function Ne(n){if(be===void 0)try{throw Error()}catch(l){var i=l.stack.trim().match(/\n( *(at )?)/);be=i&&i[1]||"",we=-1<l.stack.indexOf(`
*/var W0;function Ek(){if(W0)return Xl;W0=1;var e=_k(),t=To(),r=N_();function a(n){var i="https://react.dev/errors/"+n;if(1<arguments.length){i+="?args[]="+encodeURIComponent(arguments[1]);for(var l=2;l<arguments.length;l++)i+="&args[]="+encodeURIComponent(arguments[l])}return"Minified React error #"+n+"; visit "+i+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}function s(n){return!(!n||n.nodeType!==1&&n.nodeType!==9&&n.nodeType!==11)}function o(n){var i=n,l=n;if(n.alternate)for(;i.return;)i=i.return;else{n=i;do i=n,(i.flags&4098)!==0&&(l=i.return),n=i.return;while(n)}return i.tag===3?l:null}function c(n){if(n.tag===13){var i=n.memoizedState;if(i===null&&(n=n.alternate,n!==null&&(i=n.memoizedState)),i!==null)return i.dehydrated}return null}function d(n){if(n.tag===31){var i=n.memoizedState;if(i===null&&(n=n.alternate,n!==null&&(i=n.memoizedState)),i!==null)return i.dehydrated}return null}function f(n){if(o(n)!==n)throw Error(a(188))}function h(n){var i=n.alternate;if(!i){if(i=o(n),i===null)throw Error(a(188));return i!==n?null:n}for(var l=n,u=i;;){var b=l.return;if(b===null)break;var v=b.alternate;if(v===null){if(u=b.return,u!==null){l=u;continue}break}if(b.child===v.child){for(v=b.child;v;){if(v===l)return f(b),n;if(v===u)return f(b),i;v=v.sibling}throw Error(a(188))}if(l.return!==u.return)l=b,u=v;else{for(var A=!1,F=b.child;F;){if(F===l){A=!0,l=b,u=v;break}if(F===u){A=!0,u=b,l=v;break}F=F.sibling}if(!A){for(F=v.child;F;){if(F===l){A=!0,l=v,u=b;break}if(F===u){A=!0,u=v,l=b;break}F=F.sibling}if(!A)throw Error(a(189))}}if(l.alternate!==u)throw Error(a(190))}if(l.tag!==3)throw Error(a(188));return l.stateNode.current===l?n:i}function m(n){var i=n.tag;if(i===5||i===26||i===27||i===6)return n;for(n=n.child;n!==null;){if(i=m(n),i!==null)return i;n=n.sibling}return null}var p=Object.assign,y=Symbol.for("react.element"),x=Symbol.for("react.transitional.element"),_=Symbol.for("react.portal"),N=Symbol.for("react.fragment"),S=Symbol.for("react.strict_mode"),w=Symbol.for("react.profiler"),k=Symbol.for("react.consumer"),E=Symbol.for("react.context"),M=Symbol.for("react.forward_ref"),I=Symbol.for("react.suspense"),R=Symbol.for("react.suspense_list"),U=Symbol.for("react.memo"),B=Symbol.for("react.lazy"),Z=Symbol.for("react.activity"),D=Symbol.for("react.memo_cache_sentinel"),z=Symbol.iterator;function V(n){return n===null||typeof n!="object"?null:(n=z&&n[z]||n["@@iterator"],typeof n=="function"?n:null)}var P=Symbol.for("react.client.reference");function T(n){if(n==null)return null;if(typeof n=="function")return n.$$typeof===P?null:n.displayName||n.name||null;if(typeof n=="string")return n;switch(n){case N:return"Fragment";case w:return"Profiler";case S:return"StrictMode";case I:return"Suspense";case R:return"SuspenseList";case Z:return"Activity"}if(typeof n=="object")switch(n.$$typeof){case _:return"Portal";case E:return n.displayName||"Context";case k:return(n._context.displayName||"Context")+".Consumer";case M:var i=n.render;return n=n.displayName,n||(n=i.displayName||i.name||"",n=n!==""?"ForwardRef("+n+")":"ForwardRef"),n;case U:return i=n.displayName||null,i!==null?i:T(n.type)||"Memo";case B:i=n._payload,n=n._init;try{return T(n(i))}catch{}}return null}var $=Array.isArray,O=t.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,H=r.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,X={pending:!1,data:null,method:null,action:null},K=[],C=-1;function j(n){return{current:n}}function Y(n){0>C||(n.current=K[C],K[C]=null,C--)}function L(n,i){C++,K[C]=n.current,n.current=i}var G=j(null),q=j(null),Q=j(null),J=j(null);function W(n,i){switch(L(Q,i),L(q,n),L(G,null),i.nodeType){case 9:case 11:n=(n=i.documentElement)&&(n=n.namespaceURI)?h0(n):0;break;default:if(n=i.tagName,i=i.namespaceURI)i=h0(i),n=m0(i,n);else switch(n){case"svg":n=1;break;case"math":n=2;break;default:n=0}}Y(G),L(G,n)}function te(){Y(G),Y(q),Y(Q)}function ce(n){n.memoizedState!==null&&L(J,n);var i=G.current,l=m0(i,n.type);i!==l&&(L(q,n),L(G,l))}function fe(n){q.current===n&&(Y(G),Y(q)),J.current===n&&(Y(J),Pl._currentValue=X)}var be,we;function Ne(n){if(be===void 0)try{throw Error()}catch(l){var i=l.stack.trim().match(/\n( *(at )?)/);be=i&&i[1]||"",we=-1<l.stack.indexOf(`
at`)?" (<anonymous>)":-1<l.stack.indexOf("@")?"@unknown:0:0":""}return`
`+be+n+we}var je=!1;function $e(n,i){if(!n||je)return"";je=!0;var l=Error.prepareStackTrace;Error.prepareStackTrace=void 0;try{var u={DetermineComponentFrameRoot:function(){try{if(i){var ge=function(){throw Error()};if(Object.defineProperty(ge.prototype,"props",{set:function(){throw Error()}}),typeof Reflect=="object"&&Reflect.construct){try{Reflect.construct(ge,[])}catch(de){var oe=de}Reflect.construct(n,[],ge)}else{try{ge.call()}catch(de){oe=de}n.call(ge.prototype)}}else{try{throw Error()}catch(de){oe=de}(ge=n())&&typeof ge.catch=="function"&&ge.catch(function(){})}}catch(de){if(de&&oe&&typeof de.stack=="string")return[de.stack,oe.stack]}return[null,null]}};u.DetermineComponentFrameRoot.displayName="DetermineComponentFrameRoot";var b=Object.getOwnPropertyDescriptor(u.DetermineComponentFrameRoot,"name");b&&b.configurable&&Object.defineProperty(u.DetermineComponentFrameRoot,"name",{value:"DetermineComponentFrameRoot"});var v=u.DetermineComponentFrameRoot(),C=v[0],F=v[1];if(C&&F){var ne=C.split(`
`+be+n+we}var je=!1;function $e(n,i){if(!n||je)return"";je=!0;var l=Error.prepareStackTrace;Error.prepareStackTrace=void 0;try{var u={DetermineComponentFrameRoot:function(){try{if(i){var ge=function(){throw Error()};if(Object.defineProperty(ge.prototype,"props",{set:function(){throw Error()}}),typeof Reflect=="object"&&Reflect.construct){try{Reflect.construct(ge,[])}catch(de){var oe=de}Reflect.construct(n,[],ge)}else{try{ge.call()}catch(de){oe=de}n.call(ge.prototype)}}else{try{throw Error()}catch(de){oe=de}(ge=n())&&typeof ge.catch=="function"&&ge.catch(function(){})}}catch(de){if(de&&oe&&typeof de.stack=="string")return[de.stack,oe.stack]}return[null,null]}};u.DetermineComponentFrameRoot.displayName="DetermineComponentFrameRoot";var b=Object.getOwnPropertyDescriptor(u.DetermineComponentFrameRoot,"name");b&&b.configurable&&Object.defineProperty(u.DetermineComponentFrameRoot,"name",{value:"DetermineComponentFrameRoot"});var v=u.DetermineComponentFrameRoot(),A=v[0],F=v[1];if(A&&F){var ne=A.split(`
`),le=F.split(`
`);for(b=u=0;u<ne.length&&!ne[u].includes("DetermineComponentFrameRoot");)u++;for(;b<le.length&&!le[b].includes("DetermineComponentFrameRoot");)b++;if(u===ne.length||b===le.length)for(u=ne.length-1,b=le.length-1;1<=u&&0<=b&&ne[u]!==le[b];)b--;for(;1<=u&&0<=b;u--,b--)if(ne[u]!==le[b]){if(u!==1||b!==1)do if(u--,b--,0>b||ne[u]!==le[b]){var he=`
`+ne[u].replace(" at new "," at ");return n.displayName&&he.includes("<anonymous>")&&(he=he.replace("<anonymous>",n.displayName)),he}while(1<=u&&0<=b);break}}}finally{je=!1,Error.prepareStackTrace=l}return(l=n?n.displayName||n.name:"")?Ne(l):""}function st(n,i){switch(n.tag){case 26:case 27:case 5:return Ne(n.type);case 16:return Ne("Lazy");case 13:return n.child!==i&&i!==null?Ne("Suspense Fallback"):Ne("Suspense");case 19:return Ne("SuspenseList");case 0:case 15:return $e(n.type,!1);case 11:return $e(n.type.render,!1);case 1:return $e(n.type,!0);case 31:return Ne("Activity");default:return""}}function Rt(n){try{var i="",l=null;do i+=st(n,l),l=n,n=n.return;while(n);return i}catch(u){return`
Error generating stack: `+u.message+`
`+u.stack}}var Yt=Object.prototype.hasOwnProperty,Pt=e.unstable_scheduleCallback,Xt=e.unstable_cancelCallback,Yn=e.unstable_shouldYield,wn=e.unstable_requestPaint,ct=e.unstable_now,It=e.unstable_getCurrentPriorityLevel,ue=e.unstable_ImmediatePriority,xe=e.unstable_UserBlockingPriority,Oe=e.unstable_NormalPriority,Fe=e.unstable_LowPriority,Ze=e.unstable_IdlePriority,on=e.log,En=e.unstable_setDisableYieldValue,Kt=null,At=null;function Wt(n){if(typeof on=="function"&&En(n),At&&typeof At.setStrictMode=="function")try{At.setStrictMode(Kt,n)}catch{}}var ut=Math.clz32?Math.clz32:Ni,zn=Math.log,cn=Math.LN2;function Ni(n){return n>>>=0,n===0?32:31-(zn(n)/cn|0)|0}var nt=256,Xn=262144,An=4194304;function hn(n){var i=n&42;if(i!==0)return i;switch(n&-n){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return n&261888;case 262144:case 524288:case 1048576:case 2097152:return n&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return n&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return n}}function re(n,i,l){var u=n.pendingLanes;if(u===0)return 0;var b=0,v=n.suspendedLanes,C=n.pingedLanes;n=n.warmLanes;var F=u&134217727;return F!==0?(u=F&~v,u!==0?b=hn(u):(C&=F,C!==0?b=hn(C):l||(l=F&~n,l!==0&&(b=hn(l))))):(F=u&~v,F!==0?b=hn(F):C!==0?b=hn(C):l||(l=u&~n,l!==0&&(b=hn(l)))),b===0?0:i!==0&&i!==b&&(i&v)===0&&(v=b&-b,l=i&-i,v>=l||v===32&&(l&4194048)!==0)?i:b}function me(n,i){return(n.pendingLanes&~(n.suspendedLanes&~n.pingedLanes)&i)===0}function Ee(n,i){switch(n){case 1:case 2:case 4:case 8:case 64:return i+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return i+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function Pe(){var n=An;return An<<=1,(An&62914560)===0&&(An=4194304),n}function St(n){for(var i=[],l=0;31>l;l++)i.push(n);return i}function gt(n,i){n.pendingLanes|=i,i!==268435456&&(n.suspendedLanes=0,n.pingedLanes=0,n.warmLanes=0)}function Ae(n,i,l,u,b,v){var C=n.pendingLanes;n.pendingLanes=l,n.suspendedLanes=0,n.pingedLanes=0,n.warmLanes=0,n.expiredLanes&=l,n.entangledLanes&=l,n.errorRecoveryDisabledLanes&=l,n.shellSuspendCounter=0;var F=n.entanglements,ne=n.expirationTimes,le=n.hiddenUpdates;for(l=C&~l;0<l;){var he=31-ut(l),ge=1<<he;F[he]=0,ne[he]=-1;var oe=le[he];if(oe!==null)for(le[he]=null,he=0;he<oe.length;he++){var de=oe[he];de!==null&&(de.lane&=-536870913)}l&=~ge}u!==0&&Se(n,u,0),v!==0&&b===0&&n.tag!==0&&(n.suspendedLanes|=v&~(C&~i))}function Se(n,i,l){n.pendingLanes|=i,n.suspendedLanes&=~i;var u=31-ut(i);n.entangledLanes|=i,n.entanglements[u]=n.entanglements[u]|1073741824|l&261930}function Ue(n,i){var l=n.entangledLanes|=i;for(n=n.entanglements;l;){var u=31-ut(l),b=1<<u;b&i|n[u]&i&&(n[u]|=i),l&=~b}}function Bt(n,i){var l=i&-i;return l=(l&42)!==0?1:Mt(l),(l&(n.suspendedLanes|i))!==0?0:l}function Mt(n){switch(n){case 2:n=1;break;case 8:n=4;break;case 32:n=16;break;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:case 4194304:case 8388608:case 16777216:case 33554432:n=128;break;case 268435456:n=134217728;break;default:n=0}return n}function xr(n){return n&=-n,2<n?8<n?(n&134217727)!==0?32:268435456:8:2}function Si(){var n=H.p;return n!==0?n:(n=window.event,n===void 0?32:I0(n.type))}function ki(n,i){var l=H.p;try{return H.p=n,i()}finally{H.p=l}}var sr=Math.random().toString(36).slice(2),Ut="__reactFiber$"+sr,mn="__reactProps$"+sr,yr="__reactContainer$"+sr,Ti="__reactEvents$"+sr,pa="__reactListeners$"+sr,Ci="__reactHandles$"+sr,Ja="__reactResources$"+sr,Wr="__reactMarker$"+sr;function ga(n){delete n[Ut],delete n[mn],delete n[Ti],delete n[pa],delete n[Ci]}function bn(n){var i=n[Ut];if(i)return i;for(var l=n.parentNode;l;){if(i=l[yr]||l[Ut]){if(l=i.alternate,i.child!==null||l!==null&&l.child!==null)for(n=_0(n);n!==null;){if(l=n[Ut])return l;n=_0(n)}return i}n=l,l=n.parentNode}return null}function vr(n){if(n=n[Ut]||n[yr]){var i=n.tag;if(i===5||i===6||i===13||i===31||i===26||i===27||i===3)return n}return null}function _r(n){var i=n.tag;if(i===5||i===26||i===27||i===6)return n.stateNode;throw Error(a(33))}function Br(n){var i=n[Ja];return i||(i=n[Ja]={hoistableStyles:new Map,hoistableScripts:new Map}),i}function Ft(n){n[Wr]=!0}var es=new Set,Jr={};function wr(n,i){ye(n,i),ye(n+"Capture",i)}function ye(n,i){for(Jr[n]=i,n=0;n<i.length;n++)es.add(i[n])}var Le=RegExp("^[:A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u2 Line truncated
`).replace(I2,"")}function d0(n,i){return i=u0(i),u0(n)===i}function Et(n,i,l,u,b,v){switch(l){case"children":typeof u=="string"?i==="body"||i==="textarea"&&u===""||qe(n,u):(typeof u=="number"||typeof u=="bigint")&&i!=="body"&&qe(n,""+u);break;case"className":Mn(n,"class",u);break;case"tabIndex":Mn(n,"tabindex",u);break;case"dir":case"role":case"viewBox":case"width":case"height":Mn(n,l,u);break;case"style":bt(n,u,v);break;case"data":if(i!=="object"){Mn(n,"data",u);break}case"src":case"href":if(u===""&&(i!=="a"||l!=="href")){n.removeAttribute(l);break}if(u==null||typeof u=="function"||typeof u=="symbol"||typeof u=="boolean"){n.removeAttribute(l);break}u=Di(""+u),n.setAttribute(l,u);break;case"action":case"formAction":if(typeof u=="function"){n.setAttribute(l,"javascript:throw new Error('A React form was unexpectedly submitted. If you called form.submit() manually, consider using form.requestSubmit() instead. If you\\'re trying to use event.stopPropagation() in a submit event handler, consider also calling event.preventDefault().')");break}else typeof v=="function"&&(l==="formAction"?(i!=="input"&&Et(n,i,"name",b.name,b,null),Et(n,i,"formEncType",b.formEncType,b,null),Et(n,i,"formMethod",b.formMethod,b,null),Et(n,i,"formTarget",b.formTarget,b,null)):(Et(n,i,"encType",b.encType,b,null),Et(n,i,"method",b.method,b,null),Et(n,i,"target",b.target,b,null)));if(u==null||typeof u=="symbol"||typeof u=="boolean"){n.removeAttribute(l);break}u=Di(""+u),n.setAttribute(l,u);break;case"onClick":u!=null&&(n.onclick=_e);break;case"onScroll":u!=null&&et("scroll",n);break;case"onScrollEnd":u!=null&&et("scrollend",n);break;case"dangerouslySetInnerHTML":if(u!=null){if(typeof u!="object"||!("__html"in u))throw Error(a(61));if(l=u.__html,l!=null){if(b.children!=null)throw Error(a(60));n.innerHTML=l}}break;case"multiple":n.multiple=u&&typeof u!="function"&&typeof u!="symbol";break;case"muted":n.muted=u&&typeof u!="function"&&typeof u!="symbol";break;case"suppressContentEditableWarning":case"suppressHydrationWarning":case"defaultValue":case"defaultChecked":case"innerHTML":case"ref":break;case"autoFocus":break;case"xlinkHref":if(u==null||typeof u=="function"||typeof u=="boolean"||typeof u=="symbol"){n.removeAttribute("xlink:href");break}l=Di(""+u),n.setAttributeNS("http://www.w3.org/1999/xlink","xlink:href",l);break;case"contentEditable":case"spellCheck":case"draggable":case"value":case"autoReverse":case"externalResourcesRequired":case"focusable":case"preserveAlpha":u!=null&&typeof u!="function"&&typeof u!="symbol"?n.setAttribute(l,""+u):n.removeAttribute(l);break;case"inert":case"allowFullScreen":case"async":case"autoPlay":case"controls":case"default":case"defer":case"disabled":case"disablePictureInPicture":case"disableRemotePlayback":case"formNoValidate":case"hidden":case"loop":case"noModule":case"noValidate":case"open":case"playsInline":case"readOnly":case"required":case"reversed":case"scoped":case"seamless":case"itemScope":u&&typeof u!="function"&&typeof u!="symbol"?n.setAttribute(l,""):n.removeAttribute(l);break;case"capture":case"download":u===!0?n.setAttribute(l,""):u!==!1&&u!=null&&typeof u!="function"&&typeof u!="symbol"?n.setAttribute(l,u):n.removeAttribute(l);break;case"cols":case"rows":case"size":case"span":u!=null&&typeof u!="function"&&typeof u!="symbol"&&!isNaN(u)&&1<=u?n.setAttribute(l,u):n.removeAttribute(l);break;case"rowSpan":case"start":u==null||typeof u=="function"||typeof u=="symbol"||isNaN(u)?n.removeAttribute(l):n.setAttribute(l,u);break;case"popover":et("beforetoggle",n),et("toggle",n),pn(n,"popover",u);break;case"xlinkActuate":Nn(n,"http://www.w3.org/1999/xlink","xlink:actuate",u);break;case"xlinkArcrole":Nn(n,"http://www.w3.org/1999/xlink","xlink:arcrole",u);break;case"xlinkRole":Nn(n,"http://www.w3.org/1999/xlink","xlink:role",u);break;case"xlinkShow":Nn(n,"http://www.w3.org/1999/xlink","xlink:show",u);break;case"xlinkTitle":Nn(n,"http://www.w3.org/1999/xlink","xlink:title",u);break;case"xlinkType":Nn(n,"http://www.w3.org/1999/xlink","xlink:type",u);break;case"xmlBase":Nn(n,"http://www.w3.org/XML/1998/namespace","xml:base",u);break;case"xmlLang":Nn(n,"http://www.w3.org/XML/1998/namespace","xml:lang",u);break;case"xmlSpace":Nn(n,"http://www.w3.org/XML/1998/namespace","xml:space",u);break;case"is":pn(n,"is",u);break;case"innerText":case"textContent":break;default:(!(2<l.length)||l[0]!=="o"&&l[0]!=="O"||l[1]!=="n"&&l[1]!=="N")&&(l=ei.get(l)||l,pn(n,l,u))}}function Ff(n,i,l,u,b,v){switch(l){case"style":bt(n,u,v);break;case"dangerouslySetInnerHTML":if(u!=null){if(typeof u!="object"||!("__html"in u))throw Error(a(61));if(l=u.__html,l!=null){if(b.children!=null)throw Error(a(60));n.innerHTML=l}}break;case"children":typeof u=="string"?qe(n,u):(typeof u=="number"||typeof u=="bigint")&&qe(n,""+u);break;case"onScroll":u!=null&&et("scroll",n);break;case"onScrollEnd":u!=null&&et("scrollend",n);break;case"onClick":u!=null&&(n.onclick=_e);break;case"suppressContentEditableWarning":case"suppressHydrationWarning":case"inne Line truncated
`+u.stack}}var Yt=Object.prototype.hasOwnProperty,Pt=e.unstable_scheduleCallback,Xt=e.unstable_cancelCallback,Yn=e.unstable_shouldYield,En=e.unstable_requestPaint,ct=e.unstable_now,It=e.unstable_getCurrentPriorityLevel,ue=e.unstable_ImmediatePriority,xe=e.unstable_UserBlockingPriority,Oe=e.unstable_NormalPriority,Fe=e.unstable_LowPriority,Ze=e.unstable_IdlePriority,on=e.log,Nn=e.unstable_setDisableYieldValue,Kt=null,At=null;function Wt(n){if(typeof on=="function"&&Nn(n),At&&typeof At.setStrictMode=="function")try{At.setStrictMode(Kt,n)}catch{}}var ut=Math.clz32?Math.clz32:Ni,In=Math.log,cn=Math.LN2;function Ni(n){return n>>>=0,n===0?32:31-(In(n)/cn|0)|0}var nt=256,Xn=262144,Mn=4194304;function hn(n){var i=n&42;if(i!==0)return i;switch(n&-n){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return n&261888;case 262144:case 524288:case 1048576:case 2097152:return n&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return n&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return n}}function re(n,i,l){var u=n.pendingLanes;if(u===0)return 0;var b=0,v=n.suspendedLanes,A=n.pingedLanes;n=n.warmLanes;var F=u&134217727;return F!==0?(u=F&~v,u!==0?b=hn(u):(A&=F,A!==0?b=hn(A):l||(l=F&~n,l!==0&&(b=hn(l))))):(F=u&~v,F!==0?b=hn(F):A!==0?b=hn(A):l||(l=u&~n,l!==0&&(b=hn(l)))),b===0?0:i!==0&&i!==b&&(i&v)===0&&(v=b&-b,l=i&-i,v>=l||v===32&&(l&4194048)!==0)?i:b}function me(n,i){return(n.pendingLanes&~(n.suspendedLanes&~n.pingedLanes)&i)===0}function Ee(n,i){switch(n){case 1:case 2:case 4:case 8:case 64:return i+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return i+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function Pe(){var n=Mn;return Mn<<=1,(Mn&62914560)===0&&(Mn=4194304),n}function St(n){for(var i=[],l=0;31>l;l++)i.push(n);return i}function gt(n,i){n.pendingLanes|=i,i!==268435456&&(n.suspendedLanes=0,n.pingedLanes=0,n.warmLanes=0)}function Ae(n,i,l,u,b,v){var A=n.pendingLanes;n.pendingLanes=l,n.suspendedLanes=0,n.pingedLanes=0,n.warmLanes=0,n.expiredLanes&=l,n.entangledLanes&=l,n.errorRecoveryDisabledLanes&=l,n.shellSuspendCounter=0;var F=n.entanglements,ne=n.expirationTimes,le=n.hiddenUpdates;for(l=A&~l;0<l;){var he=31-ut(l),ge=1<<he;F[he]=0,ne[he]=-1;var oe=le[he];if(oe!==null)for(le[he]=null,he=0;he<oe.length;he++){var de=oe[he];de!==null&&(de.lane&=-536870913)}l&=~ge}u!==0&&Se(n,u,0),v!==0&&b===0&&n.tag!==0&&(n.suspendedLanes|=v&~(A&~i))}function Se(n,i,l){n.pendingLanes|=i,n.suspendedLanes&=~i;var u=31-ut(i);n.entangledLanes|=i,n.entanglements[u]=n.entanglements[u]|1073741824|l&261930}function Ue(n,i){var l=n.entangledLanes|=i;for(n=n.entanglements;l;){var u=31-ut(l),b=1<<u;b&i|n[u]&i&&(n[u]|=i),l&=~b}}function Bt(n,i){var l=i&-i;return l=(l&42)!==0?1:Mt(l),(l&(n.suspendedLanes|i))!==0?0:l}function Mt(n){switch(n){case 2:n=1;break;case 8:n=4;break;case 32:n=16;break;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:case 4194304:case 8388608:case 16777216:case 33554432:n=128;break;case 268435456:n=134217728;break;default:n=0}return n}function xr(n){return n&=-n,2<n?8<n?(n&134217727)!==0?32:268435456:8:2}function Si(){var n=H.p;return n!==0?n:(n=window.event,n===void 0?32:I0(n.type))}function ki(n,i){var l=H.p;try{return H.p=n,i()}finally{H.p=l}}var lr=Math.random().toString(36).slice(2),Ut="__reactFiber$"+lr,mn="__reactProps$"+lr,yr="__reactContainer$"+lr,Ci="__reactEvents$"+lr,pa="__reactListeners$"+lr,Ti="__reactHandles$"+lr,Ja="__reactResources$"+lr,Wr="__reactMarker$"+lr;function ga(n){delete n[Ut],delete n[mn],delete n[Ci],delete n[pa],delete n[Ti]}function bn(n){var i=n[Ut];if(i)return i;for(var l=n.parentNode;l;){if(i=l[yr]||l[Ut]){if(l=i.alternate,i.child!==null||l!==null&&l.child!==null)for(n=_0(n);n!==null;){if(l=n[Ut])return l;n=_0(n)}return i}n=l,l=n.parentNode}return null}function vr(n){if(n=n[Ut]||n[yr]){var i=n.tag;if(i===5||i===6||i===13||i===31||i===26||i===27||i===3)return n}return null}function _r(n){var i=n.tag;if(i===5||i===26||i===27||i===6)return n.stateNode;throw Error(a(33))}function Br(n){var i=n[Ja];return i||(i=n[Ja]={hoistableStyles:new Map,hoistableScripts:new Map}),i}function Ft(n){n[Wr]=!0}var es=new Set,Jr={};function wr(n,i){ye(n,i),ye(n+"Capture",i)}function ye(n,i){for(Jr[n]=i,n=0;n<i.length;n++)es.add(i[n])}var Le=RegExp("^[:A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u2 Line truncated
`).replace(U2,"")}function d0(n,i){return i=u0(i),u0(n)===i}function Et(n,i,l,u,b,v){switch(l){case"children":typeof u=="string"?i==="body"||i==="textarea"&&u===""||qe(n,u):(typeof u=="number"||typeof u=="bigint")&&i!=="body"&&qe(n,""+u);break;case"className":On(n,"class",u);break;case"tabIndex":On(n,"tabindex",u);break;case"dir":case"role":case"viewBox":case"width":case"height":On(n,l,u);break;case"style":bt(n,u,v);break;case"data":if(i!=="object"){On(n,"data",u);break}case"src":case"href":if(u===""&&(i!=="a"||l!=="href")){n.removeAttribute(l);break}if(u==null||typeof u=="function"||typeof u=="symbol"||typeof u=="boolean"){n.removeAttribute(l);break}u=Di(""+u),n.setAttribute(l,u);break;case"action":case"formAction":if(typeof u=="function"){n.setAttribute(l,"javascript:throw new Error('A React form was unexpectedly submitted. If you called form.submit() manually, consider using form.requestSubmit() instead. If you\\'re trying to use event.stopPropagation() in a submit event handler, consider also calling event.preventDefault().')");break}else typeof v=="function"&&(l==="formAction"?(i!=="input"&&Et(n,i,"name",b.name,b,null),Et(n,i,"formEncType",b.formEncType,b,null),Et(n,i,"formMethod",b.formMethod,b,null),Et(n,i,"formTarget",b.formTarget,b,null)):(Et(n,i,"encType",b.encType,b,null),Et(n,i,"method",b.method,b,null),Et(n,i,"target",b.target,b,null)));if(u==null||typeof u=="symbol"||typeof u=="boolean"){n.removeAttribute(l);break}u=Di(""+u),n.setAttribute(l,u);break;case"onClick":u!=null&&(n.onclick=_e);break;case"onScroll":u!=null&&et("scroll",n);break;case"onScrollEnd":u!=null&&et("scrollend",n);break;case"dangerouslySetInnerHTML":if(u!=null){if(typeof u!="object"||!("__html"in u))throw Error(a(61));if(l=u.__html,l!=null){if(b.children!=null)throw Error(a(60));n.innerHTML=l}}break;case"multiple":n.multiple=u&&typeof u!="function"&&typeof u!="symbol";break;case"muted":n.muted=u&&typeof u!="function"&&typeof u!="symbol";break;case"suppressContentEditableWarning":case"suppressHydrationWarning":case"defaultValue":case"defaultChecked":case"innerHTML":case"ref":break;case"autoFocus":break;case"xlinkHref":if(u==null||typeof u=="function"||typeof u=="boolean"||typeof u=="symbol"){n.removeAttribute("xlink:href");break}l=Di(""+u),n.setAttributeNS("http://www.w3.org/1999/xlink","xlink:href",l);break;case"contentEditable":case"spellCheck":case"draggable":case"value":case"autoReverse":case"externalResourcesRequired":case"focusable":case"preserveAlpha":u!=null&&typeof u!="function"&&typeof u!="symbol"?n.setAttribute(l,""+u):n.removeAttribute(l);break;case"inert":case"allowFullScreen":case"async":case"autoPlay":case"controls":case"default":case"defer":case"disabled":case"disablePictureInPicture":case"disableRemotePlayback":case"formNoValidate":case"hidden":case"loop":case"noModule":case"noValidate":case"open":case"playsInline":case"readOnly":case"required":case"reversed":case"scoped":case"seamless":case"itemScope":u&&typeof u!="function"&&typeof u!="symbol"?n.setAttribute(l,""):n.removeAttribute(l);break;case"capture":case"download":u===!0?n.setAttribute(l,""):u!==!1&&u!=null&&typeof u!="function"&&typeof u!="symbol"?n.setAttribute(l,u):n.removeAttribute(l);break;case"cols":case"rows":case"size":case"span":u!=null&&typeof u!="function"&&typeof u!="symbol"&&!isNaN(u)&&1<=u?n.setAttribute(l,u):n.removeAttribute(l);break;case"rowSpan":case"start":u==null||typeof u=="function"||typeof u=="symbol"||isNaN(u)?n.removeAttribute(l):n.setAttribute(l,u);break;case"popover":et("beforetoggle",n),et("toggle",n),pn(n,"popover",u);break;case"xlinkActuate":Sn(n,"http://www.w3.org/1999/xlink","xlink:actuate",u);break;case"xlinkArcrole":Sn(n,"http://www.w3.org/1999/xlink","xlink:arcrole",u);break;case"xlinkRole":Sn(n,"http://www.w3.org/1999/xlink","xlink:role",u);break;case"xlinkShow":Sn(n,"http://www.w3.org/1999/xlink","xlink:show",u);break;case"xlinkTitle":Sn(n,"http://www.w3.org/1999/xlink","xlink:title",u);break;case"xlinkType":Sn(n,"http://www.w3.org/1999/xlink","xlink:type",u);break;case"xmlBase":Sn(n,"http://www.w3.org/XML/1998/namespace","xml:base",u);break;case"xmlLang":Sn(n,"http://www.w3.org/XML/1998/namespace","xml:lang",u);break;case"xmlSpace":Sn(n,"http://www.w3.org/XML/1998/namespace","xml:space",u);break;case"is":pn(n,"is",u);break;case"innerText":case"textContent":break;default:(!(2<l.length)||l[0]!=="o"&&l[0]!=="O"||l[1]!=="n"&&l[1]!=="N")&&(l=ei.get(l)||l,pn(n,l,u))}}function Ff(n,i,l,u,b,v){switch(l){case"style":bt(n,u,v);break;case"dangerouslySetInnerHTML":if(u!=null){if(typeof u!="object"||!("__html"in u))throw Error(a(61));if(l=u.__html,l!=null){if(b.children!=null)throw Error(a(60));n.innerHTML=l}}break;case"children":typeof u=="string"?qe(n,u):(typeof u=="number"||typeof u=="bigint")&&qe(n,""+u);break;case"onScroll":u!=null&&et("scroll",n);break;case"onScrollEnd":u!=null&&et("scrollend",n);break;case"onClick":u!=null&&(n.onclick=_e);break;case"suppressContentEditableWarning":case"suppressHydrationWarning":case"inne Line truncated
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
@@ -56,389 +56,389 @@ Error generating stack: `+u.message+`
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const Nk=e=>e.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase();/**
*/const kk=e=>e.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase();/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const Sk=e=>e.replace(/^([A-Z])|[\s-_]+(\w)/g,(t,r,a)=>a?a.toUpperCase():r.toLowerCase());/**
*/const Ck=e=>e.replace(/^([A-Z])|[\s-_]+(\w)/g,(t,r,a)=>a?a.toUpperCase():r.toLowerCase());/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const ey=e=>{const t=Sk(e);return t.charAt(0).toUpperCase()+t.slice(1)};/**
*/const ey=e=>{const t=Ck(e);return t.charAt(0).toUpperCase()+t.slice(1)};/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/var kk={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};/**
*/var Tk={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const Tk=e=>{for(const t in e)if(t.startsWith("aria-")||t==="role"||t==="title")return!0;return!1};/**
*/const Ak=e=>{for(const t in e)if(t.startsWith("aria-")||t==="role"||t==="title")return!0;return!1};/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const Ck=ee.forwardRef(({color:e="currentColor",size:t=24,strokeWidth:r=2,absoluteStrokeWidth:a,className:s="",children:o,iconNode:c,...d},f)=>ee.createElement("svg",{ref:f,...kk,width:t,height:t,stroke:e,strokeWidth:a?Number(r)*24/Number(t):r,className:S_("lucide",s),...!o&&!Tk(d)&&{"aria-hidden":"true"},...d},[...c.map(([h,m])=>ee.createElement(h,m)),...Array.isArray(o)?o:[o]]));/**
*/const Mk=ee.forwardRef(({color:e="currentColor",size:t=24,strokeWidth:r=2,absoluteStrokeWidth:a,className:s="",children:o,iconNode:c,...d},f)=>ee.createElement("svg",{ref:f,...Tk,width:t,height:t,stroke:e,strokeWidth:a?Number(r)*24/Number(t):r,className:S_("lucide",s),...!o&&!Ak(d)&&{"aria-hidden":"true"},...d},[...c.map(([h,m])=>ee.createElement(h,m)),...Array.isArray(o)?o:[o]]));/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const Me=(e,t)=>{const r=ee.forwardRef(({className:a,...s},o)=>ee.createElement(Ck,{ref:o,iconNode:t,className:S_(`lucide-${Nk(ey(e))}`,`lucide-${e}`,a),...s}));return r.displayName=ey(e),r};/**
*/const Me=(e,t)=>{const r=ee.forwardRef(({className:a,...s},o)=>ee.createElement(Mk,{ref:o,iconNode:t,className:S_(`lucide-${kk(ey(e))}`,`lucide-${e}`,a),...s}));return r.displayName=ey(e),r};/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const Ak=[["path",{d:"m12 19-7-7 7-7",key:"1l729n"}],["path",{d:"M19 12H5",key:"x3x0zl"}]],gp=Me("arrow-left",Ak);/**
*/const Ok=[["path",{d:"m12 19-7-7 7-7",key:"1l729n"}],["path",{d:"M19 12H5",key:"x3x0zl"}]],gp=Me("arrow-left",Ok);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const Mk=[["path",{d:"M7 7h10v10",key:"1tivn9"}],["path",{d:"M7 17 17 7",key:"1vkiza"}]],k_=Me("arrow-up-right",Mk);/**
*/const Rk=[["path",{d:"M7 7h10v10",key:"1tivn9"}],["path",{d:"M7 17 17 7",key:"1vkiza"}]],k_=Me("arrow-up-right",Rk);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const Ok=[["path",{d:"m5 12 7-7 7 7",key:"hav0vg"}],["path",{d:"M12 19V5",key:"x0mq9r"}]],Rk=Me("arrow-up",Ok);/**
*/const Dk=[["path",{d:"m5 12 7-7 7 7",key:"hav0vg"}],["path",{d:"M12 19V5",key:"x0mq9r"}]],jk=Me("arrow-up",Dk);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const Dk=[["path",{d:"M4.929 4.929 19.07 19.071",key:"196cmz"}],["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}]],T_=Me("ban",Dk);/**
*/const Lk=[["path",{d:"M4.929 4.929 19.07 19.071",key:"196cmz"}],["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}]],C_=Me("ban",Lk);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const jk=[["path",{d:"M10.268 21a2 2 0 0 0 3.464 0",key:"vwvbt9"}],["path",{d:"M17 17H4a1 1 0 0 1-.74-1.673C4.59 13.956 6 12.499 6 8a6 6 0 0 1 .258-1.742",key:"178tsu"}],["path",{d:"m2 2 20 20",key:"1ooewy"}],["path",{d:"M8.668 3.01A6 6 0 0 1 18 8c0 2.687.77 4.653 1.707 6.05",key:"1hqiys"}]],Lk=Me("bell-off",jk);/**
*/const zk=[["path",{d:"M10.268 21a2 2 0 0 0 3.464 0",key:"vwvbt9"}],["path",{d:"M17 17H4a1 1 0 0 1-.74-1.673C4.59 13.956 6 12.499 6 8a6 6 0 0 1 .258-1.742",key:"178tsu"}],["path",{d:"m2 2 20 20",key:"1ooewy"}],["path",{d:"M8.668 3.01A6 6 0 0 1 18 8c0 2.687.77 4.653 1.707 6.05",key:"1hqiys"}]],Ik=Me("bell-off",zk);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const zk=[["path",{d:"M12 8V4H8",key:"hb8ula"}],["rect",{width:"16",height:"12",x:"4",y:"8",rx:"2",key:"enze0r"}],["path",{d:"M2 14h2",key:"vft8re"}],["path",{d:"M20 14h2",key:"4cs60a"}],["path",{d:"M15 13v2",key:"1xurst"}],["path",{d:"M9 13v2",key:"rq6x2g"}]],Ao=Me("bot",zk);/**
*/const Bk=[["path",{d:"M12 8V4H8",key:"hb8ula"}],["rect",{width:"16",height:"12",x:"4",y:"8",rx:"2",key:"enze0r"}],["path",{d:"M2 14h2",key:"vft8re"}],["path",{d:"M20 14h2",key:"4cs60a"}],["path",{d:"M15 13v2",key:"1xurst"}],["path",{d:"M9 13v2",key:"rq6x2g"}]],Ao=Me("bot",Bk);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const Ik=[["path",{d:"M12 18V5",key:"adv99a"}],["path",{d:"M15 13a4.17 4.17 0 0 1-3-4 4.17 4.17 0 0 1-3 4",key:"1e3is1"}],["path",{d:"M17.598 6.5A3 3 0 1 0 12 5a3 3 0 1 0-5.598 1.5",key:"1gqd8o"}],["path",{d:"M17.997 5.125a4 4 0 0 1 2.526 5.77",key:"iwvgf7"}],["path",{d:"M18 18a4 4 0 0 0 2-7.464",key:"efp6ie"}],["path",{d:"M19.967 17.483A4 4 0 1 1 12 18a4 4 0 1 1-7.967-.517",key:"1gq6am"}],["path",{d:"M6 18a4 4 0 0 1-2-7.464",key:"k1g0md"}],["path",{d:"M6.003 5.125a4 4 0 0 0-2.526 5.77",key:"q97ue3"}]],C_=Me("brain",Ik);/**
*/const Uk=[["path",{d:"M12 18V5",key:"adv99a"}],["path",{d:"M15 13a4.17 4.17 0 0 1-3-4 4.17 4.17 0 0 1-3 4",key:"1e3is1"}],["path",{d:"M17.598 6.5A3 3 0 1 0 12 5a3 3 0 1 0-5.598 1.5",key:"1gqd8o"}],["path",{d:"M17.997 5.125a4 4 0 0 1 2.526 5.77",key:"iwvgf7"}],["path",{d:"M18 18a4 4 0 0 0 2-7.464",key:"efp6ie"}],["path",{d:"M19.967 17.483A4 4 0 1 1 12 18a4 4 0 1 1-7.967-.517",key:"1gq6am"}],["path",{d:"M6 18a4 4 0 0 1-2-7.464",key:"k1g0md"}],["path",{d:"M6.003 5.125a4 4 0 0 0-2.526 5.77",key:"q97ue3"}]],T_=Me("brain",Uk);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const Bk=[["path",{d:"M16 14v2.2l1.6 1",key:"fo4ql5"}],["path",{d:"M16 2v4",key:"4m81vk"}],["path",{d:"M21 7.5V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h3.5",key:"1osxxc"}],["path",{d:"M3 10h5",key:"r794hk"}],["path",{d:"M8 2v4",key:"1cmpym"}],["circle",{cx:"16",cy:"16",r:"6",key:"qoo3c4"}]],Uk=Me("calendar-clock",Bk);/**
*/const Hk=[["path",{d:"M16 14v2.2l1.6 1",key:"fo4ql5"}],["path",{d:"M16 2v4",key:"4m81vk"}],["path",{d:"M21 7.5V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h3.5",key:"1osxxc"}],["path",{d:"M3 10h5",key:"r794hk"}],["path",{d:"M8 2v4",key:"1cmpym"}],["circle",{cx:"16",cy:"16",r:"6",key:"qoo3c4"}]],$k=Me("calendar-clock",Hk);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const Hk=[["path",{d:"M18 6 7 17l-5-5",key:"116fxf"}],["path",{d:"m22 10-7.5 7.5L13 16",key:"ke71qq"}]],$k=Me("check-check",Hk);/**
*/const qk=[["path",{d:"M18 6 7 17l-5-5",key:"116fxf"}],["path",{d:"m22 10-7.5 7.5L13 16",key:"ke71qq"}]],Pk=Me("check-check",qk);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const qk=[["path",{d:"M20 6 9 17l-5-5",key:"1gmf2c"}]],Gs=Me("check",qk);/**
*/const Fk=[["path",{d:"M20 6 9 17l-5-5",key:"1gmf2c"}]],Gs=Me("check",Fk);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const Pk=[["path",{d:"m6 9 6 6 6-6",key:"qrunsl"}]],ho=Me("chevron-down",Pk);/**
*/const Gk=[["path",{d:"m6 9 6 6 6-6",key:"qrunsl"}]],ho=Me("chevron-down",Gk);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const Fk=[["path",{d:"m9 18 6-6-6-6",key:"mthhwq"}]],Gk=Me("chevron-right",Fk);/**
*/const Vk=[["path",{d:"m9 18 6-6-6-6",key:"mthhwq"}]],Yk=Me("chevron-right",Vk);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const Vk=[["path",{d:"m18 15-6-6-6 6",key:"153udz"}]],A_=Me("chevron-up",Vk);/**
*/const Xk=[["path",{d:"m18 15-6-6-6 6",key:"153udz"}]],A_=Me("chevron-up",Xk);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const Yk=[["path",{d:"m7 15 5 5 5-5",key:"1hf1tw"}],["path",{d:"m7 9 5-5 5 5",key:"sgt6xg"}]],Xk=Me("chevrons-up-down",Yk);/**
*/const Kk=[["path",{d:"m7 15 5 5 5-5",key:"1hf1tw"}],["path",{d:"m7 9 5-5 5 5",key:"sgt6xg"}]],Zk=Me("chevrons-up-down",Kk);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const Kk=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["line",{x1:"12",x2:"12",y1:"8",y2:"12",key:"1pkeuh"}],["line",{x1:"12",x2:"12.01",y1:"16",y2:"16",key:"4dfq90"}]],Hu=Me("circle-alert",Kk);/**
*/const Qk=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["line",{x1:"12",x2:"12",y1:"8",y2:"12",key:"1pkeuh"}],["line",{x1:"12",x2:"12.01",y1:"16",y2:"16",key:"4dfq90"}]],Hu=Me("circle-alert",Qk);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const Zk=[["path",{d:"M21.801 10A10 10 0 1 1 17 3.335",key:"yps3ct"}],["path",{d:"m9 11 3 3L22 4",key:"1pflzl"}]],M_=Me("circle-check-big",Zk);/**
*/const Wk=[["path",{d:"M21.801 10A10 10 0 1 1 17 3.335",key:"yps3ct"}],["path",{d:"m9 11 3 3L22 4",key:"1pflzl"}]],M_=Me("circle-check-big",Wk);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const Qk=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"m9 12 2 2 4-4",key:"dzmm74"}]],O_=Me("circle-check",Qk);/**
*/const Jk=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"m9 12 2 2 4-4",key:"dzmm74"}]],O_=Me("circle-check",Jk);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const Wk=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["circle",{cx:"12",cy:"12",r:"1",key:"41hilf"}]],Jk=Me("circle-dot",Wk);/**
*/const eC=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["circle",{cx:"12",cy:"12",r:"1",key:"41hilf"}]],tC=Me("circle-dot",eC);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const eT=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}]],tT=Me("circle",eT);/**
*/const nC=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}]],rC=Me("circle",nC);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const nT=[["path",{d:"M12 6v6l4 2",key:"mmk7yg"}],["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}]],R_=Me("clock",nT);/**
*/const iC=[["path",{d:"M12 6v6l4 2",key:"mmk7yg"}],["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}]],R_=Me("clock",iC);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const rT=[["path",{d:"m16 18 6-6-6-6",key:"eg8j8"}],["path",{d:"m8 6-6 6 6 6",key:"ppft3o"}]],iT=Me("code",rT);/**
*/const aC=[["path",{d:"m16 18 6-6-6-6",key:"eg8j8"}],["path",{d:"m8 6-6 6 6 6",key:"ppft3o"}]],sC=Me("code",aC);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const aT=[["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2",key:"17jyea"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2",key:"zix9uf"}]],mo=Me("copy",aT);/**
*/const lC=[["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2",key:"17jyea"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2",key:"zix9uf"}]],mo=Me("copy",lC);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const sT=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["line",{x1:"22",x2:"18",y1:"12",y2:"12",key:"l9bcsi"}],["line",{x1:"6",x2:"2",y1:"12",y2:"12",key:"13hhkx"}],["line",{x1:"12",x2:"12",y1:"6",y2:"2",key:"10w3f3"}],["line",{x1:"12",x2:"12",y1:"22",y2:"18",key:"15g9kq"}]],lT=Me("crosshair",sT);/**
*/const oC=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["line",{x1:"22",x2:"18",y1:"12",y2:"12",key:"l9bcsi"}],["line",{x1:"6",x2:"2",y1:"12",y2:"12",key:"13hhkx"}],["line",{x1:"12",x2:"12",y1:"6",y2:"2",key:"10w3f3"}],["line",{x1:"12",x2:"12",y1:"22",y2:"18",key:"15g9kq"}]],cC=Me("crosshair",oC);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const oT=[["path",{d:"M15 3h6v6",key:"1q9fwt"}],["path",{d:"M10 14 21 3",key:"gplh6r"}],["path",{d:"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6",key:"a6xqqp"}]],ty=Me("external-link",oT);/**
*/const uC=[["path",{d:"M15 3h6v6",key:"1q9fwt"}],["path",{d:"M10 14 21 3",key:"gplh6r"}],["path",{d:"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6",key:"a6xqqp"}]],ty=Me("external-link",uC);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const cT=[["path",{d:"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0",key:"1nclc0"}],["circle",{cx:"12",cy:"12",r:"3",key:"1v7zrd"}]],uT=Me("eye",cT);/**
*/const dC=[["path",{d:"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0",key:"1nclc0"}],["circle",{cx:"12",cy:"12",r:"3",key:"1v7zrd"}]],fC=Me("eye",dC);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const dT=[["path",{d:"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z",key:"1oefj6"}],["path",{d:"M14 2v5a1 1 0 0 0 1 1h5",key:"wfsgrz"}],["path",{d:"M10 9H8",key:"b1mrlr"}],["path",{d:"M16 13H8",key:"t4e002"}],["path",{d:"M16 17H8",key:"z1uh3a"}]],fT=Me("file-text",dT);/**
*/const hC=[["path",{d:"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z",key:"1oefj6"}],["path",{d:"M14 2v5a1 1 0 0 0 1 1h5",key:"wfsgrz"}],["path",{d:"M10 9H8",key:"b1mrlr"}],["path",{d:"M16 13H8",key:"t4e002"}],["path",{d:"M16 17H8",key:"z1uh3a"}]],mC=Me("file-text",hC);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const hT=[["path",{d:"M4 22V4a1 1 0 0 1 .4-.8A6 6 0 0 1 8 2c3 0 5 2 7.333 2q2 0 3.067-.8A1 1 0 0 1 20 4v10a1 1 0 0 1-.4.8A6 6 0 0 1 16 16c-3 0-5-2-8-2a6 6 0 0 0-4 1.528",key:"1jaruq"}]],D_=Me("flag",hT);/**
*/const pC=[["path",{d:"M4 22V4a1 1 0 0 1 .4-.8A6 6 0 0 1 8 2c3 0 5 2 7.333 2q2 0 3.067-.8A1 1 0 0 1 20 4v10a1 1 0 0 1-.4.8A6 6 0 0 1 16 16c-3 0-5-2-8-2a6 6 0 0 0-4 1.528",key:"1jaruq"}]],D_=Me("flag",pC);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const mT=[["circle",{cx:"18",cy:"18",r:"3",key:"1xkwt0"}],["circle",{cx:"6",cy:"6",r:"3",key:"1lh9wr"}],["path",{d:"M6 21V9a9 9 0 0 0 9 9",key:"7kw0sc"}]],pT=Me("git-merge",mT);/**
*/const gC=[["circle",{cx:"18",cy:"18",r:"3",key:"1xkwt0"}],["circle",{cx:"6",cy:"6",r:"3",key:"1lh9wr"}],["path",{d:"M6 21V9a9 9 0 0 0 9 9",key:"7kw0sc"}]],bC=Me("git-merge",gC);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const gT=[["circle",{cx:"18",cy:"18",r:"3",key:"1xkwt0"}],["circle",{cx:"6",cy:"6",r:"3",key:"1lh9wr"}],["path",{d:"M13 6h3a2 2 0 0 1 2 2v7",key:"1yeb86"}],["line",{x1:"6",x2:"6",y1:"9",y2:"21",key:"rroup"}]],bT=Me("git-pull-request",gT);/**
*/const xC=[["circle",{cx:"18",cy:"18",r:"3",key:"1xkwt0"}],["circle",{cx:"6",cy:"6",r:"3",key:"1lh9wr"}],["path",{d:"M13 6h3a2 2 0 0 1 2 2v7",key:"1yeb86"}],["line",{x1:"6",x2:"6",y1:"9",y2:"21",key:"rroup"}]],yC=Me("git-pull-request",xC);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const xT=[["path",{d:"M15 22v-4a4.8 4.8 0 0 0-1-3.5c3 0 6-2 6-5.5.08-1.25-.27-2.48-1-3.5.28-1.15.28-2.35 0-3.5 0 0-1 0-3 1.5-2.64-.5-5.36-.5-8 0C6 2 5 2 5 2c-.3 1.15-.3 2.35 0 3.5A5.403 5.403 0 0 0 4 9c0 3.5 3 5.5 6 5.5-.39.49-.68 1.05-.85 1.65-.17.6-.22 1.23-.15 1.85v4",key:"tonef"}],["path",{d:"M9 18c-4.51 2-5-2-7-2",key:"9comsn"}]],yT=Me("github",xT);/**
*/const vC=[["path",{d:"M15 22v-4a4.8 4.8 0 0 0-1-3.5c3 0 6-2 6-5.5.08-1.25-.27-2.48-1-3.5.28-1.15.28-2.35 0-3.5 0 0-1 0-3 1.5-2.64-.5-5.36-.5-8 0C6 2 5 2 5 2c-.3 1.15-.3 2.35 0 3.5A5.403 5.403 0 0 0 4 9c0 3.5 3 5.5 6 5.5-.39.49-.68 1.05-.85 1.65-.17.6-.22 1.23-.15 1.85v4",key:"tonef"}],["path",{d:"M9 18c-4.51 2-5-2-7-2",key:"9comsn"}]],_C=Me("github",vC);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const vT=[["path",{d:"m22 13.29-3.33-10a.42.42 0 0 0-.14-.18.38.38 0 0 0-.22-.11.39.39 0 0 0-.23.07.42.42 0 0 0-.14.18l-2.26 6.67H8.32L6.1 3.26a.42.42 0 0 0-.1-.18.38.38 0 0 0-.26-.08.39.39 0 0 0-.23.07.42.42 0 0 0-.14.18L2 13.29a.74.74 0 0 0 .27.83L12 21l9.69-6.88a.71.71 0 0 0 .31-.83Z",key:"148pdi"}]],_T=Me("gitlab",vT);/**
*/const wC=[["path",{d:"m22 13.29-3.33-10a.42.42 0 0 0-.14-.18.38.38 0 0 0-.22-.11.39.39 0 0 0-.23.07.42.42 0 0 0-.14.18l-2.26 6.67H8.32L6.1 3.26a.42.42 0 0 0-.1-.18.38.38 0 0 0-.26-.08.39.39 0 0 0-.23.07.42.42 0 0 0-.14.18L2 13.29a.74.74 0 0 0 .27.83L12 21l9.69-6.88a.71.71 0 0 0 .31-.83Z",key:"148pdi"}]],EC=Me("gitlab",wC);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const wT=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20",key:"13o1zl"}],["path",{d:"M2 12h20",key:"9i4pu4"}]],j_=Me("globe",wT);/**
*/const NC=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20",key:"13o1zl"}],["path",{d:"M2 12h20",key:"9i4pu4"}]],j_=Me("globe",NC);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const ET=[["path",{d:"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",key:"1357e3"}],["path",{d:"M3 3v5h5",key:"1xhq8a"}],["path",{d:"M12 7v5l4 2",key:"1fdv2h"}]],Vs=Me("history",ET);/**
*/const SC=[["path",{d:"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",key:"1357e3"}],["path",{d:"M3 3v5h5",key:"1xhq8a"}],["path",{d:"M12 7v5l4 2",key:"1fdv2h"}]],Vs=Me("history",SC);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const NT=[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",ry:"2",key:"1m3agn"}],["circle",{cx:"9",cy:"9",r:"2",key:"af1f0g"}],["path",{d:"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21",key:"1xmnt7"}]],ST=Me("image",NT);/**
*/const kC=[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",ry:"2",key:"1m3agn"}],["circle",{cx:"9",cy:"9",r:"2",key:"af1f0g"}],["path",{d:"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21",key:"1xmnt7"}]],CC=Me("image",kC);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const kT=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M12 16v-4",key:"1dtifu"}],["path",{d:"M12 8h.01",key:"e9boi3"}]],TT=Me("info",kT);/**
*/const TC=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M12 16v-4",key:"1dtifu"}],["path",{d:"M12 8h.01",key:"e9boi3"}]],AC=Me("info",TC);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const CT=[["path",{d:"M13 5h8",key:"a7qcls"}],["path",{d:"M13 12h8",key:"h98zly"}],["path",{d:"M13 19h8",key:"c3s6r1"}],["path",{d:"m3 17 2 2 4-4",key:"1jhpwq"}],["rect",{x:"3",y:"4",width:"6",height:"6",rx:"1",key:"cif1o7"}]],AT=Me("list-todo",CT);/**
*/const MC=[["path",{d:"M13 5h8",key:"a7qcls"}],["path",{d:"M13 12h8",key:"h98zly"}],["path",{d:"M13 19h8",key:"c3s6r1"}],["path",{d:"m3 17 2 2 4-4",key:"1jhpwq"}],["rect",{x:"3",y:"4",width:"6",height:"6",rx:"1",key:"cif1o7"}]],OC=Me("list-todo",MC);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const MT=[["path",{d:"M21 12a9 9 0 1 1-6.219-8.56",key:"13zald"}]],qs=Me("loader-circle",MT);/**
*/const RC=[["path",{d:"M21 12a9 9 0 1 1-6.219-8.56",key:"13zald"}]],qs=Me("loader-circle",RC);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const OT=[["rect",{width:"18",height:"11",x:"3",y:"11",rx:"2",ry:"2",key:"1w4ew1"}],["path",{d:"M7 11V7a5 5 0 0 1 10 0v4",key:"fwvmzm"}]],RT=Me("lock",OT);/**
*/const DC=[["rect",{width:"18",height:"11",x:"3",y:"11",rx:"2",ry:"2",key:"1w4ew1"}],["path",{d:"M7 11V7a5 5 0 0 1 10 0v4",key:"fwvmzm"}]],jC=Me("lock",DC);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const DT=[["path",{d:"m16 17 5-5-5-5",key:"1bji2h"}],["path",{d:"M21 12H9",key:"dn1m92"}],["path",{d:"M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4",key:"1uf3rs"}]],jT=Me("log-out",DT);/**
*/const LC=[["path",{d:"m16 17 5-5-5-5",key:"1bji2h"}],["path",{d:"M21 12H9",key:"dn1m92"}],["path",{d:"M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4",key:"1uf3rs"}]],zC=Me("log-out",LC);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const LT=[["path",{d:"m22 7-8.991 5.727a2 2 0 0 1-2.009 0L2 7",key:"132q7q"}],["rect",{x:"2",y:"4",width:"20",height:"16",rx:"2",key:"izxlao"}]],bp=Me("mail",LT);/**
*/const IC=[["path",{d:"m22 7-8.991 5.727a2 2 0 0 1-2.009 0L2 7",key:"132q7q"}],["rect",{x:"2",y:"4",width:"20",height:"16",rx:"2",key:"izxlao"}]],bp=Me("mail",IC);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const zT=[["path",{d:"M2.992 16.342a2 2 0 0 1 .094 1.167l-1.065 3.29a1 1 0 0 0 1.236 1.168l3.413-.998a2 2 0 0 1 1.099.092 10 10 0 1 0-4.777-4.719",key:"1sd12s"}]],ny=Me("message-circle",zT);/**
*/const BC=[["path",{d:"M2.992 16.342a2 2 0 0 1 .094 1.167l-1.065 3.29a1 1 0 0 0 1.236 1.168l3.413-.998a2 2 0 0 1 1.099.092 10 10 0 1 0-4.777-4.719",key:"1sd12s"}]],ny=Me("message-circle",BC);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const IT=[["path",{d:"M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z",key:"1a8usu"}],["path",{d:"m15 5 4 4",key:"1mk7zo"}]],BT=Me("pencil",IT);/**
*/const UC=[["path",{d:"M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z",key:"1a8usu"}],["path",{d:"m15 5 4 4",key:"1mk7zo"}]],HC=Me("pencil",UC);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const UT=[["path",{d:"M12 22v-5",key:"1ega77"}],["path",{d:"M15 8V2",key:"18g5xt"}],["path",{d:"M17 8a1 1 0 0 1 1 1v4a4 4 0 0 1-4 4h-4a4 4 0 0 1-4-4V9a1 1 0 0 1 1-1z",key:"1xoxul"}],["path",{d:"M9 8V2",key:"14iosj"}]],HT=Me("plug",UT);/**
*/const $C=[["path",{d:"M12 22v-5",key:"1ega77"}],["path",{d:"M15 8V2",key:"18g5xt"}],["path",{d:"M17 8a1 1 0 0 1 1 1v4a4 4 0 0 1-4 4h-4a4 4 0 0 1-4-4V9a1 1 0 0 1 1-1z",key:"1xoxul"}],["path",{d:"M9 8V2",key:"14iosj"}]],qC=Me("plug",$C);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const $T=[["path",{d:"M5 12h14",key:"1ays0h"}],["path",{d:"M12 5v14",key:"s699le"}]],qT=Me("plus",$T);/**
*/const PC=[["path",{d:"M5 12h14",key:"1ays0h"}],["path",{d:"M12 5v14",key:"s699le"}]],FC=Me("plus",PC);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const PT=[["path",{d:"M19.07 4.93A10 10 0 0 0 6.99 3.34",key:"z3du51"}],["path",{d:"M4 6h.01",key:"oypzma"}],["path",{d:"M2.29 9.62A10 10 0 1 0 21.31 8.35",key:"qzzz0"}],["path",{d:"M16.24 7.76A6 6 0 1 0 8.23 16.67",key:"1yjesh"}],["path",{d:"M12 18h.01",key:"mhygvu"}],["path",{d:"M17.99 11.66A6 6 0 0 1 15.77 16.67",key:"1u2y91"}],["circle",{cx:"12",cy:"12",r:"2",key:"1c9p78"}],["path",{d:"m13.41 10.59 5.66-5.66",key:"mhq4k0"}]],FT=Me("radar",PT);/**
*/const GC=[["path",{d:"M19.07 4.93A10 10 0 0 0 6.99 3.34",key:"z3du51"}],["path",{d:"M4 6h.01",key:"oypzma"}],["path",{d:"M2.29 9.62A10 10 0 1 0 21.31 8.35",key:"qzzz0"}],["path",{d:"M16.24 7.76A6 6 0 1 0 8.23 16.67",key:"1yjesh"}],["path",{d:"M12 18h.01",key:"mhygvu"}],["path",{d:"M17.99 11.66A6 6 0 0 1 15.77 16.67",key:"1u2y91"}],["circle",{cx:"12",cy:"12",r:"2",key:"1c9p78"}],["path",{d:"m13.41 10.59 5.66-5.66",key:"mhq4k0"}]],VC=Me("radar",GC);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const GT=[["path",{d:"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8",key:"v9h5vc"}],["path",{d:"M21 3v5h-5",key:"1q7to0"}],["path",{d:"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16",key:"3uifl3"}],["path",{d:"M8 16H3v5",key:"1cv678"}]],VT=Me("refresh-cw",GT);/**
*/const YC=[["path",{d:"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8",key:"v9h5vc"}],["path",{d:"M21 3v5h-5",key:"1q7to0"}],["path",{d:"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16",key:"3uifl3"}],["path",{d:"M8 16H3v5",key:"1cv678"}]],XC=Me("refresh-cw",YC);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const YT=[["path",{d:"M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09z",key:"m3kijz"}],["path",{d:"m12 15-3-3a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.35 22.35 0 0 1-4 2z",key:"1fmvmk"}],["path",{d:"M9 12H4s.55-3.03 2-4c1.62-1.08 5 0 5 0",key:"1f8sc4"}],["path",{d:"M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5",key:"qeys4"}]],XT=Me("rocket",YT);/**
*/const KC=[["path",{d:"M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09z",key:"m3kijz"}],["path",{d:"m12 15-3-3a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.35 22.35 0 0 1-4 2z",key:"1fmvmk"}],["path",{d:"M9 12H4s.55-3.03 2-4c1.62-1.08 5 0 5 0",key:"1f8sc4"}],["path",{d:"M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5",key:"qeys4"}]],ZC=Me("rocket",KC);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const KT=[["path",{d:"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",key:"1357e3"}],["path",{d:"M3 3v5h5",key:"1xhq8a"}]],ZT=Me("rotate-ccw",KT);/**
*/const QC=[["path",{d:"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",key:"1357e3"}],["path",{d:"M3 3v5h5",key:"1xhq8a"}]],WC=Me("rotate-ccw",QC);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const QT=[["path",{d:"m21 21-4.34-4.34",key:"14j7rj"}],["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}]],WT=Me("search",QT);/**
*/const JC=[["path",{d:"m21 21-4.34-4.34",key:"14j7rj"}],["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}]],eT=Me("search",JC);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const JT=[["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",key:"oel41y"}],["path",{d:"M12 8v4",key:"1got3b"}],["path",{d:"M12 16h.01",key:"1drbdi"}]],eC=Me("shield-alert",JT);/**
*/const tT=[["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",key:"oel41y"}],["path",{d:"M12 8v4",key:"1got3b"}],["path",{d:"M12 16h.01",key:"1drbdi"}]],nT=Me("shield-alert",tT);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const tC=[["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",key:"oel41y"}],["path",{d:"m9 12 2 2 4-4",key:"dzmm74"}]],L_=Me("shield-check",tC);/**
*/const rT=[["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",key:"oel41y"}],["path",{d:"m9 12 2 2 4-4",key:"dzmm74"}]],L_=Me("shield-check",rT);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const nC=[["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",key:"oel41y"}]],rC=Me("shield",nC);/**
*/const iT=[["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",key:"oel41y"}]],aT=Me("shield",iT);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const iC=[["path",{d:"M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z",key:"1s2grr"}],["path",{d:"M20 2v4",key:"1rf3ol"}],["path",{d:"M22 4h-4",key:"gwowj6"}],["circle",{cx:"4",cy:"20",r:"2",key:"6kqj1y"}]],Im=Me("sparkles",iC);/**
*/const sT=[["path",{d:"M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z",key:"1s2grr"}],["path",{d:"M20 2v4",key:"1rf3ol"}],["path",{d:"M22 4h-4",key:"gwowj6"}],["circle",{cx:"4",cy:"20",r:"2",key:"6kqj1y"}]],Im=Me("sparkles",sT);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const aC=[["path",{d:"M21 9a2.4 2.4 0 0 0-.706-1.706l-3.588-3.588A2.4 2.4 0 0 0 15 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2z",key:"1dfntj"}],["path",{d:"M15 3v5a1 1 0 0 0 1 1h5",key:"6s6qgf"}]],sC=Me("sticky-note",aC);/**
*/const lT=[["path",{d:"M21 9a2.4 2.4 0 0 0-.706-1.706l-3.588-3.588A2.4 2.4 0 0 0 15 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2z",key:"1dfntj"}],["path",{d:"M15 3v5a1 1 0 0 0 1 1h5",key:"6s6qgf"}]],oT=Me("sticky-note",lT);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const lC=[["path",{d:"M12 19h8",key:"baeox8"}],["path",{d:"m4 17 6-6-6-6",key:"1yngyt"}]],z_=Me("terminal",lC);/**
*/const cT=[["path",{d:"M12 19h8",key:"baeox8"}],["path",{d:"m4 17 6-6-6-6",key:"1yngyt"}]],z_=Me("terminal",cT);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const oC=[["path",{d:"M10 11v6",key:"nco0om"}],["path",{d:"M14 11v6",key:"outv1u"}],["path",{d:"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6",key:"miytrc"}],["path",{d:"M3 6h18",key:"d0wm0j"}],["path",{d:"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2",key:"e791ji"}]],cC=Me("trash-2",oC);/**
*/const uT=[["path",{d:"M10 11v6",key:"nco0om"}],["path",{d:"M14 11v6",key:"outv1u"}],["path",{d:"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6",key:"miytrc"}],["path",{d:"M3 6h18",key:"d0wm0j"}],["path",{d:"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2",key:"e791ji"}]],dT=Me("trash-2",uT);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const uC=[["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",key:"wmoenq"}],["path",{d:"M12 9v4",key:"juzpu7"}],["path",{d:"M12 17h.01",key:"p32p05"}]],dC=Me("triangle-alert",uC);/**
*/const fT=[["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",key:"wmoenq"}],["path",{d:"M12 9v4",key:"juzpu7"}],["path",{d:"M12 17h.01",key:"p32p05"}]],hT=Me("triangle-alert",fT);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const fC=[["path",{d:"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2",key:"1yyitq"}],["path",{d:"M16 3.128a4 4 0 0 1 0 7.744",key:"16gr8j"}],["path",{d:"M22 21v-2a4 4 0 0 0-3-3.87",key:"kshegd"}],["circle",{cx:"9",cy:"7",r:"4",key:"nufk8"}]],hC=Me("users",fC);/**
*/const mT=[["path",{d:"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2",key:"1yyitq"}],["path",{d:"M16 3.128a4 4 0 0 1 0 7.744",key:"16gr8j"}],["path",{d:"M22 21v-2a4 4 0 0 0-3-3.87",key:"kshegd"}],["circle",{cx:"9",cy:"7",r:"4",key:"nufk8"}]],pT=Me("users",mT);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const mC=[["path",{d:"m21.64 3.64-1.28-1.28a1.21 1.21 0 0 0-1.72 0L2.36 18.64a1.21 1.21 0 0 0 0 1.72l1.28 1.28a1.2 1.2 0 0 0 1.72 0L21.64 5.36a1.2 1.2 0 0 0 0-1.72",key:"ul74o6"}],["path",{d:"m14 7 3 3",key:"1r5n42"}],["path",{d:"M5 6v4",key:"ilb8ba"}],["path",{d:"M19 14v4",key:"blhpug"}],["path",{d:"M10 2v2",key:"7u0qdc"}],["path",{d:"M7 8H3",key:"zfb6yr"}],["path",{d:"M21 16h-4",key:"1cnmox"}],["path",{d:"M11 3H9",key:"1obp7u"}]],pC=Me("wand-sparkles",mC);/**
*/const gT=[["path",{d:"m21.64 3.64-1.28-1.28a1.21 1.21 0 0 0-1.72 0L2.36 18.64a1.21 1.21 0 0 0 0 1.72l1.28 1.28a1.2 1.2 0 0 0 1.72 0L21.64 5.36a1.2 1.2 0 0 0 0-1.72",key:"ul74o6"}],["path",{d:"m14 7 3 3",key:"1r5n42"}],["path",{d:"M5 6v4",key:"ilb8ba"}],["path",{d:"M19 14v4",key:"blhpug"}],["path",{d:"M10 2v2",key:"7u0qdc"}],["path",{d:"M7 8H3",key:"zfb6yr"}],["path",{d:"M21 16h-4",key:"1cnmox"}],["path",{d:"M11 3H9",key:"1obp7u"}]],bT=Me("wand-sparkles",gT);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const gC=[["path",{d:"M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.106-3.105c.32-.322.863-.22.983.218a6 6 0 0 1-8.259 7.057l-7.91 7.91a1 1 0 0 1-2.999-3l7.91-7.91a6 6 0 0 1 7.057-8.259c.438.12.54.662.219.984z",key:"1ngwbx"}]],Bm=Me("wrench",gC);/**
*/const xT=[["path",{d:"M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.106-3.105c.32-.322.863-.22.983.218a6 6 0 0 1-8.259 7.057l-7.91 7.91a1 1 0 0 1-2.999-3l7.91-7.91a6 6 0 0 1 7.057-8.259c.438.12.54.662.219.984z",key:"1ngwbx"}]],Bm=Me("wrench",xT);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const bC=[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]],xp=Me("x",bC);/**
*/const yT=[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]],xp=Me("x",yT);/**
* @license lucide-react v0.563.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const xC=[["path",{d:"M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z",key:"1xq2db"}]],yC=Me("zap",xC),vC={open:{label:"Open",color:"bg-red-500/10 text-red-400 border-red-500/20",dotColor:"bg-red-500",description:"Newly discovered, awaiting triage"},in_progress:{label:"In Progress",color:"bg-blue-500/10 text-blue-400 border-blue-500/20",dotColor:"bg-blue-500",description:"Someone is working on this"},snoozed:{label:"Snoozed",color:"bg-purple-500/10 text-purple-400 border-purple-500/20",dotColor:"bg-purple-500",description:"Temporarily hidden until a follow-up date"},fixed:{label:"Fixed",color:"bg-emerald-500/10 text-emerald-400 border-emerald-500/20",dotColor:"bg-emerald-500",description:"This vulnerability has been fixed"},ignored:{label:"Ignored",color:"bg-gray-500/10 text-gray-400 border-gray-500/20",dotColor:"bg-gray-500",description:"Acknowledged but accepted"}},_C={trivial:{label:"Trivial",color:"bg-emerald-500/10 text-emerald-400 border-emerald-500/20"},low:{label:"Low",color:"bg-blue-500/10 text-blue-400 border-blue-500/20"},medium:{label:"Medium",color:"bg-yellow-500/10 text-yellow-400 border-yellow-500/20"},high:{label:"High",color:"bg-orange-500/10 text-orange-400 border-orange-500/20"}},I_={critical:"bg-red-500/20 text-red-500 border-red-500/30",high:"bg-orange-500/20 text-orange-500 border-orange-500/30",medium:"bg-yellow-500/20 text-yellow-500 border-yellow-500/30",low:"bg-blue-500/20 text-blue-500 border-blue-500/30"};function Zc(e){return e.original_severity!=null&&e.original_severity!==e.severity}const wC={js:"javascript",ts:"typescript",tsx:"typescript",jsx:"javascript",py:"python",rb:"ruby",go:"go",rs:"rust",java:"java",php:"php",cs:"csharp",cpp:"cpp",c:"c",sh:"bash",bash:"bash",sql:"sql",html:"html",css:"css",json:"json",yaml:"yaml",yml:"yaml",xml:"xml"};function EC(e){var r;if(!e)return null;const t=(r=e.split(".").pop())==null?void 0:r.toLowerCase();return t&&wC[t]||null}function yp(e){switch(e){case"critical":return"bg-red-500";case"high":return"bg-orange-500";case"medium":return"bg-yellow-500";default:return"bg-blue-500"}}async function vp(e){try{await navigator.clipboard.writeText(e)}catch{const t=document.createElement("textarea");t.value=e,t.style.position="absolute",t.style.left="-9999px",document.body.appendChild(t),t.select(),document.execCommand("copy"),document.body.removeChild(t)}}const $u="https://app.strix.ai/api/auth/signup",NC="https://strix.ai/pricing",SC="ref=oss_viewer&utm_source=oss_viewer&utm_medium=local_viewer&utm_campaign=oss_viewer";function fa(e,t){const r=e.includes("?")?"&":"?";return`${e}${r}${SC}&utm_content=${encodeURIComponent(t)}`}function Cr(e,t={}){try{const r={event:e};for(const[s,o]of Object.entries(t))o!==void 0&&(r[s]=o);const a=JSON.stringify(r);typeof navigator<"u"&&navigator.sendBeacon?navigator.sendBeacon("/api/event",a):fetch("/api/event",{method:"POST",body:a,keepalive:!0})}catch{}}function Dr(e,t){Cr("cta_clicked",{cta:e,surface:t})}function B_(e){var t,r,a="";if(typeof e=="string"||typeof e=="number")a+=e;else if(typeof e=="object")if(Array.isArray(e)){var s=e.length;for(t=0;t<s;t++)e[t]&&(r=B_(e[t]))&&(a&&(a+=" "),a+=r)}else for(r in e)e[r]&&(a&&(a+=" "),a+=r);return a}function kC(){for(var e,t,r=0,a="",s=arguments.length;r<s;r++)(e=arguments[r])&&(t=B_(e))&&(a&&(a+=" "),a+=t);return a}const TC=(e,t)=>{const r=new Array(e.length+t.length);for(let a=0;a<e.length;a++)r[a]=e[a];for(let a=0;a<t.length;a++)r[e.length+a]=t[a];return r},CC=(e,t)=>({classGroupId:e,validator:t}),U_=(e=new Map,t=null,r)=>({nextPart:e,validators:t,classGroupId:r}),vu="-",ry=[],AC="arbitrary..",MC=e=>{const t=RC(e),{conflictingClassGroups:r,conflictingClassGroupModifiers:a}=e;return{getClassGroupId:c=>{if(c.startsWith("[")&&c.endsWith("]"))return OC(c);const d=c.split(vu),f=d[0]===""&&d.length>1?1:0;return H_(d,f,t)},getConflictingClassGroupIds:(c,d)=>{if(d){const f=a[c],h=r[c];return f?h?TC(h,f):f:h||ry}return r[c]||ry}}},H_=(e,t,r)=>{if(e.length-t===0)return r.classGroupId;const s=e[t],o=r.nextPart.get(s);if(o){const h=H_(e,t+1,o);if(h)return h}const c=r.validators;if(c===null)return;const d=t===0?e.join(vu):e.slice(t).join(vu),f=c.length;for(let h=0;h<f;h++){const m=c[h];if(m.validator(d))return m.classGroupId}},OC=e=>e.slice(1,-1).indexOf(":")===-1?void 0:(()=>{const t=e.slice(1,-1),r=t.indexOf(":"),a=t.slice(0,r);return a?AC+a:void 0})(),RC=e=>{const{theme:t,classGroups:r}=e;return DC(r,t)},DC=(e,t)=>{const r=U_();for(const a in e){const s=e[a];_p(s,r,a,t)}return r},_p=(e,t,r,a)=>{const s=e.length;for(let o=0;o<s;o++){const c=e[o];jC(c,t,r,a)}},jC=(e,t,r,a)=>{if(typeof e=="string"){LC(e,t,r);return}if(typeof e=="function"){zC(e,t,r,a);return}IC(e,t,r,a)},LC=(e,t,r)=>{const a=e===""?t:$_(t,e);a.classGroupId=r},zC=(e,t,r,a)=>{if(BC(e)){_p(e(a),t,r,a);return}t.validators===null&&(t.validators=[]),t.validators.push(CC(r,e))},IC=(e,t,r,a)=>{const s=Object.enLine truncated
`,h="/",m="*",p="",y="comment",x="declaration";function _(S,w){if(typeof S!="string")throw new TypeError("First argument must be a string");if(!S)return[];w=w||{};var k=1,E=1;function M(A){var $=A.match(t);$&&(k+=$.length);var O=A.lastIndexOf(f);E=~O?A.length-O:E+A.length}function I(){var A={line:k,column:E};return function($){return $.position=new R(A),Z(),$}}function R(A){this.start=A,this.end={line:k,column:E},this.source=w.source}R.prototype.content=S;function U(A){var $=new Error(w.source+":"+k+":"+E+": "+A);if($.reason=A,$.filename=w.source,$.line=k,$.column=E,$.source=S,!w.silent)throw $}function B(A){var $=A.exec(S);if($){var O=$[0];return M(O),S=S.slice(O.length),$}}function Z(){B(r)}function D(A){var $;for(A=A||[];$=z();)$!==!1&&A.push($);return A}function z(){var A=I();if(!(h!=S.charAt(0)||m!=S.charAt(1))){for(var $=2;p!=S.charAt($)&&(m!=S.charAt($)||h!=S.charAt($+1));)++$;if($+=2,p===S.charAt($-1))return U("End of comment missing");var O=S.slice(2,$-2);return E+=2,M(O),S=S.slice($),E+=2,A({type:y,comment:O})}}function P(){var A=I(),$=B(a);if($){if(z(),!B(s))return U("property missing ':'");var O=B(o),H=A({type:x,property:N($[0].replace(e,p)),value:O?N(O[0].replace(e,p)):p});return B(c),H}}function V(){var A=[];D(A);for(var $;$=P();)$!==!1&&(A.push($),D(A));return A}return Z(),V()}function N(S){return S?S.replace(d,p):p}return gh=_,gh}var my;function BA(){if(my)return js;my=1;var e=js&&js.__importDefault||function(a){return a&&a.__esModule?a:{default:a}};Object.defineProperty(js,"__esModule",{value:!0}),js.default=r;const t=e(IA());function r(a,s){let o=null;if(!a||typeof a!="string")return o;const c=(0,t.default)(a),d=typeof s=="function";return c.forEach(f=>{if(f.type!=="declaration")return;const{property:h,value:m}=f;d?s(h,m,f):m&&(o=o||{},o[h]=m)}),o}return js}var Zl={},py;function UA(){if(py)return Zl;py=1,Object.defineProperty(Zl,"__esModule",{value:!0}),Zl.camelCase=void 0;var e=/^--[a-zA-Z0-9_-]+$/,t=/-([a-z])/g,r=/^[^-]+$/,a=/^-(webkit|moz|ms|o|khtml)-/,s=/^-(ms)-/,o=function(h){return!h||r.test(h)||e.test(h)},c=function(h,m){return m.toUpperCase()},d=function(h,m){return"".concat(m,"-")},f=function(h,m){return m===void 0&&(m={}),o(h)?h:(h=h.toLowerCase(),m.reactCompat?h=h.replace(s,d):h=h.replace(a,d),h.replace(t,c))};return Zl.camelCase=f,Zl}var Ql,gy;function HA(){if(gy)return Ql;gy=1;var e=Ql&&Ql.__importDefault||function(s){return s&&s.__esModule?s:{default:s}},t=e(BA()),r=UA();function a(s,o){var c={};return!s||typeof s!="string"||(0,t.default)(s,function(d,f){d&&f&&(c[(0,r.camelCase)(d,o)]=f)}),c}return a.default=a,Ql=a,Ql}var $A=HA();const qA=To($A),sw=lw("end"),Sp=lw("start");function lw(e){return t;function t(r){const a=r&&r.position&&r.position[e]||{};if(typeof a.line=="number"&&a.line>0&&typeof a.column=="number"&&a.column>0)return{line:a.line,column:a.column,offset:typeof a.offset=="number"&&a.offset>-1?a.offset:void 0}}}function PA(e){const t=Sp(e),r=sw(e);if(t&&r)return{start:t,end:r}}function lo(e){return!e||typeof e!="object"?"":"position"in e||"type"in e?by(e.position):"start"in e||"end"in e?by(e):"line"in e||"column"in e?Fm(e):""}function Fm(e){return xy(e&&e.line)+":"+xy(e&&e.column)}function by(e){return Fm(e&&e.start)+"-"+Fm(e&&e.end)}function xy(e){return e&&typeof e=="number"?e:1}class Cn extends Error{constructor(t,r,a){super(),typeof r=="string"&&(a=r,r=void 0);let s="",o={},c=!1;if(r&&("line"in r&&"column"in r?o={place:r}:"start"in r&&"end"in r?o={place:r}:"type"in r?o={ancestors:[r],place:r.position}:o={...r}),typeof t=="string"?s=t:!o.cause&&t&&(c=!0,s=t.message,o.cause=t),!o.ruleId&&!o.source&&typeof a=="string"){const f=a.indexOf(":");f===-1?o.ruleId=a:(o.source=a.slice(0,f),o.ruleId=a.slice(f+1))}if(!o.place&&o.ancestors&&o.ancestors){const f=o.ancestors[o.ancestors.length-1];f&&(o.place=f.position)}const d=o.place&&"start"in o.place?o.place.start:o.place;this.ancestors=o.ancestors||void 0,this.cause=o.cause||void 0,this.column=d?d.column:void 0,this.fatal=void 0,this.file="",this.message=s,this.line=d?d.line:void 0,this.name=lo(o.place)||"1:1",this.place=o.place||void 0,this.reason=this.message,this.ruleId=o.ruleId||void 0,this.source=o.source||void 0,this.stack=c&&o.cause&&typeof o.cause.stack=="string"?o.cause.stack:"",this.actual=void 0,this.expected=void 0,this.note=void 0,this.url=void 0}}Cn.prototype.file="";Cn.prototype.name="";Cn.prototype.reason="";Cn.prototype.message="";Cn.prototype.stack="";Cn.prototype.column=void 0;Cn.prototype.line=void 0;Cn.prototype.ancestors=void 0;Cn.prototype.cause=void 0;Cn.prototype.fatal=void 0;Cn.prototype.place=void 0;Cn.prototype.ruleId=void 0;Cn.prototype.source=void 0;const kp={}.hasOwnProperty,FA=new Map,GA=/[A-Z]/g,VA=new Set(["table","tbody","thead","tfoot","tr"]),YA=new Set(["td","th"]),ow="https://github.com/syntax-tree/hast-util-to-jsx-runtime";function XA(e,t){if(!t||t.Fragment===void 0)throw new TypeError("Expected `Fragment` in options");const r=t.filePath||void 0;let a;if(t.development){if(typeof t.j Line truncated
*/const vT=[["path",{d:"M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z",key:"1xq2db"}]],_T=Me("zap",vT),wT={open:{label:"Open",color:"bg-red-500/10 text-red-400 border-red-500/20",dotColor:"bg-red-500",description:"Newly discovered, awaiting triage"},in_progress:{label:"In Progress",color:"bg-blue-500/10 text-blue-400 border-blue-500/20",dotColor:"bg-blue-500",description:"Someone is working on this"},snoozed:{label:"Snoozed",color:"bg-purple-500/10 text-purple-400 border-purple-500/20",dotColor:"bg-purple-500",description:"Temporarily hidden until a follow-up date"},fixed:{label:"Fixed",color:"bg-emerald-500/10 text-emerald-400 border-emerald-500/20",dotColor:"bg-emerald-500",description:"This vulnerability has been fixed"},ignored:{label:"Ignored",color:"bg-gray-500/10 text-gray-400 border-gray-500/20",dotColor:"bg-gray-500",description:"Acknowledged but accepted"}},ET={trivial:{label:"Trivial",color:"bg-emerald-500/10 text-emerald-400 border-emerald-500/20"},low:{label:"Low",color:"bg-blue-500/10 text-blue-400 border-blue-500/20"},medium:{label:"Medium",color:"bg-yellow-500/10 text-yellow-400 border-yellow-500/20"},high:{label:"High",color:"bg-orange-500/10 text-orange-400 border-orange-500/20"}},I_={critical:"bg-red-500/20 text-red-500 border-red-500/30",high:"bg-orange-500/20 text-orange-500 border-orange-500/30",medium:"bg-yellow-500/20 text-yellow-500 border-yellow-500/30",low:"bg-blue-500/20 text-blue-500 border-blue-500/30"};function Zc(e){return e.original_severity!=null&&e.original_severity!==e.severity}const NT={js:"javascript",ts:"typescript",tsx:"typescript",jsx:"javascript",py:"python",rb:"ruby",go:"go",rs:"rust",java:"java",php:"php",cs:"csharp",cpp:"cpp",c:"c",sh:"bash",bash:"bash",sql:"sql",html:"html",css:"css",json:"json",yaml:"yaml",yml:"yaml",xml:"xml"};function ST(e){var r;if(!e)return null;const t=(r=e.split(".").pop())==null?void 0:r.toLowerCase();return t&&NT[t]||null}function yp(e){switch(e){case"critical":return"bg-red-500";case"high":return"bg-orange-500";case"medium":return"bg-yellow-500";default:return"bg-blue-500"}}async function vp(e){try{await navigator.clipboard.writeText(e)}catch{const t=document.createElement("textarea");t.value=e,t.style.position="absolute",t.style.left="-9999px",document.body.appendChild(t),t.select(),document.execCommand("copy"),document.body.removeChild(t)}}const $u="https://app.strix.ai/api/auth/signup",kT="https://strix.ai/pricing",CT="ref=oss_viewer&utm_source=oss_viewer&utm_medium=local_viewer&utm_campaign=oss_viewer";function fa(e,t){const r=e.includes("?")?"&":"?";return`${e}${r}${CT}&utm_content=${encodeURIComponent(t)}`}function Tr(e,t={}){try{const r={event:e};for(const[s,o]of Object.entries(t))o!==void 0&&(r[s]=o);const a=JSON.stringify(r);typeof navigator<"u"&&navigator.sendBeacon?navigator.sendBeacon("/api/event",a):fetch("/api/event",{method:"POST",body:a,keepalive:!0})}catch{}}function Dr(e,t){Tr("cta_clicked",{cta:e,surface:t})}function B_(e){var t,r,a="";if(typeof e=="string"||typeof e=="number")a+=e;else if(typeof e=="object")if(Array.isArray(e)){var s=e.length;for(t=0;t<s;t++)e[t]&&(r=B_(e[t]))&&(a&&(a+=" "),a+=r)}else for(r in e)e[r]&&(a&&(a+=" "),a+=r);return a}function TT(){for(var e,t,r=0,a="",s=arguments.length;r<s;r++)(e=arguments[r])&&(t=B_(e))&&(a&&(a+=" "),a+=t);return a}const AT=(e,t)=>{const r=new Array(e.length+t.length);for(let a=0;a<e.length;a++)r[a]=e[a];for(let a=0;a<t.length;a++)r[e.length+a]=t[a];return r},MT=(e,t)=>({classGroupId:e,validator:t}),U_=(e=new Map,t=null,r)=>({nextPart:e,validators:t,classGroupId:r}),vu="-",ry=[],OT="arbitrary..",RT=e=>{const t=jT(e),{conflictingClassGroups:r,conflictingClassGroupModifiers:a}=e;return{getClassGroupId:c=>{if(c.startsWith("[")&&c.endsWith("]"))return DT(c);const d=c.split(vu),f=d[0]===""&&d.length>1?1:0;return H_(d,f,t)},getConflictingClassGroupIds:(c,d)=>{if(d){const f=a[c],h=r[c];return f?h?AT(h,f):f:h||ry}return r[c]||ry}}},H_=(e,t,r)=>{if(e.length-t===0)return r.classGroupId;const s=e[t],o=r.nextPart.get(s);if(o){const h=H_(e,t+1,o);if(h)return h}const c=r.validators;if(c===null)return;const d=t===0?e.join(vu):e.slice(t).join(vu),f=c.length;for(let h=0;h<f;h++){const m=c[h];if(m.validator(d))return m.classGroupId}},DT=e=>e.slice(1,-1).indexOf(":")===-1?void 0:(()=>{const t=e.slice(1,-1),r=t.indexOf(":"),a=t.slice(0,r);return a?OT+a:void 0})(),jT=e=>{const{theme:t,classGroups:r}=e;return LT(r,t)},LT=(e,t)=>{const r=U_();for(const a in e){const s=e[a];_p(s,r,a,t)}return r},_p=(e,t,r,a)=>{const s=e.length;for(let o=0;o<s;o++){const c=e[o];zT(c,t,r,a)}},zT=(e,t,r,a)=>{if(typeof e=="string"){IT(e,t,r);return}if(typeof e=="function"){BT(e,t,r,a);return}UT(e,t,r,a)},IT=(e,t,r)=>{const a=e===""?t:$_(t,e);a.classGroupId=r},BT=(e,t,r,a)=>{if(HT(e)){_p(e(a),t,r,a);return}t.validators===null&&(t.validators=[]),t.validators.push(MT(r,e))},UT=(e,t,r,a)=>{const s=Object.enLine truncated
`,h="/",m="*",p="",y="comment",x="declaration";function _(S,w){if(typeof S!="string")throw new TypeError("First argument must be a string");if(!S)return[];w=w||{};var k=1,E=1;function M(T){var $=T.match(t);$&&(k+=$.length);var O=T.lastIndexOf(f);E=~O?T.length-O:E+T.length}function I(){var T={line:k,column:E};return function($){return $.position=new R(T),Z(),$}}function R(T){this.start=T,this.end={line:k,column:E},this.source=w.source}R.prototype.content=S;function U(T){var $=new Error(w.source+":"+k+":"+E+": "+T);if($.reason=T,$.filename=w.source,$.line=k,$.column=E,$.source=S,!w.silent)throw $}function B(T){var $=T.exec(S);if($){var O=$[0];return M(O),S=S.slice(O.length),$}}function Z(){B(r)}function D(T){var $;for(T=T||[];$=z();)$!==!1&&T.push($);return T}function z(){var T=I();if(!(h!=S.charAt(0)||m!=S.charAt(1))){for(var $=2;p!=S.charAt($)&&(m!=S.charAt($)||h!=S.charAt($+1));)++$;if($+=2,p===S.charAt($-1))return U("End of comment missing");var O=S.slice(2,$-2);return E+=2,M(O),S=S.slice($),E+=2,T({type:y,comment:O})}}function V(){var T=I(),$=B(a);if($){if(z(),!B(s))return U("property missing ':'");var O=B(o),H=T({type:x,property:N($[0].replace(e,p)),value:O?N(O[0].replace(e,p)):p});return B(c),H}}function P(){var T=[];D(T);for(var $;$=V();)$!==!1&&(T.push($),D(T));return T}return Z(),P()}function N(S){return S?S.replace(d,p):p}return gh=_,gh}var my;function HA(){if(my)return js;my=1;var e=js&&js.__importDefault||function(a){return a&&a.__esModule?a:{default:a}};Object.defineProperty(js,"__esModule",{value:!0}),js.default=r;const t=e(UA());function r(a,s){let o=null;if(!a||typeof a!="string")return o;const c=(0,t.default)(a),d=typeof s=="function";return c.forEach(f=>{if(f.type!=="declaration")return;const{property:h,value:m}=f;d?s(h,m,f):m&&(o=o||{},o[h]=m)}),o}return js}var Zl={},py;function $A(){if(py)return Zl;py=1,Object.defineProperty(Zl,"__esModule",{value:!0}),Zl.camelCase=void 0;var e=/^--[a-zA-Z0-9_-]+$/,t=/-([a-z])/g,r=/^[^-]+$/,a=/^-(webkit|moz|ms|o|khtml)-/,s=/^-(ms)-/,o=function(h){return!h||r.test(h)||e.test(h)},c=function(h,m){return m.toUpperCase()},d=function(h,m){return"".concat(m,"-")},f=function(h,m){return m===void 0&&(m={}),o(h)?h:(h=h.toLowerCase(),m.reactCompat?h=h.replace(s,d):h=h.replace(a,d),h.replace(t,c))};return Zl.camelCase=f,Zl}var Ql,gy;function qA(){if(gy)return Ql;gy=1;var e=Ql&&Ql.__importDefault||function(s){return s&&s.__esModule?s:{default:s}},t=e(HA()),r=$A();function a(s,o){var c={};return!s||typeof s!="string"||(0,t.default)(s,function(d,f){d&&f&&(c[(0,r.camelCase)(d,o)]=f)}),c}return a.default=a,Ql=a,Ql}var PA=qA();const FA=Co(PA),sw=lw("end"),Sp=lw("start");function lw(e){return t;function t(r){const a=r&&r.position&&r.position[e]||{};if(typeof a.line=="number"&&a.line>0&&typeof a.column=="number"&&a.column>0)return{line:a.line,column:a.column,offset:typeof a.offset=="number"&&a.offset>-1?a.offset:void 0}}}function GA(e){const t=Sp(e),r=sw(e);if(t&&r)return{start:t,end:r}}function lo(e){return!e||typeof e!="object"?"":"position"in e||"type"in e?by(e.position):"start"in e||"end"in e?by(e):"line"in e||"column"in e?Fm(e):""}function Fm(e){return xy(e&&e.line)+":"+xy(e&&e.column)}function by(e){return Fm(e&&e.start)+"-"+Fm(e&&e.end)}function xy(e){return e&&typeof e=="number"?e:1}class An extends Error{constructor(t,r,a){super(),typeof r=="string"&&(a=r,r=void 0);let s="",o={},c=!1;if(r&&("line"in r&&"column"in r?o={place:r}:"start"in r&&"end"in r?o={place:r}:"type"in r?o={ancestors:[r],place:r.position}:o={...r}),typeof t=="string"?s=t:!o.cause&&t&&(c=!0,s=t.message,o.cause=t),!o.ruleId&&!o.source&&typeof a=="string"){const f=a.indexOf(":");f===-1?o.ruleId=a:(o.source=a.slice(0,f),o.ruleId=a.slice(f+1))}if(!o.place&&o.ancestors&&o.ancestors){const f=o.ancestors[o.ancestors.length-1];f&&(o.place=f.position)}const d=o.place&&"start"in o.place?o.place.start:o.place;this.ancestors=o.ancestors||void 0,this.cause=o.cause||void 0,this.column=d?d.column:void 0,this.fatal=void 0,this.file="",this.message=s,this.line=d?d.line:void 0,this.name=lo(o.place)||"1:1",this.place=o.place||void 0,this.reason=this.message,this.ruleId=o.ruleId||void 0,this.source=o.source||void 0,this.stack=c&&o.cause&&typeof o.cause.stack=="string"?o.cause.stack:"",this.actual=void 0,this.expected=void 0,this.note=void 0,this.url=void 0}}An.prototype.file="";An.prototype.name="";An.prototype.reason="";An.prototype.message="";An.prototype.stack="";An.prototype.column=void 0;An.prototype.line=void 0;An.prototype.ancestors=void 0;An.prototype.cause=void 0;An.prototype.fatal=void 0;An.prototype.place=void 0;An.prototype.ruleId=void 0;An.prototype.source=void 0;const kp={}.hasOwnProperty,VA=new Map,YA=/[A-Z]/g,XA=new Set(["table","tbody","thead","tfoot","tr"]),KA=new Set(["td","th"]),ow="https://github.com/syntax-tree/hast-util-to-jsx-runtime";function ZA(e,t){if(!t||t.Fragment===void 0)throw new TypeError("Expected `Fragment` in options");const r=t.filePath||void 0;let a;if(t.development){if(typeof t.j Line truncated
`;break}case-3:{c=`\r
`;break}case-2:{c=t?" ":" ";break}case-1:{if(!t&&s)continue;c=" ";break}default:c=String.fromCharCode(o)}s=o===-2,a.push(c)}return a.join("")}function nO(e){const a={constructs:hw([W5,...(e||{}).extensions||[]]),content:s(bM),defined:[],document:s(yM),flow:s(I5),lazy:{},string:s(H5),text:s($5)};return a;function s(o){return c;function c(d){return J5(a,o,d)}}}function rO(e){for(;!xw(e););return e}const Cy=/[\0\t\n\r]/g;function iO(){let e=1,t="",r=!0,a;return s;function s(o,c,d){const f=[];let h,m,p,y,x;for(o=t+(typeof o=="string"?o.toString():new TextDecoder(c||void 0).decode(o)),p=0,t="",r&&(o.charCodeAt(0)===65279&&p++,r=void 0);p<o.length;){if(Cy.lastIndex=p,h=Cy.exec(o),y=h&&h.index!==void 0?h.index:o.length,x=o.charCodeAt(y),!h){t=o.slice(p);break}if(x===10&&p===y&&a)f.push(-3),a=void 0;else switch(a&&(f.push(-5),a=void 0),p<y&&(f.push(o.slice(p,y)),e+=y-p),x){case 0:{f.push(65533),e++;break}case 9:{for(m=Math.ceil(e/4)*4,f.push(-2);e++<m;)f.push(-1);break}case 10:{f.push(-4),e=1;break}default:a=!0,e=1}p=y+1}return d&&(a&&f.push(-5),t&&f.push(t),f.push(null)),f}}const aO=/\\([!-/:-@[-`{-~])|&(#(?:\d{1,7}|x[\da-f]{1,6})|[\da-z]{1,31});/gi;function sO(e){return e.replace(aO,lO)}function lO(e,t,r){if(t)return t;if(r.charCodeAt(0)===35){const s=r.charCodeAt(1),o=s===120||s===88;return mw(r.slice(o?2:1),o?16:10)}return Mp(r)||e}const Nw={}.hasOwnProperty;function oO(e,t,r){return t&&typeof t=="object"&&(r=t,t=void 0),cO(r)(rO(nO(r).document().write(iO()(e,t,!0))))}function cO(e){const t={transforms:[],canContainEols:["emphasis","fragment","heading","paragraph","strong"],enter:{autolink:o(Yt),autolinkProtocol:Z,autolinkEmail:Z,atxHeading:o(je),blockQuote:o(ce),characterEscape:Z,characterReference:Z,codeFenced:o(fe),codeFencedFenceInfo:c,codeFencedFenceMeta:c,codeIndented:o(fe,c),codeText:o(be,c),codeTextData:Z,data:Z,codeFlowValue:Z,definition:o(we),definitionDestinationString:c,definitionLabelString:c,definitionTitleString:c,emphasis:o(Ne),hardBreakEscape:o($e),hardBreakTrailing:o($e),htmlFlow:o(st,c),htmlFlowData:Z,htmlText:o(st,c),htmlTextData:Z,image:o(Rt),label:c,link:o(Yt),listItem:o(Xt),listItemValue:y,listOrdered:o(Pt,p),listUnordered:o(Pt),paragraph:o(Yn),reference:L,referenceString:c,resourceDestinationString:c,resourceTitleString:c,setextHeading:o(je),strong:o(wn),thematicBreak:o(It)},exit:{atxHeading:f(),atxHeadingSequence:I,autolink:f(),autolinkEmail:te,autolinkProtocol:W,blockQuote:f(),characterEscapeValue:D,characterReferenceMarkerHexadecimal:q,characterReferenceMarkerNumeric:q,characterReferenceValue:Q,characterReference:J,codeFenced:f(S),codeFencedFence:N,codeFencedFenceInfo:x,codeFencedFenceMeta:_,codeFlowValue:D,codeIndented:f(w),codeText:f($),codeTextData:D,data:D,definition:f(),definitionDestinationString:M,definitionLabelString:k,definitionTitleString:E,emphasis:f(),hardBreakEscape:f(P),hardBreakTrailing:f(P),htmlFlow:f(V),htmlFlowData:D,htmlText:f(A),htmlTextData:D,image:f(H),label:K,labelText:X,lineEnding:z,link:f(O),listItem:f(),listOrdered:f(),listUnordered:f(),paragraph:f(),referenceString:G,resourceDestinationString:T,resourceTitleString:j,resource:Y,setextHeading:f(B),setextHeadingLineSequence:U,setextHeadingText:R,strong:f(),thematicBreak:f()}};Sw(t,(e||{}).mdastExtensions||[]);const r={};return a;function a(ue){let xe={type:"root",children:[]};const Oe={stack:[xe],tokenStack:[],config:t,enter:d,exit:h,buffer:c,resume:m,data:r},Fe=[];let Ze=-1;for(;++Ze<ue.length;)if(ue[Ze][1].type==="listOrdered"||ue[Ze][1].type==="listUnordered")if(ue[Ze][0]==="enter")Fe.push(Ze);else{const on=Fe.pop();Ze=s(ue,on,Ze)}for(Ze=-1;++Ze<ue.length;){const on=t[ue[Ze][0]];Nw.call(on,ue[Ze][1].type)&&on[ue[Ze][1].type].call(Object.assign({sliceSerialize:ue[Ze][2].sliceSerialize},Oe),ue[Ze][1])}if(Oe.tokenStack.length>0){const on=Oe.tokenStack[Oe.tokenStack.length-1];(on[1]||Ay).call(Oe,void 0,on[0])}for(xe.position={start:ia(ue.length>0?ue[0][1].start:{line:1,column:1,offset:0}),end:ia(ue.length>0?ue[ue.length-2][1].end:{line:1,column:1,offset:0})},Ze=-1;++Ze<t.transforms.length;)xe=t.transforms[Ze](xe)||xe;return xe}function s(ue,xe,Oe){let Fe=xe-1,Ze=-1,on=!1,En,Kt,At,Wt;for(;++Fe<=Oe;){const ut=ue[Fe];switch(ut[1].type){case"listUnordered":case"listOrdered":case"blockQuote":{ut[0]==="enter"?Ze++:Ze--,Wt=void 0;break}case"lineEndingBlank":{ut[0]==="enter"&&(En&&!Wt&&!Ze&&!At&&(At=Fe),Wt=void 0);break}case"linePrefix":case"listItemValue":case"listItemMarker":case"listItemPrefix":case"listItemPrefixWhitespace":break;default:Wt=void 0}if(!Ze&&ut[0]==="enter"&&ut[1].type==="listItemPrefix"||Ze===-1&&ut[0]==="exit"&&(ut[1].type==="listUnordered"||ut[1].type==="listOrdered")){if(En){let zn=Fe;for(Kt=void 0;zn--;){const cn=ue[zn];if(cn[1].type==="lineEnding"||cn[1].type==="lineEndingBlank"){if(cn[0]==="exit")continue;Kt&&(ue[Kt][1].type="lineEndingBlank",on=!0),cn[1].type="lineEnding",Kt=zn}else if(!(cn[1].type==="linePrefix"||cn[1].type==="blockQuotePrefix"||cn[1].type==="blockQuotePrefixWhitespace"||cn[Line truncated
`}]}function mO(e,t){const r=t.value?t.value+`
`:"",a={},s=t.lang?t.lang.split(/\s+/):[];s.length>0&&(a.className=["language-"+s[0]]);let o={type:"element",tagName:"code",properties:a,children:[{type:"text",value:r}]};return t.meta&&(o.data={meta:t.meta}),e.patch(t,o),o=e.applyData(t,o),o={type:"element",tagName:"pre",properties:{},children:[o]},e.patch(t,o),o}function pO(e,t){const r={type:"element",tagName:"del",properties:{},children:e.all(t)};return e.patch(t,r),e.applyData(t,r)}function gO(e,t){const r={type:"element",tagName:"em",properties:{},children:e.all(t)};return e.patch(t,r),e.applyData(t,r)}function bO(e,t){const r=typeof e.options.clobberPrefix=="string"?e.options.clobberPrefix:"user-content-",a=String(t.identifier).toUpperCase(),s=nl(a.toLowerCase()),o=e.footnoteOrder.indexOf(a);let c,d=e.footnoteCounts.get(a);d===void 0?(d=0,e.footnoteOrder.push(a),c=e.footnoteOrder.length):c=o+1,d+=1,e.footnoteCounts.set(a,d);const f={type:"element",tagName:"a",properties:{href:"#"+r+"fn-"+s,id:r+"fnref-"+s+(d>1?"-"+d:""),dataFootnoteRef:!0,ariaDescribedBy:["footnote-label"]},children:[{type:"text",value:String(c)}]};e.patch(t,f);const h={type:"element",tagName:"sup",properties:{},children:[f]};return e.patch(t,h),e.applyData(t,h)}function xO(e,t){const r={type:"element",tagName:"h"+t.depth,properties:{},children:e.all(t)};return e.patch(t,r),e.applyData(t,r)}function yO(e,t){if(e.options.allowDangerousHtml){const r={type:"raw",value:t.value};return e.patch(t,r),e.applyData(t,r)}}function kw(e,t){const r=t.referenceType;let a="]";if(r==="collapsed"?a+="[]":r==="full"&&(a+="["+(t.label||t.identifier)+"]"),t.type==="imageReference")return[{type:"text",value:"!["+t.alt+a}];const s=e.all(t),o=s[0];o&&o.type==="text"?o.value="["+o.value:s.unshift({type:"text",value:"["});const c=s[s.length-1];return c&&c.type==="text"?c.value+=a:s.push({type:"text",value:a}),s}function vO(e,t){const r=String(t.identifier).toUpperCase(),a=e.definitionById.get(r);if(!a)return kw(e,t);const s={src:nl(a.url||""),alt:t.alt};a.title!==null&&a.title!==void 0&&(s.title=a.title);const o={type:"element",tagName:"img",properties:s,children:[]};return e.patch(t,o),e.applyData(t,o)}function _O(e,t){const r={src:nl(t.url)};t.alt!==null&&t.alt!==void 0&&(r.alt=t.alt),t.title!==null&&t.title!==void 0&&(r.title=t.title);const a={type:"element",tagName:"img",properties:r,children:[]};return e.patch(t,a),e.applyData(t,a)}function wO(e,t){const r={type:"text",value:t.value.replace(/\r?\n|\r/g," ")};e.patch(t,r);const a={type:"element",tagName:"code",properties:{},children:[r]};return e.patch(t,a),e.applyData(t,a)}function EO(e,t){const r=String(t.identifier).toUpperCase(),a=e.definitionById.get(r);if(!a)return kw(e,t);const s={href:nl(a.url||"")};a.title!==null&&a.title!==void 0&&(s.title=a.title);const o={type:"element",tagName:"a",properties:s,children:e.all(t)};return e.patch(t,o),e.applyData(t,o)}function NO(e,t){const r={href:nl(t.url)};t.title!==null&&t.title!==void 0&&(r.title=t.title);const a={type:"element",tagName:"a",properties:r,children:e.all(t)};return e.patch(t,a),e.applyData(t,a)}function SO(e,t,r){const a=e.all(t),s=r?kO(r):Tw(t),o={},c=[];if(typeof t.checked=="boolean"){const m=a[0];let p;m&&m.type==="element"&&m.tagName==="p"?p=m:(p={type:"element",tagName:"p",properties:{},children:[]},a.unshift(p)),p.children.length>0&&p.children.unshift({type:"text",value:" "}),p.children.unshift({type:"element",tagName:"input",properties:{type:"checkbox",checked:t.checked,disabled:!0},children:[]}),o.className=["task-list-item"]}let d=-1;for(;++d<a.length;){const m=a[d];(s||d!==0||m.type!=="element"||m.tagName!=="p")&&c.push({type:"text",value:`
`;break}case-2:{c=t?" ":" ";break}case-1:{if(!t&&s)continue;c=" ";break}default:c=String.fromCharCode(o)}s=o===-2,a.push(c)}return a.join("")}function iO(e){const a={constructs:hw([eO,...(e||{}).extensions||[]]),content:s(yM),defined:[],document:s(_M),flow:s(U5),lazy:{},string:s(q5),text:s(P5)};return a;function s(o){return c;function c(d){return tO(a,o,d)}}}function aO(e){for(;!xw(e););return e}const Ty=/[\0\t\n\r]/g;function sO(){let e=1,t="",r=!0,a;return s;function s(o,c,d){const f=[];let h,m,p,y,x;for(o=t+(typeof o=="string"?o.toString():new TextDecoder(c||void 0).decode(o)),p=0,t="",r&&(o.charCodeAt(0)===65279&&p++,r=void 0);p<o.length;){if(Ty.lastIndex=p,h=Ty.exec(o),y=h&&h.index!==void 0?h.index:o.length,x=o.charCodeAt(y),!h){t=o.slice(p);break}if(x===10&&p===y&&a)f.push(-3),a=void 0;else switch(a&&(f.push(-5),a=void 0),p<y&&(f.push(o.slice(p,y)),e+=y-p),x){case 0:{f.push(65533),e++;break}case 9:{for(m=Math.ceil(e/4)*4,f.push(-2);e++<m;)f.push(-1);break}case 10:{f.push(-4),e=1;break}default:a=!0,e=1}p=y+1}return d&&(a&&f.push(-5),t&&f.push(t),f.push(null)),f}}const lO=/\\([!-/:-@[-`{-~])|&(#(?:\d{1,7}|x[\da-f]{1,6})|[\da-z]{1,31});/gi;function oO(e){return e.replace(lO,cO)}function cO(e,t,r){if(t)return t;if(r.charCodeAt(0)===35){const s=r.charCodeAt(1),o=s===120||s===88;return mw(r.slice(o?2:1),o?16:10)}return Mp(r)||e}const Nw={}.hasOwnProperty;function uO(e,t,r){return t&&typeof t=="object"&&(r=t,t=void 0),dO(r)(aO(iO(r).document().write(sO()(e,t,!0))))}function dO(e){const t={transforms:[],canContainEols:["emphasis","fragment","heading","paragraph","strong"],enter:{autolink:o(Yt),autolinkProtocol:Z,autolinkEmail:Z,atxHeading:o(je),blockQuote:o(ce),characterEscape:Z,characterReference:Z,codeFenced:o(fe),codeFencedFenceInfo:c,codeFencedFenceMeta:c,codeIndented:o(fe,c),codeText:o(be,c),codeTextData:Z,data:Z,codeFlowValue:Z,definition:o(we),definitionDestinationString:c,definitionLabelString:c,definitionTitleString:c,emphasis:o(Ne),hardBreakEscape:o($e),hardBreakTrailing:o($e),htmlFlow:o(st,c),htmlFlowData:Z,htmlText:o(st,c),htmlTextData:Z,image:o(Rt),label:c,link:o(Yt),listItem:o(Xt),listItemValue:y,listOrdered:o(Pt,p),listUnordered:o(Pt),paragraph:o(Yn),reference:L,referenceString:c,resourceDestinationString:c,resourceTitleString:c,setextHeading:o(je),strong:o(En),thematicBreak:o(It)},exit:{atxHeading:f(),atxHeadingSequence:I,autolink:f(),autolinkEmail:te,autolinkProtocol:W,blockQuote:f(),characterEscapeValue:D,characterReferenceMarkerHexadecimal:q,characterReferenceMarkerNumeric:q,characterReferenceValue:Q,characterReference:J,codeFenced:f(S),codeFencedFence:N,codeFencedFenceInfo:x,codeFencedFenceMeta:_,codeFlowValue:D,codeIndented:f(w),codeText:f($),codeTextData:D,data:D,definition:f(),definitionDestinationString:M,definitionLabelString:k,definitionTitleString:E,emphasis:f(),hardBreakEscape:f(V),hardBreakTrailing:f(V),htmlFlow:f(P),htmlFlowData:D,htmlText:f(T),htmlTextData:D,image:f(H),label:K,labelText:X,lineEnding:z,link:f(O),listItem:f(),listOrdered:f(),listUnordered:f(),paragraph:f(),referenceString:G,resourceDestinationString:C,resourceTitleString:j,resource:Y,setextHeading:f(B),setextHeadingLineSequence:U,setextHeadingText:R,strong:f(),thematicBreak:f()}};Sw(t,(e||{}).mdastExtensions||[]);const r={};return a;function a(ue){let xe={type:"root",children:[]};const Oe={stack:[xe],tokenStack:[],config:t,enter:d,exit:h,buffer:c,resume:m,data:r},Fe=[];let Ze=-1;for(;++Ze<ue.length;)if(ue[Ze][1].type==="listOrdered"||ue[Ze][1].type==="listUnordered")if(ue[Ze][0]==="enter")Fe.push(Ze);else{const on=Fe.pop();Ze=s(ue,on,Ze)}for(Ze=-1;++Ze<ue.length;){const on=t[ue[Ze][0]];Nw.call(on,ue[Ze][1].type)&&on[ue[Ze][1].type].call(Object.assign({sliceSerialize:ue[Ze][2].sliceSerialize},Oe),ue[Ze][1])}if(Oe.tokenStack.length>0){const on=Oe.tokenStack[Oe.tokenStack.length-1];(on[1]||Ay).call(Oe,void 0,on[0])}for(xe.position={start:ia(ue.length>0?ue[0][1].start:{line:1,column:1,offset:0}),end:ia(ue.length>0?ue[ue.length-2][1].end:{line:1,column:1,offset:0})},Ze=-1;++Ze<t.transforms.length;)xe=t.transforms[Ze](xe)||xe;return xe}function s(ue,xe,Oe){let Fe=xe-1,Ze=-1,on=!1,Nn,Kt,At,Wt;for(;++Fe<=Oe;){const ut=ue[Fe];switch(ut[1].type){case"listUnordered":case"listOrdered":case"blockQuote":{ut[0]==="enter"?Ze++:Ze--,Wt=void 0;break}case"lineEndingBlank":{ut[0]==="enter"&&(Nn&&!Wt&&!Ze&&!At&&(At=Fe),Wt=void 0);break}case"linePrefix":case"listItemValue":case"listItemMarker":case"listItemPrefix":case"listItemPrefixWhitespace":break;default:Wt=void 0}if(!Ze&&ut[0]==="enter"&&ut[1].type==="listItemPrefix"||Ze===-1&&ut[0]==="exit"&&(ut[1].type==="listUnordered"||ut[1].type==="listOrdered")){if(Nn){let In=Fe;for(Kt=void 0;In--;){const cn=ue[In];if(cn[1].type==="lineEnding"||cn[1].type==="lineEndingBlank"){if(cn[0]==="exit")continue;Kt&&(ue[Kt][1].type="lineEndingBlank",on=!0),cn[1].type="lineEnding",Kt=In}else if(!(cn[1].type==="linePrefix"||cn[1].type==="blockQuotePrefix"||cn[1].type==="blockQuotePrefixWhitespace"||cn[Line truncated
`}]}function gO(e,t){const r=t.value?t.value+`
`:"",a={},s=t.lang?t.lang.split(/\s+/):[];s.length>0&&(a.className=["language-"+s[0]]);let o={type:"element",tagName:"code",properties:a,children:[{type:"text",value:r}]};return t.meta&&(o.data={meta:t.meta}),e.patch(t,o),o=e.applyData(t,o),o={type:"element",tagName:"pre",properties:{},children:[o]},e.patch(t,o),o}function bO(e,t){const r={type:"element",tagName:"del",properties:{},children:e.all(t)};return e.patch(t,r),e.applyData(t,r)}function xO(e,t){const r={type:"element",tagName:"em",properties:{},children:e.all(t)};return e.patch(t,r),e.applyData(t,r)}function yO(e,t){const r=typeof e.options.clobberPrefix=="string"?e.options.clobberPrefix:"user-content-",a=String(t.identifier).toUpperCase(),s=nl(a.toLowerCase()),o=e.footnoteOrder.indexOf(a);let c,d=e.footnoteCounts.get(a);d===void 0?(d=0,e.footnoteOrder.push(a),c=e.footnoteOrder.length):c=o+1,d+=1,e.footnoteCounts.set(a,d);const f={type:"element",tagName:"a",properties:{href:"#"+r+"fn-"+s,id:r+"fnref-"+s+(d>1?"-"+d:""),dataFootnoteRef:!0,ariaDescribedBy:["footnote-label"]},children:[{type:"text",value:String(c)}]};e.patch(t,f);const h={type:"element",tagName:"sup",properties:{},children:[f]};return e.patch(t,h),e.applyData(t,h)}function vO(e,t){const r={type:"element",tagName:"h"+t.depth,properties:{},children:e.all(t)};return e.patch(t,r),e.applyData(t,r)}function _O(e,t){if(e.options.allowDangerousHtml){const r={type:"raw",value:t.value};return e.patch(t,r),e.applyData(t,r)}}function kw(e,t){const r=t.referenceType;let a="]";if(r==="collapsed"?a+="[]":r==="full"&&(a+="["+(t.label||t.identifier)+"]"),t.type==="imageReference")return[{type:"text",value:"!["+t.alt+a}];const s=e.all(t),o=s[0];o&&o.type==="text"?o.value="["+o.value:s.unshift({type:"text",value:"["});const c=s[s.length-1];return c&&c.type==="text"?c.value+=a:s.push({type:"text",value:a}),s}function wO(e,t){const r=String(t.identifier).toUpperCase(),a=e.definitionById.get(r);if(!a)return kw(e,t);const s={src:nl(a.url||""),alt:t.alt};a.title!==null&&a.title!==void 0&&(s.title=a.title);const o={type:"element",tagName:"img",properties:s,children:[]};return e.patch(t,o),e.applyData(t,o)}function EO(e,t){const r={src:nl(t.url)};t.alt!==null&&t.alt!==void 0&&(r.alt=t.alt),t.title!==null&&t.title!==void 0&&(r.title=t.title);const a={type:"element",tagName:"img",properties:r,children:[]};return e.patch(t,a),e.applyData(t,a)}function NO(e,t){const r={type:"text",value:t.value.replace(/\r?\n|\r/g," ")};e.patch(t,r);const a={type:"element",tagName:"code",properties:{},children:[r]};return e.patch(t,a),e.applyData(t,a)}function SO(e,t){const r=String(t.identifier).toUpperCase(),a=e.definitionById.get(r);if(!a)return kw(e,t);const s={href:nl(a.url||"")};a.title!==null&&a.title!==void 0&&(s.title=a.title);const o={type:"element",tagName:"a",properties:s,children:e.all(t)};return e.patch(t,o),e.applyData(t,o)}function kO(e,t){const r={href:nl(t.url)};t.title!==null&&t.title!==void 0&&(r.title=t.title);const a={type:"element",tagName:"a",properties:r,children:e.all(t)};return e.patch(t,a),e.applyData(t,a)}function CO(e,t,r){const a=e.all(t),s=r?TO(r):Cw(t),o={},c=[];if(typeof t.checked=="boolean"){const m=a[0];let p;m&&m.type==="element"&&m.tagName==="p"?p=m:(p={type:"element",tagName:"p",properties:{},children:[]},a.unshift(p)),p.children.length>0&&p.children.unshift({type:"text",value:" "}),p.children.unshift({type:"element",tagName:"input",properties:{type:"checkbox",checked:t.checked,disabled:!0},children:[]}),o.className=["task-list-item"]}let d=-1;for(;++d<a.length;){const m=a[d];(s||d!==0||m.type!=="element"||m.tagName!=="p")&&c.push({type:"text",value:`
`}),m.type==="element"&&m.tagName==="p"&&!s?c.push(...m.children):c.push(m)}const f=a[a.length-1];f&&(s||f.type!=="element"||f.tagName!=="p")&&c.push({type:"text",value:`
`});const h={type:"element",tagName:"li",properties:o,children:c};return e.patch(t,h),e.applyData(t,h)}function kO(e){let t=!1;if(e.type==="list"){t=e.spread||!1;const r=e.children;let a=-1;for(;!t&&++a<r.length;)t=Tw(r[a])}return t}function Tw(e){const t=e.spread;return t??e.children.length>1}function TO(e,t){const r={},a=e.all(t);let s=-1;for(typeof t.start=="number"&&t.start!==1&&(r.start=t.start);++s<a.length;){const c=a[s];if(c.type==="element"&&c.tagName==="li"&&c.properties&&Array.isArray(c.properties.className)&&c.properties.className.includes("task-list-item")){r.className=["contains-task-list"];break}}const o={type:"element",tagName:t.ordered?"ol":"ul",properties:r,children:e.wrap(a,!0)};return e.patch(t,o),e.applyData(t,o)}function CO(e,t){const r={type:"element",tagName:"p",properties:{},children:e.all(t)};return e.patch(t,r),e.applyData(t,r)}function AO(e,t){const r={type:"root",children:e.wrap(e.all(t))};return e.patch(t,r),e.applyData(t,r)}function MO(e,t){const r={type:"element",tagName:"strong",properties:{},children:e.all(t)};return e.patch(t,r),e.applyData(t,r)}function OO(e,t){const r=e.all(t),a=r.shift(),s=[];if(a){const c={type:"element",tagName:"thead",properties:{},children:e.wrap([a],!0)};e.patch(t.children[0],c),s.push(c)}if(r.length>0){const c={type:"element",tagName:"tbody",properties:{},children:e.wrap(r,!0)},d=Sp(t.children[1]),f=sw(t.children[t.children.length-1]);d&&f&&(c.position={start:d,end:f}),s.push(c)}const o={type:"element",tagName:"table",properties:{},children:e.wrap(s,!0)};return e.patch(t,o),e.applyData(t,o)}function RO(e,t,r){const a=r?r.children:void 0,o=(a?a.indexOf(t):1)===0?"th":"td",c=r&&r.type==="table"?r.align:void 0,d=c?c.length:t.children.length;let f=-1;const h=[];for(;++f<d;){const p=t.children[f],y={},x=c?c[f]:void 0;x&&(y.align=x);let _={type:"element",tagName:o,properties:y,children:[]};p&&(_.children=e.all(p),e.patch(p,_),_=e.applyData(p,_)),h.push(_)}const m={type:"element",tagName:"tr",properties:{},children:e.wrap(h,!0)};return e.patch(t,m),e.applyData(t,m)}function DO(e,t){const r={type:"element",tagName:"td",properties:{},children:e.all(t)};return e.patch(t,r),e.applyData(t,r)}const My=9,Oy=32;function jO(e){const t=String(e),r=/\r?\n|\r/g;let a=r.exec(t),s=0;const o=[];for(;a;)o.push(Ry(t.slice(s,a.index),s>0,!0),a[0]),s=a.index+a[0].length,a=r.exec(t);return o.push(Ry(t.slice(s),s>0,!1)),o.join("")}function Ry(e,t,r){let a=0,s=e.length;if(t){let o=e.codePointAt(a);for(;o===My||o===Oy;)a++,o=e.codePointAt(a)}if(r){let o=e.codePointAt(s-1);for(;o===My||o===Oy;)s--,o=e.codePointAt(s-1)}return s>a?e.slice(a,s):""}function LO(e,t){const r={type:"text",value:jO(String(t.value))};return e.patch(t,r),e.applyData(t,r)}function zO(e,t){const r={type:"element",tagName:"hr",properties:{},children:[]};return e.patch(t,r),e.applyData(t,r)}const IO={blockquote:fO,break:hO,code:mO,delete:pO,emphasis:gO,footnoteReference:bO,heading:xO,html:yO,imageReference:vO,image:_O,inlineCode:wO,linkReference:EO,link:NO,listItem:SO,list:TO,paragraph:CO,root:AO,strong:MO,table:OO,tableCell:DO,tableRow:RO,text:LO,thematicBreak:zO,toml:Jc,yaml:Jc,definition:Jc,footnoteDefinition:Jc};function Jc(){}const Cw=-1,Fu=0,co=1,wu=2,Rp=3,Dp=4,jp=5,Lp=6,Aw=7,Mw=8,Ow=typeof self=="object"?self:globalThis,Dy=(e,t)=>{switch(e){case"Function":case"SharedWorker":case"Worker":case"eval":case"setInterval":case"setTimeout":throw new TypeError("unable to deserialize "+e)}return new Ow[e](t)},BO=(e,t)=>{const r=(s,o)=>(e.set(o,s),s),a=s=>{if(e.has(s))return e.get(s);const[o,c]=t[s];switch(o){case Fu:case Cw:return r(c,s);case co:{const d=r([],s);for(const f of c)d.push(a(f));return d}case wu:{const d=r({},s);for(const[f,h]of c)d[a(f)]=a(h);return d}case Rp:return r(new Date(c),s);case Dp:{const{source:d,flags:f}=c;return r(new RegExp(d,f),s)}case jp:{const d=r(new Map,s);for(const[f,h]of c)d.set(a(f),a(h));return d}case Lp:{const d=r(new Set,s);for(const f of c)d.add(a(f));return d}case Aw:{const{name:d,message:f}=c;return r(typeof Ow[d]=="function"?Dy(d,f):new Error(f),s)}case Mw:return r(BigInt(c),s);case"BigInt":return r(Object(BigInt(c)),s);case"ArrayBuffer":return r(new Uint8Array(c).buffer,c);case"DataView":{const{buffer:d}=new Uint8Array(c);return r(new DataView(d),c)}}return r(Dy(o,c),s)};return a},jy=e=>BO(new Map,e)(0),Ba="",{toString:UO}={},{keys:HO}=Object,Jl=e=>{const t=typeof e;if(t!=="object"||!e)return[Fu,t];const r=UO.call(e).slice(8,-1);switch(r){case"Array":return[co,Ba];case"Object":return[wu,Ba];case"Date":return[Rp,Ba];case"RegExp":return[Dp,Ba];case"Map":return[jp,Ba];case"Set":return[Lp,Ba];case"DataView":return[co,r]}return r.includes("Array")?[co,r]:e instanceof Error?[Aw,e.name||"Error"]:[wu,r]},eu=([e,t])=>e===Fu&&(t==="function"||t==="symbol"),$O=(e,t,r,a)=>{const s=(c,d)=>{const f=a.push(c)-1;return r.set(d,f),f},o=c=>{if(r.has(c))return r.get(c);let[d,f]=Jl(c);switch(d){case Fu:{let m=c;switch(f){case"bigint":d=Mw,m=c.toString();break;case"function":case"symbol": Line truncated
`});const h={type:"element",tagName:"li",properties:o,children:c};return e.patch(t,h),e.applyData(t,h)}function TO(e){let t=!1;if(e.type==="list"){t=e.spread||!1;const r=e.children;let a=-1;for(;!t&&++a<r.length;)t=Cw(r[a])}return t}function Cw(e){const t=e.spread;return t??e.children.length>1}function AO(e,t){const r={},a=e.all(t);let s=-1;for(typeof t.start=="number"&&t.start!==1&&(r.start=t.start);++s<a.length;){const c=a[s];if(c.type==="element"&&c.tagName==="li"&&c.properties&&Array.isArray(c.properties.className)&&c.properties.className.includes("task-list-item")){r.className=["contains-task-list"];break}}const o={type:"element",tagName:t.ordered?"ol":"ul",properties:r,children:e.wrap(a,!0)};return e.patch(t,o),e.applyData(t,o)}function MO(e,t){const r={type:"element",tagName:"p",properties:{},children:e.all(t)};return e.patch(t,r),e.applyData(t,r)}function OO(e,t){const r={type:"root",children:e.wrap(e.all(t))};return e.patch(t,r),e.applyData(t,r)}function RO(e,t){const r={type:"element",tagName:"strong",properties:{},children:e.all(t)};return e.patch(t,r),e.applyData(t,r)}function DO(e,t){const r=e.all(t),a=r.shift(),s=[];if(a){const c={type:"element",tagName:"thead",properties:{},children:e.wrap([a],!0)};e.patch(t.children[0],c),s.push(c)}if(r.length>0){const c={type:"element",tagName:"tbody",properties:{},children:e.wrap(r,!0)},d=Sp(t.children[1]),f=sw(t.children[t.children.length-1]);d&&f&&(c.position={start:d,end:f}),s.push(c)}const o={type:"element",tagName:"table",properties:{},children:e.wrap(s,!0)};return e.patch(t,o),e.applyData(t,o)}function jO(e,t,r){const a=r?r.children:void 0,o=(a?a.indexOf(t):1)===0?"th":"td",c=r&&r.type==="table"?r.align:void 0,d=c?c.length:t.children.length;let f=-1;const h=[];for(;++f<d;){const p=t.children[f],y={},x=c?c[f]:void 0;x&&(y.align=x);let _={type:"element",tagName:o,properties:y,children:[]};p&&(_.children=e.all(p),e.patch(p,_),_=e.applyData(p,_)),h.push(_)}const m={type:"element",tagName:"tr",properties:{},children:e.wrap(h,!0)};return e.patch(t,m),e.applyData(t,m)}function LO(e,t){const r={type:"element",tagName:"td",properties:{},children:e.all(t)};return e.patch(t,r),e.applyData(t,r)}const My=9,Oy=32;function zO(e){const t=String(e),r=/\r?\n|\r/g;let a=r.exec(t),s=0;const o=[];for(;a;)o.push(Ry(t.slice(s,a.index),s>0,!0),a[0]),s=a.index+a[0].length,a=r.exec(t);return o.push(Ry(t.slice(s),s>0,!1)),o.join("")}function Ry(e,t,r){let a=0,s=e.length;if(t){let o=e.codePointAt(a);for(;o===My||o===Oy;)a++,o=e.codePointAt(a)}if(r){let o=e.codePointAt(s-1);for(;o===My||o===Oy;)s--,o=e.codePointAt(s-1)}return s>a?e.slice(a,s):""}function IO(e,t){const r={type:"text",value:zO(String(t.value))};return e.patch(t,r),e.applyData(t,r)}function BO(e,t){const r={type:"element",tagName:"hr",properties:{},children:[]};return e.patch(t,r),e.applyData(t,r)}const UO={blockquote:mO,break:pO,code:gO,delete:bO,emphasis:xO,footnoteReference:yO,heading:vO,html:_O,imageReference:wO,image:EO,inlineCode:NO,linkReference:SO,link:kO,listItem:CO,list:AO,paragraph:MO,root:OO,strong:RO,table:DO,tableCell:LO,tableRow:jO,text:IO,thematicBreak:BO,toml:Jc,yaml:Jc,definition:Jc,footnoteDefinition:Jc};function Jc(){}const Tw=-1,Fu=0,co=1,wu=2,Rp=3,Dp=4,jp=5,Lp=6,Aw=7,Mw=8,Ow=typeof self=="object"?self:globalThis,Dy=(e,t)=>{switch(e){case"Function":case"SharedWorker":case"Worker":case"eval":case"setInterval":case"setTimeout":throw new TypeError("unable to deserialize "+e)}return new Ow[e](t)},HO=(e,t)=>{const r=(s,o)=>(e.set(o,s),s),a=s=>{if(e.has(s))return e.get(s);const[o,c]=t[s];switch(o){case Fu:case Tw:return r(c,s);case co:{const d=r([],s);for(const f of c)d.push(a(f));return d}case wu:{const d=r({},s);for(const[f,h]of c)d[a(f)]=a(h);return d}case Rp:return r(new Date(c),s);case Dp:{const{source:d,flags:f}=c;return r(new RegExp(d,f),s)}case jp:{const d=r(new Map,s);for(const[f,h]of c)d.set(a(f),a(h));return d}case Lp:{const d=r(new Set,s);for(const f of c)d.add(a(f));return d}case Aw:{const{name:d,message:f}=c;return r(typeof Ow[d]=="function"?Dy(d,f):new Error(f),s)}case Mw:return r(BigInt(c),s);case"BigInt":return r(Object(BigInt(c)),s);case"ArrayBuffer":return r(new Uint8Array(c).buffer,c);case"DataView":{const{buffer:d}=new Uint8Array(c);return r(new DataView(d),c)}}return r(Dy(o,c),s)};return a},jy=e=>HO(new Map,e)(0),Ba="",{toString:$O}={},{keys:qO}=Object,Jl=e=>{const t=typeof e;if(t!=="object"||!e)return[Fu,t];const r=$O.call(e).slice(8,-1);switch(r){case"Array":return[co,Ba];case"Object":return[wu,Ba];case"Date":return[Rp,Ba];case"RegExp":return[Dp,Ba];case"Map":return[jp,Ba];case"Set":return[Lp,Ba];case"DataView":return[co,r]}return r.includes("Array")?[co,r]:e instanceof Error?[Aw,e.name||"Error"]:[wu,r]},eu=([e,t])=>e===Fu&&(t==="function"||t==="symbol"),PO=(e,t,r,a)=>{const s=(c,d)=>{const f=a.push(c)-1;return r.set(d,f),f},o=c=>{if(r.has(c))return r.get(c);let[d,f]=Jl(c);switch(d){case Fu:{let m=c;switch(f){case"bigint":d=Mw,m=c.toString();break;case"function":case"symbol": Line truncated
`},{type:"element",tagName:"ol",properties:{},children:e.wrap(d,!0)},{type:"text",value:`
`}]}}const Gu=(function(e){if(e==null)return XO;if(typeof e=="function")return Vu(e);if(typeof e=="object")return Array.isArray(e)?GO(e):VO(e);if(typeof e=="string")return YO(e);throw new Error("Expected function, string, or object as test")});function GO(e){const t=[];let r=-1;for(;++r<e.length;)t[r]=Gu(e[r]);return Vu(a);function a(...s){let o=-1;for(;++o<t.length;)if(t[o].apply(this,s))return!0;return!1}}function VO(e){const t=e;return Vu(r);function r(a){const s=a;let o;for(o in e)if(s[o]!==t[o])return!1;return!0}}function YO(e){return Vu(t);function t(r){return r&&r.type===e}}function Vu(e){return t;function t(r,a,s){return!!(KO(r)&&e.call(this,r,typeof a=="number"?a:void 0,s||void 0))}}function XO(){return!0}function KO(e){return e!==null&&typeof e=="object"&&"type"in e}const Rw=[],ZO=!0,Ym=!1,QO="skip";function Dw(e,t,r,a){let s;typeof t=="function"&&typeof r!="function"?(a=r,r=t):s=t;const o=Gu(s),c=a?-1:1;d(e,void 0,[])();function d(f,h,m){const p=f&&typeof f=="object"?f:{};if(typeof p.type=="string"){const x=typeof p.tagName=="string"?p.tagName:typeof p.name=="string"?p.name:void 0;Object.defineProperty(y,"name",{value:"node ("+(f.type+(x?"<"+x+">":""))+")"})}return y;function y(){let x=Rw,_,N,S;if((!t||o(f,h,m[m.length-1]||void 0))&&(x=WO(r(f,m)),x[0]===Ym))return x;if("children"in f&&f.children){const w=f;if(w.children&&x[0]!==QO)for(N=(a?w.children.length:-1)+c,S=m.concat(w);N>-1&&N<w.children.length;){const k=w.children[N];if(_=d(k,N,S)(),_[0]===Ym)return _;N=typeof _[1]=="number"?_[1]:N+c}}return x}}}function WO(e){return Array.isArray(e)?e:typeof e=="number"?[ZO,e]:e==null?Rw:[e]}function zp(e,t,r,a){let s,o,c;typeof t=="function"&&typeof r!="function"?(o=void 0,c=t,s=r):(o=t,c=r,s=a),Dw(e,o,d,s);function d(f,h){const m=h[h.length-1],p=m?m.children.indexOf(f):void 0;return c(f,p,m)}}const Xm={}.hasOwnProperty,JO={};function eR(e,t){const r=t||JO,a=new Map,s=new Map,o=new Map,c={...IO,...r.handlers},d={all:h,applyData:nR,definitionById:a,footnoteById:s,footnoteCounts:o,footnoteOrder:[],handlers:c,one:f,options:r,patch:tR,wrap:iR};return zp(e,function(m){if(m.type==="definition"||m.type==="footnoteDefinition"){const p=m.type==="definition"?a:s,y=String(m.identifier).toUpperCase();p.has(y)||p.set(y,m)}}),d;function f(m,p){const y=m.type,x=d.handlers[y];if(Xm.call(d.handlers,y)&&x)return x(d,m,p);if(d.options.passThrough&&d.options.passThrough.includes(y)){if("children"in m){const{children:N,...S}=m,w=Eu(S);return w.children=d.all(m),w}return Eu(m)}return(d.options.unknownHandler||rR)(d,m,p)}function h(m){const p=[];if("children"in m){const y=m.children;let x=-1;for(;++x<y.length;){const _=d.one(y[x],m);if(_){if(x&&y[x-1].type==="break"&&(!Array.isArray(_)&&_.type==="text"&&(_.value=zy(_.value)),!Array.isArray(_)&&_.type==="element")){const N=_.children[0];N&&N.type==="text"&&(N.value=zy(N.value))}Array.isArray(_)?p.push(..._):p.push(_)}}}return p}}function tR(e,t){e.position&&(t.position=PA(e))}function nR(e,t){let r=t;if(e&&e.data){const a=e.data.hName,s=e.data.hChildren,o=e.data.hProperties;if(typeof a=="string")if(r.type==="element")r.tagName=a;else{const c="children"in r?r.children:[r];r={type:"element",tagName:a,properties:{},children:c}}r.type==="element"&&o&&Object.assign(r.properties,Eu(o)),"children"in r&&r.children&&s!==null&&s!==void 0&&(r.children=s)}return r}function rR(e,t){const r=t.data||{},a="value"in t&&!(Xm.call(r,"hProperties")||Xm.call(r,"hChildren"))?{type:"text",value:t.value}:{type:"element",tagName:"div",properties:{},children:e.all(t)};return e.patch(t,a),e.applyData(t,a)}function iR(e,t){const r=[];let a=-1;for(t&&r.push({type:"text",value:`
`}]}}const Gu=(function(e){if(e==null)return ZO;if(typeof e=="function")return Vu(e);if(typeof e=="object")return Array.isArray(e)?YO(e):XO(e);if(typeof e=="string")return KO(e);throw new Error("Expected function, string, or object as test")});function YO(e){const t=[];let r=-1;for(;++r<e.length;)t[r]=Gu(e[r]);return Vu(a);function a(...s){let o=-1;for(;++o<t.length;)if(t[o].apply(this,s))return!0;return!1}}function XO(e){const t=e;return Vu(r);function r(a){const s=a;let o;for(o in e)if(s[o]!==t[o])return!1;return!0}}function KO(e){return Vu(t);function t(r){return r&&r.type===e}}function Vu(e){return t;function t(r,a,s){return!!(QO(r)&&e.call(this,r,typeof a=="number"?a:void 0,s||void 0))}}function ZO(){return!0}function QO(e){return e!==null&&typeof e=="object"&&"type"in e}const Rw=[],WO=!0,Ym=!1,JO="skip";function Dw(e,t,r,a){let s;typeof t=="function"&&typeof r!="function"?(a=r,r=t):s=t;const o=Gu(s),c=a?-1:1;d(e,void 0,[])();function d(f,h,m){const p=f&&typeof f=="object"?f:{};if(typeof p.type=="string"){const x=typeof p.tagName=="string"?p.tagName:typeof p.name=="string"?p.name:void 0;Object.defineProperty(y,"name",{value:"node ("+(f.type+(x?"<"+x+">":""))+")"})}return y;function y(){let x=Rw,_,N,S;if((!t||o(f,h,m[m.length-1]||void 0))&&(x=eR(r(f,m)),x[0]===Ym))return x;if("children"in f&&f.children){const w=f;if(w.children&&x[0]!==JO)for(N=(a?w.children.length:-1)+c,S=m.concat(w);N>-1&&N<w.children.length;){const k=w.children[N];if(_=d(k,N,S)(),_[0]===Ym)return _;N=typeof _[1]=="number"?_[1]:N+c}}return x}}}function eR(e){return Array.isArray(e)?e:typeof e=="number"?[WO,e]:e==null?Rw:[e]}function zp(e,t,r,a){let s,o,c;typeof t=="function"&&typeof r!="function"?(o=void 0,c=t,s=r):(o=t,c=r,s=a),Dw(e,o,d,s);function d(f,h){const m=h[h.length-1],p=m?m.children.indexOf(f):void 0;return c(f,p,m)}}const Xm={}.hasOwnProperty,tR={};function nR(e,t){const r=t||tR,a=new Map,s=new Map,o=new Map,c={...UO,...r.handlers},d={all:h,applyData:iR,definitionById:a,footnoteById:s,footnoteCounts:o,footnoteOrder:[],handlers:c,one:f,options:r,patch:rR,wrap:sR};return zp(e,function(m){if(m.type==="definition"||m.type==="footnoteDefinition"){const p=m.type==="definition"?a:s,y=String(m.identifier).toUpperCase();p.has(y)||p.set(y,m)}}),d;function f(m,p){const y=m.type,x=d.handlers[y];if(Xm.call(d.handlers,y)&&x)return x(d,m,p);if(d.options.passThrough&&d.options.passThrough.includes(y)){if("children"in m){const{children:N,...S}=m,w=Eu(S);return w.children=d.all(m),w}return Eu(m)}return(d.options.unknownHandler||aR)(d,m,p)}function h(m){const p=[];if("children"in m){const y=m.children;let x=-1;for(;++x<y.length;){const _=d.one(y[x],m);if(_){if(x&&y[x-1].type==="break"&&(!Array.isArray(_)&&_.type==="text"&&(_.value=zy(_.value)),!Array.isArray(_)&&_.type==="element")){const N=_.children[0];N&&N.type==="text"&&(N.value=zy(N.value))}Array.isArray(_)?p.push(..._):p.push(_)}}}return p}}function rR(e,t){e.position&&(t.position=GA(e))}function iR(e,t){let r=t;if(e&&e.data){const a=e.data.hName,s=e.data.hChildren,o=e.data.hProperties;if(typeof a=="string")if(r.type==="element")r.tagName=a;else{const c="children"in r?r.children:[r];r={type:"element",tagName:a,properties:{},children:c}}r.type==="element"&&o&&Object.assign(r.properties,Eu(o)),"children"in r&&r.children&&s!==null&&s!==void 0&&(r.children=s)}return r}function aR(e,t){const r=t.data||{},a="value"in t&&!(Xm.call(r,"hProperties")||Xm.call(r,"hChildren"))?{type:"text",value:t.value}:{type:"element",tagName:"div",properties:{},children:e.all(t)};return e.patch(t,a),e.applyData(t,a)}function sR(e,t){const r=[];let a=-1;for(t&&r.push({type:"text",value:`
`});++a<e.length;)a&&r.push({type:"text",value:`
`}),r.push(e[a]);return t&&e.length>0&&r.push({type:"text",value:`
`}),r}function zy(e){let t=0,r=e.charCodeAt(t);for(;r===9||r===32;)t++,r=e.charCodeAt(t);return e.slice(t)}function Iy(e,t){const r=eR(e,t),a=r.one(e,void 0),s=FO(r),o=Array.isArray(a)?{type:"root",children:a}:a||{type:"root",children:[]};return s&&o.children.push({type:"text",value:`
`},s),o}function aR(e,t){return e&&"run"in e?async function(r,a){const s=Iy(r,{file:a,...t});await e.run(s,a)}:function(r,a){return Iy(r,{file:a,...e||t})}}function By(e){if(e)throw e}var vh,Uy;function sR(){if(Uy)return vh;Uy=1;var e=Object.prototype.hasOwnProperty,t=Object.prototype.toString,r=Object.defineProperty,a=Object.getOwnPropertyDescriptor,s=function(h){return typeof Array.isArray=="function"?Array.isArray(h):t.call(h)==="[object Array]"},o=function(h){if(!h||t.call(h)!=="[object Object]")return!1;var m=e.call(h,"constructor"),p=h.constructor&&h.constructor.prototype&&e.call(h.constructor.prototype,"isPrototypeOf");if(h.constructor&&!m&&!p)return!1;var y;for(y in h);return typeof y>"u"||e.call(h,y)},c=function(h,m){r&&m.name==="__proto__"?r(h,m.name,{enumerable:!0,configurable:!0,value:m.newValue,writable:!0}):h[m.name]=m.newValue},d=function(h,m){if(m==="__proto__")if(e.call(h,m)){if(a)return a(h,m).value}else return;return h[m]};return vh=function f(){var h,m,p,y,x,_,N=arguments[0],S=1,w=arguments.length,k=!1;for(typeof N=="boolean"&&(k=N,N=arguments[1]||{},S=2),(N==null||typeof N!="object"&&typeof N!="function")&&(N={});S<w;++S)if(h=arguments[S],h!=null)for(m in h)p=d(N,m),y=d(h,m),N!==y&&(k&&y&&(o(y)||(x=s(y)))?(x?(x=!1,_=p&&s(p)?p:[]):_=p&&o(p)?p:{},c(N,{name:m,newValue:f(k,_,y)})):typeof y<"u"&&c(N,{name:m,newValue:y}));return N},vh}var lR=sR();const _h=To(lR);function Km(e){if(typeof e!="object"||e===null)return!1;const t=Object.getPrototypeOf(e);return(t===null||t===Object.prototype||Object.getPrototypeOf(t)===null)&&!(Symbol.toStringTag in e)&&!(Symbol.iterator in e)}function oR(){const e=[],t={run:r,use:a};return t;function r(...s){let o=-1;const c=s.pop();if(typeof c!="function")throw new TypeError("Expected function as last argument, not "+c);d(null,...s);function d(f,...h){const m=e[++o];let p=-1;if(f){c(f);return}for(;++p<s.length;)(h[p]===null||h[p]===void 0)&&(h[p]=s[p]);s=h,m?cR(m,d)(...h):c(null,...h)}}function a(s){if(typeof s!="function")throw new TypeError("Expected `middelware` to be a function, not "+s);return e.push(s),t}}function cR(e,t){let r;return a;function a(...c){const d=e.length>c.length;let f;d&&c.push(s);try{f=e.apply(this,c)}catch(h){const m=h;if(d&&r)throw m;return s(m)}d||(f&&f.then&&typeof f.then=="function"?f.then(o,s):f instanceof Error?s(f):o(f))}function s(c,...d){r||(r=!0,t(c,...d))}function o(c){s(null,c)}}const Gr={basename:uR,dirname:dR,extname:fR,join:hR,sep:"/"};function uR(e,t){if(t!==void 0&&typeof t!="string")throw new TypeError('"ext" argument must be a string');Ro(e);let r=0,a=-1,s=e.length,o;if(t===void 0||t.length===0||t.length>e.length){for(;s--;)if(e.codePointAt(s)===47){if(o){r=s+1;break}}else a<0&&(o=!0,a=s+1);return a<0?"":e.slice(r,a)}if(t===e)return"";let c=-1,d=t.length-1;for(;s--;)if(e.codePointAt(s)===47){if(o){r=s+1;break}}else c<0&&(o=!0,c=s+1),d>-1&&(e.codePointAt(s)===t.codePointAt(d--)?d<0&&(a=s):(d=-1,a=c));return r===a?a=c:a<0&&(a=e.length),e.slice(r,a)}function dR(e){if(Ro(e),e.length===0)return".";let t=-1,r=e.length,a;for(;--r;)if(e.codePointAt(r)===47){if(a){t=r;break}}else a||(a=!0);return t<0?e.codePointAt(0)===47?"/":".":t===1&&e.codePointAt(0)===47?"//":e.slice(0,t)}function fR(e){Ro(e);let t=e.length,r=-1,a=0,s=-1,o=0,c;for(;t--;){const d=e.codePointAt(t);if(d===47){if(c){a=t+1;break}continue}r<0&&(c=!0,r=t+1),d===46?s<0?s=t:o!==1&&(o=1):s>-1&&(o=-1)}return s<0||r<0||o===0||o===1&&s===r-1&&s===a+1?"":e.slice(s,r)}function hR(...e){let t=-1,r;for(;++t<e.length;)Ro(e[t]),e[t]&&(r=r===void 0?e[t]:r+"/"+e[t]);return r===void 0?".":mR(r)}function mR(e){Ro(e);const t=e.codePointAt(0)===47;let r=pR(e,!t);return r.length===0&&!t&&(r="."),r.length>0&&e.codePointAt(e.length-1)===47&&(r+="/"),t?"/"+r:r}function pR(e,t){let r="",a=0,s=-1,o=0,c=-1,d,f;for(;++c<=e.length;){if(c<e.length)d=e.codePointAt(c);else{if(d===47)break;d=47}if(d===47){if(!(s===c-1||o===1))if(s!==c-1&&o===2){if(r.length<2||a!==2||r.codePointAt(r.length-1)!==46||r.codePointAt(r.length-2)!==46){if(r.length>2){if(f=r.lastIndexOf("/"),f!==r.length-1){f<0?(r="",a=0):(r=r.slice(0,f),a=r.length-1-r.lastIndexOf("/")),s=c,o=0;continue}}else if(r.length>0){r="",a=0,s=c,o=0;continue}}t&&(r=r.length>0?r+"/..":"..",a=2)}else r.length>0?r+="/"+e.slice(s+1,c):r=e.slice(s+1,c),a=c-s-1;s=c,o=0}else d===46&&o>-1?o++:o=-1}return r}function Ro(e){if(typeof e!="string")throw new TypeError("Path must be a string. Received "+JSON.stringify(e))}const gR={cwd:bR};function bR(){return"/"}function Zm(e){return!!(e!==null&&typeof e=="object"&&"href"in e&&e.href&&"protocol"in e&&e.protocol&&e.auth===void 0)}function xR(e){if(typeof e=="string")e=new URL(e);else if(!Zm(e)){const t=new TypeError('The "path" argument must be of type string or an instance of URL. Received `'+e+"`");throw t.code="ERR_INVALID_ARG_TYPE",t}if(e.protocol!=="file:"){const t=new TypeError("The URL must be of scheme file");throw t.code="ERR_INVALID_URL_SCHEME",t}return yR(e)}function yR(e){if(e.hostname!==""){consLine truncated
`:" ")+o.indentLines(o.containerFlow(a,d.current()),t?Iw:o3))),h(),f}}function o3(e,t,r){return t===0?e:Iw(e,t,r)}function Iw(e,t,r){return(r?"":" ")+e}const c3=["autolink","destinationLiteral","destinationRaw","reference","titleQuote","titleApostrophe"];Bw.peek=m3;function u3(){return{canContainEols:["delete"],enter:{strikethrough:f3},exit:{strikethrough:h3}}}function d3(){return{unsafe:[{character:"~",inConstruct:"phrasing",notInConstruct:c3}],handlers:{delete:Bw}}}function f3(e){this.enter({type:"delete",children:[]},e)}function h3(e){this.exit(e)}function Bw(e,t,r,a){const s=r.createTracker(a),o=r.enter("strikethrough");let c=s.move("~~");return c+=r.containerPhrasing(e,{...s.current(),before:c,after:"~"}),c+=s.move("~~"),o(),c}function m3(){return"~"}function p3(e){return e.length}function g3(e,t){const r=t||{},a=(r.align||[]).concat(),s=r.stringLength||p3,o=[],c=[],d=[],f=[];let h=0,m=-1;for(;++m<e.length;){const N=[],S=[];let w=-1;for(e[m].length>h&&(h=e[m].length);++w<e[m].length;){const k=b3(e[m][w]);if(r.alignDelimiters!==!1){const E=s(k);S[w]=E,(f[w]===void 0||E>f[w])&&(f[w]=E)}N.push(k)}c[m]=N,d[m]=S}let p=-1;if(typeof a=="object"&&"length"in a)for(;++p<h;)o[p]=Vy(a[p]);else{const N=Vy(a);for(;++p<h;)o[p]=N}p=-1;const y=[],x=[];for(;++p<h;){const N=o[p];let S="",w="";N===99?(S=":",w=":"):N===108?S=":":N===114&&(w=":");let k=r.alignDelimiters===!1?1:Math.max(1,f[p]-S.length-w.length);const E=S+"-".repeat(k)+w;r.alignDelimiters!==!1&&(k=S.length+k+w.length,k>f[p]&&(f[p]=k),x[p]=k),y[p]=E}c.splice(1,0,y),d.splice(1,0,x),m=-1;const _=[];for(;++m<c.length;){const N=c[m],S=d[m];p=-1;const w=[];for(;++p<h;){const k=N[p]||"";let E="",M="";if(r.alignDelimiters!==!1){const I=f[p]-(S[p]||0),R=o[p];R===114?E=" ".repeat(I):R===99?I%2?(E=" ".repeat(I/2+.5),M=" ".repeat(I/2-.5)):(E=" ".repeat(I/2),M=E):M=" ".repeat(I)}r.delimiterStart!==!1&&!p&&w.push("|"),r.padding!==!1&&!(r.alignDelimiters===!1&&k==="")&&(r.delimiterStart!==!1||p)&&w.push(" "),r.alignDelimiters!==!1&&w.push(E),w.push(k),r.alignDelimiters!==!1&&w.push(M),r.padding!==!1&&w.push(" "),(r.delimiterEnd!==!1||p!==h-1)&&w.push("|")}_.push(r.delimiterEnd===!1?w.join("").replace(/ +$/,""):w.join(""))}return _.join(`
`)}function b3(e){return e==null?"":String(e)}function Vy(e){const t=typeof e=="string"?e.codePointAt(0):0;return t===67||t===99?99:t===76||t===108?108:t===82||t===114?114:0}function x3(e,t,r,a){const s=r.enter("blockquote"),o=r.createTracker(a);o.move("> "),o.shift(2);const c=r.indentLines(r.containerFlow(e,o.current()),y3);return s(),c}function y3(e,t,r){return">"+(r?"":" ")+e}function v3(e,t){return Yy(e,t.inConstruct,!0)&&!Yy(e,t.notInConstruct,!1)}function Yy(e,t,r){if(typeof t=="string"&&(t=[t]),!t||t.length===0)return r;let a=-1;for(;++a<t.length;)if(e.includes(t[a]))return!0;return!1}function Xy(e,t,r,a){let s=-1;for(;++s<r.unsafe.length;)if(r.unsafe[s].character===`
`&&v3(r.stack,r.unsafe[s]))return/[ \t]/.test(a.before)?"":" ";return`\\
`}function _3(e,t){const r=String(e);let a=r.indexOf(t),s=a,o=0,c=0;if(typeof t!="string")throw new TypeError("Expected substring");for(;a!==-1;)a===s?++o>c&&(c=o):o=1,s=a+t.length,a=r.indexOf(t,s);return c}function w3(e,t){return!!(t.options.fences===!1&&e.value&&!e.lang&&/[^ \r\n]/.test(e.value)&&!/^[\t ]*(?:[\r\n]|$)|(?:^|[\r\n])[\t ]*$/.test(e.value))}function E3(e){const t=e.options.fence||"`";if(t!=="`"&&t!=="~")throw new Error("Cannot serialize code with `"+t+"` for `options.fence`, expected `` ` `` or `~`");return t}function N3(e,t,r,a){const s=E3(r),o=e.value||"",c=s==="`"?"GraveAccent":"Tilde";if(w3(e,r)){const p=r.enter("codeIndented"),y=r.indentLines(o,S3);return p(),y}const d=r.createTracker(a),f=s.repeat(Math.max(_3(o,s)+1,3)),h=r.enter("codeFenced");let m=d.move(f);if(e.lang){const p=r.enter(`codeFencedLang${c}`);m+=d.move(r.safe(e.lang,{before:m,after:" ",encode:["`"],...d.current()})),p()}if(e.lang&&e.meta){const p=r.enter(`codeFencedMeta${c}`);m+=d.move(" "),m+=d.move(r.safe(e.meta,{before:m,after:`
`}),r}function zy(e){let t=0,r=e.charCodeAt(t);for(;r===9||r===32;)t++,r=e.charCodeAt(t);return e.slice(t)}function Iy(e,t){const r=nR(e,t),a=r.one(e,void 0),s=VO(r),o=Array.isArray(a)?{type:"root",children:a}:a||{type:"root",children:[]};return s&&o.children.push({type:"text",value:`
`},s),o}function lR(e,t){return e&&"run"in e?async function(r,a){const s=Iy(r,{file:a,...t});await e.run(s,a)}:function(r,a){return Iy(r,{file:a,...e||t})}}function By(e){if(e)throw e}var vh,Uy;function oR(){if(Uy)return vh;Uy=1;var e=Object.prototype.hasOwnProperty,t=Object.prototype.toString,r=Object.defineProperty,a=Object.getOwnPropertyDescriptor,s=function(h){return typeof Array.isArray=="function"?Array.isArray(h):t.call(h)==="[object Array]"},o=function(h){if(!h||t.call(h)!=="[object Object]")return!1;var m=e.call(h,"constructor"),p=h.constructor&&h.constructor.prototype&&e.call(h.constructor.prototype,"isPrototypeOf");if(h.constructor&&!m&&!p)return!1;var y;for(y in h);return typeof y>"u"||e.call(h,y)},c=function(h,m){r&&m.name==="__proto__"?r(h,m.name,{enumerable:!0,configurable:!0,value:m.newValue,writable:!0}):h[m.name]=m.newValue},d=function(h,m){if(m==="__proto__")if(e.call(h,m)){if(a)return a(h,m).value}else return;return h[m]};return vh=function f(){var h,m,p,y,x,_,N=arguments[0],S=1,w=arguments.length,k=!1;for(typeof N=="boolean"&&(k=N,N=arguments[1]||{},S=2),(N==null||typeof N!="object"&&typeof N!="function")&&(N={});S<w;++S)if(h=arguments[S],h!=null)for(m in h)p=d(N,m),y=d(h,m),N!==y&&(k&&y&&(o(y)||(x=s(y)))?(x?(x=!1,_=p&&s(p)?p:[]):_=p&&o(p)?p:{},c(N,{name:m,newValue:f(k,_,y)})):typeof y<"u"&&c(N,{name:m,newValue:y}));return N},vh}var cR=oR();const _h=Co(cR);function Km(e){if(typeof e!="object"||e===null)return!1;const t=Object.getPrototypeOf(e);return(t===null||t===Object.prototype||Object.getPrototypeOf(t)===null)&&!(Symbol.toStringTag in e)&&!(Symbol.iterator in e)}function uR(){const e=[],t={run:r,use:a};return t;function r(...s){let o=-1;const c=s.pop();if(typeof c!="function")throw new TypeError("Expected function as last argument, not "+c);d(null,...s);function d(f,...h){const m=e[++o];let p=-1;if(f){c(f);return}for(;++p<s.length;)(h[p]===null||h[p]===void 0)&&(h[p]=s[p]);s=h,m?dR(m,d)(...h):c(null,...h)}}function a(s){if(typeof s!="function")throw new TypeError("Expected `middelware` to be a function, not "+s);return e.push(s),t}}function dR(e,t){let r;return a;function a(...c){const d=e.length>c.length;let f;d&&c.push(s);try{f=e.apply(this,c)}catch(h){const m=h;if(d&&r)throw m;return s(m)}d||(f&&f.then&&typeof f.then=="function"?f.then(o,s):f instanceof Error?s(f):o(f))}function s(c,...d){r||(r=!0,t(c,...d))}function o(c){s(null,c)}}const Gr={basename:fR,dirname:hR,extname:mR,join:pR,sep:"/"};function fR(e,t){if(t!==void 0&&typeof t!="string")throw new TypeError('"ext" argument must be a string');Ro(e);let r=0,a=-1,s=e.length,o;if(t===void 0||t.length===0||t.length>e.length){for(;s--;)if(e.codePointAt(s)===47){if(o){r=s+1;break}}else a<0&&(o=!0,a=s+1);return a<0?"":e.slice(r,a)}if(t===e)return"";let c=-1,d=t.length-1;for(;s--;)if(e.codePointAt(s)===47){if(o){r=s+1;break}}else c<0&&(o=!0,c=s+1),d>-1&&(e.codePointAt(s)===t.codePointAt(d--)?d<0&&(a=s):(d=-1,a=c));return r===a?a=c:a<0&&(a=e.length),e.slice(r,a)}function hR(e){if(Ro(e),e.length===0)return".";let t=-1,r=e.length,a;for(;--r;)if(e.codePointAt(r)===47){if(a){t=r;break}}else a||(a=!0);return t<0?e.codePointAt(0)===47?"/":".":t===1&&e.codePointAt(0)===47?"//":e.slice(0,t)}function mR(e){Ro(e);let t=e.length,r=-1,a=0,s=-1,o=0,c;for(;t--;){const d=e.codePointAt(t);if(d===47){if(c){a=t+1;break}continue}r<0&&(c=!0,r=t+1),d===46?s<0?s=t:o!==1&&(o=1):s>-1&&(o=-1)}return s<0||r<0||o===0||o===1&&s===r-1&&s===a+1?"":e.slice(s,r)}function pR(...e){let t=-1,r;for(;++t<e.length;)Ro(e[t]),e[t]&&(r=r===void 0?e[t]:r+"/"+e[t]);return r===void 0?".":gR(r)}function gR(e){Ro(e);const t=e.codePointAt(0)===47;let r=bR(e,!t);return r.length===0&&!t&&(r="."),r.length>0&&e.codePointAt(e.length-1)===47&&(r+="/"),t?"/"+r:r}function bR(e,t){let r="",a=0,s=-1,o=0,c=-1,d,f;for(;++c<=e.length;){if(c<e.length)d=e.codePointAt(c);else{if(d===47)break;d=47}if(d===47){if(!(s===c-1||o===1))if(s!==c-1&&o===2){if(r.length<2||a!==2||r.codePointAt(r.length-1)!==46||r.codePointAt(r.length-2)!==46){if(r.length>2){if(f=r.lastIndexOf("/"),f!==r.length-1){f<0?(r="",a=0):(r=r.slice(0,f),a=r.length-1-r.lastIndexOf("/")),s=c,o=0;continue}}else if(r.length>0){r="",a=0,s=c,o=0;continue}}t&&(r=r.length>0?r+"/..":"..",a=2)}else r.length>0?r+="/"+e.slice(s+1,c):r=e.slice(s+1,c),a=c-s-1;s=c,o=0}else d===46&&o>-1?o++:o=-1}return r}function Ro(e){if(typeof e!="string")throw new TypeError("Path must be a string. Received "+JSON.stringify(e))}const xR={cwd:yR};function yR(){return"/"}function Zm(e){return!!(e!==null&&typeof e=="object"&&"href"in e&&e.href&&"protocol"in e&&e.protocol&&e.auth===void 0)}function vR(e){if(typeof e=="string")e=new URL(e);else if(!Zm(e)){const t=new TypeError('The "path" argument must be of type string or an instance of URL. Received `'+e+"`");throw t.code="ERR_INVALID_ARG_TYPE",t}if(e.protocol!=="file:"){const t=new TypeError("The URL must be of scheme file");throw t.code="ERR_INVALID_URL_SCHEME",t}return _R(e)}function _R(e){if(e.hostname!==""){consLine truncated
`:" ")+o.indentLines(o.containerFlow(a,d.current()),t?Iw:u3))),h(),f}}function u3(e,t,r){return t===0?e:Iw(e,t,r)}function Iw(e,t,r){return(r?"":" ")+e}const d3=["autolink","destinationLiteral","destinationRaw","reference","titleQuote","titleApostrophe"];Bw.peek=g3;function f3(){return{canContainEols:["delete"],enter:{strikethrough:m3},exit:{strikethrough:p3}}}function h3(){return{unsafe:[{character:"~",inConstruct:"phrasing",notInConstruct:d3}],handlers:{delete:Bw}}}function m3(e){this.enter({type:"delete",children:[]},e)}function p3(e){this.exit(e)}function Bw(e,t,r,a){const s=r.createTracker(a),o=r.enter("strikethrough");let c=s.move("~~");return c+=r.containerPhrasing(e,{...s.current(),before:c,after:"~"}),c+=s.move("~~"),o(),c}function g3(){return"~"}function b3(e){return e.length}function x3(e,t){const r=t||{},a=(r.align||[]).concat(),s=r.stringLength||b3,o=[],c=[],d=[],f=[];let h=0,m=-1;for(;++m<e.length;){const N=[],S=[];let w=-1;for(e[m].length>h&&(h=e[m].length);++w<e[m].length;){const k=y3(e[m][w]);if(r.alignDelimiters!==!1){const E=s(k);S[w]=E,(f[w]===void 0||E>f[w])&&(f[w]=E)}N.push(k)}c[m]=N,d[m]=S}let p=-1;if(typeof a=="object"&&"length"in a)for(;++p<h;)o[p]=Vy(a[p]);else{const N=Vy(a);for(;++p<h;)o[p]=N}p=-1;const y=[],x=[];for(;++p<h;){const N=o[p];let S="",w="";N===99?(S=":",w=":"):N===108?S=":":N===114&&(w=":");let k=r.alignDelimiters===!1?1:Math.max(1,f[p]-S.length-w.length);const E=S+"-".repeat(k)+w;r.alignDelimiters!==!1&&(k=S.length+k+w.length,k>f[p]&&(f[p]=k),x[p]=k),y[p]=E}c.splice(1,0,y),d.splice(1,0,x),m=-1;const _=[];for(;++m<c.length;){const N=c[m],S=d[m];p=-1;const w=[];for(;++p<h;){const k=N[p]||"";let E="",M="";if(r.alignDelimiters!==!1){const I=f[p]-(S[p]||0),R=o[p];R===114?E=" ".repeat(I):R===99?I%2?(E=" ".repeat(I/2+.5),M=" ".repeat(I/2-.5)):(E=" ".repeat(I/2),M=E):M=" ".repeat(I)}r.delimiterStart!==!1&&!p&&w.push("|"),r.padding!==!1&&!(r.alignDelimiters===!1&&k==="")&&(r.delimiterStart!==!1||p)&&w.push(" "),r.alignDelimiters!==!1&&w.push(E),w.push(k),r.alignDelimiters!==!1&&w.push(M),r.padding!==!1&&w.push(" "),(r.delimiterEnd!==!1||p!==h-1)&&w.push("|")}_.push(r.delimiterEnd===!1?w.join("").replace(/ +$/,""):w.join(""))}return _.join(`
`)}function y3(e){return e==null?"":String(e)}function Vy(e){const t=typeof e=="string"?e.codePointAt(0):0;return t===67||t===99?99:t===76||t===108?108:t===82||t===114?114:0}function v3(e,t,r,a){const s=r.enter("blockquote"),o=r.createTracker(a);o.move("> "),o.shift(2);const c=r.indentLines(r.containerFlow(e,o.current()),_3);return s(),c}function _3(e,t,r){return">"+(r?"":" ")+e}function w3(e,t){return Yy(e,t.inConstruct,!0)&&!Yy(e,t.notInConstruct,!1)}function Yy(e,t,r){if(typeof t=="string"&&(t=[t]),!t||t.length===0)return r;let a=-1;for(;++a<t.length;)if(e.includes(t[a]))return!0;return!1}function Xy(e,t,r,a){let s=-1;for(;++s<r.unsafe.length;)if(r.unsafe[s].character===`
`&&w3(r.stack,r.unsafe[s]))return/[ \t]/.test(a.before)?"":" ";return`\\
`}function E3(e,t){const r=String(e);let a=r.indexOf(t),s=a,o=0,c=0;if(typeof t!="string")throw new TypeError("Expected substring");for(;a!==-1;)a===s?++o>c&&(c=o):o=1,s=a+t.length,a=r.indexOf(t,s);return c}function N3(e,t){return!!(t.options.fences===!1&&e.value&&!e.lang&&/[^ \r\n]/.test(e.value)&&!/^[\t ]*(?:[\r\n]|$)|(?:^|[\r\n])[\t ]*$/.test(e.value))}function S3(e){const t=e.options.fence||"`";if(t!=="`"&&t!=="~")throw new Error("Cannot serialize code with `"+t+"` for `options.fence`, expected `` ` `` or `~`");return t}function k3(e,t,r,a){const s=S3(r),o=e.value||"",c=s==="`"?"GraveAccent":"Tilde";if(N3(e,r)){const p=r.enter("codeIndented"),y=r.indentLines(o,C3);return p(),y}const d=r.createTracker(a),f=s.repeat(Math.max(E3(o,s)+1,3)),h=r.enter("codeFenced");let m=d.move(f);if(e.lang){const p=r.enter(`codeFencedLang${c}`);m+=d.move(r.safe(e.lang,{before:m,after:" ",encode:["`"],...d.current()})),p()}if(e.lang&&e.meta){const p=r.enter(`codeFencedMeta${c}`);m+=d.move(" "),m+=d.move(r.safe(e.meta,{before:m,after:`
`,encode:["`"],...d.current()})),p()}return m+=d.move(`
`),o&&(m+=d.move(o+`
`)),m+=d.move(f),h(),m}function S3(e,t,r){return(r?"":" ")+e}function Up(e){const t=e.options.quote||'"';if(t!=='"'&&t!=="'")throw new Error("Cannot serialize title with `"+t+"` for `options.quote`, expected `\"`, or `'`");return t}function k3(e,t,r,a){const s=Up(r),o=s==='"'?"Quote":"Apostrophe",c=r.enter("definition");let d=r.enter("label");const f=r.createTracker(a);let h=f.move("[");return h+=f.move(r.safe(r.associationId(e),{before:h,after:"]",...f.current()})),h+=f.move("]: "),d(),!e.url||/[\0- \u007F]/.test(e.url)?(d=r.enter("destinationLiteral"),h+=f.move("<"),h+=f.move(r.safe(e.url,{before:h,after:">",...f.current()})),h+=f.move(">")):(d=r.enter("destinationRaw"),h+=f.move(r.safe(e.url,{before:h,after:e.title?" ":`
`,...f.current()}))),d(),e.title&&(d=r.enter(`title${o}`),h+=f.move(" "+s),h+=f.move(r.safe(e.title,{before:h,after:s,...f.current()})),h+=f.move(s),d()),c(),h}function T3(e){const t=e.options.emphasis||"*";if(t!=="*"&&t!=="_")throw new Error("Cannot serialize emphasis with `"+t+"` for `options.emphasis`, expected `*`, or `_`");return t}function go(e){return"&#x"+e.toString(16).toUpperCase()+";"}function Nu(e,t,r){const a=Ys(e),s=Ys(t);return a===void 0?s===void 0?r==="_"?{inside:!0,outside:!0}:{inside:!1,outside:!1}:s===1?{inside:!0,outside:!0}:{inside:!1,outside:!0}:a===1?s===void 0?{inside:!1,outside:!1}:s===1?{inside:!0,outside:!0}:{inside:!1,outside:!1}:s===void 0?{inside:!1,outside:!1}:s===1?{inside:!0,outside:!1}:{inside:!1,outside:!1}}Uw.peek=C3;function Uw(e,t,r,a){const s=T3(r),o=r.enter("emphasis"),c=r.createTracker(a),d=c.move(s);let f=c.move(r.containerPhrasing(e,{after:s,before:d,...c.current()}));const h=f.charCodeAt(0),m=Nu(a.before.charCodeAt(a.before.length-1),h,s);m.inside&&(f=go(h)+f.slice(1));const p=f.charCodeAt(f.length-1),y=Nu(a.after.charCodeAt(0),p,s);y.inside&&(f=f.slice(0,-1)+go(p));const x=c.move(s);return o(),r.attentionEncodeSurroundingInfo={after:y.outside,before:m.outside},d+f+x}function C3(e,t,r){return r.options.emphasis||"*"}function A3(e,t){let r=!1;return zp(e,function(a){if("value"in a&&/\r?\n|\r/.test(a.value)||a.type==="break")return r=!0,Ym}),!!((!e.depth||e.depth<3)&&Ap(e)&&(t.options.setext||r))}function M3(e,t,r,a){const s=Math.max(Math.min(6,e.depth||1),1),o=r.createTracker(a);if(A3(e,r)){const m=r.enter("headingSetext"),p=r.enter("phrasing"),y=r.containerPhrasing(e,{...o.current(),before:`
`)),m+=d.move(f),h(),m}function C3(e,t,r){return(r?"":" ")+e}function Up(e){const t=e.options.quote||'"';if(t!=='"'&&t!=="'")throw new Error("Cannot serialize title with `"+t+"` for `options.quote`, expected `\"`, or `'`");return t}function T3(e,t,r,a){const s=Up(r),o=s==='"'?"Quote":"Apostrophe",c=r.enter("definition");let d=r.enter("label");const f=r.createTracker(a);let h=f.move("[");return h+=f.move(r.safe(r.associationId(e),{before:h,after:"]",...f.current()})),h+=f.move("]: "),d(),!e.url||/[\0- \u007F]/.test(e.url)?(d=r.enter("destinationLiteral"),h+=f.move("<"),h+=f.move(r.safe(e.url,{before:h,after:">",...f.current()})),h+=f.move(">")):(d=r.enter("destinationRaw"),h+=f.move(r.safe(e.url,{before:h,after:e.title?" ":`
`,...f.current()}))),d(),e.title&&(d=r.enter(`title${o}`),h+=f.move(" "+s),h+=f.move(r.safe(e.title,{before:h,after:s,...f.current()})),h+=f.move(s),d()),c(),h}function A3(e){const t=e.options.emphasis||"*";if(t!=="*"&&t!=="_")throw new Error("Cannot serialize emphasis with `"+t+"` for `options.emphasis`, expected `*`, or `_`");return t}function go(e){return"&#x"+e.toString(16).toUpperCase()+";"}function Nu(e,t,r){const a=Ys(e),s=Ys(t);return a===void 0?s===void 0?r==="_"?{inside:!0,outside:!0}:{inside:!1,outside:!1}:s===1?{inside:!0,outside:!0}:{inside:!1,outside:!0}:a===1?s===void 0?{inside:!1,outside:!1}:s===1?{inside:!0,outside:!0}:{inside:!1,outside:!1}:s===void 0?{inside:!1,outside:!1}:s===1?{inside:!0,outside:!1}:{inside:!1,outside:!1}}Uw.peek=M3;function Uw(e,t,r,a){const s=A3(r),o=r.enter("emphasis"),c=r.createTracker(a),d=c.move(s);let f=c.move(r.containerPhrasing(e,{after:s,before:d,...c.current()}));const h=f.charCodeAt(0),m=Nu(a.before.charCodeAt(a.before.length-1),h,s);m.inside&&(f=go(h)+f.slice(1));const p=f.charCodeAt(f.length-1),y=Nu(a.after.charCodeAt(0),p,s);y.inside&&(f=f.slice(0,-1)+go(p));const x=c.move(s);return o(),r.attentionEncodeSurroundingInfo={after:y.outside,before:m.outside},d+f+x}function M3(e,t,r){return r.options.emphasis||"*"}function O3(e,t){let r=!1;return zp(e,function(a){if("value"in a&&/\r?\n|\r/.test(a.value)||a.type==="break")return r=!0,Ym}),!!((!e.depth||e.depth<3)&&Ap(e)&&(t.options.setext||r))}function R3(e,t,r,a){const s=Math.max(Math.min(6,e.depth||1),1),o=r.createTracker(a);if(O3(e,r)){const m=r.enter("headingSetext"),p=r.enter("phrasing"),y=r.containerPhrasing(e,{...o.current(),before:`
`,after:`
`});return p(),m(),y+`
`+(s===1?"=":"-").repeat(y.length-(Math.max(y.lastIndexOf("\r"),y.lastIndexOf(`
`))+1))}const c="#".repeat(s),d=r.enter("headingAtx"),f=r.enter("phrasing");o.move(c+" ");let h=r.containerPhrasing(e,{before:"# ",after:`
`,...o.current()});return/^[\t ]/.test(h)&&(h=go(h.charCodeAt(0))+h.slice(1)),h=h?c+" "+h:c,r.options.closeAtx&&(h+=" "+c),f(),d(),h}Hw.peek=O3;function Hw(e){return e.value||""}function O3(){return"<"}$w.peek=R3;function $w(e,t,r,a){const s=Up(r),o=s==='"'?"Quote":"Apostrophe",c=r.enter("image");let d=r.enter("label");const f=r.createTracker(a);let h=f.move("![");return h+=f.move(r.safe(e.alt,{before:h,after:"]",...f.current()})),h+=f.move("]("),d(),!e.url&&e.title||/[\0- \u007F]/.test(e.url)?(d=r.enter("destinationLiteral"),h+=f.move("<"),h+=f.move(r.safe(e.url,{before:h,after:">",...f.current()})),h+=f.move(">")):(d=r.enter("destinationRaw"),h+=f.move(r.safe(e.url,{before:h,after:e.title?" ":")",...f.current()}))),d(),e.title&&(d=r.enter(`title${o}`),h+=f.move(" "+s),h+=f.move(r.safe(e.title,{before:h,after:s,...f.current()})),h+=f.move(s),d()),h+=f.move(")"),c(),h}function R3(){return"!"}qw.peek=D3;function qw(e,t,r,a){const s=e.referenceType,o=r.enter("imageReference");let c=r.enter("label");const d=r.createTracker(a);let f=d.move("![");const h=r.safe(e.alt,{before:f,after:"]",...d.current()});f+=d.move(h+"]["),c();const m=r.stack;r.stack=[],c=r.enter("reference");const p=r.safe(r.associationId(e),{before:f,after:"]",...d.current()});return c(),r.stack=m,o(),s==="full"||!h||h!==p?f+=d.move(p+"]"):s==="shortcut"?f=f.slice(0,-1):f+=d.move("]"),f}function D3(){return"!"}Pw.peek=j3;function Pw(e,t,r){let a=e.value||"",s="`",o=-1;for(;new RegExp("(^|[^`])"+s+"([^`]|$)").test(a);)s+="`";for(/[^ \r\n]/.test(a)&&(/^[ \r\n]/.test(a)&&/[ \r\n]$/.test(a)||/^`|`$/.test(a))&&(a=" "+a+" ");++o<r.unsafe.length;){const c=r.unsafe[o],d=r.compilePattern(c);let f;if(c.atBreak)for(;f=d.exec(a);){let h=f.index;a.charCodeAt(h)===10&&a.charCodeAt(h-1)===13&&h--,a=a.slice(0,h)+" "+a.slice(f.index+1)}}return s+a+s}function j3(){return"`"}function Fw(e,t){const r=Ap(e);return!!(!t.options.resourceLink&&e.url&&!e.title&&e.children&&e.children.length===1&&e.children[0].type==="text"&&(r===e.url||"mailto:"+r===e.url)&&/^[a-z][a-z+.-]+:/i.test(e.url)&&!/[\0- <>\u007F]/.test(e.url))}Gw.peek=L3;function Gw(e,t,r,a){const s=Up(r),o=s==='"'?"Quote":"Apostrophe",c=r.createTracker(a);let d,f;if(Fw(e,r)){const m=r.stack;r.stack=[],d=r.enter("autolink");let p=c.move("<");return p+=c.move(r.containerPhrasing(e,{before:p,after:">",...c.current()})),p+=c.move(">"),d(),r.stack=m,p}d=r.enter("link"),f=r.enter("label");let h=c.move("[");return h+=c.move(r.containerPhrasing(e,{before:h,after:"](",...c.current()})),h+=c.move("]("),f(),!e.url&&e.title||/[\0- \u007F]/.test(e.url)?(f=r.enter("destinationLiteral"),h+=c.move("<"),h+=c.move(r.safe(e.url,{before:h,after:">",...c.current()})),h+=c.move(">")):(f=r.enter("destinationRaw"),h+=c.move(r.safe(e.url,{before:h,after:e.title?" ":")",...c.current()}))),f(),e.title&&(f=r.enter(`title${o}`),h+=c.move(" "+s),h+=c.move(r.safe(e.title,{before:h,after:s,...c.current()})),h+=c.move(s),f()),h+=c.move(")"),d(),h}function L3(e,t,r){return Fw(e,r)?"<":"["}Vw.peek=z3;function Vw(e,t,r,a){const s=e.referenceType,o=r.enter("linkReference");let c=r.enter("label");const d=r.createTracker(a);let f=d.move("[");const h=r.containerPhrasing(e,{before:f,after:"]",...d.current()});f+=d.move(h+"]["),c();const m=r.stack;r.stack=[],c=r.enter("reference");const p=r.safe(r.associationId(e),{before:f,after:"]",...d.current()});return c(),r.stack=m,o(),s==="full"||!h||h!==p?f+=d.move(p+"]"):s==="shortcut"?f=f.slice(0,-1):f+=d.move("]"),f}function z3(){return"["}function Hp(e){const t=e.options.bullet||"*";if(t!=="*"&&t!=="+"&&t!=="-")throw new Error("Cannot serialize items with `"+t+"` for `options.bullet`, expected `*`, `+`, or `-`");return t}function I3(e){const t=Hp(e),r=e.options.bulletOther;if(!r)return t==="*"?"-":"*";if(r!=="*"&&r!=="+"&&r!=="-")throw new Error("Cannot serialize items with `"+r+"` for `options.bulletOther`, expected `*`, `+`, or `-`");if(r===t)throw new Error("Expected `bullet` (`"+t+"`) and `bulletOther` (`"+r+"`) to be different");return r}function B3(e){const t=e.options.bulletOrdered||".";if(t!=="."&&t!==")")throw new Error("Cannot serialize items with `"+t+"` for `options.bulletOrdered`, expected `.` or `)`");return t}function Yw(e){const t=e.options.rule||"*";if(t!=="*"&&t!=="-"&&t!=="_")throw new Error("Cannot serialize rules with `"+t+"` for `options.rule`, expected `*`, `-`, or `_`");return t}function U3(e,t,r,a){const s=r.enter("list"),o=r.bulletCurrent;let c=e.ordered?B3(r):Hp(r);const d=e.ordered?c==="."?")":".":I3(r);let f=t&&r.bulletLastUsed?c===r.bulletLastUsed:!1;if(!e.ordered){const m=e.children?e.children[0]:void 0;if((c==="*"||c==="-")&&m&&(!m.children||!m.children[0])&&r.stack[r.stack.length-1]==="list"&&r.stack[r.stack.length-2]==="listItem"&&r.stack[r.stack.length-3]==="list"&&r.stack[r.stack.length-4]==="listItem"&&r.indexStack[r.indexStack.length-1]===0&&r.indexStack[r.indexStack.length-2]===0&&r.indexStack[r.indexStack.length-3]===0&&(f=!0),Yw(r)===c&&m){let p=-1;for(;++p<e.chilLine truncated
`,...o.current()});return/^[\t ]/.test(h)&&(h=go(h.charCodeAt(0))+h.slice(1)),h=h?c+" "+h:c,r.options.closeAtx&&(h+=" "+c),f(),d(),h}Hw.peek=D3;function Hw(e){return e.value||""}function D3(){return"<"}$w.peek=j3;function $w(e,t,r,a){const s=Up(r),o=s==='"'?"Quote":"Apostrophe",c=r.enter("image");let d=r.enter("label");const f=r.createTracker(a);let h=f.move("![");return h+=f.move(r.safe(e.alt,{before:h,after:"]",...f.current()})),h+=f.move("]("),d(),!e.url&&e.title||/[\0- \u007F]/.test(e.url)?(d=r.enter("destinationLiteral"),h+=f.move("<"),h+=f.move(r.safe(e.url,{before:h,after:">",...f.current()})),h+=f.move(">")):(d=r.enter("destinationRaw"),h+=f.move(r.safe(e.url,{before:h,after:e.title?" ":")",...f.current()}))),d(),e.title&&(d=r.enter(`title${o}`),h+=f.move(" "+s),h+=f.move(r.safe(e.title,{before:h,after:s,...f.current()})),h+=f.move(s),d()),h+=f.move(")"),c(),h}function j3(){return"!"}qw.peek=L3;function qw(e,t,r,a){const s=e.referenceType,o=r.enter("imageReference");let c=r.enter("label");const d=r.createTracker(a);let f=d.move("![");const h=r.safe(e.alt,{before:f,after:"]",...d.current()});f+=d.move(h+"]["),c();const m=r.stack;r.stack=[],c=r.enter("reference");const p=r.safe(r.associationId(e),{before:f,after:"]",...d.current()});return c(),r.stack=m,o(),s==="full"||!h||h!==p?f+=d.move(p+"]"):s==="shortcut"?f=f.slice(0,-1):f+=d.move("]"),f}function L3(){return"!"}Pw.peek=z3;function Pw(e,t,r){let a=e.value||"",s="`",o=-1;for(;new RegExp("(^|[^`])"+s+"([^`]|$)").test(a);)s+="`";for(/[^ \r\n]/.test(a)&&(/^[ \r\n]/.test(a)&&/[ \r\n]$/.test(a)||/^`|`$/.test(a))&&(a=" "+a+" ");++o<r.unsafe.length;){const c=r.unsafe[o],d=r.compilePattern(c);let f;if(c.atBreak)for(;f=d.exec(a);){let h=f.index;a.charCodeAt(h)===10&&a.charCodeAt(h-1)===13&&h--,a=a.slice(0,h)+" "+a.slice(f.index+1)}}return s+a+s}function z3(){return"`"}function Fw(e,t){const r=Ap(e);return!!(!t.options.resourceLink&&e.url&&!e.title&&e.children&&e.children.length===1&&e.children[0].type==="text"&&(r===e.url||"mailto:"+r===e.url)&&/^[a-z][a-z+.-]+:/i.test(e.url)&&!/[\0- <>\u007F]/.test(e.url))}Gw.peek=I3;function Gw(e,t,r,a){const s=Up(r),o=s==='"'?"Quote":"Apostrophe",c=r.createTracker(a);let d,f;if(Fw(e,r)){const m=r.stack;r.stack=[],d=r.enter("autolink");let p=c.move("<");return p+=c.move(r.containerPhrasing(e,{before:p,after:">",...c.current()})),p+=c.move(">"),d(),r.stack=m,p}d=r.enter("link"),f=r.enter("label");let h=c.move("[");return h+=c.move(r.containerPhrasing(e,{before:h,after:"](",...c.current()})),h+=c.move("]("),f(),!e.url&&e.title||/[\0- \u007F]/.test(e.url)?(f=r.enter("destinationLiteral"),h+=c.move("<"),h+=c.move(r.safe(e.url,{before:h,after:">",...c.current()})),h+=c.move(">")):(f=r.enter("destinationRaw"),h+=c.move(r.safe(e.url,{before:h,after:e.title?" ":")",...c.current()}))),f(),e.title&&(f=r.enter(`title${o}`),h+=c.move(" "+s),h+=c.move(r.safe(e.title,{before:h,after:s,...c.current()})),h+=c.move(s),f()),h+=c.move(")"),d(),h}function I3(e,t,r){return Fw(e,r)?"<":"["}Vw.peek=B3;function Vw(e,t,r,a){const s=e.referenceType,o=r.enter("linkReference");let c=r.enter("label");const d=r.createTracker(a);let f=d.move("[");const h=r.containerPhrasing(e,{before:f,after:"]",...d.current()});f+=d.move(h+"]["),c();const m=r.stack;r.stack=[],c=r.enter("reference");const p=r.safe(r.associationId(e),{before:f,after:"]",...d.current()});return c(),r.stack=m,o(),s==="full"||!h||h!==p?f+=d.move(p+"]"):s==="shortcut"?f=f.slice(0,-1):f+=d.move("]"),f}function B3(){return"["}function Hp(e){const t=e.options.bullet||"*";if(t!=="*"&&t!=="+"&&t!=="-")throw new Error("Cannot serialize items with `"+t+"` for `options.bullet`, expected `*`, `+`, or `-`");return t}function U3(e){const t=Hp(e),r=e.options.bulletOther;if(!r)return t==="*"?"-":"*";if(r!=="*"&&r!=="+"&&r!=="-")throw new Error("Cannot serialize items with `"+r+"` for `options.bulletOther`, expected `*`, `+`, or `-`");if(r===t)throw new Error("Expected `bullet` (`"+t+"`) and `bulletOther` (`"+r+"`) to be different");return r}function H3(e){const t=e.options.bulletOrdered||".";if(t!=="."&&t!==")")throw new Error("Cannot serialize items with `"+t+"` for `options.bulletOrdered`, expected `.` or `)`");return t}function Yw(e){const t=e.options.rule||"*";if(t!=="*"&&t!=="-"&&t!=="_")throw new Error("Cannot serialize rules with `"+t+"` for `options.rule`, expected `*`, `-`, or `_`");return t}function $3(e,t,r,a){const s=r.enter("list"),o=r.bulletCurrent;let c=e.ordered?H3(r):Hp(r);const d=e.ordered?c==="."?")":".":U3(r);let f=t&&r.bulletLastUsed?c===r.bulletLastUsed:!1;if(!e.ordered){const m=e.children?e.children[0]:void 0;if((c==="*"||c==="-")&&m&&(!m.children||!m.children[0])&&r.stack[r.stack.length-1]==="list"&&r.stack[r.stack.length-2]==="listItem"&&r.stack[r.stack.length-3]==="list"&&r.stack[r.stack.length-4]==="listItem"&&r.indexStack[r.indexStack.length-1]===0&&r.indexStack[r.indexStack.length-2]===0&&r.indexStack[r.indexStack.length-3]===0&&(f=!0),Yw(r)===c&&m){let p=-1;for(;++p<e.chilLine truncated
`,inConstruct:"tableCell"},{atBreak:!0,character:"|",after:"[ :-]"},{character:"|",inConstruct:"tableCell"},{atBreak:!0,character:":",after:"-"},{atBreak:!0,character:"-",after:"[:|-]"}],handlers:{inlineCode:y,table:c,tableCell:f,tableRow:d}};function c(x,_,N,S){return h(m(x,N,S),x.align)}function d(x,_,N,S){const w=p(x,N,S),k=h([w]);return k.slice(0,k.indexOf(`
`))}function f(x,_,N,S){const w=N.enter("tableCell"),k=N.enter("phrasing"),E=N.containerPhrasing(x,{...S,before:o,after:o});return k(),w(),E}function h(x,_){return g3(x,{align:_,alignDelimiters:a,padding:r,stringLength:s})}function m(x,_,N){const S=x.children;let w=-1;const k=[],E=_.enter("table");for(;++w<S.length;)k[w]=p(S[w],_,N);return E(),k}function p(x,_,N){const S=x.children;let w=-1;const k=[],E=_.enter("tableRow");for(;++w<S.length;)k[w]=f(S[w],x,_,N);return E(),k}function y(x,_,N){let S=Kw.inlineCode(x,_,N);return N.stack.includes("tableCell")&&(S=S.replace(/\|/g,"\\$&")),S}}function r4(){return{exit:{taskListCheckValueChecked:Zy,taskListCheckValueUnchecked:Zy,paragraph:a4}}}function i4(){return{unsafe:[{atBreak:!0,character:"-",after:"[:|-]"}],handlers:{listItem:s4}}}function Zy(e){const t=this.stack[this.stack.length-2];t.type,t.checked=e.type==="taskListCheckValueChecked"}function a4(e){const t=this.stack[this.stack.length-2];if(t&&t.type==="listItem"&&typeof t.checked=="boolean"){const r=this.stack[this.stack.length-1];r.type;const a=r.children[0];if(a&&a.type==="text"){const s=t.children;let o=-1,c;for(;++o<s.length;){const d=s[o];if(d.type==="paragraph"){c=d;break}}c===r&&(a.value=a.value.slice(1),a.value.length===0?r.children.shift():r.position&&a.position&&typeof a.position.start.offset=="number"&&(a.position.start.column++,a.position.start.offset++,r.position.start=Object.assign({},a.position.start)))}}this.exit(e)}function s4(e,t,r,a){const s=e.children[0],o=typeof e.checked=="boolean"&&s&&s.type==="paragraph",c="["+(e.checked?"x":" ")+"] ",d=r.createTracker(a);o&&d.move(c);let f=Kw.listItem(e,t,r,{...a,...d.current()});return o&&(f=f.replace(/^(?:[*+-]|\d+\.)([\r\n]| {1,3})/,h)),f;function h(m){return m+c}}function l4(){return[UR(),s3(),u3(),Z3(),r4()]}function o4(e){return{extensions:[HR(),l3(e),d3(),n4(e),i4()]}}const c4={tokenize:p4,partial:!0},Zw={tokenize:g4,partial:!0},Qw={tokenize:b4,partial:!0},Ww={tokenize:x4,partial:!0},u4={tokenize:y4,partial:!0},Jw={name:"wwwAutolink",tokenize:h4,previous:tE},eE={name:"protocolAutolink",tokenize:m4,previous:nE},Ei={name:"emailAutolink",tokenize:f4,previous:rE},Kr={};function d4(){return{text:Kr}}let za=48;for(;za<123;)Kr[za]=Ei,za++,za===58?za=65:za===91&&(za=97);Kr[43]=Ei;Kr[45]=Ei;Kr[46]=Ei;Kr[95]=Ei;Kr[72]=[Ei,eE];Kr[104]=[Ei,eE];Kr[87]=[Ei,Jw];Kr[119]=[Ei,Jw];function f4(e,t,r){const a=this;let s,o;return c;function c(p){return!Qm(p)||!rE.call(a,a.previous)||$p(a.events)?r(p):(e.enter("literalAutolink"),e.enter("literalAutolinkEmail"),d(p))}function d(p){return Qm(p)?(e.consume(p),d):p===64?(e.consume(p),f):r(p)}function f(p){return p===46?e.check(u4,m,h)(p):p===45||p===95||Tn(p)?(o=!0,e.consume(p),f):m(p)}function h(p){return e.consume(p),s=!0,f}function m(p){return o&&s&&jn(a.previous)?(e.exit("literalAutolinkEmail"),e.exit("literalAutolink"),t(p)):r(p)}}function h4(e,t,r){const a=this;return s;function s(c){return c!==87&&c!==119||!tE.call(a,a.previous)||$p(a.events)?r(c):(e.enter("literalAutolink"),e.enter("literalAutolinkWww"),e.check(c4,e.attempt(Zw,e.attempt(Qw,o),r),r)(c))}function o(c){return e.exit("literalAutolinkWww"),e.exit("literalAutolink"),t(c)}}function m4(e,t,r){const a=this;let s="",o=!1;return c;function c(p){return(p===72||p===104)&&nE.call(a,a.previous)&&!$p(a.events)?(e.enter("literalAutolink"),e.enter("literalAutolinkHttp"),s+=String.fromCodePoint(p),e.consume(p),d):r(p)}function d(p){if(jn(p)&&s.length<5)return s+=String.fromCodePoint(p),e.consume(p),d;if(p===58){const y=s.toLowerCase();if(y==="http"||y==="https")return e.consume(p),f}return r(p)}function f(p){return p===47?(e.consume(p),o?h:(o=!0,f)):r(p)}function h(p){return p===null||_u(p)||Ct(p)||Fa(p)||qu(p)?r(p):e.attempt(Zw,e.attempt(Qw,m),r)(p)}function m(p){return e.exit("literalAutolinkHttp"),e.exit("literalAutolink"),t(p)}}function p4(e,t,r){let a=0;return s;function s(c){return(c===87||c===119)&&a<3?(a++,e.consume(c),s):c===46&&a===3?(e.consume(c),o):r(c)}function o(c){return c===null?r(c):t(c)}}function g4(e,t,r){let a,s,o;return c;function c(h){return h===46||h===95?e.check(Ww,f,d)(h):h===null||Ct(h)||Fa(h)||h!==45&&qu(h)?f(h):(o=!0,e.consume(h),c)}function d(h){return h===95?a=!0:(s=a,a=void 0),e.consume(h),c}function f(h){return s||a||!o?r(h):t(h)}}function b4(e,t){let r=0,a=0;return s;function s(c){return c===40?(r++,e.consume(c),s):c===41&&a<r?o(c):c===33||c===34||c===38||c===39||c===41||c===42||c===44||c===46||c===58||c===59||c===60||c===63||c===93||c===95||c===126?e.check(Ww,t,o)(c):c===null||Ct(c)||Fa(c)?t(c):(e.consume(c),s)}function o(c){return c===41&&a++,e.consume(c),s}}function x4(e,t,r){return a;function a(d){return d===33||d===34||d===39||d===41||d===42||d===44||d===46||d===58||d===59||d===63||d===95||d===126?(e.consume(d),a):d===38?(e.consume(d),o):d===93?(e.consume(d),s):d===60||d===null||Ct(d)||Fa(d)?t(d):r(d)}function s(d){return d===null||d===40||d===91||Ct(d)||Fa(d)?t(d):a(d)}function o(d){return jn(d)?c(d):r(d)}function c(d){re Line truncated
https://github.com/highlightjs/highlight.js/issues/2277`),Ht=ye,ft=Le),Qe===void 0&&(Qe=!0);const pn={code:ft,language:Ht};Jr("before:highlight",pn);const Mn=pn.result?pn.result:xr(pn.language,pn.code,Qe);return Mn.code=pn.code,Jr("after:highlight",Mn),Mn}function xr(ye,Le,Qe,ft){const Ht=Object.create(null);function pn(_e,Re){return _e.keywords[Re]}function Mn(){if(!qe.keywords){Jt.addText(bt);return}let _e=0;qe.keywordPatternRe.lastIndex=0;let Re=qe.keywordPatternRe.exec(bt),Ye="";for(;Re;){Ye+=bt.substring(_e,Re.index);const rt=un.case_insensitive?Re[0].toLowerCase():Re[0],$t=pn(qe,rt);if($t){const[lr,al]=$t;if(Jt.addText(Ye),Ye="",Ht[rt]=(Ht[rt]||0)+1,Ht[rt]<=Xn&&(Ri+=al),lr.startsWith("_"))Ye+=Re[0];else{const $o=un.classNameAliases[lr]||lr;On(Re[0],$o)}}else Ye+=Re[0];_e=qe.keywordPatternRe.lastIndex,Re=qe.keywordPatternRe.exec(bt)}Ye+=bt.substring(_e),Jt.addText(Ye)}function Nn(){if(bt==="")return;let _e=null;if(typeof qe.subLanguage=="string"){if(!me[qe.subLanguage]){Jt.addText(bt);return}_e=xr(qe.subLanguage,bt,!0,Ho[qe.subLanguage]),Ho[qe.subLanguage]=_e._top}else _e=ki(bt,qe.subLanguage.length?qe.subLanguage:null);qe.relevance>0&&(Ri+=_e.relevance),Jt.__addSublanguage(_e._emitter,_e.language)}function _t(){qe.subLanguage!=null?Nn():Mn(),bt=""}function On(_e,Re){_e!==""&&(Jt.startScope(Re),Jt.addText(_e),Jt.endScope())}function ts(_e,Re){let Ye=1;const rt=Re.length-1;for(;Ye<=rt;){if(!_e._emit[Ye]){Ye++;continue}const $t=un.classNameAliases[_e[Ye]]||_e[Ye],lr=Re[Ye];$t?On(lr,$t):(bt=lr,Mn(),bt=""),Ye++}}function Ai(_e,Re){return _e.scope&&typeof _e.scope=="string"&&Jt.openNode(un.classNameAliases[_e.scope]||_e.scope),_e.beginScope&&(_e.beginScope._wrap?(On(bt,un.classNameAliases[_e.beginScope._wrap]||_e.beginScope._wrap),bt=""):_e.beginScope._multi&&(ts(_e.beginScope,Re),bt="")),qe=Object.create(_e,{parent:{value:qe}}),qe}function Ur(_e,Re,Ye){let rt=E(_e.endRe,Ye);if(rt){if(_e["on:end"]){const $t=new t(_e);_e["on:end"](Re,$t),$t.isMatchIgnored&&(rt=!1)}if(rt){for(;_e.endsParent&&_e.parent;)_e=_e.parent;return _e}}if(_e.endsWithParent)return Ur(_e.parent,Re,Ye)}function Mi(_e){return qe.matcher.regexIndex===0?(bt+=_e[0],1):(Di=!0,0)}function ns(_e){const Re=_e[0],Ye=_e.rule,rt=new t(Ye),$t=[Ye.__beforeBegin,Ye["on:begin"]];for(const lr of $t)if(lr&&(lr(_e,rt),rt.isMatchIgnored))return Mi(Re);return Ye.skip?bt+=Re:(Ye.excludeBegin&&(bt+=Re),_t(),!Ye.returnBegin&&!Ye.excludeBegin&&(bt=Re)),Ai(Ye,_e),Ye.returnBegin?0:Re.length}function Sn(_e){const Re=_e[0],Ye=Le.substring(_e.index),rt=Ur(qe,_e,Ye);if(!rt)return nt;const $t=qe;qe.endScope&&qe.endScope._wrap?(_t(),On(Re,qe.endScope._wrap)):qe.endScope&&qe.endScope._multi?(_t(),ts(qe.endScope,_e)):$t.skip?bt+=Re:($t.returnEnd||$t.excludeEnd||(bt+=Re),_t(),$t.excludeEnd&&(bt=Re));do qe.scope&&Jt.closeNode(),!qe.skip&&!qe.subLanguage&&(Ri+=qe.relevance),qe=qe.parent;while(qe!==rt.parent);return rt.starts&&Ai(rt.starts,_e),$t.returnEnd?0:Re.length}function ba(){const _e=[];for(let Re=qe;Re!==un;Re=Re.parent)Re.scope&&_e.unshift(Re.scope);_e.forEach(Re=>Jt.openNode(Re))}let Er={};function Oi(_e,Re){const Ye=Re&&Re[0];if(bt+=_e,Ye==null)return _t(),0;if(Er.type==="begin"&&Re.type==="end"&&Er.index===Re.index&&Ye===""){if(bt+=Le.slice(Re.index,Re.index+1),!St){const rt=new Error(`0 width match regex (${ye})`);throw rt.languageName=ye,rt.badRule=Er.rule,rt}return 1}if(Er=Re,Re.type==="begin")return ns(Re);if(Re.type==="illegal"&&!Qe){const rt=new Error('Illegal lexeme "'+Ye+'" for mode "'+(qe.scope||"<unnamed>")+'"');throw rt.mode=qe,rt}else if(Re.type==="end"){const rt=Sn(Re);if(rt!==nt)return rt}if(Re.type==="illegal"&&Ye==="")return bt+=`
`,1;if(il>1e5&&il>Re.index*3)throw new Error("potential infinite loop, way more iterations than matches");return bt+=Ye,Ye.length}const un=bn(ye);if(!un)throw ct(gt.replace("{}",ye)),new Error('Unknown language: "'+ye+'"');const xa=Kt(un);let rs="",qe=ft||xa;const Ho={},Jt=new Se.__emitter(Se);ba();let bt="",Ri=0,ei=0,il=0,Di=!1;try{if(un.__emitTokens)un.__emitTokens(Le,Jt);else{for(qe.matcher.considerAll();;){il++,Di?Di=!1:qe.matcher.considerAll(),qe.matcher.lastIndex=ei;const _e=qe.matcher.exec(Le);if(!_e)break;const Re=Le.substring(ei,_e.index),Ye=Oi(Re,_e);ei=_e.index+Ye}Oi(Le.substring(ei))}return Jt.finalize(),rs=Jt.toHTML(),{language:ye,value:rs,relevance:Ri,illegal:!1,_emitter:Jt,_top:qe}}catch(_e){if(_e.message&&_e.message.includes("Illegal"))return{language:ye,value:cn(Le),illegal:!0,relevance:0,_illegalBy:{message:_e.message,index:ei,context:Le.slice(ei-100,ei+100),mode:_e.mode,resultSoFar:rs},_emitter:Jt};if(St)return{language:ye,value:cn(Le),illegal:!1,relevance:0,errorRaised:_e,_emitter:Jt,_top:qe};throw _e}}function Si(ye){const Le={value:cn(ye),illegal:!1,relevance:0,_top:Ae,_emitter:new Se.__emitter(Se)};return Le._emitter.addText(ye),Le}function ki(ye,Le){Le=Le||Se.languages||Object.keys(me);const Qe=Si(ye),ft=Le.filter(bn).filter(_r).map(_t=>xr(_t,ye,!1));ft.unshift(Qe);const Ht=ft.sort((_t,On)=>{if(_t.relevance!==On.relevance)return On.relevance-_t.relevance;if(_t.language&&On.language){if(bn(_t.language).supersetOf===On.language)return 1;if(bn(On.language).supersetOf===_t.language)return-1}return 0}),[pn,Mn]=Ht,Nn=pn;return Nn.secondBest=Mn,Nn}function sr(ye,Le,Qe){const ft=Le&&Ee[Le]||Qe;ye.classList.add("hljs"),ye.classList.add(`language-${ft}`)}function Ut(ye){let Le=null;const Qe=Bt(ye);if(Ue(Qe))return;if(Jr("before:highlightElement",{el:ye,language:Qe}),ye.dataset.highlighted){console.log("Element previously highlighted. To highlight again, first unset `dataset.highlighted`.",ye);return}if(ye.children.length>0&&(Se.ignoreUnescapedHTML||(console.warn("One of your code blocks includes unescaped HTML. This is a potentially serious security risk."),console.warn("https://github.com/highlightjs/highlight.js/wiki/security"),console.warn("The element with unescaped HTML:"),console.warn(ye)),Se.throwUnescapedHTML))throw new zn("One of your code blocks includes unescaped HTML.",ye.innerHTML);Le=ye;const ft=Le.textContent,Ht=Qe?Mt(ft,{language:Qe,ignoreIllegals:!0}):ki(ft);ye.innerHTML=Ht.value,ye.dataset.highlighted="yes",sr(ye,Qe,Ht.language),ye.result={language:Ht.language,re:Ht.relevance,relevance:Ht.relevance},Ht.secondBest&&(ye.secondBest={language:Ht.secondBest.language,relevance:Ht.secondBest.relevance}),Jr("after:highlightElement",{el:ye,result:Ht,text:ft})}function mn(ye){Se=Ni(Se,ye)}const yr=()=>{Ci(),ue("10.6.0","initHighlighting() deprecated. Use highlightAll() now.")};function Ti(){Ci(),ue("10.6.0","initHighlightingOnLoad() deprecated. Use highlightAll() now.")}let pa=!1;function Ci(){function ye(){Ci()}if(document.readyState==="loading"){pa||window.addEventListener("DOMContentLoaded",ye,!1),pa=!0;return}document.querySelectorAll(Se.cssSelector).forEach(Ut)}function Ja(ye,Le){let Qe=null;try{Qe=Le(re)}catch(ft){if(ct("Language definition for '{}' could not be registered.".replace("{}",ye)),St)ct(ft);else throw ft;Qe=Ae}Qe.name||(Qe.name=ye),me[ye]=Qe,Qe.rawDefinition=Le.bind(null,re),Qe.aliases&&vr(Qe.aliases,{languageName:ye})}function Wr(ye){delete me[ye];for(const Le of Object.keys(Ee))Ee[Le]===ye&&delete Ee[Le]}function ga(){return Object.keys(me)}function bn(ye){return ye=(ye||"").toLowerCase(),me[ye]||me[Ee[ye]]}function vr(ye,{languageName:Le}){typeof ye=="string"&&(ye=[ye]),ye.forEach(Qe=>{Ee[Qe.toLowerCase()]=Le})}function _r(ye){const Le=bn(ye);return Le&&!Le.disableAutodetect}function Br(ye){ye["before:highlightBlock"]&&!ye["before:highlightElement"]&&(ye["before:highlightElement"]=Le=>{ye["before:highlightBlock"](Object.assign({block:Le.el},Le))}),ye["after:highlightBlock"]&&!ye["after:highlightElement"]&&(ye["after:highlightElement"]=Le=>{ye["after:highlightBlock"](Object.assign({block:Le.el},Le))})}function Ft(ye){Br(ye),Pe.push(ye)}function es(ye){const Le=Pe.indexOf(ye);Le!==-1&&Pe.splice(Le,1)}function Jr(ye,Le){const Qe=ye;Pe.forEach(function(ft){ft[Qe]&&ft[Qe](Le)})}function wr(ye){return ue("10.7.0","highlightBlock will be removed entirely in v12.0"),ue("10.7.0","Please use highlightElement now."),Ut(ye)}Object.assign(re,{highlight:Mt,highlightAuto:ki,highlightAll:Ci,highlightElement:Ut,highlightBlock:wr,configure:mn,initHighlighting:yr,initHighlightingOnLoad:Ti,registerLanguage:Ja,unregisterLanguage:Wr,listLanguages:ga,getLanguage:bn,registerAliases:vr,autoDetection:_r,inherit:Ni,addPlugin:Ft,removePlugin:es}),re.debugMode=function(){St=!1},re.safeMode=function(){St=!0},re.versionString=ut,re.regex={concat:N,lookahead:y,either:w,optional:_,anyNumberOfTimes:x};for(const ye in ce)typeof ce[ye]=="object"&&e(ce[ye]);return Object.assign(re,ce),re},hn=An({}) Line truncated
`},_]}}return Xh=s,Xh}var Kh,pv;function aD(){if(pv)return Kh;pv=1;const e=m=>({IMPORTANT:{scope:"meta",begin:"!important"},BLOCK_COMMENT:m.C_BLOCK_COMMENT_MODE,HEXCOLOR:{scope:"number",begin:/#(([0-9a-fA-F]{3,4})|(([0-9a-fA-F]{2}){3,4}))\b/},FUNCTION_DISPATCH:{className:"built_in",begin:/[\w-]+(?=\()/},ATTRIBUTE_SELECTOR_MODE:{scope:"selector-attr",begin:/\[/,end:/\]/,illegal:"$",contains:[m.APOS_STRING_MODE,m.QUOTE_STRING_MODE]},CSS_NUMBER_MODE:{scope:"number",begin:m.NUMBER_RE+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",relevance:0},CSS_VARIABLE:{className:"attr",begin:/--[A-Za-z_][A-Za-z0-9_-]*/}}),t=["a","abbr","address","article","aside","audio","b","blockquote","body","button","canvas","caption","cite","code","dd","del","details","dfn","div","dl","dt","em","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","header","hgroup","html","i","iframe","img","input","ins","kbd","label","legend","li","main","mark","menu","nav","object","ol","optgroup","option","p","picture","q","quote","samp","section","select","source","span","strong","summary","sup","table","tbody","td","textarea","tfoot","th","thead","time","tr","ul","var","video"],r=["defs","g","marker","mask","pattern","svg","switch","symbol","feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feFlood","feGaussianBlur","feImage","feMerge","feMorphology","feOffset","feSpecularLighting","feTile","feTurbulence","linearGradient","radialGradient","stop","circle","ellipse","image","line","path","polygon","polyline","rect","text","use","textPath","tspan","foreignObject","clipPath"],a=[...t,...r],s=["any-hover","any-pointer","aspect-ratio","color","color-gamut","color-index","device-aspect-ratio","device-height","device-width","display-mode","forced-colors","grid","height","hover","inverted-colors","monochrome","orientation","overflow-block","overflow-inline","pointer","prefers-color-scheme","prefers-contrast","prefers-reduced-motion","prefers-reduced-transparency","resolution","scan","scripting","update","width","min-width","max-width","min-height","max-height"].sort().reverse(),o=["active","any-link","blank","checked","current","default","defined","dir","disabled","drop","empty","enabled","first","first-child","first-of-type","fullscreen","future","focus","focus-visible","focus-within","has","host","host-context","hover","indeterminate","in-range","invalid","is","lang","last-child","last-of-type","left","link","local-link","not","nth-child","nth-col","nth-last-child","nth-last-col","nth-last-of-type","nth-of-type","only-child","only-of-type","optional","out-of-range","past","placeholder-shown","read-only","read-write","required","right","root","scope","target","target-within","user-invalid","valid","visited","where"].sort().reverse(),c=["after","backdrop","before","cue","cue-region","first-letter","first-line","grammar-error","marker","part","placeholder","selection","slotted","spelling-error"].sort().reverse(),d=["accent-color","align-content","align-items","align-self","alignment-baseline","all","anchor-name","animation","animation-composition","animation-delay","animation-direction","animation-duration","animation-fill-mode","animation-iteration-count","animation-name","animation-play-state","animation-range","animation-range-end","animation-range-start","animation-timeline","animation-timing-function","appearance","aspect-ratio","backdrop-filter","backface-visibility","background","background-attachment","background-blend-mode","background-clip","background-color","background-image","background-origin","background-position","background-position-x","background-position-y","background-repeat","background-size","baseline-shift","block-size","border","border-block","border-block-color","border-block-end","border-block-end-color","border-block-end-style","border-block-end-width","border-block-start","border-block-start-color","border-block-start-style","border-block-start-width","border-block-style","border-block-width","border-bottom","border-bottom-color","border-bottom-left-radius","border-bottom-right-radius","border-bottom-style","border-bottom-width","border-collapse","border-color","border-end-end-radius","border-end-start-radius","border-image","border-image-outset","border-image-repeat","border-image-slice","border-image-source","border-image-width","border-inline","border-inline-color","border-inline-end","border-inline-end-color","border-inline-end-style","border-inline-end-width","border-inline-start","border-inline-start-color","border-inline-start-style","border-inline-start-width","border-inline-style","border-inline-width","border-left","border-left-color","border-left-style","border-left-width","border-radius","border-right","border-right-color","border-right-style","border-right-width","border-spacing","border-start-end-radius","border-start-start-radius","border-style","border-top","border-top Line truncated
]`,N={scope:"string",variants:[p,m,y,x]},S={scope:"number",variants:[{begin:"\\b0[bB][01]+(?:_[01]+)*\\b"},{begin:"\\b0[oO][0-7]+(?:_[0-7]+)*\\b"},{begin:"\\b0[xX][\\da-fA-F]+(?:_[\\da-fA-F]+)*\\b"},{begin:"(?:\\b\\d+(?:_\\d+)*(\\.(?:\\d+(?:_\\d+)*))?|\\B\\.\\d+)(?:[eE][+-]?\\d+)?"}],relevance:0},w=["false","null","true"],k=["__CLASS__","__DIR__","__FILE__","__FUNCTION__","__COMPILER_HALT_OFFSET__","__LINE__","__METHOD__","__NAMESPACE__","__TRAIT__","die","echo","exit","include","include_once","print","require","require_once","array","abstract","and","as","binary","bool","boolean","break","callable","case","catch","class","clone","const","continue","declare","default","do","double","else","elseif","empty","enddeclare","endfor","endforeach","endif","endswitch","endwhile","enum","eval","extends","final","finally","float","for","foreach","from","global","goto","if","implements","instanceof","insteadof","int","integer","interface","isset","iterable","list","match|0","mixed","new","never","object","or","private","protected","public","readonly","real","return","string","switch","throw","trait","try","unset","use","var","void","while","xor","yield"],E=["Error|0","AppendIterator","ArgumentCountError","ArithmeticError","ArrayIterator","ArrayObject","AssertionError","BadFunctionCallException","BadMethodCallException","CachingIterator","CallbackFilterIterator","CompileError","Countable","DirectoryIterator","DivisionByZeroError","DomainException","EmptyIterator","ErrorException","Exception","FilesystemIterator","FilterIterator","GlobIterator","InfiniteIterator","InvalidArgumentException","IteratorIterator","LengthException","LimitIterator","LogicException","MultipleIterator","NoRewindIterator","OutOfBoundsException","OutOfRangeException","OuterIterator","OverflowException","ParentIterator","ParseError","RangeException","RecursiveArrayIterator","RecursiveCachingIterator","RecursiveCallbackFilterIterator","RecursiveDirectoryIterator","RecursiveFilterIterator","RecursiveIterator","RecursiveIteratorIterator","RecursiveRegexIterator","RecursiveTreeIterator","RegexIterator","RuntimeException","SeekableIterator","SplDoublyLinkedList","SplFileInfo","SplFileObject","SplFixedArray","SplHeap","SplMaxHeap","SplMinHeap","SplObjectStorage","SplObserver","SplPriorityQueue","SplQueue","SplStack","SplSubject","SplTempFileObject","TypeError","UnderflowException","UnexpectedValueException","UnhandledMatchError","ArrayAccess","BackedEnum","Closure","Fiber","Generator","Iterator","IteratorAggregate","Serializable","Stringable","Throwable","Traversable","UnitEnum","WeakReference","WeakMap","Directory","__PHP_Incomplete_Class","parent","php_user_filter","self","static","stdClass"],I={keyword:k,literal:($=>{const O=[];return $.forEach(H=>{O.push(H),H.toLowerCase()===H?O.push(H.toUpperCase()):O.push(H.toLowerCase())}),O})(w),built_in:E},R=$=>$.map(O=>O.replace(/\|\d+$/,"")),U={variants:[{match:[/new/,r.concat(_,"+"),r.concat("(?!",R(E).join("\\b|"),"\\b)"),o],scope:{1:"keyword",4:"title.class"}}]},B=r.concat(s,"\\b(?!\\()"),Z={variants:[{match:[r.concat(/::/,r.lookahead(/(?!class\b)/)),B],scope:{2:"variable.constant"}},{match:[/::/,/class/],scope:{2:"variable.language"}},{match:[o,r.concat(/::/,r.lookahead(/(?!class\b)/)),B],scope:{1:"title.class",3:"variable.constant"}},{match:[o,r.concat("::",r.lookahead(/(?!class\b)/))],scope:{1:"title.class"}},{match:[o,/::/,/class/],scope:{1:"title.class",3:"variable.language"}}]},D={scope:"attr",match:r.concat(s,r.lookahead(":"),r.lookahead(/(?!::)/))},z={relevance:0,begin:/\(/,end:/\)/,keywords:I,contains:[D,d,Z,t.C_BLOCK_COMMENT_MODE,N,S,U]},P={relevance:0,match:[/\b/,r.concat("(?!fn\\b|function\\b|",R(k).join("\\b|"),"|",R(E).join("\\b|"),"\\b)"),s,r.concat(_,"*"),r.lookahead(/(?=\()/)],scope:{3:"title.function.invoke"},contains:[z]};z.contains.push(P);const V=[D,Z,t.C_BLOCK_COMMENT_MODE,N,S,U],A={begin:r.concat(/#\[\s*\\?/,r.either(o,c)),beginScope:"meta",end:/]/,endScope:"meta",keywords:{literal:w,keyword:["new","array"]},contains:[{begin:/\[/,end:/]/,keywords:{literal:w,keyword:["new","array"]},contains:["self",...V]},...V,{scope:"meta",variants:[{match:o},{match:c}]}]};return{case_insensitive:!1,keywords:I,contains:[A,t.HASH_COMMENT_MODE,t.COMMENT("//","$"),t.COMMENT("/\\*","\\*/",{contains:[{scope:"doctag",match:"@[A-Za-z]+"}]}),{match:/__halt_compiler\(\);/,keywords:"__halt_compiler",starts:{scope:"comment",end:t.MATCH_NOTHING_RE,contains:[{match:/\?>/,scope:"meta",endsParent:!0}]}},f,{scope:"variable.language",match:/\$this\b/},d,P,Z,{match:[/const/,/\s/,s],scope:{1:"keyword",3:"variable.constant"}},U,{scope:"function",relevance:0,beginKeywords:"fn function",end:/[;{]/,excludeEnd:!0,illegal:"[$%\\[]",contains:[{beginKeywords:"use"},t.UNDERSCORE_TITLE_MODE,{begin:"=>",endsParent:!0},{scope:"params",begin:"\\(",end:"\\)",excludeBegin:!0,excludeEnd:!0,keywords:I,contains:["self",A,d,Z,t.C_BLOCK_COMMENT_MODE,N,S]}]},{scope:"class",variants:[{beginKeywords:"enum",illegal:/[($"]/},{beginKeywords:"cl Line truncated
`)||c))return g.jsx("code",{className:`${e||""} bg-white/8 px-1.5 py-0.5 rounded text-[13px]`,children:t});const f=((w=r==null?void 0:r.data)==null?void 0:w.meta)||((k=r==null?void 0:r.properties)==null?void 0:k.metastring)||"",h=/title=["']?([^"'\s}]+)["']?/.exec(f),m=/startLineNumber=(\d+)/.exec(f),p=(h==null?void 0:h[1])||null,y=m?parseInt(m[1],10):1,x=p?m?`${p}:${y}`:p:null;let _;if(c)try{_=Gn.highlight(o,{language:c[1],ignoreIllegals:!0}).value}catch{_=Gn.highlightAuto(o).value}else _=Gn.highlightAuto(o).value;const N=_.split(`
`))}function f(x,_,N,S){const w=N.enter("tableCell"),k=N.enter("phrasing"),E=N.containerPhrasing(x,{...S,before:o,after:o});return k(),w(),E}function h(x,_){return x3(x,{align:_,alignDelimiters:a,padding:r,stringLength:s})}function m(x,_,N){const S=x.children;let w=-1;const k=[],E=_.enter("table");for(;++w<S.length;)k[w]=p(S[w],_,N);return E(),k}function p(x,_,N){const S=x.children;let w=-1;const k=[],E=_.enter("tableRow");for(;++w<S.length;)k[w]=f(S[w],x,_,N);return E(),k}function y(x,_,N){let S=Kw.inlineCode(x,_,N);return N.stack.includes("tableCell")&&(S=S.replace(/\|/g,"\\$&")),S}}function a4(){return{exit:{taskListCheckValueChecked:Zy,taskListCheckValueUnchecked:Zy,paragraph:l4}}}function s4(){return{unsafe:[{atBreak:!0,character:"-",after:"[:|-]"}],handlers:{listItem:o4}}}function Zy(e){const t=this.stack[this.stack.length-2];t.type,t.checked=e.type==="taskListCheckValueChecked"}function l4(e){const t=this.stack[this.stack.length-2];if(t&&t.type==="listItem"&&typeof t.checked=="boolean"){const r=this.stack[this.stack.length-1];r.type;const a=r.children[0];if(a&&a.type==="text"){const s=t.children;let o=-1,c;for(;++o<s.length;){const d=s[o];if(d.type==="paragraph"){c=d;break}}c===r&&(a.value=a.value.slice(1),a.value.length===0?r.children.shift():r.position&&a.position&&typeof a.position.start.offset=="number"&&(a.position.start.column++,a.position.start.offset++,r.position.start=Object.assign({},a.position.start)))}}this.exit(e)}function o4(e,t,r,a){const s=e.children[0],o=typeof e.checked=="boolean"&&s&&s.type==="paragraph",c="["+(e.checked?"x":" ")+"] ",d=r.createTracker(a);o&&d.move(c);let f=Kw.listItem(e,t,r,{...a,...d.current()});return o&&(f=f.replace(/^(?:[*+-]|\d+\.)([\r\n]| {1,3})/,h)),f;function h(m){return m+c}}function c4(){return[$R(),o3(),f3(),W3(),a4()]}function u4(e){return{extensions:[qR(),c3(e),h3(),i4(e),s4()]}}const d4={tokenize:b4,partial:!0},Zw={tokenize:x4,partial:!0},Qw={tokenize:y4,partial:!0},Ww={tokenize:v4,partial:!0},f4={tokenize:_4,partial:!0},Jw={name:"wwwAutolink",tokenize:p4,previous:tE},eE={name:"protocolAutolink",tokenize:g4,previous:nE},Ei={name:"emailAutolink",tokenize:m4,previous:rE},Kr={};function h4(){return{text:Kr}}let za=48;for(;za<123;)Kr[za]=Ei,za++,za===58?za=65:za===91&&(za=97);Kr[43]=Ei;Kr[45]=Ei;Kr[46]=Ei;Kr[95]=Ei;Kr[72]=[Ei,eE];Kr[104]=[Ei,eE];Kr[87]=[Ei,Jw];Kr[119]=[Ei,Jw];function m4(e,t,r){const a=this;let s,o;return c;function c(p){return!Qm(p)||!rE.call(a,a.previous)||$p(a.events)?r(p):(e.enter("literalAutolink"),e.enter("literalAutolinkEmail"),d(p))}function d(p){return Qm(p)?(e.consume(p),d):p===64?(e.consume(p),f):r(p)}function f(p){return p===46?e.check(f4,m,h)(p):p===45||p===95||Tn(p)?(o=!0,e.consume(p),f):m(p)}function h(p){return e.consume(p),s=!0,f}function m(p){return o&&s&&jn(a.previous)?(e.exit("literalAutolinkEmail"),e.exit("literalAutolink"),t(p)):r(p)}}function p4(e,t,r){const a=this;return s;function s(c){return c!==87&&c!==119||!tE.call(a,a.previous)||$p(a.events)?r(c):(e.enter("literalAutolink"),e.enter("literalAutolinkWww"),e.check(d4,e.attempt(Zw,e.attempt(Qw,o),r),r)(c))}function o(c){return e.exit("literalAutolinkWww"),e.exit("literalAutolink"),t(c)}}function g4(e,t,r){const a=this;let s="",o=!1;return c;function c(p){return(p===72||p===104)&&nE.call(a,a.previous)&&!$p(a.events)?(e.enter("literalAutolink"),e.enter("literalAutolinkHttp"),s+=String.fromCodePoint(p),e.consume(p),d):r(p)}function d(p){if(jn(p)&&s.length<5)return s+=String.fromCodePoint(p),e.consume(p),d;if(p===58){const y=s.toLowerCase();if(y==="http"||y==="https")return e.consume(p),f}return r(p)}function f(p){return p===47?(e.consume(p),o?h:(o=!0,f)):r(p)}function h(p){return p===null||_u(p)||Tt(p)||Fa(p)||qu(p)?r(p):e.attempt(Zw,e.attempt(Qw,m),r)(p)}function m(p){return e.exit("literalAutolinkHttp"),e.exit("literalAutolink"),t(p)}}function b4(e,t,r){let a=0;return s;function s(c){return(c===87||c===119)&&a<3?(a++,e.consume(c),s):c===46&&a===3?(e.consume(c),o):r(c)}function o(c){return c===null?r(c):t(c)}}function x4(e,t,r){let a,s,o;return c;function c(h){return h===46||h===95?e.check(Ww,f,d)(h):h===null||Tt(h)||Fa(h)||h!==45&&qu(h)?f(h):(o=!0,e.consume(h),c)}function d(h){return h===95?a=!0:(s=a,a=void 0),e.consume(h),c}function f(h){return s||a||!o?r(h):t(h)}}function y4(e,t){let r=0,a=0;return s;function s(c){return c===40?(r++,e.consume(c),s):c===41&&a<r?o(c):c===33||c===34||c===38||c===39||c===41||c===42||c===44||c===46||c===58||c===59||c===60||c===63||c===93||c===95||c===126?e.check(Ww,t,o)(c):c===null||Tt(c)||Fa(c)?t(c):(e.consume(c),s)}function o(c){return c===41&&a++,e.consume(c),s}}function v4(e,t,r){return a;function a(d){return d===33||d===34||d===39||d===41||d===42||d===44||d===46||d===58||d===59||d===63||d===95||d===126?(e.consume(d),a):d===38?(e.consume(d),o):d===93?(e.consume(d),s):d===60||d===null||Tt(d)||Fa(d)?t(d):r(d)}function s(d){return d===null||d===40||d===91||Tt(d)||Fa(d)?t(d):a(d)}function o(d){return jn(d)?c(d):r(d)}function c(d){re Line truncated
https://github.com/highlightjs/highlight.js/issues/2277`),Ht=ye,ft=Le),Qe===void 0&&(Qe=!0);const pn={code:ft,language:Ht};Jr("before:highlight",pn);const On=pn.result?pn.result:xr(pn.language,pn.code,Qe);return On.code=pn.code,Jr("after:highlight",On),On}function xr(ye,Le,Qe,ft){const Ht=Object.create(null);function pn(_e,Re){return _e.keywords[Re]}function On(){if(!qe.keywords){Jt.addText(bt);return}let _e=0;qe.keywordPatternRe.lastIndex=0;let Re=qe.keywordPatternRe.exec(bt),Ye="";for(;Re;){Ye+=bt.substring(_e,Re.index);const rt=un.case_insensitive?Re[0].toLowerCase():Re[0],$t=pn(qe,rt);if($t){const[or,al]=$t;if(Jt.addText(Ye),Ye="",Ht[rt]=(Ht[rt]||0)+1,Ht[rt]<=Xn&&(Ri+=al),or.startsWith("_"))Ye+=Re[0];else{const $o=un.classNameAliases[or]||or;Rn(Re[0],$o)}}else Ye+=Re[0];_e=qe.keywordPatternRe.lastIndex,Re=qe.keywordPatternRe.exec(bt)}Ye+=bt.substring(_e),Jt.addText(Ye)}function Sn(){if(bt==="")return;let _e=null;if(typeof qe.subLanguage=="string"){if(!me[qe.subLanguage]){Jt.addText(bt);return}_e=xr(qe.subLanguage,bt,!0,Ho[qe.subLanguage]),Ho[qe.subLanguage]=_e._top}else _e=ki(bt,qe.subLanguage.length?qe.subLanguage:null);qe.relevance>0&&(Ri+=_e.relevance),Jt.__addSublanguage(_e._emitter,_e.language)}function _t(){qe.subLanguage!=null?Sn():On(),bt=""}function Rn(_e,Re){_e!==""&&(Jt.startScope(Re),Jt.addText(_e),Jt.endScope())}function ts(_e,Re){let Ye=1;const rt=Re.length-1;for(;Ye<=rt;){if(!_e._emit[Ye]){Ye++;continue}const $t=un.classNameAliases[_e[Ye]]||_e[Ye],or=Re[Ye];$t?Rn(or,$t):(bt=or,On(),bt=""),Ye++}}function Ai(_e,Re){return _e.scope&&typeof _e.scope=="string"&&Jt.openNode(un.classNameAliases[_e.scope]||_e.scope),_e.beginScope&&(_e.beginScope._wrap?(Rn(bt,un.classNameAliases[_e.beginScope._wrap]||_e.beginScope._wrap),bt=""):_e.beginScope._multi&&(ts(_e.beginScope,Re),bt="")),qe=Object.create(_e,{parent:{value:qe}}),qe}function Ur(_e,Re,Ye){let rt=E(_e.endRe,Ye);if(rt){if(_e["on:end"]){const $t=new t(_e);_e["on:end"](Re,$t),$t.isMatchIgnored&&(rt=!1)}if(rt){for(;_e.endsParent&&_e.parent;)_e=_e.parent;return _e}}if(_e.endsWithParent)return Ur(_e.parent,Re,Ye)}function Mi(_e){return qe.matcher.regexIndex===0?(bt+=_e[0],1):(Di=!0,0)}function ns(_e){const Re=_e[0],Ye=_e.rule,rt=new t(Ye),$t=[Ye.__beforeBegin,Ye["on:begin"]];for(const or of $t)if(or&&(or(_e,rt),rt.isMatchIgnored))return Mi(Re);return Ye.skip?bt+=Re:(Ye.excludeBegin&&(bt+=Re),_t(),!Ye.returnBegin&&!Ye.excludeBegin&&(bt=Re)),Ai(Ye,_e),Ye.returnBegin?0:Re.length}function kn(_e){const Re=_e[0],Ye=Le.substring(_e.index),rt=Ur(qe,_e,Ye);if(!rt)return nt;const $t=qe;qe.endScope&&qe.endScope._wrap?(_t(),Rn(Re,qe.endScope._wrap)):qe.endScope&&qe.endScope._multi?(_t(),ts(qe.endScope,_e)):$t.skip?bt+=Re:($t.returnEnd||$t.excludeEnd||(bt+=Re),_t(),$t.excludeEnd&&(bt=Re));do qe.scope&&Jt.closeNode(),!qe.skip&&!qe.subLanguage&&(Ri+=qe.relevance),qe=qe.parent;while(qe!==rt.parent);return rt.starts&&Ai(rt.starts,_e),$t.returnEnd?0:Re.length}function ba(){const _e=[];for(let Re=qe;Re!==un;Re=Re.parent)Re.scope&&_e.unshift(Re.scope);_e.forEach(Re=>Jt.openNode(Re))}let Er={};function Oi(_e,Re){const Ye=Re&&Re[0];if(bt+=_e,Ye==null)return _t(),0;if(Er.type==="begin"&&Re.type==="end"&&Er.index===Re.index&&Ye===""){if(bt+=Le.slice(Re.index,Re.index+1),!St){const rt=new Error(`0 width match regex (${ye})`);throw rt.languageName=ye,rt.badRule=Er.rule,rt}return 1}if(Er=Re,Re.type==="begin")return ns(Re);if(Re.type==="illegal"&&!Qe){const rt=new Error('Illegal lexeme "'+Ye+'" for mode "'+(qe.scope||"<unnamed>")+'"');throw rt.mode=qe,rt}else if(Re.type==="end"){const rt=kn(Re);if(rt!==nt)return rt}if(Re.type==="illegal"&&Ye==="")return bt+=`
`,1;if(il>1e5&&il>Re.index*3)throw new Error("potential infinite loop, way more iterations than matches");return bt+=Ye,Ye.length}const un=bn(ye);if(!un)throw ct(gt.replace("{}",ye)),new Error('Unknown language: "'+ye+'"');const xa=Kt(un);let rs="",qe=ft||xa;const Ho={},Jt=new Se.__emitter(Se);ba();let bt="",Ri=0,ei=0,il=0,Di=!1;try{if(un.__emitTokens)un.__emitTokens(Le,Jt);else{for(qe.matcher.considerAll();;){il++,Di?Di=!1:qe.matcher.considerAll(),qe.matcher.lastIndex=ei;const _e=qe.matcher.exec(Le);if(!_e)break;const Re=Le.substring(ei,_e.index),Ye=Oi(Re,_e);ei=_e.index+Ye}Oi(Le.substring(ei))}return Jt.finalize(),rs=Jt.toHTML(),{language:ye,value:rs,relevance:Ri,illegal:!1,_emitter:Jt,_top:qe}}catch(_e){if(_e.message&&_e.message.includes("Illegal"))return{language:ye,value:cn(Le),illegal:!0,relevance:0,_illegalBy:{message:_e.message,index:ei,context:Le.slice(ei-100,ei+100),mode:_e.mode,resultSoFar:rs},_emitter:Jt};if(St)return{language:ye,value:cn(Le),illegal:!1,relevance:0,errorRaised:_e,_emitter:Jt,_top:qe};throw _e}}function Si(ye){const Le={value:cn(ye),illegal:!1,relevance:0,_top:Ae,_emitter:new Se.__emitter(Se)};return Le._emitter.addText(ye),Le}function ki(ye,Le){Le=Le||Se.languages||Object.keys(me);const Qe=Si(ye),ft=Le.filter(bn).filter(_r).map(_t=>xr(_t,ye,!1));ft.unshift(Qe);const Ht=ft.sort((_t,Rn)=>{if(_t.relevance!==Rn.relevance)return Rn.relevance-_t.relevance;if(_t.language&&Rn.language){if(bn(_t.language).supersetOf===Rn.language)return 1;if(bn(Rn.language).supersetOf===_t.language)return-1}return 0}),[pn,On]=Ht,Sn=pn;return Sn.secondBest=On,Sn}function lr(ye,Le,Qe){const ft=Le&&Ee[Le]||Qe;ye.classList.add("hljs"),ye.classList.add(`language-${ft}`)}function Ut(ye){let Le=null;const Qe=Bt(ye);if(Ue(Qe))return;if(Jr("before:highlightElement",{el:ye,language:Qe}),ye.dataset.highlighted){console.log("Element previously highlighted. To highlight again, first unset `dataset.highlighted`.",ye);return}if(ye.children.length>0&&(Se.ignoreUnescapedHTML||(console.warn("One of your code blocks includes unescaped HTML. This is a potentially serious security risk."),console.warn("https://github.com/highlightjs/highlight.js/wiki/security"),console.warn("The element with unescaped HTML:"),console.warn(ye)),Se.throwUnescapedHTML))throw new In("One of your code blocks includes unescaped HTML.",ye.innerHTML);Le=ye;const ft=Le.textContent,Ht=Qe?Mt(ft,{language:Qe,ignoreIllegals:!0}):ki(ft);ye.innerHTML=Ht.value,ye.dataset.highlighted="yes",lr(ye,Qe,Ht.language),ye.result={language:Ht.language,re:Ht.relevance,relevance:Ht.relevance},Ht.secondBest&&(ye.secondBest={language:Ht.secondBest.language,relevance:Ht.secondBest.relevance}),Jr("after:highlightElement",{el:ye,result:Ht,text:ft})}function mn(ye){Se=Ni(Se,ye)}const yr=()=>{Ti(),ue("10.6.0","initHighlighting() deprecated. Use highlightAll() now.")};function Ci(){Ti(),ue("10.6.0","initHighlightingOnLoad() deprecated. Use highlightAll() now.")}let pa=!1;function Ti(){function ye(){Ti()}if(document.readyState==="loading"){pa||window.addEventListener("DOMContentLoaded",ye,!1),pa=!0;return}document.querySelectorAll(Se.cssSelector).forEach(Ut)}function Ja(ye,Le){let Qe=null;try{Qe=Le(re)}catch(ft){if(ct("Language definition for '{}' could not be registered.".replace("{}",ye)),St)ct(ft);else throw ft;Qe=Ae}Qe.name||(Qe.name=ye),me[ye]=Qe,Qe.rawDefinition=Le.bind(null,re),Qe.aliases&&vr(Qe.aliases,{languageName:ye})}function Wr(ye){delete me[ye];for(const Le of Object.keys(Ee))Ee[Le]===ye&&delete Ee[Le]}function ga(){return Object.keys(me)}function bn(ye){return ye=(ye||"").toLowerCase(),me[ye]||me[Ee[ye]]}function vr(ye,{languageName:Le}){typeof ye=="string"&&(ye=[ye]),ye.forEach(Qe=>{Ee[Qe.toLowerCase()]=Le})}function _r(ye){const Le=bn(ye);return Le&&!Le.disableAutodetect}function Br(ye){ye["before:highlightBlock"]&&!ye["before:highlightElement"]&&(ye["before:highlightElement"]=Le=>{ye["before:highlightBlock"](Object.assign({block:Le.el},Le))}),ye["after:highlightBlock"]&&!ye["after:highlightElement"]&&(ye["after:highlightElement"]=Le=>{ye["after:highlightBlock"](Object.assign({block:Le.el},Le))})}function Ft(ye){Br(ye),Pe.push(ye)}function es(ye){const Le=Pe.indexOf(ye);Le!==-1&&Pe.splice(Le,1)}function Jr(ye,Le){const Qe=ye;Pe.forEach(function(ft){ft[Qe]&&ft[Qe](Le)})}function wr(ye){return ue("10.7.0","highlightBlock will be removed entirely in v12.0"),ue("10.7.0","Please use highlightElement now."),Ut(ye)}Object.assign(re,{highlight:Mt,highlightAuto:ki,highlightAll:Ti,highlightElement:Ut,highlightBlock:wr,configure:mn,initHighlighting:yr,initHighlightingOnLoad:Ci,registerLanguage:Ja,unregisterLanguage:Wr,listLanguages:ga,getLanguage:bn,registerAliases:vr,autoDetection:_r,inherit:Ni,addPlugin:Ft,removePlugin:es}),re.debugMode=function(){St=!1},re.safeMode=function(){St=!0},re.versionString=ut,re.regex={concat:N,lookahead:y,either:w,optional:_,anyNumberOfTimes:x};for(const ye in ce)typeof ce[ye]=="object"&&e(ce[ye]);return Object.assign(re,ce),re},hn=Mn({}) Line truncated
`},_]}}return Xh=s,Xh}var Kh,pv;function lD(){if(pv)return Kh;pv=1;const e=m=>({IMPORTANT:{scope:"meta",begin:"!important"},BLOCK_COMMENT:m.C_BLOCK_COMMENT_MODE,HEXCOLOR:{scope:"number",begin:/#(([0-9a-fA-F]{3,4})|(([0-9a-fA-F]{2}){3,4}))\b/},FUNCTION_DISPATCH:{className:"built_in",begin:/[\w-]+(?=\()/},ATTRIBUTE_SELECTOR_MODE:{scope:"selector-attr",begin:/\[/,end:/\]/,illegal:"$",contains:[m.APOS_STRING_MODE,m.QUOTE_STRING_MODE]},CSS_NUMBER_MODE:{scope:"number",begin:m.NUMBER_RE+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",relevance:0},CSS_VARIABLE:{className:"attr",begin:/--[A-Za-z_][A-Za-z0-9_-]*/}}),t=["a","abbr","address","article","aside","audio","b","blockquote","body","button","canvas","caption","cite","code","dd","del","details","dfn","div","dl","dt","em","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","header","hgroup","html","i","iframe","img","input","ins","kbd","label","legend","li","main","mark","menu","nav","object","ol","optgroup","option","p","picture","q","quote","samp","section","select","source","span","strong","summary","sup","table","tbody","td","textarea","tfoot","th","thead","time","tr","ul","var","video"],r=["defs","g","marker","mask","pattern","svg","switch","symbol","feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feFlood","feGaussianBlur","feImage","feMerge","feMorphology","feOffset","feSpecularLighting","feTile","feTurbulence","linearGradient","radialGradient","stop","circle","ellipse","image","line","path","polygon","polyline","rect","text","use","textPath","tspan","foreignObject","clipPath"],a=[...t,...r],s=["any-hover","any-pointer","aspect-ratio","color","color-gamut","color-index","device-aspect-ratio","device-height","device-width","display-mode","forced-colors","grid","height","hover","inverted-colors","monochrome","orientation","overflow-block","overflow-inline","pointer","prefers-color-scheme","prefers-contrast","prefers-reduced-motion","prefers-reduced-transparency","resolution","scan","scripting","update","width","min-width","max-width","min-height","max-height"].sort().reverse(),o=["active","any-link","blank","checked","current","default","defined","dir","disabled","drop","empty","enabled","first","first-child","first-of-type","fullscreen","future","focus","focus-visible","focus-within","has","host","host-context","hover","indeterminate","in-range","invalid","is","lang","last-child","last-of-type","left","link","local-link","not","nth-child","nth-col","nth-last-child","nth-last-col","nth-last-of-type","nth-of-type","only-child","only-of-type","optional","out-of-range","past","placeholder-shown","read-only","read-write","required","right","root","scope","target","target-within","user-invalid","valid","visited","where"].sort().reverse(),c=["after","backdrop","before","cue","cue-region","first-letter","first-line","grammar-error","marker","part","placeholder","selection","slotted","spelling-error"].sort().reverse(),d=["accent-color","align-content","align-items","align-self","alignment-baseline","all","anchor-name","animation","animation-composition","animation-delay","animation-direction","animation-duration","animation-fill-mode","animation-iteration-count","animation-name","animation-play-state","animation-range","animation-range-end","animation-range-start","animation-timeline","animation-timing-function","appearance","aspect-ratio","backdrop-filter","backface-visibility","background","background-attachment","background-blend-mode","background-clip","background-color","background-image","background-origin","background-position","background-position-x","background-position-y","background-repeat","background-size","baseline-shift","block-size","border","border-block","border-block-color","border-block-end","border-block-end-color","border-block-end-style","border-block-end-width","border-block-start","border-block-start-color","border-block-start-style","border-block-start-width","border-block-style","border-block-width","border-bottom","border-bottom-color","border-bottom-left-radius","border-bottom-right-radius","border-bottom-style","border-bottom-width","border-collapse","border-color","border-end-end-radius","border-end-start-radius","border-image","border-image-outset","border-image-repeat","border-image-slice","border-image-source","border-image-width","border-inline","border-inline-color","border-inline-end","border-inline-end-color","border-inline-end-style","border-inline-end-width","border-inline-start","border-inline-start-color","border-inline-start-style","border-inline-start-width","border-inline-style","border-inline-width","border-left","border-left-color","border-left-style","border-left-width","border-radius","border-right","border-right-color","border-right-style","border-right-width","border-spacing","border-start-end-radius","border-start-start-radius","border-style","border-top","border-top Line truncated
]`,N={scope:"string",variants:[p,m,y,x]},S={scope:"number",variants:[{begin:"\\b0[bB][01]+(?:_[01]+)*\\b"},{begin:"\\b0[oO][0-7]+(?:_[0-7]+)*\\b"},{begin:"\\b0[xX][\\da-fA-F]+(?:_[\\da-fA-F]+)*\\b"},{begin:"(?:\\b\\d+(?:_\\d+)*(\\.(?:\\d+(?:_\\d+)*))?|\\B\\.\\d+)(?:[eE][+-]?\\d+)?"}],relevance:0},w=["false","null","true"],k=["__CLASS__","__DIR__","__FILE__","__FUNCTION__","__COMPILER_HALT_OFFSET__","__LINE__","__METHOD__","__NAMESPACE__","__TRAIT__","die","echo","exit","include","include_once","print","require","require_once","array","abstract","and","as","binary","bool","boolean","break","callable","case","catch","class","clone","const","continue","declare","default","do","double","else","elseif","empty","enddeclare","endfor","endforeach","endif","endswitch","endwhile","enum","eval","extends","final","finally","float","for","foreach","from","global","goto","if","implements","instanceof","insteadof","int","integer","interface","isset","iterable","list","match|0","mixed","new","never","object","or","private","protected","public","readonly","real","return","string","switch","throw","trait","try","unset","use","var","void","while","xor","yield"],E=["Error|0","AppendIterator","ArgumentCountError","ArithmeticError","ArrayIterator","ArrayObject","AssertionError","BadFunctionCallException","BadMethodCallException","CachingIterator","CallbackFilterIterator","CompileError","Countable","DirectoryIterator","DivisionByZeroError","DomainException","EmptyIterator","ErrorException","Exception","FilesystemIterator","FilterIterator","GlobIterator","InfiniteIterator","InvalidArgumentException","IteratorIterator","LengthException","LimitIterator","LogicException","MultipleIterator","NoRewindIterator","OutOfBoundsException","OutOfRangeException","OuterIterator","OverflowException","ParentIterator","ParseError","RangeException","RecursiveArrayIterator","RecursiveCachingIterator","RecursiveCallbackFilterIterator","RecursiveDirectoryIterator","RecursiveFilterIterator","RecursiveIterator","RecursiveIteratorIterator","RecursiveRegexIterator","RecursiveTreeIterator","RegexIterator","RuntimeException","SeekableIterator","SplDoublyLinkedList","SplFileInfo","SplFileObject","SplFixedArray","SplHeap","SplMaxHeap","SplMinHeap","SplObjectStorage","SplObserver","SplPriorityQueue","SplQueue","SplStack","SplSubject","SplTempFileObject","TypeError","UnderflowException","UnexpectedValueException","UnhandledMatchError","ArrayAccess","BackedEnum","Closure","Fiber","Generator","Iterator","IteratorAggregate","Serializable","Stringable","Throwable","Traversable","UnitEnum","WeakReference","WeakMap","Directory","__PHP_Incomplete_Class","parent","php_user_filter","self","static","stdClass"],I={keyword:k,literal:($=>{const O=[];return $.forEach(H=>{O.push(H),H.toLowerCase()===H?O.push(H.toUpperCase()):O.push(H.toLowerCase())}),O})(w),built_in:E},R=$=>$.map(O=>O.replace(/\|\d+$/,"")),U={variants:[{match:[/new/,r.concat(_,"+"),r.concat("(?!",R(E).join("\\b|"),"\\b)"),o],scope:{1:"keyword",4:"title.class"}}]},B=r.concat(s,"\\b(?!\\()"),Z={variants:[{match:[r.concat(/::/,r.lookahead(/(?!class\b)/)),B],scope:{2:"variable.constant"}},{match:[/::/,/class/],scope:{2:"variable.language"}},{match:[o,r.concat(/::/,r.lookahead(/(?!class\b)/)),B],scope:{1:"title.class",3:"variable.constant"}},{match:[o,r.concat("::",r.lookahead(/(?!class\b)/))],scope:{1:"title.class"}},{match:[o,/::/,/class/],scope:{1:"title.class",3:"variable.language"}}]},D={scope:"attr",match:r.concat(s,r.lookahead(":"),r.lookahead(/(?!::)/))},z={relevance:0,begin:/\(/,end:/\)/,keywords:I,contains:[D,d,Z,t.C_BLOCK_COMMENT_MODE,N,S,U]},V={relevance:0,match:[/\b/,r.concat("(?!fn\\b|function\\b|",R(k).join("\\b|"),"|",R(E).join("\\b|"),"\\b)"),s,r.concat(_,"*"),r.lookahead(/(?=\()/)],scope:{3:"title.function.invoke"},contains:[z]};z.contains.push(V);const P=[D,Z,t.C_BLOCK_COMMENT_MODE,N,S,U],T={begin:r.concat(/#\[\s*\\?/,r.either(o,c)),beginScope:"meta",end:/]/,endScope:"meta",keywords:{literal:w,keyword:["new","array"]},contains:[{begin:/\[/,end:/]/,keywords:{literal:w,keyword:["new","array"]},contains:["self",...P]},...P,{scope:"meta",variants:[{match:o},{match:c}]}]};return{case_insensitive:!1,keywords:I,contains:[T,t.HASH_COMMENT_MODE,t.COMMENT("//","$"),t.COMMENT("/\\*","\\*/",{contains:[{scope:"doctag",match:"@[A-Za-z]+"}]}),{match:/__halt_compiler\(\);/,keywords:"__halt_compiler",starts:{scope:"comment",end:t.MATCH_NOTHING_RE,contains:[{match:/\?>/,scope:"meta",endsParent:!0}]}},f,{scope:"variable.language",match:/\$this\b/},d,V,Z,{match:[/const/,/\s/,s],scope:{1:"keyword",3:"variable.constant"}},U,{scope:"function",relevance:0,beginKeywords:"fn function",end:/[;{]/,excludeEnd:!0,illegal:"[$%\\[]",contains:[{beginKeywords:"use"},t.UNDERSCORE_TITLE_MODE,{begin:"=>",endsParent:!0},{scope:"params",begin:"\\(",end:"\\)",excludeBegin:!0,excludeEnd:!0,keywords:I,contains:["self",T,d,Z,t.C_BLOCK_COMMENT_MODE,N,S]}]},{scope:"class",variants:[{beginKeywords:"enum",illegal:/[($"]/},{beginKeywords:"cl Line truncated
`)||c))return g.jsx("code",{className:`${e||""} bg-white/8 px-1.5 py-0.5 rounded text-[13px]`,children:t});const f=((w=r==null?void 0:r.data)==null?void 0:w.meta)||((k=r==null?void 0:r.properties)==null?void 0:k.metastring)||"",h=/title=["']?([^"'\s}]+)["']?/.exec(f),m=/startLineNumber=(\d+)/.exec(f),p=(h==null?void 0:h[1])||null,y=m?parseInt(m[1],10):1,x=p?m?`${p}:${y}`:p:null,N=iE(o,c==null?void 0:c[1]).split(`
`),S=()=>{vp(o),s(!0),setTimeout(()=>s(!1),2e3)};return g.jsxs("div",{className:"group/code relative rounded-md border border-[#2a2a2a] my-4 text-[#ddd] overflow-hidden",children:[x?g.jsxs("div",{className:"flex items-stretch",children:[g.jsxs("span",{className:"relative flex items-center text-[13px] text-[#999] font-mono px-4 py-2 border-r border-[#2a2a2a]",children:[x,g.jsx("span",{className:"absolute top-0 inset-x-0 h-0.5 bg-white/60 rounded-full"})]}),g.jsx("div",{className:"flex-1 border-b border-[#2a2a2a]"}),g.jsx("button",{onClick:S,className:"px-3 py-2 text-[#555] hover:text-white transition-colors border-b border-[#2a2a2a]","aria-label":"Copy code",children:a?g.jsx(Gs,{className:"w-3.5 h-3.5 text-emerald-400"}):g.jsx(mo,{className:"w-3.5 h-3.5"})})]}):g.jsx("button",{onClick:S,className:"absolute top-2 right-2 z-10 p-1 rounded text-[#444] hover:text-white opacity-0 group-hover/code:opacity-100 transition-opacity","aria-label":"Copy code",children:a?g.jsx(Gs,{className:"w-3.5 h-3.5 text-emerald-400"}):g.jsx(mo,{className:"w-3.5 h-3.5"})}),g.jsx("div",{className:"overflow-auto max-h-[400px]",children:g.jsx("table",{className:"w-full border-collapse font-mono text-[12px] leading-[22px] [font-variant-ligatures:none]",children:g.jsx("tbody",{children:N.map((E,M)=>g.jsxs("tr",{children:[g.jsx("td",{className:"select-none w-[1px] whitespace-nowrap px-4 text-right text-[#555] align-top text-[12px] leading-[22px] border-r border-[#2a2a2a]",children:y+M}),g.jsx("td",{className:"pl-4 pr-4 whitespace-pre",dangerouslySetInnerHTML:{__html:E||`
`}})]},M))})})})]})}function Pp(){return e=>{const t=r=>{var a;if(r.type==="element"&&r.tagName==="pre"&&r.children){const s=r.children.find(o=>o.type==="element"&&o.tagName==="code");(a=s==null?void 0:s.data)!=null&&a.meta&&(s.properties=s.properties||{},s.properties.metastring=s.data.meta)}r.children&&r.children.forEach(s=>t(s))};t(e)}}const Fp={code:iE,pre:({children:e})=>g.jsx(g.Fragment,{children:e})};function oa({title:e,content:t,action:r}){return g.jsxs("section",{children:[(e||r)&&g.jsxs("div",{className:"flex items-center justify-between gap-3 mb-3",children:[e?g.jsx("h2",{className:"text-xl font-semibold text-white",children:e}):g.jsx("span",{}),r]}),g.jsx("div",{className:"prose-markdown",children:g.jsx(Bp,{remarkPlugins:[qp],rehypePlugins:[Pp],components:Fp,children:t})})]})}class RD{diff(t,r,a={}){let s;typeof a=="function"?(s=a,a={}):"callback"in a&&(s=a.callback);const o=this.castInput(t,a),c=this.castInput(r,a),d=this.removeEmpty(this.tokenize(o,a)),f=this.removeEmpty(this.tokenize(c,a));return this.diffWithOptionsObj(d,f,a,s)}diffWithOptionsObj(t,r,a,s){var o;const c=k=>{if(k=this.postProcess(k,a),s){setTimeout(function(){s(k)},0);return}else return k},d=r.length,f=t.length;let h=1,m=d+f;a.maxEditLength!=null&&(m=Math.min(m,a.maxEditLength));const p=(o=a.timeout)!==null&&o!==void 0?o:1/0,y=Date.now()+p,x=[{oldPos:-1,lastComponent:void 0}];let _=this.extractCommon(x[0],r,t,0,a);if(x[0].oldPos+1>=f&&_+1>=d)return c(this.buildValues(x[0].lastComponent,r,t));let N=-1/0,S=1/0;const w=()=>{for(let k=Math.max(N,-h);k<=Math.min(S,h);k+=2){let E;const M=x[k-1],I=x[k+1];M&&(x[k-1]=void 0);let R=!1;if(I){const B=I.oldPos-k;R=I&&0<=B&&B<d}const U=M&&M.oldPos+1<f;if(!R&&!U){x[k]=void 0;continue}if(!U||R&&M.oldPos<I.oldPos?E=this.addToPath(I,!0,!1,0,a):E=this.addToPath(M,!1,!0,1,a),_=this.extractCommon(E,r,t,k,a),E.oldPos+1>=f&&_+1>=d)return c(this.buildValues(E.lastComponent,r,t))||!0;x[k]=E,E.oldPos+1>=f&&(S=Math.min(S,k-1)),_+1>=d&&(N=Math.max(N,k+1))}h++};if(s)(function k(){setTimeout(function(){if(h>m||Date.now()>y)return s(void 0);w()||k()},0)})();else for(;h<=m&&Date.now()<=y;){const k=w();if(k)return k}}addToPath(t,r,a,s,o){const c=t.lastComponent;return c&&!o.oneChangePerToken&&c.added===r&&c.removed===a?{oldPos:t.oldPos+s,lastComponent:{count:c.count+1,added:r,removed:a,previousComponent:c.previousComponent}}:{oldPos:t.oldPos+s,lastComponent:{count:1,added:r,removed:a,previousComponent:c}}}extractCommon(t,r,a,s,o){const c=r.length,d=a.length;let f=t.oldPos,h=f-s,m=0;for(;h+1<c&&f+1<d&&this.equals(a[f+1],r[h+1],o);)h++,f++,m++,o.oneChangePerToken&&(t.lastComponent={count:1,previousComponent:t.lastComponent,added:!1,removed:!1});return m&&!o.oneChangePerToken&&(t.lastComponent={count:m,previousComponent:t.lastComponent,added:!1,removed:!1}),t.oldPos=f,h}equals(t,r,a){return a.comparator?a.comparator(t,r):t===r||!!a.ignoreCase&&t.toLowerCase()===r.toLowerCase()}removeEmpty(t){const r=[];for(let a=0;a<t.length;a++)t[a]&&r.push(t[a]);return r}castInput(t,r){return t}tokenize(t,r){return Array.from(t)}join(t){return t.join("")}postProcess(t,r){return t}get useLongestToken(){return!1}buildValues(t,r,a){const s=[];let o;for(;t;)s.push(t),o=t.previousComponent,delete t.previousComponent,t=o;s.reverse();const c=s.length;let d=0,f=0,h=0;for(;d<c;d++){const m=s[d];if(m.removed)m.value=this.join(a.slice(h,h+m.count)),h+=m.count;else{if(!m.added&&this.useLongestToken){let p=r.slice(f,f+m.count);p=p.map(function(y,x){const _=a[h+x];return _.length>y.length?_:y}),m.value=this.join(p)}else m.value=this.join(r.slice(f,f+m.count));f+=m.count,m.added||(h+=m.count)}}return s}}class DD extends RD{constructor(){super(...arguments),this.tokenize=zD}equals(t,r,a){return a.ignoreWhitespace?((!a.newlineIsToken||!t.includes(`
`}})]},M))})})})]})}function Pp(){return e=>{const t=r=>{var a;if(r.type==="element"&&r.tagName==="pre"&&r.children){const s=r.children.find(o=>o.type==="element"&&o.tagName==="code");(a=s==null?void 0:s.data)!=null&&a.meta&&(s.properties=s.properties||{},s.properties.metastring=s.data.meta)}r.children&&r.children.forEach(s=>t(s))};t(e)}}const Fp={code:aE,pre:({children:e})=>g.jsx(g.Fragment,{children:e})};function oa({title:e,content:t,action:r}){return g.jsxs("section",{children:[(e||r)&&g.jsxs("div",{className:"flex items-center justify-between gap-3 mb-3",children:[e?g.jsx("h2",{className:"text-xl font-semibold text-white",children:e}):g.jsx("span",{}),r]}),g.jsx("div",{className:"prose-markdown",children:g.jsx(Bp,{remarkPlugins:[qp],rehypePlugins:[Pp],components:Fp,children:t})})]})}class jD{diff(t,r,a={}){let s;typeof a=="function"?(s=a,a={}):"callback"in a&&(s=a.callback);const o=this.castInput(t,a),c=this.castInput(r,a),d=this.removeEmpty(this.tokenize(o,a)),f=this.removeEmpty(this.tokenize(c,a));return this.diffWithOptionsObj(d,f,a,s)}diffWithOptionsObj(t,r,a,s){var o;const c=k=>{if(k=this.postProcess(k,a),s){setTimeout(function(){s(k)},0);return}else return k},d=r.length,f=t.length;let h=1,m=d+f;a.maxEditLength!=null&&(m=Math.min(m,a.maxEditLength));const p=(o=a.timeout)!==null&&o!==void 0?o:1/0,y=Date.now()+p,x=[{oldPos:-1,lastComponent:void 0}];let _=this.extractCommon(x[0],r,t,0,a);if(x[0].oldPos+1>=f&&_+1>=d)return c(this.buildValues(x[0].lastComponent,r,t));let N=-1/0,S=1/0;const w=()=>{for(let k=Math.max(N,-h);k<=Math.min(S,h);k+=2){let E;const M=x[k-1],I=x[k+1];M&&(x[k-1]=void 0);let R=!1;if(I){const B=I.oldPos-k;R=I&&0<=B&&B<d}const U=M&&M.oldPos+1<f;if(!R&&!U){x[k]=void 0;continue}if(!U||R&&M.oldPos<I.oldPos?E=this.addToPath(I,!0,!1,0,a):E=this.addToPath(M,!1,!0,1,a),_=this.extractCommon(E,r,t,k,a),E.oldPos+1>=f&&_+1>=d)return c(this.buildValues(E.lastComponent,r,t))||!0;x[k]=E,E.oldPos+1>=f&&(S=Math.min(S,k-1)),_+1>=d&&(N=Math.max(N,k+1))}h++};if(s)(function k(){setTimeout(function(){if(h>m||Date.now()>y)return s(void 0);w()||k()},0)})();else for(;h<=m&&Date.now()<=y;){const k=w();if(k)return k}}addToPath(t,r,a,s,o){const c=t.lastComponent;return c&&!o.oneChangePerToken&&c.added===r&&c.removed===a?{oldPos:t.oldPos+s,lastComponent:{count:c.count+1,added:r,removed:a,previousComponent:c.previousComponent}}:{oldPos:t.oldPos+s,lastComponent:{count:1,added:r,removed:a,previousComponent:c}}}extractCommon(t,r,a,s,o){const c=r.length,d=a.length;let f=t.oldPos,h=f-s,m=0;for(;h+1<c&&f+1<d&&this.equals(a[f+1],r[h+1],o);)h++,f++,m++,o.oneChangePerToken&&(t.lastComponent={count:1,previousComponent:t.lastComponent,added:!1,removed:!1});return m&&!o.oneChangePerToken&&(t.lastComponent={count:m,previousComponent:t.lastComponent,added:!1,removed:!1}),t.oldPos=f,h}equals(t,r,a){return a.comparator?a.comparator(t,r):t===r||!!a.ignoreCase&&t.toLowerCase()===r.toLowerCase()}removeEmpty(t){const r=[];for(let a=0;a<t.length;a++)t[a]&&r.push(t[a]);return r}castInput(t,r){return t}tokenize(t,r){return Array.from(t)}join(t){return t.join("")}postProcess(t,r){return t}get useLongestToken(){return!1}buildValues(t,r,a){const s=[];let o;for(;t;)s.push(t),o=t.previousComponent,delete t.previousComponent,t=o;s.reverse();const c=s.length;let d=0,f=0,h=0;for(;d<c;d++){const m=s[d];if(m.removed)m.value=this.join(a.slice(h,h+m.count)),h+=m.count;else{if(!m.added&&this.useLongestToken){let p=r.slice(f,f+m.count);p=p.map(function(y,x){const _=a[h+x];return _.length>y.length?_:y}),m.value=this.join(p)}else m.value=this.join(r.slice(f,f+m.count));f+=m.count,m.added||(h+=m.count)}}return s}}class LD extends jD{constructor(){super(...arguments),this.tokenize=BD}equals(t,r,a){return a.ignoreWhitespace?((!a.newlineIsToken||!t.includes(`
`))&&(t=t.trim()),(!a.newlineIsToken||!r.includes(`
`))&&(r=r.trim())):a.ignoreNewlineAtEof&&!a.newlineIsToken&&(t.endsWith(`
`)&&(t=t.slice(0,-1)),r.endsWith(`
`)&&(r=r.slice(0,-1))),super.equals(t,r,a)}}const jD=new DD;function LD(e,t,r){return jD.diff(e,t,r)}function zD(e,t){t.stripTrailingCr&&(e=e.replace(/\r\n/g,`
`));const r=[],a=e.split(/(\n|\r\n)/);a[a.length-1]||a.pop();for(let s=0;s<a.length;s++){const o=a[s];s%2&&!t.newlineIsToken?r[r.length-1]+=o:r.push(o)}return r}function ID(e,t){try{return Gn.highlight(e,{language:t,ignoreIllegals:!0}).value}catch{return Gn.highlightAuto(e).value}}function BD({file:e,startLine:t,endLine:r,before:a,after:s,onCopy:o}){const[c,d]=ee.useState(!1),f=r&&r!==t?`${t}-${r}`:`${t}`,h=EC(e)||"text",m=LD(a,s);let p=t,y=t;const x=m.flatMap(N=>N.value.replace(/\n$/,"").split(`
`)&&(r=r.slice(0,-1))),super.equals(t,r,a)}}const zD=new LD;function ID(e,t,r){return zD.diff(e,t,r)}function BD(e,t){t.stripTrailingCr&&(e=e.replace(/\r\n/g,`
`));const r=[],a=e.split(/(\n|\r\n)/);a[a.length-1]||a.pop();for(let s=0;s<a.length;s++){const o=a[s];s%2&&!t.newlineIsToken?r[r.length-1]+=o:r.push(o)}return r}function UD(e,t){try{return Ln.highlight(e,{language:t,ignoreIllegals:!0}).value}catch{return Ln.highlightAuto(e).value}}function HD({file:e,startLine:t,endLine:r,before:a,after:s,onCopy:o}){const[c,d]=ee.useState(!1),f=r&&r!==t?`${t}-${r}`:`${t}`,h=ST(e)||"text",m=ID(a,s);let p=t,y=t;const x=m.flatMap(N=>N.value.replace(/\n$/,"").split(`
`).map(S=>{const w=S===""?`
`:h!=="text"?ID(S,h):S.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;");let k="",E="";return N.removed?k=String(p++):(N.added||(k=String(p++)),E=String(y++)),{highlighted:w,added:!!N.added,removed:!!N.removed,leftNo:k,rightNo:E}})),_=()=>{vp(s),d(!0),setTimeout(()=>d(!1),2e3),o==null||o()};return g.jsxs("div",{className:"rounded-md border border-[#2a2a2a] overflow-hidden",children:[g.jsxs("div",{className:"flex items-stretch",children:[g.jsxs("span",{className:"relative flex items-center text-[13px] text-[#999] font-mono px-4 py-2 border-r border-[#2a2a2a] break-all",children:[e,":",f,g.jsx("span",{className:"absolute top-0 inset-x-0 h-0.5 bg-white/60 rounded-full"})]}),g.jsx("div",{className:"flex-1 border-b border-[#2a2a2a]"}),g.jsx("button",{onClick:_,className:"px-3 py-2 text-[#555] hover:text-white transition-colors flex-shrink-0 border-b border-[#2a2a2a]","aria-label":"Copy fixed code",children:c?g.jsx(Gs,{className:"w-3.5 h-3.5 text-emerald-400"}):g.jsx(mo,{className:"w-3.5 h-3.5"})})]}),g.jsx("div",{className:"overflow-auto max-h-[400px]",children:g.jsx("table",{className:"w-full border-collapse font-mono text-[12px] leading-[22px] [font-variant-ligatures:none]",children:g.jsx("tbody",{children:x.map((N,S)=>g.jsxs("tr",{className:N.added?"bg-blue-500/[0.12]":N.removed?"bg-red-500/[0.12]":"",children:[g.jsx("td",{className:"select-none w-[1px] whitespace-nowrap pl-4 pr-1.5 text-right text-[#555] align-top text-[12px] leading-[22px]",children:N.leftNo}),g.jsx("td",{className:"select-none w-[1px] whitespace-nowrap pl-1.5 pr-4 text-right text-[#555] align-top text-[12px] leading-[22px] border-r border-[#2a2a2a]",children:N.rightNo}),g.jsx("td",{className:"pl-4 pr-4 whitespace-pre",dangerouslySetInnerHTML:{__html:N.highlighted}})]},S))})})})]})}function UD({description:e,scriptCode:t,onCopy:r}){const[a,s]=ee.useState(!1);if(!e&&!t)return null;const o=()=>{t&&(vp(t),s(!0),setTimeout(()=>s(!1),2e3),r==null||r())};return g.jsxs("section",{children:[g.jsx("h2",{className:"text-xl font-semibold text-white mb-3",children:"Proof of Concept"}),g.jsxs("div",{className:"space-y-4",children:[e&&g.jsx("div",{className:"prose-markdown",children:g.jsx(Bp,{remarkPlugins:[qp],rehypePlugins:[Pp],components:Fp,children:e})}),t&&g.jsxs("div",{className:"group/poc relative rounded-md border border-[#2a2a2a] overflow-hidden",children:[g.jsxs("div",{className:"flex items-stretch",children:[g.jsxs("span",{className:"relative flex items-center text-[13px] text-[#999] font-mono px-4 py-2 border-r border-[#2a2a2a]",children:["PoC Script",g.jsx("span",{className:"absolute top-0 inset-x-0 h-0.5 bg-white/60 rounded-full"})]}),g.jsx("div",{className:"flex-1 border-b border-[#2a2a2a]"}),g.jsx("button",{onClick:o,className:"px-3 py-2 text-[#555] hover:text-white transition-colors flex-shrink-0 border-b border-[#2a2a2a]","aria-label":"Copy PoC code",children:a?g.jsx(Gs,{className:"w-3.5 h-3.5 text-emerald-400"}):g.jsx(mo,{className:"w-3.5 h-3.5"})})]}),g.jsx("div",{className:"overflow-auto max-h-[400px] px-4 py-3",children:g.jsx("pre",{className:"font-mono text-[12px] leading-[22px] whitespace-pre [font-variant-ligatures:none]",children:g.jsx("code",{dangerouslySetInnerHTML:{__html:Gn.highlight(t,{language:"python"}).value}})})})]})]})]})}function aE(e){const t=e.match(/(?:https?:\/\/)?(?:www\.)?github\.com\/([^\s/]+\/[^\s/]+)/);if(t){const s=t[1].replace(/\.git$/,"");return{display:s,href:`https://github.com/${s}`,provider:"github"}}const r=e.match(/(?:https?:\/\/)?(?:www\.)?gitlab\.com\/([^\s/]+\/[^\s/]+)/);if(r){const s=r[1].replace(/\.git$/,"");return{display:s,href:`https://gitlab.com/${s}`,provider:"gitlab"}}const a=e.match(/(?:https?:\/\/)?(?:www\.)?bitbucket\.org\/([^\s/]+\/[^\s/]+)/);if(a){const s=a[1].replace(/\.git$/,"");return{display:s,href:`https://bitbucket.org/${s}`,provider:"bitbucket"}}return/^https?:\/\//i.test(e)?{display:e.replace(/^https?:\/\/(www\.)?/,""),href:e,provider:null}:/^[a-zA-Z0-9][\w.-]*\.[a-zA-Z]{2,}/.test(e)?{display:e,href:`https://${e}`,provider:null}:{display:e,href:null,provider:null}}function bo(e,t){return e?aE(e).display.replace(/\/$/,""):t||"Untitled pentest"}function HD({className:e}){return g.jsx("svg",{viewBox:"0 0 24 24",fill:"currentColor",className:e,"aria-hidden":"true",children:g.jsx("path",{d:"M2.65 3a.72.72 0 0 0-.72.83l2.86 17.39a.98.98 0 0 0 .96.82h13.72a.72.72 0 0 0 .72-.6l2.86-17.4A.72.72 0 0 0 22.3 3H2.65Zm12.1 12.53H9.3L8.06 8.9h7.8l-1.11 6.63Z"})})}function $D({provider:e,className:t}){const r=t??"w-4 h-4";return e==="gitlab"?g.jsx(_T,{className:`${r} text-orange-400`}):e==="bitbucket"?g.jsx(HD,{className:`${r} text-blue-400`}):g.jsx(yT,{className:`${r} text-white`})}const qD={attack_vector:{N:"Remotely exploitable",A:"Adjacent network",L:"Local access required",P:"Physical access required"},attack_complexity:{L:"Easy to exploit",H:"Requires specific conditions"},privileges_required:{N:"No authentication needed",L:"Low privileges needed",H:"High privileges neede Line truncated
`:h!=="text"?UD(S,h):S.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;");let k="",E="";return N.removed?k=String(p++):(N.added||(k=String(p++)),E=String(y++)),{highlighted:w,added:!!N.added,removed:!!N.removed,leftNo:k,rightNo:E}})),_=()=>{vp(s),d(!0),setTimeout(()=>d(!1),2e3),o==null||o()};return g.jsxs("div",{className:"rounded-md border border-[#2a2a2a] overflow-hidden",children:[g.jsxs("div",{className:"flex items-stretch",children:[g.jsxs("span",{className:"relative flex items-center text-[13px] text-[#999] font-mono px-4 py-2 border-r border-[#2a2a2a] break-all",children:[e,":",f,g.jsx("span",{className:"absolute top-0 inset-x-0 h-0.5 bg-white/60 rounded-full"})]}),g.jsx("div",{className:"flex-1 border-b border-[#2a2a2a]"}),g.jsx("button",{onClick:_,className:"px-3 py-2 text-[#555] hover:text-white transition-colors flex-shrink-0 border-b border-[#2a2a2a]","aria-label":"Copy fixed code",children:c?g.jsx(Gs,{className:"w-3.5 h-3.5 text-emerald-400"}):g.jsx(mo,{className:"w-3.5 h-3.5"})})]}),g.jsx("div",{className:"overflow-auto max-h-[400px]",children:g.jsx("table",{className:"w-full border-collapse font-mono text-[12px] leading-[22px] [font-variant-ligatures:none]",children:g.jsx("tbody",{children:x.map((N,S)=>g.jsxs("tr",{className:N.added?"bg-blue-500/[0.12]":N.removed?"bg-red-500/[0.12]":"",children:[g.jsx("td",{className:"select-none w-[1px] whitespace-nowrap pl-4 pr-1.5 text-right text-[#555] align-top text-[12px] leading-[22px]",children:N.leftNo}),g.jsx("td",{className:"select-none w-[1px] whitespace-nowrap pl-1.5 pr-4 text-right text-[#555] align-top text-[12px] leading-[22px] border-r border-[#2a2a2a]",children:N.rightNo}),g.jsx("td",{className:"pl-4 pr-4 whitespace-pre",dangerouslySetInnerHTML:{__html:N.highlighted}})]},S))})})})]})}const $D=/^```([^\n`]*)\r?\n([\s\S]*?)\r?\n?```$/;function sE(e){if(!e)return{code:""};const t=$D.exec(e.trim());if(!t)return{code:e};const r=t[1].trim();return{language:(r?r.split(/\s+/)[0]:void 0)||void 0,code:t[2]}}function qD({description:e,scriptCode:t,onCopy:r}){const[a,s]=ee.useState(!1);if(!e&&!t)return null;const{language:o,code:c}=sE(t),d=iE(c,o),f=()=>{c&&(vp(c),s(!0),setTimeout(()=>s(!1),2e3),r==null||r())};return g.jsxs("section",{children:[g.jsx("h2",{className:"text-xl font-semibold text-white mb-3",children:"Proof of Concept"}),g.jsxs("div",{className:"space-y-4",children:[e&&g.jsx("div",{className:"prose-markdown",children:g.jsx(Bp,{remarkPlugins:[qp],rehypePlugins:[Pp],components:Fp,children:e})}),c&&g.jsxs("div",{className:"group/poc relative rounded-md border border-[#2a2a2a] overflow-hidden",children:[g.jsxs("div",{className:"flex items-stretch",children:[g.jsxs("span",{className:"relative flex items-center text-[13px] text-[#999] font-mono px-4 py-2 border-r border-[#2a2a2a]",children:["PoC Script",g.jsx("span",{className:"absolute top-0 inset-x-0 h-0.5 bg-white/60 rounded-full"})]}),g.jsx("div",{className:"flex-1 border-b border-[#2a2a2a]"}),g.jsx("button",{onClick:f,className:"px-3 py-2 text-[#555] hover:text-white transition-colors flex-shrink-0 border-b border-[#2a2a2a]","aria-label":"Copy PoC code",children:a?g.jsx(Gs,{className:"w-3.5 h-3.5 text-emerald-400"}):g.jsx(mo,{className:"w-3.5 h-3.5"})})]}),g.jsx("div",{className:"overflow-auto max-h-[400px] px-4 py-3",children:g.jsx("pre",{className:"font-mono text-[12px] leading-[22px] whitespace-pre [font-variant-ligatures:none]",children:g.jsx("code",{dangerouslySetInnerHTML:{__html:d}})})})]})]})]})}function lE(e){const t=e.match(/(?:https?:\/\/)?(?:www\.)?github\.com\/([^\s/]+\/[^\s/]+)/);if(t){const s=t[1].replace(/\.git$/,"");return{display:s,href:`https://github.com/${s}`,provider:"github"}}const r=e.match(/(?:https?:\/\/)?(?:www\.)?gitlab\.com\/([^\s/]+\/[^\s/]+)/);if(r){const s=r[1].replace(/\.git$/,"");return{display:s,href:`https://gitlab.com/${s}`,provider:"gitlab"}}const a=e.match(/(?:https?:\/\/)?(?:www\.)?bitbucket\.org\/([^\s/]+\/[^\s/]+)/);if(a){const s=a[1].replace(/\.git$/,"");return{display:s,href:`https://bitbucket.org/${s}`,provider:"bitbucket"}}return/^https?:\/\//i.test(e)?{display:e.replace(/^https?:\/\/(www\.)?/,""),href:e,provider:null}:/^[a-zA-Z0-9][\w.-]*\.[a-zA-Z]{2,}/.test(e)?{display:e,href:`https://${e}`,provider:null}:{display:e,href:null,provider:null}}function bo(e,t){return e?lE(e).display.replace(/\/$/,""):t||"Untitled pentest"}function PD({className:e}){return g.jsx("svg",{viewBox:"0 0 24 24",fill:"currentColor",className:e,"aria-hidden":"true",children:g.jsx("path",{d:"M2.65 3a.72.72 0 0 0-.72.83l2.86 17.39a.98.98 0 0 0 .96.82h13.72a.72.72 0 0 0 .72-.6l2.86-17.4A.72.72 0 0 0 22.3 3H2.65Zm12.1 12.53H9.3L8.06 8.9h7.8l-1.11 6.63Z"})})}function FD({provider:e,className:t}){const r=t??"w-4 h-4";return e==="gitlab"?g.jsx(EC,{className:`${r} text-orange-400`}):e==="bitbucket"?g.jsx(PD,{className:`${r} text-blue-400`}):g.jsx(_C,{className:`${r} text-white`})}const GD={attack_vector:{N:"Remotely exploitable",A:"Adjacent network",L:"Local access Line truncated
* @license React
* use-sync-external-store-shim.production.js
*
@@ -446,7 +446,7 @@ https://github.com/highlightjs/highlight.js/issues/2277`),Ht=ye,ft=Le),Qe===void
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/var g1;function CI(){if(g1)return km;g1=1;var e=Co();function t(p,y){return p===y&&(p!==0||1/p===1/y)||p!==p&&y!==y}var r=typeof Object.is=="function"?Object.is:t,a=e.useState,s=e.useEffect,o=e.useLayoutEffect,c=e.useDebugValue;function d(p,y){var x=y(),_=a({inst:{value:x,getSnapshot:y}}),N=_[0].inst,S=_[1];return o(function(){N.value=x,N.getSnapshot=y,f(N)&&S({inst:N})},[p,x,y]),s(function(){return f(N)&&S({inst:N}),p(function(){f(N)&&S({inst:N})})},[p]),c(x),x}function f(p){var y=p.getSnapshot;p=p.value;try{var x=y();return!r(p,x)}catch{return!0}}function h(p,y){return y()}var m=typeof window>"u"||typeof window.document>"u"||typeof window.document.createElement>"u"?h:d;return km.useSyncExternalStore=e.useSyncExternalStore!==void 0?e.useSyncExternalStore:m,km}var b1;function AI(){return b1||(b1=1,Sm.exports=CI()),Sm.exports}/**
*/var g1;function OI(){if(g1)return km;g1=1;var e=To();function t(p,y){return p===y&&(p!==0||1/p===1/y)||p!==p&&y!==y}var r=typeof Object.is=="function"?Object.is:t,a=e.useState,s=e.useEffect,o=e.useLayoutEffect,c=e.useDebugValue;function d(p,y){var x=y(),_=a({inst:{value:x,getSnapshot:y}}),N=_[0].inst,S=_[1];return o(function(){N.value=x,N.getSnapshot=y,f(N)&&S({inst:N})},[p,x,y]),s(function(){return f(N)&&S({inst:N}),p(function(){f(N)&&S({inst:N})})},[p]),c(x),x}function f(p){var y=p.getSnapshot;p=p.value;try{var x=y();return!r(p,x)}catch{return!0}}function h(p,y){return y()}var m=typeof window>"u"||typeof window.document>"u"||typeof window.document.createElement>"u"?h:d;return km.useSyncExternalStore=e.useSyncExternalStore!==void 0?e.useSyncExternalStore:m,km}var b1;function RI(){return b1||(b1=1,Sm.exports=OI()),Sm.exports}/**
* @license React
* use-sync-external-store-shim/with-selector.production.js
*
@@ -454,34 +454,34 @@ https://github.com/highlightjs/highlight.js/issues/2277`),Ht=ye,ft=Le),Qe===void
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/var x1;function MI(){if(x1)return Nm;x1=1;var e=Co(),t=AI();function r(h,m){return h===m&&(h!==0||1/h===1/m)||h!==h&&m!==m}var a=typeof Object.is=="function"?Object.is:r,s=t.useSyncExternalStore,o=e.useRef,c=e.useEffect,d=e.useMemo,f=e.useDebugValue;return Nm.useSyncExternalStoreWithSelector=function(h,m,p,y,x){var _=o(null);if(_.current===null){var N={hasValue:!1,value:null};_.current=N}else N=_.current;_=d(function(){function w(R){if(!k){if(k=!0,E=R,R=y(R),x!==void 0&&N.hasValue){var U=N.value;if(x(U,R))return M=U}return M=R}if(U=M,a(E,R))return U;var B=y(R);return x!==void 0&&x(U,B)?(E=R,U):(E=R,M=B)}var k=!1,E,M,I=p===void 0?null:p;return[function(){return w(m())},I===null?void 0:function(){return w(I())}]},[m,p,y,x]);var S=s(h,_[0],_[1]);return c(function(){N.hasValue=!0,N.value=S},[S]),f(S),S},Nm}var y1;function OI(){return y1||(y1=1,Em.exports=MI()),Em.exports}var RI=OI();const DI=To(RI),jI={},v1=e=>{let t;const r=new Set,a=(m,p)=>{const y=typeof m=="function"?m(t):m;if(!Object.is(y,t)){const x=t;t=p??(typeof y!="object"||y===null)?y:Object.assign({},t,y),r.forEach(_=>_(t,x))}},s=()=>t,f={setState:a,getState:s,getInitialState:()=>h,subscribe:m=>(r.add(m),()=>r.delete(m)),destroy:()=>{(jI?"production":void 0)!=="production"&&console.warn("[DEPRECATED] The `destroy` method will be unsupported in a future version. Instead use unsubscribe function returned by subscribe. Everything will be garbage-collected if store is garbage-collected."),r.clear()}},h=t=e(a,s,f);return f},LI=e=>e?v1(e):v1,{useDebugValue:zI}=ua,{useSyncExternalStoreWithSelector:II}=DI,BI=e=>e;function fN(e,t=BI,r){const a=II(e.subscribe,e.getState,e.getServerState||e.getInitialState,t,r);return zI(a),a}const _1=(e,t)=>{const r=LI(e),a=(s,o=t)=>fN(r,s,o);return Object.assign(a,r),a},UI=(e,t)=>e?_1(e,t):_1;function qt(e,t){if(Object.is(e,t))return!0;if(typeof e!="object"||e===null||typeof t!="object"||t===null)return!1;if(e instanceof Map&&t instanceof Map){if(e.size!==t.size)return!1;for(const[a,s]of e)if(!Object.is(s,t.get(a)))return!1;return!0}if(e instanceof Set&&t instanceof Set){if(e.size!==t.size)return!1;for(const a of e)if(!t.has(a))return!1;return!0}const r=Object.keys(e);if(r.length!==Object.keys(t).length)return!1;for(const a of r)if(!Object.prototype.hasOwnProperty.call(t,a)||!Object.is(e[a],t[a]))return!1;return!0}N_();const td=ee.createContext(null),HI=td.Provider,hN=Lr.error001("react");function dt(e,t){const r=ee.useContext(td);if(r===null)throw new Error(hN);return fN(r,e,t)}function Lt(){const e=ee.useContext(td);if(e===null)throw new Error(hN);return ee.useMemo(()=>({getState:e.getState,setState:e.setState,subscribe:e.subscribe}),[e])}const w1={display:"none"},$I={position:"absolute",width:1,height:1,margin:-1,border:0,padding:0,overflow:"hidden",clip:"rect(0px, 0px, 0px, 0px)",clipPath:"inset(100%)"},mN="react-flow__node-desc",pN="react-flow__edge-desc",qI="react-flow__aria-live",PI=e=>e.ariaLiveMessage,FI=e=>e.ariaLabelConfig;function GI({rfId:e}){const t=dt(PI);return g.jsx("div",{id:`${qI}-${e}`,"aria-live":"assertive","aria-atomic":"true",style:$I,children:t})}function VI({rfId:e,disableKeyboardA11y:t}){const r=dt(FI);return g.jsxs(g.Fragment,{children:[g.jsx("div",{id:`${mN}-${e}`,style:w1,children:t?r["node.a11yDescription.default"]:r["node.a11yDescription.keyboardDisabled"]}),g.jsx("div",{id:`${pN}-${e}`,style:w1,children:r["edge.a11yDescription.default"]}),!t&&g.jsx(GI,{rfId:e})]})}const nd=ee.forwardRef(({position:e="top-left",children:t,className:r,style:a,...s},o)=>{const c=`${e}`.split("-");return g.jsx("div",{className:ln(["react-flow__panel",r,...c]),style:a,ref:o,...s,children:t})});nd.displayName="Panel";const E1="https://reactflow.dev?utm_source=attribution";function YI({proOptions:e,position:t="bottom-right"}){return e!=null&&e.hideAttribution?null:g.jsx(nd,{position:t,className:"react-flow__attribution","data-message":`Please only hide this attribution when you are subscribed to React Flow Pro: ${E1}`,children:g.jsx("a",{href:E1,target:"_blank",rel:"noopener noreferrer","aria-label":"React Flow attribution",children:"React Flow"})})}const XI=e=>{const t=[],r=[];for(const[,a]of e.nodeLookup)a.selected&&t.push(a.internals.userNode);for(const[,a]of e.edgeLookup)a.selected&&r.push(a);return{selectedNodes:t,selectedEdges:r}},uu=e=>e.id;function KI(e,t){return qt(e.selectedNodes.map(uu),t.selectedNodes.map(uu))&&qt(e.selectedEdges.map(uu),t.selectedEdges.map(uu))}function ZI({onSelectionChange:e}){const t=Lt(),{selectedNodes:r,selectedEdges:a}=dt(XI,KI);return ee.useEffect(()=>{const s={nodes:r,edges:a};e==null||e(s),t.getState().onSelectionChangeHandlers.forEach(o=>o(s))},[r,a,e]),null}const QI=e=>!!e.onSelectionChangeHandlers;function WI({onSelectionChange:e}){const t=dt(QI);return e||t?g.jsx(ZI,{onSelectionChange:e}):null}const gN=[0,0],JI={x:0,y:0,zoom:1},e8=["nodes","edges","defaultNodes","defaultEdges","onConnect","onConnectStart","onConnectEnd","onClickConnectStart","onClickConnectEnd","nodesDraLine truncated
*/var x1;function DI(){if(x1)return Nm;x1=1;var e=To(),t=RI();function r(h,m){return h===m&&(h!==0||1/h===1/m)||h!==h&&m!==m}var a=typeof Object.is=="function"?Object.is:r,s=t.useSyncExternalStore,o=e.useRef,c=e.useEffect,d=e.useMemo,f=e.useDebugValue;return Nm.useSyncExternalStoreWithSelector=function(h,m,p,y,x){var _=o(null);if(_.current===null){var N={hasValue:!1,value:null};_.current=N}else N=_.current;_=d(function(){function w(R){if(!k){if(k=!0,E=R,R=y(R),x!==void 0&&N.hasValue){var U=N.value;if(x(U,R))return M=U}return M=R}if(U=M,a(E,R))return U;var B=y(R);return x!==void 0&&x(U,B)?(E=R,U):(E=R,M=B)}var k=!1,E,M,I=p===void 0?null:p;return[function(){return w(m())},I===null?void 0:function(){return w(I())}]},[m,p,y,x]);var S=s(h,_[0],_[1]);return c(function(){N.hasValue=!0,N.value=S},[S]),f(S),S},Nm}var y1;function jI(){return y1||(y1=1,Em.exports=DI()),Em.exports}var LI=jI();const zI=Co(LI),II={},v1=e=>{let t;const r=new Set,a=(m,p)=>{const y=typeof m=="function"?m(t):m;if(!Object.is(y,t)){const x=t;t=p??(typeof y!="object"||y===null)?y:Object.assign({},t,y),r.forEach(_=>_(t,x))}},s=()=>t,f={setState:a,getState:s,getInitialState:()=>h,subscribe:m=>(r.add(m),()=>r.delete(m)),destroy:()=>{(II?"production":void 0)!=="production"&&console.warn("[DEPRECATED] The `destroy` method will be unsupported in a future version. Instead use unsubscribe function returned by subscribe. Everything will be garbage-collected if store is garbage-collected."),r.clear()}},h=t=e(a,s,f);return f},BI=e=>e?v1(e):v1,{useDebugValue:UI}=ua,{useSyncExternalStoreWithSelector:HI}=zI,$I=e=>e;function mN(e,t=$I,r){const a=HI(e.subscribe,e.getState,e.getServerState||e.getInitialState,t,r);return UI(a),a}const _1=(e,t)=>{const r=BI(e),a=(s,o=t)=>mN(r,s,o);return Object.assign(a,r),a},qI=(e,t)=>e?_1(e,t):_1;function qt(e,t){if(Object.is(e,t))return!0;if(typeof e!="object"||e===null||typeof t!="object"||t===null)return!1;if(e instanceof Map&&t instanceof Map){if(e.size!==t.size)return!1;for(const[a,s]of e)if(!Object.is(s,t.get(a)))return!1;return!0}if(e instanceof Set&&t instanceof Set){if(e.size!==t.size)return!1;for(const a of e)if(!t.has(a))return!1;return!0}const r=Object.keys(e);if(r.length!==Object.keys(t).length)return!1;for(const a of r)if(!Object.prototype.hasOwnProperty.call(t,a)||!Object.is(e[a],t[a]))return!1;return!0}N_();const td=ee.createContext(null),PI=td.Provider,pN=Lr.error001("react");function dt(e,t){const r=ee.useContext(td);if(r===null)throw new Error(pN);return mN(r,e,t)}function Lt(){const e=ee.useContext(td);if(e===null)throw new Error(pN);return ee.useMemo(()=>({getState:e.getState,setState:e.setState,subscribe:e.subscribe}),[e])}const w1={display:"none"},FI={position:"absolute",width:1,height:1,margin:-1,border:0,padding:0,overflow:"hidden",clip:"rect(0px, 0px, 0px, 0px)",clipPath:"inset(100%)"},gN="react-flow__node-desc",bN="react-flow__edge-desc",GI="react-flow__aria-live",VI=e=>e.ariaLiveMessage,YI=e=>e.ariaLabelConfig;function XI({rfId:e}){const t=dt(VI);return g.jsx("div",{id:`${GI}-${e}`,"aria-live":"assertive","aria-atomic":"true",style:FI,children:t})}function KI({rfId:e,disableKeyboardA11y:t}){const r=dt(YI);return g.jsxs(g.Fragment,{children:[g.jsx("div",{id:`${gN}-${e}`,style:w1,children:t?r["node.a11yDescription.default"]:r["node.a11yDescription.keyboardDisabled"]}),g.jsx("div",{id:`${bN}-${e}`,style:w1,children:r["edge.a11yDescription.default"]}),!t&&g.jsx(XI,{rfId:e})]})}const nd=ee.forwardRef(({position:e="top-left",children:t,className:r,style:a,...s},o)=>{const c=`${e}`.split("-");return g.jsx("div",{className:ln(["react-flow__panel",r,...c]),style:a,ref:o,...s,children:t})});nd.displayName="Panel";const E1="https://reactflow.dev?utm_source=attribution";function ZI({proOptions:e,position:t="bottom-right"}){return e!=null&&e.hideAttribution?null:g.jsx(nd,{position:t,className:"react-flow__attribution","data-message":`Please only hide this attribution when you are subscribed to React Flow Pro: ${E1}`,children:g.jsx("a",{href:E1,target:"_blank",rel:"noopener noreferrer","aria-label":"React Flow attribution",children:"React Flow"})})}const QI=e=>{const t=[],r=[];for(const[,a]of e.nodeLookup)a.selected&&t.push(a.internals.userNode);for(const[,a]of e.edgeLookup)a.selected&&r.push(a);return{selectedNodes:t,selectedEdges:r}},uu=e=>e.id;function WI(e,t){return qt(e.selectedNodes.map(uu),t.selectedNodes.map(uu))&&qt(e.selectedEdges.map(uu),t.selectedEdges.map(uu))}function JI({onSelectionChange:e}){const t=Lt(),{selectedNodes:r,selectedEdges:a}=dt(QI,WI);return ee.useEffect(()=>{const s={nodes:r,edges:a};e==null||e(s),t.getState().onSelectionChangeHandlers.forEach(o=>o(s))},[r,a,e]),null}const e8=e=>!!e.onSelectionChangeHandlers;function t8({onSelectionChange:e}){const t=dt(e8);return e||t?g.jsx(JI,{onSelectionChange:e}):null}const xN=[0,0],n8={x:0,y:0,zoom:1},r8=["nodes","edges","defaultNodes","defaultEdges","onConnect","onConnectStart","onConnectEnd","onClickConnectStart","onClickConnectEnd","nodesDraLine truncated
`).replace(`
`,`
+`).split(`
`)),m=h.reduce((p,y)=>p.concat(...y),[]);return[h,m]}return[[],[]]},[e]);return ee.useEffect(()=>{const f=(t==null?void 0:t.target)??T1,h=(t==null?void 0:t.actInsideInputWithModifier)??!0;if(e!==null){const m=x=>{var S,w;if(s.current=x.ctrlKey||x.metaKey||x.shiftKey||x.altKey,(!s.current||s.current&&!h)&&KE(x))return!1;const N=A1(x.code,d);if(o.current.add(x[N]),C1(c,o.current,!1)){const k=((w=(S=x.composedPath)==null?void 0:S.call(x))==null?void 0:w[0])||x.target,E=(k==null?void 0:k.nodeName)==="BUTTON"||(k==null?void 0:k.nodeName)==="A";t.preventDefault!==!1&&(s.current||!E)&&x.preventDefault(),a(!0)}},p=x=>{const _=A1(x.code,d);C1(c,o.current,!0)?(a(!1),o.current.clear()):o.current.delete(x[_]),x.key==="Meta"&&o.current.clear(),s.current=!1},y=()=>{o.current.clear(),a(!1)};return f==null||f.addEventListener("keydown",m),f==null||f.addEventListener("keyup",p),window.addEventListener("blur",y),window.addEventListener("contextmenu",y),()=>{f==null||f.removeEventListener("keydown",m),f==null||f.removeEventListener("keyup",p),window.removeEventListener("blur",y),window.removeEventListener("contextmenu",y)}}},[e,a]),r}function C1(e,t,r){return e.filter(a=>r||a.length===t.size).some(a=>a.every(s=>t.has(s)))}function A1(e,t){return t.includes(e)?"code":"key"}const i8=()=>{const e=Lt();return ee.useMemo(()=>({zoomIn:async t=>{const{panZoom:r}=e.getState();return r?r.scaleBy(1.2,t):!1},zoomOut:async t=>{const{panZoom:r}=e.getState();return r?r.scaleBy(1/1.2,t):!1},zoomTo:async(t,r)=>{const{panZoom:a}=e.getState();return a?a.scaleTo(t,r):!1},getZoom:()=>e.getState().transform[2],setViewport:async(t,r)=>{const{transform:[a,s,o],panZoom:c}=e.getState();return c?(await c.setViewport({x:t.x??a,y:t.y??s,zoom:t.zoom??o},r),!0):!1},getViewport:()=>{const[t,r,a]=e.getState().transform;return{x:t,y:r,zoom:a}},setCenter:async(t,r,a)=>e.getState().setCenter(t,r,a),fitBounds:async(t,r)=>{const{width:a,height:s,minZoom:o,maxZoom:c,panZoom:d}=e.getState(),f=tg(t,a,s,o,c,(r==null?void 0:r.padding)??.1);return d?(await d.setViewport(f,{duration:r==null?void 0:r.duration,ease:r==null?void 0:r.ease,interpolate:r==null?void 0:r.interpolate}),!0):!1},screenToFlowPosition:(t,r={})=>{const{transform:a,snapGrid:s,snapToGrid:o,domNode:c}=e.getState();if(!c)return t;const{x:d,y:f}=c.getBoundingClientRect(),h={x:t.x-d,y:t.y-f},m=r.snapGrid??s,p=r.snapToGrid??o;return Bo(h,a,p,m)},flowToScreenPosition:t=>{const{transform:r,domNode:a}=e.getState();if(!a)return t;const{x:s,y:o}=a.getBoundingClientRect(),c=Ws(t,r);return{x:c.x+s,y:c.y+o}}}),[])};function bN(e,t){const r=[],a=new Map,s=[];for(const o of e)if(o.type==="add"){s.push(o);continue}else if(o.type==="remove"||o.type==="replace")a.set(o.id,[o]);else{const c=a.get(o.id);c?c.push(o):a.set(o.id,[o])}for(const o of t){const c=a.get(o.id);if(!c){r.push(o);continue}if(c[0].type==="remove")continue;if(c[0].type==="replace"){r.push({...c[0].item});continue}const d={...o};for(const f of c)a8(f,d);r.push(d)}return s.length&&s.forEach(o=>{o.index!==void 0?r.splice(o.index,0,{...o.item}):r.push({...o.item})}),r}function a8(e,t){switch(e.type){case"select":{t.selected=e.selected;break}case"position":{typeof e.position<"u"&&(t.position=e.position),typeof e.dragging<"u"&&(t.dragging=e.dragging);break}case"dimensions":{typeof e.dimensions<"u"&&(t.measured={...e.dimensions},e.setAttributes&&((e.setAttributes===!0||e.setAttributes==="width")&&(t.width=e.dimensions.width),(e.setAttributes===!0||e.setAttributes==="height")&&(t.height=e.dimensions.height))),typeof e.resizing=="boolean"&&(t.resizing=e.resizing);break}}}function xN(e,t){return bN(e,t)}function yN(e,t){return bN(e,t)}function Ua(e,t){return{id:e,type:"select",selected:t}}function Hs(e,t=new Set,r=!1){const a=[];for(const[s,o]of e){const c=t.has(s);!(o.selected===void 0&&!c)&&o.selected!==c&&(r&&(o.selected=c),a.push(Ua(o.id,c)))}return a}function M1({items:e=[],lookup:t}){var s;const r=[],a=new Map(e.map(o=>[o.id,o]));for(const[o,c]of e.entries()){const d=t.get(c.id),f=((s=d==null?void 0:d.internals)==null?void 0:s.userNode)??d;f!==void 0&&f!==c&&r.push({id:c.id,item:c,type:"replace"}),f===void 0&&r.push({item:c,type:"add",index:o})}for(const[o]of t)a.get(o)===void 0&&r.push({id:o,type:"remove"});return r}function O1(e){return{id:e.id,type:"remove"}}const s8=GE();function l8(e,t,r={}){return Vz(e,t,{...r,onError:r.onError??s8})}const R1=e=>Oz(e),o8=e=>HE(e);function vN(e){return ee.forwardRef(e)}const _N=typeof window<"u"?ee.useLayoutEffect:ee.useEffect;function D1(e){const[t,r]=ee.useState(BigInt(0)),[a]=ee.useState(()=>c8(()=>r(s=>s+BigInt(1))));return _N(()=>{const s=a.get();s.length&&(e(s),a.reset())},[t]),a}function c8(e){let t=[];return{get:()=>t,reset:()=>{t=[]},push:r=>{t.push(r),e()}}}const wN=ee.createContext(null);function u8({children:e}){const t=Lt(),r=ee.useCallback(d=>{const{nodes:f=[],setNodes:h,hasDefaultNodes:m,onNodesChange:p,nodeLookup:y,fitViewQueued:x,onNodesChangeMiddlewareMap:_}=t.getState();let N=f;for(const w of d)N= Line truncated
M${B.x},${B.y}h${B.width}v${B.height}h${-B.width}z`,fillRule:"evenodd",pointerEvents:"none"})]})})}XN.displayName="MiniMap";const iB=ee.memo(XN),aB=e=>t=>e?`${Math.max(1/t.transform[2],1)}`:void 0,sB={[Js.Line]:"right",[Js.Handle]:"bottom-right"};function lB({nodeId:e,position:t,variant:r=Js.Handle,className:a,style:s=void 0,children:o,color:c,minWidth:d=10,minHeight:f=10,maxWidth:h=Number.MAX_VALUE,maxHeight:m=Number.MAX_VALUE,keepAspectRatio:p=!1,resizeDirection:y,autoScale:x=!0,shouldResize:_,onResizeStart:N,onResize:S,onResizeEnd:w}){const k=SN(),E=typeof e=="string"?e:k,M=Lt(),I=ee.useRef(null),R=r===Js.Handle,U=dt(ee.useCallback(aB(R&&x),[R,x]),qt),B=ee.useRef(null),Z=t??sB[r];ee.useEffect(()=>{if(!(!I.current||!E))return B.current||(B.current=TI({domNode:I.current,nodeId:E,getStoreItems:()=>{const{nodeLookup:z,transform:P,snapGrid:V,snapToGrid:A,nodeOrigin:$,domNode:O}=M.getState();return{nodeLookup:z,transform:P,snapGrid:V,snapToGrid:A,nodeOrigin:$,paneDomNode:O}},onChange:(z,P)=>{const{triggerNodeChanges:V,nodeLookup:A,parentLookup:$,nodeOrigin:O}=M.getState(),H=[],X={x:z.x,y:z.y},K=A.get(E);if(K&&K.expandParent&&K.parentId){const T=K.origin??O,j=z.width??K.measured.width??0,Y=z.height??K.measured.height??0,L={id:K.id,parentId:K.parentId,rect:{width:j,height:Y,...YE({x:z.x??K.position.x,y:z.y??K.position.y},{width:j,height:Y},K.parentId,A,T)}},G=lg([L],A,$,O);H.push(...G),X.x=z.x?Math.max(T[0]*j,z.x):void 0,X.y=z.y?Math.max(T[1]*Y,z.y):void 0}if(X.x!==void 0&&X.y!==void 0){const T={id:E,type:"position",position:{...X}};H.push(T)}if(z.width!==void 0&&z.height!==void 0){const j={id:E,type:"dimensions",resizing:!0,setAttributes:y?y==="horizontal"?"width":"height":!0,dimensions:{width:z.width,height:z.height}};H.push(j)}for(const T of P){const j={...T,type:"position"};H.push(j)}V(H)},onEnd:({width:z,height:P})=>{const V={id:E,type:"dimensions",resizing:!1,dimensions:{width:z,height:P}};M.getState().triggerNodeChanges([V])}})),B.current.update({controlPosition:Z,boundaries:{minWidth:d,minHeight:f,maxWidth:h,maxHeight:m},keepAspectRatio:p,resizeDirection:y,onResizeStart:N,onResize:S,onResizeEnd:w,shouldResize:_}),()=>{var z;(z=B.current)==null||z.destroy()}},[Z,d,f,h,m,p,N,S,w,_]);const D=Z.split("-");return g.jsx("div",{className:ln(["react-flow__resize-control","nodrag",...D,r,a]),ref:I,style:{...s,scale:U,...c&&{[R?"backgroundColor":"borderColor"]:c}},children:o})}ee.memo(lB);var vt=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),zr=vt((e,t)=>{var r=Object.defineProperty,a=(V,A,$)=>A in V?r(V,A,{enumerable:!0,configurable:!0,writable:!0,value:$}):V[A]=$,s=(V,A)=>()=>(A||V((A={exports:{}}).exports,A),A.exports),o=(V,A,$)=>a(V,typeof A!="symbol"?A+"":A,$),c=s((V,A)=>{var $="\0",O="\0",H="",X=class{constructor(G){o(this,"_isDirected",!0),o(this,"_isMultigraph",!1),o(this,"_isCompound",!1),o(this,"_label"),o(this,"_defaultNodeLabelFn",()=>{}),o(this,"_defaultEdgeLabelFn",()=>{}),o(this,"_nodes",{}),o(this,"_in",{}),o(this,"_preds",{}),o(this,"_out",{}),o(this,"_sucs",{}),o(this,"_edgeObjs",{}),o(this,"_edgeLabels",{}),o(this,"_nodeCount",0),o(this,"_edgeCount",0),o(this,"_parent"),o(this,"_children"),G&&(this._isDirected=Object.hasOwn(G,"directed")?G.directed:!0,this._isMultigraph=Object.hasOwn(G,"multigraph")?G.multigraph:!1,this._isCompound=Object.hasOwn(G,"compound")?G.compound:!1),this._isCompound&&(this._parent={},this._children={},this._children[O]={})}isDirected(){return this._isDirected}isMultigraph(){return this._isMultigraph}isCompound(){return this._isCompound}setGraph(G){return this._label=G,this}graph(){return this._label}setDefaultNodeLabel(G){return this._defaultNodeLabelFn=G,typeof G!="function"&&(this._defaultNodeLabelFn=()=>G),this}nodeCount(){return this._nodeCount}nodes(){return Object.keys(this._nodes)}sources(){var G=this;return this.nodes().filter(q=>Object.keys(G._in[q]).length===0)}sinks(){var G=this;return this.nodes().filter(q=>Object.keys(G._out[q]).length===0)}setNodes(G,q){var Q=arguments,J=this;return G.forEach(function(W){Q.length>1?J.setNode(W,q):J.setNode(W)}),this}setNode(G,q){return Object.hasOwn(this._nodes,G)?(arguments.length>1&&(this._nodes[G]=q),this):(this._nodes[G]=arguments.length>1?q:this._defaultNodeLabelFn(G),this._isCompound&&(this._parent[G]=O,this._children[G]={},this._children[O][G]=!0),this._in[G]={},this._preds[G]={},this._out[G]={},this._sucs[G]={},++this._nodeCount,this)}node(G){return this._nodes[G]}hasNode(G){return Object.hasOwn(this._nodes,G)}removeNode(G){var q=this;if(Object.hasOwn(this._nodes,G)){var Q=J=>q.removeEdge(q._edgeObjs[J]);delete this._nodes[G],this._isCompound&&(this._removeFromParentsChildList(G),delete this._parent[G],this.children(G).forEach(function(J){q.setParent(J)}),delete this._children[G]),Object.keys(this._in[G]).forEach(Q),delete this._in[G],delete this._preds[G],Object.keys(this._out[G]).forEach(Q),delete this._out[G],delete this._sucs[G],--this._nodeCount}return this}setParent(G,q){if(!this._isCompound Line truncated
`)),m=h.reduce((p,y)=>p.concat(...y),[]);return[h,m]}return[[],[]]},[e]);return ee.useEffect(()=>{const f=(t==null?void 0:t.target)??C1,h=(t==null?void 0:t.actInsideInputWithModifier)??!0;if(e!==null){const m=x=>{var S,w;if(s.current=x.ctrlKey||x.metaKey||x.shiftKey||x.altKey,(!s.current||s.current&&!h)&&QE(x))return!1;const N=A1(x.code,d);if(o.current.add(x[N]),T1(c,o.current,!1)){const k=((w=(S=x.composedPath)==null?void 0:S.call(x))==null?void 0:w[0])||x.target,E=(k==null?void 0:k.nodeName)==="BUTTON"||(k==null?void 0:k.nodeName)==="A";t.preventDefault!==!1&&(s.current||!E)&&x.preventDefault(),a(!0)}},p=x=>{const _=A1(x.code,d);T1(c,o.current,!0)?(a(!1),o.current.clear()):o.current.delete(x[_]),x.key==="Meta"&&o.current.clear(),s.current=!1},y=()=>{o.current.clear(),a(!1)};return f==null||f.addEventListener("keydown",m),f==null||f.addEventListener("keyup",p),window.addEventListener("blur",y),window.addEventListener("contextmenu",y),()=>{f==null||f.removeEventListener("keydown",m),f==null||f.removeEventListener("keyup",p),window.removeEventListener("blur",y),window.removeEventListener("contextmenu",y)}}},[e,a]),r}function T1(e,t,r){return e.filter(a=>r||a.length===t.size).some(a=>a.every(s=>t.has(s)))}function A1(e,t){return t.includes(e)?"code":"key"}const l8=()=>{const e=Lt();return ee.useMemo(()=>({zoomIn:async t=>{const{panZoom:r}=e.getState();return r?r.scaleBy(1.2,t):!1},zoomOut:async t=>{const{panZoom:r}=e.getState();return r?r.scaleBy(1/1.2,t):!1},zoomTo:async(t,r)=>{const{panZoom:a}=e.getState();return a?a.scaleTo(t,r):!1},getZoom:()=>e.getState().transform[2],setViewport:async(t,r)=>{const{transform:[a,s,o],panZoom:c}=e.getState();return c?(await c.setViewport({x:t.x??a,y:t.y??s,zoom:t.zoom??o},r),!0):!1},getViewport:()=>{const[t,r,a]=e.getState().transform;return{x:t,y:r,zoom:a}},setCenter:async(t,r,a)=>e.getState().setCenter(t,r,a),fitBounds:async(t,r)=>{const{width:a,height:s,minZoom:o,maxZoom:c,panZoom:d}=e.getState(),f=tg(t,a,s,o,c,(r==null?void 0:r.padding)??.1);return d?(await d.setViewport(f,{duration:r==null?void 0:r.duration,ease:r==null?void 0:r.ease,interpolate:r==null?void 0:r.interpolate}),!0):!1},screenToFlowPosition:(t,r={})=>{const{transform:a,snapGrid:s,snapToGrid:o,domNode:c}=e.getState();if(!c)return t;const{x:d,y:f}=c.getBoundingClientRect(),h={x:t.x-d,y:t.y-f},m=r.snapGrid??s,p=r.snapToGrid??o;return Bo(h,a,p,m)},flowToScreenPosition:t=>{const{transform:r,domNode:a}=e.getState();if(!a)return t;const{x:s,y:o}=a.getBoundingClientRect(),c=Ws(t,r);return{x:c.x+s,y:c.y+o}}}),[])};function yN(e,t){const r=[],a=new Map,s=[];for(const o of e)if(o.type==="add"){s.push(o);continue}else if(o.type==="remove"||o.type==="replace")a.set(o.id,[o]);else{const c=a.get(o.id);c?c.push(o):a.set(o.id,[o])}for(const o of t){const c=a.get(o.id);if(!c){r.push(o);continue}if(c[0].type==="remove")continue;if(c[0].type==="replace"){r.push({...c[0].item});continue}const d={...o};for(const f of c)o8(f,d);r.push(d)}return s.length&&s.forEach(o=>{o.index!==void 0?r.splice(o.index,0,{...o.item}):r.push({...o.item})}),r}function o8(e,t){switch(e.type){case"select":{t.selected=e.selected;break}case"position":{typeof e.position<"u"&&(t.position=e.position),typeof e.dragging<"u"&&(t.dragging=e.dragging);break}case"dimensions":{typeof e.dimensions<"u"&&(t.measured={...e.dimensions},e.setAttributes&&((e.setAttributes===!0||e.setAttributes==="width")&&(t.width=e.dimensions.width),(e.setAttributes===!0||e.setAttributes==="height")&&(t.height=e.dimensions.height))),typeof e.resizing=="boolean"&&(t.resizing=e.resizing);break}}}function vN(e,t){return yN(e,t)}function _N(e,t){return yN(e,t)}function Ua(e,t){return{id:e,type:"select",selected:t}}function Hs(e,t=new Set,r=!1){const a=[];for(const[s,o]of e){const c=t.has(s);!(o.selected===void 0&&!c)&&o.selected!==c&&(r&&(o.selected=c),a.push(Ua(o.id,c)))}return a}function M1({items:e=[],lookup:t}){var s;const r=[],a=new Map(e.map(o=>[o.id,o]));for(const[o,c]of e.entries()){const d=t.get(c.id),f=((s=d==null?void 0:d.internals)==null?void 0:s.userNode)??d;f!==void 0&&f!==c&&r.push({id:c.id,item:c,type:"replace"}),f===void 0&&r.push({item:c,type:"add",index:o})}for(const[o]of t)a.get(o)===void 0&&r.push({id:o,type:"remove"});return r}function O1(e){return{id:e.id,type:"remove"}}const c8=YE();function u8(e,t,r={}){return Kz(e,t,{...r,onError:r.onError??c8})}const R1=e=>jz(e),d8=e=>qE(e);function wN(e){return ee.forwardRef(e)}const EN=typeof window<"u"?ee.useLayoutEffect:ee.useEffect;function D1(e){const[t,r]=ee.useState(BigInt(0)),[a]=ee.useState(()=>f8(()=>r(s=>s+BigInt(1))));return EN(()=>{const s=a.get();s.length&&(e(s),a.reset())},[t]),a}function f8(e){let t=[];return{get:()=>t,reset:()=>{t=[]},push:r=>{t.push(r),e()}}}const NN=ee.createContext(null);function h8({children:e}){const t=Lt(),r=ee.useCallback(d=>{const{nodes:f=[],setNodes:h,hasDefaultNodes:m,onNodesChange:p,nodeLookup:y,fitViewQueued:x,onNodesChangeMiddlewareMap:_}=t.getState();let N=f;for(const w of d)N= Line truncated
M${B.x},${B.y}h${B.width}v${B.height}h${-B.width}z`,fillRule:"evenodd",pointerEvents:"none"})]})})}ZN.displayName="MiniMap";const lB=ee.memo(ZN),oB=e=>t=>e?`${Math.max(1/t.transform[2],1)}`:void 0,cB={[Js.Line]:"right",[Js.Handle]:"bottom-right"};function uB({nodeId:e,position:t,variant:r=Js.Handle,className:a,style:s=void 0,children:o,color:c,minWidth:d=10,minHeight:f=10,maxWidth:h=Number.MAX_VALUE,maxHeight:m=Number.MAX_VALUE,keepAspectRatio:p=!1,resizeDirection:y,autoScale:x=!0,shouldResize:_,onResizeStart:N,onResize:S,onResizeEnd:w}){const k=CN(),E=typeof e=="string"?e:k,M=Lt(),I=ee.useRef(null),R=r===Js.Handle,U=dt(ee.useCallback(oB(R&&x),[R,x]),qt),B=ee.useRef(null),Z=t??cB[r];ee.useEffect(()=>{if(!(!I.current||!E))return B.current||(B.current=MI({domNode:I.current,nodeId:E,getStoreItems:()=>{const{nodeLookup:z,transform:V,snapGrid:P,snapToGrid:T,nodeOrigin:$,domNode:O}=M.getState();return{nodeLookup:z,transform:V,snapGrid:P,snapToGrid:T,nodeOrigin:$,paneDomNode:O}},onChange:(z,V)=>{const{triggerNodeChanges:P,nodeLookup:T,parentLookup:$,nodeOrigin:O}=M.getState(),H=[],X={x:z.x,y:z.y},K=T.get(E);if(K&&K.expandParent&&K.parentId){const C=K.origin??O,j=z.width??K.measured.width??0,Y=z.height??K.measured.height??0,L={id:K.id,parentId:K.parentId,rect:{width:j,height:Y,...KE({x:z.x??K.position.x,y:z.y??K.position.y},{width:j,height:Y},K.parentId,T,C)}},G=lg([L],T,$,O);H.push(...G),X.x=z.x?Math.max(C[0]*j,z.x):void 0,X.y=z.y?Math.max(C[1]*Y,z.y):void 0}if(X.x!==void 0&&X.y!==void 0){const C={id:E,type:"position",position:{...X}};H.push(C)}if(z.width!==void 0&&z.height!==void 0){const j={id:E,type:"dimensions",resizing:!0,setAttributes:y?y==="horizontal"?"width":"height":!0,dimensions:{width:z.width,height:z.height}};H.push(j)}for(const C of V){const j={...C,type:"position"};H.push(j)}P(H)},onEnd:({width:z,height:V})=>{const P={id:E,type:"dimensions",resizing:!1,dimensions:{width:z,height:V}};M.getState().triggerNodeChanges([P])}})),B.current.update({controlPosition:Z,boundaries:{minWidth:d,minHeight:f,maxWidth:h,maxHeight:m},keepAspectRatio:p,resizeDirection:y,onResizeStart:N,onResize:S,onResizeEnd:w,shouldResize:_}),()=>{var z;(z=B.current)==null||z.destroy()}},[Z,d,f,h,m,p,N,S,w,_]);const D=Z.split("-");return g.jsx("div",{className:ln(["react-flow__resize-control","nodrag",...D,r,a]),ref:I,style:{...s,scale:U,...c&&{[R?"backgroundColor":"borderColor"]:c}},children:o})}ee.memo(uB);var vt=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),zr=vt((e,t)=>{var r=Object.defineProperty,a=(P,T,$)=>T in P?r(P,T,{enumerable:!0,configurable:!0,writable:!0,value:$}):P[T]=$,s=(P,T)=>()=>(T||P((T={exports:{}}).exports,T),T.exports),o=(P,T,$)=>a(P,typeof T!="symbol"?T+"":T,$),c=s((P,T)=>{var $="\0",O="\0",H="",X=class{constructor(G){o(this,"_isDirected",!0),o(this,"_isMultigraph",!1),o(this,"_isCompound",!1),o(this,"_label"),o(this,"_defaultNodeLabelFn",()=>{}),o(this,"_defaultEdgeLabelFn",()=>{}),o(this,"_nodes",{}),o(this,"_in",{}),o(this,"_preds",{}),o(this,"_out",{}),o(this,"_sucs",{}),o(this,"_edgeObjs",{}),o(this,"_edgeLabels",{}),o(this,"_nodeCount",0),o(this,"_edgeCount",0),o(this,"_parent"),o(this,"_children"),G&&(this._isDirected=Object.hasOwn(G,"directed")?G.directed:!0,this._isMultigraph=Object.hasOwn(G,"multigraph")?G.multigraph:!1,this._isCompound=Object.hasOwn(G,"compound")?G.compound:!1),this._isCompound&&(this._parent={},this._children={},this._children[O]={})}isDirected(){return this._isDirected}isMultigraph(){return this._isMultigraph}isCompound(){return this._isCompound}setGraph(G){return this._label=G,this}graph(){return this._label}setDefaultNodeLabel(G){return this._defaultNodeLabelFn=G,typeof G!="function"&&(this._defaultNodeLabelFn=()=>G),this}nodeCount(){return this._nodeCount}nodes(){return Object.keys(this._nodes)}sources(){var G=this;return this.nodes().filter(q=>Object.keys(G._in[q]).length===0)}sinks(){var G=this;return this.nodes().filter(q=>Object.keys(G._out[q]).length===0)}setNodes(G,q){var Q=arguments,J=this;return G.forEach(function(W){Q.length>1?J.setNode(W,q):J.setNode(W)}),this}setNode(G,q){return Object.hasOwn(this._nodes,G)?(arguments.length>1&&(this._nodes[G]=q),this):(this._nodes[G]=arguments.length>1?q:this._defaultNodeLabelFn(G),this._isCompound&&(this._parent[G]=O,this._children[G]={},this._children[O][G]=!0),this._in[G]={},this._preds[G]={},this._out[G]={},this._sucs[G]={},++this._nodeCount,this)}node(G){return this._nodes[G]}hasNode(G){return Object.hasOwn(this._nodes,G)}removeNode(G){var q=this;if(Object.hasOwn(this._nodes,G)){var Q=J=>q.removeEdge(q._edgeObjs[J]);delete this._nodes[G],this._isCompound&&(this._removeFromParentsChildList(G),delete this._parent[G],this.children(G).forEach(function(J){q.setParent(J)}),delete this._children[G]),Object.keys(this._in[G]).forEach(Q),delete this._in[G],delete this._preds[G],Object.keys(this._out[G]).forEach(Q),delete this._out[G],delete this._sucs[G],--this._nodeCount}return this}setParent(G,q){if(!this._isCompound Line truncated
`).length>t;return g.jsxs("div",{children:[g.jsx("div",{className:r&&o?"max-h-[1200px] overflow-auto":"",style:!r&&o?{display:"-webkit-box",WebkitLineClamp:t,WebkitBoxOrient:"vertical",overflow:"hidden"}:void 0,children:g.jsx($s,{text:e})}),o&&g.jsx("button",{onClick:()=>a(!r),className:"text-xs text-[#555] hover:text-[#888] mt-1",children:r?"Show less":"Show more"})]})}function wi({children:e,className:t=""}){const[r,a]=ee.useState(!1),o=typeof e=="string"?e.trimEnd().split(`
`):null,c=o!==null&&o.length>Z1,d=c&&!r?o.slice(0,Z1).join(`
`):e;return g.jsxs("div",{children:[g.jsx("pre",{className:`font-mono text-[13px] leading-relaxed whitespace-pre-wrap break-words mt-1 ${r?"overflow-auto max-h-[1200px]":"overflow-hidden"} ${t}`,children:d}),c&&g.jsx("button",{onClick:()=>a(!r),className:"text-xs text-[#555] hover:text-[#888] mt-0.5",children:r?"Show less":"Show more"})]})}function cg({code:e,language:t,className:r="",collapsible:a=!1}){const[s,o]=ee.useState(!1),c=e.trimEnd().split(`
`),d=a&&c.length>Q1,f=d&&!s?c.slice(0,Q1).join(`
`):e;let h;try{h=t?Gn.highlight(f,{language:t,ignoreIllegals:!0}).value:Gn.highlightAuto(f).value}catch{h=Gn.highlightAuto(f).value}return g.jsxs("div",{children:[g.jsx("pre",{className:`font-mono text-[12px] leading-relaxed px-0 py-1 mt-1 whitespace-pre-wrap break-all ${a?s?"overflow-auto max-h-[1200px]":"overflow-hidden":"overflow-auto max-h-[400px]"} ${r}`,children:g.jsx("code",{dangerouslySetInnerHTML:{__html:h}})}),d&&g.jsx("button",{onClick:()=>o(!s),className:"text-xs text-[#555] hover:text-[#888] mt-0.5",children:s?"Show less":"Show more"})]})}const $B=50,W1=200,J1=25,e_=24,qB=[/\n?\[Command still running after [\d.]+s - showing output so far\.?\s*(?:Use C-c to interrupt if needed\.)?\]/g,/^\[Below is the output of the previous command\.\]\n?/gm,/^No command is currently running\. Cannot send input\.$/gm,/^A command is already running\. Use is_input=true to send input to it, or interrupt it first \(e\.g\., with C-c\)\.$/gm],PB=/^Chunk ID: [0-9a-f]+\s*$/,FB=[/^Wall time: [\d.]+ seconds\s*$/,/^Process exited with code -?\d+\s*$/,/^Process running with session ID \d+\s*$/,/^Original token count: \d+\s*$/];function GB(e){const t=[];for(let r=0;r<e.length;r++){if(PB.test(e[r])){let a=r+1;for(;a<e.length&&FB.some(s=>s.test(e[a]));)a++;a<e.length&&e[a].trim()==="Output:"&&a++,r=a-1;continue}t.push(e[r])}return t}function VB(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function Mm(e){return e.length>W1?e.slice(0,W1-3)+"...":e}function YB(e,t=""){let r=e.replace(/\x1b(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~]|\][^\x07]*\x07)/g,"").replace(/\r/g,"");for(const a of qB)r=r.replace(a,"");if(r.trim()){const a=GB(r.split(`
`)),s=[];for(const o of a)s.length===0&&!o.trim()||/^\[STRIX_\d+\]\$\s*/.test(o)||t&&o.trim()===t.trim()||t&&new RegExp(`^[\\$#>]\\s*${VB(t.trim())}\\s*$`).test(o)||s.push(o);for(;s.length>0&&/^\[STRIX_\d+\]\$\s*/.test(s[s.length-1]);)s.pop();r=s.join(`
`)}return r.trim()}function XB(e){const t=e.split(`
`);if(t.length<=$B)return t.map(Mm).join(`
`):e;let h;try{h=t?Ln.highlight(f,{language:t,ignoreIllegals:!0}).value:Ln.highlightAuto(f).value}catch{h=Ln.highlightAuto(f).value}return g.jsxs("div",{children:[g.jsx("pre",{className:`font-mono text-[12px] leading-relaxed px-0 py-1 mt-1 whitespace-pre-wrap break-all ${a?s?"overflow-auto max-h-[1200px]":"overflow-hidden":"overflow-auto max-h-[400px]"} ${r}`,children:g.jsx("code",{dangerouslySetInnerHTML:{__html:h}})}),d&&g.jsx("button",{onClick:()=>o(!s),className:"text-xs text-[#555] hover:text-[#888] mt-0.5",children:s?"Show less":"Show more"})]})}const FB=50,W1=200,J1=25,e_=24,GB=[/\n?\[Command still running after [\d.]+s - showing output so far\.?\s*(?:Use C-c to interrupt if needed\.)?\]/g,/^\[Below is the output of the previous command\.\]\n?/gm,/^No command is currently running\. Cannot send input\.$/gm,/^A command is already running\. Use is_input=true to send input to it, or interrupt it first \(e\.g\., with C-c\)\.$/gm],VB=/^Chunk ID: [0-9a-f]+\s*$/,YB=[/^Wall time: [\d.]+ seconds\s*$/,/^Process exited with code -?\d+\s*$/,/^Process running with session ID \d+\s*$/,/^Original token count: \d+\s*$/];function XB(e){const t=[];for(let r=0;r<e.length;r++){if(VB.test(e[r])){let a=r+1;for(;a<e.length&&YB.some(s=>s.test(e[a]));)a++;a<e.length&&e[a].trim()==="Output:"&&a++,r=a-1;continue}t.push(e[r])}return t}function KB(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function Mm(e){return e.length>W1?e.slice(0,W1-3)+"...":e}function ZB(e,t=""){let r=e.replace(/\x1b(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~]|\][^\x07]*\x07)/g,"").replace(/\r/g,"");for(const a of GB)r=r.replace(a,"");if(r.trim()){const a=XB(r.split(`
`)),s=[];for(const o of a)s.length===0&&!o.trim()||/^\[STRIX_\d+\]\$\s*/.test(o)||t&&o.trim()===t.trim()||t&&new RegExp(`^[\\$#>]\\s*${KB(t.trim())}\\s*$`).test(o)||s.push(o);for(;s.length>0&&/^\[STRIX_\d+\]\$\s*/.test(s[s.length-1]);)s.pop();r=s.join(`
`)}return r.trim()}function QB(e){const t=e.split(`
`);if(t.length<=FB)return t.map(Mm).join(`
`);const r=t.length-J1-e_;return[...t.slice(0,J1).map(Mm),`... ${r} lines truncated ...`,...t.slice(-e_).map(Mm)].join(`
`)}function KB({toolName:e,args:t,result:r}){const a=e==="write_stdin",s=a?t.chars??t.input??"":t.command??t.cmd??"",o=r;let c=null,d=null,f=null;if(o&&typeof o=="object"){c=typeof o.content=="string"?o.content:null,d=typeof o.error=="string"?o.error:null,f=typeof o.exit_code=="number"?o.exit_code:null;const m=typeof o.status=="string"?o.status:"";(m==="running"||m==="command still running")&&(c=null)}else typeof o=="string"&&(c=o);const h=c?XB(YB(c,s)):null;return g.jsxs("div",{children:[g.jsx("span",{className:"text-emerald-400/80 font-semibold text-sm",children:a?"Terminal input":"Terminal"}),s&&g.jsx(cg,{code:s,language:"bash",collapsible:!0}),d&&g.jsx(wi,{className:"text-red-400/70",children:d}),h&&g.jsx(wi,{className:"text-[#666]",children:h}),f!=null&&f!==0&&g.jsxs("div",{className:"font-mono text-[13px] text-red-400/70 mt-0.5",children:["exit code ",f]})]})}const t_={back:"going back in browser history",forward:"going forward in browser history",scroll_down:"scrolling down",scroll_up:"scrolling up",refresh:"refreshing",close_tab:"closing tab",switch_tab:"switching tab",list_tabs:"listing tabs",view_source:"viewing page source",get_console_logs:"getting console logs",screenshot:"taking screenshot",wait:"waiting...",close:"closing"},n_={click:"clicking",double_click:"double clicking",hover:"hovering"};function Om({prefix:e,url:t,suffix:r}){return g.jsxs("span",{className:"text-[#888] text-[13px]",children:[e,t&&g.jsx("a",{href:t,target:"_blank",rel:"noopener noreferrer",className:"text-cyan-400/80 hover:underline",children:t}),r]})}function ZB(e){const t=e.action??"",r=e.url??void 0;if(t in t_)return t_[t];if(t==="launch")return r?g.jsx(Om,{prefix:"launching ",url:r}):"launching";if(t==="goto"||t==="navigate")return g.jsx(Om,{prefix:"navigating to ",url:r});if(t==="new_tab")return g.jsx(Om,{prefix:"opening tab ",url:r});if(t in n_)return n_[t];if(t==="type")return`typing "${(e.text??"").slice(0,40)}"`;if(t==="press_key"||t==="key_press")return`pressing key ${e.key??""}`;if(t==="save_pdf"||t==="save_as_pdf"){const a=e.file_path??"";return`saving PDF${a?` to ${a}`:""}`}return t==="execute_js"?"executing javascript":t||"browser action"}function QB({args:e}){const r=(e.action??"")==="execute_js"?e.js_code??e.code??"":"",a=ZB(e);return g.jsxs("div",{children:[g.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[g.jsx("span",{className:"text-blue-400/80 font-semibold text-sm shrink-0",children:"Browser"}),g.jsx("span",{className:"min-w-0 truncate text-[#888] text-[13px]",children:a})]}),r&&g.jsx(cg,{code:r,language:"javascript",collapsible:!0})]})}function ug(e){return e.length>60?"..."+e.slice(-57):e}const fu=30;function WB({toolName:e,args:t}){const r=t.path??t.file_path??"",a=t.command??"",s=t.old_str??"",o=t.new_str??"",c=t.regex??"";let d;e==="list_files"?d="list":e==="search_files"?d="search":a==="view"?d="view":a==="create"?d="create":a==="str_replace"?d="edit":a==="undo_edit"?d="undo":a==="insert"?d="insert":d="file";const f=r?ug(r):"",h=c?` /${c}/`:"",m=s?s.split(`
`)}function WB({toolName:e,args:t,result:r}){const a=e==="write_stdin",s=a?t.chars??t.input??"":t.command??t.cmd??"",o=r;let c=null,d=null,f=null;if(o&&typeof o=="object"){c=typeof o.content=="string"?o.content:null,d=typeof o.error=="string"?o.error:null,f=typeof o.exit_code=="number"?o.exit_code:null;const m=typeof o.status=="string"?o.status:"";(m==="running"||m==="command still running")&&(c=null)}else typeof o=="string"&&(c=o);const h=c?QB(ZB(c,s)):null;return g.jsxs("div",{children:[g.jsx("span",{className:"text-emerald-400/80 font-semibold text-sm",children:a?"Terminal input":"Terminal"}),s&&g.jsx(cg,{code:s,language:"bash",collapsible:!0}),d&&g.jsx(wi,{className:"text-red-400/70",children:d}),h&&g.jsx(wi,{className:"text-[#666]",children:h}),f!=null&&f!==0&&g.jsxs("div",{className:"font-mono text-[13px] text-red-400/70 mt-0.5",children:["exit code ",f]})]})}const t_={back:"going back in browser history",forward:"going forward in browser history",scroll_down:"scrolling down",scroll_up:"scrolling up",refresh:"refreshing",close_tab:"closing tab",switch_tab:"switching tab",list_tabs:"listing tabs",view_source:"viewing page source",get_console_logs:"getting console logs",screenshot:"taking screenshot",wait:"waiting...",close:"closing"},n_={click:"clicking",double_click:"double clicking",hover:"hovering"};function Om({prefix:e,url:t,suffix:r}){return g.jsxs("span",{className:"text-[#888] text-[13px]",children:[e,t&&g.jsx("a",{href:t,target:"_blank",rel:"noopener noreferrer",className:"text-cyan-400/80 hover:underline",children:t}),r]})}function JB(e){const t=e.action??"",r=e.url??void 0;if(t in t_)return t_[t];if(t==="launch")return r?g.jsx(Om,{prefix:"launching ",url:r}):"launching";if(t==="goto"||t==="navigate")return g.jsx(Om,{prefix:"navigating to ",url:r});if(t==="new_tab")return g.jsx(Om,{prefix:"opening tab ",url:r});if(t in n_)return n_[t];if(t==="type")return`typing "${(e.text??"").slice(0,40)}"`;if(t==="press_key"||t==="key_press")return`pressing key ${e.key??""}`;if(t==="save_pdf"||t==="save_as_pdf"){const a=e.file_path??"";return`saving PDF${a?` to ${a}`:""}`}return t==="execute_js"?"executing javascript":t||"browser action"}function e7({args:e}){const r=(e.action??"")==="execute_js"?e.js_code??e.code??"":"",a=JB(e);return g.jsxs("div",{children:[g.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[g.jsx("span",{className:"text-blue-400/80 font-semibold text-sm shrink-0",children:"Browser"}),g.jsx("span",{className:"min-w-0 truncate text-[#888] text-[13px]",children:a})]}),r&&g.jsx(cg,{code:r,language:"javascript",collapsible:!0})]})}function ug(e){return e.length>60?"..."+e.slice(-57):e}const fu=30;function t7({toolName:e,args:t}){const r=t.path??t.file_path??"",a=t.command??"",s=t.old_str??"",o=t.new_str??"",c=t.regex??"";let d;e==="list_files"?d="list":e==="search_files"?d="search":a==="view"?d="view":a==="create"?d="create":a==="str_replace"?d="edit":a==="undo_edit"?d="undo":a==="insert"?d="insert":d="file";const f=r?ug(r):"",h=c?` /${c}/`:"",m=s?s.split(`
`):[],p=o?o.split(`
`):[],y=m.length+p.length,x=y>fu,_=x?Math.round(fu*(m.length/y)):m.length,N=x?fu-_:p.length;return g.jsxs("div",{children:[g.jsxs("div",{className:"flex items-baseline gap-2",children:[g.jsx("span",{className:"text-sky-400/80 font-semibold text-sm shrink-0",children:d}),f&&g.jsx("span",{className:"text-[#888] font-mono text-[13px] break-all",children:f})]}),h&&g.jsx("div",{className:"text-purple-400/60 font-mono text-[13px] break-all mt-0.5",children:h}),(s||o)&&g.jsxs("div",{className:"font-mono text-[13px] leading-relaxed mt-1.5",children:[m.slice(0,_).map((S,w)=>g.jsxs("div",{className:"text-red-400/60",children:[g.jsx("span",{className:"select-none text-red-400/30 mr-1",children:"-"}),S]},`o${w}`)),p.slice(0,N).map((S,w)=>g.jsxs("div",{className:"text-emerald-400/60",children:[g.jsx("span",{className:"select-none text-emerald-400/30 mr-1",children:"+"}),S]},`n${w}`)),x&&g.jsxs("div",{className:"text-[#444] mt-0.5",children:["... ",y-fu," more lines"]})]})]})}const hu=30,JB="*** Begin Patch",e7="*** End Patch",r_="*** Add File: ",i_="*** Update File: ",a_="*** Delete File: ",t7={add:"create",update:"edit",delete:"delete"};function n7(e){const t=e.patch;return typeof t=="string"?t:t&&typeof t=="object"&&typeof t.patch=="string"?t.patch:typeof e.input=="string"?e.input:""}function r7(e){const t=[];let r=null;const a=()=>{r&&t.push(r),r=null};for(const s of e.split(`
`))if(!(s===JB||s===e7))if(s.startsWith(r_))a(),r={kind:"add",path:s.slice(r_.length).trim(),oldLines:[],newLines:[]};else if(s.startsWith(i_))a(),r={kind:"update",path:s.slice(i_.length).trim(),oldLines:[],newLines:[]};else if(s.startsWith(a_))a(),r={kind:"delete",path:s.slice(a_.length).trim(),oldLines:[],newLines:[]};else if((r==null?void 0:r.kind)==="update"){if(s.startsWith("@@"))continue;s.startsWith("-")&&!s.startsWith("---")?r.oldLines.push(s.slice(1)):s.startsWith("+")&&!s.startsWith("+++")&&r.newLines.push(s.slice(1))}else(r==null?void 0:r.kind)==="add"&&(s.startsWith("+")?r.newLines.push(s.slice(1)):s.trim()&&r.newLines.push(s));return a(),t}function i7({op:e}){const t=t7[e.kind]??"file",r=e.oldLines.length+e.newLines.length,a=r>hu,s=a&&r>0?Math.round(hu*(e.oldLines.length/r)):e.oldLines.length,o=a?hu-s:e.newLines.length;return g.jsxs("div",{children:[g.jsxs("div",{className:"flex items-baseline gap-2",children:[g.jsx("span",{className:"text-sky-400/80 font-semibold text-sm shrink-0",children:t}),e.path&&g.jsx("span",{className:"text-[#888] font-mono text-[13px] break-all",children:ug(e.path)})]}),(e.oldLines.length>0||e.newLines.length>0)&&g.jsxs("div",{className:"font-mono text-[13px] leading-relaxed mt-1.5",children:[e.oldLines.slice(0,s).map((c,d)=>g.jsxs("div",{className:"text-red-400/60",children:[g.jsx("span",{className:"select-none text-red-400/30 mr-1",children:"-"}),c]},`o${d}`)),e.newLines.slice(0,o).map((c,d)=>g.jsxs("div",{className:"text-emerald-400/60",children:[g.jsx("span",{className:"select-none text-emerald-400/30 mr-1",children:"+"}),c]},`n${d}`)),a&&g.jsxs("div",{className:"text-[#444] mt-0.5",children:["... ",r-hu," more lines"]})]})]})}function a7({args:e,result:t,status:r}){const a=r7(n7(e));return a.length===0?g.jsxs("div",{children:[g.jsx("span",{className:"text-sky-400/80 font-semibold text-sm",children:"patch"}),r==="failed"&&typeof t=="string"&&t.trim()&&g.jsx("div",{className:"text-red-400/70 text-[13px] mt-1",children:t.trim()})]}):g.jsxs("div",{className:"space-y-2",children:[a.map((s,o)=>g.jsx(i7,{op:s},o)),r==="failed"&&typeof t=="string"&&t.trim()&&g.jsx("div",{className:"text-red-400/70 text-[13px]",children:t.trim()})]})}function s7({args:e,result:t}){const r=(e.path??"").trim(),a=t;let s=null;if(typeof a=="string"){const o=a.trim();o&&!o.toLowerCase().startsWith("data:image/")&&!o.startsWith("{")&&(s=o)}return g.jsxs("div",{children:[g.jsxs("div",{className:"flex items-baseline gap-2",children:[g.jsx("span",{className:"text-sky-400/80 font-semibold text-sm shrink-0",children:"view image"}),r&&g.jsx("span",{className:"text-[#888] font-mono text-[13px] break-all",children:ug(r)})]}),s&&g.jsx("div",{className:"text-red-400/70 text-[13px] mt-1",children:s})]})}const l7={critical:"text-red-400",high:"text-orange-400",medium:"text-yellow-400",low:"text-blue-400",info:"text-cyan-400"};function o7({args:e,result:t}){const r=e.title??"",a=e.description??"",s=e.impact??"",o=e.target??"",c=e.endpoint??"",d=e.method??"",f=e.technical_analysis??"",h=e.poc_description??"",m=e.poc_script_code??"",p=e.remediation_steps??"",y=e.cve??"",x=e.cwe??"",_=t,N=(_&&typeof _=="object"?_.severity:null)??e.severity??"medium",S=String(N).toLowerCase(),w=(_&&typeof _=="object"?_.cvss_score:null)??e.cvss??null,k=l7[S]??"text-yellow-400";return g.jsxs("div",{className:"space-y-3",children:[g.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[g.jsx("span",{className:`font-semibold text-sm ${k}`,children:S.toUpperCase()}),w!=null&&g.jsxs("span",{className:"text-[#888] text-[13px]",children:["CVSS ",w]}),y&&g.jsx("span",{className:"text-[#888] font-mono text-[13px]",children:y}),x&&g.jsx("span",{className:"text-[#888] font-mono text-[13px]",children:x})]}),r&&g.jsx("div",{className:"text-[15px] text-white/80 font-semibold",children:r}),(o||c)&&g.jsxs("div",{className:"text-[13px] text-[#888] font-mono",children:[o,c?` ${d} ${c}`:""]}),a&&g.jsx(Ln,{text:a,maxLines:20}),s&&g.jsxs("div",{children:[g.jsx("span",{className:"text-emerald-400/60 text-sm font-semibold",children:"Impact"}),g.jsx("div",{className:"mt-1",children:g.jsx(Ln,{text:s,maxLines:15})})]}),f&&g.jsxs("div",{children:[g.jsx("span",{className:"text-emerald-400/60 text-sm font-semibold",children:"Technical Analysis"}),g.jsx("div",{className:"mt-1",children:g.jsx(Ln,{text:f,maxLines:20})})]}),(h||m)&&g.jsxs("div",{children:[g.jsx("span",{className:"text-emerald-400/60 text-sm font-semibold",children:"Proof of Concept"}),h&&g.jsx("div",{className:"mt-1",children:g.jsx($s,{text:h})}),m&&g.jsx(iE,{children:m})]}),p&&g.jsxs("div",{children:[g.jsx("span",{className:"text-emerald-400/60 text-sm font-semibold",children:"Remediation"}),g.jsx("div",{className:"mt-1",children:g.jsx(Ln,{text:p,maxLines:15})})]})]})}const ZN=200,QN={GET:"text-emerald-400/80",POST:"text-blue-400/80",PUT:"text-yellow-400/80",PATCH:"text-orange-400/80",DELETE:"text-red-400/80"};function dg(e){return e<300?"text-emerald-400/80":e<400?"text-yellow-4 Line truncated
`),a=r.slice(0,t).map(s=>Xr(s,ZN-5)).join(`
`):[],y=m.length+p.length,x=y>fu,_=x?Math.round(fu*(m.length/y)):m.length,N=x?fu-_:p.length;return g.jsxs("div",{children:[g.jsxs("div",{className:"flex items-baseline gap-2",children:[g.jsx("span",{className:"text-sky-400/80 font-semibold text-sm shrink-0",children:d}),f&&g.jsx("span",{className:"text-[#888] font-mono text-[13px] break-all",children:f})]}),h&&g.jsx("div",{className:"text-purple-400/60 font-mono text-[13px] break-all mt-0.5",children:h}),(s||o)&&g.jsxs("div",{className:"font-mono text-[13px] leading-relaxed mt-1.5",children:[m.slice(0,_).map((S,w)=>g.jsxs("div",{className:"text-red-400/60",children:[g.jsx("span",{className:"select-none text-red-400/30 mr-1",children:"-"}),S]},`o${w}`)),p.slice(0,N).map((S,w)=>g.jsxs("div",{className:"text-emerald-400/60",children:[g.jsx("span",{className:"select-none text-emerald-400/30 mr-1",children:"+"}),S]},`n${w}`)),x&&g.jsxs("div",{className:"text-[#444] mt-0.5",children:["... ",y-fu," more lines"]})]})]})}const hu=30,n7="*** Begin Patch",r7="*** End Patch",r_="*** Add File: ",i_="*** Update File: ",a_="*** Delete File: ",i7={add:"create",update:"edit",delete:"delete"};function a7(e){const t=e.patch;return typeof t=="string"?t:t&&typeof t=="object"&&typeof t.patch=="string"?t.patch:typeof e.input=="string"?e.input:""}function s7(e){const t=[];let r=null;const a=()=>{r&&t.push(r),r=null};for(const s of e.split(`
`))if(!(s===n7||s===r7))if(s.startsWith(r_))a(),r={kind:"add",path:s.slice(r_.length).trim(),oldLines:[],newLines:[]};else if(s.startsWith(i_))a(),r={kind:"update",path:s.slice(i_.length).trim(),oldLines:[],newLines:[]};else if(s.startsWith(a_))a(),r={kind:"delete",path:s.slice(a_.length).trim(),oldLines:[],newLines:[]};else if((r==null?void 0:r.kind)==="update"){if(s.startsWith("@@"))continue;s.startsWith("-")&&!s.startsWith("---")?r.oldLines.push(s.slice(1)):s.startsWith("+")&&!s.startsWith("+++")&&r.newLines.push(s.slice(1))}else(r==null?void 0:r.kind)==="add"&&(s.startsWith("+")?r.newLines.push(s.slice(1)):s.trim()&&r.newLines.push(s));return a(),t}function l7({op:e}){const t=i7[e.kind]??"file",r=e.oldLines.length+e.newLines.length,a=r>hu,s=a&&r>0?Math.round(hu*(e.oldLines.length/r)):e.oldLines.length,o=a?hu-s:e.newLines.length;return g.jsxs("div",{children:[g.jsxs("div",{className:"flex items-baseline gap-2",children:[g.jsx("span",{className:"text-sky-400/80 font-semibold text-sm shrink-0",children:t}),e.path&&g.jsx("span",{className:"text-[#888] font-mono text-[13px] break-all",children:ug(e.path)})]}),(e.oldLines.length>0||e.newLines.length>0)&&g.jsxs("div",{className:"font-mono text-[13px] leading-relaxed mt-1.5",children:[e.oldLines.slice(0,s).map((c,d)=>g.jsxs("div",{className:"text-red-400/60",children:[g.jsx("span",{className:"select-none text-red-400/30 mr-1",children:"-"}),c]},`o${d}`)),e.newLines.slice(0,o).map((c,d)=>g.jsxs("div",{className:"text-emerald-400/60",children:[g.jsx("span",{className:"select-none text-emerald-400/30 mr-1",children:"+"}),c]},`n${d}`)),a&&g.jsxs("div",{className:"text-[#444] mt-0.5",children:["... ",r-hu," more lines"]})]})]})}function o7({args:e,result:t,status:r}){const a=s7(a7(e));return a.length===0?g.jsxs("div",{children:[g.jsx("span",{className:"text-sky-400/80 font-semibold text-sm",children:"patch"}),r==="failed"&&typeof t=="string"&&t.trim()&&g.jsx("div",{className:"text-red-400/70 text-[13px] mt-1",children:t.trim()})]}):g.jsxs("div",{className:"space-y-2",children:[a.map((s,o)=>g.jsx(l7,{op:s},o)),r==="failed"&&typeof t=="string"&&t.trim()&&g.jsx("div",{className:"text-red-400/70 text-[13px]",children:t.trim()})]})}function c7({args:e,result:t}){const r=(e.path??"").trim(),a=t;let s=null;if(typeof a=="string"){const o=a.trim();o&&!o.toLowerCase().startsWith("data:image/")&&!o.startsWith("{")&&(s=o)}return g.jsxs("div",{children:[g.jsxs("div",{className:"flex items-baseline gap-2",children:[g.jsx("span",{className:"text-sky-400/80 font-semibold text-sm shrink-0",children:"view image"}),r&&g.jsx("span",{className:"text-[#888] font-mono text-[13px] break-all",children:ug(r)})]}),s&&g.jsx("div",{className:"text-red-400/70 text-[13px] mt-1",children:s})]})}const u7={critical:"text-red-400",high:"text-orange-400",medium:"text-yellow-400",low:"text-blue-400",info:"text-cyan-400"};function d7({args:e,result:t}){const r=e.title??"",a=e.description??"",s=e.impact??"",o=e.target??"",c=e.endpoint??"",d=e.method??"",f=e.technical_analysis??"",h=e.poc_description??"",{language:m,code:p}=sE(e.poc_script_code??""),y=e.remediation_steps??"",x=e.cve??"",_=e.cwe??"",N=t,S=(N&&typeof N=="object"?N.severity:null)??e.severity??"medium",w=String(S).toLowerCase(),k=(N&&typeof N=="object"?N.cvss_score:null)??e.cvss??null,E=u7[w]??"text-yellow-400";return g.jsxs("div",{className:"space-y-3",children:[g.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[g.jsx("span",{className:`font-semibold text-sm ${E}`,children:w.toUpperCase()}),k!=null&&g.jsxs("span",{className:"text-[#888] text-[13px]",children:["CVSS ",k]}),x&&g.jsx("span",{className:"text-[#888] font-mono text-[13px]",children:x}),_&&g.jsx("span",{className:"text-[#888] font-mono text-[13px]",children:_})]}),r&&g.jsx("div",{className:"text-[15px] text-white/80 font-semibold",children:r}),(o||c)&&g.jsxs("div",{className:"text-[13px] text-[#888] font-mono",children:[o,c?` ${d} ${c}`:""]}),a&&g.jsx(zn,{text:a,maxLines:20}),s&&g.jsxs("div",{children:[g.jsx("span",{className:"text-emerald-400/60 text-sm font-semibold",children:"Impact"}),g.jsx("div",{className:"mt-1",children:g.jsx(zn,{text:s,maxLines:15})})]}),f&&g.jsxs("div",{children:[g.jsx("span",{className:"text-emerald-400/60 text-sm font-semibold",children:"Technical Analysis"}),g.jsx("div",{className:"mt-1",children:g.jsx(zn,{text:f,maxLines:20})})]}),(h||p)&&g.jsxs("div",{children:[g.jsx("span",{className:"text-emerald-400/60 text-sm font-semibold",children:"Proof of Concept"}),h&&g.jsx("div",{className:"mt-1",children:g.jsx($s,{text:h})}),p&&g.jsx(aE,{className:m?`language-${m}`:void 0,children:p})]}),y&&g.jsxs("div",{children:[g.jsx("span",{className:"text-emerald-400/60 text-sm font-semibold",children:"Remediation"}),g.jsx("div",{className:"mt-1",children:g.jsx(zn,{text:y,maxLines:15})})]})]})}const WN=200,JN={GET:"text-emerald-400/80",POST:"text-blue-400/80",PUT:"text-yellow-400/80",PATCH:"text-orange-400/80",DELETE:"text-red-400/80"};function dg(e Line truncated
`),a=r.slice(0,t).map(s=>Xr(s,WN-5)).join(`
`);return r.length>t?a+`
...`:a}function c7({args:e,result:t}){const r=e.httpql_filter??"",a=t,s=a?a.requests:null,o=Array.isArray(s)?s:[];return g.jsxs("div",{children:[g.jsxs("div",{className:"flex items-center gap-2",children:[g.jsx("span",{className:"text-purple-400/80 font-semibold text-sm",children:"listing requests"}),r&&g.jsx("span",{className:"text-[#888] text-[13px]",children:Xr(r,150)})]}),o.length>0&&g.jsxs("div",{className:"mt-1.5 font-mono text-[13px] space-y-0.5",children:[o.slice(0,20).map((c,d)=>{const f=(c.method??"GET").toUpperCase(),h=c.host??"",m=c.path??"",p=c.response,y=(p==null?void 0:p.statusCode)??null;return g.jsxs("div",{className:"flex gap-2",children:[g.jsx("span",{className:`w-10 shrink-0 font-bold ${QN[f]??"text-[#888]"}`,children:f}),g.jsx("span",{className:"text-[#777] truncate",children:Xr(h+m,180)}),y!=null&&g.jsx("span",{className:`ml-auto shrink-0 ${dg(y)}`,children:y})]},d)}),o.length>20&&g.jsxs("div",{className:"text-[#555]",children:["... +",o.length-20," more"]})]})]})}function u7({args:e,result:t}){const r=e.request_id,a=e.part??"request",s=e.search_pattern??"",o=t,c=o?o.matches:null,d=Array.isArray(c)?c:[],f=o?o.content??null:null,h=o?!!o.has_more:!1;return g.jsxs("div",{children:[g.jsxs("div",{className:"flex items-center gap-2",children:[g.jsxs("span",{className:"text-purple-400/80 font-semibold text-sm",children:[s?"searching":"viewing"," ",a]}),r!=null&&g.jsxs("span",{className:"text-[#888] text-[13px]",children:["#",r]}),s&&g.jsxs("span",{className:"text-[#666] font-mono text-[13px]",children:["/",Xr(s,100),"/"]})]}),d.length>0&&g.jsxs("div",{className:"mt-1.5 font-mono text-[13px] space-y-1",children:[d.slice(0,5).map((m,p)=>{const y=(m.before??"").replace(/\n/g," ").replace(/\r/g,"").slice(-100),x=(m.after??"").replace(/\n/g," ").replace(/\r/g,"").slice(0,100);return g.jsxs("div",{children:[y&&g.jsxs("span",{className:"text-[#555]",children:["...",y]}),g.jsx("span",{className:"text-amber-400/80 font-bold",children:m.match}),x&&g.jsxs("span",{className:"text-[#555]",children:[x,"..."]})]},p)}),d.length>5&&g.jsxs("div",{className:"text-[#555]",children:["... +",d.length-5," more matches"]})]}),f&&!d.length&&(()=>{const m=f.split(`
`),p=m.slice(0,15).map(x=>Xr(x,ZN)).join(`
...`:a}function f7({args:e,result:t}){const r=e.httpql_filter??"",a=t,s=a?a.requests:null,o=Array.isArray(s)?s:[];return g.jsxs("div",{children:[g.jsxs("div",{className:"flex items-center gap-2",children:[g.jsx("span",{className:"text-purple-400/80 font-semibold text-sm",children:"listing requests"}),r&&g.jsx("span",{className:"text-[#888] text-[13px]",children:Xr(r,150)})]}),o.length>0&&g.jsxs("div",{className:"mt-1.5 font-mono text-[13px] space-y-0.5",children:[o.slice(0,20).map((c,d)=>{const f=(c.method??"GET").toUpperCase(),h=c.host??"",m=c.path??"",p=c.response,y=(p==null?void 0:p.statusCode)??null;return g.jsxs("div",{className:"flex gap-2",children:[g.jsx("span",{className:`w-10 shrink-0 font-bold ${JN[f]??"text-[#888]"}`,children:f}),g.jsx("span",{className:"text-[#777] truncate",children:Xr(h+m,180)}),y!=null&&g.jsx("span",{className:`ml-auto shrink-0 ${dg(y)}`,children:y})]},d)}),o.length>20&&g.jsxs("div",{className:"text-[#555]",children:["... +",o.length-20," more"]})]})]})}function h7({args:e,result:t}){const r=e.request_id,a=e.part??"request",s=e.search_pattern??"",o=t,c=o?o.matches:null,d=Array.isArray(c)?c:[],f=o?o.content??null:null,h=o?!!o.has_more:!1;return g.jsxs("div",{children:[g.jsxs("div",{className:"flex items-center gap-2",children:[g.jsxs("span",{className:"text-purple-400/80 font-semibold text-sm",children:[s?"searching":"viewing"," ",a]}),r!=null&&g.jsxs("span",{className:"text-[#888] text-[13px]",children:["#",r]}),s&&g.jsxs("span",{className:"text-[#666] font-mono text-[13px]",children:["/",Xr(s,100),"/"]})]}),d.length>0&&g.jsxs("div",{className:"mt-1.5 font-mono text-[13px] space-y-1",children:[d.slice(0,5).map((m,p)=>{const y=(m.before??"").replace(/\n/g," ").replace(/\r/g,"").slice(-100),x=(m.after??"").replace(/\n/g," ").replace(/\r/g,"").slice(0,100);return g.jsxs("div",{children:[y&&g.jsxs("span",{className:"text-[#555]",children:["...",y]}),g.jsx("span",{className:"text-amber-400/80 font-bold",children:m.match}),x&&g.jsxs("span",{className:"text-[#555]",children:[x,"..."]})]},p)}),d.length>5&&g.jsxs("div",{className:"text-[#555]",children:["... +",d.length-5," more matches"]})]}),f&&!d.length&&(()=>{const m=f.split(`
`),p=m.slice(0,15).map(x=>Xr(x,WN)).join(`
`),y=h||m.length>15;return g.jsx(wi,{className:"text-[#666]",children:p+(y?`
... more content available`:"")})})()]})}function d7({args:e,result:t}){const r=(e.method??"GET").toUpperCase(),a=e.url??"",s=e.headers,o=e.body,c=typeof o=="string"?o:"",d=t,f=d?d.error??null:null,h=d?d.status_code??null:null,m=d?d.response_time_ms??null:null,p=d?d.body:null,y=typeof p=="string"?p:null;return g.jsxs("div",{children:[g.jsx("span",{className:"text-purple-400/80 font-semibold text-sm",children:"request"}),g.jsxs("div",{className:"mt-1.5 font-mono text-[13px] space-y-0.5",children:[g.jsxs("div",{children:[g.jsx("span",{className:"text-[#555] select-none mr-1",children:">>"}),g.jsx("span",{className:`font-bold ${QN[r]??"text-[#888]"}`,children:r}),g.jsx("span",{className:"text-[#888] ml-1 break-all",children:Xr(a,180)})]}),s&&typeof s=="object"&&Object.entries(s).slice(0,5).map(([x,_])=>g.jsxs("div",{className:"text-[#555] pl-5",children:[x,": ",mp(String(_),150)]},x))]}),c&&g.jsx(wi,{className:"text-[#888]",children:pp(c,4)}),f&&g.jsx("div",{className:"text-red-400/70 text-[13px] mt-1.5",children:mp(f,150)}),h!=null&&g.jsxs("div",{className:"font-mono text-[13px] mt-1.5",children:[g.jsx("span",{className:"text-[#555] select-none mr-1",children:"<<"}),g.jsx("span",{className:`font-bold ${dg(h)}`,children:h}),m!=null&&g.jsxs("span",{className:"text-[#555] ml-2",children:[m,"ms"]})]}),y&&g.jsx(wi,{className:"text-[#666]",children:pp(y,6)})]})}function f7({args:e,result:t}){const r=e.request_id,a=e.modifications,s=t,o=s?s.status_code??null:null,c=s?s.response_time_ms??null:null,d=s?s.body:null,f=typeof d=="string"?d:null;return g.jsxs("div",{children:[g.jsxs("div",{className:"flex items-center gap-2",children:[g.jsx("span",{className:"text-purple-400/80 font-semibold text-sm",children:"repeating request"}),r!=null&&g.jsxs("span",{className:"text-[#888] text-[13px]",children:["#",r]})]}),a&&typeof a=="object"&&Object.keys(a).length>0&&g.jsx("div",{className:"mt-1.5 font-mono text-[13px] space-y-0.5",children:Object.entries(a).slice(0,5).map(([h,m])=>g.jsxs("div",{children:[g.jsxs("span",{className:"text-orange-400/60",children:[h,":"]})," ",g.jsx("span",{className:"text-[#777]",children:mp(typeof m=="string"?m:JSON.stringify(m),150)})]},h))}),o!=null&&g.jsxs("div",{className:"font-mono text-[13px] mt-1.5",children:[g.jsx("span",{className:"text-[#555] select-none mr-1",children:"<<"}),g.jsx("span",{className:`font-bold ${dg(o)}`,children:o}),c!=null&&g.jsxs("span",{className:"text-[#555] ml-2",children:[c,"ms"]})]}),f&&g.jsx(wi,{className:"text-[#666]",children:pp(f,5)})]})}const h7={get:"getting",list:"listing",create:"creating",update:"updating",delete:"deleting"};function m7({args:e}){const t=e.action??"",r=e.scope_name??"",a=h7[t]??(t||"managing");return g.jsxs("div",{className:"flex items-center gap-2",children:[g.jsxs("span",{className:"text-purple-400/80 font-semibold text-sm",children:[a," proxy scope"]}),r&&g.jsx("span",{className:"text-[#888] text-[13px]",children:Xr(r,50)})]})}function p7({args:e}){const t=e.parent_id;return g.jsxs("div",{className:"flex items-center gap-2",children:[g.jsx("span",{className:"text-purple-400/80 font-semibold text-sm",children:"listing sitemap"}),t&&g.jsxs("span",{className:"text-[#888] text-[13px]",children:["under #",Xr(String(t),20)]})]})}function g7({args:e}){const t=e.entry_id;return g.jsxs("div",{className:"flex items-center gap-2",children:[g.jsx("span",{className:"text-purple-400/80 font-semibold text-sm",children:"viewing sitemap entry"}),t&&g.jsxs("span",{className:"text-[#888] text-[13px]",children:["#",Xr(String(t),20)]})]})}function b7(e){switch(e.toolName){case"list_requests":return g.jsx(c7,{...e});case"view_request":return g.jsx(u7,{...e});case"send_request":return g.jsx(d7,{...e});case"repeat_request":return g.jsx(f7,{...e});case"scope_rules":return g.jsx(m7,{...e});case"list_sitemap":return g.jsx(p7,{...e});case"view_sitemap_entry":return g.jsx(g7,{...e});default:return g.jsx("span",{className:"text-purple-400/80 font-semibold text-sm",children:e.toolName.replace(/_/g," ")})}}function x7({args:e}){const t=e.thought??e.content??"";return t?g.jsxs("div",{children:[g.jsx("span",{className:"text-purple-400/80 font-semibold text-sm",children:"Agent is thinking"}),g.jsx("div",{className:"mt-1.5 italic text-[#888]",children:g.jsx(Ln,{text:t,maxLines:20})})]}):null}function y7({toolName:e,args:t}){if(e==="create_agent"){const r=t.name??t.agent_name??"",a=t.task??"";return g.jsxs("div",{children:[g.jsxs("div",{className:"flex items-center gap-2",children:[g.jsx("span",{className:"text-cyan-400/80 font-semibold text-sm",children:"spawning"}),r&&g.jsx("span",{className:"text-cyan-400 font-semibold text-sm",children:r})]}),a&&g.jsx("div",{className:"mt-1.5",children:g.jsx(Ln,{text:a,maxLines:15})})]})}if(e==="agent_finish"){const r=t.result_summary??"",a=t.success,s=t.findings,o=Array.isArray(s)?s:void 0;return g.jsxs("div",{children:[g.jsx("span",{className:`font-semibold text-sm ${a===!1?"text-red-400/80":"text-emerald-400/80"}`,children:a===!1?"A Line truncated
`);if(t.length<=_7)return t.map(Rm).join(`
... more content available`:"")})})()]})}function m7({args:e,result:t}){const r=(e.method??"GET").toUpperCase(),a=e.url??"",s=e.headers,o=e.body,c=typeof o=="string"?o:"",d=t,f=d?d.error??null:null,h=d?d.status_code??null:null,m=d?d.response_time_ms??null:null,p=d?d.body:null,y=typeof p=="string"?p:null;return g.jsxs("div",{children:[g.jsx("span",{className:"text-purple-400/80 font-semibold text-sm",children:"request"}),g.jsxs("div",{className:"mt-1.5 font-mono text-[13px] space-y-0.5",children:[g.jsxs("div",{children:[g.jsx("span",{className:"text-[#555] select-none mr-1",children:">>"}),g.jsx("span",{className:`font-bold ${JN[r]??"text-[#888]"}`,children:r}),g.jsx("span",{className:"text-[#888] ml-1 break-all",children:Xr(a,180)})]}),s&&typeof s=="object"&&Object.entries(s).slice(0,5).map(([x,_])=>g.jsxs("div",{className:"text-[#555] pl-5",children:[x,": ",mp(String(_),150)]},x))]}),c&&g.jsx(wi,{className:"text-[#888]",children:pp(c,4)}),f&&g.jsx("div",{className:"text-red-400/70 text-[13px] mt-1.5",children:mp(f,150)}),h!=null&&g.jsxs("div",{className:"font-mono text-[13px] mt-1.5",children:[g.jsx("span",{className:"text-[#555] select-none mr-1",children:"<<"}),g.jsx("span",{className:`font-bold ${dg(h)}`,children:h}),m!=null&&g.jsxs("span",{className:"text-[#555] ml-2",children:[m,"ms"]})]}),y&&g.jsx(wi,{className:"text-[#666]",children:pp(y,6)})]})}function p7({args:e,result:t}){const r=e.request_id,a=e.modifications,s=t,o=s?s.status_code??null:null,c=s?s.response_time_ms??null:null,d=s?s.body:null,f=typeof d=="string"?d:null;return g.jsxs("div",{children:[g.jsxs("div",{className:"flex items-center gap-2",children:[g.jsx("span",{className:"text-purple-400/80 font-semibold text-sm",children:"repeating request"}),r!=null&&g.jsxs("span",{className:"text-[#888] text-[13px]",children:["#",r]})]}),a&&typeof a=="object"&&Object.keys(a).length>0&&g.jsx("div",{className:"mt-1.5 font-mono text-[13px] space-y-0.5",children:Object.entries(a).slice(0,5).map(([h,m])=>g.jsxs("div",{children:[g.jsxs("span",{className:"text-orange-400/60",children:[h,":"]})," ",g.jsx("span",{className:"text-[#777]",children:mp(typeof m=="string"?m:JSON.stringify(m),150)})]},h))}),o!=null&&g.jsxs("div",{className:"font-mono text-[13px] mt-1.5",children:[g.jsx("span",{className:"text-[#555] select-none mr-1",children:"<<"}),g.jsx("span",{className:`font-bold ${dg(o)}`,children:o}),c!=null&&g.jsxs("span",{className:"text-[#555] ml-2",children:[c,"ms"]})]}),f&&g.jsx(wi,{className:"text-[#666]",children:pp(f,5)})]})}const g7={get:"getting",list:"listing",create:"creating",update:"updating",delete:"deleting"};function b7({args:e}){const t=e.action??"",r=e.scope_name??"",a=g7[t]??(t||"managing");return g.jsxs("div",{className:"flex items-center gap-2",children:[g.jsxs("span",{className:"text-purple-400/80 font-semibold text-sm",children:[a," proxy scope"]}),r&&g.jsx("span",{className:"text-[#888] text-[13px]",children:Xr(r,50)})]})}function x7({args:e}){const t=e.parent_id;return g.jsxs("div",{className:"flex items-center gap-2",children:[g.jsx("span",{className:"text-purple-400/80 font-semibold text-sm",children:"listing sitemap"}),t&&g.jsxs("span",{className:"text-[#888] text-[13px]",children:["under #",Xr(String(t),20)]})]})}function y7({args:e}){const t=e.entry_id;return g.jsxs("div",{className:"flex items-center gap-2",children:[g.jsx("span",{className:"text-purple-400/80 font-semibold text-sm",children:"viewing sitemap entry"}),t&&g.jsxs("span",{className:"text-[#888] text-[13px]",children:["#",Xr(String(t),20)]})]})}function v7(e){switch(e.toolName){case"list_requests":return g.jsx(f7,{...e});case"view_request":return g.jsx(h7,{...e});case"send_request":return g.jsx(m7,{...e});case"repeat_request":return g.jsx(p7,{...e});case"scope_rules":return g.jsx(b7,{...e});case"list_sitemap":return g.jsx(x7,{...e});case"view_sitemap_entry":return g.jsx(y7,{...e});default:return g.jsx("span",{className:"text-purple-400/80 font-semibold text-sm",children:e.toolName.replace(/_/g," ")})}}function _7({args:e}){const t=e.thought??e.content??"";return t?g.jsxs("div",{children:[g.jsx("span",{className:"text-purple-400/80 font-semibold text-sm",children:"Agent is thinking"}),g.jsx("div",{className:"mt-1.5 italic text-[#888]",children:g.jsx(zn,{text:t,maxLines:20})})]}):null}function w7({toolName:e,args:t}){if(e==="create_agent"){const r=t.name??t.agent_name??"",a=t.task??"";return g.jsxs("div",{children:[g.jsxs("div",{className:"flex items-center gap-2",children:[g.jsx("span",{className:"text-cyan-400/80 font-semibold text-sm",children:"spawning"}),r&&g.jsx("span",{className:"text-cyan-400 font-semibold text-sm",children:r})]}),a&&g.jsx("div",{className:"mt-1.5",children:g.jsx(zn,{text:a,maxLines:15})})]})}if(e==="agent_finish"){const r=t.result_summary??"",a=t.success,s=t.findings,o=Array.isArray(s)?s:void 0;return g.jsxs("div",{children:[g.jsx("span",{className:`font-semibold text-sm ${a===!1?"text-red-400/80":"text-emerald-400/80"}`,children:a===!1?"A Line truncated
`);if(t.length<=N7)return t.map(Rm).join(`
`);const r=t.length-l_-o_;return[...t.slice(0,l_).map(Rm),`... ${r} lines truncated ...`,...t.slice(-o_).map(Rm)].join(`
`)}function T7({args:e,result:t}){const r=e.action??"",a=e.code??e.script??"",s=t;let o=null;s&&typeof s=="object"?o=typeof s.stdout=="string"?s.stdout:null:typeof s=="string"&&(o=s);const c=r==="new_session"?"new session":r==="close"?"close session":r==="list_sessions"?"list sessions":null,d=o?k7(S7(o)):null;return g.jsxs("div",{children:[g.jsxs("div",{className:"flex items-center gap-2",children:[g.jsx("span",{className:"text-yellow-400/80 font-semibold text-sm",children:"Python"}),c&&g.jsx("span",{className:"text-[#888] text-[13px]",children:c})]}),a&&g.jsx(cg,{code:a,language:"python",collapsible:!0}),d&&g.jsx(wi,{className:"text-[#666]",children:d})]})}function C7({args:e}){const t=e.targets,a=(Array.isArray(t)?t:[]).map(s=>typeof s=="object"&&s?s.original??null:null).filter(Boolean);return g.jsxs("div",{children:[g.jsxs("div",{className:"flex items-center gap-2",children:[g.jsx("span",{className:"text-emerald-400/80 font-semibold text-sm",children:"Starting penetration test"}),a.length===1&&g.jsxs("span",{className:"text-[#888] text-[13px]",children:["on ",a[0]]})]}),a.length>1&&g.jsx("div",{className:"mt-1.5 space-y-0.5",children:a.map((s,o)=>g.jsxs("div",{className:"text-[13px] text-[#888]",children:[g.jsx("span",{className:"text-[#555] mr-1",children:"•"}),s]},o))})]})}function A7({args:e}){const t=e.name??"Unknown Agent",r=e.task??"";return g.jsxs("div",{children:[g.jsxs("div",{className:"flex items-center gap-2",children:[g.jsx("span",{className:"text-[#888] text-[13px]",children:"subagent"}),g.jsx("span",{className:"text-purple-400 font-semibold text-sm",children:t})]}),r&&g.jsx("div",{className:"mt-1.5",children:g.jsx(Ln,{text:r,maxLines:15})})]})}function M7(e){return e.toolName==="subagent_start_info"?g.jsx(A7,{...e}):g.jsx(C7,{...e})}function O7({args:e}){const t=e.executive_summary??"",r=e.methodology??"",a=e.technical_analysis??"",s=e.recommendations??"";return g.jsxs("div",{className:"space-y-3",children:[g.jsx("span",{className:"text-emerald-400/80 font-semibold text-sm",children:"Penetration test completed"}),t&&g.jsxs("div",{children:[g.jsx("span",{className:"text-emerald-400/60 text-sm font-semibold",children:"Executive Summary"}),g.jsx("div",{className:"mt-1",children:g.jsx(Ln,{text:t,maxLines:25})})]}),r&&g.jsxs("div",{children:[g.jsx("span",{className:"text-emerald-400/60 text-sm font-semibold",children:"Methodology"}),g.jsx("div",{className:"mt-1",children:g.jsx(Ln,{text:r,maxLines:25})})]}),a&&g.jsxs("div",{children:[g.jsx("span",{className:"text-emerald-400/60 text-sm font-semibold",children:"Technical Analysis"}),g.jsx("div",{className:"mt-1",children:g.jsx(Ln,{text:a,maxLines:25})})]}),s&&g.jsxs("div",{children:[g.jsx("span",{className:"text-emerald-400/60 text-sm font-semibold",children:"Recommendations"}),g.jsx("div",{className:"mt-1",children:g.jsx(Ln,{text:s,maxLines:25})})]}),!t&&!r&&!a&&!s&&g.jsx("div",{className:"text-[#555] text-xs",children:"Generating final report..."})]})}function R7({toolName:e,args:t,result:r}){if(e==="create_note"){const a=t.title??"",s=t.content??"",o=t.category??"general";return g.jsxs("div",{children:[g.jsxs("div",{className:"flex items-center gap-2",children:[g.jsx("span",{className:"text-amber-400/80 font-semibold text-sm",children:"note"}),g.jsxs("span",{className:"text-[#555] text-[13px]",children:["(",o,")"]})]}),a&&g.jsx("div",{className:"mt-1.5 text-[#999] text-[13px]",children:a}),s&&g.jsx("div",{className:"mt-1",children:g.jsx($s,{text:s})})]})}if(e==="delete_note")return g.jsx("span",{className:"text-amber-400/80 font-semibold text-sm",children:"note removed"});if(e==="update_note"){const a=t.title??"",s=t.content??"";return g.jsxs("div",{children:[g.jsx("span",{className:"text-amber-400/80 font-semibold text-sm",children:"note updated"}),a&&g.jsx("div",{className:"mt-1.5 text-[#999] text-[13px]",children:a}),s&&g.jsx("div",{className:"mt-1",children:g.jsx($s,{text:s})})]})}if(e==="get_note"){const a=r,s=a&&typeof a=="object"&&a.success?a.note:void 0;return g.jsxs("div",{children:[g.jsx("span",{className:"text-amber-400/80 font-semibold text-sm",children:"note read"}),s&&g.jsxs(g.Fragment,{children:[g.jsxs("div",{className:"mt-1.5 text-[#999] text-[13px]",children:[s.title??"(untitled)",g.jsxs("span",{className:"text-[#555] ml-1",children:["(",s.category??"general",")"]})]}),s.content&&g.jsx("div",{className:"mt-1",children:g.jsx($s,{text:s.content})})]})]})}if(e==="list_notes"){const a=r;let s=[];if(a&&typeof a=="object"&&a.success){const o=a.notes;s=Array.isArray(o)?o:[]}return g.jsxs("div",{children:[g.jsx("span",{className:"text-amber-400/80 font-semibold text-sm",children:"notes"}),s.length>0?g.jsx("div",{className:"mt-1.5 space-y-0.5",children:s.map((o,c)=>g.jsxs("div",{className:"text-[13px]",children:[g.jsx("span",{className:"text-[#555] mr-1",children:"-"}),g.jsx("span",{className:"text-[#999]",children:o.title??"(untitled)"}),g.jsxs("span",{className:"text-[#555] ml-1",children:["(",o.category??"general",")"]}),o.content Line truncated
`)}function M7({args:e,result:t}){const r=e.action??"",a=e.code??e.script??"",s=t;let o=null;s&&typeof s=="object"?o=typeof s.stdout=="string"?s.stdout:null:typeof s=="string"&&(o=s);const c=r==="new_session"?"new session":r==="close"?"close session":r==="list_sessions"?"list sessions":null,d=o?A7(T7(o)):null;return g.jsxs("div",{children:[g.jsxs("div",{className:"flex items-center gap-2",children:[g.jsx("span",{className:"text-yellow-400/80 font-semibold text-sm",children:"Python"}),c&&g.jsx("span",{className:"text-[#888] text-[13px]",children:c})]}),a&&g.jsx(cg,{code:a,language:"python",collapsible:!0}),d&&g.jsx(wi,{className:"text-[#666]",children:d})]})}function O7({args:e}){const t=e.targets,a=(Array.isArray(t)?t:[]).map(s=>typeof s=="object"&&s?s.original??null:null).filter(Boolean);return g.jsxs("div",{children:[g.jsxs("div",{className:"flex items-center gap-2",children:[g.jsx("span",{className:"text-emerald-400/80 font-semibold text-sm",children:"Starting penetration test"}),a.length===1&&g.jsxs("span",{className:"text-[#888] text-[13px]",children:["on ",a[0]]})]}),a.length>1&&g.jsx("div",{className:"mt-1.5 space-y-0.5",children:a.map((s,o)=>g.jsxs("div",{className:"text-[13px] text-[#888]",children:[g.jsx("span",{className:"text-[#555] mr-1",children:"•"}),s]},o))})]})}function R7({args:e}){const t=e.name??"Unknown Agent",r=e.task??"";return g.jsxs("div",{children:[g.jsxs("div",{className:"flex items-center gap-2",children:[g.jsx("span",{className:"text-[#888] text-[13px]",children:"subagent"}),g.jsx("span",{className:"text-purple-400 font-semibold text-sm",children:t})]}),r&&g.jsx("div",{className:"mt-1.5",children:g.jsx(zn,{text:r,maxLines:15})})]})}function D7(e){return e.toolName==="subagent_start_info"?g.jsx(R7,{...e}):g.jsx(O7,{...e})}function j7({args:e}){const t=e.executive_summary??"",r=e.methodology??"",a=e.technical_analysis??"",s=e.recommendations??"";return g.jsxs("div",{className:"space-y-3",children:[g.jsx("span",{className:"text-emerald-400/80 font-semibold text-sm",children:"Penetration test completed"}),t&&g.jsxs("div",{children:[g.jsx("span",{className:"text-emerald-400/60 text-sm font-semibold",children:"Executive Summary"}),g.jsx("div",{className:"mt-1",children:g.jsx(zn,{text:t,maxLines:25})})]}),r&&g.jsxs("div",{children:[g.jsx("span",{className:"text-emerald-400/60 text-sm font-semibold",children:"Methodology"}),g.jsx("div",{className:"mt-1",children:g.jsx(zn,{text:r,maxLines:25})})]}),a&&g.jsxs("div",{children:[g.jsx("span",{className:"text-emerald-400/60 text-sm font-semibold",children:"Technical Analysis"}),g.jsx("div",{className:"mt-1",children:g.jsx(zn,{text:a,maxLines:25})})]}),s&&g.jsxs("div",{children:[g.jsx("span",{className:"text-emerald-400/60 text-sm font-semibold",children:"Recommendations"}),g.jsx("div",{className:"mt-1",children:g.jsx(zn,{text:s,maxLines:25})})]}),!t&&!r&&!a&&!s&&g.jsx("div",{className:"text-[#555] text-xs",children:"Generating final report..."})]})}function L7({toolName:e,args:t,result:r}){if(e==="create_note"){const a=t.title??"",s=t.content??"",o=t.category??"general";return g.jsxs("div",{children:[g.jsxs("div",{className:"flex items-center gap-2",children:[g.jsx("span",{className:"text-amber-400/80 font-semibold text-sm",children:"note"}),g.jsxs("span",{className:"text-[#555] text-[13px]",children:["(",o,")"]})]}),a&&g.jsx("div",{className:"mt-1.5 text-[#999] text-[13px]",children:a}),s&&g.jsx("div",{className:"mt-1",children:g.jsx($s,{text:s})})]})}if(e==="delete_note")return g.jsx("span",{className:"text-amber-400/80 font-semibold text-sm",children:"note removed"});if(e==="update_note"){const a=t.title??"",s=t.content??"";return g.jsxs("div",{children:[g.jsx("span",{className:"text-amber-400/80 font-semibold text-sm",children:"note updated"}),a&&g.jsx("div",{className:"mt-1.5 text-[#999] text-[13px]",children:a}),s&&g.jsx("div",{className:"mt-1",children:g.jsx($s,{text:s})})]})}if(e==="get_note"){const a=r,s=a&&typeof a=="object"&&a.success?a.note:void 0;return g.jsxs("div",{children:[g.jsx("span",{className:"text-amber-400/80 font-semibold text-sm",children:"note read"}),s&&g.jsxs(g.Fragment,{children:[g.jsxs("div",{className:"mt-1.5 text-[#999] text-[13px]",children:[s.title??"(untitled)",g.jsxs("span",{className:"text-[#555] ml-1",children:["(",s.category??"general",")"]})]}),s.content&&g.jsx("div",{className:"mt-1",children:g.jsx($s,{text:s.content})})]})]})}if(e==="list_notes"){const a=r;let s=[];if(a&&typeof a=="object"&&a.success){const o=a.notes;s=Array.isArray(o)?o:[]}return g.jsxs("div",{children:[g.jsx("span",{className:"text-amber-400/80 font-semibold text-sm",children:"notes"}),s.length>0?g.jsx("div",{className:"mt-1.5 space-y-0.5",children:s.map((o,c)=>g.jsxs("div",{className:"text-[13px]",children:[g.jsx("span",{className:"text-[#555] mr-1",children:"-"}),g.jsx("span",{className:"text-[#999]",children:o.title??"(untitled)"}),g.jsxs("span",{className:"text-[#555] ml-1",children:["(",o.category??"general",")"]}),o.content Line truncated
`)){const s=a.match(/^#{1,6}\s+(.*)$/);if(s){const o=s[1].trim().toLowerCase();if(o===r)continue;r=o}else a.trim()!==""&&(r=null);t.push(a)}return t.join(`
`)}function oH({onOpenEmail:e}){return g.jsx("button",{onClick:e,className:"group w-full cursor-pointer rounded-xl border border-emerald-500/25 bg-emerald-500/[0.06] p-4 text-left transition-colors hover:border-emerald-500/40",children:g.jsxs("div",{className:"flex items-center gap-3",children:[g.jsx("div",{className:"flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg",style:{border:"1px solid rgba(16,185,129,0.3)",background:"rgba(16,185,129,0.08)"},children:g.jsx(bp,{className:"h-4 w-4 text-emerald-400","aria-hidden":"true"})}),g.jsxs("div",{className:"min-w-0 flex-1",children:[g.jsx("p",{className:"text-sm font-semibold text-white",children:"Email an encrypted PDF report of this run"}),g.jsx("p",{className:"mt-0.5 text-xs text-[#888]",children:"Encrypted with a key only you can see, email verified with a one-time code before sending."})]}),g.jsx("span",{className:"flex-shrink-0 rounded-lg bg-white px-3 py-1.5 text-xs font-semibold text-black transition-opacity group-hover:opacity-90",children:"Export report to PDF"})]})})}function cH({summary:e,counts:t,total:r,reportMarkdown:a,raw:s,finished:o,onOpenEmail:c}){const d=[["Executive Summary",e.executiveSummary],["Technical Analysis",e.technicalAnalysis],["Methodology",e.methodology],["Recommendations",e.recommendations]].filter(([,f])=>!!f).map(([f,h])=>({title:f,content:sH(h)}));return g.jsxs("div",{className:"space-y-6",children:[g.jsx("div",{className:"animate-card-in",children:g.jsx(YU,{raw:s,durationSeconds:e.durationSeconds})}),r>0&&g.jsx("div",{className:"animate-card-in rounded-xl border border-[#222] bg-[rgba(255,255,255,0.02)] p-5",children:g.jsx(QD,{findings:{total:r,...t}})}),o&&g.jsx("div",{className:"animate-card-in",children:g.jsx(oH,{onOpenEmail:c})}),d.length>0?g.jsx("div",{className:"animate-card-in rounded-xl border border-[#222] bg-[rgba(255,255,255,0.02)] p-5 space-y-8",children:d.map(f=>g.jsx(oa,{title:f.title,content:f.content},f.title))}):a?g.jsx("div",{className:"animate-card-in rounded-xl border border-[#222] bg-[rgba(255,255,255,0.02)] p-5",children:g.jsx(oa,{content:lH(a)})}):r===0&&g.jsx("p",{className:"text-sm text-[#888]",children:"No summary available for this run yet."})]})}function zm({active:e,onClick:t,children:r}){return g.jsxs("button",{onClick:t,className:`cursor-pointer relative pb-2.5 text-sm font-semibold transition-colors ${e?"text-white":"text-[#666] hover:text-white"}`,children:[r,e&&g.jsx("span",{className:"absolute bottom-0 inset-x-0 h-0.5 bg-white rounded-full"})]})}function uH({run:e,canSteer:t}){const{agents:r,events:a}=e.transcript,s=ee.useMemo(()=>J7(r,a),[r,a]),[o,c]=ee.useState(null),d=o?r.find(h=>h.id===o)??null:null,f=t&&!e.finished;return g.jsxs("div",{className:"space-y-5",children:[g.jsxs("div",{className:"rounded-xl border border-[#222] bg-[rgba(255,255,255,0.02)] p-5",children:[g.jsxs("div",{className:"flex items-center gap-2",children:[g.jsx(Ao,{className:"w-4 h-4 text-[#888]","aria-hidden":"true"}),g.jsx("h2",{className:"text-sm font-semibold text-white",children:"Agent graph"}),g.jsxs("span",{className:"text-xs text-[#666]",children:[r.length," agent",r.length===1?"":"s"]})]}),g.jsx("p",{className:"mt-1 mb-4 text-xs text-[#666]",children:"Click an agent to open its full transcript."}),g.jsx("div",{className:"h-[480px] rounded-lg border border-[#1a1a1a] overflow-hidden",children:g.jsx(HB,{agents:s,selectedAgentId:o,onSelectAgent:h=>c(h),eventsLoaded:!0,eventsEmpty:s.size===0,scanCompleted:e.finished})})]}),f&&g.jsx(oS,{agents:r}),g.jsxs("div",{className:"rounded-xl border border-[#222] bg-[rgba(255,255,255,0.02)] p-5",children:[g.jsx("p",{className:"text-sm font-semibold text-white",children:"Run this pentest with more depth"}),g.jsx("p",{className:"mt-0.5 text-xs text-[#666]",children:"Re-run this pentest on managed infra in the cloud."}),g.jsx("div",{className:"mt-3 flex flex-wrap gap-2.5",children:g.jsx(fS,{label:"Re-run in Strix Pro with more depth",desc:"Run this pentest on managed infra with more depth.",slug:"live_scan",surface:"agents",icon:XT})})]}),g.jsx(vU,{open:d!==null,agent:d,events:a,steerable:f,onClose:()=>c(null)})]})}Ek.createRoot(document.getElementById("root")).render(g.jsx(ee.StrictMode,{children:g.jsx(eH,{})}));
`)}function dH({onOpenEmail:e}){return g.jsx("button",{onClick:e,className:"group w-full cursor-pointer rounded-xl border border-emerald-500/25 bg-emerald-500/[0.06] p-4 text-left transition-colors hover:border-emerald-500/40",children:g.jsxs("div",{className:"flex items-center gap-3",children:[g.jsx("div",{className:"flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg",style:{border:"1px solid rgba(16,185,129,0.3)",background:"rgba(16,185,129,0.08)"},children:g.jsx(bp,{className:"h-4 w-4 text-emerald-400","aria-hidden":"true"})}),g.jsxs("div",{className:"min-w-0 flex-1",children:[g.jsx("p",{className:"text-sm font-semibold text-white",children:"Email an encrypted PDF report of this run"}),g.jsx("p",{className:"mt-0.5 text-xs text-[#888]",children:"Encrypted with a key only you can see, email verified with a one-time code before sending."})]}),g.jsx("span",{className:"flex-shrink-0 rounded-lg bg-white px-3 py-1.5 text-xs font-semibold text-black transition-opacity group-hover:opacity-90",children:"Export report to PDF"})]})})}function fH({summary:e,counts:t,total:r,reportMarkdown:a,raw:s,finished:o,onOpenEmail:c}){const d=[["Executive Summary",e.executiveSummary],["Technical Analysis",e.technicalAnalysis],["Methodology",e.methodology],["Recommendations",e.recommendations]].filter(([,f])=>!!f).map(([f,h])=>({title:f,content:cH(h)}));return g.jsxs("div",{className:"space-y-6",children:[g.jsx("div",{className:"animate-card-in",children:g.jsx(ZU,{raw:s,durationSeconds:e.durationSeconds})}),r>0&&g.jsx("div",{className:"animate-card-in rounded-xl border border-[#222] bg-[rgba(255,255,255,0.02)] p-5",children:g.jsx(ej,{findings:{total:r,...t}})}),o&&g.jsx("div",{className:"animate-card-in",children:g.jsx(dH,{onOpenEmail:c})}),d.length>0?g.jsx("div",{className:"animate-card-in rounded-xl border border-[#222] bg-[rgba(255,255,255,0.02)] p-5 space-y-8",children:d.map(f=>g.jsx(oa,{title:f.title,content:f.content},f.title))}):a?g.jsx("div",{className:"animate-card-in rounded-xl border border-[#222] bg-[rgba(255,255,255,0.02)] p-5",children:g.jsx(oa,{content:uH(a)})}):r===0&&g.jsx("p",{className:"text-sm text-[#888]",children:"No summary available for this run yet."})]})}function zm({active:e,onClick:t,children:r}){return g.jsxs("button",{onClick:t,className:`cursor-pointer relative pb-2.5 text-sm font-semibold transition-colors ${e?"text-white":"text-[#666] hover:text-white"}`,children:[r,e&&g.jsx("span",{className:"absolute bottom-0 inset-x-0 h-0.5 bg-white rounded-full"})]})}function hH({run:e,canSteer:t}){const{agents:r,events:a}=e.transcript,s=ee.useMemo(()=>nU(r,a),[r,a]),[o,c]=ee.useState(null),d=o?r.find(h=>h.id===o)??null:null,f=t&&!e.finished;return g.jsxs("div",{className:"space-y-5",children:[g.jsxs("div",{className:"rounded-xl border border-[#222] bg-[rgba(255,255,255,0.02)] p-5",children:[g.jsxs("div",{className:"flex items-center gap-2",children:[g.jsx(Ao,{className:"w-4 h-4 text-[#888]","aria-hidden":"true"}),g.jsx("h2",{className:"text-sm font-semibold text-white",children:"Agent graph"}),g.jsxs("span",{className:"text-xs text-[#666]",children:[r.length," agent",r.length===1?"":"s"]})]}),g.jsx("p",{className:"mt-1 mb-4 text-xs text-[#666]",children:"Click an agent to open its full transcript."}),g.jsx("div",{className:"h-[480px] rounded-lg border border-[#1a1a1a] overflow-hidden",children:g.jsx(PB,{agents:s,selectedAgentId:o,onSelectAgent:h=>c(h),eventsLoaded:!0,eventsEmpty:s.size===0,scanCompleted:e.finished})})]}),f&&g.jsx(uS,{agents:r}),g.jsxs("div",{className:"rounded-xl border border-[#222] bg-[rgba(255,255,255,0.02)] p-5",children:[g.jsx("p",{className:"text-sm font-semibold text-white",children:"Run this pentest with more depth"}),g.jsx("p",{className:"mt-0.5 text-xs text-[#666]",children:"Re-run this pentest on managed infra in the cloud."}),g.jsx("div",{className:"mt-3 flex flex-wrap gap-2.5",children:g.jsx(mS,{label:"Re-run in Strix Pro with more depth",desc:"Run this pentest on managed infra with more depth.",slug:"live_scan",surface:"agents",icon:ZC})})]}),g.jsx(EU,{open:d!==null,agent:d,events:a,steerable:f,onClose:()=>c(null)})]})}Sk.createRoot(document.getElementById("root")).render(g.jsx(ee.StrictMode,{children:g.jsx(rH,{})}));
@@ -0,0 +1,10 @@
pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}/*!
Theme: GitHub Dark
Description: Dark theme as seen on github.com
Author: github.com
Maintainer: @Hirse
Updated: 2021-05-15
Outdated base version: https://github.com/primer/github-syntax-dark
Current colors taken from GitHub's CSS
*/.hljs{color:#c9d1d9;background:#0d1117}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#ff7b72}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#d2a8ff}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-variable,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id{color:#79c0ff}.hljs-regexp,.hljs-string,.hljs-meta .hljs-string{color:#a5d6ff}.hljs-built_in,.hljs-symbol{color:#ffa657}.hljs-comment,.hljs-code,.hljs-formula{color:#8b949e}.hljs-name,.hljs-quote,.hljs-selector-tag,.hljs-selector-pseudo{color:#7ee787}.hljs-subst{color:#c9d1d9}.hljs-section{color:#1f6feb;font-weight:700}.hljs-bullet{color:#f2cc60}.hljs-emphasis{color:#c9d1d9;font-style:italic}.hljs-strong{color:#c9d1d9;font-weight:700}.hljs-addition{color:#aff5b4;background-color:#033a16}.hljs-deletion{color:#ffdcd7;background-color:#67060c}.react-flow{direction:ltr;--xy-edge-stroke-default: #b1b1b7;--xy-edge-stroke-width-default: 1;--xy-edge-stroke-selected-default: #555;--xy-connectionline-stroke-default: #b1b1b7;--xy-connectionline-stroke-width-default: 1;--xy-attribution-background-color-default: rgba(255, 255, 255, .5);--xy-minimap-background-color-default: #fff;--xy-minimap-mask-background-color-default: rgba(240, 240, 240, .6);--xy-minimap-mask-stroke-color-default: transparent;--xy-minimap-mask-stroke-width-default: 1;--xy-minimap-node-background-color-default: #e2e2e2;--xy-minimap-node-stroke-color-default: transparent;--xy-minimap-node-stroke-width-default: 2;--xy-background-color-default: transparent;--xy-background-pattern-dots-color-default: #91919a;--xy-background-pattern-lines-color-default: #eee;--xy-background-pattern-cross-color-default: #e2e2e2;background-color:var(--xy-background-color, var(--xy-background-color-default));--xy-node-color-default: inherit;--xy-node-border-default: 1px solid #1a192b;--xy-node-background-color-default: #fff;--xy-node-group-background-color-default: rgba(240, 240, 240, .25);--xy-node-boxshadow-hover-default: 0 1px 4px 1px rgba(0, 0, 0, .08);--xy-node-boxshadow-selected-default: 0 0 0 .5px #1a192b;--xy-node-border-radius-default: 3px;--xy-handle-background-color-default: #1a192b;--xy-handle-border-color-default: #fff;--xy-selection-background-color-default: rgba(0, 89, 220, .08);--xy-selection-border-default: 1px dotted rgba(0, 89, 220, .8);--xy-controls-button-background-color-default: #fefefe;--xy-controls-button-background-color-hover-default: #f4f4f4;--xy-controls-button-color-default: inherit;--xy-controls-button-color-hover-default: inherit;--xy-controls-button-border-color-default: #eee;--xy-controls-box-shadow-default: 0 0 2px 1px rgba(0, 0, 0, .08);--xy-edge-label-background-color-default: #ffffff;--xy-edge-label-color-default: inherit;--xy-resize-background-color-default: #3367d9}.react-flow.dark{--xy-edge-stroke-default: #3e3e3e;--xy-edge-stroke-width-default: 1;--xy-edge-stroke-selected-default: #727272;--xy-connectionline-stroke-default: #b1b1b7;--xy-connectionline-stroke-width-default: 1;--xy-attribution-background-color-default: rgba(150, 150, 150, .25);--xy-minimap-background-color-default: #141414;--xy-minimap-mask-background-color-default: rgba(60, 60, 60, .6);--xy-minimap-mask-stroke-color-default: transparent;--xy-minimap-mask-stroke-width-default: 1;--xy-minimap-node-background-color-default: #2b2b2b;--xy-minimap-node-stroke-color-default: transparent;--xy-minimap-node-stroke-width-default: 2;--xy-background-color-default: #141414;--xy-background-pattern-dots-color-default: #555;--xy-background-pattern-lines-color-default: #333;--xy-background-pattern-cross-color-default: #333;--xy-node-color-default: #f8f8f8;--xy-node-border-default: 1px solid #3c3c3c;--xy-node-background-color-default: #1e1e1e;--xy-node-group-background-color-default: rgba(240, 240, 240, .25);--xy-node-boxshadow-hover-default: 0 1px 4px 1px rgba(255, 255, 255, .08);--xy-node-boxshadow-selected-default: 0 0 0 .5px #999;--xy-handle-background-color-default: #bebebe;--xy-handle-border-color-default: #1e1e1e;--xy-selection-background-color-default: rgba(200, 200, 220, .08);--xy-selection-border-default: 1px dotted rgba(200, 200, 220, .8);--xy-controls-button-background-color-default: #2b2b2b;--xy-controls-button-background-color-hover-default: #3e3e3e;--xy-controls-button-color-default: #f8f8f8;--xy-controls-button-color-hover-default: #fff;--xy-controls-button-border-color-default: #5b5b5b;--xy-controls-box-shadow-default: 0 0 2px 1px rgba(0, 0, 0, .08);--xy-edge-label-background-color-default: #141414;--xy-edge-label-color-default: #f8f8f8}.react-flow__background{background-color:var(--xy-background-color-props, var(--xy-background-color, var(--xy-background-color-default)));pointer-events:none;z-index:-1}.react-flow__container{position:absolute;width:100%;height:100%;top:0;left:0}.react-flow__pane{z-index:1;touch-action:none}.react-flow__panLine truncated
+2 -2
View File
@@ -6,8 +6,8 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="color-scheme" content="dark" />
<title>Strix Results</title>
<script type="module" crossorigin src="./assets/index-BNKUksp9.js"></script>
<link rel="stylesheet" crossorigin href="./assets/index-BdiSGmzb.css">
<script type="module" crossorigin src="./assets/index-Dd1cyttN.js"></script>
<link rel="stylesheet" crossorigin href="./assets/index-vV8wxCG6.css">
</head>
<body>
<div id="root"></div>
+64 -5
View File
@@ -3,12 +3,14 @@
from __future__ import annotations
import json
from types import SimpleNamespace
from typing import Any, cast
import pytest
from agents.tool import FunctionTool
from agents.tool import CustomTool, FunctionTool
from strix.agents import factory
from strix.config import load_settings
def _capturing_exec_tool(captured: dict[str, str]) -> FunctionTool:
@@ -32,10 +34,37 @@ async def test_wrap_exec_command_defaults_shell_to_bash() -> None:
result = await wrapped.on_invoke_tool(cast("Any", None), json.dumps({"cmd": "source /tmp/env"}))
assert result == "ok"
assert json.loads(captured["raw_input"]) == {
"cmd": "source /tmp/env",
"shell": "bash",
}
parsed = json.loads(captured["raw_input"])
assert parsed["cmd"] == "source /tmp/env"
assert parsed["shell"] == "bash"
expected_cap = load_settings().context.tool_output_max_tokens
assert parsed["max_output_tokens"] == expected_cap
@pytest.mark.asyncio
async def test_wrap_exec_command_preserves_smaller_explicit_output_cap() -> None:
captured: dict[str, str] = {}
wrapped = factory._wrap_exec_command(_capturing_exec_tool(captured))
await wrapped.on_invoke_tool(
cast("Any", None), json.dumps({"cmd": "echo hi", "max_output_tokens": 42})
)
assert json.loads(captured["raw_input"])["max_output_tokens"] == 42
@pytest.mark.asyncio
async def test_wrap_exec_command_clamps_oversized_explicit_output_cap() -> None:
captured: dict[str, str] = {}
wrapped = factory._wrap_exec_command(_capturing_exec_tool(captured))
ceiling = load_settings().context.tool_output_max_tokens
await wrapped.on_invoke_tool(
cast("Any", None),
json.dumps({"cmd": "echo hi", "max_output_tokens": ceiling * 100}),
)
assert json.loads(captured["raw_input"])["max_output_tokens"] == ceiling
@pytest.mark.asyncio
@@ -49,3 +78,33 @@ async def test_wrap_exec_command_preserves_explicit_shell(shell: str) -> None:
)
assert json.loads(captured["raw_input"])["shell"] == shell
@pytest.mark.asyncio
async def test_responses_filesystem_custom_tool_output_is_bounded() -> None:
async def invoke(_ctx: Any, _inp: str) -> str:
return "line\n" * 50_000
toolset = SimpleNamespace(
read_file=CustomTool(name="read_file", description="read", on_invoke_tool=invoke)
)
factory._configure_filesystem_tools(toolset, chat_completions=False)
assert isinstance(toolset.read_file, CustomTool)
result = await toolset.read_file.on_invoke_tool(cast("Any", None), "{}")
assert "truncated" in result
assert len(result) < len("line\n" * 50_000)
@pytest.mark.asyncio
async def test_chat_completions_filesystem_custom_tool_becomes_function_tool() -> None:
async def invoke(_ctx: Any, _inp: str) -> str:
return "ok"
toolset = SimpleNamespace(
read_file=CustomTool(name="read_file", description="read", on_invoke_tool=invoke)
)
factory._configure_filesystem_tools(toolset, chat_completions=True)
assert isinstance(toolset.read_file, FunctionTool)
+106
View File
@@ -0,0 +1,106 @@
"""Tests for the `strix auth` CLI: subcommand routing and provider naming."""
from __future__ import annotations
from typing import TYPE_CHECKING, Any
import pytest
from strix.config import codex
from strix.interface import auth_cli
if TYPE_CHECKING:
from pathlib import Path
@pytest.fixture(autouse=True)
def _tmp_store(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(codex, "AUTH_PATH", tmp_path / "home" / ".strix" / "subscription-auth.json")
def test_login_provider_is_chatgpt() -> None:
assert auth_cli.LOGIN_PROVIDER == "chatgpt"
assert codex.PROVIDER in auth_cli._ACCEPTED_PROVIDERS
assert "chatgpt" in auth_cli._ACCEPTED_PROVIDERS
def test_unknown_subcommand_returns_usage_error() -> None:
assert auth_cli.run_auth(["bogus"]) == 2
def test_help_returns_zero() -> None:
assert auth_cli.run_auth(["--help"]) == 0
def test_status_not_signed_in() -> None:
assert auth_cli.run_auth(["status"]) == 1
def test_login_rejects_unsupported_provider(monkeypatch: pytest.MonkeyPatch) -> None:
def _should_not_run(*_args: Any, **_kwargs: Any) -> dict[str, Any]:
msg = "OAuth flow must not start for an unsupported provider"
raise AssertionError(msg)
monkeypatch.setattr(auth_cli, "_run_oauth_flow", _should_not_run)
assert auth_cli.run_auth(["login", "gemini"]) == 2
def test_finish_requires_state_on_loopback(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(codex, "exchange_code", lambda *_: {"ok": True})
# Loopback (require_state=True): missing or mismatched state is rejected.
with pytest.raises(codex.CodexAuthError) as missing:
auth_cli._finish("code", None, "verifier", "expected", require_state=True)
assert missing.value.code == "state_mismatch"
with pytest.raises(codex.CodexAuthError) as mismatch:
auth_cli._finish("code", "wrong", "verifier", "expected", require_state=True)
assert mismatch.value.code == "state_mismatch"
# Matching state proceeds to the exchange.
assert auth_cli._finish("code", "expected", "verifier", "expected", require_state=True) == {
"ok": True
}
def test_finish_manual_paste_allows_absent_state(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(codex, "exchange_code", lambda *_: {"ok": True})
# Manual paste (require_state=False): a bare code with no state is accepted,
# but a present-and-wrong state is still rejected.
assert auth_cli._finish("code", None, "verifier", "expected", require_state=False) == {
"ok": True
}
with pytest.raises(codex.CodexAuthError):
auth_cli._finish("code", "wrong", "verifier", "expected", require_state=False)
def test_finish_rejects_missing_code() -> None:
with pytest.raises(codex.CodexAuthError) as exc:
auth_cli._finish(None, "expected", "verifier", "expected", require_state=True)
assert exc.value.code == "no_code"
def test_model_subcommand_removed() -> None:
assert auth_cli.run_auth(["model", "gpt-5.5"]) == 2
@pytest.mark.parametrize("provider", ["chatgpt", "codex", "ChatGPT"])
def test_login_accepts_provider_aliases(provider: str, monkeypatch: pytest.MonkeyPatch) -> None:
reached = {"flow": False}
def _fake_flow(*_args: Any, **_kwargs: Any) -> dict[str, Any]:
reached["flow"] = True
return {
"type": "oauth",
"provider": "codex",
"access": "a",
"refresh": "r",
"account_id": "acct",
"expires_at": 0,
}
monkeypatch.setattr(auth_cli, "_run_oauth_flow", _fake_flow)
monkeypatch.setattr(codex, "save_record", lambda _record: None)
assert auth_cli.run_auth(["login", provider]) == 0
assert reached["flow"] is True
+294
View File
@@ -0,0 +1,294 @@
"""Tests for ChatGPT (Codex) subscription auth: PKCE, token handling, store."""
from __future__ import annotations
import base64
import hashlib
import json
import time
from typing import TYPE_CHECKING, Any
import pytest
from strix.config import codex
if TYPE_CHECKING:
from pathlib import Path
def _fake_jwt(account_id: str) -> str:
def seg(obj: dict[str, Any]) -> str:
return base64.urlsafe_b64encode(json.dumps(obj).encode()).rstrip(b"=").decode()
header = seg({"alg": "none"})
payload = seg({"https://api.openai.com/auth": {"chatgpt_account_id": account_id}})
return f"{header}.{payload}.sig"
@pytest.fixture(autouse=True)
def _tmp_store(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> Path:
path = tmp_path / "home" / ".strix" / "subscription-auth.json"
monkeypatch.setattr(codex, "AUTH_PATH", path)
return path
def test_pkce_challenge_matches_verifier_and_is_unpadded() -> None:
verifier, challenge = codex.generate_pkce()
expected = (
base64.urlsafe_b64encode(hashlib.sha256(verifier.encode()).digest()).rstrip(b"=").decode()
)
assert challenge == expected
assert "=" not in verifier
assert "=" not in challenge
def test_authorize_url_carries_pkce_and_client() -> None:
url = codex.build_authorize_url("chal", "st8")
assert codex.AUTHORIZE_URL in url
assert "code_challenge=chal" in url
assert "code_challenge_method=S256" in url
assert f"client_id={codex.CLIENT_ID}" in url
assert "state=st8" in url
@pytest.mark.parametrize(
("value", "expected"),
[
("http://localhost:1455/auth/callback?code=AAA&state=BBB", ("AAA", "BBB")),
("AAA#BBB", ("AAA", "BBB")),
("code=AAA&state=BBB", ("AAA", "BBB")),
("AAA", ("AAA", None)),
("", (None, None)),
],
)
def test_parse_redirect_input(value: str, expected: tuple[str | None, str | None]) -> None:
assert codex.parse_redirect_input(value) == expected
@pytest.mark.parametrize(
("model", "expected"),
[
("chatgpt/gpt-5.4", "gpt-5.4"),
("ChatGPT/GPT-5.5", "GPT-5.5"),
(" chatgpt/gpt-5.4 ", "gpt-5.4"),
("openai/gpt-5.4", None), # metered API path
("anthropic/claude-opus-4-8", None),
("gpt-5.4", None),
("chatgpt/", None),
("", None),
(None, None),
],
)
def test_subscription_model(model: str | None, expected: str | None) -> None:
assert codex.subscription_model(model) == expected
def test_auth_mode() -> None:
assert codex.auth_mode("chatgpt/gpt-5.4") == "subscription"
assert codex.auth_mode("openai/gpt-5.4") == "api_key"
assert codex.auth_mode("anthropic/claude-opus-4-8") == "api_key"
assert codex.auth_mode(None) == "api_key"
def test_is_content_guardrail_error() -> None:
# The backend's real wording (from a live gpt-5.6-sol block).
raw = RuntimeError(
"This content was flagged for possible cybersecurity risk. If this seems "
"wrong, try rephrasing. To get authorized, join the Trusted Access for Cyber program."
)
assert codex.is_content_guardrail_error(raw) is True
# The already-typed error is recognized regardless of its message wording.
assert codex.is_content_guardrail_error(codex.CodexContentGuardrailError("gpt-5.6-sol")) is True
# Unrelated errors are not misclassified.
assert codex.is_content_guardrail_error(RuntimeError("rate limit exceeded")) is False
def test_content_guardrail_error_message() -> None:
err = codex.CodexContentGuardrailError("gpt-5.6-sol")
assert err.model == "gpt-5.6-sol"
assert "gpt-5.6-sol" in str(err)
assert "STRIX_LLM" in str(err)
def test_account_id_from_jwt() -> None:
assert codex._account_id_from_jwt(_fake_jwt("acct-42")) == "acct-42"
assert codex._account_id_from_jwt("not-a-jwt") is None
assert codex._account_id_from_jwt("") is None
def test_store_roundtrip_and_logout() -> None:
assert codex.read_record() is None
assert codex.is_authenticated() is False
codex.save_record(
{
"type": "oauth",
"provider": "codex",
"access": _fake_jwt("acct-42"),
"refresh": "r1",
"account_id": "acct-42",
"expires_at": time.time() + 3600,
}
)
record = codex.read_record()
assert record is not None
assert record["account_id"] == "acct-42"
assert codex.is_authenticated() is True
codex.logout()
assert codex.read_record() is None
codex.logout() # no-op when already gone
def test_read_record_rejects_incomplete_records() -> None:
codex.save_record({"type": "oauth", "access": "a"}) # missing refresh/account
assert codex.read_record() is None
assert codex.is_authenticated() is False
def test_get_valid_token_returns_stored_when_fresh(monkeypatch: pytest.MonkeyPatch) -> None:
def _boom(_payload: dict[str, str]) -> dict[str, Any]:
msg = "should not refresh a fresh token"
raise AssertionError(msg)
monkeypatch.setattr(codex, "_post_form", _boom)
codex.save_record(
{
"type": "oauth",
"provider": "codex",
"access": "access-fresh",
"refresh": "r1",
"account_id": "acct-42",
"expires_at": time.time() + 3600,
}
)
assert codex.get_valid_token() == ("access-fresh", "acct-42")
def test_get_valid_token_refreshes_and_persists_rotation(monkeypatch: pytest.MonkeyPatch) -> None:
calls = {"n": 0}
def _fake_post(payload: dict[str, str]) -> dict[str, Any]:
calls["n"] += 1
assert payload["grant_type"] == "refresh_token"
assert payload["refresh_token"] == "r1"
return {"access_token": _fake_jwt("acct-42"), "refresh_token": "r2", "expires_in": 3600}
monkeypatch.setattr(codex, "_post_form", _fake_post)
codex.save_record(
{
"type": "oauth",
"provider": "codex",
"access": "stale",
"refresh": "r1",
"account_id": "acct-42",
"expires_at": time.time() - 10, # already expired
}
)
_access, account_id = codex.get_valid_token()
assert calls["n"] == 1
assert account_id == "acct-42"
# Rotated refresh token was written back to the store.
record = codex.read_record()
assert record is not None
assert record["refresh"] == "r2"
def test_get_valid_token_uses_token_rotated_by_another_process(
monkeypatch: pytest.MonkeyPatch,
) -> None:
# Simulate a parallel Strix process rotating the token while we wait for the
# refresh guard: the pre-guard read sees the stale token, the in-guard read
# sees the winner's fresh one, so we must NOT exchange the now-dead refresh.
records = [
{
"type": "oauth",
"provider": "codex",
"access": "stale",
"refresh": "r1",
"account_id": "acct",
"expires_at": time.time() - 10,
},
{
"type": "oauth",
"provider": "codex",
"access": "fresh-from-other-process",
"refresh": "r2",
"account_id": "acct",
"expires_at": time.time() + 3600,
},
]
calls = {"n": 0}
def _fake_read() -> dict[str, Any]:
record = records[min(calls["n"], len(records) - 1)]
calls["n"] += 1
return record
def _boom(_payload: dict[str, str]) -> dict[str, Any]:
msg = "must not refresh a token another process already rotated"
raise AssertionError(msg)
monkeypatch.setattr(codex, "read_record", _fake_read)
monkeypatch.setattr(codex, "_post_form", _boom)
access, account_id = codex.get_valid_token()
assert access == "fresh-from-other-process"
assert account_id == "acct"
def _expired_record(refresh: str, access: str) -> dict[str, Any]:
return {
"type": "oauth",
"provider": "codex",
"access": access,
"refresh": refresh,
"account_id": "acct-42",
"expires_at": time.time() - 10,
}
def test_get_valid_token_recovers_when_refresh_loses_race(
monkeypatch: pytest.MonkeyPatch,
) -> None:
# Lock failed open: our in-guard read still saw the stale token, so we tried to
# refresh and lost the race (invalid_grant). By then a peer has saved a fresh
# token — recover from it instead of failing the scan on the dead one.
codex.save_record(_expired_record("r1", "stale"))
def _fake_post(_payload: dict[str, str]) -> dict[str, Any]:
codex.save_record(
{
"type": "oauth",
"provider": "codex",
"access": "fresh-from-peer",
"refresh": "r2",
"account_id": "acct-42",
"expires_at": time.time() + 3600,
}
)
raise codex.CodexAuthError("token_http_error", "HTTP 400: invalid_grant")
monkeypatch.setattr(codex, "_post_form", _fake_post)
assert codex.get_valid_token() == ("fresh-from-peer", "acct-42")
def test_get_valid_token_reraises_refresh_error_without_rotation(
monkeypatch: pytest.MonkeyPatch,
) -> None:
# Refresh fails and no peer rotated the token: surface the error, don't mask it.
codex.save_record(_expired_record("r1", "stale"))
def _fake_post(_payload: dict[str, str]) -> dict[str, Any]:
raise codex.CodexAuthError("token_http_error", "HTTP 400: invalid_grant")
monkeypatch.setattr(codex, "_post_form", _fake_post)
with pytest.raises(codex.CodexAuthError):
codex.get_valid_token()
def test_get_valid_token_raises_when_not_signed_in() -> None:
with pytest.raises(codex.CodexAuthError) as exc:
codex.get_valid_token()
assert exc.value.code == "not_authenticated"
+225
View File
@@ -0,0 +1,225 @@
"""Regression test for the ChatGPT Codex backend's streaming requirement.
The backend rejects non-streamed requests with ``{"detail": "Stream must be set
to true"}``. ``_CodexResponsesModel`` must therefore issue a streamed request
even from the non-streaming ``get_response`` path and aggregate the events into
a single response. A local server that mimics that behaviour proves the wrapper
works where the stock responses model would fail.
"""
from __future__ import annotations
import json
import threading
from http.server import BaseHTTPRequestHandler, HTTPServer
from typing import TYPE_CHECKING, Any
import pytest
from agents.model_settings import ModelSettings
from agents.models.interface import ModelTracing
from agents.models.openai_responses import OpenAIResponsesModel
from openai import AsyncOpenAI, BadRequestError
from openai.types.responses import ResponseOutputMessage, ResponseOutputText
from strix.config import codex
from strix.config.models import _CodexResponsesModel
if TYPE_CHECKING:
from collections.abc import AsyncIterator, Iterator
def _response_payload() -> dict[str, Any]:
return {
"id": "resp_1",
"object": "response",
"created_at": 0,
"status": "completed",
"model": "gpt-5.5",
"output": [
{
"type": "message",
"id": "m1",
"status": "completed",
"role": "assistant",
"content": [{"type": "output_text", "text": "OK", "annotations": []}],
}
],
"usage": {
"input_tokens": 1,
"output_tokens": 1,
"total_tokens": 2,
"input_tokens_details": {"cached_tokens": 0},
"output_tokens_details": {"reasoning_tokens": 0},
},
"parallel_tool_calls": False,
"tool_choice": "auto",
"tools": [],
"metadata": {},
"temperature": 1.0,
"top_p": 1.0,
"error": None,
"incomplete_details": None,
"instructions": None,
"max_output_tokens": None,
}
_CAPTURED: dict[str, Any] = {}
class _Handler(BaseHTTPRequestHandler):
def log_message(self, *args: Any) -> None:
pass
def do_POST(self) -> None:
length = int(self.headers.get("Content-Length", 0))
body = json.loads(self.rfile.read(length) or b"{}")
_CAPTURED.clear()
_CAPTURED.update(body)
if not body.get("stream"):
payload = json.dumps({"detail": "Stream must be set to true"}).encode()
self.send_response(400)
self.send_header("Content-Type", "application/json")
self.send_header("Content-Length", str(len(payload)))
self.end_headers()
self.wfile.write(payload)
return
event = {
"type": "response.completed",
"sequence_number": 0,
"response": _response_payload(),
}
frame = f"event: response.completed\ndata: {json.dumps(event)}\n\n".encode()
self.send_response(200)
self.send_header("Content-Type", "text/event-stream")
self.end_headers()
self.wfile.write(frame)
@pytest.fixture
def backend_url() -> Iterator[str]:
server = HTTPServer(("127.0.0.1", 0), _Handler)
thread = threading.Thread(target=server.serve_forever, daemon=True)
thread.start()
try:
yield f"http://127.0.0.1:{server.server_address[1]}/backend-api/codex"
finally:
server.shutdown()
server.server_close()
def _client(base_url: str) -> AsyncOpenAI:
return AsyncOpenAI(api_key="tok", base_url=base_url)
def _call_kwargs() -> dict[str, Any]:
return {
"system_instructions": "s",
"input": "hi",
"model_settings": ModelSettings(
store=False, response_include=["reasoning.encrypted_content"]
),
"tools": [],
"output_schema": None,
"handoffs": [],
"tracing": ModelTracing.DISABLED,
"previous_response_id": None,
"conversation_id": None,
"prompt": None,
}
@pytest.mark.asyncio
async def test_stock_model_fails_on_non_streamed_backend(backend_url: str) -> None:
model = OpenAIResponsesModel(model="gpt-5.5", openai_client=_client(backend_url))
with pytest.raises(BadRequestError, match="Stream must be set to true"):
await model.get_response(**_call_kwargs())
@pytest.mark.asyncio
async def test_codex_model_streams_and_aggregates(backend_url: str) -> None:
model = _CodexResponsesModel(model="gpt-5.5", openai_client=_client(backend_url))
response = await model.get_response(**_call_kwargs())
message = response.output[0]
assert isinstance(message, ResponseOutputMessage)
text = message.content[0]
assert isinstance(text, ResponseOutputText)
assert text.text == "OK"
assert response.usage.total_tokens == 2
class _TrackingStream:
"""An async iterator that yields, then raises, and records if it was closed."""
def __init__(self, events: list[Any], error: Exception | None) -> None:
self._events = iter(events)
self._error = error
self.closed = False
def __aiter__(self) -> _TrackingStream:
return self
async def __anext__(self) -> Any:
try:
return next(self._events)
except StopIteration:
if self._error is not None:
raise self._error from None
raise StopAsyncIteration from None
async def aclose(self) -> None:
self.closed = True
async def _drain(gen: AsyncIterator[Any]) -> list[Any]:
return [event async for event in gen]
@pytest.mark.asyncio
async def test_guarded_converts_guardrail_error() -> None:
# A mid-stream backend rejection becomes a typed, model-tagged error.
model = _CodexResponsesModel(model="gpt-5.6-sol", openai_client=_client("http://x/backend-api"))
guardrail = RuntimeError("This content was flagged for possible cybersecurity risk.")
stream = _TrackingStream(["a", "b"], guardrail)
with pytest.raises(codex.CodexContentGuardrailError) as exc_info:
await _drain(model._guarded(stream))
assert exc_info.value.model == "gpt-5.6-sol"
assert stream.closed is True # underlying stream is released
@pytest.mark.asyncio
async def test_guarded_passes_through_other_errors() -> None:
# A non-guardrail error propagates unchanged (still not swallowed).
model = _CodexResponsesModel(model="gpt-5.5", openai_client=_client("http://x/backend-api"))
boom = RuntimeError("some unrelated failure")
stream = _TrackingStream(["a"], boom)
with pytest.raises(RuntimeError, match="some unrelated failure"):
await _drain(model._guarded(stream))
assert stream.closed is True
@pytest.mark.asyncio
async def test_guarded_yields_all_events_when_clean() -> None:
model = _CodexResponsesModel(model="gpt-5.4", openai_client=_client("http://x/backend-api"))
stream = _TrackingStream(["a", "b", "c"], None)
assert await _drain(model._guarded(stream)) == ["a", "b", "c"]
assert stream.closed is True
@pytest.mark.asyncio
async def test_codex_model_self_enforces_backend_requirements(backend_url: str) -> None:
# The caller passes ordinary settings; the model must impose the backend's
# requirements (stream, store=false, encrypted reasoning) and the configured
# reasoning effort itself.
model = _CodexResponsesModel(
model="gpt-5.4", openai_client=_client(backend_url), reasoning_effort="high"
)
kwargs = _call_kwargs()
kwargs["model_settings"] = ModelSettings() # nothing special from the caller
await model.get_response(**kwargs)
assert _CAPTURED["stream"] is True
assert _CAPTURED["store"] is False
assert _CAPTURED["include"] == ["reasoning.encrypted_content"]
assert _CAPTURED["reasoning"] == {"effort": "high"}
+11 -1
View File
@@ -6,10 +6,11 @@ import json
from typing import TYPE_CHECKING
import pytest
from pydantic import AliasChoices, Field
from pydantic import AliasChoices, Field, ValidationError
from pydantic.fields import FieldInfo
from strix.config import loader
from strix.config.settings import ContextSettings
if TYPE_CHECKING:
@@ -120,6 +121,15 @@ def test_read_json_overrides_uses_json_when_no_alias_in_environ(tmp_path: Path)
assert loader._read_json_overrides(path) == {"llm": {"api_key": "sk-file"}}
def test_tool_output_max_bytes_rejects_sub_notice_values() -> None:
with pytest.raises(ValidationError):
ContextSettings(STRIX_TOOL_OUTPUT_MAX_BYTES=64)
def test_tool_output_max_bytes_accepts_floor() -> None:
assert ContextSettings(STRIX_TOOL_OUTPUT_MAX_BYTES=1024).tool_output_max_bytes == 1024
# --------------------------------------------------------------------------- #
# _aliases_for
# --------------------------------------------------------------------------- #
+94
View File
@@ -0,0 +1,94 @@
"""Tests for the dedicated deduplication model configuration."""
from __future__ import annotations
import json
from typing import TYPE_CHECKING
from strix.config import loader
from strix.config.settings import DedupeSettings
from strix.report.dedupe import _dedupe_model_settings
if TYPE_CHECKING:
from pathlib import Path
import pytest
def test_dedupe_key_sent_per_call_not_via_global_env() -> None:
dedupe = DedupeSettings(STRIX_DEDUPE_MODEL="deepseek/cheap", DEDUPE_LLM_API_KEY="dedupe-key")
settings = _dedupe_model_settings(dedupe, "deepseek/cheap", 300)
# The key rides on the request, so a shared-provider main key can't clobber
# it (and vice versa) through the global provider env var.
assert (settings.extra_args or {})["api_key"] == "dedupe-key"
def test_dedupe_settings_omit_api_key_when_unset() -> None:
dedupe = DedupeSettings(STRIX_DEDUPE_MODEL="deepseek/cheap")
settings = _dedupe_model_settings(dedupe, "deepseek/cheap", 300)
assert "api_key" not in (settings.extra_args or {})
assert "api_base" not in (settings.extra_args or {})
def test_dedupe_endpoint_sent_per_call() -> None:
dedupe = DedupeSettings(
STRIX_DEDUPE_MODEL="openai/cheap",
DEDUPE_LLM_API_KEY="dedupe-key",
DEDUPE_LLM_API_BASE="https://dedupe.example/v1",
)
settings = _dedupe_model_settings(dedupe, "openai/cheap", 300)
# A distinct dedupe endpoint rides on the request instead of the
# process-wide base URL, so it can't clobber the main model's endpoint.
assert (settings.extra_args or {})["api_base"] == "https://dedupe.example/v1"
assert (settings.extra_args or {})["api_key"] == "dedupe-key"
def test_dedupe_defaults_are_empty() -> None:
settings = DedupeSettings()
assert settings.model is None
assert settings.reasoning_effort is None
assert settings.api_key is None
def test_dedupe_model_read_from_env(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setenv("STRIX_DEDUPE_MODEL", "deepseek/deepseek-v4-flash")
monkeypatch.setenv("STRIX_DEDUPE_REASONING_EFFORT", "low")
settings = DedupeSettings()
assert settings.model == "deepseek/deepseek-v4-flash"
assert settings.reasoning_effort == "low"
def test_config_file_loads_dedupe_model(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
for key in ("STRIX_LLM", "STRIX_DEDUPE_MODEL", "STRIX_DEDUPE_REASONING_EFFORT"):
monkeypatch.delenv(key, raising=False)
path = tmp_path / "config.json"
path.write_text(
json.dumps(
{
"env": {
"STRIX_LLM": "openai/root",
"STRIX_DEDUPE_MODEL": "deepseek/cheap",
"STRIX_DEDUPE_REASONING_EFFORT": "minimal",
}
}
),
encoding="utf-8",
)
loader._cached = None
loader._override = path
try:
settings = loader.load_settings()
finally:
loader._cached = None
loader._override = None
assert settings.dedupe.model == "deepseek/cheap"
assert settings.dedupe.reasoning_effort == "minimal"
# Main model stays independent of the dedupe override.
assert settings.llm.model == "openai/root"
+78
View File
@@ -0,0 +1,78 @@
"""Tests for stripping the markdown code fence off stored code fields."""
from __future__ import annotations
from pygments.lexers import BashLexer, PythonLexer
from strix.report.writer import (
guess_language_name,
parse_fenced_code,
resolve_lexer,
safe_fence,
)
from strix.viewer.report_pdf import _strip_code_fence
def test_parse_fenced_code_extracts_language_and_body() -> None:
language, code = parse_fenced_code("```python\nimport requests\nprint(1)\n```")
assert language == "python"
assert code == "import requests\nprint(1)"
def test_parse_fenced_code_uses_first_token_of_info_string() -> None:
language, code = parse_fenced_code("```python title=app.py\nx = 1\n```")
assert language == "python"
assert code == "x = 1"
def test_parse_fenced_code_handles_non_python_language() -> None:
language, code = parse_fenced_code("```http\nGET / HTTP/1.1\n```")
assert language == "http"
assert code == "GET / HTTP/1.1"
def test_parse_fenced_code_passes_through_unfenced() -> None:
language, code = parse_fenced_code("import requests\nprint(1)")
assert language is None
assert code == "import requests\nprint(1)"
def test_parse_fenced_code_fence_without_language() -> None:
language, code = parse_fenced_code("```\nplain\n```")
assert language is None
assert code == "plain"
def test_strip_code_fence_removes_fence() -> None:
assert _strip_code_fence("```python\nx = 1\n```") == "x = 1"
def test_strip_code_fence_passes_through_non_string_and_unfenced() -> None:
assert _strip_code_fence(None) is None
assert _strip_code_fence("x = 1") == "x = 1"
def test_resolve_lexer_honors_explicit_language() -> None:
assert isinstance(resolve_lexer("bash", "echo hi"), BashLexer)
def test_resolve_lexer_falls_back_to_python_when_unresolvable() -> None:
# Unknown language name and empty body -> nothing to auto-detect -> Python.
assert isinstance(resolve_lexer("not-a-language", ""), PythonLexer)
def test_guess_language_name_defaults_to_python_when_inconclusive() -> None:
assert guess_language_name("") == "python"
def test_parse_fenced_code_handles_crlf() -> None:
language, code = parse_fenced_code("```python\r\nx = 1\r\n```")
assert language == "python"
assert code == "x = 1"
def test_safe_fence_widens_past_embedded_backticks() -> None:
# A PoC body containing a ``` run must be wrapped in a longer fence so it
# can't terminate the block early.
assert safe_fence("plain code") == "```"
assert safe_fence("has ```\nfence inside") == "````"
+35
View File
@@ -106,3 +106,38 @@ def test_nested_symlinks_inside_linked_dir(tmp_path: Path) -> None:
assert (staged / "pkg" / "shared_link" / "conf.json").read_text() == "{}\n"
assert not (staged / "pkg" / "shared_link" / "escape").exists()
assert not (staged / "shared" / "escape").exists()
def test_staged_path_has_no_symlink_ancestor(tmp_path: Path, monkeypatch) -> None: # noqa: ANN001
"""The staging directory itself must never sit behind a symlink.
``tempfile.mkdtemp()`` honors ``$TMPDIR``, and on macOS the default
``$TMPDIR`` resolves through ``/var``, which is itself a symlink to
``/private/var``. ``LocalDir`` rejects any symlink component in its
source path, so returning the raw ``mkdtemp()`` result breaks every
local-dir upload on macOS whenever the source tree contains a symlink.
This reproduces that shape without depending on the host OS layout.
"""
repo = _make_repo(tmp_path)
(repo / "link.py").symlink_to(repo / "pkg" / "mod.py")
real_tmp_root = tmp_path / "real_tmp"
real_tmp_root.mkdir()
symlinked_tmp_root = tmp_path / "tmp_symlink"
symlinked_tmp_root.symlink_to(real_tmp_root)
def fake_mkdtemp(prefix: str = "") -> str:
real_dir = real_tmp_root / f"{prefix}fake"
real_dir.mkdir()
return str(symlinked_tmp_root / real_dir.name)
monkeypatch.setattr(
"strix.runtime.local_dir_staging.tempfile.mkdtemp", fake_mkdtemp
)
upload_path, staged = stage_symlink_safe_dir(repo)
assert staged is not None
assert upload_path == staged
for path in (staged, *staged.parents):
assert not path.is_symlink(), f"staged path has a symlink ancestor: {path}"
+17 -4
View File
@@ -13,12 +13,15 @@ import asyncio
from agents.retry import ModelRetryNormalizedError, RetryPolicyContext
from strix.config import codex
from strix.config.models import DEFAULT_MODEL_RETRY, _retry_statusless_provider_errors
def _context(normalized: ModelRetryNormalizedError) -> RetryPolicyContext:
def _context(
normalized: ModelRetryNormalizedError, error: Exception | None = None
) -> RetryPolicyContext:
return RetryPolicyContext(
error=RuntimeError("boom"),
error=error or RuntimeError("boom"),
attempt=1,
max_retries=5,
stream=True,
@@ -27,11 +30,11 @@ def _context(normalized: ModelRetryNormalizedError) -> RetryPolicyContext:
)
def _retries(normalized: ModelRetryNormalizedError) -> bool:
def _retries(normalized: ModelRetryNormalizedError, error: Exception | None = None) -> bool:
"""Evaluate the composed DEFAULT_MODEL_RETRY policy for a normalized error."""
policy = DEFAULT_MODEL_RETRY.policy
assert policy is not None
decision = asyncio.run(policy(_context(normalized)))
decision = asyncio.run(policy(_context(normalized, error)))
return bool(getattr(decision, "retry", decision))
@@ -63,6 +66,16 @@ def test_timeout_error_is_retried() -> None:
assert _retries(ModelRetryNormalizedError(is_network_error=True)) is True
def test_content_guardrail_error_is_not_retried() -> None:
# A guardrail block is status-less, so it would match the statusless policy;
# the guard must keep it from being retried (retrying never clears it).
guardrail = codex.CodexContentGuardrailError("gpt-5.6-sol")
assert _retries(ModelRetryNormalizedError(status_code=None), guardrail) is False
# A raw provider error carrying the backend's wording is excluded too.
raw = RuntimeError("This content was flagged for possible cybersecurity risk.")
assert _retries(ModelRetryNormalizedError(status_code=None), raw) is False
def test_policy_helper_matches_statusless_only() -> None:
assert _retry_statusless_provider_errors(_context(ModelRetryNormalizedError())) is True
assert (
+4
View File
@@ -42,9 +42,11 @@ def test_recommended_models_are_matched_case_insensitively() -> None:
"model_name",
[
"gpt-5.5",
"chatgpt/gpt-5.4",
"litellm/openai/gpt-5.4-pro",
"azure_ai/gpt-5.5-pro",
"bedrock_mantle/openai.gpt-5.5",
"anthropic/claude-opus-5",
"anthropic/claude-opus-4-8",
"anthropic.claude-opus-4-8",
"anthropic/claude-opus-4-7",
@@ -60,8 +62,10 @@ def test_recommended_models_are_matched_case_insensitively() -> None:
"deepseek/deepseek-reasoner",
"dashscope/qwen3-max-2026-01-23",
"qwen3.7-max",
"dashscope/qwen3.8-max",
"moonshot/kimi-k2.6",
"kimi-k2.7-code",
"moonshot/kimi-k3",
],
)
def test_frontier_model_families_are_accepted(model_name: str) -> None:
+60
View File
@@ -0,0 +1,60 @@
"""Tests for per-tool-output bounding."""
from __future__ import annotations
import re
from strix.tools.output_store import bound_text
def test_small_output_passes_through_unchanged() -> None:
text = "line 1\nline 2\nline 3"
assert bound_text(text, max_lines=100, max_bytes=10_000) == text
def test_line_limit_keeps_head_and_tail() -> None:
text = "\n".join(str(i) for i in range(1000))
bounded = bound_text(text, max_lines=10, max_bytes=1_000_000)
assert bounded.startswith("0\n1\n2\n3\n4")
assert bounded.rstrip().endswith("999")
assert "truncated" in bounded
assert len(bounded.splitlines()) < 30
def test_byte_limit_enforced_on_single_long_line() -> None:
text = "x" * 100_000
bounded = bound_text(text, max_lines=2_000, max_bytes=1_000)
assert "truncated" in bounded
assert len(bounded.encode("utf-8")) <= 1_000
def test_multibyte_characters_not_split() -> None:
text = "😀" * 50_000
bounded = bound_text(text, max_lines=2_000, max_bytes=1_000)
# Must remain valid UTF-8 (no mid-character cut).
assert bounded == bounded.encode("utf-8").decode("utf-8")
assert "truncated" in bounded
def test_notice_reports_dropped_counts() -> None:
text = "\n".join("y" * 10 for _ in range(500))
bounded = bound_text(text, max_lines=10, max_bytes=1_000_000)
assert "lines" in bounded
assert "bytes" in bounded
def test_dropped_line_count_accounts_for_byte_trimming() -> None:
# Tight byte budget drops whole lines from head/tail; the notice must count them.
text = "\n".join(f"line-{i}" for i in range(200))
bounded = bound_text(text, max_lines=20, max_bytes=40)
match = re.search(r"\[\.\.\. (\d+) lines", bounded)
assert match is not None, bounded
dropped = int(match.group(1))
kept = [ln for ln in bounded.splitlines() if ln and "truncated" not in ln]
assert dropped == 200 - len(kept)
assert dropped > 200 - 20
+5 -3
View File
@@ -119,9 +119,11 @@ def test_render_vulnerability_md_poc_code_cannot_break_out_of_fence() -> None:
injected = "curl x\n```\n\n## Injected Heading\n![x](https://evil.example/beacon.png)"
md = render_vulnerability_md(_sample_report(poc_script_code=injected))
lines = md.split("\n")
fence = next(ln for ln in lines[lines.index("## Proof of Concept") + 1 :] if ln.strip())
assert set(fence) == {"`"}
assert len(fence) >= 4 # wider than the payload's 3-backtick run
opening = next(ln for ln in lines[lines.index("## Proof of Concept") + 1 :] if ln.strip())
ticks = opening[: len(opening) - len(opening.lstrip("`"))]
assert len(ticks) >= 4 # wider than the payload's 3-backtick run
assert "`" not in opening.removeprefix(ticks) # backtick run + language tag only
assert f"\n{ticks}\n" in md # pure-backtick closing fence of the same width
assert injected in md # the payload survives verbatim, inside the fence
+2 -1
View File
@@ -46,7 +46,8 @@ def _patch_engine_scaffold(
reasoning_effort="high",
force_required_tool_choice=False,
timeout=300,
)
),
runtime=types.SimpleNamespace(max_context_images=3),
)
monkeypatch.setattr(runner, "load_settings", lambda: settings)
monkeypatch.setattr(runner, "configure_sdk_model_defaults", lambda _settings: None)
+172
View File
@@ -0,0 +1,172 @@
import hashlib
import io
import json
import platform
import time
from pathlib import Path
import pytest
from rich.console import Console
from strix.interface import update_check
@pytest.fixture(autouse=True)
def _isolated_cache(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(update_check, "_CACHE_PATH", tmp_path / "update-check.json")
monkeypatch.setattr(update_check, "_background_thread", None)
monkeypatch.delenv("STRIX_NO_UPDATE_CHECK", raising=False)
for key in ("CI", "GITHUB_ACTIONS", "GITLAB_CI", "JENKINS_URL", "BUILDKITE", "CIRCLECI"):
monkeypatch.delenv(key, raising=False)
@pytest.mark.parametrize(
("latest", "current", "expected"),
[
("1.2.0", "1.1.0", True),
("1.1.0", "1.1.0", False),
("1.0.9", "1.1.0", False),
("2.0.0", "1.99.99", True),
("1.10.0", "1.9.0", True),
("v1.2.0", "1.1.0", True),
("not-a-version", "1.1.0", False),
("1.2.0", "unknown", False),
],
)
def test_is_newer(latest: str, current: str, expected: bool) -> None:
assert update_check._is_newer(latest, current) is expected
def test_get_available_update_from_cache(monkeypatch: pytest.MonkeyPatch) -> None:
update_check._CACHE_PATH.write_text(
json.dumps({"latest_version": "9.9.9", "checked_at": time.time()})
)
monkeypatch.setattr(update_check, "get_version", lambda: "1.0.0")
assert update_check.get_available_update() == "9.9.9"
def test_get_available_update_up_to_date(monkeypatch: pytest.MonkeyPatch) -> None:
update_check._CACHE_PATH.write_text(
json.dumps({"latest_version": "1.0.0", "checked_at": time.time()})
)
monkeypatch.setattr(update_check, "get_version", lambda: "1.0.0")
assert update_check.get_available_update() is None
def test_get_available_update_disabled_by_env(monkeypatch: pytest.MonkeyPatch) -> None:
update_check._CACHE_PATH.write_text(
json.dumps({"latest_version": "9.9.9", "checked_at": time.time()})
)
monkeypatch.setattr(update_check, "get_version", lambda: "1.0.0")
monkeypatch.setenv("STRIX_NO_UPDATE_CHECK", "1")
assert update_check.get_available_update() is None
def test_get_available_update_disabled_in_ci(monkeypatch: pytest.MonkeyPatch) -> None:
update_check._CACHE_PATH.write_text(
json.dumps({"latest_version": "9.9.9", "checked_at": time.time()})
)
monkeypatch.setattr(update_check, "get_version", lambda: "1.0.0")
monkeypatch.setenv("CI", "true")
assert update_check.get_available_update() is None
def test_get_available_update_corrupt_cache(monkeypatch: pytest.MonkeyPatch) -> None:
update_check._CACHE_PATH.write_text("{not json")
monkeypatch.setattr(update_check, "get_version", lambda: "1.0.0")
assert update_check.get_available_update() is None
def test_background_check_skipped_when_fresh(monkeypatch: pytest.MonkeyPatch) -> None:
update_check._CACHE_PATH.write_text(
json.dumps({"latest_version": "1.0.0", "checked_at": time.time()})
)
called = False
def fake_refresh() -> None:
nonlocal called
called = True
monkeypatch.setattr(update_check, "_refresh_cache", fake_refresh)
update_check.start_background_check()
assert update_check._background_thread is None
assert called is False
def test_background_check_runs_when_stale(monkeypatch: pytest.MonkeyPatch) -> None:
update_check._CACHE_PATH.write_text(
json.dumps({"latest_version": "1.0.0", "checked_at": time.time() - 2 * 24 * 60 * 60})
)
monkeypatch.setattr(update_check, "_fetch_latest_version", lambda: "1.2.3")
update_check.start_background_check()
assert update_check._background_thread is not None
update_check._background_thread.join(timeout=5)
cache = json.loads(update_check._CACHE_PATH.read_text())
assert cache["latest_version"] == "1.2.3"
def test_skipped_version_suppresses_update(monkeypatch: pytest.MonkeyPatch) -> None:
update_check._CACHE_PATH.write_text(
json.dumps({"latest_version": "9.9.9", "checked_at": time.time()})
)
monkeypatch.setattr(update_check, "get_version", lambda: "1.0.0")
update_check.skip_version("9.9.9")
assert update_check.get_available_update() is None
assert update_check.get_available_update(respect_skip=False) == "9.9.9"
def test_newer_release_overrides_skipped_version(monkeypatch: pytest.MonkeyPatch) -> None:
update_check._CACHE_PATH.write_text(
json.dumps(
{"latest_version": "9.9.10", "checked_at": time.time(), "skipped_version": "9.9.9"}
)
)
monkeypatch.setattr(update_check, "get_version", lambda: "1.0.0")
assert update_check.get_available_update() == "9.9.10"
def test_write_cache_preserves_existing_fields() -> None:
update_check.skip_version("9.9.9")
update_check._write_cache(latest_version="1.2.3", checked_at=123.0)
cache = json.loads(update_check._CACHE_PATH.read_text())
assert cache == {"latest_version": "1.2.3", "checked_at": 123.0, "skipped_version": "9.9.9"}
def test_get_upgrade_command_all_methods() -> None:
assert update_check.get_upgrade_command("binary") == "strix --update"
assert update_check.get_upgrade_command("pipx") == "pipx upgrade strix-agent"
assert update_check.get_upgrade_command("uv") == "uv tool upgrade strix-agent"
assert update_check.get_upgrade_command("pip") == "pip install --upgrade strix-agent"
def test_self_update_non_binary_prints_command(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(update_check, "is_binary_install", lambda: False)
buffer = io.StringIO()
assert update_check.self_update(Console(file=buffer)) is False
assert "upgrade" in buffer.getvalue()
def test_self_update_already_latest(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(update_check, "is_binary_install", lambda: True)
monkeypatch.setattr(update_check, "_fetch_latest_version", lambda: "1.0.0")
monkeypatch.setattr(update_check, "get_version", lambda: "1.0.0")
assert update_check.self_update() is True
def test_sha256_file(tmp_path: Path) -> None:
path = tmp_path / "blob"
path.write_bytes(b"strix")
assert update_check._sha256_file(path) == hashlib.sha256(b"strix").hexdigest()
def test_release_target(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(platform, "system", lambda: "Linux")
monkeypatch.setattr(platform, "machine", lambda: "x86_64")
assert update_check._release_target() == "linux-x86_64"
monkeypatch.setattr(platform, "system", lambda: "Darwin")
monkeypatch.setattr(platform, "machine", lambda: "arm64")
assert update_check._release_target() == "macos-arm64"
monkeypatch.setattr(platform, "machine", lambda: "riscv64")
assert update_check._release_target() is None
+46
View File
@@ -0,0 +1,46 @@
"""Subscription runs track tokens but report zero cost."""
from __future__ import annotations
from agents.usage import Usage
from strix.report.usage import LLMUsageLedger
def _usage() -> Usage:
usage = Usage()
usage.requests = 1
usage.input_tokens = 1000
usage.output_tokens = 200
usage.total_tokens = 1200
return usage
def test_zero_cost_ledger_keeps_tokens_but_reports_no_cost() -> None:
ledger = LLMUsageLedger()
ledger.zero_cost = True
ledger.record(agent_id="a", usage=_usage(), agent_name="strix", model="gpt-5.5")
record = ledger.to_record()
assert record["cost"] == 0.0
assert record["total_tokens"] == 1200
assert record["input_tokens"] == 1000
assert record["output_tokens"] == 200
assert ledger.total_cost == 0.0
def test_zero_cost_ledger_ignores_observed_cost() -> None:
ledger = LLMUsageLedger()
ledger.zero_cost = True
ledger.record_observed_cost(4.20)
assert ledger.total_cost == 0.0
def test_normal_ledger_still_estimates_cost() -> None:
# Sanity check the flag is opt-in: without it, an OpenAI-native model still
# accrues an estimated cost (proves zeroing is what suppresses it).
ledger = LLMUsageLedger()
ledger.record(agent_id="a", usage=_usage(), agent_name="strix", model="gpt-5.5")
assert ledger.to_record()["total_tokens"] == 1200
# Cost estimation depends on litellm's cost map; it should be >= 0 and not error.
assert ledger.total_cost >= 0.0
Generated
+52 -52
View File
@@ -469,55 +469,55 @@ wheels = [
[[package]]
name = "cryptography"
version = "46.0.7"
version = "48.0.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "cffi", marker = "platform_python_implementation != 'PyPy'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/47/93/ac8f3d5ff04d54bc814e961a43ae5b0b146154c89c61b47bb07557679b18/cryptography-46.0.7.tar.gz", hash = "sha256:e4cfd68c5f3e0bfdad0d38e023239b96a2fe84146481852dffbcca442c245aa5", size = 750652, upload-time = "2026-04-08T01:57:54.692Z" }
sdist = { url = "https://files.pythonhosted.org/packages/12/45/870e7f4bef50e5f53b9f51d4428aee5290eedf58ba443f16b1ebb7ab8e66/cryptography-48.0.1.tar.gz", hash = "sha256:266f4ee051abb2f725b74ef8072b521ce1feacf685a3364fa6a6b45548db791a", size = 832989, upload-time = "2026-06-09T22:32:31.8Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/0b/5d/4a8f770695d73be252331e60e526291e3df0c9b27556a90a6b47bccca4c2/cryptography-46.0.7-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:ea42cbe97209df307fdc3b155f1b6fa2577c0defa8f1f7d3be7d31d189108ad4", size = 7179869, upload-time = "2026-04-08T01:56:17.157Z" },
{ url = "https://files.pythonhosted.org/packages/5f/45/6d80dc379b0bbc1f9d1e429f42e4cb9e1d319c7a8201beffd967c516ea01/cryptography-46.0.7-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b36a4695e29fe69215d75960b22577197aca3f7a25b9cf9d165dcfe9d80bc325", size = 4275492, upload-time = "2026-04-08T01:56:19.36Z" },
{ url = "https://files.pythonhosted.org/packages/4a/9a/1765afe9f572e239c3469f2cb429f3ba7b31878c893b246b4b2994ffe2fe/cryptography-46.0.7-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5ad9ef796328c5e3c4ceed237a183f5d41d21150f972455a9d926593a1dcb308", size = 4426670, upload-time = "2026-04-08T01:56:21.415Z" },
{ url = "https://files.pythonhosted.org/packages/8f/3e/af9246aaf23cd4ee060699adab1e47ced3f5f7e7a8ffdd339f817b446462/cryptography-46.0.7-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:73510b83623e080a2c35c62c15298096e2a5dc8d51c3b4e1740211839d0dea77", size = 4280275, upload-time = "2026-04-08T01:56:23.539Z" },
{ url = "https://files.pythonhosted.org/packages/0f/54/6bbbfc5efe86f9d71041827b793c24811a017c6ac0fd12883e4caa86b8ed/cryptography-46.0.7-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:cbd5fb06b62bd0721e1170273d3f4d5a277044c47ca27ee257025146c34cbdd1", size = 4928402, upload-time = "2026-04-08T01:56:25.624Z" },
{ url = "https://files.pythonhosted.org/packages/2d/cf/054b9d8220f81509939599c8bdbc0c408dbd2bdd41688616a20731371fe0/cryptography-46.0.7-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:420b1e4109cc95f0e5700eed79908cef9268265c773d3a66f7af1eef53d409ef", size = 4459985, upload-time = "2026-04-08T01:56:27.309Z" },
{ url = "https://files.pythonhosted.org/packages/f9/46/4e4e9c6040fb01c7467d47217d2f882daddeb8828f7df800cb806d8a2288/cryptography-46.0.7-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:24402210aa54baae71d99441d15bb5a1919c195398a87b563df84468160a65de", size = 3990652, upload-time = "2026-04-08T01:56:29.095Z" },
{ url = "https://files.pythonhosted.org/packages/36/5f/313586c3be5a2fbe87e4c9a254207b860155a8e1f3cca99f9910008e7d08/cryptography-46.0.7-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:8a469028a86f12eb7d2fe97162d0634026d92a21f3ae0ac87ed1c4a447886c83", size = 4279805, upload-time = "2026-04-08T01:56:30.928Z" },
{ url = "https://files.pythonhosted.org/packages/69/33/60dfc4595f334a2082749673386a4d05e4f0cf4df8248e63b2c3437585f2/cryptography-46.0.7-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:9694078c5d44c157ef3162e3bf3946510b857df5a3955458381d1c7cfc143ddb", size = 4892883, upload-time = "2026-04-08T01:56:32.614Z" },
{ url = "https://files.pythonhosted.org/packages/c7/0b/333ddab4270c4f5b972f980adef4faa66951a4aaf646ca067af597f15563/cryptography-46.0.7-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:42a1e5f98abb6391717978baf9f90dc28a743b7d9be7f0751a6f56a75d14065b", size = 4459756, upload-time = "2026-04-08T01:56:34.306Z" },
{ url = "https://files.pythonhosted.org/packages/d2/14/633913398b43b75f1234834170947957c6b623d1701ffc7a9600da907e89/cryptography-46.0.7-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:91bbcb08347344f810cbe49065914fe048949648f6bd5c2519f34619142bbe85", size = 4410244, upload-time = "2026-04-08T01:56:35.977Z" },
{ url = "https://files.pythonhosted.org/packages/10/f2/19ceb3b3dc14009373432af0c13f46aa08e3ce334ec6eff13492e1812ccd/cryptography-46.0.7-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:5d1c02a14ceb9148cc7816249f64f623fbfee39e8c03b3650d842ad3f34d637e", size = 4674868, upload-time = "2026-04-08T01:56:38.034Z" },
{ url = "https://files.pythonhosted.org/packages/1a/bb/a5c213c19ee94b15dfccc48f363738633a493812687f5567addbcbba9f6f/cryptography-46.0.7-cp311-abi3-win32.whl", hash = "sha256:d23c8ca48e44ee015cd0a54aeccdf9f09004eba9fc96f38c911011d9ff1bd457", size = 3026504, upload-time = "2026-04-08T01:56:39.666Z" },
{ url = "https://files.pythonhosted.org/packages/2b/02/7788f9fefa1d060ca68717c3901ae7fffa21ee087a90b7f23c7a603c32ae/cryptography-46.0.7-cp311-abi3-win_amd64.whl", hash = "sha256:397655da831414d165029da9bc483bed2fe0e75dde6a1523ec2fe63f3c46046b", size = 3488363, upload-time = "2026-04-08T01:56:41.893Z" },
{ url = "https://files.pythonhosted.org/packages/7b/56/15619b210e689c5403bb0540e4cb7dbf11a6bf42e483b7644e471a2812b3/cryptography-46.0.7-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:d151173275e1728cf7839aaa80c34fe550c04ddb27b34f48c232193df8db5842", size = 7119671, upload-time = "2026-04-08T01:56:44Z" },
{ url = "https://files.pythonhosted.org/packages/74/66/e3ce040721b0b5599e175ba91ab08884c75928fbeb74597dd10ef13505d2/cryptography-46.0.7-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:db0f493b9181c7820c8134437eb8b0b4792085d37dbb24da050476ccb664e59c", size = 4268551, upload-time = "2026-04-08T01:56:46.071Z" },
{ url = "https://files.pythonhosted.org/packages/03/11/5e395f961d6868269835dee1bafec6a1ac176505a167f68b7d8818431068/cryptography-46.0.7-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ebd6daf519b9f189f85c479427bbd6e9c9037862cf8fe89ee35503bd209ed902", size = 4408887, upload-time = "2026-04-08T01:56:47.718Z" },
{ url = "https://files.pythonhosted.org/packages/40/53/8ed1cf4c3b9c8e611e7122fb56f1c32d09e1fff0f1d77e78d9ff7c82653e/cryptography-46.0.7-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:b7b412817be92117ec5ed95f880defe9cf18a832e8cafacf0a22337dc1981b4d", size = 4271354, upload-time = "2026-04-08T01:56:49.312Z" },
{ url = "https://files.pythonhosted.org/packages/50/46/cf71e26025c2e767c5609162c866a78e8a2915bbcfa408b7ca495c6140c4/cryptography-46.0.7-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:fbfd0e5f273877695cb93baf14b185f4878128b250cc9f8e617ea0c025dfb022", size = 4905845, upload-time = "2026-04-08T01:56:50.916Z" },
{ url = "https://files.pythonhosted.org/packages/c0/ea/01276740375bac6249d0a971ebdf6b4dc9ead0ee0a34ef3b5a88c1a9b0d4/cryptography-46.0.7-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:ffca7aa1d00cf7d6469b988c581598f2259e46215e0140af408966a24cf086ce", size = 4444641, upload-time = "2026-04-08T01:56:52.882Z" },
{ url = "https://files.pythonhosted.org/packages/3d/4c/7d258f169ae71230f25d9f3d06caabcff8c3baf0978e2b7d65e0acac3827/cryptography-46.0.7-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:60627cf07e0d9274338521205899337c5d18249db56865f943cbe753aa96f40f", size = 3967749, upload-time = "2026-04-08T01:56:54.597Z" },
{ url = "https://files.pythonhosted.org/packages/b5/2a/2ea0767cad19e71b3530e4cad9605d0b5e338b6a1e72c37c9c1ceb86c333/cryptography-46.0.7-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:80406c3065e2c55d7f49a9550fe0c49b3f12e5bfff5dedb727e319e1afb9bf99", size = 4270942, upload-time = "2026-04-08T01:56:56.416Z" },
{ url = "https://files.pythonhosted.org/packages/41/3d/fe14df95a83319af25717677e956567a105bb6ab25641acaa093db79975d/cryptography-46.0.7-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:c5b1ccd1239f48b7151a65bc6dd54bcfcc15e028c8ac126d3fada09db0e07ef1", size = 4871079, upload-time = "2026-04-08T01:56:58.31Z" },
{ url = "https://files.pythonhosted.org/packages/9c/59/4a479e0f36f8f378d397f4eab4c850b4ffb79a2f0d58704b8fa0703ddc11/cryptography-46.0.7-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:d5f7520159cd9c2154eb61eb67548ca05c5774d39e9c2c4339fd793fe7d097b2", size = 4443999, upload-time = "2026-04-08T01:57:00.508Z" },
{ url = "https://files.pythonhosted.org/packages/28/17/b59a741645822ec6d04732b43c5d35e4ef58be7bfa84a81e5ae6f05a1d33/cryptography-46.0.7-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:fcd8eac50d9138c1d7fc53a653ba60a2bee81a505f9f8850b6b2888555a45d0e", size = 4399191, upload-time = "2026-04-08T01:57:02.654Z" },
{ url = "https://files.pythonhosted.org/packages/59/6a/bb2e166d6d0e0955f1e9ff70f10ec4b2824c9cfcdb4da772c7dd69cc7d80/cryptography-46.0.7-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:65814c60f8cc400c63131584e3e1fad01235edba2614b61fbfbfa954082db0ee", size = 4655782, upload-time = "2026-04-08T01:57:04.592Z" },
{ url = "https://files.pythonhosted.org/packages/95/b6/3da51d48415bcb63b00dc17c2eff3a651b7c4fed484308d0f19b30e8cb2c/cryptography-46.0.7-cp314-cp314t-win32.whl", hash = "sha256:fdd1736fed309b4300346f88f74cd120c27c56852c3838cab416e7a166f67298", size = 3002227, upload-time = "2026-04-08T01:57:06.91Z" },
{ url = "https://files.pythonhosted.org/packages/32/a8/9f0e4ed57ec9cebe506e58db11ae472972ecb0c659e4d52bbaee80ca340a/cryptography-46.0.7-cp314-cp314t-win_amd64.whl", hash = "sha256:e06acf3c99be55aa3b516397fe42f5855597f430add9c17fa46bf2e0fb34c9bb", size = 3475332, upload-time = "2026-04-08T01:57:08.807Z" },
{ url = "https://files.pythonhosted.org/packages/a7/7f/cd42fc3614386bc0c12f0cb3c4ae1fc2bbca5c9662dfed031514911d513d/cryptography-46.0.7-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:462ad5cb1c148a22b2e3bcc5ad52504dff325d17daf5df8d88c17dda1f75f2a4", size = 7165618, upload-time = "2026-04-08T01:57:10.645Z" },
{ url = "https://files.pythonhosted.org/packages/a5/d0/36a49f0262d2319139d2829f773f1b97ef8aef7f97e6e5bd21455e5a8fb5/cryptography-46.0.7-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:84d4cced91f0f159a7ddacad249cc077e63195c36aac40b4150e7a57e84fffe7", size = 4270628, upload-time = "2026-04-08T01:57:12.885Z" },
{ url = "https://files.pythonhosted.org/packages/8a/6c/1a42450f464dda6ffbe578a911f773e54dd48c10f9895a23a7e88b3e7db5/cryptography-46.0.7-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:128c5edfe5e5938b86b03941e94fac9ee793a94452ad1365c9fc3f4f62216832", size = 4415405, upload-time = "2026-04-08T01:57:14.923Z" },
{ url = "https://files.pythonhosted.org/packages/9a/92/4ed714dbe93a066dc1f4b4581a464d2d7dbec9046f7c8b7016f5286329e2/cryptography-46.0.7-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:5e51be372b26ef4ba3de3c167cd3d1022934bc838ae9eaad7e644986d2a3d163", size = 4272715, upload-time = "2026-04-08T01:57:16.638Z" },
{ url = "https://files.pythonhosted.org/packages/b7/e6/a26b84096eddd51494bba19111f8fffe976f6a09f132706f8f1bf03f51f7/cryptography-46.0.7-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:cdf1a610ef82abb396451862739e3fc93b071c844399e15b90726ef7470eeaf2", size = 4918400, upload-time = "2026-04-08T01:57:19.021Z" },
{ url = "https://files.pythonhosted.org/packages/c7/08/ffd537b605568a148543ac3c2b239708ae0bd635064bab41359252ef88ed/cryptography-46.0.7-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:1d25aee46d0c6f1a501adcddb2d2fee4b979381346a78558ed13e50aa8a59067", size = 4450634, upload-time = "2026-04-08T01:57:21.185Z" },
{ url = "https://files.pythonhosted.org/packages/16/01/0cd51dd86ab5b9befe0d031e276510491976c3a80e9f6e31810cce46c4ad/cryptography-46.0.7-cp38-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:cdfbe22376065ffcf8be74dc9a909f032df19bc58a699456a21712d6e5eabfd0", size = 3985233, upload-time = "2026-04-08T01:57:22.862Z" },
{ url = "https://files.pythonhosted.org/packages/92/49/819d6ed3a7d9349c2939f81b500a738cb733ab62fbecdbc1e38e83d45e12/cryptography-46.0.7-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:abad9dac36cbf55de6eb49badd4016806b3165d396f64925bf2999bcb67837ba", size = 4271955, upload-time = "2026-04-08T01:57:24.814Z" },
{ url = "https://files.pythonhosted.org/packages/80/07/ad9b3c56ebb95ed2473d46df0847357e01583f4c52a85754d1a55e29e4d0/cryptography-46.0.7-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:935ce7e3cfdb53e3536119a542b839bb94ec1ad081013e9ab9b7cfd478b05006", size = 4879888, upload-time = "2026-04-08T01:57:26.88Z" },
{ url = "https://files.pythonhosted.org/packages/b8/c7/201d3d58f30c4c2bdbe9b03844c291feb77c20511cc3586daf7edc12a47b/cryptography-46.0.7-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:35719dc79d4730d30f1c2b6474bd6acda36ae2dfae1e3c16f2051f215df33ce0", size = 4449961, upload-time = "2026-04-08T01:57:29.068Z" },
{ url = "https://files.pythonhosted.org/packages/a5/ef/649750cbf96f3033c3c976e112265c33906f8e462291a33d77f90356548c/cryptography-46.0.7-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:7bbc6ccf49d05ac8f7d7b5e2e2c33830d4fe2061def88210a126d130d7f71a85", size = 4401696, upload-time = "2026-04-08T01:57:31.029Z" },
{ url = "https://files.pythonhosted.org/packages/41/52/a8908dcb1a389a459a29008c29966c1d552588d4ae6d43f3a1a4512e0ebe/cryptography-46.0.7-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a1529d614f44b863a7b480c6d000fe93b59acee9c82ffa027cfadc77521a9f5e", size = 4664256, upload-time = "2026-04-08T01:57:33.144Z" },
{ url = "https://files.pythonhosted.org/packages/4b/fa/f0ab06238e899cc3fb332623f337a7364f36f4bb3f2534c2bb95a35b132c/cryptography-46.0.7-cp38-abi3-win32.whl", hash = "sha256:f247c8c1a1fb45e12586afbb436ef21ff1e80670b2861a90353d9b025583d246", size = 3013001, upload-time = "2026-04-08T01:57:34.933Z" },
{ url = "https://files.pythonhosted.org/packages/d2/f1/00ce3bde3ca542d1acd8f8cfa38e446840945aa6363f9b74746394b14127/cryptography-46.0.7-cp38-abi3-win_amd64.whl", hash = "sha256:506c4ff91eff4f82bdac7633318a526b1d1309fc07ca76a3ad182cb5b686d6d3", size = 3472985, upload-time = "2026-04-08T01:57:36.714Z" },
{ url = "https://files.pythonhosted.org/packages/1b/bc/ee4137cbbe105652c0ee4252792b78fc8e7afa4b8e61d9d5dc05a7f45731/cryptography-48.0.1-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:3e4a1a3232eef2e6c732827d5722db29a0cc8b27af2a4d865b094cf954be9ca1", size = 8008324, upload-time = "2026-06-09T22:31:00.702Z" },
{ url = "https://files.pythonhosted.org/packages/d5/85/6379d42181bfc713094f081360fc5784d6c816b599d45e7f082502d173ce/cryptography-48.0.1-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:32143b24adb918f078134e1e230f1eb8cc04886b92c28b5f0041aaf3e5699225", size = 4696243, upload-time = "2026-06-09T22:32:33.446Z" },
{ url = "https://files.pythonhosted.org/packages/9c/87/c85d147b53323c7eb4d850920c8901377323c2a0ff8d79c262d4fee89aa2/cryptography-48.0.1-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f0d27a5696721ef7a672b8c810f6aded391058e0b9486e63e6d93baf765da691", size = 4713235, upload-time = "2026-06-09T22:31:40.141Z" },
{ url = "https://files.pythonhosted.org/packages/79/58/67cbf8cf1ee7c54b439ca07bbecf8362c07afc11a3724fea70f745784add/cryptography-48.0.1-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:eb86ce1af36fe65041b6db9a8bb064ee621a7e5fded0f80d475ec243477cd242", size = 4702323, upload-time = "2026-06-09T22:31:42.191Z" },
{ url = "https://files.pythonhosted.org/packages/89/c6/24266ac10c47f6cd2a865f4446062b466da1d1f10b27189eac00e61bf0c9/cryptography-48.0.1-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:b024e784ad6c077ee0147b35ea9cbfc1e34e1fd4c1dcca214c2794d73a12df08", size = 5300085, upload-time = "2026-06-09T22:31:58.703Z" },
{ url = "https://files.pythonhosted.org/packages/d2/bb/cc4b78784f97efc8c5874c2a9743708d172be6663024b34a0467885ae0c8/cryptography-48.0.1-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3752f2dbc8f07a30aad2932c986cea495b03bb554887828225da104f732852b6", size = 4746137, upload-time = "2026-06-09T22:31:31.01Z" },
{ url = "https://files.pythonhosted.org/packages/1f/52/0c44de3f5267f8fbe8e835138017522a333436166e406f0db9b9e6e3033f/cryptography-48.0.1-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:bd81490cd5801d755cf97bb68ac191f14b708470b1c7cf4580f669b9c9264cd8", size = 4333867, upload-time = "2026-06-09T22:32:28.096Z" },
{ url = "https://files.pythonhosted.org/packages/9a/2e/772d7adbfa931537bc401640b7cac9976bff689bda187833e5d63b428e49/cryptography-48.0.1-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:66fd0771e7b9c6dcd44cf1120690d2338d16d72795cf40cae2786a39eba65429", size = 4701805, upload-time = "2026-06-09T22:31:38.284Z" },
{ url = "https://files.pythonhosted.org/packages/f8/a3/b06844f303873493c963caf581c04df31c7035e0c1b0f02c4814d319ec80/cryptography-48.0.1-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:3fd2ca57062b241c856670b073487d2e86c4637937ca5601e48f97bf8e11fc8f", size = 5258461, upload-time = "2026-06-09T22:31:04.187Z" },
{ url = "https://files.pythonhosted.org/packages/9f/13/8b765e2e12b07c74941caadb9d1c8fdc006c4dfbf2b8f2d610519758954d/cryptography-48.0.1-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:0ee6ea481db1ab889cba043ec1eda17bb9c1ea79db6722f779c3667f9f70322f", size = 4745488, upload-time = "2026-06-09T22:32:30.07Z" },
{ url = "https://files.pythonhosted.org/packages/2e/aa/48972bce55049b32a94f4907eda4d75fa385aad8a39506cc2fc72196ecf0/cryptography-48.0.1-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:f2ceef93cb096aa3c4cc4b5c94ca6131f9196d28c64d6111533402a9b2054d41", size = 4830256, upload-time = "2026-06-09T22:31:43.868Z" },
{ url = "https://files.pythonhosted.org/packages/47/a2/e5079a032fb85cf6005046ca92bbd78b0c82dad2b5751ab8c311659da06f/cryptography-48.0.1-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:9bd3f92d76217892b15df84ca256c2c113d386fdda7a7d8691aeeced976507c6", size = 4979117, upload-time = "2026-06-09T22:31:05.845Z" },
{ url = "https://files.pythonhosted.org/packages/b7/a0/8f50cae9c74e718ed769d63ed5c74bd0ea830c9550a74629cebd1b9c7bc7/cryptography-48.0.1-cp311-abi3-win32.whl", hash = "sha256:b9a32b876490d66c8bcc9963ef220199569748434ab01a9d6aaeabf88e7f5158", size = 3304154, upload-time = "2026-06-09T22:32:16.845Z" },
{ url = "https://files.pythonhosted.org/packages/c5/69/0572c77dbace6fef72f33755bd52ea399c71367250d366237f8691826b9e/cryptography-48.0.1-cp311-abi3-win_amd64.whl", hash = "sha256:39489bfca54c7a1f6b297efcd8bc608ab92d16c4ca631b0cad4da46724588b24", size = 3817138, upload-time = "2026-06-09T22:32:00.388Z" },
{ url = "https://files.pythonhosted.org/packages/42/06/3e768b4c3bc78201583fa35a0e18f640dd782ff41afba88f8545481a8874/cryptography-48.0.1-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:f817adc181390bd54f2f700107a7419040fb7c1bdf2fc26f36551a06a68c3345", size = 7989830, upload-time = "2026-06-09T22:31:07.8Z" },
{ url = "https://files.pythonhosted.org/packages/8a/13/6476736484b94041110c8340a3eb63962fea4975baea8cb4a512adb44d4d/cryptography-48.0.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d5d30989c6917b478b5817902e85fddaea2261efa8648383d965381ccb9e1ac4", size = 4689201, upload-time = "2026-06-09T22:31:09.745Z" },
{ url = "https://files.pythonhosted.org/packages/79/62/65a87f34d2a431546e2509b85d55e8c90df86d668f6731da64d538512ac2/cryptography-48.0.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:df637c05205ea7c1d7fbcbe54bbfea648a52951155f997af13d895d0ecc96991", size = 4702822, upload-time = "2026-06-09T22:32:24.409Z" },
{ url = "https://files.pythonhosted.org/packages/7f/59/810b5204b0a9b10f4b6bc06bd551a8b609803cd931806bc3b71884b225e5/cryptography-48.0.1-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:869c3b8a53bfe27147832df48b32adadf558249d50e76cb3769d40e986b13265", size = 4694875, upload-time = "2026-06-09T22:32:08.737Z" },
{ url = "https://files.pythonhosted.org/packages/24/dc/d8ca05ffea724eec6d232ea6f18e74c269eb6bdfdcc9bfba689790d1325f/cryptography-48.0.1-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:e361afba8918070d376df76f408a4f67fec0ee9cff81a99e48fe9a233ef59e17", size = 5290385, upload-time = "2026-06-09T22:31:15.212Z" },
{ url = "https://files.pythonhosted.org/packages/03/8c/3be6cb4da181f5bb6c19cf560c2359d60644a6b5fc5b57854e528f47b296/cryptography-48.0.1-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:d069066deead00ac7f090be101be875a06855908f7ec004c27b8fefb4acfb411", size = 4737082, upload-time = "2026-06-09T22:32:22.66Z" },
{ url = "https://files.pythonhosted.org/packages/aa/f6/d5f60a5a1434dbfd949e227fd0065d194c7e6b6ac526b17f5c06152b8231/cryptography-48.0.1-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:09f73a725d582cef64b91281a322cd798d14a33b2b6f2b7ad9531dc336d84c02", size = 4325328, upload-time = "2026-06-09T22:32:10.777Z" },
{ url = "https://files.pythonhosted.org/packages/17/b7/ba75dd947a14b6ad907b01ae8f6b5b348cdd1b48142f0063dee9e20c1d9d/cryptography-48.0.1-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:15254441469dd6bf027039453288e2072124f8b6603563f5d759e1c9b69273fa", size = 4694530, upload-time = "2026-06-09T22:31:53.105Z" },
{ url = "https://files.pythonhosted.org/packages/62/29/50d6b9e8aff12d8b67afaeb3569335e32dc83a5723e3bbded24fdac9f809/cryptography-48.0.1-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:8ace4507d1e6533c125f4fac754f8bb8b6a74c08e92179dabd7e16571a3efbf3", size = 5245046, upload-time = "2026-06-09T22:31:25.774Z" },
{ url = "https://files.pythonhosted.org/packages/9f/04/618f4115cfc0add0838c82507aa18a346089428da8653ad38b3ff36f5cb3/cryptography-48.0.1-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:b4e391975f038e66432328639620a4aff2d307513b004f1ca06d6225bced815c", size = 4736660, upload-time = "2026-06-09T22:32:12.676Z" },
{ url = "https://files.pythonhosted.org/packages/24/9c/06e062462a0de28a3b3911322eded4c16deb9f441b1b7575d3dc59488ab5/cryptography-48.0.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:42fcd8e26fe555d9b3577a135f5091fefa0aa4e99129c23fb56787a1bd4ada72", size = 4822229, upload-time = "2026-06-09T22:31:17.062Z" },
{ url = "https://files.pythonhosted.org/packages/f4/be/0561971eaaee4b8a0e7d5113c536921063ab91aaf23278ac374eaf881e11/cryptography-48.0.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:c1400da5e32a43253392277eac7490a60e497d810a63dd5608d71bbd7af507c9", size = 4966364, upload-time = "2026-06-09T22:31:32.842Z" },
{ url = "https://files.pythonhosted.org/packages/a4/27/728c77876f12b000820b69ae490f3c4083775e79e07827e9e60be07ad209/cryptography-48.0.1-cp314-cp314t-win32.whl", hash = "sha256:0df56b056bc17c1b7d6821dfa65216e62bd232d8ab05eb3db44e71d235651471", size = 3278498, upload-time = "2026-06-09T22:31:29.154Z" },
{ url = "https://files.pythonhosted.org/packages/06/e3/79a612c6d7b1e6ee0edd43633d53035bec2cfb78c82b76f7864f39e36f34/cryptography-48.0.1-cp314-cp314t-win_amd64.whl", hash = "sha256:9de21387aa95e2a895823d0745b430bed4f33503ba9ab5e0b5311f33e37d66d2", size = 3798790, upload-time = "2026-06-09T22:31:56.697Z" },
{ url = "https://files.pythonhosted.org/packages/ca/6c/00fa2a95997164c8b2072ce327c23d4ab20809ccc323ea5fab91e53a4bba/cryptography-48.0.1-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:4fdc69f8e4316bcf0c8c8ec1f26f285d12e8142d88d96c876a59a03be3f6ae67", size = 7987408, upload-time = "2026-06-09T22:32:20.777Z" },
{ url = "https://files.pythonhosted.org/packages/b0/d9/45f309a7e4e5f3f8f121d6d3be9e94024a7726ec598d6e08ae04edb2f04d/cryptography-48.0.1-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:48fe40804d4caa2288f24e70ca8c64c42dd826da0ad7e4f1b41b2128d679e6c8", size = 4690196, upload-time = "2026-06-09T22:31:54.74Z" },
{ url = "https://files.pythonhosted.org/packages/5f/9f/a1bc8bcc798811b8527eb374bbccf30a3f3e806829d967118222bf1125eb/cryptography-48.0.1-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:86be3b1b0b6bf09482fb50a979c508d2950ed95f5621ec77f4e385962006b83a", size = 4696782, upload-time = "2026-06-09T22:31:45.615Z" },
{ url = "https://files.pythonhosted.org/packages/66/c2/81a4fb4e4373c500bb526bc337ac5719dd31dd15b970b84a238168c6aa08/cryptography-48.0.1-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:4ab0a343c807bbcd90c971cd1ecf072937cd01847a9e002bef88fb47ac6be577", size = 4696618, upload-time = "2026-06-09T22:31:11.564Z" },
{ url = "https://files.pythonhosted.org/packages/e5/0b/aa68b221dde92d09cb29a024ede17550ee21e77a404e59fc093c82bb51e1/cryptography-48.0.1-cp39-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:9621de99d2da096006b629979efd8ae7eb2d8b822488d0c89ee4000c306c59b1", size = 5289970, upload-time = "2026-06-09T22:31:20.368Z" },
{ url = "https://files.pythonhosted.org/packages/78/13/fba657f958d2af66ea959a4ba01212632089249d34af1ae48054136344d7/cryptography-48.0.1-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:88c852a0ae366e262e5a1744b685e6a433dc8788dd2a277e418bf4904203609d", size = 4731873, upload-time = "2026-06-09T22:31:22.253Z" },
{ url = "https://files.pythonhosted.org/packages/4c/4c/9a964756d24a26b3e34dfcb16f961b89838786e6700b635b0d1e3adff4b6/cryptography-48.0.1-cp39-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:43c5835e2cb98c8733d86f57d6fc879b613f5c3478607281c3e36daffc6dd8a6", size = 4330804, upload-time = "2026-06-09T22:31:36.56Z" },
{ url = "https://files.pythonhosted.org/packages/4b/0f/a10f3a6eb12950a10e3a874070283aa2dd5875b2bfd15fad8a3e17b3f13e/cryptography-48.0.1-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:fe0180af5bf9236518a087e35bf2d9a347d5f5f51e63c579d683ddff424e3d46", size = 4696217, upload-time = "2026-06-09T22:31:13.351Z" },
{ url = "https://files.pythonhosted.org/packages/f3/6f/5cd12f951165ea73ef85266775d97e4c763b2474ccfd816dd69d3a18d6f8/cryptography-48.0.1-cp39-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:b7a2d1a937a738a881737cec135a38bb61470589b17515b9f73f571d0ae10401", size = 5245252, upload-time = "2026-06-09T22:32:02.193Z" },
{ url = "https://files.pythonhosted.org/packages/68/ab/8aaa12e4516ec4464033ab79b6f3b592bd5a92102467c4ace8a0d970203f/cryptography-48.0.1-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:b74ca3b8e5ecdd833bf6a002ca41b4793bb27fb8f1c06ffaf2643c9e9140e31b", size = 4731388, upload-time = "2026-06-09T22:32:04.019Z" },
{ url = "https://files.pythonhosted.org/packages/1b/24/50027ea4dca85ec1f40688f3c24fb32ccacd520583c9592c3cc95628e6fb/cryptography-48.0.1-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2c37f2461406063b417837f5f3daab668652acd82423efcd7f0a9f04be972de1", size = 4824186, upload-time = "2026-06-09T22:32:18.707Z" },
{ url = "https://files.pythonhosted.org/packages/52/41/04cb5eb17085ade6f50cc611fb657df6a0f5885350de8764ece89c050197/cryptography-48.0.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:86fe77abb1bd87afb251d4d02ada7ecf53a32cee9b67d976abb2e45a13297475", size = 4964539, upload-time = "2026-06-09T22:31:18.793Z" },
{ url = "https://files.pythonhosted.org/packages/36/bf/ed70785c496e89d7e73b7cda2d21f2447fd6d4e821714b8d04ff217fed92/cryptography-48.0.1-cp39-abi3-win32.whl", hash = "sha256:6b2c0c3e6ccf3ade7750f836ef3ee36eea250cc467d45c256895573ac08cc6f1", size = 3282307, upload-time = "2026-06-09T22:30:53.162Z" },
{ url = "https://files.pythonhosted.org/packages/b3/ff/371ea7d252656ee1eb6d83eeeef3d1d0c6baf1d6497687d081ea03814670/cryptography-48.0.1-cp39-abi3-win_amd64.whl", hash = "sha256:9a49ca6c81417f6a5edb50375a60cccdd70fa0a91a5211829dbea74eba94d2ac", size = 3793408, upload-time = "2026-06-09T22:32:15.191Z" },
]
[[package]]
@@ -1685,11 +1685,11 @@ wheels = [
[[package]]
name = "pyasn1"
version = "0.6.3"
version = "0.6.4"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/5c/5f/6583902b6f79b399c9c40674ac384fd9cd77805f9e6205075f828ef11fb2/pyasn1-0.6.3.tar.gz", hash = "sha256:697a8ecd6d98891189184ca1fa05d1bb00e2f84b5977c481452050549c8a72cf", size = 148685, upload-time = "2026-03-17T01:06:53.382Z" }
sdist = { url = "https://files.pythonhosted.org/packages/a4/9a/23310166d960def5897e91fe20e5b724601b02a22e84ba1f94232c0b7f67/pyasn1-0.6.4.tar.gz", hash = "sha256:9c447d8431c947fe4c8febc4ed9e760bc29011a5b01e5c74b67025bd9fb8ce81", size = 151262, upload-time = "2026-07-09T01:12:33.988Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/5d/a0/7d793dce3fa811fe047d6ae2431c672364b462850c6235ae306c0efd025f/pyasn1-0.6.3-py3-none-any.whl", hash = "sha256:a80184d120f0864a52a073acc6fc642847d0be408e7c7252f31390c0f4eadcde", size = 83997, upload-time = "2026-03-17T01:06:52.036Z" },
{ url = "https://files.pythonhosted.org/packages/9a/3b/6163796d69c3977d1e4287bea4a6979161cbbdd170ebb430511e8e1999ce/pyasn1-0.6.4-py3-none-any.whl", hash = "sha256:deda9277cfd454080ec40b207fb6df82206a3a2688735233cdcd8d3d565f088b", size = 84410, upload-time = "2026-07-09T01:12:32.92Z" },
]
[[package]]
@@ -2340,11 +2340,11 @@ wheels = [
[[package]]
name = "setuptools"
version = "82.0.1"
version = "83.0.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/4f/db/cfac1baf10650ab4d1c111714410d2fbb77ac5a616db26775db562c8fab2/setuptools-82.0.1.tar.gz", hash = "sha256:7d872682c5d01cfde07da7bccc7b65469d3dca203318515ada1de5eda35efbf9", size = 1152316, upload-time = "2026-03-09T12:47:17.221Z" }
sdist = { url = "https://files.pythonhosted.org/packages/34/26/f5d29e25ffdb535afef2d35cdb55b325298f96debd670da4c325e08d70f4/setuptools-83.0.0.tar.gz", hash = "sha256:025bccbbf0fa05b6192bc64ae1e7b16e001fd6d6d4d5de03c97b1c1ade523bef", size = 1154254, upload-time = "2026-07-04T15:31:22.699Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/9d/76/f789f7a86709c6b087c5a2f52f911838cad707cc613162401badc665acfe/setuptools-82.0.1-py3-none-any.whl", hash = "sha256:a59e362652f08dcd477c78bb6e7bd9d80a7995bc73ce773050228a348ce2e5bb", size = 1006223, upload-time = "2026-03-09T12:47:15.026Z" },
{ url = "https://files.pythonhosted.org/packages/5d/40/e1e72872c6354b306daef1703549e8e83b4d43cfea356311bf722a043752/setuptools-83.0.0-py3-none-any.whl", hash = "sha256:29b23c360f22f414dc7336bb39178cc7bcbf6021ed2733cde173f09dba19abb3", size = 1008090, upload-time = "2026-07-04T15:31:20.885Z" },
]
[[package]]
@@ -2411,7 +2411,7 @@ wheels = [
[[package]]
name = "strix-agent"
version = "1.3.0"
version = "1.3.1"
source = { editable = "." }
dependencies = [
{ name = "caido-sdk-client" },
@@ -2454,7 +2454,7 @@ dev = [
requires-dist = [
{ name = "boto3", marker = "extra == 'bedrock'", specifier = ">=1.28.0" },
{ name = "caido-sdk-client", specifier = ">=0.2.0" },
{ name = "cryptography", specifier = ">=42" },
{ name = "cryptography", specifier = ">=48.0.1,<49" },
{ name = "cvss", specifier = ">=3.2" },
{ name = "docker", specifier = ">=7.1.0" },
{ name = "google-auth", marker = "extra == 'vertex'", specifier = ">=2.0.0" },