diff --git a/package.json b/package.json index 0b12893d..ca1a283a 100644 --- a/package.json +++ b/package.json @@ -33,10 +33,11 @@ }, "dependencies": { "@anthropic-ai/claude-agent-sdk": "0.3.169", - "@earendil-works/pi-ai": "^0.79.1", - "@earendil-works/pi-coding-agent": "^0.79.1", + "@earendil-works/pi-ai": "~0.79.8", + "@earendil-works/pi-coding-agent": "~0.79.8", "@inkjs/ui": "^2.0.0", "@langchain/core": "^0.3.40", + "@modelcontextprotocol/sdk": "^1.29.0", "@posthog/warlock": "0.2.4", "axios": "1.7.4", "fast-glob": "^3.3.3", @@ -50,7 +51,7 @@ "magicast": "^0.2.10", "nanostores": "^1.1.1", "opn": "^5.4.0", - "pi-mcp-adapter": "^2.9.0", + "pi-mcp-adapter": "~2.15.0", "posthog-node": "^5.24.17", "react": "^19.2.4", "read-env": "^1.3.0", @@ -69,7 +70,6 @@ "@babel/plugin-transform-modules-commonjs": "^7.28.6", "@babel/preset-env": "^7.29.0", "@babel/types": "~7.21.4", - "@modelcontextprotocol/sdk": "^1.29.0", "@types/chai": "^4.3.17", "@types/glob": "^7.2.0", "@types/inquirer": "^0.0.43", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f8661189..0cf0c343 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,10 +12,10 @@ importers: specifier: 0.3.169 version: 0.3.169(@anthropic-ai/sdk@0.91.1(zod@3.25.76))(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@3.25.76))(zod@3.25.76) '@earendil-works/pi-ai': - specifier: ^0.79.1 + specifier: ~0.79.8 version: 0.79.8(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@3.25.76))(ws@8.18.1)(zod@3.25.76) '@earendil-works/pi-coding-agent': - specifier: ^0.79.1 + specifier: ~0.79.8 version: 0.79.8(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@3.25.76))(ws@8.18.1)(zod@3.25.76) '@inkjs/ui': specifier: ^2.0.0 @@ -23,6 +23,9 @@ importers: '@langchain/core': specifier: ^0.3.40 version: 0.3.40(openai@6.26.0(ws@8.18.1)(zod@3.25.76)) + '@modelcontextprotocol/sdk': + specifier: ^1.29.0 + version: 1.29.0(@cfworker/json-schema@4.1.1)(zod@3.25.76) '@posthog/warlock': specifier: 0.2.4 version: 0.2.4 @@ -63,8 +66,8 @@ importers: specifier: ^5.4.0 version: 5.5.0 pi-mcp-adapter: - specifier: ^2.9.0 - version: 2.10.0(@cfworker/json-schema@4.1.1)(@opentelemetry/api@1.9.0)(react@19.2.4)(ws@8.18.1)(zod@3.25.76) + specifier: ~2.15.0 + version: 2.15.0(@cfworker/json-schema@4.1.1)(@earendil-works/pi-ai@0.79.8(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@3.25.76))(ws@8.18.1)(zod@3.25.76))(@earendil-works/pi-tui@0.79.8)(react@19.2.4)(typebox@1.1.38)(zod@3.25.76) posthog-node: specifier: ^5.24.17 version: 5.24.17 @@ -114,9 +117,6 @@ importers: '@babel/types': specifier: ~7.21.4 version: 7.21.5 - '@modelcontextprotocol/sdk': - specifier: ^1.29.0 - version: 1.29.0(@cfworker/json-schema@4.1.1)(zod@3.25.76) '@types/chai': specifier: ^4.3.17 version: 4.3.20 @@ -312,10 +312,6 @@ packages: resolution: {integrity: sha512-u+NT61JZEkRFtpL0CAw1N1dwxnaLgwVXQl/zjJxTGgLyS/jTIdg2SdoEoCTHxgDyCnqa1HEi9QOoE9/pYRNpOQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/client-bedrock-runtime@3.1073.0': - resolution: {integrity: sha512-Vecj8r9/KIh/Nu9T7CRoCw5EBqnmAa9Q+Iwi5J5Mr0IEBMH6KUoOgAjayfyEZjvvZTllLJ2dOAx5cYeIz8QD6A==} - engines: {node: '>=20.0.0'} - '@aws-sdk/core@3.974.22': resolution: {integrity: sha512-YofH63shc6YRdXjz80BJkpJW+Bkn0Cuu2dn4Rv7s9G2Idt58tgtzQEWxrR2xVljlVfIBeUjPuULnSVYLke3sUQ==} engines: {node: '>=20.0.0'} @@ -380,10 +376,6 @@ packages: resolution: {integrity: sha512-4LDW2Qob6LoLFuqYSYZq2AyTE9koSE9+i+n5UZcm10GpmQOK0zRD9L4uYlzItiTKksIWgC/qMFChAi3RvKYtMg==} engines: {node: '>=20.0.0'} - '@aws-sdk/token-providers@3.1073.0': - resolution: {integrity: sha512-Tolawuc3I9Q6pElcqoBQMLCiCOfKn3eqG4oNIRci4BurhsrJmzXkhF3N+6LRXJrWYFtJKfTkBuLbYCLr8+pwig==} - engines: {node: '>=20.0.0'} - '@aws-sdk/types@3.973.13': resolution: {integrity: sha512-pEHZqRkAlHfnfAU9tK+WpKv/gBNjGJrHMgA3A0iYRGyswBS2t0pfez+lWlwktb3Bqa0ovh7w/QJTFwp3fDxLNg==} engines: {node: '>=20.0.0'} @@ -1071,11 +1063,6 @@ packages: resolution: {integrity: sha512-8m5fcqRpoGpq3QY0I/tFXROSTmPwBb1dAuzYZO3XYgjsdCokkRMAGRjA9P8s/UD6Jy9yy69lyE4H6sz/5A1TmQ==} engines: {node: '>=22.19.0'} - '@earendil-works/pi-ai@0.74.2': - resolution: {integrity: sha512-ukQBHGDm20k9ZUS2cGjNN9vDJp/48r35xmvgSx3paCaC06r2N/PLuRZoJmwQ1ZM7f8T3072odv9YPWn+77w0LA==} - engines: {node: '>=20.0.0'} - hasBin: true - '@earendil-works/pi-ai@0.79.8': resolution: {integrity: sha512-ZpSwaD7oNpsjn9vtEatZQNT9PSdDJXi6rFeY5Qv+OHQGFDKlmcrfJE4ypm4SAc/fBECPs4Rdi3l+YjVtXYrkKw==} engines: {node: '>=22.19.0'} @@ -1086,10 +1073,6 @@ packages: engines: {node: '>=22.19.0'} hasBin: true - '@earendil-works/pi-tui@0.74.2': - resolution: {integrity: sha512-valQPz74qbdydRqII6t9rJ46YANMOOJeDhKm25a1ZrWvWwdjAaAEu6s3ur/LWz84Wkkwcbub2ZkVjzCZi8gFGA==} - engines: {node: '>=20.0.0'} - '@earendil-works/pi-tui@0.79.8': resolution: {integrity: sha512-QerB+0wUc6eEO8MwvzOQGtzcsbwo6y8VvdxYU6vGcakz6ofJZWhrmwrknp1dCGx3bEtCf+siUIxEzkqvFCzIsg==} engines: {node: '>=22.19.0'} @@ -1689,6 +1672,14 @@ packages: '@opentelemetry/api': optional: true + '@modelcontextprotocol/client@2.0.0-beta.5': + resolution: {integrity: sha512-YuuNm5f2TMoFQRje1UqVP8TJRjijCXMz4ckvoVpx1cUXuBEmykWQ2d8R536pek6UKcXT41T5nWc4qR1JFIbEmg==} + engines: {node: '>=20'} + + '@modelcontextprotocol/core@2.0.0-beta.5': + resolution: {integrity: sha512-HKbY9XTbsDy1Y6r2I55TGE3JEapM0vg96e1MUmBIF9LGjos5gjhcIrTz1yvBPLg2aFKHjwhUAQfRdrCEnPxNew==} + engines: {node: '>=20'} + '@modelcontextprotocol/ext-apps@1.7.4': resolution: {integrity: sha512-QQqysE549cf/Y0VabBmAACXhj92EhB3t8yVct2BHbkWiPTFA1S91EqTVjYXXcZEefXU0pmHcdObhsNMcomJIOQ==} engines: {node: '>=20'} @@ -1717,6 +1708,87 @@ packages: resolution: {integrity: sha512-RuzCup9Ct91Y7V79xwCb146RaBRHZ7NBbrIUySumd1rpKqHL5OonaqrGIbug5hNwP/fRyxFMA6ISgw4FTtYFYg==} engines: {node: '>=18'} + '@napi-rs/keyring-darwin-arm64@1.3.0': + resolution: {integrity: sha512-pl76hJvdYUBn6I24bXiOBMA9nbDapo3I5B+f3OorjDU4dUMSypXeKbOVehJe8fhgTiH24flMyTS3aAIy43xegQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@napi-rs/keyring-darwin-x64@1.3.0': + resolution: {integrity: sha512-YcJtEV5LA3cvA4z3BurgxH5IhTsW1JfIvcAAcqcecwk06Si9F9NqkxbZVIfDwQ8oRHgaBmT3zZJnLAotCrVahw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@napi-rs/keyring-freebsd-x64@1.3.0': + resolution: {integrity: sha512-vlLf31TGhfRAaxLDBhg8b89ss0HHD/lyNmL5F3UjSaz5CUXElsJmKYq9fqA/B+cZKUEUcLHHGhF0I/CqcFdaVw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [freebsd] + + '@napi-rs/keyring-linux-arm-gnueabihf@1.3.0': + resolution: {integrity: sha512-KiWdMMu/Inz/bHHIAGrnF7r54FZDYXuHO6UFF/rhIrshUsxbMG1Rl9lEymNtqqsVo927G0VYcb02FzWQ3iBQRQ==} + engines: {node: '>= 10'} + cpu: [arm] + os: [linux] + + '@napi-rs/keyring-linux-arm64-gnu@1.3.0': + resolution: {integrity: sha512-eyKGpY40lm9Jvs1aD294XRH4y7+TlJM0YVAryZeXA6TX0mb4gMkxVXwSQv7MCwgah7raeUd0dKUb4BPAYIgcMg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@napi-rs/keyring-linux-arm64-musl@1.3.0': + resolution: {integrity: sha512-iIK6JWHXAJqDrEyLY3TmswwloVyt2vj+04TZnew+uSJ9gnDO8EwRbp3/iw3LpWaXiDO7VomGO6y8I0Id8uBZSw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@napi-rs/keyring-linux-riscv64-gnu@1.3.0': + resolution: {integrity: sha512-/PGqrwn6EwgtK6vccASSXJRfOSP4vN1F4ASsIQ+7MdrK6hNvAJ1FZPrIuD5gGGdxezo3F++To2Wq7DbuGIeuNQ==} + engines: {node: '>= 10'} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@napi-rs/keyring-linux-x64-gnu@1.3.0': + resolution: {integrity: sha512-2PDK1WKWTu9lBGq9VvNEkSlQD3O7YwVpmnyN2M3cy4v7NJ/8gDMd9GXv3G+FVXN13uhp4gnnPBS+ScefmEeD2A==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@napi-rs/keyring-linux-x64-musl@1.3.0': + resolution: {integrity: sha512-oJ2HkX8YUo46QBkn0pG+HuIKQNqr523q6vBobCn+P95s4C4K6/kLBqHY/1bg5J4ap31DzsznhnFKcfBNBsjCnw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + libc: [musl] + + '@napi-rs/keyring-win32-arm64-msvc@1.3.0': + resolution: {integrity: sha512-tOd3c/uAaeoE4ycVlmAdSvygz0Zt3zdca6Y7gokBeIbaRDWpjDIUOpU3MvML59XAaqyuKGsVVu0F/DZb1lHPmw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@napi-rs/keyring-win32-ia32-msvc@1.3.0': + resolution: {integrity: sha512-sPSqeAFZMGqP1R++M2JTza7GQJJ/TpCo6JU6Vcd4jnebvOaEDs9b7eipakU1PJdSvhpC2yXMCNRk9gXfrhuwHQ==} + engines: {node: '>= 10'} + cpu: [ia32] + os: [win32] + + '@napi-rs/keyring-win32-x64-msvc@1.3.0': + resolution: {integrity: sha512-4DnCWXwDc0HRKwyRlG5y0VhKZW2tNRQfKKfyj6IX/KWfDNyq9hn4n+GL1auyDcOO/v8PwnhmYo2+rOOqCkvvOg==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + '@napi-rs/keyring@1.3.0': + resolution: {integrity: sha512-WrOw/bcXm0f9qHkumlT1QlArXSTWqaY9sunsDpOk+yCCorCKMxvWT/a3xko4EYHVdeZoh00yI2TydXn6eyICDA==} + engines: {node: '>= 10'} + '@napi-rs/wasm-runtime@1.1.4': resolution: {integrity: sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==} peerDependencies: @@ -3880,9 +3952,6 @@ packages: resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} engines: {node: '>=6'} - koffi@2.16.2: - resolution: {integrity: sha512-owU0MRwv6xkrVqCd+33uw6BaYppkTRXbO/rVdJNI2dvZG0gzyRhYwW25eWtc5pauwK8TGh3AbkFONSezdykfSA==} - langsmith@0.3.11: resolution: {integrity: sha512-pzA7wemfMjqCiaNY3AtUkQJ7jubIBmKRTl0dMNEUz8A4ewIqCEpB2caiTeeAwVkugEylny80cDk3u16WqL25Sw==} peerDependencies: @@ -3974,11 +4043,6 @@ packages: makeerror@1.0.12: resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} - marked@15.0.12: - resolution: {integrity: sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA==} - engines: {node: '>= 18'} - hasBin: true - marked@18.0.5: resolution: {integrity: sha512-S6GcvALHg6K4ohtu4E7x0a1AqhAjp6cV8KhLSyN9qVapnzJkusVBxZRcIU9AeYsbe6P1hKDusSbEOzGyyuce6w==} engines: {node: '>= 20'} @@ -4320,11 +4384,22 @@ packages: resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==} engines: {node: '>= 14.16'} - pi-mcp-adapter@2.10.0: - resolution: {integrity: sha512-fSCLimNbR71/VboE1q5zcfauthNDPkOBO/b59xoISF+cSiaxOwd+CzhYclVDRVb3Nwukh3XLhEPQKkzyWkgzCQ==} + pi-mcp-adapter@2.15.0: + resolution: {integrity: sha512-HJAVt2I5IB52pKpSUYbVJnzOmuXYBCc/ZrI9ylHxYQWmE7p75j7aWzsHe734EFN+gL7WaM23CTX3eYHz2THKBA==} + engines: {node: '>=20'} hasBin: true peerDependencies: + '@earendil-works/pi-ai': '*' + '@earendil-works/pi-tui': '*' + typebox: '*' zod: ^3.25.0 || ^4.0.0 + peerDependenciesMeta: + '@earendil-works/pi-ai': + optional: true + '@earendil-works/pi-tui': + optional: true + typebox: + optional: true picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -4714,6 +4789,10 @@ packages: resolution: {integrity: sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg==} engines: {node: '>=20'} + smol-toml@1.7.1: + resolution: {integrity: sha512-PPlsspAZ4jbMBu5DMFhfUGDQLu/vrL4SyBROVS37x8ynnVmFIs1VPBz1Co8Xks3TvpIaZXmU85y4DrQ+UyVFoQ==} + engines: {node: '>= 18'} + source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} @@ -4813,6 +4892,10 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} + strip-json-comments@5.0.3: + resolution: {integrity: sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==} + engines: {node: '>=14.16'} + strip-literal@3.1.0: resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==} @@ -5338,6 +5421,9 @@ packages: zod@3.25.76: resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} + zod@4.4.3: + resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==} + snapshots: '@alcalzone/ansi-tokenize@0.2.5': @@ -5444,23 +5530,6 @@ snapshots: '@smithy/types': 4.15.0 tslib: 2.8.1 - '@aws-sdk/client-bedrock-runtime@3.1073.0': - dependencies: - '@aws-crypto/sha256-browser': 5.2.0 - '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.974.22 - '@aws-sdk/credential-provider-node': 3.972.57 - '@aws-sdk/eventstream-handler-node': 3.972.22 - '@aws-sdk/middleware-eventstream': 3.972.18 - '@aws-sdk/middleware-websocket': 3.972.30 - '@aws-sdk/token-providers': 3.1073.0 - '@aws-sdk/types': 3.973.13 - '@smithy/core': 3.25.1 - '@smithy/fetch-http-handler': 5.5.1 - '@smithy/node-http-handler': 4.8.1 - '@smithy/types': 4.15.0 - tslib: 2.8.1 - '@aws-sdk/core@3.974.22': dependencies: '@aws-sdk/types': 3.973.13 @@ -5618,15 +5687,6 @@ snapshots: '@smithy/types': 4.15.0 tslib: 2.8.1 - '@aws-sdk/token-providers@3.1073.0': - dependencies: - '@aws-sdk/core': 3.974.22 - '@aws-sdk/nested-clients': 3.997.22 - '@aws-sdk/types': 3.973.13 - '@smithy/core': 3.25.1 - '@smithy/types': 4.15.0 - tslib: 2.8.1 - '@aws-sdk/types@3.973.13': dependencies: '@smithy/types': 4.15.0 @@ -6483,26 +6543,6 @@ snapshots: - ws - zod - '@earendil-works/pi-ai@0.74.2(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@3.25.76))(@opentelemetry/api@1.9.0)(ws@8.18.1)(zod@3.25.76)': - dependencies: - '@anthropic-ai/sdk': 0.91.1(zod@3.25.76) - '@aws-sdk/client-bedrock-runtime': 3.1073.0 - '@google/genai': 1.52.0(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@3.25.76)) - '@mistralai/mistralai': 2.2.6(@opentelemetry/api@1.9.0) - http-proxy-agent: 7.0.2 - https-proxy-agent: 7.0.6 - openai: 6.26.0(ws@8.18.1)(zod@3.25.76) - partial-json: 0.1.7 - typebox: 1.1.38 - transitivePeerDependencies: - - '@modelcontextprotocol/sdk' - - '@opentelemetry/api' - - bufferutil - - supports-color - - utf-8-validate - - ws - - zod - '@earendil-works/pi-ai@0.79.8(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@3.25.76))(ws@8.18.1)(zod@3.25.76)': dependencies: '@anthropic-ai/sdk': 0.91.1(zod@3.25.76) @@ -6554,13 +6594,6 @@ snapshots: - ws - zod - '@earendil-works/pi-tui@0.74.2': - dependencies: - get-east-asian-width: 1.5.0 - marked: 15.0.12 - optionalDependencies: - koffi: 2.16.2 - '@earendil-works/pi-tui@0.79.8': dependencies: get-east-asian-width: 1.6.0 @@ -7117,6 +7150,20 @@ snapshots: - bufferutil - utf-8-validate + '@modelcontextprotocol/client@2.0.0-beta.5': + dependencies: + '@modelcontextprotocol/core': 2.0.0-beta.5 + cross-spawn: 7.0.6 + eventsource: 3.0.7 + eventsource-parser: 3.0.8 + jose: 6.2.3 + pkce-challenge: 5.0.1 + zod: 4.4.3 + + '@modelcontextprotocol/core@2.0.0-beta.5': + dependencies: + zod: 4.4.3 + '@modelcontextprotocol/ext-apps@1.7.4(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@3.25.76))(react@19.2.4)(zod@3.25.76)': dependencies: '@modelcontextprotocol/sdk': 1.29.0(@cfworker/json-schema@4.1.1)(zod@3.25.76) @@ -7158,6 +7205,57 @@ snapshots: outvariant: 1.4.3 strict-event-emitter: 0.5.1 + '@napi-rs/keyring-darwin-arm64@1.3.0': + optional: true + + '@napi-rs/keyring-darwin-x64@1.3.0': + optional: true + + '@napi-rs/keyring-freebsd-x64@1.3.0': + optional: true + + '@napi-rs/keyring-linux-arm-gnueabihf@1.3.0': + optional: true + + '@napi-rs/keyring-linux-arm64-gnu@1.3.0': + optional: true + + '@napi-rs/keyring-linux-arm64-musl@1.3.0': + optional: true + + '@napi-rs/keyring-linux-riscv64-gnu@1.3.0': + optional: true + + '@napi-rs/keyring-linux-x64-gnu@1.3.0': + optional: true + + '@napi-rs/keyring-linux-x64-musl@1.3.0': + optional: true + + '@napi-rs/keyring-win32-arm64-msvc@1.3.0': + optional: true + + '@napi-rs/keyring-win32-ia32-msvc@1.3.0': + optional: true + + '@napi-rs/keyring-win32-x64-msvc@1.3.0': + optional: true + + '@napi-rs/keyring@1.3.0': + optionalDependencies: + '@napi-rs/keyring-darwin-arm64': 1.3.0 + '@napi-rs/keyring-darwin-x64': 1.3.0 + '@napi-rs/keyring-freebsd-x64': 1.3.0 + '@napi-rs/keyring-linux-arm-gnueabihf': 1.3.0 + '@napi-rs/keyring-linux-arm64-gnu': 1.3.0 + '@napi-rs/keyring-linux-arm64-musl': 1.3.0 + '@napi-rs/keyring-linux-riscv64-gnu': 1.3.0 + '@napi-rs/keyring-linux-x64-gnu': 1.3.0 + '@napi-rs/keyring-linux-x64-musl': 1.3.0 + '@napi-rs/keyring-win32-arm64-msvc': 1.3.0 + '@napi-rs/keyring-win32-ia32-msvc': 1.3.0 + '@napi-rs/keyring-win32-x64-msvc': 1.3.0 + '@napi-rs/wasm-runtime@1.1.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)': dependencies: '@emnapi/core': 1.9.2 @@ -9525,9 +9623,6 @@ snapshots: kleur@3.0.3: {} - koffi@2.16.2: - optional: true - langsmith@0.3.11(openai@6.26.0(ws@8.18.1)(zod@3.25.76)): dependencies: '@types/uuid': 10.0.0 @@ -9637,8 +9732,6 @@ snapshots: dependencies: tmpl: 1.0.5 - marked@15.0.12: {} - marked@18.0.5: {} math-intrinsics@1.1.0: {} @@ -9919,25 +10012,27 @@ snapshots: pathval@2.0.1: {} - pi-mcp-adapter@2.10.0(@cfworker/json-schema@4.1.1)(@opentelemetry/api@1.9.0)(react@19.2.4)(ws@8.18.1)(zod@3.25.76): + pi-mcp-adapter@2.15.0(@cfworker/json-schema@4.1.1)(@earendil-works/pi-ai@0.79.8(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@3.25.76))(ws@8.18.1)(zod@3.25.76))(@earendil-works/pi-tui@0.79.8)(react@19.2.4)(typebox@1.1.38)(zod@3.25.76): dependencies: - '@earendil-works/pi-ai': 0.74.2(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@3.25.76))(@opentelemetry/api@1.9.0)(ws@8.18.1)(zod@3.25.76) - '@earendil-works/pi-tui': 0.74.2 + '@modelcontextprotocol/client': 2.0.0-beta.5 '@modelcontextprotocol/ext-apps': 1.7.4(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@3.25.76))(react@19.2.4)(zod@3.25.76) '@modelcontextprotocol/sdk': 1.29.0(@cfworker/json-schema@4.1.1)(zod@3.25.76) + '@napi-rs/keyring': 1.3.0 + cross-spawn: 7.0.6 open: 10.2.0 recheck: 4.5.0 - typebox: 1.1.38 + smol-toml: 1.7.1 + strip-json-comments: 5.0.3 zod: 3.25.76 + optionalDependencies: + '@earendil-works/pi-ai': 0.79.8(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@3.25.76))(ws@8.18.1)(zod@3.25.76) + '@earendil-works/pi-tui': 0.79.8 + typebox: 1.1.38 transitivePeerDependencies: - '@cfworker/json-schema' - - '@opentelemetry/api' - - bufferutil - react - react-dom - supports-color - - utf-8-validate - - ws picocolors@1.1.1: {} @@ -10366,6 +10461,8 @@ snapshots: ansi-styles: 6.2.3 is-fullwidth-code-point: 5.1.0 + smol-toml@1.7.1: {} + source-map-js@1.2.1: {} source-map-support@0.5.13: @@ -10454,6 +10551,8 @@ snapshots: strip-json-comments@3.1.1: {} + strip-json-comments@5.0.3: {} + strip-literal@3.1.0: dependencies: js-tokens: 9.0.1 @@ -10913,3 +11012,5 @@ snapshots: zod: 3.25.76 zod@3.25.76: {} + + zod@4.4.3: {} diff --git a/src/lib/agent/runner/harness/pi/index.ts b/src/lib/agent/runner/harness/pi/index.ts index 86fcec7d..59fed66a 100644 --- a/src/lib/agent/runner/harness/pi/index.ts +++ b/src/lib/agent/runner/harness/pi/index.ts @@ -297,16 +297,21 @@ export const piBackend: AgentHarness = { let mcpCleanup: (() => void) | undefined; let mcpInstructions: string | undefined; try { - const { setupPostHogMcp } = await import('./mcp'); + const { setupPostHogMcp, fetchInstructions } = await import('./mcp'); + // Overlaps the network handshake with the adapter's jiti load. + const instructionsPromise = fetchInstructions( + boot.credentials.host.mcpUrl, + boot.credentials.accessToken, + WIZARD_USER_AGENT, + ); const mcp = await setupPostHogMcp({ - agentDir: getAgentDir(), mcpUrl: boot.credentials.host.mcpUrl, accessToken: boot.credentials.accessToken, userAgent: WIZARD_USER_AGENT, }); extensionFactories.push(mcp.extensionFactory); mcpCleanup = mcp.cleanup; - mcpInstructions = mcp.instructions; + mcpInstructions = await instructionsPromise; } catch (err) { logToFile(`[pi] PostHog MCP setup skipped: ${String(err)}`); } diff --git a/src/lib/agent/runner/harness/pi/mcp.ts b/src/lib/agent/runner/harness/pi/mcp.ts index 56127637..4e662178 100644 --- a/src/lib/agent/runner/harness/pi/mcp.ts +++ b/src/lib/agent/runner/harness/pi/mcp.ts @@ -1,22 +1,13 @@ /** - * Wire the real PostHog MCP into the pi backend (#10). pi has no built-in MCP, - * but `pi-mcp-adapter` is pi's own MCP extension — we load it the way pi itself - * does, with `jiti` (pi's runtime `.ts` loader, already a transitive dep). The - * adapter connects to the same hosted MCP the anthropic path uses (`boot.credentials.host.mcpUrl`). - * - * In CLI mode the server exposes a single `exec` tool that carries the whole - * command protocol on its schema. We pre-warm the adapter's metadata cache by - * connecting once and register the roster as DIRECT tools — so the agent calls - * `exec` in one step instead of through the fragile `mcp` proxy search. - * - * The bearer token is passed by env-var NAME (`bearerTokenEnv`), so it lives only - * in the wizard process for the adapter's in-process client. It is never written - * to disk and never reaches pi's (env-scrubbed) tool subprocesses. + * pi has no built-in MCP; `pi-mcp-adapter` — pi's own MCP extension, built here + * with its supported `createMcpAdapter` embedding API — bridges the same hosted + * MCP the anthropic path uses into the agent. */ -import fs from 'fs'; -import path from 'path'; +import { Client } from '@modelcontextprotocol/sdk/client/index.js'; +import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'; import { createJiti } from 'jiti'; +import { VERSION } from '@lib/version'; import { logToFile } from '@utils/debug'; const MCP_TOKEN_ENV = 'POSTHOG_MCP_TOKEN'; @@ -24,132 +15,75 @@ const MCP_TOKEN_ENV = 'POSTHOG_MCP_TOKEN'; export interface PostHogMcpSetup { /** pi ExtensionFactory to add to the resource loader's `extensionFactories`. */ extensionFactory: (pi: unknown) => void; - /** Restore prior config + drop the token env var. Call after the run. */ + /** Drop the token env var. Call after the run. */ cleanup: () => void; - /** - * The MCP server's `instructions` payload, captured at warm-connect. The - * adapter drops it, so the caller rides it into the system prompt — it carries - * the "prioritize skills over tools" steer, the active project/environment, and - * the tool domains the agent searches to discover tools. Undefined if the - * warm-connect failed. - */ - instructions?: string; +} + +/** Server `instructions` for the system prompt — the adapter exposes no accessor, so one standard-SDK handshake; best-effort. */ +export async function fetchInstructions( + mcpUrl: string, + accessToken: string, + userAgent: string, +): Promise { + const client = new Client({ name: 'posthog-wizard', version: VERSION }); + try { + const transport = new StreamableHTTPClientTransport(new URL(mcpUrl), { + requestInit: { + headers: { + Authorization: `Bearer ${accessToken}`, + 'User-Agent': userAgent, + }, + }, + }); + await client.connect(transport); + const instructions = client.getInstructions() || undefined; + logToFile(`[pi-mcp] instructions ${instructions?.length ?? 0} chars`); + return instructions; + } catch (err) { + logToFile(`[pi-mcp] instructions fetch skipped: ${String(err)}`); + return undefined; + } finally { + await client.close().catch(() => undefined); + } } export async function setupPostHogMcp(opts: { - agentDir: string; mcpUrl: string; accessToken: string; userAgent: string; }): Promise { - const { agentDir, mcpUrl, accessToken, userAgent } = opts; + const { mcpUrl, accessToken, userAgent } = opts; + // By env NAME: the token stays in this process, off disk, and never reaches pi's env-scrubbed tool subprocesses. process.env[MCP_TOKEN_ENV] = accessToken; - // The adapter discovers servers from /mcp.json. Merge our server in - // and restore the prior file on cleanup so a user's own config is never lost. - const configPath = path.join(agentDir, 'mcp.json'); - const previous = fs.existsSync(configPath) - ? fs.readFileSync(configPath, 'utf8') - : null; - - let config: { mcpServers: Record> } = { - mcpServers: {}, - }; - if (previous) { - try { - config = JSON.parse(previous); - config.mcpServers ??= {}; - } catch { - config = { mcpServers: {} }; - } - } - const server: Record = { - url: mcpUrl, - auth: 'bearer', - bearerTokenEnv: MCP_TOKEN_ENV, - headers: { 'User-Agent': userAgent }, - lifecycle: 'lazy', - // Register only `exec`: `directTools: true` also mints a `posthog_get_` tool per MCP resource, whose sentence-length names overflow Anthropic's 128-char tool-name limit and 400 the whole request. - directTools: ['exec'], - exposeResources: false, - }; - config.mcpServers.posthog = server; - // Disable the proxy `mcp` tool (its search indirection pollutes context); the adapter re-enables it only if no direct tools resolve. - const settings = (config as { settings?: Record }).settings; - (config as { settings?: Record }).settings = { - ...settings, - disableProxyTool: true, - toolPrefix: 'posthog', - }; - - const writeConfig = (): void => { - fs.mkdirSync(agentDir, { recursive: true }); - fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf8'); - }; - writeConfig(); - + // The adapter ships raw TypeScript; loading through jiti is its documented requirement. const jiti = createJiti(import.meta.url); - - // The server `instructions` (adapter drops them), captured below for the system prompt. - let instructions: string | undefined; - - // Pre-warm: connect once to seed the adapter's metadata cache; best-effort (proxy fallback on failure). - try { - const sm = await jiti.import('pi-mcp-adapter/server-manager.ts'); - const mc = await jiti.import('pi-mcp-adapter/metadata-cache.ts'); - const manager = new sm.McpServerManager(); - try { - const conn = await manager.connect('posthog', server); - if (conn.status === 'connected' && conn.tools.length > 0) { - mc.saveMetadataCache({ - version: 1, - servers: { - posthog: { - configHash: mc.computeServerHash(server), - tools: mc.serializeTools(conn.tools), - resources: mc.serializeResources(conn.resources ?? []), - cachedAt: Date.now(), - }, - }, - }); - // The adapter drops the server `instructions` (skill steer + env + tool domains), so read them off the SDK client. - const client = (conn as { client?: { getInstructions?: () => string } }) - .client; - instructions = client?.getInstructions?.() || undefined; - // Log the exec description length so adapter truncation of the protocol is detectable. - const execTool = conn.tools.find((t: { name: string }) => - /(^|_)exec$/.test(t.name), - ) as { description?: string } | undefined; - const execDescLen = execTool?.description?.length ?? 0; - logToFile( - `[pi-mcp] warmed: ${conn.tools.length} tools, all direct; ` + - `exec description ${execDescLen} chars; ` + - `instructions ${instructions?.length ?? 0} chars`, - ); - } - } finally { - await manager.closeAll().catch(() => undefined); - } - } catch (err) { - logToFile(`[pi-mcp] cache warm skipped (proxy fallback): ${String(err)}`); - } - - const mod = await jiti.import('pi-mcp-adapter/index.ts'); - const extensionFactory = ((mod as { default?: unknown }).default ?? mod) as ( - pi: unknown, - ) => void; + const mod = await jiti.import('pi-mcp-adapter'); + const extensionFactory = mod.createMcpAdapter({ + config: { + mcpServers: { + posthog: { + url: mcpUrl, + auth: 'bearer', + bearerTokenEnv: MCP_TOKEN_ENV, + headers: { 'User-Agent': userAgent }, + // Connect at extension load — direct tools register without a session_start. + lifecycle: 'eager', + // Register only `exec`: `directTools: true` also mints a `posthog_get_` tool per MCP resource, whose sentence-length names overflow Anthropic's 128-char tool-name limit and 400 the whole request. + directTools: ['exec'], + exposeResources: false, + }, + }, + // Disable the proxy `mcp` tool (its search indirection pollutes context); the adapter re-enables it only if no direct tools resolve. + settings: { disableProxyTool: true, toolPrefix: 'posthog' }, + }, + }); logToFile(`[pi-mcp] adapter loaded; posthog MCP at ${mcpUrl}`); const cleanup = (): void => { - try { - if (previous != null) fs.writeFileSync(configPath, previous, 'utf8'); - else fs.rmSync(configPath, { force: true }); - } catch (err) { - logToFile(`[pi-mcp] config cleanup skipped: ${String(err)}`); - } delete process.env[MCP_TOKEN_ENV]; }; - return { extensionFactory, cleanup, instructions }; + return { extensionFactory, cleanup }; } diff --git a/src/lib/agent/runner/harness/pi/task.ts b/src/lib/agent/runner/harness/pi/task.ts index 0dc2bca8..99362a64 100644 --- a/src/lib/agent/runner/harness/pi/task.ts +++ b/src/lib/agent/runner/harness/pi/task.ts @@ -219,7 +219,6 @@ export async function runPiTask(inputs: TaskRunInputs): Promise { try { const { setupPostHogMcp } = await import('./mcp'); const mcp = await setupPostHogMcp({ - agentDir: getAgentDir(), mcpUrl: boot.credentials.host.mcpUrl, accessToken: boot.credentials.accessToken, userAgent: WIZARD_USER_AGENT,