@inkeep/agents-manage-ui 0.6.5 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (178) hide show
  1. package/.next/standalone/agents-manage-ui/.next/BUILD_ID +1 -1
  2. package/.next/standalone/agents-manage-ui/.next/app-build-manifest.json +124 -124
  3. package/.next/standalone/agents-manage-ui/.next/app-path-routes-manifest.json +6 -6
  4. package/.next/standalone/agents-manage-ui/.next/build-manifest.json +2 -2
  5. package/.next/standalone/agents-manage-ui/.next/prerender-manifest.json +3 -3
  6. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/page.js +1 -1
  7. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/page_client-reference-manifest.js +1 -1
  8. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/api-keys/page.js +3 -3
  9. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/api-keys/page_client-reference-manifest.js +1 -1
  10. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/artifact-components/[artifactComponentId]/page.js +1 -1
  11. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/artifact-components/[artifactComponentId]/page.js.nft.json +1 -1
  12. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/artifact-components/[artifactComponentId]/page_client-reference-manifest.js +1 -1
  13. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/artifact-components/new/page.js +2 -2
  14. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/artifact-components/new/page.js.nft.json +1 -1
  15. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/artifact-components/new/page_client-reference-manifest.js +1 -1
  16. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/artifact-components/page.js +2 -2
  17. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/artifact-components/page_client-reference-manifest.js +1 -1
  18. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/credentials/[credentialId]/page.js +1 -1
  19. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/credentials/[credentialId]/page.js.nft.json +1 -1
  20. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/credentials/[credentialId]/page_client-reference-manifest.js +1 -1
  21. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/credentials/new/bearer/page.js +2 -2
  22. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/credentials/new/bearer/page.js.nft.json +1 -1
  23. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/credentials/new/bearer/page_client-reference-manifest.js +1 -1
  24. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/credentials/new/page.js +1 -1
  25. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/credentials/new/page_client-reference-manifest.js +1 -1
  26. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/credentials/new/providers/[providerId]/page.js +1 -1
  27. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/credentials/new/providers/[providerId]/page.js.nft.json +1 -1
  28. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/credentials/new/providers/[providerId]/page_client-reference-manifest.js +1 -1
  29. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/credentials/new/providers/page.js +2 -2
  30. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/credentials/new/providers/page.js.nft.json +1 -1
  31. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/credentials/new/providers/page_client-reference-manifest.js +1 -1
  32. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/credentials/page.js +2 -2
  33. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/credentials/page_client-reference-manifest.js +1 -1
  34. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/data-components/[dataComponentId]/page.js +2 -2
  35. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/data-components/[dataComponentId]/page.js.nft.json +1 -1
  36. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/data-components/[dataComponentId]/page_client-reference-manifest.js +1 -1
  37. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/data-components/new/page.js +2 -2
  38. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/data-components/new/page.js.nft.json +1 -1
  39. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/data-components/new/page_client-reference-manifest.js +1 -1
  40. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/data-components/page.js +2 -2
  41. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/data-components/page_client-reference-manifest.js +1 -1
  42. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/graphs/[graphId]/page.js +2 -2
  43. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/graphs/[graphId]/page.js.nft.json +1 -1
  44. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/graphs/[graphId]/page_client-reference-manifest.js +1 -1
  45. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/graphs/new/page.js +2 -2
  46. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/graphs/new/page.js.nft.json +1 -1
  47. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/graphs/new/page_client-reference-manifest.js +1 -1
  48. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/graphs/page.js +2 -2
  49. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/graphs/page_client-reference-manifest.js +1 -1
  50. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/mcp-servers/[mcpServerId]/edit/page.js +2 -2
  51. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/mcp-servers/[mcpServerId]/edit/page.js.nft.json +1 -1
  52. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/mcp-servers/[mcpServerId]/edit/page_client-reference-manifest.js +1 -1
  53. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/mcp-servers/[mcpServerId]/page.js +2 -2
  54. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/mcp-servers/[mcpServerId]/page.js.nft.json +1 -1
  55. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/mcp-servers/[mcpServerId]/page_client-reference-manifest.js +1 -1
  56. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/mcp-servers/new/page.js +1 -1
  57. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/mcp-servers/new/page.js.nft.json +1 -1
  58. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/mcp-servers/new/page_client-reference-manifest.js +1 -1
  59. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/mcp-servers/page.js +2 -2
  60. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/mcp-servers/page.js.nft.json +1 -1
  61. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/mcp-servers/page_client-reference-manifest.js +1 -1
  62. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/page.js +2 -2
  63. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/page_client-reference-manifest.js +1 -1
  64. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/settings/page.js +2 -2
  65. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/settings/page_client-reference-manifest.js +1 -1
  66. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/traces/ai-calls/page.js +2 -2
  67. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/traces/ai-calls/page.js.nft.json +1 -1
  68. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/traces/ai-calls/page_client-reference-manifest.js +1 -1
  69. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/traces/conversations/[conversationId]/page.js +2 -2
  70. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/traces/conversations/[conversationId]/page_client-reference-manifest.js +1 -1
  71. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/traces/page.js +2 -2
  72. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/traces/page.js.nft.json +1 -1
  73. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/[projectId]/traces/page_client-reference-manifest.js +1 -1
  74. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/page.js +1 -1
  75. package/.next/standalone/agents-manage-ui/.next/server/app/[tenantId]/projects/page_client-reference-manifest.js +1 -1
  76. package/.next/standalone/agents-manage-ui/.next/server/app/_not-found/page.js +1 -1
  77. package/.next/standalone/agents-manage-ui/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  78. package/.next/standalone/agents-manage-ui/.next/server/app/_not-found.html +1 -1
  79. package/.next/standalone/agents-manage-ui/.next/server/app/_not-found.rsc +9 -9
  80. package/.next/standalone/agents-manage-ui/.next/server/app/api/signoz/conversations/[conversationId]/route_client-reference-manifest.js +1 -1
  81. package/.next/standalone/agents-manage-ui/.next/server/app/api/signoz/route_client-reference-manifest.js +1 -1
  82. package/.next/standalone/agents-manage-ui/.next/server/app/page.js +2 -2
  83. package/.next/standalone/agents-manage-ui/.next/server/app/page_client-reference-manifest.js +1 -1
  84. package/.next/standalone/agents-manage-ui/.next/server/app-paths-manifest.json +6 -6
  85. package/.next/standalone/agents-manage-ui/.next/server/chunks/1267.js +1 -0
  86. package/.next/standalone/agents-manage-ui/.next/server/chunks/1828.js +1 -0
  87. package/.next/standalone/agents-manage-ui/.next/server/chunks/2124.js +23 -13
  88. package/.next/standalone/agents-manage-ui/.next/server/chunks/3144.js +1 -0
  89. package/.next/standalone/agents-manage-ui/.next/server/chunks/3460.js +1 -0
  90. package/.next/standalone/agents-manage-ui/.next/server/chunks/3547.js +1 -1
  91. package/.next/standalone/agents-manage-ui/.next/server/chunks/{7211.js → 4108.js} +12 -12
  92. package/.next/standalone/agents-manage-ui/.next/server/chunks/499.js +1 -0
  93. package/.next/standalone/agents-manage-ui/.next/server/chunks/5232.js +1 -1
  94. package/.next/standalone/agents-manage-ui/.next/server/chunks/6831.js +1 -0
  95. package/.next/standalone/agents-manage-ui/.next/server/chunks/8449.js +2 -2
  96. package/.next/standalone/agents-manage-ui/.next/server/pages/404.html +1 -1
  97. package/.next/standalone/agents-manage-ui/.next/server/pages/500.html +1 -1
  98. package/.next/standalone/agents-manage-ui/.next/server/server-reference-manifest.js +1 -1
  99. package/.next/standalone/agents-manage-ui/.next/server/server-reference-manifest.json +1 -1
  100. package/.next/standalone/agents-manage-ui/.next/static/chunks/2915-f48fe90984ae5d8b.js +1 -0
  101. package/.next/standalone/agents-manage-ui/.next/static/chunks/6497-b90b21b559925fc6.js +1 -0
  102. package/.next/standalone/agents-manage-ui/.next/static/chunks/6763-5c2401becfe1a959.js +1 -0
  103. package/.next/standalone/agents-manage-ui/.next/static/chunks/7167-efbb83dcb2b4c5ce.js +1 -0
  104. package/.next/standalone/agents-manage-ui/.next/static/chunks/7232-63c17ffc2737968a.js +25 -0
  105. package/.next/standalone/agents-manage-ui/.next/static/chunks/{6952-3f2a84c5ba03fb2b.js → 8825-c4a769ea3a8e81d1.js} +1 -1
  106. package/.next/standalone/agents-manage-ui/.next/static/chunks/app/[tenantId]/projects/[projectId]/api-keys/page-c92a1f042f5ea538.js +1 -0
  107. package/.next/standalone/agents-manage-ui/.next/static/chunks/app/[tenantId]/projects/[projectId]/artifact-components/[artifactComponentId]/page-d8c96c8cefdfd4bd.js +1 -0
  108. package/.next/standalone/agents-manage-ui/.next/static/chunks/app/[tenantId]/projects/[projectId]/artifact-components/new/page-d8c96c8cefdfd4bd.js +1 -0
  109. package/.next/standalone/agents-manage-ui/.next/static/chunks/app/[tenantId]/projects/[projectId]/artifact-components/{page-3f9ff93fab72705b.js → page-9723ca38f4d36dda.js} +1 -1
  110. package/.next/standalone/agents-manage-ui/.next/static/chunks/app/[tenantId]/projects/[projectId]/credentials/[credentialId]/page-a1be97e0e467835a.js +1 -0
  111. package/.next/standalone/agents-manage-ui/.next/static/chunks/app/[tenantId]/projects/[projectId]/credentials/new/bearer/page-dcc6276bc353efb2.js +1 -0
  112. package/.next/standalone/agents-manage-ui/.next/static/chunks/app/[tenantId]/projects/[projectId]/credentials/new/providers/[providerId]/page-b4038baed88b93f9.js +1 -0
  113. package/.next/standalone/agents-manage-ui/.next/static/chunks/app/[tenantId]/projects/[projectId]/credentials/page-72ecfe1df8e379a5.js +1 -0
  114. package/.next/standalone/agents-manage-ui/.next/static/chunks/app/[tenantId]/projects/[projectId]/data-components/[dataComponentId]/{page-e02707f69e0015e0.js → page-ee89187f61e8d315.js} +1 -1
  115. package/.next/standalone/agents-manage-ui/.next/static/chunks/app/[tenantId]/projects/[projectId]/data-components/new/{page-e02707f69e0015e0.js → page-ee89187f61e8d315.js} +1 -1
  116. package/.next/standalone/agents-manage-ui/.next/static/chunks/app/[tenantId]/projects/[projectId]/data-components/page-e8b99c1272c1540c.js +1 -0
  117. package/.next/standalone/agents-manage-ui/.next/static/chunks/app/[tenantId]/projects/[projectId]/graphs/[graphId]/{page-149dc9cf7b8332ab.js → page-b574c5e1d3df7e73.js} +1 -1
  118. package/.next/standalone/agents-manage-ui/.next/static/chunks/app/[tenantId]/projects/[projectId]/graphs/new/{page-c15be44435dd5f2d.js → page-95c13c0305dfddfb.js} +1 -1
  119. package/.next/standalone/agents-manage-ui/.next/static/chunks/app/[tenantId]/projects/[projectId]/graphs/page-78554443bb163ae9.js +1 -0
  120. package/.next/standalone/agents-manage-ui/.next/static/chunks/app/[tenantId]/projects/[projectId]/mcp-servers/[mcpServerId]/edit/{page-33053057910de3eb.js → page-6a1affa547b51cd8.js} +1 -1
  121. package/.next/standalone/agents-manage-ui/.next/static/chunks/app/[tenantId]/projects/[projectId]/mcp-servers/[mcpServerId]/page-aa753859a6cd98f8.js +1 -0
  122. package/.next/standalone/agents-manage-ui/.next/static/chunks/app/[tenantId]/projects/[projectId]/mcp-servers/new/{page-1a6683f262056080.js → page-6222398da9ee2271.js} +1 -1
  123. package/.next/standalone/agents-manage-ui/.next/static/chunks/app/[tenantId]/projects/[projectId]/mcp-servers/page-cdf6cf1143f6a553.js +1 -0
  124. package/.next/standalone/agents-manage-ui/.next/static/chunks/app/[tenantId]/projects/[projectId]/settings/{page-78887bbecb44fd26.js → page-77f0a0e0e4372681.js} +1 -1
  125. package/.next/standalone/agents-manage-ui/.next/static/chunks/app/[tenantId]/projects/[projectId]/traces/page-b2e49d12c1c10e47.js +1 -0
  126. package/.next/standalone/agents-manage-ui/.next/static/chunks/app/[tenantId]/projects/page-fc18e3ba5c2fc6a5.js +1 -0
  127. package/.next/standalone/agents-manage-ui/.next/static/chunks/app/layout-35c8d055f3f8d91c.js +1 -0
  128. package/.next/standalone/agents-manage-ui/.next/static/css/98c416ff19152db0.css +1 -0
  129. package/.next/standalone/agents-manage-ui/package.json +2 -2
  130. package/.next/standalone/packages/agents-core/package.json +1 -1
  131. package/package.json +5 -5
  132. package/src/app/[tenantId]/projects/[projectId]/mcp-servers/[mcpServerId]/page.tsx +12 -12
  133. package/src/components/credentials/credential-tools-list.tsx +0 -25
  134. package/src/components/graph/configuration/node-types.tsx +6 -2
  135. package/src/components/graph/graph.tsx +66 -8
  136. package/src/components/graph/nodes/mcp-node.tsx +6 -11
  137. package/src/components/graph/playground/chat-widget.tsx +10 -0
  138. package/src/components/graph/sidepane/nodes/mcp-node-editor.tsx +69 -68
  139. package/src/components/graph/sidepane/nodes/mcp-selector/mcp-selector.tsx +44 -44
  140. package/src/components/graph/sidepane/sidepane.tsx +5 -0
  141. package/src/components/mcp-servers/form/mcp-server-form.tsx +47 -46
  142. package/src/components/mcp-servers/mcp-tool-item.tsx +3 -0
  143. package/src/components/mcp-servers/view-mcp-server-details.tsx +76 -37
  144. package/src/components/ui/copyable-multi-line-code.tsx +17 -0
  145. package/src/features/graph/domain/__tests__/serialize.test.ts +21 -51
  146. package/src/features/graph/domain/deserialize.ts +5 -26
  147. package/src/features/graph/domain/serialize.ts +56 -52
  148. package/src/lib/api/tools.ts +2 -92
  149. package/src/lib/utils/orphaned-tools-detector.ts +145 -0
  150. package/.next/standalone/agents-manage-ui/.next/server/chunks/1631.js +0 -1
  151. package/.next/standalone/agents-manage-ui/.next/server/chunks/2298.js +0 -1
  152. package/.next/standalone/agents-manage-ui/.next/server/chunks/329.js +0 -1
  153. package/.next/standalone/agents-manage-ui/.next/server/chunks/4754.js +0 -1
  154. package/.next/standalone/agents-manage-ui/.next/server/chunks/5773.js +0 -1
  155. package/.next/standalone/agents-manage-ui/.next/server/chunks/6577.js +0 -1
  156. package/.next/standalone/agents-manage-ui/.next/server/chunks/8798.js +0 -1
  157. package/.next/standalone/agents-manage-ui/.next/static/chunks/2229-e980fad7ac777384.js +0 -25
  158. package/.next/standalone/agents-manage-ui/.next/static/chunks/3200-6d80f96a4d5ea423.js +0 -1
  159. package/.next/standalone/agents-manage-ui/.next/static/chunks/6187-75bda81ee4117ed2.js +0 -1
  160. package/.next/standalone/agents-manage-ui/.next/static/chunks/6497-1503999d28bd793b.js +0 -1
  161. package/.next/standalone/agents-manage-ui/.next/static/chunks/7167-506ca8b1a906ac2a.js +0 -1
  162. package/.next/standalone/agents-manage-ui/.next/static/chunks/app/[tenantId]/projects/[projectId]/api-keys/page-81788595a817e711.js +0 -1
  163. package/.next/standalone/agents-manage-ui/.next/static/chunks/app/[tenantId]/projects/[projectId]/artifact-components/[artifactComponentId]/page-8ec4191752587977.js +0 -1
  164. package/.next/standalone/agents-manage-ui/.next/static/chunks/app/[tenantId]/projects/[projectId]/artifact-components/new/page-8ec4191752587977.js +0 -1
  165. package/.next/standalone/agents-manage-ui/.next/static/chunks/app/[tenantId]/projects/[projectId]/credentials/[credentialId]/page-a637ecda071e042c.js +0 -1
  166. package/.next/standalone/agents-manage-ui/.next/static/chunks/app/[tenantId]/projects/[projectId]/credentials/new/bearer/page-fd2c318c31373f80.js +0 -1
  167. package/.next/standalone/agents-manage-ui/.next/static/chunks/app/[tenantId]/projects/[projectId]/credentials/new/providers/[providerId]/page-f55b6e769c4b1db8.js +0 -1
  168. package/.next/standalone/agents-manage-ui/.next/static/chunks/app/[tenantId]/projects/[projectId]/credentials/page-db25060b2d52ebb8.js +0 -1
  169. package/.next/standalone/agents-manage-ui/.next/static/chunks/app/[tenantId]/projects/[projectId]/data-components/page-b494291f7a5cebf6.js +0 -1
  170. package/.next/standalone/agents-manage-ui/.next/static/chunks/app/[tenantId]/projects/[projectId]/graphs/page-5edc45db8e78342a.js +0 -1
  171. package/.next/standalone/agents-manage-ui/.next/static/chunks/app/[tenantId]/projects/[projectId]/mcp-servers/[mcpServerId]/page-190351c7f4b5d2f8.js +0 -1
  172. package/.next/standalone/agents-manage-ui/.next/static/chunks/app/[tenantId]/projects/[projectId]/mcp-servers/page-36c9163f810b36a0.js +0 -1
  173. package/.next/standalone/agents-manage-ui/.next/static/chunks/app/[tenantId]/projects/[projectId]/traces/page-bb7eb8042fbce7b4.js +0 -1
  174. package/.next/standalone/agents-manage-ui/.next/static/chunks/app/[tenantId]/projects/page-af5372b8e0a563b0.js +0 -1
  175. package/.next/standalone/agents-manage-ui/.next/static/chunks/app/layout-71456c0293edc200.js +0 -1
  176. package/.next/standalone/agents-manage-ui/.next/static/css/70e9093ef73fbe1b.css +0 -1
  177. /package/.next/standalone/agents-manage-ui/.next/static/{X9iq1SzdbJH24pPiGko3K → 0c8HYV9Bsdgx06_BNb0kR}/_buildManifest.js +0 -0
  178. /package/.next/standalone/agents-manage-ui/.next/static/{X9iq1SzdbJH24pPiGko3K → 0c8HYV9Bsdgx06_BNb0kR}/_ssgManifest.js +0 -0
