flowent 0.0.7 → 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 (386) 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/__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 +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 +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__/model_metadata.cpython-313.pyc +0 -0
  64. package/backend/src/flowent/__pycache__/network.cpython-313.pyc +0 -0
  65. package/backend/src/flowent/__pycache__/observability_service.cpython-313.pyc +0 -0
  66. package/backend/src/flowent/__pycache__/registry.cpython-313.pyc +0 -0
  67. package/backend/src/flowent/__pycache__/role_management.cpython-313.pyc +0 -0
  68. package/backend/src/flowent/__pycache__/runtime.cpython-313.pyc +0 -0
  69. package/backend/src/flowent/__pycache__/security.cpython-313.pyc +0 -0
  70. package/backend/src/flowent/__pycache__/settings.cpython-313.pyc +0 -0
  71. package/backend/src/flowent/__pycache__/settings_management.cpython-313.pyc +0 -0
  72. package/backend/src/flowent/__pycache__/state_db.cpython-313.pyc +0 -0
  73. package/backend/src/flowent/__pycache__/workspace_store.cpython-313.pyc +0 -0
  74. package/backend/src/flowent/access.py +0 -247
  75. package/backend/src/flowent/assistant_commands.py +0 -115
  76. package/backend/src/flowent/channels/__init__.py +0 -3
  77. package/backend/src/flowent/channels/__pycache__/__init__.cpython-313.pyc +0 -0
  78. package/backend/src/flowent/channels/__pycache__/telegram.cpython-313.pyc +0 -0
  79. package/backend/src/flowent/channels/telegram.py +0 -615
  80. package/backend/src/flowent/config.py +0 -14
  81. package/backend/src/flowent/dev.py +0 -3
  82. package/backend/src/flowent/events.py +0 -157
  83. package/backend/src/flowent/graph_runtime.py +0 -60
  84. package/backend/src/flowent/graph_service.py +0 -2401
  85. package/backend/src/flowent/image_assets.py +0 -356
  86. package/backend/src/flowent/model_metadata.py +0 -102
  87. package/backend/src/flowent/models/__init__.py +0 -125
  88. package/backend/src/flowent/models/__pycache__/__init__.cpython-313.pyc +0 -0
  89. package/backend/src/flowent/models/__pycache__/agent.cpython-313.pyc +0 -0
  90. package/backend/src/flowent/models/__pycache__/base.cpython-313.pyc +0 -0
  91. package/backend/src/flowent/models/__pycache__/blueprint.cpython-313.pyc +0 -0
  92. package/backend/src/flowent/models/__pycache__/content.cpython-313.pyc +0 -0
  93. package/backend/src/flowent/models/__pycache__/delta.cpython-313.pyc +0 -0
  94. package/backend/src/flowent/models/__pycache__/event.cpython-313.pyc +0 -0
  95. package/backend/src/flowent/models/__pycache__/graph.cpython-313.pyc +0 -0
  96. package/backend/src/flowent/models/__pycache__/history.cpython-313.pyc +0 -0
  97. package/backend/src/flowent/models/__pycache__/llm.cpython-313.pyc +0 -0
  98. package/backend/src/flowent/models/__pycache__/message.cpython-313.pyc +0 -0
  99. package/backend/src/flowent/models/__pycache__/tab.cpython-313.pyc +0 -0
  100. package/backend/src/flowent/models/__pycache__/todo.cpython-313.pyc +0 -0
  101. package/backend/src/flowent/models/agent.py +0 -34
  102. package/backend/src/flowent/models/base.py +0 -24
  103. package/backend/src/flowent/models/blueprint.py +0 -176
  104. package/backend/src/flowent/models/content.py +0 -164
  105. package/backend/src/flowent/models/delta.py +0 -44
  106. package/backend/src/flowent/models/event.py +0 -51
  107. package/backend/src/flowent/models/graph.py +0 -472
  108. package/backend/src/flowent/models/history.py +0 -272
  109. package/backend/src/flowent/models/llm.py +0 -62
  110. package/backend/src/flowent/models/message.py +0 -33
  111. package/backend/src/flowent/models/tab.py +0 -85
  112. package/backend/src/flowent/models/todo.py +0 -10
  113. package/backend/src/flowent/network.py +0 -146
  114. package/backend/src/flowent/observability_service.py +0 -218
  115. package/backend/src/flowent/prompts/__init__.py +0 -67
  116. package/backend/src/flowent/prompts/__pycache__/__init__.cpython-313.pyc +0 -0
  117. package/backend/src/flowent/prompts/__pycache__/common.cpython-313.pyc +0 -0
  118. package/backend/src/flowent/prompts/__pycache__/steward.cpython-313.pyc +0 -0
  119. package/backend/src/flowent/prompts/common.py +0 -250
  120. package/backend/src/flowent/prompts/steward.py +0 -64
  121. package/backend/src/flowent/providers/__init__.py +0 -23
  122. package/backend/src/flowent/providers/__pycache__/__init__.cpython-313.pyc +0 -0
  123. package/backend/src/flowent/providers/__pycache__/anthropic.cpython-313.pyc +0 -0
  124. package/backend/src/flowent/providers/__pycache__/base_url.cpython-313.pyc +0 -0
  125. package/backend/src/flowent/providers/__pycache__/configuration.cpython-313.pyc +0 -0
  126. package/backend/src/flowent/providers/__pycache__/content.cpython-313.pyc +0 -0
  127. package/backend/src/flowent/providers/__pycache__/errors.cpython-313.pyc +0 -0
  128. package/backend/src/flowent/providers/__pycache__/gateway.cpython-313.pyc +0 -0
  129. package/backend/src/flowent/providers/__pycache__/headers.cpython-313.pyc +0 -0
  130. package/backend/src/flowent/providers/__pycache__/management.cpython-313.pyc +0 -0
  131. package/backend/src/flowent/providers/__pycache__/openai.cpython-313.pyc +0 -0
  132. package/backend/src/flowent/providers/__pycache__/openai_responses.cpython-313.pyc +0 -0
  133. package/backend/src/flowent/providers/__pycache__/registry.cpython-313.pyc +0 -0
  134. package/backend/src/flowent/providers/__pycache__/sse.cpython-313.pyc +0 -0
  135. package/backend/src/flowent/providers/__pycache__/thinking.cpython-313.pyc +0 -0
  136. package/backend/src/flowent/providers/anthropic.py +0 -468
  137. package/backend/src/flowent/providers/base_url.py +0 -60
  138. package/backend/src/flowent/providers/configuration.py +0 -189
  139. package/backend/src/flowent/providers/content.py +0 -122
  140. package/backend/src/flowent/providers/errors.py +0 -223
  141. package/backend/src/flowent/providers/gateway.py +0 -169
  142. package/backend/src/flowent/providers/gemini.py +0 -447
  143. package/backend/src/flowent/providers/headers.py +0 -20
  144. package/backend/src/flowent/providers/management.py +0 -96
  145. package/backend/src/flowent/providers/ollama.py +0 -293
  146. package/backend/src/flowent/providers/openai.py +0 -422
  147. package/backend/src/flowent/providers/openai_responses.py +0 -655
  148. package/backend/src/flowent/providers/registry.py +0 -144
  149. package/backend/src/flowent/providers/sse.py +0 -31
  150. package/backend/src/flowent/providers/thinking.py +0 -79
  151. package/backend/src/flowent/registry.py +0 -73
  152. package/backend/src/flowent/role_management.py +0 -270
  153. package/backend/src/flowent/routes/__init__.py +0 -26
  154. package/backend/src/flowent/routes/__pycache__/__init__.cpython-313.pyc +0 -0
  155. package/backend/src/flowent/routes/__pycache__/access.cpython-313.pyc +0 -0
  156. package/backend/src/flowent/routes/__pycache__/assistant.cpython-313.pyc +0 -0
  157. package/backend/src/flowent/routes/__pycache__/image_assets.cpython-313.pyc +0 -0
  158. package/backend/src/flowent/routes/__pycache__/meta.cpython-313.pyc +0 -0
  159. package/backend/src/flowent/routes/__pycache__/nodes.cpython-313.pyc +0 -0
  160. package/backend/src/flowent/routes/__pycache__/prompts.cpython-313.pyc +0 -0
  161. package/backend/src/flowent/routes/__pycache__/providers_route.cpython-313.pyc +0 -0
  162. package/backend/src/flowent/routes/__pycache__/roles.cpython-313.pyc +0 -0
  163. package/backend/src/flowent/routes/__pycache__/settings.cpython-313.pyc +0 -0
  164. package/backend/src/flowent/routes/__pycache__/tabs.cpython-313.pyc +0 -0
  165. package/backend/src/flowent/routes/__pycache__/ws.cpython-313.pyc +0 -0
  166. package/backend/src/flowent/routes/access.py +0 -48
  167. package/backend/src/flowent/routes/assistant.py +0 -158
  168. package/backend/src/flowent/routes/image_assets.py +0 -33
  169. package/backend/src/flowent/routes/meta.py +0 -28
  170. package/backend/src/flowent/routes/nodes.py +0 -423
  171. package/backend/src/flowent/routes/prompts.py +0 -46
  172. package/backend/src/flowent/routes/providers_route.py +0 -365
  173. package/backend/src/flowent/routes/roles.py +0 -207
  174. package/backend/src/flowent/routes/settings.py +0 -379
  175. package/backend/src/flowent/routes/tabs.py +0 -298
  176. package/backend/src/flowent/routes/ws.py +0 -33
  177. package/backend/src/flowent/runtime.py +0 -160
  178. package/backend/src/flowent/security.py +0 -37
  179. package/backend/src/flowent/settings.py +0 -2112
  180. package/backend/src/flowent/settings_management.py +0 -394
  181. package/backend/src/flowent/state_db.py +0 -108
  182. package/backend/src/flowent/static/assets/AssistantPage-BW7XAd9I.js +0 -1
  183. package/backend/src/flowent/static/assets/ChannelsPage-tCJHgt6m.js +0 -1
  184. package/backend/src/flowent/static/assets/PageScaffold-f6g2l7XN.js +0 -1
  185. package/backend/src/flowent/static/assets/PromptsPage-C3Sxn2D7.js +0 -1
  186. package/backend/src/flowent/static/assets/ProvidersPage-BfmdXmNt.js +0 -3
  187. package/backend/src/flowent/static/assets/RolesPage-DET8wO4r.js +0 -1
  188. package/backend/src/flowent/static/assets/SettingsPage-D-g3deMm.js +0 -3
  189. package/backend/src/flowent/static/assets/ToolsPage-CDmtE2g4.js +0 -1
  190. package/backend/src/flowent/static/assets/WorkspacePage-AZsJ0sD0.js +0 -3
  191. package/backend/src/flowent/static/assets/WorkspacePanels-CteCjolX.js +0 -1
  192. package/backend/src/flowent/static/assets/alert-dialog-Duorp_S-.js +0 -1
  193. package/backend/src/flowent/static/assets/dialog-C3ixjGjN.js +0 -1
  194. package/backend/src/flowent/static/assets/elk-worker.min-C9JGDOE-.js +0 -6312
  195. package/backend/src/flowent/static/assets/graph-vendor-CHpVij2M.css +0 -1
  196. package/backend/src/flowent/static/assets/graph-vendor-DRq_-6fV.js +0 -7
  197. package/backend/src/flowent/static/assets/index--o_0fv0N.css +0 -1
  198. package/backend/src/flowent/static/assets/index-C9HuekJm.js +0 -10
  199. package/backend/src/flowent/static/assets/layout.worker-jMHqAFbP.js +0 -24
  200. package/backend/src/flowent/static/assets/markdown-vendor-C9RtvaJh.js +0 -29
  201. package/backend/src/flowent/static/assets/modelParams-DmnF2hwR.js +0 -1
  202. package/backend/src/flowent/static/assets/providerTypes-DT3Ahwl_.js +0 -1
  203. package/backend/src/flowent/static/assets/react-vendor-mEs_JJxa.js +0 -9
  204. package/backend/src/flowent/static/assets/roles-CuRT_chR.js +0 -1
  205. package/backend/src/flowent/static/assets/rolldown-runtime-BYbx6iT9.js +0 -1
  206. package/backend/src/flowent/static/assets/select-DCfeNu-F.js +0 -1
  207. package/backend/src/flowent/static/assets/surface-pWwG5ogx.js +0 -1
  208. package/backend/src/flowent/static/assets/ui-vendor-C5pJa8N7.js +0 -51
  209. package/backend/src/flowent/static/assets/useAppRoute-FgSHBKhV.js +0 -1
  210. package/backend/src/flowent/static/favicon.svg +0 -4
  211. package/backend/src/flowent/tools/__init__.py +0 -176
  212. package/backend/src/flowent/tools/__pycache__/__init__.cpython-313.pyc +0 -0
  213. package/backend/src/flowent/tools/__pycache__/connect.cpython-313.pyc +0 -0
  214. package/backend/src/flowent/tools/__pycache__/contacts.cpython-313.pyc +0 -0
  215. package/backend/src/flowent/tools/__pycache__/create_agent.cpython-313.pyc +0 -0
  216. package/backend/src/flowent/tools/__pycache__/create_tab.cpython-313.pyc +0 -0
  217. package/backend/src/flowent/tools/__pycache__/delete_tab.cpython-313.pyc +0 -0
  218. package/backend/src/flowent/tools/__pycache__/edit.cpython-313.pyc +0 -0
  219. package/backend/src/flowent/tools/__pycache__/exec.cpython-313.pyc +0 -0
  220. package/backend/src/flowent/tools/__pycache__/fetch.cpython-313.pyc +0 -0
  221. package/backend/src/flowent/tools/__pycache__/idle.cpython-313.pyc +0 -0
  222. package/backend/src/flowent/tools/__pycache__/list_roles.cpython-313.pyc +0 -0
  223. package/backend/src/flowent/tools/__pycache__/list_tabs.cpython-313.pyc +0 -0
  224. package/backend/src/flowent/tools/__pycache__/list_tools.cpython-313.pyc +0 -0
  225. package/backend/src/flowent/tools/__pycache__/manage_prompts.cpython-313.pyc +0 -0
  226. package/backend/src/flowent/tools/__pycache__/manage_providers.cpython-313.pyc +0 -0
  227. package/backend/src/flowent/tools/__pycache__/manage_roles.cpython-313.pyc +0 -0
  228. package/backend/src/flowent/tools/__pycache__/manage_settings.cpython-313.pyc +0 -0
  229. package/backend/src/flowent/tools/__pycache__/read.cpython-313.pyc +0 -0
  230. package/backend/src/flowent/tools/__pycache__/send.cpython-313.pyc +0 -0
  231. package/backend/src/flowent/tools/__pycache__/set_permissions.cpython-313.pyc +0 -0
  232. package/backend/src/flowent/tools/__pycache__/sleep.cpython-313.pyc +0 -0
  233. package/backend/src/flowent/tools/__pycache__/todo.cpython-313.pyc +0 -0
  234. package/backend/src/flowent/tools/connect.py +0 -100
  235. package/backend/src/flowent/tools/contacts.py +0 -22
  236. package/backend/src/flowent/tools/create_agent.py +0 -191
  237. package/backend/src/flowent/tools/create_tab.py +0 -61
  238. package/backend/src/flowent/tools/delete_tab.py +0 -39
  239. package/backend/src/flowent/tools/edit.py +0 -142
  240. package/backend/src/flowent/tools/exec.py +0 -118
  241. package/backend/src/flowent/tools/fetch.py +0 -85
  242. package/backend/src/flowent/tools/idle.py +0 -27
  243. package/backend/src/flowent/tools/list_roles.py +0 -68
  244. package/backend/src/flowent/tools/list_tabs.py +0 -100
  245. package/backend/src/flowent/tools/list_tools.py +0 -28
  246. package/backend/src/flowent/tools/manage_prompts.py +0 -102
  247. package/backend/src/flowent/tools/manage_providers.py +0 -220
  248. package/backend/src/flowent/tools/manage_roles.py +0 -275
  249. package/backend/src/flowent/tools/manage_settings.py +0 -326
  250. package/backend/src/flowent/tools/read.py +0 -152
  251. package/backend/src/flowent/tools/send.py +0 -68
  252. package/backend/src/flowent/tools/set_permissions.py +0 -99
  253. package/backend/src/flowent/tools/sleep.py +0 -41
  254. package/backend/src/flowent/tools/todo.py +0 -51
  255. package/backend/src/flowent/workspace_store.py +0 -479
  256. package/backend/tests/__init__.py +0 -0
  257. package/backend/tests/__pycache__/__init__.cpython-313.pyc +0 -0
  258. package/backend/tests/__pycache__/conftest.cpython-313-pytest-9.0.3.pyc +0 -0
  259. package/backend/tests/conftest.py +0 -6
  260. package/backend/tests/integration/api/__pycache__/conftest.cpython-313-pytest-9.0.3.pyc +0 -0
  261. package/backend/tests/integration/api/__pycache__/test_access_api.cpython-313-pytest-9.0.3.pyc +0 -0
  262. package/backend/tests/integration/api/__pycache__/test_assistant_api.cpython-313-pytest-9.0.3.pyc +0 -0
  263. package/backend/tests/integration/api/__pycache__/test_frontend_mounting.cpython-313-pytest-9.0.3.pyc +0 -0
  264. package/backend/tests/integration/api/__pycache__/test_meta_api.cpython-313-pytest-9.0.3.pyc +0 -0
  265. package/backend/tests/integration/api/__pycache__/test_nodes_api.cpython-313-pytest-9.0.3.pyc +0 -0
  266. package/backend/tests/integration/api/__pycache__/test_prompts_api.cpython-313-pytest-9.0.3.pyc +0 -0
  267. package/backend/tests/integration/api/__pycache__/test_roles_api.cpython-313-pytest-9.0.3.pyc +0 -0
  268. package/backend/tests/integration/api/__pycache__/test_tabs_api.cpython-313-pytest-9.0.3.pyc +0 -0
  269. package/backend/tests/integration/api/conftest.py +0 -29
  270. package/backend/tests/integration/api/test_access_api.py +0 -182
  271. package/backend/tests/integration/api/test_assistant_api.py +0 -422
  272. package/backend/tests/integration/api/test_frontend_mounting.py +0 -61
  273. package/backend/tests/integration/api/test_meta_api.py +0 -32
  274. package/backend/tests/integration/api/test_nodes_api.py +0 -787
  275. package/backend/tests/integration/api/test_prompts_api.py +0 -47
  276. package/backend/tests/integration/api/test_roles_api.py +0 -228
  277. package/backend/tests/integration/api/test_tabs_api.py +0 -688
  278. package/backend/tests/unit/__pycache__/test_access.cpython-313-pytest-9.0.3.pyc +0 -0
  279. package/backend/tests/unit/__pycache__/test_cli.cpython-313-pytest-9.0.3.pyc +0 -0
  280. package/backend/tests/unit/__pycache__/test_graph_runtime.cpython-313-pytest-9.0.3.pyc +0 -0
  281. package/backend/tests/unit/__pycache__/test_network.cpython-313-pytest-9.0.3.pyc +0 -0
  282. package/backend/tests/unit/__pycache__/test_state_sqlite_storage.cpython-313-pytest-9.0.3.pyc +0 -0
  283. package/backend/tests/unit/__pycache__/test_workspace_store.cpython-313-pytest-9.0.3.pyc +0 -0
  284. package/backend/tests/unit/agent/__pycache__/test_agent_public_api.cpython-313-pytest-9.0.3.pyc +0 -0
  285. package/backend/tests/unit/agent/__pycache__/test_agent_runtime.cpython-313-pytest-9.0.3.pyc +0 -0
  286. package/backend/tests/unit/agent/test_agent_public_api.py +0 -822
  287. package/backend/tests/unit/agent/test_agent_runtime.py +0 -3088
  288. package/backend/tests/unit/channels/__pycache__/test_telegram_channel.cpython-313-pytest-9.0.3.pyc +0 -0
  289. package/backend/tests/unit/channels/test_telegram_channel.py +0 -552
  290. package/backend/tests/unit/logging/__pycache__/test_logging.cpython-313-pytest-9.0.3.pyc +0 -0
  291. package/backend/tests/unit/logging/test_logging.py +0 -132
  292. package/backend/tests/unit/prompts/__pycache__/test_prompts.cpython-313-pytest-9.0.3.pyc +0 -0
  293. package/backend/tests/unit/prompts/test_prompts.py +0 -570
  294. package/backend/tests/unit/providers/__pycache__/test_anthropic_provider.cpython-313-pytest-9.0.3.pyc +0 -0
  295. package/backend/tests/unit/providers/__pycache__/test_errors.cpython-313-pytest-9.0.3.pyc +0 -0
  296. package/backend/tests/unit/providers/__pycache__/test_extract_delta_parts.cpython-313-pytest-9.0.3.pyc +0 -0
  297. package/backend/tests/unit/providers/__pycache__/test_openai_provider.cpython-313-pytest-9.0.3.pyc +0 -0
  298. package/backend/tests/unit/providers/__pycache__/test_openai_responses.cpython-313-pytest-9.0.3.pyc +0 -0
  299. package/backend/tests/unit/providers/__pycache__/test_provider_gateway.cpython-313-pytest-9.0.3.pyc +0 -0
  300. package/backend/tests/unit/providers/__pycache__/test_think_tag_parser.cpython-313-pytest-9.0.3.pyc +0 -0
  301. package/backend/tests/unit/providers/test_anthropic_provider.py +0 -185
  302. package/backend/tests/unit/providers/test_errors.py +0 -68
  303. package/backend/tests/unit/providers/test_extract_delta_parts.py +0 -22
  304. package/backend/tests/unit/providers/test_openai_provider.py +0 -139
  305. package/backend/tests/unit/providers/test_openai_responses.py +0 -402
  306. package/backend/tests/unit/providers/test_provider_gateway.py +0 -359
  307. package/backend/tests/unit/providers/test_think_tag_parser.py +0 -36
  308. package/backend/tests/unit/routes/__pycache__/test_prompts_routes.cpython-313-pytest-9.0.3.pyc +0 -0
  309. package/backend/tests/unit/routes/__pycache__/test_providers_route.cpython-313-pytest-9.0.3.pyc +0 -0
  310. package/backend/tests/unit/routes/__pycache__/test_roles_routes.cpython-313-pytest-9.0.3.pyc +0 -0
  311. package/backend/tests/unit/routes/__pycache__/test_settings_routes.cpython-313-pytest-9.0.3.pyc +0 -0
  312. package/backend/tests/unit/routes/test_prompts_routes.py +0 -82
  313. package/backend/tests/unit/routes/test_providers_route.py +0 -370
  314. package/backend/tests/unit/routes/test_roles_routes.py +0 -539
  315. package/backend/tests/unit/routes/test_settings_routes.py +0 -1123
  316. package/backend/tests/unit/runtime/__pycache__/test_bootstrap_runtime.cpython-313-pytest-9.0.3.pyc +0 -0
  317. package/backend/tests/unit/runtime/test_bootstrap_runtime.py +0 -1002
  318. package/backend/tests/unit/sandbox/__pycache__/test_sandbox_tools.cpython-313-pytest-9.0.3.pyc +0 -0
  319. package/backend/tests/unit/sandbox/test_sandbox_tools.py +0 -78
  320. package/backend/tests/unit/security/__pycache__/test_security.cpython-313-pytest-9.0.3.pyc +0 -0
  321. package/backend/tests/unit/security/test_security.py +0 -124
  322. package/backend/tests/unit/settings/__pycache__/test_settings_roles.cpython-313-pytest-9.0.3.pyc +0 -0
  323. package/backend/tests/unit/settings/test_settings_roles.py +0 -703
  324. package/backend/tests/unit/test_access.py +0 -45
  325. package/backend/tests/unit/test_cli.py +0 -102
  326. package/backend/tests/unit/test_graph_runtime.py +0 -72
  327. package/backend/tests/unit/test_network.py +0 -51
  328. package/backend/tests/unit/test_state_sqlite_storage.py +0 -87
  329. package/backend/tests/unit/test_workspace_store.py +0 -228
  330. package/backend/tests/unit/tools/__pycache__/test_connect_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  331. package/backend/tests/unit/tools/__pycache__/test_create_agent_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  332. package/backend/tests/unit/tools/__pycache__/test_delete_tab_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  333. package/backend/tests/unit/tools/__pycache__/test_edit_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  334. package/backend/tests/unit/tools/__pycache__/test_exec_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  335. package/backend/tests/unit/tools/__pycache__/test_fetch_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  336. package/backend/tests/unit/tools/__pycache__/test_manage_prompts_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  337. package/backend/tests/unit/tools/__pycache__/test_manage_providers_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  338. package/backend/tests/unit/tools/__pycache__/test_manage_roles_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  339. package/backend/tests/unit/tools/__pycache__/test_manage_settings_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  340. package/backend/tests/unit/tools/__pycache__/test_read_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  341. package/backend/tests/unit/tools/__pycache__/test_set_permissions_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  342. package/backend/tests/unit/tools/__pycache__/test_todo_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  343. package/backend/tests/unit/tools/__pycache__/test_tool_registry.cpython-313-pytest-9.0.3.pyc +0 -0
  344. package/backend/tests/unit/tools/test_connect_tool.py +0 -228
  345. package/backend/tests/unit/tools/test_create_agent_tool.py +0 -404
  346. package/backend/tests/unit/tools/test_delete_tab_tool.py +0 -116
  347. package/backend/tests/unit/tools/test_edit_tool.py +0 -115
  348. package/backend/tests/unit/tools/test_exec_tool.py +0 -81
  349. package/backend/tests/unit/tools/test_fetch_tool.py +0 -65
  350. package/backend/tests/unit/tools/test_manage_prompts_tool.py +0 -92
  351. package/backend/tests/unit/tools/test_manage_providers_tool.py +0 -460
  352. package/backend/tests/unit/tools/test_manage_roles_tool.py +0 -411
  353. package/backend/tests/unit/tools/test_manage_settings_tool.py +0 -611
  354. package/backend/tests/unit/tools/test_read_tool.py +0 -33
  355. package/backend/tests/unit/tools/test_set_permissions_tool.py +0 -595
  356. package/backend/tests/unit/tools/test_todo_tool.py +0 -37
  357. package/backend/tests/unit/tools/test_tool_registry.py +0 -199
  358. package/dist/frontend/assets/AssistantPage-BW7XAd9I.js +0 -1
  359. package/dist/frontend/assets/ChannelsPage-tCJHgt6m.js +0 -1
  360. package/dist/frontend/assets/PageScaffold-f6g2l7XN.js +0 -1
  361. package/dist/frontend/assets/PromptsPage-C3Sxn2D7.js +0 -1
  362. package/dist/frontend/assets/ProvidersPage-BfmdXmNt.js +0 -3
  363. package/dist/frontend/assets/RolesPage-DET8wO4r.js +0 -1
  364. package/dist/frontend/assets/SettingsPage-D-g3deMm.js +0 -3
  365. package/dist/frontend/assets/ToolsPage-CDmtE2g4.js +0 -1
  366. package/dist/frontend/assets/WorkspacePage-AZsJ0sD0.js +0 -3
  367. package/dist/frontend/assets/WorkspacePanels-CteCjolX.js +0 -1
  368. package/dist/frontend/assets/alert-dialog-Duorp_S-.js +0 -1
  369. package/dist/frontend/assets/dialog-C3ixjGjN.js +0 -1
  370. package/dist/frontend/assets/elk-worker.min-C9JGDOE-.js +0 -6312
  371. package/dist/frontend/assets/graph-vendor-CHpVij2M.css +0 -1
  372. package/dist/frontend/assets/graph-vendor-DRq_-6fV.js +0 -7
  373. package/dist/frontend/assets/index--o_0fv0N.css +0 -1
  374. package/dist/frontend/assets/index-C9HuekJm.js +0 -10
  375. package/dist/frontend/assets/layout.worker-jMHqAFbP.js +0 -24
  376. package/dist/frontend/assets/markdown-vendor-C9RtvaJh.js +0 -29
  377. package/dist/frontend/assets/modelParams-DmnF2hwR.js +0 -1
  378. package/dist/frontend/assets/providerTypes-DT3Ahwl_.js +0 -1
  379. package/dist/frontend/assets/react-vendor-mEs_JJxa.js +0 -9
  380. package/dist/frontend/assets/roles-CuRT_chR.js +0 -1
  381. package/dist/frontend/assets/rolldown-runtime-BYbx6iT9.js +0 -1
  382. package/dist/frontend/assets/select-DCfeNu-F.js +0 -1
  383. package/dist/frontend/assets/surface-pWwG5ogx.js +0 -1
  384. package/dist/frontend/assets/ui-vendor-C5pJa8N7.js +0 -51
  385. package/dist/frontend/assets/useAppRoute-FgSHBKhV.js +0 -1
  386. package/dist/frontend/favicon.svg +0 -4
