diff --git a/biome.json b/biome.json index ae7b60129..584a2b62d 100644 --- a/biome.json +++ b/biome.json @@ -18,10 +18,19 @@ }, "formatter": { "enabled": true, - "formatWithErrors": false, "indentStyle": "tab", "indentWidth": 3, - "lineWidth": 120 + "lineWidth": 120, + "lineEnding": "lf" + }, + "javascript": { + "formatter": { + "semicolons": "always", + "quoteStyle": "double", + "trailingCommas": "all", + "bracketSpacing": true, + "arrowParentheses": "always" + } }, "files": { "includes": [ @@ -38,5 +47,6 @@ "!packages/mom/data/**/*", "!!**/node_modules" ] - } + }, + "assist": { "actions": { "source": { "organizeImports": "on" } } } } diff --git a/bun.lock b/bun.lock index 3c3dbeb89..693989c6c 100644 --- a/bun.lock +++ b/bun.lock @@ -1,1055 +1,4031 @@ { - "lockfileVersion": 1, - "configVersion": 1, - "workspaces": { - "": { - "name": "omp-monorepo", - "dependencies": { - "@sinclair/typebox": "^0.34.46", - "get-east-asian-width": "^1.4.0", - }, - "devDependencies": { - "@biomejs/biome": "2.3.10", - "@types/bun": "^1.2.17", - "@types/node": "^22.10.5", - "@typescript/native-preview": "^7.0.0-dev.20260102.1", - "bun-types": "^1.3.5", - "concurrently": "^9.2.1", - "lint-staged": "^16.2.7", - }, - }, - "packages/agent": { - "name": "@oh-my-pi/pi-agent-core", - "version": "3.21.0", - "dependencies": { - "@mariozechner/pi-ai": "^0.37.4", - "@oh-my-pi/pi-tui": "workspace:*", - }, - "devDependencies": { - "@types/node": "^24.3.0", - "vitest": "^3.2.4", - }, - }, - "packages/coding-agent": { - "name": "@oh-my-pi/pi-coding-agent", - "version": "3.21.0", - "bin": { - "omp": "src/cli.ts", - }, - "dependencies": { - "@mariozechner/pi-ai": "^0.37.4", - "@oh-my-pi/pi-agent-core": "workspace:*", - "@oh-my-pi/pi-git-tool": "workspace:*", - "@oh-my-pi/pi-tui": "workspace:*", - "@openai/agents": "^0.3.7", - "@sinclair/typebox": "^0.34.46", - "ajv": "^8.17.1", - "chalk": "^5.5.0", - "cli-highlight": "^2.1.11", - "diff": "^8.0.2", - "file-type": "^21.1.1", - "glob": "^11.0.3", - "highlight.js": "^11.11.1", - "marked": "^15.0.12", - "minimatch": "^10.1.1", - "nanoid": "^5.1.6", - "ndjson": "^2.0.0", - "node-html-parser": "^6.1.13", - "sharp": "^0.34.2", - "smol-toml": "^1.6.0", - "strip-ansi": "^7.1.2", - "winston": "^3.17.0", - "winston-daily-rotate-file": "^5.0.0", - "yaml": "^2.8.2", - "zod": "^4.3.5", - }, - "devDependencies": { - "@types/diff": "^7.0.2", - "@types/ms": "^2.1.0", - "@types/ndjson": "^2.0.4", - "@types/node": "^24.3.0", - "ms": "^2.1.3", - }, - }, - "packages/git-tool": { - "name": "@oh-my-pi/pi-git-tool", - "version": "3.21.0", - "devDependencies": { - "@types/node": "^24.3.0", - "vitest": "^3.2.4", - }, - }, - "packages/tui": { - "name": "@oh-my-pi/pi-tui", - "version": "3.21.0", - "dependencies": { - "@types/mime-types": "^2.1.4", - "chalk": "^5.5.0", - "get-east-asian-width": "^1.3.0", - "marked": "^15.0.12", - "mime-types": "^3.0.1", - }, - "devDependencies": { - "@xterm/headless": "^5.5.0", - "@xterm/xterm": "^5.5.0", - }, - }, - }, - "packages": { - "@anthropic-ai/sdk": ["@anthropic-ai/sdk@0.71.2", "", { "dependencies": { "json-schema-to-ts": "^3.1.1" }, "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" }, "optionalPeers": ["zod"], "bin": { "anthropic-ai-sdk": "bin/cli" } }, "sha512-TGNDEUuEstk/DKu0/TflXAEt+p+p/WhTlFzEnoosvbaDU2LTjm42igSdlL0VijrKpWejtOKxX0b8A7uc+XiSAQ=="], - - "@babel/runtime": ["@babel/runtime@7.28.4", "", {}, "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ=="], - - "@biomejs/biome": ["@biomejs/biome@2.3.10", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.3.10", "@biomejs/cli-darwin-x64": "2.3.10", "@biomejs/cli-linux-arm64": "2.3.10", "@biomejs/cli-linux-arm64-musl": "2.3.10", "@biomejs/cli-linux-x64": "2.3.10", "@biomejs/cli-linux-x64-musl": "2.3.10", "@biomejs/cli-win32-arm64": "2.3.10", "@biomejs/cli-win32-x64": "2.3.10" }, "bin": { "biome": "bin/biome" } }, "sha512-/uWSUd1MHX2fjqNLHNL6zLYWBbrJeG412/8H7ESuK8ewoRoMPUgHDebqKrPTx/5n6f17Xzqc9hdg3MEqA5hXnQ=="], - - "@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.3.10", "", { "os": "darwin", "cpu": "arm64" }, "sha512-M6xUjtCVnNGFfK7HMNKa593nb7fwNm43fq1Mt71kpLpb+4mE7odO8W/oWVDyBVO4ackhresy1ZYO7OJcVo/B7w=="], - - "@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.3.10", "", { "os": "darwin", "cpu": "x64" }, "sha512-Vae7+V6t/Avr8tVbFNjnFSTKZogZHFYl7MMH62P/J1kZtr0tyRQ9Fe0onjqjS2Ek9lmNLmZc/VR5uSekh+p1fg=="], - - "@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.3.10", "", { "os": "linux", "cpu": "arm64" }, "sha512-hhPw2V3/EpHKsileVOFynuWiKRgFEV48cLe0eA+G2wO4SzlwEhLEB9LhlSrVeu2mtSn205W283LkX7Fh48CaxA=="], - - "@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.3.10", "", { "os": "linux", "cpu": "arm64" }, "sha512-B9DszIHkuKtOH2IFeeVkQmSMVUjss9KtHaNXquYYWCjH8IstNgXgx5B0aSBQNr6mn4RcKKRQZXn9Zu1rM3O0/A=="], - - "@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.3.10", "", { "os": "linux", "cpu": "x64" }, "sha512-wwAkWD1MR95u+J4LkWP74/vGz+tRrIQvr8kfMMJY8KOQ8+HMVleREOcPYsQX82S7uueco60L58Wc6M1I9WA9Dw=="], - - "@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.3.10", "", { "os": "linux", "cpu": "x64" }, "sha512-QTfHZQh62SDFdYc2nfmZFuTm5yYb4eO1zwfB+90YxUumRCR171tS1GoTX5OD0wrv4UsziMPmrePMtkTnNyYG3g=="], - - "@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.3.10", "", { "os": "win32", "cpu": "arm64" }, "sha512-o7lYc9n+CfRbHvkjPhm8s9FgbKdYZu5HCcGVMItLjz93EhgJ8AM44W+QckDqLA9MKDNFrR8nPbO4b73VC5kGGQ=="], - - "@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.3.10", "", { "os": "win32", "cpu": "x64" }, "sha512-pHEFgq7dUEsKnqG9mx9bXihxGI49X+ar+UBrEIj3Wqj3UCZp1rNgV+OoyjFgcXsjCWpuEAF4VJdkZr3TrWdCbQ=="], - - "@borewit/text-codec": ["@borewit/text-codec@0.2.1", "", {}, "sha512-k7vvKPbf7J2fZ5klGRD9AeKfUvojuZIQ3BT5u7Jfv+puwXkUBUT5PVyMDfJZpy30CBDXGMgw7fguK/lpOMBvgw=="], - - "@colors/colors": ["@colors/colors@1.6.0", "", {}, "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA=="], - - "@dabh/diagnostics": ["@dabh/diagnostics@2.0.8", "", { "dependencies": { "@so-ric/colorspace": "^1.1.6", "enabled": "2.0.x", "kuler": "^2.0.0" } }, "sha512-R4MSXTVnuMzGD7bzHdW2ZhhdPC/igELENcq5IjEverBvq5hn1SXCWcsi6eSsdWP0/Ur+SItRRjAktmdoX/8R/Q=="], - - "@emnapi/runtime": ["@emnapi/runtime@1.8.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg=="], - - "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw=="], - - "@esbuild/android-arm": ["@esbuild/android-arm@0.27.2", "", { "os": "android", "cpu": "arm" }, "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA=="], - - "@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.2", "", { "os": "android", "cpu": "arm64" }, "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA=="], - - "@esbuild/android-x64": ["@esbuild/android-x64@0.27.2", "", { "os": "android", "cpu": "x64" }, "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A=="], - - "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg=="], - - "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA=="], - - "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g=="], - - "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA=="], - - "@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.2", "", { "os": "linux", "cpu": "arm" }, "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw=="], - - "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw=="], - - "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.2", "", { "os": "linux", "cpu": "ia32" }, "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w=="], - - "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.2", "", { "os": "linux", "cpu": "none" }, "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg=="], - - "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.2", "", { "os": "linux", "cpu": "none" }, "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw=="], - - "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ=="], - - "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.2", "", { "os": "linux", "cpu": "none" }, "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA=="], - - "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w=="], - - "@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.2", "", { "os": "linux", "cpu": "x64" }, "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA=="], - - "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.2", "", { "os": "none", "cpu": "arm64" }, "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw=="], - - "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.2", "", { "os": "none", "cpu": "x64" }, "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA=="], - - "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.2", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA=="], - - "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.2", "", { "os": "openbsd", "cpu": "x64" }, "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg=="], - - "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.2", "", { "os": "none", "cpu": "arm64" }, "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag=="], - - "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.2", "", { "os": "sunos", "cpu": "x64" }, "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg=="], - - "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg=="], - - "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ=="], - - "@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.2", "", { "os": "win32", "cpu": "x64" }, "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ=="], - - "@google/genai": ["@google/genai@1.34.0", "", { "dependencies": { "google-auth-library": "^10.3.0", "ws": "^8.18.0" }, "peerDependencies": { "@modelcontextprotocol/sdk": "^1.24.0" }, "optionalPeers": ["@modelcontextprotocol/sdk"] }, "sha512-vu53UMPvjmb7PGzlYu6Tzxso8Dfhn+a7eQFaS2uNemVtDZKwzSpJ5+ikqBbXplF7RGB1STcVDqCkPvquiwb2sw=="], - - "@hono/node-server": ["@hono/node-server@1.19.7", "", { "peerDependencies": { "hono": "^4" } }, "sha512-vUcD0uauS7EU2caukW8z5lJKtoGMokxNbJtBiwHgpqxEXokaHCBkQUmCHhjFB1VUTWdqj25QoMkMKzgjq+uhrw=="], - - "@img/colour": ["@img/colour@1.0.0", "", {}, "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw=="], - - "@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.2.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w=="], - - "@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.2.4" }, "os": "darwin", "cpu": "x64" }, "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw=="], - - "@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.2.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g=="], - - "@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.2.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg=="], - - "@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.2.4", "", { "os": "linux", "cpu": "arm" }, "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A=="], - - "@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw=="], - - "@img/sharp-libvips-linux-ppc64": ["@img/sharp-libvips-linux-ppc64@1.2.4", "", { "os": "linux", "cpu": "ppc64" }, "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA=="], - - "@img/sharp-libvips-linux-riscv64": ["@img/sharp-libvips-linux-riscv64@1.2.4", "", { "os": "linux", "cpu": "none" }, "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA=="], - - "@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.2.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ=="], - - "@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw=="], - - "@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw=="], - - "@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg=="], - - "@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.2.4" }, "os": "linux", "cpu": "arm" }, "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw=="], - - "@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.2.4" }, "os": "linux", "cpu": "arm64" }, "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg=="], - - "@img/sharp-linux-ppc64": ["@img/sharp-linux-ppc64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-ppc64": "1.2.4" }, "os": "linux", "cpu": "ppc64" }, "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA=="], - - "@img/sharp-linux-riscv64": ["@img/sharp-linux-riscv64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-riscv64": "1.2.4" }, "os": "linux", "cpu": "none" }, "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw=="], - - "@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.2.4" }, "os": "linux", "cpu": "s390x" }, "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg=="], - - "@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.2.4" }, "os": "linux", "cpu": "x64" }, "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ=="], - - "@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" }, "os": "linux", "cpu": "arm64" }, "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg=="], - - "@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.2.4" }, "os": "linux", "cpu": "x64" }, "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q=="], - - "@img/sharp-wasm32": ["@img/sharp-wasm32@0.34.5", "", { "dependencies": { "@emnapi/runtime": "^1.7.0" }, "cpu": "none" }, "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw=="], - - "@img/sharp-win32-arm64": ["@img/sharp-win32-arm64@0.34.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g=="], - - "@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.34.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg=="], - - "@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.34.5", "", { "os": "win32", "cpu": "x64" }, "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw=="], - - "@isaacs/balanced-match": ["@isaacs/balanced-match@4.0.1", "", {}, "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ=="], - - "@isaacs/brace-expansion": ["@isaacs/brace-expansion@5.0.0", "", { "dependencies": { "@isaacs/balanced-match": "^4.0.1" } }, "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA=="], - - "@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="], - - "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="], - - "@mariozechner/pi-ai": ["@mariozechner/pi-ai@0.37.5", "", { "dependencies": { "@anthropic-ai/sdk": "0.71.2", "@google/genai": "1.34.0", "@mistralai/mistralai": "1.10.0", "@sinclair/typebox": "^0.34.41", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "chalk": "^5.6.2", "openai": "6.10.0", "partial-json": "^0.1.7", "zod-to-json-schema": "^3.24.6" }, "bin": { "pi-ai": "dist/cli.js" } }, "sha512-LhUtOih1UnEZjWR86geVX6PkmoGwz3dpKEQFSHb1UvCA3M9Z0xVwR8OmRFTLtfCY7mMYT/mrzH5vWi2qsTmE+Q=="], - - "@mistralai/mistralai": ["@mistralai/mistralai@1.10.0", "", { "dependencies": { "zod": "^3.20.0", "zod-to-json-schema": "^3.24.1" } }, "sha512-tdIgWs4Le8vpvPiUEWne6tK0qbVc+jMenujnvTqOjogrJUsCSQhus0tHTU1avDDh5//Rq2dFgP9mWRAdIEoBqg=="], - - "@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.25.1", "", { "dependencies": { "@hono/node-server": "^1.19.7", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "content-type": "^1.0.5", "cors": "^2.8.5", "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", "eventsource-parser": "^3.0.0", "express": "^5.0.1", "express-rate-limit": "^7.5.0", "jose": "^6.1.1", "json-schema-typed": "^8.0.2", "pkce-challenge": "^5.0.0", "raw-body": "^3.0.0", "zod": "^3.25 || ^4.0", "zod-to-json-schema": "^3.25.0" }, "peerDependencies": { "@cfworker/json-schema": "^4.1.1" }, "optionalPeers": ["@cfworker/json-schema"] }, "sha512-yO28oVFFC7EBoiKdAn+VqRm+plcfv4v0xp6osG/VsCB0NlPZWi87ajbCZZ8f/RvOFLEu7//rSRmuZZ7lMoe3gQ=="], - - "@oh-my-pi/pi-agent-core": ["@oh-my-pi/pi-agent-core@workspace:packages/agent"], - - "@oh-my-pi/pi-coding-agent": ["@oh-my-pi/pi-coding-agent@workspace:packages/coding-agent"], - - "@oh-my-pi/pi-git-tool": ["@oh-my-pi/pi-git-tool@workspace:packages/git-tool"], - - "@oh-my-pi/pi-tui": ["@oh-my-pi/pi-tui@workspace:packages/tui"], - - "@openai/agents": ["@openai/agents@0.3.7", "", { "dependencies": { "@openai/agents-core": "0.3.7", "@openai/agents-openai": "0.3.7", "@openai/agents-realtime": "0.3.7", "debug": "^4.4.0", "openai": "^6" }, "peerDependencies": { "zod": "^3.25.40 || ^4.0" } }, "sha512-9QKr6Gqb0yy0VLsyKSjxUoHHxN8j0fqtlZ1YTNmo2j5SqRcFG5LdSVyaQbkeJ3sWsCUugCXvEBEir7yAbxjSRw=="], - - "@openai/agents-core": ["@openai/agents-core@0.3.7", "", { "dependencies": { "debug": "^4.4.0", "openai": "^6" }, "optionalDependencies": { "@modelcontextprotocol/sdk": "^1.24.0" }, "peerDependencies": { "zod": "^3.25.40 || ^4.0" }, "optionalPeers": ["zod"] }, "sha512-Ya1sPc8UyHXxgQjNWN1sn/vFNP4CRdT/0SWd0tIc+kHgYuxrvRjwSfWNBqXc70XOZGS5bWWaRTqJBMwQt6AlYg=="], - - "@openai/agents-openai": ["@openai/agents-openai@0.3.7", "", { "dependencies": { "@openai/agents-core": "0.3.7", "debug": "^4.4.0", "openai": "^6" }, "peerDependencies": { "zod": "^3.25.40 || ^4.0" } }, "sha512-xjFNFeKDt3TkAWfoXhvUG3sdBQJ/R3FWd/s3Dv1rt1fdcFCaS1BUKkXX1fu79oo24H5DV8zZJfuUu6Bgi0ZAHw=="], - - "@openai/agents-realtime": ["@openai/agents-realtime@0.3.7", "", { "dependencies": { "@openai/agents-core": "0.3.7", "@types/ws": "^8.18.1", "debug": "^4.4.0", "ws": "^8.18.1" }, "peerDependencies": { "zod": "^3.25.40 || ^4.0" } }, "sha512-8zKu33Q8bmXCkReR7UOWQa1rNbIaLwqI4QgjMD20ALaEkuRglRZeaJyfVTIhTcw9COIF35uyiq+GugxFUvPE5A=="], - - "@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="], - - "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.55.1", "", { "os": "android", "cpu": "arm" }, "sha512-9R0DM/ykwfGIlNu6+2U09ga0WXeZ9MRC2Ter8jnz8415VbuIykVuc6bhdrbORFZANDmTDvq26mJrEVTl8TdnDg=="], - - "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.55.1", "", { "os": "android", "cpu": "arm64" }, "sha512-eFZCb1YUqhTysgW3sj/55du5cG57S7UTNtdMjCW7LwVcj3dTTcowCsC8p7uBdzKsZYa8J7IDE8lhMI+HX1vQvg=="], - - "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.55.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-p3grE2PHcQm2e8PSGZdzIhCKbMCw/xi9XvMPErPhwO17vxtvCN5FEA2mSLgmKlCjHGMQTP6phuQTYWUnKewwGg=="], - - "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.55.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-rDUjG25C9qoTm+e02Esi+aqTKSBYwVTaoS1wxcN47/Luqef57Vgp96xNANwt5npq9GDxsH7kXxNkJVEsWEOEaQ=="], - - "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.55.1", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-+JiU7Jbp5cdxekIgdte0jfcu5oqw4GCKr6i3PJTlXTCU5H5Fvtkpbs4XJHRmWNXF+hKmn4v7ogI5OQPaupJgOg=="], - - "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.55.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-V5xC1tOVWtLLmr3YUk2f6EJK4qksksOYiz/TCsFHu/R+woubcLWdC9nZQmwjOAbmExBIVKsm1/wKmEy4z4u4Bw=="], - - "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.55.1", "", { "os": "linux", "cpu": "arm" }, "sha512-Rn3n+FUk2J5VWx+ywrG/HGPTD9jXNbicRtTM11e/uorplArnXZYsVifnPPqNNP5BsO3roI4n8332ukpY/zN7rQ=="], - - "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.55.1", "", { "os": "linux", "cpu": "arm" }, "sha512-grPNWydeKtc1aEdrJDWk4opD7nFtQbMmV7769hiAaYyUKCT1faPRm2av8CX1YJsZ4TLAZcg9gTR1KvEzoLjXkg=="], - - "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.55.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-a59mwd1k6x8tXKcUxSyISiquLwB5pX+fJW9TkWU46lCqD/GRDe9uDN31jrMmVP3feI3mhAdvcCClhV8V5MhJFQ=="], - - "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.55.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-puS1MEgWX5GsHSoiAsF0TYrpomdvkaXm0CofIMG5uVkP6IBV+ZO9xhC5YEN49nsgYo1DuuMquF9+7EDBVYu4uA=="], - - "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.55.1", "", { "os": "linux", "cpu": "none" }, "sha512-r3Wv40in+lTsULSb6nnoudVbARdOwb2u5fpeoOAZjFLznp6tDU8kd+GTHmJoqZ9lt6/Sys33KdIHUaQihFcu7g=="], - - "@rollup/rollup-linux-loong64-musl": ["@rollup/rollup-linux-loong64-musl@4.55.1", "", { "os": "linux", "cpu": "none" }, "sha512-MR8c0+UxAlB22Fq4R+aQSPBayvYa3+9DrwG/i1TKQXFYEaoW3B5b/rkSRIypcZDdWjWnpcvxbNaAJDcSbJU3Lw=="], - - "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.55.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-3KhoECe1BRlSYpMTeVrD4sh2Pw2xgt4jzNSZIIPLFEsnQn9gAnZagW9+VqDqAHgm1Xc77LzJOo2LdigS5qZ+gw=="], - - "@rollup/rollup-linux-ppc64-musl": ["@rollup/rollup-linux-ppc64-musl@4.55.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-ziR1OuZx0vdYZZ30vueNZTg73alF59DicYrPViG0NEgDVN8/Jl87zkAPu4u6VjZST2llgEUjaiNl9JM6HH1Vdw=="], - - "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.55.1", "", { "os": "linux", "cpu": "none" }, "sha512-uW0Y12ih2XJRERZ4jAfKamTyIHVMPQnTZcQjme2HMVDAHY4amf5u414OqNYC+x+LzRdRcnIG1YodLrrtA8xsxw=="], - - "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.55.1", "", { "os": "linux", "cpu": "none" }, "sha512-u9yZ0jUkOED1BFrqu3BwMQoixvGHGZ+JhJNkNKY/hyoEgOwlqKb62qu+7UjbPSHYjiVy8kKJHvXKv5coH4wDeg=="], - - "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.55.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-/0PenBCmqM4ZUd0190j7J0UsQ/1nsi735iPRakO8iPciE7BQ495Y6msPzaOmvx0/pn+eJVVlZrNrSh4WSYLxNg=="], - - "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.55.1", "", { "os": "linux", "cpu": "x64" }, "sha512-a8G4wiQxQG2BAvo+gU6XrReRRqj+pLS2NGXKm8io19goR+K8lw269eTrPkSdDTALwMmJp4th2Uh0D8J9bEV1vg=="], - - "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.55.1", "", { "os": "linux", "cpu": "x64" }, "sha512-bD+zjpFrMpP/hqkfEcnjXWHMw5BIghGisOKPj+2NaNDuVT+8Ds4mPf3XcPHuat1tz89WRL+1wbcxKY3WSbiT7w=="], - - "@rollup/rollup-openbsd-x64": ["@rollup/rollup-openbsd-x64@4.55.1", "", { "os": "openbsd", "cpu": "x64" }, "sha512-eLXw0dOiqE4QmvikfQ6yjgkg/xDM+MdU9YJuP4ySTibXU0oAvnEWXt7UDJmD4UkYialMfOGFPJnIHSe/kdzPxg=="], - - "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.55.1", "", { "os": "none", "cpu": "arm64" }, "sha512-xzm44KgEP11te3S2HCSyYf5zIzWmx3n8HDCc7EE59+lTcswEWNpvMLfd9uJvVX8LCg9QWG67Xt75AuHn4vgsXw=="], - - "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.55.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-yR6Bl3tMC/gBok5cz/Qi0xYnVbIxGx5Fcf/ca0eB6/6JwOY+SRUcJfI0OpeTpPls7f194as62thCt/2BjxYN8g=="], - - "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.55.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-3fZBidchE0eY0oFZBnekYCfg+5wAB0mbpCBuofh5mZuzIU/4jIVkbESmd2dOsFNS78b53CYv3OAtwqkZZmU5nA=="], - - "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.55.1", "", { "os": "win32", "cpu": "x64" }, "sha512-xGGY5pXj69IxKb4yv/POoocPy/qmEGhimy/FoTpTSVju3FYXUQQMFCaZZXJVidsmGxRioZAwpThl/4zX41gRKg=="], - - "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.55.1", "", { "os": "win32", "cpu": "x64" }, "sha512-SPEpaL6DX4rmcXtnhdrQYgzQ5W2uW3SCJch88lB2zImhJRhIIK44fkUrgIV/Q8yUNfw5oyZ5vkeQsZLhCb06lw=="], - - "@sinclair/typebox": ["@sinclair/typebox@0.34.47", "", {}, "sha512-ZGIBQ+XDvO5JQku9wmwtabcVTHJsgSWAHYtVuM9pBNNR5E88v6Jcj/llpmsjivig5X8A8HHOb4/mbEKPS5EvAw=="], - - "@so-ric/colorspace": ["@so-ric/colorspace@1.1.6", "", { "dependencies": { "color": "^5.0.2", "text-hex": "1.0.x" } }, "sha512-/KiKkpHNOBgkFJwu9sh48LkHSMYGyuTcSFK/qMBdnOAlrRJzRSXAOFB5qwzaVQuDl8wAvHVMkaASQDReTahxuw=="], - - "@tokenizer/inflate": ["@tokenizer/inflate@0.4.1", "", { "dependencies": { "debug": "^4.4.3", "token-types": "^6.1.1" } }, "sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA=="], - - "@tokenizer/token": ["@tokenizer/token@0.3.0", "", {}, "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A=="], - - "@types/bun": ["@types/bun@1.3.5", "", { "dependencies": { "bun-types": "1.3.5" } }, "sha512-RnygCqNrd3srIPEWBd5LFeUYG7plCoH2Yw9WaZGyNmdTEei+gWaHqydbaIRkIkcbXwhBT94q78QljxN0Sk838w=="], - - "@types/chai": ["@types/chai@5.2.3", "", { "dependencies": { "@types/deep-eql": "*", "assertion-error": "^2.0.1" } }, "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA=="], - - "@types/deep-eql": ["@types/deep-eql@4.0.2", "", {}, "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw=="], - - "@types/diff": ["@types/diff@7.0.2", "", {}, "sha512-JSWRMozjFKsGlEjiiKajUjIJVKuKdE3oVy2DNtK+fUo8q82nhFZ2CPQwicAIkXrofahDXrWJ7mjelvZphMS98Q=="], - - "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], - - "@types/mime-types": ["@types/mime-types@2.1.4", "", {}, "sha512-lfU4b34HOri+kAY5UheuFMWPDOI+OPceBSHZKp69gEyTL/mmJ4cnU6Y/rlme3UL3GyOn6Y42hyIEw0/q8sWx5w=="], - - "@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="], - - "@types/ndjson": ["@types/ndjson@2.0.4", "", { "dependencies": { "@types/node": "*", "@types/through": "*" } }, "sha512-ajAl7AjhFstF6waORYNSS49GL5iBKisqJlgvXuprXFKCX9fto4ordlNU3+XMgkMddgeR0WoQQBmKUk0v0dJ4pw=="], - - "@types/node": ["@types/node@22.19.3", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-1N9SBnWYOJTrNZCdh/yJE+t910Y128BoyY+zBLWhL3r0TYzlTmFdXrPwHL9DyFZmlEXNQQolTZh3KHV31QDhyA=="], - - "@types/through": ["@types/through@0.0.33", "", { "dependencies": { "@types/node": "*" } }, "sha512-HsJ+z3QuETzP3cswwtzt2vEIiHBk/dCcHGhbmG5X3ecnwFD/lPrMpliGXxSCg03L9AhrdwA4Oz/qfspkDW+xGQ=="], - - "@types/triple-beam": ["@types/triple-beam@1.3.5", "", {}, "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw=="], - - "@types/ws": ["@types/ws@8.18.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg=="], - - "@typescript/native-preview": ["@typescript/native-preview@7.0.0-dev.20260106.1", "", { "optionalDependencies": { "@typescript/native-preview-darwin-arm64": "7.0.0-dev.20260106.1", "@typescript/native-preview-darwin-x64": "7.0.0-dev.20260106.1", "@typescript/native-preview-linux-arm": "7.0.0-dev.20260106.1", "@typescript/native-preview-linux-arm64": "7.0.0-dev.20260106.1", "@typescript/native-preview-linux-x64": "7.0.0-dev.20260106.1", "@typescript/native-preview-win32-arm64": "7.0.0-dev.20260106.1", "@typescript/native-preview-win32-x64": "7.0.0-dev.20260106.1" }, "bin": { "tsgo": "bin/tsgo.js" } }, "sha512-EeH81rQsgLjewxuVOBN0MnQWAyf5YNeHRP3+Et6wJyr4d7HuA7zFwfNaEdfX1k366kgpKOR5K6dakorBhKZGng=="], - - "@typescript/native-preview-darwin-arm64": ["@typescript/native-preview-darwin-arm64@7.0.0-dev.20260106.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-9n7HIVP3UMgWSK8Yi2H+23hrrEDNNfkW78mbkxfatGh/ghU4m2QuO8R6MdMdPsSmmKDvbWOtpLEuSZFKNzu7eQ=="], - - "@typescript/native-preview-darwin-x64": ["@typescript/native-preview-darwin-x64@7.0.0-dev.20260106.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-zHJ1KsgQTpBnG3RbI1kjH/fD8juc5DTlQ9gbmJi23OhhaOgNF+PkqC2vAAWLFqdH99tAMvmJf9BJncbB7LwxXA=="], - - "@typescript/native-preview-linux-arm": ["@typescript/native-preview-linux-arm@7.0.0-dev.20260106.1", "", { "os": "linux", "cpu": "arm" }, "sha512-z7hdUMOOhdiVg1RmWyRyrIG3IIki4eJF3/TUtVVSTRwGq3t+j2JnLUUoK5VgX7EiqlN6wuJ94/FpWtyf+X4fkw=="], - - "@typescript/native-preview-linux-arm64": ["@typescript/native-preview-linux-arm64@7.0.0-dev.20260106.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-Mp7M7fgUsVW8MHadN58gjie1bzg06K1Id6vm2Aycnmk9rKgu8CxdaDayllr5giPo+iZLZOnw2FyGItrywd4fuA=="], - - "@typescript/native-preview-linux-x64": ["@typescript/native-preview-linux-x64@7.0.0-dev.20260106.1", "", { "os": "linux", "cpu": "x64" }, "sha512-H+c7xgK0gItbntnPFvt9nVv+cjjjn0lTj2tIjBQcTbH92q9RgFkIfztgxrP5zD8MzJKDOyIw/iAUSsb57lyxjw=="], - - "@typescript/native-preview-win32-arm64": ["@typescript/native-preview-win32-arm64@7.0.0-dev.20260106.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-PS1FyYa+/sHQa5Va0yz21DxaBkGGwOYfjMyRSs6oHq01DzMnVIjtsdNAALP0+oqki8Adw0D2XtsdB5QapDbBJw=="], - - "@typescript/native-preview-win32-x64": ["@typescript/native-preview-win32-x64@7.0.0-dev.20260106.1", "", { "os": "win32", "cpu": "x64" }, "sha512-AKVSTGcIE7d5KFtclhK3PVwUrsNnzziA7ZC/VDbMbvYCjLk7FE2GdNKaxQxLGHb53IUirgmltR5r4htn0WSM6A=="], - - "@vitest/expect": ["@vitest/expect@3.2.4", "", { "dependencies": { "@types/chai": "^5.2.2", "@vitest/spy": "3.2.4", "@vitest/utils": "3.2.4", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" } }, "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig=="], - - "@vitest/mocker": ["@vitest/mocker@3.2.4", "", { "dependencies": { "@vitest/spy": "3.2.4", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" }, "optionalPeers": ["msw", "vite"] }, "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ=="], - - "@vitest/pretty-format": ["@vitest/pretty-format@3.2.4", "", { "dependencies": { "tinyrainbow": "^2.0.0" } }, "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA=="], - - "@vitest/runner": ["@vitest/runner@3.2.4", "", { "dependencies": { "@vitest/utils": "3.2.4", "pathe": "^2.0.3", "strip-literal": "^3.0.0" } }, "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ=="], - - "@vitest/snapshot": ["@vitest/snapshot@3.2.4", "", { "dependencies": { "@vitest/pretty-format": "3.2.4", "magic-string": "^0.30.17", "pathe": "^2.0.3" } }, "sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ=="], - - "@vitest/spy": ["@vitest/spy@3.2.4", "", { "dependencies": { "tinyspy": "^4.0.3" } }, "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw=="], - - "@vitest/utils": ["@vitest/utils@3.2.4", "", { "dependencies": { "@vitest/pretty-format": "3.2.4", "loupe": "^3.1.4", "tinyrainbow": "^2.0.0" } }, "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA=="], - - "@xterm/headless": ["@xterm/headless@5.5.0", "", {}, "sha512-5xXB7kdQlFBP82ViMJTwwEc3gKCLGKR/eoxQm4zge7GPBl86tCdI0IdPJjoKd8mUSFXz5V7i/25sfsEkP4j46g=="], - - "@xterm/xterm": ["@xterm/xterm@5.5.0", "", {}, "sha512-hqJHYaQb5OptNunnyAnkHyM8aCjZ1MEIDTQu1iIbbTD/xops91NB5yq1ZK/dC2JDbVWtF23zUtl9JE2NqwT87A=="], - - "accepts": ["accepts@2.0.0", "", { "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" } }, "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng=="], - - "agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="], - - "ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="], - - "ajv-formats": ["ajv-formats@3.0.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ=="], - - "ansi-escapes": ["ansi-escapes@7.2.0", "", { "dependencies": { "environment": "^1.0.0" } }, "sha512-g6LhBsl+GBPRWGWsBtutpzBYuIIdBkLEvad5C/va/74Db018+5TZiyA26cZJAr3Rft5lprVqOIPxf5Vid6tqAw=="], - - "ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], - - "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], - - "any-promise": ["any-promise@1.3.0", "", {}, "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="], - - "assertion-error": ["assertion-error@2.0.1", "", {}, "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA=="], - - "async": ["async@3.2.6", "", {}, "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA=="], - - "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - - "base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="], - - "bignumber.js": ["bignumber.js@9.3.1", "", {}, "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ=="], - - "body-parser": ["body-parser@2.2.1", "", { "dependencies": { "bytes": "^3.1.2", "content-type": "^1.0.5", "debug": "^4.4.3", "http-errors": "^2.0.0", "iconv-lite": "^0.7.0", "on-finished": "^2.4.1", "qs": "^6.14.0", "raw-body": "^3.0.1", "type-is": "^2.0.1" } }, "sha512-nfDwkulwiZYQIGwxdy0RUmowMhKcFVcYXUU7m4QlKYim1rUtg83xm2yjZ40QjDuc291AJjjeSc9b++AWHSgSHw=="], - - "boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="], - - "brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], - - "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], - - "buffer-equal-constant-time": ["buffer-equal-constant-time@1.0.1", "", {}, "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="], - - "bun-types": ["bun-types@1.3.5", "", { "dependencies": { "@types/node": "*" } }, "sha512-inmAYe2PFLs0SUbFOWSVD24sg1jFlMPxOjOSSCYqUgn4Hsc3rDc7dFvfVYjFPNHtov6kgUeulV4SxbuIV/stPw=="], - - "bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="], - - "cac": ["cac@6.7.14", "", {}, "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ=="], - - "call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="], - - "call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="], - - "chai": ["chai@5.3.3", "", { "dependencies": { "assertion-error": "^2.0.1", "check-error": "^2.1.1", "deep-eql": "^5.0.1", "loupe": "^3.1.0", "pathval": "^2.0.0" } }, "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw=="], - - "chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="], - - "check-error": ["check-error@2.1.3", "", {}, "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA=="], - - "cli-cursor": ["cli-cursor@5.0.0", "", { "dependencies": { "restore-cursor": "^5.0.0" } }, "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw=="], - - "cli-highlight": ["cli-highlight@2.1.11", "", { "dependencies": { "chalk": "^4.0.0", "highlight.js": "^10.7.1", "mz": "^2.4.0", "parse5": "^5.1.1", "parse5-htmlparser2-tree-adapter": "^6.0.0", "yargs": "^16.0.0" }, "bin": { "highlight": "bin/highlight" } }, "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg=="], - - "cli-truncate": ["cli-truncate@5.1.1", "", { "dependencies": { "slice-ansi": "^7.1.0", "string-width": "^8.0.0" } }, "sha512-SroPvNHxUnk+vIW/dOSfNqdy1sPEFkrTk6TUtqLCnBlo3N7TNYYkzzN7uSD6+jVjrdO4+p8nH7JzH6cIvUem6A=="], - - "cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="], - - "color": ["color@5.0.3", "", { "dependencies": { "color-convert": "^3.1.3", "color-string": "^2.1.3" } }, "sha512-ezmVcLR3xAVp8kYOm4GS45ZLLgIE6SPAFoduLr6hTDajwb3KZ2F46gulK3XpcwRFb5KKGCSezCBAY4Dw4HsyXA=="], - - "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], - - "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], - - "color-string": ["color-string@2.1.4", "", { "dependencies": { "color-name": "^2.0.0" } }, "sha512-Bb6Cq8oq0IjDOe8wJmi4JeNn763Xs9cfrBcaylK1tPypWzyoy2G3l90v9k64kjphl/ZJjPIShFztenRomi8WTg=="], - - "colorette": ["colorette@2.0.20", "", {}, "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w=="], - - "commander": ["commander@14.0.2", "", {}, "sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ=="], - - "concurrently": ["concurrently@9.2.1", "", { "dependencies": { "chalk": "4.1.2", "rxjs": "7.8.2", "shell-quote": "1.8.3", "supports-color": "8.1.1", "tree-kill": "1.2.2", "yargs": "17.7.2" }, "bin": { "conc": "dist/bin/concurrently.js", "concurrently": "dist/bin/concurrently.js" } }, "sha512-fsfrO0MxV64Znoy8/l1vVIjjHa29SZyyqPgQBwhiDcaW8wJc2W3XWVOGx4M3oJBnv/zdUZIIp1gDeS98GzP8Ng=="], - - "content-disposition": ["content-disposition@1.0.1", "", {}, "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q=="], - - "content-type": ["content-type@1.0.5", "", {}, "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="], - - "cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="], - - "cookie-signature": ["cookie-signature@1.2.2", "", {}, "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg=="], - - "cors": ["cors@2.8.5", "", { "dependencies": { "object-assign": "^4", "vary": "^1" } }, "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g=="], - - "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], - - "css-select": ["css-select@5.2.2", "", { "dependencies": { "boolbase": "^1.0.0", "css-what": "^6.1.0", "domhandler": "^5.0.2", "domutils": "^3.0.1", "nth-check": "^2.0.1" } }, "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw=="], - - "css-what": ["css-what@6.2.2", "", {}, "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA=="], - - "data-uri-to-buffer": ["data-uri-to-buffer@4.0.1", "", {}, "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A=="], - - "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], - - "deep-eql": ["deep-eql@5.0.2", "", {}, "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q=="], - - "depd": ["depd@2.0.0", "", {}, "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="], - - "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], - - "diff": ["diff@8.0.2", "", {}, "sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg=="], - - "dom-serializer": ["dom-serializer@2.0.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", "entities": "^4.2.0" } }, "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg=="], - - "domelementtype": ["domelementtype@2.3.0", "", {}, "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="], - - "domhandler": ["domhandler@5.0.3", "", { "dependencies": { "domelementtype": "^2.3.0" } }, "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w=="], - - "domutils": ["domutils@3.2.2", "", { "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3" } }, "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw=="], - - "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="], - - "eastasianwidth": ["eastasianwidth@0.2.0", "", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="], - - "ecdsa-sig-formatter": ["ecdsa-sig-formatter@1.0.11", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ=="], - - "ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="], - - "emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], - - "enabled": ["enabled@2.0.0", "", {}, "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ=="], - - "encodeurl": ["encodeurl@2.0.0", "", {}, "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="], - - "entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], - - "environment": ["environment@1.1.0", "", {}, "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q=="], - - "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="], - - "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="], - - "es-module-lexer": ["es-module-lexer@1.7.0", "", {}, "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA=="], - - "es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="], - - "esbuild": ["esbuild@0.27.2", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.2", "@esbuild/android-arm": "0.27.2", "@esbuild/android-arm64": "0.27.2", "@esbuild/android-x64": "0.27.2", "@esbuild/darwin-arm64": "0.27.2", "@esbuild/darwin-x64": "0.27.2", "@esbuild/freebsd-arm64": "0.27.2", "@esbuild/freebsd-x64": "0.27.2", "@esbuild/linux-arm": "0.27.2", "@esbuild/linux-arm64": "0.27.2", "@esbuild/linux-ia32": "0.27.2", "@esbuild/linux-loong64": "0.27.2", "@esbuild/linux-mips64el": "0.27.2", "@esbuild/linux-ppc64": "0.27.2", "@esbuild/linux-riscv64": "0.27.2", "@esbuild/linux-s390x": "0.27.2", "@esbuild/linux-x64": "0.27.2", "@esbuild/netbsd-arm64": "0.27.2", "@esbuild/netbsd-x64": "0.27.2", "@esbuild/openbsd-arm64": "0.27.2", "@esbuild/openbsd-x64": "0.27.2", "@esbuild/openharmony-arm64": "0.27.2", "@esbuild/sunos-x64": "0.27.2", "@esbuild/win32-arm64": "0.27.2", "@esbuild/win32-ia32": "0.27.2", "@esbuild/win32-x64": "0.27.2" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw=="], - - "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], - - "escape-html": ["escape-html@1.0.3", "", {}, "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="], - - "estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="], - - "etag": ["etag@1.8.1", "", {}, "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="], - - "eventemitter3": ["eventemitter3@5.0.1", "", {}, "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="], - - "eventsource": ["eventsource@3.0.7", "", { "dependencies": { "eventsource-parser": "^3.0.1" } }, "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA=="], - - "eventsource-parser": ["eventsource-parser@3.0.6", "", {}, "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg=="], - - "expect-type": ["expect-type@1.3.0", "", {}, "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA=="], - - "express": ["express@5.2.1", "", { "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.1", "content-disposition": "^1.0.0", "content-type": "^1.0.5", "cookie": "^0.7.1", "cookie-signature": "^1.2.1", "debug": "^4.4.0", "depd": "^2.0.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "finalhandler": "^2.1.0", "fresh": "^2.0.0", "http-errors": "^2.0.0", "merge-descriptors": "^2.0.0", "mime-types": "^3.0.0", "on-finished": "^2.4.1", "once": "^1.4.0", "parseurl": "^1.3.3", "proxy-addr": "^2.0.7", "qs": "^6.14.0", "range-parser": "^1.2.1", "router": "^2.2.0", "send": "^1.1.0", "serve-static": "^2.2.0", "statuses": "^2.0.1", "type-is": "^2.0.1", "vary": "^1.1.2" } }, "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw=="], - - "express-rate-limit": ["express-rate-limit@7.5.1", "", { "peerDependencies": { "express": ">= 4.11" } }, "sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw=="], - - "extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="], - - "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], - - "fast-uri": ["fast-uri@3.1.0", "", {}, "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA=="], - - "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], - - "fecha": ["fecha@4.2.3", "", {}, "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw=="], - - "fetch-blob": ["fetch-blob@3.2.0", "", { "dependencies": { "node-domexception": "^1.0.0", "web-streams-polyfill": "^3.0.3" } }, "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ=="], - - "file-stream-rotator": ["file-stream-rotator@0.6.1", "", { "dependencies": { "moment": "^2.29.1" } }, "sha512-u+dBid4PvZw17PmDeRcNOtCP9CCK/9lRN2w+r1xIS7yOL9JFrIBKTvrYsxT4P0pGtThYTn++QS5ChHaUov3+zQ=="], - - "file-type": ["file-type@21.3.0", "", { "dependencies": { "@tokenizer/inflate": "^0.4.1", "strtok3": "^10.3.4", "token-types": "^6.1.1", "uint8array-extras": "^1.4.0" } }, "sha512-8kPJMIGz1Yt/aPEwOsrR97ZyZaD1Iqm8PClb1nYFclUCkBi0Ma5IsYNQzvSFS9ib51lWyIw5mIT9rWzI/xjpzA=="], - - "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], - - "finalhandler": ["finalhandler@2.1.1", "", { "dependencies": { "debug": "^4.4.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "on-finished": "^2.4.1", "parseurl": "^1.3.3", "statuses": "^2.0.1" } }, "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA=="], - - "fn.name": ["fn.name@1.1.0", "", {}, "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw=="], - - "foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="], - - "formdata-polyfill": ["formdata-polyfill@4.0.10", "", { "dependencies": { "fetch-blob": "^3.1.2" } }, "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g=="], - - "forwarded": ["forwarded@0.2.0", "", {}, "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="], - - "fresh": ["fresh@2.0.0", "", {}, "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A=="], - - "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], - - "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], - - "gaxios": ["gaxios@7.1.3", "", { "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", "node-fetch": "^3.3.2", "rimraf": "^5.0.1" } }, "sha512-YGGyuEdVIjqxkxVH1pUTMY/XtmmsApXrCVv5EU25iX6inEPbV+VakJfLealkBtJN69AQmh1eGOdCl9Sm1UP6XQ=="], - - "gcp-metadata": ["gcp-metadata@8.1.2", "", { "dependencies": { "gaxios": "^7.0.0", "google-logging-utils": "^1.0.0", "json-bigint": "^1.0.0" } }, "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg=="], - - "get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="], - - "get-east-asian-width": ["get-east-asian-width@1.4.0", "", {}, "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q=="], - - "get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="], - - "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="], - - "glob": ["glob@11.1.0", "", { "dependencies": { "foreground-child": "^3.3.1", "jackspeak": "^4.1.1", "minimatch": "^10.1.1", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^2.0.0" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw=="], - - "google-auth-library": ["google-auth-library@10.5.0", "", { "dependencies": { "base64-js": "^1.3.0", "ecdsa-sig-formatter": "^1.0.11", "gaxios": "^7.0.0", "gcp-metadata": "^8.0.0", "google-logging-utils": "^1.0.0", "gtoken": "^8.0.0", "jws": "^4.0.0" } }, "sha512-7ABviyMOlX5hIVD60YOfHw4/CxOfBhyduaYB+wbFWCWoni4N7SLcV46hrVRktuBbZjFC9ONyqamZITN7q3n32w=="], - - "google-logging-utils": ["google-logging-utils@1.1.3", "", {}, "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA=="], - - "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="], - - "gtoken": ["gtoken@8.0.0", "", { "dependencies": { "gaxios": "^7.0.0", "jws": "^4.0.0" } }, "sha512-+CqsMbHPiSTdtSO14O51eMNlrp9N79gmeqmXeouJOhfucAedHw9noVe/n5uJk3tbKE6a+6ZCQg3RPhVhHByAIw=="], - - "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], - - "has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="], - - "hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="], - - "he": ["he@1.2.0", "", { "bin": { "he": "bin/he" } }, "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="], - - "highlight.js": ["highlight.js@11.11.1", "", {}, "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w=="], - - "hono": ["hono@4.11.3", "", {}, "sha512-PmQi306+M/ct/m5s66Hrg+adPnkD5jiO6IjA7WhWw0gSBSo1EcRegwuI1deZ+wd5pzCGynCcn2DprnE4/yEV4w=="], - - "http-errors": ["http-errors@2.0.1", "", { "dependencies": { "depd": "~2.0.0", "inherits": "~2.0.4", "setprototypeof": "~1.2.0", "statuses": "~2.0.2", "toidentifier": "~1.0.1" } }, "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ=="], - - "https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="], - - "iconv-lite": ["iconv-lite@0.7.1", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-2Tth85cXwGFHfvRgZWszZSvdo+0Xsqmw8k8ZwxScfcBneNUraK+dxRxRm24nszx80Y0TVio8kKLt5sLE7ZCLlw=="], - - "ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], - - "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], - - "ipaddr.js": ["ipaddr.js@1.9.1", "", {}, "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="], - - "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], - - "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], - - "is-promise": ["is-promise@4.0.0", "", {}, "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ=="], - - "is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="], - - "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], - - "jackspeak": ["jackspeak@4.1.1", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" } }, "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ=="], - - "jose": ["jose@6.1.3", "", {}, "sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ=="], - - "js-tokens": ["js-tokens@9.0.1", "", {}, "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ=="], - - "json-bigint": ["json-bigint@1.0.0", "", { "dependencies": { "bignumber.js": "^9.0.0" } }, "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ=="], - - "json-schema-to-ts": ["json-schema-to-ts@3.1.1", "", { "dependencies": { "@babel/runtime": "^7.18.3", "ts-algebra": "^2.0.0" } }, "sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g=="], - - "json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], - - "json-schema-typed": ["json-schema-typed@8.0.2", "", {}, "sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA=="], - - "json-stringify-safe": ["json-stringify-safe@5.0.1", "", {}, "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA=="], - - "jwa": ["jwa@2.0.1", "", { "dependencies": { "buffer-equal-constant-time": "^1.0.1", "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "^5.0.1" } }, "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg=="], - - "jws": ["jws@4.0.1", "", { "dependencies": { "jwa": "^2.0.1", "safe-buffer": "^5.0.1" } }, "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA=="], - - "kuler": ["kuler@2.0.0", "", {}, "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A=="], - - "lint-staged": ["lint-staged@16.2.7", "", { "dependencies": { "commander": "^14.0.2", "listr2": "^9.0.5", "micromatch": "^4.0.8", "nano-spawn": "^2.0.0", "pidtree": "^0.6.0", "string-argv": "^0.3.2", "yaml": "^2.8.1" }, "bin": { "lint-staged": "bin/lint-staged.js" } }, "sha512-lDIj4RnYmK7/kXMya+qJsmkRFkGolciXjrsZ6PC25GdTfWOAWetR0ZbsNXRAj1EHHImRSalc+whZFg56F5DVow=="], - - "listr2": ["listr2@9.0.5", "", { "dependencies": { "cli-truncate": "^5.0.0", "colorette": "^2.0.20", "eventemitter3": "^5.0.1", "log-update": "^6.1.0", "rfdc": "^1.4.1", "wrap-ansi": "^9.0.0" } }, "sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g=="], - - "log-update": ["log-update@6.1.0", "", { "dependencies": { "ansi-escapes": "^7.0.0", "cli-cursor": "^5.0.0", "slice-ansi": "^7.1.0", "strip-ansi": "^7.1.0", "wrap-ansi": "^9.0.0" } }, "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w=="], - - "logform": ["logform@2.7.0", "", { "dependencies": { "@colors/colors": "1.6.0", "@types/triple-beam": "^1.3.2", "fecha": "^4.2.0", "ms": "^2.1.1", "safe-stable-stringify": "^2.3.1", "triple-beam": "^1.3.0" } }, "sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ=="], - - "loupe": ["loupe@3.2.1", "", {}, "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ=="], - - "lru-cache": ["lru-cache@11.2.4", "", {}, "sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg=="], - - "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], - - "marked": ["marked@15.0.12", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA=="], - - "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="], - - "media-typer": ["media-typer@1.1.0", "", {}, "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw=="], - - "merge-descriptors": ["merge-descriptors@2.0.0", "", {}, "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g=="], - - "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], - - "mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="], - - "mime-types": ["mime-types@3.0.2", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A=="], - - "mimic-function": ["mimic-function@5.0.1", "", {}, "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA=="], - - "minimatch": ["minimatch@10.1.1", "", { "dependencies": { "@isaacs/brace-expansion": "^5.0.0" } }, "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ=="], - - "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="], - - "minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="], - - "moment": ["moment@2.30.1", "", {}, "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how=="], - - "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], - - "mz": ["mz@2.7.0", "", { "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", "thenify-all": "^1.0.0" } }, "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q=="], - - "nano-spawn": ["nano-spawn@2.0.0", "", {}, "sha512-tacvGzUY5o2D8CBh2rrwxyNojUsZNU2zjNTzKQrkgGJQTbGAfArVWXSKMBokBeeg6C7OLRGUEyoFlYbfeWQIqw=="], - - "nanoid": ["nanoid@5.1.6", "", { "bin": { "nanoid": "bin/nanoid.js" } }, "sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg=="], - - "ndjson": ["ndjson@2.0.0", "", { "dependencies": { "json-stringify-safe": "^5.0.1", "minimist": "^1.2.5", "readable-stream": "^3.6.0", "split2": "^3.0.0", "through2": "^4.0.0" }, "bin": { "ndjson": "cli.js" } }, "sha512-nGl7LRGrzugTtaFcJMhLbpzJM6XdivmbkdlaGcrk/LXg2KL/YBC6z1g70xh0/al+oFuVFP8N8kiWRucmeEH/qQ=="], - - "negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="], - - "node-domexception": ["node-domexception@1.0.0", "", {}, "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="], - - "node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="], - - "node-html-parser": ["node-html-parser@6.1.13", "", { "dependencies": { "css-select": "^5.1.0", "he": "1.2.0" } }, "sha512-qIsTMOY4C/dAa5Q5vsobRpOOvPfC4pB61UVW2uSwZNUp0QU/jCekTal1vMmbO0DgdHeLUJpv/ARmDqErVxA3Sg=="], - - "nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="], - - "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="], - - "object-hash": ["object-hash@3.0.0", "", {}, "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw=="], - - "object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="], - - "on-finished": ["on-finished@2.4.1", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg=="], - - "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="], - - "one-time": ["one-time@1.0.0", "", { "dependencies": { "fn.name": "1.x.x" } }, "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g=="], - - "onetime": ["onetime@7.0.0", "", { "dependencies": { "mimic-function": "^5.0.0" } }, "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ=="], - - "openai": ["openai@6.10.0", "", { "peerDependencies": { "ws": "^8.18.0", "zod": "^3.25 || ^4.0" }, "optionalPeers": ["ws", "zod"], "bin": { "openai": "bin/cli" } }, "sha512-ITxOGo7rO3XRMiKA5l7tQ43iNNu+iXGFAcf2t+aWVzzqRaS0i7m1K2BhxNdaveB+5eENhO0VY1FkiZzhBk4v3A=="], - - "package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="], - - "parse5": ["parse5@5.1.1", "", {}, "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug=="], - - "parse5-htmlparser2-tree-adapter": ["parse5-htmlparser2-tree-adapter@6.0.1", "", { "dependencies": { "parse5": "^6.0.1" } }, "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA=="], - - "parseurl": ["parseurl@1.3.3", "", {}, "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="], - - "partial-json": ["partial-json@0.1.7", "", {}, "sha512-Njv/59hHaokb/hRUjce3Hdv12wd60MtM9Z5Olmn+nehe0QDAsRtRbJPvJ0Z91TusF0SuZRIvnM+S4l6EIP8leA=="], - - "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], - - "path-scurry": ["path-scurry@2.0.1", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA=="], - - "path-to-regexp": ["path-to-regexp@8.3.0", "", {}, "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA=="], - - "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], - - "pathval": ["pathval@2.0.1", "", {}, "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ=="], - - "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], - - "picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], - - "pidtree": ["pidtree@0.6.0", "", { "bin": { "pidtree": "bin/pidtree.js" } }, "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g=="], - - "pkce-challenge": ["pkce-challenge@5.0.1", "", {}, "sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ=="], - - "postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="], - - "proxy-addr": ["proxy-addr@2.0.7", "", { "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg=="], - - "qs": ["qs@6.14.1", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ=="], - - "range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="], - - "raw-body": ["raw-body@3.0.2", "", { "dependencies": { "bytes": "~3.1.2", "http-errors": "~2.0.1", "iconv-lite": "~0.7.0", "unpipe": "~1.0.0" } }, "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA=="], - - "readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], - - "require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="], - - "require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="], - - "restore-cursor": ["restore-cursor@5.1.0", "", { "dependencies": { "onetime": "^7.0.0", "signal-exit": "^4.1.0" } }, "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA=="], - - "rfdc": ["rfdc@1.4.1", "", {}, "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="], - - "rimraf": ["rimraf@5.0.10", "", { "dependencies": { "glob": "^10.3.7" }, "bin": { "rimraf": "dist/esm/bin.mjs" } }, "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ=="], - - "rollup": ["rollup@4.55.1", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.55.1", "@rollup/rollup-android-arm64": "4.55.1", "@rollup/rollup-darwin-arm64": "4.55.1", "@rollup/rollup-darwin-x64": "4.55.1", "@rollup/rollup-freebsd-arm64": "4.55.1", "@rollup/rollup-freebsd-x64": "4.55.1", "@rollup/rollup-linux-arm-gnueabihf": "4.55.1", "@rollup/rollup-linux-arm-musleabihf": "4.55.1", "@rollup/rollup-linux-arm64-gnu": "4.55.1", "@rollup/rollup-linux-arm64-musl": "4.55.1", "@rollup/rollup-linux-loong64-gnu": "4.55.1", "@rollup/rollup-linux-loong64-musl": "4.55.1", "@rollup/rollup-linux-ppc64-gnu": "4.55.1", "@rollup/rollup-linux-ppc64-musl": "4.55.1", "@rollup/rollup-linux-riscv64-gnu": "4.55.1", "@rollup/rollup-linux-riscv64-musl": "4.55.1", "@rollup/rollup-linux-s390x-gnu": "4.55.1", "@rollup/rollup-linux-x64-gnu": "4.55.1", "@rollup/rollup-linux-x64-musl": "4.55.1", "@rollup/rollup-openbsd-x64": "4.55.1", "@rollup/rollup-openharmony-arm64": "4.55.1", "@rollup/rollup-win32-arm64-msvc": "4.55.1", "@rollup/rollup-win32-ia32-msvc": "4.55.1", "@rollup/rollup-win32-x64-gnu": "4.55.1", "@rollup/rollup-win32-x64-msvc": "4.55.1", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-wDv/Ht1BNHB4upNbK74s9usvl7hObDnvVzknxqY/E/O3X6rW1U1rV1aENEfJ54eFZDTNo7zv1f5N4edCluH7+A=="], - - "router": ["router@2.2.0", "", { "dependencies": { "debug": "^4.4.0", "depd": "^2.0.0", "is-promise": "^4.0.0", "parseurl": "^1.3.3", "path-to-regexp": "^8.0.0" } }, "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ=="], - - "rxjs": ["rxjs@7.8.2", "", { "dependencies": { "tslib": "^2.1.0" } }, "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA=="], - - "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], - - "safe-stable-stringify": ["safe-stable-stringify@2.5.0", "", {}, "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA=="], - - "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="], - - "semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="], - - "send": ["send@1.2.1", "", { "dependencies": { "debug": "^4.4.3", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "fresh": "^2.0.0", "http-errors": "^2.0.1", "mime-types": "^3.0.2", "ms": "^2.1.3", "on-finished": "^2.4.1", "range-parser": "^1.2.1", "statuses": "^2.0.2" } }, "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ=="], - - "serve-static": ["serve-static@2.2.1", "", { "dependencies": { "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "parseurl": "^1.3.3", "send": "^1.2.0" } }, "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw=="], - - "setprototypeof": ["setprototypeof@1.2.0", "", {}, "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="], - - "sharp": ["sharp@0.34.5", "", { "dependencies": { "@img/colour": "^1.0.0", "detect-libc": "^2.1.2", "semver": "^7.7.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.34.5", "@img/sharp-darwin-x64": "0.34.5", "@img/sharp-libvips-darwin-arm64": "1.2.4", "@img/sharp-libvips-darwin-x64": "1.2.4", "@img/sharp-libvips-linux-arm": "1.2.4", "@img/sharp-libvips-linux-arm64": "1.2.4", "@img/sharp-libvips-linux-ppc64": "1.2.4", "@img/sharp-libvips-linux-riscv64": "1.2.4", "@img/sharp-libvips-linux-s390x": "1.2.4", "@img/sharp-libvips-linux-x64": "1.2.4", "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", "@img/sharp-libvips-linuxmusl-x64": "1.2.4", "@img/sharp-linux-arm": "0.34.5", "@img/sharp-linux-arm64": "0.34.5", "@img/sharp-linux-ppc64": "0.34.5", "@img/sharp-linux-riscv64": "0.34.5", "@img/sharp-linux-s390x": "0.34.5", "@img/sharp-linux-x64": "0.34.5", "@img/sharp-linuxmusl-arm64": "0.34.5", "@img/sharp-linuxmusl-x64": "0.34.5", "@img/sharp-wasm32": "0.34.5", "@img/sharp-win32-arm64": "0.34.5", "@img/sharp-win32-ia32": "0.34.5", "@img/sharp-win32-x64": "0.34.5" } }, "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg=="], - - "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], - - "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], - - "shell-quote": ["shell-quote@1.8.3", "", {}, "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw=="], - - "side-channel": ["side-channel@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", "side-channel-list": "^1.0.0", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="], - - "side-channel-list": ["side-channel-list@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3" } }, "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA=="], - - "side-channel-map": ["side-channel-map@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3" } }, "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA=="], - - "side-channel-weakmap": ["side-channel-weakmap@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3", "side-channel-map": "^1.0.1" } }, "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A=="], - - "siginfo": ["siginfo@2.0.0", "", {}, "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g=="], - - "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], - - "slice-ansi": ["slice-ansi@7.1.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^5.0.0" } }, "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w=="], - - "smol-toml": ["smol-toml@1.6.0", "", {}, "sha512-4zemZi0HvTnYwLfrpk/CF9LOd9Lt87kAt50GnqhMpyF9U3poDAP2+iukq2bZsO/ufegbYehBkqINbsWxj4l4cw=="], - - "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], - - "split2": ["split2@3.2.2", "", { "dependencies": { "readable-stream": "^3.0.0" } }, "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg=="], - - "stack-trace": ["stack-trace@0.0.10", "", {}, "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg=="], - - "stackback": ["stackback@0.0.2", "", {}, "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw=="], - - "statuses": ["statuses@2.0.2", "", {}, "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="], - - "std-env": ["std-env@3.10.0", "", {}, "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg=="], - - "string-argv": ["string-argv@0.3.2", "", {}, "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q=="], - - "string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], - - "string-width-cjs": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], - - "string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="], - - "strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="], - - "strip-ansi-cjs": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - - "strip-literal": ["strip-literal@3.1.0", "", { "dependencies": { "js-tokens": "^9.0.1" } }, "sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg=="], - - "strtok3": ["strtok3@10.3.4", "", { "dependencies": { "@tokenizer/token": "^0.3.0" } }, "sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg=="], - - "supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], - - "text-hex": ["text-hex@1.0.0", "", {}, "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg=="], - - "thenify": ["thenify@3.3.1", "", { "dependencies": { "any-promise": "^1.0.0" } }, "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw=="], - - "thenify-all": ["thenify-all@1.6.0", "", { "dependencies": { "thenify": ">= 3.1.0 < 4" } }, "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA=="], - - "through2": ["through2@4.0.2", "", { "dependencies": { "readable-stream": "3" } }, "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw=="], - - "tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="], - - "tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="], - - "tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="], - - "tinypool": ["tinypool@1.1.1", "", {}, "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg=="], - - "tinyrainbow": ["tinyrainbow@2.0.0", "", {}, "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw=="], - - "tinyspy": ["tinyspy@4.0.4", "", {}, "sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q=="], - - "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], - - "toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="], - - "token-types": ["token-types@6.1.2", "", { "dependencies": { "@borewit/text-codec": "^0.2.1", "@tokenizer/token": "^0.3.0", "ieee754": "^1.2.1" } }, "sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww=="], - - "tree-kill": ["tree-kill@1.2.2", "", { "bin": { "tree-kill": "cli.js" } }, "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A=="], - - "triple-beam": ["triple-beam@1.4.1", "", {}, "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg=="], - - "ts-algebra": ["ts-algebra@2.0.0", "", {}, "sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw=="], - - "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], - - "type-is": ["type-is@2.0.1", "", { "dependencies": { "content-type": "^1.0.5", "media-typer": "^1.1.0", "mime-types": "^3.0.0" } }, "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw=="], - - "uint8array-extras": ["uint8array-extras@1.5.0", "", {}, "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A=="], - - "undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], - - "unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="], - - "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], - - "vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="], - - "vite": ["vite@7.3.0", "", { "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-dZwN5L1VlUBewiP6H9s2+B3e3Jg96D0vzN+Ry73sOefebhYr9f94wwkMNN/9ouoU8pV1BqA1d1zGk8928cx0rg=="], - - "vite-node": ["vite-node@3.2.4", "", { "dependencies": { "cac": "^6.7.14", "debug": "^4.4.1", "es-module-lexer": "^1.7.0", "pathe": "^2.0.3", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" }, "bin": { "vite-node": "vite-node.mjs" } }, "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg=="], - - "vitest": ["vitest@3.2.4", "", { "dependencies": { "@types/chai": "^5.2.2", "@vitest/expect": "3.2.4", "@vitest/mocker": "3.2.4", "@vitest/pretty-format": "^3.2.4", "@vitest/runner": "3.2.4", "@vitest/snapshot": "3.2.4", "@vitest/spy": "3.2.4", "@vitest/utils": "3.2.4", "chai": "^5.2.0", "debug": "^4.4.1", "expect-type": "^1.2.1", "magic-string": "^0.30.17", "pathe": "^2.0.3", "picomatch": "^4.0.2", "std-env": "^3.9.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", "tinyglobby": "^0.2.14", "tinypool": "^1.1.1", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0", "vite-node": "3.2.4", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "@vitest/browser": "3.2.4", "@vitest/ui": "3.2.4", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@types/debug", "@types/node", "@vitest/browser", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A=="], - - "web-streams-polyfill": ["web-streams-polyfill@3.3.3", "", {}, "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw=="], - - "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], - - "why-is-node-running": ["why-is-node-running@2.3.0", "", { "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" }, "bin": { "why-is-node-running": "cli.js" } }, "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w=="], - - "winston": ["winston@3.19.0", "", { "dependencies": { "@colors/colors": "^1.6.0", "@dabh/diagnostics": "^2.0.8", "async": "^3.2.3", "is-stream": "^2.0.0", "logform": "^2.7.0", "one-time": "^1.0.0", "readable-stream": "^3.4.0", "safe-stable-stringify": "^2.3.1", "stack-trace": "0.0.x", "triple-beam": "^1.3.0", "winston-transport": "^4.9.0" } }, "sha512-LZNJgPzfKR+/J3cHkxcpHKpKKvGfDZVPS4hfJCc4cCG0CgYzvlD6yE/S3CIL/Yt91ak327YCpiF/0MyeZHEHKA=="], - - "winston-daily-rotate-file": ["winston-daily-rotate-file@5.0.0", "", { "dependencies": { "file-stream-rotator": "^0.6.1", "object-hash": "^3.0.0", "triple-beam": "^1.4.1", "winston-transport": "^4.7.0" }, "peerDependencies": { "winston": "^3" } }, "sha512-JDjiXXkM5qvwY06733vf09I2wnMXpZEhxEVOSPenZMii+g7pcDcTBt2MRugnoi8BwVSuCT2jfRXBUy+n1Zz/Yw=="], - - "winston-transport": ["winston-transport@4.9.0", "", { "dependencies": { "logform": "^2.7.0", "readable-stream": "^3.6.2", "triple-beam": "^1.3.0" } }, "sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A=="], - - "wrap-ansi": ["wrap-ansi@9.0.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", "strip-ansi": "^7.1.0" } }, "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww=="], - - "wrap-ansi-cjs": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], - - "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="], - - "ws": ["ws@8.19.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg=="], - - "y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="], - - "yaml": ["yaml@2.8.2", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A=="], - - "yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], - - "yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="], - - "zod": ["zod@4.3.5", "", {}, "sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g=="], - - "zod-to-json-schema": ["zod-to-json-schema@3.25.1", "", { "peerDependencies": { "zod": "^3.25 || ^4" } }, "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA=="], - - "@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], - - "@isaacs/cliui/wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="], - - "@mistralai/mistralai/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], - - "@oh-my-pi/pi-agent-core/@types/node": ["@types/node@24.10.4", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-vnDVpYPMzs4wunl27jHrfmwojOGKya0xyM3sH+UE5iv5uPS6vX7UIoh6m+vQc5LGBq52HBKPIn/zcSZVzeDEZg=="], - - "@oh-my-pi/pi-coding-agent/@types/node": ["@types/node@24.10.4", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-vnDVpYPMzs4wunl27jHrfmwojOGKya0xyM3sH+UE5iv5uPS6vX7UIoh6m+vQc5LGBq52HBKPIn/zcSZVzeDEZg=="], - - "@oh-my-pi/pi-git-tool/@types/node": ["@types/node@24.10.4", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-vnDVpYPMzs4wunl27jHrfmwojOGKya0xyM3sH+UE5iv5uPS6vX7UIoh6m+vQc5LGBq52HBKPIn/zcSZVzeDEZg=="], - - "@openai/agents/openai": ["openai@6.15.0", "", { "peerDependencies": { "ws": "^8.18.0", "zod": "^3.25 || ^4.0" }, "optionalPeers": ["ws", "zod"], "bin": { "openai": "bin/cli" } }, "sha512-F1Lvs5BoVvmZtzkUEVyh8mDQPPFolq4F+xdsx/DO8Hee8YF3IGAlZqUIsF+DVGhqf4aU0a3bTghsxB6OIsRy1g=="], - - "@openai/agents-core/openai": ["openai@6.15.0", "", { "peerDependencies": { "ws": "^8.18.0", "zod": "^3.25 || ^4.0" }, "optionalPeers": ["ws", "zod"], "bin": { "openai": "bin/cli" } }, "sha512-F1Lvs5BoVvmZtzkUEVyh8mDQPPFolq4F+xdsx/DO8Hee8YF3IGAlZqUIsF+DVGhqf4aU0a3bTghsxB6OIsRy1g=="], - - "@openai/agents-openai/openai": ["openai@6.15.0", "", { "peerDependencies": { "ws": "^8.18.0", "zod": "^3.25 || ^4.0" }, "optionalPeers": ["ws", "zod"], "bin": { "openai": "bin/cli" } }, "sha512-F1Lvs5BoVvmZtzkUEVyh8mDQPPFolq4F+xdsx/DO8Hee8YF3IGAlZqUIsF+DVGhqf4aU0a3bTghsxB6OIsRy1g=="], - - "@types/ndjson/@types/node": ["@types/node@24.10.4", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-vnDVpYPMzs4wunl27jHrfmwojOGKya0xyM3sH+UE5iv5uPS6vX7UIoh6m+vQc5LGBq52HBKPIn/zcSZVzeDEZg=="], - - "@types/through/@types/node": ["@types/node@24.10.4", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-vnDVpYPMzs4wunl27jHrfmwojOGKya0xyM3sH+UE5iv5uPS6vX7UIoh6m+vQc5LGBq52HBKPIn/zcSZVzeDEZg=="], - - "@types/ws/@types/node": ["@types/node@24.10.4", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-vnDVpYPMzs4wunl27jHrfmwojOGKya0xyM3sH+UE5iv5uPS6vX7UIoh6m+vQc5LGBq52HBKPIn/zcSZVzeDEZg=="], - - "bun-types/@types/node": ["@types/node@24.10.4", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-vnDVpYPMzs4wunl27jHrfmwojOGKya0xyM3sH+UE5iv5uPS6vX7UIoh6m+vQc5LGBq52HBKPIn/zcSZVzeDEZg=="], - - "cli-highlight/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], - - "cli-highlight/highlight.js": ["highlight.js@10.7.3", "", {}, "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A=="], - - "cli-highlight/yargs": ["yargs@16.2.0", "", { "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.0", "y18n": "^5.0.5", "yargs-parser": "^20.2.2" } }, "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw=="], - - "cli-truncate/string-width": ["string-width@8.1.0", "", { "dependencies": { "get-east-asian-width": "^1.3.0", "strip-ansi": "^7.1.0" } }, "sha512-Kxl3KJGb/gxkaUMOjRsQ8IrXiGW75O4E3RPjFIINOVH8AMl2SQ/yWdTzWwF3FevIX9LcMAjJW+GRwAlAbTSXdg=="], - - "cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - - "cliui/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], - - "color/color-convert": ["color-convert@3.1.3", "", { "dependencies": { "color-name": "^2.0.0" } }, "sha512-fasDH2ont2GqF5HpyO4w0+BcewlhHEZOFn9c1ckZdHpJ56Qb7MHhH/IcJZbBGgvdtwdwNbLvxiBEdg336iA9Sg=="], - - "color-string/color-name": ["color-name@2.1.0", "", {}, "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg=="], - - "concurrently/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], - - "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], - - "parse5-htmlparser2-tree-adapter/parse5": ["parse5@6.0.1", "", {}, "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw=="], - - "postcss/nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], - - "rimraf/glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="], - - "slice-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], - - "slice-ansi/is-fullwidth-code-point": ["is-fullwidth-code-point@5.1.0", "", { "dependencies": { "get-east-asian-width": "^1.3.1" } }, "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ=="], - - "string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - - "string-width-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - - "strip-ansi-cjs/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - - "wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], - - "wrap-ansi/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="], - - "wrap-ansi-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - - "@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], - - "@isaacs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], - - "@oh-my-pi/pi-agent-core/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], - - "@oh-my-pi/pi-coding-agent/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], - - "@oh-my-pi/pi-git-tool/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], - - "@types/ndjson/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], - - "@types/through/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], - - "@types/ws/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], - - "bun-types/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], - - "cli-highlight/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], - - "cli-highlight/yargs/cliui": ["cliui@7.0.4", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^7.0.0" } }, "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ=="], - - "cli-highlight/yargs/yargs-parser": ["yargs-parser@20.2.9", "", {}, "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w=="], - - "cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - - "color/color-convert/color-name": ["color-name@2.1.0", "", {}, "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg=="], - - "concurrently/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], - - "rimraf/glob/jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="], - - "rimraf/glob/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], - - "rimraf/glob/path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="], - - "string-width-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - - "string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - - "wrap-ansi-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - - "wrap-ansi/string-width/emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="], - - "cli-highlight/yargs/cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - - "cli-highlight/yargs/cliui/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], - - "rimraf/glob/path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], - - "cli-highlight/yargs/cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - } + "lockfileVersion": 1, + "configVersion": 1, + "workspaces": { + "": { + "name": "omp-monorepo", + "dependencies": { + "@sinclair/typebox": "^0.34.46", + "get-east-asian-width": "^1.4.0" + }, + "devDependencies": { + "@biomejs/biome": "2.3.11", + "@types/bun": "^1.2.17", + "@types/node": "^22.10.5", + "@typescript/native-preview": "^7.0.0-dev.20260102.1", + "bun-types": "^1.3.5", + "concurrently": "^9.2.1", + "lint-staged": "^16.2.7" + } + }, + "packages/agent": { + "name": "@oh-my-pi/pi-agent-core", + "version": "3.21.0", + "dependencies": { + "@mariozechner/pi-ai": "^0.37.4", + "@oh-my-pi/pi-tui": "workspace:*" + }, + "devDependencies": { + "@types/node": "^24.3.0", + "vitest": "^3.2.4" + } + }, + "packages/coding-agent": { + "name": "@oh-my-pi/pi-coding-agent", + "version": "3.21.0", + "bin": { + "omp": "src/cli.ts" + }, + "dependencies": { + "@mariozechner/pi-ai": "^0.37.4", + "@oh-my-pi/pi-agent-core": "workspace:*", + "@oh-my-pi/pi-git-tool": "workspace:*", + "@oh-my-pi/pi-tui": "workspace:*", + "@openai/agents": "^0.3.7", + "@sinclair/typebox": "^0.34.46", + "ajv": "^8.17.1", + "chalk": "^5.5.0", + "cli-highlight": "^2.1.11", + "diff": "^8.0.2", + "file-type": "^21.1.1", + "glob": "^11.0.3", + "highlight.js": "^11.11.1", + "marked": "^15.0.12", + "minimatch": "^10.1.1", + "nanoid": "^5.1.6", + "ndjson": "^2.0.0", + "node-html-parser": "^6.1.13", + "sharp": "^0.34.2", + "smol-toml": "^1.6.0", + "strip-ansi": "^7.1.2", + "winston": "^3.17.0", + "winston-daily-rotate-file": "^5.0.0", + "yaml": "^2.8.2", + "zod": "^4.3.5" + }, + "devDependencies": { + "@types/diff": "^7.0.2", + "@types/ms": "^2.1.0", + "@types/ndjson": "^2.0.4", + "@types/node": "^24.3.0", + "ms": "^2.1.3" + } + }, + "packages/git-tool": { + "name": "@oh-my-pi/pi-git-tool", + "version": "3.21.0", + "devDependencies": { + "@types/node": "^24.3.0", + "vitest": "^3.2.4" + } + }, + "packages/tui": { + "name": "@oh-my-pi/pi-tui", + "version": "3.21.0", + "dependencies": { + "@types/mime-types": "^2.1.4", + "chalk": "^5.5.0", + "get-east-asian-width": "^1.3.0", + "marked": "^15.0.12", + "mime-types": "^3.0.1" + }, + "devDependencies": { + "@xterm/headless": "^5.5.0", + "@xterm/xterm": "^5.5.0" + } + } + }, + "packages": { + "@anthropic-ai/sdk": [ + "@anthropic-ai/sdk@0.71.2", + "", + { + "dependencies": { "json-schema-to-ts": "^3.1.1" }, + "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" }, + "optionalPeers": ["zod"], + "bin": { "anthropic-ai-sdk": "bin/cli" } + }, + "sha512-TGNDEUuEstk/DKu0/TflXAEt+p+p/WhTlFzEnoosvbaDU2LTjm42igSdlL0VijrKpWejtOKxX0b8A7uc+XiSAQ==" + ], + + "@babel/runtime": [ + "@babel/runtime@7.28.4", + "", + {}, + "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==" + ], + + "@biomejs/biome": [ + "@biomejs/biome@2.3.11", + "", + { + "optionalDependencies": { + "@biomejs/cli-darwin-arm64": "2.3.11", + "@biomejs/cli-darwin-x64": "2.3.11", + "@biomejs/cli-linux-arm64": "2.3.11", + "@biomejs/cli-linux-arm64-musl": "2.3.11", + "@biomejs/cli-linux-x64": "2.3.11", + "@biomejs/cli-linux-x64-musl": "2.3.11", + "@biomejs/cli-win32-arm64": "2.3.11", + "@biomejs/cli-win32-x64": "2.3.11" + }, + "bin": { "biome": "bin/biome" } + }, + "sha512-/uWSUd1MHX2fjqNLHNL6zLYWBbrJeG412/8H7ESuK8ewoRoMPUgHDebqKrPTx/5n6f17Xzqc9hdg3MEqA5hXnQ==" + ], + + "@biomejs/cli-darwin-arm64": [ + "@biomejs/cli-darwin-arm64@2.3.11", + "", + { "os": "darwin", "cpu": "arm64" }, + "sha512-M6xUjtCVnNGFfK7HMNKa593nb7fwNm43fq1Mt71kpLpb+4mE7odO8W/oWVDyBVO4ackhresy1ZYO7OJcVo/B7w==" + ], + + "@biomejs/cli-darwin-x64": [ + "@biomejs/cli-darwin-x64@2.3.11", + "", + { "os": "darwin", "cpu": "x64" }, + "sha512-Vae7+V6t/Avr8tVbFNjnFSTKZogZHFYl7MMH62P/J1kZtr0tyRQ9Fe0onjqjS2Ek9lmNLmZc/VR5uSekh+p1fg==" + ], + + "@biomejs/cli-linux-arm64": [ + "@biomejs/cli-linux-arm64@2.3.11", + "", + { "os": "linux", "cpu": "arm64" }, + "sha512-hhPw2V3/EpHKsileVOFynuWiKRgFEV48cLe0eA+G2wO4SzlwEhLEB9LhlSrVeu2mtSn205W283LkX7Fh48CaxA==" + ], + + "@biomejs/cli-linux-arm64-musl": [ + "@biomejs/cli-linux-arm64-musl@2.3.11", + "", + { "os": "linux", "cpu": "arm64" }, + "sha512-B9DszIHkuKtOH2IFeeVkQmSMVUjss9KtHaNXquYYWCjH8IstNgXgx5B0aSBQNr6mn4RcKKRQZXn9Zu1rM3O0/A==" + ], + + "@biomejs/cli-linux-x64": [ + "@biomejs/cli-linux-x64@2.3.11", + "", + { "os": "linux", "cpu": "x64" }, + "sha512-wwAkWD1MR95u+J4LkWP74/vGz+tRrIQvr8kfMMJY8KOQ8+HMVleREOcPYsQX82S7uueco60L58Wc6M1I9WA9Dw==" + ], + + "@biomejs/cli-linux-x64-musl": [ + "@biomejs/cli-linux-x64-musl@2.3.11", + "", + { "os": "linux", "cpu": "x64" }, + "sha512-QTfHZQh62SDFdYc2nfmZFuTm5yYb4eO1zwfB+90YxUumRCR171tS1GoTX5OD0wrv4UsziMPmrePMtkTnNyYG3g==" + ], + + "@biomejs/cli-win32-arm64": [ + "@biomejs/cli-win32-arm64@2.3.11", + "", + { "os": "win32", "cpu": "arm64" }, + "sha512-o7lYc9n+CfRbHvkjPhm8s9FgbKdYZu5HCcGVMItLjz93EhgJ8AM44W+QckDqLA9MKDNFrR8nPbO4b73VC5kGGQ==" + ], + + "@biomejs/cli-win32-x64": [ + "@biomejs/cli-win32-x64@2.3.11", + "", + { "os": "win32", "cpu": "x64" }, + "sha512-pHEFgq7dUEsKnqG9mx9bXihxGI49X+ar+UBrEIj3Wqj3UCZp1rNgV+OoyjFgcXsjCWpuEAF4VJdkZr3TrWdCbQ==" + ], + + "@borewit/text-codec": [ + "@borewit/text-codec@0.2.1", + "", + {}, + "sha512-k7vvKPbf7J2fZ5klGRD9AeKfUvojuZIQ3BT5u7Jfv+puwXkUBUT5PVyMDfJZpy30CBDXGMgw7fguK/lpOMBvgw==" + ], + + "@colors/colors": [ + "@colors/colors@1.6.0", + "", + {}, + "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==" + ], + + "@dabh/diagnostics": [ + "@dabh/diagnostics@2.0.8", + "", + { "dependencies": { "@so-ric/colorspace": "^1.1.6", "enabled": "2.0.x", "kuler": "^2.0.0" } }, + "sha512-R4MSXTVnuMzGD7bzHdW2ZhhdPC/igELENcq5IjEverBvq5hn1SXCWcsi6eSsdWP0/Ur+SItRRjAktmdoX/8R/Q==" + ], + + "@emnapi/runtime": [ + "@emnapi/runtime@1.8.1", + "", + { "dependencies": { "tslib": "^2.4.0" } }, + "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==" + ], + + "@esbuild/aix-ppc64": [ + "@esbuild/aix-ppc64@0.27.2", + "", + { "os": "aix", "cpu": "ppc64" }, + "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==" + ], + + "@esbuild/android-arm": [ + "@esbuild/android-arm@0.27.2", + "", + { "os": "android", "cpu": "arm" }, + "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==" + ], + + "@esbuild/android-arm64": [ + "@esbuild/android-arm64@0.27.2", + "", + { "os": "android", "cpu": "arm64" }, + "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==" + ], + + "@esbuild/android-x64": [ + "@esbuild/android-x64@0.27.2", + "", + { "os": "android", "cpu": "x64" }, + "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==" + ], + + "@esbuild/darwin-arm64": [ + "@esbuild/darwin-arm64@0.27.2", + "", + { "os": "darwin", "cpu": "arm64" }, + "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==" + ], + + "@esbuild/darwin-x64": [ + "@esbuild/darwin-x64@0.27.2", + "", + { "os": "darwin", "cpu": "x64" }, + "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==" + ], + + "@esbuild/freebsd-arm64": [ + "@esbuild/freebsd-arm64@0.27.2", + "", + { "os": "freebsd", "cpu": "arm64" }, + "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==" + ], + + "@esbuild/freebsd-x64": [ + "@esbuild/freebsd-x64@0.27.2", + "", + { "os": "freebsd", "cpu": "x64" }, + "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==" + ], + + "@esbuild/linux-arm": [ + "@esbuild/linux-arm@0.27.2", + "", + { "os": "linux", "cpu": "arm" }, + "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==" + ], + + "@esbuild/linux-arm64": [ + "@esbuild/linux-arm64@0.27.2", + "", + { "os": "linux", "cpu": "arm64" }, + "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==" + ], + + "@esbuild/linux-ia32": [ + "@esbuild/linux-ia32@0.27.2", + "", + { "os": "linux", "cpu": "ia32" }, + "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==" + ], + + "@esbuild/linux-loong64": [ + "@esbuild/linux-loong64@0.27.2", + "", + { "os": "linux", "cpu": "none" }, + "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==" + ], + + "@esbuild/linux-mips64el": [ + "@esbuild/linux-mips64el@0.27.2", + "", + { "os": "linux", "cpu": "none" }, + "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==" + ], + + "@esbuild/linux-ppc64": [ + "@esbuild/linux-ppc64@0.27.2", + "", + { "os": "linux", "cpu": "ppc64" }, + "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==" + ], + + "@esbuild/linux-riscv64": [ + "@esbuild/linux-riscv64@0.27.2", + "", + { "os": "linux", "cpu": "none" }, + "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==" + ], + + "@esbuild/linux-s390x": [ + "@esbuild/linux-s390x@0.27.2", + "", + { "os": "linux", "cpu": "s390x" }, + "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==" + ], + + "@esbuild/linux-x64": [ + "@esbuild/linux-x64@0.27.2", + "", + { "os": "linux", "cpu": "x64" }, + "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==" + ], + + "@esbuild/netbsd-arm64": [ + "@esbuild/netbsd-arm64@0.27.2", + "", + { "os": "none", "cpu": "arm64" }, + "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==" + ], + + "@esbuild/netbsd-x64": [ + "@esbuild/netbsd-x64@0.27.2", + "", + { "os": "none", "cpu": "x64" }, + "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==" + ], + + "@esbuild/openbsd-arm64": [ + "@esbuild/openbsd-arm64@0.27.2", + "", + { "os": "openbsd", "cpu": "arm64" }, + "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==" + ], + + "@esbuild/openbsd-x64": [ + "@esbuild/openbsd-x64@0.27.2", + "", + { "os": "openbsd", "cpu": "x64" }, + "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==" + ], + + "@esbuild/openharmony-arm64": [ + "@esbuild/openharmony-arm64@0.27.2", + "", + { "os": "none", "cpu": "arm64" }, + "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==" + ], + + "@esbuild/sunos-x64": [ + "@esbuild/sunos-x64@0.27.2", + "", + { "os": "sunos", "cpu": "x64" }, + "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==" + ], + + "@esbuild/win32-arm64": [ + "@esbuild/win32-arm64@0.27.2", + "", + { "os": "win32", "cpu": "arm64" }, + "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==" + ], + + "@esbuild/win32-ia32": [ + "@esbuild/win32-ia32@0.27.2", + "", + { "os": "win32", "cpu": "ia32" }, + "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==" + ], + + "@esbuild/win32-x64": [ + "@esbuild/win32-x64@0.27.2", + "", + { "os": "win32", "cpu": "x64" }, + "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==" + ], + + "@google/genai": [ + "@google/genai@1.34.0", + "", + { + "dependencies": { "google-auth-library": "^10.3.0", "ws": "^8.18.0" }, + "peerDependencies": { "@modelcontextprotocol/sdk": "^1.24.0" }, + "optionalPeers": ["@modelcontextprotocol/sdk"] + }, + "sha512-vu53UMPvjmb7PGzlYu6Tzxso8Dfhn+a7eQFaS2uNemVtDZKwzSpJ5+ikqBbXplF7RGB1STcVDqCkPvquiwb2sw==" + ], + + "@hono/node-server": [ + "@hono/node-server@1.19.7", + "", + { "peerDependencies": { "hono": "^4" } }, + "sha512-vUcD0uauS7EU2caukW8z5lJKtoGMokxNbJtBiwHgpqxEXokaHCBkQUmCHhjFB1VUTWdqj25QoMkMKzgjq+uhrw==" + ], + + "@img/colour": [ + "@img/colour@1.0.0", + "", + {}, + "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==" + ], + + "@img/sharp-darwin-arm64": [ + "@img/sharp-darwin-arm64@0.34.5", + "", + { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.2.4" }, "os": "darwin", "cpu": "arm64" }, + "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==" + ], + + "@img/sharp-darwin-x64": [ + "@img/sharp-darwin-x64@0.34.5", + "", + { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.2.4" }, "os": "darwin", "cpu": "x64" }, + "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==" + ], + + "@img/sharp-libvips-darwin-arm64": [ + "@img/sharp-libvips-darwin-arm64@1.2.4", + "", + { "os": "darwin", "cpu": "arm64" }, + "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==" + ], + + "@img/sharp-libvips-darwin-x64": [ + "@img/sharp-libvips-darwin-x64@1.2.4", + "", + { "os": "darwin", "cpu": "x64" }, + "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==" + ], + + "@img/sharp-libvips-linux-arm": [ + "@img/sharp-libvips-linux-arm@1.2.4", + "", + { "os": "linux", "cpu": "arm" }, + "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==" + ], + + "@img/sharp-libvips-linux-arm64": [ + "@img/sharp-libvips-linux-arm64@1.2.4", + "", + { "os": "linux", "cpu": "arm64" }, + "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==" + ], + + "@img/sharp-libvips-linux-ppc64": [ + "@img/sharp-libvips-linux-ppc64@1.2.4", + "", + { "os": "linux", "cpu": "ppc64" }, + "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==" + ], + + "@img/sharp-libvips-linux-riscv64": [ + "@img/sharp-libvips-linux-riscv64@1.2.4", + "", + { "os": "linux", "cpu": "none" }, + "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==" + ], + + "@img/sharp-libvips-linux-s390x": [ + "@img/sharp-libvips-linux-s390x@1.2.4", + "", + { "os": "linux", "cpu": "s390x" }, + "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==" + ], + + "@img/sharp-libvips-linux-x64": [ + "@img/sharp-libvips-linux-x64@1.2.4", + "", + { "os": "linux", "cpu": "x64" }, + "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==" + ], + + "@img/sharp-libvips-linuxmusl-arm64": [ + "@img/sharp-libvips-linuxmusl-arm64@1.2.4", + "", + { "os": "linux", "cpu": "arm64" }, + "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==" + ], + + "@img/sharp-libvips-linuxmusl-x64": [ + "@img/sharp-libvips-linuxmusl-x64@1.2.4", + "", + { "os": "linux", "cpu": "x64" }, + "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==" + ], + + "@img/sharp-linux-arm": [ + "@img/sharp-linux-arm@0.34.5", + "", + { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.2.4" }, "os": "linux", "cpu": "arm" }, + "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==" + ], + + "@img/sharp-linux-arm64": [ + "@img/sharp-linux-arm64@0.34.5", + "", + { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.2.4" }, "os": "linux", "cpu": "arm64" }, + "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==" + ], + + "@img/sharp-linux-ppc64": [ + "@img/sharp-linux-ppc64@0.34.5", + "", + { "optionalDependencies": { "@img/sharp-libvips-linux-ppc64": "1.2.4" }, "os": "linux", "cpu": "ppc64" }, + "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==" + ], + + "@img/sharp-linux-riscv64": [ + "@img/sharp-linux-riscv64@0.34.5", + "", + { "optionalDependencies": { "@img/sharp-libvips-linux-riscv64": "1.2.4" }, "os": "linux", "cpu": "none" }, + "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==" + ], + + "@img/sharp-linux-s390x": [ + "@img/sharp-linux-s390x@0.34.5", + "", + { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.2.4" }, "os": "linux", "cpu": "s390x" }, + "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==" + ], + + "@img/sharp-linux-x64": [ + "@img/sharp-linux-x64@0.34.5", + "", + { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.2.4" }, "os": "linux", "cpu": "x64" }, + "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==" + ], + + "@img/sharp-linuxmusl-arm64": [ + "@img/sharp-linuxmusl-arm64@0.34.5", + "", + { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" }, "os": "linux", "cpu": "arm64" }, + "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==" + ], + + "@img/sharp-linuxmusl-x64": [ + "@img/sharp-linuxmusl-x64@0.34.5", + "", + { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.2.4" }, "os": "linux", "cpu": "x64" }, + "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==" + ], + + "@img/sharp-wasm32": [ + "@img/sharp-wasm32@0.34.5", + "", + { "dependencies": { "@emnapi/runtime": "^1.7.0" }, "cpu": "none" }, + "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==" + ], + + "@img/sharp-win32-arm64": [ + "@img/sharp-win32-arm64@0.34.5", + "", + { "os": "win32", "cpu": "arm64" }, + "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==" + ], + + "@img/sharp-win32-ia32": [ + "@img/sharp-win32-ia32@0.34.5", + "", + { "os": "win32", "cpu": "ia32" }, + "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==" + ], + + "@img/sharp-win32-x64": [ + "@img/sharp-win32-x64@0.34.5", + "", + { "os": "win32", "cpu": "x64" }, + "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==" + ], + + "@isaacs/balanced-match": [ + "@isaacs/balanced-match@4.0.1", + "", + {}, + "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==" + ], + + "@isaacs/brace-expansion": [ + "@isaacs/brace-expansion@5.0.0", + "", + { "dependencies": { "@isaacs/balanced-match": "^4.0.1" } }, + "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==" + ], + + "@isaacs/cliui": [ + "@isaacs/cliui@8.0.2", + "", + { + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + } + }, + "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==" + ], + + "@jridgewell/sourcemap-codec": [ + "@jridgewell/sourcemap-codec@1.5.5", + "", + {}, + "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==" + ], + + "@mariozechner/pi-ai": [ + "@mariozechner/pi-ai@0.37.5", + "", + { + "dependencies": { + "@anthropic-ai/sdk": "0.71.2", + "@google/genai": "1.34.0", + "@mistralai/mistralai": "1.10.0", + "@sinclair/typebox": "^0.34.41", + "ajv": "^8.17.1", + "ajv-formats": "^3.0.1", + "chalk": "^5.6.2", + "openai": "6.10.0", + "partial-json": "^0.1.7", + "zod-to-json-schema": "^3.24.6" + }, + "bin": { "pi-ai": "dist/cli.js" } + }, + "sha512-LhUtOih1UnEZjWR86geVX6PkmoGwz3dpKEQFSHb1UvCA3M9Z0xVwR8OmRFTLtfCY7mMYT/mrzH5vWi2qsTmE+Q==" + ], + + "@mistralai/mistralai": [ + "@mistralai/mistralai@1.10.0", + "", + { "dependencies": { "zod": "^3.20.0", "zod-to-json-schema": "^3.24.1" } }, + "sha512-tdIgWs4Le8vpvPiUEWne6tK0qbVc+jMenujnvTqOjogrJUsCSQhus0tHTU1avDDh5//Rq2dFgP9mWRAdIEoBqg==" + ], + + "@modelcontextprotocol/sdk": [ + "@modelcontextprotocol/sdk@1.25.1", + "", + { + "dependencies": { + "@hono/node-server": "^1.19.7", + "ajv": "^8.17.1", + "ajv-formats": "^3.0.1", + "content-type": "^1.0.5", + "cors": "^2.8.5", + "cross-spawn": "^7.0.5", + "eventsource": "^3.0.2", + "eventsource-parser": "^3.0.0", + "express": "^5.0.1", + "express-rate-limit": "^7.5.0", + "jose": "^6.1.1", + "json-schema-typed": "^8.0.2", + "pkce-challenge": "^5.0.0", + "raw-body": "^3.0.0", + "zod": "^3.25 || ^4.0", + "zod-to-json-schema": "^3.25.0" + }, + "peerDependencies": { "@cfworker/json-schema": "^4.1.1" }, + "optionalPeers": ["@cfworker/json-schema"] + }, + "sha512-yO28oVFFC7EBoiKdAn+VqRm+plcfv4v0xp6osG/VsCB0NlPZWi87ajbCZZ8f/RvOFLEu7//rSRmuZZ7lMoe3gQ==" + ], + + "@oh-my-pi/pi-agent-core": ["@oh-my-pi/pi-agent-core@workspace:packages/agent"], + + "@oh-my-pi/pi-coding-agent": ["@oh-my-pi/pi-coding-agent@workspace:packages/coding-agent"], + + "@oh-my-pi/pi-git-tool": ["@oh-my-pi/pi-git-tool@workspace:packages/git-tool"], + + "@oh-my-pi/pi-tui": ["@oh-my-pi/pi-tui@workspace:packages/tui"], + + "@openai/agents": [ + "@openai/agents@0.3.7", + "", + { + "dependencies": { + "@openai/agents-core": "0.3.7", + "@openai/agents-openai": "0.3.7", + "@openai/agents-realtime": "0.3.7", + "debug": "^4.4.0", + "openai": "^6" + }, + "peerDependencies": { "zod": "^3.25.40 || ^4.0" } + }, + "sha512-9QKr6Gqb0yy0VLsyKSjxUoHHxN8j0fqtlZ1YTNmo2j5SqRcFG5LdSVyaQbkeJ3sWsCUugCXvEBEir7yAbxjSRw==" + ], + + "@openai/agents-core": [ + "@openai/agents-core@0.3.7", + "", + { + "dependencies": { "debug": "^4.4.0", "openai": "^6" }, + "optionalDependencies": { "@modelcontextprotocol/sdk": "^1.24.0" }, + "peerDependencies": { "zod": "^3.25.40 || ^4.0" }, + "optionalPeers": ["zod"] + }, + "sha512-Ya1sPc8UyHXxgQjNWN1sn/vFNP4CRdT/0SWd0tIc+kHgYuxrvRjwSfWNBqXc70XOZGS5bWWaRTqJBMwQt6AlYg==" + ], + + "@openai/agents-openai": [ + "@openai/agents-openai@0.3.7", + "", + { + "dependencies": { "@openai/agents-core": "0.3.7", "debug": "^4.4.0", "openai": "^6" }, + "peerDependencies": { "zod": "^3.25.40 || ^4.0" } + }, + "sha512-xjFNFeKDt3TkAWfoXhvUG3sdBQJ/R3FWd/s3Dv1rt1fdcFCaS1BUKkXX1fu79oo24H5DV8zZJfuUu6Bgi0ZAHw==" + ], + + "@openai/agents-realtime": [ + "@openai/agents-realtime@0.3.7", + "", + { + "dependencies": { "@openai/agents-core": "0.3.7", "@types/ws": "^8.18.1", "debug": "^4.4.0", "ws": "^8.18.1" }, + "peerDependencies": { "zod": "^3.25.40 || ^4.0" } + }, + "sha512-8zKu33Q8bmXCkReR7UOWQa1rNbIaLwqI4QgjMD20ALaEkuRglRZeaJyfVTIhTcw9COIF35uyiq+GugxFUvPE5A==" + ], + + "@pkgjs/parseargs": [ + "@pkgjs/parseargs@0.11.0", + "", + {}, + "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==" + ], + + "@rollup/rollup-android-arm-eabi": [ + "@rollup/rollup-android-arm-eabi@4.55.1", + "", + { "os": "android", "cpu": "arm" }, + "sha512-9R0DM/ykwfGIlNu6+2U09ga0WXeZ9MRC2Ter8jnz8415VbuIykVuc6bhdrbORFZANDmTDvq26mJrEVTl8TdnDg==" + ], + + "@rollup/rollup-android-arm64": [ + "@rollup/rollup-android-arm64@4.55.1", + "", + { "os": "android", "cpu": "arm64" }, + "sha512-eFZCb1YUqhTysgW3sj/55du5cG57S7UTNtdMjCW7LwVcj3dTTcowCsC8p7uBdzKsZYa8J7IDE8lhMI+HX1vQvg==" + ], + + "@rollup/rollup-darwin-arm64": [ + "@rollup/rollup-darwin-arm64@4.55.1", + "", + { "os": "darwin", "cpu": "arm64" }, + "sha512-p3grE2PHcQm2e8PSGZdzIhCKbMCw/xi9XvMPErPhwO17vxtvCN5FEA2mSLgmKlCjHGMQTP6phuQTYWUnKewwGg==" + ], + + "@rollup/rollup-darwin-x64": [ + "@rollup/rollup-darwin-x64@4.55.1", + "", + { "os": "darwin", "cpu": "x64" }, + "sha512-rDUjG25C9qoTm+e02Esi+aqTKSBYwVTaoS1wxcN47/Luqef57Vgp96xNANwt5npq9GDxsH7kXxNkJVEsWEOEaQ==" + ], + + "@rollup/rollup-freebsd-arm64": [ + "@rollup/rollup-freebsd-arm64@4.55.1", + "", + { "os": "freebsd", "cpu": "arm64" }, + "sha512-+JiU7Jbp5cdxekIgdte0jfcu5oqw4GCKr6i3PJTlXTCU5H5Fvtkpbs4XJHRmWNXF+hKmn4v7ogI5OQPaupJgOg==" + ], + + "@rollup/rollup-freebsd-x64": [ + "@rollup/rollup-freebsd-x64@4.55.1", + "", + { "os": "freebsd", "cpu": "x64" }, + "sha512-V5xC1tOVWtLLmr3YUk2f6EJK4qksksOYiz/TCsFHu/R+woubcLWdC9nZQmwjOAbmExBIVKsm1/wKmEy4z4u4Bw==" + ], + + "@rollup/rollup-linux-arm-gnueabihf": [ + "@rollup/rollup-linux-arm-gnueabihf@4.55.1", + "", + { "os": "linux", "cpu": "arm" }, + "sha512-Rn3n+FUk2J5VWx+ywrG/HGPTD9jXNbicRtTM11e/uorplArnXZYsVifnPPqNNP5BsO3roI4n8332ukpY/zN7rQ==" + ], + + "@rollup/rollup-linux-arm-musleabihf": [ + "@rollup/rollup-linux-arm-musleabihf@4.55.1", + "", + { "os": "linux", "cpu": "arm" }, + "sha512-grPNWydeKtc1aEdrJDWk4opD7nFtQbMmV7769hiAaYyUKCT1faPRm2av8CX1YJsZ4TLAZcg9gTR1KvEzoLjXkg==" + ], + + "@rollup/rollup-linux-arm64-gnu": [ + "@rollup/rollup-linux-arm64-gnu@4.55.1", + "", + { "os": "linux", "cpu": "arm64" }, + "sha512-a59mwd1k6x8tXKcUxSyISiquLwB5pX+fJW9TkWU46lCqD/GRDe9uDN31jrMmVP3feI3mhAdvcCClhV8V5MhJFQ==" + ], + + "@rollup/rollup-linux-arm64-musl": [ + "@rollup/rollup-linux-arm64-musl@4.55.1", + "", + { "os": "linux", "cpu": "arm64" }, + "sha512-puS1MEgWX5GsHSoiAsF0TYrpomdvkaXm0CofIMG5uVkP6IBV+ZO9xhC5YEN49nsgYo1DuuMquF9+7EDBVYu4uA==" + ], + + "@rollup/rollup-linux-loong64-gnu": [ + "@rollup/rollup-linux-loong64-gnu@4.55.1", + "", + { "os": "linux", "cpu": "none" }, + "sha512-r3Wv40in+lTsULSb6nnoudVbARdOwb2u5fpeoOAZjFLznp6tDU8kd+GTHmJoqZ9lt6/Sys33KdIHUaQihFcu7g==" + ], + + "@rollup/rollup-linux-loong64-musl": [ + "@rollup/rollup-linux-loong64-musl@4.55.1", + "", + { "os": "linux", "cpu": "none" }, + "sha512-MR8c0+UxAlB22Fq4R+aQSPBayvYa3+9DrwG/i1TKQXFYEaoW3B5b/rkSRIypcZDdWjWnpcvxbNaAJDcSbJU3Lw==" + ], + + "@rollup/rollup-linux-ppc64-gnu": [ + "@rollup/rollup-linux-ppc64-gnu@4.55.1", + "", + { "os": "linux", "cpu": "ppc64" }, + "sha512-3KhoECe1BRlSYpMTeVrD4sh2Pw2xgt4jzNSZIIPLFEsnQn9gAnZagW9+VqDqAHgm1Xc77LzJOo2LdigS5qZ+gw==" + ], + + "@rollup/rollup-linux-ppc64-musl": [ + "@rollup/rollup-linux-ppc64-musl@4.55.1", + "", + { "os": "linux", "cpu": "ppc64" }, + "sha512-ziR1OuZx0vdYZZ30vueNZTg73alF59DicYrPViG0NEgDVN8/Jl87zkAPu4u6VjZST2llgEUjaiNl9JM6HH1Vdw==" + ], + + "@rollup/rollup-linux-riscv64-gnu": [ + "@rollup/rollup-linux-riscv64-gnu@4.55.1", + "", + { "os": "linux", "cpu": "none" }, + "sha512-uW0Y12ih2XJRERZ4jAfKamTyIHVMPQnTZcQjme2HMVDAHY4amf5u414OqNYC+x+LzRdRcnIG1YodLrrtA8xsxw==" + ], + + "@rollup/rollup-linux-riscv64-musl": [ + "@rollup/rollup-linux-riscv64-musl@4.55.1", + "", + { "os": "linux", "cpu": "none" }, + "sha512-u9yZ0jUkOED1BFrqu3BwMQoixvGHGZ+JhJNkNKY/hyoEgOwlqKb62qu+7UjbPSHYjiVy8kKJHvXKv5coH4wDeg==" + ], + + "@rollup/rollup-linux-s390x-gnu": [ + "@rollup/rollup-linux-s390x-gnu@4.55.1", + "", + { "os": "linux", "cpu": "s390x" }, + "sha512-/0PenBCmqM4ZUd0190j7J0UsQ/1nsi735iPRakO8iPciE7BQ495Y6msPzaOmvx0/pn+eJVVlZrNrSh4WSYLxNg==" + ], + + "@rollup/rollup-linux-x64-gnu": [ + "@rollup/rollup-linux-x64-gnu@4.55.1", + "", + { "os": "linux", "cpu": "x64" }, + "sha512-a8G4wiQxQG2BAvo+gU6XrReRRqj+pLS2NGXKm8io19goR+K8lw269eTrPkSdDTALwMmJp4th2Uh0D8J9bEV1vg==" + ], + + "@rollup/rollup-linux-x64-musl": [ + "@rollup/rollup-linux-x64-musl@4.55.1", + "", + { "os": "linux", "cpu": "x64" }, + "sha512-bD+zjpFrMpP/hqkfEcnjXWHMw5BIghGisOKPj+2NaNDuVT+8Ds4mPf3XcPHuat1tz89WRL+1wbcxKY3WSbiT7w==" + ], + + "@rollup/rollup-openbsd-x64": [ + "@rollup/rollup-openbsd-x64@4.55.1", + "", + { "os": "openbsd", "cpu": "x64" }, + "sha512-eLXw0dOiqE4QmvikfQ6yjgkg/xDM+MdU9YJuP4ySTibXU0oAvnEWXt7UDJmD4UkYialMfOGFPJnIHSe/kdzPxg==" + ], + + "@rollup/rollup-openharmony-arm64": [ + "@rollup/rollup-openharmony-arm64@4.55.1", + "", + { "os": "none", "cpu": "arm64" }, + "sha512-xzm44KgEP11te3S2HCSyYf5zIzWmx3n8HDCc7EE59+lTcswEWNpvMLfd9uJvVX8LCg9QWG67Xt75AuHn4vgsXw==" + ], + + "@rollup/rollup-win32-arm64-msvc": [ + "@rollup/rollup-win32-arm64-msvc@4.55.1", + "", + { "os": "win32", "cpu": "arm64" }, + "sha512-yR6Bl3tMC/gBok5cz/Qi0xYnVbIxGx5Fcf/ca0eB6/6JwOY+SRUcJfI0OpeTpPls7f194as62thCt/2BjxYN8g==" + ], + + "@rollup/rollup-win32-ia32-msvc": [ + "@rollup/rollup-win32-ia32-msvc@4.55.1", + "", + { "os": "win32", "cpu": "ia32" }, + "sha512-3fZBidchE0eY0oFZBnekYCfg+5wAB0mbpCBuofh5mZuzIU/4jIVkbESmd2dOsFNS78b53CYv3OAtwqkZZmU5nA==" + ], + + "@rollup/rollup-win32-x64-gnu": [ + "@rollup/rollup-win32-x64-gnu@4.55.1", + "", + { "os": "win32", "cpu": "x64" }, + "sha512-xGGY5pXj69IxKb4yv/POoocPy/qmEGhimy/FoTpTSVju3FYXUQQMFCaZZXJVidsmGxRioZAwpThl/4zX41gRKg==" + ], + + "@rollup/rollup-win32-x64-msvc": [ + "@rollup/rollup-win32-x64-msvc@4.55.1", + "", + { "os": "win32", "cpu": "x64" }, + "sha512-SPEpaL6DX4rmcXtnhdrQYgzQ5W2uW3SCJch88lB2zImhJRhIIK44fkUrgIV/Q8yUNfw5oyZ5vkeQsZLhCb06lw==" + ], + + "@sinclair/typebox": [ + "@sinclair/typebox@0.34.47", + "", + {}, + "sha512-ZGIBQ+XDvO5JQku9wmwtabcVTHJsgSWAHYtVuM9pBNNR5E88v6Jcj/llpmsjivig5X8A8HHOb4/mbEKPS5EvAw==" + ], + + "@so-ric/colorspace": [ + "@so-ric/colorspace@1.1.6", + "", + { "dependencies": { "color": "^5.0.2", "text-hex": "1.0.x" } }, + "sha512-/KiKkpHNOBgkFJwu9sh48LkHSMYGyuTcSFK/qMBdnOAlrRJzRSXAOFB5qwzaVQuDl8wAvHVMkaASQDReTahxuw==" + ], + + "@tokenizer/inflate": [ + "@tokenizer/inflate@0.4.1", + "", + { "dependencies": { "debug": "^4.4.3", "token-types": "^6.1.1" } }, + "sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA==" + ], + + "@tokenizer/token": [ + "@tokenizer/token@0.3.0", + "", + {}, + "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==" + ], + + "@types/bun": [ + "@types/bun@1.3.5", + "", + { "dependencies": { "bun-types": "1.3.5" } }, + "sha512-RnygCqNrd3srIPEWBd5LFeUYG7plCoH2Yw9WaZGyNmdTEei+gWaHqydbaIRkIkcbXwhBT94q78QljxN0Sk838w==" + ], + + "@types/chai": [ + "@types/chai@5.2.3", + "", + { "dependencies": { "@types/deep-eql": "*", "assertion-error": "^2.0.1" } }, + "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==" + ], + + "@types/deep-eql": [ + "@types/deep-eql@4.0.2", + "", + {}, + "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==" + ], + + "@types/diff": [ + "@types/diff@7.0.2", + "", + {}, + "sha512-JSWRMozjFKsGlEjiiKajUjIJVKuKdE3oVy2DNtK+fUo8q82nhFZ2CPQwicAIkXrofahDXrWJ7mjelvZphMS98Q==" + ], + + "@types/estree": [ + "@types/estree@1.0.8", + "", + {}, + "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==" + ], + + "@types/mime-types": [ + "@types/mime-types@2.1.4", + "", + {}, + "sha512-lfU4b34HOri+kAY5UheuFMWPDOI+OPceBSHZKp69gEyTL/mmJ4cnU6Y/rlme3UL3GyOn6Y42hyIEw0/q8sWx5w==" + ], + + "@types/ms": [ + "@types/ms@2.1.0", + "", + {}, + "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==" + ], + + "@types/ndjson": [ + "@types/ndjson@2.0.4", + "", + { "dependencies": { "@types/node": "*", "@types/through": "*" } }, + "sha512-ajAl7AjhFstF6waORYNSS49GL5iBKisqJlgvXuprXFKCX9fto4ordlNU3+XMgkMddgeR0WoQQBmKUk0v0dJ4pw==" + ], + + "@types/node": [ + "@types/node@22.19.3", + "", + { "dependencies": { "undici-types": "~6.21.0" } }, + "sha512-1N9SBnWYOJTrNZCdh/yJE+t910Y128BoyY+zBLWhL3r0TYzlTmFdXrPwHL9DyFZmlEXNQQolTZh3KHV31QDhyA==" + ], + + "@types/through": [ + "@types/through@0.0.33", + "", + { "dependencies": { "@types/node": "*" } }, + "sha512-HsJ+z3QuETzP3cswwtzt2vEIiHBk/dCcHGhbmG5X3ecnwFD/lPrMpliGXxSCg03L9AhrdwA4Oz/qfspkDW+xGQ==" + ], + + "@types/triple-beam": [ + "@types/triple-beam@1.3.5", + "", + {}, + "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==" + ], + + "@types/ws": [ + "@types/ws@8.18.1", + "", + { "dependencies": { "@types/node": "*" } }, + "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==" + ], + + "@typescript/native-preview": [ + "@typescript/native-preview@7.0.0-dev.20260106.1", + "", + { + "optionalDependencies": { + "@typescript/native-preview-darwin-arm64": "7.0.0-dev.20260106.1", + "@typescript/native-preview-darwin-x64": "7.0.0-dev.20260106.1", + "@typescript/native-preview-linux-arm": "7.0.0-dev.20260106.1", + "@typescript/native-preview-linux-arm64": "7.0.0-dev.20260106.1", + "@typescript/native-preview-linux-x64": "7.0.0-dev.20260106.1", + "@typescript/native-preview-win32-arm64": "7.0.0-dev.20260106.1", + "@typescript/native-preview-win32-x64": "7.0.0-dev.20260106.1" + }, + "bin": { "tsgo": "bin/tsgo.js" } + }, + "sha512-EeH81rQsgLjewxuVOBN0MnQWAyf5YNeHRP3+Et6wJyr4d7HuA7zFwfNaEdfX1k366kgpKOR5K6dakorBhKZGng==" + ], + + "@typescript/native-preview-darwin-arm64": [ + "@typescript/native-preview-darwin-arm64@7.0.0-dev.20260106.1", + "", + { "os": "darwin", "cpu": "arm64" }, + "sha512-9n7HIVP3UMgWSK8Yi2H+23hrrEDNNfkW78mbkxfatGh/ghU4m2QuO8R6MdMdPsSmmKDvbWOtpLEuSZFKNzu7eQ==" + ], + + "@typescript/native-preview-darwin-x64": [ + "@typescript/native-preview-darwin-x64@7.0.0-dev.20260106.1", + "", + { "os": "darwin", "cpu": "x64" }, + "sha512-zHJ1KsgQTpBnG3RbI1kjH/fD8juc5DTlQ9gbmJi23OhhaOgNF+PkqC2vAAWLFqdH99tAMvmJf9BJncbB7LwxXA==" + ], + + "@typescript/native-preview-linux-arm": [ + "@typescript/native-preview-linux-arm@7.0.0-dev.20260106.1", + "", + { "os": "linux", "cpu": "arm" }, + "sha512-z7hdUMOOhdiVg1RmWyRyrIG3IIki4eJF3/TUtVVSTRwGq3t+j2JnLUUoK5VgX7EiqlN6wuJ94/FpWtyf+X4fkw==" + ], + + "@typescript/native-preview-linux-arm64": [ + "@typescript/native-preview-linux-arm64@7.0.0-dev.20260106.1", + "", + { "os": "linux", "cpu": "arm64" }, + "sha512-Mp7M7fgUsVW8MHadN58gjie1bzg06K1Id6vm2Aycnmk9rKgu8CxdaDayllr5giPo+iZLZOnw2FyGItrywd4fuA==" + ], + + "@typescript/native-preview-linux-x64": [ + "@typescript/native-preview-linux-x64@7.0.0-dev.20260106.1", + "", + { "os": "linux", "cpu": "x64" }, + "sha512-H+c7xgK0gItbntnPFvt9nVv+cjjjn0lTj2tIjBQcTbH92q9RgFkIfztgxrP5zD8MzJKDOyIw/iAUSsb57lyxjw==" + ], + + "@typescript/native-preview-win32-arm64": [ + "@typescript/native-preview-win32-arm64@7.0.0-dev.20260106.1", + "", + { "os": "win32", "cpu": "arm64" }, + "sha512-PS1FyYa+/sHQa5Va0yz21DxaBkGGwOYfjMyRSs6oHq01DzMnVIjtsdNAALP0+oqki8Adw0D2XtsdB5QapDbBJw==" + ], + + "@typescript/native-preview-win32-x64": [ + "@typescript/native-preview-win32-x64@7.0.0-dev.20260106.1", + "", + { "os": "win32", "cpu": "x64" }, + "sha512-AKVSTGcIE7d5KFtclhK3PVwUrsNnzziA7ZC/VDbMbvYCjLk7FE2GdNKaxQxLGHb53IUirgmltR5r4htn0WSM6A==" + ], + + "@vitest/expect": [ + "@vitest/expect@3.2.4", + "", + { + "dependencies": { + "@types/chai": "^5.2.2", + "@vitest/spy": "3.2.4", + "@vitest/utils": "3.2.4", + "chai": "^5.2.0", + "tinyrainbow": "^2.0.0" + } + }, + "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==" + ], + + "@vitest/mocker": [ + "@vitest/mocker@3.2.4", + "", + { + "dependencies": { "@vitest/spy": "3.2.4", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, + "peerDependencies": { "msw": "^2.4.9", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" }, + "optionalPeers": ["msw", "vite"] + }, + "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==" + ], + + "@vitest/pretty-format": [ + "@vitest/pretty-format@3.2.4", + "", + { "dependencies": { "tinyrainbow": "^2.0.0" } }, + "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==" + ], + + "@vitest/runner": [ + "@vitest/runner@3.2.4", + "", + { "dependencies": { "@vitest/utils": "3.2.4", "pathe": "^2.0.3", "strip-literal": "^3.0.0" } }, + "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==" + ], + + "@vitest/snapshot": [ + "@vitest/snapshot@3.2.4", + "", + { "dependencies": { "@vitest/pretty-format": "3.2.4", "magic-string": "^0.30.17", "pathe": "^2.0.3" } }, + "sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==" + ], + + "@vitest/spy": [ + "@vitest/spy@3.2.4", + "", + { "dependencies": { "tinyspy": "^4.0.3" } }, + "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==" + ], + + "@vitest/utils": [ + "@vitest/utils@3.2.4", + "", + { "dependencies": { "@vitest/pretty-format": "3.2.4", "loupe": "^3.1.4", "tinyrainbow": "^2.0.0" } }, + "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==" + ], + + "@xterm/headless": [ + "@xterm/headless@5.5.0", + "", + {}, + "sha512-5xXB7kdQlFBP82ViMJTwwEc3gKCLGKR/eoxQm4zge7GPBl86tCdI0IdPJjoKd8mUSFXz5V7i/25sfsEkP4j46g==" + ], + + "@xterm/xterm": [ + "@xterm/xterm@5.5.0", + "", + {}, + "sha512-hqJHYaQb5OptNunnyAnkHyM8aCjZ1MEIDTQu1iIbbTD/xops91NB5yq1ZK/dC2JDbVWtF23zUtl9JE2NqwT87A==" + ], + + "accepts": [ + "accepts@2.0.0", + "", + { "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" } }, + "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==" + ], + + "agent-base": [ + "agent-base@7.1.4", + "", + {}, + "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==" + ], + + "ajv": [ + "ajv@8.17.1", + "", + { + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + } + }, + "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==" + ], + + "ajv-formats": [ + "ajv-formats@3.0.1", + "", + { "dependencies": { "ajv": "^8.0.0" } }, + "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==" + ], + + "ansi-escapes": [ + "ansi-escapes@7.2.0", + "", + { "dependencies": { "environment": "^1.0.0" } }, + "sha512-g6LhBsl+GBPRWGWsBtutpzBYuIIdBkLEvad5C/va/74Db018+5TZiyA26cZJAr3Rft5lprVqOIPxf5Vid6tqAw==" + ], + + "ansi-regex": [ + "ansi-regex@6.2.2", + "", + {}, + "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==" + ], + + "ansi-styles": [ + "ansi-styles@4.3.0", + "", + { "dependencies": { "color-convert": "^2.0.1" } }, + "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==" + ], + + "any-promise": [ + "any-promise@1.3.0", + "", + {}, + "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" + ], + + "assertion-error": [ + "assertion-error@2.0.1", + "", + {}, + "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==" + ], + + "async": [ + "async@3.2.6", + "", + {}, + "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==" + ], + + "balanced-match": [ + "balanced-match@1.0.2", + "", + {}, + "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + ], + + "base64-js": [ + "base64-js@1.5.1", + "", + {}, + "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + ], + + "bignumber.js": [ + "bignumber.js@9.3.1", + "", + {}, + "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==" + ], + + "body-parser": [ + "body-parser@2.2.1", + "", + { + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.3", + "http-errors": "^2.0.0", + "iconv-lite": "^0.7.0", + "on-finished": "^2.4.1", + "qs": "^6.14.0", + "raw-body": "^3.0.1", + "type-is": "^2.0.1" + } + }, + "sha512-nfDwkulwiZYQIGwxdy0RUmowMhKcFVcYXUU7m4QlKYim1rUtg83xm2yjZ40QjDuc291AJjjeSc9b++AWHSgSHw==" + ], + + "boolbase": [ + "boolbase@1.0.0", + "", + {}, + "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + ], + + "brace-expansion": [ + "brace-expansion@2.0.2", + "", + { "dependencies": { "balanced-match": "^1.0.0" } }, + "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==" + ], + + "braces": [ + "braces@3.0.3", + "", + { "dependencies": { "fill-range": "^7.1.1" } }, + "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==" + ], + + "buffer-equal-constant-time": [ + "buffer-equal-constant-time@1.0.1", + "", + {}, + "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + ], + + "bun-types": [ + "bun-types@1.3.5", + "", + { "dependencies": { "@types/node": "*" } }, + "sha512-inmAYe2PFLs0SUbFOWSVD24sg1jFlMPxOjOSSCYqUgn4Hsc3rDc7dFvfVYjFPNHtov6kgUeulV4SxbuIV/stPw==" + ], + + "bytes": [ + "bytes@3.1.2", + "", + {}, + "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" + ], + + "cac": [ + "cac@6.7.14", + "", + {}, + "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==" + ], + + "call-bind-apply-helpers": [ + "call-bind-apply-helpers@1.0.2", + "", + { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, + "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==" + ], + + "call-bound": [ + "call-bound@1.0.4", + "", + { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, + "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==" + ], + + "chai": [ + "chai@5.3.3", + "", + { + "dependencies": { + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" + } + }, + "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==" + ], + + "chalk": [ + "chalk@5.6.2", + "", + {}, + "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==" + ], + + "check-error": [ + "check-error@2.1.3", + "", + {}, + "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==" + ], + + "cli-cursor": [ + "cli-cursor@5.0.0", + "", + { "dependencies": { "restore-cursor": "^5.0.0" } }, + "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==" + ], + + "cli-highlight": [ + "cli-highlight@2.1.11", + "", + { + "dependencies": { + "chalk": "^4.0.0", + "highlight.js": "^10.7.1", + "mz": "^2.4.0", + "parse5": "^5.1.1", + "parse5-htmlparser2-tree-adapter": "^6.0.0", + "yargs": "^16.0.0" + }, + "bin": { "highlight": "bin/highlight" } + }, + "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==" + ], + + "cli-truncate": [ + "cli-truncate@5.1.1", + "", + { "dependencies": { "slice-ansi": "^7.1.0", "string-width": "^8.0.0" } }, + "sha512-SroPvNHxUnk+vIW/dOSfNqdy1sPEFkrTk6TUtqLCnBlo3N7TNYYkzzN7uSD6+jVjrdO4+p8nH7JzH6cIvUem6A==" + ], + + "cliui": [ + "cliui@8.0.1", + "", + { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, + "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==" + ], + + "color": [ + "color@5.0.3", + "", + { "dependencies": { "color-convert": "^3.1.3", "color-string": "^2.1.3" } }, + "sha512-ezmVcLR3xAVp8kYOm4GS45ZLLgIE6SPAFoduLr6hTDajwb3KZ2F46gulK3XpcwRFb5KKGCSezCBAY4Dw4HsyXA==" + ], + + "color-convert": [ + "color-convert@2.0.1", + "", + { "dependencies": { "color-name": "~1.1.4" } }, + "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==" + ], + + "color-name": [ + "color-name@1.1.4", + "", + {}, + "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + ], + + "color-string": [ + "color-string@2.1.4", + "", + { "dependencies": { "color-name": "^2.0.0" } }, + "sha512-Bb6Cq8oq0IjDOe8wJmi4JeNn763Xs9cfrBcaylK1tPypWzyoy2G3l90v9k64kjphl/ZJjPIShFztenRomi8WTg==" + ], + + "colorette": [ + "colorette@2.0.20", + "", + {}, + "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" + ], + + "commander": [ + "commander@14.0.2", + "", + {}, + "sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==" + ], + + "concurrently": [ + "concurrently@9.2.1", + "", + { + "dependencies": { + "chalk": "4.1.2", + "rxjs": "7.8.2", + "shell-quote": "1.8.3", + "supports-color": "8.1.1", + "tree-kill": "1.2.2", + "yargs": "17.7.2" + }, + "bin": { "conc": "dist/bin/concurrently.js", "concurrently": "dist/bin/concurrently.js" } + }, + "sha512-fsfrO0MxV64Znoy8/l1vVIjjHa29SZyyqPgQBwhiDcaW8wJc2W3XWVOGx4M3oJBnv/zdUZIIp1gDeS98GzP8Ng==" + ], + + "content-disposition": [ + "content-disposition@1.0.1", + "", + {}, + "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==" + ], + + "content-type": [ + "content-type@1.0.5", + "", + {}, + "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" + ], + + "cookie": [ + "cookie@0.7.2", + "", + {}, + "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==" + ], + + "cookie-signature": [ + "cookie-signature@1.2.2", + "", + {}, + "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==" + ], + + "cors": [ + "cors@2.8.5", + "", + { "dependencies": { "object-assign": "^4", "vary": "^1" } }, + "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==" + ], + + "cross-spawn": [ + "cross-spawn@7.0.6", + "", + { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, + "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==" + ], + + "css-select": [ + "css-select@5.2.2", + "", + { + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + } + }, + "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==" + ], + + "css-what": [ + "css-what@6.2.2", + "", + {}, + "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==" + ], + + "data-uri-to-buffer": [ + "data-uri-to-buffer@4.0.1", + "", + {}, + "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==" + ], + + "debug": [ + "debug@4.4.3", + "", + { "dependencies": { "ms": "^2.1.3" } }, + "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==" + ], + + "deep-eql": [ + "deep-eql@5.0.2", + "", + {}, + "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==" + ], + + "depd": [ + "depd@2.0.0", + "", + {}, + "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + ], + + "detect-libc": [ + "detect-libc@2.1.2", + "", + {}, + "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==" + ], + + "diff": [ + "diff@8.0.2", + "", + {}, + "sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg==" + ], + + "dom-serializer": [ + "dom-serializer@2.0.0", + "", + { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", "entities": "^4.2.0" } }, + "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==" + ], + + "domelementtype": [ + "domelementtype@2.3.0", + "", + {}, + "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" + ], + + "domhandler": [ + "domhandler@5.0.3", + "", + { "dependencies": { "domelementtype": "^2.3.0" } }, + "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==" + ], + + "domutils": [ + "domutils@3.2.2", + "", + { "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3" } }, + "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==" + ], + + "dunder-proto": [ + "dunder-proto@1.0.1", + "", + { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, + "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==" + ], + + "eastasianwidth": [ + "eastasianwidth@0.2.0", + "", + {}, + "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + ], + + "ecdsa-sig-formatter": [ + "ecdsa-sig-formatter@1.0.11", + "", + { "dependencies": { "safe-buffer": "^5.0.1" } }, + "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==" + ], + + "ee-first": [ + "ee-first@1.1.1", + "", + {}, + "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + ], + + "emoji-regex": [ + "emoji-regex@8.0.0", + "", + {}, + "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + ], + + "enabled": [ + "enabled@2.0.0", + "", + {}, + "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" + ], + + "encodeurl": [ + "encodeurl@2.0.0", + "", + {}, + "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==" + ], + + "entities": [ + "entities@4.5.0", + "", + {}, + "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==" + ], + + "environment": [ + "environment@1.1.0", + "", + {}, + "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==" + ], + + "es-define-property": [ + "es-define-property@1.0.1", + "", + {}, + "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==" + ], + + "es-errors": [ + "es-errors@1.3.0", + "", + {}, + "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" + ], + + "es-module-lexer": [ + "es-module-lexer@1.7.0", + "", + {}, + "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==" + ], + + "es-object-atoms": [ + "es-object-atoms@1.1.1", + "", + { "dependencies": { "es-errors": "^1.3.0" } }, + "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==" + ], + + "esbuild": [ + "esbuild@0.27.2", + "", + { + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.2", + "@esbuild/android-arm": "0.27.2", + "@esbuild/android-arm64": "0.27.2", + "@esbuild/android-x64": "0.27.2", + "@esbuild/darwin-arm64": "0.27.2", + "@esbuild/darwin-x64": "0.27.2", + "@esbuild/freebsd-arm64": "0.27.2", + "@esbuild/freebsd-x64": "0.27.2", + "@esbuild/linux-arm": "0.27.2", + "@esbuild/linux-arm64": "0.27.2", + "@esbuild/linux-ia32": "0.27.2", + "@esbuild/linux-loong64": "0.27.2", + "@esbuild/linux-mips64el": "0.27.2", + "@esbuild/linux-ppc64": "0.27.2", + "@esbuild/linux-riscv64": "0.27.2", + "@esbuild/linux-s390x": "0.27.2", + "@esbuild/linux-x64": "0.27.2", + "@esbuild/netbsd-arm64": "0.27.2", + "@esbuild/netbsd-x64": "0.27.2", + "@esbuild/openbsd-arm64": "0.27.2", + "@esbuild/openbsd-x64": "0.27.2", + "@esbuild/openharmony-arm64": "0.27.2", + "@esbuild/sunos-x64": "0.27.2", + "@esbuild/win32-arm64": "0.27.2", + "@esbuild/win32-ia32": "0.27.2", + "@esbuild/win32-x64": "0.27.2" + }, + "bin": { "esbuild": "bin/esbuild" } + }, + "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==" + ], + + "escalade": [ + "escalade@3.2.0", + "", + {}, + "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==" + ], + + "escape-html": [ + "escape-html@1.0.3", + "", + {}, + "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + ], + + "estree-walker": [ + "estree-walker@3.0.3", + "", + { "dependencies": { "@types/estree": "^1.0.0" } }, + "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==" + ], + + "etag": [ + "etag@1.8.1", + "", + {}, + "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" + ], + + "eventemitter3": [ + "eventemitter3@5.0.1", + "", + {}, + "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" + ], + + "eventsource": [ + "eventsource@3.0.7", + "", + { "dependencies": { "eventsource-parser": "^3.0.1" } }, + "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==" + ], + + "eventsource-parser": [ + "eventsource-parser@3.0.6", + "", + {}, + "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==" + ], + + "expect-type": [ + "expect-type@1.3.0", + "", + {}, + "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==" + ], + + "express": [ + "express@5.2.1", + "", + { + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.1", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "depd": "^2.0.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + } + }, + "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==" + ], + + "express-rate-limit": [ + "express-rate-limit@7.5.1", + "", + { "peerDependencies": { "express": ">= 4.11" } }, + "sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw==" + ], + + "extend": [ + "extend@3.0.2", + "", + {}, + "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + ], + + "fast-deep-equal": [ + "fast-deep-equal@3.1.3", + "", + {}, + "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + ], + + "fast-uri": [ + "fast-uri@3.1.0", + "", + {}, + "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==" + ], + + "fdir": [ + "fdir@6.5.0", + "", + { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, + "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==" + ], + + "fecha": [ + "fecha@4.2.3", + "", + {}, + "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==" + ], + + "fetch-blob": [ + "fetch-blob@3.2.0", + "", + { "dependencies": { "node-domexception": "^1.0.0", "web-streams-polyfill": "^3.0.3" } }, + "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==" + ], + + "file-stream-rotator": [ + "file-stream-rotator@0.6.1", + "", + { "dependencies": { "moment": "^2.29.1" } }, + "sha512-u+dBid4PvZw17PmDeRcNOtCP9CCK/9lRN2w+r1xIS7yOL9JFrIBKTvrYsxT4P0pGtThYTn++QS5ChHaUov3+zQ==" + ], + + "file-type": [ + "file-type@21.3.0", + "", + { + "dependencies": { + "@tokenizer/inflate": "^0.4.1", + "strtok3": "^10.3.4", + "token-types": "^6.1.1", + "uint8array-extras": "^1.4.0" + } + }, + "sha512-8kPJMIGz1Yt/aPEwOsrR97ZyZaD1Iqm8PClb1nYFclUCkBi0Ma5IsYNQzvSFS9ib51lWyIw5mIT9rWzI/xjpzA==" + ], + + "fill-range": [ + "fill-range@7.1.1", + "", + { "dependencies": { "to-regex-range": "^5.0.1" } }, + "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==" + ], + + "finalhandler": [ + "finalhandler@2.1.1", + "", + { + "dependencies": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + } + }, + "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==" + ], + + "fn.name": [ + "fn.name@1.1.0", + "", + {}, + "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" + ], + + "foreground-child": [ + "foreground-child@3.3.1", + "", + { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, + "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==" + ], + + "formdata-polyfill": [ + "formdata-polyfill@4.0.10", + "", + { "dependencies": { "fetch-blob": "^3.1.2" } }, + "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==" + ], + + "forwarded": [ + "forwarded@0.2.0", + "", + {}, + "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" + ], + + "fresh": [ + "fresh@2.0.0", + "", + {}, + "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==" + ], + + "fsevents": [ + "fsevents@2.3.3", + "", + { "os": "darwin" }, + "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==" + ], + + "function-bind": [ + "function-bind@1.1.2", + "", + {}, + "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" + ], + + "gaxios": [ + "gaxios@7.1.3", + "", + { + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "node-fetch": "^3.3.2", + "rimraf": "^5.0.1" + } + }, + "sha512-YGGyuEdVIjqxkxVH1pUTMY/XtmmsApXrCVv5EU25iX6inEPbV+VakJfLealkBtJN69AQmh1eGOdCl9Sm1UP6XQ==" + ], + + "gcp-metadata": [ + "gcp-metadata@8.1.2", + "", + { "dependencies": { "gaxios": "^7.0.0", "google-logging-utils": "^1.0.0", "json-bigint": "^1.0.0" } }, + "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==" + ], + + "get-caller-file": [ + "get-caller-file@2.0.5", + "", + {}, + "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + ], + + "get-east-asian-width": [ + "get-east-asian-width@1.4.0", + "", + {}, + "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==" + ], + + "get-intrinsic": [ + "get-intrinsic@1.3.0", + "", + { + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + } + }, + "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==" + ], + + "get-proto": [ + "get-proto@1.0.1", + "", + { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, + "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==" + ], + + "glob": [ + "glob@11.1.0", + "", + { + "dependencies": { + "foreground-child": "^3.3.1", + "jackspeak": "^4.1.1", + "minimatch": "^10.1.1", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "bin": { "glob": "dist/esm/bin.mjs" } + }, + "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==" + ], + + "google-auth-library": [ + "google-auth-library@10.5.0", + "", + { + "dependencies": { + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "gaxios": "^7.0.0", + "gcp-metadata": "^8.0.0", + "google-logging-utils": "^1.0.0", + "gtoken": "^8.0.0", + "jws": "^4.0.0" + } + }, + "sha512-7ABviyMOlX5hIVD60YOfHw4/CxOfBhyduaYB+wbFWCWoni4N7SLcV46hrVRktuBbZjFC9ONyqamZITN7q3n32w==" + ], + + "google-logging-utils": [ + "google-logging-utils@1.1.3", + "", + {}, + "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==" + ], + + "gopd": [ + "gopd@1.2.0", + "", + {}, + "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==" + ], + + "gtoken": [ + "gtoken@8.0.0", + "", + { "dependencies": { "gaxios": "^7.0.0", "jws": "^4.0.0" } }, + "sha512-+CqsMbHPiSTdtSO14O51eMNlrp9N79gmeqmXeouJOhfucAedHw9noVe/n5uJk3tbKE6a+6ZCQg3RPhVhHByAIw==" + ], + + "has-flag": [ + "has-flag@4.0.0", + "", + {}, + "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + ], + + "has-symbols": [ + "has-symbols@1.1.0", + "", + {}, + "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==" + ], + + "hasown": [ + "hasown@2.0.2", + "", + { "dependencies": { "function-bind": "^1.1.2" } }, + "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==" + ], + + "he": [ + "he@1.2.0", + "", + { "bin": { "he": "bin/he" } }, + "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" + ], + + "highlight.js": [ + "highlight.js@11.11.1", + "", + {}, + "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==" + ], + + "hono": [ + "hono@4.11.3", + "", + {}, + "sha512-PmQi306+M/ct/m5s66Hrg+adPnkD5jiO6IjA7WhWw0gSBSo1EcRegwuI1deZ+wd5pzCGynCcn2DprnE4/yEV4w==" + ], + + "http-errors": [ + "http-errors@2.0.1", + "", + { + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + } + }, + "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==" + ], + + "https-proxy-agent": [ + "https-proxy-agent@7.0.6", + "", + { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, + "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==" + ], + + "iconv-lite": [ + "iconv-lite@0.7.1", + "", + { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, + "sha512-2Tth85cXwGFHfvRgZWszZSvdo+0Xsqmw8k8ZwxScfcBneNUraK+dxRxRm24nszx80Y0TVio8kKLt5sLE7ZCLlw==" + ], + + "ieee754": [ + "ieee754@1.2.1", + "", + {}, + "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + ], + + "inherits": [ + "inherits@2.0.4", + "", + {}, + "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + ], + + "ipaddr.js": [ + "ipaddr.js@1.9.1", + "", + {}, + "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + ], + + "is-fullwidth-code-point": [ + "is-fullwidth-code-point@3.0.0", + "", + {}, + "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + ], + + "is-number": [ + "is-number@7.0.0", + "", + {}, + "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + ], + + "is-promise": [ + "is-promise@4.0.0", + "", + {}, + "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==" + ], + + "is-stream": [ + "is-stream@2.0.1", + "", + {}, + "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" + ], + + "isexe": [ + "isexe@2.0.0", + "", + {}, + "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + ], + + "jackspeak": [ + "jackspeak@4.1.1", + "", + { "dependencies": { "@isaacs/cliui": "^8.0.2" } }, + "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==" + ], + + "jose": [ + "jose@6.1.3", + "", + {}, + "sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ==" + ], + + "js-tokens": [ + "js-tokens@9.0.1", + "", + {}, + "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==" + ], + + "json-bigint": [ + "json-bigint@1.0.0", + "", + { "dependencies": { "bignumber.js": "^9.0.0" } }, + "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==" + ], + + "json-schema-to-ts": [ + "json-schema-to-ts@3.1.1", + "", + { "dependencies": { "@babel/runtime": "^7.18.3", "ts-algebra": "^2.0.0" } }, + "sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g==" + ], + + "json-schema-traverse": [ + "json-schema-traverse@1.0.0", + "", + {}, + "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + ], + + "json-schema-typed": [ + "json-schema-typed@8.0.2", + "", + {}, + "sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==" + ], + + "json-stringify-safe": [ + "json-stringify-safe@5.0.1", + "", + {}, + "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" + ], + + "jwa": [ + "jwa@2.0.1", + "", + { + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==" + ], + + "jws": [ + "jws@4.0.1", + "", + { "dependencies": { "jwa": "^2.0.1", "safe-buffer": "^5.0.1" } }, + "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==" + ], + + "kuler": [ + "kuler@2.0.0", + "", + {}, + "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==" + ], + + "lint-staged": [ + "lint-staged@16.2.7", + "", + { + "dependencies": { + "commander": "^14.0.2", + "listr2": "^9.0.5", + "micromatch": "^4.0.8", + "nano-spawn": "^2.0.0", + "pidtree": "^0.6.0", + "string-argv": "^0.3.2", + "yaml": "^2.8.1" + }, + "bin": { "lint-staged": "bin/lint-staged.js" } + }, + "sha512-lDIj4RnYmK7/kXMya+qJsmkRFkGolciXjrsZ6PC25GdTfWOAWetR0ZbsNXRAj1EHHImRSalc+whZFg56F5DVow==" + ], + + "listr2": [ + "listr2@9.0.5", + "", + { + "dependencies": { + "cli-truncate": "^5.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.1.0", + "rfdc": "^1.4.1", + "wrap-ansi": "^9.0.0" + } + }, + "sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==" + ], + + "log-update": [ + "log-update@6.1.0", + "", + { + "dependencies": { + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + } + }, + "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==" + ], + + "logform": [ + "logform@2.7.0", + "", + { + "dependencies": { + "@colors/colors": "1.6.0", + "@types/triple-beam": "^1.3.2", + "fecha": "^4.2.0", + "ms": "^2.1.1", + "safe-stable-stringify": "^2.3.1", + "triple-beam": "^1.3.0" + } + }, + "sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==" + ], + + "loupe": [ + "loupe@3.2.1", + "", + {}, + "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==" + ], + + "lru-cache": [ + "lru-cache@11.2.4", + "", + {}, + "sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==" + ], + + "magic-string": [ + "magic-string@0.30.21", + "", + { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, + "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==" + ], + + "marked": [ + "marked@15.0.12", + "", + { "bin": { "marked": "bin/marked.js" } }, + "sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA==" + ], + + "math-intrinsics": [ + "math-intrinsics@1.1.0", + "", + {}, + "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==" + ], + + "media-typer": [ + "media-typer@1.1.0", + "", + {}, + "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==" + ], + + "merge-descriptors": [ + "merge-descriptors@2.0.0", + "", + {}, + "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==" + ], + + "micromatch": [ + "micromatch@4.0.8", + "", + { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, + "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==" + ], + + "mime-db": [ + "mime-db@1.54.0", + "", + {}, + "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==" + ], + + "mime-types": [ + "mime-types@3.0.2", + "", + { "dependencies": { "mime-db": "^1.54.0" } }, + "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==" + ], + + "mimic-function": [ + "mimic-function@5.0.1", + "", + {}, + "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==" + ], + + "minimatch": [ + "minimatch@10.1.1", + "", + { "dependencies": { "@isaacs/brace-expansion": "^5.0.0" } }, + "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==" + ], + + "minimist": [ + "minimist@1.2.8", + "", + {}, + "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + ], + + "minipass": [ + "minipass@7.1.2", + "", + {}, + "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==" + ], + + "moment": [ + "moment@2.30.1", + "", + {}, + "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==" + ], + + "ms": [ + "ms@2.1.3", + "", + {}, + "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + ], + + "mz": [ + "mz@2.7.0", + "", + { "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", "thenify-all": "^1.0.0" } }, + "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==" + ], + + "nano-spawn": [ + "nano-spawn@2.0.0", + "", + {}, + "sha512-tacvGzUY5o2D8CBh2rrwxyNojUsZNU2zjNTzKQrkgGJQTbGAfArVWXSKMBokBeeg6C7OLRGUEyoFlYbfeWQIqw==" + ], + + "nanoid": [ + "nanoid@5.1.6", + "", + { "bin": { "nanoid": "bin/nanoid.js" } }, + "sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg==" + ], + + "ndjson": [ + "ndjson@2.0.0", + "", + { + "dependencies": { + "json-stringify-safe": "^5.0.1", + "minimist": "^1.2.5", + "readable-stream": "^3.6.0", + "split2": "^3.0.0", + "through2": "^4.0.0" + }, + "bin": { "ndjson": "cli.js" } + }, + "sha512-nGl7LRGrzugTtaFcJMhLbpzJM6XdivmbkdlaGcrk/LXg2KL/YBC6z1g70xh0/al+oFuVFP8N8kiWRucmeEH/qQ==" + ], + + "negotiator": [ + "negotiator@1.0.0", + "", + {}, + "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==" + ], + + "node-domexception": [ + "node-domexception@1.0.0", + "", + {}, + "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==" + ], + + "node-fetch": [ + "node-fetch@3.3.2", + "", + { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, + "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==" + ], + + "node-html-parser": [ + "node-html-parser@6.1.13", + "", + { "dependencies": { "css-select": "^5.1.0", "he": "1.2.0" } }, + "sha512-qIsTMOY4C/dAa5Q5vsobRpOOvPfC4pB61UVW2uSwZNUp0QU/jCekTal1vMmbO0DgdHeLUJpv/ARmDqErVxA3Sg==" + ], + + "nth-check": [ + "nth-check@2.1.1", + "", + { "dependencies": { "boolbase": "^1.0.0" } }, + "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==" + ], + + "object-assign": [ + "object-assign@4.1.1", + "", + {}, + "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + ], + + "object-hash": [ + "object-hash@3.0.0", + "", + {}, + "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==" + ], + + "object-inspect": [ + "object-inspect@1.13.4", + "", + {}, + "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==" + ], + + "on-finished": [ + "on-finished@2.4.1", + "", + { "dependencies": { "ee-first": "1.1.1" } }, + "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==" + ], + + "once": [ + "once@1.4.0", + "", + { "dependencies": { "wrappy": "1" } }, + "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==" + ], + + "one-time": [ + "one-time@1.0.0", + "", + { "dependencies": { "fn.name": "1.x.x" } }, + "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==" + ], + + "onetime": [ + "onetime@7.0.0", + "", + { "dependencies": { "mimic-function": "^5.0.0" } }, + "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==" + ], + + "openai": [ + "openai@6.10.0", + "", + { + "peerDependencies": { "ws": "^8.18.0", "zod": "^3.25 || ^4.0" }, + "optionalPeers": ["ws", "zod"], + "bin": { "openai": "bin/cli" } + }, + "sha512-ITxOGo7rO3XRMiKA5l7tQ43iNNu+iXGFAcf2t+aWVzzqRaS0i7m1K2BhxNdaveB+5eENhO0VY1FkiZzhBk4v3A==" + ], + + "package-json-from-dist": [ + "package-json-from-dist@1.0.1", + "", + {}, + "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==" + ], + + "parse5": [ + "parse5@5.1.1", + "", + {}, + "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==" + ], + + "parse5-htmlparser2-tree-adapter": [ + "parse5-htmlparser2-tree-adapter@6.0.1", + "", + { "dependencies": { "parse5": "^6.0.1" } }, + "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==" + ], + + "parseurl": [ + "parseurl@1.3.3", + "", + {}, + "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + ], + + "partial-json": [ + "partial-json@0.1.7", + "", + {}, + "sha512-Njv/59hHaokb/hRUjce3Hdv12wd60MtM9Z5Olmn+nehe0QDAsRtRbJPvJ0Z91TusF0SuZRIvnM+S4l6EIP8leA==" + ], + + "path-key": [ + "path-key@3.1.1", + "", + {}, + "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + ], + + "path-scurry": [ + "path-scurry@2.0.1", + "", + { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, + "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==" + ], + + "path-to-regexp": [ + "path-to-regexp@8.3.0", + "", + {}, + "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==" + ], + + "pathe": [ + "pathe@2.0.3", + "", + {}, + "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==" + ], + + "pathval": [ + "pathval@2.0.1", + "", + {}, + "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==" + ], + + "picocolors": [ + "picocolors@1.1.1", + "", + {}, + "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" + ], + + "picomatch": [ + "picomatch@4.0.3", + "", + {}, + "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==" + ], + + "pidtree": [ + "pidtree@0.6.0", + "", + { "bin": { "pidtree": "bin/pidtree.js" } }, + "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==" + ], + + "pkce-challenge": [ + "pkce-challenge@5.0.1", + "", + {}, + "sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==" + ], + + "postcss": [ + "postcss@8.5.6", + "", + { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, + "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==" + ], + + "proxy-addr": [ + "proxy-addr@2.0.7", + "", + { "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, + "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==" + ], + + "qs": [ + "qs@6.14.1", + "", + { "dependencies": { "side-channel": "^1.1.0" } }, + "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==" + ], + + "range-parser": [ + "range-parser@1.2.1", + "", + {}, + "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + ], + + "raw-body": [ + "raw-body@3.0.2", + "", + { "dependencies": { "bytes": "~3.1.2", "http-errors": "~2.0.1", "iconv-lite": "~0.7.0", "unpipe": "~1.0.0" } }, + "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==" + ], + + "readable-stream": [ + "readable-stream@3.6.2", + "", + { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, + "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==" + ], + + "require-directory": [ + "require-directory@2.1.1", + "", + {}, + "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" + ], + + "require-from-string": [ + "require-from-string@2.0.2", + "", + {}, + "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" + ], + + "restore-cursor": [ + "restore-cursor@5.1.0", + "", + { "dependencies": { "onetime": "^7.0.0", "signal-exit": "^4.1.0" } }, + "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==" + ], + + "rfdc": [ + "rfdc@1.4.1", + "", + {}, + "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==" + ], + + "rimraf": [ + "rimraf@5.0.10", + "", + { "dependencies": { "glob": "^10.3.7" }, "bin": { "rimraf": "dist/esm/bin.mjs" } }, + "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==" + ], + + "rollup": [ + "rollup@4.55.1", + "", + { + "dependencies": { "@types/estree": "1.0.8" }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.55.1", + "@rollup/rollup-android-arm64": "4.55.1", + "@rollup/rollup-darwin-arm64": "4.55.1", + "@rollup/rollup-darwin-x64": "4.55.1", + "@rollup/rollup-freebsd-arm64": "4.55.1", + "@rollup/rollup-freebsd-x64": "4.55.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.55.1", + "@rollup/rollup-linux-arm-musleabihf": "4.55.1", + "@rollup/rollup-linux-arm64-gnu": "4.55.1", + "@rollup/rollup-linux-arm64-musl": "4.55.1", + "@rollup/rollup-linux-loong64-gnu": "4.55.1", + "@rollup/rollup-linux-loong64-musl": "4.55.1", + "@rollup/rollup-linux-ppc64-gnu": "4.55.1", + "@rollup/rollup-linux-ppc64-musl": "4.55.1", + "@rollup/rollup-linux-riscv64-gnu": "4.55.1", + "@rollup/rollup-linux-riscv64-musl": "4.55.1", + "@rollup/rollup-linux-s390x-gnu": "4.55.1", + "@rollup/rollup-linux-x64-gnu": "4.55.1", + "@rollup/rollup-linux-x64-musl": "4.55.1", + "@rollup/rollup-openbsd-x64": "4.55.1", + "@rollup/rollup-openharmony-arm64": "4.55.1", + "@rollup/rollup-win32-arm64-msvc": "4.55.1", + "@rollup/rollup-win32-ia32-msvc": "4.55.1", + "@rollup/rollup-win32-x64-gnu": "4.55.1", + "@rollup/rollup-win32-x64-msvc": "4.55.1", + "fsevents": "~2.3.2" + }, + "bin": { "rollup": "dist/bin/rollup" } + }, + "sha512-wDv/Ht1BNHB4upNbK74s9usvl7hObDnvVzknxqY/E/O3X6rW1U1rV1aENEfJ54eFZDTNo7zv1f5N4edCluH7+A==" + ], + + "router": [ + "router@2.2.0", + "", + { + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + } + }, + "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==" + ], + + "rxjs": [ + "rxjs@7.8.2", + "", + { "dependencies": { "tslib": "^2.1.0" } }, + "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==" + ], + + "safe-buffer": [ + "safe-buffer@5.2.1", + "", + {}, + "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + ], + + "safe-stable-stringify": [ + "safe-stable-stringify@2.5.0", + "", + {}, + "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==" + ], + + "safer-buffer": [ + "safer-buffer@2.1.2", + "", + {}, + "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + ], + + "semver": [ + "semver@7.7.3", + "", + { "bin": { "semver": "bin/semver.js" } }, + "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==" + ], + + "send": [ + "send@1.2.1", + "", + { + "dependencies": { + "debug": "^4.4.3", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.1", + "mime-types": "^3.0.2", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.2" + } + }, + "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==" + ], + + "serve-static": [ + "serve-static@2.2.1", + "", + { "dependencies": { "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "parseurl": "^1.3.3", "send": "^1.2.0" } }, + "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==" + ], + + "setprototypeof": [ + "setprototypeof@1.2.0", + "", + {}, + "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + ], + + "sharp": [ + "sharp@0.34.5", + "", + { + "dependencies": { "@img/colour": "^1.0.0", "detect-libc": "^2.1.2", "semver": "^7.7.3" }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.34.5", + "@img/sharp-darwin-x64": "0.34.5", + "@img/sharp-libvips-darwin-arm64": "1.2.4", + "@img/sharp-libvips-darwin-x64": "1.2.4", + "@img/sharp-libvips-linux-arm": "1.2.4", + "@img/sharp-libvips-linux-arm64": "1.2.4", + "@img/sharp-libvips-linux-ppc64": "1.2.4", + "@img/sharp-libvips-linux-riscv64": "1.2.4", + "@img/sharp-libvips-linux-s390x": "1.2.4", + "@img/sharp-libvips-linux-x64": "1.2.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", + "@img/sharp-libvips-linuxmusl-x64": "1.2.4", + "@img/sharp-linux-arm": "0.34.5", + "@img/sharp-linux-arm64": "0.34.5", + "@img/sharp-linux-ppc64": "0.34.5", + "@img/sharp-linux-riscv64": "0.34.5", + "@img/sharp-linux-s390x": "0.34.5", + "@img/sharp-linux-x64": "0.34.5", + "@img/sharp-linuxmusl-arm64": "0.34.5", + "@img/sharp-linuxmusl-x64": "0.34.5", + "@img/sharp-wasm32": "0.34.5", + "@img/sharp-win32-arm64": "0.34.5", + "@img/sharp-win32-ia32": "0.34.5", + "@img/sharp-win32-x64": "0.34.5" + } + }, + "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==" + ], + + "shebang-command": [ + "shebang-command@2.0.0", + "", + { "dependencies": { "shebang-regex": "^3.0.0" } }, + "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==" + ], + + "shebang-regex": [ + "shebang-regex@3.0.0", + "", + {}, + "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" + ], + + "shell-quote": [ + "shell-quote@1.8.3", + "", + {}, + "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==" + ], + + "side-channel": [ + "side-channel@1.1.0", + "", + { + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + } + }, + "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==" + ], + + "side-channel-list": [ + "side-channel-list@1.0.0", + "", + { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3" } }, + "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==" + ], + + "side-channel-map": [ + "side-channel-map@1.0.1", + "", + { + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + } + }, + "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==" + ], + + "side-channel-weakmap": [ + "side-channel-weakmap@1.0.2", + "", + { + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + } + }, + "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==" + ], + + "siginfo": [ + "siginfo@2.0.0", + "", + {}, + "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==" + ], + + "signal-exit": [ + "signal-exit@4.1.0", + "", + {}, + "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==" + ], + + "slice-ansi": [ + "slice-ansi@7.1.2", + "", + { "dependencies": { "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^5.0.0" } }, + "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==" + ], + + "smol-toml": [ + "smol-toml@1.6.0", + "", + {}, + "sha512-4zemZi0HvTnYwLfrpk/CF9LOd9Lt87kAt50GnqhMpyF9U3poDAP2+iukq2bZsO/ufegbYehBkqINbsWxj4l4cw==" + ], + + "source-map-js": [ + "source-map-js@1.2.1", + "", + {}, + "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==" + ], + + "split2": [ + "split2@3.2.2", + "", + { "dependencies": { "readable-stream": "^3.0.0" } }, + "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==" + ], + + "stack-trace": [ + "stack-trace@0.0.10", + "", + {}, + "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==" + ], + + "stackback": [ + "stackback@0.0.2", + "", + {}, + "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==" + ], + + "statuses": [ + "statuses@2.0.2", + "", + {}, + "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==" + ], + + "std-env": [ + "std-env@3.10.0", + "", + {}, + "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==" + ], + + "string-argv": [ + "string-argv@0.3.2", + "", + {}, + "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==" + ], + + "string-width": [ + "string-width@4.2.3", + "", + { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, + "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==" + ], + + "string-width-cjs": [ + "string-width@4.2.3", + "", + { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, + "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==" + ], + + "string_decoder": [ + "string_decoder@1.3.0", + "", + { "dependencies": { "safe-buffer": "~5.2.0" } }, + "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==" + ], + + "strip-ansi": [ + "strip-ansi@7.1.2", + "", + { "dependencies": { "ansi-regex": "^6.0.1" } }, + "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==" + ], + + "strip-ansi-cjs": [ + "strip-ansi@6.0.1", + "", + { "dependencies": { "ansi-regex": "^5.0.1" } }, + "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==" + ], + + "strip-literal": [ + "strip-literal@3.1.0", + "", + { "dependencies": { "js-tokens": "^9.0.1" } }, + "sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==" + ], + + "strtok3": [ + "strtok3@10.3.4", + "", + { "dependencies": { "@tokenizer/token": "^0.3.0" } }, + "sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg==" + ], + + "supports-color": [ + "supports-color@8.1.1", + "", + { "dependencies": { "has-flag": "^4.0.0" } }, + "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==" + ], + + "text-hex": [ + "text-hex@1.0.0", + "", + {}, + "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==" + ], + + "thenify": [ + "thenify@3.3.1", + "", + { "dependencies": { "any-promise": "^1.0.0" } }, + "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==" + ], + + "thenify-all": [ + "thenify-all@1.6.0", + "", + { "dependencies": { "thenify": ">= 3.1.0 < 4" } }, + "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==" + ], + + "through2": [ + "through2@4.0.2", + "", + { "dependencies": { "readable-stream": "3" } }, + "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==" + ], + + "tinybench": [ + "tinybench@2.9.0", + "", + {}, + "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==" + ], + + "tinyexec": [ + "tinyexec@0.3.2", + "", + {}, + "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==" + ], + + "tinyglobby": [ + "tinyglobby@0.2.15", + "", + { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, + "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==" + ], + + "tinypool": [ + "tinypool@1.1.1", + "", + {}, + "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==" + ], + + "tinyrainbow": [ + "tinyrainbow@2.0.0", + "", + {}, + "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==" + ], + + "tinyspy": [ + "tinyspy@4.0.4", + "", + {}, + "sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==" + ], + + "to-regex-range": [ + "to-regex-range@5.0.1", + "", + { "dependencies": { "is-number": "^7.0.0" } }, + "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==" + ], + + "toidentifier": [ + "toidentifier@1.0.1", + "", + {}, + "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" + ], + + "token-types": [ + "token-types@6.1.2", + "", + { "dependencies": { "@borewit/text-codec": "^0.2.1", "@tokenizer/token": "^0.3.0", "ieee754": "^1.2.1" } }, + "sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww==" + ], + + "tree-kill": [ + "tree-kill@1.2.2", + "", + { "bin": { "tree-kill": "cli.js" } }, + "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==" + ], + + "triple-beam": [ + "triple-beam@1.4.1", + "", + {}, + "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==" + ], + + "ts-algebra": [ + "ts-algebra@2.0.0", + "", + {}, + "sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw==" + ], + + "tslib": [ + "tslib@2.8.1", + "", + {}, + "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + ], + + "type-is": [ + "type-is@2.0.1", + "", + { "dependencies": { "content-type": "^1.0.5", "media-typer": "^1.1.0", "mime-types": "^3.0.0" } }, + "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==" + ], + + "uint8array-extras": [ + "uint8array-extras@1.5.0", + "", + {}, + "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==" + ], + + "undici-types": [ + "undici-types@6.21.0", + "", + {}, + "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==" + ], + + "unpipe": [ + "unpipe@1.0.0", + "", + {}, + "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" + ], + + "util-deprecate": [ + "util-deprecate@1.0.2", + "", + {}, + "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + ], + + "vary": [ + "vary@1.1.2", + "", + {}, + "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" + ], + + "vite": [ + "vite@7.3.0", + "", + { + "dependencies": { + "esbuild": "^0.27.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "optionalDependencies": { "fsevents": "~2.3.3" }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "optionalPeers": [ + "@types/node", + "jiti", + "less", + "lightningcss", + "sass", + "sass-embedded", + "stylus", + "sugarss", + "terser", + "tsx", + "yaml" + ], + "bin": { "vite": "bin/vite.js" } + }, + "sha512-dZwN5L1VlUBewiP6H9s2+B3e3Jg96D0vzN+Ry73sOefebhYr9f94wwkMNN/9ouoU8pV1BqA1d1zGk8928cx0rg==" + ], + + "vite-node": [ + "vite-node@3.2.4", + "", + { + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.4.1", + "es-module-lexer": "^1.7.0", + "pathe": "^2.0.3", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" + }, + "bin": { "vite-node": "vite-node.mjs" } + }, + "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==" + ], + + "vitest": [ + "vitest@3.2.4", + "", + { + "dependencies": { + "@types/chai": "^5.2.2", + "@vitest/expect": "3.2.4", + "@vitest/mocker": "3.2.4", + "@vitest/pretty-format": "^3.2.4", + "@vitest/runner": "3.2.4", + "@vitest/snapshot": "3.2.4", + "@vitest/spy": "3.2.4", + "@vitest/utils": "3.2.4", + "chai": "^5.2.0", + "debug": "^4.4.1", + "expect-type": "^1.2.1", + "magic-string": "^0.30.17", + "pathe": "^2.0.3", + "picomatch": "^4.0.2", + "std-env": "^3.9.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.2", + "tinyglobby": "^0.2.14", + "tinypool": "^1.1.1", + "tinyrainbow": "^2.0.0", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0", + "vite-node": "3.2.4", + "why-is-node-running": "^2.3.0" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/debug": "^4.1.12", + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "@vitest/browser": "3.2.4", + "@vitest/ui": "3.2.4", + "happy-dom": "*", + "jsdom": "*" + }, + "optionalPeers": [ + "@edge-runtime/vm", + "@types/debug", + "@types/node", + "@vitest/browser", + "@vitest/ui", + "happy-dom", + "jsdom" + ], + "bin": { "vitest": "vitest.mjs" } + }, + "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==" + ], + + "web-streams-polyfill": [ + "web-streams-polyfill@3.3.3", + "", + {}, + "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==" + ], + + "which": [ + "which@2.0.2", + "", + { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, + "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==" + ], + + "why-is-node-running": [ + "why-is-node-running@2.3.0", + "", + { "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" }, "bin": { "why-is-node-running": "cli.js" } }, + "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==" + ], + + "winston": [ + "winston@3.19.0", + "", + { + "dependencies": { + "@colors/colors": "^1.6.0", + "@dabh/diagnostics": "^2.0.8", + "async": "^3.2.3", + "is-stream": "^2.0.0", + "logform": "^2.7.0", + "one-time": "^1.0.0", + "readable-stream": "^3.4.0", + "safe-stable-stringify": "^2.3.1", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.9.0" + } + }, + "sha512-LZNJgPzfKR+/J3cHkxcpHKpKKvGfDZVPS4hfJCc4cCG0CgYzvlD6yE/S3CIL/Yt91ak327YCpiF/0MyeZHEHKA==" + ], + + "winston-daily-rotate-file": [ + "winston-daily-rotate-file@5.0.0", + "", + { + "dependencies": { + "file-stream-rotator": "^0.6.1", + "object-hash": "^3.0.0", + "triple-beam": "^1.4.1", + "winston-transport": "^4.7.0" + }, + "peerDependencies": { "winston": "^3" } + }, + "sha512-JDjiXXkM5qvwY06733vf09I2wnMXpZEhxEVOSPenZMii+g7pcDcTBt2MRugnoi8BwVSuCT2jfRXBUy+n1Zz/Yw==" + ], + + "winston-transport": [ + "winston-transport@4.9.0", + "", + { "dependencies": { "logform": "^2.7.0", "readable-stream": "^3.6.2", "triple-beam": "^1.3.0" } }, + "sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==" + ], + + "wrap-ansi": [ + "wrap-ansi@9.0.2", + "", + { "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", "strip-ansi": "^7.1.0" } }, + "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==" + ], + + "wrap-ansi-cjs": [ + "wrap-ansi@7.0.0", + "", + { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, + "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==" + ], + + "wrappy": [ + "wrappy@1.0.2", + "", + {}, + "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + ], + + "ws": [ + "ws@8.19.0", + "", + { + "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, + "optionalPeers": ["bufferutil", "utf-8-validate"] + }, + "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==" + ], + + "y18n": [ + "y18n@5.0.8", + "", + {}, + "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" + ], + + "yaml": [ + "yaml@2.8.2", + "", + { "bin": { "yaml": "bin.mjs" } }, + "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==" + ], + + "yargs": [ + "yargs@17.7.2", + "", + { + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + } + }, + "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==" + ], + + "yargs-parser": [ + "yargs-parser@21.1.1", + "", + {}, + "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==" + ], + + "zod": [ + "zod@4.3.5", + "", + {}, + "sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g==" + ], + + "zod-to-json-schema": [ + "zod-to-json-schema@3.25.1", + "", + { "peerDependencies": { "zod": "^3.25 || ^4" } }, + "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==" + ], + + "@isaacs/cliui/string-width": [ + "string-width@5.1.2", + "", + { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, + "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==" + ], + + "@isaacs/cliui/wrap-ansi": [ + "wrap-ansi@8.1.0", + "", + { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, + "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==" + ], + + "@mistralai/mistralai/zod": [ + "zod@3.25.76", + "", + {}, + "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==" + ], + + "@oh-my-pi/pi-agent-core/@types/node": [ + "@types/node@24.10.4", + "", + { "dependencies": { "undici-types": "~7.16.0" } }, + "sha512-vnDVpYPMzs4wunl27jHrfmwojOGKya0xyM3sH+UE5iv5uPS6vX7UIoh6m+vQc5LGBq52HBKPIn/zcSZVzeDEZg==" + ], + + "@oh-my-pi/pi-coding-agent/@types/node": [ + "@types/node@24.10.4", + "", + { "dependencies": { "undici-types": "~7.16.0" } }, + "sha512-vnDVpYPMzs4wunl27jHrfmwojOGKya0xyM3sH+UE5iv5uPS6vX7UIoh6m+vQc5LGBq52HBKPIn/zcSZVzeDEZg==" + ], + + "@oh-my-pi/pi-git-tool/@types/node": [ + "@types/node@24.10.4", + "", + { "dependencies": { "undici-types": "~7.16.0" } }, + "sha512-vnDVpYPMzs4wunl27jHrfmwojOGKya0xyM3sH+UE5iv5uPS6vX7UIoh6m+vQc5LGBq52HBKPIn/zcSZVzeDEZg==" + ], + + "@openai/agents/openai": [ + "openai@6.15.0", + "", + { + "peerDependencies": { "ws": "^8.18.0", "zod": "^3.25 || ^4.0" }, + "optionalPeers": ["ws", "zod"], + "bin": { "openai": "bin/cli" } + }, + "sha512-F1Lvs5BoVvmZtzkUEVyh8mDQPPFolq4F+xdsx/DO8Hee8YF3IGAlZqUIsF+DVGhqf4aU0a3bTghsxB6OIsRy1g==" + ], + + "@openai/agents-core/openai": [ + "openai@6.15.0", + "", + { + "peerDependencies": { "ws": "^8.18.0", "zod": "^3.25 || ^4.0" }, + "optionalPeers": ["ws", "zod"], + "bin": { "openai": "bin/cli" } + }, + "sha512-F1Lvs5BoVvmZtzkUEVyh8mDQPPFolq4F+xdsx/DO8Hee8YF3IGAlZqUIsF+DVGhqf4aU0a3bTghsxB6OIsRy1g==" + ], + + "@openai/agents-openai/openai": [ + "openai@6.15.0", + "", + { + "peerDependencies": { "ws": "^8.18.0", "zod": "^3.25 || ^4.0" }, + "optionalPeers": ["ws", "zod"], + "bin": { "openai": "bin/cli" } + }, + "sha512-F1Lvs5BoVvmZtzkUEVyh8mDQPPFolq4F+xdsx/DO8Hee8YF3IGAlZqUIsF+DVGhqf4aU0a3bTghsxB6OIsRy1g==" + ], + + "@types/ndjson/@types/node": [ + "@types/node@24.10.4", + "", + { "dependencies": { "undici-types": "~7.16.0" } }, + "sha512-vnDVpYPMzs4wunl27jHrfmwojOGKya0xyM3sH+UE5iv5uPS6vX7UIoh6m+vQc5LGBq52HBKPIn/zcSZVzeDEZg==" + ], + + "@types/through/@types/node": [ + "@types/node@24.10.4", + "", + { "dependencies": { "undici-types": "~7.16.0" } }, + "sha512-vnDVpYPMzs4wunl27jHrfmwojOGKya0xyM3sH+UE5iv5uPS6vX7UIoh6m+vQc5LGBq52HBKPIn/zcSZVzeDEZg==" + ], + + "@types/ws/@types/node": [ + "@types/node@24.10.4", + "", + { "dependencies": { "undici-types": "~7.16.0" } }, + "sha512-vnDVpYPMzs4wunl27jHrfmwojOGKya0xyM3sH+UE5iv5uPS6vX7UIoh6m+vQc5LGBq52HBKPIn/zcSZVzeDEZg==" + ], + + "bun-types/@types/node": [ + "@types/node@24.10.4", + "", + { "dependencies": { "undici-types": "~7.16.0" } }, + "sha512-vnDVpYPMzs4wunl27jHrfmwojOGKya0xyM3sH+UE5iv5uPS6vX7UIoh6m+vQc5LGBq52HBKPIn/zcSZVzeDEZg==" + ], + + "cli-highlight/chalk": [ + "chalk@4.1.2", + "", + { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, + "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==" + ], + + "cli-highlight/highlight.js": [ + "highlight.js@10.7.3", + "", + {}, + "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==" + ], + + "cli-highlight/yargs": [ + "yargs@16.2.0", + "", + { + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==" + ], + + "cli-truncate/string-width": [ + "string-width@8.1.0", + "", + { "dependencies": { "get-east-asian-width": "^1.3.0", "strip-ansi": "^7.1.0" } }, + "sha512-Kxl3KJGb/gxkaUMOjRsQ8IrXiGW75O4E3RPjFIINOVH8AMl2SQ/yWdTzWwF3FevIX9LcMAjJW+GRwAlAbTSXdg==" + ], + + "cliui/strip-ansi": [ + "strip-ansi@6.0.1", + "", + { "dependencies": { "ansi-regex": "^5.0.1" } }, + "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==" + ], + + "cliui/wrap-ansi": [ + "wrap-ansi@7.0.0", + "", + { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, + "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==" + ], + + "color/color-convert": [ + "color-convert@3.1.3", + "", + { "dependencies": { "color-name": "^2.0.0" } }, + "sha512-fasDH2ont2GqF5HpyO4w0+BcewlhHEZOFn9c1ckZdHpJ56Qb7MHhH/IcJZbBGgvdtwdwNbLvxiBEdg336iA9Sg==" + ], + + "color-string/color-name": [ + "color-name@2.1.0", + "", + {}, + "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==" + ], + + "concurrently/chalk": [ + "chalk@4.1.2", + "", + { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, + "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==" + ], + + "micromatch/picomatch": [ + "picomatch@2.3.1", + "", + {}, + "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" + ], + + "parse5-htmlparser2-tree-adapter/parse5": [ + "parse5@6.0.1", + "", + {}, + "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + ], + + "postcss/nanoid": [ + "nanoid@3.3.11", + "", + { "bin": { "nanoid": "bin/nanoid.cjs" } }, + "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==" + ], + + "rimraf/glob": [ + "glob@10.5.0", + "", + { + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { "glob": "dist/esm/bin.mjs" } + }, + "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==" + ], + + "slice-ansi/ansi-styles": [ + "ansi-styles@6.2.3", + "", + {}, + "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==" + ], + + "slice-ansi/is-fullwidth-code-point": [ + "is-fullwidth-code-point@5.1.0", + "", + { "dependencies": { "get-east-asian-width": "^1.3.1" } }, + "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==" + ], + + "string-width/strip-ansi": [ + "strip-ansi@6.0.1", + "", + { "dependencies": { "ansi-regex": "^5.0.1" } }, + "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==" + ], + + "string-width-cjs/strip-ansi": [ + "strip-ansi@6.0.1", + "", + { "dependencies": { "ansi-regex": "^5.0.1" } }, + "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==" + ], + + "strip-ansi-cjs/ansi-regex": [ + "ansi-regex@5.0.1", + "", + {}, + "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + ], + + "wrap-ansi/ansi-styles": [ + "ansi-styles@6.2.3", + "", + {}, + "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==" + ], + + "wrap-ansi/string-width": [ + "string-width@7.2.0", + "", + { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, + "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==" + ], + + "wrap-ansi-cjs/strip-ansi": [ + "strip-ansi@6.0.1", + "", + { "dependencies": { "ansi-regex": "^5.0.1" } }, + "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==" + ], + + "@isaacs/cliui/string-width/emoji-regex": [ + "emoji-regex@9.2.2", + "", + {}, + "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + ], + + "@isaacs/cliui/wrap-ansi/ansi-styles": [ + "ansi-styles@6.2.3", + "", + {}, + "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==" + ], + + "@oh-my-pi/pi-agent-core/@types/node/undici-types": [ + "undici-types@7.16.0", + "", + {}, + "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==" + ], + + "@oh-my-pi/pi-coding-agent/@types/node/undici-types": [ + "undici-types@7.16.0", + "", + {}, + "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==" + ], + + "@oh-my-pi/pi-git-tool/@types/node/undici-types": [ + "undici-types@7.16.0", + "", + {}, + "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==" + ], + + "@types/ndjson/@types/node/undici-types": [ + "undici-types@7.16.0", + "", + {}, + "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==" + ], + + "@types/through/@types/node/undici-types": [ + "undici-types@7.16.0", + "", + {}, + "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==" + ], + + "@types/ws/@types/node/undici-types": [ + "undici-types@7.16.0", + "", + {}, + "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==" + ], + + "bun-types/@types/node/undici-types": [ + "undici-types@7.16.0", + "", + {}, + "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==" + ], + + "cli-highlight/chalk/supports-color": [ + "supports-color@7.2.0", + "", + { "dependencies": { "has-flag": "^4.0.0" } }, + "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==" + ], + + "cli-highlight/yargs/cliui": [ + "cliui@7.0.4", + "", + { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^7.0.0" } }, + "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==" + ], + + "cli-highlight/yargs/yargs-parser": [ + "yargs-parser@20.2.9", + "", + {}, + "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==" + ], + + "cliui/strip-ansi/ansi-regex": [ + "ansi-regex@5.0.1", + "", + {}, + "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + ], + + "color/color-convert/color-name": [ + "color-name@2.1.0", + "", + {}, + "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==" + ], + + "concurrently/chalk/supports-color": [ + "supports-color@7.2.0", + "", + { "dependencies": { "has-flag": "^4.0.0" } }, + "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==" + ], + + "rimraf/glob/jackspeak": [ + "jackspeak@3.4.3", + "", + { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, + "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==" + ], + + "rimraf/glob/minimatch": [ + "minimatch@9.0.5", + "", + { "dependencies": { "brace-expansion": "^2.0.1" } }, + "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==" + ], + + "rimraf/glob/path-scurry": [ + "path-scurry@1.11.1", + "", + { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, + "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==" + ], + + "string-width-cjs/strip-ansi/ansi-regex": [ + "ansi-regex@5.0.1", + "", + {}, + "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + ], + + "string-width/strip-ansi/ansi-regex": [ + "ansi-regex@5.0.1", + "", + {}, + "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + ], + + "wrap-ansi-cjs/strip-ansi/ansi-regex": [ + "ansi-regex@5.0.1", + "", + {}, + "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + ], + + "wrap-ansi/string-width/emoji-regex": [ + "emoji-regex@10.6.0", + "", + {}, + "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==" + ], + + "cli-highlight/yargs/cliui/strip-ansi": [ + "strip-ansi@6.0.1", + "", + { "dependencies": { "ansi-regex": "^5.0.1" } }, + "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==" + ], + + "cli-highlight/yargs/cliui/wrap-ansi": [ + "wrap-ansi@7.0.0", + "", + { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, + "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==" + ], + + "rimraf/glob/path-scurry/lru-cache": [ + "lru-cache@10.4.3", + "", + {}, + "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" + ], + + "cli-highlight/yargs/cliui/strip-ansi/ansi-regex": [ + "ansi-regex@5.0.1", + "", + {}, + "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + ] + } } diff --git a/package.json b/package.json index 317cc0ee1..6705a92a5 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "release": "bun scripts/release.ts" }, "devDependencies": { - "@biomejs/biome": "2.3.10", + "@biomejs/biome": "2.3.11", "@types/bun": "^1.2.17", "@types/node": "^22.10.5", "@typescript/native-preview": "^7.0.0-dev.20260102.1", diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index f7c0e6bd3..919b7c08b 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -1,14 +1,43 @@ # Changelog ## [Unreleased] +### Added + +- Added `ToolSession` interface to unify tool creation with session context including cwd, UI availability, and rulebook rules +- Added Bun Worker-based execution for subagent tasks, replacing subprocess spawning for improved performance and event streaming +- Added `toolNames` option to filter which built-in tools are included in agent sessions +- Added `BUILTIN_TOOLS` registry constant for programmatic access to available tool factories +- Added unit tests for `createTools` function covering tool filtering and conditional tool creation + ### Changed +- Changed subagent execution from spawning separate `omp` processes to running in Bun Workers with direct event streaming +- Changed tool factories to accept `ToolSession` parameter instead of separate cwd and options arguments +- Changed `createTools` to return tools as a Map and support conditional tool creation based on session context +- Changed system prompt builder to dynamically generate tool descriptions from the tool registry +- Changed task tool description to be generated from a template with dynamic agent list injection +- Changed tool creation to use a unified `ToolSession` interface instead of separate parameters for cwd, options, and callbacks +- Changed `createTools` to return tools as a Map instead of an array for consistent tool registry access +- Changed system prompt builder to receive tool registry Map for dynamic tool description generation - Changed subprocess usage tracking to accumulate incrementally from message_end events rather than parsing stored events after completion +### Removed + +- Removed `browser` embedded agent from task tool agent discovery +- Removed `recursive` property from agent definitions +- Removed environment variables `OMP_NO_SUBAGENTS`, `OMP_BLOCKED_AGENT`, and `OMP_SPAWNS` for subagent control +- Removed pre-instantiated tool exports (`readTool`, `bashTool`, `editTool`, `writeTool`, `grepTool`, `findTool`, `lsTool`) in favor of factory functions +- Removed `createCodingTools` and `createReadOnlyTools` helper functions +- Removed `codingTools` and `readOnlyTools` convenience exports +- Removed `wrapToolsWithExtensions` function from extensions API +- Removed `hidden` property support from custom tools +- Removed subagent and question custom tool examples + ### Fixed - Fixed memory accumulation in task subprocess by streaming events directly to disk instead of storing in memory - Fixed session persistence to exclude transient streaming data (partialJson, jsonlEvents) that was causing unnecessary storage bloat +- Fixed createTools respecting explicit tool lists instead of returning all non-hidden tools ## [3.21.0] - 2026-01-06 diff --git a/packages/coding-agent/DEVELOPMENT.md b/packages/coding-agent/DEVELOPMENT.md index a8af91d99..2bfa21744 100644 --- a/packages/coding-agent/DEVELOPMENT.md +++ b/packages/coding-agent/DEVELOPMENT.md @@ -80,7 +80,7 @@ src/ │ │ └── loader.ts # loadCustomTools() from multiple locations │ │ │ └── tools/ # Built-in tool implementations -│ ├── index.ts # Tool exports, allTools, codingTools +│ ├── index.ts # Tool exports, BUILTIN_TOOLS, createTools │ ├── bash.ts # Bash command execution │ ├── edit.ts # Surgical file editing │ ├── find.ts # File search by glob @@ -278,9 +278,9 @@ npm run build:binary ### Adding a New Tool -1. Create tool in `core/tools/` following existing patterns -2. Export from `core/tools/index.ts` -3. Add to `allTools` and optionally `codingTools` +1. Create tool factory in `core/tools/` following existing patterns (e.g., `createMyTool(session: ToolSession)`) +2. Export factory from `core/tools/index.ts` +3. Add to `BUILTIN_TOOLS` map in `core/tools/index.ts` 4. Add description to `toolDescriptions` in `core/system-prompt.ts` ### Adding a New Hook Event diff --git a/packages/coding-agent/docs/sdk.md b/packages/coding-agent/docs/sdk.md index 40061c037..40a09ceed 100644 --- a/packages/coding-agent/docs/sdk.md +++ b/packages/coding-agent/docs/sdk.md @@ -347,60 +347,60 @@ const { session } = await createAgentSession({ ### Tools +By default, `createAgentSession` creates all built-in tools automatically. You can filter which tools are available using `toolNames`: + ```typescript -import { - codingTools, // read, bash, edit, write (default) - readOnlyTools, // read, grep, find, ls - readTool, - bashTool, - editTool, - writeTool, - grepTool, - findTool, - lsTool, -} from "@oh-my-pi/pi-coding-agent"; +// Use all built-in tools (default) +const { session } = await createAgentSession(); -// Use built-in tool set +// Filter to specific tools const { session } = await createAgentSession({ - tools: readOnlyTools, -}); - -// Pick specific tools -const { session } = await createAgentSession({ - tools: [readTool, bashTool, grepTool], + toolNames: ["read", "grep", "find", "ls"], // Read-only tools }); ``` -#### Tools with Custom cwd +#### Available Built-in Tools -**Important:** The pre-built tool instances (`readTool`, `bashTool`, etc.) use `process.cwd()` for path resolution. When you specify a custom `cwd` AND provide explicit `tools`, you must use the tool factory functions to ensure paths resolve correctly: +All tools are defined in `BUILTIN_TOOLS`: + +- `ask` - Interactive user prompts (requires UI) +- `bash` - Shell command execution +- `edit` - Surgical file editing +- `find` - File search by glob patterns +- `git` - Git operations (can be disabled via settings) +- `grep` - Content search with regex +- `ls` - Directory listing +- `lsp` - Language server protocol integration +- `notebook` - Jupyter notebook editing +- `output` - Task output retrieval +- `read` - File reading (text and images) +- `rulebook` - Rule reference (requires rules) +- `task` - Subagent spawning +- `web_fetch` - Web page fetching +- `web_search` - Web search +- `write` - File writing + +#### Creating Tools Manually + +For advanced use cases, you can create tools directly using `createTools`: ```typescript import { - createCodingTools, // Creates [read, bash, edit, write] for specific cwd - createReadOnlyTools, // Creates [read, grep, find, ls] for specific cwd - createReadTool, - createBashTool, - createEditTool, - createWriteTool, - createGrepTool, - createFindTool, - createLsTool, + BUILTIN_TOOLS, + createTools, + type ToolSession, } from "@oh-my-pi/pi-coding-agent"; -const cwd = "/path/to/project"; +const session: ToolSession = { + cwd: "/path/to/project", + hasUI: false, + rulebookRules: [], + getSessionFile: () => null, + getSessionSpawns: () => "*", + getAvailableTools: () => Object.keys(BUILTIN_TOOLS), +}; -// Use factory for tool sets -const { session } = await createAgentSession({ - cwd, - tools: createCodingTools(cwd), // Tools resolve paths relative to cwd -}); - -// Or pick specific tools -const { session } = await createAgentSession({ - cwd, - tools: [createReadTool(cwd), createBashTool(cwd), createGrepTool(cwd)], -}); +const tools = await createTools(session); ``` **When you don't need factories:** @@ -943,17 +943,14 @@ buildSystemPrompt SessionManager SettingsManager -// Built-in tools (use process.cwd()) -codingTools -readOnlyTools -readTool, bashTool, editTool, writeTool -grepTool, findTool, lsTool +// Tool registry and factory +BUILTIN_TOOLS // Map of tool name to factory +createTools // Create all tools from ToolSession +type ToolSession // Session context for tool creation -// Tool factories (for custom cwd) -createCodingTools -createReadOnlyTools +// Individual tool factories createReadTool, createBashTool, createEditTool, createWriteTool -createGrepTool, createFindTool, createLsTool +createGrepTool, createFindTool, createLsTool, createGitTool // Types type CreateAgentSessionOptions diff --git a/packages/coding-agent/examples/custom-tools/README.md b/packages/coding-agent/examples/custom-tools/README.md index 117f4ab4c..b18f70390 100644 --- a/packages/coding-agent/examples/custom-tools/README.md +++ b/packages/coding-agent/examples/custom-tools/README.md @@ -10,10 +10,6 @@ Each example uses the `subdirectory/index.ts` structure required for tool discov Minimal example showing the basic structure of a custom tool. -### question/ - -Demonstrates `pi.ui.select()` for asking the user questions with options. - ### todo/ Full-featured example demonstrating: @@ -23,17 +19,6 @@ Full-featured example demonstrating: - Proper branching support via details storage - State management without external files -### subagent/ - -Delegate tasks to specialized subagents with isolated context windows. Includes: - -- `index.ts` - The custom tool (single, parallel, and chain modes) -- `agents.ts` - Agent discovery helper -- `agents/` - Sample agent definitions (scout, planner, reviewer, worker) -- `commands/` - Workflow presets (/implement, /scout-and-plan, /implement-and-review) - -See [subagent/README.md](subagent/README.md) for full documentation. - ## Usage ```bash diff --git a/packages/coding-agent/examples/custom-tools/question/index.ts b/packages/coding-agent/examples/custom-tools/question/index.ts deleted file mode 100644 index 8b8a043d8..000000000 --- a/packages/coding-agent/examples/custom-tools/question/index.ts +++ /dev/null @@ -1,84 +0,0 @@ -/** - * Question Tool - Let the LLM ask the user a question with options - */ - -import type { CustomTool, CustomToolFactory } from "@oh-my-pi/pi-coding-agent"; - -interface QuestionDetails { - question: string; - options: string[]; - answer: string | null; -} - -const factory: CustomToolFactory = (pi) => { - const { Type } = pi.typebox; - const { Text } = pi.pi; - - const QuestionParams = Type.Object({ - question: Type.String({ description: "The question to ask the user" }), - options: Type.Array(Type.String(), { description: "Options for the user to choose from" }), - }); - - const tool: CustomTool = { - name: "question", - label: "Question", - description: "Ask the user a question and let them pick from options. Use when you need user input to proceed.", - parameters: QuestionParams, - - async execute(_toolCallId, params, _onUpdate, _ctx, _signal) { - if (!pi.hasUI) { - return { - content: [{ type: "text", text: "Error: UI not available (running in non-interactive mode)" }], - details: { question: params.question, options: params.options, answer: null }, - }; - } - - if (params.options.length === 0) { - return { - content: [{ type: "text", text: "Error: No options provided" }], - details: { question: params.question, options: [], answer: null }, - }; - } - - const answer = await pi.ui.select(params.question, params.options); - - if (answer === undefined) { - return { - content: [{ type: "text", text: "User cancelled the selection" }], - details: { question: params.question, options: params.options, answer: null }, - }; - } - - return { - content: [{ type: "text", text: `User selected: ${answer}` }], - details: { question: params.question, options: params.options, answer }, - }; - }, - - renderCall(args, theme) { - let text = theme.fg("toolTitle", theme.bold("question ")) + theme.fg("muted", args.question); - if (args.options?.length) { - text += `\n${theme.fg("dim", ` Options: ${args.options.join(", ")}`)}`; - } - return new Text(text, 0, 0); - }, - - renderResult(result, _options, theme) { - const { details } = result; - if (!details) { - const text = result.content[0]; - return new Text(text?.type === "text" ? text.text : "", 0, 0); - } - - if (details.answer === null) { - return new Text(theme.fg("warning", "Cancelled"), 0, 0); - } - - return new Text(theme.fg("success", "✓ ") + theme.fg("accent", details.answer), 0, 0); - }, - }; - - return tool; -}; - -export default factory; diff --git a/packages/coding-agent/examples/custom-tools/subagent/README.md b/packages/coding-agent/examples/custom-tools/subagent/README.md deleted file mode 100644 index f312a9f9e..000000000 --- a/packages/coding-agent/examples/custom-tools/subagent/README.md +++ /dev/null @@ -1,172 +0,0 @@ -# Subagent Example - -Delegate tasks to specialized subagents with isolated context windows. - -## Features - -- **Isolated context**: Each subagent runs in a separate `omp` process -- **Streaming output**: See tool calls and progress as they happen -- **Parallel streaming**: All parallel tasks stream updates simultaneously -- **Markdown rendering**: Final output rendered with proper formatting (expanded view) -- **Usage tracking**: Shows turns, tokens, cost, and context usage per agent -- **Abort support**: Ctrl+C propagates to kill subagent processes - -## Structure - -``` -subagent/ -├── README.md # This file -├── subagent.ts # The custom tool (entry point) -├── agents.ts # Agent discovery logic -├── agents/ # Sample agent definitions -│ ├── scout.md # Fast recon, returns compressed context -│ ├── planner.md # Creates implementation plans -│ ├── reviewer.md # Code review -│ └── worker.md # General-purpose (full capabilities) -└── commands/ # Workflow presets - ├── implement.md # scout -> planner -> worker - ├── scout-and-plan.md # scout -> planner (no implementation) - └── implement-and-review.md # worker -> reviewer -> worker -``` - -## Installation - -From the repository root, symlink the files: - -```bash -# Symlink the tool (must be in a subdirectory with index.ts) -mkdir -p ~/.omp/agent/tools/subagent -ln -sf "$(pwd)/packages/coding-agent/examples/custom-tools/subagent/subagent.ts" ~/.omp/agent/tools/subagent/index.ts -ln -sf "$(pwd)/packages/coding-agent/examples/custom-tools/subagent/agents.ts" ~/.omp/agent/tools/subagent/agents.ts - -# Symlink agents -mkdir -p ~/.omp/agent/agents -for f in packages/coding-agent/examples/custom-tools/subagent/agents/*.md; do - ln -sf "$(pwd)/$f" ~/.omp/agent/agents/$(basename "$f") -done - -# Symlink workflow commands -mkdir -p ~/.omp/agent/commands -for f in packages/coding-agent/examples/custom-tools/subagent/commands/*.md; do - ln -sf "$(pwd)/$f" ~/.omp/agent/commands/$(basename "$f") -done -``` - -## Security Model - -This tool executes a separate `omp` subprocess with a delegated system prompt and tool/model configuration. - -**Project-local agents** (`.omp/agents/*.md`) are repo-controlled prompts that can instruct the model to read files, run bash commands, etc. - -**Default behavior:** Only loads **user-level agents** from `~/.omp/agent/agents`. - -To enable project-local agents, pass `agentScope: "both"` (or `"project"`). Only do this for repositories you trust. - -When running interactively, the tool prompts for confirmation before running project-local agents. Set `confirmProjectAgents: false` to disable. - -## Usage - -### Single agent -``` -Use scout to find all authentication code -``` - -### Parallel execution -``` -Run 2 scouts in parallel: one to find models, one to find providers -``` - -### Chained workflow -``` -Use a chain: first have scout find the read tool, then have planner suggest improvements -``` - -### Workflow commands -``` -/implement add Redis caching to the session store -/scout-and-plan refactor auth to support OAuth -/implement-and-review add input validation to API endpoints -``` - -## Tool Modes - -| Mode | Parameter | Description | -|------|-----------|-------------| -| Single | `{ agent, task }` | One agent, one task | -| Parallel | `{ tasks: [...] }` | Multiple agents run concurrently (max 8, 4 concurrent) | -| Chain | `{ chain: [...] }` | Sequential with `{previous}` placeholder | - -## Output Display - -**Collapsed view** (default): -- Status icon (✓/✗/⏳) and agent name -- Last 5-10 items (tool calls and text) -- Usage stats: `3 turns ↑input ↓output RcacheRead WcacheWrite $cost ctx:contextTokens model` - -**Expanded view** (Ctrl+O): -- Full task text -- All tool calls with formatted arguments -- Final output rendered as Markdown -- Per-task usage (for chain/parallel) - -**Parallel mode streaming**: -- Shows all tasks with live status (⏳ running, ✓ done, ✗ failed) -- Updates as each task makes progress -- Shows "2/3 done, 1 running" status - -**Tool call formatting** (mimics built-in tools): -- `$ command` for bash -- `read ~/path:1-10` for read -- `grep /pattern/ in ~/path` for grep -- etc. - -## Agent Definitions - -Agents are markdown files with YAML frontmatter: - -```markdown ---- -name: my-agent -description: What this agent does -tools: read, grep, find, ls -model: claude-haiku-4-5 ---- - -System prompt for the agent goes here. -``` - -**Locations:** -- `~/.omp/agent/agents/*.md` - User-level (always loaded) -- `.omp/agents/*.md` - Project-level (only with `agentScope: "project"` or `"both"`) - -Project agents override user agents with the same name when `agentScope: "both"`. - -## Sample Agents - -| Agent | Purpose | Model | Tools | -|-------|---------|-------|-------| -| `scout` | Fast codebase recon | Haiku | read, grep, find, ls, bash | -| `planner` | Implementation plans | Sonnet | read, grep, find, ls | -| `reviewer` | Code review | Sonnet | read, grep, find, ls, bash | -| `worker` | General-purpose | Sonnet | (all default) | - -## Workflow Commands - -| Command | Flow | -|---------|------| -| `/implement ` | scout → planner → worker | -| `/scout-and-plan ` | scout → planner | -| `/implement-and-review ` | worker → reviewer → worker | - -## Error Handling - -- **Exit code != 0**: Tool returns error with stderr/output -- **stopReason "error"**: LLM error propagated with error message -- **stopReason "aborted"**: User abort (Ctrl+C) kills subprocess, throws error -- **Chain mode**: Stops at first failing step, reports which step failed - -## Limitations - -- Output truncated to last 10 items in collapsed view (expand to see all) -- Agents discovered fresh on each invocation (allows editing mid-session) -- Parallel mode limited to 8 tasks, 4 concurrent diff --git a/packages/coding-agent/examples/custom-tools/subagent/agents.ts b/packages/coding-agent/examples/custom-tools/subagent/agents.ts deleted file mode 100644 index 260e37684..000000000 --- a/packages/coding-agent/examples/custom-tools/subagent/agents.ts +++ /dev/null @@ -1,156 +0,0 @@ -/** - * Agent discovery and configuration - */ - -import * as fs from "node:fs"; -import * as os from "node:os"; -import * as path from "node:path"; - -export type AgentScope = "user" | "project" | "both"; - -export interface AgentConfig { - name: string; - description: string; - tools?: string[]; - model?: string; - systemPrompt: string; - source: "user" | "project"; - filePath: string; -} - -export interface AgentDiscoveryResult { - agents: AgentConfig[]; - projectAgentsDir: string | null; -} - -function parseFrontmatter(content: string): { frontmatter: Record; body: string } { - const frontmatter: Record = {}; - const normalized = content.replace(/\r\n/g, "\n"); - - if (!normalized.startsWith("---")) { - return { frontmatter, body: normalized }; - } - - const endIndex = normalized.indexOf("\n---", 3); - if (endIndex === -1) { - return { frontmatter, body: normalized }; - } - - const frontmatterBlock = normalized.slice(4, endIndex); - const body = normalized.slice(endIndex + 4).trim(); - - for (const line of frontmatterBlock.split("\n")) { - const match = line.match(/^([\w-]+):\s*(.*)$/); - if (match) { - let value = match[2].trim(); - if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) { - value = value.slice(1, -1); - } - frontmatter[match[1]] = value; - } - } - - return { frontmatter, body }; -} - -function loadAgentsFromDir(dir: string, source: "user" | "project"): AgentConfig[] { - const agents: AgentConfig[] = []; - - if (!fs.existsSync(dir)) { - return agents; - } - - let entries: fs.Dirent[]; - try { - entries = fs.readdirSync(dir, { withFileTypes: true }); - } catch { - return agents; - } - - for (const entry of entries) { - if (!entry.name.endsWith(".md")) continue; - if (!entry.isFile() && !entry.isSymbolicLink()) continue; - - const filePath = path.join(dir, entry.name); - let content: string; - try { - content = fs.readFileSync(filePath, "utf-8"); - } catch { - continue; - } - - const { frontmatter, body } = parseFrontmatter(content); - - if (!frontmatter.name || !frontmatter.description) { - continue; - } - - const tools = frontmatter.tools - ?.split(",") - .map((t) => t.trim()) - .filter(Boolean); - - agents.push({ - name: frontmatter.name, - description: frontmatter.description, - tools: tools && tools.length > 0 ? tools : undefined, - model: frontmatter.model, - systemPrompt: body, - source, - filePath, - }); - } - - return agents; -} - -function isDirectory(p: string): boolean { - try { - return fs.statSync(p).isDirectory(); - } catch { - return false; - } -} - -function findNearestProjectAgentsDir(cwd: string): string | null { - let currentDir = cwd; - while (true) { - const candidate = path.join(currentDir, ".omp", "agents"); - if (isDirectory(candidate)) return candidate; - - const parentDir = path.dirname(currentDir); - if (parentDir === currentDir) return null; - currentDir = parentDir; - } -} - -export function discoverAgents(cwd: string, scope: AgentScope): AgentDiscoveryResult { - const userDir = path.join(os.homedir(), ".omp", "agent", "agents"); - const projectAgentsDir = findNearestProjectAgentsDir(cwd); - - const userAgents = scope === "project" ? [] : loadAgentsFromDir(userDir, "user"); - const projectAgents = scope === "user" || !projectAgentsDir ? [] : loadAgentsFromDir(projectAgentsDir, "project"); - - const agentMap = new Map(); - - if (scope === "both") { - for (const agent of userAgents) agentMap.set(agent.name, agent); - for (const agent of projectAgents) agentMap.set(agent.name, agent); - } else if (scope === "user") { - for (const agent of userAgents) agentMap.set(agent.name, agent); - } else { - for (const agent of projectAgents) agentMap.set(agent.name, agent); - } - - return { agents: Array.from(agentMap.values()), projectAgentsDir }; -} - -export function formatAgentList(agents: AgentConfig[], maxItems: number): { text: string; remaining: number } { - if (agents.length === 0) return { text: "none", remaining: 0 }; - const listed = agents.slice(0, maxItems); - const remaining = agents.length - listed.length; - return { - text: listed.map((a) => `${a.name} (${a.source}): ${a.description}`).join("; "), - remaining, - }; -} diff --git a/packages/coding-agent/examples/custom-tools/subagent/agents/planner.md b/packages/coding-agent/examples/custom-tools/subagent/agents/planner.md deleted file mode 100644 index 7acc7187a..000000000 --- a/packages/coding-agent/examples/custom-tools/subagent/agents/planner.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -name: planner -description: Creates implementation plans from context and requirements -tools: read, grep, find, ls -model: claude-sonnet-4-5 ---- - -You are a planning specialist. You receive context (from a scout) and requirements, then produce a clear implementation plan. - -You must NOT make any changes. Only read, analyze, and plan. - -Input format you'll receive: -- Context/findings from a scout agent -- Original query or requirements - -Output format: - -## Goal -One sentence summary of what needs to be done. - -## Plan -Numbered steps, each small and actionable: -1. Step one - specific file/function to modify -2. Step two - what to add/change -3. ... - -## Files to Modify -- `path/to/file.ts` - what changes -- `path/to/other.ts` - what changes - -## New Files (if any) -- `path/to/new.ts` - purpose - -## Risks -Anything to watch out for. - -Keep the plan concrete. The worker agent will execute it verbatim. diff --git a/packages/coding-agent/examples/custom-tools/subagent/agents/scout.md b/packages/coding-agent/examples/custom-tools/subagent/agents/scout.md deleted file mode 100644 index c59611b7e..000000000 --- a/packages/coding-agent/examples/custom-tools/subagent/agents/scout.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -name: scout -description: Fast codebase recon that returns compressed context for handoff to other agents -tools: read, grep, find, ls, bash -model: claude-haiku-4-5 ---- - -You are a scout. Quickly investigate a codebase and return structured findings that another agent can use without re-reading everything. - -Your output will be passed to an agent who has NOT seen the files you explored. - -Thoroughness (infer from task, default medium): -- Quick: Targeted lookups, key files only -- Medium: Follow imports, read critical sections -- Thorough: Trace all dependencies, check tests/types - -Strategy: -1. grep/find to locate relevant code -2. Read key sections (not entire files) -3. Identify types, interfaces, key functions -4. Note dependencies between files - -Output format: - -## Files Retrieved -List with exact line ranges: -1. `path/to/file.ts` (lines 10-50) - Description of what's here -2. `path/to/other.ts` (lines 100-150) - Description -3. ... - -## Key Code -Critical types, interfaces, or functions: - -```typescript -interface Example { - // actual code from the files -} -``` - -```typescript -function keyFunction() { - // actual implementation -} -``` - -## Architecture -Brief explanation of how the pieces connect. - -## Start Here -Which file to look at first and why. diff --git a/packages/coding-agent/examples/custom-tools/subagent/agents/worker.md b/packages/coding-agent/examples/custom-tools/subagent/agents/worker.md deleted file mode 100644 index d9688355c..000000000 --- a/packages/coding-agent/examples/custom-tools/subagent/agents/worker.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -name: worker -description: General-purpose subagent with full capabilities, isolated context -model: claude-sonnet-4-5 ---- - -You are a worker agent with full capabilities. You operate in an isolated context window to handle delegated tasks without polluting the main conversation. - -Work autonomously to complete the assigned task. Use all available tools as needed. - -Output format when finished: - -## Completed -What was done. - -## Files Changed -- `path/to/file.ts` - what changed - -## Notes (if any) -Anything the main agent should know. - -If handing off to another agent (e.g. reviewer), include: -- Exact file paths changed -- Key functions/types touched (short list) diff --git a/packages/coding-agent/examples/custom-tools/subagent/commands/implement-and-review.md b/packages/coding-agent/examples/custom-tools/subagent/commands/implement-and-review.md deleted file mode 100644 index 6493b3d67..000000000 --- a/packages/coding-agent/examples/custom-tools/subagent/commands/implement-and-review.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -description: Worker implements, reviewer reviews, worker applies feedback ---- -Use the subagent tool with the chain parameter to execute this workflow: - -1. First, use the "worker" agent to implement: $@ -2. Then, use the "reviewer" agent to review the implementation from the previous step (use {previous} placeholder) -3. Finally, use the "worker" agent to apply the feedback from the review (use {previous} placeholder) - -Execute this as a chain, passing output between steps via {previous}. diff --git a/packages/coding-agent/examples/custom-tools/subagent/commands/implement.md b/packages/coding-agent/examples/custom-tools/subagent/commands/implement.md deleted file mode 100644 index 559da4d6c..000000000 --- a/packages/coding-agent/examples/custom-tools/subagent/commands/implement.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -description: Full implementation workflow - scout gathers context, planner creates plan, worker implements ---- -Use the subagent tool with the chain parameter to execute this workflow: - -1. First, use the "scout" agent to find all code relevant to: $@ -2. Then, use the "planner" agent to create an implementation plan for "$@" using the context from the previous step (use {previous} placeholder) -3. Finally, use the "worker" agent to implement the plan from the previous step (use {previous} placeholder) - -Execute this as a chain, passing output between steps via {previous}. diff --git a/packages/coding-agent/examples/custom-tools/subagent/commands/scout-and-plan.md b/packages/coding-agent/examples/custom-tools/subagent/commands/scout-and-plan.md deleted file mode 100644 index 093b63396..000000000 --- a/packages/coding-agent/examples/custom-tools/subagent/commands/scout-and-plan.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -description: Scout gathers context, planner creates implementation plan (no implementation) ---- -Use the subagent tool with the chain parameter to execute this workflow: - -1. First, use the "scout" agent to find all code relevant to: $@ -2. Then, use the "planner" agent to create an implementation plan for "$@" using the context from the previous step (use {previous} placeholder) - -Execute this as a chain, passing output between steps via {previous}. Do NOT implement - just return the plan. diff --git a/packages/coding-agent/examples/custom-tools/subagent/index.ts b/packages/coding-agent/examples/custom-tools/subagent/index.ts deleted file mode 100644 index e34a64bc8..000000000 --- a/packages/coding-agent/examples/custom-tools/subagent/index.ts +++ /dev/null @@ -1,1002 +0,0 @@ -/** - * Subagent Tool - Delegate tasks to specialized agents - * - * Spawns a separate `omp` process for each subagent invocation, - * giving it an isolated context window. - * - * Supports three modes: - * - Single: { agent: "name", task: "..." } - * - Parallel: { tasks: [{ agent: "name", task: "..." }, ...] } - * - Chain: { chain: [{ agent: "name", task: "... {previous} ..." }, ...] } - * - * Uses JSON mode to capture structured output from subagents. - */ - -import * as fs from "node:fs"; -import * as os from "node:os"; -import * as path from "node:path"; -import type { Message } from "@mariozechner/pi-ai"; -import type { AgentToolResult } from "@oh-my-pi/pi-agent-core"; -import type { CustomTool, CustomToolAPI, CustomToolFactory } from "@oh-my-pi/pi-coding-agent"; -import { type AgentConfig, type AgentScope, discoverAgents, formatAgentList } from "./agents"; - -const MAX_PARALLEL_TASKS = 8; -const MAX_CONCURRENCY = 4; -const MAX_AGENTS_IN_DESCRIPTION = 10; -const COLLAPSED_ITEM_COUNT = 10; - -function formatTokens(count: number): string { - if (count < 1000) return count.toString(); - if (count < 10000) return `${(count / 1000).toFixed(1)}k`; - if (count < 1000000) return `${Math.round(count / 1000)}k`; - return `${(count / 1000000).toFixed(1)}M`; -} - -function formatUsageStats( - usage: { - input: number; - output: number; - cacheRead: number; - cacheWrite: number; - cost: number; - contextTokens?: number; - turns?: number; - }, - model?: string, -): string { - const parts: string[] = []; - if (usage.turns) parts.push(`${usage.turns} turn${usage.turns > 1 ? "s" : ""}`); - if (usage.input) parts.push(`↑${formatTokens(usage.input)}`); - if (usage.output) parts.push(`↓${formatTokens(usage.output)}`); - if (usage.cacheRead) parts.push(`R${formatTokens(usage.cacheRead)}`); - if (usage.cacheWrite) parts.push(`W${formatTokens(usage.cacheWrite)}`); - if (usage.cost) parts.push(`$${usage.cost.toFixed(4)}`); - if (usage.contextTokens && usage.contextTokens > 0) { - parts.push(`ctx:${formatTokens(usage.contextTokens)}`); - } - if (model) parts.push(model); - return parts.join(" "); -} - -function formatToolCall( - toolName: string, - args: Record, - themeFg: (color: any, text: string) => string, -): string { - const shortenPath = (p: string) => { - const home = os.homedir(); - return p.startsWith(home) ? `~${p.slice(home.length)}` : p; - }; - - switch (toolName) { - case "bash": { - const command = (args.command as string) || "..."; - const preview = command.length > 60 ? `${command.slice(0, 60)}...` : command; - return themeFg("muted", "$ ") + themeFg("toolOutput", preview); - } - case "read": { - const rawPath = (args.file_path || args.path || "...") as string; - const filePath = shortenPath(rawPath); - const offset = args.offset as number | undefined; - const limit = args.limit as number | undefined; - let text = themeFg("accent", filePath); - if (offset !== undefined || limit !== undefined) { - const startLine = offset ?? 1; - const endLine = limit !== undefined ? startLine + limit - 1 : ""; - text += themeFg("warning", `:${startLine}${endLine ? `-${endLine}` : ""}`); - } - return themeFg("muted", "read ") + text; - } - case "write": { - const rawPath = (args.file_path || args.path || "...") as string; - const filePath = shortenPath(rawPath); - const content = (args.content || "") as string; - const lines = content.split("\n").length; - let text = themeFg("muted", "write ") + themeFg("accent", filePath); - if (lines > 1) text += themeFg("dim", ` (${lines} lines)`); - return text; - } - case "edit": { - const rawPath = (args.file_path || args.path || "...") as string; - return themeFg("muted", "edit ") + themeFg("accent", shortenPath(rawPath)); - } - case "ls": { - const rawPath = (args.path || ".") as string; - return themeFg("muted", "ls ") + themeFg("accent", shortenPath(rawPath)); - } - case "find": { - const pattern = (args.pattern || "*") as string; - const rawPath = (args.path || ".") as string; - return themeFg("muted", "find ") + themeFg("accent", pattern) + themeFg("dim", ` in ${shortenPath(rawPath)}`); - } - case "grep": { - const pattern = (args.pattern || "") as string; - const rawPath = (args.path || ".") as string; - return ( - themeFg("muted", "grep ") + - themeFg("accent", `/${pattern}/`) + - themeFg("dim", ` in ${shortenPath(rawPath)}`) - ); - } - default: { - const argsStr = JSON.stringify(args); - const preview = argsStr.length > 50 ? `${argsStr.slice(0, 50)}...` : argsStr; - return themeFg("accent", toolName) + themeFg("dim", ` ${preview}`); - } - } -} - -interface UsageStats { - input: number; - output: number; - cacheRead: number; - cacheWrite: number; - cost: number; - contextTokens: number; - turns: number; -} - -interface SingleResult { - agent: string; - agentSource: "user" | "project" | "unknown"; - task: string; - exitCode: number; - messages: Message[]; - stderr: string; - usage: UsageStats; - model?: string; - stopReason?: string; - errorMessage?: string; - step?: number; -} - -interface SubagentDetails { - mode: "single" | "parallel" | "chain"; - agentScope: AgentScope; - projectAgentsDir: string | null; - results: SingleResult[]; -} - -function getFinalOutput(messages: Message[]): string { - for (let i = messages.length - 1; i >= 0; i--) { - const msg = messages[i]; - if (msg.role === "assistant") { - for (const part of msg.content) { - if (part.type === "text") return part.text; - } - } - } - return ""; -} - -type DisplayItem = { type: "text"; text: string } | { type: "toolCall"; name: string; args: Record }; - -function getDisplayItems(messages: Message[]): DisplayItem[] { - const items: DisplayItem[] = []; - for (const msg of messages) { - if (msg.role === "assistant") { - for (const part of msg.content) { - if (part.type === "text") items.push({ type: "text", text: part.text }); - else if (part.type === "toolCall") items.push({ type: "toolCall", name: part.name, args: part.arguments }); - } - } - } - return items; -} - -async function mapWithConcurrencyLimit( - items: TIn[], - concurrency: number, - fn: (item: TIn, index: number) => Promise, -): Promise { - if (items.length === 0) return []; - const limit = Math.max(1, Math.min(concurrency, items.length)); - const results: TOut[] = new Array(items.length); - let nextIndex = 0; - const workers = new Array(limit).fill(null).map(async () => { - while (true) { - const current = nextIndex++; - if (current >= items.length) return; - results[current] = await fn(items[current], current); - } - }); - await Promise.all(workers); - return results; -} - -function writePromptToTempFile(agentName: string, prompt: string): { dir: string; filePath: string } { - const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "omp-subagent-")); - const safeName = agentName.replace(/[^\w.-]+/g, "_"); - const filePath = path.join(tmpDir, `prompt-${safeName}.md`); - fs.writeFileSync(filePath, prompt, { encoding: "utf-8", mode: 0o600 }); - return { dir: tmpDir, filePath }; -} - -type OnUpdateCallback = (partial: AgentToolResult) => void; - -async function runSingleAgent( - pi: CustomToolAPI, - agents: AgentConfig[], - agentName: string, - task: string, - cwd: string | undefined, - step: number | undefined, - signal: AbortSignal | undefined, - onUpdate: OnUpdateCallback | undefined, - makeDetails: (results: SingleResult[]) => SubagentDetails, -): Promise { - const agent = agents.find((a) => a.name === agentName); - - if (!agent) { - return { - agent: agentName, - agentSource: "unknown", - task, - exitCode: 1, - messages: [], - stderr: `Unknown agent: ${agentName}`, - usage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0, contextTokens: 0, turns: 0 }, - step, - }; - } - - const args: string[] = ["--mode", "json", "-p", "--no-session"]; - if (agent.model) args.push("--model", agent.model); - if (agent.tools && agent.tools.length > 0) args.push("--tools", agent.tools.join(",")); - - let tmpPromptDir: string | null = null; - let tmpPromptPath: string | null = null; - - const currentResult: SingleResult = { - agent: agentName, - agentSource: agent.source, - task, - exitCode: 0, - messages: [], - stderr: "", - usage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0, contextTokens: 0, turns: 0 }, - model: agent.model, - step, - }; - - const emitUpdate = () => { - if (onUpdate) { - onUpdate({ - content: [{ type: "text", text: getFinalOutput(currentResult.messages) || "(running...)" }], - details: makeDetails([currentResult]), - }); - } - }; - - try { - if (agent.systemPrompt.trim()) { - const tmp = writePromptToTempFile(agent.name, agent.systemPrompt); - tmpPromptDir = tmp.dir; - tmpPromptPath = tmp.filePath; - args.push("--append-system-prompt", tmpPromptPath); - } - - args.push(`Task: ${task}`); - let wasAborted = false; - - const exitCode = await new Promise((resolve) => { - const proc = Bun.spawn(["omp", ...args], { - cwd: cwd ?? pi.cwd, - stdin: "ignore", - stdout: "pipe", - stderr: "pipe", - }); - let buffer = ""; - - const processLine = (line: string) => { - if (!line.trim()) return; - let event: any; - try { - event = JSON.parse(line); - } catch { - return; - } - - if (event.type === "message_end" && event.message) { - const msg = event.message as Message; - currentResult.messages.push(msg); - - if (msg.role === "assistant") { - currentResult.usage.turns++; - const usage = msg.usage; - if (usage) { - currentResult.usage.input += usage.input || 0; - currentResult.usage.output += usage.output || 0; - currentResult.usage.cacheRead += usage.cacheRead || 0; - currentResult.usage.cacheWrite += usage.cacheWrite || 0; - currentResult.usage.cost += usage.cost?.total || 0; - currentResult.usage.contextTokens = usage.totalTokens || 0; - } - if (!currentResult.model && msg.model) currentResult.model = msg.model; - if (msg.stopReason) currentResult.stopReason = msg.stopReason; - if (msg.errorMessage) currentResult.errorMessage = msg.errorMessage; - } - emitUpdate(); - } - - if (event.type === "tool_result_end" && event.message) { - currentResult.messages.push(event.message as Message); - emitUpdate(); - } - }; - - (async () => { - const decoder = new TextDecoder(); - const reader = proc.stdout.getReader(); - try { - while (true) { - const { done, value } = await reader.read(); - if (done) break; - buffer += decoder.decode(value, { stream: true }); - const lines = buffer.split("\n"); - buffer = lines.pop() || ""; - for (const line of lines) processLine(line); - } - if (buffer.trim()) processLine(buffer); - } finally { - reader.releaseLock(); - } - })(); - - (async () => { - const decoder = new TextDecoder(); - const reader = proc.stderr.getReader(); - try { - while (true) { - const { done, value } = await reader.read(); - if (done) break; - currentResult.stderr += decoder.decode(value, { stream: true }); - } - } finally { - reader.releaseLock(); - } - })(); - - proc.exited.then((code) => { - resolve(code); - }); - - if (signal) { - const killProc = () => { - wasAborted = true; - proc.kill("SIGTERM"); - setTimeout(() => { - if (!proc.killed) proc.kill("SIGKILL"); - }, 5000); - }; - if (signal.aborted) killProc(); - else signal.addEventListener("abort", killProc, { once: true }); - } - }); - - currentResult.exitCode = exitCode; - if (wasAborted) throw new Error("Subagent was aborted"); - return currentResult; - } finally { - if (tmpPromptPath) - try { - fs.unlinkSync(tmpPromptPath); - } catch { - /* ignore */ - } - if (tmpPromptDir) - try { - fs.rmdirSync(tmpPromptDir); - } catch { - /* ignore */ - } - } -} - -const factory: CustomToolFactory = (pi) => { - const { Type } = pi.typebox; - const { StringEnum, Container, Markdown, Spacer, Text, getMarkdownTheme } = pi.pi; - - const TaskItem = Type.Object({ - agent: Type.String({ description: "Name of the agent to invoke" }), - task: Type.String({ description: "Task to delegate to the agent" }), - cwd: Type.Optional(Type.String({ description: "Working directory for the agent process" })), - }); - - const ChainItem = Type.Object({ - agent: Type.String({ description: "Name of the agent to invoke" }), - task: Type.String({ description: "Task with optional {previous} placeholder for prior output" }), - cwd: Type.Optional(Type.String({ description: "Working directory for the agent process" })), - }); - - const AgentScopeSchema = StringEnum(["user", "project", "both"] as const, { - description: 'Which agent directories to use. Default: "user". Use "both" to include project-local agents.', - default: "user", - }); - - const SubagentParams = Type.Object({ - agent: Type.Optional(Type.String({ description: "Name of the agent to invoke (for single mode)" })), - task: Type.Optional(Type.String({ description: "Task to delegate (for single mode)" })), - tasks: Type.Optional(Type.Array(TaskItem, { description: "Array of {agent, task} for parallel execution" })), - chain: Type.Optional(Type.Array(ChainItem, { description: "Array of {agent, task} for sequential execution" })), - agentScope: Type.Optional(AgentScopeSchema), - confirmProjectAgents: Type.Optional( - Type.Boolean({ description: "Prompt before running project-local agents. Default: true.", default: true }), - ), - cwd: Type.Optional(Type.String({ description: "Working directory for the agent process (single mode)" })), - }); - - const tool: CustomTool = { - name: "subagent", - label: "Subagent", - get description() { - const user = discoverAgents(pi.cwd, "user"); - const project = discoverAgents(pi.cwd, "project"); - const userList = formatAgentList(user.agents, MAX_AGENTS_IN_DESCRIPTION); - const projectList = formatAgentList(project.agents, MAX_AGENTS_IN_DESCRIPTION); - const userSuffix = userList.remaining > 0 ? `; ... and ${userList.remaining} more` : ""; - const projectSuffix = projectList.remaining > 0 ? `; ... and ${projectList.remaining} more` : ""; - const projectDirNote = project.projectAgentsDir ? ` (from ${project.projectAgentsDir})` : ""; - return [ - "Delegate tasks to specialized subagents with isolated context.", - "Modes: single (agent + task), parallel (tasks array), chain (sequential with {previous} placeholder).", - 'Default agent scope is "user" (from ~/.omp/agent/agents).', - 'To enable project-local agents in .omp/agents, set agentScope: "both" (or "project").', - `User agents: ${userList.text}${userSuffix}.`, - `Project agents${projectDirNote}: ${projectList.text}${projectSuffix}.`, - ].join(" "); - }, - parameters: SubagentParams, - - async execute(_toolCallId, params, onUpdate, _ctx, signal) { - const agentScope = (params.agentScope ?? "user") as AgentScope; - const discovery = discoverAgents(pi.cwd, agentScope); - const agents = discovery.agents; - const confirmProjectAgents = params.confirmProjectAgents ?? true; - - const hasChain = (params.chain?.length ?? 0) > 0; - const hasTasks = (params.tasks?.length ?? 0) > 0; - const hasSingle = Boolean(params.agent && params.task); - const modeCount = Number(hasChain) + Number(hasTasks) + Number(hasSingle); - - const makeDetails = - (mode: "single" | "parallel" | "chain") => - (results: SingleResult[]): SubagentDetails => ({ - mode, - agentScope, - projectAgentsDir: discovery.projectAgentsDir, - results, - }); - - if (modeCount !== 1) { - const available = agents.map((a) => `${a.name} (${a.source})`).join(", ") || "none"; - return { - content: [ - { - type: "text", - text: `Invalid parameters. Provide exactly one mode.\nAvailable agents: ${available}`, - }, - ], - details: makeDetails("single")([]), - }; - } - - if ((agentScope === "project" || agentScope === "both") && confirmProjectAgents && pi.hasUI) { - const requestedAgentNames = new Set(); - if (params.chain) for (const step of params.chain) requestedAgentNames.add(step.agent); - if (params.tasks) for (const t of params.tasks) requestedAgentNames.add(t.agent); - if (params.agent) requestedAgentNames.add(params.agent); - - const projectAgentsRequested = Array.from(requestedAgentNames) - .map((name) => agents.find((a) => a.name === name)) - .filter((a): a is AgentConfig => a?.source === "project"); - - if (projectAgentsRequested.length > 0) { - const names = projectAgentsRequested.map((a) => a.name).join(", "); - const dir = discovery.projectAgentsDir ?? "(unknown)"; - const ok = await pi.ui.confirm( - "Run project-local agents?", - `Agents: ${names}\nSource: ${dir}\n\nProject agents are repo-controlled. Only continue for trusted repositories.`, - ); - if (!ok) - return { - content: [{ type: "text", text: "Canceled: project-local agents not approved." }], - details: makeDetails(hasChain ? "chain" : hasTasks ? "parallel" : "single")([]), - }; - } - } - - if (params.chain && params.chain.length > 0) { - const results: SingleResult[] = []; - let previousOutput = ""; - - for (let i = 0; i < params.chain.length; i++) { - const step = params.chain[i]; - const taskWithContext = step.task.replace(/\{previous\}/g, previousOutput); - - // Create update callback that includes all previous results - const chainUpdate: OnUpdateCallback | undefined = onUpdate - ? (partial) => { - // Combine completed results with current streaming result - const currentResult = partial.details?.results[0]; - if (currentResult) { - const allResults = [...results, currentResult]; - onUpdate({ - content: partial.content, - details: makeDetails("chain")(allResults), - }); - } - } - : undefined; - - const result = await runSingleAgent( - pi, - agents, - step.agent, - taskWithContext, - step.cwd, - i + 1, - signal, - chainUpdate, - makeDetails("chain"), - ); - results.push(result); - - const isError = - result.exitCode !== 0 || result.stopReason === "error" || result.stopReason === "aborted"; - if (isError) { - const errorMsg = - result.errorMessage || result.stderr || getFinalOutput(result.messages) || "(no output)"; - return { - content: [{ type: "text", text: `Chain stopped at step ${i + 1} (${step.agent}): ${errorMsg}` }], - details: makeDetails("chain")(results), - isError: true, - }; - } - previousOutput = getFinalOutput(result.messages); - } - return { - content: [{ type: "text", text: getFinalOutput(results[results.length - 1].messages) || "(no output)" }], - details: makeDetails("chain")(results), - }; - } - - if (params.tasks && params.tasks.length > 0) { - if (params.tasks.length > MAX_PARALLEL_TASKS) - return { - content: [ - { - type: "text", - text: `Too many parallel tasks (${params.tasks.length}). Max is ${MAX_PARALLEL_TASKS}.`, - }, - ], - details: makeDetails("parallel")([]), - }; - - // Track all results for streaming updates - const allResults: SingleResult[] = new Array(params.tasks.length); - - // Initialize placeholder results - for (let i = 0; i < params.tasks.length; i++) { - allResults[i] = { - agent: params.tasks[i].agent, - agentSource: "unknown", - task: params.tasks[i].task, - exitCode: -1, // -1 = still running - messages: [], - stderr: "", - usage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0, contextTokens: 0, turns: 0 }, - }; - } - - const emitParallelUpdate = () => { - if (onUpdate) { - const running = allResults.filter((r) => r.exitCode === -1).length; - const done = allResults.filter((r) => r.exitCode !== -1).length; - onUpdate({ - content: [ - { type: "text", text: `Parallel: ${done}/${allResults.length} done, ${running} running...` }, - ], - details: makeDetails("parallel")([...allResults]), - }); - } - }; - - const results = await mapWithConcurrencyLimit(params.tasks, MAX_CONCURRENCY, async (t, index) => { - const result = await runSingleAgent( - pi, - agents, - t.agent, - t.task, - t.cwd, - undefined, - signal, - // Per-task update callback - (partial) => { - if (partial.details?.results[0]) { - allResults[index] = partial.details.results[0]; - emitParallelUpdate(); - } - }, - makeDetails("parallel"), - ); - allResults[index] = result; - emitParallelUpdate(); - return result; - }); - - const successCount = results.filter((r) => r.exitCode === 0).length; - const summaries = results.map((r) => { - const output = getFinalOutput(r.messages); - const preview = output.slice(0, 100) + (output.length > 100 ? "..." : ""); - return `[${r.agent}] ${r.exitCode === 0 ? "completed" : "failed"}: ${preview || "(no output)"}`; - }); - return { - content: [ - { - type: "text", - text: `Parallel: ${successCount}/${results.length} succeeded\n\n${summaries.join("\n\n")}`, - }, - ], - details: makeDetails("parallel")(results), - }; - } - - if (params.agent && params.task) { - const result = await runSingleAgent( - pi, - agents, - params.agent, - params.task, - params.cwd, - undefined, - signal, - onUpdate, - makeDetails("single"), - ); - const isError = result.exitCode !== 0 || result.stopReason === "error" || result.stopReason === "aborted"; - if (isError) { - const errorMsg = - result.errorMessage || result.stderr || getFinalOutput(result.messages) || "(no output)"; - return { - content: [{ type: "text", text: `Agent ${result.stopReason || "failed"}: ${errorMsg}` }], - details: makeDetails("single")([result]), - isError: true, - }; - } - return { - content: [{ type: "text", text: getFinalOutput(result.messages) || "(no output)" }], - details: makeDetails("single")([result]), - }; - } - - const available = agents.map((a) => `${a.name} (${a.source})`).join(", ") || "none"; - return { - content: [{ type: "text", text: `Invalid parameters. Available agents: ${available}` }], - details: makeDetails("single")([]), - }; - }, - - renderCall(args, theme) { - const scope = (args.agentScope ?? "user") as AgentScope; - if (args.chain && args.chain.length > 0) { - let text = - theme.fg("toolTitle", theme.bold("subagent ")) + - theme.fg("accent", `chain (${args.chain.length} steps)`) + - theme.fg("muted", ` [${scope}]`); - for (let i = 0; i < Math.min(args.chain.length, 3); i++) { - const step = args.chain[i]; - // Clean up {previous} placeholder for display - const cleanTask = step.task.replace(/\{previous\}/g, "").trim(); - const preview = cleanTask.length > 40 ? `${cleanTask.slice(0, 40)}...` : cleanTask; - text += - "\n " + - theme.fg("muted", `${i + 1}.`) + - " " + - theme.fg("accent", step.agent) + - theme.fg("dim", ` ${preview}`); - } - if (args.chain.length > 3) text += `\n ${theme.fg("muted", `... +${args.chain.length - 3} more`)}`; - return new Text(text, 0, 0); - } - if (args.tasks && args.tasks.length > 0) { - let text = - theme.fg("toolTitle", theme.bold("subagent ")) + - theme.fg("accent", `parallel (${args.tasks.length} tasks)`) + - theme.fg("muted", ` [${scope}]`); - for (const t of args.tasks.slice(0, 3)) { - const preview = t.task.length > 40 ? `${t.task.slice(0, 40)}...` : t.task; - text += `\n ${theme.fg("accent", t.agent)}${theme.fg("dim", ` ${preview}`)}`; - } - if (args.tasks.length > 3) text += `\n ${theme.fg("muted", `... +${args.tasks.length - 3} more`)}`; - return new Text(text, 0, 0); - } - const agentName = args.agent || "..."; - const preview = args.task ? (args.task.length > 60 ? `${args.task.slice(0, 60)}...` : args.task) : "..."; - let text = - theme.fg("toolTitle", theme.bold("subagent ")) + - theme.fg("accent", agentName) + - theme.fg("muted", ` [${scope}]`); - text += `\n ${theme.fg("dim", preview)}`; - return new Text(text, 0, 0); - }, - - renderResult(result, { expanded }, theme) { - const { details } = result; - if (!details || details.results.length === 0) { - const text = result.content[0]; - return new Text(text?.type === "text" ? text.text : "(no output)", 0, 0); - } - - const mdTheme = getMarkdownTheme(); - - const renderDisplayItems = (items: DisplayItem[], limit?: number) => { - const toShow = limit ? items.slice(-limit) : items; - const skipped = limit && items.length > limit ? items.length - limit : 0; - let text = ""; - if (skipped > 0) text += theme.fg("muted", `... ${skipped} earlier items\n`); - for (const item of toShow) { - if (item.type === "text") { - const preview = expanded ? item.text : item.text.split("\n").slice(0, 3).join("\n"); - text += `${theme.fg("toolOutput", preview)}\n`; - } else { - text += `${theme.fg("muted", "→ ") + formatToolCall(item.name, item.args, theme.fg.bind(theme))}\n`; - } - } - return text.trimEnd(); - }; - - if (details.mode === "single" && details.results.length === 1) { - const r = details.results[0]; - const isError = r.exitCode !== 0 || r.stopReason === "error" || r.stopReason === "aborted"; - const icon = isError ? theme.fg("error", "✗") : theme.fg("success", "✓"); - const displayItems = getDisplayItems(r.messages); - const finalOutput = getFinalOutput(r.messages); - - if (expanded) { - const container = new Container(); - let header = `${icon} ${theme.fg("toolTitle", theme.bold(r.agent))}${theme.fg( - "muted", - ` (${r.agentSource})`, - )}`; - if (isError && r.stopReason) header += ` ${theme.fg("error", `[${r.stopReason}]`)}`; - container.addChild(new Text(header, 0, 0)); - if (isError && r.errorMessage) - container.addChild(new Text(theme.fg("error", `Error: ${r.errorMessage}`), 0, 0)); - container.addChild(new Spacer(1)); - container.addChild(new Text(theme.fg("muted", "─── Task ───"), 0, 0)); - container.addChild(new Text(theme.fg("dim", r.task), 0, 0)); - container.addChild(new Spacer(1)); - container.addChild(new Text(theme.fg("muted", "─── Output ───"), 0, 0)); - if (displayItems.length === 0 && !finalOutput) { - container.addChild(new Text(theme.fg("muted", "(no output)"), 0, 0)); - } else { - for (const item of displayItems) { - if (item.type === "toolCall") - container.addChild( - new Text( - theme.fg("muted", "→ ") + formatToolCall(item.name, item.args, theme.fg.bind(theme)), - 0, - 0, - ), - ); - } - if (finalOutput) { - container.addChild(new Spacer(1)); - container.addChild(new Markdown(finalOutput.trim(), 0, 0, mdTheme)); - } - } - const usageStr = formatUsageStats(r.usage, r.model); - if (usageStr) { - container.addChild(new Spacer(1)); - container.addChild(new Text(theme.fg("dim", usageStr), 0, 0)); - } - return container; - } - - let text = `${icon} ${theme.fg("toolTitle", theme.bold(r.agent))}${theme.fg("muted", ` (${r.agentSource})`)}`; - if (isError && r.stopReason) text += ` ${theme.fg("error", `[${r.stopReason}]`)}`; - if (isError && r.errorMessage) text += `\n${theme.fg("error", `Error: ${r.errorMessage}`)}`; - else if (displayItems.length === 0) text += `\n${theme.fg("muted", "(no output)")}`; - else { - text += `\n${renderDisplayItems(displayItems, COLLAPSED_ITEM_COUNT)}`; - if (displayItems.length > COLLAPSED_ITEM_COUNT) text += `\n${theme.fg("muted", "(Ctrl+O to expand)")}`; - } - const usageStr = formatUsageStats(r.usage, r.model); - if (usageStr) text += `\n${theme.fg("dim", usageStr)}`; - return new Text(text, 0, 0); - } - - const aggregateUsage = (results: SingleResult[]) => { - const total = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0, turns: 0 }; - for (const r of results) { - total.input += r.usage.input; - total.output += r.usage.output; - total.cacheRead += r.usage.cacheRead; - total.cacheWrite += r.usage.cacheWrite; - total.cost += r.usage.cost; - total.turns += r.usage.turns; - } - return total; - }; - - if (details.mode === "chain") { - const successCount = details.results.filter((r) => r.exitCode === 0).length; - const icon = successCount === details.results.length ? theme.fg("success", "✓") : theme.fg("error", "✗"); - - if (expanded) { - const container = new Container(); - container.addChild( - new Text( - icon + - " " + - theme.fg("toolTitle", theme.bold("chain ")) + - theme.fg("accent", `${successCount}/${details.results.length} steps`), - 0, - 0, - ), - ); - - for (const r of details.results) { - const rIcon = r.exitCode === 0 ? theme.fg("success", "✓") : theme.fg("error", "✗"); - const displayItems = getDisplayItems(r.messages); - const finalOutput = getFinalOutput(r.messages); - - container.addChild(new Spacer(1)); - container.addChild( - new Text( - `${theme.fg("muted", `─── Step ${r.step}: `) + theme.fg("accent", r.agent)} ${rIcon}`, - 0, - 0, - ), - ); - container.addChild(new Text(theme.fg("muted", "Task: ") + theme.fg("dim", r.task), 0, 0)); - - // Show tool calls - for (const item of displayItems) { - if (item.type === "toolCall") { - container.addChild( - new Text( - theme.fg("muted", "→ ") + formatToolCall(item.name, item.args, theme.fg.bind(theme)), - 0, - 0, - ), - ); - } - } - - // Show final output as markdown - if (finalOutput) { - container.addChild(new Spacer(1)); - container.addChild(new Markdown(finalOutput.trim(), 0, 0, mdTheme)); - } - - const stepUsage = formatUsageStats(r.usage, r.model); - if (stepUsage) container.addChild(new Text(theme.fg("dim", stepUsage), 0, 0)); - } - - const usageStr = formatUsageStats(aggregateUsage(details.results)); - if (usageStr) { - container.addChild(new Spacer(1)); - container.addChild(new Text(theme.fg("dim", `Total: ${usageStr}`), 0, 0)); - } - return container; - } - - // Collapsed view - let text = - icon + - " " + - theme.fg("toolTitle", theme.bold("chain ")) + - theme.fg("accent", `${successCount}/${details.results.length} steps`); - for (const r of details.results) { - const rIcon = r.exitCode === 0 ? theme.fg("success", "✓") : theme.fg("error", "✗"); - const displayItems = getDisplayItems(r.messages); - text += `\n\n${theme.fg("muted", `─── Step ${r.step}: `)}${theme.fg("accent", r.agent)} ${rIcon}`; - if (displayItems.length === 0) text += `\n${theme.fg("muted", "(no output)")}`; - else text += `\n${renderDisplayItems(displayItems, 5)}`; - } - const usageStr = formatUsageStats(aggregateUsage(details.results)); - if (usageStr) text += `\n\n${theme.fg("dim", `Total: ${usageStr}`)}`; - text += `\n${theme.fg("muted", "(Ctrl+O to expand)")}`; - return new Text(text, 0, 0); - } - - if (details.mode === "parallel") { - const running = details.results.filter((r) => r.exitCode === -1).length; - const successCount = details.results.filter((r) => r.exitCode === 0).length; - const failCount = details.results.filter((r) => r.exitCode > 0).length; - const isRunning = running > 0; - const icon = isRunning - ? theme.fg("warning", "⏳") - : failCount > 0 - ? theme.fg("warning", "◐") - : theme.fg("success", "✓"); - const status = isRunning - ? `${successCount + failCount}/${details.results.length} done, ${running} running` - : `${successCount}/${details.results.length} tasks`; - - if (expanded && !isRunning) { - const container = new Container(); - container.addChild( - new Text( - `${icon} ${theme.fg("toolTitle", theme.bold("parallel "))}${theme.fg("accent", status)}`, - 0, - 0, - ), - ); - - for (const r of details.results) { - const rIcon = r.exitCode === 0 ? theme.fg("success", "✓") : theme.fg("error", "✗"); - const displayItems = getDisplayItems(r.messages); - const finalOutput = getFinalOutput(r.messages); - - container.addChild(new Spacer(1)); - container.addChild( - new Text(`${theme.fg("muted", "─── ") + theme.fg("accent", r.agent)} ${rIcon}`, 0, 0), - ); - container.addChild(new Text(theme.fg("muted", "Task: ") + theme.fg("dim", r.task), 0, 0)); - - // Show tool calls - for (const item of displayItems) { - if (item.type === "toolCall") { - container.addChild( - new Text( - theme.fg("muted", "→ ") + formatToolCall(item.name, item.args, theme.fg.bind(theme)), - 0, - 0, - ), - ); - } - } - - // Show final output as markdown - if (finalOutput) { - container.addChild(new Spacer(1)); - container.addChild(new Markdown(finalOutput.trim(), 0, 0, mdTheme)); - } - - const taskUsage = formatUsageStats(r.usage, r.model); - if (taskUsage) container.addChild(new Text(theme.fg("dim", taskUsage), 0, 0)); - } - - const usageStr = formatUsageStats(aggregateUsage(details.results)); - if (usageStr) { - container.addChild(new Spacer(1)); - container.addChild(new Text(theme.fg("dim", `Total: ${usageStr}`), 0, 0)); - } - return container; - } - - // Collapsed view (or still running) - let text = `${icon} ${theme.fg("toolTitle", theme.bold("parallel "))}${theme.fg("accent", status)}`; - for (const r of details.results) { - const rIcon = - r.exitCode === -1 - ? theme.fg("warning", "⏳") - : r.exitCode === 0 - ? theme.fg("success", "✓") - : theme.fg("error", "✗"); - const displayItems = getDisplayItems(r.messages); - text += `\n\n${theme.fg("muted", "─── ")}${theme.fg("accent", r.agent)} ${rIcon}`; - if (displayItems.length === 0) - text += `\n${theme.fg("muted", r.exitCode === -1 ? "(running...)" : "(no output)")}`; - else text += `\n${renderDisplayItems(displayItems, 5)}`; - } - if (!isRunning) { - const usageStr = formatUsageStats(aggregateUsage(details.results)); - if (usageStr) text += `\n\n${theme.fg("dim", `Total: ${usageStr}`)}`; - } - if (!expanded) text += `\n${theme.fg("muted", "(Ctrl+O to expand)")}`; - return new Text(text, 0, 0); - } - - const text = result.content[0]; - return new Text(text?.type === "text" ? text.text : "(no output)", 0, 0); - }, - }; - - return tool; -}; - -export default factory; diff --git a/packages/coding-agent/examples/hooks/custom-compaction.ts b/packages/coding-agent/examples/hooks/custom-compaction.ts index 48d50f7d7..d736fcf70 100644 --- a/packages/coding-agent/examples/hooks/custom-compaction.ts +++ b/packages/coding-agent/examples/hooks/custom-compaction.ts @@ -42,9 +42,7 @@ export default function (pi: HookAPI) { const allMessages = [...messagesToSummarize, ...turnPrefixMessages]; ctx.ui.notify( - `Custom compaction: summarizing ${allMessages.length} messages (${tokensBefore.toLocaleString()} tokens) with ${ - model.id - }...`, + `Custom compaction: summarizing ${allMessages.length} messages (${tokensBefore.toLocaleString()} tokens) with ${model.id}...`, "info", ); diff --git a/packages/coding-agent/examples/sdk/05-tools.ts b/packages/coding-agent/examples/sdk/05-tools.ts deleted file mode 100644 index 46997e2ba..000000000 --- a/packages/coding-agent/examples/sdk/05-tools.ts +++ /dev/null @@ -1,94 +0,0 @@ -/** - * Tools Configuration - * - * Use built-in tool sets, individual tools, or add custom tools. - * - * IMPORTANT: When using a custom `cwd`, you must use the tool factory functions - * (createCodingTools, createReadOnlyTools, createReadTool, etc.) to ensure - * tools resolve paths relative to your cwd, not process.cwd(). - */ - -import { - bashTool, // read, bash, edit, write - uses process.cwd() - type CustomTool, - createAgentSession, - createBashTool, - createCodingTools, // Factory: creates tools for specific cwd - createGrepTool, - createReadTool, - grepTool, - readOnlyTools, // read, grep, find, ls - uses process.cwd() - readTool, - SessionManager, -} from "@oh-my-pi/pi-coding-agent"; -import { Type } from "@sinclair/typebox"; - -// Read-only mode (no edit/write) - uses process.cwd() -await createAgentSession({ - tools: readOnlyTools, - sessionManager: SessionManager.inMemory(), -}); -console.log("Read-only session created"); - -// Custom tool selection - uses process.cwd() -await createAgentSession({ - tools: [readTool, bashTool, grepTool], - sessionManager: SessionManager.inMemory(), -}); -console.log("Custom tools session created"); - -// With custom cwd - MUST use factory functions! -const customCwd = "/path/to/project"; -const customTools = await createCodingTools(customCwd); -await createAgentSession({ - cwd: customCwd, - tools: customTools, // Tools resolve paths relative to customCwd - sessionManager: SessionManager.inMemory(), -}); -console.log("Custom cwd session created"); - -// Or pick specific tools for custom cwd -const customReadTool = await createReadTool(customCwd); -const customBashTool = await createBashTool(customCwd); -const customGrepTool = await createGrepTool(customCwd); -await createAgentSession({ - cwd: customCwd, - tools: [customReadTool, customBashTool, customGrepTool], - sessionManager: SessionManager.inMemory(), -}); -console.log("Specific tools with custom cwd session created"); - -// Inline custom tool (needs TypeBox schema) -const weatherTool: CustomTool = { - name: "get_weather", - label: "Get Weather", - description: "Get current weather for a city", - parameters: Type.Object({ - city: Type.String({ description: "City name" }), - }), - execute: async (_toolCallId, params) => ({ - content: [{ type: "text", text: `Weather in ${(params as { city: string }).city}: 22°C, sunny` }], - details: {}, - }), -}; - -const { session } = await createAgentSession({ - customTools: [weatherTool], - sessionManager: SessionManager.inMemory(), -}); - -session.subscribe((event) => { - if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") { - process.stdout.write(event.assistantMessageEvent.delta); - } -}); - -await session.prompt("What's the weather in Tokyo?"); -console.log(); - -// Merge with discovered tools from cwd/.omp/tools and ~/.omp/agent/tools: -// const discovered = await discoverCustomTools(); -// customTools: [...discovered, { tool: myTool }] - -// Or add paths without replacing discovery: -// additionalCustomToolPaths: ["/extra/tools"] diff --git a/packages/coding-agent/examples/sdk/12-full-control.ts b/packages/coding-agent/examples/sdk/12-full-control.ts deleted file mode 100644 index 3530b5938..000000000 --- a/packages/coding-agent/examples/sdk/12-full-control.ts +++ /dev/null @@ -1,95 +0,0 @@ -/** - * Full Control - * - * Replace everything - no discovery, explicit configuration. - * - * IMPORTANT: When providing `tools` with a custom `cwd`, use the tool factory - * functions (createReadTool, createBashTool, etc.) to ensure tools resolve - * paths relative to your cwd. - */ - -import { getModel } from "@mariozechner/pi-ai"; -import { - AuthStorage, - type CustomTool, - createAgentSession, - createBashTool, - createReadTool, - type ExtensionFactory, - ModelRegistry, - SessionManager, - SettingsManager, -} from "@oh-my-pi/pi-coding-agent"; -import { Type } from "@sinclair/typebox"; - -// Custom auth storage location -const authStorage = new AuthStorage("/tmp/my-agent/auth.json"); - -// Runtime API key override (not persisted) -if (process.env.MY_ANTHROPIC_KEY) { - authStorage.setRuntimeApiKey("anthropic", process.env.MY_ANTHROPIC_KEY); -} - -// Model registry with no custom models.json -const modelRegistry = new ModelRegistry(authStorage); - -// Inline extension -const auditHook: ExtensionFactory = (api) => { - api.on("tool_call", async (event) => { - console.log(`[Audit] ${event.toolName}`); - return undefined; - }); -}; - -// Inline custom tool -const statusTool: CustomTool = { - name: "status", - label: "Status", - description: "Get system status", - parameters: Type.Object({}), - execute: async () => ({ - content: [{ type: "text", text: `Uptime: ${process.uptime()}s, Node: ${process.version}` }], - details: {}, - }), -}; - -const model = getModel("anthropic", "claude-opus-4-5"); -if (!model) throw new Error("Model not found"); - -// In-memory settings with overrides -const settingsManager = SettingsManager.inMemory({ - compaction: { enabled: false }, - retry: { enabled: true, maxRetries: 2 }, -}); - -// When using a custom cwd with explicit tools, use the factory functions -const cwd = process.cwd(); - -const { session } = await createAgentSession({ - cwd, - agentDir: "/tmp/my-agent", - model, - thinkingLevel: "off", - authStorage, - modelRegistry, - systemPrompt: `You are a minimal assistant. -Available: read, bash, status. Be concise.`, - // Use factory functions with the same cwd to ensure path resolution works correctly - tools: [createReadTool(cwd), createBashTool(cwd)], - customTools: [statusTool], - extensions: [auditHook], - skills: [], - contextFiles: [], - promptTemplates: [], - sessionManager: SessionManager.inMemory(), - settingsManager, -}); - -session.subscribe((event) => { - if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") { - process.stdout.write(event.assistantMessageEvent.delta); - } -}); - -await session.prompt("Get status and list files."); -console.log(); diff --git a/packages/coding-agent/examples/sdk/README.md b/packages/coding-agent/examples/sdk/README.md index 499209e94..824f11d00 100644 --- a/packages/coding-agent/examples/sdk/README.md +++ b/packages/coding-agent/examples/sdk/README.md @@ -44,12 +44,8 @@ import { buildSystemPrompt, ModelRegistry, SessionManager, - codingTools, - readOnlyTools, - readTool, - bashTool, - editTool, - writeTool, + BUILTIN_TOOLS, + createTools, } from "@oh-my-pi/pi-coding-agent"; // Auth and models setup @@ -70,8 +66,8 @@ const { session } = await createAgentSession({ modelRegistry, }); -// Read-only -const { session } = await createAgentSession({ tools: readOnlyTools, authStorage, modelRegistry }); +// Read-only tools +const { session } = await createAgentSession({ toolNames: ["read", "grep", "find", "ls"], authStorage, modelRegistry }); // In-memory const { session } = await createAgentSession({ @@ -90,7 +86,7 @@ const { session } = await createAgentSession({ authStorage: customAuth, modelRegistry: customRegistry, systemPrompt: "You are helpful.", - tools: [readTool, bashTool], + toolNames: ["read", "bash"], customTools: [{ tool: myTool }], hooks: [{ factory: myHook }], skills: [], @@ -119,7 +115,7 @@ await session.prompt("Hello"); | `model` | From settings/first available | Model to use | | `thinkingLevel` | From settings/"off" | off, low, medium, high | | `systemPrompt` | Discovered | String or `(default) => modified` | -| `tools` | `codingTools` | Built-in tools | +| `toolNames` | All built-in tools | Filter which tools to include | | `customTools` | Discovered | Replaces discovery | | `additionalCustomToolPaths` | `[]` | Merge with discovery | | `hooks` | Discovered | Replaces discovery | diff --git a/packages/coding-agent/package.json b/packages/coding-agent/package.json index de680ab52..dbd4c4cba 100644 --- a/packages/coding-agent/package.json +++ b/packages/coding-agent/package.json @@ -29,7 +29,7 @@ "CHANGELOG.md" ], "scripts": { - "check": "tsgo --noEmit", + "check": "tsgo -p tsconfig.check.json", "clean": "rm -rf dist", "build": "tsgo -p tsconfig.build.json && chmod +x dist/cli.js", "build:binary": "bun build --compile ./src/cli.ts --outfile dist/omp", diff --git a/packages/coding-agent/src/cli/args.ts b/packages/coding-agent/src/cli/args.ts index f185a7fc2..f361245d0 100644 --- a/packages/coding-agent/src/cli/args.ts +++ b/packages/coding-agent/src/cli/args.ts @@ -5,11 +5,12 @@ import type { ThinkingLevel } from "@oh-my-pi/pi-agent-core"; import chalk from "chalk"; import { APP_NAME, CONFIG_DIR_NAME, ENV_AGENT_DIR } from "../config"; -import { allTools, type ToolName } from "../core/tools/index"; +import { BUILTIN_TOOLS } from "../core/tools/index"; export type Mode = "text" | "json" | "rpc"; export interface Args { + cwd?: string; provider?: string; model?: string; smol?: string; @@ -27,7 +28,7 @@ export interface Args { session?: string; sessionDir?: string; models?: string[]; - tools?: ToolName[]; + tools?: string[]; hooks?: string[]; extensions?: string[]; print?: boolean; @@ -94,13 +95,15 @@ export function parseArgs(args: string[], extensionFlags?: Map s.trim()); } else if (arg === "--tools" && i + 1 < args.length) { const toolNames = args[++i].split(",").map((s) => s.trim()); - const validTools: ToolName[] = []; + const validTools: string[] = []; for (const name of toolNames) { - if (name in allTools) { - validTools.push(name as ToolName); + if (name in BUILTIN_TOOLS) { + validTools.push(name); } else { console.error( - chalk.yellow(`Warning: Unknown tool "${name}". Valid tools: ${Object.keys(allTools).join(", ")}`), + chalk.yellow( + `Warning: Unknown tool "${name}". Valid tools: ${Object.keys(BUILTIN_TOOLS).join(", ")}`, + ), ); } } diff --git a/packages/coding-agent/src/core/agent-session.ts b/packages/coding-agent/src/core/agent-session.ts index b7c0117ae..ec9512def 100644 --- a/packages/coding-agent/src/core/agent-session.ts +++ b/packages/coding-agent/src/core/agent-session.ts @@ -90,7 +90,7 @@ export interface AgentSessionConfig { /** Tool registry for LSP and settings */ toolRegistry?: Map; /** System prompt builder that can consider tool availability */ - rebuildSystemPrompt?: (toolNames: string[]) => string; + rebuildSystemPrompt?: (toolNames: string[], tools: Map) => string; /** TTSR manager for time-traveling stream rules */ ttsrManager?: TtsrManager; } @@ -222,7 +222,7 @@ export class AgentSession { // Tool registry and prompt builder for extensions private _toolRegistry: Map; - private _rebuildSystemPrompt: ((toolNames: string[]) => string) | undefined; + private _rebuildSystemPrompt: ((toolNames: string[], tools: Map) => string) | undefined; private _baseSystemPrompt: string; // TTSR manager for time-traveling stream rules @@ -603,7 +603,7 @@ export class AgentSession { // Rebuild base system prompt with new tool set if (this._rebuildSystemPrompt) { - this._baseSystemPrompt = this._rebuildSystemPrompt(validToolNames); + this._baseSystemPrompt = this._rebuildSystemPrompt(validToolNames, this._toolRegistry); this.agent.setSystemPrompt(this._baseSystemPrompt); } } diff --git a/packages/coding-agent/src/core/custom-tools/wrapper.ts b/packages/coding-agent/src/core/custom-tools/wrapper.ts index eab3ca934..90dcd97c4 100644 --- a/packages/coding-agent/src/core/custom-tools/wrapper.ts +++ b/packages/coding-agent/src/core/custom-tools/wrapper.ts @@ -16,7 +16,6 @@ export function wrapCustomTool(tool: CustomTool, getContext: () => CustomToolCon label: tool.label, description: tool.description, parameters: tool.parameters, - hidden: tool.hidden, execute: (toolCallId, params, signal, onUpdate, context) => tool.execute(toolCallId, params, onUpdate, context ?? getContext(), signal), renderCall: tool.renderCall ? (args, theme) => tool.renderCall?.(args, theme as Theme) : undefined, diff --git a/packages/coding-agent/src/core/extensions/index.ts b/packages/coding-agent/src/core/extensions/index.ts index 0ce363e25..33440b895 100644 --- a/packages/coding-agent/src/core/extensions/index.ts +++ b/packages/coding-agent/src/core/extensions/index.ts @@ -92,9 +92,4 @@ export { isReadToolResult, isWriteToolResult, } from "./types"; -export { - wrapRegisteredTool, - wrapRegisteredTools, - wrapToolsWithExtensions, - wrapToolWithExtensions, -} from "./wrapper"; +export { wrapRegisteredTool, wrapRegisteredTools, wrapToolWithExtensions } from "./wrapper"; diff --git a/packages/coding-agent/src/core/extensions/wrapper.ts b/packages/coding-agent/src/core/extensions/wrapper.ts index 8a766e519..8067dbbf9 100644 --- a/packages/coding-agent/src/core/extensions/wrapper.ts +++ b/packages/coding-agent/src/core/extensions/wrapper.ts @@ -138,10 +138,3 @@ export function wrapToolWithExtensions(tool: AgentTool, runner: Exten }, }; } - -/** - * Wrap all tools with extension callbacks. - */ -export function wrapToolsWithExtensions(tools: AgentTool[], runner: ExtensionRunner): AgentTool[] { - return tools.map((tool) => wrapToolWithExtensions(tool, runner)); -} diff --git a/packages/coding-agent/src/core/file-mentions.ts b/packages/coding-agent/src/core/file-mentions.ts index a9effa0f5..b0c77449e 100644 --- a/packages/coding-agent/src/core/file-mentions.ts +++ b/packages/coding-agent/src/core/file-mentions.ts @@ -6,9 +6,9 @@ * so the agent doesn't need to read them manually. */ +import path from "node:path"; import type { AgentMessage } from "@oh-my-pi/pi-agent-core"; import type { FileMentionMessage } from "./messages"; -import { createReadTool } from "./tools/read"; /** Regex to match @filepath patterns in text */ const FILE_MENTION_REGEX = /@((?:[^\s@]+\/)*[^\s@]+\.[a-zA-Z0-9]+)/g; @@ -26,17 +26,14 @@ export function extractFileMentions(text: string): string[] { export async function generateFileMentionMessages(filePaths: string[], cwd: string): Promise { if (filePaths.length === 0) return []; - const readTool = createReadTool(cwd); const files: FileMentionMessage["files"] = []; for (const filePath of filePaths) { try { - const result = await readTool.execute("auto-read", { path: filePath }); - const textContent = result.content.find((c) => c.type === "text"); - if (textContent && textContent.type === "text") { - const lineCount = textContent.text.split("\n").length; - files.push({ path: filePath, content: textContent.text, lineCount }); - } + const absolutePath = path.resolve(cwd, filePath); + const content = await Bun.file(absolutePath).text(); + const lineCount = content.split("\n").length; + files.push({ path: filePath, content, lineCount }); } catch { // File doesn't exist or isn't readable - skip silently } diff --git a/packages/coding-agent/src/core/sdk.ts b/packages/coding-agent/src/core/sdk.ts index 07dd6fc3c..60c43e862 100644 --- a/packages/coding-agent/src/core/sdk.ts +++ b/packages/coding-agent/src/core/sdk.ts @@ -18,7 +18,7 @@ * const session = await createAgentSession({ * model: myModel, * getApiKey: async () => process.env.MY_KEY, - * tools: [readTool, bashTool], + * toolNames: ["read", "bash", "edit", "write"], // Filter tools * extensions: [], * skills: [], * sessionFile: false, @@ -55,7 +55,7 @@ import { loadExtensionFromFactory, type ToolDefinition, wrapRegisteredTools, - wrapToolsWithExtensions, + wrapToolWithExtensions, } from "./extensions/index"; import { logger } from "./logger"; import { discoverAndLoadMCPTools, type MCPManager, type MCPToolsLoadResult } from "./mcp/index"; @@ -75,48 +75,34 @@ import { time } from "./timings"; import { createToolContextStore } from "./tools/context"; import { getGeminiImageTools } from "./tools/gemini-image"; import { - allTools, - applyBashInterception, - baseCodingToolNames, - bashTool, - codingTools, - createAllTools, + BUILTIN_TOOLS, createBashTool, - createCodingTools, createEditTool, createFindTool, createGitTool, createGrepTool, createLsTool, - createReadOnlyTools, createReadTool, - createRulebookTool, + createTools, createWriteTool, - editTool, filterRulebookRules, - findTool, getWebSearchTools, - gitTool, - grepTool, - lsTool, - readOnlyTools, - readTool, setPreferredImageProvider, setPreferredWebSearchProvider, type Tool, - type ToolName, + type ToolSession, warmupLspServers, - writeTool, } from "./tools/index"; import { createTtsrManager } from "./ttsr"; // Types - export interface CreateAgentSessionOptions { /** Working directory for project-local discovery. Default: process.cwd() */ cwd?: string; /** Global config directory. Default: ~/.omp/agent */ agentDir?: string; + /** Spawns to allow. Default: "*" */ + spawns?: string; /** Auth storage for credentials. Default: discoverAuthStorage(agentDir) */ authStorage?: AuthStorage; @@ -133,8 +119,6 @@ export interface CreateAgentSessionOptions { /** System prompt. String replaces default, function receives default and returns final. */ systemPrompt?: string | ((defaultPrompt: string) => string); - /** Built-in tools to use. Default: all coding tools (read, bash, edit, write, grep, find, ls, lsp, notebook, output, task, web_fetch, web_search) */ - tools?: Tool[]; /** Custom tools to register (in addition to built-in tools). Accepts both CustomTool and ToolDefinition. */ customTools?: (CustomTool | ToolDefinition)[]; /** Inline extensions (merged with discovery). */ @@ -163,7 +147,7 @@ export interface CreateAgentSessionOptions { enableMCP?: boolean; /** Tool names explicitly requested (enables disabled-by-default tools) */ - explicitTools?: string[]; + toolNames?: string[]; /** Session manager. Default: SessionManager.create(cwd) */ sessionManager?: SessionManager; @@ -208,21 +192,11 @@ export type { FileSlashCommand } from "./slash-commands"; export type { Tool } from "./tools/index"; export { - // Pre-built tools (use process.cwd()) - readTool, - bashTool, - editTool, - writeTool, - grepTool, - findTool, - gitTool, - lsTool, - codingTools, - readOnlyTools, - allTools as allBuiltInTools, - // Tool factories (for custom cwd) - createCodingTools, - createReadOnlyTools, + // Tool factories + BUILTIN_TOOLS, + createTools, + type ToolSession, + // Individual tool factories (for custom usage) createReadTool, createBashTool, createEditTool, @@ -426,7 +400,6 @@ function customToolToDefinition(tool: CustomTool): ToolDefinition { label: tool.label, description: tool.description, parameters: tool.parameters, - hidden: tool.hidden, execute: (toolCallId, params, onUpdate, ctx, signal) => tool.execute(toolCallId, params, onUpdate, createCustomToolContext(ctx), signal), onSession: tool.onSession ? (event, ctx) => tool.onSession?.(event, createCustomToolContext(ctx)) : undefined, @@ -509,7 +482,7 @@ function createCustomToolsExtension(tools: CustomTool[]): ExtensionFactory { * model: myModel, * getApiKey: async () => process.env.MY_KEY, * systemPrompt: 'You are helpful.', - * tools: [readTool, bashTool], + * tools: codingTools({ cwd: process.cwd() }), * skills: [], * sessionManager: SessionManager.inMemory(), * }); @@ -630,31 +603,19 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {} const contextFiles = options.contextFiles ?? discoverContextFiles(cwd, agentDir); time("discoverContextFiles"); - const sessionContext = { + const toolSession: ToolSession = { + cwd, + hasUI: options.hasUI ?? false, + rulebookRules, + eventBus, getSessionFile: () => sessionManager.getSessionFile() ?? null, + getSessionSpawns: () => options.spawns ?? "*", + settings: settingsManager, }; - const allBuiltInToolsMap = await createAllTools(cwd, sessionContext, { - lspFormatOnWrite: settingsManager.getLspFormatOnWrite(), - lspDiagnosticsOnWrite: settingsManager.getLspDiagnosticsOnWrite(), - lspDiagnosticsOnEdit: settingsManager.getLspDiagnosticsOnEdit(), - editFuzzyMatch: settingsManager.getEditFuzzyMatch(), - readAutoResizeImages: settingsManager.getImageAutoResize(), - }); + + const builtinTools = await createTools(toolSession, options.toolNames); time("createAllTools"); - // Determine which tools to include based on settings - let baseToolNames = options.tools - ? options.tools.map((t) => t.name).filter((n): n is ToolName => n in allBuiltInToolsMap) - : [...baseCodingToolNames]; - - // Filter out git tool if disabled in settings - if (!settingsManager.getGitToolEnabled()) { - baseToolNames = baseToolNames.filter((name) => name !== "git"); - } - - const initialActiveToolNames: ToolName[] = baseToolNames; - const initialActiveBuiltInTools = initialActiveToolNames.map((name) => allBuiltInToolsMap[name]); - // Discover MCP tools from .mcp.json files let mcpManager: MCPManager | undefined; const enableMCP = options.enableMCP ?? true; @@ -840,61 +801,30 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {} hasQueuedMessages: () => session.queuedMessageCount > 0, })); + // All built-in tools are active (conditional tools like git/ask return null from factory if disabled) const toolRegistry = new Map(); - for (const [name, tool] of Object.entries(allBuiltInToolsMap)) { - toolRegistry.set(name, tool as AgentTool); + for (const tool of builtinTools) { + toolRegistry.set(tool.name, tool as AgentTool); } - for (const tool of wrappedExtensionTools as AgentTool[]) { + for (const tool of wrappedExtensionTools) { toolRegistry.set(tool.name, tool); } - - let activeToolsArray: Tool[] = [...initialActiveBuiltInTools, ...wrappedExtensionTools]; - - if (rulebookRules.length > 0) { - activeToolsArray.push(createRulebookTool(rulebookRules)); - } - - if (options.explicitTools) { - const explicitSet = new Set(options.explicitTools); - activeToolsArray = activeToolsArray.filter((tool) => !tool.hidden || explicitSet.has(tool.name)); - } else { - activeToolsArray = activeToolsArray.filter((tool) => !tool.hidden); + if (extensionRunner) { + for (const tool of toolRegistry.values()) { + toolRegistry.set(tool.name, wrapToolWithExtensions(tool, extensionRunner)); + } } time("combineTools"); - if (settingsManager.getBashInterceptorEnabled()) { - activeToolsArray = applyBashInterception(activeToolsArray); - } - time("applyBashInterception"); - - let wrappedToolRegistry: Map | undefined; - if (extensionRunner) { - activeToolsArray = wrapToolsWithExtensions(activeToolsArray as AgentTool[], extensionRunner); - const allRegistryTools = Array.from(toolRegistry.values()); - const wrappedAllTools = wrapToolsWithExtensions(allRegistryTools, extensionRunner); - wrappedToolRegistry = new Map(); - for (const tool of wrappedAllTools) { - wrappedToolRegistry.set(tool.name, tool); - } - } - - const rebuildSystemPrompt = (toolNames: string[]): string => { - const validToolNames = toolNames.filter((n): n is ToolName => n in allBuiltInToolsMap); - const extraToolDescriptions = toolNames - .filter((name) => !(name in allBuiltInToolsMap)) - .map((name) => { - const tool = toolRegistry.get(name); - if (!tool) return null; - return { name, description: tool.description || tool.label || "Custom tool" }; - }) - .filter((tool): tool is { name: string; description: string } => tool !== null); + const rebuildSystemPrompt = (toolNames: string[], tools: Map): string => { + toolContextStore.setToolNames(toolNames); const defaultPrompt = buildSystemPromptInternal({ cwd, skills, contextFiles, - rulebookRules, - selectedTools: validToolNames, - extraToolDescriptions, + tools, + toolNames, + rules: rulebookRules, skillsSettings: settingsManager.getSkillsSettings(), }); @@ -906,9 +836,9 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {} cwd, skills, contextFiles, - rulebookRules, - selectedTools: validToolNames, - extraToolDescriptions, + tools, + toolNames, + rules: rulebookRules, skillsSettings: settingsManager.getSkillsSettings(), customPrompt: options.systemPrompt, }); @@ -916,7 +846,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {} return options.systemPrompt(defaultPrompt); }; - const systemPrompt = rebuildSystemPrompt(initialActiveToolNames); + const systemPrompt = rebuildSystemPrompt(Array.from(toolRegistry.keys()), toolRegistry); time("buildSystemPrompt"); const promptTemplates = options.promptTemplates ?? (await discoverPromptTemplates(cwd, agentDir)); @@ -936,7 +866,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {} systemPrompt, model, thinkingLevel, - tools: activeToolsArray, + tools: Array.from(toolRegistry.values()), }, convertToLlm, transformContext: extensionRunner @@ -984,7 +914,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {} customCommands: customCommandsResult.commands, skillsSettings: settingsManager.getSkillsSettings(), modelRegistry, - toolRegistry: wrappedToolRegistry ?? toolRegistry, + toolRegistry, rebuildSystemPrompt, ttsrManager, }); diff --git a/packages/coding-agent/src/core/system-prompt.ts b/packages/coding-agent/src/core/system-prompt.ts index 4390b1327..b0958d049 100644 --- a/packages/coding-agent/src/core/system-prompt.ts +++ b/packages/coding-agent/src/core/system-prompt.ts @@ -256,10 +256,10 @@ export function loadSystemPromptFiles(options: LoadContextFilesOptions = {}): st export interface BuildSystemPromptOptions { /** Custom system prompt (replaces default). */ customPrompt?: string; - /** Tools to include in prompt. Default: [read, bash, edit, write] */ - selectedTools?: ToolName[]; - /** Extra tool descriptions to include in prompt (non built-in tools). */ - extraToolDescriptions?: Array<{ name: string; description: string }>; + /** Tools to include in prompt. */ + tools?: Map; + /** Tool names to include in prompt. */ + toolNames?: string[]; /** Text to append to system prompt. */ appendSystemPrompt?: string; /** Skills settings for discovery. */ @@ -271,21 +271,21 @@ export interface BuildSystemPromptOptions { /** Pre-loaded skills (skips discovery if provided). */ skills?: Skill[]; /** Pre-loaded rulebook rules (rules with descriptions, excluding TTSR and always-apply). */ - rulebookRules?: Rule[]; + rules?: Rule[]; } /** Build the system prompt with tools, guidelines, and context */ export function buildSystemPrompt(options: BuildSystemPromptOptions = {}): string { const { customPrompt, - selectedTools, - extraToolDescriptions = [], + tools, appendSystemPrompt, skillsSettings, + toolNames, cwd, contextFiles: providedContextFiles, skills: providedSkills, - rulebookRules, + rules: rulebookRules, } = options; const resolvedCwd = cwd ?? process.cwd(); const resolvedCustomPrompt = resolvePromptInput(customPrompt, "system prompt"); @@ -311,6 +311,9 @@ export function buildSystemPrompt(options: BuildSystemPromptOptions = {}): strin // Resolve context files: use provided or discover const contextFiles = providedContextFiles ?? loadProjectContextFiles({ cwd: resolvedCwd }); + // Build tools list based on selected tools + const toolsList = toolNames?.map((name) => `- ${name}: ${toolDescriptions[name as ToolName]}`).join("\n") ?? ""; + // Resolve skills: use provided or discover const skills = providedSkills ?? @@ -335,9 +338,11 @@ export function buildSystemPrompt(options: BuildSystemPromptOptions = {}): strin } // Append custom tool descriptions if provided - if (extraToolDescriptions.length > 0) { - prompt += "\n\n# Additional Tools\n\n"; - prompt += extraToolDescriptions.map((tool) => `- ${tool.name}: ${tool.description}`).join("\n"); + if (tools && tools.size > 0) { + prompt += "\n\n# Tools\n\n"; + prompt += Array.from(tools.entries()) + .map(([name, { description }]) => `- ${name}: ${description}`) + .join("\n"); } // Append git context if in a git repo @@ -347,8 +352,7 @@ export function buildSystemPrompt(options: BuildSystemPromptOptions = {}): strin } // Append skills section (only if read tool is available) - const customPromptHasRead = !selectedTools || selectedTools.includes("read"); - if (customPromptHasRead && skills.length > 0) { + if (tools?.has("read") && skills.length > 0) { prompt += formatSkillsForPrompt(skills); } @@ -369,25 +373,16 @@ export function buildSystemPrompt(options: BuildSystemPromptOptions = {}): strin const docsPath = getDocsPath(); const examplesPath = getExamplesPath(); - // Build tools list based on selected tools - const tools = selectedTools || (["read", "bash", "edit", "write"] as ToolName[]); - const builtInToolsList = tools.map((t) => `- ${t}: ${toolDescriptions[t]}`).join("\n"); - const extraToolsList = - extraToolDescriptions.length > 0 - ? extraToolDescriptions.map((tool) => `- ${tool.name}: ${tool.description}`).join("\n") - : ""; - const toolsList = [builtInToolsList, extraToolsList].filter(Boolean).join("\n"); - // Generate anti-bash rules (returns null if not applicable) - const antiBashSection = generateAntiBashRules(tools); + const antiBashSection = generateAntiBashRules(Array.from(tools?.keys() ?? [])); // Build guidelines based on which tools are actually available const guidelinesList: string[] = []; - const hasBash = tools.includes("bash"); - const hasEdit = tools.includes("edit"); - const hasWrite = tools.includes("write"); - const hasRead = tools.includes("read"); + const hasBash = tools?.has("bash"); + const hasEdit = tools?.has("edit"); + const hasWrite = tools?.has("write"); + const hasRead = tools?.has("read"); // Read-only mode notice (no bash, edit, or write) if (!hasBash && !hasEdit && !hasWrite) { @@ -454,12 +449,6 @@ export function buildSystemPrompt(options: BuildSystemPromptOptions = {}): strin } } - // Append custom tool descriptions if provided - if (extraToolDescriptions.length > 0) { - prompt += "\n\n# Additional Tools\n\n"; - prompt += extraToolDescriptions.map((tool) => `- ${tool.name}: ${tool.description}`).join("\n"); - } - // Append git context if in a git repo const gitContext = loadGitContext(resolvedCwd); if (gitContext) { diff --git a/packages/coding-agent/src/core/tools/ask.ts b/packages/coding-agent/src/core/tools/ask.ts index 60d11055f..ad624ba6e 100644 --- a/packages/coding-agent/src/core/tools/ask.ts +++ b/packages/coding-agent/src/core/tools/ask.ts @@ -22,6 +22,7 @@ import { Type } from "@sinclair/typebox"; import { type Theme, theme } from "../../modes/interactive/theme/theme"; import askDescription from "../../prompts/tools/ask.md" with { type: "text" }; import type { RenderResultOptions } from "../custom-tools/types"; +import type { ToolSession } from "./index"; import { formatErrorMessage, formatMeta } from "./render-utils"; // ============================================================================= @@ -67,7 +68,10 @@ function getDoneOptionLabel(): string { // Tool Implementation // ============================================================================= -export function createAskTool(_cwd: string): AgentTool { +export function createAskTool(session: ToolSession): null | AgentTool { + if (!session.hasUI) { + return null; + } return { name: "ask", label: "Ask", @@ -193,8 +197,14 @@ export function createAskTool(_cwd: string): AgentTool null, + getSessionSpawns: () => "*", +}); // ============================================================================= // TUI Renderer @@ -225,10 +235,7 @@ export const askToolRenderer = { const opt = args.options[i]; const isLast = i === args.options.length - 1; const branch = isLast ? uiTheme.tree.last : uiTheme.tree.branch; - text += `\n ${uiTheme.fg("dim", branch)} ${uiTheme.fg( - "dim", - uiTheme.checkbox.unchecked, - )} ${uiTheme.fg("muted", opt.label)}`; + text += `\n ${uiTheme.fg("dim", branch)} ${uiTheme.fg("dim", uiTheme.checkbox.unchecked)} ${uiTheme.fg("muted", opt.label)}`; } } diff --git a/packages/coding-agent/src/core/tools/bash-interceptor.ts b/packages/coding-agent/src/core/tools/bash-interceptor.ts index dceef48fc..ab51a57e9 100644 --- a/packages/coding-agent/src/core/tools/bash-interceptor.ts +++ b/packages/coding-agent/src/core/tools/bash-interceptor.ts @@ -80,13 +80,13 @@ const forbiddenPatterns: Array<{ * @param availableTools Set of tool names that are available * @returns InterceptionResult indicating if the command should be blocked */ -export function checkBashInterception(command: string, availableTools: Set): InterceptionResult { +export function checkBashInterception(command: string, availableTools: string[]): InterceptionResult { // Normalize command for pattern matching const normalizedCommand = command.trim(); for (const { pattern, tool, message } of forbiddenPatterns) { // Only block if the suggested tool is actually available - if (!availableTools.has(tool)) { + if (!availableTools.includes(tool)) { continue; } @@ -106,8 +106,8 @@ export function checkBashInterception(command: string, availableTools: Set): InterceptionResult { - if (!availableTools.has("ls")) { +export function checkSimpleLsInterception(command: string, availableTools: string[]): InterceptionResult { + if (!availableTools.includes("ls")) { return { block: false }; } diff --git a/packages/coding-agent/src/core/tools/bash.ts b/packages/coding-agent/src/core/tools/bash.ts index 8891aba39..38d46fb20 100644 --- a/packages/coding-agent/src/core/tools/bash.ts +++ b/packages/coding-agent/src/core/tools/bash.ts @@ -1,4 +1,4 @@ -import type { AgentTool } from "@oh-my-pi/pi-agent-core"; +import type { AgentTool, AgentToolContext } from "@oh-my-pi/pi-agent-core"; import type { Component } from "@oh-my-pi/pi-tui"; import { Text } from "@oh-my-pi/pi-tui"; import { Type } from "@sinclair/typebox"; @@ -6,6 +6,8 @@ import type { Theme } from "../../modes/interactive/theme/theme"; import bashDescription from "../../prompts/tools/bash.md" with { type: "text" }; import { executeBash } from "../bash-executor"; import type { RenderResultOptions } from "../custom-tools/types"; +import { checkBashInterception, checkSimpleLsInterception } from "./bash-interceptor"; +import type { ToolSession } from "./index"; import { formatBytes, wrapBrackets } from "./render-utils"; import { DEFAULT_MAX_BYTES, formatSize, type TruncationResult, truncateTail } from "./truncate"; @@ -19,7 +21,7 @@ export interface BashToolDetails { fullOutputPath?: string; } -export function createBashTool(cwd: string): AgentTool { +export function createBashTool(session: ToolSession): AgentTool { return { name: "bash", label: "Bash", @@ -30,12 +32,25 @@ export function createBashTool(cwd: string): AgentTool { { command, timeout }: { command: string; timeout?: number }, signal?: AbortSignal, onUpdate?, + ctx?: AgentToolContext, ) => { + // Check interception if enabled and available tools are known + if (session.settings?.getBashInterceptorEnabled()) { + const interception = checkBashInterception(command, ctx?.toolNames ?? []); + if (interception.block) { + throw new Error(interception.message); + } + const lsInterception = checkSimpleLsInterception(command, ctx?.toolNames ?? []); + if (lsInterception.block) { + throw new Error(lsInterception.message); + } + } + // Track output for streaming updates let currentOutput = ""; const result = await executeBash(command, { - cwd, + cwd: session.cwd, timeout: timeout ? timeout * 1000 : undefined, // Convert to milliseconds signal, onChunk: (chunk) => { @@ -92,9 +107,6 @@ export function createBashTool(cwd: string): AgentTool { }; } -/** Default bash tool using process.cwd() - for backwards compatibility */ -export const bashTool = createBashTool(process.cwd()); - // ============================================================================= // TUI Renderer // ============================================================================= @@ -183,9 +195,7 @@ export const bashToolRenderer = { warnings.push(`Truncated: showing ${truncation.outputLines} of ${truncation.totalLines} lines`); } else { warnings.push( - `Truncated: ${truncation.outputLines} lines shown (${formatBytes( - truncation.maxBytes ?? DEFAULT_MAX_BYTES, - )} limit)`, + `Truncated: ${truncation.outputLines} lines shown (${formatBytes(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit)`, ); } } diff --git a/packages/coding-agent/src/core/tools/context.ts b/packages/coding-agent/src/core/tools/context.ts index 3738ca5e7..9804a4c53 100644 --- a/packages/coding-agent/src/core/tools/context.ts +++ b/packages/coding-agent/src/core/tools/context.ts @@ -6,27 +6,34 @@ declare module "@oh-my-pi/pi-agent-core" { interface AgentToolContext extends CustomToolContext { ui?: ExtensionUIContext; hasUI?: boolean; + toolNames?: string[]; } } export interface ToolContextStore { getContext(): AgentToolContext; setUIContext(uiContext: ExtensionUIContext, hasUI: boolean): void; + setToolNames(names: string[]): void; } export function createToolContextStore(getBaseContext: () => CustomToolContext): ToolContextStore { let uiContext: ExtensionUIContext | undefined; let hasUI = false; + let toolNames: string[] = []; return { getContext: () => ({ ...getBaseContext(), ui: uiContext, hasUI, + toolNames, }), setUIContext: (context, uiAvailable) => { uiContext = context; hasUI = uiAvailable; }, + setToolNames: (names) => { + toolNames = names; + }, }; } diff --git a/packages/coding-agent/src/core/tools/edit.ts b/packages/coding-agent/src/core/tools/edit.ts index df6f023c0..2573d6cb8 100644 --- a/packages/coding-agent/src/core/tools/edit.ts +++ b/packages/coding-agent/src/core/tools/edit.ts @@ -17,7 +17,8 @@ import { restoreLineEndings, stripBom, } from "./edit-diff"; -import { type FileDiagnosticsResult, type WritethroughCallback, writethroughNoop } from "./lsp/index"; +import type { ToolSession } from "./index"; +import { createLspWritethrough, type FileDiagnosticsResult } from "./lsp/index"; import { resolveToCwd } from "./path-utils"; import { formatDiagnostics, @@ -46,16 +47,11 @@ export interface EditToolDetails { diagnostics?: FileDiagnosticsResult; } -export interface EditToolOptions { - /** Whether to accept high-confidence fuzzy matches for whitespace/indentation (default: true) */ - fuzzyMatch?: boolean; - /** Writethrough callback to get LSP diagnostics after editing a file */ - writethrough?: WritethroughCallback; -} - -export function createEditTool(cwd: string, options: EditToolOptions = {}): AgentTool { - const allowFuzzy = options.fuzzyMatch ?? true; - const writethrough = options.writethrough ?? writethroughNoop; +export function createEditTool(session: ToolSession): AgentTool { + const allowFuzzy = session.settings?.getEditFuzzyMatch() ?? true; + const enableDiagnostics = session.settings?.getLspDiagnosticsOnEdit() ?? false; + const enableFormat = session.settings?.getLspFormatOnWrite() ?? true; + const writethrough = createLspWritethrough(session.cwd, { enableFormat, enableDiagnostics }); return { name: "edit", label: "Edit", @@ -71,7 +67,7 @@ export function createEditTool(cwd: string, options: EditToolOptions = {}): Agen throw new Error("Cannot edit Jupyter notebooks with the Edit tool. Use the NotebookEdit tool instead."); } - const absolutePath = resolveToCwd(path, cwd); + const absolutePath = resolveToCwd(path, session.cwd); const file = Bun.file(absolutePath); if (!(await file.exists())) { @@ -203,9 +199,6 @@ export function createEditTool(cwd: string, options: EditToolOptions = {}): Agen }; } -/** Default edit tool using process.cwd() - for backwards compatibility */ -export const editTool = createEditTool(process.cwd()); - // ============================================================================= // TUI Renderer // ============================================================================= diff --git a/packages/coding-agent/src/core/tools/exa/render.ts b/packages/coding-agent/src/core/tools/exa/render.ts index 4a4c25a90..6613efc09 100644 --- a/packages/coding-agent/src/core/tools/exa/render.ts +++ b/packages/coding-agent/src/core/tools/exa/render.ts @@ -78,10 +78,7 @@ export function renderExaResult( } if (remaining > 0) { - text += `\n ${uiTheme.fg("dim", uiTheme.tree.last)} ${uiTheme.fg( - "muted", - formatMoreItems(remaining, "line", uiTheme), - )}`; + text += `\n ${uiTheme.fg("dim", uiTheme.tree.last)} ${uiTheme.fg("muted", formatMoreItems(remaining, "line", uiTheme))}`; } return new Text(text, 0, 0); @@ -168,17 +165,11 @@ export function renderExaResult( text += `\n ${uiTheme.fg("dim", branch)} ${uiTheme.fg("accent", title)}${domainPart}`; if (res.url) { - text += `\n ${uiTheme.fg("dim", cont)} ${uiTheme.fg("dim", uiTheme.tree.hook)} ${uiTheme.fg( - "mdLinkUrl", - res.url, - )}`; + text += `\n ${uiTheme.fg("dim", cont)} ${uiTheme.fg("dim", uiTheme.tree.hook)} ${uiTheme.fg("mdLinkUrl", res.url)}`; } if (res.author) { - text += `\n ${uiTheme.fg("dim", cont)} ${uiTheme.fg("dim", uiTheme.tree.hook)} ${uiTheme.fg( - "muted", - `Author: ${res.author}`, - )}`; + text += `\n ${uiTheme.fg("dim", cont)} ${uiTheme.fg("dim", uiTheme.tree.hook)} ${uiTheme.fg("muted", `Author: ${res.author}`)}`; } if (res.publishedDate) { @@ -206,10 +197,7 @@ export function renderExaResult( } if (res.highlights?.length) { - text += `\n ${uiTheme.fg("dim", cont)} ${uiTheme.fg("dim", uiTheme.tree.hook)} ${uiTheme.fg( - "accent", - "Highlights", - )}`; + text += `\n ${uiTheme.fg("dim", cont)} ${uiTheme.fg("dim", uiTheme.tree.hook)} ${uiTheme.fg("accent", "Highlights")}`; const maxHighlights = Math.min(res.highlights.length, 3); for (let j = 0; j < maxHighlights; j++) { const h = res.highlights[j]; diff --git a/packages/coding-agent/src/core/tools/find.ts b/packages/coding-agent/src/core/tools/find.ts index bce425541..ddb653707 100644 --- a/packages/coding-agent/src/core/tools/find.ts +++ b/packages/coding-agent/src/core/tools/find.ts @@ -10,6 +10,7 @@ import findDescription from "../../prompts/tools/find.md" with { type: "text" }; import { ensureTool } from "../../utils/tools-manager"; import type { RenderResultOptions } from "../custom-tools/types"; import { untilAborted } from "../utils"; +import type { ToolSession } from "./index"; import { resolveToCwd } from "./path-utils"; import { formatCount, @@ -55,7 +56,7 @@ export interface FindToolDetails { error?: string; } -export function createFindTool(cwd: string): AgentTool { +export function createFindTool(session: ToolSession): AgentTool { return { name: "find", label: "Find", @@ -87,9 +88,9 @@ export function createFindTool(cwd: string): AgentTool { throw new Error("fd is not available and could not be downloaded"); } - const searchPath = resolveToCwd(searchDir || ".", cwd); + const searchPath = resolveToCwd(searchDir || ".", session.cwd); const scopePath = (() => { - const relative = path.relative(cwd, searchPath).replace(/\\/g, "/"); + const relative = path.relative(session.cwd, searchPath).replace(/\\/g, "/"); return relative.length === 0 ? "." : relative; })(); const effectiveLimit = limit ?? DEFAULT_LIMIT; @@ -261,9 +262,6 @@ export function createFindTool(cwd: string): AgentTool { }; } -/** Default find tool using process.cwd() - for backwards compatibility */ -export const findTool = createFindTool(process.cwd()); - // ============================================================================= // TUI Renderer // ============================================================================= @@ -332,10 +330,7 @@ export const findToolRenderer = { text += `\n ${uiTheme.fg("dim", branch)} ${uiTheme.fg("accent", displayLines[i])}`; } if (remaining > 0) { - text += `\n ${uiTheme.fg("dim", uiTheme.tree.last)} ${uiTheme.fg( - "muted", - formatMoreItems(remaining, "file", uiTheme), - )}`; + text += `\n ${uiTheme.fg("dim", uiTheme.tree.last)} ${uiTheme.fg("muted", formatMoreItems(remaining, "file", uiTheme))}`; } return new Text(text, 0, 0); } @@ -355,10 +350,7 @@ export const findToolRenderer = { const hasMoreFiles = files.length > maxFiles; const expandHint = formatExpandHint(expanded, hasMoreFiles, uiTheme); - let text = `${icon} ${uiTheme.fg("dim", summaryText)}${formatTruncationSuffix( - truncated, - uiTheme, - )}${scopeLabel}${expandHint}`; + let text = `${icon} ${uiTheme.fg("dim", summaryText)}${formatTruncationSuffix(truncated, uiTheme)}${scopeLabel}${expandHint}`; const truncationReasons: string[] = []; if (details?.resultLimitReached) { @@ -394,10 +386,7 @@ export const findToolRenderer = { } if (hasTruncation) { - text += `\n ${uiTheme.fg("dim", uiTheme.tree.last)} ${uiTheme.fg( - "warning", - `truncated: ${truncationReasons.join(", ")}`, - )}`; + text += `\n ${uiTheme.fg("dim", uiTheme.tree.last)} ${uiTheme.fg("warning", `truncated: ${truncationReasons.join(", ")}`)}`; } return new Text(text, 0, 0); diff --git a/packages/coding-agent/src/core/tools/git.ts b/packages/coding-agent/src/core/tools/git.ts index 27f3ac4b4..a3fcf4b9d 100644 --- a/packages/coding-agent/src/core/tools/git.ts +++ b/packages/coding-agent/src/core/tools/git.ts @@ -2,6 +2,7 @@ import type { AgentTool } from "@oh-my-pi/pi-agent-core"; import { type GitParams, gitTool as gitToolCore, type ToolResponse } from "@oh-my-pi/pi-git-tool"; import { type Static, Type } from "@sinclair/typebox"; import gitDescription from "../../prompts/tools/git.md" with { type: "text" }; +import type { ToolSession } from "./index"; const gitSchema = Type.Object({ operation: Type.Union([ @@ -192,7 +193,10 @@ const gitSchema = Type.Object({ export type GitToolDetails = ToolResponse; -export function createGitTool(cwd: string): AgentTool { +export function createGitTool(session: ToolSession): AgentTool | null { + if (session.settings?.getGitToolEnabled() === false) { + return null; + } return { name: "git", label: "Git", @@ -203,7 +207,7 @@ export function createGitTool(cwd: string): AgentTool null, + getSessionSpawns: () => null, +})!; diff --git a/packages/coding-agent/src/core/tools/grep.ts b/packages/coding-agent/src/core/tools/grep.ts index fdceda134..86d33b79f 100644 --- a/packages/coding-agent/src/core/tools/grep.ts +++ b/packages/coding-agent/src/core/tools/grep.ts @@ -9,6 +9,7 @@ import { getLanguageFromPath, type Theme } from "../../modes/interactive/theme/t import grepDescription from "../../prompts/tools/grep.md" with { type: "text" }; import { ensureTool } from "../../utils/tools-manager"; import type { RenderResultOptions } from "../custom-tools/types"; +import type { ToolSession } from "./index"; import { resolveToCwd } from "./path-utils"; import { formatCount, @@ -79,7 +80,7 @@ export interface GrepToolDetails { error?: string; } -export function createGrepTool(cwd: string): AgentTool { +export function createGrepTool(session: ToolSession): AgentTool { return { name: "grep", label: "Grep", @@ -127,9 +128,9 @@ export function createGrepTool(cwd: string): AgentTool { throw new Error("ripgrep (rg) is not available and could not be downloaded"); } - const searchPath = resolveToCwd(searchDir || ".", cwd); + const searchPath = resolveToCwd(searchDir || ".", session.cwd); const scopePath = (() => { - const relative = nodePath.relative(cwd, searchPath).replace(/\\/g, "/"); + const relative = nodePath.relative(session.cwd, searchPath).replace(/\\/g, "/"); return relative.length === 0 ? "." : relative; })(); let searchStat: Stats; @@ -595,9 +596,6 @@ export function createGrepTool(cwd: string): AgentTool { }; } -/** Default grep tool using process.cwd() - for backwards compatibility */ -export const grepTool = createGrepTool(process.cwd()); - // ============================================================================= // TUI Renderer // ============================================================================= @@ -681,10 +679,7 @@ export const grepToolRenderer = { } if (remaining > 0) { - text += `\n ${uiTheme.fg("dim", uiTheme.tree.last)} ${uiTheme.fg( - "muted", - formatMoreItems(remaining, "item", uiTheme), - )}`; + text += `\n ${uiTheme.fg("dim", uiTheme.tree.last)} ${uiTheme.fg("muted", formatMoreItems(remaining, "item", uiTheme))}`; } return new Text(text, 0, 0); @@ -715,10 +710,7 @@ export const grepToolRenderer = { const hasMoreFiles = fileEntries.length > maxFiles; const expandHint = formatExpandHint(expanded, hasMoreFiles, uiTheme); - let text = `${icon} ${uiTheme.fg("dim", summaryText)}${formatTruncationSuffix( - truncated, - uiTheme, - )}${scopeLabel}${expandHint}`; + let text = `${icon} ${uiTheme.fg("dim", summaryText)}${formatTruncationSuffix(truncated, uiTheme)}${scopeLabel}${expandHint}`; const truncationReasons: string[] = []; if (details?.matchLimitReached) { @@ -764,10 +756,7 @@ export const grepToolRenderer = { } if (hasTruncation) { - text += `\n ${uiTheme.fg("dim", uiTheme.tree.last)} ${uiTheme.fg( - "warning", - `truncated: ${truncationReasons.join(", ")}`, - )}`; + text += `\n ${uiTheme.fg("dim", uiTheme.tree.last)} ${uiTheme.fg("warning", `truncated: ${truncationReasons.join(", ")}`)}`; } return new Text(text, 0, 0); diff --git a/packages/coding-agent/src/core/tools/index.test.ts b/packages/coding-agent/src/core/tools/index.test.ts new file mode 100644 index 000000000..9fa362584 --- /dev/null +++ b/packages/coding-agent/src/core/tools/index.test.ts @@ -0,0 +1,180 @@ +import { describe, expect, it } from "bun:test"; +import { BUILTIN_TOOLS, createTools, HIDDEN_TOOLS, type ToolSession } from "./index"; + +function createTestSession(overrides: Partial = {}): ToolSession { + return { + cwd: "/tmp/test", + hasUI: false, + rulebookRules: [], + getSessionFile: () => null, + getSessionSpawns: () => "*", + ...overrides, + }; +} + +describe("createTools", () => { + it("creates all builtin tools by default", async () => { + const session = createTestSession(); + const tools = await createTools(session); + const names = tools.map((t) => t.name); + + // Core tools should always be present + expect(names).toContain("bash"); + expect(names).toContain("read"); + expect(names).toContain("edit"); + expect(names).toContain("write"); + expect(names).toContain("grep"); + expect(names).toContain("find"); + expect(names).toContain("ls"); + expect(names).toContain("lsp"); + expect(names).toContain("notebook"); + expect(names).toContain("task"); + expect(names).toContain("output"); + expect(names).toContain("web_fetch"); + expect(names).toContain("web_search"); + }); + + it("respects requested tool subset", async () => { + const session = createTestSession(); + const tools = await createTools(session, ["read", "write"]); + const names = tools.map((t) => t.name); + + expect(names).toEqual(["read", "write"]); + }); + + it("includes hidden tools when explicitly requested", async () => { + const session = createTestSession(); + const tools = await createTools(session, ["report_finding"]); + const names = tools.map((t) => t.name); + + expect(names).toEqual(["report_finding"]); + }); + + it("excludes ask tool when hasUI is false", async () => { + const session = createTestSession({ hasUI: false }); + const tools = await createTools(session); + const names = tools.map((t) => t.name); + + expect(names).not.toContain("ask"); + }); + + it("includes ask tool when hasUI is true", async () => { + const session = createTestSession({ hasUI: true }); + const tools = await createTools(session); + const names = tools.map((t) => t.name); + + expect(names).toContain("ask"); + }); + + it("excludes rulebook tool when no rules provided", async () => { + const session = createTestSession({ rulebookRules: [] }); + const tools = await createTools(session); + const names = tools.map((t) => t.name); + + expect(names).not.toContain("rulebook"); + }); + + it("includes rulebook tool when rules provided", async () => { + const session = createTestSession({ + rulebookRules: [ + { + path: "/test/rule.md", + name: "Test Rule", + content: "Test content", + description: "A test rule", + _source: { provider: "test", providerName: "Test", path: "/test", level: "project" }, + }, + ], + }); + const tools = await createTools(session); + const names = tools.map((t) => t.name); + + expect(names).toContain("rulebook"); + }); + + it("excludes git tool when disabled in settings", async () => { + const session = createTestSession({ + settings: { + getImageAutoResize: () => true, + getLspFormatOnWrite: () => true, + getLspDiagnosticsOnWrite: () => true, + getLspDiagnosticsOnEdit: () => false, + getEditFuzzyMatch: () => true, + getGitToolEnabled: () => false, + getBashInterceptorEnabled: () => true, + }, + }); + const tools = await createTools(session); + const names = tools.map((t) => t.name); + + expect(names).not.toContain("git"); + }); + + it("includes git tool when enabled in settings", async () => { + const session = createTestSession({ + settings: { + getImageAutoResize: () => true, + getLspFormatOnWrite: () => true, + getLspDiagnosticsOnWrite: () => true, + getLspDiagnosticsOnEdit: () => false, + getEditFuzzyMatch: () => true, + getGitToolEnabled: () => true, + getBashInterceptorEnabled: () => true, + }, + }); + const tools = await createTools(session); + const names = tools.map((t) => t.name); + + expect(names).toContain("git"); + }); + + it("includes git tool when no settings provided (default enabled)", async () => { + const session = createTestSession({ settings: undefined }); + const tools = await createTools(session); + const names = tools.map((t) => t.name); + + expect(names).toContain("git"); + }); + + it("always includes output tool when task tool is present", async () => { + const session = createTestSession(); + const tools = await createTools(session); + const names = tools.map((t) => t.name); + + // Both should be present together + expect(names).toContain("task"); + expect(names).toContain("output"); + }); + + it("BUILTIN_TOOLS contains all expected tools", () => { + const expectedTools = [ + "ask", + "bash", + "edit", + "find", + "git", + "grep", + "ls", + "lsp", + "notebook", + "output", + "read", + "rulebook", + "task", + "web_fetch", + "web_search", + "write", + ]; + + for (const tool of expectedTools) { + expect(BUILTIN_TOOLS).toHaveProperty(tool); + } + + // Ensure we haven't missed any + expect(Object.keys(BUILTIN_TOOLS).sort()).toEqual(expectedTools.sort()); + }); + + it("HIDDEN_TOOLS contains review tools", () => { + expect(Object.keys(HIDDEN_TOOLS).sort()).toEqual(["report_finding", "submit_review"]); + }); +}); diff --git a/packages/coding-agent/src/core/tools/index.ts b/packages/coding-agent/src/core/tools/index.ts index 78ebffbe2..2437a3f7f 100644 --- a/packages/coding-agent/src/core/tools/index.ts +++ b/packages/coding-agent/src/core/tools/index.ts @@ -1,14 +1,14 @@ export { type AskToolDetails, askTool, createAskTool } from "./ask"; -export { type BashToolDetails, bashTool, createBashTool } from "./bash"; -export { createEditTool, type EditToolOptions, editTool } from "./edit"; +export { type BashToolDetails, createBashTool } from "./bash"; +export { createEditTool } from "./edit"; // Exa MCP tools (22 tools) export { exaTools } from "./exa/index"; export type { ExaRenderDetails, ExaSearchResponse, ExaSearchResult } from "./exa/types"; -export { createFindTool, type FindToolDetails, findTool } from "./find"; +export { createFindTool, type FindToolDetails } from "./find"; export { setPreferredImageProvider } from "./gemini-image"; export { createGitTool, type GitToolDetails, gitTool } from "./git"; -export { createGrepTool, type GrepToolDetails, grepTool } from "./grep"; -export { createLsTool, type LsToolDetails, lsTool } from "./ls"; +export { createGrepTool, type GrepToolDetails } from "./grep"; +export { createLsTool, type LsToolDetails } from "./ls"; export { createLspTool, type FileDiagnosticsResult, @@ -20,14 +20,14 @@ export { lspTool, warmupLspServers, } from "./lsp/index"; -export { createNotebookTool, type NotebookToolDetails, notebookTool } from "./notebook"; -export { createOutputTool, type OutputToolDetails, outputTool } from "./output"; -export { createReadTool, type ReadToolDetails, type ReadToolOptions, readTool } from "./read"; -export { createReportFindingTool, createSubmitReviewTool, reportFindingTool, submitReviewTool } from "./review"; -export { createRulebookTool, filterRulebookRules, formatRulesForPrompt, type RulebookToolDetails } from "./rulebook"; +export { createNotebookTool, type NotebookToolDetails } from "./notebook"; +export { createOutputTool, type OutputToolDetails } from "./output"; +export { createReadTool, type ReadToolDetails } from "./read"; +export { reportFindingTool, submitReviewTool } from "./review"; +export { filterRulebookRules, formatRulesForPrompt, type RulebookToolDetails } from "./rulebook"; export { BUNDLED_AGENTS, createTaskTool, taskTool } from "./task/index"; export type { TruncationResult } from "./truncate"; -export { createWebFetchTool, type WebFetchToolDetails, webFetchCustomTool, webFetchTool } from "./web-fetch"; +export { createWebFetchTool, type WebFetchToolDetails } from "./web-fetch"; export { companyWebSearchTools, createWebSearchTool, @@ -47,247 +47,104 @@ export { webSearchLinkedinTool, webSearchTool, } from "./web-search/index"; -export { createWriteTool, type WriteToolDetails, type WriteToolOptions, writeTool } from "./write"; +export { createWriteTool, type WriteToolDetails } from "./write"; import type { AgentTool } from "@oh-my-pi/pi-agent-core"; -import { askTool, createAskTool } from "./ask"; -import { bashTool, createBashTool } from "./bash"; -import { checkBashInterception, checkSimpleLsInterception } from "./bash-interceptor"; -import { createEditTool, editTool } from "./edit"; -import { createFindTool, findTool } from "./find"; -import { createGitTool, gitTool } from "./git"; -import { createGrepTool, grepTool } from "./grep"; -import { createLsTool, lsTool } from "./ls"; -import { createLspTool, createLspWritethrough, lspTool } from "./lsp/index"; -import { createNotebookTool, notebookTool } from "./notebook"; -import { createOutputTool, outputTool } from "./output"; -import { createReadTool, readTool } from "./read"; -import { createReportFindingTool, createSubmitReviewTool, reportFindingTool, submitReviewTool } from "./review"; -import { createTaskTool, taskTool } from "./task/index"; -import { createWebFetchTool, webFetchTool } from "./web-fetch"; -import { createWebSearchTool, webSearchTool } from "./web-search/index"; -import { createWriteTool, writeTool } from "./write"; +import type { Rule } from "../../capability/rule"; +import type { EventBus } from "../event-bus"; +import { createAskTool } from "./ask"; +import { createBashTool } from "./bash"; +import { createEditTool } from "./edit"; +import { createFindTool } from "./find"; +import { createGitTool } from "./git"; +import { createGrepTool } from "./grep"; +import { createLsTool } from "./ls"; +import { createLspTool } from "./lsp/index"; +import { createNotebookTool } from "./notebook"; +import { createOutputTool } from "./output"; +import { createReadTool } from "./read"; +import { reportFindingTool, submitReviewTool } from "./review"; +import { createRulebookTool } from "./rulebook"; +import { createTaskTool } from "./task/index"; +import { createWebFetchTool } from "./web-fetch"; +import { createWebSearchTool } from "./web-search/index"; +import { createWriteTool } from "./write"; /** Tool type (AgentTool from pi-ai) */ export type Tool = AgentTool; -/** Context for tools that need session information */ -export interface SessionContext { +/** Session context for tool factories */ +export interface ToolSession { + /** Current working directory */ + cwd: string; + /** Whether UI is available */ + hasUI: boolean; + /** Rulebook rules */ + rulebookRules: Rule[]; + /** Event bus for tool/extension communication */ + eventBus?: EventBus; + /** Get session file */ getSessionFile: () => string | null; -} - -/** Options for creating coding tools */ -export interface CodingToolsOptions { - /** Whether to fetch LSP diagnostics after write tool writes files (default: true) */ - lspDiagnosticsOnWrite?: boolean; - /** Whether to fetch LSP diagnostics after edit tool edits files (default: false) */ - lspDiagnosticsOnEdit?: boolean; - /** Whether to format files using LSP after write tool writes (default: true) */ - lspFormatOnWrite?: boolean; - /** Whether to accept high-confidence fuzzy matches in edit tool (default: true) */ - editFuzzyMatch?: boolean; - /** Whether to auto-resize images to 2000x2000 max in read tool (default: true) */ - readAutoResizeImages?: boolean; - /** Set of tool names available to the agent (for cross-tool awareness) */ - availableTools?: Set; -} - -// Factory function type -type ToolFactory = (cwd: string, sessionContext?: SessionContext, options?: CodingToolsOptions) => Tool | Promise; - -// Tool definitions: static tools and their factory functions -const toolDefs: Record = { - ask: { tool: askTool, create: createAskTool }, - read: { - tool: readTool, - create: (cwd, _ctx, options) => createReadTool(cwd, { autoResizeImages: options?.readAutoResizeImages ?? true }), - }, - bash: { tool: bashTool, create: createBashTool }, - edit: { - tool: editTool, - create: (cwd, _ctx, options) => { - const enableDiagnostics = options?.lspDiagnosticsOnEdit ?? false; - const enableFormat = options?.lspFormatOnWrite ?? true; - const writethrough = createLspWritethrough(cwd, { - enableFormat, - enableDiagnostics, - }); - return createEditTool(cwd, { fuzzyMatch: options?.editFuzzyMatch ?? true, writethrough }); - }, - }, - write: { - tool: writeTool, - create: (cwd, _ctx, options) => { - const enableFormat = options?.lspFormatOnWrite ?? true; - const enableDiagnostics = options?.lspDiagnosticsOnWrite ?? true; - const writethrough = createLspWritethrough(cwd, { - enableFormat, - enableDiagnostics, - }); - return createWriteTool(cwd, { writethrough }); - }, - }, - grep: { tool: grepTool, create: createGrepTool }, - find: { tool: findTool, create: createFindTool }, - git: { tool: gitTool, create: createGitTool }, - ls: { tool: lsTool, create: createLsTool }, - lsp: { tool: lspTool, create: createLspTool }, - notebook: { tool: notebookTool, create: createNotebookTool }, - output: { tool: outputTool, create: (cwd, ctx) => createOutputTool(cwd, ctx) }, - task: { tool: taskTool, create: (cwd, ctx, opts) => createTaskTool(cwd, ctx, opts) }, - web_fetch: { tool: webFetchTool, create: createWebFetchTool }, - web_search: { tool: webSearchTool, create: createWebSearchTool }, - report_finding: { tool: reportFindingTool, create: createReportFindingTool }, - submit_review: { tool: submitReviewTool, create: createSubmitReviewTool }, -}; - -export type ToolName = keyof typeof toolDefs; - -// Tools that require UI (excluded when hasUI is false) -const uiToolNames: ToolName[] = ["ask"]; - -// Tool sets defined by name (base sets, without UI-only tools) -export const baseCodingToolNames: ToolName[] = [ - "read", - "bash", - "edit", - "write", - "grep", - "find", - "git", - "ls", - "lsp", - "notebook", - "output", - "task", - "web_fetch", - "web_search", -]; -const baseReadOnlyToolNames: ToolName[] = ["read", "grep", "find", "ls"]; - -// Default tools for full access mode (using process.cwd(), no UI) -export const codingTools: Tool[] = baseCodingToolNames.map((name) => toolDefs[name].tool); - -// Read-only tools for exploration without modification (using process.cwd(), no UI) -export const readOnlyTools: Tool[] = baseReadOnlyToolNames.map((name) => toolDefs[name].tool); - -// All available tools (using process.cwd(), no UI) -export const allTools = Object.fromEntries(Object.entries(toolDefs).map(([name, def]) => [name, def.tool])) as Record< - ToolName, - Tool ->; - -/** - * Create coding tools configured for a specific working directory. - * @param cwd - Working directory for tools - * @param hasUI - Whether UI is available (includes ask tool if true) - * @param sessionContext - Optional session context for tools that need it - * @param options - Options for tool configuration - */ -export async function createCodingTools( - cwd: string, - hasUI = false, - sessionContext?: SessionContext, - options?: CodingToolsOptions, -): Promise { - const names = hasUI ? [...baseCodingToolNames, ...uiToolNames] : baseCodingToolNames; - const optionsWithTools = { ...options, availableTools: new Set(names) }; - return Promise.all(names.map((name) => toolDefs[name].create(cwd, sessionContext, optionsWithTools))); -} - -/** - * Create read-only tools configured for a specific working directory. - * @param cwd - Working directory for tools - * @param hasUI - Whether UI is available (includes ask tool if true) - * @param sessionContext - Optional session context for tools that need it - * @param options - Options for tool configuration - */ -export async function createReadOnlyTools( - cwd: string, - hasUI = false, - sessionContext?: SessionContext, - options?: CodingToolsOptions, -): Promise { - const names = hasUI ? [...baseReadOnlyToolNames, ...uiToolNames] : baseReadOnlyToolNames; - const optionsWithTools = { ...options, availableTools: new Set(names) }; - return Promise.all(names.map((name) => toolDefs[name].create(cwd, sessionContext, optionsWithTools))); -} - -/** - * Create all tools configured for a specific working directory. - * @param cwd - Working directory for tools - * @param sessionContext - Optional session context for tools that need it - * @param options - Options for tool configuration - */ -export async function createAllTools( - cwd: string, - sessionContext?: SessionContext, - options?: CodingToolsOptions, -): Promise> { - const names = Object.keys(toolDefs); - const optionsWithTools = { ...options, availableTools: new Set(names) }; - const entries = await Promise.all( - Object.entries(toolDefs).map(async ([name, def]) => [ - name, - await def.create(cwd, sessionContext, optionsWithTools), - ]), - ); - return Object.fromEntries(entries) as Record; -} - -/** - * Wrap a bash tool with interception that redirects common patterns to specialized tools. - * This helps prevent LLMs from falling back to shell commands when better tools exist. - * - * @param bashTool - The bash tool to wrap - * @param availableTools - Set of tool names that are available (for context-aware blocking) - * @returns Wrapped bash tool with interception - */ -export function wrapBashWithInterception(bashTool: Tool, availableTools: Set): Tool { - const originalExecute = bashTool.execute; - - return { - ...bashTool, - execute: async (toolCallId, params, signal, onUpdate, context) => { - const command = (params as { command: string }).command; - - // Check for forbidden patterns - const interception = checkBashInterception(command, availableTools); - if (interception.block) { - throw new Error(interception.message); - } - - // Check for simple ls that should use ls tool - const lsInterception = checkSimpleLsInterception(command, availableTools); - if (lsInterception.block) { - throw new Error(lsInterception.message); - } - - // Pass through to original bash tool - return originalExecute(toolCallId, params, signal, onUpdate, context); - }, + /** Get session spawns */ + getSessionSpawns: () => string | null; + /** Settings manager (optional) */ + settings?: { + getImageAutoResize(): boolean; + getLspFormatOnWrite(): boolean; + getLspDiagnosticsOnWrite(): boolean; + getLspDiagnosticsOnEdit(): boolean; + getEditFuzzyMatch(): boolean; + getGitToolEnabled(): boolean; + getBashInterceptorEnabled(): boolean; }; } -/** - * Apply bash interception to a set of tools. - * Finds the bash tool and wraps it with interception based on other available tools. - * - * @param tools - Array of tools to process - * @returns Tools with bash interception applied - */ -export function applyBashInterception(tools: Tool[]): Tool[] { - const toolNames = new Set(tools.map((t) => t.name)); +type ToolFactory = (session: ToolSession) => Tool | null | Promise; - // If bash isn't in the tools, nothing to do - if (!toolNames.has("bash")) { - return tools; +export const BUILTIN_TOOLS: Record = { + ask: createAskTool, + bash: createBashTool, + edit: createEditTool, + find: createFindTool, + git: createGitTool, + grep: createGrepTool, + ls: createLsTool, + lsp: createLspTool, + notebook: createNotebookTool, + output: createOutputTool, + read: createReadTool, + rulebook: createRulebookTool, + task: createTaskTool, + web_fetch: createWebFetchTool, + web_search: createWebSearchTool, + write: createWriteTool, +}; + +export const HIDDEN_TOOLS: Record = { + report_finding: () => reportFindingTool, + submit_review: () => submitReviewTool, +}; + +export type ToolName = keyof typeof BUILTIN_TOOLS; + +/** + * Create tools from BUILTIN_TOOLS registry. + */ +export async function createTools(session: ToolSession, toolNames?: string[]): Promise { + const requestedTools = toolNames && toolNames.length > 0 ? toolNames : undefined; + const allTools: Record = { ...BUILTIN_TOOLS, ...HIDDEN_TOOLS }; + const entries = requestedTools + ? requestedTools + .filter((name, index) => requestedTools.indexOf(name) === index && name in allTools) + .map((name) => [name, allTools[name]] as const) + : Object.entries(BUILTIN_TOOLS); + const results = await Promise.all(entries.map(([, factory]) => factory(session))); + const tools = results.filter((t): t is Tool => t !== null); + + if (requestedTools) { + const allowed = new Set(requestedTools); + return tools.filter((tool) => allowed.has(tool.name)); } - return tools.map((tool) => { - if (tool.name === "bash") { - return wrapBashWithInterception(tool, toolNames); - } - return tool; - }); + return tools; } diff --git a/packages/coding-agent/src/core/tools/ls.ts b/packages/coding-agent/src/core/tools/ls.ts index 768f11e93..7f30962e4 100644 --- a/packages/coding-agent/src/core/tools/ls.ts +++ b/packages/coding-agent/src/core/tools/ls.ts @@ -7,6 +7,7 @@ import { Type } from "@sinclair/typebox"; import { getLanguageFromPath, type Theme } from "../../modes/interactive/theme/theme"; import type { RenderResultOptions } from "../custom-tools/types"; import { untilAborted } from "../utils"; +import type { ToolSession } from "./index"; import { resolveToCwd } from "./path-utils"; import { formatAge, @@ -37,7 +38,7 @@ export interface LsToolDetails { entryLimitReached?: number; } -export function createLsTool(cwd: string): AgentTool { +export function createLsTool(session: ToolSession): AgentTool { return { name: "ls", label: "Ls", @@ -49,7 +50,7 @@ export function createLsTool(cwd: string): AgentTool { signal?: AbortSignal, ) => { return untilAborted(signal, async () => { - const dirPath = resolveToCwd(path || ".", cwd); + const dirPath = resolveToCwd(path || ".", session.cwd); const effectiveLimit = limit ?? DEFAULT_LIMIT; // Check if path exists @@ -159,9 +160,6 @@ export function createLsTool(cwd: string): AgentTool { }; } -/** Default ls tool using process.cwd() - for backwards compatibility */ -export const lsTool = createLsTool(process.cwd()); - // ============================================================================= // TUI Renderer // ============================================================================= @@ -271,10 +269,7 @@ export const lsToolRenderer = { } if (hasTruncation) { - text += `\n ${uiTheme.fg("dim", uiTheme.tree.last)} ${uiTheme.fg( - "warning", - `truncated: ${truncationReasons.join(", ")}`, - )}`; + text += `\n ${uiTheme.fg("dim", uiTheme.tree.last)} ${uiTheme.fg("warning", `truncated: ${truncationReasons.join(", ")}`)}`; } return new Text(text, 0, 0); diff --git a/packages/coding-agent/src/core/tools/lsp/index.ts b/packages/coding-agent/src/core/tools/lsp/index.ts index 947334b2c..7c47fd309 100644 --- a/packages/coding-agent/src/core/tools/lsp/index.ts +++ b/packages/coding-agent/src/core/tools/lsp/index.ts @@ -7,6 +7,7 @@ import { type Theme, theme } from "../../../modes/interactive/theme/theme"; import lspDescription from "../../../prompts/tools/lsp.md" with { type: "text" }; import { logger } from "../../logger"; import { once, untilAborted } from "../../utils"; +import type { ToolSession } from "../index"; import { resolveToCwd } from "../path-utils"; import { ensureFileOpen, @@ -687,7 +688,7 @@ export function createLspWritethrough(cwd: string, options?: WritethroughOptions } /** Create an LSP tool */ -export function createLspTool(cwd: string): AgentTool { +export function createLspTool(session: ToolSession): AgentTool { return { name: "lsp", label: "LSP", @@ -713,7 +714,7 @@ export function createLspTool(cwd: string): AgentTool(); for (const target of targets) { - const resolved = resolveToCwd(target, cwd); + const resolved = resolveToCwd(target, session.cwd); const servers = getServersForFile(config, resolved); if (servers.length === 0) { results.push(`${theme.status.error} ${target}: No language server found`); @@ -765,7 +766,7 @@ export function createLspTool(cwd: string): AgentTool ` ${formatLocation(loc, cwd)}`) + .map((loc) => ` ${formatLocation(loc, session.cwd)}`) .join("\n")}`; } } @@ -931,7 +932,7 @@ export function createLspTool(cwd: string): AgentTool ` ${formatLocation(loc, cwd)}`); + const lines = result.map((loc) => ` ${formatLocation(loc, session.cwd)}`); output = `Found ${result.length} reference(s):\n${lines.join("\n")}`; } break; @@ -964,7 +965,7 @@ export function createLspTool(cwd: string): AgentTool formatSymbolInformation(s, cwd)); - output = `Found ${result.length} symbol(s) matching "${query}":\n${lines - .map((l) => ` ${l}`) - .join("\n")}`; + const lines = result.map((s) => formatSymbolInformation(s, session.cwd)); + output = `Found ${result.length} symbol(s) matching "${query}":\n${lines.map((l) => ` ${l}`).join("\n")}`; } break; } @@ -1025,10 +1024,10 @@ export function createLspTool(cwd: string): AgentTool ` ${a}`).join("\n")}`; } else { - const preview = formatWorkspaceEdit(result, cwd); + const preview = formatWorkspaceEdit(result, session.cwd); output = `Rename preview:\n${preview.map((p) => ` ${p}`).join("\n")}`; } } @@ -1114,7 +1113,7 @@ export function createLspTool(cwd: string): AgentTool ` ${a}`).join("\n")}`; } else { const commandPayload = getCommandPayload(resolvedAction); @@ -1136,9 +1135,7 @@ export function createLspTool(cwd: string): AgentTool { const loc = { uri: call.from.uri, range: call.from.selectionRange }; const detail = call.from.detail ? ` (${call.from.detail})` : ""; - return ` ${call.from.name}${detail} @ ${formatLocation(loc, cwd)}`; + return ` ${call.from.name}${detail} @ ${formatLocation(loc, session.cwd)}`; }); output = `Found ${calls.length} caller(s) of "${item.name}":\n${lines.join("\n")}`; } @@ -1184,7 +1181,7 @@ export function createLspTool(cwd: string): AgentTool { const loc = { uri: call.to.uri, range: call.to.selectionRange }; const detail = call.to.detail ? ` (${call.to.detail})` : ""; - return ` ${call.to.name}${detail} @ ${formatLocation(loc, cwd)}`; + return ` ${call.to.name}${detail} @ ${formatLocation(loc, session.cwd)}`; }); output = `"${item.name}" calls ${calls.length} function(s):\n${lines.join("\n")}`; } @@ -1207,7 +1204,7 @@ export function createLspTool(cwd: string): AgentTool = []; for (const [diagUri, diags] of client.diagnostics.entries()) { - const relPath = path.relative(cwd, uriToFile(diagUri)); + const relPath = path.relative(session.cwd, uriToFile(diagUri)); for (const diag of diags) { collected.push({ filePath: relPath, diagnostic: diag }); } @@ -1274,13 +1271,13 @@ export function createLspTool(cwd: string): AgentTool 0 ? `Applied SSR:\n${applied.map((a) => ` ${a}`).join("\n")}` : "SSR: no matches found"; } else { - const preview = formatWorkspaceEdit(result, cwd); + const preview = formatWorkspaceEdit(result, session.cwd); output = preview.length > 0 ? `SSR preview:\n${preview.map((p) => ` ${p}`).join("\n")}` @@ -1366,4 +1363,10 @@ export function createLspTool(cwd: string): AgentTool null, + getSessionSpawns: () => null, +}); diff --git a/packages/coding-agent/src/core/tools/lsp/render.ts b/packages/coding-agent/src/core/tools/lsp/render.ts index 147d23e2e..8e1163cfd 100644 --- a/packages/coding-agent/src/core/tools/lsp/render.ts +++ b/packages/coding-agent/src/core/tools/lsp/render.ts @@ -237,10 +237,7 @@ function renderDiagnostics( } const severityColor = severityToColor(item.severity); const location = formatDiagnosticLocation(item.file, item.line, item.col, theme); - output += `\n ${theme.fg("dim", branch)} ${theme.fg(severityColor, location)} ${theme.fg( - "dim", - `[${item.severity}]`, - )}`; + output += `\n ${theme.fg("dim", branch)} ${theme.fg(severityColor, location)} ${theme.fg("dim", `[${item.severity}]`)}`; if (item.message) { output += `\n ${theme.fg("dim", detailPrefix)}${theme.fg( "muted", @@ -274,10 +271,7 @@ function renderDiagnostics( output += `\n ${theme.fg("dim", branch)} ${theme.fg(severityColor, location)}${message}`; } if (remaining > 0) { - output += `\n ${theme.fg("dim", theme.tree.last)} ${theme.fg( - "muted", - `${theme.format.ellipsis} ${remaining} more`, - )}`; + output += `\n ${theme.fg("dim", theme.tree.last)} ${theme.fg("muted", `${theme.format.ellipsis} ${remaining} more`)}`; } return new Text(output, 0, 0); @@ -332,10 +326,7 @@ function renderReferences(refMatch: RegExpMatchArray, lines: string[], expanded: const isLastLoc = li === locsToShow.length - 1 && locs.length <= maxLocsPerFile; const locBranch = isLastLoc ? theme.tree.last : theme.tree.branch; const locCont = isLastLoc ? " " : `${theme.tree.vertical} `; - output += `\n ${theme.fg("dim", fileCont)}${theme.fg("dim", locBranch)} ${theme.fg( - "muted", - `line ${line}, col ${col}`, - )}`; + output += `\n ${theme.fg("dim", fileCont)}${theme.fg("dim", locBranch)} ${theme.fg("muted", `line ${line}, col ${col}`)}`; if (expanded) { const context = `at ${file}:${line}:${col}`; output += `\n ${theme.fg("dim", fileCont)}${theme.fg("dim", locCont)}${theme.fg( @@ -354,10 +345,7 @@ function renderReferences(refMatch: RegExpMatchArray, lines: string[], expanded: } if (files.length > maxFiles) { - output += `\n ${theme.fg("dim", theme.tree.last)} ${theme.fg( - "muted", - formatMoreItems(files.length - maxFiles, "file", theme), - )}`; + output += `\n ${theme.fg("dim", theme.tree.last)} ${theme.fg("muted", formatMoreItems(files.length - maxFiles, "file", theme))}`; } return output; @@ -463,10 +451,7 @@ function renderSymbols(symbolsMatch: RegExpMatchArray, lines: string[], expanded )}`; } if (topLevelCount > 3) { - output += `\n ${theme.fg("dim", theme.tree.last)} ${theme.fg( - "muted", - `${theme.format.ellipsis} ${topLevelCount - 3} more`, - )}`; + output += `\n ${theme.fg("dim", theme.tree.last)} ${theme.fg("muted", `${theme.format.ellipsis} ${topLevelCount - 3} more`)}`; } return new Text(output, 0, 0); @@ -502,10 +487,7 @@ function renderGeneric(text: string, lines: string[], expanded: boolean, theme: const firstLine = lines[0] || "No output"; const expandHint = formatExpandHint(false, lines.length > 1, theme); - let output = `${icon} ${theme.fg( - "dim", - truncate(firstLine, TRUNCATE_LENGTHS.TITLE, theme.format.ellipsis), - )}${expandHint}`; + let output = `${icon} ${theme.fg("dim", truncate(firstLine, TRUNCATE_LENGTHS.TITLE, theme.format.ellipsis))}${expandHint}`; if (lines.length > 1) { const previewLines = lines.slice(1, 4); @@ -518,10 +500,7 @@ function renderGeneric(text: string, lines: string[], expanded: boolean, theme: )}`; } if (lines.length > 4) { - output += `\n ${theme.fg("dim", theme.tree.last)} ${theme.fg( - "muted", - formatMoreItems(lines.length - 4, "line", theme), - )}`; + output += `\n ${theme.fg("dim", theme.tree.last)} ${theme.fg("muted", formatMoreItems(lines.length - 4, "line", theme))}`; } } diff --git a/packages/coding-agent/src/core/tools/notebook.ts b/packages/coding-agent/src/core/tools/notebook.ts index c8fb0011a..28025e70e 100644 --- a/packages/coding-agent/src/core/tools/notebook.ts +++ b/packages/coding-agent/src/core/tools/notebook.ts @@ -4,6 +4,7 @@ import { Text } from "@oh-my-pi/pi-tui"; import { Type } from "@sinclair/typebox"; import type { Theme } from "../../modes/interactive/theme/theme"; import type { RenderResultOptions } from "../custom-tools/types"; +import type { ToolSession } from "../sdk"; import { untilAborted } from "../utils"; import { resolveToCwd } from "./path-utils"; import { @@ -61,7 +62,7 @@ function splitIntoLines(content: string): string[] { return content.split("\n").map((line, i, arr) => (i < arr.length - 1 ? `${line}\n` : line)); } -export function createNotebookTool(cwd: string): AgentTool { +export function createNotebookTool(session: ToolSession): AgentTool { return { name: "notebook", label: "Notebook", @@ -79,7 +80,7 @@ export function createNotebookTool(cwd: string): AgentTool { - const absolutePath = resolveToCwd(notebook_path, cwd); + const absolutePath = resolveToCwd(notebook_path, session.cwd); return untilAborted(signal, async () => { // Check if file exists @@ -190,9 +191,6 @@ export function createNotebookTool(cwd: string): AgentTool { +export function createOutputTool(session: ToolSession): AgentTool { return { name: "output", label: "Output", @@ -133,7 +130,7 @@ export function createOutputTool( _toolCallId: string, params: { ids: string[]; format?: "raw" | "json" | "stripped"; offset?: number; limit?: number }, ): Promise<{ content: TextContent[]; details: OutputToolDetails }> => { - const sessionFile = sessionContext?.getSessionFile(); + const sessionFile = session.getSessionFile(); if (!sessionFile) { return { @@ -253,9 +250,6 @@ export function createOutputTool( }; } -/** Default output tool using process.cwd() - for backwards compatibility */ -export const outputTool = createOutputTool(process.cwd()); - // ============================================================================= // TUI Renderer // ============================================================================= @@ -309,15 +303,9 @@ export const outputToolRenderer = { const icon = uiTheme.styledSymbol("status.error", "error"); let text = `${icon} ${uiTheme.fg("error", `Error: Not found: ${details.notFound.join(", ")}`)}`; if (details.availableIds?.length) { - text += `\n ${uiTheme.fg("dim", uiTheme.tree.last)} ${uiTheme.fg( - "muted", - `Available: ${details.availableIds.join(", ")}`, - )}`; + text += `\n ${uiTheme.fg("dim", uiTheme.tree.last)} ${uiTheme.fg("muted", `Available: ${details.availableIds.join(", ")}`)}`; } else { - text += `\n ${uiTheme.fg("dim", uiTheme.tree.last)} ${uiTheme.fg( - "muted", - "No outputs available in current session", - )}`; + text += `\n ${uiTheme.fg("dim", uiTheme.tree.last)} ${uiTheme.fg("muted", "No outputs available in current session")}`; } return new Text(text, 0, 0); } diff --git a/packages/coding-agent/src/core/tools/read.ts b/packages/coding-agent/src/core/tools/read.ts index 90e78d020..bda03321c 100644 --- a/packages/coding-agent/src/core/tools/read.ts +++ b/packages/coding-agent/src/core/tools/read.ts @@ -12,6 +12,7 @@ import { formatDimensionNote, resizeImage } from "../../utils/image-resize"; import { detectSupportedImageMimeTypeFromFile } from "../../utils/mime"; import { ensureTool } from "../../utils/tools-manager"; import type { RenderResultOptions } from "../custom-tools/types"; +import type { ToolSession } from "../sdk"; import { untilAborted } from "../utils"; import { createLsTool } from "./ls"; import { resolveReadPath, resolveToCwd } from "./path-utils"; @@ -340,14 +341,9 @@ export interface ReadToolDetails { redirectedTo?: "ls"; } -export interface ReadToolOptions { - /** Whether to auto-resize images to 2000x2000 max. Default: true */ - autoResizeImages?: boolean; -} - -export function createReadTool(cwd: string, options?: ReadToolOptions): AgentTool { - const autoResizeImages = options?.autoResizeImages ?? true; - const lsTool = createLsTool(cwd); +export function createReadTool(session: ToolSession): AgentTool { + const autoResizeImages = session.settings?.getImageAutoResize() ?? true; + const lsTool = createLsTool(session); return { name: "read", label: "Read", @@ -358,7 +354,7 @@ export function createReadTool(cwd: string, options?: ReadToolOptions): AgentToo { path: readPath, offset, limit }: { path: string; offset?: number; limit?: number }, signal?: AbortSignal, ) => { - const absolutePath = resolveReadPath(readPath, cwd); + const absolutePath = resolveReadPath(readPath, session.cwd); return untilAborted(signal, async () => { let isDirectory = false; @@ -378,14 +374,12 @@ export function createReadTool(cwd: string, options?: ReadToolOptions): AgentToo } } catch (error) { if (isNotFoundError(error)) { - const suggestions = await findReadPathSuggestions(readPath, cwd); + const suggestions = await findReadPathSuggestions(readPath, session.cwd); let message = `File not found: ${readPath}`; if (suggestions?.suggestions.length) { const scopeLabel = suggestions.scopeLabel ? ` in ${suggestions.scopeLabel}` : ""; - message += `\n\nClosest matches${scopeLabel}:\n${suggestions.suggestions - .map((match) => `- ${match}`) - .join("\n")}`; + message += `\n\nClosest matches${scopeLabel}:\n${suggestions.suggestions.map((match) => `- ${match}`).join("\n")}`; if (suggestions.truncated) { message += `\n[Search truncated to first ${MAX_FUZZY_CANDIDATES} paths. Refine the path if the match isn't listed.]`; } @@ -462,9 +456,7 @@ export function createReadTool(cwd: string, options?: ReadToolOptions): AgentToo let outputText = truncation.content; if (truncation.truncated) { - outputText += `\n\n[Document converted via markitdown. Output truncated to ${formatSize( - DEFAULT_MAX_BYTES, - )}]`; + outputText += `\n\n[Document converted via markitdown. Output truncated to ${formatSize(DEFAULT_MAX_BYTES)}]`; details = { truncation }; } @@ -562,9 +554,6 @@ export function createReadTool(cwd: string, options?: ReadToolOptions): AgentToo }; } -/** Default read tool using process.cwd() - for backwards compatibility */ -export const readTool = createReadTool(process.cwd()); - // ============================================================================= // TUI Renderer // ============================================================================= diff --git a/packages/coding-agent/src/core/tools/review.ts b/packages/coding-agent/src/core/tools/review.ts index d7c94b67a..e22a71010 100644 --- a/packages/coding-agent/src/core/tools/review.ts +++ b/packages/coding-agent/src/core/tools/review.ts @@ -19,13 +19,6 @@ const PRIORITY_LABELS: Record = { 3: "P3", }; -const _PRIORITY_DESCRIPTIONS: Record = { - 0: "Drop everything to fix. Blocking release, operations, or major usage.", - 1: "Urgent. Should be addressed in the next cycle.", - 2: "Normal. To be fixed eventually.", - 3: "Low. Nice to have.", -}; - // report_finding schema const ReportFindingParams = Type.Object({ title: Type.String({ @@ -62,8 +55,6 @@ export const reportFindingTool: AgentTool { - return reportFindingTool; -} - -export function createSubmitReviewTool(): AgentTool { - return submitReviewTool; -} - // Re-export types for external use export type { ReportFindingDetails, SubmitReviewDetails }; diff --git a/packages/coding-agent/src/core/tools/rulebook.ts b/packages/coding-agent/src/core/tools/rulebook.ts index 9deacebdc..edc19ea81 100644 --- a/packages/coding-agent/src/core/tools/rulebook.ts +++ b/packages/coding-agent/src/core/tools/rulebook.ts @@ -9,6 +9,7 @@ import type { AgentTool } from "@oh-my-pi/pi-agent-core"; import { Type } from "@sinclair/typebox"; import type { Rule } from "../../capability/rule"; +import type { ToolSession } from "./index"; export interface RulebookToolDetails { type: "rulebook"; @@ -23,9 +24,14 @@ const rulebookSchema = Type.Object({ /** * Create a rulebook tool with access to discovered rules. - * @param rules - Array of discovered rules (non-TTSR rules with descriptions) + * Returns null if no rules available. */ -export function createRulebookTool(rules: Rule[]): AgentTool { +export function createRulebookTool(session: ToolSession): AgentTool | null { + const rules = session.rulebookRules; + if (!rules || rules.length === 0) { + return null; + } + // Build lookup map for O(1) access const ruleMap = new Map(); for (const rule of rules) { diff --git a/packages/coding-agent/src/core/tools/task/agents.ts b/packages/coding-agent/src/core/tools/task/agents.ts index e7c591911..a9b17d229 100644 --- a/packages/coding-agent/src/core/tools/task/agents.ts +++ b/packages/coding-agent/src/core/tools/task/agents.ts @@ -5,7 +5,6 @@ */ // Embed agent markdown files at build time -import browserMd from "../../../prompts/browser.md" with { type: "text" }; import exploreMd from "../../../prompts/explore.md" with { type: "text" }; import planMd from "../../../prompts/plan.md" with { type: "text" }; import reviewerMd from "../../../prompts/reviewer.md" with { type: "text" }; @@ -13,11 +12,37 @@ import taskMd from "../../../prompts/task.md" with { type: "text" }; import type { AgentDefinition, AgentSource } from "./types"; const EMBEDDED_AGENTS: { name: string; content: string }[] = [ - { name: "browser.md", content: browserMd }, { name: "explore.md", content: exploreMd }, { name: "plan.md", content: planMd }, { name: "reviewer.md", content: reviewerMd }, - { name: "task.md", content: taskMd }, + { + name: "task.md", + content: `--- +name: task +description: General-purpose subagent with full capabilities for delegated multi-step tasks +spawns: explore +model: default +--- +${taskMd}`, + }, + { + name: "quick_task.md", + content: `--- +name: quick_task +description: Quick task for fast execution +model: pi/smol +--- +${taskMd}`, + }, + { + name: "deep_task.md", + content: `--- +name: deep_task +description: Deep task for comprehensive reasoning +model: pi/slow +--- +${taskMd}`, + }, ]; /** @@ -88,16 +113,12 @@ function parseAgent(fileName: string, content: string, source: AgentSource): Age spawns = "*"; } - const recursive = - frontmatter.recursive === undefined ? false : frontmatter.recursive === "true" || frontmatter.recursive === "1"; - return { name: frontmatter.name, description: frontmatter.description, tools: tools && tools.length > 0 ? tools : undefined, spawns, model: frontmatter.model, - recursive, systemPrompt: body, source, filePath: `embedded:${fileName}`, diff --git a/packages/coding-agent/src/core/tools/task/discovery.ts b/packages/coding-agent/src/core/tools/task/discovery.ts index a5e491dca..46e2e3a10 100644 --- a/packages/coding-agent/src/core/tools/task/discovery.ts +++ b/packages/coding-agent/src/core/tools/task/discovery.ts @@ -126,18 +126,12 @@ function loadAgentsFromDir(dir: string, source: AgentSource): AgentDefinition[] spawns = "*"; } - const recursive = - frontmatter.recursive === undefined - ? undefined - : frontmatter.recursive === "true" || frontmatter.recursive === "1"; - agents.push({ name: frontmatter.name, description: frontmatter.description, tools: tools && tools.length > 0 ? tools : undefined, spawns, model: frontmatter.model, - recursive, systemPrompt: body, source, filePath, diff --git a/packages/coding-agent/src/core/tools/task/executor.ts b/packages/coding-agent/src/core/tools/task/executor.ts index 1a04fab69..a5b347320 100644 --- a/packages/coding-agent/src/core/tools/task/executor.ts +++ b/packages/coding-agent/src/core/tools/task/executor.ts @@ -1,28 +1,27 @@ /** - * Subprocess execution for subagents. + * Worker execution for subagents. * - * Spawns `omp` in JSON mode to execute tasks with isolated context. - * Parses JSON events for progress tracking. + * Runs each subagent in a Bun Worker and forwards AgentEvents for progress tracking. */ -import { existsSync, unlinkSync, writeFileSync } from "node:fs"; -import { tmpdir } from "node:os"; -import * as path from "node:path"; +import { writeFileSync } from "node:fs"; +import type { AgentEvent } from "@oh-my-pi/pi-agent-core"; +import type { EventBus } from "../../event-bus"; import { ensureArtifactsDir, getArtifactPaths } from "./artifacts"; import { resolveModelPattern } from "./model-resolver"; -import { resolveOmpCommand } from "./omp-command"; import { subprocessToolRegistry } from "./subprocess-tool-registry"; import { type AgentDefinition, type AgentProgress, MAX_OUTPUT_BYTES, MAX_OUTPUT_LINES, - OMP_BLOCKED_AGENT_ENV, - OMP_SPAWNS_ENV, type SingleResult, + TASK_SUBAGENT_EVENT_CHANNEL, + TASK_SUBAGENT_PROGRESS_CHANNEL, } from "./types"; +import type { SubagentWorkerRequest, SubagentWorkerResponse } from "./worker-protocol"; -/** Options for subprocess execution */ +/** Options for worker execution */ export interface ExecutorOptions { cwd: string; agent: AgentDefinition; @@ -36,6 +35,7 @@ export interface ExecutorOptions { sessionFile?: string | null; persistArtifacts?: boolean; artifactsDir?: string; + eventBus?: EventBus; } /** @@ -127,7 +127,7 @@ function getUsageTokens(usage: unknown): number { } /** - * Run a single agent as a subprocess. + * Run a single agent in a worker. */ export async function runSubprocess(options: ExecutorOptions): Promise { const { cwd, agent, task, index, context, modelOverride, signal, onProgress } = options; @@ -168,33 +168,6 @@ export async function runSubprocess(options: ExecutorOptions): Promise 0) { - let toolList = agent.tools; + toolNames = agent.tools; // Auto-include task tool if spawns defined but task not in tools - if (agent.spawns !== undefined && !toolList.includes("task")) { - toolList = [...toolList, "task"]; + if (agent.spawns !== undefined && !toolNames.includes("task")) { + toolNames = [...toolNames, "task"]; } - args.push("--tools", toolList.join(",")); } // Resolve and add model const resolvedModel = resolveModelPattern(modelOverride || agent.model); - if (resolvedModel) { - args.push("--model", resolvedModel); - } + const sessionFile = subtaskSessionFile ?? options.sessionFile ?? null; + const spawnsEnv = agent.spawns === undefined ? "" : agent.spawns === "*" ? "*" : agent.spawns.join(","); - // Add session options - use subtask-specific session file for real-time streaming - if (subtaskSessionFile) { - args.push("--session", subtaskSessionFile); - } else if (options.sessionFile) { - args.push("--session", options.sessionFile); - } else { - args.push("--no-session"); - } - - // Add task as prompt - args.push("--prompt", fullTask); - - // Set up environment - block same-agent recursion unless explicitly recursive - const env = { ...process.env }; - if (!agent.recursive) { - env[OMP_BLOCKED_AGENT_ENV] = agent.name; - } - - // Propagate spawn restrictions to subprocess - if (agent.spawns === undefined) { - env[OMP_SPAWNS_ENV] = ""; // No spawns = deny all - } else if (agent.spawns === "*") { - env[OMP_SPAWNS_ENV] = "*"; - } else { - env[OMP_SPAWNS_ENV] = agent.spawns.join(","); - } - - // Spawn subprocess - const ompCommand = resolveOmpCommand(); - const proc = Bun.spawn([ompCommand.cmd, ...ompCommand.args, ...args], { - cwd, - stdin: "ignore", - stdout: "pipe", - stderr: "pipe", - env, - }); + const worker = new Worker(new URL("./worker.ts", import.meta.url), { type: "module" }); let output = ""; let stderr = ""; @@ -291,238 +222,284 @@ export async function runSubprocess(options: ExecutorOptions): Promise { + if (abortSent) return; + abortSent = true; + const abortMessage: SubagentWorkerRequest = { type: "abort" }; + worker.postMessage(abortMessage); + setTimeout(() => { + if (!resolved) { + worker.terminate(); + } + }, 2000); + }; + // Handle abort signal const onAbort = () => { - if (!resolved) { - proc.kill(15); // SIGTERM - } + if (!resolved) requestAbort(); }; if (signal) { signal.addEventListener("abort", onAbort, { once: true }); } - // Parse JSON events from stdout - const reader = proc.stdout.getReader(); - const decoder = new TextDecoder(); - let buffer = ""; - - const processLine = (line: string) => { - if (resolved) return; - - try { - const event = JSON.parse(line); - // Events are written to subtask session file by subprocess - no need to accumulate in memory - const now = Date.now(); - - switch (event.type) { - case "tool_execution_start": - progress.toolCount++; - progress.currentTool = event.toolName; - progress.currentToolArgs = extractToolArgsPreview(event.toolArgs || event.args || {}); - progress.currentToolStartMs = now; - break; - - case "tool_execution_end": { - if (progress.currentTool) { - progress.recentTools.unshift({ - tool: progress.currentTool, - args: progress.currentToolArgs || "", - endMs: now, - }); - // Keep only last 5 - if (progress.recentTools.length > 5) { - progress.recentTools.pop(); - } - } - progress.currentTool = undefined; - progress.currentToolArgs = undefined; - progress.currentToolStartMs = undefined; - - // Check for registered subprocess tool handler - const handler = subprocessToolRegistry.getHandler(event.toolName); - if (handler) { - // Extract data using handler - if (handler.extractData) { - const data = handler.extractData({ - toolName: event.toolName, - toolCallId: event.toolCallId, - args: event.args, - result: event.result, - isError: event.isError, - }); - if (data !== undefined) { - progress.extractedToolData = progress.extractedToolData || {}; - progress.extractedToolData[event.toolName] = progress.extractedToolData[event.toolName] || []; - progress.extractedToolData[event.toolName].push(data); - } - } - - // Check if handler wants to terminate subprocess - if ( - handler.shouldTerminate?.({ - toolName: event.toolName, - toolCallId: event.toolCallId, - args: event.args, - result: event.result, - isError: event.isError, - }) - ) { - // Don't kill immediately - wait for message_end to get token counts - pendingTermination = true; - // Safety timeout in case message_end never arrives - setTimeout(() => { - if (!resolved) { - resolved = true; - proc.kill(15); // SIGTERM - } - }, 2000); - } - } - break; - } - - case "message_update": { - // Extract text for progress display only (replace, don't accumulate) - const updateContent = event.message?.content || event.content; - if (updateContent && Array.isArray(updateContent)) { - const allText: string[] = []; - for (const block of updateContent) { - if (block.type === "text" && block.text) { - const lines = block.text.split("\n").filter((l: string) => l.trim()); - allText.push(...lines); - } - } - // Show last 8 lines from current state (not accumulated) - progress.recentOutput = allText.slice(-8).reverse(); - } - break; - } - - case "message_end": { - // Extract text from assistant and toolResult messages (not user prompts) - const role = event.message?.role; - if (role === "assistant") { - const messageContent = event.message?.content || event.content; - if (messageContent && Array.isArray(messageContent)) { - for (const block of messageContent) { - if (block.type === "text" && block.text) { - output += block.text; - } - } - } - } - // Extract and accumulate usage (prefer message.usage, fallback to event.usage) - const messageUsage = event.message?.usage || event.usage; - if (messageUsage) { - // Only count assistant messages (not tool results, etc.) - const role = event.message?.role; - if ( - role === "assistant" && - event.message?.stopReason !== "aborted" && - event.message?.stopReason !== "error" - ) { - hasUsage = true; - accumulatedUsage.input += messageUsage.input ?? 0; - accumulatedUsage.output += messageUsage.output ?? 0; - accumulatedUsage.cacheRead += messageUsage.cacheRead ?? 0; - accumulatedUsage.cacheWrite += messageUsage.cacheWrite ?? 0; - accumulatedUsage.totalTokens += messageUsage.totalTokens ?? 0; - if (messageUsage.cost) { - accumulatedUsage.cost.input += messageUsage.cost.input ?? 0; - accumulatedUsage.cost.output += messageUsage.cost.output ?? 0; - accumulatedUsage.cost.cacheRead += messageUsage.cost.cacheRead ?? 0; - accumulatedUsage.cost.cacheWrite += messageUsage.cost.cacheWrite ?? 0; - accumulatedUsage.cost.total += messageUsage.cost.total ?? 0; - } - } - // Accumulate tokens for progress display - progress.tokens += getUsageTokens(messageUsage); - } - // If pending termination, now we have tokens - terminate - if (pendingTermination && !resolved) { - resolved = true; - proc.kill(15); // SIGTERM - } - break; - } - - case "agent_end": - // Extract final content from messages array - if (event.messages && Array.isArray(event.messages)) { - for (const msg of event.messages) { - if (msg.content && Array.isArray(msg.content)) { - for (const block of msg.content) { - if (block.type === "text" && block.text) { - finalOutput += block.text; - } - } - } - } - } - break; - } - - progress.durationMs = now - startTime; - // Clone progress object before passing to callback to prevent mutation during render - onProgress?.({ ...progress }); - } catch { - // Ignore non-JSON lines + const emitProgress = () => { + progress.durationMs = Date.now() - startTime; + onProgress?.({ ...progress }); + if (options.eventBus) { + options.eventBus.emit(TASK_SUBAGENT_PROGRESS_CHANNEL, { + index, + agent: agent.name, + agentSource: agent.source, + task, + progress: { ...progress }, + }); } }; - // Read stdout asynchronously - const stdoutDone = (async () => { - try { - while (true) { - const { done, value } = await reader.read(); - if (done) break; - buffer += decoder.decode(value, { stream: true }); - const lines = buffer.split("\n"); - buffer = lines.pop() || ""; - for (const line of lines) { - processLine(line); + const getMessageContent = (message: unknown): unknown => { + if (message && typeof message === "object" && "content" in message) { + return (message as { content?: unknown }).content; + } + return undefined; + }; + + const getMessageUsage = (message: unknown): unknown => { + if (message && typeof message === "object" && "usage" in message) { + return (message as { usage?: unknown }).usage; + } + return undefined; + }; + + const processEvent = (event: AgentEvent) => { + if (resolved) return; + + if (options.eventBus) { + options.eventBus.emit(TASK_SUBAGENT_EVENT_CHANNEL, { + index, + agent: agent.name, + agentSource: agent.source, + task, + event, + }); + } + + const now = Date.now(); + + switch (event.type) { + case "tool_execution_start": + progress.toolCount++; + progress.currentTool = event.toolName; + progress.currentToolArgs = extractToolArgsPreview( + (event as { toolArgs?: Record }).toolArgs || event.args || {}, + ); + progress.currentToolStartMs = now; + break; + + case "tool_execution_end": { + if (progress.currentTool) { + progress.recentTools.unshift({ + tool: progress.currentTool, + args: progress.currentToolArgs || "", + endMs: now, + }); + // Keep only last 5 + if (progress.recentTools.length > 5) { + progress.recentTools.pop(); + } } - } - // Process remaining buffer - if (buffer.trim()) { - processLine(buffer); - } - } catch { - // Ignore read errors - } - })(); + progress.currentTool = undefined; + progress.currentToolArgs = undefined; + progress.currentToolStartMs = undefined; - // Capture stderr - Bun.spawn returns ReadableStream, convert to text - const stderrDone = (async () => { - try { - const stderrReader = proc.stderr.getReader(); - const stderrDecoder = new TextDecoder(); - while (true) { - const { done, value } = await stderrReader.read(); - if (done) break; - stderr += stderrDecoder.decode(value, { stream: true }); - } - } catch { - // Ignore stderr read errors - } - })(); + // Check for registered subagent tool handler + const handler = subprocessToolRegistry.getHandler(event.toolName); + const eventArgs = (event as { args?: Record }).args ?? {}; + if (handler) { + // Extract data using handler + if (handler.extractData) { + const data = handler.extractData({ + toolName: event.toolName, + toolCallId: event.toolCallId, + args: eventArgs, + result: event.result, + isError: event.isError, + }); + if (data !== undefined) { + progress.extractedToolData = progress.extractedToolData || {}; + progress.extractedToolData[event.toolName] = progress.extractedToolData[event.toolName] || []; + progress.extractedToolData[event.toolName].push(data); + } + } - // Wait for process and stream readers to finish - const exitCode = await proc.exited; - await Promise.all([stdoutDone, stderrDone]); - resolved = true; + // Check if handler wants to terminate worker + if ( + handler.shouldTerminate?.({ + toolName: event.toolName, + toolCallId: event.toolCallId, + args: eventArgs, + result: event.result, + isError: event.isError, + }) + ) { + // Don't terminate immediately - wait for message_end to get token counts + pendingTermination = true; + // Safety timeout in case message_end never arrives + setTimeout(() => { + if (!resolved) { + requestAbort(); + } + }, 2000); + } + } + break; + } + + case "message_update": { + // Extract text for progress display only (replace, don't accumulate) + const updateContent = + getMessageContent(event.message) || (event as AgentEvent & { content?: unknown }).content; + if (updateContent && Array.isArray(updateContent)) { + const allText: string[] = []; + for (const block of updateContent) { + if (block.type === "text" && block.text) { + const lines = block.text.split("\n").filter((l: string) => l.trim()); + allText.push(...lines); + } + } + // Show last 8 lines from current state (not accumulated) + progress.recentOutput = allText.slice(-8).reverse(); + } + break; + } + + case "message_end": { + // Extract text from assistant and toolResult messages (not user prompts) + const role = event.message?.role; + if (role === "assistant") { + const messageContent = + getMessageContent(event.message) || (event as AgentEvent & { content?: unknown }).content; + if (messageContent && Array.isArray(messageContent)) { + for (const block of messageContent) { + if (block.type === "text" && block.text) { + output += block.text; + } + } + } + } + // Extract and accumulate usage (prefer message.usage, fallback to event.usage) + const messageUsage = getMessageUsage(event.message) || (event as AgentEvent & { usage?: unknown }).usage; + if (messageUsage && typeof messageUsage === "object") { + // Only count assistant messages (not tool results, etc.) + if ( + role === "assistant" && + event.message?.stopReason !== "aborted" && + event.message?.stopReason !== "error" + ) { + const usageRecord = messageUsage as Record; + const costRecord = (messageUsage as { cost?: Record }).cost; + hasUsage = true; + accumulatedUsage.input += usageRecord.input ?? 0; + accumulatedUsage.output += usageRecord.output ?? 0; + accumulatedUsage.cacheRead += usageRecord.cacheRead ?? 0; + accumulatedUsage.cacheWrite += usageRecord.cacheWrite ?? 0; + accumulatedUsage.totalTokens += usageRecord.totalTokens ?? 0; + if (costRecord) { + accumulatedUsage.cost.input += costRecord.input ?? 0; + accumulatedUsage.cost.output += costRecord.output ?? 0; + accumulatedUsage.cost.cacheRead += costRecord.cacheRead ?? 0; + accumulatedUsage.cost.cacheWrite += costRecord.cacheWrite ?? 0; + accumulatedUsage.cost.total += costRecord.total ?? 0; + } + } + // Accumulate tokens for progress display + progress.tokens += getUsageTokens(messageUsage); + } + // If pending termination, now we have tokens - terminate + if (pendingTermination && !resolved) { + requestAbort(); + } + break; + } + + case "agent_end": + // Extract final content from assistant messages only (not user prompts) + if (event.messages && Array.isArray(event.messages)) { + for (const msg of event.messages) { + if ((msg as { role?: string })?.role !== "assistant") continue; + const messageContent = getMessageContent(msg); + if (messageContent && Array.isArray(messageContent)) { + for (const block of messageContent) { + if (block.type === "text" && block.text) { + finalOutput += block.text; + } + } + } + } + } + break; + } + + emitProgress(); + }; + + const startMessage: SubagentWorkerRequest = { + type: "start", + payload: { + cwd, + task: fullTask, + systemPrompt: agent.systemPrompt, + model: resolvedModel, + toolNames, + sessionFile, + spawnsEnv, + }, + }; + + interface WorkerMessageEvent { + data: T; + } + interface WorkerErrorEvent { + message: string; + } + + const done = await new Promise>((resolve) => { + const onMessage = (event: WorkerMessageEvent) => { + const message = event.data; + if (!message || resolved) return; + if (message.type === "event") { + processEvent(message.event); + return; + } + if (message.type === "done") { + resolved = true; + resolve(message); + } + }; + const onError = (event: WorkerErrorEvent) => { + if (resolved) return; + resolved = true; + resolve({ + type: "done", + exitCode: 1, + durationMs: Date.now() - startTime, + error: event.message, + }); + }; + worker.addEventListener("message", onMessage); + worker.addEventListener("error", onError); + worker.postMessage(startMessage); + }); // Cleanup if (signal) { signal.removeEventListener("abort", onAbort); } + worker.terminate(); - try { - if (existsSync(promptFile)) { - unlinkSync(promptFile); - } - } catch { - // Ignore cleanup errors + const exitCode = done.exitCode; + if (done.error) { + stderr = done.error; } // Use final output if available, otherwise accumulated output @@ -545,10 +522,9 @@ export async function runSubprocess(options: ExecutorOptions): Promise): void { target.cost.total += cost.total; } -/** Session context interface */ -interface SessionContext { - getSessionFile: () => string | null; -} - -/** Task tool options */ -interface TaskToolOptions { - /** Set of available tool names (for cross-tool awareness) */ - availableTools?: Set; -} - // Re-export types and utilities export { loadBundledAgents as BUNDLED_AGENTS } from "./agents"; export { discoverCommands, expandCommand, getCommand } from "./commands"; @@ -107,166 +95,45 @@ export { taskSchema } from "./types"; async function buildDescription(cwd: string): Promise { const { agents } = await discoverAgents(cwd); - const lines: string[] = []; - - lines.push("Launch a new agent to handle complex, multi-step tasks autonomously."); - lines.push(""); - lines.push( - "The Task tool launches specialized agents (subprocesses) that autonomously handle complex tasks. Each agent type has specific capabilities and tools available to it.", - ); - lines.push(""); - lines.push("Available agent types and the tools they have access to:"); - + // Build agents list + const agentLines: string[] = []; for (const agent of agents.slice(0, MAX_AGENTS_IN_DESCRIPTION)) { const tools = agent.tools?.join(", ") || "All tools"; - lines.push(`- ${agent.name}: ${agent.description} (Tools: ${tools})`); + agentLines.push(`- ${agent.name}: ${agent.description} (Tools: ${tools})`); } if (agents.length > MAX_AGENTS_IN_DESCRIPTION) { - lines.push(` ...and ${agents.length - MAX_AGENTS_IN_DESCRIPTION} more agents`); + agentLines.push(` ...and ${agents.length - MAX_AGENTS_IN_DESCRIPTION} more agents`); } - lines.push(""); - lines.push("When NOT to use the Task tool:"); - lines.push( - "- If you want to read a specific file path, use the Read or Glob tool instead of the Task tool, to find the match more quickly", - ); - lines.push( - '- If you are searching for a specific class definition like "class Foo", use the Glob tool instead, to find the match more quickly', - ); - lines.push( - "- If you are searching for code within a specific file or set of 2-3 files, use the Read tool instead of the Task tool, to find the match more quickly", - ); - lines.push("- Other tasks that are not related to the agent descriptions above"); - lines.push(""); - lines.push(""); - lines.push("Usage notes:"); - lines.push("- Always include a short description of the task in the task parameter"); - lines.push( - "- Prefer plan-then-execute: put shared constraints in context, keep each task focused, and specify output format and acceptance criteria", - ); - lines.push( - "- Minimize tool chatter: avoid repeating large context and use the Output tool with output ids for full logs", - ); - lines.push("- Launch multiple agents concurrently whenever possible, to maximize performance"); - lines.push( - "- When the agent is done, it will return a single message back to you. The result returned by the agent is not visible to the user. To show the user the result, you should send a text message back to the user with a concise summary of the result.", - ); - lines.push( - "- Each agent invocation is stateless. You will not be able to send additional messages to the agent, nor will the agent be able to communicate with you outside of its final report. Therefore, your task should contain a highly detailed task description for the agent to perform autonomously and you should specify exactly what information the agent should return back to you in its final and only message to you.", - ); - lines.push( - "- IMPORTANT: Agent results are intermediate data, not task completions. Use the agent's findings to continue executing the user's request. Do not treat agent reports as 'task complete' signals - they provide context for you to perform the actual work.", - ); - lines.push("- The agent's outputs should generally be trusted"); - lines.push( - "- Clearly tell the agent whether you expect it to write code or just to do research (search, file reads, web fetches, etc.), since it is not aware of the user's intent", - ); - lines.push( - "- If the agent description mentions that it should be used proactively, then you should try your best to use it without the user having to ask for it first. Use your judgement.", - ); - lines.push(""); - lines.push("Parameters:"); - lines.push( - `- tasks: Array of {agent, task, description?, model?} - tasks to run in parallel (max ${MAX_PARALLEL_TASKS}, ${MAX_CONCURRENCY} concurrent)`, - ); - lines.push( - ' - model: (optional) Override the agent\'s default model with fuzzy matching (e.g., "sonnet", "codex", "5.2"). Supports comma-separated fallbacks: "gpt, opus" tries gpt first, then opus. Use "default" for omp\'s default model', - ); - lines.push( - "- context: (optional) Shared context string prepended to all task prompts - use this to avoid repeating instructions", - ); - lines.push(""); - lines.push("Results are always written to {tempdir}/omp-task-{runId}/task_{agent}_{index}.md"); - lines.push(""); - lines.push("Example usage:"); - lines.push(""); - lines.push(""); - lines.push('"code-reviewer": use this agent after you are done writing a significant piece of code'); - lines.push('"explore": use this agent for fast codebase exploration and research'); - lines.push(""); - lines.push(""); - lines.push(""); - lines.push('user: "Please write a function that checks if a number is prime"'); - lines.push("assistant: Sure let me write a function that checks if a number is prime"); - lines.push("assistant: I'm going to use the Write tool to write the following code:"); - lines.push(""); - lines.push("function isPrime(n) {"); - lines.push(" if (n <= 1) return false"); - lines.push(" for (let i = 2; i * i <= n; i++) {"); - lines.push(" if (n % i === 0) return false"); - lines.push(" }"); - lines.push(" return true"); - lines.push("}"); - lines.push(""); - lines.push(""); - lines.push( - "Since a significant piece of code was written and the task was completed, now use the code-reviewer agent to review the code", - ); - lines.push(""); - lines.push("assistant: Now let me use the code-reviewer agent to review the code"); - lines.push( - 'assistant: Uses the Task tool: { tasks: [{ agent: "code-reviewer", task: "Review the isPrime function" }] }', - ); - lines.push(""); - lines.push(""); - lines.push(""); - lines.push('user: "Find all TODO comments in the codebase"'); - lines.push("assistant: I'll use multiple explore agents to search different directories in parallel"); - lines.push("assistant: Uses the Task tool:"); - lines.push("{"); - lines.push(' "context": "Find all TODO comments. Return file:line:content format.",'); - lines.push(' "tasks": ['); - lines.push(' { "agent": "explore", "task": "Search in src/" },'); - lines.push(' { "agent": "explore", "task": "Search in lib/" },'); - lines.push(' { "agent": "explore", "task": "Search in tests/" }'); - lines.push(" ]"); - lines.push("}"); - lines.push("Results → {tempdir}/omp-task-{runId}/task_explore_*.md"); - lines.push(""); - - return lines.join("\n"); + // Fill template placeholders + return taskDescriptionTemplate + .replace("{{AGENTS_LIST}}", agentLines.join("\n")) + .replace("{{MAX_PARALLEL_TASKS}}", String(MAX_PARALLEL_TASKS)) + .replace("{{MAX_CONCURRENCY}}", String(MAX_CONCURRENCY)); } /** - * Create the task tool configured for a specific working directory. + * Create the task tool configured for a specific session. */ export async function createTaskTool( - cwd: string, - sessionContext?: SessionContext, - options?: TaskToolOptions, + session: ToolSession, ): Promise> { - const hasOutputTool = options?.availableTools?.has("output") ?? false; - // Check if subagents are completely inhibited (legacy recursion prevention) - if (process.env[OMP_NO_SUBAGENTS_ENV]) { - return { - name: "task", - label: "Task", - description: "Sub-agents disabled (recursion prevention)", - parameters: taskSchema, - execute: async () => ({ - content: [{ type: "text", text: "Sub-agents are disabled for this agent (recursion prevention)." }], - details: { - projectAgentsDir: null, - results: [], - totalDurationMs: 0, - }, - }), - }; - } - // Check for same-agent blocking (allows other agent types) - const blockedAgent = process.env[OMP_BLOCKED_AGENT_ENV]; + const blockedAgent = process.env.OMP_BLOCKED_AGENT; + + // Build description upfront + const description = await buildDescription(session.cwd); return { name: "task", label: "Task", - description: await buildDescription(cwd), + description, parameters: taskSchema, renderCall, renderResult, execute: async (_toolCallId, params, signal, onUpdate) => { const startTime = Date.now(); - const { agents, projectAgentsDir } = await discoverAgents(cwd); + const { agents, projectAgentsDir } = await discoverAgents(session.cwd); const context = params.context; // Handle empty or missing tasks @@ -305,7 +172,7 @@ export async function createTaskTool( } // Derive artifacts directory - const sessionFile = sessionContext?.getSessionFile() ?? null; + const sessionFile = session.getSessionFile(); const artifactsDir = sessionFile ? getArtifactsDir(sessionFile) : null; const tempArtifactsDir = artifactsDir ? null : createTempArtifactsDir(); const effectiveArtifactsDir = artifactsDir || tempArtifactsDir!; @@ -370,13 +237,12 @@ export async function createTaskTool( } // Check spawn restrictions from parent - const parentSpawns = process.env[OMP_SPAWNS_ENV]; + const parentSpawns = session.getSessionSpawns() ?? "*"; + const allowedSpawns = parentSpawns.split(",").map((s) => s.trim()); const isSpawnAllowed = (agentName: string): boolean => { - if (parentSpawns === undefined) return true; // Root = allow all if (parentSpawns === "") return false; // Empty = deny all if (parentSpawns === "*") return true; // Wildcard = allow all - const allowed = new Set(parentSpawns.split(",").map((s) => s.trim())); - return allowed.has(agentName); + return allowedSpawns.includes(agentName); }; for (const task of tasks) { @@ -425,7 +291,7 @@ export async function createTaskTool( const results = await mapWithConcurrencyLimit(tasksWithContext, MAX_CONCURRENCY, async (task, index) => { const agent = getAgent(agents, task.agent)!; return runSubprocess({ - cwd, + cwd: session.cwd, agent, task: task.task, description: task.description, @@ -436,6 +302,7 @@ export async function createTaskTool( persistArtifacts: !!artifactsDir, artifactsDir: effectiveArtifactsDir, signal, + eventBus: undefined, onProgress: (progress) => { progressMap.set(index, structuredClone(progress)); emitProgress(); @@ -469,26 +336,21 @@ export async function createTaskTool( const status = r.exitCode === 0 ? "completed" : `failed (exit ${r.exitCode})`; const output = r.output.trim() || r.stderr.trim() || "(no output)"; const preview = output.split("\n").slice(0, 5).join("\n"); - // Include output metadata and ID; include path only if Output tool unavailable (for Read fallback) + // Include output metadata and ID const outputId = `${r.agent}_${r.index}`; const meta = r.outputMeta ? ` [${r.outputMeta.lineCount} lines, ${formatBytes(r.outputMeta.charCount)}]` : ""; - const pathInfo = !hasOutputTool && r.artifactPaths?.outputPath ? ` (${r.artifactPaths.outputPath})` : ""; - return `[${r.agent}] ${status}${meta} ${outputId}${pathInfo}\n${preview}`; + return `[${r.agent}] ${status}${meta} ${outputId}\n${preview}`; }); const skippedNote = skippedSelfRecursion > 0 - ? ` (${skippedSelfRecursion} ${blockedAgent} task${ - skippedSelfRecursion > 1 ? "s" : "" - } skipped - self-recursion blocked)` + ? ` (${skippedSelfRecursion} ${blockedAgent} task${skippedSelfRecursion > 1 ? "s" : ""} skipped - self-recursion blocked)` : ""; const outputIds = results.map((r) => `${r.agent}_${r.index}`); const outputHint = - hasOutputTool && outputIds.length > 0 - ? `\n\nUse output tool for full logs: output ids ${outputIds.join(", ")}` - : ""; + outputIds.length > 0 ? `\n\nUse output tool for full logs: output ids ${outputIds.join(", ")}` : ""; const summary = `${successCount}/${results.length} succeeded${skippedNote} [${formatDuration( totalDuration, )}]\n\n${summaries.join("\n\n---\n\n")}${outputHint}`; @@ -527,16 +389,15 @@ export async function createTaskTool( }; } -// Default task tool using process.cwd() - returns a placeholder sync tool -// Real implementations should use createTaskTool() which properly initializes the tool +// Default task tool - returns a placeholder tool +// Real implementations should use createTaskTool(session) to initialize the tool export const taskTool: AgentTool = { name: "task", label: "Task", - description: - "Launch a new agent to handle complex, multi-step tasks autonomously. (Agent discovery pending - use createTaskTool for full functionality)", + description: "Launch a new agent to handle complex, multi-step tasks autonomously.", parameters: taskSchema, execute: async () => ({ - content: [{ type: "text", text: "Task tool not properly initialized. Use createTaskTool(cwd) instead." }], + content: [{ type: "text", text: "Task tool not properly initialized. Use createTaskTool(session) instead." }], details: { projectAgentsDir: null, results: [], diff --git a/packages/coding-agent/src/core/tools/task/render.ts b/packages/coding-agent/src/core/tools/task/render.ts index 9698bd392..3736031b8 100644 --- a/packages/coding-agent/src/core/tools/task/render.ts +++ b/packages/coding-agent/src/core/tools/task/render.ts @@ -181,19 +181,29 @@ function renderAgentProgress( lines.push(statusLine); - // Current tool (if running) - if (progress.status === "running" && progress.currentTool) { - let toolLine = `${continuePrefix}${theme.tree.hook} ${theme.fg("muted", progress.currentTool)}`; - if (progress.currentToolArgs) { - toolLine += `: ${theme.fg("dim", truncate(progress.currentToolArgs, 40, theme.format.ellipsis))}`; - } - if (progress.currentToolStartMs) { - const elapsed = Date.now() - progress.currentToolStartMs; - if (elapsed > 5000) { - toolLine += `${theme.sep.dot}${theme.fg("warning", formatDuration(elapsed))}`; + // Current tool (if running) or most recent completed tool + if (progress.status === "running") { + if (progress.currentTool) { + let toolLine = `${continuePrefix}${theme.tree.hook} ${theme.fg("muted", progress.currentTool)}`; + if (progress.currentToolArgs) { + toolLine += `: ${theme.fg("dim", truncate(progress.currentToolArgs, 40, theme.format.ellipsis))}`; } + if (progress.currentToolStartMs) { + const elapsed = Date.now() - progress.currentToolStartMs; + if (elapsed > 5000) { + toolLine += `${theme.sep.dot}${theme.fg("warning", formatDuration(elapsed))}`; + } + } + lines.push(toolLine); + } else if (progress.recentTools.length > 0) { + // Show most recent completed tool when idle between tools + const recent = progress.recentTools[0]; + let toolLine = `${continuePrefix}${theme.tree.hook} ${theme.fg("dim", recent.tool)}`; + if (recent.args) { + toolLine += `: ${theme.fg("dim", truncate(recent.args, 40, theme.format.ellipsis))}`; + } + lines.push(toolLine); } - lines.push(toolLine); } // Render extracted tool data inline (e.g., review findings) diff --git a/packages/coding-agent/src/core/tools/task/types.ts b/packages/coding-agent/src/core/tools/task/types.ts index 9eed3605d..d1fbae0f6 100644 --- a/packages/coding-agent/src/core/tools/task/types.ts +++ b/packages/coding-agent/src/core/tools/task/types.ts @@ -19,14 +19,11 @@ export const MAX_OUTPUT_LINES = 5000; /** Maximum agents to show in description */ export const MAX_AGENTS_IN_DESCRIPTION = 10; -/** Environment variable to inhibit subagent spawning (legacy, still checked for backwards compat) */ -export const OMP_NO_SUBAGENTS_ENV = "OMP_NO_SUBAGENTS"; +/** EventBus channel for raw subagent events */ +export const TASK_SUBAGENT_EVENT_CHANNEL = "task:subagent:event"; -/** Environment variable containing blocked agent name (self-recursion prevention) */ -export const OMP_BLOCKED_AGENT_ENV = "OMP_BLOCKED_AGENT"; - -/** Environment variable containing allowed spawn list (propagated to subprocesses) */ -export const OMP_SPAWNS_ENV = "OMP_SPAWNS"; +/** EventBus channel for aggregated subagent progress */ +export const TASK_SUBAGENT_PROGRESS_CHANNEL = "task:subagent:progress"; /** Single task item for parallel execution */ export const taskItemSchema = Type.Object({ @@ -81,7 +78,6 @@ export interface AgentDefinition { tools?: string[]; spawns?: string[] | "*"; model?: string; - recursive?: boolean; source: AgentSource; filePath?: string; } diff --git a/packages/coding-agent/src/core/tools/task/worker-protocol.ts b/packages/coding-agent/src/core/tools/task/worker-protocol.ts new file mode 100644 index 000000000..77b0a3e35 --- /dev/null +++ b/packages/coding-agent/src/core/tools/task/worker-protocol.ts @@ -0,0 +1,17 @@ +import type { AgentEvent } from "@oh-my-pi/pi-agent-core"; + +export interface SubagentWorkerStartPayload { + cwd: string; + task: string; + systemPrompt: string; + model?: string; + toolNames?: string[]; + sessionFile?: string | null; + spawnsEnv?: string; +} + +export type SubagentWorkerRequest = { type: "start"; payload: SubagentWorkerStartPayload } | { type: "abort" }; + +export type SubagentWorkerResponse = + | { type: "event"; event: AgentEvent } + | { type: "done"; exitCode: number; durationMs: number; error?: string; aborted?: boolean }; diff --git a/packages/coding-agent/src/core/tools/task/worker.ts b/packages/coding-agent/src/core/tools/task/worker.ts new file mode 100644 index 000000000..951dfc0ea --- /dev/null +++ b/packages/coding-agent/src/core/tools/task/worker.ts @@ -0,0 +1,238 @@ +/** + * Worker thread for subagent execution. + * + * This worker runs in a separate thread via Bun's Worker API. It creates a minimal + * AgentSession and forwards events back to the parent thread. + * + * ## Event Flow + * + * 1. Parent sends { type: "start", payload } with task config + * 2. Worker creates AgentSession and subscribes to events + * 3. Worker forwards AgentEvent messages via postMessage + * 4. Worker sends { type: "done", exitCode, ... } on completion + * 5. Parent can send { type: "abort" } to request cancellation + */ + +import type { Api, Model } from "@mariozechner/pi-ai"; +import type { AgentEvent, ThinkingLevel } from "@oh-my-pi/pi-agent-core"; +import type { AgentSessionEvent } from "../../agent-session"; +import { parseModelPattern, parseModelString } from "../../model-resolver"; +import { createAgentSession, discoverAuthStorage, discoverModels } from "../../sdk"; +import { SessionManager } from "../../session-manager"; +import type { SubagentWorkerRequest, SubagentWorkerResponse, SubagentWorkerStartPayload } from "./worker-protocol"; + +type PostMessageFn = (message: SubagentWorkerResponse) => void; + +const postMessageSafe: PostMessageFn = (message) => { + (globalThis as typeof globalThis & { postMessage: PostMessageFn }).postMessage(message); +}; + +interface WorkerMessageEvent { + data: T; +} + +/** Agent event types to forward to parent (excludes session-only events like compaction) */ +const agentEventTypes = new Set([ + "agent_start", + "agent_end", + "turn_start", + "turn_end", + "message_start", + "message_update", + "message_end", + "tool_execution_start", + "tool_execution_update", + "tool_execution_end", +]); + +const isAgentEvent = (event: AgentSessionEvent): event is AgentEvent => { + return agentEventTypes.has(event.type as AgentEvent["type"]); +}; + +let running = false; +let abortRequested = false; +let activeSession: { abort: () => Promise; dispose: () => Promise } | null = null; + +/** + * Resolve model string to Model object with optional thinking level. + * Supports both exact "provider/id" format and fuzzy matching ("sonnet", "opus"). + */ +function resolveModelOverride( + override: string | undefined, + modelRegistry: { getAvailable: () => Model[]; find: (provider: string, id: string) => Model | undefined }, +): { model?: Model; thinkingLevel?: ThinkingLevel } { + if (!override) return {}; + + // Try exact "provider/id" format first + const parsed = parseModelString(override); + if (parsed) { + return { model: modelRegistry.find(parsed.provider, parsed.id) }; + } + + // Fall back to fuzzy pattern matching + const result = parseModelPattern(override, modelRegistry.getAvailable()); + return { + model: result.model, + thinkingLevel: result.thinkingLevel !== "off" ? result.thinkingLevel : undefined, + }; +} + +/** + * Main task execution function. + * + * Equivalent to CLI flow: + * 1. omp --mode json --non-interactive + * 2. --append-system-prompt + * 3. --tools (if specified) + * 4. --model (if specified) + * 5. --session OR --no-session + * 6. --prompt + * + * Environment equivalent: + * - OMP_BLOCKED_AGENT: payload.blockedAgent (prevents same-agent recursion) + * - OMP_SPAWNS: payload.spawnsEnv (controls nested spawn permissions) + */ +async function runTask(payload: SubagentWorkerStartPayload): Promise { + const startTime = Date.now(); + let exitCode = 0; + let error: string | undefined; + let aborted = false; + + try { + // Check for pre-start abort + if (abortRequested) { + aborted = true; + exitCode = 1; + return; + } + + // Set working directory (CLI does this implicitly) + process.chdir(payload.cwd); + + // Discover auth and models (equivalent to CLI's discoverAuthStorage/discoverModels) + const authStorage = await discoverAuthStorage(); + const modelRegistry = await discoverModels(authStorage); + + // Resolve model override (equivalent to CLI's parseModelPattern with --model) + const { model, thinkingLevel } = resolveModelOverride(payload.model, modelRegistry); + + // Create session manager (equivalent to CLI's --session or --no-session) + const sessionManager = payload.sessionFile + ? await SessionManager.open(payload.sessionFile) + : SessionManager.inMemory(payload.cwd); + + // Create agent session (equivalent to CLI's createAgentSession) + // Note: hasUI: false disables interactive features + const { session } = await createAgentSession({ + cwd: payload.cwd, + authStorage, + modelRegistry, + model, + thinkingLevel, + toolNames: payload.toolNames, + // Append system prompt (equivalent to CLI's --append-system-prompt) + systemPrompt: (defaultPrompt) => `${defaultPrompt}\n\n${payload.systemPrompt}`, + sessionManager, + hasUI: false, + // Pass spawn restrictions to nested tasks + spawns: payload.spawnsEnv, + }); + + activeSession = session; + + // Initialize extensions (equivalent to CLI's extension initialization) + // Note: Does not support --extension CLI flag or extension CLI flags + const extensionRunner = session.extensionRunner; + if (extensionRunner) { + extensionRunner.initialize({ + getModel: () => session.model, + sendMessageHandler: (message, options) => { + session.sendCustomMessage(message, options).catch((e) => { + console.error(`Extension sendMessage failed: ${e instanceof Error ? e.message : String(e)}`); + }); + }, + appendEntryHandler: (customType, data) => { + session.sessionManager.appendCustomEntry(customType, data); + }, + getActiveToolsHandler: () => session.getActiveToolNames(), + getAllToolsHandler: () => session.getAllToolNames(), + setActiveToolsHandler: (toolNamesList: string[]) => session.setActiveToolsByName(toolNamesList), + }); + extensionRunner.onError((err) => { + console.error(`Extension error (${err.extensionPath}): ${err.error}`); + }); + await extensionRunner.emit({ type: "session_start" }); + } + + // Subscribe to events and forward to parent (equivalent to --mode json output) + session.subscribe((event: AgentSessionEvent) => { + if (isAgentEvent(event)) { + postMessageSafe({ type: "event", event }); + } + }); + + // Run the prompt (equivalent to --prompt flag) + await session.prompt(payload.task); + + // Check if aborted during execution + const lastMessage = session.state.messages[session.state.messages.length - 1]; + if (lastMessage?.role === "assistant" && lastMessage.stopReason === "aborted") { + aborted = true; + exitCode = 1; + } + } catch (err) { + exitCode = 1; + error = err instanceof Error ? err.stack || err.message : String(err); + } finally { + // Handle abort requested during execution + if (abortRequested) { + aborted = true; + if (exitCode === 0) exitCode = 1; + } + + // Cleanup session + if (activeSession) { + try { + await activeSession.dispose(); + } catch { + // Ignore cleanup errors + } + activeSession = null; + } + + // Send completion message to parent + postMessageSafe({ + type: "done", + exitCode, + durationMs: Date.now() - startTime, + error, + aborted, + }); + } +} + +/** Handle abort request from parent */ +function handleAbort(): void { + abortRequested = true; + if (activeSession) { + void activeSession.abort(); + } +} + +// Message handler - receives start/abort commands from parent +globalThis.addEventListener("message", (event: WorkerMessageEvent) => { + const message = event.data; + if (!message) return; + + if (message.type === "abort") { + handleAbort(); + return; + } + + if (message.type === "start") { + // Only allow one task per worker + if (running) return; + running = true; + void runTask(message.payload); + } +}); diff --git a/packages/coding-agent/src/core/tools/web-fetch.ts b/packages/coding-agent/src/core/tools/web-fetch.ts index 1cc660e08..d951c38ce 100644 --- a/packages/coding-agent/src/core/tools/web-fetch.ts +++ b/packages/coding-agent/src/core/tools/web-fetch.ts @@ -5,6 +5,7 @@ import { Type } from "@sinclair/typebox"; import { parse as parseHtml } from "node-html-parser"; import webFetchDescription from "../../prompts/tools/web-fetch.md" with { type: "text" }; import { logger } from "../logger"; +import type { ToolSession } from "./index"; // ============================================================================= // Types and Constants @@ -1239,9 +1240,7 @@ async function handleStackOverflow(url: string, timeout: number): Promise { +export function createWebFetchTool(_session: ToolSession): AgentTool { return { name: "web_fetch", label: "Web Fetch", @@ -2316,9 +2315,6 @@ export function createWebFetchTool(_cwd: string): AgentTool = { - name: "web_fetch", - label: "Web Fetch", - description: webFetchDescription, - parameters: webFetchSchema, - - async execute( - toolCallId: string, - params: WebFetchParams, - _onUpdate, - _ctx: CustomToolContext, - _signal?: AbortSignal, - ) { - return webFetchTool.execute(toolCallId, params); - }, - - renderCall(args: WebFetchParams, uiTheme: Theme) { - return renderWebFetchCall(args, uiTheme); - }, - - renderResult(result, options: RenderResultOptions, uiTheme: Theme) { - return renderWebFetchResult(result, options, uiTheme); - }, -}; diff --git a/packages/coding-agent/src/core/tools/web-search/index.ts b/packages/coding-agent/src/core/tools/web-search/index.ts index 137d50edf..f7dae1c4d 100644 --- a/packages/coding-agent/src/core/tools/web-search/index.ts +++ b/packages/coding-agent/src/core/tools/web-search/index.ts @@ -20,6 +20,7 @@ import type { CustomTool, CustomToolContext, RenderResultOptions } from "../../c import { callExaTool, findApiKey as findExaKey, formatSearchResults, isSearchResponse } from "../exa/mcp-client"; import { renderExaCall, renderExaResult } from "../exa/render"; import type { ExaRenderDetails } from "../exa/types"; +import type { ToolSession } from "../index"; import { formatAge } from "../render-utils"; import { findAnthropicAuth } from "./auth"; import { searchAnthropic } from "./providers/anthropic"; @@ -365,7 +366,7 @@ export const webSearchCustomTool: CustomTool { +export function createWebSearchTool(_session: ToolSession): AgentTool { return webSearchTool; } diff --git a/packages/coding-agent/src/core/tools/web-search/render.ts b/packages/coding-agent/src/core/tools/web-search/render.ts index 35f146abe..5e518b63c 100644 --- a/packages/coding-agent/src/core/tools/web-search/render.ts +++ b/packages/coding-agent/src/core/tools/web-search/render.ts @@ -257,10 +257,7 @@ export function renderWebSearchResult( } if (response.requestId) { metaLines.push( - `${theme.fg("muted", "Request:")} ${theme.fg( - "text", - truncate(response.requestId, MAX_REQUEST_ID_LEN, theme.format.ellipsis), - )}`, + `${theme.fg("muted", "Request:")} ${theme.fg("text", truncate(response.requestId, MAX_REQUEST_ID_LEN, theme.format.ellipsis))}`, ); } if (searchQueries.length > 0) { diff --git a/packages/coding-agent/src/core/tools/write.ts b/packages/coding-agent/src/core/tools/write.ts index b5bda0d47..183f73f60 100644 --- a/packages/coding-agent/src/core/tools/write.ts +++ b/packages/coding-agent/src/core/tools/write.ts @@ -5,7 +5,8 @@ import { Type } from "@sinclair/typebox"; import { getLanguageFromPath, highlightCode, type Theme } from "../../modes/interactive/theme/theme"; import writeDescription from "../../prompts/tools/write.md" with { type: "text" }; import type { RenderResultOptions } from "../custom-tools/types"; -import { type FileDiagnosticsResult, type WritethroughCallback, writethroughNoop } from "./lsp/index"; +import type { ToolSession } from "../sdk"; +import { createLspWritethrough, type FileDiagnosticsResult } from "./lsp/index"; import { resolveToCwd } from "./path-utils"; import { formatDiagnostics, replaceTabs, shortenPath } from "./render-utils"; @@ -14,21 +15,15 @@ const writeSchema = Type.Object({ content: Type.String({ description: "Content to write to the file" }), }); -/** Options for creating the write tool */ -export interface WriteToolOptions { - writethrough?: WritethroughCallback; -} - /** Details returned by the write tool for TUI rendering */ export interface WriteToolDetails { diagnostics?: FileDiagnosticsResult; } -export function createWriteTool( - cwd: string, - options: WriteToolOptions = {}, -): AgentTool { - const writethrough = options.writethrough ?? writethroughNoop; +export function createWriteTool(session: ToolSession): AgentTool { + const enableFormat = session.settings?.getLspFormatOnWrite() ?? true; + const enableDiagnostics = session.settings?.getLspDiagnosticsOnWrite() ?? true; + const writethrough = createLspWritethrough(session.cwd, { enableFormat, enableDiagnostics }); return { name: "write", label: "Write", @@ -39,7 +34,7 @@ export function createWriteTool( { path, content }: { path: string; content: string }, signal?: AbortSignal, ) => { - const absolutePath = resolveToCwd(path, cwd); + const absolutePath = resolveToCwd(path, session.cwd); const diagnostics = await writethrough(absolutePath, content, signal); @@ -64,9 +59,6 @@ export function createWriteTool( }; } -/** Default write tool using process.cwd() - for backwards compatibility */ -export const writeTool = createWriteTool(process.cwd()); - // ============================================================================= // TUI Renderer // ============================================================================= diff --git a/packages/coding-agent/src/discovery/helpers.test.ts b/packages/coding-agent/src/discovery/helpers.test.ts index f955741fe..55e56e5e8 100644 --- a/packages/coding-agent/src/discovery/helpers.test.ts +++ b/packages/coding-agent/src/discovery/helpers.test.ts @@ -1,4 +1,4 @@ -import { describe, expect, test } from "vitest"; +import { describe, expect, test } from "bun:test"; import { parseFrontmatter } from "./helpers"; describe("parseFrontmatter", () => { diff --git a/packages/coding-agent/src/index.ts b/packages/coding-agent/src/index.ts index 9574363eb..92ae0d6db 100644 --- a/packages/coding-agent/src/index.ts +++ b/packages/coding-agent/src/index.ts @@ -81,6 +81,8 @@ export { ModelRegistry } from "./core/model-registry"; export type { PromptTemplate } from "./core/prompt-templates"; // SDK for programmatic usage export { + // Tool factories + BUILTIN_TOOLS, type BuildSystemPromptOptions, buildSystemPrompt, type CreateAgentSessionOptions, @@ -88,14 +90,12 @@ export { // Factory createAgentSession, createBashTool, - // Tool factories (for custom cwd) - createCodingTools, createEditTool, createFindTool, createGrepTool, createLsTool, - createReadOnlyTools, createReadTool, + createTools, createWriteTool, // Discovery discoverAuthStorage, @@ -107,8 +107,7 @@ export { discoverPromptTemplates, discoverSkills, loadSettings, - // Pre-built tools (use process.cwd()) - readOnlyTools, + type ToolSession, } from "./core/sdk"; export { type BranchSummaryEntry, @@ -154,27 +153,17 @@ export { } from "./core/skills"; // Slash commands export { type FileSlashCommand, loadSlashCommands as discoverSlashCommands } from "./core/slash-commands"; -// Tools +// Tools (detail types only - factories exported from sdk) export { type BashToolDetails, - bashTool, - type CodingToolsOptions, - codingTools, - editTool, type FindToolDetails, - findTool, type GitToolDetails, type GrepToolDetails, gitTool, - grepTool, type LsToolDetails, - lsTool, type ReadToolDetails, - readTool, type TruncationResult, type WriteToolDetails, - type WriteToolOptions, - writeTool, } from "./core/tools/index"; export type { FileDiagnosticsResult } from "./core/tools/lsp/index"; // Main entry point diff --git a/packages/coding-agent/src/main.ts b/packages/coding-agent/src/main.ts index 5f354043d..439ba7241 100644 --- a/packages/coding-agent/src/main.ts +++ b/packages/coding-agent/src/main.ts @@ -24,7 +24,6 @@ import { SessionManager } from "./core/session-manager"; import { SettingsManager } from "./core/settings-manager"; import { resolvePromptInput } from "./core/system-prompt"; import { printTimings, time } from "./core/timings"; -import { allTools } from "./core/tools/index"; import { runMigrations, showDeprecationWarnings } from "./migrations"; import { InteractiveMode, installTerminalCrashHandlers, runPrintMode, runRpcMode } from "./modes/index"; import { initTheme, stopThemeWatcher } from "./modes/interactive/theme/theme"; @@ -210,7 +209,9 @@ async function buildSessionOptions( modelRegistry: ModelRegistry, settingsManager: SettingsManager, ): Promise { - const options: CreateAgentSessionOptions = {}; + const options: CreateAgentSessionOptions = { + cwd: parsed.cwd ?? process.cwd(), + }; // Auto-discover SYSTEM.md if no CLI system prompt provided const systemPromptSource = parsed.systemPrompt ?? discoverSystemPromptFile(); @@ -263,8 +264,7 @@ async function buildSessionOptions( // Tools if (parsed.tools) { - options.tools = parsed.tools.map((name) => allTools[name]); - options.explicitTools = parsed.tools; + options.toolNames = parsed.tools; } // Skills diff --git a/packages/coding-agent/src/modes/interactive/theme/theme.ts b/packages/coding-agent/src/modes/interactive/theme/theme.ts index ae68c1926..c16054d9f 100644 --- a/packages/coding-agent/src/modes/interactive/theme/theme.ts +++ b/packages/coding-agent/src/modes/interactive/theme/theme.ts @@ -1367,9 +1367,9 @@ export class Theme { return (str: string) => this.fg("bashMode", str); } - // ------------------------------------------------------------------------- + // ============================================================================ // Symbol Methods - // ------------------------------------------------------------------------- + // ============================================================================ /** * Get a symbol by key. @@ -1392,9 +1392,9 @@ export class Theme { return this.symbolPreset; } - // ------------------------------------------------------------------------- + // ============================================================================ // Symbol Category Accessors - // ------------------------------------------------------------------------- + // ============================================================================ get status() { return { diff --git a/packages/coding-agent/src/prompts/browser.md b/packages/coding-agent/src/prompts/browser.md deleted file mode 100644 index 4aa7942c0..000000000 --- a/packages/coding-agent/src/prompts/browser.md +++ /dev/null @@ -1,71 +0,0 @@ ---- -name: browser -description: Fetches and renders a single URL into clean, digestible text for extraction -tools: bash -model: claude-haiku-4-5, haiku, flash, mini ---- - -You are a web content extraction specialist. Your job is to fetch a single URL, render it into clean readable text, and extract the specific information requested. - -=== CRITICAL: EXTRACTION ONLY === -This is a SINGLE-URL extraction task. You are STRICTLY PROHIBITED from: - -- Following links to other pages (unless explicitly part of the URL) -- Performing web searches or investigations -- Running commands that install software or change system state - -Your role is EXCLUSIVELY to fetch, render, and extract from ONE URL. - -=== HOW TO FETCH === - -Use the `omp render-web` command to fetch and render the URL: - -```bash -omp render-web "" -``` - -This command automatically: - -1. Checks for LLM-friendly endpoints (llms.txt, llms.md) -2. Tries content negotiation for markdown/plain text -3. Looks for page-specific alternate feeds (RSS, Atom) -4. Falls back to lynx for HTML→text rendering -5. Pretty-prints JSON/XML if applicable -6. Reports any issues (JS-gated pages, truncation, etc.) - -Options: - -- `--raw` — Output only the content, no metadata headers -- `--json` — Structured JSON output with metadata -- `--timeout ` — Request timeout (default: 20) - -=== WORKFLOW === - -1. Run `omp render-web ""` to fetch the page -2. Review the output — check the "Method" and "Notes" fields for any issues -3. If the page appears JS-gated or incomplete, note this in your response -4. Extract the specific information requested by the caller -5. Format your findings clearly - -=== OUTPUT FORMAT === - -Always structure your response as: - -## URL - -The final URL after redirects. - -## Metadata - -``` -Content-Type: -Method: -``` - -## Extracted Information - -The specific information requested by the caller, clearly formatted. - -## Notes - -Any issues encountered (JS-gated, paywall, truncated, etc). diff --git a/packages/coding-agent/src/prompts/task.md b/packages/coding-agent/src/prompts/task.md index 1b00fe2e1..d508050a0 100644 --- a/packages/coding-agent/src/prompts/task.md +++ b/packages/coding-agent/src/prompts/task.md @@ -1,10 +1,3 @@ ---- -name: task -description: General-purpose subagent with full capabilities for delegated multi-step tasks -spawns: explore -model: default ---- - You are a worker agent for delegated tasks. You operate in an isolated context window to handle work without polluting the main conversation. Do what has been asked; nothing more, nothing less. Work autonomously using all available tools. diff --git a/packages/coding-agent/src/prompts/tools/output.md b/packages/coding-agent/src/prompts/tools/output.md index 16977c05f..4dcca1288 100644 --- a/packages/coding-agent/src/prompts/tools/output.md +++ b/packages/coding-agent/src/prompts/tools/output.md @@ -1,16 +1,16 @@ -# TaskOutput - Retrieves complete output from background tasks spawned with the Task tool. ## When to Use Use TaskOutput when: + - Task tool returns truncated preview with "Output truncated" message - You need full output to debug errors or analyze detailed results - Task tool's summary shows substantial line/character counts but preview is incomplete - You're analyzing multi-step task output requiring full context Do NOT use when: + - Task preview already shows complete output (no truncation indicator) - Summary alone answers your question diff --git a/packages/coding-agent/src/prompts/tools/task.md b/packages/coding-agent/src/prompts/tools/task.md new file mode 100644 index 000000000..342d1bb9f --- /dev/null +++ b/packages/coding-agent/src/prompts/tools/task.md @@ -0,0 +1,68 @@ +Launch a new agent to handle complex, multi-step tasks autonomously. + +The Task tool launches specialized agents (workers) that autonomously handle complex tasks. Each agent type has specific capabilities and tools available to it. + +## Available Agents + +{{AGENTS_LIST}} + +## When NOT to Use + +- Reading a specific file path → Use Read or Glob tool instead +- Searching for a specific class/function definition → Use Glob tool instead +- Searching code within 2-3 specific files → Use Read tool instead +- Tasks unrelated to the agent descriptions above + +## Usage Notes + +- Always include a short description of the task in the task parameter +- **Plan-then-execute**: Put shared constraints in `context`, keep each task focused, specify output format and acceptance criteria +- **Minimize tool chatter**: Avoid repeating large context; use Output tool with output ids for full logs +- **Parallelize**: Launch multiple agents concurrently whenever possible +- **Results are intermediate data**: Agent findings provide context for YOU to perform actual work. Do not treat agent reports as "task complete" signals. +- **Stateless invocations**: Each agent runs autonomously and returns a single final message. Include all necessary context and specify exactly what information to return. +- **Trust outputs**: Agent results should generally be trusted +- **Clarify intent**: Tell the agent whether you expect code changes or just research (search, file reads, web fetches) +- **Proactive use**: If an agent description says to use it proactively, do so without waiting for explicit user request + +## Parameters + +- `tasks`: Array of `{agent, task, description?, model?}` - tasks to run in parallel (max {{MAX_PARALLEL_TASKS}}, {{MAX_CONCURRENCY}} concurrent) + - `model`: (optional) Override the agent's default model with fuzzy matching (e.g., "sonnet", "codex", "5.2"). Supports comma-separated fallbacks: "gpt, opus" tries gpt first, then opus. Use "default" for omp's default model +- `context`: (optional) Shared context string prepended to all task prompts - use this to avoid repeating instructions + +## Examples + + +user: "Please write a function that checks if a number is prime" +assistant: Sure let me write a function that checks if a number is prime +assistant: I'm going to use the Write tool to write the following code: + +function isPrime(n) { + if (n <= 1) return false + for (let i = 2; i * i <= n; i++) { + if (n % i === 0) return false + } + return true +} + + +Since a significant piece of code was written and the task was completed, now use the code-reviewer agent to review the code + +assistant: Now let me use the code-reviewer agent to review the code +assistant: Uses the Task tool: { tasks: [{ agent: "code-reviewer", task: "Review the isPrime function" }] } + + + +user: "Find all TODO comments in the codebase" +assistant: I'll use multiple explore agents to search different directories in parallel +assistant: Uses the Task tool: +{ + "context": "Find all TODO comments. Return file:line:content format.", + "tasks": [ + { "agent": "explore", "task": "Search in src/" }, + { "agent": "explore", "task": "Search in lib/" }, + { "agent": "explore", "task": "Search in tests/" } + ] +} + diff --git a/packages/coding-agent/test/agent-session-branching.test.ts b/packages/coding-agent/test/agent-session-branching.test.ts index f5d5a9888..157c8d788 100644 --- a/packages/coding-agent/test/agent-session-branching.test.ts +++ b/packages/coding-agent/test/agent-session-branching.test.ts @@ -18,7 +18,7 @@ import { AuthStorage } from "../src/core/auth-storage"; import { ModelRegistry } from "../src/core/model-registry"; import { SessionManager } from "../src/core/session-manager"; import { SettingsManager } from "../src/core/settings-manager"; -import { codingTools } from "../src/core/tools/index"; +import { createTools, type ToolSession } from "../src/core/tools/index"; import { API_KEY } from "./utilities"; describe.skipIf(!API_KEY)("AgentSession branching", () => { @@ -41,14 +41,23 @@ describe.skipIf(!API_KEY)("AgentSession branching", () => { } }); - function createSession(noSession: boolean = false) { + async function createSession(noSession: boolean = false) { + const toolSession: ToolSession = { + cwd: tempDir, + hasUI: false, + rulebookRules: [], + getSessionFile: () => null, + getSessionSpawns: () => "*", + }; + const tools = await createTools(toolSession); + const model = getModel("anthropic", "claude-sonnet-4-5")!; const agent = new Agent({ getApiKey: () => API_KEY, initialState: { model, systemPrompt: "You are a helpful assistant. Be extremely concise, reply with just a few words.", - tools: codingTools, + tools, }, }); diff --git a/packages/coding-agent/test/agent-session-compaction.test.ts b/packages/coding-agent/test/agent-session-compaction.test.ts index 9b2407a95..711366183 100644 --- a/packages/coding-agent/test/agent-session-compaction.test.ts +++ b/packages/coding-agent/test/agent-session-compaction.test.ts @@ -18,7 +18,7 @@ import { AuthStorage } from "../src/core/auth-storage"; import { ModelRegistry } from "../src/core/model-registry"; import { SessionManager } from "../src/core/session-manager"; import { SettingsManager } from "../src/core/settings-manager"; -import { codingTools } from "../src/core/tools/index"; +import { createTools, type ToolSession } from "../src/core/tools/index"; import { API_KEY } from "./utilities"; describe.skipIf(!API_KEY)("AgentSession compaction e2e", () => { @@ -45,14 +45,23 @@ describe.skipIf(!API_KEY)("AgentSession compaction e2e", () => { } }); - function createSession(inMemory = false) { + async function createSession(inMemory = false) { + const toolSession: ToolSession = { + cwd: tempDir, + hasUI: false, + rulebookRules: [], + getSessionFile: () => null, + getSessionSpawns: () => "*", + }; + const tools = await createTools(toolSession); + const model = getModel("anthropic", "claude-sonnet-4-5")!; const agent = new Agent({ getApiKey: () => API_KEY, initialState: { model, systemPrompt: "You are a helpful assistant. Be concise.", - tools: codingTools, + tools, }, }); diff --git a/packages/coding-agent/test/agent-session-tree-navigation.test.ts b/packages/coding-agent/test/agent-session-tree-navigation.test.ts index 4817876a9..89d4228ce 100644 --- a/packages/coding-agent/test/agent-session-tree-navigation.test.ts +++ b/packages/coding-agent/test/agent-session-tree-navigation.test.ts @@ -15,8 +15,8 @@ import { API_KEY, createTestSession, type TestSessionContext } from "./utilities describe.skipIf(!API_KEY)("AgentSession tree navigation e2e", () => { let ctx: TestSessionContext; - beforeEach(() => { - ctx = createTestSession({ + beforeEach(async () => { + ctx = await createTestSession({ systemPrompt: "You are a helpful assistant. Reply with just a few words.", settingsOverrides: { compaction: { keepRecentTokens: 1 } }, }); @@ -274,8 +274,8 @@ describe.skipIf(!API_KEY)("AgentSession tree navigation e2e", () => { describe.skipIf(!API_KEY)("AgentSession tree navigation - branch scenarios", () => { let ctx: TestSessionContext; - beforeEach(() => { - ctx = createTestSession({ + beforeEach(async () => { + ctx = await createTestSession({ systemPrompt: "You are a helpful assistant. Reply with just a few words.", }); }); diff --git a/packages/coding-agent/test/compaction-hooks.test.ts b/packages/coding-agent/test/compaction-hooks.test.ts index 4f5d696fc..23a3df4f3 100644 --- a/packages/coding-agent/test/compaction-hooks.test.ts +++ b/packages/coding-agent/test/compaction-hooks.test.ts @@ -20,7 +20,7 @@ import { import { ModelRegistry } from "../src/core/model-registry"; import { SessionManager } from "../src/core/session-manager"; import { SettingsManager } from "../src/core/settings-manager"; -import { createCodingTools } from "../src/core/tools/index"; +import { createTools, type ToolSession } from "../src/core/tools/index"; import { theme } from "../src/modes/interactive/theme/theme"; const API_KEY = process.env.ANTHROPIC_OAUTH_TOKEN || process.env.ANTHROPIC_API_KEY; @@ -84,8 +84,15 @@ describe.skipIf(!API_KEY)("Compaction hooks", () => { } async function createSession(hooks: LoadedHook[]) { + const toolSession: ToolSession = { + cwd: tempDir, + hasUI: false, + rulebookRules: [], + getSessionFile: () => null, + getSessionSpawns: () => "*", + }; + const tools = await createTools(toolSession); const model = getModel("anthropic", "claude-sonnet-4-5")!; - const tools = await createCodingTools(tempDir); const agent = new Agent({ getApiKey: () => API_KEY, initialState: { diff --git a/packages/coding-agent/test/compaction-thinking-model.test.ts b/packages/coding-agent/test/compaction-thinking-model.test.ts index ccfcccde6..812fc72c5 100644 --- a/packages/coding-agent/test/compaction-thinking-model.test.ts +++ b/packages/coding-agent/test/compaction-thinking-model.test.ts @@ -19,7 +19,7 @@ import { AuthStorage } from "../src/core/auth-storage"; import { ModelRegistry } from "../src/core/model-registry"; import { SessionManager } from "../src/core/session-manager"; import { SettingsManager } from "../src/core/settings-manager"; -import { codingTools } from "../src/core/tools/index"; +import { createTools, type ToolSession } from "../src/core/tools/index"; import { API_KEY } from "./utilities"; // Check for auth @@ -44,10 +44,19 @@ describe.skipIf(!HAS_ANTIGRAVITY_AUTH)("Compaction with thinking models (Antigra } }); - function createSession( + async function createSession( modelId: "claude-opus-4-5-thinking" | "claude-sonnet-4-5", thinkingLevel: ThinkingLevel = "high", ) { + const toolSession: ToolSession = { + cwd: tempDir, + hasUI: false, + rulebookRules: [], + getSessionFile: () => null, + getSessionSpawns: () => "*", + }; + const tools = await createTools(toolSession); + const model = getModel("google-antigravity", modelId); if (!model) { throw new Error(`Model not found: google-antigravity/${modelId}`); @@ -58,7 +67,7 @@ describe.skipIf(!HAS_ANTIGRAVITY_AUTH)("Compaction with thinking models (Antigra initialState: { model, systemPrompt: "You are a helpful assistant. Be concise.", - tools: codingTools, + tools, thinkingLevel, }, }); @@ -148,13 +157,22 @@ describe.skipIf(!HAS_ANTHROPIC_AUTH)("Compaction with thinking models (Anthropic } }); - function createSession(model: Model, thinkingLevel: ThinkingLevel = "high") { + async function createSession(model: Model, thinkingLevel: ThinkingLevel = "high") { + const toolSession: ToolSession = { + cwd: tempDir, + hasUI: false, + rulebookRules: [], + getSessionFile: () => null, + getSessionSpawns: () => "*", + }; + const tools = await createTools(toolSession); + const agent = new Agent({ getApiKey: () => API_KEY, initialState: { model, systemPrompt: "You are a helpful assistant. Be concise.", - tools: codingTools, + tools, thinkingLevel, }, }); diff --git a/packages/coding-agent/test/tools.test.ts b/packages/coding-agent/test/tools.test.ts index 8ed72598c..083a78e71 100644 --- a/packages/coding-agent/test/tools.test.ts +++ b/packages/coding-agent/test/tools.test.ts @@ -2,13 +2,14 @@ import { afterEach, beforeEach, describe, expect, it } from "bun:test"; import { mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { bashTool } from "../src/core/tools/bash"; -import { editTool } from "../src/core/tools/edit"; -import { findTool } from "../src/core/tools/find"; -import { grepTool } from "../src/core/tools/grep"; -import { lsTool } from "../src/core/tools/ls"; -import { readTool } from "../src/core/tools/read"; -import { writeTool } from "../src/core/tools/write"; +import { createBashTool } from "../src/core/tools/bash"; +import { createEditTool } from "../src/core/tools/edit"; +import { createFindTool } from "../src/core/tools/find"; +import { createGrepTool } from "../src/core/tools/grep"; +import type { ToolSession } from "../src/core/tools/index"; +import { createLsTool } from "../src/core/tools/ls"; +import { createReadTool } from "../src/core/tools/read"; +import { createWriteTool } from "../src/core/tools/write"; // Helper to extract text from content blocks function getTextOutput(result: any): string { @@ -20,13 +21,40 @@ function getTextOutput(result: any): string { ); } +function createTestToolSession(cwd: string): ToolSession { + return { + cwd, + hasUI: false, + rulebookRules: [], + getSessionFile: () => null, + getSessionSpawns: () => "*", + }; +} + describe("Coding Agent Tools", () => { let testDir: string; + let readTool: ReturnType; + let writeTool: ReturnType; + let editTool: ReturnType; + let bashTool: ReturnType; + let grepTool: ReturnType; + let findTool: ReturnType; + let lsTool: ReturnType; beforeEach(() => { // Create a unique temporary directory for each test testDir = join(tmpdir(), `coding-agent-test-${Date.now()}`); mkdirSync(testDir, { recursive: true }); + + // Create tools for this test directory + const session = createTestToolSession(testDir); + readTool = createReadTool(session); + writeTool = createWriteTool(session); + editTool = createEditTool(session); + bashTool = createBashTool(session); + grepTool = createGrepTool(session); + findTool = createFindTool(session); + lsTool = createLsTool(session); }); afterEach(() => { @@ -461,10 +489,12 @@ function b() { describe("edit tool CRLF handling", () => { let testDir: string; + let editTool: ReturnType; beforeEach(() => { testDir = join(tmpdir(), `coding-agent-crlf-test-${Date.now()}`); mkdirSync(testDir, { recursive: true }); + editTool = createEditTool(createTestToolSession(testDir)); }); afterEach(() => { diff --git a/packages/coding-agent/test/utilities.ts b/packages/coding-agent/test/utilities.ts index ca688b86b..d6d7fe7a4 100644 --- a/packages/coding-agent/test/utilities.ts +++ b/packages/coding-agent/test/utilities.ts @@ -12,7 +12,7 @@ import { AuthStorage } from "../src/core/auth-storage"; import { ModelRegistry } from "../src/core/model-registry"; import { SessionManager } from "../src/core/session-manager"; import { SettingsManager } from "../src/core/settings-manager"; -import { codingTools } from "../src/core/tools/index"; +import { createTools, type ToolSession } from "../src/core/tools/index"; /** * API key for authenticated tests. Tests using this should be wrapped in @@ -76,17 +76,26 @@ export interface TestSessionContext { * Create an AgentSession for testing with proper setup and cleanup. * Use this for e2e tests that need real LLM calls. */ -export function createTestSession(options: TestSessionOptions = {}): TestSessionContext { +export async function createTestSession(options: TestSessionOptions = {}): Promise { const tempDir = join(tmpdir(), `omp-test-${Date.now()}-${Math.random().toString(36).slice(2)}`); mkdirSync(tempDir, { recursive: true }); + const toolSession: ToolSession = { + cwd: tempDir, + hasUI: false, + rulebookRules: [], + getSessionFile: () => null, + getSessionSpawns: () => "*", + }; + const tools = await createTools(toolSession); + const model = getModel("anthropic", "claude-sonnet-4-5")!; const agent = new Agent({ getApiKey: () => API_KEY, initialState: { model, systemPrompt: options.systemPrompt ?? "You are a helpful assistant. Be extremely concise.", - tools: codingTools, + tools, }, }); diff --git a/packages/coding-agent/test/worktree/collapse.test.ts b/packages/coding-agent/test/worktree/collapse.test.ts index 13e745155..933a8f9a8 100644 --- a/packages/coding-agent/test/worktree/collapse.test.ts +++ b/packages/coding-agent/test/worktree/collapse.test.ts @@ -1,7 +1,7 @@ +import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { mkdtemp, rm } from "node:fs/promises"; import * as os from "node:os"; import * as path from "node:path"; -import { afterEach, beforeEach, describe, expect, test } from "vitest"; import { collapse } from "../../src/lib/worktree/collapse"; import { WORKTREE_BASE } from "../../src/lib/worktree/constants"; import { getRepoRoot, git } from "../../src/lib/worktree/git"; diff --git a/packages/coding-agent/test/worktree/operations.test.ts b/packages/coding-agent/test/worktree/operations.test.ts index d719a73d0..eea56823d 100644 --- a/packages/coding-agent/test/worktree/operations.test.ts +++ b/packages/coding-agent/test/worktree/operations.test.ts @@ -1,8 +1,8 @@ +import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { existsSync } from "node:fs"; import { mkdtemp, rm } from "node:fs/promises"; import * as os from "node:os"; import * as path from "node:path"; -import { afterEach, beforeEach, describe, expect, test } from "vitest"; import { WORKTREE_BASE } from "../../src/lib/worktree/constants"; import { WorktreeError } from "../../src/lib/worktree/errors"; import { git } from "../../src/lib/worktree/git"; diff --git a/packages/coding-agent/tsconfig.check.json b/packages/coding-agent/tsconfig.check.json new file mode 100644 index 000000000..52dfa54af --- /dev/null +++ b/packages/coding-agent/tsconfig.check.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "noEmit": true + }, + "include": ["src/**/*.ts", "test/**/*.ts", "src/bun-imports.d.ts"], + "exclude": ["node_modules", "dist"] +} diff --git a/packages/git-tool/src/render.ts b/packages/git-tool/src/render.ts index 3c08adc62..18ea7968d 100644 --- a/packages/git-tool/src/render.ts +++ b/packages/git-tool/src/render.ts @@ -33,16 +33,12 @@ export function renderStatus(result: StatusResult): string { if (result.staged.length > 0) { parts.push( - `Staged (${result.staged.length}):\n${result.staged - .map((file) => `- ${file.path} (${file.status})`) - .join("\n")}`, + `Staged (${result.staged.length}):\n${result.staged.map((file) => `- ${file.path} (${file.status})`).join("\n")}`, ); } if (result.modified.length > 0) { parts.push( - `Modified (${result.modified.length}):\n${result.modified - .map((file) => `- ${file.path} (${file.status})`) - .join("\n")}`, + `Modified (${result.modified.length}):\n${result.modified.map((file) => `- ${file.path} (${file.status})`).join("\n")}`, ); } if (result.untracked.length > 0) {