flowent 0.0.6 → 0.0.10

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 (398) hide show
  1. package/README.md +1 -4
  2. package/backend/README.md +1 -4
  3. package/backend/pyproject.toml +2 -8
  4. package/backend/src/flowent/__pycache__/__init__.cpython-313.pyc +0 -0
  5. package/backend/src/flowent/__pycache__/agent.cpython-313.pyc +0 -0
  6. package/backend/src/flowent/__pycache__/cli.cpython-313.pyc +0 -0
  7. package/backend/src/flowent/__pycache__/context.cpython-313.pyc +0 -0
  8. package/backend/src/flowent/__pycache__/llm.cpython-313.pyc +0 -0
  9. package/backend/src/flowent/__pycache__/logging.cpython-313.pyc +0 -0
  10. package/backend/src/flowent/__pycache__/main.cpython-313.pyc +0 -0
  11. package/backend/src/flowent/__pycache__/patch.cpython-313.pyc +0 -0
  12. package/backend/src/flowent/__pycache__/paths.cpython-313.pyc +0 -0
  13. package/backend/src/flowent/__pycache__/sandbox.cpython-313.pyc +0 -0
  14. package/backend/src/flowent/__pycache__/storage.cpython-313.pyc +0 -0
  15. package/backend/src/flowent/__pycache__/tools.cpython-313.pyc +0 -0
  16. package/backend/src/flowent/agent.py +217 -3094
  17. package/backend/src/flowent/cli.py +19 -24
  18. package/backend/src/flowent/context.py +127 -0
  19. package/backend/src/flowent/llm.py +256 -0
  20. package/backend/src/flowent/logging.py +170 -129
  21. package/backend/src/flowent/main.py +321 -70
  22. package/backend/src/flowent/patch.py +182 -0
  23. package/backend/src/flowent/paths.py +11 -0
  24. package/backend/src/flowent/sandbox.py +214 -40
  25. package/backend/src/flowent/static/assets/geist-cyrillic-wght-normal-CHSlOQsW.woff2 +0 -0
  26. package/backend/src/flowent/static/assets/geist-latin-ext-wght-normal-DMtmJ5ZE.woff2 +0 -0
  27. package/backend/src/flowent/static/assets/geist-latin-wght-normal-Dm3htQBi.woff2 +0 -0
  28. package/backend/src/flowent/static/assets/index-C76K95ty.js +81 -0
  29. package/backend/src/flowent/static/assets/index-iUMNKvlU.css +2 -0
  30. package/backend/src/flowent/static/flowent.png +0 -0
  31. package/backend/src/flowent/static/index.html +5 -25
  32. package/backend/src/flowent/storage.py +302 -0
  33. package/backend/src/flowent/tools.py +364 -0
  34. package/backend/tests/__pycache__/test_agent_tools.cpython-313-pytest-9.0.3.pyc +0 -0
  35. package/backend/tests/__pycache__/test_health.cpython-313-pytest-9.0.3.pyc +0 -0
  36. package/backend/tests/__pycache__/test_llm_providers.cpython-313-pytest-9.0.3.pyc +0 -0
  37. package/backend/tests/__pycache__/test_logging.cpython-313-pytest-9.0.3.pyc +0 -0
  38. package/backend/tests/__pycache__/test_persistence.cpython-313-pytest-9.0.3.pyc +0 -0
  39. package/backend/tests/__pycache__/test_workspace_chat.cpython-313-pytest-9.0.3.pyc +0 -0
  40. package/backend/tests/test_agent_tools.py +449 -0
  41. package/backend/tests/test_health.py +12 -0
  42. package/backend/tests/test_llm_providers.py +113 -0
  43. package/backend/tests/test_logging.py +182 -0
  44. package/backend/tests/test_persistence.py +125 -0
  45. package/backend/tests/test_workspace_chat.py +578 -0
  46. package/backend/uv.lock +803 -99
  47. package/dist/frontend/assets/geist-cyrillic-wght-normal-CHSlOQsW.woff2 +0 -0
  48. package/dist/frontend/assets/geist-latin-ext-wght-normal-DMtmJ5ZE.woff2 +0 -0
  49. package/dist/frontend/assets/geist-latin-wght-normal-Dm3htQBi.woff2 +0 -0
  50. package/dist/frontend/assets/index-C76K95ty.js +81 -0
  51. package/dist/frontend/assets/index-iUMNKvlU.css +2 -0
  52. package/dist/frontend/flowent.png +0 -0
  53. package/dist/frontend/index.html +5 -25
  54. package/package.json +1 -2
  55. package/backend/src/flowent/__pycache__/_version.cpython-313.pyc +0 -0
  56. package/backend/src/flowent/__pycache__/access.cpython-313.pyc +0 -0
  57. package/backend/src/flowent/__pycache__/assistant_commands.cpython-313.pyc +0 -0
  58. package/backend/src/flowent/__pycache__/config.cpython-313.pyc +0 -0
  59. package/backend/src/flowent/__pycache__/events.cpython-313.pyc +0 -0
  60. package/backend/src/flowent/__pycache__/graph_runtime.cpython-313.pyc +0 -0
  61. package/backend/src/flowent/__pycache__/graph_service.cpython-313.pyc +0 -0
  62. package/backend/src/flowent/__pycache__/image_assets.cpython-313.pyc +0 -0
  63. package/backend/src/flowent/__pycache__/mcp_service.cpython-313.pyc +0 -0
  64. package/backend/src/flowent/__pycache__/model_metadata.cpython-313.pyc +0 -0
  65. package/backend/src/flowent/__pycache__/network.cpython-313.pyc +0 -0
  66. package/backend/src/flowent/__pycache__/observability_service.cpython-313.pyc +0 -0
  67. package/backend/src/flowent/__pycache__/registry.cpython-313.pyc +0 -0
  68. package/backend/src/flowent/__pycache__/role_management.cpython-313.pyc +0 -0
  69. package/backend/src/flowent/__pycache__/runtime.cpython-313.pyc +0 -0
  70. package/backend/src/flowent/__pycache__/security.cpython-313.pyc +0 -0
  71. package/backend/src/flowent/__pycache__/settings.cpython-313.pyc +0 -0
  72. package/backend/src/flowent/__pycache__/settings_management.cpython-313.pyc +0 -0
  73. package/backend/src/flowent/__pycache__/state_db.cpython-313.pyc +0 -0
  74. package/backend/src/flowent/__pycache__/workspace_store.cpython-313.pyc +0 -0
  75. package/backend/src/flowent/access.py +0 -247
  76. package/backend/src/flowent/assistant_commands.py +0 -115
  77. package/backend/src/flowent/channels/__init__.py +0 -3
  78. package/backend/src/flowent/channels/__pycache__/__init__.cpython-313.pyc +0 -0
  79. package/backend/src/flowent/channels/__pycache__/telegram.cpython-313.pyc +0 -0
  80. package/backend/src/flowent/channels/telegram.py +0 -615
  81. package/backend/src/flowent/config.py +0 -14
  82. package/backend/src/flowent/dev.py +0 -3
  83. package/backend/src/flowent/events.py +0 -157
  84. package/backend/src/flowent/graph_runtime.py +0 -60
  85. package/backend/src/flowent/graph_service.py +0 -2508
  86. package/backend/src/flowent/image_assets.py +0 -356
  87. package/backend/src/flowent/mcp_service.py +0 -1918
  88. package/backend/src/flowent/model_metadata.py +0 -102
  89. package/backend/src/flowent/models/__init__.py +0 -125
  90. package/backend/src/flowent/models/__pycache__/__init__.cpython-313.pyc +0 -0
  91. package/backend/src/flowent/models/__pycache__/agent.cpython-313.pyc +0 -0
  92. package/backend/src/flowent/models/__pycache__/base.cpython-313.pyc +0 -0
  93. package/backend/src/flowent/models/__pycache__/blueprint.cpython-313.pyc +0 -0
  94. package/backend/src/flowent/models/__pycache__/content.cpython-313.pyc +0 -0
  95. package/backend/src/flowent/models/__pycache__/delta.cpython-313.pyc +0 -0
  96. package/backend/src/flowent/models/__pycache__/event.cpython-313.pyc +0 -0
  97. package/backend/src/flowent/models/__pycache__/graph.cpython-313.pyc +0 -0
  98. package/backend/src/flowent/models/__pycache__/history.cpython-313.pyc +0 -0
  99. package/backend/src/flowent/models/__pycache__/llm.cpython-313.pyc +0 -0
  100. package/backend/src/flowent/models/__pycache__/message.cpython-313.pyc +0 -0
  101. package/backend/src/flowent/models/__pycache__/tab.cpython-313.pyc +0 -0
  102. package/backend/src/flowent/models/__pycache__/todo.cpython-313.pyc +0 -0
  103. package/backend/src/flowent/models/agent.py +0 -34
  104. package/backend/src/flowent/models/base.py +0 -24
  105. package/backend/src/flowent/models/blueprint.py +0 -176
  106. package/backend/src/flowent/models/content.py +0 -164
  107. package/backend/src/flowent/models/delta.py +0 -44
  108. package/backend/src/flowent/models/event.py +0 -51
  109. package/backend/src/flowent/models/graph.py +0 -472
  110. package/backend/src/flowent/models/history.py +0 -272
  111. package/backend/src/flowent/models/llm.py +0 -62
  112. package/backend/src/flowent/models/message.py +0 -33
  113. package/backend/src/flowent/models/tab.py +0 -85
  114. package/backend/src/flowent/models/todo.py +0 -10
  115. package/backend/src/flowent/network.py +0 -146
  116. package/backend/src/flowent/observability_service.py +0 -218
  117. package/backend/src/flowent/prompts/__init__.py +0 -67
  118. package/backend/src/flowent/prompts/__pycache__/__init__.cpython-313.pyc +0 -0
  119. package/backend/src/flowent/prompts/__pycache__/common.cpython-313.pyc +0 -0
  120. package/backend/src/flowent/prompts/__pycache__/steward.cpython-313.pyc +0 -0
  121. package/backend/src/flowent/prompts/common.py +0 -250
  122. package/backend/src/flowent/prompts/steward.py +0 -64
  123. package/backend/src/flowent/providers/__init__.py +0 -23
  124. package/backend/src/flowent/providers/__pycache__/__init__.cpython-313.pyc +0 -0
  125. package/backend/src/flowent/providers/__pycache__/anthropic.cpython-313.pyc +0 -0
  126. package/backend/src/flowent/providers/__pycache__/base_url.cpython-313.pyc +0 -0
  127. package/backend/src/flowent/providers/__pycache__/configuration.cpython-313.pyc +0 -0
  128. package/backend/src/flowent/providers/__pycache__/content.cpython-313.pyc +0 -0
  129. package/backend/src/flowent/providers/__pycache__/errors.cpython-313.pyc +0 -0
  130. package/backend/src/flowent/providers/__pycache__/gateway.cpython-313.pyc +0 -0
  131. package/backend/src/flowent/providers/__pycache__/headers.cpython-313.pyc +0 -0
  132. package/backend/src/flowent/providers/__pycache__/management.cpython-313.pyc +0 -0
  133. package/backend/src/flowent/providers/__pycache__/openai.cpython-313.pyc +0 -0
  134. package/backend/src/flowent/providers/__pycache__/openai_responses.cpython-313.pyc +0 -0
  135. package/backend/src/flowent/providers/__pycache__/registry.cpython-313.pyc +0 -0
  136. package/backend/src/flowent/providers/__pycache__/sse.cpython-313.pyc +0 -0
  137. package/backend/src/flowent/providers/__pycache__/thinking.cpython-313.pyc +0 -0
  138. package/backend/src/flowent/providers/anthropic.py +0 -468
  139. package/backend/src/flowent/providers/base_url.py +0 -60
  140. package/backend/src/flowent/providers/configuration.py +0 -189
  141. package/backend/src/flowent/providers/content.py +0 -122
  142. package/backend/src/flowent/providers/errors.py +0 -223
  143. package/backend/src/flowent/providers/gateway.py +0 -169
  144. package/backend/src/flowent/providers/gemini.py +0 -447
  145. package/backend/src/flowent/providers/headers.py +0 -20
  146. package/backend/src/flowent/providers/management.py +0 -96
  147. package/backend/src/flowent/providers/ollama.py +0 -293
  148. package/backend/src/flowent/providers/openai.py +0 -422
  149. package/backend/src/flowent/providers/openai_responses.py +0 -655
  150. package/backend/src/flowent/providers/registry.py +0 -144
  151. package/backend/src/flowent/providers/sse.py +0 -31
  152. package/backend/src/flowent/providers/thinking.py +0 -79
  153. package/backend/src/flowent/registry.py +0 -73
  154. package/backend/src/flowent/role_management.py +0 -267
  155. package/backend/src/flowent/routes/__init__.py +0 -28
  156. package/backend/src/flowent/routes/__pycache__/__init__.cpython-313.pyc +0 -0
  157. package/backend/src/flowent/routes/__pycache__/access.cpython-313.pyc +0 -0
  158. package/backend/src/flowent/routes/__pycache__/assistant.cpython-313.pyc +0 -0
  159. package/backend/src/flowent/routes/__pycache__/image_assets.cpython-313.pyc +0 -0
  160. package/backend/src/flowent/routes/__pycache__/mcp.cpython-313.pyc +0 -0
  161. package/backend/src/flowent/routes/__pycache__/meta.cpython-313.pyc +0 -0
  162. package/backend/src/flowent/routes/__pycache__/nodes.cpython-313.pyc +0 -0
  163. package/backend/src/flowent/routes/__pycache__/prompts.cpython-313.pyc +0 -0
  164. package/backend/src/flowent/routes/__pycache__/providers_route.cpython-313.pyc +0 -0
  165. package/backend/src/flowent/routes/__pycache__/roles.cpython-313.pyc +0 -0
  166. package/backend/src/flowent/routes/__pycache__/settings.cpython-313.pyc +0 -0
  167. package/backend/src/flowent/routes/__pycache__/tabs.cpython-313.pyc +0 -0
  168. package/backend/src/flowent/routes/__pycache__/ws.cpython-313.pyc +0 -0
  169. package/backend/src/flowent/routes/access.py +0 -48
  170. package/backend/src/flowent/routes/assistant.py +0 -155
  171. package/backend/src/flowent/routes/image_assets.py +0 -33
  172. package/backend/src/flowent/routes/mcp.py +0 -125
  173. package/backend/src/flowent/routes/meta.py +0 -28
  174. package/backend/src/flowent/routes/nodes.py +0 -413
  175. package/backend/src/flowent/routes/prompts.py +0 -46
  176. package/backend/src/flowent/routes/providers_route.py +0 -365
  177. package/backend/src/flowent/routes/roles.py +0 -207
  178. package/backend/src/flowent/routes/settings.py +0 -328
  179. package/backend/src/flowent/routes/tabs.py +0 -310
  180. package/backend/src/flowent/routes/ws.py +0 -33
  181. package/backend/src/flowent/runtime.py +0 -165
  182. package/backend/src/flowent/security.py +0 -57
  183. package/backend/src/flowent/settings.py +0 -2518
  184. package/backend/src/flowent/settings_management.py +0 -298
  185. package/backend/src/flowent/state_db.py +0 -120
  186. package/backend/src/flowent/static/assets/AssistantPage-VBohhz4d.js +0 -1
  187. package/backend/src/flowent/static/assets/ChannelsPage-CIydPZA_.js +0 -1
  188. package/backend/src/flowent/static/assets/McpPage-CHPm2TPY.js +0 -7
  189. package/backend/src/flowent/static/assets/PageScaffold-DteOA8V7.js +0 -1
  190. package/backend/src/flowent/static/assets/PromptsPage-CSmJ3sZg.js +0 -1
  191. package/backend/src/flowent/static/assets/ProvidersPage-sl2jeG4e.js +0 -3
  192. package/backend/src/flowent/static/assets/RolesPage-DCe7W6Km.js +0 -1
  193. package/backend/src/flowent/static/assets/SettingsPage-Bix9e63E.js +0 -3
  194. package/backend/src/flowent/static/assets/ToolsPage-favNkj5C.js +0 -1
  195. package/backend/src/flowent/static/assets/WorkspaceCommandDialog-DRS6wiD6.js +0 -1
  196. package/backend/src/flowent/static/assets/WorkspacePage-KuaDjt_D.js +0 -3
  197. package/backend/src/flowent/static/assets/WorkspacePanels-BZxBw8M5.js +0 -1
  198. package/backend/src/flowent/static/assets/alert-dialog-DIBUCmqM.js +0 -1
  199. package/backend/src/flowent/static/assets/datetime-eJqd0V2S.js +0 -1
  200. package/backend/src/flowent/static/assets/dialog-BOvHIBrg.js +0 -1
  201. package/backend/src/flowent/static/assets/elk-worker.min-C9JGDOE-.js +0 -6312
  202. package/backend/src/flowent/static/assets/graph-vendor-CHpVij2M.css +0 -1
  203. package/backend/src/flowent/static/assets/graph-vendor-DRq_-6fV.js +0 -7
  204. package/backend/src/flowent/static/assets/index-Biio-CoI.js +0 -10
  205. package/backend/src/flowent/static/assets/index-CmQvO7sl.css +0 -1
  206. package/backend/src/flowent/static/assets/layout.worker-jMHqAFbP.js +0 -24
  207. package/backend/src/flowent/static/assets/markdown-vendor-C9RtvaJh.js +0 -29
  208. package/backend/src/flowent/static/assets/modelParams-DcEhGnu0.js +0 -1
  209. package/backend/src/flowent/static/assets/react-vendor-mEs_JJxa.js +0 -9
  210. package/backend/src/flowent/static/assets/roles-BbIEIMeG.js +0 -1
  211. package/backend/src/flowent/static/assets/rolldown-runtime-BYbx6iT9.js +0 -1
  212. package/backend/src/flowent/static/assets/select-D9SwnlXF.js +0 -1
  213. package/backend/src/flowent/static/assets/surface-Bzr1FRG4.js +0 -1
  214. package/backend/src/flowent/static/assets/triState-DgLlKdRR.js +0 -1
  215. package/backend/src/flowent/static/assets/ui-vendor-UazN8rcv.js +0 -51
  216. package/backend/src/flowent/static/favicon.svg +0 -4
  217. package/backend/src/flowent/tools/__init__.py +0 -275
  218. package/backend/src/flowent/tools/__pycache__/__init__.cpython-313.pyc +0 -0
  219. package/backend/src/flowent/tools/__pycache__/connect.cpython-313.pyc +0 -0
  220. package/backend/src/flowent/tools/__pycache__/contacts.cpython-313.pyc +0 -0
  221. package/backend/src/flowent/tools/__pycache__/create_agent.cpython-313.pyc +0 -0
  222. package/backend/src/flowent/tools/__pycache__/create_tab.cpython-313.pyc +0 -0
  223. package/backend/src/flowent/tools/__pycache__/delete_tab.cpython-313.pyc +0 -0
  224. package/backend/src/flowent/tools/__pycache__/edit.cpython-313.pyc +0 -0
  225. package/backend/src/flowent/tools/__pycache__/exec.cpython-313.pyc +0 -0
  226. package/backend/src/flowent/tools/__pycache__/fetch.cpython-313.pyc +0 -0
  227. package/backend/src/flowent/tools/__pycache__/idle.cpython-313.pyc +0 -0
  228. package/backend/src/flowent/tools/__pycache__/list_roles.cpython-313.pyc +0 -0
  229. package/backend/src/flowent/tools/__pycache__/list_tabs.cpython-313.pyc +0 -0
  230. package/backend/src/flowent/tools/__pycache__/list_tools.cpython-313.pyc +0 -0
  231. package/backend/src/flowent/tools/__pycache__/manage_prompts.cpython-313.pyc +0 -0
  232. package/backend/src/flowent/tools/__pycache__/manage_providers.cpython-313.pyc +0 -0
  233. package/backend/src/flowent/tools/__pycache__/manage_roles.cpython-313.pyc +0 -0
  234. package/backend/src/flowent/tools/__pycache__/manage_settings.cpython-313.pyc +0 -0
  235. package/backend/src/flowent/tools/__pycache__/mcp.cpython-313.pyc +0 -0
  236. package/backend/src/flowent/tools/__pycache__/read.cpython-313.pyc +0 -0
  237. package/backend/src/flowent/tools/__pycache__/send.cpython-313.pyc +0 -0
  238. package/backend/src/flowent/tools/__pycache__/set_permissions.cpython-313.pyc +0 -0
  239. package/backend/src/flowent/tools/__pycache__/sleep.cpython-313.pyc +0 -0
  240. package/backend/src/flowent/tools/__pycache__/todo.cpython-313.pyc +0 -0
  241. package/backend/src/flowent/tools/connect.py +0 -100
  242. package/backend/src/flowent/tools/contacts.py +0 -22
  243. package/backend/src/flowent/tools/create_agent.py +0 -191
  244. package/backend/src/flowent/tools/create_tab.py +0 -61
  245. package/backend/src/flowent/tools/delete_tab.py +0 -39
  246. package/backend/src/flowent/tools/edit.py +0 -142
  247. package/backend/src/flowent/tools/exec.py +0 -118
  248. package/backend/src/flowent/tools/fetch.py +0 -85
  249. package/backend/src/flowent/tools/idle.py +0 -27
  250. package/backend/src/flowent/tools/list_roles.py +0 -75
  251. package/backend/src/flowent/tools/list_tabs.py +0 -100
  252. package/backend/src/flowent/tools/list_tools.py +0 -28
  253. package/backend/src/flowent/tools/manage_prompts.py +0 -102
  254. package/backend/src/flowent/tools/manage_providers.py +0 -220
  255. package/backend/src/flowent/tools/manage_roles.py +0 -275
  256. package/backend/src/flowent/tools/manage_settings.py +0 -364
  257. package/backend/src/flowent/tools/mcp.py +0 -199
  258. package/backend/src/flowent/tools/read.py +0 -152
  259. package/backend/src/flowent/tools/send.py +0 -68
  260. package/backend/src/flowent/tools/set_permissions.py +0 -99
  261. package/backend/src/flowent/tools/sleep.py +0 -41
  262. package/backend/src/flowent/tools/todo.py +0 -51
  263. package/backend/src/flowent/workspace_store.py +0 -479
  264. package/backend/tests/__init__.py +0 -0
  265. package/backend/tests/__pycache__/__init__.cpython-313.pyc +0 -0
  266. package/backend/tests/__pycache__/conftest.cpython-313-pytest-9.0.3.pyc +0 -0
  267. package/backend/tests/conftest.py +0 -6
  268. package/backend/tests/integration/api/__pycache__/conftest.cpython-313-pytest-9.0.3.pyc +0 -0
  269. package/backend/tests/integration/api/__pycache__/test_access_api.cpython-313-pytest-9.0.3.pyc +0 -0
  270. package/backend/tests/integration/api/__pycache__/test_assistant_api.cpython-313-pytest-9.0.3.pyc +0 -0
  271. package/backend/tests/integration/api/__pycache__/test_frontend_mounting.cpython-313-pytest-9.0.3.pyc +0 -0
  272. package/backend/tests/integration/api/__pycache__/test_mcp_api.cpython-313-pytest-9.0.3.pyc +0 -0
  273. package/backend/tests/integration/api/__pycache__/test_meta_api.cpython-313-pytest-9.0.3.pyc +0 -0
  274. package/backend/tests/integration/api/__pycache__/test_nodes_api.cpython-313-pytest-9.0.3.pyc +0 -0
  275. package/backend/tests/integration/api/__pycache__/test_prompts_api.cpython-313-pytest-9.0.3.pyc +0 -0
  276. package/backend/tests/integration/api/__pycache__/test_roles_api.cpython-313-pytest-9.0.3.pyc +0 -0
  277. package/backend/tests/integration/api/__pycache__/test_tabs_api.cpython-313-pytest-9.0.3.pyc +0 -0
  278. package/backend/tests/integration/api/conftest.py +0 -29
  279. package/backend/tests/integration/api/test_access_api.py +0 -182
  280. package/backend/tests/integration/api/test_assistant_api.py +0 -354
  281. package/backend/tests/integration/api/test_frontend_mounting.py +0 -61
  282. package/backend/tests/integration/api/test_mcp_api.py +0 -116
  283. package/backend/tests/integration/api/test_meta_api.py +0 -33
  284. package/backend/tests/integration/api/test_nodes_api.py +0 -722
  285. package/backend/tests/integration/api/test_prompts_api.py +0 -47
  286. package/backend/tests/integration/api/test_roles_api.py +0 -228
  287. package/backend/tests/integration/api/test_tabs_api.py +0 -802
  288. package/backend/tests/unit/__pycache__/test_access.cpython-313-pytest-9.0.3.pyc +0 -0
  289. package/backend/tests/unit/__pycache__/test_cli.cpython-313-pytest-9.0.3.pyc +0 -0
  290. package/backend/tests/unit/__pycache__/test_graph_runtime.cpython-313-pytest-9.0.3.pyc +0 -0
  291. package/backend/tests/unit/__pycache__/test_network.cpython-313-pytest-9.0.3.pyc +0 -0
  292. package/backend/tests/unit/__pycache__/test_state_sqlite_storage.cpython-313-pytest-9.0.3.pyc +0 -0
  293. package/backend/tests/unit/__pycache__/test_workspace_store.cpython-313-pytest-9.0.3.pyc +0 -0
  294. package/backend/tests/unit/agent/__pycache__/test_agent_public_api.cpython-313-pytest-9.0.3.pyc +0 -0
  295. package/backend/tests/unit/agent/__pycache__/test_agent_runtime.cpython-313-pytest-9.0.3.pyc +0 -0
  296. package/backend/tests/unit/agent/test_agent_public_api.py +0 -837
  297. package/backend/tests/unit/agent/test_agent_runtime.py +0 -2942
  298. package/backend/tests/unit/channels/__pycache__/test_telegram_channel.cpython-313-pytest-9.0.3.pyc +0 -0
  299. package/backend/tests/unit/channels/test_telegram_channel.py +0 -552
  300. package/backend/tests/unit/logging/__pycache__/test_logging.cpython-313-pytest-9.0.3.pyc +0 -0
  301. package/backend/tests/unit/logging/test_logging.py +0 -132
  302. package/backend/tests/unit/prompts/__pycache__/test_prompts.cpython-313-pytest-9.0.3.pyc +0 -0
  303. package/backend/tests/unit/prompts/test_prompts.py +0 -570
  304. package/backend/tests/unit/providers/__pycache__/test_anthropic_provider.cpython-313-pytest-9.0.3.pyc +0 -0
  305. package/backend/tests/unit/providers/__pycache__/test_errors.cpython-313-pytest-9.0.3.pyc +0 -0
  306. package/backend/tests/unit/providers/__pycache__/test_extract_delta_parts.cpython-313-pytest-9.0.3.pyc +0 -0
  307. package/backend/tests/unit/providers/__pycache__/test_openai_provider.cpython-313-pytest-9.0.3.pyc +0 -0
  308. package/backend/tests/unit/providers/__pycache__/test_openai_responses.cpython-313-pytest-9.0.3.pyc +0 -0
  309. package/backend/tests/unit/providers/__pycache__/test_provider_gateway.cpython-313-pytest-9.0.3.pyc +0 -0
  310. package/backend/tests/unit/providers/__pycache__/test_think_tag_parser.cpython-313-pytest-9.0.3.pyc +0 -0
  311. package/backend/tests/unit/providers/test_anthropic_provider.py +0 -185
  312. package/backend/tests/unit/providers/test_errors.py +0 -68
  313. package/backend/tests/unit/providers/test_extract_delta_parts.py +0 -22
  314. package/backend/tests/unit/providers/test_openai_provider.py +0 -139
  315. package/backend/tests/unit/providers/test_openai_responses.py +0 -402
  316. package/backend/tests/unit/providers/test_provider_gateway.py +0 -359
  317. package/backend/tests/unit/providers/test_think_tag_parser.py +0 -36
  318. package/backend/tests/unit/routes/__pycache__/test_prompts_routes.cpython-313-pytest-9.0.3.pyc +0 -0
  319. package/backend/tests/unit/routes/__pycache__/test_providers_route.cpython-313-pytest-9.0.3.pyc +0 -0
  320. package/backend/tests/unit/routes/__pycache__/test_roles_routes.cpython-313-pytest-9.0.3.pyc +0 -0
  321. package/backend/tests/unit/routes/__pycache__/test_settings_routes.cpython-313-pytest-9.0.3.pyc +0 -0
  322. package/backend/tests/unit/routes/test_prompts_routes.py +0 -104
  323. package/backend/tests/unit/routes/test_providers_route.py +0 -370
  324. package/backend/tests/unit/routes/test_roles_routes.py +0 -535
  325. package/backend/tests/unit/routes/test_settings_routes.py +0 -1142
  326. package/backend/tests/unit/runtime/__pycache__/test_bootstrap_runtime.cpython-313-pytest-9.0.3.pyc +0 -0
  327. package/backend/tests/unit/runtime/test_bootstrap_runtime.py +0 -1002
  328. package/backend/tests/unit/sandbox/__pycache__/test_sandbox_tools.cpython-313-pytest-9.0.3.pyc +0 -0
  329. package/backend/tests/unit/sandbox/test_sandbox_tools.py +0 -78
  330. package/backend/tests/unit/security/__pycache__/test_security.cpython-313-pytest-9.0.3.pyc +0 -0
  331. package/backend/tests/unit/security/test_security.py +0 -124
  332. package/backend/tests/unit/settings/__pycache__/test_settings_roles.cpython-313-pytest-9.0.3.pyc +0 -0
  333. package/backend/tests/unit/settings/test_settings_roles.py +0 -751
  334. package/backend/tests/unit/test_access.py +0 -45
  335. package/backend/tests/unit/test_cli.py +0 -124
  336. package/backend/tests/unit/test_graph_runtime.py +0 -72
  337. package/backend/tests/unit/test_network.py +0 -51
  338. package/backend/tests/unit/test_state_sqlite_storage.py +0 -159
  339. package/backend/tests/unit/test_workspace_store.py +0 -231
  340. package/backend/tests/unit/tools/__pycache__/test_connect_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  341. package/backend/tests/unit/tools/__pycache__/test_create_agent_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  342. package/backend/tests/unit/tools/__pycache__/test_delete_tab_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  343. package/backend/tests/unit/tools/__pycache__/test_edit_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  344. package/backend/tests/unit/tools/__pycache__/test_exec_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  345. package/backend/tests/unit/tools/__pycache__/test_fetch_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  346. package/backend/tests/unit/tools/__pycache__/test_manage_prompts_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  347. package/backend/tests/unit/tools/__pycache__/test_manage_providers_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  348. package/backend/tests/unit/tools/__pycache__/test_manage_roles_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  349. package/backend/tests/unit/tools/__pycache__/test_manage_settings_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  350. package/backend/tests/unit/tools/__pycache__/test_read_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  351. package/backend/tests/unit/tools/__pycache__/test_set_permissions_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  352. package/backend/tests/unit/tools/__pycache__/test_todo_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  353. package/backend/tests/unit/tools/__pycache__/test_tool_registry.cpython-313-pytest-9.0.3.pyc +0 -0
  354. package/backend/tests/unit/tools/test_connect_tool.py +0 -228
  355. package/backend/tests/unit/tools/test_create_agent_tool.py +0 -436
  356. package/backend/tests/unit/tools/test_delete_tab_tool.py +0 -116
  357. package/backend/tests/unit/tools/test_edit_tool.py +0 -115
  358. package/backend/tests/unit/tools/test_exec_tool.py +0 -81
  359. package/backend/tests/unit/tools/test_fetch_tool.py +0 -65
  360. package/backend/tests/unit/tools/test_manage_prompts_tool.py +0 -117
  361. package/backend/tests/unit/tools/test_manage_providers_tool.py +0 -460
  362. package/backend/tests/unit/tools/test_manage_roles_tool.py +0 -411
  363. package/backend/tests/unit/tools/test_manage_settings_tool.py +0 -611
  364. package/backend/tests/unit/tools/test_read_tool.py +0 -33
  365. package/backend/tests/unit/tools/test_set_permissions_tool.py +0 -595
  366. package/backend/tests/unit/tools/test_todo_tool.py +0 -37
  367. package/backend/tests/unit/tools/test_tool_registry.py +0 -194
  368. package/dist/frontend/assets/AssistantPage-VBohhz4d.js +0 -1
  369. package/dist/frontend/assets/ChannelsPage-CIydPZA_.js +0 -1
  370. package/dist/frontend/assets/McpPage-CHPm2TPY.js +0 -7
  371. package/dist/frontend/assets/PageScaffold-DteOA8V7.js +0 -1
  372. package/dist/frontend/assets/PromptsPage-CSmJ3sZg.js +0 -1
  373. package/dist/frontend/assets/ProvidersPage-sl2jeG4e.js +0 -3
  374. package/dist/frontend/assets/RolesPage-DCe7W6Km.js +0 -1
  375. package/dist/frontend/assets/SettingsPage-Bix9e63E.js +0 -3
  376. package/dist/frontend/assets/ToolsPage-favNkj5C.js +0 -1
  377. package/dist/frontend/assets/WorkspaceCommandDialog-DRS6wiD6.js +0 -1
  378. package/dist/frontend/assets/WorkspacePage-KuaDjt_D.js +0 -3
  379. package/dist/frontend/assets/WorkspacePanels-BZxBw8M5.js +0 -1
  380. package/dist/frontend/assets/alert-dialog-DIBUCmqM.js +0 -1
  381. package/dist/frontend/assets/datetime-eJqd0V2S.js +0 -1
  382. package/dist/frontend/assets/dialog-BOvHIBrg.js +0 -1
  383. package/dist/frontend/assets/elk-worker.min-C9JGDOE-.js +0 -6312
  384. package/dist/frontend/assets/graph-vendor-CHpVij2M.css +0 -1
  385. package/dist/frontend/assets/graph-vendor-DRq_-6fV.js +0 -7
  386. package/dist/frontend/assets/index-Biio-CoI.js +0 -10
  387. package/dist/frontend/assets/index-CmQvO7sl.css +0 -1
  388. package/dist/frontend/assets/layout.worker-jMHqAFbP.js +0 -24
  389. package/dist/frontend/assets/markdown-vendor-C9RtvaJh.js +0 -29
  390. package/dist/frontend/assets/modelParams-DcEhGnu0.js +0 -1
  391. package/dist/frontend/assets/react-vendor-mEs_JJxa.js +0 -9
  392. package/dist/frontend/assets/roles-BbIEIMeG.js +0 -1
  393. package/dist/frontend/assets/rolldown-runtime-BYbx6iT9.js +0 -1
  394. package/dist/frontend/assets/select-D9SwnlXF.js +0 -1
  395. package/dist/frontend/assets/surface-Bzr1FRG4.js +0 -1
  396. package/dist/frontend/assets/triState-DgLlKdRR.js +0 -1
  397. package/dist/frontend/assets/ui-vendor-UazN8rcv.js +0 -51
  398. package/dist/frontend/favicon.svg +0 -4
