diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 02c45e7c..0c7fb572 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -143,6 +143,10 @@ jobs:
# Use production build for faster startup
NODE_ENV: production
+ - name: Run component tests
+ working-directory: ./ui
+ run: pnpm run test:ct
+
- name: Upload Playwright report
uses: actions/upload-artifact@v4
if: failure()
diff --git a/server/src/agent_control_server/endpoints/controls.py b/server/src/agent_control_server/endpoints/controls.py
index 4fa44dbb..f28e42a2 100644
--- a/server/src/agent_control_server/endpoints/controls.py
+++ b/server/src/agent_control_server/endpoints/controls.py
@@ -100,7 +100,11 @@ def _serialize_control_definition(control_def: ControlDefinition) -> dict[str, o
async def _validate_control_definition(
control_def: ControlDefinition, db: AsyncSession
) -> None:
- """Validate evaluator config for a control definition."""
+ """Validate evaluator config for definitions referencing known global evaluators.
+
+ Agent-scoped evaluators must exist on the referenced agent. Builtin and external
+ names that are not loaded in this process are accepted without config checks.
+ """
available_evaluators = list_evaluators()
agent_data_by_name: dict[str, AgentData] = {}
for field_prefix, leaf in _iter_condition_leaves(control_def.condition):
@@ -212,6 +216,9 @@ async def _validate_control_definition(
evaluator_cls = available_evaluators.get(parsed.name)
if evaluator_cls is None:
+ # Global (builtin / external) evaluators may be absent from this runtime
+ # (optional packages, forward compatibility). Store the definition without
+ # config validation; evaluation will fail later if the evaluator is missing.
continue
try:
diff --git a/server/tests/test_controls_validation.py b/server/tests/test_controls_validation.py
index 2761bdd3..b6d53562 100644
--- a/server/tests/test_controls_validation.py
+++ b/server/tests/test_controls_validation.py
@@ -318,3 +318,32 @@ def test_validation_nested_agent_scoped_evaluator_error_uses_bracketed_field_pat
and err.get("code") == "evaluator_not_found"
for err in body.get("errors", [])
)
+
+
+def test_validation_standalone_evaluator_error_uses_bracketed_field_path(
+ client: TestClient,
+):
+ """Nested standalone (global) evaluator config errors use bracketed leaf paths."""
+ control_id = create_control(client)
+ payload = deepcopy(VALID_CONTROL_PAYLOAD)
+ payload["condition"] = {
+ "or": [
+ {
+ "selector": {"path": "input"},
+ "evaluator": {
+ "name": "regex",
+ "config": {},
+ },
+ }
+ ]
+ }
+
+ resp = client.put(f"/api/v1/controls/{control_id}/data", json={"data": payload})
+
+ assert resp.status_code == 422
+ body = resp.json()
+ assert body["error_code"] == "VALIDATION_ERROR"
+ assert any(
+ err.get("field", "").startswith("data.condition.or[0].evaluator")
+ for err in body.get("errors", [])
+ )
diff --git a/ui/.gitignore b/ui/.gitignore
index c8fc9c98..b066e039 100644
--- a/ui/.gitignore
+++ b/ui/.gitignore
@@ -42,3 +42,5 @@ next-env.d.ts
CLAUDE.md
.claude
+
+playwright/.cache/
\ No newline at end of file
diff --git a/ui/package.json b/ui/package.json
index 1d8748ac..a9f29044 100644
--- a/ui/package.json
+++ b/ui/package.json
@@ -13,6 +13,8 @@
"typecheck": "tsc --noEmit",
"fetch-api-types": "openapi-typescript http://localhost:8000/openapi.json -o src/core/api/generated/api-types.ts",
"test:integration": "playwright test",
+ "test:ct": "playwright test -c playwright-ct.config.ts",
+ "test:ct:ui": "playwright test -c playwright-ct.config.ts --ui",
"test:integration:ui": "playwright test --ui",
"test:integration:headed": "playwright test --headed",
"test:integration:debug": "playwright test --debug",
@@ -31,6 +33,8 @@
"typecheck": "Run TypeScript checks (no emit)",
"fetch-api-types": "Regenerate API types from the server OpenAPI schema at localhost:8000",
"test:integration": "Run Playwright integration tests",
+ "test:ct": "Run Playwright component tests (JsonEditor, etc.)",
+ "test:ct:ui": "Run component tests in interactive UI mode",
"test:integration:ui": "Run Playwright integration tests in interactive UI mode",
"test:integration:headed": "Run Playwright integration tests in headed browser mode",
"test:integration:debug": "Run Playwright integration tests in debug mode",
@@ -39,7 +43,14 @@
"prettify:check": "Check formatting with Prettier without changing files"
},
"dependencies": {
+ "@codemirror/autocomplete": "^6.20.1",
+ "@codemirror/lang-json": "^6.0.2",
+ "@codemirror/language": "^6.12.3",
+ "@codemirror/lint": "^6.9.5",
+ "@codemirror/state": "^6.6.0",
+ "@codemirror/view": "^6.40.0",
"@emotion/is-prop-valid": "^1.4.0",
+ "@lezer/highlight": "^1.2.3",
"@mantine/charts": "^7.17.8",
"@mantine/code-highlight": "7.17.5",
"@mantine/core": "7.17.5",
@@ -56,6 +67,10 @@
"@tanstack/react-query": "5.74.4",
"@tanstack/react-query-devtools": "5.72.2",
"@tanstack/react-table": "8.20.5",
+ "@uiw/codemirror-extensions-basic-setup": "^4.25.9",
+ "@uiw/codemirror-themes": "^4.25.9",
+ "@uiw/codemirror-themes-all": "4.25.9",
+ "@uiw/react-codemirror": "^4.25.9",
"axios": "1.12.0",
"classix": "2.2.0",
"date-fns": "4.1.0",
@@ -71,11 +86,13 @@
},
"devDependencies": {
"@eslint/eslintrc": "^3.3.3",
+ "@playwright/experimental-ct-react": "1.57.0",
"@playwright/test": "^1.57.0",
"@tailwindcss/postcss": "^4",
"@types/node": "^20",
"@types/react": "^19",
"@types/react-dom": "^19",
+ "@vitejs/plugin-react": "^4.7.0",
"eslint": "^9",
"eslint-config-next": "16.1.1",
"eslint-plugin-simple-import-sort": "^12.1.1",
@@ -87,6 +104,7 @@
"prettier": "^3.4.2",
"tailwindcss": "^4",
"typescript": "^5",
- "typescript-eslint": "^8.32.1"
+ "typescript-eslint": "^8.32.1",
+ "vite": "^6.4.1"
}
}
diff --git a/ui/playwright-ct.config.ts b/ui/playwright-ct.config.ts
new file mode 100644
index 00000000..f57d4c7f
--- /dev/null
+++ b/ui/playwright-ct.config.ts
@@ -0,0 +1,35 @@
+import path from 'node:path';
+
+import { defineConfig, devices } from '@playwright/experimental-ct-react';
+
+/**
+ * Component tests: mount React in-browser via Vite (no Next.js server).
+ * @see https://playwright.dev/docs/test-components
+ */
+export default defineConfig({
+ testDir: './tests/ct',
+ fullyParallel: true,
+ forbidOnly: !!process.env.CI,
+ retries: process.env.CI ? 2 : 0,
+ workers: process.env.CI ? 2 : undefined,
+ reporter: [['html', { open: 'never' }], ['list']],
+
+ use: {
+ trace: 'on-first-retry',
+ screenshot: 'only-on-failure',
+ ctViteConfig: {
+ resolve: {
+ alias: {
+ '@': path.resolve(__dirname, './src'),
+ },
+ },
+ },
+ },
+
+ projects: [
+ {
+ name: 'chromium',
+ use: { ...devices['Desktop Chrome'] },
+ },
+ ],
+});
diff --git a/ui/playwright.config.ts b/ui/playwright.config.ts
index 60b2ac66..f0c73169 100644
--- a/ui/playwright.config.ts
+++ b/ui/playwright.config.ts
@@ -7,6 +7,8 @@ import { defineConfig, devices } from '@playwright/test';
*/
export default defineConfig({
testDir: './tests',
+ /* Component tests use playwright-ct.config.ts (Vite + mount). */
+ testIgnore: '**/ct/**',
/* Run tests in files in parallel */
fullyParallel: true,
/* Fail the build on CI if you accidentally left test.only in the source code. */
diff --git a/ui/playwright/index.html b/ui/playwright/index.html
new file mode 100644
index 00000000..9b3a31c6
--- /dev/null
+++ b/ui/playwright/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+ Playwright CT
+
+
+
+
+
+
diff --git a/ui/playwright/index.tsx b/ui/playwright/index.tsx
new file mode 100644
index 00000000..a9b87f09
--- /dev/null
+++ b/ui/playwright/index.tsx
@@ -0,0 +1,28 @@
+import '@mantine/charts/styles.css';
+import '@mantine/code-highlight/styles.css';
+import '@mantine/core/styles.css';
+import '@mantine/dates/styles.css';
+import '@mantine/notifications/styles.css';
+import '@rungalileo/icons/styles.css';
+import '@rungalileo/jupiter-ds/styles.css';
+import '@/styles/globals.css';
+
+import { MantineProvider } from '@mantine/core';
+import { DatesProvider } from '@mantine/dates';
+import { ModalsProvider } from '@mantine/modals';
+import { beforeMount } from '@playwright/experimental-ct-react/hooks';
+import { JupiterThemeProvider } from '@rungalileo/jupiter-ds';
+
+import { appTheme } from '@/theme';
+
+beforeMount(async ({ App }) => (
+
+
+
+
+
+
+
+
+
+));
diff --git a/ui/pnpm-lock.yaml b/ui/pnpm-lock.yaml
index 49f92450..af1cf499 100644
--- a/ui/pnpm-lock.yaml
+++ b/ui/pnpm-lock.yaml
@@ -8,9 +8,30 @@ importers:
.:
dependencies:
+ '@codemirror/autocomplete':
+ specifier: ^6.20.1
+ version: 6.20.1
+ '@codemirror/lang-json':
+ specifier: ^6.0.2
+ version: 6.0.2
+ '@codemirror/language':
+ specifier: ^6.12.3
+ version: 6.12.3
+ '@codemirror/lint':
+ specifier: ^6.9.5
+ version: 6.9.5
+ '@codemirror/state':
+ specifier: ^6.6.0
+ version: 6.6.0
+ '@codemirror/view':
+ specifier: ^6.40.0
+ version: 6.40.0
'@emotion/is-prop-valid':
specifier: ^1.4.0
version: 1.4.0
+ '@lezer/highlight':
+ specifier: ^1.2.3
+ version: 1.2.3
'@mantine/charts':
specifier: ^7.17.8
version: 7.17.8(@mantine/core@7.17.5(@mantine/hooks@7.17.5(react@19.1.4))(@types/react@19.2.7)(react-dom@19.1.4(react@19.1.4))(react@19.1.4))(@mantine/hooks@7.17.5(react@19.1.4))(react-dom@19.1.4(react@19.1.4))(react@19.1.4)(recharts@2.15.4(react-dom@19.1.4(react@19.1.4))(react@19.1.4))
@@ -59,6 +80,18 @@ importers:
'@tanstack/react-table':
specifier: 8.20.5
version: 8.20.5(react-dom@19.1.4(react@19.1.4))(react@19.1.4)
+ '@uiw/codemirror-extensions-basic-setup':
+ specifier: ^4.25.9
+ version: 4.25.9(@codemirror/autocomplete@6.20.1)(@codemirror/commands@6.10.3)(@codemirror/language@6.12.3)(@codemirror/lint@6.9.5)(@codemirror/search@6.6.0)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ '@uiw/codemirror-themes':
+ specifier: ^4.25.9
+ version: 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ '@uiw/codemirror-themes-all':
+ specifier: 4.25.9
+ version: 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ '@uiw/react-codemirror':
+ specifier: ^4.25.9
+ version: 4.25.9(@babel/runtime@7.28.4)(@codemirror/autocomplete@6.20.1)(@codemirror/language@6.12.3)(@codemirror/lint@6.9.5)(@codemirror/search@6.6.0)(@codemirror/state@6.6.0)(@codemirror/theme-one-dark@6.1.3)(@codemirror/view@6.40.0)(codemirror@6.0.2)(react-dom@19.1.4(react@19.1.4))(react@19.1.4)
axios:
specifier: 1.12.0
version: 1.12.0
@@ -99,6 +132,9 @@ importers:
'@eslint/eslintrc':
specifier: ^3.3.3
version: 3.3.3
+ '@playwright/experimental-ct-react':
+ specifier: 1.57.0
+ version: 1.57.0(@types/node@20.19.27)(jiti@2.6.1)(lightningcss@1.30.2)(sugarss@4.0.1(postcss@8.5.6))(vite@6.4.1(@types/node@20.19.27)(jiti@2.6.1)(lightningcss@1.30.2)(sugarss@4.0.1(postcss@8.5.6)))
'@playwright/test':
specifier: ^1.57.0
version: 1.57.0
@@ -114,6 +150,9 @@ importers:
'@types/react-dom':
specifier: ^19
version: 19.2.3(@types/react@19.2.7)
+ '@vitejs/plugin-react':
+ specifier: ^4.7.0
+ version: 4.7.0(vite@6.4.1(@types/node@20.19.27)(jiti@2.6.1)(lightningcss@1.30.2)(sugarss@4.0.1(postcss@8.5.6)))
eslint:
specifier: ^9
version: 9.39.2(jiti@2.6.1)
@@ -150,6 +189,9 @@ importers:
typescript-eslint:
specifier: ^8.32.1
version: 8.51.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
+ vite:
+ specifier: ^6.4.1
+ version: 6.4.1(@types/node@20.19.27)(jiti@2.6.1)(lightningcss@1.30.2)(sugarss@4.0.1(postcss@8.5.6))
packages:
@@ -191,6 +233,10 @@ packages:
peerDependencies:
'@babel/core': ^7.0.0
+ '@babel/helper-plugin-utils@7.28.6':
+ resolution: {integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==}
+ engines: {node: '>=6.9.0'}
+
'@babel/helper-string-parser@7.27.1':
resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==}
engines: {node: '>=6.9.0'}
@@ -212,6 +258,18 @@ packages:
engines: {node: '>=6.0.0'}
hasBin: true
+ '@babel/plugin-transform-react-jsx-self@7.27.1':
+ resolution: {integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-react-jsx-source@7.27.1':
+ resolution: {integrity: sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/runtime@7.28.4':
resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==}
engines: {node: '>=6.9.0'}
@@ -228,6 +286,33 @@ packages:
resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==}
engines: {node: '>=6.9.0'}
+ '@codemirror/autocomplete@6.20.1':
+ resolution: {integrity: sha512-1cvg3Vz1dSSToCNlJfRA2WSI4ht3K+WplO0UMOgmUYPivCyy2oueZY6Lx7M9wThm7SDUBViRmuT+OG/i8+ON9A==}
+
+ '@codemirror/commands@6.10.3':
+ resolution: {integrity: sha512-JFRiqhKu+bvSkDLI+rUhJwSxQxYb759W5GBezE8Uc8mHLqC9aV/9aTC7yJSqCtB3F00pylrLCwnyS91Ap5ej4Q==}
+
+ '@codemirror/lang-json@6.0.2':
+ resolution: {integrity: sha512-x2OtO+AvwEHrEwR0FyyPtfDUiloG3rnVTSZV1W8UteaLL8/MajQd8DpvUb2YVzC+/T18aSDv0H9mu+xw0EStoQ==}
+
+ '@codemirror/language@6.12.3':
+ resolution: {integrity: sha512-QwCZW6Tt1siP37Jet9Tb02Zs81TQt6qQrZR2H+eGMcFsL1zMrk2/b9CLC7/9ieP1fjIUMgviLWMmgiHoJrj+ZA==}
+
+ '@codemirror/lint@6.9.5':
+ resolution: {integrity: sha512-GElsbU9G7QT9xXhpUg1zWGmftA/7jamh+7+ydKRuT0ORpWS3wOSP0yT1FOlIZa7mIJjpVPipErsyvVqB9cfTFA==}
+
+ '@codemirror/search@6.6.0':
+ resolution: {integrity: sha512-koFuNXcDvyyotWcgOnZGmY7LZqEOXZaaxD/j6n18TCLx2/9HieZJ5H6hs1g8FiRxBD0DNfs0nXn17g872RmYdw==}
+
+ '@codemirror/state@6.6.0':
+ resolution: {integrity: sha512-4nbvra5R5EtiCzr9BTHiTLc+MLXK2QGiAVYMyi8PkQd3SR+6ixar/Q/01Fa21TBIDOZXgeWV4WppsQolSreAPQ==}
+
+ '@codemirror/theme-one-dark@6.1.3':
+ resolution: {integrity: sha512-NzBdIvEJmx6fjeremiGp3t/okrLPYT0d9orIc7AFun8oZcRk58aejkqhv6spnz4MLAevrKNPMQYXEWMg4s+sKA==}
+
+ '@codemirror/view@6.40.0':
+ resolution: {integrity: sha512-WA0zdU7xfF10+5I3HhUUq3kqOx3KjqmtQ9lqZjfK7jtYk4G72YW9rezcSywpaUMCWOMlq+6E0pO1IWg1TNIhtg==}
+
'@emnapi/core@1.8.1':
resolution: {integrity: sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==}
@@ -243,6 +328,162 @@ packages:
'@emotion/memoize@0.9.0':
resolution: {integrity: sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==}
+ '@esbuild/aix-ppc64@0.25.12':
+ resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==}
+ engines: {node: '>=18'}
+ cpu: [ppc64]
+ os: [aix]
+
+ '@esbuild/android-arm64@0.25.12':
+ resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [android]
+
+ '@esbuild/android-arm@0.25.12':
+ resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==}
+ engines: {node: '>=18'}
+ cpu: [arm]
+ os: [android]
+
+ '@esbuild/android-x64@0.25.12':
+ resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [android]
+
+ '@esbuild/darwin-arm64@0.25.12':
+ resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@esbuild/darwin-x64@0.25.12':
+ resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@esbuild/freebsd-arm64@0.25.12':
+ resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [freebsd]
+
+ '@esbuild/freebsd-x64@0.25.12':
+ resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@esbuild/linux-arm64@0.25.12':
+ resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@esbuild/linux-arm@0.25.12':
+ resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==}
+ engines: {node: '>=18'}
+ cpu: [arm]
+ os: [linux]
+
+ '@esbuild/linux-ia32@0.25.12':
+ resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==}
+ engines: {node: '>=18'}
+ cpu: [ia32]
+ os: [linux]
+
+ '@esbuild/linux-loong64@0.25.12':
+ resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==}
+ engines: {node: '>=18'}
+ cpu: [loong64]
+ os: [linux]
+
+ '@esbuild/linux-mips64el@0.25.12':
+ resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==}
+ engines: {node: '>=18'}
+ cpu: [mips64el]
+ os: [linux]
+
+ '@esbuild/linux-ppc64@0.25.12':
+ resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==}
+ engines: {node: '>=18'}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@esbuild/linux-riscv64@0.25.12':
+ resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==}
+ engines: {node: '>=18'}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@esbuild/linux-s390x@0.25.12':
+ resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==}
+ engines: {node: '>=18'}
+ cpu: [s390x]
+ os: [linux]
+
+ '@esbuild/linux-x64@0.25.12':
+ resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [linux]
+
+ '@esbuild/netbsd-arm64@0.25.12':
+ resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [netbsd]
+
+ '@esbuild/netbsd-x64@0.25.12':
+ resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [netbsd]
+
+ '@esbuild/openbsd-arm64@0.25.12':
+ resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [openbsd]
+
+ '@esbuild/openbsd-x64@0.25.12':
+ resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [openbsd]
+
+ '@esbuild/openharmony-arm64@0.25.12':
+ resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [openharmony]
+
+ '@esbuild/sunos-x64@0.25.12':
+ resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [sunos]
+
+ '@esbuild/win32-arm64@0.25.12':
+ resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@esbuild/win32-ia32@0.25.12':
+ resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==}
+ engines: {node: '>=18'}
+ cpu: [ia32]
+ os: [win32]
+
+ '@esbuild/win32-x64@0.25.12':
+ resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [win32]
+
'@eslint-community/eslint-utils@4.9.1':
resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -487,6 +728,18 @@ packages:
'@jridgewell/trace-mapping@0.3.31':
resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
+ '@lezer/common@1.5.1':
+ resolution: {integrity: sha512-6YRVG9vBkaY7p1IVxL4s44n5nUnaNnGM2/AckNgYOnxTG2kWh1vR8BMxPseWPjRNpb5VtXnMpeYAEAADoRV1Iw==}
+
+ '@lezer/highlight@1.2.3':
+ resolution: {integrity: sha512-qXdH7UqTvGfdVBINrgKhDsVTJTxactNNxLk7+UMwZhU13lMHaOBlJe9Vqp907ya56Y3+ed2tlqzys7jDkTmW0g==}
+
+ '@lezer/json@1.0.3':
+ resolution: {integrity: sha512-BP9KzdF9Y35PDpv04r0VeSTKDeox5vVr3efE7eBbx3r4s3oNLfunchejZhjArmeieBH+nVOpgIiBJpEAv8ilqQ==}
+
+ '@lezer/lr@1.4.8':
+ resolution: {integrity: sha512-bPWa0Pgx69ylNlMlPvBPryqeLYQjyJjqPx+Aupm5zydLIF3NE+6MMLT8Yi23Bd9cif9VS00aUebn+6fDIGBcDA==}
+
'@mantine/charts@7.17.8':
resolution: {integrity: sha512-lzDa2JM0uD2X32vnUPtERJc4V5nYkrbpOpnC/G3p0Kkwcxh9v59p5uMDxHXoHcv/OsMPALKYWBkY9aGWvD/E4g==}
peerDependencies:
@@ -559,6 +812,9 @@ packages:
peerDependencies:
react: ^18.x || ^19.x
+ '@marijn/find-cluster-break@1.0.2':
+ resolution: {integrity: sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==}
+
'@monaco-editor/loader@1.7.0':
resolution: {integrity: sha512-gIwR1HrJrrx+vfyOhYmCZ0/JcWqG5kbfG7+d3f/C1LXk2EvzAbHSg3MQ5lO2sMlo9izoAZ04shohfKLVT6crVA==}
@@ -646,6 +902,15 @@ packages:
resolution: {integrity: sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==}
engines: {node: '>=12.4.0'}
+ '@playwright/experimental-ct-core@1.57.0':
+ resolution: {integrity: sha512-Z5Uh+61vR5FDRE+YJIMrnD8m6i2wJmYK525AHCJNcAcGcEC+i7xuMnZmZkg+booi3YHIwql/ApAlm03+jsCIzQ==}
+ engines: {node: '>=18'}
+
+ '@playwright/experimental-ct-react@1.57.0':
+ resolution: {integrity: sha512-wNRmkLOxHEXA9OL7QggNYVHnqaGlMOTB5q9FhrnlcFHHRs+M8SH9mQy5//dGFoYKAkhuZf4GPA3poi9bBdkdfQ==}
+ engines: {node: '>=18'}
+ hasBin: true
+
'@playwright/test@1.57.0':
resolution: {integrity: sha512-6TyEnHgd6SArQO8UO2OMTxshln3QMWBtPGrOCgs3wVEmQmwyuNtB10IZMfmYDE0riwNR1cu4q+pPcxMVtaG3TA==}
engines: {node: '>=18'}
@@ -661,6 +926,147 @@ packages:
resolution: {integrity: sha512-2+O+riuIUgVSuLl3Lyh5AplWZyVMNuG2F98/o6NrutKJfW4/GTZdPpZlIphS0HGgcOHgmWcCSHj+dWFlZaGSHw==}
engines: {node: '>=18.17.0', npm: '>=9.5.0'}
+ '@rolldown/pluginutils@1.0.0-beta.27':
+ resolution: {integrity: sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==}
+
+ '@rollup/rollup-android-arm-eabi@4.60.1':
+ resolution: {integrity: sha512-d6FinEBLdIiK+1uACUttJKfgZREXrF0Qc2SmLII7W2AD8FfiZ9Wjd+rD/iRuf5s5dWrr1GgwXCvPqOuDquOowA==}
+ cpu: [arm]
+ os: [android]
+
+ '@rollup/rollup-android-arm64@4.60.1':
+ resolution: {integrity: sha512-YjG/EwIDvvYI1YvYbHvDz/BYHtkY4ygUIXHnTdLhG+hKIQFBiosfWiACWortsKPKU/+dUwQQCKQM3qrDe8c9BA==}
+ cpu: [arm64]
+ os: [android]
+
+ '@rollup/rollup-darwin-arm64@4.60.1':
+ resolution: {integrity: sha512-mjCpF7GmkRtSJwon+Rq1N8+pI+8l7w5g9Z3vWj4T7abguC4Czwi3Yu/pFaLvA3TTeMVjnu3ctigusqWUfjZzvw==}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@rollup/rollup-darwin-x64@4.60.1':
+ resolution: {integrity: sha512-haZ7hJ1JT4e9hqkoT9R/19XW2QKqjfJVv+i5AGg57S+nLk9lQnJ1F/eZloRO3o9Scy9CM3wQ9l+dkXtcBgN5Ew==}
+ cpu: [x64]
+ os: [darwin]
+
+ '@rollup/rollup-freebsd-arm64@4.60.1':
+ resolution: {integrity: sha512-czw90wpQq3ZsAVBlinZjAYTKduOjTywlG7fEeWKUA7oCmpA8xdTkxZZlwNJKWqILlq0wehoZcJYfBvOyhPTQ6w==}
+ cpu: [arm64]
+ os: [freebsd]
+
+ '@rollup/rollup-freebsd-x64@4.60.1':
+ resolution: {integrity: sha512-KVB2rqsxTHuBtfOeySEyzEOB7ltlB/ux38iu2rBQzkjbwRVlkhAGIEDiiYnO2kFOkJp+Z7pUXKyrRRFuFUKt+g==}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@rollup/rollup-linux-arm-gnueabihf@4.60.1':
+ resolution: {integrity: sha512-L+34Qqil+v5uC0zEubW7uByo78WOCIrBvci69E7sFASRl0X7b/MB6Cqd1lky/CtcSVTydWa2WZwFuWexjS5o6g==}
+ cpu: [arm]
+ os: [linux]
+ libc: [glibc]
+
+ '@rollup/rollup-linux-arm-musleabihf@4.60.1':
+ resolution: {integrity: sha512-n83O8rt4v34hgFzlkb1ycniJh7IR5RCIqt6mz1VRJD6pmhRi0CXdmfnLu9dIUS6buzh60IvACM842Ffb3xd6Gg==}
+ cpu: [arm]
+ os: [linux]
+ libc: [musl]
+
+ '@rollup/rollup-linux-arm64-gnu@4.60.1':
+ resolution: {integrity: sha512-Nql7sTeAzhTAja3QXeAI48+/+GjBJ+QmAH13snn0AJSNL50JsDqotyudHyMbO2RbJkskbMbFJfIJKWA6R1LCJQ==}
+ cpu: [arm64]
+ os: [linux]
+ libc: [glibc]
+
+ '@rollup/rollup-linux-arm64-musl@4.60.1':
+ resolution: {integrity: sha512-+pUymDhd0ys9GcKZPPWlFiZ67sTWV5UU6zOJat02M1+PiuSGDziyRuI/pPue3hoUwm2uGfxdL+trT6Z9rxnlMA==}
+ cpu: [arm64]
+ os: [linux]
+ libc: [musl]
+
+ '@rollup/rollup-linux-loong64-gnu@4.60.1':
+ resolution: {integrity: sha512-VSvgvQeIcsEvY4bKDHEDWcpW4Yw7BtlKG1GUT4FzBUlEKQK0rWHYBqQt6Fm2taXS+1bXvJT6kICu5ZwqKCnvlQ==}
+ cpu: [loong64]
+ os: [linux]
+ libc: [glibc]
+
+ '@rollup/rollup-linux-loong64-musl@4.60.1':
+ resolution: {integrity: sha512-4LqhUomJqwe641gsPp6xLfhqWMbQV04KtPp7/dIp0nzPxAkNY1AbwL5W0MQpcalLYk07vaW9Kp1PBhdpZYYcEw==}
+ cpu: [loong64]
+ os: [linux]
+ libc: [musl]
+
+ '@rollup/rollup-linux-ppc64-gnu@4.60.1':
+ resolution: {integrity: sha512-tLQQ9aPvkBxOc/EUT6j3pyeMD6Hb8QF2BTBnCQWP/uu1lhc9AIrIjKnLYMEroIz/JvtGYgI9dF3AxHZNaEH0rw==}
+ cpu: [ppc64]
+ os: [linux]
+ libc: [glibc]
+
+ '@rollup/rollup-linux-ppc64-musl@4.60.1':
+ resolution: {integrity: sha512-RMxFhJwc9fSXP6PqmAz4cbv3kAyvD1etJFjTx4ONqFP9DkTkXsAMU4v3Vyc5BgzC+anz7nS/9tp4obsKfqkDHg==}
+ cpu: [ppc64]
+ os: [linux]
+ libc: [musl]
+
+ '@rollup/rollup-linux-riscv64-gnu@4.60.1':
+ resolution: {integrity: sha512-QKgFl+Yc1eEk6MmOBfRHYF6lTxiiiV3/z/BRrbSiW2I7AFTXoBFvdMEyglohPj//2mZS4hDOqeB0H1ACh3sBbg==}
+ cpu: [riscv64]
+ os: [linux]
+ libc: [glibc]
+
+ '@rollup/rollup-linux-riscv64-musl@4.60.1':
+ resolution: {integrity: sha512-RAjXjP/8c6ZtzatZcA1RaQr6O1TRhzC+adn8YZDnChliZHviqIjmvFwHcxi4JKPSDAt6Uhf/7vqcBzQJy0PDJg==}
+ cpu: [riscv64]
+ os: [linux]
+ libc: [musl]
+
+ '@rollup/rollup-linux-s390x-gnu@4.60.1':
+ resolution: {integrity: sha512-wcuocpaOlaL1COBYiA89O6yfjlp3RwKDeTIA0hM7OpmhR1Bjo9j31G1uQVpDlTvwxGn2nQs65fBFL5UFd76FcQ==}
+ cpu: [s390x]
+ os: [linux]
+ libc: [glibc]
+
+ '@rollup/rollup-linux-x64-gnu@4.60.1':
+ resolution: {integrity: sha512-77PpsFQUCOiZR9+LQEFg9GClyfkNXj1MP6wRnzYs0EeWbPcHs02AXu4xuUbM1zhwn3wqaizle3AEYg5aeoohhg==}
+ cpu: [x64]
+ os: [linux]
+ libc: [glibc]
+
+ '@rollup/rollup-linux-x64-musl@4.60.1':
+ resolution: {integrity: sha512-5cIATbk5vynAjqqmyBjlciMJl1+R/CwX9oLk/EyiFXDWd95KpHdrOJT//rnUl4cUcskrd0jCCw3wpZnhIHdD9w==}
+ cpu: [x64]
+ os: [linux]
+ libc: [musl]
+
+ '@rollup/rollup-openbsd-x64@4.60.1':
+ resolution: {integrity: sha512-cl0w09WsCi17mcmWqqglez9Gk8isgeWvoUZ3WiJFYSR3zjBQc2J5/ihSjpl+VLjPqjQ/1hJRcqBfLjssREQILw==}
+ cpu: [x64]
+ os: [openbsd]
+
+ '@rollup/rollup-openharmony-arm64@4.60.1':
+ resolution: {integrity: sha512-4Cv23ZrONRbNtbZa37mLSueXUCtN7MXccChtKpUnQNgF010rjrjfHx3QxkS2PI7LqGT5xXyYs1a7LbzAwT0iCA==}
+ cpu: [arm64]
+ os: [openharmony]
+
+ '@rollup/rollup-win32-arm64-msvc@4.60.1':
+ resolution: {integrity: sha512-i1okWYkA4FJICtr7KpYzFpRTHgy5jdDbZiWfvny21iIKky5YExiDXP+zbXzm3dUcFpkEeYNHgQ5fuG236JPq0g==}
+ cpu: [arm64]
+ os: [win32]
+
+ '@rollup/rollup-win32-ia32-msvc@4.60.1':
+ resolution: {integrity: sha512-u09m3CuwLzShA0EYKMNiFgcjjzwqtUMLmuCJLeZWjjOYA3IT2Di09KaxGBTP9xVztWyIWjVdsB2E9goMjZvTQg==}
+ cpu: [ia32]
+ os: [win32]
+
+ '@rollup/rollup-win32-x64-gnu@4.60.1':
+ resolution: {integrity: sha512-k+600V9Zl1CM7eZxJgMyTUzmrmhB/0XZnF4pRypKAlAgxmedUA+1v9R+XOFv56W4SlHEzfeMtzujLJD22Uz5zg==}
+ cpu: [x64]
+ os: [win32]
+
+ '@rollup/rollup-win32-x64-msvc@4.60.1':
+ resolution: {integrity: sha512-lWMnixq/QzxyhTV6NjQJ4SFo1J6PvOX8vUx5Wb4bBPsEb+8xZ89Bz6kOXpfXj9ak9AHTQVQzlgzBEc1SyM27xQ==}
+ cpu: [x64]
+ os: [win32]
+
'@rtsao/scc@1.1.0':
resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==}
@@ -815,6 +1221,18 @@ packages:
'@tybys/wasm-util@0.10.1':
resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==}
+ '@types/babel__core@7.20.5':
+ resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==}
+
+ '@types/babel__generator@7.27.0':
+ resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==}
+
+ '@types/babel__template@7.4.4':
+ resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==}
+
+ '@types/babel__traverse@7.28.0':
+ resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==}
+
'@types/d3-array@3.2.2':
resolution: {integrity: sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==}
@@ -924,6 +1342,143 @@ packages:
resolution: {integrity: sha512-mM/JRQOzhVN1ykejrvwnBRV3+7yTKK8tVANVN3o1O0t0v7o+jqdVu9crPy5Y9dov15TJk/FTIgoUGHrTOVL3Zg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ '@uiw/codemirror-extensions-basic-setup@4.25.9':
+ resolution: {integrity: sha512-QFAqr+pu6lDmNpAlecODcF49TlsrZ0bj15zPzfhiqSDl+Um3EsDLFLppixC7kFLn+rdDM2LTvVjn5CPvefpRgw==}
+ peerDependencies:
+ '@codemirror/autocomplete': '>=6.0.0'
+ '@codemirror/commands': '>=6.0.0'
+ '@codemirror/language': '>=6.0.0'
+ '@codemirror/lint': '>=6.0.0'
+ '@codemirror/search': '>=6.0.0'
+ '@codemirror/state': '>=6.0.0'
+ '@codemirror/view': '>=6.0.0'
+
+ '@uiw/codemirror-theme-abcdef@4.25.9':
+ resolution: {integrity: sha512-F6bZcm20N3r4ZeCMdyjjII/fYHqE17sbRk6pFWfU+NPxe522A/uaRKpEaBK/iDwYqpKZgI3XUz7j3KcYzA99Mg==}
+
+ '@uiw/codemirror-theme-abyss@4.25.9':
+ resolution: {integrity: sha512-zcMHX3abHsaV+IRhnHeWA5aYTP/9HTk/MR5Zh3pfwASv8YMsQlcjBva8vEZULV9pJDferW/9GXbKbbPdmceJeg==}
+
+ '@uiw/codemirror-theme-androidstudio@4.25.9':
+ resolution: {integrity: sha512-HPIWpEC9ElhpJ2NZUKB6z+eStQzFDrkIGW9pTJxYHSCv2Los7FgD/R6eGqjTS4LVlBf9FR+KU/5E6dLT8DQHlw==}
+
+ '@uiw/codemirror-theme-andromeda@4.25.9':
+ resolution: {integrity: sha512-JSqK8/sVFbFfTyv/okaT4c8suulf9zasqd4YBuTSkPZo+Sd/50blxMSVe5IWwDSiW5hkiupb7FC2IP1siHhncw==}
+
+ '@uiw/codemirror-theme-atomone@4.25.9':
+ resolution: {integrity: sha512-EXG/+p+Y9j/StU2yAtz/+JZj/8WaSGqwjsad79CSBgpHrSU0ERzv4urYWXgEmLTKKkFimwTigy7qOJlLAwkN2A==}
+
+ '@uiw/codemirror-theme-aura@4.25.9':
+ resolution: {integrity: sha512-cJyInS81wh0lWYs1XDiyFSxCCXrJ+4qifBsDHSYELdLgbnr441T3Kr6a9lyUobtL4DZVaIaCKE9rajrFdJIeAw==}
+
+ '@uiw/codemirror-theme-basic@4.25.9':
+ resolution: {integrity: sha512-40x+anangMmPziZSeEcg6P5YDLn7fF1ioS5VxEPXMGUTbikv0au4PXVNsf7CtP0VwO4MmGt87zZI6rQIexEP3w==}
+
+ '@uiw/codemirror-theme-bbedit@4.25.9':
+ resolution: {integrity: sha512-SGXQ0tLsqcRvxXCrdeU/MiQ3liNKvr8DCxaSt4N5LP7EPGO94ebuvba0F+H/3LpeJJrn5Xq0FuhaPlMYJ10RXg==}
+
+ '@uiw/codemirror-theme-bespin@4.25.9':
+ resolution: {integrity: sha512-Zr35B1FpM+VMIoHot397GP/dQBWkFz6SlFqf3JSX6wlwgy2d4ot3YF9fBglGkM3C3ITmkBBQRnlvELwke+dXBg==}
+
+ '@uiw/codemirror-theme-console@4.25.9':
+ resolution: {integrity: sha512-vhN9QKStneKyiNzu+DuA5JOss9WfzecuDjvmEYApQL9zvRmNUAP6La0C2vpZCji1Y23OAFZUJvTU+eKbept3cw==}
+
+ '@uiw/codemirror-theme-copilot@4.25.9':
+ resolution: {integrity: sha512-MLBXBEp+jDQC+BbFUQxxwsOKvhbCsIpIjwBgNfR4KKKQxD6tF6u+CE7ERcrRWJ6cCV2lDrs1IZRZGPQCSpHMIA==}
+
+ '@uiw/codemirror-theme-darcula@4.25.9':
+ resolution: {integrity: sha512-lrex1DXg/mx2BX1UtnyFlat7w6c3RyE5GMvyR8uPfXNAXMUEKjYxNRdUuQ9WGlOMzQZ3x+UbKnUZd/r6AmXwsw==}
+
+ '@uiw/codemirror-theme-dracula@4.25.9':
+ resolution: {integrity: sha512-0VTnpPCHPc+7LqYsQOX6nvW32XiiT+O6kJjReUbV7Eio3vPHsb+b9P4DKhz4AAvIIYMxmHkMuautHKuWktFXSg==}
+
+ '@uiw/codemirror-theme-duotone@4.25.9':
+ resolution: {integrity: sha512-6IPZncdrtcgnU1EtQ1/IzaULZ+Jw5uAeVeQCae+rFBnW/m6Q8nWB8+iVnk8kCevgjT5ScZmRd9h4yqtSeJbUwQ==}
+
+ '@uiw/codemirror-theme-eclipse@4.25.9':
+ resolution: {integrity: sha512-0pT0vRyLAotj5UjIZbHSmsZ8oz7l8IU5bhx5p7MDrTOdi73ZjyTsG4YsDzSXndERnfgkBbZJrlZiExBkXnhtUA==}
+
+ '@uiw/codemirror-theme-github@4.25.9':
+ resolution: {integrity: sha512-AGpTamNiySKNzq3Jc7QjpwgQRVaHUaBtmOKiUDghYSfEGjsc5uW4NUW70sSU3BnkGv+lCTUnF3175KM24BWZbw==}
+
+ '@uiw/codemirror-theme-gruvbox-dark@4.25.9':
+ resolution: {integrity: sha512-9qIa1z4zwubN2kHAs+lJvdrmMMMf69JeyVPAwSoNaImL8wUQ/J3291qcfuoZjv8RsqSzrKTgxqLHtkAhB7xcwg==}
+
+ '@uiw/codemirror-theme-kimbie@4.25.9':
+ resolution: {integrity: sha512-zLjT7MkotuT07rx4ZPZOM1/H+sa+kCmJr5BDu2ASNpF7Sj4w0cTNcAyxKHj+N6LcgIM8PICxqB97CJhlurNTBA==}
+
+ '@uiw/codemirror-theme-material@4.25.9':
+ resolution: {integrity: sha512-6f2x+gmj2hHagqy6VkpnPbK7SWyP6kKruGgqpyIy09/f9pAUCqkW8mRY5ZEr28tA+YEGQaSY0Z2IBCHl8OKJog==}
+
+ '@uiw/codemirror-theme-monokai-dimmed@4.25.9':
+ resolution: {integrity: sha512-6/Z9tF4UFngaXifAKC4DI2l61G3rtcWOxvCwgs5zzNVMTciUI+Bl/K7eCvjf2y0LfLmK8Ovob8ODDBcVgwzp5g==}
+
+ '@uiw/codemirror-theme-monokai@4.25.9':
+ resolution: {integrity: sha512-qKWRZOGpBCasZJdYU+SsXd92TjncF3QYHpraCPe29bxN22jeIxi2UC4MCuJHwa8hHljHOCSdx1XG/GuUMn7XiQ==}
+
+ '@uiw/codemirror-theme-noctis-lilac@4.25.9':
+ resolution: {integrity: sha512-HXjQutWsVYfiBM6ze4SomXmSJNzYYJ/fUYJ3TJLhnp5cjIPNBsMsgOAaWp3L64xUqqorb0+1y6kdmUKxTEp6rQ==}
+
+ '@uiw/codemirror-theme-nord@4.25.9':
+ resolution: {integrity: sha512-5c568xmMidwICADxACB1zIhKoEgqbdVrdeOUZ2p5pE6NNKGR4ATzk9OSqhvr1ZhZPNOktxqSLLRzihFaZG0bDQ==}
+
+ '@uiw/codemirror-theme-okaidia@4.25.9':
+ resolution: {integrity: sha512-lIJFUs/ws0prQz+dVo5ZIp0o6vxW7p6nf8iRFETN5S3KA3nJUR2cTF6u8mYLFwHMrFs2eReRsFyH94wjmuPWvg==}
+
+ '@uiw/codemirror-theme-quietlight@4.25.9':
+ resolution: {integrity: sha512-BWFcFb3WHTCVROkjExh/TMMTJ5SNcDafaVEIwneKypiHoTJoIY6RlSRBj6GA3O5IgKdrGmhje87s0Gx2OLIndg==}
+
+ '@uiw/codemirror-theme-red@4.25.9':
+ resolution: {integrity: sha512-pSOs2ByCVGJXbABhfTEU4TlRh/Wa9BJlDUa219iq1jO3AUDUM/LIPNLhmQvMtOituMX8WKJprspBrDcveXsisg==}
+
+ '@uiw/codemirror-theme-solarized@4.25.9':
+ resolution: {integrity: sha512-axUgU9+3JKXW83F+te454qcyTmQAm0+2Fxv0yoegiH6bdl7DjFq/lNVGGZtLwN47AQCj2Qwrheeet2t3GbY9VQ==}
+
+ '@uiw/codemirror-theme-sublime@4.25.9':
+ resolution: {integrity: sha512-/Ha1K3P0sqFWrsYtCu6Uih/t8C73dVY6m5rObjCnnokr//kOusKwlwt1fJiEFdIcSKlH2WBIvW5tb75tcYitnw==}
+
+ '@uiw/codemirror-theme-tokyo-night-day@4.25.9':
+ resolution: {integrity: sha512-1ziFletBO6tfRtX4FVWij1wYIf95uYi54dgnMz5CXe4A4u710rJ3uS3C4ijlnclRbwHjNTqtrMWNuicKDBMsPg==}
+
+ '@uiw/codemirror-theme-tokyo-night-storm@4.25.9':
+ resolution: {integrity: sha512-qz8Vg+ze12TuLk+fqwx3oga3H6rDE+81PpKMGLfbI1BwPDgg7GZGTGrWZoN1Bpf6EV0dA4WO8K6lbzFhlS6S1Q==}
+
+ '@uiw/codemirror-theme-tokyo-night@4.25.9':
+ resolution: {integrity: sha512-NkSqguMpzRjsRBbTIfOrGS35tQkE3K8AAetZHlbRZC7fnI52RreZ11X41cOYrc/Dapt8xqUPlhlvclymGFgy8g==}
+
+ '@uiw/codemirror-theme-tomorrow-night-blue@4.25.9':
+ resolution: {integrity: sha512-iG2wCXO/rkJIrvW7rJY7Ehh4yushw8X4vQnstjArxofR6uNrE9ay3Ut7M0cxrwY7z8YIU5f7NQFODE/h3HNmVA==}
+
+ '@uiw/codemirror-theme-vscode@4.25.9':
+ resolution: {integrity: sha512-9KTnScHTSk97yGnyNYvDm6QZuBCdbO1OzMQ5bHtoBSPSVtH0LjY3bS6CXsBagb22v8OLPx/XwrBYOjKFp409CQ==}
+
+ '@uiw/codemirror-theme-white@4.25.9':
+ resolution: {integrity: sha512-75PHfVejBvgF1EbponpEOgND/T6MJYZ673aODPuR7mKPZNfn8649qOSrp7wvMN/NEZ+W5CxV3U7tb9MQWPcM4A==}
+
+ '@uiw/codemirror-theme-xcode@4.25.9':
+ resolution: {integrity: sha512-sMiDpOiW0iiNsLyqL1Vx6wZKOSoVUNfmWbBDtaYzlkRcKzkyJQp68cPIq5VG8Mhl2z+PX5cPbOA0nZEegNLicA==}
+
+ '@uiw/codemirror-themes-all@4.25.9':
+ resolution: {integrity: sha512-OVcGb6dkgJ8NgcHFvSQkRLHHIRswZhBKK0XZZzRVMxDnCIXfmnDfeChNoKjuzwBr+C0jS7UAAqrWbcqrLj3mhg==}
+
+ '@uiw/codemirror-themes@4.25.9':
+ resolution: {integrity: sha512-DAHKb/L9ELwjY4nCf/MP/mIllHOn4GQe7RR4x8AMJuNeh9nGRRoo1uPxrxMmUL/bKqe6kDmDbIZ2AlhlqyIJuw==}
+ peerDependencies:
+ '@codemirror/language': '>=6.0.0'
+ '@codemirror/state': '>=6.0.0'
+ '@codemirror/view': '>=6.0.0'
+
+ '@uiw/react-codemirror@4.25.9':
+ resolution: {integrity: sha512-HftqCBUYShAOH0pGi1CHP8vfm5L8fQ3+0j0VI6lQD6QpK+UBu3J7nxfEN5O/BXMilMNf9ZyFJRvRcuMMOLHMng==}
+ peerDependencies:
+ '@babel/runtime': '>=7.11.0'
+ '@codemirror/state': '>=6.0.0'
+ '@codemirror/theme-one-dark': '>=6.0.0'
+ '@codemirror/view': '>=6.0.0'
+ codemirror: '>=6.0.0'
+ react: '>=17.0.0'
+ react-dom: '>=17.0.0'
+
'@unrs/resolver-binding-android-arm-eabi@1.11.1':
resolution: {integrity: sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==}
cpu: [arm]
@@ -1027,6 +1582,12 @@ packages:
cpu: [x64]
os: [win32]
+ '@vitejs/plugin-react@4.7.0':
+ resolution: {integrity: sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==}
+ engines: {node: ^14.18.0 || >=16.0.0}
+ peerDependencies:
+ vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0
+
acorn-jsx@5.3.2:
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
peerDependencies:
@@ -1202,6 +1763,9 @@ packages:
resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==}
engines: {node: '>=6'}
+ codemirror@6.0.2:
+ resolution: {integrity: sha512-VhydHotNW5w1UGK0Qj96BwSk/Zqbp9WbnyK2W/eVMv4QyF41INRGpjUhFJY7/uDNuudSc33a/PKr4iDqRduvHw==}
+
color-convert@1.9.3:
resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
@@ -1228,6 +1792,9 @@ packages:
convert-source-map@2.0.0:
resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
+ crelt@1.0.6:
+ resolution: {integrity: sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==}
+
cross-spawn@7.0.6:
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
engines: {node: '>= 8'}
@@ -1418,6 +1985,11 @@ packages:
resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==}
engines: {node: '>= 0.4'}
+ esbuild@0.25.12:
+ resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==}
+ engines: {node: '>=18'}
+ hasBin: true
+
escalade@3.2.0:
resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
engines: {node: '>=6'}
@@ -1658,6 +2230,11 @@ packages:
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
os: [darwin]
+ fsevents@2.3.3:
+ resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
+ engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
+ os: [darwin]
+
function-bind@1.1.2:
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
@@ -2459,6 +3036,10 @@ packages:
react: ^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
react-dom: ^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+ react-refresh@0.17.0:
+ resolution: {integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==}
+ engines: {node: '>=0.10.0'}
+
react-remove-scroll-bar@2.3.8:
resolution: {integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==}
engines: {node: '>=10'}
@@ -2565,6 +3146,11 @@ packages:
resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==}
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
+ rollup@4.60.1:
+ resolution: {integrity: sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w==}
+ engines: {node: '>=18.0.0', npm: '>=8.0.0'}
+ hasBin: true
+
run-parallel@1.2.0:
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
@@ -2700,6 +3286,9 @@ packages:
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
engines: {node: '>=8'}
+ style-mod@4.1.3:
+ resolution: {integrity: sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ==}
+
styled-jsx@5.1.6:
resolution: {integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==}
engines: {node: '>= 12.0.0'}
@@ -2886,6 +3475,49 @@ packages:
victory-vendor@36.9.2:
resolution: {integrity: sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==}
+ vite@6.4.1:
+ resolution: {integrity: sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==}
+ engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
+ hasBin: true
+ peerDependencies:
+ '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0
+ jiti: '>=1.21.0'
+ less: '*'
+ lightningcss: ^1.21.0
+ sass: '*'
+ sass-embedded: '*'
+ stylus: '*'
+ sugarss: '*'
+ terser: ^5.16.0
+ tsx: ^4.8.1
+ yaml: ^2.4.2
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+ jiti:
+ optional: true
+ less:
+ optional: true
+ lightningcss:
+ optional: true
+ sass:
+ optional: true
+ sass-embedded:
+ optional: true
+ stylus:
+ optional: true
+ sugarss:
+ optional: true
+ terser:
+ optional: true
+ tsx:
+ optional: true
+ yaml:
+ optional: true
+
+ w3c-keyname@2.2.8:
+ resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==}
+
which-boxed-primitive@1.1.1:
resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==}
engines: {node: '>= 0.4'}
@@ -3000,6 +3632,8 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@babel/helper-plugin-utils@7.28.6': {}
+
'@babel/helper-string-parser@7.27.1': {}
'@babel/helper-validator-identifier@7.28.5': {}
@@ -3015,6 +3649,16 @@ snapshots:
dependencies:
'@babel/types': 7.28.5
+ '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.28.5)':
+ dependencies:
+ '@babel/core': 7.28.5
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.28.5)':
+ dependencies:
+ '@babel/core': 7.28.5
+ '@babel/helper-plugin-utils': 7.28.6
+
'@babel/runtime@7.28.4': {}
'@babel/template@7.27.2':
@@ -3035,32 +3679,168 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@babel/types@7.28.5':
- dependencies:
- '@babel/helper-string-parser': 7.27.1
- '@babel/helper-validator-identifier': 7.28.5
+ '@babel/types@7.28.5':
+ dependencies:
+ '@babel/helper-string-parser': 7.27.1
+ '@babel/helper-validator-identifier': 7.28.5
+
+ '@codemirror/autocomplete@6.20.1':
+ dependencies:
+ '@codemirror/language': 6.12.3
+ '@codemirror/state': 6.6.0
+ '@codemirror/view': 6.40.0
+ '@lezer/common': 1.5.1
+
+ '@codemirror/commands@6.10.3':
+ dependencies:
+ '@codemirror/language': 6.12.3
+ '@codemirror/state': 6.6.0
+ '@codemirror/view': 6.40.0
+ '@lezer/common': 1.5.1
+
+ '@codemirror/lang-json@6.0.2':
+ dependencies:
+ '@codemirror/language': 6.12.3
+ '@lezer/json': 1.0.3
+
+ '@codemirror/language@6.12.3':
+ dependencies:
+ '@codemirror/state': 6.6.0
+ '@codemirror/view': 6.40.0
+ '@lezer/common': 1.5.1
+ '@lezer/highlight': 1.2.3
+ '@lezer/lr': 1.4.8
+ style-mod: 4.1.3
+
+ '@codemirror/lint@6.9.5':
+ dependencies:
+ '@codemirror/state': 6.6.0
+ '@codemirror/view': 6.40.0
+ crelt: 1.0.6
+
+ '@codemirror/search@6.6.0':
+ dependencies:
+ '@codemirror/state': 6.6.0
+ '@codemirror/view': 6.40.0
+ crelt: 1.0.6
+
+ '@codemirror/state@6.6.0':
+ dependencies:
+ '@marijn/find-cluster-break': 1.0.2
+
+ '@codemirror/theme-one-dark@6.1.3':
+ dependencies:
+ '@codemirror/language': 6.12.3
+ '@codemirror/state': 6.6.0
+ '@codemirror/view': 6.40.0
+ '@lezer/highlight': 1.2.3
+
+ '@codemirror/view@6.40.0':
+ dependencies:
+ '@codemirror/state': 6.6.0
+ crelt: 1.0.6
+ style-mod: 4.1.3
+ w3c-keyname: 2.2.8
+
+ '@emnapi/core@1.8.1':
+ dependencies:
+ '@emnapi/wasi-threads': 1.1.0
+ tslib: 2.8.1
+ optional: true
+
+ '@emnapi/runtime@1.8.1':
+ dependencies:
+ tslib: 2.8.1
+ optional: true
+
+ '@emnapi/wasi-threads@1.1.0':
+ dependencies:
+ tslib: 2.8.1
+ optional: true
+
+ '@emotion/is-prop-valid@1.4.0':
+ dependencies:
+ '@emotion/memoize': 0.9.0
+
+ '@emotion/memoize@0.9.0': {}
+
+ '@esbuild/aix-ppc64@0.25.12':
+ optional: true
+
+ '@esbuild/android-arm64@0.25.12':
+ optional: true
+
+ '@esbuild/android-arm@0.25.12':
+ optional: true
+
+ '@esbuild/android-x64@0.25.12':
+ optional: true
+
+ '@esbuild/darwin-arm64@0.25.12':
+ optional: true
+
+ '@esbuild/darwin-x64@0.25.12':
+ optional: true
+
+ '@esbuild/freebsd-arm64@0.25.12':
+ optional: true
+
+ '@esbuild/freebsd-x64@0.25.12':
+ optional: true
+
+ '@esbuild/linux-arm64@0.25.12':
+ optional: true
+
+ '@esbuild/linux-arm@0.25.12':
+ optional: true
+
+ '@esbuild/linux-ia32@0.25.12':
+ optional: true
+
+ '@esbuild/linux-loong64@0.25.12':
+ optional: true
+
+ '@esbuild/linux-mips64el@0.25.12':
+ optional: true
+
+ '@esbuild/linux-ppc64@0.25.12':
+ optional: true
+
+ '@esbuild/linux-riscv64@0.25.12':
+ optional: true
+
+ '@esbuild/linux-s390x@0.25.12':
+ optional: true
- '@emnapi/core@1.8.1':
- dependencies:
- '@emnapi/wasi-threads': 1.1.0
- tslib: 2.8.1
+ '@esbuild/linux-x64@0.25.12':
optional: true
- '@emnapi/runtime@1.8.1':
- dependencies:
- tslib: 2.8.1
+ '@esbuild/netbsd-arm64@0.25.12':
optional: true
- '@emnapi/wasi-threads@1.1.0':
- dependencies:
- tslib: 2.8.1
+ '@esbuild/netbsd-x64@0.25.12':
optional: true
- '@emotion/is-prop-valid@1.4.0':
- dependencies:
- '@emotion/memoize': 0.9.0
+ '@esbuild/openbsd-arm64@0.25.12':
+ optional: true
- '@emotion/memoize@0.9.0': {}
+ '@esbuild/openbsd-x64@0.25.12':
+ optional: true
+
+ '@esbuild/openharmony-arm64@0.25.12':
+ optional: true
+
+ '@esbuild/sunos-x64@0.25.12':
+ optional: true
+
+ '@esbuild/win32-arm64@0.25.12':
+ optional: true
+
+ '@esbuild/win32-ia32@0.25.12':
+ optional: true
+
+ '@esbuild/win32-x64@0.25.12':
+ optional: true
'@eslint-community/eslint-utils@4.9.1(eslint@9.39.2(jiti@2.6.1))':
dependencies:
@@ -3260,6 +4040,22 @@ snapshots:
'@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.5
+ '@lezer/common@1.5.1': {}
+
+ '@lezer/highlight@1.2.3':
+ dependencies:
+ '@lezer/common': 1.5.1
+
+ '@lezer/json@1.0.3':
+ dependencies:
+ '@lezer/common': 1.5.1
+ '@lezer/highlight': 1.2.3
+ '@lezer/lr': 1.4.8
+
+ '@lezer/lr@1.4.8':
+ dependencies:
+ '@lezer/common': 1.5.1
+
'@mantine/charts@7.17.8(@mantine/core@7.17.5(@mantine/hooks@7.17.5(react@19.1.4))(@types/react@19.2.7)(react-dom@19.1.4(react@19.1.4))(react@19.1.4))(@mantine/hooks@7.17.5(react@19.1.4))(react-dom@19.1.4(react@19.1.4))(react@19.1.4)(recharts@2.15.4(react-dom@19.1.4(react@19.1.4))(react@19.1.4))':
dependencies:
'@mantine/core': 7.17.5(@mantine/hooks@7.17.5(react@19.1.4))(@types/react@19.2.7)(react-dom@19.1.4(react@19.1.4))(react@19.1.4)
@@ -3338,6 +4134,8 @@ snapshots:
dependencies:
react: 19.1.4
+ '@marijn/find-cluster-break@1.0.2': {}
+
'@monaco-editor/loader@1.7.0':
dependencies:
state-local: 1.0.7
@@ -3400,6 +4198,43 @@ snapshots:
'@nolyfill/is-core-module@1.0.39': {}
+ '@playwright/experimental-ct-core@1.57.0(@types/node@20.19.27)(jiti@2.6.1)(lightningcss@1.30.2)(sugarss@4.0.1(postcss@8.5.6))':
+ dependencies:
+ playwright: 1.57.0
+ playwright-core: 1.57.0
+ vite: 6.4.1(@types/node@20.19.27)(jiti@2.6.1)(lightningcss@1.30.2)(sugarss@4.0.1(postcss@8.5.6))
+ transitivePeerDependencies:
+ - '@types/node'
+ - jiti
+ - less
+ - lightningcss
+ - sass
+ - sass-embedded
+ - stylus
+ - sugarss
+ - terser
+ - tsx
+ - yaml
+
+ '@playwright/experimental-ct-react@1.57.0(@types/node@20.19.27)(jiti@2.6.1)(lightningcss@1.30.2)(sugarss@4.0.1(postcss@8.5.6))(vite@6.4.1(@types/node@20.19.27)(jiti@2.6.1)(lightningcss@1.30.2)(sugarss@4.0.1(postcss@8.5.6)))':
+ dependencies:
+ '@playwright/experimental-ct-core': 1.57.0(@types/node@20.19.27)(jiti@2.6.1)(lightningcss@1.30.2)(sugarss@4.0.1(postcss@8.5.6))
+ '@vitejs/plugin-react': 4.7.0(vite@6.4.1(@types/node@20.19.27)(jiti@2.6.1)(lightningcss@1.30.2)(sugarss@4.0.1(postcss@8.5.6)))
+ transitivePeerDependencies:
+ - '@types/node'
+ - jiti
+ - less
+ - lightningcss
+ - sass
+ - sass-embedded
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+ - tsx
+ - vite
+ - yaml
+
'@playwright/test@1.57.0':
dependencies:
playwright: 1.57.0
@@ -3427,6 +4262,83 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@rolldown/pluginutils@1.0.0-beta.27': {}
+
+ '@rollup/rollup-android-arm-eabi@4.60.1':
+ optional: true
+
+ '@rollup/rollup-android-arm64@4.60.1':
+ optional: true
+
+ '@rollup/rollup-darwin-arm64@4.60.1':
+ optional: true
+
+ '@rollup/rollup-darwin-x64@4.60.1':
+ optional: true
+
+ '@rollup/rollup-freebsd-arm64@4.60.1':
+ optional: true
+
+ '@rollup/rollup-freebsd-x64@4.60.1':
+ optional: true
+
+ '@rollup/rollup-linux-arm-gnueabihf@4.60.1':
+ optional: true
+
+ '@rollup/rollup-linux-arm-musleabihf@4.60.1':
+ optional: true
+
+ '@rollup/rollup-linux-arm64-gnu@4.60.1':
+ optional: true
+
+ '@rollup/rollup-linux-arm64-musl@4.60.1':
+ optional: true
+
+ '@rollup/rollup-linux-loong64-gnu@4.60.1':
+ optional: true
+
+ '@rollup/rollup-linux-loong64-musl@4.60.1':
+ optional: true
+
+ '@rollup/rollup-linux-ppc64-gnu@4.60.1':
+ optional: true
+
+ '@rollup/rollup-linux-ppc64-musl@4.60.1':
+ optional: true
+
+ '@rollup/rollup-linux-riscv64-gnu@4.60.1':
+ optional: true
+
+ '@rollup/rollup-linux-riscv64-musl@4.60.1':
+ optional: true
+
+ '@rollup/rollup-linux-s390x-gnu@4.60.1':
+ optional: true
+
+ '@rollup/rollup-linux-x64-gnu@4.60.1':
+ optional: true
+
+ '@rollup/rollup-linux-x64-musl@4.60.1':
+ optional: true
+
+ '@rollup/rollup-openbsd-x64@4.60.1':
+ optional: true
+
+ '@rollup/rollup-openharmony-arm64@4.60.1':
+ optional: true
+
+ '@rollup/rollup-win32-arm64-msvc@4.60.1':
+ optional: true
+
+ '@rollup/rollup-win32-ia32-msvc@4.60.1':
+ optional: true
+
+ '@rollup/rollup-win32-x64-gnu@4.60.1':
+ optional: true
+
+ '@rollup/rollup-win32-x64-msvc@4.60.1':
+ optional: true
+
'@rtsao/scc@1.1.0': {}
'@rungalileo/icons@0.0.1(@mantine/core@7.17.5(@mantine/hooks@7.17.5(react@19.1.4))(@types/react@19.2.7)(react-dom@19.1.4(react@19.1.4))(react@19.1.4))(react-dom@19.1.4(react@19.1.4))(react@19.1.4)':
@@ -3553,6 +4465,27 @@ snapshots:
tslib: 2.8.1
optional: true
+ '@types/babel__core@7.20.5':
+ dependencies:
+ '@babel/parser': 7.28.5
+ '@babel/types': 7.28.5
+ '@types/babel__generator': 7.27.0
+ '@types/babel__template': 7.4.4
+ '@types/babel__traverse': 7.28.0
+
+ '@types/babel__generator@7.27.0':
+ dependencies:
+ '@babel/types': 7.28.5
+
+ '@types/babel__template@7.4.4':
+ dependencies:
+ '@babel/parser': 7.28.5
+ '@babel/types': 7.28.5
+
+ '@types/babel__traverse@7.28.0':
+ dependencies:
+ '@babel/types': 7.28.5
+
'@types/d3-array@3.2.2': {}
'@types/d3-color@3.1.3': {}
@@ -3689,6 +4622,362 @@ snapshots:
'@typescript-eslint/types': 8.51.0
eslint-visitor-keys: 4.2.1
+ '@uiw/codemirror-extensions-basic-setup@4.25.9(@codemirror/autocomplete@6.20.1)(@codemirror/commands@6.10.3)(@codemirror/language@6.12.3)(@codemirror/lint@6.9.5)(@codemirror/search@6.6.0)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)':
+ dependencies:
+ '@codemirror/autocomplete': 6.20.1
+ '@codemirror/commands': 6.10.3
+ '@codemirror/language': 6.12.3
+ '@codemirror/lint': 6.9.5
+ '@codemirror/search': 6.6.0
+ '@codemirror/state': 6.6.0
+ '@codemirror/view': 6.40.0
+
+ '@uiw/codemirror-theme-abcdef@4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)':
+ dependencies:
+ '@uiw/codemirror-themes': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ transitivePeerDependencies:
+ - '@codemirror/language'
+ - '@codemirror/state'
+ - '@codemirror/view'
+
+ '@uiw/codemirror-theme-abyss@4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)':
+ dependencies:
+ '@uiw/codemirror-themes': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ transitivePeerDependencies:
+ - '@codemirror/language'
+ - '@codemirror/state'
+ - '@codemirror/view'
+
+ '@uiw/codemirror-theme-androidstudio@4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)':
+ dependencies:
+ '@uiw/codemirror-themes': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ transitivePeerDependencies:
+ - '@codemirror/language'
+ - '@codemirror/state'
+ - '@codemirror/view'
+
+ '@uiw/codemirror-theme-andromeda@4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)':
+ dependencies:
+ '@uiw/codemirror-themes': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ transitivePeerDependencies:
+ - '@codemirror/language'
+ - '@codemirror/state'
+ - '@codemirror/view'
+
+ '@uiw/codemirror-theme-atomone@4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)':
+ dependencies:
+ '@uiw/codemirror-themes': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ transitivePeerDependencies:
+ - '@codemirror/language'
+ - '@codemirror/state'
+ - '@codemirror/view'
+
+ '@uiw/codemirror-theme-aura@4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)':
+ dependencies:
+ '@uiw/codemirror-themes': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ transitivePeerDependencies:
+ - '@codemirror/language'
+ - '@codemirror/state'
+ - '@codemirror/view'
+
+ '@uiw/codemirror-theme-basic@4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)':
+ dependencies:
+ '@uiw/codemirror-themes': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ transitivePeerDependencies:
+ - '@codemirror/language'
+ - '@codemirror/state'
+ - '@codemirror/view'
+
+ '@uiw/codemirror-theme-bbedit@4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)':
+ dependencies:
+ '@uiw/codemirror-themes': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ transitivePeerDependencies:
+ - '@codemirror/language'
+ - '@codemirror/state'
+ - '@codemirror/view'
+
+ '@uiw/codemirror-theme-bespin@4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)':
+ dependencies:
+ '@uiw/codemirror-themes': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ transitivePeerDependencies:
+ - '@codemirror/language'
+ - '@codemirror/state'
+ - '@codemirror/view'
+
+ '@uiw/codemirror-theme-console@4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)':
+ dependencies:
+ '@uiw/codemirror-themes': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ transitivePeerDependencies:
+ - '@codemirror/language'
+ - '@codemirror/state'
+ - '@codemirror/view'
+
+ '@uiw/codemirror-theme-copilot@4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)':
+ dependencies:
+ '@uiw/codemirror-themes': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ transitivePeerDependencies:
+ - '@codemirror/language'
+ - '@codemirror/state'
+ - '@codemirror/view'
+
+ '@uiw/codemirror-theme-darcula@4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)':
+ dependencies:
+ '@uiw/codemirror-themes': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ transitivePeerDependencies:
+ - '@codemirror/language'
+ - '@codemirror/state'
+ - '@codemirror/view'
+
+ '@uiw/codemirror-theme-dracula@4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)':
+ dependencies:
+ '@uiw/codemirror-themes': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ transitivePeerDependencies:
+ - '@codemirror/language'
+ - '@codemirror/state'
+ - '@codemirror/view'
+
+ '@uiw/codemirror-theme-duotone@4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)':
+ dependencies:
+ '@uiw/codemirror-themes': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ transitivePeerDependencies:
+ - '@codemirror/language'
+ - '@codemirror/state'
+ - '@codemirror/view'
+
+ '@uiw/codemirror-theme-eclipse@4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)':
+ dependencies:
+ '@uiw/codemirror-themes': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ transitivePeerDependencies:
+ - '@codemirror/language'
+ - '@codemirror/state'
+ - '@codemirror/view'
+
+ '@uiw/codemirror-theme-github@4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)':
+ dependencies:
+ '@uiw/codemirror-themes': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ transitivePeerDependencies:
+ - '@codemirror/language'
+ - '@codemirror/state'
+ - '@codemirror/view'
+
+ '@uiw/codemirror-theme-gruvbox-dark@4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)':
+ dependencies:
+ '@uiw/codemirror-themes': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ transitivePeerDependencies:
+ - '@codemirror/language'
+ - '@codemirror/state'
+ - '@codemirror/view'
+
+ '@uiw/codemirror-theme-kimbie@4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)':
+ dependencies:
+ '@uiw/codemirror-themes': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ transitivePeerDependencies:
+ - '@codemirror/language'
+ - '@codemirror/state'
+ - '@codemirror/view'
+
+ '@uiw/codemirror-theme-material@4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)':
+ dependencies:
+ '@uiw/codemirror-themes': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ transitivePeerDependencies:
+ - '@codemirror/language'
+ - '@codemirror/state'
+ - '@codemirror/view'
+
+ '@uiw/codemirror-theme-monokai-dimmed@4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)':
+ dependencies:
+ '@uiw/codemirror-themes': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ transitivePeerDependencies:
+ - '@codemirror/language'
+ - '@codemirror/state'
+ - '@codemirror/view'
+
+ '@uiw/codemirror-theme-monokai@4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)':
+ dependencies:
+ '@uiw/codemirror-themes': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ transitivePeerDependencies:
+ - '@codemirror/language'
+ - '@codemirror/state'
+ - '@codemirror/view'
+
+ '@uiw/codemirror-theme-noctis-lilac@4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)':
+ dependencies:
+ '@uiw/codemirror-themes': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ transitivePeerDependencies:
+ - '@codemirror/language'
+ - '@codemirror/state'
+ - '@codemirror/view'
+
+ '@uiw/codemirror-theme-nord@4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)':
+ dependencies:
+ '@uiw/codemirror-themes': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ transitivePeerDependencies:
+ - '@codemirror/language'
+ - '@codemirror/state'
+ - '@codemirror/view'
+
+ '@uiw/codemirror-theme-okaidia@4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)':
+ dependencies:
+ '@uiw/codemirror-themes': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ transitivePeerDependencies:
+ - '@codemirror/language'
+ - '@codemirror/state'
+ - '@codemirror/view'
+
+ '@uiw/codemirror-theme-quietlight@4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)':
+ dependencies:
+ '@uiw/codemirror-themes': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ transitivePeerDependencies:
+ - '@codemirror/language'
+ - '@codemirror/state'
+ - '@codemirror/view'
+
+ '@uiw/codemirror-theme-red@4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)':
+ dependencies:
+ '@uiw/codemirror-themes': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ transitivePeerDependencies:
+ - '@codemirror/language'
+ - '@codemirror/state'
+ - '@codemirror/view'
+
+ '@uiw/codemirror-theme-solarized@4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)':
+ dependencies:
+ '@uiw/codemirror-themes': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ transitivePeerDependencies:
+ - '@codemirror/language'
+ - '@codemirror/state'
+ - '@codemirror/view'
+
+ '@uiw/codemirror-theme-sublime@4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)':
+ dependencies:
+ '@uiw/codemirror-themes': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ transitivePeerDependencies:
+ - '@codemirror/language'
+ - '@codemirror/state'
+ - '@codemirror/view'
+
+ '@uiw/codemirror-theme-tokyo-night-day@4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)':
+ dependencies:
+ '@uiw/codemirror-themes': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ transitivePeerDependencies:
+ - '@codemirror/language'
+ - '@codemirror/state'
+ - '@codemirror/view'
+
+ '@uiw/codemirror-theme-tokyo-night-storm@4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)':
+ dependencies:
+ '@uiw/codemirror-themes': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ transitivePeerDependencies:
+ - '@codemirror/language'
+ - '@codemirror/state'
+ - '@codemirror/view'
+
+ '@uiw/codemirror-theme-tokyo-night@4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)':
+ dependencies:
+ '@uiw/codemirror-themes': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ transitivePeerDependencies:
+ - '@codemirror/language'
+ - '@codemirror/state'
+ - '@codemirror/view'
+
+ '@uiw/codemirror-theme-tomorrow-night-blue@4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)':
+ dependencies:
+ '@uiw/codemirror-themes': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ transitivePeerDependencies:
+ - '@codemirror/language'
+ - '@codemirror/state'
+ - '@codemirror/view'
+
+ '@uiw/codemirror-theme-vscode@4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)':
+ dependencies:
+ '@uiw/codemirror-themes': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ transitivePeerDependencies:
+ - '@codemirror/language'
+ - '@codemirror/state'
+ - '@codemirror/view'
+
+ '@uiw/codemirror-theme-white@4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)':
+ dependencies:
+ '@uiw/codemirror-themes': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ transitivePeerDependencies:
+ - '@codemirror/language'
+ - '@codemirror/state'
+ - '@codemirror/view'
+
+ '@uiw/codemirror-theme-xcode@4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)':
+ dependencies:
+ '@uiw/codemirror-themes': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ transitivePeerDependencies:
+ - '@codemirror/language'
+ - '@codemirror/state'
+ - '@codemirror/view'
+
+ '@uiw/codemirror-themes-all@4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)':
+ dependencies:
+ '@uiw/codemirror-theme-abcdef': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ '@uiw/codemirror-theme-abyss': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ '@uiw/codemirror-theme-androidstudio': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ '@uiw/codemirror-theme-andromeda': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ '@uiw/codemirror-theme-atomone': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ '@uiw/codemirror-theme-aura': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ '@uiw/codemirror-theme-basic': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ '@uiw/codemirror-theme-bbedit': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ '@uiw/codemirror-theme-bespin': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ '@uiw/codemirror-theme-console': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ '@uiw/codemirror-theme-copilot': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ '@uiw/codemirror-theme-darcula': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ '@uiw/codemirror-theme-dracula': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ '@uiw/codemirror-theme-duotone': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ '@uiw/codemirror-theme-eclipse': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ '@uiw/codemirror-theme-github': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ '@uiw/codemirror-theme-gruvbox-dark': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ '@uiw/codemirror-theme-kimbie': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ '@uiw/codemirror-theme-material': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ '@uiw/codemirror-theme-monokai': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ '@uiw/codemirror-theme-monokai-dimmed': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ '@uiw/codemirror-theme-noctis-lilac': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ '@uiw/codemirror-theme-nord': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ '@uiw/codemirror-theme-okaidia': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ '@uiw/codemirror-theme-quietlight': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ '@uiw/codemirror-theme-red': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ '@uiw/codemirror-theme-solarized': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ '@uiw/codemirror-theme-sublime': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ '@uiw/codemirror-theme-tokyo-night': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ '@uiw/codemirror-theme-tokyo-night-day': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ '@uiw/codemirror-theme-tokyo-night-storm': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ '@uiw/codemirror-theme-tomorrow-night-blue': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ '@uiw/codemirror-theme-vscode': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ '@uiw/codemirror-theme-white': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ '@uiw/codemirror-theme-xcode': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ '@uiw/codemirror-themes': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ transitivePeerDependencies:
+ - '@codemirror/language'
+ - '@codemirror/state'
+ - '@codemirror/view'
+
+ '@uiw/codemirror-themes@4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)':
+ dependencies:
+ '@codemirror/language': 6.12.3
+ '@codemirror/state': 6.6.0
+ '@codemirror/view': 6.40.0
+
+ '@uiw/react-codemirror@4.25.9(@babel/runtime@7.28.4)(@codemirror/autocomplete@6.20.1)(@codemirror/language@6.12.3)(@codemirror/lint@6.9.5)(@codemirror/search@6.6.0)(@codemirror/state@6.6.0)(@codemirror/theme-one-dark@6.1.3)(@codemirror/view@6.40.0)(codemirror@6.0.2)(react-dom@19.1.4(react@19.1.4))(react@19.1.4)':
+ dependencies:
+ '@babel/runtime': 7.28.4
+ '@codemirror/commands': 6.10.3
+ '@codemirror/state': 6.6.0
+ '@codemirror/theme-one-dark': 6.1.3
+ '@codemirror/view': 6.40.0
+ '@uiw/codemirror-extensions-basic-setup': 4.25.9(@codemirror/autocomplete@6.20.1)(@codemirror/commands@6.10.3)(@codemirror/language@6.12.3)(@codemirror/lint@6.9.5)(@codemirror/search@6.6.0)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
+ codemirror: 6.0.2
+ react: 19.1.4
+ react-dom: 19.1.4(react@19.1.4)
+ transitivePeerDependencies:
+ - '@codemirror/autocomplete'
+ - '@codemirror/language'
+ - '@codemirror/lint'
+ - '@codemirror/search'
+
'@unrs/resolver-binding-android-arm-eabi@1.11.1':
optional: true
@@ -3748,6 +5037,18 @@ snapshots:
'@unrs/resolver-binding-win32-x64-msvc@1.11.1':
optional: true
+ '@vitejs/plugin-react@4.7.0(vite@6.4.1(@types/node@20.19.27)(jiti@2.6.1)(lightningcss@1.30.2)(sugarss@4.0.1(postcss@8.5.6)))':
+ dependencies:
+ '@babel/core': 7.28.5
+ '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.5)
+ '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.28.5)
+ '@rolldown/pluginutils': 1.0.0-beta.27
+ '@types/babel__core': 7.20.5
+ react-refresh: 0.17.0
+ vite: 6.4.1(@types/node@20.19.27)(jiti@2.6.1)(lightningcss@1.30.2)(sugarss@4.0.1(postcss@8.5.6))
+ transitivePeerDependencies:
+ - supports-color
+
acorn-jsx@5.3.2(acorn@8.15.0):
dependencies:
acorn: 8.15.0
@@ -3945,6 +5246,16 @@ snapshots:
clsx@2.1.1: {}
+ codemirror@6.0.2:
+ dependencies:
+ '@codemirror/autocomplete': 6.20.1
+ '@codemirror/commands': 6.10.3
+ '@codemirror/language': 6.12.3
+ '@codemirror/lint': 6.9.5
+ '@codemirror/search': 6.6.0
+ '@codemirror/state': 6.6.0
+ '@codemirror/view': 6.40.0
+
color-convert@1.9.3:
dependencies:
color-name: 1.1.3
@@ -3967,6 +5278,8 @@ snapshots:
convert-source-map@2.0.0: {}
+ crelt@1.0.6: {}
+
cross-spawn@7.0.6:
dependencies:
path-key: 3.1.1
@@ -4215,6 +5528,35 @@ snapshots:
is-date-object: 1.1.0
is-symbol: 1.1.1
+ esbuild@0.25.12:
+ optionalDependencies:
+ '@esbuild/aix-ppc64': 0.25.12
+ '@esbuild/android-arm': 0.25.12
+ '@esbuild/android-arm64': 0.25.12
+ '@esbuild/android-x64': 0.25.12
+ '@esbuild/darwin-arm64': 0.25.12
+ '@esbuild/darwin-x64': 0.25.12
+ '@esbuild/freebsd-arm64': 0.25.12
+ '@esbuild/freebsd-x64': 0.25.12
+ '@esbuild/linux-arm': 0.25.12
+ '@esbuild/linux-arm64': 0.25.12
+ '@esbuild/linux-ia32': 0.25.12
+ '@esbuild/linux-loong64': 0.25.12
+ '@esbuild/linux-mips64el': 0.25.12
+ '@esbuild/linux-ppc64': 0.25.12
+ '@esbuild/linux-riscv64': 0.25.12
+ '@esbuild/linux-s390x': 0.25.12
+ '@esbuild/linux-x64': 0.25.12
+ '@esbuild/netbsd-arm64': 0.25.12
+ '@esbuild/netbsd-x64': 0.25.12
+ '@esbuild/openbsd-arm64': 0.25.12
+ '@esbuild/openbsd-x64': 0.25.12
+ '@esbuild/openharmony-arm64': 0.25.12
+ '@esbuild/sunos-x64': 0.25.12
+ '@esbuild/win32-arm64': 0.25.12
+ '@esbuild/win32-ia32': 0.25.12
+ '@esbuild/win32-x64': 0.25.12
+
escalade@3.2.0: {}
escape-string-regexp@1.0.5: {}
@@ -4521,6 +5863,9 @@ snapshots:
fsevents@2.3.2:
optional: true
+ fsevents@2.3.3:
+ optional: true
+
function-bind@1.1.2: {}
function.prototype.name@1.1.8:
@@ -5271,6 +6616,8 @@ snapshots:
react: 19.1.4
react-dom: 19.1.4(react@19.1.4)
+ react-refresh@0.17.0: {}
+
react-remove-scroll-bar@2.3.8(@types/react@19.2.7)(react@19.1.4):
dependencies:
react: 19.1.4
@@ -5399,6 +6746,37 @@ snapshots:
reusify@1.1.0: {}
+ rollup@4.60.1:
+ dependencies:
+ '@types/estree': 1.0.8
+ optionalDependencies:
+ '@rollup/rollup-android-arm-eabi': 4.60.1
+ '@rollup/rollup-android-arm64': 4.60.1
+ '@rollup/rollup-darwin-arm64': 4.60.1
+ '@rollup/rollup-darwin-x64': 4.60.1
+ '@rollup/rollup-freebsd-arm64': 4.60.1
+ '@rollup/rollup-freebsd-x64': 4.60.1
+ '@rollup/rollup-linux-arm-gnueabihf': 4.60.1
+ '@rollup/rollup-linux-arm-musleabihf': 4.60.1
+ '@rollup/rollup-linux-arm64-gnu': 4.60.1
+ '@rollup/rollup-linux-arm64-musl': 4.60.1
+ '@rollup/rollup-linux-loong64-gnu': 4.60.1
+ '@rollup/rollup-linux-loong64-musl': 4.60.1
+ '@rollup/rollup-linux-ppc64-gnu': 4.60.1
+ '@rollup/rollup-linux-ppc64-musl': 4.60.1
+ '@rollup/rollup-linux-riscv64-gnu': 4.60.1
+ '@rollup/rollup-linux-riscv64-musl': 4.60.1
+ '@rollup/rollup-linux-s390x-gnu': 4.60.1
+ '@rollup/rollup-linux-x64-gnu': 4.60.1
+ '@rollup/rollup-linux-x64-musl': 4.60.1
+ '@rollup/rollup-openbsd-x64': 4.60.1
+ '@rollup/rollup-openharmony-arm64': 4.60.1
+ '@rollup/rollup-win32-arm64-msvc': 4.60.1
+ '@rollup/rollup-win32-ia32-msvc': 4.60.1
+ '@rollup/rollup-win32-x64-gnu': 4.60.1
+ '@rollup/rollup-win32-x64-msvc': 4.60.1
+ fsevents: 2.3.3
+
run-parallel@1.2.0:
dependencies:
queue-microtask: 1.2.3
@@ -5601,6 +6979,8 @@ snapshots:
strip-json-comments@3.1.1: {}
+ style-mod@4.1.3: {}
+
styled-jsx@5.1.6(@babel/core@7.28.5)(react@19.1.4):
dependencies:
client-only: 0.0.1
@@ -5811,6 +7191,23 @@ snapshots:
d3-time: 3.1.0
d3-timer: 3.0.1
+ vite@6.4.1(@types/node@20.19.27)(jiti@2.6.1)(lightningcss@1.30.2)(sugarss@4.0.1(postcss@8.5.6)):
+ dependencies:
+ esbuild: 0.25.12
+ fdir: 6.5.0(picomatch@4.0.3)
+ picomatch: 4.0.3
+ postcss: 8.5.6
+ rollup: 4.60.1
+ tinyglobby: 0.2.15
+ optionalDependencies:
+ '@types/node': 20.19.27
+ fsevents: 2.3.3
+ jiti: 2.6.1
+ lightningcss: 1.30.2
+ sugarss: 4.0.1(postcss@8.5.6)
+
+ w3c-keyname@2.2.8: {}
+
which-boxed-primitive@1.1.1:
dependencies:
is-bigint: 1.1.0
diff --git a/ui/src/components/json-editor-codemirror/codemirror-theme-presets.ts b/ui/src/components/json-editor-codemirror/codemirror-theme-presets.ts
new file mode 100644
index 00000000..1f6c7550
--- /dev/null
+++ b/ui/src/components/json-editor-codemirror/codemirror-theme-presets.ts
@@ -0,0 +1,157 @@
+import {
+ defaultHighlightStyle,
+ syntaxHighlighting,
+} from '@codemirror/language';
+import { type Extension } from '@codemirror/state';
+import { EditorView } from '@codemirror/view';
+import {
+ atomone,
+ darcula,
+ dracula,
+ eclipse,
+ githubDark,
+ githubLight,
+ gruvboxDark,
+ gruvboxLight,
+ monokai,
+ nord,
+ quietlight,
+ solarizedDark,
+ solarizedLight,
+ tokyoNight,
+ tokyoNightDay,
+ tokyoNightStorm,
+ vscodeDark,
+ vscodeLight,
+ whiteLight,
+} from '@uiw/codemirror-themes-all';
+
+export const CODE_MIRROR_THEME_STORAGE_KEY =
+ 'agent-control.jsonEditor.cmTheme.v1';
+
+export const DEFAULT_DARK_THEME_ID = 'vscode-dark';
+export const DEFAULT_LIGHT_THEME_ID = 'mantine-light';
+
+const LIGHT_CHROME_THEME = EditorView.theme({
+ '&': {
+ backgroundColor: 'var(--mantine-color-body)',
+ color: 'var(--mantine-color-text)',
+ },
+ '.cm-gutters': {
+ backgroundColor: 'var(--mantine-color-body)',
+ borderRightColor: 'var(--mantine-color-body)',
+ color: 'var(--mantine-color-dimmed)',
+ },
+ '.cm-content': {
+ caretColor: 'var(--mantine-color-text)',
+ },
+ '.cm-cursor, .cm-dropCursor': {
+ borderLeftColor: 'var(--mantine-color-text)',
+ },
+});
+
+/** Light preset matching Mantine surface colors + default token palette. */
+export const mantineLightCodeMirrorTheme: Extension[] = [
+ LIGHT_CHROME_THEME,
+ syntaxHighlighting(defaultHighlightStyle),
+];
+
+export type CodeMirrorThemePreset = {
+ label: string;
+ extension: Extension | Extension[];
+};
+
+export const CODE_MIRROR_DARK_THEME_PRESETS: Record<
+ string,
+ CodeMirrorThemePreset
+> = {
+ [DEFAULT_DARK_THEME_ID]: {
+ label: 'VS Code Dark',
+ extension: vscodeDark,
+ },
+ 'github-dark': { label: 'GitHub Dark', extension: githubDark },
+ 'tokyo-night': { label: 'Tokyo Night', extension: tokyoNight },
+ 'tokyo-night-storm': {
+ label: 'Tokyo Night Storm',
+ extension: tokyoNightStorm,
+ },
+ nord: { label: 'Nord', extension: nord },
+ dracula: { label: 'Dracula', extension: dracula },
+ monokai: { label: 'Monokai', extension: monokai },
+ 'gruvbox-dark': { label: 'Gruvbox Dark', extension: gruvboxDark },
+ darcula: { label: 'Darcula', extension: darcula },
+ 'atom-one': { label: 'Atom One', extension: atomone },
+ 'solarized-dark': { label: 'Solarized Dark', extension: solarizedDark },
+};
+
+export const CODE_MIRROR_LIGHT_THEME_PRESETS: Record<
+ string,
+ CodeMirrorThemePreset
+> = {
+ [DEFAULT_LIGHT_THEME_ID]: {
+ label: 'Mantine (match app)',
+ extension: mantineLightCodeMirrorTheme,
+ },
+ 'vscode-light': { label: 'VS Code Light', extension: vscodeLight },
+ 'github-light': { label: 'GitHub Light', extension: githubLight },
+ 'tokyo-night-day': { label: 'Tokyo Night Day', extension: tokyoNightDay },
+ 'quiet-light': { label: 'Quiet Light', extension: quietlight },
+ eclipse: { label: 'Eclipse', extension: eclipse },
+ white: { label: 'White', extension: whiteLight },
+ 'gruvbox-light': { label: 'Gruvbox Light', extension: gruvboxLight },
+ 'solarized-light': { label: 'Solarized Light', extension: solarizedLight },
+};
+
+export type StoredCodeMirrorThemePrefs = {
+ dark: string;
+ light: string;
+};
+
+export function readStoredCodeMirrorThemePrefs(): StoredCodeMirrorThemePrefs {
+ const fallback: StoredCodeMirrorThemePrefs = {
+ dark: DEFAULT_DARK_THEME_ID,
+ light: DEFAULT_LIGHT_THEME_ID,
+ };
+ if (typeof window === 'undefined') {
+ return fallback;
+ }
+ try {
+ const raw = window.localStorage.getItem(CODE_MIRROR_THEME_STORAGE_KEY);
+ if (!raw) return fallback;
+ const parsed = JSON.parse(raw) as Partial;
+ return {
+ dark:
+ parsed.dark &&
+ Object.prototype.hasOwnProperty.call(
+ CODE_MIRROR_DARK_THEME_PRESETS,
+ parsed.dark
+ )
+ ? parsed.dark
+ : DEFAULT_DARK_THEME_ID,
+ light:
+ parsed.light &&
+ Object.prototype.hasOwnProperty.call(
+ CODE_MIRROR_LIGHT_THEME_PRESETS,
+ parsed.light
+ )
+ ? parsed.light
+ : DEFAULT_LIGHT_THEME_ID,
+ };
+ } catch {
+ return fallback;
+ }
+}
+
+export function writeStoredCodeMirrorThemePrefs(
+ prefs: StoredCodeMirrorThemePrefs
+): void {
+ if (typeof window === 'undefined') return;
+ try {
+ window.localStorage.setItem(
+ CODE_MIRROR_THEME_STORAGE_KEY,
+ JSON.stringify(prefs)
+ );
+ } catch {
+ /* ignore quota / private mode */
+ }
+}
diff --git a/ui/src/components/json-editor-codemirror/harness-schema.ts b/ui/src/components/json-editor-codemirror/harness-schema.ts
new file mode 100644
index 00000000..dab4b662
--- /dev/null
+++ b/ui/src/components/json-editor-codemirror/harness-schema.ts
@@ -0,0 +1,129 @@
+import type { JsonSchema } from '@/core/page-components/agent-detail/modals/edit-control/types';
+
+/**
+ * Control JSON Schema used by the Playwright harness for JsonEditorCodeMirror.
+ * Aligned with mock control schema in ui/tests/fixtures.ts.
+ */
+export const HARNESS_CONTROL_SCHEMA: JsonSchema = {
+ $defs: {
+ ControlSelector: {
+ type: 'object',
+ properties: {
+ path: {
+ anyOf: [{ type: 'string' }, { type: 'null' }],
+ default: '*',
+ examples: ['output', 'context.user_id', '*'],
+ },
+ },
+ },
+ EvaluatorSpec: {
+ type: 'object',
+ required: ['name', 'config'],
+ properties: {
+ name: {
+ type: 'string',
+ examples: ['regex', 'list'],
+ },
+ config: {
+ type: 'object',
+ additionalProperties: true,
+ },
+ },
+ },
+ ConditionNode: {
+ type: 'object',
+ properties: {
+ selector: {
+ anyOf: [{ $ref: '#/$defs/ControlSelector' }, { type: 'null' }],
+ },
+ evaluator: {
+ anyOf: [{ $ref: '#/$defs/EvaluatorSpec' }, { type: 'null' }],
+ },
+ and: {
+ anyOf: [
+ { type: 'array', items: { $ref: '#/$defs/ConditionNode' } },
+ { type: 'null' },
+ ],
+ },
+ or: {
+ anyOf: [
+ { type: 'array', items: { $ref: '#/$defs/ConditionNode' } },
+ { type: 'null' },
+ ],
+ },
+ not: {
+ anyOf: [{ $ref: '#/$defs/ConditionNode' }, { type: 'null' }],
+ },
+ },
+ },
+ ControlScope: {
+ type: 'object',
+ properties: {
+ step_types: {
+ anyOf: [
+ { type: 'array', items: { type: 'string' } },
+ { type: 'null' },
+ ],
+ },
+ step_names: {
+ anyOf: [
+ { type: 'array', items: { type: 'string' } },
+ { type: 'null' },
+ ],
+ },
+ step_name_regex: { anyOf: [{ type: 'string' }, { type: 'null' }] },
+ stages: {
+ anyOf: [
+ {
+ type: 'array',
+ items: { type: 'string', enum: ['pre', 'post'] },
+ },
+ { type: 'null' },
+ ],
+ },
+ },
+ },
+ SteeringContext: {
+ type: 'object',
+ required: ['message'],
+ properties: {
+ message: { type: 'string' },
+ },
+ },
+ ControlAction: {
+ type: 'object',
+ required: ['decision'],
+ properties: {
+ decision: {
+ type: 'string',
+ enum: ['allow', 'deny', 'steer', 'warn', 'log'],
+ },
+ steering_context: {
+ anyOf: [{ $ref: '#/$defs/SteeringContext' }, { type: 'null' }],
+ },
+ },
+ },
+ },
+ type: 'object',
+ required: ['execution', 'condition', 'action'],
+ properties: {
+ description: {
+ anyOf: [{ type: 'string' }, { type: 'null' }],
+ },
+ enabled: { type: 'boolean' },
+ execution: { type: 'string', enum: ['server', 'sdk'] },
+ scope: {
+ $ref: '#/$defs/ControlScope',
+ },
+ condition: {
+ $ref: '#/$defs/ConditionNode',
+ },
+ action: {
+ $ref: '#/$defs/ControlAction',
+ },
+ tags: {
+ type: 'array',
+ items: { type: 'string' },
+ },
+ },
+};
diff --git a/ui/src/components/json-editor-codemirror/index.ts b/ui/src/components/json-editor-codemirror/index.ts
new file mode 100644
index 00000000..3c5037a8
--- /dev/null
+++ b/ui/src/components/json-editor-codemirror/index.ts
@@ -0,0 +1 @@
+export { JsonEditorCodeMirror } from './json-editor-codemirror';
diff --git a/ui/src/components/json-editor-codemirror/json-editor-codemirror-language.ts b/ui/src/components/json-editor-codemirror/json-editor-codemirror-language.ts
new file mode 100644
index 00000000..cdb9faf6
--- /dev/null
+++ b/ui/src/components/json-editor-codemirror/json-editor-codemirror-language.ts
@@ -0,0 +1,17 @@
+export {
+ applyTextEdit,
+ buildCodeMirrorInlineServerValidationErrorsExtension,
+ buildCodeMirrorJsonExtensions,
+ buildCodeMirrorRefactorLightbulbExtension,
+ buildCodeMirrorStandaloneDebugExtensions,
+ caretAfterPrettyJsonReplace,
+ computeAutoEdit,
+ extractEvaluatorNames,
+ fixJsonCommas,
+ getCodeMirrorCompletionItems,
+ normalizeOnBlur,
+ setInlineServerValidationErrorsEffect,
+ shouldTriggerEvaluatorNameCompletion,
+ triggerRefactorActionsDropdown,
+ tryFormat,
+} from './language';
diff --git a/ui/src/components/json-editor-codemirror/json-editor-codemirror.playwright-story.tsx b/ui/src/components/json-editor-codemirror/json-editor-codemirror.playwright-story.tsx
new file mode 100644
index 00000000..48ae896e
--- /dev/null
+++ b/ui/src/components/json-editor-codemirror/json-editor-codemirror.playwright-story.tsx
@@ -0,0 +1,106 @@
+import { Box, Button, Group } from '@mantine/core';
+import { useCallback, useEffect, useState } from 'react';
+
+import type {
+ JsonEditorEvaluatorOption,
+ JsonEditorMode,
+} from '@/core/page-components/agent-detail/modals/edit-control/types';
+
+import { HARNESS_CONTROL_SCHEMA } from './harness-schema';
+import { JsonEditorCodeMirror } from './json-editor-codemirror';
+
+/** `data-testid` on the editor root for `tests/json-editor-bridge.ts` helpers. */
+export const CT_JSON_EDITOR_TEST_ID = 'codemirror-json-editor-ct';
+
+const DEFAULT_CONTROL_JSON =
+ '{"execution":"server","condition":{},"action":{"decision":"allow"}}';
+
+const CT_EVALUATORS: JsonEditorEvaluatorOption[] = [
+ {
+ id: 'regex',
+ label: 'Regex',
+ source: 'global',
+ configSchema: {
+ type: 'object',
+ properties: {
+ pattern: { type: 'string', default: '.*' },
+ },
+ required: ['pattern'],
+ },
+ },
+ {
+ id: 'json',
+ label: 'JSON',
+ source: 'global',
+ configSchema: {
+ type: 'object',
+ properties: {
+ json_schema: { type: 'object', additionalProperties: true },
+ },
+ },
+ },
+];
+
+/** Host for Playwright component tests only (see `tests/ct/json-editor-codemirror.spec.tsx`). */
+export function JsonEditorCodeMirrorCtHost({ mode }: { mode: JsonEditorMode }) {
+ const [jsonText, setJsonText] = useState(() =>
+ mode === 'control' ? DEFAULT_CONTROL_JSON : '{}'
+ );
+ const [jsonError, setJsonError] = useState(null);
+
+ useEffect(() => {
+ queueMicrotask(() => {
+ setJsonText(mode === 'control' ? DEFAULT_CONTROL_JSON : '{}');
+ setJsonError(null);
+ });
+ }, [mode]);
+
+ const handleJsonChange = useCallback((next: string) => {
+ setJsonText(next);
+ }, []);
+
+ return (
+
+
+
+ {mode === 'control' ? (
+
+ ) : null}
+
+
+
+ );
+}
diff --git a/ui/src/components/json-editor-codemirror/json-editor-codemirror.tsx b/ui/src/components/json-editor-codemirror/json-editor-codemirror.tsx
new file mode 100644
index 00000000..e27d11ae
--- /dev/null
+++ b/ui/src/components/json-editor-codemirror/json-editor-codemirror.tsx
@@ -0,0 +1,718 @@
+import { closeCompletion, startCompletion } from '@codemirror/autocomplete';
+import { json, jsonParseLinter } from '@codemirror/lang-json';
+import { type Diagnostic, linter, lintGutter } from '@codemirror/lint';
+import { EditorSelection, type Extension } from '@codemirror/state';
+import { EditorView, type ViewUpdate } from '@codemirror/view';
+import {
+ ActionIcon,
+ Box,
+ Group,
+ NativeSelect,
+ Text,
+ Tooltip,
+ useMantineColorScheme,
+} from '@mantine/core';
+import { useClipboard, useDebouncedValue } from '@mantine/hooks';
+import {
+ IconClipboardCheck,
+ IconClipboardCopy,
+ IconCode,
+} from '@tabler/icons-react';
+import { findNodeAtLocation, parseTree } from 'jsonc-parser';
+import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
+
+import { isApiError } from '@/core/api/errors';
+import type { ProblemDetail, StepSchema } from '@/core/api/types';
+import { LabelWithTooltip } from '@/core/components/label-with-tooltip';
+import { ApiErrorAlert } from '@/core/page-components/agent-detail/modals/edit-control/api-error-alert';
+import type {
+ JsonEditorEvaluatorOption,
+ JsonEditorMode,
+ JsonSchema,
+} from '@/core/page-components/agent-detail/modals/edit-control/types';
+
+import {
+ CODE_MIRROR_DARK_THEME_PRESETS,
+ CODE_MIRROR_LIGHT_THEME_PRESETS,
+ DEFAULT_DARK_THEME_ID,
+ DEFAULT_LIGHT_THEME_ID,
+ mantineLightCodeMirrorTheme,
+ readStoredCodeMirrorThemePrefs,
+ type StoredCodeMirrorThemePrefs,
+ writeStoredCodeMirrorThemePrefs,
+} from './codemirror-theme-presets';
+import {
+ buildCodeMirrorInlineServerValidationErrorsExtension,
+ buildCodeMirrorJsonExtensions,
+ buildCodeMirrorStandaloneDebugExtensions,
+ caretAfterPrettyJsonReplace,
+ computeAutoEdit,
+ extractEvaluatorNames,
+ fixJsonCommas,
+ getCodeMirrorCompletionItems,
+ setInlineServerValidationErrorsEffect,
+ tryFormat,
+} from './json-editor-codemirror-language';
+import type { JsonEditorCodeMirrorContext } from './language/types';
+
+type JsonEditorTestElement = HTMLDivElement & {
+ __getJsonEditorValue?: () => string;
+ __getJsonEditorLanguageId?: () => string | null;
+ __setJsonEditorValue?: (value: string) => void;
+ __isJsonEditorReady?: () => boolean;
+ __focusJsonEditorAt?: (lineNumber: number, column: number) => void;
+ __triggerJsonEditorSuggest?: () => void;
+ __getJsonEditorSuggestions?: (
+ lineNumber: number,
+ column: number
+ ) => Array<{ label: string; detail?: string }>;
+};
+
+const DEFAULT_HEIGHT = 400;
+const DEFAULT_LABEL = 'Configuration (JSON)';
+const DEFAULT_TOOLTIP = 'Raw JSON configuration';
+const DEFAULT_TEST_ID = 'raw-json-textarea';
+const DEFAULT_VALIDATE_DEBOUNCE_MS = 500;
+
+const DENSITY_THEME = EditorView.theme({
+ '&': {
+ fontSize: '12px',
+ fontFamily:
+ 'ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, monospace',
+ },
+ '.cm-scroller': {
+ fontFamily:
+ 'ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, monospace',
+ lineHeight: '1.4',
+ },
+});
+
+/** Default @codemirror/autocomplete uses maxHeight ~10em; long lists clip the last items. */
+const AUTOCOMPLETE_LIST_THEME = EditorView.theme({
+ '.cm-tooltip.cm-tooltip-autocomplete > ul': {
+ maxHeight: 'min(24em, 55vh)',
+ scrollbarGutter: 'stable',
+ },
+});
+
+type CodeMirrorComponentType = typeof import('@uiw/react-codemirror').default;
+
+export type JsonEditorCodeMirrorProps = {
+ jsonText: string;
+ handleJsonChange: (text: string) => void;
+ jsonError?: string | null;
+ setJsonError?: (error: string | null) => void;
+ validationError?: ProblemDetail | null;
+ setValidationError?: (error: ProblemDetail | null) => void;
+ onValidateConfig?: (
+ config: Record,
+ options?: { signal?: AbortSignal }
+ ) => Promise;
+ onValidationStatusChange?: (
+ status: 'idle' | 'validating' | 'valid' | 'invalid'
+ ) => void;
+ validateDebounceMs?: number;
+ height?: number;
+ label?: string;
+ tooltip?: string;
+ helperText?: React.ReactNode;
+ testId?: string;
+ editorMode?: JsonEditorMode;
+ schema?: JsonSchema | null;
+ evaluators?: JsonEditorEvaluatorOption[];
+ activeEvaluatorId?: string | null;
+ steps?: StepSchema[];
+ debugFlags?: {
+ enableBasicSetupExtension?: boolean;
+ enableAutoEdits?: boolean;
+ enableExternalSync?: boolean;
+ enableLintExtensions?: boolean;
+ useStandaloneCompletionSource?: boolean;
+ };
+};
+
+export function JsonEditorCodeMirror({
+ jsonText,
+ handleJsonChange,
+ jsonError,
+ validationError,
+ onValidateConfig,
+ onValidationStatusChange,
+ setJsonError,
+ setValidationError,
+ validateDebounceMs,
+ height = DEFAULT_HEIGHT,
+ label = DEFAULT_LABEL,
+ tooltip = DEFAULT_TOOLTIP,
+ helperText,
+ testId = DEFAULT_TEST_ID,
+ editorMode = 'evaluator-config',
+ schema,
+ evaluators,
+ activeEvaluatorId,
+ steps,
+ debugFlags,
+}: JsonEditorCodeMirrorProps) {
+ const [CodeMirrorComponent, setCodeMirrorComponent] =
+ useState(null);
+ const { colorScheme } = useMantineColorScheme();
+ const isDarkMode = colorScheme === 'dark';
+ const [cmThemePrefs, setCmThemePrefs] = useState(
+ () => readStoredCodeMirrorThemePrefs()
+ );
+ const [isReady, setIsReady] = useState(false);
+ const [lintErrors, setLintErrors] = useState([]);
+ const editorViewRef = useRef(null);
+ const editorRootRef = useRef(null);
+ const internalChangeRef = useRef(false);
+ const autoEditInProgressRef = useRef(false);
+ const previousEvaluatorNamesRef = useRef