@@ -27,7 +27,7 @@ describe('serializeGraphData', () => {
27
27
  ];
28
28
  const edges: Edge[] = [];
29
29
 
30
- const result = serializeGraphData(nodes, edges);
30
+ const result = serializeGraphData(nodes, edges, undefined, {}, {}, {});
31
31
 
32
32
  expect((result.agents.agent1 as any).models).toBeUndefined();
33
33
  });
@@ -52,7 +52,7 @@ describe('serializeGraphData', () => {
52
52
  ];
53
53
  const edges: Edge[] = [];
54
54
 
55
- const result = serializeGraphData(nodes, edges);
55
+ const result = serializeGraphData(nodes, edges, undefined, {}, {}, {});
56
56
 
57
57
  expect((result.agents.agent1 as any).models).toBeUndefined();
58
58
  });
@@ -77,7 +77,7 @@ describe('serializeGraphData', () => {
77
77
  ];
78
78
  const edges: Edge[] = [];
79
79
 
80
- const result = serializeGraphData(nodes, edges);
80
+ const result = serializeGraphData(nodes, edges, undefined, {}, {}, {});
81
81
 
82
82
  expect((result.agents.agent1 as any).models).toEqual({
83
83
  base: { model: 'gpt-4' },
@@ -106,7 +106,7 @@ describe('serializeGraphData', () => {
106
106
  ];
107
107
  const edges: Edge[] = [];
108
108
 
109
- const result = serializeGraphData(nodes, edges);
109
+ const result = serializeGraphData(nodes, edges, undefined, {}, {}, {});
110
110
 
111
111
  expect((result.agents.agent1 as any).models).toEqual({
112
112
  base: undefined,
@@ -135,7 +135,7 @@ describe('serializeGraphData', () => {
135
135
  ];
136
136
  const edges: Edge[] = [];
137
137
 
138
- const result = serializeGraphData(nodes, edges);
138
+ const result = serializeGraphData(nodes, edges, undefined, {}, {}, {});
139
139
 
140
140
  expect((result.agents.agent1 as any).models).toEqual({
141
141
  base: undefined,
@@ -164,7 +164,7 @@ describe('serializeGraphData', () => {
164
164
  ];
165
165
  const edges: Edge[] = [];
166
166
 
167
- const result = serializeGraphData(nodes, edges);
167
+ const result = serializeGraphData(nodes, edges, undefined, {}, {}, {});
168
168
 
169
169
  expect((result.agents.agent1 as any).models).toEqual({
170
170
  base: { model: 'gpt-4' },
@@ -189,7 +189,7 @@ describe('serializeGraphData', () => {
189
189
  ];
190
190
  const edges: Edge[] = [];
191
191
 
192
- const result = serializeGraphData(nodes, edges);
192
+ const result = serializeGraphData(nodes, edges, undefined, {}, {}, {});
193
193
 
194
194
  expect((result.agents.agent1 as any).models).toBeUndefined();
195
195
  });
@@ -213,15 +213,9 @@ describe('serializeGraphData', () => {
213
213
  type: NodeType.MCP,
214
214
  position: { x: 200, y: 0 },
215
215
  data: {
216
- id: 'mcp1',
216
+ toolId: 'mcp1',
217
217
  name: 'Test MCP Server',
218
- config: { type: 'mcp', mcp: { server: { url: 'test://server' } } },
219
218
  tempSelectedTools: ['tool1', 'tool2'],
220
- tenantId: 'test-tenant',
221
- projectId: 'test-project',
222
- status: 'unknown',
223
- createdAt: new Date(),
224
- updatedAt: new Date(),
225
219
  } as MCPNodeData,
226
220
  },
227
221
  ];
@@ -235,13 +229,13 @@ describe('serializeGraphData', () => {
235
229
  },
236
230
  ];
237
231
 
238
- const result = serializeGraphData(nodes, edges);
232
+ const result = serializeGraphData(nodes, edges, undefined, {}, {}, {});
239
233
 
240
234
  expect((result.agents.agent1 as any).canUse).toBeDefined();
241
235
  expect((result.agents.agent1 as any).canUse).toHaveLength(1);
242
236
  expect((result.agents.agent1 as any).canUse[0]).toEqual({
243
237
  toolId: 'mcp1',
244
- toolSelection: ['tool1', 'tool2']
238
+ toolSelection: ['tool1', 'tool2'],
245
239
  });
246
240
  });
247
241
 
@@ -263,15 +257,9 @@ describe('serializeGraphData', () => {
263
257
  type: NodeType.MCP,
264
258
  position: { x: 200, y: 0 },
265
259
  data: {
266
- id: 'mcp1',
260
+ toolId: 'mcp1',
267
261
  name: 'Test MCP Server',
268
- config: { type: 'mcp', mcp: { server: { url: 'test://server' } } },
269
262
  tempSelectedTools: null, // null means all tools selected
270
- tenantId: 'test-tenant',
271
- projectId: 'test-project',
272
- status: 'unknown',
273
- createdAt: new Date(),
274
- updatedAt: new Date(),
275
263
  } as MCPNodeData,
276
264
  },
277
265
  ];
@@ -285,14 +273,14 @@ describe('serializeGraphData', () => {
285
273
  },
286
274
  ];
287
275
 
288
- const result = serializeGraphData(nodes, edges);
276
+ const result = serializeGraphData(nodes, edges, undefined, {}, {}, {});
289
277
 
290
278
  // When tempSelectedTools is null, all tools should be selected (toolSelection: null)
291
279
  expect((result.agents.agent1 as any).canUse).toBeDefined();
292
280
  expect((result.agents.agent1 as any).canUse).toHaveLength(1);
293
281
  expect((result.agents.agent1 as any).canUse[0]).toEqual({
294
282
  toolId: 'mcp1',
295
- toolSelection: null
283
+ toolSelection: null,
296
284
  });
297
285
  });
298
286
 
@@ -313,15 +301,9 @@ describe('serializeGraphData', () => {
313
301
  type: NodeType.MCP,
314
302
  position: { x: 200, y: 0 },
315
303
  data: {
316
- id: 'mcp1',
304
+ toolId: 'mcp1',
317
305
  name: 'Test MCP Server',
318
- config: { type: 'mcp', mcp: { server: { url: 'test://server' } } },
319
306
  tempSelectedTools: [], // empty array means no tools selected
320
- tenantId: 'test-tenant',
321
- projectId: 'test-project',
322
- status: 'unknown',
323
- createdAt: new Date(),
324
- updatedAt: new Date(),
325
307
  } as MCPNodeData,
326
308
  },
327
309
  ];
@@ -335,13 +317,13 @@ describe('serializeGraphData', () => {
335
317
  },
336
318
  ];
337
319
 
338
- const result = serializeGraphData(nodes, edges);
320
+ const result = serializeGraphData(nodes, edges, undefined, {}, {}, {});
339
321
 
340
322
  expect((result.agents.agent1 as any).canUse).toBeDefined();
341
323
  expect((result.agents.agent1 as any).canUse).toHaveLength(1);
342
324
  expect((result.agents.agent1 as any).canUse[0]).toEqual({
343
325
  toolId: 'mcp1',
344
- toolSelection: []
326
+ toolSelection: [],
345
327
  });
346
328
  });
347
329
 
@@ -362,15 +344,9 @@ describe('serializeGraphData', () => {
362
344
  type: NodeType.MCP,
363
345
  position: { x: 200, y: 0 },
364
346
  data: {
365
- id: 'mcp1',
347
+ toolId: 'mcp1',
366
348
  name: 'Test MCP Server',
367
- config: { type: 'mcp', mcp: { server: { url: 'test://server' } } },
368
349
  // no tempSelectedTools property
369
- tenantId: 'test-tenant',
370
- projectId: 'test-project',
371
- status: 'unknown',
372
- createdAt: new Date(),
373
- updatedAt: new Date(),
374
350
  } as MCPNodeData,
375
351
  },
376
352
  ];
@@ -384,7 +360,7 @@ describe('serializeGraphData', () => {
384
360
  },
385
361
  ];
386
362
 
387
- const result = serializeGraphData(nodes, edges);
363
+ const result = serializeGraphData(nodes, edges, undefined, {}, {}, {});
388
364
 
389
365
  // selectedTools should not be created if tempSelectedTools is undefined
390
366
  expect((result.agents.agent1 as any).selectedTools).toBeUndefined();
@@ -409,15 +385,9 @@ describe('serializeGraphData', () => {
409
385
  type: NodeType.MCP,
410
386
  position: { x: 200, y: 0 },
411
387
  data: {
412
- id: 'mcp1',
388
+ toolId: 'mcp1',
413
389
  name: 'Test MCP Server',
414
- config: { type: 'mcp', mcp: { server: { url: 'test://server' } } },
415
390
  // tempSelectedTools is undefined (user didn't interact with UI)
416
- tenantId: 'test-tenant',
417
- projectId: 'test-project',
418
- status: 'unknown',
419
- createdAt: new Date(),
420
- updatedAt: new Date(),
421
391
  } as MCPNodeData,
422
392
  },
423
393
  ];
@@ -431,7 +401,7 @@ describe('serializeGraphData', () => {
431
401
  },
432
402
  ];
433
403
 
434
- const result = serializeGraphData(nodes, edges);
404
+ const result = serializeGraphData(nodes, edges, undefined, {}, {}, {});
435
405
 
436
406
  // When tempSelectedTools is undefined and there's an edge to MCP tool,
437
407
  // the toolSelection will be null (all tools selected by default)
@@ -439,7 +409,7 @@ describe('serializeGraphData', () => {
439
409
  expect((result.agents.agent1 as any).canUse).toHaveLength(1);
440
410
  expect((result.agents.agent1 as any).canUse[0]).toEqual({
441
411
  toolId: 'mcp1',
442
- toolSelection: null // null means all tools are selected
412
+ toolSelection: null, // null means all tools are selected
443
413
  });
444
414
  });
445
415
  });
@@ -14,7 +14,7 @@ import type {
14
14
  FullGraphDefinition,
15
15
  InternalAgentDefinition,
16
16
  } from '@/lib/types/graph-full';
17
- import type { MCPTool } from '@/lib/types/tools';
17
+
18
18
  import { formatJsonField } from '@/lib/utils';
19
19
 
20
20
  interface TransformResult {
@@ -101,10 +101,7 @@ function applyDagreLayout(nodes: Node[], edges: Edge[]): Node[] {
101
101
  });
102
102
  }
103
103
 
104
- export function deserializeGraphData(
105
- data: FullGraphDefinition,
106
- toolLookup?: Record<string, MCPTool>
107
- ): TransformResult {
104
+ export function deserializeGraphData(data: FullGraphDefinition): TransformResult {
108
105
  const nodes: Node[] = [];
109
106
  const edges: Edge[] = [];
110
107
 
@@ -213,7 +210,7 @@ export function deserializeGraphData(
213
210
  id: toolNodeId,
214
211
  type: NodeType.MCP,
215
212
  position: { x: 0, y: 0 },
216
- data: { id: tool.id, ...tool },
213
+ data: { toolId: tool.id },
217
214
  };
218
215
  nodes.push(toolNode);
219
216
 
@@ -228,33 +225,15 @@ export function deserializeGraphData(
228
225
  edges.push(agentToToolEdge);
229
226
  }
230
227
  } else {
231
- // Tools are project-scoped, use the tool lookup if available
228
+ // Tools are project-scoped - just store the tool ID
232
229
  for (const canUseItem of agent.canUse) {
233
230
  const toolId = canUseItem.toolId;
234
- const tool = toolLookup?.[toolId];
235
231
  const toolNodeId = nanoid();
236
232
  const toolNode: Node = {
237
233
  id: toolNodeId,
238
234
  type: NodeType.MCP,
239
235
  position: { x: 0, y: 0 },
240
- data: tool
241
- ? {
242
- id: tool.id,
243
- name: tool.name,
244
- description: '', // MCPTool doesn't have a description field at top level
245
- type: 'mcp',
246
- config: tool.config || {},
247
- status: tool.status,
248
- availableTools: tool.availableTools,
249
- selectedTools: canUseItem.toolSelection, // Use toolSelection from canUseItem
250
- }
251
- : {
252
- id: toolId,
253
- name: toolId,
254
- description: 'Project-scoped tool',
255
- type: 'project-scoped',
256
- config: {},
257
- },
236
+ data: { toolId },
258
237
  };
259
238
  nodes.push(toolNode);
260
239
 
@@ -9,7 +9,10 @@ import type { DataComponent } from '@/lib/api/data-components';
9
9
  import type { FullGraphDefinition } from '@/lib/types/graph-full';
10
10
 
11
11
  // Extract the internal agent type from the union
12
- type InternalAgent = Extract<FullGraphDefinition['agents'][string], { canUse: Array<{ toolId: string; toolSelection?: string[] | null }> }>;
12
+ type InternalAgent = Extract<
13
+ FullGraphDefinition['agents'][string],
14
+ { canUse: Array<{ toolId: string; toolSelection?: string[] | null }> }
15
+ >;
13
16
 
14
17
  type ExternalAgent = {
15
18
  id: string;
@@ -82,7 +85,8 @@ export function serializeGraphData(
82
85
  edges: Edge[],
83
86
  metadata?: GraphMetadata,
84
87
  dataComponentLookup?: Record<string, DataComponent>,
85
- artifactComponentLookup?: Record<string, ArtifactComponent>
88
+ artifactComponentLookup?: Record<string, ArtifactComponent>,
89
+ selectedToolsLookup?: Record<string, Record<string, string[]>>
86
90
  ): FullGraphDefinition {
87
91
  const agents: Record<string, ExtendedAgent> = {};
88
92
  // Note: Tools are now project-scoped and not included in graph serialization
@@ -108,13 +112,56 @@ export function serializeGraphData(
108
112
 
109
113
  const stopWhen = (node.data as any).stopWhen;
110
114
 
111
- // Convert tools and selectedTools to canUse array
112
- const tools = (node.data as any).tools || [];
113
- const selectedTools = (node.data as any).selectedTools || {};
114
- const canUse = tools.map((toolId: string) => ({
115
- toolId,
116
- toolSelection: selectedTools[toolId] || null
117
- }));
115
+ // Build canUse array from edges connecting this agent to MCP nodes
116
+ const canUse: Array<{ toolId: string; toolSelection?: string[] | null }> = [];
117
+
118
+ // Find edges from this agent to MCP nodes
119
+ const agentToMcpEdges = edges.filter(
120
+ (edge) =>
121
+ edge.source === node.id &&
122
+ nodes.some((n) => n.id === edge.target && n.type === NodeType.MCP)
123
+ );
124
+
125
+ for (const edge of agentToMcpEdges) {
126
+ const mcpNode = nodes.find((n) => n.id === edge.target);
127
+
128
+ if (mcpNode && mcpNode.type === NodeType.MCP) {
129
+ const toolId = (mcpNode.data as any).toolId;
130
+
131
+ if (toolId) {
132
+ // Get selected tools from MCP node's tempSelectedTools
133
+ const tempSelectedTools = (mcpNode.data as any).tempSelectedTools;
134
+ let toolSelection: string[] | null = null;
135
+
136
+ if (tempSelectedTools !== undefined) {
137
+ // User has made changes to tool selection in the UI
138
+ if (Array.isArray(tempSelectedTools)) {
139
+ toolSelection = tempSelectedTools;
140
+ } else if (tempSelectedTools === null) {
141
+ toolSelection = null; // All tools selected
142
+ }
143
+ } else {
144
+ // No changes made to tool selection - preserve existing selection
145
+ if (
146
+ selectedToolsLookup &&
147
+ selectedToolsLookup[agentId] &&
148
+ selectedToolsLookup[agentId][toolId] !== undefined
149
+ ) {
150
+ // Get existing selection from saved data
151
+ toolSelection = selectedToolsLookup[agentId][toolId];
152
+ } else {
153
+ // Default to all tools selected when no existing data found
154
+ toolSelection = null;
155
+ }
156
+ }
157
+
158
+ canUse.push({
159
+ toolId,
160
+ toolSelection,
161
+ });
162
+ }
163
+ }
164
+ }
118
165
 
119
166
  const agent: ExtendedAgent = {
120
167
  id: agentId,
@@ -151,10 +198,6 @@ export function serializeGraphData(
151
198
  }
152
199
 
153
200
  agents[agentId] = agent;
154
- } else if (node.type === NodeType.MCP) {
155
- // Note: Tools are now project-scoped and not processed during graph serialization
156
- // Tool nodes in the UI are handled separately at the project level
157
- console.log('Skipping MCP tool node during graph serialization (tools are project-scoped)');
158
201
  }
159
202
  }
160
203
 
@@ -209,45 +252,6 @@ export function serializeGraphData(
209
252
  addRelationship(targetAgent, 'canDelegateTo', sourceAgentId);
210
253
  }
211
254
  }
212
- } else if (edge.type === EdgeType.Default) {
213
- const sourceAgentNode = nodes.find((node) => node.id === edge.source);
214
- const sourceAgentId = (sourceAgentNode?.data.id || sourceAgentNode?.id) as string;
215
- const sourceAgent: ExtendedAgent = agents[sourceAgentId];
216
- const targetToolNode = nodes.find((node) => node.id === edge.target);
217
- if (sourceAgent && targetToolNode && sourceAgent.type === 'internal') {
218
- const toolId = (targetToolNode.data as any).id as string;
219
- const internalAgent = sourceAgent as InternalAgent & {
220
- dataComponents: string[];
221
- artifactComponents: string[];
222
- models?: GraphMetadata['models'];
223
- type: 'internal';
224
- };
225
-
226
- // Check if tool is already in canUse array
227
- const existingCanUse = internalAgent.canUse.find(item => item.toolId === toolId);
228
- if (!existingCanUse) {
229
- internalAgent.canUse.push({
230
- toolId,
231
- toolSelection: null
232
- });
233
- }
234
-
235
- // Only override toolSelection if user made changes in the UI for this specific tool
236
- const userSelectedTools = (targetToolNode.data as any).tempSelectedTools;
237
- if (userSelectedTools !== undefined) {
238
- // User has made selections in the UI for this tool
239
- const canUseItem = internalAgent.canUse.find(item => item.toolId === toolId);
240
- if (canUseItem) {
241
- if (userSelectedTools === null) {
242
- // User selected all tools - set to null (null = all)
243
- canUseItem.toolSelection = null;
244
- } else {
245
- // User selected specific tools (including empty array for "none selected")
246
- canUseItem.toolSelection = userSelectedTools;
247
- }
248
- }
249
- }
250
- }
251
255
  }
252
256
  }
253
257
 
@@ -122,97 +122,7 @@ export async function deleteMCPTool(
122
122
  validateTenantId(tenantId);
123
123
  validateProjectId(projectId);
124
124
 
125
- await makeManagementApiRequest<void>(
126
- `tenants/${tenantId}/projects/${projectId}/tools/${id}`,
127
- {
128
- method: 'DELETE',
129
- }
130
- );
131
- }
132
-
133
- /**
134
- * Check health of an MCP tool
135
- */
136
- export async function checkMCPToolHealth(
137
- tenantId: string,
138
- projectId: string,
139
- id: string
140
- ): Promise<{
141
- tool: McpTool;
142
- healthCheck: {
143
- status: McpTool['status'];
144
- error?: string;
145
- };
146
- }> {
147
- validateTenantId(tenantId);
148
- validateProjectId(projectId);
149
-
150
- const response = await makeManagementApiRequest<
151
- SingleResponse<{
152
- tool: McpTool;
153
- healthCheck: {
154
- status: McpTool['status'];
155
- error?: string;
156
- };
157
- }>
158
- >(`tenants/${tenantId}/projects/${projectId}/tools/${id}/health-check`, {
159
- method: 'POST',
125
+ await makeManagementApiRequest<void>(`tenants/${tenantId}/projects/${projectId}/tools/${id}`, {
126
+ method: 'DELETE',
160
127
  });
161
-
162
- return response.data;
163
- }
164
-
165
- /**
166
- * Get available tools from an MCP server
167
- */
168
- export async function getMCPToolAvailableTools(
169
- tenantId: string,
170
- projectId: string,
171
- id: string
172
- ): Promise<{
173
- availableTools: Array<{
174
- name: string;
175
- description?: string;
176
- inputSchema?: Record<string, unknown>;
177
- }>;
178
- lastSync?: string;
179
- status: McpTool['status'];
180
- }> {
181
- validateTenantId(tenantId);
182
- validateProjectId(projectId);
183
-
184
- const response = await makeManagementApiRequest<
185
- SingleResponse<{
186
- availableTools: Array<{
187
- name: string;
188
- description?: string;
189
- inputSchema?: Record<string, unknown>;
190
- }>;
191
- lastSync?: string;
192
- status: McpTool['status'];
193
- }>
194
- >(`tenants/${tenantId}/projects/${projectId}/tools/${id}/available-tools`);
195
-
196
- return response.data;
197
- }
198
-
199
- /**
200
- * Sync tool definitions from an MCP server
201
- */
202
- export async function syncMCPTool(
203
- tenantId: string,
204
- projectId: string,
205
- id: string
206
- ): Promise<McpTool> {
207
- validateTenantId(tenantId);
208
- validateProjectId(projectId);
209
-
210
- const response = await makeManagementApiRequest<SingleResponse<McpTool>>(
211
- `tenants/${tenantId}/projects/${projectId}/tools/${id}/sync`,
212
- {
213
- method: 'POST',
214
- }
215
- );
216
-
217
- return response.data;
218
128
  }
@@ -0,0 +1,145 @@
1
+ import type { Node } from '@xyflow/react';
2
+ import { getActiveTools } from '@/app/utils/active-tools';
3
+ import type { MCPNodeData } from '@/components/graph/configuration/node-types';
4
+ import { NodeType } from '@/components/graph/configuration/node-types';
5
+ import type { MCPTool } from '@/lib/types/tools';
6
+
7
+ export interface OrphanedToolsInfo {
8
+ nodeId: string;
9
+ nodeName: string;
10
+ orphanedTools: string[];
11
+ }
12
+
13
+ export interface OrphanedToolsDetectionResult {
14
+ hasOrphanedTools: boolean;
15
+ orphanedToolsByNode: OrphanedToolsInfo[];
16
+ totalOrphanedCount: number;
17
+ }
18
+
19
+ /**
20
+ * Simplified API that combines detection and message creation
21
+ * Returns null if no orphaned tools found, otherwise returns the warning message
22
+ */
23
+ export function detectOrphanedToolsAndGetWarning(
24
+ nodes: Node[],
25
+ selectedToolsLookup: Record<string, Record<string, string[]>>,
26
+ toolLookup: Record<string, MCPTool>
27
+ ): string | null {
28
+ const result = detectOrphanedToolsInGraph(nodes, selectedToolsLookup, toolLookup);
29
+ return result.hasOrphanedTools ? createOrphanedToolsWarningMessage(result) : null;
30
+ }
31
+
32
+ /**
33
+ * Extract shared logic for getting selected tools for a node
34
+ * This replaces the duplicated logic between detector and MCP node editor
35
+ */
36
+ export function getCurrentSelectedToolsForNode(
37
+ node: Node<MCPNodeData>,
38
+ selectedToolsLookup: Record<string, Record<string, string[]>>
39
+ ): string[] | null {
40
+ // First check if we have temporary selections stored on the node (from recent clicks)
41
+ if ((node.data as any).tempSelectedTools !== undefined) {
42
+ return (node.data as any).tempSelectedTools;
43
+ }
44
+
45
+ // Otherwise, get from the database/initial state
46
+ const allSelectedTools = new Set<string>();
47
+ let hasAnyData = false;
48
+ let hasEmptyArray = false;
49
+ let hasNullValue = false;
50
+
51
+ Object.values(selectedToolsLookup).forEach((agentTools) => {
52
+ const toolsForThisMCP = agentTools[node.data.toolId];
53
+ if (toolsForThisMCP !== undefined) {
54
+ hasAnyData = true;
55
+ if (Array.isArray(toolsForThisMCP) && toolsForThisMCP.length === 0) {
56
+ hasEmptyArray = true;
57
+ } else if (toolsForThisMCP === null) {
58
+ hasNullValue = true;
59
+ } else if (Array.isArray(toolsForThisMCP)) {
60
+ toolsForThisMCP.forEach((tool) => {
61
+ allSelectedTools.add(tool);
62
+ });
63
+ }
64
+ }
65
+ });
66
+
67
+ if (hasNullValue) return null;
68
+ if (hasEmptyArray) return [];
69
+ if (!hasAnyData) return null;
70
+
71
+ return Array.from(allSelectedTools);
72
+ }
73
+
74
+ /**
75
+ * Detects orphaned tools across all MCP nodes in the graph
76
+ * Orphaned tools are tools that were selected but are no longer available in the MCP server
77
+ */
78
+ export function detectOrphanedToolsInGraph(
79
+ nodes: Node[],
80
+ selectedToolsLookup: Record<string, Record<string, string[]>>,
81
+ toolLookup: Record<string, MCPTool>
82
+ ): OrphanedToolsDetectionResult {
83
+ const orphanedToolsByNode: OrphanedToolsInfo[] = [];
84
+
85
+ // Find all MCP nodes
86
+ const mcpNodes = nodes.filter((node): node is Node<MCPNodeData> => node.type === NodeType.MCP);
87
+
88
+ for (const node of mcpNodes) {
89
+ const toolData = toolLookup[node.data.toolId];
90
+ if (!toolData) continue; // Skip if tool data not found
91
+
92
+ const activeTools = getActiveTools({
93
+ availableTools: toolData.availableTools,
94
+ activeTools: toolData.config?.mcp?.activeTools,
95
+ });
96
+
97
+ const selectedTools = getCurrentSelectedToolsForNode(node, selectedToolsLookup);
98
+
99
+ // Find orphaned tools for this node
100
+ const orphanedTools =
101
+ selectedTools && Array.isArray(selectedTools)
102
+ ? selectedTools.filter((toolName) => !activeTools?.some((tool) => tool.name === toolName))
103
+ : [];
104
+
105
+ if (orphanedTools.length > 0) {
106
+ orphanedToolsByNode.push({
107
+ nodeId: node.data.toolId,
108
+ nodeName: node.data.name || toolData.name || 'Unnamed MCP Server',
109
+ orphanedTools,
110
+ });
111
+ }
112
+ }
113
+
114
+ const totalOrphanedCount = orphanedToolsByNode.reduce(
115
+ (total, nodeInfo) => total + nodeInfo.orphanedTools.length,
116
+ 0
117
+ );
118
+
119
+ return {
120
+ hasOrphanedTools: orphanedToolsByNode.length > 0,
121
+ orphanedToolsByNode,
122
+ totalOrphanedCount,
123
+ };
124
+ }
125
+
126
+ /**
127
+ * Creates a user-friendly warning message for orphaned tools
128
+ * Assumes result.hasOrphanedTools is true (should be checked by caller)
129
+ */
130
+ export function createOrphanedToolsWarningMessage(result: OrphanedToolsDetectionResult): string {
131
+ const nodeCount = result.orphanedToolsByNode.length;
132
+ const toolCount = result.totalOrphanedCount;
133
+
134
+ if (nodeCount === 1) {
135
+ const nodeInfo = result.orphanedToolsByNode[0];
136
+ const toolList = nodeInfo.orphanedTools.join(', ');
137
+ const toolText = toolCount > 1 ? 'tools' : 'tool';
138
+ const verbText = toolCount > 1 ? 'are' : 'is';
139
+ const pronounText = toolCount > 1 ? 'These tools' : 'This tool';
140
+
141
+ return `The MCP server "${nodeInfo.nodeName}" has ${toolCount} selected ${toolText} that ${verbText} no longer available: ${toolList}. ${pronounText} will not be available at runtime. Please update your tool selections.`;
142
+ }
143
+
144
+ return `${nodeCount} MCP servers have a total of ${toolCount} selected tools that are no longer available. These orphaned tools will not be available at runtime. Please update your tool selections.`;
145
+ }