@@ -1,4 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
2
- <rect width="64" height="64" rx="12" fill="#111111" />
3
- <path fill="#ffffff" d="M18 16h31v8H27v10h18v8H27v16h-9z" />
4
- </svg>
@@ -1,275 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from abc import ABC, abstractmethod
4
- from typing import TYPE_CHECKING, Any
5
-
6
- if TYPE_CHECKING:
7
- from typing import ClassVar
8
-
9
- from flowent.agent import Agent
10
-
11
- MINIMUM_TOOLS = (
12
- "idle",
13
- "sleep",
14
- "todo",
15
- "contacts",
16
- "send",
17
- )
18
-
19
- MCP_BROWSING_TOOLS = (
20
- "list_mcp_resources",
21
- "list_mcp_resource_templates",
22
- "read_mcp_resource",
23
- "list_mcp_prompts",
24
- "get_mcp_prompt",
25
- )
26
-
27
- ASSISTANT_ONLY_TOOLS = frozenset(
28
- {
29
- "create_workflow",
30
- "delete_workflow",
31
- "list_workflows",
32
- "manage_providers",
33
- "manage_roles",
34
- "manage_settings",
35
- "manage_prompts",
36
- }
37
- )
38
-
39
- ASSISTANT_ONLY_MCP_TOOL_NAMES = frozenset(
40
- {
41
- "create_workflow",
42
- "create_workflows",
43
- "delete_workflow",
44
- "delete_workflows",
45
- "duplicate_workflow",
46
- "duplicate_workflows",
47
- "copy_workflow",
48
- "copy_workflows",
49
- "list_workflow",
50
- "list_workflows",
51
- "select_workflow",
52
- "select_workflows",
53
- "switch_workflow",
54
- "switch_workflows",
55
- "manage_provider",
56
- "manage_providers",
57
- "manage_role",
58
- "manage_roles",
59
- "manage_setting",
60
- "manage_settings",
61
- "manage_prompt",
62
- "manage_prompts",
63
- }
64
- )
65
-
66
-
67
- def is_assistant_only_tool_name(tool_name: str) -> bool:
68
- return tool_name in ASSISTANT_ONLY_TOOLS
69
-
70
-
71
- def is_assistant_only_mcp_tool_name(tool_name: str) -> bool:
72
- normalized = tool_name.strip().lower().replace("-", "_")
73
- candidate = (
74
- normalized.rsplit("__", 1)[-1] if normalized.startswith("mcp__") else normalized
75
- )
76
- return (
77
- normalized in ASSISTANT_ONLY_MCP_TOOL_NAMES
78
- or candidate in ASSISTANT_ONLY_MCP_TOOL_NAMES
79
- )
80
-
81
-
82
- class Tool(ABC):
83
- name: str
84
- description: str
85
- parameters: ClassVar[dict[str, Any]]
86
- agent_visible: ClassVar[bool] = True
87
- llm_visible: ClassVar[bool] = True
88
-
89
- @abstractmethod
90
- def execute(
91
- self, agent: Agent, args: dict[str, Any], **kwargs: Any
92
- ) -> str | None: ...
93
-
94
- def to_schema(self) -> dict[str, Any]:
95
- return {
96
- "type": "function",
97
- "function": {
98
- "name": self.name,
99
- "description": self.description,
100
- "parameters": self.parameters,
101
- },
102
- }
103
-
104
-
105
- def re_raise_interrupt(agent: Agent, exc: BaseException) -> None:
106
- from flowent.agent import InterruptRequestedError
107
-
108
- if isinstance(exc, InterruptRequestedError) or agent.is_interrupt_requested():
109
- raise InterruptRequestedError() from exc
110
-
111
-
112
- class ToolRegistry:
113
- def __init__(self) -> None:
114
- self._tools: dict[str, Tool] = {}
115
-
116
- def register(self, tool: Tool) -> None:
117
- self._tools[tool.name] = tool
118
-
119
- def get(self, name: str) -> Tool | None:
120
- tool = self._tools.get(name)
121
- if tool is not None:
122
- return tool
123
- from flowent.mcp_service import mcp_service
124
- from flowent.tools.mcp import DynamicMCPTool
125
-
126
- descriptor = mcp_service.get_dynamic_tool_descriptor(name)
127
- if descriptor is None:
128
- return None
129
- return DynamicMCPTool(descriptor=descriptor)
130
-
131
- def list_tools(self, *, agent_visible_only: bool = False) -> list[Tool]:
132
- tools = list(self._tools.values())
133
- from flowent.mcp_service import mcp_service
134
- from flowent.tools.mcp import DynamicMCPTool
135
-
136
- dynamic_tools = [
137
- DynamicMCPTool(descriptor=descriptor)
138
- for descriptor in mcp_service.list_discovered_tools()
139
- ]
140
- tools.extend(dynamic_tools)
141
- if not agent_visible_only:
142
- return tools
143
- return [tool for tool in tools if tool.agent_visible]
144
-
145
- def get_tools_for_agent(self, agent: Agent) -> list[Tool]:
146
- from flowent.mcp_service import mcp_service
147
- from flowent.models import NodeType
148
- from flowent.settings import find_role, get_settings
149
- from flowent.tools.mcp import DynamicMCPTool
150
-
151
- allowed = set(agent.config.tools) | set(MINIMUM_TOOLS)
152
- if agent.node_type != NodeType.ASSISTANT:
153
- allowed -= ASSISTANT_ONLY_TOOLS
154
- visible_tools = [
155
- t for t in self._tools.values() if t.name in allowed and t.llm_visible
156
- ]
157
- role = find_role(get_settings(), agent.config.role_name or "")
158
- excluded = set(role.excluded_tools) if role is not None else set()
159
- dynamic_tools = [
160
- DynamicMCPTool(descriptor=descriptor)
161
- for descriptor in mcp_service.list_agent_dynamic_tools(agent)
162
- if descriptor.fully_qualified_id in allowed
163
- and descriptor.fully_qualified_id not in excluded
164
- and (
165
- agent.node_type == NodeType.ASSISTANT
166
- or not is_assistant_only_mcp_tool_name(descriptor.tool_name)
167
- )
168
- ]
169
- return [*visible_tools, *dynamic_tools]
170
-
171
- def get_tools_schema(self, agent: Agent) -> list[dict[str, Any]]:
172
- return [t.to_schema() for t in self.get_tools_for_agent(agent)]
173
-
174
-
175
- def build_tool_registry() -> ToolRegistry:
176
- from flowent.tools.connect import ConnectTool
177
- from flowent.tools.contacts import ContactsTool
178
- from flowent.tools.create_agent import CreateAgentTool
179
- from flowent.tools.create_tab import CreateTabTool
180
- from flowent.tools.delete_tab import DeleteTabTool
181
- from flowent.tools.edit import EditTool
182
- from flowent.tools.exec import ExecTool
183
- from flowent.tools.fetch import FetchTool
184
- from flowent.tools.idle import IdleTool
185
- from flowent.tools.list_roles import ListRolesTool
186
- from flowent.tools.list_tabs import ListTabsTool
187
- from flowent.tools.list_tools import ListToolsTool
188
- from flowent.tools.manage_prompts import ManagePromptsTool
189
- from flowent.tools.manage_providers import ManageProvidersTool
190
- from flowent.tools.manage_roles import ManageRolesTool
191
- from flowent.tools.manage_settings import ManageSettingsTool
192
- from flowent.tools.mcp import (
193
- GetMCPPromptTool,
194
- ListMCPPromptsTool,
195
- ListMCPResourcesTool,
196
- ListMCPResourceTemplatesTool,
197
- ReadMCPResourceTool,
198
- )
199
- from flowent.tools.read import ReadTool
200
- from flowent.tools.send import SendTool
201
- from flowent.tools.set_permissions import SetPermissionsTool
202
- from flowent.tools.sleep import SleepTool
203
- from flowent.tools.todo import TodoTool
204
-
205
- reg = ToolRegistry()
206
- for tool_cls in [
207
- IdleTool,
208
- SleepTool,
209
- TodoTool,
210
- ContactsTool,
211
- SendTool,
212
- CreateTabTool,
213
- DeleteTabTool,
214
- SetPermissionsTool,
215
- CreateAgentTool,
216
- ConnectTool,
217
- ManageProvidersTool,
218
- ManageRolesTool,
219
- ManageSettingsTool,
220
- ManagePromptsTool,
221
- ReadTool,
222
- EditTool,
223
- ExecTool,
224
- FetchTool,
225
- ListRolesTool,
226
- ListTabsTool,
227
- ListToolsTool,
228
- ListMCPResourcesTool,
229
- ListMCPResourceTemplatesTool,
230
- ReadMCPResourceTool,
231
- ListMCPPromptsTool,
232
- GetMCPPromptTool,
233
- ]:
234
- reg.register(tool_cls()) # type: ignore[abstract]
235
- return reg
236
-
237
-
238
- def list_agent_visible_tool_descriptors(
239
- *,
240
- include_assistant_only: bool = True,
241
- ) -> list[dict[str, Any]]:
242
- registry = build_tool_registry()
243
- from flowent.mcp_service import mcp_service
244
-
245
- descriptors: list[dict[str, Any]] = []
246
- for tool in registry.list_tools(agent_visible_only=True):
247
- if tool.name.startswith("mcp__"):
248
- continue
249
- if not include_assistant_only and is_assistant_only_tool_name(tool.name):
250
- continue
251
- schema = tool.to_schema()
252
- function = schema.get("function")
253
- parameters = (
254
- function.get("parameters")
255
- if isinstance(function, dict)
256
- else {"type": "object", "properties": {}, "required": []}
257
- )
258
- descriptors.append(
259
- {
260
- "name": tool.name,
261
- "description": tool.description,
262
- "parameters": parameters,
263
- "source": "builtin",
264
- }
265
- )
266
- for descriptor in mcp_service.list_discovered_tool_descriptors():
267
- tool_name = descriptor.get("tool_name")
268
- if (
269
- not include_assistant_only
270
- and isinstance(tool_name, str)
271
- and is_assistant_only_mcp_tool_name(tool_name)
272
- ):
273
- continue
274
- descriptors.append(descriptor)
275
- return descriptors
@@ -1,100 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import json
4
- from typing import TYPE_CHECKING, Any, ClassVar
5
-
6
- from flowent.models import NodeType
7
- from flowent.tools import Tool
8
-
9
- if TYPE_CHECKING:
10
- from flowent.agent import Agent
11
-
12
-
13
- class ConnectTool(Tool):
14
- name = "connect"
15
- description = (
16
- "Create a directed workflow edge between two nodes in the same workflow."
17
- )
18
- parameters: ClassVar[dict[str, Any]] = {
19
- "type": "object",
20
- "properties": {
21
- "from": {
22
- "type": "string",
23
- "description": "Source node UUID or name",
24
- },
25
- "to": {
26
- "type": "string",
27
- "description": "Target node UUID or name",
28
- },
29
- "from_port_key": {
30
- "type": "string",
31
- "description": "Source output port key",
32
- "default": "out",
33
- },
34
- "to_port_key": {
35
- "type": "string",
36
- "description": "Target input port key",
37
- "default": "in",
38
- },
39
- },
40
- "required": ["from", "to"],
41
- }
42
-
43
- def execute(self, agent: Agent, args: dict[str, Any], **_kwargs: Any) -> str:
44
- from flowent.graph_service import (
45
- create_edge,
46
- is_tab_leader,
47
- resolve_workflow_node_ref,
48
- )
49
-
50
- from_ref = args.get("from")
51
- to_ref = args.get("to")
52
- from_port_key = args.get("from_port_key", "out")
53
- to_port_key = args.get("to_port_key", "in")
54
-
55
- if not isinstance(from_ref, str) or not from_ref:
56
- return json.dumps({"error": "from must be a non-empty string"})
57
- if not isinstance(to_ref, str) or not to_ref:
58
- return json.dumps({"error": "to must be a non-empty string"})
59
- if not isinstance(from_port_key, str) or not from_port_key.strip():
60
- return json.dumps({"error": "from_port_key must be a non-empty string"})
61
- if not isinstance(to_port_key, str) or not to_port_key.strip():
62
- return json.dumps({"error": "to_port_key must be a non-empty string"})
63
- if not agent.config.tab_id:
64
- return json.dumps(
65
- {"error": "Only a workflow Leader may connect task nodes"}
66
- )
67
-
68
- source_id = resolve_workflow_node_ref(
69
- tab_id=agent.config.tab_id,
70
- node_ref=from_ref,
71
- )
72
- target_id = resolve_workflow_node_ref(
73
- tab_id=agent.config.tab_id,
74
- node_ref=to_ref,
75
- )
76
- if source_id is None:
77
- return json.dumps({"error": f"Node '{from_ref}' not found"})
78
- if target_id is None:
79
- return json.dumps({"error": f"Node '{to_ref}' not found"})
80
-
81
- if agent.node_type == NodeType.ASSISTANT:
82
- return json.dumps(
83
- {"error": "Assistant may not rewire a Workflow Graph directly"}
84
- )
85
- if not is_tab_leader(node_id=agent.uuid, tab_id=agent.config.tab_id):
86
- return json.dumps(
87
- {"error": "Only a workflow Leader may connect task nodes"}
88
- )
89
-
90
- edge, error = create_edge(
91
- tab_id=agent.config.tab_id,
92
- from_node_id=source_id,
93
- from_port_key=from_port_key,
94
- to_node_id=target_id,
95
- to_port_key=to_port_key,
96
- )
97
- if error is not None or edge is None:
98
- return json.dumps({"error": error or "Failed to connect nodes"})
99
-
100
- return json.dumps(edge.serialize())
@@ -1,22 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import json
4
- from typing import TYPE_CHECKING, Any, ClassVar
5
-
6
- from flowent.tools import Tool
7
-
8
- if TYPE_CHECKING:
9
- from flowent.agent import Agent
10
-
11
-
12
- class ContactsTool(Tool):
13
- name = "contacts"
14
- description = "List current contacts and output-port paths."
15
- parameters: ClassVar[dict[str, Any]] = {
16
- "type": "object",
17
- "properties": {},
18
- "required": [],
19
- }
20
-
21
- def execute(self, agent: Agent, args: dict[str, Any], **_kwargs: Any) -> str:
22
- return json.dumps({"contacts": agent.get_contacts_info()})
@@ -1,191 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import json
4
- from typing import TYPE_CHECKING, Any, ClassVar
5
-
6
- from flowent.graph_service import create_agent_node
7
- from flowent.models import NodeType
8
- from flowent.tools import Tool
9
-
10
- if TYPE_CHECKING:
11
- from flowent.agent import Agent
12
-
13
-
14
- class CreateAgentTool(Tool):
15
- name = "create_agent"
16
- description = "Create a new agent node inside your current workflow."
17
- parameters: ClassVar[dict[str, Any]] = {
18
- "type": "object",
19
- "properties": {
20
- "role_name": {
21
- "type": "string",
22
- "description": "Role assigned to the new agent",
23
- },
24
- "name": {
25
- "type": "string",
26
- "description": "Optional human-readable node name",
27
- },
28
- "tools": {
29
- "type": "array",
30
- "items": {"type": "string"},
31
- "description": "Optional additional tools",
32
- },
33
- "placement": {
34
- "type": "string",
35
- "enum": ["standalone", "after", "between"],
36
- "description": (
37
- "How to place the new agent inside the current workflow graph"
38
- ),
39
- "default": "standalone",
40
- },
41
- "after_node_id": {
42
- "type": "string",
43
- "description": "Anchor node id when placement is `after`",
44
- },
45
- "between_from_node_id": {
46
- "type": "string",
47
- "description": "Upstream node id when placement is `between`",
48
- },
49
- "between_to_node_id": {
50
- "type": "string",
51
- "description": "Downstream node id when placement is `between`",
52
- },
53
- },
54
- "required": ["role_name"],
55
- }
56
-
57
- def execute(self, agent: Agent, args: dict[str, Any], **_kwargs: Any) -> str:
58
- if "workflow_id" in args or "tab_id" in args:
59
- return json.dumps({"error": "create_agent does not accept workflow_id"})
60
- if "write_dirs" in args or "allow_network" in args:
61
- return json.dumps(
62
- {
63
- "error": (
64
- "create_agent uses the current workflow permissions; "
65
- "update the workflow permissions instead"
66
- )
67
- }
68
- )
69
- if "connect_to_creator" in args:
70
- return json.dumps(
71
- {
72
- "error": "create_agent no longer supports connect_to_creator; use placement"
73
- }
74
- )
75
- role_name = args.get("role_name")
76
- name = args.get("name")
77
- tools = args.get("tools", [])
78
- placement = args.get("placement", "standalone")
79
- after_node_id = args.get("after_node_id")
80
- between_from_node_id = args.get("between_from_node_id")
81
- between_to_node_id = args.get("between_to_node_id")
82
-
83
- if not isinstance(role_name, str) or not role_name.strip():
84
- return json.dumps({"error": "role_name must be a non-empty string"})
85
- if name is not None and not isinstance(name, str):
86
- return json.dumps({"error": "name must be a string"})
87
- if not isinstance(tools, list) or not all(
88
- isinstance(item, str) for item in tools
89
- ):
90
- return json.dumps({"error": "tools must be an array of strings"})
91
- if placement not in {"standalone", "after", "between"}:
92
- return json.dumps(
93
- {"error": "placement must be standalone, after, or between"}
94
- )
95
- if after_node_id is not None and not isinstance(after_node_id, str):
96
- return json.dumps({"error": "after_node_id must be a string"})
97
- if between_from_node_id is not None and not isinstance(
98
- between_from_node_id, str
99
- ):
100
- return json.dumps({"error": "between_from_node_id must be a string"})
101
- if between_to_node_id is not None and not isinstance(between_to_node_id, str):
102
- return json.dumps({"error": "between_to_node_id must be a string"})
103
- normalized_role_name = role_name.strip()
104
- if agent.node_type == NodeType.ASSISTANT:
105
- return json.dumps(
106
- {"error": "Assistant may not create ordinary task nodes directly"}
107
- )
108
- if not agent.config.tab_id:
109
- return json.dumps(
110
- {
111
- "error": "Only a node inside a workflow may create ordinary task nodes"
112
- }
113
- )
114
- if "create_agent" not in agent.config.tools:
115
- return json.dumps({"error": "create_agent is not enabled for this node"})
116
- from flowent.graph_service import get_tab_leader_id
117
-
118
- leader_id = get_tab_leader_id(agent.config.tab_id)
119
- if leader_id is None:
120
- return json.dumps(
121
- {"error": "Current workflow does not have a bound Leader"}
122
- )
123
- from flowent.registry import registry
124
- from flowent.workspace_store import workspace_store
125
-
126
- leader = registry.get(leader_id)
127
- leader_record = workspace_store.get_node_record(leader_id)
128
- if leader is None and leader_record is None:
129
- return json.dumps({"error": f"Leader '{leader_id}' was not found"})
130
-
131
- record, error = create_agent_node(
132
- role_name=normalized_role_name,
133
- tab_id=agent.config.tab_id,
134
- name=name,
135
- tools=tools,
136
- )
137
- if error is not None or record is None:
138
- return json.dumps({"error": error or "Failed to create agent"})
139
- if placement == "after":
140
- if not isinstance(after_node_id, str) or not after_node_id.strip():
141
- return json.dumps(
142
- {"error": "after_node_id is required when placement=after"}
143
- )
144
- from flowent.graph_service import create_edge
145
-
146
- edge, edge_error = create_edge(
147
- tab_id=agent.config.tab_id,
148
- from_node_id=after_node_id,
149
- to_node_id=record.id,
150
- )
151
- if edge_error is not None or edge is None:
152
- return json.dumps({"error": edge_error or "Failed to place agent"})
153
- elif placement == "between":
154
- if (
155
- not isinstance(between_from_node_id, str)
156
- or not between_from_node_id.strip()
157
- ):
158
- return json.dumps(
159
- {"error": "between_from_node_id is required when placement=between"}
160
- )
161
- if (
162
- not isinstance(between_to_node_id, str)
163
- or not between_to_node_id.strip()
164
- ):
165
- return json.dumps(
166
- {"error": "between_to_node_id is required when placement=between"}
167
- )
168
- from flowent.graph_service import create_edge, delete_edge
169
-
170
- deleted, delete_error = delete_edge(
171
- tab_id=agent.config.tab_id,
172
- from_node_id=between_from_node_id,
173
- to_node_id=between_to_node_id,
174
- )
175
- if delete_error is not None or deleted is None:
176
- return json.dumps({"error": delete_error or "Failed to place agent"})
177
- first_edge, first_error = create_edge(
178
- tab_id=agent.config.tab_id,
179
- from_node_id=between_from_node_id,
180
- to_node_id=record.id,
181
- )
182
- if first_error is not None or first_edge is None:
183
- return json.dumps({"error": first_error or "Failed to place agent"})
184
- second_edge, second_error = create_edge(
185
- tab_id=agent.config.tab_id,
186
- from_node_id=record.id,
187
- to_node_id=between_to_node_id,
188
- )
189
- if second_error is not None or second_edge is None:
190
- return json.dumps({"error": second_error or "Failed to place agent"})
191
- return json.dumps(record.serialize())