diff --git a/AGENTS.md b/AGENTS.md
index af121f0..31c538d 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -648,6 +648,17 @@ Use full redeploy instead if:
---
+## Support Target Operational Notes (Feb 2026)
+
+- `Support_Feature_Store` notebook path must be `${workspace.root_path}/stages/support_feature_store` (no `.py` suffix).
+- `Support Response Evals Hourly` should remain enabled (`pause_status: UNPAUSED`) unless explicitly paused for incident response.
+- The eval notebook in `demos/agent-compare-models/demo_materials/support-response-evals.ipynb` must tolerate output schema drift from `mlflow.genai.evaluate()` and should not fail the job when optional columns are absent.
+- `casperskitchens.support.support_request_features` is the expected offline feature table. Verify with:
+ - `databricks tables exists casperskitchens.support.support_request_features -p DEFAULT`
+- Online Table creation is currently blocked by Databricks platform deprecation messaging ("Online Table is being deprecated"). Treat online publish as a follow-up migration to Synced Tables-compatible workflows.
+
+---
+
## Current Work: Canonical Data Migration
**Context**: Migrating from live generator to canonical dataset approach
diff --git a/README.md b/README.md
index 87a37c6..7f3074f 100644
--- a/README.md
+++ b/README.md
@@ -96,6 +96,22 @@ Each event includes order ID, sequence number, timestamp, and location context.
- **π¨ UX Prototyping**: Fully loaded platform for design iteration
- **π¬ Demo Creation**: Unified narrative for new feature demonstrations
+## Support Feature Store Notes
+
+For the support scenario (`-t support` target), feature serving is split from app OLTP storage:
+
+- App runtime tables (actions, replies, status) stay on Lakebase Autoscaling (v2).
+- Features are materialized into the offline UC table `casperskitchens.support.support_request_features`.
+- Current support features include deterministic signals (`repeat_complaints_30d`, `policy_limit_usd`) and a risk score currently computed via deterministic fallback logic in the stage.
+- The support initializer now includes a dedicated `Support_Feature_Store` task and depends on it before `Support_Lakebase`.
+
+### Current Platform Behavior (Feb 2026)
+
+- `Support Response Evals Hourly` has been fixed and is now scheduled (`UNPAUSED`).
+- The eval notebook was hardened to handle schema variations in `mlflow.genai.evaluate()` output without failing.
+- Legacy Online Table creation is currently blocked by Databricks platform behavior ("Online Table is being deprecated"), so online publish is intentionally deferred.
+- Next migration step is to map feature serving exposure to Synced Tables-compatible patterns.
+
## Check out the [Casper's Kitchens Blog](https://databricks-solutions.github.io/caspers-kitchens/)!
## License
diff --git a/apps/refund-manager/app.yaml b/apps/refund-manager/app.yaml
deleted file mode 100644
index b60875e..0000000
--- a/apps/refund-manager/app.yaml
+++ /dev/null
@@ -1,8 +0,0 @@
-command:
- - uvicorn
- - app.main:app
-env:
- - name: DATABRICKS_WAREHOUSE_ID
- value: 'e1a2914f603fc607'
- - name: DATABRICKS_CATALOG
- value: 'cazzper'
diff --git a/apps/refund-manager/app/__init__.py b/apps/refund-manager/app/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/apps/refund-manager/app/databricks_events.py b/apps/refund-manager/app/databricks_events.py
deleted file mode 100644
index 05d409c..0000000
--- a/apps/refund-manager/app/databricks_events.py
+++ /dev/null
@@ -1,76 +0,0 @@
-# app/databricks_events.py
-import os, json
-from typing import List, Dict, Any
-from databricks.sdk import WorkspaceClient
-from databricks.sdk.service.sql import (
- ExecuteStatementRequestOnWaitTimeout,
- StatementParameterListItem,
- Disposition,
- Format,
-)
-
-_w = WorkspaceClient()
-
-WAREHOUSE_ID = os.getenv("DATABRICKS_WAREHOUSE_ID", "")
-CATALOG = os.getenv("DATABRICKS_CATALOG", "")
-SCHEMA = os.getenv("DATABRICKS_SCHEMA", "lakeflow")
-
-_COLS = [
- "body", "event_id", "event_type", "location_id",
- "order_id", "sequence", "ts"
-]
-
-def _state_name(resp) -> str | None:
- st = getattr(resp, "status", None)
- state = getattr(st, "state", None)
- if state is None:
- return None
- # Enum-safe β "SUCCEEDED"
- name = getattr(state, "name", str(state))
- if "." in name: # e.g. "StatementState.SUCCEEDED"
- name = name.split(".")[-1]
- return name
-
-def fetch_order_events(order_id: str) -> List[Dict[str, Any]]:
- stmt = f"""
- SELECT body, event_id, event_type, location_id, order_id, sequence, ts
- FROM {CATALOG}.{SCHEMA}.all_events
- WHERE order_id = :oid
- AND event_type <> 'driver_ping'
- ORDER BY sequence ASC
- """.strip()
-
- params = [StatementParameterListItem(name="oid", value=order_id)]
-
- resp = _w.statement_execution.execute_statement(
- warehouse_id=WAREHOUSE_ID,
- catalog=CATALOG,
- schema=SCHEMA,
- statement=stmt,
- parameters=params,
- wait_timeout="30s",
- on_wait_timeout=ExecuteStatementRequestOnWaitTimeout.CONTINUE,
- disposition=Disposition.INLINE, # ensure rows returned inline
- format=Format.JSON_ARRAY, # ensure result.data_array
- )
-
- state = _state_name(resp)
- if state and state not in {"SUCCEEDED", "SUCCESS", "COMPLETED"}:
- msg = getattr(getattr(resp.status, "error", None), "message", "unknown error")
- raise RuntimeError(f"Statement failed: state={state} message={msg}")
-
- data = resp.result.data_array if resp.result and resp.result.data_array else []
-
- out: List[Dict[str, Any]] = []
- for row in data:
- d = { _COLS[i]: row[i] for i in range(min(len(_COLS), len(row))) }
- v = d.get("body")
- if isinstance(v, str):
- s = v.strip()
- if s.startswith("{") and s.endswith("}"):
- try:
- d["body"] = json.loads(s)
- except Exception:
- pass
- out.append(d)
- return out
diff --git a/apps/refund-manager/app/db.py b/apps/refund-manager/app/db.py
deleted file mode 100644
index 93b5064..0000000
--- a/apps/refund-manager/app/db.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# app/db.py
-import os
-from sqlalchemy import create_engine, event
-from databricks.sdk.core import Config
-from databricks.sdk import WorkspaceClient
-
-_cfg = Config()
-_w = WorkspaceClient() # caches & refreshes tokens
-
-PGHOST = os.environ["PGHOST"]
-PGPORT = os.environ.get("PGPORT", "5432")
-PGDATABASE = os.environ["PGDATABASE"]
-PGSSLMODE = os.environ.get("PGSSLMODE", "require")
-# default to app client_id unless PGUSER is provided explicitly
-PGUSER = os.environ.get("PGUSER", _cfg.client_id)
-
-DSN = f"postgresql+psycopg://{PGUSER}:@{PGHOST}:{PGPORT}/{PGDATABASE}?sslmode={PGSSLMODE}"
-
-engine = create_engine(DSN, future=True, pool_pre_ping=True)
-
-@event.listens_for(engine, "do_connect")
-def _provide_token(dialect, conn_rec, cargs, cparams):
- # Pass the app OAuth token as the password
- cparams["password"] = _w.config.oauth_token().access_token
diff --git a/apps/refund-manager/app/main.py b/apps/refund-manager/app/main.py
deleted file mode 100644
index 03b8c1b..0000000
--- a/apps/refund-manager/app/main.py
+++ /dev/null
@@ -1,262 +0,0 @@
-# app/main.py
-from pathlib import Path
-from typing import Dict, Any, List
-import os, json, traceback, logging
-from collections import Counter
-
-from fastapi import FastAPI, HTTPException
-from fastapi.responses import FileResponse, JSONResponse
-from sqlalchemy import text, bindparam
-
-from .db import engine
-from .models import RefundDecisionCreate, parse_agent_response, ERROR_SUGGESTION
-from .databricks_events import fetch_order_events
-
-DEBUG = os.getenv("DEBUG") in ("1", "true", "TRUE", "yes", "on")
-log = logging.getLogger("refund_manager")
-
-app = FastAPI(title="Refund Manager", version="2.0.0")
-
-# βββ Configurable schemas βββββββββββββββββββββββββββββββββββββββββββββββββββββ
-REFUNDS_SCHEMA = os.environ.get("REFUNDS_SCHEMA", "refunds")
-RECS_SCHEMA = os.environ.get("RECS_SCHEMA", "recommender")
-
-def _qi(name: str) -> str:
- return '"' + name.replace('"', '""') + '"'
-
-REFUNDS_TABLE = f"{_qi(REFUNDS_SCHEMA)}.refund_decisions"
-RECS_TABLE = f"{_qi(RECS_SCHEMA)}.pg_recommendations"
-
-# βββ Startup: ensure refunds table ββββββββββββββββββββββββββββββββββββββββββββ
-DDL = f"""
-CREATE SCHEMA IF NOT EXISTS {_qi(REFUNDS_SCHEMA)};
-
-CREATE TABLE IF NOT EXISTS {REFUNDS_TABLE} (
- id BIGSERIAL PRIMARY KEY,
- order_id TEXT NOT NULL,
- decided_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
- amount_usd NUMERIC(10,2) NOT NULL CHECK (amount_usd >= 0),
- refund_class TEXT NOT NULL CHECK (refund_class IN ('none','partial','full')),
- reason TEXT NOT NULL,
- decided_by TEXT,
- source_suggestion JSONB
-);
-CREATE INDEX IF NOT EXISTS idx_refund_decisions_order_id ON {REFUNDS_TABLE}(order_id);
-"""
-
-@app.on_event("startup")
-def _startup():
- with engine.begin() as conn:
- conn.exec_driver_sql(DDL)
-
-# βββ Static SPA βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-@app.get("/")
-def index():
- path = Path(__file__).parent.parent / "index.html"
- if not path.exists():
- raise HTTPException(status_code=404, detail="index.html not found")
- return FileResponse(str(path))
-
-# βββ Summary (robust to bad JSON) ββββββββββββββββββββββββββββββββββββββββββββ
-@app.get("/api/summary")
-def summary(include_zero: bool = False):
- suggestions_by_class = Counter()
- suggested_total = 0.0
- filtered_count = 0
-
- with engine.connect() as conn:
- total = conn.exec_driver_sql(f"SELECT COUNT(*) FROM {RECS_TABLE}").scalar_one()
-
- # Pull raw strings and parse safely
- rows = conn.execute(text(f"""
- SELECT agent_response
- FROM {RECS_TABLE}
- WHERE agent_response IS NOT NULL
- """)).fetchall()
-
- for (raw,) in rows:
- sug = parse_agent_response(raw)
- cls = sug.get("refund_class", "error")
- refund_usd = sug.get("refund_usd", 0)
-
- # Filter out zero-dollar recommendations unless include_zero is True
- if not include_zero and refund_usd == 0:
- continue
-
- filtered_count += 1
- suggestions_by_class[cls] += 1
- if cls != "error":
- try:
- suggested_total += float(refund_usd or 0)
- except Exception:
- pass
-
- # Decisions summary (always show all decisions)
- decisions_total = conn.exec_driver_sql(f"SELECT COUNT(*) FROM {REFUNDS_TABLE}").scalar_one()
- decided_total_usd = conn.exec_driver_sql(f"SELECT COALESCE(SUM(amount_usd),0) FROM {REFUNDS_TABLE}").scalar_one()
- dec_by_class_rows = conn.execute(text(f"""
- SELECT refund_class, COUNT(*) AS c
- FROM {REFUNDS_TABLE}
- GROUP BY refund_class
- """)).mappings().all()
- decisions_by_class = {r["refund_class"]: r["c"] for r in dec_by_class_rows}
-
- return {
- "recommendations_count": filtered_count,
- "total_recommendations": total,
- "suggestions_by_class": dict(suggestions_by_class),
- "suggested_total_usd": round(suggested_total, 2),
- "decisions_count": decisions_total,
- "decisions_by_class": decisions_by_class,
- "decided_total_usd": float(decided_total_usd or 0),
- "pending_count": max(filtered_count - decisions_total, 0),
- }
-
-# βββ Recommendations list (robust suggestions) βββββββββββββββββββββββββββββββ
-@app.get("/api/recommendations")
-def list_recommendations(limit: int = 50, offset: int = 0, include_zero: bool = False):
- with engine.connect() as conn:
- # Fetch a larger batch to account for filtering
- # We fetch enough to ensure we can fill the page after filtering
- # Using a multiplier to handle the case where many rows are filtered out
- fetch_limit = 1000 if not include_zero else limit + offset + 100
-
- all_recs = conn.execute(
- text(f"""
- SELECT order_id, ts, order_ts, agent_response
- FROM {RECS_TABLE}
- ORDER BY order_ts DESC, order_id DESC
- LIMIT :fetch_limit
- """),
- {"fetch_limit": fetch_limit},
- ).mappings().all()
-
- # Parse and filter recommendations
- filtered_recs = []
- for r in all_recs:
- sug = parse_agent_response(r["agent_response"])
- refund_usd = sug.get("refund_usd", 0)
-
- # Skip zero-dollar recommendations unless include_zero is True
- if not include_zero and refund_usd == 0:
- continue
-
- filtered_recs.append({
- "order_id": r["order_id"],
- "ts": r["ts"],
- "order_ts": r["order_ts"],
- "agent_response": r["agent_response"],
- "suggestion": sug,
- })
-
- # Apply pagination to filtered results
- total_filtered = len(filtered_recs)
- paginated_recs = filtered_recs[offset:offset + limit]
-
- # Fetch decisions for the paginated results
- dec_map: Dict[str, Any] = {}
- if paginated_recs:
- order_ids = [r["order_id"] for r in paginated_recs]
- decs = conn.execute(
- text(f"""
- SELECT DISTINCT ON (order_id)
- order_id, id, decided_ts, amount_usd, refund_class, reason, decided_by
- FROM {REFUNDS_TABLE}
- WHERE order_id IN :ids
- ORDER BY order_id, decided_ts DESC
- """).bindparams(bindparam("ids", expanding=True)),
- {"ids": tuple(order_ids)},
- ).mappings().all()
- dec_map = {d["order_id"]: d for d in decs}
-
- items: List[Dict[str, Any]] = []
- for r in paginated_recs:
- items.append({
- "order_id": r["order_id"],
- "ts": r["ts"],
- "order_ts": r["order_ts"],
- "suggestion": r["suggestion"], # will be ERROR_SUGGESTION for bad rows
- "decision": dec_map.get(r["order_id"]) or None,
- "status": "applied" if r["order_id"] in dec_map else "pending",
- })
-
- return {
- "items": items,
- "limit": limit,
- "offset": offset,
- "total": total_filtered,
- "has_more": offset + limit < total_filtered,
- }
-
-# βββ Apply refund ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-@app.post("/api/refunds")
-def apply_refund(body: RefundDecisionCreate):
- with engine.begin() as conn:
- # latest suggestion (robust parse)
- sug_row = conn.execute(
- text(f"""
- SELECT agent_response
- FROM "{RECS_SCHEMA}".pg_recommendations
- WHERE order_id = :oid
- ORDER BY ts DESC, order_ts DESC
- LIMIT 1
- """),
- {"oid": body.order_id},
- ).mappings().first()
-
- from .models import parse_agent_response, ERROR_SUGGESTION # if not already imported at top
- source_suggestion = parse_agent_response(sug_row["agent_response"]) if sug_row else dict(ERROR_SUGGESTION)
-
- row = conn.execute(
- text(f"""
- INSERT INTO "{REFUNDS_SCHEMA}".refund_decisions
- (order_id, amount_usd, refund_class, reason, decided_by, source_suggestion)
- VALUES
- (:order_id, :amount_usd, :refund_class, :reason, :decided_by, CAST(:source_suggestion AS JSONB))
- RETURNING id, decided_ts
- """),
- {
- "order_id": body.order_id,
- "amount_usd": body.amount_usd,
- "refund_class": body.refund_class,
- "reason": body.reason,
- "decided_by": body.decided_by,
- "source_suggestion": json.dumps(source_suggestion),
- },
- ).mappings().first()
-
- return JSONResponse({
- "id": row["id"],
- "order_id": body.order_id,
- "decided_ts": str(row["decided_ts"]),
- "amount_usd": body.amount_usd,
- "refund_class": body.refund_class,
- "reason": body.reason,
- "decided_by": body.decided_by,
- }, status_code=201)
-
-# βββ Order events (Databricks SQL) βββββββββββββββββββββββββββββββββββββββββββ
-@app.get("/api/orders/{order_id}/events")
-def order_events(order_id: str, debug: int = 0):
- try:
- events = fetch_order_events(order_id)
- return {"order_id": order_id, "events": events}
- except Exception as e:
- log.exception("order_events failed for %s", order_id)
- if DEBUG or debug:
- return JSONResponse(
- status_code=500,
- content={
- "error": "databricks_statement_failed",
- "message": str(e),
- "traceback": traceback.format_exc(),
- },
- )
- raise HTTPException(status_code=500, detail="Databricks SQL query failed")
-
-# βββ Health ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-@app.get("/healthz")
-def healthz():
- with engine.connect() as conn:
- conn.exec_driver_sql("SELECT 1")
- return {"ok": True}
diff --git a/apps/refund-manager/app/models.py b/apps/refund-manager/app/models.py
deleted file mode 100644
index 3435022..0000000
--- a/apps/refund-manager/app/models.py
+++ /dev/null
@@ -1,80 +0,0 @@
-# app/models.py
-from typing import Any, Dict, Optional
-from pydantic import BaseModel, Field, validator
-import json
-import math
-
-ERROR_SUGGESTION: Dict[str, Any] = {
- "refund_usd": 0.0,
- "refund_class": "error",
- "reason": "agent did not return valid JSON",
-}
-
-ALLOWED_CLASSES = {"none", "partial", "full"}
-
-class RefundDecisionCreate(BaseModel):
- order_id: str
- amount_usd: float = Field(ge=0)
- refund_class: str
- reason: str
- decided_by: Optional[str] = None
-
- @validator("refund_class")
- def _class_ok(cls, v):
- if v not in {"none", "partial", "full"}:
- raise ValueError("refund_class must be one of {'none','partial','full'}")
- return v
-
-def _coerce_number(x: Any) -> Optional[float]:
- try:
- f = float(x)
- return f if math.isfinite(f) else None
- except Exception:
- return None
-
-def parse_agent_response(raw: Optional[str]) -> Dict[str, Any]:
- """
- Robustly parse/validate agent_response.
- - Accepts only JSON objects with the expected keys.
- - If invalid/malformed/missing keys or types => ERROR_SUGGESTION.
- - Tries a simple 'trim-to-last-}' recovery for trailing junk.
- """
- if not raw or not isinstance(raw, str):
- return dict(ERROR_SUGGESTION)
-
- s = raw.strip()
- # 1) try direct
- obj = None
- try:
- obj = json.loads(s)
- except Exception:
- # 2) quick recovery if there is trailing junk after the last }
- if "}" in s:
- try:
- obj = json.loads(s[: s.rfind("}") + 1])
- except Exception:
- obj = None
-
- if not isinstance(obj, dict):
- return dict(ERROR_SUGGESTION)
-
- # Validate fields
- cls = str(obj.get("refund_class", "")).lower()
- usd = _coerce_number(obj.get("refund_usd"))
- reason = obj.get("reason")
-
- if cls not in ALLOWED_CLASSES:
- # we mark invalid as error
- return dict(ERROR_SUGGESTION)
-
- if usd is None or usd < 0:
- # repair to 0 but keep class; however spec says on error use "error"
- # since JSON was malformed or types wrong, return error suggestion
- return dict(ERROR_SUGGESTION)
-
- # reason can be missing/empty; it's just a suggestion field, keep if present
- if not isinstance(reason, str):
- reason = ""
-
- # Valid suggestion
- return {"refund_usd": float(usd), "refund_class": cls, "reason": reason}
diff --git a/apps/refund-manager/index.html b/apps/refund-manager/index.html
deleted file mode 100644
index 59da43b..0000000
--- a/apps/refund-manager/index.html
+++ /dev/null
@@ -1,520 +0,0 @@
-
-
-
-
- Refund Manager
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Refund Manager
-
Internal Operations Dashboard
-
-
-
-
-
-
-
-
-
-
-
-
Recommendations
-
β
-
β
-
-
-
Suggested Total
-
β
-
USD
-
-
-
Decisions Made
-
β
-
β
-
-
-
Pending Review
-
β
-
Awaiting action
-
-
-
-
-
-
-
-
-
Orders & Suggestions
-
Review and apply refund recommendations
-
-
-
- pg_recommendations
-
-
-
-
-
-
-
- Filtered: >$0 only
-
-
-
-
-
-
-
- | Order ID |
- Suggested Refund |
- Reason |
- Status |
- Decision |
- Actions |
-
-
-
-
-
-
-
Latest recommendations shown first
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/apps/refund-manager/requirements.txt b/apps/refund-manager/requirements.txt
deleted file mode 100644
index 19ef92e..0000000
--- a/apps/refund-manager/requirements.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-fastapi
-uvicorn[standard]
-sqlalchemy
-psycopg[binary]
-databricks-sdk
-databricks-sql-connector
diff --git a/apps/supportconsolek/supportconsolek/.env.example b/apps/supportconsolek/supportconsolek/.env.example
new file mode 100644
index 0000000..bc164a3
--- /dev/null
+++ b/apps/supportconsolek/supportconsolek/.env.example
@@ -0,0 +1,4 @@
+DATABRICKS_HOST=https://...
+DATABRICKS_APP_PORT=8000
+DATABRICKS_APP_NAME=caspers-supportconsole
+FLASK_RUN_HOST=0.0.0.0
diff --git a/apps/supportconsolek/supportconsolek/.gitignore b/apps/supportconsolek/supportconsolek/.gitignore
new file mode 100644
index 0000000..f2abc32
--- /dev/null
+++ b/apps/supportconsolek/supportconsolek/.gitignore
@@ -0,0 +1,10 @@
+.DS_Store
+node_modules/
+client/dist/
+dist/
+build/
+.env
+.databricks/
+.smoke-test/
+test-results/
+playwright-report/
diff --git a/apps/supportconsolek/supportconsolek/.prettierignore b/apps/supportconsolek/supportconsolek/.prettierignore
new file mode 100644
index 0000000..7d3d77c
--- /dev/null
+++ b/apps/supportconsolek/supportconsolek/.prettierignore
@@ -0,0 +1,36 @@
+# Dependencies
+node_modules
+
+# Build outputs
+dist
+build
+client/dist
+.next
+.databricks/
+
+# Environment files
+.env
+.env.local
+.env.*.local
+
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# Coverage
+coverage
+
+# Cache
+.cache
+.turbo
+
+# Lock files
+package-lock.json
+yarn.lock
+pnpm-lock.yaml
+
+# Vendor
+vendor
diff --git a/apps/supportconsolek/supportconsolek/.prettierrc.json b/apps/supportconsolek/supportconsolek/.prettierrc.json
new file mode 100644
index 0000000..d95a63f
--- /dev/null
+++ b/apps/supportconsolek/supportconsolek/.prettierrc.json
@@ -0,0 +1,12 @@
+{
+ "semi": true,
+ "trailingComma": "es5",
+ "singleQuote": true,
+ "printWidth": 120,
+ "tabWidth": 2,
+ "useTabs": false,
+ "arrowParens": "always",
+ "endOfLine": "lf",
+ "bracketSpacing": true,
+ "jsxSingleQuote": false
+}
diff --git a/apps/supportconsolek/supportconsolek/CLAUDE.md b/apps/supportconsolek/supportconsolek/CLAUDE.md
new file mode 100644
index 0000000..69d5b13
--- /dev/null
+++ b/apps/supportconsolek/supportconsolek/CLAUDE.md
@@ -0,0 +1,10 @@
+# AI Assistant Instructions
+
+
+## Databricks AppKit
+
+This project uses Databricks AppKit packages. For AI assistant guidance on using these packages, refer to:
+
+- **@databricks/appkit** (Backend SDK): [./node_modules/@databricks/appkit/CLAUDE.md](./node_modules/@databricks/appkit/CLAUDE.md)
+- **@databricks/appkit-ui** (UI Integration, Charts, Tables, SSE, and more.): [./node_modules/@databricks/appkit-ui/CLAUDE.md](./node_modules/@databricks/appkit-ui/CLAUDE.md)
+
diff --git a/apps/supportconsolek/supportconsolek/README.md b/apps/supportconsolek/supportconsolek/README.md
new file mode 100644
index 0000000..faa012b
--- /dev/null
+++ b/apps/supportconsolek/supportconsolek/README.md
@@ -0,0 +1,189 @@
+# Minimal Databricks App
+
+A minimal Databricks App powered by Databricks AppKit, featuring React, TypeScript, tRPC, and Tailwind CSS.
+
+## Prerequisites
+
+- Node.js 18+ and npm
+- Databricks CLI (for deployment)
+- Access to a Databricks workspace
+
+## Databricks Authentication
+
+### Local Development
+
+For local development, configure your environment variables by creating a `.env` file:
+
+```bash
+cp env.example .env
+```
+
+Edit `.env` and set the following:
+
+```env
+DATABRICKS_HOST=https://your-workspace.cloud.databricks.com
+DATABRICKS_WAREHOUSE_ID=your-warehouse-id
+DATABRICKS_APP_PORT=8000
+```
+
+### CLI Authentication
+
+The Databricks CLI requires authentication to deploy and manage apps. Configure authentication using one of these methods:
+
+#### OAuth U2M
+
+Interactive browser-based authentication with short-lived tokens:
+
+```bash
+databricks auth login --host https://your-workspace.cloud.databricks.com
+```
+
+This will open your browser to complete authentication. The CLI saves credentials to `~/.databrickscfg`.
+
+#### Configuration Profiles
+
+Use multiple profiles for different workspaces:
+
+```ini
+[DEFAULT]
+host = https://dev-workspace.cloud.databricks.com
+
+[production]
+host = https://prod-workspace.cloud.databricks.com
+client_id = prod-client-id
+client_secret = prod-client-secret
+```
+
+Deploy using a specific profile:
+
+```bash
+databricks bundle deploy -t prod --profile production
+```
+
+**Note:** Personal Access Tokens (PATs) are legacy authentication. OAuth is strongly recommended for better security.
+
+## Getting Started
+
+### Install Dependencies
+
+```bash
+npm install
+```
+
+### Development
+
+Run the app in development mode with hot reload:
+
+```bash
+npm run dev
+```
+
+The app will be available at the URL shown in the console output.
+
+### Build
+
+Build both client and server for production:
+
+```bash
+npm run build
+```
+
+This creates:
+
+- `dist/server/` - Compiled server code
+- `client/dist/` - Bundled client assets
+
+### Production
+
+Run the production build:
+
+```bash
+npm start
+```
+
+## Code Quality
+
+```bash
+# Type checking
+npm run typecheck
+
+# Linting
+npm run lint
+npm run lint:fix
+
+# Formatting
+npm run format
+npm run format:fix
+```
+
+## Deployment with Databricks Asset Bundles
+
+### 1. Configure Bundle
+
+Update `databricks.yml` with your workspace settings:
+
+```yaml
+targets:
+ dev:
+ workspace:
+ host: https://your-workspace.cloud.databricks.com
+ variables:
+ warehouse_id: your-warehouse-id
+```
+
+### 2. Validate Bundle
+
+```bash
+databricks bundle validate
+```
+
+### 3. Deploy
+
+Deploy to the development target:
+
+```bash
+databricks bundle deploy -t dev
+```
+
+### 4. Run
+
+Start the deployed app:
+
+```bash
+databricks bundle run -t dev
+```
+
+## Support Console Runtime Notes
+
+- The server uses the AppKit Lakebase plugin (`lakebase()`) and `createLakebasePool()` from `@databricks/appkit` for connection management.
+- Ensure the app service principal has schema/table ownership and grants on Lakebase schemas used by the app (`public` and `support` in this project).
+- Support evals are run as a separate Databricks job (`Support Response Evals Hourly`) and are not required for app startup.
+
+### Deploy to Production
+
+1. Configure the production target in `databricks.yml`
+2. Deploy to production:
+
+```bash
+databricks bundle deploy -t prod
+```
+
+## Project Structure
+
+```
+* client/ # React frontend
+ * src/ # Source code
+ * public/ # Static assets
+* server/ # Express backend
+ * server.ts # Server entry point
+ * trpc.ts # tRPC router
+* shared/ # Shared types
+* databricks.yml # Bundle configuration
+```
+
+## Tech Stack
+
+- **Frontend**: React 19, TypeScript, Vite, Tailwind CSS
+- **Backend**: Node.js, Express, tRPC
+- **UI Components**: Radix UI, shadcn/ui
+- **Databricks**: App Kit SDK, Analytics SDK
diff --git a/apps/supportconsolek/supportconsolek/app.yaml b/apps/supportconsolek/supportconsolek/app.yaml
new file mode 100644
index 0000000..95576a0
--- /dev/null
+++ b/apps/supportconsolek/supportconsolek/app.yaml
@@ -0,0 +1,14 @@
+command: ['npm', 'run', 'start']
+env:
+ - name: PGPORT
+ value: "5432"
+ - name: PGDATABASE
+ value: "databricks_postgres"
+ - name: PGSSLMODE
+ value: "require"
+ - name: LAKEBASE_ENDPOINT
+ value: "projects/casperskitchens-support-db/branches/production/endpoints/primary"
+ - name: DATABRICKS_WAREHOUSE_ID
+ value: "e5ed18828056f3cf"
+ - name: SUPPORT_AGENT_ENDPOINT_NAME
+ value: "caspers_support_agent"
\ No newline at end of file
diff --git a/apps/supportconsolek/supportconsolek/appkit.plugins.json b/apps/supportconsolek/supportconsolek/appkit.plugins.json
new file mode 100644
index 0000000..67f3874
--- /dev/null
+++ b/apps/supportconsolek/supportconsolek/appkit.plugins.json
@@ -0,0 +1,41 @@
+{
+ "$schema": "https://databricks.github.io/appkit/schemas/template-plugins.schema.json",
+ "version": "1.0",
+ "plugins": {
+ "analytics": {
+ "name": "analytics",
+ "displayName": "Analytics Plugin",
+ "description": "SQL query execution against Databricks SQL Warehouses",
+ "package": "@databricks/appkit",
+ "resources": {
+ "required": [
+ {
+ "type": "sql_warehouse",
+ "alias": "SQL Warehouse",
+ "resourceKey": "sql-warehouse",
+ "description": "SQL Warehouse for executing analytics queries",
+ "permission": "CAN_USE",
+ "fields": {
+ "id": {
+ "env": "DATABRICKS_WAREHOUSE_ID",
+ "description": "SQL Warehouse ID"
+ }
+ }
+ }
+ ],
+ "optional": []
+ }
+ },
+ "server": {
+ "name": "server",
+ "displayName": "Server Plugin",
+ "description": "HTTP server with Express, static file serving, and Vite dev mode support",
+ "package": "@databricks/appkit",
+ "requiredByTemplate": true,
+ "resources": {
+ "required": [],
+ "optional": []
+ }
+ }
+ }
+}
diff --git a/apps/supportconsolek/supportconsolek/client/components.json b/apps/supportconsolek/supportconsolek/client/components.json
new file mode 100644
index 0000000..13e1db0
--- /dev/null
+++ b/apps/supportconsolek/supportconsolek/client/components.json
@@ -0,0 +1,21 @@
+{
+ "$schema": "https://ui.shadcn.com/schema.json",
+ "style": "new-york",
+ "rsc": false,
+ "tsx": true,
+ "tailwind": {
+ "config": "",
+ "css": "src/index.css",
+ "baseColor": "neutral",
+ "cssVariables": true,
+ "prefix": ""
+ },
+ "aliases": {
+ "components": "@/components",
+ "utils": "@/lib/utils",
+ "ui": "@/components/ui",
+ "lib": "@/lib",
+ "hooks": "@/hooks"
+ },
+ "iconLibrary": "lucide"
+}
diff --git a/apps/supportconsolek/supportconsolek/client/index.html b/apps/supportconsolek/supportconsolek/client/index.html
new file mode 100644
index 0000000..26f3416
--- /dev/null
+++ b/apps/supportconsolek/supportconsolek/client/index.html
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+ caspers-supportconsole
+
+
+
+
+
+
diff --git a/apps/supportconsolek/supportconsolek/client/postcss.config.js b/apps/supportconsolek/supportconsolek/client/postcss.config.js
new file mode 100644
index 0000000..51a6e4e
--- /dev/null
+++ b/apps/supportconsolek/supportconsolek/client/postcss.config.js
@@ -0,0 +1,6 @@
+export default {
+ plugins: {
+ '@tailwindcss/postcss': {},
+ autoprefixer: {},
+ },
+};
diff --git a/apps/supportconsolek/supportconsolek/client/public/apple-touch-icon.png b/apps/supportconsolek/supportconsolek/client/public/apple-touch-icon.png
new file mode 100644
index 0000000..32053bd
Binary files /dev/null and b/apps/supportconsolek/supportconsolek/client/public/apple-touch-icon.png differ
diff --git a/apps/supportconsolek/supportconsolek/client/public/favicon-16x16.png b/apps/supportconsolek/supportconsolek/client/public/favicon-16x16.png
new file mode 100644
index 0000000..d7c16eb
Binary files /dev/null and b/apps/supportconsolek/supportconsolek/client/public/favicon-16x16.png differ
diff --git a/apps/supportconsolek/supportconsolek/client/public/favicon-192x192.png b/apps/supportconsolek/supportconsolek/client/public/favicon-192x192.png
new file mode 100644
index 0000000..8b4f18d
Binary files /dev/null and b/apps/supportconsolek/supportconsolek/client/public/favicon-192x192.png differ
diff --git a/apps/supportconsolek/supportconsolek/client/public/favicon-32x32.png b/apps/supportconsolek/supportconsolek/client/public/favicon-32x32.png
new file mode 100644
index 0000000..46aa684
Binary files /dev/null and b/apps/supportconsolek/supportconsolek/client/public/favicon-32x32.png differ
diff --git a/apps/supportconsolek/supportconsolek/client/public/favicon-48x48.png b/apps/supportconsolek/supportconsolek/client/public/favicon-48x48.png
new file mode 100644
index 0000000..d2f89fb
Binary files /dev/null and b/apps/supportconsolek/supportconsolek/client/public/favicon-48x48.png differ
diff --git a/apps/supportconsolek/supportconsolek/client/public/favicon-512x512.png b/apps/supportconsolek/supportconsolek/client/public/favicon-512x512.png
new file mode 100644
index 0000000..14d7d20
Binary files /dev/null and b/apps/supportconsolek/supportconsolek/client/public/favicon-512x512.png differ
diff --git a/apps/supportconsolek/supportconsolek/client/public/favicon.svg b/apps/supportconsolek/supportconsolek/client/public/favicon.svg
new file mode 100644
index 0000000..cb30c1e
--- /dev/null
+++ b/apps/supportconsolek/supportconsolek/client/public/favicon.svg
@@ -0,0 +1,6 @@
+
diff --git a/apps/supportconsolek/supportconsolek/client/public/site.webmanifest b/apps/supportconsolek/supportconsolek/client/public/site.webmanifest
new file mode 100644
index 0000000..03106ce
--- /dev/null
+++ b/apps/supportconsolek/supportconsolek/client/public/site.webmanifest
@@ -0,0 +1,19 @@
+{
+ "name": "{{.project_name}}",
+ "short_name": "{{.project_name}}",
+ "icons": [
+ {
+ "src": "/favicon-192x192.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ },
+ {
+ "src": "/favicon-512x512.png",
+ "sizes": "512x512",
+ "type": "image/png"
+ }
+ ],
+ "theme_color": "#ffffff",
+ "background_color": "#ffffff",
+ "display": "standalone"
+}
diff --git a/apps/supportconsolek/supportconsolek/client/src/App.tsx b/apps/supportconsolek/supportconsolek/client/src/App.tsx
new file mode 100644
index 0000000..aa5ea08
--- /dev/null
+++ b/apps/supportconsolek/supportconsolek/client/src/App.tsx
@@ -0,0 +1,860 @@
+/**
+ * β οΈ BEFORE MODIFYING THIS FILE:
+ *
+ * 1. Create SQL files in config/queries/
+ * 2. Run `npm run typegen` to generate query types
+ * 3. Check appKitTypes.d.ts for available types
+ *
+ * Common Mistakes:
+ * - DataTable does NOT accept `data` or `columns` props
+ * - Charts use `xKey` and `yKey`, NOT `seriesKey`/`nameKey`/`valueKey`
+ * - useAnalyticsQuery has no `enabled` option - use conditional rendering
+ */
+import { useEffect, useRef, useState } from "react";
+import {
+ Badge,
+ Button,
+ Card,
+ CardContent,
+ CardHeader,
+ CardTitle,
+ Input,
+ Sheet,
+ SheetClose,
+ SheetContent,
+ SheetDescription,
+ SheetFooter,
+ SheetHeader,
+ SheetTitle,
+ Textarea,
+} from "@databricks/appkit-ui/react";
+import { Toaster, toast } from "sonner";
+
+type Summary = { requests: number; actions: number; replies: number };
+
+type Recommendation = {
+ amount_usd?: number | null;
+ reason?: string;
+};
+
+type Report = {
+ draft_response?: string;
+ past_interactions_summary?: string;
+ order_details_summary?: string;
+ decision_confidence?: string;
+ escalation_flag?: boolean;
+ refund_recommendation?: Recommendation | null;
+ credit_recommendation?: Recommendation | null;
+};
+
+type CaseState = {
+ case_status: "pending" | "in_progress" | "done" | "blocked";
+ next_action: string;
+ has_reply: boolean;
+ has_refund: boolean;
+ has_credit: boolean;
+ action_count: number;
+ reply_count: number;
+ regen_count: number;
+ last_action_type?: string | null;
+ last_event_at?: string | null;
+ latest_report_source?: string | null;
+};
+
+type TimelineEvent = {
+ event_type: string;
+ event_at: string;
+ actor?: string | null;
+ details?: Record;
+};
+
+type RegenerationItem = {
+ regenerated_report_id: number;
+ operator_context?: string | null;
+ actor?: string | null;
+ created_at: string;
+ report: Report;
+};
+
+type ResponseRating = {
+ rating_id: number;
+ rating: "thumbs_up" | "thumbs_down";
+ reason_code?: string | null;
+ feedback_notes?: string | null;
+ actor?: string | null;
+ created_at: string;
+};
+
+type RequestItem = {
+ support_request_id: string;
+ user_id: string;
+ user_display_name?: string | null;
+ order_id: string;
+ ts: string;
+ request_text?: string | null;
+ report: Report;
+ case_state?: CaseState;
+};
+
+type RequestDetails = RequestItem & {
+ actions: Array>;
+ replies: Array>;
+ ratings?: ResponseRating[];
+ latest_rating?: ResponseRating | null;
+ regenerations?: RegenerationItem[];
+ timeline?: TimelineEvent[];
+};
+
+type NoticeState = {
+ kind: "success" | "error";
+ message: string;
+ supportRequestId?: string;
+} | null;
+
+const RATING_REASON_OPTIONS: Array<{ value: string; label: string }> = [
+ { value: "incorrect_facts", label: "Incorrect facts in response" },
+ { value: "wrong_refund_amount", label: "Wrong refund amount" },
+ { value: "wrong_credit_amount", label: "Wrong credit amount" },
+ { value: "should_escalate", label: "Should have escalated" },
+ { value: "should_not_escalate", label: "Should not have escalated" },
+ { value: "poor_tone", label: "Poor tone or wording" },
+ { value: "unclear_response", label: "Unclear or incomplete response" },
+ { value: "other", label: "Other" },
+];
+
+function App() {
+ const PAGE_SIZE = 50;
+ const [summary, setSummary] = useState(null);
+ const [requests, setRequests] = useState([]);
+ const [totalRequests, setTotalRequests] = useState(0);
+ const [currentPage, setCurrentPage] = useState(1);
+ const [selected, setSelected] = useState(null);
+ const [replyText, setReplyText] = useState("");
+ const [operatorContext, setOperatorContext] = useState("");
+ const [actor, setActor] = useState("");
+ const [refundAmount, setRefundAmount] = useState("");
+ const [creditAmount, setCreditAmount] = useState("");
+ const [ratingChoice, setRatingChoice] = useState<"thumbs_up" | "thumbs_down">("thumbs_up");
+ const [ratingReason, setRatingReason] = useState("");
+ const [ratingNotes, setRatingNotes] = useState("");
+ const [loading, setLoading] = useState(false);
+ const [detailsLoading, setDetailsLoading] = useState(false);
+ const [isDrawerOpen, setIsDrawerOpen] = useState(false);
+ const [pendingAction, setPendingAction] = useState<"apply_refund" | "apply_credit" | "send_reply" | "regenerate" | "rate_response" | null>(null);
+ const [notice, setNotice] = useState(null);
+ const [error, setError] = useState(null);
+ const drawerScrollRef = useRef(null);
+
+ useEffect(() => {
+ void refresh();
+ }, [currentPage]);
+
+ const formatCurrency = (value?: number | null) =>
+ typeof value === "number" ? `$${value.toFixed(2)}` : "No recommendation";
+
+ const formatTs = (value: string) => {
+ const date = new Date(value);
+ if (Number.isNaN(date.getTime())) {
+ return "Recent";
+ }
+ return date.toLocaleString();
+ };
+
+ const statusLabel = (status: CaseState["case_status"] | undefined) => {
+ if (status === "done") return "Done";
+ if (status === "in_progress") return "In Progress";
+ if (status === "blocked") return "Blocked";
+ return "Pending";
+ };
+
+ const statusVariant = (status: CaseState["case_status"] | undefined): "default" | "secondary" | "outline" => {
+ if (status === "done") return "default";
+ if (status === "in_progress") return "secondary";
+ return "outline";
+ };
+
+ const nextActionLabel = (nextAction: string | undefined) => {
+ const mapping: Record = {
+ review_report: "Review report",
+ apply_resolution_or_regenerate: "Apply resolution or re-gen",
+ send_customer_reply: "Send customer reply",
+ monitor: "Monitor case",
+ investigate_blocker: "Investigate blocker",
+ continue_investigation: "Continue investigation",
+ };
+ return mapping[nextAction ?? ""] ?? "Review report";
+ };
+
+ const suggestedRefund = selected?.report?.refund_recommendation?.amount_usd ?? null;
+ const suggestedCredit = selected?.report?.credit_recommendation?.amount_usd ?? null;
+ const selectedCaseState = selected?.case_state;
+ const latestRating = selected?.latest_rating;
+ const latestRatingLabel = latestRating?.rating === "thumbs_up"
+ ? "Agent Rating: Thumbs Up"
+ : latestRating?.rating === "thumbs_down"
+ ? "Agent Rating: Thumbs Down"
+ : "Agent Rating: Not rated";
+
+ const appliedRefund = selected?.actions.find((a) => a.action_type === "apply_refund");
+ const appliedCredit = selected?.actions.find((a) => a.action_type === "apply_credit");
+
+ const parseErrorMessage = async (res: Response): Promise => {
+ try {
+ const body = (await res.json()) as { message?: string; error?: string };
+ return body.message || body.error || `Request failed (${res.status})`;
+ } catch {
+ return `Request failed (${res.status})`;
+ }
+ };
+
+ const showNotice = (nextNotice: Exclude) => {
+ setNotice(nextNotice);
+ if (nextNotice.kind === "success") {
+ toast.success(nextNotice.message);
+ } else {
+ toast.error(nextNotice.message);
+ }
+ };
+
+ const refresh = async () => {
+ setLoading(true);
+ setError(null);
+ try {
+ const offset = (currentPage - 1) * PAGE_SIZE;
+ const [summaryRes, reqRes] = await Promise.all([
+ fetch("/api/support/summary"),
+ fetch(`/api/support/requests?limit=${PAGE_SIZE}&offset=${offset}`),
+ ]);
+ if (!summaryRes.ok || !reqRes.ok) {
+ throw new Error("Failed to load support data");
+ }
+ const summaryJson = (await summaryRes.json()) as Summary;
+ const reqJson = (await reqRes.json()) as { items?: RequestItem[]; total?: number };
+ setSummary(summaryJson);
+ setRequests(reqJson.items || []);
+ setTotalRequests(reqJson.total ?? 0);
+ } catch (e) {
+ setError(e instanceof Error ? e.message : String(e));
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ const openDetails = async (
+ supportRequestId: string,
+ options?: { showLoading?: boolean; preserveScroll?: boolean },
+ ) => {
+ const showLoading = options?.showLoading ?? true;
+ const preserveScroll = options?.preserveScroll ?? false;
+ const previousScrollTop = preserveScroll ? drawerScrollRef.current?.scrollTop ?? 0 : 0;
+ setIsDrawerOpen(true);
+ if (showLoading) {
+ setDetailsLoading(true);
+ }
+ setNotice((prev) => (prev?.supportRequestId === supportRequestId ? prev : null));
+ try {
+ const res = await fetch(`/api/support/requests/${supportRequestId}`);
+ if (!res.ok) {
+ throw new Error("Failed to load request details");
+ }
+ const json = (await res.json()) as RequestDetails;
+ setSelected(json);
+ setReplyText(json?.report?.draft_response ?? "");
+ setRefundAmount(
+ typeof json?.report?.refund_recommendation?.amount_usd === "number"
+ ? String(json.report.refund_recommendation.amount_usd)
+ : "",
+ );
+ setCreditAmount(
+ typeof json?.report?.credit_recommendation?.amount_usd === "number"
+ ? String(json.report.credit_recommendation.amount_usd)
+ : "",
+ );
+ setRatingChoice(json?.latest_rating?.rating === "thumbs_down" ? "thumbs_down" : "thumbs_up");
+ setRatingReason(json?.latest_rating?.reason_code ?? "");
+ setRatingNotes(json?.latest_rating?.feedback_notes ?? "");
+ setError(null);
+ if (preserveScroll) {
+ requestAnimationFrame(() => {
+ if (drawerScrollRef.current) {
+ drawerScrollRef.current.scrollTop = previousScrollTop;
+ }
+ });
+ }
+ return true;
+ } catch (e) {
+ setError(e instanceof Error ? e.message : String(e));
+ return false;
+ } finally {
+ if (showLoading) {
+ setDetailsLoading(false);
+ }
+ }
+ };
+
+ const totalPages = Math.max(1, Math.ceil(totalRequests / PAGE_SIZE));
+
+ const applyAction = async (actionType: "apply_refund" | "apply_credit", amount: string) => {
+ if (!selected) return;
+ if (!amount || Number.isNaN(Number(amount))) return;
+ setPendingAction(actionType);
+ setNotice(null);
+ try {
+ const res = await fetch("/api/support/actions", {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify({
+ support_request_id: selected.support_request_id,
+ order_id: selected.order_id,
+ user_id: selected.user_id,
+ action_type: actionType,
+ amount_usd: Number(amount),
+ actor: actor || null,
+ payload: { source: "appkit-ui" },
+ }),
+ });
+ if (!res.ok) {
+ throw new Error(await parseErrorMessage(res));
+ }
+ showNotice({
+ kind: "success",
+ message: actionType === "apply_credit" ? "Credits applied successfully." : "Refund applied successfully.",
+ supportRequestId: selected.support_request_id,
+ });
+ await openDetails(selected.support_request_id, { showLoading: false, preserveScroll: true });
+ await refresh();
+ } catch (e) {
+ showNotice({
+ kind: "error",
+ message: e instanceof Error ? e.message : String(e),
+ });
+ } finally {
+ setPendingAction(null);
+ }
+ };
+
+ const sendReply = async () => {
+ if (!selected) return;
+ setPendingAction("send_reply");
+ setNotice(null);
+ try {
+ const res = await fetch("/api/support/replies", {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify({
+ support_request_id: selected.support_request_id,
+ order_id: selected.order_id,
+ user_id: selected.user_id,
+ message_text: replyText,
+ sent_by: actor || null,
+ }),
+ });
+ if (!res.ok) {
+ throw new Error(await parseErrorMessage(res));
+ }
+ showNotice({
+ kind: "success",
+ message: "Reply sent successfully.",
+ supportRequestId: selected.support_request_id,
+ });
+ await openDetails(selected.support_request_id, { showLoading: false, preserveScroll: true });
+ await refresh();
+ } catch (e) {
+ showNotice({
+ kind: "error",
+ message: e instanceof Error ? e.message : String(e),
+ });
+ } finally {
+ setPendingAction(null);
+ }
+ };
+
+ const regenerateReport = async () => {
+ if (!selected) return;
+ setPendingAction("regenerate");
+ setNotice(null);
+ try {
+ const res = await fetch("/api/support/regenerate", {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify({
+ support_request_id: selected.support_request_id,
+ order_id: selected.order_id,
+ user_id: selected.user_id,
+ actor: actor || null,
+ operator_context: operatorContext || null,
+ current_report: selected.report,
+ }),
+ });
+ if (!res.ok) {
+ throw new Error(await parseErrorMessage(res));
+ }
+ const body = (await res.json()) as { warning?: string };
+ showNotice({
+ kind: "success",
+ message: body.warning
+ ? `Report regenerated with fallback. ${body.warning}`
+ : "Report regenerated with operator context.",
+ supportRequestId: selected.support_request_id,
+ });
+ await openDetails(selected.support_request_id, { showLoading: false, preserveScroll: true });
+ await refresh();
+ } catch (e) {
+ showNotice({
+ kind: "error",
+ message: e instanceof Error ? e.message : String(e),
+ });
+ } finally {
+ setPendingAction(null);
+ }
+ };
+
+ const submitRating = async () => {
+ if (!selected) return;
+ setPendingAction("rate_response");
+ setNotice(null);
+ try {
+ const res = await fetch("/api/support/ratings", {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify({
+ support_request_id: selected.support_request_id,
+ order_id: selected.order_id,
+ user_id: selected.user_id,
+ rating: ratingChoice,
+ reason_code: ratingReason || null,
+ feedback_notes: ratingNotes || null,
+ actor: actor || null,
+ }),
+ });
+ if (!res.ok) {
+ throw new Error(await parseErrorMessage(res));
+ }
+ showNotice({
+ kind: "success",
+ message: "Agent response rating saved.",
+ supportRequestId: selected.support_request_id,
+ });
+ await openDetails(selected.support_request_id, { showLoading: false, preserveScroll: true });
+ await refresh();
+ } catch (e) {
+ showNotice({
+ kind: "error",
+ message: e instanceof Error ? e.message : String(e),
+ });
+ } finally {
+ setPendingAction(null);
+ }
+ };
+
+ return (
+
+
+
+
+
Support Console
+
+ Triage support requests, review agent analysis, and take operator actions.
+
+
+
+
+
+ {error && (
+
+ Error: {error}
+
+ )}
+
+
+
+
+ Requests
+
+
+ {summary?.requests ?? "-"}
+
+
+
+
+ Actions
+
+
+ {summary?.actions ?? "-"}
+
+
+
+
+ Replies
+
+
+ {summary?.replies ?? "-"}
+
+
+
+
+
+
+
+ Support Requests
+
+
+ {loading && requests.length === 0 && (
+ <>
+ {Array.from({ length: 4 }).map((_, idx) => (
+
+ ))}
+ >
+ )}
+ {requests.length === 0 && (
+
+ No support requests yet.
+
+ )}
+ {requests.map((r) => {
+ const previewSource =
+ r.report?.draft_response ||
+ r.report?.order_details_summary ||
+ "Support request ready for review.";
+ const preview = previewSource.replace(/\s+/g, " ").trim();
+ return (
+
+
+
+
+ {r.user_display_name ?? "Customer"}
+
+
+ {statusLabel(r.case_state?.case_status)}
+
+
+ Next: {nextActionLabel(r.case_state?.next_action)}
+
+ {r.case_state?.has_reply &&
Replied}
+ {r.case_state?.has_refund &&
Refund Applied}
+ {r.case_state?.has_credit &&
Credits Applied}
+
+ Refund: {formatCurrency(r.report?.refund_recommendation?.amount_usd)}
+
+
+ Credit: {formatCurrency(r.report?.credit_recommendation?.amount_usd)}
+
+
+
+ Updated {formatTs(r.case_state?.last_event_at ?? r.ts)}
+
+ Replies {r.case_state?.reply_count ?? 0}
+
+
+ Actions {r.case_state?.action_count ?? 0}
+
+
+ Re-gens {r.case_state?.regen_count ?? 0}
+
+
+
{preview}
+
+
+
+ );
+ })}
+
+
+ Page {currentPage} of {totalPages}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Request Details
+
+ Review agent analysis and take operator actions for the selected support case.
+
+
+
+ {notice && (
+
+
+ {notice.message}
+
+
+ )}
+ {detailsLoading &&
Loading request details...
}
+ {!detailsLoading && !selected && (
+
Select a request from the list.
+ )}
+ {!detailsLoading && selected && (
+ <>
+
+
+ {selected.user_display_name ?? "Customer"}
+
+ Updated: {formatTs(selectedCaseState?.last_event_at ?? selected.ts)}
+
+
+ Confidence: {selected.report?.decision_confidence ?? "unknown"}
+
+
+ {statusLabel(selectedCaseState?.case_status)}
+
+
+
+
+
History
+
+
+ Current Status: {statusLabel(selectedCaseState?.case_status)}
+
+ Next: {nextActionLabel(selectedCaseState?.next_action)}
+ Last Action: {selectedCaseState?.last_action_type ?? "none"}
+ {latestRatingLabel}
+
+
+ {(selected.timeline ?? []).slice(0, 8).map((event, idx) => (
+
+
{event.event_type.replaceAll("_", " ")}
+
+ {formatTs(event.event_at)}{event.actor ? ` Β· ${event.actor}` : ""}
+
+
+ ))}
+ {(selected.timeline ?? []).length === 0 && (
+
No activity yet.
+ )}
+
+
+
+
+
Support Request & Actions
+
+
Raw Support Message
+
+ {selected.request_text || "Raw support message not available for this request yet."}
+
+
+
+
Suggested Agent Response
+
+
+
setActor(e.target.value)} />
+
+
+
+
+
+
setRefundAmount(e.target.value)}
+ disabled={Boolean(appliedRefund) || pendingAction !== null}
+ />
+
+
+
+
+
+
setCreditAmount(e.target.value)}
+ disabled={Boolean(appliedCredit) || pendingAction !== null}
+ />
+
+
+
+
+
+ Suggested refund: {formatCurrency(selected.report?.refund_recommendation?.amount_usd)} Β· Suggested credit: {formatCurrency(selected.report?.credit_recommendation?.amount_usd)}
+
+
+
+
+
Re-Generate Agent
+
+
+
+
Rate Agent
+
+
Agent Draft
+
{selected.report?.draft_response || "No draft response"}
+
+ Refund: {formatCurrency(selected.report?.refund_recommendation?.amount_usd)} Β· Credit: {formatCurrency(selected.report?.credit_recommendation?.amount_usd)}
+
+
+
+
+
+
+
+
+
+
+ >
+ )}
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export default App;
diff --git a/apps/supportconsolek/supportconsolek/client/src/ErrorBoundary.tsx b/apps/supportconsolek/supportconsolek/client/src/ErrorBoundary.tsx
new file mode 100644
index 0000000..6a73c26
--- /dev/null
+++ b/apps/supportconsolek/supportconsolek/client/src/ErrorBoundary.tsx
@@ -0,0 +1,75 @@
+import React, { Component } from 'react';
+import type { ReactNode } from 'react';
+import { Card, CardContent, CardHeader, CardTitle } from '@databricks/appkit-ui/react';
+
+interface Props {
+ children: ReactNode;
+}
+
+interface State {
+ hasError: boolean;
+ error: Error | null;
+ errorInfo: React.ErrorInfo | null;
+}
+
+export class ErrorBoundary extends Component {
+ constructor(props: Props) {
+ super(props);
+ this.state = {
+ hasError: false,
+ error: null,
+ errorInfo: null,
+ };
+ }
+
+ static getDerivedStateFromError(error: Error): Partial {
+ return { hasError: true, error };
+ }
+
+ componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
+ console.error('ErrorBoundary caught an error:', error);
+ console.error('Error details:', errorInfo);
+ this.setState({
+ error,
+ errorInfo,
+ });
+ }
+
+ render() {
+ if (this.state.hasError) {
+ return (
+
+
+
+ Application Error
+
+
+
+
+
Error Message:
+
{this.state.error?.toString()}
+
+ {this.state.errorInfo && (
+
+
Component Stack:
+
+ {this.state.errorInfo.componentStack}
+
+
+ )}
+ {this.state.error?.stack && (
+
+
Stack Trace:
+
{this.state.error.stack}
+
+ )}
+
+
+
+
+ );
+ }
+
+ return this.props.children;
+ }
+}
diff --git a/apps/supportconsolek/supportconsolek/client/src/index.css b/apps/supportconsolek/supportconsolek/client/src/index.css
new file mode 100644
index 0000000..4686818
--- /dev/null
+++ b/apps/supportconsolek/supportconsolek/client/src/index.css
@@ -0,0 +1,63 @@
+@import "@databricks/appkit-ui/styles.css";
+
+:root,
+:root.light,
+:root.dark,
+html.light,
+html.dark {
+ --radius: 0.625rem;
+ --background: #f6f8fb;
+ --foreground: #1f2937;
+ --card: #ffffff;
+ --card-foreground: #111827;
+ --popover: #ffffff;
+ --popover-foreground: #111827;
+ --primary: #ff3621;
+ --primary-foreground: #ffffff;
+ --secondary: #edf2f8;
+ --secondary-foreground: #1f2937;
+ --muted: #f3f6fa;
+ --muted-foreground: #4b5563;
+ --accent: #e7efff;
+ --accent-foreground: #1e3a8a;
+ --destructive: #dc2626;
+ --destructive-foreground: #ffffff;
+ --success: #0f9d58;
+ --success-foreground: #ffffff;
+ --warning: #f59e0b;
+ --warning-foreground: #111827;
+ --border: #d9e1eb;
+ --input: #d9e1eb;
+ --ring: #ff6f61;
+ --chart-1: #2563eb;
+ --chart-2: #16a34a;
+ --chart-3: #f59e0b;
+ --chart-4: #a855f7;
+ --chart-5: #0ea5e9;
+ --sidebar: #ffffff;
+ --sidebar-foreground: #111827;
+ --sidebar-primary: #ff3621;
+ --sidebar-primary-foreground: #ffffff;
+ --sidebar-accent: #edf2f8;
+ --sidebar-accent-foreground: #1f2937;
+ --sidebar-border: #d9e1eb;
+ --sidebar-ring: #ff6f61;
+ color-scheme: light;
+}
+
+@media (prefers-color-scheme: dark) {
+ :root,
+ :root.light,
+ :root.dark,
+ html.light,
+ html.dark {
+ color-scheme: light;
+ }
+}
+
+html,
+body,
+#root {
+ background: var(--background);
+ color: var(--foreground);
+}
diff --git a/apps/supportconsolek/supportconsolek/client/src/lib/utils.ts b/apps/supportconsolek/supportconsolek/client/src/lib/utils.ts
new file mode 100644
index 0000000..2819a83
--- /dev/null
+++ b/apps/supportconsolek/supportconsolek/client/src/lib/utils.ts
@@ -0,0 +1,6 @@
+import { clsx, type ClassValue } from 'clsx';
+import { twMerge } from 'tailwind-merge';
+
+export function cn(...inputs: ClassValue[]) {
+ return twMerge(clsx(inputs));
+}
diff --git a/apps/supportconsolek/supportconsolek/client/src/main.tsx b/apps/supportconsolek/supportconsolek/client/src/main.tsx
new file mode 100644
index 0000000..e1455b2
--- /dev/null
+++ b/apps/supportconsolek/supportconsolek/client/src/main.tsx
@@ -0,0 +1,19 @@
+import { StrictMode } from 'react';
+import { createRoot } from 'react-dom/client';
+import './index.css';
+import App from './App.tsx';
+import { ErrorBoundary } from './ErrorBoundary.tsx';
+
+// Force a consistent light theme regardless of host dark-mode defaults.
+document.documentElement.classList.remove("dark");
+document.documentElement.classList.add("light");
+document.body.classList.remove("dark");
+document.body.classList.add("light");
+
+createRoot(document.getElementById('root')!).render(
+
+
+
+
+
+);
diff --git a/apps/supportconsolek/supportconsolek/client/src/vite-env.d.ts b/apps/supportconsolek/supportconsolek/client/src/vite-env.d.ts
new file mode 100644
index 0000000..11f02fe
--- /dev/null
+++ b/apps/supportconsolek/supportconsolek/client/src/vite-env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/apps/supportconsolek/supportconsolek/client/tailwind.config.ts b/apps/supportconsolek/supportconsolek/client/tailwind.config.ts
new file mode 100644
index 0000000..31dece8
--- /dev/null
+++ b/apps/supportconsolek/supportconsolek/client/tailwind.config.ts
@@ -0,0 +1,10 @@
+import type { Config } from 'tailwindcss';
+import tailwindcssAnimate from 'tailwindcss-animate';
+
+const config: Config = {
+ darkMode: ['class', 'media'],
+ content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
+ plugins: [tailwindcssAnimate],
+};
+
+export default config;
diff --git a/apps/supportconsolek/supportconsolek/client/vite.config.ts b/apps/supportconsolek/supportconsolek/client/vite.config.ts
new file mode 100644
index 0000000..b49d405
--- /dev/null
+++ b/apps/supportconsolek/supportconsolek/client/vite.config.ts
@@ -0,0 +1,25 @@
+import { defineConfig } from 'vite';
+import react from '@vitejs/plugin-react';
+import tailwindcss from '@tailwindcss/vite';
+import path from 'node:path';
+
+// https://vite.dev/config/
+export default defineConfig({
+ root: __dirname,
+ plugins: [react(), tailwindcss()],
+ server: {
+ middlewareMode: true,
+ },
+ build: {
+ outDir: path.resolve(__dirname, './dist'),
+ emptyOutDir: true,
+ },
+ optimizeDeps: {
+ include: ['react', 'react-dom', 'react/jsx-dev-runtime', 'react/jsx-runtime', 'recharts'],
+ },
+ resolve: {
+ alias: {
+ '@': path.resolve(__dirname, './src'),
+ },
+ },
+});
diff --git a/apps/supportconsolek/supportconsolek/databricks.yml b/apps/supportconsolek/supportconsolek/databricks.yml
new file mode 100644
index 0000000..560adcf
--- /dev/null
+++ b/apps/supportconsolek/supportconsolek/databricks.yml
@@ -0,0 +1,20 @@
+bundle:
+ name: supportconsolek
+
+
+resources:
+ apps:
+ app:
+ name: "casperskitchens-supportconsole"
+ description: "Support console"
+ source_code_path: ./
+
+ # Uncomment to enable on behalf of user API scopes. Available scopes: sql, dashboards.genie, files.files
+ # user_api_scopes:
+ # - sql
+
+
+targets:
+ default:
+ default: true
+
diff --git a/apps/supportconsolek/supportconsolek/eslint.config.js b/apps/supportconsolek/supportconsolek/eslint.config.js
new file mode 100644
index 0000000..5ac5ece
--- /dev/null
+++ b/apps/supportconsolek/supportconsolek/eslint.config.js
@@ -0,0 +1,91 @@
+import js from '@eslint/js';
+import tseslint from 'typescript-eslint';
+import reactPlugin from 'eslint-plugin-react';
+import reactHooksPlugin from 'eslint-plugin-react-hooks';
+import reactRefreshPlugin from 'eslint-plugin-react-refresh';
+import prettier from 'eslint-config-prettier';
+
+export default tseslint.config(
+ // Global ignores
+ {
+ ignores: [
+ '**/dist/**',
+ '**/build/**',
+ '**/node_modules/**',
+ '**/.next/**',
+ '**/coverage/**',
+ 'client/dist/**',
+ '**.databricks/**',
+ 'tests/**',
+ '**/.smoke-test/**',
+ ],
+ },
+
+ // Base JavaScript config
+ js.configs.recommended,
+
+ // TypeScript config for all TS files
+ ...tseslint.configs.recommendedTypeChecked,
+ {
+ languageOptions: {
+ parserOptions: {
+ projectService: true,
+ tsconfigRootDir: import.meta.dirname,
+ },
+ },
+ },
+
+ // React config for client-side files
+ {
+ files: ['client/**/*.{ts,tsx}', '**/*.tsx'],
+ plugins: {
+ react: reactPlugin,
+ 'react-hooks': reactHooksPlugin,
+ 'react-refresh': reactRefreshPlugin,
+ },
+ settings: {
+ react: {
+ version: 'detect',
+ },
+ },
+ rules: {
+ ...reactPlugin.configs.recommended.rules,
+ ...reactPlugin.configs['jsx-runtime'].rules,
+ ...reactHooksPlugin.configs.recommended.rules,
+ 'react-refresh/only-export-components': ['warn', { allowConstantExport: true }],
+ 'react/prop-types': 'off', // Using TypeScript for prop validation
+ 'react/no-array-index-key': 'warn',
+ },
+ },
+
+ // Node.js specific config for server files
+ {
+ files: ['server/**/*.ts', '*.config.{js,ts}'],
+ rules: {
+ '@typescript-eslint/no-var-requires': 'off',
+ },
+ },
+
+ // Disable type-checking for JS config files and standalone config files
+ {
+ files: ['**/*.js', '*.config.ts', '**/*.config.ts'],
+ ...tseslint.configs.disableTypeChecked,
+ },
+
+ // Prettier config (must be last to override other formatting rules)
+ prettier,
+
+ // Custom rules
+ {
+ rules: {
+ '@typescript-eslint/no-unused-vars': [
+ 'error',
+ {
+ argsIgnorePattern: '^_',
+ varsIgnorePattern: '^_',
+ },
+ ],
+ '@typescript-eslint/no-explicit-any': 'warn',
+ },
+ }
+);
diff --git a/apps/supportconsolek/supportconsolek/package-lock.json b/apps/supportconsolek/supportconsolek/package-lock.json
new file mode 100644
index 0000000..938af0c
--- /dev/null
+++ b/apps/supportconsolek/supportconsolek/package-lock.json
@@ -0,0 +1,14167 @@
+{
+ "name": "supportconsolek",
+ "version": "1.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "supportconsolek",
+ "version": "1.0.0",
+ "hasInstallScript": true,
+ "license": "Unlicensed",
+ "dependencies": {
+ "@databricks/appkit": "^0.11.2",
+ "@databricks/appkit-ui": "^0.11.2",
+ "@databricks/sdk-experimental": "^0.14.2",
+ "clsx": "^2.1.1",
+ "embla-carousel-react": "^8.6.0",
+ "lucide-react": "^0.546.0",
+ "next-themes": "^0.4.6",
+ "pg": "^8.18.0",
+ "react": "^19.1.1",
+ "react-dom": "^19.1.1",
+ "react-resizable-panels": "^3.0.6",
+ "sonner": "^2.0.7",
+ "superjson": "^2.2.5",
+ "tailwind-merge": "^3.3.1",
+ "tailwindcss-animate": "^1.0.7",
+ "tw-animate-css": "^1.4.0",
+ "zod": "^4.1.13"
+ },
+ "devDependencies": {
+ "@ast-grep/napi": "^0.37.0",
+ "@eslint/compat": "^2.0.0",
+ "@eslint/js": "^9.39.1",
+ "@playwright/test": "^1.57.0",
+ "@tailwindcss/postcss": "^4.1.17",
+ "@tailwindcss/vite": "^4.1.17",
+ "@types/express": "^5.0.5",
+ "@types/node": "^24.6.0",
+ "@types/pg": "^8.16.0",
+ "@types/react": "^19.1.16",
+ "@types/react-dom": "^19.1.9",
+ "@typescript-eslint/eslint-plugin": "^8.48.0",
+ "@typescript-eslint/parser": "^8.48.0",
+ "@vitejs/plugin-react": "^5.0.4",
+ "autoprefixer": "^10.4.21",
+ "eslint": "^9.39.1",
+ "eslint-config-prettier": "^10.1.8",
+ "eslint-plugin-react": "^7.37.5",
+ "eslint-plugin-react-hooks": "^7.0.1",
+ "eslint-plugin-react-refresh": "^0.4.24",
+ "prettier": "^3.6.2",
+ "sharp": "^0.34.5",
+ "tailwindcss": "^4.0.14",
+ "tsx": "^4.20.6",
+ "typescript": "~5.9.3",
+ "typescript-eslint": "^8.48.0",
+ "vite": "npm:rolldown-vite@7.1.14",
+ "vitest": "^4.0.14"
+ }
+ },
+ "node_modules/@alloc/quick-lru": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
+ "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@ast-grep/napi": {
+ "version": "0.37.0",
+ "resolved": "https://registry.npmjs.org/@ast-grep/napi/-/napi-0.37.0.tgz",
+ "integrity": "sha512-Hb4o6h1Pf6yRUAX07DR4JVY7dmQw+RVQMW5/m55GoiAT/VRoKCWBtIUPPOnqDVhbx1Cjfil9b6EDrgJsUAujEQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10"
+ },
+ "optionalDependencies": {
+ "@ast-grep/napi-darwin-arm64": "0.37.0",
+ "@ast-grep/napi-darwin-x64": "0.37.0",
+ "@ast-grep/napi-linux-arm64-gnu": "0.37.0",
+ "@ast-grep/napi-linux-arm64-musl": "0.37.0",
+ "@ast-grep/napi-linux-x64-gnu": "0.37.0",
+ "@ast-grep/napi-linux-x64-musl": "0.37.0",
+ "@ast-grep/napi-win32-arm64-msvc": "0.37.0",
+ "@ast-grep/napi-win32-ia32-msvc": "0.37.0",
+ "@ast-grep/napi-win32-x64-msvc": "0.37.0"
+ }
+ },
+ "node_modules/@ast-grep/napi-darwin-arm64": {
+ "version": "0.37.0",
+ "resolved": "https://registry.npmjs.org/@ast-grep/napi-darwin-arm64/-/napi-darwin-arm64-0.37.0.tgz",
+ "integrity": "sha512-QAiIiaAbLvMEg/yBbyKn+p1gX2/FuaC0SMf7D7capm/oG4xGMzdeaQIcSosF4TCxxV+hIH4Bz9e4/u7w6Bnk3Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@ast-grep/napi-darwin-x64": {
+ "version": "0.37.0",
+ "resolved": "https://registry.npmjs.org/@ast-grep/napi-darwin-x64/-/napi-darwin-x64-0.37.0.tgz",
+ "integrity": "sha512-zvcvdgekd4ySV3zUbUp8HF5nk5zqwiMXTuVzTUdl/w08O7JjM6XPOIVT+d2o/MqwM9rsXdzdergY5oY2RdhSPA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@ast-grep/napi-linux-arm64-gnu": {
+ "version": "0.37.0",
+ "resolved": "https://registry.npmjs.org/@ast-grep/napi-linux-arm64-gnu/-/napi-linux-arm64-gnu-0.37.0.tgz",
+ "integrity": "sha512-L7Sj0lXy8X+BqSMgr1LB8cCoWk0rericdeu+dC8/c8zpsav5Oo2IQKY1PmiZ7H8IHoFBbURLf8iklY9wsD+cyA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@ast-grep/napi-linux-arm64-musl": {
+ "version": "0.37.0",
+ "resolved": "https://registry.npmjs.org/@ast-grep/napi-linux-arm64-musl/-/napi-linux-arm64-musl-0.37.0.tgz",
+ "integrity": "sha512-LF9sAvYy6es/OdyJDO3RwkX3I82Vkfsng1sqUBcoWC1jVb1wX5YVzHtpQox9JrEhGl+bNp7FYxB4Qba9OdA5GA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@ast-grep/napi-linux-x64-gnu": {
+ "version": "0.37.0",
+ "resolved": "https://registry.npmjs.org/@ast-grep/napi-linux-x64-gnu/-/napi-linux-x64-gnu-0.37.0.tgz",
+ "integrity": "sha512-TViz5/klqre6aSmJzswEIjApnGjJzstG/SE8VDWsrftMBMYt2PTu3MeluZVwzSqDao8doT/P+6U11dU05UOgxw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@ast-grep/napi-linux-x64-musl": {
+ "version": "0.37.0",
+ "resolved": "https://registry.npmjs.org/@ast-grep/napi-linux-x64-musl/-/napi-linux-x64-musl-0.37.0.tgz",
+ "integrity": "sha512-/BcCH33S9E3ovOAEoxYngUNXgb+JLg991sdyiNP2bSoYd30a9RHrG7CYwW6fMgua3ijQ474eV6cq9yZO1bCpXg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@ast-grep/napi-win32-arm64-msvc": {
+ "version": "0.37.0",
+ "resolved": "https://registry.npmjs.org/@ast-grep/napi-win32-arm64-msvc/-/napi-win32-arm64-msvc-0.37.0.tgz",
+ "integrity": "sha512-TjQA4cFoIEW2bgjLkaL9yqT4XWuuLa5MCNd0VCDhGRDMNQ9+rhwi9eLOWRaap3xzT7g+nlbcEHL3AkVCD2+b3A==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@ast-grep/napi-win32-ia32-msvc": {
+ "version": "0.37.0",
+ "resolved": "https://registry.npmjs.org/@ast-grep/napi-win32-ia32-msvc/-/napi-win32-ia32-msvc-0.37.0.tgz",
+ "integrity": "sha512-uNmVka8fJCdYsyOlF9aZqQMLTatEYBynjChVTzUfFMDfmZ0bihs/YTqJVbkSm8TZM7CUX82apvn50z/dX5iWRA==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@ast-grep/napi-win32-x64-msvc": {
+ "version": "0.37.0",
+ "resolved": "https://registry.npmjs.org/@ast-grep/napi-win32-x64-msvc/-/napi-win32-x64-msvc-0.37.0.tgz",
+ "integrity": "sha512-vCiFOT3hSCQuHHfZ933GAwnPzmL0G04JxQEsBRfqONywyT8bSdDc/ECpAfr3S9VcS4JZ9/F6tkePKW/Om2Dq2g==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.28.6.tgz",
+ "integrity": "sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.28.5",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/compat-data": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.6.tgz",
+ "integrity": "sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/core": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.6.tgz",
+ "integrity": "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.28.6",
+ "@babel/generator": "^7.28.6",
+ "@babel/helper-compilation-targets": "^7.28.6",
+ "@babel/helper-module-transforms": "^7.28.6",
+ "@babel/helpers": "^7.28.6",
+ "@babel/parser": "^7.28.6",
+ "@babel/template": "^7.28.6",
+ "@babel/traverse": "^7.28.6",
+ "@babel/types": "^7.28.6",
+ "@jridgewell/remapping": "^2.3.5",
+ "convert-source-map": "^2.0.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/@babel/core/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/generator": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.6.tgz",
+ "integrity": "sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.28.6",
+ "@babel/types": "^7.28.6",
+ "@jridgewell/gen-mapping": "^0.3.12",
+ "@jridgewell/trace-mapping": "^0.3.28",
+ "jsesc": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz",
+ "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/compat-data": "^7.28.6",
+ "@babel/helper-validator-option": "^7.27.1",
+ "browserslist": "^4.24.0",
+ "lru-cache": "^5.1.1",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/helper-globals": {
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
+ "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-imports": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz",
+ "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/traverse": "^7.28.6",
+ "@babel/types": "^7.28.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-transforms": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz",
+ "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.28.6",
+ "@babel/helper-validator-identifier": "^7.28.5",
+ "@babel/traverse": "^7.28.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-plugin-utils": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz",
+ "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
+ "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
+ "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-option": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
+ "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helpers": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz",
+ "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/template": "^7.28.6",
+ "@babel/types": "^7.28.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.6.tgz",
+ "integrity": "sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.28.6"
+ },
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx-self": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz",
+ "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx-source": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz",
+ "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/template": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz",
+ "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.28.6",
+ "@babel/parser": "^7.28.6",
+ "@babel/types": "^7.28.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.6.tgz",
+ "integrity": "sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.28.6",
+ "@babel/generator": "^7.28.6",
+ "@babel/helper-globals": "^7.28.0",
+ "@babel/parser": "^7.28.6",
+ "@babel/template": "^7.28.6",
+ "@babel/types": "^7.28.6",
+ "debug": "^4.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.6.tgz",
+ "integrity": "sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.27.1",
+ "@babel/helper-validator-identifier": "^7.28.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@clack/core": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@clack/core/-/core-1.0.1.tgz",
+ "integrity": "sha512-WKeyK3NOBwDOzagPR5H08rFk9D/WuN705yEbuZvKqlkmoLM2woKtXb10OO2k1NoSU4SFG947i2/SCYh+2u5e4g==",
+ "license": "MIT",
+ "dependencies": {
+ "picocolors": "^1.0.0",
+ "sisteransi": "^1.0.5"
+ }
+ },
+ "node_modules/@clack/prompts": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@clack/prompts/-/prompts-1.0.1.tgz",
+ "integrity": "sha512-/42G73JkuYdyWZ6m8d/CJtBrGl1Hegyc7Fy78m5Ob+jF85TOUmLR5XLce/U3LxYAw0kJ8CT5aI99RIvPHcGp/Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@clack/core": "1.0.1",
+ "picocolors": "^1.0.0",
+ "sisteransi": "^1.0.5"
+ }
+ },
+ "node_modules/@databricks/appkit": {
+ "version": "0.11.2",
+ "resolved": "https://registry.npmjs.org/@databricks/appkit/-/appkit-0.11.2.tgz",
+ "integrity": "sha512-tvkcHsOTBFOwnLsaQwHb37nil24MJODNDPsBH8YJA/U2ol/+3FATLQcuk8ilr7IW+4s0YuRh95MsKcrtg3GiFQ==",
+ "hasInstallScript": true,
+ "dependencies": {
+ "@ast-grep/napi": "^0.37.0",
+ "@clack/prompts": "^1.0.1",
+ "@databricks/lakebase": "0.2.0",
+ "@databricks/sdk-experimental": "^0.16.0",
+ "@opentelemetry/api": "^1.9.0",
+ "@opentelemetry/api-logs": "^0.208.0",
+ "@opentelemetry/auto-instrumentations-node": "^0.67.0",
+ "@opentelemetry/exporter-logs-otlp-proto": "^0.208.0",
+ "@opentelemetry/exporter-metrics-otlp-proto": "^0.208.0",
+ "@opentelemetry/exporter-trace-otlp-proto": "^0.208.0",
+ "@opentelemetry/instrumentation": "^0.208.0",
+ "@opentelemetry/instrumentation-express": "^0.57.0",
+ "@opentelemetry/instrumentation-http": "^0.208.0",
+ "@opentelemetry/resources": "^2.2.0",
+ "@opentelemetry/sdk-logs": "^0.208.0",
+ "@opentelemetry/sdk-metrics": "^2.2.0",
+ "@opentelemetry/sdk-node": "^0.208.0",
+ "@opentelemetry/semantic-conventions": "^1.38.0",
+ "@types/semver": "^7.7.1",
+ "ajv": "^8.17.1",
+ "ajv-formats": "^3.0.1",
+ "commander": "^12.1.0",
+ "dotenv": "^16.6.1",
+ "express": "^4.22.0",
+ "obug": "^2.1.1",
+ "pg": "^8.18.0",
+ "semver": "^7.7.3",
+ "vite": "npm:rolldown-vite@7.1.14",
+ "ws": "^8.18.3",
+ "zod-to-ts": "^2.0.0"
+ },
+ "bin": {
+ "appkit": "bin/appkit.js"
+ }
+ },
+ "node_modules/@databricks/appkit-ui": {
+ "version": "0.11.2",
+ "resolved": "https://registry.npmjs.org/@databricks/appkit-ui/-/appkit-ui-0.11.2.tgz",
+ "integrity": "sha512-aToYKadA+LO2q7LvhZvxjqm5+WI5lCjjDTxOJDYH8hCQ/7GmKb5mm+3+gvfRi0a9wWbXwQ9M3tCRuOW9vx3g2Q==",
+ "hasInstallScript": true,
+ "dependencies": {
+ "@ast-grep/napi": "^0.37.0",
+ "@clack/prompts": "^1.0.1",
+ "@hookform/resolvers": "^5.2.2",
+ "@radix-ui/react-accordion": "^1.2.12",
+ "@radix-ui/react-alert-dialog": "^1.1.15",
+ "@radix-ui/react-aspect-ratio": "^1.1.8",
+ "@radix-ui/react-avatar": "^1.1.11",
+ "@radix-ui/react-checkbox": "^1.3.3",
+ "@radix-ui/react-collapsible": "^1.1.12",
+ "@radix-ui/react-context-menu": "^2.2.16",
+ "@radix-ui/react-dialog": "^1.1.15",
+ "@radix-ui/react-dropdown-menu": "^2.1.16",
+ "@radix-ui/react-hover-card": "^1.1.15",
+ "@radix-ui/react-label": "^2.1.8",
+ "@radix-ui/react-menubar": "^1.1.16",
+ "@radix-ui/react-navigation-menu": "^1.2.14",
+ "@radix-ui/react-popover": "^1.1.15",
+ "@radix-ui/react-progress": "^1.1.8",
+ "@radix-ui/react-radio-group": "^1.3.8",
+ "@radix-ui/react-scroll-area": "^1.2.10",
+ "@radix-ui/react-select": "^2.2.6",
+ "@radix-ui/react-separator": "^1.1.8",
+ "@radix-ui/react-slider": "^1.3.6",
+ "@radix-ui/react-slot": "^1.2.4",
+ "@radix-ui/react-switch": "^1.2.6",
+ "@radix-ui/react-tabs": "^1.1.13",
+ "@radix-ui/react-toggle": "^1.1.10",
+ "@radix-ui/react-toggle-group": "^1.1.11",
+ "@radix-ui/react-tooltip": "^1.2.8",
+ "@tanstack/react-table": "^8.21.3",
+ "@tanstack/react-virtual": "^3.13.12",
+ "ajv": "^8.17.1",
+ "ajv-formats": "^3.0.1",
+ "apache-arrow": "^21.1.0",
+ "class-variance-authority": "^0.7.1",
+ "clsx": "^2.1.1",
+ "cmdk": "^1.1.1",
+ "commander": "^12.1.0",
+ "date-fns": "^4.1.0",
+ "echarts-for-react": "^3.0.5",
+ "embla-carousel-react": "^8.6.0",
+ "input-otp": "^1.4.2",
+ "lucide-react": "^0.554.0",
+ "next-themes": "^0.4.6",
+ "react-day-picker": "^9.11.3",
+ "react-hook-form": "^7.68.0",
+ "react-resizable-panels": "^3.0.6",
+ "sonner": "^2.0.7",
+ "tailwind-merge": "^3.4.0",
+ "vaul": "^1.1.2",
+ "zod": "^4.1.13"
+ },
+ "bin": {
+ "appkit": "bin/appkit.js"
+ },
+ "peerDependencies": {
+ "react": "^18.0.0 || ^19.0.0",
+ "react-dom": "^18.0.0 || ^19.0.0",
+ "recharts": "^2.0.0 || ^3.0.0"
+ }
+ },
+ "node_modules/@databricks/appkit-ui/node_modules/ajv": {
+ "version": "8.18.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz",
+ "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==",
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3",
+ "fast-uri": "^3.0.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/@databricks/appkit-ui/node_modules/json-schema-traverse": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+ "license": "MIT"
+ },
+ "node_modules/@databricks/appkit-ui/node_modules/lucide-react": {
+ "version": "0.554.0",
+ "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.554.0.tgz",
+ "integrity": "sha512-St+z29uthEJVx0Is7ellNkgTEhaeSoA42I7JjOCBCrc5X6LYMGSv0P/2uS5HDLTExP5tpiqRD2PyUEOS6s9UXA==",
+ "license": "ISC",
+ "peerDependencies": {
+ "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
+ "node_modules/@databricks/appkit/node_modules/@databricks/sdk-experimental": {
+ "version": "0.16.0",
+ "resolved": "https://registry.npmjs.org/@databricks/sdk-experimental/-/sdk-experimental-0.16.0.tgz",
+ "integrity": "sha512-9c2RxWYoRDFupdt4ZnBc1IPE1XaXgN+/wyV4DVcEqOnIa31ep51OnwAD/3014BImfKdyXg32nmgrB9dwvB6+lg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "google-auth-library": "^10.5.0",
+ "ini": "^6.0.0",
+ "reflect-metadata": "^0.2.2",
+ "semver": "^7.7.3"
+ },
+ "engines": {
+ "node": ">=22.0",
+ "npm": ">=10.0.0"
+ }
+ },
+ "node_modules/@databricks/appkit/node_modules/ajv": {
+ "version": "8.18.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz",
+ "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==",
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3",
+ "fast-uri": "^3.0.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/@databricks/appkit/node_modules/json-schema-traverse": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+ "license": "MIT"
+ },
+ "node_modules/@databricks/lakebase": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/@databricks/lakebase/-/lakebase-0.2.0.tgz",
+ "integrity": "sha512-dlLav/bLEbfpqdazcStbPk/8VYocXU/6KGyFhYsuNeUYbl8txrmEdSUB81N5D/kz41xEwuGkngu5BIUj1zcHZQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@databricks/sdk-experimental": "^0.16.0",
+ "@opentelemetry/api": "^1.9.0",
+ "pg": "^8.18.0"
+ }
+ },
+ "node_modules/@databricks/lakebase/node_modules/@databricks/sdk-experimental": {
+ "version": "0.16.0",
+ "resolved": "https://registry.npmjs.org/@databricks/sdk-experimental/-/sdk-experimental-0.16.0.tgz",
+ "integrity": "sha512-9c2RxWYoRDFupdt4ZnBc1IPE1XaXgN+/wyV4DVcEqOnIa31ep51OnwAD/3014BImfKdyXg32nmgrB9dwvB6+lg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "google-auth-library": "^10.5.0",
+ "ini": "^6.0.0",
+ "reflect-metadata": "^0.2.2",
+ "semver": "^7.7.3"
+ },
+ "engines": {
+ "node": ">=22.0",
+ "npm": ">=10.0.0"
+ }
+ },
+ "node_modules/@databricks/sdk-experimental": {
+ "version": "0.14.2",
+ "resolved": "https://registry.npmjs.org/@databricks/sdk-experimental/-/sdk-experimental-0.14.2.tgz",
+ "integrity": "sha512-G7lwQYOyF95IGdTiY9RRVYN5VlGZQ4xVIcfGYIBtW5VjJGKDSC3h8BN0JHKdhZceMNePF0aQ62iBiWpJZ3tQkg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "google-auth-library": "^10.5.0",
+ "ini": "^6.0.0",
+ "reflect-metadata": "^0.2.2",
+ "semver": "^7.7.3"
+ },
+ "engines": {
+ "node": ">=18.0",
+ "npm": ">=9.0.0"
+ }
+ },
+ "node_modules/@date-fns/tz": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/@date-fns/tz/-/tz-1.4.1.tgz",
+ "integrity": "sha512-P5LUNhtbj6YfI3iJjw5EL9eUAG6OitD0W3fWQcpQjDRc/QIsL0tRNuO1PcDvPccWL1fSTXXdE1ds+l95DV/OFA==",
+ "license": "MIT"
+ },
+ "node_modules/@emnapi/core": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.8.1.tgz",
+ "integrity": "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/wasi-threads": "1.1.0",
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@emnapi/runtime": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz",
+ "integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@emnapi/wasi-threads": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz",
+ "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils": {
+ "version": "4.9.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz",
+ "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "eslint-visitor-keys": "^3.4.3"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+ }
+ },
+ "node_modules/@eslint-community/regexpp": {
+ "version": "4.12.2",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz",
+ "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@eslint/compat": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-2.0.1.tgz",
+ "integrity": "sha512-yl/JsgplclzuvGFNqwNYV4XNPhP3l62ZOP9w/47atNAdmDtIFCx6X7CSk/SlWUuBGkT4Et/5+UD+WyvX2iiIWA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/core": "^1.0.1"
+ },
+ "engines": {
+ "node": "^20.19.0 || ^22.13.0 || >=24"
+ },
+ "peerDependencies": {
+ "eslint": "^8.40 || 9"
+ },
+ "peerDependenciesMeta": {
+ "eslint": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@eslint/config-array": {
+ "version": "0.21.1",
+ "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz",
+ "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/object-schema": "^2.1.7",
+ "debug": "^4.3.1",
+ "minimatch": "^3.1.2"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/config-array/node_modules/brace-expansion": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/@eslint/config-array/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/@eslint/config-helpers": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz",
+ "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/core": "^0.17.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/config-helpers/node_modules/@eslint/core": {
+ "version": "0.17.0",
+ "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz",
+ "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/json-schema": "^7.0.15"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/core": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.0.1.tgz",
+ "integrity": "sha512-r18fEAj9uCk+VjzGt2thsbOmychS+4kxI14spVNibUO2vqKX7obOG+ymZljAwuPZl+S3clPGwCwTDtrdqTiY6Q==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/json-schema": "^7.0.15"
+ },
+ "engines": {
+ "node": "^20.19.0 || ^22.13.0 || >=24"
+ }
+ },
+ "node_modules/@eslint/eslintrc": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz",
+ "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^10.0.1",
+ "globals": "^14.0.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.1",
+ "minimatch": "^3.1.2",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/brace-expansion": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/ignore": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
+ "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/@eslint/js": {
+ "version": "9.39.2",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz",
+ "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://eslint.org/donate"
+ }
+ },
+ "node_modules/@eslint/object-schema": {
+ "version": "2.1.7",
+ "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz",
+ "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/plugin-kit": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz",
+ "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/core": "^0.17.0",
+ "levn": "^0.4.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/plugin-kit/node_modules/@eslint/core": {
+ "version": "0.17.0",
+ "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz",
+ "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/json-schema": "^7.0.15"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@floating-ui/core": {
+ "version": "1.7.4",
+ "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.4.tgz",
+ "integrity": "sha512-C3HlIdsBxszvm5McXlB8PeOEWfBhcGBTZGkGlWc2U0KFY5IwG5OQEuQ8rq52DZmcHDlPLd+YFBK+cZcytwIFWg==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/utils": "^0.2.10"
+ }
+ },
+ "node_modules/@floating-ui/dom": {
+ "version": "1.7.5",
+ "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.5.tgz",
+ "integrity": "sha512-N0bD2kIPInNHUHehXhMke1rBGs1dwqvC9O9KYMyyjK7iXt7GAhnro7UlcuYcGdS/yYOlq0MAVgrow8IbWJwyqg==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/core": "^1.7.4",
+ "@floating-ui/utils": "^0.2.10"
+ }
+ },
+ "node_modules/@floating-ui/react-dom": {
+ "version": "2.1.7",
+ "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.7.tgz",
+ "integrity": "sha512-0tLRojf/1Go2JgEVm+3Frg9A3IW8bJgKgdO0BN5RkF//ufuz2joZM63Npau2ff3J6lUVYgDSNzNkR+aH3IVfjg==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/dom": "^1.7.5"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0",
+ "react-dom": ">=16.8.0"
+ }
+ },
+ "node_modules/@floating-ui/utils": {
+ "version": "0.2.10",
+ "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz",
+ "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==",
+ "license": "MIT"
+ },
+ "node_modules/@grpc/grpc-js": {
+ "version": "1.14.3",
+ "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.14.3.tgz",
+ "integrity": "sha512-Iq8QQQ/7X3Sac15oB6p0FmUg/klxQvXLeileoqrTRGJYLV+/9tubbr9ipz0GKHjmXVsgFPo/+W+2cA8eNcR+XA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@grpc/proto-loader": "^0.8.0",
+ "@js-sdsl/ordered-map": "^4.4.2"
+ },
+ "engines": {
+ "node": ">=12.10.0"
+ }
+ },
+ "node_modules/@grpc/proto-loader": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.8.0.tgz",
+ "integrity": "sha512-rc1hOQtjIWGxcxpb9aHAfLpIctjEnsDehj0DAiVfBlmT84uvR0uUtN2hEi/ecvWVjXUGf5qPF4qEgiLOx1YIMQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "lodash.camelcase": "^4.3.0",
+ "long": "^5.0.0",
+ "protobufjs": "^7.5.3",
+ "yargs": "^17.7.2"
+ },
+ "bin": {
+ "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@hookform/resolvers": {
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-5.2.2.tgz",
+ "integrity": "sha512-A/IxlMLShx3KjV/HeTcTfaMxdwy690+L/ZADoeaTltLx+CVuzkeVIPuybK3jrRfw7YZnmdKsVVHAlEPIAEUNlA==",
+ "license": "MIT",
+ "dependencies": {
+ "@standard-schema/utils": "^0.3.0"
+ },
+ "peerDependencies": {
+ "react-hook-form": "^7.55.0"
+ }
+ },
+ "node_modules/@humanfs/core": {
+ "version": "0.19.1",
+ "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
+ "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
+ "node_modules/@humanfs/node": {
+ "version": "0.16.7",
+ "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz",
+ "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@humanfs/core": "^0.19.1",
+ "@humanwhocodes/retry": "^0.4.0"
+ },
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
+ "node_modules/@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/retry": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz",
+ "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@img/colour": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.0.0.tgz",
+ "integrity": "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@img/sharp-darwin-arm64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz",
+ "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-darwin-arm64": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-darwin-x64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz",
+ "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-darwin-x64": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-libvips-darwin-arm64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz",
+ "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-darwin-x64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz",
+ "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-arm": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz",
+ "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-arm64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz",
+ "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-ppc64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz",
+ "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-riscv64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz",
+ "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-s390x": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz",
+ "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-x64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz",
+ "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linuxmusl-arm64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz",
+ "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linuxmusl-x64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz",
+ "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-linux-arm": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz",
+ "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-arm": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-linux-arm64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz",
+ "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-arm64": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-linux-ppc64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz",
+ "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-ppc64": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-linux-riscv64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz",
+ "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-riscv64": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-linux-s390x": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz",
+ "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-s390x": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-linux-x64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz",
+ "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-x64": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-linuxmusl-arm64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz",
+ "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linuxmusl-arm64": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-linuxmusl-x64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz",
+ "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linuxmusl-x64": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-wasm32": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz",
+ "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==",
+ "cpu": [
+ "wasm32"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/runtime": "^1.7.0"
+ },
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-win32-arm64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz",
+ "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 AND LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-win32-ia32": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz",
+ "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 AND LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-win32-x64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz",
+ "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 AND LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@isaacs/cliui": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
+ "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^5.1.2",
+ "string-width-cjs": "npm:string-width@^4.2.0",
+ "strip-ansi": "^7.0.1",
+ "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
+ "wrap-ansi": "^8.1.0",
+ "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/ansi-regex": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz",
+ "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/ansi-styles": {
+ "version": "6.2.3",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz",
+ "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+ "license": "MIT"
+ },
+ "node_modules/@isaacs/cliui/node_modules/string-width": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+ "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+ "license": "MIT",
+ "dependencies": {
+ "eastasianwidth": "^0.2.0",
+ "emoji-regex": "^9.2.2",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/strip-ansi": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz",
+ "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/wrap-ansi": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
+ "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^6.1.0",
+ "string-width": "^5.0.1",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.13",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
+ "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.0",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "node_modules/@jridgewell/remapping": {
+ "version": "2.3.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
+ "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
+ "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.31",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
+ "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/@js-sdsl/ordered-map": {
+ "version": "4.4.2",
+ "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz",
+ "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==",
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/js-sdsl"
+ }
+ },
+ "node_modules/@napi-rs/wasm-runtime": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.1.tgz",
+ "integrity": "sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/core": "^1.7.1",
+ "@emnapi/runtime": "^1.7.1",
+ "@tybys/wasm-util": "^0.10.1"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/Brooooooklyn"
+ }
+ },
+ "node_modules/@opentelemetry/api": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz",
+ "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/api-logs": {
+ "version": "0.208.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.208.0.tgz",
+ "integrity": "sha512-CjruKY9V6NMssL/T1kAFgzosF1v9o6oeN+aX5JB/C/xPNtmgIJqcXHG7fA82Ou1zCpWGl4lROQUKwUNE1pMCyg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/auto-instrumentations-node": {
+ "version": "0.67.3",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/auto-instrumentations-node/-/auto-instrumentations-node-0.67.3.tgz",
+ "integrity": "sha512-sRzw/T1JU7CCATGxnnKhHbWMlwMH1qO62+4/znfsJTg24ATP5qNKFkt8B/JD7HAQ/0ceMeyQin9KOBnjkLkCvA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.208.0",
+ "@opentelemetry/instrumentation-amqplib": "^0.56.0",
+ "@opentelemetry/instrumentation-aws-lambda": "^0.61.1",
+ "@opentelemetry/instrumentation-aws-sdk": "^0.64.1",
+ "@opentelemetry/instrumentation-bunyan": "^0.54.0",
+ "@opentelemetry/instrumentation-cassandra-driver": "^0.54.1",
+ "@opentelemetry/instrumentation-connect": "^0.52.0",
+ "@opentelemetry/instrumentation-cucumber": "^0.24.0",
+ "@opentelemetry/instrumentation-dataloader": "^0.26.1",
+ "@opentelemetry/instrumentation-dns": "^0.52.0",
+ "@opentelemetry/instrumentation-express": "^0.57.1",
+ "@opentelemetry/instrumentation-fastify": "^0.53.1",
+ "@opentelemetry/instrumentation-fs": "^0.28.0",
+ "@opentelemetry/instrumentation-generic-pool": "^0.52.0",
+ "@opentelemetry/instrumentation-graphql": "^0.56.0",
+ "@opentelemetry/instrumentation-grpc": "^0.208.0",
+ "@opentelemetry/instrumentation-hapi": "^0.55.1",
+ "@opentelemetry/instrumentation-http": "^0.208.0",
+ "@opentelemetry/instrumentation-ioredis": "^0.57.0",
+ "@opentelemetry/instrumentation-kafkajs": "^0.18.1",
+ "@opentelemetry/instrumentation-knex": "^0.53.1",
+ "@opentelemetry/instrumentation-koa": "^0.57.1",
+ "@opentelemetry/instrumentation-lru-memoizer": "^0.53.1",
+ "@opentelemetry/instrumentation-memcached": "^0.52.1",
+ "@opentelemetry/instrumentation-mongodb": "^0.62.0",
+ "@opentelemetry/instrumentation-mongoose": "^0.55.1",
+ "@opentelemetry/instrumentation-mysql": "^0.55.0",
+ "@opentelemetry/instrumentation-mysql2": "^0.55.1",
+ "@opentelemetry/instrumentation-nestjs-core": "^0.55.0",
+ "@opentelemetry/instrumentation-net": "^0.53.0",
+ "@opentelemetry/instrumentation-openai": "^0.7.1",
+ "@opentelemetry/instrumentation-oracledb": "^0.34.1",
+ "@opentelemetry/instrumentation-pg": "^0.61.2",
+ "@opentelemetry/instrumentation-pino": "^0.55.1",
+ "@opentelemetry/instrumentation-redis": "^0.57.2",
+ "@opentelemetry/instrumentation-restify": "^0.54.0",
+ "@opentelemetry/instrumentation-router": "^0.53.0",
+ "@opentelemetry/instrumentation-runtime-node": "^0.22.0",
+ "@opentelemetry/instrumentation-socket.io": "^0.55.1",
+ "@opentelemetry/instrumentation-tedious": "^0.28.0",
+ "@opentelemetry/instrumentation-undici": "^0.19.0",
+ "@opentelemetry/instrumentation-winston": "^0.53.0",
+ "@opentelemetry/resource-detector-alibaba-cloud": "^0.32.0",
+ "@opentelemetry/resource-detector-aws": "^2.9.0",
+ "@opentelemetry/resource-detector-azure": "^0.17.0",
+ "@opentelemetry/resource-detector-container": "^0.8.0",
+ "@opentelemetry/resource-detector-gcp": "^0.44.0",
+ "@opentelemetry/resources": "^2.0.0",
+ "@opentelemetry/sdk-node": "^0.208.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.4.1",
+ "@opentelemetry/core": "^2.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/context-async-hooks": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-2.2.0.tgz",
+ "integrity": "sha512-qRkLWiUEZNAmYapZ7KGS5C4OmBLcP/H2foXeOEaowYCR0wi89fHejrfYfbuLVCMLp/dWZXKvQusdbUEZjERfwQ==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/core": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.5.0.tgz",
+ "integrity": "sha512-ka4H8OM6+DlUhSAZpONu0cPBtPPTQKxbxVzC4CzVx5+K4JnroJVBtDzLAMx4/3CDTJXRvVFhpFjtl4SaiTNoyQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-logs-otlp-grpc": {
+ "version": "0.208.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-grpc/-/exporter-logs-otlp-grpc-0.208.0.tgz",
+ "integrity": "sha512-AmZDKFzbq/idME/yq68M155CJW1y056MNBekH9OZewiZKaqgwYN4VYfn3mXVPftYsfrCM2r4V6tS8H2LmfiDCg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@grpc/grpc-js": "^1.7.1",
+ "@opentelemetry/core": "2.2.0",
+ "@opentelemetry/otlp-exporter-base": "0.208.0",
+ "@opentelemetry/otlp-grpc-exporter-base": "0.208.0",
+ "@opentelemetry/otlp-transformer": "0.208.0",
+ "@opentelemetry/sdk-logs": "0.208.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-logs-otlp-grpc/node_modules/@opentelemetry/core": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.2.0.tgz",
+ "integrity": "sha512-FuabnnUm8LflnieVxs6eP7Z383hgQU4W1e3KJS6aOG3RxWxcHyBxH8fDMHNgu/gFx/M2jvTOW/4/PHhLz6bjWw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-logs-otlp-http": {
+ "version": "0.208.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-http/-/exporter-logs-otlp-http-0.208.0.tgz",
+ "integrity": "sha512-jOv40Bs9jy9bZVLo/i8FwUiuCvbjWDI+ZW13wimJm4LjnlwJxGgB+N/VWOZUTpM+ah/awXeQqKdNlpLf2EjvYg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api-logs": "0.208.0",
+ "@opentelemetry/core": "2.2.0",
+ "@opentelemetry/otlp-exporter-base": "0.208.0",
+ "@opentelemetry/otlp-transformer": "0.208.0",
+ "@opentelemetry/sdk-logs": "0.208.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-logs-otlp-http/node_modules/@opentelemetry/core": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.2.0.tgz",
+ "integrity": "sha512-FuabnnUm8LflnieVxs6eP7Z383hgQU4W1e3KJS6aOG3RxWxcHyBxH8fDMHNgu/gFx/M2jvTOW/4/PHhLz6bjWw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-logs-otlp-proto": {
+ "version": "0.208.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-proto/-/exporter-logs-otlp-proto-0.208.0.tgz",
+ "integrity": "sha512-Wy8dZm16AOfM7yddEzSFzutHZDZ6HspKUODSUJVjyhnZFMBojWDjSNgduyCMlw6qaxJYz0dlb0OEcb4Eme+BfQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api-logs": "0.208.0",
+ "@opentelemetry/core": "2.2.0",
+ "@opentelemetry/otlp-exporter-base": "0.208.0",
+ "@opentelemetry/otlp-transformer": "0.208.0",
+ "@opentelemetry/resources": "2.2.0",
+ "@opentelemetry/sdk-logs": "0.208.0",
+ "@opentelemetry/sdk-trace-base": "2.2.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-logs-otlp-proto/node_modules/@opentelemetry/core": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.2.0.tgz",
+ "integrity": "sha512-FuabnnUm8LflnieVxs6eP7Z383hgQU4W1e3KJS6aOG3RxWxcHyBxH8fDMHNgu/gFx/M2jvTOW/4/PHhLz6bjWw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-logs-otlp-proto/node_modules/@opentelemetry/resources": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.2.0.tgz",
+ "integrity": "sha512-1pNQf/JazQTMA0BiO5NINUzH0cbLbbl7mntLa4aJNmCCXSj0q03T5ZXXL0zw4G55TjdL9Tz32cznGClf+8zr5A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.2.0",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-metrics-otlp-grpc": {
+ "version": "0.208.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-grpc/-/exporter-metrics-otlp-grpc-0.208.0.tgz",
+ "integrity": "sha512-YbEnk7jjYmvhIwp2xJGkEvdgnayrA2QSr28R1LR1klDPvCxsoQPxE6TokDbQpoCEhD3+KmJVEXfb4EeEQxjymg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@grpc/grpc-js": "^1.7.1",
+ "@opentelemetry/core": "2.2.0",
+ "@opentelemetry/exporter-metrics-otlp-http": "0.208.0",
+ "@opentelemetry/otlp-exporter-base": "0.208.0",
+ "@opentelemetry/otlp-grpc-exporter-base": "0.208.0",
+ "@opentelemetry/otlp-transformer": "0.208.0",
+ "@opentelemetry/resources": "2.2.0",
+ "@opentelemetry/sdk-metrics": "2.2.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-metrics-otlp-grpc/node_modules/@opentelemetry/core": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.2.0.tgz",
+ "integrity": "sha512-FuabnnUm8LflnieVxs6eP7Z383hgQU4W1e3KJS6aOG3RxWxcHyBxH8fDMHNgu/gFx/M2jvTOW/4/PHhLz6bjWw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-metrics-otlp-grpc/node_modules/@opentelemetry/resources": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.2.0.tgz",
+ "integrity": "sha512-1pNQf/JazQTMA0BiO5NINUzH0cbLbbl7mntLa4aJNmCCXSj0q03T5ZXXL0zw4G55TjdL9Tz32cznGClf+8zr5A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.2.0",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-metrics-otlp-grpc/node_modules/@opentelemetry/sdk-metrics": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.2.0.tgz",
+ "integrity": "sha512-G5KYP6+VJMZzpGipQw7Giif48h6SGQ2PFKEYCybeXJsOCB4fp8azqMAAzE5lnnHK3ZVwYQrgmFbsUJO/zOnwGw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.2.0",
+ "@opentelemetry/resources": "2.2.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.9.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-metrics-otlp-http": {
+ "version": "0.208.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-http/-/exporter-metrics-otlp-http-0.208.0.tgz",
+ "integrity": "sha512-QZ3TrI90Y0i1ezWQdvreryjY0a5TK4J9gyDLIyhLBwV+EQUvyp5wR7TFPKCAexD4TDSWM0t3ulQDbYYjVtzTyA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.2.0",
+ "@opentelemetry/otlp-exporter-base": "0.208.0",
+ "@opentelemetry/otlp-transformer": "0.208.0",
+ "@opentelemetry/resources": "2.2.0",
+ "@opentelemetry/sdk-metrics": "2.2.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-metrics-otlp-http/node_modules/@opentelemetry/core": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.2.0.tgz",
+ "integrity": "sha512-FuabnnUm8LflnieVxs6eP7Z383hgQU4W1e3KJS6aOG3RxWxcHyBxH8fDMHNgu/gFx/M2jvTOW/4/PHhLz6bjWw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-metrics-otlp-http/node_modules/@opentelemetry/resources": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.2.0.tgz",
+ "integrity": "sha512-1pNQf/JazQTMA0BiO5NINUzH0cbLbbl7mntLa4aJNmCCXSj0q03T5ZXXL0zw4G55TjdL9Tz32cznGClf+8zr5A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.2.0",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-metrics-otlp-http/node_modules/@opentelemetry/sdk-metrics": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.2.0.tgz",
+ "integrity": "sha512-G5KYP6+VJMZzpGipQw7Giif48h6SGQ2PFKEYCybeXJsOCB4fp8azqMAAzE5lnnHK3ZVwYQrgmFbsUJO/zOnwGw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.2.0",
+ "@opentelemetry/resources": "2.2.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.9.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-metrics-otlp-proto": {
+ "version": "0.208.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-proto/-/exporter-metrics-otlp-proto-0.208.0.tgz",
+ "integrity": "sha512-CvvVD5kRDmRB/uSMalvEF6kiamY02pB46YAqclHtfjJccNZFxbkkXkMMmcJ7NgBFa5THmQBNVQ2AHyX29nRxOw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.2.0",
+ "@opentelemetry/exporter-metrics-otlp-http": "0.208.0",
+ "@opentelemetry/otlp-exporter-base": "0.208.0",
+ "@opentelemetry/otlp-transformer": "0.208.0",
+ "@opentelemetry/resources": "2.2.0",
+ "@opentelemetry/sdk-metrics": "2.2.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-metrics-otlp-proto/node_modules/@opentelemetry/core": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.2.0.tgz",
+ "integrity": "sha512-FuabnnUm8LflnieVxs6eP7Z383hgQU4W1e3KJS6aOG3RxWxcHyBxH8fDMHNgu/gFx/M2jvTOW/4/PHhLz6bjWw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-metrics-otlp-proto/node_modules/@opentelemetry/resources": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.2.0.tgz",
+ "integrity": "sha512-1pNQf/JazQTMA0BiO5NINUzH0cbLbbl7mntLa4aJNmCCXSj0q03T5ZXXL0zw4G55TjdL9Tz32cznGClf+8zr5A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.2.0",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-metrics-otlp-proto/node_modules/@opentelemetry/sdk-metrics": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.2.0.tgz",
+ "integrity": "sha512-G5KYP6+VJMZzpGipQw7Giif48h6SGQ2PFKEYCybeXJsOCB4fp8azqMAAzE5lnnHK3ZVwYQrgmFbsUJO/zOnwGw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.2.0",
+ "@opentelemetry/resources": "2.2.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.9.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-prometheus": {
+ "version": "0.208.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-prometheus/-/exporter-prometheus-0.208.0.tgz",
+ "integrity": "sha512-Rgws8GfIfq2iNWCD3G1dTD9xwYsCof1+tc5S5X0Ahdb5CrAPE+k5P70XCWHqrFFurVCcKaHLJ/6DjIBHWVfLiw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.2.0",
+ "@opentelemetry/resources": "2.2.0",
+ "@opentelemetry/sdk-metrics": "2.2.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-prometheus/node_modules/@opentelemetry/core": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.2.0.tgz",
+ "integrity": "sha512-FuabnnUm8LflnieVxs6eP7Z383hgQU4W1e3KJS6aOG3RxWxcHyBxH8fDMHNgu/gFx/M2jvTOW/4/PHhLz6bjWw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-prometheus/node_modules/@opentelemetry/resources": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.2.0.tgz",
+ "integrity": "sha512-1pNQf/JazQTMA0BiO5NINUzH0cbLbbl7mntLa4aJNmCCXSj0q03T5ZXXL0zw4G55TjdL9Tz32cznGClf+8zr5A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.2.0",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-prometheus/node_modules/@opentelemetry/sdk-metrics": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.2.0.tgz",
+ "integrity": "sha512-G5KYP6+VJMZzpGipQw7Giif48h6SGQ2PFKEYCybeXJsOCB4fp8azqMAAzE5lnnHK3ZVwYQrgmFbsUJO/zOnwGw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.2.0",
+ "@opentelemetry/resources": "2.2.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.9.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-trace-otlp-grpc": {
+ "version": "0.208.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-grpc/-/exporter-trace-otlp-grpc-0.208.0.tgz",
+ "integrity": "sha512-E/eNdcqVUTAT7BC+e8VOw/krqb+5rjzYkztMZ/o+eyJl+iEY6PfczPXpwWuICwvsm0SIhBoh9hmYED5Vh5RwIw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@grpc/grpc-js": "^1.7.1",
+ "@opentelemetry/core": "2.2.0",
+ "@opentelemetry/otlp-exporter-base": "0.208.0",
+ "@opentelemetry/otlp-grpc-exporter-base": "0.208.0",
+ "@opentelemetry/otlp-transformer": "0.208.0",
+ "@opentelemetry/resources": "2.2.0",
+ "@opentelemetry/sdk-trace-base": "2.2.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-trace-otlp-grpc/node_modules/@opentelemetry/core": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.2.0.tgz",
+ "integrity": "sha512-FuabnnUm8LflnieVxs6eP7Z383hgQU4W1e3KJS6aOG3RxWxcHyBxH8fDMHNgu/gFx/M2jvTOW/4/PHhLz6bjWw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-trace-otlp-grpc/node_modules/@opentelemetry/resources": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.2.0.tgz",
+ "integrity": "sha512-1pNQf/JazQTMA0BiO5NINUzH0cbLbbl7mntLa4aJNmCCXSj0q03T5ZXXL0zw4G55TjdL9Tz32cznGClf+8zr5A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.2.0",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-trace-otlp-http": {
+ "version": "0.208.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.208.0.tgz",
+ "integrity": "sha512-jbzDw1q+BkwKFq9yxhjAJ9rjKldbt5AgIy1gmEIJjEV/WRxQ3B6HcLVkwbjJ3RcMif86BDNKR846KJ0tY0aOJA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.2.0",
+ "@opentelemetry/otlp-exporter-base": "0.208.0",
+ "@opentelemetry/otlp-transformer": "0.208.0",
+ "@opentelemetry/resources": "2.2.0",
+ "@opentelemetry/sdk-trace-base": "2.2.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-trace-otlp-http/node_modules/@opentelemetry/core": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.2.0.tgz",
+ "integrity": "sha512-FuabnnUm8LflnieVxs6eP7Z383hgQU4W1e3KJS6aOG3RxWxcHyBxH8fDMHNgu/gFx/M2jvTOW/4/PHhLz6bjWw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-trace-otlp-http/node_modules/@opentelemetry/resources": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.2.0.tgz",
+ "integrity": "sha512-1pNQf/JazQTMA0BiO5NINUzH0cbLbbl7mntLa4aJNmCCXSj0q03T5ZXXL0zw4G55TjdL9Tz32cznGClf+8zr5A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.2.0",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-trace-otlp-proto": {
+ "version": "0.208.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-proto/-/exporter-trace-otlp-proto-0.208.0.tgz",
+ "integrity": "sha512-q844Jc3ApkZVdWYd5OAl+an3n1XXf3RWHa3Zgmnhw3HpsM3VluEKHckUUEqHPzbwDUx2lhPRVkqK7LsJ/CbDzA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.2.0",
+ "@opentelemetry/otlp-exporter-base": "0.208.0",
+ "@opentelemetry/otlp-transformer": "0.208.0",
+ "@opentelemetry/resources": "2.2.0",
+ "@opentelemetry/sdk-trace-base": "2.2.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-trace-otlp-proto/node_modules/@opentelemetry/core": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.2.0.tgz",
+ "integrity": "sha512-FuabnnUm8LflnieVxs6eP7Z383hgQU4W1e3KJS6aOG3RxWxcHyBxH8fDMHNgu/gFx/M2jvTOW/4/PHhLz6bjWw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-trace-otlp-proto/node_modules/@opentelemetry/resources": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.2.0.tgz",
+ "integrity": "sha512-1pNQf/JazQTMA0BiO5NINUzH0cbLbbl7mntLa4aJNmCCXSj0q03T5ZXXL0zw4G55TjdL9Tz32cznGClf+8zr5A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.2.0",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-zipkin": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-zipkin/-/exporter-zipkin-2.2.0.tgz",
+ "integrity": "sha512-VV4QzhGCT7cWrGasBWxelBjqbNBbyHicWWS/66KoZoe9BzYwFB72SH2/kkc4uAviQlO8iwv2okIJy+/jqqEHTg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.2.0",
+ "@opentelemetry/resources": "2.2.0",
+ "@opentelemetry/sdk-trace-base": "2.2.0",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-zipkin/node_modules/@opentelemetry/core": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.2.0.tgz",
+ "integrity": "sha512-FuabnnUm8LflnieVxs6eP7Z383hgQU4W1e3KJS6aOG3RxWxcHyBxH8fDMHNgu/gFx/M2jvTOW/4/PHhLz6bjWw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-zipkin/node_modules/@opentelemetry/resources": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.2.0.tgz",
+ "integrity": "sha512-1pNQf/JazQTMA0BiO5NINUzH0cbLbbl7mntLa4aJNmCCXSj0q03T5ZXXL0zw4G55TjdL9Tz32cznGClf+8zr5A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.2.0",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation": {
+ "version": "0.208.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.208.0.tgz",
+ "integrity": "sha512-Eju0L4qWcQS+oXxi6pgh7zvE2byogAkcsVv0OjHF/97iOz1N/aKE6etSGowYkie+YA1uo6DNwdSxaaNnLvcRlA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api-logs": "0.208.0",
+ "import-in-the-middle": "^2.0.0",
+ "require-in-the-middle": "^8.0.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-amqplib": {
+ "version": "0.56.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-amqplib/-/instrumentation-amqplib-0.56.0.tgz",
+ "integrity": "sha512-/orV2zO2K7iGa1TR6lbs170LNNDbeTC6E3JF1EeB+okJ3rB5tl1gHFSjoqEDkQYFprNs5CPitqU8Y4l4S2Pkmg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "^2.0.0",
+ "@opentelemetry/instrumentation": "^0.208.0",
+ "@opentelemetry/semantic-conventions": "^1.33.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-aws-lambda": {
+ "version": "0.61.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-aws-lambda/-/instrumentation-aws-lambda-0.61.1.tgz",
+ "integrity": "sha512-leISmqN7/KSCYAKEVOAnQ0NUCa3rigB7ShCVLnYrHr6+7CXPef7C+nvowElMcYTid8egiHKgApR/FaNdlBda3A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.208.0",
+ "@opentelemetry/semantic-conventions": "^1.27.0",
+ "@types/aws-lambda": "^8.10.155"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-aws-sdk": {
+ "version": "0.64.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-aws-sdk/-/instrumentation-aws-sdk-0.64.1.tgz",
+ "integrity": "sha512-A8joPAuHwvwrkG5UpH7OYhzkeYznNBiG3o1TKoZ7yvyXU/q4CNxnZ7vzZBEpt9OocptCe6X/YyBENFSa0axqiw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "^2.0.0",
+ "@opentelemetry/instrumentation": "^0.208.0",
+ "@opentelemetry/semantic-conventions": "^1.34.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-bunyan": {
+ "version": "0.54.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-bunyan/-/instrumentation-bunyan-0.54.0.tgz",
+ "integrity": "sha512-DnPoHSLcKwQmueW+7OOaXFD/cj1M6hqwTm6P88QdMbln/dqEatLxzt/ACPk4Yb5x4aU3ZLyeLyKxtzfhp76+aw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api-logs": "^0.208.0",
+ "@opentelemetry/instrumentation": "^0.208.0",
+ "@types/bunyan": "1.8.11"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-cassandra-driver": {
+ "version": "0.54.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-cassandra-driver/-/instrumentation-cassandra-driver-0.54.1.tgz",
+ "integrity": "sha512-wVGI4YrWmaNNtNjg84KTl8sHebG7jm3PHvmZxPl2V/aSskAyQMSxgJZpnv1dmBmJuISc+a8H8daporljbscCcQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.208.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-connect": {
+ "version": "0.52.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-connect/-/instrumentation-connect-0.52.0.tgz",
+ "integrity": "sha512-GXPxfNB5szMbV3I9b7kNWSmQBoBzw7MT0ui6iU/p+NIzVx3a06Ri2cdQO7tG9EKb4aKSLmfX9Cw5cKxXqX6Ohg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "^2.0.0",
+ "@opentelemetry/instrumentation": "^0.208.0",
+ "@opentelemetry/semantic-conventions": "^1.27.0",
+ "@types/connect": "3.4.38"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-cucumber": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-cucumber/-/instrumentation-cucumber-0.24.0.tgz",
+ "integrity": "sha512-ICHrmax9PwU/Z+fehD0uIjM8W0cEvdToglV1+o76Mgw51HZBVp2Y3mkga1qMPIN5tPMoWUYoYtI4U85rea5HYg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.208.0",
+ "@opentelemetry/semantic-conventions": "^1.27.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-dataloader": {
+ "version": "0.26.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-dataloader/-/instrumentation-dataloader-0.26.1.tgz",
+ "integrity": "sha512-S2JAM6lV16tMravuPLd3tJCC6ySb5a//5KgJeXutbTVb/UbSTXcnHSdEtMaAvE2KbazVWyWzcoytLRy6AUOwsw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.208.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-dns": {
+ "version": "0.52.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-dns/-/instrumentation-dns-0.52.0.tgz",
+ "integrity": "sha512-XJvS8PkZec+X6HhOi1xldJydTpmIUAW14+1vyqwAK97LWKXlxmiWst8/fjZ709+CHgshz8i5V37yCHlr6o3pxw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.208.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-express": {
+ "version": "0.57.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-express/-/instrumentation-express-0.57.1.tgz",
+ "integrity": "sha512-r+ulPbvgG8rGgFFWbJWJpTh7nMzsEYH7rBFNWdFs7ZfVAtgpFijMkRtU7DecIo6ItF8Op+RxogSuk/083W8HKw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "^2.0.0",
+ "@opentelemetry/instrumentation": "^0.208.0",
+ "@opentelemetry/semantic-conventions": "^1.27.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-fastify": {
+ "version": "0.53.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-fastify/-/instrumentation-fastify-0.53.1.tgz",
+ "integrity": "sha512-tTa84J9rcrl4iTHdJDwirrNbM4prgJH+MF0iMlVLu++6gZg8TTfmYYqDiKPWBgdXB4M+bnlCkvgag36uV34uwA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "^2.0.0",
+ "@opentelemetry/instrumentation": "^0.208.0",
+ "@opentelemetry/semantic-conventions": "^1.27.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-fs": {
+ "version": "0.28.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-fs/-/instrumentation-fs-0.28.0.tgz",
+ "integrity": "sha512-FFvg8fq53RRXVBRHZViP+EMxMR03tqzEGpuq55lHNbVPyFklSVfQBN50syPhK5UYYwaStx0eyCtHtbRreusc5g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "^2.0.0",
+ "@opentelemetry/instrumentation": "^0.208.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-generic-pool": {
+ "version": "0.52.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-generic-pool/-/instrumentation-generic-pool-0.52.0.tgz",
+ "integrity": "sha512-ISkNcv5CM2IwvsMVL31Tl61/p2Zm2I2NAsYq5SSBgOsOndT0TjnptjufYVScCnD5ZLD1tpl4T3GEYULLYOdIdQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.208.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-graphql": {
+ "version": "0.56.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-graphql/-/instrumentation-graphql-0.56.0.tgz",
+ "integrity": "sha512-IPvNk8AFoVzTAM0Z399t34VDmGDgwT6rIqCUug8P9oAGerl2/PEIYMPOl/rerPGu+q8gSWdmbFSjgg7PDVRd3Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.208.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-grpc": {
+ "version": "0.208.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-grpc/-/instrumentation-grpc-0.208.0.tgz",
+ "integrity": "sha512-8hFEQRAiOyIWO6LYj7tUfdAgNCuQUdYjLYMItRYlOLGJhshGdGYD7aeNzt2H+HPMDEWnKWqldIHfLTqM7ep7gg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "0.208.0",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-hapi": {
+ "version": "0.55.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-hapi/-/instrumentation-hapi-0.55.1.tgz",
+ "integrity": "sha512-Pm1HCHnnijUOGXd+nyJp96CfU8Lb6XdT6H6YvvmXO/NHMb6tV+EjzDRBr9sZ/XQjka9zLCz7jR0js7ut0IJAyg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "^2.0.0",
+ "@opentelemetry/instrumentation": "^0.208.0",
+ "@opentelemetry/semantic-conventions": "^1.27.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-http": {
+ "version": "0.208.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-http/-/instrumentation-http-0.208.0.tgz",
+ "integrity": "sha512-rhmK46DRWEbQQB77RxmVXGyjs6783crXCnFjYQj+4tDH/Kpv9Rbg3h2kaNyp5Vz2emF1f9HOQQvZoHzwMWOFZQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.2.0",
+ "@opentelemetry/instrumentation": "0.208.0",
+ "@opentelemetry/semantic-conventions": "^1.29.0",
+ "forwarded-parse": "2.1.2"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-http/node_modules/@opentelemetry/core": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.2.0.tgz",
+ "integrity": "sha512-FuabnnUm8LflnieVxs6eP7Z383hgQU4W1e3KJS6aOG3RxWxcHyBxH8fDMHNgu/gFx/M2jvTOW/4/PHhLz6bjWw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-ioredis": {
+ "version": "0.57.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-ioredis/-/instrumentation-ioredis-0.57.0.tgz",
+ "integrity": "sha512-o/PYGPbfFbS0Sq8EEQC8YUgDMiTGvwoMejPjV2d466yJoii+BUpffGejVQN0hC5V5/GT29m1B1jL+3yruNxwDw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.208.0",
+ "@opentelemetry/redis-common": "^0.38.2",
+ "@opentelemetry/semantic-conventions": "^1.33.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-kafkajs": {
+ "version": "0.18.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-kafkajs/-/instrumentation-kafkajs-0.18.1.tgz",
+ "integrity": "sha512-qM9hk7BIsVWqWJsrCa1fAEcEfutVvwhHO9kk4vpwaTGYR+lPWRk2r5+nEPcM+sIiYBmQNJCef5tEjQpKxTpP0A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.208.0",
+ "@opentelemetry/semantic-conventions": "^1.30.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-knex": {
+ "version": "0.53.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-knex/-/instrumentation-knex-0.53.1.tgz",
+ "integrity": "sha512-tIW3gqVC8d9CCE+oxPO63WNvC+5PKC/LrPrYWFobii5afUpHJV+0pfyt08okAFBHztzT0voMOEPGkLKoacZRXQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.208.0",
+ "@opentelemetry/semantic-conventions": "^1.33.1"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-koa": {
+ "version": "0.57.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-koa/-/instrumentation-koa-0.57.1.tgz",
+ "integrity": "sha512-XPjdzgXvMG3YSZvsSgOj0Je0fsmlaBYIFFGJqUn1HRpbrVjdpP45eXI+6yUp48J8N5Qss32WDD5f+2tmV7Xvsg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "^2.0.0",
+ "@opentelemetry/instrumentation": "^0.208.0",
+ "@opentelemetry/semantic-conventions": "^1.36.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.9.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-lru-memoizer": {
+ "version": "0.53.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-lru-memoizer/-/instrumentation-lru-memoizer-0.53.1.tgz",
+ "integrity": "sha512-L93bPJKFzrObD4FvKpsavYEFTzXFKMmAeRHz7J4lUFc7TPZLouxX3PYW1+YGr/bT1y24H9NLNX66l7BW1s75QA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.208.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-memcached": {
+ "version": "0.52.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-memcached/-/instrumentation-memcached-0.52.1.tgz",
+ "integrity": "sha512-qg92SyWAypSZmX3Lhm2wz4BsovKarkWg9OHm4DPW6fGzmk40eB5voQIuctrBAfsml6gr+vbg4VEBcC1AKRvzzQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.208.0",
+ "@opentelemetry/semantic-conventions": "^1.33.0",
+ "@types/memcached": "^2.2.6"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-mongodb": {
+ "version": "0.62.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongodb/-/instrumentation-mongodb-0.62.0.tgz",
+ "integrity": "sha512-hcEEW26ToGVpQGblXk9m3p2cXkBu9j2bcyeevS/ahujr1WodfrItmMldWCEJkmN4+4uMo9pb6jAMhm6bZIMnig==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.208.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-mongoose": {
+ "version": "0.55.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongoose/-/instrumentation-mongoose-0.55.1.tgz",
+ "integrity": "sha512-M2MusLn/31YOt176Y6qXJQcpDuZPmq/fqQ9vIaKb4x/qIJ3oYO2lT45SUMFmZpODEhrpYXgGaEKwG6TGXhlosA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "^2.0.0",
+ "@opentelemetry/instrumentation": "^0.208.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-mysql": {
+ "version": "0.55.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql/-/instrumentation-mysql-0.55.0.tgz",
+ "integrity": "sha512-tEGaVMzqAlwhoDomaUWOP2H4KkK16m18qq+TZoyvcSe9O21UxnYFWQa87a4kmc7N4Q6Q70L/YhwDt+fC+NDRBA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.208.0",
+ "@opentelemetry/semantic-conventions": "^1.33.0",
+ "@types/mysql": "2.15.27"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-mysql2": {
+ "version": "0.55.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql2/-/instrumentation-mysql2-0.55.1.tgz",
+ "integrity": "sha512-/cw7TzEmeaCQ5xi+FwrCWQUlY8v9RXjN5tqtb0D1sgBedfiV6DvW+dlMl1jo6Nkx9eSHmGcDy9IjyR0frHpKLg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.208.0",
+ "@opentelemetry/semantic-conventions": "^1.33.0",
+ "@opentelemetry/sql-common": "^0.41.2"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-nestjs-core": {
+ "version": "0.55.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-nestjs-core/-/instrumentation-nestjs-core-0.55.0.tgz",
+ "integrity": "sha512-JFLNhbbEGnnQrMKOYoXx0nNk5N9cPeghu4xP/oup40a7VaSeYruyOiFbg9nkbS4ZQiI8aMuRqUT3Mo4lQjKEKg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.208.0",
+ "@opentelemetry/semantic-conventions": "^1.30.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-net": {
+ "version": "0.53.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-net/-/instrumentation-net-0.53.0.tgz",
+ "integrity": "sha512-d8tU5z0fx28z622RwVwU4zfNt40EKxzEcQcaPzch/CqpkKNAlvBOW/1K9OkjNdydpsKqxpMkbjvo3tY6PD1EMA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.208.0",
+ "@opentelemetry/semantic-conventions": "^1.33.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-openai": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-openai/-/instrumentation-openai-0.7.1.tgz",
+ "integrity": "sha512-QDnnAYxByJoJ3jMly/EwRbXhnfZpGigfBcHyPcgWEMR4bfawJZhdOdFi1GVcC4ImdS7fGaYQOTX1WW24mftISg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api-logs": "^0.208.0",
+ "@opentelemetry/instrumentation": "^0.208.0",
+ "@opentelemetry/semantic-conventions": "^1.36.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-oracledb": {
+ "version": "0.34.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-oracledb/-/instrumentation-oracledb-0.34.1.tgz",
+ "integrity": "sha512-RI5EV3ZIkHA748dPm4hwLkUnqYU/rrBcq+qA5cNks0dZaAgsu46XMA/MEPcubrBSsgaG1NAIG78P9NLZs2gN/A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.208.0",
+ "@opentelemetry/semantic-conventions": "^1.34.0",
+ "@types/oracledb": "6.5.2"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-pg": {
+ "version": "0.61.2",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pg/-/instrumentation-pg-0.61.2.tgz",
+ "integrity": "sha512-l1tN4dX8Ig1bKzMu81Q1EBXWFRy9wqchXbeHDRniJsXYND5dC8u1Uhah7wz1zZta3fbBWflP2mJZcDPWNsAMRg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "^2.0.0",
+ "@opentelemetry/instrumentation": "^0.208.0",
+ "@opentelemetry/semantic-conventions": "^1.34.0",
+ "@opentelemetry/sql-common": "^0.41.2",
+ "@types/pg": "8.15.6",
+ "@types/pg-pool": "2.0.6"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-pg/node_modules/@types/pg": {
+ "version": "8.15.6",
+ "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.15.6.tgz",
+ "integrity": "sha512-NoaMtzhxOrubeL/7UZuNTrejB4MPAJ0RpxZqXQf2qXuVlTPuG6Y8p4u9dKRaue4yjmC7ZhzVO2/Yyyn25znrPQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*",
+ "pg-protocol": "*",
+ "pg-types": "^2.2.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-pino": {
+ "version": "0.55.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pino/-/instrumentation-pino-0.55.1.tgz",
+ "integrity": "sha512-rt35H5vvP9KA1xrMrJGsnqwcVxyt8dher04pR64gvX4rxLwsmijUF1cEMbPZ2O8jXpeV8nAIzGHBnWEYp5ILNA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api-logs": "^0.208.0",
+ "@opentelemetry/core": "^2.0.0",
+ "@opentelemetry/instrumentation": "^0.208.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-redis": {
+ "version": "0.57.2",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-redis/-/instrumentation-redis-0.57.2.tgz",
+ "integrity": "sha512-vD1nzOUDOPjnvDCny7fmRSX/hMTFzPUCZKADF5tQ5DvBqlOEV/de/tOkwvIwo9YX956EBMT+8qSjhd7qPXFkRw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.208.0",
+ "@opentelemetry/redis-common": "^0.38.2",
+ "@opentelemetry/semantic-conventions": "^1.27.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-restify": {
+ "version": "0.54.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-restify/-/instrumentation-restify-0.54.0.tgz",
+ "integrity": "sha512-V6kCoAtU8jLuUi9hr3IEWVTHr8d8s4wObV1DlI/A+VzYToK1W4Zv1SI8x3hiF0yR1poRjOY6rl91Q427HHTMww==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "^2.0.0",
+ "@opentelemetry/instrumentation": "^0.208.0",
+ "@opentelemetry/semantic-conventions": "^1.27.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-router": {
+ "version": "0.53.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-router/-/instrumentation-router-0.53.0.tgz",
+ "integrity": "sha512-3gF9jJ7C3lwlCOer1KzKKdpLr6/c7yOZBP44KI+Xi/TqiZjhsfUlHjetzC6BLDjkSk1DnIGyf+YzJR4aF5dJBQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.208.0",
+ "@opentelemetry/semantic-conventions": "^1.27.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-runtime-node": {
+ "version": "0.22.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-runtime-node/-/instrumentation-runtime-node-0.22.0.tgz",
+ "integrity": "sha512-27aodhzdWqPuPVWM2UsLYz2gl6yLRqLP7Z6Kn6ukUx/I+9oruaztJkLtYg4SqCrm/7Nsv9FIly7gO3/ZyDIMPg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.208.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-socket.io": {
+ "version": "0.55.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-socket.io/-/instrumentation-socket.io-0.55.1.tgz",
+ "integrity": "sha512-KQaOvZlw7NpA/VDRJdm45FIdzt4hXrDhvtmLU5a2AttcTI9e/VpVg4Y/LPOXM+o29VkKxETZzJfRlOJEIHl+uQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.208.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-tedious": {
+ "version": "0.28.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-tedious/-/instrumentation-tedious-0.28.0.tgz",
+ "integrity": "sha512-nQ9k1Bdk2yG4SPRuHZ+QVcc3YMm2sfsBV1MQIc/Y/OcN83Q+jA7gXgYgYIblQ1wI+/RtKlJpdl6hobAXuj+pSA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.208.0",
+ "@opentelemetry/semantic-conventions": "^1.33.0",
+ "@types/tedious": "^4.0.14"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-undici": {
+ "version": "0.19.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.19.0.tgz",
+ "integrity": "sha512-Pst/RhR61A2OoZQZkn6OLpdVpXp6qn3Y92wXa6umfJe9rV640r4bc6SWvw4pPN6DiQqPu2c8gnSSZPDtC6JlpQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "^2.0.0",
+ "@opentelemetry/instrumentation": "^0.208.0",
+ "@opentelemetry/semantic-conventions": "^1.24.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.7.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-winston": {
+ "version": "0.53.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-winston/-/instrumentation-winston-0.53.0.tgz",
+ "integrity": "sha512-yF9v0DphyG715er1HG1pbweNUSygvc22xw2s2Y8E8oaEMJo2/nH3Ww/8c4K6gdI/6xvi2unla1KQBCYN4uCo8w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api-logs": "^0.208.0",
+ "@opentelemetry/instrumentation": "^0.208.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/otlp-exporter-base": {
+ "version": "0.208.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.208.0.tgz",
+ "integrity": "sha512-gMd39gIfVb2OgxldxUtOwGJYSH8P1kVFFlJLuut32L6KgUC4gl1dMhn+YC2mGn0bDOiQYSk/uHOdSjuKp58vvA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.2.0",
+ "@opentelemetry/otlp-transformer": "0.208.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/otlp-exporter-base/node_modules/@opentelemetry/core": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.2.0.tgz",
+ "integrity": "sha512-FuabnnUm8LflnieVxs6eP7Z383hgQU4W1e3KJS6aOG3RxWxcHyBxH8fDMHNgu/gFx/M2jvTOW/4/PHhLz6bjWw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/otlp-grpc-exporter-base": {
+ "version": "0.208.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-grpc-exporter-base/-/otlp-grpc-exporter-base-0.208.0.tgz",
+ "integrity": "sha512-fGvAg3zb8fC0oJAzfz7PQppADI2HYB7TSt/XoCaBJFi1mSquNUjtHXEoviMgObLAa1NRIgOC1lsV1OUKi+9+lQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@grpc/grpc-js": "^1.7.1",
+ "@opentelemetry/core": "2.2.0",
+ "@opentelemetry/otlp-exporter-base": "0.208.0",
+ "@opentelemetry/otlp-transformer": "0.208.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/otlp-grpc-exporter-base/node_modules/@opentelemetry/core": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.2.0.tgz",
+ "integrity": "sha512-FuabnnUm8LflnieVxs6eP7Z383hgQU4W1e3KJS6aOG3RxWxcHyBxH8fDMHNgu/gFx/M2jvTOW/4/PHhLz6bjWw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/otlp-transformer": {
+ "version": "0.208.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.208.0.tgz",
+ "integrity": "sha512-DCFPY8C6lAQHUNkzcNT9R+qYExvsk6C5Bto2pbNxgicpcSWbe2WHShLxkOxIdNcBiYPdVHv/e7vH7K6TI+C+fQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api-logs": "0.208.0",
+ "@opentelemetry/core": "2.2.0",
+ "@opentelemetry/resources": "2.2.0",
+ "@opentelemetry/sdk-logs": "0.208.0",
+ "@opentelemetry/sdk-metrics": "2.2.0",
+ "@opentelemetry/sdk-trace-base": "2.2.0",
+ "protobufjs": "^7.3.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/otlp-transformer/node_modules/@opentelemetry/core": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.2.0.tgz",
+ "integrity": "sha512-FuabnnUm8LflnieVxs6eP7Z383hgQU4W1e3KJS6aOG3RxWxcHyBxH8fDMHNgu/gFx/M2jvTOW/4/PHhLz6bjWw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/otlp-transformer/node_modules/@opentelemetry/resources": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.2.0.tgz",
+ "integrity": "sha512-1pNQf/JazQTMA0BiO5NINUzH0cbLbbl7mntLa4aJNmCCXSj0q03T5ZXXL0zw4G55TjdL9Tz32cznGClf+8zr5A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.2.0",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/otlp-transformer/node_modules/@opentelemetry/sdk-metrics": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.2.0.tgz",
+ "integrity": "sha512-G5KYP6+VJMZzpGipQw7Giif48h6SGQ2PFKEYCybeXJsOCB4fp8azqMAAzE5lnnHK3ZVwYQrgmFbsUJO/zOnwGw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.2.0",
+ "@opentelemetry/resources": "2.2.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.9.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/propagator-b3": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-b3/-/propagator-b3-2.2.0.tgz",
+ "integrity": "sha512-9CrbTLFi5Ee4uepxg2qlpQIozoJuoAZU5sKMx0Mn7Oh+p7UrgCiEV6C02FOxxdYVRRFQVCinYR8Kf6eMSQsIsw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.2.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/propagator-b3/node_modules/@opentelemetry/core": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.2.0.tgz",
+ "integrity": "sha512-FuabnnUm8LflnieVxs6eP7Z383hgQU4W1e3KJS6aOG3RxWxcHyBxH8fDMHNgu/gFx/M2jvTOW/4/PHhLz6bjWw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/propagator-jaeger": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-jaeger/-/propagator-jaeger-2.2.0.tgz",
+ "integrity": "sha512-FfeOHOrdhiNzecoB1jZKp2fybqmqMPJUXe2ZOydP7QzmTPYcfPeuaclTLYVhK3HyJf71kt8sTl92nV4YIaLaKA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.2.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/propagator-jaeger/node_modules/@opentelemetry/core": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.2.0.tgz",
+ "integrity": "sha512-FuabnnUm8LflnieVxs6eP7Z383hgQU4W1e3KJS6aOG3RxWxcHyBxH8fDMHNgu/gFx/M2jvTOW/4/PHhLz6bjWw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/redis-common": {
+ "version": "0.38.2",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/redis-common/-/redis-common-0.38.2.tgz",
+ "integrity": "sha512-1BCcU93iwSRZvDAgwUxC/DV4T/406SkMfxGqu5ojc3AvNI+I9GhV7v0J1HljsczuuhcnFLYqD5VmwVXfCGHzxA==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ }
+ },
+ "node_modules/@opentelemetry/resource-detector-alibaba-cloud": {
+ "version": "0.32.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-alibaba-cloud/-/resource-detector-alibaba-cloud-0.32.0.tgz",
+ "integrity": "sha512-W+n4ZIbNndOaW6xlGeW7afKQeCMNlOHsSflGRLkzjnSfAl2tWJU5Mhr6hf/t6m8uhic71psHx/CoFQMsRQKnvQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "^2.0.0",
+ "@opentelemetry/resources": "^2.0.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/resource-detector-aws": {
+ "version": "2.11.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-aws/-/resource-detector-aws-2.11.0.tgz",
+ "integrity": "sha512-Wphbm9fGyinMLC8BiLU/5aK6yG191ws2q2SN4biCcQZQCTo6yEij4ka+fXQXAiLMGSzb5w8wa/FxOn/7KWPiSQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "^2.0.0",
+ "@opentelemetry/resources": "^2.0.0",
+ "@opentelemetry/semantic-conventions": "^1.27.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/resource-detector-azure": {
+ "version": "0.17.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-azure/-/resource-detector-azure-0.17.0.tgz",
+ "integrity": "sha512-JGNPW+Om8MNiVOK1Jl5jg3znGJQP7YeGsgRQiegftqEZj0th8e1Uf6U5s6H672KBT442WDGOG0a4du5xJgJB5w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "^2.0.0",
+ "@opentelemetry/resources": "^2.0.0",
+ "@opentelemetry/semantic-conventions": "^1.37.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/resource-detector-container": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-container/-/resource-detector-container-0.8.2.tgz",
+ "integrity": "sha512-8oT0tUO+QS8Tz7u0YQZKoZOpS+LIgS4FnLjWSCPyXPOgKuOeOK5Xe0sd0ulkAGPN4yKr7toNYNVkBeaC/HlmFQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "^2.0.0",
+ "@opentelemetry/resources": "^2.0.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/resource-detector-gcp": {
+ "version": "0.44.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-gcp/-/resource-detector-gcp-0.44.0.tgz",
+ "integrity": "sha512-sj9WSSjMyZJDP7DSmfQpsfivM2sQECwhjAmK6V97uVAeJiXSMiPhfo3fZi0Hpu+GQQ1Wb09qQIkwkMjwr0MH/g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "^2.0.0",
+ "@opentelemetry/resources": "^2.0.0",
+ "gcp-metadata": "^6.0.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/resources": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.5.0.tgz",
+ "integrity": "sha512-F8W52ApePshpoSrfsSk1H2yJn9aKjCrbpQF1M9Qii0GHzbfVeFUB+rc3X4aggyZD8x9Gu3Slua+s6krmq6Dt8g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.5.0",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-logs": {
+ "version": "0.208.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.208.0.tgz",
+ "integrity": "sha512-QlAyL1jRpOeaqx7/leG1vJMp84g0xKP6gJmfELBpnI4O/9xPX+Hu5m1POk9Kl+veNkyth5t19hRlN6tNY1sjbA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api-logs": "0.208.0",
+ "@opentelemetry/core": "2.2.0",
+ "@opentelemetry/resources": "2.2.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.4.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-logs/node_modules/@opentelemetry/core": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.2.0.tgz",
+ "integrity": "sha512-FuabnnUm8LflnieVxs6eP7Z383hgQU4W1e3KJS6aOG3RxWxcHyBxH8fDMHNgu/gFx/M2jvTOW/4/PHhLz6bjWw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-logs/node_modules/@opentelemetry/resources": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.2.0.tgz",
+ "integrity": "sha512-1pNQf/JazQTMA0BiO5NINUzH0cbLbbl7mntLa4aJNmCCXSj0q03T5ZXXL0zw4G55TjdL9Tz32cznGClf+8zr5A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.2.0",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-metrics": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.5.0.tgz",
+ "integrity": "sha512-BeJLtU+f5Gf905cJX9vXFQorAr6TAfK3SPvTFqP+scfIpDQEJfRaGJWta7sJgP+m4dNtBf9y3yvBKVAZZtJQVA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.5.0",
+ "@opentelemetry/resources": "2.5.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.9.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-node": {
+ "version": "0.208.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-node/-/sdk-node-0.208.0.tgz",
+ "integrity": "sha512-pbAqpZ7zTMFuTf3YecYsecsto/mheuvnK2a/jgstsE5ynWotBjgF5bnz5500W9Xl2LeUfg04WMt63TWtAgzRMw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api-logs": "0.208.0",
+ "@opentelemetry/core": "2.2.0",
+ "@opentelemetry/exporter-logs-otlp-grpc": "0.208.0",
+ "@opentelemetry/exporter-logs-otlp-http": "0.208.0",
+ "@opentelemetry/exporter-logs-otlp-proto": "0.208.0",
+ "@opentelemetry/exporter-metrics-otlp-grpc": "0.208.0",
+ "@opentelemetry/exporter-metrics-otlp-http": "0.208.0",
+ "@opentelemetry/exporter-metrics-otlp-proto": "0.208.0",
+ "@opentelemetry/exporter-prometheus": "0.208.0",
+ "@opentelemetry/exporter-trace-otlp-grpc": "0.208.0",
+ "@opentelemetry/exporter-trace-otlp-http": "0.208.0",
+ "@opentelemetry/exporter-trace-otlp-proto": "0.208.0",
+ "@opentelemetry/exporter-zipkin": "2.2.0",
+ "@opentelemetry/instrumentation": "0.208.0",
+ "@opentelemetry/propagator-b3": "2.2.0",
+ "@opentelemetry/propagator-jaeger": "2.2.0",
+ "@opentelemetry/resources": "2.2.0",
+ "@opentelemetry/sdk-logs": "0.208.0",
+ "@opentelemetry/sdk-metrics": "2.2.0",
+ "@opentelemetry/sdk-trace-base": "2.2.0",
+ "@opentelemetry/sdk-trace-node": "2.2.0",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/core": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.2.0.tgz",
+ "integrity": "sha512-FuabnnUm8LflnieVxs6eP7Z383hgQU4W1e3KJS6aOG3RxWxcHyBxH8fDMHNgu/gFx/M2jvTOW/4/PHhLz6bjWw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/resources": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.2.0.tgz",
+ "integrity": "sha512-1pNQf/JazQTMA0BiO5NINUzH0cbLbbl7mntLa4aJNmCCXSj0q03T5ZXXL0zw4G55TjdL9Tz32cznGClf+8zr5A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.2.0",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/sdk-metrics": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.2.0.tgz",
+ "integrity": "sha512-G5KYP6+VJMZzpGipQw7Giif48h6SGQ2PFKEYCybeXJsOCB4fp8azqMAAzE5lnnHK3ZVwYQrgmFbsUJO/zOnwGw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.2.0",
+ "@opentelemetry/resources": "2.2.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.9.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-trace-base": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.2.0.tgz",
+ "integrity": "sha512-xWQgL0Bmctsalg6PaXExmzdedSp3gyKV8mQBwK/j9VGdCDu2fmXIb2gAehBKbkXCpJ4HPkgv3QfoJWRT4dHWbw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.2.0",
+ "@opentelemetry/resources": "2.2.0",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-trace-base/node_modules/@opentelemetry/core": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.2.0.tgz",
+ "integrity": "sha512-FuabnnUm8LflnieVxs6eP7Z383hgQU4W1e3KJS6aOG3RxWxcHyBxH8fDMHNgu/gFx/M2jvTOW/4/PHhLz6bjWw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-trace-base/node_modules/@opentelemetry/resources": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.2.0.tgz",
+ "integrity": "sha512-1pNQf/JazQTMA0BiO5NINUzH0cbLbbl7mntLa4aJNmCCXSj0q03T5ZXXL0zw4G55TjdL9Tz32cznGClf+8zr5A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.2.0",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-trace-node": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-node/-/sdk-trace-node-2.2.0.tgz",
+ "integrity": "sha512-+OaRja3f0IqGG2kptVeYsrZQK9nKRSpfFrKtRBq4uh6nIB8bTBgaGvYQrQoRrQWQMA5dK5yLhDMDc0dvYvCOIQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/context-async-hooks": "2.2.0",
+ "@opentelemetry/core": "2.2.0",
+ "@opentelemetry/sdk-trace-base": "2.2.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-trace-node/node_modules/@opentelemetry/core": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.2.0.tgz",
+ "integrity": "sha512-FuabnnUm8LflnieVxs6eP7Z383hgQU4W1e3KJS6aOG3RxWxcHyBxH8fDMHNgu/gFx/M2jvTOW/4/PHhLz6bjWw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/semantic-conventions": {
+ "version": "1.39.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.39.0.tgz",
+ "integrity": "sha512-R5R9tb2AXs2IRLNKLBJDynhkfmx7mX0vi8NkhZb3gUkPWHn6HXk5J8iQ/dql0U3ApfWym4kXXmBDRGO+oeOfjg==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@opentelemetry/sql-common": {
+ "version": "0.41.2",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sql-common/-/sql-common-0.41.2.tgz",
+ "integrity": "sha512-4mhWm3Z8z+i508zQJ7r6Xi7y4mmoJpdvH0fZPFRkWrdp5fq7hhZ2HhYokEOLkfqSMgPR4Z9EyB3DBkbKGOqZiQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "^2.0.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.1.0"
+ }
+ },
+ "node_modules/@oxc-project/runtime": {
+ "version": "0.92.0",
+ "resolved": "https://registry.npmjs.org/@oxc-project/runtime/-/runtime-0.92.0.tgz",
+ "integrity": "sha512-Z7x2dZOmznihvdvCvLKMl+nswtOSVxS2H2ocar+U9xx6iMfTp0VGIrX6a4xB1v80IwOPC7dT1LXIJrY70Xu3Jw==",
+ "license": "MIT",
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxc-project/types": {
+ "version": "0.93.0",
+ "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.93.0.tgz",
+ "integrity": "sha512-yNtwmWZIBtJsMr5TEfoZFDxIWV6OdScOpza/f5YxbqUMJk+j6QX3Cf3jgZShGEFYWQJ5j9mJ6jM0tZHu2J9Yrg==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/Boshen"
+ }
+ },
+ "node_modules/@pkgjs/parseargs": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
+ "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@playwright/test": {
+ "version": "1.58.0",
+ "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.58.0.tgz",
+ "integrity": "sha512-fWza+Lpbj6SkQKCrU6si4iu+fD2dD3gxNHFhUPxsfXBPhnv3rRSQVd0NtBUT9Z/RhF/boCBcuUaMUSTRTopjZg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "playwright": "1.58.0"
+ },
+ "bin": {
+ "playwright": "cli.js"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@protobufjs/aspromise": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
+ "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/base64": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz",
+ "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/codegen": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz",
+ "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/eventemitter": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz",
+ "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/fetch": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz",
+ "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@protobufjs/aspromise": "^1.1.1",
+ "@protobufjs/inquire": "^1.1.0"
+ }
+ },
+ "node_modules/@protobufjs/float": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz",
+ "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/inquire": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz",
+ "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/path": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz",
+ "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/pool": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz",
+ "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/utf8": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
+ "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@radix-ui/number": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.1.tgz",
+ "integrity": "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==",
+ "license": "MIT"
+ },
+ "node_modules/@radix-ui/primitive": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz",
+ "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==",
+ "license": "MIT"
+ },
+ "node_modules/@radix-ui/react-accordion": {
+ "version": "1.2.12",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-accordion/-/react-accordion-1.2.12.tgz",
+ "integrity": "sha512-T4nygeh9YE9dLRPhAHSeOZi7HBXo+0kYIPJXayZfvWOWA0+n3dESrZbjfDPUABkUNym6Hd+f2IR113To8D2GPA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-collapsible": "1.1.12",
+ "@radix-ui/react-collection": "1.1.7",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-direction": "1.1.1",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-controllable-state": "1.2.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-alert-dialog": {
+ "version": "1.1.15",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-alert-dialog/-/react-alert-dialog-1.1.15.tgz",
+ "integrity": "sha512-oTVLkEw5GpdRe29BqJ0LSDFWI3qu0vR1M0mUkOQWDIUnY/QIkLpgDMWuKxP94c2NAC2LGcgVhG1ImF3jkZ5wXw==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-dialog": "1.1.15",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-slot": "1.2.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-alert-dialog/node_modules/@radix-ui/react-slot": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
+ "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-arrow": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz",
+ "integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-primitive": "2.1.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-aspect-ratio": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-aspect-ratio/-/react-aspect-ratio-1.1.8.tgz",
+ "integrity": "sha512-5nZrJTF7gH+e0nZS7/QxFz6tJV4VimhQb1avEgtsJxvvIp5JilL+c58HICsKzPxghdwaDt48hEfPM1au4zGy+w==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-primitive": "2.1.4"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-aspect-ratio/node_modules/@radix-ui/react-primitive": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz",
+ "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-slot": "1.2.4"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-avatar": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.1.11.tgz",
+ "integrity": "sha512-0Qk603AHGV28BOBO34p7IgD5m+V5Sg/YovfayABkoDDBM5d3NCx0Mp4gGrjzLGes1jV5eNOE1r3itqOR33VC6Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-context": "1.1.3",
+ "@radix-ui/react-primitive": "2.1.4",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
+ "@radix-ui/react-use-is-hydrated": "0.1.0",
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-avatar/node_modules/@radix-ui/react-context": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.3.tgz",
+ "integrity": "sha512-ieIFACdMpYfMEjF0rEf5KLvfVyIkOz6PDGyNnP+u+4xQ6jny3VCgA4OgXOwNx2aUkxn8zx9fiVcM8CfFYv9Lxw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-avatar/node_modules/@radix-ui/react-primitive": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz",
+ "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-slot": "1.2.4"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-checkbox": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.3.3.tgz",
+ "integrity": "sha512-wBbpv+NQftHDdG86Qc0pIyXk5IR3tM8Vd0nWLKDcX8nNn4nXFOFwsKuqw2okA/1D/mpaAkmuyndrPJTYDNZtFw==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-presence": "1.1.5",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-controllable-state": "1.2.2",
+ "@radix-ui/react-use-previous": "1.1.1",
+ "@radix-ui/react-use-size": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-collapsible": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.12.tgz",
+ "integrity": "sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-presence": "1.1.5",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-controllable-state": "1.2.2",
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-collection": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz",
+ "integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-slot": "1.2.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-slot": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
+ "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-compose-refs": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz",
+ "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-context": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz",
+ "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-context-menu": {
+ "version": "2.2.16",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-context-menu/-/react-context-menu-2.2.16.tgz",
+ "integrity": "sha512-O8morBEW+HsVG28gYDZPTrT9UUovQUlJue5YO836tiTJhuIWBm/zQHc7j388sHWtdH/xUZurK9olD2+pcqx5ww==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-menu": "2.1.16",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
+ "@radix-ui/react-use-controllable-state": "1.2.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-dialog": {
+ "version": "1.1.15",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.15.tgz",
+ "integrity": "sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-dismissable-layer": "1.1.11",
+ "@radix-ui/react-focus-guards": "1.1.3",
+ "@radix-ui/react-focus-scope": "1.1.7",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-portal": "1.1.9",
+ "@radix-ui/react-presence": "1.1.5",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-slot": "1.2.3",
+ "@radix-ui/react-use-controllable-state": "1.2.2",
+ "aria-hidden": "^1.2.4",
+ "react-remove-scroll": "^2.6.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-slot": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
+ "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-direction": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz",
+ "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-dismissable-layer": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.11.tgz",
+ "integrity": "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
+ "@radix-ui/react-use-escape-keydown": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-dropdown-menu": {
+ "version": "2.1.16",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.16.tgz",
+ "integrity": "sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-menu": "2.1.16",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-controllable-state": "1.2.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-focus-guards": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.3.tgz",
+ "integrity": "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-focus-scope": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz",
+ "integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-hover-card": {
+ "version": "1.1.15",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-hover-card/-/react-hover-card-1.1.15.tgz",
+ "integrity": "sha512-qgTkjNT1CfKMoP0rcasmlH2r1DAiYicWsDsufxl940sT2wHNEWWv6FMWIQXWhVdmC1d/HYfbhQx60KYyAtKxjg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-dismissable-layer": "1.1.11",
+ "@radix-ui/react-popper": "1.2.8",
+ "@radix-ui/react-portal": "1.1.9",
+ "@radix-ui/react-presence": "1.1.5",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-controllable-state": "1.2.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-id": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz",
+ "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-label": {
+ "version": "2.1.8",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.8.tgz",
+ "integrity": "sha512-FmXs37I6hSBVDlO4y764TNz1rLgKwjJMQ0EGte6F3Cb3f4bIuHB/iLa/8I9VKkmOy+gNHq8rql3j686ACVV21A==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-primitive": "2.1.4"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-label/node_modules/@radix-ui/react-primitive": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz",
+ "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-slot": "1.2.4"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-menu": {
+ "version": "2.1.16",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.16.tgz",
+ "integrity": "sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-collection": "1.1.7",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-direction": "1.1.1",
+ "@radix-ui/react-dismissable-layer": "1.1.11",
+ "@radix-ui/react-focus-guards": "1.1.3",
+ "@radix-ui/react-focus-scope": "1.1.7",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-popper": "1.2.8",
+ "@radix-ui/react-portal": "1.1.9",
+ "@radix-ui/react-presence": "1.1.5",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-roving-focus": "1.1.11",
+ "@radix-ui/react-slot": "1.2.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
+ "aria-hidden": "^1.2.4",
+ "react-remove-scroll": "^2.6.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-slot": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
+ "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-menubar": {
+ "version": "1.1.16",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-menubar/-/react-menubar-1.1.16.tgz",
+ "integrity": "sha512-EB1FktTz5xRRi2Er974AUQZWg2yVBb1yjip38/lgwtCVRd3a+maUoGHN/xs9Yv8SY8QwbSEb+YrxGadVWbEutA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-collection": "1.1.7",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-direction": "1.1.1",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-menu": "2.1.16",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-roving-focus": "1.1.11",
+ "@radix-ui/react-use-controllable-state": "1.2.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-navigation-menu": {
+ "version": "1.2.14",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-navigation-menu/-/react-navigation-menu-1.2.14.tgz",
+ "integrity": "sha512-YB9mTFQvCOAQMHU+C/jVl96WmuWeltyUEpRJJky51huhds5W2FQr1J8D/16sQlf0ozxkPK8uF3niQMdUwZPv5w==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-collection": "1.1.7",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-direction": "1.1.1",
+ "@radix-ui/react-dismissable-layer": "1.1.11",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-presence": "1.1.5",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
+ "@radix-ui/react-use-controllable-state": "1.2.2",
+ "@radix-ui/react-use-layout-effect": "1.1.1",
+ "@radix-ui/react-use-previous": "1.1.1",
+ "@radix-ui/react-visually-hidden": "1.2.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-popover": {
+ "version": "1.1.15",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.15.tgz",
+ "integrity": "sha512-kr0X2+6Yy/vJzLYJUPCZEc8SfQcf+1COFoAqauJm74umQhta9M7lNJHP7QQS3vkvcGLQUbWpMzwrXYwrYztHKA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-dismissable-layer": "1.1.11",
+ "@radix-ui/react-focus-guards": "1.1.3",
+ "@radix-ui/react-focus-scope": "1.1.7",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-popper": "1.2.8",
+ "@radix-ui/react-portal": "1.1.9",
+ "@radix-ui/react-presence": "1.1.5",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-slot": "1.2.3",
+ "@radix-ui/react-use-controllable-state": "1.2.2",
+ "aria-hidden": "^1.2.4",
+ "react-remove-scroll": "^2.6.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-popover/node_modules/@radix-ui/react-slot": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
+ "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-popper": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.8.tgz",
+ "integrity": "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/react-dom": "^2.0.0",
+ "@radix-ui/react-arrow": "1.1.7",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
+ "@radix-ui/react-use-layout-effect": "1.1.1",
+ "@radix-ui/react-use-rect": "1.1.1",
+ "@radix-ui/react-use-size": "1.1.1",
+ "@radix-ui/rect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-portal": {
+ "version": "1.1.9",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz",
+ "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-presence": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.5.tgz",
+ "integrity": "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-primitive": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
+ "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-slot": "1.2.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-primitive/node_modules/@radix-ui/react-slot": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
+ "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-progress": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.1.8.tgz",
+ "integrity": "sha512-+gISHcSPUJ7ktBy9RnTqbdKW78bcGke3t6taawyZ71pio1JewwGSJizycs7rLhGTvMJYCQB1DBK4KQsxs7U8dA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-context": "1.1.3",
+ "@radix-ui/react-primitive": "2.1.4"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-progress/node_modules/@radix-ui/react-context": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.3.tgz",
+ "integrity": "sha512-ieIFACdMpYfMEjF0rEf5KLvfVyIkOz6PDGyNnP+u+4xQ6jny3VCgA4OgXOwNx2aUkxn8zx9fiVcM8CfFYv9Lxw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-progress/node_modules/@radix-ui/react-primitive": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz",
+ "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-slot": "1.2.4"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-radio-group": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-radio-group/-/react-radio-group-1.3.8.tgz",
+ "integrity": "sha512-VBKYIYImA5zsxACdisNQ3BjCBfmbGH3kQlnFVqlWU4tXwjy7cGX8ta80BcrO+WJXIn5iBylEH3K6ZTlee//lgQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-direction": "1.1.1",
+ "@radix-ui/react-presence": "1.1.5",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-roving-focus": "1.1.11",
+ "@radix-ui/react-use-controllable-state": "1.2.2",
+ "@radix-ui/react-use-previous": "1.1.1",
+ "@radix-ui/react-use-size": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-roving-focus": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.11.tgz",
+ "integrity": "sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-collection": "1.1.7",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-direction": "1.1.1",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
+ "@radix-ui/react-use-controllable-state": "1.2.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-scroll-area": {
+ "version": "1.2.10",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.10.tgz",
+ "integrity": "sha512-tAXIa1g3sM5CGpVT0uIbUx/U3Gs5N8T52IICuCtObaos1S8fzsrPXG5WObkQN3S6NVl6wKgPhAIiBGbWnvc97A==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/number": "1.1.1",
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-direction": "1.1.1",
+ "@radix-ui/react-presence": "1.1.5",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-select": {
+ "version": "2.2.6",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.2.6.tgz",
+ "integrity": "sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/number": "1.1.1",
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-collection": "1.1.7",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-direction": "1.1.1",
+ "@radix-ui/react-dismissable-layer": "1.1.11",
+ "@radix-ui/react-focus-guards": "1.1.3",
+ "@radix-ui/react-focus-scope": "1.1.7",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-popper": "1.2.8",
+ "@radix-ui/react-portal": "1.1.9",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-slot": "1.2.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
+ "@radix-ui/react-use-controllable-state": "1.2.2",
+ "@radix-ui/react-use-layout-effect": "1.1.1",
+ "@radix-ui/react-use-previous": "1.1.1",
+ "@radix-ui/react-visually-hidden": "1.2.3",
+ "aria-hidden": "^1.2.4",
+ "react-remove-scroll": "^2.6.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-slot": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
+ "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-separator": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.8.tgz",
+ "integrity": "sha512-sDvqVY4itsKwwSMEe0jtKgfTh+72Sy3gPmQpjqcQneqQ4PFmr/1I0YA+2/puilhggCe2gJcx5EBAYFkWkdpa5g==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-primitive": "2.1.4"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-separator/node_modules/@radix-ui/react-primitive": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz",
+ "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-slot": "1.2.4"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-slider": {
+ "version": "1.3.6",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slider/-/react-slider-1.3.6.tgz",
+ "integrity": "sha512-JPYb1GuM1bxfjMRlNLE+BcmBC8onfCi60Blk7OBqi2MLTFdS+8401U4uFjnwkOr49BLmXxLC6JHkvAsx5OJvHw==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/number": "1.1.1",
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-collection": "1.1.7",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-direction": "1.1.1",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-controllable-state": "1.2.2",
+ "@radix-ui/react-use-layout-effect": "1.1.1",
+ "@radix-ui/react-use-previous": "1.1.1",
+ "@radix-ui/react-use-size": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-slot": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.4.tgz",
+ "integrity": "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-switch": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.2.6.tgz",
+ "integrity": "sha512-bByzr1+ep1zk4VubeEVViV592vu2lHE2BZY5OnzehZqOOgogN80+mNtCqPkhn2gklJqOpxWgPoYTSnhBCqpOXQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-controllable-state": "1.2.2",
+ "@radix-ui/react-use-previous": "1.1.1",
+ "@radix-ui/react-use-size": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-tabs": {
+ "version": "1.1.13",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.13.tgz",
+ "integrity": "sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-direction": "1.1.1",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-presence": "1.1.5",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-roving-focus": "1.1.11",
+ "@radix-ui/react-use-controllable-state": "1.2.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-toggle": {
+ "version": "1.1.10",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-toggle/-/react-toggle-1.1.10.tgz",
+ "integrity": "sha512-lS1odchhFTeZv3xwHH31YPObmJn8gOg7Lq12inrr0+BH/l3Tsq32VfjqH1oh80ARM3mlkfMic15n0kg4sD1poQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-controllable-state": "1.2.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-toggle-group": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-toggle-group/-/react-toggle-group-1.1.11.tgz",
+ "integrity": "sha512-5umnS0T8JQzQT6HbPyO7Hh9dgd82NmS36DQr+X/YJ9ctFNCiiQd6IJAYYZ33LUwm8M+taCz5t2ui29fHZc4Y6Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-direction": "1.1.1",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-roving-focus": "1.1.11",
+ "@radix-ui/react-toggle": "1.1.10",
+ "@radix-ui/react-use-controllable-state": "1.2.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-tooltip": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.2.8.tgz",
+ "integrity": "sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-dismissable-layer": "1.1.11",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-popper": "1.2.8",
+ "@radix-ui/react-portal": "1.1.9",
+ "@radix-ui/react-presence": "1.1.5",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-slot": "1.2.3",
+ "@radix-ui/react-use-controllable-state": "1.2.2",
+ "@radix-ui/react-visually-hidden": "1.2.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-slot": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
+ "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-callback-ref": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz",
+ "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-controllable-state": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz",
+ "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-use-effect-event": "0.0.2",
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-effect-event": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz",
+ "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-escape-keydown": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz",
+ "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-use-callback-ref": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-is-hydrated": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-is-hydrated/-/react-use-is-hydrated-0.1.0.tgz",
+ "integrity": "sha512-U+UORVEq+cTnRIaostJv9AGdV3G6Y+zbVd+12e18jQ5A3c0xL03IhnHuiU4UV69wolOQp5GfR58NW/EgdQhwOA==",
+ "license": "MIT",
+ "dependencies": {
+ "use-sync-external-store": "^1.5.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-layout-effect": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz",
+ "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-previous": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.1.tgz",
+ "integrity": "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-rect": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz",
+ "integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/rect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-size": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz",
+ "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-visually-hidden": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz",
+ "integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-primitive": "2.1.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/rect": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz",
+ "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==",
+ "license": "MIT"
+ },
+ "node_modules/@reduxjs/toolkit": {
+ "version": "2.11.2",
+ "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.11.2.tgz",
+ "integrity": "sha512-Kd6kAHTA6/nUpp8mySPqj3en3dm0tdMIgbttnQ1xFMVpufoj+ADi8pXLBsd4xzTRHQa7t/Jv8W5UnCuW4kuWMQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@standard-schema/spec": "^1.0.0",
+ "@standard-schema/utils": "^0.3.0",
+ "immer": "^11.0.0",
+ "redux": "^5.0.1",
+ "redux-thunk": "^3.1.0",
+ "reselect": "^5.1.0"
+ },
+ "peerDependencies": {
+ "react": "^16.9.0 || ^17.0.0 || ^18 || ^19",
+ "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "react": {
+ "optional": true
+ },
+ "react-redux": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@reduxjs/toolkit/node_modules/immer": {
+ "version": "11.1.4",
+ "resolved": "https://registry.npmjs.org/immer/-/immer-11.1.4.tgz",
+ "integrity": "sha512-XREFCPo6ksxVzP4E0ekD5aMdf8WMwmdNaz6vuvxgI40UaEiu6q3p8X52aU6GdyvLY3XXX/8R7JOTXStz/nBbRw==",
+ "license": "MIT",
+ "peer": true,
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/immer"
+ }
+ },
+ "node_modules/@rolldown/binding-android-arm64": {
+ "version": "1.0.0-beta.41",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-beta.41.tgz",
+ "integrity": "sha512-Edflndd9lU7JVhVIvJlZhdCj5DkhYDJPIRn4Dx0RUdfc8asP9xHOI5gMd8MesDDx+BJpdIT/uAmVTearteU/mQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-darwin-arm64": {
+ "version": "1.0.0-beta.41",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-beta.41.tgz",
+ "integrity": "sha512-XGCzqfjdk7550PlyZRTBKbypXrB7ATtXhw/+bjtxnklLQs0mKP/XkQVOKyn9qGKSlvH8I56JLYryVxl0PCvSNw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-darwin-x64": {
+ "version": "1.0.0-beta.41",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-beta.41.tgz",
+ "integrity": "sha512-Ho6lIwGJed98zub7n0xcRKuEtnZgbxevAmO4x3zn3C3N4GVXZD5xvCvTVxSMoeBJwTcIYzkVDRTIhylQNsTgLQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-freebsd-x64": {
+ "version": "1.0.0-beta.41",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-beta.41.tgz",
+ "integrity": "sha512-ijAZETywvL+gACjbT4zBnCp5ez1JhTRs6OxRN4J+D6AzDRbU2zb01Esl51RP5/8ZOlvB37xxsRQ3X4YRVyYb3g==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-arm-gnueabihf": {
+ "version": "1.0.0-beta.41",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-beta.41.tgz",
+ "integrity": "sha512-EgIOZt7UildXKFEFvaiLNBXm+4ggQyGe3E5Z1QP9uRcJJs9omihOnm897FwOBQdCuMvI49iBgjFrkhH+wMJ2MA==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-arm64-gnu": {
+ "version": "1.0.0-beta.41",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-beta.41.tgz",
+ "integrity": "sha512-F8bUwJq8v/JAU8HSwgF4dztoqJ+FjdyjuvX4//3+Fbe2we9UktFeZ27U4lRMXF1vxWtdV4ey6oCSqI7yUrSEeg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-arm64-musl": {
+ "version": "1.0.0-beta.41",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-beta.41.tgz",
+ "integrity": "sha512-MioXcCIX/wB1pBnBoJx8q4OGucUAfC1+/X1ilKFsjDK05VwbLZGRgOVD5OJJpUQPK86DhQciNBrfOKDiatxNmg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-x64-gnu": {
+ "version": "1.0.0-beta.41",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-beta.41.tgz",
+ "integrity": "sha512-m66M61fizvRCwt5pOEiZQMiwBL9/y0bwU/+Kc4Ce/Pef6YfoEkR28y+DzN9rMdjo8Z28NXjsDPq9nH4mXnAP0g==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-x64-musl": {
+ "version": "1.0.0-beta.41",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-beta.41.tgz",
+ "integrity": "sha512-yRxlSfBvWnnfrdtJfvi9lg8xfG5mPuyoSHm0X01oiE8ArmLRvoJGHUTJydCYz+wbK2esbq5J4B4Tq9WAsOlP1Q==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-openharmony-arm64": {
+ "version": "1.0.0-beta.41",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-beta.41.tgz",
+ "integrity": "sha512-PHVxYhBpi8UViS3/hcvQQb9RFqCtvFmFU1PvUoTRiUdBtgHA6fONNHU4x796lgzNlVSD3DO/MZNk1s5/ozSMQg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-wasm32-wasi": {
+ "version": "1.0.0-beta.41",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-beta.41.tgz",
+ "integrity": "sha512-OAfcO37ME6GGWmj9qTaDT7jY4rM0T2z0/8ujdQIJQ2x2nl+ztO32EIwURfmXOK0U1tzkyuaKYvE34Pug/ucXlQ==",
+ "cpu": [
+ "wasm32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@napi-rs/wasm-runtime": "^1.0.5"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@rolldown/binding-win32-arm64-msvc": {
+ "version": "1.0.0-beta.41",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-beta.41.tgz",
+ "integrity": "sha512-NIYGuCcuXaq5BC4Q3upbiMBvmZsTsEPG9k/8QKQdmrch+ocSy5Jv9tdpdmXJyighKqm182nh/zBt+tSJkYoNlg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-win32-ia32-msvc": {
+ "version": "1.0.0-beta.41",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.0.0-beta.41.tgz",
+ "integrity": "sha512-kANdsDbE5FkEOb5NrCGBJBCaZ2Sabp3D7d4PRqMYJqyLljwh9mDyYyYSv5+QNvdAmifj+f3lviNEUUuUZPEFPw==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-win32-x64-msvc": {
+ "version": "1.0.0-beta.41",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-beta.41.tgz",
+ "integrity": "sha512-UlpxKmFdik0Y2VjZrgUCgoYArZJiZllXgIipdBRV1hw6uK45UbQabSTW6Kp6enuOu7vouYWftwhuxfpE8J2JAg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/pluginutils": {
+ "version": "1.0.0-beta.53",
+ "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.53.tgz",
+ "integrity": "sha512-vENRlFU4YbrwVqNDZ7fLvy+JR1CRkyr01jhSiDpE1u6py3OMzQfztQU2jxykW3ALNxO4kSlqIDeYyD0Y9RcQeQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@standard-schema/spec": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz",
+ "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==",
+ "license": "MIT"
+ },
+ "node_modules/@standard-schema/utils": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz",
+ "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==",
+ "license": "MIT"
+ },
+ "node_modules/@swc/helpers": {
+ "version": "0.5.18",
+ "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.18.tgz",
+ "integrity": "sha512-TXTnIcNJQEKwThMMqBXsZ4VGAza6bvN4pa41Rkqoio6QBKMvo+5lexeTMScGCIxtzgQJzElcvIltani+adC5PQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.8.0"
+ }
+ },
+ "node_modules/@tailwindcss/node": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.18.tgz",
+ "integrity": "sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/remapping": "^2.3.4",
+ "enhanced-resolve": "^5.18.3",
+ "jiti": "^2.6.1",
+ "lightningcss": "1.30.2",
+ "magic-string": "^0.30.21",
+ "source-map-js": "^1.2.1",
+ "tailwindcss": "4.1.18"
+ }
+ },
+ "node_modules/@tailwindcss/oxide": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.18.tgz",
+ "integrity": "sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10"
+ },
+ "optionalDependencies": {
+ "@tailwindcss/oxide-android-arm64": "4.1.18",
+ "@tailwindcss/oxide-darwin-arm64": "4.1.18",
+ "@tailwindcss/oxide-darwin-x64": "4.1.18",
+ "@tailwindcss/oxide-freebsd-x64": "4.1.18",
+ "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.18",
+ "@tailwindcss/oxide-linux-arm64-gnu": "4.1.18",
+ "@tailwindcss/oxide-linux-arm64-musl": "4.1.18",
+ "@tailwindcss/oxide-linux-x64-gnu": "4.1.18",
+ "@tailwindcss/oxide-linux-x64-musl": "4.1.18",
+ "@tailwindcss/oxide-wasm32-wasi": "4.1.18",
+ "@tailwindcss/oxide-win32-arm64-msvc": "4.1.18",
+ "@tailwindcss/oxide-win32-x64-msvc": "4.1.18"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-android-arm64": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.18.tgz",
+ "integrity": "sha512-dJHz7+Ugr9U/diKJA0W6N/6/cjI+ZTAoxPf9Iz9BFRF2GzEX8IvXxFIi/dZBloVJX/MZGvRuFA9rqwdiIEZQ0Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-darwin-arm64": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.18.tgz",
+ "integrity": "sha512-Gc2q4Qhs660bhjyBSKgq6BYvwDz4G+BuyJ5H1xfhmDR3D8HnHCmT/BSkvSL0vQLy/nkMLY20PQ2OoYMO15Jd0A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-darwin-x64": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.18.tgz",
+ "integrity": "sha512-FL5oxr2xQsFrc3X9o1fjHKBYBMD1QZNyc1Xzw/h5Qu4XnEBi3dZn96HcHm41c/euGV+GRiXFfh2hUCyKi/e+yw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-freebsd-x64": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.18.tgz",
+ "integrity": "sha512-Fj+RHgu5bDodmV1dM9yAxlfJwkkWvLiRjbhuO2LEtwtlYlBgiAT4x/j5wQr1tC3SANAgD+0YcmWVrj8R9trVMA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.18.tgz",
+ "integrity": "sha512-Fp+Wzk/Ws4dZn+LV2Nqx3IilnhH51YZoRaYHQsVq3RQvEl+71VGKFpkfHrLM/Li+kt5c0DJe/bHXK1eHgDmdiA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.18.tgz",
+ "integrity": "sha512-S0n3jboLysNbh55Vrt7pk9wgpyTTPD0fdQeh7wQfMqLPM/Hrxi+dVsLsPrycQjGKEQk85Kgbx+6+QnYNiHalnw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-arm64-musl": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.18.tgz",
+ "integrity": "sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-x64-gnu": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.18.tgz",
+ "integrity": "sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-x64-musl": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.18.tgz",
+ "integrity": "sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-wasm32-wasi": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.18.tgz",
+ "integrity": "sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA==",
+ "bundleDependencies": [
+ "@napi-rs/wasm-runtime",
+ "@emnapi/core",
+ "@emnapi/runtime",
+ "@tybys/wasm-util",
+ "@emnapi/wasi-threads",
+ "tslib"
+ ],
+ "cpu": [
+ "wasm32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/core": "^1.7.1",
+ "@emnapi/runtime": "^1.7.1",
+ "@emnapi/wasi-threads": "^1.1.0",
+ "@napi-rs/wasm-runtime": "^1.1.0",
+ "@tybys/wasm-util": "^0.10.1",
+ "tslib": "^2.4.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.18.tgz",
+ "integrity": "sha512-HjSA7mr9HmC8fu6bdsZvZ+dhjyGCLdotjVOgLA2vEqxEBZaQo9YTX4kwgEvPCpRh8o4uWc4J/wEoFzhEmjvPbA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-win32-x64-msvc": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.18.tgz",
+ "integrity": "sha512-bJWbyYpUlqamC8dpR7pfjA0I7vdF6t5VpUGMWRkXVE3AXgIZjYUYAK7II1GNaxR8J1SSrSrppRar8G++JekE3Q==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/postcss": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.18.tgz",
+ "integrity": "sha512-Ce0GFnzAOuPyfV5SxjXGn0CubwGcuDB0zcdaPuCSzAa/2vII24JTkH+I6jcbXLb1ctjZMZZI6OjDaLPJQL1S0g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@alloc/quick-lru": "^5.2.0",
+ "@tailwindcss/node": "4.1.18",
+ "@tailwindcss/oxide": "4.1.18",
+ "postcss": "^8.4.41",
+ "tailwindcss": "4.1.18"
+ }
+ },
+ "node_modules/@tailwindcss/vite": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.18.tgz",
+ "integrity": "sha512-jVA+/UpKL1vRLg6Hkao5jldawNmRo7mQYrZtNHMIVpLfLhDml5nMRUo/8MwoX2vNXvnaXNNMedrMfMugAVX1nA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@tailwindcss/node": "4.1.18",
+ "@tailwindcss/oxide": "4.1.18",
+ "tailwindcss": "4.1.18"
+ },
+ "peerDependencies": {
+ "vite": "^5.2.0 || ^6 || ^7"
+ }
+ },
+ "node_modules/@tanstack/react-table": {
+ "version": "8.21.3",
+ "resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.21.3.tgz",
+ "integrity": "sha512-5nNMTSETP4ykGegmVkhjcS8tTLW6Vl4axfEGQN3v0zdHYbK4UfoqfPChclTrJ4EoK9QynqAu9oUf8VEmrpZ5Ww==",
+ "license": "MIT",
+ "dependencies": {
+ "@tanstack/table-core": "8.21.3"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/tannerlinsley"
+ },
+ "peerDependencies": {
+ "react": ">=16.8",
+ "react-dom": ">=16.8"
+ }
+ },
+ "node_modules/@tanstack/react-virtual": {
+ "version": "3.13.18",
+ "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.13.18.tgz",
+ "integrity": "sha512-dZkhyfahpvlaV0rIKnvQiVoWPyURppl6w4m9IwMDpuIjcJ1sD9YGWrt0wISvgU7ewACXx2Ct46WPgI6qAD4v6A==",
+ "license": "MIT",
+ "dependencies": {
+ "@tanstack/virtual-core": "3.13.18"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/tannerlinsley"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
+ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
+ "node_modules/@tanstack/table-core": {
+ "version": "8.21.3",
+ "resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.21.3.tgz",
+ "integrity": "sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/tannerlinsley"
+ }
+ },
+ "node_modules/@tanstack/virtual-core": {
+ "version": "3.13.18",
+ "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.13.18.tgz",
+ "integrity": "sha512-Mx86Hqu1k39icq2Zusq+Ey2J6dDWTjDvEv43PJtRCoEYTLyfaPnxIQ6iy7YAOK0NV/qOEmZQ/uCufrppZxTgcg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/tannerlinsley"
+ }
+ },
+ "node_modules/@tybys/wasm-util": {
+ "version": "0.10.1",
+ "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz",
+ "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@types/aws-lambda": {
+ "version": "8.10.160",
+ "resolved": "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.160.tgz",
+ "integrity": "sha512-uoO4QVQNWFPJMh26pXtmtrRfGshPUSpMZGUyUQY20FhfHEElEBOPKgVmFs1z+kbpyBsRs2JnoOPT7++Z4GA9pA==",
+ "license": "MIT"
+ },
+ "node_modules/@types/babel__core": {
+ "version": "7.20.5",
+ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
+ "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.20.7",
+ "@babel/types": "^7.20.7",
+ "@types/babel__generator": "*",
+ "@types/babel__template": "*",
+ "@types/babel__traverse": "*"
+ }
+ },
+ "node_modules/@types/babel__generator": {
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz",
+ "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__template": {
+ "version": "7.4.4",
+ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
+ "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__traverse": {
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz",
+ "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.28.2"
+ }
+ },
+ "node_modules/@types/body-parser": {
+ "version": "1.19.6",
+ "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz",
+ "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/connect": "*",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/bunyan": {
+ "version": "1.8.11",
+ "resolved": "https://registry.npmjs.org/@types/bunyan/-/bunyan-1.8.11.tgz",
+ "integrity": "sha512-758fRH7umIMk5qt5ELmRMff4mLDlN+xyYzC+dkPTdKwbSkJFvz6xwyScrytPU0QIBbRRwbiE8/BIg8bpajerNQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/chai": {
+ "version": "5.2.3",
+ "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz",
+ "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/deep-eql": "*",
+ "assertion-error": "^2.0.1"
+ }
+ },
+ "node_modules/@types/command-line-args": {
+ "version": "5.2.3",
+ "resolved": "https://registry.npmjs.org/@types/command-line-args/-/command-line-args-5.2.3.tgz",
+ "integrity": "sha512-uv0aG6R0Y8WHZLTamZwtfsDLVRnOa+n+n5rEvFWL5Na5gZ8V2Teab/duDPFzIIIhs9qizDpcavCusCLJZu62Kw==",
+ "license": "MIT"
+ },
+ "node_modules/@types/command-line-usage": {
+ "version": "5.0.4",
+ "resolved": "https://registry.npmjs.org/@types/command-line-usage/-/command-line-usage-5.0.4.tgz",
+ "integrity": "sha512-BwR5KP3Es/CSht0xqBcUXS3qCAUVXwpRKsV2+arxeb65atasuXG9LykC9Ab10Cw3s2raH92ZqOeILaQbsB2ACg==",
+ "license": "MIT"
+ },
+ "node_modules/@types/connect": {
+ "version": "3.4.38",
+ "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz",
+ "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/d3-array": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.2.tgz",
+ "integrity": "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@types/d3-color": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz",
+ "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@types/d3-ease": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz",
+ "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@types/d3-interpolate": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz",
+ "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@types/d3-color": "*"
+ }
+ },
+ "node_modules/@types/d3-path": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz",
+ "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@types/d3-scale": {
+ "version": "4.0.9",
+ "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz",
+ "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@types/d3-time": "*"
+ }
+ },
+ "node_modules/@types/d3-shape": {
+ "version": "3.1.8",
+ "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.8.tgz",
+ "integrity": "sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@types/d3-path": "*"
+ }
+ },
+ "node_modules/@types/d3-time": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz",
+ "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@types/d3-timer": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz",
+ "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@types/deep-eql": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz",
+ "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
+ "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/express": {
+ "version": "5.0.6",
+ "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.6.tgz",
+ "integrity": "sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/body-parser": "*",
+ "@types/express-serve-static-core": "^5.0.0",
+ "@types/serve-static": "^2"
+ }
+ },
+ "node_modules/@types/express-serve-static-core": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.1.1.tgz",
+ "integrity": "sha512-v4zIMr/cX7/d2BpAEX3KNKL/JrT1s43s96lLvvdTmza1oEvDudCqK9aF/djc/SWgy8Yh0h30TZx5VpzqFCxk5A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*",
+ "@types/qs": "*",
+ "@types/range-parser": "*",
+ "@types/send": "*"
+ }
+ },
+ "node_modules/@types/http-errors": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz",
+ "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/json-schema": {
+ "version": "7.0.15",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
+ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/memcached": {
+ "version": "2.2.10",
+ "resolved": "https://registry.npmjs.org/@types/memcached/-/memcached-2.2.10.tgz",
+ "integrity": "sha512-AM9smvZN55Gzs2wRrqeMHVP7KE8KWgCJO/XL5yCly2xF6EKa4YlbpK+cLSAH4NG/Ah64HrlegmGqW8kYws7Vxg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/mysql": {
+ "version": "2.15.27",
+ "resolved": "https://registry.npmjs.org/@types/mysql/-/mysql-2.15.27.tgz",
+ "integrity": "sha512-YfWiV16IY0OeBfBCk8+hXKmdTKrKlwKN1MNKAPBu5JYxLwBEZl7QzeEpGnlZb3VMGJrrGmB84gXiH+ofs/TezA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/node": {
+ "version": "24.10.9",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.9.tgz",
+ "integrity": "sha512-ne4A0IpG3+2ETuREInjPNhUGis1SFjv1d5asp8MzEAGtOZeTeHVDOYqOgqfhvseqg/iXty2hjBf1zAOb7RNiNw==",
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~7.16.0"
+ }
+ },
+ "node_modules/@types/oracledb": {
+ "version": "6.5.2",
+ "resolved": "https://registry.npmjs.org/@types/oracledb/-/oracledb-6.5.2.tgz",
+ "integrity": "sha512-kK1eBS/Adeyis+3OlBDMeQQuasIDLUYXsi2T15ccNJ0iyUpQ4xDF7svFu3+bGVrI0CMBUclPciz+lsQR3JX3TQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/pg": {
+ "version": "8.16.0",
+ "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.16.0.tgz",
+ "integrity": "sha512-RmhMd/wD+CF8Dfo+cVIy3RR5cl8CyfXQ0tGgW6XBL8L4LM/UTEbNXYRbLwU6w+CgrKBNbrQWt4FUtTfaU5jSYQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*",
+ "pg-protocol": "*",
+ "pg-types": "^2.2.0"
+ }
+ },
+ "node_modules/@types/pg-pool": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/@types/pg-pool/-/pg-pool-2.0.6.tgz",
+ "integrity": "sha512-TaAUE5rq2VQYxab5Ts7WZhKNmuN78Q6PiFonTDdpbx8a1H0M1vhy3rhiMjl+e2iHmogyMw7jZF4FrE6eJUy5HQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/pg": "*"
+ }
+ },
+ "node_modules/@types/qs": {
+ "version": "6.14.0",
+ "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz",
+ "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/range-parser": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz",
+ "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/react": {
+ "version": "19.2.10",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.10.tgz",
+ "integrity": "sha512-WPigyYuGhgZ/cTPRXB2EwUw+XvsRA3GqHlsP4qteqrnnjDrApbS7MxcGr/hke5iUoeB7E/gQtrs9I37zAJ0Vjw==",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "csstype": "^3.2.2"
+ }
+ },
+ "node_modules/@types/react-dom": {
+ "version": "19.2.3",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz",
+ "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
+ "devOptional": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "^19.2.0"
+ }
+ },
+ "node_modules/@types/semver": {
+ "version": "7.7.1",
+ "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.1.tgz",
+ "integrity": "sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==",
+ "license": "MIT"
+ },
+ "node_modules/@types/send": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz",
+ "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/serve-static": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-2.2.0.tgz",
+ "integrity": "sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/http-errors": "*",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/tedious": {
+ "version": "4.0.14",
+ "resolved": "https://registry.npmjs.org/@types/tedious/-/tedious-4.0.14.tgz",
+ "integrity": "sha512-KHPsfX/FoVbUGbyYvk1q9MMQHLPeRZhRJZdO45Q4YjvFkv4hMNghCWTvy7rdKessBsmtz4euWCWAB6/tVpI1Iw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/use-sync-external-store": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz",
+ "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@typescript-eslint/eslint-plugin": {
+ "version": "8.54.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.54.0.tgz",
+ "integrity": "sha512-hAAP5io/7csFStuOmR782YmTthKBJ9ND3WVL60hcOjvtGFb+HJxH4O5huAcmcZ9v9G8P+JETiZ/G1B8MALnWZQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/regexpp": "^4.12.2",
+ "@typescript-eslint/scope-manager": "8.54.0",
+ "@typescript-eslint/type-utils": "8.54.0",
+ "@typescript-eslint/utils": "8.54.0",
+ "@typescript-eslint/visitor-keys": "8.54.0",
+ "ignore": "^7.0.5",
+ "natural-compare": "^1.4.0",
+ "ts-api-utils": "^2.4.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/parser": "^8.54.0",
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/parser": {
+ "version": "8.54.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.54.0.tgz",
+ "integrity": "sha512-BtE0k6cjwjLZoZixN0t5AKP0kSzlGu7FctRXYuPAm//aaiZhmfq1JwdYpYr1brzEspYyFeF+8XF5j2VK6oalrA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/scope-manager": "8.54.0",
+ "@typescript-eslint/types": "8.54.0",
+ "@typescript-eslint/typescript-estree": "8.54.0",
+ "@typescript-eslint/visitor-keys": "8.54.0",
+ "debug": "^4.4.3"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/project-service": {
+ "version": "8.54.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.54.0.tgz",
+ "integrity": "sha512-YPf+rvJ1s7MyiWM4uTRhE4DvBXrEV+d8oC3P9Y2eT7S+HBS0clybdMIPnhiATi9vZOYDc7OQ1L/i6ga6NFYK/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/tsconfig-utils": "^8.54.0",
+ "@typescript-eslint/types": "^8.54.0",
+ "debug": "^4.4.3"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/scope-manager": {
+ "version": "8.54.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.54.0.tgz",
+ "integrity": "sha512-27rYVQku26j/PbHYcVfRPonmOlVI6gihHtXFbTdB5sb6qA0wdAQAbyXFVarQ5t4HRojIz64IV90YtsjQSSGlQg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.54.0",
+ "@typescript-eslint/visitor-keys": "8.54.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/tsconfig-utils": {
+ "version": "8.54.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.54.0.tgz",
+ "integrity": "sha512-dRgOyT2hPk/JwxNMZDsIXDgyl9axdJI3ogZ2XWhBPsnZUv+hPesa5iuhdYt2gzwA9t8RE5ytOJ6xB0moV0Ujvw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils": {
+ "version": "8.54.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.54.0.tgz",
+ "integrity": "sha512-hiLguxJWHjjwL6xMBwD903ciAwd7DmK30Y9Axs/etOkftC3ZNN9K44IuRD/EB08amu+Zw6W37x9RecLkOo3pMA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.54.0",
+ "@typescript-eslint/typescript-estree": "8.54.0",
+ "@typescript-eslint/utils": "8.54.0",
+ "debug": "^4.4.3",
+ "ts-api-utils": "^2.4.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/types": {
+ "version": "8.54.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.54.0.tgz",
+ "integrity": "sha512-PDUI9R1BVjqu7AUDsRBbKMtwmjWcn4J3le+5LpcFgWULN3LvHC5rkc9gCVxbrsrGmO1jfPybN5s6h4Jy+OnkAA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree": {
+ "version": "8.54.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.54.0.tgz",
+ "integrity": "sha512-BUwcskRaPvTk6fzVWgDPdUndLjB87KYDrN5EYGetnktoeAvPtO4ONHlAZDnj5VFnUANg0Sjm7j4usBlnoVMHwA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/project-service": "8.54.0",
+ "@typescript-eslint/tsconfig-utils": "8.54.0",
+ "@typescript-eslint/types": "8.54.0",
+ "@typescript-eslint/visitor-keys": "8.54.0",
+ "debug": "^4.4.3",
+ "minimatch": "^9.0.5",
+ "semver": "^7.7.3",
+ "tinyglobby": "^0.2.15",
+ "ts-api-utils": "^2.4.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/utils": {
+ "version": "8.54.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.54.0.tgz",
+ "integrity": "sha512-9Cnda8GS57AQakvRyG0PTejJNlA2xhvyNtEVIMlDWOOeEyBkYWhGPnfrIAnqxLMTSTo6q8g12XVjjev5l1NvMA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.9.1",
+ "@typescript-eslint/scope-manager": "8.54.0",
+ "@typescript-eslint/types": "8.54.0",
+ "@typescript-eslint/typescript-estree": "8.54.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys": {
+ "version": "8.54.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.54.0.tgz",
+ "integrity": "sha512-VFlhGSl4opC0bprJiItPQ1RfUhGDIBokcPwaFH4yiBCaNPeld/9VeXbiPO1cLyorQi1G1vL+ecBk1x8o1axORA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.54.0",
+ "eslint-visitor-keys": "^4.2.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
+ "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@vitejs/plugin-react": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.1.2.tgz",
+ "integrity": "sha512-EcA07pHJouywpzsoTUqNh5NwGayl2PPVEJKUSinGGSxFGYn+shYbqMGBg6FXDqgXum9Ou/ecb+411ssw8HImJQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.28.5",
+ "@babel/plugin-transform-react-jsx-self": "^7.27.1",
+ "@babel/plugin-transform-react-jsx-source": "^7.27.1",
+ "@rolldown/pluginutils": "1.0.0-beta.53",
+ "@types/babel__core": "^7.20.5",
+ "react-refresh": "^0.18.0"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "peerDependencies": {
+ "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
+ }
+ },
+ "node_modules/@vitest/expect": {
+ "version": "4.0.18",
+ "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.18.tgz",
+ "integrity": "sha512-8sCWUyckXXYvx4opfzVY03EOiYVxyNrHS5QxX3DAIi5dpJAAkyJezHCP77VMX4HKA2LDT/Jpfo8i2r5BE3GnQQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@standard-schema/spec": "^1.0.0",
+ "@types/chai": "^5.2.2",
+ "@vitest/spy": "4.0.18",
+ "@vitest/utils": "4.0.18",
+ "chai": "^6.2.1",
+ "tinyrainbow": "^3.0.3"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/mocker": {
+ "version": "4.0.18",
+ "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.18.tgz",
+ "integrity": "sha512-HhVd0MDnzzsgevnOWCBj5Otnzobjy5wLBe4EdeeFGv8luMsGcYqDuFRMcttKWZA5vVO8RFjexVovXvAM4JoJDQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/spy": "4.0.18",
+ "estree-walker": "^3.0.3",
+ "magic-string": "^0.30.21"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ },
+ "peerDependencies": {
+ "msw": "^2.4.9",
+ "vite": "^6.0.0 || ^7.0.0-0"
+ },
+ "peerDependenciesMeta": {
+ "msw": {
+ "optional": true
+ },
+ "vite": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@vitest/pretty-format": {
+ "version": "4.0.18",
+ "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.18.tgz",
+ "integrity": "sha512-P24GK3GulZWC5tz87ux0m8OADrQIUVDPIjjj65vBXYG17ZeU3qD7r+MNZ1RNv4l8CGU2vtTRqixrOi9fYk/yKw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tinyrainbow": "^3.0.3"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/runner": {
+ "version": "4.0.18",
+ "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.0.18.tgz",
+ "integrity": "sha512-rpk9y12PGa22Jg6g5M3UVVnTS7+zycIGk9ZNGN+m6tZHKQb7jrP7/77WfZy13Y/EUDd52NDsLRQhYKtv7XfPQw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/utils": "4.0.18",
+ "pathe": "^2.0.3"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/snapshot": {
+ "version": "4.0.18",
+ "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.0.18.tgz",
+ "integrity": "sha512-PCiV0rcl7jKQjbgYqjtakly6T1uwv/5BQ9SwBLekVg/EaYeQFPiXcgrC2Y7vDMA8dM1SUEAEV82kgSQIlXNMvA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/pretty-format": "4.0.18",
+ "magic-string": "^0.30.21",
+ "pathe": "^2.0.3"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/spy": {
+ "version": "4.0.18",
+ "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.18.tgz",
+ "integrity": "sha512-cbQt3PTSD7P2OARdVW3qWER5EGq7PHlvE+QfzSC0lbwO+xnt7+XH06ZzFjFRgzUX//JmpxrCu92VdwvEPlWSNw==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/utils": {
+ "version": "4.0.18",
+ "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.18.tgz",
+ "integrity": "sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/pretty-format": "4.0.18",
+ "tinyrainbow": "^3.0.3"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/accepts": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
+ "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-types": "~2.1.34",
+ "negotiator": "0.6.3"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/acorn": {
+ "version": "8.15.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
+ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
+ "license": "MIT",
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-import-attributes": {
+ "version": "1.9.5",
+ "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz",
+ "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==",
+ "license": "MIT",
+ "peerDependencies": {
+ "acorn": "^8"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/agent-base": {
+ "version": "7.1.4",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
+ "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ajv-formats": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz",
+ "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ajv": "^8.0.0"
+ },
+ "peerDependencies": {
+ "ajv": "^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "ajv": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/ajv-formats/node_modules/ajv": {
+ "version": "8.18.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz",
+ "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==",
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3",
+ "fast-uri": "^3.0.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ajv-formats/node_modules/json-schema-traverse": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+ "license": "MIT"
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/ansis": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/ansis/-/ansis-4.2.0.tgz",
+ "integrity": "sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/apache-arrow": {
+ "version": "21.1.0",
+ "resolved": "https://registry.npmjs.org/apache-arrow/-/apache-arrow-21.1.0.tgz",
+ "integrity": "sha512-kQrYLxhC+NTVVZ4CCzGF6L/uPVOzJmD1T3XgbiUnP7oTeVFOFgEUu6IKNwCDkpFoBVqDKQivlX4RUFqqnWFlEA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@swc/helpers": "^0.5.11",
+ "@types/command-line-args": "^5.2.3",
+ "@types/command-line-usage": "^5.0.4",
+ "@types/node": "^24.0.3",
+ "command-line-args": "^6.0.1",
+ "command-line-usage": "^7.0.1",
+ "flatbuffers": "^25.1.24",
+ "json-bignum": "^0.0.3",
+ "tslib": "^2.6.2"
+ },
+ "bin": {
+ "arrow2csv": "bin/arrow2csv.js"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true,
+ "license": "Python-2.0"
+ },
+ "node_modules/aria-hidden": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz",
+ "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==",
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/array-back": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.2.tgz",
+ "integrity": "sha512-gUAZ7HPyb4SJczXAMUXMGAvI976JoK3qEx9v1FTmeYuJj0IBiaKttG1ydtGKdkfqWkIkouke7nG8ufGy77+Cvw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.17"
+ }
+ },
+ "node_modules/array-buffer-byte-length": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz",
+ "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "is-array-buffer": "^3.0.5"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array-flatten": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
+ "license": "MIT"
+ },
+ "node_modules/array-includes": {
+ "version": "3.1.9",
+ "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz",
+ "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.24.0",
+ "es-object-atoms": "^1.1.1",
+ "get-intrinsic": "^1.3.0",
+ "is-string": "^1.1.1",
+ "math-intrinsics": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.findlast": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz",
+ "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0",
+ "es-shim-unscopables": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.flat": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz",
+ "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.5",
+ "es-shim-unscopables": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.flatmap": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz",
+ "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.5",
+ "es-shim-unscopables": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.tosorted": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz",
+ "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.3",
+ "es-errors": "^1.3.0",
+ "es-shim-unscopables": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/arraybuffer.prototype.slice": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz",
+ "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array-buffer-byte-length": "^1.0.1",
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.5",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6",
+ "is-array-buffer": "^3.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/assertion-error": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz",
+ "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/async-function": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz",
+ "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/autoprefixer": {
+ "version": "10.4.23",
+ "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.23.tgz",
+ "integrity": "sha512-YYTXSFulfwytnjAPlw8QHncHJmlvFKtczb8InXaAx9Q0LbfDnfEYDE55omerIJKihhmU61Ft+cAOSzQVaBUmeA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/autoprefixer"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "browserslist": "^4.28.1",
+ "caniuse-lite": "^1.0.30001760",
+ "fraction.js": "^5.3.4",
+ "picocolors": "^1.1.1",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "bin": {
+ "autoprefixer": "bin/autoprefixer"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ },
+ "peerDependencies": {
+ "postcss": "^8.1.0"
+ }
+ },
+ "node_modules/available-typed-arrays": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
+ "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "possible-typed-array-names": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "license": "MIT"
+ },
+ "node_modules/base64-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/baseline-browser-mapping": {
+ "version": "2.9.19",
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.19.tgz",
+ "integrity": "sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "baseline-browser-mapping": "dist/cli.js"
+ }
+ },
+ "node_modules/bignumber.js": {
+ "version": "9.3.1",
+ "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz",
+ "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==",
+ "license": "MIT",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/body-parser": {
+ "version": "1.20.4",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz",
+ "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==",
+ "license": "MIT",
+ "dependencies": {
+ "bytes": "~3.1.2",
+ "content-type": "~1.0.5",
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "destroy": "~1.2.0",
+ "http-errors": "~2.0.1",
+ "iconv-lite": "~0.4.24",
+ "on-finished": "~2.4.1",
+ "qs": "~6.14.0",
+ "raw-body": "~2.5.3",
+ "type-is": "~1.6.18",
+ "unpipe": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8",
+ "npm": "1.2.8000 || >= 1.4.16"
+ }
+ },
+ "node_modules/body-parser/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/body-parser/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "license": "MIT"
+ },
+ "node_modules/brace-expansion": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
+ "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.28.1",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz",
+ "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "baseline-browser-mapping": "^2.9.0",
+ "caniuse-lite": "^1.0.30001759",
+ "electron-to-chromium": "^1.5.263",
+ "node-releases": "^2.0.27",
+ "update-browserslist-db": "^1.2.0"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "node_modules/buffer-equal-constant-time": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
+ "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/bytes": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
+ "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/call-bind": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
+ "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.0",
+ "es-define-property": "^1.0.0",
+ "get-intrinsic": "^1.2.4",
+ "set-function-length": "^1.2.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/call-bind-apply-helpers": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+ "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/call-bound": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
+ "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "get-intrinsic": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001766",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001766.tgz",
+ "integrity": "sha512-4C0lfJ0/YPjJQHagaE9x2Elb69CIqEPZeG0anQt9SIvIoOH4a4uaRl73IavyO+0qZh6MDLH//DrXThEYKHkmYA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "CC-BY-4.0"
+ },
+ "node_modules/chai": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz",
+ "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/chalk-template": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/chalk-template/-/chalk-template-0.4.0.tgz",
+ "integrity": "sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg==",
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.1.2"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk-template?sponsor=1"
+ }
+ },
+ "node_modules/cjs-module-lexer": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.2.0.tgz",
+ "integrity": "sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==",
+ "license": "MIT"
+ },
+ "node_modules/class-variance-authority": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz",
+ "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "clsx": "^2.1.1"
+ },
+ "funding": {
+ "url": "https://polar.sh/cva"
+ }
+ },
+ "node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/clsx": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
+ "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/cmdk": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/cmdk/-/cmdk-1.1.1.tgz",
+ "integrity": "sha512-Vsv7kFaXm+ptHDMZ7izaRsP70GgrW9NBNGswt9OZaVBLlE0SNpDq8eu/VGXyF9r7M0azK3Wy7OlYXsuyYLFzHg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "^1.1.1",
+ "@radix-ui/react-dialog": "^1.1.6",
+ "@radix-ui/react-id": "^1.1.0",
+ "@radix-ui/react-primitive": "^2.0.2"
+ },
+ "peerDependencies": {
+ "react": "^18 || ^19 || ^19.0.0-rc",
+ "react-dom": "^18 || ^19 || ^19.0.0-rc"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "license": "MIT"
+ },
+ "node_modules/command-line-args": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-6.0.1.tgz",
+ "integrity": "sha512-Jr3eByUjqyK0qd8W0SGFW1nZwqCaNCtbXjRo2cRJC1OYxWl3MZ5t1US3jq+cO4sPavqgw4l9BMGX0CBe+trepg==",
+ "license": "MIT",
+ "dependencies": {
+ "array-back": "^6.2.2",
+ "find-replace": "^5.0.2",
+ "lodash.camelcase": "^4.3.0",
+ "typical": "^7.2.0"
+ },
+ "engines": {
+ "node": ">=12.20"
+ },
+ "peerDependencies": {
+ "@75lb/nature": "latest"
+ },
+ "peerDependenciesMeta": {
+ "@75lb/nature": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/command-line-usage": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-7.0.3.tgz",
+ "integrity": "sha512-PqMLy5+YGwhMh1wS04mVG44oqDsgyLRSKJBdOo1bnYhMKBW65gZF1dRp2OZRhiTjgUHljy99qkO7bsctLaw35Q==",
+ "license": "MIT",
+ "dependencies": {
+ "array-back": "^6.2.2",
+ "chalk-template": "^0.4.0",
+ "table-layout": "^4.1.0",
+ "typical": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=12.20.0"
+ }
+ },
+ "node_modules/commander": {
+ "version": "12.1.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz",
+ "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/content-disposition": {
+ "version": "0.5.4",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
+ "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "5.2.1"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/content-type": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
+ "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/cookie": {
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
+ "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/cookie-signature": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz",
+ "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==",
+ "license": "MIT"
+ },
+ "node_modules/copy-anything": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-4.0.5.tgz",
+ "integrity": "sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA==",
+ "license": "MIT",
+ "dependencies": {
+ "is-what": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mesqueeb"
+ }
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/csstype": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
+ "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/d3-array": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz",
+ "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==",
+ "license": "ISC",
+ "peer": true,
+ "dependencies": {
+ "internmap": "1 - 2"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-color": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz",
+ "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==",
+ "license": "ISC",
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-ease": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz",
+ "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==",
+ "license": "BSD-3-Clause",
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-format": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz",
+ "integrity": "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==",
+ "license": "ISC",
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-interpolate": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz",
+ "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==",
+ "license": "ISC",
+ "peer": true,
+ "dependencies": {
+ "d3-color": "1 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-path": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz",
+ "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==",
+ "license": "ISC",
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-scale": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz",
+ "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==",
+ "license": "ISC",
+ "peer": true,
+ "dependencies": {
+ "d3-array": "2.10.0 - 3",
+ "d3-format": "1 - 3",
+ "d3-interpolate": "1.2.0 - 3",
+ "d3-time": "2.1.1 - 3",
+ "d3-time-format": "2 - 4"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-shape": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz",
+ "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==",
+ "license": "ISC",
+ "peer": true,
+ "dependencies": {
+ "d3-path": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-time": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz",
+ "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==",
+ "license": "ISC",
+ "peer": true,
+ "dependencies": {
+ "d3-array": "2 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-time-format": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz",
+ "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==",
+ "license": "ISC",
+ "peer": true,
+ "dependencies": {
+ "d3-time": "1 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-timer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz",
+ "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==",
+ "license": "ISC",
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/data-uri-to-buffer": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
+ "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 12"
+ }
+ },
+ "node_modules/data-view-buffer": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz",
+ "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/data-view-byte-length": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz",
+ "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/inspect-js"
+ }
+ },
+ "node_modules/data-view-byte-offset": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz",
+ "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/date-fns": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz",
+ "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/kossnocorp"
+ }
+ },
+ "node_modules/date-fns-jalali": {
+ "version": "4.1.0-0",
+ "resolved": "https://registry.npmjs.org/date-fns-jalali/-/date-fns-jalali-4.1.0-0.tgz",
+ "integrity": "sha512-hTIP/z+t+qKwBDcmmsnmjWTduxCg+5KfdqWQvb2X/8C9+knYY6epN/pfxdDuyVlSVeFz0sM5eEfwIUQ70U4ckg==",
+ "license": "MIT"
+ },
+ "node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/decimal.js-light": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz",
+ "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/define-data-property": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
+ "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/define-properties": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
+ "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-data-property": "^1.0.1",
+ "has-property-descriptors": "^1.0.0",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/depd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/destroy": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
+ "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8",
+ "npm": "1.2.8000 || >= 1.4.16"
+ }
+ },
+ "node_modules/detect-libc": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
+ "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/detect-node-es": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz",
+ "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==",
+ "license": "MIT"
+ },
+ "node_modules/doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/dotenv": {
+ "version": "16.6.1",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz",
+ "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://dotenvx.com"
+ }
+ },
+ "node_modules/dunder-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
+ "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.2.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/eastasianwidth": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
+ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
+ "license": "MIT"
+ },
+ "node_modules/ecdsa-sig-formatter": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
+ "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/echarts": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/echarts/-/echarts-6.0.0.tgz",
+ "integrity": "sha512-Tte/grDQRiETQP4xz3iZWSvoHrkCQtwqd6hs+mifXcjrCuo2iKWbajFObuLJVBlDIJlOzgQPd1hsaKt/3+OMkQ==",
+ "license": "Apache-2.0",
+ "peer": true,
+ "dependencies": {
+ "tslib": "2.3.0",
+ "zrender": "6.0.0"
+ }
+ },
+ "node_modules/echarts-for-react": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/echarts-for-react/-/echarts-for-react-3.0.6.tgz",
+ "integrity": "sha512-4zqLgTGWS3JvkQDXjzkR1k1CHRdpd6by0988TWMJgnvDytegWLbeP/VNZmMa+0VJx2eD7Y632bi2JquXDgiGJg==",
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3",
+ "size-sensor": "^1.0.1"
+ },
+ "peerDependencies": {
+ "echarts": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0",
+ "react": "^15.0.0 || >=16.0.0"
+ }
+ },
+ "node_modules/echarts/node_modules/tslib": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz",
+ "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==",
+ "license": "0BSD",
+ "peer": true
+ },
+ "node_modules/ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
+ "license": "MIT"
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.5.283",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.283.tgz",
+ "integrity": "sha512-3vifjt1HgrGW/h76UEeny+adYApveS9dH2h3p57JYzBSXJIKUJAvtmIytDKjcSCt9xHfrNCFJ7gts6vkhuq++w==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/embla-carousel": {
+ "version": "8.6.0",
+ "resolved": "https://registry.npmjs.org/embla-carousel/-/embla-carousel-8.6.0.tgz",
+ "integrity": "sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA==",
+ "license": "MIT"
+ },
+ "node_modules/embla-carousel-react": {
+ "version": "8.6.0",
+ "resolved": "https://registry.npmjs.org/embla-carousel-react/-/embla-carousel-react-8.6.0.tgz",
+ "integrity": "sha512-0/PjqU7geVmo6F734pmPqpyHqiM99olvyecY7zdweCw+6tKEXnrE90pBiBbMMU8s5tICemzpQ3hi5EpxzGW+JA==",
+ "license": "MIT",
+ "dependencies": {
+ "embla-carousel": "8.6.0",
+ "embla-carousel-reactive-utils": "8.6.0"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.1 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
+ }
+ },
+ "node_modules/embla-carousel-reactive-utils": {
+ "version": "8.6.0",
+ "resolved": "https://registry.npmjs.org/embla-carousel-reactive-utils/-/embla-carousel-reactive-utils-8.6.0.tgz",
+ "integrity": "sha512-fMVUDUEx0/uIEDM0Mz3dHznDhfX+znCCDCeIophYb1QGVM7YThSWX+wz11zlYwWFOr74b4QLGg0hrGPJeG2s4A==",
+ "license": "MIT",
+ "peerDependencies": {
+ "embla-carousel": "8.6.0"
+ }
+ },
+ "node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "license": "MIT"
+ },
+ "node_modules/encodeurl": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
+ "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/enhanced-resolve": {
+ "version": "5.18.4",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.4.tgz",
+ "integrity": "sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "graceful-fs": "^4.2.4",
+ "tapable": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/es-abstract": {
+ "version": "1.24.1",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.1.tgz",
+ "integrity": "sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array-buffer-byte-length": "^1.0.2",
+ "arraybuffer.prototype.slice": "^1.0.4",
+ "available-typed-arrays": "^1.0.7",
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "data-view-buffer": "^1.0.2",
+ "data-view-byte-length": "^1.0.2",
+ "data-view-byte-offset": "^1.0.1",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "es-set-tostringtag": "^2.1.0",
+ "es-to-primitive": "^1.3.0",
+ "function.prototype.name": "^1.1.8",
+ "get-intrinsic": "^1.3.0",
+ "get-proto": "^1.0.1",
+ "get-symbol-description": "^1.1.0",
+ "globalthis": "^1.0.4",
+ "gopd": "^1.2.0",
+ "has-property-descriptors": "^1.0.2",
+ "has-proto": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "hasown": "^2.0.2",
+ "internal-slot": "^1.1.0",
+ "is-array-buffer": "^3.0.5",
+ "is-callable": "^1.2.7",
+ "is-data-view": "^1.0.2",
+ "is-negative-zero": "^2.0.3",
+ "is-regex": "^1.2.1",
+ "is-set": "^2.0.3",
+ "is-shared-array-buffer": "^1.0.4",
+ "is-string": "^1.1.1",
+ "is-typed-array": "^1.1.15",
+ "is-weakref": "^1.1.1",
+ "math-intrinsics": "^1.1.0",
+ "object-inspect": "^1.13.4",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.7",
+ "own-keys": "^1.0.1",
+ "regexp.prototype.flags": "^1.5.4",
+ "safe-array-concat": "^1.1.3",
+ "safe-push-apply": "^1.0.0",
+ "safe-regex-test": "^1.1.0",
+ "set-proto": "^1.0.0",
+ "stop-iteration-iterator": "^1.1.0",
+ "string.prototype.trim": "^1.2.10",
+ "string.prototype.trimend": "^1.0.9",
+ "string.prototype.trimstart": "^1.0.8",
+ "typed-array-buffer": "^1.0.3",
+ "typed-array-byte-length": "^1.0.3",
+ "typed-array-byte-offset": "^1.0.4",
+ "typed-array-length": "^1.0.7",
+ "unbox-primitive": "^1.1.0",
+ "which-typed-array": "^1.1.19"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/es-define-property": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
+ "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-iterator-helpers": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.2.tgz",
+ "integrity": "sha512-BrUQ0cPTB/IwXj23HtwHjS9n7O4h9FX94b4xc5zlTHxeLgTAdzYUDyy6KdExAl9lbN5rtfe44xpjpmj9grxs5w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.24.1",
+ "es-errors": "^1.3.0",
+ "es-set-tostringtag": "^2.1.0",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.3.0",
+ "globalthis": "^1.0.4",
+ "gopd": "^1.2.0",
+ "has-property-descriptors": "^1.0.2",
+ "has-proto": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "internal-slot": "^1.1.0",
+ "iterator.prototype": "^1.1.5",
+ "safe-array-concat": "^1.1.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-module-lexer": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz",
+ "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/es-object-atoms": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
+ "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-set-tostringtag": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+ "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-shim-unscopables": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz",
+ "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-to-primitive": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz",
+ "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-callable": "^1.2.7",
+ "is-date-object": "^1.0.5",
+ "is-symbol": "^1.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/es-toolkit": {
+ "version": "1.44.0",
+ "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.44.0.tgz",
+ "integrity": "sha512-6penXeZalaV88MM3cGkFZZfOoLGWshWWfdy0tWw/RlVVyhvMaWSBTOvXNeiW3e5FwdS5ePW0LGEu17zT139ktg==",
+ "license": "MIT",
+ "peer": true,
+ "workspaces": [
+ "docs",
+ "benchmarks"
+ ]
+ },
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
+ "license": "MIT"
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "9.39.2",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz",
+ "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.8.0",
+ "@eslint-community/regexpp": "^4.12.1",
+ "@eslint/config-array": "^0.21.1",
+ "@eslint/config-helpers": "^0.4.2",
+ "@eslint/core": "^0.17.0",
+ "@eslint/eslintrc": "^3.3.1",
+ "@eslint/js": "9.39.2",
+ "@eslint/plugin-kit": "^0.4.1",
+ "@humanfs/node": "^0.16.6",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@humanwhocodes/retry": "^0.4.2",
+ "@types/estree": "^1.0.6",
+ "ajv": "^6.12.4",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.6",
+ "debug": "^4.3.2",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^8.4.0",
+ "eslint-visitor-keys": "^4.2.1",
+ "espree": "^10.4.0",
+ "esquery": "^1.5.0",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^8.0.0",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://eslint.org/donate"
+ },
+ "peerDependencies": {
+ "jiti": "*"
+ },
+ "peerDependenciesMeta": {
+ "jiti": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-config-prettier": {
+ "version": "10.1.8",
+ "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz",
+ "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "eslint-config-prettier": "bin/cli.js"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint-config-prettier"
+ },
+ "peerDependencies": {
+ "eslint": ">=7.0.0"
+ }
+ },
+ "node_modules/eslint-plugin-react": {
+ "version": "7.37.5",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz",
+ "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array-includes": "^3.1.8",
+ "array.prototype.findlast": "^1.2.5",
+ "array.prototype.flatmap": "^1.3.3",
+ "array.prototype.tosorted": "^1.1.4",
+ "doctrine": "^2.1.0",
+ "es-iterator-helpers": "^1.2.1",
+ "estraverse": "^5.3.0",
+ "hasown": "^2.0.2",
+ "jsx-ast-utils": "^2.4.1 || ^3.0.0",
+ "minimatch": "^3.1.2",
+ "object.entries": "^1.1.9",
+ "object.fromentries": "^2.0.8",
+ "object.values": "^1.2.1",
+ "prop-types": "^15.8.1",
+ "resolve": "^2.0.0-next.5",
+ "semver": "^6.3.1",
+ "string.prototype.matchall": "^4.0.12",
+ "string.prototype.repeat": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependencies": {
+ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7"
+ }
+ },
+ "node_modules/eslint-plugin-react-hooks": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.0.1.tgz",
+ "integrity": "sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.24.4",
+ "@babel/parser": "^7.24.4",
+ "hermes-parser": "^0.25.1",
+ "zod": "^3.25.0 || ^4.0.0",
+ "zod-validation-error": "^3.5.0 || ^4.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0"
+ }
+ },
+ "node_modules/eslint-plugin-react-refresh": {
+ "version": "0.4.26",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.26.tgz",
+ "integrity": "sha512-1RETEylht2O6FM/MvgnyvT+8K21wLqDNg4qD51Zj3guhjt433XbnnkVttHMyaVyAFD03QSV4LPS5iE3VQmO7XQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "eslint": ">=8.40"
+ }
+ },
+ "node_modules/eslint-plugin-react/node_modules/brace-expansion": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/eslint-plugin-react/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/eslint-plugin-react/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "8.4.0",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz",
+ "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint/node_modules/@eslint/core": {
+ "version": "0.17.0",
+ "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz",
+ "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/json-schema": "^7.0.15"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/eslint/node_modules/brace-expansion": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/eslint/node_modules/eslint-visitor-keys": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
+ "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint/node_modules/ignore": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
+ "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/eslint/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/espree": {
+ "version": "10.4.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
+ "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "acorn": "^8.15.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^4.2.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/espree/node_modules/eslint-visitor-keys": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
+ "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz",
+ "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estree-walker": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
+ "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/etag": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+ "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/eventemitter3": {
+ "version": "5.0.4",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz",
+ "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/expect-type": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz",
+ "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/express": {
+ "version": "4.22.1",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz",
+ "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==",
+ "license": "MIT",
+ "dependencies": {
+ "accepts": "~1.3.8",
+ "array-flatten": "1.1.1",
+ "body-parser": "~1.20.3",
+ "content-disposition": "~0.5.4",
+ "content-type": "~1.0.4",
+ "cookie": "~0.7.1",
+ "cookie-signature": "~1.0.6",
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "encodeurl": "~2.0.0",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "finalhandler": "~1.3.1",
+ "fresh": "~0.5.2",
+ "http-errors": "~2.0.0",
+ "merge-descriptors": "1.0.3",
+ "methods": "~1.1.2",
+ "on-finished": "~2.4.1",
+ "parseurl": "~1.3.3",
+ "path-to-regexp": "~0.1.12",
+ "proxy-addr": "~2.0.7",
+ "qs": "~6.14.0",
+ "range-parser": "~1.2.1",
+ "safe-buffer": "5.2.1",
+ "send": "~0.19.0",
+ "serve-static": "~1.16.2",
+ "setprototypeof": "1.2.0",
+ "statuses": "~2.0.1",
+ "type-is": "~1.6.18",
+ "utils-merge": "1.0.1",
+ "vary": "~1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.10.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/express/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/express/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "license": "MIT"
+ },
+ "node_modules/extend": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
+ "license": "MIT"
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "license": "MIT"
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-uri": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz",
+ "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fastify"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fastify"
+ }
+ ],
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/fdir": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
+ "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "picomatch": "^3 || ^4"
+ },
+ "peerDependenciesMeta": {
+ "picomatch": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/fetch-blob": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
+ "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/jimmywarting"
+ },
+ {
+ "type": "paypal",
+ "url": "https://paypal.me/jimmywarting"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "node-domexception": "^1.0.0",
+ "web-streams-polyfill": "^3.0.3"
+ },
+ "engines": {
+ "node": "^12.20 || >= 14.13"
+ }
+ },
+ "node_modules/file-entry-cache": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
+ "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flat-cache": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "node_modules/finalhandler": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz",
+ "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "2.6.9",
+ "encodeurl": "~2.0.0",
+ "escape-html": "~1.0.3",
+ "on-finished": "~2.4.1",
+ "parseurl": "~1.3.3",
+ "statuses": "~2.0.2",
+ "unpipe": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/finalhandler/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/finalhandler/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "license": "MIT"
+ },
+ "node_modules/find-replace": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-5.0.2.tgz",
+ "integrity": "sha512-Y45BAiE3mz2QsrN2fb5QEtO4qb44NcS7en/0y9PEVsg351HsLeVclP8QPMH79Le9sH3rs5RSwJu99W0WPZO43Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@75lb/nature": "latest"
+ },
+ "peerDependenciesMeta": {
+ "@75lb/nature": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
+ "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.4"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/flatbuffers": {
+ "version": "25.9.23",
+ "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-25.9.23.tgz",
+ "integrity": "sha512-MI1qs7Lo4Syw0EOzUl0xjs2lsoeqFku44KpngfIduHBYvzm8h2+7K8YMQh1JtVVVrUvhLpNwqVi4DERegUJhPQ==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/flatted": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
+ "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/for-each": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
+ "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-callable": "^1.2.7"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/foreground-child": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
+ "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==",
+ "license": "ISC",
+ "dependencies": {
+ "cross-spawn": "^7.0.6",
+ "signal-exit": "^4.0.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/formdata-polyfill": {
+ "version": "4.0.10",
+ "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
+ "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
+ "license": "MIT",
+ "dependencies": {
+ "fetch-blob": "^3.1.2"
+ },
+ "engines": {
+ "node": ">=12.20.0"
+ }
+ },
+ "node_modules/forwarded": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
+ "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/forwarded-parse": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/forwarded-parse/-/forwarded-parse-2.1.2.tgz",
+ "integrity": "sha512-alTFZZQDKMporBH77856pXgzhEzaUVmLCDk+egLgIgHst3Tpndzz8MnKe+GzRJRfvVdn69HhpW7cmXzvtLvJAw==",
+ "license": "MIT"
+ },
+ "node_modules/fraction.js": {
+ "version": "5.3.4",
+ "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz",
+ "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/rawify"
+ }
+ },
+ "node_modules/fresh": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+ "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/function.prototype.name": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz",
+ "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "define-properties": "^1.2.1",
+ "functions-have-names": "^1.2.3",
+ "hasown": "^2.0.2",
+ "is-callable": "^1.2.7"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/functions-have-names": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
+ "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/gaxios": {
+ "version": "6.7.1",
+ "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.7.1.tgz",
+ "integrity": "sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "extend": "^3.0.2",
+ "https-proxy-agent": "^7.0.1",
+ "is-stream": "^2.0.0",
+ "node-fetch": "^2.6.9",
+ "uuid": "^9.0.1"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/gcp-metadata": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-6.1.1.tgz",
+ "integrity": "sha512-a4tiq7E0/5fTjxPAaH4jpjkSv/uCaU2p5KC6HVGrvl0cDjA8iBZv4vv1gyzlmK0ZUKqwpOyQMKzZQe3lTit77A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "gaxios": "^6.1.1",
+ "google-logging-utils": "^0.0.2",
+ "json-bigint": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/generator-function": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz",
+ "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/gensync": {
+ "version": "1.0.0-beta.2",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "license": "ISC",
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+ "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "function-bind": "^1.1.2",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "hasown": "^2.0.2",
+ "math-intrinsics": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-nonce": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz",
+ "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/get-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
+ "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/get-symbol-description": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz",
+ "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-tsconfig": {
+ "version": "4.13.0",
+ "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz",
+ "integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "resolve-pkg-maps": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
+ }
+ },
+ "node_modules/glob": {
+ "version": "10.5.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz",
+ "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==",
+ "license": "ISC",
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^3.1.2",
+ "minimatch": "^9.0.4",
+ "minipass": "^7.1.2",
+ "package-json-from-dist": "^1.0.0",
+ "path-scurry": "^1.11.1"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/globals": {
+ "version": "14.0.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
+ "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/globalthis": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz",
+ "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-properties": "^1.2.1",
+ "gopd": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/google-auth-library": {
+ "version": "10.5.0",
+ "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.5.0.tgz",
+ "integrity": "sha512-7ABviyMOlX5hIVD60YOfHw4/CxOfBhyduaYB+wbFWCWoni4N7SLcV46hrVRktuBbZjFC9ONyqamZITN7q3n32w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "base64-js": "^1.3.0",
+ "ecdsa-sig-formatter": "^1.0.11",
+ "gaxios": "^7.0.0",
+ "gcp-metadata": "^8.0.0",
+ "google-logging-utils": "^1.0.0",
+ "gtoken": "^8.0.0",
+ "jws": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/google-auth-library/node_modules/gaxios": {
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.3.tgz",
+ "integrity": "sha512-YGGyuEdVIjqxkxVH1pUTMY/XtmmsApXrCVv5EU25iX6inEPbV+VakJfLealkBtJN69AQmh1eGOdCl9Sm1UP6XQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "extend": "^3.0.2",
+ "https-proxy-agent": "^7.0.1",
+ "node-fetch": "^3.3.2",
+ "rimraf": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/google-auth-library/node_modules/gcp-metadata": {
+ "version": "8.1.2",
+ "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-8.1.2.tgz",
+ "integrity": "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "gaxios": "^7.0.0",
+ "google-logging-utils": "^1.0.0",
+ "json-bigint": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/google-auth-library/node_modules/google-logging-utils": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-1.1.3.tgz",
+ "integrity": "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/google-auth-library/node_modules/node-fetch": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
+ "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
+ "license": "MIT",
+ "dependencies": {
+ "data-uri-to-buffer": "^4.0.0",
+ "fetch-blob": "^3.1.4",
+ "formdata-polyfill": "^4.0.10"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/node-fetch"
+ }
+ },
+ "node_modules/google-logging-utils": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-0.0.2.tgz",
+ "integrity": "sha512-NEgUnEcBiP5HrPzufUkBzJOD/Sxsco3rLNo1F1TNf7ieU8ryUzBhqba8r756CjLX7rn3fHl6iLEwPYuqpoKgQQ==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/gopd": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
+ "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/gtoken": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-8.0.0.tgz",
+ "integrity": "sha512-+CqsMbHPiSTdtSO14O51eMNlrp9N79gmeqmXeouJOhfucAedHw9noVe/n5uJk3tbKE6a+6ZCQg3RPhVhHByAIw==",
+ "license": "MIT",
+ "dependencies": {
+ "gaxios": "^7.0.0",
+ "jws": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/gtoken/node_modules/gaxios": {
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.3.tgz",
+ "integrity": "sha512-YGGyuEdVIjqxkxVH1pUTMY/XtmmsApXrCVv5EU25iX6inEPbV+VakJfLealkBtJN69AQmh1eGOdCl9Sm1UP6XQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "extend": "^3.0.2",
+ "https-proxy-agent": "^7.0.1",
+ "node-fetch": "^3.3.2",
+ "rimraf": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/gtoken/node_modules/node-fetch": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
+ "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
+ "license": "MIT",
+ "dependencies": {
+ "data-uri-to-buffer": "^4.0.0",
+ "fetch-blob": "^3.1.4",
+ "formdata-polyfill": "^4.0.10"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/node-fetch"
+ }
+ },
+ "node_modules/has-bigints": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz",
+ "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/has-property-descriptors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
+ "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-define-property": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-proto": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz",
+ "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
+ "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-tostringtag": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+ "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-symbols": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "license": "MIT",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/hermes-estree": {
+ "version": "0.25.1",
+ "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz",
+ "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/hermes-parser": {
+ "version": "0.25.1",
+ "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz",
+ "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hermes-estree": "0.25.1"
+ }
+ },
+ "node_modules/http-errors": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz",
+ "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==",
+ "license": "MIT",
+ "dependencies": {
+ "depd": "~2.0.0",
+ "inherits": "~2.0.4",
+ "setprototypeof": "~1.2.0",
+ "statuses": "~2.0.2",
+ "toidentifier": "~1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/https-proxy-agent": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
+ "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^7.1.2",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "license": "MIT",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/ignore": {
+ "version": "7.0.5",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
+ "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/immer": {
+ "version": "10.2.0",
+ "resolved": "https://registry.npmjs.org/immer/-/immer-10.2.0.tgz",
+ "integrity": "sha512-d/+XTN3zfODyjr89gM3mPq1WNX2B8pYsu7eORitdwyA2sBubnTl3laYlBk4sXY5FUa5qTZGBDPJICVbvqzjlbw==",
+ "license": "MIT",
+ "peer": true,
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/immer"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
+ "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/import-in-the-middle": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-2.0.6.tgz",
+ "integrity": "sha512-3vZV3jX0XRFW3EJDTwzWoZa+RH1b8eTTx6YOCjglrLyPuepwoBti1k3L2dKwdCUrnVEfc5CuRuGstaC/uQJJaw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "acorn": "^8.15.0",
+ "acorn-import-attributes": "^1.9.5",
+ "cjs-module-lexer": "^2.2.0",
+ "module-details-from-path": "^1.0.4"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "license": "ISC"
+ },
+ "node_modules/ini": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-6.0.0.tgz",
+ "integrity": "sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ==",
+ "license": "ISC",
+ "engines": {
+ "node": "^20.17.0 || >=22.9.0"
+ }
+ },
+ "node_modules/input-otp": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/input-otp/-/input-otp-1.4.2.tgz",
+ "integrity": "sha512-l3jWwYNvrEa6NTCt7BECfCm48GvwuZzkoeG3gBL2w4CHeOXW3eKFmf9UNYkNfYc3mxMrthMnxjIE07MT0zLBQA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc"
+ }
+ },
+ "node_modules/internal-slot": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz",
+ "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "hasown": "^2.0.2",
+ "side-channel": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/internmap": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz",
+ "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==",
+ "license": "ISC",
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/ipaddr.js": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
+ "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/is-array-buffer": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz",
+ "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "get-intrinsic": "^1.2.6"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-async-function": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz",
+ "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "async-function": "^1.0.0",
+ "call-bound": "^1.0.3",
+ "get-proto": "^1.0.1",
+ "has-tostringtag": "^1.0.2",
+ "safe-regex-test": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-bigint": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz",
+ "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-bigints": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-boolean-object": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz",
+ "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-callable": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
+ "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.16.1",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
+ "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-data-view": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz",
+ "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "get-intrinsic": "^1.2.6",
+ "is-typed-array": "^1.1.13"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-date-object": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz",
+ "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-finalizationregistry": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz",
+ "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-generator-function": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz",
+ "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.4",
+ "generator-function": "^2.0.0",
+ "get-proto": "^1.0.1",
+ "has-tostringtag": "^1.0.2",
+ "safe-regex-test": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-map": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz",
+ "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-negative-zero": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz",
+ "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-number-object": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz",
+ "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-regex": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
+ "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "gopd": "^1.2.0",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-set": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz",
+ "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-shared-array-buffer": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz",
+ "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-stream": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
+ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-string": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz",
+ "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-symbol": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz",
+ "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "has-symbols": "^1.1.0",
+ "safe-regex-test": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-typed-array": {
+ "version": "1.1.15",
+ "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz",
+ "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "which-typed-array": "^1.1.16"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-weakmap": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz",
+ "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-weakref": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz",
+ "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-weakset": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz",
+ "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "get-intrinsic": "^1.2.6"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-what": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/is-what/-/is-what-5.5.0.tgz",
+ "integrity": "sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mesqueeb"
+ }
+ },
+ "node_modules/isarray": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
+ "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "license": "ISC"
+ },
+ "node_modules/iterator.prototype": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz",
+ "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-data-property": "^1.1.4",
+ "es-object-atoms": "^1.0.0",
+ "get-intrinsic": "^1.2.6",
+ "get-proto": "^1.0.0",
+ "has-symbols": "^1.1.0",
+ "set-function-name": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/jackspeak": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
+ "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "@isaacs/cliui": "^8.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "optionalDependencies": {
+ "@pkgjs/parseargs": "^0.11.0"
+ }
+ },
+ "node_modules/jiti": {
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz",
+ "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==",
+ "devOptional": true,
+ "license": "MIT",
+ "bin": {
+ "jiti": "lib/jiti-cli.mjs"
+ }
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/js-yaml": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
+ "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/jsesc": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
+ "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/json-bigint": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz",
+ "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==",
+ "license": "MIT",
+ "dependencies": {
+ "bignumber.js": "^9.0.0"
+ }
+ },
+ "node_modules/json-bignum": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/json-bignum/-/json-bignum-0.0.3.tgz",
+ "integrity": "sha512-2WHyXj3OfHSgNyuzDbSxI1w2jgw5gkWSWhS7Qg4bWXx1nLk3jnbwfUeS0PSba3IzpTUWdHxBieELUzXRjQB2zg==",
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json5": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "json5": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/jsx-ast-utils": {
+ "version": "3.3.5",
+ "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz",
+ "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array-includes": "^3.1.6",
+ "array.prototype.flat": "^1.3.1",
+ "object.assign": "^4.1.4",
+ "object.values": "^1.1.6"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/jwa": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz",
+ "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==",
+ "license": "MIT",
+ "dependencies": {
+ "buffer-equal-constant-time": "^1.0.1",
+ "ecdsa-sig-formatter": "1.0.11",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/jws": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz",
+ "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==",
+ "license": "MIT",
+ "dependencies": {
+ "jwa": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/lightningcss": {
+ "version": "1.30.2",
+ "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.2.tgz",
+ "integrity": "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==",
+ "license": "MPL-2.0",
+ "dependencies": {
+ "detect-libc": "^2.0.3"
+ },
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ },
+ "optionalDependencies": {
+ "lightningcss-android-arm64": "1.30.2",
+ "lightningcss-darwin-arm64": "1.30.2",
+ "lightningcss-darwin-x64": "1.30.2",
+ "lightningcss-freebsd-x64": "1.30.2",
+ "lightningcss-linux-arm-gnueabihf": "1.30.2",
+ "lightningcss-linux-arm64-gnu": "1.30.2",
+ "lightningcss-linux-arm64-musl": "1.30.2",
+ "lightningcss-linux-x64-gnu": "1.30.2",
+ "lightningcss-linux-x64-musl": "1.30.2",
+ "lightningcss-win32-arm64-msvc": "1.30.2",
+ "lightningcss-win32-x64-msvc": "1.30.2"
+ }
+ },
+ "node_modules/lightningcss-android-arm64": {
+ "version": "1.30.2",
+ "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.30.2.tgz",
+ "integrity": "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-darwin-arm64": {
+ "version": "1.30.2",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.2.tgz",
+ "integrity": "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-darwin-x64": {
+ "version": "1.30.2",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.2.tgz",
+ "integrity": "sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-freebsd-x64": {
+ "version": "1.30.2",
+ "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.2.tgz",
+ "integrity": "sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm-gnueabihf": {
+ "version": "1.30.2",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.2.tgz",
+ "integrity": "sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm64-gnu": {
+ "version": "1.30.2",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.2.tgz",
+ "integrity": "sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm64-musl": {
+ "version": "1.30.2",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.2.tgz",
+ "integrity": "sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-x64-gnu": {
+ "version": "1.30.2",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.2.tgz",
+ "integrity": "sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-x64-musl": {
+ "version": "1.30.2",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.2.tgz",
+ "integrity": "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-win32-arm64-msvc": {
+ "version": "1.30.2",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.2.tgz",
+ "integrity": "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-win32-x64-msvc": {
+ "version": "1.30.2",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.2.tgz",
+ "integrity": "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lodash.camelcase": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
+ "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/long": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz",
+ "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ },
+ "bin": {
+ "loose-envify": "cli.js"
+ }
+ },
+ "node_modules/lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "node_modules/lucide-react": {
+ "version": "0.546.0",
+ "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.546.0.tgz",
+ "integrity": "sha512-Z94u6fKT43lKeYHiVyvyR8fT7pwCzDu7RyMPpTvh054+xahSgj4HFQ+NmflvzdXsoAjYGdCguGaFKYuvq0ThCQ==",
+ "license": "ISC",
+ "peerDependencies": {
+ "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
+ "node_modules/magic-string": {
+ "version": "0.30.21",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
+ "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.5"
+ }
+ },
+ "node_modules/math-intrinsics": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+ "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/media-typer": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+ "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/merge-descriptors": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
+ "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/methods": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+ "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+ "license": "MIT",
+ "bin": {
+ "mime": "cli.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+ "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/minipass": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
+ "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/module-details-from-path": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.4.tgz",
+ "integrity": "sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==",
+ "license": "MIT"
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.11",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
+ "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/negotiator": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
+ "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/next-themes": {
+ "version": "0.4.6",
+ "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.4.6.tgz",
+ "integrity": "sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc"
+ }
+ },
+ "node_modules/node-domexception": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
+ "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
+ "deprecated": "Use your platform's native DOMException instead",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/jimmywarting"
+ },
+ {
+ "type": "github",
+ "url": "https://paypal.me/jimmywarting"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.5.0"
+ }
+ },
+ "node_modules/node-fetch": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
+ "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
+ "license": "MIT",
+ "dependencies": {
+ "whatwg-url": "^5.0.0"
+ },
+ "engines": {
+ "node": "4.x || >=6.0.0"
+ },
+ "peerDependencies": {
+ "encoding": "^0.1.0"
+ },
+ "peerDependenciesMeta": {
+ "encoding": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.27",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz",
+ "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-inspect": {
+ "version": "1.13.4",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
+ "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.assign": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz",
+ "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0",
+ "has-symbols": "^1.1.0",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object.entries": {
+ "version": "1.1.9",
+ "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz",
+ "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.fromentries": {
+ "version": "2.0.8",
+ "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz",
+ "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object.values": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz",
+ "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/obug": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz",
+ "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==",
+ "funding": [
+ "https://github.com/sponsors/sxzz",
+ "https://opencollective.com/debug"
+ ],
+ "license": "MIT"
+ },
+ "node_modules/on-finished": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
+ "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
+ "license": "MIT",
+ "dependencies": {
+ "ee-first": "1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/optionator": {
+ "version": "0.9.4",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
+ "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.5"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/own-keys": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz",
+ "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "get-intrinsic": "^1.2.6",
+ "object-keys": "^1.1.1",
+ "safe-push-apply": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/package-json-from-dist": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
+ "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
+ "license": "BlueOak-1.0.0"
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parseurl": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/path-scurry": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
+ "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "lru-cache": "^10.2.0",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/path-scurry/node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+ "license": "ISC"
+ },
+ "node_modules/path-to-regexp": {
+ "version": "0.1.12",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz",
+ "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==",
+ "license": "MIT"
+ },
+ "node_modules/pathe": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
+ "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/pg": {
+ "version": "8.18.0",
+ "resolved": "https://registry.npmjs.org/pg/-/pg-8.18.0.tgz",
+ "integrity": "sha512-xqrUDL1b9MbkydY/s+VZ6v+xiMUmOUk7SS9d/1kpyQxoJ6U9AO1oIJyUWVZojbfe5Cc/oluutcgFG4L9RDP1iQ==",
+ "license": "MIT",
+ "dependencies": {
+ "pg-connection-string": "^2.11.0",
+ "pg-pool": "^3.11.0",
+ "pg-protocol": "^1.11.0",
+ "pg-types": "2.2.0",
+ "pgpass": "1.0.5"
+ },
+ "engines": {
+ "node": ">= 16.0.0"
+ },
+ "optionalDependencies": {
+ "pg-cloudflare": "^1.3.0"
+ },
+ "peerDependencies": {
+ "pg-native": ">=3.0.1"
+ },
+ "peerDependenciesMeta": {
+ "pg-native": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/pg-cloudflare": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.3.0.tgz",
+ "integrity": "sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/pg-connection-string": {
+ "version": "2.11.0",
+ "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.11.0.tgz",
+ "integrity": "sha512-kecgoJwhOpxYU21rZjULrmrBJ698U2RxXofKVzOn5UDj61BPj/qMb7diYUR1nLScCDbrztQFl1TaQZT0t1EtzQ==",
+ "license": "MIT"
+ },
+ "node_modules/pg-int8": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz",
+ "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
+ "node_modules/pg-pool": {
+ "version": "3.11.0",
+ "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.11.0.tgz",
+ "integrity": "sha512-MJYfvHwtGp870aeusDh+hg9apvOe2zmpZJpyt+BMtzUWlVqbhFmMK6bOBXLBUPd7iRtIF9fZplDc7KrPN3PN7w==",
+ "license": "MIT",
+ "peerDependencies": {
+ "pg": ">=8.0"
+ }
+ },
+ "node_modules/pg-protocol": {
+ "version": "1.11.0",
+ "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.11.0.tgz",
+ "integrity": "sha512-pfsxk2M9M3BuGgDOfuy37VNRRX3jmKgMjcvAcWqNDpZSf4cUmv8HSOl5ViRQFsfARFn0KuUQTgLxVMbNq5NW3g==",
+ "license": "MIT"
+ },
+ "node_modules/pg-types": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz",
+ "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==",
+ "license": "MIT",
+ "dependencies": {
+ "pg-int8": "1.0.1",
+ "postgres-array": "~2.0.0",
+ "postgres-bytea": "~1.0.0",
+ "postgres-date": "~1.0.4",
+ "postgres-interval": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/pgpass": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz",
+ "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==",
+ "license": "MIT",
+ "dependencies": {
+ "split2": "^4.1.0"
+ }
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "license": "ISC"
+ },
+ "node_modules/picomatch": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
+ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/playwright": {
+ "version": "1.58.0",
+ "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.58.0.tgz",
+ "integrity": "sha512-2SVA0sbPktiIY/MCOPX8e86ehA/e+tDNq+e5Y8qjKYti2Z/JG7xnronT/TXTIkKbYGWlCbuucZ6dziEgkoEjQQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "playwright-core": "1.58.0"
+ },
+ "bin": {
+ "playwright": "cli.js"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "fsevents": "2.3.2"
+ }
+ },
+ "node_modules/playwright-core": {
+ "version": "1.58.0",
+ "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.58.0.tgz",
+ "integrity": "sha512-aaoB1RWrdNi3//rOeKuMiS65UCcgOVljU46At6eFcOFPFHWtd2weHRRow6z/n+Lec0Lvu0k9ZPKJSjPugikirw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "playwright-core": "cli.js"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/possible-typed-array-names": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
+ "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.5.6",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
+ "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "nanoid": "^3.3.11",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/postcss-value-parser": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
+ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/postgres-array": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz",
+ "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/postgres-bytea": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.1.tgz",
+ "integrity": "sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/postgres-date": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz",
+ "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/postgres-interval": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz",
+ "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==",
+ "license": "MIT",
+ "dependencies": {
+ "xtend": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/prettier": {
+ "version": "3.8.1",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz",
+ "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "prettier": "bin/prettier.cjs"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
+ "node_modules/prop-types": {
+ "version": "15.8.1",
+ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+ "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "loose-envify": "^1.4.0",
+ "object-assign": "^4.1.1",
+ "react-is": "^16.13.1"
+ }
+ },
+ "node_modules/prop-types/node_modules/react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/protobufjs": {
+ "version": "7.5.4",
+ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.4.tgz",
+ "integrity": "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==",
+ "hasInstallScript": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@protobufjs/aspromise": "^1.1.2",
+ "@protobufjs/base64": "^1.1.2",
+ "@protobufjs/codegen": "^2.0.4",
+ "@protobufjs/eventemitter": "^1.1.0",
+ "@protobufjs/fetch": "^1.1.0",
+ "@protobufjs/float": "^1.0.2",
+ "@protobufjs/inquire": "^1.1.0",
+ "@protobufjs/path": "^1.1.2",
+ "@protobufjs/pool": "^1.1.0",
+ "@protobufjs/utf8": "^1.1.0",
+ "@types/node": ">=13.7.0",
+ "long": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/proxy-addr": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
+ "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
+ "license": "MIT",
+ "dependencies": {
+ "forwarded": "0.2.0",
+ "ipaddr.js": "1.9.1"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/punycode": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/qs": {
+ "version": "6.14.1",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz",
+ "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "side-channel": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/range-parser": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
+ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/raw-body": {
+ "version": "2.5.3",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz",
+ "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==",
+ "license": "MIT",
+ "dependencies": {
+ "bytes": "~3.1.2",
+ "http-errors": "~2.0.1",
+ "iconv-lite": "~0.4.24",
+ "unpipe": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/react": {
+ "version": "19.2.4",
+ "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz",
+ "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-day-picker": {
+ "version": "9.13.2",
+ "resolved": "https://registry.npmjs.org/react-day-picker/-/react-day-picker-9.13.2.tgz",
+ "integrity": "sha512-IMPiXfXVIAuR5Yk58DDPBC8QKClrhdXV+Tr/alBrwrHUw0qDDYB1m5zPNuTnnPIr/gmJ4ChMxmtqPdxm8+R4Eg==",
+ "license": "MIT",
+ "dependencies": {
+ "@date-fns/tz": "^1.4.1",
+ "date-fns": "^4.1.0",
+ "date-fns-jalali": "^4.1.0-0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "individual",
+ "url": "https://github.com/sponsors/gpbl"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0"
+ }
+ },
+ "node_modules/react-dom": {
+ "version": "19.2.4",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz",
+ "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==",
+ "license": "MIT",
+ "dependencies": {
+ "scheduler": "^0.27.0"
+ },
+ "peerDependencies": {
+ "react": "^19.2.4"
+ }
+ },
+ "node_modules/react-hook-form": {
+ "version": "7.71.1",
+ "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.71.1.tgz",
+ "integrity": "sha512-9SUJKCGKo8HUSsCO+y0CtqkqI5nNuaDqTxyqPsZPqIwudpj4rCrAz/jZV+jn57bx5gtZKOh3neQu94DXMc+w5w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/react-hook-form"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17 || ^18 || ^19"
+ }
+ },
+ "node_modules/react-is": {
+ "version": "19.2.4",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.4.tgz",
+ "integrity": "sha512-W+EWGn2v0ApPKgKKCy/7s7WHXkboGcsrXE+2joLyVxkbyVQfO3MUEaUQDHoSmb8TFFrSKYa9mw64WZHNHSDzYA==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/react-redux": {
+ "version": "9.2.0",
+ "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz",
+ "integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@types/use-sync-external-store": "^0.0.6",
+ "use-sync-external-store": "^1.4.0"
+ },
+ "peerDependencies": {
+ "@types/react": "^18.2.25 || ^19",
+ "react": "^18.0 || ^19",
+ "redux": "^5.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "redux": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-refresh": {
+ "version": "0.18.0",
+ "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz",
+ "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-remove-scroll": {
+ "version": "2.7.2",
+ "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.2.tgz",
+ "integrity": "sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==",
+ "license": "MIT",
+ "dependencies": {
+ "react-remove-scroll-bar": "^2.3.7",
+ "react-style-singleton": "^2.2.3",
+ "tslib": "^2.1.0",
+ "use-callback-ref": "^1.3.3",
+ "use-sidecar": "^1.1.3"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-remove-scroll-bar": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz",
+ "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==",
+ "license": "MIT",
+ "dependencies": {
+ "react-style-singleton": "^2.2.2",
+ "tslib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-resizable-panels": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/react-resizable-panels/-/react-resizable-panels-3.0.6.tgz",
+ "integrity": "sha512-b3qKHQ3MLqOgSS+FRYKapNkJZf5EQzuf6+RLiq1/IlTHw99YrZ2NJZLk4hQIzTnnIkRg2LUqyVinu6YWWpUYew==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc",
+ "react-dom": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
+ }
+ },
+ "node_modules/react-style-singleton": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz",
+ "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==",
+ "license": "MIT",
+ "dependencies": {
+ "get-nonce": "^1.0.0",
+ "tslib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/recharts": {
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/recharts/-/recharts-3.7.0.tgz",
+ "integrity": "sha512-l2VCsy3XXeraxIID9fx23eCb6iCBsxUQDnE8tWm6DFdszVAO7WVY/ChAD9wVit01y6B2PMupYiMmQwhgPHc9Ew==",
+ "license": "MIT",
+ "peer": true,
+ "workspaces": [
+ "www"
+ ],
+ "dependencies": {
+ "@reduxjs/toolkit": "1.x.x || 2.x.x",
+ "clsx": "^2.1.1",
+ "decimal.js-light": "^2.5.1",
+ "es-toolkit": "^1.39.3",
+ "eventemitter3": "^5.0.1",
+ "immer": "^10.1.1",
+ "react-redux": "8.x.x || 9.x.x",
+ "reselect": "5.1.1",
+ "tiny-invariant": "^1.3.3",
+ "use-sync-external-store": "^1.2.2",
+ "victory-vendor": "^37.0.2"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
+ "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
+ "react-is": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
+ "node_modules/redux": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz",
+ "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/redux-thunk": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz",
+ "integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==",
+ "license": "MIT",
+ "peer": true,
+ "peerDependencies": {
+ "redux": "^5.0.0"
+ }
+ },
+ "node_modules/reflect-metadata": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz",
+ "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/reflect.getprototypeof": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
+ "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.9",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0",
+ "get-intrinsic": "^1.2.7",
+ "get-proto": "^1.0.1",
+ "which-builtin-type": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/regexp.prototype.flags": {
+ "version": "1.5.4",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz",
+ "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-errors": "^1.3.0",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "set-function-name": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/require-from-string": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/require-in-the-middle": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-8.0.1.tgz",
+ "integrity": "sha512-QT7FVMXfWOYFbeRBF6nu+I6tr2Tf3u0q8RIEjNob/heKY/nh7drD/k7eeMFmSQgnTtCzLDcCu/XEnpW2wk4xCQ==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.3.5",
+ "module-details-from-path": "^1.0.3"
+ },
+ "engines": {
+ "node": ">=9.3.0 || >=8.10.0 <9.0.0"
+ }
+ },
+ "node_modules/reselect": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz",
+ "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/resolve": {
+ "version": "2.0.0-next.5",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz",
+ "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-core-module": "^2.13.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/resolve-pkg-maps": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
+ "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
+ "devOptional": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
+ }
+ },
+ "node_modules/rimraf": {
+ "version": "5.0.10",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz",
+ "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==",
+ "license": "ISC",
+ "dependencies": {
+ "glob": "^10.3.7"
+ },
+ "bin": {
+ "rimraf": "dist/esm/bin.mjs"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/rolldown": {
+ "version": "1.0.0-beta.41",
+ "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-beta.41.tgz",
+ "integrity": "sha512-U+NPR0Bkg3wm61dteD2L4nAM1U9dtaqVrpDXwC36IKRHpEO/Ubpid4Nijpa2imPchcVNHfxVFwSSMJdwdGFUbg==",
+ "license": "MIT",
+ "dependencies": {
+ "@oxc-project/types": "=0.93.0",
+ "@rolldown/pluginutils": "1.0.0-beta.41",
+ "ansis": "=4.2.0"
+ },
+ "bin": {
+ "rolldown": "bin/cli.mjs"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "optionalDependencies": {
+ "@rolldown/binding-android-arm64": "1.0.0-beta.41",
+ "@rolldown/binding-darwin-arm64": "1.0.0-beta.41",
+ "@rolldown/binding-darwin-x64": "1.0.0-beta.41",
+ "@rolldown/binding-freebsd-x64": "1.0.0-beta.41",
+ "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-beta.41",
+ "@rolldown/binding-linux-arm64-gnu": "1.0.0-beta.41",
+ "@rolldown/binding-linux-arm64-musl": "1.0.0-beta.41",
+ "@rolldown/binding-linux-x64-gnu": "1.0.0-beta.41",
+ "@rolldown/binding-linux-x64-musl": "1.0.0-beta.41",
+ "@rolldown/binding-openharmony-arm64": "1.0.0-beta.41",
+ "@rolldown/binding-wasm32-wasi": "1.0.0-beta.41",
+ "@rolldown/binding-win32-arm64-msvc": "1.0.0-beta.41",
+ "@rolldown/binding-win32-ia32-msvc": "1.0.0-beta.41",
+ "@rolldown/binding-win32-x64-msvc": "1.0.0-beta.41"
+ }
+ },
+ "node_modules/rolldown/node_modules/@rolldown/pluginutils": {
+ "version": "1.0.0-beta.41",
+ "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.41.tgz",
+ "integrity": "sha512-ycMEPrS3StOIeb87BT3/+bu+blEtyvwQ4zmo2IcJQy0Rd1DAAhKksA0iUZ3MYSpJtjlPhg0Eo6mvVS6ggPhRbw==",
+ "license": "MIT"
+ },
+ "node_modules/safe-array-concat": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz",
+ "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.2",
+ "get-intrinsic": "^1.2.6",
+ "has-symbols": "^1.1.0",
+ "isarray": "^2.0.5"
+ },
+ "engines": {
+ "node": ">=0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/safe-push-apply": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz",
+ "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "isarray": "^2.0.5"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/safe-regex-test": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz",
+ "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "is-regex": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "license": "MIT"
+ },
+ "node_modules/scheduler": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
+ "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==",
+ "license": "MIT"
+ },
+ "node_modules/semver": {
+ "version": "7.7.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
+ "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/send": {
+ "version": "0.19.2",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz",
+ "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "destroy": "1.2.0",
+ "encodeurl": "~2.0.0",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "fresh": "~0.5.2",
+ "http-errors": "~2.0.1",
+ "mime": "1.6.0",
+ "ms": "2.1.3",
+ "on-finished": "~2.4.1",
+ "range-parser": "~1.2.1",
+ "statuses": "~2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/send/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/send/node_modules/debug/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "license": "MIT"
+ },
+ "node_modules/serve-static": {
+ "version": "1.16.3",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz",
+ "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==",
+ "license": "MIT",
+ "dependencies": {
+ "encodeurl": "~2.0.0",
+ "escape-html": "~1.0.3",
+ "parseurl": "~1.3.3",
+ "send": "~0.19.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/set-function-length": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
+ "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-data-property": "^1.1.4",
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.4",
+ "gopd": "^1.0.1",
+ "has-property-descriptors": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/set-function-name": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz",
+ "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-data-property": "^1.1.4",
+ "es-errors": "^1.3.0",
+ "functions-have-names": "^1.2.3",
+ "has-property-descriptors": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/set-proto": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz",
+ "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/setprototypeof": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
+ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
+ "license": "ISC"
+ },
+ "node_modules/sharp": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz",
+ "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@img/colour": "^1.0.0",
+ "detect-libc": "^2.1.2",
+ "semver": "^7.7.3"
+ },
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-darwin-arm64": "0.34.5",
+ "@img/sharp-darwin-x64": "0.34.5",
+ "@img/sharp-libvips-darwin-arm64": "1.2.4",
+ "@img/sharp-libvips-darwin-x64": "1.2.4",
+ "@img/sharp-libvips-linux-arm": "1.2.4",
+ "@img/sharp-libvips-linux-arm64": "1.2.4",
+ "@img/sharp-libvips-linux-ppc64": "1.2.4",
+ "@img/sharp-libvips-linux-riscv64": "1.2.4",
+ "@img/sharp-libvips-linux-s390x": "1.2.4",
+ "@img/sharp-libvips-linux-x64": "1.2.4",
+ "@img/sharp-libvips-linuxmusl-arm64": "1.2.4",
+ "@img/sharp-libvips-linuxmusl-x64": "1.2.4",
+ "@img/sharp-linux-arm": "0.34.5",
+ "@img/sharp-linux-arm64": "0.34.5",
+ "@img/sharp-linux-ppc64": "0.34.5",
+ "@img/sharp-linux-riscv64": "0.34.5",
+ "@img/sharp-linux-s390x": "0.34.5",
+ "@img/sharp-linux-x64": "0.34.5",
+ "@img/sharp-linuxmusl-arm64": "0.34.5",
+ "@img/sharp-linuxmusl-x64": "0.34.5",
+ "@img/sharp-wasm32": "0.34.5",
+ "@img/sharp-win32-arm64": "0.34.5",
+ "@img/sharp-win32-ia32": "0.34.5",
+ "@img/sharp-win32-x64": "0.34.5"
+ }
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "license": "MIT",
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/side-channel": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
+ "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "object-inspect": "^1.13.3",
+ "side-channel-list": "^1.0.0",
+ "side-channel-map": "^1.0.1",
+ "side-channel-weakmap": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-list": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
+ "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "object-inspect": "^1.13.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-map": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
+ "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.5",
+ "object-inspect": "^1.13.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-weakmap": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
+ "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.5",
+ "object-inspect": "^1.13.3",
+ "side-channel-map": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/siginfo": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz",
+ "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/signal-exit": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/sisteransi": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
+ "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==",
+ "license": "MIT"
+ },
+ "node_modules/size-sensor": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/size-sensor/-/size-sensor-1.0.3.tgz",
+ "integrity": "sha512-+k9mJ2/rQMiRmQUcjn+qznch260leIXY8r4FyYKKyRBO/s5UoeMAHGkCJyE1R/4wrIhTJONfyloY55SkE7ve3A==",
+ "license": "ISC"
+ },
+ "node_modules/sonner": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/sonner/-/sonner-2.0.7.tgz",
+ "integrity": "sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^18.0.0 || ^19.0.0 || ^19.0.0-rc",
+ "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-rc"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/split2": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
+ "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
+ "license": "ISC",
+ "engines": {
+ "node": ">= 10.x"
+ }
+ },
+ "node_modules/stackback": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz",
+ "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/statuses": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
+ "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/std-env": {
+ "version": "3.10.0",
+ "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz",
+ "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/stop-iteration-iterator": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz",
+ "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "internal-slot": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width-cjs": {
+ "name": "string-width",
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string.prototype.matchall": {
+ "version": "4.0.12",
+ "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz",
+ "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.6",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0",
+ "get-intrinsic": "^1.2.6",
+ "gopd": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "internal-slot": "^1.1.0",
+ "regexp.prototype.flags": "^1.5.3",
+ "set-function-name": "^2.0.2",
+ "side-channel": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.repeat": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz",
+ "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.17.5"
+ }
+ },
+ "node_modules/string.prototype.trim": {
+ "version": "1.2.10",
+ "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz",
+ "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.2",
+ "define-data-property": "^1.1.4",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.5",
+ "es-object-atoms": "^1.0.0",
+ "has-property-descriptors": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimend": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz",
+ "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.2",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimstart": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz",
+ "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi-cjs": {
+ "name": "strip-ansi",
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/superjson": {
+ "version": "2.2.6",
+ "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.6.tgz",
+ "integrity": "sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA==",
+ "license": "MIT",
+ "dependencies": {
+ "copy-anything": "^4"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/table-layout": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-4.1.1.tgz",
+ "integrity": "sha512-iK5/YhZxq5GO5z8wb0bY1317uDF3Zjpha0QFFLA8/trAoiLbQD0HUbMesEaxyzUgDxi2QlcbM8IvqOlEjgoXBA==",
+ "license": "MIT",
+ "dependencies": {
+ "array-back": "^6.2.2",
+ "wordwrapjs": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=12.17"
+ }
+ },
+ "node_modules/tailwind-merge": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.4.0.tgz",
+ "integrity": "sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/dcastil"
+ }
+ },
+ "node_modules/tailwindcss": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz",
+ "integrity": "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==",
+ "license": "MIT"
+ },
+ "node_modules/tailwindcss-animate": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz",
+ "integrity": "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "tailwindcss": ">=3.0.0 || insiders"
+ }
+ },
+ "node_modules/tapable": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz",
+ "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ }
+ },
+ "node_modules/tiny-invariant": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz",
+ "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/tinybench": {
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz",
+ "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/tinyexec": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz",
+ "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tinyglobby": {
+ "version": "0.2.15",
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
+ "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
+ "license": "MIT",
+ "dependencies": {
+ "fdir": "^6.5.0",
+ "picomatch": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/SuperchupuDev"
+ }
+ },
+ "node_modules/tinyrainbow": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.0.3.tgz",
+ "integrity": "sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/toidentifier": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
+ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "node_modules/tr46": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
+ "license": "MIT"
+ },
+ "node_modules/ts-api-utils": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz",
+ "integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.12"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
+ "license": "0BSD"
+ },
+ "node_modules/tsx": {
+ "version": "4.21.0",
+ "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz",
+ "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "esbuild": "~0.27.0",
+ "get-tsconfig": "^4.7.5"
+ },
+ "bin": {
+ "tsx": "dist/cli.mjs"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/aix-ppc64": {
+ "version": "0.27.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz",
+ "integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/android-arm": {
+ "version": "0.27.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.2.tgz",
+ "integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/android-arm64": {
+ "version": "0.27.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz",
+ "integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/android-x64": {
+ "version": "0.27.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz",
+ "integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/darwin-arm64": {
+ "version": "0.27.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz",
+ "integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/darwin-x64": {
+ "version": "0.27.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz",
+ "integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.27.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz",
+ "integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/freebsd-x64": {
+ "version": "0.27.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz",
+ "integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-arm": {
+ "version": "0.27.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz",
+ "integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-arm64": {
+ "version": "0.27.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz",
+ "integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-ia32": {
+ "version": "0.27.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz",
+ "integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-loong64": {
+ "version": "0.27.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz",
+ "integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==",
+ "cpu": [
+ "loong64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-mips64el": {
+ "version": "0.27.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz",
+ "integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==",
+ "cpu": [
+ "mips64el"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-ppc64": {
+ "version": "0.27.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz",
+ "integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-riscv64": {
+ "version": "0.27.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz",
+ "integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==",
+ "cpu": [
+ "riscv64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-s390x": {
+ "version": "0.27.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz",
+ "integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==",
+ "cpu": [
+ "s390x"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-x64": {
+ "version": "0.27.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz",
+ "integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/netbsd-arm64": {
+ "version": "0.27.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz",
+ "integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/netbsd-x64": {
+ "version": "0.27.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz",
+ "integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/openbsd-arm64": {
+ "version": "0.27.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz",
+ "integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/openbsd-x64": {
+ "version": "0.27.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz",
+ "integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/openharmony-arm64": {
+ "version": "0.27.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz",
+ "integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/sunos-x64": {
+ "version": "0.27.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz",
+ "integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/win32-arm64": {
+ "version": "0.27.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz",
+ "integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/win32-ia32": {
+ "version": "0.27.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz",
+ "integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/win32-x64": {
+ "version": "0.27.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz",
+ "integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/esbuild": {
+ "version": "0.27.2",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz",
+ "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==",
+ "devOptional": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.27.2",
+ "@esbuild/android-arm": "0.27.2",
+ "@esbuild/android-arm64": "0.27.2",
+ "@esbuild/android-x64": "0.27.2",
+ "@esbuild/darwin-arm64": "0.27.2",
+ "@esbuild/darwin-x64": "0.27.2",
+ "@esbuild/freebsd-arm64": "0.27.2",
+ "@esbuild/freebsd-x64": "0.27.2",
+ "@esbuild/linux-arm": "0.27.2",
+ "@esbuild/linux-arm64": "0.27.2",
+ "@esbuild/linux-ia32": "0.27.2",
+ "@esbuild/linux-loong64": "0.27.2",
+ "@esbuild/linux-mips64el": "0.27.2",
+ "@esbuild/linux-ppc64": "0.27.2",
+ "@esbuild/linux-riscv64": "0.27.2",
+ "@esbuild/linux-s390x": "0.27.2",
+ "@esbuild/linux-x64": "0.27.2",
+ "@esbuild/netbsd-arm64": "0.27.2",
+ "@esbuild/netbsd-x64": "0.27.2",
+ "@esbuild/openbsd-arm64": "0.27.2",
+ "@esbuild/openbsd-x64": "0.27.2",
+ "@esbuild/openharmony-arm64": "0.27.2",
+ "@esbuild/sunos-x64": "0.27.2",
+ "@esbuild/win32-arm64": "0.27.2",
+ "@esbuild/win32-ia32": "0.27.2",
+ "@esbuild/win32-x64": "0.27.2"
+ }
+ },
+ "node_modules/tsx/node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/tw-animate-css": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/tw-animate-css/-/tw-animate-css-1.4.0.tgz",
+ "integrity": "sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/Wombosvideo"
+ }
+ },
+ "node_modules/type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/type-is": {
+ "version": "1.6.18",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
+ "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
+ "license": "MIT",
+ "dependencies": {
+ "media-typer": "0.3.0",
+ "mime-types": "~2.1.24"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/typed-array-buffer": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz",
+ "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "es-errors": "^1.3.0",
+ "is-typed-array": "^1.1.14"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/typed-array-byte-length": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz",
+ "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "for-each": "^0.3.3",
+ "gopd": "^1.2.0",
+ "has-proto": "^1.2.0",
+ "is-typed-array": "^1.1.14"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typed-array-byte-offset": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz",
+ "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "available-typed-arrays": "^1.0.7",
+ "call-bind": "^1.0.8",
+ "for-each": "^0.3.3",
+ "gopd": "^1.2.0",
+ "has-proto": "^1.2.0",
+ "is-typed-array": "^1.1.15",
+ "reflect.getprototypeof": "^1.0.9"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typed-array-length": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz",
+ "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "for-each": "^0.3.3",
+ "gopd": "^1.0.1",
+ "is-typed-array": "^1.1.13",
+ "possible-typed-array-names": "^1.0.0",
+ "reflect.getprototypeof": "^1.0.6"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "5.9.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
+ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
+ "license": "Apache-2.0",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/typescript-eslint": {
+ "version": "8.54.0",
+ "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.54.0.tgz",
+ "integrity": "sha512-CKsJ+g53QpsNPqbzUsfKVgd3Lny4yKZ1pP4qN3jdMOg/sisIDLGyDMezycquXLE5JsEU0wp3dGNdzig0/fmSVQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/eslint-plugin": "8.54.0",
+ "@typescript-eslint/parser": "8.54.0",
+ "@typescript-eslint/typescript-estree": "8.54.0",
+ "@typescript-eslint/utils": "8.54.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/typical": {
+ "version": "7.3.0",
+ "resolved": "https://registry.npmjs.org/typical/-/typical-7.3.0.tgz",
+ "integrity": "sha512-ya4mg/30vm+DOWfBg4YK3j2WD6TWtRkCbasOJr40CseYENzCUby/7rIvXA99JGsQHeNxLbnXdyLLxKSv3tauFw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.17"
+ }
+ },
+ "node_modules/unbox-primitive": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz",
+ "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "has-bigints": "^1.0.2",
+ "has-symbols": "^1.1.0",
+ "which-boxed-primitive": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "7.16.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
+ "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
+ "license": "MIT"
+ },
+ "node_modules/unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/update-browserslist-db": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
+ "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "escalade": "^3.2.0",
+ "picocolors": "^1.1.1"
+ },
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/use-callback-ref": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz",
+ "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==",
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/use-sidecar": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz",
+ "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==",
+ "license": "MIT",
+ "dependencies": {
+ "detect-node-es": "^1.1.0",
+ "tslib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/use-sync-external-store": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz",
+ "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
+ "node_modules/utils-merge": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+ "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/uuid": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
+ "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
+ "funding": [
+ "https://github.com/sponsors/broofa",
+ "https://github.com/sponsors/ctavan"
+ ],
+ "license": "MIT",
+ "bin": {
+ "uuid": "dist/bin/uuid"
+ }
+ },
+ "node_modules/vary": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+ "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/vaul": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vaul/-/vaul-1.1.2.tgz",
+ "integrity": "sha512-ZFkClGpWyI2WUQjdLJ/BaGuV6AVQiJ3uELGk3OYtP+B6yCO7Cmn9vPFXVJkRaGkOJu3m8bQMgtyzNHixULceQA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-dialog": "^1.1.1"
+ },
+ "peerDependencies": {
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc"
+ }
+ },
+ "node_modules/victory-vendor": {
+ "version": "37.3.6",
+ "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-37.3.6.tgz",
+ "integrity": "sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ==",
+ "license": "MIT AND ISC",
+ "peer": true,
+ "dependencies": {
+ "@types/d3-array": "^3.0.3",
+ "@types/d3-ease": "^3.0.0",
+ "@types/d3-interpolate": "^3.0.1",
+ "@types/d3-scale": "^4.0.2",
+ "@types/d3-shape": "^3.1.0",
+ "@types/d3-time": "^3.0.0",
+ "@types/d3-timer": "^3.0.0",
+ "d3-array": "^3.1.6",
+ "d3-ease": "^3.0.1",
+ "d3-interpolate": "^3.0.1",
+ "d3-scale": "^4.0.2",
+ "d3-shape": "^3.1.0",
+ "d3-time": "^3.0.0",
+ "d3-timer": "^3.0.1"
+ }
+ },
+ "node_modules/vite": {
+ "name": "rolldown-vite",
+ "version": "7.1.14",
+ "resolved": "https://registry.npmjs.org/rolldown-vite/-/rolldown-vite-7.1.14.tgz",
+ "integrity": "sha512-eSiiRJmovt8qDJkGyZuLnbxAOAdie6NCmmd0NkTC0RJI9duiSBTfr8X2mBYJOUFzxQa2USaHmL99J9uMxkjCyw==",
+ "license": "MIT",
+ "dependencies": {
+ "@oxc-project/runtime": "0.92.0",
+ "fdir": "^6.5.0",
+ "lightningcss": "^1.30.1",
+ "picomatch": "^4.0.3",
+ "postcss": "^8.5.6",
+ "rolldown": "1.0.0-beta.41",
+ "tinyglobby": "^0.2.15"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "funding": {
+ "url": "https://github.com/vitejs/vite?sponsor=1"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ },
+ "peerDependencies": {
+ "@types/node": "^20.19.0 || >=22.12.0",
+ "esbuild": "^0.25.0",
+ "jiti": ">=1.21.0",
+ "less": "^4.0.0",
+ "sass": "^1.70.0",
+ "sass-embedded": "^1.70.0",
+ "stylus": ">=0.54.8",
+ "sugarss": "^5.0.0",
+ "terser": "^5.16.0",
+ "tsx": "^4.8.1",
+ "yaml": "^2.4.2"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "esbuild": {
+ "optional": true
+ },
+ "jiti": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "sass-embedded": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ },
+ "tsx": {
+ "optional": true
+ },
+ "yaml": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/vite/node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/vitest": {
+ "version": "4.0.18",
+ "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.18.tgz",
+ "integrity": "sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/expect": "4.0.18",
+ "@vitest/mocker": "4.0.18",
+ "@vitest/pretty-format": "4.0.18",
+ "@vitest/runner": "4.0.18",
+ "@vitest/snapshot": "4.0.18",
+ "@vitest/spy": "4.0.18",
+ "@vitest/utils": "4.0.18",
+ "es-module-lexer": "^1.7.0",
+ "expect-type": "^1.2.2",
+ "magic-string": "^0.30.21",
+ "obug": "^2.1.1",
+ "pathe": "^2.0.3",
+ "picomatch": "^4.0.3",
+ "std-env": "^3.10.0",
+ "tinybench": "^2.9.0",
+ "tinyexec": "^1.0.2",
+ "tinyglobby": "^0.2.15",
+ "tinyrainbow": "^3.0.3",
+ "vite": "^6.0.0 || ^7.0.0",
+ "why-is-node-running": "^2.3.0"
+ },
+ "bin": {
+ "vitest": "vitest.mjs"
+ },
+ "engines": {
+ "node": "^20.0.0 || ^22.0.0 || >=24.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ },
+ "peerDependencies": {
+ "@edge-runtime/vm": "*",
+ "@opentelemetry/api": "^1.9.0",
+ "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0",
+ "@vitest/browser-playwright": "4.0.18",
+ "@vitest/browser-preview": "4.0.18",
+ "@vitest/browser-webdriverio": "4.0.18",
+ "@vitest/ui": "4.0.18",
+ "happy-dom": "*",
+ "jsdom": "*"
+ },
+ "peerDependenciesMeta": {
+ "@edge-runtime/vm": {
+ "optional": true
+ },
+ "@opentelemetry/api": {
+ "optional": true
+ },
+ "@types/node": {
+ "optional": true
+ },
+ "@vitest/browser-playwright": {
+ "optional": true
+ },
+ "@vitest/browser-preview": {
+ "optional": true
+ },
+ "@vitest/browser-webdriverio": {
+ "optional": true
+ },
+ "@vitest/ui": {
+ "optional": true
+ },
+ "happy-dom": {
+ "optional": true
+ },
+ "jsdom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/web-streams-polyfill": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
+ "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/webidl-conversions": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/whatwg-url": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+ "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
+ "license": "MIT",
+ "dependencies": {
+ "tr46": "~0.0.3",
+ "webidl-conversions": "^3.0.0"
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/which-boxed-primitive": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz",
+ "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-bigint": "^1.1.0",
+ "is-boolean-object": "^1.2.1",
+ "is-number-object": "^1.1.1",
+ "is-string": "^1.1.1",
+ "is-symbol": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-builtin-type": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz",
+ "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "function.prototype.name": "^1.1.6",
+ "has-tostringtag": "^1.0.2",
+ "is-async-function": "^2.0.0",
+ "is-date-object": "^1.1.0",
+ "is-finalizationregistry": "^1.1.0",
+ "is-generator-function": "^1.0.10",
+ "is-regex": "^1.2.1",
+ "is-weakref": "^1.0.2",
+ "isarray": "^2.0.5",
+ "which-boxed-primitive": "^1.1.0",
+ "which-collection": "^1.0.2",
+ "which-typed-array": "^1.1.16"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-collection": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz",
+ "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-map": "^2.0.3",
+ "is-set": "^2.0.3",
+ "is-weakmap": "^2.0.2",
+ "is-weakset": "^2.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-typed-array": {
+ "version": "1.1.20",
+ "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.20.tgz",
+ "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "available-typed-arrays": "^1.0.7",
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "for-each": "^0.3.5",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/why-is-node-running": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz",
+ "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "siginfo": "^2.0.0",
+ "stackback": "0.0.2"
+ },
+ "bin": {
+ "why-is-node-running": "cli.js"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/word-wrap": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
+ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/wordwrapjs": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-5.1.1.tgz",
+ "integrity": "sha512-0yweIbkINJodk27gX9LBGMzyQdBDan3s/dEAiwBOj+Mf0PPyWL6/rikalkv8EeD0E8jm4o5RXEOrFTP3NXbhJg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.17"
+ }
+ },
+ "node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi-cjs": {
+ "name": "wrap-ansi",
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/ws": {
+ "version": "8.19.0",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz",
+ "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": ">=5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/xtend": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4"
+ }
+ },
+ "node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "license": "MIT",
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/zod": {
+ "version": "4.3.6",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz",
+ "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/colinhacks"
+ }
+ },
+ "node_modules/zod-to-ts": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/zod-to-ts/-/zod-to-ts-2.0.0.tgz",
+ "integrity": "sha512-aHsUgIl+CQutKAxtRNeZslLCLXoeuSq+j5HU7q3kvi/c2KIAo6q4YjT7/lwFfACxLB923ELHYMkHmlxiqFy4lw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "typescript": "^5.0.0",
+ "zod": "^3.25.0 || ^4.0.0"
+ }
+ },
+ "node_modules/zod-validation-error": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz",
+ "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "zod": "^3.25.0 || ^4.0.0"
+ }
+ },
+ "node_modules/zrender": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/zrender/-/zrender-6.0.0.tgz",
+ "integrity": "sha512-41dFXEEXuJpNecuUQq6JlbybmnHaqqpGlbH1yxnA5V9MMP4SbohSVZsJIwz+zdjQXSSlR1Vc34EgH1zxyTDvhg==",
+ "license": "BSD-3-Clause",
+ "peer": true,
+ "dependencies": {
+ "tslib": "2.3.0"
+ }
+ },
+ "node_modules/zrender/node_modules/tslib": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz",
+ "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==",
+ "license": "0BSD",
+ "peer": true
+ }
+ }
+}
diff --git a/apps/supportconsolek/supportconsolek/package.json b/apps/supportconsolek/supportconsolek/package.json
new file mode 100644
index 0000000..1309542
--- /dev/null
+++ b/apps/supportconsolek/supportconsolek/package.json
@@ -0,0 +1,85 @@
+{
+ "name": "supportconsolek",
+ "version": "1.0.0",
+ "main": "build/index.js",
+ "type": "module",
+ "scripts": {
+ "start": "NODE_ENV=production node --env-file-if-exists=./.env ./dist/server/server/server.js",
+ "dev": "NODE_ENV=development tsx watch --tsconfig ./tsconfig.server.json --env-file-if-exists=./.env ./server/server.ts",
+ "build:client": "vite build --config client/vite.config.ts",
+ "build:server": "tsc --target es2022 --module ESNext --moduleResolution Bundler --outDir dist/server --rootDir . --esModuleInterop --skipLibCheck --resolveJsonModule server/server.ts server/support-plugin.ts server/lib/lakebase.ts",
+ "build": "npm run build:server && npm run build:client",
+ "typecheck": "tsc -p ./tsconfig.server.json --noEmit && tsc -p ./tsconfig.client.json --noEmit",
+ "lint": "eslint .",
+ "lint:fix": "eslint . --fix",
+ "lint:ast-grep": "appkit lint",
+ "format": "prettier --check .",
+ "format:fix": "prettier --write .",
+ "test": "vitest run && npm run test:smoke",
+ "test:e2e": "playwright test",
+ "test:e2e:ui": "playwright test --ui",
+ "test:smoke": "playwright install chromium && playwright test tests/smoke.spec.ts",
+ "clean": "rm -rf client/dist dist build node_modules .smoke-test test-results playwright-report",
+ "postinstall": "npm run typegen",
+ "prebuild": "npm run typegen",
+ "predev": "npm run typegen",
+ "typegen": "appkit generate-types",
+ "setup": "appkit setup --write"
+ },
+ "keywords": [],
+ "author": "",
+ "license": "Unlicensed",
+ "description": "Support console",
+ "dependencies": {
+ "@databricks/appkit": "^0.11.2",
+ "@databricks/appkit-ui": "^0.11.2",
+ "@databricks/sdk-experimental": "^0.14.2",
+ "clsx": "^2.1.1",
+ "embla-carousel-react": "^8.6.0",
+ "lucide-react": "^0.546.0",
+ "next-themes": "^0.4.6",
+ "pg": "^8.18.0",
+ "react": "^19.1.1",
+ "react-dom": "^19.1.1",
+ "react-resizable-panels": "^3.0.6",
+ "sonner": "^2.0.7",
+ "superjson": "^2.2.5",
+ "tailwind-merge": "^3.3.1",
+ "tailwindcss-animate": "^1.0.7",
+ "tw-animate-css": "^1.4.0",
+ "zod": "^4.1.13"
+ },
+ "devDependencies": {
+ "@ast-grep/napi": "^0.37.0",
+ "@eslint/compat": "^2.0.0",
+ "@eslint/js": "^9.39.1",
+ "@playwright/test": "^1.57.0",
+ "@tailwindcss/postcss": "^4.1.17",
+ "@tailwindcss/vite": "^4.1.17",
+ "@types/express": "^5.0.5",
+ "@types/node": "^24.6.0",
+ "@types/pg": "^8.16.0",
+ "@types/react": "^19.1.16",
+ "@types/react-dom": "^19.1.9",
+ "@typescript-eslint/eslint-plugin": "^8.48.0",
+ "@typescript-eslint/parser": "^8.48.0",
+ "@vitejs/plugin-react": "^5.0.4",
+ "autoprefixer": "^10.4.21",
+ "eslint": "^9.39.1",
+ "eslint-config-prettier": "^10.1.8",
+ "eslint-plugin-react": "^7.37.5",
+ "eslint-plugin-react-hooks": "^7.0.1",
+ "eslint-plugin-react-refresh": "^0.4.24",
+ "prettier": "^3.6.2",
+ "sharp": "^0.34.5",
+ "tailwindcss": "^4.0.14",
+ "tsx": "^4.20.6",
+ "typescript": "~5.9.3",
+ "typescript-eslint": "^8.48.0",
+ "vite": "npm:rolldown-vite@7.1.14",
+ "vitest": "^4.0.14"
+ },
+ "overrides": {
+ "vite": "npm:rolldown-vite@7.1.14"
+ }
+}
diff --git a/apps/supportconsolek/supportconsolek/playwright.config.ts b/apps/supportconsolek/supportconsolek/playwright.config.ts
new file mode 100644
index 0000000..c4cad7a
--- /dev/null
+++ b/apps/supportconsolek/supportconsolek/playwright.config.ts
@@ -0,0 +1,26 @@
+import { defineConfig, devices } from '@playwright/test';
+
+export default defineConfig({
+ testDir: './tests',
+ fullyParallel: true,
+ forbidOnly: !!process.env.CI,
+ retries: process.env.CI ? 2 : 0,
+ workers: process.env.CI ? 1 : undefined,
+ reporter: 'html',
+ use: {
+ baseURL: `http://localhost:${process.env.PORT || 8000}`,
+ trace: 'on-first-retry',
+ },
+ projects: [
+ {
+ name: 'chromium',
+ use: { ...devices['Desktop Chrome'] },
+ },
+ ],
+ webServer: {
+ command: 'npm run dev',
+ url: `http://localhost:${process.env.PORT || 8000}`,
+ reuseExistingServer: !process.env.CI,
+ timeout: 120 * 1000,
+ },
+});
diff --git a/apps/supportconsolek/supportconsolek/server/lib/lakebase.ts b/apps/supportconsolek/supportconsolek/server/lib/lakebase.ts
new file mode 100644
index 0000000..e3112e5
--- /dev/null
+++ b/apps/supportconsolek/supportconsolek/server/lib/lakebase.ts
@@ -0,0 +1,63 @@
+import type pg from "pg";
+import { createLakebasePool as createAppKitLakebasePool } from "@databricks/appkit";
+import { WorkspaceClient } from "@databricks/sdk-experimental";
+
+interface LakebaseEndpointResponse {
+ status?: {
+ hosts?: {
+ host?: string;
+ };
+ };
+}
+
+async function resolveLakebaseHost(): Promise {
+ const configuredHost = process.env.PGHOST;
+ if (configuredHost && configuredHost.trim().length > 0) {
+ return configuredHost;
+ }
+
+ const endpoint = process.env.LAKEBASE_ENDPOINT;
+ if (!endpoint || endpoint.trim().length === 0) {
+ throw new Error("Set PGHOST or LAKEBASE_ENDPOINT for Lakebase connections");
+ }
+
+ const workspaceClient = new WorkspaceClient({
+ host: process.env.DATABRICKS_HOST,
+ ...(process.env.DATABRICKS_CONFIG_PROFILE && {
+ profile: process.env.DATABRICKS_CONFIG_PROFILE,
+ }),
+ });
+
+ const response = (await workspaceClient.apiClient.request({
+ method: "GET",
+ path: `/api/2.0/postgres/${endpoint}`,
+ headers: new Headers({
+ Accept: "application/json",
+ }),
+ raw: false,
+ })) as LakebaseEndpointResponse;
+
+ const resolvedHost = response?.status?.hosts?.host;
+ if (!resolvedHost) {
+ throw new Error(`Could not resolve Lakebase host from endpoint ${endpoint}`);
+ }
+ return resolvedHost;
+}
+
+export async function createLakebasePool(): Promise {
+ const sslModeEnv = process.env.PGSSLMODE;
+ const sslMode =
+ sslModeEnv === "disable" || sslModeEnv === "prefer" || sslModeEnv === "require"
+ ? sslModeEnv
+ : "require";
+ const strictSslVerify = process.env.PGSSL_STRICT_VERIFY === "true";
+ const host = await resolveLakebaseHost();
+
+ return createAppKitLakebasePool({
+ host,
+ sslMode,
+ // Some Lakebase endpoint hosts include region segments not present in cert SANs.
+ // Keep TLS on by default but allow hostname verification opt-in via PGSSL_STRICT_VERIFY=true.
+ ssl: sslMode === "require" ? { rejectUnauthorized: strictSslVerify } : undefined,
+ });
+}
diff --git a/apps/supportconsolek/supportconsolek/server/server.ts b/apps/supportconsolek/supportconsolek/server/server.ts
new file mode 100644
index 0000000..eac8114
--- /dev/null
+++ b/apps/supportconsolek/supportconsolek/server/server.ts
@@ -0,0 +1,11 @@
+import { createApp, lakebase, server, toPlugin } from "@databricks/appkit";
+import { SupportPlugin } from "./support-plugin.js";
+
+const support = toPlugin, "support">(
+ SupportPlugin,
+ "support",
+);
+
+createApp({
+ plugins: [lakebase(), support(), server()],
+}).catch(console.error);
diff --git a/apps/supportconsolek/supportconsolek/server/support-plugin.ts b/apps/supportconsolek/supportconsolek/server/support-plugin.ts
new file mode 100644
index 0000000..53e100e
--- /dev/null
+++ b/apps/supportconsolek/supportconsolek/server/support-plugin.ts
@@ -0,0 +1,1085 @@
+import { Plugin } from "@databricks/appkit";
+import type { IAppRouter } from "@databricks/appkit";
+import { WorkspaceClient } from "@databricks/sdk-experimental";
+import type { Pool } from "pg";
+import { createLakebasePool } from "./lib/lakebase.js";
+
+type Json = Record;
+
+interface ActionBody {
+ support_request_id: string;
+ order_id: string;
+ user_id?: string | null;
+ action_type: "apply_refund" | "apply_credit";
+ amount_usd: number;
+ actor?: string | null;
+ payload?: Json;
+}
+
+interface ReplyBody {
+ support_request_id: string;
+ order_id: string;
+ user_id?: string | null;
+ message_text: string;
+ sent_by?: string | null;
+}
+
+interface RegenerateBody {
+ support_request_id: string;
+ user_id?: string | null;
+ order_id: string;
+ operator_context?: string | null;
+ actor?: string | null;
+ current_report?: Record | null;
+}
+
+interface RatingBody {
+ support_request_id: string;
+ order_id: string;
+ user_id?: string | null;
+ rating: "thumbs_up" | "thumbs_down";
+ reason_code?: string | null;
+ feedback_notes?: string | null;
+ actor?: string | null;
+}
+
+type CaseStatus = "pending" | "in_progress" | "done" | "blocked";
+
+const DEFAULT_REPORT = {
+ credit_recommendation: null,
+ refund_recommendation: null,
+ draft_response: "",
+ past_interactions_summary: "",
+ order_details_summary: "",
+ decision_confidence: "medium",
+ escalation_flag: false,
+};
+
+const FIRST_NAMES = [
+ "Alex",
+ "Sam",
+ "Jordan",
+ "Taylor",
+ "Morgan",
+ "Casey",
+ "Riley",
+ "Avery",
+ "Cameron",
+ "Quinn",
+];
+
+const LAST_NAMES = [
+ "Parker",
+ "Hayes",
+ "Brooks",
+ "Reed",
+ "Foster",
+ "Bailey",
+ "Carter",
+ "Gray",
+ "Miller",
+ "Price",
+];
+
+function fakeDisplayName(userId: string | null | undefined): string | null {
+ if (!userId) return null;
+ let hash = 0;
+ for (let i = 0; i < userId.length; i += 1) {
+ hash = (hash * 31 + userId.charCodeAt(i)) >>> 0;
+ }
+ const first = FIRST_NAMES[hash % FIRST_NAMES.length];
+ const last = LAST_NAMES[Math.floor(hash / FIRST_NAMES.length) % LAST_NAMES.length];
+ return `${first} ${last}`;
+}
+
+function parseAgentReport(value: unknown): Record {
+ try {
+ if (typeof value === "string") {
+ const parsed = JSON.parse(value) as Record;
+ return { ...DEFAULT_REPORT, ...parsed };
+ }
+ if (value && typeof value === "object") {
+ return { ...DEFAULT_REPORT, ...(value as Record) };
+ }
+ } catch {
+ // fall through to default report
+ }
+ return { ...DEFAULT_REPORT };
+}
+
+function sanitizeDraftResponse(
+ draft: unknown,
+ userId: string | null | undefined,
+): string {
+ const base = typeof draft === "string" ? draft : "";
+ const displayName = fakeDisplayName(userId) ?? "there";
+
+ // Remove internal identifiers from customer-facing draft text.
+ return base
+ .replace(/\buser-\d+\b/gi, displayName)
+ .replace(/\b[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\b/gi, "your order")
+ .replace(/\b[0-9a-f]{32}\b/gi, "your order")
+ .replace(/\border\s+[0-9a-f]{8,}\b/gi, "order")
+ .replace(/\s{2,}/g, " ")
+ .trim();
+}
+
+function toNullableNumber(value: unknown): number | null {
+ if (typeof value === "number" && Number.isFinite(value)) {
+ return value;
+ }
+ if (typeof value === "string") {
+ const parsed = Number(value);
+ if (Number.isFinite(parsed)) {
+ return parsed;
+ }
+ }
+ return null;
+}
+
+function normalizeRecommendation(value: unknown): Record | null {
+ if (!value || typeof value !== "object") {
+ return null;
+ }
+
+ const raw = value as Record;
+ const amount =
+ toNullableNumber(raw.amount_usd) ??
+ toNullableNumber(raw.amount) ??
+ toNullableNumber(raw.credit_amount) ??
+ toNullableNumber(raw.refund_amount);
+
+ const reasonCandidates = [
+ raw.reason,
+ raw.credit_reason,
+ raw.refund_reason,
+ ];
+ const reason = reasonCandidates.find((r) => typeof r === "string" && r.trim().length > 0) as
+ | string
+ | undefined;
+
+ // Keep original fields for traceability, but expose normalized UI fields.
+ return {
+ ...raw,
+ amount_usd: amount,
+ reason: reason ?? raw.reason ?? "",
+ };
+}
+
+function normalizeReportForUi(
+ rawReport: Record,
+ userId: string | null | undefined,
+): Record {
+ return {
+ ...rawReport,
+ credit_recommendation: normalizeRecommendation(rawReport.credit_recommendation),
+ refund_recommendation: normalizeRecommendation(rawReport.refund_recommendation),
+ draft_response: sanitizeDraftResponse(rawReport.draft_response, userId),
+ };
+}
+
+function extractResponseText(response: unknown): string {
+ if (!response || typeof response !== "object") {
+ throw new Error("Invalid serving response");
+ }
+ const output = (response as { output?: unknown }).output;
+ if (!Array.isArray(output)) {
+ throw new Error("Serving response missing output");
+ }
+ for (const message of output) {
+ if (!message || typeof message !== "object") continue;
+ const content = (message as { content?: unknown }).content;
+ if (!Array.isArray(content)) continue;
+ for (const item of content) {
+ if (!item || typeof item !== "object") continue;
+ const text = (item as { text?: unknown }).text;
+ if (typeof text === "string" && text.trim().length > 0) {
+ return text;
+ }
+ }
+ }
+ throw new Error("Serving response text not found");
+}
+
+function extractErrorMessage(error: unknown): string {
+ if (error instanceof Error) return error.message;
+ return String(error ?? "unknown_error");
+}
+
+function isServingPermissionError(error: unknown): boolean {
+ const message = extractErrorMessage(error).toLowerCase();
+ return (
+ message.includes("do not have permission")
+ || message.includes("permission denied")
+ || message.includes("not authorized")
+ || message.includes("unauthorized")
+ );
+}
+
+function isPermissionDeniedError(error: unknown): boolean {
+ const message = extractErrorMessage(error).toLowerCase();
+ return message.includes("permission denied") || message.includes("must be owner");
+}
+
+async function fetchSupportRequestText(pool: Pool, supportRequestId: string): Promise {
+ const tableCandidates = [
+ "support.support_agent_reports_sync",
+ "support.raw_support_requests_sync",
+ "support.raw_support_requests",
+ ];
+
+ for (const tableName of tableCandidates) {
+ try {
+ const result = await pool.query(
+ `SELECT request_text
+ FROM ${tableName}
+ WHERE support_request_id = $1
+ ORDER BY ts DESC
+ LIMIT 1`,
+ [supportRequestId],
+ );
+ const value = result.rows[0]?.request_text;
+ if (typeof value === "string" && value.trim().length > 0) {
+ return value;
+ }
+ } catch (error) {
+ const message = extractErrorMessage(error).toLowerCase();
+ if (
+ message.includes("does not exist")
+ || message.includes("undefined table")
+ || message.includes("undefined column")
+ || message.includes("permission denied")
+ ) {
+ continue;
+ }
+ throw error;
+ }
+ }
+
+ return null;
+}
+
+function createRegenerationPrompt(params: {
+ supportRequestId: string;
+ userId: string | null | undefined;
+ orderId: string;
+ operatorContext: string | null | undefined;
+ currentReport: Record | null | undefined;
+}): string {
+ const {
+ supportRequestId,
+ userId,
+ orderId,
+ operatorContext,
+ currentReport,
+ } = params;
+
+ const baseContext = {
+ support_request_id: supportRequestId,
+ user_id: userId ?? "",
+ order_id: orderId,
+ previous_report: currentReport ?? {},
+ operator_context: operatorContext ?? "",
+ };
+
+ return [
+ "You are the Caspers support triage agent.",
+ "Re-evaluate this support case using the previous report and operator context.",
+ "Return strictly valid JSON only with keys:",
+ "support_request_id, user_id, order_id, credit_recommendation, refund_recommendation, draft_response, past_interactions_summary, order_details_summary, decision_confidence, escalation_flag.",
+ "Recommendation objects must use keys {\"amount_usd\": number, \"reason\": string} or null.",
+ `Case payload: ${JSON.stringify(baseContext)}`,
+ ].join("\n");
+}
+
+function createFallbackRegeneratedReport(params: {
+ currentReport: Record | null | undefined;
+ operatorContext: string | null | undefined;
+ supportRequestId: string;
+ userId: string | null | undefined;
+ orderId: string;
+}): Record {
+ const report = parseAgentReport(params.currentReport ?? {});
+ const operatorContext = (params.operatorContext ?? "").trim();
+ const existingDraft = typeof report.draft_response === "string" ? report.draft_response.trim() : "";
+
+ if (operatorContext.length > 0) {
+ const contextLine = `Operator context: ${operatorContext}`;
+ report.draft_response = existingDraft.length > 0
+ ? `${existingDraft}\n\n${contextLine}`
+ : contextLine;
+ } else if (!existingDraft) {
+ report.draft_response = "Thanks for contacting us. We reviewed your case and prepared a concrete resolution proposal below.";
+ }
+
+ report.support_request_id = params.supportRequestId;
+ report.user_id = params.userId ?? "";
+ report.order_id = params.orderId;
+ report.regeneration_mode = "fallback_permission_denied";
+
+ return normalizeReportForUi(report, params.userId);
+}
+
+function deriveCaseStatus(params: {
+ status: unknown;
+ hasRefund: unknown;
+ hasCredit: unknown;
+ actionCount: unknown;
+ replyCount: unknown;
+ regenCount: unknown;
+}): CaseStatus {
+ const status = typeof params.status === "string" ? params.status : null;
+ if (status === "blocked") return "blocked";
+ if (params.hasRefund === true || params.hasCredit === true || status === "done") return "done";
+
+ const activityCount =
+ Number(params.actionCount ?? 0) +
+ Number(params.replyCount ?? 0) +
+ Number(params.regenCount ?? 0);
+ return activityCount > 0 || status === "in_progress" ? "in_progress" : "pending";
+}
+
+function deriveNextAction(params: {
+ caseStatus: CaseStatus;
+ hasReply: boolean;
+ hasRefund: boolean;
+ hasCredit: boolean;
+}): string {
+ if (params.caseStatus === "pending") return "review_report";
+ if (params.caseStatus === "blocked") return "investigate_blocker";
+ if (params.caseStatus === "done") {
+ return params.hasReply ? "monitor" : "send_customer_reply";
+ }
+ if (params.hasReply && !params.hasRefund && !params.hasCredit) return "apply_resolution_or_regenerate";
+ if (!params.hasReply && (params.hasRefund || params.hasCredit)) return "send_customer_reply";
+ return "continue_investigation";
+}
+
+export class SupportPlugin extends Plugin {
+ public name = "support";
+ protected envVars: string[] = [];
+ private pool: Pool | null = null;
+ private setupError: string | null = null;
+ private workspaceClient: WorkspaceClient | null = null;
+ private supportAgentEndpoint = process.env.SUPPORT_AGENT_ENDPOINT_NAME ?? "caspers_support_agent";
+
+ static manifest = {
+ name: "support",
+ displayName: "Support Plugin",
+ description: "Support request APIs backed by Lakebase",
+ resources: {
+ required: [],
+ optional: [],
+ },
+ };
+
+ async setup(): Promise {
+ try {
+ this.pool = await createLakebasePool();
+ const identity = await this.pool.query<{ current_user: string }>(
+ "SELECT current_user",
+ );
+ console.log(
+ "[support] lakebase current_user:",
+ identity.rows[0]?.current_user ?? "unknown",
+ );
+ const executeSetupDdl = async (sql: string): Promise => {
+ try {
+ await this.pool?.query(sql);
+ } catch (error) {
+ const message = extractErrorMessage(error).toLowerCase();
+ if (
+ message.includes("must be owner of table")
+ || message.includes("permission denied")
+ ) {
+ console.warn("[support] skipping startup DDL:", extractErrorMessage(error));
+ return;
+ }
+ throw error;
+ }
+ };
+ this.workspaceClient = new WorkspaceClient({
+ host: process.env.DATABRICKS_HOST,
+ ...(process.env.DATABRICKS_CONFIG_PROFILE && {
+ profile: process.env.DATABRICKS_CONFIG_PROFILE,
+ }),
+ });
+ await executeSetupDdl(
+ `CREATE TABLE IF NOT EXISTS support.operator_regenerated_reports (
+ regenerated_report_id BIGSERIAL PRIMARY KEY,
+ support_request_id TEXT NOT NULL,
+ user_id TEXT,
+ order_id TEXT NOT NULL,
+ operator_context TEXT,
+ agent_response JSONB NOT NULL,
+ actor TEXT,
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
+ )`,
+ );
+ await executeSetupDdl(
+ `CREATE TABLE IF NOT EXISTS support.request_status (
+ support_request_id TEXT PRIMARY KEY,
+ status TEXT NOT NULL DEFAULT 'pending',
+ assigned_to TEXT,
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
+ last_action TEXT,
+ notes TEXT
+ )`,
+ );
+ await executeSetupDdl(
+ `CREATE TABLE IF NOT EXISTS support.response_ratings (
+ rating_id BIGSERIAL PRIMARY KEY,
+ support_request_id TEXT NOT NULL,
+ order_id TEXT NOT NULL,
+ user_id TEXT,
+ rating TEXT NOT NULL CHECK (rating IN ('thumbs_up', 'thumbs_down')),
+ reason_code TEXT,
+ feedback_notes TEXT,
+ actor TEXT,
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
+ UNIQUE (support_request_id)
+ )`,
+ );
+ await executeSetupDdl(
+ `CREATE UNIQUE INDEX IF NOT EXISTS response_ratings_support_request_id_uq
+ ON support.response_ratings (support_request_id)`,
+ );
+ } catch (error) {
+ this.setupError = error instanceof Error ? error.message : String(error);
+ console.error("[support] setup failed:", this.setupError);
+ }
+ }
+
+ injectRoutes(router: IAppRouter): void {
+ const withJsonError = (
+ handler: (req: any, res: any) => Promise,
+ ) => async (req: any, res: any) => {
+ try {
+ await handler(req, res);
+ } catch (error) {
+ const message = error instanceof Error ? error.message : String(error);
+ console.error("[support] route error:", message);
+ if (!res.headersSent) {
+ res.status(500).json({ error: "internal_error", message });
+ }
+ }
+ };
+
+ router.get("/healthz", withJsonError(async (_req, res) => {
+ if (!this.pool) {
+ res
+ .status(503)
+ .json({ ok: false, error: "DB not ready", message: this.setupError });
+ return;
+ }
+ await this.pool.query("SELECT 1");
+ res.json({ ok: true });
+ }));
+
+ router.get("/summary", withJsonError(async (_req, res) => {
+ if (!this.pool) {
+ res
+ .status(503)
+ .json({ error: "DB not ready", message: this.setupError });
+ return;
+ }
+ const [requests, actions, replies] = await Promise.all([
+ this.pool.query(
+ `WITH combined AS (
+ SELECT support_request_id, ts AS event_ts
+ FROM support.support_agent_reports_sync
+ UNION ALL
+ SELECT support_request_id, created_at AS event_ts
+ FROM support.operator_regenerated_reports
+ ),
+ latest AS (
+ SELECT DISTINCT ON (support_request_id) support_request_id, event_ts
+ FROM combined
+ ORDER BY support_request_id, event_ts DESC
+ )
+ SELECT COUNT(*)::int AS c FROM latest`,
+ ),
+ this.pool.query("SELECT COUNT(*)::int AS c FROM support.operator_actions"),
+ this.pool.query("SELECT COUNT(*)::int AS c FROM support.support_replies"),
+ ]);
+ res.json({
+ requests: requests.rows[0]?.c ?? 0,
+ actions: actions.rows[0]?.c ?? 0,
+ replies: replies.rows[0]?.c ?? 0,
+ });
+ }));
+
+ router.get("/requests", withJsonError(async (req, res) => {
+ if (!this.pool) {
+ res
+ .status(503)
+ .json({ error: "DB not ready", message: this.setupError });
+ return;
+ }
+ const limit = Number(req.query.limit ?? 50);
+ const offset = Number(req.query.offset ?? 0);
+
+ const rows = await this.pool.query(
+ `WITH combined AS (
+ SELECT support_request_id, user_id, order_id, ts, agent_response::jsonb AS agent_response, ts AS event_ts, 'sync'::text AS report_source
+ FROM support.support_agent_reports_sync
+ UNION ALL
+ SELECT support_request_id, user_id, order_id, created_at AS ts, agent_response, created_at AS event_ts, 'regenerated'::text AS report_source
+ FROM support.operator_regenerated_reports
+ ),
+ latest AS (
+ SELECT DISTINCT ON (support_request_id)
+ support_request_id, user_id, order_id, ts, agent_response, event_ts, report_source
+ FROM combined
+ ORDER BY support_request_id, event_ts DESC
+ ),
+ action_agg AS (
+ SELECT
+ support_request_id,
+ COUNT(*)::int AS action_count,
+ COALESCE(BOOL_OR(action_type = 'apply_refund'), false) AS has_refund,
+ COALESCE(BOOL_OR(action_type = 'apply_credit'), false) AS has_credit,
+ COALESCE(BOOL_OR(action_type = 'send_reply'), false) AS has_reply_action,
+ MAX(created_at) AS last_action_at,
+ (ARRAY_AGG(action_type ORDER BY created_at DESC))[1] AS last_action_type
+ FROM support.operator_actions
+ GROUP BY support_request_id
+ ),
+ reply_agg AS (
+ SELECT
+ support_request_id,
+ COUNT(*)::int AS reply_count,
+ MAX(created_at) AS last_reply_at
+ FROM support.support_replies
+ GROUP BY support_request_id
+ ),
+ regen_agg AS (
+ SELECT
+ support_request_id,
+ COUNT(*)::int AS regen_count,
+ MAX(created_at) AS last_regen_at
+ FROM support.operator_regenerated_reports
+ GROUP BY support_request_id
+ )
+ SELECT
+ latest.support_request_id,
+ latest.user_id,
+ latest.order_id,
+ latest.ts,
+ latest.agent_response,
+ latest.report_source,
+ COALESCE(action_agg.action_count, 0) AS action_count,
+ COALESCE(reply_agg.reply_count, 0) AS reply_count,
+ COALESCE(regen_agg.regen_count, 0) AS regen_count,
+ COALESCE(action_agg.has_refund, false) AS has_refund,
+ COALESCE(action_agg.has_credit, false) AS has_credit,
+ (COALESCE(reply_agg.reply_count, 0) > 0 OR COALESCE(action_agg.has_reply_action, false)) AS has_reply,
+ action_agg.last_action_type,
+ rs.status,
+ rs.last_action,
+ (
+ SELECT MAX(event_time) FROM (
+ VALUES
+ (latest.ts),
+ (action_agg.last_action_at),
+ (reply_agg.last_reply_at),
+ (regen_agg.last_regen_at),
+ (rs.updated_at)
+ ) AS events(event_time)
+ ) AS last_event_at
+ FROM latest
+ LEFT JOIN action_agg ON action_agg.support_request_id = latest.support_request_id
+ LEFT JOIN reply_agg ON reply_agg.support_request_id = latest.support_request_id
+ LEFT JOIN regen_agg ON regen_agg.support_request_id = latest.support_request_id
+ LEFT JOIN support.request_status rs ON rs.support_request_id = latest.support_request_id
+ ORDER BY latest.ts DESC
+ LIMIT $1 OFFSET $2`,
+ [limit, offset],
+ );
+ const total = await this.pool.query(
+ `WITH combined AS (
+ SELECT support_request_id, ts AS event_ts
+ FROM support.support_agent_reports_sync
+ UNION ALL
+ SELECT support_request_id, created_at AS event_ts
+ FROM support.operator_regenerated_reports
+ ),
+ latest AS (
+ SELECT DISTINCT ON (support_request_id) support_request_id, event_ts
+ FROM combined
+ ORDER BY support_request_id, event_ts DESC
+ )
+ SELECT COUNT(*)::int AS c FROM latest`,
+ );
+
+ res.json({
+ items: rows.rows.map((r) => {
+ const caseStatus = deriveCaseStatus({
+ status: r.status,
+ hasRefund: r.has_refund,
+ hasCredit: r.has_credit,
+ actionCount: r.action_count,
+ replyCount: r.reply_count,
+ regenCount: r.regen_count,
+ });
+ const hasReply = r.has_reply === true;
+ const hasRefund = r.has_refund === true;
+ const hasCredit = r.has_credit === true;
+
+ return {
+ support_request_id: r.support_request_id,
+ user_id: r.user_id,
+ user_display_name: fakeDisplayName(r.user_id),
+ order_id: r.order_id,
+ ts: r.ts,
+ report: normalizeReportForUi(parseAgentReport(r.agent_response), r.user_id),
+ case_state: {
+ case_status: caseStatus,
+ next_action: deriveNextAction({
+ caseStatus,
+ hasReply,
+ hasRefund,
+ hasCredit,
+ }),
+ has_reply: hasReply,
+ has_refund: hasRefund,
+ has_credit: hasCredit,
+ action_count: Number(r.action_count ?? 0),
+ reply_count: Number(r.reply_count ?? 0),
+ regen_count: Number(r.regen_count ?? 0),
+ last_action_type: r.last_action_type ?? r.last_action ?? null,
+ last_event_at: r.last_event_at ?? r.ts,
+ latest_report_source: r.report_source ?? "sync",
+ },
+ };
+ }),
+ total: total.rows[0]?.c ?? 0,
+ limit,
+ offset,
+ });
+ }));
+
+ router.get("/requests/:id", withJsonError(async (req, res) => {
+ if (!this.pool) {
+ res
+ .status(503)
+ .json({ error: "DB not ready", message: this.setupError });
+ return;
+ }
+ const sid = req.params.id;
+ const request = await this.pool.query(
+ `WITH combined AS (
+ SELECT support_request_id, user_id, order_id, ts, agent_response::jsonb AS agent_response, ts AS event_ts, 'sync'::text AS report_source
+ FROM support.support_agent_reports_sync
+ WHERE support_request_id = $1
+ UNION ALL
+ SELECT support_request_id, user_id, order_id, created_at AS ts, agent_response, created_at AS event_ts, 'regenerated'::text AS report_source
+ FROM support.operator_regenerated_reports
+ WHERE support_request_id = $1
+ )
+ SELECT support_request_id, user_id, order_id, ts, agent_response, report_source
+ FROM combined
+ ORDER BY event_ts DESC
+ LIMIT 1`,
+ [sid],
+ );
+ if (request.rows.length === 0) {
+ res.status(404).json({ error: "Not found" });
+ return;
+ }
+
+ let ratingsRows: Array> = [];
+ try {
+ const ratingsResult = await this.pool.query(
+ `SELECT rating_id, rating, reason_code, feedback_notes, actor, created_at
+ FROM support.response_ratings
+ WHERE support_request_id = $1
+ ORDER BY created_at DESC`,
+ [sid],
+ );
+ ratingsRows = ratingsResult.rows;
+ } catch (error) {
+ if (isPermissionDeniedError(error)) {
+ console.warn("[support] ratings unavailable for this principal:", extractErrorMessage(error));
+ } else {
+ throw error;
+ }
+ }
+
+ const [actions, replies, regenerations, statusRow] = await Promise.all([
+ this.pool.query(
+ `SELECT action_id, action_type, amount_usd, payload, status, actor, created_at
+ FROM support.operator_actions
+ WHERE support_request_id = $1
+ ORDER BY created_at DESC`,
+ [sid],
+ ),
+ this.pool.query(
+ `SELECT reply_id, message_text, sent_by, created_at
+ FROM support.support_replies
+ WHERE support_request_id = $1
+ ORDER BY created_at DESC`,
+ [sid],
+ ),
+ this.pool.query(
+ `SELECT regenerated_report_id, operator_context, actor, created_at, agent_response
+ FROM support.operator_regenerated_reports
+ WHERE support_request_id = $1
+ ORDER BY created_at DESC`,
+ [sid],
+ ),
+ this.pool.query(
+ `SELECT status, last_action, updated_at
+ FROM support.request_status
+ WHERE support_request_id = $1
+ LIMIT 1`,
+ [sid],
+ ),
+ ]);
+
+ const row = request.rows[0];
+ const requestText = await fetchSupportRequestText(this.pool, sid);
+ const hasRefund = actions.rows.some((a) => a.action_type === "apply_refund");
+ const hasCredit = actions.rows.some((a) => a.action_type === "apply_credit");
+ const hasReply = replies.rows.length > 0 || actions.rows.some((a) => a.action_type === "send_reply");
+ const status = statusRow.rows[0]?.status;
+ const caseStatus = deriveCaseStatus({
+ status,
+ hasRefund,
+ hasCredit,
+ actionCount: actions.rows.length,
+ replyCount: replies.rows.length,
+ regenCount: regenerations.rows.length,
+ });
+
+ const timeline = [
+ { event_type: "report_generated", event_at: row.ts, actor: null, details: { source: row.report_source } },
+ ...regenerations.rows.map((rr) => ({
+ event_type: "report_regenerated",
+ event_at: rr.created_at,
+ actor: rr.actor ?? null,
+ details: { operator_context: rr.operator_context ?? null },
+ })),
+ ...replies.rows.map((rp) => ({
+ event_type: "reply_sent",
+ event_at: rp.created_at,
+ actor: rp.sent_by ?? null,
+ details: { message_text: rp.message_text ?? "" },
+ })),
+ ...actions.rows.map((ac) => ({
+ event_type: ac.action_type,
+ event_at: ac.created_at,
+ actor: ac.actor ?? null,
+ details: {
+ amount_usd: ac.amount_usd ?? null,
+ status: ac.status ?? null,
+ },
+ })),
+ ...ratingsRows.map((rt) => ({
+ event_type: "response_rated",
+ event_at: rt.created_at as string,
+ actor: (rt.actor as string | null) ?? null,
+ details: {
+ rating: rt.rating as string,
+ reason_code: (rt.reason_code as string | null) ?? null,
+ },
+ })),
+ ].sort(
+ (a, b) =>
+ new Date(String(b.event_at)).getTime() - new Date(String(a.event_at)).getTime(),
+ );
+
+ res.json({
+ support_request_id: row.support_request_id,
+ user_id: row.user_id,
+ user_display_name: fakeDisplayName(row.user_id),
+ order_id: row.order_id,
+ ts: row.ts,
+ request_text: requestText,
+ report: normalizeReportForUi(parseAgentReport(row.agent_response), row.user_id),
+ actions: actions.rows,
+ replies: replies.rows,
+ ratings: ratingsRows,
+ latest_rating: ratingsRows[0] ?? null,
+ regenerations: regenerations.rows.map((rr) => ({
+ regenerated_report_id: rr.regenerated_report_id,
+ operator_context: rr.operator_context,
+ actor: rr.actor,
+ created_at: rr.created_at,
+ report: normalizeReportForUi(parseAgentReport(rr.agent_response), row.user_id),
+ })),
+ case_state: {
+ case_status: caseStatus,
+ next_action: deriveNextAction({
+ caseStatus,
+ hasReply,
+ hasRefund,
+ hasCredit,
+ }),
+ has_reply: hasReply,
+ has_refund: hasRefund,
+ has_credit: hasCredit,
+ action_count: actions.rows.length,
+ reply_count: replies.rows.length,
+ regen_count: regenerations.rows.length,
+ last_action_type: statusRow.rows[0]?.last_action ?? actions.rows[0]?.action_type ?? null,
+ last_event_at:
+ timeline[0]?.event_at ??
+ statusRow.rows[0]?.updated_at ??
+ row.ts,
+ latest_report_source: row.report_source ?? "sync",
+ },
+ timeline,
+ });
+ }));
+
+ router.post("/actions", withJsonError(async (req, res) => {
+ if (!this.pool) {
+ res
+ .status(503)
+ .json({ error: "DB not ready", message: this.setupError });
+ return;
+ }
+ const body = req.body as ActionBody;
+ if (
+ !body?.support_request_id ||
+ !body?.order_id ||
+ !body?.action_type ||
+ typeof body.amount_usd !== "number"
+ ) {
+ res.status(400).json({ error: "Invalid payload" });
+ return;
+ }
+
+ const inserted = await this.pool.query(
+ `INSERT INTO support.operator_actions
+ (support_request_id, order_id, user_id, action_type, amount_usd, payload, status, actor)
+ VALUES ($1,$2,$3,$4,$5,$6::jsonb,'recorded',$7)
+ RETURNING action_id, created_at`,
+ [
+ body.support_request_id,
+ body.order_id,
+ body.user_id ?? null,
+ body.action_type,
+ body.amount_usd,
+ JSON.stringify(body.payload ?? {}),
+ body.actor ?? null,
+ ],
+ );
+
+ const nextStatus = body.action_type === "apply_refund" || body.action_type === "apply_credit"
+ ? "done"
+ : "in_progress";
+
+ await this.pool.query(
+ `INSERT INTO support.request_status (support_request_id, status, updated_at, last_action)
+ VALUES ($1, $2, NOW(), $3)
+ ON CONFLICT (support_request_id) DO UPDATE
+ SET status = EXCLUDED.status,
+ updated_at = EXCLUDED.updated_at,
+ last_action = EXCLUDED.last_action`,
+ [body.support_request_id, nextStatus, body.action_type],
+ );
+
+ res.status(201).json(inserted.rows[0]);
+ }));
+
+ router.post("/replies", withJsonError(async (req, res) => {
+ if (!this.pool) {
+ res
+ .status(503)
+ .json({ error: "DB not ready", message: this.setupError });
+ return;
+ }
+ const body = req.body as ReplyBody;
+ if (!body?.support_request_id || !body?.order_id || !body?.message_text) {
+ res.status(400).json({ error: "Invalid payload" });
+ return;
+ }
+
+ const inserted = await this.pool.query(
+ `INSERT INTO support.support_replies
+ (support_request_id, order_id, user_id, message_text, sent_by)
+ VALUES ($1,$2,$3,$4,$5)
+ RETURNING reply_id, created_at`,
+ [
+ body.support_request_id,
+ body.order_id,
+ body.user_id ?? null,
+ body.message_text,
+ body.sent_by ?? null,
+ ],
+ );
+
+ await this.pool.query(
+ `INSERT INTO support.operator_actions
+ (support_request_id, order_id, user_id, action_type, payload, status, actor)
+ VALUES ($1,$2,$3,'send_reply',$4::jsonb,'recorded',$5)`,
+ [
+ body.support_request_id,
+ body.order_id,
+ body.user_id ?? null,
+ JSON.stringify({ message_text: body.message_text }),
+ body.sent_by ?? null,
+ ],
+ );
+
+ await this.pool.query(
+ `INSERT INTO support.request_status (support_request_id, status, updated_at, last_action)
+ VALUES ($1, 'in_progress', NOW(), 'send_reply')
+ ON CONFLICT (support_request_id) DO UPDATE
+ SET status = EXCLUDED.status,
+ updated_at = EXCLUDED.updated_at,
+ last_action = EXCLUDED.last_action`,
+ [body.support_request_id],
+ );
+
+ res.status(201).json(inserted.rows[0]);
+ }));
+
+ router.post("/ratings", withJsonError(async (req, res) => {
+ if (!this.pool) {
+ res
+ .status(503)
+ .json({ error: "DB not ready", message: this.setupError });
+ return;
+ }
+ const body = req.body as RatingBody;
+ if (!body?.support_request_id || !body?.order_id || !body?.rating) {
+ res.status(400).json({ error: "Invalid payload" });
+ return;
+ }
+ if (body.rating !== "thumbs_up" && body.rating !== "thumbs_down") {
+ res.status(400).json({ error: "Invalid rating value" });
+ return;
+ }
+
+ let inserted;
+ try {
+ inserted = await this.pool.query(
+ `INSERT INTO support.response_ratings
+ (support_request_id, order_id, user_id, rating, reason_code, feedback_notes, actor)
+ VALUES ($1,$2,$3,$4,$5,$6,$7)
+ ON CONFLICT (support_request_id) DO UPDATE
+ SET order_id = EXCLUDED.order_id,
+ user_id = EXCLUDED.user_id,
+ rating = EXCLUDED.rating,
+ reason_code = EXCLUDED.reason_code,
+ feedback_notes = EXCLUDED.feedback_notes,
+ actor = EXCLUDED.actor,
+ created_at = NOW()
+ RETURNING rating_id, rating, reason_code, feedback_notes, actor, created_at`,
+ [
+ body.support_request_id,
+ body.order_id,
+ body.user_id ?? null,
+ body.rating,
+ body.reason_code ?? null,
+ body.feedback_notes ?? null,
+ body.actor ?? null,
+ ],
+ );
+ } catch (error) {
+ if (isPermissionDeniedError(error)) {
+ res.status(403).json({
+ error: "ratings_permission_denied",
+ message: "App principal lacks permission on support.response_ratings. Grant table privileges in Lakebase.",
+ });
+ return;
+ }
+ throw error;
+ }
+
+ res.status(201).json(inserted.rows[0]);
+ }));
+
+ router.post("/regenerate", withJsonError(async (req, res) => {
+ if (!this.pool || !this.workspaceClient) {
+ res
+ .status(503)
+ .json({ error: "DB/API not ready", message: this.setupError });
+ return;
+ }
+ const body = req.body as RegenerateBody;
+ if (!body?.support_request_id || !body?.order_id) {
+ res.status(400).json({ error: "Invalid payload" });
+ return;
+ }
+
+ const prompt = createRegenerationPrompt({
+ supportRequestId: body.support_request_id,
+ userId: body.user_id ?? null,
+ orderId: body.order_id,
+ operatorContext: body.operator_context ?? "",
+ currentReport: body.current_report ?? null,
+ });
+
+ let normalized: Record;
+ let warning: string | null = null;
+ try {
+ const servingResponse = await this.workspaceClient.apiClient.request({
+ path: "/serving-endpoints/responses",
+ method: "POST",
+ headers: new Headers({
+ Accept: "application/json",
+ "Content-Type": "application/json",
+ }),
+ raw: false,
+ payload: {
+ model: this.supportAgentEndpoint,
+ input: [{ role: "user", content: prompt }],
+ },
+ });
+ const responseText = extractResponseText(servingResponse);
+ const parsed = parseAgentReport(responseText);
+ normalized = normalizeReportForUi(parsed, body.user_id ?? null);
+ } catch (error) {
+ if (!isServingPermissionError(error)) {
+ throw error;
+ }
+
+ warning = `App service principal cannot query endpoint '${this.supportAgentEndpoint}'. Saved a fallback regeneration instead. Grant CAN_QUERY to service principal '${process.env.DATABRICKS_CLIENT_ID ?? "app service principal"}' for model-based regeneration.`;
+ console.warn("[support] regenerate fallback:", warning);
+ normalized = createFallbackRegeneratedReport({
+ currentReport: body.current_report ?? null,
+ operatorContext: body.operator_context ?? null,
+ supportRequestId: body.support_request_id,
+ userId: body.user_id ?? null,
+ orderId: body.order_id,
+ });
+ }
+
+ await this.pool.query(
+ `INSERT INTO support.operator_regenerated_reports
+ (support_request_id, user_id, order_id, operator_context, agent_response, actor)
+ VALUES ($1,$2,$3,$4,$5::jsonb,$6)`,
+ [
+ body.support_request_id,
+ body.user_id ?? null,
+ body.order_id,
+ body.operator_context ?? null,
+ JSON.stringify(normalized),
+ body.actor ?? null,
+ ],
+ );
+
+ await this.pool.query(
+ `INSERT INTO support.request_status (support_request_id, status, updated_at, last_action)
+ VALUES ($1, 'in_progress', NOW(), 'regenerate_report')
+ ON CONFLICT (support_request_id) DO UPDATE
+ SET status = EXCLUDED.status,
+ updated_at = EXCLUDED.updated_at,
+ last_action = EXCLUDED.last_action`,
+ [body.support_request_id],
+ );
+
+ res.status(201).json({ report: normalized, warning });
+ }));
+ }
+
+ async close(): Promise {
+ if (this.pool) {
+ await this.pool.end();
+ }
+ }
+}
diff --git a/apps/supportconsolek/supportconsolek/tests/smoke.spec.ts b/apps/supportconsolek/supportconsolek/tests/smoke.spec.ts
new file mode 100644
index 0000000..d712c69
--- /dev/null
+++ b/apps/supportconsolek/supportconsolek/tests/smoke.spec.ts
@@ -0,0 +1,108 @@
+import { test, expect } from '@playwright/test';
+import { writeFileSync, mkdirSync } from 'node:fs';
+import { join } from 'node:path';
+
+let testArtifactsDir: string;
+let consoleLogs: string[] = [];
+let consoleErrors: string[] = [];
+let pageErrors: string[] = [];
+let failedRequests: string[] = [];
+
+test('smoke test - app loads and displays data', async ({ page }) => {
+ // Navigate to the app
+ await page.goto('/');
+
+ // β οΈ UPDATE THESE SELECTORS after customizing App.tsx:
+ // - Change heading name to match your app title
+ // - Change data selector to match your primary data display
+ await expect(page.getByRole('heading', { name: 'Minimal Databricks App' })).toBeVisible();
+ await expect(page.getByText('hello world', { exact: true })).toBeVisible({ timeout: 30000 });
+
+ // Wait for health check to complete (wait for "OK" status)
+ await expect(page.getByText('OK')).toBeVisible({ timeout: 30000 });
+
+ // Verify console logs were captured
+ expect(consoleLogs.length).toBeGreaterThan(0);
+ expect(consoleErrors.length).toBe(0);
+ expect(pageErrors.length).toBe(0);
+});
+
+test.beforeEach(async ({ page }) => {
+ consoleLogs = [];
+ consoleErrors = [];
+ pageErrors = [];
+ failedRequests = [];
+
+ // Create temp directory for test artifacts
+ testArtifactsDir = join(process.cwd(), '.smoke-test');
+ mkdirSync(testArtifactsDir, { recursive: true });
+
+ // Capture console logs and errors (including React errors)
+ page.on('console', (msg) => {
+ const type = msg.type();
+ const text = msg.text();
+
+ // Skip empty lines and formatting placeholders
+ if (!text.trim() || /^%[osd]$/.test(text.trim())) {
+ return;
+ }
+
+ // Get stack trace for errors if available
+ const location = msg.location();
+ const locationStr = location.url ? ` at ${location.url}:${location.lineNumber}:${location.columnNumber}` : '';
+
+ consoleLogs.push(`[${type}] ${text}${locationStr}`);
+
+ // Separately track error messages (React errors appear here)
+ if (type === 'error') {
+ consoleErrors.push(`${text}${locationStr}`);
+ }
+ });
+
+ // Capture page errors with full stack trace
+ page.on('pageerror', (error) => {
+ const errorDetails = `Page error: ${error.message}\nStack: ${error.stack || 'No stack trace available'}`;
+ pageErrors.push(errorDetails);
+ // Also log to console for immediate visibility
+ console.error('Page error detected:', errorDetails);
+ });
+
+ // Capture failed requests
+ page.on('requestfailed', (request) => {
+ failedRequests.push(`Failed request: ${request.url()} - ${request.failure()?.errorText}`);
+ });
+});
+
+test.afterEach(async ({ page }, testInfo) => {
+ const testName = testInfo.title.replace(/ /g, '-').toLowerCase();
+ // Always capture artifacts, even if test fails
+ const screenshotPath = join(testArtifactsDir, `${testName}-app-screenshot.png`);
+ await page.screenshot({ path: screenshotPath, fullPage: true });
+
+ const logsPath = join(testArtifactsDir, `${testName}-console-logs.txt`);
+ const allLogs = [
+ '=== Console Logs ===',
+ ...consoleLogs,
+ '\n=== Console Errors (React errors) ===',
+ ...consoleErrors,
+ '\n=== Page Errors ===',
+ ...pageErrors,
+ '\n=== Failed Requests ===',
+ ...failedRequests,
+ ];
+ writeFileSync(logsPath, allLogs.join('\n'), 'utf-8');
+
+ console.log(`Screenshot saved to: ${screenshotPath}`);
+ console.log(`Console logs saved to: ${logsPath}`);
+ if (consoleErrors.length > 0) {
+ console.log('Console errors detected:', consoleErrors);
+ }
+ if (pageErrors.length > 0) {
+ console.log('Page errors detected:', pageErrors);
+ }
+ if (failedRequests.length > 0) {
+ console.log('Failed requests detected:', failedRequests);
+ }
+
+ await page.close();
+});
diff --git a/apps/supportconsolek/supportconsolek/vitest.config.ts b/apps/supportconsolek/supportconsolek/vitest.config.ts
new file mode 100644
index 0000000..3f54fed
--- /dev/null
+++ b/apps/supportconsolek/supportconsolek/vitest.config.ts
@@ -0,0 +1,16 @@
+import { defineConfig } from 'vitest/config';
+import path from 'node:path';
+
+export default defineConfig({
+ test: {
+ passWithNoTests: true,
+ globals: true,
+ environment: 'node',
+ exclude: ['**/node_modules/**', '**/dist/**', '**/*.spec.ts', '**/.smoke-test/**', '**/.databricks/**'],
+ },
+ resolve: {
+ alias: {
+ '@': path.resolve(__dirname, './client/src'),
+ },
+ },
+});
diff --git a/databricks.yml b/databricks.yml
index 1da18d7..e6ec4c8 100644
--- a/databricks.yml
+++ b/databricks.yml
@@ -21,6 +21,10 @@ sync:
- .DS_Store
- .claude/**
- .databricks/**
+ - apps/supportconsolek/**/.databricks/**
+ - apps/supportconsolek/**/node_modules/**
+ - apps/supportconsolek/**/dist/**
+ - apps/supportconsolek/**/client/dist/**
- ./data/universe/**
scripts:
@@ -65,7 +69,6 @@ scripts:
targets:
default:
default: true
-
resources:
jobs:
caspers:
@@ -73,16 +76,11 @@ targets:
queue:
enabled: true
performance_target: PERFORMANCE_OPTIMIZED
-
parameters:
- name: CATALOG
default: ${var.catalog}
- name: EVENTS_VOLUME
default: events
- - name: LLM_MODEL
- default: databricks-meta-llama-3-3-70b-instruct
- - name: REFUND_AGENT_ENDPOINT_NAME
- default: caspers_refund_agent
- name: SIMULATOR_SCHEMA
default: simulator
- name: START_DAY
@@ -92,44 +90,18 @@ targets:
- name: SCHEDULE_MINUTES
default: "3"
- name: PIPELINE_SCHEDULE_MINUTES
- default: "0"
-
+ default: "3"
tasks:
- task_key: Canonical_Data
notebook_task:
notebook_path: ${workspace.root_path}/stages/canonical_data
-
- task_key: Spark_Declarative_Pipeline
depends_on:
- task_key: Canonical_Data
notebook_task:
notebook_path: ${workspace.root_path}/stages/lakeflow
- - task_key: Refund_Recommender_Agent
- depends_on:
- - task_key: Spark_Declarative_Pipeline
- notebook_task:
- notebook_path: ${workspace.root_path}/stages/refunder_agent
-
- - task_key: Refund_Recommender_Stream
- depends_on:
- - task_key: Spark_Declarative_Pipeline
- notebook_task:
- notebook_path: ${workspace.root_path}/stages/refunder_stream
-
- - task_key: Lakebase_Reverse_ETL
- depends_on:
- - task_key: Refund_Recommender_Stream
- notebook_task:
- notebook_path: ${workspace.root_path}/stages/lakebase
-
- - task_key: Databricks_App_Refund_Manager
- depends_on:
- - task_key: Lakebase_Reverse_ETL
- notebook_task:
- notebook_path: ${workspace.root_path}/stages/apps
-
- complaints:
+ support:
resources:
jobs:
caspers:
@@ -137,18 +109,27 @@ targets:
queue:
enabled: true
performance_target: PERFORMANCE_OPTIMIZED
-
parameters:
- name: CATALOG
- default: ${var.catalog}
+ default: casperskitchens
- name: EVENTS_VOLUME
default: events
+ - name: LOCATIONS
+ default: sanfrancisco.json
- name: LLM_MODEL
default: databricks-meta-llama-3-3-70b-instruct
- - name: COMPLAINT_AGENT_ENDPOINT_NAME
- default: caspers_complaint_agent
- - name: COMPLAINT_RATE
- default: "0.15"
+ - name: SUPPORT_AGENT_ENDPOINT_NAME
+ default: caspers_support_agent
+ - name: SUPPORT_RISK_ENDPOINT_NAME
+ default: caspers_support_agent
+ - name: SUPPORT_RATE
+ default: "0.18"
+ - name: SUPPORT_ONLINE_STORE_NAME
+ default: caspers_support_online_store
+ - name: SUPPORT_ONLINE_STORE_CAPACITY
+ default: CU_1
+ - name: SUPPORT_ONLINE_TABLE_NAME
+ default: casperskitchens.support.support_request_features_online
- name: SIMULATOR_SCHEMA
default: simulator
- name: START_DAY
@@ -159,168 +140,62 @@ targets:
default: "3"
- name: PIPELINE_SCHEDULE_MINUTES
default: "0"
-
tasks:
- - task_key: Canonical_Data
+ - task_key: Raw_Data
notebook_task:
- notebook_path: ${workspace.root_path}/stages/canonical_data
-
+ notebook_path: ${workspace.root_path}/stages/raw_data
- task_key: Spark_Declarative_Pipeline
depends_on:
- - task_key: Canonical_Data
+ - task_key: Raw_Data
notebook_task:
notebook_path: ${workspace.root_path}/stages/lakeflow
-
- - task_key: Complaint_Agent
+ - task_key: Support_Request_Agent
depends_on:
- task_key: Spark_Declarative_Pipeline
notebook_task:
- notebook_path: ${workspace.root_path}/stages/complaint_agent
-
- - task_key: Complaint_Generator_Stream
+ notebook_path: ${workspace.root_path}/stages/support_request_agent
+ - task_key: Support_Request_Generator_Stream
depends_on:
- task_key: Spark_Declarative_Pipeline
notebook_task:
- notebook_path: ${workspace.root_path}/stages/complaint_generator_stream
-
- - task_key: Complaint_Agent_Stream
+ notebook_path: ${workspace.root_path}/stages/support_request_generator_stream
+ - task_key: Support_Request_Agent_Stream
depends_on:
- - task_key: Complaint_Agent
- - task_key: Complaint_Generator_Stream
+ - task_key: Support_Request_Agent
+ - task_key: Support_Request_Generator_Stream
notebook_task:
- notebook_path: ${workspace.root_path}/stages/complaint_agent_stream
-
- - task_key: Complaint_Lakebase
+ notebook_path: ${workspace.root_path}/stages/support_request_agent_stream
+ - task_key: Support_Feature_Store
depends_on:
- - task_key: Complaint_Agent_Stream
+ - task_key: Support_Request_Agent_Stream
notebook_task:
- notebook_path: ${workspace.root_path}/stages/complaint_lakebase
-
- free:
- resources:
- jobs:
- caspers:
- name: "Casper's Initializer"
- queue:
- enabled: true
- performance_target: PERFORMANCE_OPTIMIZED
-
- parameters:
- - name: CATALOG
- default: ${var.catalog}
- - name: EVENTS_VOLUME
- default: events
- - name: SIMULATOR_SCHEMA
- default: simulator
- - name: START_DAY
- default: "70"
- - name: SPEED_MULTIPLIER
- default: "60.0"
- - name: SCHEDULE_MINUTES
- default: "3"
- - name: PIPELINE_SCHEDULE_MINUTES
- default: "3"
-
- tasks:
- - task_key: Canonical_Data
- notebook_task:
- notebook_path: ${workspace.root_path}/stages/canonical_data
-
- - task_key: Spark_Declarative_Pipeline
+ notebook_path: ${workspace.root_path}/stages/support_feature_store
+ - task_key: Support_Lakebase
depends_on:
- - task_key: Canonical_Data
+ - task_key: Support_Feature_Store
notebook_task:
- notebook_path: ${workspace.root_path}/stages/lakeflow
-
- all:
- resources:
- jobs:
- caspers:
- name: "Casper's Initializer"
+ notebook_path: ${workspace.root_path}/stages/support_lakebase
+ support_response_evals_hourly:
+ name: "Support Response Evals Hourly"
queue:
enabled: true
performance_target: PERFORMANCE_OPTIMIZED
-
parameters:
- name: CATALOG
- default: ${var.catalog}
- - name: EVENTS_VOLUME
- default: events
- - name: LLM_MODEL
- default: databricks-meta-llama-3-3-70b-instruct
- - name: REFUND_AGENT_ENDPOINT_NAME
- default: caspers_refund_agent
- - name: COMPLAINT_AGENT_ENDPOINT_NAME
- default: caspers_complaint_agent
- - name: COMPLAINT_RATE
- default: "0.15"
- - name: SIMULATOR_SCHEMA
- default: simulator
- - name: START_DAY
- default: "70"
- - name: SPEED_MULTIPLIER
- default: "60.0"
- - name: SCHEDULE_MINUTES
- default: "3"
- - name: PIPELINE_SCHEDULE_MINUTES
- default: "0"
-
+ default: casperskitchens
+ - name: JUDGE_MODEL
+ default: databricks-gpt-5-mini
+ - name: EVAL_LIMIT
+ default: "100"
+ schedule:
+ quartz_cron_expression: "0 0 * * * ?"
+ timezone_id: "UTC"
+ pause_status: "UNPAUSED"
tasks:
- - task_key: Canonical_Data
- notebook_task:
- notebook_path: ${workspace.root_path}/stages/canonical_data
-
- - task_key: Spark_Declarative_Pipeline
- depends_on:
- - task_key: Canonical_Data
- notebook_task:
- notebook_path: ${workspace.root_path}/stages/lakeflow
-
- - task_key: Refund_Recommender_Agent
- depends_on:
- - task_key: Spark_Declarative_Pipeline
- notebook_task:
- notebook_path: ${workspace.root_path}/stages/refunder_agent
-
- - task_key: Refund_Recommender_Stream
- depends_on:
- - task_key: Spark_Declarative_Pipeline
- notebook_task:
- notebook_path: ${workspace.root_path}/stages/refunder_stream
-
- - task_key: Complaint_Agent
- depends_on:
- - task_key: Spark_Declarative_Pipeline
- notebook_task:
- notebook_path: ${workspace.root_path}/stages/complaint_agent
-
- - task_key: Complaint_Generator_Stream
- depends_on:
- - task_key: Spark_Declarative_Pipeline
- notebook_task:
- notebook_path: ${workspace.root_path}/stages/complaint_generator_stream
-
- - task_key: Complaint_Agent_Stream
- depends_on:
- - task_key: Complaint_Agent
- - task_key: Complaint_Generator_Stream
- notebook_task:
- notebook_path: ${workspace.root_path}/stages/complaint_agent_stream
-
- - task_key: Complaint_Lakebase
- depends_on:
- - task_key: Complaint_Agent_Stream
- notebook_task:
- notebook_path: ${workspace.root_path}/stages/complaint_lakebase
-
- - task_key: Lakebase_Reverse_ETL
- depends_on:
- - task_key: Refund_Recommender_Stream
- notebook_task:
- notebook_path: ${workspace.root_path}/stages/lakebase
-
- - task_key: Databricks_App_Refund_Manager
- depends_on:
- - task_key: Lakebase_Reverse_ETL
+ - task_key: run_support_response_evals
notebook_task:
- notebook_path: ${workspace.root_path}/stages/apps
\ No newline at end of file
+ notebook_path: ${workspace.root_path}/demos/agent-compare-models/demo_materials/support-response-evals
+ base_parameters:
+ CATALOG: "{{job.parameters.CATALOG}}"
+ JUDGE_MODEL: "{{job.parameters.JUDGE_MODEL}}"
+ EVAL_LIMIT: "{{job.parameters.EVAL_LIMIT}}"
diff --git a/demos/agent-compare-models/demo_materials/support-response-evals.ipynb b/demos/agent-compare-models/demo_materials/support-response-evals.ipynb
new file mode 100644
index 0000000..b80c491
--- /dev/null
+++ b/demos/agent-compare-models/demo_materials/support-response-evals.ipynb
@@ -0,0 +1,327 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Support Response Evals (Casper's Kitchens)\n",
+ "\n",
+ "This notebook shows how to evaluate support agent responses with MLflow judges and compare judge outcomes against human thumbs ratings captured in the support app.\n",
+ "\n",
+ "## What this covers\n",
+ "\n",
+ "1. Build an evaluation dataset from support requests and latest agent responses\n",
+ "2. Load human ratings (`thumbs_up` / `thumbs_down`) from Lakebase\n",
+ "3. Run `mlflow.genai.evaluate()` with an LLM judge\n",
+ "4. Compute `human_agreement_rate` between judge outcomes and app ratings\n",
+ "5. Review results in Databricks UI (MLflow traces + evaluation views)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {},
+ "source": [
+ "%pip install -U -qqqq mlflow[databricks] databricks-sdk psycopg2-binary pandas\n",
+ "%restart_python"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "code",
+ "metadata": {},
+ "source": [
+ "import json\n",
+ "import pandas as pd\n",
+ "import mlflow\n",
+ "import psycopg2\n",
+ "from databricks.sdk import WorkspaceClient\n",
+ "from mlflow.genai.judges import make_judge\n",
+ "\n",
+ "dbutils.widgets.text(\"CATALOG\", \"caspersdev\", \"UC Catalog\")\n",
+ "dbutils.widgets.text(\"JUDGE_MODEL\", \"databricks-gpt-5-mini\", \"Judge model endpoint\")\n",
+ "dbutils.widgets.text(\"EVAL_LIMIT\", \"50\", \"Max examples\")\n",
+ "\n",
+ "CATALOG = dbutils.widgets.get(\"CATALOG\")\n",
+ "JUDGE_MODEL = dbutils.widgets.get(\"JUDGE_MODEL\")\n",
+ "EVAL_LIMIT = int(dbutils.widgets.get(\"EVAL_LIMIT\") or \"50\")\n",
+ "\n",
+ "experiment = mlflow.set_experiment(f\"/Shared/{CATALOG}_support_response_evals\")\n",
+ "print(f\"Using experiment: {experiment.name}\")"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "code",
+ "metadata": {},
+ "source": [
+ "# Load latest support response per request and join request text.\n",
+ "support_df = spark.sql(f\"\"\"\n",
+ "WITH latest_reports AS (\n",
+ " SELECT support_request_id, user_id, order_id, ts, agent_response,\n",
+ " ROW_NUMBER() OVER (PARTITION BY support_request_id ORDER BY ts DESC) AS rn\n",
+ " FROM {CATALOG}.support.support_agent_reports_sync\n",
+ ")\n",
+ "SELECT\n",
+ " l.support_request_id,\n",
+ " l.user_id,\n",
+ " l.order_id,\n",
+ " l.ts,\n",
+ " l.agent_response,\n",
+ " r.request_text\n",
+ "FROM latest_reports l\n",
+ "LEFT JOIN {CATALOG}.support.raw_support_requests r\n",
+ " ON r.support_request_id = l.support_request_id\n",
+ "WHERE l.rn = 1\n",
+ "ORDER BY l.ts DESC\n",
+ "LIMIT {EVAL_LIMIT}\n",
+ "\"\"\").toPandas()\n",
+ "\n",
+ "print(f\"Loaded {len(support_df)} support responses\")\n",
+ "support_df.head(3)"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "code",
+ "metadata": {},
+ "source": [
+ "# Load latest human rating from Lakebase support.response_ratings.\n",
+ "config_row = spark.sql(f\"\"\"\n",
+ "SELECT endpoint_name, endpoint_host, database_name\n",
+ "FROM {CATALOG}.support.lakebase_v2_config\n",
+ "ORDER BY updated_at DESC\n",
+ "LIMIT 1\n",
+ "\"\"\").collect()[0]\n",
+ "\n",
+ "endpoint_name = config_row[\"endpoint_name\"]\n",
+ "endpoint_host = config_row[\"endpoint_host\"]\n",
+ "database_name = config_row[\"database_name\"]\n",
+ "\n",
+ "w = WorkspaceClient()\n",
+ "creds = w.postgres.generate_database_credential(endpoint=endpoint_name)\n",
+ "current_user = w.current_user.me().user_name\n",
+ "\n",
+ "ratings_df = pd.DataFrame(\n",
+ " columns=[\"support_request_id\", \"rating\", \"reason_code\", \"feedback_notes\", \"actor\", \"created_at\"]\n",
+ ")\n",
+ "\n",
+ "try:\n",
+ " conn = psycopg2.connect(\n",
+ " host=endpoint_host,\n",
+ " port=5432,\n",
+ " dbname=database_name,\n",
+ " user=current_user,\n",
+ " password=creds.token,\n",
+ " sslmode=\"require\",\n",
+ " )\n",
+ " with conn.cursor() as cur:\n",
+ " cur.execute(\n",
+ " \"\"\"\n",
+ " SELECT support_request_id, rating, reason_code, feedback_notes, actor, created_at\n",
+ " FROM support.response_ratings\n",
+ " ORDER BY created_at DESC\n",
+ " \"\"\"\n",
+ " )\n",
+ " rows = cur.fetchall()\n",
+ " conn.close()\n",
+ " ratings_df = pd.DataFrame(\n",
+ " rows,\n",
+ " columns=[\"support_request_id\", \"rating\", \"reason_code\", \"feedback_notes\", \"actor\", \"created_at\"],\n",
+ " )\n",
+ "except Exception as e:\n",
+ " print(f\"Could not load ratings yet: {e}\")\n",
+ "\n",
+ "if not ratings_df.empty:\n",
+ " ratings_df = (\n",
+ " ratings_df.sort_values(\"created_at\", ascending=False)\n",
+ " .drop_duplicates(subset=[\"support_request_id\"], keep=\"first\")\n",
+ " .reset_index(drop=True)\n",
+ " )\n",
+ "\n",
+ "print(f\"Loaded {len(ratings_df)} latest human ratings\")\n",
+ "ratings_df.head(3)"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "code",
+ "metadata": {},
+ "source": [
+ "def parse_report(raw):\n",
+ " if isinstance(raw, dict):\n",
+ " return raw\n",
+ " if isinstance(raw, str):\n",
+ " try:\n",
+ " return json.loads(raw)\n",
+ " except Exception:\n",
+ " return {}\n",
+ " return {}\n",
+ "\n",
+ "eval_data = []\n",
+ "for _, row in support_df.iterrows():\n",
+ " report = parse_report(row.get(\"agent_response\"))\n",
+ " eval_data.append(\n",
+ " {\n",
+ " \"inputs\": {\n",
+ " \"support_request_id\": row.get(\"support_request_id\"),\n",
+ " \"order_id\": row.get(\"order_id\"),\n",
+ " \"request_text\": row.get(\"request_text\") or \"\",\n",
+ " },\n",
+ " \"outputs\": {\n",
+ " \"draft_response\": report.get(\"draft_response\"),\n",
+ " \"refund_recommendation\": report.get(\"refund_recommendation\"),\n",
+ " \"credit_recommendation\": report.get(\"credit_recommendation\"),\n",
+ " \"decision_confidence\": report.get(\"decision_confidence\"),\n",
+ " \"escalation_flag\": report.get(\"escalation_flag\"),\n",
+ " },\n",
+ " }\n",
+ " )\n",
+ "\n",
+ "print(f\"Prepared {len(eval_data)} eval rows\")"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "code",
+ "metadata": {},
+ "source": [
+ "policy_compliance_judge = make_judge(\n",
+ " name=\"support_policy_compliance\",\n",
+ " instructions=\"\"\"\n",
+ "Evaluate whether the support response is policy-compliant and actionable.\n",
+ "\n",
+ "Support case input: {{ inputs }}\n",
+ "Agent output: {{ outputs }}\n",
+ "\n",
+ "Pass criteria:\n",
+ "- Draft response is professional and directly addresses the complaint.\n",
+ "- If refund/credit is recommended, amount or rationale is coherent.\n",
+ "- Response does not expose internal system identifiers.\n",
+ "- Escalation flag and confidence are consistent with severity.\n",
+ "\n",
+ "Return PASS only when all major criteria are satisfied. Otherwise return FAIL.\n",
+ "\"\"\",\n",
+ " model=f\"databricks:/{JUDGE_MODEL}\",\n",
+ ")\n",
+ "\n",
+ "evaluation_result = mlflow.genai.evaluate(\n",
+ " data=eval_data,\n",
+ " scorers=[policy_compliance_judge],\n",
+ ")\n",
+ "\n",
+ "print(\"Evaluation completed\")\n",
+ "evaluation_result"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "code",
+ "metadata": {},
+ "source": [
+ "def to_pandas_table(obj):\n",
+ " if obj is None:\n",
+ " return None\n",
+ " if isinstance(obj, pd.DataFrame):\n",
+ " return obj\n",
+ " if hasattr(obj, \"toPandas\"):\n",
+ " return obj.toPandas()\n",
+ " return None\n",
+ "\n",
+ "eval_df = None\n",
+ "if hasattr(evaluation_result, \"tables\") and isinstance(evaluation_result.tables, dict):\n",
+ " for _, table in evaluation_result.tables.items():\n",
+ " candidate = to_pandas_table(table)\n",
+ " if candidate is not None and len(candidate) > 0:\n",
+ " eval_df = candidate\n",
+ " break\n",
+ "\n",
+ "if eval_df is None:\n",
+ " print(\"Could not extract evaluation rows from EvaluationResult.tables\")\n",
+ "else:\n",
+ " judge_value_col = next(\n",
+ " (\n",
+ " c for c in eval_df.columns\n",
+ " if \"support_policy_compliance\" in c and (c.endswith(\"value\") or c.endswith(\"label\"))\n",
+ " ),\n",
+ " None,\n",
+ " )\n",
+ " inputs_col = \"inputs\" if \"inputs\" in eval_df.columns else None\n",
+ "\n",
+ " if judge_value_col is None or inputs_col is None:\n",
+ " print(\"Skipping agreement calc: expected evaluation columns were not found\")\n",
+ " print(\"Available columns:\", list(eval_df.columns))\n",
+ " else:\n",
+ " def parse_inputs(value):\n",
+ " if isinstance(value, dict):\n",
+ " return value\n",
+ " if isinstance(value, str):\n",
+ " try:\n",
+ " return json.loads(value)\n",
+ " except Exception:\n",
+ " return {}\n",
+ " return {}\n",
+ "\n",
+ " eval_df[\"support_request_id\"] = eval_df[inputs_col].apply(lambda v: parse_inputs(v).get(\"support_request_id\"))\n",
+ " eval_df[\"judge_label\"] = eval_df[judge_value_col].astype(str).str.upper().map({\"PASS\": \"thumbs_up\", \"FAIL\": \"thumbs_down\"})\n",
+ "\n",
+ " if ratings_df.empty:\n",
+ " print(\"No human ratings yet. Submit ratings in the support app, then rerun this cell.\")\n",
+ " else:\n",
+ " merged = eval_df[[\"support_request_id\", \"judge_label\"]].merge(\n",
+ " ratings_df[[\"support_request_id\", \"rating\"]],\n",
+ " on=\"support_request_id\",\n",
+ " how=\"inner\",\n",
+ " )\n",
+ " if len(merged) == 0:\n",
+ " print(\"No overlap yet between evaluated rows and rated rows.\")\n",
+ " else:\n",
+ " merged[\"agrees\"] = merged[\"judge_label\"] == merged[\"rating\"]\n",
+ " human_agreement_rate = float(merged[\"agrees\"].mean())\n",
+ " print(f\"human_agreement_rate: {human_agreement_rate:.2%} ({merged['agrees'].sum()}/{len(merged)})\")\n",
+ " display(merged.head(20))"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Where to review in Databricks UI\n",
+ "\n",
+ "1. **Support app UI**\n",
+ " - Open a support request in the details drawer.\n",
+ " - Use **Rate Agent Response** to save thumbs up/down (+ optional reason and notes).\n",
+ "\n",
+ "2. **Lakebase ratings table**\n",
+ " - Query `support.response_ratings` to audit latest operator feedback per request.\n",
+ "\n",
+ "3. **MLflow experiment view** (`/Shared/_support_response_evals`)\n",
+ " - **Runs**: see each `mlflow.genai.evaluate` execution.\n",
+ " - **Evaluation** tab: see scorer pass/fail values and judge rationales.\n",
+ " - **Traces** tab / trace detail: inspect per-example records and add human assessments if you want judge alignment.\n",
+ "\n",
+ "4. **Judge alignment (optional)**\n",
+ " - After adding human assessments in trace details, align the template judge with `judge.align(...)` in a follow-up run."
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "name": "python"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
\ No newline at end of file
diff --git a/jobs/complaint_agent_stream.ipynb b/jobs/complaint_agent_stream.ipynb
deleted file mode 100644
index 4c2a816..0000000
--- a/jobs/complaint_agent_stream.ipynb
+++ /dev/null
@@ -1,112 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "##### Complaint Agent Stream\n",
- "\n",
- "This notebook streams complaints through the complaint agent for processing"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "DATABRICKS_TOKEN = dbutils.notebook.entry_point.getDbutils().notebook().getContext().apiToken().getOrElse(None)\n",
- "DATABRICKS_HOST = dbutils.notebook.entry_point.getDbutils().notebook().getContext().apiUrl().getOrElse(None)\n",
- "\n",
- "CATALOG = dbutils.widgets.get(\"CATALOG\")\n",
- "COMPLAINT_AGENT_ENDPOINT_NAME = dbutils.widgets.get(\"COMPLAINT_AGENT_ENDPOINT_NAME\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "%pip install openai"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": "from pyspark.sql import functions as F\nfrom pyspark.sql.types import StringType\nfrom pyspark.sql.functions import udf\nimport json\n\nfrom openai import OpenAI\n\ndef process_complaint(complaint_text: str, order_id: str) -> str:\n \"\"\"Process a complaint through the agent endpoint.\"\"\"\n client = OpenAI(\n api_key=DATABRICKS_TOKEN,\n base_url=f\"{DATABRICKS_HOST}/serving-endpoints\",\n )\n \n default_response = json.dumps({\n \"order_id\": order_id,\n \"complaint_category\": \"other\",\n \"decision\": \"escalate\",\n \"credit_amount\": 0.0,\n \"rationale\": \"agent did not return valid JSON\",\n \"customer_response\": \"We're reviewing your complaint and will get back to you shortly.\"\n })\n \n for _ in range(3):\n try:\n # Call agent endpoint using Responses SDK\n response_obj = client.responses.create(\n model=f\"{COMPLAINT_AGENT_ENDPOINT_NAME}\",\n input=[{\n \"role\": \"user\", \n \"content\": f\"{complaint_text} (Order ID: {order_id})\"\n }]\n )\n # Extract text from ResponsesAgent output structure\n response = response_obj.output[-1].content[0].text\n \n # Validate JSON\n json.loads(response)\n return response\n except Exception as e:\n # If call fails, continue to retry\n continue\n \n # After 3 retries, return default response\n return default_response\n\nprocess_complaint_udf = udf(process_complaint, StringType())"
- },
- {
- "cell_type": "code",
- "source": "# Stream processing\ncomplaint_responses = (\n spark.readStream\n .table(f\"{CATALOG}.complaints.raw_complaints\")\n .select(\n F.col(\"complaint_id\"),\n F.col(\"order_id\"),\n F.current_timestamp().alias(\"ts\"),\n process_complaint_udf(F.col(\"complaint_text\"), F.col(\"order_id\")).alias(\"agent_response\")\n )\n)",
- "metadata": {},
- "execution_count": null,
- "outputs": []
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "%sql\n",
- "CREATE SCHEMA IF NOT EXISTS ${CATALOG}.complaints;\n",
- "CREATE VOLUME IF NOT EXISTS ${CATALOG}.complaints.checkpoints;"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "%sql\n",
- "CREATE TABLE IF NOT EXISTS ${CATALOG}.complaints.complaint_responses (\n",
- " complaint_id STRING,\n",
- " order_id STRING,\n",
- " ts TIMESTAMP,\n",
- " agent_response STRING\n",
- ")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "%sql\n",
- "-- Enable Change Data Feed for Lakebase sync\n",
- "ALTER TABLE ${CATALOG}.complaints.complaint_responses \n",
- "SET TBLPROPERTIES (delta.enableChangeDataFeed = true)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "complaint_responses.writeStream \\\n",
- " .option(\"checkpointLocation\", f\"/Volumes/{CATALOG}/complaints/checkpoints/complaint_agent_stream\") \\\n",
- " .trigger(availableNow=True) \\\n",
- " .table(f\"{CATALOG}.complaints.complaint_responses\")"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "name": "python",
- "version": "3.9.0"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
\ No newline at end of file
diff --git a/jobs/complaint_generator.ipynb b/jobs/complaint_generator.ipynb
deleted file mode 100644
index 294a371..0000000
--- a/jobs/complaint_generator.ipynb
+++ /dev/null
@@ -1,141 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "##### Complaint Generator\n",
- "\n",
- "This notebook generates synthetic customer complaints from delivered orders using AI SQL functions"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "CATALOG = dbutils.widgets.get(\"CATALOG\")\n",
- "COMPLAINT_RATE = float(dbutils.widgets.get(\"COMPLAINT_RATE\"))\n",
- "LLM_MODEL = dbutils.widgets.get(\"LLM_MODEL\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "from pyspark.sql import functions as F\n",
- "from pyspark.sql.types import StringType\n",
- "import random\n",
- "\n",
- "# Complaint category weights\n",
- "CATEGORIES = [\"delivery_delay\", \"missing_items\", \"food_quality\", \"service_issue\", \"other\"]\n",
- "WEIGHTS = [0.40, 0.25, 0.20, 0.10, 0.05]\n",
- "\n",
- "# Create a deterministic but varied category assignment\n",
- "# Using hash of order_id to ensure same order always gets same category\n",
- "@F.udf(returnType=StringType())\n",
- "def assign_category(order_id: str) -> str:\n",
- " \"\"\"Assign category based on hash of order_id for deterministic but varied distribution.\"\"\"\n",
- " # Use hash to get deterministic random selection\n",
- " seed = hash(order_id) % (2**31)\n",
- " rng = random.Random(seed)\n",
- " return rng.choices(CATEGORIES, weights=WEIGHTS, k=1)[0]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Create schema and checkpoint volume\n",
- "spark.sql(f\"CREATE SCHEMA IF NOT EXISTS {CATALOG}.complaints\")\n",
- "spark.sql(f\"CREATE VOLUME IF NOT EXISTS {CATALOG}.complaints.checkpoints\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Stream processing pipeline\n",
- "# Samples COMPLAINT_RATE of both historical and new delivered orders\n",
- "complaints_stream = (\n",
- " spark.readStream\n",
- " .table(f\"{CATALOG}.lakeflow.all_events\")\n",
- " .filter(\"event_type = 'delivered'\")\n",
- " .filter(F.rand() < COMPLAINT_RATE) # Sample orders for complaints (same rate for historical and new)\n",
- " .withColumn(\"complaint_id\", F.expr(\"uuid()\"))\n",
- " .withColumn(\"complaint_category\", assign_category(F.col(\"order_id\")))\n",
- " .withColumn(\"ts\", F.current_timestamp())\n",
- " .selectExpr(\n",
- " \"complaint_id\",\n",
- " \"order_id\",\n",
- " \"ts\",\n",
- " \"complaint_category\",\n",
- " f\"\"\"ai_gen(\n",
- " concat(\n",
- " 'You are an upset customer writing a complaint about your food delivery. ',\n",
- " 'Write a realistic 1-2 sentence complaint about: ', \n",
- " complaint_category, \n",
- " '. Order ID: ', \n",
- " order_id, \n",
- " '. Be specific and sound frustrated but realistic. Do not include greeting or signature.'\n",
- " )\n",
- " ) as complaint_text\"\"\",\n",
- " \"'llm_generator' as generated_by\"\n",
- " )\n",
- ")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Create target table schema\n",
- "spark.sql(f\"\"\"\n",
- "CREATE TABLE IF NOT EXISTS {CATALOG}.complaints.raw_complaints (\n",
- " complaint_id STRING,\n",
- " order_id STRING,\n",
- " ts TIMESTAMP,\n",
- " complaint_category STRING,\n",
- " complaint_text STRING,\n",
- " generated_by STRING\n",
- ")\n",
- "\"\"\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Write stream to raw_complaints table\n",
- "complaints_stream.writeStream \\\n",
- " .option(\"checkpointLocation\", f\"/Volumes/{CATALOG}/complaints/checkpoints/complaint_generator\") \\\n",
- " .trigger(availableNow=True) \\\n",
- " .table(f\"{CATALOG}.complaints.raw_complaints\")"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "name": "python",
- "version": "3.9.0"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/jobs/refund_recommender_stream.ipynb b/jobs/refund_recommender_stream.ipynb
deleted file mode 100644
index 304e5e1..0000000
--- a/jobs/refund_recommender_stream.ipynb
+++ /dev/null
@@ -1,452 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {},
- "inputWidgets": {},
- "nuid": "d9dd8d3e-2923-4e16-9435-bd2fd134d94f",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "source": [
- "\n",
- "##### refunder stream\n",
- "\n",
- "this notebook starts a stream to score completed orders for potential refunds"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {},
- "inputWidgets": {},
- "nuid": "54b5ea14-d02b-413b-9f69-86b932322ec0",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "DATABRICKS_TOKEN = dbutils.notebook.entry_point.getDbutils().notebook().getContext().apiToken().getOrElse(None)\n",
- "DATABRICKS_HOST = dbutils.notebook.entry_point.getDbutils().notebook().getContext().apiUrl().getOrElse(None)\n",
- "\n",
- "CATALOG = dbutils.widgets.get(\"CATALOG\")\n",
- "REFUND_AGENT_ENDPOINT_NAME = dbutils.widgets.get(\"REFUND_AGENT_ENDPOINT_NAME\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {},
- "inputWidgets": {},
- "nuid": "b2af6e4b-0a96-4810-9c15-eedb7e84db67",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "%pip install openai"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# In the canonical full demo run this stream job will start BEFORE the agent is actually ready\n",
- "# (because model serving deployment from previous stage takes 15~20min)\n",
- "# So, we seed some fake responses, and return them instead while the model isn't yet loaded\n",
- "# See next cell too\n",
- "fake_responses = [\n",
- " {\n",
- " \"refund_usd\": 0.0,\n",
- " \"refund_class\": \"none\",\n",
- " \"reason\": \"Order was delivered within the P75 delivery time\",\n",
- " },\n",
- " {\n",
- " \"refund_usd\": 0.0,\n",
- " \"refund_class\": \"none\",\n",
- " \"reason\": \"Order was delivered within the P75 delivery time\",\n",
- " },\n",
- " {\n",
- " \"refund_usd\": 4.47,\n",
- " \"refund_class\": \"partial\",\n",
- " \"reason\": \"Order was delivered late by 1.6 minutes\",\n",
- " },\n",
- " {\n",
- " \"refund_usd\": 0.0,\n",
- " \"refund_class\": \"none\",\n",
- " \"reason\": \"Order was delivered on time\",\n",
- " },\n",
- " {\n",
- " \"refund_usd\": 8.91,\n",
- " \"refund_class\": \"partial\",\n",
- " \"reason\": \"Order was delivered late by 5.5875 minutes\",\n",
- " },\n",
- " {\n",
- " \"refund_usd\": 5.48,\n",
- " \"refund_class\": \"partial\",\n",
- " \"reason\": \"Order was delivered 1.9 minutes after the P75 delivery time\",\n",
- " },\n",
- " {\n",
- " \"refund_usd\": 0.0,\n",
- " \"refund_class\": \"none\",\n",
- " \"reason\": \"Order was delivered on time\",\n",
- " },\n",
- " {\n",
- " \"refund_usd\": 9.25,\n",
- " \"refund_class\": \"partial\",\n",
- " \"reason\": \"Order was delivered 18.9 minutes after creation, which is less than the P75 delivery time of 32.804165 minutes, but still late compared to the P50 delivery time of 29.016666 minutes\",\n",
- " },\n",
- " {\n",
- " \"refund_usd\": 11.34,\n",
- " \"refund_class\": \"partial\",\n",
- " \"reason\": \"Order was delivered in 25.35 minutes, which is between the 75th percentile (32.80 minutes) and the 99th percentile (38.84 minutes) for the Bellevue location\",\n",
- " },\n",
- " {\n",
- " \"refund_usd\": 8.66,\n",
- " \"refund_class\": \"partial\",\n",
- " \"reason\": \"Order was late by 2.6625 minutes\",\n",
- " },\n",
- " {\n",
- " \"refund_usd\": 4.93,\n",
- " \"refund_class\": \"partial\",\n",
- " \"reason\": \"Order was late by 2.175 minutes\",\n",
- " },\n",
- " {\n",
- " \"refund_usd\": 0.0,\n",
- " \"refund_class\": \"none\",\n",
- " \"reason\": \"Order was delivered on time\",\n",
- " },\n",
- " {\n",
- " \"refund_usd\": 12.34,\n",
- " \"refund_class\": \"partial\",\n",
- " \"reason\": \"Order was delivered 7.97 minutes after the P75 delivery time\",\n",
- " },\n",
- " {\n",
- " \"refund_usd\": 0.0,\n",
- " \"refund_class\": \"none\",\n",
- " \"reason\": \"Order was delivered within the P75 delivery time\",\n",
- " },\n",
- "]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {},
- "inputWidgets": {},
- "nuid": "5540baa0-a16b-4bd1-a61d-dcb80eb2ce98",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "from pyspark.sql import functions as F\n",
- "from pyspark.sql.types import StringType\n",
- "from pyspark.sql.functions import udf\n",
- "from pyspark.sql.window import Window\n",
- "import json\n",
- "import random\n",
- "import os\n",
- "\n",
- "from openai import OpenAI\n",
- "\n",
- "# Configuration for inference capping\n",
- "CHECKPOINT_PATH = f\"/Volumes/{CATALOG}/recommender/checkpoints/refundrecommenderstream\"\n",
- "MAX_INFERENCES_PER_BATCH = 50\n",
- "\n",
- "def is_first_run():\n",
- " \"\"\"Check if checkpoint exists (indicates this is NOT the first run)\"\"\"\n",
- " return not os.path.exists(CHECKPOINT_PATH) or len(os.listdir(CHECKPOINT_PATH)) == 0\n",
- "\n",
- "def get_chat_completion(content: str) -> str:\n",
- " \"\"\"Call the refund agent endpoint for real inference\"\"\"\n",
- " client = OpenAI(\n",
- " api_key=DATABRICKS_TOKEN,\n",
- " base_url=f\"{DATABRICKS_HOST}/serving-endpoints\",\n",
- " )\n",
- " default_response = json.dumps({\n",
- " \"refund_usd\": 0.0,\n",
- " \"refund_class\": \"error\",\n",
- " \"reason\": \"agent did not return valid JSON\"\n",
- " })\n",
- "\n",
- " for _ in range(3):\n",
- " try:\n",
- " chat_completion = client.chat.completions.create(\n",
- " model=f\"{REFUND_AGENT_ENDPOINT_NAME}\",\n",
- " messages=[{\"role\": \"user\", \"content\": content}],\n",
- " )\n",
- " except Exception as e:\n",
- " # Fake data injection when serving endpoint isn't available\n",
- " response = json.dumps(random.choice(fake_responses))\n",
- " else:\n",
- " response = chat_completion.messages[-1].get(\"content\")\n",
- "\n",
- " try:\n",
- " json.loads(response)\n",
- " return response\n",
- " except json.JSONDecodeError:\n",
- " continue\n",
- "\n",
- " return default_response\n",
- "\n",
- "def get_fake_response(order_id: str) -> str:\n",
- " \"\"\"Return a fake response (fast path for backfill and overflow)\"\"\"\n",
- " return json.dumps(random.choice(fake_responses))\n",
- "\n",
- "get_chat_completion_udf = udf(get_chat_completion, StringType())\n",
- "get_fake_response_udf = udf(get_fake_response, StringType())\n",
- "\n",
- "def process_batch(batch_df, batch_id):\n",
- " \"\"\"Process each micro-batch with inference capping\n",
- "\n",
- " - First run (no checkpoint): ALL rows get fake responses (fast backfill)\n",
- " - Subsequent runs: First 50 rows get real inference, rest get fake\n",
- " \"\"\"\n",
- " if batch_df.isEmpty():\n",
- " return\n",
- "\n",
- " first_run = is_first_run()\n",
- " row_count = batch_df.count()\n",
- "\n",
- " print(f\"Processing batch {batch_id}: {row_count} rows, first_run={first_run}\")\n",
- "\n",
- " if first_run:\n",
- " # First run: ALL rows get fake responses (fast)\n",
- " print(f\" -> First run detected, using fake responses for all {row_count} rows\")\n",
- " result_df = batch_df.select(\n",
- " F.col(\"order_id\"),\n",
- " F.current_timestamp().alias(\"ts\"),\n",
- " F.to_timestamp(F.col(\"ts\")).alias(\"order_ts\"),\n",
- " get_fake_response_udf(F.col(\"order_id\")).alias(\"agent_response\")\n",
- " )\n",
- " else:\n",
- " # Subsequent runs: First N rows get real inference, rest get fake\n",
- " windowed = batch_df \\\n",
- " .withColumn(\"order_ts\", F.to_timestamp(F.col(\"ts\"))) \\\n",
- " .withColumn(\"row_num\", F.row_number().over(Window.orderBy(F.col(\"order_ts\"), F.col(\"order_id\"))))\n",
- "\n",
- " real_count = min(row_count, MAX_INFERENCES_PER_BATCH)\n",
- " fake_count = max(0, row_count - MAX_INFERENCES_PER_BATCH)\n",
- " print(f\" -> Real inference: {real_count} rows, fake: {fake_count} rows\")\n",
- "\n",
- " # Split into real inference vs fake\n",
- " real_inference_df = windowed.filter(f\"row_num <= {MAX_INFERENCES_PER_BATCH}\") \\\n",
- " .select(\n",
- " F.col(\"order_id\"),\n",
- " F.current_timestamp().alias(\"ts\"),\n",
- " F.col(\"order_ts\"),\n",
- " get_chat_completion_udf(F.col(\"order_id\")).alias(\"agent_response\")\n",
- " )\n",
- "\n",
- " fake_response_df = windowed.filter(f\"row_num > {MAX_INFERENCES_PER_BATCH}\") \\\n",
- " .select(\n",
- " F.col(\"order_id\"),\n",
- " F.current_timestamp().alias(\"ts\"),\n",
- " F.col(\"order_ts\"),\n",
- " get_fake_response_udf(F.col(\"order_id\")).alias(\"agent_response\")\n",
- " )\n",
- "\n",
- " result_df = real_inference_df.union(fake_response_df)\n",
- "\n",
- " # Write to table\n",
- " result_df.write.mode(\"append\").saveAsTable(f\"{CATALOG}.recommender.refund_recommendations\")\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {},
- "inputWidgets": {},
- "nuid": "4aa36d99-1219-4998-878e-7d49ff9dad2d",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": "# Read stream of delivered events - no sampling needed, we control volume in foreachBatch\ndelivered_events = spark.readStream.table(f\"{CATALOG}.lakeflow.all_events\") \\\n .filter(\"event_type = 'delivered'\")"
- },
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {},
- "inputWidgets": {},
- "nuid": "1cf733f0-a483-4c1b-a142-e0f0e0539bd1",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "%sql\n",
- "CREATE SCHEMA IF NOT EXISTS ${CATALOG}.recommender;\n",
- "CREATE VOLUME IF NOT EXISTS ${CATALOG}.recommender.checkpoints;"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {},
- "inputWidgets": {},
- "nuid": "9a12df85-36d4-485d-ac94-74dd12266a89",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "%sql\n",
- "CREATE TABLE IF NOT EXISTS ${CATALOG}.recommender.refund_recommendations (\n",
- " order_id STRING,\n",
- " ts TIMESTAMP,\n",
- " order_ts TIMESTAMP,\n",
- " agent_response STRING\n",
- ")\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {
- "byteLimit": 2048000,
- "implicitDf": true,
- "rowLimit": 10000
- },
- "inputWidgets": {},
- "nuid": "77a3cd40-e993-4308-a860-139372ba8d12",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": "# Enable CDC only if not already enabled (avoids unnecessary table writes)\ntable_name = f\"{CATALOG}.recommender.refund_recommendations\"\n\ntry:\n props = spark.sql(f\"SHOW TBLPROPERTIES {table_name}\").collect()\n cdc_enabled = any(row.key == \"delta.enableChangeDataFeed\" and row.value == \"true\" for row in props)\nexcept Exception:\n cdc_enabled = False\n\nif not cdc_enabled:\n print(f\"Enabling CDC on {table_name}\")\n spark.sql(f\"ALTER TABLE {table_name} SET TBLPROPERTIES (delta.enableChangeDataFeed = true)\")\nelse:\n print(f\"CDC already enabled on {table_name}, skipping\")"
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {},
- "inputWidgets": {},
- "nuid": "40d33309-fcdc-4e94-a65c-de78aac4422e",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": "# Process with foreachBatch for fine-grained control over inference volume\ndelivered_events.writeStream \\\n .foreachBatch(process_batch) \\\n .option(\"checkpointLocation\", f\"/Volumes/{CATALOG}/recommender/checkpoints/refundrecommenderstream\") \\\n .trigger(availableNow=True) \\\n .start() \\\n .awaitTermination()"
- }
- ],
- "metadata": {
- "application/vnd.databricks.v1+notebook": {
- "computePreferences": null,
- "dashboards": [],
- "environmentMetadata": {
- "base_environment": "",
- "environment_version": "3"
- },
- "inputWidgetPreferences": null,
- "language": "python",
- "notebookMetadata": {
- "mostRecentlyExecutedCommandWithImplicitDF": {
- "commandId": 8812248119570203,
- "dataframes": [
- "_sqldf"
- ]
- },
- "pythonIndentUnit": 4
- },
- "notebookName": "refund_recommender_stream",
- "widgets": {
- "CATALOG": {
- "currentValue": "cazzper",
- "nuid": "4fed5096-973b-4a59-acc5-e4a96cc00360",
- "typedWidgetInfo": {
- "autoCreated": false,
- "defaultValue": "",
- "label": "",
- "name": "CATALOG",
- "options": {
- "validationRegex": null,
- "widgetDisplayType": "Text"
- },
- "parameterDataType": "String"
- },
- "widgetInfo": {
- "defaultValue": "",
- "label": "",
- "name": "CATALOG",
- "options": {
- "autoCreated": false,
- "validationRegex": null,
- "widgetType": "text"
- },
- "widgetType": "text"
- }
- },
- "REFUND_AGENT_ENDPOINT_NAME": {
- "currentValue": "",
- "nuid": "bf162244-8e75-4570-82f4-ef93955c6891",
- "typedWidgetInfo": {
- "autoCreated": false,
- "defaultValue": "",
- "label": "",
- "name": "REFUND_AGENT_ENDPOINT_NAME",
- "options": {
- "validationRegex": null,
- "widgetDisplayType": "Text"
- },
- "parameterDataType": "String"
- },
- "widgetInfo": {
- "defaultValue": "",
- "label": "",
- "name": "REFUND_AGENT_ENDPOINT_NAME",
- "options": {
- "autoCreated": false,
- "validationRegex": null,
- "widgetType": "text"
- },
- "widgetType": "text"
- }
- }
- }
- },
- "language_info": {
- "name": "python"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 0
-}
\ No newline at end of file
diff --git a/jobs/support_request_agent_stream.ipynb b/jobs/support_request_agent_stream.ipynb
new file mode 100644
index 0000000..1187f1c
--- /dev/null
+++ b/jobs/support_request_agent_stream.ipynb
@@ -0,0 +1,330 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "##### Support Request Agent Stream\n",
+ "\n",
+ "Stream support requests through the support agent endpoint and persist reports."
+ ],
+ "id": "013aaba0"
+ },
+ {
+ "cell_type": "code",
+ "metadata": {},
+ "source": [
+ "DATABRICKS_TOKEN = dbutils.notebook.entry_point.getDbutils().notebook().getContext().apiToken().getOrElse(None)\n",
+ "DATABRICKS_HOST = dbutils.notebook.entry_point.getDbutils().notebook().getContext().apiUrl().getOrElse(None)\n",
+ "\n",
+ "CATALOG = dbutils.widgets.get(\"CATALOG\")\n",
+ "SUPPORT_AGENT_ENDPOINT_NAME = dbutils.widgets.get(\"SUPPORT_AGENT_ENDPOINT_NAME\")"
+ ],
+ "execution_count": null,
+ "outputs": [],
+ "id": "c8bcc31a"
+ },
+ {
+ "cell_type": "code",
+ "metadata": {},
+ "source": [
+ "%pip install openai"
+ ],
+ "execution_count": null,
+ "outputs": [],
+ "id": "f5f574c4"
+ },
+ {
+ "cell_type": "code",
+ "metadata": {},
+ "source": [
+ "import json\n",
+ "from pyspark.sql import functions as F\n",
+ "from pyspark.sql.functions import udf\n",
+ "from pyspark.sql.types import StringType\n",
+ "from pyspark.sql.window import Window\n",
+ "from openai import OpenAI\n",
+ "\n",
+ "BATCH_SIZE = 20\n",
+ "\n",
+ "\n",
+ "def process_support_request(payload_json: str) -> str:\n",
+ " payload = json.loads(payload_json)\n",
+ " support_request_id = payload.get(\"support_request_id\", \"\")\n",
+ " user_id = payload.get(\"user_id\", \"\")\n",
+ " order_id = payload.get(\"order_id\", \"\")\n",
+ "\n",
+ " client = OpenAI(\n",
+ " api_key=DATABRICKS_TOKEN,\n",
+ " base_url=f\"{DATABRICKS_HOST}/serving-endpoints\",\n",
+ " )\n",
+ "\n",
+ " fallback = json.dumps({\n",
+ " \"support_request_id\": support_request_id,\n",
+ " \"user_id\": user_id,\n",
+ " \"order_id\": order_id,\n",
+ " \"credit_recommendation\": {\"amount_usd\": 3.0, \"reason\": \"Fallback goodwill credit.\"},\n",
+ " \"refund_recommendation\": {\"amount_usd\": 0.0, \"reason\": \"No verified severe failure in fallback mode.\"},\n",
+ " \"draft_response\": \"Thanks for contacting us. I reviewed your case and added a $3.00 goodwill credit while we complete a final verification.\",\n",
+ " \"past_interactions_summary\": \"Fallback summary: history unavailable in this attempt.\",\n",
+ " \"order_details_summary\": \"Fallback summary: order details unavailable in this attempt.\",\n",
+ " \"decision_confidence\": \"medium\",\n",
+ " \"escalation_flag\": False,\n",
+ " })\n",
+ "\n",
+ " message = \"\\n\".join([\n",
+ " \"You are the Caspers support triage agent.\",\n",
+ " \"Use the structured case payload below.\",\n",
+ " \"Return strictly valid JSON only with keys:\",\n",
+ " \"support_request_id, user_id, order_id, credit_recommendation, refund_recommendation, draft_response, past_interactions_summary, order_details_summary, decision_confidence, escalation_flag.\",\n",
+ " \"Do not return placeholders like 'we will look into this'.\",\n",
+ " f\"Case payload: {json.dumps(payload)}\",\n",
+ " ])\n",
+ "\n",
+ " def deterministic_final_report() -> str:\n",
+ " features = payload.get(\"feature_context\") or {}\n",
+ " request_text = str(payload.get(\"request_text\") or \"\")\n",
+ " repeat = int(features.get(\"repeat_complaints_30d\") or 0)\n",
+ " risk = float(features.get(\"risk_score\") or 0.25)\n",
+ " policy_limit = float(features.get(\"policy_limit_usd\") or 20.0)\n",
+ "\n",
+ " if repeat >= 2 or risk >= 0.75:\n",
+ " refund = round(min(policy_limit, max(policy_limit * 0.9, 15.0)), 2)\n",
+ " credit = round(min(10.0, max(5.0, policy_limit * 0.25)), 2)\n",
+ " confidence = \"high\"\n",
+ " elif repeat == 1 or risk >= 0.45:\n",
+ " refund = round(min(policy_limit, max(policy_limit * 0.5, 6.0)), 2)\n",
+ " credit = round(min(7.0, max(3.0, policy_limit * 0.15)), 2)\n",
+ " confidence = \"high\"\n",
+ " else:\n",
+ " refund = 0.0\n",
+ " credit = round(min(5.0, max(2.0, policy_limit * 0.1)), 2)\n",
+ " confidence = \"medium\"\n",
+ "\n",
+ " if repeat >= 2:\n",
+ " intro = \"I can see this has happened more than once, and that is not acceptable.\"\n",
+ " else:\n",
+ " intro = \"I am sorry this happened, and thank you for reporting it.\"\n",
+ "\n",
+ " draft = (\n",
+ " f\"{intro} We are issuing a ${refund:.2f} refund and adding ${credit:.2f} in credits. \"\n",
+ " f\"Issue noted: {request_text}\"\n",
+ " ).strip()\n",
+ "\n",
+ " return json.dumps({\n",
+ " \"support_request_id\": support_request_id,\n",
+ " \"user_id\": user_id,\n",
+ " \"order_id\": order_id,\n",
+ " \"credit_recommendation\": {\"amount_usd\": credit, \"reason\": \"Policy-based support resolution.\"},\n",
+ " \"refund_recommendation\": {\"amount_usd\": refund, \"reason\": \"Policy-based support resolution.\"},\n",
+ " \"draft_response\": draft,\n",
+ " \"past_interactions_summary\": \"Computed from available user support history.\",\n",
+ " \"order_details_summary\": \"Computed from available order context.\",\n",
+ " \"decision_confidence\": confidence,\n",
+ " \"escalation_flag\": False,\n",
+ " })\n",
+ "\n",
+ " for _ in range(3):\n",
+ " try:\n",
+ " response_obj = client.responses.create(\n",
+ " model=SUPPORT_AGENT_ENDPOINT_NAME,\n",
+ " input=[{\"role\": \"user\", \"content\": message}],\n",
+ " )\n",
+ " response = response_obj.output[-1].content[0].text\n",
+ " parsed = json.loads(response)\n",
+ " draft = str(parsed.get(\"draft_response\") or \"\").lower()\n",
+ " has_placeholder = \"look into this\" in draft or \"reviewing your request\" in draft\n",
+ " bad_ordinal = \" 1th \" in draft or \" 2th \" in draft or \" 3th \" in draft\n",
+ " missing_amounts = parsed.get(\"refund_recommendation\") in (None, {}, \"\") and parsed.get(\"credit_recommendation\") in (None, {}, \"\")\n",
+ " if has_placeholder or missing_amounts or bad_ordinal:\n",
+ " return deterministic_final_report()\n",
+ " return response\n",
+ " except Exception:\n",
+ " continue\n",
+ "\n",
+ " return deterministic_final_report()\n",
+ "\n",
+ "\n",
+ "process_support_request_udf = udf(process_support_request, StringType())\n",
+ "\n",
+ "spark.sql(f\"CREATE SCHEMA IF NOT EXISTS {CATALOG}.support\")\n",
+ "spark.sql(\n",
+ " f\"\"\"\n",
+ " CREATE TABLE IF NOT EXISTS {CATALOG}.support.support_agent_reports (\n",
+ " support_request_id STRING,\n",
+ " user_id STRING,\n",
+ " order_id STRING,\n",
+ " request_text STRING,\n",
+ " ts TIMESTAMP,\n",
+ " agent_response STRING\n",
+ " )\n",
+ " \"\"\"\n",
+ ")\n",
+ "\n",
+ "# Backfill-safe schema evolution for existing tables.\n",
+ "try:\n",
+ " spark.sql(f\"ALTER TABLE {CATALOG}.support.support_agent_reports ADD COLUMNS (request_text STRING)\")\n",
+ "except Exception:\n",
+ " pass\n",
+ "\n",
+ "spark.sql(\n",
+ " f\"\"\"\n",
+ " ALTER TABLE {CATALOG}.support.support_agent_reports\n",
+ " SET TBLPROPERTIES (delta.enableChangeDataFeed = true)\n",
+ " \"\"\"\n",
+ ")\n",
+ "\n",
+ "# Backfill raw request text for historical rows where it was not stored yet.\n",
+ "spark.sql(\n",
+ " f\"\"\"\n",
+ " MERGE INTO {CATALOG}.support.support_agent_reports s\n",
+ " USING (\n",
+ " SELECT support_request_id, request_text\n",
+ " FROM {CATALOG}.support.raw_support_requests\n",
+ " ) r\n",
+ " ON s.support_request_id = r.support_request_id\n",
+ " WHEN MATCHED AND s.request_text IS NULL THEN\n",
+ " UPDATE SET s.request_text = r.request_text\n",
+ " \"\"\"\n",
+ ")\n",
+ "\n",
+ "pending = spark.sql(\n",
+ " f\"\"\"\n",
+ " SELECT\n",
+ " r.support_request_id,\n",
+ " r.user_id,\n",
+ " r.order_id,\n",
+ " r.ts,\n",
+ " r.request_type,\n",
+ " COALESCE(r.edge_case_type, 'standard') AS edge_case_type,\n",
+ " r.request_text,\n",
+ " COALESCE(f.repeat_complaints_30d, 0) AS repeat_complaints_30d,\n",
+ " COALESCE(f.policy_limit_usd, 20.0) AS policy_limit_usd,\n",
+ " COALESCE(f.risk_score, 0.25) AS risk_score\n",
+ " FROM {CATALOG}.support.raw_support_requests r\n",
+ " LEFT JOIN {CATALOG}.support.support_request_features f\n",
+ " ON r.support_request_id = f.support_request_id\n",
+ " LEFT ANTI JOIN {CATALOG}.support.support_agent_reports s\n",
+ " ON r.support_request_id = s.support_request_id\n",
+ " ORDER BY r.ts DESC\n",
+ " LIMIT {BATCH_SIZE}\n",
+ " \"\"\"\n",
+ ")\n",
+ "\n",
+ "order_context = spark.sql(\n",
+ " f\"\"\"\n",
+ " SELECT\n",
+ " order_id,\n",
+ " MAX(CASE WHEN event_type = 'order_created' THEN location END) AS location,\n",
+ " MAX(CASE WHEN event_type = 'order_created' THEN get_json_object(body, '$.items') END) AS items_json,\n",
+ " MAX(CASE WHEN event_type = 'order_created' THEN get_json_object(body, '$.customer_addr') END) AS customer_address,\n",
+ " MIN(CASE WHEN event_type = 'order_created' THEN try_to_timestamp(ts) END) AS order_created_ts,\n",
+ " MAX(CASE WHEN event_type = 'delivered' THEN try_to_timestamp(ts) END) AS delivered_ts\n",
+ " FROM {CATALOG}.lakeflow.all_events\n",
+ " GROUP BY order_id\n",
+ " \"\"\"\n",
+ ")\n",
+ "\n",
+ "history_rows = spark.sql(\n",
+ " f\"\"\"\n",
+ " SELECT user_id, support_request_id, ts, request_text, request_type, COALESCE(edge_case_type, 'standard') AS edge_case_type\n",
+ " FROM {CATALOG}.support.raw_support_requests\n",
+ " \"\"\"\n",
+ ")\n",
+ "\n",
+ "history_latest = (\n",
+ " history_rows\n",
+ " .withColumn(\"rn\", F.row_number().over(Window.partitionBy(\"user_id\").orderBy(F.col(\"ts\").desc())))\n",
+ " .filter(F.col(\"rn\") <= 5)\n",
+ " .groupBy(\"user_id\")\n",
+ " .agg(\n",
+ " F.to_json(\n",
+ " F.collect_list(\n",
+ " F.struct(\n",
+ " \"support_request_id\",\n",
+ " \"ts\",\n",
+ " \"request_type\",\n",
+ " \"edge_case_type\",\n",
+ " \"request_text\",\n",
+ " )\n",
+ " )\n",
+ " ).alias(\"past_request_context_json\")\n",
+ " )\n",
+ ")\n",
+ "\n",
+ "enriched = (\n",
+ " pending\n",
+ " .join(order_context, on=\"order_id\", how=\"left\")\n",
+ " .join(history_latest, on=\"user_id\", how=\"left\")\n",
+ " .withColumn(\n",
+ " \"payload_json\",\n",
+ " F.to_json(\n",
+ " F.struct(\n",
+ " F.col(\"support_request_id\"),\n",
+ " F.col(\"user_id\"),\n",
+ " F.col(\"order_id\"),\n",
+ " F.col(\"request_type\"),\n",
+ " F.col(\"edge_case_type\"),\n",
+ " F.col(\"request_text\"),\n",
+ " F.struct(\n",
+ " F.col(\"repeat_complaints_30d\"),\n",
+ " F.col(\"policy_limit_usd\"),\n",
+ " F.col(\"risk_score\"),\n",
+ " ).alias(\"feature_context\"),\n",
+ " F.struct(\n",
+ " F.col(\"location\"),\n",
+ " F.col(\"items_json\"),\n",
+ " F.col(\"customer_address\"),\n",
+ " F.col(\"order_created_ts\"),\n",
+ " F.col(\"delivered_ts\"),\n",
+ " ).alias(\"order_context\"),\n",
+ " F.coalesce(F.col(\"past_request_context_json\"), F.lit(\"[]\")).alias(\"past_request_context_json\"),\n",
+ " )\n",
+ " ),\n",
+ " )\n",
+ ")\n",
+ "\n",
+ "processed = (\n",
+ " enriched\n",
+ " .withColumn(\"ts\", F.current_timestamp())\n",
+ " .withColumn(\"agent_response\", process_support_request_udf(F.col(\"payload_json\")))\n",
+ " .select(\"support_request_id\", \"user_id\", \"order_id\", \"request_text\", \"ts\", \"agent_response\")\n",
+ ")\n",
+ "\n",
+ "processed.write.mode(\"append\").saveAsTable(f\"{CATALOG}.support.support_agent_reports\")\n",
+ "processed_count = processed.count()\n",
+ "print(f\"Processed {processed_count} support requests in this run\")\n",
+ "\n",
+ "sample_rows = processed.select(\"support_request_id\", \"agent_response\").limit(3).collect()\n",
+ "for sample in sample_rows:\n",
+ " print(f\"sample_support_request_id={sample['support_request_id']}\")\n",
+ " print(sample[\"agent_response\"][:600])\n",
+ "\n",
+ "sample_preview = sample_rows[0][\"agent_response\"][:600] if sample_rows else \"\"\n",
+ "dbutils.notebook.exit(\n",
+ " json.dumps(\n",
+ " {\n",
+ " \"processed_count\": processed_count,\n",
+ " \"sample_preview\": sample_preview,\n",
+ " }\n",
+ " )\n",
+ ")"
+ ],
+ "execution_count": null,
+ "outputs": [],
+ "id": "19cb1b2c"
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "name": "python"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
\ No newline at end of file
diff --git a/jobs/support_request_generator.ipynb b/jobs/support_request_generator.ipynb
new file mode 100644
index 0000000..9334696
--- /dev/null
+++ b/jobs/support_request_generator.ipynb
@@ -0,0 +1,250 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "##### Support Request Generator\n",
+ "\n",
+ "Generate generic support requests from delivered orders and assign repeat user IDs."
+ ],
+ "id": "2dc61cac"
+ },
+ {
+ "cell_type": "code",
+ "metadata": {},
+ "source": [
+ "CATALOG = dbutils.widgets.get(\"CATALOG\")\n",
+ "SUPPORT_RATE = float(dbutils.widgets.get(\"SUPPORT_RATE\"))\n",
+ "LLM_MODEL = dbutils.widgets.get(\"LLM_MODEL\")"
+ ],
+ "execution_count": null,
+ "outputs": [],
+ "id": "a66a324f"
+ },
+ {
+ "cell_type": "code",
+ "metadata": {},
+ "source": [
+ "from pyspark.sql import functions as F\n",
+ "\n",
+ "spark.sql(f\"CREATE SCHEMA IF NOT EXISTS {CATALOG}.support\")\n",
+ "spark.sql(f\"CREATE VOLUME IF NOT EXISTS {CATALOG}.support.checkpoints\")\n",
+ "\n",
+ "# Deterministic repeatable user IDs and controlled edge-case distribution.\n",
+ "# - ~10% create an extra follow-up request for same order/user\n",
+ "# - ~3% create two extra follow-ups (spam/repeat bursts)\n",
+ "# - ~5% spammy/escalation phrasing\n",
+ "# - ~2% abusive phrasing\n",
+ "source = (\n",
+ " spark.readStream\n",
+ " .table(f\"{CATALOG}.lakeflow.all_events\")\n",
+ " .filter(F.col(\"event_type\") == \"delivered\")\n",
+ " .filter(F.rand() < SUPPORT_RATE)\n",
+ " .withColumn(\"seed\", F.abs(F.hash(F.col(\"order_id\"))))\n",
+ " .withColumn(\"hash_bucket\", F.col(\"seed\") % F.lit(25))\n",
+ " .withColumn(\"user_id\", F.concat(F.lit(\"user-\"), F.format_string(\"%03d\", F.col(\"hash_bucket\"))))\n",
+ " .withColumn(\n",
+ " \"request_type\",\n",
+ " F.expr(\n",
+ " \"\"\"\n",
+ " CASE\n",
+ " WHEN hash_bucket % 5 = 0 THEN 'delivery_delay'\n",
+ " WHEN hash_bucket % 5 = 1 THEN 'missing_items'\n",
+ " WHEN hash_bucket % 5 = 2 THEN 'food_quality'\n",
+ " WHEN hash_bucket % 5 = 3 THEN 'billing'\n",
+ " ELSE 'general_support'\n",
+ " END\n",
+ " \"\"\"\n",
+ " ),\n",
+ " )\n",
+ " .withColumn(\n",
+ " \"edge_case_type\",\n",
+ " F.expr(\n",
+ " \"\"\"\n",
+ " CASE\n",
+ " WHEN seed % 100 < 2 THEN 'abusive_language'\n",
+ " WHEN seed % 100 < 7 THEN 'spammy_escalation'\n",
+ " WHEN seed % 100 < 15 THEN 'repeat_follow_up'\n",
+ " WHEN seed % 100 < 21 THEN 'non_compensable_confusion'\n",
+ " ELSE 'standard'\n",
+ " END\n",
+ " \"\"\"\n",
+ " ),\n",
+ " )\n",
+ " .withColumn(\n",
+ " \"repeat_multiplier\",\n",
+ " F.expr(\n",
+ " \"\"\"\n",
+ " CASE\n",
+ " WHEN seed % 100 < 3 THEN 3\n",
+ " WHEN seed % 100 < 13 THEN 2\n",
+ " ELSE 1\n",
+ " END\n",
+ " \"\"\"\n",
+ " ),\n",
+ " )\n",
+ ")\n",
+ "\n",
+ "expanded = (\n",
+ " source\n",
+ " .withColumn(\"repeat_idx\", F.explode(F.sequence(F.lit(1), F.col(\"repeat_multiplier\"))))\n",
+ " .withColumn(\"support_request_id\", F.expr(\"uuid()\"))\n",
+ " .withColumn(\"request_attempt\", F.col(\"repeat_idx\"))\n",
+ " .withColumn(\n",
+ " \"request_text\",\n",
+ " F.expr(\n",
+ " \"\"\"\n",
+ " CASE\n",
+ " WHEN edge_case_type = 'abusive_language' THEN\n",
+ " 'This is unacceptable and ridiculous. Your team keeps messing this up. Fix this now.'\n",
+ " WHEN edge_case_type = 'spammy_escalation' AND request_attempt > 1 THEN\n",
+ " 'Third message: still unresolved. Refund me immediately and escalate this to a supervisor now.'\n",
+ " WHEN edge_case_type = 'spammy_escalation' THEN\n",
+ " 'Second request today. Please resolve this immediately. I need clear compensation details now.'\n",
+ " WHEN edge_case_type = 'repeat_follow_up' AND request_attempt > 1 THEN\n",
+ " 'Following up again because this is not the first time this happened. Please review previous cases and offer a fair resolution.'\n",
+ " WHEN request_type = 'delivery_delay' AND request_attempt > 1 THEN\n",
+ " 'This is another delay issue for me. I need a concrete resolution with refund and credit details.'\n",
+ " WHEN request_type = 'delivery_delay' THEN\n",
+ " 'My delivery arrived much later than expected. Can you help with a credit or refund?'\n",
+ " WHEN request_type = 'missing_items' AND request_attempt > 1 THEN\n",
+ " 'This is the second time items were missing from my order. Please make this right with a concrete offer.'\n",
+ " WHEN request_type = 'missing_items' THEN\n",
+ " 'My order was missing one or more items. Please review and advise next steps.'\n",
+ " WHEN request_type = 'food_quality' THEN\n",
+ " 'I had a quality issue with my food. I would like support and possible compensation.'\n",
+ " WHEN request_type = 'billing' THEN\n",
+ " 'I think there is a billing issue on my recent order. Can you verify the charge?'\n",
+ " WHEN edge_case_type = 'non_compensable_confusion' THEN\n",
+ " 'I changed my mind after ordering and wanted to check if I can still get a courtesy credit.'\n",
+ " ELSE\n",
+ " 'I need help with a recent order. Please review my request and let me know what you can do.'\n",
+ " END\n",
+ " \"\"\"\n",
+ " ),\n",
+ " )\n",
+ " .select(\n",
+ " \"support_request_id\",\n",
+ " \"user_id\",\n",
+ " \"order_id\",\n",
+ " F.current_timestamp().alias(\"ts\"),\n",
+ " \"request_type\",\n",
+ " \"request_text\",\n",
+ " \"edge_case_type\",\n",
+ " \"request_attempt\",\n",
+ " F.lit(\"generator-v2\").alias(\"generated_by\"),\n",
+ " )\n",
+ ")\n",
+ "\n",
+ "spark.sql(\n",
+ " f\"\"\"\n",
+ " CREATE TABLE IF NOT EXISTS {CATALOG}.support.raw_support_requests (\n",
+ " support_request_id STRING,\n",
+ " user_id STRING,\n",
+ " order_id STRING,\n",
+ " ts TIMESTAMP,\n",
+ " request_type STRING,\n",
+ " request_text STRING,\n",
+ " edge_case_type STRING,\n",
+ " request_attempt INT,\n",
+ " generated_by STRING\n",
+ " )\n",
+ " \"\"\"\n",
+ ")\n",
+ "\n",
+ "# Backfill-safe schema evolution for existing environments.\n",
+ "try:\n",
+ " spark.sql(f\"ALTER TABLE {CATALOG}.support.raw_support_requests ADD COLUMNS (edge_case_type STRING)\")\n",
+ "except Exception:\n",
+ " pass\n",
+ "\n",
+ "try:\n",
+ " spark.sql(f\"ALTER TABLE {CATALOG}.support.raw_support_requests ADD COLUMNS (request_attempt INT)\")\n",
+ "except Exception:\n",
+ " pass\n",
+ "\n",
+ "expanded.writeStream \\\n",
+ " .option(\"checkpointLocation\", f\"/Volumes/{CATALOG}/support/checkpoints/support_request_generator\") \\\n",
+ " .trigger(availableNow=True) \\\n",
+ " .table(f\"{CATALOG}.support.raw_support_requests\")\n",
+ "\n",
+ "# Fallback batch seeding ensures fresh requests even when stream checkpoints have no new offsets.\n",
+ "spark.sql(\n",
+ " f\"\"\"\n",
+ " INSERT INTO {CATALOG}.support.raw_support_requests (\n",
+ " support_request_id,\n",
+ " user_id,\n",
+ " order_id,\n",
+ " ts,\n",
+ " request_type,\n",
+ " request_text,\n",
+ " edge_case_type,\n",
+ " request_attempt,\n",
+ " generated_by\n",
+ " )\n",
+ " SELECT\n",
+ " uuid() AS support_request_id,\n",
+ " concat('user-', lpad(cast(abs(hash(order_id)) % 25 as string), 3, '0')) AS user_id,\n",
+ " order_id,\n",
+ " current_timestamp() AS ts,\n",
+ " CASE\n",
+ " WHEN abs(hash(order_id)) % 5 = 0 THEN 'delivery_delay'\n",
+ " WHEN abs(hash(order_id)) % 5 = 1 THEN 'missing_items'\n",
+ " WHEN abs(hash(order_id)) % 5 = 2 THEN 'food_quality'\n",
+ " WHEN abs(hash(order_id)) % 5 = 3 THEN 'billing'\n",
+ " ELSE 'general_support'\n",
+ " END AS request_type,\n",
+ " CASE\n",
+ " WHEN abs(hash(order_id)) % 100 < 2 THEN 'This is unacceptable and keeps happening. Escalate this now.'\n",
+ " WHEN abs(hash(order_id)) % 100 < 7 THEN 'Second request today: still unresolved. I need a concrete refund and credit now.'\n",
+ " WHEN abs(hash(order_id)) % 100 < 15 THEN 'Following up again because this has happened before. Please offer a concrete resolution.'\n",
+ " WHEN abs(hash(order_id)) % 5 = 1 THEN 'My order was missing items again. Please review history and make this right.'\n",
+ " WHEN abs(hash(order_id)) % 5 = 0 THEN 'My delivery was delayed. Please provide a concrete refund and credit decision.'\n",
+ " ELSE 'I need help with a recent order issue and would like a clear resolution.'\n",
+ " END AS request_text,\n",
+ " CASE\n",
+ " WHEN abs(hash(order_id)) % 100 < 2 THEN 'abusive_language'\n",
+ " WHEN abs(hash(order_id)) % 100 < 7 THEN 'spammy_escalation'\n",
+ " WHEN abs(hash(order_id)) % 100 < 15 THEN 'repeat_follow_up'\n",
+ " WHEN abs(hash(order_id)) % 100 < 21 THEN 'non_compensable_confusion'\n",
+ " ELSE 'standard'\n",
+ " END AS edge_case_type,\n",
+ " CASE\n",
+ " WHEN abs(hash(order_id)) % 100 < 3 THEN 3\n",
+ " WHEN abs(hash(order_id)) % 100 < 13 THEN 2\n",
+ " ELSE 1\n",
+ " END AS request_attempt,\n",
+ " 'generator-v2-fallback-batch' AS generated_by\n",
+ " FROM (\n",
+ " SELECT DISTINCT order_id\n",
+ " FROM (\n",
+ " SELECT order_id FROM {CATALOG}.lakeflow.all_events WHERE event_type = 'delivered'\n",
+ " UNION ALL\n",
+ " SELECT order_id FROM {CATALOG}.support.support_agent_reports\n",
+ " ) candidate_orders\n",
+ " WHERE order_id IS NOT NULL\n",
+ " ORDER BY order_id DESC\n",
+ " LIMIT 50\n",
+ " ) latest_delivered\n",
+ " \"\"\"\n",
+ ")"
+ ],
+ "execution_count": null,
+ "outputs": [],
+ "id": "b6423428"
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "name": "python"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
\ No newline at end of file
diff --git a/pipelines/order_items/transformations/transformation.py b/pipelines/order_items/transformations/transformation.py
index 28908a5..d892110 100644
--- a/pipelines/order_items/transformations/transformation.py
+++ b/pipelines/order_items/transformations/transformation.py
@@ -59,22 +59,34 @@ def silver_order_items():
.withColumn("item", F.explode("body_obj.items"))
.withColumn("extended_price", F.col("item.price") * F.col("item.qty"))
.withColumn("order_day", F.to_date("event_ts"))
- .select(
- "order_id",
- "location_id",
- F.col("event_ts").alias("order_ts"), # canonical event time
- "order_day",
- F.col("item.id").alias("item_id"),
- F.col("item.menu_id"),
- F.col("item.category_id"),
- F.col("item.brand_id"),
- F.col("item.name").alias("item_name"),
- F.col("item.price"),
- F.col("item.qty"),
- "extended_price"
- )
)
- return df
+ # Support both canonical events (location_id) and legacy generator events (location/gk_id).
+ source_columns = set(df.columns)
+ if "location_id" in source_columns:
+ location_expr = F.col("location_id").cast("string")
+ elif "location" in source_columns:
+ location_expr = F.col("location")
+ elif "gk_id" in source_columns:
+ location_expr = F.col("gk_id")
+ else:
+ location_expr = F.lit(None).cast("string")
+
+ return (
+ df.select(
+ "order_id",
+ location_expr.alias("location_id"),
+ F.col("event_ts").alias("order_ts"), # canonical event time
+ "order_day",
+ F.col("item.id").alias("item_id"),
+ F.col("item.menu_id"),
+ F.col("item.category_id"),
+ F.col("item.brand_id"),
+ F.col("item.name").alias("item_name"),
+ F.col("item.price"),
+ F.col("item.qty"),
+ "extended_price"
+ )
+ )
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# 2-A. Gold β order header (one row per order)
diff --git a/stages/apps.ipynb b/stages/apps.ipynb
deleted file mode 100644
index 92fb660..0000000
--- a/stages/apps.ipynb
+++ /dev/null
@@ -1,414 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {
- "byteLimit": 2048000,
- "rowLimit": 10000
- },
- "inputWidgets": {},
- "nuid": "57d5ef69-54d8-4362-9634-0bfd94bc0b87",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "%pip install databricks-sdk --upgrade"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {
- "byteLimit": 2048000,
- "rowLimit": 10000
- },
- "inputWidgets": {},
- "nuid": "cb30ddf3-2a01-45a8-a7bd-4615a79b9158",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "CATALOG = dbutils.widgets.get(\"CATALOG\")\n",
- "REFUNDMANAGER_LAKEBASE_INSTANCE_NAME = f\"{CATALOG}refundmanager\""
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "import sys\n",
- "sys.path.append('../utils')\n",
- "from uc_state import add"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {
- "byteLimit": 2048000,
- "rowLimit": 10000
- },
- "inputWidgets": {},
- "nuid": "642684b2-5b19-4927-bfeb-e53e632813cc",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "from databricks.sdk import WorkspaceClient\n",
- "from databricks.sdk.service import sql\n",
- "\n",
- "w = WorkspaceClient()\n",
- "\n",
- "warehouse = w.warehouses.create(\n",
- " name=f\"{CATALOG}-warehouse\",\n",
- " cluster_size=\"2X-Small\",\n",
- " max_num_clusters=1,\n",
- " min_num_clusters=1,\n",
- " enable_serverless_compute=True\n",
- ").result()\n",
- "\n",
- "add(CATALOG, \"warehouses\", warehouse)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {
- "byteLimit": 2048000,
- "rowLimit": 10000
- },
- "inputWidgets": {},
- "nuid": "535f6730-a58f-4846-849a-96738fe5148d",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "print(warehouse)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {
- "byteLimit": 2048000,
- "rowLimit": 10000
- },
- "inputWidgets": {},
- "nuid": "d11e551c-5ddf-4ebf-a1c5-d31d1ae5db41",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "app_yaml_contents = f\"\"\"command:\n",
- " - uvicorn \n",
- " - app.main:app\n",
- "env:\n",
- " - name: DATABRICKS_WAREHOUSE_ID\n",
- " value: '{warehouse.id}'\n",
- " - name: DATABRICKS_CATALOG\n",
- " value: '{CATALOG}'\n",
- "\"\"\"\n",
- "\n",
- "# for some reason we need to remove it first before this works\n",
- "import os\n",
- "if os.path.exists(\"../apps/refund-manager/app.yaml\"):\n",
- " os.remove(\"../apps/refund-manager/app.yaml\")\n",
- "\n",
- "import time\n",
- "time.sleep(3)\n",
- "\n",
- "with open(\"../apps/refund-manager/app.yaml\", \"w\") as f:\n",
- " f.write(app_yaml_contents)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {
- "byteLimit": 2048000,
- "rowLimit": 10000
- },
- "inputWidgets": {},
- "nuid": "cb44bec0-71aa-4d21-8a5d-c4ad08a7643d",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "from databricks.sdk.service.apps import App, AppResource, AppResourceSqlWarehouse, AppResourceDatabase, AppResourceSqlWarehouseSqlWarehousePermission, AppResourceDatabaseDatabasePermission\n",
- "import os\n",
- "\n",
- "source_code_path = os.path.abspath(\"../apps/refund-manager\")\n",
- "\n",
- "app = w.apps.create(\n",
- " App(\n",
- " name=f\"{CATALOG}-refundmanager\",\n",
- " default_source_code_path=source_code_path,\n",
- " resources=[\n",
- " AppResource(\n",
- " name=\"sql-warehouse\",\n",
- " sql_warehouse=AppResourceSqlWarehouse(\n",
- " id=warehouse.id, \n",
- " permission=AppResourceSqlWarehouseSqlWarehousePermission.CAN_USE) \n",
- " ),\n",
- " AppResource(\n",
- " name=\"database\",\n",
- " database=AppResourceDatabase(\n",
- " instance_name=f\"{REFUNDMANAGER_LAKEBASE_INSTANCE_NAME}\",\n",
- " database_name=\"caspers\",\n",
- " permission=AppResourceDatabaseDatabasePermission.CAN_CONNECT_AND_CREATE\n",
- " )\n",
- " )\n",
- " ]\n",
- " )\n",
- ")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {
- "byteLimit": 2048000,
- "rowLimit": 10000
- },
- "inputWidgets": {},
- "nuid": "752e30d4-463f-43ce-bd9f-5be143af55c6",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "# blocks until app is ready\n",
- "app_status = app.result()\n",
- "\n",
- "# add to state\n",
- "add(CATALOG, \"apps\", app_status)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# grant app permissions to catalog, schema, `all_events` table for reading events\n",
- "from databricks.sdk.service import catalog\n",
- "\n",
- "w.grants.update(\n",
- " full_name=f\"{CATALOG}\",\n",
- " securable_type=\"CATALOG\",\n",
- " changes=[\n",
- " catalog.PermissionsChange(\n",
- " add=[catalog.Privilege.USE_CATALOG],\n",
- " principal=app_status.id\n",
- " )\n",
- " ]\n",
- ")\n",
- "\n",
- "w.grants.update(\n",
- " full_name=f\"{CATALOG}.lakeflow\",\n",
- " securable_type=\"SCHEMA\",\n",
- " changes=[\n",
- " catalog.PermissionsChange(\n",
- " add=[catalog.Privilege.USE_SCHEMA],\n",
- " principal=app_status.id\n",
- " )\n",
- " ]\n",
- ")\n",
- "\n",
- "w.grants.update(\n",
- " full_name=f\"{CATALOG}.lakeflow.all_events\",\n",
- " securable_type=\"TABLE\",\n",
- " changes=[\n",
- " catalog.PermissionsChange(\n",
- " add=[catalog.Privilege.SELECT],\n",
- " principal=app_status.id\n",
- " )\n",
- " ]\n",
- ")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {
- "byteLimit": 2048000,
- "rowLimit": 10000
- },
- "inputWidgets": {},
- "nuid": "44b92362-ba40-4e7c-a78c-a8cd648750eb",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "# there's no clean way to update the apps role in postgres so we delete it & recreate it\n",
- "# TODO: figure this out\n",
- "\n",
- "from databricks.sdk import WorkspaceClient\n",
- "from databricks.sdk.service.database import (\n",
- " DatabaseInstanceRole,\n",
- " DatabaseInstanceRoleIdentityType,\n",
- " DatabaseInstanceRoleMembershipRole,\n",
- ")\n",
- "\n",
- "w = WorkspaceClient()\n",
- "\n",
- "INSTANCE = f\"{REFUNDMANAGER_LAKEBASE_INSTANCE_NAME}\"\n",
- "APP_ID = app_status.id \n",
- "\n",
- "current_user = dbutils.notebook.entry_point.getDbutils().notebook().getContext().userName().get()\n",
- "w.database.delete_database_instance_role(INSTANCE, APP_ID, reassign_owned_to=current_user)\n",
- "\n",
- "role = DatabaseInstanceRole(\n",
- " name=APP_ID,\n",
- " identity_type=DatabaseInstanceRoleIdentityType.SERVICE_PRINCIPAL,\n",
- " membership_role=DatabaseInstanceRoleMembershipRole.DATABRICKS_SUPERUSER,\n",
- ")\n",
- "\n",
- "# Creates the role\n",
- "w.database.create_database_instance_role(INSTANCE, role)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {
- "byteLimit": 2048000,
- "rowLimit": 10000
- },
- "inputWidgets": {},
- "nuid": "159f8115-1bad-4d72-8f36-62042fbdeaf1",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "app_status"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {
- "byteLimit": 2048000,
- "rowLimit": 10000
- },
- "inputWidgets": {},
- "nuid": "a1fc9fa2-0bad-433a-b975-e3dfb988da8e",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "from databricks.sdk.service.apps import AppDeployment\n",
- "\n",
- "deployment = w.apps.deploy(\n",
- " app_name=app_status.name,\n",
- " app_deployment=AppDeployment(\n",
- " source_code_path=source_code_path\n",
- " )\n",
- ")\n",
- "deployment_status = deployment.result()\n",
- "display(deployment_status)"
- ]
- }
- ],
- "metadata": {
- "application/vnd.databricks.v1+notebook": {
- "computePreferences": null,
- "dashboards": [],
- "environmentMetadata": {
- "base_environment": "",
- "environment_version": "3"
- },
- "inputWidgetPreferences": null,
- "language": "python",
- "notebookMetadata": {
- "pythonIndentUnit": 4
- },
- "notebookName": "apps",
- "widgets": {
- "CATALOG": {
- "currentValue": "cazzper",
- "nuid": "65530636-5ecb-40c8-b410-4d64ad0602b3",
- "typedWidgetInfo": {
- "autoCreated": false,
- "defaultValue": "",
- "label": "",
- "name": "CATALOG",
- "options": {
- "validationRegex": null,
- "widgetDisplayType": "Text"
- },
- "parameterDataType": "String"
- },
- "widgetInfo": {
- "defaultValue": "",
- "label": "",
- "name": "CATALOG",
- "options": {
- "autoCreated": false,
- "validationRegex": null,
- "widgetType": "text"
- },
- "widgetType": "text"
- }
- }
- }
- },
- "language_info": {
- "name": "python"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 0
-}
diff --git a/stages/complaint_agent.ipynb b/stages/complaint_agent.ipynb
deleted file mode 100644
index 6dd2a0a..0000000
--- a/stages/complaint_agent.ipynb
+++ /dev/null
@@ -1,732 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "id": "cell-0",
- "metadata": {},
- "source": "#### complaint agent\n\nBuilds and ships an order-complaint agent using DSPy: author Unity Catalog tools, assemble the DSPy ReAct workflow, evaluate it, and promote the packaged model into production."
- },
- {
- "cell_type": "markdown",
- "id": "cell-1",
- "metadata": {},
- "source": [
- "#### Tool & View Registration\n",
- "\n",
- "- `CREATE SCHEMA` guarantees the shared `${CATALOG}.ai` workspace exists for agent assets.\n",
- "- `order_delivery_times_per_location_view` summarizes delivery percentiles per brand/location.\n",
- "- `get_order_overview(oid)` returns structured order metadata, items, and customer info.\n",
- "- `get_order_timing(oid)` exposes created/delivered timestamps plus transit duration.\n",
- "- `get_location_timings(loc)` yields P50/P75/P99 delivery benchmarks for benchmarking complaints.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "cell-2",
- "metadata": {},
- "outputs": [],
- "source": [
- "%sql\n",
- "CREATE SCHEMA IF NOT EXISTS ${CATALOG}.ai;"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "tdy6yy3gheg",
- "metadata": {},
- "outputs": [],
- "source": [
- "%sql\n",
- "CREATE OR REPLACE VIEW ${CATALOG}.ai.order_delivery_times_per_location_view AS\n",
- "WITH order_times AS (\n",
- " SELECT\n",
- " order_id,\n",
- " location,\n",
- " MAX(CASE WHEN event_type = 'order_created' THEN try_to_timestamp(ts) END) AS order_created_time,\n",
- " MAX(CASE WHEN event_type = 'delivered' THEN try_to_timestamp(ts) END) AS delivered_time\n",
- " FROM\n",
- " ${CATALOG}.lakeflow.all_events\n",
- " WHERE\n",
- " try_to_timestamp(ts) >= CURRENT_TIMESTAMP() - INTERVAL 1 DAY\n",
- " GROUP BY\n",
- " order_id,\n",
- " location\n",
- "),\n",
- "total_order_times AS (\n",
- " SELECT\n",
- " order_id,\n",
- " location,\n",
- " (UNIX_TIMESTAMP(delivered_time) - UNIX_TIMESTAMP(order_created_time)) / 60 AS total_order_time_minutes\n",
- " FROM\n",
- " order_times\n",
- " WHERE\n",
- " order_created_time IS NOT NULL\n",
- " AND delivered_time IS NOT NULL\n",
- ")\n",
- "SELECT\n",
- " location,\n",
- " PERCENTILE(total_order_time_minutes, 0.50) AS P50,\n",
- " PERCENTILE(total_order_time_minutes, 0.75) AS P75,\n",
- " PERCENTILE(total_order_time_minutes, 0.99) AS P99\n",
- "FROM\n",
- " total_order_times\n",
- "GROUP BY\n",
- " location"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "cell-3",
- "metadata": {},
- "outputs": [],
- "source": [
- "%sql\n",
- "CREATE OR REPLACE FUNCTION ${CATALOG}.ai.get_order_overview(oid STRING COMMENT 'The unique order identifier to retrieve information for')\n",
- "RETURNS TABLE (\n",
- " order_id STRING COMMENT 'The order id',\n",
- " location STRING COMMENT 'Order location',\n",
- " items_json STRING COMMENT 'JSON array of ordered items with details',\n",
- " customer_address STRING COMMENT 'Customer delivery address',\n",
- " brand_id BIGINT COMMENT 'Brand ID for the order',\n",
- " order_created_ts TIMESTAMP COMMENT 'When the order was created'\n",
- ")\n",
- "COMMENT 'Returns basic order information including items, location, and customer details'\n",
- "RETURN\n",
- " WITH order_created_events AS (\n",
- " SELECT\n",
- " order_id,\n",
- " location,\n",
- " get_json_object(body, '$.items') as items_json,\n",
- " get_json_object(body, '$.customer_addr') as customer_address,\n",
- " -- Extract brand_id from first item in the order\n",
- " CAST(get_json_object(get_json_object(body, '$.items[0]'), '$.brand_id') AS BIGINT) as brand_id,\n",
- " try_to_timestamp(ts) as order_created_ts\n",
- " FROM ${CATALOG}.lakeflow.all_events\n",
- " WHERE order_id = oid AND event_type = 'order_created'\n",
- " LIMIT 1\n",
- " )\n",
- " SELECT\n",
- " order_id,\n",
- " location,\n",
- " items_json,\n",
- " customer_address,\n",
- " brand_id,\n",
- " order_created_ts\n",
- " FROM order_created_events;"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "cell-4",
- "metadata": {},
- "outputs": [],
- "source": [
- "%sql\n",
- "CREATE OR REPLACE FUNCTION ${CATALOG}.ai.get_order_timing(oid STRING COMMENT 'The unique order identifier to get timing information for')\n",
- "RETURNS TABLE (\n",
- " order_id STRING COMMENT 'The order id',\n",
- " order_created_ts TIMESTAMP COMMENT 'When the order was created',\n",
- " delivered_ts TIMESTAMP COMMENT 'When the order was delivered (NULL if not delivered)',\n",
- " delivery_duration_minutes FLOAT COMMENT 'Time from order creation to delivery in minutes (NULL if not delivered)',\n",
- " delivery_status STRING COMMENT 'Current delivery status: delivered, in_progress, or unknown'\n",
- ")\n",
- "COMMENT 'Returns timing information for a specific order'\n",
- "RETURN\n",
- " WITH order_events AS (\n",
- " SELECT\n",
- " order_id,\n",
- " event_type,\n",
- " try_to_timestamp(ts) as event_ts\n",
- " FROM ${CATALOG}.lakeflow.all_events\n",
- " WHERE order_id = oid\n",
- " ),\n",
- " timing_summary AS (\n",
- " SELECT\n",
- " order_id,\n",
- " MIN(CASE WHEN event_type = 'order_created' THEN event_ts END) as order_created_ts,\n",
- " MAX(CASE WHEN event_type = 'delivered' THEN event_ts END) as delivered_ts\n",
- " FROM order_events\n",
- " GROUP BY order_id\n",
- " )\n",
- " SELECT\n",
- " order_id,\n",
- " order_created_ts,\n",
- " delivered_ts,\n",
- " CASE\n",
- " WHEN delivered_ts IS NOT NULL AND order_created_ts IS NOT NULL THEN\n",
- " CAST((UNIX_TIMESTAMP(delivered_ts) - UNIX_TIMESTAMP(order_created_ts)) / 60 AS FLOAT)\n",
- " ELSE NULL\n",
- " END as delivery_duration_minutes,\n",
- " CASE\n",
- " WHEN delivered_ts IS NOT NULL THEN 'delivered'\n",
- " WHEN order_created_ts IS NOT NULL THEN 'in_progress'\n",
- " ELSE 'unknown'\n",
- " END as delivery_status\n",
- " FROM timing_summary;"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "cell-5",
- "metadata": {},
- "outputs": [],
- "source": [
- "%sql\n",
- "CREATE OR REPLACE FUNCTION ${CATALOG}.ai.get_location_timings(loc STRING COMMENT 'Location name as a string')\n",
- "RETURNS TABLE (\n",
- " location STRING COMMENT 'Location of the order source',\n",
- " P50 FLOAT COMMENT '50th percentile delivery time in minutes',\n",
- " P75 FLOAT COMMENT '75th percentile delivery time in minutes',\n",
- " P99 FLOAT COMMENT '99th percentile delivery time in minutes'\n",
- ")\n",
- "COMMENT 'Returns the 50/75/99th percentile of delivery times for a location to benchmark order timing'\n",
- "RETURN\n",
- " SELECT location, P50, P75, P99\n",
- " FROM ${CATALOG}.ai.order_delivery_times_per_location_view AS odlt\n",
- " WHERE odlt.location = loc;"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "dq5ml4wp6v",
- "metadata": {},
- "source": "#### Model\n\n- Install DSPy, Databricks agent packages, and restart Python for a clean runtime.\n- Capture widget inputs (`CATALOG`, `LLM_MODEL`) and create an MLflow dev experiment for trace logging.\n- Define a templated `%%writefilev` magic that emits files with notebook variable substitution.\n- Materialize `agent.py` containing the DSPy ReAct complaint workflow wired to UC SQL tools and the chosen LLM endpoint.\n- Pull a delivered `order_id` sample and build the MLflow model signature/resources for logging."
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "bd3tu3r2gso",
- "metadata": {},
- "outputs": [],
- "source": "%pip install -U -qqqq typing_extensions dspy-ai mlflow unitycatalog-openai[databricks] openai databricks-sdk databricks-agents pydantic\n%restart_python"
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "dl04kgwv9ap",
- "metadata": {},
- "outputs": [],
- "source": [
- "CATALOG = dbutils.widgets.get(\"CATALOG\")\n",
- "LLM_MODEL = dbutils.widgets.get(\"LLM_MODEL\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "ktoahik8tl",
- "metadata": {},
- "outputs": [],
- "source": [
- "import mlflow\n",
- "\n",
- "# Create/set dev experiment for development and evaluation traces\n",
- "# Use shared path for job compatibility\n",
- "dev_experiment_name = f\"/Shared/{CATALOG}_complaint_agent_dev\"\n",
- "\n",
- "# set_experiment creates the experiment if it doesn't exist, or activates it if it does\n",
- "dev_experiment = mlflow.set_experiment(dev_experiment_name)\n",
- "dev_experiment_id = dev_experiment.experiment_id\n",
- "print(f\"β
Using dev experiment: {dev_experiment_name} (ID: {dev_experiment_id})\")\n",
- "\n",
- "# Add experiment to UC state for cleanup\n",
- "import sys\n",
- "sys.path.append('../utils')\n",
- "from uc_state import add\n",
- "\n",
- "experiment_data = {\n",
- " \"experiment_id\": dev_experiment_id,\n",
- " \"name\": dev_experiment_name\n",
- "}\n",
- "add(CATALOG, \"experiments\", experiment_data)\n",
- "print(f\"β
Added dev experiment to UC state\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "bruu85upqq5",
- "metadata": {},
- "outputs": [],
- "source": [
- "import re\n",
- "from IPython.core.magic import register_cell_magic\n",
- "\n",
- "@register_cell_magic\n",
- "def writefilev(line, cell):\n",
- " \"\"\"\n",
- " %%writefilev file.py\n",
- " Allows {{var}} substitutions while leaving normal {} intact.\n",
- " \"\"\"\n",
- " filename = line.strip()\n",
- "\n",
- " def replacer(match):\n",
- " expr = match.group(1)\n",
- " return str(eval(expr, globals(), locals()))\n",
- "\n",
- " # Replace only double braces {{var}}\n",
- " content = re.sub(r\"\\{\\{(.*?)\\}\\}\", replacer, cell)\n",
- "\n",
- " with open(filename, \"w\") as f:\n",
- " f.write(content)\n",
- " print(f\"Wrote file with substitutions: {filename}\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "w2c70l4ca8",
- "metadata": {},
- "outputs": [],
- "source": "%%writefilev agent.py\nimport warnings\nfrom typing import Optional, Literal\nfrom uuid import uuid4\nfrom pydantic import BaseModel, Field, field_validator, ValidationError\n\nwarnings.filterwarnings(\"ignore\", message=\".*Ignoring the default notebook Spark session.*\")\n\nimport dspy\nimport mlflow\nfrom unitycatalog.ai.core.base import get_uc_function_client\nfrom mlflow.pyfunc import ResponsesAgent\nfrom mlflow.types.responses import (\n ResponsesAgentRequest,\n ResponsesAgentResponse,\n)\n\n# Enable DSPy autologging for automatic trace capture\nmlflow.dspy.autolog(log_traces=True)\n\nLLM_MODEL = \"{{LLM_MODEL}}\"\nCATALOG = \"{{CATALOG}}\"\n\n# Configure DSPy with Databricks LM\nlm = dspy.LM(f'databricks/{LLM_MODEL}', max_tokens=2000)\ndspy.configure(lm=lm)\n\n# Initialize UC function client\nuc_client = get_uc_function_client()\n\n\nclass ComplaintResponse(BaseModel):\n \"\"\"Structured output for complaint triage decisions.\"\"\"\n order_id: str\n complaint_category: Literal[\"delivery_delay\", \"missing_items\", \"food_quality\", \"service_issue\", \"billing\", \"other\"] = Field(\n description=\"Exactly ONE primary complaint category\"\n )\n decision: Literal[\"suggest_credit\", \"escalate\"]\n credit_amount: Optional[float] = None\n confidence: Optional[Literal[\"high\", \"medium\", \"low\"]] = None\n priority: Optional[Literal[\"standard\", \"urgent\"]] = None\n rationale: str\n \n @field_validator('complaint_category', mode='before')\n @classmethod\n def parse_category(cls, v):\n \"\"\"Extract first valid category if multiple provided.\"\"\"\n if not isinstance(v, str):\n return v\n \n valid_categories = [\"delivery_delay\", \"missing_items\", \"food_quality\", \"service_issue\", \"billing\", \"other\"]\n v_lower = v.lower().strip()\n \n # Exact match\n if v_lower in valid_categories:\n return v_lower\n \n # Find first valid category in string\n for cat in valid_categories:\n if cat in v_lower:\n return cat\n \n return \"other\"\n \n @field_validator('confidence', mode='before')\n @classmethod\n def parse_confidence(cls, v):\n \"\"\"Ensure valid confidence value.\"\"\"\n if v is None or (isinstance(v, str) and v.lower() == \"null\"):\n return None\n if isinstance(v, str):\n v_lower = v.lower().strip()\n if v_lower in [\"high\", \"medium\", \"low\"]:\n return v_lower\n return \"medium\"\n return v\n \n @field_validator('priority', mode='before')\n @classmethod\n def parse_priority(cls, v):\n \"\"\"Ensure valid priority value.\"\"\"\n if v is None or (isinstance(v, str) and v.lower() == \"null\"):\n return None\n if isinstance(v, str):\n v_lower = v.lower().strip()\n if v_lower in [\"standard\", \"urgent\"]:\n return v_lower\n return \"standard\"\n return v\n\n\nclass ComplaintTriage(dspy.Signature):\n \"\"\"Analyze customer complaints for Casper's Kitchens and recommend triage actions.\n \n Process:\n 1. Extract order_id from complaint\n 2. Use get_order_overview(order_id) for order details and items\n 3. Use get_order_timing(order_id) for delivery timing\n 4. For delays, use get_location_timings(location) for percentile benchmarks\n 5. Make data-backed decision\n \n Decision Framework:\n \n SUGGEST_CREDIT (with credit_amount and confidence):\n - Delivery delays: Compare actual delivery time to location percentiles\n * P99: Suggest 25% of order total (high confidence)\n - Missing items: Use actual item prices from order data when available\n * Verify claimed item exists in order (affects confidence)\n * Use real costs from order data, or estimate $8-12 per item if unavailable\n - Food quality: 20-40% of order total based on severity\n * Minor issues (slightly cold, minor preparation issue): 20% (medium confidence)\n * Major issues (completely inedible, wrong preparation, health concern): 40% (high confidence)\n * Vague complaints (\"bad\", \"gross\"): escalate instead\n \n ESCALATE (with priority):\n - priority=\"standard\": Vague complaints, missing data, billing issues, service complaints\n - priority=\"urgent\": Legal threats, health/safety concerns, suspected fraud, abusive language\n \n Output Requirements:\n - For suggest_credit: credit_amount is REQUIRED and must be a number (can be 0.0 if no credit warranted), confidence is REQUIRED, priority must be null\n - For escalate: priority is REQUIRED, credit_amount and confidence must be null\n - complaint_category: Choose EXACTLY ONE category (the primary one)\n - Rationale must cite specific evidence (delivery times, percentiles, item verification, order total)\n - Rationale should be detailed but under 150 words\n - Round credit amounts to nearest $0.50\n - Confidence: high (strong data), medium (reasonable inference), low (weak/contradictory)\n \"\"\"\n \n complaint: str = dspy.InputField(desc=\"Customer complaint text\")\n order_id: str = dspy.OutputField(desc=\"Extracted order ID\")\n complaint_category: str = dspy.OutputField(desc=\"EXACTLY ONE category: delivery_delay, missing_items, food_quality, service_issue, billing, or other\")\n decision: str = dspy.OutputField(desc=\"EXACTLY ONE: suggest_credit or escalate\")\n credit_amount: str = dspy.OutputField(desc=\"If suggest_credit: MUST be a number (e.g., 0.0, 10.5). If escalate: null\")\n confidence: str = dspy.OutputField(desc=\"If suggest_credit: EXACTLY ONE of high, medium, low. If escalate: null\")\n priority: str = dspy.OutputField(desc=\"If escalate: EXACTLY ONE of standard or urgent. If suggest_credit: null\")\n rationale: str = dspy.OutputField(desc=\"Data-focused justification citing specific evidence\")\n\n\n# Unity Catalog tool wrappers\ndef get_order_overview(order_id: str) -> str:\n \"\"\"Get order details including items, location, and customer info.\"\"\"\n result = uc_client.execute_function(\n f\"{CATALOG}.ai.get_order_overview\",\n {\"oid\": order_id}\n )\n return str(result.value)\n\n\ndef get_order_timing(order_id: str) -> str:\n \"\"\"Get timing information for a specific order.\"\"\"\n result = uc_client.execute_function(\n f\"{CATALOG}.ai.get_order_timing\",\n {\"oid\": order_id}\n )\n return str(result.value)\n\n\ndef get_location_timings(location: str) -> str:\n \"\"\"Get delivery time percentiles for a specific location.\"\"\"\n result = uc_client.execute_function(\n f\"{CATALOG}.ai.get_location_timings\",\n {\"loc\": location}\n )\n return str(result.value)\n\n\nclass ComplaintTriageModule(dspy.Module):\n \"\"\"DSPy module for complaint triage with tool calling.\"\"\"\n \n def __init__(self):\n super().__init__()\n self.react = dspy.ReAct(\n signature=ComplaintTriage,\n tools=[get_order_overview, get_order_timing, get_location_timings],\n max_iters=10\n )\n \n def forward(self, complaint: str, max_retries: int = 2) -> ComplaintResponse:\n \"\"\"Process complaint and return structured triage decision with retry on validation failure.\"\"\"\n \n for attempt in range(max_retries + 1):\n try:\n result = self.react(complaint=complaint)\n \n # Parse credit_amount\n credit_amount = None\n if result.credit_amount and result.credit_amount.lower() != \"null\":\n try:\n credit_amount = float(result.credit_amount)\n except (ValueError, TypeError):\n if result.decision == \"suggest_credit\":\n raise ValidationError(\"suggest_credit requires valid numeric credit_amount\")\n \n # Validate business rules before Pydantic construction\n if result.decision == \"suggest_credit\" and credit_amount is None:\n raise ValidationError(\"suggest_credit requires credit_amount to be a number (can be 0.0)\")\n \n # Construct Pydantic model - field validators run here\n return ComplaintResponse(\n order_id=result.order_id,\n complaint_category=result.complaint_category,\n decision=result.decision,\n credit_amount=credit_amount,\n confidence=result.confidence,\n priority=result.priority,\n rationale=result.rationale\n )\n \n except (ValidationError, ValueError) as e:\n if attempt < max_retries:\n # Retry - DSPy will regenerate with potentially different output\n continue\n else:\n # Final attempt failed - re-raise\n raise\n\n\nclass DSPyComplaintAgent(ResponsesAgent):\n \"\"\"ResponsesAgent wrapper for DSPy complaint triage module.\"\"\"\n \n def __init__(self):\n self.module = ComplaintTriageModule()\n \n def predict(self, request: ResponsesAgentRequest) -> ResponsesAgentResponse:\n \"\"\"Process complaint request and return structured response.\"\"\"\n complaint = None\n for msg in request.input:\n msg_dict = msg.model_dump() if hasattr(msg, \"model_dump\") else msg\n if msg_dict.get(\"role\") == \"user\":\n complaint = msg_dict.get(\"content\", \"\")\n break\n \n if not complaint:\n raise ValueError(\"No user message found in request\")\n \n result = self.module(complaint=complaint)\n \n return ResponsesAgentResponse(\n output=[\n self.create_text_output_item(\n text=result.model_dump_json(),\n id=str(uuid4())\n )\n ],\n custom_outputs=request.custom_inputs\n )\n\n\n# Initialize agent\nAGENT = DSPyComplaintAgent()\nmlflow.models.set_model(AGENT)"
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "dd6gjrp4mx6",
- "metadata": {},
- "outputs": [],
- "source": [
- "# get an actual order_id for input example\n",
- "sample_order_id = spark.sql(f\"\"\"\n",
- " SELECT order_id \n",
- " FROM {CATALOG}.lakeflow.all_events \n",
- " WHERE event_type='delivered'\n",
- " LIMIT 1\n",
- "\"\"\").collect()[0]['order_id']"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "ih3tt5qeb5",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert sample_order_id is not None\n",
- "print(sample_order_id)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "23o4h7j6amzh",
- "metadata": {},
- "outputs": [],
- "source": "import mlflow\nfrom agent import LLM_MODEL\nfrom mlflow.models.resources import DatabricksFunction, DatabricksServingEndpoint\nfrom pkg_resources import get_distribution\n\nresources = [DatabricksServingEndpoint(endpoint_name=LLM_MODEL)]\n# Add UC function resources\nuc_tool_names = [\n f\"{CATALOG}.ai.get_order_overview\",\n f\"{CATALOG}.ai.get_order_timing\",\n f\"{CATALOG}.ai.get_location_timings\",\n]\nfor func_name in uc_tool_names:\n resources.append(DatabricksFunction(function_name=func_name))\n\ninput_example = {\n \"input\": [\n {\n \"role\": \"user\",\n \"content\": f\"My order was really late! Order ID: {sample_order_id}\"\n }\n ]\n}\n\n# Create custom conda environment with mlflow explicitly specified\nconda_env = {\n \"channels\": [\"conda-forge\"],\n \"dependencies\": [\n \"python=3.11\",\n \"pip\",\n {\n \"pip\": [\n \"mlflow==3.6\",\n f\"typing_extensions=={get_distribution('typing_extensions').version}\",\n f\"dspy-ai=={get_distribution('dspy-ai').version}\",\n f\"unitycatalog-openai[databricks]=={get_distribution('unitycatalog-openai').version}\",\n f\"pydantic=={get_distribution('pydantic').version}\",\n ]\n }\n ],\n \"name\": \"mlflow-env\"\n}\n\nwith mlflow.start_run():\n logged_agent_info = mlflow.pyfunc.log_model(\n name=\"complaint_agent\",\n python_model=\"agent.py\",\n input_example=input_example,\n resources=resources,\n conda_env=conda_env,\n )\n\nmlflow.set_active_model(model_id = logged_agent_info.model_id)"
- },
- {
- "cell_type": "markdown",
- "id": "gfympowd7q",
- "metadata": {},
- "source": "#### Evaluate the Agent\n\n- Synthesize diverse complaint scenarios from recent orders covering delivery delays, food quality issues, missing items, service complaints, and edge cases.\n- Configure MLflow `Guidelines` scorers to evaluate evidence-based reasoning, credit amount reasonableness, and decision metadata consistency.\n- Run batch evaluations with rate limiting (2s delay per request) to quantify decision quality before promotion."
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "2loovjto96g",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Comprehensive complaint scenarios for evaluation\n",
- "import random\n",
- "\n",
- "# Get sample order IDs for different scenarios\n",
- "all_order_ids = [\n",
- " row['order_id'] for row in spark.sql(f\"\"\"\n",
- " SELECT DISTINCT order_id \n",
- " FROM {CATALOG}.lakeflow.all_events \n",
- " WHERE event_type='delivered'\n",
- " LIMIT 50\n",
- " \"\"\").collect()\n",
- "]\n",
- "\n",
- "# Create diverse, realistic complaint scenarios\n",
- "complaint_scenarios = []\n",
- "\n",
- "# 1. Delivery delay complaints - mix of legitimate and questionable\n",
- "for oid in all_order_ids[:8]:\n",
- " complaint_scenarios.extend([\n",
- " f\"My order took forever to arrive! Order ID: {oid}\",\n",
- " f\"Been waiting 2 hours, this is ridiculous. Order {oid}\",\n",
- " f\"Order {oid} arrived late and cold\",\n",
- " f\"Delivery was slower than usual for order {oid}\",\n",
- " ])\n",
- "\n",
- "# 2. Food quality issues - range from specific to vague\n",
- "for oid in all_order_ids[8:12]:\n",
- " complaint_scenarios.extend([\n",
- " f\"My falafel was completely soggy and inedible. Order: {oid}\",\n",
- " f\"The food was cold when it arrived, very disappointing. Order: {oid}\",\n",
- " f\"Everything tasted bad. Order {oid}\",\n",
- " f\"Not happy with the quality. {oid}\",\n",
- " f\"The gyro meat was overcooked and dry, very disappointing. Order: {oid}\",\n",
- " ])\n",
- "\n",
- "# 3. Missing items - some verifiable, some suspicious\n",
- "for oid in all_order_ids[12:16]:\n",
- " complaint_scenarios.extend([\n",
- " f\"My entire falafel bowl was missing from the order! Order: {oid}\",\n",
- " f\"No drinks or sides in my order {oid}\",\n",
- " f\"Missing my gyro from order {oid}\",\n",
- " f\"You forgot half my items. {oid}\",\n",
- " ])\n",
- "\n",
- "# 4. Items claimed that might not match the order\n",
- "for oid in all_order_ids[16:18]:\n",
- " complaint_scenarios.extend([\n",
- " f\"Where are my chicken wings?! Order {oid}\",\n",
- " f\"Missing my pizza from order {oid}\",\n",
- " ])\n",
- "\n",
- "# 5. Service issues - should escalate\n",
- "for oid in all_order_ids[18:20]:\n",
- " complaint_scenarios.extend([\n",
- " f\"Your driver was extremely rude to me. Order: {oid}\",\n",
- " f\"Driver left my food at wrong address. Order: {oid}\",\n",
- " f\"The delivery person refused to come to my door. {oid}\",\n",
- " ])\n",
- "\n",
- "# 6. Multiple issues in one complaint\n",
- "for oid in all_order_ids[20:22]:\n",
- " complaint_scenarios.extend([\n",
- " f\"Order {oid} was late AND missing items AND cold!\",\n",
- " f\"Late delivery, rude driver, and food quality was poor. Order: {oid}\",\n",
- " ])\n",
- "\n",
- "# 7. Escalation triggers - legal threats, health concerns\n",
- "for oid in all_order_ids[22:24]:\n",
- " complaint_scenarios.extend([\n",
- " f\"I'm calling my lawyer about this terrible service! Order: {oid}\",\n",
- " f\"This food made me sick, possible food poisoning. Order: {oid}\",\n",
- " f\"Found a piece of plastic in my food! Order {oid} - this is dangerous!\",\n",
- " ])\n",
- "\n",
- "# 8. Vague complaints without specifics\n",
- "for oid in all_order_ids[24:26]:\n",
- " complaint_scenarios.extend([\n",
- " f\"Not satisfied with order {oid}\",\n",
- " f\"Bad experience. {oid}\",\n",
- " f\"Order {oid} was wrong\",\n",
- " ])\n",
- "\n",
- "# 9. Billing/promo issues\n",
- "for oid in all_order_ids[26:28]:\n",
- " complaint_scenarios.extend([\n",
- " f\"My promo code didn't work on order {oid}\",\n",
- " f\"I was charged twice for order {oid}!\",\n",
- " ])\n",
- "\n",
- "# 10. Edge cases - no order ID or invalid format\n",
- "complaint_scenarios.extend([\n",
- " \"My order was really late and the food was cold!\", # Missing order ID\n",
- " \"terrible service, do better\", # No order ID, vague\n",
- " \"Order ABC123 never arrived\", # Invalid order ID format\n",
- "])\n",
- "\n",
- "# 11. Non-complaints / comments\n",
- "for oid in all_order_ids[28:30]:\n",
- " complaint_scenarios.extend([\n",
- " f\"Great food, loved it! Order {oid}\", # Positive comment\n",
- " f\"Just wanted to say the driver was very polite today. {oid}\", # Positive feedback\n",
- " f\"How do I reorder my previous order {oid}?\", # Question, not complaint\n",
- " ])\n",
- "\n",
- "# 12. Unfounded complaints (on-time delivery but claiming delay)\n",
- "for oid in all_order_ids[30:32]:\n",
- " complaint_scenarios.extend([\n",
- " f\"This took way too long! Order {oid}\",\n",
- " ])\n",
- "\n",
- "# Sample for reasonable eval size (aim for ~25-30 scenarios)\n",
- "complaint_scenarios = random.sample(complaint_scenarios, min(30, len(complaint_scenarios)))\n",
- "\n",
- "# Wrap in correct input schema for ResponsesAgent\n",
- "data = []\n",
- "for complaint in complaint_scenarios:\n",
- " data.append({\n",
- " \"inputs\": {\n",
- " \"input\": [{\n",
- " \"role\": \"user\",\n",
- " \"content\": complaint\n",
- " }]\n",
- " }\n",
- " })\n",
- "\n",
- "print(f\"Created {len(data)} diverse evaluation scenarios including:\")\n",
- "print(\" - Delivery delays (legitimate & questionable)\")\n",
- "print(\" - Food quality issues (specific & vague)\")\n",
- "print(\" - Missing items (verifiable & suspicious)\")\n",
- "print(\" - Service complaints\")\n",
- "print(\" - Escalation triggers (health/legal)\")\n",
- "print(\" - Edge cases (no order ID, invalid ID)\")\n",
- "print(\" - Non-complaints (positive feedback, questions)\")\n",
- "print(\" - Multiple issues in one complaint\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "9l6zrp5n03b",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Create three focused scorers and run evaluation\n",
- "\n",
- "from mlflow.genai.scorers import Guidelines\n",
- "import mlflow\n",
- "import sys\n",
- "import os\n",
- "import time\n",
- "sys.path.append(os.getcwd())\n",
- "\n",
- "notebook_path = dbutils.notebook.entry_point.getDbutils().notebook().getContext().notebookPath().get()\n",
- "project_directory = os.path.dirname(notebook_path)\n",
- "sys.path.append(project_directory)\n",
- "\n",
- "from agent import AGENT\n",
- "\n",
- "# Scorer 1: Evidence-Based Reasoning - Does the rationale support the decision?\n",
- "evidence_reasoning = Guidelines(\n",
- " name=\"evidence_reasoning\",\n",
- " guidelines=[\n",
- " \"The rationale should provide specific evidence or reasoning for the decision made\",\n",
- " \"For timing complaints, rationale should mention delivery times or timing data if available\",\n",
- " \"For missing item complaints, rationale should reference the items in question\",\n",
- " \"For escalations, rationale should explain why human judgment is needed\"\n",
- " ]\n",
- ")\n",
- "\n",
- "# Scorer 2: Credit Amount Reasonableness - Is the refund amount appropriate?\n",
- "credit_reasonableness = Guidelines(\n",
- " name=\"credit_reasonableness\",\n",
- " guidelines=[\n",
- " \"If decision='escalate', automatically pass this check\",\n",
- " \"If decision='suggest_credit' with credit_amount > $0, amount should be reasonable ($5-$50)\",\n",
- " \"A credit_amount of $0 is valid when rationale indicates no issue\"\n",
- " ]\n",
- ")\n",
- "\n",
- "# Scorer 3: Decision Metadata Consistency - Are confidence and priority used correctly?\n",
- "decision_metadata = Guidelines(\n",
- " name=\"decision_metadata\",\n",
- " guidelines=[\n",
- " \"If decision='suggest_credit': confidence should be present and priority should be null\",\n",
- " \"If decision='escalate': priority should be present and confidence should be null\"\n",
- " ]\n",
- ")\n",
- "\n",
- "# ResponsesAgent predict wrapper with rate limiting\n",
- "def predict_fn(input):\n",
- " from mlflow.types.responses import ResponsesAgentRequest\n",
- " time.sleep(2) # Rate limiting to avoid hitting API limits\n",
- " request = ResponsesAgentRequest(input=input)\n",
- " response = AGENT.predict(request)\n",
- " output_item = response.output[-1]\n",
- " if hasattr(output_item, 'content') and output_item.content:\n",
- " return output_item.content[0][\"text\"]\n",
- " return str(output_item)\n",
- "\n",
- "# Run evaluation\n",
- "results = mlflow.genai.evaluate(\n",
- " data=data,\n",
- " scorers=[evidence_reasoning, credit_reasonableness, decision_metadata],\n",
- " predict_fn=predict_fn\n",
- ")\n",
- "\n",
- "print(f\"β
Evaluation complete\")"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "ttse3kj3pcj",
- "metadata": {},
- "source": "#### Log the Agent to Unity Catalog\n\n- Point MLflow at the Unity Catalog registry and name the artifact `${CATALOG}.ai.complaint_agent`.\n- Register the run-produced model so versioned deployments can be promoted through UC stages."
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "y8lfco9zzn",
- "metadata": {},
- "outputs": [],
- "source": [
- "mlflow.set_registry_uri(\"databricks-uc\")\n",
- "\n",
- "UC_MODEL_NAME = f\"{CATALOG}.ai.complaint_agent\"\n",
- "\n",
- "# register the model to UC\n",
- "uc_registered_model_info = mlflow.register_model(\n",
- " model_uri=logged_agent_info.model_uri, name=UC_MODEL_NAME\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "me3m6ovfqkd",
- "metadata": {},
- "source": "#### Deploy the Agent to Model Serving\n\n- Create a production MLflow experiment for live trace capture.\n- Use `agents.deploy` to create/update the Databricks Model Serving endpoint backed by the UC model version.\n- Wait until the serving endpoint reports READY before continuing to downstream steps.\n- Pass the prod experiment ID via environment variables so inference traces are logged automatically."
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "qjnjjztbbna",
- "metadata": {},
- "outputs": [],
- "source": [
- "import mlflow\n",
- "\n",
- "# Create prod experiment for production inference traces\n",
- "# Use shared path for job compatibility and visibility\n",
- "prod_experiment_name = f\"/Shared/{CATALOG}_complaint_agent_prod\"\n",
- "\n",
- "# set_experiment creates the experiment if it doesn't exist, or activates it if it does\n",
- "prod_experiment = mlflow.set_experiment(prod_experiment_name)\n",
- "prod_experiment_id = prod_experiment.experiment_id\n",
- "print(f\"β
Using prod experiment: {prod_experiment_name} (ID: {prod_experiment_id})\")\n",
- "\n",
- "# Add experiment to UC state for cleanup\n",
- "import sys\n",
- "sys.path.append('../utils')\n",
- "from uc_state import add\n",
- "\n",
- "experiment_data = {\n",
- " \"experiment_id\": prod_experiment_id,\n",
- " \"name\": prod_experiment_name\n",
- "}\n",
- "add(CATALOG, \"experiments\", experiment_data)\n",
- "print(f\"β
Added prod experiment to UC state\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "exckljo2zx4",
- "metadata": {},
- "outputs": [],
- "source": [
- "from datetime import timedelta\n",
- "\n",
- "from databricks import agents\n",
- "from databricks.sdk import WorkspaceClient\n",
- "from databricks.sdk.service.serving import EndpointStateReady\n",
- "\n",
- "endpoint_name = dbutils.widgets.get(\"COMPLAINT_AGENT_ENDPOINT_NAME\")\n",
- "deployment_info = agents.deploy(\n",
- " model_name=UC_MODEL_NAME,\n",
- " model_version=uc_registered_model_info.version,\n",
- " scale_to_zero=False,\n",
- " endpoint_name=endpoint_name,\n",
- " environment_vars={\"MLFLOW_EXPERIMENT_ID\": str(prod_experiment_id)},\n",
- ")\n",
- "\n",
- "workspace = WorkspaceClient()\n",
- "ready_endpoint = workspace.serving_endpoints.wait_get_serving_endpoint_not_updating(\n",
- " name=endpoint_name,\n",
- " timeout=timedelta(minutes=30),\n",
- ")\n",
- "\n",
- "if ready_endpoint.state.ready != EndpointStateReady.READY:\n",
- " raise RuntimeError(\n",
- " f\"Endpoint {endpoint_name} is {ready_endpoint.state.ready} after deployment; retry or investigate.\"\n",
- " )\n",
- "\n",
- "print(f\"β
Endpoint {endpoint_name} is READY\")\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "i1syfkwcivl",
- "metadata": {},
- "outputs": [],
- "source": [
- "print(deployment_info)"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "4i9yj8vjs2",
- "metadata": {},
- "source": "#### Record Model in State\n\n- Store the deployment metadata with `uc_state.add` to facilitate cleanup in the future."
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "ihnhnv5plw",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Also add to UC-state\n",
- "import sys\n",
- "sys.path.append('../utils')\n",
- "from uc_state import add\n",
- "\n",
- "add(dbutils.widgets.get(\"CATALOG\"), \"endpoints\", deployment_info)"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "bhjj7zuan9g",
- "metadata": {},
- "source": "#### Production Monitoring\n\n- Register MLflow guideline scorers to monitor decision quality and refund reasoning on production traffic.\n- Enable 10% sampling to flag decision drift or policy regressions without impacting performance."
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "v1j0a0y21ct",
- "metadata": {},
- "outputs": [],
- "source": [
- "from mlflow.genai.scorers import Guidelines, ScorerSamplingConfig\n",
- "\n",
- "# Register scorers for production monitoring (10% sampling)\n",
- "decision_quality_monitor = Guidelines(\n",
- " name=\"decision_quality_prod\",\n",
- " guidelines=[\n",
- " \"Food quality complaints should be classified as 'investigate', not 'auto_credit'\",\n",
- " \"Missing item complaints should be classified as 'investigate', not 'auto_credit'\",\n",
- " \"Legal threats or serious health concerns should be classified as 'escalate'\"\n",
- " ]\n",
- ").register(name=f\"{UC_MODEL_NAME}_decision_quality\")\n",
- "\n",
- "refund_reason_monitor = Guidelines(\n",
- " name=\"refund_reason_prod\",\n",
- " guidelines=[\n",
- " \"If a refund is offered, it must clearly relate to the complaint made by the user\"\n",
- " ]\n",
- ").register(name=f\"{UC_MODEL_NAME}_refund_reason\")\n",
- "\n",
- "# Start monitoring with 10% sampling of production traffic\n",
- "decision_quality_monitor = decision_quality_monitor.start(\n",
- " sampling_config=ScorerSamplingConfig(sample_rate=0.1)\n",
- ")\n",
- "\n",
- "refund_reason_monitor = refund_reason_monitor.start(\n",
- " sampling_config=ScorerSamplingConfig(sample_rate=0.1)\n",
- ")\n",
- "\n",
- "print(\"β
Production monitoring enabled with 10% sampling\")\n",
- "print(f\" - decision_quality scorer monitoring: {decision_quality_monitor}\")\n",
- "print(f\" - refund_reason scorer monitoring: {refund_reason_monitor}\")"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "name": "python",
- "version": "3.9.0"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
-}
\ No newline at end of file
diff --git a/stages/complaint_agent_stream.ipynb b/stages/complaint_agent_stream.ipynb
deleted file mode 100644
index a052c3d..0000000
--- a/stages/complaint_agent_stream.ipynb
+++ /dev/null
@@ -1,84 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "##### Complaint Agent Stream\n",
- "\n",
- "This notebook creates a scheduled job to process complaints through the complaint agent"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "%pip install --upgrade databricks-sdk"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "from databricks.sdk import WorkspaceClient\n",
- "import databricks.sdk.service.jobs as j\n",
- "import os\n",
- "\n",
- "w = WorkspaceClient()\n",
- "\n",
- "# Resolve the workspace notebook path\n",
- "notebook_abs_path = os.path.abspath(\"../jobs/complaint_agent_stream\")\n",
- "notebook_dbx_path = notebook_abs_path.replace(\n",
- " os.environ.get(\"DATABRICKS_WORKSPACE_ROOT\", \"/Workspace\"),\n",
- " \"/Workspace\"\n",
- ")\n",
- "\n",
- "job = w.jobs.create(\n",
- " name=\"Complaint Agent Stream\",\n",
- " schedule=j.CronSchedule(\n",
- " quartz_cron_expression=\"0 0/10 * * * ?\", # Every 10 minutes\n",
- " timezone_id=\"UTC\",\n",
- " pause_status=j.PauseStatus.UNPAUSED),\n",
- " tasks=[\n",
- " j.Task(\n",
- " task_key=\"complaint_agent_stream\",\n",
- " notebook_task=j.NotebookTask(\n",
- " notebook_path=notebook_dbx_path,\n",
- " base_parameters={\n",
- " \"CATALOG\": dbutils.widgets.get(\"CATALOG\"),\n",
- " \"COMPLAINT_AGENT_ENDPOINT_NAME\": dbutils.widgets.get(\"COMPLAINT_AGENT_ENDPOINT_NAME\")\n",
- " },\n",
- " )\n",
- " )\n",
- " ],\n",
- ")\n",
- "print(f\"Created job_id={job.job_id}\")\n",
- "\n",
- "import sys\n",
- "sys.path.append('../utils')\n",
- "from uc_state import add\n",
- "\n",
- "add(dbutils.widgets.get(\"CATALOG\"), \"jobs\", job)\n",
- "\n",
- "w.jobs.run_now(job_id=job.job_id)"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "name": "python",
- "version": "3.9.0"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/stages/complaint_generator_stream.ipynb b/stages/complaint_generator_stream.ipynb
deleted file mode 100644
index ba629cf..0000000
--- a/stages/complaint_generator_stream.ipynb
+++ /dev/null
@@ -1,85 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "##### Complaint Generator Stream\n",
- "\n",
- "This notebook creates a scheduled job to generate customer complaints from delivered orders"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "%pip install --upgrade databricks-sdk"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "from databricks.sdk import WorkspaceClient\n",
- "import databricks.sdk.service.jobs as j\n",
- "import os\n",
- "\n",
- "w = WorkspaceClient()\n",
- "\n",
- "# Resolve the workspace notebook path\n",
- "notebook_abs_path = os.path.abspath(\"../jobs/complaint_generator\")\n",
- "notebook_dbx_path = notebook_abs_path.replace(\n",
- " os.environ.get(\"DATABRICKS_WORKSPACE_ROOT\", \"/Workspace\"),\n",
- " \"/Workspace\"\n",
- ")\n",
- "\n",
- "job = w.jobs.create(\n",
- " name=\"Complaint Generator Stream\",\n",
- " schedule=j.CronSchedule(\n",
- " quartz_cron_expression=\"0 0/10 * * * ?\", # Every 10 minutes\n",
- " timezone_id=\"UTC\",\n",
- " pause_status=j.PauseStatus.UNPAUSED),\n",
- " tasks=[\n",
- " j.Task(\n",
- " task_key=\"complaint_generator_stream\",\n",
- " notebook_task=j.NotebookTask(\n",
- " notebook_path=notebook_dbx_path,\n",
- " base_parameters={\n",
- " \"CATALOG\": dbutils.widgets.get(\"CATALOG\"),\n",
- " \"COMPLAINT_RATE\": dbutils.widgets.get(\"COMPLAINT_RATE\"),\n",
- " \"LLM_MODEL\": dbutils.widgets.get(\"LLM_MODEL\")\n",
- " },\n",
- " )\n",
- " )\n",
- " ],\n",
- ")\n",
- "print(f\"Created job_id={job.job_id}\")\n",
- "\n",
- "import sys\n",
- "sys.path.append('../utils')\n",
- "from uc_state import add\n",
- "\n",
- "add(dbutils.widgets.get(\"CATALOG\"), \"jobs\", job)\n",
- "\n",
- "w.jobs.run_now(job_id=job.job_id)"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "name": "python",
- "version": "3.9.0"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/stages/complaint_lakebase.ipynb b/stages/complaint_lakebase.ipynb
deleted file mode 100644
index 5ab1c43..0000000
--- a/stages/complaint_lakebase.ipynb
+++ /dev/null
@@ -1,135 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "CATALOG = dbutils.widgets.get(\"CATALOG\")\n",
- "COMPLAINT_LAKEBASE_INSTANCE_NAME = f\"{CATALOG}complaintmanager\""
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "%pip install databricks-sdk --upgrade"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "from databricks.sdk import WorkspaceClient\n",
- "from databricks.sdk.service.database import DatabaseInstance\n",
- "import uuid\n",
- "import time\n",
- "\n",
- "import sys\n",
- "sys.path.append('../utils')\n",
- "from uc_state import add\n",
- "\n",
- "# Initialize the Workspace client\n",
- "w = WorkspaceClient()\n",
- "\n",
- "UNIQUE = str(uuid.uuid4())[:8]\n",
- "\n",
- "# Create a database instance\n",
- "instance = w.database.create_database_instance(\n",
- " DatabaseInstance(\n",
- " name=f\"{COMPLAINT_LAKEBASE_INSTANCE_NAME}\",\n",
- " capacity=\"CU_1\"\n",
- " )\n",
- ")\n",
- "\n",
- "print(f\"Created database instance: {instance.name}\")\n",
- "add(CATALOG, \"databaseinstances\", {\"name\": instance.name, \"type\": \"complaint\"})\n",
- "print(f\"Connection endpoint: {instance.response.read_write_dns}\")\n",
- "\n",
- "# block until it's actually ready\n",
- "print(\"Waiting for database instance to be available...\")\n",
- "while True:\n",
- " if str(w.database.get_database_instance(instance.name).state) == \"DatabaseInstanceState.AVAILABLE\":\n",
- " print(str(w.database.get_database_instance(instance.name).state))\n",
- " break\n",
- " time.sleep(10)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# create a database `caspers_complaints` in the lakebase instance\n",
- "# register it to UC as concat of CATALOG-INSTANCE_NAME (params)\n",
- "\n",
- "from databricks.sdk.service.database import DatabaseCatalog\n",
- "\n",
- "catalog = w.database.create_database_catalog(\n",
- " DatabaseCatalog(\n",
- " name=f\"{COMPLAINT_LAKEBASE_INSTANCE_NAME}\", # Name of the UC catalog to create\n",
- " database_instance_name=COMPLAINT_LAKEBASE_INSTANCE_NAME, # Name of the database instance\n",
- " database_name=\"caspers_complaints\", # Name of the Postgres database to register (and optionally create)\n",
- " create_database_if_not_exists=True # Create the database if it doesn't exist\n",
- " )\n",
- ")\n",
- "print(f\"Created new database and catalog: {catalog.name}\")\n",
- "\n",
- "add(CATALOG, \"databasecatalogs\", catalog)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "from databricks.sdk import WorkspaceClient\n",
- "from databricks.sdk.service.database import SyncedDatabaseTable, SyncedTableSpec, NewPipelineSpec, SyncedTableSchedulingPolicy\n",
- "\n",
- "# Initialize the Workspace client\n",
- "w = WorkspaceClient()\n",
- "\n",
- "# Create a synced table in a standard UC catalog\n",
- "synced_table = w.database.create_synced_database_table(\n",
- " SyncedDatabaseTable(\n",
- " name=f\"{CATALOG}.complaints.pg_complaint_responses\", # Full three-part name\n",
- " database_instance_name=instance.name, # Required for standard catalogs\n",
- " logical_database_name=\"caspers_complaints\", # Required for standard catalogs\n",
- " spec=SyncedTableSpec(\n",
- " source_table_full_name=f\"{CATALOG}.complaints.complaint_responses\",\n",
- " primary_key_columns=[\"complaint_id\"],\n",
- " scheduling_policy=SyncedTableSchedulingPolicy.CONTINUOUS,\n",
- " create_database_objects_if_missing=True, # Create database/schema if needed\n",
- " new_pipeline_spec=NewPipelineSpec(\n",
- " storage_catalog=\"storage_catalog\",\n",
- " storage_schema=\"storage_schema\"\n",
- " )\n",
- " ),\n",
- " )\n",
- ")\n",
- "print(f\"Created synced table: {synced_table.name}\")\n",
- "add(CATALOG, \"pipelines\", synced_table.data_synchronization_status)"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "name": "python",
- "version": "3.9.0"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/stages/lakebase.ipynb b/stages/lakebase.ipynb
deleted file mode 100644
index d13e7f4..0000000
--- a/stages/lakebase.ipynb
+++ /dev/null
@@ -1,232 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {
- "byteLimit": 2048000,
- "rowLimit": 10000
- },
- "inputWidgets": {},
- "nuid": "1c4c079b-307d-4445-9f4d-4bb65c2a9bbe",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "CATALOG = dbutils.widgets.get(\"CATALOG\")\n",
- "REFUNDMANAGER_LAKEBASE_INSTANCE_NAME = f\"{CATALOG}refundmanager\""
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {
- "byteLimit": 2048000,
- "rowLimit": 10000
- },
- "inputWidgets": {},
- "nuid": "2e691724-d672-4857-82a3-ad2b2114417c",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "%pip install databricks-sdk --upgrade"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {
- "byteLimit": 2048000,
- "rowLimit": 10000
- },
- "inputWidgets": {},
- "nuid": "7160a660-ea15-4e86-9c93-166728a0dec2",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "from databricks.sdk import WorkspaceClient\n",
- "from databricks.sdk.service.database import DatabaseInstance\n",
- "import uuid\n",
- "import time\n",
- "\n",
- "import sys\n",
- "sys.path.append('../utils')\n",
- "from uc_state import add\n",
- "\n",
- "# Initialize the Workspace client\n",
- "w = WorkspaceClient()\n",
- "\n",
- "UNIQUE = str(uuid.uuid4())[:8]\n",
- "\n",
- "# Create a database instance\n",
- "instance = w.database.create_database_instance(\n",
- " DatabaseInstance(\n",
- " name=f\"{REFUNDMANAGER_LAKEBASE_INSTANCE_NAME}\",\n",
- " capacity=\"CU_1\"\n",
- " )\n",
- ")\n",
- "\n",
- "print(f\"Created database instance: {instance.name}\")\n",
- "add(CATALOG, \"databaseinstances\", {\"name\": instance.name})\n",
- "print(f\"Connection endpoint: {instance.response.read_write_dns}\")\n",
- "\n",
- "# block until it's actually ready\n",
- "print(\"Waiting for database instance to be available...\")\n",
- "while True:\n",
- " if str(w.database.get_database_instance(instance.name).state) == \"DatabaseInstanceState.AVAILABLE\":\n",
- " print(str(w.database.get_database_instance(instance.name).state))\n",
- " break\n",
- " time.sleep(10)\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {
- "byteLimit": 2048000,
- "rowLimit": 10000
- },
- "inputWidgets": {},
- "nuid": "9fe12046-6846-4ff8-9ed0-c263ca634a2f",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "# create a database `caspers` in the lakebase instance\n",
- "# register it to UC as concat of CATALOG-INSTANCE_NAME (params)\n",
- "\n",
- "from databricks.sdk.service.database import DatabaseCatalog\n",
- "\n",
- "catalog = w.database.create_database_catalog(\n",
- " DatabaseCatalog(\n",
- " name=f\"{REFUNDMANAGER_LAKEBASE_INSTANCE_NAME}\", # Name of the UC catalog to create\n",
- " database_instance_name=REFUNDMANAGER_LAKEBASE_INSTANCE_NAME, # Name of the database instance\n",
- " database_name=\"caspers\", # Name of the Postgres database to register (and optionally create)\n",
- " create_database_if_not_exists=True # Create the database if it doesn't exist\n",
- " )\n",
- ")\n",
- "print(f\"Created new database and catalog: {catalog.name}\")\n",
- "\n",
- "add(CATALOG, \"databasecatalogs\", catalog)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {
- "byteLimit": 2048000,
- "rowLimit": 10000
- },
- "inputWidgets": {},
- "nuid": "3f104624-0728-4605-aa89-0c0a18f294b7",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "from databricks.sdk import WorkspaceClient\n",
- "from databricks.sdk.service.database import SyncedDatabaseTable, SyncedTableSpec, NewPipelineSpec, SyncedTableSchedulingPolicy\n",
- "\n",
- "# Initialize the Workspace client\n",
- "w = WorkspaceClient()\n",
- "\n",
- "# Create a synced table in a standard UC catalog\n",
- "synced_table = w.database.create_synced_database_table(\n",
- " SyncedDatabaseTable(\n",
- " name=f\"{CATALOG}.recommender.pg_recommendations\", # Full three-part name\n",
- " database_instance_name=instance.name, # Required for standard catalogs\n",
- " logical_database_name=\"caspers\", # Required for standard catalogs\n",
- " spec=SyncedTableSpec(\n",
- " source_table_full_name=f\"{CATALOG}.recommender.refund_recommendations\",\n",
- " primary_key_columns=[\"order_id\"],\n",
- " scheduling_policy=SyncedTableSchedulingPolicy.CONTINUOUS,\n",
- " create_database_objects_if_missing=True, # Create database/schema if needed\n",
- " new_pipeline_spec=NewPipelineSpec(\n",
- " storage_catalog=\"storage_catalog\",\n",
- " storage_schema=\"storage_schema\"\n",
- " )\n",
- " ),\n",
- " )\n",
- ")\n",
- "print(f\"Created synced table: {synced_table.name}\")\n",
- "add(CATALOG, \"pipelines\", synced_table.data_synchronization_status)"
- ]
- }
- ],
- "metadata": {
- "application/vnd.databricks.v1+notebook": {
- "computePreferences": null,
- "dashboards": [],
- "environmentMetadata": {
- "base_environment": "",
- "environment_version": "3"
- },
- "inputWidgetPreferences": null,
- "language": "python",
- "notebookMetadata": {
- "pythonIndentUnit": 4
- },
- "notebookName": "lakebase",
- "widgets": {
- "CATALOG": {
- "currentValue": "cazzper",
- "nuid": "73cb92d5-f843-4e41-92d6-5081124a02c9",
- "typedWidgetInfo": {
- "autoCreated": false,
- "defaultValue": "",
- "label": "",
- "name": "CATALOG",
- "options": {
- "validationRegex": null,
- "widgetDisplayType": "Text"
- },
- "parameterDataType": "String"
- },
- "widgetInfo": {
- "defaultValue": "",
- "label": "",
- "name": "CATALOG",
- "options": {
- "autoCreated": false,
- "validationRegex": null,
- "widgetType": "text"
- },
- "widgetType": "text"
- }
- }
- }
- },
- "language_info": {
- "name": "python"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 0
-}
diff --git a/stages/lakeflow.ipynb b/stages/lakeflow.ipynb
index 27b8234..bcac856 100644
--- a/stages/lakeflow.ipynb
+++ b/stages/lakeflow.ipynb
@@ -1,226 +1,343 @@
{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {},
- "inputWidgets": {},
- "nuid": "14a10bae-42e6-4e06-81fa-c6d2336d157a",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "source": [
- "\n",
- "### Raw Data\n",
- "\n",
- "This notebook assumes raw_data has already run and creates a medallion architecture declarative pipeline to normalize the event stream and create summary tables"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {},
- "inputWidgets": {},
- "nuid": "2953476c-3a7a-406c-b3f7-c1b45f1f7ca0",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "%pip install --upgrade databricks-sdk"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {},
- "inputWidgets": {},
- "nuid": "e8704c18-8794-4ac2-8d7e-1c69bb3b4371",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": "CATALOG = dbutils.widgets.get(\"CATALOG\")\nEVENTS_VOLUME = dbutils.widgets.get(\"EVENTS_VOLUME\")\nSIMULATOR_SCHEMA = dbutils.widgets.get(\"SIMULATOR_SCHEMA\")\nPIPELINE_SCHEDULE_MINUTES = int(dbutils.widgets.get(\"PIPELINE_SCHEDULE_MINUTES\"))\n\n# 0 = continuous mode, N > 0 = triggered mode with schedule every N minutes\ncontinuous_mode = (PIPELINE_SCHEDULE_MINUTES == 0)\n\nprint(f\"Pipeline mode: {'Continuous' if continuous_mode else f'Triggered (every {PIPELINE_SCHEDULE_MINUTES} minutes)'}\")"
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {},
- "inputWidgets": {},
- "nuid": "69dfc806-58b2-43d5-b13e-29d2661ca099",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": "import os\n\nfrom databricks.sdk import WorkspaceClient\nfrom databricks.sdk.service import pipelines\n\nw = WorkspaceClient()\n\nroot_abs_path = os.path.abspath(\"../pipelines/order_items\")\nroot_dbx_path = root_abs_path.replace(\n os.environ.get(\"DATABRICKS_WORKSPACE_ROOT\", \"/Workspace\"),\n \"/Workspace\"\n)\n\ncreated = w.pipelines.create(\n catalog=CATALOG,\n schema='lakeflow',\n continuous=continuous_mode,\n name=f\"Order Items Medallion Declarative Pipeline\",\n serverless=True,\n configuration={\n \"RAW_DATA_CATALOG\":CATALOG,\n \"RAW_DATA_SCHEMA\":SIMULATOR_SCHEMA,\n \"RAW_DATA_VOLUME\":EVENTS_VOLUME\n },\n root_path=root_dbx_path,\n libraries=[pipelines.PipelineLibrary(glob=pipelines.PathPattern(include=f\"{root_dbx_path}/**\"))],\n allow_duplicate_names=True\n)\n\nprint(f\"Created pipeline_id={created.pipeline_id} (continuous={continuous_mode})\")\n\n# If triggered mode, create a scheduled job to run pipeline updates\nif not continuous_mode:\n import databricks.sdk.service.jobs as j\n \n cron_expression = f\"0 0/{PIPELINE_SCHEDULE_MINUTES} * * * ?\"\n \n pipeline_job = w.jobs.create(\n name=f\"Pipeline Update Scheduler (every {PIPELINE_SCHEDULE_MINUTES} min)\",\n tasks=[\n j.Task(\n task_key=\"update_pipeline\",\n pipeline_task=j.PipelineTask(\n pipeline_id=created.pipeline_id\n )\n )\n ],\n schedule=j.CronSchedule(\n quartz_cron_expression=cron_expression,\n timezone_id=\"UTC\",\n pause_status=j.PauseStatus.UNPAUSED\n )\n )\n \n print(f\"Created scheduled job_id={pipeline_job.job_id} to run pipeline every {PIPELINE_SCHEDULE_MINUTES} minutes\")\n \n # Register the job with uc_state\n import sys\n sys.path.append('../utils')\n from uc_state import add\n add(CATALOG, \"jobs\", pipeline_job)\n \n # Run immediately once\n w.jobs.run_now(job_id=pipeline_job.job_id)\n print(f\"Started initial pipeline run\")"
- },
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {},
- "inputWidgets": {},
- "nuid": "78fe42c2-32da-4526-ac02-99094ac85d0a",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "# wait for the tables to be created\n",
- "# future stages may require their existence before being able to be run\n",
- "\n",
- "import time\n",
- "\n",
- "while True:\n",
- " try:\n",
- " if spark.catalog.tableExists(f\"{CATALOG}.lakeflow.all_events\"):\n",
- " break\n",
- " except Exception:\n",
- " pass\n",
- " time.sleep(5)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {},
- "inputWidgets": {},
- "nuid": "24a507e5-644b-42de-91d4-3214146ae409",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "# Also add to UC-state\n",
- "import sys\n",
- "sys.path.append('../utils')\n",
- "from uc_state import add\n",
- "\n",
- "add(CATALOG, \"pipelines\", created)"
- ]
- }
- ],
- "metadata": {
- "application/vnd.databricks.v1+notebook": {
- "computePreferences": null,
- "dashboards": [],
- "environmentMetadata": {
- "base_environment": "",
- "environment_version": "3"
- },
- "inputWidgetPreferences": null,
- "language": "python",
- "notebookMetadata": {
- "pythonIndentUnit": 4
- },
- "notebookName": "lakeflow",
- "widgets": {
- "CATALOG": {
- "currentValue": "",
- "nuid": "1b879c13-e967-45d3-9848-122420dc1369",
- "typedWidgetInfo": {
- "autoCreated": false,
- "defaultValue": "",
- "label": null,
- "name": "CATALOG",
- "options": {
- "validationRegex": null,
- "widgetDisplayType": "Text"
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "application/vnd.databricks.v1+cell": {
+ "cellMetadata": {},
+ "inputWidgets": {},
+ "nuid": "14a10bae-42e6-4e06-81fa-c6d2336d157a",
+ "showTitle": false,
+ "tableResultSettingsMap": {},
+ "title": ""
+ }
},
- "parameterDataType": "String"
- },
- "widgetInfo": {
- "defaultValue": "",
- "label": null,
- "name": "CATALOG",
- "options": {
- "autoCreated": false,
- "validationRegex": null,
- "widgetType": "text"
+ "source": [
+ "\n",
+ "### Raw Data\n",
+ "\n",
+ "This notebook assumes raw_data has already run and creates a medallion architecture declarative pipeline to normalize the event stream and create summary tables"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 0,
+ "metadata": {
+ "application/vnd.databricks.v1+cell": {
+ "cellMetadata": {},
+ "inputWidgets": {},
+ "nuid": "2953476c-3a7a-406c-b3f7-c1b45f1f7ca0",
+ "showTitle": false,
+ "tableResultSettingsMap": {},
+ "title": ""
+ }
},
- "widgetType": "text"
- }
+ "outputs": [],
+ "source": [
+ "%pip install --upgrade databricks-sdk"
+ ]
},
- "EVENTS_VOLUME": {
- "currentValue": "",
- "nuid": "267538f4-e4bf-4e45-a232-83760867245e",
- "typedWidgetInfo": {
- "autoCreated": false,
- "defaultValue": "",
- "label": null,
- "name": "EVENTS_VOLUME",
- "options": {
- "validationRegex": null,
- "widgetDisplayType": "Text"
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "application/vnd.databricks.v1+cell": {
+ "cellMetadata": {},
+ "inputWidgets": {},
+ "nuid": "e8704c18-8794-4ac2-8d7e-1c69bb3b4371",
+ "showTitle": false,
+ "tableResultSettingsMap": {},
+ "title": ""
+ }
},
- "parameterDataType": "String"
- },
- "widgetInfo": {
- "defaultValue": "",
- "label": null,
- "name": "EVENTS_VOLUME",
- "options": {
- "autoCreated": false,
- "validationRegex": null,
- "widgetType": "text"
+ "outputs": [],
+ "source": [
+ "CATALOG = dbutils.widgets.get(\"CATALOG\")\n",
+ "EVENTS_VOLUME = dbutils.widgets.get(\"EVENTS_VOLUME\")\n",
+ "SIMULATOR_SCHEMA = dbutils.widgets.get(\"SIMULATOR_SCHEMA\")\n",
+ "PIPELINE_SCHEDULE_MINUTES = int(dbutils.widgets.get(\"PIPELINE_SCHEDULE_MINUTES\"))\n",
+ "\n",
+ "# 0 = continuous mode, N > 0 = triggered mode with schedule every N minutes\n",
+ "continuous_mode = (PIPELINE_SCHEDULE_MINUTES == 0)\n",
+ "\n",
+ "print(f\"Pipeline mode: {'Continuous' if continuous_mode else f'Triggered (every {PIPELINE_SCHEDULE_MINUTES} minutes)'}\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "application/vnd.databricks.v1+cell": {
+ "cellMetadata": {},
+ "inputWidgets": {},
+ "nuid": "69dfc806-58b2-43d5-b13e-29d2661ca099",
+ "showTitle": false,
+ "tableResultSettingsMap": {},
+ "title": ""
+ }
},
- "widgetType": "text"
- }
+ "outputs": [],
+ "source": [
+ "import os\n",
+ "from typing import Optional\n",
+ "\n",
+ "from databricks.sdk import WorkspaceClient\n",
+ "from databricks.sdk.service import pipelines\n",
+ "\n",
+ "w = WorkspaceClient()\n",
+ "\n",
+ "PIPELINE_NAME = \"Order Items Medallion Declarative Pipeline\"\n",
+ "\n",
+ "root_abs_path = os.path.abspath(\"../pipelines/order_items\")\n",
+ "root_dbx_path = root_abs_path.replace(\n",
+ " os.environ.get(\"DATABRICKS_WORKSPACE_ROOT\", \"/Workspace\"),\n",
+ " \"/Workspace\"\n",
+ ")\n",
+ "\n",
+ "\n",
+ "def find_existing_pipeline_id(name: str, root_path: str) -> Optional[str]:\n",
+ " for pipeline_state in w.pipelines.list_pipelines():\n",
+ " pipeline_name = getattr(pipeline_state, \"name\", None)\n",
+ " pipeline_id = getattr(pipeline_state, \"pipeline_id\", None)\n",
+ "\n",
+ " if pipeline_name != name or not pipeline_id:\n",
+ " continue\n",
+ "\n",
+ " details = w.pipelines.get(pipeline_id=pipeline_id)\n",
+ " spec = details.spec\n",
+ " if spec and spec.root_path == root_path:\n",
+ " return pipeline_id\n",
+ "\n",
+ " return None\n",
+ "\n",
+ "\n",
+ "pipeline_id: Optional[str] = None\n",
+ "all_events_table = f\"{CATALOG}.lakeflow.all_events\"\n",
+ "\n",
+ "if spark.catalog.tableExists(all_events_table):\n",
+ " print(\n",
+ " f\"{all_events_table} already exists; skipping pipeline create/update to avoid table ownership conflicts.\"\n",
+ " )\n",
+ "else:\n",
+ " existing_pipeline_id = find_existing_pipeline_id(PIPELINE_NAME, root_dbx_path)\n",
+ "\n",
+ " pipeline_spec = dict(\n",
+ " catalog=CATALOG,\n",
+ " schema=\"lakeflow\",\n",
+ " continuous=continuous_mode,\n",
+ " name=PIPELINE_NAME,\n",
+ " serverless=True,\n",
+ " configuration={\n",
+ " \"RAW_DATA_CATALOG\": CATALOG,\n",
+ " \"RAW_DATA_SCHEMA\": SIMULATOR_SCHEMA,\n",
+ " \"RAW_DATA_VOLUME\": EVENTS_VOLUME,\n",
+ " },\n",
+ " root_path=root_dbx_path,\n",
+ " libraries=[\n",
+ " pipelines.PipelineLibrary(\n",
+ " glob=pipelines.PathPattern(include=f\"{root_dbx_path}/**\")\n",
+ " )\n",
+ " ],\n",
+ " )\n",
+ "\n",
+ " if existing_pipeline_id:\n",
+ " w.pipelines.update(pipeline_id=existing_pipeline_id, **pipeline_spec)\n",
+ " pipeline_id = existing_pipeline_id\n",
+ " print(f\"Updated existing pipeline_id={pipeline_id} (continuous={continuous_mode})\")\n",
+ " else:\n",
+ " created = w.pipelines.create(allow_duplicate_names=False, **pipeline_spec)\n",
+ " pipeline_id = created.pipeline_id\n",
+ " print(f\"Created pipeline_id={pipeline_id} (continuous={continuous_mode})\")\n",
+ "\n",
+ " # If triggered mode, create a scheduled job to run pipeline updates\n",
+ " if not continuous_mode:\n",
+ " import databricks.sdk.service.jobs as j\n",
+ "\n",
+ " cron_expression = f\"0 0/{PIPELINE_SCHEDULE_MINUTES} * * * ?\"\n",
+ "\n",
+ " pipeline_job = w.jobs.create(\n",
+ " name=f\"Pipeline Update Scheduler (every {PIPELINE_SCHEDULE_MINUTES} min)\",\n",
+ " tasks=[\n",
+ " j.Task(\n",
+ " task_key=\"update_pipeline\",\n",
+ " pipeline_task=j.PipelineTask(\n",
+ " pipeline_id=pipeline_id\n",
+ " )\n",
+ " )\n",
+ " ],\n",
+ " schedule=j.CronSchedule(\n",
+ " quartz_cron_expression=cron_expression,\n",
+ " timezone_id=\"UTC\",\n",
+ " pause_status=j.PauseStatus.UNPAUSED\n",
+ " )\n",
+ " )\n",
+ "\n",
+ " print(f\"Created scheduled job_id={pipeline_job.job_id} to run pipeline every {PIPELINE_SCHEDULE_MINUTES} minutes\")\n",
+ "\n",
+ " # Register the job with uc_state\n",
+ " import sys\n",
+ " sys.path.append('../utils')\n",
+ " from uc_state import add\n",
+ " add(CATALOG, \"jobs\", pipeline_job)\n",
+ "\n",
+ " # Run immediately once\n",
+ " w.jobs.run_now(job_id=pipeline_job.job_id)\n",
+ " print(\"Started initial pipeline run\")"
+ ]
},
- "SIMULATOR_SCHEMA": {
- "currentValue": "",
- "nuid": "1eebe964-7af5-44a0-9d82-804fa88755f7",
- "typedWidgetInfo": {
- "autoCreated": false,
- "defaultValue": "",
- "label": null,
- "name": "SIMULATOR_SCHEMA",
- "options": {
- "validationRegex": null,
- "widgetDisplayType": "Text"
+ {
+ "cell_type": "code",
+ "execution_count": 0,
+ "metadata": {
+ "application/vnd.databricks.v1+cell": {
+ "cellMetadata": {},
+ "inputWidgets": {},
+ "nuid": "78fe42c2-32da-4526-ac02-99094ac85d0a",
+ "showTitle": false,
+ "tableResultSettingsMap": {},
+ "title": ""
+ }
},
- "parameterDataType": "String"
- },
- "widgetInfo": {
- "defaultValue": "",
- "label": null,
- "name": "SIMULATOR_SCHEMA",
- "options": {
- "autoCreated": false,
- "validationRegex": null,
- "widgetType": "text"
+ "outputs": [],
+ "source": [
+ "# wait for the tables to be created\n",
+ "# future stages may require their existence before being able to be run\n",
+ "\n",
+ "import time\n",
+ "\n",
+ "while True:\n",
+ " try:\n",
+ " if spark.catalog.tableExists(f\"{CATALOG}.lakeflow.all_events\"):\n",
+ " break\n",
+ " except Exception:\n",
+ " pass\n",
+ " time.sleep(5)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "application/vnd.databricks.v1+cell": {
+ "cellMetadata": {},
+ "inputWidgets": {},
+ "nuid": "24a507e5-644b-42de-91d4-3214146ae409",
+ "showTitle": false,
+ "tableResultSettingsMap": {},
+ "title": ""
+ }
},
- "widgetType": "text"
- }
+ "outputs": [],
+ "source": [
+ "# Also add to UC-state\n",
+ "if pipeline_id:\n",
+ " import sys\n",
+ " sys.path.append('../utils')\n",
+ " from uc_state import add\n",
+ "\n",
+ " add(CATALOG, \"pipelines\", {\"pipeline_id\": pipeline_id, \"name\": PIPELINE_NAME})"
+ ]
+ }
+ ],
+ "metadata": {
+ "application/vnd.databricks.v1+notebook": {
+ "computePreferences": null,
+ "dashboards": [],
+ "environmentMetadata": {
+ "base_environment": "",
+ "environment_version": "3"
+ },
+ "inputWidgetPreferences": null,
+ "language": "python",
+ "notebookMetadata": {
+ "pythonIndentUnit": 4
+ },
+ "notebookName": "lakeflow",
+ "widgets": {
+ "CATALOG": {
+ "currentValue": "",
+ "nuid": "1b879c13-e967-45d3-9848-122420dc1369",
+ "typedWidgetInfo": {
+ "autoCreated": false,
+ "defaultValue": "",
+ "label": null,
+ "name": "CATALOG",
+ "options": {
+ "validationRegex": null,
+ "widgetDisplayType": "Text"
+ },
+ "parameterDataType": "String"
+ },
+ "widgetInfo": {
+ "defaultValue": "",
+ "label": null,
+ "name": "CATALOG",
+ "options": {
+ "autoCreated": false,
+ "validationRegex": null,
+ "widgetType": "text"
+ },
+ "widgetType": "text"
+ }
+ },
+ "EVENTS_VOLUME": {
+ "currentValue": "",
+ "nuid": "267538f4-e4bf-4e45-a232-83760867245e",
+ "typedWidgetInfo": {
+ "autoCreated": false,
+ "defaultValue": "",
+ "label": null,
+ "name": "EVENTS_VOLUME",
+ "options": {
+ "validationRegex": null,
+ "widgetDisplayType": "Text"
+ },
+ "parameterDataType": "String"
+ },
+ "widgetInfo": {
+ "defaultValue": "",
+ "label": null,
+ "name": "EVENTS_VOLUME",
+ "options": {
+ "autoCreated": false,
+ "validationRegex": null,
+ "widgetType": "text"
+ },
+ "widgetType": "text"
+ }
+ },
+ "SIMULATOR_SCHEMA": {
+ "currentValue": "",
+ "nuid": "1eebe964-7af5-44a0-9d82-804fa88755f7",
+ "typedWidgetInfo": {
+ "autoCreated": false,
+ "defaultValue": "",
+ "label": null,
+ "name": "SIMULATOR_SCHEMA",
+ "options": {
+ "validationRegex": null,
+ "widgetDisplayType": "Text"
+ },
+ "parameterDataType": "String"
+ },
+ "widgetInfo": {
+ "defaultValue": "",
+ "label": null,
+ "name": "SIMULATOR_SCHEMA",
+ "options": {
+ "autoCreated": false,
+ "validationRegex": null,
+ "widgetType": "text"
+ },
+ "widgetType": "text"
+ }
+ }
+ }
+ },
+ "language_info": {
+ "name": "python"
}
- }
},
- "language_info": {
- "name": "python"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 0
-}
\ No newline at end of file
+ "nbformat": 4,
+ "nbformat_minor": 0
+}
diff --git a/stages/raw_data.ipynb b/stages/raw_data.ipynb
index 870a49a..345e85e 100644
--- a/stages/raw_data.ipynb
+++ b/stages/raw_data.ipynb
@@ -1,472 +1,529 @@
{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {},
- "inputWidgets": {},
- "nuid": "b4b235ce-c6b8-4573-bca3-2719632d4efc",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "source": [
- "\n",
- "### Raw Data\n",
- "\n",
- "This notebook will bootstrap Caspers raw data into the provided catalog and schema"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {},
- "inputWidgets": {},
- "nuid": "e7ea4bbf-d953-4c42-8c04-046392612a75",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "%pip install --upgrade databricks-sdk"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {},
- "inputWidgets": {},
- "nuid": "f9100bbc-b3e0-4fff-8aac-af90d83f426e",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "dbutils.library.restartPython()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {},
- "inputWidgets": {},
- "nuid": "8ed7fe02-e440-448a-a4e7-a3bb957e70b0",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "CATALOG = dbutils.widgets.get(\"CATALOG\")\n",
- "EVENTS_VOLUME = dbutils.widgets.get(\"EVENTS_VOLUME\")\n",
- "SIMULATOR_SCHEMA = dbutils.widgets.get(\"SIMULATOR_SCHEMA\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {},
- "inputWidgets": {},
- "nuid": "82e95cb7-3475-45f3-ba9f-1c508cda06eb",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "source": [
- "\n",
- "##### Create main catalog, simulator related schemas and volumes"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {},
- "inputWidgets": {},
- "nuid": "326b836a-0c13-4239-b013-18cc6f7c889e",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "%sql\n",
- "CREATE CATALOG IF NOT EXISTS ${CATALOG};\n",
- "CREATE SCHEMA IF NOT EXISTS ${CATALOG}.${SIMULATOR_SCHEMA};\n",
- "CREATE VOLUME IF NOT EXISTS ${CATALOG}.${SIMULATOR_SCHEMA}.${EVENTS_VOLUME};"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {},
- "inputWidgets": {},
- "nuid": "3c2c4b0e-8a4c-459c-bb7b-67b19e5e6b1d",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "source": [
- "\n",
- "##### Create tables from parquet data"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {},
- "inputWidgets": {},
- "nuid": "21a83f2b-d1d3-4e33-bd43-ef7c5fd5baf1",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "import pandas as pd\n",
- "\n",
- "spark.createDataFrame(pd.read_parquet(\"../data/dimensional/brands.parquet\")) \\\n",
- " .write.mode(\"overwrite\").saveAsTable(f\"{CATALOG}.{SIMULATOR_SCHEMA}.brands\")\n",
- "spark.createDataFrame(pd.read_parquet(\"../data/dimensional/menus.parquet\")) \\\n",
- " .write.mode(\"overwrite\").saveAsTable(f\"{CATALOG}.{SIMULATOR_SCHEMA}.menus\")\n",
- "spark.createDataFrame(pd.read_parquet(\"../data/dimensional/categories.parquet\")) \\\n",
- " .write.mode(\"overwrite\").saveAsTable(f\"{CATALOG}.{SIMULATOR_SCHEMA}.categories\")\n",
- "spark.createDataFrame(pd.read_parquet(\"../data/dimensional/items.parquet\")) \\\n",
- " .write.mode(\"overwrite\").saveAsTable(f\"{CATALOG}.{SIMULATOR_SCHEMA}.items\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {},
- "inputWidgets": {},
- "nuid": "859d56d9-d728-44b2-be13-39b1a67e59e0",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "source": [
- "\n",
- "##### Start data generation"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {},
- "inputWidgets": {},
- "nuid": "2d57d601-108d-4ea2-a47d-8c52b0a8adba",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "source": [
- "\n",
- "##### Read all .jsons in ./data/generator/configs. Each json file represents a location."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {},
- "inputWidgets": {},
- "nuid": "ded63223-6426-43ec-aa6f-953e16879833",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "import glob\n",
- "import os\n",
- "\n",
- "# Get all JSON file paths under the directory\n",
- "json_paths = glob.glob(\"../data/generator/configs/*.json\")\n",
- "\n",
- "# Read each file's content as a string and collect into a dict mapping filename to content\n",
- "config_json_map = {}\n",
- "for path in json_paths:\n",
- " filename = os.path.basename(path)\n",
- " with open(path, \"r\", encoding=\"utf-8\") as f:\n",
- " config_json_map[filename] = f.read()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {},
- "inputWidgets": {},
- "nuid": "2f9074aa-5853-492d-a54b-c31a3470dc25",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "source": [
- "\n",
- "##### Start a job for each of the config jsons found in ./data/generator/configs"
- ]
- },
- {
- "cell_type": "code",
- "source": "# Filter locations based on LOCATIONS parameter\nlocations_param = dbutils.widgets.get(\"LOCATIONS\")\nif locations_param.lower() != \"all\":\n selected = [loc.strip() for loc in locations_param.split(\",\")]\n config_json_map = {k: v for k, v in config_json_map.items() if k in selected}\n print(f\"Running selected locations: {list(config_json_map.keys())}\")\nelse:\n print(f\"Running all locations: {list(config_json_map.keys())}\")",
- "metadata": {},
- "execution_count": null,
- "outputs": []
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {},
- "inputWidgets": {},
- "nuid": "fb5b2f59-c6a9-4158-bbdf-9397fe473e18",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "from databricks.sdk import WorkspaceClient\n",
- "import databricks.sdk.service.jobs as j\n",
- "import os, json\n",
- "\n",
- "w = WorkspaceClient()\n",
- "\n",
- "# Resolve the workspace notebook path (keeps your approach)\n",
- "notebook_abs_path = os.path.abspath(\"../data/generator/generator\")\n",
- "notebook_dbx_path = notebook_abs_path.replace(\n",
- " os.environ.get(\"DATABRICKS_WORKSPACE_ROOT\", \"/Workspace\"),\n",
- " \"/Workspace\"\n",
- ")\n",
- "\n",
- "import sys\n",
- "sys.path.append('../utils')\n",
- "from uc_state import add\n",
- "\n",
- "for filename, json_content in config_json_map.items():\n",
- " job_name = f\"Order Flow Generator: {filename}\"\n",
- "\n",
- " # Ensure SIM_CFG_JSON is a JSON string (Jobs widget params are strings)\n",
- " sim_cfg_str = json_content if isinstance(json_content, str) else json.dumps(json_content)\n",
- "\n",
- " job = w.jobs.create(\n",
- " name=job_name,\n",
- " tasks=[\n",
- " j.Task(\n",
- " task_key=\"order_flow_generator\",\n",
- " notebook_task=j.NotebookTask(\n",
- " notebook_path=notebook_dbx_path,\n",
- " base_parameters={\n",
- " \"CATALOG\": CATALOG,\n",
- " \"VOLUME\": EVENTS_VOLUME,\n",
- " \"SCHEMA\": SIMULATOR_SCHEMA,\n",
- " \"SIM_CFG_JSON\": sim_cfg_str,\n",
- " },\n",
- " )\n",
- " )\n",
- " ],\n",
- " )\n",
- " print(f\"Created job_id={job.job_id} for {filename}\")\n",
- " add(CATALOG, \"jobs\", job)\n",
- " w.jobs.run_now(job_id=job.job_id)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {},
- "inputWidgets": {},
- "nuid": "8f0b77b8-650e-4ad9-a538-fbf39163af37",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "source": [
- "\n",
- "##### Blocking cell to wait for some data to arrive at the volume.\n",
- "\n",
- "The lakeflow declarative pipeline that comes next infers the schema from existing data.\n",
- "\n",
- "Lakeflow Jobs doesn't have a file arrival trigger at the task level (yet?)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {},
- "inputWidgets": {},
- "nuid": "f5b6e3df-ece6-477f-a057-ff2c97c6f888",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "import time\n",
- "\n",
- "# Construct the path to the volume where JSONs will arrive\n",
- "volume_path = f\"/Volumes/{CATALOG}/{SIMULATOR_SCHEMA}/{EVENTS_VOLUME}\"\n",
- "\n",
- "def wait_for_data(path, timeout=300, poll_interval=5):\n",
- " \"\"\"\n",
- " Wait until at least one file appears in the given path.\n",
- " Args:\n",
- " path (str): The directory to watch.\n",
- " timeout (int): Maximum seconds to wait.\n",
- " poll_interval (int): Seconds between checks.\n",
- " Raises:\n",
- " TimeoutError: If no file appears within the timeout.\n",
- " \"\"\"\n",
- " start = time.time()\n",
- " while time.time() - start < timeout:\n",
- " files = dbutils.fs.ls(path)\n",
- " if any(f.size > 0 for f in files if not f.path.endswith('/')):\n",
- " print(\"Data arrived. Safe to proceed.\")\n",
- " return\n",
- " time.sleep(poll_interval)\n",
- " raise TimeoutError(f\"No data found in {path} after {timeout} seconds.\")\n",
- "\n",
- "wait_for_data(volume_path)"
- ]
- }
- ],
- "metadata": {
- "application/vnd.databricks.v1+notebook": {
- "computePreferences": null,
- "dashboards": [],
- "environmentMetadata": {
- "base_environment": "",
- "environment_version": "3"
- },
- "inputWidgetPreferences": null,
- "language": "python",
- "notebookMetadata": {
- "pythonIndentUnit": 4
- },
- "notebookName": "raw_data",
- "widgets": {
- "CATALOG": {
- "currentValue": "",
- "nuid": "39bc9f65-25ff-4696-83c3-89b3d5ecc686",
- "typedWidgetInfo": {
- "autoCreated": false,
- "defaultValue": "",
- "label": "",
- "name": "CATALOG",
- "options": {
- "validationRegex": null,
- "widgetDisplayType": "Text"
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "application/vnd.databricks.v1+cell": {
+ "cellMetadata": {},
+ "inputWidgets": {},
+ "nuid": "b4b235ce-c6b8-4573-bca3-2719632d4efc",
+ "showTitle": false,
+ "tableResultSettingsMap": {},
+ "title": ""
+ }
+ },
+ "source": [
+ "\n",
+ "### Raw Data\n",
+ "\n",
+ "This notebook will bootstrap Caspers raw data into the provided catalog and schema"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "application/vnd.databricks.v1+cell": {
+ "cellMetadata": {},
+ "inputWidgets": {},
+ "nuid": "e7ea4bbf-d953-4c42-8c04-046392612a75",
+ "showTitle": false,
+ "tableResultSettingsMap": {},
+ "title": ""
+ }
+ },
+ "source": [
+ "%pip install --upgrade databricks-sdk"
+ ],
+ "execution_count": 0,
+ "outputs": []
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "application/vnd.databricks.v1+cell": {
+ "cellMetadata": {},
+ "inputWidgets": {},
+ "nuid": "f9100bbc-b3e0-4fff-8aac-af90d83f426e",
+ "showTitle": false,
+ "tableResultSettingsMap": {},
+ "title": ""
+ }
+ },
+ "source": [
+ "dbutils.library.restartPython()"
+ ],
+ "execution_count": 0,
+ "outputs": []
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "application/vnd.databricks.v1+cell": {
+ "cellMetadata": {},
+ "inputWidgets": {},
+ "nuid": "8ed7fe02-e440-448a-a4e7-a3bb957e70b0",
+ "showTitle": false,
+ "tableResultSettingsMap": {},
+ "title": ""
+ }
+ },
+ "source": [
+ "CATALOG = dbutils.widgets.get(\"CATALOG\")\n",
+ "EVENTS_VOLUME = dbutils.widgets.get(\"EVENTS_VOLUME\")\n",
+ "SIMULATOR_SCHEMA = dbutils.widgets.get(\"SIMULATOR_SCHEMA\")"
+ ],
+ "execution_count": 0,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "application/vnd.databricks.v1+cell": {
+ "cellMetadata": {},
+ "inputWidgets": {},
+ "nuid": "82e95cb7-3475-45f3-ba9f-1c508cda06eb",
+ "showTitle": false,
+ "tableResultSettingsMap": {},
+ "title": ""
+ }
+ },
+ "source": [
+ "\n",
+ "##### Create main catalog, simulator related schemas and volumes"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "application/vnd.databricks.v1+cell": {
+ "cellMetadata": {},
+ "inputWidgets": {},
+ "nuid": "326b836a-0c13-4239-b013-18cc6f7c889e",
+ "showTitle": false,
+ "tableResultSettingsMap": {},
+ "title": ""
+ }
+ },
+ "source": [
+ "%sql\n",
+ "CREATE CATALOG IF NOT EXISTS ${CATALOG};\n",
+ "CREATE SCHEMA IF NOT EXISTS ${CATALOG}.${SIMULATOR_SCHEMA};\n",
+ "CREATE VOLUME IF NOT EXISTS ${CATALOG}.${SIMULATOR_SCHEMA}.${EVENTS_VOLUME};"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "application/vnd.databricks.v1+cell": {
+ "cellMetadata": {},
+ "inputWidgets": {},
+ "nuid": "3c2c4b0e-8a4c-459c-bb7b-67b19e5e6b1d",
+ "showTitle": false,
+ "tableResultSettingsMap": {},
+ "title": ""
+ }
},
- "parameterDataType": "String"
- },
- "widgetInfo": {
- "defaultValue": "",
- "label": "",
- "name": "CATALOG",
- "options": {
- "autoCreated": false,
- "validationRegex": null,
- "widgetType": "text"
+ "source": [
+ "\n",
+ "##### Create tables from parquet data"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "application/vnd.databricks.v1+cell": {
+ "cellMetadata": {},
+ "inputWidgets": {},
+ "nuid": "21a83f2b-d1d3-4e33-bd43-ef7c5fd5baf1",
+ "showTitle": false,
+ "tableResultSettingsMap": {},
+ "title": ""
+ }
+ },
+ "source": [
+ "import pandas as pd\n",
+ "\n",
+ "spark.createDataFrame(pd.read_parquet(\"../data/dimensional/brands.parquet\")) \\\n",
+ " .write.mode(\"overwrite\").saveAsTable(f\"{CATALOG}.{SIMULATOR_SCHEMA}.brands\")\n",
+ "spark.createDataFrame(pd.read_parquet(\"../data/dimensional/menus.parquet\")) \\\n",
+ " .write.mode(\"overwrite\").saveAsTable(f\"{CATALOG}.{SIMULATOR_SCHEMA}.menus\")\n",
+ "spark.createDataFrame(pd.read_parquet(\"../data/dimensional/categories.parquet\")) \\\n",
+ " .write.mode(\"overwrite\").saveAsTable(f\"{CATALOG}.{SIMULATOR_SCHEMA}.categories\")\n",
+ "spark.createDataFrame(pd.read_parquet(\"../data/dimensional/items.parquet\")) \\\n",
+ " .write.mode(\"overwrite\").saveAsTable(f\"{CATALOG}.{SIMULATOR_SCHEMA}.items\")"
+ ],
+ "execution_count": 0,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "application/vnd.databricks.v1+cell": {
+ "cellMetadata": {},
+ "inputWidgets": {},
+ "nuid": "859d56d9-d728-44b2-be13-39b1a67e59e0",
+ "showTitle": false,
+ "tableResultSettingsMap": {},
+ "title": ""
+ }
+ },
+ "source": [
+ "\n",
+ "##### Start data generation"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "application/vnd.databricks.v1+cell": {
+ "cellMetadata": {},
+ "inputWidgets": {},
+ "nuid": "2d57d601-108d-4ea2-a47d-8c52b0a8adba",
+ "showTitle": false,
+ "tableResultSettingsMap": {},
+ "title": ""
+ }
+ },
+ "source": [
+ "\n",
+ "##### Read all .jsons in ./data/generator/configs. Each json file represents a location."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "application/vnd.databricks.v1+cell": {
+ "cellMetadata": {},
+ "inputWidgets": {},
+ "nuid": "ded63223-6426-43ec-aa6f-953e16879833",
+ "showTitle": false,
+ "tableResultSettingsMap": {},
+ "title": ""
+ }
},
- "widgetType": "text"
- }
+ "source": [
+ "import glob\n",
+ "import os\n",
+ "\n",
+ "# Get all JSON file paths under the directory\n",
+ "json_paths = glob.glob(\"../data/generator/configs/*.json\")\n",
+ "\n",
+ "# Read each file's content as a string and collect into a dict mapping filename to content\n",
+ "config_json_map = {}\n",
+ "for path in json_paths:\n",
+ " filename = os.path.basename(path)\n",
+ " with open(path, \"r\", encoding=\"utf-8\") as f:\n",
+ " config_json_map[filename] = f.read()"
+ ],
+ "execution_count": 0,
+ "outputs": []
},
- "EVENTS_VOLUME": {
- "currentValue": "",
- "nuid": "06d6cc56-f73c-4948-b84f-f0f12cd47a94",
- "typedWidgetInfo": {
- "autoCreated": false,
- "defaultValue": "",
- "label": "",
- "name": "EVENTS_VOLUME",
- "options": {
- "validationRegex": null,
- "widgetDisplayType": "Text"
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "application/vnd.databricks.v1+cell": {
+ "cellMetadata": {},
+ "inputWidgets": {},
+ "nuid": "2f9074aa-5853-492d-a54b-c31a3470dc25",
+ "showTitle": false,
+ "tableResultSettingsMap": {},
+ "title": ""
+ }
},
- "parameterDataType": "String"
- },
- "widgetInfo": {
- "defaultValue": "",
- "label": "",
- "name": "EVENTS_VOLUME",
- "options": {
- "autoCreated": false,
- "validationRegex": null,
- "widgetType": "text"
+ "source": [
+ "\n",
+ "##### Start a job for each of the config jsons found in ./data/generator/configs"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {},
+ "source": [
+ "# Filter locations based on LOCATIONS parameter\n",
+ "locations_param = dbutils.widgets.get(\"LOCATIONS\")\n",
+ "if locations_param.lower() != \"all\":\n",
+ " selected = [loc.strip() for loc in locations_param.split(\",\")]\n",
+ " config_json_map = {k: v for k, v in config_json_map.items() if k in selected}\n",
+ " print(f\"Running selected locations: {list(config_json_map.keys())}\")\n",
+ "else:\n",
+ " print(f\"Running all locations: {list(config_json_map.keys())}\")"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "application/vnd.databricks.v1+cell": {
+ "cellMetadata": {},
+ "inputWidgets": {},
+ "nuid": "fb5b2f59-c6a9-4158-bbdf-9397fe473e18",
+ "showTitle": false,
+ "tableResultSettingsMap": {},
+ "title": ""
+ }
},
- "widgetType": "text"
- }
+ "source": [
+ "from databricks.sdk import WorkspaceClient\n",
+ "import databricks.sdk.service.jobs as j\n",
+ "import os, json\n",
+ "\n",
+ "w = WorkspaceClient()\n",
+ "\n",
+ "# Resolve the workspace notebook path (keeps your approach)\n",
+ "notebook_abs_path = os.path.abspath(\"../data/generator/generator\")\n",
+ "notebook_dbx_path = notebook_abs_path.replace(\n",
+ " os.environ.get(\"DATABRICKS_WORKSPACE_ROOT\", \"/Workspace\"),\n",
+ " \"/Workspace\"\n",
+ ")\n",
+ "\n",
+ "import sys\n",
+ "sys.path.append('../utils')\n",
+ "from uc_state import add\n",
+ "\n",
+ "for filename, json_content in config_json_map.items():\n",
+ " job_name = f\"Order Flow Generator: {filename}\"\n",
+ "\n",
+ " # Ensure SIM_CFG_JSON is a JSON string (Jobs widget params are strings)\n",
+ " sim_cfg_str = json_content if isinstance(json_content, str) else json.dumps(json_content)\n",
+ "\n",
+ " new_settings = j.JobSettings(\n",
+ " name=job_name,\n",
+ " tasks=[\n",
+ " j.Task(\n",
+ " task_key=\"order_flow_generator\",\n",
+ " notebook_task=j.NotebookTask(\n",
+ " notebook_path=notebook_dbx_path,\n",
+ " base_parameters={\n",
+ " \"CATALOG\": CATALOG,\n",
+ " \"VOLUME\": EVENTS_VOLUME,\n",
+ " \"SCHEMA\": SIMULATOR_SCHEMA,\n",
+ " \"SIM_CFG_JSON\": sim_cfg_str,\n",
+ " },\n",
+ " )\n",
+ " )\n",
+ " ],\n",
+ " )\n",
+ "\n",
+ " matches = sorted(\n",
+ " [job for job in w.jobs.list(name=job_name) if job.settings and job.settings.name == job_name],\n",
+ " key=lambda x: x.created_time or 0,\n",
+ " reverse=True,\n",
+ " )\n",
+ "\n",
+ " if matches:\n",
+ " target_job_id = matches[0].job_id\n",
+ " w.jobs.reset(job_id=target_job_id, new_settings=new_settings)\n",
+ " job = w.jobs.get(job_id=target_job_id)\n",
+ " print(f\"Updated existing job_id={target_job_id} for {filename}\")\n",
+ "\n",
+ " for stale in matches[1:]:\n",
+ " stale_id = stale.job_id\n",
+ " for run in w.jobs.list_runs(job_id=stale_id, active_only=True):\n",
+ " w.jobs.cancel_run(run_id=run.run_id)\n",
+ " w.jobs.delete(job_id=stale_id)\n",
+ " print(f\"Deleted stale duplicate job_id={stale_id} for {filename}\")\n",
+ " else:\n",
+ " settings_payload = new_settings.as_dict() if hasattr(new_settings, \"as_dict\") else new_settings\n",
+ " created = w.api_client.do(\"POST\", \"/api/2.2/jobs/create\", body=settings_payload)\n",
+ " target_job_id = created[\"job_id\"] if isinstance(created, dict) else created.job_id\n",
+ " job = w.jobs.get(job_id=target_job_id)\n",
+ " print(f\"Created job_id={target_job_id} for {filename}\")\n",
+ "\n",
+ " add(CATALOG, \"jobs\", job)\n",
+ " # Keep exactly one active run per generator job during redeploys.\n",
+ " active_runs = list(w.jobs.list_runs(job_id=target_job_id, active_only=True))\n",
+ " running_runs = []\n",
+ " queued_runs = []\n",
+ "\n",
+ " for run in active_runs:\n",
+ " life_cycle_state = str(getattr(getattr(run, \"state\", None), \"life_cycle_state\", \"\")).upper()\n",
+ " if \"RUNNING\" in life_cycle_state:\n",
+ " running_runs.append(run)\n",
+ " elif any(s in life_cycle_state for s in [\"QUEUED\", \"PENDING\", \"BLOCKED\"]):\n",
+ " queued_runs.append(run)\n",
+ "\n",
+ " for queued in queued_runs:\n",
+ " w.jobs.cancel_run(run_id=queued.run_id)\n",
+ " print(f\"Cancelled queued run_id={queued.run_id} for job_id={target_job_id}\")\n",
+ "\n",
+ " if running_runs:\n",
+ " print(\n",
+ " f\"Skipped run_now for {filename}; already running run_id={running_runs[0].run_id} \"\n",
+ " f\"for job_id={target_job_id}\"\n",
+ " )\n",
+ " else:\n",
+ " run_now = w.jobs.run_now(job_id=target_job_id)\n",
+ " print(f\"Triggered run_id={run_now.run_id} for job_id={target_job_id}\")"
+ ],
+ "execution_count": null,
+ "outputs": []
},
- "SIMULATOR_SCHEMA": {
- "currentValue": "",
- "nuid": "70241427-8b78-43ec-8435-9688f17f69d9",
- "typedWidgetInfo": {
- "autoCreated": false,
- "defaultValue": "",
- "label": "",
- "name": "SIMULATOR_SCHEMA",
- "options": {
- "validationRegex": null,
- "widgetDisplayType": "Text"
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "application/vnd.databricks.v1+cell": {
+ "cellMetadata": {},
+ "inputWidgets": {},
+ "nuid": "8f0b77b8-650e-4ad9-a538-fbf39163af37",
+ "showTitle": false,
+ "tableResultSettingsMap": {},
+ "title": ""
+ }
},
- "parameterDataType": "String"
- },
- "widgetInfo": {
- "defaultValue": "",
- "label": "",
- "name": "SIMULATOR_SCHEMA",
- "options": {
- "autoCreated": false,
- "validationRegex": null,
- "widgetType": "text"
+ "source": [
+ "\n",
+ "##### Blocking cell to wait for some data to arrive at the volume.\n",
+ "\n",
+ "The lakeflow declarative pipeline that comes next infers the schema from existing data.\n",
+ "\n",
+ "Lakeflow Jobs doesn't have a file arrival trigger at the task level (yet?)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "application/vnd.databricks.v1+cell": {
+ "cellMetadata": {},
+ "inputWidgets": {},
+ "nuid": "f5b6e3df-ece6-477f-a057-ff2c97c6f888",
+ "showTitle": false,
+ "tableResultSettingsMap": {},
+ "title": ""
+ }
},
- "widgetType": "text"
- }
+ "source": [
+ "import time\n",
+ "\n",
+ "# Construct the path to the volume where JSONs will arrive\n",
+ "volume_path = f\"/Volumes/{CATALOG}/{SIMULATOR_SCHEMA}/{EVENTS_VOLUME}\"\n",
+ "\n",
+ "def wait_for_data(path, timeout=300, poll_interval=5):\n",
+ " \"\"\"\n",
+ " Wait until at least one file appears in the given path.\n",
+ " Args:\n",
+ " path (str): The directory to watch.\n",
+ " timeout (int): Maximum seconds to wait.\n",
+ " poll_interval (int): Seconds between checks.\n",
+ " Raises:\n",
+ " TimeoutError: If no file appears within the timeout.\n",
+ " \"\"\"\n",
+ " start = time.time()\n",
+ " while time.time() - start < timeout:\n",
+ " files = dbutils.fs.ls(path)\n",
+ " if any(f.size > 0 for f in files if not f.path.endswith('/')):\n",
+ " print(\"Data arrived. Safe to proceed.\")\n",
+ " return\n",
+ " time.sleep(poll_interval)\n",
+ " raise TimeoutError(f\"No data found in {path} after {timeout} seconds.\")\n",
+ "\n",
+ "wait_for_data(volume_path)"
+ ],
+ "execution_count": 0,
+ "outputs": []
+ }
+ ],
+ "metadata": {
+ "application/vnd.databricks.v1+notebook": {
+ "computePreferences": null,
+ "dashboards": [],
+ "environmentMetadata": {
+ "base_environment": "",
+ "environment_version": "3"
+ },
+ "inputWidgetPreferences": null,
+ "language": "python",
+ "notebookMetadata": {
+ "pythonIndentUnit": 4
+ },
+ "notebookName": "raw_data",
+ "widgets": {
+ "CATALOG": {
+ "currentValue": "",
+ "nuid": "39bc9f65-25ff-4696-83c3-89b3d5ecc686",
+ "typedWidgetInfo": {
+ "autoCreated": false,
+ "defaultValue": "",
+ "label": "",
+ "name": "CATALOG",
+ "options": {
+ "validationRegex": null,
+ "widgetDisplayType": "Text"
+ },
+ "parameterDataType": "String"
+ },
+ "widgetInfo": {
+ "defaultValue": "",
+ "label": "",
+ "name": "CATALOG",
+ "options": {
+ "autoCreated": false,
+ "validationRegex": null,
+ "widgetType": "text"
+ },
+ "widgetType": "text"
+ }
+ },
+ "EVENTS_VOLUME": {
+ "currentValue": "",
+ "nuid": "06d6cc56-f73c-4948-b84f-f0f12cd47a94",
+ "typedWidgetInfo": {
+ "autoCreated": false,
+ "defaultValue": "",
+ "label": "",
+ "name": "EVENTS_VOLUME",
+ "options": {
+ "validationRegex": null,
+ "widgetDisplayType": "Text"
+ },
+ "parameterDataType": "String"
+ },
+ "widgetInfo": {
+ "defaultValue": "",
+ "label": "",
+ "name": "EVENTS_VOLUME",
+ "options": {
+ "autoCreated": false,
+ "validationRegex": null,
+ "widgetType": "text"
+ },
+ "widgetType": "text"
+ }
+ },
+ "SIMULATOR_SCHEMA": {
+ "currentValue": "",
+ "nuid": "70241427-8b78-43ec-8435-9688f17f69d9",
+ "typedWidgetInfo": {
+ "autoCreated": false,
+ "defaultValue": "",
+ "label": "",
+ "name": "SIMULATOR_SCHEMA",
+ "options": {
+ "validationRegex": null,
+ "widgetDisplayType": "Text"
+ },
+ "parameterDataType": "String"
+ },
+ "widgetInfo": {
+ "defaultValue": "",
+ "label": "",
+ "name": "SIMULATOR_SCHEMA",
+ "options": {
+ "autoCreated": false,
+ "validationRegex": null,
+ "widgetType": "text"
+ },
+ "widgetType": "text"
+ }
+ }
+ }
+ },
+ "language_info": {
+ "name": "python"
}
- }
},
- "language_info": {
- "name": "python"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 0
+ "nbformat": 4,
+ "nbformat_minor": 0
}
\ No newline at end of file
diff --git a/stages/refunder_agent.ipynb b/stages/refunder_agent.ipynb
deleted file mode 100644
index a8c1169..0000000
--- a/stages/refunder_agent.ipynb
+++ /dev/null
@@ -1,950 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {},
- "inputWidgets": {},
- "nuid": "2be128f4-c802-4fe3-930c-4e5e8ec1d10c",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "source": [
- "\n",
- "#### refunder agent\n",
- "\n",
- "this notebook creates an agent with tools to suggest refunds for orders"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {},
- "inputWidgets": {},
- "nuid": "5ffc7e90-b728-4e83-8cad-3eda46e941e2",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "source": [
- "#### Tool & View Registration"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {
- "byteLimit": 2048000,
- "implicitDf": true,
- "rowLimit": 10000
- },
- "inputWidgets": {},
- "nuid": "76e0583b-b9cf-41d7-aa21-9bc159ca4da2",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "%sql\n",
- "CREATE SCHEMA IF NOT EXISTS ${CATALOG}.ai;"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {
- "byteLimit": 2048000,
- "implicitDf": true,
- "rowLimit": 10000
- },
- "inputWidgets": {},
- "nuid": "a140cb0f-afb5-4c1a-8417-6191aedd8fa7",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": "%sql\nCREATE OR REPLACE FUNCTION ${CATALOG}.ai.get_order_details(oid STRING COMMENT 'order id of the order')\nRETURNS TABLE (\n body STRING COMMENT 'Body of the event',\n event_type STRING COMMENT 'The type of event',\n order_id STRING COMMENT 'The order id',\n ts STRING COMMENT 'The timestamp of the event',\n location STRING COMMENT 'the location of the order'\n)\nCOMMENT 'Returns all events associated with the order id (oid)'\nRETURN\n SELECT ae.body, ae.event_type, ae.order_id, ae.ts, loc.name as location\n FROM ${CATALOG}.lakeflow.all_events ae\n LEFT JOIN ${CATALOG}.simulator.locations loc ON ae.location_id = loc.location_id\n WHERE ae.order_id = oid;"
- },
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {
- "byteLimit": 2048000,
- "implicitDf": true,
- "rowLimit": 10000
- },
- "inputWidgets": {},
- "nuid": "55d1bf76-afca-4d7d-86e3-0b78bdfaf467",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "%sql\n",
- "CREATE OR REPLACE FUNCTION ${CATALOG}.ai.get_order_delivery_time(oid STRING COMMENT 'order id of the order')\n",
- "RETURNS TABLE (\n",
- " order_id STRING COMMENT 'The order id',\n",
- " creation_time TIMESTAMP COMMENT 'The timestamp of the first event for the order',\n",
- " delivery_time TIMESTAMP COMMENT 'The timestamp of the last event for the order',\n",
- " duration_minutes FLOAT COMMENT 'The total duration from the first to the last event in minutes'\n",
- ")\n",
- "COMMENT 'Returns the first event time, last event time, and total duration for a given order id.'\n",
- "RETURN\n",
- " WITH MinMaxTimestamps AS (\n",
- " SELECT\n",
- " MIN(try_to_timestamp(ts)) as first_event_time,\n",
- " MAX(try_to_timestamp(ts)) as last_event_time\n",
- " FROM\n",
- " ${CATALOG}.lakeflow.all_events\n",
- " WHERE\n",
- " order_id = oid\n",
- " )\n",
- " SELECT\n",
- " oid as order_id,\n",
- " first_event_time AS creation_time,\n",
- " last_event_time AS delivery_time,\n",
- " CAST(\n",
- " try_divide(\n",
- " (UNIX_TIMESTAMP(last_event_time) - UNIX_TIMESTAMP(first_event_time)),\n",
- " 60\n",
- " ) AS FLOAT\n",
- " ) AS duration_minutes\n",
- " FROM\n",
- " MinMaxTimestamps;"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {
- "byteLimit": 2048000,
- "implicitDf": true,
- "rowLimit": 10000
- },
- "inputWidgets": {},
- "nuid": "b1707682-0913-44bd-b05b-90547ee230fd",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": "%sql\nCREATE OR REPLACE VIEW ${CATALOG}.ai.order_delivery_times_per_location_view AS\nWITH order_times AS (\n SELECT\n ae.order_id,\n loc.name as location,\n MAX(CASE WHEN ae.event_type = 'order_created' THEN try_to_timestamp(ae.ts) END) AS order_created_time,\n MAX(CASE WHEN ae.event_type = 'delivered' THEN try_to_timestamp(ae.ts) END) AS delivered_time\n FROM\n ${CATALOG}.lakeflow.all_events ae\n LEFT JOIN ${CATALOG}.simulator.locations loc ON ae.location_id = loc.location_id\n WHERE\n try_to_timestamp(ae.ts) >= CURRENT_TIMESTAMP() - INTERVAL 1 DAY\n GROUP BY\n ae.order_id,\n loc.name\n),\ntotal_order_times AS (\n SELECT\n order_id,\n location,\n (UNIX_TIMESTAMP(delivered_time) - UNIX_TIMESTAMP(order_created_time)) / 60 AS total_order_time_minutes\n FROM\n order_times\n WHERE\n order_created_time IS NOT NULL\n AND delivered_time IS NOT NULL\n)\nSELECT\n location,\n PERCENTILE(total_order_time_minutes, 0.50) AS P50,\n PERCENTILE(total_order_time_minutes, 0.75) AS P75,\n PERCENTILE(total_order_time_minutes, 0.99) AS P99\nFROM\n total_order_times\nGROUP BY\n location"
- },
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {
- "byteLimit": 2048000,
- "implicitDf": true,
- "rowLimit": 10000
- },
- "inputWidgets": {},
- "nuid": "32eca549-67b1-4dc0-9e1a-3e9f131c0e1c",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "%sql\n",
- "CREATE OR REPLACE FUNCTION ${CATALOG}.ai.get_location_timings(loc STRING COMMENT 'Location name as a string')\n",
- "RETURNS TABLE (\n",
- " location STRING COMMENT 'Location of the order source',\n",
- " P50 FLOAT COMMENT '50th percentile',\n",
- " P75 FLOAT COMMENT '75th percentile',\n",
- " P99 FLOAT COMMENT '99th percentile'\n",
- ")\n",
- "COMMENT 'Returns the 50/75/99th percentile of total delivery times for locations'\n",
- "RETURN\n",
- " SELECT location, P50, P75, P99\n",
- " FROM ${CATALOG}.ai.order_delivery_times_per_location_view AS odlt\n",
- " WHERE odlt.location = loc;"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {},
- "inputWidgets": {},
- "nuid": "e7f5e202-58a3-462e-9f2c-2b61b4366f97",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "source": [
- "#### Model"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {
- "byteLimit": 2048000,
- "rowLimit": 10000
- },
- "inputWidgets": {},
- "nuid": "05805ea8-65b7-49c1-90c7-ce255c257ef1",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "%pip install -U -qqqq mlflow-skinny[databricks] langgraph==0.3.4 databricks-langchain databricks-agents uv\n",
- "dbutils.library.restartPython()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {
- "byteLimit": 2048000,
- "rowLimit": 10000
- },
- "inputWidgets": {},
- "nuid": "70c1a6e2-fc53-4337-b919-957896f2322d",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "CATALOG = dbutils.widgets.get(\"CATALOG\")\n",
- "LLM_MODEL = dbutils.widgets.get(\"LLM_MODEL\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {
- "byteLimit": 2048000,
- "rowLimit": 10000
- },
- "inputWidgets": {},
- "nuid": "e1e226ce-f3ee-4522-82fd-8bdf7121f999",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "import re\n",
- "from IPython.core.magic import register_cell_magic\n",
- "\n",
- "@register_cell_magic\n",
- "def writefilev(line, cell):\n",
- " \"\"\"\n",
- " %%writefilev file.py\n",
- " Allows {{var}} substitutions while leaving normal {} intact.\n",
- " \"\"\"\n",
- " filename = line.strip()\n",
- "\n",
- " def replacer(match):\n",
- " expr = match.group(1)\n",
- " return str(eval(expr, globals(), locals()))\n",
- "\n",
- " # Replace only double braces {{var}}\n",
- " content = re.sub(r\"\\{\\{(.*?)\\}\\}\", replacer, cell)\n",
- "\n",
- " with open(filename, \"w\") as f:\n",
- " f.write(content)\n",
- " print(f\"Wrote file with substitutions: {filename}\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {
- "byteLimit": 2048000,
- "rowLimit": 10000
- },
- "inputWidgets": {},
- "nuid": "63ddd9df-5f1c-42ea-9446-196558fd5b2c",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "%%writefilev agent.py\n",
- "from typing import Any, Generator, Optional, Sequence, Union\n",
- "\n",
- "import mlflow\n",
- "from databricks_langchain import (\n",
- " ChatDatabricks,\n",
- " VectorSearchRetrieverTool,\n",
- " DatabricksFunctionClient,\n",
- " UCFunctionToolkit,\n",
- " set_uc_function_client,\n",
- ")\n",
- "from langchain_core.language_models import LanguageModelLike\n",
- "from langchain_core.runnables import RunnableConfig, RunnableLambda\n",
- "from langchain_core.tools import BaseTool\n",
- "from langgraph.graph import END, StateGraph\n",
- "from langgraph.graph.graph import CompiledGraph\n",
- "from langgraph.graph.state import CompiledStateGraph\n",
- "from langgraph.prebuilt.tool_node import ToolNode\n",
- "from mlflow.langchain.chat_agent_langgraph import ChatAgentState, ChatAgentToolNode\n",
- "from mlflow.pyfunc import ChatAgent\n",
- "from mlflow.types.agent import (\n",
- " ChatAgentChunk,\n",
- " ChatAgentMessage,\n",
- " ChatAgentResponse,\n",
- " ChatContext,\n",
- ")\n",
- "\n",
- "mlflow.langchain.autolog()\n",
- "\n",
- "client = DatabricksFunctionClient()\n",
- "set_uc_function_client(client)\n",
- "\n",
- "############################################\n",
- "# Define your LLM endpoint and system prompt\n",
- "############################################\n",
- "LLM_ENDPOINT_NAME = f\"{{LLM_MODEL}}\"\n",
- "llm = ChatDatabricks(endpoint=LLM_ENDPOINT_NAME)\n",
- "\n",
- "system_prompt = \"\"\"You are RefundGPT, a CX agent responsible for refunding late food delivery orders.\n",
- "\n",
- " You can call tools to gather the information you need. Start with an `order_id`.\n",
- "\n",
- " Instructions:\n",
- " 1. Call `order_details(order_id)` first to get event history and confirm the id is valid and the order was delivered.\n",
- " 2. Figure out the delivery duration by calling `get_order_delivery_time(order_id)`.\n",
- " 3. Extract the location (either directly or from the first event's body).\n",
- " 4. Call `get_location_timings(location)` to get the P50/P75/P99 values.\n",
- " 5. Compare actual delivery time to those percentiles to decide on a fair refund.\n",
- "\n",
- " Only provide refunds for late orders, and use only the tool call results to determine whether a refund is appropriate.\n",
- "\n",
- " Do not provide any refund for orders arriving before the P75 delivery time value.\n",
- "\n",
- " Output a single-line JSON with these fields:\n",
- " - `refund_usd` (float),\n",
- " - `refund_class` (\"none\" | \"partial\" | \"full\"),\n",
- " - `reason` (short human explanation of whether the order was late and, if late, how late the order was)\n",
- "\n",
- " You must return only the JSON. No extra text or markdown.\"\"\"\n",
- "\n",
- "###############################################################################\n",
- "## Define tools for your agent, enabling it to retrieve data or take actions\n",
- "## beyond text generation\n",
- "## To create and see usage examples of more tools, see\n",
- "## https://docs.databricks.com/generative-ai/agent-framework/agent-tool.html\n",
- "###############################################################################\n",
- "tools = []\n",
- "\n",
- "uc_tool_names = [f\"{{CATALOG}}.ai.get_order_details\", \n",
- " f\"{{CATALOG}}.ai.get_location_timings\",\n",
- " f\"{{CATALOG}}.ai.get_order_delivery_time\"]\n",
- "uc_toolkit = UCFunctionToolkit(function_names=uc_tool_names)\n",
- "tools.extend(uc_toolkit.tools)\n",
- "\n",
- "#####################\n",
- "## Define agent logic\n",
- "#####################\n",
- "\n",
- "\n",
- "def create_tool_calling_agent(\n",
- " model: LanguageModelLike,\n",
- " tools: Union[Sequence[BaseTool], ToolNode],\n",
- " system_prompt: Optional[str] = None,\n",
- ") -> CompiledGraph:\n",
- " model = model.bind_tools(tools)\n",
- "\n",
- " # Define the function that determines which node to go to\n",
- " def should_continue(state: ChatAgentState):\n",
- " messages = state[\"messages\"]\n",
- " last_message = messages[-1]\n",
- " # If there are function calls, continue. else, end\n",
- " if last_message.get(\"tool_calls\"):\n",
- " return \"continue\"\n",
- " else:\n",
- " return \"end\"\n",
- "\n",
- " if system_prompt:\n",
- " preprocessor = RunnableLambda(\n",
- " lambda state: [{\"role\": \"system\", \"content\": system_prompt}]\n",
- " + state[\"messages\"]\n",
- " )\n",
- " else:\n",
- " preprocessor = RunnableLambda(lambda state: state[\"messages\"])\n",
- " model_runnable = preprocessor | model\n",
- "\n",
- " def call_model(\n",
- " state: ChatAgentState,\n",
- " config: RunnableConfig,\n",
- " ):\n",
- " response = model_runnable.invoke(state, config)\n",
- "\n",
- " return {\"messages\": [response]}\n",
- "\n",
- " workflow = StateGraph(ChatAgentState)\n",
- "\n",
- " workflow.add_node(\"agent\", RunnableLambda(call_model))\n",
- " workflow.add_node(\"tools\", ChatAgentToolNode(tools))\n",
- "\n",
- " workflow.set_entry_point(\"agent\")\n",
- " workflow.add_conditional_edges(\n",
- " \"agent\",\n",
- " should_continue,\n",
- " {\n",
- " \"continue\": \"tools\",\n",
- " \"end\": END,\n",
- " },\n",
- " )\n",
- " workflow.add_edge(\"tools\", \"agent\")\n",
- "\n",
- " return workflow.compile()\n",
- "\n",
- "\n",
- "class LangGraphChatAgent(ChatAgent):\n",
- " def __init__(self, agent: CompiledStateGraph):\n",
- " self.agent = agent\n",
- "\n",
- " def predict(\n",
- " self,\n",
- " messages: list[ChatAgentMessage],\n",
- " context: Optional[ChatContext] = None,\n",
- " custom_inputs: Optional[dict[str, Any]] = None,\n",
- " ) -> ChatAgentResponse:\n",
- " request = {\"messages\": self._convert_messages_to_dict(messages)}\n",
- "\n",
- " messages = []\n",
- " for event in self.agent.stream(request, stream_mode=\"updates\"):\n",
- " for node_data in event.values():\n",
- " messages.extend(\n",
- " ChatAgentMessage(**msg) for msg in node_data.get(\"messages\", [])\n",
- " )\n",
- " return ChatAgentResponse(messages=messages)\n",
- "\n",
- " def predict_stream(\n",
- " self,\n",
- " messages: list[ChatAgentMessage],\n",
- " context: Optional[ChatContext] = None,\n",
- " custom_inputs: Optional[dict[str, Any]] = None,\n",
- " ) -> Generator[ChatAgentChunk, None, None]:\n",
- " request = {\"messages\": self._convert_messages_to_dict(messages)}\n",
- " for event in self.agent.stream(request, stream_mode=\"updates\"):\n",
- " for node_data in event.values():\n",
- " yield from (\n",
- " ChatAgentChunk(**{\"delta\": msg}) for msg in node_data[\"messages\"]\n",
- " )\n",
- "\n",
- "\n",
- "# Create the agent object, and specify it as the agent object to use when\n",
- "# loading the agent back for inference via mlflow.models.set_model()\n",
- "agent = create_tool_calling_agent(llm, tools, system_prompt)\n",
- "AGENT = LangGraphChatAgent(agent)\n",
- "mlflow.models.set_model(AGENT)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {
- "byteLimit": 2048000,
- "rowLimit": 10000
- },
- "inputWidgets": {},
- "nuid": "6a909c3e-4fd0-4cdd-98af-93a7ccb3badb",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "# get an actual order_id\n",
- "sample_order_id = spark.sql(f\"\"\"\n",
- " SELECT order_id \n",
- " FROM {CATALOG}.lakeflow.all_events \n",
- " WHERE event_type='delivered'\n",
- " LIMIT 1\n",
- "\"\"\").collect()[0]['order_id']"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {
- "byteLimit": 2048000,
- "rowLimit": 10000
- },
- "inputWidgets": {},
- "nuid": "0c672421-c8d0-4252-92d1-576dd01f0f72",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "assert sample_order_id is not None\n",
- "print(sample_order_id)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {
- "byteLimit": 2048000,
- "rowLimit": 10000
- },
- "inputWidgets": {},
- "nuid": "38ee737e-0495-4856-a87a-60bac7baf043",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "import mlflow\n",
- "from agent import LLM_ENDPOINT_NAME, tools\n",
- "from databricks_langchain import VectorSearchRetrieverTool\n",
- "from mlflow.models.resources import DatabricksFunction, DatabricksServingEndpoint\n",
- "from pkg_resources import get_distribution\n",
- "from unitycatalog.ai.langchain.toolkit import UnityCatalogTool\n",
- "\n",
- "resources = [DatabricksServingEndpoint(endpoint_name=LLM_ENDPOINT_NAME)]\n",
- "for tool in tools:\n",
- " resources.append(DatabricksFunction(function_name=tool.uc_function_name))\n",
- "\n",
- "input_example = {\n",
- " \"messages\": [\n",
- " {\n",
- " \"role\": \"user\",\n",
- " \"content\": f\"{sample_order_id}\"\n",
- " }\n",
- " ]\n",
- "}\n",
- "\n",
- "with mlflow.start_run():\n",
- " logged_agent_info = mlflow.pyfunc.log_model(\n",
- " name=\"agent_v2\",\n",
- " python_model=\"agent.py\",\n",
- " input_example=input_example,\n",
- " resources=resources,\n",
- " pip_requirements=[\n",
- " f\"databricks-connect=={get_distribution('databricks-connect').version}\",\n",
- " f\"mlflow=={get_distribution('mlflow').version}\",\n",
- " f\"databricks-langchain=={get_distribution('databricks-langchain').version}\",\n",
- " f\"langgraph=={get_distribution('langgraph').version}\",\n",
- " ],\n",
- " )\n",
- "\n",
- "mlflow.set_active_model(model_id = logged_agent_info.model_id)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {},
- "inputWidgets": {},
- "nuid": "93c5ffb0-ed1b-4e86-809e-9b7af90656e1",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "source": [
- "#### eval"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {
- "byteLimit": 2048000,
- "rowLimit": 10000
- },
- "inputWidgets": {},
- "nuid": "72348da2-fd71-4413-8e0a-5cb16ed03d17",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "# sample 10 order_ids\n",
- "refund_queries = [\n",
- " row['order_id'] for row in spark.sql(f\"\"\"\n",
- " SELECT order_id \n",
- " FROM {CATALOG}.lakeflow.all_events \n",
- " WHERE event_type='delivered'\n",
- " LIMIT 10\n",
- " \"\"\").collect()\n",
- "]\n",
- "\n",
- "# wrap in correct input schema\n",
- "data = []\n",
- "for query in refund_queries:\n",
- " data.append(\n",
- " {\n",
- " \"inputs\": {\n",
- " \"messages\": [\n",
- " {\n",
- " \"role\": \"user\",\n",
- " \"content\": query,\n",
- " }\n",
- " ]\n",
- " },\n",
- " }\n",
- " )\n",
- "\n",
- "print(data)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {
- "byteLimit": 2048000,
- "rowLimit": 10000
- },
- "inputWidgets": {},
- "nuid": "bfcf41db-e682-4ef3-964d-e5c40a07983c",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "# create guideline, run evals\n",
- "\n",
- "from mlflow.genai.scorers import Guidelines\n",
- "import mlflow\n",
- "import sys\n",
- "import os\n",
- "sys.path.append(os.getcwd())\n",
- "\n",
- "notebook_path = dbutils.notebook.entry_point.getDbutils().notebook().getContext().notebookPath().get()\n",
- "project_directory = os.path.dirname(notebook_path)\n",
- "\n",
- "# Add the project directory to the system path\n",
- "sys.path.append(project_directory)\n",
- "\n",
- "from agent import AGENT\n",
- "\n",
- "refund_reason = Guidelines(\n",
- " name=\"refund_reason\",\n",
- " guidelines=[\"If a refund is offered, its reason must relate to order timing, not to other issues such as missing components.\"]\n",
- ")\n",
- "\n",
- "\n",
- "results = mlflow.genai.evaluate(\n",
- " data=data,\n",
- " scorers=[refund_reason],\n",
- " predict_fn = lambda messages: AGENT.predict({\"messages\": messages})\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {},
- "inputWidgets": {},
- "nuid": "b2f870d6-05d0-478e-8784-98793ba8480c",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "source": [
- "#### log refunder to `UC`"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {
- "byteLimit": 2048000,
- "rowLimit": 10000
- },
- "inputWidgets": {},
- "nuid": "273249df-a966-45fc-9ddf-d7138af804b7",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "mlflow.set_registry_uri(\"databricks-uc\")\n",
- "\n",
- "UC_MODEL_NAME = f\"{CATALOG}.ai.refunder\"\n",
- "\n",
- "# register the model to UC\n",
- "uc_registered_model_info = mlflow.register_model(\n",
- " model_uri=logged_agent_info.model_uri, name=UC_MODEL_NAME\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {},
- "inputWidgets": {},
- "nuid": "bf715fb3-953c-4516-8d07-79c0d362a99e",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "source": [
- "#### deploy the agent to model serving"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {
- "byteLimit": 2048000,
- "rowLimit": 10000
- },
- "inputWidgets": {},
- "nuid": "11c0d2d9-6379-4e2c-84bf-9004dd74b6dd",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "from databricks import agents\n",
- "deployment_info = agents.deploy(\n",
- " model_name=UC_MODEL_NAME, \n",
- " model_version=uc_registered_model_info.version, \n",
- " scale_to_zero=False,\n",
- " endpoint_name=f\"{dbutils.widgets.get(\"REFUND_AGENT_ENDPOINT_NAME\")}\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {
- "byteLimit": 2048000,
- "rowLimit": 10000
- },
- "inputWidgets": {},
- "nuid": "212d8c67-af4d-48c9-88d8-aba01a22edb0",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "print(deployment_info)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {},
- "inputWidgets": {},
- "nuid": "a35fccd0-52e3-4efd-b345-83756040e098",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "source": [
- "##### record model in state"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {
- "byteLimit": 2048000,
- "rowLimit": 10000
- },
- "inputWidgets": {},
- "nuid": "ff483b29-ed19-4f2b-ba21-f398c0968ff2",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "# Also add to UC-state\n",
- "import sys\n",
- "sys.path.append('../utils')\n",
- "from uc_state import add\n",
- "\n",
- "add(dbutils.widgets.get(\"CATALOG\"), \"endpoints\", deployment_info)"
- ]
- }
- ],
- "metadata": {
- "application/vnd.databricks.v1+notebook": {
- "computePreferences": null,
- "dashboards": [],
- "environmentMetadata": {
- "base_environment": "",
- "environment_version": "3"
- },
- "inputWidgetPreferences": null,
- "language": "python",
- "notebookMetadata": {
- "mostRecentlyExecutedCommandWithImplicitDF": {
- "commandId": 5241498588668969,
- "dataframes": [
- "_sqldf"
- ]
- },
- "pythonIndentUnit": 4
- },
- "notebookName": "refunder_agent",
- "widgets": {
- "CATALOG": {
- "currentValue": "",
- "nuid": "ec6aab2b-9dae-46a5-a002-31181de04243",
- "typedWidgetInfo": {
- "autoCreated": false,
- "defaultValue": "",
- "label": "",
- "name": "CATALOG",
- "options": {
- "validationRegex": null,
- "widgetDisplayType": "Text"
- },
- "parameterDataType": "String"
- },
- "widgetInfo": {
- "defaultValue": "",
- "label": "",
- "name": "CATALOG",
- "options": {
- "autoCreated": false,
- "validationRegex": null,
- "widgetType": "text"
- },
- "widgetType": "text"
- }
- },
- "LLM_MODEL": {
- "currentValue": "",
- "nuid": "579d358e-a5e4-4925-afda-75dbb651c6c1",
- "typedWidgetInfo": {
- "autoCreated": false,
- "defaultValue": "",
- "label": "",
- "name": "LLM_MODEL",
- "options": {
- "validationRegex": null,
- "widgetDisplayType": "Text"
- },
- "parameterDataType": "String"
- },
- "widgetInfo": {
- "defaultValue": "",
- "label": "",
- "name": "LLM_MODEL",
- "options": {
- "autoCreated": false,
- "validationRegex": null,
- "widgetType": "text"
- },
- "widgetType": "text"
- }
- },
- "REFUND_AGENT_ENDPOINT_NAME": {
- "currentValue": "",
- "nuid": "ccf262a5-2c34-435f-a8f3-ea86126c6353",
- "typedWidgetInfo": {
- "autoCreated": false,
- "defaultValue": "",
- "label": "",
- "name": "REFUND_AGENT_ENDPOINT_NAME",
- "options": {
- "validationRegex": null,
- "widgetDisplayType": "Text"
- },
- "parameterDataType": "String"
- },
- "widgetInfo": {
- "defaultValue": "",
- "label": "",
- "name": "REFUND_AGENT_ENDPOINT_NAME",
- "options": {
- "autoCreated": false,
- "validationRegex": null,
- "widgetType": "text"
- },
- "widgetType": "text"
- }
- }
- }
- },
- "language_info": {
- "name": "python"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 0
-}
\ No newline at end of file
diff --git a/stages/refunder_stream.ipynb b/stages/refunder_stream.ipynb
deleted file mode 100644
index 95e4dc4..0000000
--- a/stages/refunder_stream.ipynb
+++ /dev/null
@@ -1,193 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {},
- "inputWidgets": {},
- "nuid": "d9dd8d3e-2923-4e16-9435-bd2fd134d94f",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "source": [
- "\n",
- "##### refunder stream\n",
- "\n",
- "this notebook starts a stream to score completed orders for potential refunds"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {},
- "inputWidgets": {},
- "nuid": "6d900cee-ca27-478e-a61f-c42559ce12d6",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "%pip install --upgrade databricks-sdk"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {},
- "inputWidgets": {},
- "nuid": "b1736348-0509-44af-886c-0a95ee55498b",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "#### TODO: for some reason the experiments tracing page is not registering the calls made through this, investigate that\n",
- "### update: i believe this happens because the experiment created by the task of this job (see ./jobs/refund_recommender_stream) comes from a \"notebook\" that is ephemeral (exists only for the scope of the job) and so inference calls outside the runtime of the job go nowhere"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "application/vnd.databricks.v1+cell": {
- "cellMetadata": {},
- "inputWidgets": {},
- "nuid": "f2c5360a-7c62-4ad3-9823-e381f91d31f1",
- "showTitle": false,
- "tableResultSettingsMap": {},
- "title": ""
- }
- },
- "outputs": [],
- "source": [
- "from databricks.sdk import WorkspaceClient\n",
- "import databricks.sdk.service.jobs as j\n",
- "import os, json\n",
- "\n",
- "w = WorkspaceClient()\n",
- "\n",
- "# Resolve the workspace notebook path (keeps your approach)\n",
- "notebook_abs_path = os.path.abspath(\"../jobs/refund_recommender_stream\")\n",
- "notebook_dbx_path = notebook_abs_path.replace(\n",
- " os.environ.get(\"DATABRICKS_WORKSPACE_ROOT\", \"/Workspace\"),\n",
- " \"/Workspace\"\n",
- ")\n",
- "\n",
- "job = w.jobs.create(\n",
- " name=\"Refund Recommender Stream\",\n",
- " schedule=j.CronSchedule(\n",
- " quartz_cron_expression=\"0 0/10 * * * ?\",\n",
- " timezone_id=\"UTC\",\n",
- " pause_status=j.PauseStatus.UNPAUSED),\n",
- " tasks=[\n",
- " j.Task(\n",
- " task_key=\"refund_recommender_stream\",\n",
- " notebook_task=j.NotebookTask(\n",
- " notebook_path=notebook_dbx_path,\n",
- " base_parameters={\n",
- " \"CATALOG\": dbutils.widgets.get(\"CATALOG\"),\n",
- " \"REFUND_AGENT_ENDPOINT_NAME\": dbutils.widgets.get(\"REFUND_AGENT_ENDPOINT_NAME\")\n",
- " },\n",
- " )\n",
- " )\n",
- " ],\n",
- ")\n",
- "print(f\"Created job_id={job.job_id}\")\n",
- "\n",
- "import sys\n",
- "sys.path.append('../utils')\n",
- "from uc_state import add\n",
- "\n",
- "add(dbutils.widgets.get(\"CATALOG\"), \"jobs\", job)\n",
- "\n",
- "w.jobs.run_now(job_id=job.job_id)\n"
- ]
- }
- ],
- "metadata": {
- "application/vnd.databricks.v1+notebook": {
- "computePreferences": null,
- "dashboards": [],
- "environmentMetadata": {
- "base_environment": "",
- "environment_version": "3"
- },
- "inputWidgetPreferences": null,
- "language": "python",
- "notebookMetadata": {
- "pythonIndentUnit": 4
- },
- "notebookName": "refunder_stream",
- "widgets": {
- "CATALOG": {
- "currentValue": "",
- "nuid": "4fed5096-973b-4a59-acc5-e4a96cc00360",
- "typedWidgetInfo": {
- "autoCreated": false,
- "defaultValue": "",
- "label": "",
- "name": "CATALOG",
- "options": {
- "validationRegex": null,
- "widgetDisplayType": "Text"
- },
- "parameterDataType": "String"
- },
- "widgetInfo": {
- "defaultValue": "",
- "label": "",
- "name": "CATALOG",
- "options": {
- "autoCreated": false,
- "validationRegex": null,
- "widgetType": "text"
- },
- "widgetType": "text"
- }
- },
- "REFUND_AGENT_ENDPOINT_NAME": {
- "currentValue": "",
- "nuid": "f8358127-303e-4f0e-ac3c-e686c70adce6",
- "typedWidgetInfo": {
- "autoCreated": false,
- "defaultValue": "",
- "label": "",
- "name": "REFUND_AGENT_ENDPOINT_NAME",
- "options": {
- "validationRegex": null,
- "widgetDisplayType": "Text"
- },
- "parameterDataType": "String"
- },
- "widgetInfo": {
- "defaultValue": "",
- "label": "",
- "name": "REFUND_AGENT_ENDPOINT_NAME",
- "options": {
- "autoCreated": false,
- "validationRegex": null,
- "widgetType": "text"
- },
- "widgetType": "text"
- }
- }
- }
- },
- "language_info": {
- "name": "python"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 0
-}
diff --git a/stages/support_feature_store.py b/stages/support_feature_store.py
new file mode 100644
index 0000000..1bfaa60
--- /dev/null
+++ b/stages/support_feature_store.py
@@ -0,0 +1,177 @@
+# Databricks notebook source
+# MAGIC %pip install -U -qqqq typing_extensions
+
+# COMMAND ----------
+
+import json
+import re
+from typing import Optional
+
+from pyspark.sql import functions as F
+from pyspark.sql.types import DoubleType
+from pyspark.sql.window import Window
+
+try:
+ from databricks.feature_engineering import FeatureEngineeringClient # type: ignore
+except Exception:
+ try:
+ from databricks.feature_store import FeatureStoreClient as FeatureEngineeringClient # type: ignore
+ except Exception:
+ FeatureEngineeringClient = None
+
+CATALOG = dbutils.widgets.get("CATALOG")
+SUPPORT_ONLINE_STORE_NAME = dbutils.widgets.get("SUPPORT_ONLINE_STORE_NAME")
+SUPPORT_ONLINE_STORE_CAPACITY = dbutils.widgets.get("SUPPORT_ONLINE_STORE_CAPACITY")
+SUPPORT_ONLINE_TABLE_NAME = dbutils.widgets.get("SUPPORT_ONLINE_TABLE_NAME")
+SUPPORT_RISK_ENDPOINT_NAME = dbutils.widgets.get("SUPPORT_RISK_ENDPOINT_NAME")
+
+spark.sql(f"CREATE SCHEMA IF NOT EXISTS {CATALOG}.support")
+
+base = spark.sql(
+ f"""
+ WITH latest AS (
+ SELECT support_request_id, user_id, order_id, request_text, ts, agent_response,
+ ROW_NUMBER() OVER (PARTITION BY support_request_id ORDER BY ts DESC) AS rn
+ FROM {CATALOG}.support.support_agent_reports
+ )
+ SELECT support_request_id, user_id, order_id, request_text, ts, agent_response
+ FROM latest
+ WHERE rn = 1
+ """
+)
+
+history = spark.sql(
+ f"""
+ SELECT
+ support_request_id,
+ user_id,
+ ts,
+ COUNT(*) OVER (
+ PARTITION BY user_id
+ ORDER BY ts
+ RANGE BETWEEN INTERVAL 30 DAYS PRECEDING AND CURRENT ROW
+ ) AS repeat_complaints_30d
+ FROM {CATALOG}.support.raw_support_requests
+ """
+)
+
+latest_repeat = (
+ history.withColumn(
+ "rn",
+ F.row_number().over(
+ Window.partitionBy("support_request_id").orderBy(F.col("ts").desc())
+ ),
+ )
+ .filter(F.col("rn") == 1)
+ .select("support_request_id", "repeat_complaints_30d")
+)
+
+features = (
+ base.join(latest_repeat, on="support_request_id", how="left")
+ .fillna({"repeat_complaints_30d": 1})
+ .withColumn(
+ "policy_limit_usd",
+ F.when(F.col("repeat_complaints_30d") >= 8, F.lit(10.0))
+ .when(F.col("repeat_complaints_30d") >= 4, F.lit(20.0))
+ .otherwise(F.lit(35.0)),
+ )
+)
+
+def _extract_risk_score(text: str) -> Optional[float]:
+ try:
+ obj = json.loads(text)
+ score = float(obj.get("risk_score"))
+ return max(0.0, min(1.0, score))
+ except Exception:
+ match = re.search(r"([01](?:\\.\\d+)?)", text)
+ if not match:
+ return None
+ try:
+ score = float(match.group(1))
+ return max(0.0, min(1.0, score))
+ except Exception:
+ return None
+
+
+def score_risk(request_text: str, repeat_complaints_30d: int, policy_limit_usd: float) -> float:
+ # Reliability fallback: score from deterministic signals until endpoint scoring is stable.
+ text_boost = 0.1 if ("fraud" in (request_text or "").lower() or "chargeback" in (request_text or "").lower()) else 0.0
+ repeat_boost = 0.08 * float(repeat_complaints_30d)
+ limit_penalty = 0.05 if float(policy_limit_usd) <= 10.0 else 0.0
+ return max(0.0, min(1.0, 0.15 + text_boost + repeat_boost + limit_penalty))
+
+
+risk_udf = F.udf(score_risk, DoubleType())
+
+features = features.withColumn(
+ "risk_score",
+ risk_udf(
+ F.coalesce(F.col("request_text"), F.lit("")),
+ F.coalesce(F.col("repeat_complaints_30d"), F.lit(1)),
+ F.coalesce(F.col("policy_limit_usd"), F.lit(35.0)),
+ ),
+)
+
+materialized = features.select(
+ "support_request_id",
+ "user_id",
+ "order_id",
+ "ts",
+ "repeat_complaints_30d",
+ "policy_limit_usd",
+ "risk_score",
+)
+
+materialized.write.mode("overwrite").saveAsTable(f"{CATALOG}.support.support_request_features")
+
+spark.sql(
+ f"""
+ ALTER TABLE {CATALOG}.support.support_request_features
+ SET TBLPROPERTIES ('delta.enableChangeDataFeed' = 'true')
+ """
+)
+
+try:
+ spark.sql(
+ f"""
+ ALTER TABLE {CATALOG}.support.support_request_features
+ ALTER COLUMN support_request_id SET NOT NULL
+ """
+ )
+except Exception:
+ pass
+
+try:
+ spark.sql(
+ f"""
+ ALTER TABLE {CATALOG}.support.support_request_features
+ ADD CONSTRAINT support_request_features_pk PRIMARY KEY (support_request_id)
+ """
+ )
+except Exception:
+ pass
+
+if FeatureEngineeringClient is None:
+ print(
+ "Feature engineering client package is unavailable on this runtime; "
+ "offline feature table was created but online publish was skipped."
+ )
+else:
+ fe = FeatureEngineeringClient()
+ try:
+ fe.get_online_store(name=SUPPORT_ONLINE_STORE_NAME)
+ except Exception:
+ fe.create_online_store(
+ name=SUPPORT_ONLINE_STORE_NAME,
+ capacity=SUPPORT_ONLINE_STORE_CAPACITY,
+ )
+
+ online_store = fe.get_online_store(name=SUPPORT_ONLINE_STORE_NAME)
+ fe.publish_table(
+ online_store=online_store,
+ source_table_name=f"{CATALOG}.support.support_request_features",
+ online_table_name=SUPPORT_ONLINE_TABLE_NAME,
+ publish_mode="TRIGGERED",
+ )
+
+print("Support feature store materialization complete")
diff --git a/stages/support_lakebase.ipynb b/stages/support_lakebase.ipynb
new file mode 100644
index 0000000..29a4b36
--- /dev/null
+++ b/stages/support_lakebase.ipynb
@@ -0,0 +1,314 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "##### Support Lakebase (v2 autoscaling)\n",
+ "\n",
+ "Provision a Lakebase v2 project/branch/endpoint and sync support + credit recommendation data from lakehouse."
+ ],
+ "id": "e73bba9e"
+ },
+ {
+ "cell_type": "code",
+ "metadata": {},
+ "source": [
+ "%pip install --upgrade databricks-sdk psycopg2-binary\n",
+ "%restart_python"
+ ],
+ "execution_count": null,
+ "outputs": [],
+ "id": "300f6ff0"
+ },
+ {
+ "cell_type": "code",
+ "metadata": {},
+ "source": [
+ "import re\n",
+ "import time\n",
+ "from databricks.sdk import WorkspaceClient\n",
+ "from databricks.sdk.service.postgres import Project, ProjectSpec\n",
+ "\n",
+ "dbutils.widgets.text(\"SUPPORT_APP_NAME\", \"casperskitchens-supportconsole\", \"Support app name\")\n",
+ "\n",
+ "CATALOG = dbutils.widgets.get(\"CATALOG\")\n",
+ "SUPPORT_APP_NAME = dbutils.widgets.get(\"SUPPORT_APP_NAME\")\n",
+ "w = WorkspaceClient()\n",
+ "\n",
+ "safe = re.sub(r\"[^a-z0-9-]\", \"-\", CATALOG.lower())\n",
+ "safe = re.sub(r\"-+\", \"-\", safe).strip(\"-\")\n",
+ "if not safe:\n",
+ " safe = \"support\"\n",
+ "\n",
+ "project_id = f\"{safe}-support-db\"\n",
+ "project_name = f\"projects/{project_id}\"\n",
+ "\n",
+ "try:\n",
+ " project = w.postgres.get_project(project_name)\n",
+ "except Exception:\n",
+ " op = w.postgres.create_project(\n",
+ " project_id=project_id,\n",
+ " project=Project(spec=ProjectSpec(display_name=f\"{CATALOG}-support-db\")),\n",
+ " )\n",
+ " project = op.wait()\n",
+ "\n",
+ "branches = list(w.postgres.list_branches(parent=project_name))\n",
+ "default_branch = next((b for b in branches if getattr(getattr(b, \"status\", None), \"default\", False)), branches[0])\n",
+ "branch_name = default_branch.name\n",
+ "\n",
+ "endpoints = list(w.postgres.list_endpoints(parent=branch_name))\n",
+ "if endpoints:\n",
+ " endpoint = next((e for e in endpoints if str(getattr(getattr(e, \"status\", None), \"endpoint_type\", \"\")).endswith(\"READ_WRITE\")), endpoints[0])\n",
+ "else:\n",
+ " # Should normally exist by default; wait and retry a few times before hard fail.\n",
+ " endpoint = None\n",
+ " for _ in range(12):\n",
+ " time.sleep(5)\n",
+ " endpoints = list(w.postgres.list_endpoints(parent=branch_name))\n",
+ " if endpoints:\n",
+ " endpoint = endpoints[0]\n",
+ " break\n",
+ " if endpoint is None:\n",
+ " raise RuntimeError(\"No Lakebase v2 endpoint found for support-db project\")\n",
+ "\n",
+ "endpoint_name = endpoint.name\n",
+ "endpoint_host = endpoint.status.hosts.host\n",
+ "print(f\"Project: {project_name}\")\n",
+ "print(f\"Branch: {branch_name}\")\n",
+ "print(f\"Endpoint: {endpoint_name}\")\n",
+ "print(f\"Host: {endpoint_host}\")\n",
+ "\n",
+ "spark.sql(f\"CREATE SCHEMA IF NOT EXISTS {CATALOG}.support\")\n",
+ "spark.sql(f\"\"\"\n",
+ "CREATE OR REPLACE TABLE {CATALOG}.support.lakebase_v2_config (\n",
+ " updated_at TIMESTAMP,\n",
+ " project_name STRING,\n",
+ " branch_name STRING,\n",
+ " endpoint_name STRING,\n",
+ " endpoint_host STRING,\n",
+ " database_name STRING\n",
+ ")\n",
+ "\"\"\")\n",
+ "spark.sql(\n",
+ " f\"\"\"\n",
+ " INSERT OVERWRITE {CATALOG}.support.lakebase_v2_config\n",
+ " SELECT current_timestamp(), '{project_name}', '{branch_name}', '{endpoint_name}', '{endpoint_host}', 'databricks_postgres'\n",
+ " \"\"\"\n",
+ ")\n",
+ "\n",
+ "import sys\n",
+ "sys.path.append('../utils')\n",
+ "from uc_state import add\n",
+ "\n",
+ "add(CATALOG, \"databaseinstances\", {\"name\": project_name, \"type\": \"lakebase_v2_project\"})\n",
+ "add(CATALOG, \"databasecatalogs\", {\"name\": branch_name, \"type\": \"lakebase_v2_branch\"})\n",
+ "add(CATALOG, \"pipelines\", {\"pipeline_id\": endpoint_name, \"type\": \"lakebase_v2_endpoint\"})"
+ ],
+ "execution_count": null,
+ "outputs": [],
+ "id": "a6bb5572"
+ },
+ {
+ "cell_type": "code",
+ "metadata": {},
+ "source": [
+ "import psycopg2\n",
+ "\n",
+ "\n",
+ "def quote_ident(identifier: str) -> str:\n",
+ " return '\"' + identifier.replace('\"', '\"\"') + '\"'\n",
+ "\n",
+ "\n",
+ "creds = w.postgres.generate_database_credential(endpoint=endpoint_name)\n",
+ "current_user = w.current_user.me().user_name\n",
+ "password = creds.token\n",
+ "\n",
+ "app_principal_client_ids = []\n",
+ "try:\n",
+ " app = w.apps.get(name=SUPPORT_APP_NAME)\n",
+ " if app.service_principal_client_id:\n",
+ " app_principal_client_ids.append(app.service_principal_client_id)\n",
+ " if app.oauth2_app_client_id:\n",
+ " app_principal_client_ids.append(app.oauth2_app_client_id)\n",
+ " if app.service_principal_name:\n",
+ " app_principal_client_ids.append(app.service_principal_name)\n",
+ " app_principal_client_ids = sorted(set(app_principal_client_ids))\n",
+ " print(f\"Granting Lakebase access to app principal identities: {app_principal_client_ids}\")\n",
+ "except Exception as e:\n",
+ " print(f\"Warning: could not resolve app '{SUPPORT_APP_NAME}' for grants: {e}\")\n",
+ "\n",
+ "conn = psycopg2.connect(\n",
+ " host=endpoint_host,\n",
+ " port=5432,\n",
+ " dbname=\"databricks_postgres\",\n",
+ " user=current_user,\n",
+ " password=password,\n",
+ " sslmode=\"require\",\n",
+ ")\n",
+ "conn.autocommit = False\n",
+ "\n",
+ "with conn.cursor() as cur:\n",
+ " cur.execute(\"CREATE SCHEMA IF NOT EXISTS support\")\n",
+ "\n",
+ " cur.execute(\n",
+ " \"\"\"\n",
+ " CREATE TABLE IF NOT EXISTS support.operator_actions (\n",
+ " action_id BIGSERIAL PRIMARY KEY,\n",
+ " support_request_id TEXT NOT NULL,\n",
+ " order_id TEXT NOT NULL,\n",
+ " user_id TEXT,\n",
+ " action_type TEXT NOT NULL CHECK (action_type IN ('apply_refund','apply_credit','send_reply')),\n",
+ " amount_usd NUMERIC(10,2),\n",
+ " payload JSONB,\n",
+ " status TEXT NOT NULL DEFAULT 'recorded',\n",
+ " actor TEXT,\n",
+ " created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()\n",
+ " )\n",
+ " \"\"\"\n",
+ " )\n",
+ "\n",
+ " cur.execute(\n",
+ " \"\"\"\n",
+ " CREATE TABLE IF NOT EXISTS support.support_replies (\n",
+ " reply_id BIGSERIAL PRIMARY KEY,\n",
+ " support_request_id TEXT NOT NULL,\n",
+ " order_id TEXT NOT NULL,\n",
+ " user_id TEXT,\n",
+ " message_text TEXT NOT NULL,\n",
+ " sent_by TEXT,\n",
+ " created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()\n",
+ " )\n",
+ " \"\"\"\n",
+ " )\n",
+ "\n",
+ " cur.execute(\n",
+ " \"\"\"\n",
+ " CREATE TABLE IF NOT EXISTS support.request_status (\n",
+ " support_request_id TEXT PRIMARY KEY,\n",
+ " status TEXT NOT NULL DEFAULT 'pending',\n",
+ " assigned_to TEXT,\n",
+ " updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n",
+ " last_action TEXT,\n",
+ " notes TEXT\n",
+ " )\n",
+ " \"\"\"\n",
+ " )\n",
+ "\n",
+ " cur.execute(\n",
+ " \"\"\"\n",
+ " CREATE TABLE IF NOT EXISTS support.response_ratings (\n",
+ " rating_id BIGSERIAL PRIMARY KEY,\n",
+ " support_request_id TEXT NOT NULL,\n",
+ " order_id TEXT NOT NULL,\n",
+ " user_id TEXT,\n",
+ " rating TEXT NOT NULL CHECK (rating IN ('thumbs_up','thumbs_down')),\n",
+ " reason_code TEXT,\n",
+ " feedback_notes TEXT,\n",
+ " actor TEXT,\n",
+ " created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n",
+ " UNIQUE (support_request_id)\n",
+ " )\n",
+ " \"\"\"\n",
+ " )\n",
+ "\n",
+ " # Grant app principal permissions for current and future support/public schema objects.\n",
+ " # This must be kept in sync whenever support tables/sequences are added.\n",
+ " if app_principal_client_ids:\n",
+ " # Lakebase OAuth roles must be created via databricks_auth for app principals.\n",
+ " cur.execute(\"CREATE EXTENSION IF NOT EXISTS databricks_auth\")\n",
+ "\n",
+ " for principal_client_id in app_principal_client_ids:\n",
+ " principal = quote_ident(principal_client_id)\n",
+ "\n",
+ " cur.execute(\"SAVEPOINT create_sp_role\")\n",
+ " try:\n",
+ " cur.execute(\n",
+ " \"SELECT databricks_create_role(%s, 'SERVICE_PRINCIPAL')\",\n",
+ " (principal_client_id,),\n",
+ " )\n",
+ " except psycopg2.errors.DuplicateObject:\n",
+ " # Role already exists in this Lakebase branch; continue with grants.\n",
+ " cur.execute(\"ROLLBACK TO SAVEPOINT create_sp_role\")\n",
+ " except Exception as role_error:\n",
+ " cur.execute(\"ROLLBACK TO SAVEPOINT create_sp_role\")\n",
+ " message = str(role_error)\n",
+ " if \"Identity not found\" in message:\n",
+ " # Some app identities (for example oauth2 app clients) are not resolvable\n",
+ " # through databricks_auth; create a native role fallback.\n",
+ " cur.execute(\n",
+ " f\"DO $$ BEGIN CREATE ROLE {principal}; EXCEPTION WHEN duplicate_object THEN NULL; END $$;\"\n",
+ " )\n",
+ " else:\n",
+ " raise\n",
+ " finally:\n",
+ " cur.execute(\"RELEASE SAVEPOINT create_sp_role\")\n",
+ "\n",
+ " cur.execute(f\"GRANT USAGE, CREATE ON SCHEMA support TO {principal}\")\n",
+ " cur.execute(f\"GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA support TO {principal}\")\n",
+ " cur.execute(f\"GRANT USAGE, SELECT, UPDATE ON ALL SEQUENCES IN SCHEMA support TO {principal}\")\n",
+ "\n",
+ " # AppKit persistent cache creates its own metadata in public by default.\n",
+ " cur.execute(f\"GRANT USAGE, CREATE ON SCHEMA public TO {principal}\")\n",
+ " cur.execute(f\"GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO {principal}\")\n",
+ " cur.execute(f\"GRANT USAGE, SELECT, UPDATE ON ALL SEQUENCES IN SCHEMA public TO {principal}\")\n",
+ "\n",
+ " cur.execute(\n",
+ " f\"ALTER DEFAULT PRIVILEGES IN SCHEMA support \"\n",
+ " f\"GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO {principal}\"\n",
+ " )\n",
+ " cur.execute(\n",
+ " f\"ALTER DEFAULT PRIVILEGES IN SCHEMA support \"\n",
+ " f\"GRANT USAGE, SELECT, UPDATE ON SEQUENCES TO {principal}\"\n",
+ " )\n",
+ " cur.execute(\n",
+ " f\"ALTER DEFAULT PRIVILEGES IN SCHEMA public \"\n",
+ " f\"GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO {principal}\"\n",
+ " )\n",
+ " cur.execute(\n",
+ " f\"ALTER DEFAULT PRIVILEGES IN SCHEMA public \"\n",
+ " f\"GRANT USAGE, SELECT, UPDATE ON SEQUENCES TO {principal}\"\n",
+ " )\n",
+ "\n",
+ " # Synced support tables are managed externally and may be created after\n",
+ " # app-owned objects, so default privileges do not reliably cover them.\n",
+ " if app_principal_client_ids:\n",
+ " cur.execute(\n",
+ " \"\"\"\n",
+ " SELECT table_name\n",
+ " FROM information_schema.tables\n",
+ " WHERE table_schema = 'support'\n",
+ " AND table_name LIKE '%\\\\_sync' ESCAPE '\\\\'\n",
+ " \"\"\"\n",
+ " )\n",
+ " sync_table_names = [row[0] for row in cur.fetchall()]\n",
+ "\n",
+ " for principal_client_id in app_principal_client_ids:\n",
+ " principal = quote_ident(principal_client_id)\n",
+ " for table_name in sync_table_names:\n",
+ " table_ident = quote_ident(table_name)\n",
+ " cur.execute(f\"GRANT SELECT ON TABLE support.{table_ident} TO {principal}\")\n",
+ "\n",
+ " conn.commit()\n",
+ "\n",
+ "conn.close()\n",
+ "print(\"Support Lakebase v2 provisioning complete\")"
+ ],
+ "execution_count": null,
+ "outputs": [],
+ "id": "92835191"
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "name": "python"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
\ No newline at end of file
diff --git a/stages/support_request_agent.ipynb b/stages/support_request_agent.ipynb
new file mode 100644
index 0000000..9dbd440
--- /dev/null
+++ b/stages/support_request_agent.ipynb
@@ -0,0 +1,625 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### support request agent\n",
+ "\n",
+ "Build and deploy a generic support-request agent with order context and user interaction history.\n",
+ "\n",
+ "Outputs include:\n",
+ "- credit recommendation\n",
+ "- refund recommendation\n",
+ "- draft customer response\n",
+ "- past interactions summary\n",
+ "- order details summary"
+ ],
+ "id": "67c1e4f0"
+ },
+ {
+ "cell_type": "code",
+ "metadata": {},
+ "source": [
+ "CATALOG = dbutils.widgets.get(\"CATALOG\")\n",
+ "LLM_MODEL = dbutils.widgets.get(\"LLM_MODEL\")\n",
+ "SUPPORT_AGENT_ENDPOINT_NAME = dbutils.widgets.get(\"SUPPORT_AGENT_ENDPOINT_NAME\")"
+ ],
+ "execution_count": null,
+ "outputs": [],
+ "id": "bc1af022"
+ },
+ {
+ "cell_type": "code",
+ "metadata": {},
+ "source": [
+ "spark.sql(f\"CREATE SCHEMA IF NOT EXISTS {CATALOG}.support\")\n",
+ "spark.sql(f\"CREATE SCHEMA IF NOT EXISTS {CATALOG}.ai\")\n",
+ "\n",
+ "# Bootstrap core support tables so blank workspaces do not fail before downstream stages materialize data.\n",
+ "spark.sql(f\"CREATE TABLE IF NOT EXISTS {CATALOG}.support.support_agent_reports (support_request_id STRING, user_id STRING, order_id STRING, request_text STRING, ts TIMESTAMP, agent_response STRING)\")\n",
+ "spark.sql(f\"CREATE TABLE IF NOT EXISTS {CATALOG}.support.raw_support_requests (support_request_id STRING, user_id STRING, order_id STRING, ts TIMESTAMP, request_type STRING, edge_case_type STRING, request_text STRING)\")\n",
+ "spark.sql(f\"CREATE TABLE IF NOT EXISTS {CATALOG}.support.support_request_features (support_request_id STRING, user_id STRING, order_id STRING, ts TIMESTAMP, repeat_complaints_30d BIGINT, policy_limit_usd DOUBLE, risk_score DOUBLE)\")\n",
+ "\n",
+ "# Backfill-safe schema evolution for existing tables.\n",
+ "try:\n",
+ " spark.sql(f\"ALTER TABLE {CATALOG}.support.support_agent_reports ADD COLUMNS (request_text STRING)\")\n",
+ "except Exception:\n",
+ " # Column already exists or table metadata already evolved.\n",
+ " pass\n",
+ "\n",
+ "spark.sql(f\"\"\"\n",
+ "CREATE OR REPLACE FUNCTION {CATALOG}.ai.get_order_overview(oid STRING)\n",
+ "RETURNS TABLE (\n",
+ " order_id STRING,\n",
+ " location STRING,\n",
+ " items_json STRING,\n",
+ " customer_address STRING,\n",
+ " order_created_ts TIMESTAMP\n",
+ ")\n",
+ "RETURN\n",
+ " SELECT\n",
+ " order_id,\n",
+ " location,\n",
+ " get_json_object(body, '$.items') AS items_json,\n",
+ " get_json_object(body, '$.customer_addr') AS customer_address,\n",
+ " try_to_timestamp(ts) AS order_created_ts\n",
+ " FROM {CATALOG}.lakeflow.all_events\n",
+ " WHERE order_id = oid AND event_type = 'order_created'\n",
+ " LIMIT 1\n",
+ "\"\"\")\n",
+ "\n",
+ "spark.sql(f\"\"\"\n",
+ "CREATE OR REPLACE FUNCTION {CATALOG}.ai.get_order_timing(oid STRING)\n",
+ "RETURNS TABLE (\n",
+ " order_id STRING,\n",
+ " order_created_ts TIMESTAMP,\n",
+ " delivered_ts TIMESTAMP,\n",
+ " delivery_duration_minutes FLOAT\n",
+ ")\n",
+ "RETURN\n",
+ " WITH order_events AS (\n",
+ " SELECT order_id, event_type, try_to_timestamp(ts) AS event_ts\n",
+ " FROM {CATALOG}.lakeflow.all_events\n",
+ " WHERE order_id = oid\n",
+ " )\n",
+ " SELECT\n",
+ " order_id,\n",
+ " MIN(CASE WHEN event_type='order_created' THEN event_ts END) AS order_created_ts,\n",
+ " MAX(CASE WHEN event_type='delivered' THEN event_ts END) AS delivered_ts,\n",
+ " CAST((UNIX_TIMESTAMP(MAX(CASE WHEN event_type='delivered' THEN event_ts END)) - UNIX_TIMESTAMP(MIN(CASE WHEN event_type='order_created' THEN event_ts END))) / 60 AS FLOAT) AS delivery_duration_minutes\n",
+ " FROM order_events\n",
+ " GROUP BY order_id\n",
+ "\"\"\")\n",
+ "\n",
+ "spark.sql(f\"\"\"\n",
+ "CREATE OR REPLACE FUNCTION {CATALOG}.ai.get_user_support_history(uid STRING)\n",
+ "RETURNS TABLE (\n",
+ " support_request_id STRING,\n",
+ " order_id STRING,\n",
+ " ts TIMESTAMP,\n",
+ " request_text STRING,\n",
+ " agent_response STRING\n",
+ ")\n",
+ "RETURN\n",
+ " SELECT support_request_id, order_id, ts, request_text, agent_response\n",
+ " FROM {CATALOG}.support.support_agent_reports\n",
+ " WHERE user_id = uid\n",
+ " ORDER BY ts DESC\n",
+ " LIMIT 10\n",
+ "\"\"\")\n",
+ "\n",
+ "spark.sql(f\"\"\"\n",
+ "CREATE OR REPLACE FUNCTION {CATALOG}.ai.get_user_request_history(uid STRING)\n",
+ "RETURNS TABLE (\n",
+ " support_request_id STRING,\n",
+ " order_id STRING,\n",
+ " ts TIMESTAMP,\n",
+ " request_type STRING,\n",
+ " edge_case_type STRING,\n",
+ " request_text STRING\n",
+ ")\n",
+ "RETURN\n",
+ " SELECT support_request_id, order_id, ts, request_type, edge_case_type, request_text\n",
+ " FROM {CATALOG}.support.raw_support_requests\n",
+ " WHERE user_id = uid\n",
+ " ORDER BY ts DESC\n",
+ " LIMIT 10\n",
+ "\"\"\")\n",
+ "\n",
+ "spark.sql(f\"\"\"\n",
+ "CREATE OR REPLACE FUNCTION {CATALOG}.ai.get_support_features(sid STRING)\n",
+ "RETURNS TABLE (\n",
+ " support_request_id STRING,\n",
+ " repeat_complaints_30d BIGINT,\n",
+ " policy_limit_usd DOUBLE,\n",
+ " risk_score DOUBLE,\n",
+ " feature_ts TIMESTAMP\n",
+ ")\n",
+ "RETURN\n",
+ " SELECT\n",
+ " support_request_id,\n",
+ " repeat_complaints_30d,\n",
+ " policy_limit_usd,\n",
+ " risk_score,\n",
+ " ts AS feature_ts\n",
+ " FROM {CATALOG}.support.support_request_features\n",
+ " WHERE support_request_id = sid\n",
+ " LIMIT 1\n",
+ "\"\"\")"
+ ],
+ "execution_count": null,
+ "outputs": [],
+ "id": "0c080efe"
+ },
+ {
+ "cell_type": "code",
+ "metadata": {},
+ "source": [
+ "%pip install -U -qqqq typing_extensions dspy-ai mlflow unitycatalog-openai[databricks] openai databricks-sdk databricks-agents pydantic\n",
+ "%restart_python"
+ ],
+ "execution_count": null,
+ "outputs": [],
+ "id": "4777956b"
+ },
+ {
+ "cell_type": "code",
+ "metadata": {},
+ "source": [
+ "import mlflow\n",
+ "import sys\n",
+ "from databricks.sdk import WorkspaceClient\n",
+ "\n",
+ "CATALOG = dbutils.widgets.get(\"CATALOG\")\n",
+ "LLM_MODEL = dbutils.widgets.get(\"LLM_MODEL\")\n",
+ "SUPPORT_AGENT_ENDPOINT_NAME = dbutils.widgets.get(\"SUPPORT_AGENT_ENDPOINT_NAME\")\n",
+ "\n",
+ "sys.path.append('../utils')\n",
+ "from uc_state import add\n",
+ "\n",
+ "dev_experiment = mlflow.set_experiment(f\"/Shared/{CATALOG}_support_agent_dev\")\n",
+ "add(CATALOG, \"experiments\", {\"experiment_id\": dev_experiment.experiment_id, \"name\": dev_experiment.name})"
+ ],
+ "execution_count": null,
+ "outputs": [],
+ "id": "4d21e98c"
+ },
+ {
+ "cell_type": "code",
+ "metadata": {},
+ "source": [
+ "%%writefile agent.py\n",
+ "import json\n",
+ "import re\n",
+ "import warnings\n",
+ "from typing import Any, Dict, Literal, Optional\n",
+ "from uuid import uuid4\n",
+ "\n",
+ "import dspy\n",
+ "import mlflow\n",
+ "from mlflow.pyfunc import ResponsesAgent\n",
+ "from mlflow.types.responses import ResponsesAgentRequest, ResponsesAgentResponse\n",
+ "from pydantic import BaseModel, Field\n",
+ "from unitycatalog.ai.core.base import get_uc_function_client\n",
+ "\n",
+ "warnings.filterwarnings(\"ignore\", message=\".*Ignoring the default notebook Spark session.*\")\n",
+ "\n",
+ "mlflow.dspy.autolog(log_traces=True)\n",
+ "\n",
+ "LLM_MODEL = \"{{LLM_MODEL}}\"\n",
+ "CATALOG = \"{{CATALOG}}\"\n",
+ "\n",
+ "lm = dspy.LM(f\"databricks/{LLM_MODEL}\", max_tokens=2000)\n",
+ "dspy.configure(lm=lm)\n",
+ "uc_client = get_uc_function_client()\n",
+ "\n",
+ "\n",
+ "class SupportReport(BaseModel):\n",
+ " support_request_id: str\n",
+ " user_id: str\n",
+ " order_id: str\n",
+ " credit_recommendation: Optional[dict] = None\n",
+ " refund_recommendation: Optional[dict] = None\n",
+ " draft_response: str\n",
+ " past_interactions_summary: str\n",
+ " order_details_summary: str\n",
+ " decision_confidence: Literal[\"high\", \"medium\", \"low\"] = Field(default=\"medium\")\n",
+ " escalation_flag: bool = Field(default=False)\n",
+ "\n",
+ "\n",
+ "class SupportTriage(dspy.Signature):\n",
+ " \"\"\"Produce a final support resolution report using full context.\n",
+ "\n",
+ " Required inputs to reason over:\n",
+ " - support request text and edge-case metadata\n",
+ " - order details and delivery timing\n",
+ " - prior support history for this user\n",
+ " - support features: repeat_complaints_30d, policy_limit_usd, risk_score\n",
+ "\n",
+ " Decision policy:\n",
+ " - Severe repeat/high-risk issue: provide concrete refund + credit and apology.\n",
+ " - Moderate issue: provide bounded partial refund and/or credit with rationale.\n",
+ " - Minor/non-compensable issue: typically no refund, small goodwill credit or clear denial.\n",
+ " - Spam/abusive patterns: avoid excessive compensation, set escalation_flag=true.\n",
+ "\n",
+ " Never return placeholder text like \"we will look into this\".\n",
+ " Always return a final customer-ready message with concrete next steps.\n",
+ " \"\"\"\n",
+ "\n",
+ " support_request: str = dspy.InputField(desc=\"Structured case payload JSON string\")\n",
+ " support_request_id: str = dspy.OutputField()\n",
+ " user_id: str = dspy.OutputField()\n",
+ " order_id: str = dspy.OutputField()\n",
+ " credit_recommendation_json: str = dspy.OutputField(desc=\"JSON object with amount_usd/reason\")\n",
+ " refund_recommendation_json: str = dspy.OutputField(desc=\"JSON object with amount_usd/reason\")\n",
+ " draft_response: str = dspy.OutputField()\n",
+ " past_interactions_summary: str = dspy.OutputField()\n",
+ " order_details_summary: str = dspy.OutputField()\n",
+ " decision_confidence: str = dspy.OutputField(desc=\"high, medium, low\")\n",
+ " escalation_flag: str = dspy.OutputField(desc=\"true or false\")\n",
+ "\n",
+ "\n",
+ "def get_order_overview(order_id: str) -> str:\n",
+ " return str(uc_client.execute_function(f\"{CATALOG}.ai.get_order_overview\", {\"oid\": order_id}).value)\n",
+ "\n",
+ "\n",
+ "def get_order_timing(order_id: str) -> str:\n",
+ " return str(uc_client.execute_function(f\"{CATALOG}.ai.get_order_timing\", {\"oid\": order_id}).value)\n",
+ "\n",
+ "\n",
+ "def get_user_support_history(user_id: str) -> str:\n",
+ " return str(uc_client.execute_function(f\"{CATALOG}.ai.get_user_support_history\", {\"uid\": user_id}).value)\n",
+ "\n",
+ "\n",
+ "def get_user_request_history(user_id: str) -> str:\n",
+ " return str(uc_client.execute_function(f\"{CATALOG}.ai.get_user_request_history\", {\"uid\": user_id}).value)\n",
+ "\n",
+ "\n",
+ "def get_support_features(support_request_id: str) -> str:\n",
+ " return str(uc_client.execute_function(f\"{CATALOG}.ai.get_support_features\", {\"sid\": support_request_id}).value)\n",
+ "\n",
+ "\n",
+ "def _parse_case_payload(raw: str) -> Dict[str, Any]:\n",
+ " try:\n",
+ " payload = json.loads(raw)\n",
+ " return payload if isinstance(payload, dict) else {}\n",
+ " except Exception:\n",
+ " parsed: Dict[str, Any] = {}\n",
+ " for key in [\"support_request_id\", \"user_id\", \"order_id\", \"text\"]:\n",
+ " match = re.search(rf\"{key}=([^\\s]+)\", raw)\n",
+ " if match:\n",
+ " parsed[key] = match.group(1)\n",
+ " if \"text\" in parsed:\n",
+ " parsed[\"request_text\"] = parsed[\"text\"]\n",
+ " return parsed\n",
+ "\n",
+ "\n",
+ "def _safe_float(value: Any, default: float = 0.0) -> float:\n",
+ " try:\n",
+ " return float(value)\n",
+ " except Exception:\n",
+ " return default\n",
+ "\n",
+ "\n",
+ "def _safe_int(value: Any, default: int = 0) -> int:\n",
+ " try:\n",
+ " return int(value)\n",
+ " except Exception:\n",
+ " return default\n",
+ "\n",
+ "\n",
+ "def _compute_policy_resolution(payload: Dict[str, Any]) -> Dict[str, Any]:\n",
+ " features = payload.get(\"feature_context\", {}) if isinstance(payload.get(\"feature_context\"), dict) else {}\n",
+ " request_text = str(payload.get(\"request_text\", \"\"))\n",
+ " edge_case_type = str(payload.get(\"edge_case_type\", \"standard\"))\n",
+ "\n",
+ " repeat_count = _safe_int(features.get(\"repeat_complaints_30d\"), 0)\n",
+ " risk_score = _safe_float(features.get(\"risk_score\"), 0.25)\n",
+ " policy_limit = max(0.0, _safe_float(features.get(\"policy_limit_usd\"), 20.0))\n",
+ "\n",
+ " text_lower = request_text.lower()\n",
+ " mentions_missing = \"missing\" in text_lower\n",
+ " mentions_delay = \"late\" in text_lower or \"delay\" in text_lower\n",
+ " abusive = edge_case_type == \"abusive_language\"\n",
+ " spammy = edge_case_type == \"spammy_escalation\"\n",
+ "\n",
+ " if abusive or (spammy and repeat_count >= 4 and risk_score < 0.4):\n",
+ " refund_amount = 0.0\n",
+ " credit_amount = min(3.0, policy_limit)\n",
+ " escalation = True\n",
+ " confidence = \"medium\"\n",
+ " reason = \"Abusive/spammy pattern detected; restricted compensation with escalation.\"\n",
+ " elif repeat_count >= 2 or risk_score >= 0.75 or (mentions_missing and mentions_delay):\n",
+ " refund_amount = round(min(policy_limit, max(policy_limit * 0.9, 15.0)), 2)\n",
+ " credit_amount = round(min(10.0, max(5.0, policy_limit * 0.25)), 2)\n",
+ " escalation = False\n",
+ " confidence = \"high\"\n",
+ " reason = \"Repeated or high-risk service failure.\"\n",
+ " elif repeat_count == 1 or risk_score >= 0.45 or mentions_missing or mentions_delay:\n",
+ " refund_amount = round(min(policy_limit, max(policy_limit * 0.5, 6.0)), 2)\n",
+ " credit_amount = round(min(7.0, max(3.0, policy_limit * 0.15)), 2)\n",
+ " escalation = False\n",
+ " confidence = \"high\"\n",
+ " reason = \"Moderate service issue with customer impact.\"\n",
+ " else:\n",
+ " refund_amount = 0.0\n",
+ " credit_amount = round(min(5.0, max(2.0, policy_limit * 0.1)), 2)\n",
+ " escalation = False\n",
+ " confidence = \"medium\"\n",
+ " reason = \"Minor issue or low-confidence compensable case.\"\n",
+ "\n",
+ " return {\n",
+ " \"refund_amount\": refund_amount,\n",
+ " \"credit_amount\": credit_amount,\n",
+ " \"escalation\": escalation,\n",
+ " \"confidence\": confidence,\n",
+ " \"reason\": reason,\n",
+ " \"repeat_count\": repeat_count,\n",
+ " }\n",
+ "\n",
+ "\n",
+ "def _ordinal(value: int) -> str:\n",
+ " if 10 <= value % 100 <= 20:\n",
+ " suffix = \"th\"\n",
+ " else:\n",
+ " suffix = {1: \"st\", 2: \"nd\", 3: \"rd\"}.get(value % 10, \"th\")\n",
+ " return f\"{value}{suffix}\"\n",
+ "\n",
+ "\n",
+ "def _compose_customer_message(payload: Dict[str, Any], policy: Dict[str, Any]) -> str:\n",
+ " request_text = str(payload.get(\"request_text\", \"\")).strip()\n",
+ " repeat_count = policy[\"repeat_count\"]\n",
+ " refund_amount = policy[\"refund_amount\"]\n",
+ " credit_amount = policy[\"credit_amount\"]\n",
+ "\n",
+ " lead = \"Thanks for contacting us, and I am really sorry about this experience.\"\n",
+ " if repeat_count >= 2:\n",
+ " lead = (\n",
+ " f\"I see this is at least the {_ordinal(repeat_count)} time you've had to contact us for similar issues, \"\n",
+ " \"and that is not acceptable.\"\n",
+ " )\n",
+ "\n",
+ " resolution_parts = []\n",
+ " if refund_amount > 0:\n",
+ " resolution_parts.append(f\"a ${refund_amount:.2f} refund\")\n",
+ " if credit_amount > 0:\n",
+ " resolution_parts.append(f\"a ${credit_amount:.2f} credit\")\n",
+ "\n",
+ " if resolution_parts:\n",
+ " resolution = \"We are offering \" + \" and \".join(resolution_parts) + \" on this case.\"\n",
+ " else:\n",
+ " resolution = \"We are escalating this case for manual review and will follow up quickly.\"\n",
+ "\n",
+ " context_line = f\"Issue noted: {request_text}\" if request_text else \"Issue noted from your support ticket.\"\n",
+ "\n",
+ " return f\"{lead} {resolution} {context_line}\"\n",
+ "\n",
+ "\n",
+ "class SupportModule(dspy.Module):\n",
+ " def __init__(self):\n",
+ " super().__init__()\n",
+ " self.react = dspy.ReAct(\n",
+ " signature=SupportTriage,\n",
+ " tools=[\n",
+ " get_order_overview,\n",
+ " get_order_timing,\n",
+ " get_user_support_history,\n",
+ " get_user_request_history,\n",
+ " get_support_features,\n",
+ " ],\n",
+ " max_iters=10,\n",
+ " )\n",
+ "\n",
+ " def forward(self, support_request: str) -> SupportReport:\n",
+ " payload = _parse_case_payload(support_request)\n",
+ " result = self.react(support_request=support_request)\n",
+ "\n",
+ " policy = _compute_policy_resolution(payload)\n",
+ " final_message = _compose_customer_message(payload, policy)\n",
+ "\n",
+ " # Guarantee concrete recommendations and customer-ready final response.\n",
+ " credit_recommendation = {\n",
+ " \"amount_usd\": policy[\"credit_amount\"],\n",
+ " \"reason\": policy[\"reason\"],\n",
+ " }\n",
+ " refund_recommendation = {\n",
+ " \"amount_usd\": policy[\"refund_amount\"],\n",
+ " \"reason\": policy[\"reason\"],\n",
+ " }\n",
+ "\n",
+ " return SupportReport(\n",
+ " support_request_id=str(payload.get(\"support_request_id\") or result.support_request_id),\n",
+ " user_id=str(payload.get(\"user_id\") or result.user_id),\n",
+ " order_id=str(payload.get(\"order_id\") or result.order_id),\n",
+ " credit_recommendation=credit_recommendation,\n",
+ " refund_recommendation=refund_recommendation,\n",
+ " draft_response=final_message,\n",
+ " past_interactions_summary=str(result.past_interactions_summary),\n",
+ " order_details_summary=str(result.order_details_summary),\n",
+ " decision_confidence=policy[\"confidence\"],\n",
+ " escalation_flag=bool(policy[\"escalation\"]),\n",
+ " )\n",
+ "\n",
+ "\n",
+ "class DSPySupportAgent(ResponsesAgent):\n",
+ " def __init__(self):\n",
+ " self.module = SupportModule()\n",
+ "\n",
+ " def predict(self, request: ResponsesAgentRequest) -> ResponsesAgentResponse:\n",
+ " user_message = None\n",
+ " for msg in request.input:\n",
+ " msg_dict = msg.model_dump() if hasattr(msg, \"model_dump\") else msg\n",
+ " if msg_dict.get(\"role\") == \"user\":\n",
+ " user_message = msg_dict.get(\"content\", \"\")\n",
+ " break\n",
+ " if not user_message:\n",
+ " raise ValueError(\"No user message found\")\n",
+ "\n",
+ " result = self.module(support_request=user_message)\n",
+ " return ResponsesAgentResponse(\n",
+ " output=[self.create_text_output_item(text=result.model_dump_json(), id=str(uuid4()))],\n",
+ " custom_outputs=request.custom_inputs,\n",
+ " )\n",
+ "\n",
+ "\n",
+ "AGENT = DSPySupportAgent()\n",
+ "mlflow.models.set_model(AGENT)"
+ ],
+ "execution_count": null,
+ "outputs": [],
+ "id": "2c42256c"
+ },
+ {
+ "cell_type": "code",
+ "metadata": {},
+ "source": [
+ "from pathlib import Path\n",
+ "\n",
+ "agent_path = Path(\"agent.py\")\n",
+ "source = agent_path.read_text(encoding=\"utf-8\")\n",
+ "source = source.replace(\"{{LLM_MODEL}}\", LLM_MODEL).replace(\"{{CATALOG}}\", CATALOG)\n",
+ "agent_path.write_text(source, encoding=\"utf-8\")\n",
+ "\n",
+ "print(\"Wrote agent.py with concrete CATALOG/LLM_MODEL values\")"
+ ],
+ "execution_count": null,
+ "outputs": [],
+ "id": "14e836ea"
+ },
+ {
+ "cell_type": "code",
+ "metadata": {},
+ "source": [
+ "import json\n",
+ "import mlflow\n",
+ "from mlflow.models.resources import DatabricksFunction, DatabricksServingEndpoint\n",
+ "\n",
+ "sample = spark.sql(f\"SELECT support_request_id, user_id, order_id, request_type, edge_case_type, request_text FROM {CATALOG}.support.raw_support_requests LIMIT 1\").collect()\n",
+ "if sample:\n",
+ " row = sample[0]\n",
+ " payload = {\n",
+ " \"support_request_id\": row[\"support_request_id\"],\n",
+ " \"user_id\": row[\"user_id\"],\n",
+ " \"order_id\": row[\"order_id\"],\n",
+ " \"request_type\": row[\"request_type\"],\n",
+ " \"edge_case_type\": row[\"edge_case_type\"],\n",
+ " \"request_text\": row[\"request_text\"],\n",
+ " \"feature_context\": {\n",
+ " \"repeat_complaints_30d\": 2,\n",
+ " \"policy_limit_usd\": 20.0,\n",
+ " \"risk_score\": 0.67,\n",
+ " },\n",
+ " \"order_context\": {},\n",
+ " \"past_request_context\": [],\n",
+ " }\n",
+ "else:\n",
+ " payload = {\n",
+ " \"support_request_id\": \"sample-1\",\n",
+ " \"user_id\": \"user-1\",\n",
+ " \"order_id\": \"order-1\",\n",
+ " \"request_type\": \"missing_items\",\n",
+ " \"edge_case_type\": \"repeat_follow_up\",\n",
+ " \"request_text\": \"This is the second time items were missing from my order.\",\n",
+ " \"feature_context\": {\n",
+ " \"repeat_complaints_30d\": 2,\n",
+ " \"policy_limit_usd\": 20.0,\n",
+ " \"risk_score\": 0.71,\n",
+ " },\n",
+ " \"order_context\": {},\n",
+ " \"past_request_context\": [],\n",
+ " }\n",
+ "\n",
+ "resources = [DatabricksServingEndpoint(endpoint_name=LLM_MODEL)]\n",
+ "for fn in [\n",
+ " f\"{CATALOG}.ai.get_order_overview\",\n",
+ " f\"{CATALOG}.ai.get_order_timing\",\n",
+ " f\"{CATALOG}.ai.get_user_support_history\",\n",
+ " f\"{CATALOG}.ai.get_user_request_history\",\n",
+ " f\"{CATALOG}.ai.get_support_features\",\n",
+ "]:\n",
+ " resources.append(DatabricksFunction(function_name=fn))\n",
+ "\n",
+ "input_example = {\"input\": [{\"role\": \"user\", \"content\": json.dumps(payload)}]}\n",
+ "\n",
+ "with mlflow.start_run():\n",
+ " logged_agent_info = mlflow.pyfunc.log_model(\n",
+ " name=\"support_agent\",\n",
+ " python_model=\"agent.py\",\n",
+ " input_example=input_example,\n",
+ " resources=resources,\n",
+ " )\n",
+ "\n",
+ "mlflow.set_active_model(model_id=logged_agent_info.model_id)\n",
+ "mlflow.set_registry_uri(\"databricks-uc\")\n",
+ "UC_MODEL_NAME = f\"{CATALOG}.ai.support_agent\"\n",
+ "uc_registered_model_info = mlflow.register_model(model_uri=logged_agent_info.model_uri, name=UC_MODEL_NAME)"
+ ],
+ "execution_count": null,
+ "outputs": [],
+ "id": "ed761f74"
+ },
+ {
+ "cell_type": "code",
+ "metadata": {},
+ "source": [
+ "import mlflow\n",
+ "import time\n",
+ "from databricks import agents\n",
+ "from databricks.sdk import WorkspaceClient\n",
+ "from databricks.sdk.service.serving import EndpointStateReady\n",
+ "\n",
+ "prod_experiment = mlflow.set_experiment(f\"/Shared/{CATALOG}_support_agent_prod\")\n",
+ "add(CATALOG, \"experiments\", {\"experiment_id\": prod_experiment.experiment_id, \"name\": prod_experiment.name})\n",
+ "\n",
+ "deployment_info = None\n",
+ "try:\n",
+ " deployment_info = agents.deploy(\n",
+ " model_name=UC_MODEL_NAME,\n",
+ " model_version=uc_registered_model_info.version,\n",
+ " scale_to_zero=True,\n",
+ " endpoint_name=SUPPORT_AGENT_ENDPOINT_NAME,\n",
+ " environment_vars={\"MLFLOW_EXPERIMENT_ID\": str(prod_experiment.experiment_id)},\n",
+ " )\n",
+ "except ValueError as e:\n",
+ " # Blank-workspace reliability: another run may already be updating this endpoint.\n",
+ " if \"currently updating\" not in str(e).lower():\n",
+ " raise\n",
+ " print(f\"Endpoint {SUPPORT_AGENT_ENDPOINT_NAME} already updating; waiting for readiness.\")\n",
+ "\n",
+ "workspace = WorkspaceClient()\n",
+ "ready = False\n",
+ "for _ in range(120):\n",
+ " endpoint = workspace.serving_endpoints.get(name=SUPPORT_AGENT_ENDPOINT_NAME)\n",
+ " if endpoint.state and endpoint.state.ready == EndpointStateReady.READY:\n",
+ " ready = True\n",
+ " break\n",
+ " time.sleep(10)\n",
+ "\n",
+ "if not ready:\n",
+ " raise RuntimeError(f\"Endpoint {SUPPORT_AGENT_ENDPOINT_NAME} did not reach READY within polling window\")\n",
+ "\n",
+ "if deployment_info is None:\n",
+ " deployment_info = workspace.serving_endpoints.get(name=SUPPORT_AGENT_ENDPOINT_NAME)\n",
+ "\n",
+ "add(CATALOG, \"endpoints\", deployment_info)\n",
+ "print(f\"Endpoint {SUPPORT_AGENT_ENDPOINT_NAME} is READY\")"
+ ],
+ "execution_count": null,
+ "outputs": [],
+ "id": "bb160c06"
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "name": "python"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
\ No newline at end of file
diff --git a/stages/support_request_agent_stream.ipynb b/stages/support_request_agent_stream.ipynb
new file mode 100644
index 0000000..46ee601
--- /dev/null
+++ b/stages/support_request_agent_stream.ipynb
@@ -0,0 +1,108 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "##### Support Request Agent Stream\n",
+ "\n",
+ "Create a scheduled job to process support requests through the support agent."
+ ],
+ "id": "a8c9f620"
+ },
+ {
+ "cell_type": "code",
+ "metadata": {},
+ "source": [
+ "%pip install --upgrade databricks-sdk"
+ ],
+ "execution_count": null,
+ "outputs": [],
+ "id": "b6e12e8f"
+ },
+ {
+ "cell_type": "code",
+ "metadata": {},
+ "source": [
+ "from databricks.sdk import WorkspaceClient\n",
+ "import databricks.sdk.service.jobs as j\n",
+ "import os\n",
+ "\n",
+ "w = WorkspaceClient()\n",
+ "notebook_abs_path = os.path.abspath(\"../jobs/support_request_agent_stream\")\n",
+ "notebook_dbx_path = notebook_abs_path.replace(\n",
+ " os.environ.get(\"DATABRICKS_WORKSPACE_ROOT\", \"/Workspace\"),\n",
+ " \"/Workspace\"\n",
+ ")\n",
+ "\n",
+ "job_name = \"Support Request Agent Stream\"\n",
+ "new_settings = j.JobSettings(\n",
+ " name=job_name,\n",
+ " schedule=j.CronSchedule(\n",
+ " quartz_cron_expression=\"0 0/10 * * * ?\",\n",
+ " timezone_id=\"UTC\",\n",
+ " pause_status=j.PauseStatus.UNPAUSED,\n",
+ " ),\n",
+ " tasks=[\n",
+ " j.Task(\n",
+ " task_key=\"support_request_agent_stream\",\n",
+ " notebook_task=j.NotebookTask(\n",
+ " notebook_path=notebook_dbx_path,\n",
+ " base_parameters={\n",
+ " \"CATALOG\": dbutils.widgets.get(\"CATALOG\"),\n",
+ " \"SUPPORT_AGENT_ENDPOINT_NAME\": dbutils.widgets.get(\"SUPPORT_AGENT_ENDPOINT_NAME\"),\n",
+ " },\n",
+ " ),\n",
+ " )\n",
+ " ],\n",
+ ")\n",
+ "\n",
+ "matches = sorted(\n",
+ " [job for job in w.jobs.list(name=job_name) if job.settings and job.settings.name == job_name],\n",
+ " key=lambda x: x.created_time or 0,\n",
+ " reverse=True,\n",
+ ")\n",
+ "if matches:\n",
+ " target_job_id = matches[0].job_id\n",
+ " w.jobs.reset(job_id=target_job_id, new_settings=new_settings)\n",
+ " job = w.jobs.get(job_id=target_job_id)\n",
+ " print(f\"Updated existing job_id={target_job_id}\")\n",
+ "\n",
+ " for stale in matches[1:]:\n",
+ " stale_id = stale.job_id\n",
+ " for run in w.jobs.list_runs(job_id=stale_id, active_only=True):\n",
+ " w.jobs.cancel_run(run_id=run.run_id)\n",
+ " w.jobs.delete(job_id=stale_id)\n",
+ " print(f\"Deleted stale duplicate job_id={stale_id}\")\n",
+ "else:\n",
+ " settings_payload = new_settings.as_dict() if hasattr(new_settings, \"as_dict\") else new_settings\n",
+ " created = w.api_client.do(\"POST\", \"/api/2.2/jobs/create\", body=settings_payload)\n",
+ " target_job_id = created[\"job_id\"] if isinstance(created, dict) else created.job_id\n",
+ " job = w.jobs.get(job_id=target_job_id)\n",
+ " print(f\"Created job_id={target_job_id}\")\n",
+ "\n",
+ "import sys\n",
+ "sys.path.append('../utils')\n",
+ "from uc_state import add\n",
+ "\n",
+ "add(dbutils.widgets.get(\"CATALOG\"), \"jobs\", job)\n",
+ "w.jobs.run_now(job_id=target_job_id)"
+ ],
+ "execution_count": null,
+ "outputs": [],
+ "id": "43b290dc"
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "name": "python"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
\ No newline at end of file
diff --git a/stages/support_request_generator_stream.ipynb b/stages/support_request_generator_stream.ipynb
new file mode 100644
index 0000000..8050f79
--- /dev/null
+++ b/stages/support_request_generator_stream.ipynb
@@ -0,0 +1,109 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "##### Support Request Generator Stream\n",
+ "\n",
+ "Create a scheduled job to generate support requests."
+ ],
+ "id": "6e3166ee"
+ },
+ {
+ "cell_type": "code",
+ "metadata": {},
+ "source": [
+ "%pip install --upgrade databricks-sdk"
+ ],
+ "execution_count": null,
+ "outputs": [],
+ "id": "a27b29bc"
+ },
+ {
+ "cell_type": "code",
+ "metadata": {},
+ "source": [
+ "from databricks.sdk import WorkspaceClient\n",
+ "import databricks.sdk.service.jobs as j\n",
+ "import os\n",
+ "\n",
+ "w = WorkspaceClient()\n",
+ "notebook_abs_path = os.path.abspath(\"../jobs/support_request_generator\")\n",
+ "notebook_dbx_path = notebook_abs_path.replace(\n",
+ " os.environ.get(\"DATABRICKS_WORKSPACE_ROOT\", \"/Workspace\"),\n",
+ " \"/Workspace\"\n",
+ ")\n",
+ "\n",
+ "job_name = \"Support Request Generator Stream\"\n",
+ "new_settings = j.JobSettings(\n",
+ " name=job_name,\n",
+ " schedule=j.CronSchedule(\n",
+ " quartz_cron_expression=\"0 0/10 * * * ?\",\n",
+ " timezone_id=\"UTC\",\n",
+ " pause_status=j.PauseStatus.UNPAUSED,\n",
+ " ),\n",
+ " tasks=[\n",
+ " j.Task(\n",
+ " task_key=\"support_request_generator_stream\",\n",
+ " notebook_task=j.NotebookTask(\n",
+ " notebook_path=notebook_dbx_path,\n",
+ " base_parameters={\n",
+ " \"CATALOG\": dbutils.widgets.get(\"CATALOG\"),\n",
+ " \"SUPPORT_RATE\": dbutils.widgets.get(\"SUPPORT_RATE\"),\n",
+ " \"LLM_MODEL\": dbutils.widgets.get(\"LLM_MODEL\"),\n",
+ " },\n",
+ " ),\n",
+ " )\n",
+ " ],\n",
+ ")\n",
+ "\n",
+ "matches = sorted(\n",
+ " [job for job in w.jobs.list(name=job_name) if job.settings and job.settings.name == job_name],\n",
+ " key=lambda x: x.created_time or 0,\n",
+ " reverse=True,\n",
+ ")\n",
+ "if matches:\n",
+ " target_job_id = matches[0].job_id\n",
+ " w.jobs.reset(job_id=target_job_id, new_settings=new_settings)\n",
+ " job = w.jobs.get(job_id=target_job_id)\n",
+ " print(f\"Updated existing job_id={target_job_id}\")\n",
+ "\n",
+ " for stale in matches[1:]:\n",
+ " stale_id = stale.job_id\n",
+ " for run in w.jobs.list_runs(job_id=stale_id, active_only=True):\n",
+ " w.jobs.cancel_run(run_id=run.run_id)\n",
+ " w.jobs.delete(job_id=stale_id)\n",
+ " print(f\"Deleted stale duplicate job_id={stale_id}\")\n",
+ "else:\n",
+ " settings_payload = new_settings.as_dict() if hasattr(new_settings, \"as_dict\") else new_settings\n",
+ " created = w.api_client.do(\"POST\", \"/api/2.2/jobs/create\", body=settings_payload)\n",
+ " target_job_id = created[\"job_id\"] if isinstance(created, dict) else created.job_id\n",
+ " job = w.jobs.get(job_id=target_job_id)\n",
+ " print(f\"Created job_id={target_job_id}\")\n",
+ "\n",
+ "import sys\n",
+ "sys.path.append('../utils')\n",
+ "from uc_state import add\n",
+ "\n",
+ "add(dbutils.widgets.get(\"CATALOG\"), \"jobs\", job)\n",
+ "w.jobs.run_now(job_id=target_job_id)"
+ ],
+ "execution_count": null,
+ "outputs": [],
+ "id": "f3e004fe"
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "name": "python"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
\ No newline at end of file