flowent 0.0.6 → 0.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (398) hide show
  1. package/README.md +1 -4
  2. package/backend/README.md +1 -4
  3. package/backend/pyproject.toml +2 -8
  4. package/backend/src/flowent/__pycache__/__init__.cpython-313.pyc +0 -0
  5. package/backend/src/flowent/__pycache__/agent.cpython-313.pyc +0 -0
  6. package/backend/src/flowent/__pycache__/cli.cpython-313.pyc +0 -0
  7. package/backend/src/flowent/__pycache__/context.cpython-313.pyc +0 -0
  8. package/backend/src/flowent/__pycache__/llm.cpython-313.pyc +0 -0
  9. package/backend/src/flowent/__pycache__/logging.cpython-313.pyc +0 -0
  10. package/backend/src/flowent/__pycache__/main.cpython-313.pyc +0 -0
  11. package/backend/src/flowent/__pycache__/patch.cpython-313.pyc +0 -0
  12. package/backend/src/flowent/__pycache__/paths.cpython-313.pyc +0 -0
  13. package/backend/src/flowent/__pycache__/sandbox.cpython-313.pyc +0 -0
  14. package/backend/src/flowent/__pycache__/storage.cpython-313.pyc +0 -0
  15. package/backend/src/flowent/__pycache__/tools.cpython-313.pyc +0 -0
  16. package/backend/src/flowent/agent.py +217 -3094
  17. package/backend/src/flowent/cli.py +19 -24
  18. package/backend/src/flowent/context.py +127 -0
  19. package/backend/src/flowent/llm.py +256 -0
  20. package/backend/src/flowent/logging.py +170 -129
  21. package/backend/src/flowent/main.py +321 -70
  22. package/backend/src/flowent/patch.py +182 -0
  23. package/backend/src/flowent/paths.py +11 -0
  24. package/backend/src/flowent/sandbox.py +214 -40
  25. package/backend/src/flowent/static/assets/geist-cyrillic-wght-normal-CHSlOQsW.woff2 +0 -0
  26. package/backend/src/flowent/static/assets/geist-latin-ext-wght-normal-DMtmJ5ZE.woff2 +0 -0
  27. package/backend/src/flowent/static/assets/geist-latin-wght-normal-Dm3htQBi.woff2 +0 -0
  28. package/backend/src/flowent/static/assets/index-C76K95ty.js +81 -0
  29. package/backend/src/flowent/static/assets/index-iUMNKvlU.css +2 -0
  30. package/backend/src/flowent/static/flowent.png +0 -0
  31. package/backend/src/flowent/static/index.html +5 -25
  32. package/backend/src/flowent/storage.py +302 -0
  33. package/backend/src/flowent/tools.py +364 -0
  34. package/backend/tests/__pycache__/test_agent_tools.cpython-313-pytest-9.0.3.pyc +0 -0
  35. package/backend/tests/__pycache__/test_health.cpython-313-pytest-9.0.3.pyc +0 -0
  36. package/backend/tests/__pycache__/test_llm_providers.cpython-313-pytest-9.0.3.pyc +0 -0
  37. package/backend/tests/__pycache__/test_logging.cpython-313-pytest-9.0.3.pyc +0 -0
  38. package/backend/tests/__pycache__/test_persistence.cpython-313-pytest-9.0.3.pyc +0 -0
  39. package/backend/tests/__pycache__/test_workspace_chat.cpython-313-pytest-9.0.3.pyc +0 -0
  40. package/backend/tests/test_agent_tools.py +449 -0
  41. package/backend/tests/test_health.py +12 -0
  42. package/backend/tests/test_llm_providers.py +113 -0
  43. package/backend/tests/test_logging.py +182 -0
  44. package/backend/tests/test_persistence.py +125 -0
  45. package/backend/tests/test_workspace_chat.py +578 -0
  46. package/backend/uv.lock +803 -99
  47. package/dist/frontend/assets/geist-cyrillic-wght-normal-CHSlOQsW.woff2 +0 -0
  48. package/dist/frontend/assets/geist-latin-ext-wght-normal-DMtmJ5ZE.woff2 +0 -0
  49. package/dist/frontend/assets/geist-latin-wght-normal-Dm3htQBi.woff2 +0 -0
  50. package/dist/frontend/assets/index-C76K95ty.js +81 -0
  51. package/dist/frontend/assets/index-iUMNKvlU.css +2 -0
  52. package/dist/frontend/flowent.png +0 -0
  53. package/dist/frontend/index.html +5 -25
  54. package/package.json +1 -2
  55. package/backend/src/flowent/__pycache__/_version.cpython-313.pyc +0 -0
  56. package/backend/src/flowent/__pycache__/access.cpython-313.pyc +0 -0
  57. package/backend/src/flowent/__pycache__/assistant_commands.cpython-313.pyc +0 -0
  58. package/backend/src/flowent/__pycache__/config.cpython-313.pyc +0 -0
  59. package/backend/src/flowent/__pycache__/events.cpython-313.pyc +0 -0
  60. package/backend/src/flowent/__pycache__/graph_runtime.cpython-313.pyc +0 -0
  61. package/backend/src/flowent/__pycache__/graph_service.cpython-313.pyc +0 -0
  62. package/backend/src/flowent/__pycache__/image_assets.cpython-313.pyc +0 -0
  63. package/backend/src/flowent/__pycache__/mcp_service.cpython-313.pyc +0 -0
  64. package/backend/src/flowent/__pycache__/model_metadata.cpython-313.pyc +0 -0
  65. package/backend/src/flowent/__pycache__/network.cpython-313.pyc +0 -0
  66. package/backend/src/flowent/__pycache__/observability_service.cpython-313.pyc +0 -0
  67. package/backend/src/flowent/__pycache__/registry.cpython-313.pyc +0 -0
  68. package/backend/src/flowent/__pycache__/role_management.cpython-313.pyc +0 -0
  69. package/backend/src/flowent/__pycache__/runtime.cpython-313.pyc +0 -0
  70. package/backend/src/flowent/__pycache__/security.cpython-313.pyc +0 -0
  71. package/backend/src/flowent/__pycache__/settings.cpython-313.pyc +0 -0
  72. package/backend/src/flowent/__pycache__/settings_management.cpython-313.pyc +0 -0
  73. package/backend/src/flowent/__pycache__/state_db.cpython-313.pyc +0 -0
  74. package/backend/src/flowent/__pycache__/workspace_store.cpython-313.pyc +0 -0
  75. package/backend/src/flowent/access.py +0 -247
  76. package/backend/src/flowent/assistant_commands.py +0 -115
  77. package/backend/src/flowent/channels/__init__.py +0 -3
  78. package/backend/src/flowent/channels/__pycache__/__init__.cpython-313.pyc +0 -0
  79. package/backend/src/flowent/channels/__pycache__/telegram.cpython-313.pyc +0 -0
  80. package/backend/src/flowent/channels/telegram.py +0 -615
  81. package/backend/src/flowent/config.py +0 -14
  82. package/backend/src/flowent/dev.py +0 -3
  83. package/backend/src/flowent/events.py +0 -157
  84. package/backend/src/flowent/graph_runtime.py +0 -60
  85. package/backend/src/flowent/graph_service.py +0 -2508
  86. package/backend/src/flowent/image_assets.py +0 -356
  87. package/backend/src/flowent/mcp_service.py +0 -1918
  88. package/backend/src/flowent/model_metadata.py +0 -102
  89. package/backend/src/flowent/models/__init__.py +0 -125
  90. package/backend/src/flowent/models/__pycache__/__init__.cpython-313.pyc +0 -0
  91. package/backend/src/flowent/models/__pycache__/agent.cpython-313.pyc +0 -0
  92. package/backend/src/flowent/models/__pycache__/base.cpython-313.pyc +0 -0
  93. package/backend/src/flowent/models/__pycache__/blueprint.cpython-313.pyc +0 -0
  94. package/backend/src/flowent/models/__pycache__/content.cpython-313.pyc +0 -0
  95. package/backend/src/flowent/models/__pycache__/delta.cpython-313.pyc +0 -0
  96. package/backend/src/flowent/models/__pycache__/event.cpython-313.pyc +0 -0
  97. package/backend/src/flowent/models/__pycache__/graph.cpython-313.pyc +0 -0
  98. package/backend/src/flowent/models/__pycache__/history.cpython-313.pyc +0 -0
  99. package/backend/src/flowent/models/__pycache__/llm.cpython-313.pyc +0 -0
  100. package/backend/src/flowent/models/__pycache__/message.cpython-313.pyc +0 -0
  101. package/backend/src/flowent/models/__pycache__/tab.cpython-313.pyc +0 -0
  102. package/backend/src/flowent/models/__pycache__/todo.cpython-313.pyc +0 -0
  103. package/backend/src/flowent/models/agent.py +0 -34
  104. package/backend/src/flowent/models/base.py +0 -24
  105. package/backend/src/flowent/models/blueprint.py +0 -176
  106. package/backend/src/flowent/models/content.py +0 -164
  107. package/backend/src/flowent/models/delta.py +0 -44
  108. package/backend/src/flowent/models/event.py +0 -51
  109. package/backend/src/flowent/models/graph.py +0 -472
  110. package/backend/src/flowent/models/history.py +0 -272
  111. package/backend/src/flowent/models/llm.py +0 -62
  112. package/backend/src/flowent/models/message.py +0 -33
  113. package/backend/src/flowent/models/tab.py +0 -85
  114. package/backend/src/flowent/models/todo.py +0 -10
  115. package/backend/src/flowent/network.py +0 -146
  116. package/backend/src/flowent/observability_service.py +0 -218
  117. package/backend/src/flowent/prompts/__init__.py +0 -67
  118. package/backend/src/flowent/prompts/__pycache__/__init__.cpython-313.pyc +0 -0
  119. package/backend/src/flowent/prompts/__pycache__/common.cpython-313.pyc +0 -0
  120. package/backend/src/flowent/prompts/__pycache__/steward.cpython-313.pyc +0 -0
  121. package/backend/src/flowent/prompts/common.py +0 -250
  122. package/backend/src/flowent/prompts/steward.py +0 -64
  123. package/backend/src/flowent/providers/__init__.py +0 -23
  124. package/backend/src/flowent/providers/__pycache__/__init__.cpython-313.pyc +0 -0
  125. package/backend/src/flowent/providers/__pycache__/anthropic.cpython-313.pyc +0 -0
  126. package/backend/src/flowent/providers/__pycache__/base_url.cpython-313.pyc +0 -0
  127. package/backend/src/flowent/providers/__pycache__/configuration.cpython-313.pyc +0 -0
  128. package/backend/src/flowent/providers/__pycache__/content.cpython-313.pyc +0 -0
  129. package/backend/src/flowent/providers/__pycache__/errors.cpython-313.pyc +0 -0
  130. package/backend/src/flowent/providers/__pycache__/gateway.cpython-313.pyc +0 -0
  131. package/backend/src/flowent/providers/__pycache__/headers.cpython-313.pyc +0 -0
  132. package/backend/src/flowent/providers/__pycache__/management.cpython-313.pyc +0 -0
  133. package/backend/src/flowent/providers/__pycache__/openai.cpython-313.pyc +0 -0
  134. package/backend/src/flowent/providers/__pycache__/openai_responses.cpython-313.pyc +0 -0
  135. package/backend/src/flowent/providers/__pycache__/registry.cpython-313.pyc +0 -0
  136. package/backend/src/flowent/providers/__pycache__/sse.cpython-313.pyc +0 -0
  137. package/backend/src/flowent/providers/__pycache__/thinking.cpython-313.pyc +0 -0
  138. package/backend/src/flowent/providers/anthropic.py +0 -468
  139. package/backend/src/flowent/providers/base_url.py +0 -60
  140. package/backend/src/flowent/providers/configuration.py +0 -189
  141. package/backend/src/flowent/providers/content.py +0 -122
  142. package/backend/src/flowent/providers/errors.py +0 -223
  143. package/backend/src/flowent/providers/gateway.py +0 -169
  144. package/backend/src/flowent/providers/gemini.py +0 -447
  145. package/backend/src/flowent/providers/headers.py +0 -20
  146. package/backend/src/flowent/providers/management.py +0 -96
  147. package/backend/src/flowent/providers/ollama.py +0 -293
  148. package/backend/src/flowent/providers/openai.py +0 -422
  149. package/backend/src/flowent/providers/openai_responses.py +0 -655
  150. package/backend/src/flowent/providers/registry.py +0 -144
  151. package/backend/src/flowent/providers/sse.py +0 -31
  152. package/backend/src/flowent/providers/thinking.py +0 -79
  153. package/backend/src/flowent/registry.py +0 -73
  154. package/backend/src/flowent/role_management.py +0 -267
  155. package/backend/src/flowent/routes/__init__.py +0 -28
  156. package/backend/src/flowent/routes/__pycache__/__init__.cpython-313.pyc +0 -0
  157. package/backend/src/flowent/routes/__pycache__/access.cpython-313.pyc +0 -0
  158. package/backend/src/flowent/routes/__pycache__/assistant.cpython-313.pyc +0 -0
  159. package/backend/src/flowent/routes/__pycache__/image_assets.cpython-313.pyc +0 -0
  160. package/backend/src/flowent/routes/__pycache__/mcp.cpython-313.pyc +0 -0
  161. package/backend/src/flowent/routes/__pycache__/meta.cpython-313.pyc +0 -0
  162. package/backend/src/flowent/routes/__pycache__/nodes.cpython-313.pyc +0 -0
  163. package/backend/src/flowent/routes/__pycache__/prompts.cpython-313.pyc +0 -0
  164. package/backend/src/flowent/routes/__pycache__/providers_route.cpython-313.pyc +0 -0
  165. package/backend/src/flowent/routes/__pycache__/roles.cpython-313.pyc +0 -0
  166. package/backend/src/flowent/routes/__pycache__/settings.cpython-313.pyc +0 -0
  167. package/backend/src/flowent/routes/__pycache__/tabs.cpython-313.pyc +0 -0
  168. package/backend/src/flowent/routes/__pycache__/ws.cpython-313.pyc +0 -0
  169. package/backend/src/flowent/routes/access.py +0 -48
  170. package/backend/src/flowent/routes/assistant.py +0 -155
  171. package/backend/src/flowent/routes/image_assets.py +0 -33
  172. package/backend/src/flowent/routes/mcp.py +0 -125
  173. package/backend/src/flowent/routes/meta.py +0 -28
  174. package/backend/src/flowent/routes/nodes.py +0 -413
  175. package/backend/src/flowent/routes/prompts.py +0 -46
  176. package/backend/src/flowent/routes/providers_route.py +0 -365
  177. package/backend/src/flowent/routes/roles.py +0 -207
  178. package/backend/src/flowent/routes/settings.py +0 -328
  179. package/backend/src/flowent/routes/tabs.py +0 -310
  180. package/backend/src/flowent/routes/ws.py +0 -33
  181. package/backend/src/flowent/runtime.py +0 -165
  182. package/backend/src/flowent/security.py +0 -57
  183. package/backend/src/flowent/settings.py +0 -2518
  184. package/backend/src/flowent/settings_management.py +0 -298
  185. package/backend/src/flowent/state_db.py +0 -120
  186. package/backend/src/flowent/static/assets/AssistantPage-VBohhz4d.js +0 -1
  187. package/backend/src/flowent/static/assets/ChannelsPage-CIydPZA_.js +0 -1
  188. package/backend/src/flowent/static/assets/McpPage-CHPm2TPY.js +0 -7
  189. package/backend/src/flowent/static/assets/PageScaffold-DteOA8V7.js +0 -1
  190. package/backend/src/flowent/static/assets/PromptsPage-CSmJ3sZg.js +0 -1
  191. package/backend/src/flowent/static/assets/ProvidersPage-sl2jeG4e.js +0 -3
  192. package/backend/src/flowent/static/assets/RolesPage-DCe7W6Km.js +0 -1
  193. package/backend/src/flowent/static/assets/SettingsPage-Bix9e63E.js +0 -3
  194. package/backend/src/flowent/static/assets/ToolsPage-favNkj5C.js +0 -1
  195. package/backend/src/flowent/static/assets/WorkspaceCommandDialog-DRS6wiD6.js +0 -1
  196. package/backend/src/flowent/static/assets/WorkspacePage-KuaDjt_D.js +0 -3
  197. package/backend/src/flowent/static/assets/WorkspacePanels-BZxBw8M5.js +0 -1
  198. package/backend/src/flowent/static/assets/alert-dialog-DIBUCmqM.js +0 -1
  199. package/backend/src/flowent/static/assets/datetime-eJqd0V2S.js +0 -1
  200. package/backend/src/flowent/static/assets/dialog-BOvHIBrg.js +0 -1
  201. package/backend/src/flowent/static/assets/elk-worker.min-C9JGDOE-.js +0 -6312
  202. package/backend/src/flowent/static/assets/graph-vendor-CHpVij2M.css +0 -1
  203. package/backend/src/flowent/static/assets/graph-vendor-DRq_-6fV.js +0 -7
  204. package/backend/src/flowent/static/assets/index-Biio-CoI.js +0 -10
  205. package/backend/src/flowent/static/assets/index-CmQvO7sl.css +0 -1
  206. package/backend/src/flowent/static/assets/layout.worker-jMHqAFbP.js +0 -24
  207. package/backend/src/flowent/static/assets/markdown-vendor-C9RtvaJh.js +0 -29
  208. package/backend/src/flowent/static/assets/modelParams-DcEhGnu0.js +0 -1
  209. package/backend/src/flowent/static/assets/react-vendor-mEs_JJxa.js +0 -9
  210. package/backend/src/flowent/static/assets/roles-BbIEIMeG.js +0 -1
  211. package/backend/src/flowent/static/assets/rolldown-runtime-BYbx6iT9.js +0 -1
  212. package/backend/src/flowent/static/assets/select-D9SwnlXF.js +0 -1
  213. package/backend/src/flowent/static/assets/surface-Bzr1FRG4.js +0 -1
  214. package/backend/src/flowent/static/assets/triState-DgLlKdRR.js +0 -1
  215. package/backend/src/flowent/static/assets/ui-vendor-UazN8rcv.js +0 -51
  216. package/backend/src/flowent/static/favicon.svg +0 -4
  217. package/backend/src/flowent/tools/__init__.py +0 -275
  218. package/backend/src/flowent/tools/__pycache__/__init__.cpython-313.pyc +0 -0
  219. package/backend/src/flowent/tools/__pycache__/connect.cpython-313.pyc +0 -0
  220. package/backend/src/flowent/tools/__pycache__/contacts.cpython-313.pyc +0 -0
  221. package/backend/src/flowent/tools/__pycache__/create_agent.cpython-313.pyc +0 -0
  222. package/backend/src/flowent/tools/__pycache__/create_tab.cpython-313.pyc +0 -0
  223. package/backend/src/flowent/tools/__pycache__/delete_tab.cpython-313.pyc +0 -0
  224. package/backend/src/flowent/tools/__pycache__/edit.cpython-313.pyc +0 -0
  225. package/backend/src/flowent/tools/__pycache__/exec.cpython-313.pyc +0 -0
  226. package/backend/src/flowent/tools/__pycache__/fetch.cpython-313.pyc +0 -0
  227. package/backend/src/flowent/tools/__pycache__/idle.cpython-313.pyc +0 -0
  228. package/backend/src/flowent/tools/__pycache__/list_roles.cpython-313.pyc +0 -0
  229. package/backend/src/flowent/tools/__pycache__/list_tabs.cpython-313.pyc +0 -0
  230. package/backend/src/flowent/tools/__pycache__/list_tools.cpython-313.pyc +0 -0
  231. package/backend/src/flowent/tools/__pycache__/manage_prompts.cpython-313.pyc +0 -0
  232. package/backend/src/flowent/tools/__pycache__/manage_providers.cpython-313.pyc +0 -0
  233. package/backend/src/flowent/tools/__pycache__/manage_roles.cpython-313.pyc +0 -0
  234. package/backend/src/flowent/tools/__pycache__/manage_settings.cpython-313.pyc +0 -0
  235. package/backend/src/flowent/tools/__pycache__/mcp.cpython-313.pyc +0 -0
  236. package/backend/src/flowent/tools/__pycache__/read.cpython-313.pyc +0 -0
  237. package/backend/src/flowent/tools/__pycache__/send.cpython-313.pyc +0 -0
  238. package/backend/src/flowent/tools/__pycache__/set_permissions.cpython-313.pyc +0 -0
  239. package/backend/src/flowent/tools/__pycache__/sleep.cpython-313.pyc +0 -0
  240. package/backend/src/flowent/tools/__pycache__/todo.cpython-313.pyc +0 -0
  241. package/backend/src/flowent/tools/connect.py +0 -100
  242. package/backend/src/flowent/tools/contacts.py +0 -22
  243. package/backend/src/flowent/tools/create_agent.py +0 -191
  244. package/backend/src/flowent/tools/create_tab.py +0 -61
  245. package/backend/src/flowent/tools/delete_tab.py +0 -39
  246. package/backend/src/flowent/tools/edit.py +0 -142
  247. package/backend/src/flowent/tools/exec.py +0 -118
  248. package/backend/src/flowent/tools/fetch.py +0 -85
  249. package/backend/src/flowent/tools/idle.py +0 -27
  250. package/backend/src/flowent/tools/list_roles.py +0 -75
  251. package/backend/src/flowent/tools/list_tabs.py +0 -100
  252. package/backend/src/flowent/tools/list_tools.py +0 -28
  253. package/backend/src/flowent/tools/manage_prompts.py +0 -102
  254. package/backend/src/flowent/tools/manage_providers.py +0 -220
  255. package/backend/src/flowent/tools/manage_roles.py +0 -275
  256. package/backend/src/flowent/tools/manage_settings.py +0 -364
  257. package/backend/src/flowent/tools/mcp.py +0 -199
  258. package/backend/src/flowent/tools/read.py +0 -152
  259. package/backend/src/flowent/tools/send.py +0 -68
  260. package/backend/src/flowent/tools/set_permissions.py +0 -99
  261. package/backend/src/flowent/tools/sleep.py +0 -41
  262. package/backend/src/flowent/tools/todo.py +0 -51
  263. package/backend/src/flowent/workspace_store.py +0 -479
  264. package/backend/tests/__init__.py +0 -0
  265. package/backend/tests/__pycache__/__init__.cpython-313.pyc +0 -0
  266. package/backend/tests/__pycache__/conftest.cpython-313-pytest-9.0.3.pyc +0 -0
  267. package/backend/tests/conftest.py +0 -6
  268. package/backend/tests/integration/api/__pycache__/conftest.cpython-313-pytest-9.0.3.pyc +0 -0
  269. package/backend/tests/integration/api/__pycache__/test_access_api.cpython-313-pytest-9.0.3.pyc +0 -0
  270. package/backend/tests/integration/api/__pycache__/test_assistant_api.cpython-313-pytest-9.0.3.pyc +0 -0
  271. package/backend/tests/integration/api/__pycache__/test_frontend_mounting.cpython-313-pytest-9.0.3.pyc +0 -0
  272. package/backend/tests/integration/api/__pycache__/test_mcp_api.cpython-313-pytest-9.0.3.pyc +0 -0
  273. package/backend/tests/integration/api/__pycache__/test_meta_api.cpython-313-pytest-9.0.3.pyc +0 -0
  274. package/backend/tests/integration/api/__pycache__/test_nodes_api.cpython-313-pytest-9.0.3.pyc +0 -0
  275. package/backend/tests/integration/api/__pycache__/test_prompts_api.cpython-313-pytest-9.0.3.pyc +0 -0
  276. package/backend/tests/integration/api/__pycache__/test_roles_api.cpython-313-pytest-9.0.3.pyc +0 -0
  277. package/backend/tests/integration/api/__pycache__/test_tabs_api.cpython-313-pytest-9.0.3.pyc +0 -0
  278. package/backend/tests/integration/api/conftest.py +0 -29
  279. package/backend/tests/integration/api/test_access_api.py +0 -182
  280. package/backend/tests/integration/api/test_assistant_api.py +0 -354
  281. package/backend/tests/integration/api/test_frontend_mounting.py +0 -61
  282. package/backend/tests/integration/api/test_mcp_api.py +0 -116
  283. package/backend/tests/integration/api/test_meta_api.py +0 -33
  284. package/backend/tests/integration/api/test_nodes_api.py +0 -722
  285. package/backend/tests/integration/api/test_prompts_api.py +0 -47
  286. package/backend/tests/integration/api/test_roles_api.py +0 -228
  287. package/backend/tests/integration/api/test_tabs_api.py +0 -802
  288. package/backend/tests/unit/__pycache__/test_access.cpython-313-pytest-9.0.3.pyc +0 -0
  289. package/backend/tests/unit/__pycache__/test_cli.cpython-313-pytest-9.0.3.pyc +0 -0
  290. package/backend/tests/unit/__pycache__/test_graph_runtime.cpython-313-pytest-9.0.3.pyc +0 -0
  291. package/backend/tests/unit/__pycache__/test_network.cpython-313-pytest-9.0.3.pyc +0 -0
  292. package/backend/tests/unit/__pycache__/test_state_sqlite_storage.cpython-313-pytest-9.0.3.pyc +0 -0
  293. package/backend/tests/unit/__pycache__/test_workspace_store.cpython-313-pytest-9.0.3.pyc +0 -0
  294. package/backend/tests/unit/agent/__pycache__/test_agent_public_api.cpython-313-pytest-9.0.3.pyc +0 -0
  295. package/backend/tests/unit/agent/__pycache__/test_agent_runtime.cpython-313-pytest-9.0.3.pyc +0 -0
  296. package/backend/tests/unit/agent/test_agent_public_api.py +0 -837
  297. package/backend/tests/unit/agent/test_agent_runtime.py +0 -2942
  298. package/backend/tests/unit/channels/__pycache__/test_telegram_channel.cpython-313-pytest-9.0.3.pyc +0 -0
  299. package/backend/tests/unit/channels/test_telegram_channel.py +0 -552
  300. package/backend/tests/unit/logging/__pycache__/test_logging.cpython-313-pytest-9.0.3.pyc +0 -0
  301. package/backend/tests/unit/logging/test_logging.py +0 -132
  302. package/backend/tests/unit/prompts/__pycache__/test_prompts.cpython-313-pytest-9.0.3.pyc +0 -0
  303. package/backend/tests/unit/prompts/test_prompts.py +0 -570
  304. package/backend/tests/unit/providers/__pycache__/test_anthropic_provider.cpython-313-pytest-9.0.3.pyc +0 -0
  305. package/backend/tests/unit/providers/__pycache__/test_errors.cpython-313-pytest-9.0.3.pyc +0 -0
  306. package/backend/tests/unit/providers/__pycache__/test_extract_delta_parts.cpython-313-pytest-9.0.3.pyc +0 -0
  307. package/backend/tests/unit/providers/__pycache__/test_openai_provider.cpython-313-pytest-9.0.3.pyc +0 -0
  308. package/backend/tests/unit/providers/__pycache__/test_openai_responses.cpython-313-pytest-9.0.3.pyc +0 -0
  309. package/backend/tests/unit/providers/__pycache__/test_provider_gateway.cpython-313-pytest-9.0.3.pyc +0 -0
  310. package/backend/tests/unit/providers/__pycache__/test_think_tag_parser.cpython-313-pytest-9.0.3.pyc +0 -0
  311. package/backend/tests/unit/providers/test_anthropic_provider.py +0 -185
  312. package/backend/tests/unit/providers/test_errors.py +0 -68
  313. package/backend/tests/unit/providers/test_extract_delta_parts.py +0 -22
  314. package/backend/tests/unit/providers/test_openai_provider.py +0 -139
  315. package/backend/tests/unit/providers/test_openai_responses.py +0 -402
  316. package/backend/tests/unit/providers/test_provider_gateway.py +0 -359
  317. package/backend/tests/unit/providers/test_think_tag_parser.py +0 -36
  318. package/backend/tests/unit/routes/__pycache__/test_prompts_routes.cpython-313-pytest-9.0.3.pyc +0 -0
  319. package/backend/tests/unit/routes/__pycache__/test_providers_route.cpython-313-pytest-9.0.3.pyc +0 -0
  320. package/backend/tests/unit/routes/__pycache__/test_roles_routes.cpython-313-pytest-9.0.3.pyc +0 -0
  321. package/backend/tests/unit/routes/__pycache__/test_settings_routes.cpython-313-pytest-9.0.3.pyc +0 -0
  322. package/backend/tests/unit/routes/test_prompts_routes.py +0 -104
  323. package/backend/tests/unit/routes/test_providers_route.py +0 -370
  324. package/backend/tests/unit/routes/test_roles_routes.py +0 -535
  325. package/backend/tests/unit/routes/test_settings_routes.py +0 -1142
  326. package/backend/tests/unit/runtime/__pycache__/test_bootstrap_runtime.cpython-313-pytest-9.0.3.pyc +0 -0
  327. package/backend/tests/unit/runtime/test_bootstrap_runtime.py +0 -1002
  328. package/backend/tests/unit/sandbox/__pycache__/test_sandbox_tools.cpython-313-pytest-9.0.3.pyc +0 -0
  329. package/backend/tests/unit/sandbox/test_sandbox_tools.py +0 -78
  330. package/backend/tests/unit/security/__pycache__/test_security.cpython-313-pytest-9.0.3.pyc +0 -0
  331. package/backend/tests/unit/security/test_security.py +0 -124
  332. package/backend/tests/unit/settings/__pycache__/test_settings_roles.cpython-313-pytest-9.0.3.pyc +0 -0
  333. package/backend/tests/unit/settings/test_settings_roles.py +0 -751
  334. package/backend/tests/unit/test_access.py +0 -45
  335. package/backend/tests/unit/test_cli.py +0 -124
  336. package/backend/tests/unit/test_graph_runtime.py +0 -72
  337. package/backend/tests/unit/test_network.py +0 -51
  338. package/backend/tests/unit/test_state_sqlite_storage.py +0 -159
  339. package/backend/tests/unit/test_workspace_store.py +0 -231
  340. package/backend/tests/unit/tools/__pycache__/test_connect_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  341. package/backend/tests/unit/tools/__pycache__/test_create_agent_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  342. package/backend/tests/unit/tools/__pycache__/test_delete_tab_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  343. package/backend/tests/unit/tools/__pycache__/test_edit_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  344. package/backend/tests/unit/tools/__pycache__/test_exec_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  345. package/backend/tests/unit/tools/__pycache__/test_fetch_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  346. package/backend/tests/unit/tools/__pycache__/test_manage_prompts_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  347. package/backend/tests/unit/tools/__pycache__/test_manage_providers_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  348. package/backend/tests/unit/tools/__pycache__/test_manage_roles_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  349. package/backend/tests/unit/tools/__pycache__/test_manage_settings_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  350. package/backend/tests/unit/tools/__pycache__/test_read_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  351. package/backend/tests/unit/tools/__pycache__/test_set_permissions_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  352. package/backend/tests/unit/tools/__pycache__/test_todo_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  353. package/backend/tests/unit/tools/__pycache__/test_tool_registry.cpython-313-pytest-9.0.3.pyc +0 -0
  354. package/backend/tests/unit/tools/test_connect_tool.py +0 -228
  355. package/backend/tests/unit/tools/test_create_agent_tool.py +0 -436
  356. package/backend/tests/unit/tools/test_delete_tab_tool.py +0 -116
  357. package/backend/tests/unit/tools/test_edit_tool.py +0 -115
  358. package/backend/tests/unit/tools/test_exec_tool.py +0 -81
  359. package/backend/tests/unit/tools/test_fetch_tool.py +0 -65
  360. package/backend/tests/unit/tools/test_manage_prompts_tool.py +0 -117
  361. package/backend/tests/unit/tools/test_manage_providers_tool.py +0 -460
  362. package/backend/tests/unit/tools/test_manage_roles_tool.py +0 -411
  363. package/backend/tests/unit/tools/test_manage_settings_tool.py +0 -611
  364. package/backend/tests/unit/tools/test_read_tool.py +0 -33
  365. package/backend/tests/unit/tools/test_set_permissions_tool.py +0 -595
  366. package/backend/tests/unit/tools/test_todo_tool.py +0 -37
  367. package/backend/tests/unit/tools/test_tool_registry.py +0 -194
  368. package/dist/frontend/assets/AssistantPage-VBohhz4d.js +0 -1
  369. package/dist/frontend/assets/ChannelsPage-CIydPZA_.js +0 -1
  370. package/dist/frontend/assets/McpPage-CHPm2TPY.js +0 -7
  371. package/dist/frontend/assets/PageScaffold-DteOA8V7.js +0 -1
  372. package/dist/frontend/assets/PromptsPage-CSmJ3sZg.js +0 -1
  373. package/dist/frontend/assets/ProvidersPage-sl2jeG4e.js +0 -3
  374. package/dist/frontend/assets/RolesPage-DCe7W6Km.js +0 -1
  375. package/dist/frontend/assets/SettingsPage-Bix9e63E.js +0 -3
  376. package/dist/frontend/assets/ToolsPage-favNkj5C.js +0 -1
  377. package/dist/frontend/assets/WorkspaceCommandDialog-DRS6wiD6.js +0 -1
  378. package/dist/frontend/assets/WorkspacePage-KuaDjt_D.js +0 -3
  379. package/dist/frontend/assets/WorkspacePanels-BZxBw8M5.js +0 -1
  380. package/dist/frontend/assets/alert-dialog-DIBUCmqM.js +0 -1
  381. package/dist/frontend/assets/datetime-eJqd0V2S.js +0 -1
  382. package/dist/frontend/assets/dialog-BOvHIBrg.js +0 -1
  383. package/dist/frontend/assets/elk-worker.min-C9JGDOE-.js +0 -6312
  384. package/dist/frontend/assets/graph-vendor-CHpVij2M.css +0 -1
  385. package/dist/frontend/assets/graph-vendor-DRq_-6fV.js +0 -7
  386. package/dist/frontend/assets/index-Biio-CoI.js +0 -10
  387. package/dist/frontend/assets/index-CmQvO7sl.css +0 -1
  388. package/dist/frontend/assets/layout.worker-jMHqAFbP.js +0 -24
  389. package/dist/frontend/assets/markdown-vendor-C9RtvaJh.js +0 -29
  390. package/dist/frontend/assets/modelParams-DcEhGnu0.js +0 -1
  391. package/dist/frontend/assets/react-vendor-mEs_JJxa.js +0 -9
  392. package/dist/frontend/assets/roles-BbIEIMeG.js +0 -1
  393. package/dist/frontend/assets/rolldown-runtime-BYbx6iT9.js +0 -1
  394. package/dist/frontend/assets/select-D9SwnlXF.js +0 -1
  395. package/dist/frontend/assets/surface-Bzr1FRG4.js +0 -1
  396. package/dist/frontend/assets/triState-DgLlKdRR.js +0 -1
  397. package/dist/frontend/assets/ui-vendor-UazN8rcv.js +0 -51
  398. package/dist/frontend/favicon.svg +0 -4
