diff --git a/.obsidian/core-plugins.json b/.obsidian/core-plugins.json new file mode 100644 index 000000000..e69de29bb diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f68a80cd4..59299b7b6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -64,4 +64,24 @@ When submitting a pull request, please follow these guidelines: - Run `cargo test` for Rust code - Test the application manually before submitting +## Contributing Translations + +We welcome translation contributions! opcode supports multiple languages and we'd love your help making it accessible to more users. + +### How to Contribute Translations + +1. **Read the Translation Guide**: See [docs/TRANSLATION_GUIDE.md](docs/TRANSLATION_GUIDE.md) for detailed instructions +2. **Add or Improve Translations**: Edit files in `src/locales/[language-code]/` +3. **Test Your Changes**: Run the app and verify translations appear correctly +4. **Submit a Pull Request**: Use the prefix `i18n:` in your PR title (e.g., `i18n: Add French translation`) + +### Translation Guidelines + +- **Preserve Technical Terms**: Keep terms like "Agent", "MCP Server", "Token", etc. in English +- **Be Consistent**: Use the same translation for the same term throughout +- **Professional Tone**: Maintain a professional, technical style +- **Test Thoroughly**: Check all modules and ensure UI layout isn't broken + +For more details, see our [Translation Contribution Guide](docs/TRANSLATION_GUIDE.md). + Please adhere to the coding conventions, maintain clear documentation, and provide thorough testing for your contributions. diff --git a/README.md b/README.md index cb9ca51f5..97f754abe 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,11 @@

Create custom agents, manage interactive Claude Code sessions, run secure background agents, and more.

- + +

+ English | 简体中文 +

+

