diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f3ea4ed37..a9c0fee6f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -15,6 +15,10 @@ on: description: "Version to release (e.g., v0.1.0)" required: true default: "v0.1.0" + source_ref: + description: "Git ref to build from (e.g., v0.96.0 or main)" + required: false + default: "" permissions: contents: write @@ -48,12 +52,14 @@ jobs: TAURI_SIGNING_PRIVATE_KEY_RAW: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }} NODE_OPTIONS: --max-old-space-size=8192 + SCCACHE_NO_DAEMON: "1" steps: - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0 + ref: ${{ github.event.inputs.source_ref || github.ref }} - name: Setup Node.js uses: actions/setup-node@v4 diff --git a/docs/aiprompts/commands.md b/docs/aiprompts/commands.md index 45553517c..9e074de60 100644 --- a/docs/aiprompts/commands.md +++ b/docs/aiprompts/commands.md @@ -154,6 +154,20 @@ npm run verify:local 5. `npm run test:contracts` 通过 6. 涉及 compat / deprecated 的改动,已补 `governance:legacy-report` 或明确说明不需要 +## 自动化 `agent_turn` 负载补充约定 + +当 `create_automation_job` / `update_automation_job` 的 `payload.kind = "agent_turn"` 用于持续产出交付物时,允许并推荐透传以下字段: + +- `content_id`:绑定长期内容主线,供自动化版本持续沉淀到同一交付链 +- `request_metadata`:与运行时 turn 保持同合同,至少可包含 `artifact` 与 `harness` 两层 + +推荐形态: + +- `request_metadata.artifact`:`artifact_mode / artifact_kind / artifact_stage / workbench_surface` +- `request_metadata.harness`:`theme / session_mode / content_id` + +这样做的目的不是给自动化新增第二套协议,而是让自动化直接复用现有 runtime turn 的 Artifact 主链。 + ## 明确禁止 - 在页面、组件、普通 Hook 中直接散落 `invoke` diff --git a/docs/aiprompts/playwright-e2e.md b/docs/aiprompts/playwright-e2e.md index be3e6004e..b44ee0259 100644 --- a/docs/aiprompts/playwright-e2e.md +++ b/docs/aiprompts/playwright-e2e.md @@ -130,6 +130,17 @@ npm run test:contracts 7. 验证页面出现 `Theme Workbench` 或相关工作台内容 8. 再次检查控制台 error +### 服务型技能自动化交付链 + +1. 从首页进入服务型技能卡片 +2. 选择一个 `scheduled / managed` 的本地服务型技能 +3. 打开“创建自动化任务”,提交后进入对应工作区 +4. 确认同一次操作里: + - 自动化任务已创建 + - 工作区已打开 + - 对应内容仍落在同一个 `contentId` +5. 如能查看运行记录或调试面板,继续确认自动化 `agent_turn` payload 含 `content_id` 与 `request_metadata.artifact` + ### 素材页验证 1. 从社媒内容项目进入 `素材` diff --git a/docs/aiprompts/quality-workflow.md b/docs/aiprompts/quality-workflow.md index c941eba34..01c57be0c 100644 --- a/docs/aiprompts/quality-workflow.md +++ b/docs/aiprompts/quality-workflow.md @@ -181,6 +181,10 @@ npm run bridge:health -- --timeout-ms 120000 | Rust 模块改动 | 受影响 crate / 模块定向测试 | 再决定是否跑全量 `cargo test` | | 真实页面交互验证 | 先跑 `npm run verify:gui-smoke` | 再进入 `playwright-e2e.md` | +补充说明: + +- 如果这次改动把 `ServiceSkill -> automation_job -> agent_turn` 接到 Artifact 主线,除了常规 `verify:local` / `test:contracts` 之外,还应至少补一条稳定回归,证明 `content_id + request_metadata.artifact` 没在表单编辑或执行链路里丢失。 + ## CI 事实源 主工作流: diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 645540c03..83d40a77a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -191,6 +191,9 @@ importers: mermaid: specifier: ^11.12.2 version: 11.12.3 + qrcode: + specifier: ^1.5.4 + version: 1.5.4 react: specifier: ^18.3.1 version: 18.3.1 @@ -270,6 +273,9 @@ importers: '@types/node': specifier: ^22.9.0 version: 22.19.3 + '@types/qrcode': + specifier: ^1.5.6 + version: 1.5.6 '@types/react': specifier: ^18.3.12 version: 18.3.27 @@ -291,6 +297,12 @@ importers: autoprefixer: specifier: ^10.4.20 version: 10.4.23(postcss@8.5.6) + cytoscape: + specifier: ^3.33.1 + version: 3.33.1 + dependency-cruiser: + specifier: ^16.10.4 + version: 16.10.4 eslint: specifier: ^9.15.0 version: 9.39.2(jiti@1.21.7) @@ -312,6 +324,9 @@ importers: jsdom: specifier: ^22.1.0 version: 22.1.0(canvas@2.11.2) + knip: + specifier: ^6.0.2 + version: 6.0.5 postcss: specifier: ^8.4.47 version: 8.5.6 @@ -320,7 +335,7 @@ importers: version: 3.7.4 tailwindcss: specifier: ^3.4.14 - version: 3.4.19(tsx@4.21.0) + version: 3.4.19(tsx@4.21.0)(yaml@2.8.3) tsx: specifier: ^4.21.0 version: 4.21.0 @@ -336,6 +351,9 @@ importers: vitest: specifier: ^3.2.4 version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.3)(jsdom@22.1.0(canvas@2.11.2)) + yaml: + specifier: ^2.8.3 + version: 2.8.3 packages: @@ -455,6 +473,15 @@ packages: '@chevrotain/utils@11.1.2': resolution: {integrity: sha512-4mudFAQ6H+MqBTfqLmU7G1ZwRzCLfJEooL/fsF6rCX5eePMbGhoy5n4g+G4vlh2muDcsCTJtL+uKbOzWxs5LHA==} + '@emnapi/core@1.9.1': + resolution: {integrity: sha512-mukuNALVsoix/w1BJwFzwXBN/dHeejQtuVzcDsfOEsdpCumXb/E9j8w11h5S54tT1xhifGfbbSm/ICrObRb3KA==} + + '@emnapi/runtime@1.9.1': + resolution: {integrity: sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA==} + + '@emnapi/wasi-threads@1.2.0': + resolution: {integrity: sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg==} + '@emotion/is-prop-valid@1.2.2': resolution: {integrity: sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==} @@ -873,6 +900,9 @@ packages: '@mixmark-io/domino@2.2.0': resolution: {integrity: sha512-Y28PR25bHXUg88kCV7nivXrP2Nj2RueZ3/l/jdx6J9f8J4nsEGcgX0Qe6lt7Pa+J79+kPiJU3LguR6O/6zrLOw==} + '@napi-rs/wasm-runtime@1.1.1': + resolution: {integrity: sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A==} + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -889,6 +919,228 @@ packages: resolution: {integrity: sha512-/qaXP/7mc4MUS0s4cPPFASDRjtsWp85/TbfsciqDgU1HwYixbSbbytNuInD8AcTYC3xaxACgVX06agdfQy9W+g==} engines: {node: '>=12'} + '@oxc-parser/binding-android-arm-eabi@0.120.0': + resolution: {integrity: sha512-WU3qtINx802wOl8RxAF1v0VvmC2O4D9M8Sv486nLeQ7iPHVmncYZrtBhB4SYyX+XZxj2PNnCcN+PW21jHgiOxg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [android] + + '@oxc-parser/binding-android-arm64@0.120.0': + resolution: {integrity: sha512-SEf80EHdhlbjZEgzeWm0ZA/br4GKMenDW3QB/gtyeTV1gStvvZeFi40ioHDZvds2m4Z9J1bUAUL8yn1/+A6iGg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@oxc-parser/binding-darwin-arm64@0.120.0': + resolution: {integrity: sha512-xVrrbCai8R8CUIBu3CjryutQnEYhZqs1maIqDvtUCFZb8vY33H7uh9mHpL3a0JBIKoBUKjPH8+rzyAeXnS2d6A==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@oxc-parser/binding-darwin-x64@0.120.0': + resolution: {integrity: sha512-xyHBbnJ6mydnQUH7MAcafOkkrNzQC6T+LXgDH/3InEq2BWl/g424IMRiJVSpVqGjB+p2bd0h0WRR8iIwzjU7rw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@oxc-parser/binding-freebsd-x64@0.120.0': + resolution: {integrity: sha512-UMnVRllquXUYTeNfFKmxTTEdZ/ix1nLl0ducDzMSREoWYGVIHnOOxoKMWlCOvRr9Wk/HZqo2rh1jeumbPGPV9A==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@oxc-parser/binding-linux-arm-gnueabihf@0.120.0': + resolution: {integrity: sha512-tkvn2CQ7QdcsMnpfiX3fd3wA3EFsWKYlcQzq9cFw/xc89Al7W6Y4O0FgLVkVQpo0Tnq/qtE1XfkJOnRRA9S/NA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxc-parser/binding-linux-arm-musleabihf@0.120.0': + resolution: {integrity: sha512-WN5y135Ic42gQDk9grbwY9++fDhqf8knN6fnP+0WALlAUh4odY/BDK1nfTJRSfpJD9P3r1BwU0m3pW2DU89whQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxc-parser/binding-linux-arm64-gnu@0.120.0': + resolution: {integrity: sha512-1GgQBCcXvFMw99EPdMy+4NZ3aYyXsxjf9kbUUg8HuAy3ZBXzOry5KfFEzT9nqmgZI1cuetvApkiJBZLAPo8uaw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + + '@oxc-parser/binding-linux-arm64-musl@0.120.0': + resolution: {integrity: sha512-gmMQ70gsPdDBgpcErvJEoWNBr7bJooSLlvOBVBSGfOzlP5NvJ3bFvnUeZZ9d+dPrqSngtonf7nyzWUTUj/U+lw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + + '@oxc-parser/binding-linux-ppc64-gnu@0.120.0': + resolution: {integrity: sha512-T/kZuU0ajop0xhzVMwH5r3srC9Nqup5HaIo+3uFjIN5uPxa0LvSxC1ZqP4aQGJVW5G0z8/nCkjIfSMS91P/wzw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + + '@oxc-parser/binding-linux-riscv64-gnu@0.120.0': + resolution: {integrity: sha512-vn21KXLAXzaI3N5CZWlBr1iWeXLl9QFIMor7S1hUjUGTeUuWCoE6JZB040/ZNDwf+JXPX8Ao9KbmJq9FMC2iGw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + + '@oxc-parser/binding-linux-riscv64-musl@0.120.0': + resolution: {integrity: sha512-SUbUxlar007LTGmSLGIC5x/WJvwhdX+PwNzFJ9f/nOzZOrCFbOT4ikt7pJIRg1tXVsEfzk5mWpGO1NFiSs4PIw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + + '@oxc-parser/binding-linux-s390x-gnu@0.120.0': + resolution: {integrity: sha512-hYiPJTxyfJY2+lMBFk3p2bo0R9GN+TtpPFlRqVchL1qvLG+pznstramHNvJlw9AjaoRUHwp9IKR7UZQnRPGjgQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + + '@oxc-parser/binding-linux-x64-gnu@0.120.0': + resolution: {integrity: sha512-q+5jSVZkprJCIy3dzJpApat0InJaoxQLsJuD6DkX8hrUS61z2lHQ1Fe9L2+TYbKHXCLWbL0zXe7ovkIdopBGMQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + + '@oxc-parser/binding-linux-x64-musl@0.120.0': + resolution: {integrity: sha512-D9QDDZNnH24e7X4ftSa6ar/2hCavETfW3uk0zgcMIrZNy459O5deTbWrjGzZiVrSWigGtlQwzs2McBP0QsfV1w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + + '@oxc-parser/binding-openharmony-arm64@0.120.0': + resolution: {integrity: sha512-TBU8ZwOUWAOUWVfmI16CYWbvh4uQb9zHnGBHsw5Cp2JUVG044OIY1CSHODLifqzQIMTXvDvLzcL89GGdUIqNrA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@oxc-parser/binding-wasm32-wasi@0.120.0': + resolution: {integrity: sha512-WG/FOZgDJCpJnuF3ToG/K28rcOmSY7FmFmfBKYb2fmLyhDzPpUldFGV7/Fz4ru0Iz/v4KPmf8xVgO8N3lO4KHA==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@oxc-parser/binding-win32-arm64-msvc@0.120.0': + resolution: {integrity: sha512-1T0HKGcsz/BKo77t7+89L8Qvu4f9DoleKWHp3C5sJEcbCjDOLx3m9m722bWZTY+hANlUEs+yjlK+lBFsA+vrVQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@oxc-parser/binding-win32-ia32-msvc@0.120.0': + resolution: {integrity: sha512-L7vfLzbOXsjBXV0rv/6Y3Jd9BRjPeCivINZAqrSyAOZN3moCopDN+Psq9ZrGNZtJzP8946MtlRFZ0Als0wBCOw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ia32] + os: [win32] + + '@oxc-parser/binding-win32-x64-msvc@0.120.0': + resolution: {integrity: sha512-ys+upfqNtSu58huAhJMBKl3XCkGzyVFBlMlGPzHeFKgpFF/OdgNs1MMf8oaJIbgMH8ZxgGF7qfue39eJohmKIg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@oxc-project/types@0.120.0': + resolution: {integrity: sha512-k1YNu55DuvAip/MGE1FTsIuU3FUCn6v/ujG9V7Nq5Df/kX2CWb13hhwD0lmJGMGqE+bE1MXvv9SZVnMzEXlWcg==} + + '@oxc-resolver/binding-android-arm-eabi@11.19.1': + resolution: {integrity: sha512-aUs47y+xyXHUKlbhqHUjBABjvycq6YSD7bpxSW7vplUmdzAlJ93yXY6ZR0c1o1x5A/QKbENCvs3+NlY8IpIVzg==} + cpu: [arm] + os: [android] + + '@oxc-resolver/binding-android-arm64@11.19.1': + resolution: {integrity: sha512-oolbkRX+m7Pq2LNjr/kKgYeC7bRDMVTWPgxBGMjSpZi/+UskVo4jsMU3MLheZV55jL6c3rNelPl4oD60ggYmqA==} + cpu: [arm64] + os: [android] + + '@oxc-resolver/binding-darwin-arm64@11.19.1': + resolution: {integrity: sha512-nUC6d2i3R5B12sUW4O646qD5cnMXf2oBGPLIIeaRfU9doJRORAbE2SGv4eW6rMqhD+G7nf2Y8TTJTLiiO3Q/dQ==} + cpu: [arm64] + os: [darwin] + + '@oxc-resolver/binding-darwin-x64@11.19.1': + resolution: {integrity: sha512-cV50vE5+uAgNcFa3QY1JOeKDSkM/9ReIcc/9wn4TavhW/itkDGrXhw9jaKnkQnGbjJ198Yh5nbX/Gr2mr4Z5jQ==} + cpu: [x64] + os: [darwin] + + '@oxc-resolver/binding-freebsd-x64@11.19.1': + resolution: {integrity: sha512-xZOQiYGFxtk48PBKff+Zwoym7ScPAIVp4c14lfLxizO2LTTTJe5sx9vQNGrBymrf/vatSPNMD4FgsaaRigPkqw==} + cpu: [x64] + os: [freebsd] + + '@oxc-resolver/binding-linux-arm-gnueabihf@11.19.1': + resolution: {integrity: sha512-lXZYWAC6kaGe/ky2su94e9jN9t6M0/6c+GrSlCqL//XO1cxi5lpAhnJYdyrKfm0ZEr/c7RNyAx3P7FSBcBd5+A==} + cpu: [arm] + os: [linux] + + '@oxc-resolver/binding-linux-arm-musleabihf@11.19.1': + resolution: {integrity: sha512-veG1kKsuK5+t2IsO9q0DErYVSw2azvCVvWHnfTOS73WE0STdLLB7Q1bB9WR+yHPQM76ASkFyRbogWo1GR1+WbQ==} + cpu: [arm] + os: [linux] + + '@oxc-resolver/binding-linux-arm64-gnu@11.19.1': + resolution: {integrity: sha512-heV2+jmXyYnUrpUXSPugqWDRpnsQcDm2AX4wzTuvgdlZfoNYO0O3W2AVpJYaDn9AG4JdM6Kxom8+foE7/BcSig==} + cpu: [arm64] + os: [linux] + + '@oxc-resolver/binding-linux-arm64-musl@11.19.1': + resolution: {integrity: sha512-jvo2Pjs1c9KPxMuMPIeQsgu0mOJF9rEb3y3TdpsrqwxRM+AN6/nDDwv45n5ZrUnQMsdBy5gIabioMKnQfWo9ew==} + cpu: [arm64] + os: [linux] + + '@oxc-resolver/binding-linux-ppc64-gnu@11.19.1': + resolution: {integrity: sha512-vLmdNxWCdN7Uo5suays6A/+ywBby2PWBBPXctWPg5V0+eVuzsJxgAn6MMB4mPlshskYbppjpN2Zg83ArHze9gQ==} + cpu: [ppc64] + os: [linux] + + '@oxc-resolver/binding-linux-riscv64-gnu@11.19.1': + resolution: {integrity: sha512-/b+WgR+VTSBxzgOhDO7TlMXC1ufPIMR6Vj1zN+/x+MnyXGW7prTLzU9eW85Aj7Th7CCEG9ArCbTeqxCzFWdg2w==} + cpu: [riscv64] + os: [linux] + + '@oxc-resolver/binding-linux-riscv64-musl@11.19.1': + resolution: {integrity: sha512-YlRdeWb9j42p29ROh+h4eg/OQ3dTJlpHSa+84pUM9+p6i3djtPz1q55yLJhgW9XfDch7FN1pQ/Vd6YP+xfRIuw==} + cpu: [riscv64] + os: [linux] + + '@oxc-resolver/binding-linux-s390x-gnu@11.19.1': + resolution: {integrity: sha512-EDpafVOQWF8/MJynsjOGFThcqhRHy417sRyLfQmeiamJ8qVhSKAn2Dn2VVKUGCjVB9C46VGjhNo7nOPUi1x6uA==} + cpu: [s390x] + os: [linux] + + '@oxc-resolver/binding-linux-x64-gnu@11.19.1': + resolution: {integrity: sha512-NxjZe+rqWhr+RT8/Ik+5ptA3oz7tUw361Wa5RWQXKnfqwSSHdHyrw6IdcTfYuml9dM856AlKWZIUXDmA9kkiBQ==} + cpu: [x64] + os: [linux] + + '@oxc-resolver/binding-linux-x64-musl@11.19.1': + resolution: {integrity: sha512-cM/hQwsO3ReJg5kR+SpI69DMfvNCp+A/eVR4b4YClE5bVZwz8rh2Nh05InhwI5HR/9cArbEkzMjcKgTHS6UaNw==} + cpu: [x64] + os: [linux] + + '@oxc-resolver/binding-openharmony-arm64@11.19.1': + resolution: {integrity: sha512-QF080IowFB0+9Rh6RcD19bdgh49BpQHUW5TajG1qvWHvmrQznTZZjYlgE2ltLXyKY+qs4F/v5xuX1XS7Is+3qA==} + cpu: [arm64] + os: [openharmony] + + '@oxc-resolver/binding-wasm32-wasi@11.19.1': + resolution: {integrity: sha512-w8UCKhX826cP/ZLokXDS6+milN8y4X7zidsAttEdWlVoamTNf6lhBJldaWr3ukTDiye7s4HRcuPEPOXNC432Vg==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@oxc-resolver/binding-win32-arm64-msvc@11.19.1': + resolution: {integrity: sha512-nJ4AsUVZrVKwnU/QRdzPCCrO0TrabBqgJ8pJhXITdZGYOV28TIYystV1VFLbQ7DtAcaBHpocT5/ZJnF78YJPtQ==} + cpu: [arm64] + os: [win32] + + '@oxc-resolver/binding-win32-ia32-msvc@11.19.1': + resolution: {integrity: sha512-EW+ND5q2Tl+a3pH81l1QbfgbF3HmqgwLfDfVithRFheac8OTcnbXt/JxqD2GbDkb7xYEqy1zNaVFRr3oeG8npA==} + cpu: [ia32] + os: [win32] + + '@oxc-resolver/binding-win32-x64-msvc@11.19.1': + resolution: {integrity: sha512-6hIU3RQu45B+VNTY4Ru8ppFwjVS/S5qwYyGhBotmjxfEKk41I2DlGtRfGJndZ5+6lneE2pwloqunlOyZuX/XAw==} + cpu: [x64] + os: [win32] + '@popperjs/core@2.11.8': resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} @@ -1397,67 +1649,56 @@ packages: resolution: {integrity: sha512-EHMUcDwhtdRGlXZsGSIuXSYwD5kOT9NVnx9sqzYiwAc91wfYOE1g1djOEDseZJKKqtHAHGwnGPQu3kytmfaXLQ==} cpu: [arm] os: [linux] - libc: [glibc] '@rollup/rollup-linux-arm-musleabihf@4.54.0': resolution: {integrity: sha512-+pBrqEjaakN2ySv5RVrj/qLytYhPKEUwk+e3SFU5jTLHIcAtqh2rLrd/OkbNuHJpsBgxsD8ccJt5ga/SeG0JmA==} cpu: [arm] os: [linux] - libc: [musl] '@rollup/rollup-linux-arm64-gnu@4.54.0': resolution: {integrity: sha512-NSqc7rE9wuUaRBsBp5ckQ5CVz5aIRKCwsoa6WMF7G01sX3/qHUw/z4pv+D+ahL1EIKy6Enpcnz1RY8pf7bjwng==} cpu: [arm64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-arm64-musl@4.54.0': resolution: {integrity: sha512-gr5vDbg3Bakga5kbdpqx81m2n9IX8M6gIMlQQIXiLTNeQW6CucvuInJ91EuCJ/JYvc+rcLLsDFcfAD1K7fMofg==} cpu: [arm64] os: [linux] - libc: [musl] '@rollup/rollup-linux-loong64-gnu@4.54.0': resolution: {integrity: sha512-gsrtB1NA3ZYj2vq0Rzkylo9ylCtW/PhpLEivlgWe0bpgtX5+9j9EZa0wtZiCjgu6zmSeZWyI/e2YRX1URozpIw==} cpu: [loong64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-ppc64-gnu@4.54.0': resolution: {integrity: sha512-y3qNOfTBStmFNq+t4s7Tmc9hW2ENtPg8FeUD/VShI7rKxNW7O4fFeaYbMsd3tpFlIg1Q8IapFgy7Q9i2BqeBvA==} cpu: [ppc64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-riscv64-gnu@4.54.0': resolution: {integrity: sha512-89sepv7h2lIVPsFma8iwmccN7Yjjtgz0Rj/Ou6fEqg3HDhpCa+Et+YSufy27i6b0Wav69Qv4WBNl3Rs6pwhebQ==} cpu: [riscv64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-riscv64-musl@4.54.0': resolution: {integrity: sha512-ZcU77ieh0M2Q8Ur7D5X7KvK+UxbXeDHwiOt/CPSBTI1fBmeDMivW0dPkdqkT4rOgDjrDDBUed9x4EgraIKoR2A==} cpu: [riscv64] os: [linux] - libc: [musl] '@rollup/rollup-linux-s390x-gnu@4.54.0': resolution: {integrity: sha512-2AdWy5RdDF5+4YfG/YesGDDtbyJlC9LHmL6rZw6FurBJ5n4vFGupsOBGfwMRjBYH7qRQowT8D/U4LoSvVwOhSQ==} cpu: [s390x] os: [linux] - libc: [glibc] '@rollup/rollup-linux-x64-gnu@4.54.0': resolution: {integrity: sha512-WGt5J8Ij/rvyqpFexxk3ffKqqbLf9AqrTBbWDk7ApGUzaIs6V+s2s84kAxklFwmMF/vBNGrVdYgbblCOFFezMQ==} cpu: [x64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-x64-musl@4.54.0': resolution: {integrity: sha512-JzQmb38ATzHjxlPHuTH6tE7ojnMKM2kYNzt44LO/jJi8BpceEC8QuXYA908n8r3CNuG/B3BV8VR3Hi1rYtmPiw==} cpu: [x64] os: [linux] - libc: [musl] '@rollup/rollup-openharmony-arm64@4.54.0': resolution: {integrity: sha512-huT3fd0iC7jigGh7n3q/+lfPcXxBi+om/Rs3yiFxjvSxbSB6aohDFXbWvlspaqjeOh+hx7DDHS+5Es5qRkWkZg==} @@ -1611,35 +1852,30 @@ packages: engines: {node: '>= 10'} cpu: [arm64] os: [linux] - libc: [glibc] '@tauri-apps/cli-linux-arm64-musl@2.10.1': resolution: {integrity: sha512-MIj78PDDGjkg3NqGptDOGgfXks7SYJwhiMh8SBoZS+vfdz7yP5jN18bNaLnDhsVIPARcAhE1TlsZe/8Yxo2zqg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - libc: [musl] '@tauri-apps/cli-linux-riscv64-gnu@2.10.1': resolution: {integrity: sha512-X0lvOVUg8PCVaoEtEAnpxmnkwlE1gcMDTqfhbefICKDnOTJ5Est3qL0SrWxizDackIOKBcvtpejrSiVpuJI1kw==} engines: {node: '>= 10'} cpu: [riscv64] os: [linux] - libc: [glibc] '@tauri-apps/cli-linux-x64-gnu@2.10.1': resolution: {integrity: sha512-2/12bEzsJS9fAKybxgicCDFxYD1WEI9kO+tlDwX5znWG2GwMBaiWcmhGlZ8fi+DMe9CXlcVarMTYc0L3REIRxw==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - libc: [glibc] '@tauri-apps/cli-linux-x64-musl@2.10.1': resolution: {integrity: sha512-Y8J0ZzswPz50UcGOFuXGEMrxbjwKSPgXftx5qnkuMs2rmwQB5ssvLb6tn54wDSYxe7S6vlLob9vt0VKuNOaCIQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - libc: [musl] '@tauri-apps/cli-win32-arm64-msvc@2.10.1': resolution: {integrity: sha512-iSt5B86jHYAPJa/IlYw++SXtFPGnWtFJriHn7X0NFBVunF6zu9+/zOn8OgqIWSl8RgzhLGXQEEtGBdR4wzpVgg==} @@ -1884,6 +2120,9 @@ packages: resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} engines: {node: '>= 10'} + '@tybys/wasm-util@0.10.1': + resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} + '@types/babel__core@7.20.5': resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} @@ -2057,6 +2296,9 @@ packages: '@types/prop-types@15.7.15': resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==} + '@types/qrcode@1.5.6': + resolution: {integrity: sha512-te7NQcV2BOvdj2b1hCAHzAoMNuj65kNBMz0KBaxM6c3VGBOhU0dURQKOtH8CFNI/dsKkwlv32p26qYQTWoB5bw==} + '@types/react-dom@18.3.7': resolution: {integrity: sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==} peerDependencies: @@ -2214,15 +2456,26 @@ packages: acorn-globals@6.0.0: resolution: {integrity: sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==} + acorn-jsx-walk@2.0.0: + resolution: {integrity: sha512-uuo6iJj4D4ygkdzd6jPtcxs8vZgDX9YFIkqczGImoypX2fQ4dVImmu3UzA4ynixCIMTrEOWW+95M2HuBaCEOVA==} + acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + acorn-loose@8.5.2: + resolution: {integrity: sha512-PPvV6g8UGMGgjrMu+n/f9E/tCSkNQ2Y97eFvuVdJfG11+xdIeDcLyNdC8SHcrHbRqkfwLASdplyR6B6sKM1U4A==} + engines: {node: '>=0.4.0'} + acorn-walk@7.2.0: resolution: {integrity: sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==} engines: {node: '>=0.4.0'} + acorn-walk@8.3.5: + resolution: {integrity: sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==} + engines: {node: '>=0.4.0'} + acorn@7.4.1: resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==} engines: {node: '>=0.4.0'} @@ -2240,6 +2493,9 @@ packages: ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + ajv@8.18.0: + resolution: {integrity: sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==} + ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -2345,6 +2601,10 @@ packages: resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} engines: {node: '>= 6'} + camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + camelcase@6.3.0: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} @@ -2405,6 +2665,9 @@ packages: class-variance-authority@0.7.1: resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==} + cliui@6.0.0: + resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} + clsx@2.1.1: resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} engines: {node: '>=6'} @@ -2433,6 +2696,10 @@ packages: comma-separated-tokens@2.0.3: resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} + commander@13.1.0: + resolution: {integrity: sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==} + engines: {node: '>=18'} + commander@4.1.1: resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} engines: {node: '>= 6'} @@ -2694,6 +2961,10 @@ packages: supports-color: optional: true + decamelize@1.2.0: + resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} + engines: {node: '>=0.10.0'} + decimal.js@10.6.0: resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} @@ -2721,6 +2992,11 @@ packages: delegates@1.0.0: resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} + dependency-cruiser@16.10.4: + resolution: {integrity: sha512-hrxVOjIm8idZ9ZVDGSyyG3SHiNcEUPhL6RTEmO/3wfQWLepH5pA3nuDMMrcJ1DkZztFA7xg3tk8OVO+MmwwH9w==} + engines: {node: ^18.17||>=20} + hasBin: true + dequal@2.0.3: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} @@ -2738,6 +3014,9 @@ packages: didyoumean@1.2.2: resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} + dijkstrajs@1.0.3: + resolution: {integrity: sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==} + dlv@1.1.3: resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} @@ -2762,6 +3041,10 @@ packages: emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + enhanced-resolve@5.20.1: + resolution: {integrity: sha512-Qohcme7V1inbAfvjItgw0EaxVX5q2rdVEZHRBrEQdRZTssLDGsL8Lwrznl8oQ/6kuTJONLaDcGjkNP247XEhcA==} + engines: {node: '>=10.13.0'} + entities@4.5.0: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} @@ -2918,12 +3201,18 @@ packages: fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + fast-uri@3.1.0: + resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} + fastq@1.20.1: resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} fault@1.0.4: resolution: {integrity: sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA==} + fd-package-json@2.0.0: + resolution: {integrity: sha512-jKmm9YtsNXN789RS/0mSzOC1NUq9mkVd65vbSSVsKdjGvYXBuE4oWe2QOEoFeRmJg+lPuZxpmrfFclNhoRMneQ==} + fdir@6.5.0: resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} engines: {node: '>=12.0.0'} @@ -2941,6 +3230,10 @@ packages: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} + find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + find-up@5.0.0: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} @@ -2960,6 +3253,11 @@ packages: resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==} engines: {node: '>=0.4.x'} + formatly@0.3.0: + resolution: {integrity: sha512-9XNj/o4wrRFyhSMJOvsuyMwy8aUfBaZ1VrqHVfohyXf0Sw0e+yfKG+xZaY3arGCOMdwFsqObtzVOc1gU9KiT9w==} + engines: {node: '>=18.3.0'} + hasBin: true + fraction.js@5.3.4: resolution: {integrity: sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==} @@ -2987,6 +3285,10 @@ packages: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + get-intrinsic@1.3.0: resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} engines: {node: '>= 0.4'} @@ -3002,6 +3304,9 @@ packages: get-tsconfig@4.13.0: resolution: {integrity: sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==} + get-tsconfig@4.13.7: + resolution: {integrity: sha512-7tN6rFgBlMgpBML5j8typ92BKFi2sFQvIdpAqLA2beia5avZDrMs0FLZiM5etShWq5irVyGcGMEA1jcDaK7A/Q==} + glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -3012,7 +3317,11 @@ packages: glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - deprecated: Glob versions prior to v9 are no longer supported + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me + + global-directory@4.0.1: + resolution: {integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==} + engines: {node: '>=18'} globals@14.0.0: resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} @@ -3026,6 +3335,9 @@ packages: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} engines: {node: '>= 0.4'} + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + hachure-fill@0.5.2: resolution: {integrity: sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==} @@ -3157,6 +3469,10 @@ packages: inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + ini@4.1.1: + resolution: {integrity: sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + inline-style-parser@0.2.7: resolution: {integrity: sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==} @@ -3167,6 +3483,10 @@ packages: resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} engines: {node: '>=12'} + interpret@3.1.1: + resolution: {integrity: sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==} + engines: {node: '>=10.13.0'} + interval-tree-1d@1.0.4: resolution: {integrity: sha512-wY8QJH+6wNI0uh4pDQzMvl+478Qh7Rl4qLmqiluxALlNvl+I+o5x38Pw3/z7mDPTPS1dQalZJXsmbvxx5gclhQ==} @@ -3205,10 +3525,18 @@ packages: is-hexadecimal@2.0.1: resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==} + is-installed-globally@1.0.0: + resolution: {integrity: sha512-K55T22lfpQ63N4KEN57jZUAaAYqYHEe8veb/TycJRk9DdSCLLcovXz/mL6mOnhQaZsQGwPhuFopdQIlqGSEjiQ==} + engines: {node: '>=18'} + is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} + is-path-inside@4.0.0: + resolution: {integrity: sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==} + engines: {node: '>=12'} + is-plain-obj@4.1.0: resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} engines: {node: '>=12'} @@ -3226,6 +3554,10 @@ packages: resolution: {integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==} hasBin: true + jiti@2.6.1: + resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} + hasBin: true + jotai@2.16.1: resolution: {integrity: sha512-vrHcAbo3P7Br37C8Bv6JshMtlKMPqqmx0DDREtTjT4nf3QChDrYdbH+4ik/9V0cXA57dK28RkJ5dctYvavcIlg==} engines: {node: '>=12.20.0'} @@ -3286,6 +3618,9 @@ packages: json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} @@ -3304,6 +3639,15 @@ packages: khroma@2.1.0: resolution: {integrity: sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==} + kleur@3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} + + knip@6.0.5: + resolution: {integrity: sha512-+i9e/ZKuYlECB5iIK82NQwnYso4oNLBhzsTbXhSqCG1qfGi6D84GNtRENafmS3C0lABX8Wf3BKM434nPXi2AbQ==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + langium@4.2.1: resolution: {integrity: sha512-zu9QWmjpzJcomzdJQAHgDVhLGq5bLosVak1KVa40NzQHXfqr4eAHupvnPOVXEoLkg6Ocefvf/93d//SB7du4YQ==} engines: {node: '>=20.10.0', npm: '>=10.2.3'} @@ -3331,6 +3675,10 @@ packages: linkifyjs@4.3.2: resolution: {integrity: sha512-NT1CJtq3hHIreOianA8aSXn6Cw0JzYOuDQbOrSPe7gqFnCpKP++MQe3ODgO3oh2GJFORkAAdqredOa60z63GbA==} + locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} @@ -3447,6 +3795,10 @@ packages: mdurl@2.0.0: resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} + memoize@10.2.0: + resolution: {integrity: sha512-DeC6b7QBrZsRs3Y02A6A7lQyzFbsQbqgjI6UW0GigGWV+u1s25TycMr0XHZE4cJce7rY/vyw2ctMQqfDkIhUEA==} + engines: {node: '>=18'} + merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} @@ -3556,6 +3908,10 @@ packages: resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} engines: {node: '>= 0.6'} + mimic-function@5.0.1: + resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} + engines: {node: '>=18'} + mimic-response@2.1.0: resolution: {integrity: sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==} engines: {node: '>=8'} @@ -3567,6 +3923,9 @@ packages: resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} engines: {node: '>=16 || 14 >=14.17'} + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + minipass@3.3.6: resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} engines: {node: '>=8'} @@ -3653,14 +4012,33 @@ packages: orderedmap@2.1.1: resolution: {integrity: sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g==} + oxc-parser@0.120.0: + resolution: {integrity: sha512-WyPWZlcIm+Fkte63FGfgFB8mAAk33aH9h5N9lphXVOHSXEBFFsmYdOBedVKly363aWABjZdaj/m9lBfEY4wt+w==} + engines: {node: ^20.19.0 || >=22.12.0} + + oxc-resolver@11.19.1: + resolution: {integrity: sha512-qE/CIg/spwrTBFt5aKmwe3ifeDdLfA2NESN30E42X/lII5ClF8V7Wt6WIJhcGZjp0/Q+nQ+9vgxGk//xZNX2hg==} + + p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + p-limit@3.1.0: resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} engines: {node: '>=10'} + p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + p-locate@5.0.0: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} + p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + package-manager-detector@1.6.0: resolution: {integrity: sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==} @@ -3732,6 +4110,10 @@ packages: pkg-types@1.3.1: resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} + pngjs@5.0.0: + resolution: {integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==} + engines: {node: '>=10.13.0'} + points-on-curve@0.2.0: resolution: {integrity: sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A==} @@ -3802,6 +4184,10 @@ packages: resolution: {integrity: sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==} engines: {node: '>=6'} + prompts@2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} + property-information@7.1.0: resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==} @@ -3877,6 +4263,11 @@ packages: pure-rand@7.0.1: resolution: {integrity: sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ==} + qrcode@1.5.4: + resolution: {integrity: sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==} + engines: {node: '>=10.13.0'} + hasBin: true + querystringify@2.2.0: resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} @@ -3991,9 +4382,17 @@ packages: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} + rechoir@0.8.0: + resolution: {integrity: sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==} + engines: {node: '>= 10.13.0'} + refractor@5.0.0: resolution: {integrity: sha512-QXOrHQF5jOpjjLfiNk5GFnWhRXvxjUVnlFxkeDmewR5sXkr3iM46Zo+CnRR8B+MDVqkULW4EcLVcRBNOPXHosw==} + regexp-tree@0.1.27: + resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==} + hasBin: true + rehype-katex@7.0.1: resolution: {integrity: sha512-OiM2wrZ/wuhKkigASodFoo8wimG3H12LWQaH8qSPVJn9apWKFSH3YOCtbKpBorTVw/eI7cuT21XBbvwEswbIOA==} @@ -4015,6 +4414,17 @@ packages: remark-stringify@11.0.0: resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==} + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + require-main-filename@2.0.0: + resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} + requires-port@1.0.0: resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} @@ -4065,6 +4475,9 @@ packages: safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + safe-regex@2.1.1: + resolution: {integrity: sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A==} + safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} @@ -4117,6 +4530,13 @@ packages: simple-get@3.1.1: resolution: {integrity: sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==} + sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + + smol-toml@1.6.1: + resolution: {integrity: sha512-dWUG8F5sIIARXih1DTaQAX4SsiTXhInKf1buxdY9DIg4ZYPZK5nGM1VRIYmEbDbsHt7USo99xSLFu5Q1IqTmsg==} + engines: {node: '>= 18'} + snake-case@3.0.4: resolution: {integrity: sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==} @@ -4160,10 +4580,18 @@ packages: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} + strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + strip-json-comments@3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} + strip-json-comments@5.0.3: + resolution: {integrity: sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==} + engines: {node: '>=14.16'} + strip-literal@3.1.0: resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==} @@ -4216,9 +4644,17 @@ packages: engines: {node: '>=14.0.0'} hasBin: true + tapable@2.3.2: + resolution: {integrity: sha512-1MOpMXuhGzGL5TTCZFItxCc0AARf1EZFQkGqMm7ERKj8+Hgr5oLvJOVFcC+lRmR8hCe2S3jC4T5D7Vg/d7/fhA==} + engines: {node: '>=6'} + tar@6.2.1: resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} engines: {node: '>=10'} + deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me + + teamcity-service-messages@0.1.14: + resolution: {integrity: sha512-29aQwaHqm8RMX74u2o/h1KbMLP89FjNiMxD9wbF2BbWOnbM+q+d1sCEC+MqCc4QW3NJykn77OMpTFw/xTHIc0w==} thenify-all@1.6.0: resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} @@ -4297,6 +4733,14 @@ packages: ts-interface-checker@0.1.13: resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + tsconfig-paths-webpack-plugin@4.2.0: + resolution: {integrity: sha512-zbem3rfRS8BgeNK50Zz5SIQgXzLafiHjOwUAvk/38/o1jHn/V5QAgVUcz884or7WYcPaH3N2CIfUc2u0ul7UcA==} + engines: {node: '>=10.13.0'} + + tsconfig-paths@4.2.0: + resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==} + engines: {node: '>=6'} + tslib@2.6.2: resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} @@ -4326,6 +4770,10 @@ packages: ufo@1.6.3: resolution: {integrity: sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==} + unbash@2.2.0: + resolution: {integrity: sha512-X2wH19RAPZE3+ldGicOkoj/SIA83OIxcJ6Cuaw23hf8Xc6fQpvZXY0SftE2JgS0QhYLUG4uwodSI3R53keyh7w==} + engines: {node: '>=14'} + undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} @@ -4518,6 +4966,15 @@ packages: resolution: {integrity: sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==} engines: {node: '>=14'} + walk-up-path@4.0.0: + resolution: {integrity: sha512-3hu+tD8YzSLGuFYtPRb48vdhKMi0KQV5sn+uWr8+7dMEq/2G/dtLrdDinkLjqq5TIbIBjYJ4Ax/n3YiaW7QM8A==} + engines: {node: 20 || >=22} + + watskeburt@4.2.3: + resolution: {integrity: sha512-uG9qtQYoHqAsnT711nG5iZc/8M5inSmkGCOp7pFaytKG2aTfIca7p//CjiVzAE4P7hzaYuCozMjNNaLgmhbK5g==} + engines: {node: ^18||>=20} + hasBin: true + web-namespaces@2.0.1: resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==} @@ -4552,6 +5009,9 @@ packages: whatwg-url@5.0.0: resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + which-module@2.0.1: + resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} + which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -4569,6 +5029,10 @@ packages: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} + wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} @@ -4591,16 +5055,35 @@ packages: xmlchars@2.2.0: resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + y18n@4.0.3: + resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} + yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + yaml@2.8.3: + resolution: {integrity: sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==} + engines: {node: '>= 14.6'} + hasBin: true + + yargs-parser@18.1.3: + resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} + engines: {node: '>=6'} + + yargs@15.4.1: + resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} + engines: {node: '>=8'} + yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} + zod@4.3.6: + resolution: {integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==} + zustand@5.0.11: resolution: {integrity: sha512-fdZY+dk7zn/vbWNCYmzZULHRrss0jx5pPFiOuMZ/5HJN6Yv3u+1Wswy/4MpZEkEGhtNH+pwxZB8OKgUBPzYAGg==} engines: {node: '>=12.20.0'} @@ -4766,6 +5249,22 @@ snapshots: '@chevrotain/utils@11.1.2': {} + '@emnapi/core@1.9.1': + dependencies: + '@emnapi/wasi-threads': 1.2.0 + tslib: 2.8.1 + optional: true + + '@emnapi/runtime@1.9.1': + dependencies: + tslib: 2.8.1 + optional: true + + '@emnapi/wasi-threads@1.2.0': + dependencies: + tslib: 2.8.1 + optional: true + '@emotion/is-prop-valid@1.2.2': dependencies: '@emotion/memoize': 0.8.1 @@ -5061,6 +5560,13 @@ snapshots: '@mixmark-io/domino@2.2.0': {} + '@napi-rs/wasm-runtime@1.1.1': + dependencies: + '@emnapi/core': 1.9.1 + '@emnapi/runtime': 1.9.1 + '@tybys/wasm-util': 0.10.1 + optional: true + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -5079,6 +5585,132 @@ snapshots: interval-tree-1d: 1.0.4 isoformat: 0.2.1 + '@oxc-parser/binding-android-arm-eabi@0.120.0': + optional: true + + '@oxc-parser/binding-android-arm64@0.120.0': + optional: true + + '@oxc-parser/binding-darwin-arm64@0.120.0': + optional: true + + '@oxc-parser/binding-darwin-x64@0.120.0': + optional: true + + '@oxc-parser/binding-freebsd-x64@0.120.0': + optional: true + + '@oxc-parser/binding-linux-arm-gnueabihf@0.120.0': + optional: true + + '@oxc-parser/binding-linux-arm-musleabihf@0.120.0': + optional: true + + '@oxc-parser/binding-linux-arm64-gnu@0.120.0': + optional: true + + '@oxc-parser/binding-linux-arm64-musl@0.120.0': + optional: true + + '@oxc-parser/binding-linux-ppc64-gnu@0.120.0': + optional: true + + '@oxc-parser/binding-linux-riscv64-gnu@0.120.0': + optional: true + + '@oxc-parser/binding-linux-riscv64-musl@0.120.0': + optional: true + + '@oxc-parser/binding-linux-s390x-gnu@0.120.0': + optional: true + + '@oxc-parser/binding-linux-x64-gnu@0.120.0': + optional: true + + '@oxc-parser/binding-linux-x64-musl@0.120.0': + optional: true + + '@oxc-parser/binding-openharmony-arm64@0.120.0': + optional: true + + '@oxc-parser/binding-wasm32-wasi@0.120.0': + dependencies: + '@napi-rs/wasm-runtime': 1.1.1 + optional: true + + '@oxc-parser/binding-win32-arm64-msvc@0.120.0': + optional: true + + '@oxc-parser/binding-win32-ia32-msvc@0.120.0': + optional: true + + '@oxc-parser/binding-win32-x64-msvc@0.120.0': + optional: true + + '@oxc-project/types@0.120.0': {} + + '@oxc-resolver/binding-android-arm-eabi@11.19.1': + optional: true + + '@oxc-resolver/binding-android-arm64@11.19.1': + optional: true + + '@oxc-resolver/binding-darwin-arm64@11.19.1': + optional: true + + '@oxc-resolver/binding-darwin-x64@11.19.1': + optional: true + + '@oxc-resolver/binding-freebsd-x64@11.19.1': + optional: true + + '@oxc-resolver/binding-linux-arm-gnueabihf@11.19.1': + optional: true + + '@oxc-resolver/binding-linux-arm-musleabihf@11.19.1': + optional: true + + '@oxc-resolver/binding-linux-arm64-gnu@11.19.1': + optional: true + + '@oxc-resolver/binding-linux-arm64-musl@11.19.1': + optional: true + + '@oxc-resolver/binding-linux-ppc64-gnu@11.19.1': + optional: true + + '@oxc-resolver/binding-linux-riscv64-gnu@11.19.1': + optional: true + + '@oxc-resolver/binding-linux-riscv64-musl@11.19.1': + optional: true + + '@oxc-resolver/binding-linux-s390x-gnu@11.19.1': + optional: true + + '@oxc-resolver/binding-linux-x64-gnu@11.19.1': + optional: true + + '@oxc-resolver/binding-linux-x64-musl@11.19.1': + optional: true + + '@oxc-resolver/binding-openharmony-arm64@11.19.1': + optional: true + + '@oxc-resolver/binding-wasm32-wasi@11.19.1': + dependencies: + '@napi-rs/wasm-runtime': 1.1.1 + optional: true + + '@oxc-resolver/binding-win32-arm64-msvc@11.19.1': + optional: true + + '@oxc-resolver/binding-win32-ia32-msvc@11.19.1': + optional: true + + '@oxc-resolver/binding-win32-x64-msvc@11.19.1': + optional: true + '@popperjs/core@2.11.8': {} '@radix-ui/number@1.1.1': {} @@ -6032,6 +6664,11 @@ snapshots: '@tootallnate/once@2.0.0': {} + '@tybys/wasm-util@0.10.1': + dependencies: + tslib: 2.8.1 + optional: true + '@types/babel__core@7.20.5': dependencies: '@babel/parser': 7.28.5 @@ -6242,6 +6879,10 @@ snapshots: '@types/prop-types@15.7.15': {} + '@types/qrcode@1.5.6': + dependencies: + '@types/node': 22.19.3 + '@types/react-dom@18.3.7(@types/react@18.3.27)': dependencies: '@types/react': 18.3.27 @@ -6444,13 +7085,23 @@ snapshots: acorn-walk: 7.2.0 optional: true + acorn-jsx-walk@2.0.0: {} + acorn-jsx@5.3.2(acorn@8.15.0): dependencies: acorn: 8.15.0 + acorn-loose@8.5.2: + dependencies: + acorn: 8.15.0 + acorn-walk@7.2.0: optional: true + acorn-walk@8.3.5: + dependencies: + acorn: 8.15.0 + acorn@7.4.1: optional: true @@ -6469,8 +7120,14 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 - ansi-regex@5.0.1: - optional: true + ajv@8.18.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.0 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + ansi-regex@5.0.1: {} ansi-styles@4.3.0: dependencies: @@ -6565,6 +7222,8 @@ snapshots: camelcase-css@2.0.1: {} + camelcase@5.3.1: {} + camelcase@6.3.0: {} camelize@1.0.1: {} @@ -6639,6 +7298,12 @@ snapshots: dependencies: clsx: 2.1.1 + cliui@6.0.0: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 6.2.0 + clsx@2.1.1: {} cmdk@1.1.1(@types/react-dom@18.3.7(@types/react@18.3.27))(@types/react@18.3.27)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): @@ -6668,6 +7333,8 @@ snapshots: comma-separated-tokens@2.0.3: {} + commander@13.1.0: {} + commander@4.1.1: {} commander@7.2.0: {} @@ -6944,6 +7611,8 @@ snapshots: dependencies: ms: 2.1.3 + decamelize@1.2.0: {} + decimal.js@10.6.0: {} decode-named-character-reference@1.2.0: @@ -6968,6 +7637,31 @@ snapshots: delegates@1.0.0: optional: true + dependency-cruiser@16.10.4: + dependencies: + acorn: 8.15.0 + acorn-jsx: 5.3.2(acorn@8.15.0) + acorn-jsx-walk: 2.0.0 + acorn-loose: 8.5.2 + acorn-walk: 8.3.5 + ajv: 8.18.0 + commander: 13.1.0 + enhanced-resolve: 5.20.1 + ignore: 7.0.5 + interpret: 3.1.1 + is-installed-globally: 1.0.0 + json5: 2.2.3 + memoize: 10.2.0 + picocolors: 1.1.1 + picomatch: 4.0.3 + prompts: 2.4.2 + rechoir: 0.8.0 + safe-regex: 2.1.1 + semver: 7.7.3 + teamcity-service-messages: 0.1.14 + tsconfig-paths-webpack-plugin: 4.2.0 + watskeburt: 4.2.3 + dequal@2.0.3: {} detect-libc@2.1.2: @@ -6981,6 +7675,8 @@ snapshots: didyoumean@1.2.2: {} + dijkstrajs@1.0.3: {} + dlv@1.1.3: {} domexception@4.0.0: @@ -7004,8 +7700,12 @@ snapshots: electron-to-chromium@1.5.267: {} - emoji-regex@8.0.0: - optional: true + emoji-regex@8.0.0: {} + + enhanced-resolve@5.20.1: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.3.2 entities@4.5.0: {} @@ -7223,6 +7923,8 @@ snapshots: fast-levenshtein@2.0.6: {} + fast-uri@3.1.0: {} + fastq@1.20.1: dependencies: reusify: 1.1.0 @@ -7231,6 +7933,10 @@ snapshots: dependencies: format: 0.2.2 + fd-package-json@2.0.0: + dependencies: + walk-up-path: 4.0.0 + fdir@6.5.0(picomatch@4.0.3): optionalDependencies: picomatch: 4.0.3 @@ -7243,6 +7949,11 @@ snapshots: dependencies: to-regex-range: 5.0.1 + find-up@4.1.0: + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + find-up@5.0.0: dependencies: locate-path: 6.0.0 @@ -7265,6 +7976,10 @@ snapshots: format@0.2.2: {} + formatly@0.3.0: + dependencies: + fd-package-json: 2.0.0 + fraction.js@5.3.4: {} fs-minipass@2.1.0: @@ -7295,6 +8010,8 @@ snapshots: gensync@1.0.0-beta.2: {} + get-caller-file@2.0.5: {} + get-intrinsic@1.3.0: dependencies: call-bind-apply-helpers: 1.0.2 @@ -7319,6 +8036,10 @@ snapshots: dependencies: resolve-pkg-maps: 1.0.0 + get-tsconfig@4.13.7: + dependencies: + resolve-pkg-maps: 1.0.0 + glob-parent@5.1.2: dependencies: is-glob: 4.0.3 @@ -7337,12 +8058,18 @@ snapshots: path-is-absolute: 1.0.1 optional: true + global-directory@4.0.1: + dependencies: + ini: 4.1.1 + globals@14.0.0: {} globals@15.15.0: {} gopd@1.2.0: {} + graceful-fs@4.2.11: {} + hachure-fill@0.5.2: {} has-flag@4.0.0: {} @@ -7547,12 +8274,16 @@ snapshots: inherits@2.0.4: optional: true + ini@4.1.1: {} + inline-style-parser@0.2.7: {} internmap@1.0.1: {} internmap@2.0.3: {} + interpret@3.1.1: {} + interval-tree-1d@1.0.4: dependencies: binary-search-bounds: 2.0.5 @@ -7578,8 +8309,7 @@ snapshots: is-extglob@2.1.1: {} - is-fullwidth-code-point@3.0.0: - optional: true + is-fullwidth-code-point@3.0.0: {} is-glob@4.0.3: dependencies: @@ -7587,8 +8317,15 @@ snapshots: is-hexadecimal@2.0.1: {} + is-installed-globally@1.0.0: + dependencies: + global-directory: 4.0.1 + is-path-inside: 4.0.0 + is-number@7.0.0: {} + is-path-inside@4.0.0: {} + is-plain-obj@4.1.0: {} is-potential-custom-element-name@1.0.1: {} @@ -7599,6 +8336,8 @@ snapshots: jiti@1.21.7: {} + jiti@2.6.1: {} + jotai@2.16.1(@babel/core@7.28.5)(@babel/template@7.27.2)(@types/react@18.3.27)(react@18.3.1): optionalDependencies: '@babel/core': 7.28.5 @@ -7691,6 +8430,8 @@ snapshots: json-schema-traverse@0.4.1: {} + json-schema-traverse@1.0.0: {} + json-stable-stringify-without-jsonify@1.0.1: {} json5@2.2.3: {} @@ -7705,6 +8446,26 @@ snapshots: khroma@2.1.0: {} + kleur@3.0.3: {} + + knip@6.0.5: + dependencies: + '@nodelib/fs.walk': 1.2.8 + fast-glob: 3.3.3 + formatly: 0.3.0 + get-tsconfig: 4.13.7 + jiti: 2.6.1 + minimist: 1.2.8 + oxc-parser: 0.120.0 + oxc-resolver: 11.19.1 + picocolors: 1.1.1 + picomatch: 4.0.3 + smol-toml: 1.6.1 + strip-json-comments: 5.0.3 + unbash: 2.2.0 + yaml: 2.8.3 + zod: 4.3.6 + langium@4.2.1: dependencies: chevrotain: 11.1.2 @@ -7732,6 +8493,10 @@ snapshots: linkifyjs@4.3.2: {} + locate-path@5.0.0: + dependencies: + p-locate: 4.1.0 + locate-path@6.0.0: dependencies: p-locate: 5.0.0 @@ -7960,6 +8725,10 @@ snapshots: mdurl@2.0.0: {} + memoize@10.2.0: + dependencies: + mimic-function: 5.0.1 + merge2@1.4.1: {} mermaid@11.12.3: @@ -8199,6 +8968,8 @@ snapshots: dependencies: mime-db: 1.52.0 + mimic-function@5.0.1: {} + mimic-response@2.1.0: optional: true @@ -8210,6 +8981,8 @@ snapshots: dependencies: brace-expansion: 2.0.2 + minimist@1.2.8: {} + minipass@3.3.6: dependencies: yallist: 4.0.0 @@ -8298,14 +9071,72 @@ snapshots: orderedmap@2.1.1: {} + oxc-parser@0.120.0: + dependencies: + '@oxc-project/types': 0.120.0 + optionalDependencies: + '@oxc-parser/binding-android-arm-eabi': 0.120.0 + '@oxc-parser/binding-android-arm64': 0.120.0 + '@oxc-parser/binding-darwin-arm64': 0.120.0 + '@oxc-parser/binding-darwin-x64': 0.120.0 + '@oxc-parser/binding-freebsd-x64': 0.120.0 + '@oxc-parser/binding-linux-arm-gnueabihf': 0.120.0 + '@oxc-parser/binding-linux-arm-musleabihf': 0.120.0 + '@oxc-parser/binding-linux-arm64-gnu': 0.120.0 + '@oxc-parser/binding-linux-arm64-musl': 0.120.0 + '@oxc-parser/binding-linux-ppc64-gnu': 0.120.0 + '@oxc-parser/binding-linux-riscv64-gnu': 0.120.0 + '@oxc-parser/binding-linux-riscv64-musl': 0.120.0 + '@oxc-parser/binding-linux-s390x-gnu': 0.120.0 + '@oxc-parser/binding-linux-x64-gnu': 0.120.0 + '@oxc-parser/binding-linux-x64-musl': 0.120.0 + '@oxc-parser/binding-openharmony-arm64': 0.120.0 + '@oxc-parser/binding-wasm32-wasi': 0.120.0 + '@oxc-parser/binding-win32-arm64-msvc': 0.120.0 + '@oxc-parser/binding-win32-ia32-msvc': 0.120.0 + '@oxc-parser/binding-win32-x64-msvc': 0.120.0 + + oxc-resolver@11.19.1: + optionalDependencies: + '@oxc-resolver/binding-android-arm-eabi': 11.19.1 + '@oxc-resolver/binding-android-arm64': 11.19.1 + '@oxc-resolver/binding-darwin-arm64': 11.19.1 + '@oxc-resolver/binding-darwin-x64': 11.19.1 + '@oxc-resolver/binding-freebsd-x64': 11.19.1 + '@oxc-resolver/binding-linux-arm-gnueabihf': 11.19.1 + '@oxc-resolver/binding-linux-arm-musleabihf': 11.19.1 + '@oxc-resolver/binding-linux-arm64-gnu': 11.19.1 + '@oxc-resolver/binding-linux-arm64-musl': 11.19.1 + '@oxc-resolver/binding-linux-ppc64-gnu': 11.19.1 + '@oxc-resolver/binding-linux-riscv64-gnu': 11.19.1 + '@oxc-resolver/binding-linux-riscv64-musl': 11.19.1 + '@oxc-resolver/binding-linux-s390x-gnu': 11.19.1 + '@oxc-resolver/binding-linux-x64-gnu': 11.19.1 + '@oxc-resolver/binding-linux-x64-musl': 11.19.1 + '@oxc-resolver/binding-openharmony-arm64': 11.19.1 + '@oxc-resolver/binding-wasm32-wasi': 11.19.1 + '@oxc-resolver/binding-win32-arm64-msvc': 11.19.1 + '@oxc-resolver/binding-win32-ia32-msvc': 11.19.1 + '@oxc-resolver/binding-win32-x64-msvc': 11.19.1 + + p-limit@2.3.0: + dependencies: + p-try: 2.2.0 + p-limit@3.1.0: dependencies: yocto-queue: 0.1.0 + p-locate@4.1.0: + dependencies: + p-limit: 2.3.0 + p-locate@5.0.0: dependencies: p-limit: 3.1.0 + p-try@2.2.0: {} + package-manager-detector@1.6.0: {} parent-module@1.0.1: @@ -8369,6 +9200,8 @@ snapshots: mlly: 1.8.0 pathe: 2.0.3 + pngjs@5.0.0: {} + points-on-curve@0.2.0: {} points-on-path@0.2.1: @@ -8388,13 +9221,14 @@ snapshots: camelcase-css: 2.0.1 postcss: 8.5.6 - postcss-load-config@6.0.1(jiti@1.21.7)(postcss@8.5.6)(tsx@4.21.0): + postcss-load-config@6.0.1(jiti@1.21.7)(postcss@8.5.6)(tsx@4.21.0)(yaml@2.8.3): dependencies: lilconfig: 3.1.3 optionalDependencies: jiti: 1.21.7 postcss: 8.5.6 tsx: 4.21.0 + yaml: 2.8.3 postcss-nested@6.2.0(postcss@8.5.6): dependencies: @@ -8426,6 +9260,11 @@ snapshots: prismjs@1.30.0: {} + prompts@2.4.2: + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + property-information@7.1.0: {} prosemirror-changeset@2.4.0: @@ -8541,6 +9380,12 @@ snapshots: pure-rand@7.0.1: {} + qrcode@1.5.4: + dependencies: + dijkstrajs: 1.0.3 + pngjs: 5.0.0 + yargs: 15.4.1 + querystringify@2.2.0: {} queue-microtask@1.2.3: {} @@ -8659,6 +9504,10 @@ snapshots: dependencies: picomatch: 2.3.1 + rechoir@0.8.0: + dependencies: + resolve: 1.22.11 + refractor@5.0.0: dependencies: '@types/hast': 3.0.4 @@ -8666,6 +9515,8 @@ snapshots: hastscript: 9.0.1 parse-entities: 4.0.2 + regexp-tree@0.1.27: {} + rehype-katex@7.0.1: dependencies: '@types/hast': 3.0.4 @@ -8725,6 +9576,12 @@ snapshots: mdast-util-to-markdown: 2.1.2 unified: 11.0.5 + require-directory@2.1.1: {} + + require-from-string@2.0.2: {} + + require-main-filename@2.0.0: {} + requires-port@1.0.0: {} resolve-from@4.0.0: {} @@ -8794,6 +9651,10 @@ snapshots: safe-buffer@5.2.1: optional: true + safe-regex@2.1.1: + dependencies: + regexp-tree: 0.1.27 + safer-buffer@2.1.2: {} saxes@5.0.1: @@ -8813,8 +9674,7 @@ snapshots: semver@7.7.3: {} - set-blocking@2.0.0: - optional: true + set-blocking@2.0.0: {} set-cookie-parser@2.7.2: {} @@ -8841,6 +9701,10 @@ snapshots: simple-concat: 1.0.1 optional: true + sisteransi@1.0.5: {} + + smol-toml@1.6.1: {} + snake-case@3.0.4: dependencies: dot-case: 3.0.4 @@ -8873,7 +9737,6 @@ snapshots: emoji-regex: 8.0.0 is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 - optional: true string_decoder@1.3.0: dependencies: @@ -8888,10 +9751,13 @@ snapshots: strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 - optional: true + + strip-bom@3.0.0: {} strip-json-comments@3.1.1: {} + strip-json-comments@5.0.3: {} + strip-literal@3.1.0: dependencies: js-tokens: 9.0.1 @@ -8946,7 +9812,7 @@ snapshots: tailwind-merge@2.6.0: {} - tailwindcss@3.4.19(tsx@4.21.0): + tailwindcss@3.4.19(tsx@4.21.0)(yaml@2.8.3): dependencies: '@alloc/quick-lru': 5.2.0 arg: 5.0.2 @@ -8965,7 +9831,7 @@ snapshots: postcss: 8.5.6 postcss-import: 15.1.0(postcss@8.5.6) postcss-js: 4.1.0(postcss@8.5.6) - postcss-load-config: 6.0.1(jiti@1.21.7)(postcss@8.5.6)(tsx@4.21.0) + postcss-load-config: 6.0.1(jiti@1.21.7)(postcss@8.5.6)(tsx@4.21.0)(yaml@2.8.3) postcss-nested: 6.2.0(postcss@8.5.6) postcss-selector-parser: 6.1.2 resolve: 1.22.11 @@ -8974,6 +9840,8 @@ snapshots: - tsx - yaml + tapable@2.3.2: {} + tar@6.2.1: dependencies: chownr: 2.0.0 @@ -8984,6 +9852,8 @@ snapshots: yallist: 4.0.0 optional: true + teamcity-service-messages@0.1.14: {} + thenify-all@1.6.0: dependencies: thenify: 3.3.1 @@ -9053,6 +9923,19 @@ snapshots: ts-interface-checker@0.1.13: {} + tsconfig-paths-webpack-plugin@4.2.0: + dependencies: + chalk: 4.1.2 + enhanced-resolve: 5.20.1 + tapable: 2.3.2 + tsconfig-paths: 4.2.0 + + tsconfig-paths@4.2.0: + dependencies: + json5: 2.2.3 + minimist: 1.2.8 + strip-bom: 3.0.0 + tslib@2.6.2: {} tslib@2.8.1: {} @@ -9078,6 +9961,8 @@ snapshots: ufo@1.6.3: {} + unbash@2.2.0: {} + undici-types@6.21.0: {} unified@11.0.5: @@ -9291,6 +10176,10 @@ snapshots: dependencies: xml-name-validator: 4.0.0 + walk-up-path@4.0.0: {} + + watskeburt@4.2.3: {} + web-namespaces@2.0.1: {} webidl-conversions@3.0.1: @@ -9327,6 +10216,8 @@ snapshots: webidl-conversions: 3.0.1 optional: true + which-module@2.0.1: {} + which@2.0.2: dependencies: isexe: 2.0.0 @@ -9343,6 +10234,12 @@ snapshots: word-wrap@1.2.5: {} + wrap-ansi@6.2.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrappy@1.0.2: optional: true @@ -9352,13 +10249,38 @@ snapshots: xmlchars@2.2.0: {} + y18n@4.0.3: {} + yallist@3.1.1: {} yallist@4.0.0: optional: true + yaml@2.8.3: {} + + yargs-parser@18.1.3: + dependencies: + camelcase: 5.3.1 + decamelize: 1.2.0 + + yargs@15.4.1: + dependencies: + cliui: 6.0.0 + decamelize: 1.2.0 + find-up: 4.1.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + require-main-filename: 2.0.0 + set-blocking: 2.0.0 + string-width: 4.2.3 + which-module: 2.0.1 + y18n: 4.0.3 + yargs-parser: 18.1.3 + yocto-queue@0.1.0: {} + zod@4.3.6: {} + zustand@5.0.11(@types/react@18.3.27)(react@18.3.1)(use-sync-external-store@1.6.0(react@18.3.1)): optionalDependencies: '@types/react': 18.3.27 diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 6678788f2..e29bb9a8e 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -237,6 +237,7 @@ tauri-plugin-dialog.workspace = true tauri-plugin-single-instance.workspace = true tauri-plugin-global-shortcut.workspace = true tauri-plugin-updater.workspace = true +tauri-plugin-deep-link.workspace = true # 序列化 serde.workspace = true @@ -343,7 +344,6 @@ winreg.workspace = true [target.'cfg(target_os = "macos")'.dependencies] cocoa.workspace = true objc.workspace = true -tauri-plugin-deep-link.workspace = true [dev-dependencies] proptest.workspace = true diff --git a/src-tauri/src/services/automation_service/executor.rs b/src-tauri/src/services/automation_service/executor.rs index 05ae4a241..5bbac391b 100644 --- a/src-tauri/src/services/automation_service/executor.rs +++ b/src-tauri/src/services/automation_service/executor.rs @@ -3,17 +3,25 @@ //! 负责把结构化自动化任务映射到 Aster 执行链路。 use super::{AutomationJobRecord, AutomationPayload}; -use crate::agent::{AsterAgentState, AsterAgentWrapper}; +use crate::agent::AsterAgentWrapper; use crate::app::AppState; +use crate::commands::api_key_provider_cmd::ApiKeyProviderServiceState; +use crate::commands::aster_agent_cmd::{ + build_queued_turn_task, build_runtime_queue_executor, AsterChatRequest, +}; use crate::commands::browser_runtime_cmd::{ launch_browser_session_with_db, LaunchBrowserSessionRequest, }; +use crate::config::GlobalConfigManagerState; use crate::database::DbConnection; +use crate::mcp::McpManagerState; +use crate::services::automation_service::AutomationServiceState; use crate::services::workspace_health_service::ensure_workspace_ready_with_auto_relocate; use crate::workspace::WorkspaceManager; +use crate::LogState; use chrono::Utc; use lime_browser_runtime::CdpSessionState; -use serde_json::{json, Value}; +use serde_json::{json, Map, Value}; use tauri::{AppHandle, Manager}; #[derive(Debug)] @@ -50,8 +58,20 @@ pub async fn execute_job( prompt, system_prompt, web_search, + request_metadata, + content_id, } => { - execute_agent_turn(job, db, app_handle, prompt, system_prompt, web_search).await + execute_agent_turn( + job, + db, + app_handle, + prompt, + system_prompt, + web_search, + request_metadata, + content_id, + ) + .await } AutomationPayload::BrowserSession { profile_id, @@ -91,11 +111,13 @@ async fn execute_agent_turn( prompt: String, system_prompt: Option, web_search: bool, + request_metadata: Option, + content_id: Option, ) -> Result { let app = app_handle .as_ref() .ok_or_else(|| "应用句柄不可用,无法执行自动化任务".to_string())?; - let prompt = build_prompt(job, &prompt, system_prompt.as_deref(), web_search); + let prompt = build_prompt(job, &prompt, web_search); let workspace_manager = WorkspaceManager::new(db.clone()); let workspace = workspace_manager @@ -115,16 +137,58 @@ async fn execute_agent_turn( )?; let agent_state = app - .try_state::() + .try_state::() .ok_or_else(|| "AsterAgentState 未初始化".to_string())?; + let api_key_provider_service = app + .try_state::() + .ok_or_else(|| "ApiKeyProviderServiceState 未初始化".to_string())?; + let logs = app + .try_state::() + .ok_or_else(|| "LogState 未初始化".to_string())?; + let config_manager = app + .try_state::() + .ok_or_else(|| "GlobalConfigManagerState 未初始化".to_string())?; + let mcp_manager = app + .try_state::() + .ok_or_else(|| "McpManagerState 未初始化".to_string())?; + let automation_state = app + .try_state::() + .ok_or_else(|| "AutomationServiceState 未初始化".to_string())?; let event_name = format!("automation:agent:{}:{}", job.id, Utc::now().timestamp()); - AsterAgentWrapper::send_message( - &agent_state, - db, - app, - prompt, - session_id.clone(), + let runtime_request = AsterChatRequest { + message: prompt, + session_id: session_id.clone(), event_name, + images: None, + provider_config: None, + provider_preference: None, + model_preference: None, + thinking_enabled: None, + project_id: None, + workspace_id: job.workspace_id.clone(), + web_search: Some(web_search), + search_mode: None, + execution_strategy: None, + auto_continue: None, + system_prompt, + metadata: normalize_agent_turn_request_metadata(request_metadata, content_id.clone()), + turn_id: None, + queue_if_busy: Some(false), + queued_turn_id: None, + }; + let queued_task = build_queued_turn_task(runtime_request)?; + crate::agent::runtime_queue_service::submit_runtime_turn( + app.clone(), + agent_state.inner(), + db, + api_key_provider_service.inner(), + logs.inner(), + config_manager.inner(), + mcp_manager.inner(), + automation_state.inner(), + queued_task, + false, + build_runtime_queue_executor(), ) .await?; @@ -136,6 +200,7 @@ async fn execute_agent_turn( "job_name": job.name.clone(), "workspace_id": job.workspace_id.clone(), "session_id": session_id.clone(), + "content_id": content_id, "status": "success", })), session_id: Some(session_id), @@ -184,24 +249,13 @@ async fn execute_browser_session( }) } -fn build_prompt( - job: &AutomationJobRecord, - prompt: &str, - system_prompt: Option<&str>, - web_search: bool, -) -> String { +fn build_prompt(job: &AutomationJobRecord, prompt: &str, web_search: bool) -> String { let mut sections = vec![ "你是一个自动化任务执行助手。".to_string(), format!("任务名称:{}", job.name), format!("任务描述:{}", job.description.clone().unwrap_or_default()), format!("工作区 ID:{}", job.workspace_id), ]; - if let Some(system_prompt) = system_prompt { - let trimmed = system_prompt.trim(); - if !trimmed.is_empty() { - sections.push(format!("附加系统指令:{trimmed}")); - } - } if web_search { sections.push("允许按需使用 WebSearch。".to_string()); } @@ -209,3 +263,89 @@ fn build_prompt( sections.push(prompt.trim().to_string()); sections.join("\n\n") } + +fn normalize_agent_turn_request_metadata( + request_metadata: Option, + content_id: Option, +) -> Option { + let normalized_content_id = content_id + .as_deref() + .map(str::trim) + .filter(|value| !value.is_empty()) + .map(str::to_string); + + if request_metadata.is_none() && normalized_content_id.is_none() { + return None; + } + + let mut root = match request_metadata { + Some(Value::Object(object)) => object, + Some(other) => { + let mut object = Map::new(); + object.insert("request_metadata".to_string(), other); + object + } + None => Map::new(), + }; + + if let Some(content_id) = normalized_content_id { + let harness_entry = root + .entry("harness".to_string()) + .or_insert_with(|| Value::Object(Map::new())); + if !harness_entry.is_object() { + *harness_entry = Value::Object(Map::new()); + } + if let Some(harness) = harness_entry.as_object_mut() { + harness.insert("content_id".to_string(), Value::String(content_id)); + } + } + + Some(Value::Object(root)) +} + +#[cfg(test)] +mod tests { + use super::*; + use serde_json::json; + + #[test] + fn normalize_agent_turn_request_metadata_should_attach_content_id_to_harness() { + let normalized = normalize_agent_turn_request_metadata( + Some(json!({ + "artifact": { + "artifact_mode": "draft", + "artifact_kind": "analysis" + } + })), + Some("content-1".to_string()), + ) + .expect("normalized metadata"); + + assert_eq!( + normalized + .pointer("/harness/content_id") + .and_then(Value::as_str), + Some("content-1") + ); + assert_eq!( + normalized + .pointer("/artifact/artifact_kind") + .and_then(Value::as_str), + Some("analysis") + ); + } + + #[test] + fn normalize_agent_turn_request_metadata_should_create_minimal_harness_when_only_content_id_exists( + ) { + let normalized = normalize_agent_turn_request_metadata(None, Some("content-2".to_string())) + .expect("normalized metadata"); + + assert_eq!( + normalized + .pointer("/harness/content_id") + .and_then(Value::as_str), + Some("content-2") + ); + } +} diff --git a/src-tauri/src/services/automation_service/mod.rs b/src-tauri/src/services/automation_service/mod.rs index ec553f843..379c87cf8 100644 --- a/src-tauri/src/services/automation_service/mod.rs +++ b/src-tauri/src/services/automation_service/mod.rs @@ -74,6 +74,10 @@ pub enum AutomationPayload { system_prompt: Option, #[serde(default)] web_search: bool, + #[serde(default, skip_serializing_if = "Option::is_none")] + request_metadata: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + content_id: Option, }, BrowserSession { profile_id: String, @@ -749,10 +753,25 @@ fn validate_job(conn: &Connection, job: &AutomationJobRecord) -> Result<(), Stri fn validate_payload(payload: &AutomationPayload) -> Result<(), String> { match payload { - AutomationPayload::AgentTurn { prompt, .. } => { + AutomationPayload::AgentTurn { + prompt, + request_metadata, + content_id, + .. + } => { if prompt.trim().is_empty() { return Err("自动化任务内容不能为空".to_string()); } + if let Some(content_id) = content_id { + if content_id.trim().is_empty() { + return Err("自动化任务 content_id 不能为空字符串".to_string()); + } + } + if let Some(request_metadata) = request_metadata { + if !request_metadata.is_object() { + return Err("自动化任务 request_metadata 必须为对象".to_string()); + } + } } AutomationPayload::BrowserSession { profile_id, .. } => { if profile_id.trim().is_empty() { @@ -1355,4 +1374,40 @@ mod tests { assert!(context.attempt_id.starts_with("dlv-")); assert_eq!(context.execution_retry_count, 2); } + + #[test] + fn validate_payload_should_reject_blank_agent_turn_content_id() { + let payload = AutomationPayload::AgentTurn { + prompt: "汇总今日异常".to_string(), + system_prompt: None, + web_search: false, + request_metadata: Some(json!({ + "harness": { + "theme": "social-media", + } + })), + content_id: Some(" ".to_string()), + }; + + assert_eq!( + validate_payload(&payload), + Err("自动化任务 content_id 不能为空字符串".to_string()) + ); + } + + #[test] + fn validate_payload_should_reject_non_object_request_metadata() { + let payload = AutomationPayload::AgentTurn { + prompt: "汇总今日异常".to_string(), + system_prompt: None, + web_search: false, + request_metadata: Some(json!(["invalid"])), + content_id: Some("content-1".to_string()), + }; + + assert_eq!( + validate_payload(&payload), + Err("自动化任务 request_metadata 必须为对象".to_string()) + ); + } } diff --git a/src/components/agent/chat/AgentChatHomeShell.test.tsx b/src/components/agent/chat/AgentChatHomeShell.test.tsx index 76c5af5e5..aa2706828 100644 --- a/src/components/agent/chat/AgentChatHomeShell.test.tsx +++ b/src/components/agent/chat/AgentChatHomeShell.test.tsx @@ -10,6 +10,7 @@ import { SettingsTabs } from "@/types/settings"; const { mockBuildClawAgentParams, mockCreateAutomationJob, + mockCreateContent, mockHomeShellExecutionStrategy, mockHomeShellModel, mockHomeShellProviderType, @@ -82,6 +83,7 @@ const { runnerType: "instant", defaultExecutorBinding: "agent_turn", executionLocation: "client_default", + defaultArtifactKind: "brief", themeTarget: "video", version: "seed-v1", slotSchema: [ @@ -112,6 +114,7 @@ const { runnerType: "scheduled", defaultExecutorBinding: "automation_job", executionLocation: "client_default", + defaultArtifactKind: "analysis", themeTarget: "social-media", version: "seed-v1", slotSchema: [ @@ -180,6 +183,22 @@ const { ...request, }), ), + mockCreateContent: vi.fn(async (request: Record) => ({ + id: "content-service-skill-1", + project_id: request.project_id, + title: request.title, + content_type: request.content_type, + status: "draft", + order: 0, + word_count: 0, + body: typeof request.body === "string" ? request.body : "", + metadata: + request.metadata && typeof request.metadata === "object" + ? request.metadata + : undefined, + created_at: 1, + updated_at: 1, + })), mockHomeShellProviderType: { current: "mock-provider" }, mockHomeShellModel: { current: "mock-model" }, mockHomeShellExecutionStrategy: { current: "react" }, @@ -366,6 +385,17 @@ vi.mock("@/lib/api/serviceSkillRuns", () => ({ })); vi.mock("@/lib/api/project", () => ({ + createContent: mockCreateContent, + getDefaultContentTypeForProject: vi.fn((projectType: string) => { + switch (projectType) { + case "video": + return "episode"; + case "social-media": + return "post"; + default: + return "document"; + } + }), listProjects: mockListProjects, })); @@ -1138,11 +1168,27 @@ describe("AgentChatHomeShell", () => { await flushEffects(); + expect(mockCreateContent).toHaveBeenCalledWith( + expect.objectContaining({ + project_id: "project-1", + title: "复制短视频脚本", + content_type: "episode", + body: "", + }), + ); expect(onEnterWorkspace).toHaveBeenCalledWith( expect.objectContaining({ projectId: "project-1", + contentId: "content-service-skill-1", theme: "video", initialCreationMode: "guided", + initialRequestMetadata: { + artifact: { + artifact_mode: "draft", + artifact_kind: "brief", + workbench_surface: "right_panel", + }, + }, initialUserPrompt: expect.stringContaining("[服务型技能] 复制短视频脚本"), }), @@ -1302,14 +1348,46 @@ describe("AgentChatHomeShell", () => { payload: expect.objectContaining({ kind: "agent_turn", prompt: expect.stringContaining("[服务型技能] 每日趋势摘要"), + content_id: "content-service-skill-1", + request_metadata: expect.objectContaining({ + artifact: expect.objectContaining({ + artifact_mode: "draft", + artifact_kind: "analysis", + }), + harness: expect.objectContaining({ + theme: "social-media", + session_mode: "theme_workbench", + content_id: "content-service-skill-1", + }), + }), }), }), ); + expect(mockCreateContent).toHaveBeenCalledTimes(1); + expect(mockCreateContent).toHaveBeenCalledWith( + expect.objectContaining({ + project_id: "project-1", + title: "每日趋势摘要", + content_type: "post", + body: "", + }), + ); + expect(mockCreateContent.mock.invocationCallOrder[0]).toBeLessThan( + mockCreateAutomationJob.mock.invocationCallOrder[0], + ); expect(onEnterWorkspace).toHaveBeenCalledWith( expect.objectContaining({ projectId: "project-1", + contentId: "content-service-skill-1", theme: "social-media", initialCreationMode: "guided", + initialRequestMetadata: { + artifact: { + artifact_mode: "draft", + artifact_kind: "analysis", + workbench_surface: "right_panel", + }, + }, initialUserPrompt: expect.stringContaining("[服务型技能] 每日趋势摘要"), }), ); diff --git a/src/components/agent/chat/AgentChatHomeShell.tsx b/src/components/agent/chat/AgentChatHomeShell.tsx index 62cf5918b..073e1a0d9 100644 --- a/src/components/agent/chat/AgentChatHomeShell.tsx +++ b/src/components/agent/chat/AgentChatHomeShell.tsx @@ -9,7 +9,7 @@ import { isTerminalServiceSkillRunStatus, type ServiceSkillRun, } from "@/lib/api/serviceSkillRuns"; -import { listProjects, type Project } from "@/lib/api/project"; +import { createContent, listProjects, type Project } from "@/lib/api/project"; import { AutomationJobDialog, type AutomationJobDialogInitialValues, @@ -19,9 +19,7 @@ import type { Page, PageParams } from "@/types/page"; import { SettingsTabs } from "@/types/settings"; import { EmptyState } from "./components/EmptyState"; import type { CreationMode } from "./components/types"; -import { - saveChatToolPreferences, -} from "./utils/chatToolPreferences"; +import { saveChatToolPreferences } from "./utils/chatToolPreferences"; import { isTeamRuntimeRecommendation } from "./utils/contextualRecommendations"; import { resolveClawWorkspaceProviderSelection } from "./utils/clawWorkspaceProviderSelection"; import { normalizeProjectId } from "./utils/topicProjectResolution"; @@ -53,6 +51,7 @@ import { ServiceSkillHomePanel } from "./service-skills/ServiceSkillHomePanel"; import { ServiceSkillLaunchDialog } from "./service-skills/ServiceSkillLaunchDialog"; import { composeServiceSkillPrompt } from "./service-skills/promptComposer"; import { + buildServiceSkillAutomationAgentTurnPayloadContext, buildServiceSkillAutomationInitialValues, supportsServiceSkillLocalAutomation, } from "./service-skills/automationDraft"; @@ -61,6 +60,7 @@ import type { ServiceSkillHomeItem, ServiceSkillSlotValues, } from "./service-skills/types"; +import { buildServiceSkillWorkspaceSeed } from "./service-skills/workspaceLaunch"; const PageContainer = styled.div<{ $compact?: boolean }>` display: flex; @@ -213,10 +213,14 @@ function prioritizeAutomationWorkspaces( return workspaces; } - const matched = workspaces.find((workspace) => workspace.id === normalizedProjectId); + const matched = workspaces.find( + (workspace) => workspace.id === normalizedProjectId, + ); const fallbackWorkspace = matched ?? buildFallbackAutomationWorkspace(normalizedProjectId, theme); - const remaining = workspaces.filter((workspace) => workspace.id !== normalizedProjectId); + const remaining = workspaces.filter( + (workspace) => workspace.id !== normalizedProjectId, + ); return [fallbackWorkspace, ...remaining]; } @@ -253,7 +257,8 @@ function buildServiceSkillRunSuccessMessage( } interface PendingServiceSkillAutomationLaunch { - enterWorkspacePayload: HomeShellEnterWorkspacePayload; + skill: ServiceSkillHomeItem; + prompt: string; usage: { skillId: string; runnerType: ServiceSkillHomeItem["runnerType"]; @@ -327,7 +332,9 @@ export function AgentChatHomeShell({ const [automationDialogOpen, setAutomationDialogOpen] = useState(false); const [automationDialogInitialValues, setAutomationDialogInitialValues] = useState(null); - const [automationWorkspaces, setAutomationWorkspaces] = useState([]); + const [automationWorkspaces, setAutomationWorkspaces] = useState( + [], + ); const [automationJobSaving, setAutomationJobSaving] = useState(false); const [pendingServiceSkillAutomation, setPendingServiceSkillAutomation] = useState(null); @@ -449,11 +456,13 @@ export function AgentChatHomeShell({ launch.enterWorkspacePayload.themeOverride ?? activeTheme; try { - const providerSelection = await resolveClawWorkspaceProviderSelection({ - currentProviderType: providerType, - currentModel: model, - theme: targetTheme, - }); + const providerSelection = await resolveClawWorkspaceProviderSelection( + { + currentProviderType: providerType, + currentModel: model, + theme: targetTheme, + }, + ); if (providerSelection) { if (providerSelection.providerType !== providerType) { @@ -509,10 +518,13 @@ export function AgentChatHomeShell({ ], ); - const handleServiceSkillSelect = useCallback((skill: ServiceSkillHomeItem) => { - setSelectedServiceSkill(skill); - setServiceSkillDialogOpen(true); - }, []); + const handleServiceSkillSelect = useCallback( + (skill: ServiceSkillHomeItem) => { + setSelectedServiceSkill(skill); + setServiceSkillDialogOpen(true); + }, + [], + ); const handleOpenServiceSkillAutomationJob = useCallback( (skill: ServiceSkillHomeItem) => { @@ -529,11 +541,91 @@ export function AgentChatHomeShell({ [onNavigate], ); - const handleServiceSkillLaunch = useCallback( + const createServiceSkillSeededContent = useCallback( + async (skill: ServiceSkillHomeItem, projectId?: string | null) => { + const normalizedProjectId = normalizeProjectId( + projectId ?? currentProjectId, + ); + const seed = buildServiceSkillWorkspaceSeed( + skill, + skill.themeTarget ?? activeTheme, + ); + + if (!normalizedProjectId || !seed) { + return null; + } + + return createContent({ + project_id: normalizedProjectId, + title: seed.title, + content_type: seed.contentType, + body: "", + metadata: seed.metadata, + }); + }, + [activeTheme, currentProjectId], + ); + + const prepareServiceSkillWorkspacePayload = useCallback( async ( skill: ServiceSkillHomeItem, - slotValues: ServiceSkillSlotValues, - ) => { + prompt: string, + options?: { + contentId?: string | null; + projectId?: string | null; + }, + ): Promise => { + const normalizedProjectId = normalizeProjectId( + options?.projectId ?? currentProjectId, + ); + const existingContentId = options?.contentId?.trim(); + const seed = buildServiceSkillWorkspaceSeed( + skill, + skill.themeTarget ?? activeTheme, + ); + + if (existingContentId) { + return { + prompt, + contentId: existingContentId, + themeOverride: skill.themeTarget, + initialRequestMetadata: seed?.requestMetadata, + }; + } + + if (!normalizedProjectId || !seed) { + return { + prompt, + themeOverride: skill.themeTarget, + initialRequestMetadata: seed?.requestMetadata, + }; + } + + const created = await createServiceSkillSeededContent( + skill, + normalizedProjectId, + ); + + if (!created) { + return { + prompt, + themeOverride: skill.themeTarget, + initialRequestMetadata: seed.requestMetadata, + }; + } + + return { + prompt, + contentId: created.id, + themeOverride: skill.themeTarget, + initialRequestMetadata: seed.requestMetadata, + }; + }, + [activeTheme, createServiceSkillSeededContent, currentProjectId], + ); + + const handleServiceSkillLaunch = useCallback( + async (skill: ServiceSkillHomeItem, slotValues: ServiceSkillSlotValues) => { const prompt = composeServiceSkillPrompt({ skill, slotValues, @@ -599,13 +691,23 @@ export function AgentChatHomeShell({ } if (skill.runnerType !== "instant") { - toast.info("当前先进入工作区生成首版方案,下一阶段再接本地自动化任务。"); + toast.info( + "当前先进入工作区生成首版方案,下一阶段再接本地自动化任务。", + ); } - const entered = handleEnterWorkspace({ - prompt, - themeOverride: skill.themeTarget, - }); + let workspacePayload: HomeShellEnterWorkspacePayload; + try { + workspacePayload = await prepareServiceSkillWorkspacePayload( + skill, + prompt, + ); + } catch (error) { + toast.error(`准备服务型技能工作区失败:${getErrorMessage(error)}`); + return; + } + + const entered = handleEnterWorkspace(workspacePayload); if (!entered) { return; @@ -618,14 +720,16 @@ export function AgentChatHomeShell({ setServiceSkillDialogOpen(false); setSelectedServiceSkill(null); }, - [handleEnterWorkspace, input, recordServiceSkillUsage], + [ + handleEnterWorkspace, + input, + prepareServiceSkillWorkspacePayload, + recordServiceSkillUsage, + ], ); const handleServiceSkillAutomationSetup = useCallback( - async ( - skill: ServiceSkillHomeItem, - slotValues: ServiceSkillSlotValues, - ) => { + async (skill: ServiceSkillHomeItem, slotValues: ServiceSkillSlotValues) => { if (!supportsServiceSkillLocalAutomation(skill)) { await handleServiceSkillLaunch(skill, slotValues); return; @@ -670,10 +774,8 @@ export function AgentChatHomeShell({ }), ); setPendingServiceSkillAutomation({ - enterWorkspacePayload: { - prompt, - themeOverride: skill.themeTarget, - }, + skill, + prompt, usage: { skillId: skill.id, runnerType: skill.runnerType, @@ -705,10 +807,31 @@ export function AgentChatHomeShell({ setAutomationJobSaving(true); try { - const createdJob = await createAutomationJob(payload.request); + const pendingLaunch = pendingServiceSkillAutomation; + let request = payload.request; + let automationContentId: string | null = null; + + if (pendingLaunch && request.payload.kind === "agent_turn") { + const createdContent = await createServiceSkillSeededContent( + pendingLaunch.skill, + request.workspace_id, + ); + automationContentId = createdContent?.id ?? null; + request = { + ...request, + payload: { + ...request.payload, + ...buildServiceSkillAutomationAgentTurnPayloadContext({ + skill: pendingLaunch.skill, + contentId: automationContentId, + }), + }, + }; + } + + const createdJob = await createAutomationJob(request); toast.success(`本地自动化任务已创建:${createdJob.name}`); - const pendingLaunch = pendingServiceSkillAutomation; setAutomationDialogOpen(false); setAutomationDialogInitialValues(null); setPendingServiceSkillAutomation(null); @@ -723,7 +846,23 @@ export function AgentChatHomeShell({ jobName: createdJob.name, }); recordServiceSkillUsage(pendingLaunch.usage); - const entered = handleEnterWorkspace(pendingLaunch.enterWorkspacePayload); + let workspacePayload: HomeShellEnterWorkspacePayload; + try { + workspacePayload = await prepareServiceSkillWorkspacePayload( + pendingLaunch.skill, + pendingLaunch.prompt, + { + contentId: automationContentId, + projectId: request.workspace_id, + }, + ); + } catch (error) { + toast.error( + `自动化任务已创建,但准备工作区失败:${getErrorMessage(error)}`, + ); + return; + } + const entered = handleEnterWorkspace(workspacePayload); if (!entered) { toast.error("自动化任务已创建,但进入工作区失败,请稍后手动打开。"); } @@ -734,7 +873,14 @@ export function AgentChatHomeShell({ setAutomationJobSaving(false); } }, - [handleEnterWorkspace, pendingServiceSkillAutomation, recordServiceSkillUsage], + [ + createServiceSkillSeededContent, + currentProjectId, + handleEnterWorkspace, + pendingServiceSkillAutomation, + prepareServiceSkillWorkspacePayload, + recordServiceSkillUsage, + ], ); const handleRecommendationClick = useCallback( @@ -850,7 +996,9 @@ export function AgentChatHomeShell({ catalogMeta={serviceSkillCatalogMeta} loading={serviceSkillsLoading} onSelect={handleServiceSkillSelect} - onOpenAutomationJob={handleOpenServiceSkillAutomationJob} + onOpenAutomationJob={ + handleOpenServiceSkillAutomationJob + } /> { syncChatToolPreferencesSource(activeTheme, runtimeChatToolPreferences); - }, [ - activeTheme, - runtimeChatToolPreferences, - syncChatToolPreferencesSource, - ]); + }, [activeTheme, runtimeChatToolPreferences, syncChatToolPreferencesSource]); const hasRealTeamGraph = childSubagentSessions.length > 0 || Boolean(subagentParentContext); @@ -1442,18 +1417,19 @@ export function AgentChatWorkspace({ harnessAttentionLevel, navbarHarnessPanelVisible, } = contextHarnessRuntime; - const themeWorkbenchScaffoldRuntime = useWorkspaceThemeWorkbenchScaffoldRuntime({ - isThemeWorkbench, - mappedTheme, - sessionId, - projectId, - canvasState, - documentVersionStatusMap, - setDocumentVersionStatusMap, - clearThemeSkillsRailState, - setCanvasState, - setLayoutMode, - }); + const themeWorkbenchScaffoldRuntime = + useWorkspaceThemeWorkbenchScaffoldRuntime({ + isThemeWorkbench, + mappedTheme, + sessionId, + projectId, + canvasState, + documentVersionStatusMap, + setDocumentVersionStatusMap, + clearThemeSkillsRailState, + setCanvasState, + setLayoutMode, + }); const { shouldUseCompactThemeWorkbench, shouldSkipThemeWorkbenchAutoGuideWithoutPrompt, @@ -1492,15 +1468,17 @@ export function AgentChatWorkspace({ pendingActionRequest, }); - const themeWorkbenchSidebarRuntime = useWorkspaceThemeWorkbenchSidebarRuntime({ - isThemeWorkbench, - sessionId, - messages, - isSending, - themeWorkbenchBackendRunState, - contextActivityLogs: contextWorkspace.activityLogs, - historyPageSize: THEME_WORKBENCH_HISTORY_PAGE_SIZE, - }); + const themeWorkbenchSidebarRuntime = useWorkspaceThemeWorkbenchSidebarRuntime( + { + isThemeWorkbench, + sessionId, + messages, + isSending, + themeWorkbenchBackendRunState, + contextActivityLogs: contextWorkspace.activityLogs, + historyPageSize: THEME_WORKBENCH_HISTORY_PAGE_SIZE, + }, + ); const { handleViewContextDetail } = useWorkspaceContextDetailActions({ contextWorkspace, @@ -1709,45 +1687,42 @@ export function AgentChatWorkspace({ setCreationMode, setTaskFiles, }); - const { - handleClearMessages, - handleBackHome, - resetTopicLocalState, - } = useWorkspaceResetRuntime({ - clearMessages, - clearRuntimeTeamState, - clearProjectSelectionRuntime, - resetRestoredSessionState, - resetProjectSelection, - resetGuideState, - hasHandledNewChatRequest, - markNewChatRequestHandled, - createFreshSession, - defaultTopicSidebarVisible, - normalizedInitialTheme: normalizedEntryTheme, - initialCreationMode, - newChatAt, - initialSessionName, - projectId, - externalProjectId, - onNavigate: _onNavigate, - autoCollapsedTopicSidebarRef, - processedMessageIdsRef: processedMessageIds, - setInput, - setSelectedText, - setLayoutMode, - setShowSidebar, - setCanvasState, - setGeneralCanvasState, - setTaskFiles, - setSelectedFileId, - setBrowserTaskPreflight, - setMentionedCharacters, - setProject, - setProjectMemory, - setActiveTheme, - setCreationMode, - }); + const { handleClearMessages, handleBackHome, resetTopicLocalState } = + useWorkspaceResetRuntime({ + clearMessages, + clearRuntimeTeamState, + clearProjectSelectionRuntime, + resetRestoredSessionState, + resetProjectSelection, + resetGuideState, + hasHandledNewChatRequest, + markNewChatRequestHandled, + createFreshSession, + defaultTopicSidebarVisible, + normalizedInitialTheme: normalizedEntryTheme, + initialCreationMode, + newChatAt, + initialSessionName, + projectId, + externalProjectId, + onNavigate: _onNavigate, + autoCollapsedTopicSidebarRef, + processedMessageIdsRef: processedMessageIds, + setInput, + setSelectedText, + setLayoutMode, + setShowSidebar, + setCanvasState, + setGeneralCanvasState, + setTaskFiles, + setSelectedFileId, + setBrowserTaskPreflight, + setMentionedCharacters, + setProject, + setProjectMemory, + setActiveTheme, + setCreationMode, + }); const { switchTopic } = useWorkspaceTopicSwitch({ projectId, @@ -2184,7 +2159,9 @@ export function AgentChatWorkspace({ return; } - setLayoutMode((current) => (current === "canvas" ? "chat-canvas" : current)); + setLayoutMode((current) => + current === "canvas" ? "chat-canvas" : current, + ); setFocusedTimelineItemId(normalizedItemId); setTimelineFocusRequestKey((current) => current + 1); }, []); @@ -2433,136 +2410,135 @@ export function AgentChatWorkspace({ teamDispatchPreviewState, }); - const workspaceShellSceneRuntime = - useWorkspaceConversationShellSceneRuntime({ - navigationActions, - inputbarScene, - canvasScene, - shellChromeRuntime, - themeWorkbenchShellRuntime, - contextHarnessRuntime, - teamSessionRuntime, - currentImageWorkbenchState, - project, - projectId, - projectMemory, - handleSend, - mappedTheme, - runtimeStyleSelection, - setRuntimeStyleSelection, - generalCanvasState, - runtimeStylePrompt, - showSidebar, - topics, - switchTopic, - handleResumeSidebarTask, - deleteTopic, - renameTopic, - childSubagentSessions, - subagentParentContext, - handleReturnToParentSession, - entryBannerVisible, - entryBannerMessage, - contextWorkspaceEnabled: contextWorkspace.enabled, - input, - setInput, - providerType, - setProviderType, - model, - setModel, - executionStrategy, - setExecutionStrategy, - chatToolPreferences, - setChatToolPreferences, - selectedTeam, - handleSelectTeam, - handleEnableSuggestedTeam, - creationMode, - setCreationMode, - activeTheme, - setActiveTheme, - lockTheme, - artifacts, - resolvedCanvasState, - contentId, - selectedText, - handleRecommendationClick, - skills, - skillsLoading, - handleNavigateToSkillSettings, - handleRefreshSkills, - handleOpenBrowserAssistInCanvas, - browserAssistLaunching, - hideHistoryToggle, - showChatPanel, - topBarChrome, - onBackToProjectManagement, - fromResources, - handleBackHome, - handleToggleSidebar, - chatMode, - isBrowserAssistCanvasVisible, - browserAssistAttentionLevel, - browserAssistEntryLabel, - showHarnessToggle, - navbarHarnessPanelVisible, - harnessPendingCount, - harnessAttentionLevel, - sessionId, - syncStatus, - pendingA2UIForm, - handleToggleCanvas, - hideInlineStepProgress, - isContentCreationMode, - hasMessages, - steps, - currentStepIndex, - goToStep, - displayMessages, - turns, - effectiveThreadItems, - currentTurnId, - threadRead, - pendingActions, - submittedActionsInFlight, - queuedTurns, - isSending, - stopSending, - resumeThread, - replayPendingAction, - promoteQueuedTurn, - deleteMessage, - editMessage, - handleA2UISubmit, - handleWriteFile, - handleFileClick: handleWorkspaceFileClick, - handleOpenArtifactFromTimeline, - handleOpenSavedSiteContent, - handleArtifactClick: handleWorkspaceArtifactClick, - handleOpenSubagentSession, - handlePermissionResponseWithBrowserPreflight, - pendingPromotedA2UIActionRequest, - shouldCollapseCodeBlocks, - shouldCollapseCodeBlockInChat, - handleCodeBlockClick, - layoutMode, - handleActivateTeamWorkbench, - isThemeWorkbench, - showNovelNavbarControls, - novelChapterListCollapsed, - handleToggleNovelChapterList, - handleAddNovelChapter, - handleCloseCanvas, - settledWorkbenchArtifacts, - taskFiles, - selectedFileId, - handleHarnessLoadFilePreview, - setCanvasWorkbenchLayoutMode, - workspacePathMissing: Boolean(workspacePathMissing), - workspaceHealthError, - focusedTimelineItemId, - timelineFocusRequestKey, - }); + const workspaceShellSceneRuntime = useWorkspaceConversationShellSceneRuntime({ + navigationActions, + inputbarScene, + canvasScene, + shellChromeRuntime, + themeWorkbenchShellRuntime, + contextHarnessRuntime, + teamSessionRuntime, + currentImageWorkbenchState, + project, + projectId, + projectMemory, + handleSend, + mappedTheme, + runtimeStyleSelection, + setRuntimeStyleSelection, + generalCanvasState, + runtimeStylePrompt, + showSidebar, + topics, + switchTopic, + handleResumeSidebarTask, + deleteTopic, + renameTopic, + childSubagentSessions, + subagentParentContext, + handleReturnToParentSession, + entryBannerVisible, + entryBannerMessage, + contextWorkspaceEnabled: contextWorkspace.enabled, + input, + setInput, + providerType, + setProviderType, + model, + setModel, + executionStrategy, + setExecutionStrategy, + chatToolPreferences, + setChatToolPreferences, + selectedTeam, + handleSelectTeam, + handleEnableSuggestedTeam, + creationMode, + setCreationMode, + activeTheme, + setActiveTheme, + lockTheme, + artifacts, + resolvedCanvasState, + contentId, + selectedText, + handleRecommendationClick, + skills, + skillsLoading, + handleNavigateToSkillSettings, + handleRefreshSkills, + handleOpenBrowserAssistInCanvas, + browserAssistLaunching, + hideHistoryToggle, + showChatPanel, + topBarChrome, + onBackToProjectManagement, + fromResources, + handleBackHome, + handleToggleSidebar, + chatMode, + isBrowserAssistCanvasVisible, + browserAssistAttentionLevel, + browserAssistEntryLabel, + showHarnessToggle, + navbarHarnessPanelVisible, + harnessPendingCount, + harnessAttentionLevel, + sessionId, + syncStatus, + pendingA2UIForm, + handleToggleCanvas, + hideInlineStepProgress, + isContentCreationMode, + hasMessages, + steps, + currentStepIndex, + goToStep, + displayMessages, + turns, + effectiveThreadItems, + currentTurnId, + threadRead, + pendingActions, + submittedActionsInFlight, + queuedTurns, + isSending, + stopSending, + resumeThread, + replayPendingAction, + promoteQueuedTurn, + deleteMessage, + editMessage, + handleA2UISubmit, + handleWriteFile, + handleFileClick: handleWorkspaceFileClick, + handleOpenArtifactFromTimeline, + handleOpenSavedSiteContent, + handleArtifactClick: handleWorkspaceArtifactClick, + handleOpenSubagentSession, + handlePermissionResponseWithBrowserPreflight, + pendingPromotedA2UIActionRequest, + shouldCollapseCodeBlocks, + shouldCollapseCodeBlockInChat, + handleCodeBlockClick, + layoutMode, + handleActivateTeamWorkbench, + isThemeWorkbench, + showNovelNavbarControls, + novelChapterListCollapsed, + handleToggleNovelChapterList, + handleAddNovelChapter, + handleCloseCanvas, + settledWorkbenchArtifacts, + taskFiles, + selectedFileId, + handleHarnessLoadFilePreview, + setCanvasWorkbenchLayoutMode, + workspacePathMissing: Boolean(workspacePathMissing), + workspaceHealthError, + focusedTimelineItemId, + timelineFocusRequestKey, + }); return workspaceShellSceneRuntime.shellSceneNode; } diff --git a/src/components/agent/chat/components/TeamWorkbenchSummaryPanel.tsx b/src/components/agent/chat/components/TeamWorkbenchSummaryPanel.tsx index 62c050f66..7a7a5bfc8 100644 --- a/src/components/agent/chat/components/TeamWorkbenchSummaryPanel.tsx +++ b/src/components/agent/chat/components/TeamWorkbenchSummaryPanel.tsx @@ -77,7 +77,7 @@ export function TeamWorkbenchSummaryPanel({ selectedTeamRoles = [], teamDispatchPreviewState = null, }: TeamWorkbenchSummaryPanelProps) { - const runtimeTeamState = teamDispatchPreviewState; + const dispatchPreviewState = teamDispatchPreviewState; const executionSummary = summarizeTeamWorkspaceExecution({ currentSessionId, currentSessionRuntimeStatus, @@ -89,17 +89,17 @@ export function TeamWorkbenchSummaryPanel({ }); const hasRealTeamGraph = childSubagentSessions.length > 0 || Boolean(subagentParentContext); - const runtimeFormationMeta = runtimeTeamState - ? resolveRuntimeFormationStatusMeta(runtimeTeamState.status) + const runtimeFormationMeta = dispatchPreviewState + ? resolveRuntimeFormationStatusMeta(dispatchPreviewState.status) : null; const runtimeTeamLabel = - runtimeTeamState?.label?.trim() || - runtimeTeamState?.blueprint?.label?.trim() || + dispatchPreviewState?.label?.trim() || + dispatchPreviewState?.blueprint?.label?.trim() || selectedTeamLabel?.trim() || null; const runtimeSummaryText = - runtimeTeamState?.summary?.trim() || - runtimeTeamState?.blueprint?.summary?.trim() || + dispatchPreviewState?.summary?.trim() || + dispatchPreviewState?.blueprint?.summary?.trim() || selectedTeamSummary || null; const operationSummary = buildOperationSummary({ @@ -111,10 +111,10 @@ export function TeamWorkbenchSummaryPanel({ .slice(0, 4); const displayRoleCount = hasRealTeamGraph ? executionSummary.totalSessionCount - : runtimeTeamState?.members.length ?? 0; + : dispatchPreviewState?.members.length ?? 0; const roleCards = - runtimeTeamState?.members.length - ? runtimeTeamState.members.map((member) => ({ + dispatchPreviewState?.members.length + ? dispatchPreviewState.members.map((member) => ({ id: member.id, label: member.label, roleKey: member.roleKey, @@ -151,7 +151,7 @@ export function TeamWorkbenchSummaryPanel({ { label: hasRealTeamGraph ? "总会话" - : runtimeTeamState + : dispatchPreviewState ? "当前成员" : "总会话", value: String( @@ -159,7 +159,7 @@ export function TeamWorkbenchSummaryPanel({ ), hint: hasRealTeamGraph ? "已进入团队图谱" - : runtimeTeamState + : dispatchPreviewState ? "当前编队" : "等待创建", }, @@ -193,13 +193,13 @@ export function TeamWorkbenchSummaryPanel({ "团队已就绪,等待主代理开始编排"}

