flowent 0.0.7 → 0.0.11

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 (387) hide show
  1. package/README.md +0 -3
  2. package/backend/README.md +0 -3
  3. package/backend/pyproject.toml +2 -8
  4. package/backend/src/flowent/__init__.py +6 -2
  5. package/backend/src/flowent/__pycache__/__init__.cpython-313.pyc +0 -0
  6. package/backend/src/flowent/__pycache__/agent.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 +213 -3173
  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 +376 -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 +477 -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__/cli.cpython-313.pyc +0 -0
  59. package/backend/src/flowent/__pycache__/config.cpython-313.pyc +0 -0
  60. package/backend/src/flowent/__pycache__/events.cpython-313.pyc +0 -0
  61. package/backend/src/flowent/__pycache__/graph_runtime.cpython-313.pyc +0 -0
  62. package/backend/src/flowent/__pycache__/graph_service.cpython-313.pyc +0 -0
  63. package/backend/src/flowent/__pycache__/image_assets.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 -2401
  86. package/backend/src/flowent/image_assets.py +0 -356
  87. package/backend/src/flowent/model_metadata.py +0 -102
  88. package/backend/src/flowent/models/__init__.py +0 -125
  89. package/backend/src/flowent/models/__pycache__/__init__.cpython-313.pyc +0 -0
  90. package/backend/src/flowent/models/__pycache__/agent.cpython-313.pyc +0 -0
  91. package/backend/src/flowent/models/__pycache__/base.cpython-313.pyc +0 -0
  92. package/backend/src/flowent/models/__pycache__/blueprint.cpython-313.pyc +0 -0
  93. package/backend/src/flowent/models/__pycache__/content.cpython-313.pyc +0 -0
  94. package/backend/src/flowent/models/__pycache__/delta.cpython-313.pyc +0 -0
  95. package/backend/src/flowent/models/__pycache__/event.cpython-313.pyc +0 -0
  96. package/backend/src/flowent/models/__pycache__/graph.cpython-313.pyc +0 -0
  97. package/backend/src/flowent/models/__pycache__/history.cpython-313.pyc +0 -0
  98. package/backend/src/flowent/models/__pycache__/llm.cpython-313.pyc +0 -0
  99. package/backend/src/flowent/models/__pycache__/message.cpython-313.pyc +0 -0
  100. package/backend/src/flowent/models/__pycache__/tab.cpython-313.pyc +0 -0
  101. package/backend/src/flowent/models/__pycache__/todo.cpython-313.pyc +0 -0
  102. package/backend/src/flowent/models/agent.py +0 -34
  103. package/backend/src/flowent/models/base.py +0 -24
  104. package/backend/src/flowent/models/blueprint.py +0 -176
  105. package/backend/src/flowent/models/content.py +0 -164
  106. package/backend/src/flowent/models/delta.py +0 -44
  107. package/backend/src/flowent/models/event.py +0 -51
  108. package/backend/src/flowent/models/graph.py +0 -472
  109. package/backend/src/flowent/models/history.py +0 -272
  110. package/backend/src/flowent/models/llm.py +0 -62
  111. package/backend/src/flowent/models/message.py +0 -33
  112. package/backend/src/flowent/models/tab.py +0 -85
  113. package/backend/src/flowent/models/todo.py +0 -10
  114. package/backend/src/flowent/network.py +0 -146
  115. package/backend/src/flowent/observability_service.py +0 -218
  116. package/backend/src/flowent/prompts/__init__.py +0 -67
  117. package/backend/src/flowent/prompts/__pycache__/__init__.cpython-313.pyc +0 -0
  118. package/backend/src/flowent/prompts/__pycache__/common.cpython-313.pyc +0 -0
  119. package/backend/src/flowent/prompts/__pycache__/steward.cpython-313.pyc +0 -0
  120. package/backend/src/flowent/prompts/common.py +0 -250
  121. package/backend/src/flowent/prompts/steward.py +0 -64
  122. package/backend/src/flowent/providers/__init__.py +0 -23
  123. package/backend/src/flowent/providers/__pycache__/__init__.cpython-313.pyc +0 -0
  124. package/backend/src/flowent/providers/__pycache__/anthropic.cpython-313.pyc +0 -0
  125. package/backend/src/flowent/providers/__pycache__/base_url.cpython-313.pyc +0 -0
  126. package/backend/src/flowent/providers/__pycache__/configuration.cpython-313.pyc +0 -0
  127. package/backend/src/flowent/providers/__pycache__/content.cpython-313.pyc +0 -0
  128. package/backend/src/flowent/providers/__pycache__/errors.cpython-313.pyc +0 -0
  129. package/backend/src/flowent/providers/__pycache__/gateway.cpython-313.pyc +0 -0
  130. package/backend/src/flowent/providers/__pycache__/headers.cpython-313.pyc +0 -0
  131. package/backend/src/flowent/providers/__pycache__/management.cpython-313.pyc +0 -0
  132. package/backend/src/flowent/providers/__pycache__/openai.cpython-313.pyc +0 -0
  133. package/backend/src/flowent/providers/__pycache__/openai_responses.cpython-313.pyc +0 -0
  134. package/backend/src/flowent/providers/__pycache__/registry.cpython-313.pyc +0 -0
  135. package/backend/src/flowent/providers/__pycache__/sse.cpython-313.pyc +0 -0
  136. package/backend/src/flowent/providers/__pycache__/thinking.cpython-313.pyc +0 -0
  137. package/backend/src/flowent/providers/anthropic.py +0 -468
  138. package/backend/src/flowent/providers/base_url.py +0 -60
  139. package/backend/src/flowent/providers/configuration.py +0 -189
  140. package/backend/src/flowent/providers/content.py +0 -122
  141. package/backend/src/flowent/providers/errors.py +0 -223
  142. package/backend/src/flowent/providers/gateway.py +0 -169
  143. package/backend/src/flowent/providers/gemini.py +0 -447
  144. package/backend/src/flowent/providers/headers.py +0 -20
  145. package/backend/src/flowent/providers/management.py +0 -96
  146. package/backend/src/flowent/providers/ollama.py +0 -293
  147. package/backend/src/flowent/providers/openai.py +0 -422
  148. package/backend/src/flowent/providers/openai_responses.py +0 -655
  149. package/backend/src/flowent/providers/registry.py +0 -144
  150. package/backend/src/flowent/providers/sse.py +0 -31
  151. package/backend/src/flowent/providers/thinking.py +0 -79
  152. package/backend/src/flowent/registry.py +0 -73
  153. package/backend/src/flowent/role_management.py +0 -270
  154. package/backend/src/flowent/routes/__init__.py +0 -26
  155. package/backend/src/flowent/routes/__pycache__/__init__.cpython-313.pyc +0 -0
  156. package/backend/src/flowent/routes/__pycache__/access.cpython-313.pyc +0 -0
  157. package/backend/src/flowent/routes/__pycache__/assistant.cpython-313.pyc +0 -0
  158. package/backend/src/flowent/routes/__pycache__/image_assets.cpython-313.pyc +0 -0
  159. package/backend/src/flowent/routes/__pycache__/meta.cpython-313.pyc +0 -0
  160. package/backend/src/flowent/routes/__pycache__/nodes.cpython-313.pyc +0 -0
  161. package/backend/src/flowent/routes/__pycache__/prompts.cpython-313.pyc +0 -0
  162. package/backend/src/flowent/routes/__pycache__/providers_route.cpython-313.pyc +0 -0
  163. package/backend/src/flowent/routes/__pycache__/roles.cpython-313.pyc +0 -0
  164. package/backend/src/flowent/routes/__pycache__/settings.cpython-313.pyc +0 -0
  165. package/backend/src/flowent/routes/__pycache__/tabs.cpython-313.pyc +0 -0
  166. package/backend/src/flowent/routes/__pycache__/ws.cpython-313.pyc +0 -0
  167. package/backend/src/flowent/routes/access.py +0 -48
  168. package/backend/src/flowent/routes/assistant.py +0 -158
  169. package/backend/src/flowent/routes/image_assets.py +0 -33
  170. package/backend/src/flowent/routes/meta.py +0 -28
  171. package/backend/src/flowent/routes/nodes.py +0 -423
  172. package/backend/src/flowent/routes/prompts.py +0 -46
  173. package/backend/src/flowent/routes/providers_route.py +0 -365
  174. package/backend/src/flowent/routes/roles.py +0 -207
  175. package/backend/src/flowent/routes/settings.py +0 -379
  176. package/backend/src/flowent/routes/tabs.py +0 -298
  177. package/backend/src/flowent/routes/ws.py +0 -33
  178. package/backend/src/flowent/runtime.py +0 -160
  179. package/backend/src/flowent/security.py +0 -37
  180. package/backend/src/flowent/settings.py +0 -2112
  181. package/backend/src/flowent/settings_management.py +0 -394
  182. package/backend/src/flowent/state_db.py +0 -108
  183. package/backend/src/flowent/static/assets/AssistantPage-BW7XAd9I.js +0 -1
  184. package/backend/src/flowent/static/assets/ChannelsPage-tCJHgt6m.js +0 -1
  185. package/backend/src/flowent/static/assets/PageScaffold-f6g2l7XN.js +0 -1
  186. package/backend/src/flowent/static/assets/PromptsPage-C3Sxn2D7.js +0 -1
  187. package/backend/src/flowent/static/assets/ProvidersPage-BfmdXmNt.js +0 -3
  188. package/backend/src/flowent/static/assets/RolesPage-DET8wO4r.js +0 -1
  189. package/backend/src/flowent/static/assets/SettingsPage-D-g3deMm.js +0 -3
  190. package/backend/src/flowent/static/assets/ToolsPage-CDmtE2g4.js +0 -1
  191. package/backend/src/flowent/static/assets/WorkspacePage-AZsJ0sD0.js +0 -3
  192. package/backend/src/flowent/static/assets/WorkspacePanels-CteCjolX.js +0 -1
  193. package/backend/src/flowent/static/assets/alert-dialog-Duorp_S-.js +0 -1
  194. package/backend/src/flowent/static/assets/dialog-C3ixjGjN.js +0 -1
  195. package/backend/src/flowent/static/assets/elk-worker.min-C9JGDOE-.js +0 -6312
  196. package/backend/src/flowent/static/assets/graph-vendor-CHpVij2M.css +0 -1
  197. package/backend/src/flowent/static/assets/graph-vendor-DRq_-6fV.js +0 -7
  198. package/backend/src/flowent/static/assets/index--o_0fv0N.css +0 -1
  199. package/backend/src/flowent/static/assets/index-C9HuekJm.js +0 -10
  200. package/backend/src/flowent/static/assets/layout.worker-jMHqAFbP.js +0 -24
  201. package/backend/src/flowent/static/assets/markdown-vendor-C9RtvaJh.js +0 -29
  202. package/backend/src/flowent/static/assets/modelParams-DmnF2hwR.js +0 -1
  203. package/backend/src/flowent/static/assets/providerTypes-DT3Ahwl_.js +0 -1
  204. package/backend/src/flowent/static/assets/react-vendor-mEs_JJxa.js +0 -9
  205. package/backend/src/flowent/static/assets/roles-CuRT_chR.js +0 -1
  206. package/backend/src/flowent/static/assets/rolldown-runtime-BYbx6iT9.js +0 -1
  207. package/backend/src/flowent/static/assets/select-DCfeNu-F.js +0 -1
  208. package/backend/src/flowent/static/assets/surface-pWwG5ogx.js +0 -1
  209. package/backend/src/flowent/static/assets/ui-vendor-C5pJa8N7.js +0 -51
  210. package/backend/src/flowent/static/assets/useAppRoute-FgSHBKhV.js +0 -1
  211. package/backend/src/flowent/static/favicon.svg +0 -4
  212. package/backend/src/flowent/tools/__init__.py +0 -176
  213. package/backend/src/flowent/tools/__pycache__/__init__.cpython-313.pyc +0 -0
  214. package/backend/src/flowent/tools/__pycache__/connect.cpython-313.pyc +0 -0
  215. package/backend/src/flowent/tools/__pycache__/contacts.cpython-313.pyc +0 -0
  216. package/backend/src/flowent/tools/__pycache__/create_agent.cpython-313.pyc +0 -0
  217. package/backend/src/flowent/tools/__pycache__/create_tab.cpython-313.pyc +0 -0
  218. package/backend/src/flowent/tools/__pycache__/delete_tab.cpython-313.pyc +0 -0
  219. package/backend/src/flowent/tools/__pycache__/edit.cpython-313.pyc +0 -0
  220. package/backend/src/flowent/tools/__pycache__/exec.cpython-313.pyc +0 -0
  221. package/backend/src/flowent/tools/__pycache__/fetch.cpython-313.pyc +0 -0
  222. package/backend/src/flowent/tools/__pycache__/idle.cpython-313.pyc +0 -0
  223. package/backend/src/flowent/tools/__pycache__/list_roles.cpython-313.pyc +0 -0
  224. package/backend/src/flowent/tools/__pycache__/list_tabs.cpython-313.pyc +0 -0
  225. package/backend/src/flowent/tools/__pycache__/list_tools.cpython-313.pyc +0 -0
  226. package/backend/src/flowent/tools/__pycache__/manage_prompts.cpython-313.pyc +0 -0
  227. package/backend/src/flowent/tools/__pycache__/manage_providers.cpython-313.pyc +0 -0
  228. package/backend/src/flowent/tools/__pycache__/manage_roles.cpython-313.pyc +0 -0
  229. package/backend/src/flowent/tools/__pycache__/manage_settings.cpython-313.pyc +0 -0
  230. package/backend/src/flowent/tools/__pycache__/read.cpython-313.pyc +0 -0
  231. package/backend/src/flowent/tools/__pycache__/send.cpython-313.pyc +0 -0
  232. package/backend/src/flowent/tools/__pycache__/set_permissions.cpython-313.pyc +0 -0
  233. package/backend/src/flowent/tools/__pycache__/sleep.cpython-313.pyc +0 -0
  234. package/backend/src/flowent/tools/__pycache__/todo.cpython-313.pyc +0 -0
  235. package/backend/src/flowent/tools/connect.py +0 -100
  236. package/backend/src/flowent/tools/contacts.py +0 -22
  237. package/backend/src/flowent/tools/create_agent.py +0 -191
  238. package/backend/src/flowent/tools/create_tab.py +0 -61
  239. package/backend/src/flowent/tools/delete_tab.py +0 -39
  240. package/backend/src/flowent/tools/edit.py +0 -142
  241. package/backend/src/flowent/tools/exec.py +0 -118
  242. package/backend/src/flowent/tools/fetch.py +0 -85
  243. package/backend/src/flowent/tools/idle.py +0 -27
  244. package/backend/src/flowent/tools/list_roles.py +0 -68
  245. package/backend/src/flowent/tools/list_tabs.py +0 -100
  246. package/backend/src/flowent/tools/list_tools.py +0 -28
  247. package/backend/src/flowent/tools/manage_prompts.py +0 -102
  248. package/backend/src/flowent/tools/manage_providers.py +0 -220
  249. package/backend/src/flowent/tools/manage_roles.py +0 -275
  250. package/backend/src/flowent/tools/manage_settings.py +0 -326
  251. package/backend/src/flowent/tools/read.py +0 -152
  252. package/backend/src/flowent/tools/send.py +0 -68
  253. package/backend/src/flowent/tools/set_permissions.py +0 -99
  254. package/backend/src/flowent/tools/sleep.py +0 -41
  255. package/backend/src/flowent/tools/todo.py +0 -51
  256. package/backend/src/flowent/workspace_store.py +0 -479
  257. package/backend/tests/__init__.py +0 -0
  258. package/backend/tests/__pycache__/__init__.cpython-313.pyc +0 -0
  259. package/backend/tests/__pycache__/conftest.cpython-313-pytest-9.0.3.pyc +0 -0
  260. package/backend/tests/conftest.py +0 -6
  261. package/backend/tests/integration/api/__pycache__/conftest.cpython-313-pytest-9.0.3.pyc +0 -0
  262. package/backend/tests/integration/api/__pycache__/test_access_api.cpython-313-pytest-9.0.3.pyc +0 -0
  263. package/backend/tests/integration/api/__pycache__/test_assistant_api.cpython-313-pytest-9.0.3.pyc +0 -0
  264. package/backend/tests/integration/api/__pycache__/test_frontend_mounting.cpython-313-pytest-9.0.3.pyc +0 -0
  265. package/backend/tests/integration/api/__pycache__/test_meta_api.cpython-313-pytest-9.0.3.pyc +0 -0
  266. package/backend/tests/integration/api/__pycache__/test_nodes_api.cpython-313-pytest-9.0.3.pyc +0 -0
  267. package/backend/tests/integration/api/__pycache__/test_prompts_api.cpython-313-pytest-9.0.3.pyc +0 -0
  268. package/backend/tests/integration/api/__pycache__/test_roles_api.cpython-313-pytest-9.0.3.pyc +0 -0
  269. package/backend/tests/integration/api/__pycache__/test_tabs_api.cpython-313-pytest-9.0.3.pyc +0 -0
  270. package/backend/tests/integration/api/conftest.py +0 -29
  271. package/backend/tests/integration/api/test_access_api.py +0 -182
  272. package/backend/tests/integration/api/test_assistant_api.py +0 -422
  273. package/backend/tests/integration/api/test_frontend_mounting.py +0 -61
  274. package/backend/tests/integration/api/test_meta_api.py +0 -32
  275. package/backend/tests/integration/api/test_nodes_api.py +0 -787
  276. package/backend/tests/integration/api/test_prompts_api.py +0 -47
  277. package/backend/tests/integration/api/test_roles_api.py +0 -228
  278. package/backend/tests/integration/api/test_tabs_api.py +0 -688
  279. package/backend/tests/unit/__pycache__/test_access.cpython-313-pytest-9.0.3.pyc +0 -0
  280. package/backend/tests/unit/__pycache__/test_cli.cpython-313-pytest-9.0.3.pyc +0 -0
  281. package/backend/tests/unit/__pycache__/test_graph_runtime.cpython-313-pytest-9.0.3.pyc +0 -0
  282. package/backend/tests/unit/__pycache__/test_network.cpython-313-pytest-9.0.3.pyc +0 -0
  283. package/backend/tests/unit/__pycache__/test_state_sqlite_storage.cpython-313-pytest-9.0.3.pyc +0 -0
  284. package/backend/tests/unit/__pycache__/test_workspace_store.cpython-313-pytest-9.0.3.pyc +0 -0
  285. package/backend/tests/unit/agent/__pycache__/test_agent_public_api.cpython-313-pytest-9.0.3.pyc +0 -0
  286. package/backend/tests/unit/agent/__pycache__/test_agent_runtime.cpython-313-pytest-9.0.3.pyc +0 -0
  287. package/backend/tests/unit/agent/test_agent_public_api.py +0 -822
  288. package/backend/tests/unit/agent/test_agent_runtime.py +0 -3088
  289. package/backend/tests/unit/channels/__pycache__/test_telegram_channel.cpython-313-pytest-9.0.3.pyc +0 -0
  290. package/backend/tests/unit/channels/test_telegram_channel.py +0 -552
  291. package/backend/tests/unit/logging/__pycache__/test_logging.cpython-313-pytest-9.0.3.pyc +0 -0
  292. package/backend/tests/unit/logging/test_logging.py +0 -132
  293. package/backend/tests/unit/prompts/__pycache__/test_prompts.cpython-313-pytest-9.0.3.pyc +0 -0
  294. package/backend/tests/unit/prompts/test_prompts.py +0 -570
  295. package/backend/tests/unit/providers/__pycache__/test_anthropic_provider.cpython-313-pytest-9.0.3.pyc +0 -0
  296. package/backend/tests/unit/providers/__pycache__/test_errors.cpython-313-pytest-9.0.3.pyc +0 -0
  297. package/backend/tests/unit/providers/__pycache__/test_extract_delta_parts.cpython-313-pytest-9.0.3.pyc +0 -0
  298. package/backend/tests/unit/providers/__pycache__/test_openai_provider.cpython-313-pytest-9.0.3.pyc +0 -0
  299. package/backend/tests/unit/providers/__pycache__/test_openai_responses.cpython-313-pytest-9.0.3.pyc +0 -0
  300. package/backend/tests/unit/providers/__pycache__/test_provider_gateway.cpython-313-pytest-9.0.3.pyc +0 -0
  301. package/backend/tests/unit/providers/__pycache__/test_think_tag_parser.cpython-313-pytest-9.0.3.pyc +0 -0
  302. package/backend/tests/unit/providers/test_anthropic_provider.py +0 -185
  303. package/backend/tests/unit/providers/test_errors.py +0 -68
  304. package/backend/tests/unit/providers/test_extract_delta_parts.py +0 -22
  305. package/backend/tests/unit/providers/test_openai_provider.py +0 -139
  306. package/backend/tests/unit/providers/test_openai_responses.py +0 -402
  307. package/backend/tests/unit/providers/test_provider_gateway.py +0 -359
  308. package/backend/tests/unit/providers/test_think_tag_parser.py +0 -36
  309. package/backend/tests/unit/routes/__pycache__/test_prompts_routes.cpython-313-pytest-9.0.3.pyc +0 -0
  310. package/backend/tests/unit/routes/__pycache__/test_providers_route.cpython-313-pytest-9.0.3.pyc +0 -0
  311. package/backend/tests/unit/routes/__pycache__/test_roles_routes.cpython-313-pytest-9.0.3.pyc +0 -0
  312. package/backend/tests/unit/routes/__pycache__/test_settings_routes.cpython-313-pytest-9.0.3.pyc +0 -0
  313. package/backend/tests/unit/routes/test_prompts_routes.py +0 -82
  314. package/backend/tests/unit/routes/test_providers_route.py +0 -370
  315. package/backend/tests/unit/routes/test_roles_routes.py +0 -539
  316. package/backend/tests/unit/routes/test_settings_routes.py +0 -1123
  317. package/backend/tests/unit/runtime/__pycache__/test_bootstrap_runtime.cpython-313-pytest-9.0.3.pyc +0 -0
  318. package/backend/tests/unit/runtime/test_bootstrap_runtime.py +0 -1002
  319. package/backend/tests/unit/sandbox/__pycache__/test_sandbox_tools.cpython-313-pytest-9.0.3.pyc +0 -0
  320. package/backend/tests/unit/sandbox/test_sandbox_tools.py +0 -78
  321. package/backend/tests/unit/security/__pycache__/test_security.cpython-313-pytest-9.0.3.pyc +0 -0
  322. package/backend/tests/unit/security/test_security.py +0 -124
  323. package/backend/tests/unit/settings/__pycache__/test_settings_roles.cpython-313-pytest-9.0.3.pyc +0 -0
  324. package/backend/tests/unit/settings/test_settings_roles.py +0 -703
  325. package/backend/tests/unit/test_access.py +0 -45
  326. package/backend/tests/unit/test_cli.py +0 -102
  327. package/backend/tests/unit/test_graph_runtime.py +0 -72
  328. package/backend/tests/unit/test_network.py +0 -51
  329. package/backend/tests/unit/test_state_sqlite_storage.py +0 -87
  330. package/backend/tests/unit/test_workspace_store.py +0 -228
  331. package/backend/tests/unit/tools/__pycache__/test_connect_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  332. package/backend/tests/unit/tools/__pycache__/test_create_agent_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  333. package/backend/tests/unit/tools/__pycache__/test_delete_tab_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  334. package/backend/tests/unit/tools/__pycache__/test_edit_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  335. package/backend/tests/unit/tools/__pycache__/test_exec_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  336. package/backend/tests/unit/tools/__pycache__/test_fetch_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  337. package/backend/tests/unit/tools/__pycache__/test_manage_prompts_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  338. package/backend/tests/unit/tools/__pycache__/test_manage_providers_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  339. package/backend/tests/unit/tools/__pycache__/test_manage_roles_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  340. package/backend/tests/unit/tools/__pycache__/test_manage_settings_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  341. package/backend/tests/unit/tools/__pycache__/test_read_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  342. package/backend/tests/unit/tools/__pycache__/test_set_permissions_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  343. package/backend/tests/unit/tools/__pycache__/test_todo_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  344. package/backend/tests/unit/tools/__pycache__/test_tool_registry.cpython-313-pytest-9.0.3.pyc +0 -0
  345. package/backend/tests/unit/tools/test_connect_tool.py +0 -228
  346. package/backend/tests/unit/tools/test_create_agent_tool.py +0 -404
  347. package/backend/tests/unit/tools/test_delete_tab_tool.py +0 -116
  348. package/backend/tests/unit/tools/test_edit_tool.py +0 -115
  349. package/backend/tests/unit/tools/test_exec_tool.py +0 -81
  350. package/backend/tests/unit/tools/test_fetch_tool.py +0 -65
  351. package/backend/tests/unit/tools/test_manage_prompts_tool.py +0 -92
  352. package/backend/tests/unit/tools/test_manage_providers_tool.py +0 -460
  353. package/backend/tests/unit/tools/test_manage_roles_tool.py +0 -411
  354. package/backend/tests/unit/tools/test_manage_settings_tool.py +0 -611
  355. package/backend/tests/unit/tools/test_read_tool.py +0 -33
  356. package/backend/tests/unit/tools/test_set_permissions_tool.py +0 -595
  357. package/backend/tests/unit/tools/test_todo_tool.py +0 -37
  358. package/backend/tests/unit/tools/test_tool_registry.py +0 -199
  359. package/dist/frontend/assets/AssistantPage-BW7XAd9I.js +0 -1
  360. package/dist/frontend/assets/ChannelsPage-tCJHgt6m.js +0 -1
  361. package/dist/frontend/assets/PageScaffold-f6g2l7XN.js +0 -1
  362. package/dist/frontend/assets/PromptsPage-C3Sxn2D7.js +0 -1
  363. package/dist/frontend/assets/ProvidersPage-BfmdXmNt.js +0 -3
  364. package/dist/frontend/assets/RolesPage-DET8wO4r.js +0 -1
  365. package/dist/frontend/assets/SettingsPage-D-g3deMm.js +0 -3
  366. package/dist/frontend/assets/ToolsPage-CDmtE2g4.js +0 -1
  367. package/dist/frontend/assets/WorkspacePage-AZsJ0sD0.js +0 -3
  368. package/dist/frontend/assets/WorkspacePanels-CteCjolX.js +0 -1
  369. package/dist/frontend/assets/alert-dialog-Duorp_S-.js +0 -1
  370. package/dist/frontend/assets/dialog-C3ixjGjN.js +0 -1
  371. package/dist/frontend/assets/elk-worker.min-C9JGDOE-.js +0 -6312
  372. package/dist/frontend/assets/graph-vendor-CHpVij2M.css +0 -1
  373. package/dist/frontend/assets/graph-vendor-DRq_-6fV.js +0 -7
  374. package/dist/frontend/assets/index--o_0fv0N.css +0 -1
  375. package/dist/frontend/assets/index-C9HuekJm.js +0 -10
  376. package/dist/frontend/assets/layout.worker-jMHqAFbP.js +0 -24
  377. package/dist/frontend/assets/markdown-vendor-C9RtvaJh.js +0 -29
  378. package/dist/frontend/assets/modelParams-DmnF2hwR.js +0 -1
  379. package/dist/frontend/assets/providerTypes-DT3Ahwl_.js +0 -1
  380. package/dist/frontend/assets/react-vendor-mEs_JJxa.js +0 -9
  381. package/dist/frontend/assets/roles-CuRT_chR.js +0 -1
  382. package/dist/frontend/assets/rolldown-runtime-BYbx6iT9.js +0 -1
  383. package/dist/frontend/assets/select-DCfeNu-F.js +0 -1
  384. package/dist/frontend/assets/surface-pWwG5ogx.js +0 -1
  385. package/dist/frontend/assets/ui-vendor-C5pJa8N7.js +0 -51
  386. package/dist/frontend/assets/useAppRoute-FgSHBKhV.js +0 -1
  387. package/dist/frontend/favicon.svg +0 -4