Features Installation @@ -46,17 +50,19 @@ Think of opcode as your command center for Claude Code - bridging the gap betwee - [✨ Features](#-features) - [🗂️ Project & Session Management](#️-project--session-management) - [🤖 CC Agents](#-cc-agents) - + - [📊 Usage Analytics Dashboard](#-usage-analytics-dashboard) - [🔌 MCP Server Management](#-mcp-server-management) - [⏰ Timeline & Checkpoints](#-timeline--checkpoints) - [📝 CLAUDE.md Management](#-claudemd-management) + - [🌐 Internationalization](#-internationalization) - [📖 Usage](#-usage) - [Getting Started](#getting-started) - [Managing Projects](#managing-projects) - [Creating Agents](#creating-agents) - [Tracking Usage](#tracking-usage) - [Working with MCP Servers](#working-with-mcp-servers) + - [Changing Language](#changing-language) - [🚀 Installation](#-installation) - [🔨 Build from Source](#-build-from-source) - [🛠️ Development](#️-development) @@ -106,6 +112,12 @@ Think of opcode as your command center for Claude Code - bridging the gap betwee - **Project Scanner**: Find all CLAUDE.md files in your projects - **Syntax Highlighting**: Full markdown support with syntax highlighting +### 🌐 **Internationalization** +- **Multi-language Support**: Full support for English and Simplified Chinese +- **Easy Language Switching**: Change language from Settings with one click +- **Technical Terms Preserved**: Technical terminology (Agent, MCP Server, Token, etc.) kept in English for consistency +- **Extensible**: Easy to add more languages with the i18next framework + ## 📖 Usage ### Getting Started @@ -155,6 +167,16 @@ Menu → MCP Manager → Add Server → Configure - Import from Claude Desktop configuration - Test connections before using +### Changing Language + +``` +Menu → Settings → General → Language +``` + +- Switch between English and Simplified Chinese +- Changes apply immediately +- Language preference is saved automatically + ## 🚀 Installation ### Prerequisites diff --git a/README.zh-CN.md b/README.zh-CN.md new file mode 100644 index 000000000..1ff329a47 --- /dev/null +++ b/README.zh-CN.md @@ -0,0 +1,222 @@ +# opcode + +

+ opcode Logo + +

opcode

+ +

+ 强大的 Claude Code GUI 应用和工具包 +

+

+ 创建自定义 Agents、管理交互式 Claude Code Sessions、运行安全的后台 Agents 等 +

+ +

+ English | 简体中文 +

+
+ +## 🌟 概述 + +**opcode** 是一个强大的桌面应用程序,改变了您与 Claude Code 的交互方式。基于 Tauri 2 构建,它为管理 Claude Code Sessions、创建自定义 Agents、跟踪使用情况等提供了美观的 GUI。 + +将 opcode 视为您的 Claude Code 指挥中心 - 在命令行工具和可视化体验之间架起桥梁,使 AI 辅助开发更加直观和高效。 + +## ✨ 特性 + +### 🗂️ **Project 和 Session 管理** +- **可视化 Project 浏览器**:浏览 `~/.claude/projects/` 中的所有 Claude Code Projects +- **Session 历史**:查看和恢复过去的编码 Sessions,保留完整上下文 +- **智能搜索**:使用内置搜索快速查找 Projects 和 Sessions +- **Session 洞察**:一目了然地查看首条消息、时间戳和 Session 元数据 + +### 🤖 **CC Agents** +- **自定义 AI Agents**:使用自定义 System Prompts 和行为创建专用 Agents +- **Agent 库**:为不同任务构建专用 Agents 集合 +- **后台执行**:在独立进程中运行 Agents,实现非阻塞操作 +- **执行历史**:跟踪所有 Agent 运行,包含详细日志和性能指标 + +### 📊 **使用分析仪表板** +- **成本跟踪**:实时监控您的 Claude API 使用情况和成本 +- **Token 分析**:按模型、Project 和时间段详细分解 +- **可视化图表**:显示使用趋势和模式的精美图表 +- **导出数据**:导出使用数据用于会计和分析 + +### 🔌 **MCP Server 管理** +- **服务器注册表**:从中央 UI 管理 Model Context Protocol 服务器 +- **简易配置**:通过 UI 添加服务器或从现有配置导入 +- **连接测试**:使用前验证服务器连接 +- **Claude Desktop 导入**:从 Claude Desktop 导入服务器配置 + +### ⏰ **Timeline 和 Checkpoints** +- **Session 版本控制**:在编码 Session 的任何时刻创建 Checkpoints +- **可视化 Timeline**:通过分支 Timeline 浏览 Session 历史 +- **即时恢复**:一键跳转到任何 Checkpoint +- **Fork Sessions**:从现有 Checkpoints 创建新分支 +- **差异查看器**:查看 Checkpoints 之间的确切变化 + +### 📝 **CLAUDE.md 管理** +- **内置编辑器**:直接在应用内编辑 CLAUDE.md 文件 +- **实时预览**:实时查看 Markdown 渲染效果 +- **Project 扫描器**:查找 Projects 中的所有 CLAUDE.md 文件 +- **语法高亮**:完整的 Markdown 支持和语法高亮 + +### 🌐 **国际化** +- **多语言支持**:完整支持英语和简体中文 +- **轻松切换语言**:在设置中一键更改语言 +- **技术术语保留**:技术术语(Agent、MCP Server、Token 等)保持英文以确保一致性 +- **可扩展**:使用 i18next 框架轻松添加更多语言 + +## 📖 使用方法 + +### 入门 + +1. **启动 opcode**:安装后打开应用程序 +2. **欢迎屏幕**:在 CC Agents 或 Projects 之间选择 +3. **首次设置**:opcode 将自动检测您的 `~/.claude` 目录 + +### 管理 Projects + +``` +Projects → 选择 Project → 查看 Sessions → 恢复或开始新 Session +``` + +- 点击任何 Project 查看其 Sessions +- 每个 Session 显示首条消息和时间戳 +- 直接恢复 Sessions 或开始新 Session + +### 创建 Agents + +``` +CC Agents → 创建 Agent → 配置 → 执行 +``` + +1. **设计您的 Agent**:设置名称、图标和 System Prompt +2. **配置模型**:在可用的 Claude 模型之间选择 +3. **设置权限**:配置文件读/写和网络访问 +4. **执行任务**:在任何 Project 上运行您的 Agent + +### 跟踪使用情况 + +``` +菜单 → 使用统计 → 查看分析 +``` + +- 按模型、Project 和日期监控成本 +- 导出数据用于报告 +- 设置使用警报(即将推出) + +### 使用 MCP Servers + +``` +菜单 → MCP Manager → 添加服务器 → 配置 +``` + +- 手动添加服务器或通过 JSON 添加 +- 从 Claude Desktop 配置导入 +- 使用前测试连接 + +### 更改语言 + +``` +菜单 → 设置 → 常规 → Language +``` + +- 在英语和简体中文之间切换 +- 更改立即生效 +- 语言偏好自动保存 + +## 🚀 安装 + +### 前提条件 + +- **Claude Code CLI**:从 [Claude 官方网站](https://claude.ai/code) 安装 + +### 发布版本即将推出 + +## 🔨 从源码构建 + +请参阅 [英文 README](README.md#-build-from-source) 了解详细的构建说明。 + +## 🛠️ 开发 + +### 技术栈 + +- **前端**:React 18 + TypeScript + Vite 6 +- **后端**:Rust + Tauri 2 +- **UI 框架**:Tailwind CSS v4 + shadcn/ui +- **数据库**:SQLite (通过 rusqlite) +- **包管理器**:Bun +- **国际化**:i18next + react-i18next + +### 开发命令 + +```bash +# 启动开发服务器 +bun run tauri dev + +# 仅运行前端 +bun run dev + +# 类型检查 +bunx tsc --noEmit + +# 运行 Rust 测试 +cd src-tauri && cargo test + +# 格式化代码 +cd src-tauri && cargo fmt + +# 提取翻译字符串 +bun run i18n:extract +``` + +## 🌐 贡献翻译 + +我们欢迎翻译贡献!请查看 [翻译贡献指南](docs/TRANSLATION_GUIDE.md) 了解如何添加或改进翻译。 + +## 🔒 安全 + +opcode 优先考虑您的隐私和安全: + +1. **进程隔离**:Agents 在独立进程中运行 +2. **权限控制**:为每个 Agent 配置文件和网络访问 +3. **本地存储**:所有数据保留在您的机器上 +4. **无遥测**:无数据收集或跟踪 +5. **开源**:通过开源代码实现完全透明 + +## 🤝 贡献 + +我们欢迎贡献!请查看我们的 [贡献指南](CONTRIBUTING.md) 了解详情。 + +### 贡献领域 + +- 🐛 Bug 修复和改进 +- ✨ 新功能和增强 +- 📚 文档改进 +- 🎨 UI/UX 增强 +- 🧪 测试覆盖 +- 🌐 国际化 + +## 📄 许可证 + +本项目采用 AGPL 许可证 - 详见 [LICENSE](LICENSE) 文件。 + +## 🙏 致谢 + +- 使用 [Tauri](https://tauri.app/) 构建 - 用于构建桌面应用的安全框架 +- [Claude](https://claude.ai) by Anthropic + +--- + +
+

+ Asterisk 用 ❤️ 制作 +

+

+ 报告 Bug + · + 请求功能 +

+
diff --git a/bun.lock b/bun.lock index 0152c93a4..8bc5e3730 100644 --- a/bun.lock +++ b/bun.lock @@ -1,5 +1,6 @@ { "lockfileVersion": 1, + "configVersion": 0, "workspaces": { "": { "name": "opcode", @@ -18,11 +19,11 @@ "@tailwindcss/cli": "^4.1.8", "@tailwindcss/vite": "^4.1.8", "@tanstack/react-virtual": "^3.13.10", - "@tauri-apps/api": "^2.1.1", - "@tauri-apps/plugin-dialog": "^2.0.2", - "@tauri-apps/plugin-global-shortcut": "^2.0.0", + "@tauri-apps/api": "~2.8.0", + "@tauri-apps/plugin-dialog": "~2.4.0", + "@tauri-apps/plugin-global-shortcut": "~2.3.0", "@tauri-apps/plugin-opener": "^2", - "@tauri-apps/plugin-shell": "^2.0.1", + "@tauri-apps/plugin-shell": "~2.3.0", "@types/diff": "^8.0.0", "@types/react-syntax-highlighter": "^15.5.13", "@uiw/react-md-editor": "^4.0.7", @@ -33,11 +34,14 @@ "diff": "^8.0.2", "framer-motion": "^12.0.0-alpha.1", "html2canvas": "^1.4.1", + "i18next": "^25.8.0", + "i18next-browser-languagedetector": "^8.2.0", "lucide-react": "^0.468.0", "posthog-js": "^1.258.3", "react": "^18.3.1", "react-dom": "^18.3.1", "react-hook-form": "^7.54.2", + "react-i18next": "^16.5.4", "react-markdown": "^9.0.3", "react-syntax-highlighter": "^15.6.1", "recharts": "^2.14.1", @@ -48,16 +52,21 @@ "zustand": "^5.0.6", }, "devDependencies": { - "@tauri-apps/cli": "^2.7.1", + "@tauri-apps/cli": "~2.8.0", "@types/node": "^22.15.30", "@types/react": "^18.3.1", "@types/react-dom": "^18.3.1", "@types/sharp": "^0.32.0", "@vitejs/plugin-react": "^4.3.4", + "i18next-parser": "^9.3.0", "sharp": "^0.34.2", "typescript": "~5.6.2", "vite": "^6.0.3", }, + "optionalDependencies": { + "@esbuild/linux-x64": "^0.25.6", + "@rollup/rollup-linux-x64-gnu": "^4.45.1", + }, }, }, "trustedDependencies": [ @@ -97,7 +106,7 @@ "@babel/plugin-transform-react-jsx-source": ["@babel/plugin-transform-react-jsx-source@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw=="], - "@babel/runtime": ["@babel/runtime@7.27.6", "", {}, "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q=="], + "@babel/runtime": ["@babel/runtime@7.28.6", "", {}, "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA=="], "@babel/template": ["@babel/template@7.27.2", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/parser": "^7.27.2", "@babel/types": "^7.27.1" } }, "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw=="], @@ -139,7 +148,7 @@ "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.5", "", { "os": "linux", "cpu": "s390x" }, "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ=="], - "@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.5", "", { "os": "linux", "cpu": "x64" }, "sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw=="], + "@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.12", "", { "os": "linux", "cpu": "x64" }, "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw=="], "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.5", "", { "os": "none", "cpu": "arm64" }, "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw=="], @@ -165,6 +174,8 @@ "@floating-ui/utils": ["@floating-ui/utils@0.2.9", "", {}, "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg=="], + "@gulpjs/to-absolute-glob": ["@gulpjs/to-absolute-glob@4.0.0", "", { "dependencies": { "is-negated-glob": "^1.0.0" } }, "sha512-kjotm7XJrJ6v+7knhPaRgaT6q8F8K2jiafwYdNHLzmV0uGLuZY43FK6smNSHUPrhq5kX2slCUy+RGG/xGqmIKA=="], + "@hookform/resolvers": ["@hookform/resolvers@3.10.0", "", { "peerDependencies": { "react-hook-form": "^7.0.0" } }, "sha512-79Dv+3mDF7i+2ajj7SkypSKHhl1cbln1OGavqrsF7p6mbUv11xpqpacPsGDCTRvCSjEEIez2ef1NveSVL3b0Ag=="], "@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.34.2", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.1.0" }, "os": "darwin", "cpu": "arm64" }, "sha512-OfXHZPppddivUJnqyKoi5YVeHRkkNE2zUFT2gbpKxp/JZCFYEYubnMg+gOp6lWfasPrTS+KPosKqdI+ELYVDtg=="], @@ -209,6 +220,8 @@ "@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.34.2", "", { "os": "win32", "cpu": "x64" }, "sha512-aUdT6zEYtDKCaxkofmmJDJYGCf0+pJg3eU9/oBuqvEeoB9dKI6ZLc/1iLJCTuJQDO4ptntAlkUmHgGjyuobZbw=="], + "@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="], + "@isaacs/fs-minipass": ["@isaacs/fs-minipass@4.0.1", "", { "dependencies": { "minipass": "^7.0.4" } }, "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w=="], "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.8", "", { "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA=="], @@ -249,6 +262,8 @@ "@parcel/watcher-win32-x64": ["@parcel/watcher-win32-x64@2.5.1", "", { "os": "win32", "cpu": "x64" }, "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA=="], + "@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="], + "@radix-ui/number": ["@radix-ui/number@1.1.1", "", {}, "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g=="], "@radix-ui/primitive": ["@radix-ui/primitive@1.1.2", "", {}, "sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA=="], @@ -357,7 +372,7 @@ "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.43.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-QmNIAqDiEMEvFV15rsSnjoSmO0+eJLoKRD9EAa9rrYNwO/XRCtOGM3A5A0X+wmG+XRrw9Fxdsw+LnyYiZWWcVw=="], - "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.43.0", "", { "os": "linux", "cpu": "x64" }, "sha512-jAHr/S0iiBtFyzjhOkAics/2SrXE092qyqEg96e90L3t9Op8OTzS6+IX0Fy5wCt2+KqeHAkti+eitV0wvblEoQ=="], + "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.57.1", "", { "os": "linux", "cpu": "x64" }, "sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg=="], "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.43.0", "", { "os": "linux", "cpu": "x64" }, "sha512-3yATWgdeXyuHtBhrLt98w+5fKurdqvs8B53LaoKD7P7H7FKOONLsBVMNl9ghPQZQuYcceV5CDyPfyfGpMWD9mQ=="], @@ -403,39 +418,39 @@ "@tanstack/virtual-core": ["@tanstack/virtual-core@3.13.10", "", {}, "sha512-sPEDhXREou5HyZYqSWIqdU580rsF6FGeN7vpzijmP3KTiOGjOMZASz4Y6+QKjiFQwhWrR58OP8izYaNGVxvViA=="], - "@tauri-apps/api": ["@tauri-apps/api@2.5.0", "", {}, "sha512-Ldux4ip+HGAcPUmuLT8EIkk6yafl5vK0P0c0byzAKzxJh7vxelVtdPONjfgTm96PbN24yjZNESY8CKo8qniluA=="], + "@tauri-apps/api": ["@tauri-apps/api@2.8.0", "", {}, "sha512-ga7zdhbS2GXOMTIZRT0mYjKJtR9fivsXzsyq5U3vjDL0s6DTMwYRm0UHNjzTY5dh4+LSC68Sm/7WEiimbQNYlw=="], - "@tauri-apps/cli": ["@tauri-apps/cli@2.7.1", "", { "optionalDependencies": { "@tauri-apps/cli-darwin-arm64": "2.7.1", "@tauri-apps/cli-darwin-x64": "2.7.1", "@tauri-apps/cli-linux-arm-gnueabihf": "2.7.1", "@tauri-apps/cli-linux-arm64-gnu": "2.7.1", "@tauri-apps/cli-linux-arm64-musl": "2.7.1", "@tauri-apps/cli-linux-riscv64-gnu": "2.7.1", "@tauri-apps/cli-linux-x64-gnu": "2.7.1", "@tauri-apps/cli-linux-x64-musl": "2.7.1", "@tauri-apps/cli-win32-arm64-msvc": "2.7.1", "@tauri-apps/cli-win32-ia32-msvc": "2.7.1", "@tauri-apps/cli-win32-x64-msvc": "2.7.1" }, "bin": { "tauri": "tauri.js" } }, "sha512-RcGWR4jOUEl92w3uvI0h61Llkfj9lwGD1iwvDRD2isMrDhOzjeeeVn9aGzeW1jubQ/kAbMYfydcA4BA0Cy733Q=="], + "@tauri-apps/cli": ["@tauri-apps/cli@2.8.4", "", { "optionalDependencies": { "@tauri-apps/cli-darwin-arm64": "2.8.4", "@tauri-apps/cli-darwin-x64": "2.8.4", "@tauri-apps/cli-linux-arm-gnueabihf": "2.8.4", "@tauri-apps/cli-linux-arm64-gnu": "2.8.4", "@tauri-apps/cli-linux-arm64-musl": "2.8.4", "@tauri-apps/cli-linux-riscv64-gnu": "2.8.4", "@tauri-apps/cli-linux-x64-gnu": "2.8.4", "@tauri-apps/cli-linux-x64-musl": "2.8.4", "@tauri-apps/cli-win32-arm64-msvc": "2.8.4", "@tauri-apps/cli-win32-ia32-msvc": "2.8.4", "@tauri-apps/cli-win32-x64-msvc": "2.8.4" }, "bin": { "tauri": "tauri.js" } }, "sha512-ejUZBzuQRcjFV+v/gdj/DcbyX/6T4unZQjMSBZwLzP/CymEjKcc2+Fc8xTORThebHDUvqoXMdsCZt8r+hyN15g=="], - "@tauri-apps/cli-darwin-arm64": ["@tauri-apps/cli-darwin-arm64@2.7.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-j2NXQN6+08G03xYiyKDKqbCV2Txt+hUKg0a8hYr92AmoCU8fgCjHyva/p16lGFGUG3P2Yu0xiNe1hXL9ZuRMzA=="], + "@tauri-apps/cli-darwin-arm64": ["@tauri-apps/cli-darwin-arm64@2.8.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-BKu8HRkYV01SMTa7r4fLx+wjgtRK8Vep7lmBdHDioP6b8XH3q2KgsAyPWfEZaZIkZ2LY4SqqGARaE9oilNe0oA=="], - "@tauri-apps/cli-darwin-x64": ["@tauri-apps/cli-darwin-x64@2.7.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-CdYAefeM35zKsc91qIyKzbaO7FhzTyWKsE8hj7tEJ1INYpoh1NeNNyL/NSEA3Nebi5ilugioJ5tRK8ZXG8y3gw=="], + "@tauri-apps/cli-darwin-x64": ["@tauri-apps/cli-darwin-x64@2.8.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-imb9PfSd/7G6VAO7v1bQ2A3ZH4NOCbhGJFLchxzepGcXf9NKkfun157JH9mko29K6sqAwuJ88qtzbKCbWJTH9g=="], - "@tauri-apps/cli-linux-arm-gnueabihf": ["@tauri-apps/cli-linux-arm-gnueabihf@2.7.1", "", { "os": "linux", "cpu": "arm" }, "sha512-dnvyJrTA1UJxJjQ8q1N/gWomjP8Twij1BUQu2fdcT3OPpqlrbOk5R1yT0oD/721xoKNjroB5BXCsmmlykllxNg=="], + "@tauri-apps/cli-linux-arm-gnueabihf": ["@tauri-apps/cli-linux-arm-gnueabihf@2.8.4", "", { "os": "linux", "cpu": "arm" }, "sha512-Ml215UnDdl7/fpOrF1CNovym/KjtUbCuPgrcZ4IhqUCnhZdXuphud/JT3E8X97Y03TZ40Sjz8raXYI2ET0exzw=="], - "@tauri-apps/cli-linux-arm64-gnu": ["@tauri-apps/cli-linux-arm64-gnu@2.7.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-FtBW6LJPNRTws3qyUc294AqCWU91l/H0SsFKq6q4Q45MSS4x6wxLxou8zB53tLDGEPx3JSoPLcDaSfPlSbyujQ=="], + "@tauri-apps/cli-linux-arm64-gnu": ["@tauri-apps/cli-linux-arm64-gnu@2.8.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-pbcgBpMyI90C83CxE5REZ9ODyIlmmAPkkJXtV398X3SgZEIYy5TACYqlyyv2z5yKgD8F8WH4/2fek7+jH+ZXAw=="], - "@tauri-apps/cli-linux-arm64-musl": ["@tauri-apps/cli-linux-arm64-musl@2.7.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-/HXY0t4FHkpFzjeYS5c16mlA6z0kzn5uKLWptTLTdFSnYpr8FCnOP4Sdkvm2TDQPF2ERxXtNCd+WR/jQugbGnA=="], + "@tauri-apps/cli-linux-arm64-musl": ["@tauri-apps/cli-linux-arm64-musl@2.8.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-zumFeaU1Ws5Ay872FTyIm7z8kfzEHu8NcIn8M6TxbJs0a7GRV21KBdpW1zNj2qy7HynnpQCqjAYXTUUmm9JAOw=="], - "@tauri-apps/cli-linux-riscv64-gnu": ["@tauri-apps/cli-linux-riscv64-gnu@2.7.1", "", { "os": "linux", "cpu": "none" }, "sha512-GeW5lVI2GhhnaYckiDzstG2j2Jwlud5d2XefRGwlOK+C/bVGLT1le8MNPYK8wgRlpeK8fG1WnJJYD6Ke7YQ8bg=="], + "@tauri-apps/cli-linux-riscv64-gnu": ["@tauri-apps/cli-linux-riscv64-gnu@2.8.4", "", { "os": "linux", "cpu": "none" }, "sha512-qiqbB3Zz6IyO201f+1ojxLj65WYj8mixL5cOMo63nlg8CIzsP23cPYUrx1YaDPsCLszKZo7tVs14pc7BWf+/aQ=="], - "@tauri-apps/cli-linux-x64-gnu": ["@tauri-apps/cli-linux-x64-gnu@2.7.1", "", { "os": "linux", "cpu": "x64" }, "sha512-DprxKQkPxIPYwUgg+cscpv2lcIUhn2nxEPlk0UeaiV9vATxCXyytxr1gLcj3xgjGyNPlM0MlJyYaPy1JmRg1cA=="], + "@tauri-apps/cli-linux-x64-gnu": ["@tauri-apps/cli-linux-x64-gnu@2.8.4", "", { "os": "linux", "cpu": "x64" }, "sha512-TaqaDd9Oy6k45Hotx3pOf+pkbsxLaApv4rGd9mLuRM1k6YS/aw81YrsMryYPThrxrScEIUcmNIHaHsLiU4GMkw=="], - "@tauri-apps/cli-linux-x64-musl": ["@tauri-apps/cli-linux-x64-musl@2.7.1", "", { "os": "linux", "cpu": "x64" }, "sha512-KLlq3kOK7OUyDR757c0zQjPULpGZpLhNB0lZmZpHXvoOUcqZoCXJHh4dT/mryWZJp5ilrem5l8o9ngrDo0X1AA=="], + "@tauri-apps/cli-linux-x64-musl": ["@tauri-apps/cli-linux-x64-musl@2.8.4", "", { "os": "linux", "cpu": "x64" }, "sha512-ot9STAwyezN8w+bBHZ+bqSQIJ0qPZFlz/AyscpGqB/JnJQVDFQcRDmUPFEaAtt2UUHSWzN3GoTJ5ypqLBp2WQA=="], - "@tauri-apps/cli-win32-arm64-msvc": ["@tauri-apps/cli-win32-arm64-msvc@2.7.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-dH7KUjKkSypCeWPiainHyXoES3obS+JIZVoSwSZfKq2gWgs48FY3oT0hQNYrWveE+VR4VoR3b/F3CPGbgFvksA=="], + "@tauri-apps/cli-win32-arm64-msvc": ["@tauri-apps/cli-win32-arm64-msvc@2.8.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-+2aJ/g90dhLiOLFSD1PbElXX3SoMdpO7HFPAZB+xot3CWlAZD1tReUFy7xe0L5GAR16ZmrxpIDM9v9gn5xRy/w=="], - "@tauri-apps/cli-win32-ia32-msvc": ["@tauri-apps/cli-win32-ia32-msvc@2.7.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-1oeibfyWQPVcijOrTg709qhbXArjX3x1MPjrmA5anlygwrbByxLBcLXvotcOeULFcnH2FYUMMLLant8kgvwE5A=="], + "@tauri-apps/cli-win32-ia32-msvc": ["@tauri-apps/cli-win32-ia32-msvc@2.8.4", "", { "os": "win32", "cpu": "ia32" }, "sha512-yj7WDxkL1t9Uzr2gufQ1Hl7hrHuFKTNEOyascbc109EoiAqCp0tgZ2IykQqOZmZOHU884UAWI1pVMqBhS/BfhA=="], - "@tauri-apps/cli-win32-x64-msvc": ["@tauri-apps/cli-win32-x64-msvc@2.7.1", "", { "os": "win32", "cpu": "x64" }, "sha512-D7Q9kDObutuirCNLxYQ7KAg2Xxg99AjcdYz/KuMw5HvyEPbkC9Q7JL0vOrQOrHEHxIQ2lYzFOZvKKoC2yyqXcg=="], + "@tauri-apps/cli-win32-x64-msvc": ["@tauri-apps/cli-win32-x64-msvc@2.8.4", "", { "os": "win32", "cpu": "x64" }, "sha512-XuvGB4ehBdd7QhMZ9qbj/8icGEatDuBNxyYHbLKsTYh90ggUlPa/AtaqcC1Fo69lGkTmq9BOKrs1aWSi7xDonA=="], - "@tauri-apps/plugin-dialog": ["@tauri-apps/plugin-dialog@2.2.2", "", { "dependencies": { "@tauri-apps/api": "^2.0.0" } }, "sha512-Pm9qnXQq8ZVhAMFSEPwxvh+nWb2mk7LASVlNEHYaksHvcz8P6+ElR5U5dNL9Ofrm+uwhh1/gYKWswK8JJJAh6A=="], + "@tauri-apps/plugin-dialog": ["@tauri-apps/plugin-dialog@2.4.2", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-lNIn5CZuw8WZOn8zHzmFmDSzg5zfohWoa3mdULP0YFh/VogVdMVWZPcWSHlydsiJhRQYaTNSYKN7RmZKE2lCYQ=="], - "@tauri-apps/plugin-global-shortcut": ["@tauri-apps/plugin-global-shortcut@2.2.1", "", { "dependencies": { "@tauri-apps/api": "^2.0.0" } }, "sha512-b64/TI1t5LIi2JY4OWlYjZpPRq60T5GVVL/no27sUuxaNUZY8dVtwsMtDUgxUpln2yR+P2PJsYlqY5V8sLSxEw=="], + "@tauri-apps/plugin-global-shortcut": ["@tauri-apps/plugin-global-shortcut@2.3.1", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-vr40W2N6G63dmBPaha1TsBQLLURXG538RQbH5vAm0G/ovVZyXJrmZR1HF1W+WneNloQvwn4dm8xzwpEXRW560g=="], "@tauri-apps/plugin-opener": ["@tauri-apps/plugin-opener@2.3.0", "", { "dependencies": { "@tauri-apps/api": "^2.0.0" } }, "sha512-yAbauwp8BCHIhhA48NN8rEf6OtfZBPCgTOCa10gmtoVCpmic5Bq+1Ba7C+NZOjogedkSiV7hAotjYnnbUVmYrw=="], - "@tauri-apps/plugin-shell": ["@tauri-apps/plugin-shell@2.2.2", "", { "dependencies": { "@tauri-apps/api": "^2.0.0" } }, "sha512-fg9XKWfzRQsN8p+Zrk82WeHvXFvGVnG0/mTlujQdLWNnO5cM6WD9qCrHbFytScVS+WhmRAkuypQPcxeKKl3VBg=="], + "@tauri-apps/plugin-shell": ["@tauri-apps/plugin-shell@2.3.4", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-ktsRWf8wHLD17aZEyqE8c5x98eNAuTizR1FSX475zQ4TxaiJnhwksLygQz+AGwckJL5bfEP13nWrlTNQJUpKpA=="], "@types/babel__core": ["@types/babel__core@7.20.5", "", { "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" } }, "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA=="], @@ -475,6 +490,8 @@ "@types/mdast": ["@types/mdast@4.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA=="], + "@types/minimatch": ["@types/minimatch@3.0.5", "", {}, "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ=="], + "@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="], "@types/node": ["@types/node@22.15.32", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-3jigKqgSjsH6gYZv2nEsqdXfZqIFGAV36XYYjf9KGZ3PSG+IhLecqPnI310RvjutyMwifE2hhhNEklOUrvx/wA=="], @@ -491,6 +508,8 @@ "@types/sharp": ["@types/sharp@0.32.0", "", { "dependencies": { "sharp": "*" } }, "sha512-OOi3kL+FZDnPhVzsfD37J88FNeZh6gQsGcLc95NbeURRGvmSjeXiDcyWzF2o3yh/gQAUn2uhh/e+CPCa5nwAxw=="], + "@types/symlink-or-copy": ["@types/symlink-or-copy@1.2.2", "", {}, "sha512-MQ1AnmTLOncwEf9IVU+B2e4Hchrku5N67NkgcAHW0p3sdzPe0FNMANxEm6OJUzPniEQGkeT3OROLlCwZJLWFZA=="], + "@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="], "@uiw/copy-to-clipboard": ["@uiw/copy-to-clipboard@1.0.17", "", {}, "sha512-O2GUHV90Iw2VrSLVLK0OmNIMdZ5fgEg4NhvtwINsX+eZ/Wf6DWD0TdsK9xwV7dNRnK/UI2mQtl0a2/kRgm1m1A=="], @@ -503,22 +522,52 @@ "@vitejs/plugin-react": ["@vitejs/plugin-react@4.5.2", "", { "dependencies": { "@babel/core": "^7.27.4", "@babel/plugin-transform-react-jsx-self": "^7.27.1", "@babel/plugin-transform-react-jsx-source": "^7.27.1", "@rolldown/pluginutils": "1.0.0-beta.11", "@types/babel__core": "^7.20.5", "react-refresh": "^0.17.0" }, "peerDependencies": { "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0" } }, "sha512-QNVT3/Lxx99nMQWJWF7K4N6apUEuT0KlZA3mx/mVaoGj3smm/8rc8ezz15J1pcbcjDK0V15rpHetVfya08r76Q=="], + "ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], + + "ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], + "ansi-to-html": ["ansi-to-html@0.7.2", "", { "dependencies": { "entities": "^2.2.0" }, "bin": { "ansi-to-html": "bin/ansi-to-html" } }, "sha512-v6MqmEpNlxF+POuyhKkidusCHWWkaLcGRURzivcU3I9tv7k4JVhFcnukrM5Rlk2rUywdZuzYAZ+kbZqWCnfN3g=="], + "anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="], + + "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], + "aria-hidden": ["aria-hidden@1.2.6", "", { "dependencies": { "tslib": "^2.0.0" } }, "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA=="], + "b4a": ["b4a@1.7.3", "", { "peerDependencies": { "react-native-b4a": "*" }, "optionalPeers": ["react-native-b4a"] }, "sha512-5Q2mfq2WfGuFp3uS//0s6baOJLMoVduPYVeNmDYxu5OUA1/cBfvr2RIS7vi62LdNj/urk1hfmj867I3qt6uZ7Q=="], + "bail": ["bail@2.0.2", "", {}, "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw=="], + "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + + "bare-events": ["bare-events@2.8.2", "", { "peerDependencies": { "bare-abort-controller": "*" }, "optionalPeers": ["bare-abort-controller"] }, "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ=="], + "base64-arraybuffer": ["base64-arraybuffer@1.0.2", "", {}, "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ=="], + "base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="], + "bcp-47-match": ["bcp-47-match@2.0.3", "", {}, "sha512-JtTezzbAibu8G0R9op9zb3vcWZd9JF6M0xOYGPn0fNCd7wOpRB1mU2mH9T8gaBGbAAyIIVgB2G7xG0GP98zMAQ=="], + "bl": ["bl@5.1.0", "", { "dependencies": { "buffer": "^6.0.3", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ=="], + "boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="], + "brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], + "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], + "broccoli-node-api": ["broccoli-node-api@1.7.0", "", {}, "sha512-QIqLSVJWJUVOhclmkmypJJH9u9s/aWH4+FH6Q6Ju5l+Io4dtwqdPUNmDfw40o6sxhbZHhqGujDJuHTML1wG8Yw=="], + + "broccoli-node-info": ["broccoli-node-info@2.2.0", "", {}, "sha512-VabSGRpKIzpmC+r+tJueCE5h8k6vON7EIMMWu6d/FyPdtijwLQ7QvzShEw+m3mHoDzUaj/kiZsDYrS8X2adsBg=="], + + "broccoli-output-wrapper": ["broccoli-output-wrapper@3.2.5", "", { "dependencies": { "fs-extra": "^8.1.0", "heimdalljs-logger": "^0.1.10", "symlink-or-copy": "^1.2.0" } }, "sha512-bQAtwjSrF4Nu0CK0JOy5OZqw9t5U0zzv2555EA/cF8/a8SLDTIetk9UgrtMVw7qKLKdSpOZ2liZNeZZDaKgayw=="], + + "broccoli-plugin": ["broccoli-plugin@4.0.7", "", { "dependencies": { "broccoli-node-api": "^1.7.0", "broccoli-output-wrapper": "^3.2.5", "fs-merger": "^3.2.1", "promise-map-series": "^0.3.0", "quick-temp": "^0.1.8", "rimraf": "^3.0.2", "symlink-or-copy": "^1.3.1" } }, "sha512-a4zUsWtA1uns1K7p9rExYVYG99rdKeGRymW0qOCNkvDPHQxVi3yVyJHhQbM3EZwdt2E0mnhr5e0c/bPpJ7p3Wg=="], + "browserslist": ["browserslist@4.25.0", "", { "dependencies": { "caniuse-lite": "^1.0.30001718", "electron-to-chromium": "^1.5.160", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.3" }, "bin": { "browserslist": "cli.js" } }, "sha512-PJ8gYKeS5e/whHBh8xrwYK+dAvEj7JXtz6uTucnMRB8OiGTsKccFekoRrjajPBHV8oOY+2tI4uxeceSimKwMFA=="], + "buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="], + "caniuse-lite": ["caniuse-lite@1.0.30001723", "", {}, "sha512-1R/elMjtehrFejxwmexeXAtae5UO9iSyFn6G/I806CYC/BLyyBk1EPhrKBkWhy6wM6Xnm47dSJQec+tLJ39WHw=="], "ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="], @@ -531,10 +580,16 @@ "character-reference-invalid": ["character-reference-invalid@1.1.4", "", {}, "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg=="], + "cheerio": ["cheerio@1.2.0", "", { "dependencies": { "cheerio-select": "^2.1.0", "dom-serializer": "^2.0.0", "domhandler": "^5.0.3", "domutils": "^3.2.2", "encoding-sniffer": "^0.2.1", "htmlparser2": "^10.1.0", "parse5": "^7.3.0", "parse5-htmlparser2-tree-adapter": "^7.1.0", "parse5-parser-stream": "^7.1.2", "undici": "^7.19.0", "whatwg-mimetype": "^4.0.0" } }, "sha512-WDrybc/gKFpTYQutKIK6UvfcuxijIZfMfXaYm8NMsPQxSYvf+13fXUJ4rztGGbJcBQ/GF55gvrZ0Bc0bj/mqvg=="], + + "cheerio-select": ["cheerio-select@2.1.0", "", { "dependencies": { "boolbase": "^1.0.0", "css-select": "^5.1.0", "css-what": "^6.1.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3", "domutils": "^3.0.1" } }, "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g=="], + "chownr": ["chownr@3.0.0", "", {}, "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g=="], "class-variance-authority": ["class-variance-authority@0.7.1", "", { "dependencies": { "clsx": "^2.1.1" } }, "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg=="], + "clone": ["clone@2.1.2", "", {}, "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w=="], + "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="], "color": ["color@4.2.3", "", { "dependencies": { "color-convert": "^2.0.1", "color-string": "^1.9.0" } }, "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A=="], @@ -545,16 +600,30 @@ "color-string": ["color-string@1.9.1", "", { "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg=="], + "colors": ["colors@1.4.0", "", {}, "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA=="], + "comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="], + "commander": ["commander@12.1.0", "", {}, "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA=="], + + "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], + "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="], "core-js": ["core-js@3.44.0", "", {}, "sha512-aFCtd4l6GvAXwVEh3XbbVqJGHDJt0OZRa+5ePGx3LLwi12WfexqQxcsohb2wgsa/92xtl19Hd66G/L+TaAxDMw=="], + "core-util-is": ["core-util-is@1.0.3", "", {}, "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="], + + "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], + "css-line-break": ["css-line-break@2.1.0", "", { "dependencies": { "utrie": "^1.0.2" } }, "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w=="], + "css-select": ["css-select@5.2.2", "", { "dependencies": { "boolbase": "^1.0.0", "css-what": "^6.1.0", "domhandler": "^5.0.2", "domutils": "^3.0.1", "nth-check": "^2.0.1" } }, "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw=="], + "css-selector-parser": ["css-selector-parser@3.1.2", "", {}, "sha512-WfUcL99xWDs7b3eZPoRszWVfbNo8ErCF15PTvVROjkShGlAfjIkG6hlfj/sl6/rfo5Q9x9ryJ3VqVnAZDA+gcw=="], + "css-what": ["css-what@6.2.2", "", {}, "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA=="], + "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="], "d3-array": ["d3-array@3.2.4", "", { "dependencies": { "internmap": "1 - 2" } }, "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg=="], @@ -601,12 +670,30 @@ "dom-helpers": ["dom-helpers@5.2.1", "", { "dependencies": { "@babel/runtime": "^7.8.7", "csstype": "^3.0.2" } }, "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA=="], + "dom-serializer": ["dom-serializer@2.0.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", "entities": "^4.2.0" } }, "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg=="], + + "domelementtype": ["domelementtype@2.3.0", "", {}, "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="], + + "domhandler": ["domhandler@5.0.3", "", { "dependencies": { "domelementtype": "^2.3.0" } }, "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w=="], + + "domutils": ["domutils@3.2.2", "", { "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3" } }, "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw=="], + + "eastasianwidth": ["eastasianwidth@0.2.0", "", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="], + "electron-to-chromium": ["electron-to-chromium@1.5.169", "", {}, "sha512-q7SQx6mkLy0GTJK9K9OiWeaBMV4XQtBSdf6MJUzDB/H/5tFXfIiX38Lci1Kl6SsgiEhz1SQI1ejEOU5asWEhwQ=="], + "emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], + + "encoding-sniffer": ["encoding-sniffer@0.2.1", "", { "dependencies": { "iconv-lite": "^0.6.3", "whatwg-encoding": "^3.1.1" } }, "sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw=="], + "enhanced-resolve": ["enhanced-resolve@5.18.1", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg=="], + "ensure-posix-path": ["ensure-posix-path@1.1.1", "", {}, "sha512-VWU0/zXzVbeJNXvME/5EmLuEj2TauvoaTz6aFYK1Z92JCBlDlZ3Gu0tuGR42kpW1754ywTs+QB0g5TP0oj9Zaw=="], + "entities": ["entities@2.2.0", "", {}, "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A=="], + "eol": ["eol@0.9.1", "", {}, "sha512-Ds/TEoZjwggRoz/Q2O7SE3i4Jm66mqTDfmdHdq/7DKVk3bro9Q8h6WdXKdPqFLMoqxrDK5SVRzHVPOS6uuGtrg=="], + "esbuild": ["esbuild@0.25.5", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.5", "@esbuild/android-arm": "0.25.5", "@esbuild/android-arm64": "0.25.5", "@esbuild/android-x64": "0.25.5", "@esbuild/darwin-arm64": "0.25.5", "@esbuild/darwin-x64": "0.25.5", "@esbuild/freebsd-arm64": "0.25.5", "@esbuild/freebsd-x64": "0.25.5", "@esbuild/linux-arm": "0.25.5", "@esbuild/linux-arm64": "0.25.5", "@esbuild/linux-ia32": "0.25.5", "@esbuild/linux-loong64": "0.25.5", "@esbuild/linux-mips64el": "0.25.5", "@esbuild/linux-ppc64": "0.25.5", "@esbuild/linux-riscv64": "0.25.5", "@esbuild/linux-s390x": "0.25.5", "@esbuild/linux-x64": "0.25.5", "@esbuild/netbsd-arm64": "0.25.5", "@esbuild/netbsd-x64": "0.25.5", "@esbuild/openbsd-arm64": "0.25.5", "@esbuild/openbsd-x64": "0.25.5", "@esbuild/sunos-x64": "0.25.5", "@esbuild/win32-arm64": "0.25.5", "@esbuild/win32-ia32": "0.25.5", "@esbuild/win32-x64": "0.25.5" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ=="], "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], @@ -617,10 +704,16 @@ "eventemitter3": ["eventemitter3@4.0.7", "", {}, "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="], + "events-universal": ["events-universal@1.0.1", "", { "dependencies": { "bare-events": "^2.7.0" } }, "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw=="], + "extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="], "fast-equals": ["fast-equals@5.2.2", "", {}, "sha512-V7/RktU11J3I36Nwq2JnZEM7tNm17eBJz+u25qdxBZeCKiX6BkVSZQjwWIr+IobgnZy+ag73tTZgZi7tr0LrBw=="], + "fast-fifo": ["fast-fifo@1.3.2", "", {}, "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ=="], + + "fastq": ["fastq@1.20.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="], + "fault": ["fault@1.0.4", "", { "dependencies": { "format": "^0.2.0" } }, "sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA=="], "fdir": ["fdir@6.4.6", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w=="], @@ -629,10 +722,22 @@ "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], + "foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="], + "format": ["format@0.2.2", "", {}, "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww=="], "framer-motion": ["framer-motion@12.18.1", "", { "dependencies": { "motion-dom": "^12.18.1", "motion-utils": "^12.18.1", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-6o4EDuRPLk4LSZ1kRnnEOurbQ86MklVk+Y1rFBUKiF+d2pCdvMjWVu0ZkyMVCTwl5UyTH2n/zJEJx+jvTYuxow=="], + "fs-extra": ["fs-extra@11.3.3", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg=="], + + "fs-merger": ["fs-merger@3.2.1", "", { "dependencies": { "broccoli-node-api": "^1.7.0", "broccoli-node-info": "^2.1.0", "fs-extra": "^8.0.1", "fs-tree-diff": "^2.0.1", "walk-sync": "^2.2.0" } }, "sha512-AN6sX12liy0JE7C2evclwoo0aCG3PFulLjrTLsJpWh/2mM+DinhpSGqYLbHBBbIW1PLRNcFhJG8Axtz8mQW3ug=="], + + "fs-mkdirp-stream": ["fs-mkdirp-stream@2.0.1", "", { "dependencies": { "graceful-fs": "^4.2.8", "streamx": "^2.12.0" } }, "sha512-UTOY+59K6IA94tec8Wjqm0FSh5OVudGNB0NL/P6fB3HiE3bYOY3VYBGijsnOHNkQSwC1FKkU77pmq7xp9CskLw=="], + + "fs-tree-diff": ["fs-tree-diff@2.0.1", "", { "dependencies": { "@types/symlink-or-copy": "^1.2.0", "heimdalljs-logger": "^0.1.7", "object-assign": "^4.1.0", "path-posix": "^1.0.0", "symlink-or-copy": "^1.1.8" } }, "sha512-x+CfAZ/lJHQqwlD64pYM5QxWjzWhSjroaVsr8PW831zOApL55qPibed0c+xebaLWVr2BnHFoHdrwOv8pzt8R5A=="], + + "fs.realpath": ["fs.realpath@1.0.0", "", {}, "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="], + "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], "gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="], @@ -641,10 +746,18 @@ "github-slugger": ["github-slugger@2.0.0", "", {}, "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw=="], + "glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], + + "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], + + "glob-stream": ["glob-stream@8.0.3", "", { "dependencies": { "@gulpjs/to-absolute-glob": "^4.0.0", "anymatch": "^3.1.3", "fastq": "^1.13.0", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", "is-negated-glob": "^1.0.0", "normalize-path": "^3.0.0", "streamx": "^2.12.5" } }, "sha512-fqZVj22LtFJkHODT+M4N1RJQ3TjnnQhfE9GwZI8qXscYarnhpip70poMldRnP8ipQ/w0B621kOhfc53/J9bd/A=="], + "globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="], "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], + "gulp-sort": ["gulp-sort@2.0.0", "", { "dependencies": { "through2": "^2.0.1" } }, "sha512-MyTel3FXOdh1qhw1yKhpimQrAmur9q1X0ZigLmCOxouQD+BD3za9/89O+HfbgBQvvh4igEbp0/PUWO+VqGYG1g=="], + "hast-util-from-html": ["hast-util-from-html@2.0.3", "", { "dependencies": { "@types/hast": "^3.0.0", "devlop": "^1.1.0", "hast-util-from-parse5": "^8.0.0", "parse5": "^7.0.0", "vfile": "^6.0.0", "vfile-message": "^4.0.0" } }, "sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw=="], "hast-util-from-parse5": ["hast-util-from-parse5@8.0.3", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "devlop": "^1.0.0", "hastscript": "^9.0.0", "property-information": "^7.0.0", "vfile": "^6.0.0", "vfile-location": "^5.0.0", "web-namespaces": "^2.0.0" } }, "sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg=="], @@ -673,16 +786,38 @@ "hastscript": ["hastscript@6.0.0", "", { "dependencies": { "@types/hast": "^2.0.0", "comma-separated-tokens": "^1.0.0", "hast-util-parse-selector": "^2.0.0", "property-information": "^5.0.0", "space-separated-tokens": "^1.0.0" } }, "sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w=="], + "heimdalljs": ["heimdalljs@0.2.6", "", { "dependencies": { "rsvp": "~3.2.1" } }, "sha512-o9bd30+5vLBvBtzCPwwGqpry2+n0Hi6H1+qwt6y+0kwRHGGF8TFIhJPmnuM0xO97zaKrDZMwO/V56fAnn8m/tA=="], + + "heimdalljs-logger": ["heimdalljs-logger@0.1.10", "", { "dependencies": { "debug": "^2.2.0", "heimdalljs": "^0.2.6" } }, "sha512-pO++cJbhIufVI/fmB/u2Yty3KJD0TqNPecehFae0/eps0hkZ3b4Zc/PezUMOpYuHFQbA7FxHZxa305EhmjLj4g=="], + "highlight.js": ["highlight.js@10.7.3", "", {}, "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A=="], "highlightjs-vue": ["highlightjs-vue@1.0.0", "", {}, "sha512-PDEfEF102G23vHmPhLyPboFCD+BkMGu+GuJe2d9/eH4FsCwvgBpnc9n0pGE+ffKdph38s6foEZiEjdgHdzp+IA=="], + "html-parse-stringify": ["html-parse-stringify@3.0.1", "", { "dependencies": { "void-elements": "3.1.0" } }, "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg=="], + "html-url-attributes": ["html-url-attributes@3.0.1", "", {}, "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ=="], "html-void-elements": ["html-void-elements@3.0.0", "", {}, "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg=="], "html2canvas": ["html2canvas@1.4.1", "", { "dependencies": { "css-line-break": "^2.1.0", "text-segmentation": "^1.0.3" } }, "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA=="], + "htmlparser2": ["htmlparser2@10.1.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.3", "domutils": "^3.2.2", "entities": "^7.0.1" } }, "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ=="], + + "i18next": ["i18next@25.8.0", "", { "dependencies": { "@babel/runtime": "^7.28.4" }, "peerDependencies": { "typescript": "^5" }, "optionalPeers": ["typescript"] }, "sha512-urrg4HMFFMQZ2bbKRK7IZ8/CTE7D8H4JRlAwqA2ZwDRFfdd0K/4cdbNNLgfn9mo+I/h9wJu61qJzH7jCFAhUZQ=="], + + "i18next-browser-languagedetector": ["i18next-browser-languagedetector@8.2.0", "", { "dependencies": { "@babel/runtime": "^7.23.2" } }, "sha512-P+3zEKLnOF0qmiesW383vsLdtQVyKtCNA9cjSoKCppTKPQVfKd2W8hbVo5ZhNJKDqeM7BOcvNoKJOjpHh4Js9g=="], + + "i18next-parser": ["i18next-parser@9.3.0", "", { "dependencies": { "@babel/runtime": "^7.25.0", "broccoli-plugin": "^4.0.7", "cheerio": "^1.0.0", "colors": "^1.4.0", "commander": "^12.1.0", "eol": "^0.9.1", "esbuild": "^0.25.0", "fs-extra": "^11.2.0", "gulp-sort": "^2.0.0", "i18next": "^23.5.1 || ^24.2.0", "js-yaml": "^4.1.0", "lilconfig": "^3.1.3", "rsvp": "^4.8.5", "sort-keys": "^5.0.0", "typescript": "^5.0.4", "vinyl": "^3.0.0", "vinyl-fs": "^4.0.0" }, "bin": { "i18next": "bin/cli.js" } }, "sha512-VaQqk/6nLzTFx1MDiCZFtzZXKKyBV6Dv0cJMFM/hOt4/BWHWRgYafzYfVQRUzotwUwjqeNCprWnutzD/YAGczg=="], + + "iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="], + + "ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], + + "inflight": ["inflight@1.0.6", "", { "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA=="], + + "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], + "inline-style-parser": ["inline-style-parser@0.2.4", "", {}, "sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q=="], "internmap": ["internmap@2.0.3", "", {}, "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg=="], @@ -697,22 +832,40 @@ "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], + "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], + "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], "is-hexadecimal": ["is-hexadecimal@1.0.4", "", {}, "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw=="], + "is-negated-glob": ["is-negated-glob@1.0.0", "", {}, "sha512-czXVVn/QEmgvej1f50BZ648vUI+em0xqMq2Sn+QncCLN4zj1UAxlT+kw/6ggQTOaZPd1HqKQGEqbpQVtJucWug=="], + "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], "is-plain-obj": ["is-plain-obj@4.1.0", "", {}, "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg=="], + "is-valid-glob": ["is-valid-glob@1.0.0", "", {}, "sha512-AhiROmoEFDSsjx8hW+5sGwgKVIORcXnrlAx/R0ZSeaPw70Vw0CqkGBBhHGL58Uox2eXnU1AnvXJl1XlyedO5bA=="], + + "isarray": ["isarray@1.0.0", "", {}, "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="], + + "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], + + "jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="], + "jiti": ["jiti@2.4.2", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A=="], "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], + "js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="], + "jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="], "json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="], + "jsonfile": ["jsonfile@6.2.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg=="], + + "lead": ["lead@4.0.0", "", {}, "sha512-DpMa59o5uGUWWjruMp71e6knmwKU3jRBBn1kjuLWN9EeIOxNeSAwvHf03WIl8g/ZMR2oSQC9ej3yeLBwdDc/pg=="], + "lightningcss": ["lightningcss@1.30.1", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-darwin-arm64": "1.30.1", "lightningcss-darwin-x64": "1.30.1", "lightningcss-freebsd-x64": "1.30.1", "lightningcss-linux-arm-gnueabihf": "1.30.1", "lightningcss-linux-arm64-gnu": "1.30.1", "lightningcss-linux-arm64-musl": "1.30.1", "lightningcss-linux-x64-gnu": "1.30.1", "lightningcss-linux-x64-musl": "1.30.1", "lightningcss-win32-arm64-msvc": "1.30.1", "lightningcss-win32-x64-msvc": "1.30.1" } }, "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg=="], "lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.30.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ=="], @@ -735,6 +888,8 @@ "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.30.1", "", { "os": "win32", "cpu": "x64" }, "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg=="], + "lilconfig": ["lilconfig@3.1.3", "", {}, "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw=="], + "lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="], "longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="], @@ -751,6 +906,8 @@ "markdown-table": ["markdown-table@3.0.4", "", {}, "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw=="], + "matcher-collection": ["matcher-collection@2.0.1", "", { "dependencies": { "@types/minimatch": "^3.0.3", "minimatch": "^3.0.2" } }, "sha512-daE62nS2ZQsDg9raM0IlZzLmI2u+7ZapXBwdoeBUKAYERPDDIc0qNqA8E0Rp2D+gspKR7BgIFP52GeujaGXWeQ=="], + "mdast-util-find-and-replace": ["mdast-util-find-and-replace@3.0.2", "", { "dependencies": { "@types/mdast": "^4.0.0", "escape-string-regexp": "^5.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg=="], "mdast-util-from-markdown": ["mdast-util-from-markdown@2.0.2", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "mdast-util-to-string": "^4.0.0", "micromark": "^4.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-decode-string": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA=="], @@ -839,12 +996,16 @@ "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], + "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], + "minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="], "minizlib": ["minizlib@3.0.2", "", { "dependencies": { "minipass": "^7.1.2" } }, "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA=="], "mkdirp": ["mkdirp@3.0.1", "", { "bin": { "mkdirp": "dist/cjs/src/bin.js" } }, "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg=="], + "mktemp": ["mktemp@2.0.2", "", {}, "sha512-Q9wJ/xhzeD9Wua1MwDN2v3ah3HENsUVSlzzL9Qw149cL9hHZkXtQGl3Eq36BbdLV+/qUwaP1WtJQ+H/+Oxso8g=="], + "motion-dom": ["motion-dom@12.18.1", "", { "dependencies": { "motion-utils": "^12.18.1" } }, "sha512-dR/4EYT23Snd+eUSLrde63Ws3oXQtJNw/krgautvTfwrN/2cHfCZMdu6CeTxVfRRWREW3Fy1f5vobRDiBb/q+w=="], "motion-utils": ["motion-utils@12.18.1", "", {}, "sha512-az26YDU4WoDP0ueAkUtABLk2BIxe28d8NH1qWT8jPGhPyf44XTdDUh8pDk9OPphaSrR9McgpcJlgwSOIw/sfkA=="], @@ -859,16 +1020,36 @@ "node-releases": ["node-releases@2.0.19", "", {}, "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw=="], + "normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="], + + "now-and-later": ["now-and-later@3.0.0", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-pGO4pzSdaxhWTGkfSfHx3hVzJVslFPwBp2Myq9MYN/ChfJZF87ochMAXnvz6/58RJSf5ik2q9tXprBBrk2cpcg=="], + "nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="], "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="], + "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="], + + "package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="], + "parse-entities": ["parse-entities@2.0.0", "", { "dependencies": { "character-entities": "^1.0.0", "character-entities-legacy": "^1.0.0", "character-reference-invalid": "^1.0.0", "is-alphanumerical": "^1.0.0", "is-decimal": "^1.0.0", "is-hexadecimal": "^1.0.0" } }, "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ=="], "parse-numeric-range": ["parse-numeric-range@1.3.0", "", {}, "sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ=="], "parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="], + "parse5-htmlparser2-tree-adapter": ["parse5-htmlparser2-tree-adapter@7.1.0", "", { "dependencies": { "domhandler": "^5.0.3", "parse5": "^7.0.0" } }, "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g=="], + + "parse5-parser-stream": ["parse5-parser-stream@7.1.2", "", { "dependencies": { "parse5": "^7.0.0" } }, "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow=="], + + "path-is-absolute": ["path-is-absolute@1.0.1", "", {}, "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="], + + "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], + + "path-posix": ["path-posix@1.0.0", "", {}, "sha512-1gJ0WpNIiYcQydgg3Ed8KzvIqTsDpNwq+cjBCssvBtuTWjEqY1AW+i+OepiEMqDCzyro9B2sLAe4RBPajMYFiA=="], + + "path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="], + "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], "picomatch": ["picomatch@4.0.2", "", {}, "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="], @@ -881,16 +1062,24 @@ "prismjs": ["prismjs@1.30.0", "", {}, "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw=="], + "process-nextick-args": ["process-nextick-args@2.0.1", "", {}, "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="], + + "promise-map-series": ["promise-map-series@0.3.0", "", {}, "sha512-3npG2NGhTc8BWBolLLf8l/92OxMGaRLbqvIh9wjCHhDXNvk4zsxaTaCpiCunW09qWPrN2zeNSNwRLVBrQQtutA=="], + "prop-types": ["prop-types@15.8.1", "", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="], "property-information": ["property-information@7.1.0", "", {}, "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ=="], + "quick-temp": ["quick-temp@0.1.9", "", { "dependencies": { "mktemp": "^2.0.1", "rimraf": "^5.0.10", "underscore.string": "~3.3.6" } }, "sha512-yI0h7tIhKVObn03kD+Ln9JFi4OljD28lfaOsTdfpTR0xzrhGOod+q66CjGafUqYX2juUfT9oHIGrTBBo22mkRA=="], + "react": ["react@18.3.1", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ=="], "react-dom": ["react-dom@18.3.1", "", { "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" }, "peerDependencies": { "react": "^18.3.1" } }, "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw=="], "react-hook-form": ["react-hook-form@7.58.1", "", { "peerDependencies": { "react": "^16.8.0 || ^17 || ^18 || ^19" } }, "sha512-Lml/KZYEEFfPhUVgE0RdCVpnC4yhW+PndRhbiTtdvSlQTL8IfVR+iQkBjLIvmmc6+GGoVeM11z37ktKFPAb0FA=="], + "react-i18next": ["react-i18next@16.5.4", "", { "dependencies": { "@babel/runtime": "^7.28.4", "html-parse-stringify": "^3.0.1", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "i18next": ">= 25.6.2", "react": ">= 16.8.0", "typescript": "^5" }, "optionalPeers": ["typescript"] }, "sha512-6yj+dcfMncEC21QPhOTsW8mOSO+pzFmT6uvU7XXdvM/Cp38zJkmTeMeKmTrmCMD5ToT79FmiE/mRWiYWcJYW4g=="], + "react-is": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="], "react-markdown": ["react-markdown@9.1.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "hast-util-to-jsx-runtime": "^2.0.0", "html-url-attributes": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.0.0", "unified": "^11.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" }, "peerDependencies": { "@types/react": ">=18", "react": ">=18" } }, "sha512-xaijuJB0kzGiUdG7nc2MOMDUDBWPyGAjZtUrow9XxUeua8IqeP+VlIfAZ3bphpcLTnSZXz6z9jcVC/TCwbfgdw=="], @@ -909,6 +1098,8 @@ "react-transition-group": ["react-transition-group@4.4.5", "", { "dependencies": { "@babel/runtime": "^7.5.5", "dom-helpers": "^5.0.1", "loose-envify": "^1.4.0", "prop-types": "^15.6.2" }, "peerDependencies": { "react": ">=16.6.0", "react-dom": ">=16.6.0" } }, "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g=="], + "readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="], + "recharts": ["recharts@2.15.3", "", { "dependencies": { "clsx": "^2.0.0", "eventemitter3": "^4.0.1", "lodash": "^4.17.21", "react-is": "^18.3.1", "react-smooth": "^4.0.4", "recharts-scale": "^0.4.4", "tiny-invariant": "^1.3.1", "victory-vendor": "^36.6.8" }, "peerDependencies": { "react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-EdOPzTwcFSuqtvkDoaM5ws/Km1+WTAO2eizL7rqiG0V2UVhTnz0m7J2i0CjVPUCdEkZImaWvXLbZDS2H5t6GFQ=="], "recharts-scale": ["recharts-scale@0.4.5", "", { "dependencies": { "decimal.js-light": "^2.4.1" } }, "sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w=="], @@ -945,26 +1136,68 @@ "remark-stringify": ["remark-stringify@11.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-to-markdown": "^2.0.0", "unified": "^11.0.0" } }, "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw=="], + "remove-trailing-separator": ["remove-trailing-separator@1.1.0", "", {}, "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw=="], + + "replace-ext": ["replace-ext@2.0.0", "", {}, "sha512-UszKE5KVK6JvyD92nzMn9cDapSk6w/CaFZ96CnmDMUqH9oowfxF/ZjRITD25H4DnOQClLA4/j7jLGXXLVKxAug=="], + + "resolve-options": ["resolve-options@2.0.0", "", { "dependencies": { "value-or-function": "^4.0.0" } }, "sha512-/FopbmmFOQCfsCx77BRFdKOniglTiHumLgwvd6IDPihy1GKkadZbgQJBcTb2lMzSR1pndzd96b1nZrreZ7+9/A=="], + + "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], + + "rimraf": ["rimraf@3.0.2", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" } }, "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA=="], + "rollup": ["rollup@4.43.0", "", { "dependencies": { "@types/estree": "1.0.7" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.43.0", "@rollup/rollup-android-arm64": "4.43.0", "@rollup/rollup-darwin-arm64": "4.43.0", "@rollup/rollup-darwin-x64": "4.43.0", "@rollup/rollup-freebsd-arm64": "4.43.0", "@rollup/rollup-freebsd-x64": "4.43.0", "@rollup/rollup-linux-arm-gnueabihf": "4.43.0", "@rollup/rollup-linux-arm-musleabihf": "4.43.0", "@rollup/rollup-linux-arm64-gnu": "4.43.0", "@rollup/rollup-linux-arm64-musl": "4.43.0", "@rollup/rollup-linux-loongarch64-gnu": "4.43.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.43.0", "@rollup/rollup-linux-riscv64-gnu": "4.43.0", "@rollup/rollup-linux-riscv64-musl": "4.43.0", "@rollup/rollup-linux-s390x-gnu": "4.43.0", "@rollup/rollup-linux-x64-gnu": "4.43.0", "@rollup/rollup-linux-x64-musl": "4.43.0", "@rollup/rollup-win32-arm64-msvc": "4.43.0", "@rollup/rollup-win32-ia32-msvc": "4.43.0", "@rollup/rollup-win32-x64-msvc": "4.43.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-wdN2Kd3Twh8MAEOEJZsuxuLKCsBEo4PVNLK6tQWAn10VhsVewQLzcucMgLolRlhFybGxfclbPeEYBaP6RvUFGg=="], + "rsvp": ["rsvp@4.8.5", "", {}, "sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA=="], + + "safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="], + + "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="], + "scheduler": ["scheduler@0.23.2", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ=="], "semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="], "sharp": ["sharp@0.34.2", "", { "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.4", "semver": "^7.7.2" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.34.2", "@img/sharp-darwin-x64": "0.34.2", "@img/sharp-libvips-darwin-arm64": "1.1.0", "@img/sharp-libvips-darwin-x64": "1.1.0", "@img/sharp-libvips-linux-arm": "1.1.0", "@img/sharp-libvips-linux-arm64": "1.1.0", "@img/sharp-libvips-linux-ppc64": "1.1.0", "@img/sharp-libvips-linux-s390x": "1.1.0", "@img/sharp-libvips-linux-x64": "1.1.0", "@img/sharp-libvips-linuxmusl-arm64": "1.1.0", "@img/sharp-libvips-linuxmusl-x64": "1.1.0", "@img/sharp-linux-arm": "0.34.2", "@img/sharp-linux-arm64": "0.34.2", "@img/sharp-linux-s390x": "0.34.2", "@img/sharp-linux-x64": "0.34.2", "@img/sharp-linuxmusl-arm64": "0.34.2", "@img/sharp-linuxmusl-x64": "0.34.2", "@img/sharp-wasm32": "0.34.2", "@img/sharp-win32-arm64": "0.34.2", "@img/sharp-win32-ia32": "0.34.2", "@img/sharp-win32-x64": "0.34.2" } }, "sha512-lszvBmB9QURERtyKT2bNmsgxXK0ShJrL/fvqlonCo7e6xBF8nT8xU6pW+PMIbLsz0RxQk3rgH9kd8UmvOzlMJg=="], + "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], + + "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], + + "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], + "simple-swizzle": ["simple-swizzle@0.2.2", "", { "dependencies": { "is-arrayish": "^0.3.1" } }, "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg=="], + "sort-keys": ["sort-keys@5.1.0", "", { "dependencies": { "is-plain-obj": "^4.0.0" } }, "sha512-aSbHV0DaBcr7u0PVHXzM6NbZNAtrr9sF6+Qfs9UUVG7Ll3jQ6hHi8F/xqIIcn2rvIVbr0v/2zyjSdwSV47AgLQ=="], + "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], "space-separated-tokens": ["space-separated-tokens@2.0.2", "", {}, "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q=="], + "sprintf-js": ["sprintf-js@1.1.3", "", {}, "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA=="], + + "stream-composer": ["stream-composer@1.0.2", "", { "dependencies": { "streamx": "^2.13.2" } }, "sha512-bnBselmwfX5K10AH6L4c8+S5lgZMWI7ZYrz2rvYjCPB2DIMC4Ig8OpxGpNJSxRZ58oti7y1IcNvjBAz9vW5m4w=="], + + "streamx": ["streamx@2.23.0", "", { "dependencies": { "events-universal": "^1.0.0", "fast-fifo": "^1.3.2", "text-decoder": "^1.1.0" } }, "sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg=="], + + "string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], + + "string-width-cjs": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + + "string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="], + "stringify-entities": ["stringify-entities@4.0.4", "", { "dependencies": { "character-entities-html4": "^2.0.0", "character-entities-legacy": "^3.0.0" } }, "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg=="], + "strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="], + + "strip-ansi-cjs": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + "style-to-js": ["style-to-js@1.1.17", "", { "dependencies": { "style-to-object": "1.0.9" } }, "sha512-xQcBGDxJb6jjFCTzvQtfiPn6YvvP2O8U1MDIPNfJQlWMYfktPy+iGsHE7cssjs7y84d9fQaK4UF3RIJaAHSoYA=="], "style-to-object": ["style-to-object@1.0.9", "", { "dependencies": { "inline-style-parser": "0.2.4" } }, "sha512-G4qppLgKu/k6FwRpHiGiKPaPTFcG3g4wNVX/Qsfu+RqQM30E7Tyu/TEgxcL9PNLF5pdRLwQdE3YKKf+KF2Dzlw=="], + "symlink-or-copy": ["symlink-or-copy@1.3.1", "", {}, "sha512-0K91MEXFpBUaywiwSSkmKjnGcasG/rVBXFLJz5DrgGabpYD6N+3yZrfD6uUIfpuTu65DZLHi7N8CizHc07BPZA=="], + "tailwind-merge": ["tailwind-merge@2.6.0", "", {}, "sha512-P+Vu1qXfzediirmHOC3xKGAYeZtPcV9g76X+xg2FD4tYgR71ewMA35Y3sCz3zhiN/dwefRpJX0yBcgwi1fXNQA=="], "tailwindcss": ["tailwindcss@4.1.10", "", {}, "sha512-P3nr6WkvKV/ONsTzj6Gb57sWPMX29EPNPopo7+FcpkQaNsrNpZ1pv8QmrYI2RqEKD7mlGqLnGovlcYnBK0IqUA=="], @@ -973,14 +1206,22 @@ "tar": ["tar@7.4.3", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.0.1", "mkdirp": "^3.0.1", "yallist": "^5.0.0" } }, "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw=="], + "teex": ["teex@1.0.1", "", { "dependencies": { "streamx": "^2.12.5" } }, "sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg=="], + + "text-decoder": ["text-decoder@1.2.3", "", { "dependencies": { "b4a": "^1.6.4" } }, "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA=="], + "text-segmentation": ["text-segmentation@1.0.3", "", { "dependencies": { "utrie": "^1.0.2" } }, "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw=="], + "through2": ["through2@2.0.5", "", { "dependencies": { "readable-stream": "~2.3.6", "xtend": "~4.0.1" } }, "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ=="], + "tiny-invariant": ["tiny-invariant@1.3.3", "", {}, "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg=="], "tinyglobby": ["tinyglobby@0.2.14", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ=="], "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], + "to-through": ["to-through@3.0.0", "", { "dependencies": { "streamx": "^2.12.5" } }, "sha512-y8MN937s/HVhEoBU1SxfHC+wxCHkV1a9gW8eAdTadYh/bGyesZIVcbjI+mSpFbSVwQici/XjBjuUyri1dnXwBw=="], + "trim-lines": ["trim-lines@3.0.1", "", {}, "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg=="], "trough": ["trough@2.2.0", "", {}, "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw=="], @@ -989,6 +1230,10 @@ "typescript": ["typescript@5.6.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw=="], + "underscore.string": ["underscore.string@3.3.6", "", { "dependencies": { "sprintf-js": "^1.1.1", "util-deprecate": "^1.0.2" } }, "sha512-VoC83HWXmCrF6rgkyxS9GHv8W9Q5nhMKho+OadDJGzL2oDYbYEppBaCMH6pFlwLeqj2QS+hhkw2kpXkSdD1JxQ=="], + + "undici": ["undici@7.19.2", "", {}, "sha512-4VQSpGEGsWzk0VYxyB/wVX/Q7qf9t5znLRgs0dzszr9w9Fej/8RVNQ+S20vdXSAyra/bJ7ZQfGv6ZMj7UEbzSg=="], + "undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], "unified": ["unified@11.0.5", "", { "dependencies": { "@types/unist": "^3.0.0", "bail": "^2.0.0", "devlop": "^1.0.0", "extend": "^3.0.0", "is-plain-obj": "^4.0.0", "trough": "^2.0.0", "vfile": "^6.0.0" } }, "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA=="], @@ -1005,14 +1250,22 @@ "unist-util-visit-parents": ["unist-util-visit-parents@6.0.1", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0" } }, "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw=="], + "universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="], + "update-browserslist-db": ["update-browserslist-db@1.1.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw=="], "use-callback-ref": ["use-callback-ref@1.3.3", "", { "dependencies": { "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg=="], "use-sidecar": ["use-sidecar@1.1.3", "", { "dependencies": { "detect-node-es": "^1.1.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ=="], + "use-sync-external-store": ["use-sync-external-store@1.6.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w=="], + + "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], + "utrie": ["utrie@1.0.2", "", { "dependencies": { "base64-arraybuffer": "^1.0.2" } }, "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw=="], + "value-or-function": ["value-or-function@4.0.0", "", {}, "sha512-aeVK81SIuT6aMJfNo9Vte8Dw0/FZINGBV8BfCraGtqVxIeLAEhJyoWs8SmvRVmXfGss2PmmOwZCuBPbZR+IYWg=="], + "vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="], "vfile-location": ["vfile-location@5.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile": "^6.0.0" } }, "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg=="], @@ -1021,12 +1274,36 @@ "victory-vendor": ["victory-vendor@36.9.2", "", { "dependencies": { "@types/d3-array": "^3.0.3", "@types/d3-ease": "^3.0.0", "@types/d3-interpolate": "^3.0.1", "@types/d3-scale": "^4.0.2", "@types/d3-shape": "^3.1.0", "@types/d3-time": "^3.0.0", "@types/d3-timer": "^3.0.0", "d3-array": "^3.1.6", "d3-ease": "^3.0.1", "d3-interpolate": "^3.0.1", "d3-scale": "^4.0.2", "d3-shape": "^3.1.0", "d3-time": "^3.0.0", "d3-timer": "^3.0.1" } }, "sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ=="], + "vinyl": ["vinyl@3.0.1", "", { "dependencies": { "clone": "^2.1.2", "remove-trailing-separator": "^1.1.0", "replace-ext": "^2.0.0", "teex": "^1.0.1" } }, "sha512-0QwqXteBNXgnLCdWdvPQBX6FXRHtIH3VhJPTd5Lwn28tJXc34YqSCWUmkOvtJHBmB3gGoPtrOKk3Ts8/kEZ9aA=="], + + "vinyl-contents": ["vinyl-contents@2.0.0", "", { "dependencies": { "bl": "^5.0.0", "vinyl": "^3.0.0" } }, "sha512-cHq6NnGyi2pZ7xwdHSW1v4Jfnho4TEGtxZHw01cmnc8+i7jgR6bRnED/LbrKan/Q7CvVLbnvA5OepnhbpjBZ5Q=="], + + "vinyl-fs": ["vinyl-fs@4.0.2", "", { "dependencies": { "fs-mkdirp-stream": "^2.0.1", "glob-stream": "^8.0.3", "graceful-fs": "^4.2.11", "iconv-lite": "^0.6.3", "is-valid-glob": "^1.0.0", "lead": "^4.0.0", "normalize-path": "3.0.0", "resolve-options": "^2.0.0", "stream-composer": "^1.0.2", "streamx": "^2.14.0", "to-through": "^3.0.0", "value-or-function": "^4.0.0", "vinyl": "^3.0.1", "vinyl-sourcemap": "^2.0.0" } }, "sha512-XRFwBLLTl8lRAOYiBqxY279wY46tVxLaRhSwo3GzKEuLz1giffsOquWWboD/haGf5lx+JyTigCFfe7DWHoARIA=="], + + "vinyl-sourcemap": ["vinyl-sourcemap@2.0.0", "", { "dependencies": { "convert-source-map": "^2.0.0", "graceful-fs": "^4.2.10", "now-and-later": "^3.0.0", "streamx": "^2.12.5", "vinyl": "^3.0.0", "vinyl-contents": "^2.0.0" } }, "sha512-BAEvWxbBUXvlNoFQVFVHpybBbjW1r03WhohJzJDSfgrrK5xVYIDTan6xN14DlyImShgDRv2gl9qhM6irVMsV0Q=="], + "vite": ["vite@6.3.5", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ=="], + "void-elements": ["void-elements@3.1.0", "", {}, "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w=="], + + "walk-sync": ["walk-sync@2.2.0", "", { "dependencies": { "@types/minimatch": "^3.0.3", "ensure-posix-path": "^1.1.0", "matcher-collection": "^2.0.0", "minimatch": "^3.0.4" } }, "sha512-IC8sL7aB4/ZgFcGI2T1LczZeFWZ06b3zoHH7jBPyHxOtIIz1jppWHjjEXkOFvFojBVAK9pV7g47xOZ4LW3QLfg=="], + "web-namespaces": ["web-namespaces@2.0.1", "", {}, "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ=="], "web-vitals": ["web-vitals@4.2.4", "", {}, "sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw=="], + "whatwg-encoding": ["whatwg-encoding@3.1.1", "", { "dependencies": { "iconv-lite": "0.6.3" } }, "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ=="], + + "whatwg-mimetype": ["whatwg-mimetype@4.0.0", "", {}, "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg=="], + + "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], + + "wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="], + + "wrap-ansi-cjs": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], + + "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="], + "xtend": ["xtend@4.0.2", "", {}, "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="], "yallist": ["yallist@5.0.0", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="], @@ -1055,12 +1332,38 @@ "@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + "@tauri-apps/plugin-dialog/@tauri-apps/api": ["@tauri-apps/api@2.9.1", "", {}, "sha512-IGlhP6EivjXHepbBic618GOmiWe4URJiIeZFlB7x3czM0yDHHYviH1Xvoiv4FefdkQtn6v7TuwWCRfOGdnVUGw=="], + + "@tauri-apps/plugin-global-shortcut/@tauri-apps/api": ["@tauri-apps/api@2.9.1", "", {}, "sha512-IGlhP6EivjXHepbBic618GOmiWe4URJiIeZFlB7x3czM0yDHHYviH1Xvoiv4FefdkQtn6v7TuwWCRfOGdnVUGw=="], + + "@tauri-apps/plugin-opener/@tauri-apps/api": ["@tauri-apps/api@2.5.0", "", {}, "sha512-Ldux4ip+HGAcPUmuLT8EIkk6yafl5vK0P0c0byzAKzxJh7vxelVtdPONjfgTm96PbN24yjZNESY8CKo8qniluA=="], + + "@tauri-apps/plugin-shell/@tauri-apps/api": ["@tauri-apps/api@2.9.1", "", {}, "sha512-IGlhP6EivjXHepbBic618GOmiWe4URJiIeZFlB7x3czM0yDHHYviH1Xvoiv4FefdkQtn6v7TuwWCRfOGdnVUGw=="], + + "@uiw/react-markdown-preview/@babel/runtime": ["@babel/runtime@7.27.6", "", {}, "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q=="], + "@uiw/react-markdown-preview/react-markdown": ["react-markdown@9.0.3", "", { "dependencies": { "@types/hast": "^3.0.0", "devlop": "^1.0.0", "hast-util-to-jsx-runtime": "^2.0.0", "html-url-attributes": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.0.0", "unified": "^11.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" }, "peerDependencies": { "@types/react": ">=18", "react": ">=18" } }, "sha512-Yk7Z94dbgYTOrdk41Z74GoKA7rThnsbbqBTRYuxoe08qvfQ9tJVhmAKw6BJS/ZORG7kTy/s1QvYzSuaoBA1qfw=="], "@uiw/react-markdown-preview/rehype-prism-plus": ["rehype-prism-plus@2.0.0", "", { "dependencies": { "hast-util-to-string": "^3.0.0", "parse-numeric-range": "^1.3.0", "refractor": "^4.8.0", "rehype-parse": "^9.0.0", "unist-util-filter": "^5.0.0", "unist-util-visit": "^5.0.0" } }, "sha512-FeM/9V2N7EvDZVdR2dqhAzlw5YI49m9Tgn7ZrYJeYHIahM6gcXpH0K1y2gNnKanZCydOMluJvX2cB9z3lhY8XQ=="], + "@uiw/react-md-editor/@babel/runtime": ["@babel/runtime@7.27.6", "", {}, "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q=="], + + "anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + + "bl/readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], + + "broccoli-output-wrapper/fs-extra": ["fs-extra@8.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g=="], + "decode-named-character-reference/character-entities": ["character-entities@2.0.2", "", {}, "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ=="], + "dom-helpers/@babel/runtime": ["@babel/runtime@7.27.6", "", {}, "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q=="], + + "dom-serializer/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], + + "esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.5", "", { "os": "linux", "cpu": "x64" }, "sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw=="], + + "fs-merger/fs-extra": ["fs-extra@8.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g=="], + "hast-util-from-parse5/hastscript": ["hastscript@9.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-parse-selector": "^4.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0" } }, "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w=="], "hast-util-to-parse5/property-information": ["property-information@6.5.0", "", {}, "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig=="], @@ -1073,6 +1376,16 @@ "hastscript/space-separated-tokens": ["space-separated-tokens@1.1.5", "", {}, "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA=="], + "heimdalljs/rsvp": ["rsvp@3.2.1", "", {}, "sha512-Rf4YVNYpKjZ6ASAmibcwTNciQ5Co5Ztq6iZPEykHpkoflnD/K5ryE/rHehFsTm4NJj8nKDhbi3eKBWGogmNnkg=="], + + "heimdalljs-logger/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], + + "htmlparser2/entities": ["entities@7.0.1", "", {}, "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA=="], + + "i18next-browser-languagedetector/@babel/runtime": ["@babel/runtime@7.27.6", "", {}, "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q=="], + + "i18next-parser/i18next": ["i18next@24.2.3", "", { "dependencies": { "@babel/runtime": "^7.26.10" }, "peerDependencies": { "typescript": "^5" }, "optionalPeers": ["typescript"] }, "sha512-lfbf80OzkocvX7nmZtu7nSTNbrTYR52sLWxPtlXX1zAhVw8WEnFk4puUkCR4B1dNQwbSpEHHHemcZu//7EcB7A=="], + "lru-cache/yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], "mdast-util-mdx-jsx/parse-entities": ["parse-entities@4.0.2", "", { "dependencies": { "@types/unist": "^2.0.0", "character-entities-legacy": "^3.0.0", "character-reference-invalid": "^2.0.0", "decode-named-character-reference": "^1.0.0", "is-alphanumerical": "^2.0.0", "is-decimal": "^2.0.0", "is-hexadecimal": "^2.0.0" } }, "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw=="], @@ -1081,20 +1394,52 @@ "parse5/entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="], + "path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], + "prop-types/react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="], + "quick-temp/rimraf": ["rimraf@5.0.10", "", { "dependencies": { "glob": "^10.3.7" }, "bin": { "rimraf": "dist/esm/bin.mjs" } }, "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ=="], + + "react-syntax-highlighter/@babel/runtime": ["@babel/runtime@7.27.6", "", {}, "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q=="], + + "react-transition-group/@babel/runtime": ["@babel/runtime@7.27.6", "", {}, "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q=="], + "refractor/prismjs": ["prismjs@1.27.0", "", {}, "sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA=="], "rehype-prism-plus/refractor": ["refractor@4.9.0", "", { "dependencies": { "@types/hast": "^2.0.0", "@types/prismjs": "^1.0.0", "hastscript": "^7.0.0", "parse-entities": "^4.0.0" } }, "sha512-nEG1SPXFoGGx+dcjftjv8cAjEusIh6ED1xhf5DG3C0x/k+rmZ2duKnc3QLpt6qeHv5fPb8uwN3VWN2BT7fr3Og=="], + "rollup/@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.43.0", "", { "os": "linux", "cpu": "x64" }, "sha512-jAHr/S0iiBtFyzjhOkAics/2SrXE092qyqEg96e90L3t9Op8OTzS6+IX0Fy5wCt2+KqeHAkti+eitV0wvblEoQ=="], + + "string-width-cjs/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "string-width-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + "stringify-entities/character-entities-legacy": ["character-entities-legacy@3.0.0", "", {}, "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ=="], + "strip-ansi-cjs/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "wrap-ansi-cjs/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], + + "wrap-ansi-cjs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + + "wrap-ansi-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + "@uiw/react-markdown-preview/rehype-prism-plus/refractor": ["refractor@4.9.0", "", { "dependencies": { "@types/hast": "^2.0.0", "@types/prismjs": "^1.0.0", "hastscript": "^7.0.0", "parse-entities": "^4.0.0" } }, "sha512-nEG1SPXFoGGx+dcjftjv8cAjEusIh6ED1xhf5DG3C0x/k+rmZ2duKnc3QLpt6qeHv5fPb8uwN3VWN2BT7fr3Og=="], + "broccoli-output-wrapper/fs-extra/jsonfile": ["jsonfile@4.0.0", "", { "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg=="], + + "broccoli-output-wrapper/fs-extra/universalify": ["universalify@0.1.2", "", {}, "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="], + + "fs-merger/fs-extra/jsonfile": ["jsonfile@4.0.0", "", { "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg=="], + + "fs-merger/fs-extra/universalify": ["universalify@0.1.2", "", {}, "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="], + "hast-util-from-parse5/hastscript/hast-util-parse-selector": ["hast-util-parse-selector@4.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A=="], "hastscript/@types/hast/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], + "heimdalljs-logger/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], + "mdast-util-mdx-jsx/parse-entities/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], "mdast-util-mdx-jsx/parse-entities/character-entities-legacy": ["character-entities-legacy@3.0.0", "", {}, "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ=="], @@ -1107,12 +1452,20 @@ "mdast-util-mdx-jsx/parse-entities/is-hexadecimal": ["is-hexadecimal@2.0.1", "", {}, "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg=="], + "quick-temp/rimraf/glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="], + "rehype-prism-plus/refractor/@types/hast": ["@types/hast@2.3.10", "", { "dependencies": { "@types/unist": "^2" } }, "sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw=="], "rehype-prism-plus/refractor/hastscript": ["hastscript@7.2.0", "", { "dependencies": { "@types/hast": "^2.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-parse-selector": "^3.0.0", "property-information": "^6.0.0", "space-separated-tokens": "^2.0.0" } }, "sha512-TtYPq24IldU8iKoJQqvZOuhi5CyCQRAbvDOX0x1eW6rsHSxa/1i2CCiptNTotGHJ3VoHRGmqiv6/D3q113ikkw=="], "rehype-prism-plus/refractor/parse-entities": ["parse-entities@4.0.2", "", { "dependencies": { "@types/unist": "^2.0.0", "character-entities-legacy": "^3.0.0", "character-reference-invalid": "^2.0.0", "decode-named-character-reference": "^1.0.0", "is-alphanumerical": "^2.0.0", "is-decimal": "^2.0.0", "is-hexadecimal": "^2.0.0" } }, "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw=="], + "string-width-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "wrap-ansi-cjs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "wrap-ansi-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + "@uiw/react-markdown-preview/rehype-prism-plus/refractor/@types/hast": ["@types/hast@2.3.10", "", { "dependencies": { "@types/unist": "^2" } }, "sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw=="], "@uiw/react-markdown-preview/rehype-prism-plus/refractor/hastscript": ["hastscript@7.2.0", "", { "dependencies": { "@types/hast": "^2.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-parse-selector": "^3.0.0", "property-information": "^6.0.0", "space-separated-tokens": "^2.0.0" } }, "sha512-TtYPq24IldU8iKoJQqvZOuhi5CyCQRAbvDOX0x1eW6rsHSxa/1i2CCiptNTotGHJ3VoHRGmqiv6/D3q113ikkw=="], @@ -1121,6 +1474,8 @@ "mdast-util-mdx-jsx/parse-entities/is-alphanumerical/is-alphabetical": ["is-alphabetical@2.0.1", "", {}, "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ=="], + "quick-temp/rimraf/glob/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + "rehype-prism-plus/refractor/@types/hast/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], "rehype-prism-plus/refractor/hastscript/hast-util-parse-selector": ["hast-util-parse-selector@3.1.1", "", { "dependencies": { "@types/hast": "^2.0.0" } }, "sha512-jdlwBjEexy1oGz0aJ2f4GKMaVKkA9jwjr4MjAAI22E5fM/TXVZHuS5OpONtdeIkRKqAaryQ2E9xNQxijoThSZA=="], @@ -1157,6 +1512,8 @@ "@uiw/react-markdown-preview/rehype-prism-plus/refractor/parse-entities/is-hexadecimal": ["is-hexadecimal@2.0.1", "", {}, "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg=="], + "quick-temp/rimraf/glob/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], + "rehype-prism-plus/refractor/parse-entities/is-alphanumerical/is-alphabetical": ["is-alphabetical@2.0.1", "", {}, "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ=="], "@uiw/react-markdown-preview/rehype-prism-plus/refractor/parse-entities/is-alphanumerical/is-alphabetical": ["is-alphabetical@2.0.1", "", {}, "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ=="], diff --git a/docs/TRANSLATION_GUIDE.md b/docs/TRANSLATION_GUIDE.md new file mode 100644 index 000000000..5df9a5b62 --- /dev/null +++ b/docs/TRANSLATION_GUIDE.md @@ -0,0 +1,251 @@ +# Translation Contribution Guide + +Thank you for your interest in contributing translations to opcode! This guide will help you add or improve translations. + +## 🌐 Supported Languages + +Currently supported languages: +- **English** (en) - Default +- **Simplified Chinese** (zh) - 简体中文 + +## 📁 Translation File Structure + +Translation files are located in `src/locales/`: + +``` +src/locales/ +├── en/ # English translations +│ ├── common.json # Common UI elements +│ ├── agents.json # CC Agents module +│ ├── projects.json # Project management +│ ├── sessions.json # Session management +│ ├── settings.json # Settings page +│ ├── mcp.json # MCP server management +│ ├── usage.json # Usage analytics +│ └── errors.json # Error messages +└── zh/ # Chinese translations + └── (same structure) +``` + +## 🔑 Translation Key Structure + +Translation keys follow a hierarchical structure: + +``` +namespace:category.key +``` + +Examples: +- `common:buttons.save` - Save button +- `agents:messages.agent_created` - Agent created message +- `settings:tabs.general` - General settings tab + +## ✍️ Adding a New Language + +### Step 1: Create Translation Files + +1. Create a new directory in `src/locales/` with the language code (e.g., `fr` for French) +2. Copy all JSON files from `src/locales/en/` to your new directory +3. Translate the values (keep the keys in English) + +### Step 2: Update i18n Configuration + +Edit `src/i18n/config.ts`: + +```typescript +// Add your language to resources +const resources = { + en: { /* ... */ }, + zh: { /* ... */ }, + fr: { // Add your language + common: commonFR, + agents: agentsFR, + // ... other namespaces + }, +}; +``` + +### Step 3: Update Language Selector + +Edit `src/i18n/helpers.ts`: + +```typescript +export const getSupportedLanguages = () => { + return [ + { code: 'en', name: 'English' }, + { code: 'zh', name: '简体中文' }, + { code: 'fr', name: 'Français' }, // Add your language + ]; +}; +``` + +## 📝 Translation Guidelines + +### 1. Technical Terms + +**Keep technical terms in English** for consistency across languages: + +✅ **Preserve in English:** +- Agent / Agents +- CC Agents +- MCP Server +- Token / Tokens +- Session / Sessions +- Checkpoint / Checkpoints +- Timeline +- Project / Projects +- Prompt +- API, CLI, GUI +- Tauri, WebView +- Markdown, JSON +- CLAUDE.md + +✅ **Mixed expressions are OK:** +- Chinese: "创建 Agent" (Create Agent) +- Chinese: "MCP 服务器管理" (MCP Server Management) +- Chinese: "Token 使用量" (Token Usage) + +### 2. Tone and Style + +- **Professional**: Use professional, technical language +- **Concise**: Keep translations brief and clear +- **Consistent**: Use the same translation for the same term throughout + +### 3. Placeholders and Variables + +Preserve placeholders in translations: + +```json +{ + "created_count": "Created {{count}} agents" +} +``` + +Chinese translation: +```json +{ + "created_count": "已创建 {{count}} 个 Agent" +} +``` + +### 4. Pluralization + +i18next handles pluralization automatically. Use `_plural` suffix: + +```json +{ + "sessions": "{{count}} session", + "sessions_plural": "{{count}} sessions" +} +``` + +## 🧪 Testing Your Translations + +### 1. Run the Development Server + +```bash +bun run dev +``` + +### 2. Switch Language + +Go to **Settings → General → Language** and select your language. + +### 3. Check All Modules + +Navigate through all sections of the app: +- CC Agents +- Projects +- Sessions +- Settings +- MCP Servers +- Usage Dashboard + +### 4. Verify + +- [ ] All text is translated +- [ ] Technical terms are preserved +- [ ] No missing translations (shows key instead of text) +- [ ] Placeholders work correctly +- [ ] UI layout is not broken by longer text + +## 🔍 Finding Missing Translations + +### Method 1: Visual Inspection + +Look for text that appears as keys (e.g., `common:buttons.save` instead of "Save") + +### Method 2: Use i18next-parser + +Extract all translatable strings: + +```bash +bun run i18n:extract +``` + +This will update translation files with any missing keys. + +## 📤 Submitting Your Translation + +### 1. Fork the Repository + +Fork the opcode repository on GitHub. + +### 2. Create a Branch + +```bash +git checkout -b add-french-translation +``` + +### 3. Add Your Translation Files + +```bash +git add src/locales/fr/ +git add src/i18n/config.ts +git add src/i18n/helpers.ts +``` + +### 4. Commit Your Changes + +```bash +git commit -m "Add French translation" +``` + +### 5. Push and Create Pull Request + +```bash +git push origin add-french-translation +``` + +Then create a Pull Request on GitHub. + +## 📋 Translation Checklist + +Before submitting, ensure: + +- [ ] All JSON files are valid (no syntax errors) +- [ ] All keys from English version are present +- [ ] Technical terms are preserved in English +- [ ] Placeholders ({{variable}}) are preserved +- [ ] Tested in the application +- [ ] No UI layout issues +- [ ] Consistent terminology throughout +- [ ] Professional tone maintained + +## 🤝 Getting Help + +If you have questions: + +1. Check existing translations in `src/locales/zh/` for examples +2. Open an issue on GitHub +3. Join our Discord community + +## 📚 Resources + +- [i18next Documentation](https://www.i18next.com/) +- [React i18next Guide](https://react.i18next.com/) +- [Pluralization Rules](https://www.i18next.com/translation-function/plurals) + +--- + +Thank you for contributing to make opcode accessible to more users worldwide! 🌍 diff --git a/i18next-parser.config.js b/i18next-parser.config.js new file mode 100644 index 000000000..ca2889fb7 --- /dev/null +++ b/i18next-parser.config.js @@ -0,0 +1,35 @@ +module.exports = { + locales: ['en', 'zh'], + output: 'src/locales/$LOCALE/$NAMESPACE.json', + input: ['src/**/*.{ts,tsx}'], + + // 默认命名空间 + defaultNamespace: 'common', + + // 命名空间 + lexers: { + ts: ['JavascriptLexer'], + tsx: ['JsxLexer'], + }, + + // 保持 key 排序 + sort: true, + + // 保留旧的翻译 + keepRemoved: false, + + // 使用 key 作为默认值 + defaultValue: (locale, namespace, key) => { + return key; + }, + + // 命名空间分离 + createOldCatalogs: false, + + // 缩进 + indentation: 2, + + // 命名空间映射规则 + namespaceSeparator: ':', + keySeparator: '.', +}; diff --git a/package-lock.json b/package-lock.json index b408ecec9..7e0ecbe8f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "opcode", - "version": "0.1.0", + "version": "0.2.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "opcode", - "version": "0.1.0", + "version": "0.2.1", "license": "AGPL-3.0", "dependencies": { "@hookform/resolvers": "^3.9.1", @@ -38,10 +38,14 @@ "diff": "^8.0.2", "framer-motion": "^12.0.0-alpha.1", "html2canvas": "^1.4.1", + "i18next": "^25.8.0", + "i18next-browser-languagedetector": "^8.2.0", "lucide-react": "^0.468.0", + "posthog-js": "^1.258.3", "react": "^18.3.1", "react-dom": "^18.3.1", "react-hook-form": "^7.54.2", + "react-i18next": "^16.5.4", "react-markdown": "^9.0.3", "react-syntax-highlighter": "^15.6.1", "recharts": "^2.14.1", @@ -52,12 +56,13 @@ "zustand": "^5.0.6" }, "devDependencies": { - "@tauri-apps/cli": "^2", + "@tauri-apps/cli": "^2.7.1", "@types/node": "^22.15.30", "@types/react": "^18.3.1", "@types/react-dom": "^18.3.1", "@types/sharp": "^0.32.0", "@vitejs/plugin-react": "^4.3.4", + "i18next-parser": "^9.3.0", "sharp": "^0.34.2", "typescript": "~5.6.2", "vite": "^6.0.3" @@ -111,6 +116,7 @@ "integrity": "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.27.1", @@ -315,9 +321,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.27.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.6.tgz", - "integrity": "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz", + "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -835,6 +841,19 @@ "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==", "license": "MIT" }, + "node_modules/@gulpjs/to-absolute-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@gulpjs/to-absolute-glob/-/to-absolute-glob-4.0.0.tgz", + "integrity": "sha512-kjotm7XJrJ6v+7knhPaRgaT6q8F8K2jiafwYdNHLzmV0uGLuZY43FK6smNSHUPrhq5kX2slCUy+RGG/xGqmIKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-negated-glob": "^1.0.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/@hookform/resolvers": { "version": "3.10.0", "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-3.10.0.tgz", @@ -1284,6 +1303,24 @@ "url": "https://opencollective.com/libvips" } }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/@isaacs/fs-minipass": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", @@ -1331,6 +1368,253 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@opentelemetry/api": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", + "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", + "license": "Apache-2.0", + "peer": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@opentelemetry/api-logs": { + "version": "0.208.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.208.0.tgz", + "integrity": "sha512-CjruKY9V6NMssL/T1kAFgzosF1v9o6oeN+aX5JB/C/xPNtmgIJqcXHG7fA82Ou1zCpWGl4lROQUKwUNE1pMCyg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.3.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@opentelemetry/core": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.2.0.tgz", + "integrity": "sha512-FuabnnUm8LflnieVxs6eP7Z383hgQU4W1e3KJS6aOG3RxWxcHyBxH8fDMHNgu/gFx/M2jvTOW/4/PHhLz6bjWw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/exporter-logs-otlp-http": { + "version": "0.208.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-http/-/exporter-logs-otlp-http-0.208.0.tgz", + "integrity": "sha512-jOv40Bs9jy9bZVLo/i8FwUiuCvbjWDI+ZW13wimJm4LjnlwJxGgB+N/VWOZUTpM+ah/awXeQqKdNlpLf2EjvYg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.208.0", + "@opentelemetry/core": "2.2.0", + "@opentelemetry/otlp-exporter-base": "0.208.0", + "@opentelemetry/otlp-transformer": "0.208.0", + "@opentelemetry/sdk-logs": "0.208.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/otlp-exporter-base": { + "version": "0.208.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.208.0.tgz", + "integrity": "sha512-gMd39gIfVb2OgxldxUtOwGJYSH8P1kVFFlJLuut32L6KgUC4gl1dMhn+YC2mGn0bDOiQYSk/uHOdSjuKp58vvA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.2.0", + "@opentelemetry/otlp-transformer": "0.208.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/otlp-transformer": { + "version": "0.208.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.208.0.tgz", + "integrity": "sha512-DCFPY8C6lAQHUNkzcNT9R+qYExvsk6C5Bto2pbNxgicpcSWbe2WHShLxkOxIdNcBiYPdVHv/e7vH7K6TI+C+fQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.208.0", + "@opentelemetry/core": "2.2.0", + "@opentelemetry/resources": "2.2.0", + "@opentelemetry/sdk-logs": "0.208.0", + "@opentelemetry/sdk-metrics": "2.2.0", + "@opentelemetry/sdk-trace-base": "2.2.0", + "protobufjs": "^7.3.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/otlp-transformer/node_modules/@opentelemetry/resources": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.2.0.tgz", + "integrity": "sha512-1pNQf/JazQTMA0BiO5NINUzH0cbLbbl7mntLa4aJNmCCXSj0q03T5ZXXL0zw4G55TjdL9Tz32cznGClf+8zr5A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.2.0", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/resources": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.5.0.tgz", + "integrity": "sha512-F8W52ApePshpoSrfsSk1H2yJn9aKjCrbpQF1M9Qii0GHzbfVeFUB+rc3X4aggyZD8x9Gu3Slua+s6krmq6Dt8g==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.5.0", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/resources/node_modules/@opentelemetry/core": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.5.0.tgz", + "integrity": "sha512-ka4H8OM6+DlUhSAZpONu0cPBtPPTQKxbxVzC4CzVx5+K4JnroJVBtDzLAMx4/3CDTJXRvVFhpFjtl4SaiTNoyQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-logs": { + "version": "0.208.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.208.0.tgz", + "integrity": "sha512-QlAyL1jRpOeaqx7/leG1vJMp84g0xKP6gJmfELBpnI4O/9xPX+Hu5m1POk9Kl+veNkyth5t19hRlN6tNY1sjbA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.208.0", + "@opentelemetry/core": "2.2.0", + "@opentelemetry/resources": "2.2.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.4.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-logs/node_modules/@opentelemetry/resources": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.2.0.tgz", + "integrity": "sha512-1pNQf/JazQTMA0BiO5NINUzH0cbLbbl7mntLa4aJNmCCXSj0q03T5ZXXL0zw4G55TjdL9Tz32cznGClf+8zr5A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.2.0", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-metrics": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.2.0.tgz", + "integrity": "sha512-G5KYP6+VJMZzpGipQw7Giif48h6SGQ2PFKEYCybeXJsOCB4fp8azqMAAzE5lnnHK3ZVwYQrgmFbsUJO/zOnwGw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.2.0", + "@opentelemetry/resources": "2.2.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.9.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-metrics/node_modules/@opentelemetry/resources": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.2.0.tgz", + "integrity": "sha512-1pNQf/JazQTMA0BiO5NINUzH0cbLbbl7mntLa4aJNmCCXSj0q03T5ZXXL0zw4G55TjdL9Tz32cznGClf+8zr5A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.2.0", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-trace-base": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.2.0.tgz", + "integrity": "sha512-xWQgL0Bmctsalg6PaXExmzdedSp3gyKV8mQBwK/j9VGdCDu2fmXIb2gAehBKbkXCpJ4HPkgv3QfoJWRT4dHWbw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.2.0", + "@opentelemetry/resources": "2.2.0", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-trace-base/node_modules/@opentelemetry/resources": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.2.0.tgz", + "integrity": "sha512-1pNQf/JazQTMA0BiO5NINUzH0cbLbbl7mntLa4aJNmCCXSj0q03T5ZXXL0zw4G55TjdL9Tz32cznGClf+8zr5A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.2.0", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/semantic-conventions": { + "version": "1.39.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.39.0.tgz", + "integrity": "sha512-R5R9tb2AXs2IRLNKLBJDynhkfmx7mX0vi8NkhZb3gUkPWHn6HXk5J8iQ/dql0U3ApfWym4kXXmBDRGO+oeOfjg==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, "node_modules/@parcel/watcher": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz", @@ -1626,6 +1910,96 @@ "url": "https://opencollective.com/parcel" } }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@posthog/core": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/@posthog/core/-/core-1.17.0.tgz", + "integrity": "sha512-8pDNL+/u9ojzXloA5wILVDXBCV5daJ7w2ipCALQlEEZmL752cCKhRpbyiHn3tjKXh3Hy6aOboJneYa1JdlVHrQ==", + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.6" + } + }, + "node_modules/@posthog/types": { + "version": "1.336.4", + "resolved": "https://registry.npmjs.org/@posthog/types/-/types-1.336.4.tgz", + "integrity": "sha512-BY3cq/8segbXEvHbEXx9SWmaKJEM0AGgsOgMFH2yy13AV+rUHsGcp4Z5LDI5pU25DURN9EAZvzcoVyYy/Iokmw==", + "license": "MIT" + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", + "license": "BSD-3-Clause" + }, "node_modules/@radix-ui/number": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.1.tgz", @@ -3095,9 +3469,9 @@ } }, "node_modules/@tauri-apps/cli": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-2.6.2.tgz", - "integrity": "sha512-s1/eyBHxk0wG1blLeOY2IDjgZcxVrkxU5HFL8rNDwjYGr0o7yr3RAtwmuUPhz13NO+xGAL1bJZaLFBdp+5joKg==", + "version": "2.9.6", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-2.9.6.tgz", + "integrity": "sha512-3xDdXL5omQ3sPfBfdC8fCtDKcnyV7OqyzQgfyT5P3+zY6lcPqIYKQBvUasNvppi21RSdfhy44ttvJmftb0PCDw==", "dev": true, "license": "Apache-2.0 OR MIT", "bin": { @@ -3111,23 +3485,23 @@ "url": "https://opencollective.com/tauri" }, "optionalDependencies": { - "@tauri-apps/cli-darwin-arm64": "2.6.2", - "@tauri-apps/cli-darwin-x64": "2.6.2", - "@tauri-apps/cli-linux-arm-gnueabihf": "2.6.2", - "@tauri-apps/cli-linux-arm64-gnu": "2.6.2", - "@tauri-apps/cli-linux-arm64-musl": "2.6.2", - "@tauri-apps/cli-linux-riscv64-gnu": "2.6.2", - "@tauri-apps/cli-linux-x64-gnu": "2.6.2", - "@tauri-apps/cli-linux-x64-musl": "2.6.2", - "@tauri-apps/cli-win32-arm64-msvc": "2.6.2", - "@tauri-apps/cli-win32-ia32-msvc": "2.6.2", - "@tauri-apps/cli-win32-x64-msvc": "2.6.2" + "@tauri-apps/cli-darwin-arm64": "2.9.6", + "@tauri-apps/cli-darwin-x64": "2.9.6", + "@tauri-apps/cli-linux-arm-gnueabihf": "2.9.6", + "@tauri-apps/cli-linux-arm64-gnu": "2.9.6", + "@tauri-apps/cli-linux-arm64-musl": "2.9.6", + "@tauri-apps/cli-linux-riscv64-gnu": "2.9.6", + "@tauri-apps/cli-linux-x64-gnu": "2.9.6", + "@tauri-apps/cli-linux-x64-musl": "2.9.6", + "@tauri-apps/cli-win32-arm64-msvc": "2.9.6", + "@tauri-apps/cli-win32-ia32-msvc": "2.9.6", + "@tauri-apps/cli-win32-x64-msvc": "2.9.6" } }, "node_modules/@tauri-apps/cli-darwin-arm64": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.6.2.tgz", - "integrity": "sha512-YlvT+Yb7u2HplyN2Cf/nBplCQARC/I4uedlYHlgtxg6rV7xbo9BvG1jLOo29IFhqA2rOp5w1LtgvVGwsOf2kxw==", + "version": "2.9.6", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.9.6.tgz", + "integrity": "sha512-gf5no6N9FCk1qMrti4lfwP77JHP5haASZgVbBgpZG7BUepB3fhiLCXGUK8LvuOjP36HivXewjg72LTnPDScnQQ==", "cpu": [ "arm64" ], @@ -3142,9 +3516,9 @@ } }, "node_modules/@tauri-apps/cli-darwin-x64": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.6.2.tgz", - "integrity": "sha512-21gdPWfv1bP8rkTdCL44in70QcYcPaDM70L+y78N8TkBuC+/+wqnHcwwjzb+mUyck6UoEw2DORagSI/oKKUGJw==", + "version": "2.9.6", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.9.6.tgz", + "integrity": "sha512-oWh74WmqbERwwrwcueJyY6HYhgCksUc6NT7WKeXyrlY/FPmNgdyQAgcLuTSkhRFuQ6zh4Np1HZpOqCTpeZBDcw==", "cpu": [ "x64" ], @@ -3159,9 +3533,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm-gnueabihf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.6.2.tgz", - "integrity": "sha512-MW8Y6HqHS5yzQkwGoLk/ZyE1tWpnz/seDoY4INsbvUZdknuUf80yn3H+s6eGKtT/0Bfqon/W9sY7pEkgHRPQgA==", + "version": "2.9.6", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.9.6.tgz", + "integrity": "sha512-/zde3bFroFsNXOHN204DC2qUxAcAanUjVXXSdEGmhwMUZeAQalNj5cz2Qli2elsRjKN/hVbZOJj0gQ5zaYUjSg==", "cpu": [ "arm" ], @@ -3176,9 +3550,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm64-gnu": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.6.2.tgz", - "integrity": "sha512-9PdINTUtnyrnQt9hvC4y1m0NoxKSw/wUB9OTBAQabPj8WLAdvySWiUpEiqJjwLhlu4T6ltXZRpNTEzous3/RXg==", + "version": "2.9.6", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.9.6.tgz", + "integrity": "sha512-pvbljdhp9VOo4RnID5ywSxgBs7qiylTPlK56cTk7InR3kYSTJKYMqv/4Q/4rGo/mG8cVppesKIeBMH42fw6wjg==", "cpu": [ "arm64" ], @@ -3193,9 +3567,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm64-musl": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.6.2.tgz", - "integrity": "sha512-LrcJTRr7FrtQlTDkYaRXIGo/8YU/xkWmBPC646WwKNZ/S6yqCiDcOMoPe7Cx4ZvcG6sK6LUCLQMfaSNEL7PT0A==", + "version": "2.9.6", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.9.6.tgz", + "integrity": "sha512-02TKUndpodXBCR0oP//6dZWGYcc22Upf2eP27NvC6z0DIqvkBBFziQUcvi2n6SrwTRL0yGgQjkm9K5NIn8s6jw==", "cpu": [ "arm64" ], @@ -3210,9 +3584,9 @@ } }, "node_modules/@tauri-apps/cli-linux-riscv64-gnu": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-riscv64-gnu/-/cli-linux-riscv64-gnu-2.6.2.tgz", - "integrity": "sha512-GnTshO/BaZ9KGIazz2EiFfXGWgLur5/pjqklRA/ck42PGdUQJhV/Ao7A7TdXPjqAzpFxNo6M/Hx0GCH2iMS7IA==", + "version": "2.9.6", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-riscv64-gnu/-/cli-linux-riscv64-gnu-2.9.6.tgz", + "integrity": "sha512-fmp1hnulbqzl1GkXl4aTX9fV+ubHw2LqlLH1PE3BxZ11EQk+l/TmiEongjnxF0ie4kV8DQfDNJ1KGiIdWe1GvQ==", "cpu": [ "riscv64" ], @@ -3227,9 +3601,9 @@ } }, "node_modules/@tauri-apps/cli-linux-x64-gnu": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.6.2.tgz", - "integrity": "sha512-QDG3WeJD6UJekmrtVPCJRzlKgn9sGzhvD58oAw5gIU+DRovgmmG2U1jH9fS361oYGjWWO7d/KM9t0kugZzi4lQ==", + "version": "2.9.6", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.9.6.tgz", + "integrity": "sha512-vY0le8ad2KaV1PJr+jCd8fUF9VOjwwQP/uBuTJvhvKTloEwxYA/kAjKK9OpIslGA9m/zcnSo74czI6bBrm2sYA==", "cpu": [ "x64" ], @@ -3244,9 +3618,9 @@ } }, "node_modules/@tauri-apps/cli-linux-x64-musl": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.6.2.tgz", - "integrity": "sha512-TNVTDDtnWzuVqWBFdZ4+8ZTg17tc21v+CT5XBQ+KYCoYtCrIaHpW04fS5Tmudi+vYdBwoPDfwpKEB6LhCeFraQ==", + "version": "2.9.6", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.9.6.tgz", + "integrity": "sha512-TOEuB8YCFZTWVDzsO2yW0+zGcoMiPPwcUgdnW1ODnmgfwccpnihDRoks+ABT1e3fHb1ol8QQWsHSCovb3o2ENQ==", "cpu": [ "x64" ], @@ -3261,9 +3635,9 @@ } }, "node_modules/@tauri-apps/cli-win32-arm64-msvc": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.6.2.tgz", - "integrity": "sha512-z77C1oa/hMLO/jM1JF39tK3M3v9nou7RsBnQoOY54z5WPcpVAbS0XdFhXB7sSN72BOiO3moDky9lQANQz6L3CA==", + "version": "2.9.6", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.9.6.tgz", + "integrity": "sha512-ujmDGMRc4qRLAnj8nNG26Rlz9klJ0I0jmZs2BPpmNNf0gM/rcVHhqbEkAaHPTBVIrtUdf7bGvQAD2pyIiUrBHQ==", "cpu": [ "arm64" ], @@ -3278,9 +3652,9 @@ } }, "node_modules/@tauri-apps/cli-win32-ia32-msvc": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.6.2.tgz", - "integrity": "sha512-TmD8BbzbjluBw8+QEIWUVmFa9aAluSkT1N937n1mpYLXcPbTpbunqRFiIznTwupoJNJIdtpF/t7BdZDRh5rrcg==", + "version": "2.9.6", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.9.6.tgz", + "integrity": "sha512-S4pT0yAJgFX8QRCyKA1iKjZ9Q/oPjCZf66A/VlG5Yw54Nnr88J1uBpmenINbXxzyhduWrIXBaUbEY1K80ZbpMg==", "cpu": [ "ia32" ], @@ -3295,9 +3669,9 @@ } }, "node_modules/@tauri-apps/cli-win32-x64-msvc": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.6.2.tgz", - "integrity": "sha512-ItB8RCKk+nCmqOxOvbNtltz6x1A4QX6cSM21kj3NkpcnjT9rHSMcfyf8WVI2fkoMUJR80iqCblUX6ARxC3lj6w==", + "version": "2.9.6", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.9.6.tgz", + "integrity": "sha512-ldWuWSSkWbKOPjQMJoYVj9wLHcOniv7diyI5UAJ4XsBdtaFB0pKHQsqw/ItUma0VXGC7vB4E9fZjivmxur60aw==", "cpu": [ "x64" ], @@ -3507,6 +3881,13 @@ "@types/unist": "*" } }, + "node_modules/@types/minimatch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/ms": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", @@ -3517,7 +3898,6 @@ "version": "22.16.4", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.16.4.tgz", "integrity": "sha512-PYRhNtZdm2wH/NT2k/oAJ6/f2VD2N2Dag0lGlx2vWgMSJXGNmlce5MiTQzoWAiIJtso30mjnfQCOKVH+kAQC/g==", - "devOptional": true, "license": "MIT", "dependencies": { "undici-types": "~6.21.0" @@ -3540,6 +3920,7 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.23.tgz", "integrity": "sha512-/LDXMQh55EzZQ0uVAZmKKhfENivEvWz6E+EYzh+/MCjMhNsotd+ZHhBGIjFDTi6+fz0OhQQQLbTgdQIxxCsC0w==", "license": "MIT", + "peer": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -3551,6 +3932,7 @@ "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", "devOptional": true, "license": "MIT", + "peer": true, "peerDependencies": { "@types/react": "^18.0.0" } @@ -3575,6 +3957,20 @@ "sharp": "*" } }, + "node_modules/@types/symlink-or-copy": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@types/symlink-or-copy/-/symlink-or-copy-1.2.2.tgz", + "integrity": "sha512-MQ1AnmTLOncwEf9IVU+B2e4Hchrku5N67NkgcAHW0p3sdzPe0FNMANxEm6OJUzPniEQGkeT3OROLlCwZJLWFZA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "license": "MIT", + "optional": true + }, "node_modules/@types/unist": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", @@ -3793,6 +4189,32 @@ "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0" } }, + "node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/ansi-to-html": { "version": "0.7.2", "resolved": "https://registry.npmjs.org/ansi-to-html/-/ansi-to-html-0.7.2.tgz", @@ -3808,6 +4230,27 @@ "node": ">=8.0.0" } }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, "node_modules/aria-hidden": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz", @@ -3830,6 +4273,28 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/bare-events": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.8.2.tgz", + "integrity": "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==", + "dev": true, + "license": "Apache-2.0", + "peerDependencies": { + "bare-abort-controller": "*" + }, + "peerDependenciesMeta": { + "bare-abort-controller": { + "optional": true + } + } + }, "node_modules/base64-arraybuffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", @@ -3839,6 +4304,27 @@ "node": ">= 0.6.0" } }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/bcp-47-match": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/bcp-47-match/-/bcp-47-match-2.0.3.tgz", @@ -3849,13 +4335,51 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "license": "ISC" + "node_modules/bl": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz", + "integrity": "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer": "^6.0.3", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } }, - "node_modules/braces": { + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "license": "ISC" + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", @@ -3867,6 +4391,92 @@ "node": ">=8" } }, + "node_modules/broccoli-node-api": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/broccoli-node-api/-/broccoli-node-api-1.7.0.tgz", + "integrity": "sha512-QIqLSVJWJUVOhclmkmypJJH9u9s/aWH4+FH6Q6Ju5l+Io4dtwqdPUNmDfw40o6sxhbZHhqGujDJuHTML1wG8Yw==", + "dev": true, + "license": "MIT" + }, + "node_modules/broccoli-node-info": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/broccoli-node-info/-/broccoli-node-info-2.2.0.tgz", + "integrity": "sha512-VabSGRpKIzpmC+r+tJueCE5h8k6vON7EIMMWu6d/FyPdtijwLQ7QvzShEw+m3mHoDzUaj/kiZsDYrS8X2adsBg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "8.* || >= 10.*" + } + }, + "node_modules/broccoli-output-wrapper": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/broccoli-output-wrapper/-/broccoli-output-wrapper-3.2.5.tgz", + "integrity": "sha512-bQAtwjSrF4Nu0CK0JOy5OZqw9t5U0zzv2555EA/cF8/a8SLDTIetk9UgrtMVw7qKLKdSpOZ2liZNeZZDaKgayw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fs-extra": "^8.1.0", + "heimdalljs-logger": "^0.1.10", + "symlink-or-copy": "^1.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + } + }, + "node_modules/broccoli-output-wrapper/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/broccoli-output-wrapper/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/broccoli-output-wrapper/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/broccoli-plugin": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/broccoli-plugin/-/broccoli-plugin-4.0.7.tgz", + "integrity": "sha512-a4zUsWtA1uns1K7p9rExYVYG99rdKeGRymW0qOCNkvDPHQxVi3yVyJHhQbM3EZwdt2E0mnhr5e0c/bPpJ7p3Wg==", + "dev": true, + "license": "MIT", + "dependencies": { + "broccoli-node-api": "^1.7.0", + "broccoli-output-wrapper": "^3.2.5", + "fs-merger": "^3.2.1", + "promise-map-series": "^0.3.0", + "quick-temp": "^0.1.8", + "rimraf": "^3.0.2", + "symlink-or-copy": "^1.3.1" + }, + "engines": { + "node": "10.* || >= 12.*" + } + }, "node_modules/browserslist": { "version": "4.25.1", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz", @@ -3887,6 +4497,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001726", "electron-to-chromium": "^1.5.173", @@ -3900,6 +4511,31 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, "node_modules/caniuse-lite": { "version": "1.0.30001727", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001727.tgz", @@ -3971,6 +4607,50 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/cheerio": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.2.0.tgz", + "integrity": "sha512-WDrybc/gKFpTYQutKIK6UvfcuxijIZfMfXaYm8NMsPQxSYvf+13fXUJ4rztGGbJcBQ/GF55gvrZ0Bc0bj/mqvg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cheerio-select": "^2.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.2.2", + "encoding-sniffer": "^0.2.1", + "htmlparser2": "^10.1.0", + "parse5": "^7.3.0", + "parse5-htmlparser2-tree-adapter": "^7.1.0", + "parse5-parser-stream": "^7.1.2", + "undici": "^7.19.0", + "whatwg-mimetype": "^4.0.0" + }, + "engines": { + "node": ">=20.18.1" + }, + "funding": { + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" + } + }, + "node_modules/cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, "node_modules/chownr": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", @@ -3992,6 +4672,16 @@ "url": "https://polar.sh/cva" } }, + "node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, "node_modules/clsx": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", @@ -4046,6 +4736,16 @@ "simple-swizzle": "^0.2.2" } }, + "node_modules/colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.1.90" + } + }, "node_modules/comma-separated-tokens": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", @@ -4056,6 +4756,23 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -4063,6 +4780,38 @@ "dev": true, "license": "MIT" }, + "node_modules/core-js": { + "version": "3.48.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.48.0.tgz", + "integrity": "sha512-zpEHTy1fjTMZCKLHUZoVeylt9XrzaIN2rbPXEt0k+q7JE5CkCZdo6bNq55bn24a69CH7ErAVLKijxJja4fw+UQ==", + "hasInstallScript": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/css-line-break": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz", @@ -4072,6 +4821,23 @@ "utrie": "^1.0.2" } }, + "node_modules/css-select": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", + "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, "node_modules/css-selector-parser": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/css-selector-parser/-/css-selector-parser-3.1.3.tgz", @@ -4088,6 +4854,19 @@ ], "license": "MIT" }, + "node_modules/css-what": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", @@ -4302,9 +5081,9 @@ } }, "node_modules/diff": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.2.tgz", - "integrity": "sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg==", + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.3.tgz", + "integrity": "sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ==", "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" @@ -4333,6 +5112,94 @@ "csstype": "^3.0.2" } }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dev": true, + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/dom-serializer/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/dompurify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.1.tgz", + "integrity": "sha512-qkdCKzLNtrgPFP1Vo+98FRzJnBRGe4ffyCea9IwHB1fyxPOeNTHpLKYGd4Uk9xvNoH0ZoOjwZxNptyMwqrId1Q==", + "license": "(MPL-2.0 OR Apache-2.0)", + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } + }, + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, "node_modules/electron-to-chromium": { "version": "1.5.186", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.186.tgz", @@ -4340,6 +5207,27 @@ "dev": true, "license": "ISC" }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/encoding-sniffer": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.1.tgz", + "integrity": "sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "^0.6.3", + "whatwg-encoding": "^3.1.1" + }, + "funding": { + "url": "https://github.com/fb55/encoding-sniffer?sponsor=1" + } + }, "node_modules/enhanced-resolve": { "version": "5.18.2", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz", @@ -4353,6 +5241,13 @@ "node": ">=10.13.0" } }, + "node_modules/ensure-posix-path": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ensure-posix-path/-/ensure-posix-path-1.1.1.tgz", + "integrity": "sha512-VWU0/zXzVbeJNXvME/5EmLuEj2TauvoaTz6aFYK1Z92JCBlDlZ3Gu0tuGR42kpW1754ywTs+QB0g5TP0oj9Zaw==", + "dev": true, + "license": "ISC" + }, "node_modules/entities": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", @@ -4362,6 +5257,13 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/eol": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/eol/-/eol-0.9.1.tgz", + "integrity": "sha512-Ds/TEoZjwggRoz/Q2O7SE3i4Jm66mqTDfmdHdq/7DKVk3bro9Q8h6WdXKdPqFLMoqxrDK5SVRzHVPOS6uuGtrg==", + "dev": true, + "license": "MIT" + }, "node_modules/esbuild": { "version": "0.25.6", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.6.tgz", @@ -4441,6 +5343,16 @@ "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", "license": "MIT" }, + "node_modules/events-universal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz", + "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "bare-events": "^2.7.0" + } + }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -4456,6 +5368,23 @@ "node": ">=6.0.0" } }, + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, "node_modules/fault": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/fault/-/fault-1.0.4.tgz", @@ -4469,6 +5398,12 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/fflate": { + "version": "0.4.8", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.4.8.tgz", + "integrity": "sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==", + "license": "MIT" + }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -4481,6 +5416,23 @@ "node": ">=8" } }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/format": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", @@ -4516,21 +5468,123 @@ } } }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "hasInstallScript": true, + "node_modules/fs-extra": { + "version": "11.3.3", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.3.tgz", + "integrity": "sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + "node": ">=14.14" } }, - "node_modules/gensync": { + "node_modules/fs-merger": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/fs-merger/-/fs-merger-3.2.1.tgz", + "integrity": "sha512-AN6sX12liy0JE7C2evclwoo0aCG3PFulLjrTLsJpWh/2mM+DinhpSGqYLbHBBbIW1PLRNcFhJG8Axtz8mQW3ug==", + "dev": true, + "license": "MIT", + "dependencies": { + "broccoli-node-api": "^1.7.0", + "broccoli-node-info": "^2.1.0", + "fs-extra": "^8.0.1", + "fs-tree-diff": "^2.0.1", + "walk-sync": "^2.2.0" + } + }, + "node_modules/fs-merger/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/fs-merger/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/fs-merger/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/fs-mkdirp-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-2.0.1.tgz", + "integrity": "sha512-UTOY+59K6IA94tec8Wjqm0FSh5OVudGNB0NL/P6fB3HiE3bYOY3VYBGijsnOHNkQSwC1FKkU77pmq7xp9CskLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.8", + "streamx": "^2.12.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/fs-tree-diff": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fs-tree-diff/-/fs-tree-diff-2.0.1.tgz", + "integrity": "sha512-x+CfAZ/lJHQqwlD64pYM5QxWjzWhSjroaVsr8PW831zOApL55qPibed0c+xebaLWVr2BnHFoHdrwOv8pzt8R5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/symlink-or-copy": "^1.2.0", + "heimdalljs-logger": "^0.1.7", + "object-assign": "^4.1.0", + "path-posix": "^1.0.0", + "symlink-or-copy": "^1.1.8" + }, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", @@ -4555,12 +5609,77 @@ "integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==", "license": "ISC" }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob-stream": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-8.0.3.tgz", + "integrity": "sha512-fqZVj22LtFJkHODT+M4N1RJQ3TjnnQhfE9GwZI8qXscYarnhpip70poMldRnP8ipQ/w0B621kOhfc53/J9bd/A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@gulpjs/to-absolute-glob": "^4.0.0", + "anymatch": "^3.1.3", + "fastq": "^1.13.0", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "is-negated-glob": "^1.0.0", + "normalize-path": "^3.0.0", + "streamx": "^2.12.5" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "license": "ISC" }, + "node_modules/gulp-sort": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/gulp-sort/-/gulp-sort-2.0.0.tgz", + "integrity": "sha512-MyTel3FXOdh1qhw1yKhpimQrAmur9q1X0ZigLmCOxouQD+BD3za9/89O+HfbgBQvvh4igEbp0/PUWO+VqGYG1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "through2": "^2.0.1" + } + }, "node_modules/hast-util-from-html": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz", @@ -4900,6 +6019,51 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/heimdalljs": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/heimdalljs/-/heimdalljs-0.2.6.tgz", + "integrity": "sha512-o9bd30+5vLBvBtzCPwwGqpry2+n0Hi6H1+qwt6y+0kwRHGGF8TFIhJPmnuM0xO97zaKrDZMwO/V56fAnn8m/tA==", + "dev": true, + "license": "MIT", + "dependencies": { + "rsvp": "~3.2.1" + } + }, + "node_modules/heimdalljs-logger": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/heimdalljs-logger/-/heimdalljs-logger-0.1.10.tgz", + "integrity": "sha512-pO++cJbhIufVI/fmB/u2Yty3KJD0TqNPecehFae0/eps0hkZ3b4Zc/PezUMOpYuHFQbA7FxHZxa305EhmjLj4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^2.2.0", + "heimdalljs": "^0.2.6" + } + }, + "node_modules/heimdalljs-logger/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/heimdalljs-logger/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/heimdalljs/node_modules/rsvp": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-3.2.1.tgz", + "integrity": "sha512-Rf4YVNYpKjZ6ASAmibcwTNciQ5Co5Ztq6iZPEykHpkoflnD/K5ryE/rHehFsTm4NJj8nKDhbi3eKBWGogmNnkg==", + "dev": true, + "license": "MIT" + }, "node_modules/highlight.js": { "version": "10.7.3", "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", @@ -4915,6 +6079,15 @@ "integrity": "sha512-PDEfEF102G23vHmPhLyPboFCD+BkMGu+GuJe2d9/eH4FsCwvgBpnc9n0pGE+ffKdph38s6foEZiEjdgHdzp+IA==", "license": "CC0-1.0" }, + "node_modules/html-parse-stringify": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz", + "integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==", + "license": "MIT", + "dependencies": { + "void-elements": "3.1.0" + } + }, "node_modules/html-url-attributes": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.1.tgz", @@ -4948,6 +6121,199 @@ "node": ">=8.0.0" } }, + "node_modules/htmlparser2": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.1.0.tgz", + "integrity": "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.2.2", + "entities": "^7.0.1" + } + }, + "node_modules/htmlparser2/node_modules/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/i18next": { + "version": "25.8.0", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-25.8.0.tgz", + "integrity": "sha512-urrg4HMFFMQZ2bbKRK7IZ8/CTE7D8H4JRlAwqA2ZwDRFfdd0K/4cdbNNLgfn9mo+I/h9wJu61qJzH7jCFAhUZQ==", + "funding": [ + { + "type": "individual", + "url": "https://locize.com" + }, + { + "type": "individual", + "url": "https://locize.com/i18next.html" + }, + { + "type": "individual", + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.28.4" + }, + "peerDependencies": { + "typescript": "^5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/i18next-browser-languagedetector": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-8.2.0.tgz", + "integrity": "sha512-P+3zEKLnOF0qmiesW383vsLdtQVyKtCNA9cjSoKCppTKPQVfKd2W8hbVo5ZhNJKDqeM7BOcvNoKJOjpHh4Js9g==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.2" + } + }, + "node_modules/i18next-parser": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/i18next-parser/-/i18next-parser-9.3.0.tgz", + "integrity": "sha512-VaQqk/6nLzTFx1MDiCZFtzZXKKyBV6Dv0cJMFM/hOt4/BWHWRgYafzYfVQRUzotwUwjqeNCprWnutzD/YAGczg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.25.0", + "broccoli-plugin": "^4.0.7", + "cheerio": "^1.0.0", + "colors": "^1.4.0", + "commander": "^12.1.0", + "eol": "^0.9.1", + "esbuild": "^0.25.0", + "fs-extra": "^11.2.0", + "gulp-sort": "^2.0.0", + "i18next": "^23.5.1 || ^24.2.0", + "js-yaml": "^4.1.0", + "lilconfig": "^3.1.3", + "rsvp": "^4.8.5", + "sort-keys": "^5.0.0", + "typescript": "^5.0.4", + "vinyl": "^3.0.0", + "vinyl-fs": "^4.0.0" + }, + "bin": { + "i18next": "bin/cli.js" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || ^22.0.0", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/i18next-parser/node_modules/i18next": { + "version": "24.2.3", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-24.2.3.tgz", + "integrity": "sha512-lfbf80OzkocvX7nmZtu7nSTNbrTYR52sLWxPtlXX1zAhVw8WEnFk4puUkCR4B1dNQwbSpEHHHemcZu//7EcB7A==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://locize.com" + }, + { + "type": "individual", + "url": "https://locize.com/i18next.html" + }, + { + "type": "individual", + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + } + ], + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.26.10" + }, + "peerDependencies": { + "typescript": "^5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, "node_modules/inline-style-parser": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.4.tgz", @@ -5013,6 +6379,16 @@ "node": ">=0.10.0" } }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -5035,6 +6411,16 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/is-negated-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", + "integrity": "sha512-czXVVn/QEmgvej1f50BZ648vUI+em0xqMq2Sn+QncCLN4zj1UAxlT+kw/6ggQTOaZPd1HqKQGEqbpQVtJucWug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -5056,6 +6442,45 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-valid-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", + "integrity": "sha512-AhiROmoEFDSsjx8hW+5sGwgKVIORcXnrlAx/R0ZSeaPw70Vw0CqkGBBhHGL58Uox2eXnU1AnvXJl1XlyedO5bA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, "node_modules/jiti": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz", @@ -5071,6 +6496,19 @@ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "license": "MIT" }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/jsesc": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", @@ -5097,6 +6535,29 @@ "node": ">=6" } }, + "node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/lead": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/lead/-/lead-4.0.0.tgz", + "integrity": "sha512-DpMa59o5uGUWWjruMp71e6knmwKU3jRBBn1kjuLWN9EeIOxNeSAwvHf03WIl8g/ZMR2oSQC9ej3yeLBwdDc/pg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/lightningcss": { "version": "1.30.1", "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz", @@ -5334,12 +6795,31 @@ "node": ">=8" } }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", "license": "MIT" }, + "node_modules/long": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "license": "Apache-2.0" + }, "node_modules/longest-streak": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", @@ -5414,6 +6894,20 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/matcher-collection": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/matcher-collection/-/matcher-collection-2.0.1.tgz", + "integrity": "sha512-daE62nS2ZQsDg9raM0IlZzLmI2u+7ZapXBwdoeBUKAYERPDDIc0qNqA8E0Rp2D+gspKR7BgIFP52GeujaGXWeQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "@types/minimatch": "^3.0.3", + "minimatch": "^3.0.2" + }, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, "node_modules/mdast-util-find-and-replace": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz", @@ -5630,9 +7124,9 @@ } }, "node_modules/mdast-util-to-hast": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", - "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", + "version": "13.2.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", + "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", @@ -6260,6 +7754,19 @@ "node": ">=8.6" } }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/minipass": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", @@ -6270,9 +7777,9 @@ } }, "node_modules/minizlib": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz", - "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", + "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", "license": "MIT", "dependencies": { "minipass": "^7.1.2" @@ -6281,19 +7788,14 @@ "node": ">= 18" } }, - "node_modules/mkdirp": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", - "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "node_modules/mktemp": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/mktemp/-/mktemp-2.0.2.tgz", + "integrity": "sha512-Q9wJ/xhzeD9Wua1MwDN2v3ah3HENsUVSlzzL9Qw149cL9hHZkXtQGl3Eq36BbdLV+/qUwaP1WtJQ+H/+Oxso8g==", + "dev": true, "license": "MIT", - "bin": { - "mkdirp": "dist/cjs/src/bin.js" - }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": "20 || 22 || 24" } }, "node_modules/motion-dom": { @@ -6357,6 +7859,29 @@ "dev": true, "license": "MIT" }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/now-and-later": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-3.0.0.tgz", + "integrity": "sha512-pGO4pzSdaxhWTGkfSfHx3hVzJVslFPwBp2Myq9MYN/ChfJZF87ochMAXnvz6/58RJSf5ik2q9tXprBBrk2cpcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, "node_modules/nth-check": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", @@ -6378,6 +7903,23 @@ "node": ">=0.10.0" } }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, "node_modules/parse-entities": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", @@ -6421,18 +7963,95 @@ "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/parse5/node_modules/entities": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", - "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", - "license": "BSD-2-Clause", + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz", + "integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "domhandler": "^5.0.3", + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-parser-stream": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz", + "integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==", + "dev": true, + "license": "MIT", + "dependencies": { + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-posix": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/path-posix/-/path-posix-1.0.0.tgz", + "integrity": "sha512-1gJ0WpNIiYcQydgg3Ed8KzvIqTsDpNwq+cjBCssvBtuTWjEqY1AW+i+OepiEMqDCzyro9B2sLAe4RBPajMYFiA==", + "dev": true, + "license": "ISC" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, "engines": { - "node": ">=0.12" + "node": ">=16 || 14 >=14.18" }, "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -6479,6 +8098,37 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/posthog-js": { + "version": "1.336.4", + "resolved": "https://registry.npmjs.org/posthog-js/-/posthog-js-1.336.4.tgz", + "integrity": "sha512-NX81XaqOjS/gue3UsbAAuJxi6vD0AGy1HUvywBIhAArCwbTXKS04NhEFwUcYJdrmwXUf94MntEIWGoc1pTFDtg==", + "license": "SEE LICENSE IN LICENSE", + "dependencies": { + "@opentelemetry/api": "^1.9.0", + "@opentelemetry/api-logs": "^0.208.0", + "@opentelemetry/exporter-logs-otlp-http": "^0.208.0", + "@opentelemetry/resources": "^2.2.0", + "@opentelemetry/sdk-logs": "^0.208.0", + "@posthog/core": "1.17.0", + "@posthog/types": "1.336.4", + "core-js": "^3.38.1", + "dompurify": "^3.3.1", + "fflate": "^0.4.8", + "preact": "^10.28.2", + "query-selector-shadow-dom": "^1.0.1", + "web-vitals": "^5.1.0" + } + }, + "node_modules/preact": { + "version": "10.28.3", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.28.3.tgz", + "integrity": "sha512-tCmoRkPQLpBeWzpmbhryairGnhW9tKV6c6gr/w+RhoRoKEJwsjzipwp//1oCpGPOchvSLaAPlpcJi9MwMmoPyA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, "node_modules/prismjs": { "version": "1.30.0", "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz", @@ -6488,6 +8138,23 @@ "node": ">=6" } }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true, + "license": "MIT" + }, + "node_modules/promise-map-series": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/promise-map-series/-/promise-map-series-0.3.0.tgz", + "integrity": "sha512-3npG2NGhTc8BWBolLLf8l/92OxMGaRLbqvIh9wjCHhDXNvk4zsxaTaCpiCunW09qWPrN2zeNSNwRLVBrQQtutA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "10.* || >= 12.*" + } + }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -6515,11 +8182,117 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/protobufjs": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.4.tgz", + "integrity": "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/query-selector-shadow-dom": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/query-selector-shadow-dom/-/query-selector-shadow-dom-1.0.1.tgz", + "integrity": "sha512-lT5yCqEBgfoMYpf3F2xQRK7zEr1rhIIZuceDK6+xRkJQ4NMbHTwXqk4NkwDwQMNqXgG9r9fyHnzwNVs6zV5KRw==", + "license": "MIT" + }, + "node_modules/quick-temp": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/quick-temp/-/quick-temp-0.1.9.tgz", + "integrity": "sha512-yI0h7tIhKVObn03kD+Ln9JFi4OljD28lfaOsTdfpTR0xzrhGOod+q66CjGafUqYX2juUfT9oHIGrTBBo22mkRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mktemp": "^2.0.1", + "rimraf": "^5.0.10", + "underscore.string": "~3.3.6" + } + }, + "node_modules/quick-temp/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/quick-temp/node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/quick-temp/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/quick-temp/node_modules/rimraf": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", + "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^10.3.7" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/react": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "license": "MIT", + "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -6532,6 +8305,7 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "license": "MIT", + "peer": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" @@ -6545,6 +8319,7 @@ "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.60.0.tgz", "integrity": "sha512-SBrYOvMbDB7cV8ZfNpaiLcgjH/a1c7aK0lK+aNigpf4xWLO8q+o4tcvVurv3c4EOyzn/3dCsYt4GKD42VvJ/+A==", "license": "MIT", + "peer": true, "engines": { "node": ">=18.0.0" }, @@ -6556,6 +8331,33 @@ "react": "^16.8.0 || ^17 || ^18 || ^19" } }, + "node_modules/react-i18next": { + "version": "16.5.4", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-16.5.4.tgz", + "integrity": "sha512-6yj+dcfMncEC21QPhOTsW8mOSO+pzFmT6uvU7XXdvM/Cp38zJkmTeMeKmTrmCMD5ToT79FmiE/mRWiYWcJYW4g==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4", + "html-parse-stringify": "^3.0.1", + "use-sync-external-store": "^1.6.0" + }, + "peerDependencies": { + "i18next": ">= 25.6.2", + "react": ">= 16.8.0", + "typescript": "^5" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, "node_modules/react-is": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", @@ -6684,16 +8486,16 @@ } }, "node_modules/react-syntax-highlighter": { - "version": "15.6.1", - "resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-15.6.1.tgz", - "integrity": "sha512-OqJ2/vL7lEeV5zTJyG7kmARppUjiB9h9udl4qHQjjgEos66z00Ia0OckwYfRxCSFrW8RJIBnsBwQsHZbVPspqg==", + "version": "15.6.6", + "resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-15.6.6.tgz", + "integrity": "sha512-DgXrc+AZF47+HvAPEmn7Ua/1p10jNoVZVI/LoPiYdtY+OM+/nG5yefLHKJwdKqY1adMuHFbeyBaG9j64ML7vTw==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.3.1", "highlight.js": "^10.4.1", "highlightjs-vue": "^1.0.0", "lowlight": "^1.17.0", - "prismjs": "^1.27.0", + "prismjs": "^1.30.0", "refractor": "^3.6.0" }, "peerDependencies": { @@ -6716,6 +8518,22 @@ "react-dom": ">=16.6.0" } }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, "node_modules/recharts": { "version": "2.15.4", "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.15.4.tgz", @@ -7176,6 +8994,64 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==", + "dev": true, + "license": "ISC" + }, + "node_modules/replace-ext": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-2.0.0.tgz", + "integrity": "sha512-UszKE5KVK6JvyD92nzMn9cDapSk6w/CaFZ96CnmDMUqH9oowfxF/ZjRITD25H4DnOQClLA4/j7jLGXXLVKxAug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/resolve-options": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-2.0.0.tgz", + "integrity": "sha512-/FopbmmFOQCfsCx77BRFdKOniglTiHumLgwvd6IDPihy1GKkadZbgQJBcTb2lMzSR1pndzd96b1nZrreZ7+9/A==", + "dev": true, + "license": "MIT", + "dependencies": { + "value-or-function": "^4.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/rollup": { "version": "4.45.1", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.45.1.tgz", @@ -7215,6 +9091,30 @@ "fsevents": "~2.3.2" } }, + "node_modules/rsvp": { + "version": "4.8.5", + "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz", + "integrity": "sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "6.* || >= 7.*" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT" + }, "node_modules/scheduler": { "version": "0.23.2", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", @@ -7300,6 +9200,40 @@ "node": ">=10" } }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/simple-swizzle": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", @@ -7310,6 +9244,22 @@ "is-arrayish": "^0.3.1" } }, + "node_modules/sort-keys": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-5.1.0.tgz", + "integrity": "sha512-aSbHV0DaBcr7u0PVHXzM6NbZNAtrr9sF6+Qfs9UUVG7Ll3jQ6hHi8F/xqIIcn2rvIVbr0v/2zyjSdwSV47AgLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-plain-obj": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -7324,9 +9274,112 @@ "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/stream-composer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-composer/-/stream-composer-1.0.2.tgz", + "integrity": "sha512-bnBselmwfX5K10AH6L4c8+S5lgZMWI7ZYrz2rvYjCPB2DIMC4Ig8OpxGpNJSxRZ58oti7y1IcNvjBAz9vW5m4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "streamx": "^2.13.2" + } + }, + "node_modules/streamx": { + "version": "2.23.0", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.23.0.tgz", + "integrity": "sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "events-universal": "^1.0.0", + "fast-fifo": "^1.3.2", + "text-decoder": "^1.1.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" } }, "node_modules/stringify-entities": { @@ -7343,6 +9396,46 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/style-to-js": { "version": "1.1.17", "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.17.tgz", @@ -7361,6 +9454,13 @@ "inline-style-parser": "0.2.4" } }, + "node_modules/symlink-or-copy": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/symlink-or-copy/-/symlink-or-copy-1.3.1.tgz", + "integrity": "sha512-0K91MEXFpBUaywiwSSkmKjnGcasG/rVBXFLJz5DrgGabpYD6N+3yZrfD6uUIfpuTu65DZLHi7N8CizHc07BPZA==", + "dev": true, + "license": "MIT" + }, "node_modules/tailwind-merge": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.6.0.tgz", @@ -7387,16 +9487,15 @@ } }, "node_modules/tar": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", - "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", - "license": "ISC", + "version": "7.5.7", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.7.tgz", + "integrity": "sha512-fov56fJiRuThVFXD6o6/Q354S7pnWMJIVlDBYijsTNx6jKSE4pvrDTs6lUnmGvNyfJwFQQwWy3owKz1ucIhveQ==", + "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", - "minizlib": "^3.0.1", - "mkdirp": "^3.0.1", + "minizlib": "^3.1.0", "yallist": "^5.0.0" }, "engines": { @@ -7412,6 +9511,41 @@ "node": ">=18" } }, + "node_modules/teex": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/teex/-/teex-1.0.1.tgz", + "integrity": "sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "streamx": "^2.12.5" + } + }, + "node_modules/text-decoder": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz", + "integrity": "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "b4a": "^1.6.4" + } + }, + "node_modules/text-decoder/node_modules/b4a": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.7.3.tgz", + "integrity": "sha512-5Q2mfq2WfGuFp3uS//0s6baOJLMoVduPYVeNmDYxu5OUA1/cBfvr2RIS7vi62LdNj/urk1hfmj867I3qt6uZ7Q==", + "dev": true, + "license": "Apache-2.0", + "peerDependencies": { + "react-native-b4a": "*" + }, + "peerDependenciesMeta": { + "react-native-b4a": { + "optional": true + } + } + }, "node_modules/text-segmentation": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz", @@ -7421,6 +9555,17 @@ "utrie": "^1.0.2" } }, + "node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, "node_modules/tiny-invariant": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", @@ -7462,6 +9607,7 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -7481,6 +9627,19 @@ "node": ">=8.0" } }, + "node_modules/to-through": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/to-through/-/to-through-3.0.0.tgz", + "integrity": "sha512-y8MN937s/HVhEoBU1SxfHC+wxCHkV1a9gW8eAdTadYh/bGyesZIVcbjI+mSpFbSVwQici/XjBjuUyri1dnXwBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "streamx": "^2.12.5" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/trim-lines": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", @@ -7511,8 +9670,9 @@ "version": "5.6.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", - "dev": true, + "devOptional": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -7521,11 +9681,34 @@ "node": ">=14.17" } }, + "node_modules/underscore.string": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.6.tgz", + "integrity": "sha512-VoC83HWXmCrF6rgkyxS9GHv8W9Q5nhMKho+OadDJGzL2oDYbYEppBaCMH6pFlwLeqj2QS+hhkw2kpXkSdD1JxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "^1.1.1", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/undici": { + "version": "7.19.2", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.19.2.tgz", + "integrity": "sha512-4VQSpGEGsWzk0VYxyB/wVX/Q7qf9t5znLRgs0dzszr9w9Fej/8RVNQ+S20vdXSAyra/bJ7ZQfGv6ZMj7UEbzSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, "node_modules/undici-types": { "version": "6.21.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", - "devOptional": true, "license": "MIT" }, "node_modules/unified": { @@ -7626,6 +9809,16 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/update-browserslist-db": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", @@ -7700,6 +9893,22 @@ } } }, + "node_modules/use-sync-external-store": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", + "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, "node_modules/utrie": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz", @@ -7709,6 +9918,16 @@ "base64-arraybuffer": "^1.0.2" } }, + "node_modules/value-or-function": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-4.0.0.tgz", + "integrity": "sha512-aeVK81SIuT6aMJfNo9Vte8Dw0/FZINGBV8BfCraGtqVxIeLAEhJyoWs8SmvRVmXfGss2PmmOwZCuBPbZR+IYWg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.13.0" + } + }, "node_modules/vfile": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", @@ -7773,11 +9992,86 @@ "d3-timer": "^3.0.1" } }, + "node_modules/vinyl": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-3.0.1.tgz", + "integrity": "sha512-0QwqXteBNXgnLCdWdvPQBX6FXRHtIH3VhJPTd5Lwn28tJXc34YqSCWUmkOvtJHBmB3gGoPtrOKk3Ts8/kEZ9aA==", + "dev": true, + "license": "MIT", + "dependencies": { + "clone": "^2.1.2", + "remove-trailing-separator": "^1.1.0", + "replace-ext": "^2.0.0", + "teex": "^1.0.1" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/vinyl-contents": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/vinyl-contents/-/vinyl-contents-2.0.0.tgz", + "integrity": "sha512-cHq6NnGyi2pZ7xwdHSW1v4Jfnho4TEGtxZHw01cmnc8+i7jgR6bRnED/LbrKan/Q7CvVLbnvA5OepnhbpjBZ5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "bl": "^5.0.0", + "vinyl": "^3.0.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/vinyl-fs": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-4.0.2.tgz", + "integrity": "sha512-XRFwBLLTl8lRAOYiBqxY279wY46tVxLaRhSwo3GzKEuLz1giffsOquWWboD/haGf5lx+JyTigCFfe7DWHoARIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fs-mkdirp-stream": "^2.0.1", + "glob-stream": "^8.0.3", + "graceful-fs": "^4.2.11", + "iconv-lite": "^0.6.3", + "is-valid-glob": "^1.0.0", + "lead": "^4.0.0", + "normalize-path": "3.0.0", + "resolve-options": "^2.0.0", + "stream-composer": "^1.0.2", + "streamx": "^2.14.0", + "to-through": "^3.0.0", + "value-or-function": "^4.0.0", + "vinyl": "^3.0.1", + "vinyl-sourcemap": "^2.0.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/vinyl-sourcemap": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-2.0.0.tgz", + "integrity": "sha512-BAEvWxbBUXvlNoFQVFVHpybBbjW1r03WhohJzJDSfgrrK5xVYIDTan6xN14DlyImShgDRv2gl9qhM6irVMsV0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "convert-source-map": "^2.0.0", + "graceful-fs": "^4.2.10", + "now-and-later": "^3.0.0", + "streamx": "^2.12.5", + "vinyl": "^3.0.0", + "vinyl-contents": "^2.0.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/vite": { - "version": "6.3.5", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz", - "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", + "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", @@ -7866,6 +10160,7 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -7873,6 +10168,31 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/void-elements": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", + "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/walk-sync": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/walk-sync/-/walk-sync-2.2.0.tgz", + "integrity": "sha512-IC8sL7aB4/ZgFcGI2T1LczZeFWZ06b3zoHH7jBPyHxOtIIz1jppWHjjEXkOFvFojBVAK9pV7g47xOZ4LW3QLfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/minimatch": "^3.0.3", + "ensure-posix-path": "^1.1.0", + "matcher-collection": "^2.0.0", + "minimatch": "^3.0.4" + }, + "engines": { + "node": "8.* || >= 10.*" + } + }, "node_modules/web-namespaces": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", @@ -7883,6 +10203,156 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/web-vitals": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-5.1.0.tgz", + "integrity": "sha512-ArI3kx5jI0atlTtmV0fWU3fjpLmq/nD3Zr1iFFlJLaqa5wLBkUSzINwBPySCX/8jRyjlmy1Volw1kz1g9XE4Jg==", + "license": "Apache-2.0" + }, + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "deprecated": "Use @exodus/bytes instead for a more spec-conformant and faster implementation", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", diff --git a/package.json b/package.json index c072d265a..e482f6a67 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,9 @@ "preview": "vite preview", "tauri": "tauri", "build:dmg": "tauri build --bundles dmg", - "check": "tsc --noEmit && cd src-tauri && cargo check" + "check": "tsc --noEmit && cd src-tauri && cargo check", + "i18n:extract": "i18next-parser", + "i18n:check": "node scripts/check-translations.js" }, "dependencies": { "@hookform/resolvers": "^3.9.1", @@ -33,11 +35,11 @@ "@tailwindcss/cli": "^4.1.8", "@tailwindcss/vite": "^4.1.8", "@tanstack/react-virtual": "^3.13.10", - "@tauri-apps/api": "^2.1.1", - "@tauri-apps/plugin-dialog": "^2.0.2", - "@tauri-apps/plugin-global-shortcut": "^2.0.0", + "@tauri-apps/api": "~2.8.0", + "@tauri-apps/plugin-dialog": "~2.4.0", + "@tauri-apps/plugin-global-shortcut": "~2.3.0", "@tauri-apps/plugin-opener": "^2", - "@tauri-apps/plugin-shell": "^2.0.1", + "@tauri-apps/plugin-shell": "~2.3.0", "@types/diff": "^8.0.0", "@types/react-syntax-highlighter": "^15.5.13", "@uiw/react-md-editor": "^4.0.7", @@ -48,11 +50,14 @@ "diff": "^8.0.2", "framer-motion": "^12.0.0-alpha.1", "html2canvas": "^1.4.1", + "i18next": "^25.8.0", + "i18next-browser-languagedetector": "^8.2.0", "lucide-react": "^0.468.0", "posthog-js": "^1.258.3", "react": "^18.3.1", "react-dom": "^18.3.1", "react-hook-form": "^7.54.2", + "react-i18next": "^16.5.4", "react-markdown": "^9.0.3", "react-syntax-highlighter": "^15.6.1", "recharts": "^2.14.1", @@ -63,12 +68,13 @@ "zustand": "^5.0.6" }, "devDependencies": { - "@tauri-apps/cli": "^2.7.1", + "@tauri-apps/cli": "~2.8.0", "@types/node": "^22.15.30", "@types/react": "^18.3.1", "@types/react-dom": "^18.3.1", "@types/sharp": "^0.32.0", "@vitejs/plugin-react": "^4.3.4", + "i18next-parser": "^9.3.0", "sharp": "^0.34.2", "typescript": "~5.6.2", "vite": "^6.0.3" diff --git a/scripts/check-translations.js b/scripts/check-translations.js new file mode 100644 index 000000000..707b36332 --- /dev/null +++ b/scripts/check-translations.js @@ -0,0 +1,191 @@ +#!/usr/bin/env node + +/** + * 国际化翻译完整性检查脚本 + * + * 功能: + * 1. 检查所有翻译文件的 JSON 语法 + * 2. 对比英文和中文翻译文件的键是否一致 + * 3. 检查是否有缺失的翻译 + * 4. 生成检查报告 + */ + +import fs from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +const LOCALES_DIR = path.join(__dirname, '../src/locales'); +const LANGUAGES = ['en', 'zh']; +const NAMESPACES = ['common', 'agents', 'projects', 'sessions', 'settings', 'mcp', 'usage', 'errors']; + +// 颜色输出 +const colors = { + reset: '\x1b[0m', + red: '\x1b[31m', + green: '\x1b[32m', + yellow: '\x1b[33m', + blue: '\x1b[34m', + cyan: '\x1b[36m', +}; + +function log(message, color = 'reset') { + console.log(`${colors[color]}${message}${colors.reset}`); +} + +// 读取并解析 JSON 文件 +function readTranslationFile(lang, namespace) { + const filePath = path.join(LOCALES_DIR, lang, `${namespace}.json`); + + try { + const content = fs.readFileSync(filePath, 'utf-8'); + return JSON.parse(content); + } catch (error) { + if (error.code === 'ENOENT') { + return null; + } + throw new Error(`Failed to parse ${filePath}: ${error.message}`); + } +} + +// 获取所有键的扁平化列表 +function flattenKeys(obj, prefix = '') { + const keys = []; + + for (const [key, value] of Object.entries(obj)) { + const fullKey = prefix ? `${prefix}.${key}` : key; + + if (typeof value === 'object' && value !== null && !Array.isArray(value)) { + keys.push(...flattenKeys(value, fullKey)); + } else { + keys.push(fullKey); + } + } + + return keys; +} + +// 检查单个命名空间 +function checkNamespace(namespace) { + log(`\n📦 检查命名空间: ${namespace}`, 'cyan'); + + const translations = {}; + const errors = []; + + // 读取所有语言的翻译文件 + for (const lang of LANGUAGES) { + const data = readTranslationFile(lang, namespace); + + if (!data) { + errors.push(`❌ 缺失文件: ${lang}/${namespace}.json`); + continue; + } + + translations[lang] = data; + } + + if (errors.length > 0) { + errors.forEach(err => log(err, 'red')); + return { namespace, errors, warnings: [], success: false }; + } + + // 获取所有键 + const enKeys = flattenKeys(translations.en); + const zhKeys = flattenKeys(translations.zh); + + const warnings = []; + + // 检查缺失的键 + const missingInZh = enKeys.filter(key => !zhKeys.includes(key)); + const missingInEn = zhKeys.filter(key => !enKeys.includes(key)); + + if (missingInZh.length > 0) { + warnings.push(`⚠️ 中文缺失 ${missingInZh.length} 个键:`); + missingInZh.forEach(key => warnings.push(` - ${key}`)); + } + + if (missingInEn.length > 0) { + warnings.push(`⚠️ 英文缺失 ${missingInEn.length} 个键:`); + missingInEn.forEach(key => warnings.push(` - ${key}`)); + } + + if (warnings.length === 0) { + log(`✅ 完整性检查通过 (${enKeys.length} 个键)`, 'green'); + } else { + warnings.forEach(warn => log(warn, 'yellow')); + } + + return { + namespace, + errors, + warnings, + success: errors.length === 0, + keyCount: enKeys.length, + missingInZh: missingInZh.length, + missingInEn: missingInEn.length, + }; +} + +// 主函数 +function main() { + log('🌐 国际化翻译完整性检查', 'blue'); + log('='.repeat(50), 'blue'); + + const results = []; + let totalErrors = 0; + let totalWarnings = 0; + + // 检查所有命名空间 + for (const namespace of NAMESPACES) { + const result = checkNamespace(namespace); + results.push(result); + + totalErrors += result.errors.length; + totalWarnings += result.warnings.length; + } + + // 生成总结报告 + log('\n' + '='.repeat(50), 'blue'); + log('📊 检查总结', 'blue'); + log('='.repeat(50), 'blue'); + + const totalKeys = results.reduce((sum, r) => sum + (r.keyCount || 0), 0); + const totalMissingZh = results.reduce((sum, r) => sum + (r.missingInZh || 0), 0); + const totalMissingEn = results.reduce((sum, r) => sum + (r.missingInEn || 0), 0); + + log(`\n总翻译键数: ${totalKeys}`); + log(`命名空间数: ${NAMESPACES.length}`); + log(`支持语言数: ${LANGUAGES.length}`); + + if (totalErrors > 0) { + log(`\n❌ 发现 ${totalErrors} 个错误`, 'red'); + } + + if (totalWarnings > 0) { + log(`⚠️ 发现 ${totalWarnings} 个警告`, 'yellow'); + log(` - 中文缺失: ${totalMissingZh} 个键`, 'yellow'); + log(` - 英文缺失: ${totalMissingEn} 个键`, 'yellow'); + } + + if (totalErrors === 0 && totalWarnings === 0) { + log('\n✅ 所有检查通过!翻译文件完整且一致。', 'green'); + process.exit(0); + } else if (totalErrors === 0) { + log('\n⚠️ 检查完成,但有警告需要处理。', 'yellow'); + process.exit(1); + } else { + log('\n❌ 检查失败,请修复错误后重试。', 'red'); + process.exit(1); + } +} + +// 运行检查 +try { + main(); +} catch (error) { + log(`\n❌ 检查过程中发生错误: ${error.message}`, 'red'); + console.error(error); + process.exit(1); +} diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 91288d4f6..56e43d43c 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -5,6 +5,7 @@ description = "GUI app and Toolkit for Claude Code" authors = ["mufeedvh", "123vviekr"] license = "AGPL-3.0" edition = "2021" +default-run = "opcode" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/src-tauri/diagnostics.json b/src-tauri/diagnostics.json new file mode 100644 index 000000000..cec1334f8 Binary files /dev/null and b/src-tauri/diagnostics.json differ diff --git a/src-tauri/src/checkpoint/mod.rs b/src-tauri/src/checkpoint/mod.rs index 030418bb6..79a439b79 100644 --- a/src-tauri/src/checkpoint/mod.rs +++ b/src-tauri/src/checkpoint/mod.rs @@ -96,7 +96,7 @@ pub struct SessionTimeline { } /// Strategy for automatic checkpoint creation -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize, Default)] #[serde(rename_all = "snake_case")] pub enum CheckpointStrategy { /// Only create checkpoints manually @@ -106,6 +106,7 @@ pub enum CheckpointStrategy { /// Create checkpoint after each tool use PerToolUse, /// Create checkpoint after destructive operations + #[default] Smart, } @@ -170,12 +171,6 @@ pub struct FileDiff { pub diff_content: Option, } -impl Default for CheckpointStrategy { - fn default() -> Self { - CheckpointStrategy::Smart - } -} - impl SessionTimeline { /// Create a new empty timeline pub fn new(session_id: String) -> Self { @@ -218,8 +213,10 @@ pub struct CheckpointPaths { pub files_dir: PathBuf, } +use std::path::Path; + impl CheckpointPaths { - pub fn new(claude_dir: &PathBuf, project_id: &str, session_id: &str) -> Self { + pub fn new(claude_dir: &Path, project_id: &str, session_id: &str) -> Self { let base_dir = claude_dir .join("projects") .join(project_id) diff --git a/src-tauri/src/checkpoint/state.rs b/src-tauri/src/checkpoint/state.rs index a633ebc3d..8da6a5d07 100644 --- a/src-tauri/src/checkpoint/state.rs +++ b/src-tauri/src/checkpoint/state.rs @@ -1,3 +1,4 @@ +#![allow(dead_code)] use anyhow::Result; use std::collections::HashMap; use std::path::PathBuf; diff --git a/src-tauri/src/checkpoint/storage.rs b/src-tauri/src/checkpoint/storage.rs index ce82de342..7e440270d 100644 --- a/src-tauri/src/checkpoint/storage.rs +++ b/src-tauri/src/checkpoint/storage.rs @@ -133,8 +133,7 @@ impl CheckpointStorage { let safe_filename = snapshot .file_path .to_string_lossy() - .replace('/', "_") - .replace('\\', "_"); + .replace(['/', '\\'], "_"); let ref_path = checkpoint_refs_dir.join(format!("{}.json", safe_filename)); fs::write(&ref_path, serde_json::to_string_pretty(&ref_metadata)?) @@ -446,10 +445,8 @@ impl CheckpointStorage { let content_file = entry?.path(); if content_file.is_file() { if let Some(hash) = content_file.file_name().and_then(|n| n.to_str()) { - if !referenced_hashes.contains(hash) { - if fs::remove_file(&content_file).is_ok() { - removed_count += 1; - } + if !referenced_hashes.contains(hash) && fs::remove_file(&content_file).is_ok() { + removed_count += 1; } } } diff --git a/src-tauri/src/claude_binary.rs b/src-tauri/src/claude_binary.rs index 0ce4ce48e..098046b8f 100644 --- a/src-tauri/src/claude_binary.rs +++ b/src-tauri/src/claude_binary.rs @@ -664,7 +664,7 @@ pub fn create_command_with_env(program: &str) -> Command { // Ensure the Node.js bin directory is in PATH let current_path = std::env::var("PATH").unwrap_or_default(); let node_bin_str = node_bin_dir.to_string_lossy(); - if !current_path.contains(&node_bin_str.as_ref()) { + if !current_path.contains(node_bin_str.as_ref()) { let new_path = format!("{}:{}", node_bin_str, current_path); debug!("Adding NVM bin directory to PATH: {}", node_bin_str); cmd.env("PATH", new_path); @@ -678,7 +678,7 @@ pub fn create_command_with_env(program: &str) -> Command { // Ensure the Homebrew bin directory is in PATH let current_path = std::env::var("PATH").unwrap_or_default(); let homebrew_bin_str = program_dir.to_string_lossy(); - if !current_path.contains(&homebrew_bin_str.as_ref()) { + if !current_path.contains(homebrew_bin_str.as_ref()) { let new_path = format!("{}:{}", homebrew_bin_str, current_path); debug!( "Adding Homebrew bin directory to PATH: {}", diff --git a/src-tauri/src/commands/agents.rs b/src-tauri/src/commands/agents.rs index 36513a7a4..bca3e97f3 100644 --- a/src-tauri/src/commands/agents.rs +++ b/src-tauri/src/commands/agents.rs @@ -1,3 +1,4 @@ +#![allow(dead_code)] use anyhow::Result; use chrono; use dirs; @@ -382,6 +383,7 @@ pub async fn list_agents(db: State<'_, AgentDb>) -> Result, String> { /// Create a new agent #[tauri::command] +#[allow(clippy::too_many_arguments)] pub async fn create_agent( db: State<'_, AgentDb>, name: String, @@ -437,6 +439,7 @@ pub async fn create_agent( /// Update an existing agent #[tauri::command] +#[allow(clippy::too_many_arguments)] pub async fn update_agent( db: State<'_, AgentDb>, id: i64, @@ -806,6 +809,7 @@ fn create_agent_system_command( } /// Spawn agent using system binary command +#[allow(clippy::too_many_arguments)] async fn spawn_agent_system( app: AppHandle, run_id: i64, @@ -1675,7 +1679,7 @@ fn create_command_with_env(program: &str) -> Command { if let Some(node_bin_dir) = std::path::Path::new(program).parent() { let current_path = std::env::var("PATH").unwrap_or_default(); let node_bin_str = node_bin_dir.to_string_lossy(); - if !current_path.contains(&node_bin_str.as_ref()) { + if !current_path.contains(node_bin_str.as_ref()) { let new_path = format!("{}:{}", node_bin_str, current_path); tokio_cmd.env("PATH", new_path); } @@ -1981,11 +1985,9 @@ pub async fn load_agent_session_history( let reader = BufReader::new(file); let mut messages = Vec::new(); - for line in reader.lines() { - if let Ok(line) = line { - if let Ok(json) = serde_json::from_str::(&line) { - messages.push(json); - } + for line in reader.lines().map_while(Result::ok) { + if let Ok(json) = serde_json::from_str::(&line) { + messages.push(json); } } diff --git a/src-tauri/src/commands/claude.rs b/src-tauri/src/commands/claude.rs index 529eb1a2a..0823ae9f0 100644 --- a/src-tauri/src/commands/claude.rs +++ b/src-tauri/src/commands/claude.rs @@ -1,3 +1,4 @@ +#![allow(dead_code)] use anyhow::{Context, Result}; use serde::{Deserialize, Serialize}; use std::fs; @@ -149,26 +150,20 @@ fn get_project_path_from_sessions(project_dir: &PathBuf) -> Result(&line_content) - { - if let Some(cwd) = json.get("cwd").and_then(|v| v.as_str()) { - if !cwd.is_empty() { - return Ok(cwd.to_string()); - } - } + for entry in entries.flatten() { + let path = entry.path(); + if path.is_file() && path.extension().and_then(|s| s.to_str()) == Some("jsonl") { + // Read the JSONL file and find the first line with a valid cwd + if let Ok(file) = fs::File::open(&path) { + let reader = BufReader::new(file); + // Check first few lines instead of just the first line + // Some session files may have null cwd in the first line + for line in reader.lines().take(10).map_while(Result::ok) { + // Parse the JSON and extract cwd + if let Ok(json) = serde_json::from_str::(&line) { + if let Some(cwd) = json.get("cwd").and_then(|v| v.as_str()) { + if !cwd.is_empty() { + return Ok(cwd.to_string()); } } } @@ -199,27 +194,25 @@ fn extract_first_user_message(jsonl_path: &PathBuf) -> (Option, Option(&line) { - if let Some(message) = entry.message { - if message.role.as_deref() == Some("user") { - if let Some(content) = message.content { - // Skip if it contains the caveat message - if content.contains("Caveat: The messages below were generated by the user while running local commands") { - continue; - } - - // Skip if it starts with command tags - if content.starts_with("") - || content.starts_with("") - { - continue; - } + for line in reader.lines().map_while(Result::ok) { + if let Ok(entry) = serde_json::from_str::(&line) { + if let Some(message) = entry.message { + if message.role.as_deref() == Some("user") { + if let Some(content) = message.content { + // Skip if it contains the caveat message + if content.contains("Caveat: The messages below were generated by the user while running local commands") { + continue; + } - // Found a valid user message - return (Some(content), entry.timestamp); + // Skip if it starts with command tags + if content.starts_with("") + || content.starts_with("") + { + continue; } + + // Found a valid user message + return (Some(content), entry.timestamp); } } } @@ -263,7 +256,7 @@ fn create_command_with_env(program: &str) -> Command { if let Some(node_bin_dir) = std::path::Path::new(program).parent() { let current_path = std::env::var("PATH").unwrap_or_default(); let node_bin_str = node_bin_dir.to_string_lossy(); - if !current_path.contains(&node_bin_str.as_ref()) { + if !current_path.contains(node_bin_str.as_ref()) { let new_path = format!("{}:{}", node_bin_str, current_path); tokio_cmd.env("PATH", new_path); } @@ -275,7 +268,7 @@ fn create_command_with_env(program: &str) -> Command { if let Some(program_dir) = std::path::Path::new(program).parent() { let current_path = std::env::var("PATH").unwrap_or_default(); let homebrew_bin_str = program_dir.to_string_lossy(); - if !current_path.contains(&homebrew_bin_str.as_ref()) { + if !current_path.contains(homebrew_bin_str.as_ref()) { let new_path = format!("{}:{}", homebrew_bin_str, current_path); log::debug!( "Adding Homebrew bin directory to PATH: {}", @@ -905,11 +898,9 @@ pub async fn load_session_history( let reader = BufReader::new(file); let mut messages = Vec::new(); - for line in reader.lines() { - if let Ok(line) = line { - if let Ok(json) = serde_json::from_str::(&line) { - messages.push(json); - } + for line in reader.lines().map_while(Result::ok) { + if let Ok(json) = serde_json::from_str::(&line) { + messages.push(json); } } @@ -1466,7 +1457,7 @@ pub async fn search_files(base_path: String, query: String) -> Result, depth: usize, @@ -1526,7 +1517,7 @@ fn search_files_recursive( } } - search_files_recursive(&entry_path, base_path, query, results, depth + 1)?; + search_files_recursive(&entry_path, _base_path, query, results, depth + 1)?; } } @@ -1570,8 +1561,7 @@ pub async fn create_checkpoint( .map_err(|e| format!("Failed to open session file: {}", e))?; let reader = BufReader::new(file); - let mut line_count = 0; - for line in reader.lines() { + for (line_count, line) in reader.lines().enumerate() { if let Some(index) = message_index { if line_count > index { break; @@ -1583,7 +1573,6 @@ pub async fn create_checkpoint( .await .map_err(|e| format!("Failed to track message: {}", e))?; } - line_count += 1; } } @@ -1841,7 +1830,7 @@ pub async fn get_checkpoint_diff( } // Check for added files - for (path, _) in &to_map { + for path in to_map.keys() { if !from_map.contains_key(path) { added_files.push(path.clone()); } diff --git a/src-tauri/src/commands/mcp.rs b/src-tauri/src/commands/mcp.rs index 2db974f63..cbd6b34bc 100644 --- a/src-tauri/src/commands/mcp.rs +++ b/src-tauri/src/commands/mcp.rs @@ -1,3 +1,4 @@ +#![allow(dead_code)] use anyhow::{Context, Result}; use dirs; use log::{error, info}; @@ -118,6 +119,7 @@ fn execute_claude_mcp_command(app_handle: &AppHandle, args: Vec<&str>) -> Result /// Adds a new MCP server #[tauri::command] +#[allow(clippy::too_many_arguments)] pub async fn mcp_add( app: AppHandle, name: String, diff --git a/src-tauri/src/commands/proxy.rs b/src-tauri/src/commands/proxy.rs index 2192e0efe..45127d70f 100644 --- a/src-tauri/src/commands/proxy.rs +++ b/src-tauri/src/commands/proxy.rs @@ -1,10 +1,12 @@ +#![allow(dead_code)] +use anyhow::Result; use rusqlite::params; use serde::{Deserialize, Serialize}; use tauri::State; use crate::commands::agents::AgentDb; -#[derive(Debug, Serialize, Deserialize, Clone)] +#[derive(Debug, Serialize, Deserialize, Clone, Default)] pub struct ProxySettings { pub http_proxy: Option, pub https_proxy: Option, @@ -13,18 +15,6 @@ pub struct ProxySettings { pub enabled: bool, } -impl Default for ProxySettings { - fn default() -> Self { - Self { - http_proxy: None, - https_proxy: None, - no_proxy: None, - all_proxy: None, - enabled: false, - } - } -} - /// Get proxy settings from the database #[tauri::command] pub async fn get_proxy_settings(db: State<'_, AgentDb>) -> Result { diff --git a/src-tauri/src/commands/slash_commands.rs b/src-tauri/src/commands/slash_commands.rs index 6f77309ea..55c6e0293 100644 --- a/src-tauri/src/commands/slash_commands.rs +++ b/src-tauri/src/commands/slash_commands.rs @@ -1,3 +1,4 @@ +#![allow(dead_code)] use anyhow::{Context, Result}; use dirs; use log::{debug, error, info}; diff --git a/src-tauri/src/commands/storage.rs b/src-tauri/src/commands/storage.rs index 02c552980..a64bdecab 100644 --- a/src-tauri/src/commands/storage.rs +++ b/src-tauri/src/commands/storage.rs @@ -1,3 +1,4 @@ +#![allow(dead_code)] use super::agents::AgentDb; use anyhow::Result; use rusqlite::{params, types::ValueRef, Connection, Result as SqliteResult}; diff --git a/src-tauri/src/commands/usage.rs b/src-tauri/src/commands/usage.rs index b459c15e5..d3b8c1266 100644 --- a/src-tauri/src/commands/usage.rs +++ b/src-tauri/src/commands/usage.rs @@ -1,3 +1,5 @@ +#![allow(dead_code)] +#![allow(clippy::double_ended_iterator_last)] use chrono::{DateTime, Local, NaiveDate}; use serde::{Deserialize, Serialize}; use serde_json; @@ -129,16 +131,14 @@ fn calculate_cost(model: &str, usage: &UsageData) -> f64 { }; // Calculate cost (prices are per million tokens) - let cost = (input_tokens * input_price / 1_000_000.0) + (input_tokens * input_price / 1_000_000.0) + (output_tokens * output_price / 1_000_000.0) + (cache_creation_tokens * cache_write_price / 1_000_000.0) - + (cache_read_tokens * cache_read_price / 1_000_000.0); - - cost + + (cache_read_tokens * cache_read_price / 1_000_000.0) } fn parse_jsonl_file( - path: &PathBuf, + path: &std::path::Path, encoded_project_name: &str, processed_hashes: &mut HashSet, ) -> Vec { @@ -228,7 +228,7 @@ fn parse_jsonl_file( entries } -fn get_earliest_timestamp(path: &PathBuf) -> Option { +fn get_earliest_timestamp(path: &std::path::Path) -> Option { if let Ok(content) = fs::read_to_string(path) { let mut earliest_timestamp: Option = None; for line in content.lines() { @@ -249,7 +249,7 @@ fn get_earliest_timestamp(path: &PathBuf) -> Option { None } -fn get_all_usage_entries(claude_path: &PathBuf) -> Vec { +fn get_all_usage_entries(claude_path: &std::path::Path) -> Vec { let mut all_entries = Vec::new(); let mut processed_hashes = HashSet::new(); let projects_dir = claude_path.join("projects"); @@ -662,8 +662,8 @@ pub fn get_session_stats( .filter(|e| { if let Ok(dt) = DateTime::parse_from_rfc3339(&e.timestamp) { let date = dt.date_naive(); - let is_after_since = since_date.map_or(true, |s| date >= s); - let is_before_until = until_date.map_or(true, |u| date <= u); + let is_after_since = since_date.is_none_or(|s| date >= s); + let is_before_until = until_date.is_none_or(|u| date <= u); is_after_since && is_before_until } else { false diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index fc93adbcf..5c313e31d 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -60,7 +60,7 @@ fn main() { .plugin(tauri_plugin_shell::init()) .setup(|app| { // Initialize agents database - let conn = init_database(&app.handle()).expect("Failed to initialize agents database"); + let conn = init_database(app.handle()).expect("Failed to initialize agents database"); // Load and apply proxy settings from the database { @@ -117,7 +117,7 @@ fn main() { } // Re-open the connection for the app to manage - let conn = init_database(&app.handle()).expect("Failed to initialize agents database"); + let conn = init_database(app.handle()).expect("Failed to initialize agents database"); app.manage(AgentDb(Mutex::new(conn))); // Initialize checkpoint state @@ -125,7 +125,7 @@ fn main() { // Set the Claude directory path if let Ok(claude_dir) = dirs::home_dir() - .ok_or_else(|| "Could not find home directory") + .ok_or("Could not find home directory") .and_then(|home| { let claude_path = home.join(".claude"); claude_path diff --git a/src-tauri/src/process/registry.rs b/src-tauri/src/process/registry.rs index f4f33b5a2..a119f9111 100644 --- a/src-tauri/src/process/registry.rs +++ b/src-tauri/src/process/registry.rs @@ -1,3 +1,4 @@ +#![allow(dead_code)] use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; @@ -54,6 +55,7 @@ impl ProcessRegistry { } /// Register a new running agent process + #[allow(clippy::too_many_arguments)] pub fn register_process( &self, run_id: i64, @@ -82,6 +84,7 @@ impl ProcessRegistry { } /// Register a new running agent process using sidecar (similar to register_process but for sidecar children) + #[allow(clippy::too_many_arguments)] pub fn register_sidecar_process( &self, run_id: i64, @@ -497,15 +500,15 @@ impl ProcessRegistry { let processes_lock = self.processes.clone(); // First, identify finished processes - { + // First, identify finished processes + let run_ids: Vec = { let processes = processes_lock.lock().map_err(|e| e.to_string())?; - let run_ids: Vec = processes.keys().cloned().collect(); - drop(processes); + processes.keys().cloned().collect() + }; - for run_id in run_ids { - if !self.is_process_running(run_id).await? { - finished_runs.push(run_id); - } + for run_id in run_ids { + if !self.is_process_running(run_id).await? { + finished_runs.push(run_id); } } diff --git a/src-tauri/src/web_server.rs b/src-tauri/src/web_server.rs index 01a28436f..16184d815 100644 --- a/src-tauri/src/web_server.rs +++ b/src-tauri/src/web_server.rs @@ -1,3 +1,4 @@ +#![allow(dead_code)] use axum::extract::ws::{Message, WebSocket}; use axum::http::Method; use axum::{ @@ -6,7 +7,6 @@ use axum::{ routing::get, Router, }; -use chrono; use futures_util::{SinkExt, StreamExt}; use serde::{Deserialize, Serialize}; use serde_json::json; @@ -16,7 +16,6 @@ use tokio::net::TcpListener; use tokio::sync::Mutex; use tower_http::cors::{Any, CorsLayer}; use tower_http::services::ServeDir; -use which; use crate::commands; @@ -233,17 +232,17 @@ async fn resume_claude_code() -> Json> { } /// Cancel Claude execution -async fn cancel_claude_execution(Path(sessionId): Path) -> Json> { +async fn cancel_claude_execution(Path(session_id): Path) -> Json> { // In web mode, we don't have a way to cancel the subprocess cleanly // The WebSocket closing should handle cleanup - println!("[TRACE] Cancel request for session: {}", sessionId); + println!("[TRACE] Cancel request for session: {}", session_id); Json(ApiResponse::success(())) } /// Get Claude session output -async fn get_claude_session_output(Path(sessionId): Path) -> Json> { +async fn get_claude_session_output(Path(session_id): Path) -> Json> { // In web mode, output is streamed via WebSocket, not stored - println!("[TRACE] Output request for session: {}", sessionId); + println!("[TRACE] Output request for session: {}", session_id); Json(ApiResponse::success( "Output available via WebSocket only".to_string(), )) diff --git a/src/components/AgentExecution.tsx b/src/components/AgentExecution.tsx index 90f089ccd..55d3b0e06 100644 --- a/src/components/AgentExecution.tsx +++ b/src/components/AgentExecution.tsx @@ -1,9 +1,9 @@ import React, { useState, useEffect, useRef } from "react"; import { motion, AnimatePresence } from "framer-motion"; -import { - ArrowLeft, - Play, - StopCircle, +import { + ArrowLeft, + Play, + StopCircle, Terminal, AlertCircle, Loader2, @@ -34,6 +34,7 @@ import { useVirtualizer } from "@tanstack/react-virtual"; import { HooksEditor } from "./HooksEditor"; import { useTrackEvent, useComponentMetrics, useFeatureAdoptionTracking } from "@/hooks"; import { useTabState } from "@/hooks/useTabState"; +import { useTranslation } from "@/hooks/useTranslation"; interface AgentExecutionProps { /** @@ -88,6 +89,7 @@ export const AgentExecution: React.FC = ({ onBack, className, }) => { + const { t } = useTranslation('agents'); const [projectPath] = useState(initialProjectPath || ""); const [task, setTask] = useState(agent.default_task || ""); const [model, setModel] = useState(agent.model || "sonnet"); @@ -445,17 +447,17 @@ export const AgentExecution: React.FC = ({ if (isRunning) { // Show confirmation dialog before navigating away during execution const shouldLeave = window.confirm( - "An agent is currently running. If you navigate away, the agent will continue running in the background. You can view running sessions in the 'Running Sessions' tab within CC Agents.\n\nDo you want to continue?" + t('messages.agent_running_warning') ); if (!shouldLeave) { return; } } - + // Clean up listeners but don't stop the actual agent process unlistenRefs.current.forEach(unlisten => unlisten()); unlistenRefs.current = []; - + // Navigate back onBack(); }; @@ -546,14 +548,14 @@ export const AgentExecution: React.FC = ({ size="icon" onClick={handleBackWithConfirmation} className="h-9 w-9 -ml-2" - title="Back" + title={t('buttons.back_to_agents')} >

