├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .vscode ├── .gitignore └── settings.json ├── README.md ├── eslint.config.mjs ├── hands-please.gif ├── package.json ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── renovate.json ├── src ├── bin-test.ts ├── bin.ts ├── comment.test.ts ├── comment.ts ├── ignore.ts ├── loop.ts ├── message.test.ts ├── message.ts ├── spinner.ts └── watch.ts ├── tsconfig.json └── tsup.config.ts /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: 🚀 ci 2 | on: 3 | push: 4 | branches: ["main"] 5 | pull_request: 6 | types: [opened, synchronize] 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-24.04 11 | strategy: 12 | matrix: 13 | node-version: [22] 14 | env: 15 | CHECK: "pnpm check" 16 | steps: 17 | - uses: actions/checkout@v4 18 | - name: setup pnpm 19 | uses: pnpm/action-setup@v4 20 | with: 21 | version: 10.10.0 22 | - name: use node ${{ matrix.node-version }} 23 | uses: actions/setup-node@v4 24 | with: 25 | node-version: ${{ matrix.node-version }} 26 | cache: "pnpm" 27 | - name: pnpm install 28 | run: pnpm install 29 | - name: pnpm build 30 | run: pnpm build 31 | - name: pnpm check 32 | run: pnpm check 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | .env 4 | -------------------------------------------------------------------------------- /.vscode/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | .env 4 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.tsdk": "node_modules/typescript/lib" 3 | } 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ![hands-please](https://github.com/joseferben/hands-please/blob/main/hands-please.gif) 4 | 5 | # hands-please 🫱 6 | 7 | `hands-please` 8 | 9 | 1. Watch codebase for `// @ai fix this code` 10 | 2. Run an agent like Claude Code in the background with the prompt from the comment until lint/build passes 11 | 12 | ## Example 13 | 14 | ```bash 15 | $ npx hands-please@latest --agent 'claude --print --output-format stream-json --verbose --allowedTools "Edit,Write,WebFetch"' --check 'npm run check' --file-check 'npm run lint' 16 | ``` 17 | 18 | Add a comment: 19 | 20 | ```typescript 21 | // @ai add a test case to divide by 0 22 | describe("division", () => { 23 | it("should divide 10 by 2", () => { 24 | expect(10 / 2).toBe(5); 25 | }); 26 | }); 27 | ``` 28 | 29 | ```bash 30 | $ npx hands-please@latest --agent 'claude --print --output-format stream-json --verbose --allowedTools "Edit,Write,WebFetch"' --check 'npm run check' --file-check 'npm run lint' 31 | ⠏ Watching for comments with "@ai".... 32 | ℹ 🫱 Processing comment src/math.test.ts:194 33 | ℹ 🤖 I'll implement the test case for division by zero as requested in the comment. 34 | ℹ 🤖 Added test case that verifies division by zero returns Infinity in JavaScript. 35 | ℹ 💸 $0.04 in 12.38s 36 | ℹ ✓ $ npm run lint 37 | ℹ ✓ $ npm run check 38 | ℹ ✓ All checks passed 39 | ⠙ Watching files for "@ai".... 40 | ``` 41 | 42 | ## Configuration 43 | 44 | `hands-please` is configured using command line arguments: 45 | 46 | ```bash 47 | # Basic usage 48 | npx hands-please --agent --check --file-check [options] 49 | 50 | # Options: 51 | # --agent The command to run the AI agent in non-interactive mode(required) 52 | # --check The command to check the codebase (required) 53 | # --file-check The command to check specific files (required) 54 | # --trigger The tag that triggers comment processing (default: "@ai") 55 | # --skip-watch Exit after processing all comments (default: false) 56 | ``` 57 | 58 | Example for Claude Code: 59 | 60 | ```bash 61 | pnpm dlx hands-please@latest \ 62 | --agent 'claude --print --output-format stream-json --verbose --allowedTools "Edit,Write,WebFetch"' \ 63 | --check 'pnpm check' \ 64 | --file-check 'pnpm lint' 65 | ``` 66 | 67 | ## Motivation 68 | 69 | I wanted the productivity of vibe coding without the mess: Running local coding agents with surgical precision based on comments. 70 | 71 | There is no chat interface, the only way to interact with the code agents is through code comments. 72 | 73 | Workflow: 74 | 75 | 1. Pick up a comment containing `@ai` 76 | 2. Run agent with prompt from comment or linting issues 77 | 3. Run file-check command on changed files, on error go to 2. 78 | 4. Run full codebase check command, on error go to 2. 79 | 5. => Done! Process next comment. 80 | 81 | For `hands-please` to work well it's important to provide a file-specific check using the `--file-check` option like `eslint` that works with `eslint `. This allows `hands-please` to run checks only on changed files and provide feedback to the code agent that is relevant to the changes it made. => Super fast feedback loop! 82 | 83 | ## Inspiration 84 | 85 | - [aider](https://github.com/Aider-AI/aider): For the comment-based code agent 86 | - [Claude Code](https://docs.anthropic.com/en/docs/claude-code/): For the DX and the nice auto-mode experience 87 | -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | 3 | import eslint from "@eslint/js"; 4 | import tseslint from "typescript-eslint"; 5 | 6 | export default tseslint.config( 7 | eslint.configs.recommended, 8 | tseslint.configs.recommendedTypeChecked, 9 | { 10 | languageOptions: { 11 | parserOptions: { 12 | projectService: true, 13 | tsconfigRootDir: import.meta.dirname, 14 | }, 15 | }, 16 | }, 17 | { 18 | ignores: ["node_modules", "dist"], 19 | } 20 | ); 21 | -------------------------------------------------------------------------------- /hands-please.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joseferben/hands-please/0f480e741e35bfca8827c3a7a9b902a62ca31203/hands-please.gif -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hands-please", 3 | "version": "0.0.5", 4 | "type": "module", 5 | "description": "Run CLI code agents based on comments in your codebase.", 6 | "files": [ 7 | "dist", 8 | "README.md" 9 | ], 10 | "bin": { 11 | "hands": "dist/bin.js", 12 | "hands-please": "dist/bin.js" 13 | }, 14 | "scripts": { 15 | "dev": "tsup --watch", 16 | "build": "tsup", 17 | "lint": "eslint", 18 | "typecheck": "tsc --noEmit", 19 | "test": "vitest run", 20 | "check": "pnpm typecheck && pnpm lint && pnpm test" 21 | }, 22 | "author": "Josef Erben ", 23 | "license": "MIT", 24 | "packageManager": "pnpm@10.10.0", 25 | "devDependencies": { 26 | "@eslint/js": "^9.27.0", 27 | "@tsconfig/strictest": "^2.0.5", 28 | "@types/node": "^22.15.18", 29 | "@types/shell-quote": "^1.7.5", 30 | "ai": "^4.3.16", 31 | "eslint": "^9.27.0", 32 | "tsup": "^8.5.0", 33 | "tsx": "^4.19.4", 34 | "typescript": "^5.8.3", 35 | "typescript-eslint": "^8.32.1", 36 | "vitest": "^3.1.3" 37 | }, 38 | "dependencies": { 39 | "chokidar": "^4.0.3", 40 | "citty": "^0.1.6", 41 | "consola": "^3.4.2", 42 | "dotenv": "^16.5.0", 43 | "ignore": "^7.0.4", 44 | "minimatch": "^10.0.1", 45 | "ora": "^8.2.0", 46 | "shell-quote": "^1.8.2", 47 | "zod": "^3.24.4" 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '9.0' 2 | 3 | settings: 4 | autoInstallPeers: true 5 | excludeLinksFromLockfile: false 6 | 7 | importers: 8 | 9 | .: 10 | dependencies: 11 | chokidar: 12 | specifier: ^4.0.3 13 | version: 4.0.3 14 | citty: 15 | specifier: ^0.1.6 16 | version: 0.1.6 17 | consola: 18 | specifier: ^3.4.2 19 | version: 3.4.2 20 | dotenv: 21 | specifier: ^16.5.0 22 | version: 16.5.0 23 | ignore: 24 | specifier: ^7.0.4 25 | version: 7.0.5 26 | minimatch: 27 | specifier: ^10.0.1 28 | version: 10.0.1 29 | ora: 30 | specifier: ^8.2.0 31 | version: 8.2.0 32 | shell-quote: 33 | specifier: ^1.8.2 34 | version: 1.8.2 35 | zod: 36 | specifier: ^3.24.4 37 | version: 3.25.42 38 | devDependencies: 39 | '@eslint/js': 40 | specifier: ^9.27.0 41 | version: 9.28.0 42 | '@tsconfig/strictest': 43 | specifier: ^2.0.5 44 | version: 2.0.5 45 | '@types/node': 46 | specifier: ^22.15.18 47 | version: 22.15.29 48 | '@types/shell-quote': 49 | specifier: ^1.7.5 50 | version: 1.7.5 51 | ai: 52 | specifier: ^4.3.16 53 | version: 4.3.16(react@19.1.0)(zod@3.25.42) 54 | eslint: 55 | specifier: ^9.27.0 56 | version: 9.28.0 57 | tsup: 58 | specifier: ^8.5.0 59 | version: 8.5.0(postcss@8.5.3)(tsx@4.19.4)(typescript@5.8.3) 60 | tsx: 61 | specifier: ^4.19.4 62 | version: 4.19.4 63 | typescript: 64 | specifier: ^5.8.3 65 | version: 5.8.3 66 | typescript-eslint: 67 | specifier: ^8.32.1 68 | version: 8.33.0(eslint@9.28.0)(typescript@5.8.3) 69 | vitest: 70 | specifier: ^3.1.3 71 | version: 3.1.4(@types/node@22.15.29)(tsx@4.19.4) 72 | 73 | packages: 74 | 75 | '@ai-sdk/provider-utils@2.2.8': 76 | resolution: {integrity: sha512-fqhG+4sCVv8x7nFzYnFo19ryhAa3w096Kmc3hWxMQfW/TubPOmt3A6tYZhl4mUfQWWQMsuSkLrtjlWuXBVSGQA==} 77 | engines: {node: '>=18'} 78 | peerDependencies: 79 | zod: ^3.23.8 80 | 81 | '@ai-sdk/provider@1.1.3': 82 | resolution: {integrity: sha512-qZMxYJ0qqX/RfnuIaab+zp8UAeJn/ygXXAffR5I4N0n1IrvA6qBsjc8hXLmBiMV2zoXlifkacF7sEFnYnjBcqg==} 83 | engines: {node: '>=18'} 84 | 85 | '@ai-sdk/react@1.2.12': 86 | resolution: {integrity: sha512-jK1IZZ22evPZoQW3vlkZ7wvjYGYF+tRBKXtrcolduIkQ/m/sOAVcVeVDUDvh1T91xCnWCdUGCPZg2avZ90mv3g==} 87 | engines: {node: '>=18'} 88 | peerDependencies: 89 | react: ^18 || ^19 || ^19.0.0-rc 90 | zod: ^3.23.8 91 | peerDependenciesMeta: 92 | zod: 93 | optional: true 94 | 95 | '@ai-sdk/ui-utils@1.2.11': 96 | resolution: {integrity: sha512-3zcwCc8ezzFlwp3ZD15wAPjf2Au4s3vAbKsXQVyhxODHcmu0iyPO2Eua6D/vicq/AUm/BAo60r97O6HU+EI0+w==} 97 | engines: {node: '>=18'} 98 | peerDependencies: 99 | zod: ^3.23.8 100 | 101 | '@esbuild/aix-ppc64@0.25.4': 102 | resolution: {integrity: sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q==} 103 | engines: {node: '>=18'} 104 | cpu: [ppc64] 105 | os: [aix] 106 | 107 | '@esbuild/android-arm64@0.25.4': 108 | resolution: {integrity: sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A==} 109 | engines: {node: '>=18'} 110 | cpu: [arm64] 111 | os: [android] 112 | 113 | '@esbuild/android-arm@0.25.4': 114 | resolution: {integrity: sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ==} 115 | engines: {node: '>=18'} 116 | cpu: [arm] 117 | os: [android] 118 | 119 | '@esbuild/android-x64@0.25.4': 120 | resolution: {integrity: sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ==} 121 | engines: {node: '>=18'} 122 | cpu: [x64] 123 | os: [android] 124 | 125 | '@esbuild/darwin-arm64@0.25.4': 126 | resolution: {integrity: sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g==} 127 | engines: {node: '>=18'} 128 | cpu: [arm64] 129 | os: [darwin] 130 | 131 | '@esbuild/darwin-x64@0.25.4': 132 | resolution: {integrity: sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A==} 133 | engines: {node: '>=18'} 134 | cpu: [x64] 135 | os: [darwin] 136 | 137 | '@esbuild/freebsd-arm64@0.25.4': 138 | resolution: {integrity: sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ==} 139 | engines: {node: '>=18'} 140 | cpu: [arm64] 141 | os: [freebsd] 142 | 143 | '@esbuild/freebsd-x64@0.25.4': 144 | resolution: {integrity: sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ==} 145 | engines: {node: '>=18'} 146 | cpu: [x64] 147 | os: [freebsd] 148 | 149 | '@esbuild/linux-arm64@0.25.4': 150 | resolution: {integrity: sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ==} 151 | engines: {node: '>=18'} 152 | cpu: [arm64] 153 | os: [linux] 154 | 155 | '@esbuild/linux-arm@0.25.4': 156 | resolution: {integrity: sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ==} 157 | engines: {node: '>=18'} 158 | cpu: [arm] 159 | os: [linux] 160 | 161 | '@esbuild/linux-ia32@0.25.4': 162 | resolution: {integrity: sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ==} 163 | engines: {node: '>=18'} 164 | cpu: [ia32] 165 | os: [linux] 166 | 167 | '@esbuild/linux-loong64@0.25.4': 168 | resolution: {integrity: sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA==} 169 | engines: {node: '>=18'} 170 | cpu: [loong64] 171 | os: [linux] 172 | 173 | '@esbuild/linux-mips64el@0.25.4': 174 | resolution: {integrity: sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg==} 175 | engines: {node: '>=18'} 176 | cpu: [mips64el] 177 | os: [linux] 178 | 179 | '@esbuild/linux-ppc64@0.25.4': 180 | resolution: {integrity: sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag==} 181 | engines: {node: '>=18'} 182 | cpu: [ppc64] 183 | os: [linux] 184 | 185 | '@esbuild/linux-riscv64@0.25.4': 186 | resolution: {integrity: sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA==} 187 | engines: {node: '>=18'} 188 | cpu: [riscv64] 189 | os: [linux] 190 | 191 | '@esbuild/linux-s390x@0.25.4': 192 | resolution: {integrity: sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g==} 193 | engines: {node: '>=18'} 194 | cpu: [s390x] 195 | os: [linux] 196 | 197 | '@esbuild/linux-x64@0.25.4': 198 | resolution: {integrity: sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA==} 199 | engines: {node: '>=18'} 200 | cpu: [x64] 201 | os: [linux] 202 | 203 | '@esbuild/netbsd-arm64@0.25.4': 204 | resolution: {integrity: sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ==} 205 | engines: {node: '>=18'} 206 | cpu: [arm64] 207 | os: [netbsd] 208 | 209 | '@esbuild/netbsd-x64@0.25.4': 210 | resolution: {integrity: sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw==} 211 | engines: {node: '>=18'} 212 | cpu: [x64] 213 | os: [netbsd] 214 | 215 | '@esbuild/openbsd-arm64@0.25.4': 216 | resolution: {integrity: sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A==} 217 | engines: {node: '>=18'} 218 | cpu: [arm64] 219 | os: [openbsd] 220 | 221 | '@esbuild/openbsd-x64@0.25.4': 222 | resolution: {integrity: sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw==} 223 | engines: {node: '>=18'} 224 | cpu: [x64] 225 | os: [openbsd] 226 | 227 | '@esbuild/sunos-x64@0.25.4': 228 | resolution: {integrity: sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q==} 229 | engines: {node: '>=18'} 230 | cpu: [x64] 231 | os: [sunos] 232 | 233 | '@esbuild/win32-arm64@0.25.4': 234 | resolution: {integrity: sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ==} 235 | engines: {node: '>=18'} 236 | cpu: [arm64] 237 | os: [win32] 238 | 239 | '@esbuild/win32-ia32@0.25.4': 240 | resolution: {integrity: sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg==} 241 | engines: {node: '>=18'} 242 | cpu: [ia32] 243 | os: [win32] 244 | 245 | '@esbuild/win32-x64@0.25.4': 246 | resolution: {integrity: sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ==} 247 | engines: {node: '>=18'} 248 | cpu: [x64] 249 | os: [win32] 250 | 251 | '@eslint-community/eslint-utils@4.7.0': 252 | resolution: {integrity: sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==} 253 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 254 | peerDependencies: 255 | eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 256 | 257 | '@eslint-community/regexpp@4.12.1': 258 | resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} 259 | engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} 260 | 261 | '@eslint/config-array@0.20.0': 262 | resolution: {integrity: sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==} 263 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 264 | 265 | '@eslint/config-helpers@0.2.2': 266 | resolution: {integrity: sha512-+GPzk8PlG0sPpzdU5ZvIRMPidzAnZDl/s9L+y13iodqvb8leL53bTannOrQ/Im7UkpsmFU5Ily5U60LWixnmLg==} 267 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 268 | 269 | '@eslint/core@0.14.0': 270 | resolution: {integrity: sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==} 271 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 272 | 273 | '@eslint/eslintrc@3.3.1': 274 | resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} 275 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 276 | 277 | '@eslint/js@9.28.0': 278 | resolution: {integrity: sha512-fnqSjGWd/CoIp4EXIxWVK/sHA6DOHN4+8Ix2cX5ycOY7LG0UY8nHCU5pIp2eaE1Mc7Qd8kHspYNzYXT2ojPLzg==} 279 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 280 | 281 | '@eslint/object-schema@2.1.6': 282 | resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==} 283 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 284 | 285 | '@eslint/plugin-kit@0.3.1': 286 | resolution: {integrity: sha512-0J+zgWxHN+xXONWIyPWKFMgVuJoZuGiIFu8yxk7RJjxkzpGmyja5wRFqZIVtjDVOQpV+Rw0iOAjYPE2eQyjr0w==} 287 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 288 | 289 | '@humanfs/core@0.19.1': 290 | resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} 291 | engines: {node: '>=18.18.0'} 292 | 293 | '@humanfs/node@0.16.6': 294 | resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==} 295 | engines: {node: '>=18.18.0'} 296 | 297 | '@humanwhocodes/module-importer@1.0.1': 298 | resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} 299 | engines: {node: '>=12.22'} 300 | 301 | '@humanwhocodes/retry@0.3.1': 302 | resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} 303 | engines: {node: '>=18.18'} 304 | 305 | '@humanwhocodes/retry@0.4.3': 306 | resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} 307 | engines: {node: '>=18.18'} 308 | 309 | '@isaacs/cliui@8.0.2': 310 | resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} 311 | engines: {node: '>=12'} 312 | 313 | '@jridgewell/gen-mapping@0.3.8': 314 | resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} 315 | engines: {node: '>=6.0.0'} 316 | 317 | '@jridgewell/resolve-uri@3.1.2': 318 | resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} 319 | engines: {node: '>=6.0.0'} 320 | 321 | '@jridgewell/set-array@1.2.1': 322 | resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} 323 | engines: {node: '>=6.0.0'} 324 | 325 | '@jridgewell/sourcemap-codec@1.5.0': 326 | resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} 327 | 328 | '@jridgewell/trace-mapping@0.3.25': 329 | resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} 330 | 331 | '@nodelib/fs.scandir@2.1.5': 332 | resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} 333 | engines: {node: '>= 8'} 334 | 335 | '@nodelib/fs.stat@2.0.5': 336 | resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} 337 | engines: {node: '>= 8'} 338 | 339 | '@nodelib/fs.walk@1.2.8': 340 | resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} 341 | engines: {node: '>= 8'} 342 | 343 | '@opentelemetry/api@1.9.0': 344 | resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==} 345 | engines: {node: '>=8.0.0'} 346 | 347 | '@pkgjs/parseargs@0.11.0': 348 | resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} 349 | engines: {node: '>=14'} 350 | 351 | '@rollup/rollup-android-arm-eabi@4.41.1': 352 | resolution: {integrity: sha512-NELNvyEWZ6R9QMkiytB4/L4zSEaBC03KIXEghptLGLZWJ6VPrL63ooZQCOnlx36aQPGhzuOMwDerC1Eb2VmrLw==} 353 | cpu: [arm] 354 | os: [android] 355 | 356 | '@rollup/rollup-android-arm64@4.41.1': 357 | resolution: {integrity: sha512-DXdQe1BJ6TK47ukAoZLehRHhfKnKg9BjnQYUu9gzhI8Mwa1d2fzxA1aw2JixHVl403bwp1+/o/NhhHtxWJBgEA==} 358 | cpu: [arm64] 359 | os: [android] 360 | 361 | '@rollup/rollup-darwin-arm64@4.41.1': 362 | resolution: {integrity: sha512-5afxvwszzdulsU2w8JKWwY8/sJOLPzf0e1bFuvcW5h9zsEg+RQAojdW0ux2zyYAz7R8HvvzKCjLNJhVq965U7w==} 363 | cpu: [arm64] 364 | os: [darwin] 365 | 366 | '@rollup/rollup-darwin-x64@4.41.1': 367 | resolution: {integrity: sha512-egpJACny8QOdHNNMZKf8xY0Is6gIMz+tuqXlusxquWu3F833DcMwmGM7WlvCO9sB3OsPjdC4U0wHw5FabzCGZg==} 368 | cpu: [x64] 369 | os: [darwin] 370 | 371 | '@rollup/rollup-freebsd-arm64@4.41.1': 372 | resolution: {integrity: sha512-DBVMZH5vbjgRk3r0OzgjS38z+atlupJ7xfKIDJdZZL6sM6wjfDNo64aowcLPKIx7LMQi8vybB56uh1Ftck/Atg==} 373 | cpu: [arm64] 374 | os: [freebsd] 375 | 376 | '@rollup/rollup-freebsd-x64@4.41.1': 377 | resolution: {integrity: sha512-3FkydeohozEskBxNWEIbPfOE0aqQgB6ttTkJ159uWOFn42VLyfAiyD9UK5mhu+ItWzft60DycIN1Xdgiy8o/SA==} 378 | cpu: [x64] 379 | os: [freebsd] 380 | 381 | '@rollup/rollup-linux-arm-gnueabihf@4.41.1': 382 | resolution: {integrity: sha512-wC53ZNDgt0pqx5xCAgNunkTzFE8GTgdZ9EwYGVcg+jEjJdZGtq9xPjDnFgfFozQI/Xm1mh+D9YlYtl+ueswNEg==} 383 | cpu: [arm] 384 | os: [linux] 385 | 386 | '@rollup/rollup-linux-arm-musleabihf@4.41.1': 387 | resolution: {integrity: sha512-jwKCca1gbZkZLhLRtsrka5N8sFAaxrGz/7wRJ8Wwvq3jug7toO21vWlViihG85ei7uJTpzbXZRcORotE+xyrLA==} 388 | cpu: [arm] 389 | os: [linux] 390 | 391 | '@rollup/rollup-linux-arm64-gnu@4.41.1': 392 | resolution: {integrity: sha512-g0UBcNknsmmNQ8V2d/zD2P7WWfJKU0F1nu0k5pW4rvdb+BIqMm8ToluW/eeRmxCared5dD76lS04uL4UaNgpNA==} 393 | cpu: [arm64] 394 | os: [linux] 395 | 396 | '@rollup/rollup-linux-arm64-musl@4.41.1': 397 | resolution: {integrity: sha512-XZpeGB5TKEZWzIrj7sXr+BEaSgo/ma/kCgrZgL0oo5qdB1JlTzIYQKel/RmhT6vMAvOdM2teYlAaOGJpJ9lahg==} 398 | cpu: [arm64] 399 | os: [linux] 400 | 401 | '@rollup/rollup-linux-loongarch64-gnu@4.41.1': 402 | resolution: {integrity: sha512-bkCfDJ4qzWfFRCNt5RVV4DOw6KEgFTUZi2r2RuYhGWC8WhCA8lCAJhDeAmrM/fdiAH54m0mA0Vk2FGRPyzI+tw==} 403 | cpu: [loong64] 404 | os: [linux] 405 | 406 | '@rollup/rollup-linux-powerpc64le-gnu@4.41.1': 407 | resolution: {integrity: sha512-3mr3Xm+gvMX+/8EKogIZSIEF0WUu0HL9di+YWlJpO8CQBnoLAEL/roTCxuLncEdgcfJcvA4UMOf+2dnjl4Ut1A==} 408 | cpu: [ppc64] 409 | os: [linux] 410 | 411 | '@rollup/rollup-linux-riscv64-gnu@4.41.1': 412 | resolution: {integrity: sha512-3rwCIh6MQ1LGrvKJitQjZFuQnT2wxfU+ivhNBzmxXTXPllewOF7JR1s2vMX/tWtUYFgphygxjqMl76q4aMotGw==} 413 | cpu: [riscv64] 414 | os: [linux] 415 | 416 | '@rollup/rollup-linux-riscv64-musl@4.41.1': 417 | resolution: {integrity: sha512-LdIUOb3gvfmpkgFZuccNa2uYiqtgZAz3PTzjuM5bH3nvuy9ty6RGc/Q0+HDFrHrizJGVpjnTZ1yS5TNNjFlklw==} 418 | cpu: [riscv64] 419 | os: [linux] 420 | 421 | '@rollup/rollup-linux-s390x-gnu@4.41.1': 422 | resolution: {integrity: sha512-oIE6M8WC9ma6xYqjvPhzZYk6NbobIURvP/lEbh7FWplcMO6gn7MM2yHKA1eC/GvYwzNKK/1LYgqzdkZ8YFxR8g==} 423 | cpu: [s390x] 424 | os: [linux] 425 | 426 | '@rollup/rollup-linux-x64-gnu@4.41.1': 427 | resolution: {integrity: sha512-cWBOvayNvA+SyeQMp79BHPK8ws6sHSsYnK5zDcsC3Hsxr1dgTABKjMnMslPq1DvZIp6uO7kIWhiGwaTdR4Og9A==} 428 | cpu: [x64] 429 | os: [linux] 430 | 431 | '@rollup/rollup-linux-x64-musl@4.41.1': 432 | resolution: {integrity: sha512-y5CbN44M+pUCdGDlZFzGGBSKCA4A/J2ZH4edTYSSxFg7ce1Xt3GtydbVKWLlzL+INfFIZAEg1ZV6hh9+QQf9YQ==} 433 | cpu: [x64] 434 | os: [linux] 435 | 436 | '@rollup/rollup-win32-arm64-msvc@4.41.1': 437 | resolution: {integrity: sha512-lZkCxIrjlJlMt1dLO/FbpZbzt6J/A8p4DnqzSa4PWqPEUUUnzXLeki/iyPLfV0BmHItlYgHUqJe+3KiyydmiNQ==} 438 | cpu: [arm64] 439 | os: [win32] 440 | 441 | '@rollup/rollup-win32-ia32-msvc@4.41.1': 442 | resolution: {integrity: sha512-+psFT9+pIh2iuGsxFYYa/LhS5MFKmuivRsx9iPJWNSGbh2XVEjk90fmpUEjCnILPEPJnikAU6SFDiEUyOv90Pg==} 443 | cpu: [ia32] 444 | os: [win32] 445 | 446 | '@rollup/rollup-win32-x64-msvc@4.41.1': 447 | resolution: {integrity: sha512-Wq2zpapRYLfi4aKxf2Xff0tN+7slj2d4R87WEzqw7ZLsVvO5zwYCIuEGSZYiK41+GlwUo1HiR+GdkLEJnCKTCw==} 448 | cpu: [x64] 449 | os: [win32] 450 | 451 | '@tsconfig/strictest@2.0.5': 452 | resolution: {integrity: sha512-ec4tjL2Rr0pkZ5hww65c+EEPYwxOi4Ryv+0MtjeaSQRJyq322Q27eOQiFbuNgw2hpL4hB1/W/HBGk3VKS43osg==} 453 | 454 | '@types/diff-match-patch@1.0.36': 455 | resolution: {integrity: sha512-xFdR6tkm0MWvBfO8xXCSsinYxHcqkQUlcHeSpMC2ukzOb6lwQAfDmW+Qt0AvlGd8HpsS28qKsB+oPeJn9I39jg==} 456 | 457 | '@types/estree@1.0.7': 458 | resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==} 459 | 460 | '@types/json-schema@7.0.15': 461 | resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} 462 | 463 | '@types/node@22.15.29': 464 | resolution: {integrity: sha512-LNdjOkUDlU1RZb8e1kOIUpN1qQUlzGkEtbVNo53vbrwDg5om6oduhm4SiUaPW5ASTXhAiP0jInWG8Qx9fVlOeQ==} 465 | 466 | '@types/shell-quote@1.7.5': 467 | resolution: {integrity: sha512-+UE8GAGRPbJVQDdxi16dgadcBfQ+KG2vgZhV1+3A1XmHbmwcdwhCUwIdy+d3pAGrbvgRoVSjeI9vOWyq376Yzw==} 468 | 469 | '@typescript-eslint/eslint-plugin@8.33.0': 470 | resolution: {integrity: sha512-CACyQuqSHt7ma3Ns601xykeBK/rDeZa3w6IS6UtMQbixO5DWy+8TilKkviGDH6jtWCo8FGRKEK5cLLkPvEammQ==} 471 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 472 | peerDependencies: 473 | '@typescript-eslint/parser': ^8.33.0 474 | eslint: ^8.57.0 || ^9.0.0 475 | typescript: '>=4.8.4 <5.9.0' 476 | 477 | '@typescript-eslint/parser@8.33.0': 478 | resolution: {integrity: sha512-JaehZvf6m0yqYp34+RVnihBAChkqeH+tqqhS0GuX1qgPpwLvmTPheKEs6OeCK6hVJgXZHJ2vbjnC9j119auStQ==} 479 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 480 | peerDependencies: 481 | eslint: ^8.57.0 || ^9.0.0 482 | typescript: '>=4.8.4 <5.9.0' 483 | 484 | '@typescript-eslint/project-service@8.33.0': 485 | resolution: {integrity: sha512-d1hz0u9l6N+u/gcrk6s6gYdl7/+pp8yHheRTqP6X5hVDKALEaTn8WfGiit7G511yueBEL3OpOEpD+3/MBdoN+A==} 486 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 487 | 488 | '@typescript-eslint/scope-manager@8.33.0': 489 | resolution: {integrity: sha512-LMi/oqrzpqxyO72ltP+dBSP6V0xiUb4saY7WLtxSfiNEBI8m321LLVFU9/QDJxjDQG9/tjSqKz/E3380TEqSTw==} 490 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 491 | 492 | '@typescript-eslint/tsconfig-utils@8.33.0': 493 | resolution: {integrity: sha512-sTkETlbqhEoiFmGr1gsdq5HyVbSOF0145SYDJ/EQmXHtKViCaGvnyLqWFFHtEXoS0J1yU8Wyou2UGmgW88fEug==} 494 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 495 | peerDependencies: 496 | typescript: '>=4.8.4 <5.9.0' 497 | 498 | '@typescript-eslint/type-utils@8.33.0': 499 | resolution: {integrity: sha512-lScnHNCBqL1QayuSrWeqAL5GmqNdVUQAAMTaCwdYEdWfIrSrOGzyLGRCHXcCixa5NK6i5l0AfSO2oBSjCjf4XQ==} 500 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 501 | peerDependencies: 502 | eslint: ^8.57.0 || ^9.0.0 503 | typescript: '>=4.8.4 <5.9.0' 504 | 505 | '@typescript-eslint/types@8.33.0': 506 | resolution: {integrity: sha512-DKuXOKpM5IDT1FA2g9x9x1Ug81YuKrzf4mYX8FAVSNu5Wo/LELHWQyM1pQaDkI42bX15PWl0vNPt1uGiIFUOpg==} 507 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 508 | 509 | '@typescript-eslint/typescript-estree@8.33.0': 510 | resolution: {integrity: sha512-vegY4FQoB6jL97Tu/lWRsAiUUp8qJTqzAmENH2k59SJhw0Th1oszb9Idq/FyyONLuNqT1OADJPXfyUNOR8SzAQ==} 511 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 512 | peerDependencies: 513 | typescript: '>=4.8.4 <5.9.0' 514 | 515 | '@typescript-eslint/utils@8.33.0': 516 | resolution: {integrity: sha512-lPFuQaLA9aSNa7D5u2EpRiqdAUhzShwGg/nhpBlc4GR6kcTABttCuyjFs8BcEZ8VWrjCBof/bePhP3Q3fS+Yrw==} 517 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 518 | peerDependencies: 519 | eslint: ^8.57.0 || ^9.0.0 520 | typescript: '>=4.8.4 <5.9.0' 521 | 522 | '@typescript-eslint/visitor-keys@8.33.0': 523 | resolution: {integrity: sha512-7RW7CMYoskiz5OOGAWjJFxgb7c5UNjTG292gYhWeOAcFmYCtVCSqjqSBj5zMhxbXo2JOW95YYrUWJfU0zrpaGQ==} 524 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 525 | 526 | '@vitest/expect@3.1.4': 527 | resolution: {integrity: sha512-xkD/ljeliyaClDYqHPNCiJ0plY5YIcM0OlRiZizLhlPmpXWpxnGMyTZXOHFhFeG7w9P5PBeL4IdtJ/HeQwTbQA==} 528 | 529 | '@vitest/mocker@3.1.4': 530 | resolution: {integrity: sha512-8IJ3CvwtSw/EFXqWFL8aCMu+YyYXG2WUSrQbViOZkWTKTVicVwZ/YiEZDSqD00kX+v/+W+OnxhNWoeVKorHygA==} 531 | peerDependencies: 532 | msw: ^2.4.9 533 | vite: ^5.0.0 || ^6.0.0 534 | peerDependenciesMeta: 535 | msw: 536 | optional: true 537 | vite: 538 | optional: true 539 | 540 | '@vitest/pretty-format@3.1.4': 541 | resolution: {integrity: sha512-cqv9H9GvAEoTaoq+cYqUTCGscUjKqlJZC7PRwY5FMySVj5J+xOm1KQcCiYHJOEzOKRUhLH4R2pTwvFlWCEScsg==} 542 | 543 | '@vitest/runner@3.1.4': 544 | resolution: {integrity: sha512-djTeF1/vt985I/wpKVFBMWUlk/I7mb5hmD5oP8K9ACRmVXgKTae3TUOtXAEBfslNKPzUQvnKhNd34nnRSYgLNQ==} 545 | 546 | '@vitest/snapshot@3.1.4': 547 | resolution: {integrity: sha512-JPHf68DvuO7vilmvwdPr9TS0SuuIzHvxeaCkxYcCD4jTk67XwL45ZhEHFKIuCm8CYstgI6LZ4XbwD6ANrwMpFg==} 548 | 549 | '@vitest/spy@3.1.4': 550 | resolution: {integrity: sha512-Xg1bXhu+vtPXIodYN369M86K8shGLouNjoVI78g8iAq2rFoHFdajNvJJ5A/9bPMFcfQqdaCpOgWKEoMQg/s0Yg==} 551 | 552 | '@vitest/utils@3.1.4': 553 | resolution: {integrity: sha512-yriMuO1cfFhmiGc8ataN51+9ooHRuURdfAZfwFd3usWynjzpLslZdYnRegTv32qdgtJTsj15FoeZe2g15fY1gg==} 554 | 555 | acorn-jsx@5.3.2: 556 | resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} 557 | peerDependencies: 558 | acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 559 | 560 | acorn@8.14.1: 561 | resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==} 562 | engines: {node: '>=0.4.0'} 563 | hasBin: true 564 | 565 | ai@4.3.16: 566 | resolution: {integrity: sha512-KUDwlThJ5tr2Vw0A1ZkbDKNME3wzWhuVfAOwIvFUzl1TPVDFAXDFTXio3p+jaKneB+dKNCvFFlolYmmgHttG1g==} 567 | engines: {node: '>=18'} 568 | peerDependencies: 569 | react: ^18 || ^19 || ^19.0.0-rc 570 | zod: ^3.23.8 571 | peerDependenciesMeta: 572 | react: 573 | optional: true 574 | 575 | ajv@6.12.6: 576 | resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} 577 | 578 | ansi-regex@5.0.1: 579 | resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} 580 | engines: {node: '>=8'} 581 | 582 | ansi-regex@6.1.0: 583 | resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} 584 | engines: {node: '>=12'} 585 | 586 | ansi-styles@4.3.0: 587 | resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} 588 | engines: {node: '>=8'} 589 | 590 | ansi-styles@6.2.1: 591 | resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} 592 | engines: {node: '>=12'} 593 | 594 | any-promise@1.3.0: 595 | resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} 596 | 597 | argparse@2.0.1: 598 | resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} 599 | 600 | assertion-error@2.0.1: 601 | resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} 602 | engines: {node: '>=12'} 603 | 604 | balanced-match@1.0.2: 605 | resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} 606 | 607 | brace-expansion@1.1.11: 608 | resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} 609 | 610 | brace-expansion@2.0.1: 611 | resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} 612 | 613 | braces@3.0.3: 614 | resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} 615 | engines: {node: '>=8'} 616 | 617 | bundle-require@5.1.0: 618 | resolution: {integrity: sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==} 619 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} 620 | peerDependencies: 621 | esbuild: '>=0.18' 622 | 623 | cac@6.7.14: 624 | resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} 625 | engines: {node: '>=8'} 626 | 627 | callsites@3.1.0: 628 | resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} 629 | engines: {node: '>=6'} 630 | 631 | chai@5.2.0: 632 | resolution: {integrity: sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==} 633 | engines: {node: '>=12'} 634 | 635 | chalk@4.1.2: 636 | resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} 637 | engines: {node: '>=10'} 638 | 639 | chalk@5.4.1: 640 | resolution: {integrity: sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==} 641 | engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} 642 | 643 | check-error@2.1.1: 644 | resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} 645 | engines: {node: '>= 16'} 646 | 647 | chokidar@4.0.3: 648 | resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} 649 | engines: {node: '>= 14.16.0'} 650 | 651 | citty@0.1.6: 652 | resolution: {integrity: sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==} 653 | 654 | cli-cursor@5.0.0: 655 | resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} 656 | engines: {node: '>=18'} 657 | 658 | cli-spinners@2.9.2: 659 | resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} 660 | engines: {node: '>=6'} 661 | 662 | color-convert@2.0.1: 663 | resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} 664 | engines: {node: '>=7.0.0'} 665 | 666 | color-name@1.1.4: 667 | resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} 668 | 669 | commander@4.1.1: 670 | resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} 671 | engines: {node: '>= 6'} 672 | 673 | concat-map@0.0.1: 674 | resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} 675 | 676 | confbox@0.1.8: 677 | resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} 678 | 679 | consola@3.4.2: 680 | resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==} 681 | engines: {node: ^14.18.0 || >=16.10.0} 682 | 683 | cross-spawn@7.0.6: 684 | resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} 685 | engines: {node: '>= 8'} 686 | 687 | debug@4.4.1: 688 | resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} 689 | engines: {node: '>=6.0'} 690 | peerDependencies: 691 | supports-color: '*' 692 | peerDependenciesMeta: 693 | supports-color: 694 | optional: true 695 | 696 | deep-eql@5.0.2: 697 | resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} 698 | engines: {node: '>=6'} 699 | 700 | deep-is@0.1.4: 701 | resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} 702 | 703 | dequal@2.0.3: 704 | resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} 705 | engines: {node: '>=6'} 706 | 707 | diff-match-patch@1.0.5: 708 | resolution: {integrity: sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==} 709 | 710 | dotenv@16.5.0: 711 | resolution: {integrity: sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==} 712 | engines: {node: '>=12'} 713 | 714 | eastasianwidth@0.2.0: 715 | resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} 716 | 717 | emoji-regex@10.4.0: 718 | resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} 719 | 720 | emoji-regex@8.0.0: 721 | resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} 722 | 723 | emoji-regex@9.2.2: 724 | resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} 725 | 726 | es-module-lexer@1.7.0: 727 | resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} 728 | 729 | esbuild@0.25.4: 730 | resolution: {integrity: sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==} 731 | engines: {node: '>=18'} 732 | hasBin: true 733 | 734 | escape-string-regexp@4.0.0: 735 | resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} 736 | engines: {node: '>=10'} 737 | 738 | eslint-scope@8.3.0: 739 | resolution: {integrity: sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==} 740 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 741 | 742 | eslint-visitor-keys@3.4.3: 743 | resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} 744 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 745 | 746 | eslint-visitor-keys@4.2.0: 747 | resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} 748 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 749 | 750 | eslint@9.28.0: 751 | resolution: {integrity: sha512-ocgh41VhRlf9+fVpe7QKzwLj9c92fDiqOj8Y3Sd4/ZmVA4Btx4PlUYPq4pp9JDyupkf1upbEXecxL2mwNV7jPQ==} 752 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 753 | hasBin: true 754 | peerDependencies: 755 | jiti: '*' 756 | peerDependenciesMeta: 757 | jiti: 758 | optional: true 759 | 760 | espree@10.3.0: 761 | resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} 762 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 763 | 764 | esquery@1.6.0: 765 | resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} 766 | engines: {node: '>=0.10'} 767 | 768 | esrecurse@4.3.0: 769 | resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} 770 | engines: {node: '>=4.0'} 771 | 772 | estraverse@5.3.0: 773 | resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} 774 | engines: {node: '>=4.0'} 775 | 776 | estree-walker@3.0.3: 777 | resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} 778 | 779 | esutils@2.0.3: 780 | resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} 781 | engines: {node: '>=0.10.0'} 782 | 783 | expect-type@1.2.1: 784 | resolution: {integrity: sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw==} 785 | engines: {node: '>=12.0.0'} 786 | 787 | fast-deep-equal@3.1.3: 788 | resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} 789 | 790 | fast-glob@3.3.3: 791 | resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} 792 | engines: {node: '>=8.6.0'} 793 | 794 | fast-json-stable-stringify@2.1.0: 795 | resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} 796 | 797 | fast-levenshtein@2.0.6: 798 | resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} 799 | 800 | fastq@1.19.1: 801 | resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} 802 | 803 | fdir@6.4.4: 804 | resolution: {integrity: sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==} 805 | peerDependencies: 806 | picomatch: ^3 || ^4 807 | peerDependenciesMeta: 808 | picomatch: 809 | optional: true 810 | 811 | file-entry-cache@8.0.0: 812 | resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} 813 | engines: {node: '>=16.0.0'} 814 | 815 | fill-range@7.1.1: 816 | resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} 817 | engines: {node: '>=8'} 818 | 819 | find-up@5.0.0: 820 | resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} 821 | engines: {node: '>=10'} 822 | 823 | fix-dts-default-cjs-exports@1.0.1: 824 | resolution: {integrity: sha512-pVIECanWFC61Hzl2+oOCtoJ3F17kglZC/6N94eRWycFgBH35hHx0Li604ZIzhseh97mf2p0cv7vVrOZGoqhlEg==} 825 | 826 | flat-cache@4.0.1: 827 | resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} 828 | engines: {node: '>=16'} 829 | 830 | flatted@3.3.3: 831 | resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} 832 | 833 | foreground-child@3.3.1: 834 | resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} 835 | engines: {node: '>=14'} 836 | 837 | fsevents@2.3.3: 838 | resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} 839 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 840 | os: [darwin] 841 | 842 | get-east-asian-width@1.3.0: 843 | resolution: {integrity: sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==} 844 | engines: {node: '>=18'} 845 | 846 | get-tsconfig@4.10.1: 847 | resolution: {integrity: sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==} 848 | 849 | glob-parent@5.1.2: 850 | resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} 851 | engines: {node: '>= 6'} 852 | 853 | glob-parent@6.0.2: 854 | resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} 855 | engines: {node: '>=10.13.0'} 856 | 857 | glob@10.4.5: 858 | resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} 859 | hasBin: true 860 | 861 | globals@14.0.0: 862 | resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} 863 | engines: {node: '>=18'} 864 | 865 | graphemer@1.4.0: 866 | resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} 867 | 868 | has-flag@4.0.0: 869 | resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} 870 | engines: {node: '>=8'} 871 | 872 | ignore@5.3.2: 873 | resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} 874 | engines: {node: '>= 4'} 875 | 876 | ignore@7.0.5: 877 | resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} 878 | engines: {node: '>= 4'} 879 | 880 | import-fresh@3.3.1: 881 | resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} 882 | engines: {node: '>=6'} 883 | 884 | imurmurhash@0.1.4: 885 | resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} 886 | engines: {node: '>=0.8.19'} 887 | 888 | is-extglob@2.1.1: 889 | resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} 890 | engines: {node: '>=0.10.0'} 891 | 892 | is-fullwidth-code-point@3.0.0: 893 | resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} 894 | engines: {node: '>=8'} 895 | 896 | is-glob@4.0.3: 897 | resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} 898 | engines: {node: '>=0.10.0'} 899 | 900 | is-interactive@2.0.0: 901 | resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==} 902 | engines: {node: '>=12'} 903 | 904 | is-number@7.0.0: 905 | resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} 906 | engines: {node: '>=0.12.0'} 907 | 908 | is-unicode-supported@1.3.0: 909 | resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} 910 | engines: {node: '>=12'} 911 | 912 | is-unicode-supported@2.1.0: 913 | resolution: {integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==} 914 | engines: {node: '>=18'} 915 | 916 | isexe@2.0.0: 917 | resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} 918 | 919 | jackspeak@3.4.3: 920 | resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} 921 | 922 | joycon@3.1.1: 923 | resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} 924 | engines: {node: '>=10'} 925 | 926 | js-yaml@4.1.0: 927 | resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} 928 | hasBin: true 929 | 930 | json-buffer@3.0.1: 931 | resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} 932 | 933 | json-schema-traverse@0.4.1: 934 | resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} 935 | 936 | json-schema@0.4.0: 937 | resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} 938 | 939 | json-stable-stringify-without-jsonify@1.0.1: 940 | resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} 941 | 942 | jsondiffpatch@0.6.0: 943 | resolution: {integrity: sha512-3QItJOXp2AP1uv7waBkao5nCvhEv+QmJAd38Ybq7wNI74Q+BBmnLn4EDKz6yI9xGAIQoUF87qHt+kc1IVxB4zQ==} 944 | engines: {node: ^18.0.0 || >=20.0.0} 945 | hasBin: true 946 | 947 | keyv@4.5.4: 948 | resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} 949 | 950 | levn@0.4.1: 951 | resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} 952 | engines: {node: '>= 0.8.0'} 953 | 954 | lilconfig@3.1.3: 955 | resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} 956 | engines: {node: '>=14'} 957 | 958 | lines-and-columns@1.2.4: 959 | resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} 960 | 961 | load-tsconfig@0.2.5: 962 | resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==} 963 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} 964 | 965 | locate-path@6.0.0: 966 | resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} 967 | engines: {node: '>=10'} 968 | 969 | lodash.merge@4.6.2: 970 | resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} 971 | 972 | lodash.sortby@4.7.0: 973 | resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} 974 | 975 | log-symbols@6.0.0: 976 | resolution: {integrity: sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==} 977 | engines: {node: '>=18'} 978 | 979 | loupe@3.1.3: 980 | resolution: {integrity: sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==} 981 | 982 | lru-cache@10.4.3: 983 | resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} 984 | 985 | magic-string@0.30.17: 986 | resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} 987 | 988 | merge2@1.4.1: 989 | resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} 990 | engines: {node: '>= 8'} 991 | 992 | micromatch@4.0.8: 993 | resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} 994 | engines: {node: '>=8.6'} 995 | 996 | mimic-function@5.0.1: 997 | resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} 998 | engines: {node: '>=18'} 999 | 1000 | minimatch@10.0.1: 1001 | resolution: {integrity: sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==} 1002 | engines: {node: 20 || >=22} 1003 | 1004 | minimatch@3.1.2: 1005 | resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} 1006 | 1007 | minimatch@9.0.5: 1008 | resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} 1009 | engines: {node: '>=16 || 14 >=14.17'} 1010 | 1011 | minipass@7.1.2: 1012 | resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} 1013 | engines: {node: '>=16 || 14 >=14.17'} 1014 | 1015 | mlly@1.7.4: 1016 | resolution: {integrity: sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==} 1017 | 1018 | ms@2.1.3: 1019 | resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} 1020 | 1021 | mz@2.7.0: 1022 | resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} 1023 | 1024 | nanoid@3.3.11: 1025 | resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} 1026 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 1027 | hasBin: true 1028 | 1029 | natural-compare@1.4.0: 1030 | resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} 1031 | 1032 | object-assign@4.1.1: 1033 | resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} 1034 | engines: {node: '>=0.10.0'} 1035 | 1036 | onetime@7.0.0: 1037 | resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} 1038 | engines: {node: '>=18'} 1039 | 1040 | optionator@0.9.4: 1041 | resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} 1042 | engines: {node: '>= 0.8.0'} 1043 | 1044 | ora@8.2.0: 1045 | resolution: {integrity: sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==} 1046 | engines: {node: '>=18'} 1047 | 1048 | p-limit@3.1.0: 1049 | resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} 1050 | engines: {node: '>=10'} 1051 | 1052 | p-locate@5.0.0: 1053 | resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} 1054 | engines: {node: '>=10'} 1055 | 1056 | package-json-from-dist@1.0.1: 1057 | resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} 1058 | 1059 | parent-module@1.0.1: 1060 | resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} 1061 | engines: {node: '>=6'} 1062 | 1063 | path-exists@4.0.0: 1064 | resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} 1065 | engines: {node: '>=8'} 1066 | 1067 | path-key@3.1.1: 1068 | resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} 1069 | engines: {node: '>=8'} 1070 | 1071 | path-scurry@1.11.1: 1072 | resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} 1073 | engines: {node: '>=16 || 14 >=14.18'} 1074 | 1075 | pathe@2.0.3: 1076 | resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} 1077 | 1078 | pathval@2.0.0: 1079 | resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==} 1080 | engines: {node: '>= 14.16'} 1081 | 1082 | picocolors@1.1.1: 1083 | resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} 1084 | 1085 | picomatch@2.3.1: 1086 | resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} 1087 | engines: {node: '>=8.6'} 1088 | 1089 | picomatch@4.0.2: 1090 | resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} 1091 | engines: {node: '>=12'} 1092 | 1093 | pirates@4.0.7: 1094 | resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} 1095 | engines: {node: '>= 6'} 1096 | 1097 | pkg-types@1.3.1: 1098 | resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} 1099 | 1100 | postcss-load-config@6.0.1: 1101 | resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==} 1102 | engines: {node: '>= 18'} 1103 | peerDependencies: 1104 | jiti: '>=1.21.0' 1105 | postcss: '>=8.0.9' 1106 | tsx: ^4.8.1 1107 | yaml: ^2.4.2 1108 | peerDependenciesMeta: 1109 | jiti: 1110 | optional: true 1111 | postcss: 1112 | optional: true 1113 | tsx: 1114 | optional: true 1115 | yaml: 1116 | optional: true 1117 | 1118 | postcss@8.5.3: 1119 | resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} 1120 | engines: {node: ^10 || ^12 || >=14} 1121 | 1122 | prelude-ls@1.2.1: 1123 | resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} 1124 | engines: {node: '>= 0.8.0'} 1125 | 1126 | punycode@2.3.1: 1127 | resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} 1128 | engines: {node: '>=6'} 1129 | 1130 | queue-microtask@1.2.3: 1131 | resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} 1132 | 1133 | react@19.1.0: 1134 | resolution: {integrity: sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==} 1135 | engines: {node: '>=0.10.0'} 1136 | 1137 | readdirp@4.1.2: 1138 | resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} 1139 | engines: {node: '>= 14.18.0'} 1140 | 1141 | resolve-from@4.0.0: 1142 | resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} 1143 | engines: {node: '>=4'} 1144 | 1145 | resolve-from@5.0.0: 1146 | resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} 1147 | engines: {node: '>=8'} 1148 | 1149 | resolve-pkg-maps@1.0.0: 1150 | resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} 1151 | 1152 | restore-cursor@5.1.0: 1153 | resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} 1154 | engines: {node: '>=18'} 1155 | 1156 | reusify@1.1.0: 1157 | resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} 1158 | engines: {iojs: '>=1.0.0', node: '>=0.10.0'} 1159 | 1160 | rollup@4.41.1: 1161 | resolution: {integrity: sha512-cPmwD3FnFv8rKMBc1MxWCwVQFxwf1JEmSX3iQXrRVVG15zerAIXRjMFVWnd5Q5QvgKF7Aj+5ykXFhUl+QGnyOw==} 1162 | engines: {node: '>=18.0.0', npm: '>=8.0.0'} 1163 | hasBin: true 1164 | 1165 | run-parallel@1.2.0: 1166 | resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} 1167 | 1168 | secure-json-parse@2.7.0: 1169 | resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} 1170 | 1171 | semver@7.7.2: 1172 | resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} 1173 | engines: {node: '>=10'} 1174 | hasBin: true 1175 | 1176 | shebang-command@2.0.0: 1177 | resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} 1178 | engines: {node: '>=8'} 1179 | 1180 | shebang-regex@3.0.0: 1181 | resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} 1182 | engines: {node: '>=8'} 1183 | 1184 | shell-quote@1.8.2: 1185 | resolution: {integrity: sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==} 1186 | engines: {node: '>= 0.4'} 1187 | 1188 | siginfo@2.0.0: 1189 | resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} 1190 | 1191 | signal-exit@4.1.0: 1192 | resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} 1193 | engines: {node: '>=14'} 1194 | 1195 | source-map-js@1.2.1: 1196 | resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} 1197 | engines: {node: '>=0.10.0'} 1198 | 1199 | source-map@0.8.0-beta.0: 1200 | resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==} 1201 | engines: {node: '>= 8'} 1202 | 1203 | stackback@0.0.2: 1204 | resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} 1205 | 1206 | std-env@3.9.0: 1207 | resolution: {integrity: sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==} 1208 | 1209 | stdin-discarder@0.2.2: 1210 | resolution: {integrity: sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==} 1211 | engines: {node: '>=18'} 1212 | 1213 | string-width@4.2.3: 1214 | resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} 1215 | engines: {node: '>=8'} 1216 | 1217 | string-width@5.1.2: 1218 | resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} 1219 | engines: {node: '>=12'} 1220 | 1221 | string-width@7.2.0: 1222 | resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} 1223 | engines: {node: '>=18'} 1224 | 1225 | strip-ansi@6.0.1: 1226 | resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} 1227 | engines: {node: '>=8'} 1228 | 1229 | strip-ansi@7.1.0: 1230 | resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} 1231 | engines: {node: '>=12'} 1232 | 1233 | strip-json-comments@3.1.1: 1234 | resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} 1235 | engines: {node: '>=8'} 1236 | 1237 | sucrase@3.35.0: 1238 | resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} 1239 | engines: {node: '>=16 || 14 >=14.17'} 1240 | hasBin: true 1241 | 1242 | supports-color@7.2.0: 1243 | resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} 1244 | engines: {node: '>=8'} 1245 | 1246 | swr@2.3.3: 1247 | resolution: {integrity: sha512-dshNvs3ExOqtZ6kJBaAsabhPdHyeY4P2cKwRCniDVifBMoG/SVI7tfLWqPXriVspf2Rg4tPzXJTnwaihIeFw2A==} 1248 | peerDependencies: 1249 | react: ^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 1250 | 1251 | thenify-all@1.6.0: 1252 | resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} 1253 | engines: {node: '>=0.8'} 1254 | 1255 | thenify@3.3.1: 1256 | resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} 1257 | 1258 | throttleit@2.1.0: 1259 | resolution: {integrity: sha512-nt6AMGKW1p/70DF/hGBdJB57B8Tspmbp5gfJ8ilhLnt7kkr2ye7hzD6NVG8GGErk2HWF34igrL2CXmNIkzKqKw==} 1260 | engines: {node: '>=18'} 1261 | 1262 | tinybench@2.9.0: 1263 | resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} 1264 | 1265 | tinyexec@0.3.2: 1266 | resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} 1267 | 1268 | tinyglobby@0.2.14: 1269 | resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==} 1270 | engines: {node: '>=12.0.0'} 1271 | 1272 | tinypool@1.0.2: 1273 | resolution: {integrity: sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==} 1274 | engines: {node: ^18.0.0 || >=20.0.0} 1275 | 1276 | tinyrainbow@2.0.0: 1277 | resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} 1278 | engines: {node: '>=14.0.0'} 1279 | 1280 | tinyspy@3.0.2: 1281 | resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} 1282 | engines: {node: '>=14.0.0'} 1283 | 1284 | to-regex-range@5.0.1: 1285 | resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} 1286 | engines: {node: '>=8.0'} 1287 | 1288 | tr46@1.0.1: 1289 | resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} 1290 | 1291 | tree-kill@1.2.2: 1292 | resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} 1293 | hasBin: true 1294 | 1295 | ts-api-utils@2.1.0: 1296 | resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==} 1297 | engines: {node: '>=18.12'} 1298 | peerDependencies: 1299 | typescript: '>=4.8.4' 1300 | 1301 | ts-interface-checker@0.1.13: 1302 | resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} 1303 | 1304 | tsup@8.5.0: 1305 | resolution: {integrity: sha512-VmBp77lWNQq6PfuMqCHD3xWl22vEoWsKajkF8t+yMBawlUS8JzEI+vOVMeuNZIuMML8qXRizFKi9oD5glKQVcQ==} 1306 | engines: {node: '>=18'} 1307 | hasBin: true 1308 | peerDependencies: 1309 | '@microsoft/api-extractor': ^7.36.0 1310 | '@swc/core': ^1 1311 | postcss: ^8.4.12 1312 | typescript: '>=4.5.0' 1313 | peerDependenciesMeta: 1314 | '@microsoft/api-extractor': 1315 | optional: true 1316 | '@swc/core': 1317 | optional: true 1318 | postcss: 1319 | optional: true 1320 | typescript: 1321 | optional: true 1322 | 1323 | tsx@4.19.4: 1324 | resolution: {integrity: sha512-gK5GVzDkJK1SI1zwHf32Mqxf2tSJkNx+eYcNly5+nHvWqXUJYUkWBQtKauoESz3ymezAI++ZwT855x5p5eop+Q==} 1325 | engines: {node: '>=18.0.0'} 1326 | hasBin: true 1327 | 1328 | type-check@0.4.0: 1329 | resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} 1330 | engines: {node: '>= 0.8.0'} 1331 | 1332 | typescript-eslint@8.33.0: 1333 | resolution: {integrity: sha512-5YmNhF24ylCsvdNW2oJwMzTbaeO4bg90KeGtMjUw0AGtHksgEPLRTUil+coHwCfiu4QjVJFnjp94DmU6zV7DhQ==} 1334 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 1335 | peerDependencies: 1336 | eslint: ^8.57.0 || ^9.0.0 1337 | typescript: '>=4.8.4 <5.9.0' 1338 | 1339 | typescript@5.8.3: 1340 | resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==} 1341 | engines: {node: '>=14.17'} 1342 | hasBin: true 1343 | 1344 | ufo@1.6.1: 1345 | resolution: {integrity: sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==} 1346 | 1347 | undici-types@6.21.0: 1348 | resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} 1349 | 1350 | uri-js@4.4.1: 1351 | resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} 1352 | 1353 | use-sync-external-store@1.5.0: 1354 | resolution: {integrity: sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==} 1355 | peerDependencies: 1356 | react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 1357 | 1358 | vite-node@3.1.4: 1359 | resolution: {integrity: sha512-6enNwYnpyDo4hEgytbmc6mYWHXDHYEn0D1/rw4Q+tnHUGtKTJsn8T1YkX6Q18wI5LCrS8CTYlBaiCqxOy2kvUA==} 1360 | engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} 1361 | hasBin: true 1362 | 1363 | vite@6.3.5: 1364 | resolution: {integrity: sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==} 1365 | engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} 1366 | hasBin: true 1367 | peerDependencies: 1368 | '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 1369 | jiti: '>=1.21.0' 1370 | less: '*' 1371 | lightningcss: ^1.21.0 1372 | sass: '*' 1373 | sass-embedded: '*' 1374 | stylus: '*' 1375 | sugarss: '*' 1376 | terser: ^5.16.0 1377 | tsx: ^4.8.1 1378 | yaml: ^2.4.2 1379 | peerDependenciesMeta: 1380 | '@types/node': 1381 | optional: true 1382 | jiti: 1383 | optional: true 1384 | less: 1385 | optional: true 1386 | lightningcss: 1387 | optional: true 1388 | sass: 1389 | optional: true 1390 | sass-embedded: 1391 | optional: true 1392 | stylus: 1393 | optional: true 1394 | sugarss: 1395 | optional: true 1396 | terser: 1397 | optional: true 1398 | tsx: 1399 | optional: true 1400 | yaml: 1401 | optional: true 1402 | 1403 | vitest@3.1.4: 1404 | resolution: {integrity: sha512-Ta56rT7uWxCSJXlBtKgIlApJnT6e6IGmTYxYcmxjJ4ujuZDI59GUQgVDObXXJujOmPDBYXHK1qmaGtneu6TNIQ==} 1405 | engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} 1406 | hasBin: true 1407 | peerDependencies: 1408 | '@edge-runtime/vm': '*' 1409 | '@types/debug': ^4.1.12 1410 | '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 1411 | '@vitest/browser': 3.1.4 1412 | '@vitest/ui': 3.1.4 1413 | happy-dom: '*' 1414 | jsdom: '*' 1415 | peerDependenciesMeta: 1416 | '@edge-runtime/vm': 1417 | optional: true 1418 | '@types/debug': 1419 | optional: true 1420 | '@types/node': 1421 | optional: true 1422 | '@vitest/browser': 1423 | optional: true 1424 | '@vitest/ui': 1425 | optional: true 1426 | happy-dom: 1427 | optional: true 1428 | jsdom: 1429 | optional: true 1430 | 1431 | webidl-conversions@4.0.2: 1432 | resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} 1433 | 1434 | whatwg-url@7.1.0: 1435 | resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==} 1436 | 1437 | which@2.0.2: 1438 | resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} 1439 | engines: {node: '>= 8'} 1440 | hasBin: true 1441 | 1442 | why-is-node-running@2.3.0: 1443 | resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} 1444 | engines: {node: '>=8'} 1445 | hasBin: true 1446 | 1447 | word-wrap@1.2.5: 1448 | resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} 1449 | engines: {node: '>=0.10.0'} 1450 | 1451 | wrap-ansi@7.0.0: 1452 | resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} 1453 | engines: {node: '>=10'} 1454 | 1455 | wrap-ansi@8.1.0: 1456 | resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} 1457 | engines: {node: '>=12'} 1458 | 1459 | yocto-queue@0.1.0: 1460 | resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} 1461 | engines: {node: '>=10'} 1462 | 1463 | zod-to-json-schema@3.24.5: 1464 | resolution: {integrity: sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g==} 1465 | peerDependencies: 1466 | zod: ^3.24.1 1467 | 1468 | zod@3.25.42: 1469 | resolution: {integrity: sha512-PcALTLskaucbeHc41tU/xfjfhcz8z0GdhhDcSgrCTmSazUuqnYqiXO63M0QUBVwpBlsLsNVn5qHSC5Dw3KZvaQ==} 1470 | 1471 | snapshots: 1472 | 1473 | '@ai-sdk/provider-utils@2.2.8(zod@3.25.42)': 1474 | dependencies: 1475 | '@ai-sdk/provider': 1.1.3 1476 | nanoid: 3.3.11 1477 | secure-json-parse: 2.7.0 1478 | zod: 3.25.42 1479 | 1480 | '@ai-sdk/provider@1.1.3': 1481 | dependencies: 1482 | json-schema: 0.4.0 1483 | 1484 | '@ai-sdk/react@1.2.12(react@19.1.0)(zod@3.25.42)': 1485 | dependencies: 1486 | '@ai-sdk/provider-utils': 2.2.8(zod@3.25.42) 1487 | '@ai-sdk/ui-utils': 1.2.11(zod@3.25.42) 1488 | react: 19.1.0 1489 | swr: 2.3.3(react@19.1.0) 1490 | throttleit: 2.1.0 1491 | optionalDependencies: 1492 | zod: 3.25.42 1493 | 1494 | '@ai-sdk/ui-utils@1.2.11(zod@3.25.42)': 1495 | dependencies: 1496 | '@ai-sdk/provider': 1.1.3 1497 | '@ai-sdk/provider-utils': 2.2.8(zod@3.25.42) 1498 | zod: 3.25.42 1499 | zod-to-json-schema: 3.24.5(zod@3.25.42) 1500 | 1501 | '@esbuild/aix-ppc64@0.25.4': 1502 | optional: true 1503 | 1504 | '@esbuild/android-arm64@0.25.4': 1505 | optional: true 1506 | 1507 | '@esbuild/android-arm@0.25.4': 1508 | optional: true 1509 | 1510 | '@esbuild/android-x64@0.25.4': 1511 | optional: true 1512 | 1513 | '@esbuild/darwin-arm64@0.25.4': 1514 | optional: true 1515 | 1516 | '@esbuild/darwin-x64@0.25.4': 1517 | optional: true 1518 | 1519 | '@esbuild/freebsd-arm64@0.25.4': 1520 | optional: true 1521 | 1522 | '@esbuild/freebsd-x64@0.25.4': 1523 | optional: true 1524 | 1525 | '@esbuild/linux-arm64@0.25.4': 1526 | optional: true 1527 | 1528 | '@esbuild/linux-arm@0.25.4': 1529 | optional: true 1530 | 1531 | '@esbuild/linux-ia32@0.25.4': 1532 | optional: true 1533 | 1534 | '@esbuild/linux-loong64@0.25.4': 1535 | optional: true 1536 | 1537 | '@esbuild/linux-mips64el@0.25.4': 1538 | optional: true 1539 | 1540 | '@esbuild/linux-ppc64@0.25.4': 1541 | optional: true 1542 | 1543 | '@esbuild/linux-riscv64@0.25.4': 1544 | optional: true 1545 | 1546 | '@esbuild/linux-s390x@0.25.4': 1547 | optional: true 1548 | 1549 | '@esbuild/linux-x64@0.25.4': 1550 | optional: true 1551 | 1552 | '@esbuild/netbsd-arm64@0.25.4': 1553 | optional: true 1554 | 1555 | '@esbuild/netbsd-x64@0.25.4': 1556 | optional: true 1557 | 1558 | '@esbuild/openbsd-arm64@0.25.4': 1559 | optional: true 1560 | 1561 | '@esbuild/openbsd-x64@0.25.4': 1562 | optional: true 1563 | 1564 | '@esbuild/sunos-x64@0.25.4': 1565 | optional: true 1566 | 1567 | '@esbuild/win32-arm64@0.25.4': 1568 | optional: true 1569 | 1570 | '@esbuild/win32-ia32@0.25.4': 1571 | optional: true 1572 | 1573 | '@esbuild/win32-x64@0.25.4': 1574 | optional: true 1575 | 1576 | '@eslint-community/eslint-utils@4.7.0(eslint@9.28.0)': 1577 | dependencies: 1578 | eslint: 9.28.0 1579 | eslint-visitor-keys: 3.4.3 1580 | 1581 | '@eslint-community/regexpp@4.12.1': {} 1582 | 1583 | '@eslint/config-array@0.20.0': 1584 | dependencies: 1585 | '@eslint/object-schema': 2.1.6 1586 | debug: 4.4.1 1587 | minimatch: 3.1.2 1588 | transitivePeerDependencies: 1589 | - supports-color 1590 | 1591 | '@eslint/config-helpers@0.2.2': {} 1592 | 1593 | '@eslint/core@0.14.0': 1594 | dependencies: 1595 | '@types/json-schema': 7.0.15 1596 | 1597 | '@eslint/eslintrc@3.3.1': 1598 | dependencies: 1599 | ajv: 6.12.6 1600 | debug: 4.4.1 1601 | espree: 10.3.0 1602 | globals: 14.0.0 1603 | ignore: 5.3.2 1604 | import-fresh: 3.3.1 1605 | js-yaml: 4.1.0 1606 | minimatch: 3.1.2 1607 | strip-json-comments: 3.1.1 1608 | transitivePeerDependencies: 1609 | - supports-color 1610 | 1611 | '@eslint/js@9.28.0': {} 1612 | 1613 | '@eslint/object-schema@2.1.6': {} 1614 | 1615 | '@eslint/plugin-kit@0.3.1': 1616 | dependencies: 1617 | '@eslint/core': 0.14.0 1618 | levn: 0.4.1 1619 | 1620 | '@humanfs/core@0.19.1': {} 1621 | 1622 | '@humanfs/node@0.16.6': 1623 | dependencies: 1624 | '@humanfs/core': 0.19.1 1625 | '@humanwhocodes/retry': 0.3.1 1626 | 1627 | '@humanwhocodes/module-importer@1.0.1': {} 1628 | 1629 | '@humanwhocodes/retry@0.3.1': {} 1630 | 1631 | '@humanwhocodes/retry@0.4.3': {} 1632 | 1633 | '@isaacs/cliui@8.0.2': 1634 | dependencies: 1635 | string-width: 5.1.2 1636 | string-width-cjs: string-width@4.2.3 1637 | strip-ansi: 7.1.0 1638 | strip-ansi-cjs: strip-ansi@6.0.1 1639 | wrap-ansi: 8.1.0 1640 | wrap-ansi-cjs: wrap-ansi@7.0.0 1641 | 1642 | '@jridgewell/gen-mapping@0.3.8': 1643 | dependencies: 1644 | '@jridgewell/set-array': 1.2.1 1645 | '@jridgewell/sourcemap-codec': 1.5.0 1646 | '@jridgewell/trace-mapping': 0.3.25 1647 | 1648 | '@jridgewell/resolve-uri@3.1.2': {} 1649 | 1650 | '@jridgewell/set-array@1.2.1': {} 1651 | 1652 | '@jridgewell/sourcemap-codec@1.5.0': {} 1653 | 1654 | '@jridgewell/trace-mapping@0.3.25': 1655 | dependencies: 1656 | '@jridgewell/resolve-uri': 3.1.2 1657 | '@jridgewell/sourcemap-codec': 1.5.0 1658 | 1659 | '@nodelib/fs.scandir@2.1.5': 1660 | dependencies: 1661 | '@nodelib/fs.stat': 2.0.5 1662 | run-parallel: 1.2.0 1663 | 1664 | '@nodelib/fs.stat@2.0.5': {} 1665 | 1666 | '@nodelib/fs.walk@1.2.8': 1667 | dependencies: 1668 | '@nodelib/fs.scandir': 2.1.5 1669 | fastq: 1.19.1 1670 | 1671 | '@opentelemetry/api@1.9.0': {} 1672 | 1673 | '@pkgjs/parseargs@0.11.0': 1674 | optional: true 1675 | 1676 | '@rollup/rollup-android-arm-eabi@4.41.1': 1677 | optional: true 1678 | 1679 | '@rollup/rollup-android-arm64@4.41.1': 1680 | optional: true 1681 | 1682 | '@rollup/rollup-darwin-arm64@4.41.1': 1683 | optional: true 1684 | 1685 | '@rollup/rollup-darwin-x64@4.41.1': 1686 | optional: true 1687 | 1688 | '@rollup/rollup-freebsd-arm64@4.41.1': 1689 | optional: true 1690 | 1691 | '@rollup/rollup-freebsd-x64@4.41.1': 1692 | optional: true 1693 | 1694 | '@rollup/rollup-linux-arm-gnueabihf@4.41.1': 1695 | optional: true 1696 | 1697 | '@rollup/rollup-linux-arm-musleabihf@4.41.1': 1698 | optional: true 1699 | 1700 | '@rollup/rollup-linux-arm64-gnu@4.41.1': 1701 | optional: true 1702 | 1703 | '@rollup/rollup-linux-arm64-musl@4.41.1': 1704 | optional: true 1705 | 1706 | '@rollup/rollup-linux-loongarch64-gnu@4.41.1': 1707 | optional: true 1708 | 1709 | '@rollup/rollup-linux-powerpc64le-gnu@4.41.1': 1710 | optional: true 1711 | 1712 | '@rollup/rollup-linux-riscv64-gnu@4.41.1': 1713 | optional: true 1714 | 1715 | '@rollup/rollup-linux-riscv64-musl@4.41.1': 1716 | optional: true 1717 | 1718 | '@rollup/rollup-linux-s390x-gnu@4.41.1': 1719 | optional: true 1720 | 1721 | '@rollup/rollup-linux-x64-gnu@4.41.1': 1722 | optional: true 1723 | 1724 | '@rollup/rollup-linux-x64-musl@4.41.1': 1725 | optional: true 1726 | 1727 | '@rollup/rollup-win32-arm64-msvc@4.41.1': 1728 | optional: true 1729 | 1730 | '@rollup/rollup-win32-ia32-msvc@4.41.1': 1731 | optional: true 1732 | 1733 | '@rollup/rollup-win32-x64-msvc@4.41.1': 1734 | optional: true 1735 | 1736 | '@tsconfig/strictest@2.0.5': {} 1737 | 1738 | '@types/diff-match-patch@1.0.36': {} 1739 | 1740 | '@types/estree@1.0.7': {} 1741 | 1742 | '@types/json-schema@7.0.15': {} 1743 | 1744 | '@types/node@22.15.29': 1745 | dependencies: 1746 | undici-types: 6.21.0 1747 | 1748 | '@types/shell-quote@1.7.5': {} 1749 | 1750 | '@typescript-eslint/eslint-plugin@8.33.0(@typescript-eslint/parser@8.33.0(eslint@9.28.0)(typescript@5.8.3))(eslint@9.28.0)(typescript@5.8.3)': 1751 | dependencies: 1752 | '@eslint-community/regexpp': 4.12.1 1753 | '@typescript-eslint/parser': 8.33.0(eslint@9.28.0)(typescript@5.8.3) 1754 | '@typescript-eslint/scope-manager': 8.33.0 1755 | '@typescript-eslint/type-utils': 8.33.0(eslint@9.28.0)(typescript@5.8.3) 1756 | '@typescript-eslint/utils': 8.33.0(eslint@9.28.0)(typescript@5.8.3) 1757 | '@typescript-eslint/visitor-keys': 8.33.0 1758 | eslint: 9.28.0 1759 | graphemer: 1.4.0 1760 | ignore: 7.0.5 1761 | natural-compare: 1.4.0 1762 | ts-api-utils: 2.1.0(typescript@5.8.3) 1763 | typescript: 5.8.3 1764 | transitivePeerDependencies: 1765 | - supports-color 1766 | 1767 | '@typescript-eslint/parser@8.33.0(eslint@9.28.0)(typescript@5.8.3)': 1768 | dependencies: 1769 | '@typescript-eslint/scope-manager': 8.33.0 1770 | '@typescript-eslint/types': 8.33.0 1771 | '@typescript-eslint/typescript-estree': 8.33.0(typescript@5.8.3) 1772 | '@typescript-eslint/visitor-keys': 8.33.0 1773 | debug: 4.4.1 1774 | eslint: 9.28.0 1775 | typescript: 5.8.3 1776 | transitivePeerDependencies: 1777 | - supports-color 1778 | 1779 | '@typescript-eslint/project-service@8.33.0(typescript@5.8.3)': 1780 | dependencies: 1781 | '@typescript-eslint/tsconfig-utils': 8.33.0(typescript@5.8.3) 1782 | '@typescript-eslint/types': 8.33.0 1783 | debug: 4.4.1 1784 | transitivePeerDependencies: 1785 | - supports-color 1786 | - typescript 1787 | 1788 | '@typescript-eslint/scope-manager@8.33.0': 1789 | dependencies: 1790 | '@typescript-eslint/types': 8.33.0 1791 | '@typescript-eslint/visitor-keys': 8.33.0 1792 | 1793 | '@typescript-eslint/tsconfig-utils@8.33.0(typescript@5.8.3)': 1794 | dependencies: 1795 | typescript: 5.8.3 1796 | 1797 | '@typescript-eslint/type-utils@8.33.0(eslint@9.28.0)(typescript@5.8.3)': 1798 | dependencies: 1799 | '@typescript-eslint/typescript-estree': 8.33.0(typescript@5.8.3) 1800 | '@typescript-eslint/utils': 8.33.0(eslint@9.28.0)(typescript@5.8.3) 1801 | debug: 4.4.1 1802 | eslint: 9.28.0 1803 | ts-api-utils: 2.1.0(typescript@5.8.3) 1804 | typescript: 5.8.3 1805 | transitivePeerDependencies: 1806 | - supports-color 1807 | 1808 | '@typescript-eslint/types@8.33.0': {} 1809 | 1810 | '@typescript-eslint/typescript-estree@8.33.0(typescript@5.8.3)': 1811 | dependencies: 1812 | '@typescript-eslint/project-service': 8.33.0(typescript@5.8.3) 1813 | '@typescript-eslint/tsconfig-utils': 8.33.0(typescript@5.8.3) 1814 | '@typescript-eslint/types': 8.33.0 1815 | '@typescript-eslint/visitor-keys': 8.33.0 1816 | debug: 4.4.1 1817 | fast-glob: 3.3.3 1818 | is-glob: 4.0.3 1819 | minimatch: 9.0.5 1820 | semver: 7.7.2 1821 | ts-api-utils: 2.1.0(typescript@5.8.3) 1822 | typescript: 5.8.3 1823 | transitivePeerDependencies: 1824 | - supports-color 1825 | 1826 | '@typescript-eslint/utils@8.33.0(eslint@9.28.0)(typescript@5.8.3)': 1827 | dependencies: 1828 | '@eslint-community/eslint-utils': 4.7.0(eslint@9.28.0) 1829 | '@typescript-eslint/scope-manager': 8.33.0 1830 | '@typescript-eslint/types': 8.33.0 1831 | '@typescript-eslint/typescript-estree': 8.33.0(typescript@5.8.3) 1832 | eslint: 9.28.0 1833 | typescript: 5.8.3 1834 | transitivePeerDependencies: 1835 | - supports-color 1836 | 1837 | '@typescript-eslint/visitor-keys@8.33.0': 1838 | dependencies: 1839 | '@typescript-eslint/types': 8.33.0 1840 | eslint-visitor-keys: 4.2.0 1841 | 1842 | '@vitest/expect@3.1.4': 1843 | dependencies: 1844 | '@vitest/spy': 3.1.4 1845 | '@vitest/utils': 3.1.4 1846 | chai: 5.2.0 1847 | tinyrainbow: 2.0.0 1848 | 1849 | '@vitest/mocker@3.1.4(vite@6.3.5(@types/node@22.15.29)(tsx@4.19.4))': 1850 | dependencies: 1851 | '@vitest/spy': 3.1.4 1852 | estree-walker: 3.0.3 1853 | magic-string: 0.30.17 1854 | optionalDependencies: 1855 | vite: 6.3.5(@types/node@22.15.29)(tsx@4.19.4) 1856 | 1857 | '@vitest/pretty-format@3.1.4': 1858 | dependencies: 1859 | tinyrainbow: 2.0.0 1860 | 1861 | '@vitest/runner@3.1.4': 1862 | dependencies: 1863 | '@vitest/utils': 3.1.4 1864 | pathe: 2.0.3 1865 | 1866 | '@vitest/snapshot@3.1.4': 1867 | dependencies: 1868 | '@vitest/pretty-format': 3.1.4 1869 | magic-string: 0.30.17 1870 | pathe: 2.0.3 1871 | 1872 | '@vitest/spy@3.1.4': 1873 | dependencies: 1874 | tinyspy: 3.0.2 1875 | 1876 | '@vitest/utils@3.1.4': 1877 | dependencies: 1878 | '@vitest/pretty-format': 3.1.4 1879 | loupe: 3.1.3 1880 | tinyrainbow: 2.0.0 1881 | 1882 | acorn-jsx@5.3.2(acorn@8.14.1): 1883 | dependencies: 1884 | acorn: 8.14.1 1885 | 1886 | acorn@8.14.1: {} 1887 | 1888 | ai@4.3.16(react@19.1.0)(zod@3.25.42): 1889 | dependencies: 1890 | '@ai-sdk/provider': 1.1.3 1891 | '@ai-sdk/provider-utils': 2.2.8(zod@3.25.42) 1892 | '@ai-sdk/react': 1.2.12(react@19.1.0)(zod@3.25.42) 1893 | '@ai-sdk/ui-utils': 1.2.11(zod@3.25.42) 1894 | '@opentelemetry/api': 1.9.0 1895 | jsondiffpatch: 0.6.0 1896 | zod: 3.25.42 1897 | optionalDependencies: 1898 | react: 19.1.0 1899 | 1900 | ajv@6.12.6: 1901 | dependencies: 1902 | fast-deep-equal: 3.1.3 1903 | fast-json-stable-stringify: 2.1.0 1904 | json-schema-traverse: 0.4.1 1905 | uri-js: 4.4.1 1906 | 1907 | ansi-regex@5.0.1: {} 1908 | 1909 | ansi-regex@6.1.0: {} 1910 | 1911 | ansi-styles@4.3.0: 1912 | dependencies: 1913 | color-convert: 2.0.1 1914 | 1915 | ansi-styles@6.2.1: {} 1916 | 1917 | any-promise@1.3.0: {} 1918 | 1919 | argparse@2.0.1: {} 1920 | 1921 | assertion-error@2.0.1: {} 1922 | 1923 | balanced-match@1.0.2: {} 1924 | 1925 | brace-expansion@1.1.11: 1926 | dependencies: 1927 | balanced-match: 1.0.2 1928 | concat-map: 0.0.1 1929 | 1930 | brace-expansion@2.0.1: 1931 | dependencies: 1932 | balanced-match: 1.0.2 1933 | 1934 | braces@3.0.3: 1935 | dependencies: 1936 | fill-range: 7.1.1 1937 | 1938 | bundle-require@5.1.0(esbuild@0.25.4): 1939 | dependencies: 1940 | esbuild: 0.25.4 1941 | load-tsconfig: 0.2.5 1942 | 1943 | cac@6.7.14: {} 1944 | 1945 | callsites@3.1.0: {} 1946 | 1947 | chai@5.2.0: 1948 | dependencies: 1949 | assertion-error: 2.0.1 1950 | check-error: 2.1.1 1951 | deep-eql: 5.0.2 1952 | loupe: 3.1.3 1953 | pathval: 2.0.0 1954 | 1955 | chalk@4.1.2: 1956 | dependencies: 1957 | ansi-styles: 4.3.0 1958 | supports-color: 7.2.0 1959 | 1960 | chalk@5.4.1: {} 1961 | 1962 | check-error@2.1.1: {} 1963 | 1964 | chokidar@4.0.3: 1965 | dependencies: 1966 | readdirp: 4.1.2 1967 | 1968 | citty@0.1.6: 1969 | dependencies: 1970 | consola: 3.4.2 1971 | 1972 | cli-cursor@5.0.0: 1973 | dependencies: 1974 | restore-cursor: 5.1.0 1975 | 1976 | cli-spinners@2.9.2: {} 1977 | 1978 | color-convert@2.0.1: 1979 | dependencies: 1980 | color-name: 1.1.4 1981 | 1982 | color-name@1.1.4: {} 1983 | 1984 | commander@4.1.1: {} 1985 | 1986 | concat-map@0.0.1: {} 1987 | 1988 | confbox@0.1.8: {} 1989 | 1990 | consola@3.4.2: {} 1991 | 1992 | cross-spawn@7.0.6: 1993 | dependencies: 1994 | path-key: 3.1.1 1995 | shebang-command: 2.0.0 1996 | which: 2.0.2 1997 | 1998 | debug@4.4.1: 1999 | dependencies: 2000 | ms: 2.1.3 2001 | 2002 | deep-eql@5.0.2: {} 2003 | 2004 | deep-is@0.1.4: {} 2005 | 2006 | dequal@2.0.3: {} 2007 | 2008 | diff-match-patch@1.0.5: {} 2009 | 2010 | dotenv@16.5.0: {} 2011 | 2012 | eastasianwidth@0.2.0: {} 2013 | 2014 | emoji-regex@10.4.0: {} 2015 | 2016 | emoji-regex@8.0.0: {} 2017 | 2018 | emoji-regex@9.2.2: {} 2019 | 2020 | es-module-lexer@1.7.0: {} 2021 | 2022 | esbuild@0.25.4: 2023 | optionalDependencies: 2024 | '@esbuild/aix-ppc64': 0.25.4 2025 | '@esbuild/android-arm': 0.25.4 2026 | '@esbuild/android-arm64': 0.25.4 2027 | '@esbuild/android-x64': 0.25.4 2028 | '@esbuild/darwin-arm64': 0.25.4 2029 | '@esbuild/darwin-x64': 0.25.4 2030 | '@esbuild/freebsd-arm64': 0.25.4 2031 | '@esbuild/freebsd-x64': 0.25.4 2032 | '@esbuild/linux-arm': 0.25.4 2033 | '@esbuild/linux-arm64': 0.25.4 2034 | '@esbuild/linux-ia32': 0.25.4 2035 | '@esbuild/linux-loong64': 0.25.4 2036 | '@esbuild/linux-mips64el': 0.25.4 2037 | '@esbuild/linux-ppc64': 0.25.4 2038 | '@esbuild/linux-riscv64': 0.25.4 2039 | '@esbuild/linux-s390x': 0.25.4 2040 | '@esbuild/linux-x64': 0.25.4 2041 | '@esbuild/netbsd-arm64': 0.25.4 2042 | '@esbuild/netbsd-x64': 0.25.4 2043 | '@esbuild/openbsd-arm64': 0.25.4 2044 | '@esbuild/openbsd-x64': 0.25.4 2045 | '@esbuild/sunos-x64': 0.25.4 2046 | '@esbuild/win32-arm64': 0.25.4 2047 | '@esbuild/win32-ia32': 0.25.4 2048 | '@esbuild/win32-x64': 0.25.4 2049 | 2050 | escape-string-regexp@4.0.0: {} 2051 | 2052 | eslint-scope@8.3.0: 2053 | dependencies: 2054 | esrecurse: 4.3.0 2055 | estraverse: 5.3.0 2056 | 2057 | eslint-visitor-keys@3.4.3: {} 2058 | 2059 | eslint-visitor-keys@4.2.0: {} 2060 | 2061 | eslint@9.28.0: 2062 | dependencies: 2063 | '@eslint-community/eslint-utils': 4.7.0(eslint@9.28.0) 2064 | '@eslint-community/regexpp': 4.12.1 2065 | '@eslint/config-array': 0.20.0 2066 | '@eslint/config-helpers': 0.2.2 2067 | '@eslint/core': 0.14.0 2068 | '@eslint/eslintrc': 3.3.1 2069 | '@eslint/js': 9.28.0 2070 | '@eslint/plugin-kit': 0.3.1 2071 | '@humanfs/node': 0.16.6 2072 | '@humanwhocodes/module-importer': 1.0.1 2073 | '@humanwhocodes/retry': 0.4.3 2074 | '@types/estree': 1.0.7 2075 | '@types/json-schema': 7.0.15 2076 | ajv: 6.12.6 2077 | chalk: 4.1.2 2078 | cross-spawn: 7.0.6 2079 | debug: 4.4.1 2080 | escape-string-regexp: 4.0.0 2081 | eslint-scope: 8.3.0 2082 | eslint-visitor-keys: 4.2.0 2083 | espree: 10.3.0 2084 | esquery: 1.6.0 2085 | esutils: 2.0.3 2086 | fast-deep-equal: 3.1.3 2087 | file-entry-cache: 8.0.0 2088 | find-up: 5.0.0 2089 | glob-parent: 6.0.2 2090 | ignore: 5.3.2 2091 | imurmurhash: 0.1.4 2092 | is-glob: 4.0.3 2093 | json-stable-stringify-without-jsonify: 1.0.1 2094 | lodash.merge: 4.6.2 2095 | minimatch: 3.1.2 2096 | natural-compare: 1.4.0 2097 | optionator: 0.9.4 2098 | transitivePeerDependencies: 2099 | - supports-color 2100 | 2101 | espree@10.3.0: 2102 | dependencies: 2103 | acorn: 8.14.1 2104 | acorn-jsx: 5.3.2(acorn@8.14.1) 2105 | eslint-visitor-keys: 4.2.0 2106 | 2107 | esquery@1.6.0: 2108 | dependencies: 2109 | estraverse: 5.3.0 2110 | 2111 | esrecurse@4.3.0: 2112 | dependencies: 2113 | estraverse: 5.3.0 2114 | 2115 | estraverse@5.3.0: {} 2116 | 2117 | estree-walker@3.0.3: 2118 | dependencies: 2119 | '@types/estree': 1.0.7 2120 | 2121 | esutils@2.0.3: {} 2122 | 2123 | expect-type@1.2.1: {} 2124 | 2125 | fast-deep-equal@3.1.3: {} 2126 | 2127 | fast-glob@3.3.3: 2128 | dependencies: 2129 | '@nodelib/fs.stat': 2.0.5 2130 | '@nodelib/fs.walk': 1.2.8 2131 | glob-parent: 5.1.2 2132 | merge2: 1.4.1 2133 | micromatch: 4.0.8 2134 | 2135 | fast-json-stable-stringify@2.1.0: {} 2136 | 2137 | fast-levenshtein@2.0.6: {} 2138 | 2139 | fastq@1.19.1: 2140 | dependencies: 2141 | reusify: 1.1.0 2142 | 2143 | fdir@6.4.4(picomatch@4.0.2): 2144 | optionalDependencies: 2145 | picomatch: 4.0.2 2146 | 2147 | file-entry-cache@8.0.0: 2148 | dependencies: 2149 | flat-cache: 4.0.1 2150 | 2151 | fill-range@7.1.1: 2152 | dependencies: 2153 | to-regex-range: 5.0.1 2154 | 2155 | find-up@5.0.0: 2156 | dependencies: 2157 | locate-path: 6.0.0 2158 | path-exists: 4.0.0 2159 | 2160 | fix-dts-default-cjs-exports@1.0.1: 2161 | dependencies: 2162 | magic-string: 0.30.17 2163 | mlly: 1.7.4 2164 | rollup: 4.41.1 2165 | 2166 | flat-cache@4.0.1: 2167 | dependencies: 2168 | flatted: 3.3.3 2169 | keyv: 4.5.4 2170 | 2171 | flatted@3.3.3: {} 2172 | 2173 | foreground-child@3.3.1: 2174 | dependencies: 2175 | cross-spawn: 7.0.6 2176 | signal-exit: 4.1.0 2177 | 2178 | fsevents@2.3.3: 2179 | optional: true 2180 | 2181 | get-east-asian-width@1.3.0: {} 2182 | 2183 | get-tsconfig@4.10.1: 2184 | dependencies: 2185 | resolve-pkg-maps: 1.0.0 2186 | 2187 | glob-parent@5.1.2: 2188 | dependencies: 2189 | is-glob: 4.0.3 2190 | 2191 | glob-parent@6.0.2: 2192 | dependencies: 2193 | is-glob: 4.0.3 2194 | 2195 | glob@10.4.5: 2196 | dependencies: 2197 | foreground-child: 3.3.1 2198 | jackspeak: 3.4.3 2199 | minimatch: 9.0.5 2200 | minipass: 7.1.2 2201 | package-json-from-dist: 1.0.1 2202 | path-scurry: 1.11.1 2203 | 2204 | globals@14.0.0: {} 2205 | 2206 | graphemer@1.4.0: {} 2207 | 2208 | has-flag@4.0.0: {} 2209 | 2210 | ignore@5.3.2: {} 2211 | 2212 | ignore@7.0.5: {} 2213 | 2214 | import-fresh@3.3.1: 2215 | dependencies: 2216 | parent-module: 1.0.1 2217 | resolve-from: 4.0.0 2218 | 2219 | imurmurhash@0.1.4: {} 2220 | 2221 | is-extglob@2.1.1: {} 2222 | 2223 | is-fullwidth-code-point@3.0.0: {} 2224 | 2225 | is-glob@4.0.3: 2226 | dependencies: 2227 | is-extglob: 2.1.1 2228 | 2229 | is-interactive@2.0.0: {} 2230 | 2231 | is-number@7.0.0: {} 2232 | 2233 | is-unicode-supported@1.3.0: {} 2234 | 2235 | is-unicode-supported@2.1.0: {} 2236 | 2237 | isexe@2.0.0: {} 2238 | 2239 | jackspeak@3.4.3: 2240 | dependencies: 2241 | '@isaacs/cliui': 8.0.2 2242 | optionalDependencies: 2243 | '@pkgjs/parseargs': 0.11.0 2244 | 2245 | joycon@3.1.1: {} 2246 | 2247 | js-yaml@4.1.0: 2248 | dependencies: 2249 | argparse: 2.0.1 2250 | 2251 | json-buffer@3.0.1: {} 2252 | 2253 | json-schema-traverse@0.4.1: {} 2254 | 2255 | json-schema@0.4.0: {} 2256 | 2257 | json-stable-stringify-without-jsonify@1.0.1: {} 2258 | 2259 | jsondiffpatch@0.6.0: 2260 | dependencies: 2261 | '@types/diff-match-patch': 1.0.36 2262 | chalk: 5.4.1 2263 | diff-match-patch: 1.0.5 2264 | 2265 | keyv@4.5.4: 2266 | dependencies: 2267 | json-buffer: 3.0.1 2268 | 2269 | levn@0.4.1: 2270 | dependencies: 2271 | prelude-ls: 1.2.1 2272 | type-check: 0.4.0 2273 | 2274 | lilconfig@3.1.3: {} 2275 | 2276 | lines-and-columns@1.2.4: {} 2277 | 2278 | load-tsconfig@0.2.5: {} 2279 | 2280 | locate-path@6.0.0: 2281 | dependencies: 2282 | p-locate: 5.0.0 2283 | 2284 | lodash.merge@4.6.2: {} 2285 | 2286 | lodash.sortby@4.7.0: {} 2287 | 2288 | log-symbols@6.0.0: 2289 | dependencies: 2290 | chalk: 5.4.1 2291 | is-unicode-supported: 1.3.0 2292 | 2293 | loupe@3.1.3: {} 2294 | 2295 | lru-cache@10.4.3: {} 2296 | 2297 | magic-string@0.30.17: 2298 | dependencies: 2299 | '@jridgewell/sourcemap-codec': 1.5.0 2300 | 2301 | merge2@1.4.1: {} 2302 | 2303 | micromatch@4.0.8: 2304 | dependencies: 2305 | braces: 3.0.3 2306 | picomatch: 2.3.1 2307 | 2308 | mimic-function@5.0.1: {} 2309 | 2310 | minimatch@10.0.1: 2311 | dependencies: 2312 | brace-expansion: 2.0.1 2313 | 2314 | minimatch@3.1.2: 2315 | dependencies: 2316 | brace-expansion: 1.1.11 2317 | 2318 | minimatch@9.0.5: 2319 | dependencies: 2320 | brace-expansion: 2.0.1 2321 | 2322 | minipass@7.1.2: {} 2323 | 2324 | mlly@1.7.4: 2325 | dependencies: 2326 | acorn: 8.14.1 2327 | pathe: 2.0.3 2328 | pkg-types: 1.3.1 2329 | ufo: 1.6.1 2330 | 2331 | ms@2.1.3: {} 2332 | 2333 | mz@2.7.0: 2334 | dependencies: 2335 | any-promise: 1.3.0 2336 | object-assign: 4.1.1 2337 | thenify-all: 1.6.0 2338 | 2339 | nanoid@3.3.11: {} 2340 | 2341 | natural-compare@1.4.0: {} 2342 | 2343 | object-assign@4.1.1: {} 2344 | 2345 | onetime@7.0.0: 2346 | dependencies: 2347 | mimic-function: 5.0.1 2348 | 2349 | optionator@0.9.4: 2350 | dependencies: 2351 | deep-is: 0.1.4 2352 | fast-levenshtein: 2.0.6 2353 | levn: 0.4.1 2354 | prelude-ls: 1.2.1 2355 | type-check: 0.4.0 2356 | word-wrap: 1.2.5 2357 | 2358 | ora@8.2.0: 2359 | dependencies: 2360 | chalk: 5.4.1 2361 | cli-cursor: 5.0.0 2362 | cli-spinners: 2.9.2 2363 | is-interactive: 2.0.0 2364 | is-unicode-supported: 2.1.0 2365 | log-symbols: 6.0.0 2366 | stdin-discarder: 0.2.2 2367 | string-width: 7.2.0 2368 | strip-ansi: 7.1.0 2369 | 2370 | p-limit@3.1.0: 2371 | dependencies: 2372 | yocto-queue: 0.1.0 2373 | 2374 | p-locate@5.0.0: 2375 | dependencies: 2376 | p-limit: 3.1.0 2377 | 2378 | package-json-from-dist@1.0.1: {} 2379 | 2380 | parent-module@1.0.1: 2381 | dependencies: 2382 | callsites: 3.1.0 2383 | 2384 | path-exists@4.0.0: {} 2385 | 2386 | path-key@3.1.1: {} 2387 | 2388 | path-scurry@1.11.1: 2389 | dependencies: 2390 | lru-cache: 10.4.3 2391 | minipass: 7.1.2 2392 | 2393 | pathe@2.0.3: {} 2394 | 2395 | pathval@2.0.0: {} 2396 | 2397 | picocolors@1.1.1: {} 2398 | 2399 | picomatch@2.3.1: {} 2400 | 2401 | picomatch@4.0.2: {} 2402 | 2403 | pirates@4.0.7: {} 2404 | 2405 | pkg-types@1.3.1: 2406 | dependencies: 2407 | confbox: 0.1.8 2408 | mlly: 1.7.4 2409 | pathe: 2.0.3 2410 | 2411 | postcss-load-config@6.0.1(postcss@8.5.3)(tsx@4.19.4): 2412 | dependencies: 2413 | lilconfig: 3.1.3 2414 | optionalDependencies: 2415 | postcss: 8.5.3 2416 | tsx: 4.19.4 2417 | 2418 | postcss@8.5.3: 2419 | dependencies: 2420 | nanoid: 3.3.11 2421 | picocolors: 1.1.1 2422 | source-map-js: 1.2.1 2423 | 2424 | prelude-ls@1.2.1: {} 2425 | 2426 | punycode@2.3.1: {} 2427 | 2428 | queue-microtask@1.2.3: {} 2429 | 2430 | react@19.1.0: {} 2431 | 2432 | readdirp@4.1.2: {} 2433 | 2434 | resolve-from@4.0.0: {} 2435 | 2436 | resolve-from@5.0.0: {} 2437 | 2438 | resolve-pkg-maps@1.0.0: {} 2439 | 2440 | restore-cursor@5.1.0: 2441 | dependencies: 2442 | onetime: 7.0.0 2443 | signal-exit: 4.1.0 2444 | 2445 | reusify@1.1.0: {} 2446 | 2447 | rollup@4.41.1: 2448 | dependencies: 2449 | '@types/estree': 1.0.7 2450 | optionalDependencies: 2451 | '@rollup/rollup-android-arm-eabi': 4.41.1 2452 | '@rollup/rollup-android-arm64': 4.41.1 2453 | '@rollup/rollup-darwin-arm64': 4.41.1 2454 | '@rollup/rollup-darwin-x64': 4.41.1 2455 | '@rollup/rollup-freebsd-arm64': 4.41.1 2456 | '@rollup/rollup-freebsd-x64': 4.41.1 2457 | '@rollup/rollup-linux-arm-gnueabihf': 4.41.1 2458 | '@rollup/rollup-linux-arm-musleabihf': 4.41.1 2459 | '@rollup/rollup-linux-arm64-gnu': 4.41.1 2460 | '@rollup/rollup-linux-arm64-musl': 4.41.1 2461 | '@rollup/rollup-linux-loongarch64-gnu': 4.41.1 2462 | '@rollup/rollup-linux-powerpc64le-gnu': 4.41.1 2463 | '@rollup/rollup-linux-riscv64-gnu': 4.41.1 2464 | '@rollup/rollup-linux-riscv64-musl': 4.41.1 2465 | '@rollup/rollup-linux-s390x-gnu': 4.41.1 2466 | '@rollup/rollup-linux-x64-gnu': 4.41.1 2467 | '@rollup/rollup-linux-x64-musl': 4.41.1 2468 | '@rollup/rollup-win32-arm64-msvc': 4.41.1 2469 | '@rollup/rollup-win32-ia32-msvc': 4.41.1 2470 | '@rollup/rollup-win32-x64-msvc': 4.41.1 2471 | fsevents: 2.3.3 2472 | 2473 | run-parallel@1.2.0: 2474 | dependencies: 2475 | queue-microtask: 1.2.3 2476 | 2477 | secure-json-parse@2.7.0: {} 2478 | 2479 | semver@7.7.2: {} 2480 | 2481 | shebang-command@2.0.0: 2482 | dependencies: 2483 | shebang-regex: 3.0.0 2484 | 2485 | shebang-regex@3.0.0: {} 2486 | 2487 | shell-quote@1.8.2: {} 2488 | 2489 | siginfo@2.0.0: {} 2490 | 2491 | signal-exit@4.1.0: {} 2492 | 2493 | source-map-js@1.2.1: {} 2494 | 2495 | source-map@0.8.0-beta.0: 2496 | dependencies: 2497 | whatwg-url: 7.1.0 2498 | 2499 | stackback@0.0.2: {} 2500 | 2501 | std-env@3.9.0: {} 2502 | 2503 | stdin-discarder@0.2.2: {} 2504 | 2505 | string-width@4.2.3: 2506 | dependencies: 2507 | emoji-regex: 8.0.0 2508 | is-fullwidth-code-point: 3.0.0 2509 | strip-ansi: 6.0.1 2510 | 2511 | string-width@5.1.2: 2512 | dependencies: 2513 | eastasianwidth: 0.2.0 2514 | emoji-regex: 9.2.2 2515 | strip-ansi: 7.1.0 2516 | 2517 | string-width@7.2.0: 2518 | dependencies: 2519 | emoji-regex: 10.4.0 2520 | get-east-asian-width: 1.3.0 2521 | strip-ansi: 7.1.0 2522 | 2523 | strip-ansi@6.0.1: 2524 | dependencies: 2525 | ansi-regex: 5.0.1 2526 | 2527 | strip-ansi@7.1.0: 2528 | dependencies: 2529 | ansi-regex: 6.1.0 2530 | 2531 | strip-json-comments@3.1.1: {} 2532 | 2533 | sucrase@3.35.0: 2534 | dependencies: 2535 | '@jridgewell/gen-mapping': 0.3.8 2536 | commander: 4.1.1 2537 | glob: 10.4.5 2538 | lines-and-columns: 1.2.4 2539 | mz: 2.7.0 2540 | pirates: 4.0.7 2541 | ts-interface-checker: 0.1.13 2542 | 2543 | supports-color@7.2.0: 2544 | dependencies: 2545 | has-flag: 4.0.0 2546 | 2547 | swr@2.3.3(react@19.1.0): 2548 | dependencies: 2549 | dequal: 2.0.3 2550 | react: 19.1.0 2551 | use-sync-external-store: 1.5.0(react@19.1.0) 2552 | 2553 | thenify-all@1.6.0: 2554 | dependencies: 2555 | thenify: 3.3.1 2556 | 2557 | thenify@3.3.1: 2558 | dependencies: 2559 | any-promise: 1.3.0 2560 | 2561 | throttleit@2.1.0: {} 2562 | 2563 | tinybench@2.9.0: {} 2564 | 2565 | tinyexec@0.3.2: {} 2566 | 2567 | tinyglobby@0.2.14: 2568 | dependencies: 2569 | fdir: 6.4.4(picomatch@4.0.2) 2570 | picomatch: 4.0.2 2571 | 2572 | tinypool@1.0.2: {} 2573 | 2574 | tinyrainbow@2.0.0: {} 2575 | 2576 | tinyspy@3.0.2: {} 2577 | 2578 | to-regex-range@5.0.1: 2579 | dependencies: 2580 | is-number: 7.0.0 2581 | 2582 | tr46@1.0.1: 2583 | dependencies: 2584 | punycode: 2.3.1 2585 | 2586 | tree-kill@1.2.2: {} 2587 | 2588 | ts-api-utils@2.1.0(typescript@5.8.3): 2589 | dependencies: 2590 | typescript: 5.8.3 2591 | 2592 | ts-interface-checker@0.1.13: {} 2593 | 2594 | tsup@8.5.0(postcss@8.5.3)(tsx@4.19.4)(typescript@5.8.3): 2595 | dependencies: 2596 | bundle-require: 5.1.0(esbuild@0.25.4) 2597 | cac: 6.7.14 2598 | chokidar: 4.0.3 2599 | consola: 3.4.2 2600 | debug: 4.4.1 2601 | esbuild: 0.25.4 2602 | fix-dts-default-cjs-exports: 1.0.1 2603 | joycon: 3.1.1 2604 | picocolors: 1.1.1 2605 | postcss-load-config: 6.0.1(postcss@8.5.3)(tsx@4.19.4) 2606 | resolve-from: 5.0.0 2607 | rollup: 4.41.1 2608 | source-map: 0.8.0-beta.0 2609 | sucrase: 3.35.0 2610 | tinyexec: 0.3.2 2611 | tinyglobby: 0.2.14 2612 | tree-kill: 1.2.2 2613 | optionalDependencies: 2614 | postcss: 8.5.3 2615 | typescript: 5.8.3 2616 | transitivePeerDependencies: 2617 | - jiti 2618 | - supports-color 2619 | - tsx 2620 | - yaml 2621 | 2622 | tsx@4.19.4: 2623 | dependencies: 2624 | esbuild: 0.25.4 2625 | get-tsconfig: 4.10.1 2626 | optionalDependencies: 2627 | fsevents: 2.3.3 2628 | 2629 | type-check@0.4.0: 2630 | dependencies: 2631 | prelude-ls: 1.2.1 2632 | 2633 | typescript-eslint@8.33.0(eslint@9.28.0)(typescript@5.8.3): 2634 | dependencies: 2635 | '@typescript-eslint/eslint-plugin': 8.33.0(@typescript-eslint/parser@8.33.0(eslint@9.28.0)(typescript@5.8.3))(eslint@9.28.0)(typescript@5.8.3) 2636 | '@typescript-eslint/parser': 8.33.0(eslint@9.28.0)(typescript@5.8.3) 2637 | '@typescript-eslint/utils': 8.33.0(eslint@9.28.0)(typescript@5.8.3) 2638 | eslint: 9.28.0 2639 | typescript: 5.8.3 2640 | transitivePeerDependencies: 2641 | - supports-color 2642 | 2643 | typescript@5.8.3: {} 2644 | 2645 | ufo@1.6.1: {} 2646 | 2647 | undici-types@6.21.0: {} 2648 | 2649 | uri-js@4.4.1: 2650 | dependencies: 2651 | punycode: 2.3.1 2652 | 2653 | use-sync-external-store@1.5.0(react@19.1.0): 2654 | dependencies: 2655 | react: 19.1.0 2656 | 2657 | vite-node@3.1.4(@types/node@22.15.29)(tsx@4.19.4): 2658 | dependencies: 2659 | cac: 6.7.14 2660 | debug: 4.4.1 2661 | es-module-lexer: 1.7.0 2662 | pathe: 2.0.3 2663 | vite: 6.3.5(@types/node@22.15.29)(tsx@4.19.4) 2664 | transitivePeerDependencies: 2665 | - '@types/node' 2666 | - jiti 2667 | - less 2668 | - lightningcss 2669 | - sass 2670 | - sass-embedded 2671 | - stylus 2672 | - sugarss 2673 | - supports-color 2674 | - terser 2675 | - tsx 2676 | - yaml 2677 | 2678 | vite@6.3.5(@types/node@22.15.29)(tsx@4.19.4): 2679 | dependencies: 2680 | esbuild: 0.25.4 2681 | fdir: 6.4.4(picomatch@4.0.2) 2682 | picomatch: 4.0.2 2683 | postcss: 8.5.3 2684 | rollup: 4.41.1 2685 | tinyglobby: 0.2.14 2686 | optionalDependencies: 2687 | '@types/node': 22.15.29 2688 | fsevents: 2.3.3 2689 | tsx: 4.19.4 2690 | 2691 | vitest@3.1.4(@types/node@22.15.29)(tsx@4.19.4): 2692 | dependencies: 2693 | '@vitest/expect': 3.1.4 2694 | '@vitest/mocker': 3.1.4(vite@6.3.5(@types/node@22.15.29)(tsx@4.19.4)) 2695 | '@vitest/pretty-format': 3.1.4 2696 | '@vitest/runner': 3.1.4 2697 | '@vitest/snapshot': 3.1.4 2698 | '@vitest/spy': 3.1.4 2699 | '@vitest/utils': 3.1.4 2700 | chai: 5.2.0 2701 | debug: 4.4.1 2702 | expect-type: 1.2.1 2703 | magic-string: 0.30.17 2704 | pathe: 2.0.3 2705 | std-env: 3.9.0 2706 | tinybench: 2.9.0 2707 | tinyexec: 0.3.2 2708 | tinyglobby: 0.2.14 2709 | tinypool: 1.0.2 2710 | tinyrainbow: 2.0.0 2711 | vite: 6.3.5(@types/node@22.15.29)(tsx@4.19.4) 2712 | vite-node: 3.1.4(@types/node@22.15.29)(tsx@4.19.4) 2713 | why-is-node-running: 2.3.0 2714 | optionalDependencies: 2715 | '@types/node': 22.15.29 2716 | transitivePeerDependencies: 2717 | - jiti 2718 | - less 2719 | - lightningcss 2720 | - msw 2721 | - sass 2722 | - sass-embedded 2723 | - stylus 2724 | - sugarss 2725 | - supports-color 2726 | - terser 2727 | - tsx 2728 | - yaml 2729 | 2730 | webidl-conversions@4.0.2: {} 2731 | 2732 | whatwg-url@7.1.0: 2733 | dependencies: 2734 | lodash.sortby: 4.7.0 2735 | tr46: 1.0.1 2736 | webidl-conversions: 4.0.2 2737 | 2738 | which@2.0.2: 2739 | dependencies: 2740 | isexe: 2.0.0 2741 | 2742 | why-is-node-running@2.3.0: 2743 | dependencies: 2744 | siginfo: 2.0.0 2745 | stackback: 0.0.2 2746 | 2747 | word-wrap@1.2.5: {} 2748 | 2749 | wrap-ansi@7.0.0: 2750 | dependencies: 2751 | ansi-styles: 4.3.0 2752 | string-width: 4.2.3 2753 | strip-ansi: 6.0.1 2754 | 2755 | wrap-ansi@8.1.0: 2756 | dependencies: 2757 | ansi-styles: 6.2.1 2758 | string-width: 5.1.2 2759 | strip-ansi: 7.1.0 2760 | 2761 | yocto-queue@0.1.0: {} 2762 | 2763 | zod-to-json-schema@3.24.5(zod@3.25.42): 2764 | dependencies: 2765 | zod: 3.25.42 2766 | 2767 | zod@3.25.42: {} 2768 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | onlyBuiltDependencies: 2 | - esbuild 3 | - ignores 4 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": ["config:recommended"], 4 | "lockFileMaintenance": { 5 | "enabled": true, 6 | "automerge": true 7 | }, 8 | "packageRules": [ 9 | { 10 | "matchUpdateTypes": ["minor", "patch"], 11 | "matchCurrentVersion": "!/^0/", 12 | "automerge": true 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /src/bin-test.ts: -------------------------------------------------------------------------------- 1 | async function main() {} 2 | 3 | void main(); 4 | -------------------------------------------------------------------------------- /src/bin.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import { defineCommand, runMain } from "citty"; 4 | import { consola } from "consola"; 5 | import { watch } from "./watch.js"; 6 | 7 | if ( 8 | process.env["DEBUG"] === "true" || 9 | process.env["DEBUG"] === "1" || 10 | process.env["DEBUG"] === "yes" 11 | ) 12 | consola.level = 5; 13 | else consola.level = 3; 14 | consola.options.formatOptions = { 15 | compact: true, 16 | }; 17 | const main = defineCommand({ 18 | meta: { 19 | name: "hands-please", 20 | version: "0.0.5", 21 | description: "Run CLI code agents based on comments in your codebase.", 22 | }, 23 | args: { 24 | agent: { 25 | type: "string", 26 | required: true, 27 | description: 28 | "The CLI code agent command, needs to accept prompt from stdin", 29 | }, 30 | check: { 31 | type: "string", 32 | required: true, 33 | description: "The command to check the full codebase", 34 | }, 35 | trigger: { 36 | type: "string", 37 | description: "The tag that hands-please looks for to trigger the agent", 38 | default: "@ai", 39 | }, 40 | fileCheck: { 41 | type: "string", 42 | description: 43 | "The command to check specific files, must accept a list of files as arguments", 44 | }, 45 | skipWatch: { 46 | type: "boolean", 47 | description: 48 | "Whether to skip watching for changes (exit process after all comments are processed)", 49 | default: false, 50 | }, 51 | }, 52 | run({ args }) { 53 | return watch({ 54 | agentCommand: args.agent, 55 | checkCommand: args.check, 56 | skipWatch: args.skipWatch, 57 | trigger: args.trigger, 58 | fileCheckCommand: args.fileCheck, 59 | }); 60 | }, 61 | }); 62 | 63 | void runMain(main).catch(consola.error); 64 | -------------------------------------------------------------------------------- /src/comment.test.ts: -------------------------------------------------------------------------------- 1 | import { parse } from "./comment.js"; 2 | import { it, expect, describe } from "vitest"; 3 | 4 | const trigger = "@foo"; 5 | 6 | describe("parse()", () => { 7 | it("should handle import statements and track line numbers correctly", () => { 8 | const comments = parse({ 9 | trigger, 10 | filepath: "imports.js", 11 | content: `import React from 'react'; 12 | import { useState, useEffect } from 'react'; 13 | import axios from 'axios'; 14 | 15 | // ${trigger} implement API fetching logic 16 | function DataFetcher() { 17 | return null; 18 | } 19 | `, 20 | }); 21 | expect(comments).toHaveLength(1); 22 | expect(comments[0]?.comment).toEqual("implement API fetching logic"); 23 | expect(comments[0]?.filepath).toEqual("imports.js"); 24 | expect(comments[0]?.line).toEqual(4); // Line number should count from the start, including imports 25 | }); 26 | }); 27 | 28 | describe("parseComments() additional cases", () => { 29 | it("should handle when first line is @ai and the next line is a comment", () => { 30 | const comments = parse({ 31 | trigger, 32 | filepath: "firstline.js", 33 | content: `// ${trigger} 34 | // This is a regular comment 35 | function example() { 36 | return true; 37 | }`, 38 | }); 39 | expect(comments).toHaveLength(1); 40 | expect(comments[0]?.comment).toEqual("\nThis is a regular comment"); 41 | expect(comments[0]?.filepath).toEqual("firstline.js"); 42 | expect(comments[0]?.line).toEqual(0); 43 | }); 44 | 45 | it("should parse comments with emojis", () => { 46 | const comments = parse({ 47 | trigger, 48 | filepath: "test.js", 49 | content: ` 50 | function emojis() { 51 | // ${trigger} emojis: 😀, 🚀, 👍 52 | } 53 | `, 54 | }); 55 | expect(comments).toHaveLength(1); 56 | expect(comments[0]?.comment).toEqual("emojis: 😀, 🚀, 👍"); 57 | expect(comments[0]?.filepath).toEqual("test.js"); 58 | expect(comments[0]?.line).toEqual(2); 59 | }); 60 | 61 | it("should parse comments with code snippets", () => { 62 | const comments = parse({ 63 | trigger, 64 | filepath: "code.js", 65 | content: ` 66 | function example() { 67 | // ${trigger} code: console.log('Hello world') 68 | return true; 69 | } 70 | `, 71 | }); 72 | expect(comments).toHaveLength(1); 73 | expect(comments[0]?.comment).toEqual("code: console.log('Hello world')"); 74 | expect(comments[0]?.filepath).toEqual("code.js"); 75 | expect(comments[0]?.line).toEqual(2); 76 | }); 77 | 78 | it("should parse multi-line comments", () => { 79 | const comments = parse({ 80 | trigger, 81 | filepath: "multiline.js", 82 | content: ` 83 | function multiLineExample() { 84 | // ${trigger} first line of a multi-line comment 85 | // second line that should be captured 86 | // ${trigger} another tagged comment line 87 | return true; 88 | } 89 | `, 90 | }); 91 | expect(comments).toHaveLength(2); 92 | expect(comments[0]?.comment).toEqual( 93 | "first line of a multi-line comment\nsecond line that should be captured" 94 | ); 95 | expect(comments[0]?.filepath).toEqual("multiline.js"); 96 | expect(comments[0]?.line).toEqual(2); 97 | expect(comments[1]?.comment).toEqual("another tagged comment line"); 98 | expect(comments[1]?.filepath).toEqual("multiline.js"); 99 | expect(comments[1]?.line).toEqual(4); 100 | }); 101 | 102 | it("should handle continuation lines with varying indentation", () => { 103 | const comments = parse({ 104 | trigger, 105 | filepath: "indentation.js", 106 | content: ` 107 | function indentationExample() { 108 | // ${trigger} first line with normal indentation 109 | // second line with extra indentation 110 | // third line with different indentation 111 | // fourth line with normal indentation 112 | return true; 113 | } 114 | `, 115 | }); 116 | expect(comments).toHaveLength(1); 117 | expect(comments[0]?.comment).toEqual( 118 | "first line with normal indentation\nsecond line with extra indentation\nthird line with different indentation\nfourth line with normal indentation" 119 | ); 120 | expect(comments[0]?.filepath).toEqual("indentation.js"); 121 | expect(comments[0]?.line).toEqual(2); 122 | }); 123 | 124 | describe("ignoring files with 'hands-please-ignore' in first line", () => { 125 | it("should ignore JavaScript files with // hands-please-ignore", () => { 126 | const comments = parse({ 127 | trigger, 128 | filepath: "javascript.js", 129 | content: `// hands-please-ignore 130 | function example() { 131 | // ${trigger} this should be ignored 132 | return true; 133 | }`, 134 | }); 135 | expect(comments).toHaveLength(0); 136 | }); 137 | 138 | it("should ignore JavaScript files with /* hands-please-ignore */", () => { 139 | const comments = parse({ 140 | trigger, 141 | filepath: "javascript-multiline.js", 142 | content: `/* hands-please-ignore */ 143 | function example() { 144 | // ${trigger} this should be ignored 145 | return true; 146 | }`, 147 | }); 148 | expect(comments).toHaveLength(0); 149 | }); 150 | 151 | it("should ignore HTML files with ", () => { 152 | const comments = parse({ 153 | trigger, 154 | filepath: "index.html", 155 | content: ` 156 | 157 | 158 | 159 |

