From 4e4fd9b0e43d22ab7ef574d27ec86e32cb52acdc Mon Sep 17 00:00:00 2001 From: dimavedenyapin Date: Mon, 9 Mar 2026 20:30:58 +0800 Subject: [PATCH 1/3] feat: add inline data file viewer for tabular data in agent chat Add DataFilePreview and DataFileDialog components that detect tabular files (CSV, JSON, JSONL, TSV, Excel) in agent tool calls and task attachments, rendering interactive inline table previews with sort, filter, and fullscreen expansion. Parsing is handled in the main process via papaparse and xlsx. Co-Authored-By: Claude Opus 4.6 --- docs/data-file-preview.png | Bin 0 -> 96883 bytes package.json | 10 +- pnpm-lock.yaml | 1748 ++++++++++++++++- .../remotion/DataFilePreviewScreenshot.tsx | 206 ++ scripts/remotion/Root.tsx | 18 + scripts/remotion/index.ts | 4 + scripts/remotion/render-screenshot.mjs | 41 + src/main/ipc-handlers.ts | 93 + src/preload/index.ts | 10 +- .../agents/AgentTranscriptPanel.tsx | 125 +- .../src/components/tasks/TaskAttachments.tsx | 35 +- .../src/components/ui/DataFileDialog.tsx | 35 + .../src/components/ui/DataFilePreview.tsx | 241 +++ src/renderer/src/lib/ipc-client.ts | 16 +- src/renderer/src/types/electron.d.ts | 26 + 15 files changed, 2540 insertions(+), 68 deletions(-) create mode 100644 docs/data-file-preview.png create mode 100644 scripts/remotion/DataFilePreviewScreenshot.tsx create mode 100644 scripts/remotion/Root.tsx create mode 100644 scripts/remotion/index.ts create mode 100644 scripts/remotion/render-screenshot.mjs create mode 100644 src/renderer/src/components/ui/DataFileDialog.tsx create mode 100644 src/renderer/src/components/ui/DataFilePreview.tsx diff --git a/docs/data-file-preview.png b/docs/data-file-preview.png new file mode 100644 index 0000000000000000000000000000000000000000..ca496e17f3bed0f87d68ac81d93524acfec531b4 GIT binary patch literal 96883 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 T_*NPC1n$o5yV5n1#zFrFJeKN! literal 0 HcmV?d00001 diff --git a/package.json b/package.json index 01f225e8..8ed66e64 100644 --- a/package.json +++ b/package.json @@ -36,9 +36,12 @@ "@zed-industries/codex-acp": "^0.9.2", "better-sqlite3": "^12.6.2", "cron-parser": "^5.5.0", + "hyparquet": "^1.25.1", "js-yaml": "^4.1.1", + "papaparse": "^5.5.3", "undici": "^7.21.0", - "ws": "^8.19.0" + "ws": "^8.19.0", + "xlsx": "^0.18.5" }, "devDependencies": { "@electron-toolkit/preload": "^3.0.1", @@ -53,12 +56,16 @@ "@radix-ui/react-switch": "^1.1.1", "@radix-ui/react-tabs": "^1.1.1", "@radix-ui/react-visually-hidden": "^1.2.4", + "@remotion/bundler": "^4.0.434", + "@remotion/cli": "^4.0.434", + "@remotion/renderer": "^4.0.434", "@tailwindcss/vite": "^4.0.0", "@tanstack/react-virtual": "^3.13.19", "@testing-library/jest-dom": "^6.9.1", "@testing-library/react": "^16.3.2", "@types/better-sqlite3": "^7.6.13", "@types/js-yaml": "^4.0.9", + "@types/papaparse": "^5.5.2", "@types/react": "^19.0.0", "@types/react-dom": "^19.0.0", "@types/ws": "^8.18.1", @@ -76,6 +83,7 @@ "react-dom": "^19.0.0", "react-markdown": "^10.1.0", "remark-gfm": "^4.0.1", + "remotion": "^4.0.434", "tailwind-merge": "^2.6.0", "tailwindcss": "^4.0.0", "typescript": "^5.7.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c3e2678e..6d8bc129 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -41,15 +41,24 @@ importers: cron-parser: specifier: ^5.5.0 version: 5.5.0 + hyparquet: + specifier: ^1.25.1 + version: 1.25.1 js-yaml: specifier: ^4.1.1 version: 4.1.1 + papaparse: + specifier: ^5.5.3 + version: 5.5.3 undici: specifier: ^7.21.0 version: 7.21.0 ws: specifier: ^8.19.0 version: 8.19.0 + xlsx: + specifier: ^0.18.5 + version: 0.18.5 devDependencies: '@electron-toolkit/preload': specifier: ^3.0.1 @@ -87,9 +96,18 @@ importers: '@radix-ui/react-visually-hidden': specifier: ^1.2.4 version: 1.2.4(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@remotion/bundler': + specifier: ^4.0.434 + version: 4.0.434(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@remotion/cli': + specifier: ^4.0.434 + version: 4.0.434(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@remotion/renderer': + specifier: ^4.0.434 + version: 4.0.434(react-dom@19.2.4(react@19.2.4))(react@19.2.4) '@tailwindcss/vite': specifier: ^4.0.0 - version: 4.1.18(vite@6.4.1(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2)) + version: 4.1.18(vite@6.4.1(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.46.0)) '@tanstack/react-virtual': specifier: ^3.13.19 version: 3.13.19(react-dom@19.2.4(react@19.2.4))(react@19.2.4) @@ -105,6 +123,9 @@ importers: '@types/js-yaml': specifier: ^4.0.9 version: 4.0.9 + '@types/papaparse': + specifier: ^5.5.2 + version: 5.5.2 '@types/react': specifier: ^19.0.0 version: 19.2.13 @@ -116,7 +137,7 @@ importers: version: 8.18.1 '@vitejs/plugin-react': specifier: ^4.3.4 - version: 4.7.0(vite@6.4.1(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2)) + version: 4.7.0(vite@6.4.1(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.46.0)) class-variance-authority: specifier: ^0.7.1 version: 0.7.1 @@ -131,7 +152,7 @@ importers: version: 25.1.8(electron-builder-squirrel-windows@25.1.8) electron-vite: specifier: ^3.0.0 - version: 3.1.0(vite@6.4.1(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2)) + version: 3.1.0(vite@6.4.1(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.46.0)) eslint: specifier: ^10.0.1 version: 10.0.1(jiti@2.6.1) @@ -156,6 +177,9 @@ importers: remark-gfm: specifier: ^4.0.1 version: 4.0.1 + remotion: + specifier: ^4.0.434 + version: 4.0.434(react-dom@19.2.4(react@19.2.4))(react@19.2.4) tailwind-merge: specifier: ^2.6.0 version: 2.6.1 @@ -170,10 +194,10 @@ importers: version: 8.56.0(eslint@10.0.1(jiti@2.6.1))(typescript@5.9.3) vite: specifier: ^6.0.0 - version: 6.4.1(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2) + version: 6.4.1(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.46.0) vitest: specifier: ^4.0.18 - version: 4.0.18(@types/node@25.2.3)(happy-dom@20.5.0)(jiti@2.6.1)(lightningcss@1.30.2) + version: 4.0.18(@types/node@25.2.3)(happy-dom@20.5.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.46.0) zustand: specifier: ^5.0.3 version: 5.0.11(@types/react@19.2.13)(react@19.2.4) @@ -251,6 +275,11 @@ packages: resolution: {integrity: sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==} engines: {node: '>=6.9.0'} + '@babel/parser@7.24.1': + resolution: {integrity: sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg==} + engines: {node: '>=6.0.0'} + hasBin: true + '@babel/parser@7.29.0': resolution: {integrity: sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==} engines: {node: '>=6.0.0'} @@ -336,126 +365,261 @@ packages: resolution: {integrity: sha512-fKpv9kg4SPmt+hY7SVBnIYULE9QJl8L3sCfcBsnqbJwwBwAeTLokJ9TRt9y7bK0JAzIW2y78TVVjvnQEms/yyA==} engines: {node: '>=16.4'} + '@emnapi/core@1.8.1': + resolution: {integrity: sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==} + + '@emnapi/runtime@1.8.1': + resolution: {integrity: sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==} + + '@emnapi/wasi-threads@1.1.0': + resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==} + + '@esbuild/aix-ppc64@0.25.0': + resolution: {integrity: sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + '@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.0': + resolution: {integrity: sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + '@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.0': + resolution: {integrity: sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g==} + engines: {node: '>=18'} + cpu: [arm] + 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.0': + resolution: {integrity: sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg==} + engines: {node: '>=18'} + cpu: [x64] + 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.0': + resolution: {integrity: sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + '@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.0': + resolution: {integrity: sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + '@esbuild/darwin-x64@0.25.12': resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} engines: {node: '>=18'} cpu: [x64] os: [darwin] + '@esbuild/freebsd-arm64@0.25.0': + resolution: {integrity: sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + '@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.0': + resolution: {integrity: sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + '@esbuild/freebsd-x64@0.25.12': resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] + '@esbuild/linux-arm64@0.25.0': + resolution: {integrity: sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + '@esbuild/linux-arm64@0.25.12': resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} engines: {node: '>=18'} cpu: [arm64] os: [linux] + '@esbuild/linux-arm@0.25.0': + resolution: {integrity: sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg==} + engines: {node: '>=18'} + cpu: [arm] + 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.0': + resolution: {integrity: sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==} + engines: {node: '>=18'} + cpu: [ia32] + 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.0': + resolution: {integrity: sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw==} + engines: {node: '>=18'} + cpu: [loong64] + 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.0': + resolution: {integrity: sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ==} + engines: {node: '>=18'} + cpu: [mips64el] + 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.0': + resolution: {integrity: sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw==} + engines: {node: '>=18'} + cpu: [ppc64] + 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.0': + resolution: {integrity: sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA==} + engines: {node: '>=18'} + cpu: [riscv64] + 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.0': + resolution: {integrity: sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA==} + engines: {node: '>=18'} + cpu: [s390x] + 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.0': + resolution: {integrity: sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw==} + engines: {node: '>=18'} + cpu: [x64] + 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.0': + resolution: {integrity: sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + '@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.0': + resolution: {integrity: sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA==} + engines: {node: '>=18'} + cpu: [x64] + 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.0': + resolution: {integrity: sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + '@esbuild/openbsd-arm64@0.25.12': resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] + '@esbuild/openbsd-x64@0.25.0': + resolution: {integrity: sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + '@esbuild/openbsd-x64@0.25.12': resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} engines: {node: '>=18'} @@ -468,24 +632,48 @@ packages: cpu: [arm64] os: [openharmony] + '@esbuild/sunos-x64@0.25.0': + resolution: {integrity: sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + '@esbuild/sunos-x64@0.25.12': resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} engines: {node: '>=18'} cpu: [x64] os: [sunos] + '@esbuild/win32-arm64@0.25.0': + resolution: {integrity: sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + '@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.0': + resolution: {integrity: sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + '@esbuild/win32-ia32@0.25.12': resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} engines: {node: '>=18'} cpu: [ia32] os: [win32] + '@esbuild/win32-x64@0.25.0': + resolution: {integrity: sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + '@esbuild/win32-x64@0.25.12': resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} engines: {node: '>=18'} @@ -667,6 +855,9 @@ packages: resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} + '@jridgewell/source-map@0.3.11': + resolution: {integrity: sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==} + '@jridgewell/sourcemap-codec@1.5.5': resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} @@ -681,6 +872,21 @@ packages: resolution: {integrity: sha512-9QOtNffcOF/c1seMCDnjckb3R9WHcG34tky+FHpNKKCW0wc/scYLwMtO+ptyGUfMW0/b/n4qRiALlaFHc9Oj7Q==} engines: {node: '>= 10.0.0'} + '@mediabunny/aac-encoder@1.37.0': + resolution: {integrity: sha512-mYnF1sObnPE+7+QWn9H7c0rbl5Dwu50JejUD/GJefRl8ozYp0sz3tt+zBLCeif5GXBkPhABIX3JVg1eGfqx6tg==} + peerDependencies: + mediabunny: ^1.0.0 + + '@mediabunny/flac-encoder@1.37.0': + resolution: {integrity: sha512-VwKIL5p1WZE4dSwZ1SVv/bd2ksul8a4run4S1eEbPRysnG87nmCXddO5ajD3b2k2478XWitKnVDXl/kxdIIWBw==} + peerDependencies: + mediabunny: ^1.0.0 + + '@mediabunny/mp3-encoder@1.37.0': + resolution: {integrity: sha512-6tXBO3iHDA55WiMhOoaOmeCCOQ51U38mdXRxYNS9/hUCpR0ScRo+NtWu2YUa/jp2q99JNPrA4yYjahE5xHDxpg==} + peerDependencies: + mediabunny: ^1.0.0 + '@modelcontextprotocol/sdk@1.26.0': resolution: {integrity: sha512-Y5RmPncpiDtTXDbLKswIJzTqu2hyBKxTNsgKqKclDbhIgg1wgtf1fRuvxgTnRfcnxtvvgbIEcqUOzZrJ6iSReg==} engines: {node: '>=18'} @@ -691,6 +897,27 @@ packages: '@cfworker/json-schema': optional: true + '@module-federation/error-codes@0.22.0': + resolution: {integrity: sha512-xF9SjnEy7vTdx+xekjPCV5cIHOGCkdn3pIxo9vU7gEZMIw0SvAEdsy6Uh17xaCpm8V0FWvR0SZoK9Ik6jGOaug==} + + '@module-federation/runtime-core@0.22.0': + resolution: {integrity: sha512-GR1TcD6/s7zqItfhC87zAp30PqzvceoeDGYTgF3Vx2TXvsfDrhP6Qw9T4vudDQL3uJRne6t7CzdT29YyVxlgIA==} + + '@module-federation/runtime-tools@0.22.0': + resolution: {integrity: sha512-4ScUJ/aUfEernb+4PbLdhM/c60VHl698Gn1gY21m9vyC1Ucn69fPCA1y2EwcCB7IItseRMoNhdcWQnzt/OPCNA==} + + '@module-federation/runtime@0.22.0': + resolution: {integrity: sha512-38g5iPju2tPC3KHMPxRKmy4k4onNp6ypFPS1eKGsNLUkXgHsPMBFqAjDw96iEcjri91BrahG4XcdyKi97xZzlA==} + + '@module-federation/sdk@0.22.0': + resolution: {integrity: sha512-x4aFNBKn2KVQRuNVC5A7SnrSCSqyfIWmm1DvubjbO9iKFe7ith5niw8dqSFBekYBg2Fwy+eMg4sEFNVvCAdo6g==} + + '@module-federation/webpack-bundler-runtime@0.22.0': + resolution: {integrity: sha512-aM8gCqXu+/4wBmJtVeMeeMN5guw3chf+2i6HajKtQv7SJfxV/f4IyNQJUeUQu9HfiAZHjqtMV5Lvq/Lvh8LdyA==} + + '@napi-rs/wasm-runtime@1.0.7': + resolution: {integrity: sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw==} + '@noble/hashes@1.8.0': resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==} engines: {node: ^14.21.3 || >=16} @@ -1118,6 +1345,107 @@ packages: '@radix-ui/rect@1.1.1': resolution: {integrity: sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==} + '@remotion/bundler@4.0.434': + resolution: {integrity: sha512-S62GkQnMbS/svtNTxZwWvKE7oCSVGaeZllMMig07bFXsf+xLbgfZDBhe4iMqdOyk9+++OVmwgz0qNo+1q2r0FQ==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + + '@remotion/cli@4.0.434': + resolution: {integrity: sha512-yuZYBQ1mXCJJaQHAf60Y1HupCWGqIM3hV+BYrGwx/TiXqv1GVMU4On5yuJSGVKoOc8ZTZkorOB0gNzB8fzC8qg==} + hasBin: true + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + + '@remotion/compositor-darwin-arm64@4.0.434': + resolution: {integrity: sha512-9nJgIQcUrOYhr9EsbvCMNhC7g/HD/R+cDPsatFaD2FONHHNLKLZQp/wHGyPfcriblvoxy2hRjfqV8Z7nmkaWAQ==} + cpu: [arm64] + os: [darwin] + + '@remotion/compositor-darwin-x64@4.0.434': + resolution: {integrity: sha512-oIlEnStUCdVQbP5DB0GSXCavoWUaSpd+1z1VsSd7x9QfHiv4BsVjit3Say/HejoJB27YxuSzol47qhRDrruPEA==} + cpu: [x64] + os: [darwin] + + '@remotion/compositor-linux-arm64-gnu@4.0.434': + resolution: {integrity: sha512-928YpjfSKcVBIIJl1HI7KYiYYYQpsxdVldzvDjl3eWViqExeErzsS/R0lH/cDSaxtHttFDw+FgKr3RKsX9Yc8Q==} + cpu: [arm64] + os: [linux] + + '@remotion/compositor-linux-arm64-musl@4.0.434': + resolution: {integrity: sha512-8xEEhKk0E+dTtHnr/ESIZX1USBc6w/pbsxddzLFtaQLsfyiM+lfpvL/j/gYVdTZbqKe9idOkX14n3GlIu4N9rA==} + cpu: [arm64] + os: [linux] + + '@remotion/compositor-linux-x64-gnu@4.0.434': + resolution: {integrity: sha512-zvzLVeSK08j9U0z2FokwQ4DXAdbvL5oUboikR7G5l4e+ziYGx7dukCsTBDBb5Egd8eT+497viaWNSi1dK7hY0Q==} + cpu: [x64] + os: [linux] + + '@remotion/compositor-linux-x64-musl@4.0.434': + resolution: {integrity: sha512-Dze2Dsu+1oMmBrTQXWIfL+PwlA7XG2wBoaIE2W6/UAWAdKRb7vRybenDT7vIL9ErVREnVDxwHLF4NwpB2WeMFA==} + cpu: [x64] + os: [linux] + + '@remotion/compositor-win32-x64-msvc@4.0.434': + resolution: {integrity: sha512-3PmLo03LBYf123FvjlUNphbtnTJnvToHMDgBQYdrlQBGbAQpJGLsX7IViQwWSNFGZVzonwliNtC9568Nbts8lw==} + cpu: [x64] + os: [win32] + + '@remotion/licensing@4.0.434': + resolution: {integrity: sha512-Jp9pHUlQBOX7ZjDuG9OVIEDGU5JiN2eSjvHEDS8zwyIIGUaRwDhZRzvGULEiZpu1IJ6UMDpHqIylJ18Inl1PMg==} + + '@remotion/media-parser@4.0.434': + resolution: {integrity: sha512-+vuVOTd3v9BR2WQE3N4CUsCCUb4z8U1bvvxKrP6NGL9nqudu6IQpueXHNwxc/RzDTaxJ1aH6xOLzB3Iqc6EnIA==} + + '@remotion/media-utils@4.0.434': + resolution: {integrity: sha512-3wBtgZSBNXqwQFqQp6eLwsw3m32zlGhZHsD8bn1TeBJQkHflUXo3WhmGkLoUoZdU8nGutFOoFtckjVq1DEXzpg==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + + '@remotion/player@4.0.434': + resolution: {integrity: sha512-H3SugDjf0QS7lU85A/hej+zUqJLRd0EHfW0jBsu4kerYVXZqi2vswqf7MRqEwQhMGtySVrhI+n9fGBqfcAbRpw==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + + '@remotion/renderer@4.0.434': + resolution: {integrity: sha512-I0MT0A6YHpO420ntQjF0KzERetpYcnsHlMNUWlNFDeAzFuEjrOgUcZ+6NcUV1lX9nOhixLANvfuMpCrdZazdYg==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + + '@remotion/streaming@4.0.434': + resolution: {integrity: sha512-Qlb7sSSXs3nkbs/C/62fLIn/ZxUiNdqtnim3AzAMmi9HdC1qcCMAJiQfugnpnKQ57xbS5Okp1HzSPQalpcgXgw==} + + '@remotion/studio-server@4.0.434': + resolution: {integrity: sha512-k1j7he3H6H19t0iiJ6qNRqzJiGqLzpSfFoi7Hb1NVAwFbcrBOYCsRh/sr+ecL5VMAcWZf2s+cgnaL+mZD6sCrQ==} + + '@remotion/studio-shared@4.0.434': + resolution: {integrity: sha512-5HL2ciT8BpGW8izhwOehMBVh2fR+/2X5EjoIUlWrXoDWpSgzSXmT8yI2nkKmBCxbZyYyyW/pQZKkvDj56jcB2Q==} + + '@remotion/studio@4.0.434': + resolution: {integrity: sha512-faNm11hVsjFyjNg9R7TQZcjsDflUfqkWGgbrq5jSubpVJD+eHEVBo1HIZwrDHIlvee8gTyAscR0tFrH27PLShQ==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + + '@remotion/web-renderer@4.0.434': + resolution: {integrity: sha512-yYLQ/BbIlHd61pFH0B979UYWUnSMwubXvf1jeyu6w7/44Z2ZbI4h05fzzvIKEr9XZFZSVntBWeFUHuNCf/Tomg==} + peerDependencies: + react: '>=18.0.0' + react-dom: '>=18.0.0' + + '@remotion/webcodecs@4.0.434': + resolution: {integrity: sha512-Eq/3EB9w0L2F4Q2lgTXcc7maoGYn0nkfvoKclVkA4N6gsfgNand+SX/nDe8n8JMOD8NsEKOs5EEd3YWYY3oN5A==} + + '@remotion/zod-types@4.0.434': + resolution: {integrity: sha512-5urhO+1NYCWvddy7cPdqqfHH+VLHP1+5pREO8fqwemIU6jmJR9SFR0vDgMa9wyrQfGyQA7Q0sTMX73KInwszFg==} + peerDependencies: + zod: 4.3.6 + '@rolldown/pluginutils@1.0.0-beta.27': resolution: {integrity: sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==} @@ -1246,6 +1574,79 @@ packages: cpu: [x64] os: [win32] + '@rspack/binding-darwin-arm64@1.7.6': + resolution: {integrity: sha512-NZ9AWtB1COLUX1tA9HQQvWpTy07NSFfKBU8A6ylWd5KH8AePZztpNgLLAVPTuNO4CZXYpwcoclf8jG/luJcQdQ==} + cpu: [arm64] + os: [darwin] + + '@rspack/binding-darwin-x64@1.7.6': + resolution: {integrity: sha512-J2g6xk8ZS7uc024dNTGTHxoFzFovAZIRixUG7PiciLKTMP78svbSSWrmW6N8oAsAkzYfJWwQpVgWfFNRHvYxSw==} + cpu: [x64] + os: [darwin] + + '@rspack/binding-linux-arm64-gnu@1.7.6': + resolution: {integrity: sha512-eQfcsaxhFrv5FmtaA7+O1F9/2yFDNIoPZzV/ZvqvFz5bBXVc4FAm/1fVpBg8Po/kX1h0chBc7Xkpry3cabFW8w==} + cpu: [arm64] + os: [linux] + + '@rspack/binding-linux-arm64-musl@1.7.6': + resolution: {integrity: sha512-DfQXKiyPIl7i1yECHy4eAkSmlUzzsSAbOjgMuKn7pudsWf483jg0UUYutNgXSlBjc/QSUp7906Cg8oty9OfwPA==} + cpu: [arm64] + os: [linux] + + '@rspack/binding-linux-x64-gnu@1.7.6': + resolution: {integrity: sha512-NdA+2X3lk2GGrMMnTGyYTzM3pn+zNjaqXqlgKmFBXvjfZqzSsKq3pdD1KHZCd5QHN+Fwvoszj0JFsquEVhE1og==} + cpu: [x64] + os: [linux] + + '@rspack/binding-linux-x64-musl@1.7.6': + resolution: {integrity: sha512-rEy6MHKob02t/77YNgr6dREyJ0e0tv1X6Xsg8Z5E7rPXead06zefUbfazj4RELYySWnM38ovZyJAkPx/gOn3VA==} + cpu: [x64] + os: [linux] + + '@rspack/binding-wasm32-wasi@1.7.6': + resolution: {integrity: sha512-YupOrz0daSG+YBbCIgpDgzfMM38YpChv+afZpaxx5Ml7xPeAZIIdgWmLHnQ2rts73N2M1NspAiBwV00Xx0N4Vg==} + cpu: [wasm32] + + '@rspack/binding-win32-arm64-msvc@1.7.6': + resolution: {integrity: sha512-INj7aVXjBvlZ84kEhSK4kJ484ub0i+BzgnjDWOWM1K+eFYDZjLdAsQSS3fGGXwVc3qKbPIssFfnftATDMTEJHQ==} + cpu: [arm64] + os: [win32] + + '@rspack/binding-win32-ia32-msvc@1.7.6': + resolution: {integrity: sha512-lXGvC+z67UMcw58In12h8zCa9IyYRmuptUBMItQJzu+M278aMuD1nETyGLL7e4+OZ2lvrnnBIcjXN1hfw2yRzw==} + cpu: [ia32] + os: [win32] + + '@rspack/binding-win32-x64-msvc@1.7.6': + resolution: {integrity: sha512-zeUxEc0ZaPpmaYlCeWcjSJUPuRRySiSHN23oJ2Xyw0jsQ01Qm4OScPdr0RhEOFuK/UE+ANyRtDo4zJsY52Hadw==} + cpu: [x64] + os: [win32] + + '@rspack/binding@1.7.6': + resolution: {integrity: sha512-/NrEcfo8Gx22hLGysanrV6gHMuqZSxToSci/3M4kzEQtF5cPjfOv5pqeLK/+B6cr56ul/OmE96cCdWcXeVnFjQ==} + + '@rspack/core@1.7.6': + resolution: {integrity: sha512-Iax6UhrfZqJajA778c1d5DBFbSIqPOSrI34kpNIiNpWd8Jq7mFIa+Z60SQb5ZQDZuUxcCZikjz5BxinFjTkg7Q==} + engines: {node: '>=18.12.0'} + peerDependencies: + '@swc/helpers': '>=0.5.1' + peerDependenciesMeta: + '@swc/helpers': + optional: true + + '@rspack/lite-tapable@1.1.0': + resolution: {integrity: sha512-E2B0JhYFmVAwdDiG14+DW0Di4Ze4Jg10Pc4/lILUrd5DRCaklduz2OvJ5HYQ6G+hd+WTzqQb3QnDNfK4yvAFYw==} + + '@rspack/plugin-react-refresh@1.6.1': + resolution: {integrity: sha512-eqqW5645VG3CzGzFgNg5HqNdHVXY+567PGjtDhhrM8t67caxmsSzRmT5qfoEIfBcGgFkH9vEg7kzXwmCYQdQDw==} + peerDependencies: + react-refresh: '>=0.10.0 <1.0.0' + webpack-hot-middleware: 2.x + peerDependenciesMeta: + webpack-hot-middleware: + optional: true + '@sindresorhus/is@4.6.0': resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} engines: {node: '>=10'} @@ -1407,6 +1808,9 @@ packages: resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} engines: {node: '>= 10'} + '@tybys/wasm-util@0.10.1': + resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} + '@types/aria-query@5.0.4': resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} @@ -1437,6 +1841,18 @@ packages: '@types/deep-eql@4.0.2': resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + '@types/dom-mediacapture-transform@0.1.11': + resolution: {integrity: sha512-Y2p+nGf1bF2XMttBnsVPHUWzRRZzqUoJAKmiP10b5umnO6DDrWI0BrGDJy1pOHoOULVmGSfFNkQrAlC5dcj6nQ==} + + '@types/dom-webcodecs@0.1.13': + resolution: {integrity: sha512-O5hkiFIcjjszPIYyUSyvScyvrBoV3NOEEZx/pMlsu44TKzWNkLVBBxnxJz42in5n3QIolYOcBYFCPZZ0h8SkwQ==} + + '@types/eslint-scope@3.7.7': + resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} + + '@types/eslint@9.6.1': + resolution: {integrity: sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==} + '@types/esrecurse@4.3.1': resolution: {integrity: sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==} @@ -1479,6 +1895,9 @@ packages: '@types/node@25.2.3': resolution: {integrity: sha512-m0jEgYlYz+mDJZ2+F4v8D1AyQb+QzsNqRuI7xg1VQX/KlKS0qT9r1Mo16yo5F/MtifXFgaofIFsdFMox2SxIbQ==} + '@types/papaparse@5.5.2': + resolution: {integrity: sha512-gFnFp/JMzLHCwRf7tQHrNnfhN4eYBVYYI897CGX4MY1tzY9l2aLkVyx2IlKZ/SAqDbB3I1AOZW5gTMGGsqWliA==} + '@types/phoenix@1.6.7': resolution: {integrity: sha512-oN9ive//QSBkf19rfDv45M7eZPi0eEXylht2OLEXicu5b4KoQ1OzXIw+xDSGWxSxe1JmepRR/ZH283vsu518/Q==} @@ -1611,10 +2030,61 @@ packages: '@vitest/utils@4.0.18': resolution: {integrity: sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA==} + '@webassemblyjs/ast@1.14.1': + resolution: {integrity: sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==} + + '@webassemblyjs/floating-point-hex-parser@1.13.2': + resolution: {integrity: sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==} + + '@webassemblyjs/helper-api-error@1.13.2': + resolution: {integrity: sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==} + + '@webassemblyjs/helper-buffer@1.14.1': + resolution: {integrity: sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==} + + '@webassemblyjs/helper-numbers@1.13.2': + resolution: {integrity: sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==} + + '@webassemblyjs/helper-wasm-bytecode@1.13.2': + resolution: {integrity: sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==} + + '@webassemblyjs/helper-wasm-section@1.14.1': + resolution: {integrity: sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==} + + '@webassemblyjs/ieee754@1.13.2': + resolution: {integrity: sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==} + + '@webassemblyjs/leb128@1.13.2': + resolution: {integrity: sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==} + + '@webassemblyjs/utf8@1.13.2': + resolution: {integrity: sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==} + + '@webassemblyjs/wasm-edit@1.14.1': + resolution: {integrity: sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==} + + '@webassemblyjs/wasm-gen@1.14.1': + resolution: {integrity: sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==} + + '@webassemblyjs/wasm-opt@1.14.1': + resolution: {integrity: sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==} + + '@webassemblyjs/wasm-parser@1.14.1': + resolution: {integrity: sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==} + + '@webassemblyjs/wast-printer@1.14.1': + resolution: {integrity: sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==} + '@xmldom/xmldom@0.8.11': resolution: {integrity: sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==} engines: {node: '>=10.0.0'} + '@xtuc/ieee754@1.2.0': + resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} + + '@xtuc/long@4.2.2': + resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} + '@zed-industries/claude-code-acp@0.16.1': resolution: {integrity: sha512-/fKDYLCtiKthYUeOu4vPHSE79arh0ciYnBd5uSTY8OWMURJoelBwkK5QGZZSmxjAwG9tHkvjxUjxhMDgC071VA==} hasBin: true @@ -1666,6 +2136,12 @@ packages: resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==} engines: {node: '>= 0.6'} + acorn-import-phases@1.0.4: + resolution: {integrity: sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==} + engines: {node: '>=10.13.0'} + peerDependencies: + acorn: ^8.14.0 + acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -1676,6 +2152,10 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + adler-32@1.3.1: + resolution: {integrity: sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==} + engines: {node: '>=0.8'} + agent-base@6.0.2: resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} engines: {node: '>= 6.0.0'} @@ -1692,6 +2172,14 @@ packages: resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} engines: {node: '>=8'} + ajv-formats@2.1.1: + resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + ajv-formats@3.0.1: resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} peerDependencies: @@ -1705,6 +2193,11 @@ packages: peerDependencies: ajv: ^6.9.1 + ajv-keywords@5.1.0: + resolution: {integrity: sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==} + peerDependencies: + ajv: ^8.8.2 + ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} @@ -1783,6 +2276,10 @@ packages: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} + ast-types@0.16.1: + resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==} + engines: {node: '>=4'} + astral-regex@2.0.0: resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} engines: {node: '>=8'} @@ -1822,6 +2319,9 @@ packages: resolution: {integrity: sha512-8VYKM3MjCa9WcaSAI3hzwhmyHVlH8tiGFwf0RlTsZPWJ1I5MkzjiudCo4KC4DxOaL/53A5B1sI/IbldNFDbsKA==} engines: {node: 20.x || 22.x || 23.x || 24.x || 25.x} + big.js@5.2.2: + resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==} + bindings@1.5.0: resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} @@ -1907,6 +2407,10 @@ packages: ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} + cfb@1.2.2: + resolution: {integrity: sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==} + engines: {node: '>=0.8'} + chai@6.2.2: resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} engines: {node: '>=18'} @@ -1934,6 +2438,10 @@ packages: resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} engines: {node: '>=10'} + chrome-trace-event@1.0.4: + resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==} + engines: {node: '>=6.0'} + chromium-pickle-js@0.2.0: resolution: {integrity: sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw==} @@ -1975,6 +2483,10 @@ packages: resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} engines: {node: '>=6'} + codepage@1.15.0: + resolution: {integrity: sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==} + engines: {node: '>=0.8'} + color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} @@ -1993,6 +2505,9 @@ packages: comma-separated-tokens@2.0.3: resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} + commander@2.20.3: + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + commander@5.1.0: resolution: {integrity: sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==} engines: {node: '>= 6'} @@ -2063,9 +2578,20 @@ packages: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} + css-loader@5.2.7: + resolution: {integrity: sha512-Q7mOvpBNBG7YrVGMxRxcBJZFL75o+cH2abNASdibkj/fffYD8qWbInZrD0S9ccI6vZclF3DsHE7njGlLtaHbhg==} + engines: {node: '>= 10.13.0'} + peerDependencies: + webpack: ^4.27.0 || ^5.0.0 + css.escape@1.5.1: resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==} + cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + csstype@3.2.3: resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} @@ -2103,6 +2629,10 @@ packages: resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} engines: {node: '>= 0.4'} + define-lazy-prop@2.0.0: + resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} + engines: {node: '>=8'} + define-properties@1.2.1: resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} engines: {node: '>= 0.4'} @@ -2165,6 +2695,10 @@ packages: resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==} engines: {node: '>=12'} + dotenv@17.3.1: + resolution: {integrity: sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA==} + engines: {node: '>=12'} + dunder-proto@1.0.1: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} @@ -2216,6 +2750,10 @@ packages: emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + emojis-list@3.0.0: + resolution: {integrity: sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==} + engines: {node: '>= 4'} + encodeurl@2.0.0: resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} engines: {node: '>= 0.8'} @@ -2241,6 +2779,9 @@ packages: err-code@2.0.3: resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==} + error-stack-parser@2.1.4: + resolution: {integrity: sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==} + es-define-property@1.0.1: resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} engines: {node: '>= 0.4'} @@ -2252,6 +2793,9 @@ packages: es-module-lexer@1.7.0: resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} + es-module-lexer@2.0.0: + resolution: {integrity: sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==} + es-object-atoms@1.1.1: resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} engines: {node: '>= 0.4'} @@ -2263,6 +2807,11 @@ packages: es6-error@4.1.1: resolution: {integrity: sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==} + esbuild@0.25.0: + resolution: {integrity: sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw==} + engines: {node: '>=18'} + hasBin: true + esbuild@0.25.12: resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} engines: {node: '>=18'} @@ -2283,6 +2832,10 @@ packages: resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} engines: {node: '>=12'} + eslint-scope@5.1.1: + resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} + engines: {node: '>=8.0.0'} + eslint-scope@9.1.1: resolution: {integrity: sha512-GaUN0sWim5qc8KVErfPBWmc31LEsOkrUJbvJZV+xuL3u2phMUK4HIvXlWAakfC8W4nzlK+chPEAkYOYb5ZScIw==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} @@ -2309,6 +2862,11 @@ packages: resolution: {integrity: sha512-AVHPqQoZYc+RUM4/3Ly5udlZY/U4LS8pIG05jEjWM2lQMU/oaZ7qshzAl2YP1tfNmXfftH3ohurfwNAug+MnsQ==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + esquery@1.7.0: resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} engines: {node: '>=0.10'} @@ -2317,6 +2875,10 @@ packages: resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} engines: {node: '>=4.0'} + estraverse@4.3.0: + resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} + engines: {node: '>=4.0'} + estraverse@5.3.0: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} @@ -2335,6 +2897,10 @@ packages: resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} engines: {node: '>= 0.6'} + events@3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + eventsource-parser@3.0.6: resolution: {integrity: sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==} engines: {node: '>=18.0.0'} @@ -2343,6 +2909,10 @@ packages: resolution: {integrity: sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==} engines: {node: '>=18.0.0'} + execa@5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + expand-template@2.0.3: resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} engines: {node: '>=6'} @@ -2437,6 +3007,10 @@ packages: resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} engines: {node: '>= 0.6'} + frac@1.1.2: + resolution: {integrity: sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==} + engines: {node: '>=0.8'} + fresh@2.0.0: resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==} engines: {node: '>= 0.8'} @@ -2464,6 +3038,9 @@ packages: resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} engines: {node: '>= 8'} + fs-monkey@1.0.3: + resolution: {integrity: sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==} + fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} @@ -2504,6 +3081,10 @@ packages: resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} engines: {node: '>=8'} + get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + github-from-package@0.0.0: resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} @@ -2511,6 +3092,9 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} + glob-to-regexp@0.4.1: + resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} + glob@10.5.0: resolution: {integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==} deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me @@ -2584,6 +3168,9 @@ packages: resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} engines: {node: '>=10'} + html-entities@2.6.0: + resolution: {integrity: sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==} + html-url-attributes@3.0.1: resolution: {integrity: sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==} @@ -2614,6 +3201,10 @@ packages: resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} engines: {node: '>= 14'} + human-signals@2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + humanize-ms@1.2.1: resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} @@ -2622,6 +3213,9 @@ packages: engines: {node: '>=18'} hasBin: true + hyparquet@1.25.1: + resolution: {integrity: sha512-CXcN/u6RdQqsK8IphUptpAEqY8IzgwzHY+MuXX+2wpoWTumfxPVr6JYbbywsNsiAl9aEbM5sRtxkwRBa22b49w==} + iceberg-js@0.8.1: resolution: {integrity: sha512-1dhVQZXhcHje7798IVM+xoo/1ZdVfzOMIc8/rgVSijRK38EDqOJoGula9N/8ZI5RD8QTxNQtK/Gozpr+qUqRRA==} engines: {node: '>=20.0.0'} @@ -2639,6 +3233,12 @@ packages: resolution: {integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==} engines: {node: '>=0.10.0'} + icss-utils@5.1.0: + resolution: {integrity: sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} @@ -2699,6 +3299,11 @@ packages: is-decimal@2.0.1: resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} + is-docker@2.2.1: + resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} + engines: {node: '>=8'} + hasBin: true + is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -2728,10 +3333,18 @@ packages: is-promise@4.0.0: resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} + is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + is-unicode-supported@0.1.0: resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} engines: {node: '>=10'} + is-wsl@2.2.0: + resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} + engines: {node: '>=8'} + isarray@1.0.0: resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} @@ -2754,6 +3367,10 @@ packages: engines: {node: '>=10'} hasBin: true + jest-worker@27.5.1: + resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} + engines: {node: '>= 10.13.0'} + jiti@2.6.1: resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} hasBin: true @@ -2776,6 +3393,9 @@ packages: json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} @@ -2805,6 +3425,10 @@ packages: keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + kleur@3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} + lazy-val@1.0.5: resolution: {integrity: sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==} @@ -2886,6 +3510,14 @@ packages: resolution: {integrity: sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==} engines: {node: '>= 12.0.0'} + loader-runner@4.3.1: + resolution: {integrity: sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==} + engines: {node: '>=6.11.5'} + + loader-utils@2.0.4: + resolution: {integrity: sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==} + engines: {node: '>=8.9.0'} + locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} @@ -2902,6 +3534,9 @@ packages: lodash.isplainobject@4.0.6: resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + lodash.sortby@4.7.0: + resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} + lodash.union@4.6.0: resolution: {integrity: sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==} @@ -3013,10 +3648,20 @@ packages: resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==} engines: {node: '>= 0.8'} + mediabunny@1.37.0: + resolution: {integrity: sha512-eV7M9IJ29pr/8RNL1sYtIxNbdMfDMN1hMwMaOFfNLhwuKKGSC+eKwiJFpdVjEJ3zrMA4LGerF4Hps0SENFSAlg==} + + memfs@3.4.3: + resolution: {integrity: sha512-eivjfi7Ahr6eQTn44nvTnR60e4a1Fs1Via2kCR5lHo/kyNoiMWaXCNJ/GpSd0ilXas2JSOl9B5FTIhflXu0hlg==} + engines: {node: '>= 4.0.0'} + merge-descriptors@2.0.0: resolution: {integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==} engines: {node: '>=18'} + merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + micromark-core-commonmark@2.0.3: resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==} @@ -3157,6 +3802,9 @@ packages: resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} engines: {node: '>=16 || 14 >=14.17'} + minimist@1.2.6: + resolution: {integrity: sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==} + minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} @@ -3226,6 +3874,9 @@ packages: resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==} engines: {node: '>= 0.6'} + neo-async@2.6.2: + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + node-abi@3.87.0: resolution: {integrity: sha512-+CGM1L1CgmtheLcBuleyYOn7NWPVu0s0EJH2C4puxgEZb9h8QpR9G2dBfZJOAUhi7VQxuBPMd0hiISWcTyiYyQ==} engines: {node: '>=10'} @@ -3257,6 +3908,10 @@ packages: resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==} engines: {node: '>=10'} + npm-run-path@4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + npmlog@6.0.2: resolution: {integrity: sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} @@ -3288,6 +3943,10 @@ packages: resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} engines: {node: '>=6'} + open@8.4.2: + resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} + engines: {node: '>=12'} + optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} @@ -3315,6 +3974,9 @@ packages: package-json-from-dist@1.0.1: resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + papaparse@5.5.3: + resolution: {integrity: sha512-5QvjGxYVjxO59MGU2lHVYpRWBBtKHnlIAcSe1uNFCkkptUh63NFRj0FJQm7nR67puEruUci/ZkjmEFrjCAyP4A==} + parse-entities@4.0.2: resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==} @@ -3366,6 +4028,37 @@ packages: resolution: {integrity: sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==} engines: {node: '>=10.4.0'} + postcss-modules-extract-imports@3.1.0: + resolution: {integrity: sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + postcss-modules-local-by-default@4.2.0: + resolution: {integrity: sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + postcss-modules-scope@3.2.1: + resolution: {integrity: sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + postcss-modules-values@4.0.0: + resolution: {integrity: sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + postcss-selector-parser@7.1.1: + resolution: {integrity: sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==} + engines: {node: '>=4'} + + postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + postcss@8.5.6: resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} engines: {node: ^10 || ^12 || >=14} @@ -3379,6 +4072,11 @@ packages: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} + prettier@3.8.1: + resolution: {integrity: sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==} + engines: {node: '>=14'} + hasBin: true + pretty-format@27.5.1: resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -3402,6 +4100,10 @@ packages: resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==} engines: {node: '>=10'} + prompts@2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} + property-information@7.1.0: resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==} @@ -3454,6 +4156,10 @@ packages: resolution: {integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==} engines: {node: '>=0.10.0'} + react-refresh@0.18.0: + resolution: {integrity: sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==} + engines: {node: '>=0.10.0'} + react-remove-scroll-bar@2.3.8: resolution: {integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==} engines: {node: '>=10'} @@ -3502,6 +4208,10 @@ packages: readdir-glob@1.1.3: resolution: {integrity: sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==} + recast@0.23.11: + resolution: {integrity: sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==} + engines: {node: '>= 4'} + redent@3.0.0: resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} engines: {node: '>=8'} @@ -3518,6 +4228,12 @@ packages: remark-stringify@11.0.0: resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==} + remotion@4.0.434: + resolution: {integrity: sha512-r5SRjrB9lFeZPkNGTcFG0qJJOhV7m/W/xandMvReCZyvV8D3ScmfpJWqRoq/zGzBt6t2F6TW/3sUQ0QTU110ZQ==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} @@ -3581,6 +4297,14 @@ packages: scheduler@0.27.0: resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} + schema-utils@3.3.0: + resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==} + engines: {node: '>= 10.13.0'} + + schema-utils@4.3.3: + resolution: {integrity: sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==} + engines: {node: '>= 10.13.0'} + semver-compare@1.0.0: resolution: {integrity: sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==} @@ -3588,6 +4312,11 @@ packages: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true + semver@7.5.3: + resolution: {integrity: sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==} + engines: {node: '>=10'} + hasBin: true + semver@7.7.4: resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==} engines: {node: '>=10'} @@ -3655,6 +4384,9 @@ packages: resolution: {integrity: sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==} engines: {node: '>=10'} + sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + slice-ansi@3.0.0: resolution: {integrity: sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==} engines: {node: '>=8'} @@ -3682,12 +4414,25 @@ packages: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} + source-map@0.7.3: + resolution: {integrity: sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==} + engines: {node: '>= 8'} + + source-map@0.8.0-beta.0: + resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==} + engines: {node: '>= 8'} + deprecated: The work that was done in this beta branch won't be included in future versions + space-separated-tokens@2.0.2: resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} sprintf-js@1.1.3: resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} + ssf@0.11.2: + resolution: {integrity: sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==} + engines: {node: '>=0.8'} + ssri@9.0.1: resolution: {integrity: sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} @@ -3695,6 +4440,9 @@ packages: stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + stackframe@1.3.4: + resolution: {integrity: sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==} + stat-mode@1.0.0: resolution: {integrity: sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==} engines: {node: '>= 6'} @@ -3731,6 +4479,10 @@ packages: resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==} engines: {node: '>=12'} + strip-final-newline@2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + strip-indent@3.0.0: resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} engines: {node: '>=8'} @@ -3739,6 +4491,12 @@ packages: resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} engines: {node: '>=0.10.0'} + style-loader@4.0.0: + resolution: {integrity: sha512-1V4WqhhZZgjVAVJyt7TdDPZoPBPNHbekX4fWnCJL1yQukhCeZhJySUL+gL9y6sNdN95uEOS83Y55SqHcP7MzLA==} + engines: {node: '>= 18.12.0'} + peerDependencies: + webpack: ^5.27.0 + style-to-js@1.1.21: resolution: {integrity: sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==} @@ -3753,6 +4511,10 @@ packages: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} + supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + tailwind-merge@2.6.1: resolution: {integrity: sha512-Oo6tHdpZsGpkKG88HJ8RR1rg/RdnEkQEfMoEk2x1XRI3F1AxeU+ijRXpiVUF4UbLfcxxRGw6TbUINKYdWVsQTQ==} @@ -3778,6 +4540,30 @@ packages: temp-file@3.4.0: resolution: {integrity: sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg==} + terser-webpack-plugin@5.3.17: + resolution: {integrity: sha512-YR7PtUp6GMU91BgSJmlaX/rS2lGDbAF7D+Wtq7hRO+MiljNmodYvqslzCFiYVAgW+Qoaaia/QUIP4lGXufjdZw==} + engines: {node: '>= 10.13.0'} + peerDependencies: + '@swc/core': '*' + esbuild: '*' + uglify-js: '*' + webpack: ^5.1.0 + peerDependenciesMeta: + '@swc/core': + optional: true + esbuild: + optional: true + uglify-js: + optional: true + + terser@5.46.0: + resolution: {integrity: sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==} + engines: {node: '>=10'} + hasBin: true + + tiny-invariant@1.3.3: + resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} + tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} @@ -3804,6 +4590,9 @@ packages: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} + tr46@1.0.1: + resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} + trim-lines@3.0.1: resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} @@ -4020,13 +4809,37 @@ packages: jsdom: optional: true + watchpack@2.5.1: + resolution: {integrity: sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==} + engines: {node: '>=10.13.0'} + wcwidth@1.0.1: resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + webidl-conversions@4.0.2: + resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} + + webpack-sources@3.3.4: + resolution: {integrity: sha512-7tP1PdV4vF+lYPnkMR0jMY5/la2ub5Fc/8VQrrU+lXkiM6C4TjVfGw7iKfyhnTQOsD+6Q/iKw0eFciziRgD58Q==} + engines: {node: '>=10.13.0'} + + webpack@5.105.0: + resolution: {integrity: sha512-gX/dMkRQc7QOMzgTe6KsYFM7DxeIONQSui1s0n/0xht36HvrgbxtM1xBlgx596NbpHuQU8P7QpKwrZYwUX48nw==} + engines: {node: '>=10.13.0'} + hasBin: true + peerDependencies: + webpack-cli: '*' + peerDependenciesMeta: + webpack-cli: + optional: true + whatwg-mimetype@3.0.0: resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==} engines: {node: '>=12'} + whatwg-url@7.1.0: + resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==} + which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -4040,10 +4853,18 @@ packages: wide-align@1.1.5: resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} + wmf@1.0.2: + resolution: {integrity: sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==} + engines: {node: '>=0.8'} + word-wrap@1.2.5: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} + word@0.3.0: + resolution: {integrity: sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==} + engines: {node: '>=0.8'} + wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} @@ -4055,6 +4876,18 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + ws@8.17.1: + resolution: {integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==} + 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 + ws@8.19.0: resolution: {integrity: sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==} engines: {node: '>=10.0.0'} @@ -4067,6 +4900,11 @@ packages: utf-8-validate: optional: true + xlsx@0.18.5: + resolution: {integrity: sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==} + engines: {node: '>=0.8'} + hasBin: true + xmlbuilder@15.1.1: resolution: {integrity: sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==} engines: {node: '>=8.0'} @@ -4227,6 +5065,10 @@ snapshots: '@babel/template': 7.28.6 '@babel/types': 7.29.0 + '@babel/parser@7.24.1': + dependencies: + '@babel/types': 7.29.0 + '@babel/parser@7.29.0': dependencies: '@babel/types': 7.29.0 @@ -4359,81 +5201,172 @@ snapshots: transitivePeerDependencies: - supports-color + '@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 + + '@esbuild/aix-ppc64@0.25.0': + optional: true + '@esbuild/aix-ppc64@0.25.12': optional: true + '@esbuild/android-arm64@0.25.0': + optional: true + '@esbuild/android-arm64@0.25.12': optional: true + '@esbuild/android-arm@0.25.0': + optional: true + '@esbuild/android-arm@0.25.12': optional: true + '@esbuild/android-x64@0.25.0': + optional: true + '@esbuild/android-x64@0.25.12': optional: true + '@esbuild/darwin-arm64@0.25.0': + optional: true + '@esbuild/darwin-arm64@0.25.12': optional: true + '@esbuild/darwin-x64@0.25.0': + optional: true + '@esbuild/darwin-x64@0.25.12': optional: true + '@esbuild/freebsd-arm64@0.25.0': + optional: true + '@esbuild/freebsd-arm64@0.25.12': optional: true + '@esbuild/freebsd-x64@0.25.0': + optional: true + '@esbuild/freebsd-x64@0.25.12': optional: true + '@esbuild/linux-arm64@0.25.0': + optional: true + '@esbuild/linux-arm64@0.25.12': optional: true + '@esbuild/linux-arm@0.25.0': + optional: true + '@esbuild/linux-arm@0.25.12': optional: true + '@esbuild/linux-ia32@0.25.0': + optional: true + '@esbuild/linux-ia32@0.25.12': optional: true + '@esbuild/linux-loong64@0.25.0': + optional: true + '@esbuild/linux-loong64@0.25.12': optional: true + '@esbuild/linux-mips64el@0.25.0': + optional: true + '@esbuild/linux-mips64el@0.25.12': optional: true + '@esbuild/linux-ppc64@0.25.0': + optional: true + '@esbuild/linux-ppc64@0.25.12': optional: true + '@esbuild/linux-riscv64@0.25.0': + optional: true + '@esbuild/linux-riscv64@0.25.12': optional: true + '@esbuild/linux-s390x@0.25.0': + optional: true + '@esbuild/linux-s390x@0.25.12': optional: true + '@esbuild/linux-x64@0.25.0': + optional: true + '@esbuild/linux-x64@0.25.12': optional: true + '@esbuild/netbsd-arm64@0.25.0': + optional: true + '@esbuild/netbsd-arm64@0.25.12': optional: true + '@esbuild/netbsd-x64@0.25.0': + optional: true + '@esbuild/netbsd-x64@0.25.12': optional: true + '@esbuild/openbsd-arm64@0.25.0': + optional: true + '@esbuild/openbsd-arm64@0.25.12': optional: true + '@esbuild/openbsd-x64@0.25.0': + optional: true + '@esbuild/openbsd-x64@0.25.12': optional: true '@esbuild/openharmony-arm64@0.25.12': optional: true + '@esbuild/sunos-x64@0.25.0': + optional: true + '@esbuild/sunos-x64@0.25.12': optional: true + '@esbuild/win32-arm64@0.25.0': + optional: true + '@esbuild/win32-arm64@0.25.12': optional: true + '@esbuild/win32-ia32@0.25.0': + optional: true + '@esbuild/win32-ia32@0.25.12': optional: true + '@esbuild/win32-x64@0.25.0': + optional: true + '@esbuild/win32-x64@0.25.12': optional: true @@ -4587,6 +5520,11 @@ snapshots: '@jridgewell/resolve-uri@3.1.2': {} + '@jridgewell/source-map@0.3.11': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + '@jridgewell/sourcemap-codec@1.5.5': {} '@jridgewell/trace-mapping@0.3.31': @@ -4607,6 +5545,18 @@ snapshots: transitivePeerDependencies: - supports-color + '@mediabunny/aac-encoder@1.37.0(mediabunny@1.37.0)': + dependencies: + mediabunny: 1.37.0 + + '@mediabunny/flac-encoder@1.37.0(mediabunny@1.37.0)': + dependencies: + mediabunny: 1.37.0 + + '@mediabunny/mp3-encoder@1.37.0(mediabunny@1.37.0)': + dependencies: + mediabunny: 1.37.0 + '@modelcontextprotocol/sdk@1.26.0(zod@4.3.6)': dependencies: '@hono/node-server': 1.19.9(hono@4.11.9) @@ -4629,6 +5579,38 @@ snapshots: transitivePeerDependencies: - supports-color + '@module-federation/error-codes@0.22.0': {} + + '@module-federation/runtime-core@0.22.0': + dependencies: + '@module-federation/error-codes': 0.22.0 + '@module-federation/sdk': 0.22.0 + + '@module-federation/runtime-tools@0.22.0': + dependencies: + '@module-federation/runtime': 0.22.0 + '@module-federation/webpack-bundler-runtime': 0.22.0 + + '@module-federation/runtime@0.22.0': + dependencies: + '@module-federation/error-codes': 0.22.0 + '@module-federation/runtime-core': 0.22.0 + '@module-federation/sdk': 0.22.0 + + '@module-federation/sdk@0.22.0': {} + + '@module-federation/webpack-bundler-runtime@0.22.0': + dependencies: + '@module-federation/runtime': 0.22.0 + '@module-federation/sdk': 0.22.0 + + '@napi-rs/wasm-runtime@1.0.7': + dependencies: + '@emnapi/core': 1.8.1 + '@emnapi/runtime': 1.8.1 + '@tybys/wasm-util': 0.10.1 + optional: true + '@noble/hashes@1.8.0': {} '@npmcli/fs@2.1.2': @@ -5010,16 +5992,210 @@ snapshots: '@types/react': 19.2.13 '@types/react-dom': 19.2.3(@types/react@19.2.13) - '@radix-ui/react-visually-hidden@1.2.4(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + '@radix-ui/react-visually-hidden@1.2.4(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/react-primitive': 2.1.4(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.13 + '@types/react-dom': 19.2.3(@types/react@19.2.13) + + '@radix-ui/rect@1.1.1': {} + + '@remotion/bundler@4.0.434(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@remotion/media-parser': 4.0.434 + '@remotion/studio': 4.0.434(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@remotion/studio-shared': 4.0.434(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rspack/core': 1.7.6 + '@rspack/plugin-react-refresh': 1.6.1(react-refresh@0.18.0) + css-loader: 5.2.7(webpack@5.105.0(esbuild@0.25.0)) + esbuild: 0.25.0 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + react-refresh: 0.18.0 + remotion: 4.0.434(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + source-map: 0.7.3 + style-loader: 4.0.0(webpack@5.105.0(esbuild@0.25.0)) + webpack: 5.105.0(esbuild@0.25.0) + transitivePeerDependencies: + - '@swc/core' + - '@swc/helpers' + - bufferutil + - supports-color + - uglify-js + - utf-8-validate + - webpack-cli + - webpack-hot-middleware + + '@remotion/cli@4.0.434(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@remotion/bundler': 4.0.434(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@remotion/media-utils': 4.0.434(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@remotion/player': 4.0.434(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@remotion/renderer': 4.0.434(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@remotion/studio': 4.0.434(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@remotion/studio-server': 4.0.434(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@remotion/studio-shared': 4.0.434(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + dotenv: 17.3.1 + minimist: 1.2.6 + prompts: 2.4.2 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + remotion: 4.0.434(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + transitivePeerDependencies: + - '@swc/core' + - '@swc/helpers' + - bufferutil + - supports-color + - uglify-js + - utf-8-validate + - webpack-cli + - webpack-hot-middleware + + '@remotion/compositor-darwin-arm64@4.0.434': + optional: true + + '@remotion/compositor-darwin-x64@4.0.434': + optional: true + + '@remotion/compositor-linux-arm64-gnu@4.0.434': + optional: true + + '@remotion/compositor-linux-arm64-musl@4.0.434': + optional: true + + '@remotion/compositor-linux-x64-gnu@4.0.434': + optional: true + + '@remotion/compositor-linux-x64-musl@4.0.434': + optional: true + + '@remotion/compositor-win32-x64-msvc@4.0.434': + optional: true + + '@remotion/licensing@4.0.434': {} + + '@remotion/media-parser@4.0.434': {} + + '@remotion/media-utils@4.0.434(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@remotion/media-parser': 4.0.434 + '@remotion/webcodecs': 4.0.434 + mediabunny: 1.37.0 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + remotion: 4.0.434(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + + '@remotion/player@4.0.434(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + remotion: 4.0.434(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + + '@remotion/renderer@4.0.434(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@remotion/licensing': 4.0.434 + '@remotion/streaming': 4.0.434 + execa: 5.1.1 + extract-zip: 2.0.1 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + remotion: 4.0.434(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + source-map: 0.8.0-beta.0 + ws: 8.17.1 + optionalDependencies: + '@remotion/compositor-darwin-arm64': 4.0.434 + '@remotion/compositor-darwin-x64': 4.0.434 + '@remotion/compositor-linux-arm64-gnu': 4.0.434 + '@remotion/compositor-linux-arm64-musl': 4.0.434 + '@remotion/compositor-linux-x64-gnu': 4.0.434 + '@remotion/compositor-linux-x64-musl': 4.0.434 + '@remotion/compositor-win32-x64-msvc': 4.0.434 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + '@remotion/streaming@4.0.434': {} + + '@remotion/studio-server@4.0.434(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@babel/parser': 7.24.1 + '@remotion/bundler': 4.0.434(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@remotion/renderer': 4.0.434(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@remotion/studio-shared': 4.0.434(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + memfs: 3.4.3 + open: 8.4.2 + prettier: 3.8.1 + recast: 0.23.11 + remotion: 4.0.434(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + semver: 7.5.3 + source-map: 0.7.3 + transitivePeerDependencies: + - '@swc/core' + - '@swc/helpers' + - bufferutil + - react + - react-dom + - supports-color + - uglify-js + - utf-8-validate + - webpack-cli + - webpack-hot-middleware + + '@remotion/studio-shared@4.0.434(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + remotion: 4.0.434(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + transitivePeerDependencies: + - react + - react-dom + + '@remotion/studio@4.0.434(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@remotion/media-utils': 4.0.434(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@remotion/player': 4.0.434(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@remotion/renderer': 4.0.434(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@remotion/studio-shared': 4.0.434(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@remotion/web-renderer': 4.0.434(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@remotion/zod-types': 4.0.434(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(zod@4.3.6) + mediabunny: 1.37.0 + memfs: 3.4.3 + open: 8.4.2 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + remotion: 4.0.434(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + semver: 7.5.3 + source-map: 0.7.3 + zod: 4.3.6 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + '@remotion/web-renderer@4.0.434(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: - '@radix-ui/react-primitive': 2.1.4(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@mediabunny/aac-encoder': 1.37.0(mediabunny@1.37.0) + '@mediabunny/flac-encoder': 1.37.0(mediabunny@1.37.0) + '@mediabunny/mp3-encoder': 1.37.0(mediabunny@1.37.0) + '@remotion/licensing': 4.0.434 + mediabunny: 1.37.0 react: 19.2.4 react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.13 - '@types/react-dom': 19.2.3(@types/react@19.2.13) + remotion: 4.0.434(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/rect@1.1.1': {} + '@remotion/webcodecs@4.0.434': + dependencies: + '@remotion/media-parser': 4.0.434 + + '@remotion/zod-types@4.0.434(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(zod@4.3.6)': + dependencies: + remotion: 4.0.434(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + zod: 4.3.6 + transitivePeerDependencies: + - react + - react-dom '@rolldown/pluginutils@1.0.0-beta.27': {} @@ -5098,6 +6274,65 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.57.1': optional: true + '@rspack/binding-darwin-arm64@1.7.6': + optional: true + + '@rspack/binding-darwin-x64@1.7.6': + optional: true + + '@rspack/binding-linux-arm64-gnu@1.7.6': + optional: true + + '@rspack/binding-linux-arm64-musl@1.7.6': + optional: true + + '@rspack/binding-linux-x64-gnu@1.7.6': + optional: true + + '@rspack/binding-linux-x64-musl@1.7.6': + optional: true + + '@rspack/binding-wasm32-wasi@1.7.6': + dependencies: + '@napi-rs/wasm-runtime': 1.0.7 + optional: true + + '@rspack/binding-win32-arm64-msvc@1.7.6': + optional: true + + '@rspack/binding-win32-ia32-msvc@1.7.6': + optional: true + + '@rspack/binding-win32-x64-msvc@1.7.6': + optional: true + + '@rspack/binding@1.7.6': + optionalDependencies: + '@rspack/binding-darwin-arm64': 1.7.6 + '@rspack/binding-darwin-x64': 1.7.6 + '@rspack/binding-linux-arm64-gnu': 1.7.6 + '@rspack/binding-linux-arm64-musl': 1.7.6 + '@rspack/binding-linux-x64-gnu': 1.7.6 + '@rspack/binding-linux-x64-musl': 1.7.6 + '@rspack/binding-wasm32-wasi': 1.7.6 + '@rspack/binding-win32-arm64-msvc': 1.7.6 + '@rspack/binding-win32-ia32-msvc': 1.7.6 + '@rspack/binding-win32-x64-msvc': 1.7.6 + + '@rspack/core@1.7.6': + dependencies: + '@module-federation/runtime-tools': 0.22.0 + '@rspack/binding': 1.7.6 + '@rspack/lite-tapable': 1.1.0 + + '@rspack/lite-tapable@1.1.0': {} + + '@rspack/plugin-react-refresh@1.6.1(react-refresh@0.18.0)': + dependencies: + error-stack-parser: 2.1.4 + html-entities: 2.6.0 + react-refresh: 0.18.0 + '@sindresorhus/is@4.6.0': {} '@standard-schema/spec@1.1.0': {} @@ -5205,12 +6440,12 @@ snapshots: '@tailwindcss/oxide-win32-arm64-msvc': 4.1.18 '@tailwindcss/oxide-win32-x64-msvc': 4.1.18 - '@tailwindcss/vite@4.1.18(vite@6.4.1(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2))': + '@tailwindcss/vite@4.1.18(vite@6.4.1(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.46.0))': dependencies: '@tailwindcss/node': 4.1.18 '@tailwindcss/oxide': 4.1.18 tailwindcss: 4.1.18 - vite: 6.4.1(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2) + vite: 6.4.1(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.46.0) '@tanstack/react-virtual@3.13.19(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: @@ -5252,6 +6487,11 @@ snapshots: '@tootallnate/once@2.0.0': {} + '@tybys/wasm-util@0.10.1': + dependencies: + tslib: 2.8.1 + optional: true + '@types/aria-query@5.0.4': {} '@types/babel__core@7.20.5': @@ -5297,6 +6537,22 @@ snapshots: '@types/deep-eql@4.0.2': {} + '@types/dom-mediacapture-transform@0.1.11': + dependencies: + '@types/dom-webcodecs': 0.1.13 + + '@types/dom-webcodecs@0.1.13': {} + + '@types/eslint-scope@3.7.7': + dependencies: + '@types/eslint': 9.6.1 + '@types/estree': 1.0.8 + + '@types/eslint@9.6.1': + dependencies: + '@types/estree': 1.0.8 + '@types/json-schema': 7.0.15 + '@types/esrecurse@4.3.1': {} '@types/estree-jsx@1.0.5': @@ -5341,6 +6597,10 @@ snapshots: dependencies: undici-types: 7.16.0 + '@types/papaparse@5.5.2': + dependencies: + '@types/node': 25.2.3 + '@types/phoenix@1.6.7': {} '@types/plist@3.0.5': @@ -5472,7 +6732,7 @@ snapshots: '@ungap/structured-clone@1.3.0': {} - '@vitejs/plugin-react@4.7.0(vite@6.4.1(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2))': + '@vitejs/plugin-react@4.7.0(vite@6.4.1(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.46.0))': dependencies: '@babel/core': 7.29.0 '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.0) @@ -5480,7 +6740,7 @@ snapshots: '@rolldown/pluginutils': 1.0.0-beta.27 '@types/babel__core': 7.20.5 react-refresh: 0.17.0 - vite: 6.4.1(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2) + vite: 6.4.1(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.46.0) transitivePeerDependencies: - supports-color @@ -5493,13 +6753,13 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.0.3 - '@vitest/mocker@4.0.18(vite@6.4.1(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2))': + '@vitest/mocker@4.0.18(vite@6.4.1(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.46.0))': dependencies: '@vitest/spy': 4.0.18 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 6.4.1(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2) + vite: 6.4.1(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.46.0) '@vitest/pretty-format@4.0.18': dependencies: @@ -5523,8 +6783,88 @@ snapshots: '@vitest/pretty-format': 4.0.18 tinyrainbow: 3.0.3 + '@webassemblyjs/ast@1.14.1': + dependencies: + '@webassemblyjs/helper-numbers': 1.13.2 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + + '@webassemblyjs/floating-point-hex-parser@1.13.2': {} + + '@webassemblyjs/helper-api-error@1.13.2': {} + + '@webassemblyjs/helper-buffer@1.14.1': {} + + '@webassemblyjs/helper-numbers@1.13.2': + dependencies: + '@webassemblyjs/floating-point-hex-parser': 1.13.2 + '@webassemblyjs/helper-api-error': 1.13.2 + '@xtuc/long': 4.2.2 + + '@webassemblyjs/helper-wasm-bytecode@1.13.2': {} + + '@webassemblyjs/helper-wasm-section@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-buffer': 1.14.1 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + '@webassemblyjs/wasm-gen': 1.14.1 + + '@webassemblyjs/ieee754@1.13.2': + dependencies: + '@xtuc/ieee754': 1.2.0 + + '@webassemblyjs/leb128@1.13.2': + dependencies: + '@xtuc/long': 4.2.2 + + '@webassemblyjs/utf8@1.13.2': {} + + '@webassemblyjs/wasm-edit@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-buffer': 1.14.1 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + '@webassemblyjs/helper-wasm-section': 1.14.1 + '@webassemblyjs/wasm-gen': 1.14.1 + '@webassemblyjs/wasm-opt': 1.14.1 + '@webassemblyjs/wasm-parser': 1.14.1 + '@webassemblyjs/wast-printer': 1.14.1 + + '@webassemblyjs/wasm-gen@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + '@webassemblyjs/ieee754': 1.13.2 + '@webassemblyjs/leb128': 1.13.2 + '@webassemblyjs/utf8': 1.13.2 + + '@webassemblyjs/wasm-opt@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-buffer': 1.14.1 + '@webassemblyjs/wasm-gen': 1.14.1 + '@webassemblyjs/wasm-parser': 1.14.1 + + '@webassemblyjs/wasm-parser@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-api-error': 1.13.2 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + '@webassemblyjs/ieee754': 1.13.2 + '@webassemblyjs/leb128': 1.13.2 + '@webassemblyjs/utf8': 1.13.2 + + '@webassemblyjs/wast-printer@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@xtuc/long': 4.2.2 + '@xmldom/xmldom@0.8.11': {} + '@xtuc/ieee754@1.2.0': {} + + '@xtuc/long@4.2.2': {} + '@zed-industries/claude-code-acp@0.16.1(zod@4.3.6)': dependencies: '@agentclientprotocol/sdk': 0.14.1(zod@4.3.6) @@ -5571,12 +6911,18 @@ snapshots: mime-types: 3.0.2 negotiator: 1.0.0 + acorn-import-phases@1.0.4(acorn@8.16.0): + dependencies: + acorn: 8.16.0 + acorn-jsx@5.3.2(acorn@8.16.0): dependencies: acorn: 8.16.0 acorn@8.16.0: {} + adler-32@1.3.1: {} + agent-base@6.0.2: dependencies: debug: 4.4.3 @@ -5594,6 +6940,10 @@ snapshots: clean-stack: 2.2.0 indent-string: 4.0.0 + ajv-formats@2.1.1(ajv@8.17.1): + optionalDependencies: + ajv: 8.17.1 + ajv-formats@3.0.1(ajv@8.17.1): optionalDependencies: ajv: 8.17.1 @@ -5602,6 +6952,11 @@ snapshots: dependencies: ajv: 6.12.6 + ajv-keywords@5.1.0(ajv@8.17.1): + dependencies: + ajv: 8.17.1 + fast-deep-equal: 3.1.3 + ajv@6.12.6: dependencies: fast-deep-equal: 3.1.3 @@ -5730,6 +7085,10 @@ snapshots: assertion-error@2.0.1: {} + ast-types@0.16.1: + dependencies: + tslib: 2.8.1 + astral-regex@2.0.0: optional: true @@ -5756,6 +7115,8 @@ snapshots: bindings: 1.5.0 prebuild-install: 7.1.3 + big.js@5.2.2: {} + bindings@1.5.0: dependencies: file-uri-to-path: 1.0.0 @@ -5900,6 +7261,11 @@ snapshots: ccount@2.0.1: {} + cfb@1.2.2: + dependencies: + adler-32: 1.3.1 + crc-32: 1.2.2 + chai@6.2.2: {} chalk@4.1.2: @@ -5919,6 +7285,8 @@ snapshots: chownr@2.0.0: {} + chrome-trace-event@1.0.4: {} + chromium-pickle-js@0.2.0: {} ci-info@3.9.0: {} @@ -5955,6 +7323,8 @@ snapshots: clsx@2.1.1: {} + codepage@1.15.0: {} + color-convert@2.0.1: dependencies: color-name: 1.1.4 @@ -5969,6 +7339,8 @@ snapshots: comma-separated-tokens@2.0.3: {} + commander@2.20.3: {} + commander@5.1.0: {} compare-version@0.1.2: {} @@ -6031,8 +7403,24 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 + css-loader@5.2.7(webpack@5.105.0(esbuild@0.25.0)): + dependencies: + icss-utils: 5.1.0(postcss@8.5.6) + loader-utils: 2.0.4 + postcss: 8.5.6 + postcss-modules-extract-imports: 3.1.0(postcss@8.5.6) + postcss-modules-local-by-default: 4.2.0(postcss@8.5.6) + postcss-modules-scope: 3.2.1(postcss@8.5.6) + postcss-modules-values: 4.0.0(postcss@8.5.6) + postcss-value-parser: 4.2.0 + schema-utils: 3.3.0 + semver: 7.7.4 + webpack: 5.105.0(esbuild@0.25.0) + css.escape@1.5.1: {} + cssesc@3.0.0: {} + csstype@3.2.3: {} debug@4.4.3: @@ -6064,6 +7452,8 @@ snapshots: gopd: 1.2.0 optional: true + define-lazy-prop@2.0.0: {} + define-properties@1.2.1: dependencies: define-data-property: 1.1.4 @@ -6134,6 +7524,8 @@ snapshots: dotenv@16.6.1: {} + dotenv@17.3.1: {} + dunder-proto@1.0.1: dependencies: call-bind-apply-helpers: 1.0.2 @@ -6190,7 +7582,7 @@ snapshots: electron-to-chromium@1.5.286: {} - electron-vite@3.1.0(vite@6.4.1(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2)): + electron-vite@3.1.0(vite@6.4.1(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.46.0)): dependencies: '@babel/core': 7.29.0 '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.29.0) @@ -6198,7 +7590,7 @@ snapshots: esbuild: 0.25.12 magic-string: 0.30.21 picocolors: 1.1.1 - vite: 6.4.1(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2) + vite: 6.4.1(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.46.0) transitivePeerDependencies: - supports-color @@ -6214,6 +7606,8 @@ snapshots: emoji-regex@9.2.2: {} + emojis-list@3.0.0: {} + encodeurl@2.0.0: {} encoding@0.1.13: @@ -6236,12 +7630,18 @@ snapshots: err-code@2.0.3: {} + error-stack-parser@2.1.4: + dependencies: + stackframe: 1.3.4 + es-define-property@1.0.1: {} es-errors@1.3.0: {} es-module-lexer@1.7.0: {} + es-module-lexer@2.0.0: {} + es-object-atoms@1.1.1: dependencies: es-errors: 1.3.0 @@ -6256,6 +7656,34 @@ snapshots: es6-error@4.1.1: optional: true + esbuild@0.25.0: + optionalDependencies: + '@esbuild/aix-ppc64': 0.25.0 + '@esbuild/android-arm': 0.25.0 + '@esbuild/android-arm64': 0.25.0 + '@esbuild/android-x64': 0.25.0 + '@esbuild/darwin-arm64': 0.25.0 + '@esbuild/darwin-x64': 0.25.0 + '@esbuild/freebsd-arm64': 0.25.0 + '@esbuild/freebsd-x64': 0.25.0 + '@esbuild/linux-arm': 0.25.0 + '@esbuild/linux-arm64': 0.25.0 + '@esbuild/linux-ia32': 0.25.0 + '@esbuild/linux-loong64': 0.25.0 + '@esbuild/linux-mips64el': 0.25.0 + '@esbuild/linux-ppc64': 0.25.0 + '@esbuild/linux-riscv64': 0.25.0 + '@esbuild/linux-s390x': 0.25.0 + '@esbuild/linux-x64': 0.25.0 + '@esbuild/netbsd-arm64': 0.25.0 + '@esbuild/netbsd-x64': 0.25.0 + '@esbuild/openbsd-arm64': 0.25.0 + '@esbuild/openbsd-x64': 0.25.0 + '@esbuild/sunos-x64': 0.25.0 + '@esbuild/win32-arm64': 0.25.0 + '@esbuild/win32-ia32': 0.25.0 + '@esbuild/win32-x64': 0.25.0 + esbuild@0.25.12: optionalDependencies: '@esbuild/aix-ppc64': 0.25.12 @@ -6293,6 +7721,11 @@ snapshots: escape-string-regexp@5.0.0: {} + eslint-scope@5.1.1: + dependencies: + esrecurse: 4.3.0 + estraverse: 4.3.0 + eslint-scope@9.1.1: dependencies: '@types/esrecurse': 4.3.1 @@ -6347,6 +7780,8 @@ snapshots: acorn-jsx: 5.3.2(acorn@8.16.0) eslint-visitor-keys: 5.0.1 + esprima@4.0.1: {} + esquery@1.7.0: dependencies: estraverse: 5.3.0 @@ -6355,6 +7790,8 @@ snapshots: dependencies: estraverse: 5.3.0 + estraverse@4.3.0: {} + estraverse@5.3.0: {} estree-util-is-identifier-name@3.0.0: {} @@ -6367,12 +7804,26 @@ snapshots: etag@1.8.1: {} + events@3.3.0: {} + eventsource-parser@3.0.6: {} eventsource@3.0.7: dependencies: eventsource-parser: 3.0.6 + execa@5.1.1: + dependencies: + cross-spawn: 7.0.6 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + expand-template@2.0.3: {} expect-type@1.3.0: {} @@ -6496,6 +7947,8 @@ snapshots: forwarded@0.2.0: {} + frac@1.1.2: {} + fresh@2.0.0: {} fs-constants@1.0.0: {} @@ -6529,6 +7982,8 @@ snapshots: dependencies: minipass: 3.3.6 + fs-monkey@1.0.3: {} + fs.realpath@1.0.0: {} fsevents@2.3.3: @@ -6575,12 +8030,16 @@ snapshots: dependencies: pump: 3.0.3 + get-stream@6.0.1: {} + github-from-package@0.0.0: {} glob-parent@6.0.2: dependencies: is-glob: 4.0.3 + glob-to-regexp@0.4.1: {} + glob@10.5.0: dependencies: foreground-child: 3.3.1 @@ -6702,6 +8161,8 @@ snapshots: dependencies: lru-cache: 6.0.0 + html-entities@2.6.0: {} + html-url-attributes@3.0.1: {} http-cache-semantics@4.2.0: {} @@ -6748,12 +8209,16 @@ snapshots: transitivePeerDependencies: - supports-color + human-signals@2.1.0: {} + humanize-ms@1.2.1: dependencies: ms: 2.1.3 husky@9.1.7: {} + hyparquet@1.25.1: {} + iceberg-js@0.8.1: {} iconv-corefoundation@1.1.7: @@ -6770,6 +8235,10 @@ snapshots: dependencies: safer-buffer: 2.1.2 + icss-utils@5.1.0(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + ieee754@1.2.1: {} ignore@5.3.2: {} @@ -6812,6 +8281,8 @@ snapshots: is-decimal@2.0.1: {} + is-docker@2.2.1: {} + is-extglob@2.1.1: {} is-fullwidth-code-point@3.0.0: {} @@ -6830,8 +8301,14 @@ snapshots: is-promise@4.0.0: {} + is-stream@2.0.1: {} + is-unicode-supported@0.1.0: {} + is-wsl@2.2.0: + dependencies: + is-docker: 2.2.1 + isarray@1.0.0: {} isbinaryfile@4.0.10: {} @@ -6852,6 +8329,12 @@ snapshots: filelist: 1.0.4 picocolors: 1.1.1 + jest-worker@27.5.1: + dependencies: + '@types/node': 25.2.3 + merge-stream: 2.0.0 + supports-color: 8.1.1 + jiti@2.6.1: {} jose@6.1.3: {} @@ -6866,6 +8349,8 @@ snapshots: json-buffer@3.0.1: {} + json-parse-even-better-errors@2.3.1: {} + json-schema-traverse@0.4.1: {} json-schema-traverse@1.0.0: {} @@ -6893,6 +8378,8 @@ snapshots: dependencies: json-buffer: 3.0.1 + kleur@3.0.3: {} + lazy-val@1.0.5: {} lazystream@1.0.1: @@ -6953,6 +8440,14 @@ snapshots: lightningcss-win32-arm64-msvc: 1.30.2 lightningcss-win32-x64-msvc: 1.30.2 + loader-runner@4.3.1: {} + + loader-utils@2.0.4: + dependencies: + big.js: 5.2.2 + emojis-list: 3.0.0 + json5: 2.2.3 + locate-path@6.0.0: dependencies: p-locate: 5.0.0 @@ -6965,6 +8460,8 @@ snapshots: lodash.isplainobject@4.0.6: {} + lodash.sortby@4.7.0: {} + lodash.union@4.6.0: {} lodash@4.17.23: {} @@ -7188,8 +8685,19 @@ snapshots: media-typer@1.1.0: {} + mediabunny@1.37.0: + dependencies: + '@types/dom-mediacapture-transform': 0.1.11 + '@types/dom-webcodecs': 0.1.13 + + memfs@3.4.3: + dependencies: + fs-monkey: 1.0.3 + merge-descriptors@2.0.0: {} + merge-stream@2.0.0: {} + micromark-core-commonmark@2.0.3: dependencies: decode-named-character-reference: 1.3.0 @@ -7423,6 +8931,8 @@ snapshots: dependencies: brace-expansion: 2.0.2 + minimist@1.2.6: {} + minimist@1.2.8: {} minipass-collect@1.0.2: @@ -7478,6 +8988,8 @@ snapshots: negotiator@1.0.0: {} + neo-async@2.6.2: {} + node-abi@3.87.0: dependencies: semver: 7.7.4 @@ -7516,6 +9028,10 @@ snapshots: normalize-url@6.1.0: {} + npm-run-path@4.0.1: + dependencies: + path-key: 3.1.1 + npmlog@6.0.2: dependencies: are-we-there-yet: 3.0.1 @@ -7544,6 +9060,12 @@ snapshots: dependencies: mimic-fn: 2.1.0 + open@8.4.2: + dependencies: + define-lazy-prop: 2.0.0 + is-docker: 2.2.1 + is-wsl: 2.2.0 + optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -7581,6 +9103,8 @@ snapshots: package-json-from-dist@1.0.1: {} + papaparse@5.5.3: {} + parse-entities@4.0.2: dependencies: '@types/unist': 2.0.11 @@ -7624,6 +9148,34 @@ snapshots: base64-js: 1.5.1 xmlbuilder: 15.1.1 + postcss-modules-extract-imports@3.1.0(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + + postcss-modules-local-by-default@4.2.0(postcss@8.5.6): + dependencies: + icss-utils: 5.1.0(postcss@8.5.6) + postcss: 8.5.6 + postcss-selector-parser: 7.1.1 + postcss-value-parser: 4.2.0 + + postcss-modules-scope@3.2.1(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + postcss-selector-parser: 7.1.1 + + postcss-modules-values@4.0.0(postcss@8.5.6): + dependencies: + icss-utils: 5.1.0(postcss@8.5.6) + postcss: 8.5.6 + + postcss-selector-parser@7.1.1: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss-value-parser@4.2.0: {} + postcss@8.5.6: dependencies: nanoid: 3.3.11 @@ -7647,6 +9199,8 @@ snapshots: prelude-ls@1.2.1: {} + prettier@3.8.1: {} + pretty-format@27.5.1: dependencies: ansi-regex: 5.0.1 @@ -7664,6 +9218,11 @@ snapshots: err-code: 2.0.3 retry: 0.12.0 + prompts@2.4.2: + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + property-information@7.1.0: {} proxy-addr@2.0.7: @@ -7727,6 +9286,8 @@ snapshots: react-refresh@0.17.0: {} + react-refresh@0.18.0: {} + react-remove-scroll-bar@2.3.8(@types/react@19.2.13)(react@19.2.4): dependencies: react: 19.2.4 @@ -7782,6 +9343,14 @@ snapshots: dependencies: minimatch: 5.1.6 + recast@0.23.11: + dependencies: + ast-types: 0.16.1 + esprima: 4.0.1 + source-map: 0.6.1 + tiny-invariant: 1.3.3 + tslib: 2.8.1 + redent@3.0.0: dependencies: indent-string: 4.0.0 @@ -7821,6 +9390,11 @@ snapshots: mdast-util-to-markdown: 2.1.2 unified: 11.0.5 + remotion@4.0.434(react-dom@19.2.4(react@19.2.4))(react@19.2.4): + dependencies: + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + require-directory@2.1.1: {} require-from-string@2.0.2: {} @@ -7911,11 +9485,28 @@ snapshots: scheduler@0.27.0: {} + schema-utils@3.3.0: + dependencies: + '@types/json-schema': 7.0.15 + ajv: 6.12.6 + ajv-keywords: 3.5.2(ajv@6.12.6) + + schema-utils@4.3.3: + dependencies: + '@types/json-schema': 7.0.15 + ajv: 8.17.1 + ajv-formats: 2.1.1(ajv@8.17.1) + ajv-keywords: 5.1.0(ajv@8.17.1) + semver-compare@1.0.0: optional: true semver@6.3.1: {} + semver@7.5.3: + dependencies: + lru-cache: 6.0.0 + semver@7.7.4: {} send@1.2.1: @@ -8004,6 +9595,8 @@ snapshots: dependencies: semver: 7.7.4 + sisteransi@1.0.5: {} + slice-ansi@3.0.0: dependencies: ansi-styles: 4.3.0 @@ -8035,17 +9628,29 @@ snapshots: source-map@0.6.1: {} + source-map@0.7.3: {} + + source-map@0.8.0-beta.0: + dependencies: + whatwg-url: 7.1.0 + space-separated-tokens@2.0.2: {} sprintf-js@1.1.3: optional: true + ssf@0.11.2: + dependencies: + frac: 1.1.2 + ssri@9.0.1: dependencies: minipass: 3.3.6 stackback@0.0.2: {} + stackframe@1.3.4: {} + stat-mode@1.0.0: {} statuses@2.0.2: {} @@ -8085,12 +9690,18 @@ snapshots: dependencies: ansi-regex: 6.2.2 + strip-final-newline@2.0.0: {} + strip-indent@3.0.0: dependencies: min-indent: 1.0.1 strip-json-comments@2.0.1: {} + style-loader@4.0.0(webpack@5.105.0(esbuild@0.25.0)): + dependencies: + webpack: 5.105.0(esbuild@0.25.0) + style-to-js@1.1.21: dependencies: style-to-object: 1.0.14 @@ -8109,6 +9720,10 @@ snapshots: dependencies: has-flag: 4.0.0 + supports-color@8.1.1: + dependencies: + has-flag: 4.0.0 + tailwind-merge@2.6.1: {} tailwindcss@4.1.18: {} @@ -8144,6 +9759,25 @@ snapshots: async-exit-hook: 2.0.1 fs-extra: 10.1.0 + terser-webpack-plugin@5.3.17(esbuild@0.25.0)(webpack@5.105.0): + dependencies: + '@jridgewell/trace-mapping': 0.3.31 + jest-worker: 27.5.1 + schema-utils: 4.3.3 + terser: 5.46.0 + webpack: 5.105.0(esbuild@0.25.0) + optionalDependencies: + esbuild: 0.25.0 + + terser@5.46.0: + dependencies: + '@jridgewell/source-map': 0.3.11 + acorn: 8.16.0 + commander: 2.20.3 + source-map-support: 0.5.21 + + tiny-invariant@1.3.3: {} + tinybench@2.9.0: {} tinyexec@1.0.2: {} @@ -8163,6 +9797,10 @@ snapshots: toidentifier@1.0.1: {} + tr46@1.0.1: + dependencies: + punycode: 2.3.1 + trim-lines@3.0.1: {} trough@2.2.0: {} @@ -8308,7 +9946,7 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.3 - vite@6.4.1(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2): + vite@6.4.1(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.46.0): dependencies: esbuild: 0.25.12 fdir: 6.5.0(picomatch@4.0.3) @@ -8321,11 +9959,12 @@ snapshots: fsevents: 2.3.3 jiti: 2.6.1 lightningcss: 1.30.2 + terser: 5.46.0 - vitest@4.0.18(@types/node@25.2.3)(happy-dom@20.5.0)(jiti@2.6.1)(lightningcss@1.30.2): + vitest@4.0.18(@types/node@25.2.3)(happy-dom@20.5.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.46.0): dependencies: '@vitest/expect': 4.0.18 - '@vitest/mocker': 4.0.18(vite@6.4.1(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2)) + '@vitest/mocker': 4.0.18(vite@6.4.1(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.46.0)) '@vitest/pretty-format': 4.0.18 '@vitest/runner': 4.0.18 '@vitest/snapshot': 4.0.18 @@ -8342,7 +9981,7 @@ snapshots: tinyexec: 1.0.2 tinyglobby: 0.2.15 tinyrainbow: 3.0.3 - vite: 6.4.1(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2) + vite: 6.4.1(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.46.0) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 25.2.3 @@ -8360,12 +9999,59 @@ snapshots: - tsx - yaml + watchpack@2.5.1: + dependencies: + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + wcwidth@1.0.1: dependencies: defaults: 1.0.4 + webidl-conversions@4.0.2: {} + + webpack-sources@3.3.4: {} + + webpack@5.105.0(esbuild@0.25.0): + dependencies: + '@types/eslint-scope': 3.7.7 + '@types/estree': 1.0.8 + '@types/json-schema': 7.0.15 + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/wasm-edit': 1.14.1 + '@webassemblyjs/wasm-parser': 1.14.1 + acorn: 8.16.0 + acorn-import-phases: 1.0.4(acorn@8.16.0) + browserslist: 4.28.1 + chrome-trace-event: 1.0.4 + enhanced-resolve: 5.19.0 + es-module-lexer: 2.0.0 + eslint-scope: 5.1.1 + events: 3.3.0 + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + json-parse-even-better-errors: 2.3.1 + loader-runner: 4.3.1 + mime-types: 2.1.35 + neo-async: 2.6.2 + schema-utils: 4.3.3 + tapable: 2.3.0 + terser-webpack-plugin: 5.3.17(esbuild@0.25.0)(webpack@5.105.0) + watchpack: 2.5.1 + webpack-sources: 3.3.4 + transitivePeerDependencies: + - '@swc/core' + - esbuild + - uglify-js + whatwg-mimetype@3.0.0: {} + whatwg-url@7.1.0: + dependencies: + lodash.sortby: 4.7.0 + tr46: 1.0.1 + webidl-conversions: 4.0.2 + which@2.0.2: dependencies: isexe: 2.0.0 @@ -8379,8 +10065,12 @@ snapshots: dependencies: string-width: 4.2.3 + wmf@1.0.2: {} + word-wrap@1.2.5: {} + word@0.3.0: {} + wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0 @@ -8395,8 +10085,20 @@ snapshots: wrappy@1.0.2: {} + ws@8.17.1: {} + ws@8.19.0: {} + xlsx@0.18.5: + dependencies: + adler-32: 1.3.1 + cfb: 1.2.2 + codepage: 1.15.0 + crc-32: 1.2.2 + ssf: 0.11.2 + wmf: 1.0.2 + word: 0.3.0 + xmlbuilder@15.1.1: {} y18n@5.0.8: {} diff --git a/scripts/remotion/DataFilePreviewScreenshot.tsx b/scripts/remotion/DataFilePreviewScreenshot.tsx new file mode 100644 index 00000000..6a561576 --- /dev/null +++ b/scripts/remotion/DataFilePreviewScreenshot.tsx @@ -0,0 +1,206 @@ +import React from 'react' +import { AbsoluteFill } from 'remotion' + +// Sample data to showcase the DataFilePreview component +const sampleColumns = ['name', 'email', 'department', 'salary', 'start_date', 'status'] +const sampleRows = [ + { name: 'Alice Chen', email: 'alice@acme.co', department: 'Engineering', salary: 145000, start_date: '2023-01-15', status: 'Active' }, + { name: 'Bob Martinez', email: 'bob@acme.co', department: 'Marketing', salary: 98000, start_date: '2022-06-20', status: 'Active' }, + { name: 'Carol Patel', email: 'carol@acme.co', department: 'Engineering', salary: 152000, start_date: '2021-11-03', status: 'Active' }, + { name: 'David Kim', email: 'david@acme.co', department: 'Sales', salary: 115000, start_date: '2023-03-08', status: 'On Leave' }, + { name: 'Eva Johnson', email: 'eva@acme.co', department: 'Engineering', salary: 138000, start_date: '2022-09-14', status: 'Active' }, + { name: 'Frank Liu', email: 'frank@acme.co', department: 'Design', salary: 105000, start_date: '2024-01-22', status: 'Active' }, + { name: 'Grace Wilson', email: 'grace@acme.co', department: 'Engineering', salary: 160000, start_date: '2020-04-10', status: 'Active' }, + { name: 'Henry Brown', email: 'henry@acme.co', department: 'Marketing', salary: 92000, start_date: '2023-07-01', status: 'Active' }, +] + +// Simulated chat message context +function ToolCallHeader() { + return ( +
+ + + + Read + — employees.csv + + + + +
+ ) +} + +function DataTable() { + return ( +
+ {/* Table Header Bar */} +
+
+ + + + + + + + employees.csv + 1,247 rows · 6 cols +
+
+ + + + + + +
+
+ + {/* Table */} + + + + + {sampleColumns.map((col) => ( + + ))} + + + + {sampleRows.map((row, i) => ( + + + + + + + + + + ))} + +
# + + {col} + + + + +
{i + 1}{row.name}{row.email}{row.department}{row.salary.toLocaleString()}{row.start_date}{row.status}
+ + {/* Footer */} +
+ Showing 8 of 1,247 rows (truncated) + View full table → +
+
+ ) +} + +export const DataFilePreviewScreenshot: React.FC = () => { + return ( + + {/* Title */} +
+ + + + + + + + Data File Viewer + + inline preview + +
+ + {/* Chat context - tool call message */} +
+ + + {/* Embedded Data Preview */} +
+ +
+ + {/* Timestamp */} +
+ 2:34:12 PM + 1.2s · in:450 out:120 +
+
+ + {/* Feature callouts */} +
+ {[ + { label: 'Sort columns', desc: 'Click headers to sort' }, + { label: 'Fullscreen', desc: 'Expand for deep analysis' }, + { label: 'Auto-detect', desc: 'CSV, JSON, Excel, TSV' }, + { label: 'Filter rows', desc: 'Search across all columns' }, + ].map((feat) => ( +
+
{feat.label}
+
{feat.desc}
+
+ ))} +
+
+ ) +} diff --git a/scripts/remotion/Root.tsx b/scripts/remotion/Root.tsx new file mode 100644 index 00000000..2fafdda0 --- /dev/null +++ b/scripts/remotion/Root.tsx @@ -0,0 +1,18 @@ +import React from 'react' +import { Composition } from 'remotion' +import { DataFilePreviewScreenshot } from './DataFilePreviewScreenshot' + +export const RemotionRoot: React.FC = () => { + return ( + <> + + + ) +} diff --git a/scripts/remotion/index.ts b/scripts/remotion/index.ts new file mode 100644 index 00000000..3e5b3f9a --- /dev/null +++ b/scripts/remotion/index.ts @@ -0,0 +1,4 @@ +import { registerRoot } from 'remotion' +import { RemotionRoot } from './Root' + +registerRoot(RemotionRoot) diff --git a/scripts/remotion/render-screenshot.mjs b/scripts/remotion/render-screenshot.mjs new file mode 100644 index 00000000..abdfb573 --- /dev/null +++ b/scripts/remotion/render-screenshot.mjs @@ -0,0 +1,41 @@ +#!/usr/bin/env node +import { bundle } from '@remotion/bundler' +import { renderStill } from '@remotion/renderer' +import { createRequire } from 'module' +import path from 'path' +import { fileURLToPath } from 'url' + +const __dirname = path.dirname(fileURLToPath(import.meta.url)) + +async function main() { + console.log('Bundling Remotion project...') + const bundled = await bundle({ + entryPoint: path.join(__dirname, 'index.ts'), + webpackOverride: (config) => config, + }) + + const outputPath = path.join(__dirname, '..', '..', 'docs', 'data-file-preview.png') + + console.log('Rendering screenshot...') + await renderStill({ + composition: { + id: 'DataFilePreview', + durationInFrames: 1, + fps: 1, + width: 1200, + height: 700, + defaultProps: {}, + defaultCodec: null, + }, + serveUrl: bundled, + output: outputPath, + frame: 0, + }) + + console.log(`Screenshot saved to: ${outputPath}`) +} + +main().catch((err) => { + console.error(err) + process.exit(1) +}) diff --git a/src/main/ipc-handlers.ts b/src/main/ipc-handlers.ts index 59b32eba..552e0ecc 100644 --- a/src/main/ipc-handlers.ts +++ b/src/main/ipc-handlers.ts @@ -3,6 +3,8 @@ import { copyFileSync, existsSync, unlinkSync, readdirSync, statSync, readFileSy import { execFile } from 'child_process' import { promisify } from 'util' import { join, basename, extname } from 'path' +import Papa from 'papaparse' +import * as XLSX from 'xlsx' const execFileAsync = promisify(execFile) import type { @@ -141,6 +143,14 @@ export function registerIpcHandlers( return db.getWorkspaceDir(taskId) }) + ipcMain.handle('attachments:resolvePath', (_, taskId: string, attachmentId: string): string | null => { + const dir = db.getAttachmentsDir(taskId) + if (!existsSync(dir)) return null + const files = readdirSync(dir) + const match = files.find((f) => f.startsWith(`${attachmentId}-`)) + return match ? join(dir, match) : null + }) + ipcMain.handle('attachments:open', (_, taskId: string, attachmentId: string) => { console.log('[IPC] attachments:open called:', { taskId, attachmentId }) @@ -230,6 +240,89 @@ export function registerIpcHandlers( await shell.openExternal(url) }) + // ── File Viewer handlers ────────────────────────────────────────────────── + const TABULAR_EXTENSIONS = new Set(['.csv', '.tsv', '.json', '.jsonl', '.xlsx', '.xls', '.parquet']) + + ipcMain.handle('fileViewer:getFileInfo', (_, filePath: string): { exists: boolean; size: number; extension: string; isTabular: boolean } => { + if (!existsSync(filePath)) return { exists: false, size: 0, extension: '', isTabular: false } + const stat = statSync(filePath) + const ext = extname(filePath).toLowerCase() + return { exists: true, size: stat.size, extension: ext, isTabular: TABULAR_EXTENSIONS.has(ext) } + }) + + ipcMain.handle( + 'fileViewer:readTabularFile', + (_, filePath: string, limit?: number): { columns: string[]; rows: Record[]; totalRows: number; truncated: boolean; filePath: string } | { error: string } => { + const maxRows = limit ?? 500 + if (!existsSync(filePath)) return { error: 'File not found' } + + const ext = extname(filePath).toLowerCase() + try { + if (ext === '.csv' || ext === '.tsv') { + const content = readFileSync(filePath, 'utf-8') + const result = Papa.parse(content, { + header: true, + delimiter: ext === '.tsv' ? '\t' : undefined, + skipEmptyLines: true, + preview: maxRows + }) + const columns = result.meta.fields || [] + const rows = result.data as Record[] + // Count total lines for the footer + let totalRows = rows.length + if (rows.length === maxRows) { + // Estimate total by counting newlines + totalRows = content.split('\n').filter(l => l.trim()).length - 1 // minus header + } + return { columns, rows, totalRows, truncated: rows.length < totalRows, filePath } + } + + if (ext === '.json') { + const content = readFileSync(filePath, 'utf-8') + let parsed = JSON.parse(content) + if (!Array.isArray(parsed)) { + // If it's a single object, wrap it + parsed = [parsed] + } + const totalRows = parsed.length + const rows = parsed.slice(0, maxRows) as Record[] + const columns = rows.length > 0 ? Object.keys(rows[0]) : [] + return { columns, rows, totalRows, truncated: totalRows > maxRows, filePath } + } + + if (ext === '.jsonl') { + const content = readFileSync(filePath, 'utf-8') + const lines = content.split('\n').filter(l => l.trim()) + const totalRows = lines.length + const rows = lines.slice(0, maxRows).map(l => JSON.parse(l)) as Record[] + const columns = rows.length > 0 ? Object.keys(rows[0]) : [] + return { columns, rows, totalRows, truncated: totalRows > maxRows, filePath } + } + + if (ext === '.xlsx' || ext === '.xls') { + const workbook = XLSX.read(readFileSync(filePath), { type: 'buffer' }) + const sheetName = workbook.SheetNames[0] + if (!sheetName) return { error: 'No sheets found in workbook' } + const sheet = workbook.Sheets[sheetName] + const allRows = XLSX.utils.sheet_to_json(sheet) as Record[] + const totalRows = allRows.length + const rows = allRows.slice(0, maxRows) + const columns = rows.length > 0 ? Object.keys(rows[0]) : [] + return { columns, rows, totalRows, truncated: totalRows > maxRows, filePath } + } + + if (ext === '.parquet') { + // Parquet requires async — for now return a helpful error + return { error: 'Parquet support coming soon. Convert to CSV or JSON for preview.' } + } + + return { error: `Unsupported file type: ${ext}` } + } catch (err) { + return { error: `Failed to parse file: ${err instanceof Error ? err.message : String(err)}` } + } + } + ) + // Notification handler ipcMain.handle('notifications:show', (_, title: string, body: string) => { new Notification({ title, body }).show() diff --git a/src/preload/index.ts b/src/preload/index.ts index 6464d26c..c37ea08a 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -23,7 +23,9 @@ contextBridge.exposeInMainWorld('electronAPI', { open: (taskId: string, attachmentId: string): Promise => ipcRenderer.invoke('attachments:open', taskId, attachmentId), download: (taskId: string, attachmentId: string): Promise => - ipcRenderer.invoke('attachments:download', taskId, attachmentId) + ipcRenderer.invoke('attachments:download', taskId, attachmentId), + resolvePath: (taskId: string, attachmentId: string): Promise => + ipcRenderer.invoke('attachments:resolvePath', taskId, attachmentId) }, shell: { openPath: (filePath: string): Promise => @@ -35,6 +37,12 @@ contextBridge.exposeInMainWorld('electronAPI', { openExternal: (url: string): Promise => ipcRenderer.invoke('shell:openExternal', url) }, + fileViewer: { + getFileInfo: (filePath: string): Promise<{ exists: boolean; size: number; extension: string; isTabular: boolean }> => + ipcRenderer.invoke('fileViewer:getFileInfo', filePath), + readTabularFile: (filePath: string, limit?: number): Promise<{ columns: string[]; rows: Record[]; totalRows: number; truncated: boolean; filePath: string } | { error: string }> => + ipcRenderer.invoke('fileViewer:readTabularFile', filePath, limit) + }, oauth: { startFlow: (provider: string, config: Record): Promise => ipcRenderer.invoke('oauth:startFlow', provider, config), diff --git a/src/renderer/src/components/agents/AgentTranscriptPanel.tsx b/src/renderer/src/components/agents/AgentTranscriptPanel.tsx index 9b46ff33..3f15785d 100644 --- a/src/renderer/src/components/agents/AgentTranscriptPanel.tsx +++ b/src/renderer/src/components/agents/AgentTranscriptPanel.tsx @@ -3,9 +3,27 @@ import { useVirtualizer } from '@tanstack/react-virtual' import { StopCircle, Loader2, Terminal, Send, ChevronRight, ChevronDown, Wrench, AlertTriangle, CheckCircle2, Circle, Clock, RotateCcw, Code2, Eye, ListTodo, FileText, ArrowDown } from 'lucide-react' import { Button } from '@/components/ui/Button' import { Markdown } from '@/components/ui/Markdown' +import { DataFilePreview } from '@/components/ui/DataFilePreview' +import { DataFileDialog } from '@/components/ui/DataFileDialog' import type { AgentMessage } from '@/hooks/use-agent-session' import { SessionStatus } from '@/stores/agent-store' +const TABULAR_EXT_RE = /\.(csv|tsv|json|jsonl|xlsx|xls|parquet)$/i + +function extractTabularFilePath(toolInput: unknown): string | null { + if (!toolInput) return null + try { + const input = typeof toolInput === 'string' ? JSON.parse(toolInput) : toolInput + // Check common field names for file paths + const path = input.file_path || input.path || input.filePath || input.filename + if (typeof path === 'string' && TABULAR_EXT_RE.test(path)) return path + } catch { + // If input is a plain string path + if (typeof toolInput === 'string' && TABULAR_EXT_RE.test(toolInput)) return toolInput + } + return null +} + enum ViewMode { MARKDOWN = 'markdown', RAW = 'raw' @@ -245,52 +263,83 @@ function PlanReviewMessage({ message }: { message: AgentMessage }) { function ToolCallMessage({ message }: { message: AgentMessage }) { const [expanded, setExpanded] = useState(false) + const [showDataDialog, setShowDataDialog] = useState(false) const tool = message.tool! const isRunning = !tool.status || tool.status === 'in_progress' || tool.status === 'running' || tool.status === 'pending' const isError = tool.status === 'error' || tool.status === 'failed' + const isCompleted = tool.status === 'completed' || tool.status === 'done' || tool.status === 'success' + + // Detect tabular file from tool input + const tabularFilePath = useMemo(() => { + if (!isCompleted) return null + return extractTabularFilePath(tool.input) + }, [isCompleted, tool.input]) return ( -
- - {expanded && ( -
- {tool.input && ( -
- Input: -
{sanitizeToolContent(tool.input)}
-
- )} - {tool.output && ( -
- Output: -
{sanitizeToolContent(tool.output)}
-
- )} - {tool.error && ( -
- Error: -
{tool.error}
-
+ <> +
+ + {expanded && ( +
+ {tool.input && ( +
+ Input: +
{sanitizeToolContent(tool.input)}
+
+ )} + {tool.output && ( +
+ Output: +
{sanitizeToolContent(tool.output)}
+
+ )} + {tool.error && ( +
+ Error: +
{tool.error}
+
+ )} +
+ )} + + {/* Inline data file preview */} + {tabularFilePath && ( +
+ setShowDataDialog(true)} + /> +
+ )} + +
+ {message.timestamp.toLocaleTimeString()} + {message.stepMeta && ( + {formatStepMeta(message.stepMeta)} )}
- )} -
- {message.timestamp.toLocaleTimeString()} - {message.stepMeta && ( - {formatStepMeta(message.stepMeta)} - )}
-
+ + {/* Fullscreen data dialog */} + {tabularFilePath && ( + + )} + ) } diff --git a/src/renderer/src/components/tasks/TaskAttachments.tsx b/src/renderer/src/components/tasks/TaskAttachments.tsx index 97c742e1..6af06dfc 100644 --- a/src/renderer/src/components/tasks/TaskAttachments.tsx +++ b/src/renderer/src/components/tasks/TaskAttachments.tsx @@ -1,8 +1,14 @@ import { useState, useCallback } from 'react' -import { Paperclip, X, FileText, Download } from 'lucide-react' +import { Paperclip, X, FileText, Download, Table2 } from 'lucide-react' import { attachmentApi } from '@/lib/ipc-client' +import { DataFileDialog } from '@/components/ui/DataFileDialog' import type { FileAttachment } from '@/types' +const TABULAR_EXT_RE = /\.(csv|tsv|json|jsonl|xlsx|xls|parquet)$/i +function isTabularFile(filename: string): boolean { + return TABULAR_EXT_RE.test(filename) +} + export interface PendingFile { id: string filename: string @@ -34,6 +40,7 @@ export function TaskAttachments({ onPendingChange }: TaskAttachmentsProps) { const [isDragging, setIsDragging] = useState(false) + const [dataDialogPath, setDataDialogPath] = useState(null) const processFilePaths = useCallback( async (filePaths: string[]) => { @@ -111,8 +118,16 @@ export function TaskAttachments({ onPendingChange?.(pendingFiles.filter((f) => f.id !== id)) } - const handleOpen = (attachment: FileAttachment) => { - if (taskId) attachmentApi.open(taskId, attachment.id) + const handleOpen = async (attachment: FileAttachment) => { + if (!taskId) return + if (isTabularFile(attachment.filename)) { + const resolved = await attachmentApi.resolvePath(taskId, attachment.id) + if (resolved) { + setDataDialogPath(resolved) + return + } + } + attachmentApi.open(taskId, attachment.id) } const handleDownload = (attachment: FileAttachment) => { @@ -150,7 +165,11 @@ export function TaskAttachments({
{items.map((a) => (
- + {isTabularFile(a.filename) ? ( + + ) : ( + + )} )} + + {dataDialogPath && ( + { if (!open) setDataDialogPath(null) }} + filePath={dataDialogPath} + /> + )}
) } diff --git a/src/renderer/src/components/ui/DataFileDialog.tsx b/src/renderer/src/components/ui/DataFileDialog.tsx new file mode 100644 index 00000000..79691604 --- /dev/null +++ b/src/renderer/src/components/ui/DataFileDialog.tsx @@ -0,0 +1,35 @@ +import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/Dialog' +import { DataFilePreview } from '@/components/ui/DataFilePreview' +import { Table2 } from 'lucide-react' + +interface DataFileDialogProps { + open: boolean + onOpenChange: (open: boolean) => void + filePath: string +} + +export function DataFileDialog({ open, onOpenChange, filePath }: DataFileDialogProps) { + const fileName = filePath.split('/').pop() || filePath.split('\\').pop() || filePath + + return ( + + + + + + + {fileName} + + + +
+ +
+
+
+ ) +} diff --git a/src/renderer/src/components/ui/DataFilePreview.tsx b/src/renderer/src/components/ui/DataFilePreview.tsx new file mode 100644 index 00000000..1e60d2c1 --- /dev/null +++ b/src/renderer/src/components/ui/DataFilePreview.tsx @@ -0,0 +1,241 @@ +import { useState, useEffect, useMemo, useCallback, useRef } from 'react' +import { Table2, Maximize2, ArrowUpDown, ArrowUp, ArrowDown, AlertTriangle, Loader2 } from 'lucide-react' +import { fileViewerApi } from '@/lib/ipc-client' +import type { TabularData } from '@/types/electron' + +interface DataFilePreviewProps { + filePath: string + maxRows?: number + compact?: boolean + onExpand?: () => void +} + +type SortDir = 'asc' | 'desc' | null + +function formatNumber(n: number): string { + return n.toLocaleString() +} + +function formatCellValue(value: unknown): string { + if (value == null) return '' + if (typeof value === 'object') return JSON.stringify(value) + return String(value) +} + +export function DataFilePreview({ filePath, maxRows = 100, compact = true, onExpand }: DataFilePreviewProps) { + const [data, setData] = useState(null) + const [error, setError] = useState(null) + const [loading, setLoading] = useState(true) + const [sortCol, setSortCol] = useState(null) + const [sortDir, setSortDir] = useState(null) + const [filter, setFilter] = useState('') + const tableRef = useRef(null) + + useEffect(() => { + let cancelled = false + setLoading(true) + setError(null) + + fileViewerApi.readTabularFile(filePath, maxRows).then((result) => { + if (cancelled) return + if ('error' in result) { + setError(result.error) + } else { + setData(result) + } + setLoading(false) + }).catch((err) => { + if (cancelled) return + setError(err instanceof Error ? err.message : String(err)) + setLoading(false) + }) + + return () => { cancelled = true } + }, [filePath, maxRows]) + + const handleSort = useCallback((col: string) => { + if (sortCol === col) { + setSortDir((prev) => prev === 'asc' ? 'desc' : prev === 'desc' ? null : 'asc') + if (sortDir === 'desc') setSortCol(null) + } else { + setSortCol(col) + setSortDir('asc') + } + }, [sortCol, sortDir]) + + const processedRows = useMemo(() => { + if (!data) return [] + let rows = [...data.rows] + + // Filter + if (filter) { + const lowerFilter = filter.toLowerCase() + rows = rows.filter((row) => + data.columns.some((col) => { + const val = row[col] + return val != null && String(val).toLowerCase().includes(lowerFilter) + }) + ) + } + + // Sort + if (sortCol && sortDir) { + rows.sort((a, b) => { + const aVal = a[sortCol] + const bVal = b[sortCol] + if (aVal == null && bVal == null) return 0 + if (aVal == null) return 1 + if (bVal == null) return -1 + + // Try numeric comparison + const aNum = Number(aVal) + const bNum = Number(bVal) + if (!isNaN(aNum) && !isNaN(bNum)) { + return sortDir === 'asc' ? aNum - bNum : bNum - aNum + } + + // String comparison + const aStr = String(aVal) + const bStr = String(bVal) + return sortDir === 'asc' ? aStr.localeCompare(bStr) : bStr.localeCompare(aStr) + }) + } + + return rows + }, [data, sortCol, sortDir, filter]) + + const fileName = filePath.split('/').pop() || filePath.split('\\').pop() || filePath + + if (loading) { + return ( +
+
+ + Loading {fileName}... +
+
+ ) + } + + if (error) { + return ( +
+
+ + {error} +
+
+ ) + } + + if (!data || data.rows.length === 0) { + return ( +
+
+ + No data in {fileName} +
+
+ ) + } + + return ( +
+ {/* Header */} +
+
+ + {fileName} + + {formatNumber(data.totalRows)} rows {data.columns.length} cols + +
+
+ {!compact && ( + setFilter(e.target.value)} + placeholder="Filter..." + className="w-40 bg-background border border-border/50 rounded px-2 py-1 text-[11px] text-foreground placeholder:text-muted-foreground focus:outline-none focus:border-primary/50" + /> + )} + {onExpand && ( + + )} +
+
+ + {/* Table */} +
+ + + + + {data.columns.map((col) => ( + + ))} + + + + {processedRows.map((row, i) => ( + + + {data.columns.map((col) => ( + + ))} + + ))} + +
# handleSort(col)} + className="px-2.5 py-1.5 text-left font-medium text-muted-foreground cursor-pointer hover:text-foreground transition-colors select-none whitespace-nowrap" + > + + {col} + {sortCol === col ? ( + sortDir === 'asc' ? : + ) : ( + + )} + +
{i + 1} + {formatCellValue(row[col])} +
+
+ + {/* Footer */} +
+ + Showing {formatNumber(processedRows.length)}{filter ? ` (filtered)` : ''} of {formatNumber(data.totalRows)} rows + {data.truncated && ' (truncated)'} + + {compact && onExpand && ( + + )} +
+
+ ) +} diff --git a/src/renderer/src/lib/ipc-client.ts b/src/renderer/src/lib/ipc-client.ts index 4a9107e5..068b6b6a 100644 --- a/src/renderer/src/lib/ipc-client.ts +++ b/src/renderer/src/lib/ipc-client.ts @@ -1,5 +1,5 @@ import type { WorkfloTask, CreateTaskDTO, UpdateTaskDTO, FileAttachment, Agent, CreateAgentDTO, UpdateAgentDTO, McpServer, CreateMcpServerDTO, UpdateMcpServerDTO, Skill, CreateSkillDTO, UpdateSkillDTO, Secret, CreateSecretDTO, UpdateSecretDTO, TaskSource, CreateTaskSourceDTO, UpdateTaskSourceDTO, SyncResult, PluginMeta, ConfigFieldSchema, ConfigFieldOption, PluginAction, ActionResult, SourceUser, ReassignResult, MarketplaceSource, InstalledPlugin, DiscoverablePlugin, MarketplaceCatalog, PluginResources } from '@/types' -import type { AgentOutputEvent, AgentOutputBatchEvent, AgentStatusEvent, AgentApprovalRequest, GhCliStatus, GitHubRepo, GitHubCollaborator, WorktreeProgressEvent, McpTestResult, SkillSyncResult, DepsStatus } from '@/types/electron' +import type { AgentOutputEvent, AgentOutputBatchEvent, AgentStatusEvent, AgentApprovalRequest, GhCliStatus, GitHubRepo, GitHubCollaborator, WorktreeProgressEvent, McpTestResult, SkillSyncResult, DepsStatus, TabularDataResult, FileInfo } from '@/types/electron' export const taskApi = { getAll: (): Promise => { @@ -176,6 +176,20 @@ export const attachmentApi = { download: (taskId: string, attachmentId: string): Promise => { return window.electronAPI.attachments.download(taskId, attachmentId) + }, + + resolvePath: (taskId: string, attachmentId: string): Promise => { + return window.electronAPI.attachments.resolvePath(taskId, attachmentId) + } +} + +export const fileViewerApi = { + getFileInfo: (filePath: string): Promise => { + return window.electronAPI.fileViewer.getFileInfo(filePath) + }, + + readTabularFile: (filePath: string, limit?: number): Promise => { + return window.electronAPI.fileViewer.readTabularFile(filePath, limit) } } diff --git a/src/renderer/src/types/electron.d.ts b/src/renderer/src/types/electron.d.ts index a706d0e0..da2edf66 100644 --- a/src/renderer/src/types/electron.d.ts +++ b/src/renderer/src/types/electron.d.ts @@ -133,6 +133,27 @@ export interface DepsStatus { codexBinary: boolean } +export interface TabularData { + columns: string[] + rows: Record[] + totalRows: number + truncated: boolean + filePath: string +} + +export interface TabularDataError { + error: string +} + +export type TabularDataResult = TabularData | TabularDataError + +export interface FileInfo { + exists: boolean + size: number + extension: string + isTabular: boolean +} + interface ElectronAPI { db: { getTasks: () => Promise @@ -184,6 +205,7 @@ interface ElectronAPI { remove: (taskId: string, attachmentId: string) => Promise open: (taskId: string, attachmentId: string) => Promise download: (taskId: string, attachmentId: string) => Promise + resolvePath: (taskId: string, attachmentId: string) => Promise } shell: { openPath: (filePath: string) => Promise @@ -191,6 +213,10 @@ interface ElectronAPI { readTextFile: (filePath: string) => Promise<{ content: string; size: number } | null> openExternal: (url: string) => Promise } + fileViewer: { + getFileInfo: (filePath: string) => Promise + readTabularFile: (filePath: string, limit?: number) => Promise + } oauth: { startFlow: (provider: string, config: Record) => Promise exchangeCode: (provider: string, code: string, state: string, sourceId: string) => Promise From 25fba7b1f700d08236866d6f22319f9d579a7cbb Mon Sep 17 00:00:00 2001 From: dimavedenyapin Date: Mon, 9 Mar 2026 21:03:36 +0800 Subject: [PATCH 2/3] feat: add marimo notebook detection and live embed in agent chat When the agent writes a .py file containing marimo markers (`import marimo`, `@app.cell`, `marimo.App`), the transcript auto-detects it and shows a MarimoEmbed component with Run/Edit buttons. Clicking Run spawns a local `marimo run --headless --no-token` server and embeds the live notebook in an iframe inline in the chat, with fullscreen expansion support. - marimo-server.ts: manages marimo process lifecycle (launch, stop, cleanup) - MarimoEmbed.tsx: inline component with run/edit/fullscreen/stop controls - Detection: content-based (tool input/output) + async disk fallback - Graceful handling when marimo is not installed (shows install instructions) - All marimo servers cleaned up on app quit Co-Authored-By: Claude Opus 4.6 --- src/main/index.ts | 8 +- src/main/ipc-handlers.ts | 26 ++ src/main/marimo-server.ts | 212 +++++++++++++++ src/preload/index.ts | 12 + .../agents/AgentTranscriptPanel.tsx | 81 +++++- .../src/components/ui/MarimoEmbed.tsx | 247 ++++++++++++++++++ src/renderer/src/lib/ipc-client.ts | 24 +- src/renderer/src/types/electron.d.ts | 25 ++ 8 files changed, 624 insertions(+), 11 deletions(-) create mode 100644 src/main/marimo-server.ts create mode 100644 src/renderer/src/components/ui/MarimoEmbed.tsx diff --git a/src/main/index.ts b/src/main/index.ts index e16f03dc..38ac24fb 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -405,7 +405,7 @@ app.on('window-all-closed', () => { } }) -app.on('before-quit', () => { +app.on('before-quit', async () => { isQuitting = true // Ensure cleanup before quitting heartbeatScheduler?.stop() @@ -414,6 +414,12 @@ app.on('before-quit', () => { mcpToolCaller?.destroy() oauthManager?.destroy() + // Stop all marimo server instances + try { + const { stopAllMarimo } = await import('./marimo-server') + stopAllMarimo() + } catch { /* marimo module may not be loaded */ } + // Checkpoint WAL and close database db?.close() diff --git a/src/main/ipc-handlers.ts b/src/main/ipc-handlers.ts index 552e0ecc..8b38c6a9 100644 --- a/src/main/ipc-handlers.ts +++ b/src/main/ipc-handlers.ts @@ -328,6 +328,32 @@ export function registerIpcHandlers( new Notification({ title, body }).show() }) + // ── Marimo handlers ──────────────────────────────────────────────────── + ipcMain.handle('marimo:check', async () => { + const { checkMarimo } = await import('./marimo-server') + return checkMarimo() + }) + + ipcMain.handle('marimo:isNotebook', async (_, filePath: string) => { + const { isMarimoNotebook } = await import('./marimo-server') + return isMarimoNotebook(filePath) + }) + + ipcMain.handle('marimo:launch', async (_, filePath: string, mode?: 'run' | 'edit') => { + const { launchMarimo } = await import('./marimo-server') + return launchMarimo(filePath, mode || 'run') + }) + + ipcMain.handle('marimo:stop', async (_, filePath: string) => { + const { stopMarimo } = await import('./marimo-server') + return stopMarimo(filePath) + }) + + ipcMain.handle('marimo:status', async (_, filePath: string) => { + const { getMarimoStatus } = await import('./marimo-server') + return getMarimoStatus(filePath) + }) + // Agent handlers ipcMain.handle('agent:getAll', () => { return db.getAgents() diff --git a/src/main/marimo-server.ts b/src/main/marimo-server.ts new file mode 100644 index 00000000..af6d6045 --- /dev/null +++ b/src/main/marimo-server.ts @@ -0,0 +1,212 @@ +/** + * Manages marimo notebook server instances. + * + * When the agent writes a .py file that contains `import marimo`, + * we spin up `marimo run --headless --no-token --port ` + * and expose the URL so the renderer can embed it in an iframe. + */ +import { spawn, execFile } from 'child_process' +import { promisify } from 'util' +import { existsSync, readFileSync } from 'fs' +import type { ChildProcess } from 'child_process' + +const execFileAsync = promisify(execFile) + +interface MarimoInstance { + port: number + process: ChildProcess + filePath: string + url: string +} + +// Track all running marimo instances by file path +const instances = new Map() +let marimoPath: string | null = null +let marimoChecked = false + +/** + * Check if marimo is installed and return its path + */ +export async function checkMarimo(): Promise<{ installed: boolean; path: string | null; version: string | null }> { + if (marimoChecked && marimoPath) { + return { installed: true, path: marimoPath, version: null } + } + + // Try common locations + const candidates = ['marimo', '/usr/local/bin/marimo', '/opt/homebrew/bin/marimo'] + + // Also check if it's in a pipx or pip --user location + const home = process.env.HOME || process.env.USERPROFILE || '' + if (home) { + candidates.push(`${home}/.local/bin/marimo`) + candidates.push(`${home}/Library/Python/3.11/bin/marimo`) + candidates.push(`${home}/Library/Python/3.12/bin/marimo`) + candidates.push(`${home}/Library/Python/3.13/bin/marimo`) + } + + for (const candidate of candidates) { + try { + const { stdout } = await execFileAsync(candidate, ['--version'], { timeout: 5000 }) + marimoPath = candidate + marimoChecked = true + const version = stdout.trim().replace('marimo ', '') + console.log(`[marimo] Found marimo at ${candidate} (v${version})`) + return { installed: true, path: candidate, version } + } catch { + // Not found at this path, try next + } + } + + marimoChecked = true + return { installed: false, path: null, version: null } +} + +/** + * Detect whether a .py file is a marimo notebook + */ +export function isMarimoNotebook(filePath: string): boolean { + if (!filePath.endsWith('.py')) return false + if (!existsSync(filePath)) return false + + try { + // Read first 2KB to check for marimo markers + const content = readFileSync(filePath, 'utf-8').slice(0, 2048) + return ( + content.includes('import marimo') || + content.includes('marimo.App') || + content.includes('@app.cell') + ) + } catch { + return false + } +} + +/** + * Find a free port in a range + */ +function getRandomPort(): number { + return 2718 + Math.floor(Math.random() * 1000) +} + +/** + * Launch a marimo server for a notebook file. + * Returns the URL to embed in an iframe. + */ +export async function launchMarimo( + filePath: string, + mode: 'run' | 'edit' = 'run' +): Promise<{ url: string; port: number; pid: number }> { + // If already running for this file, return existing + const existing = instances.get(filePath) + if (existing) { + return { url: existing.url, port: existing.port, pid: existing.process.pid! } + } + + const marimoStatus = await checkMarimo() + if (!marimoStatus.installed || !marimoStatus.path) { + throw new Error('marimo is not installed. Install it with: pip install marimo') + } + + if (!existsSync(filePath)) { + throw new Error(`File not found: ${filePath}`) + } + + const port = getRandomPort() + const args = [ + mode, + '--headless', + '--no-token', + '--port', String(port), + '--host', '127.0.0.1', + filePath + ] + + console.log(`[marimo] Launching: ${marimoStatus.path} ${args.join(' ')}`) + + const proc = spawn(marimoStatus.path, args, { + stdio: ['ignore', 'pipe', 'pipe'], + detached: false, + }) + + const url = `http://127.0.0.1:${port}` + + const instance: MarimoInstance = { + port, + process: proc, + filePath, + url, + } + + instances.set(filePath, instance) + + // Log output for debugging + proc.stdout?.on('data', (data: Buffer) => { + console.log(`[marimo:${port}] ${data.toString().trim()}`) + }) + proc.stderr?.on('data', (data: Buffer) => { + console.log(`[marimo:${port}:err] ${data.toString().trim()}`) + }) + + // Clean up on exit + proc.on('exit', (code) => { + console.log(`[marimo:${port}] Process exited with code ${code}`) + instances.delete(filePath) + }) + + // Wait for the server to be ready by polling + await waitForServer(url, 15000) + + console.log(`[marimo] Server ready at ${url} (pid: ${proc.pid})`) + return { url, port, pid: proc.pid! } +} + +/** + * Stop a marimo server instance + */ +export function stopMarimo(filePath: string): boolean { + const instance = instances.get(filePath) + if (!instance) return false + + console.log(`[marimo] Stopping server for ${filePath} (pid: ${instance.process.pid})`) + instance.process.kill('SIGTERM') + instances.delete(filePath) + return true +} + +/** + * Stop all running marimo instances (call on app quit) + */ +export function stopAllMarimo(): void { + for (const [filePath, instance] of instances) { + console.log(`[marimo] Stopping server for ${filePath}`) + instance.process.kill('SIGTERM') + } + instances.clear() +} + +/** + * Get status of a running marimo instance + */ +export function getMarimoStatus(filePath: string): { running: boolean; url: string | null; port: number | null } { + const instance = instances.get(filePath) + if (!instance) return { running: false, url: null, port: null } + return { running: true, url: instance.url, port: instance.port } +} + +/** + * Poll a URL until it responds (server startup) + */ +async function waitForServer(url: string, timeoutMs: number): Promise { + const start = Date.now() + while (Date.now() - start < timeoutMs) { + try { + const response = await fetch(url, { signal: AbortSignal.timeout(1000) }) + if (response.ok || response.status === 200) return + } catch { + // Server not ready yet + } + await new Promise((r) => setTimeout(r, 300)) + } + // Don't throw — server may still be starting, let the iframe handle it + console.log(`[marimo] Server at ${url} did not respond within ${timeoutMs}ms, proceeding anyway`) +} diff --git a/src/preload/index.ts b/src/preload/index.ts index c37ea08a..902a5714 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -43,6 +43,18 @@ contextBridge.exposeInMainWorld('electronAPI', { readTabularFile: (filePath: string, limit?: number): Promise<{ columns: string[]; rows: Record[]; totalRows: number; truncated: boolean; filePath: string } | { error: string }> => ipcRenderer.invoke('fileViewer:readTabularFile', filePath, limit) }, + marimo: { + check: (): Promise<{ installed: boolean; path: string | null; version: string | null }> => + ipcRenderer.invoke('marimo:check'), + isNotebook: (filePath: string): Promise => + ipcRenderer.invoke('marimo:isNotebook', filePath), + launch: (filePath: string, mode?: 'run' | 'edit'): Promise<{ url: string; port: number; pid: number }> => + ipcRenderer.invoke('marimo:launch', filePath, mode), + stop: (filePath: string): Promise => + ipcRenderer.invoke('marimo:stop', filePath), + status: (filePath: string): Promise<{ running: boolean; url: string | null; port: number | null }> => + ipcRenderer.invoke('marimo:status', filePath) + }, oauth: { startFlow: (provider: string, config: Record): Promise => ipcRenderer.invoke('oauth:startFlow', provider, config), diff --git a/src/renderer/src/components/agents/AgentTranscriptPanel.tsx b/src/renderer/src/components/agents/AgentTranscriptPanel.tsx index 3f15785d..b614e5af 100644 --- a/src/renderer/src/components/agents/AgentTranscriptPanel.tsx +++ b/src/renderer/src/components/agents/AgentTranscriptPanel.tsx @@ -5,25 +5,65 @@ import { Button } from '@/components/ui/Button' import { Markdown } from '@/components/ui/Markdown' import { DataFilePreview } from '@/components/ui/DataFilePreview' import { DataFileDialog } from '@/components/ui/DataFileDialog' +import { MarimoEmbed } from '@/components/ui/MarimoEmbed' +import { marimoApi } from '@/lib/ipc-client' import type { AgentMessage } from '@/hooks/use-agent-session' import { SessionStatus } from '@/stores/agent-store' const TABULAR_EXT_RE = /\.(csv|tsv|json|jsonl|xlsx|xls|parquet)$/i -function extractTabularFilePath(toolInput: unknown): string | null { +function extractFilePath(toolInput: unknown): string | null { if (!toolInput) return null try { const input = typeof toolInput === 'string' ? JSON.parse(toolInput) : toolInput - // Check common field names for file paths - const path = input.file_path || input.path || input.filePath || input.filename - if (typeof path === 'string' && TABULAR_EXT_RE.test(path)) return path + return input.file_path || input.path || input.filePath || input.filename || null } catch { - // If input is a plain string path - if (typeof toolInput === 'string' && TABULAR_EXT_RE.test(toolInput)) return toolInput + if (typeof toolInput === 'string') return toolInput + } + return null +} + +function extractTabularFilePath(toolInput: unknown): string | null { + const path = extractFilePath(toolInput) + if (path && TABULAR_EXT_RE.test(path)) return path + return null +} + +function extractMarimoFilePath(toolInput: unknown, toolOutput: unknown): string | null { + const path = extractFilePath(toolInput) + if (!path || !path.endsWith('.py')) return null + + // Check tool output for marimo markers (content written by agent) + const output = typeof toolOutput === 'string' ? toolOutput : '' + const input = typeof toolInput === 'string' ? toolInput : JSON.stringify(toolInput || '') + const combined = output + input + + if ( + combined.includes('import marimo') || + combined.includes('marimo.App') || + combined.includes('@app.cell') + ) { + return path } return null } +/** + * Hook that async-checks if a .py file is a marimo notebook (reads from disk). + * Used as fallback when content isn't visible in tool input/output. + */ +function useMarimoDetection(filePath: string | null, isCompleted: boolean): boolean { + const [isMarimo, setIsMarimo] = useState(false) + useEffect(() => { + if (!filePath || !isCompleted || !filePath.endsWith('.py')) { + setIsMarimo(false) + return + } + marimoApi.isNotebook(filePath).then(setIsMarimo).catch(() => setIsMarimo(false)) + }, [filePath, isCompleted]) + return isMarimo +} + enum ViewMode { MARKDOWN = 'markdown', RAW = 'raw' @@ -275,6 +315,22 @@ function ToolCallMessage({ message }: { message: AgentMessage }) { return extractTabularFilePath(tool.input) }, [isCompleted, tool.input]) + // Detect marimo notebook from tool input/output (sync check via content) + const marimoFilePathFromContent = useMemo(() => { + if (!isCompleted) return null + return extractMarimoFilePath(tool.input, tool.output) + }, [isCompleted, tool.input, tool.output]) + + // Async fallback: check disk for marimo markers if .py file was written + const pyFilePath = useMemo(() => { + if (!isCompleted || marimoFilePathFromContent) return null + const fp = extractFilePath(tool.input) + return fp?.endsWith('.py') ? fp : null + }, [isCompleted, tool.input, marimoFilePathFromContent]) + + const isMarimoFromDisk = useMarimoDetection(pyFilePath, isCompleted) + const marimoFilePath = marimoFilePathFromContent || (isMarimoFromDisk ? pyFilePath : null) + return ( <>
@@ -312,8 +368,15 @@ function ToolCallMessage({ message }: { message: AgentMessage }) {
)} - {/* Inline data file preview */} - {tabularFilePath && ( + {/* Inline marimo notebook embed */} + {marimoFilePath && ( +
+ +
+ )} + + {/* Inline data file preview (non-marimo tabular files) */} + {!marimoFilePath && tabularFilePath && (
{/* Fullscreen data dialog */} - {tabularFilePath && ( + {tabularFilePath && !marimoFilePath && ( ({ phase: 'idle' }) + const [fullscreen, setFullscreen] = useState(false) + const [mode, setMode] = useState<'run' | 'edit'>('run') + + const fileName = filePath.split('/').pop() || filePath + + const launch = useCallback(async (launchMode: 'run' | 'edit' = mode) => { + setState({ phase: 'checking' }) + try { + // Check if already running + const status = await marimoApi.status(filePath) + if (status.running && status.url) { + setState({ phase: 'running', url: status.url }) + return + } + + // Check if marimo is installed + const check = await marimoApi.check() + if (!check.installed) { + setState({ phase: 'not-installed' }) + return + } + + setState({ phase: 'launching' }) + const result = await marimoApi.launch(filePath, launchMode) + setMode(launchMode) + setState({ phase: 'running', url: result.url }) + } catch (err) { + setState({ phase: 'error', message: err instanceof Error ? err.message : String(err) }) + } + }, [filePath, mode]) + + const stop = useCallback(async () => { + await marimoApi.stop(filePath) + setState({ phase: 'idle' }) + setFullscreen(false) + }, [filePath]) + + // Check on mount if already running + useEffect(() => { + marimoApi.status(filePath).then((status) => { + if (status.running && status.url) { + setState({ phase: 'running', url: status.url }) + } + }).catch(() => { /* ignore */ }) + }, [filePath]) + + // Idle state — show launch button + if (state.phase === 'idle') { + return ( +
+
+ + {fileName} + marimo notebook +
+ + +
+
+
+ ) + } + + // Not installed + if (state.phase === 'not-installed') { + return ( +
+
+ +
+ {fileName} + + marimo is not installed. Run: pip install marimo + +
+
+
+ ) + } + + // Checking / Launching + if (state.phase === 'checking' || state.phase === 'launching') { + return ( +
+
+ + + {state.phase === 'checking' ? 'Checking marimo...' : `Starting marimo ${mode} server...`} + +
+
+ ) + } + + // Error + if (state.phase === 'error') { + return ( +
+
+ +
+ {state.message} +
+ +
+
+ ) + } + + // Running — show embedded iframe + const iframeContent = ( +
+ {/* Toolbar */} +
+ + {fileName} + + + {mode === 'edit' ? 'editing' : 'running'} + +
+ {mode === 'run' && ( + + )} + + {!fullscreen && ( + + )} + +
+
+ + {/* iframe */} +