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,142 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import json
4
- import os
5
- from collections.abc import Callable
6
- from pathlib import Path
7
- from typing import TYPE_CHECKING, Any, ClassVar
8
-
9
- from loguru import logger
10
-
11
- from flowent.tools import Tool, re_raise_interrupt
12
-
13
- if TYPE_CHECKING:
14
- from flowent.agent import Agent
15
-
16
-
17
- class EditTool(Tool):
18
- name = "edit"
19
- description = (
20
- "Apply one or more line-based edits to a file in order. "
21
- "Use the read tool first to get the exact line numbers. "
22
- "Each edit uses 1-indexed inclusive start_line and end_line. "
23
- "new_content replaces those lines exactly as given (include a trailing newline if needed). "
24
- "If the file does not exist it will be created."
25
- )
26
- parameters: ClassVar[dict[str, Any]] = {
27
- "type": "object",
28
- "properties": {
29
- "path": {
30
- "type": "string",
31
- "description": "Absolute path to the file to edit or create",
32
- },
33
- "edits": {
34
- "type": "array",
35
- "items": {
36
- "type": "object",
37
- "properties": {
38
- "start_line": {
39
- "type": "integer",
40
- "description": "First line to replace (1-indexed, inclusive). Use 1 for a new file.",
41
- },
42
- "end_line": {
43
- "type": "integer",
44
- "description": "Last line to replace (1-indexed, inclusive).",
45
- },
46
- "new_content": {
47
- "type": "string",
48
- "description": "Replacement text for the specified line range. Use an empty string to delete lines.",
49
- },
50
- },
51
- "required": ["start_line", "end_line", "new_content"],
52
- },
53
- "description": "Edits to apply in order. Later line numbers are based on the file state after earlier edits.",
54
- },
55
- },
56
- "required": ["path", "edits"],
57
- }
58
-
59
- def execute(self, agent: Agent, args: dict[str, Any], **kwargs: Any) -> str:
60
- path_str = args["path"]
61
- real_path = Path(path_str)
62
- on_output: Callable[[str], None] | None = kwargs.get("on_output")
63
-
64
- try:
65
- edits = args["edits"]
66
- if not isinstance(edits, list):
67
- return json.dumps({"error": "edits must be an array"})
68
-
69
- if not real_path.exists():
70
- os.makedirs(real_path.parent, exist_ok=True)
71
- real_path.write_text("", encoding="utf-8")
72
- if on_output is not None:
73
- on_output(f"Created {path_str}\n")
74
-
75
- with open(real_path, encoding="utf-8") as f:
76
- lines = f.readlines()
77
-
78
- applied_edits: list[dict[str, int | str]] = []
79
- for index, raw_edit in enumerate(edits, start=1):
80
- if not isinstance(raw_edit, dict):
81
- return json.dumps({"error": "each edit must be an object"})
82
-
83
- start_line = int(raw_edit["start_line"])
84
- end_line = int(raw_edit["end_line"])
85
- new_content: str = raw_edit["new_content"]
86
-
87
- if start_line < 1:
88
- return json.dumps({"error": "start_line must be >= 1"})
89
- if end_line < start_line:
90
- return json.dumps({"error": "end_line must be >= start_line"})
91
-
92
- total_lines = len(lines)
93
- if start_line > total_lines + 1:
94
- return json.dumps(
95
- {
96
- "error": f"start_line {start_line} exceeds file length {total_lines}"
97
- }
98
- )
99
-
100
- current_end_line = min(end_line, total_lines)
101
- if on_output is not None:
102
- on_output(
103
- f"Applying edit {index}/{len(edits)} at lines {start_line}-{current_end_line}\n"
104
- )
105
-
106
- replacement = []
107
- if new_content:
108
- replacement = new_content.splitlines(keepends=True)
109
- if replacement and not replacement[-1].endswith("\n"):
110
- replacement[-1] += "\n"
111
-
112
- lines = lines[: start_line - 1] + replacement + lines[current_end_line:]
113
- applied_edits.append(
114
- {
115
- "start_line": start_line,
116
- "end_line": current_end_line,
117
- "replacement_line_count": len(replacement),
118
- }
119
- )
120
-
121
- with open(real_path, "w", encoding="utf-8") as f:
122
- f.writelines(lines)
123
- if on_output is not None:
124
- on_output(f"Wrote {path_str}\n")
125
-
126
- logger.debug(
127
- "Edited file: {} ({} edit(s), new_line_count={})",
128
- path_str,
129
- len(applied_edits),
130
- len(lines),
131
- )
132
- return json.dumps(
133
- {
134
- "status": "edited",
135
- "path": path_str,
136
- "applied_edits": applied_edits,
137
- "new_line_count": len(lines),
138
- }
139
- )
140
- except Exception as e:
141
- re_raise_interrupt(agent, e)
142
- return json.dumps({"error": str(e)})
@@ -1,118 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import json
4
- import subprocess
5
- import threading
6
- from collections.abc import Callable
7
- from pathlib import Path
8
- from typing import TYPE_CHECKING, Any, ClassVar
9
-
10
- from loguru import logger
11
-
12
- from flowent.sandbox import build_bwrap_cmd
13
- from flowent.tools import Tool, re_raise_interrupt
14
-
15
- if TYPE_CHECKING:
16
- from flowent.agent import Agent
17
-
18
-
19
- class ExecTool(Tool):
20
- name = "exec"
21
- description = "Execute a shell command in a sandboxed environment."
22
- parameters: ClassVar[dict[str, Any]] = {
23
- "type": "object",
24
- "properties": {
25
- "command": {
26
- "type": "string",
27
- "description": "Shell command to execute",
28
- },
29
- "timeout": {
30
- "type": "number",
31
- "description": "Timeout in seconds (default 30)",
32
- },
33
- },
34
- "required": ["command"],
35
- }
36
-
37
- def execute(self, agent: Agent, args: dict[str, Any], **kwargs: Any) -> str:
38
- on_output: Callable[[str], None] | None = kwargs.get("on_output")
39
- from flowent.graph_service import resolve_effective_permissions_for_agent
40
- from flowent.settings import get_runtime_working_dir_path
41
-
42
- command = args["command"]
43
- timeout = int(args.get("timeout", 30))
44
- allow_network, write_dirs = resolve_effective_permissions_for_agent(agent)
45
- cwd = Path(get_runtime_working_dir_path())
46
-
47
- bwrap_cmd = build_bwrap_cmd(
48
- write_dirs,
49
- command,
50
- allow_network=allow_network,
51
- cwd=cwd,
52
- )
53
-
54
- logger.debug(
55
- "Executing command: {} (timeout={}s, cwd={})",
56
- command,
57
- timeout,
58
- cwd,
59
- )
60
-
61
- proc: subprocess.Popen[str] | None = None
62
- try:
63
- proc = subprocess.Popen(
64
- bwrap_cmd,
65
- stdout=subprocess.PIPE,
66
- stderr=subprocess.PIPE,
67
- text=True,
68
- cwd=str(cwd),
69
- )
70
- agent.set_interrupt_callback(
71
- lambda: proc.kill() if proc.poll() is None else None
72
- )
73
-
74
- stdout_lines: list[str] = []
75
- stderr_lines: list[str] = []
76
-
77
- def _read_stderr() -> None:
78
- assert proc.stderr is not None
79
- for line in proc.stderr:
80
- stderr_lines.append(line)
81
-
82
- stderr_thread = threading.Thread(target=_read_stderr, daemon=True)
83
- stderr_thread.start()
84
-
85
- assert proc.stdout is not None
86
- for line in proc.stdout:
87
- stdout_lines.append(line)
88
- if on_output:
89
- on_output(line)
90
-
91
- try:
92
- proc.wait(timeout=timeout)
93
- except subprocess.TimeoutExpired:
94
- proc.kill()
95
- proc.wait()
96
- logger.warning("Command timed out after {}s: {}", timeout, command)
97
- return json.dumps({"error": f"Command timed out after {timeout}s"})
98
-
99
- stderr_thread.join(timeout=5)
100
-
101
- stdout = "".join(stdout_lines)
102
- stderr = "".join(stderr_lines)
103
- logger.debug("Command exited with code {}", proc.returncode)
104
- return json.dumps(
105
- {
106
- "returncode": proc.returncode,
107
- "stdout": stdout[:5000],
108
- "stderr": stderr[:2000],
109
- }
110
- )
111
- except Exception as e:
112
- if proc is not None and proc.poll() is None:
113
- proc.kill()
114
- proc.wait()
115
- re_raise_interrupt(agent, e)
116
- return json.dumps({"error": str(e)})
117
- finally:
118
- agent.set_interrupt_callback(None)
@@ -1,85 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import json
4
- from collections.abc import Callable
5
- from typing import TYPE_CHECKING, Any, ClassVar
6
-
7
- from loguru import logger
8
-
9
- from flowent.network import create_http_session, iter_response_text
10
- from flowent.tools import Tool, re_raise_interrupt
11
-
12
- if TYPE_CHECKING:
13
- from flowent.agent import Agent
14
-
15
-
16
- class FetchTool(Tool):
17
- name = "fetch"
18
- description = "Make an HTTP request."
19
- parameters: ClassVar[dict[str, Any]] = {
20
- "type": "object",
21
- "properties": {
22
- "method": {
23
- "type": "string",
24
- "enum": ["GET", "POST", "PUT", "DELETE", "PATCH"],
25
- "description": "HTTP method",
26
- },
27
- "url": {"type": "string", "description": "Request URL"},
28
- "headers": {
29
- "type": "object",
30
- "description": "Request headers (optional)",
31
- },
32
- "body": {"type": "string", "description": "Request body (optional)"},
33
- },
34
- "required": ["method", "url"],
35
- }
36
-
37
- def execute(self, agent: Agent, args: dict[str, Any], **kwargs: Any) -> str:
38
- method = args["method"]
39
- url = args["url"]
40
- on_output: Callable[[str], None] | None = kwargs.get("on_output")
41
- logger.debug("HTTP {} {}", method, url)
42
- try:
43
- with (
44
- create_http_session(timeout=30.0, impersonate_browser=True) as client,
45
- client.stream(
46
- method,
47
- url,
48
- headers=args.get("headers"),
49
- data=args.get("body"),
50
- ) as response,
51
- ):
52
- close_response = getattr(response, "close", None)
53
- agent.set_interrupt_callback(
54
- close_response if callable(close_response) else None
55
- )
56
- if on_output is not None:
57
- on_output(f"{method} {url}\n")
58
- on_output(f"HTTP {response.status_code}\n\n")
59
-
60
- remaining = 5000
61
- body_parts: list[str] = []
62
- for chunk in iter_response_text(response):
63
- if not chunk or remaining <= 0:
64
- continue
65
- if len(chunk) > remaining:
66
- chunk = chunk[:remaining]
67
- body_parts.append(chunk)
68
- remaining -= len(chunk)
69
- if on_output is not None:
70
- on_output(chunk)
71
-
72
- body = "".join(body_parts)
73
- logger.debug("HTTP {} {} -> {}", method, url, response.status_code)
74
- return json.dumps(
75
- {
76
- "status_code": response.status_code,
77
- "body": body,
78
- }
79
- )
80
- except Exception as e:
81
- re_raise_interrupt(agent, e)
82
- logger.warning("HTTP request failed: {} {} - {}", method, url, e)
83
- return json.dumps({"error": str(e)})
84
- finally:
85
- agent.set_interrupt_callback(None)
@@ -1,27 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from typing import TYPE_CHECKING, Any, ClassVar
4
-
5
- from flowent.tools import Tool
6
-
7
- if TYPE_CHECKING:
8
- from flowent.agent import Agent
9
-
10
-
11
- class IdleTool(Tool):
12
- name = "idle"
13
- description = (
14
- "Enter idle state. The agent suspends execution until a wake signal re-activates it. "
15
- "Use this when the current step or task is finished, paused, or blocked, and there is no "
16
- "immediate next action to take right now. Incoming messages will automatically re-activate you as new input messages, and the tool returns the idle duration when execution resumes."
17
- )
18
- parameters: ClassVar[dict[str, Any]] = {
19
- "type": "object",
20
- "properties": {},
21
- }
22
-
23
- def execute(self, agent: Agent, args: dict[str, Any], **kwargs: Any) -> str:
24
- tool_call_id = kwargs.get("tool_call_id")
25
- if tool_call_id is not None and not isinstance(tool_call_id, str):
26
- tool_call_id = None
27
- return agent.request_idle(tool_call_id=tool_call_id)
@@ -1,68 +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 ListRolesTool(Tool):
13
- name = "list_roles"
14
- description = "List all registered roles with builtin and optional tool views."
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
- from flowent.models import NodeType
23
- from flowent.settings import get_settings, normalize_tool_names
24
- from flowent.tools import (
25
- MINIMUM_TOOLS,
26
- build_tool_registry,
27
- is_assistant_only_tool_name,
28
- )
29
-
30
- settings = get_settings()
31
- tool_registry = build_tool_registry()
32
- all_tool_names: list[str] = []
33
- for tool in tool_registry.list_tools(agent_visible_only=True):
34
- all_tool_names.append(tool.name)
35
- if agent.node_type != NodeType.ASSISTANT:
36
- all_tool_names = [
37
- tool_name
38
- for tool_name in all_tool_names
39
- if not is_assistant_only_tool_name(tool_name)
40
- ]
41
- payload: list[dict[str, object]] = []
42
-
43
- for role in settings.roles:
44
- builtin_tools = normalize_tool_names([*MINIMUM_TOOLS, *role.included_tools])
45
- if agent.node_type != NodeType.ASSISTANT:
46
- builtin_tools = [
47
- tool_name
48
- for tool_name in builtin_tools
49
- if not tool_name.startswith("mcp__")
50
- and not is_assistant_only_tool_name(tool_name)
51
- ]
52
- optional_tools = [
53
- tool_name
54
- for tool_name in all_tool_names
55
- if tool_name not in builtin_tools
56
- and tool_name not in role.excluded_tools
57
- ]
58
- payload.append(
59
- {
60
- "name": role.name,
61
- "description": role.description,
62
- "system_prompt": role.system_prompt,
63
- "builtin_tools": builtin_tools,
64
- "optional_tools": optional_tools,
65
- }
66
- )
67
-
68
- return json.dumps(payload)
@@ -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.graph_service import (
7
- is_tab_leader,
8
- list_tab_edges,
9
- list_tab_nodes,
10
- list_workflow_nodes,
11
- serialize_tab_summary,
12
- )
13
- from flowent.models import NodeType
14
- from flowent.tools import Tool
15
- from flowent.workspace_store import workspace_store
16
-
17
- if TYPE_CHECKING:
18
- from flowent.agent import Agent
19
-
20
-
21
- class ListTabsTool(Tool):
22
- name = "list_workflows"
23
- description = "List persistent workflows. Optionally include the full Workflow Graph for one workflow."
24
- parameters: ClassVar[dict[str, Any]] = {
25
- "type": "object",
26
- "properties": {
27
- "workflow_id": {
28
- "type": "string",
29
- "description": "Optional workflow ID to inspect in detail",
30
- }
31
- },
32
- "required": [],
33
- }
34
-
35
- def execute(self, agent: Agent, args: dict[str, Any], **_kwargs: Any) -> str:
36
- if agent.node_type != NodeType.ASSISTANT:
37
- return json.dumps({"error": "Only the Assistant may list workflows"})
38
-
39
- workflow_id = args.get("workflow_id")
40
- if workflow_id is not None and not isinstance(workflow_id, str):
41
- return json.dumps({"error": "workflow_id must be a string"})
42
-
43
- if isinstance(workflow_id, str) and workflow_id.strip():
44
- tab = workspace_store.get_tab(workflow_id.strip())
45
- if tab is None:
46
- return json.dumps(
47
- {"error": f"Workflow '{workflow_id.strip()}' not found"}
48
- )
49
- nodes = [
50
- {
51
- "id": node.id,
52
- "node_type": node.type.value,
53
- "name": (
54
- node.config["name"]
55
- if isinstance(node.config.get("name"), str)
56
- else None
57
- ),
58
- "role_name": (
59
- node.config["role_name"]
60
- if isinstance(node.config.get("role_name"), str)
61
- else None
62
- ),
63
- "is_leader": False,
64
- "position": (
65
- tab.definition.view.positions[node.id].serialize()
66
- if node.id in tab.definition.view.positions
67
- else None
68
- ),
69
- }
70
- for node in list_workflow_nodes(tab.id)
71
- ]
72
- return json.dumps(
73
- {
74
- "workflow": serialize_tab_summary(tab),
75
- "nodes": nodes,
76
- "runtime_nodes": [
77
- {
78
- "id": node.id,
79
- "name": node.config.name,
80
- "role_name": node.config.role_name,
81
- "is_leader": is_tab_leader(
82
- node_id=node.id,
83
- tab_id=tab.id,
84
- ),
85
- "state": node.state.value,
86
- "position": (
87
- node.position.serialize()
88
- if node.position is not None
89
- else None
90
- ),
91
- }
92
- for node in list_tab_nodes(tab.id)
93
- ],
94
- "edges": [edge.serialize() for edge in list_tab_edges(tab.id)],
95
- }
96
- )
97
-
98
- return json.dumps(
99
- [serialize_tab_summary(tab) for tab in workspace_store.list_tabs()]
100
- )
@@ -1,28 +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 ListToolsTool(Tool):
13
- name = "list_tools"
14
- description = "List all registered tools with their names and descriptions."
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
- from flowent.models import NodeType
23
- from flowent.tools import list_agent_visible_tool_descriptors
24
-
25
- descriptors = list_agent_visible_tool_descriptors(
26
- include_assistant_only=agent.node_type == NodeType.ASSISTANT
27
- )
28
- return json.dumps(descriptors)
@@ -1,102 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import json
4
- from typing import TYPE_CHECKING, Any, ClassVar
5
-
6
- if TYPE_CHECKING:
7
- from flowent.agent import Agent
8
-
9
- from flowent.tools import Tool
10
-
11
-
12
- class ManagePromptsTool(Tool):
13
- name = "manage_prompts"
14
- description = (
15
- "Read and update the global custom prompt and custom post prompt. The "
16
- "custom prompt is appended to every node's system prompt, and the "
17
- "custom post prompt is appended after the built-in runtime post prompt "
18
- "in every runtime request tail."
19
- )
20
- parameters: ClassVar[dict[str, Any]] = {
21
- "type": "object",
22
- "properties": {
23
- "action": {
24
- "type": "string",
25
- "enum": ["get", "update"],
26
- "description": "Prompt management action",
27
- },
28
- "custom_prompt": {
29
- "type": "string",
30
- "description": "Updated global custom prompt",
31
- },
32
- "custom_post_prompt": {
33
- "type": "string",
34
- "description": "Updated global custom post prompt",
35
- },
36
- },
37
- "required": ["action"],
38
- }
39
-
40
- def execute(self, agent: Agent, args: dict[str, Any], **_kwargs: Any) -> str:
41
- from flowent.settings import get_settings, save_settings
42
-
43
- action = args.get("action")
44
- custom_prompt = args.get("custom_prompt")
45
- custom_post_prompt = args.get("custom_post_prompt")
46
- legacy_post_prompt = args.get("post_prompt")
47
-
48
- if not isinstance(action, str):
49
- return json.dumps({"error": "action must be a string"})
50
-
51
- settings = get_settings()
52
-
53
- if action == "get":
54
- return json.dumps(
55
- {
56
- "custom_prompt": settings.custom_prompt,
57
- "custom_post_prompt": settings.custom_post_prompt,
58
- }
59
- )
60
-
61
- if action != "update":
62
- return json.dumps({"error": f"Unsupported action: {action}"})
63
-
64
- if (
65
- "custom_prompt" not in args
66
- and "custom_post_prompt" not in args
67
- and "post_prompt" not in args
68
- ):
69
- return json.dumps(
70
- {"error": "custom_prompt or custom_post_prompt is required"}
71
- )
72
- if "custom_prompt" in args and not isinstance(custom_prompt, str):
73
- return json.dumps({"error": "custom_prompt must be a string"})
74
- if "custom_post_prompt" in args and not isinstance(custom_post_prompt, str):
75
- return json.dumps({"error": "custom_post_prompt must be a string"})
76
- if (
77
- "post_prompt" in args
78
- and "custom_post_prompt" not in args
79
- and not isinstance(legacy_post_prompt, str)
80
- ):
81
- return json.dumps({"error": "custom_post_prompt must be a string"})
82
-
83
- next_custom_prompt = custom_prompt if isinstance(custom_prompt, str) else None
84
- next_custom_post_prompt = (
85
- custom_post_prompt
86
- if isinstance(custom_post_prompt, str)
87
- else legacy_post_prompt
88
- if isinstance(legacy_post_prompt, str)
89
- else None
90
- )
91
-
92
- if next_custom_prompt is not None:
93
- settings.custom_prompt = next_custom_prompt
94
- if next_custom_post_prompt is not None:
95
- settings.custom_post_prompt = next_custom_post_prompt
96
- save_settings(settings)
97
- return json.dumps(
98
- {
99
- "custom_prompt": settings.custom_prompt,
100
- "custom_post_prompt": settings.custom_post_prompt,
101
- }
102
- )