From 8acad5ff916573248749292602873e2413e82a4c Mon Sep 17 00:00:00 2001 From: "yanan.zhangyn" Date: Mon, 10 Aug 2026 12:56:19 +0800 Subject: [PATCH] feat(studio): add managed Harness Sidecar integration --- .../harness-sidecar-release-gate.yaml | 82 + .github/workflows/publish-studio-release.yaml | 7 + .github/workflows/publish-tag-to-pypi.yaml | 4 + .../workflows/push-preview-image-to-vecr.yaml | 7 +- .../workflows/push-stable-image-to-vecr.yaml | 7 +- .gitignore | 1 + frontend/README.md | 7 +- frontend/package-lock.json | 1858 ++++++++++++++++- frontend/package.json | 5 +- frontend/src/adk/client.ts | 8 +- frontend/src/create/CustomCreate.css | 110 +- frontend/src/create/CustomCreate.tsx | 215 +- frontend/src/create/configYaml.ts | 13 +- frontend/src/create/harnessSidecarOptions.ts | 144 ++ frontend/src/create/normalizeDraft.ts | 45 + frontend/src/create/types.ts | 19 + frontend/src/ui/ProjectPreview.tsx | 46 +- frontend/src/ui/Sidebar.tsx | 14 +- frontend/tests/deploymentEnv.test.mjs | 2 +- frontend/tests/harnessSidecarCoverage.test.ts | 168 ++ frontend/tests/harnessSidecarOptions.test.mjs | 290 +++ frontend/tests/markdownPromptEditor.test.mjs | 21 +- frontend/tests/myAgents.test.mjs | 11 + frontend/tests/runtimeScalingDeploy.test.mjs | 14 +- frontend/tests/studioAccess.test.mjs | 2 +- frontend/vitest.harness-sidecar.config.ts | 18 + pyproject.toml | 5 + ...enerated_agent_backend_codegen_extended.py | 128 +- .../test_generated_agent_harness_sidecar.py | 113 + tests/cli/test_studio_rbac.py | 193 ++ .../sidecar_runtime/test_component_catalog.py | 200 ++ .../harness/sidecar_runtime/test_deploy.py | 177 ++ .../sidecar_runtime/test_failover_proxy.py | 86 + .../harness/sidecar_runtime/test_sidecar.py | 563 +++++ .../sidecar_runtime/test_sidecar_config.py | 400 ++++ tests/extensions/harness/test_extension.py | 10 + .../harness/test_sidecar_public_api.py | 399 ++++ .../extensions/harness/test_sidecar_wheel.py | 141 ++ .../extensions/harness/test_studio_sidecar.py | 336 +++ tests/integrations/agentkit/test_app.py | 45 +- veadk/cli/cli_frontend.py | 1086 +++++++++- veadk/cli/generated_agent_codegen.py | 151 +- veadk/cli/generated_agent_test_runner.py | 26 +- veadk/extensions/harness/__init__.py | 75 + veadk/extensions/harness/extension.py | 110 +- veadk/extensions/harness/sidecar.py | 651 ++++++ .../harness/sidecar_runtime/__init__.py | 93 + .../sidecar_runtime/component_catalog.py | 246 +++ .../harness/sidecar_runtime/deploy.py | 203 ++ .../harness/sidecar_runtime/failover_proxy.py | 176 ++ .../harness/sidecar_runtime/profiles.py | 156 ++ .../sidecar_runtime/runtime_components.py | 125 ++ .../sidecar_runtime/runtime_gateway_proxy.py | 214 ++ .../harness/sidecar_runtime/selection.py | 307 +++ .../harness/sidecar_runtime/sidecar.py | 518 +++++ .../harness/sidecar_runtime/sidecar_config.py | 437 ++++ veadk/integrations/agentkit/app.py | 124 +- ...2H.js => MarkdownPromptEditor-C6gQ7e_q.js} | 2 +- ...{index-DCJLnNdm.css => index-CxqWexEm.css} | 2 +- .../{index-Bg99KZ8e.js => index-Dm4tIGbB.js} | 522 ++--- veadk/webui/index.html | 4 +- 61 files changed, 10613 insertions(+), 529 deletions(-) create mode 100644 .github/workflows/harness-sidecar-release-gate.yaml create mode 100644 frontend/src/create/harnessSidecarOptions.ts create mode 100644 frontend/tests/harnessSidecarCoverage.test.ts create mode 100644 frontend/tests/harnessSidecarOptions.test.mjs create mode 100644 frontend/vitest.harness-sidecar.config.ts create mode 100644 tests/cli/test_generated_agent_harness_sidecar.py create mode 100644 tests/extensions/harness/sidecar_runtime/test_component_catalog.py create mode 100644 tests/extensions/harness/sidecar_runtime/test_deploy.py create mode 100644 tests/extensions/harness/sidecar_runtime/test_failover_proxy.py create mode 100644 tests/extensions/harness/sidecar_runtime/test_sidecar.py create mode 100644 tests/extensions/harness/sidecar_runtime/test_sidecar_config.py create mode 100644 tests/extensions/harness/test_sidecar_public_api.py create mode 100644 tests/extensions/harness/test_sidecar_wheel.py create mode 100644 tests/extensions/harness/test_studio_sidecar.py create mode 100644 veadk/extensions/harness/sidecar.py create mode 100644 veadk/extensions/harness/sidecar_runtime/__init__.py create mode 100644 veadk/extensions/harness/sidecar_runtime/component_catalog.py create mode 100644 veadk/extensions/harness/sidecar_runtime/deploy.py create mode 100644 veadk/extensions/harness/sidecar_runtime/failover_proxy.py create mode 100644 veadk/extensions/harness/sidecar_runtime/profiles.py create mode 100644 veadk/extensions/harness/sidecar_runtime/runtime_components.py create mode 100644 veadk/extensions/harness/sidecar_runtime/runtime_gateway_proxy.py create mode 100644 veadk/extensions/harness/sidecar_runtime/selection.py create mode 100644 veadk/extensions/harness/sidecar_runtime/sidecar.py create mode 100644 veadk/extensions/harness/sidecar_runtime/sidecar_config.py rename veadk/webui/assets/{MarkdownPromptEditor-BZZjAY2H.js => MarkdownPromptEditor-C6gQ7e_q.js} (99%) rename veadk/webui/assets/{index-DCJLnNdm.css => index-CxqWexEm.css} (79%) rename veadk/webui/assets/{index-Bg99KZ8e.js => index-Dm4tIGbB.js} (58%) diff --git a/.github/workflows/harness-sidecar-release-gate.yaml b/.github/workflows/harness-sidecar-release-gate.yaml new file mode 100644 index 000000000..518125f3d --- /dev/null +++ b/.github/workflows/harness-sidecar-release-gate.yaml @@ -0,0 +1,82 @@ +name: Harness Sidecar Release Gate + +on: + workflow_call: + push: + paths: + - '.github/workflows/harness-sidecar-release-gate.yaml' + - 'frontend/**' + - 'tests/cli/test_generated_agent_harness_sidecar.py' + - 'tests/cli/test_generated_agent_backend_codegen_extended.py' + - 'tests/cli/test_studio_rbac.py' + - 'tests/extensions/harness/**' + - 'tests/integrations/agentkit/test_app.py' + - 'veadk/cli/generated_agent_codegen.py' + - 'veadk/cli/cli_frontend.py' + - 'veadk/extensions/harness/**' + - 'veadk/integrations/agentkit/app.py' + - 'pyproject.toml' + pull_request: + paths: + - '.github/workflows/harness-sidecar-release-gate.yaml' + - 'frontend/**' + - 'tests/cli/test_generated_agent_harness_sidecar.py' + - 'tests/cli/test_generated_agent_backend_codegen_extended.py' + - 'tests/cli/test_studio_rbac.py' + - 'tests/extensions/harness/**' + - 'tests/integrations/agentkit/test_app.py' + - 'veadk/cli/generated_agent_codegen.py' + - 'veadk/cli/cli_frontend.py' + - 'veadk/extensions/harness/**' + - 'veadk/integrations/agentkit/app.py' + - 'pyproject.toml' + +permissions: + contents: read + +jobs: + gate: + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: '3.12' + + - uses: actions/setup-node@v4 + with: + node-version: 22.17.0 + cache: npm + cache-dependency-path: frontend/package-lock.json + + - name: Install Python test dependencies + run: python -m pip install -e '.[dev]' + + - name: Enforce public Python Sidecar coverage above 90 percent + run: | + python -m pytest -q \ + tests/extensions/harness/test_studio_sidecar.py \ + tests/extensions/harness/test_sidecar_public_api.py \ + tests/extensions/harness/test_extension.py \ + tests/cli/test_generated_agent_harness_sidecar.py \ + tests/integrations/agentkit/test_app.py \ + tests/cli/test_studio_rbac.py::test_sidecar_deployment_uses_agentkit_cli_structured_release \ + tests/cli/test_generated_agent_backend_codegen_extended.py::test_generated_agent_sidecar_debug_uses_runtime_apig_and_active_plan \ + --cov=. --cov-branch --cov-report= --cov-fail-under=0 + python -m coverage report \ + --include='*/veadk/extensions/harness/sidecar.py' \ + --fail-under=91 --show-missing + + - name: Install frontend dependencies + working-directory: frontend + run: npm ci --ignore-scripts + + - name: Enforce public Studio Sidecar coverage above 90 percent + working-directory: frontend + run: npm run test:harness-sidecar-coverage + + - name: Verify frontend Sidecar integration + working-directory: frontend + run: npm test diff --git a/.github/workflows/publish-studio-release.yaml b/.github/workflows/publish-studio-release.yaml index 1a1cb2f18..4a1233b81 100644 --- a/.github/workflows/publish-studio-release.yaml +++ b/.github/workflows/publish-studio-release.yaml @@ -39,10 +39,17 @@ concurrency: cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: + harness-sidecar-release-gate: + if: >- + github.repository == 'volcengine/veadk-python' && + (github.event_name == 'pull_request' || github.ref == 'refs/heads/main') + uses: ./.github/workflows/harness-sidecar-release-gate.yaml + verify: if: >- github.repository == 'volcengine/veadk-python' && (github.event_name == 'pull_request' || github.ref == 'refs/heads/main') + needs: harness-sidecar-release-gate runs-on: ubuntu-latest timeout-minutes: 45 diff --git a/.github/workflows/publish-tag-to-pypi.yaml b/.github/workflows/publish-tag-to-pypi.yaml index d820bfc01..43825078c 100644 --- a/.github/workflows/publish-tag-to-pypi.yaml +++ b/.github/workflows/publish-tag-to-pypi.yaml @@ -5,7 +5,11 @@ on: workflow_dispatch: jobs: + harness-sidecar-release-gate: + uses: ./.github/workflows/harness-sidecar-release-gate.yaml + build: + needs: harness-sidecar-release-gate runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/push-preview-image-to-vecr.yaml b/.github/workflows/push-preview-image-to-vecr.yaml index fec65e142..6f52cb72d 100644 --- a/.github/workflows/push-preview-image-to-vecr.yaml +++ b/.github/workflows/push-preview-image-to-vecr.yaml @@ -24,7 +24,12 @@ on: workflow_dispatch: jobs: + harness-sidecar-release-gate: + if: github.repository == 'volcengine/veadk-python' + uses: ./.github/workflows/harness-sidecar-release-gate.yaml + build-and-push: + needs: harness-sidecar-release-gate runs-on: ubuntu-latest # To avoid forked repo execute this workflow @@ -64,4 +69,4 @@ jobs: --push \ --cache-from=type=gha \ --cache-to=type=gha,mode=max \ - . \ No newline at end of file + . diff --git a/.github/workflows/push-stable-image-to-vecr.yaml b/.github/workflows/push-stable-image-to-vecr.yaml index a30e1b65f..e30e8cceb 100644 --- a/.github/workflows/push-stable-image-to-vecr.yaml +++ b/.github/workflows/push-stable-image-to-vecr.yaml @@ -22,7 +22,12 @@ on: workflow_dispatch: jobs: + harness-sidecar-release-gate: + if: github.repository == 'volcengine/veadk-python' + uses: ./.github/workflows/harness-sidecar-release-gate.yaml + build-and-push: + needs: harness-sidecar-release-gate runs-on: ubuntu-latest permissions: contents: read @@ -67,4 +72,4 @@ jobs: --push \ --cache-from=type=gha \ --cache-to=type=gha,mode=max \ - . \ No newline at end of file + . diff --git a/.gitignore b/.gitignore index d8d1ecd12..2f08d84b3 100644 --- a/.gitignore +++ b/.gitignore @@ -45,6 +45,7 @@ htmlcov/ .cache nosetests.xml coverage.xml +coverage/ *.cover *.py,cover .hypothesis/ diff --git a/frontend/README.md b/frontend/README.md index 2673d87a3..9c3481ea9 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -104,7 +104,12 @@ server that `veadk frontend` launches — no separate backend. - **Custom-agent workbench**: configure an agent with a rich Markdown system-prompt editor (including heading and list shortcuts), then debug with expandable, copyable runner error details, per-result Trace inspection, and - review. In-progress drafts are stored only in the current browser and scoped + review. Test configurations expose Harness Sidecar as `优化场景`: `自定义` + appears first and starts with no components, while `运维场景` applies the + `ops` component combination. Component checkboxes remain editable, an empty + selection keeps Sidecar disabled, and the UI explains the operations + scenario's automatic SQL read-only protection. In-progress drafts are stored only in the + current browser and scoped to the signed-in user. MCP tokens are converted to Runtime environment variables: generated source retains only the `${ENV_NAME}` reference, while YAML and browser drafts preserve the corresponding environment value. diff --git a/frontend/package-lock.json b/frontend/package-lock.json index b5ad99f10..20b83ed09 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -36,10 +36,12 @@ "@types/react": "^19.2.18", "@types/react-dom": "^19.2.4", "@vitejs/plugin-react": "^4.3.4", + "@vitest/coverage-v8": "^4.1.9", "esbuild": "^0.21.3", "tailwindcss": "^4.3.3", "typescript": "^5.6.3", - "vite": "^5.4.11" + "vite": "^5.4.11", + "vitest": "^4.1.9" } }, "node_modules/@apmplus/web": { @@ -339,6 +341,16 @@ "node": ">=6.9.0" } }, + "node_modules/@bcoe/v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-1.0.2.tgz", + "integrity": "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/@codemirror/autocomplete": { "version": "6.20.3", "resolved": "https://registry.npmmirror.com/@codemirror/autocomplete/-/autocomplete-6.20.3.tgz", @@ -1069,6 +1081,24 @@ "node": ">=12" } }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz", + "integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, "node_modules/@esbuild/netbsd-x64": { "version": "0.21.5", "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", @@ -1086,6 +1116,24 @@ "node": ">=12" } }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz", + "integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, "node_modules/@esbuild/openbsd-x64": { "version": "0.21.5", "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", @@ -1103,6 +1151,24 @@ "node": ">=12" } }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz", + "integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, "node_modules/@esbuild/sunos-x64": { "version": "0.21.5", "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", @@ -2053,6 +2119,16 @@ "tailwindcss": "^4.0.10" } }, + "node_modules/@oxc-project/types": { + "version": "0.143.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.143.0.tgz", + "integrity": "sha512-u6JZdLBTLotrNC9Vd6vPssINdzcCzleKAH6EJKImQb7GtYvX5keN2dxkoK44stCc4tffE6QQRtZTXVSzsLUlWA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, "node_modules/@preact/signals-core": { "version": "1.14.4", "resolved": "https://registry.npmmirror.com/@preact/signals-core/-/signals-core-1.14.4.tgz", @@ -3574,6 +3650,244 @@ "integrity": "sha512-JtyZR+mqgBibTo8xea3B6ZRmzZiM/YeVBtUkas6zMuXjAlfIFIW2FgqeM9eLyvEaYX66vr6DJMK+4U6LV0KhNw==", "license": "MIT" }, + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.3.tgz", + "integrity": "sha512-zrJtHDcaZJ1Fp7xf4hNl+7seH9Cn/N5TwLYkhgXREtBwAd/jaqW3uqeHxpDugJLVICWg4eW44kOQEGJ1r6jCGw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.3.tgz", + "integrity": "sha512-ieIiibVCp0tX7TLu2cafoNPv8wJyYi01ekXpbf8q2j7F4rGAhhXb/eQh7ge9DRBY78GwmRQtvjZDux7EDbA8kA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.3.tgz", + "integrity": "sha512-Zh9tCon19eDXJoihx0rqKhMUlMYqzwj3aPsSuHmI4RWZh62dWUL+DJN4C5YQya5TcQBJU/Fe8+rY0jhXTQITqA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.3.tgz", + "integrity": "sha512-nGbJWewA1wrXXZiQhjAT5rhibGfns5ZNkDVqxsO6zJ3f3YvpoDNNmGMSbbhLuXKjNScaBJVOAboztAWVespQMg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.3.tgz", + "integrity": "sha512-QNniJr5Kml0kDEB98jiDOJjXNroxIIi0IXIbdYzY26Xt1pVbeP62+KnoIZLwirOymX/0jDk/2gI/bNUv7A7OIw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.3.tgz", + "integrity": "sha512-TkqEAcmmvH3I/q4114NB4RVt6241Dao48pF45uLcFGrwAaIn0iITgTAKP/dLjbN0R4buJjGb91+UHSoFmpgIWw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.3.tgz", + "integrity": "sha512-NHqjnxpsndf4MPymxteFAWHHfkTL8HjWh1KB7z23ofZ6QO2euONuxDXjat69dKZRALnGypg8k8SsK8vZJoXv1Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.3.tgz", + "integrity": "sha512-6tbrbwfz5GB9DQ4Jwo6hy9v+vR31xZlvzZ6n5Xut6Hhx5PvrA9q/HsK8KMaYQp063iqZGXwNvZtYNLD7EM/x0w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.3.tgz", + "integrity": "sha512-oyuXxXmoZHjXC917IAPFAAv4wWAa0cM9afk8nx1+9/jNNOX1uPf8yDA6p7G0RypOfw/X0PQt5IfoquY1um+zSg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.3.tgz", + "integrity": "sha512-TytMwF2KVGqP2tgd0I1OY0PAv78dZRAYcF5ssDzjM34SUXCED3uXvSd5+lHoC0bTD6eEdFz7LdQNCO1y0oVk9w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.3.tgz", + "integrity": "sha512-/E9m3qstrJFVPoULV25mVQblSNExY2+kBsYe4sy0Tn0yOOgJ8wZbZt3KnRbF/XeU2Gl1STKUQnDNTqhIE5MD4A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.3.tgz", + "integrity": "sha512-Kr0OcsoQI816i6HOl3vFHpd1K0eZyh76zgfj4c1nTyaTsd5r2Mj1lwM4R90y/qaCfmTn9eHy0SKwi98eitRxug==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.3.tgz", + "integrity": "sha512-hOtMwTqnME+/gJcH/PCZ0wn0zPUjiWOgkHpxbSJpfGKMezHltx1S7/k1SitzVa7Ww2cqrDDaFbZEhcJZO8o+Jw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.3.tgz", + "integrity": "sha512-ekcqMMkI2PlhYnfzQnB/cEdYUVVJViWvoUyLrbzgDoi3Snfc1mVBwdnc306ufA5ejy8JSPjT2RlW1nQSjW7efg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, "node_modules/@rolldown/pluginutils": { "version": "1.0.0-beta.27", "resolved": "https://registry.npmmirror.com/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", @@ -3931,6 +4245,13 @@ "win32" ] }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "dev": true, + "license": "MIT" + }, "node_modules/@tailwindcss/node": { "version": "4.3.3", "resolved": "https://registry.npmmirror.com/@tailwindcss/node/-/node-4.3.3.tgz", @@ -4154,25 +4475,91 @@ "node": ">=14.0.0" } }, - "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { - "version": "4.3.3", - "resolved": "https://registry.npmmirror.com/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.3.tgz", - "integrity": "sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==", - "cpu": [ - "arm64" - ], + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": { + "version": "1.11.1", "dev": true, + "inBundle": true, "license": "MIT", "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 20" + "dependencies": { + "@emnapi/wasi-threads": "1.2.2", + "tslib": "^2.4.0" } }, - "node_modules/@tailwindcss/oxide-win32-x64-msvc": { - "version": "4.3.3", + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": { + "version": "1.11.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/wasi-threads": { + "version": "1.2.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": { + "version": "1.1.4", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@tybys/wasm-util": "^0.10.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@tybys/wasm-util": { + "version": "0.10.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/tslib": { + "version": "2.8.1", + "dev": true, + "inBundle": true, + "license": "0BSD", + "optional": true + }, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.3.3", + "resolved": "https://registry.npmmirror.com/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.3.tgz", + "integrity": "sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.3.3", "resolved": "https://registry.npmmirror.com/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.3.tgz", "integrity": "sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw==", "cpu": [ @@ -4248,6 +4635,17 @@ "@babel/types": "^7.28.2" } }, + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" + } + }, "node_modules/@types/d3-color": { "version": "3.1.3", "resolved": "https://registry.npmmirror.com/@types/d3-color/-/d3-color-3.1.3.tgz", @@ -4306,6 +4704,13 @@ "@types/ms": "*" } }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.8.tgz", @@ -4468,6 +4873,123 @@ "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, + "node_modules/@vitest/coverage-v8": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.1.10.tgz", + "integrity": "sha512-IM49HmthevbgAO4anp1hwtoT9wYe59w0LR00gr+eagHE+ZJ5lK4sLPeO0ubgoJcwLk6dehU3R24N+FbEEKDc8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@bcoe/v8-coverage": "^1.0.2", + "@vitest/utils": "4.1.10", + "ast-v8-to-istanbul": "^1.0.0", + "istanbul-lib-coverage": "^3.2.2", + "istanbul-lib-report": "^3.0.1", + "istanbul-reports": "^3.2.0", + "magicast": "^0.5.2", + "obug": "^2.1.1", + "std-env": "^4.0.0-rc.1", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@vitest/browser": "4.1.10", + "vitest": "4.1.10" + }, + "peerDependenciesMeta": { + "@vitest/browser": { + "optional": true + } + } + }, + "node_modules/@vitest/expect": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.10.tgz", + "integrity": "sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.1.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.1.10", + "@vitest/utils": "4.1.10", + "chai": "^6.2.2", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/pretty-format": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.10.tgz", + "integrity": "sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.10.tgz", + "integrity": "sha512-IKI6kpIH+LmpROplyLwBBaCfMgOZOMsygVa6BARD6ahA04VRuJSa6OaVG7kRvSEMD870Vd91rSSw0eegtWyLGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "4.1.10", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.10.tgz", + "integrity": "sha512-xRkfOT1qpTAi/Ti4Y1LtfRc3kEuqxGw59eN2jN9pRWMtS/XDevekhcFSqvQqjUNGksfjMJu3Y+oJ+4Ypn2OaJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.10", + "@vitest/utils": "4.1.10", + "magic-string": "^0.30.21", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.10.tgz", + "integrity": "sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.10.tgz", + "integrity": "sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.10", + "convert-source-map": "^2.0.0", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, "node_modules/@xyflow/react": { "version": "12.11.0", "resolved": "https://registry.npmmirror.com/@xyflow/react/-/react-12.11.0.tgz", @@ -4549,6 +5071,35 @@ "node": ">=10" } }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/ast-v8-to-istanbul": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-1.0.5.tgz", + "integrity": "sha512-UPAgKJFSEGMWSDr3LX4tqnAb4f7KGT8O40Tyx8wbYmmZ/yn58lNCm8h3svs3eXgiGd5AXxz8NDOvXWvicq+rJA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.31", + "estree-walker": "^3.0.3", + "js-tokens": "^10.0.0" + } + }, + "node_modules/ast-v8-to-istanbul/node_modules/js-tokens": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-10.0.0.tgz", + "integrity": "sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==", + "dev": true, + "license": "MIT" + }, "node_modules/bail": { "version": "2.0.2", "resolved": "https://registry.npmmirror.com/bail/-/bail-2.0.2.tgz", @@ -4637,6 +5188,16 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/chai": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", + "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/character-entities": { "version": "2.0.2", "resolved": "https://registry.npmmirror.com/character-entities/-/character-entities-2.0.2.tgz", @@ -5000,6 +5561,13 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/es-module-lexer": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.1.tgz", + "integrity": "sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==", + "dev": true, + "license": "MIT" + }, "node_modules/esbuild": { "version": "0.21.5", "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.21.5.tgz", @@ -5085,6 +5653,26 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/expect-type": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.4.0.tgz", + "integrity": "sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmmirror.com/extend/-/extend-3.0.2.tgz", @@ -5104,6 +5692,24 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, "node_modules/format": { "version": "0.2.2", "resolved": "https://registry.npmmirror.com/format/-/format-0.2.2.tgz", @@ -5180,6 +5786,16 @@ "dev": true, "license": "ISC" }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/hast-util-from-dom": { "version": "5.0.1", "resolved": "https://registry.npmmirror.com/hast-util-from-dom/-/hast-util-from-dom-5.0.1.tgz", @@ -5407,6 +6023,13 @@ "integrity": "sha512-PDEfEF102G23vHmPhLyPboFCD+BkMGu+GuJe2d9/eH4FsCwvgBpnc9n0pGE+ffKdph38s6foEZiEjdgHdzp+IA==", "license": "CC0-1.0" }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true, + "license": "MIT" + }, "node_modules/html-url-attributes": { "version": "3.0.1", "resolved": "https://registry.npmmirror.com/html-url-attributes/-/html-url-attributes-3.0.1.tgz", @@ -5500,6 +6123,45 @@ "url": "https://github.com/sponsors/dmonad" } }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/jiti": { "version": "2.7.0", "resolved": "https://registry.npmmirror.com/jiti/-/jiti-2.7.0.tgz", @@ -5976,6 +6638,47 @@ "@jridgewell/sourcemap-codec": "^1.5.5" } }, + "node_modules/magicast": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.4.tgz", + "integrity": "sha512-llBEhWm1SacoRwgHUoQJYtwp4PBLF4faQi5TCpIGyGs9n4y5+juI0tDgyKIfpqxckRHaHzouUEph3THklWh03w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7", + "source-map-js": "^1.2.1" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/markdown-table": { "version": "3.0.4", "resolved": "https://registry.npmmirror.com/markdown-table/-/markdown-table-3.0.4.tgz", @@ -7196,9 +7899,9 @@ "license": "MIT" }, "node_modules/nanoid": { - "version": "3.3.12", - "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.12.tgz", - "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", + "version": "3.3.18", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz", + "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==", "dev": true, "funding": [ { @@ -7233,6 +7936,20 @@ "node": ">=0.10.0" } }, + "node_modules/obug": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.4.tgz", + "integrity": "sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==", + "dev": true, + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT", + "engines": { + "node": ">=12.20.0" + } + }, "node_modules/parse-entities": { "version": "4.0.2", "resolved": "https://registry.npmmirror.com/parse-entities/-/parse-entities-4.0.2.tgz", @@ -7270,6 +7987,13 @@ "url": "https://github.com/inikulin/parse5?sponsor=1" } }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz", @@ -7277,10 +8001,23 @@ "dev": true, "license": "ISC" }, + "node_modules/picomatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/postcss": { - "version": "8.5.15", - "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.15.tgz", - "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", + "version": "8.5.26", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz", + "integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==", "dev": true, "funding": [ { @@ -7298,7 +8035,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.12", + "nanoid": "^3.3.17", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -7824,8 +8561,48 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/rollup": { - "version": "4.60.4", + "node_modules/rolldown": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.3.tgz", + "integrity": "sha512-rn9wpmxplLf7NLNyCk9FyWh3FM43DbY8jOzCdEPzH7uflhTftRbCEpqi6Ly2osgoU8OwObtmavMbWLaWy4LX7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oxc-project/types": "=0.143.0", + "@rolldown/pluginutils": "^1.0.0" + }, + "bin": { + "rolldown": "bin/cli.mjs" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm64": "1.2.3", + "@rolldown/binding-darwin-arm64": "1.2.3", + "@rolldown/binding-darwin-x64": "1.2.3", + "@rolldown/binding-freebsd-x64": "1.2.3", + "@rolldown/binding-linux-arm-gnueabihf": "1.2.3", + "@rolldown/binding-linux-arm64-gnu": "1.2.3", + "@rolldown/binding-linux-arm64-musl": "1.2.3", + "@rolldown/binding-linux-ppc64-gnu": "1.2.3", + "@rolldown/binding-linux-s390x-gnu": "1.2.3", + "@rolldown/binding-linux-x64-gnu": "1.2.3", + "@rolldown/binding-linux-x64-musl": "1.2.3", + "@rolldown/binding-openharmony-arm64": "1.2.3", + "@rolldown/binding-win32-arm64-msvc": "1.2.3", + "@rolldown/binding-win32-x64-msvc": "1.2.3" + } + }, + "node_modules/rolldown/node_modules/@rolldown/pluginutils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", + "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", + "dev": true, + "license": "MIT" + }, + "node_modules/rollup": { + "version": "4.60.4", "resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.60.4.tgz", "integrity": "sha512-WHeFSbZYsPu3+bLoNRUuAO+wavNlocOPf3wSHTP7hcFKVnJeWsYlCDbr3mTS14FCizf9ccIxXA8sGL8zKeQN3g==", "dev": true, @@ -7897,6 +8674,13 @@ "semver": "bin/semver.js" } }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz", @@ -7917,6 +8701,20 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/std-env": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.2.0.tgz", + "integrity": "sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==", + "dev": true, + "license": "MIT" + }, "node_modules/stringify-entities": { "version": "4.0.4", "resolved": "https://registry.npmmirror.com/stringify-entities/-/stringify-entities-4.0.4.tgz", @@ -7955,6 +8753,19 @@ "inline-style-parser": "0.2.7" } }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/tabbable": { "version": "6.5.0", "resolved": "https://registry.npmmirror.com/tabbable/-/tabbable-6.5.0.tgz", @@ -7981,6 +8792,50 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.3.0.tgz", + "integrity": "sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyrainbow": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.1.tgz", + "integrity": "sha512-yau8yJdTt989Mm0Bd/236QnzEiPf2xLLTqUZRUJOo/3CB078LSwzei343DgtJVmfJKJE3TMINY1u42SQsP6mXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/trim-lines": { "version": "3.0.1", "resolved": "https://registry.npmmirror.com/trim-lines/-/trim-lines-3.0.1.tgz", @@ -8376,20 +9231,951 @@ } } }, - "node_modules/w3c-keyname": { - "version": "2.2.8", - "resolved": "https://registry.npmmirror.com/w3c-keyname/-/w3c-keyname-2.2.8.tgz", - "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", - "license": "MIT" - }, - "node_modules/web-namespaces": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", - "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==", + "node_modules/vitest": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.10.tgz", + "integrity": "sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw==", + "dev": true, "license": "MIT", + "dependencies": { + "@vitest/expect": "4.1.10", + "@vitest/mocker": "4.1.10", + "@vitest/pretty-format": "4.1.10", + "@vitest/runner": "4.1.10", + "@vitest/snapshot": "4.1.10", + "@vitest/spy": "4.1.10", + "@vitest/utils": "4.1.10", + "es-module-lexer": "^2.0.0", + "expect-type": "^1.3.0", + "magic-string": "^0.30.21", + "obug": "^2.1.1", + "pathe": "^2.0.3", + "picomatch": "^4.0.3", + "std-env": "^4.0.0-rc.1", + "tinybench": "^2.9.0", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.1.0", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" + }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.1.10", + "@vitest/browser-preview": "4.1.10", + "@vitest/browser-webdriverio": "4.1.10", + "@vitest/coverage-istanbul": "4.1.10", + "@vitest/coverage-v8": "4.1.10", + "@vitest/ui": "4.1.10", + "happy-dom": "*", + "jsdom": "*", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@opentelemetry/api": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser-playwright": { + "optional": true + }, + "@vitest/browser-preview": { + "optional": true + }, + "@vitest/browser-webdriverio": { + "optional": true + }, + "@vitest/coverage-istanbul": { + "optional": true + }, + "@vitest/coverage-v8": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + }, + "vite": { + "optional": false + } + } + }, + "node_modules/vitest/node_modules/@esbuild/aix-ppc64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz", + "integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vitest/node_modules/@esbuild/android-arm": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.2.tgz", + "integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vitest/node_modules/@esbuild/android-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz", + "integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vitest/node_modules/@esbuild/android-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.2.tgz", + "integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vitest/node_modules/@esbuild/darwin-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz", + "integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vitest/node_modules/@esbuild/darwin-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz", + "integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vitest/node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz", + "integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vitest/node_modules/@esbuild/freebsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz", + "integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vitest/node_modules/@esbuild/linux-arm": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz", + "integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vitest/node_modules/@esbuild/linux-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz", + "integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vitest/node_modules/@esbuild/linux-ia32": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz", + "integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vitest/node_modules/@esbuild/linux-loong64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz", + "integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vitest/node_modules/@esbuild/linux-mips64el": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz", + "integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vitest/node_modules/@esbuild/linux-ppc64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz", + "integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vitest/node_modules/@esbuild/linux-riscv64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz", + "integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vitest/node_modules/@esbuild/linux-s390x": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz", + "integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vitest/node_modules/@esbuild/linux-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz", + "integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vitest/node_modules/@esbuild/netbsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz", + "integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vitest/node_modules/@esbuild/openbsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz", + "integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vitest/node_modules/@esbuild/sunos-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz", + "integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vitest/node_modules/@esbuild/win32-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz", + "integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vitest/node_modules/@esbuild/win32-ia32": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz", + "integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vitest/node_modules/@esbuild/win32-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz", + "integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vitest/node_modules/@vitest/mocker": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.10.tgz", + "integrity": "sha512-v0xaezt+DKEmKfaxg133ldzADrwLGd7Ze1MfQQTYfvs8OqZIwbxyxaYURivwV7sWy5fqn3rH5uOrSp07bp44Ow==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "4.1.10", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.21" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/vitest/node_modules/esbuild": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz", + "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "peer": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.2", + "@esbuild/android-arm": "0.28.2", + "@esbuild/android-arm64": "0.28.2", + "@esbuild/android-x64": "0.28.2", + "@esbuild/darwin-arm64": "0.28.2", + "@esbuild/darwin-x64": "0.28.2", + "@esbuild/freebsd-arm64": "0.28.2", + "@esbuild/freebsd-x64": "0.28.2", + "@esbuild/linux-arm": "0.28.2", + "@esbuild/linux-arm64": "0.28.2", + "@esbuild/linux-ia32": "0.28.2", + "@esbuild/linux-loong64": "0.28.2", + "@esbuild/linux-mips64el": "0.28.2", + "@esbuild/linux-ppc64": "0.28.2", + "@esbuild/linux-riscv64": "0.28.2", + "@esbuild/linux-s390x": "0.28.2", + "@esbuild/linux-x64": "0.28.2", + "@esbuild/netbsd-arm64": "0.28.2", + "@esbuild/netbsd-x64": "0.28.2", + "@esbuild/openbsd-arm64": "0.28.2", + "@esbuild/openbsd-x64": "0.28.2", + "@esbuild/openharmony-arm64": "0.28.2", + "@esbuild/sunos-x64": "0.28.2", + "@esbuild/win32-arm64": "0.28.2", + "@esbuild/win32-ia32": "0.28.2", + "@esbuild/win32-x64": "0.28.2" + } + }, + "node_modules/vitest/node_modules/lightningcss": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.33.0.tgz", + "integrity": "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.33.0", + "lightningcss-darwin-arm64": "1.33.0", + "lightningcss-darwin-x64": "1.33.0", + "lightningcss-freebsd-x64": "1.33.0", + "lightningcss-linux-arm-gnueabihf": "1.33.0", + "lightningcss-linux-arm64-gnu": "1.33.0", + "lightningcss-linux-arm64-musl": "1.33.0", + "lightningcss-linux-x64-gnu": "1.33.0", + "lightningcss-linux-x64-musl": "1.33.0", + "lightningcss-win32-arm64-msvc": "1.33.0", + "lightningcss-win32-x64-msvc": "1.33.0" + } + }, + "node_modules/vitest/node_modules/lightningcss-android-arm64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz", + "integrity": "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/vitest/node_modules/lightningcss-darwin-arm64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz", + "integrity": "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/vitest/node_modules/lightningcss-darwin-x64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz", + "integrity": "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/vitest/node_modules/lightningcss-freebsd-x64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz", + "integrity": "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/vitest/node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz", + "integrity": "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/vitest/node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz", + "integrity": "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/vitest/node_modules/lightningcss-linux-arm64-musl": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz", + "integrity": "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/vitest/node_modules/lightningcss-linux-x64-gnu": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz", + "integrity": "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/vitest/node_modules/lightningcss-linux-x64-musl": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz", + "integrity": "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/vitest/node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz", + "integrity": "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/vitest/node_modules/lightningcss-win32-x64-msvc": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz", + "integrity": "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/vitest/node_modules/vite": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.2.1.tgz", + "integrity": "sha512-EU/eS7BH3XROHh2YnBefjM6DBKA6ZeMZEYQbj7NLWg5wHYlhB8B/Mayd5XsgWq+NFYccDOTemRpdETWR6Ka/lw==", + "dev": true, + "license": "MIT", + "dependencies": { + "lightningcss": "^1.33.0", + "picomatch": "^4.0.5", + "postcss": "^8.5.25", + "rolldown": "~1.2.1", + "tinyglobby": "^0.2.17" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "@vitejs/devtools": "^0.4.0", + "esbuild": "^0.27.0 || ^0.28.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "@vitejs/devtools": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/w3c-keyname": { + "version": "2.2.8", + "resolved": "https://registry.npmmirror.com/w3c-keyname/-/w3c-keyname-2.2.8.tgz", + "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", + "license": "MIT" + }, + "node_modules/web-namespaces": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", + "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" } }, "node_modules/yallist": { diff --git a/frontend/package.json b/frontend/package.json index 4f902b989..836e209d9 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -8,6 +8,7 @@ "dev": "vite", "build": "tsc && vite build", "test": "node --test tests/*.test.mjs", + "test:harness-sidecar-coverage": "vitest run --coverage -c vitest.harness-sidecar.config.ts", "preview": "vite preview" }, "dependencies": { @@ -42,6 +43,8 @@ "esbuild": "^0.21.3", "tailwindcss": "^4.3.3", "typescript": "^5.6.3", - "vite": "^5.4.11" + "@vitest/coverage-v8": "^4.1.9", + "vite": "^5.4.11", + "vitest": "^4.1.9" } } diff --git a/frontend/src/adk/client.ts b/frontend/src/adk/client.ts index fac0c24e2..2a0da3b22 100644 --- a/frontend/src/adk/client.ts +++ b/frontend/src/adk/client.ts @@ -18,7 +18,10 @@ import { TRANSFER_REQUEST_TIMEOUT_MS, } from "./timeout"; import type { AgentProject } from "../create/project"; -import type { AgentDraft, NetworkConfig } from "../create/types"; +import type { + AgentDraft, + NetworkConfig, +} from "../create/types"; import type { IssueFeedbackReport } from "./issueFeedback"; import { BYTEPLUS_DEFAULT_REGION, @@ -2130,6 +2133,7 @@ export async function deployAgentkitProject( }; envs?: { key: string; value: string }[]; resources?: DeployResources; + harnessSidecar?: AgentDraft["harnessSidecar"]; }, ): Promise { const taskId = opts?.taskId; @@ -2171,6 +2175,7 @@ export async function deployAgentkitProject( im: opts?.im, envs: opts?.envs, resources: opts?.resources, + harnessSidecar: opts?.harnessSidecar, }), }, {}, @@ -2859,6 +2864,7 @@ export interface GeneratedAgentTestRun { runId: string; appName: string; expiresAt: number; + planHash?: string; } export async function generateAgentProject( diff --git a/frontend/src/create/CustomCreate.css b/frontend/src/create/CustomCreate.css index b6c7fcbbd..34cdb2b69 100644 --- a/frontend/src/create/CustomCreate.css +++ b/frontend/src/create/CustomCreate.css @@ -1393,6 +1393,83 @@ font-style: normal; font-weight: 550; } +.cw-ab-profile-field { + display: grid; + gap: 7px; + margin-bottom: 10px; +} +.cw-ab-profile-label { + color: hsl(var(--foreground)); + font-size: 12px; + font-weight: 600; +} +.cw-ab-profile-options { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 7px; +} +.cw-ab-profile-option { + min-width: 0; + min-height: 44px; + display: flex; + border: 1px solid hsl(var(--border)); + border-radius: 8px; + background: hsl(var(--background) / 0.82); + color: hsl(var(--foreground)); + transition: + border-color 150ms ease, + background-color 150ms ease, + box-shadow 150ms ease; +} +.cw-ab-profile-option:hover:not(.is-disabled) { + border-color: hsl(var(--foreground) / 0.2); + background: hsl(var(--secondary) / 0.28); +} +.cw-ab-profile-option.is-on { + border-color: hsl(var(--foreground) / 0.3); + background: hsl(var(--secondary) / 0.42); +} +.cw-ab-profile-option.is-disabled { + cursor: not-allowed; + opacity: 0.55; +} +.cw-ab-profile-option:focus-within { + outline: none; + box-shadow: 0 0 0 2px hsl(var(--ring) / 0.28); +} +.cw-ab-profile-option > .flex { + align-self: stretch; + flex: 1; + min-width: 0; +} +.cw-ab-profile-control { + align-self: stretch; + width: 100%; + min-width: 0; + min-height: 100%; + padding: 7px 8px; + color: inherit; +} +.cw-ab-profile-copy { + min-width: 0; + display: grid; + gap: 2px; + text-align: left; +} +.cw-ab-profile-copy strong { + overflow: hidden; + font-size: 12px; + font-weight: 650; + text-overflow: ellipsis; + white-space: nowrap; +} +.cw-ab-profile-copy small, +.cw-ab-profile-help { + color: hsl(var(--muted-foreground)); + font-size: 10.5px; + font-weight: 400; + line-height: 1.4; +} .cw-ab-config input[type="text"], .cw-ab-config > label > input, .cw-ab-config > label > textarea { @@ -1426,14 +1503,40 @@ background: hsl(var(--background) / 0.82); color: hsl(var(--foreground)); font-size: 12.5px; - cursor: not-allowed; - opacity: 0.5; + cursor: pointer; } .cw-ab-optimization-checkbox > label { padding-left: 7px; color: inherit; font-size: inherit; } +.cw-ab-optimization-copy { + display: grid; + gap: 2px; +} +.cw-ab-optimization-copy strong { + font-size: 12.5px; + font-weight: 650; +} +.cw-ab-optimization-copy small { + color: hsl(var(--muted-foreground)); + font-size: 10.5px; + font-weight: 400; + line-height: 1.35; +} +.cw-ab-optimization-note, +.cw-ab-optimization-error { + display: block; + margin-top: 7px; + font-size: 11.5px; + line-height: 1.4; +} +.cw-ab-optimization-note { + color: hsl(var(--muted-foreground)); +} +.cw-ab-optimization-error { + color: hsl(var(--destructive)); +} .cw-ab-config > p { margin: 0; color: hsl(var(--muted-foreground)); @@ -4362,6 +4465,9 @@ .cw-ab-config { grid-template-columns: minmax(0, 1fr); } + .cw-ab-profile-options { + grid-template-columns: minmax(0, 1fr); + } .cw-ab-composer { grid-template-columns: minmax(0, 1fr); padding-bottom: 12px; diff --git a/frontend/src/create/CustomCreate.tsx b/frontend/src/create/CustomCreate.tsx index 8d7a8b348..c71201a17 100644 --- a/frontend/src/create/CustomCreate.tsx +++ b/frontend/src/create/CustomCreate.tsx @@ -38,10 +38,23 @@ import { import { type CreateModeProps, type AgentDraft, + type HarnessSidecarOptionId, + type HarnessSidecarProfileId, type McpTool, type SelectedSkill, emptyDraft, } from "./types"; +import { + HARNESS_SIDECAR_OPTIONS, + HARNESS_SIDECAR_PROFILES, + harnessIntentFromOptimizations, + harnessProfileDefaultOptimizations, + harnessSidecarOptionLabel, + harnessSidecarProfileLabel, + releaseDraftFromDebugVariant, + selectedHarnessProfile, + selectedHarnessOptimizations, +} from "./harnessSidecarOptions"; import { A2A_REGISTRY_DEFAULTS, A2A_REGISTRY_ENV, @@ -1989,7 +2002,8 @@ interface DebugVariant { modelName: string; description: string; instruction: string; - optimizations: string[]; + profile: HarnessSidecarProfileId; + optimizations: HarnessSidecarOptionId[]; configOpen: boolean; phase: DebugPhase; runtimeSnapshot: string; @@ -2106,7 +2120,7 @@ function debugVariantSnapshot( draftSnapshot: string, variant: Pick< DebugVariant, - "modelName" | "description" | "instruction" | "optimizations" + "modelName" | "description" | "instruction" | "profile" | "optimizations" >, ): string { return JSON.stringify({ @@ -2114,6 +2128,7 @@ function debugVariantSnapshot( modelName: variant.modelName, description: variant.description, instruction: variant.instruction, + profile: variant.profile, optimizations: variant.optimizations, }); } @@ -2121,13 +2136,14 @@ function debugVariantSnapshot( function debugVariantConfigurationKey( variant: Pick< DebugVariant, - "modelName" | "description" | "instruction" | "optimizations" + "modelName" | "description" | "instruction" | "profile" | "optimizations" >, ): string { return JSON.stringify({ modelName: variant.modelName.trim(), description: variant.description.trim(), instruction: variant.instruction.trim(), + profile: variant.profile, optimizations: variant.optimizations, }); } @@ -2147,6 +2163,8 @@ function DebugComparisonWorkspace({ onToggleConfig, onCompleteConfig, onConfigChange, + onProfileChange, + onOptimizationChange, onOpenTrace, }: { enabled: boolean; @@ -2167,8 +2185,15 @@ function DebugComparisonWorkspace({ field: "modelName" | "description" | "instruction", value: string, ) => void; + onProfileChange: (id: string, profile: HarnessSidecarProfileId) => void; + onOptimizationChange: ( + id: string, + optionId: HarnessSidecarOptionId, + selected: boolean, + ) => void; onOpenTrace: (id: string) => void; }) { + const harnessOptions = HARNESS_SIDECAR_OPTIONS; const runningVariants = variants.filter((variant) => { if (variant.phase !== "ready") return false; return ( @@ -2214,12 +2239,17 @@ function DebugComparisonWorkspace({ const starting = variant.phase === "starting"; const ready = variant.phase === "ready" && !stale; const busy = starting || variant.phase === "sending"; + const selectedProfile = HARNESS_SIDECAR_PROFILES.find( + (profile) => profile.id === variant.profile, + ); const traceAvailable = ready && variant.phase !== "sending" && variant.messages.some((message) => message.role === "assistant"); const startDisabled = - busy || variant.configOpen || configurationUnavailable; + busy || + variant.configOpen || + configurationUnavailable; const disabledReason = !modelName ? "请先选择模型" : !description @@ -2468,22 +2498,90 @@ function DebugComparisonWorkspace({ } /> -
+
优化选项 - 待开放 + 当前版本已集成 +
+ 优化场景 + + className="cw-ab-profile-options" + aria-label="优化场景" + value={variant.profile} + onChange={(profile) => + onProfileChange(variant.id, profile) + } + > + {HARNESS_SIDECAR_PROFILES.map((profile) => ( +
+ + + {profile.displayName} + {profile.description} + + +
+ ))} + + + {variant.profile === "default" + ? "按需勾选组件;不勾选时不启动 Sidecar。" + : `${selectedProfile?.description ?? "该场景"} 已勾选默认组件,可按需调整。`} + +
- {DEBUG_OPTIMIZATIONS.map((item) => ( + {harnessOptions.map((item) => { + const optionId = item.id as HarnessSidecarOptionId; + const checked = variant.optimizations.includes(optionId); + return ( { + if (next !== checked) { + onOptimizationChange( + variant.id, + optionId, + Boolean(next), + ); + } + }} + label={ + + {item.displayName} + {item.description} + + } className="cw-ab-optimization-checkbox" /> - ))} + ); + })}
+ {variant.optimizations.includes("mcp_resilience") && ( + + 当前组合将自动启用 SQL 只读保护(sql_readonly) + + )}