- {runtimeTeamState?.status === "failed" - ? runtimeTeamState.errorMessage?.trim() || + {dispatchPreviewState?.status === "failed" + ? dispatchPreviewState.errorMessage?.trim() || "这次 Team 准备失败,可继续在当前对话中推进。" : runtimeSummaryText || "这里展示团队总览与运行密度;主对话只保留调度记录,角色执行正文在左侧 Team 画布查看。"}

- {!hasRealTeamGraph && runtimeTeamState ? ( + {!hasRealTeamGraph && dispatchPreviewState ? (
- {runtimeTeamState.status === "forming" + {dispatchPreviewState.status === "forming" ? "模型正在依据当前任务准备 Team,真实成员加入后会自动切换到实时协作轨道。" - : runtimeTeamState.status === "formed" - ? `已准备 ${runtimeTeamState.members.length} 个成员,当前等待系统分派真实成员进入协作。` - : runtimeTeamState.errorMessage?.trim() || + : dispatchPreviewState.status === "formed" + ? `已准备 ${dispatchPreviewState.members.length} 个成员,当前等待系统分派真实成员进入协作。` + : dispatchPreviewState.errorMessage?.trim() || "暂未成功准备这次 Team。"}
) : null} - {!hasRealTeamGraph && !runtimeTeamState ? ( + {!hasRealTeamGraph && !dispatchPreviewState ? (
尚未出现真实团队成员。开始分派成员后,左侧 Team 画布会自动切换为实时协作视图。
@@ -243,7 +243,7 @@ export function TeamWorkbenchSummaryPanel({
- {runtimeTeamState ? "当前成员" : "角色分工"} + {dispatchPreviewState ? "当前成员" : "角色分工"}
{roleCards.map((role) => ( @@ -294,9 +294,9 @@ export function TeamWorkbenchSummaryPanel({
))} - {runtimeTeamState?.blueprint?.label ? ( + {dispatchPreviewState?.blueprint?.label ? (
- 参考蓝图 Team:{runtimeTeamState.blueprint.label} + 参考蓝图 Team:{dispatchPreviewState.blueprint.label}
) : null}
diff --git a/src/components/agent/chat/components/TeamWorkspaceBoard.tsx b/src/components/agent/chat/components/TeamWorkspaceBoard.tsx index 911f0bf9a..5ac667e70 100644 --- a/src/components/agent/chat/components/TeamWorkspaceBoard.tsx +++ b/src/components/agent/chat/components/TeamWorkspaceBoard.tsx @@ -1394,12 +1394,12 @@ export function TeamWorkspaceBoard({ selectedTeamRoles = [], teamDispatchPreviewState = null, }: TeamWorkspaceBoardProps) { - const runtimeTeamState = teamDispatchPreviewState; + const dispatchPreviewState = teamDispatchPreviewState; const isChildSession = Boolean(subagentParentContext); const canvasStorageScopeId = currentSessionId?.trim() || subagentParentContext?.parent_session_id?.trim() || - runtimeTeamState?.requestId?.trim() || + dispatchPreviewState?.requestId?.trim() || "team-workspace"; const [shellExpanded, setShellExpanded] = useState(defaultShellExpanded); const detailExpanded = !embedded; @@ -1623,26 +1623,26 @@ export function TeamWorkspaceBoard({ const normalizedSelectedTeamRoles = (selectedTeamRoles ?? []).filter((role) => role.label.trim(), ); - const runtimeFormationMeta = runtimeTeamState - ? resolveRuntimeFormationStatusMeta(runtimeTeamState.status) + const runtimeFormationMeta = dispatchPreviewState + ? resolveRuntimeFormationStatusMeta(dispatchPreviewState.status) : null; const runtimeFormationLabel = - runtimeTeamState?.label?.trim() || - runtimeTeamState?.blueprint?.label?.trim() || + dispatchPreviewState?.label?.trim() || + dispatchPreviewState?.blueprint?.label?.trim() || normalizedSelectedTeamLabel; const runtimeFormationSummary = - runtimeTeamState?.summary?.trim() || - runtimeTeamState?.blueprint?.summary?.trim() || + dispatchPreviewState?.summary?.trim() || + dispatchPreviewState?.blueprint?.summary?.trim() || normalizedSelectedTeamSummary; const runtimeMembers = useMemo( - () => runtimeTeamState?.members ?? [], - [runtimeTeamState?.members], + () => dispatchPreviewState?.members ?? [], + [dispatchPreviewState?.members], ); const runtimeBlueprintRoles = useMemo( - () => runtimeTeamState?.blueprint?.roles ?? [], - [runtimeTeamState?.blueprint?.roles], + () => dispatchPreviewState?.blueprint?.roles ?? [], + [dispatchPreviewState?.blueprint?.roles], ); - const hasRuntimeFormation = Boolean(runtimeTeamState); + const hasRuntimeFormation = Boolean(dispatchPreviewState); const hasSelectedTeamPlan = Boolean(normalizedSelectedTeamLabel) || Boolean(normalizedSelectedTeamSummary) || @@ -1740,9 +1740,9 @@ export function TeamWorkspaceBoard({ {runtimeMembers.length} 位当前成员 ) : null} - {runtimeTeamState?.blueprint?.label ? ( + {dispatchPreviewState?.blueprint?.label ? ( - 参考方案 · {runtimeTeamState.blueprint.label} + 参考方案 · {dispatchPreviewState.blueprint.label} ) : null} @@ -1750,7 +1750,7 @@ export function TeamWorkspaceBoard({ }; const renderRuntimeFormationPanel = () => { - if (!runtimeTeamState || !runtimeFormationMeta) { + if (!dispatchPreviewState || !runtimeFormationMeta) { return null; } @@ -1780,15 +1780,15 @@ export function TeamWorkspaceBoard({ {runtimeFormationMeta.title}

- {runtimeTeamState.status === "failed" - ? runtimeTeamState.errorMessage?.trim() || + {dispatchPreviewState.status === "failed" + ? dispatchPreviewState.errorMessage?.trim() || "当前协作准备失败,暂时无法展示更多内容。" : runtimeFormationSummary || "这里会先展示当前协作方案,成员加入后再切换成实时进展。"}

- {runtimeTeamState.blueprint?.label ? ( + {dispatchPreviewState.blueprint?.label ? (
- 参考方案:{runtimeTeamState.blueprint.label} + 参考方案:{dispatchPreviewState.blueprint.label}
) : null} @@ -3212,11 +3212,11 @@ export function TeamWorkspaceBoard({ ? isChildSession ? "当前协作成员会在各自面板里持续更新进展和结果,主对话只保留必要摘要。" : `${visibleSessions.length} 位协作成员已加入,每位成员都会在自己的面板里持续更新进展和结果。` - : runtimeTeamState?.status === "forming" + : dispatchPreviewState?.status === "forming" ? "正在准备当前协作分工,成员接入后会在这里独立更新进展。" - : runtimeTeamState?.status === "formed" + : dispatchPreviewState?.status === "formed" ? "当前协作分工已经就绪,成员接入后会在各自面板里开始处理。" - : runtimeTeamState?.status === "failed" + : dispatchPreviewState?.status === "failed" ? "这次协作准备失败,暂时无法生成成员面板。" : "成员加入后,这里会展开为独立的协作进展面板。"; @@ -3258,7 +3258,7 @@ export function TeamWorkspaceBoard({

{hasRuntimeFormation - ? buildRuntimeFormationHint(runtimeTeamState) + ? buildRuntimeFormationHint(dispatchPreviewState) : "这里先保持简洁,避免遮挡消息区;只有真正需要协作分工时才会展开完整面板。"}

{hasRuntimeFormation @@ -3295,7 +3295,7 @@ export function TeamWorkspaceBoard({ }); const boardHint = !hasRealTeamGraph && hasRuntimeFormation - ? buildRuntimeFormationHint(runtimeTeamState) + ? buildRuntimeFormationHint(dispatchPreviewState) : buildBoardHint({ hasRealTeamGraph, isChildSession, @@ -4558,14 +4558,14 @@ export function TeamWorkspaceBoard({ renderSelectedTeamPlanPanel() )}
- {runtimeTeamState?.status === "forming" ? ( + {dispatchPreviewState?.status === "forming" ? ( "系统正在准备当前协作分工,完成后会先展示成员卡片,后续再切换为独立的实时进展面板。" - ) : runtimeTeamState?.status === "formed" ? ( + ) : dispatchPreviewState?.status === "formed" ? ( <> 当前协作方案已就绪。系统开始分工后,这里会从方案视图过渡到实时协作画布。 - ) : runtimeTeamState?.status === "failed" ? ( - runtimeTeamState.errorMessage?.trim() || + ) : dispatchPreviewState?.status === "failed" ? ( + dispatchPreviewState.errorMessage?.trim() || "当前协作准备失败,暂时还没有协作成员加入。" ) : ( <> @@ -4589,7 +4589,7 @@ export function TeamWorkspaceBoard({ {runtimeFormationMeta?.title || "等待协作成员加入"}

- {buildRuntimeFormationEmptyDetail(runtimeTeamState)} + {buildRuntimeFormationEmptyDetail(dispatchPreviewState)}

{hasRuntimeFormation ? (
diff --git a/src/components/agent/chat/components/TeamWorkspaceDock.tsx b/src/components/agent/chat/components/TeamWorkspaceDock.tsx index b9d58d695..f11295690 100644 --- a/src/components/agent/chat/components/TeamWorkspaceDock.tsx +++ b/src/components/agent/chat/components/TeamWorkspaceDock.tsx @@ -510,22 +510,22 @@ export function TeamWorkspaceDock({ selectedTeamRoles = [], teamDispatchPreviewState = null, }: TeamWorkspaceDockProps) { - const runtimeTeamState = teamDispatchPreviewState; + const dispatchPreviewState = teamDispatchPreviewState; const launcherOnly = typeof onActivateWorkbench === "function"; const hasRealTeamGraph = childSubagentSessions.length > 0 || Boolean(subagentParentContext); - const hasRuntimeFormation = Boolean(runtimeTeamState); - const runtimeFormationMeta = runtimeTeamState - ? resolveRuntimeFormationStatusMeta(runtimeTeamState.status) + const hasRuntimeFormation = Boolean(dispatchPreviewState); + const runtimeFormationMeta = dispatchPreviewState + ? resolveRuntimeFormationStatusMeta(dispatchPreviewState.status) : null; const runtimeTeamLabel = - runtimeTeamState?.label?.trim() || - runtimeTeamState?.blueprint?.label?.trim() || + dispatchPreviewState?.label?.trim() || + dispatchPreviewState?.blueprint?.label?.trim() || selectedTeamLabel?.trim() || null; const runtimeTeamSummary = - runtimeTeamState?.summary?.trim() || - runtimeTeamState?.blueprint?.summary?.trim() || + dispatchPreviewState?.summary?.trim() || + dispatchPreviewState?.blueprint?.summary?.trim() || selectedTeamSummary?.trim() || null; const [expanded, setExpanded] = useState(false); @@ -540,9 +540,9 @@ export function TeamWorkspaceDock({ const showAttentionCue = !expanded && (hasRealTeamGraph || - runtimeTeamState?.status === "forming" || - runtimeTeamState?.status === "formed" || - runtimeTeamState?.status === "failed"); + dispatchPreviewState?.status === "forming" || + dispatchPreviewState?.status === "formed" || + dispatchPreviewState?.status === "failed"); const dockCount = subagentParentContext ? (subagentParentContext.sibling_subagent_sessions?.length ?? 0) + 1 : childSubagentSessions.length; @@ -550,9 +550,9 @@ export function TeamWorkspaceDock({ const [teamDetailExpanded, setTeamDetailExpanded] = useState(false); const hasSelectedTeamDetails = Boolean(runtimeTeamSummary) || - (runtimeTeamState?.members.length ?? 0) > 0 || - Boolean(runtimeTeamState?.blueprint?.summary?.trim()) || - (runtimeTeamState?.blueprint?.roles.length ?? 0) > 0 || + (dispatchPreviewState?.members.length ?? 0) > 0 || + Boolean(dispatchPreviewState?.blueprint?.summary?.trim()) || + (dispatchPreviewState?.blueprint?.roles.length ?? 0) > 0 || Boolean(selectedTeamSummary?.trim()) || (selectedTeamRoles?.length ?? 0) > 0; const activeRuntimeSessionCount = childSubagentSessions.filter( @@ -592,11 +592,11 @@ export function TeamWorkspaceDock({ return null; } - if (runtimeTeamState?.status === "forming") { + if (dispatchPreviewState?.status === "forming") { return { label: "准备中", tone: "active" }; } - if (runtimeTeamState?.status === "failed") { + if (dispatchPreviewState?.status === "failed") { return { label: "失败", tone: "error" }; } @@ -616,9 +616,12 @@ export function TeamWorkspaceDock({ }; } - if (runtimeTeamState?.status === "formed") { - return runtimeTeamState.members.length > 0 - ? { label: `${runtimeTeamState.members.length} 名成员`, tone: "success" } + if (dispatchPreviewState?.status === "formed") { + return dispatchPreviewState.members.length > 0 + ? { + label: `${dispatchPreviewState.members.length} 名成员`, + tone: "success", + } : { label: "已就绪", tone: "success" }; } @@ -634,7 +637,7 @@ export function TeamWorkspaceDock({ launcherOnly, teamConcurrencyBadgeText, runtimeTeamLabel, - runtimeTeamState, + dispatchPreviewState, ]); const toggleLabel = useMemo(() => { if (expanded) { @@ -652,13 +655,13 @@ export function TeamWorkspaceDock({ } return `查看任务进展 · ${dockCount}`; } - if (runtimeTeamState?.status === "forming") { + if (dispatchPreviewState?.status === "forming") { return "查看任务进展 · 准备中"; } - if (runtimeTeamState?.status === "formed") { - return `查看任务进展 · ${runtimeTeamState.members.length}`; + if (dispatchPreviewState?.status === "formed") { + return `查看任务进展 · ${dispatchPreviewState.members.length}`; } - if (runtimeTeamState?.status === "failed") { + if (dispatchPreviewState?.status === "failed") { return "查看任务进展 · 失败"; } return TEAM_WORKSPACE_SURFACE_TITLE; @@ -666,7 +669,7 @@ export function TeamWorkspaceDock({ dockCount, expanded, hasRealTeamGraph, - runtimeTeamState, + dispatchPreviewState, teamConcurrencyBadgeText, teamQueueBadgeText, ]); @@ -787,7 +790,7 @@ export function TeamWorkspaceDock({ selectedTeamLabel={selectedTeamLabel} selectedTeamSummary={selectedTeamSummary} selectedTeamRoles={selectedTeamRoles} - teamDispatchPreviewState={runtimeTeamState} + teamDispatchPreviewState={dispatchPreviewState} /> ) : ( @@ -808,12 +811,12 @@ export function TeamWorkspaceDock({ {runtimeFormationMeta?.title || "等待协作成员加入"} - {runtimeTeamState?.status === "forming" + {dispatchPreviewState?.status === "forming" ? "系统正在按当前任务准备协作分工,成员接入后会自动展开完整协作面板。" - : runtimeTeamState?.status === "formed" - ? `已准备 ${runtimeTeamState.members.length} 位协作成员,后续会自动接入并继续处理。` - : runtimeTeamState?.status === "failed" - ? runtimeTeamState.errorMessage?.trim() || + : dispatchPreviewState?.status === "formed" + ? `已准备 ${dispatchPreviewState.members.length} 位协作成员,后续会自动接入并继续处理。` + : dispatchPreviewState?.status === "failed" + ? dispatchPreviewState.errorMessage?.trim() || "这次协作准备失败,你仍然可以继续在当前对话中处理。" : ( <> @@ -835,7 +838,7 @@ export function TeamWorkspaceDock({
{runtimeTeamLabel} - {runtimeTeamState + {dispatchPreviewState ? "查看当前协作分工与参考方案" : "查看当前协作方案与分工"} @@ -851,12 +854,12 @@ export function TeamWorkspaceDock({ {runtimeTeamSummary ? ( - {runtimeTeamState ? "当前摘要" : "方案摘要"} + {dispatchPreviewState ? "当前摘要" : "方案摘要"} {runtimeTeamSummary} ) : null} - {runtimeTeamState?.members.map((member) => { + {dispatchPreviewState?.members.map((member) => { const memberStatusMeta = resolveRuntimeMemberStatusMeta( member.status, ); @@ -896,7 +899,7 @@ export function TeamWorkspaceDock({ ); })} - {!runtimeTeamState + {!dispatchPreviewState ? selectedTeamRoles?.map((role) => ( {role.label} @@ -904,13 +907,13 @@ export function TeamWorkspaceDock({ )) : null} - {runtimeTeamState?.blueprint?.label ? ( + {dispatchPreviewState?.blueprint?.label ? ( - 参考方案 · {runtimeTeamState.blueprint.label} + 参考方案 · {dispatchPreviewState.blueprint.label} - {runtimeTeamState.blueprint.summary || + {dispatchPreviewState.blueprint.summary || "当前协作参考了当前方案里的分工偏好。"} @@ -928,8 +931,8 @@ export function TeamWorkspaceDock({ {runtimeTeamSummary ? ( {runtimeTeamSummary} ) : null} - {runtimeTeamState?.members.length ? ( - {runtimeTeamState.members.length} 个成员 + {dispatchPreviewState?.members.length ? ( + {dispatchPreviewState.members.length} 个成员 ) : null} 不遮挡画布 diff --git a/src/components/agent/chat/homeShellEntry.test.ts b/src/components/agent/chat/homeShellEntry.test.ts index d22611ee5..0b81030b7 100644 --- a/src/components/agent/chat/homeShellEntry.test.ts +++ b/src/components/agent/chat/homeShellEntry.test.ts @@ -53,6 +53,12 @@ describe("homeShellEntry", () => { defaultToolPreferences, payload: { prompt: "请起草一版首稿", + contentId: "content-1", + initialRequestMetadata: { + artifact: { + artifact_mode: "draft", + }, + }, themeOverride: "social-media", }, now: () => 456, @@ -66,18 +72,30 @@ describe("homeShellEntry", () => { agentEntry: "claw", immersiveHome: false, projectId: "project-1", + contentId: "content-1", theme: "social-media", initialCreationMode: "guided", initialUserPrompt: "请起草一版首稿", initialUserImages: undefined, + initialRequestMetadata: { + artifact: { + artifact_mode: "draft", + }, + }, openBrowserAssistOnMount: undefined, newChatAt: 456, lockTheme: false, }, workspaceBootstrap: { projectId: "project-1", + contentId: "content-1", initialUserPrompt: "请起草一版首稿", initialUserImages: undefined, + initialRequestMetadata: { + artifact: { + artifact_mode: "draft", + }, + }, theme: "social-media", initialCreationMode: "guided", openBrowserAssistOnMount: undefined, diff --git a/src/components/agent/chat/index.tsx b/src/components/agent/chat/index.tsx index a5dac9d90..d90c31365 100644 --- a/src/components/agent/chat/index.tsx +++ b/src/components/agent/chat/index.tsx @@ -1,10 +1,4 @@ -import { - Suspense, - lazy, - useCallback, - useEffect, - useState, -} from "react"; +import { Suspense, lazy, useCallback, useEffect, useState } from "react"; import { AgentChatHomeShell, type AgentChatWorkspaceBootstrap, @@ -37,7 +31,10 @@ function scheduleWorkspacePrefetch(task: () => void): () => void { }; } - const timeoutId = window.setTimeout(task, WORKSPACE_PREFETCH_FALLBACK_DELAY_MS); + const timeoutId = window.setTimeout( + task, + WORKSPACE_PREFETCH_FALLBACK_DELAY_MS, + ); return () => { window.clearTimeout(timeoutId); }; diff --git a/src/components/agent/chat/service-skills/automationDraft.test.ts b/src/components/agent/chat/service-skills/automationDraft.test.ts index 6ad3b2b73..e0894f763 100644 --- a/src/components/agent/chat/service-skills/automationDraft.test.ts +++ b/src/components/agent/chat/service-skills/automationDraft.test.ts @@ -1,5 +1,6 @@ import { describe, expect, it } from "vitest"; import { + buildServiceSkillAutomationAgentTurnPayloadContext, buildServiceSkillAutomationInitialValues, supportsServiceSkillLocalAutomation, } from "./automationDraft"; @@ -15,6 +16,8 @@ const SCHEDULED_SKILL: ServiceSkillItem = { runnerType: "scheduled", defaultExecutorBinding: "automation_job", executionLocation: "client_default", + defaultArtifactKind: "analysis", + themeTarget: "social-media", version: "seed-v1", slotSchema: [ { @@ -75,5 +78,42 @@ describe("service skill automation draft", () => { expect(initialValues.cron_expr).toBe("00 09 * * *"); expect(initialValues.prompt).toContain("[服务型技能] 每日趋势摘要"); expect(initialValues.prompt).toContain("[自动化执行要求]"); + expect(initialValues.agent_request_metadata).toEqual( + expect.objectContaining({ + artifact: expect.objectContaining({ + artifact_mode: "draft", + artifact_kind: "analysis", + }), + harness: expect.objectContaining({ + theme: "social-media", + session_mode: "theme_workbench", + run_title: "每日趋势摘要", + }), + }), + ); + }); + + it("应为自动化 agent_turn 生成可复用的 artifact/content payload 上下文", () => { + const payloadContext = buildServiceSkillAutomationAgentTurnPayloadContext({ + skill: SCHEDULED_SKILL, + contentId: "content-1", + }); + + expect(payloadContext).toEqual( + expect.objectContaining({ + content_id: "content-1", + request_metadata: expect.objectContaining({ + artifact: expect.objectContaining({ + artifact_mode: "draft", + artifact_kind: "analysis", + }), + harness: expect.objectContaining({ + theme: "social-media", + session_mode: "theme_workbench", + content_id: "content-1", + }), + }), + }), + ); }); }); diff --git a/src/components/agent/chat/service-skills/automationDraft.ts b/src/components/agent/chat/service-skills/automationDraft.ts index 42bca4e67..dd00b8a51 100644 --- a/src/components/agent/chat/service-skills/automationDraft.ts +++ b/src/components/agent/chat/service-skills/automationDraft.ts @@ -1,10 +1,12 @@ import type { AutomationJobDialogInitialValues } from "@/components/settings-v2/system/automation/AutomationJobDialog"; +import { buildHarnessRequestMetadata } from "../utils/harnessRequestMetadata"; import { composeServiceSkillAutomationPrompt } from "./promptComposer"; import type { ServiceSkillItem, ServiceSkillSlotDefinition, ServiceSkillSlotValues, } from "./types"; +import { buildServiceSkillWorkspaceSeed } from "./workspaceLaunch"; const DEFAULT_AUTOMATION_INTERVAL_SECS = 86_400; const WEEKDAY_TO_CRON_DAY: Record = { @@ -25,6 +27,11 @@ interface BuildServiceSkillAutomationInitialValuesInput { workspaceId: string; } +interface BuildServiceSkillAutomationAgentTurnPayloadContextInput { + skill: ServiceSkillItem; + contentId?: string | null; +} + function resolveSlotValue( slot: ServiceSkillSlotDefinition, slotValues: ServiceSkillSlotValues, @@ -53,7 +60,9 @@ function resolveScheduleSlotValue( skill: ServiceSkillItem, slotValues: ServiceSkillSlotValues, ): string { - const scheduleSlot = skill.slotSchema.find((slot) => slot.type === "schedule_time"); + const scheduleSlot = skill.slotSchema.find( + (slot) => slot.type === "schedule_time", + ); if (!scheduleSlot) { return ""; } @@ -70,7 +79,9 @@ function buildDefaultSchedulePrefill(): Pick< }; } -function buildCronPrefill(expr: string): Pick< +function buildCronPrefill( + expr: string, +): Pick< AutomationJobDialogInitialValues, "schedule_kind" | "cron_expr" | "cron_tz" > { @@ -115,7 +126,9 @@ function parseScheduleTextToPrefill( return buildCronPrefill(`${dailyMatch[2]} ${dailyMatch[1]} * * *`); } - const weekdayMatch = value.match(/^每周([一二三四五六日天])\s*(\d{1,2}):(\d{2})$/); + const weekdayMatch = value.match( + /^每周([一二三四五六日天])\s*(\d{1,2}):(\d{2})$/, + ); if (weekdayMatch) { const cronDay = WEEKDAY_TO_CRON_DAY[weekdayMatch[1]]; if (cronDay) { @@ -125,7 +138,9 @@ function parseScheduleTextToPrefill( } } - const weekdayDailyMatch = value.match(/^(?:工作日|每个工作日)\s*(\d{1,2}):(\d{2})$/); + const weekdayDailyMatch = value.match( + /^(?:工作日|每个工作日)\s*(\d{1,2}):(\d{2})$/, + ); if (weekdayDailyMatch) { return buildCronPrefill( `${weekdayDailyMatch[2]} ${weekdayDailyMatch[1]} * * 1-5`, @@ -156,6 +171,34 @@ function buildServiceSkillAutomationDescription( return lines.join("\n"); } +function buildServiceSkillAutomationRequestMetadata( + skill: ServiceSkillItem, + contentId?: string | null, +): Record | undefined { + const targetTheme = skill.themeTarget?.trim(); + const workspaceSeed = buildServiceSkillWorkspaceSeed(skill, targetTheme); + + if (!targetTheme && !workspaceSeed?.requestMetadata) { + return undefined; + } + + return { + ...(workspaceSeed?.requestMetadata ?? {}), + harness: buildHarnessRequestMetadata({ + theme: targetTheme || "general", + preferences: { + webSearch: false, + thinking: false, + task: false, + subagent: false, + }, + sessionMode: workspaceSeed ? "theme_workbench" : "default", + runTitle: skill.title, + contentId: contentId || undefined, + }), + }; +} + export function supportsServiceSkillLocalAutomation( skill: ServiceSkillItem, ): boolean { @@ -165,6 +208,25 @@ export function supportsServiceSkillLocalAutomation( ); } +export function buildServiceSkillAutomationAgentTurnPayloadContext({ + skill, + contentId, +}: BuildServiceSkillAutomationAgentTurnPayloadContextInput): { + content_id?: string | null; + request_metadata?: Record | null; +} { + const normalizedContentId = contentId?.trim() || null; + const requestMetadata = buildServiceSkillAutomationRequestMetadata( + skill, + normalizedContentId, + ); + + return { + content_id: normalizedContentId, + request_metadata: requestMetadata ?? null, + }; +} + export function buildServiceSkillAutomationInitialValues({ skill, slotValues, @@ -188,6 +250,10 @@ export function buildServiceSkillAutomationInitialValues({ }), system_prompt: "", web_search: false, + agent_content_id: "", + agent_request_metadata: buildServiceSkillAutomationAgentTurnPayloadContext({ + skill, + }).request_metadata, max_retries: "2", delivery_mode: "none", ...schedulePrefill, diff --git a/src/components/agent/chat/service-skills/workspaceLaunch.ts b/src/components/agent/chat/service-skills/workspaceLaunch.ts index fa9379c3f..4a1c50532 100644 --- a/src/components/agent/chat/service-skills/workspaceLaunch.ts +++ b/src/components/agent/chat/service-skills/workspaceLaunch.ts @@ -1,6 +1,9 @@ import type { ContentType, ProjectType } from "@/lib/api/project"; import { getDefaultContentTypeForProject } from "@/lib/api/project"; -import type { ServiceSkillArtifactKind, ServiceSkillItem } from "@/lib/api/serviceSkills"; +import type { + ServiceSkillArtifactKind, + ServiceSkillItem, +} from "@/lib/api/serviceSkills"; import { isContentCreationTheme } from "@/components/content-creator/utils/systemPrompt"; export interface ServiceSkillWorkspaceSeed { diff --git a/src/components/agent/chat/workspace/teamWorkbenchPresentation.tsx b/src/components/agent/chat/workspace/teamWorkbenchPresentation.tsx index f49852be1..95c10d922 100644 --- a/src/components/agent/chat/workspace/teamWorkbenchPresentation.tsx +++ b/src/components/agent/chat/workspace/teamWorkbenchPresentation.tsx @@ -42,16 +42,16 @@ function resolveTeamWorkbenchTriggerState(params: { teamControlSummary?: TeamWorkspaceControlSummary | null; executionSummary: ReturnType; }): CanvasWorkbenchTeamView["triggerState"] { - const runtimeTeamState = params.teamDispatchPreviewState; + const dispatchPreviewState = params.teamDispatchPreviewState; if (!params.enabled) { return null; } - if (runtimeTeamState?.status === "failed") { + if (dispatchPreviewState?.status === "failed") { return { tone: "error", label: "失败" }; } - if (runtimeTeamState?.status === "forming") { + if (dispatchPreviewState?.status === "forming") { return { tone: "active", label: "组建中" }; } @@ -75,7 +75,7 @@ function resolveTeamWorkbenchTriggerState(params: { }; } - if (runtimeTeamState?.status === "formed" && !params.hasRealTeamGraph) { + if (dispatchPreviewState?.status === "formed" && !params.hasRealTeamGraph) { return { tone: "active", label: "已就绪" }; } @@ -102,7 +102,7 @@ export function useTeamWorkbenchPresentation({ teamWaitSummary = null, teamControlSummary = null, }: UseTeamWorkbenchPresentationParams) { - const runtimeTeamState = teamDispatchPreviewState; + const dispatchPreviewState = teamDispatchPreviewState; const boardProps = useMemo>( () => ({ ...surfaceProps, @@ -194,8 +194,8 @@ export function useTeamWorkbenchPresentation({ return { enabled: true, title: - runtimeTeamState?.label?.trim() || - runtimeTeamState?.blueprint?.label?.trim() || + dispatchPreviewState?.label?.trim() || + dispatchPreviewState?.blueprint?.label?.trim() || surfaceProps.selectedTeamLabel || "团队工作台", subtitle: "主对话保留调度记录,画布按角色分别展示执行过程与结果。", @@ -210,7 +210,7 @@ export function useTeamWorkbenchPresentation({ autoFocusToken, enabled, renderTeamWorkbenchPreview, - runtimeTeamState, + dispatchPreviewState, surfaceProps.selectedTeamLabel, teamWorkbenchSummaryPanel, triggerState, diff --git a/src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx b/src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx index e79a7dc81..ee92a5f88 100644 --- a/src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx +++ b/src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx @@ -18,9 +18,9 @@ interface HookHarness { } const mockSendMessage = vi.fn(async () => undefined); -const mockPrepareRuntimeTeamBeforeSend = vi.fn( - async () => null, -); +const mockPrepareRuntimeTeamBeforeSend = vi.fn< + HookProps["prepareRuntimeTeamBeforeSend"] +>(async () => null); const mockFinalizeAfterSendSuccess = vi.fn(); const mockRollbackAfterSendFailure = vi.fn(); const mockSetInput = vi.fn(); @@ -98,6 +98,7 @@ function mountHook(initialProps?: Partial): HookHarness { currentGateKey: "default_gate", themeWorkbenchActiveQueueTitle: undefined, contentId: null, + workspaceRequestMetadataBase: undefined, messagesCount: 0, sendMessage: mockSendMessage, resolveSendBoundary: (({ sourceText }) => ({ @@ -106,9 +107,10 @@ function mountHook(initialProps?: Partial): HookHarness { shouldConsumePendingThemeWorkbenchInitialPrompt: false, shouldDismissThemeWorkbenchEntryPrompt: false, })) as HookProps["resolveSendBoundary"], - isBlockedByBrowserPreflight: (() => false) as HookProps["isBlockedByBrowserPreflight"], - maybeStartBrowserTaskPreflight: - (() => false) as HookProps["maybeStartBrowserTaskPreflight"], + isBlockedByBrowserPreflight: (() => + false) as HookProps["isBlockedByBrowserPreflight"], + maybeStartBrowserTaskPreflight: (() => + false) as HookProps["maybeStartBrowserTaskPreflight"], finalizeAfterSendSuccess: mockFinalizeAfterSendSuccess as HookProps["finalizeAfterSendSuccess"], rollbackAfterSendFailure: @@ -171,20 +173,23 @@ describe("useWorkspaceSendActions", () => { try { await act(async () => { - const started = await harness.getValue().handleSend( - [], - false, - false, - "继续处理当前话题", - "react", - autoContinue, - ); + const started = await harness + .getValue() + .handleSend( + [], + false, + false, + "继续处理当前话题", + "react", + autoContinue, + ); expect(started).toBe(true); }); expect(mockSendMessage).toHaveBeenCalledTimes(1); - const args = - mockSendMessage.mock.calls[0] as Parameters; + const args = mockSendMessage.mock.calls[0] as Parameters< + HookProps["sendMessage"] + >; expect(args?.[6]).toBeUndefined(); expect(args?.[7]).toEqual(autoContinue); expect(args?.[8]).toMatchObject({ @@ -221,7 +226,10 @@ describe("useWorkspaceSendActions", () => { expect(started).toBe(true); }); - expect(mockSetRuntimeTeamDispatchPreview).toHaveBeenNthCalledWith(1, null); + expect(mockSetRuntimeTeamDispatchPreview).toHaveBeenNthCalledWith( + 1, + null, + ); expect(mockSetRuntimeTeamDispatchPreview).toHaveBeenNthCalledWith( 2, expect.objectContaining({ @@ -239,4 +247,45 @@ describe("useWorkspaceSendActions", () => { harness.unmount(); } }); + + it("应保留 workspace 级 request metadata,并与 harness 元数据合并", async () => { + const harness = mountHook({ + isThemeWorkbench: true, + mappedTheme: "social-media", + contentId: "content-service-skill-1", + workspaceRequestMetadataBase: { + artifact: { + artifact_mode: "draft", + artifact_kind: "analysis", + }, + }, + }); + + try { + await act(async () => { + const started = await harness.getValue().handleSend(); + expect(started).toBe(true); + }); + + expect(mockSendMessage).toHaveBeenCalledTimes(1); + const args = mockSendMessage.mock.calls[0] as Parameters< + HookProps["sendMessage"] + >; + expect(args?.[8]).toMatchObject({ + requestMetadata: { + artifact: { + artifact_mode: "draft", + artifact_kind: "analysis", + }, + harness: expect.objectContaining({ + theme: "social-media", + session_mode: "theme_workbench", + content_id: "content-service-skill-1", + }), + }, + }); + } finally { + harness.unmount(); + } + }); }); diff --git a/src/components/agent/chat/workspace/useWorkspaceSendActions.ts b/src/components/agent/chat/workspace/useWorkspaceSendActions.ts index 1030abe20..00997dc28 100644 --- a/src/components/agent/chat/workspace/useWorkspaceSendActions.ts +++ b/src/components/agent/chat/workspace/useWorkspaceSendActions.ts @@ -10,7 +10,10 @@ import { extractExistingHarnessMetadata, } from "../utils/harnessRequestMetadata"; import { isTeamRuntimeRecommendation } from "../utils/contextualRecommendations"; -import { saveChatToolPreferences, type ChatToolPreferences } from "../utils/chatToolPreferences"; +import { + saveChatToolPreferences, + type ChatToolPreferences, +} from "../utils/chatToolPreferences"; import type { HandleSendOptions } from "../hooks/handleSendTypes"; import type { ThemeWorkbenchSendBoundaryState } from "../hooks/useThemeWorkbenchSendBoundary"; import type { UseRuntimeTeamFormationResult } from "../hooks/useRuntimeTeamFormation"; @@ -90,7 +93,10 @@ interface UseWorkspaceSendActionsParams { }) => Promise; } -function applyActiveContextPrompt(text: string, activeContextPrompt: string): string { +function applyActiveContextPrompt( + text: string, + activeContextPrompt: string, +): string { if (!activeContextPrompt.trim()) { return text; } diff --git a/src/components/settings-v2/system/automation/AutomationJobDialog.test.tsx b/src/components/settings-v2/system/automation/AutomationJobDialog.test.tsx index ed1692c1a..9cdc5a714 100644 --- a/src/components/settings-v2/system/automation/AutomationJobDialog.test.tsx +++ b/src/components/settings-v2/system/automation/AutomationJobDialog.test.tsx @@ -4,13 +4,11 @@ import { createRoot, type Root } from "react-dom/client"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { AutomationJobDialog } from "./AutomationJobDialog"; -const { - mockListBrowserProfiles, - mockListBrowserEnvironmentPresets, -} = vi.hoisted(() => ({ - mockListBrowserProfiles: vi.fn(), - mockListBrowserEnvironmentPresets: vi.fn(), -})); +const { mockListBrowserProfiles, mockListBrowserEnvironmentPresets } = + vi.hoisted(() => ({ + mockListBrowserProfiles: vi.fn(), + mockListBrowserEnvironmentPresets: vi.fn(), + })); vi.mock("@/features/browser-runtime/api", () => ({ browserRuntimeApi: { @@ -162,6 +160,67 @@ async function renderDialog(props: { } describe("AutomationJobDialog", () => { + it("编辑 agent_turn 任务时应保留 content_id 与 request_metadata", async () => { + const onSubmit = vi.fn().mockResolvedValue(undefined); + await renderDialog({ + onSubmit, + jobOverride: { + payload: { + kind: "agent_turn", + prompt: "生成趋势摘要", + system_prompt: "请保持简洁", + web_search: false, + content_id: "content-1", + request_metadata: { + artifact: { + artifact_mode: "draft", + artifact_kind: "analysis", + }, + harness: { + theme: "social-media", + session_mode: "theme_workbench", + content_id: "content-1", + }, + }, + }, + }, + }); + + const submitButton = Array.from(document.querySelectorAll("button")).find( + (button) => button.textContent?.includes("保存修改"), + ) as HTMLButtonElement | undefined; + + await act(async () => { + submitButton?.click(); + await Promise.resolve(); + }); + + expect(onSubmit).toHaveBeenCalledWith({ + mode: "edit", + id: "job-1", + request: expect.objectContaining({ + payload: expect.objectContaining({ + kind: "agent_turn", + prompt: "生成趋势摘要", + system_prompt: "请保持简洁", + web_search: false, + content_id: "content-1", + request_metadata: expect.objectContaining({ + artifact: expect.objectContaining({ + artifact_mode: "draft", + artifact_kind: "analysis", + }), + harness: expect.objectContaining({ + theme: "social-media", + session_mode: "theme_workbench", + content_id: "content-1", + }), + }), + }), + }), + }); + }, 10_000); + it("编辑浏览器任务时应保持 browser_session payload 提交", async () => { const onSubmit = vi.fn().mockResolvedValue(undefined); await renderDialog({ onSubmit }); @@ -265,7 +324,9 @@ describe("AutomationJobDialog", () => { }); expect( - document.querySelector("[data-testid='automation-job-dialog-scroll-area']"), + document.querySelector( + "[data-testid='automation-job-dialog-scroll-area']", + ), ).not.toBeNull(); const submitButton = Array.from(document.querySelectorAll("button")).find( diff --git a/src/components/settings-v2/system/automation/AutomationJobDialog.tsx b/src/components/settings-v2/system/automation/AutomationJobDialog.tsx index 6e90dcdf8..7064c45b3 100644 --- a/src/components/settings-v2/system/automation/AutomationJobDialog.tsx +++ b/src/components/settings-v2/system/automation/AutomationJobDialog.tsx @@ -1,5 +1,12 @@ import { useEffect, useMemo, useState } from "react"; -import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; @@ -53,6 +60,8 @@ type AutomationJobFormState = { prompt: string; system_prompt: string; web_search: boolean; + agent_content_id: string; + agent_request_metadata: Record | null; browser_profile_id: string; browser_profile_key: string; browser_url: string; @@ -103,6 +112,8 @@ function createDefaultForm(workspaces: Project[]): AutomationJobFormState { prompt: "", system_prompt: "", web_search: false, + agent_content_id: "", + agent_request_metadata: null, browser_profile_id: "", browser_profile_key: "", browser_url: "", @@ -210,6 +221,8 @@ function createFormFromJob( form.prompt = job.payload.prompt; form.system_prompt = job.payload.system_prompt ?? ""; form.web_search = job.payload.web_search; + form.agent_content_id = job.payload.content_id ?? ""; + form.agent_request_metadata = job.payload.request_metadata ?? null; } else { form.browser_profile_id = job.payload.profile_id; form.browser_profile_key = job.payload.profile_key ?? ""; @@ -228,9 +241,9 @@ function createFormFromJob( ? "telegram" : job.delivery.channel === "google_sheets" ? "google_sheets" - : job.delivery.channel === "local_file" - ? "local_file" - : "webhook"; + : job.delivery.channel === "local_file" + ? "local_file" + : "webhook"; form.delivery_target = job.delivery.target ?? ""; const deliveryOutputContract = normalizeDeliveryOutputContract( form.delivery_channel, @@ -311,7 +324,9 @@ function scheduleHint(form: AutomationJobFormState): string { if (form.schedule_kind === "cron") { return "使用 Cron 表达式驱动执行。"; } - return form.at_local ? "一次性任务,到点后自动停用。" : "选择一次性触发时间。"; + return form.at_local + ? "一次性任务,到点后自动停用。" + : "选择一次性触发时间。"; } export function AutomationJobDialog({ @@ -370,7 +385,9 @@ export function AutomationJobDialog({ if (cancelled) { return; } - setProfiles(nextProfiles.filter((profile) => profile.archived_at === null)); + setProfiles( + nextProfiles.filter((profile) => profile.archived_at === null), + ); setPresets(nextPresets.filter((preset) => preset.archived_at === null)); } catch (loadError) { if (!cancelled) { @@ -421,16 +438,19 @@ export function AutomationJobDialog({ const scheduleSummary = useMemo(() => scheduleHint(form), [form]); const selectedBrowserProfile = useMemo( () => - profiles.find((profile) => profile.id === form.browser_profile_id) ?? null, + profiles.find((profile) => profile.id === form.browser_profile_id) ?? + null, [form.browser_profile_id, profiles], ); const selectedEnvironmentPreset = useMemo( () => - presets.find((preset) => preset.id === form.browser_environment_preset_id) ?? - null, + presets.find( + (preset) => preset.id === form.browser_environment_preset_id, + ) ?? null, [form.browser_environment_preset_id, presets], ); - const isTextOnlyDelivery = form.delivery_channel === TEXT_ONLY_DELIVERY_CHANNEL; + const isTextOnlyDelivery = + form.delivery_channel === TEXT_ONLY_DELIVERY_CHANNEL; async function handleSubmit() { try { @@ -454,13 +474,16 @@ export function AutomationJobDialog({ prompt: form.prompt.trim(), system_prompt: form.system_prompt.trim() || null, web_search: form.web_search, + content_id: form.agent_content_id.trim() || null, + request_metadata: form.agent_request_metadata ?? null, }; } else { if (!form.browser_profile_id.trim()) { throw new Error("请选择浏览器资料"); } const profileKey = - selectedBrowserProfile?.profile_key ?? form.browser_profile_key.trim(); + selectedBrowserProfile?.profile_key ?? + form.browser_profile_key.trim(); if (!profileKey) { throw new Error("浏览器资料不可用,请重新选择"); } @@ -472,7 +495,10 @@ export function AutomationJobDialog({ } catch { throw new Error("浏览器启动地址格式无效"); } - if (parsedUrl.protocol !== "http:" && parsedUrl.protocol !== "https:") { + if ( + parsedUrl.protocol !== "http:" && + parsedUrl.protocol !== "https:" + ) { throw new Error("浏览器启动地址仅支持 http/https"); } } @@ -543,7 +569,9 @@ export function AutomationJobDialog({ }); } } catch (submitError) { - setError(submitError instanceof Error ? submitError.message : "保存任务失败"); + setError( + submitError instanceof Error ? submitError.message : "保存任务失败", + ); } } @@ -559,7 +587,8 @@ export function AutomationJobDialog({ {mode === "create" ? "新建自动化任务" : "编辑自动化任务"} - 用结构化 job 承载 Agent 与浏览器任务,调度、工作区、运行历史都在单一模型里维护。 + 用结构化 job 承载 Agent + 与浏览器任务,调度、工作区、运行历史都在单一模型里维护。 @@ -568,37 +597,40 @@ export function AutomationJobDialog({ className="min-h-0 flex-1 overflow-y-auto px-4 pb-4 pt-4 sm:px-6 sm:pb-6 sm:pt-5" >
-
- - - setForm((current) => ({ ...current, name: event.target.value })) - } - placeholder="例如:每日品牌线索巡检" - /> -
-
- - -
+
+ + + setForm((current) => ({ + ...current, + name: event.target.value, + })) + } + placeholder="例如:每日品牌线索巡检" + /> +
+
+ + +
@@ -634,7 +666,9 @@ export function AutomationJobDialog({ Agent 对话任务 - 浏览器会话任务 + + 浏览器会话任务 +
@@ -714,72 +748,74 @@ export function AutomationJobDialog({
- {form.schedule_kind === "every" ? ( -
- - - setForm((current) => ({ - ...current, - every_secs: event.target.value, - })) - } - /> -
- ) : null} - - {form.schedule_kind === "cron" ? ( - <> + {form.schedule_kind === "every" ? (
- + setForm((current) => ({ ...current, - cron_expr: event.target.value, + every_secs: event.target.value, })) } - placeholder="0 9 * * *" />
-
- + ) : null} + + {form.schedule_kind === "cron" ? ( + <> +
+ + + setForm((current) => ({ + ...current, + cron_expr: event.target.value, + })) + } + placeholder="0 9 * * *" + /> +
+
+ + + setForm((current) => ({ + ...current, + cron_tz: event.target.value, + })) + } + placeholder="Asia/Shanghai" + /> +
+ + ) : null} + + {form.schedule_kind === "at" ? ( +
+ setForm((current) => ({ ...current, - cron_tz: event.target.value, + at_local: event.target.value, })) } - placeholder="Asia/Shanghai" />
- - ) : null} + ) : null} +
- {form.schedule_kind === "at" ? ( -
- - - setForm((current) => ({ - ...current, - at_local: event.target.value, - })) - } - /> -
- ) : null} -
- -
{scheduleSummary}
+
+ {scheduleSummary} +
{form.payload_kind === "agent_turn" ? ( @@ -801,7 +837,9 @@ export function AutomationJobDialog({
- +