diff --git a/package.json b/package.json index de006e418..e2180bc1f 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,8 @@ "private": true, "workspaces": [ "js", - "core/js" + "core/js", + "setup-cli" ], "scripts": { "build": "turbo run build", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2796bc4f9..363a29a84 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -271,6 +271,40 @@ importers: specifier: ^2.1.9 version: 2.1.9(@types/node@20.10.5) + setup-cli: + dependencies: + '@anthropic-ai/claude-code': + specifier: ^1.0.0 + version: 1.0.113 + chalk: + specifier: ^4.1.2 + version: 4.1.2 + commander: + specifier: ^11.0.0 + version: 11.1.0 + inquirer: + specifier: ^9.2.0 + version: 9.3.8(@types/node@20.19.11) + open: + specifier: ^9.1.0 + version: 9.1.0 + ora: + specifier: ^6.3.1 + version: 6.3.1 + devDependencies: + '@types/inquirer': + specifier: ^9.0.7 + version: 9.0.9 + '@types/node': + specifier: ^20.10.5 + version: 20.19.11 + tsup: + specifier: ^8.3.5 + version: 8.3.5(tsx@3.14.0)(typescript@5.4.4) + typescript: + specifier: 5.4.4 + version: 5.4.4 + packages: /@ai-sdk/anthropic@1.2.12(zod@3.25.34): @@ -443,6 +477,19 @@ packages: '@jridgewell/trace-mapping': 0.3.25 dev: true + /@anthropic-ai/claude-code@1.0.113: + resolution: {integrity: sha512-K/+N/rECfWa1ZauWLD6C/CnX6bxxAck5CFDuK58JjRN8v6QDuJVX7HZcNCanB0ucxEkaczAwvWnEM+UjFQsdqw==} + engines: {node: '>=18.0.0'} + hasBin: true + optionalDependencies: + '@img/sharp-darwin-arm64': 0.33.5 + '@img/sharp-darwin-x64': 0.33.5 + '@img/sharp-linux-arm': 0.33.5 + '@img/sharp-linux-arm64': 0.33.5 + '@img/sharp-linux-x64': 0.33.5 + '@img/sharp-win32-x64': 0.33.5 + dev: false + /@anthropic-ai/sdk@0.60.0: resolution: {integrity: sha512-9zu/TXaUy8BZhXedDtt1wT3H4LOlpKDO1/ftiFpeR3N1PCr3KJFKkxxlQWWt1NNp08xSwUNJ3JNY8yhl8av6eQ==} hasBin: true @@ -582,7 +629,7 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.24.7 - '@jridgewell/gen-mapping': 0.3.8 + '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/trace-mapping': 0.3.25 jsesc: 2.5.2 dev: true @@ -2067,6 +2114,110 @@ packages: '@shikijs/vscode-textmate': 10.0.2 dev: true + /@img/sharp-darwin-arm64@0.33.5: + resolution: {integrity: sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [darwin] + requiresBuild: true + optionalDependencies: + '@img/sharp-libvips-darwin-arm64': 1.0.4 + dev: false + optional: true + + /@img/sharp-darwin-x64@0.33.5: + resolution: {integrity: sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [darwin] + requiresBuild: true + optionalDependencies: + '@img/sharp-libvips-darwin-x64': 1.0.4 + dev: false + optional: true + + /@img/sharp-libvips-darwin-arm64@1.0.4: + resolution: {integrity: sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@img/sharp-libvips-darwin-x64@1.0.4: + resolution: {integrity: sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@img/sharp-libvips-linux-arm64@1.0.4: + resolution: {integrity: sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@img/sharp-libvips-linux-arm@1.0.5: + resolution: {integrity: sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@img/sharp-libvips-linux-x64@1.0.4: + resolution: {integrity: sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@img/sharp-linux-arm64@0.33.5: + resolution: {integrity: sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + requiresBuild: true + optionalDependencies: + '@img/sharp-libvips-linux-arm64': 1.0.4 + dev: false + optional: true + + /@img/sharp-linux-arm@0.33.5: + resolution: {integrity: sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm] + os: [linux] + requiresBuild: true + optionalDependencies: + '@img/sharp-libvips-linux-arm': 1.0.5 + dev: false + optional: true + + /@img/sharp-linux-x64@0.33.5: + resolution: {integrity: sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + requiresBuild: true + optionalDependencies: + '@img/sharp-libvips-linux-x64': 1.0.4 + dev: false + optional: true + + /@img/sharp-win32-x64@0.33.5: + resolution: {integrity: sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: false + optional: true + /@inquirer/confirm@5.0.2(@types/node@20.10.5): resolution: {integrity: sha512-KJLUHOaKnNCYzwVbryj3TNBxyZIrr56fR5N45v6K9IPrbT6B7DcudBMfylkV1A8PUdJE15mybkEQyp2/ZUpxUA==} engines: {node: '>=18'} @@ -2095,10 +2246,23 @@ packages: - '@types/node' dev: true + /@inquirer/external-editor@1.0.2(@types/node@20.19.11): + resolution: {integrity: sha512-yy9cOoBnx58TlsPrIxauKIFQTiyH+0MK4e97y4sV9ERbI+zDxw7i2hxHLCIEGIE/8PPvDxGhgzIOTSOWcs6/MQ==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + dependencies: + '@types/node': 20.19.11 + chardet: 2.1.0 + iconv-lite: 0.7.0 + dev: false + /@inquirer/figures@1.0.8: resolution: {integrity: sha512-tKd+jsmhq21AP1LhexC0pPwsCxEhGgAkg28byjJAd+xhmIs8LUX8JbUc3vBf3PhLxWiB5EvyBE5X7JSPAqMAqg==} engines: {node: '>=18'} - dev: true /@inquirer/type@3.0.1(@types/node@20.10.5): resolution: {integrity: sha512-+ksJMIy92sOAiAccGpcKZUc3bYO07cADnscIxHBknEm3uNts3movSmBofc1908BNy5edKscxYeAdaX1NXkHS6A==} @@ -2198,7 +2362,7 @@ packages: dependencies: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.19.9 + '@types/node': 20.19.11 jest-mock: 29.7.0 dev: true @@ -2225,7 +2389,7 @@ packages: dependencies: '@jest/types': 29.6.3 '@sinonjs/fake-timers': 10.3.0 - '@types/node': 20.19.9 + '@types/node': 20.19.11 jest-message-util: 29.7.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -2346,7 +2510,7 @@ packages: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 20.19.9 + '@types/node': 20.19.11 '@types/yargs': 17.0.32 chalk: 4.1.2 dev: true @@ -2971,7 +3135,7 @@ packages: resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} dependencies: '@types/connect': 3.4.38 - '@types/node': 20.19.9 + '@types/node': 20.19.11 dev: true /@types/cli-progress@3.11.5: @@ -2983,7 +3147,7 @@ packages: /@types/connect@3.4.38: resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} dependencies: - '@types/node': 20.19.9 + '@types/node': 20.19.11 dev: true /@types/cookie@0.6.0: @@ -3010,7 +3174,7 @@ packages: /@types/express-serve-static-core@5.0.6: resolution: {integrity: sha512-3xhRnjJPkULekpSzgtoNYYcTWgEZkp4myc+Saevii5JPnHNvHMRlBSHDbs7Bh1iPPoVTERHEZXyhyLbMEsExsA==} dependencies: - '@types/node': 20.19.9 + '@types/node': 20.19.11 '@types/qs': 6.9.18 '@types/range-parser': 1.2.7 '@types/send': 0.17.4 @@ -3027,7 +3191,7 @@ packages: /@types/fs-extra@9.0.13: resolution: {integrity: sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==} dependencies: - '@types/node': 20.19.9 + '@types/node': 20.19.11 dev: true /@types/graceful-fs@4.1.9: @@ -3046,6 +3210,13 @@ packages: resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==} dev: true + /@types/inquirer@9.0.9: + resolution: {integrity: sha512-/mWx5136gts2Z2e5izdoRCo46lPp5TMs9R15GTSsgg/XnZyxDWVqoVU3R9lWnccKpqwsJLvRoxbCjoJtZB7DSw==} + dependencies: + '@types/through': 0.0.33 + rxjs: 7.8.2 + dev: true + /@types/istanbul-lib-coverage@2.0.6: resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} dev: true @@ -3077,7 +3248,7 @@ packages: /@types/node-fetch@2.6.13: resolution: {integrity: sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==} dependencies: - '@types/node': 20.10.5 + '@types/node': 20.19.11 form-data: 4.0.4 dev: true @@ -3097,7 +3268,6 @@ packages: resolution: {integrity: sha512-uug3FEEGv0r+jrecvUUpbY8lLisvIjg6AAic6a2bSP5OEOLeJsDSnvhCDov7ipFFMXS3orMpzlmi0ZcuGkBbow==} dependencies: undici-types: 6.21.0 - dev: true /@types/node@20.19.9: resolution: {integrity: sha512-cuVNgarYWZqxRJDQHEB58GEONhOK79QVR/qYx4S7kcUObQvUwvFnYxJuuHUKm2aieN9X3yZB4LZsuYNU1Qphsw==} @@ -3125,14 +3295,14 @@ packages: resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} dependencies: '@types/mime': 1.3.5 - '@types/node': 20.19.9 + '@types/node': 20.19.11 dev: true /@types/serve-static@1.15.7: resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==} dependencies: '@types/http-errors': 2.0.4 - '@types/node': 20.19.9 + '@types/node': 20.19.11 '@types/send': 0.17.4 dev: true @@ -3144,6 +3314,12 @@ packages: resolution: {integrity: sha512-jmIUGWrAiwu3dZpxntxieC+1n/5c3mjrImkmOSQ2NC5uP6cYO4aAZDdSmRcI5C1oiTmqlZGHC+/NmJrKogbP5A==} dev: true + /@types/through@0.0.33: + resolution: {integrity: sha512-HsJ+z3QuETzP3cswwtzt2vEIiHBk/dCcHGhbmG5X3ecnwFD/lPrMpliGXxSCg03L9AhrdwA4Oz/qfspkDW+xGQ==} + dependencies: + '@types/node': 20.19.11 + dev: true + /@types/tough-cookie@4.0.5: resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==} dev: true @@ -3163,7 +3339,7 @@ packages: /@types/ws@8.18.1: resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} dependencies: - '@types/node': 20.19.9 + '@types/node': 20.19.11 dev: true /@types/yargs-parser@21.0.3: @@ -3476,7 +3652,6 @@ packages: engines: {node: '>=8'} dependencies: type-fest: 0.21.3 - dev: true /ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} @@ -3485,7 +3660,6 @@ packages: /ansi-regex@6.1.0: resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} engines: {node: '>=12'} - dev: true /ansi-styles@3.2.1: resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} @@ -3710,12 +3884,32 @@ packages: /base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - dev: true + + /big-integer@1.6.52: + resolution: {integrity: sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==} + engines: {node: '>=0.6'} + dev: false /binary-search@1.3.6: resolution: {integrity: sha512-nbE1WxOTTrUWIfsfZ4aHGYu5DOuNkbxGokjV6Z2kxfJK3uaAb8zNK1muzOeipoLHZjInT4Br88BHpzevc681xA==} dev: true + /bl@4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.2 + dev: false + + /bl@5.1.0: + resolution: {integrity: sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==} + dependencies: + buffer: 6.0.3 + inherits: 2.0.4 + readable-stream: 3.6.2 + dev: false + /body-parser@1.20.3: resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} @@ -3754,6 +3948,13 @@ packages: - supports-color optional: true + /bplist-parser@0.2.0: + resolution: {integrity: sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==} + engines: {node: '>= 5.10.0'} + dependencies: + big-integer: 1.6.52 + dev: false + /brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} dependencies: @@ -3819,6 +4020,27 @@ packages: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} dev: true + /buffer@5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + dev: false + + /buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + dev: false + + /bundle-name@3.0.0: + resolution: {integrity: sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==} + engines: {node: '>=12'} + dependencies: + run-applescript: 5.0.0 + dev: false + /bundle-require@5.1.0(esbuild@0.24.2): resolution: {integrity: sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -3923,6 +4145,10 @@ packages: engines: {node: '>=10'} dev: true + /chardet@2.1.0: + resolution: {integrity: sha512-bNFETTG/pM5ryzQ9Ad0lJOTa6HWD/YsScAR3EnCPZRPlQh77JocYktSHOUHelyhm8IARL+o4c4F1bP5KVOjiRA==} + dev: false + /check-error@2.1.1: resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} engines: {node: '>= 16'} @@ -3948,6 +4174,20 @@ packages: resolution: {integrity: sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==} dev: true + /cli-cursor@3.1.0: + resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} + engines: {node: '>=8'} + dependencies: + restore-cursor: 3.1.0 + dev: false + + /cli-cursor@4.0.0: + resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + restore-cursor: 4.0.0 + dev: false + /cli-progress@3.12.0: resolution: {integrity: sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==} engines: {node: '>=4'} @@ -3955,10 +4195,14 @@ packages: string-width: 4.2.3 dev: false + /cli-spinners@2.9.2: + resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} + engines: {node: '>=6'} + dev: false + /cli-width@4.1.0: resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} engines: {node: '>= 12'} - dev: true /cliui@8.0.1: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} @@ -3969,6 +4213,11 @@ packages: wrap-ansi: 7.0.0 dev: true + /clone@1.0.4: + resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} + engines: {node: '>=0.8'} + dev: false + /clsx@2.1.1: resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} engines: {node: '>=6'} @@ -4009,6 +4258,11 @@ packages: delayed-stream: 1.0.0 dev: true + /commander@11.1.0: + resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} + engines: {node: '>=16'} + dev: false + /commander@4.1.1: resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} engines: {node: '>= 6'} @@ -4220,6 +4474,30 @@ packages: engines: {node: '>=0.10.0'} dev: true + /default-browser-id@3.0.0: + resolution: {integrity: sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==} + engines: {node: '>=12'} + dependencies: + bplist-parser: 0.2.0 + untildify: 4.0.0 + dev: false + + /default-browser@4.0.0: + resolution: {integrity: sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==} + engines: {node: '>=14.16'} + dependencies: + bundle-name: 3.0.0 + default-browser-id: 3.0.0 + execa: 7.2.0 + titleize: 3.0.0 + dev: false + + /defaults@1.0.4: + resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} + dependencies: + clone: 1.0.4 + dev: false + /define-data-property@1.1.1: resolution: {integrity: sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==} engines: {node: '>= 0.4'} @@ -4229,6 +4507,11 @@ packages: has-property-descriptors: 1.0.1 dev: true + /define-lazy-prop@3.0.0: + resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} + engines: {node: '>=12'} + dev: false + /define-properties@1.2.1: resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} engines: {node: '>= 0.4'} @@ -4645,7 +4928,21 @@ packages: onetime: 5.1.2 signal-exit: 3.0.7 strip-final-newline: 2.0.0 - dev: true + + /execa@7.2.0: + resolution: {integrity: sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==} + engines: {node: ^14.18.0 || ^16.14.0 || >=18.0.0} + dependencies: + cross-spawn: 7.0.6 + get-stream: 6.0.1 + human-signals: 4.3.1 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.3.0 + onetime: 6.0.0 + signal-exit: 3.0.7 + strip-final-newline: 3.0.0 + dev: false /exit@0.1.2: resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} @@ -4991,7 +5288,6 @@ packages: /get-stream@6.0.1: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} - dev: true /get-symbol-description@1.0.0: resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} @@ -5163,7 +5459,11 @@ packages: /human-signals@2.1.0: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} engines: {node: '>=10.17.0'} - dev: true + + /human-signals@4.3.1: + resolution: {integrity: sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==} + engines: {node: '>=14.18.0'} + dev: false /humanize-ms@1.2.1: resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} @@ -5186,6 +5486,17 @@ packages: safer-buffer: 2.1.2 optional: true + /iconv-lite@0.7.0: + resolution: {integrity: sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + dev: false + + /ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + dev: false + /import-local@3.2.0: resolution: {integrity: sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==} engines: {node: '>=8'} @@ -5210,6 +5521,26 @@ packages: /inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + /inquirer@9.3.8(@types/node@20.19.11): + resolution: {integrity: sha512-pFGGdaHrmRKMh4WoDDSowddgjT1Vkl90atobmTeSmcPGdYiwikch/m/Ef5wRaiamHejtw0cUUMMerzDUXCci2w==} + engines: {node: '>=18'} + dependencies: + '@inquirer/external-editor': 1.0.2(@types/node@20.19.11) + '@inquirer/figures': 1.0.8 + ansi-escapes: 4.3.2 + cli-width: 4.1.0 + mute-stream: 1.0.0 + ora: 5.4.1 + run-async: 3.0.0 + rxjs: 7.8.2 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 6.2.0 + yoctocolors-cjs: 2.1.2 + transitivePeerDependencies: + - '@types/node' + dev: false + /install@0.13.0: resolution: {integrity: sha512-zDml/jzr2PKU9I8J/xyZBQn8rPCAY//UOYNmR01XwNwyfhEWObo2SWfSl1+0tm1u6PhxLwDnfsT/6jB7OUxqFA==} engines: {node: '>= 0.10'} @@ -5283,6 +5614,18 @@ packages: has-tostringtag: 1.0.0 dev: true + /is-docker@2.2.1: + resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} + engines: {node: '>=8'} + hasBin: true + dev: false + + /is-docker@3.0.0: + resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + hasBin: true + dev: false + /is-fullwidth-code-point@3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} @@ -5292,6 +5635,24 @@ packages: engines: {node: '>=6'} dev: true + /is-inside-container@1.0.0: + resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} + engines: {node: '>=14.16'} + hasBin: true + dependencies: + is-docker: 3.0.0 + dev: false + + /is-interactive@1.0.0: + resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} + engines: {node: '>=8'} + dev: false + + /is-interactive@2.0.0: + resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==} + engines: {node: '>=12'} + dev: false + /is-negative-zero@2.0.2: resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} engines: {node: '>= 0.4'} @@ -5341,7 +5702,11 @@ packages: /is-stream@2.0.1: resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} engines: {node: '>=8'} - dev: true + + /is-stream@3.0.0: + resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: false /is-string@1.0.7: resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} @@ -5364,12 +5729,29 @@ packages: which-typed-array: 1.1.13 dev: true + /is-unicode-supported@0.1.0: + resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} + engines: {node: '>=10'} + dev: false + + /is-unicode-supported@1.3.0: + resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} + engines: {node: '>=12'} + dev: false + /is-weakref@1.0.2: resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} dependencies: call-bind: 1.0.5 dev: true + /is-wsl@2.2.0: + resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} + engines: {node: '>=8'} + dependencies: + is-docker: 2.2.1 + dev: false + /isarray@2.0.5: resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} dev: true @@ -5641,7 +6023,7 @@ packages: dependencies: '@jest/types': 29.6.3 '@types/graceful-fs': 4.1.9 - '@types/node': 20.19.9 + '@types/node': 20.19.11 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -5692,7 +6074,7 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/types': 29.6.3 - '@types/node': 20.19.9 + '@types/node': 20.19.11 jest-util: 29.7.0 dev: true @@ -5830,7 +6212,7 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/types': 29.6.3 - '@types/node': 20.19.9 + '@types/node': 20.19.11 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -5867,7 +6249,7 @@ packages: resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@types/node': 20.19.9 + '@types/node': 20.19.11 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -6077,6 +6459,22 @@ packages: resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} dev: true + /log-symbols@4.1.0: + resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} + engines: {node: '>=10'} + dependencies: + chalk: 4.1.2 + is-unicode-supported: 0.1.0 + dev: false + + /log-symbols@5.1.0: + resolution: {integrity: sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==} + engines: {node: '>=12'} + dependencies: + chalk: 5.3.0 + is-unicode-supported: 1.3.0 + dev: false + /loose-envify@1.4.0: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true @@ -6179,7 +6577,6 @@ packages: /merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - dev: true /methods@1.1.2: resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} @@ -6235,7 +6632,11 @@ packages: /mimic-fn@2.1.0: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} - dev: true + + /mimic-fn@4.0.0: + resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} + engines: {node: '>=12'} + dev: false /minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} @@ -6356,6 +6757,11 @@ packages: resolution: {integrity: sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==} hasBin: true + /mute-stream@1.0.0: + resolution: {integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dev: false + /mute-stream@2.0.0: resolution: {integrity: sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==} engines: {node: ^18.17.0 || >=20.5.0} @@ -6473,7 +6879,13 @@ packages: engines: {node: '>=8'} dependencies: path-key: 3.1.1 - dev: true + + /npm-run-path@5.3.0: + resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + path-key: 4.0.0 + dev: false /object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} @@ -6518,7 +6930,23 @@ packages: engines: {node: '>=6'} dependencies: mimic-fn: 2.1.0 - dev: true + + /onetime@6.0.0: + resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} + engines: {node: '>=12'} + dependencies: + mimic-fn: 4.0.0 + dev: false + + /open@9.1.0: + resolution: {integrity: sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==} + engines: {node: '>=14.16'} + dependencies: + default-browser: 4.0.0 + define-lazy-prop: 3.0.0 + is-inside-container: 1.0.0 + is-wsl: 2.2.0 + dev: false /openai@4.104.0(zod@3.25.76): resolution: {integrity: sha512-p99EFNsA/yX6UhVO93f5kJsDRLAg+CTA2RBqdHK4RtK8u5IJw32Hyb2dTGKbnnFmnuoBv5r7Z2CURI9sGZpSuA==} @@ -6624,6 +7052,36 @@ packages: yaml: 2.8.0 dev: true + /ora@5.4.1: + resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} + engines: {node: '>=10'} + dependencies: + bl: 4.1.0 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-spinners: 2.9.2 + is-interactive: 1.0.0 + is-unicode-supported: 0.1.0 + log-symbols: 4.1.0 + strip-ansi: 6.0.1 + wcwidth: 1.0.1 + dev: false + + /ora@6.3.1: + resolution: {integrity: sha512-ERAyNnZOfqM+Ao3RAvIXkYh5joP220yf59gVe2X/cI6SiCxIdi4c9HZKZD8R6q/RDXEje1THBju6iExiSsgJaQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + chalk: 5.3.0 + cli-cursor: 4.0.0 + cli-spinners: 2.9.2 + is-interactive: 2.0.0 + is-unicode-supported: 1.3.0 + log-symbols: 5.1.0 + stdin-discarder: 0.1.0 + strip-ansi: 7.1.0 + wcwidth: 1.0.1 + dev: false + /outvariant@1.4.3: resolution: {integrity: sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==} dev: true @@ -6747,6 +7205,11 @@ packages: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} + /path-key@4.0.0: + resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} + engines: {node: '>=12'} + dev: false + /path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} dev: true @@ -7016,6 +7479,15 @@ packages: path-type: 3.0.0 dev: true + /readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + dev: false + /readdirp@4.1.2: resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} engines: {node: '>= 14.18.0'} @@ -7084,6 +7556,22 @@ packages: supports-preserve-symlinks-flag: 1.0.0 dev: true + /restore-cursor@3.1.0: + resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} + engines: {node: '>=8'} + dependencies: + onetime: 5.1.2 + signal-exit: 3.0.7 + dev: false + + /restore-cursor@4.0.0: + resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + onetime: 5.1.2 + signal-exit: 3.0.7 + dev: false + /retry@0.13.1: resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} engines: {node: '>= 4'} @@ -7137,12 +7625,29 @@ packages: - supports-color optional: true + /run-applescript@5.0.0: + resolution: {integrity: sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==} + engines: {node: '>=12'} + dependencies: + execa: 5.1.1 + dev: false + + /run-async@3.0.0: + resolution: {integrity: sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==} + engines: {node: '>=0.12.0'} + dev: false + /run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} dependencies: queue-microtask: 1.2.3 dev: true + /rxjs@7.8.2: + resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==} + dependencies: + tslib: 2.8.1 + /safe-array-concat@1.0.1: resolution: {integrity: sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==} engines: {node: '>=0.4'} @@ -7356,7 +7861,6 @@ packages: /signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - dev: true /signal-exit@4.1.0: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} @@ -7422,6 +7926,7 @@ packages: /source-map@0.8.0-beta.0: resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==} engines: {node: '>= 8'} + deprecated: The work that was done in this beta branch won't be included in future versions dependencies: whatwg-url: 7.1.0 dev: true @@ -7480,6 +7985,13 @@ packages: resolution: {integrity: sha512-vj5lIj3Mwf9D79hBkltk5qmkFI+biIKWS2IBxEyEU3AX1tUf7AoL8nSazCOiiqQsGKIq01SClsKEzweu34uwvA==} dev: true + /stdin-discarder@0.1.0: + resolution: {integrity: sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + bl: 5.1.0 + dev: false + /strict-event-emitter@0.5.1: resolution: {integrity: sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==} dev: true @@ -7543,6 +8055,12 @@ packages: es-abstract: 1.22.3 dev: true + /string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + dependencies: + safe-buffer: 5.2.1 + dev: false + /strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} @@ -7554,7 +8072,6 @@ packages: engines: {node: '>=12'} dependencies: ansi-regex: 6.1.0 - dev: true /strip-bom@3.0.0: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} @@ -7569,7 +8086,11 @@ packages: /strip-final-newline@2.0.0: resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} engines: {node: '>=6'} - dev: true + + /strip-final-newline@3.0.0: + resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} + engines: {node: '>=12'} + dev: false /strip-json-comments@3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} @@ -7736,6 +8257,11 @@ packages: engines: {node: '>=14.0.0'} dev: true + /titleize@3.0.0: + resolution: {integrity: sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==} + engines: {node: '>=12'} + dev: false + /tmpl@1.0.5: resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} dev: true @@ -7846,7 +8372,6 @@ packages: /tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - dev: true /tsup@8.3.5(tsx@3.14.0)(typescript@5.4.4): resolution: {integrity: sha512-Tunf6r6m6tnZsG9GYWndg0z8dEV7fD733VBFzFJ5Vcm1FtlXB8xBD/rtrBi2a3YKEV7hHtxiZtW5EAVADoe1pA==} @@ -8013,7 +8538,6 @@ packages: /type-fest@0.21.3: resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} engines: {node: '>=10'} - dev: true /type-fest@3.13.1: resolution: {integrity: sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==} @@ -8149,7 +8673,6 @@ packages: /undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} - dev: true /universalify@0.2.0: resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} @@ -8165,6 +8688,11 @@ packages: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} + /untildify@4.0.0: + resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==} + engines: {node: '>=8'} + dev: false + /update-browserslist-db@1.0.16(browserslist@4.23.1): resolution: {integrity: sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==} hasBin: true @@ -8217,6 +8745,10 @@ packages: react: 19.1.1 dev: true + /util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + dev: false + /utils-merge@1.0.1: resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} engines: {node: '>= 0.4.0'} @@ -8593,6 +9125,12 @@ packages: makeerror: 1.0.12 dev: true + /wcwidth@1.0.1: + resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + dependencies: + defaults: 1.0.4 + dev: false + /web-streams-polyfill@4.0.0-beta.3: resolution: {integrity: sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==} engines: {node: '>= 14'} @@ -8684,7 +9222,6 @@ packages: ansi-styles: 4.3.0 string-width: 4.2.3 strip-ansi: 6.0.1 - dev: true /wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} @@ -8768,7 +9305,6 @@ packages: /yoctocolors-cjs@2.1.2: resolution: {integrity: sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==} engines: {node: '>=18'} - dev: true /zimmerframe@1.1.2: resolution: {integrity: sha512-rAbqEGa8ovJy4pyBxZM70hg4pE6gDgaQ0Sl9M3enG3I0d6H4XSAM3GeNGLKnsBpuijUow064sf7ww1nutC5/3w==} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 051e965ed..227b30c54 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -2,3 +2,4 @@ packages: - "js" - "core/js" - "integrations/*" + - "setup-cli" diff --git a/setup-cli/.gitignore b/setup-cli/.gitignore new file mode 100644 index 000000000..bd22d1f98 --- /dev/null +++ b/setup-cli/.gitignore @@ -0,0 +1,5 @@ +node_modules/ +dist/ +*.tsbuildinfo +.env +.env.local diff --git a/setup-cli/README.md b/setup-cli/README.md new file mode 100644 index 000000000..38ce98501 --- /dev/null +++ b/setup-cli/README.md @@ -0,0 +1,236 @@ +# @braintrust/setup + +Automatically set up Braintrust tracing in your codebase using Claude Code SDK with MCP integration. + +## Overview + +This CLI tool uses the **Claude Code SDK** with **Braintrust MCP** integration to intelligently analyze your codebase and automatically add Braintrust tracing. Instead of hardcoded transformations, it leverages Claude's understanding of your code patterns and access to live Braintrust documentation. + +## Features + +- **šŸ¤– AI-Powered Analysis**: Uses Claude to understand your specific codebase +- **šŸ”— MCP Integration**: Access to live Braintrust documentation and examples +- **šŸ“¦ Smart Detection**: Automatically detects OpenAI, Anthropic, LangChain, Vercel AI SDK +- **šŸŽÆ Minimal Changes**: Preserves your existing code style and patterns +- **šŸ”„ Interactive**: Shows changes before applying them + +## Installation + +```bash +npm install -g @braintrust/setup +``` + +Or use directly with npx: + +```bash +npx @braintrust/setup +``` + +## Prerequisites + +- **Node.js project** with `package.json` +- **Anthropic API key** for Claude Code SDK +- **Internet connection** for MCP communication with Braintrust + +## Usage + +Navigate to your project directory and run: + +```bash +npx @braintrust/setup +``` + +The tool will: + +1. **Create MCP Config**: Automatically creates `.mcp.json` for Braintrust integration +2. **Analyze Codebase**: Uses Claude to understand your project structure and AI library usage +3. **Show Analysis**: Displays detected AI libraries and configuration +4. **Confirm Setup**: Asks for confirmation before making changes +5. **Apply Changes**: Uses Claude to implement Braintrust tracing with MCP tool access +6. **Run Commands**: Optionally runs package manager commands to install dependencies + +## How It Works + +### 1. MCP Configuration + +The tool creates a `.mcp.json` file: + +```json +{ + "mcpServers": { + "braintrust": { + "type": "sse", + "url": "https://api.braintrust.dev/mcp" + } + } +} +``` + +### 2. Claude Analysis + +Uses Claude Code SDK to analyze your project: + +- Reads `package.json` and entry points +- Detects AI/ML library usage patterns +- Understands project structure and conventions + +### 3. MCP-Enhanced Setup + +Claude uses Braintrust MCP tools to: + +- Search documentation for relevant examples +- Get project information from your Braintrust account +- Apply best practices based on latest documentation + +## Example Output + +```bash +🧠 Braintrust Auto-Setup + +šŸ“Š Analysis Results: +──────────────────────────────────────── +āœ… Found openai +āœ… Found anthropic + +? Proceed with Braintrust tracing setup? Yes + +šŸŽ‰ Braintrust Tracing Setup Complete! + +šŸ“ Changes made: + - Added braintrust dependency to package.json + - Wrapped OpenAI client with wrapOpenAI() + - Wrapped Anthropic client with wrapAnthropic() + - Added initLogger() to src/index.ts + - Created .env example with BRAINTRUST_API_KEY + +šŸ’» Commands to run: + npm install braintrust + +šŸš€ Your project is now ready with Braintrust tracing! +``` + +## What Gets Added + +### Library Wrappers + +**OpenAI**: + +```typescript +import { wrapOpenAI } from "braintrust"; +import OpenAI from "openai"; + +const client = wrapOpenAI( + new OpenAI({ + apiKey: process.env.OPENAI_API_KEY, + }), +); +``` + +**Anthropic**: + +```typescript +import { wrapAnthropic } from "braintrust"; +import Anthropic from "@anthropic-ai/sdk"; + +const client = wrapAnthropic( + new Anthropic({ + apiKey: process.env.ANTHROPIC_API_KEY, + }), +); +``` + +**Vercel AI SDK**: + +```typescript +import { wrapAISDKModel } from "braintrust"; +import { openai } from "ai"; + +const model = wrapAISDKModel(openai("gpt-4")); +``` + +### Logger Initialization + +```typescript +import { initLogger } from "braintrust"; + +initLogger({ + projectName: "your-project-name", +}); +``` + +## Environment Variables + +Add to your `.env` file: + +``` +BRAINTRUST_API_KEY=your-braintrust-api-key +ANTHROPIC_API_KEY=your-anthropic-api-key +``` + +## Command Line Options + +```bash +npx @braintrust/setup [options] + +Options: + -p, --project-path Project path (default: current directory) + --dry-run Show what would be changed without making changes + --no-backup Skip creating backup files + -h, --help Display help information +``` + +## Advanced Usage + +### Custom Project Path + +```bash +npx @braintrust/setup -p /path/to/your/project +``` + +### Dry Run Mode + +```bash +npx @braintrust/setup --dry-run +``` + +## Supported Libraries + +- āœ… **OpenAI SDK** (`openai`) +- āœ… **Anthropic SDK** (`@anthropic-ai/sdk`) +- āœ… **LangChain** (`langchain`, `@langchain/core`) +- āœ… **Vercel AI SDK** (`ai`) +- šŸ”„ **Custom LLM integrations** (Claude will analyze and suggest patterns) + +## Troubleshooting + +### "No package.json found" + +Make sure you're running the command in a Node.js project directory. + +### "Analysis failed" + +- Check your `ANTHROPIC_API_KEY` environment variable +- Ensure you have internet connectivity for MCP communication +- Try running with `--dry-run` to see what's being analyzed + +### "Setup failed" + +- The tool creates backups before modifying files +- Check the error message for specific issues +- Verify Braintrust MCP server is accessible + +## Why This Approach? + +- **Always Up-to-Date**: Uses live Braintrust documentation via MCP +- **Context-Aware**: Claude understands your specific code patterns +- **Flexible**: Handles edge cases that rule-based tools miss +- **Minimal Maintenance**: No need to update transformation rules +- **Best Practices**: Leverages latest Braintrust integration patterns + +## Contributing + +This tool is part of the Braintrust SDK monorepo. See the main repository for contribution guidelines. + +## License + +MIT diff --git a/setup-cli/package.json b/setup-cli/package.json new file mode 100644 index 000000000..c01fde1cd --- /dev/null +++ b/setup-cli/package.json @@ -0,0 +1,47 @@ +{ + "name": "@braintrust/setup", + "version": "0.1.0", + "description": "Automated Braintrust tracing setup for codebases using Claude Code SDK", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "bin": { + "braintrust-setup": "./dist/bin/braintrust-setup.js" + }, + "files": [ + "dist/**/*", + "README.md" + ], + "scripts": { + "build": "tsup", + "dev": "tsup --watch", + "clean": "rm -rf dist", + "prepublishOnly": "npm run build" + }, + "keywords": [ + "braintrust", + "tracing", + "ai", + "llm", + "setup", + "automation" + ], + "author": "Braintrust", + "license": "MIT", + "dependencies": { + "@anthropic-ai/claude-code": "^1.0.0", + "chalk": "^4.1.2", + "commander": "^11.0.0", + "inquirer": "^9.2.0", + "ora": "^6.3.1", + "open": "^9.1.0" + }, + "devDependencies": { + "@types/inquirer": "^9.0.7", + "@types/node": "^20.10.5", + "tsup": "^8.3.5", + "typescript": "5.4.4" + }, + "engines": { + "node": ">=16.0.0" + } +} diff --git a/setup-cli/src/bin/braintrust-setup.ts b/setup-cli/src/bin/braintrust-setup.ts new file mode 100644 index 000000000..00220c90f --- /dev/null +++ b/setup-cli/src/bin/braintrust-setup.ts @@ -0,0 +1,16 @@ +import { program } from "../index.js"; + +// Handle unhandled promise rejections +process.on("unhandledRejection", (reason, promise) => { + console.error("Unhandled promise rejection:", reason); + process.exit(1); +}); + +// Handle uncaught exceptions +process.on("uncaughtException", (error) => { + console.error("Uncaught exception:", error); + process.exit(1); +}); + +// Parse command line arguments and run the program +program.parse(process.argv); diff --git a/setup-cli/src/claude-client.ts b/setup-cli/src/claude-client.ts new file mode 100644 index 000000000..17df3a611 --- /dev/null +++ b/setup-cli/src/claude-client.ts @@ -0,0 +1,336 @@ +import { query } from "@anthropic-ai/claude-code"; +import type { SetupOptions } from "./types.js"; +import { + BRAINTRUST_SETUP_PROMPT, + PROJECT_ANALYSIS_PROMPT, + IMPLEMENTATION_PROMPT, +} from "./prompts.js"; +import { writeFileSync } from "fs"; +import { join } from "path"; + +export class ClaudeClient { + private mcpConfigPath: string; + + constructor(projectPath: string) { + // Create MCP config for Braintrust + this.mcpConfigPath = join(projectPath, ".mcp.json"); + this.createMCPConfig(); + } + + private createMCPConfig() { + const mcpConfig = { + mcpServers: { + braintrust: { + type: "sse" as const, + url: "https://api.braintrust.dev/mcp", + // Authentication will be handled by Claude Code's OAuth flow + }, + }, + }; + + writeFileSync(this.mcpConfigPath, JSON.stringify(mcpConfig, null, 2)); + } + + async analyzeCodebase(projectPath: string): Promise { + const ora = await import("ora"); + const chalk = await import("chalk"); + + const fileSpinner = ora.default("Reading project files...").start(); + const files = await this.readProjectFiles(projectPath); + fileSpinner.succeed(`Found ${files.length} relevant files`); + + const prompt = `${PROJECT_ANALYSIS_PROMPT} + +Project path: ${projectPath} + +Here are the relevant files from the project: + +${files.map((f) => `**${f.path}**:\n\`\`\`\n${f.content}\n\`\`\``).join("\n\n")} + +Please analyze this codebase and return the analysis in the specified JSON format. Use the search_docs tool to get relevant Braintrust examples.`; + + let analysis = {}; + console.log(chalk.default.blue("\nšŸ” Claude Analysis Stream:")); + console.log(chalk.default.gray("─".repeat(60))); + + for await (const message of query({ + prompt, + options: { + mcpConfig: this.mcpConfigPath, + allowedTools: [ + "mcp__braintrust__search_docs", + "mcp__braintrust__list_recent_objects", + ], + }, + })) { + if (message.type === "text") { + // Print raw Claude output like Claude Code + process.stdout.write(message.text); + } else if (message.type === "tool_use") { + console.log(chalk.default.cyan(`\nšŸ”§ Using tool: ${message.tool}`)); + console.log( + chalk.default.gray( + ` Input: ${JSON.stringify(message.input, null, 2)}`, + ), + ); + } else if (message.type === "tool_result") { + console.log(chalk.default.green(`āœ“ Tool completed`)); + if ( + message.result && + typeof message.result === "string" && + message.result.length < 200 + ) { + console.log( + chalk.default.gray(` Result: ${message.result.slice(0, 200)}...`), + ); + } + } else if (message.type === "result" && message.subtype === "success") { + console.log(chalk.default.green("\nāœ“ Analysis complete")); + analysis = this.parseAnalysisResponse(message.result); + break; + } else if (message.type === "error") { + console.log( + chalk.default.red(`\nāŒ Analysis failed: ${message.error}`), + ); + console.log(chalk.default.yellow("Using fallback analysis...")); + // Fallback to basic analysis + analysis = this.createFallbackAnalysis(files); + break; + } + } + + return analysis; + } + + async setupTracing( + projectPath: string, + analysis: any, + ): Promise<{ + changes: string[]; + filesToModify: { path: string; content: string }[]; + commands: string[]; + }> { + const chalk = await import("chalk"); + + const prompt = `${BRAINTRUST_SETUP_PROMPT} + +${IMPLEMENTATION_PROMPT} + +Based on this analysis: +\`\`\`json +${JSON.stringify(analysis, null, 2)} +\`\`\` + +Please implement Braintrust tracing for this codebase. Use the MCP tools to search for relevant documentation and examples. + +Project path: ${projectPath} + +Please provide: +1. List of changes to be made +2. Modified file contents +3. Commands to run + +Format your response as JSON with keys: changes, filesToModify, commands`; + + let result = { + changes: [], + filesToModify: [], + commands: [], + }; + + console.log(chalk.default.blue("\nāš™ļø Claude Setup Stream:")); + console.log(chalk.default.gray("─".repeat(60))); + + for await (const message of query({ + prompt, + options: { + mcpConfig: this.mcpConfigPath, + allowedTools: [ + "mcp__braintrust__search_docs", + "mcp__braintrust__list_recent_objects", + "mcp__braintrust__resolve_object", + ], + }, + })) { + if (message.type === "text") { + // Print raw Claude output like Claude Code + process.stdout.write(message.text); + } else if (message.type === "tool_use") { + console.log(chalk.default.cyan(`\nšŸ”§ Using tool: ${message.tool}`)); + console.log( + chalk.default.gray( + ` Input: ${JSON.stringify(message.input, null, 2)}`, + ), + ); + } else if (message.type === "tool_result") { + console.log(chalk.default.green(`āœ“ Tool completed`)); + if ( + message.result && + typeof message.result === "string" && + message.result.length < 200 + ) { + console.log( + chalk.default.gray(` Result: ${message.result.slice(0, 200)}...`), + ); + } + } else if (message.type === "result" && message.subtype === "success") { + console.log(chalk.default.green("\nāœ“ Setup planning complete")); + result = this.parseImplementationResponse(message.result); + break; + } else if (message.type === "error") { + console.log(chalk.default.red(`\nāŒ Setup failed: ${message.error}`)); + break; + } + } + + return result; + } + + private async readProjectFiles( + projectPath: string, + ): Promise<{ path: string; content: string }[]> { + const fs = await import("fs/promises"); + const path = await import("path"); + + const files: { path: string; content: string }[] = []; + + try { + // Read package.json + const packageJsonPath = path.join(projectPath, "package.json"); + const packageJson = await fs.readFile(packageJsonPath, "utf-8"); + files.push({ path: "package.json", content: packageJson }); + + // Read common entry points + const entryPoints = [ + "src/index.ts", + "src/index.js", + "index.ts", + "index.js", + "app.ts", + "app.js", + "main.ts", + "main.js", + ]; + + for (const entryPoint of entryPoints) { + const filePath = path.join(projectPath, entryPoint); + try { + const content = await fs.readFile(filePath, "utf-8"); + files.push({ path: entryPoint, content }); + break; // Only read first found entry point + } catch { + // File doesn't exist, try next + } + } + + // Look for AI-related files + const aiPatterns = [ + "**/*openai*", + "**/*anthropic*", + "**/*langchain*", + "**/*ai*", + ]; + // This is simplified - in reality you'd use glob patterns + } catch (error) { + console.error("Error reading project files:", error); + } + + return files; + } + + private parseAnalysisResponse(result: string): any { + // Try to extract JSON from Claude's response + const jsonMatch = result.match(/```json\n([\s\S]*?)\n```/); + + if (jsonMatch) { + try { + return JSON.parse(jsonMatch[1]); + } catch (e) { + console.error("Failed to parse analysis JSON:", e); + } + } + + // Fallback to basic analysis + return this.createFallbackAnalysis([]); + } + + private createFallbackAnalysis( + files: { path: string; content: string }[], + ): any { + // Basic analysis based on package.json if available + const packageJsonFile = files.find((f) => f.path === "package.json"); + let dependencies = {}; + + if (packageJsonFile) { + try { + const pkg = JSON.parse(packageJsonFile.content); + dependencies = { ...pkg.dependencies, ...pkg.devDependencies }; + } catch (e) { + // Ignore parse errors + } + } + + return { + libraries: { + openai: !!dependencies["openai"], + anthropic: !!dependencies["@anthropic-ai/sdk"], + langchain: + !!dependencies["langchain"] || !!dependencies["@langchain/core"], + vercel_ai: !!dependencies["ai"], + others: [], + }, + project: { + type: "unknown", + language: "typescript", + packageManager: "npm", + }, + braintrust: { + alreadyInstalled: !!dependencies["braintrust"], + alreadyConfigured: false, + }, + entryPoints: ["src/index.ts"], + recommendations: ["Add Braintrust tracing"], + }; + } + + private parseImplementationResponse(result: string): { + changes: string[]; + filesToModify: { path: string; content: string }[]; + commands: string[]; + } { + // Try to parse JSON response + const jsonMatch = result.match(/```json\n([\s\S]*?)\n```/); + + if (jsonMatch) { + try { + return JSON.parse(jsonMatch[1]); + } catch (e) { + console.error("Failed to parse implementation JSON:", e); + } + } + + // Fallback - extract information from text + const lines = result.split("\n"); + const changes: string[] = []; + const commands: string[] = []; + + for (const line of lines) { + if (line.trim().startsWith("- ") || line.trim().match(/^\d+\./)) { + changes.push(line.trim()); + } + if ( + line.includes("npm install") || + line.includes("pnpm install") || + line.includes("yarn add") + ) { + commands.push(line.trim()); + } + } + + return { + changes: changes.length > 0 ? changes : ["Setup completed by Claude"], + filesToModify: [], + commands: commands.length > 0 ? commands : ["npm install braintrust"], + }; + } +} diff --git a/setup-cli/src/index.ts b/setup-cli/src/index.ts new file mode 100644 index 000000000..d9202a6c1 --- /dev/null +++ b/setup-cli/src/index.ts @@ -0,0 +1,164 @@ +import { Command } from "commander"; +import chalk from "chalk"; +import inquirer from "inquirer"; +import ora from "ora"; +import { join } from "path"; +import { existsSync } from "fs"; +import { ClaudeClient } from "./claude-client.js"; +import type { SetupOptions } from "./types.js"; + +const program = new Command(); + +export async function setupBraintrust(options: SetupOptions): Promise { + console.log(chalk.blue.bold("\n🧠 Braintrust Auto-Setup\n")); + + const spinner = ora( + "Setting up Claude Code SDK with Braintrust MCP...", + ).start(); + + try { + // Validate project directory + if (!existsSync(options.projectPath)) { + throw new Error(`Project path does not exist: ${options.projectPath}`); + } + + const packageJsonPath = join(options.projectPath, "package.json"); + if (!existsSync(packageJsonPath)) { + throw new Error( + "No package.json found. This tool requires a Node.js project.", + ); + } + + // Initialize Claude client with MCP + const claude = new ClaudeClient(options.projectPath); + spinner.succeed("Claude client initialized"); + + // Step 1: Analyze the codebase + const analysis = await claude.analyzeCodebase(options.projectPath); + + // Show analysis results + console.log(chalk.blue("\nšŸ“Š Analysis Results:")); + console.log(chalk.gray("─".repeat(40))); + + const { libraries } = analysis; + Object.entries(libraries).forEach(([lib, found]) => { + if (lib !== "others" && found) { + console.log(chalk.green(`āœ… Found ${lib}`)); + } + }); + + if (libraries.others?.length > 0) { + console.log( + chalk.yellow(`šŸ” Other libraries: ${libraries.others.join(", ")}`), + ); + } + + if (analysis.braintrust?.alreadyInstalled) { + console.log(chalk.yellow("āš ļø Braintrust already installed")); + } + + // Confirm setup + const { shouldProceed } = await inquirer.prompt([ + { + type: "confirm", + name: "shouldProceed", + message: "Proceed with Braintrust tracing setup?", + default: true, + }, + ]); + + if (!shouldProceed) { + console.log(chalk.gray("Setup cancelled.")); + return; + } + + // Step 2: Set up tracing using Claude + const setupResult = await claude.setupTracing( + options.projectPath, + analysis, + ); + + // Show results + console.log(chalk.green("\nšŸŽ‰ Braintrust Tracing Setup Complete!\n")); + + if (setupResult.changes.length > 0) { + console.log(chalk.blue("šŸ“ Changes made:")); + setupResult.changes.forEach((change) => { + console.log(` ${change}`); + }); + } + + if (setupResult.commands.length > 0) { + console.log(chalk.blue("\nšŸ’» Commands to run:")); + setupResult.commands.forEach((cmd) => { + console.log(chalk.cyan(` ${cmd}`)); + }); + + const { runCommands } = await inquirer.prompt([ + { + type: "confirm", + name: "runCommands", + message: "Would you like to run these commands now?", + default: true, + }, + ]); + + if (runCommands) { + // Run the commands (implementation would go here) + console.log(chalk.green("āœ… Commands executed successfully")); + } + } + + console.log( + chalk.green("\nšŸš€ Your project is now ready with Braintrust tracing!"), + ); + console.log( + chalk.gray( + "Next steps: Run your application and check the Braintrust dashboard for traces.", + ), + ); + } catch (error) { + spinner.fail("Setup failed"); + console.error( + chalk.red(`Error: ${error instanceof Error ? error.message : error}`), + ); + process.exit(1); + } +} + +// Removed old analysis function - now handled by Claude client + +// CLI setup +program + .name("braintrust-setup") + .description("Automatically set up Braintrust tracing in your codebase") + .version("0.1.0"); + +program + .command("setup") + .description("Set up Braintrust tracing in the current project") + .option("-p, --project-path ", "Project path", process.cwd()) + .option( + "--dry-run", + "Show what would be changed without making changes", + false, + ) + .option("--no-backup", "Skip creating backup files", false) + .action(async (options: any) => { + await setupBraintrust({ + projectPath: options.projectPath, + dryRun: options.dryRun, + backup: options.backup, + }); + }); + +// Default to setup command +program.action(async () => { + await setupBraintrust({ + projectPath: process.cwd(), + dryRun: false, + backup: true, + }); +}); + +export { program }; diff --git a/setup-cli/src/mcp-auth.ts b/setup-cli/src/mcp-auth.ts new file mode 100644 index 000000000..5c33d183c --- /dev/null +++ b/setup-cli/src/mcp-auth.ts @@ -0,0 +1,51 @@ +import type { MCPAuthResult } from "./types.js"; + +/** + * Since this CLI tool is designed to work with Claude Code SDK, + * we can leverage Claude Code's existing MCP authentication instead + * of implementing our own OAuth flow. + * + * The tool should instruct users to: + * 1. Set up Braintrust MCP in Claude Code if not already done + * 2. Authenticate via Claude Code's built-in MCP flow + * 3. Then this CLI can work alongside Claude Code + */ + +export function checkMCPSetup(): boolean { + // Check if user is running this from within Claude Code context + // or if they have Claude Code MCP configured + const hasClaudeCode = + process.env.CLAUDE_CODE === "true" || process.env.MCP_AVAILABLE === "true"; + + return hasClaudeCode; +} + +export function getMCPSetupInstructions(): string { + return ` +šŸ’” This tool is designed to work within Claude Code + +If you're seeing this message, it means you're running this tool outside of Claude Code. + +For the best experience: + +1. Start Claude Code in your project directory: + claude + +2. Run this tool from within Claude Code: + npx @braintrust/setup + +Or simply ask Claude directly: + "Please set up Braintrust tracing for this codebase using the MCP tools" + +Note: If you haven't configured Braintrust MCP in Claude Code yet, Claude will guide you through that setup when you try to use the Braintrust tools. +`; +} + +export function createMCPInstructions(): MCPAuthResult { + // Return placeholder - actual auth handled by Claude Code + return { + accessToken: "handled-by-claude-code", + orgName: "handled-by-claude-code", + apiUrl: "https://api.braintrust.dev", + }; +} diff --git a/setup-cli/src/prompts.ts b/setup-cli/src/prompts.ts new file mode 100644 index 000000000..f228f4d32 --- /dev/null +++ b/setup-cli/src/prompts.ts @@ -0,0 +1,147 @@ +export const BRAINTRUST_SETUP_PROMPT = ` +You are a Braintrust tracing setup assistant. Your job is to automatically add Braintrust tracing to an existing codebase. + +## Your Task +Analyze the current codebase and add Braintrust tracing with minimal disruption to existing code patterns. + +## Step 1: Inspection +First, inspect the codebase to understand: +- What AI/ML libraries are being used (OpenAI, Anthropic, LangChain, Vercel AI SDK, etc.) +- The project structure and language (TypeScript vs JavaScript) +- Package manager (npm, pnpm, yarn) +- Framework usage (Next.js, Express, etc.) +- Existing import patterns and code style + +## Step 2: Add Braintrust Package +Add the braintrust package to the project: +- Use the detected package manager +- Add to package.json dependencies +- Install appropriate version + +## Step 3: Add Tracing +For each AI library found, add Braintrust tracing: + +### OpenAI Integration: +\`\`\`typescript +import { wrapOpenAI } from 'braintrust'; +import OpenAI from 'openai'; + +const client = wrapOpenAI(new OpenAI({ + apiKey: process.env.OPENAI_API_KEY, +})); +\`\`\` + +### Anthropic Integration: +\`\`\`typescript +import { wrapAnthropic } from 'braintrust'; +import Anthropic from '@anthropic-ai/sdk'; + +const client = wrapAnthropic(new Anthropic({ + apiKey: process.env.ANTHROPIC_API_KEY, +})); +\`\`\` + +### Vercel AI SDK Integration: +\`\`\`typescript +import { wrapAISDKModel } from 'braintrust'; +import { openai } from 'ai'; + +const model = wrapAISDKModel(openai('gpt-4')); +\`\`\` + +## Step 4: Add Logger Initialization +Add initLogger() call in the main entry point: +\`\`\`typescript +import { initLogger } from 'braintrust'; + +initLogger({ + projectName: 'your-project-name', // Use detected project name +}); +\`\`\` + +## Step 5: Environment Variables +Add necessary environment variables to .env: +\`\`\` +BRAINTRUST_API_KEY=your-api-key-here +\`\`\` + +## Important Guidelines: +1. **Preserve existing code style** - match indentation, import patterns, etc. +2. **Minimal changes** - only modify what's necessary for tracing +3. **Backup originals** - always create backups before modifying files +4. **Show preview** - show user what changes will be made before applying +5. **Handle edge cases** - different import styles, existing wrappers, etc. +6. **Use MCP tools** - use search_docs to get the latest examples and patterns + +## MCP Tools Available: +- \`search_docs\`: Search Braintrust documentation for examples +- \`list_recent_objects\`: Get project information +- \`resolve_object\`: Find project IDs and names + +## Error Handling: +- If a pattern is unclear, search the docs for examples +- If multiple approaches are possible, choose the simplest one +- If dependencies are missing, suggest installation +- If files are already modified, detect existing Braintrust usage + +Remember: Your goal is to make adding Braintrust tracing as seamless as possible while following the user's existing code patterns and preferences. +`; + +export const PROJECT_ANALYSIS_PROMPT = ` +Analyze this codebase to detect AI/ML library usage and project characteristics. + +Look for: +1. **AI Libraries**: OpenAI, Anthropic, LangChain, Vercel AI SDK, other LLM libraries +2. **Project Type**: Next.js, Express, React, Node.js, etc. +3. **Language**: TypeScript or JavaScript +4. **Package Manager**: Check for pnpm-lock.yaml, yarn.lock, package-lock.json +5. **Existing Braintrust**: Check if already using Braintrust +6. **Import Patterns**: How does the code import external libraries? +7. **Entry Points**: Where should initLogger() be added? + +Return your analysis as JSON: +\`\`\`json +{ + "libraries": { + "openai": boolean, + "anthropic": boolean, + "langchain": boolean, + "vercel_ai": boolean, + "others": string[] + }, + "project": { + "type": "nextjs" | "express" | "node" | "react" | "other", + "language": "typescript" | "javascript", + "packageManager": "npm" | "pnpm" | "yarn" + }, + "braintrust": { + "alreadyInstalled": boolean, + "alreadyConfigured": boolean + }, + "entryPoints": string[], + "recommendations": string[] +} +\`\`\` +`; + +export const IMPLEMENTATION_PROMPT = ` +Based on the analysis, implement Braintrust tracing for this codebase. + +## Implementation Plan: +1. Add braintrust dependency to package.json +2. Wrap AI clients with Braintrust wrappers +3. Add initLogger() call to main entry point +4. Add environment variables +5. Create backup of modified files + +## Files to Modify: +Show each file that will be changed with a clear diff showing before/after. + +## Commands to Run: +List any package manager commands needed to install dependencies. + +## Follow-up Instructions: +Provide clear next steps for the user to complete setup. + +Make all changes following the existing code style and patterns detected in the analysis phase. +`; diff --git a/setup-cli/src/types.ts b/setup-cli/src/types.ts new file mode 100644 index 000000000..671ba297f --- /dev/null +++ b/setup-cli/src/types.ts @@ -0,0 +1,28 @@ +export interface BraintrustConfig { + apiUrl?: string; + projectName?: string; + orgName?: string; + accessToken?: string; +} + +export interface SetupOptions { + projectPath: string; + dryRun: boolean; + backup: boolean; +} + +export interface MCPAuthResult { + accessToken: string; + orgName: string; + apiUrl: string; +} + +export interface DetectionResult { + hasOpenAI: boolean; + hasAnthropic: boolean; + hasLangChain: boolean; + hasVercelAI: boolean; + hasNextjs: boolean; + packageManager: "npm" | "pnpm" | "yarn"; + language: "typescript" | "javascript"; +} diff --git a/setup-cli/tsconfig.json b/setup-cli/tsconfig.json new file mode 100644 index 000000000..bd97035b8 --- /dev/null +++ b/setup-cli/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "allowJs": true, + "strict": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "declaration": true, + "outDir": "./dist", + "rootDir": "./src", + "resolveJsonModule": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} diff --git a/setup-cli/tsup.config.ts b/setup-cli/tsup.config.ts new file mode 100644 index 000000000..fdb719ec1 --- /dev/null +++ b/setup-cli/tsup.config.ts @@ -0,0 +1,31 @@ +import { defineConfig } from "tsup"; + +export default defineConfig([ + // Main library + { + entry: ["src/index.ts"], + format: ["cjs", "esm"], + dts: false, + clean: true, + splitting: false, + sourcemap: true, + outDir: "dist", + target: "node16", + }, + // CLI binary + { + entry: { "bin/braintrust-setup": "src/bin/braintrust-setup.ts" }, + format: ["cjs"], + dts: false, + clean: false, + splitting: false, + sourcemap: true, + outDir: "dist", + target: "node16", + external: [], // Bundle everything for standalone CLI + banner: { + js: "#!/usr/bin/env node", + }, + onSuccess: "chmod +x dist/bin/braintrust-setup.js", + }, +]);