diff --git a/.github/workflows/build-dmg.yml b/.github/workflows/build-dmg.yml new file mode 100644 index 0000000..b22355a --- /dev/null +++ b/.github/workflows/build-dmg.yml @@ -0,0 +1,59 @@ +name: Build Universal DMG + +on: + workflow_dispatch: + +permissions: + contents: write + +env: + CARGO_TERM_COLOR: always + +jobs: + build-universal: + name: Build macOS Universal + runs-on: macos-latest + steps: + - uses: actions/checkout@v5 + + - name: Install Rust stable with both targets + uses: dtolnay/rust-toolchain@stable + with: + targets: aarch64-apple-darwin,x86_64-apple-darwin + + - name: Install pnpm + uses: pnpm/action-setup@v4 + with: + version: 9 + + - name: Setup Node.js + uses: actions/setup-node@v6 + with: + node-version: "22" + cache: pnpm + cache-dependency-path: crates/cratebay-gui/pnpm-lock.yaml + + - name: Cargo cache + uses: Swatinem/rust-cache@v2 + with: + key: build-universal + + - name: Install frontend dependencies + working-directory: crates/cratebay-gui + run: pnpm install --frozen-lockfile + + - name: Build Tauri Universal app + uses: tauri-apps/tauri-action@v0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + projectPath: crates/cratebay-gui + args: --target universal-apple-darwin + + - name: Upload Universal DMG + uses: actions/upload-artifact@v4 + with: + name: CrateBay-macos-universal + path: | + target/universal-apple-darwin/release/bundle/dmg/*.dmg + if-no-files-found: error diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f38e072..1c3def8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -85,11 +85,21 @@ jobs: target: x86_64-unknown-linux-gnu cli-artifact: cratebay-linux-x86_64 ext: "" + - name: Linux-aarch64 + os: ubuntu-latest + target: aarch64-unknown-linux-gnu + cli-artifact: cratebay-linux-aarch64 + ext: "" - name: Windows-x86_64 os: windows-latest target: x86_64-pc-windows-msvc cli-artifact: cratebay-windows-x86_64 ext: ".exe" + - name: Windows-aarch64 + os: windows-latest + target: aarch64-pc-windows-msvc + cli-artifact: cratebay-windows-aarch64 + ext: ".exe" steps: - uses: actions/checkout@v5 @@ -122,6 +132,14 @@ jobs: key: release-${{ matrix.target }} # -- Build CLI -- + - name: Install cross-compilation dependencies (Linux aarch64) + if: matrix.target == 'aarch64-unknown-linux-gnu' + run: | + sudo apt-get update + sudo apt-get install -y gcc-aarch64-linux-gnu + echo '[target.aarch64-unknown-linux-gnu]' >> ~/.cargo/config.toml + echo 'linker = "aarch64-linux-gnu-gcc"' >> ~/.cargo/config.toml + - name: Build CLI (release) run: cargo build --release --target ${{ matrix.target }} -p cratebay-cli @@ -156,10 +174,18 @@ jobs: os: ubuntu-latest target: x86_64-unknown-linux-gnu artifact: cratebay-gui-linux-x86_64 + - name: Linux-aarch64 + os: ubuntu-latest + target: aarch64-unknown-linux-gnu + artifact: cratebay-gui-linux-aarch64 - name: Windows-x86_64 os: windows-latest target: x86_64-pc-windows-msvc artifact: cratebay-gui-windows-x86_64 + - name: Windows-aarch64 + os: windows-latest + target: aarch64-pc-windows-msvc + artifact: cratebay-gui-windows-aarch64 steps: - uses: actions/checkout@v5 @@ -227,6 +253,22 @@ jobs: qemu-system-x86 \ squashfs-tools + - name: Install cross-compilation dependencies (Linux aarch64) + if: matrix.target == 'aarch64-unknown-linux-gnu' + run: | + sudo dpkg --add-architecture arm64 + sudo apt-get update + sudo apt-get install -y \ + gcc-aarch64-linux-gnu \ + libgtk-3-dev:arm64 \ + libwebkit2gtk-4.1-dev:arm64 \ + libappindicator3-dev:arm64 \ + librsvg2-dev:arm64 \ + patchelf + echo '[target.aarch64-unknown-linux-gnu]' >> ~/.cargo/config.toml + echo 'linker = "aarch64-linux-gnu-gcc"' >> ~/.cargo/config.toml + export PKG_CONFIG_SYSROOT_DIR=/usr/aarch64-linux-gnu + - name: Install Zig (Linux only) if: runner.os == 'Linux' run: bash scripts/install-zig.sh @@ -259,28 +301,61 @@ jobs: working-directory: crates/cratebay-gui run: pnpm install --frozen-lockfile + # macOS: prepare cratebay-vz external binary with entitlements + - name: Prepare external binaries (macOS) + if: runner.os == 'macOS' + shell: bash + run: bash scripts/prepare-tauri-external-bins.sh "${{ matrix.target }}" + + # Build sandbox bundle images (requires Docker) + - name: Build sandbox bundle images + if: runner.os == 'Linux' || runner.os == 'macOS' + shell: bash + run: | + if command -v docker >/dev/null 2>&1 && docker info >/dev/null 2>&1; then + bash scripts/build-bundle-images.sh + else + echo "SKIP: Docker not available, bundle images will not be included" + fi + - name: Build Tauri app uses: tauri-apps/tauri-action@v0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # macOS code signing (Apple Developer ID) - # Required secrets: APPLE_CERTIFICATE, APPLE_CERTIFICATE_PASSWORD, - # APPLE_SIGNING_IDENTITY, APPLE_ID, APPLE_PASSWORD, - # APPLE_TEAM_ID APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }} APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} - # Windows code signing (Authenticode / Azure Trusted Signing) - # Required secrets: WINDOWS_CERTIFICATE, WINDOWS_CERTIFICATE_PASSWORD + # Windows code signing WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }} WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }} with: projectPath: crates/cratebay-gui args: --target ${{ matrix.target }} + # macOS: re-sign cratebay-vz with virtualization entitlements after Tauri bundling + - name: Sign cratebay-vz with virtualization entitlements (macOS) + if: runner.os == 'macOS' + shell: bash + run: | + VZ_BIN="target/${{ matrix.target }}/release/bundle/macos/CrateBay.app/Contents/MacOS/cratebay-vz" + if [ -f "$VZ_BIN" ]; then + identity="${APPLE_SIGNING_IDENTITY:--}" + codesign --force --sign "$identity" \ + --options runtime \ + --entitlements scripts/macos-entitlements.plist \ + "$VZ_BIN" + # Re-sign the outer app bundle + APP_BUNDLE="target/${{ matrix.target }}/release/bundle/macos/CrateBay.app" + codesign --force --sign "$identity" --options runtime "$APP_BUNDLE" + echo "Re-signed cratebay-vz with virtualization entitlements" + fi + env: + APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }} + - name: Verify release bundles shell: bash run: ./scripts/verify-release-artifacts.sh --mode ci --os "${{ runner.os }}" --target "${{ matrix.target }}" diff --git a/AGENTS.md b/AGENTS.md index 92ccb90..10f1a38 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,6 +1,6 @@ # AGENTS.md — CrateBay Project Guide -> **Version**: 0.9.0 | **Branch**: `master` | **Last Updated**: 2026-03-29 +> **Version**: 0.9.0 | **Branch**: `feat/chatpage-v1` | **Last Updated**: 2026-04-01 > > This file is the **entry point** for all AI Agents working on this project. > Detailed specs are in `docs/specs/` — load them on-demand based on your task (see Spec Loading Protocol below). @@ -11,17 +11,26 @@ ## Project Identity -**CrateBay** is an open-source **local AI sandbox** — a secure, private container for AI agents to execute code. +**CrateBay** is an open-source, cross-platform **container management tool with AI sandbox capabilities** — an alternative to Docker Desktop and OrbStack that is fully open-source, works on all platforms, and has built-in AI code execution. -- **MCP Server** (`cratebay-mcp`) — let any AI (Claude, Cursor, Windsurf, your own) run code safely -- **Zero cost** — runs locally in a lightweight VM, no cloud fees +- **Desktop App** (`cratebay-gui`) — manage containers, images, and AI chat with code execution +- **MCP Server** (`cratebay-mcp`) — let any AI (Claude, Cursor, Windsurf) run code safely via MCP protocol +- **CLI** (`cratebay-cli`) — headless container and sandbox operations - **Built-in runtime** — no Docker installation required (macOS: VZ.framework, Linux: KVM, Windows: WSL2) +- **Zero cost** — runs locally in a lightweight VM, no cloud fees - **Platforms**: macOS, Windows, Linux - **License**: MIT -**Core value proposition**: CrateBay replaces cloud sandboxes (E2B, Modal) with a local, free, privacy-first alternative specifically designed for AI agents. +**Core value proposition**: CrateBay combines the container management of Docker Desktop/OrbStack with AI sandbox capabilities (like E2B/Modal) — all open-source, cross-platform, and free. + +**vs Docker Desktop**: open-source, cross-platform, built-in AI +**vs OrbStack**: open-source, cross-platform (not macOS only), built-in AI +**vs E2B/Modal**: local execution, zero cost, full privacy -**User journey**: Install → Configure MCP → Tell Claude "run this code" → CrateBay handles isolation, execution, result delivery. +**User journeys**: +1. **GUI user**: Open CrateBay → Chat with AI → AI runs code in sandboxes → manage containers/images visually +2. **MCP user**: Configure Claude Desktop/Cursor → AI calls sandbox_run_code → CrateBay handles execution +3. **CLI user**: `cratebay container create` / `cratebay mcp export` for headless workflows --- @@ -52,32 +61,48 @@ Non-goals for routine development: ## Product Direction (CRITICAL — AI Agents MUST follow) -**CrateBay = Local AI Sandbox.** All development decisions must serve this positioning. +**CrateBay = Open-source container management + AI Sandbox.** Two pillars, both important. -### Primary user flow +### Pillar 1: Container Management (like Docker Desktop / OrbStack) ``` -User installs CrateBay → Configures MCP in Claude/Cursor/Windsurf -→ AI says "sandbox_run_code(python, 'print(1+1)')" → CrateBay returns "2" +User opens CrateBay → Manages containers, images, volumes +→ Full lifecycle: create, start, stop, delete, inspect, logs +→ Built-in runtime: no Docker installation required +``` + +### Pillar 2: AI Sandbox (like E2B / Modal, but local) + +``` +Route A (GUI): User opens ChatPage → Chats with AI → AI runs code in sandboxes +Route B (MCP): User configures Claude/Cursor → AI calls sandbox_run_code via MCP ``` ### Priority order for all development work -1. **MCP Server (`cratebay-mcp`)** — the primary product interface. `sandbox_run_code` is the #1 feature. -2. **Built-in Runtime** — zero-config VM that makes the sandbox work without Docker. -3. **CLI (`cratebay-cli`)** — headless sandbox operations for CI/automation. -4. **Desktop App (GUI)** — visual dashboard for sandbox monitoring and settings. **NOT the primary interface.** +1. **Built-in Runtime** — zero-config VM that powers both container management and AI sandbox. +2. **Desktop App (GUI)** — container management UI + AI ChatPage with code execution. +3. **MCP Server (`cratebay-mcp`)** — external AI integration via MCP protocol. +4. **CLI (`cratebay-cli`)** — headless operations for CI/automation. ### What NOT to do -- Do NOT treat the GUI ChatPage as the core product entry. MCP Server is the entry. -- Do NOT spend time on GUI polish before MCP tools are complete. -- Do NOT add features unrelated to code execution (e.g., UI theming, animation, cosmetic changes). -- Do NOT optimize for "container management" — optimize for "AI runs code safely". +- Do NOT remove container/image management features — they are core functionality. +- Do NOT add features unrelated to containers or code execution. +- Do NOT optimize for a single use case — both container management and AI sandbox matter. + +### Navigation structure (4 pages) + +``` +Chat — AI chat with sandbox code execution +Containers — Container lifecycle management +Images — Image management (pull, remove, inspect) +Settings — LLM providers, MCP servers, Runtime, Appearance, About +``` ### Execution plan -See `docs/ROADMAP.md` for the v2.1-Alpha release plan (Phase 1-5). +See `docs/ROADMAP.md` for the release plan. See `docs/progress.md` Quick Resume section for what to do next. --- @@ -348,9 +373,9 @@ When a feature is completed, the responsible agent MUST check: ## Current Development Stage -**Current**: v0.9.0 — MCP Sandbox core complete. Next: ChatPage polish + UI optimization → v1.0.0. +**Current**: v0.9.0 — ChatPage v1.0 complete (sandbox tools + provider config + UI upgrade). Next: merge to master → v1.0.0. -**Completed**: Phase 1 (docs) + Phase 2 (skeleton + core + frontend + runtime + MCP + tests + GUI polish). +**Completed**: Phase 1 (docs) + Phase 2 (core + frontend + runtime + MCP + tests) + ChatPage v1.0 (sandbox Agent Tools, provider config, UI components, MCP→Settings merge, system image protection). See [docs/progress.md](docs/progress.md) for detailed progress and [docs/ROADMAP.md](docs/ROADMAP.md) for the release plan. diff --git a/README.md b/README.md index f5c63f8..eccbeb4 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,17 @@ # CrateBay -Open-source local AI sandbox. Run code safely on your machine — no cloud, no cost. +Open-source, cross-platform container management with built-in AI sandbox. -CrateBay gives any AI agent (Claude, Cursor, Windsurf, your own) a secure sandbox to execute code, install packages, and manage files — all running locally inside a lightweight VM. No Docker installation required. +CrateBay is an alternative to Docker Desktop and OrbStack — fully open-source, works on macOS/Windows/Linux, and has built-in AI code execution capabilities. Manage containers and images through a desktop GUI, or let AI agents run code safely in local sandboxes via MCP protocol. ## Why CrateBay? -AI agents need a safe place to run code. Cloud sandboxes (E2B, Modal) charge per minute and send your code off-machine. CrateBay runs everything locally: - -- **Zero cost** — no cloud bills, no usage limits -- **Private** — code never leaves your machine -- **Fast** — local VM, no network round-trip -- **Works with any AI** — MCP protocol, works with Claude Desktop, Cursor, Windsurf, and any MCP-compatible client +- **Open source** — MIT licensed, free forever. Docker Desktop is proprietary; OrbStack is macOS-only +- **Cross-platform** — macOS, Windows, Linux. No platform lock-in +- **Built-in AI** — Chat with AI that can execute code in sandboxes. No other container tool does this - **No Docker required** — built-in VM runtime (macOS: Virtualization.framework, Linux: KVM, Windows: WSL2) +- **MCP compatible** — connect Claude Desktop, Cursor, Windsurf to run code via MCP protocol +- **Zero cost** — no cloud bills, no usage limits, code never leaves your machine ## How It Works @@ -139,18 +138,19 @@ cratebay sandbox stop ## Compared To -| | CrateBay | E2B | Docker Desktop | -|---|---|---|---| -| Runs locally | Yes | No (cloud) | Yes | -| AI-native (MCP) | Yes | API only | No | -| Cost | Free | $0.01/min | Free / $5+/mo | -| Privacy | Code stays local | Code on cloud | Code stays local | -| No Docker required | Yes (built-in VM) | N/A | Requires Docker | -| Open source | MIT | Partial | No | +| | CrateBay | Docker Desktop | OrbStack | E2B | +|---|---|---|---|---| +| Open source | MIT | No | No | Partial | +| Cross-platform | macOS/Win/Linux | macOS/Win/Linux | macOS only | Cloud | +| Container mgmt | Yes | Yes | Yes | No | +| AI chat + sandbox | Yes | No | No | API only | +| MCP support | Yes | No | No | No | +| Cost | Free | Free / $5+/mo | Free / $8/mo | $0.01/min | +| No Docker needed | Yes (built-in VM) | Is Docker | Requires Docker | N/A | ## Status -v0.9.0 — Core sandbox infrastructure complete, working toward v1.0 release. +v0.9.0 → v1.0.0 — Container management + AI ChatPage with sandbox execution. See [docs/progress.md](docs/progress.md) for detailed development status and [docs/ROADMAP.md](docs/ROADMAP.md) for the release plan. diff --git a/crates/cratebay-cli/src/commands/container.rs b/crates/cratebay-cli/src/commands/container.rs index 02e563e..d9af21d 100644 --- a/crates/cratebay-cli/src/commands/container.rs +++ b/crates/cratebay-cli/src/commands/container.rs @@ -1,5 +1,5 @@ use anyhow::Result; -use bollard::container::{LogOutput, LogsOptions}; +use bollard::container::{InspectContainerOptions, LogOutput, LogsOptions}; use bollard::errors::Error as BollardError; use bollard::Docker; use futures_util::StreamExt; @@ -189,6 +189,67 @@ pub async fn inspect(docker: &Docker, id: &str, format: &OutputFormat) -> Result } } +pub async fn run_compat( + docker: &Docker, + name: String, + image: String, + env: Vec, +) -> Result<()> { + create( + docker, + name, + image, + None, + None, + None, + None, + env, + false, + &OutputFormat::Table, + ) + .await +} + +pub async fn ps_compat(docker: &Docker) -> Result<()> { + list(docker, false, &OutputFormat::Table).await +} + +pub async fn print_env(docker: &Docker, id: &str) -> Result<()> { + let detail = docker + .inspect_container(id, Some(InspectContainerOptions { size: false })) + .await?; + for env_entry in detail + .config + .and_then(|config| config.env) + .unwrap_or_default() + { + println!("{}", env_entry); + } + Ok(()) +} + +pub fn print_login_cmd(id: &str) { + println!("docker exec -it {} /bin/sh", id); +} + +pub async fn start_compat(docker: &Docker, id: &str) -> Result<()> { + container::start(docker, id).await?; + println!("Started container {}", id); + Ok(()) +} + +pub async fn stop_compat(docker: &Docker, id: &str) -> Result<()> { + container::stop(docker, id, None).await?; + println!("Stopped container {}", id); + Ok(()) +} + +pub async fn rm_compat(docker: &Docker, id: &str, _force: bool) -> Result<()> { + container::delete(docker, id, true).await?; + println!("Removed container {}", id); + Ok(()) +} + fn is_missing_image_error(err: &AppError) -> bool { match err { AppError::Docker(BollardError::DockerResponseServerError { diff --git a/crates/cratebay-cli/src/commands/image.rs b/crates/cratebay-cli/src/commands/image.rs index 612ad0b..59e827e 100644 --- a/crates/cratebay-cli/src/commands/image.rs +++ b/crates/cratebay-cli/src/commands/image.rs @@ -1,4 +1,6 @@ use anyhow::Result; +use bollard::container::Config; +use bollard::image::CommitContainerOptions; use bollard::Docker; use cratebay_core::container; @@ -84,3 +86,52 @@ pub async fn delete(docker: &Docker, id: &str) -> Result<()> { println!("Deleted {}", id); Ok(()) } + +pub async fn inspect(docker: &Docker, id: &str, format: &OutputFormat) -> Result<()> { + let detail = container::image_inspect(docker, id).await?; + match format { + OutputFormat::Table => { + println!("ID: {}", detail.id); + println!("RepoTags: {}", detail.repo_tags.join(", ")); + println!("SizeBytes: {}", detail.size_bytes); + println!("Created: {}", detail.created); + Ok(()) + } + _ => print_structured(&detail, format), + } +} + +pub async fn pack_container(docker: &Docker, container_id: &str, image: &str) -> Result<()> { + let (repo, tag) = split_repo_and_tag(image); + let options = CommitContainerOptions { + container: container_id.to_string(), + repo, + tag, + pause: false, + ..Default::default() + }; + docker + .commit_container(options, Config::::default()) + .await?; + println!("Packed container {} into {}", container_id, image); + Ok(()) +} + +fn split_repo_and_tag(reference: &str) -> (String, String) { + let last_slash = reference.rfind('/'); + let last_colon = reference.rfind(':'); + + match last_colon { + Some(colon_index) + if last_slash + .map(|slash_index| colon_index > slash_index) + .unwrap_or(true) => + { + ( + reference[..colon_index].to_string(), + reference[colon_index + 1..].to_string(), + ) + } + _ => (reference.to_string(), "latest".to_string()), + } +} diff --git a/crates/cratebay-cli/src/commands/mod.rs b/crates/cratebay-cli/src/commands/mod.rs index c1e810a..f152d9a 100644 --- a/crates/cratebay-cli/src/commands/mod.rs +++ b/crates/cratebay-cli/src/commands/mod.rs @@ -3,6 +3,7 @@ pub mod image; pub mod mcp; pub mod runtime; pub mod system; +pub mod volume; use clap::ValueEnum; use serde::Serialize; diff --git a/crates/cratebay-cli/src/commands/volume.rs b/crates/cratebay-cli/src/commands/volume.rs new file mode 100644 index 0000000..090cf6c --- /dev/null +++ b/crates/cratebay-cli/src/commands/volume.rs @@ -0,0 +1,61 @@ +use std::collections::HashMap; + +use anyhow::Result; +use bollard::volume::{CreateVolumeOptions, ListVolumesOptions, RemoveVolumeOptions}; +use bollard::Docker; + +use super::{print_structured, OutputFormat}; + +pub async fn create(docker: &Docker, name: &str) -> Result<()> { + let volume = docker + .create_volume(CreateVolumeOptions { + name: name.to_string(), + driver: String::new(), + driver_opts: HashMap::new(), + labels: HashMap::new(), + }) + .await?; + println!("Created volume {}", volume.name); + Ok(()) +} + +pub async fn list(docker: &Docker, format: &OutputFormat) -> Result<()> { + let response = docker + .list_volumes::(None::>) + .await?; + + match format { + OutputFormat::Table => { + println!("{:<32} {:<12} MOUNTPOINT", "NAME", "DRIVER"); + for volume in response.volumes.unwrap_or_default() { + println!( + "{:<32} {:<12} {}", + volume.name, volume.driver, volume.mountpoint, + ); + } + Ok(()) + } + _ => print_structured(&response, format), + } +} + +pub async fn inspect(docker: &Docker, name: &str, format: &OutputFormat) -> Result<()> { + let volume = docker.inspect_volume(name).await?; + match format { + OutputFormat::Table => { + println!("\"Name\": \"{}\"", volume.name); + println!("\"Driver\": \"{}\"", volume.driver); + println!("\"Mountpoint\": \"{}\"", volume.mountpoint); + Ok(()) + } + _ => print_structured(&volume, format), + } +} + +pub async fn remove(docker: &Docker, name: &str, force: bool) -> Result<()> { + docker + .remove_volume(name, Some(RemoveVolumeOptions { force })) + .await?; + println!("Removed volume {}", name); + Ok(()) +} diff --git a/crates/cratebay-cli/src/main.rs b/crates/cratebay-cli/src/main.rs index fe97726..7b1a074 100644 --- a/crates/cratebay-cli/src/main.rs +++ b/crates/cratebay-cli/src/main.rs @@ -37,6 +37,14 @@ enum Commands { #[command(subcommand)] Image(ImageCommands), + /// Docker-compatible convenience commands used by local smoke tests + #[command(subcommand)] + Docker(DockerCommands), + + /// Volume operations + #[command(subcommand)] + Volume(VolumeCommands), + /// Runtime management (start/stop/status) #[command(subcommand)] Runtime(RuntimeCommands), @@ -135,6 +143,46 @@ enum ContainerCommands { Inspect { id: String }, } +#[derive(Subcommand)] +enum DockerCommands { + /// Run a container with Docker-like flags + Run { + /// Pull image before run when missing locally + #[arg(long)] + pull: bool, + /// Container name + #[arg(long)] + name: String, + /// Environment variables (KEY=VALUE). Can be repeated. + #[arg(short = 'e', action = ArgAction::Append)] + env: Vec, + /// Image reference, e.g. nginx:1.27-alpine + image: String, + }, + + /// List running containers + Ps, + + /// Print container environment variables + Env { id: String }, + + /// Print shell login command for a container + LoginCmd { id: String }, + + /// Start a container + Start { id: String }, + + /// Stop a container + Stop { id: String }, + + /// Remove a container + Rm { + id: String, + #[arg(long)] + force: bool, + }, +} + #[derive(Subcommand)] enum ImageCommands { /// List local images @@ -143,6 +191,9 @@ enum ImageCommands { /// Search images from registry Search { query: String, + /// Search backend (`auto` or `dockerhub`) + #[arg(long, default_value = "auto", value_parser = ["auto", "dockerhub"])] + source: String, /// Max results #[arg(long)] limit: Option, @@ -151,10 +202,35 @@ enum ImageCommands { /// Pull an image Pull { image: String }, + /// Inspect a local image + Inspect { id: String }, + + /// Commit a container into a new image tag + PackContainer { container: String, image: String }, + /// Delete a local image Delete { id: String }, } +#[derive(Subcommand)] +enum VolumeCommands { + /// Create a volume + Create { name: String }, + + /// List volumes + List, + + /// Inspect a volume + Inspect { name: String }, + + /// Remove a volume + Remove { + name: String, + #[arg(long)] + force: bool, + }, +} + #[derive(Subcommand)] enum RuntimeCommands { /// Show runtime status @@ -186,6 +262,67 @@ enum SystemCommands { DockerStatus, } +fn current_docker_context_host() -> Option { + let context_output = std::process::Command::new("docker") + .args(["context", "show"]) + .output() + .ok()?; + if !context_output.status.success() { + return None; + } + + let context = String::from_utf8(context_output.stdout).ok()?; + let context = context.trim(); + if context.is_empty() { + return None; + } + + let host_output = std::process::Command::new("docker") + .args([ + "context", + "inspect", + context, + "--format", + "{{.Endpoints.docker.Host}}", + ]) + .output() + .ok()?; + if !host_output.status.success() { + return None; + } + + let host = String::from_utf8(host_output.stdout).ok()?; + let host = host.trim(); + if host.is_empty() { + None + } else { + Some(host.to_string()) + } +} + +async fn try_connect_host_docker() -> Option { + if let Some(host) = current_docker_context_host() { + let previous = std::env::var("DOCKER_HOST").ok(); + std::env::set_var("DOCKER_HOST", &host); + let docker = cratebay_core::docker::connect().await.ok(); + if let Some(previous) = previous { + std::env::set_var("DOCKER_HOST", previous); + } else { + std::env::remove_var("DOCKER_HOST"); + } + if docker.is_some() { + return docker; + } + } + + let docker = bollard::Docker::connect_with_local_defaults().ok()?; + if cratebay_core::docker::is_available(&docker).await { + Some(docker) + } else { + None + } +} + #[tokio::main] async fn main() -> anyhow::Result<()> { tracing_subscriber::fmt::init(); @@ -201,8 +338,10 @@ async fn main() -> anyhow::Result<()> { match cli.command { Commands::Container(cmd) => { - let docker = - cratebay_core::engine::ensure_docker(runtime.as_ref(), Default::default()).await?; + let docker = cratebay_core::engine::ensure_docker(runtime.as_ref(), Default::default()) + .await? + .as_ref() + .clone(); match cmd { ContainerCommands::List { all } => { commands::container::list(&docker, all, &cli.format).await? @@ -259,9 +398,15 @@ async fn main() -> anyhow::Result<()> { } Commands::Image(cmd) => { match cmd { - ImageCommands::Search { query, limit } => { - // Image search should not require starting the runtime. Prefer any - // already-available Docker, otherwise fall back to Docker Hub HTTP API. + ImageCommands::Search { + query, + source: _, + limit, + } => { + // Image search should not require starting the runtime. Both + // `auto` and `dockerhub` prefer any already-available Docker first + // because the engine queries the Docker Hub index and is more + // reliable in CI, then fall back to the Docker Hub HTTP API. if let Some(docker) = cratebay_core::docker::try_connect().await { commands::image::search(&docker, &query, limit, &cli.format).await?; } else { @@ -274,25 +419,112 @@ async fn main() -> anyhow::Result<()> { } } ImageCommands::List => { - let docker = + let docker = if let Some(docker) = try_connect_host_docker().await { + docker + } else { cratebay_core::engine::ensure_docker(runtime.as_ref(), Default::default()) - .await?; + .await? + .as_ref() + .clone() + }; commands::image::list(&docker, &cli.format).await? } ImageCommands::Pull { image } => { - let docker = + let docker = if let Some(docker) = try_connect_host_docker().await { + docker + } else { cratebay_core::engine::ensure_docker(runtime.as_ref(), Default::default()) - .await?; + .await? + .as_ref() + .clone() + }; commands::image::pull(&docker, &image).await? } + ImageCommands::Inspect { id } => { + let docker = if let Some(docker) = try_connect_host_docker().await { + docker + } else { + cratebay_core::engine::ensure_docker(runtime.as_ref(), Default::default()) + .await? + .as_ref() + .clone() + }; + commands::image::inspect(&docker, &id, &cli.format).await? + } + ImageCommands::PackContainer { container, image } => { + let docker = if let Some(docker) = try_connect_host_docker().await { + docker + } else { + cratebay_core::engine::ensure_docker(runtime.as_ref(), Default::default()) + .await? + .as_ref() + .clone() + }; + commands::image::pack_container(&docker, &container, &image).await? + } ImageCommands::Delete { id } => { - let docker = + let docker = if let Some(docker) = try_connect_host_docker().await { + docker + } else { cratebay_core::engine::ensure_docker(runtime.as_ref(), Default::default()) - .await?; + .await? + .as_ref() + .clone() + }; commands::image::delete(&docker, &id).await? } } } + Commands::Docker(cmd) => { + let docker = if let Some(docker) = try_connect_host_docker().await { + docker + } else { + cratebay_core::engine::ensure_docker(runtime.as_ref(), Default::default()) + .await? + .as_ref() + .clone() + }; + match cmd { + DockerCommands::Run { + pull: _, + name, + env, + image, + } => commands::container::run_compat(&docker, name, image, env).await?, + DockerCommands::Ps => commands::container::ps_compat(&docker).await?, + DockerCommands::Env { id } => commands::container::print_env(&docker, &id).await?, + DockerCommands::LoginCmd { id } => commands::container::print_login_cmd(&id), + DockerCommands::Start { id } => { + commands::container::start_compat(&docker, &id).await? + } + DockerCommands::Stop { id } => { + commands::container::stop_compat(&docker, &id).await? + } + DockerCommands::Rm { id, force } => { + commands::container::rm_compat(&docker, &id, force).await? + } + } + } + Commands::Volume(cmd) => { + let docker = if let Some(docker) = try_connect_host_docker().await { + docker + } else { + cratebay_core::engine::ensure_docker(runtime.as_ref(), Default::default()) + .await? + .as_ref() + .clone() + }; + match cmd { + VolumeCommands::Create { name } => commands::volume::create(&docker, &name).await?, + VolumeCommands::List => commands::volume::list(&docker, &cli.format).await?, + VolumeCommands::Inspect { name } => { + commands::volume::inspect(&docker, &name, &cli.format).await? + } + VolumeCommands::Remove { name, force } => { + commands::volume::remove(&docker, &name, force).await? + } + } + } Commands::Runtime(cmd) => match cmd { RuntimeCommands::Status => commands::runtime::status().await?, RuntimeCommands::Start => commands::runtime::start().await?, diff --git a/crates/cratebay-core/src/lib.rs b/crates/cratebay-core/src/lib.rs index b379a12..456a678 100644 --- a/crates/cratebay-core/src/lib.rs +++ b/crates/cratebay-core/src/lib.rs @@ -15,6 +15,7 @@ pub mod mcp; pub mod models; pub mod proxy; pub mod runtime; +pub mod sandbox; pub mod storage; pub mod validation; diff --git a/crates/cratebay-core/src/runtime/common.rs b/crates/cratebay-core/src/runtime/common.rs index f44be64..f6fdb0a 100644 --- a/crates/cratebay-core/src/runtime/common.rs +++ b/crates/cratebay-core/src/runtime/common.rs @@ -255,19 +255,12 @@ pub fn runtime_os_image_id() -> &'static str { } } - #[cfg(target_arch = "aarch64")] - { - "cratebay-runtime-aarch64".to_string() - } - - #[cfg(target_arch = "x86_64")] - { - "cratebay-runtime-x86_64".to_string() - } - - #[cfg(not(any(target_arch = "aarch64", target_arch = "x86_64")))] - { - "cratebay-runtime-aarch64".to_string() + // Runtime detection: supports Universal Binary (aarch64 + x86_64 in single app) + let arch = std::env::consts::ARCH; + match arch { + "aarch64" => "cratebay-runtime-aarch64".to_string(), + "x86_64" => "cratebay-runtime-x86_64".to_string(), + _ => "cratebay-runtime-aarch64".to_string(), // fallback } }) .as_str() diff --git a/crates/cratebay-core/src/runtime/macos.rs b/crates/cratebay-core/src/runtime/macos.rs index 9140195..1b575f2 100644 --- a/crates/cratebay-core/src/runtime/macos.rs +++ b/crates/cratebay-core/src/runtime/macos.rs @@ -313,22 +313,35 @@ fn vz_runner_path() -> PathBuf { } /// Check if a binary has the required macOS virtualization entitlements. +/// +/// Tries both `codesign --entitlements :-` (XML plist, legacy) and +/// `codesign --entitlements -` (human-readable, macOS 15+) to handle +/// all macOS versions. The `:` prefix is deprecated on newer systems +/// and may produce empty output. fn runner_has_virtualization_entitlements(path: &Path) -> bool { - let output = Command::new("codesign") - .args(["-d", "--entitlements", ":-"]) - .arg(path) - .output(); - let Ok(output) = output else { - return false; - }; - if !output.status.success() { - return false; - } + // Try XML plist format first (works on older macOS), then + // human-readable format (required on macOS 15+ / Sequoia+). + for flag in [":-", "-"] { + let output = Command::new("codesign") + .args(["-d", "--entitlements", flag]) + .arg(path) + .output(); + let Ok(output) = output else { + continue; + }; + if !output.status.success() { + continue; + } - let mut combined = String::from_utf8_lossy(&output.stdout).into_owned(); - combined.push_str(&String::from_utf8_lossy(&output.stderr)); - combined.contains("com.apple.security.virtualization") - && combined.contains("com.apple.security.hypervisor") + let mut combined = String::from_utf8_lossy(&output.stdout).into_owned(); + combined.push_str(&String::from_utf8_lossy(&output.stderr)); + if combined.contains("com.apple.security.virtualization") + && combined.contains("com.apple.security.hypervisor") + { + return true; + } + } + false } /// Attempt to sign the VZ runner with required entitlements. diff --git a/crates/cratebay-core/src/sandbox.rs b/crates/cratebay-core/src/sandbox.rs new file mode 100644 index 0000000..806a153 --- /dev/null +++ b/crates/cratebay-core/src/sandbox.rs @@ -0,0 +1,421 @@ +//! Sandbox high-level operations. +//! +//! Provides `run_code` and `install_packages` — the primary functions for +//! AI agents to execute code in isolated containers. Shared by both +//! cratebay-mcp (MCP Server) and cratebay-gui (Tauri commands). + +use std::collections::HashMap; + +use bollard::container::{Config, CreateContainerOptions, RemoveContainerOptions}; +use bollard::Docker; +use serde::Serialize; + +use crate::error::AppError; + +// --------------------------------------------------------------------------- +// Templates +// --------------------------------------------------------------------------- + +/// A sandbox template definition. +#[derive(Debug, Clone, Serialize)] +pub struct SandboxTemplate { + pub id: String, + pub name: String, + pub description: String, + pub image: String, + pub default_command: String, + pub default_cpu_cores: u32, + pub default_memory_mb: u64, + pub tags: Vec, +} + +/// Return the 4 built-in sandbox templates. +pub fn builtin_templates() -> Vec { + vec![ + SandboxTemplate { + id: "node-dev".to_string(), + name: "Node.js Development".to_string(), + description: "Node.js 20 LTS with npm, yarn, and common dev tools".to_string(), + image: "node:20-slim".to_string(), + default_command: "sleep infinity".to_string(), + default_cpu_cores: 2, + default_memory_mb: 2048, + tags: vec![ + "javascript".to_string(), + "typescript".to_string(), + "node".to_string(), + ], + }, + SandboxTemplate { + id: "python-dev".to_string(), + name: "Python Development".to_string(), + description: "Python 3.12 with pip, venv, and common scientific packages".to_string(), + image: "python:3.12-slim-bookworm".to_string(), + default_command: "sleep infinity".to_string(), + default_cpu_cores: 2, + default_memory_mb: 2048, + tags: vec![ + "python".to_string(), + "data-science".to_string(), + "ml".to_string(), + ], + }, + SandboxTemplate { + id: "rust-dev".to_string(), + name: "Rust Development".to_string(), + description: "Rust stable with cargo, rustfmt, clippy".to_string(), + image: "rust:1-slim-bookworm".to_string(), + default_command: "sleep infinity".to_string(), + default_cpu_cores: 4, + default_memory_mb: 4096, + tags: vec!["rust".to_string(), "systems".to_string()], + }, + SandboxTemplate { + id: "ubuntu-base".to_string(), + name: "Ubuntu Base".to_string(), + description: "Clean Ubuntu 24.04 with basic tools".to_string(), + image: "ubuntu:24.04".to_string(), + default_command: "sleep infinity".to_string(), + default_cpu_cores: 1, + default_memory_mb: 1024, + tags: vec!["general".to_string(), "linux".to_string()], + }, + ] +} + +/// Look up a template by ID. +pub fn find_template(id: &str) -> Option { + builtin_templates().into_iter().find(|t| t.id == id) +} + +// --------------------------------------------------------------------------- +// run_code +// --------------------------------------------------------------------------- + +/// Parameters for the run_code operation. +#[derive(Debug)] +pub struct RunCodeParams { + pub language: String, + pub code: String, + pub timeout_seconds: Option, + pub environment: Option>, + pub cleanup: Option, + /// Reuse an existing sandbox instead of creating a new one. + pub sandbox_id: Option, +} + +/// Result of a run_code operation. +#[derive(Debug, Serialize)] +pub struct RunCodeResult { + pub sandbox_id: String, + pub exit_code: i64, + pub stdout: String, + pub stderr: String, + pub duration_ms: u64, + pub language: String, +} + +/// Language-specific configuration. +struct LangConfig { + template_id: &'static str, + file_path: &'static str, + run_cmd: &'static str, +} + +fn lang_config(language: &str) -> Result { + match language { + "python" => Ok(LangConfig { + template_id: "python-dev", + file_path: "/app/run.py", + run_cmd: "python /app/run.py", + }), + "javascript" => Ok(LangConfig { + template_id: "node-dev", + file_path: "/app/run.js", + run_cmd: "node /app/run.js", + }), + "bash" => Ok(LangConfig { + template_id: "ubuntu-base", + file_path: "/app/run.sh", + run_cmd: "bash /app/run.sh", + }), + "rust" => Ok(LangConfig { + template_id: "rust-dev", + file_path: "/app/run.rs", + run_cmd: "rustc /app/run.rs -o /app/run && /app/run", + }), + _ => Err(AppError::Validation(format!( + "Unsupported language '{}'. Supported: python, javascript, bash, rust", + language + ))), + } +} + +/// Create a temporary sandbox container for code execution. +async fn create_temp_sandbox( + docker: &Docker, + template_id: &str, + env: Option>, +) -> Result { + let template = find_template(template_id) + .ok_or_else(|| AppError::Validation(format!("Unknown template '{}'", template_id)))?; + + let sandbox_name = format!( + "cratebay-{}-{}", + template_id, + &uuid::Uuid::new_v4().to_string()[..8] + ); + + let mut labels = HashMap::new(); + labels.insert( + "com.cratebay.sandbox.managed".to_string(), + "true".to_string(), + ); + labels.insert( + "com.cratebay.sandbox.template_id".to_string(), + template_id.to_string(), + ); + labels.insert( + "com.cratebay.sandbox.owner".to_string(), + "gui_run_code".to_string(), + ); + + let host_config = bollard::models::HostConfig { + memory: Some((template.default_memory_mb * 1024 * 1024) as i64), + nano_cpus: Some((template.default_cpu_cores as i64) * 1_000_000_000), + ..Default::default() + }; + + let config = Config { + image: Some(template.image.clone()), + cmd: Some(vec![ + "/bin/sh".to_string(), + "-c".to_string(), + template.default_command.clone(), + ]), + env, + host_config: Some(host_config), + labels: Some(labels), + ..Default::default() + }; + + let options = CreateContainerOptions { + name: sandbox_name.as_str(), + platform: None, + }; + + let response = docker.create_container(Some(options), config).await?; + docker.start_container::(&response.id, None).await?; + + Ok(response.id) +} + +/// Delete a sandbox container. +async fn delete_temp_sandbox(docker: &Docker, sandbox_id: &str) { + let options = Some(RemoveContainerOptions { + force: true, + ..Default::default() + }); + let _ = docker.remove_container(sandbox_id, options).await; +} + +/// Create a sandbox, write code, execute it, and return the result. +/// +/// This is the primary high-level function for AI agents to run code. +pub async fn run_code(docker: &Docker, params: RunCodeParams) -> Result { + let start = std::time::Instant::now(); + let config = lang_config(¶ms.language)?; + let timeout_secs = params.timeout_seconds.unwrap_or(60); + let should_cleanup = params.cleanup.unwrap_or(true); + + let env: Option> = params.environment.map(|map| { + map.into_iter() + .map(|(k, v)| format!("{}={}", k, v)) + .collect() + }); + + // Use existing sandbox or create a new one + let (sandbox_id, created_new) = if let Some(ref id) = params.sandbox_id { + (id.clone(), false) + } else { + let id = create_temp_sandbox(docker, config.template_id, env).await?; + (id, true) + }; + + // Write code to file + if let Err(e) = + crate::container::exec_put_text(docker, &sandbox_id, config.file_path, ¶ms.code).await + { + if should_cleanup && created_new { + delete_temp_sandbox(docker, &sandbox_id).await; + } + return Err(AppError::Runtime(format!( + "Failed to write code file: {}", + e + ))); + } + + // Execute code + let exec_result = crate::container::exec_with_timeout( + docker, + &sandbox_id, + vec![ + "/bin/sh".to_string(), + "-c".to_string(), + config.run_cmd.to_string(), + ], + Some("/app".to_string()), + timeout_secs, + ) + .await; + + let exec_result = match exec_result { + Ok(r) => r, + Err(e) => { + if should_cleanup && created_new { + delete_temp_sandbox(docker, &sandbox_id).await; + } + return Err(AppError::Runtime(format!("Code execution failed: {}", e))); + } + }; + + let duration_ms = start.elapsed().as_millis() as u64; + + // Cleanup if requested + if should_cleanup && created_new { + delete_temp_sandbox(docker, &sandbox_id).await; + } + + Ok(RunCodeResult { + sandbox_id: if should_cleanup && created_new { + sandbox_id.chars().take(12).collect() + } else { + sandbox_id + }, + exit_code: exec_result.exit_code, + stdout: exec_result.stdout, + stderr: exec_result.stderr, + duration_ms, + language: params.language, + }) +} + +// --------------------------------------------------------------------------- +// install_packages +// --------------------------------------------------------------------------- + +/// Parameters for the install operation. +#[derive(Debug)] +pub struct InstallParams { + pub sandbox_id: String, + pub package_manager: String, + pub packages: Vec, +} + +/// Result of an install operation. +#[derive(Debug, Serialize)] +pub struct InstallResult { + pub sandbox_id: String, + pub package_manager: String, + pub exit_code: i64, + pub stdout: String, + pub stderr: String, + pub duration_ms: u64, +} + +/// Install packages in an existing sandbox. +pub async fn install_packages( + docker: &Docker, + params: InstallParams, +) -> Result { + let start = std::time::Instant::now(); + + // Validate package names + for pkg in ¶ms.packages { + if pkg.contains(';') || pkg.contains('&') || pkg.contains('|') || pkg.contains('`') { + return Err(AppError::Validation(format!( + "Invalid package name '{}': contains shell metacharacters", + pkg + ))); + } + } + + let packages_str = params.packages.join(" "); + + let cmd = match params.package_manager.as_str() { + "pip" => format!("pip install --no-cache-dir {}", packages_str), + "npm" => format!("npm install --no-fund --no-audit {}", packages_str), + "cargo" => format!("cargo add {}", packages_str), + "apt" => format!( + "apt-get update -qq && apt-get install -y -qq {}", + packages_str + ), + other => { + return Err(AppError::Validation(format!( + "Unsupported package manager '{}'. Supported: pip, npm, cargo, apt", + other + ))); + } + }; + + let result = crate::container::exec_with_timeout( + docker, + ¶ms.sandbox_id, + vec!["/bin/sh".to_string(), "-c".to_string(), cmd], + None, + 300, + ) + .await?; + + let duration_ms = start.elapsed().as_millis() as u64; + + Ok(InstallResult { + sandbox_id: params.sandbox_id, + package_manager: params.package_manager, + exit_code: result.exit_code, + stdout: result.stdout, + stderr: result.stderr, + duration_ms, + }) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_builtin_templates_count() { + assert_eq!(builtin_templates().len(), 4); + } + + #[test] + fn test_find_template() { + assert!(find_template("python-dev").is_some()); + assert!(find_template("node-dev").is_some()); + assert!(find_template("rust-dev").is_some()); + assert!(find_template("ubuntu-base").is_some()); + assert!(find_template("nonexistent").is_none()); + } + + #[test] + fn test_lang_config() { + assert!(lang_config("python").is_ok()); + assert!(lang_config("javascript").is_ok()); + assert!(lang_config("bash").is_ok()); + assert!(lang_config("rust").is_ok()); + assert!(lang_config("go").is_err()); + } + + #[test] + fn test_lang_config_templates_exist() { + for lang in &["python", "javascript", "bash", "rust"] { + let cfg = lang_config(lang).unwrap(); + assert!( + find_template(cfg.template_id).is_some(), + "Template '{}' for language '{}' not found", + cfg.template_id, + lang + ); + } + } +} diff --git a/crates/cratebay-gui/e2e/navigation.spec.ts b/crates/cratebay-gui/e2e/navigation.spec.ts index 25284fe..3c7ef60 100644 --- a/crates/cratebay-gui/e2e/navigation.spec.ts +++ b/crates/cratebay-gui/e2e/navigation.spec.ts @@ -30,7 +30,7 @@ test.describe("Navigation", () => { // 验证所有导航项存在 await expect(page.locator('[data-testid="nav-chat"]')).toBeVisible(); await expect(page.locator('[data-testid="nav-containers"]')).toBeVisible(); - await expect(page.locator('[data-testid="nav-mcp"]')).toBeVisible(); + await expect(page.locator('[data-testid="nav-images"]')).toBeVisible(); await expect(page.locator('[data-testid="nav-settings"]')).toBeVisible(); }); @@ -61,16 +61,14 @@ test.describe("Navigation", () => { }); }); - test("能够从 MCP 导航到 Settings 页面", async ({ page }) => { + test("能够从 MCP 标签切换回 Settings General 标签", async ({ page }) => { await appLayout.navigateToMcp(); await page.waitForTimeout(500); - // 导航到 Settings - await appLayout.navigateToSettings(); - - // 验证 Settings 页面加载 const generalTab = page.locator('[data-testid="settings-tab-general"]'); - await expect(generalTab).toBeVisible({ timeout: 10000 }); + await generalTab.click(); + + await expect(generalTab).toHaveAttribute("data-state", "active"); }); test("能够从 Settings 返回到 Chat 页面", async ({ page }) => { @@ -109,8 +107,8 @@ test.describe("Navigation", () => { test("快速连续导航不会导致错误", async ({ page }) => { // 执行快速导航序列 await appLayout.navigateToContainers(); + await appLayout.navigateToImages(); await appLayout.navigateToMcp(); - await appLayout.navigateToSettings(); await appLayout.navigateToChat(); // 验证应用仍然可用 @@ -137,12 +135,21 @@ test.describe("Navigation", () => { }).catch(() => {}); }, }, + { + name: "Images", + navigate: () => appLayout.navigateToImages(), + verify: async () => { + await page.waitForTimeout(500); + }, + }, { name: "MCP", navigate: () => appLayout.navigateToMcp(), verify: async () => { - // MCP 页面可能为空 - await page.waitForTimeout(500); + await expect(page.locator('[data-testid="settings-tab-mcp"]')).toHaveAttribute( + "data-state", + "active", + ); }, }, { diff --git a/crates/cratebay-gui/e2e/pages/index.ts b/crates/cratebay-gui/e2e/pages/index.ts index 5518ae0..dcf23c1 100644 --- a/crates/cratebay-gui/e2e/pages/index.ts +++ b/crates/cratebay-gui/e2e/pages/index.ts @@ -50,9 +50,12 @@ export class AppLayoutPage extends BasePage { readonly chatNavButton = '[data-testid="nav-chat"], button:has-text("Chat")'; readonly containersNavButton = '[data-testid="nav-containers"], button:has-text("Containers")'; - readonly mcpNavButton = '[data-testid="nav-mcp"], button:has-text("MCP")'; + readonly imagesNavButton = + '[data-testid="nav-images"], button:has-text("Images")'; readonly settingsNavButton = '[data-testid="nav-settings"], button:has-text("Settings")'; + readonly mcpNavButton = + '[data-testid="settings-tab-mcp"], button:has-text("MCP")'; // 应用标题 readonly appTitle = '[data-testid="app-title"]'; @@ -67,7 +70,13 @@ export class AppLayoutPage extends BasePage { await this.waitForNavigation(); } + async navigateToImages() { + await this.click(this.imagesNavButton); + await this.waitForNavigation(); + } + async navigateToMcp() { + await this.navigateToSettings(); await this.click(this.mcpNavButton); await this.waitForNavigation(); } @@ -93,13 +102,22 @@ export class AppLayoutPage extends BasePage { ); if (containersActive) return "containers"; - const mcpActive = await this.isVisible(this.mcpNavButton + "[aria-current]"); - if (mcpActive) return "mcp"; + const imagesActive = await this.isVisible( + this.imagesNavButton + "[aria-current]" + ); + if (imagesActive) return "images"; const settingsActive = await this.isVisible( this.settingsNavButton + "[aria-current]" ); - if (settingsActive) return "settings"; + if (settingsActive) { + const mcpActive = await this.page + .locator(this.mcpNavButton) + .getAttribute("data-state") + .then((value) => value === "active") + .catch(() => false); + return mcpActive ? "mcp" : "settings"; + } return "unknown"; } diff --git a/crates/cratebay-gui/package-lock.json b/crates/cratebay-gui/package-lock.json index d46ef61..9feacdc 100644 --- a/crates/cratebay-gui/package-lock.json +++ b/crates/cratebay-gui/package-lock.json @@ -1,15 +1,15 @@ { "name": "cratebay-gui", - "version": "2.0.0", + "version": "0.9.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "cratebay-gui", - "version": "2.0.0", + "version": "0.9.0", "dependencies": { - "@mariozechner/pi-agent-core": "^0.61.0", - "@mariozechner/pi-ai": "^0.61.0", + "@mariozechner/pi-agent-core": "^0.63.2", + "@mariozechner/pi-ai": "^0.63.2", "@sinclair/typebox": "^0.34.48", "@tauri-apps/api": "^2.0.0", "class-variance-authority": "^0.7.1", @@ -76,7 +76,7 @@ }, "node_modules/@anthropic-ai/sdk": { "version": "0.73.0", - "resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.73.0.tgz", + "resolved": "https://mirrors.tencent.com/npm/@anthropic-ai/sdk/-/sdk-0.73.0.tgz", "integrity": "sha512-URURVzhxXGJDGUGFunIOtBlSl7KWvZiAAKY/ttTkZAkXT9bTPqdk2eK0b8qqSxXpikh3QKPnPYpiyX98zf5ebw==", "license": "MIT", "dependencies": { @@ -117,7 +117,7 @@ }, "node_modules/@aws-crypto/crc32": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz", + "resolved": "https://mirrors.tencent.com/npm/@aws-crypto/crc32/-/crc32-5.2.0.tgz", "integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==", "license": "Apache-2.0", "dependencies": { @@ -131,7 +131,7 @@ }, "node_modules/@aws-crypto/sha256-browser": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz", + "resolved": "https://mirrors.tencent.com/npm/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz", "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==", "license": "Apache-2.0", "dependencies": { @@ -146,7 +146,7 @@ }, "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/is-array-buffer": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "resolved": "https://mirrors.tencent.com/npm/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", "license": "Apache-2.0", "dependencies": { @@ -158,7 +158,7 @@ }, "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-buffer-from": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "resolved": "https://mirrors.tencent.com/npm/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", "license": "Apache-2.0", "dependencies": { @@ -171,7 +171,7 @@ }, "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-utf8": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "resolved": "https://mirrors.tencent.com/npm/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", "license": "Apache-2.0", "dependencies": { @@ -184,7 +184,7 @@ }, "node_modules/@aws-crypto/sha256-js": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz", + "resolved": "https://mirrors.tencent.com/npm/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz", "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", "license": "Apache-2.0", "dependencies": { @@ -198,7 +198,7 @@ }, "node_modules/@aws-crypto/supports-web-crypto": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz", + "resolved": "https://mirrors.tencent.com/npm/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz", "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==", "license": "Apache-2.0", "dependencies": { @@ -207,7 +207,7 @@ }, "node_modules/@aws-crypto/util": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz", + "resolved": "https://mirrors.tencent.com/npm/@aws-crypto/util/-/util-5.2.0.tgz", "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", "license": "Apache-2.0", "dependencies": { @@ -218,7 +218,7 @@ }, "node_modules/@aws-crypto/util/node_modules/@smithy/is-array-buffer": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "resolved": "https://mirrors.tencent.com/npm/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", "license": "Apache-2.0", "dependencies": { @@ -230,7 +230,7 @@ }, "node_modules/@aws-crypto/util/node_modules/@smithy/util-buffer-from": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "resolved": "https://mirrors.tencent.com/npm/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", "license": "Apache-2.0", "dependencies": { @@ -243,7 +243,7 @@ }, "node_modules/@aws-crypto/util/node_modules/@smithy/util-utf8": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "resolved": "https://mirrors.tencent.com/npm/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", "license": "Apache-2.0", "dependencies": { @@ -255,30 +255,30 @@ } }, "node_modules/@aws-sdk/client-bedrock-runtime": { - "version": "3.1014.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-bedrock-runtime/-/client-bedrock-runtime-3.1014.0.tgz", - "integrity": "sha512-K0TmX1D6dIh4J2QtqUuEXxbyMmtHD+kwHvUg1JwDXaLXC7zJJlR0p1692YBh/eze9tHbuKqP/VWzUy6XX9IPGw==", + "version": "3.1023.0", + "resolved": "https://mirrors.tencent.com/npm/@aws-sdk/client-bedrock-runtime/-/client-bedrock-runtime-3.1023.0.tgz", + "integrity": "sha512-C0He9qhrClUp6JEk3QjE0WScDN1GSZF8eruP0uoh5kXeQEJLxyfFDrR2TIYnHntlRs/sMwhO82Vu7yGGQM2pfQ==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.23", - "@aws-sdk/credential-provider-node": "^3.972.24", - "@aws-sdk/eventstream-handler-node": "^3.972.11", + "@aws-sdk/core": "^3.973.26", + "@aws-sdk/credential-provider-node": "^3.972.29", + "@aws-sdk/eventstream-handler-node": "^3.972.12", "@aws-sdk/middleware-eventstream": "^3.972.8", "@aws-sdk/middleware-host-header": "^3.972.8", "@aws-sdk/middleware-logger": "^3.972.8", - "@aws-sdk/middleware-recursion-detection": "^3.972.8", - "@aws-sdk/middleware-user-agent": "^3.972.24", - "@aws-sdk/middleware-websocket": "^3.972.13", - "@aws-sdk/region-config-resolver": "^3.972.9", - "@aws-sdk/token-providers": "3.1014.0", + "@aws-sdk/middleware-recursion-detection": "^3.972.9", + "@aws-sdk/middleware-user-agent": "^3.972.28", + "@aws-sdk/middleware-websocket": "^3.972.14", + "@aws-sdk/region-config-resolver": "^3.972.10", + "@aws-sdk/token-providers": "3.1023.0", "@aws-sdk/types": "^3.973.6", "@aws-sdk/util-endpoints": "^3.996.5", "@aws-sdk/util-user-agent-browser": "^3.972.8", - "@aws-sdk/util-user-agent-node": "^3.973.10", + "@aws-sdk/util-user-agent-node": "^3.973.14", "@smithy/config-resolver": "^4.4.13", - "@smithy/core": "^3.23.12", + "@smithy/core": "^3.23.13", "@smithy/eventstream-serde-browser": "^4.2.12", "@smithy/eventstream-serde-config-resolver": "^4.3.12", "@smithy/eventstream-serde-node": "^4.2.12", @@ -286,25 +286,25 @@ "@smithy/hash-node": "^4.2.12", "@smithy/invalid-dependency": "^4.2.12", "@smithy/middleware-content-length": "^4.2.12", - "@smithy/middleware-endpoint": "^4.4.27", - "@smithy/middleware-retry": "^4.4.44", - "@smithy/middleware-serde": "^4.2.15", + "@smithy/middleware-endpoint": "^4.4.28", + "@smithy/middleware-retry": "^4.4.46", + "@smithy/middleware-serde": "^4.2.16", "@smithy/middleware-stack": "^4.2.12", "@smithy/node-config-provider": "^4.3.12", - "@smithy/node-http-handler": "^4.5.0", + "@smithy/node-http-handler": "^4.5.1", "@smithy/protocol-http": "^5.3.12", - "@smithy/smithy-client": "^4.12.7", + "@smithy/smithy-client": "^4.12.8", "@smithy/types": "^4.13.1", "@smithy/url-parser": "^4.2.12", "@smithy/util-base64": "^4.3.2", "@smithy/util-body-length-browser": "^4.2.2", "@smithy/util-body-length-node": "^4.2.3", - "@smithy/util-defaults-mode-browser": "^4.3.43", - "@smithy/util-defaults-mode-node": "^4.2.47", + "@smithy/util-defaults-mode-browser": "^4.3.44", + "@smithy/util-defaults-mode-node": "^4.2.48", "@smithy/util-endpoints": "^3.3.3", "@smithy/util-middleware": "^4.2.12", - "@smithy/util-retry": "^4.2.12", - "@smithy/util-stream": "^4.5.20", + "@smithy/util-retry": "^4.2.13", + "@smithy/util-stream": "^4.5.21", "@smithy/util-utf8": "^4.2.2", "tslib": "^2.6.2" }, @@ -313,19 +313,19 @@ } }, "node_modules/@aws-sdk/core": { - "version": "3.973.23", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.973.23.tgz", - "integrity": "sha512-aoJncvD1XvloZ9JLnKqTRL9dBy+Szkryoag9VT+V1TqsuUgIxV9cnBVM/hrDi2vE8bDqLiDR8nirdRcCdtJu0w==", + "version": "3.973.26", + "resolved": "https://mirrors.tencent.com/npm/@aws-sdk/core/-/core-3.973.26.tgz", + "integrity": "sha512-A/E6n2W42ruU+sfWk+mMUOyVXbsSgGrY3MJ9/0Az5qUdG67y8I6HYzzoAa+e/lzxxl1uCYmEL6BTMi9ZiZnplQ==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "^3.973.6", - "@aws-sdk/xml-builder": "^3.972.15", - "@smithy/core": "^3.23.12", + "@aws-sdk/xml-builder": "^3.972.16", + "@smithy/core": "^3.23.13", "@smithy/node-config-provider": "^4.3.12", "@smithy/property-provider": "^4.2.12", "@smithy/protocol-http": "^5.3.12", "@smithy/signature-v4": "^5.3.12", - "@smithy/smithy-client": "^4.12.7", + "@smithy/smithy-client": "^4.12.8", "@smithy/types": "^4.13.1", "@smithy/util-base64": "^4.3.2", "@smithy/util-middleware": "^4.2.12", @@ -337,12 +337,12 @@ } }, "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.972.21", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.21.tgz", - "integrity": "sha512-BkAfKq8Bd4shCtec1usNz//urPJF/SZy14qJyxkSaRJQ/Vv1gVh0VZSTmS7aE6aLMELkFV5wHHrS9ZcdG8Kxsg==", + "version": "3.972.24", + "resolved": "https://mirrors.tencent.com/npm/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.24.tgz", + "integrity": "sha512-FWg8uFmT6vQM7VuzELzwVo5bzExGaKHdubn0StjgrcU5FvuLExUe+k06kn/40uKv59rYzhez8eFNM4yYE/Yb/w==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.23", + "@aws-sdk/core": "^3.973.26", "@aws-sdk/types": "^3.973.6", "@smithy/property-provider": "^4.2.12", "@smithy/types": "^4.13.1", @@ -353,20 +353,20 @@ } }, "node_modules/@aws-sdk/credential-provider-http": { - "version": "3.972.23", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.23.tgz", - "integrity": "sha512-4XZ3+Gu5DY8/n8zQFHBgcKTF7hWQl42G6CY9xfXVo2d25FM/lYkpmuzhYopYoPL1ITWkJ2OSBQfYEu5JRfHOhA==", + "version": "3.972.26", + "resolved": "https://mirrors.tencent.com/npm/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.26.tgz", + "integrity": "sha512-CY4ppZ+qHYqcXqBVi//sdHST1QK3KzOEiLtpLsc9W2k2vfZPKExGaQIsOwcyvjpjUEolotitmd3mUNY56IwDEA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.23", + "@aws-sdk/core": "^3.973.26", "@aws-sdk/types": "^3.973.6", "@smithy/fetch-http-handler": "^5.3.15", - "@smithy/node-http-handler": "^4.5.0", + "@smithy/node-http-handler": "^4.5.1", "@smithy/property-provider": "^4.2.12", "@smithy/protocol-http": "^5.3.12", - "@smithy/smithy-client": "^4.12.7", + "@smithy/smithy-client": "^4.12.8", "@smithy/types": "^4.13.1", - "@smithy/util-stream": "^4.5.20", + "@smithy/util-stream": "^4.5.21", "tslib": "^2.6.2" }, "engines": { @@ -374,19 +374,19 @@ } }, "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.972.23", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.972.23.tgz", - "integrity": "sha512-PZLSmU0JFpNCDFReidBezsgL5ji9jOBry8CnZdw4Jj6d0K2z3Ftnp44NXgADqYx5BLMu/ZHujfeJReaDoV+IwQ==", + "version": "3.972.28", + "resolved": "https://mirrors.tencent.com/npm/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.972.28.tgz", + "integrity": "sha512-wXYvq3+uQcZV7k+bE4yDXCTBdzWTU9x/nMiKBfzInmv6yYK1veMK0AKvRfRBd72nGWYKcL6AxwiPg9z/pYlgpw==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.23", - "@aws-sdk/credential-provider-env": "^3.972.21", - "@aws-sdk/credential-provider-http": "^3.972.23", - "@aws-sdk/credential-provider-login": "^3.972.23", - "@aws-sdk/credential-provider-process": "^3.972.21", - "@aws-sdk/credential-provider-sso": "^3.972.23", - "@aws-sdk/credential-provider-web-identity": "^3.972.23", - "@aws-sdk/nested-clients": "^3.996.13", + "@aws-sdk/core": "^3.973.26", + "@aws-sdk/credential-provider-env": "^3.972.24", + "@aws-sdk/credential-provider-http": "^3.972.26", + "@aws-sdk/credential-provider-login": "^3.972.28", + "@aws-sdk/credential-provider-process": "^3.972.24", + "@aws-sdk/credential-provider-sso": "^3.972.28", + "@aws-sdk/credential-provider-web-identity": "^3.972.28", + "@aws-sdk/nested-clients": "^3.996.18", "@aws-sdk/types": "^3.973.6", "@smithy/credential-provider-imds": "^4.2.12", "@smithy/property-provider": "^4.2.12", @@ -399,13 +399,13 @@ } }, "node_modules/@aws-sdk/credential-provider-login": { - "version": "3.972.23", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.23.tgz", - "integrity": "sha512-OmE/pSkbMM3dCj1HdOnZ5kXnKK+R/Yz+kbBugraBecp0pGAs21eEURfQRz+1N2gzIHLVyGIP1MEjk/uSrFsngg==", + "version": "3.972.28", + "resolved": "https://mirrors.tencent.com/npm/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.28.tgz", + "integrity": "sha512-ZSTfO6jqUTCysbdBPtEX5OUR//3rbD0lN7jO3sQeS2Gjr/Y+DT6SbIJ0oT2cemNw3UzKu97sNONd1CwNMthuZQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.23", - "@aws-sdk/nested-clients": "^3.996.13", + "@aws-sdk/core": "^3.973.26", + "@aws-sdk/nested-clients": "^3.996.18", "@aws-sdk/types": "^3.973.6", "@smithy/property-provider": "^4.2.12", "@smithy/protocol-http": "^5.3.12", @@ -418,17 +418,17 @@ } }, "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.972.24", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.24.tgz", - "integrity": "sha512-9Jwi7aps3AfUicJyF5udYadPypPpCwUZ6BSKr/QjRbVCpRVS1wc+1Q6AEZ/qz8J4JraeRd247pSzyMQSIHVebw==", + "version": "3.972.29", + "resolved": "https://mirrors.tencent.com/npm/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.29.tgz", + "integrity": "sha512-clSzDcvndpFJAggLDnDb36sPdlZYyEs5Zm6zgZjjUhwsJgSWiWKwFIXUVBcbruidNyBdbpOv2tNDL9sX8y3/0g==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/credential-provider-env": "^3.972.21", - "@aws-sdk/credential-provider-http": "^3.972.23", - "@aws-sdk/credential-provider-ini": "^3.972.23", - "@aws-sdk/credential-provider-process": "^3.972.21", - "@aws-sdk/credential-provider-sso": "^3.972.23", - "@aws-sdk/credential-provider-web-identity": "^3.972.23", + "@aws-sdk/credential-provider-env": "^3.972.24", + "@aws-sdk/credential-provider-http": "^3.972.26", + "@aws-sdk/credential-provider-ini": "^3.972.28", + "@aws-sdk/credential-provider-process": "^3.972.24", + "@aws-sdk/credential-provider-sso": "^3.972.28", + "@aws-sdk/credential-provider-web-identity": "^3.972.28", "@aws-sdk/types": "^3.973.6", "@smithy/credential-provider-imds": "^4.2.12", "@smithy/property-provider": "^4.2.12", @@ -441,12 +441,12 @@ } }, "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.972.21", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.21.tgz", - "integrity": "sha512-nRxbeOJ1E1gVA0lNQezuMVndx+ZcuyaW/RB05pUsznN5BxykSlH6KkZ/7Ca/ubJf3i5N3p0gwNO5zgPSCzj+ww==", + "version": "3.972.24", + "resolved": "https://mirrors.tencent.com/npm/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.24.tgz", + "integrity": "sha512-Q2k/XLrFXhEztPHqj4SLCNID3hEPdlhh1CDLBpNnM+1L8fq7P+yON9/9M1IGN/dA5W45v44ylERfXtDAlmMNmw==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.23", + "@aws-sdk/core": "^3.973.26", "@aws-sdk/types": "^3.973.6", "@smithy/property-provider": "^4.2.12", "@smithy/shared-ini-file-loader": "^4.4.7", @@ -458,14 +458,32 @@ } }, "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.972.23", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.972.23.tgz", - "integrity": "sha512-APUccADuYPLL0f2htpM8Z4czabSmHOdo4r41W6lKEZdy++cNJ42Radqy6x4TopENzr3hR6WYMyhiuiqtbf/nAA==", + "version": "3.972.28", + "resolved": "https://mirrors.tencent.com/npm/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.972.28.tgz", + "integrity": "sha512-IoUlmKMLEITFn1SiCTjPfR6KrE799FBo5baWyk/5Ppar2yXZoUdaRqZzJzK6TcJxx450M8m8DbpddRVYlp5R/A==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.23", - "@aws-sdk/nested-clients": "^3.996.13", - "@aws-sdk/token-providers": "3.1014.0", + "@aws-sdk/core": "^3.973.26", + "@aws-sdk/nested-clients": "^3.996.18", + "@aws-sdk/token-providers": "3.1021.0", + "@aws-sdk/types": "^3.973.6", + "@smithy/property-provider": "^4.2.12", + "@smithy/shared-ini-file-loader": "^4.4.7", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers": { + "version": "3.1021.0", + "resolved": "https://mirrors.tencent.com/npm/@aws-sdk/token-providers/-/token-providers-3.1021.0.tgz", + "integrity": "sha512-TKY6h9spUk3OLs5v1oAgW9mAeBE3LAGNBwJokLy96wwmd4W2v/tYlXseProyed9ValDj2u1jK/4Rg1T+1NXyJA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.973.26", + "@aws-sdk/nested-clients": "^3.996.18", "@aws-sdk/types": "^3.973.6", "@smithy/property-provider": "^4.2.12", "@smithy/shared-ini-file-loader": "^4.4.7", @@ -477,13 +495,13 @@ } }, "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.972.23", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.23.tgz", - "integrity": "sha512-H5JNqtIwOu/feInmMMWcK0dL5r897ReEn7n2m16Dd0DPD9gA2Hg8Cq4UDzZ/9OzaLh/uqBM6seixz0U6Fi2Eag==", + "version": "3.972.28", + "resolved": "https://mirrors.tencent.com/npm/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.28.tgz", + "integrity": "sha512-d+6h0SD8GGERzKe27v5rOzNGKOl0D+l0bWJdqrxH8WSQzHzjsQFIAPgIeOTUwBHVsKKwtSxc91K/SWax6XgswQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.23", - "@aws-sdk/nested-clients": "^3.996.13", + "@aws-sdk/core": "^3.973.26", + "@aws-sdk/nested-clients": "^3.996.18", "@aws-sdk/types": "^3.973.6", "@smithy/property-provider": "^4.2.12", "@smithy/shared-ini-file-loader": "^4.4.7", @@ -495,9 +513,9 @@ } }, "node_modules/@aws-sdk/eventstream-handler-node": { - "version": "3.972.11", - "resolved": "https://registry.npmjs.org/@aws-sdk/eventstream-handler-node/-/eventstream-handler-node-3.972.11.tgz", - "integrity": "sha512-2IrLrOruRr1NhTK0vguBL1gCWv1pu4bf4KaqpsA+/vCJpFEbvXFawn71GvCzk1wyjnDUsemtKypqoKGv4cSGbA==", + "version": "3.972.12", + "resolved": "https://mirrors.tencent.com/npm/@aws-sdk/eventstream-handler-node/-/eventstream-handler-node-3.972.12.tgz", + "integrity": "sha512-ruyc/MNR6e+cUrGCth7fLQ12RXBZDy/bV06tgqB9Z5n/0SN/C0m6bsQEV8FF9zPI6VSAOaRd0rNgmpYVnGawrQ==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "^3.973.6", @@ -511,7 +529,7 @@ }, "node_modules/@aws-sdk/middleware-eventstream": { "version": "3.972.8", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-eventstream/-/middleware-eventstream-3.972.8.tgz", + "resolved": "https://mirrors.tencent.com/npm/@aws-sdk/middleware-eventstream/-/middleware-eventstream-3.972.8.tgz", "integrity": "sha512-r+oP+tbCxgqXVC3pu3MUVePgSY0ILMjA+aEwOosS77m3/DRbtvHrHwqvMcw+cjANMeGzJ+i0ar+n77KXpRA8RQ==", "license": "Apache-2.0", "dependencies": { @@ -526,7 +544,7 @@ }, "node_modules/@aws-sdk/middleware-host-header": { "version": "3.972.8", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.972.8.tgz", + "resolved": "https://mirrors.tencent.com/npm/@aws-sdk/middleware-host-header/-/middleware-host-header-3.972.8.tgz", "integrity": "sha512-wAr2REfKsqoKQ+OkNqvOShnBoh+nkPurDKW7uAeVSu6kUECnWlSJiPvnoqxGlfousEY/v9LfS9sNc46hjSYDIQ==", "license": "Apache-2.0", "dependencies": { @@ -541,7 +559,7 @@ }, "node_modules/@aws-sdk/middleware-logger": { "version": "3.972.8", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.972.8.tgz", + "resolved": "https://mirrors.tencent.com/npm/@aws-sdk/middleware-logger/-/middleware-logger-3.972.8.tgz", "integrity": "sha512-CWl5UCM57WUFaFi5kB7IBY1UmOeLvNZAZ2/OZ5l20ldiJ3TiIz1pC65gYj8X0BCPWkeR1E32mpsCk1L1I4n+lA==", "license": "Apache-2.0", "dependencies": { @@ -554,9 +572,9 @@ } }, "node_modules/@aws-sdk/middleware-recursion-detection": { - "version": "3.972.8", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.972.8.tgz", - "integrity": "sha512-BnnvYs2ZEpdlmZ2PNlV2ZyQ8j8AEkMTjN79y/YA475ER1ByFYrkVR85qmhni8oeTaJcDqbx364wDpitDAA/wCA==", + "version": "3.972.9", + "resolved": "https://mirrors.tencent.com/npm/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.972.9.tgz", + "integrity": "sha512-/Wt5+CT8dpTFQxEJ9iGy/UGrXr7p2wlIOEHvIr/YcHYByzoLjrqkYqXdJjd9UIgWjv7eqV2HnFJen93UTuwfTQ==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "^3.973.6", @@ -570,18 +588,18 @@ } }, "node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.972.24", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.972.24.tgz", - "integrity": "sha512-dLTWy6IfAMhNiSEvMr07g/qZ54be6pLqlxVblbF6AzafmmGAzMMj8qMoY9B4+YgT+gY9IcuxZslNh03L6PyMCQ==", + "version": "3.972.28", + "resolved": "https://mirrors.tencent.com/npm/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.972.28.tgz", + "integrity": "sha512-cfWZFlVh7Va9lRay4PN2A9ARFzaBYcA097InT5M2CdRS05ECF5yaz86jET8Wsl2WcyKYEvVr/QNmKtYtafUHtQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.23", + "@aws-sdk/core": "^3.973.26", "@aws-sdk/types": "^3.973.6", "@aws-sdk/util-endpoints": "^3.996.5", - "@smithy/core": "^3.23.12", + "@smithy/core": "^3.23.13", "@smithy/protocol-http": "^5.3.12", "@smithy/types": "^4.13.1", - "@smithy/util-retry": "^4.2.12", + "@smithy/util-retry": "^4.2.13", "tslib": "^2.6.2" }, "engines": { @@ -589,9 +607,9 @@ } }, "node_modules/@aws-sdk/middleware-websocket": { - "version": "3.972.13", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-websocket/-/middleware-websocket-3.972.13.tgz", - "integrity": "sha512-Gp6EWIqHX5wmsOR5ZxWyyzEU8P0xBdSxkm6VHEwXwBqScKZ7QWRoj6ZmHpr+S44EYb5tuzGya4ottsogSu2W3A==", + "version": "3.972.14", + "resolved": "https://mirrors.tencent.com/npm/@aws-sdk/middleware-websocket/-/middleware-websocket-3.972.14.tgz", + "integrity": "sha512-qnfDlIHjm6DrTYNvWOUbnZdVKgtoKbO/Qzj+C0Wp5Y7VUrsvBRQtGKxD+hc+mRTS4N0kBJ6iZ3+zxm4N1OSyjg==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "^3.973.6", @@ -612,47 +630,47 @@ } }, "node_modules/@aws-sdk/nested-clients": { - "version": "3.996.13", - "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.996.13.tgz", - "integrity": "sha512-ptZ1HF4yYHNJX8cgFF+8NdYO69XJKZn7ft0/ynV3c0hCbN+89fAbrLS+fqniU2tW8o9Kfqhj8FUh+IPXb2Qsuw==", + "version": "3.996.18", + "resolved": "https://mirrors.tencent.com/npm/@aws-sdk/nested-clients/-/nested-clients-3.996.18.tgz", + "integrity": "sha512-c7ZSIXrESxHKx2Mcopgd8AlzZgoXMr20fkx5ViPWPOLBvmyhw9VwJx/Govg8Ef/IhEon5R9l53Z8fdYSEmp6VA==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.23", + "@aws-sdk/core": "^3.973.26", "@aws-sdk/middleware-host-header": "^3.972.8", "@aws-sdk/middleware-logger": "^3.972.8", - "@aws-sdk/middleware-recursion-detection": "^3.972.8", - "@aws-sdk/middleware-user-agent": "^3.972.24", - "@aws-sdk/region-config-resolver": "^3.972.9", + "@aws-sdk/middleware-recursion-detection": "^3.972.9", + "@aws-sdk/middleware-user-agent": "^3.972.28", + "@aws-sdk/region-config-resolver": "^3.972.10", "@aws-sdk/types": "^3.973.6", "@aws-sdk/util-endpoints": "^3.996.5", "@aws-sdk/util-user-agent-browser": "^3.972.8", - "@aws-sdk/util-user-agent-node": "^3.973.10", + "@aws-sdk/util-user-agent-node": "^3.973.14", "@smithy/config-resolver": "^4.4.13", - "@smithy/core": "^3.23.12", + "@smithy/core": "^3.23.13", "@smithy/fetch-http-handler": "^5.3.15", "@smithy/hash-node": "^4.2.12", "@smithy/invalid-dependency": "^4.2.12", "@smithy/middleware-content-length": "^4.2.12", - "@smithy/middleware-endpoint": "^4.4.27", - "@smithy/middleware-retry": "^4.4.44", - "@smithy/middleware-serde": "^4.2.15", + "@smithy/middleware-endpoint": "^4.4.28", + "@smithy/middleware-retry": "^4.4.46", + "@smithy/middleware-serde": "^4.2.16", "@smithy/middleware-stack": "^4.2.12", "@smithy/node-config-provider": "^4.3.12", - "@smithy/node-http-handler": "^4.5.0", + "@smithy/node-http-handler": "^4.5.1", "@smithy/protocol-http": "^5.3.12", - "@smithy/smithy-client": "^4.12.7", + "@smithy/smithy-client": "^4.12.8", "@smithy/types": "^4.13.1", "@smithy/url-parser": "^4.2.12", "@smithy/util-base64": "^4.3.2", "@smithy/util-body-length-browser": "^4.2.2", "@smithy/util-body-length-node": "^4.2.3", - "@smithy/util-defaults-mode-browser": "^4.3.43", - "@smithy/util-defaults-mode-node": "^4.2.47", + "@smithy/util-defaults-mode-browser": "^4.3.44", + "@smithy/util-defaults-mode-node": "^4.2.48", "@smithy/util-endpoints": "^3.3.3", "@smithy/util-middleware": "^4.2.12", - "@smithy/util-retry": "^4.2.12", + "@smithy/util-retry": "^4.2.13", "@smithy/util-utf8": "^4.2.2", "tslib": "^2.6.2" }, @@ -661,9 +679,9 @@ } }, "node_modules/@aws-sdk/region-config-resolver": { - "version": "3.972.9", - "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.972.9.tgz", - "integrity": "sha512-eQ+dFU05ZRC/lC2XpYlYSPlXtX3VT8sn5toxN2Fv7EXlMoA2p9V7vUBKqHunfD4TRLpxUq8Y8Ol/nCqiv327Ng==", + "version": "3.972.10", + "resolved": "https://mirrors.tencent.com/npm/@aws-sdk/region-config-resolver/-/region-config-resolver-3.972.10.tgz", + "integrity": "sha512-1dq9ToC6e070QvnVhhbAs3bb5r6cQ10gTVc6cyRV5uvQe7P138TV2uG2i6+Yok4bAkVAcx5AqkTEBUvWEtBlsQ==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "^3.973.6", @@ -677,13 +695,13 @@ } }, "node_modules/@aws-sdk/token-providers": { - "version": "3.1014.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.1014.0.tgz", - "integrity": "sha512-gHTHNUoaOGNrSWkl32A7wFsU78jlNTlqMccLu0byUk5CysYYXaxNMIonIVr4YcykC7vgtDS5ABuz83giy6fzJA==", + "version": "3.1023.0", + "resolved": "https://mirrors.tencent.com/npm/@aws-sdk/token-providers/-/token-providers-3.1023.0.tgz", + "integrity": "sha512-g/t814ec7g+MbazONIdQzb0c8FalVnSKCLc665GLG4QdrviKXHzag7HQmf5wBhCDsUDNAIi77fLeElaZSkylTA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.23", - "@aws-sdk/nested-clients": "^3.996.13", + "@aws-sdk/core": "^3.973.26", + "@aws-sdk/nested-clients": "^3.996.18", "@aws-sdk/types": "^3.973.6", "@smithy/property-provider": "^4.2.12", "@smithy/shared-ini-file-loader": "^4.4.7", @@ -696,7 +714,7 @@ }, "node_modules/@aws-sdk/types": { "version": "3.973.6", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.973.6.tgz", + "resolved": "https://mirrors.tencent.com/npm/@aws-sdk/types/-/types-3.973.6.tgz", "integrity": "sha512-Atfcy4E++beKtwJHiDln2Nby8W/mam64opFPTiHEqgsthqeydFS1pY+OUlN1ouNOmf8ArPU/6cDS65anOP3KQw==", "license": "Apache-2.0", "dependencies": { @@ -709,7 +727,7 @@ }, "node_modules/@aws-sdk/util-endpoints": { "version": "3.996.5", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.996.5.tgz", + "resolved": "https://mirrors.tencent.com/npm/@aws-sdk/util-endpoints/-/util-endpoints-3.996.5.tgz", "integrity": "sha512-Uh93L5sXFNbyR5sEPMzUU8tJ++Ku97EY4udmC01nB8Zu+xfBPwpIwJ6F7snqQeq8h2pf+8SGN5/NoytfKgYPIw==", "license": "Apache-2.0", "dependencies": { @@ -725,7 +743,7 @@ }, "node_modules/@aws-sdk/util-format-url": { "version": "3.972.8", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-format-url/-/util-format-url-3.972.8.tgz", + "resolved": "https://mirrors.tencent.com/npm/@aws-sdk/util-format-url/-/util-format-url-3.972.8.tgz", "integrity": "sha512-J6DS9oocrgxM8xlUTTmQOuwRF6rnAGEujAN9SAzllcrQmwn5iJ58ogxy3SEhD0Q7JZvlA5jvIXBkpQRqEqlE9A==", "license": "Apache-2.0", "dependencies": { @@ -740,7 +758,7 @@ }, "node_modules/@aws-sdk/util-locate-window": { "version": "3.965.5", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.965.5.tgz", + "resolved": "https://mirrors.tencent.com/npm/@aws-sdk/util-locate-window/-/util-locate-window-3.965.5.tgz", "integrity": "sha512-WhlJNNINQB+9qtLtZJcpQdgZw3SCDCpXdUJP7cToGwHbCWCnRckGlc6Bx/OhWwIYFNAn+FIydY8SZ0QmVu3xTQ==", "license": "Apache-2.0", "dependencies": { @@ -752,7 +770,7 @@ }, "node_modules/@aws-sdk/util-user-agent-browser": { "version": "3.972.8", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.972.8.tgz", + "resolved": "https://mirrors.tencent.com/npm/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.972.8.tgz", "integrity": "sha512-B3KGXJviV2u6Cdw2SDY2aDhoJkVfY/Q/Trwk2CMSkikE1Oi6gRzxhvhIfiRpHfmIsAhV4EA54TVEX8K6CbHbkA==", "license": "Apache-2.0", "dependencies": { @@ -763,12 +781,12 @@ } }, "node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.973.10", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.973.10.tgz", - "integrity": "sha512-E99zeTscCc+pTMfsvnfi6foPpKmdD1cZfOC7/P8UUrjsoQdg9VEWPRD+xdFduKnfPXwcvby58AlO9jwwF6U96g==", + "version": "3.973.14", + "resolved": "https://mirrors.tencent.com/npm/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.973.14.tgz", + "integrity": "sha512-vNSB/DYaPOyujVZBg/zUznH9QC142MaTHVmaFlF7uzzfg3CgT9f/l4C0Yi+vU/tbBhxVcXVB90Oohk5+o+ZbWw==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/middleware-user-agent": "^3.972.24", + "@aws-sdk/middleware-user-agent": "^3.972.28", "@aws-sdk/types": "^3.973.6", "@smithy/node-config-provider": "^4.3.12", "@smithy/types": "^4.13.1", @@ -788,9 +806,9 @@ } }, "node_modules/@aws-sdk/xml-builder": { - "version": "3.972.15", - "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.972.15.tgz", - "integrity": "sha512-PxMRlCFNiQnke9YR29vjFQwz4jq+6Q04rOVFeTDR2K7Qpv9h9FOWOxG+zJjageimYbWqE3bTuLjmryWHAWbvaA==", + "version": "3.972.16", + "resolved": "https://mirrors.tencent.com/npm/@aws-sdk/xml-builder/-/xml-builder-3.972.16.tgz", + "integrity": "sha512-iu2pyvaqmeatIJLURLqx9D+4jKAdTH20ntzB6BFwjyN7V960r4jK32mx0Zf7YbtOYAbmbtQfDNuL60ONinyw7A==", "license": "Apache-2.0", "dependencies": { "@smithy/types": "^4.13.1", @@ -803,7 +821,7 @@ }, "node_modules/@aws/lambda-invoke-store": { "version": "0.2.4", - "resolved": "https://registry.npmjs.org/@aws/lambda-invoke-store/-/lambda-invoke-store-0.2.4.tgz", + "resolved": "https://mirrors.tencent.com/npm/@aws/lambda-invoke-store/-/lambda-invoke-store-0.2.4.tgz", "integrity": "sha512-iY8yvjE0y651BixKNPgmv1WrQc+GZ142sb0z4gYnChDDY2YqI4P/jsSopBWrKfAt7LOJAkOXt7rC/hms+WclQQ==", "license": "Apache-2.0", "engines": { @@ -1752,9 +1770,9 @@ "license": "MIT" }, "node_modules/@google/genai": { - "version": "1.46.0", - "resolved": "https://registry.npmjs.org/@google/genai/-/genai-1.46.0.tgz", - "integrity": "sha512-ewPMN5JkKfgU5/kdco9ZhXBHDPhVqZpMQqIFQhwsHLf8kyZfx1cNpw1pHo1eV6PGEW7EhIBFi3aYZraFndAXqg==", + "version": "1.48.0", + "resolved": "https://mirrors.tencent.com/npm/@google/genai/-/genai-1.48.0.tgz", + "integrity": "sha512-plonYK4ML2PrxsRD9SeqmFt76eREWkQdPCglOA6aYDzL1AAbE+7PUnT54SvpWGfws13L0AZEqGSpL7+1IPnTxQ==", "license": "Apache-2.0", "dependencies": { "google-auth-library": "^10.3.0", @@ -1870,21 +1888,21 @@ } }, "node_modules/@mariozechner/pi-agent-core": { - "version": "0.61.1", - "resolved": "https://registry.npmjs.org/@mariozechner/pi-agent-core/-/pi-agent-core-0.61.1.tgz", - "integrity": "sha512-ELZsyx6INGBYXPAbYTAiRWtkmnwAlcXOOVPY434BE605TBdpzMrXF5gNckKdEyCCWYJiLzSKpHaAzWwB7Vx2nA==", + "version": "0.63.2", + "resolved": "https://mirrors.tencent.com/npm/@mariozechner/pi-agent-core/-/pi-agent-core-0.63.2.tgz", + "integrity": "sha512-9QTS7ylcmoAIWXk0EVpwCCop3fK4NIqTAN8TiRuXvuKYx+wYmUJc+P5+RfehIZhwsy7g9O/rktz0c1YEUBFB0g==", "license": "MIT", "dependencies": { - "@mariozechner/pi-ai": "^0.61.1" + "@mariozechner/pi-ai": "^0.63.2" }, "engines": { "node": ">=20.0.0" } }, "node_modules/@mariozechner/pi-ai": { - "version": "0.61.1", - "resolved": "https://registry.npmjs.org/@mariozechner/pi-ai/-/pi-ai-0.61.1.tgz", - "integrity": "sha512-BOk8xwluIgauX93qgC9qyrWteKKnk6pNDM8szE1m/EJKMhcJ/jIJpgAUQgj4yXiwSMtcZm30h2Po97gqqXTIIg==", + "version": "0.63.2", + "resolved": "https://mirrors.tencent.com/npm/@mariozechner/pi-ai/-/pi-ai-0.63.2.tgz", + "integrity": "sha512-EJNPyzeZeifTJmkD8PPYQmSO4P4h8kFCrhUqU4NvFUkug+GNYr954KlxhYnXH0f77MpdIEpf/O5zdDrYJQyafA==", "license": "MIT", "dependencies": { "@anthropic-ai/sdk": "^0.73.0", @@ -1919,7 +1937,7 @@ }, "node_modules/@mistralai/mistralai": { "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@mistralai/mistralai/-/mistralai-1.14.1.tgz", + "resolved": "https://mirrors.tencent.com/npm/@mistralai/mistralai/-/mistralai-1.14.1.tgz", "integrity": "sha512-IiLmmZFCCTReQgPAT33r7KQ1nYo5JPdvGkrkZqA8qQ2qB1GHgs5LoP5K2ICyrjnpw2n8oSxMM/VP+liiKcGNlQ==", "dependencies": { "ws": "^8.18.0", @@ -1956,31 +1974,30 @@ }, "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" + "resolved": "https://mirrors.tencent.com/npm/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" }, "node_modules/@protobufjs/base64": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "resolved": "https://mirrors.tencent.com/npm/@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", + "resolved": "https://mirrors.tencent.com/npm/@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", + "resolved": "https://mirrors.tencent.com/npm/@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", + "resolved": "https://mirrors.tencent.com/npm/@protobufjs/fetch/-/fetch-1.1.0.tgz", "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", "license": "BSD-3-Clause", "dependencies": { @@ -1990,31 +2007,30 @@ }, "node_modules/@protobufjs/float": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "resolved": "https://mirrors.tencent.com/npm/@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" + "resolved": "https://mirrors.tencent.com/npm/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" }, "node_modules/@protobufjs/path": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "resolved": "https://mirrors.tencent.com/npm/@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", + "resolved": "https://mirrors.tencent.com/npm/@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", + "resolved": "https://mirrors.tencent.com/npm/@protobufjs/utf8/-/utf8-1.1.0.tgz", "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", "license": "BSD-3-Clause" }, @@ -3879,22 +3895,9 @@ "integrity": "sha512-kKJTNuK3AQOrgjjotVxMrCn1sUJwM76wMszfq1kdU4uYVJjvEWuFQ6HgvLt4Xz3fSmZlTOxJ/Ie13KnIcWQXFA==", "license": "MIT" }, - "node_modules/@smithy/abort-controller": { - "version": "4.2.12", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.2.12.tgz", - "integrity": "sha512-xolrFw6b+2iYGl6EcOL7IJY71vvyZ0DJ3mcKtpykqPe2uscwtzDZJa1uVQXyP7w9Dd+kGwYnPbMsJrGISKiY/Q==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.13.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@smithy/config-resolver": { "version": "4.4.13", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.4.13.tgz", + "resolved": "https://mirrors.tencent.com/npm/@smithy/config-resolver/-/config-resolver-4.4.13.tgz", "integrity": "sha512-iIzMC5NmOUP6WL6o8iPBjFhUhBZ9pPjpUpQYWMUFQqKyXXzOftbfK8zcQCz/jFV1Psmf05BK5ypx4K2r4Tnwdg==", "license": "Apache-2.0", "dependencies": { @@ -3910,9 +3913,9 @@ } }, "node_modules/@smithy/core": { - "version": "3.23.12", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.23.12.tgz", - "integrity": "sha512-o9VycsYNtgC+Dy3I0yrwCqv9CWicDnke0L7EVOrZtJpjb2t0EjaEofmMrYc0T1Kn3yk32zm6cspxF9u9Bj7e5w==", + "version": "3.23.13", + "resolved": "https://mirrors.tencent.com/npm/@smithy/core/-/core-3.23.13.tgz", + "integrity": "sha512-J+2TT9D6oGsUVXVEMvz8h2EmdVnkBiy2auCie4aSJMvKlzUtO5hqjEzXhoCUkIMo7gAYjbQcN0g/MMSXEhDs1Q==", "license": "Apache-2.0", "dependencies": { "@smithy/protocol-http": "^5.3.12", @@ -3921,7 +3924,7 @@ "@smithy/util-base64": "^4.3.2", "@smithy/util-body-length-browser": "^4.2.2", "@smithy/util-middleware": "^4.2.12", - "@smithy/util-stream": "^4.5.20", + "@smithy/util-stream": "^4.5.21", "@smithy/util-utf8": "^4.2.2", "@smithy/uuid": "^1.1.2", "tslib": "^2.6.2" @@ -3932,7 +3935,7 @@ }, "node_modules/@smithy/credential-provider-imds": { "version": "4.2.12", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.2.12.tgz", + "resolved": "https://mirrors.tencent.com/npm/@smithy/credential-provider-imds/-/credential-provider-imds-4.2.12.tgz", "integrity": "sha512-cr2lR792vNZcYMriSIj+Um3x9KWrjcu98kn234xA6reOAFMmbRpQMOv8KPgEmLLtx3eldU6c5wALKFqNOhugmg==", "license": "Apache-2.0", "dependencies": { @@ -3948,7 +3951,7 @@ }, "node_modules/@smithy/eventstream-codec": { "version": "4.2.12", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-4.2.12.tgz", + "resolved": "https://mirrors.tencent.com/npm/@smithy/eventstream-codec/-/eventstream-codec-4.2.12.tgz", "integrity": "sha512-FE3bZdEl62ojmy8x4FHqxq2+BuOHlcxiH5vaZ6aqHJr3AIZzwF5jfx8dEiU/X0a8RboyNDjmXjlbr8AdEyLgiA==", "license": "Apache-2.0", "dependencies": { @@ -3963,7 +3966,7 @@ }, "node_modules/@smithy/eventstream-serde-browser": { "version": "4.2.12", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-4.2.12.tgz", + "resolved": "https://mirrors.tencent.com/npm/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-4.2.12.tgz", "integrity": "sha512-XUSuMxlTxV5pp4VpqZf6Sa3vT/Q75FVkLSpSSE3KkWBvAQWeuWt1msTv8fJfgA4/jcJhrbrbMzN1AC/hvPmm5A==", "license": "Apache-2.0", "dependencies": { @@ -3977,7 +3980,7 @@ }, "node_modules/@smithy/eventstream-serde-config-resolver": { "version": "4.3.12", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-4.3.12.tgz", + "resolved": "https://mirrors.tencent.com/npm/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-4.3.12.tgz", "integrity": "sha512-7epsAZ3QvfHkngz6RXQYseyZYHlmWXSTPOfPmXkiS+zA6TBNo1awUaMFL9vxyXlGdoELmCZyZe1nQE+imbmV+Q==", "license": "Apache-2.0", "dependencies": { @@ -3990,7 +3993,7 @@ }, "node_modules/@smithy/eventstream-serde-node": { "version": "4.2.12", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-4.2.12.tgz", + "resolved": "https://mirrors.tencent.com/npm/@smithy/eventstream-serde-node/-/eventstream-serde-node-4.2.12.tgz", "integrity": "sha512-D1pFuExo31854eAvg89KMn9Oab/wEeJR6Buy32B49A9Ogdtx5fwZPqBHUlDzaCDpycTFk2+fSQgX689Qsk7UGA==", "license": "Apache-2.0", "dependencies": { @@ -4004,7 +4007,7 @@ }, "node_modules/@smithy/eventstream-serde-universal": { "version": "4.2.12", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-4.2.12.tgz", + "resolved": "https://mirrors.tencent.com/npm/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-4.2.12.tgz", "integrity": "sha512-+yNuTiyBACxOJUTvbsNsSOfH9G9oKbaJE1lNL3YHpGcuucl6rPZMi3nrpehpVOVR2E07YqFFmtwpImtpzlouHQ==", "license": "Apache-2.0", "dependencies": { @@ -4018,7 +4021,7 @@ }, "node_modules/@smithy/fetch-http-handler": { "version": "5.3.15", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.3.15.tgz", + "resolved": "https://mirrors.tencent.com/npm/@smithy/fetch-http-handler/-/fetch-http-handler-5.3.15.tgz", "integrity": "sha512-T4jFU5N/yiIfrtrsb9uOQn7RdELdM/7HbyLNr6uO/mpkj1ctiVs7CihVr51w4LyQlXWDpXFn4BElf1WmQvZu/A==", "license": "Apache-2.0", "dependencies": { @@ -4034,7 +4037,7 @@ }, "node_modules/@smithy/hash-node": { "version": "4.2.12", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.2.12.tgz", + "resolved": "https://mirrors.tencent.com/npm/@smithy/hash-node/-/hash-node-4.2.12.tgz", "integrity": "sha512-QhBYbGrbxTkZ43QoTPrK72DoYviDeg6YKDrHTMJbbC+A0sml3kSjzFtXP7BtbyJnXojLfTQldGdUR0RGD8dA3w==", "license": "Apache-2.0", "dependencies": { @@ -4049,7 +4052,7 @@ }, "node_modules/@smithy/invalid-dependency": { "version": "4.2.12", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.2.12.tgz", + "resolved": "https://mirrors.tencent.com/npm/@smithy/invalid-dependency/-/invalid-dependency-4.2.12.tgz", "integrity": "sha512-/4F1zb7Z8LOu1PalTdESFHR0RbPwHd3FcaG1sI3UEIriQTWakysgJr65lc1jj6QY5ye7aFsisajotH6UhWfm/g==", "license": "Apache-2.0", "dependencies": { @@ -4062,7 +4065,7 @@ }, "node_modules/@smithy/is-array-buffer": { "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-4.2.2.tgz", + "resolved": "https://mirrors.tencent.com/npm/@smithy/is-array-buffer/-/is-array-buffer-4.2.2.tgz", "integrity": "sha512-n6rQ4N8Jj4YTQO3YFrlgZuwKodf4zUFs7EJIWH86pSCWBaAtAGBFfCM7Wx6D2bBJ2xqFNxGBSrUWswT3M0VJow==", "license": "Apache-2.0", "dependencies": { @@ -4074,7 +4077,7 @@ }, "node_modules/@smithy/middleware-content-length": { "version": "4.2.12", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.2.12.tgz", + "resolved": "https://mirrors.tencent.com/npm/@smithy/middleware-content-length/-/middleware-content-length-4.2.12.tgz", "integrity": "sha512-YE58Yz+cvFInWI/wOTrB+DbvUVz/pLn5mC5MvOV4fdRUc6qGwygyngcucRQjAhiCEbmfLOXX0gntSIcgMvAjmA==", "license": "Apache-2.0", "dependencies": { @@ -4087,13 +4090,13 @@ } }, "node_modules/@smithy/middleware-endpoint": { - "version": "4.4.27", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.4.27.tgz", - "integrity": "sha512-T3TFfUgXQlpcg+UdzcAISdZpj4Z+XECZ/cefgA6wLBd6V4lRi0svN2hBouN/be9dXQ31X4sLWz3fAQDf+nt6BA==", + "version": "4.4.28", + "resolved": "https://mirrors.tencent.com/npm/@smithy/middleware-endpoint/-/middleware-endpoint-4.4.28.tgz", + "integrity": "sha512-p1gfYpi91CHcs5cBq982UlGlDrxoYUX6XdHSo91cQ2KFuz6QloHosO7Jc60pJiVmkWrKOV8kFYlGFFbQ2WUKKQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.23.12", - "@smithy/middleware-serde": "^4.2.15", + "@smithy/core": "^3.23.13", + "@smithy/middleware-serde": "^4.2.16", "@smithy/node-config-provider": "^4.3.12", "@smithy/shared-ini-file-loader": "^4.4.7", "@smithy/types": "^4.13.1", @@ -4106,18 +4109,18 @@ } }, "node_modules/@smithy/middleware-retry": { - "version": "4.4.44", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.4.44.tgz", - "integrity": "sha512-Y1Rav7m5CFRPQyM4CI0koD/bXjyjJu3EQxZZhtLGD88WIrBrQ7kqXM96ncd6rYnojwOo/u9MXu57JrEvu/nLrA==", + "version": "4.4.46", + "resolved": "https://mirrors.tencent.com/npm/@smithy/middleware-retry/-/middleware-retry-4.4.46.tgz", + "integrity": "sha512-SpvWNNOPOrKQGUqZbEPO+es+FRXMWvIyzUKUOYdDgdlA6BdZj/R58p4umoQ76c2oJC44PiM7mKizyyex1IJzow==", "license": "Apache-2.0", "dependencies": { "@smithy/node-config-provider": "^4.3.12", "@smithy/protocol-http": "^5.3.12", "@smithy/service-error-classification": "^4.2.12", - "@smithy/smithy-client": "^4.12.7", + "@smithy/smithy-client": "^4.12.8", "@smithy/types": "^4.13.1", "@smithy/util-middleware": "^4.2.12", - "@smithy/util-retry": "^4.2.12", + "@smithy/util-retry": "^4.2.13", "@smithy/uuid": "^1.1.2", "tslib": "^2.6.2" }, @@ -4126,12 +4129,12 @@ } }, "node_modules/@smithy/middleware-serde": { - "version": "4.2.15", - "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.2.15.tgz", - "integrity": "sha512-ExYhcltZSli0pgAKOpQQe1DLFBLryeZ22605y/YS+mQpdNWekum9Ujb/jMKfJKgjtz1AZldtwA/wCYuKJgjjlg==", + "version": "4.2.16", + "resolved": "https://mirrors.tencent.com/npm/@smithy/middleware-serde/-/middleware-serde-4.2.16.tgz", + "integrity": "sha512-beqfV+RZ9RSv+sQqor3xroUUYgRFCGRw6niGstPG8zO9LgTl0B0MCucxjmrH/2WwksQN7UUgI7KNANoZv+KALA==", "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.23.12", + "@smithy/core": "^3.23.13", "@smithy/protocol-http": "^5.3.12", "@smithy/types": "^4.13.1", "tslib": "^2.6.2" @@ -4142,7 +4145,7 @@ }, "node_modules/@smithy/middleware-stack": { "version": "4.2.12", - "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.2.12.tgz", + "resolved": "https://mirrors.tencent.com/npm/@smithy/middleware-stack/-/middleware-stack-4.2.12.tgz", "integrity": "sha512-kruC5gRHwsCOuyCd4ouQxYjgRAym2uDlCvQ5acuMtRrcdfg7mFBg6blaxcJ09STpt3ziEkis6bhg1uwrWU7txw==", "license": "Apache-2.0", "dependencies": { @@ -4155,7 +4158,7 @@ }, "node_modules/@smithy/node-config-provider": { "version": "4.3.12", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.3.12.tgz", + "resolved": "https://mirrors.tencent.com/npm/@smithy/node-config-provider/-/node-config-provider-4.3.12.tgz", "integrity": "sha512-tr2oKX2xMcO+rBOjobSwVAkV05SIfUKz8iI53rzxEmgW3GOOPOv0UioSDk+J8OpRQnpnhsO3Af6IEBabQBVmiw==", "license": "Apache-2.0", "dependencies": { @@ -4169,12 +4172,11 @@ } }, "node_modules/@smithy/node-http-handler": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.5.0.tgz", - "integrity": "sha512-Rnq9vQWiR1+/I6NZZMNzJHV6pZYyEHt2ZnuV3MG8z2NNenC4i/8Kzttz7CjZiHSmsN5frhXhg17z3Zqjjhmz1A==", + "version": "4.5.1", + "resolved": "https://mirrors.tencent.com/npm/@smithy/node-http-handler/-/node-http-handler-4.5.1.tgz", + "integrity": "sha512-ejjxdAXjkPIs9lyYyVutOGNOraqUE9v/NjGMKwwFrfOM354wfSD8lmlj8hVwUzQmlLLF4+udhfCX9Exnbmvfzw==", "license": "Apache-2.0", "dependencies": { - "@smithy/abort-controller": "^4.2.12", "@smithy/protocol-http": "^5.3.12", "@smithy/querystring-builder": "^4.2.12", "@smithy/types": "^4.13.1", @@ -4186,7 +4188,7 @@ }, "node_modules/@smithy/property-provider": { "version": "4.2.12", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.2.12.tgz", + "resolved": "https://mirrors.tencent.com/npm/@smithy/property-provider/-/property-provider-4.2.12.tgz", "integrity": "sha512-jqve46eYU1v7pZ5BM+fmkbq3DerkSluPr5EhvOcHxygxzD05ByDRppRwRPPpFrsFo5yDtCYLKu+kreHKVrvc7A==", "license": "Apache-2.0", "dependencies": { @@ -4199,7 +4201,7 @@ }, "node_modules/@smithy/protocol-http": { "version": "5.3.12", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.3.12.tgz", + "resolved": "https://mirrors.tencent.com/npm/@smithy/protocol-http/-/protocol-http-5.3.12.tgz", "integrity": "sha512-fit0GZK9I1xoRlR4jXmbLhoN0OdEpa96ul8M65XdmXnxXkuMxM0Y8HDT0Fh0Xb4I85MBvBClOzgSrV1X2s1Hxw==", "license": "Apache-2.0", "dependencies": { @@ -4212,7 +4214,7 @@ }, "node_modules/@smithy/querystring-builder": { "version": "4.2.12", - "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.2.12.tgz", + "resolved": "https://mirrors.tencent.com/npm/@smithy/querystring-builder/-/querystring-builder-4.2.12.tgz", "integrity": "sha512-6wTZjGABQufekycfDGMEB84BgtdOE/rCVTov+EDXQ8NHKTUNIp/j27IliwP7tjIU9LR+sSzyGBOXjeEtVgzCHg==", "license": "Apache-2.0", "dependencies": { @@ -4226,7 +4228,7 @@ }, "node_modules/@smithy/querystring-parser": { "version": "4.2.12", - "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.2.12.tgz", + "resolved": "https://mirrors.tencent.com/npm/@smithy/querystring-parser/-/querystring-parser-4.2.12.tgz", "integrity": "sha512-P2OdvrgiAKpkPNKlKUtWbNZKB1XjPxM086NeVhK+W+wI46pIKdWBe5QyXvhUm3MEcyS/rkLvY8rZzyUdmyDZBw==", "license": "Apache-2.0", "dependencies": { @@ -4239,7 +4241,7 @@ }, "node_modules/@smithy/service-error-classification": { "version": "4.2.12", - "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.2.12.tgz", + "resolved": "https://mirrors.tencent.com/npm/@smithy/service-error-classification/-/service-error-classification-4.2.12.tgz", "integrity": "sha512-LlP29oSQN0Tw0b6D0Xo6BIikBswuIiGYbRACy5ujw/JgWSzTdYj46U83ssf6Ux0GyNJVivs2uReU8pt7Eu9okQ==", "license": "Apache-2.0", "dependencies": { @@ -4251,7 +4253,7 @@ }, "node_modules/@smithy/shared-ini-file-loader": { "version": "4.4.7", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.4.7.tgz", + "resolved": "https://mirrors.tencent.com/npm/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.4.7.tgz", "integrity": "sha512-HrOKWsUb+otTeo1HxVWeEb99t5ER1XrBi/xka2Wv6NVmTbuCUC1dvlrksdvxFtODLBjsC+PHK+fuy2x/7Ynyiw==", "license": "Apache-2.0", "dependencies": { @@ -4264,7 +4266,7 @@ }, "node_modules/@smithy/signature-v4": { "version": "5.3.12", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.3.12.tgz", + "resolved": "https://mirrors.tencent.com/npm/@smithy/signature-v4/-/signature-v4-5.3.12.tgz", "integrity": "sha512-B/FBwO3MVOL00DaRSXfXfa/TRXRheagt/q5A2NM13u7q+sHS59EOVGQNfG7DkmVtdQm5m3vOosoKAXSqn/OEgw==", "license": "Apache-2.0", "dependencies": { @@ -4282,17 +4284,17 @@ } }, "node_modules/@smithy/smithy-client": { - "version": "4.12.7", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.12.7.tgz", - "integrity": "sha512-q3gqnwml60G44FECaEEsdQMplYhDMZYCtYhMCzadCnRnnHIobZJjegmdoUo6ieLQlPUzvrMdIJUpx6DoPmzANQ==", + "version": "4.12.8", + "resolved": "https://mirrors.tencent.com/npm/@smithy/smithy-client/-/smithy-client-4.12.8.tgz", + "integrity": "sha512-aJaAX7vHe5i66smoSSID7t4rKY08PbD8EBU7DOloixvhOozfYWdcSYE4l6/tjkZ0vBZhGjheWzB2mh31sLgCMA==", "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.23.12", - "@smithy/middleware-endpoint": "^4.4.27", + "@smithy/core": "^3.23.13", + "@smithy/middleware-endpoint": "^4.4.28", "@smithy/middleware-stack": "^4.2.12", "@smithy/protocol-http": "^5.3.12", "@smithy/types": "^4.13.1", - "@smithy/util-stream": "^4.5.20", + "@smithy/util-stream": "^4.5.21", "tslib": "^2.6.2" }, "engines": { @@ -4301,7 +4303,7 @@ }, "node_modules/@smithy/types": { "version": "4.13.1", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.13.1.tgz", + "resolved": "https://mirrors.tencent.com/npm/@smithy/types/-/types-4.13.1.tgz", "integrity": "sha512-787F3yzE2UiJIQ+wYW1CVg2odHjmaWLGksnKQHUrK/lYZSEcy1msuLVvxaR/sI2/aDe9U+TBuLsXnr3vod1g0g==", "license": "Apache-2.0", "dependencies": { @@ -4313,7 +4315,7 @@ }, "node_modules/@smithy/url-parser": { "version": "4.2.12", - "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.2.12.tgz", + "resolved": "https://mirrors.tencent.com/npm/@smithy/url-parser/-/url-parser-4.2.12.tgz", "integrity": "sha512-wOPKPEpso+doCZGIlr+e1lVI6+9VAKfL4kZWFgzVgGWY2hZxshNKod4l2LXS3PRC9otH/JRSjtEHqQ/7eLciRA==", "license": "Apache-2.0", "dependencies": { @@ -4327,7 +4329,7 @@ }, "node_modules/@smithy/util-base64": { "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-4.3.2.tgz", + "resolved": "https://mirrors.tencent.com/npm/@smithy/util-base64/-/util-base64-4.3.2.tgz", "integrity": "sha512-XRH6b0H/5A3SgblmMa5ErXQ2XKhfbQB+Fm/oyLZ2O2kCUrwgg55bU0RekmzAhuwOjA9qdN5VU2BprOvGGUkOOQ==", "license": "Apache-2.0", "dependencies": { @@ -4341,7 +4343,7 @@ }, "node_modules/@smithy/util-body-length-browser": { "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-4.2.2.tgz", + "resolved": "https://mirrors.tencent.com/npm/@smithy/util-body-length-browser/-/util-body-length-browser-4.2.2.tgz", "integrity": "sha512-JKCrLNOup3OOgmzeaKQwi4ZCTWlYR5H4Gm1r2uTMVBXoemo1UEghk5vtMi1xSu2ymgKVGW631e2fp9/R610ZjQ==", "license": "Apache-2.0", "dependencies": { @@ -4353,7 +4355,7 @@ }, "node_modules/@smithy/util-body-length-node": { "version": "4.2.3", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-4.2.3.tgz", + "resolved": "https://mirrors.tencent.com/npm/@smithy/util-body-length-node/-/util-body-length-node-4.2.3.tgz", "integrity": "sha512-ZkJGvqBzMHVHE7r/hcuCxlTY8pQr1kMtdsVPs7ex4mMU+EAbcXppfo5NmyxMYi2XU49eqaz56j2gsk4dHHPG/g==", "license": "Apache-2.0", "dependencies": { @@ -4365,7 +4367,7 @@ }, "node_modules/@smithy/util-buffer-from": { "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-4.2.2.tgz", + "resolved": "https://mirrors.tencent.com/npm/@smithy/util-buffer-from/-/util-buffer-from-4.2.2.tgz", "integrity": "sha512-FDXD7cvUoFWwN6vtQfEta540Y/YBe5JneK3SoZg9bThSoOAC/eGeYEua6RkBgKjGa/sz6Y+DuBZj3+YEY21y4Q==", "license": "Apache-2.0", "dependencies": { @@ -4378,7 +4380,7 @@ }, "node_modules/@smithy/util-config-provider": { "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-4.2.2.tgz", + "resolved": "https://mirrors.tencent.com/npm/@smithy/util-config-provider/-/util-config-provider-4.2.2.tgz", "integrity": "sha512-dWU03V3XUprJwaUIFVv4iOnS1FC9HnMHDfUrlNDSh4315v0cWyaIErP8KiqGVbf5z+JupoVpNM7ZB3jFiTejvQ==", "license": "Apache-2.0", "dependencies": { @@ -4389,13 +4391,13 @@ } }, "node_modules/@smithy/util-defaults-mode-browser": { - "version": "4.3.43", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.3.43.tgz", - "integrity": "sha512-Qd/0wCKMaXxev/z00TvNzGCH2jlKKKxXP1aDxB6oKwSQthe3Og2dMhSayGCnsma1bK/kQX1+X7SMP99t6FgiiQ==", + "version": "4.3.44", + "resolved": "https://mirrors.tencent.com/npm/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.3.44.tgz", + "integrity": "sha512-eZg6XzaCbVr2S5cAErU5eGBDaOVTuTo1I65i4tQcHENRcZ8rMWhQy1DaIYUSLyZjsfXvmCqZrstSMYyGFocvHA==", "license": "Apache-2.0", "dependencies": { "@smithy/property-provider": "^4.2.12", - "@smithy/smithy-client": "^4.12.7", + "@smithy/smithy-client": "^4.12.8", "@smithy/types": "^4.13.1", "tslib": "^2.6.2" }, @@ -4404,16 +4406,16 @@ } }, "node_modules/@smithy/util-defaults-mode-node": { - "version": "4.2.47", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.2.47.tgz", - "integrity": "sha512-qSRbYp1EQ7th+sPFuVcVO05AE0QH635hycdEXlpzIahqHHf2Fyd/Zl+8v0XYMJ3cgDVPa0lkMefU7oNUjAP+DQ==", + "version": "4.2.48", + "resolved": "https://mirrors.tencent.com/npm/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.2.48.tgz", + "integrity": "sha512-FqOKTlqSaoV3nzO55pMs5NBnZX8EhoI0DGmn9kbYeXWppgHD6dchyuj2HLqp4INJDJbSrj6OFYJkAh/WhSzZPg==", "license": "Apache-2.0", "dependencies": { "@smithy/config-resolver": "^4.4.13", "@smithy/credential-provider-imds": "^4.2.12", "@smithy/node-config-provider": "^4.3.12", "@smithy/property-provider": "^4.2.12", - "@smithy/smithy-client": "^4.12.7", + "@smithy/smithy-client": "^4.12.8", "@smithy/types": "^4.13.1", "tslib": "^2.6.2" }, @@ -4423,7 +4425,7 @@ }, "node_modules/@smithy/util-endpoints": { "version": "3.3.3", - "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.3.3.tgz", + "resolved": "https://mirrors.tencent.com/npm/@smithy/util-endpoints/-/util-endpoints-3.3.3.tgz", "integrity": "sha512-VACQVe50j0HZPjpwWcjyT51KUQ4AnsvEaQ2lKHOSL4mNLD0G9BjEniQ+yCt1qqfKfiAHRAts26ud7hBjamrwig==", "license": "Apache-2.0", "dependencies": { @@ -4437,7 +4439,7 @@ }, "node_modules/@smithy/util-hex-encoding": { "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-4.2.2.tgz", + "resolved": "https://mirrors.tencent.com/npm/@smithy/util-hex-encoding/-/util-hex-encoding-4.2.2.tgz", "integrity": "sha512-Qcz3W5vuHK4sLQdyT93k/rfrUwdJ8/HZ+nMUOyGdpeGA1Wxt65zYwi3oEl9kOM+RswvYq90fzkNDahPS8K0OIg==", "license": "Apache-2.0", "dependencies": { @@ -4449,7 +4451,7 @@ }, "node_modules/@smithy/util-middleware": { "version": "4.2.12", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.2.12.tgz", + "resolved": "https://mirrors.tencent.com/npm/@smithy/util-middleware/-/util-middleware-4.2.12.tgz", "integrity": "sha512-Er805uFUOvgc0l8nv0e0su0VFISoxhJ/AwOn3gL2NWNY2LUEldP5WtVcRYSQBcjg0y9NfG8JYrCJaYDpupBHJQ==", "license": "Apache-2.0", "dependencies": { @@ -4461,9 +4463,9 @@ } }, "node_modules/@smithy/util-retry": { - "version": "4.2.12", - "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.2.12.tgz", - "integrity": "sha512-1zopLDUEOwumjcHdJ1mwBHddubYF8GMQvstVCLC54Y46rqoHwlIU+8ZzUeaBcD+WCJHyDGSeZ2ml9YSe9aqcoQ==", + "version": "4.2.13", + "resolved": "https://mirrors.tencent.com/npm/@smithy/util-retry/-/util-retry-4.2.13.tgz", + "integrity": "sha512-qQQsIvL0MGIbUjeSrg0/VlQ3jGNKyM3/2iU3FPNgy01z+Sp4OvcaxbgIoFOTvB61ZoohtutuOvOcgmhbD0katQ==", "license": "Apache-2.0", "dependencies": { "@smithy/service-error-classification": "^4.2.12", @@ -4475,13 +4477,13 @@ } }, "node_modules/@smithy/util-stream": { - "version": "4.5.20", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.5.20.tgz", - "integrity": "sha512-4yXLm5n/B5SRBR2p8cZ90Sbv4zL4NKsgxdzCzp/83cXw2KxLEumt5p+GAVyRNZgQOSrzXn9ARpO0lUe8XSlSDw==", + "version": "4.5.21", + "resolved": "https://mirrors.tencent.com/npm/@smithy/util-stream/-/util-stream-4.5.21.tgz", + "integrity": "sha512-KzSg+7KKywLnkoKejRtIBXDmwBfjGvg1U1i/etkC7XSWUyFCoLno1IohV2c74IzQqdhX5y3uE44r/8/wuK+A7Q==", "license": "Apache-2.0", "dependencies": { "@smithy/fetch-http-handler": "^5.3.15", - "@smithy/node-http-handler": "^4.5.0", + "@smithy/node-http-handler": "^4.5.1", "@smithy/types": "^4.13.1", "@smithy/util-base64": "^4.3.2", "@smithy/util-buffer-from": "^4.2.2", @@ -4495,7 +4497,7 @@ }, "node_modules/@smithy/util-uri-escape": { "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.2.2.tgz", + "resolved": "https://mirrors.tencent.com/npm/@smithy/util-uri-escape/-/util-uri-escape-4.2.2.tgz", "integrity": "sha512-2kAStBlvq+lTXHyAZYfJRb/DfS3rsinLiwb+69SstC9Vb0s9vNWkRwpnj918Pfi85mzi42sOqdV72OLxWAISnw==", "license": "Apache-2.0", "dependencies": { @@ -4507,7 +4509,7 @@ }, "node_modules/@smithy/util-utf8": { "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.2.2.tgz", + "resolved": "https://mirrors.tencent.com/npm/@smithy/util-utf8/-/util-utf8-4.2.2.tgz", "integrity": "sha512-75MeYpjdWRe8M5E3AW0O4Cx3UadweS+cwdXjwYGBW5h/gxxnbeZ877sLPX/ZJA9GVTlL/qG0dXP29JWFCD1Ayw==", "license": "Apache-2.0", "dependencies": { @@ -4520,7 +4522,7 @@ }, "node_modules/@smithy/uuid": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@smithy/uuid/-/uuid-1.1.2.tgz", + "resolved": "https://mirrors.tencent.com/npm/@smithy/uuid/-/uuid-1.1.2.tgz", "integrity": "sha512-O/IEdcCUKkubz60tFbGA7ceITTAJsty+lBjNoorP4Z6XRqaFb/OjQjZODophEcuq68nKm6/0r+6/lLQ+XVpk8g==", "license": "Apache-2.0", "dependencies": { @@ -5171,7 +5173,7 @@ }, "node_modules/@tootallnate/quickjs-emscripten": { "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", + "resolved": "https://mirrors.tencent.com/npm/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", "license": "MIT" }, @@ -5584,7 +5586,7 @@ }, "node_modules/@types/retry": { "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "resolved": "https://mirrors.tencent.com/npm/@types/retry/-/retry-0.12.0.tgz", "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", "license": "MIT" }, @@ -5810,9 +5812,8 @@ }, "node_modules/ajv": { "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "resolved": "https://mirrors.tencent.com/npm/ajv/-/ajv-8.18.0.tgz", "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", - "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -5826,7 +5827,7 @@ }, "node_modules/ajv-formats": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "resolved": "https://mirrors.tencent.com/npm/ajv-formats/-/ajv-formats-3.0.1.tgz", "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", "license": "MIT", "dependencies": { @@ -5899,7 +5900,7 @@ }, "node_modules/ast-types": { "version": "0.13.4", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", + "resolved": "https://mirrors.tencent.com/npm/ast-types/-/ast-types-0.13.4.tgz", "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", "license": "MIT", "dependencies": { @@ -5957,7 +5958,7 @@ }, "node_modules/base64-js": { "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "resolved": "https://mirrors.tencent.com/npm/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", "funding": [ { @@ -5972,8 +5973,7 @@ "type": "consulting", "url": "https://feross.org/support" } - ], - "license": "MIT" + ] }, "node_modules/baseline-browser-mapping": { "version": "2.10.10", @@ -5990,7 +5990,7 @@ }, "node_modules/basic-ftp": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.2.0.tgz", + "resolved": "https://mirrors.tencent.com/npm/basic-ftp/-/basic-ftp-5.2.0.tgz", "integrity": "sha512-VoMINM2rqJwJgfdHq6RiUudKt2BV+FY5ZFezP/ypmwayk68+NzzAQy4XXLlqsGD4MCzq3DrmNFD/uUmBJuGoXw==", "license": "MIT", "engines": { @@ -5999,7 +5999,7 @@ }, "node_modules/bignumber.js": { "version": "9.3.1", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz", + "resolved": "https://mirrors.tencent.com/npm/bignumber.js/-/bignumber.js-9.3.1.tgz", "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==", "license": "MIT", "engines": { @@ -6008,7 +6008,7 @@ }, "node_modules/bowser": { "version": "2.14.1", - "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.14.1.tgz", + "resolved": "https://mirrors.tencent.com/npm/bowser/-/bowser-2.14.1.tgz", "integrity": "sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==", "license": "MIT" }, @@ -6061,7 +6061,7 @@ }, "node_modules/buffer-equal-constant-time": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "resolved": "https://mirrors.tencent.com/npm/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", "license": "BSD-3-Clause" }, @@ -6139,7 +6139,7 @@ }, "node_modules/chalk": { "version": "5.6.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "resolved": "https://mirrors.tencent.com/npm/chalk/-/chalk-5.6.2.tgz", "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", "license": "MIT", "engines": { @@ -6871,7 +6871,7 @@ }, "node_modules/data-uri-to-buffer": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "resolved": "https://mirrors.tencent.com/npm/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", "license": "MIT", "engines": { @@ -6947,7 +6947,7 @@ }, "node_modules/degenerator": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", + "resolved": "https://mirrors.tencent.com/npm/degenerator/-/degenerator-5.0.1.tgz", "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", "license": "MIT", "dependencies": { @@ -7057,7 +7057,7 @@ }, "node_modules/ecdsa-sig-formatter": { "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "resolved": "https://mirrors.tencent.com/npm/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", "license": "Apache-2.0", "dependencies": { @@ -7226,7 +7226,7 @@ }, "node_modules/escodegen": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "resolved": "https://mirrors.tencent.com/npm/escodegen/-/escodegen-2.1.0.tgz", "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", "license": "BSD-2-Clause", "dependencies": { @@ -7247,7 +7247,7 @@ }, "node_modules/esprima": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "resolved": "https://mirrors.tencent.com/npm/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "license": "BSD-2-Clause", "bin": { @@ -7260,9 +7260,8 @@ }, "node_modules/estraverse": { "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "resolved": "https://mirrors.tencent.com/npm/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } @@ -7289,7 +7288,7 @@ }, "node_modules/esutils": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "resolved": "https://mirrors.tencent.com/npm/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "license": "BSD-2-Clause", "engines": { @@ -7314,13 +7313,13 @@ }, "node_modules/fast-deep-equal": { "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "resolved": "https://mirrors.tencent.com/npm/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "license": "MIT" }, "node_modules/fast-uri": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "resolved": "https://mirrors.tencent.com/npm/fast-uri/-/fast-uri-3.1.0.tgz", "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", "funding": [ { @@ -7336,7 +7335,7 @@ }, "node_modules/fast-xml-builder": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.1.4.tgz", + "resolved": "https://mirrors.tencent.com/npm/fast-xml-builder/-/fast-xml-builder-1.1.4.tgz", "integrity": "sha512-f2jhpN4Eccy0/Uz9csxh3Nu6q4ErKxf0XIsasomfOihuSUa3/xw6w8dnOtCDgEItQFJG8KyXPzQXzcODDrrbOg==", "funding": [ { @@ -7351,7 +7350,7 @@ }, "node_modules/fast-xml-parser": { "version": "5.5.8", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.5.8.tgz", + "resolved": "https://mirrors.tencent.com/npm/fast-xml-parser/-/fast-xml-parser-5.5.8.tgz", "integrity": "sha512-Z7Fh2nVQSb2d+poDViM063ix2ZGt9jmY1nWhPfHBOK2Hgnb/OW3P4Et3P/81SEej0J7QbWtJqxO05h8QYfK7LQ==", "funding": [ { @@ -7359,7 +7358,6 @@ "url": "https://github.com/sponsors/NaturalIntelligence" } ], - "license": "MIT", "dependencies": { "fast-xml-builder": "^1.1.4", "path-expression-matcher": "^1.2.0", @@ -7389,7 +7387,7 @@ }, "node_modules/fetch-blob": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "resolved": "https://mirrors.tencent.com/npm/fetch-blob/-/fetch-blob-3.2.0.tgz", "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", "funding": [ { @@ -7446,7 +7444,7 @@ }, "node_modules/formdata-polyfill": { "version": "4.0.10", - "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "resolved": "https://mirrors.tencent.com/npm/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", "license": "MIT", "dependencies": { @@ -7483,7 +7481,7 @@ }, "node_modules/gaxios": { "version": "7.1.4", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.4.tgz", + "resolved": "https://mirrors.tencent.com/npm/gaxios/-/gaxios-7.1.4.tgz", "integrity": "sha512-bTIgTsM2bWn3XklZISBTQX7ZSddGW+IO3bMdGaemHZ3tbqExMENHLx6kKZ/KlejgrMtj8q7wBItt51yegqalrA==", "license": "Apache-2.0", "dependencies": { @@ -7497,7 +7495,7 @@ }, "node_modules/gcp-metadata": { "version": "8.1.2", - "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-8.1.2.tgz", + "resolved": "https://mirrors.tencent.com/npm/gcp-metadata/-/gcp-metadata-8.1.2.tgz", "integrity": "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==", "license": "Apache-2.0", "dependencies": { @@ -7569,7 +7567,7 @@ }, "node_modules/get-uri": { "version": "6.0.5", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.5.tgz", + "resolved": "https://mirrors.tencent.com/npm/get-uri/-/get-uri-6.0.5.tgz", "integrity": "sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==", "license": "MIT", "dependencies": { @@ -7583,7 +7581,7 @@ }, "node_modules/get-uri/node_modules/data-uri-to-buffer": { "version": "6.0.2", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", + "resolved": "https://mirrors.tencent.com/npm/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==", "license": "MIT", "engines": { @@ -7647,7 +7645,7 @@ }, "node_modules/google-auth-library": { "version": "10.6.2", - "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.6.2.tgz", + "resolved": "https://mirrors.tencent.com/npm/google-auth-library/-/google-auth-library-10.6.2.tgz", "integrity": "sha512-e27Z6EThmVNNvtYASwQxose/G57rkRuaRbQyxM2bvYLLX/GqWZ5chWq2EBoUchJbCc57eC9ArzO5wMsEmWftCw==", "license": "Apache-2.0", "dependencies": { @@ -7664,7 +7662,7 @@ }, "node_modules/google-logging-utils": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-1.1.3.tgz", + "resolved": "https://mirrors.tencent.com/npm/google-logging-utils/-/google-logging-utils-1.1.3.tgz", "integrity": "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==", "license": "Apache-2.0", "engines": { @@ -8003,7 +8001,7 @@ }, "node_modules/ip-address": { "version": "10.1.0", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz", + "resolved": "https://mirrors.tencent.com/npm/ip-address/-/ip-address-10.1.0.tgz", "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==", "license": "MIT", "engines": { @@ -8233,7 +8231,7 @@ }, "node_modules/json-bigint": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "resolved": "https://mirrors.tencent.com/npm/json-bigint/-/json-bigint-1.0.0.tgz", "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", "license": "MIT", "dependencies": { @@ -8242,7 +8240,7 @@ }, "node_modules/json-schema-to-ts": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/json-schema-to-ts/-/json-schema-to-ts-3.1.1.tgz", + "resolved": "https://mirrors.tencent.com/npm/json-schema-to-ts/-/json-schema-to-ts-3.1.1.tgz", "integrity": "sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g==", "license": "MIT", "dependencies": { @@ -8255,9 +8253,8 @@ }, "node_modules/json-schema-traverse": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "license": "MIT" + "resolved": "https://mirrors.tencent.com/npm/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, "node_modules/json5": { "version": "2.2.3", @@ -8274,7 +8271,7 @@ }, "node_modules/jwa": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", + "resolved": "https://mirrors.tencent.com/npm/jwa/-/jwa-2.0.1.tgz", "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", "license": "MIT", "dependencies": { @@ -8285,7 +8282,7 @@ }, "node_modules/jws": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz", + "resolved": "https://mirrors.tencent.com/npm/jws/-/jws-4.0.1.tgz", "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", "license": "MIT", "dependencies": { @@ -8615,7 +8612,7 @@ }, "node_modules/long": { "version": "5.3.2", - "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "resolved": "https://mirrors.tencent.com/npm/long/-/long-5.3.2.tgz", "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", "license": "Apache-2.0" }, @@ -9721,7 +9718,7 @@ }, "node_modules/netmask": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", + "resolved": "https://mirrors.tencent.com/npm/netmask/-/netmask-2.0.2.tgz", "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", "license": "MIT", "engines": { @@ -9730,7 +9727,7 @@ }, "node_modules/node-domexception": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "resolved": "https://mirrors.tencent.com/npm/node-domexception/-/node-domexception-1.0.0.tgz", "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", "deprecated": "Use your platform's native DOMException instead", "funding": [ @@ -9750,9 +9747,8 @@ }, "node_modules/node-fetch": { "version": "3.3.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "resolved": "https://mirrors.tencent.com/npm/node-fetch/-/node-fetch-3.3.2.tgz", "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", - "license": "MIT", "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", @@ -9782,7 +9778,7 @@ }, "node_modules/openai": { "version": "6.26.0", - "resolved": "https://registry.npmjs.org/openai/-/openai-6.26.0.tgz", + "resolved": "https://mirrors.tencent.com/npm/openai/-/openai-6.26.0.tgz", "integrity": "sha512-zd23dbWTjiJ6sSAX6s0HrCZi41JwTA1bQVs0wLQPZ2/5o2gxOJA5wh7yOAUgwYybfhDXyhwlpeQf7Mlgx8EOCA==", "license": "Apache-2.0", "bin": { @@ -9803,7 +9799,7 @@ }, "node_modules/p-retry": { "version": "4.6.2", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "resolved": "https://mirrors.tencent.com/npm/p-retry/-/p-retry-4.6.2.tgz", "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", "license": "MIT", "dependencies": { @@ -9816,7 +9812,7 @@ }, "node_modules/pac-proxy-agent": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.2.0.tgz", + "resolved": "https://mirrors.tencent.com/npm/pac-proxy-agent/-/pac-proxy-agent-7.2.0.tgz", "integrity": "sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==", "license": "MIT", "dependencies": { @@ -9835,7 +9831,7 @@ }, "node_modules/pac-resolver": { "version": "7.0.1", - "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", + "resolved": "https://mirrors.tencent.com/npm/pac-resolver/-/pac-resolver-7.0.1.tgz", "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", "license": "MIT", "dependencies": { @@ -9898,7 +9894,7 @@ }, "node_modules/partial-json": { "version": "0.1.7", - "resolved": "https://registry.npmjs.org/partial-json/-/partial-json-0.1.7.tgz", + "resolved": "https://mirrors.tencent.com/npm/partial-json/-/partial-json-0.1.7.tgz", "integrity": "sha512-Njv/59hHaokb/hRUjce3Hdv12wd60MtM9Z5Olmn+nehe0QDAsRtRbJPvJ0Z91TusF0SuZRIvnM+S4l6EIP8leA==", "license": "MIT" }, @@ -9909,9 +9905,9 @@ "license": "MIT" }, "node_modules/path-expression-matcher": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.2.0.tgz", - "integrity": "sha512-DwmPWeFn+tq7TiyJ2CxezCAirXjFxvaiD03npak3cRjlP9+OjTmSy1EpIrEbh+l6JgUundniloMLDQ/6VTdhLQ==", + "version": "1.2.1", + "resolved": "https://mirrors.tencent.com/npm/path-expression-matcher/-/path-expression-matcher-1.2.1.tgz", + "integrity": "sha512-d7gQQmLvAKXKXE2GeP9apIGbMYKz88zWdsn/BN2HRWVQsDFdUY36WSLTY0Jvd4HWi7Fb30gQ62oAOzdgJA6fZw==", "funding": [ { "type": "github", @@ -10109,7 +10105,7 @@ }, "node_modules/protobufjs": { "version": "7.5.4", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.4.tgz", + "resolved": "https://mirrors.tencent.com/npm/protobufjs/-/protobufjs-7.5.4.tgz", "integrity": "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==", "hasInstallScript": true, "license": "BSD-3-Clause", @@ -10133,7 +10129,7 @@ }, "node_modules/proxy-agent": { "version": "6.5.0", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.5.0.tgz", + "resolved": "https://mirrors.tencent.com/npm/proxy-agent/-/proxy-agent-6.5.0.tgz", "integrity": "sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==", "license": "MIT", "dependencies": { @@ -10152,7 +10148,7 @@ }, "node_modules/proxy-agent/node_modules/lru-cache": { "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "resolved": "https://mirrors.tencent.com/npm/lru-cache/-/lru-cache-7.18.3.tgz", "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", "license": "ISC", "engines": { @@ -10161,9 +10157,8 @@ }, "node_modules/proxy-from-env": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "license": "MIT" + "resolved": "https://mirrors.tencent.com/npm/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, "node_modules/punycode": { "version": "2.3.1", @@ -10486,7 +10481,7 @@ }, "node_modules/require-from-string": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "resolved": "https://mirrors.tencent.com/npm/require-from-string/-/require-from-string-2.0.2.tgz", "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "license": "MIT", "engines": { @@ -10495,7 +10490,7 @@ }, "node_modules/retry": { "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "resolved": "https://mirrors.tencent.com/npm/retry/-/retry-0.13.1.tgz", "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", "license": "MIT", "engines": { @@ -10580,7 +10575,7 @@ }, "node_modules/safe-buffer": { "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "resolved": "https://mirrors.tencent.com/npm/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "funding": [ { @@ -10678,7 +10673,7 @@ }, "node_modules/smart-buffer": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "resolved": "https://mirrors.tencent.com/npm/smart-buffer/-/smart-buffer-4.2.0.tgz", "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", "license": "MIT", "engines": { @@ -10688,7 +10683,7 @@ }, "node_modules/socks": { "version": "2.8.7", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", + "resolved": "https://mirrors.tencent.com/npm/socks/-/socks-2.8.7.tgz", "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", "license": "MIT", "dependencies": { @@ -10702,7 +10697,7 @@ }, "node_modules/socks-proxy-agent": { "version": "8.0.5", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", + "resolved": "https://mirrors.tencent.com/npm/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", "license": "MIT", "dependencies": { @@ -10716,9 +10711,8 @@ }, "node_modules/source-map": { "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "resolved": "https://mirrors.tencent.com/npm/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "license": "BSD-3-Clause", "optional": true, "engines": { "node": ">=0.10.0" @@ -10931,9 +10925,9 @@ "license": "MIT" }, "node_modules/strnum": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.2.1.tgz", - "integrity": "sha512-BwRvNd5/QoAtyW1na1y1LsJGQNvRlkde6Q/ipqqEaivoMdV+B1OMOTVdwR+N/cwVUcIt9PYyHmV8HyexCZSupg==", + "version": "2.2.2", + "resolved": "https://mirrors.tencent.com/npm/strnum/-/strnum-2.2.2.tgz", + "integrity": "sha512-DnR90I+jtXNSTXWdwrEy9FakW7UX+qUZg28gj5fk2vxxl7uS/3bpI4fjFYVmdK9etptYBPNkpahuQnEwhwECqA==", "funding": [ { "type": "github", @@ -11163,7 +11157,7 @@ }, "node_modules/ts-algebra": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ts-algebra/-/ts-algebra-2.0.0.tgz", + "resolved": "https://mirrors.tencent.com/npm/ts-algebra/-/ts-algebra-2.0.0.tgz", "integrity": "sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw==", "license": "MIT" }, @@ -11212,9 +11206,9 @@ "license": "MIT" }, "node_modules/undici": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.24.5.tgz", - "integrity": "sha512-3IWdCpjgxp15CbJnsi/Y9TCDE7HWVN19j1hmzVhoAkY/+CJx449tVxT5wZc1Gwg8J+P0LWvzlBzxYRnHJ+1i7Q==", + "version": "7.24.7", + "resolved": "https://mirrors.tencent.com/npm/undici/-/undici-7.24.7.tgz", + "integrity": "sha512-H/nlJ/h0ggGC+uRL3ovD+G0i4bqhvsDOpbDv7At5eFLlj2b41L8QliGbnl2H7SnDiYhENphh1tQFJZf+MyfLsQ==", "license": "MIT", "engines": { "node": ">=20.18.1" @@ -11718,9 +11712,8 @@ }, "node_modules/web-streams-polyfill": { "version": "3.3.3", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "resolved": "https://mirrors.tencent.com/npm/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", - "license": "MIT", "engines": { "node": ">= 8" } @@ -11954,7 +11947,7 @@ }, "node_modules/zod": { "version": "4.3.6", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz", + "resolved": "https://mirrors.tencent.com/npm/zod/-/zod-4.3.6.tgz", "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", "license": "MIT", "funding": { @@ -11962,12 +11955,12 @@ } }, "node_modules/zod-to-json-schema": { - "version": "3.25.1", - "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.1.tgz", - "integrity": "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==", + "version": "3.25.2", + "resolved": "https://mirrors.tencent.com/npm/zod-to-json-schema/-/zod-to-json-schema-3.25.2.tgz", + "integrity": "sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA==", "license": "ISC", "peerDependencies": { - "zod": "^3.25 || ^4" + "zod": "^3.25.28 || ^4" } }, "node_modules/zustand": { diff --git a/crates/cratebay-gui/package.json b/crates/cratebay-gui/package.json index ad08cd7..86d6d87 100644 --- a/crates/cratebay-gui/package.json +++ b/crates/cratebay-gui/package.json @@ -21,8 +21,8 @@ "test:e2e": "playwright test" }, "dependencies": { - "@mariozechner/pi-agent-core": "^0.61.0", - "@mariozechner/pi-ai": "^0.61.0", + "@mariozechner/pi-agent-core": "^0.63.2", + "@mariozechner/pi-ai": "^0.63.2", "@sinclair/typebox": "^0.34.48", "@tauri-apps/api": "^2.0.0", "class-variance-authority": "^0.7.1", diff --git a/crates/cratebay-gui/pnpm-lock.yaml b/crates/cratebay-gui/pnpm-lock.yaml index 6255e28..94351ff 100644 --- a/crates/cratebay-gui/pnpm-lock.yaml +++ b/crates/cratebay-gui/pnpm-lock.yaml @@ -9,11 +9,11 @@ importers: .: dependencies: '@mariozechner/pi-agent-core': - specifier: ^0.61.0 - version: 0.61.0(ws@8.19.0)(zod@4.3.6) + specifier: ^0.63.2 + version: 0.63.2(ws@8.19.0)(zod@4.3.6) '@mariozechner/pi-ai': - specifier: ^0.61.0 - version: 0.61.0(ws@8.19.0)(zod@4.3.6) + specifier: ^0.63.2 + version: 0.63.2(ws@8.19.0)(zod@4.3.6) '@sinclair/typebox': specifier: ^0.34.48 version: 0.34.48 @@ -598,12 +598,12 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} - '@mariozechner/pi-agent-core@0.61.0': - resolution: {integrity: sha512-MBCZfcYDmc5ssZGitv66nSsjma0W+4VwnfzPDRXdOcIhtxiJYux2t8mZe23CbUb4WNkeY3eMU2N6pe4YWeGexg==} + '@mariozechner/pi-agent-core@0.63.2': + resolution: {integrity: sha512-9QTS7ylcmoAIWXk0EVpwCCop3fK4NIqTAN8TiRuXvuKYx+wYmUJc+P5+RfehIZhwsy7g9O/rktz0c1YEUBFB0g==} engines: {node: '>=20.0.0'} - '@mariozechner/pi-ai@0.61.0': - resolution: {integrity: sha512-iiTiZ91aEND1AfP314exsissbPJnMMZv0NWLkazFf8TwYlUo9qD+6TlXEUYnX1ZRMCnZ7RjSEVerRrQ63FGZXw==} + '@mariozechner/pi-ai@0.63.2': + resolution: {integrity: sha512-EJNPyzeZeifTJmkD8PPYQmSO4P4h8kFCrhUqU4NvFUkug+GNYr954KlxhYnXH0f77MpdIEpf/O5zdDrYJQyafA==} engines: {node: '>=20.0.0'} hasBin: true @@ -4610,9 +4610,9 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@mariozechner/pi-agent-core@0.61.0(ws@8.19.0)(zod@4.3.6)': + '@mariozechner/pi-agent-core@0.63.2(ws@8.19.0)(zod@4.3.6)': dependencies: - '@mariozechner/pi-ai': 0.61.0(ws@8.19.0)(zod@4.3.6) + '@mariozechner/pi-ai': 0.63.2(ws@8.19.0)(zod@4.3.6) transitivePeerDependencies: - '@modelcontextprotocol/sdk' - aws-crt @@ -4622,7 +4622,7 @@ snapshots: - ws - zod - '@mariozechner/pi-ai@0.61.0(ws@8.19.0)(zod@4.3.6)': + '@mariozechner/pi-ai@0.63.2(ws@8.19.0)(zod@4.3.6)': dependencies: '@anthropic-ai/sdk': 0.73.0(zod@4.3.6) '@aws-sdk/client-bedrock-runtime': 3.1013.0 diff --git a/crates/cratebay-gui/src-tauri/src/commands/mod.rs b/crates/cratebay-gui/src-tauri/src/commands/mod.rs index 9a27800..a4587e8 100644 --- a/crates/cratebay-gui/src-tauri/src/commands/mod.rs +++ b/crates/cratebay-gui/src-tauri/src/commands/mod.rs @@ -3,5 +3,6 @@ pub mod container; pub mod llm; pub mod mcp; +pub mod sandbox; pub mod storage; pub mod system; diff --git a/crates/cratebay-gui/src-tauri/src/commands/sandbox.rs b/crates/cratebay-gui/src-tauri/src/commands/sandbox.rs new file mode 100644 index 0000000..c769d89 --- /dev/null +++ b/crates/cratebay-gui/src-tauri/src/commands/sandbox.rs @@ -0,0 +1,59 @@ +//! Sandbox execution Tauri commands. +//! +//! Exposes `cratebay_core::sandbox` operations (run_code, install_packages) +//! to the frontend via Tauri invoke. + +use tauri::State; + +use crate::state::AppState; +use cratebay_core::error::AppError; +use cratebay_core::sandbox; + +/// Run code in a temporary sandbox container. +/// +/// Creates a container, writes the code, executes it, and returns the result. +/// By default the container is cleaned up after execution. +#[tauri::command] +pub async fn sandbox_run_code( + state: State<'_, AppState>, + language: String, + code: String, + sandbox_id: Option, + timeout_seconds: Option, +) -> Result { + let docker = state.ensure_docker_once().await?; + + let params = sandbox::RunCodeParams { + language, + code, + timeout_seconds, + environment: None, + cleanup: if sandbox_id.is_some() { + Some(false) + } else { + Some(true) + }, + sandbox_id, + }; + + sandbox::run_code(&docker, params).await +} + +/// Install packages in an existing sandbox container. +#[tauri::command] +pub async fn sandbox_install( + state: State<'_, AppState>, + sandbox_id: String, + package_manager: String, + packages: Vec, +) -> Result { + let docker = state.ensure_docker_once().await?; + + let params = sandbox::InstallParams { + sandbox_id, + package_manager, + packages, + }; + + sandbox::install_packages(&docker, params).await +} diff --git a/crates/cratebay-gui/src-tauri/src/main.rs b/crates/cratebay-gui/src-tauri/src/main.rs index a30fa1f..bd3d355 100644 --- a/crates/cratebay-gui/src-tauri/src/main.rs +++ b/crates/cratebay-gui/src-tauri/src/main.rs @@ -616,6 +616,9 @@ fn main() { commands::system::runtime_status, commands::system::runtime_start, commands::system::runtime_stop, + // Sandbox + commands::sandbox::sandbox_run_code, + commands::sandbox::sandbox_install, // Debug #[cfg(debug_assertions)] commands::system::webview_debug_report, diff --git a/crates/cratebay-gui/src/App.tsx b/crates/cratebay-gui/src/App.tsx index 91de090..3f188a6 100644 --- a/crates/cratebay-gui/src/App.tsx +++ b/crates/cratebay-gui/src/App.tsx @@ -8,7 +8,6 @@ import { AppLayout } from "@/components/layout/AppLayout"; import { ToastContainer } from "@/components/common/Toast"; import { ChatPage } from "@/pages/ChatPage"; import { ContainersPage } from "@/pages/ContainersPage"; -import { McpPage } from "@/pages/McpPage"; import { SettingsPage } from "@/pages/SettingsPage"; import { ImagesPage } from "@/pages/ImagesPage"; @@ -252,7 +251,6 @@ function App() { {currentPage === "chat" && } {currentPage === "containers" && } {currentPage === "images" && } - {currentPage === "mcp" && } {currentPage === "settings" && } diff --git a/crates/cratebay-gui/src/__tests__/App.test.tsx b/crates/cratebay-gui/src/__tests__/App.test.tsx index 98c6efd..8f75780 100644 --- a/crates/cratebay-gui/src/__tests__/App.test.tsx +++ b/crates/cratebay-gui/src/__tests__/App.test.tsx @@ -1,6 +1,7 @@ import { describe, it, expect, vi, beforeEach } from "vitest"; import { render, screen } from "@testing-library/react"; import { useAppStore } from "@/stores/appStore"; +import { APP_VERSION } from "@/lib/constants"; // Mock child pages to avoid deep rendering issues (e.g. infinite update loops) vi.mock("@/pages/ChatPage", () => ({ @@ -9,9 +10,6 @@ vi.mock("@/pages/ChatPage", () => ({ vi.mock("@/pages/ContainersPage", () => ({ ContainersPage: () =>
ContainersPage
, })); -vi.mock("@/pages/McpPage", () => ({ - McpPage: () =>
McpPage
, -})); vi.mock("@/pages/SettingsPage", () => ({ SettingsPage: () =>
SettingsPage
, })); @@ -49,7 +47,7 @@ describe("App", () => { it("renders the version number", () => { render(); - const versionElements = screen.getAllByText(/v2\.0\.0/); + const versionElements = screen.getAllByText(`v${APP_VERSION}`); expect(versionElements.length).toBeGreaterThanOrEqual(1); }); @@ -60,8 +58,9 @@ describe("App", () => { it("renders navigation sidebar with all pages", () => { render(); + expect(screen.getByText("Chat")).toBeInTheDocument(); expect(screen.getByText("Containers")).toBeInTheDocument(); - expect(screen.getByText("MCP")).toBeInTheDocument(); + expect(screen.getByText("Images")).toBeInTheDocument(); const settingsElements = screen.getAllByText("Settings"); expect(settingsElements.length).toBeGreaterThanOrEqual(1); }); diff --git a/crates/cratebay-gui/src/__tests__/agentFlow.test.ts b/crates/cratebay-gui/src/__tests__/agentFlow.test.ts index b792aa8..cf08e11 100644 --- a/crates/cratebay-gui/src/__tests__/agentFlow.test.ts +++ b/crates/cratebay-gui/src/__tests__/agentFlow.test.ts @@ -403,8 +403,8 @@ describe("buildSystemPrompt", () => { it("contains behavioral rules section", () => { const prompt = buildSystemPrompt(allTools); - expect(prompt).toContain("Safety First"); - expect(prompt).toContain("Error Recovery"); + expect(prompt).toContain("Behavioral Rules"); + expect(prompt).toContain("Error recovery"); expect(prompt).toContain("Restrictions"); }); }); diff --git a/crates/cratebay-gui/src/__tests__/layout.test.tsx b/crates/cratebay-gui/src/__tests__/layout.test.tsx index 0773756..9670cf3 100644 --- a/crates/cratebay-gui/src/__tests__/layout.test.tsx +++ b/crates/cratebay-gui/src/__tests__/layout.test.tsx @@ -67,7 +67,7 @@ describe("AppLayout", () => { // Children are rendered expect(screen.getByTestId("child-content")).toBeInTheDocument(); // Version is rendered (appears in both Sidebar bottom and StatusBar) - const versionElements = screen.getAllByText(/v2\.0\.0/); + const versionElements = screen.getAllByText(/v0\.9\.0/); expect(versionElements.length).toBeGreaterThanOrEqual(1); }); @@ -82,7 +82,7 @@ describe("AppLayout", () => { const chatElements = screen.getAllByText("Chat"); expect(chatElements.length).toBeGreaterThanOrEqual(1); expect(screen.getByText("Containers")).toBeInTheDocument(); - expect(screen.getByText("MCP")).toBeInTheDocument(); + expect(screen.getByText("Images")).toBeInTheDocument(); const settingsElements = screen.getAllByText("Settings"); expect(settingsElements.length).toBeGreaterThanOrEqual(1); }); @@ -110,7 +110,7 @@ describe("Sidebar", () => { expect(screen.getByText("Chat")).toBeInTheDocument(); expect(screen.getByText("Containers")).toBeInTheDocument(); - expect(screen.getByText("MCP")).toBeInTheDocument(); + expect(screen.getByText("Images")).toBeInTheDocument(); expect(screen.getByText("Settings")).toBeInTheDocument(); }); @@ -184,29 +184,29 @@ describe("StatusBar", () => { it("shows disconnected status by default", () => { render(); - expect(screen.getByText("未连接")).toBeInTheDocument(); + expect(screen.getByText("Not Connected")).toBeInTheDocument(); }); it("shows engine ready when docker connected", () => { useAppStore.setState({ dockerConnected: true, runtimeStatus: "running" }); render(); - expect(screen.getByText("引擎就绪")).toBeInTheDocument(); + expect(screen.getByText("Engine Ready")).toBeInTheDocument(); }); it("shows engine ready when docker connected regardless of runtimeStatus", () => { useAppStore.setState({ dockerConnected: true, runtimeStatus: "stopped" }); render(); - expect(screen.getByText("引擎就绪")).toBeInTheDocument(); + expect(screen.getByText("Engine Ready")).toBeInTheDocument(); }); it("shows starting when runtime is starting", () => { useAppStore.setState({ runtimeStatus: "starting" }); render(); - expect(screen.getByText("启动中…")).toBeInTheDocument(); + expect(screen.getByText("Engine Starting...")).toBeInTheDocument(); }); it("shows version number", () => { render(); - expect(screen.getByText("v2.0.0")).toBeInTheDocument(); + expect(screen.getByText("v0.9.0")).toBeInTheDocument(); }); }); diff --git a/crates/cratebay-gui/src/components/chat/ChatInput.tsx b/crates/cratebay-gui/src/components/chat/ChatInput.tsx index 5e97064..95f2f21 100644 --- a/crates/cratebay-gui/src/components/chat/ChatInput.tsx +++ b/crates/cratebay-gui/src/components/chat/ChatInput.tsx @@ -64,13 +64,34 @@ export function ChatInput({ onSend, onStop, disabled, placeholder }: ChatInputPr const mcpServers = useMcpStore((s) => s.servers); const mcpTools = useMcpStore((s) => s.availableTools); + const providers = useSettingsStore((s) => s.providers); + const allEnabledModels = useMemo(() => enabledModels(), [enabledModels]); const activeModelName = useMemo(() => { if (activeModelId === null) return t("chat", "selectModel"); const model = allEnabledModels.find((m) => m.id === activeModelId); - return model?.name ?? t("chat", "selectModel"); + return model?.name ?? model?.id ?? t("chat", "selectModel"); }, [activeModelId, allEnabledModels]); + // Group enabled models by provider + const groupedModels = useMemo(() => { + const groups: { provider: { id: string; name: string }; models: typeof allEnabledModels }[] = []; + const providerMap = new Map(); + for (const model of allEnabledModels) { + const list = providerMap.get(model.providerId) ?? []; + list.push(model); + providerMap.set(model.providerId, list); + } + for (const [providerId, models] of providerMap) { + const provider = providers.find((p) => p.id === providerId); + groups.push({ + provider: { id: providerId, name: provider?.name ?? providerId }, + models, + }); + } + return groups; + }, [allEnabledModels, providers]); + const mentionItems: MentionItem[] = useMemo(() => { const items: MentionItem[] = []; @@ -348,32 +369,47 @@ export function ChatInput({ onSend, onStop, disabled, placeholder }: ChatInputPr - {/* Model dropdown */} - {modelDropdownOpen && allEnabledModels.length > 0 && ( -
- {allEnabledModels.map((model) => ( - + {/* Model dropdown — grouped by provider */} + {modelDropdownOpen && groupedModels.length > 0 && ( +
+ {groupedModels.map((group) => ( +
+
+ {group.provider.name} +
+ {group.models.map((model) => ( + + ))} +
))}
)} + {/* Empty state */} + {modelDropdownOpen && groupedModels.length === 0 && ( +
+

+ No models available. Add a provider in Settings and fetch models. +

+
+ )}
diff --git a/crates/cratebay-gui/src/components/chat/MessageBubble.tsx b/crates/cratebay-gui/src/components/chat/MessageBubble.tsx index a2cc51e..36212cd 100644 --- a/crates/cratebay-gui/src/components/chat/MessageBubble.tsx +++ b/crates/cratebay-gui/src/components/chat/MessageBubble.tsx @@ -4,8 +4,8 @@ import { useI18n } from "@/lib/i18n"; import { User, Bot } from "lucide-react"; import { Streamdown } from "streamdown"; import type { ChatMessage } from "@/types/chat"; -import { AgentThinking } from "./AgentThinking"; -import { ToolCallCard } from "./ToolCallCard"; +import { ThinkingBlock } from "./ThinkingBlock"; +import { ToolCallItem } from "./ToolCallItem"; interface MessageBubbleProps { message: ChatMessage; @@ -15,7 +15,7 @@ interface MessageBubbleProps { /** * Single message bubble with Streamdown rendering for assistant messages. - * Includes agent thinking display and tool call cards. + * Includes ThinkingBlock and ToolCallItem components. * * Visual design: * - User messages: right-aligned, purple translucent bg, rounded-2xl with tr-sm @@ -75,25 +75,25 @@ export function MessageBubble({ message, isThinking, thinkingContent }: MessageB {/* Assistant message: structured content */} {!isUser && (
- {/* Agent thinking / reasoning */} + {/* Thinking block — replaces AgentThinking */} {isAssistant && message.reasoning !== undefined && ( - )} {isAssistant && isThinking === true && thinkingContent !== undefined && message.reasoning === undefined && ( - )} - {/* Tool call cards */} + {/* Tool call items — replaces ToolCallCard */} {message.toolCalls !== undefined && message.toolCalls.length > 0 && ( -
+
{message.toolCalls.map((tc) => ( - + ))}
)} diff --git a/crates/cratebay-gui/src/components/chat/MessageList.tsx b/crates/cratebay-gui/src/components/chat/MessageList.tsx index 8e9c903..aa54ea1 100644 --- a/crates/cratebay-gui/src/components/chat/MessageList.tsx +++ b/crates/cratebay-gui/src/components/chat/MessageList.tsx @@ -3,22 +3,22 @@ import { useChatStore } from "@/stores/chatStore"; import { useI18n } from "@/lib/i18n"; import { ScrollArea } from "@/components/ui/scroll-area"; import { MessageBubble } from "./MessageBubble"; -import { Box, Database, Plug, Rocket } from "lucide-react"; +import { Code, Server, TerminalSquare, Cog } from "lucide-react"; import type { LucideIcon } from "lucide-react"; const EMPTY_MESSAGES: never[] = []; interface Suggestion { icon: LucideIcon; - titleKey: "suggestionCreateContainer" | "suggestionQueryDb" | "suggestionManageMcp" | "suggestionDeploy"; - descKey: "suggestionCreateContainerDesc" | "suggestionQueryDbDesc" | "suggestionManageMcpDesc" | "suggestionDeployDesc"; + titleKey: "suggestionPythonAnalysis" | "suggestionNodeServer" | "suggestionBashSystem" | "suggestionRustSort"; + descKey: "suggestionPythonAnalysisDesc" | "suggestionNodeServerDesc" | "suggestionBashSystemDesc" | "suggestionRustSortDesc"; } const suggestions: Suggestion[] = [ - { icon: Box, titleKey: "suggestionCreateContainer", descKey: "suggestionCreateContainerDesc" }, - { icon: Database, titleKey: "suggestionQueryDb", descKey: "suggestionQueryDbDesc" }, - { icon: Plug, titleKey: "suggestionManageMcp", descKey: "suggestionManageMcpDesc" }, - { icon: Rocket, titleKey: "suggestionDeploy", descKey: "suggestionDeployDesc" }, + { icon: Code, titleKey: "suggestionPythonAnalysis", descKey: "suggestionPythonAnalysisDesc" }, + { icon: Server, titleKey: "suggestionNodeServer", descKey: "suggestionNodeServerDesc" }, + { icon: TerminalSquare, titleKey: "suggestionBashSystem", descKey: "suggestionBashSystemDesc" }, + { icon: Cog, titleKey: "suggestionRustSort", descKey: "suggestionRustSortDesc" }, ]; function CrateBayLogo({ size = 64 }: { size?: number }) { diff --git a/crates/cratebay-gui/src/components/chat/SandboxBar.tsx b/crates/cratebay-gui/src/components/chat/SandboxBar.tsx new file mode 100644 index 0000000..ffecefb --- /dev/null +++ b/crates/cratebay-gui/src/components/chat/SandboxBar.tsx @@ -0,0 +1,50 @@ +import { Box } from "lucide-react"; + +interface SandboxBarProps { + sandboxId: string; + language?: string; + status: "running" | "stopped" | "unknown"; +} + +/** + * Compact bar showing the sandbox bound to the current chat session. + * Placed above the message list. + */ +export function SandboxBar({ sandboxId, language, status }: SandboxBarProps) { + const shortId = sandboxId.length > 12 ? sandboxId.slice(0, 12) : sandboxId; + + const statusColor = + status === "running" + ? "bg-emerald-500" + : status === "stopped" + ? "bg-zinc-400" + : "bg-yellow-400"; + + const statusLabel = + status === "running" + ? "Running" + : status === "stopped" + ? "Stopped" + : "Unknown"; + + return ( +
+ + + Sandbox + + {shortId} + + {language && ( + + {language} + + )} + +
+ + {statusLabel} +
+
+ ); +} diff --git a/crates/cratebay-gui/src/components/chat/ThinkingBlock.tsx b/crates/cratebay-gui/src/components/chat/ThinkingBlock.tsx new file mode 100644 index 0000000..671d3cd --- /dev/null +++ b/crates/cratebay-gui/src/components/chat/ThinkingBlock.tsx @@ -0,0 +1,64 @@ +import { useState, useEffect, useRef } from "react"; +import { useI18n } from "@/lib/i18n"; +import { Sparkles, ChevronRight } from "lucide-react"; + +interface ThinkingBlockProps { + content: string; + isActive: boolean; +} + +/** + * Collapsible thinking/reasoning block. + * + * - Auto-opens while streaming (isActive=true) + * - Once the user manually collapses it, stays collapsed even during streaming + * - Sparkles icon + "Thinking..." label + */ +export function ThinkingBlock({ content, isActive }: ThinkingBlockProps) { + const { t } = useI18n(); + const [isOpen, setIsOpen] = useState(isActive); + const userInteractedRef = useRef(false); + + // Auto-open during streaming, but respect user's manual collapse + useEffect(() => { + if (!userInteractedRef.current && isActive) { + setIsOpen(true); + } + }, [isActive]); + + if (!/\S/.test(content || "")) return null; + + return ( +
+ + + {isOpen && ( +
+
+            {content}
+          
+
+ )} +
+ ); +} diff --git a/crates/cratebay-gui/src/components/chat/ToolCallItem.tsx b/crates/cratebay-gui/src/components/chat/ToolCallItem.tsx new file mode 100644 index 0000000..078f2f6 --- /dev/null +++ b/crates/cratebay-gui/src/components/chat/ToolCallItem.tsx @@ -0,0 +1,216 @@ +import { useState } from "react"; +import { useI18n } from "@/lib/i18n"; +import type { ToolCallInfo } from "@/types/chat"; +import { Terminal, Wrench, ChevronRight } from "lucide-react"; + +function safeStringify(value: unknown): string { + try { + return JSON.stringify(value, null, 2); + } catch { + return String(value); + } +} + +function previewText(text: string, maxLen: number): string { + if (text.length <= maxLen) return text; + return text.slice(0, maxLen) + "\n…(truncated)"; +} + +interface ToolCallItemProps { + toolCall: ToolCallInfo; +} + +/** + * A single tool call card with compact header and collapsible detail. + * + * - Status dot: running=yellow pulse, success=green, error=red, pending=gray + * - Bash/shell commands show the command inline in the header + * - Other tools show the tool name + * - Collapsible via native
element + */ +export function ToolCallItem({ toolCall }: ToolCallItemProps) { + const { t } = useI18n(); + const [open, setOpen] = useState(false); + + const isBash = + toolCall.toolName === "Bash" || + toolCall.toolName === "bash" || + toolCall.toolName === "shell"; + + const bashCmd = + isBash && typeof toolCall.parameters?.command === "string" + ? toolCall.parameters.command.trim() + : ""; + const firstLine = bashCmd ? bashCmd.split("\n")[0] : ""; + + // Status dot color + const dotClass = + toolCall.status === "running" + ? "bg-yellow-400 animate-pulse" + : toolCall.status === "success" + ? "bg-emerald-500" + : toolCall.status === "error" + ? "bg-red-500" + : "bg-zinc-400"; + + // Status label + const statusLabel = + toolCall.status === "running" + ? t("chat", "toolExecuting") + : toolCall.status === "success" + ? t("chat", "toolCompleted") + : toolCall.status === "error" + ? t("chat", "toolFailed") + : t("chat", "toolPreparing"); + + // Status text color + const statusClass = + toolCall.status === "running" + ? "text-yellow-500" + : toolCall.status === "success" + ? "text-emerald-500" + : toolCall.status === "error" + ? "text-red-500" + : "text-muted-foreground"; + + // Duration + const duration = + toolCall.startedAt && toolCall.completedAt + ? (() => { + const ms = + new Date(toolCall.completedAt).getTime() - + new Date(toolCall.startedAt).getTime(); + return ms < 1000 ? `${ms}ms` : `${(ms / 1000).toFixed(1)}s`; + })() + : null; + + return ( +
+ setOpen((e.currentTarget as HTMLDetailsElement).open) + } + > + + {/* Status dot */} + + + {isBash ? ( + /* Bash: terminal icon + inline command */ +
+ + {firstLine ? ( + + $ + {firstLine.length > 56 ? ( + <> + {firstLine.slice(0, 56)} + + + ) : ( + firstLine + )} + {bashCmd.includes("\n") && ( + + +{bashCmd.split("\n").length - 1} lines + + )} + + ) : ( + + Bash + + )} +
+ ) : ( + /* Other tools: wrench icon + tool name + param summary */ +
+ + + {toolCall.toolLabel || toolCall.toolName} + + {!isBash && toolCall.parameters && Object.keys(toolCall.parameters).length > 0 && ( + + ({Object.keys(toolCall.parameters).join(", ")}) + + )} +
+ )} + + {/* Duration */} + {duration !== null && ( + + {duration} + + )} + + {/* Status label */} + + {statusLabel} + + + {/* Chevron */} + +
+ + {open && ( +
+ {/* Parameters / Command */} + {isBash && bashCmd ? ( +
+
+ Command +
+
+                $
+                {bashCmd}
+              
+
+ ) : ( +
+
+ {t("common", "parameters")} +
+
+                {safeStringify(toolCall.parameters)}
+              
+
+ )} + + {/* Result */} + {toolCall.status === "success" && toolCall.result !== undefined && ( +
+
+ {t("common", "result")} +
+
+                {previewText(
+                  typeof toolCall.result === "string"
+                    ? toolCall.result
+                    : safeStringify(toolCall.result),
+                  6000,
+                )}
+              
+
+ )} + + {/* Error */} + {toolCall.status === "error" && toolCall.error !== undefined && ( +
+
+ {t("common", "error")} +
+
+                {toolCall.error}
+              
+
+ )} +
+ )} +
+ ); +} diff --git a/crates/cratebay-gui/src/components/container/ContainerCard.tsx b/crates/cratebay-gui/src/components/container/ContainerCard.tsx index 4d74683..8c33504 100644 --- a/crates/cratebay-gui/src/components/container/ContainerCard.tsx +++ b/crates/cratebay-gui/src/components/container/ContainerCard.tsx @@ -30,10 +30,10 @@ export function ContainerCard({ container }: ContainerCardProps) { const isRunning = container.status === "running" || container.status === "paused"; const isStopped = container.status === "stopped" || - container.status === "exited" || - container.status === "created"; + container.status === "exited"; const isCreating = container.status === "creating" || + container.status === "created" || container.status === "restarting" || container.status === "removing"; const isError = container.status === "dead"; diff --git a/crates/cratebay-gui/src/components/container/ContainerCreate.tsx b/crates/cratebay-gui/src/components/container/ContainerCreate.tsx index 54cc143..18e22a5 100644 --- a/crates/cratebay-gui/src/components/container/ContainerCreate.tsx +++ b/crates/cratebay-gui/src/components/container/ContainerCreate.tsx @@ -13,16 +13,10 @@ import { } from "@/components/ui/dialog"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from "@/components/ui/select"; import { Plus, ChevronDown, Loader2 } from "lucide-react"; import { cn } from "@/lib/utils"; + /** * Format bytes to human-readable size string. */ @@ -35,7 +29,6 @@ function formatSize(bytes: number): string { export function ContainerCreate() { const { t } = useI18n(); const createContainer = useContainerStore((s) => s.createContainer); - const templates = useContainerStore((s) => s.templates); const images = useContainerStore((s) => s.images); const imagesLoading = useContainerStore((s) => s.imagesLoading); const fetchImages = useContainerStore((s) => s.fetchImages); @@ -44,7 +37,6 @@ export function ContainerCreate() { const [name, setName] = useState(""); const [image, setImage] = useState(""); const [imageDropdownOpen, setImageDropdownOpen] = useState(false); - const [templateId, setTemplateId] = useState(""); const [cpuCores, setCpuCores] = useState(2); const [memoryMb, setMemoryMb] = useState(2048); @@ -74,48 +66,31 @@ export function ContainerCreate() { return () => document.removeEventListener("mousedown", handleClickOutside); }, []); - // Flatten all image tags into a flat list and filter by search + // Build deduplicated image list: one entry per image, prefer non-cratebay tags const imageOptions = useMemo(() => { - const allTags: { tag: string; sizeBytes: number }[] = []; + const result: { tag: string; sizeBytes: number }[] = []; for (const img of images) { - for (const tag of img.repoTags) { - if (tag && tag !== ":") { - allTags.push({ tag, sizeBytes: img.sizeBytes }); - } - } + const validTags = img.repoTags.filter( + (tag) => tag && tag !== ":", + ); + if (validTags.length === 0) continue; + // Prefer the original upstream tag over cratebay-* alias + const preferred = validTags.find((t) => !t.startsWith("cratebay-")) ?? validTags[0]; + result.push({ tag: preferred, sizeBytes: img.sizeBytes }); } - // Sort: exact prefix match first, then alphabetical const query = image.trim().toLowerCase(); - if (query.length === 0) return allTags; - return allTags.filter( - (item) => item.tag.toLowerCase().includes(query), - ); + if (query.length === 0) return result; + return result.filter((item) => item.tag.toLowerCase().includes(query)); }, [images, image]); const resetForm = useCallback(() => { setName(""); setImage(""); setImageDropdownOpen(false); - setTemplateId(""); setCpuCores(2); setMemoryMb(2048); }, []); - const selectedTemplate = templates.find((tmpl) => tmpl.id === templateId); - - const handleTemplateChange = useCallback( - (id: string) => { - setTemplateId(id); - const tmpl = templates.find((t2) => t2.id === id); - if (tmpl) { - setImage(tmpl.image); - setCpuCores(tmpl.defaultCpuCores); - setMemoryMb(tmpl.defaultMemoryMb); - } - }, - [templates], - ); - const canCreate = image.trim().length > 0; const handleCreate = useCallback(() => { @@ -124,19 +99,15 @@ export function ContainerCreate() { const req: ContainerCreateRequest = { name: trimmedName || `cratebay-${Date.now().toString(36)}`, image: image.trim(), - templateId: templateId || undefined, cpuCores, memoryMb, autoStart: true, }; - if (selectedTemplate?.defaultCommand?.trim()) { - req.command = selectedTemplate.defaultCommand.trim(); - } // Fire-and-forget: close dialog immediately, store handles optimistic update void createContainer(req); resetForm(); setOpen(false); - }, [canCreate, templateId, name, image, cpuCores, memoryMb, selectedTemplate, createContainer, resetForm]); + }, [canCreate, name, image, cpuCores, memoryMb, createContainer, resetForm]); return ( { setOpen(v); if (!v) resetForm(); }}> @@ -146,7 +117,7 @@ export function ContainerCreate() { {t("containers", "create")} - + {t("containers", "create")} @@ -154,26 +125,7 @@ export function ContainerCreate() { -
- {/* Template */} - {templates.length > 0 && ( -
- - -
- )} - +
{/* Name */}
@@ -187,7 +139,7 @@ export function ContainerCreate() { {/* Image — searchable dropdown with local images */}
- +
setImageDropdownOpen(true)} - placeholder={selectedTemplate?.image ?? "ubuntu:latest"} + placeholder={t("containers", "selectImage")} className="pr-8" autoComplete="off" /> @@ -221,7 +173,7 @@ export function ContainerCreate() { {imageDropdownOpen && imageOptions.length > 0 && (
{imageOptions.map((item) => (