From 51eb35046290b296b021b10cdbeae842ba6cf127 Mon Sep 17 00:00:00 2001 From: Ido Salomon Date: Mon, 4 Aug 2025 00:06:40 +0300 Subject: [PATCH 1/4] fix: package.lock --- package-lock.json | 173 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 136 insertions(+), 37 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0ddad9f..30d69a3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,7 +17,7 @@ "@ai-sdk/react": "^1.2.9", "@ai-sdk/xai": "^1.2.15", "@cloudflare/workers-oauth-provider": "^0.0.2", - "@modelcontextprotocol/sdk": "^1.10.2", + "@modelcontextprotocol/sdk": "^1.11.2", "@radix-ui/react-accordion": "^1.2.8", "@radix-ui/react-avatar": "^1.1.7", "@radix-ui/react-dialog": "^1.1.11", @@ -33,7 +33,7 @@ "@remix-run/cloudflare": "^2.16.5", "@types/react": "^19.1.2", "@types/react-dom": "^19.1.2", - "agents": "^0.0.66", + "agents": "^0.0.84", "ai": "^4.3.10", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", @@ -60,7 +60,7 @@ }, "devDependencies": { "@cloudflare/vite-plugin": "^0.1.21", - "@cloudflare/workers-types": "^4.20250426.0", + "@cloudflare/workers-types": "^4.20250505.0", "@playwright/test": "^1.52.0", "@react-router/dev": "^7.5.2", "@tailwindcss/postcss": "^4.1.4", @@ -80,7 +80,7 @@ "vite-tsconfig-paths": "^5.1.4", "vitest": "^1.6.1", "workers-mcp": "0.1.0-3", - "wrangler": "^4.13.2" + "wrangler": "^4.14.1" } }, "node_modules/@ai-sdk/anthropic": { @@ -209,13 +209,13 @@ } }, "node_modules/@ai-sdk/react": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/@ai-sdk/react/-/react-1.2.11.tgz", - "integrity": "sha512-+kPqLkJ3TWP6czaJPV+vzAKSUcKQ1598BUrcLHt56sH99+LhmIIW3ylZp0OfC3O6TR3eO1Lt0Yzw4R0mK6g9Gw==", + "version": "1.2.12", + "resolved": "https://registry.npmjs.org/@ai-sdk/react/-/react-1.2.12.tgz", + "integrity": "sha512-jK1IZZ22evPZoQW3vlkZ7wvjYGYF+tRBKXtrcolduIkQ/m/sOAVcVeVDUDvh1T91xCnWCdUGCPZg2avZ90mv3g==", "license": "Apache-2.0", "dependencies": { - "@ai-sdk/provider-utils": "2.2.7", - "@ai-sdk/ui-utils": "1.2.10", + "@ai-sdk/provider-utils": "2.2.8", + "@ai-sdk/ui-utils": "1.2.11", "swr": "^2.2.5", "throttleit": "2.1.0" }, @@ -232,14 +232,31 @@ } } }, + "node_modules/@ai-sdk/react/node_modules/@ai-sdk/provider-utils": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-2.2.8.tgz", + "integrity": "sha512-fqhG+4sCVv8x7nFzYnFo19ryhAa3w096Kmc3hWxMQfW/TubPOmt3A6tYZhl4mUfQWWQMsuSkLrtjlWuXBVSGQA==", + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider": "1.1.3", + "nanoid": "^3.3.8", + "secure-json-parse": "^2.7.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.23.8" + } + }, "node_modules/@ai-sdk/ui-utils": { - "version": "1.2.10", - "resolved": "https://registry.npmjs.org/@ai-sdk/ui-utils/-/ui-utils-1.2.10.tgz", - "integrity": "sha512-GUj+LBoAlRQF1dL/M49jtufGqtLOMApxTpCmVjoRpIPt/dFALVL9RfqfvxwztyIwbK+IxGzcYjSGRsrWrj+86g==", + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@ai-sdk/ui-utils/-/ui-utils-1.2.11.tgz", + "integrity": "sha512-3zcwCc8ezzFlwp3ZD15wAPjf2Au4s3vAbKsXQVyhxODHcmu0iyPO2Eua6D/vicq/AUm/BAo60r97O6HU+EI0+w==", "license": "Apache-2.0", "dependencies": { "@ai-sdk/provider": "1.1.3", - "@ai-sdk/provider-utils": "2.2.7", + "@ai-sdk/provider-utils": "2.2.8", "zod-to-json-schema": "^3.24.1" }, "engines": { @@ -249,6 +266,23 @@ "zod": "^3.23.8" } }, + "node_modules/@ai-sdk/ui-utils/node_modules/@ai-sdk/provider-utils": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-2.2.8.tgz", + "integrity": "sha512-fqhG+4sCVv8x7nFzYnFo19ryhAa3w096Kmc3hWxMQfW/TubPOmt3A6tYZhl4mUfQWWQMsuSkLrtjlWuXBVSGQA==", + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider": "1.1.3", + "nanoid": "^3.3.8", + "secure-json-parse": "^2.7.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.23.8" + } + }, "node_modules/@ai-sdk/xai": { "version": "1.2.15", "resolved": "https://registry.npmjs.org/@ai-sdk/xai/-/xai-1.2.15.tgz", @@ -2458,15 +2492,17 @@ "license": "MIT" }, "node_modules/@modelcontextprotocol/sdk": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.11.0.tgz", - "integrity": "sha512-k/1pb70eD638anoi0e8wUGAlbMJXyvdV4p62Ko+EZ7eBe1xMx8Uhak1R5DgfoofsK5IBBnRwsYGTaLZl+6/+RQ==", + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.17.1.tgz", + "integrity": "sha512-CPle1OQehbWqd25La9Ack5B07StKIxh4+Bf19qnpZKJC1oI22Y0czZHbifjw1UoczIfKBwBDAp/dFxvHG13B5A==", "license": "MIT", "dependencies": { + "ajv": "^6.12.6", "content-type": "^1.0.5", "cors": "^2.8.5", - "cross-spawn": "^7.0.3", + "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", + "eventsource-parser": "^3.0.0", "express": "^5.0.1", "express-rate-limit": "^7.5.0", "pkce-challenge": "^5.0.0", @@ -4622,18 +4658,18 @@ } }, "node_modules/agents": { - "version": "0.0.66", - "resolved": "https://registry.npmjs.org/agents/-/agents-0.0.66.tgz", - "integrity": "sha512-GFBuRi48oZ7hOA65dGNtVEVNZGH6MUGU2pIBKQYWagqwCd7rD5yXtZ1/YCaFR1wmKC9p9/YbZRBPw4LzjvsOwQ==", + "version": "0.0.84", + "resolved": "https://registry.npmjs.org/agents/-/agents-0.0.84.tgz", + "integrity": "sha512-hzhyEKygo6I5rnjXPl7h6CNdsLaEYDbEYSypTo9OGj1KJyu74XlfGO6wI6CO60t1K3Bbl4u5p7z4p+Ieo1j3oA==", "license": "MIT", "dependencies": { - "@modelcontextprotocol/sdk": "^1.10.2", - "ai": "^4.3.9", + "@modelcontextprotocol/sdk": "^1.11.2", + "ai": "^4.3.15", "cron-schedule": "^5.0.4", "nanoid": "^5.1.5", - "partyserver": "^0.0.67", - "partysocket": "1.1.3", - "zod": "^3.24.3" + "partyserver": "^0.0.71", + "partysocket": "1.1.4", + "zod": "^3.24.4" }, "peerDependencies": { "react": "*" @@ -4658,15 +4694,15 @@ } }, "node_modules/ai": { - "version": "4.3.13", - "resolved": "https://registry.npmjs.org/ai/-/ai-4.3.13.tgz", - "integrity": "sha512-cC5HXItuOwGykSMacCPzNp6+NMTxeuTjOenztVgSJhdC9Z4OrzBxwkyeDAf4h1QP938ZFi7IBdq3u4lxVoVmvw==", + "version": "4.3.19", + "resolved": "https://registry.npmjs.org/ai/-/ai-4.3.19.tgz", + "integrity": "sha512-dIE2bfNpqHN3r6IINp9znguYdhIOheKW2LDigAMrgt/upT3B8eBGPSCblENvaZGoq+hxaN9fSMzjWpbqloP+7Q==", "license": "Apache-2.0", "dependencies": { "@ai-sdk/provider": "1.1.3", - "@ai-sdk/provider-utils": "2.2.7", - "@ai-sdk/react": "1.2.11", - "@ai-sdk/ui-utils": "1.2.10", + "@ai-sdk/provider-utils": "2.2.8", + "@ai-sdk/react": "1.2.12", + "@ai-sdk/ui-utils": "1.2.11", "@opentelemetry/api": "1.9.0", "jsondiffpatch": "0.6.0" }, @@ -4683,6 +4719,39 @@ } } }, + "node_modules/ai/node_modules/@ai-sdk/provider-utils": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-2.2.8.tgz", + "integrity": "sha512-fqhG+4sCVv8x7nFzYnFo19ryhAa3w096Kmc3hWxMQfW/TubPOmt3A6tYZhl4mUfQWWQMsuSkLrtjlWuXBVSGQA==", + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider": "1.1.3", + "nanoid": "^3.3.8", + "secure-json-parse": "^2.7.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.23.8" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/ansi-escapes": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", @@ -6028,6 +6097,12 @@ "node": ">=8.6.0" } }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "license": "MIT" + }, "node_modules/fast-querystring": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/fast-querystring/-/fast-querystring-1.1.2.tgz", @@ -6987,6 +7062,12 @@ "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", "license": "(AFL-2.1 OR BSD-3-Clause)" }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "license": "MIT" + }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -9143,9 +9224,9 @@ } }, "node_modules/partyserver": { - "version": "0.0.67", - "resolved": "https://registry.npmjs.org/partyserver/-/partyserver-0.0.67.tgz", - "integrity": "sha512-GQ0fjJ7n5r5LrsFHFUkGR3Bd50YdBZaDNjvRTi8PowZgI5fvCFliT/XdDpRVuwfDDk0jb9es2cXcaAh1z5GsLA==", + "version": "0.0.71", + "resolved": "https://registry.npmjs.org/partyserver/-/partyserver-0.0.71.tgz", + "integrity": "sha512-PJZoX08tyNcNJVXqWJedZ6Jzj8EOFGBA/PJ37KhAnWmTkq6A8SqA4u2ol+zq8zwSfRy9FPvVgABCY0yLpe62Dg==", "license": "ISC", "dependencies": { "nanoid": "^5.1.5" @@ -9173,9 +9254,9 @@ } }, "node_modules/partysocket": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/partysocket/-/partysocket-1.1.3.tgz", - "integrity": "sha512-87Jd/nqPoWnVfzHE6Z12WLWTJ+TAgxs0b7i2S163HfQSrVDUK5tW/FC64T5N8L5ss+gqF+EV0BwjZMWggMY3UA==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/partysocket/-/partysocket-1.1.4.tgz", + "integrity": "sha512-jXP7PFj2h5/v4UjDS8P7MZy6NJUQ7sspiFyxL4uc/+oKOL+KdtXzHnTV8INPGxBrLTXgalyG3kd12Qm7WrYc3A==", "license": "ISC", "dependencies": { "event-target-polyfill": "^0.0.4" @@ -9483,6 +9564,15 @@ "node": ">= 0.10" } }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/punycode.js": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", @@ -11199,6 +11289,15 @@ "browserslist": ">= 4.21.0" } }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, "node_modules/urlpattern-polyfill": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz", From c35c0e94919135a76031b0a35ec950b16d8ce066 Mon Sep 17 00:00:00 2001 From: Ido Salomon Date: Mon, 4 Aug 2025 00:08:39 +0300 Subject: [PATCH 2/4] fix --- pnpm-lock.yaml | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c52e193..1d367cc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -95,6 +95,9 @@ importers: dotenv: specifier: ^16.5.0 version: 16.5.0 + falkordb: + specifier: ^6.2.7 + version: 6.3.0 fast-deep-equal: specifier: ^3.1.3 version: 3.1.3 @@ -1669,6 +1672,35 @@ packages: typescript: optional: true + '@redis/bloom@1.2.0': + resolution: {integrity: sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==} + peerDependencies: + '@redis/client': ^1.0.0 + + '@redis/client@1.6.1': + resolution: {integrity: sha512-/KCsg3xSlR+nCK8/8ZYSknYxvXHwubJrU82F3Lm1Fp6789VQ0/3RJKfsmRXjqfaTA++23CvC3hqmqe/2GEt6Kw==} + engines: {node: '>=14'} + + '@redis/graph@1.1.1': + resolution: {integrity: sha512-FEMTcTHZozZciLRl6GiiIB4zGm5z5F3F6a6FZCyrfxdKOhFlGkiAqlexWMBzCi4DcRoyiOsuLfW+cjlGWyExOw==} + peerDependencies: + '@redis/client': ^1.0.0 + + '@redis/json@1.0.7': + resolution: {integrity: sha512-6UyXfjVaTBTJtKNG4/9Z8PSpKE6XgSyEb8iwaqDcy+uKrd/DGYHTWkUdnQDyzm727V7p21WUMhsqz5oy65kPcQ==} + peerDependencies: + '@redis/client': ^1.0.0 + + '@redis/search@1.2.0': + resolution: {integrity: sha512-tYoDBbtqOVigEDMAcTGsRlMycIIjwMCgD8eR2t0NANeQmgK/lvxNAvYyb6bZDD4frHRhIHkJu2TBRvB0ERkOmw==} + peerDependencies: + '@redis/client': ^1.0.0 + + '@redis/time-series@1.1.0': + resolution: {integrity: sha512-c1Q99M5ljsIuc4YdaCwfUEXsofakb9c8+Zse2qxTadu8TalLXuAESzLvFAvNVbkmSlvlzIQOLpBCmWI9wTOt+g==} + peerDependencies: + '@redis/client': ^1.0.0 + '@remix-run/cloudflare@2.16.5': resolution: {integrity: sha512-dYPH1BdNhnEvs/mUo+pivtdHbj7hU5LFVDOqv+Q/Ss7VRfAMHbfEref72rQ5Z/Opyc2YyHnXW/+NOH8VB2RKdw==} engines: {node: '>=18.0.0'} @@ -2182,6 +2214,10 @@ packages: resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} engines: {node: '>=6'} + cluster-key-slot@1.1.2: + resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==} + engines: {node: '>=0.10.0'} + color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} @@ -2463,6 +2499,9 @@ packages: extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + falkordb@6.3.0: + resolution: {integrity: sha512-ZbGkgmDPpDWZsOwc4i5sWKCRSMLmd0zYdoIwwkowutel7oQjjAogVLjGFUnFBKMav7vhKhF6MXykBW2P83hCxw==} + fast-decode-uri-component@1.0.1: resolution: {integrity: sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==} @@ -2563,6 +2602,10 @@ packages: function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + generic-pool@3.9.0: + resolution: {integrity: sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==} + engines: {node: '>= 4'} + gensync@1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} @@ -3523,6 +3566,9 @@ packages: resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} engines: {node: '>= 14.18.0'} + redis@4.7.1: + resolution: {integrity: sha512-S1bJDnqLftzHXHP8JsT5II/CtHWQrASX5K96REjWjlmWKrviSOLWmM7QnRLstAWsu1VBBV1ffV6DzCvxNP0UJQ==} + remark-gfm@4.0.1: resolution: {integrity: sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==} @@ -4172,6 +4218,9 @@ packages: yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + yaml@2.7.1: resolution: {integrity: sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==} engines: {node: '>= 14'} @@ -5532,6 +5581,32 @@ snapshots: optionalDependencies: typescript: 5.8.3 + '@redis/bloom@1.2.0(@redis/client@1.6.1)': + dependencies: + '@redis/client': 1.6.1 + + '@redis/client@1.6.1': + dependencies: + cluster-key-slot: 1.1.2 + generic-pool: 3.9.0 + yallist: 4.0.0 + + '@redis/graph@1.1.1(@redis/client@1.6.1)': + dependencies: + '@redis/client': 1.6.1 + + '@redis/json@1.0.7(@redis/client@1.6.1)': + dependencies: + '@redis/client': 1.6.1 + + '@redis/search@1.2.0(@redis/client@1.6.1)': + dependencies: + '@redis/client': 1.6.1 + + '@redis/time-series@1.1.0(@redis/client@1.6.1)': + dependencies: + '@redis/client': 1.6.1 + '@remix-run/cloudflare@2.16.5(@cloudflare/workers-types@4.20250510.0)(typescript@5.8.3)': dependencies: '@cloudflare/kv-asset-handler': 0.1.3 @@ -5998,6 +6073,8 @@ snapshots: clsx@2.1.1: {} + cluster-key-slot@1.1.2: {} + color-convert@2.0.1: dependencies: color-name: 1.1.4 @@ -6311,6 +6388,14 @@ snapshots: extend@3.0.2: {} + falkordb@6.3.0: + dependencies: + '@redis/client': 1.6.1 + cluster-key-slot: 1.1.2 + generic-pool: 3.9.0 + lodash: 4.17.21 + redis: 4.7.1 + fast-decode-uri-component@1.0.1: {} fast-deep-equal@3.1.3: {} @@ -6409,6 +6494,8 @@ snapshots: function-bind@1.1.2: {} + generic-pool@3.9.0: {} + gensync@1.0.0-beta.2: {} get-east-asian-width@1.3.0: {} @@ -7533,6 +7620,15 @@ snapshots: readdirp@4.1.2: {} + redis@4.7.1: + dependencies: + '@redis/bloom': 1.2.0(@redis/client@1.6.1) + '@redis/client': 1.6.1 + '@redis/graph': 1.1.1(@redis/client@1.6.1) + '@redis/json': 1.0.7(@redis/client@1.6.1) + '@redis/search': 1.2.0(@redis/client@1.6.1) + '@redis/time-series': 1.1.0(@redis/client@1.6.1) + remark-gfm@4.0.1: dependencies: '@types/mdast': 4.0.4 @@ -8247,6 +8343,8 @@ snapshots: yallist@3.1.1: {} + yallist@4.0.0: {} + yaml@2.7.1: {} yocto-queue@1.2.1: {} From a6cd386122fd2e8471ca1bdcdc4078682edbeb3d Mon Sep 17 00:00:00 2001 From: Ido Salomon Date: Mon, 4 Aug 2025 00:19:20 +0300 Subject: [PATCH 3/4] disable --- src/api/tools/index.test.ts | 16 +- .../tools/repoHandlers/DefaultRepoHandler.ts | 707 +++++++++--------- .../tools/repoHandlers/graphTools.disabled.ts | 433 +++++++++++ src/api/tools/repoHandlers/graphTools.test.ts | 433 ----------- 4 files changed, 794 insertions(+), 795 deletions(-) create mode 100644 src/api/tools/repoHandlers/graphTools.disabled.ts delete mode 100644 src/api/tools/repoHandlers/graphTools.test.ts diff --git a/src/api/tools/index.test.ts b/src/api/tools/index.test.ts index 935dcf4..a4eea3b 100644 --- a/src/api/tools/index.test.ts +++ b/src/api/tools/index.test.ts @@ -60,10 +60,10 @@ describe("Tools Module", () => { description: 'Search for code within the GitHub repository: "myorg/myrepo" using the GitHub Search API (exact match). Returns matching files for you to query further if relevant.', }, - fetchUsageCodeExamples: { - description: - "Fetch code examples that use the given function. Use it when the user asks about code example or how to use his function. Returns code snippets that demonstrate how to call this function.", - }, + // fetch_code_usage_examples: { + // description: + // "Fetch code examples from the repository that use the given function. Only use this if no other examples are found.", + // }, }, }, // default handler - subdomain @@ -87,10 +87,10 @@ describe("Tools Module", () => { description: 'Search for code within the GitHub repository: "myorg/myrepo" using the GitHub Search API (exact match). Returns matching files for you to query further if relevant.', }, - fetchUsageCodeExamples: { - description: - "Fetch code examples that use the given function. Use it when the user asks about code example or how to use his function. Returns code snippets that demonstrate how to calls this function.", - }, + // fetch_code_usage_examples: { + // description: + // "Fetch code examples from the repository that use the given function. Only use this if no other examples are found.", + // }, }, }, // generic handler diff --git a/src/api/tools/repoHandlers/DefaultRepoHandler.ts b/src/api/tools/repoHandlers/DefaultRepoHandler.ts index 4bf63a9..c4880e4 100644 --- a/src/api/tools/repoHandlers/DefaultRepoHandler.ts +++ b/src/api/tools/repoHandlers/DefaultRepoHandler.ts @@ -86,360 +86,359 @@ class DefaultRepoHandler implements RepoHandler { }); }, }, - { - name: "fetchUsageCodeExamples", - description: - "Fetch code examples that use the given function. Use it when the user asks about code example or how to use his function. Returns code snippets that demonstrate how to calls this function.", - paramsSchema: { - functionName: z - .string() - .describe("Name of the function to find who calls it"), - // limit: z.number().optional().default(10).describe("Max number of calling functions to return") - }, - cb: async ({ functionName, limit = 10 }) => { - const graphService = getGraphService(); - - try { - // Input validation - check for empty or invalid repo data - if ( - !repoData.owner || - !repoData.repo || - repoData.owner.trim() === "" || - repoData.repo.trim() === "" - ) { - return { - content: [ - { - type: "text", - text: `āŒ Error: Invalid repository data. Owner and repository name cannot be empty.`, - }, - ], - }; - } - - const graphName = repoData.repo!; - const repoKey = `${repoData.owner}/${repoData.repo}`; - - // Simple check: does the graph exist? - const graphExists = await graphService.checkGraphExists(graphName); - - if (graphExists) { - // Graph exists - proceed with normal functionality with timeout - console.log( - `Graph ${graphName} exists, proceeding with code examples search`, - ); - - try { - // Add simple timeout to prevent infinite loading - const result = await Promise.race([ - // The actual graph operation - (async () => { - const client = await createFalkorDBConnection(); - - try { - const graph = client.selectGraph(graphName); - - // Use the centralized function from graphTools - const result = await getFunctionInfo({ - repoData, - ctx: { graph }, - env, - nodeName: functionName, - functionLimit: limit, - }); - - const callers = result.connectedFunctions; - - if (!callers.length) { - // Before showing "no functions found", check if creation is still in progress - const creationProgress = - graphService.getCreationProgress(repoKey); - if (creationProgress.inProgress) { - return { - content: [ - { - type: "text", - text: `šŸ”„ **Graph Creation Still In Progress for ${repoKey}**\n\nā±ļø **Current Status**: ${creationProgress.phase}\nšŸ“Š **Elapsed Time**: ${creationProgress.elapsedMinutes} minutes\nāŒ› **Estimated Remaining**: ${creationProgress.estimatedRemaining}\n\nšŸ”„ **Please wait a bit longer and try again:**\n"Show me code examples of how to use the ${functionName} function"\n\nšŸ’” *The graph analysis is still building function relationships. Once complete, you'll get detailed code examples.*`, - }, - ], - }; - } - - return { - content: [ - { - type: "text", - text: `šŸ” No calling functions found for "${functionName}".\n\nThis could mean:\n1. The function doesn't exist in the codebase\n2. No other functions call this function\n3. The function name might be misspelled\n4. The function might be called dynamically (not statically analyzable)\n\nTry searching for similar function names or check if the function exists in the repository.`, - }, - ], - }; - } - - // Get the default branch for the repository - const defaultBranch = await getRepoBranch( - repoData.owner!, - repoData.repo!, - env, - ); - - // Process each caller and get actual code with timeout protection - const codeExamples = await Promise.all( - callers.map( - async ( - caller: { - name: string; - path: string; - line: number; - }, - index: number, - ) => { - const { name, path, line } = caller; - - // Extract relative path from the database path - const pathMatch = path.match( - /.*\/repositories\/[^\/]+\/(.+)$/, - ); - const relativePath = pathMatch - ? pathMatch[1] - : path.split("/").slice(-2).join("/"); - - let codeSnippet = ""; - try { - // Add timeout to prevent hanging on GitHub API calls - const timeoutPromise = new Promise((_, reject) => - setTimeout( - () => reject(new Error("GitHub API timeout")), - 5000, - ), - ); - - const fetchPromise = fetchFileFromGitHub( - repoData.owner!, - repoData.repo!, - defaultBranch, - relativePath, - env, - false, - ); - - const fileContent = await Promise.race([ - fetchPromise, - timeoutPromise, - ]); - - if ( - fileContent && - typeof fileContent === "string" - ) { - const lines = fileContent.split("\n"); - const centerLine = line - 1; // Convert to 0-based index - const startLine = Math.max(0, centerLine - 5); - const endLine = Math.min( - lines.length - 1, - centerLine + 5, - ); - - const snippet = lines.slice( - startLine, - endLine + 1, - ); - codeSnippet = snippet - .map( - (codeLine: string, lineIndex: number) => { - const actualLineNumber = - startLine + lineIndex + 1; - const marker = - actualLineNumber === line - ? ">>>" - : " "; - return `${marker} ${actualLineNumber.toString().padStart(3)}: ${codeLine}`; - }, - ) - .join("\n"); - } else { - throw new Error("File content not found"); - } - } catch (error) { - // Fallback to showing just the function info without code content - codeSnippet = `Function: ${name}\nFile: ${relativePath}:${line}\nCalls: ${functionName}\n\n(Code content temporarily unavailable)`; - } - - return `## Code Example ${index + 1}: ${name} - - File: ${relativePath}:${line} - Calls: ${functionName} - - \`\`\` - ${codeSnippet} - \`\`\` - `; - }, - ), - ); - - return { - content: [ - { - type: "text", - text: `šŸ“‹ Code Example Results for "${functionName}" function:\n\nFound ${callers.length} function${callers.length === 1 ? "" : "s"} that call "${functionName}":\n\n${codeExamples.join("\n\n")}`, - }, - ], - }; - } finally { - await client.close(); - } - })(), - // 8 second timeout - new Promise((_, reject) => - setTimeout( - () => reject(new Error("Operation timeout")), - 8000, - ), - ), - ]); - - return result; - } catch (error) { - console.error(`Graph query failed for ${functionName}:`, error); - return { - content: [ - { - type: "text", - text: `ā±ļø **Search Timeout**\n\nThe search for "${functionName}" is taking too long. Please try again.\n\n**Possible causes:**\n• Large repository analysis in progress\n• Database temporarily busy\n• Complex query processing\n\n**Try again in a moment!**`, - }, - ], - }; - } - } else { - // Phase 2: Graph doesn't exist - check creation status and provide immediate feedback - console.log( - `Graph ${graphName} not found. Checking creation status...`, - ); - - // FIRST: Force clear any stale locks (older than 20 minutes) to prevent stuck states - graphService.clearStaleLocks(repoKey); - - // SECOND: If locks are older than 5 minutes, force clear them to allow fresh requests - const progress = graphService.getCreationProgress(repoKey); - if (progress.inProgress && progress.elapsedMinutes >= 5) { - console.log( - `[Debug] Forcing cleanup of ${repoKey} creation locks after ${progress.elapsedMinutes} minutes`, - ); - graphService.setCreationLock(repoKey, false); - // Force clear all related locks - const registry = getGlobalCreationRegistry(); - registry.delete(repoKey); - } - - // THEN: Check if creation is actually in progress (after clearing stale locks) - const finalProgress = graphService.getCreationProgress(repoKey); - console.log( - `[Debug] Progress check for ${repoKey} after clearing stale locks:`, - finalProgress, - ); - - if (finalProgress.inProgress) { - // Creation is genuinely in progress - show progress and ask to wait - console.log( - `[Debug] Creation in progress for ${repoKey}, showing progress`, - ); - return { - content: [ - { - type: "text", - text: `šŸ”„ **Graph Creation In Progress for ${repoKey}**\n\nā±ļø **Current Status**: ${finalProgress.phase}\nšŸ“Š **Elapsed Time**: ${finalProgress.elapsedMinutes} minutes\nāŒ› **Estimated Remaining**: ${finalProgress.estimatedRemaining}\n\nšŸ”„ **Please wait and try your question again in a few minutes:**\n"Show me code examples of how to use the ${functionName} function"\n\nšŸ’” *The system is analyzing the repository to build a knowledge graph of function relationships. This process takes time but enables precise code example searches.*`, - }, - ], - }; - } else { - // No creation in progress - start it now and return immediate response - console.log( - `Starting graph creation for ${repoKey} in background...`, - ); - - // Set creation lock immediately - graphService.setCreationLock(repoKey, true); - - // Get configuration for the API call - const config = getCodeGraphConfig(); - const repoUrl = getGitHubRepoUrl( - repoData.owner!, - repoData.repo!, - ); - const apiUrl = getCodeGraphApiUrl(); - - const requestBody = { - repo_url: repoUrl, - ignore: config.ignorePatterns, - }; - - console.log(`[Immediate] Making API request to ${apiUrl}`); - console.log( - `[Immediate] Request body:`, - JSON.stringify(requestBody), - ); - - // Make the API call with a very short timeout to ensure it fires but doesn't block - try { - fetch(apiUrl, { - method: "POST", - headers: { - "Content-Type": "application/json", - Authorization: config.authToken, - }, - body: JSON.stringify(requestBody), - signal: AbortSignal.timeout(5000), // Short 5 second timeout - }) - .then((response) => { - if (response.ok) { - console.log( - `[Immediate] API request successful for ${repoKey}`, - ); - } else { - console.error( - `[Immediate] API request failed: ${response.status} ${response.statusText}`, - ); - } - }) - .catch((error) => { - console.error( - `[Immediate] API request error for ${repoKey}:`, - error, - ); - }); - } catch (error) { - console.error( - `[Immediate] Failed to initiate API request:`, - error, - ); - } - - return { - content: [ - { - type: "text", - text: `šŸš€ **Starting Code Analysis for ${repoKey}**\n\nāœ… **Graph creation has been initiated!** The system is now analyzing the repository to build a knowledge graph of function relationships.\n\nā±ļø **Estimated Time**: 5-10 minutes\nšŸ“Š **What's happening**: \n • Scanning repository structure\n • Analyzing function definitions\n • Mapping function call relationships\n • Building searchable graph database\n\nšŸ”„ **Please ask your question again in about 5-10 minutes:**\n"Show me code examples of how to use the ${functionName} function"\n\nšŸ’” *This one-time setup enables fast and precise code example searches for this repository!*`, - }, - ], - }; - } - } - } catch (error) { - console.error("Error in fetchUsageCodeExamples:", error); - return { - content: [ - { - type: "text", - text: `āŒ Error processing code examples for "${functionName}": ${error instanceof Error ? error.message : "Unknown error"}`, - }, - ], - }; - } finally { - // Clean up the service connection - await graphService.disconnect(); - } - }, - }, + // { + // name: "fetch_code_usage_examples", + // description: + // "Fetch code examples from the repository that use the given function. Only use this if no other examples are found.", + // paramsSchema: { + // functionName: z + // .string() + // .describe("Function name"), + // }, + // cb: async ({ functionName, limit = 10 }) => { + // const graphService = getGraphService(); + + // try { + // // Input validation - check for empty or invalid repo data + // if ( + // !repoData.owner || + // !repoData.repo || + // repoData.owner.trim() === "" || + // repoData.repo.trim() === "" + // ) { + // return { + // content: [ + // { + // type: "text", + // text: `āŒ Error: Invalid repository data. Owner and repository name cannot be empty.`, + // }, + // ], + // }; + // } + + // const graphName = repoData.repo!; + // const repoKey = `${repoData.owner}/${repoData.repo}`; + + // // Simple check: does the graph exist? + // const graphExists = await graphService.checkGraphExists(graphName); + + // if (graphExists) { + // // Graph exists - proceed with normal functionality with timeout + // console.log( + // `Graph ${graphName} exists, proceeding with code examples search`, + // ); + + // try { + // // Add simple timeout to prevent infinite loading + // const result = await Promise.race([ + // // The actual graph operation + // (async () => { + // const client = await createFalkorDBConnection(); + + // try { + // const graph = client.selectGraph(graphName); + + // // Use the centralized function from graphTools + // const result = await getFunctionInfo({ + // repoData, + // ctx: { graph }, + // env, + // nodeName: functionName, + // functionLimit: limit, + // }); + + // const callers = result.connectedFunctions; + + // if (!callers.length) { + // // Before showing "no functions found", check if creation is still in progress + // const creationProgress = + // graphService.getCreationProgress(repoKey); + // if (creationProgress.inProgress) { + // return { + // content: [ + // { + // type: "text", + // text: `šŸ”„ **Graph Creation Still In Progress for ${repoKey}**\n\nā±ļø **Current Status**: ${creationProgress.phase}\nšŸ“Š **Elapsed Time**: ${creationProgress.elapsedMinutes} minutes\nāŒ› **Estimated Remaining**: ${creationProgress.estimatedRemaining}\n\nšŸ”„ **Please wait a bit longer and try again:**\n"Show me code examples of how to use the ${functionName} function"\n\nšŸ’” *The graph analysis is still building function relationships. Once complete, you'll get detailed code examples.*`, + // }, + // ], + // }; + // } + + // return { + // content: [ + // { + // type: "text", + // text: `šŸ” No calling functions found for "${functionName}".\n\nThis could mean:\n1. The function doesn't exist in the codebase\n2. No other functions call this function\n3. The function name might be misspelled\n4. The function might be called dynamically (not statically analyzable)\n\nTry searching for similar function names or check if the function exists in the repository.`, + // }, + // ], + // }; + // } + + // // Get the default branch for the repository + // const defaultBranch = await getRepoBranch( + // repoData.owner!, + // repoData.repo!, + // env, + // ); + + // // Process each caller and get actual code with timeout protection + // const codeExamples = await Promise.all( + // callers.map( + // async ( + // caller: { + // name: string; + // path: string; + // line: number; + // }, + // index: number, + // ) => { + // const { name, path, line } = caller; + + // // Extract relative path from the database path + // const pathMatch = path.match( + // /.*\/repositories\/[^\/]+\/(.+)$/, + // ); + // const relativePath = pathMatch + // ? pathMatch[1] + // : path.split("/").slice(-2).join("/"); + + // let codeSnippet = ""; + // try { + // // Add timeout to prevent hanging on GitHub API calls + // const timeoutPromise = new Promise((_, reject) => + // setTimeout( + // () => reject(new Error("GitHub API timeout")), + // 5000, + // ), + // ); + + // const fetchPromise = fetchFileFromGitHub( + // repoData.owner!, + // repoData.repo!, + // defaultBranch, + // relativePath, + // env, + // false, + // ); + + // const fileContent = await Promise.race([ + // fetchPromise, + // timeoutPromise, + // ]); + + // if ( + // fileContent && + // typeof fileContent === "string" + // ) { + // const lines = fileContent.split("\n"); + // const centerLine = line - 1; // Convert to 0-based index + // const startLine = Math.max(0, centerLine - 5); + // const endLine = Math.min( + // lines.length - 1, + // centerLine + 5, + // ); + + // const snippet = lines.slice( + // startLine, + // endLine + 1, + // ); + // codeSnippet = snippet + // .map( + // (codeLine: string, lineIndex: number) => { + // const actualLineNumber = + // startLine + lineIndex + 1; + // const marker = + // actualLineNumber === line + // ? ">>>" + // : " "; + // return `${marker} ${actualLineNumber.toString().padStart(3)}: ${codeLine}`; + // }, + // ) + // .join("\n"); + // } else { + // throw new Error("File content not found"); + // } + // } catch (error) { + // // Fallback to showing just the function info without code content + // codeSnippet = `Function: ${name}\nFile: ${relativePath}:${line}\nCalls: ${functionName}\n\n(Code content temporarily unavailable)`; + // } + + // return `## Code Example ${index + 1}: ${name} + + // File: ${relativePath}:${line} + // Calls: ${functionName} + + // \`\`\` + // ${codeSnippet} + // \`\`\` + // `; + // }, + // ), + // ); + + // return { + // content: [ + // { + // type: "text", + // text: `šŸ“‹ Code Example Results for "${functionName}" function:\n\nFound ${callers.length} function${callers.length === 1 ? "" : "s"} that call "${functionName}":\n\n${codeExamples.join("\n\n")}`, + // }, + // ], + // }; + // } finally { + // await client.close(); + // } + // })(), + // // 8 second timeout + // new Promise((_, reject) => + // setTimeout( + // () => reject(new Error("Operation timeout")), + // 8000, + // ), + // ), + // ]); + + // return result; + // } catch (error) { + // console.error(`Graph query failed for ${functionName}:`, error); + // return { + // content: [ + // { + // type: "text", + // text: `ā±ļø **Search Timeout**\n\nThe search for "${functionName}" is taking too long. Please try again.\n\n**Possible causes:**\n• Large repository analysis in progress\n• Database temporarily busy\n• Complex query processing\n\n**Try again in a moment!**`, + // }, + // ], + // }; + // } + // } else { + // // Phase 2: Graph doesn't exist - check creation status and provide immediate feedback + // console.log( + // `Graph ${graphName} not found. Checking creation status...`, + // ); + + // // FIRST: Force clear any stale locks (older than 20 minutes) to prevent stuck states + // graphService.clearStaleLocks(repoKey); + + // // SECOND: If locks are older than 5 minutes, force clear them to allow fresh requests + // const progress = graphService.getCreationProgress(repoKey); + // if (progress.inProgress && progress.elapsedMinutes >= 5) { + // console.log( + // `[Debug] Forcing cleanup of ${repoKey} creation locks after ${progress.elapsedMinutes} minutes`, + // ); + // graphService.setCreationLock(repoKey, false); + // // Force clear all related locks + // const registry = getGlobalCreationRegistry(); + // registry.delete(repoKey); + // } + + // // THEN: Check if creation is actually in progress (after clearing stale locks) + // const finalProgress = graphService.getCreationProgress(repoKey); + // console.log( + // `[Debug] Progress check for ${repoKey} after clearing stale locks:`, + // finalProgress, + // ); + + // if (finalProgress.inProgress) { + // // Creation is genuinely in progress - show progress and ask to wait + // console.log( + // `[Debug] Creation in progress for ${repoKey}, showing progress`, + // ); + // return { + // content: [ + // { + // type: "text", + // text: `šŸ”„ **Graph Creation In Progress for ${repoKey}**\n\nā±ļø **Current Status**: ${finalProgress.phase}\nšŸ“Š **Elapsed Time**: ${finalProgress.elapsedMinutes} minutes\nāŒ› **Estimated Remaining**: ${finalProgress.estimatedRemaining}\n\nšŸ”„ **Please wait and try your question again in a few minutes:**\n"Show me code examples of how to use the ${functionName} function"\n\nšŸ’” *The system is analyzing the repository to build a knowledge graph of function relationships. This process takes time but enables precise code example searches.*`, + // }, + // ], + // }; + // } else { + // // No creation in progress - start it now and return immediate response + // console.log( + // `Starting graph creation for ${repoKey} in background...`, + // ); + + // // Set creation lock immediately + // graphService.setCreationLock(repoKey, true); + + // // Get configuration for the API call + // const config = getCodeGraphConfig(); + // const repoUrl = getGitHubRepoUrl( + // repoData.owner!, + // repoData.repo!, + // ); + // const apiUrl = getCodeGraphApiUrl(); + + // const requestBody = { + // repo_url: repoUrl, + // ignore: config.ignorePatterns, + // }; + + // console.log(`[Immediate] Making API request to ${apiUrl}`); + // console.log( + // `[Immediate] Request body:`, + // JSON.stringify(requestBody), + // ); + + // // Make the API call with a very short timeout to ensure it fires but doesn't block + // try { + // fetch(apiUrl, { + // method: "POST", + // headers: { + // "Content-Type": "application/json", + // Authorization: config.authToken, + // }, + // body: JSON.stringify(requestBody), + // signal: AbortSignal.timeout(5000), // Short 5 second timeout + // }) + // .then((response) => { + // if (response.ok) { + // console.log( + // `[Immediate] API request successful for ${repoKey}`, + // ); + // } else { + // console.error( + // `[Immediate] API request failed: ${response.status} ${response.statusText}`, + // ); + // } + // }) + // .catch((error) => { + // console.error( + // `[Immediate] API request error for ${repoKey}:`, + // error, + // ); + // }); + // } catch (error) { + // console.error( + // `[Immediate] Failed to initiate API request:`, + // error, + // ); + // } + + // return { + // content: [ + // { + // type: "text", + // text: `šŸš€ **Starting Code Analysis for ${repoKey}**\n\nāœ… **Graph creation has been initiated!** The system is now analyzing the repository to build a knowledge graph of function relationships.\n\nā±ļø **Estimated Time**: 5-10 minutes\nšŸ“Š **What's happening**: \n • Scanning repository structure\n • Analyzing function definitions\n • Mapping function call relationships\n • Building searchable graph database\n\nšŸ”„ **Please ask your question again in about 5-10 minutes:**\n"Show me code examples of how to use the ${functionName} function"\n\nšŸ’” *This one-time setup enables fast and precise code example searches for this repository!*`, + // }, + // ], + // }; + // } + // } + // } catch (error) { + // console.error("Error in fetch_code_usage_examples:", error); + // return { + // content: [ + // { + // type: "text", + // text: `āŒ Error processing code examples for "${functionName}": ${error instanceof Error ? error.message : "Unknown error"}`, + // }, + // ], + // }; + // } finally { + // // Clean up the service connection + // await graphService.disconnect(); + // } + // }, + // }, ]; } diff --git a/src/api/tools/repoHandlers/graphTools.disabled.ts b/src/api/tools/repoHandlers/graphTools.disabled.ts new file mode 100644 index 0000000..b0d5962 --- /dev/null +++ b/src/api/tools/repoHandlers/graphTools.disabled.ts @@ -0,0 +1,433 @@ +// import { describe, it, expect, beforeAll, afterAll } from "vitest"; +// import { FalkorDB } from "falkordb"; +// import { getDefaultRepoHandler } from "./DefaultRepoHandler"; +// import { getGraphService } from "./graphTools"; +// import path from "path"; + +// describe("fetch_code_usage_examples", () => { +// let client: FalkorDB; +// let graphService: any; + +// const realRepoData = { +// owner: "FalkorDB", +// repo: "GraphRAG-SDK", +// host: "gitmcp.io", +// urlType: "github" as const, +// }; + +// const testRepoData = { +// owner: "testuser", +// repo: "test-scenario-repo", +// host: "gitmcp.io", +// urlType: "github" as const, +// }; + +// const nonExistentRepoData = { +// owner: "nonexistent", +// repo: "fake-repo", +// host: "gitmcp.io", +// urlType: "github" as const, +// }; + +// beforeAll(async () => { +// client = await FalkorDB.connect({ +// socket: { host: "localhost", port: 6379 }, +// }); +// graphService = getGraphService(); +// }); + +// afterAll(async () => { +// if (client) { +// // Clean up any test graphs +// try { +// const graphs = await client.list(); +// const testGraphs = ["test-scenario-repo", "fake-repo"]; +// for (const graphName of testGraphs) { +// if (graphs.includes(graphName)) { +// const graph = client.selectGraph(graphName); +// await graph.delete(); +// console.log(`Cleaned up test graph: ${graphName}`); +// } +// } +// } catch (error) { +// console.log("Test cleanup error (expected):", error); +// } +// await client.close(); +// } +// }); + +// describe("Scenario 1: Graph exists + Function found", () => { +// it("should return actual code examples when function exists in real graph", async () => { +// const graphExists = await graphService.checkGraphExists("GraphRAG-SDK"); + +// if (!graphExists) { +// console.log("āš ļø GraphRAG-SDK graph not found, skipping Scenario 1"); +// return; +// } + +// const tools = getDefaultRepoHandler().getTools(realRepoData, {}, {}); +// const toolCb = tools.find((t) => t.name === "fetchUsageCodeExamples")?.cb; + +// if (!toolCb) { +// throw new Error("fetchUsageCodeExamples tool not found"); +// } + +// const result = await toolCb({ +// functionName: "chat_session", +// }); + +// expect(result.content[0].text).toMatch( +// /šŸ“‹ Code Example Results for "chat_session" function/, +// ); +// expect(result.content[0].text).toMatch(/Found \d+ function/); +// expect(result.content[0].text).toMatch(/Code Example \d+:/); + +// console.log("āœ… Scenario 1: Real code examples returned"); +// console.log( +// "Sample response:", +// result.content[0].text.substring(0, 300) + "...", +// ); +// }); +// }); + +// describe("Scenario 2: Graph exists + No results + Creation in progress", () => { +// it("should show creation progress when function not found but creation ongoing", async () => { +// const graphExists = await graphService.checkGraphExists("GraphRAG-SDK"); + +// if (!graphExists) { +// console.log("āš ļø GraphRAG-SDK graph not found, skipping Scenario 2"); +// return; +// } + +// // Test with a function that definitely doesn't exist +// const tools = getDefaultRepoHandler().getTools(realRepoData, {}, {}); +// const toolCb = tools.find((t) => t.name === "fetch_code_usage_examples") +// ?.cb; + +// if (!toolCb) { +// throw new Error("fetch_code_usage_examples tool not found"); +// } + +// // Manually set creation in progress to simulate this scenario +// const repoKey = `${realRepoData.owner}/${realRepoData.repo}`; +// graphService.setCreationLock(repoKey, true); + +// const result = await toolCb({ +// functionName: "definitely_nonexistent_function_12345", +// }); + +// // Clean up the lock +// graphService.setCreationLock(repoKey, false); + +// // Should show either creation progress or no results found +// const isCreationProgress = result.content[0].text.includes( +// "Graph Creation Still In Progress", +// ); +// const isNoResults = result.content[0].text.includes( +// "No calling functions found", +// ); + +// expect(isCreationProgress || isNoResults).toBe(true); +// console.log("āœ… Scenario 2: Handled non-existent function properly"); +// }); +// }); + +// describe("Scenario 3: Graph exists + No results + Creation complete", () => { +// it("should show 'no functions found' when function doesn't exist", async () => { +// const graphExists = await graphService.checkGraphExists("GraphRAG-SDK"); + +// if (!graphExists) { +// console.log("āš ļø GraphRAG-SDK graph not found, skipping Scenario 3"); +// return; +// } + +// const tools = getDefaultRepoHandler().getTools(realRepoData, {}, {}); +// const toolCb = tools.find((t) => t.name === "fetchUsageCodeExamples")?.cb; + +// if (!toolCb) { +// throw new Error("fetchUsageCodeExamples tool not found"); +// } + +// // Ensure no creation in progress +// const repoKey = `${realRepoData.owner}/${realRepoData.repo}`; +// graphService.setCreationLock(repoKey, false); + +// const result = await toolCb({ +// functionName: "absolutely_nonexistent_function_xyz_999", +// }); + +// expect(result.content[0].text).toMatch( +// /šŸ” No calling functions found|No function|not found/i, +// ); +// console.log("āœ… Scenario 3: No functions found message displayed"); +// }); +// }); + +// describe("Scenario 4: Graph exists + Query timeout", () => { +// it("should handle timeout gracefully with real database", async () => { +// const graphExists = await graphService.checkGraphExists("GraphRAG-SDK"); + +// if (!graphExists) { +// console.log("āš ļø GraphRAG-SDK graph not found, skipping Scenario 4"); +// return; +// } + +// const tools = getDefaultRepoHandler().getTools(realRepoData, {}, {}); +// const toolCb = tools.find((t) => t.name === "fetchUsageCodeExamples")?.cb; + +// if (!toolCb) { +// throw new Error("fetchUsageCodeExamples tool not found"); +// } + +// // Test with a function that might cause complex queries +// const start = Date.now(); +// const result = await toolCb({ +// functionName: "chat_session", +// }); +// const duration = Date.now() - start; + +// // Should complete within reasonable time (< 10 seconds) or show timeout +// if (duration > 10000) { +// expect(result.content[0].text).toMatch(/timeout|taking too long/i); +// console.log("āœ… Scenario 4: Timeout handled gracefully"); +// } else { +// console.log("āœ… Scenario 4: Query completed within timeout period"); +// } +// }); +// }); + +// describe("Scenario 5: No graph + Creation in progress", () => { +// it("should show creation progress for non-existent graph", async () => { +// const repoKey = `${testRepoData.owner}/${testRepoData.repo}`; + +// // Ensure graph doesn't exist +// const graphExists = await graphService.checkGraphExists( +// testRepoData.repo, +// ); +// expect(graphExists).toBe(false); + +// // Set creation in progress manually +// graphService.setCreationLock(repoKey, true); + +// const tools = getDefaultRepoHandler().getTools(testRepoData, {}, {}); +// const toolCb = tools.find((t) => t.name === "fetchUsageCodeExamples")?.cb; + +// if (!toolCb) { +// throw new Error("fetchUsageCodeExamples tool not found"); +// } + +// const result = await toolCb({ +// functionName: "test_function", +// }); + +// expect(result.content[0].text).toMatch(/šŸ”„.*Graph Creation In Progress/); +// expect(result.content[0].text).toMatch(/testuser\/test-scenario-repo/); + +// // Clean up +// graphService.setCreationLock(repoKey, false); + +// console.log("āœ… Scenario 5: Creation progress displayed"); +// }); +// }); + +// describe("Scenario 6: No graph + First time (Start creation)", () => { +// it("should initiate graph creation for new repository", async () => { +// const repoKey = `${nonExistentRepoData.owner}/${nonExistentRepoData.repo}`; + +// // Clean up any existing state +// graphService.setCreationLock(repoKey, false); +// graphService.clearStaleLocks(repoKey); + +// // Ensure graph doesn't exist +// const graphExists = await graphService.checkGraphExists( +// nonExistentRepoData.repo, +// ); +// expect(graphExists).toBe(false); + +// const tools = getDefaultRepoHandler().getTools( +// nonExistentRepoData, +// {}, +// {}, +// ); +// const toolCb = tools.find((t) => t.name === "fetchUsageCodeExamples")?.cb; + +// if (!toolCb) { +// throw new Error("fetchUsageCodeExamples tool not found"); +// } + +// const result = await toolCb({ +// functionName: "test_function", +// }); + +// expect(result.content[0].text).toMatch(/šŸš€.*Starting Code Analysis/); +// expect(result.content[0].text).toMatch( +// /Graph creation has been initiated/, +// ); +// expect(result.content[0].text).toMatch(/5-10 minutes/); + +// console.log("āœ… Scenario 6: Graph creation initiated"); + +// // Verify creation lock was set +// const progress = graphService.getCreationProgress(repoKey); +// expect(progress.inProgress).toBe(true); + +// // Clean up +// graphService.setCreationLock(repoKey, false); +// }); +// }); + +// describe("Scenario 7: GitHub API timeout during code fetching", () => { +// it("should handle GitHub API timeouts gracefully", async () => { +// const graphExists = await graphService.checkGraphExists("GraphRAG-SDK"); + +// if (!graphExists) { +// console.log("āš ļø GraphRAG-SDK graph not found, skipping Scenario 7"); +// return; +// } + +// // Test with a function that exists but might have GitHub API issues +// const tools = getDefaultRepoHandler().getTools(realRepoData, {}, {}); +// const toolCb = tools.find((t) => t.name === "fetchUsageCodeExamples")?.cb; + +// if (!toolCb) { +// throw new Error("fetchUsageCodeExamples tool not found"); +// } + +// const result = await toolCb({ +// functionName: "chat_session", +// }); + +// // Should either return code examples or show fallback message +// const hasCodeExamples = result.content[0].text.includes("Code Example"); +// const hasFallback = result.content[0].text.includes( +// "temporarily unavailable", +// ); + +// expect(hasCodeExamples || hasFallback).toBe(true); +// console.log("āœ… Scenario 7: GitHub API handling working"); +// }); +// }); + +// describe("Scenario 8: General error/exception", () => { +// it("should handle database connection errors gracefully", async () => { +// // Create a repo data with invalid configuration to trigger errors +// const invalidRepoData = { +// owner: "", // Empty string should cause URL construction errors +// repo: "", // Empty string should cause URL construction errors +// host: "gitmcp.io", +// urlType: "github" as const, +// }; + +// const tools = getDefaultRepoHandler().getTools(invalidRepoData, {}, {}); +// const toolCb = tools.find((t) => t.name === "fetchUsageCodeExamples")?.cb; + +// if (!toolCb) { +// throw new Error("fetchUsageCodeExamples tool not found"); +// } + +// try { +// const result = await toolCb({ +// functionName: "test_function", +// }); + +// // Should either return error message or fail with empty repo data +// const hasError = +// result.content[0].text.includes("āŒ") || +// result.content[0].text.includes("Error") || +// result.content[0].text.includes("failed") || +// result.content[0].text.includes("Invalid") || +// result.content[0].text.includes("empty"); + +// expect(hasError).toBe(true); +// console.log("āœ… Scenario 8: Error handling working"); +// } catch (error) { +// // If an exception is thrown, that's also valid error handling +// expect(error).toBeDefined(); +// console.log("āœ… Scenario 8: Error handling working (exception thrown)"); +// } +// }); +// }); + +// describe("Edge Cases and State Management", () => { +// it("should handle stale lock cleanup properly", async () => { +// const repoKey = `${testRepoData.owner}/${testRepoData.repo}`; + +// // Manually create a stale lock (simulate old timestamp) +// const registry = graphService.getGlobalCreationRegistry?.() || new Map(); +// registry.set(repoKey, { +// inProgress: true, +// timestamp: Date.now() - 15 * 60 * 1000, // 15 minutes ago +// phase: "Stale analysis", +// }); + +// const tools = getDefaultRepoHandler().getTools(testRepoData, {}, {}); +// const toolCb = tools.find((t) => t.name === "fetchUsageCodeExamples")?.cb; + +// if (!toolCb) { +// throw new Error("fetchUsageCodeExamples tool not found"); +// } + +// const result = await toolCb({ +// functionName: "test_function", +// }); + +// // Should clean up stale locks and either start fresh or show progress +// expect(result.content[0].text).toMatch( +// /Starting Code Analysis|Graph Creation/, +// ); +// console.log("āœ… Stale lock cleanup working"); +// }); + +// it("should handle multiple repositories independently", async () => { +// const repo1Key = `${realRepoData.owner}/${realRepoData.repo}`; +// const repo2Key = `${testRepoData.owner}/${testRepoData.repo}`; + +// // Set different states for each repo +// graphService.setCreationLock(repo1Key, false); +// graphService.setCreationLock(repo2Key, true); + +// const tools1 = getDefaultRepoHandler().getTools(realRepoData, {}, {}); +// const tools2 = getDefaultRepoHandler().getTools(testRepoData, {}, {}); + +// const toolCb1 = tools1.find( +// (t) => t.name === "fetchUsageCodeExamples", +// )?.cb; +// const toolCb2 = tools2.find( +// (t) => t.name === "fetchUsageCodeExamples", +// )?.cb; + +// if (!toolCb1 || !toolCb2) { +// throw new Error( +// "fetchUsageCodeExamples tool not found in one or both handlers", +// ); +// } + +// const [result1, result2] = await Promise.all([ +// toolCb1({ functionName: "test_function" }), +// toolCb2({ functionName: "test_function" }), +// ]); + +// // Results should be different based on repo state +// expect(result1.content[0].text).not.toEqual(result2.content[0].text); +// console.log("āœ… Multi-repository independence working"); + +// // Clean up +// graphService.setCreationLock(repo1Key, false); +// graphService.setCreationLock(repo2Key, false); +// }); + +// it("should validate real FalkorDB connection and operations", async () => { +// // Test actual database operations +// const graphs = await client.list(); +// expect(Array.isArray(graphs)).toBe(true); + +// // Test graph service connection +// const isConnected = await graphService.checkGraphExists("GraphRAG-SDK"); +// expect(typeof isConnected).toBe("boolean"); + +// console.log( +// `āœ… FalkorDB operations working. Available graphs: ${graphs.join(", ")}`, +// ); +// }); +// }); +// }); diff --git a/src/api/tools/repoHandlers/graphTools.test.ts b/src/api/tools/repoHandlers/graphTools.test.ts deleted file mode 100644 index 6689d63..0000000 --- a/src/api/tools/repoHandlers/graphTools.test.ts +++ /dev/null @@ -1,433 +0,0 @@ -import { describe, it, expect, beforeAll, afterAll } from "vitest"; -import { FalkorDB } from "falkordb"; -import { getDefaultRepoHandler } from "./DefaultRepoHandler"; -import { getGraphService } from "./graphTools"; -import path from "path"; - -// Comprehensive test suite for all 8 fetchUsageCodeExamples scenarios using real data -describe("fetchUsageCodeExamples - All 8 Scenarios with Real Data", () => { - let client: FalkorDB; - let graphService: any; - - const realRepoData = { - owner: "FalkorDB", - repo: "GraphRAG-SDK", - host: "gitmcp.io", - urlType: "github" as const, - }; - - const testRepoData = { - owner: "testuser", - repo: "test-scenario-repo", - host: "gitmcp.io", - urlType: "github" as const, - }; - - const nonExistentRepoData = { - owner: "nonexistent", - repo: "fake-repo", - host: "gitmcp.io", - urlType: "github" as const, - }; - - beforeAll(async () => { - client = await FalkorDB.connect({ - socket: { host: "localhost", port: 6379 }, - }); - graphService = getGraphService(); - }); - - afterAll(async () => { - if (client) { - // Clean up any test graphs - try { - const graphs = await client.list(); - const testGraphs = ["test-scenario-repo", "fake-repo"]; - for (const graphName of testGraphs) { - if (graphs.includes(graphName)) { - const graph = client.selectGraph(graphName); - await graph.delete(); - console.log(`Cleaned up test graph: ${graphName}`); - } - } - } catch (error) { - console.log("Test cleanup error (expected):", error); - } - await client.close(); - } - }); - - describe("Scenario 1: Graph exists + Function found", () => { - it("should return actual code examples when function exists in real graph", async () => { - const graphExists = await graphService.checkGraphExists("GraphRAG-SDK"); - - if (!graphExists) { - console.log("āš ļø GraphRAG-SDK graph not found, skipping Scenario 1"); - return; - } - - const tools = getDefaultRepoHandler().getTools(realRepoData, {}, {}); - const toolCb = tools.find((t) => t.name === "fetchUsageCodeExamples")?.cb; - - if (!toolCb) { - throw new Error("fetchUsageCodeExamples tool not found"); - } - - const result = await toolCb({ - functionName: "chat_session", - }); - - expect(result.content[0].text).toMatch( - /šŸ“‹ Code Example Results for "chat_session" function/, - ); - expect(result.content[0].text).toMatch(/Found \d+ function/); - expect(result.content[0].text).toMatch(/Code Example \d+:/); - - console.log("āœ… Scenario 1: Real code examples returned"); - console.log( - "Sample response:", - result.content[0].text.substring(0, 300) + "...", - ); - }); - }); - - describe("Scenario 2: Graph exists + No results + Creation in progress", () => { - it("should show creation progress when function not found but creation ongoing", async () => { - const graphExists = await graphService.checkGraphExists("GraphRAG-SDK"); - - if (!graphExists) { - console.log("āš ļø GraphRAG-SDK graph not found, skipping Scenario 2"); - return; - } - - // Test with a function that definitely doesn't exist - const tools = getDefaultRepoHandler().getTools(realRepoData, {}, {}); - const toolCb = tools.find((t) => t.name === "fetchUsageCodeExamples")?.cb; - - if (!toolCb) { - throw new Error("fetchUsageCodeExamples tool not found"); - } - - // Manually set creation in progress to simulate this scenario - const repoKey = `${realRepoData.owner}/${realRepoData.repo}`; - graphService.setCreationLock(repoKey, true); - - const result = await toolCb({ - functionName: "definitely_nonexistent_function_12345", - }); - - // Clean up the lock - graphService.setCreationLock(repoKey, false); - - // Should show either creation progress or no results found - const isCreationProgress = result.content[0].text.includes( - "Graph Creation Still In Progress", - ); - const isNoResults = result.content[0].text.includes( - "No calling functions found", - ); - - expect(isCreationProgress || isNoResults).toBe(true); - console.log("āœ… Scenario 2: Handled non-existent function properly"); - }); - }); - - describe("Scenario 3: Graph exists + No results + Creation complete", () => { - it("should show 'no functions found' when function doesn't exist", async () => { - const graphExists = await graphService.checkGraphExists("GraphRAG-SDK"); - - if (!graphExists) { - console.log("āš ļø GraphRAG-SDK graph not found, skipping Scenario 3"); - return; - } - - const tools = getDefaultRepoHandler().getTools(realRepoData, {}, {}); - const toolCb = tools.find((t) => t.name === "fetchUsageCodeExamples")?.cb; - - if (!toolCb) { - throw new Error("fetchUsageCodeExamples tool not found"); - } - - // Ensure no creation in progress - const repoKey = `${realRepoData.owner}/${realRepoData.repo}`; - graphService.setCreationLock(repoKey, false); - - const result = await toolCb({ - functionName: "absolutely_nonexistent_function_xyz_999", - }); - - expect(result.content[0].text).toMatch( - /šŸ” No calling functions found|No function|not found/i, - ); - console.log("āœ… Scenario 3: No functions found message displayed"); - }); - }); - - describe("Scenario 4: Graph exists + Query timeout", () => { - it("should handle timeout gracefully with real database", async () => { - const graphExists = await graphService.checkGraphExists("GraphRAG-SDK"); - - if (!graphExists) { - console.log("āš ļø GraphRAG-SDK graph not found, skipping Scenario 4"); - return; - } - - const tools = getDefaultRepoHandler().getTools(realRepoData, {}, {}); - const toolCb = tools.find((t) => t.name === "fetchUsageCodeExamples")?.cb; - - if (!toolCb) { - throw new Error("fetchUsageCodeExamples tool not found"); - } - - // Test with a function that might cause complex queries - const start = Date.now(); - const result = await toolCb({ - functionName: "chat_session", - }); - const duration = Date.now() - start; - - // Should complete within reasonable time (< 10 seconds) or show timeout - if (duration > 10000) { - expect(result.content[0].text).toMatch(/timeout|taking too long/i); - console.log("āœ… Scenario 4: Timeout handled gracefully"); - } else { - console.log("āœ… Scenario 4: Query completed within timeout period"); - } - }); - }); - - describe("Scenario 5: No graph + Creation in progress", () => { - it("should show creation progress for non-existent graph", async () => { - const repoKey = `${testRepoData.owner}/${testRepoData.repo}`; - - // Ensure graph doesn't exist - const graphExists = await graphService.checkGraphExists( - testRepoData.repo, - ); - expect(graphExists).toBe(false); - - // Set creation in progress manually - graphService.setCreationLock(repoKey, true); - - const tools = getDefaultRepoHandler().getTools(testRepoData, {}, {}); - const toolCb = tools.find((t) => t.name === "fetchUsageCodeExamples")?.cb; - - if (!toolCb) { - throw new Error("fetchUsageCodeExamples tool not found"); - } - - const result = await toolCb({ - functionName: "test_function", - }); - - expect(result.content[0].text).toMatch(/šŸ”„.*Graph Creation In Progress/); - expect(result.content[0].text).toMatch(/testuser\/test-scenario-repo/); - - // Clean up - graphService.setCreationLock(repoKey, false); - - console.log("āœ… Scenario 5: Creation progress displayed"); - }); - }); - - describe("Scenario 6: No graph + First time (Start creation)", () => { - it("should initiate graph creation for new repository", async () => { - const repoKey = `${nonExistentRepoData.owner}/${nonExistentRepoData.repo}`; - - // Clean up any existing state - graphService.setCreationLock(repoKey, false); - graphService.clearStaleLocks(repoKey); - - // Ensure graph doesn't exist - const graphExists = await graphService.checkGraphExists( - nonExistentRepoData.repo, - ); - expect(graphExists).toBe(false); - - const tools = getDefaultRepoHandler().getTools( - nonExistentRepoData, - {}, - {}, - ); - const toolCb = tools.find((t) => t.name === "fetchUsageCodeExamples")?.cb; - - if (!toolCb) { - throw new Error("fetchUsageCodeExamples tool not found"); - } - - const result = await toolCb({ - functionName: "test_function", - }); - - expect(result.content[0].text).toMatch(/šŸš€.*Starting Code Analysis/); - expect(result.content[0].text).toMatch( - /Graph creation has been initiated/, - ); - expect(result.content[0].text).toMatch(/5-10 minutes/); - - console.log("āœ… Scenario 6: Graph creation initiated"); - - // Verify creation lock was set - const progress = graphService.getCreationProgress(repoKey); - expect(progress.inProgress).toBe(true); - - // Clean up - graphService.setCreationLock(repoKey, false); - }); - }); - - describe("Scenario 7: GitHub API timeout during code fetching", () => { - it("should handle GitHub API timeouts gracefully", async () => { - const graphExists = await graphService.checkGraphExists("GraphRAG-SDK"); - - if (!graphExists) { - console.log("āš ļø GraphRAG-SDK graph not found, skipping Scenario 7"); - return; - } - - // Test with a function that exists but might have GitHub API issues - const tools = getDefaultRepoHandler().getTools(realRepoData, {}, {}); - const toolCb = tools.find((t) => t.name === "fetchUsageCodeExamples")?.cb; - - if (!toolCb) { - throw new Error("fetchUsageCodeExamples tool not found"); - } - - const result = await toolCb({ - functionName: "chat_session", - }); - - // Should either return code examples or show fallback message - const hasCodeExamples = result.content[0].text.includes("Code Example"); - const hasFallback = result.content[0].text.includes( - "temporarily unavailable", - ); - - expect(hasCodeExamples || hasFallback).toBe(true); - console.log("āœ… Scenario 7: GitHub API handling working"); - }); - }); - - describe("Scenario 8: General error/exception", () => { - it("should handle database connection errors gracefully", async () => { - // Create a repo data with invalid configuration to trigger errors - const invalidRepoData = { - owner: "", // Empty string should cause URL construction errors - repo: "", // Empty string should cause URL construction errors - host: "gitmcp.io", - urlType: "github" as const, - }; - - const tools = getDefaultRepoHandler().getTools(invalidRepoData, {}, {}); - const toolCb = tools.find((t) => t.name === "fetchUsageCodeExamples")?.cb; - - if (!toolCb) { - throw new Error("fetchUsageCodeExamples tool not found"); - } - - try { - const result = await toolCb({ - functionName: "test_function", - }); - - // Should either return error message or fail with empty repo data - const hasError = - result.content[0].text.includes("āŒ") || - result.content[0].text.includes("Error") || - result.content[0].text.includes("failed") || - result.content[0].text.includes("Invalid") || - result.content[0].text.includes("empty"); - - expect(hasError).toBe(true); - console.log("āœ… Scenario 8: Error handling working"); - } catch (error) { - // If an exception is thrown, that's also valid error handling - expect(error).toBeDefined(); - console.log("āœ… Scenario 8: Error handling working (exception thrown)"); - } - }); - }); - - describe("Edge Cases and State Management", () => { - it("should handle stale lock cleanup properly", async () => { - const repoKey = `${testRepoData.owner}/${testRepoData.repo}`; - - // Manually create a stale lock (simulate old timestamp) - const registry = graphService.getGlobalCreationRegistry?.() || new Map(); - registry.set(repoKey, { - inProgress: true, - timestamp: Date.now() - 15 * 60 * 1000, // 15 minutes ago - phase: "Stale analysis", - }); - - const tools = getDefaultRepoHandler().getTools(testRepoData, {}, {}); - const toolCb = tools.find((t) => t.name === "fetchUsageCodeExamples")?.cb; - - if (!toolCb) { - throw new Error("fetchUsageCodeExamples tool not found"); - } - - const result = await toolCb({ - functionName: "test_function", - }); - - // Should clean up stale locks and either start fresh or show progress - expect(result.content[0].text).toMatch( - /Starting Code Analysis|Graph Creation/, - ); - console.log("āœ… Stale lock cleanup working"); - }); - - it("should handle multiple repositories independently", async () => { - const repo1Key = `${realRepoData.owner}/${realRepoData.repo}`; - const repo2Key = `${testRepoData.owner}/${testRepoData.repo}`; - - // Set different states for each repo - graphService.setCreationLock(repo1Key, false); - graphService.setCreationLock(repo2Key, true); - - const tools1 = getDefaultRepoHandler().getTools(realRepoData, {}, {}); - const tools2 = getDefaultRepoHandler().getTools(testRepoData, {}, {}); - - const toolCb1 = tools1.find( - (t) => t.name === "fetchUsageCodeExamples", - )?.cb; - const toolCb2 = tools2.find( - (t) => t.name === "fetchUsageCodeExamples", - )?.cb; - - if (!toolCb1 || !toolCb2) { - throw new Error( - "fetchUsageCodeExamples tool not found in one or both handlers", - ); - } - - const [result1, result2] = await Promise.all([ - toolCb1({ functionName: "test_function" }), - toolCb2({ functionName: "test_function" }), - ]); - - // Results should be different based on repo state - expect(result1.content[0].text).not.toEqual(result2.content[0].text); - console.log("āœ… Multi-repository independence working"); - - // Clean up - graphService.setCreationLock(repo1Key, false); - graphService.setCreationLock(repo2Key, false); - }); - - it("should validate real FalkorDB connection and operations", async () => { - // Test actual database operations - const graphs = await client.list(); - expect(Array.isArray(graphs)).toBe(true); - - // Test graph service connection - const isConnected = await graphService.checkGraphExists("GraphRAG-SDK"); - expect(typeof isConnected).toBe("boolean"); - - console.log( - `āœ… FalkorDB operations working. Available graphs: ${graphs.join(", ")}`, - ); - }); - }); -}); From 6be42abff45abcc41f15c4485963c94645396146 Mon Sep 17 00:00:00 2001 From: Ido Salomon Date: Mon, 4 Aug 2025 00:41:23 +0300 Subject: [PATCH 4/4] fix e2e --- playwright.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playwright.config.ts b/playwright.config.ts index 99621ae..7b34be4 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -67,7 +67,7 @@ export default defineConfig({ }, { name: 'MCP Inspector', - command: 'CLIENT_PORT=5174 SERVER_PORT=6277 npx @modelcontextprotocol/inspector', + command: 'CLIENT_PORT=5174 SERVER_PORT=6277 npx @modelcontextprotocol/inspector@0.8.2', url: 'http://localhost:5174', // Inspector UI URL (matches baseURL) stdout: 'ignore', stderr: 'pipe',