@@ -1,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
- )
@@ -1,220 +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
- if TYPE_CHECKING:
10
- from flowent.agent import Agent
11
-
12
- from flowent.providers.configuration import serialize_discovered_model_catalog_entry
13
- from flowent.providers.management import (
14
- ProviderNotFoundError,
15
- create_provider_entry,
16
- delete_provider_entry,
17
- list_provider_payloads,
18
- update_provider_entry,
19
- )
20
- from flowent.settings import (
21
- build_provider_headers,
22
- build_provider_retry_429_delay_seconds,
23
- )
24
- from flowent.tools import Tool, re_raise_interrupt
25
-
26
-
27
- class ManageProvidersTool(Tool):
28
- name = "manage_providers"
29
- description = (
30
- "Manage LLM provider configuration. Supports listing, creating, "
31
- "updating, deleting providers, and listing models for a provider."
32
- )
33
- parameters: ClassVar[dict[str, Any]] = {
34
- "type": "object",
35
- "properties": {
36
- "action": {
37
- "type": "string",
38
- "enum": ["list", "create", "update", "delete", "list_models"],
39
- "description": "Provider management action",
40
- },
41
- "id": {
42
- "type": "string",
43
- "description": "Target provider ID for update, delete, or list_models",
44
- },
45
- "name": {
46
- "type": "string",
47
- "description": "Provider display name",
48
- },
49
- "type": {
50
- "type": "string",
51
- "description": "Provider type, such as openai_compatible",
52
- },
53
- "base_url": {
54
- "type": "string",
55
- "description": "Provider API base URL",
56
- },
57
- "api_key": {
58
- "type": "string",
59
- "description": "Provider API key",
60
- },
61
- "headers": {
62
- "type": "object",
63
- "description": "Provider request header overrides",
64
- "additionalProperties": {"type": "string"},
65
- },
66
- "retry_429_delay_seconds": {
67
- "type": "integer",
68
- "description": "Extra wait time in seconds after HTTP 429 before retrying",
69
- },
70
- },
71
- "required": ["action"],
72
- }
73
-
74
- def execute(self, agent: Agent, args: dict[str, Any], **kwargs: Any) -> str:
75
- from flowent.providers.gateway import gateway
76
- from flowent.settings import get_settings, save_settings
77
-
78
- on_output: Callable[[str], None] | None = kwargs.get("on_output")
79
- action = args.get("action")
80
- provider_id = args.get("id")
81
- name = args.get("name")
82
- provider_type = args.get("type")
83
- base_url = args.get("base_url")
84
- api_key = args.get("api_key")
85
- raw_headers = args.get("headers")
86
- retry_429_delay_seconds = args.get("retry_429_delay_seconds")
87
-
88
- if not isinstance(action, str):
89
- return json.dumps({"error": "action must be a string"})
90
-
91
- if provider_id is not None and not isinstance(provider_id, str):
92
- return json.dumps({"error": "id must be a string"})
93
- if name is not None and not isinstance(name, str):
94
- return json.dumps({"error": "name must be a string"})
95
- if provider_type is not None and not isinstance(provider_type, str):
96
- return json.dumps({"error": "type must be a string"})
97
- if base_url is not None and not isinstance(base_url, str):
98
- return json.dumps({"error": "base_url must be a string"})
99
- if api_key is not None and not isinstance(api_key, str):
100
- return json.dumps({"error": "api_key must be a string"})
101
- if raw_headers is not None and not isinstance(raw_headers, dict):
102
- return json.dumps({"error": "headers must be a JSON object"})
103
- if retry_429_delay_seconds is not None:
104
- try:
105
- build_provider_retry_429_delay_seconds(retry_429_delay_seconds)
106
- except ValueError as exc:
107
- return json.dumps({"error": str(exc)})
108
-
109
- try:
110
- headers = (
111
- build_provider_headers(raw_headers) if raw_headers is not None else None
112
- )
113
- except ValueError as exc:
114
- return json.dumps({"error": str(exc)})
115
-
116
- settings = get_settings()
117
-
118
- if action == "list":
119
- return json.dumps(list_provider_payloads(settings, include_api_key=False))
120
-
121
- if action == "create":
122
- if not isinstance(name, str) or not name.strip():
123
- return json.dumps({"error": "name is required"})
124
- if not isinstance(provider_type, str) or not provider_type.strip():
125
- return json.dumps({"error": "type is required"})
126
- if not isinstance(base_url, str) or not base_url.strip():
127
- return json.dumps({"error": "base_url is required"})
128
- try:
129
- provider = create_provider_entry(
130
- settings,
131
- name=name,
132
- provider_type=provider_type,
133
- base_url=base_url,
134
- api_key=api_key or "",
135
- raw_headers=headers,
136
- raw_retry_429_delay_seconds=(
137
- retry_429_delay_seconds
138
- if retry_429_delay_seconds is not None
139
- else 0
140
- ),
141
- base_url_required_message="base_url is required",
142
- )
143
- except ValueError as exc:
144
- return json.dumps({"error": str(exc)})
145
- save_settings(settings)
146
- gateway.invalidate_cache()
147
- return json.dumps(
148
- list_provider_payloads(settings, include_api_key=False)[-1]
149
- )
150
-
151
- if action == "update":
152
- if not isinstance(provider_id, str) or not provider_id:
153
- return json.dumps({"error": "id is required"})
154
-
155
- try:
156
- provider = update_provider_entry(
157
- settings,
158
- provider_id,
159
- name=name,
160
- provider_type=provider_type,
161
- base_url=base_url,
162
- api_key=api_key,
163
- raw_headers=headers,
164
- raw_retry_429_delay_seconds=retry_429_delay_seconds,
165
- )
166
- except ValueError as exc:
167
- return json.dumps({"error": str(exc)})
168
- except ProviderNotFoundError:
169
- return json.dumps({"error": f"Provider '{provider_id}' not found"})
170
- save_settings(settings)
171
- gateway.invalidate_cache()
172
- return json.dumps(
173
- list_provider_payloads(settings, include_api_key=False)[
174
- settings.providers.index(provider)
175
- ]
176
- )
177
-
178
- if action == "delete":
179
- if not isinstance(provider_id, str) or not provider_id:
180
- return json.dumps({"error": "id is required"})
181
-
182
- try:
183
- delete_provider_entry(settings, provider_id)
184
- except ProviderNotFoundError:
185
- return json.dumps({"error": f"Provider '{provider_id}' not found"})
186
- save_settings(settings)
187
- gateway.invalidate_cache()
188
- return json.dumps({"status": "deleted"})
189
-
190
- if action == "list_models":
191
- if not isinstance(provider_id, str) or not provider_id:
192
- return json.dumps({"error": "id is required"})
193
- try:
194
- if on_output is not None:
195
- on_output(f"Listing models for {provider_id}\n")
196
- models = gateway.list_models_for(
197
- provider_id,
198
- register_interrupt=agent.set_interrupt_callback,
199
- )
200
- if on_output is not None:
201
- for model in models:
202
- on_output(f"{model.id}\n")
203
- return json.dumps(
204
- [
205
- serialize_discovered_model_catalog_entry(model)
206
- for model in models
207
- ]
208
- )
209
- except Exception as exc:
210
- re_raise_interrupt(agent, exc)
211
- logger.error(
212
- "Failed to list models for provider '{}': {}",
213
- provider_id,
214
- exc,
215
- )
216
- return json.dumps({"error": str(exc)})
217
- finally:
218
- agent.set_interrupt_callback(None)
219
-
220
- return json.dumps({"error": f"Unsupported action: {action}"})
@@ -1,275 +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.role_management import (
10
- apply_role_update,
11
- build_role_config,
12
- ensure_role_name_available,
13
- find_role_by_name,
14
- normalize_optional_role_description,
15
- normalize_optional_role_name,
16
- remove_role,
17
- require_role_description,
18
- require_role_name,
19
- resolve_role_model,
20
- resolve_role_model_params,
21
- resolve_role_tool_config,
22
- sync_running_system_roles,
23
- validate_builtin_role_update,
24
- )
25
- from flowent.tools import Tool
26
-
27
-
28
- class ManageRolesTool(Tool):
29
- name = "manage_roles"
30
- description = (
31
- "Manage Role configuration. Supports listing, creating, updating, "
32
- "and deleting roles. Built-in roles cannot be deleted, renamed, "
33
- "or modified except for model and model_params configuration."
34
- )
35
- parameters: ClassVar[dict[str, Any]] = {
36
- "type": "object",
37
- "properties": {
38
- "action": {
39
- "type": "string",
40
- "enum": ["list", "create", "update", "delete"],
41
- "description": "Role management action",
42
- },
43
- "name": {
44
- "type": "string",
45
- "description": "Role name for create, update, or delete",
46
- },
47
- "new_name": {
48
- "type": "string",
49
- "description": "New role name for update",
50
- },
51
- "description": {
52
- "type": "string",
53
- "description": "Short role description used when choosing a role",
54
- },
55
- "system_prompt": {
56
- "type": "string",
57
- "description": "Role system prompt",
58
- },
59
- "model": {
60
- "type": ["object", "null"],
61
- "description": "Optional provider and model override for this role",
62
- "properties": {
63
- "provider_id": {"type": "string"},
64
- "model": {"type": "string"},
65
- },
66
- "required": ["provider_id", "model"],
67
- "additionalProperties": False,
68
- },
69
- "model_params": {
70
- "type": ["object", "null"],
71
- "description": "Optional canonical model parameter overrides",
72
- "properties": {
73
- "reasoning_effort": {
74
- "type": "string",
75
- "enum": ["none", "low", "medium", "high", "xhigh"],
76
- },
77
- "verbosity": {
78
- "type": "string",
79
- "enum": ["low", "medium", "high"],
80
- },
81
- "max_output_tokens": {"type": "integer"},
82
- "temperature": {"type": "number"},
83
- "top_p": {"type": "number"},
84
- },
85
- "additionalProperties": False,
86
- },
87
- "included_tools": {
88
- "type": "array",
89
- "items": {"type": "string"},
90
- "description": "Tools always included in the role",
91
- },
92
- "excluded_tools": {
93
- "type": "array",
94
- "items": {"type": "string"},
95
- "description": "Tools always excluded from the role",
96
- },
97
- },
98
- "required": ["action"],
99
- }
100
-
101
- def execute(self, agent: Agent, args: dict[str, Any], **_kwargs: Any) -> str:
102
- from flowent.providers.gateway import gateway
103
- from flowent.settings import (
104
- get_settings,
105
- is_builtin_role_name,
106
- save_settings,
107
- serialize_role,
108
- )
109
-
110
- action = args.get("action")
111
- role_name = args.get("name")
112
- new_name = args.get("new_name")
113
- description = args.get("description")
114
- system_prompt = args.get("system_prompt")
115
- role_model = args.get("model")
116
- role_model_params = args.get("model_params")
117
- included_tools = args.get("included_tools")
118
- excluded_tools = args.get("excluded_tools")
119
-
120
- if not isinstance(action, str):
121
- return json.dumps({"error": "action must be a string"})
122
-
123
- if role_name is not None and not isinstance(role_name, str):
124
- return json.dumps({"error": "name must be a string"})
125
- if new_name is not None and not isinstance(new_name, str):
126
- return json.dumps({"error": "new_name must be a string"})
127
- if description is not None and not isinstance(description, str):
128
- return json.dumps({"error": "description must be a string"})
129
- if system_prompt is not None and not isinstance(system_prompt, str):
130
- return json.dumps({"error": "system_prompt must be a string"})
131
- if included_tools is not None and (
132
- not isinstance(included_tools, list)
133
- or not all(isinstance(tool_name, str) for tool_name in included_tools)
134
- ):
135
- return json.dumps({"error": "included_tools must be an array of strings"})
136
- if excluded_tools is not None and (
137
- not isinstance(excluded_tools, list)
138
- or not all(isinstance(tool_name, str) for tool_name in excluded_tools)
139
- ):
140
- return json.dumps({"error": "excluded_tools must be an array of strings"})
141
-
142
- settings = get_settings()
143
-
144
- if action == "list":
145
- return json.dumps([serialize_role(role) for role in settings.roles])
146
-
147
- if action == "create":
148
- if not isinstance(system_prompt, str):
149
- return json.dumps({"error": "system_prompt is required"})
150
- try:
151
- name = require_role_name(role_name or "")
152
- description_text = require_role_description(description or "")
153
- ensure_role_name_available(settings.roles, name)
154
- next_included, next_excluded = resolve_role_tool_config(
155
- None,
156
- included_tools,
157
- excluded_tools,
158
- )
159
- next_model = resolve_role_model(
160
- role_model,
161
- settings=settings,
162
- current=None,
163
- provided="model" in args,
164
- invalid_type_error="model must be an object or null",
165
- missing_provider_id_error=(
166
- "model.provider_id must be a non-empty string"
167
- ),
168
- missing_model_error="model.model must be a non-empty string",
169
- )
170
- next_model_params = resolve_role_model_params(
171
- role_model_params,
172
- current=None,
173
- provided="model_params" in args,
174
- )
175
- except ValueError as exc:
176
- return json.dumps({"error": str(exc)})
177
- new_role = build_role_config(
178
- name=name,
179
- description=description_text,
180
- system_prompt=system_prompt,
181
- model=next_model,
182
- model_params=next_model_params,
183
- included_tools=next_included,
184
- excluded_tools=next_excluded,
185
- )
186
- settings.roles.append(new_role)
187
- save_settings(settings)
188
- gateway.invalidate_cache()
189
- return json.dumps(serialize_role(new_role))
190
-
191
- if action == "update":
192
- if not isinstance(role_name, str) or not role_name:
193
- return json.dumps({"error": "name is required"})
194
-
195
- target_role = find_role_by_name(settings.roles, role_name)
196
- if target_role is None:
197
- return json.dumps({"error": f"Role '{role_name}' not found"})
198
-
199
- try:
200
- next_included, next_excluded = resolve_role_tool_config(
201
- target_role,
202
- included_tools,
203
- excluded_tools,
204
- )
205
- next_model = resolve_role_model(
206
- role_model,
207
- settings=settings,
208
- current=target_role.model,
209
- provided="model" in args,
210
- invalid_type_error="model must be an object or null",
211
- missing_provider_id_error=(
212
- "model.provider_id must be a non-empty string"
213
- ),
214
- missing_model_error="model.model must be a non-empty string",
215
- )
216
- next_model_params = resolve_role_model_params(
217
- role_model_params,
218
- current=target_role.model_params,
219
- provided="model_params" in args,
220
- )
221
- stripped_name = normalize_optional_role_name(new_name)
222
- stripped_description = normalize_optional_role_description(description)
223
- if stripped_name is not None:
224
- ensure_role_name_available(
225
- settings.roles,
226
- stripped_name,
227
- current_name=target_role.name,
228
- )
229
- validate_builtin_role_update(
230
- target_role,
231
- next_name=stripped_name,
232
- next_description=stripped_description,
233
- next_system_prompt=system_prompt,
234
- next_included_tools=next_included,
235
- next_excluded_tools=next_excluded,
236
- )
237
- except ValueError as exc:
238
- return json.dumps({"error": str(exc)})
239
- target_role = apply_role_update(
240
- settings=settings,
241
- role=target_role,
242
- next_name=stripped_name,
243
- next_description=stripped_description,
244
- next_system_prompt=system_prompt,
245
- next_model=next_model,
246
- update_model="model" in args,
247
- next_model_params=next_model_params,
248
- update_model_params="model_params" in args,
249
- next_included_tools=next_included,
250
- next_excluded_tools=next_excluded,
251
- )
252
- save_settings(settings)
253
- sync_running_system_roles()
254
- gateway.invalidate_cache()
255
- return json.dumps(serialize_role(target_role))
256
-
257
- if action == "delete":
258
- if not isinstance(role_name, str) or not role_name:
259
- return json.dumps({"error": "name is required"})
260
- if is_builtin_role_name(role_name):
261
- return json.dumps(
262
- {"error": f"Cannot delete built-in role '{role_name}'"}
263
- )
264
-
265
- target_role = find_role_by_name(settings.roles, role_name)
266
- if target_role is None:
267
- return json.dumps({"error": f"Role '{role_name}' not found"})
268
-
269
- remove_role(settings, target_role)
270
- save_settings(settings)
271
- sync_running_system_roles()
272
- gateway.invalidate_cache()
273
- return json.dumps({"status": "deleted"})
274
-
275
- return json.dumps({"error": f"Unsupported action: {action}"})