Hello World

160 | 161 | `, 162 | }); 163 | expect(comments).toHaveLength(0); 164 | }); 165 | 166 | it("should ignore Python files with # hands-please-ignore", () => { 167 | const comments = parse({ 168 | trigger, 169 | filepath: "script.py", 170 | content: `# hands-please-ignore 171 | def example(): 172 | # ${trigger} this should be ignored 173 | return True`, 174 | }); 175 | expect(comments).toHaveLength(0); 176 | }); 177 | 178 | it("should ignore Python files with ''' hands-please-ignore", () => { 179 | const comments = parse({ 180 | trigger, 181 | filepath: "script-multiline.py", 182 | content: `''' hands-please-ignore 183 | Some docstring content 184 | ''' 185 | def example(): 186 | # ${trigger} this should be ignored 187 | return True`, 188 | }); 189 | expect(comments).toHaveLength(0); 190 | }); 191 | 192 | it("should ignore SQL files with -- hands-please-ignore", () => { 193 | const comments = parse({ 194 | trigger, 195 | filepath: "query.sql", 196 | content: `-- hands-please-ignore 197 | SELECT * FROM users 198 | -- ${trigger} this should be ignored 199 | WHERE id = 1;`, 200 | }); 201 | expect(comments).toHaveLength(0); 202 | }); 203 | }); 204 | }); 205 | -------------------------------------------------------------------------------- /src/comment.ts: -------------------------------------------------------------------------------- 1 | export type FileComment = { 2 | filepath: string; 3 | line: number; 4 | /** The actual comment line (does not capture multiple lines) */ 5 | comment: string; 6 | /** File content around the comment */ 7 | context: string; 8 | }; 9 | 10 | /** 11 | * Parse comments from comments in a file. 12 | */ 13 | export function parse({ 14 | filepath, 15 | content, 16 | trigger, 17 | }: { 18 | filepath: string; 19 | content: string; 20 | trigger: string; 21 | }): FileComment[] { 22 | // Check if the file should be ignored based on first line 23 | if (content.startsWith(`// ${trigger} ignore`)) return []; 24 | 25 | // Check for "hands-please-ignore" in various comment formats in the first line 26 | const firstLine = content.split("\n")[0]?.trim() || ""; 27 | const ignorePatterns = [ 28 | /\/\/\s*hands-please-ignore/, // JavaScript/TypeScript single-line: // hands-please-ignore 29 | /\/\*\s*hands-please-ignore\s*\*\//, // JavaScript/TypeScript multi-line: /* hands-please-ignore */ 30 | //, // HTML/XML: 31 | /#\s*hands-please-ignore/, // Python/Ruby/Shell: # hands-please-ignore 32 | /'''\s*hands-please-ignore/, // Python multi-line start: ''' hands-please-ignore 33 | /"""\s*hands-please-ignore/, // Python multi-line start: """ hands-please-ignore 34 | /--\s*hands-please-ignore/, // SQL/Lua: -- hands-please-ignore 35 | /\*\s*hands-please-ignore/, // CSS within block: * hands-please-ignore 36 | /<%--\s*hands-please-ignore\s*--%>/, // JSP: <%-- hands-please-ignore --%> 37 | /\(\*\s*hands-please-ignore\s*\*\)/, // OCaml/Pascal: (* hands-please-ignore *) 38 | ]; 39 | 40 | if (ignorePatterns.some((pattern) => pattern.test(firstLine))) { 41 | return []; 42 | } 43 | 44 | const comments: FileComment[] = []; 45 | const lines = content.split("\n"); 46 | 47 | for (const [index, line] of lines.entries()) { 48 | // Look for '//' followed by optional whitespace, then '@' + the comment prefix + whitespace + content 49 | // Match comments with content after the tag 50 | const commentPattern = new RegExp(`//\\s*${trigger}(?:\\s+(.+)|$)`); 51 | const match = line.match(commentPattern); 52 | 53 | if (match) { 54 | let comment = match[1] ? match[1].trim() : ""; 55 | let nextLine = index + 1; 56 | 57 | // Check for continuation lines (lines that start with // but don't have the tag) 58 | while ( 59 | nextLine < lines.length && 60 | lines[nextLine]?.trim().startsWith("//") && 61 | !lines[nextLine]?.includes(`${trigger}`) 62 | ) { 63 | // Extract the comment part after // 64 | const continuationMatch = lines[nextLine]?.trim().match(/\/\/\s*(.*)/); 65 | if (continuationMatch?.[1]) { 66 | comment += "\n" + continuationMatch[1].trim(); 67 | } 68 | nextLine++; 69 | } 70 | 71 | // If there's a match, add the captured group (the comment content) to our array 72 | comments.push({ 73 | filepath, 74 | line: index, 75 | comment, 76 | context: lines 77 | .slice(Math.max(0, index - 5), Math.min(lines.length, index + 5)) 78 | .join("\n"), 79 | }); 80 | } 81 | } 82 | 83 | return comments; 84 | } 85 | -------------------------------------------------------------------------------- /src/ignore.ts: -------------------------------------------------------------------------------- 1 | import consola from "consola"; 2 | import { readFile } from "fs/promises"; 3 | import ignore from "ignore"; 4 | import { minimatch } from "minimatch"; 5 | import { existsSync } from "fs"; 6 | import { join, dirname, resolve } from "path"; 7 | 8 | const builtInIgnores = [ 9 | ".git", 10 | "node_modules", 11 | "dist", 12 | "build", 13 | "coverage", 14 | ".env", 15 | ]; 16 | 17 | let ig: ignore.Ignore; 18 | 19 | export function shouldIgnore({ path }: { path: string }) { 20 | try { 21 | if (path === ".") return false; 22 | const shouldIgnore = 23 | ig?.ignores(path) || 24 | builtInIgnores.some((pattern) => minimatch(path, pattern)); 25 | return shouldIgnore; 26 | } catch { 27 | return false; 28 | } 29 | } 30 | 31 | function findGitignore(startDir: string): string | null { 32 | let currentDir = resolve(startDir); 33 | 34 | while (true) { 35 | const gitignorePath = join(currentDir, ".gitignore"); 36 | 37 | if (existsSync(gitignorePath)) { 38 | return gitignorePath; 39 | } 40 | 41 | const parentDir = dirname(currentDir); 42 | 43 | // If we've reached the root directory 44 | if (parentDir === currentDir) { 45 | return null; 46 | } 47 | 48 | currentDir = parentDir; 49 | } 50 | } 51 | 52 | export async function createIgnore() { 53 | if (!ig) { 54 | const gitignorePath = findGitignore(process.cwd()); 55 | 56 | if (gitignorePath) { 57 | consola.debug(`Reading ${gitignorePath}`); 58 | const gitignore = await readFile(gitignorePath, "utf-8"); 59 | ig = ignore().add(gitignore); 60 | } else { 61 | consola.debug("No .gitignore file found, using built-in ignores only"); 62 | ig = ignore(); 63 | } 64 | } 65 | 66 | return { 67 | shouldIgnore: ({ path }: { path: string }) => shouldIgnore({ path }), 68 | }; 69 | } 70 | -------------------------------------------------------------------------------- /src/loop.ts: -------------------------------------------------------------------------------- 1 | import consola from "consola"; 2 | import { type FileComment } from "./comment.js"; 3 | import { spin, spinner } from "./spinner.js"; 4 | import { parse, print } from "./message.js"; 5 | import { exec } from "child_process"; 6 | 7 | type CheckResult = { ok: true } | { ok: false; error: string }; 8 | 9 | type Loop = { 10 | /** The comment to be addressed in this loop. */ 11 | comment: FileComment; 12 | trigger: string; 13 | agentStep: (args: { command: string }) => Promise; 14 | checkStep: (args: { command: string }) => Promise; 15 | shouldRun: () => boolean; 16 | lintError?: string; 17 | }; 18 | 19 | /** 20 | * Instantiate main loop that can be driven from the outside. 21 | */ 22 | function createLoop({ 23 | comment, 24 | trigger, 25 | }: { 26 | comment: FileComment; 27 | trigger: string; 28 | }): Loop { 29 | /* Is used next time calling agentStep */ 30 | const prompt = ` 31 | Please address comment around "${trigger}" by implementing or fixing the code base. 32 | 33 | 34 | - Don't run any builds, checks, lints, tests or typechecks yourself. I will do that once you are done with the change. 35 | - Remove the comment once you are done. 36 | - Summarize in a single sentence what you did. 37 | 38 | 39 | 40 | ${comment.filepath}:${comment.line}: 41 | ${comment.context} 42 | 43 | `; 44 | 45 | let checkError: string | undefined; 46 | 47 | let hasRunInitially = false; 48 | 49 | return { 50 | trigger, 51 | shouldRun: () => { 52 | if (!hasRunInitially) return true; 53 | if (checkError) return true; 54 | return false; 55 | }, 56 | comment, 57 | agentStep: async ({ command }) => { 58 | consola.debug(`$ ${command}`); 59 | return new Promise((resolve, reject) => { 60 | hasRunInitially = true; 61 | consola.debug(` $ ${command}`); 62 | if (checkError) spin(" 🤖 Fixing errors..."); 63 | else spin(" 🤖 Thinking..."); 64 | const child = exec(command); 65 | child.stdin?.write(prompt); 66 | child.stdin?.end(); 67 | child.stdout?.on("data", (data) => { 68 | const parsed = parse(data); 69 | if (parsed) print(parsed); 70 | }); 71 | child.stderr?.on("data", (data) => { 72 | const parsed = parse(data); 73 | if (parsed) print(parsed); 74 | }); 75 | child.on("close", (code) => { 76 | if (code === 0) { 77 | resolve({ ok: true }); 78 | } else { 79 | reject(new Error(`Child process exited with code ${code}`)); 80 | } 81 | }); 82 | }); 83 | }, 84 | checkStep: async ({ command }) => { 85 | return await new Promise((resolve) => { 86 | let stderr = ""; 87 | let stdout = ""; 88 | const fileCheckProcess = exec(command); 89 | fileCheckProcess.stdout?.on("data", (data) => { 90 | stdout += data; 91 | }); 92 | fileCheckProcess.stderr?.on("data", (data) => { 93 | spinner.stop(); 94 | consola.info(data); 95 | stderr += data; 96 | }); 97 | fileCheckProcess.on("close", (code) => { 98 | if (code === 0) { 99 | spinner.stop(); 100 | checkError = undefined; 101 | resolve({ ok: true }); 102 | } else { 103 | spinner.stop(); 104 | checkError = `Running "${command}" failed, please fix the following errors: \n\n\n\n${stdout}\n\n\n\n${stderr}`; 105 | resolve({ ok: false, error: checkError }); 106 | } 107 | }); 108 | }); 109 | }, 110 | }; 111 | } 112 | 113 | /** 114 | * Create and drive the main loop. 115 | */ 116 | export async function runLoop({ 117 | comment, 118 | agentCommand, 119 | checkCommand, 120 | trigger, 121 | fileCheckCommand, 122 | }: { 123 | comment: FileComment; 124 | agentCommand: string; 125 | checkCommand: string; 126 | trigger: string; 127 | fileCheckCommand?: string | undefined; 128 | }) { 129 | consola.info(`🫱 Processing comment ${comment.filepath}:${comment.line}`); 130 | const loop = createLoop({ comment, trigger: trigger }); 131 | while (loop.shouldRun()) { 132 | await loop.agentStep({ command: agentCommand }); 133 | if (fileCheckCommand) { 134 | spin(` $ ${fileCheckCommand}`); 135 | const fileCheckResult = await loop.checkStep({ 136 | command: `git ls-files --modified | xargs ${fileCheckCommand}`, 137 | }); 138 | // if the check failed, we need to run the agent again to fix it 139 | if (!fileCheckResult.ok) continue; 140 | consola.info(` $ ${checkCommand}`); 141 | const checkResult = await loop.checkStep({ command: checkCommand }); 142 | // if the check passed, we need to run the full check 143 | if (!checkResult.ok) continue; 144 | } else { 145 | consola.info(` $ ${checkCommand}`); 146 | const checkResult = await loop.checkStep({ command: checkCommand }); 147 | // if the check passed, we need to run the full check 148 | if (!checkResult.ok) continue; 149 | } 150 | } 151 | consola.info(` ✓ Comment ${comment.filepath}:${comment.line} processed`); 152 | } 153 | -------------------------------------------------------------------------------- /src/message.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, it, expect } from "vitest"; 2 | import { Message, parse } from "./message.js"; 3 | 4 | describe("parse()", () => { 5 | it("should parse a claude code final system message correctly", () => { 6 | const json = `{"type":"result","subtype":"success","cost_usd":0.05136085,"is_error":false,"duration_ms":1746,"duration_api_ms":3265,"num_turns":1,"result":"Hi! How can I help you with your code today?","total_cost":0.05136085,"session_id":"1c7d5d12-a7e2-4b5f-9bfe-33b920c888b9"}`; 7 | 8 | const result = parse(json); 9 | 10 | expect(result).toEqual({ 11 | type: "final", 12 | costUsd: 0.05136085, 13 | durationMs: 1746, 14 | } satisfies Message); 15 | }); 16 | 17 | it("should parse a claude code brief final system message correctly", () => { 18 | const json = `{ 19 | "role": "system", 20 | "cost_usd": 0.07173765, 21 | "duration_ms": 24760, 22 | "duration_api_ms": 24761 23 | }`; 24 | 25 | const result = parse(json); 26 | 27 | expect(result).toEqual({ 28 | type: "final", 29 | costUsd: 0.07173765, 30 | durationMs: 24760, 31 | } satisfies Message); 32 | }); 33 | 34 | it("should parse claude code assistant message correctly", () => { 35 | const json = `{"type":"assistant","message":{"id":"msg_01MeTKFfsqBV1aHUFjJd1b75","type":"message","role":"assistant","model":"claude-3-5-sonnet-20241022","content":[{"type":"text","text":"Hi! How can I help you with your code today?"}],"stop_reason":"end_turn","stop_sequence":null,"usage":{"input_tokens":4,"cache_creation_input_tokens":13543,"cache_read_input_tokens":0,"output_tokens":15,"service_tier":"standard"}},"session_id":"1c7d5d12-a7e2-4b5f-9bfe-33b920c888b9"}`; 36 | 37 | const result = parse(json); 38 | 39 | expect(result).toEqual({ 40 | type: "assistant", 41 | text: "Hi! How can I help you with your code today?", 42 | } satisfies Message); 43 | }); 44 | 45 | it("should parse claude code assistant message with tool use correctly", () => { 46 | const json = `{ 47 | "id": "msg_01RLococpHbVS5DNRHCV1jUK", 48 | "type": "message", 49 | "role": "assistant", 50 | "model": "claude-3-7-sonnet-20250219", 51 | "content": [ 52 | { 53 | "type": "text", 54 | "text": "I'll implement the requested change by updating the README.md to reflect the new CLI approach instead of using .env files." 55 | }, 56 | { 57 | "type": "tool_use", 58 | "id": "toolu_01GoYCprDK3iJEvvYTxxpQv4", 59 | "name": "Read", 60 | "input": { 61 | "file_path": "/Users/josef/code/joseferben/hands-please/README.md" 62 | } 63 | } 64 | ], 65 | "stop_reason": "tool_use", 66 | "stop_sequence": null, 67 | "usage": { 68 | "input_tokens": 3, 69 | "cache_creation_input_tokens": 3011, 70 | "cache_read_input_tokens": 12013, 71 | "output_tokens": 96, 72 | "service_tier": "standard" 73 | } 74 | }`; 75 | 76 | const result = parse(json); 77 | 78 | expect(result).toEqual({ 79 | type: "assistant", 80 | text: "I'll implement the requested change by updating the README.md to reflect the new CLI approach instead of using .env files.", 81 | } satisfies Message); 82 | }); 83 | 84 | it("should handle unknown message formats", () => { 85 | const json = JSON.stringify({ 86 | role: "user", 87 | content: "Some content", 88 | }); 89 | 90 | const result = parse(json); 91 | 92 | expect(result).toBeNull(); 93 | }); 94 | 95 | it("should handle invalid JSON", () => { 96 | const json = "invalid json"; 97 | 98 | const result = parse(json); 99 | 100 | expect(result).toBeNull(); 101 | }); 102 | }); 103 | -------------------------------------------------------------------------------- /src/message.ts: -------------------------------------------------------------------------------- 1 | import consola from "consola"; 2 | import { z } from "zod"; 3 | import { spin, spinner } from "./spinner.js"; 4 | 5 | export type Message = 6 | | { 7 | type: "final"; 8 | costUsd: number; 9 | durationMs: number; 10 | } 11 | | { 12 | type: "assistant"; 13 | text: string; 14 | }; 15 | 16 | function niceDuration(ms: number) { 17 | if (ms < 1000) { 18 | return `${ms}ms`; 19 | } 20 | return `${(ms / 1000).toFixed(2)}s`; 21 | } 22 | 23 | export function print(message: Message): void { 24 | spinner.stop(); 25 | if (message.type === "assistant") { 26 | consola.info(` 🤖 ${message.text}`); 27 | } else if (message.type === "final") { 28 | consola.info( 29 | ` 💸 ${message.costUsd} in ${niceDuration(message.durationMs)}` 30 | ); 31 | } 32 | 33 | spin(" 🤖 Thinking..."); 34 | } 35 | 36 | // Schema for Claude Code final message 37 | const FinalMessageSchema = z.object({ 38 | type: z.literal("result"), 39 | cost_usd: z.number(), 40 | duration_ms: z.number(), 41 | result: z.string(), 42 | }); 43 | 44 | // Schema for brief version of final message 45 | const BriefFinalMessageSchema = z.object({ 46 | role: z.literal("system"), 47 | cost_usd: z.number(), 48 | duration_ms: z.number(), 49 | }); 50 | 51 | // Schema for Claude Code assistant message content item 52 | const ContentItemSchema = z.object({ 53 | type: z.literal("text"), 54 | text: z.string(), 55 | }); 56 | 57 | // Schema for Claude Code assistant message 58 | const AssistantMessageSchema = z.object({ 59 | type: z.literal("assistant"), 60 | message: z.object({ 61 | role: z.literal("assistant"), 62 | content: z.array(ContentItemSchema), 63 | }), 64 | }); 65 | 66 | // Schema for direct assistant message (used in tool use) 67 | const DirectAssistantMessageSchema = z.object({ 68 | role: z.literal("assistant"), 69 | content: z.array( 70 | z.object({ 71 | type: z.string(), 72 | text: z.string().optional(), 73 | }) 74 | ), 75 | }); 76 | 77 | /** 78 | * Try to parse message from json string, return null if it fails 79 | */ 80 | export function parse(json: unknown): Message | null { 81 | try { 82 | const parsed = JSON.parse(json as string) as unknown; 83 | 84 | // Try to parse as a final message 85 | const finalResult = FinalMessageSchema.safeParse(parsed); 86 | if (finalResult.success) { 87 | return { 88 | type: "final", 89 | costUsd: finalResult.data.cost_usd, 90 | durationMs: finalResult.data.duration_ms, 91 | }; 92 | } 93 | 94 | // Try to parse as a brief final message 95 | const briefFinalResult = BriefFinalMessageSchema.safeParse(parsed); 96 | if (briefFinalResult.success) { 97 | return { 98 | type: "final", 99 | costUsd: briefFinalResult.data.cost_usd, 100 | durationMs: briefFinalResult.data.duration_ms, 101 | }; 102 | } 103 | 104 | // Try to parse as an assistant message 105 | const assistantResult = AssistantMessageSchema.safeParse(parsed); 106 | if (assistantResult.success) { 107 | // Get the first text content 108 | const textContent = assistantResult.data.message.content[0]; 109 | return { 110 | type: "assistant", 111 | text: textContent?.text ?? "", 112 | }; 113 | } 114 | 115 | // Try to parse as a direct assistant message (tool use case) 116 | const directAssistantResult = 117 | DirectAssistantMessageSchema.safeParse(parsed); 118 | if (directAssistantResult.success) { 119 | // Find the first text content 120 | const textContent = directAssistantResult.data.content.find( 121 | (item) => item.type === "text" 122 | ); 123 | if (textContent && "text" in textContent) { 124 | return { 125 | type: "assistant", 126 | text: textContent.text ?? "", 127 | }; 128 | } 129 | } 130 | 131 | return null; 132 | } catch { 133 | return null; 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /src/spinner.ts: -------------------------------------------------------------------------------- 1 | import ora from "ora"; 2 | 3 | export const spinner = ora(); 4 | 5 | export function spin(text: string) { 6 | spinner.start(); 7 | spinner.text = text; 8 | } 9 | -------------------------------------------------------------------------------- /src/watch.ts: -------------------------------------------------------------------------------- 1 | import { consola } from "consola"; 2 | import { parse } from "./comment.js"; 3 | import { runLoop } from "./loop.js"; 4 | import chokidar from "chokidar"; 5 | import { readFile } from "fs/promises"; 6 | import { createIgnore } from "./ignore.js"; 7 | import { spin, spinner } from "./spinner.js"; 8 | 9 | let lock = false; 10 | 11 | // files that could not be processed due to lock 12 | const filesToCheckAndProcess = new Set(); 13 | 14 | async function checkAndProcessFile({ 15 | filepath, 16 | agentCommand, 17 | checkCommand, 18 | trigger, 19 | fileCheckCommand, 20 | }: { 21 | filepath: string; 22 | agentCommand: string; 23 | checkCommand: string; 24 | trigger: string; 25 | fileCheckCommand?: string | undefined; 26 | }) { 27 | const content = await readFile(filepath, "utf-8"); 28 | const comments = parse({ filepath, content, trigger }); 29 | if (comments.length === 0) { 30 | consola.debug(`No comments found in ${filepath}`); 31 | return; 32 | } 33 | 34 | spinner.stop(); 35 | consola.debug(`Found ${comments.length} comments`); 36 | 37 | for (const comment of comments) { 38 | if (lock) { 39 | consola.debug("Lock is set, adding to queue"); 40 | filesToCheckAndProcess.add(filepath); 41 | return; 42 | } 43 | lock = true; 44 | await runLoop({ 45 | comment, 46 | agentCommand, 47 | checkCommand, 48 | trigger, 49 | fileCheckCommand, 50 | }); 51 | lock = false; 52 | } 53 | const nextFilepath = Array.from(filesToCheckAndProcess.values()).shift(); 54 | if (nextFilepath) { 55 | await checkAndProcessFile({ 56 | filepath: nextFilepath, 57 | agentCommand, 58 | checkCommand, 59 | trigger, 60 | fileCheckCommand, 61 | }); 62 | } else { 63 | spin(`Watching files for "${trigger}"....`); 64 | } 65 | } 66 | 67 | export async function watch({ 68 | agentCommand, 69 | checkCommand, 70 | skipWatch, 71 | trigger, 72 | fileCheckCommand, 73 | }: { 74 | agentCommand: string; 75 | checkCommand: string; 76 | skipWatch: boolean; 77 | trigger: string; 78 | fileCheckCommand?: string; 79 | }) { 80 | const ignore = await createIgnore(); 81 | spinner.stop(); 82 | 83 | consola.debug("Watching for changes"); 84 | const watcher = chokidar.watch(".", { 85 | ignored: (path) => ignore.shouldIgnore({ path }), 86 | }); 87 | 88 | watcher.on("add", (filepath) => { 89 | consola.debug(`Watching file: ${filepath}`); 90 | void checkAndProcessFile({ 91 | filepath, 92 | agentCommand, 93 | checkCommand, 94 | trigger, 95 | fileCheckCommand, 96 | }).catch(consola.error); 97 | }); 98 | 99 | if (!skipWatch) { 100 | watcher.on("change", (filepath) => { 101 | consola.debug(`Change detected: ${filepath}`); 102 | void checkAndProcessFile({ 103 | filepath, 104 | agentCommand, 105 | checkCommand, 106 | fileCheckCommand, 107 | trigger, 108 | }).catch(consola.error); 109 | }); 110 | spin(`Watching files for "${trigger}"....`); 111 | } else { 112 | consola.info(`No more comments with ${trigger} found, exiting...`); 113 | } 114 | 115 | process.on("SIGINT", () => { 116 | consola.info("Received SIGINT signal, shutting down..."); 117 | void watcher.close().then(() => process.exit(0)); 118 | }); 119 | } 120 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["**/*.ts", "eslint.config.mjs"], 3 | "extends": "@tsconfig/strictest/tsconfig.json", 4 | "compilerOptions": { 5 | "moduleResolution": "NodeNext", 6 | "module": "NodeNext" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "tsup"; 2 | 3 | export default defineConfig({ 4 | entry: ["src/config.ts", "src/bin.ts"], 5 | outDir: "dist", 6 | format: "esm", 7 | dts: true, 8 | sourcemap: true, 9 | clean: true, 10 | }); 11 | --------------------------------------------------------------------------------