{agent.name}

- {isRunning ? 'Running' : messages.length > 0 ? 'Complete' : 'Ready'} • {model === 'opus' ? 'Claude 4 Opus' : 'Claude 4 Sonnet'} + {isRunning ? t('status.running') : messages.length > 0 ? t('status.complete') : t('status.ready')} • {model === 'opus' ? t('models.opus.name') : t('models.sonnet.name')}

@@ -565,7 +567,7 @@ export const AgentExecution: React.FC = ({ onClick={() => setIsFullscreenModalOpen(true)} > - Fullscreen + {t('buttons.fullscreen')} )} @@ -591,7 +593,7 @@ export const AgentExecution: React.FC = ({ {/* Model Selection */}
- +
= ({ transition={{ duration: 0.15 }} className={cn( "flex-1 px-4 py-3 rounded-md border transition-all", - model === "sonnet" - ? "border-primary bg-primary/10 text-primary" + model === "sonnet" + ? "border-primary bg-primary/10 text-primary" : "border-border hover:border-primary/50 hover:bg-accent", isRunning && "opacity-50 cursor-not-allowed" )} @@ -617,12 +619,12 @@ export const AgentExecution: React.FC = ({ )}
-
Claude 4 Sonnet
-
Faster, efficient
+
{t('models.sonnet.name')}
+
{t('models.sonnet.short_desc')}
- + !isRunning && setModel("opus")} @@ -630,8 +632,8 @@ export const AgentExecution: React.FC = ({ transition={{ duration: 0.15 }} className={cn( "flex-1 px-4 py-3 rounded-md border transition-all", - model === "opus" - ? "border-primary bg-primary/10 text-primary" + model === "opus" + ? "border-primary bg-primary/10 text-primary" : "border-border hover:border-primary/50 hover:bg-accent", isRunning && "opacity-50 cursor-not-allowed" )} @@ -647,8 +649,8 @@ export const AgentExecution: React.FC = ({ )}
-
Claude 4 Opus
-
More capable
+
{t('models.opus.name')}
+
{t('models.opus.short_desc')}
@@ -658,7 +660,7 @@ export const AgentExecution: React.FC = ({ {/* Task Input */}
- + {projectPath && ( )}
@@ -676,7 +678,7 @@ export const AgentExecution: React.FC = ({ setTask(e.target.value)} - placeholder="What would you like the agent to do?" + placeholder={t('placeholders.task_input')} disabled={isRunning} className="flex-1 h-9" onKeyDown={(e) => { @@ -703,12 +705,12 @@ export const AgentExecution: React.FC = ({ {isRunning ? ( <> - Stop + {t('buttons.stop')} ) : ( <> - Execute + {t('buttons.execute')} )} @@ -716,7 +718,7 @@ export const AgentExecution: React.FC = ({
{projectPath && (

- Working in: {projectPath.split('/').pop() || projectPath} + {t('execution.working_in')} {projectPath.split('/').pop() || projectPath}

)} @@ -745,9 +747,9 @@ export const AgentExecution: React.FC = ({ {messages.length === 0 && !isRunning && (
-

Ready to Execute

+

{t('messages.ready_to_execute')}

- Enter a task to run the agent + {t('messages.enter_task')}

)} @@ -756,7 +758,7 @@ export const AgentExecution: React.FC = ({
- Initializing agent... + {t('messages.initializing')}
)} @@ -809,11 +811,11 @@ export const AgentExecution: React.FC = ({ {/* Modal Header */}
-

{agent.name} - Output

+

{agent.name} - {t('buttons.copy_output')}

{isRunning && (
- Running + {t('status.running')}
)}
@@ -826,7 +828,7 @@ export const AgentExecution: React.FC = ({ className="flex items-center gap-2" > - Copy Output + {t('buttons.copy_output')} } @@ -838,7 +840,7 @@ export const AgentExecution: React.FC = ({ className="w-full justify-start" onClick={handleCopyAsJsonl} > - Copy as JSONL + {t('buttons.copy_as_jsonl')}
} @@ -861,7 +863,7 @@ export const AgentExecution: React.FC = ({ className="flex items-center gap-2" > - Close + {t('common:buttons.close')} @@ -936,36 +938,35 @@ export const AgentExecution: React.FC = ({ )} {/* Hooks Configuration Dialog */} -
- Configure Hooks + {t('execution.configure_hooks_title')} - Configure hooks that run before, during, and after tool executions + {t('execution.configure_hooks_description')}
- +
- Project Settings + {t('execution.project_settings')} - Local Settings + {t('execution.local_settings')}
- +

- Project hooks are stored in .claude/settings.json and - are committed to version control, allowing team members to share configurations. + {t('execution.project_hooks_info')}

= ({ />
- +

- Local hooks are stored in .claude/settings.local.json and - are not committed to version control, perfect for personal preferences. + {t('execution.local_hooks_info')}

setSelectedRun(null)} * /> */ -export function AgentRunOutputViewer({ - agentRunId, +export function AgentRunOutputViewer({ + agentRunId, tabId, - className + className }: AgentRunOutputViewerProps) { + const { t } = useTranslation(['agents', 'common']); const { updateTabTitle, updateTabStatus } = useTabState(); const [run, setRun] = useState(null); const [messages, setMessages] = useState([]); @@ -323,7 +325,7 @@ export function AgentRunOutputViewer({ const jsonl = rawJsonlOutput.join('\n'); await navigator.clipboard.writeText(jsonl); setCopyPopoverOpen(false); - setToast({ message: 'Output copied as JSONL', type: 'success' }); + setToast({ message: t('sessions:output_viewer.output_copied_jsonl'), type: 'success' }); }; const handleCopyAsMarkdown = async () => { @@ -381,7 +383,7 @@ export function AgentRunOutputViewer({ await navigator.clipboard.writeText(markdown); setCopyPopoverOpen(false); - setToast({ message: 'Output copied as Markdown', type: 'success' }); + setToast({ message: t('sessions:output_viewer.output_copied_markdown'), type: 'success' }); }; const handleRefresh = async () => { @@ -399,10 +401,10 @@ export function AgentRunOutputViewer({ try { // Call the API to kill the agent session const success = await api.killAgentSession(run.id); - + if (success) { console.log(`[AgentRunOutputViewer] Successfully stopped agent session ${run.id}`); - setToast({ message: 'Agent execution stopped', type: 'success' }); + setToast({ message: t('agents:messages.execution_stopped'), type: 'success' }); // Clean up listeners unlistenRefs.current.forEach(unlisten => unlisten()); @@ -430,13 +432,13 @@ export function AgentRunOutputViewer({ await loadOutput(true); } else { console.warn(`[AgentRunOutputViewer] Failed to stop agent session ${run.id} - it may have already finished`); - setToast({ message: 'Failed to stop agent - it may have already finished', type: 'error' }); + setToast({ message: t('agents:messages.failed_to_stop'), type: 'error' }); } } catch (err) { console.error('[AgentRunOutputViewer] Failed to stop agent:', err); - setToast({ - message: `Failed to stop execution: ${err instanceof Error ? err.message : 'Unknown error'}`, - type: 'error' + setToast({ + message: t('agents:messages.failed_to_stop_with_error', { error: err instanceof Error ? err.message : 'Unknown error' }), + type: 'error' }); } }; @@ -535,7 +537,7 @@ export function AgentRunOutputViewer({
-

Loading agent run...

+

{t('agents:messages.loading')}

); @@ -557,7 +559,7 @@ export function AgentRunOutputViewer({ {run.status === 'running' && (
- Running + {t('agents:status.running')}
)} @@ -599,7 +601,7 @@ export function AgentRunOutputViewer({ className="h-8 px-2" > - Copy + {t('agents:buttons.copy_output')} } @@ -611,7 +613,7 @@ export function AgentRunOutputViewer({ className="w-full justify-start" onClick={handleCopyAsJsonl} > - Copy as JSONL + {t('agents:buttons.copy_as_jsonl')}
} @@ -631,7 +633,7 @@ export function AgentRunOutputViewer({ variant="ghost" size="sm" onClick={() => setIsFullscreen(!isFullscreen)} - title={isFullscreen ? "Exit fullscreen" : "Enter fullscreen"} + title={isFullscreen ? t('common:actions.minimize') : t('common:actions.maximize')} className="h-8 px-2" > {isFullscreen ? ( @@ -645,7 +647,7 @@ export function AgentRunOutputViewer({ size="sm" onClick={handleRefresh} disabled={refreshing} - title="Refresh output" + title={t('sessions:output_viewer.refresh_output')} className="h-8 px-2" > @@ -656,7 +658,7 @@ export function AgentRunOutputViewer({ size="sm" onClick={handleStop} disabled={refreshing} - title="Stop execution" + title={t('agents:buttons.stop')} className="h-8 px-2 text-destructive hover:text-destructive" > @@ -670,12 +672,12 @@ export function AgentRunOutputViewer({
- Loading output... + {t('sessions:output_viewer.loading_output')}
) : messages.length === 0 ? (
-

No output available yet

+

{t('sessions:output_viewer.no_output_available')}

) : (
- Copy Output + {t('agents:buttons.copy_output')} } @@ -735,7 +737,7 @@ export function AgentRunOutputViewer({ className="w-full justify-start" onClick={handleCopyAsJsonl} > - Copy as JSONL + {t('agents:buttons.copy_as_jsonl')}
} @@ -765,7 +767,7 @@ export function AgentRunOutputViewer({ disabled={refreshing} > - Stop + {t('agents:buttons.stop')} )} @@ -786,7 +788,7 @@ export function AgentRunOutputViewer({
{messages.length === 0 ? (
- No output available yet + {t('sessions:output_viewer.no_output_available')}
) : ( <> diff --git a/src/components/AgentRunView.tsx b/src/components/AgentRunView.tsx index 16ade6c51..543c5ce23 100644 --- a/src/components/AgentRunView.tsx +++ b/src/components/AgentRunView.tsx @@ -1,9 +1,9 @@ import React, { useState, useEffect } from "react"; import { motion } from "framer-motion"; -import { - ArrowLeft, - Copy, - ChevronDown, +import { + ArrowLeft, + Copy, + ChevronDown, Clock, Hash, DollarSign, @@ -21,6 +21,7 @@ import { StreamMessage } from "./StreamMessage"; import { AGENT_ICONS } from "./CCAgents"; import type { ClaudeStreamMessage } from "./AgentExecution"; import { ErrorBoundary } from "./ErrorBoundary"; +import { useTranslation } from "@/hooks/useTranslation"; interface AgentRunViewProps { /** @@ -48,6 +49,7 @@ export const AgentRunView: React.FC = ({ onBack, className, }) => { + const { t } = useTranslation('agents'); const [run, setRun] = useState(null); const [messages, setMessages] = useState([]); const [loading, setLoading] = useState(true); @@ -101,7 +103,7 @@ export const AgentRunView: React.FC = ({ } } catch (err) { console.error("Failed to load run:", err); - setError("Failed to load execution details"); + setError(t('messages.failed_to_load')); } finally { setLoading(false); } @@ -233,8 +235,8 @@ export const AgentRunView: React.FC = ({ if (error || !run) { return (
-

{error || "Run not found"}

- +

{error || t('messages.run_not_found')}

+
); } @@ -262,11 +264,11 @@ export const AgentRunView: React.FC = ({ {renderIcon(run.agent_icon)}

{run.agent_name}

-

Execution History

+

{t('labels.execution_history')}

- +
{run?.status === 'running' && ( )} - + = ({ className="flex items-center gap-2" > - Copy Output + {t('buttons.copy_output')} } @@ -300,7 +302,7 @@ export const AgentRunView: React.FC = ({ className="w-full justify-start" onClick={handleCopyAsJsonl} > - Copy as JSONL + {t('buttons.copy_as_jsonl')}
} @@ -324,10 +326,10 @@ export const AgentRunView: React.FC = ({
-

Task:

+

{t('labels.task')}:

{run.task}

- {run.model === 'opus' ? 'Claude 4 Opus' : 'Claude 4 Sonnet'} + {run.model === 'opus' ? t('models.opus.name') : t('models.sonnet.name')}
diff --git a/src/components/AgentRunsList.tsx b/src/components/AgentRunsList.tsx index deb403c37..a043209b5 100644 --- a/src/components/AgentRunsList.tsx +++ b/src/components/AgentRunsList.tsx @@ -9,6 +9,7 @@ import { formatISOTimestamp } from "@/lib/date-utils"; import type { AgentRunWithMetrics } from "@/lib/api"; import { AGENT_ICONS } from "./CCAgents"; import { useTabState } from "@/hooks/useTabState"; +import { useTranslation } from "@/hooks/useTranslation"; interface AgentRunsListProps { /** @@ -41,6 +42,7 @@ export const AgentRunsList: React.FC = ({ onRunClick, className, }) => { + const { t } = useTranslation('agents'); const [currentPage, setCurrentPage] = useState(1); const { createAgentTab } = useTabState(); @@ -91,7 +93,7 @@ export const AgentRunsList: React.FC = ({ return (
-

No execution history yet

+

{t('history.no_history')}

); } @@ -133,25 +135,25 @@ export const AgentRunsList: React.FC = ({ {run.status === "running" && (
- Running + {t('status.running')}
)}
- +

{run.task}

- +
{formatISOTimestamp(run.created_at)}
- + {run.metrics?.duration_ms && ( {formatDuration(run.metrics.duration_ms)} )} - + {run.metrics?.total_tokens && (
@@ -160,9 +162,9 @@ export const AgentRunsList: React.FC = ({ )}
- +
- = ({ } className="text-xs" > - {run.status === "completed" ? "Completed" : - run.status === "running" ? "Running" : - run.status === "failed" ? "Failed" : - "Pending"} + {run.status === "completed" ? t('status.complete') : + run.status === "running" ? t('status.running') : + run.status === "failed" ? t('status.failed') : + t('status.pending')}
diff --git a/src/components/Agents.tsx b/src/components/Agents.tsx index 795071786..adbd07e6a 100644 --- a/src/components/Agents.tsx +++ b/src/components/Agents.tsx @@ -18,8 +18,10 @@ import { invoke } from '@tauri-apps/api/core'; import { GitHubAgentBrowser } from '@/components/GitHubAgentBrowser'; import { CreateAgent } from '@/components/CreateAgent'; import { useTabState } from '@/hooks/useTabState'; +import { useTranslation } from '@/hooks/useTranslation'; export const Agents: React.FC = () => { + const { t } = useTranslation('agents'); const [activeTab, setActiveTab] = useState('agents'); const [showCreateAgent, setShowCreateAgent] = useState(false); const [editingAgent, setEditingAgent] = useState(null); @@ -54,7 +56,7 @@ export const Agents: React.FC = () => { setAgents(agents); } catch (error) { console.error('Failed to load agents:', error); - setToast({ message: 'Failed to load agents', type: 'error' }); + setToast({ message: t('messages.failed_to_load'), type: 'error' }); } finally { setLoading(false); } @@ -74,48 +76,48 @@ export const Agents: React.FC = () => { setToast({ message: 'Agent ID is missing', type: 'error' }); return; } - + // Import the dialog function const { open } = await import('@tauri-apps/plugin-dialog'); - + try { // Prompt user to select a project directory const projectPath = await open({ directory: true, multiple: false, - title: `Select project directory for ${agent.name}` + title: t('modal.title') }); - + if (!projectPath) { // User cancelled return; } - + // Dispatch event to open agent execution in a new tab const tabId = `agent-exec-${agent.id}-${Date.now()}`; - window.dispatchEvent(new CustomEvent('open-agent-execution', { - detail: { agent, tabId, projectPath } + window.dispatchEvent(new CustomEvent('open-agent-execution', { + detail: { agent, tabId, projectPath } })); - - setToast({ message: `Opening agent: ${agent.name}`, type: 'success' }); + + setToast({ message: t('messages.initializing'), type: 'success' }); } catch (error) { console.error('Failed to open agent:', error); - setToast({ message: `Failed to open agent: ${agent.name}`, type: 'error' }); + setToast({ message: t('messages.failed_to_execute'), type: 'error' }); } }; const handleDeleteAgent = async () => { if (!agentToDelete || !agentToDelete.id) return; - + try { await api.deleteAgent(agentToDelete.id); - setToast({ message: `Deleted agent: ${agentToDelete.name}`, type: 'success' }); + setToast({ message: t('messages.agent_deleted'), type: 'success' }); setAgents(prev => prev.filter(a => a.id !== agentToDelete.id)); setShowDeleteDialog(false); setAgentToDelete(null); } catch (error) { console.error('Failed to delete agent:', error); - setToast({ message: `Failed to delete agent: ${agentToDelete.name}`, type: 'error' }); + setToast({ message: t('messages.failed_to_delete'), type: 'error' }); } }; @@ -130,13 +132,13 @@ export const Agents: React.FC = () => { }); if (selected) { - const importedAgent = await api.importAgentFromFile(selected as string); - setToast({ message: `Imported agent: ${importedAgent.name}`, type: 'success' }); + await api.importAgentFromFile(selected as string); + setToast({ message: t('messages.agent_imported'), type: 'success' }); loadAgents(); } } catch (error) { console.error('Failed to import agent:', error); - setToast({ message: 'Failed to import agent', type: 'error' }); + setToast({ message: t('messages.failed_to_import'), type: 'error' }); } }; @@ -151,11 +153,11 @@ export const Agents: React.FC = () => { if (path && agent.id) { await invoke('export_agent_to_file', { id: agent.id, filePath: path }); - setToast({ message: `Exported agent: ${agent.name}`, type: 'success' }); + setToast({ message: t('messages.agent_exported', { name: agent.name }), type: 'success' }); } } catch (error) { console.error('Failed to export agent:', error); - setToast({ message: 'Failed to export agent', type: 'error' }); + setToast({ message: t('messages.failed_to_export'), type: 'error' }); } }; @@ -175,7 +177,7 @@ export const Agents: React.FC = () => { // Show CreateAgent component if creating if (showCreateAgent) { return ( - setShowCreateAgent(false)} onAgentCreated={() => { setShowCreateAgent(false); @@ -206,9 +208,9 @@ export const Agents: React.FC = () => {
-

Agents

+

{t('title')}

- Manage your Claude Code agents + {t('subtitle')}

@@ -216,25 +218,25 @@ export const Agents: React.FC = () => { - From File + {t('buttons.import_from_file')} setShowGitHubBrowser(true)}> - From GitHub + {t('buttons.import_from_github')}
@@ -249,8 +251,8 @@ export const Agents: React.FC = () => { exit={{ opacity: 0, y: -10 }} className="mx-6 mb-4" > - setToast(null)} /> @@ -258,56 +260,56 @@ export const Agents: React.FC = () => { )} - {showGitHubBrowser && ( - setShowGitHubBrowser(false)} - onImportSuccess={() => { - loadAgents(); - setShowGitHubBrowser(false); - setToast({ message: 'Agent imported successfully', type: 'success' }); - }} - /> - )} - - - {showDeleteDialog && agentToDelete && ( - setShowDeleteDialog(false)} - > + {showGitHubBrowser && ( + setShowGitHubBrowser(false)} + onImportSuccess={() => { + loadAgents(); + setShowGitHubBrowser(false); + setToast({ message: t('messages.agent_imported_github'), type: 'success' }); + }} + /> + )} + + + {showDeleteDialog && agentToDelete && ( e.stopPropagation()} + initial={{ opacity: 0 }} + animate={{ opacity: 1 }} + exit={{ opacity: 0 }} + className="fixed inset-0 bg-background/80 backdrop-blur-sm z-50 flex items-center justify-center" + onClick={() => setShowDeleteDialog(false)} > -

Delete Agent

-

- Are you sure you want to delete "{agentToDelete.name}"? This action cannot be undone. -

-
- - -
+ e.stopPropagation()} + > +

{t('delete_dialog.title')}

+

+ {t('delete_dialog.description', { name: agentToDelete.name })} +

+
+ + +
+
-
- )} -
+ )} + {/* Content */}
@@ -315,15 +317,15 @@ export const Agents: React.FC = () => { - Agents ({agents.length}) + {t('title')} ({agents.length}) - History ({runningAgents.length}) + {t('history.recent_executions')} ({runningAgents.length}) - + {loading ? (
@@ -331,13 +333,13 @@ export const Agents: React.FC = () => { ) : agents.length === 0 ? (
-

No Agents Yet

+

{t('messages.no_agents')}

- Create your first agent to get started + {t('messages.create_first_agent')}

) : ( @@ -361,17 +363,17 @@ export const Agents: React.FC = () => { setEditingAgent(agent)}> - Edit + {t('buttons.edit')} handleRunAgent(agent)}> - Run + {t('buttons.execute')} handleExportAgent(agent)}> - Export + {t('buttons.export')} - { setAgentToDelete(agent); setShowDeleteDialog(true); @@ -379,14 +381,14 @@ export const Agents: React.FC = () => { className="text-destructive" > - Delete + {t('buttons.delete')}

- No description provided + {agent.default_task || t('labels.task_description')}

@@ -398,7 +400,7 @@ export const Agents: React.FC = () => { onClick={() => handleRunAgent(agent)} > - Run + {t('buttons.execute')}
@@ -412,9 +414,9 @@ export const Agents: React.FC = () => {
-

No Agent History

+

{t('history.no_history')}

- Run an agent to see it here + {t('modal.running_appear_here')}

@@ -445,22 +447,22 @@ export const Agents: React.FC = () => {
- Started: + {t('execution_control.started')}:

{new Date(run.created_at).toLocaleString()}

- Duration: + {t('execution_control.time')}:

{run.metrics?.duration_ms ? `${(run.metrics.duration_ms / 1000).toFixed(1)}s` : run.duration_ms ? `${(run.duration_ms / 1000).toFixed(1)}s` : '—'}

- Tokens: + {t('execution_control.tokens')}:

{run.metrics?.total_tokens ? run.metrics.total_tokens.toLocaleString() : run.total_tokens ? run.total_tokens.toLocaleString() : '—'}

{run.status === 'failed' && (
- Agent execution failed + {t('messages.execution_failed')}
)} diff --git a/src/components/AgentsModal.tsx b/src/components/AgentsModal.tsx index f5eb4063c..2629a7f4c 100644 --- a/src/components/AgentsModal.tsx +++ b/src/components/AgentsModal.tsx @@ -25,6 +25,7 @@ import { formatISOTimestamp } from '@/lib/date-utils'; import { open as openDialog, save } from '@tauri-apps/plugin-dialog'; import { invoke } from '@tauri-apps/api/core'; import { GitHubAgentBrowser } from '@/components/GitHubAgentBrowser'; +import { useTranslation } from '@/hooks/useTranslation'; interface AgentsModalProps { open: boolean; @@ -32,6 +33,7 @@ interface AgentsModalProps { } export const AgentsModal: React.FC = ({ open, onOpenChange }) => { + const { t } = useTranslation('agents'); const [activeTab, setActiveTab] = useState('agents'); const [agents, setAgents] = useState([]); const [runningAgents, setRunningAgents] = useState([]); @@ -167,11 +169,11 @@ export const AgentsModal: React.FC = ({ open, onOpenChange }) if (filePath) { const agent = await api.importAgentFromFile(filePath as string); loadAgents(); // Refresh list - setToast({ message: `Agent "${agent.name}" imported successfully`, type: "success" }); + setToast({ message: t('messages.agent_imported', { name: agent.name }), type: "success" }); } } catch (error) { console.error('Failed to import agent:', error); - setToast({ message: "Failed to import agent", type: "error" }); + setToast({ message: t('messages.failed_to_import'), type: "error" }); } }; @@ -192,11 +194,11 @@ export const AgentsModal: React.FC = ({ open, onOpenChange }) if (filePath) { await invoke('write_file', { path: filePath, content: JSON.stringify(exportData, null, 2) }); - setToast({ message: "Agent exported successfully", type: "success" }); + setToast({ message: t('messages.agent_exported'), type: "success" }); } } catch (error) { console.error('Failed to export agent:', error); - setToast({ message: "Failed to export agent", type: "error" }); + setToast({ message: t('messages.failed_to_export'), type: "error" }); } }; @@ -220,18 +222,18 @@ export const AgentsModal: React.FC = ({ open, onOpenChange }) - Agent Management + {t('modal.title')} - Create new agents or manage running agent executions + {t('modal.description')} - Available Agents + {t('modal.available_agents')} - Running Agents + {t('modal.running_agents')} {runningAgents.length > 0 && ( {runningAgents.length} @@ -247,24 +249,24 @@ export const AgentsModal: React.FC = ({ open, onOpenChange })
- From File + {t('buttons.import_from_file')} - From GitHub + {t('buttons.import_from_github')} @@ -276,16 +278,16 @@ export const AgentsModal: React.FC = ({ open, onOpenChange }) ) : agents.length === 0 ? (
-

No agents available

+

{t('modal.no_agents_available')}

- Create your first agent to get started + {t('modal.create_first')}

) : ( @@ -316,7 +318,7 @@ export const AgentsModal: React.FC = ({ open, onOpenChange }) onClick={() => handleExportAgent(agent)} > - Export + {t('buttons.export')}
@@ -348,9 +350,9 @@ export const AgentsModal: React.FC = ({ open, onOpenChange }) {runningAgents.length === 0 ? (
-

No running agents

+

{t('modal.no_running')}

- Agent executions will appear here when started + {t('modal.running_appear_here')}

) : ( @@ -376,9 +378,9 @@ export const AgentsModal: React.FC = ({ open, onOpenChange }) {run.task}

- Started: {formatISOTimestamp(run.created_at)} + {t('execution_control.started')}: {formatISOTimestamp(run.created_at)} - {run.model === 'opus' ? 'Claude 4 Opus' : 'Claude 4 Sonnet'} + {run.model === 'opus' ? t('models.opus.name') : t('models.sonnet.name')}
@@ -390,7 +392,7 @@ export const AgentsModal: React.FC = ({ open, onOpenChange }) handleOpenAgentRun(run); }} > - View + {t('common:buttons.view')} @@ -409,9 +411,9 @@ export const AgentsModal: React.FC = ({ open, onOpenChange }) - Delete Agent + {t('delete_dialog.title')} - Are you sure you want to delete "{agentToDelete?.name}"? This action cannot be undone. + {t('delete_dialog.description', { name: agentToDelete?.name })}
@@ -422,13 +424,13 @@ export const AgentsModal: React.FC = ({ open, onOpenChange }) setAgentToDelete(null); }} > - Cancel + {t('common:buttons.cancel')}
@@ -441,7 +443,7 @@ export const AgentsModal: React.FC = ({ open, onOpenChange }) onImportSuccess={() => { setShowGitHubBrowser(false); loadAgents(); // Refresh the agents list - setToast({ message: "Agent imported successfully", type: "success" }); + setToast({ message: t('messages.agent_imported'), type: "success" }); }} /> diff --git a/src/components/App.cleaned.tsx b/src/components/App.cleaned.tsx deleted file mode 100644 index a6c7000bd..000000000 --- a/src/components/App.cleaned.tsx +++ /dev/null @@ -1,180 +0,0 @@ -import { useState, useEffect } from "react"; -import { motion, AnimatePresence } from "framer-motion"; -import { OutputCacheProvider } from "@/lib/outputCache"; -import { TabProvider } from "@/contexts/TabContext"; -import { NFOCredits } from "@/components/NFOCredits"; -import { ClaudeBinaryDialog } from "@/components/ClaudeBinaryDialog"; -import { Toast, ToastContainer } from "@/components/ui/toast"; -import { TabManager } from "@/components/TabManager"; -import { TabContent } from "@/components/TabContent"; -import { AgentsModal } from "@/components/AgentsModal"; -import { CustomTitlebar } from "@/components/CustomTitlebar"; -import { useTabState } from "@/hooks/useTabState"; - -/** - * AppContent component - Contains the main app logic, wrapped by providers - */ -function AppContent() { - const { } = useTabState(); - const [showNFO, setShowNFO] = useState(false); - const [showClaudeBinaryDialog, setShowClaudeBinaryDialog] = useState(false); - const [toast, setToast] = useState<{ message: string; type: "success" | "error" | "info" } | null>(null); - const [showAgentsModal, setShowAgentsModal] = useState(false); - const [, setClaudeExecutableExists] = useState(true); - - // Keyboard shortcuts for tab navigation - useEffect(() => { - const handleKeyDown = (e: KeyboardEvent) => { - const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0; - const modKey = isMac ? e.metaKey : e.ctrlKey; - - if (modKey) { - switch (e.key) { - case 't': - e.preventDefault(); - window.dispatchEvent(new CustomEvent('create-chat-tab')); - break; - case 'w': - e.preventDefault(); - window.dispatchEvent(new CustomEvent('close-current-tab')); - break; - case 'Tab': - e.preventDefault(); - if (e.shiftKey) { - window.dispatchEvent(new CustomEvent('switch-to-previous-tab')); - } else { - window.dispatchEvent(new CustomEvent('switch-to-next-tab')); - } - break; - default: - // Handle number keys 1-9 - const num = parseInt(e.key); - if (!isNaN(num) && num >= 1 && num <= 9) { - e.preventDefault(); - window.dispatchEvent(new CustomEvent('switch-to-tab', { detail: num - 1 })); - } - break; - } - } - }; - - window.addEventListener('keydown', handleKeyDown); - return () => window.removeEventListener('keydown', handleKeyDown); - }, []); - - // Check if Claude executable exists on mount - useEffect(() => { - const checkClaudeExecutable = async () => { - try { - // Check if claude executable exists - method not available in API - const exists = true; // Default to true for now - if (!exists) { - setShowClaudeBinaryDialog(true); - } - } catch (error) { - console.error("Error checking Claude executable:", error); - } - }; - - checkClaudeExecutable(); - }, []); - - // Custom event handlers - useEffect(() => { - const handleCreateProjectTab = () => { - window.dispatchEvent(new CustomEvent('create-project-tab')); - }; - - const handleShowNFO = () => setShowNFO(true); - const handleShowAgents = () => setShowAgentsModal(true); - - const projectButton = document.getElementById('create-project-tab-btn'); - if (projectButton) { - projectButton.addEventListener('click', handleCreateProjectTab); - } - - // Listen for custom events to show modals - window.addEventListener('show-nfo', handleShowNFO); - window.addEventListener('show-agents-modal', handleShowAgents); - - return () => { - if (projectButton) { - projectButton.removeEventListener('click', handleCreateProjectTab); - } - window.removeEventListener('show-nfo', handleShowNFO); - window.removeEventListener('show-agents-modal', handleShowAgents); - }; - }, []); - - return ( - - - {/* Custom Titlebar */} - { - // Open settings tab or modal - window.dispatchEvent(new CustomEvent('create-settings-tab')); - }} - onAgentsClick={() => {}} - /> - - {/* Tab-based interface */} -
- - -
- - {/* Global Modals */} - {showNFO && setShowNFO(false)} />} - - { - setClaudeExecutableExists(true); - setToast({ message: "Claude binary path set successfully", type: "success" }); - }} - onError={(message) => { - setToast({ message, type: "error" }); - }} - /> - - - - {/* Toast Container */} - {toast && ( - - setToast(null)} - /> - - )} -
-
- ); -} - -/** - * App component - Main entry point with providers - */ -function App() { - return ( - - - - - - ); -} - -export default App; \ No newline at end of file diff --git a/src/components/CCAgents.tsx b/src/components/CCAgents.tsx index f72b154ee..3ecaa5d75 100644 --- a/src/components/CCAgents.tsx +++ b/src/components/CCAgents.tsx @@ -1,9 +1,9 @@ import React, { useState, useEffect } from "react"; import { motion, AnimatePresence } from "framer-motion"; -import { - Plus, - Edit, - Trash2, +import { + Plus, + Edit, + Trash2, Play, Bot, ArrowLeft, @@ -40,6 +40,7 @@ import { AgentExecution } from "./AgentExecution"; import { AgentRunsList } from "./AgentRunsList"; import { GitHubAgentBrowser } from "./GitHubAgentBrowser"; import { ICON_MAP } from "./IconPicker"; +import { useTranslation } from "@/hooks/useTranslation"; interface CCAgentsProps { /** @@ -64,6 +65,7 @@ export type AgentIconName = keyof typeof AGENT_ICONS; * setView('home')} /> */ export const CCAgents: React.FC = ({ onBack, className }) => { + const { t } = useTranslation('agents'); const [agents, setAgents] = useState([]); const [runs, setRuns] = useState([]); const [loading, setLoading] = useState(true); @@ -94,8 +96,8 @@ export const CCAgents: React.FC = ({ onBack, className }) => { setAgents(agentsList); } catch (err) { console.error("Failed to load agents:", err); - setError("Failed to load agents"); - setToast({ message: "Failed to load agents", type: "error" }); + setError(t('messages.failed_to_load')); + setToast({ message: t('messages.failed_to_load'), type: "error" }); } finally { setLoading(false); } @@ -132,12 +134,12 @@ export const CCAgents: React.FC = ({ onBack, className }) => { try { setIsDeleting(true); await api.deleteAgent(agentToDelete.id); - setToast({ message: "Agent deleted successfully", type: "success" }); + setToast({ message: t('messages.agent_deleted'), type: "success" }); await loadAgents(); await loadRuns(); // Reload runs as they might be affected } catch (err) { console.error("Failed to delete agent:", err); - setToast({ message: "Failed to delete agent", type: "error" }); + setToast({ message: t('messages.failed_to_delete'), type: "error" }); } finally { setIsDeleting(false); setShowDeleteDialog(false); @@ -166,13 +168,13 @@ export const CCAgents: React.FC = ({ onBack, className }) => { const handleAgentCreated = async () => { setView("list"); await loadAgents(); - setToast({ message: "Agent created successfully", type: "success" }); + setToast({ message: t('messages.agent_created'), type: "success" }); }; const handleAgentUpdated = async () => { setView("list"); await loadAgents(); - setToast({ message: "Agent updated successfully", type: "success" }); + setToast({ message: t('messages.agent_updated'), type: "success" }); }; // const handleRunClick = (run: AgentRunWithMetrics) => { @@ -197,22 +199,22 @@ export const CCAgents: React.FC = ({ onBack, className }) => { extensions: ['opcode.json'] }] }); - + if (!filePath) { // User cancelled the dialog return; } - + // Export the agent to the selected file - await invoke('export_agent_to_file', { + await invoke('export_agent_to_file', { id: agent.id!, - filePath + filePath }); - - setToast({ message: `Agent "${agent.name}" exported successfully`, type: "success" }); + + setToast({ message: t('messages.agent_exported', { name: agent.name }), type: "success" }); } catch (err) { console.error("Failed to export agent:", err); - setToast({ message: "Failed to export agent", type: "error" }); + setToast({ message: t('messages.failed_to_export'), type: "error" }); } }; @@ -226,20 +228,20 @@ export const CCAgents: React.FC = ({ onBack, className }) => { extensions: ['opcode.json', 'json'] }] }); - + if (!filePath) { // User cancelled the dialog return; } - + // Import the agent from the selected file await api.importAgentFromFile(filePath as string); - - setToast({ message: "Agent imported successfully", type: "success" }); + + setToast({ message: t('messages.agent_imported'), type: "success" }); await loadAgents(); } catch (err) { console.error("Failed to import agent:", err); - const errorMessage = err instanceof Error ? err.message : "Failed to import agent"; + const errorMessage = err instanceof Error ? err.message : t('messages.failed_to_import'); setToast({ message: errorMessage, type: "error" }); } }; @@ -308,9 +310,9 @@ export const CCAgents: React.FC = ({ onBack, className }) => {
-

CC Agents

+

{t('title')}

- Manage your Claude Code agents + {t('subtitle')}

@@ -323,18 +325,18 @@ export const CCAgents: React.FC = ({ onBack, className }) => { className="flex items-center gap-2" > - Import + {t('buttons.import')} - From File + {t('buttons.import_from_file')} setShowGitHubBrowser(true)}> - From GitHub + {t('buttons.import_from_github')} @@ -344,7 +346,7 @@ export const CCAgents: React.FC = ({ onBack, className }) => { className="flex items-center gap-2" > - Create CC Agent + {t('buttons.create')} @@ -380,13 +382,13 @@ export const CCAgents: React.FC = ({ onBack, className }) => { ) : agents.length === 0 ? (
-

No agents yet

+

{t('messages.no_agents')}

- Create your first CC Agent to get started + {t('messages.create_first_agent')}

) : ( @@ -410,7 +412,7 @@ export const CCAgents: React.FC = ({ onBack, className }) => { {agent.name}

- Created: {new Date(agent.created_at).toLocaleDateString()} + {t('labels.created')}: {new Date(agent.created_at).toLocaleDateString()}

@@ -419,40 +421,40 @@ export const CCAgents: React.FC = ({ onBack, className }) => { variant="ghost" onClick={() => handleExecuteAgent(agent)} className="flex items-center gap-1" - title="Execute agent" + title={t('buttons.execute')} > - Execute + {t('buttons.execute')} @@ -470,10 +472,10 @@ export const CCAgents: React.FC = ({ onBack, className }) => { onClick={() => setCurrentPage(p => Math.max(1, p - 1))} disabled={currentPage === 1} > - Previous + {t('pagination.previous')} - Page {currentPage} of {totalPages} + {t('pagination.page_of', { current: currentPage, total: totalPages })} )} @@ -494,15 +496,15 @@ export const CCAgents: React.FC = ({ onBack, className }) => {
-

Recent Executions

+

{t('execution.recent_executions')}

{runsLoading ? (
) : ( - )}
@@ -530,7 +532,7 @@ export const CCAgents: React.FC = ({ onBack, className }) => { onImportSuccess={async () => { setShowGitHubBrowser(false); await loadAgents(); - setToast({ message: "Agent imported successfully from GitHub", type: "success" }); + setToast({ message: t('messages.agent_imported_github'), type: "success" }); }} /> @@ -540,11 +542,10 @@ export const CCAgents: React.FC = ({ onBack, className }) => { - Delete Agent + {t('delete_dialog.title')} - Are you sure you want to delete the agent "{agentToDelete?.name}"? - This action cannot be undone and will permanently remove the agent and all its associated data. + {t('delete_dialog.description', { name: agentToDelete?.name })} @@ -554,7 +555,7 @@ export const CCAgents: React.FC = ({ onBack, className }) => { disabled={isDeleting} className="w-full sm:w-auto" > - Cancel + {t('common:buttons.cancel')} diff --git a/src/components/CheckpointSettings.tsx b/src/components/CheckpointSettings.tsx index 4f2549836..259bd3d19 100644 --- a/src/components/CheckpointSettings.tsx +++ b/src/components/CheckpointSettings.tsx @@ -1,6 +1,7 @@ import React, { useState, useEffect } from "react"; import { motion } from "framer-motion"; -import { +import { useTranslation } from "react-i18next"; +import { Wrench, Save, Trash2, @@ -41,6 +42,7 @@ export const CheckpointSettings: React.FC = ({ projectPath, className, }) => { + const { t } = useTranslation('settings'); const [autoCheckpointEnabled, setAutoCheckpointEnabled] = useState(true); const [checkpointStrategy, setCheckpointStrategy] = useState("smart"); const [totalCheckpoints, setTotalCheckpoints] = useState(0); @@ -51,10 +53,10 @@ export const CheckpointSettings: React.FC = ({ const [successMessage, setSuccessMessage] = useState(null); const strategyOptions: SelectOption[] = [ - { value: "manual", label: "Manual Only" }, - { value: "per_prompt", label: "After Each Prompt" }, - { value: "per_tool_use", label: "After Tool Use" }, - { value: "smart", label: "Smart (Recommended)" }, + { value: "manual", label: t('checkpoint.strategy.manual') }, + { value: "per_prompt", label: t('checkpoint.strategy.per_prompt') }, + { value: "per_tool_use", label: t('checkpoint.strategy.per_tool_use') }, + { value: "smart", label: t('checkpoint.strategy.smart') }, ]; useEffect(() => { @@ -72,7 +74,7 @@ export const CheckpointSettings: React.FC = ({ setTotalCheckpoints(settings.total_checkpoints); } catch (err) { console.error("Failed to load checkpoint settings:", err); - setError("Failed to load checkpoint settings"); + setError(t('checkpoint.messages.failed_to_load')); } finally { setIsLoading(false); } @@ -91,12 +93,12 @@ export const CheckpointSettings: React.FC = ({ autoCheckpointEnabled, checkpointStrategy ); - - setSuccessMessage("Settings saved successfully"); + + setSuccessMessage(t('checkpoint.messages.saved')); setTimeout(() => setSuccessMessage(null), 3000); } catch (err) { console.error("Failed to save checkpoint settings:", err); - setError("Failed to save checkpoint settings"); + setError(t('checkpoint.messages.failed_to_save')); } finally { setIsSaving(false); } @@ -114,15 +116,15 @@ export const CheckpointSettings: React.FC = ({ projectPath, keepCount ); - - setSuccessMessage(`Removed ${removed} old checkpoints`); + + setSuccessMessage(t('checkpoint.messages.cleanup_success', { count: removed })); setTimeout(() => setSuccessMessage(null), 3000); - + // Reload settings to get updated count await loadSettings(); } catch (err) { console.error("Failed to cleanup checkpoints:", err); - setError("Failed to cleanup checkpoints"); + setError(t('checkpoint.messages.failed_to_cleanup')); } finally { setIsLoading(false); } @@ -143,8 +145,8 @@ export const CheckpointSettings: React.FC = ({
-

Checkpoint Settings

-

Manage session checkpoints and recovery

+

{t('checkpoint.title')}

+

{t('checkpoint.description')}

@@ -154,9 +156,9 @@ export const CheckpointSettings: React.FC = ({
-

Experimental Feature

+

{t('checkpoint.experimental_warning.title')}

- Checkpointing may affect directory structure or cause data loss. Use with caution. + {t('checkpoint.experimental_warning.description')}

@@ -192,9 +194,9 @@ export const CheckpointSettings: React.FC = ({ {/* Auto-checkpoint toggle */}
- +

- Automatically create checkpoints based on the selected strategy + {t('checkpoint.auto_checkpoint.description')}

= ({ {/* Checkpoint strategy */}
- + setCheckpointStrategy(value as CheckpointStrategy)} @@ -215,10 +217,10 @@ export const CheckpointSettings: React.FC = ({ disabled={isLoading || !autoCheckpointEnabled} />

- {checkpointStrategy === "manual" && "Checkpoints will only be created manually"} - {checkpointStrategy === "per_prompt" && "A checkpoint will be created after each user prompt"} - {checkpointStrategy === "per_tool_use" && "A checkpoint will be created after each tool use"} - {checkpointStrategy === "smart" && "Checkpoints will be created after destructive operations"} + {checkpointStrategy === "manual" && t('checkpoint.strategy.descriptions.manual')} + {checkpointStrategy === "per_prompt" && t('checkpoint.strategy.descriptions.per_prompt')} + {checkpointStrategy === "per_tool_use" && t('checkpoint.strategy.descriptions.per_tool_use')} + {checkpointStrategy === "smart" && t('checkpoint.strategy.descriptions.smart')}

@@ -236,12 +238,12 @@ export const CheckpointSettings: React.FC = ({ {isSaving ? ( <> - Saving... + {t('checkpoint.messages.saving')} ) : ( <> - Save Settings + {t('buttons.save_settings')} )} @@ -254,17 +256,17 @@ export const CheckpointSettings: React.FC = ({
- +

- Total checkpoints: {totalCheckpoints} + {t('checkpoint.storage.total_checkpoints')} {totalCheckpoints}

{/* Cleanup settings */}
- +
= ({ className="hover:bg-destructive/10 hover:text-destructive hover:border-destructive/50" > - Clean Up + {t('checkpoint.storage.cleanup_button')}

- Remove old checkpoints, keeping only the most recent {keepCount} + {t('checkpoint.storage.cleanup_description')} {keepCount}

diff --git a/src/components/ClaudeBinaryDialog.tsx b/src/components/ClaudeBinaryDialog.tsx index eb72ccd62..25f7b25b4 100644 --- a/src/components/ClaudeBinaryDialog.tsx +++ b/src/components/ClaudeBinaryDialog.tsx @@ -4,6 +4,7 @@ import { Button } from "@/components/ui/button"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog"; import { ExternalLink, FileQuestion, Terminal, AlertCircle, Loader2 } from "lucide-react"; import { ClaudeVersionSelector } from "./ClaudeVersionSelector"; +import { useTranslation } from "@/hooks/useTranslation"; interface ClaudeBinaryDialogProps { open: boolean; @@ -13,6 +14,7 @@ interface ClaudeBinaryDialogProps { } export function ClaudeBinaryDialog({ open, onOpenChange, onSuccess, onError }: ClaudeBinaryDialogProps) { + const { t } = useTranslation('settings'); const [selectedInstallation, setSelectedInstallation] = useState(null); const [isValidating, setIsValidating] = useState(false); const [hasInstallations, setHasInstallations] = useState(true); @@ -39,7 +41,7 @@ export function ClaudeBinaryDialog({ open, onOpenChange, onSuccess, onError }: C const handleSave = async () => { if (!selectedInstallation) { - onError("Please select a Claude installation"); + onError(t('claude_binary_dialog.select_installation_first')); return; } @@ -50,7 +52,7 @@ export function ClaudeBinaryDialog({ open, onOpenChange, onSuccess, onError }: C onOpenChange(false); } catch (error) { console.error("Failed to save Claude binary path:", error); - onError(error instanceof Error ? error.message : "Failed to save Claude binary path"); + onError(error instanceof Error ? error.message : t('claude_binary_dialog.failed_to_save')); } finally { setIsValidating(false); } @@ -62,29 +64,27 @@ export function ClaudeBinaryDialog({ open, onOpenChange, onSuccess, onError }: C - Select Claude Code Installation + {t('claude_binary_dialog.title')} {checkingInstallations ? (
- Searching for Claude installations... + {t('claude_binary_dialog.searching')}
) : hasInstallations ? (

- Multiple Claude Code installations were found on your system. - Please select which one you'd like to use. + {t('claude_binary_dialog.multiple_found')}

) : ( <>

- Claude Code was not found in any of the common installation locations. - Please install Claude Code to continue. + {t('claude_binary_dialog.not_found')}

- Searched locations: PATH, /usr/local/bin, + {t('claude_binary_dialog.searched_locations')} PATH, /usr/local/bin, /opt/homebrew/bin, ~/.nvm/versions/node/*/bin, ~/.claude/local, ~/.local/bin

@@ -94,7 +94,7 @@ export function ClaudeBinaryDialog({ open, onOpenChange, onSuccess, onError }: C

- Tip: You can install Claude Code using{" "} + {t('claude_binary_dialog.install_tip')} {t('claude_binary_dialog.install_command')}{" "} npm install -g @claude

@@ -118,20 +118,20 @@ export function ClaudeBinaryDialog({ open, onOpenChange, onSuccess, onError }: C className="mr-auto" > - Installation Guide + {t('claude_binary_dialog.installation_guide')} -
diff --git a/src/components/ClaudeCodeSession.refactored.tsx b/src/components/ClaudeCodeSession.refactored.tsx deleted file mode 100644 index 8b243324b..000000000 --- a/src/components/ClaudeCodeSession.refactored.tsx +++ /dev/null @@ -1,420 +0,0 @@ -import React, { useState, useEffect, useRef, useCallback } from "react"; -import { motion } from "framer-motion"; -import { Button } from "@/components/ui/button"; -import { Input } from "@/components/ui/input"; -import { Label } from "@/components/ui/label"; -import { api, type Session } from "@/lib/api"; -import { cn } from "@/lib/utils"; -import { open } from "@tauri-apps/plugin-dialog"; -import { FloatingPromptInput, type FloatingPromptInputRef } from "./FloatingPromptInput"; -import { ErrorBoundary } from "./ErrorBoundary"; -import { TimelineNavigator } from "./TimelineNavigator"; -import { CheckpointSettings } from "./CheckpointSettings"; -import { SlashCommandsManager } from "./SlashCommandsManager"; -import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter } from "@/components/ui/dialog"; -import { SplitPane } from "@/components/ui/split-pane"; -import { WebviewPreview } from "./WebviewPreview"; - -// Import refactored components and hooks -import { useClaudeMessages } from "./claude-code-session/useClaudeMessages"; -import { useCheckpoints } from "./claude-code-session/useCheckpoints"; -import { SessionHeader } from "./claude-code-session/SessionHeader"; -import { MessageList } from "./claude-code-session/MessageList"; -import { PromptQueue } from "./claude-code-session/PromptQueue"; - -interface ClaudeCodeSessionProps { - session?: Session; - initialProjectPath?: string; - onBack: () => void; - onProjectSettings?: (projectPath: string) => void; - className?: string; - onStreamingChange?: (isStreaming: boolean, sessionId: string | null) => void; -} - -export const ClaudeCodeSession: React.FC = ({ - session, - initialProjectPath = "", - onBack, - onProjectSettings, - className, - onStreamingChange, -}) => { - const [projectPath, setProjectPath] = useState(initialProjectPath || session?.project_path || ""); - const [error, setError] = useState(null); - const [copyPopoverOpen, setCopyPopoverOpen] = useState(false); - const [isFirstPrompt, setIsFirstPrompt] = useState(!session); - const [totalTokens, setTotalTokens] = useState(0); - const [claudeSessionId, setClaudeSessionId] = useState(null); - const [showTimeline, setShowTimeline] = useState(false); - const [showSettings, setShowSettings] = useState(false); - const [showForkDialog, setShowForkDialog] = useState(false); - const [showSlashCommandsSettings, setShowSlashCommandsSettings] = useState(false); - const [forkCheckpointId, setForkCheckpointId] = useState(null); - const [forkSessionName, setForkSessionName] = useState(""); - const [queuedPrompts, setQueuedPrompts] = useState>([]); - const [showPreview, setShowPreview] = useState(false); - const [previewUrl, setPreviewUrl] = useState(null); - const [isPreviewMaximized, setIsPreviewMaximized] = useState(false); - const promptInputRef = useRef(null); - const processQueueTimeoutRef = useRef(null); - - // Use custom hooks - const { - messages, - rawJsonlOutput, - isStreaming, - currentSessionId: _currentSessionId, - clearMessages, - loadMessages - } = useClaudeMessages({ - onSessionInfo: (info) => { - setClaudeSessionId(info.sessionId); - }, - onTokenUpdate: setTotalTokens, - onStreamingChange - }); - - const { - checkpoints: _checkpoints, - timelineVersion, - loadCheckpoints, - createCheckpoint: _createCheckpoint, - restoreCheckpoint, - forkCheckpoint - } = useCheckpoints({ - sessionId: claudeSessionId, - projectId: session?.project_id || '', - projectPath: projectPath, - onToast: (message: string, type: 'success' | 'error') => { - console.log(`Toast: ${type} - ${message}`); - } - }); - - // Handle path selection - const handleSelectPath = async () => { - const selected = await open({ - directory: true, - multiple: false, - title: "Select Project Directory" - }); - - if (selected && typeof selected === 'string') { - setProjectPath(selected); - setError(null); - setIsFirstPrompt(true); - } - }; - - // Handle sending prompts - const handleSendPrompt = useCallback(async (prompt: string, model: "sonnet" | "opus") => { - console.log('[TRACE] handleSendPrompt called:'); - console.log('[TRACE] prompt length:', prompt.length); - console.log('[TRACE] model:', model); - console.log('[TRACE] projectPath:', projectPath); - console.log('[TRACE] isStreaming:', isStreaming); - console.log('[TRACE] isFirstPrompt:', isFirstPrompt); - console.log('[TRACE] claudeSessionId:', claudeSessionId); - - if (!projectPath || !prompt.trim()) { - console.log('[TRACE] Aborting - no project path or empty prompt'); - return; - } - - // Add to queue if streaming - if (isStreaming) { - console.log('[TRACE] Currently streaming - adding to queue'); - const id = Date.now().toString(); - setQueuedPrompts(prev => [...prev, { id, prompt, model }]); - return; - } - - try { - console.log('[TRACE] Clearing error and starting prompt execution'); - setError(null); - - if (isFirstPrompt) { - console.log('[TRACE] First prompt - calling api.executeClaudeCode'); - await api.executeClaudeCode(projectPath, prompt, model); - setIsFirstPrompt(false); - console.log('[TRACE] executeClaudeCode completed'); - } else if (claudeSessionId) { - console.log('[TRACE] Continue prompt - calling api.continueClaudeCode'); - await api.continueClaudeCode(projectPath, prompt, model); - console.log('[TRACE] continueClaudeCode completed'); - } else { - console.log('[TRACE] No claude session ID for continue'); - } - } catch (error) { - console.error("[TRACE] Failed to send prompt:", error); - setError(error instanceof Error ? error.message : "Failed to send prompt"); - } - }, [projectPath, isStreaming, isFirstPrompt, claudeSessionId]); - - // Process queued prompts - const processQueuedPrompts = useCallback(async () => { - if (queuedPrompts.length === 0 || isStreaming) return; - - const nextPrompt = queuedPrompts[0]; - setQueuedPrompts(prev => prev.slice(1)); - - await handleSendPrompt(nextPrompt.prompt, nextPrompt.model); - }, [queuedPrompts, isStreaming, handleSendPrompt]); - - // Effect to process queue when streaming stops - useEffect(() => { - if (!isStreaming && queuedPrompts.length > 0) { - processQueueTimeoutRef.current = setTimeout(processQueuedPrompts, 500); - } - - return () => { - if (processQueueTimeoutRef.current) { - clearTimeout(processQueueTimeoutRef.current); - } - }; - }, [isStreaming, queuedPrompts.length, processQueuedPrompts]); - - // Copy handlers - const handleCopyAsJsonl = async () => { - try { - await navigator.clipboard.writeText(rawJsonlOutput.join('\n')); - setCopyPopoverOpen(false); - console.log("Session output copied as JSONL"); - } catch (error) { - console.error("Failed to copy:", error); - } - }; - - const handleCopyAsMarkdown = async () => { - try { - const markdown = messages - .filter(msg => msg.type === 'user' || msg.type === 'assistant') - .map(msg => { - if (msg.type === 'user') { - return `## User\n\n${msg.message || ''}`; - } else if (msg.type === 'assistant' && msg.message?.content) { - const content = Array.isArray(msg.message.content) - ? msg.message.content.map((item: any) => { - if (typeof item === 'string') return item; - if (item.type === 'text') return item.text; - return ''; - }).filter(Boolean).join('') - : msg.message.content; - return `## Assistant\n\n${content}`; - } - return ''; - }) - .filter(Boolean) - .join('\n\n---\n\n'); - - await navigator.clipboard.writeText(markdown); - setCopyPopoverOpen(false); - console.log("Session output copied as Markdown"); - } catch (error) { - console.error("Failed to copy:", error); - } - }; - - // Fork dialog handlers - const handleFork = (checkpointId: string) => { - setForkCheckpointId(checkpointId); - setForkSessionName(""); - setShowForkDialog(true); - }; - - const handleConfirmFork = async () => { - if (!forkCheckpointId || !forkSessionName.trim()) return; - - const forkedSession = await forkCheckpoint(forkCheckpointId, forkSessionName); - if (forkedSession) { - setShowForkDialog(false); - // Navigate to forked session - window.location.reload(); // Or use proper navigation - } - }; - - // Link detection handler - const handleLinkDetected = (url: string) => { - setPreviewUrl(url); - if (!showPreview) { - setShowPreview(true); - } - }; - - // Load session if provided - useEffect(() => { - if (session) { - setProjectPath(session.project_path); - setClaudeSessionId(session.id); - loadMessages(session.id); - loadCheckpoints(); - } - }, [session, loadMessages, loadCheckpoints]); - - return ( - -
- {/* Header */} - 0} - showTimeline={showTimeline} - copyPopoverOpen={copyPopoverOpen} - onBack={onBack} - onSelectPath={handleSelectPath} - onCopyAsJsonl={handleCopyAsJsonl} - onCopyAsMarkdown={handleCopyAsMarkdown} - onToggleTimeline={() => setShowTimeline(!showTimeline)} - onProjectSettings={onProjectSettings ? () => onProjectSettings(projectPath) : undefined} - onSlashCommandsSettings={() => setShowSlashCommandsSettings(true)} - setCopyPopoverOpen={setCopyPopoverOpen} - /> - - {/* Main content area */} -
- {showPreview ? ( - - - setQueuedPrompts(prev => prev.filter(p => p.id !== id))} - /> -
- } - right={ - setShowPreview(false)} - onUrlChange={setPreviewUrl} - onToggleMaximize={() => setIsPreviewMaximized(!isPreviewMaximized)} - /> - } - initialSplit={60} - /> - ) : ( -
- - setQueuedPrompts(prev => prev.filter(p => p.id !== id))} - /> -
- )} -
- - {/* Error display */} - {error && ( - -

{error}

-
- )} - - {/* Floating prompt input */} - {projectPath && ( - { - if (claudeSessionId && isStreaming) { - await api.cancelClaudeExecution(claudeSessionId); - } - }} - /> - )} - - {/* Timeline Navigator */} - {showTimeline && claudeSessionId && session && ( - { - const success = await restoreCheckpoint(checkpoint.id); - if (success) { - clearMessages(); - loadMessages(claudeSessionId); - } - }} - onFork={handleFork} - refreshVersion={timelineVersion} - /> - )} - - {/* Settings dialogs */} - {showSettings && claudeSessionId && session && ( - setShowSettings(false)} - /> - )} - - {showSlashCommandsSettings && projectPath && ( - - )} - - {/* Fork dialog */} - - - - Fork Session from Checkpoint - - Create a new session branching from this checkpoint. The original session will remain unchanged. - - -
-
- - setForkSessionName(e.target.value)} - placeholder="Enter a name for the forked session" - className="mt-2" - /> -
-
- - - - -
-
- -
- ); -}; \ No newline at end of file diff --git a/src/components/ClaudeCodeSession.tsx b/src/components/ClaudeCodeSession.tsx index f0f164f21..9af339c66 100644 --- a/src/components/ClaudeCodeSession.tsx +++ b/src/components/ClaudeCodeSession.tsx @@ -1,6 +1,6 @@ import React, { useState, useEffect, useRef, useMemo } from "react"; import { motion, AnimatePresence } from "framer-motion"; -import { +import { Copy, ChevronDown, GitBranch, @@ -15,6 +15,7 @@ import { Label } from "@/components/ui/label"; import { Popover } from "@/components/ui/popover"; import { api, type Session } from "@/lib/api"; import { cn } from "@/lib/utils"; +import { useTranslation } from "react-i18next"; // Conditional imports for Tauri APIs let tauriListen: any; @@ -106,6 +107,7 @@ export const ClaudeCodeSession: React.FC = ({ onStreamingChange, onProjectPathChange, }) => { + const { t } = useTranslation('sessions'); const [projectPath] = useState(initialProjectPath || session?.project_path || ""); const [messages, setMessages] = useState([]); const [isLoading, setIsLoading] = useState(false); @@ -491,7 +493,7 @@ export const ClaudeCodeSession: React.FC = ({ console.log('[ClaudeCodeSession] handleSendPrompt called with:', { prompt, model, projectPath, claudeSessionId, effectiveSession }); if (!projectPath) { - setError("Please select a project directory first"); + setError(t('messages.select_project_first')); return; } @@ -1061,19 +1063,19 @@ export const ClaudeCodeSession: React.FC = ({ const cancelMessage: ClaudeStreamMessage = { type: "system", subtype: "info", - result: "Session cancelled by user", + result: t('messages.session_cancelled'), timestamp: new Date().toISOString() }; setMessages(prev => [...prev, cancelMessage]); } catch (err) { console.error("Failed to cancel execution:", err); - + // Even if backend fails, we should update UI to reflect stopped state // Add error message but still stop the UI loading state const errorMessage: ClaudeStreamMessage = { type: "system", subtype: "error", - result: `Failed to cancel execution: ${err instanceof Error ? err.message : 'Unknown error'}. The process may still be running in the background.`, + result: t('messages.failed_cancel', { error: err instanceof Error ? err.message : 'Unknown error' }), timestamp: new Date().toISOString() }; setMessages(prev => [...prev, errorMessage]); @@ -1358,7 +1360,7 @@ export const ClaudeCodeSession: React.FC = ({
- {session ? "Loading session history..." : "Initializing Claude Code..."} + {session ? t('messages.loading_history') : t('messages.initializing')}
@@ -1381,9 +1383,9 @@ export const ClaudeCodeSession: React.FC = ({
- Queued Prompts ({queuedPrompts.length}) + {t('labels.queued_prompts', { count: queuedPrompts.length })}
- + = ({ className="fixed bottom-32 right-6 z-50" >
- + = ({
- + = ({ extraMenuItems={ <> {effectiveSession && ( - + = ({ {messages.length > 0 && ( + = ({ onClick={handleCopyAsMarkdown} className="w-full justify-start text-xs" > - Copy as Markdown + {t('copy.as_markdown')}
} @@ -1590,7 +1592,7 @@ export const ClaudeCodeSession: React.FC = ({ align="end" /> )} - + = ({
{totalTokens.toLocaleString()} - tokens + {t('labels.tokens')}
@@ -1646,7 +1648,7 @@ export const ClaudeCodeSession: React.FC = ({
{/* Timeline Header */}
-

Session Timeline

+

{t('timeline.title')}

@@ -1745,9 +1747,9 @@ export const ClaudeCodeSession: React.FC = ({ - Slash Commands + {t('slash_commands.title')} - Manage project-specific slash commands for {projectPath} + {t('slash_commands.description', { projectPath })}
diff --git a/src/components/ClaudeFileEditor.tsx b/src/components/ClaudeFileEditor.tsx index 252e3e7bc..9fdcddcc8 100644 --- a/src/components/ClaudeFileEditor.tsx +++ b/src/components/ClaudeFileEditor.tsx @@ -6,6 +6,7 @@ import { Button } from "@/components/ui/button"; import { Toast, ToastContainer } from "@/components/ui/toast"; import { api, type ClaudeMdFile } from "@/lib/api"; import { cn } from "@/lib/utils"; +import { useTranslation } from "@/hooks/useTranslation"; interface ClaudeFileEditorProps { /** @@ -36,20 +37,21 @@ export const ClaudeFileEditor: React.FC = ({ onBack, className, }) => { + const { t } = useTranslation('sessions'); const [content, setContent] = useState(""); const [originalContent, setOriginalContent] = useState(""); const [loading, setLoading] = useState(true); const [saving, setSaving] = useState(false); const [error, setError] = useState(null); const [toast, setToast] = useState<{ message: string; type: "success" | "error" } | null>(null); - + const hasChanges = content !== originalContent; - + // Load the file content on mount useEffect(() => { loadFileContent(); }, [file.absolute_path]); - + const loadFileContent = async () => { try { setLoading(true); @@ -59,12 +61,12 @@ export const ClaudeFileEditor: React.FC = ({ setOriginalContent(fileContent); } catch (err) { console.error("Failed to load file:", err); - setError("Failed to load CLAUDE.md file"); + setError(t('claude_file_editor.failed_to_load')); } finally { setLoading(false); } }; - + const handleSave = async () => { try { setSaving(true); @@ -72,26 +74,26 @@ export const ClaudeFileEditor: React.FC = ({ setToast(null); await api.saveClaudeMdFile(file.absolute_path, content); setOriginalContent(content); - setToast({ message: "File saved successfully", type: "success" }); + setToast({ message: t('claude_file_editor.saved_successfully'), type: "success" }); } catch (err) { console.error("Failed to save file:", err); - setError("Failed to save CLAUDE.md file"); - setToast({ message: "Failed to save file", type: "error" }); + setError(t('claude_file_editor.failed_to_save')); + setToast({ message: t('claude_file_editor.failed_to_save'), type: "error" }); } finally { setSaving(false); } }; - + const handleBack = () => { if (hasChanges) { const confirmLeave = window.confirm( - "You have unsaved changes. Are you sure you want to leave?" + t('claude_file_editor.unsaved_changes_warning') ); if (!confirmLeave) return; } onBack(); }; - + return (
@@ -114,11 +116,11 @@ export const ClaudeFileEditor: React.FC = ({

{file.relative_path}

- Edit project-specific Claude Code system prompt + {t('claude_file_editor.subtitle')}

- + - + {/* Error display */} {error && ( = ({ {error} )} - + {/* Editor */}
{loading ? ( @@ -163,7 +165,7 @@ export const ClaudeFileEditor: React.FC = ({ )}
- + {/* Toast Notification */} {toast && ( diff --git a/src/components/CreateAgent.tsx b/src/components/CreateAgent.tsx index 96861e8e0..e9dbed64b 100644 --- a/src/components/CreateAgent.tsx +++ b/src/components/CreateAgent.tsx @@ -11,6 +11,7 @@ import { cn } from "@/lib/utils"; import MDEditor from "@uiw/react-md-editor"; import { type AgentIconName } from "./CCAgents"; import { IconPicker, ICON_MAP } from "./IconPicker"; +import { useTranslation } from "@/hooks/useTranslation"; interface CreateAgentProps { @@ -44,6 +45,7 @@ export const CreateAgent: React.FC = ({ onAgentCreated, className, }) => { + const { t } = useTranslation('agents'); const [name, setName] = useState(agent?.name || ""); const [selectedIcon, setSelectedIcon] = useState((agent?.icon as AgentIconName) || "bot"); const [systemPrompt, setSystemPrompt] = useState(agent?.system_prompt || ""); @@ -58,45 +60,46 @@ export const CreateAgent: React.FC = ({ const handleSave = async () => { if (!name.trim()) { - setError("Agent name is required"); + setError(t('validation.name_required')); return; } if (!systemPrompt.trim()) { - setError("System prompt is required"); + setError(t('validation.prompt_required')); return; } try { setSaving(true); setError(null); - + if (isEditMode && agent.id) { await api.updateAgent( - agent.id, - name, - selectedIcon, - systemPrompt, - defaultTask || undefined, + agent.id, + name, + selectedIcon, + systemPrompt, + defaultTask || undefined, model ); } else { await api.createAgent( - name, - selectedIcon, - systemPrompt, - defaultTask || undefined, + name, + selectedIcon, + systemPrompt, + defaultTask || undefined, model ); } - + onAgentCreated(); } catch (err) { console.error("Failed to save agent:", err); - setError(isEditMode ? "Failed to update agent" : "Failed to create agent"); - setToast({ - message: isEditMode ? "Failed to update agent" : "Failed to create agent", - type: "error" + const errorMsg = isEditMode ? t('messages.failed_to_update') : t('messages.failed_to_create'); + setError(errorMsg); + setToast({ + message: errorMsg, + type: "error" }); } finally { setSaving(false); @@ -104,12 +107,12 @@ export const CreateAgent: React.FC = ({ }; const handleBack = () => { - if ((name !== (agent?.name || "") || - selectedIcon !== (agent?.icon || "bot") || + if ((name !== (agent?.name || "") || + selectedIcon !== (agent?.icon || "bot") || systemPrompt !== (agent?.system_prompt || "") || defaultTask !== (agent?.default_task || "") || - model !== (agent?.model || "sonnet")) && - !confirm("You have unsaved changes. Are you sure you want to leave?")) { + model !== (agent?.model || "sonnet")) && + !confirm(t('messages.unsaved_changes'))) { return; } onBack(); @@ -136,17 +139,17 @@ export const CreateAgent: React.FC = ({ size="icon" onClick={handleBack} className="h-9 w-9 -ml-2" - title="Back to Agents" + title={t('buttons.back_to_agents')} >

- {isEditMode ? "Edit Agent" : "Create New Agent"} + {isEditMode ? t('labels.edit_agent') : t('labels.create_new_agent')}

- {isEditMode ? "Update your Claude Code agent configuration" : "Configure a new Claude Code agent"} + {isEditMode ? t('labels.update_agent_config') : t('labels.configure_new_agent')}

@@ -163,12 +166,12 @@ export const CreateAgent: React.FC = ({ {saving ? ( <> - Saving... + {t('buttons.saving')} ) : ( <> - Save Agent + {t('buttons.save_agent')} )} @@ -196,23 +199,23 @@ export const CreateAgent: React.FC = ({ {/* Basic Information */}
-

Basic Information

+

{t('labels.basic_information')}

- + setName(e.target.value)} - placeholder="e.g., Code Assistant" + placeholder={t('placeholders.agent_name')} required className="h-9" />
- +
- + = ({ {/* Model Selection */}
- +
= ({ transition={{ duration: 0.15 }} className={cn( "flex-1 px-4 py-3 rounded-md border transition-all", - model === "sonnet" - ? "border-primary bg-primary/10 text-primary" + model === "sonnet" + ? "border-primary bg-primary/10 text-primary" : "border-border hover:border-primary/50 hover:bg-accent" )} > @@ -257,12 +260,12 @@ export const CreateAgent: React.FC = ({ model === "sonnet" ? "text-primary" : "text-muted-foreground" )} />
-
Claude 4 Sonnet
-
Faster, efficient for most tasks
+
{t('models.sonnet.name')}
+
{t('models.sonnet.description')}
- + setModel("opus")} @@ -270,8 +273,8 @@ export const CreateAgent: React.FC = ({ transition={{ duration: 0.15 }} className={cn( "flex-1 px-4 py-3 rounded-md border transition-all", - model === "opus" - ? "border-primary bg-primary/10 text-primary" + model === "opus" + ? "border-primary bg-primary/10 text-primary" : "border-border hover:border-primary/50 hover:bg-accent" )} > @@ -281,8 +284,8 @@ export const CreateAgent: React.FC = ({ model === "opus" ? "text-primary" : "text-muted-foreground" )} />
-
Claude 4 Opus
-
More capable, better for complex tasks
+
{t('models.opus.name')}
+
{t('models.opus.description')}
@@ -292,19 +295,19 @@ export const CreateAgent: React.FC = ({ {/* Configuration */} -

Configuration

+

{t('labels.configuration')}

- + setDefaultTask(e.target.value)} className="h-9" />

- This will be used as the default task placeholder when executing the agent + {t('default_task_description')}

@@ -312,9 +315,9 @@ export const CreateAgent: React.FC = ({ {/* System Prompt */}
-

System Prompt

+

{t('labels.system_prompt')}

- Define the behavior and capabilities of your Claude Code agent + {t('system_prompt_description')}

diff --git a/src/components/CustomTitlebar.tsx b/src/components/CustomTitlebar.tsx index 3342959b0..7db018107 100644 --- a/src/components/CustomTitlebar.tsx +++ b/src/components/CustomTitlebar.tsx @@ -3,6 +3,7 @@ import { motion } from 'framer-motion'; import { Settings, Minus, Square, X, Bot, BarChart3, FileText, Network, Info, MoreVertical } from 'lucide-react'; import { getCurrentWindow } from '@tauri-apps/api/window'; import { TooltipProvider, TooltipSimple } from '@/components/ui/tooltip-modern'; +import { useTranslation } from '@/hooks/useTranslation'; interface CustomTitlebarProps { onSettingsClick?: () => void; @@ -21,6 +22,7 @@ export const CustomTitlebar: React.FC = ({ onMCPClick, onInfoClick }) => { + const { t } = useTranslation('common'); const [isHovered, setIsHovered] = useState(false); const [isDropdownOpen, setIsDropdownOpen] = useState(false); const dropdownRef = useRef(null); @@ -90,7 +92,7 @@ export const CustomTitlebar: React.FC = ({ handleClose(); }} className="group relative w-3 h-3 rounded-full bg-red-500 hover:bg-red-600 transition-all duration-200 flex items-center justify-center tauri-no-drag" - title="Close" + title={t('actions.close_window')} > {isHovered && ( @@ -104,7 +106,7 @@ export const CustomTitlebar: React.FC = ({ handleMinimize(); }} className="group relative w-3 h-3 rounded-full bg-yellow-500 hover:bg-yellow-600 transition-all duration-200 flex items-center justify-center tauri-no-drag" - title="Minimize" + title={t('actions.minimize')} > {isHovered && ( @@ -118,7 +120,7 @@ export const CustomTitlebar: React.FC = ({ handleMaximize(); }} className="group relative w-3 h-3 rounded-full bg-green-500 hover:bg-green-600 transition-all duration-200 flex items-center justify-center tauri-no-drag" - title="Maximize" + title={t('actions.maximize')} > {isHovered && ( @@ -140,7 +142,7 @@ export const CustomTitlebar: React.FC = ({ {/* Primary actions group */}
{onAgentsClick && ( - + = ({ )} {onUsageClick && ( - + = ({ {/* Secondary actions group */}
{onSettingsClick && ( - + = ({ {/* Dropdown menu for additional options */}
- + setIsDropdownOpen(!isDropdownOpen)} whileTap={{ scale: 0.97 }} @@ -235,7 +237,7 @@ export const CustomTitlebar: React.FC = ({ className="w-full px-4 py-2 text-left text-sm hover:bg-accent hover:text-accent-foreground transition-colors flex items-center gap-3" > - About + {t('navigation.about')} )}
diff --git a/src/components/ExecutionControlBar.tsx b/src/components/ExecutionControlBar.tsx index f7c75d9f7..7181bc4cd 100644 --- a/src/components/ExecutionControlBar.tsx +++ b/src/components/ExecutionControlBar.tsx @@ -3,6 +3,7 @@ import { motion, AnimatePresence } from "framer-motion"; import { StopCircle, Clock, Hash } from "lucide-react"; import { Button } from "@/components/ui/button"; import { cn } from "@/lib/utils"; +import { useTranslation } from "react-i18next"; interface ExecutionControlBarProps { isExecuting: boolean; @@ -16,13 +17,15 @@ interface ExecutionControlBarProps { * Floating control bar shown during agent execution * Provides stop functionality and real-time statistics */ -export const ExecutionControlBar: React.FC = ({ - isExecuting, - onStop, +export const ExecutionControlBar: React.FC = ({ + isExecuting, + onStop, totalTokens = 0, elapsedTime = 0, - className + className }) => { + const { t } = useTranslation(); + // Format elapsed time const formatTime = (seconds: number) => { const mins = Math.floor(seconds / 60); @@ -62,7 +65,7 @@ export const ExecutionControlBar: React.FC = ({
{/* Status text */} - Executing... + {t('agents:execution_control.executing')} {/* Divider */}
@@ -78,7 +81,7 @@ export const ExecutionControlBar: React.FC = ({ {/* Tokens */}
- {formatTokens(totalTokens)} tokens + {formatTokens(totalTokens)} {t('agents:execution_control.tokens')}
@@ -93,7 +96,7 @@ export const ExecutionControlBar: React.FC = ({ className="gap-2" > - Stop + {t('agents:execution_control.stop')} )} diff --git a/src/components/FilePicker.optimized.tsx b/src/components/FilePicker.optimized.tsx deleted file mode 100644 index 4169e79b9..000000000 --- a/src/components/FilePicker.optimized.tsx +++ /dev/null @@ -1,416 +0,0 @@ -import React, { useState, useEffect, useRef, useCallback, useMemo } from "react"; -import { motion } from "framer-motion"; -import { useVirtualizer } from "@tanstack/react-virtual"; -import { Button } from "@/components/ui/button"; -import { api } from "@/lib/api"; -import { - X, - Folder, - File, - ArrowLeft, - FileCode, - FileText, - FileImage, - Search, - ChevronRight -} from "lucide-react"; -import type { FileEntry } from "@/lib/api"; -import { cn } from "@/lib/utils"; - -// Global caches that persist across component instances -const globalDirectoryCache = new Map(); -const globalSearchCache = new Map(); - -interface FilePickerProps { - basePath: string; - onSelect: (entry: FileEntry) => void; - onClose: () => void; - initialQuery?: string; - className?: string; - allowDirectorySelection?: boolean; -} - -// Memoized file icon selector -const getFileIcon = (entry: FileEntry) => { - if (entry.is_directory) return Folder; - - const ext = entry.name.split('.').pop()?.toLowerCase(); - switch (ext) { - case 'js': - case 'jsx': - case 'ts': - case 'tsx': - case 'py': - case 'java': - case 'cpp': - case 'c': - case 'go': - case 'rs': - return FileCode; - case 'md': - case 'txt': - case 'json': - case 'xml': - case 'yaml': - case 'yml': - return FileText; - case 'png': - case 'jpg': - case 'jpeg': - case 'gif': - case 'svg': - case 'webp': - return FileImage; - default: - return File; - } -}; - -const formatFileSize = (bytes: number): string => { - if (bytes === 0) return '0 B'; - const k = 1024; - const sizes = ['B', 'KB', 'MB', 'GB']; - const i = Math.floor(Math.log(bytes) / Math.log(k)); - return `${(bytes / Math.pow(k, i)).toFixed(1)} ${sizes[i]}`; -}; - -export const FilePicker: React.FC = React.memo(({ - basePath, - onSelect, - onClose, - initialQuery = "", - className, - allowDirectorySelection = false -}) => { - const [currentPath, setCurrentPath] = useState(basePath); - const [entries, setEntries] = useState([]); - const [searchQuery, setSearchQuery] = useState(initialQuery); - const [selectedIndex, setSelectedIndex] = useState(0); - const [isLoading, setIsLoading] = useState(false); - const [error, setError] = useState(null); - - const searchInputRef = useRef(null); - const scrollContainerRef = useRef(null); - const searchDebounceRef = useRef(); - - // Filter and sort entries - const displayEntries = useMemo(() => { - const filtered = searchQuery.trim() - ? entries.filter(entry => - entry.name.toLowerCase().includes(searchQuery.toLowerCase()) - ) - : entries; - - return filtered.sort((a, b) => { - if (a.is_directory !== b.is_directory) { - return a.is_directory ? -1 : 1; - } - return a.name.localeCompare(b.name); - }); - }, [entries, searchQuery]); - - // Virtual scrolling setup - const virtualizer = useVirtualizer({ - count: displayEntries.length, - getScrollElement: () => scrollContainerRef.current, - estimateSize: () => 32, // Height of each item - overscan: 10, // Number of items to render outside viewport - }); - - const virtualItems = virtualizer.getVirtualItems(); - - // Load directory contents - const loadDirectory = useCallback(async (path: string) => { - const cacheKey = path; - - // Check cache first - if (globalDirectoryCache.has(cacheKey)) { - setEntries(globalDirectoryCache.get(cacheKey)!); - return; - } - - setIsLoading(true); - setError(null); - - try { - const result = await api.listDirectoryContents(path); - globalDirectoryCache.set(cacheKey, result); - setEntries(result); - } catch (err) { - setError(err instanceof Error ? err.message : 'Failed to load directory'); - } finally { - setIsLoading(false); - } - }, []); - - // Search functionality - const performSearch = useCallback(async (query: string) => { - if (!query.trim()) { - loadDirectory(currentPath); - return; - } - - const cacheKey = `${currentPath}:${query}`; - - if (globalSearchCache.has(cacheKey)) { - setEntries(globalSearchCache.get(cacheKey)!); - return; - } - - setIsLoading(true); - setError(null); - - try { - const result = await api.searchFiles(currentPath, query); - globalSearchCache.set(cacheKey, result); - setEntries(result); - } catch (err) { - setError(err instanceof Error ? err.message : 'Search failed'); - } finally { - setIsLoading(false); - } - }, [currentPath, loadDirectory]); - - // Handle entry click - const handleEntryClick = useCallback((entry: FileEntry) => { - if (!entry.is_directory || allowDirectorySelection) { - onSelect(entry); - } - }, [onSelect, allowDirectorySelection]); - - // Handle entry double click - const handleEntryDoubleClick = useCallback((entry: FileEntry) => { - if (entry.is_directory) { - setCurrentPath(entry.path); - setSearchQuery(""); - setSelectedIndex(0); - } else { - onSelect(entry); - } - }, [onSelect]); - - // Keyboard navigation - const handleKeyDown = useCallback((e: React.KeyboardEvent) => { - if (displayEntries.length === 0) return; - - switch (e.key) { - case 'ArrowUp': - e.preventDefault(); - setSelectedIndex(prev => Math.max(0, prev - 1)); - break; - case 'ArrowDown': - e.preventDefault(); - setSelectedIndex(prev => Math.min(displayEntries.length - 1, prev + 1)); - break; - case 'Enter': - e.preventDefault(); - const selectedEntry = displayEntries[selectedIndex]; - if (selectedEntry) { - if (e.shiftKey || !selectedEntry.is_directory) { - handleEntryClick(selectedEntry); - } else { - handleEntryDoubleClick(selectedEntry); - } - } - break; - case 'Escape': - e.preventDefault(); - onClose(); - break; - } - }, [displayEntries, selectedIndex, handleEntryClick, handleEntryDoubleClick, onClose]); - - // Debounced search - useEffect(() => { - if (searchDebounceRef.current) { - clearTimeout(searchDebounceRef.current); - } - - searchDebounceRef.current = setTimeout(() => { - performSearch(searchQuery); - }, 300); - - return () => { - if (searchDebounceRef.current) { - clearTimeout(searchDebounceRef.current); - } - }; - }, [searchQuery, performSearch]); - - // Load initial directory - useEffect(() => { - loadDirectory(currentPath); - }, [currentPath, loadDirectory]); - - // Focus search input on mount - useEffect(() => { - searchInputRef.current?.focus(); - }, []); - - // Scroll selected item into view - useEffect(() => { - const item = virtualizer.getVirtualItems().find( - vItem => vItem.index === selectedIndex - ); - if (item) { - virtualizer.scrollToIndex(selectedIndex, { align: 'center' }); - } - }, [selectedIndex, virtualizer]); - - return ( - - {/* Header */} -
- - -
- - setSearchQuery(e.target.value)} - placeholder="Search files..." - className="flex-1 bg-transparent outline-none text-sm" - /> -
- - -
- - {/* Current path */} -
-
- {currentPath} -
-
- - {/* File list with virtual scrolling */} -
- {isLoading && ( -
-
Loading...
-
- )} - - {error && ( -
-
{error}
-
- )} - - {!isLoading && !error && displayEntries.length === 0 && ( -
- - - {searchQuery.trim() ? 'No files found' : 'Empty directory'} - -
- )} - - {displayEntries.length > 0 && ( -
- {virtualItems.map((virtualRow) => { - const entry = displayEntries[virtualRow.index]; - const Icon = getFileIcon(entry); - const isSelected = virtualRow.index === selectedIndex; - - return ( -
- -
- ); - })} -
- )} -
- - {/* Footer */} -
-
- {displayEntries.length} {displayEntries.length === 1 ? 'item' : 'items'} -
- {allowDirectorySelection && ( -
- Shift+Enter to select directory -
- )} -
-
- ); -}); \ No newline at end of file diff --git a/src/components/FilePicker.tsx b/src/components/FilePicker.tsx index 3038df4e1..612319cb2 100644 --- a/src/components/FilePicker.tsx +++ b/src/components/FilePicker.tsx @@ -2,10 +2,10 @@ import React, { useState, useEffect, useRef } from "react"; import { motion } from "framer-motion"; import { Button } from "@/components/ui/button"; import { api } from "@/lib/api"; -import { - X, - Folder, - File, +import { + X, + Folder, + File, ArrowLeft, FileCode, FileText, @@ -15,6 +15,7 @@ import { } from "lucide-react"; import type { FileEntry } from "@/lib/api"; import { cn } from "@/lib/utils"; +import { useTranslation } from "@/hooks/useTranslation"; // Global caches that persist across component instances const globalDirectoryCache = new Map(); @@ -101,6 +102,7 @@ export const FilePicker: React.FC = ({ initialQuery = "", className, }) => { + const { t } = useTranslation('common'); const searchQuery = initialQuery; const [currentPath, setCurrentPath] = useState(basePath); @@ -402,14 +404,14 @@ export const FilePicker: React.FC = ({ {/* Show loading only if no cached data */} {isLoading && displayEntries.length === 0 && (
- Loading... + {t('file_picker.loading')}
)} {/* Show subtle indicator when displaying cached data while fetching fresh */} {isShowingCached && isLoading && displayEntries.length > 0 && (
- updating... + {t('file_picker.updating')}
)} @@ -423,7 +425,7 @@ export const FilePicker: React.FC = ({
- {searchQuery.trim() ? 'No files found' : 'Empty directory'} + {searchQuery.trim() ? t('file_picker.no_files_found') : t('file_picker.empty_directory')}
)} @@ -448,7 +450,7 @@ export const FilePicker: React.FC = ({ "text-left text-sm", isSelected && "bg-accent" )} - title={entry.is_directory ? "Click to select • Double-click to enter" : "Click to select"} + title={entry.is_directory ? t('file_picker.click_to_select_double_click_to_enter') : t('file_picker.click_to_select')} > = ({ {/* Footer */}

- ↑↓ Navigate • Enter Select • → Enter Directory • ← Go Back • Esc Close + {t('file_picker.keyboard_shortcuts')}

diff --git a/src/components/FloatingPromptInput.tsx b/src/components/FloatingPromptInput.tsx index 1f042b2c6..021c8e5b1 100644 --- a/src/components/FloatingPromptInput.tsx +++ b/src/components/FloatingPromptInput.tsx @@ -12,7 +12,7 @@ import { Lightbulb, Cpu, Rocket, - + } from "lucide-react"; import { cn } from "@/lib/utils"; import { Button } from "@/components/ui/button"; @@ -23,6 +23,7 @@ import { FilePicker } from "./FilePicker"; import { SlashCommandPicker } from "./SlashCommandPicker"; import { ImagePreview } from "./ImagePreview"; import { type FileEntry, type SlashCommand } from "@/lib/api"; +import { useTranslation } from "@/hooks/useTranslation"; // Conditional import for Tauri webview window let tauriGetCurrentWebviewWindow: any; @@ -35,7 +36,7 @@ try { } // Web-compatible replacement -const getCurrentWebviewWindow = tauriGetCurrentWebviewWindow || (() => ({ listen: () => Promise.resolve(() => {}) })); +const getCurrentWebviewWindow = tauriGetCurrentWebviewWindow || (() => ({ listen: () => Promise.resolve(() => { }) })); interface FloatingPromptInputProps { /** @@ -95,58 +96,6 @@ type ThinkingModeConfig = { shortName: string; }; -const THINKING_MODES: ThinkingModeConfig[] = [ - { - id: "auto", - name: "Auto", - description: "Let Claude decide", - level: 0, - icon: , - color: "text-muted-foreground", - shortName: "A" - }, - { - id: "think", - name: "Think", - description: "Basic reasoning", - level: 1, - phrase: "think", - icon: , - color: "text-primary", - shortName: "T" - }, - { - id: "think_hard", - name: "Think Hard", - description: "Deeper analysis", - level: 2, - phrase: "think hard", - icon: , - color: "text-primary", - shortName: "T+" - }, - { - id: "think_harder", - name: "Think Harder", - description: "Extensive reasoning", - level: 3, - phrase: "think harder", - icon: , - color: "text-primary", - shortName: "T++" - }, - { - id: "ultrathink", - name: "Ultrathink", - description: "Maximum computation", - level: 4, - phrase: "ultrathink", - icon: , - color: "text-primary", - shortName: "Ultra" - } -]; - /** * ThinkingModeIndicator component - Shows visual indicator bars for thinking level */ @@ -155,7 +104,7 @@ const ThinkingModeIndicator: React.FC<{ level: number; color?: string }> = ({ le if (barIndex > level) return "bg-muted"; return "bg-primary"; }; - + return (
{[1, 2, 3, 4].map((i) => ( @@ -181,25 +130,6 @@ type Model = { color: string; }; -const MODELS: Model[] = [ - { - id: "sonnet", - name: "Claude 4 Sonnet", - description: "Faster, efficient for most tasks", - icon: , - shortName: "S", - color: "text-primary" - }, - { - id: "opus", - name: "Claude 4 Opus", - description: "More capable, better for complex tasks", - icon: , - shortName: "O", - color: "text-primary" - } -]; - /** * FloatingPromptInput component - Fixed position prompt input with model picker * @@ -224,6 +154,7 @@ const FloatingPromptInputInner = ( }: FloatingPromptInputProps, ref: React.Ref, ) => { + const { t } = useTranslation('common'); const [prompt, setPrompt] = useState(""); const [selectedModel, setSelectedModel] = useState<"sonnet" | "opus">(defaultModel); const [selectedThinkingMode, setSelectedThinkingMode] = useState("auto"); @@ -244,6 +175,79 @@ const FloatingPromptInputInner = ( const [textareaHeight, setTextareaHeight] = useState(48); const isIMEComposingRef = useRef(false); + // Define thinking modes with translations + const THINKING_MODES: ThinkingModeConfig[] = [ + { + id: "auto", + name: t('prompt_input.thinking_auto'), + description: t('prompt_input.thinking_auto_desc'), + level: 0, + icon: , + color: "text-muted-foreground", + shortName: "A" + }, + { + id: "think", + name: t('prompt_input.thinking_think'), + description: t('prompt_input.thinking_think_desc'), + level: 1, + phrase: "think", + icon: , + color: "text-primary", + shortName: "T" + }, + { + id: "think_hard", + name: t('prompt_input.thinking_think_hard'), + description: t('prompt_input.thinking_think_hard_desc'), + level: 2, + phrase: "think hard", + icon: , + color: "text-primary", + shortName: "T+" + }, + { + id: "think_harder", + name: t('prompt_input.thinking_think_harder'), + description: t('prompt_input.thinking_think_harder_desc'), + level: 3, + phrase: "think harder", + icon: , + color: "text-primary", + shortName: "T++" + }, + { + id: "ultrathink", + name: t('prompt_input.thinking_ultrathink'), + description: t('prompt_input.thinking_ultrathink_desc'), + level: 4, + phrase: "ultrathink", + icon: , + color: "text-primary", + shortName: "Ultra" + } + ]; + + // Define models with translations + const MODELS: Model[] = [ + { + id: "sonnet", + name: t('prompt_input.model_sonnet'), + description: t('prompt_input.model_sonnet_desc'), + icon: , + shortName: "S", + color: "text-primary" + }, + { + id: "opus", + name: t('prompt_input.model_opus'), + description: t('prompt_input.model_opus_desc'), + icon: , + shortName: "O", + color: "text-primary" + } + ]; + // Expose a method to add images programmatically React.useImperativeHandle( ref, @@ -287,50 +291,50 @@ const FloatingPromptInputInner = ( // Extract image paths from prompt text const extractImagePaths = (text: string): string[] => { console.log('[extractImagePaths] Input text length:', text.length); - + // Updated regex to handle both quoted and unquoted paths // Pattern 1: @"path with spaces or data URLs" - quoted paths // Pattern 2: @path - unquoted paths (continues until @ or end) const quotedRegex = /@"([^"]+)"/g; const unquotedRegex = /@([^@\n\s]+)/g; - + const pathsSet = new Set(); // Use Set to ensure uniqueness - + // First, extract quoted paths (including data URLs) let matches = Array.from(text.matchAll(quotedRegex)); console.log('[extractImagePaths] Quoted matches:', matches.length); - + for (const match of matches) { const path = match[1]; // No need to trim, quotes preserve exact path console.log('[extractImagePaths] Processing quoted path:', path.startsWith('data:') ? 'data URL' : path); - + // For data URLs, use as-is; for file paths, convert to absolute - const fullPath = path.startsWith('data:') - ? path + const fullPath = path.startsWith('data:') + ? path : (path.startsWith('/') ? path : (projectPath ? `${projectPath}/${path}` : path)); - + if (isImageFile(fullPath)) { pathsSet.add(fullPath); } } - + // Remove quoted mentions from text to avoid double-matching let textWithoutQuoted = text.replace(quotedRegex, ''); - + // Then extract unquoted paths (typically file paths) matches = Array.from(textWithoutQuoted.matchAll(unquotedRegex)); console.log('[extractImagePaths] Unquoted matches:', matches.length); - + for (const match of matches) { const path = match[1].trim(); // Skip if it looks like a data URL fragment (shouldn't happen with proper quoting) if (path.includes('data:')) continue; - + console.log('[extractImagePaths] Processing unquoted path:', path); - + // Convert relative path to absolute if needed const fullPath = path.startsWith('/') ? path : (projectPath ? `${projectPath}/${path}` : path); - + if (isImageFile(fullPath)) { pathsSet.add(fullPath); } @@ -347,7 +351,7 @@ const FloatingPromptInputInner = ( const imagePaths = extractImagePaths(prompt); console.log('[useEffect] Setting embeddedImages to:', imagePaths); setEmbeddedImages(imagePaths); - + // Auto-resize on prompt change (handles paste, programmatic changes, etc.) if (textareaRef.current && !isExpanded) { textareaRef.current.style.height = 'auto'; @@ -448,7 +452,7 @@ const FloatingPromptInputInner = ( const handleTextChange = (e: React.ChangeEvent) => { const newValue = e.target.value; const newCursorPosition = e.target.selectionStart || 0; - + // Auto-resize textarea based on content if (textareaRef.current && !isExpanded) { // Reset height to auto to get the actual scrollHeight @@ -463,9 +467,9 @@ const FloatingPromptInputInner = ( // Check if / was just typed at the beginning of input or after whitespace if (newValue.length > prompt.length && newValue[newCursorPosition - 1] === '/') { // Check if it's at the start or after whitespace - const isStartOfCommand = newCursorPosition === 1 || + const isStartOfCommand = newCursorPosition === 1 || (newCursorPosition > 1 && /\s/.test(newValue[newCursorPosition - 2])); - + if (isStartOfCommand) { console.log('[FloatingPromptInput] / detected for slash command'); setShowSlashCommandPicker(true); @@ -613,7 +617,7 @@ const FloatingPromptInputInner = ( // Simply insert the command syntax const beforeSlash = prompt.substring(0, slashPosition); const afterCursor = prompt.substring(cursorPosition); - + if (command.accepts_arguments) { // Insert command with placeholder for arguments const newPrompt = `${beforeSlash}${command.full_command} `; @@ -757,7 +761,7 @@ const FloatingPromptInputInner = ( for (const item of items) { if (item.type.startsWith('image/')) { e.preventDefault(); - + // Get the image blob const blob = item.getAsFile(); if (!blob) continue; @@ -767,13 +771,13 @@ const FloatingPromptInputInner = ( const reader = new FileReader(); reader.onload = () => { const base64Data = reader.result as string; - + // Add the base64 data URL directly to the prompt setPrompt(currentPrompt => { // Use the data URL directly as the image reference const mention = `@"${base64Data}"`; const newPrompt = currentPrompt + (currentPrompt.endsWith(' ') || currentPrompt === '' ? '' : ' ') + mention + ' '; - + // Focus the textarea and move cursor to end setTimeout(() => { const target = isExpanded ? expandedTextareaRef.current : textareaRef.current; @@ -784,7 +788,7 @@ const FloatingPromptInputInner = ( return newPrompt; }); }; - + reader.readAsDataURL(blob); } catch (error) { console.error('Failed to paste image:', error); @@ -810,7 +814,7 @@ const FloatingPromptInputInner = ( const handleRemoveImage = (index: number) => { // Remove the corresponding @mention from the prompt const imagePath = embeddedImages[index]; - + // For data URLs, we need to handle them specially since they're always quoted if (imagePath.startsWith('data:')) { // Simply remove the exact quoted data URL @@ -819,11 +823,11 @@ const FloatingPromptInputInner = ( setPrompt(newPrompt); return; } - + // For file paths, use the original logic const escapedPath = imagePath.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); const escapedRelativePath = imagePath.replace(projectPath + '/', '').replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); - + // Create patterns for both quoted and unquoted mentions const patterns = [ // Quoted full path @@ -848,132 +852,132 @@ const FloatingPromptInputInner = ( return ( - <> - {/* Expanded Modal */} - - {isExpanded && ( - setIsExpanded(false)} - > + <> + {/* Expanded Modal */} + + {isExpanded && ( e.stopPropagation()} + initial={{ opacity: 0 }} + animate={{ opacity: 1 }} + exit={{ opacity: 0 }} + className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-background/80 backdrop-blur-sm" + onClick={() => setIsExpanded(false)} > -
-

Compose your prompt

- - - - - -
+ +
+ +
+ + {/* Image previews in expanded mode */} + {embeddedImages.length > 0 && ( + + )} - {/* Image previews in expanded mode */} - {embeddedImages.length > 0 && ( - - )} - -