设置完成后返回正面,再启动当前测试环境。

@@ -2556,29 +2654,6 @@ const WORKSPACE_MODES: Array<{ { id: "publish", label: "发布" }, ]; -const DEBUG_OPTIMIZATIONS = [ - { - id: "context", - label: "上下文优化", - description: "压缩历史对话,保留与当前任务相关的信息", - }, - { - id: "grounding", - label: "幻觉抑制", - description: "对不确定内容要求依据,并明确表达未知", - }, - { - id: "tools", - label: "工具调用优化", - description: "减少重复调用,优先复用可信的工具结果", - }, - { - id: "latency", - label: "响应加速", - description: "缓存稳定上下文,降低重复推理开销", - }, -] as const; - function WorkspaceHeader({ mode }: { mode: WorkspaceMode }) { const title = mode === "validate" @@ -2778,7 +2853,8 @@ export function CustomCreate({ modelName: defaultDebugModelName(initialProviderDraft), description: initialProviderDraft.description, instruction: initialProviderDraft.instruction, - optimizations: [], + optimizations: selectedHarnessOptimizations(initialProviderDraft), + profile: selectedHarnessProfile(initialProviderDraft), configOpen: false, phase: "idle", runtimeSnapshot: "", @@ -3208,8 +3284,7 @@ export function CustomCreate({ }); }; - const openPublishPreview = async (variantId?: string) => { - if (!(await confirmLeaveDebug())) return; + const materializePublishRelease = async (variantId?: string) => { setBuildErr(""); if (!requireCompleteDraft()) { setWorkspaceMode("build"); @@ -3233,15 +3308,10 @@ export function CustomCreate({ : selectedDebugVariant; if (releaseVariant) setSelectedVariantId(releaseVariant.id); const releaseDraft = releaseVariant - ? { - ...providerDraft, - modelName: releaseVariant.modelName || providerDraft.modelName, - description: releaseVariant.description, - instruction: releaseVariant.instruction, - } + ? releaseDraftFromDebugVariant(providerDraft, releaseVariant) : providerDraft; const generated = await generateAgentProject(codegenDraft(releaseDraft)); - if (releaseDraft !== draft) setDraft(releaseDraft); + setDraft(releaseDraft); setProject(generated); setWorkspaceMode("publish"); } catch (error) { @@ -3251,6 +3321,11 @@ export function CustomCreate({ } }; + const openPublishPreview = async (variantId?: string) => { + if (!(await confirmLeaveDebug())) return; + await materializePublishRelease(variantId); + }; + const startDebugVariant = async (id: string) => { if (!debugEnabled || building) return; if (!requireCompleteDraft()) return; @@ -3301,6 +3376,10 @@ export function CustomCreate({ modelName: variant.modelName || providerDraft.modelName, description: variant.description, instruction: variant.instruction, + harnessSidecar: harnessIntentFromOptimizations( + variant.optimizations, + variant.profile, + ), }; failedPhase = "create_test_run"; createdRun = await createGeneratedAgentTestRun( @@ -3460,6 +3539,7 @@ export function CustomCreate({ modelName: draft.modelName ?? "", description: draft.description, instruction: draft.instruction, + profile: "default", optimizations: [], configOpen: true, phase: "idle", @@ -3484,6 +3564,29 @@ export function CustomCreate({ ), ); + const updateDebugVariantOptimization = ( + id: string, + optionId: HarnessSidecarOptionId, + selected: boolean, + ) => { + const variant = debugVariants.find((item) => item.id === id); + if (!variant) return; + const optimizations = selected + ? [...new Set([...variant.optimizations, optionId])] + : variant.optimizations.filter((item) => item !== optionId); + patchDebugVariant(id, { optimizations }); + }; + + const updateDebugVariantProfile = ( + id: string, + profile: HarnessSidecarProfileId, + ) => { + patchDebugVariant(id, { + profile, + optimizations: harnessProfileDefaultOptimizations(profile), + }); + }; + const updateDebugVariantConfig = ( id: string, field: "modelName" | "description" | "instruction", @@ -3550,6 +3653,7 @@ export function CustomCreate({ runtimeId: deploymentTarget?.runtimeId, appName: deploymentTarget?.appName, description: draft.description, + harnessSidecar: draft.harnessSidecar, }, ); }; @@ -3575,9 +3679,8 @@ export function CustomCreate({ const handleWorkspaceChange = async (nextMode: WorkspaceMode) => { if (nextMode === "publish") { - if (!requireCompleteDraft()) return; - if (project) setWorkspaceMode("publish"); - else openPublishPreview(); + if (!(await confirmLeaveDebug())) return; + await materializePublishRelease(); return; } if (nextMode === "validate") { @@ -4335,6 +4438,10 @@ export function CustomCreate({ }} onCompleteConfig={completeDebugVariantConfig} onConfigChange={updateDebugVariantConfig} + onProfileChange={updateDebugVariantProfile} + onOptimizationChange={(id, optionId, selected) => + updateDebugVariantOptimization(id, optionId, selected) + } onOpenTrace={openDebugTrace} /> @@ -4360,14 +4467,12 @@ export function CustomCreate({ "默认模型", description: selectedDebugVariant.description, instruction: selectedDebugVariant.instruction, - optimizations: selectedDebugVariant.optimizations.flatMap( - (id) => { - const option = DEBUG_OPTIMIZATIONS.find( - (item) => item.id === id, - ); - return option ? [option.label] : []; - }, - ), + optimizations: [ + `优化场景:${harnessSidecarProfileLabel(selectedDebugVariant.profile)}`, + ...selectedDebugVariant.optimizations.map( + harnessSidecarOptionLabel, + ), + ], } : undefined } diff --git a/frontend/src/create/configYaml.ts b/frontend/src/create/configYaml.ts index 907350fec..db002aa78 100644 --- a/frontend/src/create/configYaml.ts +++ b/frontend/src/create/configYaml.ts @@ -9,7 +9,7 @@ import { prepareMcpAuth } from "./mcpAuth"; import type { AgentDraft } from "./types"; /** Build a clean, minimal config object (omit empty/false fields). */ -function toConfig(draft: AgentDraft): Record { +function toConfig(draft: AgentDraft, root = true): Record { const o: Record = { agentType: draft.agentType ?? "llm", }; @@ -76,6 +76,13 @@ function toConfig(draft: AgentDraft): Record { o.tracing = true; o.tracingExporters = [...draft.tracingExporters]; } + if (root && draft.harnessSidecar?.enabled) { + o.harnessSidecar = { + enabled: true, + profile: draft.harnessSidecar.profile, + componentOverrides: { ...draft.harnessSidecar.componentOverrides }, + }; + } if ( draft.deployment?.feishuEnabled || Object.keys(draft.deployment?.envValues ?? {}).length > 0 @@ -109,7 +116,9 @@ function toConfig(draft: AgentDraft): Record { } return base; }); - if (draft.subAgents?.length) o.subAgents = draft.subAgents.map(toConfig); + if (draft.subAgents?.length) { + o.subAgents = draft.subAgents.map((child) => toConfig(child, false)); + } return o; } diff --git a/frontend/src/create/harnessSidecarOptions.ts b/frontend/src/create/harnessSidecarOptions.ts new file mode 100644 index 000000000..760a33700 --- /dev/null +++ b/frontend/src/create/harnessSidecarOptions.ts @@ -0,0 +1,144 @@ +import type { + AgentDraft, + HarnessSidecarIntent, + HarnessSidecarOptionId, + HarnessSidecarProfileId, +} from "./types"; + +export interface HarnessSidecarOption { + id: HarnessSidecarOptionId; + displayName: string; + description: string; +} + +export interface HarnessSidecarProfile { + id: HarnessSidecarProfileId; + displayName: string; + description: string; + defaultComponents: readonly HarnessSidecarOptionId[]; + autoAddedComponents: readonly string[]; +} + +export const HARNESS_SIDECAR_OPTIONS: readonly HarnessSidecarOption[] = [ + { + id: "context_engine", + displayName: "上下文治理", + description: "治理上下文组装、任务锚定和上下文预算。", + }, + { + id: "compressor", + displayName: "上下文与结果压缩", + description: "压缩长上下文和大型工具结果,降低 Token 成本。", + }, + { + id: "verifier", + displayName: "回答校验与修复", + description: "校验证据和回答,在失败时执行修复或告警。", + }, + { + id: "long_run_control", + displayName: "Goal任务控制", + description: "管理 Goal 任务的进度、续跑和结束条件。", + }, + { + id: "mcp_resilience", + displayName: "MCP 稳定性治理", + description: "治理连接、超时、空结果、大返回和调用预算;默认包含 SQL 只读保护。", + }, +]; + +export const HARNESS_SIDECAR_OPTION_IDS: HarnessSidecarOptionId[] = + HARNESS_SIDECAR_OPTIONS.map((item) => item.id); + +export const HARNESS_SIDECAR_PROFILES: readonly HarnessSidecarProfile[] = [ + { + id: "default", + displayName: "自定义", + description: "按需选择组件,不勾选时不启动 Sidecar。", + defaultComponents: [], + autoAddedComponents: [], + }, + { + id: "ops", + displayName: "运维场景", + description: "适用于运维诊断、数据库、日志和监控 MCP。", + defaultComponents: [ + "context_engine", + "compressor", + "verifier", + "long_run_control", + "mcp_resilience", + ], + autoAddedComponents: ["sql_readonly"], + }, +]; + +export function harnessSidecarOptionLabel(id: string): string { + return HARNESS_SIDECAR_OPTIONS.find((item) => item.id === id)?.displayName ?? id; +} + +export function harnessSidecarProfileLabel(id: string): string { + return HARNESS_SIDECAR_PROFILES.find((item) => item.id === id)?.displayName ?? id; +} + +export function harnessProfileDefaultOptimizations( + profile: HarnessSidecarProfileId, +): HarnessSidecarOptionId[] { + const metadata = HARNESS_SIDECAR_PROFILES.find((item) => item.id === profile); + if (!metadata) return []; + return [...metadata.defaultComponents]; +} + +export function harnessIntentFromOptimizations( + optimizations: readonly HarnessSidecarOptionId[], + profile: HarnessSidecarProfileId = "default", +): HarnessSidecarIntent { + const selected = new Set(optimizations); + const intent: HarnessSidecarIntent = { + enabled: selected.size > 0, + profile, + componentOverrides: Object.fromEntries( + HARNESS_SIDECAR_OPTION_IDS.map((id) => [id, selected.has(id)]), + ) as HarnessSidecarIntent["componentOverrides"], + }; + return intent; +} + +export interface HarnessSidecarDebugVariant { + modelName: string; + description: string; + instruction: string; + profile: HarnessSidecarProfileId; + optimizations: readonly HarnessSidecarOptionId[]; +} + +export function releaseDraftFromDebugVariant( + draft: AgentDraft, + variant: HarnessSidecarDebugVariant, +): AgentDraft { + return { + ...draft, + modelName: variant.modelName || draft.modelName, + description: variant.description, + instruction: variant.instruction, + harnessSidecar: harnessIntentFromOptimizations( + variant.optimizations, + variant.profile, + ), + }; +} + +export function selectedHarnessProfile( + draft: AgentDraft, +): HarnessSidecarProfileId { + return draft.harnessSidecar?.profile ?? "default"; +} + +export function selectedHarnessOptimizations( + draft: AgentDraft, +): HarnessSidecarOptionId[] { + const overrides = draft.harnessSidecar?.componentOverrides; + return overrides + ? HARNESS_SIDECAR_OPTION_IDS.filter((id) => overrides[id]) + : []; +} diff --git a/frontend/src/create/normalizeDraft.ts b/frontend/src/create/normalizeDraft.ts index 62cd23863..dcb407b70 100644 --- a/frontend/src/create/normalizeDraft.ts +++ b/frontend/src/create/normalizeDraft.ts @@ -3,6 +3,9 @@ import { type A2aRegistryConfig, type AgentDraft, type CustomTool, + type HarnessSidecarIntent, + type HarnessSidecarOptionId, + type HarnessSidecarProfileId, type SelectedSkill, } from "./types"; import { createBuiltinToolsForProvider, DEFAULT_KB_BACKEND } from "./veadkCatalog"; @@ -32,6 +35,17 @@ const TOOL_IDS = new Set([ "vesearch", ]); const AGENT_TYPES = new Set(["llm", "sequential", "parallel", "loop", "a2a"]); +const HARNESS_SIDECAR_OPTION_IDS: HarnessSidecarOptionId[] = [ + "context_engine", + "compressor", + "verifier", + "long_run_control", + "mcp_resilience", +]; +const HARNESS_SIDECAR_PROFILE_IDS = new Set([ + "default", + "ops", +]); function asString(v: unknown, fallback = ""): string { return typeof v === "string" ? v : fallback; @@ -41,6 +55,13 @@ function asBool(v: unknown): boolean { return v === true; } +function asHarnessSidecarProfile(v: unknown): HarnessSidecarProfileId { + return typeof v === "string" && + HARNESS_SIDECAR_PROFILE_IDS.has(v as HarnessSidecarProfileId) + ? (v as HarnessSidecarProfileId) + : "default"; +} + function asStringArray(v: unknown): string[] { return Array.isArray(v) ? v.filter((x): x is string => typeof x === "string") : []; } @@ -97,6 +118,29 @@ function asA2aRegistry(v: unknown): A2aRegistryConfig { }; } +function asHarnessSidecarIntent(v: unknown): HarnessSidecarIntent | undefined { + if (!v || typeof v !== "object" || Array.isArray(v)) return undefined; + const raw = v as Record; + const rawOverrides = ( + raw.componentOverrides && typeof raw.componentOverrides === "object" + ? raw.componentOverrides + : {} + ) as Record; + const componentOverrides = Object.fromEntries( + HARNESS_SIDECAR_OPTION_IDS.map((id) => [id, rawOverrides[id] === true]), + ) as Record; + const intent: HarnessSidecarIntent = { + enabled: Object.values(componentOverrides).some(Boolean), + profile: asHarnessSidecarProfile(raw.profile), + componentOverrides, + }; + const catalogVersion = asString(raw.catalogVersion).trim(); + const planHash = asString(raw.planHash).trim(); + if (catalogVersion) intent.catalogVersion = catalogVersion; + if (planHash) intent.planHash = planHash; + return intent; +} + function parseSubAgents( v: unknown, cloudProvider: NonNullable = "volcengine", @@ -278,6 +322,7 @@ export function normalizeDraft(raw: unknown): AgentDraft { ? { envValues: deploymentEnvValues } : {}), }, + harnessSidecar: asHarnessSidecarIntent(o.harnessSidecar), subAgents: parseSubAgents(o.subAgents, cloudProvider), selectedSkills: parseSelectedSkills(o), }; diff --git a/frontend/src/create/types.ts b/frontend/src/create/types.ts index 92dcf353b..dc5e9381a 100644 --- a/frontend/src/create/types.ts +++ b/frontend/src/create/types.ts @@ -74,6 +74,23 @@ export interface DeploymentConfig { envValues?: Record; } +export type HarnessSidecarOptionId = + | "context_engine" + | "compressor" + | "verifier" + | "long_run_control" + | "mcp_resilience"; + +export type HarnessSidecarProfileId = "default" | "ops"; + +export interface HarnessSidecarIntent { + enabled: boolean; + profile: HarnessSidecarProfileId; + componentOverrides: Record; + catalogVersion?: string; + planHash?: string; +} + /** A draft VeADK agent configuration produced by a creation flow. */ export interface AgentDraft { name: string; @@ -139,6 +156,8 @@ export interface AgentDraft { }; /** Deployment-time options that do not change generated agent code. */ deployment?: DeploymentConfig; + /** Root Runtime-level Harness Sidecar selection. Never set on sub-Agents. */ + harnessSidecar?: HarnessSidecarIntent; } // Pre-filled defaults so description / system prompt / model are never empty diff --git a/frontend/src/ui/ProjectPreview.tsx b/frontend/src/ui/ProjectPreview.tsx index 2a0baee60..a78b7a11f 100644 --- a/frontend/src/ui/ProjectPreview.tsx +++ b/frontend/src/ui/ProjectPreview.tsx @@ -510,6 +510,9 @@ export interface ProjectPreviewProps { description: string; instruction: string; optimizations: string[]; + effectiveOptimizations?: string[]; + autoAddedOptimizations?: string[]; + planHash?: string; }; /** When provided, files are editable and changes call onChange with the new project. Omit for read-only. */ onChange?: (project: AgentProject) => void; @@ -694,6 +697,7 @@ export function ProjectPreview({ const editable = typeof onChange === "function"; const isRuntimeUpdate = deploymentActionLabel.includes("更新"); const inMemorySession = usesInMemorySession(agentDraft); + const sidecarEnabled = agentDraft?.harnessSidecar?.enabled === true; // Initialize all hooks BEFORE any conditional returns (React hooks rule) const [selected, setSelected] = useState( @@ -728,7 +732,7 @@ export function ProjectPreview({ const deployRegionLabel = formatCloudRegion(deployRegion, cloudProvider); const [minInstance, setMinInstance] = useState("1"); const [maxInstance, setMaxInstance] = useState( - inMemorySession ? "1" : "5", + inMemorySession || sidecarEnabled ? "1" : "5", ); const [createEvaluationSets, setCreateEvaluationSets] = useState(true); const supportsEvaluationSets = cloudProvider !== "byteplus"; @@ -839,8 +843,8 @@ export function ProjectPreview({ useEffect(() => { setMinInstance("1"); - setMaxInstance(inMemorySession ? "1" : "5"); - }, [inMemorySession]); + setMaxInstance(inMemorySession || sidecarEnabled ? "1" : "5"); + }, [inMemorySession, sidecarEnabled]); useEffect(() => { if (previousDeployRegionRef.current === deployRegion) return; @@ -1577,6 +1581,32 @@ export function ProjectPreview({ : "未启用"} + {releaseConfiguration.effectiveOptimizations && + releaseConfiguration.effectiveOptimizations.length > 0 && ( +
+
生效能力
+
+ {releaseConfiguration.effectiveOptimizations.join("、")} +
+
+ )} + {releaseConfiguration.autoAddedOptimizations && + releaseConfiguration.autoAddedOptimizations.length > 0 && ( +
+
自动保护
+
+ {releaseConfiguration.autoAddedOptimizations.join("、")} +
+
+ )} + {releaseConfiguration.planHash && ( +
+
Plan Hash
+
+ {releaseConfiguration.planHash} +
+
+ )} )} @@ -1848,7 +1878,7 @@ export function ProjectPreview({ step="1" inputMode="numeric" value={minInstance} - disabled={deploying} + disabled={deploying || sidecarEnabled} aria-invalid={!instanceRange.valid} onChange={(event) => setMinInstance(event.currentTarget.value)} /> @@ -1862,15 +1892,17 @@ export function ProjectPreview({ step="1" inputMode="numeric" value={maxInstance} - disabled={deploying} + disabled={deploying || sidecarEnabled} aria-invalid={!instanceRange.valid} onChange={(event) => setMaxInstance(event.currentTarget.value)} /> - {inMemorySession && ( + {(inMemorySession || sidecarEnabled) && (

- 为避免多实例间会话丢失,推荐将 Runtime 固定为 1~1 + {sidecarEnabled + ? "Harness Sidecar 首期仅支持单实例,Runtime 固定为 1~1" + : "为避免多实例间会话丢失,推荐将 Runtime 固定为 1~1"}

)} {!instanceRange.valid && ( diff --git a/frontend/src/ui/Sidebar.tsx b/frontend/src/ui/Sidebar.tsx index 59b74e38f..29d8d6e3d 100644 --- a/frontend/src/ui/Sidebar.tsx +++ b/frontend/src/ui/Sidebar.tsx @@ -268,8 +268,7 @@ export function Sidebar({ userInfo, onLogout, }: SidebarProps) { - // Agent creation still lives outside the main navigation. - void onQuickCreate; + // The legacy full-page creator remains outside the main navigation. void onAddAgent; // Per-module feature gates; a missing flag defaults to shown. const show = (k: keyof NonNullable) => features?.[k] !== false; @@ -367,6 +366,17 @@ export function Sidebar({ 智能体 + {access.capabilities.createAgents && show("addAgent") ? ( + + ) : null} {show("skillCenter") ? (