@@ -1 +0,0 @@
1
- import{a as e}from"./rolldown-runtime-BYbx6iT9.js";import{d as t}from"./graph-vendor-DRq_-6fV.js";import{D as n,b as r}from"./index-C9HuekJm.js";var i=e(t(),1);function a(){return window.location.pathname}function o(e){return window.addEventListener(`popstate`,e),window.addEventListener(r,e),()=>{window.removeEventListener(`popstate`,e),window.removeEventListener(r,e)}}function s(){return(0,i.useSyncExternalStore)(o,a,a),n(window.location)}export{s as t};
@@ -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,176 +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
- ASSISTANT_ONLY_TOOLS = frozenset(
20
- {
21
- "create_workflow",
22
- "delete_workflow",
23
- "list_workflows",
24
- "manage_providers",
25
- "manage_roles",
26
- "manage_settings",
27
- "manage_prompts",
28
- }
29
- )
30
-
31
-
32
- def is_assistant_only_tool_name(tool_name: str) -> bool:
33
- return tool_name in ASSISTANT_ONLY_TOOLS
34
-
35
-
36
- class Tool(ABC):
37
- name: str
38
- description: str
39
- parameters: ClassVar[dict[str, Any]]
40
- agent_visible: ClassVar[bool] = True
41
- llm_visible: ClassVar[bool] = True
42
-
43
- @abstractmethod
44
- def execute(
45
- self, agent: Agent, args: dict[str, Any], **kwargs: Any
46
- ) -> str | None: ...
47
-
48
- def to_schema(self) -> dict[str, Any]:
49
- return {
50
- "type": "function",
51
- "function": {
52
- "name": self.name,
53
- "description": self.description,
54
- "parameters": self.parameters,
55
- },
56
- }
57
-
58
-
59
- def re_raise_interrupt(agent: Agent, exc: BaseException) -> None:
60
- from flowent.agent import InterruptRequestedError
61
-
62
- if isinstance(exc, InterruptRequestedError) or agent.is_interrupt_requested():
63
- raise InterruptRequestedError() from exc
64
-
65
-
66
- class ToolRegistry:
67
- def __init__(self) -> None:
68
- self._tools: dict[str, Tool] = {}
69
-
70
- def register(self, tool: Tool) -> None:
71
- self._tools[tool.name] = tool
72
-
73
- def get(self, name: str) -> Tool | None:
74
- return self._tools.get(name)
75
-
76
- def list_tools(self, *, agent_visible_only: bool = False) -> list[Tool]:
77
- tools = list(self._tools.values())
78
- if not agent_visible_only:
79
- return tools
80
- return [tool for tool in tools if tool.agent_visible]
81
-
82
- def get_tools_for_agent(self, agent: Agent) -> list[Tool]:
83
- from flowent.models import NodeType
84
- from flowent.settings import find_role, get_settings
85
-
86
- allowed = set(agent.config.tools) | set(MINIMUM_TOOLS)
87
- if agent.node_type != NodeType.ASSISTANT:
88
- allowed -= ASSISTANT_ONLY_TOOLS
89
- visible_tools = [
90
- t for t in self._tools.values() if t.name in allowed and t.llm_visible
91
- ]
92
- role = find_role(get_settings(), agent.config.role_name or "")
93
- excluded = set(role.excluded_tools) if role is not None else set()
94
- return [tool for tool in visible_tools if tool.name not in excluded]
95
-
96
- def get_tools_schema(self, agent: Agent) -> list[dict[str, Any]]:
97
- return [t.to_schema() for t in self.get_tools_for_agent(agent)]
98
-
99
-
100
- def build_tool_registry() -> ToolRegistry:
101
- from flowent.tools.connect import ConnectTool
102
- from flowent.tools.contacts import ContactsTool
103
- from flowent.tools.create_agent import CreateAgentTool
104
- from flowent.tools.create_tab import CreateTabTool
105
- from flowent.tools.delete_tab import DeleteTabTool
106
- from flowent.tools.edit import EditTool
107
- from flowent.tools.exec import ExecTool
108
- from flowent.tools.fetch import FetchTool
109
- from flowent.tools.idle import IdleTool
110
- from flowent.tools.list_roles import ListRolesTool
111
- from flowent.tools.list_tabs import ListTabsTool
112
- from flowent.tools.list_tools import ListToolsTool
113
- from flowent.tools.manage_prompts import ManagePromptsTool
114
- from flowent.tools.manage_providers import ManageProvidersTool
115
- from flowent.tools.manage_roles import ManageRolesTool
116
- from flowent.tools.manage_settings import ManageSettingsTool
117
- from flowent.tools.read import ReadTool
118
- from flowent.tools.send import SendTool
119
- from flowent.tools.set_permissions import SetPermissionsTool
120
- from flowent.tools.sleep import SleepTool
121
- from flowent.tools.todo import TodoTool
122
-
123
- reg = ToolRegistry()
124
- for tool_cls in [
125
- IdleTool,
126
- SleepTool,
127
- TodoTool,
128
- ContactsTool,
129
- SendTool,
130
- CreateTabTool,
131
- DeleteTabTool,
132
- SetPermissionsTool,
133
- CreateAgentTool,
134
- ConnectTool,
135
- ManageProvidersTool,
136
- ManageRolesTool,
137
- ManageSettingsTool,
138
- ManagePromptsTool,
139
- ReadTool,
140
- EditTool,
141
- ExecTool,
142
- FetchTool,
143
- ListRolesTool,
144
- ListTabsTool,
145
- ListToolsTool,
146
- ]:
147
- reg.register(tool_cls()) # type: ignore[abstract]
148
- return reg
149
-
150
-
151
- def list_agent_visible_tool_descriptors(
152
- *,
153
- include_assistant_only: bool = True,
154
- ) -> list[dict[str, Any]]:
155
- registry = build_tool_registry()
156
-
157
- descriptors: list[dict[str, Any]] = []
158
- for tool in registry.list_tools(agent_visible_only=True):
159
- if not include_assistant_only and is_assistant_only_tool_name(tool.name):
160
- continue
161
- schema = tool.to_schema()
162
- function = schema.get("function")
163
- parameters = (
164
- function.get("parameters")
165
- if isinstance(function, dict)
166
- else {"type": "object", "properties": {}, "required": []}
167
- )
168
- descriptors.append(
169
- {
170
- "name": tool.name,
171
- "description": tool.description,
172
- "parameters": parameters,
173
- "source": "builtin",
174
- }
175
- )
176
- 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())
@@ -1,61 +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_tab, serialize_tab_summary
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 CreateTabTool(Tool):
15
- name = "create_workflow"
16
- description = "Create a new workflow with its own permission boundary."
17
- parameters: ClassVar[dict[str, Any]] = {
18
- "type": "object",
19
- "properties": {
20
- "title": {
21
- "type": "string",
22
- "description": "Human-readable workflow title",
23
- },
24
- "allow_network": {
25
- "type": "boolean",
26
- "description": "Whether this workflow should have network access (default False)",
27
- },
28
- "write_dirs": {
29
- "type": "array",
30
- "items": {"type": "string"},
31
- "description": "List of directory paths this workflow is allowed to write to",
32
- },
33
- },
34
- "required": ["title"],
35
- }
36
-
37
- def execute(self, agent: Agent, args: dict[str, Any], **_kwargs: Any) -> str:
38
- if agent.node_type != NodeType.ASSISTANT:
39
- return json.dumps({"error": "Only the Assistant may create workflows"})
40
-
41
- title = args.get("title")
42
- allow_network = args.get("allow_network", False)
43
- write_dirs = args.get("write_dirs", [])
44
- if not isinstance(title, str) or not title.strip():
45
- return json.dumps({"error": "title must be a non-empty string"})
46
- if not isinstance(allow_network, bool):
47
- return json.dumps({"error": "allow_network must be a boolean"})
48
- if not isinstance(write_dirs, list) or not all(
49
- isinstance(x, str) for x in write_dirs
50
- ):
51
- return json.dumps({"error": "write_dirs must be a list of strings"})
52
-
53
- try:
54
- tab = create_tab(
55
- title=title,
56
- allow_network=allow_network,
57
- write_dirs=write_dirs,
58
- )
59
- except ValueError as exc:
60
- return json.dumps({"error": str(exc)})
61
- return json.dumps(serialize_tab_summary(tab))
@@ -1,39 +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 delete_tab
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 DeleteTabTool(Tool):
15
- name = "delete_workflow"
16
- description = "Delete a workflow and clean up its graph."
17
- parameters: ClassVar[dict[str, Any]] = {
18
- "type": "object",
19
- "properties": {
20
- "workflow_id": {
21
- "type": "string",
22
- "description": "ID of the workflow to delete",
23
- }
24
- },
25
- "required": ["workflow_id"],
26
- }
27
-
28
- def execute(self, agent: Agent, args: dict[str, Any], **_kwargs: Any) -> str:
29
- if agent.node_type != NodeType.ASSISTANT:
30
- return json.dumps({"error": "Only the Assistant may delete workflows"})
31
-
32
- workflow_id = args.get("workflow_id")
33
- if not isinstance(workflow_id, str) or not workflow_id.strip():
34
- return json.dumps({"error": "workflow_id must be a non-empty string"})
35
-
36
- deleted, error = delete_tab(tab_id=workflow_id.strip())
37
- if error is not None or deleted is None:
38
- return json.dumps({"error": error or "Failed to delete workflow"})
39
- return json.dumps(deleted)