@@ -1,228 +0,0 @@
1
- import json
2
-
3
- import pytest
4
-
5
- from flowent.agent import Agent
6
- from flowent.graph_service import build_workflow_node_definition, create_tab
7
- from flowent.models import (
8
- AgentState,
9
- GraphNodeRecord,
10
- NodeConfig,
11
- NodeType,
12
- WorkflowNodeKind,
13
- )
14
- from flowent.registry import registry
15
- from flowent.tools.connect import ConnectTool
16
- from flowent.workspace_store import workspace_store
17
-
18
-
19
- @pytest.fixture(autouse=True)
20
- def reset_runtime_state(monkeypatch, tmp_path):
21
- import flowent.settings as settings_module
22
-
23
- settings_file = tmp_path / "settings.json"
24
- settings_file.write_text("{}", encoding="utf-8")
25
- monkeypatch.setattr(settings_module, "_SETTINGS_FILE", settings_file)
26
- monkeypatch.setattr(settings_module, "_cached_settings", None)
27
- registry.reset()
28
- workspace_store.reset_cache()
29
- yield
30
- registry.reset()
31
- workspace_store.reset_cache()
32
- monkeypatch.setattr(settings_module, "_cached_settings", None)
33
-
34
-
35
- def register_tab_agent(
36
- *,
37
- node_id: str,
38
- tab_id: str,
39
- name: str,
40
- role_name: str = "Worker",
41
- tools: list[str] | None = None,
42
- ) -> Agent:
43
- agent = Agent(
44
- NodeConfig(
45
- node_type=NodeType.AGENT,
46
- role_name=role_name,
47
- tab_id=tab_id,
48
- name=name,
49
- tools=list(tools or []),
50
- ),
51
- uuid=node_id,
52
- )
53
- registry.register(agent)
54
- workspace_store.upsert_node_record(
55
- GraphNodeRecord(
56
- id=node_id,
57
- config=agent.config,
58
- state=AgentState.INITIALIZING,
59
- )
60
- )
61
- tab = workspace_store.get_tab(tab_id)
62
- assert tab is not None
63
- tab.definition.nodes.append(
64
- build_workflow_node_definition(
65
- node_id=node_id,
66
- node_kind=WorkflowNodeKind.AGENT,
67
- config={"role_name": role_name, "name": name},
68
- )
69
- )
70
- workspace_store.upsert_tab(tab)
71
- return agent
72
-
73
-
74
- def register_graph_node(
75
- *,
76
- node_id: str,
77
- tab_id: str,
78
- node_type: WorkflowNodeKind,
79
- name: str,
80
- ) -> None:
81
- tab = workspace_store.get_tab(tab_id)
82
- assert tab is not None
83
- tab.definition.nodes.append(
84
- build_workflow_node_definition(
85
- node_id=node_id,
86
- node_kind=node_type,
87
- config={"name": name},
88
- )
89
- )
90
- workspace_store.upsert_tab(tab)
91
-
92
-
93
- def test_connect_tool_creates_directed_workflow_edge():
94
- tab = create_tab(title="Task")
95
- leader = Agent(
96
- NodeConfig(
97
- node_type=NodeType.AGENT,
98
- role_name="Conductor",
99
- tab_id=tab.id,
100
- name="Leader",
101
- tools=["connect"],
102
- ),
103
- uuid=tab.leader_id,
104
- )
105
- registry.register(leader)
106
- left = register_tab_agent(
107
- node_id="worker-a",
108
- tab_id=tab.id,
109
- name="Worker A",
110
- )
111
- right = register_tab_agent(
112
- node_id="worker-b",
113
- tab_id=tab.id,
114
- name="Worker B",
115
- )
116
-
117
- result = json.loads(
118
- ConnectTool().execute(
119
- leader,
120
- {
121
- "from": left.uuid,
122
- "to": right.uuid,
123
- "from_port_key": "out",
124
- "to_port_key": "in",
125
- },
126
- )
127
- )
128
-
129
- assert result["tab_id"] == tab.id
130
- assert result["from_node_id"] == "worker-a"
131
- assert result["from_port_key"] == "out"
132
- assert result["to_node_id"] == "worker-b"
133
- assert result["to_port_key"] == "in"
134
- assert "kind" not in result
135
- assert left.get_connections_snapshot() == []
136
- assert right.get_connections_snapshot() == []
137
- stored_edges = workspace_store.list_edges(tab.id)
138
- assert len(stored_edges) == 1
139
- assert stored_edges[0].from_node_id == "worker-a"
140
- assert stored_edges[0].to_node_id == "worker-b"
141
- assert stored_edges[0].from_port_key == "out"
142
- assert stored_edges[0].to_port_key == "in"
143
-
144
- duplicate_result = json.loads(
145
- ConnectTool().execute(
146
- leader,
147
- {
148
- "from": left.uuid,
149
- "to": right.uuid,
150
- },
151
- )
152
- )
153
- assert duplicate_result == {"error": "Duplicate edges are not allowed"}
154
-
155
-
156
- def test_connect_tool_resolves_non_agent_workflow_nodes_by_name():
157
- tab = create_tab(title="Task")
158
- leader = Agent(
159
- NodeConfig(
160
- node_type=NodeType.AGENT,
161
- role_name="Conductor",
162
- tab_id=tab.id,
163
- name="Leader",
164
- tools=["connect"],
165
- ),
166
- uuid=tab.leader_id,
167
- )
168
- registry.register(leader)
169
- register_tab_agent(
170
- node_id="worker-a",
171
- tab_id=tab.id,
172
- name="Worker A",
173
- )
174
- register_graph_node(
175
- node_id="code-a",
176
- tab_id=tab.id,
177
- node_type=WorkflowNodeKind.CODE,
178
- name="Formatter",
179
- )
180
-
181
- result = json.loads(
182
- ConnectTool().execute(
183
- leader,
184
- {
185
- "from": "Worker A",
186
- "to": "Formatter",
187
- },
188
- )
189
- )
190
-
191
- assert result["from_node_id"] == "worker-a"
192
- assert result["to_node_id"] == "code-a"
193
- assert "kind" not in result
194
-
195
-
196
- def test_connect_tool_rejects_leader_endpoints():
197
- tab = create_tab(title="Task")
198
- leader = Agent(
199
- NodeConfig(
200
- node_type=NodeType.AGENT,
201
- role_name="Conductor",
202
- tab_id=tab.id,
203
- name="Leader",
204
- tools=["connect"],
205
- ),
206
- uuid=tab.leader_id,
207
- )
208
- registry.register(leader)
209
- register_tab_agent(
210
- node_id="worker-a",
211
- tab_id=tab.id,
212
- name="Worker A",
213
- )
214
-
215
- result = json.loads(
216
- ConnectTool().execute(
217
- leader,
218
- {
219
- "from": leader.uuid,
220
- "to": "worker-a",
221
- },
222
- )
223
- )
224
-
225
- assert result == {
226
- "error": "Workflow Leader does not participate in Workflow Graph edges"
227
- }
228
- assert workspace_store.list_edges(tab.id) == []
@@ -1,404 +0,0 @@
1
- import json
2
-
3
- import pytest
4
-
5
- from flowent.agent import Agent
6
- from flowent.graph_service import create_tab
7
- from flowent.models import NodeConfig, NodeType
8
- from flowent.registry import registry
9
- from flowent.settings import CONDUCTOR_ROLE_NAME, RoleConfig, Settings
10
- from flowent.tools.create_agent import CreateAgentTool
11
- from flowent.workspace_store import workspace_store
12
-
13
-
14
- @pytest.fixture(autouse=True)
15
- def reset_runtime_state(monkeypatch, tmp_path):
16
- import flowent.settings as settings_module
17
-
18
- settings_file = tmp_path / "settings.json"
19
- settings_file.write_text("{}", encoding="utf-8")
20
- monkeypatch.setattr(settings_module, "_SETTINGS_FILE", settings_file)
21
- monkeypatch.setattr(settings_module, "_cached_settings", None)
22
- registry.reset()
23
- workspace_store.reset_cache()
24
- yield
25
- registry.reset()
26
- workspace_store.reset_cache()
27
- monkeypatch.setattr(settings_module, "_cached_settings", None)
28
-
29
-
30
- def test_leader_create_agent_defaults_to_current_tab_without_network_edge(
31
- monkeypatch,
32
- ):
33
- monkeypatch.setattr(
34
- "flowent.settings.get_settings",
35
- lambda: Settings(
36
- roles=[
37
- RoleConfig(
38
- name="Worker",
39
- system_prompt="Do work.",
40
- included_tools=["read"],
41
- )
42
- ]
43
- ),
44
- )
45
- tab = create_tab(title="Task")
46
-
47
- owner = Agent(
48
- NodeConfig(
49
- node_type=NodeType.AGENT,
50
- role_name="Conductor",
51
- tab_id=tab.id,
52
- tools=["create_agent"],
53
- write_dirs=["/tmp/workspace"],
54
- allow_network=False,
55
- ),
56
- uuid=tab.leader_id,
57
- )
58
- registry.register(owner)
59
-
60
- result = json.loads(
61
- CreateAgentTool().execute(
62
- owner,
63
- {
64
- "role_name": "Worker",
65
- "name": "Peer Worker",
66
- },
67
- )
68
- )
69
-
70
- assert result["config"]["tab_id"] == tab.id
71
- assert result["config"]["name"] == "Peer Worker"
72
- assert owner.get_connections_snapshot() == []
73
- assert workspace_store.list_edges(tab.id) == []
74
-
75
-
76
- def test_create_agent_places_new_agent_after_anchor(monkeypatch):
77
- monkeypatch.setattr(
78
- "flowent.settings.get_settings",
79
- lambda: Settings(
80
- roles=[
81
- RoleConfig(
82
- name="Worker",
83
- system_prompt="Do work.",
84
- included_tools=["read"],
85
- )
86
- ]
87
- ),
88
- )
89
- tab = create_tab(title="Task")
90
-
91
- owner = Agent(
92
- NodeConfig(
93
- node_type=NodeType.AGENT,
94
- role_name="Conductor",
95
- tab_id=tab.id,
96
- tools=["create_agent"],
97
- write_dirs=["/tmp/workspace"],
98
- allow_network=False,
99
- ),
100
- uuid=tab.leader_id,
101
- )
102
- registry.register(owner)
103
-
104
- anchor = json.loads(
105
- CreateAgentTool().execute(
106
- owner,
107
- {
108
- "role_name": "Worker",
109
- "name": "Anchor Worker",
110
- },
111
- )
112
- )
113
- result = json.loads(
114
- CreateAgentTool().execute(
115
- owner,
116
- {
117
- "role_name": "Worker",
118
- "name": "Placed Worker",
119
- "placement": "after",
120
- "after_node_id": anchor["id"],
121
- },
122
- )
123
- )
124
-
125
- assert result["config"]["tab_id"] == tab.id
126
- assert owner.get_connections_snapshot() == []
127
- assert [
128
- (edge.from_node_id, edge.to_node_id)
129
- for edge in workspace_store.list_edges(tab.id)
130
- ] == [(anchor["id"], result["id"])]
131
-
132
-
133
- def test_create_agent_rejects_assistant_for_ordinary_nodes(monkeypatch):
134
- monkeypatch.setattr(
135
- "flowent.settings.get_settings",
136
- lambda: Settings(
137
- roles=[RoleConfig(name="Worker", system_prompt="Do work.")],
138
- ),
139
- )
140
- create_tab(title="Task")
141
-
142
- assistant = Agent(
143
- NodeConfig(
144
- node_type=NodeType.ASSISTANT,
145
- role_name="Steward",
146
- tools=["create_agent"],
147
- ),
148
- uuid="assistant",
149
- )
150
-
151
- result = json.loads(
152
- CreateAgentTool().execute(
153
- assistant,
154
- {
155
- "role_name": "Worker",
156
- },
157
- )
158
- )
159
-
160
- assert result == {"error": "Assistant may not create ordinary task nodes directly"}
161
-
162
-
163
- def test_create_agent_allows_explicitly_granted_task_node(monkeypatch):
164
- monkeypatch.setattr(
165
- "flowent.settings.get_settings",
166
- lambda: Settings(
167
- roles=[
168
- RoleConfig(
169
- name="Worker",
170
- system_prompt="Do work.",
171
- included_tools=["create_agent"],
172
- )
173
- ],
174
- ),
175
- )
176
- tab = create_tab(title="Task")
177
-
178
- leader = Agent(
179
- NodeConfig(
180
- node_type=NodeType.AGENT,
181
- role_name="Conductor",
182
- tab_id=tab.id,
183
- tools=["create_agent"],
184
- write_dirs=["/tmp/workspace"],
185
- allow_network=True,
186
- ),
187
- uuid=tab.leader_id,
188
- )
189
- registry.register(leader)
190
- creator = json.loads(
191
- CreateAgentTool().execute(
192
- leader,
193
- {
194
- "role_name": "Worker",
195
- "name": "Creator Worker",
196
- },
197
- )
198
- )
199
- creator_node = registry.get(creator["id"])
200
- assert creator_node is not None
201
-
202
- result = json.loads(
203
- CreateAgentTool().execute(
204
- creator_node,
205
- {
206
- "role_name": "Worker",
207
- "name": "Nested Worker",
208
- },
209
- )
210
- )
211
-
212
- assert result["config"]["tab_id"] == tab.id
213
- assert result["config"]["name"] == "Nested Worker"
214
- assert creator_node.get_connections_snapshot() == []
215
- assert workspace_store.list_edges(tab.id) == []
216
-
217
-
218
- def test_create_agent_rejects_task_node_without_tool(monkeypatch):
219
- monkeypatch.setattr(
220
- "flowent.settings.get_settings",
221
- lambda: Settings(roles=[RoleConfig(name="Worker", system_prompt="Do work.")]),
222
- )
223
- tab = create_tab(title="Task")
224
-
225
- worker = Agent(
226
- NodeConfig(
227
- node_type=NodeType.AGENT,
228
- role_name="Worker",
229
- tab_id=tab.id,
230
- tools=[],
231
- ),
232
- uuid="worker",
233
- )
234
-
235
- result = json.loads(
236
- CreateAgentTool().execute(
237
- worker,
238
- {
239
- "role_name": "Worker",
240
- },
241
- )
242
- )
243
-
244
- assert result == {"error": "create_agent is not enabled for this node"}
245
-
246
-
247
- def test_create_agent_rejects_workflow_id_parameter(monkeypatch):
248
- monkeypatch.setattr(
249
- "flowent.settings.get_settings",
250
- lambda: Settings(roles=[RoleConfig(name="Worker", system_prompt="Do work.")]),
251
- )
252
- tab = create_tab(title="Task")
253
-
254
- owner = Agent(
255
- NodeConfig(
256
- node_type=NodeType.AGENT,
257
- role_name="Conductor",
258
- tab_id=tab.id,
259
- tools=["create_agent"],
260
- ),
261
- uuid=tab.leader_id,
262
- )
263
-
264
- result = json.loads(
265
- CreateAgentTool().execute(
266
- owner,
267
- {
268
- "tab_id": tab.id,
269
- "role_name": "Worker",
270
- },
271
- )
272
- )
273
-
274
- assert result == {"error": "create_agent does not accept workflow_id"}
275
-
276
-
277
- def test_create_agent_rejects_reserved_conductor_role(monkeypatch):
278
- monkeypatch.setattr(
279
- "flowent.settings.get_settings",
280
- lambda: Settings(
281
- roles=[RoleConfig(name=CONDUCTOR_ROLE_NAME, system_prompt="Orchestrate.")],
282
- ),
283
- )
284
- tab = create_tab(title="Task")
285
-
286
- leader = Agent(
287
- NodeConfig(
288
- node_type=NodeType.AGENT,
289
- role_name="Conductor",
290
- tab_id=tab.id,
291
- tools=["create_agent"],
292
- ),
293
- uuid=tab.leader_id,
294
- )
295
- registry.register(leader)
296
-
297
- result = json.loads(
298
- CreateAgentTool().execute(
299
- leader,
300
- {
301
- "role_name": f" {CONDUCTOR_ROLE_NAME} ",
302
- "name": "Task Conductor",
303
- },
304
- )
305
- )
306
-
307
- assert result == {
308
- "error": f"Role '{CONDUCTOR_ROLE_NAME}' is reserved for a workflow Leader"
309
- }
310
-
311
-
312
- def test_create_agent_rejects_node_level_permissions(monkeypatch, tmp_path):
313
- monkeypatch.setattr(
314
- "flowent.settings.get_settings",
315
- lambda: Settings(roles=[RoleConfig(name="Worker", system_prompt="Do work.")]),
316
- )
317
-
318
- disallowed_dir = tmp_path / "disallowed"
319
- disallowed_dir.mkdir()
320
- tab = create_tab(title="Task")
321
-
322
- owner = Agent(
323
- NodeConfig(
324
- node_type=NodeType.AGENT,
325
- role_name="Conductor",
326
- tab_id=tab.id,
327
- tools=["create_agent"],
328
- ),
329
- uuid=tab.leader_id,
330
- )
331
-
332
- write_dir_result = json.loads(
333
- CreateAgentTool().execute(
334
- owner,
335
- {
336
- "role_name": "Worker",
337
- "write_dirs": [str(disallowed_dir)],
338
- },
339
- )
340
- )
341
- network_result = json.loads(
342
- CreateAgentTool().execute(
343
- owner,
344
- {
345
- "role_name": "Worker",
346
- "allow_network": True,
347
- },
348
- )
349
- )
350
-
351
- assert write_dir_result == {
352
- "error": (
353
- "create_agent uses the current workflow permissions; update the "
354
- "workflow permissions instead"
355
- )
356
- }
357
- assert network_result == {
358
- "error": (
359
- "create_agent uses the current workflow permissions; update the "
360
- "workflow permissions instead"
361
- )
362
- }
363
-
364
-
365
- def test_create_agent_tool_schema_exposes_workflow_placement_options():
366
- assert CreateAgentTool.parameters == {
367
- "type": "object",
368
- "properties": {
369
- "role_name": {
370
- "type": "string",
371
- "description": "Role assigned to the new agent",
372
- },
373
- "name": {
374
- "type": "string",
375
- "description": "Optional human-readable node name",
376
- },
377
- "tools": {
378
- "type": "array",
379
- "items": {"type": "string"},
380
- "description": "Optional additional tools",
381
- },
382
- "placement": {
383
- "type": "string",
384
- "enum": ["standalone", "after", "between"],
385
- "description": (
386
- "How to place the new agent inside the current workflow graph"
387
- ),
388
- "default": "standalone",
389
- },
390
- "after_node_id": {
391
- "type": "string",
392
- "description": "Anchor node id when placement is `after`",
393
- },
394
- "between_from_node_id": {
395
- "type": "string",
396
- "description": "Upstream node id when placement is `between`",
397
- },
398
- "between_to_node_id": {
399
- "type": "string",
400
- "description": "Downstream node id when placement is `between`",
401
- },
402
- },
403
- "required": ["role_name"],
404
- }