diff --git a/desktop/README.md b/desktop/README.md index eb3ba4e8f1..102c27bc04 100644 --- a/desktop/README.md +++ b/desktop/README.md @@ -16,7 +16,9 @@ Repeated launches activate the existing window for this channel. Profile storage ## Build on Windows -Use Windows 11 x64, Visual Studio C++ Build Tools with a Windows SDK, Node **24.14.1**, pnpm **11.13.1**, Rust **1.95.0 MSVC**, and WebView2. `desktop/.mise.toml`, `rust-toolchain.toml`, `pnpm-lock.yaml` and `src-tauri/Cargo.lock` pin the tools and dependencies independently of Python and the website. +Use Windows 11 x64, Visual Studio C++ Build Tools with a Windows SDK, Node **24.14.1**, pnpm **11.13.1**, Rust **1.95.0 MSVC**, **JDK 11 or newer with `java` available on `PATH`**, and WebView2. `desktop/.mise.toml`, `rust-toolchain.toml`, `pnpm-lock.yaml` and `src-tauri/Cargo.lock` pin the tools and dependencies independently of Python and the website. + +The OpenAPI Generator used by `generate` and `generate:check` runs on Java. On the first run, `openapi-generator-cli` may download the pinned generator JAR from Maven Central, so the first generation or drift check requires network access. Subsequent runs can reuse the downloaded JAR. Some machines default to Rust's GNU host. In PowerShell, explicitly select the pinned MSVC host for this process: @@ -65,7 +67,7 @@ A successful save that returns no memory record is reported as an operation succ ## Contracts and resources -`pnpm --dir desktop generate` derives TypeScript schemas and the reviewed ten-operation manifest from `openapi/powercontext.yaml`; `generate:check` detects drift, including a normalized contract SHA-256. Typed Rust adapters consume that generated manifest and generated wire schemas. No public route is independently handwritten in the application. The manifest is not an IPC permission grant. +`pnpm --dir desktop generate` derives TypeScript schemas, the reviewed ten-operation manifest, and the Rust wire models from `openapi/powercontext.yaml`; `generate:check` detects drift, including a normalized contract SHA-256. The OpenAPI Generator CLI version is pinned in `desktop/openapitools.json`, and the limited Rust customization lives in `desktop/scripts/openapi-generator/rust/`. Generated `src-tauri/src/transport/wire.rs` must not be edited by hand: after changing the contract or generator template, run `pnpm --dir desktop generate`, then run `pnpm --dir desktop generate:check` in CI. Typed Rust adapters consume that generated manifest and generated wire schemas. No public route is independently handwritten in the application. The manifest is not an IPC permission grant. `cargo run --locked --manifest-path desktop/src-tauri/Cargo.toml --example export_ipc` derives the TypeScript IPC request/receipt/error types from Rust. `ipc:check` verifies them. IPC exposes typed connection, Scope, memory and diagnostic operations to the main window only; no generic fetch, shell, file, database or secret-read command is granted. diff --git a/desktop/README.zh.md b/desktop/README.zh.md index a1db8b2e0d..62f7bc952c 100644 --- a/desktop/README.zh.md +++ b/desktop/README.zh.md @@ -16,7 +16,9 @@ ## 开发与构建 -Windows 11 x64 上需要 Node 24.14.1、pnpm 11.13.1、Rust 1.95.0 MSVC、Visual Studio C++ Build Tools、Windows SDK 和 WebView2。安装后的用户程序不依赖 Node、Rust、Python 或本地 Server。 +Windows 11 x64 上需要 Node 24.14.1、pnpm 11.13.1、Rust 1.95.0 MSVC、JDK 11 或更高版本(确保 `java` 位于 `PATH` 中)、Visual Studio C++ Build Tools、Windows SDK 和 WebView2。安装后的用户程序不依赖 Node、Rust、Python 或本地 Server。 + +`generate` 和 `generate:check` 会启动基于 Java 的 OpenAPI Generator。首次运行时,`openapi-generator-cli` 可能从 Maven Central 下载固定版本的 Generator JAR,因此首次生成或漂移检查需要网络访问;后续运行可以复用已下载的 JAR。 从仓库根目录执行: @@ -44,6 +46,7 @@ pnpm --dir desktop desktop:dev 工程边界: - OpenAPI 自动派生的 TypeScript schema 和十项 operation 映射,包含契约摘要及漂移检查。 +- `desktop/openapitools.json` 固定 OpenAPI Generator CLI 版本,Rust 模板位于 `desktop/scripts/openapi-generator/rust/`。修改 OpenAPI 合同或模板后,在仓库根目录执行 `pnpm --dir desktop generate`,不要手动编辑生成的 `src-tauri/src/transport/wire.rs`;CI 通过 `pnpm --dir desktop generate:check` 检查生成结果是否漂移。 - Rust 自动派生的 IPC 类型与安全错误;凭据只写请求必须显式选择持久化或仅会话,成功回执只含存储模式,不含秘密或凭据标识。 - Windows Credential Manager 原生适配器;保存失败直接报错,只有显式选择才采用仅会话内存。秘密类型不支持序列化,不实现 Debug。 - 使用系统证书信任的原生 HTTPS;可为单个客户端添加显式 CA,继续校验主机名。 diff --git a/desktop/openapitools.json b/desktop/openapitools.json new file mode 100644 index 0000000000..e91f32518f --- /dev/null +++ b/desktop/openapitools.json @@ -0,0 +1,7 @@ +{ + "$schema": "./node_modules/@openapitools/openapi-generator-cli/config.schema.json", + "spaces": 2, + "generator-cli": { + "version": "7.26.0" + } +} diff --git a/desktop/package.json b/desktop/package.json index 0e3df74ac8..c3a2d73f72 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -30,6 +30,7 @@ }, "devDependencies": { "@tauri-apps/cli": "2.11.4", + "@openapitools/openapi-generator-cli": "2.41.0", "@testing-library/react": "16.3.0", "@testing-library/user-event": "14.6.1", "@types/node": "26.3.0", diff --git a/desktop/pnpm-lock.yaml b/desktop/pnpm-lock.yaml index 3804567b3f..5b8539db54 100644 --- a/desktop/pnpm-lock.yaml +++ b/desktop/pnpm-lock.yaml @@ -18,6 +18,9 @@ importers: specifier: 19.2.8 version: 19.2.8(react@19.2.8) devDependencies: + '@openapitools/openapi-generator-cli': + specifier: 2.41.0 + version: 2.41.0(supports-color@10.2.2) '@tauri-apps/cli': specifier: 2.11.4 version: 2.11.4 @@ -84,6 +87,9 @@ packages: resolution: {integrity: sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==} engines: {node: '>=6.9.0'} + '@borewit/text-codec@0.2.2': + resolution: {integrity: sha512-DDaRehssg1aNrH4+2hnj1B7vnUGEjU6OIlyRdkMd0aUdIUvKXrJfXsy8LVtXAy7DRvYVluWbMspsRhz2lcW0mQ==} + '@csstools/color-helpers@5.1.0': resolution: {integrity: sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==} engines: {node: '>=18'} @@ -268,6 +274,18 @@ packages: cpu: [x64] os: [win32] + '@inquirer/core@6.0.0': + resolution: {integrity: sha512-fKi63Khkisgda3ohnskNf5uZJj+zXOaBvOllHsOkdsXRA/ubQLJQrZchFFi57NKbZzkTunXiBMdvWOv71alonw==} + engines: {node: '>=14.18.0'} + + '@inquirer/select@1.3.3': + resolution: {integrity: sha512-RzlRISXWqIKEf83FDC9ZtJ3JvuK1l7aGpretf41BCWYrvla2wU8W8MTRNMiPrPJ+1SIqrRC1nZdZ60hD9hRXLg==} + engines: {node: '>=14.18.0'} + + '@inquirer/type@1.1.6': + resolution: {integrity: sha512-OCKOpn0CrFDslR8s3who7hlr823zXTb1iShGCaaWgEJFfkIV0T9aLZV2QGnOuU78IrsPYLkr3oKx9dZwwCH3Rw==} + engines: {node: '>=14.18.0'} + '@jridgewell/resolve-uri@3.1.2': resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} @@ -278,6 +296,58 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + '@lukeed/csprng@1.1.0': + resolution: {integrity: sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==} + engines: {node: '>=8'} + + '@nestjs/axios@4.0.1': + resolution: {integrity: sha512-68pFJgu+/AZbWkGu65Z3r55bTsCPlgyKaV4BSG8yUAD72q1PPuyVRgUwFv6BxdnibTUHlyxm06FmYWNC+bjN7A==} + peerDependencies: + '@nestjs/common': ^10.0.0 || ^11.0.0 + axios: ^1.3.1 + rxjs: ^7.0.0 + + '@nestjs/common@11.2.1': + resolution: {integrity: sha512-SEgtP+M9DqNhQkgJIlJ3oTp3gemo/8owySovzMGmJj2kcfIH1G6QP45AAb8dE4a3IpVicpUvdDAy7Syk7ebjBw==} + peerDependencies: + class-transformer: '>=0.4.1' + class-validator: '>=0.13.2' + reflect-metadata: ^0.1.12 || ^0.2.0 + rxjs: ^7.1.0 + peerDependenciesMeta: + class-transformer: + optional: true + class-validator: + optional: true + + '@nestjs/core@11.2.1': + resolution: {integrity: sha512-M5PWFU8NdRTgX9Po49d7TQKg7f5t8GAVUa/Esy4tmaMWcKugTzg3ZzpJfD3LEPMuRHjfs6+8pQYgtuP2uz3rDw==} + engines: {node: '>= 20'} + peerDependencies: + '@nestjs/common': ^11.0.0 + '@nestjs/microservices': ^11.0.0 + '@nestjs/platform-express': ^11.0.0 + '@nestjs/websockets': ^11.0.0 + reflect-metadata: ^0.1.12 || ^0.2.0 + rxjs: ^7.1.0 + peerDependenciesMeta: + '@nestjs/microservices': + optional: true + '@nestjs/platform-express': + optional: true + '@nestjs/websockets': + optional: true + + '@nuxtjs/opencollective@0.3.2': + resolution: {integrity: sha512-um0xL3fO7Mf4fDxcqx9KryrB7zgRM5JSlvGN5AGkP6JLM5XEKyjeAiPbNxdXVXQ16isuAhYpvP88NgL2BGd6aA==} + engines: {node: '>=8.0.0', npm: '>=5.0.0'} + hasBin: true + + '@openapitools/openapi-generator-cli@2.41.0': + resolution: {integrity: sha512-T/cDW4XeO2MJJCgR+Teuc2z3jIuxlIlboFxFPMDvo9m/6hpIagtGGI+Z+ucMuaPVAVIM13FdVr+Zizwq4xUHJA==} + engines: {node: '>=22.0.0'} + hasBin: true + '@oxc-project/types@0.154.0': resolution: {integrity: sha512-KYOUGQFlLWR+s4QMV2Q9ko38TZm7EdO87Qm7rvZLqk/webse/cDjtyxKhg/47l0byCbs/k46LT8qc4PKjAikzA==} @@ -616,6 +686,13 @@ packages: peerDependencies: '@testing-library/dom': '>=7.21.4' + '@tokenizer/inflate@0.4.1': + resolution: {integrity: sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA==} + engines: {node: '>=18'} + + '@tokenizer/token@0.3.0': + resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} + '@types/aria-query@5.0.4': resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} @@ -628,6 +705,12 @@ packages: '@types/estree@1.0.9': resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} + '@types/mute-stream@0.0.4': + resolution: {integrity: sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==} + + '@types/node@20.19.43': + resolution: {integrity: sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==} + '@types/node@26.3.0': resolution: {integrity: sha512-L3fgrnchriRC2ExBflb8j4uZZURHZfQsmQeyVzhjcHW4kkwVyo8/0h1B2MVzMTrYUJYu6G7EWs14hW/L9putqw==} @@ -639,6 +722,9 @@ packages: '@types/react@19.2.18': resolution: {integrity: sha512-AnzbBERsrLKtk2XSfTbYRLjQPdy116Sty4q+T+Bp3IC4l6jNBvreVPAHmpq9qhXQM7CXZPjLVmGMw9sy+hxQ3w==} + '@types/wrap-ansi@3.0.0': + resolution: {integrity: sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==} + '@vitejs/plugin-react@6.1.1': resolution: {integrity: sha512-yxLaQV9gkhS8ezJqCM6+ndU7mDY6gqAg75NQ+0IjwEI8IYOmQCgkRwHKVSfWXW076DsqMo0Dk+0FK1U+M5RgFw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -669,22 +755,54 @@ packages: '@vitest/spy@5.0.1': resolution: {integrity: sha512-rbto/mF/SGERxEgYOek7Xm6B9b+y+mVoo+f4b2LymYO8zM1b7uB5nHuhVMTP2hxdzgxvGiZYGxGIaMvL5y180Q==} + agent-base@6.0.0: + resolution: {integrity: sha512-j1Q7cSCqN+AwrmDd+pzgqc0/NpC655x2bUf5ZjRIO77DcNBFmh+OgRNzF6OKdCC9RSCb19fGd99+bhXFdkRNqw==} + engines: {node: '>= 6.0.0'} + agent-base@7.1.4: resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} engines: {node: '>= 14'} + agent-base@9.0.0: + resolution: {integrity: sha512-TQf59BsZnytt8GdJKLPfUZ54g/iaUL2OWDSFCCvMOhsHduDQxO8xC4PNeyIkVcA5KwL2phPSv0douC0fgWzmnA==} + engines: {node: '>= 20'} + ansi-colors@4.1.3: resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} engines: {node: '>=6'} + ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + + ansi-regex@4.1.0: + resolution: {integrity: sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==} + engines: {node: '>=6'} + ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} + ansi-regex@6.4.0: + resolution: {integrity: sha512-KzTVk2tCWAHtYrvvvaP8bJKJq2pVinhLcGEQdtLIYPbmNGNyYe8QwNaTUYQp2J7/vIsUKt5QCqAfUkYyG9DkOw==} + engines: {node: '>=12'} + + ansi-styles@4.0.0: + resolution: {integrity: sha512-8zjUtFJ3db/QoPXuuEMloS2AUf79/yeyttJ7Abr3hteopJu9HK8vsgGviGUMq+zyA6cZZO6gAyZoMTF6TgaEjA==} + engines: {node: '>=8'} + + ansi-styles@4.1.0: + resolution: {integrity: sha512-Qts4KCLKG+waHc9C4m07weIY8qyeixoS0h6RnbsNVD6Fw+pEZGW3vTyObL3WXpE09Mq4Oi7/lBEyLmOiLtlYWQ==} + engines: {node: '>=8'} + ansi-styles@5.2.0: resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} engines: {node: '>=10'} + ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} @@ -695,22 +813,102 @@ packages: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} + ast-types@0.13.4: + resolution: {integrity: sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==} + engines: {node: '>=4'} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + axios@1.20.0: + resolution: {integrity: sha512-r8aOh8j9cGKpgQAqpzrUHnSIc6a59Y3Xf/cv8sy1DrHCkZHzQGEuoq1tARk6qSyDdtQGSDgpb9kFlruzPvrgwg==} + balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + balanced-match@4.0.4: + resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} + engines: {node: 18 || 20 || >=22} + + basic-ftp@5.3.1: + resolution: {integrity: sha512-bopVNp6ugyA150DDuZfPFdt1KZ5a94ZDiwX4hMgZDzF+GttD80lEy8kj98kbyhLXnPvhtIo93mdnLIjpCAeeOw==} + engines: {node: '>=10.0.0'} + brace-expansion@2.1.7: resolution: {integrity: sha512-uZbew1NqdmPDTMJ8ah1y+b+9QEJrfkXFk3RcTQw3X0jW/xRUvFKsg1CfQdSYGdTbXZWExtU3J3ccxtnfw1Fi0g==} + brace-expansion@5.0.12: + resolution: {integrity: sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==} + engines: {node: 20 || >=22} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + chai@6.2.2: resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} engines: {node: '>=18'} + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + chalk@5.6.2: + resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + change-case@5.4.4: resolution: {integrity: sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w==} + cli-spinners@2.9.2: + resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} + engines: {node: '>=6'} + + cli-width@4.1.0: + resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} + engines: {node: '>= 12'} + + cliui@9.0.1: + resolution: {integrity: sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==} + engines: {node: '>=20'} + + clone@1.0.4: + resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} + engines: {node: '>=0.8'} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + colorette@1.4.0: resolution: {integrity: sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==} + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + commander@8.3.0: + resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} + engines: {node: '>= 12'} + + compare-versions@6.1.1: + resolution: {integrity: sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==} + + concurrently@10.0.6: + resolution: {integrity: sha512-qgICXXFp2/3nAebRLmxcINKEXM1mLK3ij/y31P02VTs/KIkddIeC05n73DxOXsXMB9LFSqNU1/na3lDlOhcbIw==} + engines: {node: '>=22'} + hasBin: true + + consola@2.15.3: + resolution: {integrity: sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==} + + console.table@0.10.0: + resolution: {integrity: sha512-dPyZofqggxuvSf7WXvNjuRfnsOk1YazkVP8FdxH4tcH2c37wc79/Yl6Bhr7Lsu00KMgy2ql/qCMuNu8xctZM8g==} + engines: {node: '> 0.10'} + cssstyle@4.6.0: resolution: {integrity: sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==} engines: {node: '>=18'} @@ -718,6 +916,10 @@ packages: csstype@3.2.3: resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + data-uri-to-buffer@8.0.0: + resolution: {integrity: sha512-6UHfyCux51b8PTGDgveqtz1tvphBku5DrMKKJbFAZAJOI2zsjDpDoYE1+QGj7FOMS4BdTFNJsJiR3zEB0xH0yQ==} + engines: {node: '>= 20'} + data-urls@5.0.0: resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==} engines: {node: '>=18'} @@ -734,6 +936,19 @@ packages: decimal.js@10.6.0: resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} + defaults@1.0.4: + resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} + + degenerator@7.0.1: + resolution: {integrity: sha512-ABErK0IefDSyHjlPH7WUEenIAX2rPPnrDcDM+TS3z3+zu9TfyKKi07BQM+8rmxpdE2y1v5fjjdoAS/x4D2U60w==} + engines: {node: '>= 20'} + peerDependencies: + quickjs-wasi: ^2.2.0 + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + dequal@2.0.3: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} @@ -745,16 +960,71 @@ packages: dom-accessibility-api@0.5.16: resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + easy-table@1.1.0: + resolution: {integrity: sha512-oq33hWOSSnl2Hoh00tZWaIPi1ievrD9aFG82/IgjlycAnW9hHx5PkJiXpxPsgEE+H7BsbVQXFVFST8TEXS6/pA==} + + emoji-regex@10.3.0: + resolution: {integrity: sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + entities@6.0.1: resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} engines: {node: '>=0.12'} + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + es-module-lexer@2.3.2: resolution: {integrity: sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==} + es-object-atoms@1.1.2: + resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + + escodegen@2.1.0: + resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} + engines: {node: '>=6.0'} + hasBin: true + + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + estree-walker@3.0.3: resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + expect-type@1.4.0: resolution: {integrity: sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==} engines: {node: '>=12.0.0'} @@ -762,6 +1032,9 @@ packages: fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + fast-safe-stringify@2.1.1: + resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} + fdir@6.5.0: resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} engines: {node: '>=12.0.0'} @@ -771,11 +1044,86 @@ packages: picomatch: optional: true + figures@3.2.0: + resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} + engines: {node: '>=8'} + + file-type@21.3.4: + resolution: {integrity: sha512-Ievi/yy8DS3ygGvT47PjSfdFoX+2isQueoYP1cntFW1JLYAuS4GD7NUPGg4zv2iZfV52uDyk5w5Z0TdpRS6Q1g==} + engines: {node: '>=20'} + + follow-redirects@1.16.1: + resolution: {integrity: sha512-FNvFGzoMLWmE6Yj9spb/zjd7yiNCHiAW9/Tg9CXrQ8wuu32HtlJOwWO11OJafl5FfY3DxTdQ0vj42zU1kvv5jg==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + form-data@4.0.6: + resolution: {integrity: sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==} + engines: {node: '>= 6'} + + fs-extra@11.4.0: + resolution: {integrity: sha512-EQsFzMUJkCKGr1ePqlYADkIUmHW1s3ZXr5Yqy6wbGrfUCphpl2maM/kyOIRA2HpP3AaFQTZXD4ldjek+nccddA==} + engines: {node: '>=14.14'} + fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-east-asian-width@1.7.0: + resolution: {integrity: sha512-XjH1AECxf0giL2V1aU8vKyRR2ppRUb5c0EvT7zuJTokQ74bNo52zOtghqdWIqrhUD79fo3x0WfKZdOqxF6LG1Q==} + engines: {node: '>=18'} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + get-uri@8.0.1: + resolution: {integrity: sha512-/5N/P4Lrh0p/mDwlDRi7Y1+P2o/OyzZI3l6Iz1Ov6XXwwm1y3RlZLuo3gVgML99djrEDtV980bBxSuOeHLk8ww==} + engines: {node: '>= 20'} + + glob@13.0.6: + resolution: {integrity: sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==} + engines: {node: 18 || 20 || >=22} + + gopd@1.2.0: + 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==} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hasown@2.0.4: + resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} + engines: {node: '>= 0.4'} + html-encoding-sniffer@4.0.0: resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} engines: {node: '>=18'} @@ -784,21 +1132,48 @@ packages: resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} engines: {node: '>= 14'} + http-proxy-agent@9.1.0: + resolution: {integrity: sha512-2NxoveTT58mjYT4n3RPTEfCZGLMbidoO8XEieXfpSYxu+PQJ1qpx4ypwH6N+uF9twBPIvRRgvkvW5HUTYWENig==} + engines: {node: '>= 20'} + + https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + https-proxy-agent@7.0.6: resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} engines: {node: '>= 14'} + https-proxy-agent@9.1.0: + resolution: {integrity: sha512-ag87y7cJJ9/3+GxFr8Oy4O5faDsGRGnBGsJj/YjOSsSx/5eadKLYTMPlzuR6obgoCDDm0abAAZitXXQkMOPSpA==} + engines: {node: '>= 20'} + iconv-lite@0.6.3: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + index-to-position@1.2.0: resolution: {integrity: sha512-Yg7+ztRkqslMAS2iFaU+Oa4KTSidr63OsFGlOrJoW981kIYO3CGCS3wA95P1mUi/IVSJkn0D479KTJpVpvFNuw==} engines: {node: '>=18'} + ip-address@10.7.4: + resolution: {integrity: sha512-DWBMKyeM25D70nrIiTkgQth59/G+naKOTep6huF9j+GmeK3DMD60Zvxg5d5qQnz+38AHgou6ean2LECX+lrKDg==} + engines: {node: '>= 12'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + is-potential-custom-element-name@1.0.1: resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + iterare@1.2.1: + resolution: {integrity: sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q==} + engines: {node: '>=6'} + js-levenshtein@1.1.6: resolution: {integrity: sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==} engines: {node: '>=0.10.0'} @@ -822,6 +1197,9 @@ packages: json-schema-traverse@1.0.0: resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + jsonfile@6.2.1: + resolution: {integrity: sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==} + lightningcss-android-arm64@1.33.0: resolution: {integrity: sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==} engines: {node: '>= 12.0.0'} @@ -896,9 +1274,21 @@ packages: resolution: {integrity: sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==} engines: {node: '>= 12.0.0'} + load-esm@1.0.3: + resolution: {integrity: sha512-v5xlu8eHD1+6r8EHTg6hfmO97LN8ugKtiXcy5e6oN72iD2r6u0RPfLl6fxM+7Wnh2ZRq15o0russMst44WauPA==} + engines: {node: '>=13.2.0'} + lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + lru-cache@11.5.3: + resolution: {integrity: sha512-U4N8FgzmWxc8k1VH8Kr6lQg18U7Fjvby6wXHVRX/ZZ7IwWbRMgrRbP0Wrb5q5NVinryp4SQampHKdvtecItxUg==} + engines: {node: 20 || >=22} + + lru-cache@7.14.1: + resolution: {integrity: sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==} + engines: {node: '>=12'} + lz-string@1.5.0: resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} hasBin: true @@ -906,18 +1296,55 @@ packages: magic-string@1.4.1: resolution: {integrity: sha512-8lyCu36ErXR0J9uaGKlKQoiLZKmtI63YGLE8G2o9jyRPdr4X47LusSOwgOJOzcVtp81fTAAjxR7BwKz682Jhow==} + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + minimatch@10.2.6: + resolution: {integrity: sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==} + engines: {node: 18 || 20 || >=22} + minimatch@5.1.9: resolution: {integrity: sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==} engines: {node: '>=10'} + minipass@7.1.3: + resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} + engines: {node: '>=16 || 14 >=14.17'} + ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - nanoid@3.3.20: - resolution: {integrity: sha512-uKdg2G3GNCKQn9byYOpxbGqrT2fGO5KRt5J/8b3pok8rT6qxGWF6hxMyJiEYtAf+FVyYuD9hRaDqX5uPFYJ4ZQ==} + mute-stream@1.0.0: + resolution: {integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + nanoid@3.3.19: + resolution: {integrity: sha512-Y2tUNy4ouw6tq5oDSKeQYGOyhkUBhNOcGV/02KC+6kd9eDGqdZd++mjMiIDilrBYvjEnCYvVtsuHCuP+okSfug==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + netmask@2.1.1: + resolution: {integrity: sha512-eonl3sLUha+S1GzTPxychyhnUzKyeQkZ7jLjKrBagJgPla13F+uQ71HgpFefyHgqrjEbCPkDArxYsjY8/+gLKA==} + engines: {node: '>= 0.4.0'} + + node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + nwsapi@2.2.27: resolution: {integrity: sha512-gQPNF78qebCQ6tvVFBYrvJdBNOrYZm90ZlXgpIFm06p6qHDHq/XC4TnJftN6OMbxVE0UTBAoRgcsDeJBBooITw==} @@ -944,6 +1371,16 @@ packages: vite-plus: optional: true + pac-proxy-agent@9.1.0: + resolution: {integrity: sha512-1aU+1mpj3DrQPfo3gh+3Gap3G5x+axnMx1P/y0ZF2ch7kb2meyOCAH8K2k9d27ROsTE7TnAerzxqF9aon2jqnA==} + engines: {node: '>= 20'} + + pac-resolver@9.0.1: + resolution: {integrity: sha512-lJbS008tmkj08VhoM8Hzuv/VE5tK9MS0OIQ/7+s0lIF+BYhiQWFYzkSpML7lXs9iBu2jfmzBTLzhe9n6BX+dYw==} + engines: {node: '>= 20'} + peerDependencies: + quickjs-wasi: ^2.2.0 + parse-json@8.3.0: resolution: {integrity: sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==} engines: {node: '>=18'} @@ -951,6 +1388,13 @@ packages: parse5@7.3.0: resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} + path-scurry@2.0.2: + resolution: {integrity: sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==} + engines: {node: 18 || 20 || >=22} + + path-to-regexp@8.4.2: + resolution: {integrity: sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==} + picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -962,8 +1406,8 @@ packages: resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} engines: {node: '>=4'} - postcss@8.5.31: - resolution: {integrity: sha512-YUbWYCgErwnMAVkjUnYa+KlMBzGpHwiIt/DE7f0G33AuX2LH9UcTk6KgWxd3zRU+pN3u/C+Xl3EnMLM4Hea7Sg==} + postcss@8.5.28: + resolution: {integrity: sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A==} engines: {node: ^10 || ^12 || >=14} prettier@3.6.2: @@ -975,10 +1419,30 @@ packages: resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + proxy-agent-negotiate@1.1.0: + resolution: {integrity: sha512-N8IBcM3UgCVzz2L2Lqv8DVntDnnC8/hiV4nEDUPkqq72TPUgYWjQc+bdZlBPZK9LzPAvOY//gAt0S0DApoOXWQ==} + engines: {node: '>= 20'} + peerDependencies: + kerberos: ^2.0.0 + peerDependenciesMeta: + kerberos: + optional: true + + proxy-agent@8.0.2: + resolution: {integrity: sha512-idLLRewuemWd7GH/BDJzGiB0dWGfT2SQs3jy6NtZtGWU9uPTTSdeC1/cdbqLwgzhfv027daGFuXX426e2Eg20A==} + engines: {node: '>= 20'} + + proxy-from-env@2.1.0: + resolution: {integrity: sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==} + engines: {node: '>=10'} + punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} + quickjs-wasi@2.2.0: + resolution: {integrity: sha512-zQxXmQMrEoD3S+jQdYsloq4qAuaxKFHZj6hHqOYGwB2iQZH+q9e/lf5zQPXCKOk0WJuAjzRFbO4KwHIp2D05Iw==} + react-dom@19.2.8: resolution: {integrity: sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==} peerDependencies: @@ -991,6 +1455,9 @@ packages: resolution: {integrity: sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw==} engines: {node: '>=0.10.0'} + reflect-metadata@0.2.2: + resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==} + require-from-string@2.0.2: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} @@ -1003,6 +1470,13 @@ packages: rrweb-cssom@0.8.0: resolution: {integrity: sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==} + run-async@3.0.0: + resolution: {integrity: sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==} + engines: {node: '>=0.12.0'} + + rxjs@7.8.2: + resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==} + safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} @@ -1022,23 +1496,75 @@ packages: resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + shell-quote@1.12.0: + resolution: {integrity: sha512-PcByqNyT/38F2kDNi006HAMRJaULuBzq/FOsw3qdZvX/GA9W/jamDaRskgHjubHiftXK5sIFxLNkvrXUwcof6Q==} + engines: {node: '>= 0.4'} + siginfo@2.0.0: resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + smart-buffer@4.2.0: + resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} + engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} + + socks-proxy-agent@10.1.0: + resolution: {integrity: sha512-WlMj/67cEJ6MDI1OcsnjuYKDNDoyPCCYZ249kuuXPiMDw9F8PXkVaQ7YWu3siTydfQ/4BEZcvGzu+aYvz7dDCQ==} + engines: {node: '>= 20'} + + socks@2.8.10: + resolution: {integrity: sha512-e0VyvkVTwVYViNovRkZ9aodhxVlyoMn7eJhVUPxZ+eK9P/7CBkxvvsBOHqFPEH416726W8tLXXXjKwqgTErrCQ==} + engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} + source-map-js@1.2.2: resolution: {integrity: sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==} engines: {node: '>=0.10.0'} + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} std-env@4.2.0: resolution: {integrity: sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==} + string-width@4.1.0: + resolution: {integrity: sha512-NrX+1dVVh+6Y9dnQ19pR0pP4FiEIlUvdTGn8pw6CKTNq5sgib2nIhmUNT5TAmhWmvKr3WcxBcP3E8nWezuipuQ==} + engines: {node: '>=8'} + + string-width@7.2.0: + resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} + engines: {node: '>=18'} + + strip-ansi@5.2.0: + resolution: {integrity: sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==} + engines: {node: '>=6'} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.2.0: + resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} + engines: {node: '>=12'} + + strtok3@10.6.2: + resolution: {integrity: sha512-BkdixFFUt7r7LsX6aGNPVyYMLjW+M1USLlKPNbZsrZEmLFh5tGqhdfckKo6xgsZIJqdDD0CZGkeCJJwNWQIKQA==} + engines: {node: '>=18'} + supports-color@10.2.2: resolution: {integrity: sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==} engines: {node: '>=18'} + supports-color@7.1.0: + resolution: {integrity: sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==} + engines: {node: '>=8'} + symbol-tree@3.2.4: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} @@ -1061,17 +1587,32 @@ packages: resolution: {integrity: sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==} hasBin: true + token-types@6.1.2: + resolution: {integrity: sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww==} + engines: {node: '>=14.16'} + tough-cookie@5.1.2: resolution: {integrity: sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==} engines: {node: '>=16'} + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + tr46@5.1.1: resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==} engines: {node: '>=18'} + tree-kill@1.2.2: + resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} + hasBin: true + tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + type-fest@4.41.0: resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} engines: {node: '>=16'} @@ -1081,9 +1622,24 @@ packages: engines: {node: '>=14.17'} hasBin: true + uid@2.0.2: + resolution: {integrity: sha512-u3xV3X7uzvi5b1MncmZo3i2Aw222Zk1keqLA1YkHldREkAhAqi65wuPfe7lHx8H/Wzy+8CE7S7uS3jekIM5s8g==} + engines: {node: '>=8'} + + uint8array-extras@1.6.0: + resolution: {integrity: sha512-8iAasVS4wUx0gPLjH8Xtz2PeDzTSiy8QiLGu2DT3X5GU+egFEQhpnbtkehbAwjvDcxIERmCYcysiODFmE3Ud0Q==} + engines: {node: '>=18'} + + undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + undici-types@8.3.0: resolution: {integrity: sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==} + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + uri-js-replace@1.0.1: resolution: {integrity: sha512-W+C9NWNLFOoBI2QWDp4UT9pv65r2w5Cx+3sTYFvtMdDBxkKt1syCqsUdSFAChbEe1uK5TfS04wt/nGwmaeIQ0g==} @@ -1175,6 +1731,12 @@ packages: resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} engines: {node: '>=18'} + wcwidth@1.0.1: + resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + + webidl-conversions@3.0.0: + resolution: {integrity: sha512-GOK494qXZl0XBbr/YPRW2BL6oLfe+d0KDSWndKH7NdxJwJ0fCdhQG46Q2D7BmIS6cN/FJgtju8srRt/jlG9abA==} + webidl-conversions@7.0.0: resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} engines: {node: '>=12'} @@ -1192,11 +1754,22 @@ packages: resolution: {integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==} engines: {node: '>=18'} + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + why-is-node-running@2.3.0: resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} engines: {node: '>=8'} hasBin: true + wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + + wrap-ansi@9.0.0: + resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} + engines: {node: '>=18'} + ws@8.21.3: resolution: {integrity: sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==} engines: {node: '>=10.0.0'} @@ -1216,6 +1789,10 @@ packages: xmlchars@2.2.0: resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + yaml-ast-parser@0.0.43: resolution: {integrity: sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A==} @@ -1228,6 +1805,14 @@ packages: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} + yargs-parser@22.0.0: + resolution: {integrity: sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==} + engines: {node: ^20.19.0 || ^22.12.0 || >=23} + + yargs@18.0.0: + resolution: {integrity: sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==} + engines: {node: ^20.19.0 || ^22.12.0 || >=23} + snapshots: '@asamuzakjp/css-color@3.2.0': @@ -1248,6 +1833,8 @@ snapshots: '@babel/runtime@7.29.7': {} + '@borewit/text-codec@0.2.2': {} + '@csstools/color-helpers@5.1.0': {} '@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': @@ -1369,6 +1956,33 @@ snapshots: '@img/sharp-win32-x64@0.34.5': optional: true + '@inquirer/core@6.0.0': + dependencies: + '@inquirer/type': 1.1.6 + '@types/mute-stream': 0.0.4 + '@types/node': 20.19.43 + '@types/wrap-ansi': 3.0.0 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + cli-spinners: 2.9.2 + cli-width: 4.1.0 + figures: 3.2.0 + mute-stream: 1.0.0 + run-async: 3.0.0 + signal-exit: 4.1.0 + strip-ansi: 6.0.1 + wrap-ansi: 6.2.0 + + '@inquirer/select@1.3.3': + dependencies: + '@inquirer/core': 6.0.0 + '@inquirer/type': 1.1.6 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + figures: 3.2.0 + + '@inquirer/type@1.1.6': {} + '@jridgewell/resolve-uri@3.1.2': {} '@jridgewell/sourcemap-codec@1.6.0': {} @@ -1378,6 +1992,75 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.6.0 + '@lukeed/csprng@1.1.0': {} + + '@nestjs/axios@4.0.1(@nestjs/common@11.2.1(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(axios@1.20.0(supports-color@10.2.2))(rxjs@7.8.2)': + dependencies: + '@nestjs/common': 11.2.1(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) + axios: 1.20.0(supports-color@10.2.2) + rxjs: 7.8.2 + + '@nestjs/common@11.2.1(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2)': + dependencies: + file-type: 21.3.4(supports-color@10.2.2) + iterare: 1.2.1 + load-esm: 1.0.3 + reflect-metadata: 0.2.2 + rxjs: 7.8.2 + tslib: 2.8.1 + uid: 2.0.2 + transitivePeerDependencies: + - supports-color + + '@nestjs/core@11.2.1(@nestjs/common@11.2.1(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(reflect-metadata@0.2.2)(rxjs@7.8.2)': + dependencies: + '@nestjs/common': 11.2.1(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) + fast-safe-stringify: 2.1.1 + iterare: 1.2.1 + path-to-regexp: 8.4.2 + reflect-metadata: 0.2.2 + rxjs: 7.8.2 + tslib: 2.8.1 + uid: 2.0.2 + + '@nuxtjs/opencollective@0.3.2': + dependencies: + chalk: 4.1.2 + consola: 2.15.3 + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + + '@openapitools/openapi-generator-cli@2.41.0(supports-color@10.2.2)': + dependencies: + '@inquirer/select': 1.3.3 + '@nestjs/axios': 4.0.1(@nestjs/common@11.2.1(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(axios@1.20.0(supports-color@10.2.2))(rxjs@7.8.2) + '@nestjs/common': 11.2.1(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) + '@nestjs/core': 11.2.1(@nestjs/common@11.2.1(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nuxtjs/opencollective': 0.3.2 + axios: 1.20.0(supports-color@10.2.2) + chalk: 4.1.2 + commander: 8.3.0 + compare-versions: 6.1.1 + concurrently: 10.0.6 + console.table: 0.10.0 + fs-extra: 11.4.0 + glob: 13.0.6 + proxy-agent: 8.0.2(supports-color@10.2.2) + reflect-metadata: 0.2.2 + rxjs: 7.8.2 + tslib: 2.8.1 + transitivePeerDependencies: + - '@nestjs/microservices' + - '@nestjs/platform-express' + - '@nestjs/websockets' + - class-transformer + - class-validator + - debug + - encoding + - kerberos + - supports-color + '@oxc-project/types@0.154.0': {} '@oxlint/binding-android-arm-eabi@1.80.0': @@ -1581,6 +2264,15 @@ snapshots: dependencies: '@testing-library/dom': 10.4.2 + '@tokenizer/inflate@0.4.1(supports-color@10.2.2)': + dependencies: + debug: 4.4.3(supports-color@10.2.2) + token-types: 6.1.2 + transitivePeerDependencies: + - supports-color + + '@tokenizer/token@0.3.0': {} + '@types/aria-query@5.0.4': {} '@types/chai@5.2.3': @@ -1592,6 +2284,14 @@ snapshots: '@types/estree@1.0.9': {} + '@types/mute-stream@0.0.4': + dependencies: + '@types/node': 26.3.0 + + '@types/node@20.19.43': + dependencies: + undici-types: 6.21.0 + '@types/node@26.3.0': dependencies: undici-types: 8.3.0 @@ -1604,6 +2304,8 @@ snapshots: dependencies: csstype: 3.2.3 + '@types/wrap-ansi@3.0.0': {} + '@vitejs/plugin-react@6.1.1(vite@8.3.3(@types/node@26.3.0)(yaml@2.9.0))': dependencies: '@rolldown/pluginutils': 1.0.1 @@ -1620,14 +2322,40 @@ snapshots: '@vitest/spy@5.0.1': {} + agent-base@6.0.0(supports-color@10.2.2): + dependencies: + debug: 4.4.3(supports-color@10.2.2) + transitivePeerDependencies: + - supports-color + agent-base@7.1.4: {} + agent-base@9.0.0: {} + ansi-colors@4.1.3: {} + ansi-escapes@4.3.2: + dependencies: + type-fest: 0.21.3 + + ansi-regex@4.1.0: {} + ansi-regex@5.0.1: {} + ansi-regex@6.4.0: {} + + ansi-styles@4.0.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@4.1.0: + dependencies: + color-convert: 2.0.1 + ansi-styles@5.2.0: {} + ansi-styles@6.2.1: {} + argparse@2.0.1: {} aria-query@5.3.0: @@ -1636,18 +2364,96 @@ snapshots: assertion-error@2.0.1: {} + ast-types@0.13.4: + dependencies: + tslib: 2.8.1 + + asynckit@0.4.0: {} + + axios@1.20.0(supports-color@10.2.2): + dependencies: + follow-redirects: 1.16.1 + form-data: 4.0.6 + https-proxy-agent: 5.0.1(supports-color@10.2.2) + proxy-from-env: 2.1.0 + transitivePeerDependencies: + - debug + - supports-color + balanced-match@1.0.2: {} + balanced-match@4.0.4: {} + + basic-ftp@5.3.1: {} + brace-expansion@2.1.7: dependencies: balanced-match: 1.0.2 + brace-expansion@5.0.12: + dependencies: + balanced-match: 4.0.4 + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + chai@6.2.2: {} + chalk@4.1.2: + dependencies: + ansi-styles: 4.1.0 + supports-color: 7.1.0 + + chalk@5.6.2: {} + change-case@5.4.4: {} + cli-spinners@2.9.2: {} + + cli-width@4.1.0: {} + + cliui@9.0.1: + dependencies: + string-width: 7.2.0 + strip-ansi: 7.2.0 + wrap-ansi: 9.0.0 + + clone@1.0.4: + optional: true + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + colorette@1.4.0: {} + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + commander@8.3.0: {} + + compare-versions@6.1.1: {} + + concurrently@10.0.6: + dependencies: + chalk: 5.6.2 + rxjs: 7.8.2 + shell-quote: 1.12.0 + supports-color: 10.2.2 + tree-kill: 1.2.2 + yargs: 18.0.0 + + consola@2.15.3: {} + + console.table@0.10.0: + dependencies: + easy-table: 1.1.0 + cssstyle@4.6.0: dependencies: '@asamuzakjp/css-color': 3.2.0 @@ -1655,6 +2461,8 @@ snapshots: csstype@3.2.3: {} + data-uri-to-buffer@8.0.0: {} + data-urls@5.0.0: dependencies: whatwg-mimetype: 4.0.0 @@ -1668,31 +2476,177 @@ snapshots: decimal.js@10.6.0: {} + defaults@1.0.4: + dependencies: + clone: 1.0.4 + optional: true + + degenerator@7.0.1(quickjs-wasi@2.2.0): + dependencies: + ast-types: 0.13.4 + escodegen: 2.1.0 + esprima: 4.0.1 + quickjs-wasi: 2.2.0 + + delayed-stream@1.0.0: {} + dequal@2.0.3: {} detect-libc@2.1.2: {} dom-accessibility-api@0.5.16: {} + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + easy-table@1.1.0: + optionalDependencies: + wcwidth: 1.0.1 + + emoji-regex@10.3.0: {} + + emoji-regex@8.0.0: {} + entities@6.0.1: {} + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + es-module-lexer@2.3.2: {} + es-object-atoms@1.1.2: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.4 + + escalade@3.2.0: {} + + escape-string-regexp@1.0.5: {} + + escodegen@2.1.0: + dependencies: + esprima: 4.0.1 + estraverse: 5.3.0 + esutils: 2.0.3 + optionalDependencies: + source-map: 0.6.1 + + esprima@4.0.1: {} + + estraverse@5.3.0: {} + estree-walker@3.0.3: dependencies: '@types/estree': 1.0.9 + esutils@2.0.3: {} + expect-type@1.4.0: {} fast-deep-equal@3.1.3: {} + fast-safe-stringify@2.1.1: {} + fdir@6.5.0(picomatch@4.0.7): optionalDependencies: picomatch: 4.0.7 + figures@3.2.0: + dependencies: + escape-string-regexp: 1.0.5 + + file-type@21.3.4(supports-color@10.2.2): + dependencies: + '@tokenizer/inflate': 0.4.1(supports-color@10.2.2) + strtok3: 10.6.2 + token-types: 6.1.2 + uint8array-extras: 1.6.0 + transitivePeerDependencies: + - supports-color + + follow-redirects@1.16.1: {} + + form-data@4.0.6: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.4 + mime-types: 2.1.35 + + fs-extra@11.4.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.2.1 + universalify: 2.0.1 + fsevents@2.3.3: optional: true + function-bind@1.1.2: {} + + get-caller-file@2.0.5: {} + + get-east-asian-width@1.7.0: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.4 + math-intrinsics: 1.1.0 + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.2 + + get-uri@8.0.1(supports-color@10.2.2): + dependencies: + basic-ftp: 5.3.1 + data-uri-to-buffer: 8.0.0 + debug: 4.4.3(supports-color@10.2.2) + transitivePeerDependencies: + - supports-color + + glob@13.0.6: + dependencies: + minimatch: 10.2.6 + minipass: 7.1.3 + path-scurry: 2.0.2 + + gopd@1.2.0: {} + + graceful-fs@4.2.11: {} + + has-flag@4.0.0: {} + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hasown@2.0.4: + dependencies: + function-bind: 1.1.2 + html-encoding-sniffer@4.0.0: dependencies: whatwg-encoding: 3.1.1 @@ -1704,6 +2658,22 @@ snapshots: transitivePeerDependencies: - supports-color + http-proxy-agent@9.1.0(supports-color@10.2.2): + dependencies: + agent-base: 9.0.0 + debug: 4.4.3(supports-color@10.2.2) + proxy-agent-negotiate: 1.1.0 + transitivePeerDependencies: + - kerberos + - supports-color + + https-proxy-agent@5.0.1(supports-color@10.2.2): + dependencies: + agent-base: 6.0.0(supports-color@10.2.2) + debug: 4.4.3(supports-color@10.2.2) + transitivePeerDependencies: + - supports-color + https-proxy-agent@7.0.6(supports-color@10.2.2): dependencies: agent-base: 7.1.4 @@ -1711,14 +2681,31 @@ snapshots: transitivePeerDependencies: - supports-color + https-proxy-agent@9.1.0(supports-color@10.2.2): + dependencies: + agent-base: 9.0.0 + debug: 4.4.3(supports-color@10.2.2) + proxy-agent-negotiate: 1.1.0 + transitivePeerDependencies: + - kerberos + - supports-color + iconv-lite@0.6.3: dependencies: safer-buffer: 2.1.2 + ieee754@1.2.1: {} + index-to-position@1.2.0: {} + ip-address@10.7.4: {} + + is-fullwidth-code-point@3.0.0: {} + is-potential-custom-element-name@1.0.1: {} + iterare@1.2.1: {} + js-levenshtein@1.1.6: {} js-tokens@4.0.0: {} @@ -1756,6 +2743,12 @@ snapshots: json-schema-traverse@1.0.0: {} + jsonfile@6.2.1: + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + lightningcss-android-arm64@1.33.0: optional: true @@ -1805,21 +2798,49 @@ snapshots: lightningcss-win32-arm64-msvc: 1.33.0 lightningcss-win32-x64-msvc: 1.33.0 + load-esm@1.0.3: {} + lru-cache@10.4.3: {} + lru-cache@11.5.3: {} + + lru-cache@7.14.1: {} + lz-string@1.5.0: {} magic-string@1.4.1: dependencies: '@jridgewell/sourcemap-codec': 1.6.0 + math-intrinsics@1.1.0: {} + + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + minimatch@10.2.6: + dependencies: + brace-expansion: 5.0.12 + minimatch@5.1.9: dependencies: brace-expansion: 2.1.7 + minipass@7.1.3: {} + ms@2.1.3: {} - nanoid@3.3.20: {} + mute-stream@1.0.0: {} + + nanoid@3.3.19: {} + + netmask@2.1.1: {} + + node-fetch@2.7.0: + dependencies: + whatwg-url: 5.0.0 nwsapi@2.2.27: {} @@ -1857,6 +2878,26 @@ snapshots: '@oxlint/binding-win32-ia32-msvc': 1.80.0 '@oxlint/binding-win32-x64-msvc': 1.80.0 + pac-proxy-agent@9.1.0(supports-color@10.2.2): + dependencies: + agent-base: 9.0.0 + debug: 4.4.3(supports-color@10.2.2) + get-uri: 8.0.1(supports-color@10.2.2) + http-proxy-agent: 9.1.0(supports-color@10.2.2) + https-proxy-agent: 9.1.0(supports-color@10.2.2) + pac-resolver: 9.0.1(quickjs-wasi@2.2.0) + quickjs-wasi: 2.2.0 + socks-proxy-agent: 10.1.0 + transitivePeerDependencies: + - kerberos + - supports-color + + pac-resolver@9.0.1(quickjs-wasi@2.2.0): + dependencies: + degenerator: 7.0.1(quickjs-wasi@2.2.0) + netmask: 2.1.1 + quickjs-wasi: 2.2.0 + parse-json@8.3.0: dependencies: '@babel/code-frame': 7.29.7 @@ -1867,15 +2908,22 @@ snapshots: dependencies: entities: 6.0.1 + path-scurry@2.0.2: + dependencies: + lru-cache: 11.5.3 + minipass: 7.1.3 + + path-to-regexp@8.4.2: {} + picocolors@1.1.1: {} picomatch@4.0.7: {} pluralize@8.0.0: {} - postcss@8.5.31: + postcss@8.5.28: dependencies: - nanoid: 3.3.20 + nanoid: 3.3.19 picocolors: 1.1.1 source-map-js: 1.2.2 @@ -1887,8 +2935,28 @@ snapshots: ansi-styles: 5.2.0 react-is: 17.0.2 + proxy-agent-negotiate@1.1.0: {} + + proxy-agent@8.0.2(supports-color@10.2.2): + dependencies: + agent-base: 9.0.0 + debug: 4.4.3(supports-color@10.2.2) + http-proxy-agent: 9.1.0(supports-color@10.2.2) + https-proxy-agent: 9.1.0(supports-color@10.2.2) + lru-cache: 7.14.1 + pac-proxy-agent: 9.1.0(supports-color@10.2.2) + proxy-from-env: 2.1.0 + socks-proxy-agent: 10.1.0 + transitivePeerDependencies: + - kerberos + - supports-color + + proxy-from-env@2.1.0: {} + punycode@2.3.1: {} + quickjs-wasi@2.2.0: {} + react-dom@19.2.8(react@19.2.8): dependencies: react: 19.2.8 @@ -1898,6 +2966,8 @@ snapshots: react@19.2.8: {} + reflect-metadata@0.2.2: {} + require-from-string@2.0.2: {} rolldown@1.2.14: @@ -1923,6 +2993,12 @@ snapshots: rrweb-cssom@0.8.0: {} + run-async@3.0.0: {} + + rxjs@7.8.2: + dependencies: + tslib: 2.8.1 + safer-buffer@2.1.2: {} saxes@6.0.0: @@ -1964,16 +3040,70 @@ snapshots: '@img/sharp-win32-ia32': 0.34.5 '@img/sharp-win32-x64': 0.34.5 + shell-quote@1.12.0: {} + siginfo@2.0.0: {} + signal-exit@4.1.0: {} + + smart-buffer@4.2.0: {} + + socks-proxy-agent@10.1.0: + dependencies: + agent-base: 9.0.0 + debug: 4.4.3(supports-color@10.2.2) + socks: 2.8.10 + transitivePeerDependencies: + - supports-color + + socks@2.8.10: + dependencies: + ip-address: 10.7.4 + smart-buffer: 4.2.0 + source-map-js@1.2.2: {} + source-map@0.6.1: + optional: true + stackback@0.0.2: {} std-env@4.2.0: {} + string-width@4.1.0: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 5.2.0 + + string-width@7.2.0: + dependencies: + emoji-regex: 10.3.0 + get-east-asian-width: 1.7.0 + strip-ansi: 7.2.0 + + strip-ansi@5.2.0: + dependencies: + ansi-regex: 4.1.0 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.2.0: + dependencies: + ansi-regex: 6.4.0 + + strtok3@10.6.2: + dependencies: + '@tokenizer/token': 0.3.0 + supports-color@10.2.2: {} + supports-color@7.1.0: + dependencies: + has-flag: 4.0.0 + symbol-tree@3.2.4: {} tinybench@6.1.4: {} @@ -1991,30 +3121,51 @@ snapshots: dependencies: tldts-core: 6.1.86 + token-types@6.1.2: + dependencies: + '@borewit/text-codec': 0.2.2 + '@tokenizer/token': 0.3.0 + ieee754: 1.2.1 + tough-cookie@5.1.2: dependencies: tldts: 6.1.86 + tr46@0.0.3: {} + tr46@5.1.1: dependencies: punycode: 2.3.1 - tslib@2.8.1: - optional: true + tree-kill@1.2.2: {} + + tslib@2.8.1: {} + + type-fest@0.21.3: {} type-fest@4.41.0: {} typescript@5.9.3: {} + uid@2.0.2: + dependencies: + '@lukeed/csprng': 1.1.0 + + uint8array-extras@1.6.0: {} + + undici-types@6.21.0: {} + undici-types@8.3.0: {} + universalify@2.0.1: {} + uri-js-replace@1.0.1: {} vite@8.3.3(@types/node@26.3.0)(yaml@2.9.0): dependencies: lightningcss: 1.33.0 picomatch: 4.0.7 - postcss: 8.5.31 + postcss: 8.5.28 rolldown: 1.2.14 tinyglobby: 0.2.17 optionalDependencies: @@ -2048,6 +3199,13 @@ snapshots: dependencies: xml-name-validator: 5.0.0 + wcwidth@1.0.1: + dependencies: + defaults: 1.0.4 + optional: true + + webidl-conversions@3.0.0: {} + webidl-conversions@7.0.0: {} whatwg-encoding@3.1.1: @@ -2061,19 +3219,49 @@ snapshots: tr46: 5.1.1 webidl-conversions: 7.0.0 + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.0 + why-is-node-running@2.3.0: dependencies: siginfo: 2.0.0 stackback: 0.0.2 + wrap-ansi@6.2.0: + dependencies: + ansi-styles: 4.0.0 + string-width: 4.1.0 + strip-ansi: 6.0.1 + + wrap-ansi@9.0.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 7.2.0 + strip-ansi: 7.2.0 + ws@8.21.3: {} xml-name-validator@5.0.0: {} xmlchars@2.2.0: {} + y18n@5.0.8: {} + yaml-ast-parser@0.0.43: {} yaml@2.9.0: {} yargs-parser@21.1.1: {} + + yargs-parser@22.0.0: {} + + yargs@18.0.0: + dependencies: + cliui: 9.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + string-width: 7.2.0 + y18n: 5.0.8 + yargs-parser: 22.0.0 diff --git a/desktop/pnpm-workspace.yaml b/desktop/pnpm-workspace.yaml index 6aebbe802f..c59683dd55 100644 --- a/desktop/pnpm-workspace.yaml +++ b/desktop/pnpm-workspace.yaml @@ -13,4 +13,5 @@ # limitations under the License. allowBuilds: + '@openapitools/openapi-generator-cli': true sharp: true diff --git a/desktop/scripts/generate.mjs b/desktop/scripts/generate.mjs index aa90199fd8..9e055311af 100644 --- a/desktop/scripts/generate.mjs +++ b/desktop/scripts/generate.mjs @@ -14,8 +14,11 @@ * limitations under the License. */ -import { readFile, writeFile, mkdir } from "node:fs/promises"; +import { readFile, writeFile, mkdir, mkdtemp, rm } from "node:fs/promises"; import { createHash } from "node:crypto"; +import { spawn } from "node:child_process"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; import { fileURLToPath } from "node:url"; import YAML from "yaml"; import openapiTS, { astToString } from "openapi-typescript"; @@ -71,84 +74,135 @@ function collectSchemas(value) { for (const item of Object.values(contract.paths)) for (const op of Object.values(item)) if (wanted.includes(op?.operationId)) collectSchemas(op); -function rustType(schema) { - if (schema.$ref) return schema.$ref.split("/").at(-1); - // A single-member allOf is how the contract annotates a nullable or described reference. - if (schema.allOf?.length === 1) return rustType(schema.allOf[0]); - switch (schema.type) { - case "string": - return "String"; - case "integer": - return "i64"; - case "number": - return "f64"; - case "boolean": - return "bool"; - case "array": - return `Vec<${rustType(schema.items)}>`; - case "object": - if (schema.additionalProperties === true) return "serde_json::Value"; - if ( - schema.additionalProperties && - typeof schema.additionalProperties === "object" - ) - return `std::collections::BTreeMap`; - throw new Error("Unsupported inline object in Desktop wire model"); - default: - throw new Error(`Unsupported wire schema ${JSON.stringify(schema)}`); - } +function snakeCase(name) { + return name + .replace(/([a-z0-9])([A-Z])/g, "$1_$2") + .replace(/([A-Z])([A-Z][a-z])/g, "$1_$2") + .toLowerCase(); } -const rustModels = [...schemaNames] - .sort() - .map((name) => { - const schema = contract.components.schemas[name]; - const derive = - "#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize, ts_rs::TS)]"; - if (schema.$ref) return `pub type ${name} = ${rustType(schema)};\n`; - if (schema.enum) { - const values = schema.enum.filter((v) => v !== null); - const members = values.map( - (value) => - ` #[serde(rename = ${JSON.stringify(value)})]\n ${value - .split(/[^a-zA-Z0-9]+/) - .map((part) => part[0].toUpperCase() + part.slice(1)) - .join("")},`, +function run(command, args, cwd) { + return new Promise((resolve, reject) => { + const useWindowsCmd = process.platform === "win32" && command === "pnpm"; + const executable = useWindowsCmd + ? (process.env.ComSpec ?? "cmd.exe") + : command; + const executableArgs = useWindowsCmd + ? ["/d", "/s", "/c", command, ...args] + : args; + const child = spawn(executable, executableArgs, { + cwd, + stdio: ["ignore", "pipe", "pipe"], + }); + let stdout = ""; + let stderr = ""; + child.stdout.on("data", (chunk) => (stdout += chunk)); + child.stderr.on("data", (chunk) => (stderr += chunk)); + child.on("error", reject); + child.on("close", (code) => + code === 0 + ? resolve(stdout) + : reject( + new Error( + `${command} ${args.join(" ")} failed (${code})\n${stdout}\n${stderr}`, + ), + ), + ); + }); +} +async function generateRustModels() { + const temporary = await mkdtemp( + join(tmpdir(), "powercontext-desktop-openapi-"), + ); + const output = join(temporary, "generated"); + const modelNames = [...schemaNames].sort(); + const pnpm = "pnpm"; + try { + await run( + pnpm, + [ + "exec", + "openapi-generator-cli", + "generate", + "-i", + fileURLToPath(contractUrl), + "-g", + "rust", + "-t", + fileURLToPath(new URL("./openapi-generator/rust/", import.meta.url)), + "-o", + output, + "--global-property", + `models=${modelNames.join(":")},modelDocs=false,modelTests=false`, + "--additional-properties", + "packageName=powercontext_wire,packageVersion=0.1.0,hideGenerationTimestamp=true,useChrono=false,avoidBoxedModels=true", + ], + fileURLToPath(root), + ); + const imports = new Set(); + const sources = []; + for (const name of modelNames) { + const source = await readFile( + join(output, "src", "models", `${snakeCase(name)}.rs`), + "utf8", ); - return `${derive}\npub enum ${name} {\n${members.join("\n")}\n}\n`; + sources.push({ name, source }); } - if (schema.oneOf && !schema.type) { - const members = schema.oneOf.map((variant) => { - if (!variant.$ref) throw new Error("Unsupported inline wire union"); - const type = rustType(variant); - return ` ${type}(${type}),`; + const declarationCounts = new Map(); + for (const { source } of sources) { + for (const match of source.matchAll(/pub (?:struct|enum) (\w+)/gu)) { + declarationCounts.set( + match[1], + (declarationCounts.get(match[1]) ?? 0) + 1, + ); + } + } + const bodies = []; + for (const { name, source: originalSource } of sources) { + let source = originalSource; + for (const match of source.matchAll(/pub (?:struct|enum) (\w+)/gu)) { + const declaration = match[1]; + if ( + declarationCounts.get(declaration) > 1 && + !modelNames.includes(declaration) + ) { + const renamed = `${name}${declaration}`; + source = source.replace( + new RegExp(`\\b${declaration}\\b`, "gu"), + renamed, + ); + } + } + let body = source.replace(/^(?:\/\*[\s\S]*?\*\/\s*)+/u, ""); + body = body.replace(/^use crate::models;\s*$/gmu, ""); + body = body.replace(/^use .+;\s*$/gmu, (line) => { + imports.add(line.trim()); + return ""; }); - return `${derive}\n#[serde(untagged)]\npub enum ${name} {\n${members.join("\n")}\n}\n`; + body = body.replaceAll("models::", "").trim(); + bodies.push(body); } - if (schema.type !== "object") - return `pub type ${name} = ${rustType(schema)};\n`; - const fields = Object.entries(schema.properties).map(([field, value]) => { - let type = rustType(value); - if (value.nullable || !schema.required?.includes(field)) - type = `Option<${type}>`; - const opaque = - value.type === "object" && value.additionalProperties === true - ? ' #[ts(type = "Record")]\n' - : ""; - return `${!schema.required?.includes(field) ? ' #[serde(skip_serializing_if = "Option::is_none")]\n #[ts(optional = nullable)]\n' : ""}${opaque} pub r#${field}: ${type},`; - }); - return `${derive}\n#[serde(deny_unknown_fields)]\npub struct ${name} {\n${fields.join("\n")}\n}\n`; - }) - .join("\n"); + const unformatted = + [...imports].sort().join("\n") + "\n\n" + bodies.join("\n\n") + "\n"; + const wirePath = join(temporary, "wire.rs"); + await writeFile(wirePath, unformatted); + await run("rustfmt", ["--edition", "2024", wirePath], fileURLToPath(root)); + return await readFile(wirePath, "utf8"); + } finally { + await rm(temporary, { recursive: true, force: true }); + } +} +const rustModels = await generateRustModels(); +// OpenAPI Generator also emits inline enums and helper models that are not +// component schemas. Include every generated Rust declaration in the ts-rs +// export list so referenced TypeScript names are emitted as well. +const rustModelNames = [ + ...rustModels.matchAll(/pub (?:struct|enum) (\w+)/gu), +].map(([, name]) => name); const rustDeclarations = `\n#[rustfmt::skip]\npub fn declarations(config: &ts_rs::Config) -> Vec {\n vec![\n${[ - ...schemaNames, + ...new Set([...schemaNames, ...rustModelNames]), ] .sort() - .map((name) => { - const schema = contract.components.schemas[name]; - return schema.$ref - ? ` format!("type ${name} = {};", <${rustType(schema)} as ts_rs::TS>::name(config)),` - : ` <${name} as ts_rs::TS>::decl(config),`; - }) + .map((name) => ` <${name} as ts_rs::TS>::decl(config),`) .join("\n")}\n ]\n}\n`; const outputs = { "src-tauri/src/transport/wire.rs": diff --git a/desktop/scripts/openapi-generator/rust/model.mustache b/desktop/scripts/openapi-generator/rust/model.mustache new file mode 100644 index 0000000000..980f6c4939 --- /dev/null +++ b/desktop/scripts/openapi-generator/rust/model.mustache @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2026 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{{>partial_header}} +use crate::models; +use serde::{Deserialize, Serialize}; +use ts_rs::TS; +{{#models}} +{{#model}} +{{^isEnum}}{{#vendorExtensions.x-rust-has-byte-array}} +use serde_with::serde_as; +{{/vendorExtensions.x-rust-has-byte-array}}{{#vendorExtensions.x-rust-has-integer-property-enum}} +use serde_repr::{Serialize_repr,Deserialize_repr}; +{{/vendorExtensions.x-rust-has-integer-property-enum}}{{/isEnum}} +{{#isEnum}} +{{#isInteger}} +use serde_repr::{Serialize_repr,Deserialize_repr}; +{{/isInteger}} +{{/isEnum}} +{{#description}} +/// {{{classname}}} : {{{description}}} +{{/description}} +{{!-- for repr(int) enum schemas --}} +{{#isEnum}} +{{#isInteger}} +/// {{{description}}} +#[repr(i64)] +#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, TS)] +pub enum {{{classname}}} { +{{#allowableValues}} +{{#enumVars}} + {{{name}}} = {{{value}}}, +{{/enumVars}}{{/allowableValues}} +} + +impl std::fmt::Display for {{{classname}}} { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", match self { + {{#allowableValues}} + {{#enumVars}} + Self::{{{name}}} => "{{{value}}}", + {{/enumVars}} + {{/allowableValues}} + }) + } +} +{{/isInteger}} +{{/isEnum}} +{{!-- for enum schemas --}} +{{#isEnum}} +{{^isInteger}} +#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, TS, Default)] +pub enum {{{classname}}} { +{{#allowableValues}} +{{#enumVars}} + #[serde(rename = "{{{value}}}")] + {{#-first}}#[default]{{/-first}} + {{{name}}}, +{{/enumVars}}{{/allowableValues}} +} + +impl std::fmt::Display for {{{classname}}} { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + {{#allowableValues}} + {{#enumVars}} + Self::{{{name}}} => write!(f, "{{{value}}}"), + {{/enumVars}} + {{/allowableValues}} + } + } +} + +{{/isInteger}} +{{/isEnum}} +{{!-- for schemas that have a discriminator --}} +{{#discriminator}} +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, TS)] +#[serde(tag = "{{{propertyBaseName}}}")] +pub enum {{{classname}}} { + {{^oneOf}} + {{#mappedModels}} + #[serde(rename="{{mappingName}}")] + {{^vendorExtensions.x-rust-inline-variants}} + {{!-- newtype variant: the child's own fields survive; named by modelName (unique per mapping), wraps the real classname --}} + {{{modelName}}}({{^avoidBoxedModels}}Box<{{/avoidBoxedModels}}models::{{#model}}{{{classname}}}{{/model}}{{^model}}{{{modelName}}}{{/model}}{{^avoidBoxedModels}}>{{/avoidBoxedModels}}), + {{/vendorExtensions.x-rust-inline-variants}} + {{#vendorExtensions.x-rust-inline-variants}} + {{{modelName}}} { + {{#vars}} + {{#description}} + /// {{{.}}} + {{/description}} + #[serde(rename = "{{{baseName}}}"{{^required}}, skip_serializing_if = "Option::is_none"{{/required}})] + {{{name}}}: {{#required}}{{#isNullable}}Option<{{/isNullable}}{{/required}}{{^required}}Option<{{/required}}{{#isEnum}}{{{enumName}}}{{/isEnum}}{{^isEnum}}{{#isModel}}{{^avoidBoxedModels}}Box<{{/avoidBoxedModels}}{{#isInteger}}i64{{/isInteger}}{{^isInteger}}{{{dataType}}}{{/isInteger}}{{^avoidBoxedModels}}>{{/avoidBoxedModels}}{{/isModel}}{{^isModel}}{{#isInteger}}i64{{/isInteger}}{{^isInteger}}{{{dataType}}}{{/isInteger}}{{/isModel}}{{/isEnum}}{{#required}}{{#isNullable}}>{{/isNullable}}{{/required}}{{^required}}>{{/required}}, + {{/vars}} + }, + {{/vendorExtensions.x-rust-inline-variants}} + {{/mappedModels}} + {{/oneOf}} + {{^oneOf.isEmpty}} + {{#composedSchemas.oneOf}} + {{#description}} + /// {{{.}}} + {{/description}} + {{#baseName}} + #[serde(rename="{{{.}}}")] + {{/baseName}} + {{{name}}}({{#isModel}}{{^avoidBoxedModels}}Box<{{/avoidBoxedModels}}{{/isModel}}{{#isInteger}}i64{{/isInteger}}{{^isInteger}}{{{dataType}}}{{/isInteger}}{{#isModel}}{{^avoidBoxedModels}}>{{/avoidBoxedModels}}{{/isModel}}), + {{/composedSchemas.oneOf}} + {{/oneOf.isEmpty}} +} + +impl Default for {{classname}} { + fn default() -> Self { + {{^oneOf}}{{#mappedModels}}{{#-first}}{{^vendorExtensions.x-rust-inline-variants}}Self::{{modelName}}(Default::default()){{/vendorExtensions.x-rust-inline-variants}}{{#vendorExtensions.x-rust-inline-variants}}Self::{{modelName}} { + {{#vars}} + {{{name}}}: Default::default(), + {{/vars}} + }{{/vendorExtensions.x-rust-inline-variants}}{{/-first}}{{/mappedModels}} + {{/oneOf}}{{^oneOf.isEmpty}}{{#composedSchemas.oneOf}}{{#-first}}Self::{{{name}}}(Default::default()){{/-first}}{{/composedSchemas.oneOf}}{{/oneOf.isEmpty}} + } +} + +{{/discriminator}} +{{!-- for non-enum schemas --}} +{{^isEnum}} +{{^discriminator}} +{{#vendorExtensions.x-rust-has-byte-array}}#[serde_as] +{{/vendorExtensions.x-rust-has-byte-array}}{{#oneOf.isEmpty}}#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, TS)] +#[serde(deny_unknown_fields)] +pub struct {{{classname}}} { +{{#vars}} + {{#description}} + /// {{{.}}} + {{/description}} + {{#isByteArray}} + {{#vendorExtensions.isMandatory}}#[serde_as(as = "serde_with::base64::Base64")]{{/vendorExtensions.isMandatory}}{{^vendorExtensions.isMandatory}}#[serde_as(as = "{{^serdeAsDoubleOption}}Option{{/serdeAsDoubleOption}}{{#serdeAsDoubleOption}}super::DoubleOption{{/serdeAsDoubleOption}}")]{{/vendorExtensions.isMandatory}} + {{/isByteArray}} + {{!-- a mapped child's discriminator is the union's consumed serde tag: default it, skip it while unset --}} + {{#isMap}}{{#isFreeFormObject}}#[ts(type = "Record")]{{/isFreeFormObject}}{{/isMap}}{{^required}}#[ts(optional)]{{/required}}{{#isNullable}}#[ts(type = "{{#isModel}}{{{dataType}}}{{/isModel}}{{^isModel}}{{#isEnum}}{{{enumName}}}{{/isEnum}}{{^isEnum}}{{#isDateTime}}string{{/isDateTime}}{{^isDateTime}}{{#isString}}string{{/isString}}{{#isInteger}}number{{/isInteger}}{{#isNumber}}number{{/isNumber}}{{#isBoolean}}boolean{{/isBoolean}}{{/isDateTime}}{{/isEnum}}{{/isModel}} | null")]{{/isNullable}}#[serde(rename = "{{{baseName}}}"{{#isDiscriminator}}{{#required}}, default{{#isNullable}}, skip_serializing_if = "Option::is_none"{{/isNullable}}{{^isNullable}}{{#isString}}{{^isEnum}}, skip_serializing_if = "String::is_empty"{{/isEnum}}{{/isString}}{{/isNullable}}{{/required}}{{/isDiscriminator}}{{^required}}{{#isNullable}}, default{{^isByteArray}}, with = "::serde_with::rust::double_option"{{/isByteArray}}{{/isNullable}}{{/required}}{{^required}}, skip_serializing_if = "Option::is_none"{{/required}}{{#required}}{{#isNullable}}{{^isDiscriminator}}, deserialize_with = "Option::deserialize"{{/isDiscriminator}}{{/isNullable}}{{/required}})] + pub {{{name}}}: {{! + ### Option Start + }}{{#isNullable}}Option<{{/isNullable}}{{^required}}Option<{{/required}}{{! + ### Enums + }}{{#isEnum}}{{#isArray}}{{#uniqueItems}}std::collections::HashSet<{{/uniqueItems}}{{^uniqueItems}}Vec<{{/uniqueItems}}{{/isArray}}{{{enumName}}}{{#isArray}}>{{/isArray}}{{/isEnum}}{{! + ### Non-Enums Start + }}{{^isEnum}}{{! + ### Models + }}{{#isModel}}{{^avoidBoxedModels}}Box<{{/avoidBoxedModels}}{{#isInteger}}i64{{/isInteger}}{{^isInteger}}{{{dataType}}}{{/isInteger}}{{^avoidBoxedModels}}>{{/avoidBoxedModels}}{{/isModel}}{{! + ### Primative datatypes + }}{{^isModel}}{{#isByteArray}}Vec{{/isByteArray}}{{^isByteArray}}{{#isInteger}}i64{{/isInteger}}{{^isInteger}}{{{dataType}}}{{/isInteger}}{{/isByteArray}}{{/isModel}}{{! + ### Non-Enums End + }}{{/isEnum}}{{! + ### Option End (and trailing comma) + }}{{#isNullable}}>{{/isNullable}}{{^required}}>{{/required}}, +{{/vars}} +} + +impl {{{classname}}} { + {{#description}} + /// {{{.}}} + {{/description}} + #[allow(clippy::too_many_arguments)] + pub fn new({{#requiredVars}}{{{name}}}: {{! + ### Option Start + }}{{#isNullable}}Option<{{/isNullable}}{{! + ### Enums + }}{{#isEnum}}{{#isArray}}{{#uniqueItems}}std::collections::HashSet<{{/uniqueItems}}{{^uniqueItems}}Vec<{{/uniqueItems}}{{/isArray}}{{{enumName}}}{{#isArray}}>{{/isArray}}{{/isEnum}}{{! + ### Non-Enums + }}{{^isEnum}}{{#isByteArray}}Vec{{/isByteArray}}{{^isByteArray}}{{#isInteger}}i64{{/isInteger}}{{^isInteger}}{{{dataType}}}{{/isInteger}}{{/isByteArray}}{{/isEnum}}{{! + ### Option End + }}{{#isNullable}}>{{/isNullable}}{{! + ### Comma for next arguement + }}{{^-last}}, {{/-last}}{{/requiredVars}}) -> {{{classname}}} { + {{{classname}}} { + {{#vars}} + {{{name}}}{{^required}}: None{{/required}}{{#required}}{{^isEnum}}{{#isModel}}{{^avoidBoxedModels}}: {{^isNullable}}Box::new({{{name}}}){{/isNullable}}{{#isNullable}}if let Some(x) = {{{name}}} {Some(Box::new(x))} else {None}{{/isNullable}}{{/avoidBoxedModels}}{{/isModel}}{{/isEnum}}{{/required}}, + {{/vars}} + } + } +} +{{/oneOf.isEmpty}} +{{^oneOf.isEmpty}} +{{! TODO: add other vars that are not part of the oneOf}} +{{#description}} +/// {{{.}}} +{{/description}} +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, TS)] +#[serde(untagged)] +pub enum {{classname}} { +{{#composedSchemas.oneOf}} + {{#description}} + /// {{{.}}} + {{/description}} + {{{name}}}({{#isModel}}{{^avoidBoxedModels}}Box<{{/avoidBoxedModels}}{{/isModel}}{{#isInteger}}i64{{/isInteger}}{{^isInteger}}{{{dataType}}}{{/isInteger}}{{#isModel}}{{^avoidBoxedModels}}>{{/avoidBoxedModels}}{{/isModel}}), +{{/composedSchemas.oneOf}} +} + +impl Default for {{classname}} { + fn default() -> Self { + {{#composedSchemas.oneOf}}{{#-first}}Self::{{{name}}}(Default::default()){{/-first}}{{/composedSchemas.oneOf}} + } +} +{{/oneOf.isEmpty}} +{{/discriminator}} +{{/isEnum}} +{{!-- for properties that are of enum type --}} +{{#vars}} +{{#isEnum}} +{{#isInteger}} +/// {{{description}}} +#[repr(i64)] +#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, TS)] +pub enum {{{enumName}}} { +{{#allowableValues}} +{{#enumVars}} + {{{name}}} = {{{value}}}, +{{/enumVars}} +{{/allowableValues}} +} + +impl std::fmt::Display for {{{enumName}}} { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", match self { + {{#allowableValues}} + {{#enumVars}} + Self::{{{name}}} => "{{{value}}}", + {{/enumVars}} + {{/allowableValues}} + }) + } +} +{{/isInteger}} +{{^isInteger}} +#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, TS, Default)] +pub enum {{{enumName}}} { +{{#allowableValues}} +{{#enumVars}} + #[serde(rename = "{{{value}}}")] + {{#-first}}#[default]{{/-first}} + {{{name}}}, +{{/enumVars}} +{{/allowableValues}} +} +{{/isInteger}} + +{{/isEnum}} +{{/vars}} + +{{/model}} +{{/models}} diff --git a/desktop/src-tauri/Cargo.lock b/desktop/src-tauri/Cargo.lock index 9f8fb4a346..8c3bb3d9ff 100644 --- a/desktop/src-tauri/Cargo.lock +++ b/desktop/src-tauri/Cargo.lock @@ -2869,6 +2869,7 @@ dependencies = [ "rustls", "serde", "serde_json", + "serde_with", "sha2", "tauri", "tauri-build", diff --git a/desktop/src-tauri/Cargo.toml b/desktop/src-tauri/Cargo.toml index d8098f9106..ec1e8f9be1 100644 --- a/desktop/src-tauri/Cargo.toml +++ b/desktop/src-tauri/Cargo.toml @@ -34,6 +34,7 @@ tauri-build = { version = "=2.6.0", features = [] } tauri = { version = "=2.11.0", features = [] } serde = { version = "=1.0.228", features = ["derive"] } serde_json = "=1.0.149" +serde_with = { version = "=3.22.0", default-features = false, features = ["std", "macros"] } sha2 = "=0.10.9" ts-rs = { version = "=12.0.1", features = ["serde-json-impl"] } reqwest = { version = "=0.12.28", default-features = false, features = ["native-tls", "json", "stream"] } diff --git a/desktop/src-tauri/examples/export_ipc.rs b/desktop/src-tauri/examples/export_ipc.rs index 23e51a5e8c..66623da867 100644 --- a/desktop/src-tauri/examples/export_ipc.rs +++ b/desktop/src-tauri/examples/export_ipc.rs @@ -84,6 +84,10 @@ fn main() { .collect::>() .join("\n") + "\n"; + assert!( + !output.contains("?: |"), + "IPC generation produced an empty TypeScript field type", + ); let path = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("../ui/src/generated/ipc.ts"); if std::env::args().any(|arg| arg == "--check") { assert_eq!( diff --git a/desktop/src-tauri/examples/server_probe.rs b/desktop/src-tauri/examples/server_probe.rs index 7ebf86975a..e53f7fb305 100644 --- a/desktop/src-tauri/examples/server_probe.rs +++ b/desktop/src-tauri/examples/server_probe.rs @@ -397,12 +397,19 @@ async fn verify_scope_pages( let first = manager.scopes(generation, &title, None).await.unwrap(); assert_eq!(first.items.len(), 50); let second = manager - .scopes(generation, &title, first.next_cursor.as_deref()) + .scopes( + generation, + &title, + first + .next_cursor + .as_ref() + .and_then(|cursor| cursor.as_deref()), + ) .await .unwrap(); assert!(first.next_cursor.is_some()); assert_eq!(second.items.len(), 1); - assert!(second.next_cursor.is_none()); + assert!(second.next_cursor.flatten().is_none()); let found: std::collections::BTreeSet<_> = first .items .iter() diff --git a/desktop/src-tauri/src/transport/api.rs b/desktop/src-tauri/src/transport/api.rs index 2764be36c8..c48e684176 100644 --- a/desktop/src-tauri/src/transport/api.rs +++ b/desktop/src-tauri/src/transport/api.rs @@ -250,7 +250,10 @@ impl ServerApi { .await?; if result.principal.id.is_empty() || result.principal.id.chars().count() > 255 - || !matches!(result.principal.r#type.as_str(), "user" | "service") + || !matches!( + result.principal.r#type, + crate::transport::wire::Type::User | crate::transport::wire::Type::Service + ) { return Err(SafeError::InvalidResponse.into()); } @@ -285,6 +288,7 @@ impl ServerApi { || result .next_cursor .as_ref() + .and_then(|c| c.as_ref()) .is_some_and(|c| c.is_empty() || c.len() > 4096) { return Err(SafeError::InvalidResponse.into()); @@ -314,14 +318,17 @@ impl ServerApi { ) -> Result { validate_scope(scope)?; validate_text(text)?; + let request = RememberMemoryRequest { + scope_id: scope.to_owned(), + kind: "note".to_owned(), + text: text.to_owned(), + reason: None, + expected_revision: None, + }; + let body = serde_json::to_value(request) + .map_err(|_| ApiFailure::before(SafeError::InvalidInput))?; let result: MemoryMutationResponse = self - .execute( - "remember_memory", - None, - &[], - Some(serde_json::json!({"scope_id":scope,"kind":"note","text":text})), - false, - ) + .execute("remember_memory", None, &[], Some(body), false) .await?; if result .records @@ -343,14 +350,17 @@ impl ServerApi { ) -> Result { validate_scope(scope)?; validate_text(query)?; + let request = SearchMemoryRequest { + tag_filter: None, + scope_id: scope.to_owned(), + query: query.to_owned(), + limit: Some(10), + mode: Some(MemorySearchMode::Fts), + }; + let body = serde_json::to_value(request) + .map_err(|_| ApiFailure::before(SafeError::InvalidInput))?; let result: SearchMemoryResponse = self - .execute( - "search_memory", - None, - &[], - Some(serde_json::json!({"scope_id":scope,"query":query,"mode":"fts","limit":10})), - false, - ) + .execute("search_memory", None, &[], Some(body), false) .await?; if result.mode != AtomicMemorySearchMode::Text || result.hits.len() > 10 @@ -358,10 +368,13 @@ impl ServerApi { !valid_atomic_record(&hit.memory) || hit.memory.state != AtomicMemoryState::Active || !hit.score.is_finite() - || hit - .matched_by - .iter() - .any(|channel| !matches!(channel.as_str(), "text" | "vector")) + || hit.matched_by.iter().any(|channel| { + !matches!( + channel, + crate::transport::wire::MatchedBy::Text + | crate::transport::wire::MatchedBy::Vector + ) + }) }) { return Err(SafeError::InvalidResponse.into()); @@ -373,7 +386,14 @@ impl ServerApi { artifact: hit.memory.artifact, text: hit.memory.text, score: hit.score, - matched_by: hit.matched_by, + matched_by: hit + .matched_by + .into_iter() + .map(|channel| match channel { + crate::transport::wire::MatchedBy::Text => "text".to_owned(), + crate::transport::wire::MatchedBy::Vector => "vector".to_owned(), + }) + .collect(), }) .collect(); Ok(MemorySearchResponse { hits }) diff --git a/desktop/src-tauri/src/transport/wire.rs b/desktop/src-tauri/src/transport/wire.rs index 4b3ebf0b72..73828fceaa 100644 --- a/desktop/src-tauri/src/transport/wire.rs +++ b/desktop/src-tauri/src/transport/wire.rs @@ -16,9 +16,15 @@ // Generated from openapi/powercontext.yaml. Do not edit. // rustfmt uses this generated layout verbatim. -#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize, ts_rs::TS)] +use serde::{Deserialize, Serialize}; +use ts_rs::TS; + +#[derive( + Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, TS, Default, +)] pub enum AccessAction { #[serde(rename = "server.observe")] + #[default] ServerObserve, #[serde(rename = "server.admin")] ServerAdmin, @@ -46,48 +52,163 @@ pub enum AccessAction { PromptUse, } -#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize, ts_rs::TS)] +impl std::fmt::Display for AccessAction { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + Self::ServerObserve => write!(f, "server.observe"), + Self::ServerAdmin => write!(f, "server.admin"), + Self::ScopeRead => write!(f, "scope.read"), + Self::ScopeContribute => write!(f, "scope.contribute"), + Self::ScopeReview => write!(f, "scope.review"), + Self::ScopeDelegate => write!(f, "scope.delegate"), + Self::ScopeAdmin => write!(f, "scope.admin"), + Self::ArtifactRead => write!(f, "artifact.read"), + Self::ArtifactWrite => write!(f, "artifact.write"), + Self::ArtifactShare => write!(f, "artifact.share"), + Self::HandoffEvidenceInspect => write!(f, "handoff.evidence.inspect"), + Self::HandoffAcknowledge => write!(f, "handoff.acknowledge"), + Self::PromptUse => write!(f, "prompt.use"), + } + } +} + +#[derive( + Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, TS, Default, +)] pub enum AccessControlMode { #[serde(rename = "disabled")] + #[default] Disabled, #[serde(rename = "enforced")] Enforced, } -#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize, ts_rs::TS)] +impl std::fmt::Display for AccessControlMode { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + Self::Disabled => write!(f, "disabled"), + Self::Enforced => write!(f, "enforced"), + } + } +} + +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, TS)] #[serde(deny_unknown_fields)] pub struct AccessMeResponse { - pub r#principal: AccessPrincipal, - pub r#mode: AccessControlMode, - pub r#resource_kinds: Vec, - pub r#provider_capabilities: AccessProviderCapabilities, - pub r#artifact_families: Vec, + #[serde(rename = "principal")] + pub principal: AccessPrincipal, + #[serde(rename = "mode")] + pub mode: AccessControlMode, + #[serde(rename = "resource_kinds")] + pub resource_kinds: Vec, + #[serde(rename = "provider_capabilities")] + pub provider_capabilities: AccessProviderCapabilities, + #[serde(rename = "artifact_families")] + pub artifact_families: Vec, +} + +impl AccessMeResponse { + #[allow(clippy::too_many_arguments)] + pub fn new( + principal: AccessPrincipal, + mode: AccessControlMode, + resource_kinds: Vec, + provider_capabilities: AccessProviderCapabilities, + artifact_families: Vec, + ) -> AccessMeResponse { + AccessMeResponse { + principal, + mode, + resource_kinds, + provider_capabilities, + artifact_families, + } + } } -#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize, ts_rs::TS)] +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, TS)] #[serde(deny_unknown_fields)] pub struct AccessPrincipal { - pub r#type: String, - pub r#id: String, - #[serde(skip_serializing_if = "Option::is_none")] - #[ts(optional = nullable)] - pub r#description: Option, + #[serde(rename = "type")] + pub r#type: Type, + #[serde(rename = "id")] + pub id: String, + #[ts(optional)] + #[ts(type = "string | null")] + #[serde( + rename = "description", + default, + with = "::serde_with::rust::double_option", + skip_serializing_if = "Option::is_none" + )] + pub description: Option>, +} + +impl AccessPrincipal { + #[allow(clippy::too_many_arguments)] + pub fn new(r#type: Type, id: String) -> AccessPrincipal { + AccessPrincipal { + r#type, + id, + description: None, + } + } +} +#[derive( + Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, TS, Default, +)] +pub enum Type { + #[serde(rename = "user")] + #[default] + User, + #[serde(rename = "service")] + Service, } -#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize, ts_rs::TS)] +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, TS)] #[serde(deny_unknown_fields)] pub struct AccessProviderCapabilities { - pub r#safe_resource_filtering: bool, - pub r#multi_requirement_check: bool, - pub r#relationship_management: bool, - pub r#group_subjects: bool, - pub r#multi_principal: bool, - pub r#max_direct_resource_keys: i64, + #[serde(rename = "safe_resource_filtering")] + pub safe_resource_filtering: bool, + #[serde(rename = "multi_requirement_check")] + pub multi_requirement_check: bool, + #[serde(rename = "relationship_management")] + pub relationship_management: bool, + #[serde(rename = "group_subjects")] + pub group_subjects: bool, + #[serde(rename = "multi_principal")] + pub multi_principal: bool, + #[serde(rename = "max_direct_resource_keys")] + pub max_direct_resource_keys: i64, +} + +impl AccessProviderCapabilities { + #[allow(clippy::too_many_arguments)] + pub fn new( + safe_resource_filtering: bool, + multi_requirement_check: bool, + relationship_management: bool, + group_subjects: bool, + multi_principal: bool, + max_direct_resource_keys: i64, + ) -> AccessProviderCapabilities { + AccessProviderCapabilities { + safe_resource_filtering, + multi_requirement_check, + relationship_management, + group_subjects, + multi_principal, + max_direct_resource_keys, + } + } } -#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize, ts_rs::TS)] +#[derive( + Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, TS, Default, +)] pub enum AccessResourceType { #[serde(rename = "server")] + #[default] Server, #[serde(rename = "scope")] Scope, @@ -95,9 +216,22 @@ pub enum AccessResourceType { Artifact, } -#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize, ts_rs::TS)] +impl std::fmt::Display for AccessResourceType { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + Self::Server => write!(f, "server"), + Self::Scope => write!(f, "scope"), + Self::Artifact => write!(f, "artifact"), + } + } +} + +#[derive( + Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, TS, Default, +)] pub enum AccessRole { #[serde(rename = "handoff.viewer")] + #[default] HandoffViewer, #[serde(rename = "handoff.receiver")] HandoffReceiver, @@ -123,27 +257,124 @@ pub enum AccessRole { ServerAdmin, } -#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize, ts_rs::TS)] +impl std::fmt::Display for AccessRole { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + Self::HandoffViewer => write!(f, "handoff.viewer"), + Self::HandoffReceiver => write!(f, "handoff.receiver"), + Self::ArtifactViewer => write!(f, "artifact.viewer"), + Self::PromptUser => write!(f, "prompt.user"), + Self::ArtifactOwner => write!(f, "artifact.owner"), + Self::ScopeViewer => write!(f, "scope.viewer"), + Self::ScopeContributor => write!(f, "scope.contributor"), + Self::ScopeReviewer => write!(f, "scope.reviewer"), + Self::ScopeDelegator => write!(f, "scope.delegator"), + Self::ScopeAdmin => write!(f, "scope.admin"), + Self::ServerObserver => write!(f, "server.observer"), + Self::ServerAdmin => write!(f, "server.admin"), + } + } +} + +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, TS)] #[serde(deny_unknown_fields)] pub struct ArtifactDreamingOperationCapability { - pub r#operation: DreamOperation, - pub r#output_kind: String, - pub r#effect: String, + #[serde(rename = "operation")] + pub operation: DreamOperation, + #[serde(rename = "output_kind")] + pub output_kind: OutputKind, + #[serde(rename = "effect")] + pub effect: Effect, } -#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize, ts_rs::TS)] +impl ArtifactDreamingOperationCapability { + #[allow(clippy::too_many_arguments)] + pub fn new( + operation: DreamOperation, + output_kind: OutputKind, + effect: Effect, + ) -> ArtifactDreamingOperationCapability { + ArtifactDreamingOperationCapability { + operation, + output_kind, + effect, + } + } +} +#[derive( + Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, TS, Default, +)] +pub enum OutputKind { + #[serde(rename = "candidate")] + #[default] + Candidate, + #[serde(rename = "tag_candidate")] + TagCandidate, +} + +#[derive( + Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, TS, Default, +)] +pub enum Effect { + #[serde(rename = "review_then_publish")] + #[default] + ReviewThenPublish, + #[serde(rename = "review_then_publish_configuration")] + ReviewThenPublishConfiguration, + #[serde(rename = "review_then_replace_tags")] + ReviewThenReplaceTags, +} + +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, TS)] #[serde(deny_unknown_fields)] pub struct ArtifactFamilyAccessCapability { - pub r#family: String, - pub r#enabled: bool, - pub r#share_unit: String, - pub r#actions: Vec, - pub r#grantable_roles: Vec, + #[serde(rename = "family")] + pub family: String, + #[serde(rename = "enabled")] + pub enabled: bool, + #[serde(rename = "share_unit")] + pub share_unit: ShareUnit, + #[serde(rename = "actions")] + pub actions: Vec, + #[serde(rename = "grantable_roles")] + pub grantable_roles: Vec, +} + +impl ArtifactFamilyAccessCapability { + #[allow(clippy::too_many_arguments)] + pub fn new( + family: String, + enabled: bool, + share_unit: ShareUnit, + actions: Vec, + grantable_roles: Vec, + ) -> ArtifactFamilyAccessCapability { + ArtifactFamilyAccessCapability { + family, + enabled, + share_unit, + actions, + grantable_roles, + } + } +} +#[derive( + Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, TS, Default, +)] +pub enum ShareUnit { + #[serde(rename = "artifact")] + #[default] + Artifact, + #[serde(rename = "memory_entry")] + MemoryEntry, } -#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize, ts_rs::TS)] +#[derive( + Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, TS, Default, +)] pub enum ArtifactReadFamily { #[serde(rename = "memory")] + #[default] Memory, #[serde(rename = "atomic-memory")] AtomicMemory, @@ -161,62 +392,216 @@ pub enum ArtifactReadFamily { TopicMemory, } -#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize, ts_rs::TS)] +impl std::fmt::Display for ArtifactReadFamily { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + Self::Memory => write!(f, "memory"), + Self::AtomicMemory => write!(f, "atomic-memory"), + Self::Experience => write!(f, "experience"), + Self::Skill => write!(f, "skill"), + Self::Handoff => write!(f, "handoff"), + Self::Profile => write!(f, "profile"), + Self::Prompt => write!(f, "prompt"), + Self::TopicMemory => write!(f, "topic-memory"), + } + } +} + +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, TS)] #[serde(deny_unknown_fields)] pub struct ArtifactReference { - pub r#family: String, - pub r#artifact_id: String, - pub r#revision: i64, + #[serde(rename = "family")] + pub family: String, + #[serde(rename = "artifact_id")] + pub artifact_id: String, + #[serde(rename = "revision")] + pub revision: i64, } -#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize, ts_rs::TS)] +impl ArtifactReference { + #[allow(clippy::too_many_arguments)] + pub fn new(family: String, artifact_id: String, revision: i64) -> ArtifactReference { + ArtifactReference { + family, + artifact_id, + revision, + } + } +} + +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, TS)] #[serde(deny_unknown_fields)] pub struct ArtifactRevision { - pub r#scope_id: String, - pub r#family: ArtifactReadFamily, - pub r#artifact_id: String, - pub r#revision: i64, + #[serde(rename = "scope_id")] + pub scope_id: String, + #[serde(rename = "family")] + pub family: ArtifactReadFamily, + #[serde(rename = "artifact_id")] + pub artifact_id: String, + #[serde(rename = "revision")] + pub revision: i64, #[ts(type = "Record")] - pub r#content: serde_json::Value, - pub r#sources: Vec, - pub r#artifacts: Vec, - pub r#content_digest: String, - #[serde(skip_serializing_if = "Option::is_none")] - #[ts(optional = nullable)] - pub r#created_at: Option, - #[serde(skip_serializing_if = "Option::is_none")] - #[ts(optional = nullable)] - pub r#created_by: Option, - #[serde(skip_serializing_if = "Option::is_none")] - #[ts(optional = nullable)] - pub r#restored_from_revision: Option, - #[serde(skip_serializing_if = "Option::is_none")] - #[ts(optional = nullable)] - pub r#reason: Option, -} - -#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize, ts_rs::TS)] + #[serde(rename = "content")] + pub content: std::collections::HashMap, + #[serde(rename = "sources")] + pub sources: Vec, + #[serde(rename = "artifacts")] + pub artifacts: Vec, + #[serde(rename = "content_digest")] + pub content_digest: String, + /// When this revision was committed. Absent for revisions stored before this field existed. + #[ts(optional)] + #[ts(type = "string | null")] + #[serde( + rename = "created_at", + default, + with = "::serde_with::rust::double_option", + skip_serializing_if = "Option::is_none" + )] + pub created_at: Option>, + /// Principal that committed a rollback. Ordinary revisions omit it. + #[ts(optional)] + #[ts(type = "AccessPrincipal | null")] + #[serde( + rename = "created_by", + default, + with = "::serde_with::rust::double_option", + skip_serializing_if = "Option::is_none" + )] + pub created_by: Option>, + /// Historical revision restored by this rollback. + #[ts(optional)] + #[ts(type = "number | null")] + #[serde( + rename = "restored_from_revision", + default, + with = "::serde_with::rust::double_option", + skip_serializing_if = "Option::is_none" + )] + pub restored_from_revision: Option>, + /// Reason recorded for a rollback. + #[ts(optional)] + #[ts(type = "string | null")] + #[serde( + rename = "reason", + default, + with = "::serde_with::rust::double_option", + skip_serializing_if = "Option::is_none" + )] + pub reason: Option>, +} + +impl ArtifactRevision { + #[allow(clippy::too_many_arguments)] + pub fn new( + scope_id: String, + family: ArtifactReadFamily, + artifact_id: String, + revision: i64, + content: std::collections::HashMap, + sources: Vec, + artifacts: Vec, + content_digest: String, + ) -> ArtifactRevision { + ArtifactRevision { + scope_id, + family, + artifact_id, + revision, + content, + sources, + artifacts, + content_digest, + created_at: None, + created_by: None, + restored_from_revision: None, + reason: None, + } + } +} + +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, TS)] #[serde(deny_unknown_fields)] pub struct AtomicMemoryRecord { - pub r#artifact: ArtifactReference, - pub r#kind: String, - pub r#text: String, - pub r#state: AtomicMemoryState, - pub r#state_version: i64, - pub r#merged_into_id: Option, + #[serde(rename = "artifact")] + pub artifact: ArtifactReference, + #[serde(rename = "kind")] + pub kind: String, + #[serde(rename = "text")] + pub text: String, + #[serde(rename = "state")] + pub state: AtomicMemoryState, + #[serde(rename = "state_version")] + pub state_version: i64, + #[ts(type = "string | null")] + #[serde(rename = "merged_into_id", deserialize_with = "Option::deserialize")] + pub merged_into_id: Option, +} + +impl AtomicMemoryRecord { + #[allow(clippy::too_many_arguments)] + pub fn new( + artifact: ArtifactReference, + kind: String, + text: String, + state: AtomicMemoryState, + state_version: i64, + merged_into_id: Option, + ) -> AtomicMemoryRecord { + AtomicMemoryRecord { + artifact, + kind, + text, + state, + state_version, + merged_into_id, + } + } } -#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize, ts_rs::TS)] +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, TS)] #[serde(deny_unknown_fields)] pub struct AtomicMemorySearchHit { - pub r#memory: AtomicMemoryRecord, - pub r#score: f64, - pub r#matched_by: Vec, + #[serde(rename = "memory")] + pub memory: AtomicMemoryRecord, + /// Raw RRF score. Hybrid mode applies the deployment's normalized relative FTS/vector weights. + #[serde(rename = "score")] + pub score: f64, + #[serde(rename = "matched_by")] + pub matched_by: Vec, } -#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize, ts_rs::TS)] +impl AtomicMemorySearchHit { + #[allow(clippy::too_many_arguments)] + pub fn new( + memory: AtomicMemoryRecord, + score: f64, + matched_by: Vec, + ) -> AtomicMemorySearchHit { + AtomicMemorySearchHit { + memory, + score, + matched_by, + } + } +} +#[derive( + Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, TS, Default, +)] +pub enum MatchedBy { + #[serde(rename = "text")] + #[default] + Text, + #[serde(rename = "vector")] + Vector, +} + +#[derive( + Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, TS, Default, +)] pub enum AtomicMemorySearchMode { #[serde(rename = "text")] + #[default] Text, #[serde(rename = "vector")] Vector, @@ -224,9 +609,22 @@ pub enum AtomicMemorySearchMode { Hybrid, } -#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize, ts_rs::TS)] +impl std::fmt::Display for AtomicMemorySearchMode { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + Self::Text => write!(f, "text"), + Self::Vector => write!(f, "vector"), + Self::Hybrid => write!(f, "hybrid"), + } + } +} + +#[derive( + Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, TS, Default, +)] pub enum AtomicMemoryState { #[serde(rename = "active")] + #[default] Active, #[serde(rename = "forgotten")] Forgotten, @@ -236,41 +634,108 @@ pub enum AtomicMemoryState { Retired, } -#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize, ts_rs::TS)] +impl std::fmt::Display for AtomicMemoryState { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + Self::Active => write!(f, "active"), + Self::Forgotten => write!(f, "forgotten"), + Self::Merged => write!(f, "merged"), + Self::Retired => write!(f, "retired"), + } + } +} + +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, TS)] #[serde(deny_unknown_fields)] pub struct Capabilities { - #[serde(skip_serializing_if = "Option::is_none")] - #[ts(optional = nullable)] - pub r#prompts: Option>, - #[serde(skip_serializing_if = "Option::is_none")] - #[ts(optional = nullable)] - pub r#artifact_dreaming: Option, - #[serde(skip_serializing_if = "Option::is_none")] - #[ts(optional = nullable)] - pub r#artifact_dreaming_operations: Option>, - pub r#source_types: Vec, - pub r#artifact_families: Vec, - pub r#memory_extraction: bool, - #[serde(skip_serializing_if = "Option::is_none")] - #[ts(optional = nullable)] - pub r#extraction: Option, - #[serde(skip_serializing_if = "Option::is_none")] - #[ts(optional = nullable)] - pub r#experience_generation: Option, - #[serde(skip_serializing_if = "Option::is_none")] - #[ts(optional = nullable)] - pub r#managed_skill_generation: Option, - #[serde(skip_serializing_if = "Option::is_none")] - #[ts(optional = nullable)] - pub r#external_skill_registry: Option, - pub r#handoff_generation: bool, - pub r#search_modes: Vec, - pub r#context_versions: Vec, -} - -#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize, ts_rs::TS)] + #[ts(optional)] + #[serde(rename = "prompts", skip_serializing_if = "Option::is_none")] + pub prompts: Option>, + /// Whether asynchronous Artifact Dream execution is configured. + #[ts(optional)] + #[serde(rename = "artifact_dreaming", skip_serializing_if = "Option::is_none")] + pub artifact_dreaming: Option, + /// Dream operations enabled by the current Runtime, including their reviewed effect. + #[ts(optional)] + #[serde( + rename = "artifact_dreaming_operations", + skip_serializing_if = "Option::is_none" + )] + pub artifact_dreaming_operations: Option>, + #[serde(rename = "source_types")] + pub source_types: Vec, + #[serde(rename = "artifact_families")] + pub artifact_families: Vec, + /// Whether pending Sources can be extracted into Memory. + #[serde(rename = "memory_extraction")] + pub memory_extraction: bool, + #[ts(optional)] + #[serde(rename = "extraction", skip_serializing_if = "Option::is_none")] + pub extraction: Option, + /// Whether the configured model can generate reviewed Experience Candidates. + #[ts(optional)] + #[serde( + rename = "experience_generation", + skip_serializing_if = "Option::is_none" + )] + pub experience_generation: Option, + /// Whether the configured model can generate reviewed managed Skill Candidates. + #[ts(optional)] + #[serde( + rename = "managed_skill_generation", + skip_serializing_if = "Option::is_none" + )] + pub managed_skill_generation: Option, + /// Whether host-local external Skill discovery and exact resolution are configured. + #[ts(optional)] + #[serde( + rename = "external_skill_registry", + skip_serializing_if = "Option::is_none" + )] + pub external_skill_registry: Option, + /// Whether exact evidence can be generated into an inspectable Handoff Draft. + #[serde(rename = "handoff_generation")] + pub handoff_generation: bool, + #[serde(rename = "search_modes")] + pub search_modes: Vec, + #[serde(rename = "context_versions")] + pub context_versions: Vec, +} + +impl Capabilities { + #[allow(clippy::too_many_arguments)] + pub fn new( + source_types: Vec, + artifact_families: Vec, + memory_extraction: bool, + handoff_generation: bool, + search_modes: Vec, + context_versions: Vec, + ) -> Capabilities { + Capabilities { + prompts: None, + artifact_dreaming: None, + artifact_dreaming_operations: None, + source_types, + artifact_families, + memory_extraction, + extraction: None, + experience_generation: None, + managed_skill_generation: None, + external_skill_registry: None, + handoff_generation, + search_modes, + context_versions, + } + } +} + +#[derive( + Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, TS, Default, +)] pub enum DreamOperation { #[serde(rename = "refine_experience")] + #[default] RefineExperience, #[serde(rename = "derive_skill")] DeriveSkill, @@ -290,64 +755,267 @@ pub enum DreamOperation { ReviseTags, } -#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize, ts_rs::TS)] +impl std::fmt::Display for DreamOperation { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + Self::RefineExperience => write!(f, "refine_experience"), + Self::DeriveSkill => write!(f, "derive_skill"), + Self::ReviseSkill => write!(f, "revise_skill"), + Self::ReviseProfile => write!(f, "revise_profile"), + Self::ReviseMemory => write!(f, "revise_memory"), + Self::ReviseTopicMemory => write!(f, "revise_topic_memory"), + Self::RefreshHandoff => write!(f, "refresh_handoff"), + Self::RevisePrompt => write!(f, "revise_prompt"), + Self::ReviseTags => write!(f, "revise_tags"), + } + } +} + +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, TS)] #[serde(deny_unknown_fields)] pub struct ExtractionBackground { - pub r#location: String, - #[serde(skip_serializing_if = "Option::is_none")] - #[ts(optional = nullable)] - pub r#role: Option, - pub r#state: String, - #[serde(skip_serializing_if = "Option::is_none")] - #[ts(optional = nullable)] - pub r#automatic_processing_enabled: Option, + /// Placement of the Memory Supervisor. None means no background executor; synchronous flush may still work. + #[serde(rename = "location")] + pub location: Location, + /// Current local Supervisor leadership role. Standby is normal; null means no running local Supervisor. + #[ts(optional)] + #[ts(type = "Role | null")] + #[serde( + rename = "role", + default, + with = "::serde_with::rust::double_option", + skip_serializing_if = "Option::is_none" + )] + pub role: Option>, + /// Local Supervisor lifecycle and control state, independent of individual worker outcomes. A running Supervisor may be retrying failed workers. External state is unknown. + #[serde(rename = "state")] + pub state: State, + /// Whether this process schedules automatic Memory extraction. False still permits explicit flush and recovery of accepted work. Null means the external worker schedule is unknown. + #[ts(optional)] + #[ts(type = "boolean | null")] + #[serde( + rename = "automatic_processing_enabled", + default, + with = "::serde_with::rust::double_option", + skip_serializing_if = "Option::is_none" + )] + pub automatic_processing_enabled: Option>, +} + +impl ExtractionBackground { + #[allow(clippy::too_many_arguments)] + pub fn new(location: Location, state: State) -> ExtractionBackground { + ExtractionBackground { + location, + role: None, + state, + automatic_processing_enabled: None, + } + } +} +#[derive( + Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, TS, Default, +)] +pub enum Location { + #[serde(rename = "local")] + #[default] + Local, + #[serde(rename = "external")] + External, + #[serde(rename = "none")] + None, +} + +#[derive( + Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, TS, Default, +)] +pub enum Role { + #[serde(rename = "leader")] + #[default] + Leader, + #[serde(rename = "standby")] + Standby, +} + +#[derive( + Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, TS, Default, +)] +pub enum State { + #[serde(rename = "running")] + #[default] + Running, + #[serde(rename = "degraded")] + Degraded, + #[serde(rename = "stopped")] + Stopped, + #[serde(rename = "unknown")] + Unknown, } -#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize, ts_rs::TS)] +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, TS)] #[serde(deny_unknown_fields)] pub struct ExtractionFailure { - pub r#code: String, - pub r#stage: String, - pub r#occurred_at: String, + /// Sanitized category: model_configuration_error, model_timeout, model_unavailable, invalid_model_output, worker_timeout, worker_crash, invalid_worker_result, missing_durable_acknowledgement, supervisor_failed, lease_renewal_failed, scope_discovery_failed, or processing_failed. Raw exception messages, model inputs, and credentials are never returned. + #[serde(rename = "code")] + pub code: String, + /// Inference for recognized model failures; otherwise the boundary where failure was observed. Flush or worker does not identify the failing internal component. + #[serde(rename = "stage")] + pub stage: Stage, + /// UTC time when this process observed the failure. + #[serde(rename = "occurred_at")] + pub occurred_at: String, +} + +impl ExtractionFailure { + #[allow(clippy::too_many_arguments)] + pub fn new(code: String, stage: Stage, occurred_at: String) -> ExtractionFailure { + ExtractionFailure { + code, + stage, + occurred_at, + } + } +} +#[derive( + Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, TS, Default, +)] +pub enum Stage { + #[serde(rename = "inference")] + #[default] + Inference, + #[serde(rename = "flush")] + Flush, + #[serde(rename = "worker")] + Worker, + #[serde(rename = "supervisor")] + Supervisor, + #[serde(rename = "lease_renewal")] + LeaseRenewal, + #[serde(rename = "scope_discovery")] + ScopeDiscovery, } -#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize, ts_rs::TS)] +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, TS)] #[serde(deny_unknown_fields)] pub struct ExtractionObservation { - pub r#status: String, - pub r#since: String, - #[serde(skip_serializing_if = "Option::is_none")] - #[ts(optional = nullable)] - pub r#last_failure: Option, - #[serde(skip_serializing_if = "Option::is_none")] - #[ts(optional = nullable)] - pub r#last_success_at: Option, + /// Unverified means no execution outcome or control failure has been observed in this window. Observed means at least one success or failure is recorded; neither value is a health verdict. + #[serde(rename = "status")] + pub status: ExtractionObservationStatus, + /// UTC start of this Runtime's observation window. Records cover this process and its child Memory workers, reset on Runtime restart, and do not include remote workers or a durable per-Scope failure history. + #[serde(rename = "since")] + pub since: String, + #[ts(optional)] + #[serde(rename = "last_failure", skip_serializing_if = "Option::is_none")] + pub last_failure: Option, + /// UTC time of the most recent local successful nonempty synchronous flush or acknowledged Memory worker invocation. This does not prove that a model was called or that any previous failure has recovered. + #[ts(optional)] + #[ts(type = "string | null")] + #[serde( + rename = "last_success_at", + default, + with = "::serde_with::rust::double_option", + skip_serializing_if = "Option::is_none" + )] + pub last_success_at: Option>, +} + +impl ExtractionObservation { + #[allow(clippy::too_many_arguments)] + pub fn new(status: ExtractionObservationStatus, since: String) -> ExtractionObservation { + ExtractionObservation { + status, + since, + last_failure: None, + last_success_at: None, + } + } +} +#[derive( + Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, TS, Default, +)] +pub enum ExtractionObservationStatus { + #[serde(rename = "unverified")] + #[default] + Unverified, + #[serde(rename = "observed")] + Observed, } -#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize, ts_rs::TS)] +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, TS)] #[serde(deny_unknown_fields)] pub struct ExtractionStatus { - pub r#configuration: String, - pub r#background: ExtractionBackground, - pub r#observation: ExtractionObservation, + /// Whether a local extraction model or custom pipeline is assembled. Configured does not verify credentials or connectivity. Unknown means execution is external and its configuration is not observed. + #[serde(rename = "configuration")] + pub configuration: Configuration, + #[serde(rename = "background")] + pub background: ExtractionBackground, + #[serde(rename = "observation")] + pub observation: ExtractionObservation, } -#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize, ts_rs::TS)] +impl ExtractionStatus { + #[allow(clippy::too_many_arguments)] + pub fn new( + configuration: Configuration, + background: ExtractionBackground, + observation: ExtractionObservation, + ) -> ExtractionStatus { + ExtractionStatus { + configuration, + background, + observation, + } + } +} +#[derive( + Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, TS, Default, +)] +pub enum Configuration { + #[serde(rename = "configured")] + #[default] + Configured, + #[serde(rename = "unconfigured")] + Unconfigured, + #[serde(rename = "unknown")] + Unknown, +} + +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, TS)] #[serde(deny_unknown_fields)] pub struct HealthResponse { - pub r#status: String, + #[serde(rename = "status")] + pub status: String, +} + +impl HealthResponse { + #[allow(clippy::too_many_arguments)] + pub fn new(status: String) -> HealthResponse { + HealthResponse { status } + } } -#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize, ts_rs::TS)] +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, TS)] #[serde(deny_unknown_fields)] pub struct MemoryMutationResponse { - pub r#changed: bool, - pub r#records: Vec, + #[serde(rename = "changed")] + pub changed: bool, + #[serde(rename = "records")] + pub records: Vec, +} + +impl MemoryMutationResponse { + #[allow(clippy::too_many_arguments)] + pub fn new(changed: bool, records: Vec) -> MemoryMutationResponse { + MemoryMutationResponse { changed, records } + } } -#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize, ts_rs::TS)] +#[derive( + Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, TS, Default, +)] pub enum MemorySearchMode { #[serde(rename = "auto")] + #[default] Auto, #[serde(rename = "fts")] Fts, @@ -357,32 +1025,131 @@ pub enum MemorySearchMode { Hybrid, } -#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize, ts_rs::TS)] +impl std::fmt::Display for MemorySearchMode { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + Self::Auto => write!(f, "auto"), + Self::Fts => write!(f, "fts"), + Self::Vector => write!(f, "vector"), + Self::Hybrid => write!(f, "hybrid"), + } + } +} + +#[derive( + Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, TS, Default, +)] pub enum PreparedContextSchema { #[serde(rename = "powercontext.prepared-context.v1")] + #[default] PowercontextPreparedContextV1, } -#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize, ts_rs::TS)] +impl std::fmt::Display for PreparedContextSchema { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + Self::PowercontextPreparedContextV1 => write!(f, "powercontext.prepared-context.v1"), + } + } +} + +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, TS)] #[serde(deny_unknown_fields)] pub struct PromptCapability { - pub r#status: String, - pub r#reason: Option, - pub r#definition_version: String, - pub r#builtin_version: String, - pub r#builtin_profile: Option, + #[serde(rename = "status")] + pub status: PromptCapabilityStatus, + #[ts(type = "Reason | null")] + #[serde(rename = "reason", deserialize_with = "Option::deserialize")] + pub reason: Option, + #[serde(rename = "definition_version")] + pub definition_version: String, + #[serde(rename = "builtin_version")] + pub builtin_version: String, + #[ts(type = "BuiltinProfile | null")] + #[serde(rename = "builtin_profile", deserialize_with = "Option::deserialize")] + pub builtin_profile: Option, +} + +impl PromptCapability { + #[allow(clippy::too_many_arguments)] + pub fn new( + status: PromptCapabilityStatus, + reason: Option, + definition_version: String, + builtin_version: String, + builtin_profile: Option, + ) -> PromptCapability { + PromptCapability { + status, + reason, + definition_version, + builtin_version, + builtin_profile, + } + } +} +#[derive( + Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, TS, Default, +)] +pub enum PromptCapabilityStatus { + #[serde(rename = "supported")] + #[default] + Supported, + #[serde(rename = "disabled")] + Disabled, + #[serde(rename = "unsupported")] + Unsupported, } -#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize, ts_rs::TS)] +#[derive( + Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, TS, Default, +)] +pub enum Reason { + #[serde(rename = "operation_disabled")] + #[default] + OperationDisabled, + #[serde(rename = "provider_not_configured")] + ProviderNotConfigured, + #[serde(rename = "injected_component")] + InjectedComponent, +} + +#[derive( + Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, TS, Default, +)] +pub enum BuiltinProfile { + #[serde(rename = "coding")] + #[default] + Coding, + #[serde(rename = "conversation")] + Conversation, +} + +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, TS)] #[serde(deny_unknown_fields)] pub struct ReadinessResponse { - pub r#status: ReadinessStatus, - pub r#checks: std::collections::BTreeMap, + #[serde(rename = "status")] + pub status: ReadinessStatus, + #[serde(rename = "checks")] + pub checks: std::collections::HashMap, } -#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize, ts_rs::TS)] +impl ReadinessResponse { + #[allow(clippy::too_many_arguments)] + pub fn new( + status: ReadinessStatus, + checks: std::collections::HashMap, + ) -> ReadinessResponse { + ReadinessResponse { status, checks } + } +} + +#[derive( + Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, TS, Default, +)] pub enum ReadinessStatus { #[serde(rename = "ready")] + #[default] Ready, #[serde(rename = "degraded")] Degraded, @@ -390,53 +1157,155 @@ pub enum ReadinessStatus { NotReady, } -#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize, ts_rs::TS)] +impl std::fmt::Display for ReadinessStatus { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + Self::Ready => write!(f, "ready"), + Self::Degraded => write!(f, "degraded"), + Self::NotReady => write!(f, "not_ready"), + } + } +} + +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, TS)] #[serde(deny_unknown_fields)] pub struct RememberMemoryRequest { - pub r#scope_id: String, - pub r#kind: String, - pub r#text: String, - #[serde(skip_serializing_if = "Option::is_none")] - #[ts(optional = nullable)] - pub r#reason: Option, - #[serde(skip_serializing_if = "Option::is_none")] - #[ts(optional = nullable)] - pub r#expected_revision: Option, -} - -#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize, ts_rs::TS)] + #[serde(rename = "scope_id")] + pub scope_id: String, + #[serde(rename = "kind")] + pub kind: String, + /// Must not exceed 8192 UTF-8 bytes after normalization. + #[serde(rename = "text")] + pub text: String, + #[ts(optional)] + #[ts(type = "string | null")] + #[serde( + rename = "reason", + default, + with = "::serde_with::rust::double_option", + skip_serializing_if = "Option::is_none" + )] + pub reason: Option>, + #[ts(optional)] + #[ts(type = "number | null")] + #[serde( + rename = "expected_revision", + default, + with = "::serde_with::rust::double_option", + skip_serializing_if = "Option::is_none" + )] + pub expected_revision: Option>, +} + +impl RememberMemoryRequest { + #[allow(clippy::too_many_arguments)] + pub fn new(scope_id: String, kind: String, text: String) -> RememberMemoryRequest { + RememberMemoryRequest { + scope_id, + kind, + text, + reason: None, + expected_revision: None, + } + } +} + +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, TS)] #[serde(deny_unknown_fields)] pub struct ScopeDescriptor { - pub r#scope_id: String, - pub r#title: String, - pub r#summary: String, - #[serde(skip_serializing_if = "Option::is_none")] - #[ts(optional = nullable)] - pub r#parent_scope_id: Option, - pub r#context_references: Vec, - pub r#external_references: Vec, - pub r#version: i64, -} - -#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize, ts_rs::TS)] + #[serde(rename = "scope_id")] + pub scope_id: String, + #[serde(rename = "title")] + pub title: String, + #[serde(rename = "summary")] + pub summary: String, + #[ts(optional)] + #[ts(type = "string | null")] + #[serde( + rename = "parent_scope_id", + default, + with = "::serde_with::rust::double_option", + skip_serializing_if = "Option::is_none" + )] + pub parent_scope_id: Option>, + #[serde(rename = "context_references")] + pub context_references: Vec, + #[serde(rename = "external_references")] + pub external_references: Vec, + #[serde(rename = "version")] + pub version: i64, +} + +impl ScopeDescriptor { + #[allow(clippy::too_many_arguments)] + pub fn new( + scope_id: String, + title: String, + summary: String, + context_references: Vec, + external_references: Vec, + version: i64, + ) -> ScopeDescriptor { + ScopeDescriptor { + scope_id, + title, + summary, + parent_scope_id: None, + context_references, + external_references, + version, + } + } +} + +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, TS)] #[serde(deny_unknown_fields)] pub struct ScopeExternalReference { - pub r#kind: String, - pub r#value: String, + #[serde(rename = "kind")] + pub kind: String, + #[serde(rename = "value")] + pub value: String, +} + +impl ScopeExternalReference { + #[allow(clippy::too_many_arguments)] + pub fn new(kind: String, value: String) -> ScopeExternalReference { + ScopeExternalReference { kind, value } + } } -#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize, ts_rs::TS)] +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, TS)] #[serde(deny_unknown_fields)] pub struct ScopePage { - pub r#items: Vec, - #[serde(skip_serializing_if = "Option::is_none")] - #[ts(optional = nullable)] - pub r#next_cursor: Option, + #[serde(rename = "items")] + pub items: Vec, + #[ts(optional)] + #[ts(type = "string | null")] + #[serde( + rename = "next_cursor", + default, + with = "::serde_with::rust::double_option", + skip_serializing_if = "Option::is_none" + )] + pub next_cursor: Option>, +} + +impl ScopePage { + #[allow(clippy::too_many_arguments)] + pub fn new(items: Vec) -> ScopePage { + ScopePage { + items, + next_cursor: None, + } + } } -#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize, ts_rs::TS)] +#[derive( + Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, TS, Default, +)] pub enum ScopeQueryField { #[serde(rename = "scope_id")] + #[default] ScopeId, #[serde(rename = "title")] Title, @@ -448,53 +1317,129 @@ pub enum ScopeQueryField { BindingExternalId, } -#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize, ts_rs::TS)] +impl std::fmt::Display for ScopeQueryField { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + Self::ScopeId => write!(f, "scope_id"), + Self::Title => write!(f, "title"), + Self::Summary => write!(f, "summary"), + Self::ExternalReferenceValue => write!(f, "external_reference_value"), + Self::BindingExternalId => write!(f, "binding_external_id"), + } + } +} + +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, TS)] #[serde(deny_unknown_fields)] pub struct SearchMemoryRequest { - #[serde(skip_serializing_if = "Option::is_none")] - #[ts(optional = nullable)] - pub r#tag_filter: Option, - pub r#scope_id: String, - pub r#query: String, - #[serde(skip_serializing_if = "Option::is_none")] - #[ts(optional = nullable)] - pub r#limit: Option, - #[serde(skip_serializing_if = "Option::is_none")] - #[ts(optional = nullable)] - pub r#mode: Option, -} - -#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize, ts_rs::TS)] + #[ts(optional)] + #[serde(rename = "tag_filter", skip_serializing_if = "Option::is_none")] + pub tag_filter: Option, + #[serde(rename = "scope_id")] + pub scope_id: String, + #[serde(rename = "query")] + pub query: String, + #[ts(optional)] + #[serde(rename = "limit", skip_serializing_if = "Option::is_none")] + pub limit: Option, + #[ts(optional)] + #[serde(rename = "mode", skip_serializing_if = "Option::is_none")] + pub mode: Option, +} + +impl SearchMemoryRequest { + #[allow(clippy::too_many_arguments)] + pub fn new(scope_id: String, query: String) -> SearchMemoryRequest { + SearchMemoryRequest { + tag_filter: None, + scope_id, + query, + limit: None, + mode: None, + } + } +} + +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, TS)] #[serde(deny_unknown_fields)] pub struct SearchMemoryResponse { - pub r#mode: AtomicMemorySearchMode, - pub r#hits: Vec, + #[serde(rename = "mode")] + pub mode: AtomicMemorySearchMode, + #[serde(rename = "hits")] + pub hits: Vec, } -#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize, ts_rs::TS)] +impl SearchMemoryResponse { + #[allow(clippy::too_many_arguments)] + pub fn new( + mode: AtomicMemorySearchMode, + hits: Vec, + ) -> SearchMemoryResponse { + SearchMemoryResponse { mode, hits } + } +} + +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, TS)] #[serde(deny_unknown_fields)] pub struct SourceTypeReference { - pub r#source_type: String, - pub r#source_id: String, + /// Stable Source type, including dynamically registered Source names. + #[serde(rename = "source_type")] + pub source_type: String, + /// Source identity as accepted at ingestion, including Unicode and interior spaces. + #[serde(rename = "source_id")] + pub source_id: String, +} + +impl SourceTypeReference { + #[allow(clippy::too_many_arguments)] + pub fn new(source_type: String, source_id: String) -> SourceTypeReference { + SourceTypeReference { + source_type, + source_id, + } + } } -#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize, ts_rs::TS)] +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, TS)] #[serde(deny_unknown_fields)] pub struct TagFilter { - pub r#tags: Vec, - #[serde(skip_serializing_if = "Option::is_none")] - #[ts(optional = nullable)] + #[serde(rename = "tags")] + pub tags: Vec, + #[ts(optional)] + #[serde(rename = "match", skip_serializing_if = "Option::is_none")] pub r#match: Option, } -#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize, ts_rs::TS)] +impl TagFilter { + #[allow(clippy::too_many_arguments)] + pub fn new(tags: Vec) -> TagFilter { + TagFilter { + tags, + r#match: None, + } + } +} + +#[derive( + Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, TS, Default, +)] pub enum TagMatch { #[serde(rename = "all")] + #[default] All, #[serde(rename = "any")] Any, } +impl std::fmt::Display for TagMatch { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + Self::All => write!(f, "all"), + Self::Any => write!(f, "any"), + } + } +} + #[rustfmt::skip] pub fn declarations(config: &ts_rs::Config) -> Vec { vec![ @@ -514,28 +1459,42 @@ pub fn declarations(config: &ts_rs::Config) -> Vec { ::decl(config), ::decl(config), ::decl(config), + ::decl(config), ::decl(config), + ::decl(config), ::decl(config), + ::decl(config), ::decl(config), ::decl(config), ::decl(config), + ::decl(config), ::decl(config), ::decl(config), + ::decl(config), + ::decl(config), ::decl(config), ::decl(config), + ::decl(config), ::decl(config), ::decl(config), + ::decl(config), ::decl(config), ::decl(config), + ::decl(config), ::decl(config), + ::decl(config), ::decl(config), ::decl(config), ::decl(config), ::decl(config), ::decl(config), ::decl(config), + ::decl(config), ::decl(config), + ::decl(config), + ::decl(config), ::decl(config), ::decl(config), + ::decl(config), ] } diff --git a/desktop/ui/src/generated/ipc.ts b/desktop/ui/src/generated/ipc.ts index b42a1582a2..7474c29357 100644 --- a/desktop/ui/src/generated/ipc.ts +++ b/desktop/ui/src/generated/ipc.ts @@ -49,39 +49,157 @@ export type AtomicMemoryDetail = { artifact: ArtifactReference, kind: string, te export type AccessAction = "server.observe" | "server.admin" | "scope.read" | "scope.contribute" | "scope.review" | "scope.delegate" | "scope.admin" | "artifact.read" | "artifact.write" | "artifact.share" | "handoff.evidence.inspect" | "handoff.acknowledge" | "prompt.use"; export type AccessControlMode = "disabled" | "enforced"; export type AccessMeResponse = { principal: AccessPrincipal, mode: AccessControlMode, resource_kinds: Array, provider_capabilities: AccessProviderCapabilities, artifact_families: Array, }; -export type AccessPrincipal = { type: string, id: string, description?: string | null, }; +export type AccessPrincipal = { type: Type, id: string, description?: string | null, }; export type AccessProviderCapabilities = { safe_resource_filtering: boolean, multi_requirement_check: boolean, relationship_management: boolean, group_subjects: boolean, multi_principal: boolean, max_direct_resource_keys: number, }; export type AccessResourceType = "server" | "scope" | "artifact"; export type AccessRole = "handoff.viewer" | "handoff.receiver" | "artifact.viewer" | "prompt.user" | "artifact.owner" | "scope.viewer" | "scope.contributor" | "scope.reviewer" | "scope.delegator" | "scope.admin" | "server.observer" | "server.admin"; -export type ArtifactDreamingOperationCapability = { operation: DreamOperation, output_kind: string, effect: string, }; -export type ArtifactFamilyAccessCapability = { family: string, enabled: boolean, share_unit: string, actions: Array, grantable_roles: Array, }; +export type ArtifactDreamingOperationCapability = { operation: DreamOperation, output_kind: OutputKind, effect: Effect, }; +export type ArtifactFamilyAccessCapability = { family: string, enabled: boolean, share_unit: ShareUnit, actions: Array, grantable_roles: Array, }; export type ArtifactReadFamily = "memory" | "atomic-memory" | "experience" | "skill" | "handoff" | "profile" | "prompt" | "topic-memory"; export type ArtifactReference = { family: string, artifact_id: string, revision: number, }; -export type ArtifactRevision = { scope_id: string, family: ArtifactReadFamily, artifact_id: string, revision: number, content: Record, sources: Array, artifacts: Array, content_digest: string, created_at?: string | null, created_by?: AccessPrincipal | null, restored_from_revision?: number | null, reason?: string | null, }; +export type ArtifactRevision = { scope_id: string, family: ArtifactReadFamily, artifact_id: string, revision: number, content: Record, sources: Array, artifacts: Array, content_digest: string, +/** + * When this revision was committed. Absent for revisions stored before this field existed. + */ +created_at?: string | null, +/** + * Principal that committed a rollback. Ordinary revisions omit it. + */ +created_by?: AccessPrincipal | null, +/** + * Historical revision restored by this rollback. + */ +restored_from_revision?: number | null, +/** + * Reason recorded for a rollback. + */ +reason?: string | null, }; export type AtomicMemoryRecord = { artifact: ArtifactReference, kind: string, text: string, state: AtomicMemoryState, state_version: number, merged_into_id: string | null, }; -export type AtomicMemorySearchHit = { memory: AtomicMemoryRecord, score: number, matched_by: Array, }; +export type AtomicMemorySearchHit = { memory: AtomicMemoryRecord, +/** + * Raw RRF score. Hybrid mode applies the deployment's normalized relative FTS/vector weights. + */ +score: number, matched_by: Array, }; export type AtomicMemorySearchMode = "text" | "vector" | "hybrid"; export type AtomicMemoryState = "active" | "forgotten" | "merged" | "retired"; -export type Capabilities = { prompts?: { [key in string]: PromptCapability } | null, artifact_dreaming?: boolean | null, artifact_dreaming_operations?: Array | null, source_types: Array, artifact_families: Array, memory_extraction: boolean, extraction?: ExtractionStatus | null, experience_generation?: boolean | null, managed_skill_generation?: boolean | null, external_skill_registry?: boolean | null, handoff_generation: boolean, search_modes: Array, context_versions: Array, }; +export type BuiltinProfile = "coding" | "conversation"; +export type Capabilities = { prompts?: { [key in string]: PromptCapability }, +/** + * Whether asynchronous Artifact Dream execution is configured. + */ +artifact_dreaming?: boolean, +/** + * Dream operations enabled by the current Runtime, including their reviewed effect. + */ +artifact_dreaming_operations?: Array, source_types: Array, artifact_families: Array, +/** + * Whether pending Sources can be extracted into Memory. + */ +memory_extraction: boolean, extraction?: ExtractionStatus, +/** + * Whether the configured model can generate reviewed Experience Candidates. + */ +experience_generation?: boolean, +/** + * Whether the configured model can generate reviewed managed Skill Candidates. + */ +managed_skill_generation?: boolean, +/** + * Whether host-local external Skill discovery and exact resolution are configured. + */ +external_skill_registry?: boolean, +/** + * Whether exact evidence can be generated into an inspectable Handoff Draft. + */ +handoff_generation: boolean, search_modes: Array, context_versions: Array, }; +export type Configuration = "configured" | "unconfigured" | "unknown"; export type DreamOperation = "refine_experience" | "derive_skill" | "revise_skill" | "revise_profile" | "revise_memory" | "revise_topic_memory" | "refresh_handoff" | "revise_prompt" | "revise_tags"; -export type ExtractionBackground = { location: string, role?: string | null, state: string, automatic_processing_enabled?: boolean | null, }; -export type ExtractionFailure = { code: string, stage: string, occurred_at: string, }; -export type ExtractionObservation = { status: string, since: string, last_failure?: ExtractionFailure | null, last_success_at?: string | null, }; -export type ExtractionStatus = { configuration: string, background: ExtractionBackground, observation: ExtractionObservation, }; +export type Effect = "review_then_publish" | "review_then_publish_configuration" | "review_then_replace_tags"; +export type ExtractionBackground = { +/** + * Placement of the Memory Supervisor. None means no background executor; synchronous flush may still work. + */ +location: Location, +/** + * Current local Supervisor leadership role. Standby is normal; null means no running local Supervisor. + */ +role?: Role | null, +/** + * Local Supervisor lifecycle and control state, independent of individual worker outcomes. A running Supervisor may be retrying failed workers. External state is unknown. + */ +state: State, +/** + * Whether this process schedules automatic Memory extraction. False still permits explicit flush and recovery of accepted work. Null means the external worker schedule is unknown. + */ +automatic_processing_enabled?: boolean | null, }; +export type ExtractionFailure = { +/** + * Sanitized category: model_configuration_error, model_timeout, model_unavailable, invalid_model_output, worker_timeout, worker_crash, invalid_worker_result, missing_durable_acknowledgement, supervisor_failed, lease_renewal_failed, scope_discovery_failed, or processing_failed. Raw exception messages, model inputs, and credentials are never returned. + */ +code: string, +/** + * Inference for recognized model failures; otherwise the boundary where failure was observed. Flush or worker does not identify the failing internal component. + */ +stage: Stage, +/** + * UTC time when this process observed the failure. + */ +occurred_at: string, }; +export type ExtractionObservation = { +/** + * Unverified means no execution outcome or control failure has been observed in this window. Observed means at least one success or failure is recorded; neither value is a health verdict. + */ +status: ExtractionObservationStatus, +/** + * UTC start of this Runtime's observation window. Records cover this process and its child Memory workers, reset on Runtime restart, and do not include remote workers or a durable per-Scope failure history. + */ +since: string, last_failure?: ExtractionFailure, +/** + * UTC time of the most recent local successful nonempty synchronous flush or acknowledged Memory worker invocation. This does not prove that a model was called or that any previous failure has recovered. + */ +last_success_at?: string | null, }; +export type ExtractionObservationStatus = "unverified" | "observed"; +export type ExtractionStatus = { +/** + * Whether a local extraction model or custom pipeline is assembled. Configured does not verify credentials or connectivity. Unknown means execution is external and its configuration is not observed. + */ +configuration: Configuration, background: ExtractionBackground, observation: ExtractionObservation, }; export type HealthResponse = { status: string, }; +export type Location = "local" | "external" | "none"; +export type MatchedBy = "text" | "vector"; export type MemoryMutationResponse = { changed: boolean, records: Array, }; export type MemorySearchMode = "auto" | "fts" | "vector" | "hybrid"; +export type OutputKind = "candidate" | "tag_candidate"; export type PreparedContextSchema = "powercontext.prepared-context.v1"; -export type PromptCapability = { status: string, reason: string | null, definition_version: string, builtin_version: string, builtin_profile: string | null, }; +export type PromptCapability = { status: PromptCapabilityStatus, reason: Reason | null, definition_version: string, builtin_version: string, builtin_profile: BuiltinProfile | null, }; +export type PromptCapabilityStatus = "supported" | "disabled" | "unsupported"; export type ReadinessResponse = { status: ReadinessStatus, checks: { [key in string]: string }, }; export type ReadinessStatus = "ready" | "degraded" | "not_ready"; -export type RememberMemoryRequest = { scope_id: string, kind: string, text: string, reason?: string | null, expected_revision?: number | null, }; +export type Reason = "operation_disabled" | "provider_not_configured" | "injected_component"; +export type RememberMemoryRequest = { scope_id: string, kind: string, +/** + * Must not exceed 8192 UTF-8 bytes after normalization. + */ +text: string, reason?: string | null, expected_revision?: number | null, }; +export type Role = "leader" | "standby"; export type ScopeDescriptor = { scope_id: string, title: string, summary: string, parent_scope_id?: string | null, context_references: Array, external_references: Array, version: number, }; export type ScopeExternalReference = { kind: string, value: string, }; export type ScopePage = { items: Array, next_cursor?: string | null, }; export type ScopeQueryField = "scope_id" | "title" | "summary" | "external_reference_value" | "binding_external_id"; -export type SearchMemoryRequest = { tag_filter?: TagFilter | null, scope_id: string, query: string, limit?: number | null, mode?: MemorySearchMode | null, }; +export type SearchMemoryRequest = { tag_filter?: TagFilter, scope_id: string, query: string, limit?: number, mode?: MemorySearchMode, }; export type SearchMemoryResponse = { mode: AtomicMemorySearchMode, hits: Array, }; -export type SourceTypeReference = { source_type: string, source_id: string, }; -export type TagFilter = { tags: Array, match?: TagMatch | null, }; +export type ShareUnit = "artifact" | "memory_entry"; +export type SourceTypeReference = { +/** + * Stable Source type, including dynamically registered Source names. + */ +source_type: string, +/** + * Source identity as accepted at ingestion, including Unicode and interior spaces. + */ +source_id: string, }; +export type Stage = "inference" | "flush" | "worker" | "supervisor" | "lease_renewal" | "scope_discovery"; +export type State = "running" | "degraded" | "stopped" | "unknown"; +export type TagFilter = { tags: Array, match?: TagMatch, }; export type TagMatch = "all" | "any"; +export type Type = "user" | "service";