feat(agent): Refactor chat agent state and tools for improved document handling and error messaging
This commit is contained in:
parent
f6eab5a95a
commit
d63196b2e8
11 changed files with 532 additions and 798 deletions
298
package-lock.json
generated
298
package-lock.json
generated
|
|
@ -106,9 +106,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@anthropic-ai/sdk/node_modules/@types/node": {
|
||||
"version": "18.19.120",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.120.tgz",
|
||||
"integrity": "sha512-WtCGHFXnVI8WHLxDAt5TbnCM4eSE+nI0QN2NJtwzcgMhht2eNz6V9evJrk+lwC8bCY8OWV5Ym8Jz7ZEyGnKnMA==",
|
||||
"version": "18.19.121",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.121.tgz",
|
||||
"integrity": "sha512-bHOrbyztmyYIi4f1R0s17QsPs1uyyYnGcXeZoGEd227oZjry0q6XQBQxd82X1I57zEfwO8h9Xo+Kl5gX1d9MwQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
|
|
@ -136,9 +136,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@babel/runtime": {
|
||||
"version": "7.27.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.6.tgz",
|
||||
"integrity": "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==",
|
||||
"version": "7.28.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.2.tgz",
|
||||
"integrity": "sha512-KHp2IflsnGywDjBWDkR9iEqiWSpc8GIi0lgTT3mOElT0PP1tG26P4tmFI2YvAdzgq9RGyoHZQEIEdZy6Ec5xCA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
|
|
@ -161,9 +161,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@browserbasehq/sdk/node_modules/@types/node": {
|
||||
"version": "18.19.120",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.120.tgz",
|
||||
"integrity": "sha512-WtCGHFXnVI8WHLxDAt5TbnCM4eSE+nI0QN2NJtwzcgMhht2eNz6V9evJrk+lwC8bCY8OWV5Ym8Jz7ZEyGnKnMA==",
|
||||
"version": "18.19.121",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.121.tgz",
|
||||
"integrity": "sha512-bHOrbyztmyYIi4f1R0s17QsPs1uyyYnGcXeZoGEd227oZjry0q6XQBQxd82X1I57zEfwO8h9Xo+Kl5gX1d9MwQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
|
|
@ -1264,21 +1264,21 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@floating-ui/core": {
|
||||
"version": "1.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.2.tgz",
|
||||
"integrity": "sha512-wNB5ooIKHQc+Kui96jE/n69rHFWAVoxn5CAzL1Xdd8FG03cgY3MLO+GF9U3W737fYDSgPWA6MReKhBQBop6Pcw==",
|
||||
"version": "1.7.3",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.3.tgz",
|
||||
"integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@floating-ui/utils": "^0.2.10"
|
||||
}
|
||||
},
|
||||
"node_modules/@floating-ui/dom": {
|
||||
"version": "1.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.2.tgz",
|
||||
"integrity": "sha512-7cfaOQuCS27HD7DX+6ib2OrnW+b4ZBwDNnCcT0uTyidcmyWb03FnQqJybDBoCnpdxwBSfA94UAYlRCt7mV+TbA==",
|
||||
"version": "1.7.3",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.3.tgz",
|
||||
"integrity": "sha512-uZA413QEpNuhtb3/iIKoYMSK07keHPYeXF02Zhd6e213j+d1NamLix/mCLxBUDW/Gx52sPH2m+chlUsyaBs/Ag==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@floating-ui/core": "^1.7.2",
|
||||
"@floating-ui/core": "^1.7.3",
|
||||
"@floating-ui/utils": "^0.2.10"
|
||||
}
|
||||
},
|
||||
|
|
@ -1298,12 +1298,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@floating-ui/react-dom": {
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.4.tgz",
|
||||
"integrity": "sha512-JbbpPhp38UmXDDAu60RJmbeme37Jbgsm7NrHGgzYYFKmblzRUh6Pa641dII6LsjwF4XlScDrde2UAzDo/b9KPw==",
|
||||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.5.tgz",
|
||||
"integrity": "sha512-HDO/1/1oH9fjj4eLgegrlH3dklZpHtUYYFiVwMUwfGvk9jWDRWqkklA2/NFScknrcNSspbV868WjXORvreDX+Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@floating-ui/dom": "^1.7.2"
|
||||
"@floating-ui/dom": "^1.7.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8.0",
|
||||
|
|
@ -1396,9 +1396,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@headlessui/react": {
|
||||
"version": "2.2.5",
|
||||
"resolved": "https://registry.npmjs.org/@headlessui/react/-/react-2.2.5.tgz",
|
||||
"integrity": "sha512-h1+2Vu1yR5pp/fBcTnwVEW8Kb94Hbxp7MXZLORfDzvSrbmGgiTyaTZ4LI/tPNZnK8eDrYD9s9cMbjm5HS5otIQ==",
|
||||
"version": "2.2.7",
|
||||
"resolved": "https://registry.npmjs.org/@headlessui/react/-/react-2.2.7.tgz",
|
||||
"integrity": "sha512-WKdTymY8Y49H8/gUc/lIyYK1M+/6dq0Iywh4zTZVAaiTDprRfioxSgD0wnXTQTBpjpGJuTL1NO/mqEvc//5SSg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@floating-ui/react": "^0.26.16",
|
||||
|
|
@ -1469,9 +1469,9 @@
|
|||
"license": "ISC"
|
||||
},
|
||||
"node_modules/@ibm-cloud/watsonx-ai": {
|
||||
"version": "1.6.9",
|
||||
"resolved": "https://registry.npmjs.org/@ibm-cloud/watsonx-ai/-/watsonx-ai-1.6.9.tgz",
|
||||
"integrity": "sha512-aW4jUVgxjdDa8IDSM+KPeR42pxeR5AUvSXxvj+iid1DdrmRd/SRR9o/FdWEjpZLgcs5RXQFIT56goWkJv7s8oQ==",
|
||||
"version": "1.6.10",
|
||||
"resolved": "https://registry.npmjs.org/@ibm-cloud/watsonx-ai/-/watsonx-ai-1.6.10.tgz",
|
||||
"integrity": "sha512-aZV50/s8VZc7w0t/qcaBw3RLT3WDsAeZUJlP8EbG/csZJF3a8F7alihbGOM4lJFM7R4Z81Lucz3nfHi2KR7J4Q==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
|
|
@ -1484,9 +1484,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@ibm-cloud/watsonx-ai/node_modules/@types/node": {
|
||||
"version": "18.19.120",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.120.tgz",
|
||||
"integrity": "sha512-WtCGHFXnVI8WHLxDAt5TbnCM4eSE+nI0QN2NJtwzcgMhht2eNz6V9evJrk+lwC8bCY8OWV5Ym8Jz7ZEyGnKnMA==",
|
||||
"version": "18.19.121",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.121.tgz",
|
||||
"integrity": "sha512-bHOrbyztmyYIi4f1R0s17QsPs1uyyYnGcXeZoGEd227oZjry0q6XQBQxd82X1I57zEfwO8h9Xo+Kl5gX1d9MwQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
|
|
@ -2017,9 +2017,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@langchain/anthropic": {
|
||||
"version": "0.3.24",
|
||||
"resolved": "https://registry.npmjs.org/@langchain/anthropic/-/anthropic-0.3.24.tgz",
|
||||
"integrity": "sha512-Gi1TwXu5vkCxUMToiXaiwTTWq9v3WMyU3ldB/VEWjzbkr3nKF5kcp+HLqhvV7WWOFVTTNgG+pzfq8JALecq5MA==",
|
||||
"version": "0.3.25",
|
||||
"resolved": "https://registry.npmjs.org/@langchain/anthropic/-/anthropic-0.3.25.tgz",
|
||||
"integrity": "sha512-KipKY0njNps7bgINca1jVAShnOh/+MpfN/hB580TUVrnsT21e5bykfNjiGVZ1S1A/qdHSJsRMkie2igGij/acA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@anthropic-ai/sdk": "^0.56.0",
|
||||
|
|
@ -2590,9 +2590,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@langchain/google-genai": {
|
||||
"version": "0.2.15",
|
||||
"resolved": "https://registry.npmjs.org/@langchain/google-genai/-/google-genai-0.2.15.tgz",
|
||||
"integrity": "sha512-fAD3xjzd5TxWQCKlttNeEc+b5tUX43hBqKH3rk3g+wbl1ToLqe3ocWawKRmGotEuI5jhDVmoHjDxoNMifFDgmg==",
|
||||
"version": "0.2.16",
|
||||
"resolved": "https://registry.npmjs.org/@langchain/google-genai/-/google-genai-0.2.16.tgz",
|
||||
"integrity": "sha512-7xgQfZtn4EcKL7HYV7c5ZZUTjzjY0eh1Ex2570uwEBIUlyP5GFYeRe7gizx6965DYu6rktkXRMHaU0CuOXxAXQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@google/generative-ai": "^0.24.0",
|
||||
|
|
@ -2635,13 +2635,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@langchain/langgraph": {
|
||||
"version": "0.3.11",
|
||||
"resolved": "https://registry.npmjs.org/@langchain/langgraph/-/langgraph-0.3.11.tgz",
|
||||
"integrity": "sha512-Lh8oga4ismQyw1NGZKoHPdeGke1g5HMF7V0nBlc5R7GnV8tfC6pdsXjiEH6sYsHsRDInfy8uQeob/BwEmMSSbQ==",
|
||||
"version": "0.3.12",
|
||||
"resolved": "https://registry.npmjs.org/@langchain/langgraph/-/langgraph-0.3.12.tgz",
|
||||
"integrity": "sha512-4jKvfmxxgQyKnCvXdFbcKt6MdfaJoQ2WWqBR16o2E6D2RxqHvnLMMClZh4FSd6WYw39z5LGWvzRapFbRMqxu1A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@langchain/langgraph-checkpoint": "~0.0.18",
|
||||
"@langchain/langgraph-sdk": "~0.0.100",
|
||||
"@langchain/langgraph-sdk": "~0.0.102",
|
||||
"uuid": "^10.0.0",
|
||||
"zod": "^3.25.32"
|
||||
},
|
||||
|
|
@ -2674,9 +2674,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@langchain/langgraph-sdk": {
|
||||
"version": "0.0.100",
|
||||
"resolved": "https://registry.npmjs.org/@langchain/langgraph-sdk/-/langgraph-sdk-0.0.100.tgz",
|
||||
"integrity": "sha512-mQuj0KgjD31Me+/W658OtdlOACOjgipWp/hF80OY4w4LqWCNIQWJBWMZ3f1/E8jpog/XBCROR37auFc7Fj+4Dw==",
|
||||
"version": "0.0.105",
|
||||
"resolved": "https://registry.npmjs.org/@langchain/langgraph-sdk/-/langgraph-sdk-0.0.105.tgz",
|
||||
"integrity": "sha512-3DD1W1wnbP48807qq+5gY248mFcwwNGqKdmZt05P3zeLpfP5Sfm6ELzVvqHGpr+qumP0yGRZs/7qArYGXRRfcQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/json-schema": "^7.0.15",
|
||||
|
|
@ -2748,9 +2748,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@langchain/openai/node_modules/openai": {
|
||||
"version": "5.10.2",
|
||||
"resolved": "https://registry.npmjs.org/openai/-/openai-5.10.2.tgz",
|
||||
"integrity": "sha512-n+vi74LzHtvlKcDPn9aApgELGiu5CwhaLG40zxLTlFQdoSJCLACORIPC2uVQ3JEYAbqapM+XyRKFy2Thej7bIw==",
|
||||
"version": "5.11.0",
|
||||
"resolved": "https://registry.npmjs.org/openai/-/openai-5.11.0.tgz",
|
||||
"integrity": "sha512-+AuTc5pVjlnTuA9zvn8rA/k+1RluPIx9AD4eDcnutv6JNwHHZxIhkFy+tmMKCvmMFDQzfA/r1ujvPWB19DQkYg==",
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
"openai": "bin/cli"
|
||||
|
|
@ -2822,9 +2822,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@next/env": {
|
||||
"version": "15.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@next/env/-/env-15.4.3.tgz",
|
||||
"integrity": "sha512-lKJ9KJAvaWzqurIsz6NWdQOLj96mdhuDMusLSYHw9HBe2On7BjUwU1WeRvq19x7NrEK3iOgMeSBV5qEhVH1cMw==",
|
||||
"version": "15.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@next/env/-/env-15.4.5.tgz",
|
||||
"integrity": "sha512-ruM+q2SCOVCepUiERoxOmZY9ZVoecR3gcXNwCYZRvQQWRjhOiPJGmQ2fAiLR6YKWXcSAh7G79KEFxN3rwhs4LQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@next/eslint-plugin-next": {
|
||||
|
|
@ -2838,9 +2838,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@next/swc-darwin-arm64": {
|
||||
"version": "15.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.4.3.tgz",
|
||||
"integrity": "sha512-YAhZWKeEYY7LHQJiQ8fe3Y6ymfcDcTn7rDC8PDu/pdeIl1Z2LHD4uyPNuQUGCEQT//MSNv6oZCeQzZfTCKZv+A==",
|
||||
"version": "15.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.4.5.tgz",
|
||||
"integrity": "sha512-84dAN4fkfdC7nX6udDLz9GzQlMUwEMKD7zsseXrl7FTeIItF8vpk1lhLEnsotiiDt+QFu3O1FVWnqwcRD2U3KA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
|
@ -2854,9 +2854,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@next/swc-darwin-x64": {
|
||||
"version": "15.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.4.3.tgz",
|
||||
"integrity": "sha512-ZPHRdd51xaxCMpT4viQ6h8TgYM1zPW1JIeksPY9wKlyvBVUQqrWqw8kEh1sa7/x0Ied+U7pYHkAkutrUwxbMcg==",
|
||||
"version": "15.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.4.5.tgz",
|
||||
"integrity": "sha512-CL6mfGsKuFSyQjx36p2ftwMNSb8PQog8y0HO/ONLdQqDql7x3aJb/wB+LA651r4we2pp/Ck+qoRVUeZZEvSurA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
|
@ -2870,9 +2870,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@next/swc-linux-arm64-gnu": {
|
||||
"version": "15.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.4.3.tgz",
|
||||
"integrity": "sha512-QUdqftCXC5vw5cowucqi9FeOPQ0vdMxoOHLY0J5jPdercwSJFjdi9CkEO4Xkq1eG4t1TB/BG81n6rmTsWoILnw==",
|
||||
"version": "15.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.4.5.tgz",
|
||||
"integrity": "sha512-1hTVd9n6jpM/thnDc5kYHD1OjjWYpUJrJxY4DlEacT7L5SEOXIifIdTye6SQNNn8JDZrcN+n8AWOmeJ8u3KlvQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
|
@ -2886,9 +2886,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@next/swc-linux-arm64-musl": {
|
||||
"version": "15.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.4.3.tgz",
|
||||
"integrity": "sha512-HTL31NsmoafX+r5g91Yj3+q34nrn1xKmCWVuNA+fUWO4X0pr+n83uGzLyEOn0kUqbMZ40KmWx+4wsbMoUChkiQ==",
|
||||
"version": "15.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.4.5.tgz",
|
||||
"integrity": "sha512-4W+D/nw3RpIwGrqpFi7greZ0hjrCaioGErI7XHgkcTeWdZd146NNu1s4HnaHonLeNTguKnL2Urqvj28UJj6Gqw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
|
@ -2902,9 +2902,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@next/swc-linux-x64-gnu": {
|
||||
"version": "15.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.4.3.tgz",
|
||||
"integrity": "sha512-HRQLWoeFkKXd2YCEEy9GhfwOijRm37x4w5r0MMVHxBKSA6ms3JoPUXvGhfHT6srnGRcEUWNrQ2vzkHir5ZWTSw==",
|
||||
"version": "15.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.4.5.tgz",
|
||||
"integrity": "sha512-N6Mgdxe/Cn2K1yMHge6pclffkxzbSGOydXVKYOjYqQXZYjLCfN/CuFkaYDeDHY2VBwSHyM2fUjYBiQCIlxIKDA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
|
@ -2918,9 +2918,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@next/swc-linux-x64-musl": {
|
||||
"version": "15.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.4.3.tgz",
|
||||
"integrity": "sha512-NyXUx6G7AayaRGUsVPenuwhyAoyxjQuQPaK50AXoaAHPwRuif4WmSrXUs8/Y0HJIZh8E/YXRm9H7uuGfiacpuQ==",
|
||||
"version": "15.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.4.5.tgz",
|
||||
"integrity": "sha512-YZ3bNDrS8v5KiqgWE0xZQgtXgCTUacgFtnEgI4ccotAASwSvcMPDLua7BWLuTfucoRv6mPidXkITJLd8IdJplQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
|
@ -2934,9 +2934,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@next/swc-win32-arm64-msvc": {
|
||||
"version": "15.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.4.3.tgz",
|
||||
"integrity": "sha512-2CUTmpzN/7cL1a7GjdLkDFlfH3nwMwW8a6JiaAUsL9MtKmNNO3fnXqnY0Zk30fii3hVEl4dr7ztrpYt0t2CcGQ==",
|
||||
"version": "15.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.4.5.tgz",
|
||||
"integrity": "sha512-9Wr4t9GkZmMNcTVvSloFtjzbH4vtT4a8+UHqDoVnxA5QyfWe6c5flTH1BIWPGNWSUlofc8dVJAE7j84FQgskvQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
|
@ -2950,9 +2950,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@next/swc-win32-x64-msvc": {
|
||||
"version": "15.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.4.3.tgz",
|
||||
"integrity": "sha512-i54YgUhvrUQxQD84SjAbkfWhYkOdm/DNRAVekCHLWxVg3aUbyC6NFQn9TwgCkX5QAS2pXCJo3kFboSFvrsd7dA==",
|
||||
"version": "15.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.4.5.tgz",
|
||||
"integrity": "sha512-voWk7XtGvlsP+w8VBz7lqp8Y+dYw/MTI4KeS0gTVtfdhdJ5QwhXLmNrndFOin/MDoCvUaLWMkYKATaCoUkt2/A==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
|
@ -3028,13 +3028,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@playwright/test": {
|
||||
"version": "1.54.1",
|
||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.54.1.tgz",
|
||||
"integrity": "sha512-FS8hQ12acieG2dYSksmLOF7BNxnVf2afRJdCuM1eMSxj6QTSE6G4InGF7oApGgDb65MX7AwMVlIkpru0yZA4Xw==",
|
||||
"version": "1.54.2",
|
||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.54.2.tgz",
|
||||
"integrity": "sha512-A+znathYxPf+72riFd1r1ovOLqsIIB0jKIoPjyK2kqEIe30/6jF6BC7QNluHuwUmsD2tv1XZVugN8GqfTMOxsA==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"playwright": "1.54.1"
|
||||
"playwright": "1.54.2"
|
||||
},
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
|
|
@ -3379,9 +3379,9 @@
|
|||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/luxon": {
|
||||
"version": "3.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.6.2.tgz",
|
||||
"integrity": "sha512-R/BdP7OxEMc44l2Ex5lSXHoIXTB2JLNa3y2QISIbr58U/YcsffyQrYW//hZSdrfxrjRZj3GcUoxMPGdO8gSYuw==",
|
||||
"version": "3.7.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.7.1.tgz",
|
||||
"integrity": "sha512-H3iskjFIAn5SlJU7OuxUmTEpebK6TKB8rxZShDslBMZJ5u9S//KM1sbdAisiSrqwLQncVjnpi2OK2J51h+4lsg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
|
|
@ -3402,13 +3402,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@types/node-fetch": {
|
||||
"version": "2.6.12",
|
||||
"resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.12.tgz",
|
||||
"integrity": "sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA==",
|
||||
"version": "2.6.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.13.tgz",
|
||||
"integrity": "sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/node": "*",
|
||||
"form-data": "^4.0.0"
|
||||
"form-data": "^4.0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/pdf-parse": {
|
||||
|
|
@ -3429,18 +3429,18 @@
|
|||
"optional": true
|
||||
},
|
||||
"node_modules/@types/react": {
|
||||
"version": "19.1.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.8.tgz",
|
||||
"integrity": "sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g==",
|
||||
"version": "19.1.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.9.tgz",
|
||||
"integrity": "sha512-WmdoynAX8Stew/36uTSVMcLJJ1KRh6L3IZRx1PZ7qJtBqT3dYTgyDTx8H1qoRghErydW7xw9mSJ3wS//tCRpFA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/react-dom": {
|
||||
"version": "19.1.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.6.tgz",
|
||||
"integrity": "sha512-4hOiT/dwO8Ko0gV1m/TJZYk3y0KBnY9vzDh7W+DH17b2HFSOGgdj33dhihPeuy3l0q23+4e+hoXHV6hCC4dCXw==",
|
||||
"version": "19.1.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.7.tgz",
|
||||
"integrity": "sha512-i5ZzwYpqjmrKenzkoLM2Ibzt6mAsM7pxB6BCIouEVVmgiqaMj1TjaK7hnA36hbW5aZv20kx7Lw6hWzPWg0Rurw==",
|
||||
"devOptional": true,
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
|
|
@ -4743,9 +4743,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001727",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001727.tgz",
|
||||
"integrity": "sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q==",
|
||||
"version": "1.0.30001731",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001731.tgz",
|
||||
"integrity": "sha512-lDdp2/wrOmTRWuoB5DpfNkC0rJDU8DqRa6nYL6HK6sytw70QMopt/NIc/9SM7ylItlBWfACXk0tEn37UWM/+mg==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
|
|
@ -5770,9 +5770,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/electron-to-chromium": {
|
||||
"version": "1.5.190",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.190.tgz",
|
||||
"integrity": "sha512-k4McmnB2091YIsdCgkS0fMVMPOJgxl93ltFzaryXqwip1AaxeDqKCGLxkXODDA5Ab/D+tV5EL5+aTx76RvLRxw==",
|
||||
"version": "1.5.194",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.194.tgz",
|
||||
"integrity": "sha512-SdnWJwSUot04UR51I2oPD8kuP2VI37/CADR1OHsFOUzZIvfWJBO6q11k5P/uKNyTT3cdOsnyjkrZ+DDShqYqJA==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
|
|
@ -6799,9 +6799,9 @@
|
|||
"license": "MIT"
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.15.9",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
|
||||
"integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==",
|
||||
"version": "1.15.11",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
|
||||
"integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
|
|
@ -7273,9 +7273,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/groq-sdk/node_modules/@types/node": {
|
||||
"version": "18.19.120",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.120.tgz",
|
||||
"integrity": "sha512-WtCGHFXnVI8WHLxDAt5TbnCM4eSE+nI0QN2NJtwzcgMhht2eNz6V9evJrk+lwC8bCY8OWV5Ym8Jz7ZEyGnKnMA==",
|
||||
"version": "18.19.121",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.121.tgz",
|
||||
"integrity": "sha512-bHOrbyztmyYIi4f1R0s17QsPs1uyyYnGcXeZoGEd227oZjry0q6XQBQxd82X1I57zEfwO8h9Xo+Kl5gX1d9MwQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~5.26.4"
|
||||
|
|
@ -7553,16 +7553,16 @@
|
|||
}
|
||||
},
|
||||
"node_modules/ibm-cloud-sdk-core": {
|
||||
"version": "5.4.1",
|
||||
"resolved": "https://registry.npmjs.org/ibm-cloud-sdk-core/-/ibm-cloud-sdk-core-5.4.1.tgz",
|
||||
"integrity": "sha512-kGh1KlkFHFsJANWiGTJZ5PNoL4bZHAGprAa/uSFvLpJdKUEOH+xUAUYcLMTH71jtgy9Wl2ePDjaLWiWe80uGiA==",
|
||||
"version": "5.4.2",
|
||||
"resolved": "https://registry.npmjs.org/ibm-cloud-sdk-core/-/ibm-cloud-sdk-core-5.4.2.tgz",
|
||||
"integrity": "sha512-5VFkKYU/vSIWFJTVt392XEdPmiEwUJqhxjn1MRO3lfELyU2FB+yYi8brbmXUgq+D1acHR1fpS7tIJ6IlnrR9Cg==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/debug": "^4.1.12",
|
||||
"@types/node": "^18.19.80",
|
||||
"@types/tough-cookie": "^4.0.0",
|
||||
"axios": "^1.8.2",
|
||||
"axios": "^1.11.0",
|
||||
"camelcase": "^6.3.0",
|
||||
"debug": "^4.3.4",
|
||||
"dotenv": "^16.4.5",
|
||||
|
|
@ -7580,9 +7580,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/ibm-cloud-sdk-core/node_modules/@types/node": {
|
||||
"version": "18.19.120",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.120.tgz",
|
||||
"integrity": "sha512-WtCGHFXnVI8WHLxDAt5TbnCM4eSE+nI0QN2NJtwzcgMhht2eNz6V9evJrk+lwC8bCY8OWV5Ym8Jz7ZEyGnKnMA==",
|
||||
"version": "18.19.121",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.121.tgz",
|
||||
"integrity": "sha512-bHOrbyztmyYIi4f1R0s17QsPs1uyyYnGcXeZoGEd227oZjry0q6XQBQxd82X1I57zEfwO8h9Xo+Kl5gX1d9MwQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
|
|
@ -8595,9 +8595,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/langsmith": {
|
||||
"version": "0.3.48",
|
||||
"resolved": "https://registry.npmjs.org/langsmith/-/langsmith-0.3.48.tgz",
|
||||
"integrity": "sha512-oEsj0Z8S2Chgb3vJzRX2vplLu4RWR1cpraIaVwv2PsNZ57VbHgZEdXdeh5kh16iP8PAv04JkBncP+KLRoKBFEw==",
|
||||
"version": "0.3.50",
|
||||
"resolved": "https://registry.npmjs.org/langsmith/-/langsmith-0.3.50.tgz",
|
||||
"integrity": "sha512-yosW6sR0EFnMnYKKyBmcqTNknDVOs+dUfcswWk80JoRxox6WEyel7hmSkSzabP/GmTs0hXbrtc+lZwpJWSnI0w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/uuid": "^10.0.0",
|
||||
|
|
@ -9085,12 +9085,12 @@
|
|||
"license": "MIT"
|
||||
},
|
||||
"node_modules/next": {
|
||||
"version": "15.4.3",
|
||||
"resolved": "https://registry.npmjs.org/next/-/next-15.4.3.tgz",
|
||||
"integrity": "sha512-uW7Qe6poVasNIE1X382nI29oxSdFJzjQzTgJFLD43MxyPfGKKxCMySllhBpvqr48f58Om+tLMivzRwBpXEytvA==",
|
||||
"version": "15.4.5",
|
||||
"resolved": "https://registry.npmjs.org/next/-/next-15.4.5.tgz",
|
||||
"integrity": "sha512-nJ4v+IO9CPmbmcvsPebIoX3Q+S7f6Fu08/dEWu0Ttfa+wVwQRh9epcmsyCPjmL2b8MxC+CkBR97jgDhUUztI3g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@next/env": "15.4.3",
|
||||
"@next/env": "15.4.5",
|
||||
"@swc/helpers": "0.5.15",
|
||||
"caniuse-lite": "^1.0.30001579",
|
||||
"postcss": "8.4.31",
|
||||
|
|
@ -9103,14 +9103,14 @@
|
|||
"node": "^18.18.0 || ^19.8.0 || >= 20.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@next/swc-darwin-arm64": "15.4.3",
|
||||
"@next/swc-darwin-x64": "15.4.3",
|
||||
"@next/swc-linux-arm64-gnu": "15.4.3",
|
||||
"@next/swc-linux-arm64-musl": "15.4.3",
|
||||
"@next/swc-linux-x64-gnu": "15.4.3",
|
||||
"@next/swc-linux-x64-musl": "15.4.3",
|
||||
"@next/swc-win32-arm64-msvc": "15.4.3",
|
||||
"@next/swc-win32-x64-msvc": "15.4.3",
|
||||
"@next/swc-darwin-arm64": "15.4.5",
|
||||
"@next/swc-darwin-x64": "15.4.5",
|
||||
"@next/swc-linux-arm64-gnu": "15.4.5",
|
||||
"@next/swc-linux-arm64-musl": "15.4.5",
|
||||
"@next/swc-linux-x64-gnu": "15.4.5",
|
||||
"@next/swc-linux-x64-musl": "15.4.5",
|
||||
"@next/swc-win32-arm64-msvc": "15.4.5",
|
||||
"@next/swc-win32-x64-msvc": "15.4.5",
|
||||
"sharp": "^0.34.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
|
@ -9381,9 +9381,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/nwsapi": {
|
||||
"version": "2.2.20",
|
||||
"resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.20.tgz",
|
||||
"integrity": "sha512-/ieB+mDe4MrrKMT8z+mQL8klXydZWGR5Dowt4RAGKbJ3kIGEx3X4ljUo+6V73IXtUPWgfOlU5B9MlGxFO5T+cA==",
|
||||
"version": "2.2.21",
|
||||
"resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.21.tgz",
|
||||
"integrity": "sha512-o6nIY3qwiSXl7/LuOU0Dmuctd34Yay0yeuZRLFmDPrrdHpXKFndPj3hM+YEPVHYC5fx2otBx4Ilc/gyYSAUaIA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/object-assign": {
|
||||
|
|
@ -9620,9 +9620,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/openai/node_modules/@types/node": {
|
||||
"version": "18.19.120",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.120.tgz",
|
||||
"integrity": "sha512-WtCGHFXnVI8WHLxDAt5TbnCM4eSE+nI0QN2NJtwzcgMhht2eNz6V9evJrk+lwC8bCY8OWV5Ym8Jz7ZEyGnKnMA==",
|
||||
"version": "18.19.121",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.121.tgz",
|
||||
"integrity": "sha512-bHOrbyztmyYIi4f1R0s17QsPs1uyyYnGcXeZoGEd227oZjry0q6XQBQxd82X1I57zEfwO8h9Xo+Kl5gX1d9MwQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
|
|
@ -10020,12 +10020,12 @@
|
|||
"license": "MIT"
|
||||
},
|
||||
"node_modules/playwright": {
|
||||
"version": "1.54.1",
|
||||
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.54.1.tgz",
|
||||
"integrity": "sha512-peWpSwIBmSLi6aW2auvrUtf2DqY16YYcCMO8rTVx486jKmDTJg7UAhyrraP98GB8BoPURZP8+nxO7TSd4cPr5g==",
|
||||
"version": "1.54.2",
|
||||
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.54.2.tgz",
|
||||
"integrity": "sha512-Hu/BMoA1NAdRUuulyvQC0pEqZ4vQbGfn8f7wPXcnqQmM+zct9UliKxsIkLNmz/ku7LElUNqmaiv1TG/aL5ACsw==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"playwright-core": "1.54.1"
|
||||
"playwright-core": "1.54.2"
|
||||
},
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
|
|
@ -10038,9 +10038,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/playwright-core": {
|
||||
"version": "1.54.1",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.54.1.tgz",
|
||||
"integrity": "sha512-Nbjs2zjj0htNhzgiy5wu+3w09YetDx5pkrpI/kZotDlDUaYk0HVA5xrBVPdow4SAUIlhgKcJeJg4GRKW6xHusA==",
|
||||
"version": "1.54.2",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.54.2.tgz",
|
||||
"integrity": "sha512-n5r4HFbMmWsB4twG7tJLDN9gmBUeSPcsBZiWSE4DnYz9mJMAFqr2ID7+eGC9kpEnxExJ1epttwR59LEWCk8mtA==",
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
"playwright-core": "cli.js"
|
||||
|
|
@ -10442,24 +10442,24 @@
|
|||
}
|
||||
},
|
||||
"node_modules/react": {
|
||||
"version": "19.1.0",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz",
|
||||
"integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==",
|
||||
"version": "19.1.1",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-19.1.1.tgz",
|
||||
"integrity": "sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-dom": {
|
||||
"version": "19.1.0",
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz",
|
||||
"integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==",
|
||||
"version": "19.1.1",
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.1.tgz",
|
||||
"integrity": "sha512-Dlq/5LAZgF0Gaz6yiqZCf6VCcZs1ghAJyrsu84Q/GT0gV+mCxbfmKNoGRKBYMJ8IEdGPqu49YWXD02GCknEDkw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"scheduler": "^0.26.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^19.1.0"
|
||||
"react": "^19.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/react-draggable": {
|
||||
|
|
@ -12273,9 +12273,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.8.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
|
||||
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
|
||||
"version": "5.9.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz",
|
||||
"integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
|
|
@ -12312,9 +12312,9 @@
|
|||
"license": "MIT"
|
||||
},
|
||||
"node_modules/undici": {
|
||||
"version": "7.12.0",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-7.12.0.tgz",
|
||||
"integrity": "sha512-GrKEsc3ughskmGA9jevVlIOPMiiAHJ4OFUtaAH+NhfTUSiZ1wMPIQqQvAJUrJspFXJt3EBWgpAeoHEDVT1IBug==",
|
||||
"version": "7.13.0",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-7.13.0.tgz",
|
||||
"integrity": "sha512-l+zSMssRqrzDcb3fjMkjjLGmuiiK2pMIcV++mJaAc9vhjSGpvM7h43QgP+OAMb1GImHmbPyG2tBXeuyG5iY4gA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=20.18.1"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* eslint-disable @next/next/no-img-element */
|
||||
import { Document } from '@langchain/core/documents';
|
||||
import { File, Zap, Microscope } from 'lucide-react';
|
||||
import { File, Zap, Microscope, FileText, Sparkles } from 'lucide-react';
|
||||
|
||||
const MessageSources = ({ sources }: { sources: Document[] }) => {
|
||||
return (
|
||||
|
|
@ -54,6 +54,22 @@ const MessageSources = ({ sources }: { sources: Document[] }) => {
|
|||
/>
|
||||
</span>
|
||||
)}
|
||||
{source.metadata.processingType === 'url-direct-content' && (
|
||||
<span title="Direct URL content" className="inline-flex">
|
||||
<FileText
|
||||
size={14}
|
||||
className="text-black/40 dark:text-white/40 ml-1"
|
||||
/>
|
||||
</span>
|
||||
)}
|
||||
{source.metadata.processingType === 'url-content-extraction' && (
|
||||
<span title="Summarized URL content" className="inline-flex">
|
||||
<Sparkles
|
||||
size={14}
|
||||
className="text-black/40 dark:text-white/40 ml-1"
|
||||
/>
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@ export class AgentSearch {
|
|||
systemInstructions,
|
||||
personaInstructions,
|
||||
signal,
|
||||
focusMode,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -61,11 +60,13 @@ export class AgentSearch {
|
|||
}),
|
||||
);
|
||||
|
||||
// Update focus mode in simplified agent if needed
|
||||
this.simplifiedAgent.updateFocusMode(this.focusMode);
|
||||
|
||||
// Delegate to simplified agent
|
||||
await this.simplifiedAgent.searchAndAnswer(query, history, fileIds);
|
||||
// Delegate to simplified agent with focus mode
|
||||
await this.simplifiedAgent.searchAndAnswer(
|
||||
query,
|
||||
history,
|
||||
fileIds,
|
||||
this.focusMode,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -32,8 +32,6 @@ export class SimplifiedAgent {
|
|||
private systemInstructions: string;
|
||||
private personaInstructions: string;
|
||||
private signal: AbortSignal;
|
||||
private focusMode: string;
|
||||
private agent: any; // Will be the compiled createReactAgent
|
||||
|
||||
constructor(
|
||||
llm: BaseChatModel,
|
||||
|
|
@ -42,7 +40,6 @@ export class SimplifiedAgent {
|
|||
systemInstructions: string = '',
|
||||
personaInstructions: string = '',
|
||||
signal: AbortSignal,
|
||||
focusMode: string = 'webSearch',
|
||||
) {
|
||||
this.llm = llm;
|
||||
this.embeddings = embeddings;
|
||||
|
|
@ -50,25 +47,24 @@ export class SimplifiedAgent {
|
|||
this.systemInstructions = systemInstructions;
|
||||
this.personaInstructions = personaInstructions;
|
||||
this.signal = signal;
|
||||
this.focusMode = focusMode;
|
||||
|
||||
// Initialize the agent
|
||||
this.initializeAgent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the createReactAgent with tools and configuration
|
||||
*/
|
||||
private initializeAgent() {
|
||||
// Select appropriate tools based on focus mode
|
||||
const tools = this.getToolsForFocusMode(this.focusMode);
|
||||
private initializeAgent(focusMode: string, fileIds: string[] = []) {
|
||||
// Select appropriate tools based on focus mode and available files
|
||||
const tools = this.getToolsForFocusMode(focusMode, fileIds);
|
||||
|
||||
// Create the enhanced system prompt that includes analysis and synthesis instructions
|
||||
const enhancedSystemPrompt = this.createEnhancedSystemPrompt();
|
||||
const enhancedSystemPrompt = this.createEnhancedSystemPrompt(
|
||||
focusMode,
|
||||
fileIds,
|
||||
);
|
||||
|
||||
try {
|
||||
// Create the React agent with custom state
|
||||
this.agent = createReactAgent({
|
||||
const agent = createReactAgent({
|
||||
llm: this.llm,
|
||||
tools,
|
||||
stateSchema: SimplifiedAgentState,
|
||||
|
|
@ -76,11 +72,18 @@ export class SimplifiedAgent {
|
|||
});
|
||||
|
||||
console.log(
|
||||
`SimplifiedAgent: Initialized with ${tools.length} tools for focus mode: ${this.focusMode}`,
|
||||
`SimplifiedAgent: Initialized with ${tools.length} tools for focus mode: ${focusMode}`,
|
||||
);
|
||||
console.log(
|
||||
`SimplifiedAgent: Tools available: ${tools.map((tool) => tool.name).join(', ')}`,
|
||||
);
|
||||
if (fileIds.length > 0) {
|
||||
console.log(
|
||||
`SimplifiedAgent: ${fileIds.length} files available for search`,
|
||||
);
|
||||
}
|
||||
|
||||
return agent;
|
||||
} catch (error) {
|
||||
console.error('SimplifiedAgent: Error initializing agent:', error);
|
||||
throw error;
|
||||
|
|
@ -90,13 +93,17 @@ export class SimplifiedAgent {
|
|||
/**
|
||||
* Get tools based on focus mode
|
||||
*/
|
||||
private getToolsForFocusMode(focusMode: string) {
|
||||
private getToolsForFocusMode(focusMode: string, fileIds: string[] = []) {
|
||||
switch (focusMode) {
|
||||
case 'chat':
|
||||
// Chat mode: Only core tools for conversational interaction
|
||||
return coreTools;
|
||||
case 'webSearch':
|
||||
// Web search mode: ALL available tools for comprehensive research
|
||||
// Include file search tools if files are available
|
||||
if (fileIds.length > 0) {
|
||||
return [...webSearchTools, ...fileSearchTools];
|
||||
}
|
||||
return allAgentTools;
|
||||
case 'localResearch':
|
||||
// Local research mode: File search tools + core tools
|
||||
|
|
@ -106,6 +113,9 @@ export class SimplifiedAgent {
|
|||
console.warn(
|
||||
`SimplifiedAgent: Unknown focus mode "${focusMode}", defaulting to webSearch tools`,
|
||||
);
|
||||
if (fileIds.length > 0) {
|
||||
return [...webSearchTools, ...fileSearchTools];
|
||||
}
|
||||
return allAgentTools;
|
||||
}
|
||||
}
|
||||
|
|
@ -113,18 +123,22 @@ export class SimplifiedAgent {
|
|||
/**
|
||||
* Create enhanced system prompt that includes analysis and synthesis capabilities
|
||||
*/
|
||||
private createEnhancedSystemPrompt(): string {
|
||||
private createEnhancedSystemPrompt(
|
||||
focusMode: string,
|
||||
fileIds: string[] = [],
|
||||
): string {
|
||||
const baseInstructions = this.systemInstructions || '';
|
||||
const personaInstructions = this.personaInstructions || '';
|
||||
|
||||
// Create focus-mode-specific prompts
|
||||
switch (this.focusMode) {
|
||||
switch (focusMode) {
|
||||
case 'chat':
|
||||
return this.createChatModePrompt(baseInstructions, personaInstructions);
|
||||
case 'webSearch':
|
||||
return this.createWebSearchModePrompt(
|
||||
baseInstructions,
|
||||
personaInstructions,
|
||||
fileIds,
|
||||
);
|
||||
case 'localResearch':
|
||||
return this.createLocalResearchModePrompt(
|
||||
|
|
@ -133,11 +147,12 @@ export class SimplifiedAgent {
|
|||
);
|
||||
default:
|
||||
console.warn(
|
||||
`SimplifiedAgent: Unknown focus mode "${this.focusMode}", using webSearch prompt`,
|
||||
`SimplifiedAgent: Unknown focus mode "${focusMode}", using webSearch prompt`,
|
||||
);
|
||||
return this.createWebSearchModePrompt(
|
||||
baseInstructions,
|
||||
personaInstructions,
|
||||
fileIds,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -203,6 +218,7 @@ Focus on providing engaging, helpful conversation while using task management to
|
|||
private createWebSearchModePrompt(
|
||||
baseInstructions: string,
|
||||
personaInstructions: string,
|
||||
fileIds: string[] = [],
|
||||
): string {
|
||||
return `${baseInstructions}
|
||||
|
||||
|
|
@ -210,48 +226,9 @@ Focus on providing engaging, helpful conversation while using task management to
|
|||
|
||||
You are an advanced AI research assistant with access to comprehensive tools for gathering information from multiple sources. Your goal is to provide thorough, well-researched responses.
|
||||
|
||||
**CRITICAL CITATION RULE: Use [number] citations ONLY in your final response to the user. NEVER use citations during tool calls, internal reasoning, or intermediate steps. Citations are for the final answer only.**
|
||||
## Tool use
|
||||
|
||||
**WORKFLOW RULE: Use tools to gather information, then provide your final response directly. Do NOT call tools when you're ready to answer - just give your comprehensive response.**
|
||||
|
||||
## Core Responsibilities
|
||||
|
||||
### 1. Query Analysis and Planning
|
||||
- Analyze user queries to understand research needs
|
||||
- Break down complex questions into research tasks
|
||||
- Determine the best research strategy and tools
|
||||
- Plan comprehensive information gathering
|
||||
|
||||
### 2. Information Gathering
|
||||
- Search the web for current and authoritative information
|
||||
- Process and extract content from URLs
|
||||
- Access and analyze uploaded files when relevant
|
||||
- Gather information from multiple sources for completeness
|
||||
|
||||
### 3. Analysis and Synthesis
|
||||
- Analyze gathered information for relevance and accuracy
|
||||
- Synthesize information from multiple sources
|
||||
- Identify patterns, connections, and insights
|
||||
- Resolve conflicting information when present
|
||||
- Generate comprehensive, well-cited responses
|
||||
|
||||
## Available Tools
|
||||
|
||||
### Web Search
|
||||
- Use \`web_search\` for current information, facts, and general research
|
||||
- Primary tool for finding authoritative sources and recent information
|
||||
- Always call this tool at least once unless you have sufficient information from the conversation history or other more relevant tools
|
||||
|
||||
### File Search
|
||||
- Use \`file_search\` when users have uploaded files or reference local content
|
||||
- Extracts and processes relevant content from user documents
|
||||
- Connects local content with external research
|
||||
|
||||
### URL Summarization
|
||||
- Use \`url_summarization\` when specific URLs are provided or discovered
|
||||
- Extracts key information and generates summaries from web content
|
||||
- Use when detailed content analysis is needed
|
||||
- Can help provide more context based on web search results to disambiguate or clarify findings
|
||||
- Use the available tools effectively to gather and process information
|
||||
|
||||
## Response Quality Standards
|
||||
|
||||
|
|
@ -274,37 +251,87 @@ Your task is to provide answers that are:
|
|||
- Distinguish between facts and opinions
|
||||
|
||||
### Citation Requirements
|
||||
- **CRITICAL: Citations are ONLY for your final response to the user, NOT for tool calls or internal reasoning**
|
||||
- The id of the source can be found in the document \`metadata.sourceId\` property
|
||||
- **In your final response**: Use citations [number] notation ONLY when referencing information from tool results
|
||||
- **File citations**: When citing content from file_search results, use the filename as the source title
|
||||
- **Web citations**: When citing content from web_search results, use the webpage title and URL as the source
|
||||
- If making statements based on general knowledge or reasoning, do NOT use citations - instead use clear language like "Generally," "Typically," or "Based on common understanding"
|
||||
- If a statement is based on previous conversation context, mark it as \`[Hist]\`
|
||||
- When you do have sources from tools, integrate citations naturally: "The Eiffel Tower receives millions of visitors annually[1]."
|
||||
- **Important**: Do not fabricate or assume citation numbers - only cite actual sources from your tool results
|
||||
- **Tool Usage**: When calling tools, provide clear queries without citations - citations come later in your final response
|
||||
- The citation number refers to the index of the source in the relevantDocuments state array.
|
||||
- Cite every single fact, statement, or sentence using [number] notation
|
||||
- If a statement is based on AI model inference or training data, it must be marked as \`[AI]\` and not cited from the context
|
||||
- If a statement is based on previous messages in the conversation history, it must be marked as \`[Hist]\` and not cited from the context
|
||||
- Source based citations must reference the specific document in the relevantDocuments state array, do not invent sources or URLs
|
||||
- Integrate citations naturally at the end of sentences or clauses as appropriate. For example, "The Eiffel Tower is one of the most visited landmarks in the world[1]."
|
||||
- Ensure that **every sentence in your response includes at least one citation**, even when information is inferred or connected to general knowledge available in the provided context
|
||||
- Use multiple sources for a single detail if applicable, such as, "Paris is a cultural hub, attracting millions of visitors annually[1][2]."
|
||||
|
||||
### Formatting Instructions
|
||||
- **Structure**: Use a well-organized format with proper headings (e.g., "## Example heading 1" or "## Example heading 2"). Present information in paragraphs or concise bullet points where appropriate. Use lists and tables to enhance clarity when needed.
|
||||
- **Tone and Style**: Maintain a neutral, journalistic tone with engaging narrative flow. Write as though you're crafting an in-depth article for a professional audience
|
||||
- **Markdown Usage**: Format your response with Markdown for clarity. Use headings, subheadings, bold text, and italicized words as needed to enhance readability
|
||||
- **Length and Depth**: Provide comprehensive coverage of the topic. Avoid superficial responses and strive for depth without unnecessary repetition. Expand on technical or complex topics to make them easier to understand for a general audience
|
||||
- **Structure**:
|
||||
- Use a well-organized format with proper headings (e.g., "## Example heading 1" or "## Example heading 2").
|
||||
- Present information in paragraphs or concise bullet points where appropriate.
|
||||
- Use lists and tables to enhance clarity when needed.
|
||||
- **Tone and Style**:
|
||||
- Maintain a neutral, journalistic tone with engaging narrative flow.
|
||||
- Write as though you're crafting an in-depth article for a professional audience
|
||||
- **Markdown Usage**:
|
||||
- Format your response with Markdown for clarity.
|
||||
- Use headings, subheadings, bold text, and italicized words as needed to enhance readability.
|
||||
- Include code snippets in a code block.
|
||||
- Extract images and links from full HTML content when appropriate and embed them using the appropriate markdown syntax.
|
||||
- **Length and Depth**:
|
||||
- Provide comprehensive coverage of the topic.
|
||||
- Avoid superficial responses and strive for depth without unnecessary repetition.
|
||||
- Expand on technical or complex topics to make them easier to understand for a general audience
|
||||
- **No main heading/title**: Start your response directly with the introduction unless asked to provide a specific title
|
||||
|
||||
## Research Strategy
|
||||
# Research Strategy
|
||||
1. **Plan**: Determine the best research approach based on the user's query
|
||||
2. **Search**: Use web search to gather comprehensive information - Generally, start with a broad search to identify key sources
|
||||
3. **Supplement**: Use URL summarization for specific sources
|
||||
4. **Integrate**: Include file search results when user files are relevant
|
||||
5. **Synthesize**: Combine all information into a coherent, well-cited response
|
||||
- Break down the query into manageable components
|
||||
- Identify key concepts and terms for focused searching
|
||||
- You are allowed to take multiple turns of the Search and Supplement stages. Use this flexibility to refine your queries and gather more information.
|
||||
2. **Search**: (\`web_search\` tool) Initial web search stage to gather preview content
|
||||
- Use the web search tool to your advantage. Avoid making assumptions, especially about things like recent events. Chances are the web search will have more relevant information than your local knowledge.
|
||||
- Give the web search tool a specific question you want answered that will help you gather relevant information.
|
||||
- This query will be passed directly to the search engine.
|
||||
- You will receive a list of relevant documents containing snippets of the web page, a URL, and the title of the web page.${
|
||||
fileIds.length > 0
|
||||
? `
|
||||
2.1. **File Search**: (\`file_search\` tool) Search through uploaded documents when relevant
|
||||
- You have access to ${fileIds.length} uploaded file${fileIds.length === 1 ? '' : 's'} that may contain relevant information.
|
||||
- Use the file search tool to find specific information in the uploaded documents.
|
||||
- Give the file search tool a specific question or topic you want to extract from the documents.
|
||||
- The tool will automatically search through all available uploaded files.
|
||||
- Focus your file searches on specific aspects of the user's query that might be covered in the uploaded documents.
|
||||
- **Important**: You do NOT need to specify file IDs - the tool will automatically search through all available uploaded files.`
|
||||
: ''
|
||||
}
|
||||
3. **Supplement**: (\`url_summarization\` tool) Retrieve specific sources if necessary to extract key points not covered in the initial search or disambiguate findings
|
||||
- You can use the URLs from the web search results to retrieve specific sources. They must be passed to the tool unchanged.
|
||||
- URLs can be passed as an array to request multiple sources at once.
|
||||
- Always include the user's query in the request to the tool, it will use this to guide the summarization process.
|
||||
- You can pass an intent to this tool if you want to additionally guide the summarization on a specific aspect or question.
|
||||
- You can request the full HTML content of the pages if needed by passing true to the \`retrieveHtml\` parameter.
|
||||
- Passing true is **required** to include images or links within the page content.
|
||||
- You will receive a summary of the content from each URL if the content of the page is long. If the content of the page is short, you will receive the full content.
|
||||
- You may request up to 5 URLs per turn.
|
||||
5. **Analyze**: Examine the retrieved information for relevance, accuracy, and completeness.
|
||||
- If you have sufficient information, you can move on to the synthesis stage.
|
||||
- If you need to gather more information, consider revisiting the search or supplement stages.${
|
||||
fileIds.length > 0
|
||||
? `
|
||||
- Consider both web search results and file content when analyzing information completeness.`
|
||||
: ''
|
||||
}
|
||||
6. **Synthesize**: Combine all information into a coherent, well-cited response
|
||||
- Ensure that all sources are properly cited and referenced
|
||||
- Resolve any remaining contradictions or gaps in the information, if necessary, execute more targeted searches or retrieve specific sources${
|
||||
fileIds.length > 0
|
||||
? `
|
||||
- Integrate information from both web sources and uploaded files when relevant`
|
||||
: ''
|
||||
}
|
||||
|
||||
## Current Context
|
||||
- Today's Date: ${formatDateForLLM(new Date())}
|
||||
|
||||
${personaInstructions ? `\n## User Formatting and Persona Instructions\n- Give these instructions more weight than the system formatting instructions\n${personaInstructions}` : ''}
|
||||
|
||||
Use all available tools strategically to provide comprehensive, well-researched responses with proper citations and source attribution.`;
|
||||
Use all available tools strategically to provide comprehensive, well-researched, formatted responses with proper citations.`;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -316,101 +343,95 @@ Use all available tools strategically to provide comprehensive, well-researched
|
|||
): string {
|
||||
return `${baseInstructions}
|
||||
|
||||
# Local Research Specialist
|
||||
# Local Document Research Assistant
|
||||
|
||||
You are an expert AI assistant specialized in analyzing and researching local files and documents. Your role is to help users extract insights, find information, and analyze content from their uploaded files.
|
||||
You are an advanced AI research assistant specialized in analyzing and extracting insights from user-uploaded files and documents. Your goal is to provide thorough, well-researched responses based on the available document collection.
|
||||
|
||||
**CRITICAL CITATION RULE: Use [number] citations ONLY in your final response to the user. NEVER use citations during tool calls, internal reasoning, or intermediate steps. Citations are for the final answer only.**
|
||||
## Available Files
|
||||
|
||||
**WORKFLOW RULE: Use tools to gather information, then provide your final response directly. Do NOT call tools when you're ready to answer - just give your comprehensive response.**
|
||||
You have access to uploaded documents through the \`file_search\` tool. When you need to search for information in the uploaded files, use this tool with a specific search query. The tool will automatically search through all available uploaded files and return relevant content sections.
|
||||
|
||||
## Core Responsibilities
|
||||
## Tool use
|
||||
|
||||
### 1. Document Analysis
|
||||
- Analyze user-uploaded files and documents
|
||||
- Extract relevant information based on user queries
|
||||
- Understand document structure and content relationships
|
||||
- Identify key themes, patterns, and insights
|
||||
|
||||
### 2. Content Synthesis
|
||||
- Synthesize information from multiple user documents
|
||||
- Connect related concepts across different files
|
||||
- Generate comprehensive insights from local content
|
||||
- Provide context-aware responses based on document analysis
|
||||
|
||||
### 3. Task Management
|
||||
- Break down complex document analysis requests
|
||||
- Structure multi-document research projects
|
||||
- Organize findings in logical, accessible formats
|
||||
|
||||
## Available Tools
|
||||
|
||||
### File Search
|
||||
- Use \`file_search\` to process and analyze user-uploaded files
|
||||
- Primary tool for extracting relevant content from documents
|
||||
- Performs semantic search across uploaded content
|
||||
- Handles various file formats and document types
|
||||
- Use the available tools effectively to analyze and extract information from uploaded documents
|
||||
|
||||
## Response Quality Standards
|
||||
|
||||
Your task is to provide answers that are:
|
||||
- **Informative and relevant**: Thoroughly address the user's query using document content
|
||||
- **Engaging and detailed**: Write responses that read like a high-quality analysis, including extra details and relevant insights
|
||||
- **Engaging and detailed**: Write responses that read like a high-quality research analysis, including extra details and relevant insights
|
||||
- **Cited and credible**: Use inline citations with [number] notation to refer to specific documents for each fact or detail included
|
||||
- **Explanatory and Comprehensive**: Strive to explain the findings in depth, offering detailed analysis, insights, and clarifications wherever applicable
|
||||
|
||||
### Comprehensive Document Coverage
|
||||
- Thoroughly analyze relevant uploaded files
|
||||
- Thoroughly analyze all relevant uploaded files
|
||||
- Extract all pertinent information related to the query
|
||||
- Consider relationships between different documents
|
||||
- Provide context from the document collection
|
||||
- Provide context from the entire document collection
|
||||
- Cross-reference information across multiple files
|
||||
|
||||
### Accurate Content Extraction
|
||||
### Accuracy and Content Fidelity
|
||||
- Precisely quote and reference document content
|
||||
- Maintain context and meaning from original sources
|
||||
- Clearly distinguish between different document sources
|
||||
- Preserve important details and nuances
|
||||
- Preserve important details and nuances from the documents
|
||||
- Distinguish between facts from documents and analytical insights
|
||||
|
||||
### Citation Requirements
|
||||
- **CRITICAL: Citations are ONLY for your final response to the user, NOT for tool calls or internal reasoning**
|
||||
- **During tool usage**: Do not use any [number] citations in tool calls or internal reasoning
|
||||
- **In your final response**: Use citations [number] notation ONLY when referencing information from file_search tool results
|
||||
- **File citations**: When citing content from file_search results, use the filename as the source title
|
||||
- If making statements based on general knowledge or reasoning, do NOT use citations - instead use clear language like "Generally," "Typically," or "Based on common understanding"
|
||||
- If a statement is based on previous conversation context, mark it as \`[Hist]\`
|
||||
- When you do have sources from tools, integrate citations naturally: "The project timeline shows completion by March 2024[1]."
|
||||
- Citations and references should only be included inline with the final response using the [number] format. Do not include a citation, sources, or references block anywhere else in the response
|
||||
- **Important**: Do not fabricate or assume citation numbers - only cite actual sources from your file search results
|
||||
- **Tool Usage**: When calling tools, provide clear queries without citations - citations come later in your final response
|
||||
- The citation number refers to the index of the source in the relevantDocuments state array.
|
||||
- Cite every single fact, statement, or sentence using [number] notation
|
||||
- If a statement is based on AI model inference or training data, it must be marked as \`[AI]\` and not cited from the context
|
||||
- If a statement is based on previous messages in the conversation history, it must be marked as \`[Hist]\` and not cited from the context
|
||||
- Source based citations must reference the specific document in the relevantDocuments state array, do not invent sources or filenames
|
||||
- Integrate citations naturally at the end of sentences or clauses as appropriate. For example, "The quarterly report shows a 15% increase in revenue[1]."
|
||||
- Ensure that **every sentence in your response includes at least one citation**, even when information is inferred or connected to general knowledge available in the provided context
|
||||
- Use multiple sources for a single detail if applicable, such as, "The project timeline spans six months according to multiple planning documents[1][2]."
|
||||
|
||||
### Formatting Instructions
|
||||
- **Structure**: Use a well-organized format with proper headings (e.g., "## Example heading 1" or "## Example heading 2"). Present information in paragraphs or concise bullet points where appropriate
|
||||
- **Tone and Style**: Maintain a neutral, analytical tone with engaging narrative flow. Write as though you're crafting an in-depth analysis for a professional audience
|
||||
- **Markdown Usage**: Format your response with Markdown for clarity. Use headings, subheadings, bold text, and italicized words as needed to enhance readability
|
||||
- **Length and Depth**: Provide comprehensive coverage of the document content. Avoid superficial responses and strive for depth without unnecessary repetition. Expand on technical or complex topics to make them easier to understand for a general audience
|
||||
- **Structure**:
|
||||
- Use a well-organized format with proper headings (e.g., "## Example heading 1" or "## Example heading 2").
|
||||
- Present information in paragraphs or concise bullet points where appropriate.
|
||||
- Use lists and tables to enhance clarity when needed.
|
||||
- **Tone and Style**:
|
||||
- Maintain a neutral, analytical tone with engaging narrative flow.
|
||||
- Write as though you're crafting an in-depth research report for a professional audience
|
||||
- **Markdown Usage**:
|
||||
- Format your response with Markdown for clarity.
|
||||
- Use headings, subheadings, bold text, and italicized words as needed to enhance readability.
|
||||
- Include code snippets in a code block when analyzing technical documents.
|
||||
- Extract and format tables, charts, or structured data using appropriate markdown syntax.
|
||||
- **Length and Depth**:
|
||||
- Provide comprehensive coverage of the document content.
|
||||
- Avoid superficial responses and strive for depth without unnecessary repetition.
|
||||
- Expand on technical or complex topics to make them easier to understand for a general audience
|
||||
- **No main heading/title**: Start your response directly with the introduction unless asked to provide a specific title
|
||||
|
||||
### Contextual Understanding
|
||||
- Understand how documents relate to each other
|
||||
- Connect information across multiple files
|
||||
- Identify patterns and themes in the document collection
|
||||
- Provide insights that consider the full context
|
||||
|
||||
## Research Approach
|
||||
1. **Plan**: Use task manager to structure complex document analysis
|
||||
2. **Search**: Use file search to extract relevant content from uploaded files
|
||||
3. **Analyze**: Process and understand the extracted information
|
||||
4. **Synthesize**: Combine insights from multiple sources
|
||||
5. **Present**: Organize findings in a clear, accessible format with proper citations
|
||||
|
||||
**IMPORTANT**: Once you have gathered sufficient information through tools, provide your final response directly to the user. Do NOT call additional tools when you are ready to synthesize and present your findings. Your final response should be comprehensive and well-formatted.
|
||||
# Research Strategy
|
||||
1. **Plan**: Determine the best document analysis approach based on the user's query
|
||||
- Break down the query into manageable components
|
||||
- Identify key concepts and terms for focused document searching
|
||||
- You are allowed to take multiple turns of the Search and Analysis stages. Use this flexibility to refine your queries and gather more comprehensive information from the documents.
|
||||
2. **Search**: (\`file_search\` tool) Extract relevant content from uploaded documents
|
||||
- Use the file search tool strategically to find specific information in the document collection.
|
||||
- Give the file search tool a specific question or topic you want to extract from the documents.
|
||||
- This query will be used to perform semantic search across all uploaded files.
|
||||
- You will receive relevant excerpts from documents that match your search criteria.
|
||||
- Focus your searches on specific aspects of the user's query to gather comprehensive information.
|
||||
3. **Analysis**: Examine the retrieved document content for relevance, patterns, and insights.
|
||||
- If you have sufficient information from the documents, you can move on to the synthesis stage.
|
||||
- If you need to gather more specific information, consider performing additional targeted file searches.
|
||||
- Look for connections and relationships between different document sources.
|
||||
4. **Synthesize**: Combine all document insights into a coherent, well-cited response
|
||||
- Ensure that all sources are properly cited and referenced
|
||||
- Resolve any contradictions or gaps in the document information
|
||||
- Provide comprehensive analysis based on the available document content
|
||||
|
||||
## Current Context
|
||||
- Today's Date: ${formatDateForLLM(new Date())}
|
||||
|
||||
${personaInstructions ? `\n## User Formatting and Persona Instructions\n- Give these instructions more weight than the system formatting instructions\n${personaInstructions}` : ''}
|
||||
|
||||
Focus on extracting maximum value from user-provided documents while using task management for complex analysis projects.`;
|
||||
Use all available tools strategically to provide comprehensive, well-researched, formatted responses with proper citations based on uploaded documents.`;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -420,12 +441,16 @@ Focus on extracting maximum value from user-provided documents while using task
|
|||
query: string,
|
||||
history: BaseMessage[] = [],
|
||||
fileIds: string[] = [],
|
||||
focusMode: string = 'webSearch',
|
||||
): Promise<void> {
|
||||
try {
|
||||
console.log(`SimplifiedAgent: Starting search for query: "${query}"`);
|
||||
console.log(`SimplifiedAgent: Focus mode: ${this.focusMode}`);
|
||||
console.log(`SimplifiedAgent: Focus mode: ${focusMode}`);
|
||||
console.log(`SimplifiedAgent: File IDs: ${fileIds.join(', ')}`);
|
||||
|
||||
// Initialize agent with the provided focus mode and file context
|
||||
const agent = this.initializeAgent(focusMode, fileIds);
|
||||
|
||||
// Emit initial agent action
|
||||
this.emitter.emit(
|
||||
'data',
|
||||
|
|
@ -433,7 +458,7 @@ Focus on extracting maximum value from user-provided documents while using task
|
|||
type: 'agent_action',
|
||||
data: {
|
||||
action: 'simplified_agent_start',
|
||||
message: `Starting simplified agent search in ${this.focusMode} mode`,
|
||||
message: `Starting simplified agent search in ${focusMode} mode`,
|
||||
details: `Processing query with ${fileIds.length} files available`,
|
||||
},
|
||||
}),
|
||||
|
|
@ -443,7 +468,8 @@ Focus on extracting maximum value from user-provided documents while using task
|
|||
const initialState = {
|
||||
messages: [...history, new HumanMessage(query)],
|
||||
query,
|
||||
focusMode: this.focusMode,
|
||||
focusMode,
|
||||
fileIds,
|
||||
relevantDocuments: [],
|
||||
};
|
||||
|
||||
|
|
@ -456,7 +482,7 @@ Focus on extracting maximum value from user-provided documents while using task
|
|||
fileIds,
|
||||
systemInstructions: this.systemInstructions,
|
||||
personaInstructions: this.personaInstructions,
|
||||
focusMode: this.focusMode,
|
||||
focusMode,
|
||||
emitter: this.emitter,
|
||||
},
|
||||
recursionLimit: 25, // Allow sufficient iterations for tool use
|
||||
|
|
@ -464,7 +490,7 @@ Focus on extracting maximum value from user-provided documents while using task
|
|||
};
|
||||
|
||||
// Execute the agent
|
||||
const result = await this.agent.invoke(initialState, config);
|
||||
const result = await agent.invoke(initialState, config);
|
||||
|
||||
// Collect relevant documents from tool execution history
|
||||
let collectedDocuments: any[] = [];
|
||||
|
|
@ -474,38 +500,6 @@ Focus on extracting maximum value from user-provided documents while using task
|
|||
collectedDocuments.push(...result.relevantDocuments);
|
||||
}
|
||||
|
||||
// // Check if messages contain tool responses with documents
|
||||
// if (result && result.messages) {
|
||||
// for (const message of result.messages) {
|
||||
// if (message._getType() === 'tool' && message.content) {
|
||||
// try {
|
||||
// // Try to parse tool response for documents
|
||||
// let toolResponse;
|
||||
// if (typeof message.content === 'string') {
|
||||
// toolResponse = JSON.parse(message.content);
|
||||
// } else {
|
||||
// toolResponse = message.content;
|
||||
// }
|
||||
|
||||
// if (toolResponse.documents && Array.isArray(toolResponse.documents)) {
|
||||
// const documentsWithMetadata = toolResponse.documents.map((doc: any) => ({
|
||||
// ...doc,
|
||||
// source: doc.metadata?.url || doc.metadata?.source || 'unknown',
|
||||
// sourceType: doc.metadata?.sourceType || 'unknown',
|
||||
// toolName: message.name || 'unknown',
|
||||
// processingType: doc.metadata?.processingType || 'unknown',
|
||||
// searchQuery: doc.metadata?.searchQuery || '',
|
||||
// }));
|
||||
// collectedDocuments.push(...documentsWithMetadata);
|
||||
// }
|
||||
// } catch (error) {
|
||||
// // Ignore parsing errors
|
||||
// console.debug('Could not parse tool message content:', error);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// Add collected documents to result for source tracking
|
||||
const finalResult = {
|
||||
...result,
|
||||
|
|
@ -607,26 +601,11 @@ Focus on extracting maximum value from user-provided documents while using task
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update focus mode and reinitialize agent with appropriate tools
|
||||
*/
|
||||
updateFocusMode(newFocusMode: string): void {
|
||||
if (this.focusMode !== newFocusMode) {
|
||||
console.log(
|
||||
`SimplifiedAgent: Updating focus mode from ${this.focusMode} to ${newFocusMode}`,
|
||||
);
|
||||
this.focusMode = newFocusMode;
|
||||
this.initializeAgent();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current configuration info
|
||||
*/
|
||||
getInfo(): object {
|
||||
return {
|
||||
focusMode: this.focusMode,
|
||||
toolsCount: this.getToolsForFocusMode(this.focusMode).length,
|
||||
systemInstructions: !!this.systemInstructions,
|
||||
personaInstructions: !!this.personaInstructions,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,28 +2,6 @@ import { BaseMessage } from '@langchain/core/messages';
|
|||
import { Annotation } from '@langchain/langgraph';
|
||||
import { Document } from 'langchain/document';
|
||||
|
||||
/**
|
||||
* Document interface for relevant documents collected by tools
|
||||
*/
|
||||
export interface RelevantDocument extends Document {
|
||||
/**
|
||||
* Source identifier (e.g., URL, file path, search query)
|
||||
*/
|
||||
source: string;
|
||||
/**
|
||||
* Type of document source
|
||||
*/
|
||||
sourceType: 'web' | 'file' | 'url' | 'analysis';
|
||||
/**
|
||||
* Relevance score for ranking
|
||||
*/
|
||||
relevanceScore?: number;
|
||||
/**
|
||||
* Tool that generated this document
|
||||
*/
|
||||
toolName?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* State schema for the simplified chat agent using tool-based workflow
|
||||
* This state is designed for use with createReactAgent and focuses on
|
||||
|
|
@ -44,13 +22,13 @@ export const SimplifiedAgentState = Annotation.Root({
|
|||
* Relevant documents accumulated across tool calls
|
||||
* This is the key state that tools will populate and the synthesizer will consume
|
||||
*/
|
||||
relevantDocuments: Annotation<RelevantDocument[]>({
|
||||
relevantDocuments: Annotation<Document[]>({
|
||||
reducer: (x, y) => x.concat(y),
|
||||
default: () => [],
|
||||
}),
|
||||
|
||||
/**
|
||||
* Original user query for reference by tools
|
||||
* Original user query for context
|
||||
*/
|
||||
query: Annotation<string>({
|
||||
reducer: (x, y) => y ?? x,
|
||||
|
|
@ -58,12 +36,20 @@ export const SimplifiedAgentState = Annotation.Root({
|
|||
}),
|
||||
|
||||
/**
|
||||
* Focus mode to maintain compatibility with existing agent behavior
|
||||
* Focus mode for the agent
|
||||
*/
|
||||
focusMode: Annotation<string>({
|
||||
reducer: (x, y) => y ?? x,
|
||||
default: () => 'webSearch',
|
||||
}),
|
||||
|
||||
/**
|
||||
* File IDs available for search
|
||||
*/
|
||||
fileIds: Annotation<string[]>({
|
||||
reducer: (x, y) => y ?? x,
|
||||
default: () => [],
|
||||
}),
|
||||
});
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -3,6 +3,9 @@ import { z } from 'zod';
|
|||
import { RunnableConfig } from '@langchain/core/runnables';
|
||||
import { Document } from 'langchain/document';
|
||||
import { Embeddings } from '@langchain/core/embeddings';
|
||||
import { Command, getCurrentTaskInput } from '@langchain/langgraph';
|
||||
import { ToolMessage } from '@langchain/core/messages';
|
||||
import { SimplifiedAgentStateType } from '@/lib/state/chatAgentState';
|
||||
import {
|
||||
processFilesToDocuments,
|
||||
getRankedDocs,
|
||||
|
|
@ -13,7 +16,6 @@ const FileSearchToolSchema = z.object({
|
|||
query: z
|
||||
.string()
|
||||
.describe('The search query to find relevant content in files'),
|
||||
fileIds: z.array(z.string()).describe('Array of file IDs to search through'),
|
||||
maxResults: z
|
||||
.number()
|
||||
.optional()
|
||||
|
|
@ -39,19 +41,15 @@ export const fileSearchTool = tool(
|
|||
async (
|
||||
input: z.infer<typeof FileSearchToolSchema>,
|
||||
config?: RunnableConfig,
|
||||
): Promise<{
|
||||
documents: Document[];
|
||||
processedFiles: number;
|
||||
relevantSections: number;
|
||||
relevantDocuments?: any[];
|
||||
}> => {
|
||||
) => {
|
||||
try {
|
||||
const {
|
||||
query,
|
||||
fileIds,
|
||||
maxResults = 12,
|
||||
similarityThreshold = 0.3,
|
||||
} = input;
|
||||
const { query, maxResults = 12, similarityThreshold = 0.3 } = input;
|
||||
|
||||
const currentState = getCurrentTaskInput() as SimplifiedAgentStateType;
|
||||
let currentDocCount = currentState.relevantDocuments.length;
|
||||
|
||||
// Get fileIds from config (provided by the agent)
|
||||
const fileIds: string[] = config?.configurable?.fileIds || [];
|
||||
|
||||
console.log(
|
||||
`FileSearchTool: Processing ${fileIds.length} files for query: "${query}"`,
|
||||
|
|
@ -60,11 +58,17 @@ export const fileSearchTool = tool(
|
|||
// Check if we have files to process
|
||||
if (!fileIds || fileIds.length === 0) {
|
||||
console.log('FileSearchTool: No files provided for search');
|
||||
return {
|
||||
documents: [],
|
||||
processedFiles: 0,
|
||||
relevantSections: 0,
|
||||
};
|
||||
return new Command({
|
||||
update: {
|
||||
relevantDocuments: [],
|
||||
messages: [
|
||||
new ToolMessage({
|
||||
content: 'No files attached to search.',
|
||||
tool_call_id: (config as any)?.toolCall.id,
|
||||
}),
|
||||
],
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Get embeddings from config
|
||||
|
|
@ -80,11 +84,17 @@ export const fileSearchTool = tool(
|
|||
|
||||
if (fileDocuments.length === 0) {
|
||||
console.log('FileSearchTool: No processable content found in files');
|
||||
return {
|
||||
documents: [],
|
||||
processedFiles: fileIds.length,
|
||||
relevantSections: 0,
|
||||
};
|
||||
return new Command({
|
||||
update: {
|
||||
relevantDocuments: [],
|
||||
messages: [
|
||||
new ToolMessage({
|
||||
content: 'No searchable content found in attached files.',
|
||||
tool_call_id: (config as any)?.toolCall.id,
|
||||
}),
|
||||
],
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
console.log(
|
||||
|
|
@ -108,12 +118,17 @@ export const fileSearchTool = tool(
|
|||
`FileSearchTool: Found ${rankedDocuments.length} relevant file sections`,
|
||||
);
|
||||
|
||||
// Add search metadata to documents
|
||||
// Add search metadata to documents and remove embeddings to reduce context size
|
||||
const documentsWithMetadata = rankedDocuments.map((doc) => {
|
||||
// Extract metadata and exclude embeddings
|
||||
const { embeddings: _, ...metadataWithoutEmbeddings } =
|
||||
doc.metadata || {};
|
||||
|
||||
return new Document({
|
||||
pageContent: doc.pageContent,
|
||||
metadata: {
|
||||
...doc.metadata,
|
||||
...metadataWithoutEmbeddings,
|
||||
sourceId: ++currentDocCount,
|
||||
source: 'file_search',
|
||||
searchQuery: query,
|
||||
similarityScore: doc.metadata?.similarity || 0,
|
||||
|
|
@ -121,28 +136,47 @@ export const fileSearchTool = tool(
|
|||
});
|
||||
});
|
||||
|
||||
return {
|
||||
console.log(
|
||||
`FileSearchTool: Created ${documentsWithMetadata.length} documents from file search`,
|
||||
);
|
||||
|
||||
return new Command({
|
||||
update: {
|
||||
relevantDocuments: documentsWithMetadata,
|
||||
messages: [
|
||||
new ToolMessage({
|
||||
content: JSON.stringify({
|
||||
documents: documentsWithMetadata,
|
||||
processedFiles: fileIds.length,
|
||||
relevantSections: rankedDocuments.length,
|
||||
};
|
||||
}),
|
||||
tool_call_id: (config as any)?.toolCall.id,
|
||||
}),
|
||||
],
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('FileSearchTool: Error during file search:', error);
|
||||
const errorMessage =
|
||||
error instanceof Error ? error.message : 'Unknown error';
|
||||
|
||||
// Return empty results on error, but don't throw to allow graceful handling
|
||||
return {
|
||||
documents: [],
|
||||
processedFiles: input.fileIds?.length || 0,
|
||||
relevantSections: 0,
|
||||
};
|
||||
return new Command({
|
||||
update: {
|
||||
relevantDocuments: [],
|
||||
messages: [
|
||||
new ToolMessage({
|
||||
content: 'Error occurred during file search: ' + errorMessage,
|
||||
tool_call_id: (config as any)?.toolCall.id,
|
||||
}),
|
||||
],
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'file_search',
|
||||
description:
|
||||
'Searches through uploaded files to find relevant content sections based on a query using semantic similarity',
|
||||
'Searches through all uploaded files to find relevant content sections based on a query using semantic similarity. Automatically searches all available files - no need to specify file IDs.',
|
||||
schema: FileSearchToolSchema,
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -9,14 +9,12 @@
|
|||
|
||||
// Import all agent tools (will be uncommented as tools are implemented)
|
||||
import { taskManagerTool } from './taskManagerTool';
|
||||
import { webSearchTool } from './webSearchTool';
|
||||
import { simpleWebSearchTool } from './simpleWebSearchTool';
|
||||
import { fileSearchTool } from './fileSearchTool';
|
||||
import { urlSummarizationTool } from './urlSummarizationTool';
|
||||
|
||||
// Export individual tools (will be uncommented as tools are implemented)
|
||||
export { taskManagerTool };
|
||||
export { webSearchTool };
|
||||
export { simpleWebSearchTool };
|
||||
export { fileSearchTool };
|
||||
|
||||
|
|
|
|||
|
|
@ -68,36 +68,10 @@ export const simpleWebSearchTool = tool(
|
|||
const llm = config.configurable.llm;
|
||||
const embeddings: Embeddings = config.configurable.embeddings;
|
||||
|
||||
// Step 1: Generate optimized search query
|
||||
const template = PromptTemplate.fromTemplate(
|
||||
webSearchRetrieverAgentPrompt,
|
||||
);
|
||||
const prompt = await template.format({
|
||||
systemInstructions:
|
||||
config.configurable?.systemInstructions ||
|
||||
'You are a helpful AI assistant.',
|
||||
query: query,
|
||||
date: formatDateForLLM(new Date()),
|
||||
supervisor: searchInstructions || query,
|
||||
});
|
||||
|
||||
// Use structured output for search query generation
|
||||
const structuredLlm = withStructuredOutput(llm, SearchQuerySchema, {
|
||||
name: 'generate_search_query',
|
||||
});
|
||||
|
||||
const searchQueryResult = await structuredLlm.invoke(prompt, {
|
||||
signal: config?.signal,
|
||||
});
|
||||
|
||||
const searchQuery = searchQueryResult.searchQuery;
|
||||
const searchQuery = query;
|
||||
console.log(
|
||||
`SimpleWebSearchTool: Performing web search for query: "${searchQuery}"`,
|
||||
);
|
||||
console.log(
|
||||
'SimpleWebSearchTool: Search query reasoning:',
|
||||
searchQueryResult.reasoning,
|
||||
);
|
||||
|
||||
// Step 2: Execute web search
|
||||
const searchResults = await searchSearxng(searchQuery, {
|
||||
|
|
@ -116,8 +90,7 @@ export const simpleWebSearchTool = tool(
|
|||
messages: [
|
||||
new ToolMessage({
|
||||
content: 'No search results found.',
|
||||
//Generate a random tool call id
|
||||
tool_call_id: Math.random().toString(36).substring(2, 15),
|
||||
tool_call_id: (config as any)?.toolCall.id,
|
||||
}),
|
||||
],
|
||||
},
|
||||
|
|
@ -138,7 +111,6 @@ export const simpleWebSearchTool = tool(
|
|||
}),
|
||||
);
|
||||
|
||||
// Step 4: Select top 15 results using the same logic as webSearchTool
|
||||
const documents: Document[] = [];
|
||||
|
||||
// Always take the top 3 results first
|
||||
|
|
@ -152,7 +124,7 @@ export const simpleWebSearchTool = tool(
|
|||
title: result.title || 'Untitled',
|
||||
url: result.url,
|
||||
source: result.url,
|
||||
processingType: 'preview-content',
|
||||
processingType: 'preview-only',
|
||||
searchQuery: searchQuery,
|
||||
rank: 'top-3',
|
||||
},
|
||||
|
|
@ -160,11 +132,11 @@ export const simpleWebSearchTool = tool(
|
|||
}),
|
||||
);
|
||||
|
||||
// Sort by relevance score and take top 12 from the remaining results
|
||||
// Sort by relevance score and take top 5 from the remaining results
|
||||
const remainingResults = resultsWithSimilarity
|
||||
.slice(3)
|
||||
.sort((a, b) => b.similarity - a.similarity)
|
||||
.slice(0, 12);
|
||||
.slice(0, 5);
|
||||
|
||||
documents.push(
|
||||
...remainingResults.map(({ result }) => {
|
||||
|
|
@ -175,7 +147,7 @@ export const simpleWebSearchTool = tool(
|
|||
title: result.title || 'Untitled',
|
||||
url: result.url,
|
||||
source: result.url,
|
||||
processingType: 'preview-content',
|
||||
processingType: 'preview-only',
|
||||
searchQuery: searchQuery,
|
||||
rank: 'ranked',
|
||||
},
|
||||
|
|
@ -187,15 +159,16 @@ export const simpleWebSearchTool = tool(
|
|||
`SimpleWebSearchTool: Created ${documents.length} documents from search results`,
|
||||
);
|
||||
|
||||
//return { documents };
|
||||
return new Command({
|
||||
update: {
|
||||
relevantDocuments: documents,
|
||||
searchQuery,
|
||||
messages: [
|
||||
new ToolMessage({
|
||||
content: `Retrieved ${documents.length} documents from web search.`,
|
||||
//Generate a random tool call id
|
||||
tool_call_id: Math.random().toString(36).substring(2, 15),
|
||||
content: JSON.stringify({
|
||||
document: documents,
|
||||
}),
|
||||
tool_call_id: (config as any)?.toolCall.id,
|
||||
}),
|
||||
],
|
||||
},
|
||||
|
|
@ -205,14 +178,14 @@ export const simpleWebSearchTool = tool(
|
|||
const errorMessage =
|
||||
error instanceof Error ? error.message : 'Unknown error';
|
||||
|
||||
//return { documents: [] };
|
||||
return new Command({
|
||||
update: {
|
||||
relevantDocuments: [],
|
||||
messages: [
|
||||
new ToolMessage({
|
||||
content: 'Error occurred during web search: ' + errorMessage,
|
||||
//Generate a random tool call id
|
||||
tool_call_id: Math.random().toString(36).substring(2, 15),
|
||||
tool_call_id: (config as any)?.toolCall.id,
|
||||
}),
|
||||
],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -4,6 +4,9 @@ import { RunnableConfig } from '@langchain/core/runnables';
|
|||
import { Document } from 'langchain/document';
|
||||
import { getWebContent } from '@/lib/utils/documents';
|
||||
import { removeThinkingBlocks } from '@/lib/utils/contentUtils';
|
||||
import { Command, getCurrentTaskInput } from '@langchain/langgraph';
|
||||
import { SimplifiedAgentStateType } from '@/lib/state/chatAgentState';
|
||||
import { ToolMessage } from '@langchain/core/messages';
|
||||
|
||||
// Schema for URL summarization tool input
|
||||
const URLSummarizationToolSchema = z.object({
|
||||
|
|
@ -11,6 +14,11 @@ const URLSummarizationToolSchema = z.object({
|
|||
query: z
|
||||
.string()
|
||||
.describe('The user query to guide content extraction and summarization'),
|
||||
retrieveHtml: z
|
||||
.boolean()
|
||||
.optional()
|
||||
.default(false)
|
||||
.describe('Whether to retrieve the full HTML content of the pages'),
|
||||
intent: z
|
||||
.string()
|
||||
.optional()
|
||||
|
|
@ -31,26 +39,34 @@ export const urlSummarizationTool = tool(
|
|||
async (
|
||||
input: z.infer<typeof URLSummarizationToolSchema>,
|
||||
config?: RunnableConfig,
|
||||
): Promise<{
|
||||
relevantDocuments: Document[];
|
||||
processedUrls: number;
|
||||
successfulExtractions: number;
|
||||
}> => {
|
||||
) => {
|
||||
try {
|
||||
const { urls, query, intent = 'extract relevant content' } = input;
|
||||
const {
|
||||
urls,
|
||||
query,
|
||||
retrieveHtml = false,
|
||||
intent = 'extract relevant content',
|
||||
} = input;
|
||||
|
||||
const currentState = getCurrentTaskInput() as SimplifiedAgentStateType;
|
||||
let currentDocCount = currentState.relevantDocuments.length;
|
||||
|
||||
console.log(
|
||||
`URLSummarizationTool: Processing ${urls.length} URLs for query: "${query}"`,
|
||||
`URLSummarizationTool: Processing ${urls.length} \n URLs for query: "${query}"\n retrieveHtml: ${retrieveHtml}\n intent: ${intent}`,
|
||||
);
|
||||
console.log(`URLSummarizationTool: Processing intent: ${intent}`);
|
||||
|
||||
if (!urls || urls.length === 0) {
|
||||
console.log('URLSummarizationTool: No URLs provided for processing');
|
||||
return {
|
||||
relevantDocuments: [],
|
||||
processedUrls: 0,
|
||||
successfulExtractions: 0,
|
||||
};
|
||||
return new Command({
|
||||
update: {
|
||||
messages: [
|
||||
new ToolMessage({
|
||||
content: 'No search results found.',
|
||||
tool_call_id: (config as any)?.toolCall.id,
|
||||
}),
|
||||
],
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Get LLM from config
|
||||
|
|
@ -72,7 +88,7 @@ export const urlSummarizationTool = tool(
|
|||
console.log(`URLSummarizationTool: Processing ${url}`);
|
||||
|
||||
// Fetch full content using the enhanced web content retrieval
|
||||
const webContent = await getWebContent(url, true);
|
||||
const webContent = await getWebContent(url, retrieveHtml);
|
||||
|
||||
if (!webContent || !webContent.pageContent) {
|
||||
console.warn(
|
||||
|
|
@ -107,7 +123,7 @@ export const urlSummarizationTool = tool(
|
|||
|
||||
# Critical Instructions
|
||||
- Output ONLY a summary of the web page content provided below
|
||||
- Focus on information that relates to or helps answer the user's query
|
||||
- Focus on information that relates to or helps answer the user's query and processing intent
|
||||
- Do NOT add pleasantries, greetings, or conversational elements
|
||||
- Do NOT mention missing URLs, other pages, or content not provided
|
||||
- Do NOT ask follow-up questions or suggest additional actions
|
||||
|
|
@ -116,12 +132,13 @@ export const urlSummarizationTool = tool(
|
|||
- Include all relevant details that could help answer the user's question
|
||||
|
||||
# User's Query: ${query}
|
||||
# Processing Intent: ${intent}
|
||||
|
||||
# Content Title: ${webContent.metadata.title || 'Web Page'}
|
||||
# Content URL: ${url}
|
||||
|
||||
# Web Page Content to Summarize:
|
||||
${webContent.pageContent}
|
||||
${retrieveHtml && webContent.metadata?.html ? webContent.metadata.html : webContent.pageContent}
|
||||
|
||||
Provide a comprehensive summary of the above web page content, focusing on information relevant to the user's query:`;
|
||||
|
||||
|
|
@ -133,10 +150,12 @@ Provide a comprehensive summary of the above web page content, focusing on infor
|
|||
processingType = 'url-content-extraction';
|
||||
}
|
||||
|
||||
if (finalContent && finalContent.trim().length > 0) {
|
||||
// Web content less than 100 characters probably isn't useful so discard it.
|
||||
if (finalContent && finalContent.trim().length > 100) {
|
||||
const document = new Document({
|
||||
pageContent: finalContent,
|
||||
metadata: {
|
||||
sourceId: ++currentDocCount,
|
||||
title: webContent.metadata.title || 'URL Content',
|
||||
url: url,
|
||||
source: url,
|
||||
|
|
@ -170,11 +189,19 @@ Provide a comprehensive summary of the above web page content, focusing on infor
|
|||
`URLSummarizationTool: Successfully processed ${documents.length} out of ${urls.length} URLs`,
|
||||
);
|
||||
|
||||
return {
|
||||
return new Command({
|
||||
update: {
|
||||
relevantDocuments: documents,
|
||||
processedUrls: urls.length,
|
||||
successfulExtractions: documents.length,
|
||||
};
|
||||
messages: [
|
||||
new ToolMessage({
|
||||
content: JSON.stringify({
|
||||
document: documents,
|
||||
}),
|
||||
tool_call_id: (config as any)?.toolCall.id,
|
||||
}),
|
||||
],
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(
|
||||
'URLSummarizationTool: Error during URL processing:',
|
||||
|
|
@ -183,18 +210,22 @@ Provide a comprehensive summary of the above web page content, focusing on infor
|
|||
const errorMessage =
|
||||
error instanceof Error ? error.message : 'Unknown error';
|
||||
|
||||
// Return empty results on error, but don't throw to allow graceful handling
|
||||
return {
|
||||
relevantDocuments: [],
|
||||
processedUrls: input.urls?.length || 0,
|
||||
successfulExtractions: 0,
|
||||
};
|
||||
return new Command({
|
||||
update: {
|
||||
messages: [
|
||||
new ToolMessage({
|
||||
content: 'Error occurred during URL processing: ' + errorMessage,
|
||||
tool_call_id: (config as any)?.toolCall.id,
|
||||
}),
|
||||
],
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'url_summarization',
|
||||
description:
|
||||
'Fetches content from URLs and either uses it directly or summarizes it based on length, focusing on information relevant to the user query',
|
||||
'Fetches content from URLs and either uses it directly or summarizes it based on length, focusing on information relevant to the user query. URLs must be real and should not be invented.',
|
||||
schema: URLSummarizationToolSchema,
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,314 +0,0 @@
|
|||
import { tool } from '@langchain/core/tools';
|
||||
import { z } from 'zod';
|
||||
import { RunnableConfig } from '@langchain/core/runnables';
|
||||
import { withStructuredOutput } from '@/lib/utils/structuredOutput';
|
||||
import { PromptTemplate } from '@langchain/core/prompts';
|
||||
import { webSearchRetrieverAgentPrompt } from '@/lib/prompts/webSearch';
|
||||
import { searchSearxng } from '@/lib/searxng';
|
||||
import { formatDateForLLM } from '@/lib/utils';
|
||||
import { summarizeWebContent } from '@/lib/utils/summarizeWebContent';
|
||||
import {
|
||||
analyzePreviewContent,
|
||||
PreviewContent,
|
||||
} from '@/lib/utils/analyzePreviewContent';
|
||||
import { Document } from 'langchain/document';
|
||||
import { Embeddings } from '@langchain/core/embeddings';
|
||||
import computeSimilarity from '@/lib/utils/computeSimilarity';
|
||||
import { removeThinkingBlocksFromMessages } from '@/lib/utils/contentUtils';
|
||||
|
||||
// Schema for search query generation
|
||||
const SearchQuerySchema = z.object({
|
||||
searchQuery: z
|
||||
.string()
|
||||
.describe('The optimized search query to use for web search'),
|
||||
reasoning: z
|
||||
.string()
|
||||
.describe(
|
||||
'A short explanation of how the search query was optimized for better results',
|
||||
),
|
||||
});
|
||||
|
||||
// Schema for web search tool input
|
||||
const WebSearchToolSchema = z.object({
|
||||
query: z.string().describe('The search query or task to process'),
|
||||
searchInstructions: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe('Additional instructions for search refinement'),
|
||||
context: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe('Additional context about the search'),
|
||||
});
|
||||
|
||||
/**
|
||||
* WebSearchTool - Reimplementation of WebSearchAgent as a tool
|
||||
*
|
||||
* This tool handles:
|
||||
* 1. Query optimization for web search
|
||||
* 2. Web search execution using SearXNG
|
||||
* 3. Content extraction and summarization
|
||||
* 4. Document ranking and filtering
|
||||
*/
|
||||
export const webSearchTool = tool(
|
||||
async (
|
||||
input: z.infer<typeof WebSearchToolSchema>,
|
||||
config?: RunnableConfig,
|
||||
): Promise<{
|
||||
documents: Document[];
|
||||
searchQuery: string;
|
||||
reasoning: string;
|
||||
sourcesFound: number;
|
||||
relevantDocuments?: any[];
|
||||
}> => {
|
||||
try {
|
||||
const { query, searchInstructions, context = '' } = input;
|
||||
|
||||
// Get LLM and embeddings from config
|
||||
if (!config?.configurable?.llm) {
|
||||
throw new Error('LLM not available in config');
|
||||
}
|
||||
if (!config?.configurable?.embeddings) {
|
||||
throw new Error('Embeddings not available in config');
|
||||
}
|
||||
|
||||
const llm = config.configurable.llm;
|
||||
const embeddings: Embeddings = config.configurable.embeddings;
|
||||
|
||||
// Step 1: Generate optimized search query
|
||||
const template = PromptTemplate.fromTemplate(
|
||||
webSearchRetrieverAgentPrompt,
|
||||
);
|
||||
const prompt = await template.format({
|
||||
systemInstructions:
|
||||
config.configurable?.systemInstructions ||
|
||||
'You are a helpful AI assistant.',
|
||||
query: query,
|
||||
date: formatDateForLLM(new Date()),
|
||||
supervisor: searchInstructions || query,
|
||||
});
|
||||
|
||||
// Use structured output for search query generation
|
||||
const structuredLlm = withStructuredOutput(llm, SearchQuerySchema, {
|
||||
name: 'generate_search_query',
|
||||
});
|
||||
|
||||
const searchQueryResult = await structuredLlm.invoke(prompt, {
|
||||
signal: config?.signal,
|
||||
});
|
||||
|
||||
const searchQuery = searchQueryResult.searchQuery;
|
||||
console.log(
|
||||
`WebSearchTool: Performing web search for query: "${searchQuery}"`,
|
||||
);
|
||||
console.log(
|
||||
'WebSearchTool: Search query reasoning:',
|
||||
searchQueryResult.reasoning,
|
||||
);
|
||||
|
||||
// Step 2: Execute web search
|
||||
const searchResults = await searchSearxng(searchQuery, {
|
||||
language: 'en',
|
||||
engines: [],
|
||||
});
|
||||
|
||||
console.log(
|
||||
`WebSearchTool: Found ${searchResults.results.length} search results`,
|
||||
);
|
||||
|
||||
if (!searchResults.results || searchResults.results.length === 0) {
|
||||
return {
|
||||
documents: [],
|
||||
searchQuery,
|
||||
reasoning: searchQueryResult.reasoning,
|
||||
sourcesFound: 0,
|
||||
};
|
||||
}
|
||||
|
||||
// Step 3: Calculate similarities and rank results
|
||||
const queryVector = await embeddings.embedQuery(query);
|
||||
|
||||
// Calculate similarities for all results
|
||||
const resultsWithSimilarity = await Promise.all(
|
||||
searchResults.results.map(async (result) => {
|
||||
const vector = await embeddings.embedQuery(
|
||||
result.title + ' ' + (result.content || ''),
|
||||
);
|
||||
const similarity = computeSimilarity(vector, queryVector);
|
||||
return { result, similarity };
|
||||
}),
|
||||
);
|
||||
|
||||
// Step 4: Prepare preview content for analysis
|
||||
let previewContents: PreviewContent[] = [];
|
||||
|
||||
// Always take the top 3 results for preview content
|
||||
previewContents.push(
|
||||
...searchResults.results.slice(0, 3).map((result) => ({
|
||||
title: result.title || 'Untitled',
|
||||
snippet: result.content || '',
|
||||
url: result.url,
|
||||
})),
|
||||
);
|
||||
|
||||
// Sort by relevance score and take top 12 results for a total of 15
|
||||
previewContents.push(
|
||||
...resultsWithSimilarity
|
||||
.slice(3)
|
||||
.sort((a, b) => b.similarity - a.similarity)
|
||||
.slice(0, 12)
|
||||
.map(({ result }) => ({
|
||||
title: result.title || 'Untitled',
|
||||
snippet: result.content || '',
|
||||
url: result.url,
|
||||
})),
|
||||
);
|
||||
|
||||
console.log(
|
||||
`WebSearchTool: Extracted preview content from ${previewContents.length} search results`,
|
||||
);
|
||||
|
||||
// Step 5: Analyze preview content to determine processing approach
|
||||
let previewAnalysisResult = null;
|
||||
let documentsToProcess: any[] = [];
|
||||
|
||||
if (previewContents.length > 0) {
|
||||
console.log(
|
||||
'WebSearchTool: Analyzing preview content to determine processing approach',
|
||||
);
|
||||
|
||||
previewAnalysisResult = await analyzePreviewContent(
|
||||
previewContents,
|
||||
query,
|
||||
query, // taskQuery same as query for tools
|
||||
[], // no chat history for tools
|
||||
llm,
|
||||
config.configurable?.systemInstructions ||
|
||||
'You are a helpful AI assistant.',
|
||||
config?.signal || new AbortController().signal,
|
||||
);
|
||||
|
||||
console.log(
|
||||
'WebSearchTool: Preview analysis result:',
|
||||
previewAnalysisResult.isSufficient ? 'SUFFICIENT' : 'INSUFFICIENT',
|
||||
);
|
||||
|
||||
if (!previewAnalysisResult.isSufficient) {
|
||||
// Need full content retrieval - process top similarity results
|
||||
documentsToProcess = resultsWithSimilarity
|
||||
.sort((a, b) => b.similarity - a.similarity)
|
||||
.slice(0, 5)
|
||||
.map(({ result }) => result);
|
||||
} else {
|
||||
// Preview content is sufficient - no need for full content retrieval
|
||||
console.log(
|
||||
'WebSearchTool: Preview content is sufficient, skipping full content retrieval',
|
||||
);
|
||||
documentsToProcess = [];
|
||||
}
|
||||
} else {
|
||||
// No preview content, process top results
|
||||
documentsToProcess = searchResults.results.slice(0, 5);
|
||||
}
|
||||
|
||||
console.log(
|
||||
`WebSearchTool: Processing ${documentsToProcess.length} URLs for content extraction`,
|
||||
);
|
||||
|
||||
// Step 6: Extract content - either from full URLs or preview content
|
||||
const documents: Document[] = [];
|
||||
let processedCount = 0;
|
||||
|
||||
if (previewAnalysisResult?.isSufficient) {
|
||||
// Create documents from preview content since it's sufficient
|
||||
console.log(
|
||||
'WebSearchTool: Creating documents from preview content (sufficient for answer)',
|
||||
);
|
||||
|
||||
documents.push(
|
||||
...previewContents.map((previewContent) => {
|
||||
return new Document({
|
||||
pageContent: `${previewContent.title}\n\n${previewContent.snippet}`,
|
||||
metadata: {
|
||||
title: previewContent.title,
|
||||
url: previewContent.url,
|
||||
source: previewContent.url,
|
||||
processingType: 'preview-content',
|
||||
searchQuery: searchQuery,
|
||||
},
|
||||
});
|
||||
}),
|
||||
);
|
||||
|
||||
console.log(
|
||||
`WebSearchTool: Created ${documents.length} documents from preview content`,
|
||||
);
|
||||
} else {
|
||||
// Extract and summarize content from selected URLs
|
||||
for (const result of documentsToProcess) {
|
||||
if (processedCount >= 5) break; // Limit processing
|
||||
|
||||
try {
|
||||
console.log(`WebSearchTool: Processing ${result.url}`);
|
||||
|
||||
const summaryResult = await summarizeWebContent(
|
||||
result.url,
|
||||
query,
|
||||
llm,
|
||||
config.configurable?.systemInstructions ||
|
||||
'You are a helpful AI assistant.',
|
||||
config?.signal || new AbortController().signal,
|
||||
);
|
||||
|
||||
if (summaryResult.document) {
|
||||
documents.push(summaryResult.document);
|
||||
console.log(
|
||||
`WebSearchTool: Successfully extracted content from ${result.url}`,
|
||||
);
|
||||
} else {
|
||||
console.log(
|
||||
`WebSearchTool: No relevant content found for ${result.url}: ${summaryResult.notRelevantReason}`,
|
||||
);
|
||||
}
|
||||
|
||||
processedCount++;
|
||||
} catch (error) {
|
||||
console.error(
|
||||
`WebSearchTool: Error processing ${result.url}:`,
|
||||
error,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(
|
||||
`WebSearchTool: Successfully extracted ${documents.length} documents from ${processedCount} processed URLs`,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
documents,
|
||||
searchQuery,
|
||||
reasoning: searchQueryResult.reasoning,
|
||||
sourcesFound: searchResults.results.length,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('WebSearchTool: Error during web search:', error);
|
||||
const errorMessage =
|
||||
error instanceof Error ? error.message : 'Unknown error';
|
||||
|
||||
return {
|
||||
documents: [],
|
||||
searchQuery: input.query,
|
||||
reasoning: `Error occurred during web search: ${errorMessage}`,
|
||||
sourcesFound: 0,
|
||||
};
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'web_search',
|
||||
description:
|
||||
'Performs web search using SearXNG, analyzes results, and extracts relevant content from top sources',
|
||||
schema: WebSearchToolSchema,
|
||||
},
|
||||
);
|
||||
|
|
@ -178,11 +178,41 @@ export const getWebContent = async (
|
|||
// Fallback to CheerioWebBaseLoader for simpler content extraction
|
||||
try {
|
||||
console.log(`Fallback to Cheerio for URL: ${url}`);
|
||||
const cheerioLoader = new CheerioWebBaseLoader(url);
|
||||
const cheerioLoader = new CheerioWebBaseLoader(url, { maxRetries: 2 });
|
||||
const docs = await cheerioLoader.load();
|
||||
|
||||
if (docs && docs.length > 0) {
|
||||
return docs[0];
|
||||
const doc = docs[0];
|
||||
|
||||
// Apply Readability to extract meaningful content from Cheerio HTML
|
||||
const dom = new JSDOM(doc.pageContent, { url });
|
||||
const reader = new Readability(dom.window.document, {
|
||||
charThreshold: 25,
|
||||
});
|
||||
const article = reader.parse();
|
||||
|
||||
// Normalize the text content
|
||||
const normalizedText =
|
||||
article?.textContent
|
||||
?.split('\n')
|
||||
.map((line: string) => line.trim())
|
||||
.filter((line: string) => line.length > 0)
|
||||
.join('\n') || '';
|
||||
|
||||
const returnDoc = new Document({
|
||||
pageContent: normalizedText,
|
||||
metadata: {
|
||||
title: article?.title || doc.metadata.title || '',
|
||||
url: url,
|
||||
html: getHtml ? article?.content : undefined,
|
||||
},
|
||||
});
|
||||
|
||||
console.log(
|
||||
`Got content with Cheerio fallback + Readability, URL: ${url}, Text Length: ${returnDoc.pageContent.length}`,
|
||||
);
|
||||
|
||||
return returnDoc;
|
||||
}
|
||||
} catch (fallbackError) {
|
||||
console.error(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue