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,46 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from fastapi import APIRouter
4
- from pydantic import AliasChoices, BaseModel, Field
5
-
6
- from flowent.settings import get_settings, save_settings
7
-
8
- router = APIRouter()
9
-
10
-
11
- class PromptSettingsResponse(BaseModel):
12
- custom_prompt: str
13
- custom_post_prompt: str
14
-
15
-
16
- class UpdatePromptSettingsRequest(BaseModel):
17
- custom_prompt: str | None = None
18
- custom_post_prompt: str | None = Field(
19
- default=None,
20
- validation_alias=AliasChoices("custom_post_prompt", "post_prompt"),
21
- )
22
-
23
-
24
- @router.get("/api/prompts")
25
- async def get_prompts() -> PromptSettingsResponse:
26
- settings = get_settings()
27
- return PromptSettingsResponse(
28
- custom_prompt=settings.custom_prompt,
29
- custom_post_prompt=settings.custom_post_prompt,
30
- )
31
-
32
-
33
- @router.put("/api/prompts")
34
- async def update_prompts(
35
- req: UpdatePromptSettingsRequest,
36
- ) -> PromptSettingsResponse:
37
- settings = get_settings()
38
- if req.custom_prompt is not None:
39
- settings.custom_prompt = req.custom_prompt
40
- if req.custom_post_prompt is not None:
41
- settings.custom_post_prompt = req.custom_post_prompt
42
- save_settings(settings)
43
- return PromptSettingsResponse(
44
- custom_prompt=settings.custom_prompt,
45
- custom_post_prompt=settings.custom_post_prompt,
46
- )
@@ -1,365 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import time
4
-
5
- from fastapi import APIRouter, HTTPException
6
- from loguru import logger
7
- from pydantic import BaseModel, Field
8
- from starlette.concurrency import run_in_threadpool
9
-
10
- from flowent.models import ModelInfo
11
- from flowent.network import truncate_text
12
- from flowent.providers.configuration import (
13
- build_provider_config,
14
- coerce_provider_model_catalog,
15
- serialize_discovered_model_catalog_entry,
16
- serialize_provider,
17
- )
18
- from flowent.providers.management import (
19
- ProviderNotFoundError,
20
- create_provider_entry,
21
- delete_provider_entry,
22
- list_provider_payloads,
23
- update_provider_entry,
24
- )
25
- from flowent.providers.registry import create_provider as create_llm_provider
26
- from flowent.settings import (
27
- ProviderConfig,
28
- find_provider,
29
- get_settings,
30
- save_settings,
31
- )
32
-
33
- router = APIRouter()
34
-
35
-
36
- class ProviderModelRequest(BaseModel):
37
- model: str
38
- source: str = "manual"
39
- context_window_tokens: int | None = None
40
- input_image: bool | None = None
41
- output_image: bool | None = None
42
- structured_output: bool | None = None
43
-
44
-
45
- class CreateProviderRequest(BaseModel):
46
- name: str
47
- type: str
48
- base_url: str
49
- api_key: str = ""
50
- headers: dict[str, object] | None = None
51
- retry_429_delay_seconds: int = 0
52
- models: list[ProviderModelRequest] = Field(default_factory=list)
53
-
54
-
55
- class UpdateProviderRequest(BaseModel):
56
- name: str | None = None
57
- type: str | None = None
58
- base_url: str | None = None
59
- api_key: str | None = None
60
- headers: dict[str, object] | None = None
61
- retry_429_delay_seconds: int | None = None
62
- models: list[ProviderModelRequest] | None = None
63
-
64
-
65
- class ProviderDraftRequest(BaseModel):
66
- provider_id: str | None = None
67
- name: str | None = None
68
- type: str | None = None
69
- base_url: str | None = None
70
- api_key: str | None = None
71
- headers: dict[str, object] | None = None
72
-
73
-
74
- class ListModelsRequest(ProviderDraftRequest):
75
- pass
76
-
77
-
78
- class ProviderModelTestRequest(ProviderDraftRequest):
79
- model: str
80
-
81
-
82
- def _has_draft_provider_fields(req: ProviderDraftRequest) -> bool:
83
- return any(
84
- value is not None
85
- for value in (
86
- req.name,
87
- req.type,
88
- req.base_url,
89
- req.api_key,
90
- req.headers,
91
- )
92
- )
93
-
94
-
95
- def _resolve_provider_from_request(req: ProviderDraftRequest) -> ProviderConfig:
96
- settings = get_settings()
97
- saved_provider = (
98
- find_provider(settings, req.provider_id)
99
- if req.provider_id is not None
100
- else None
101
- )
102
- if (
103
- req.provider_id is not None
104
- and saved_provider is None
105
- and not _has_draft_provider_fields(req)
106
- ):
107
- raise HTTPException(status_code=404, detail="Provider not found")
108
-
109
- provider_type = (
110
- req.type.strip()
111
- if isinstance(req.type, str) and req.type.strip()
112
- else saved_provider.type
113
- if saved_provider is not None
114
- else ""
115
- )
116
- if not provider_type:
117
- raise HTTPException(status_code=400, detail="provider type is required")
118
-
119
- base_url = (
120
- req.base_url.strip()
121
- if isinstance(req.base_url, str) and req.base_url.strip()
122
- else saved_provider.base_url
123
- if saved_provider is not None
124
- else ""
125
- )
126
- if not base_url:
127
- raise HTTPException(status_code=400, detail="provider base_url is required")
128
-
129
- try:
130
- return build_provider_config(
131
- provider_id=(
132
- saved_provider.id
133
- if saved_provider is not None
134
- else req.provider_id or ""
135
- ),
136
- name=(
137
- req.name
138
- if isinstance(req.name, str)
139
- else saved_provider.name
140
- if saved_provider is not None
141
- else ""
142
- ),
143
- provider_type=provider_type,
144
- base_url=base_url,
145
- api_key=(
146
- req.api_key
147
- if isinstance(req.api_key, str)
148
- else saved_provider.api_key
149
- if saved_provider is not None
150
- else ""
151
- ),
152
- raw_headers=(
153
- req.headers
154
- if req.headers is not None
155
- else saved_provider.headers
156
- if saved_provider is not None
157
- else {}
158
- ),
159
- raw_retry_429_delay_seconds=(
160
- saved_provider.retry_429_delay_seconds
161
- if saved_provider is not None
162
- else 0
163
- ),
164
- models=list(saved_provider.models) if saved_provider is not None else [],
165
- base_url_required_message="provider base_url is required",
166
- )
167
- except ValueError as exc:
168
- raise HTTPException(status_code=400, detail=str(exc)) from exc
169
-
170
-
171
- def _list_models_with_provider(provider: ProviderConfig) -> list[ModelInfo]:
172
- llm_provider = create_llm_provider(
173
- provider_type=provider.type,
174
- base_url=provider.base_url,
175
- api_key=provider.api_key,
176
- headers=provider.headers,
177
- model="",
178
- provider_name=provider.name,
179
- request_timeout_seconds=120.0,
180
- )
181
- return llm_provider.list_models()
182
-
183
-
184
- def _summarize_provider_error(error: Exception) -> str:
185
- detail = str(error).strip()
186
- if not detail:
187
- return "Provider test failed"
188
-
189
- for line in detail.splitlines():
190
- stripped = line.strip()
191
- if stripped.startswith("Detail:"):
192
- normalized = stripped.removeprefix("Detail:").strip()
193
- if normalized:
194
- return truncate_text(normalized, limit=240)
195
-
196
- first_line = next(
197
- (line.strip() for line in detail.splitlines() if line.strip()), ""
198
- )
199
- if not first_line or first_line.lower().startswith("traceback"):
200
- return "Provider returned an unexpected error response"
201
- return truncate_text(first_line, limit=240)
202
-
203
-
204
- def _test_provider_model(provider: ProviderConfig, model: str) -> dict[str, object]:
205
- settings = get_settings()
206
- llm_provider = create_llm_provider(
207
- provider_type=provider.type,
208
- base_url=provider.base_url,
209
- api_key=provider.api_key,
210
- headers=provider.headers,
211
- model=model,
212
- provider_name=provider.name,
213
- request_timeout_seconds=max(settings.model.timeout_ms / 1000, 1.0),
214
- )
215
- started_at = time.perf_counter()
216
- llm_provider.chat(
217
- [{"role": "user", "content": "Reply with OK."}],
218
- )
219
- ended_at = time.perf_counter()
220
- return {
221
- "ok": True,
222
- "duration_ms": int((ended_at - started_at) * 1000),
223
- }
224
-
225
-
226
- @router.get("/api/providers")
227
- async def list_providers() -> dict[str, object]:
228
- settings = get_settings()
229
- return {"providers": list_provider_payloads(settings)}
230
-
231
-
232
- @router.post("/api/providers")
233
- async def create_provider(req: CreateProviderRequest) -> dict[str, object]:
234
- from flowent.providers.gateway import gateway
235
-
236
- settings = get_settings()
237
- try:
238
- provider = create_provider_entry(
239
- settings,
240
- name=req.name,
241
- provider_type=req.type,
242
- base_url=req.base_url,
243
- api_key=req.api_key,
244
- raw_headers=req.headers,
245
- raw_retry_429_delay_seconds=req.retry_429_delay_seconds,
246
- models=coerce_provider_model_catalog(req.models),
247
- )
248
- except ValueError as exc:
249
- raise HTTPException(status_code=400, detail=str(exc)) from exc
250
- save_settings(settings)
251
- gateway.invalidate_cache()
252
- return serialize_provider(provider)
253
-
254
-
255
- @router.put("/api/providers/{provider_id}")
256
- async def update_provider(
257
- provider_id: str, req: UpdateProviderRequest
258
- ) -> dict[str, object]:
259
- from flowent.providers.gateway import gateway
260
-
261
- settings = get_settings()
262
- try:
263
- provider = update_provider_entry(
264
- settings,
265
- provider_id,
266
- name=req.name,
267
- provider_type=req.type,
268
- base_url=req.base_url,
269
- api_key=req.api_key,
270
- raw_headers=req.headers,
271
- raw_retry_429_delay_seconds=req.retry_429_delay_seconds,
272
- models=(
273
- coerce_provider_model_catalog(req.models)
274
- if req.models is not None
275
- else None
276
- ),
277
- )
278
- except ValueError as exc:
279
- raise HTTPException(status_code=400, detail=str(exc)) from exc
280
- except ProviderNotFoundError as exc:
281
- raise HTTPException(status_code=404, detail="Provider not found") from exc
282
- save_settings(settings)
283
- gateway.invalidate_cache()
284
- return serialize_provider(provider)
285
-
286
-
287
- @router.delete("/api/providers/{provider_id}")
288
- async def delete_provider(provider_id: str) -> dict[str, object]:
289
- from flowent.providers.gateway import gateway
290
-
291
- settings = get_settings()
292
- try:
293
- delete_provider_entry(settings, provider_id)
294
- except ProviderNotFoundError as exc:
295
- raise HTTPException(status_code=404, detail="Provider not found") from exc
296
- save_settings(settings)
297
- gateway.invalidate_cache()
298
- return {"status": "deleted"}
299
-
300
-
301
- @router.post("/api/providers/models")
302
- async def list_provider_models(req: ListModelsRequest) -> dict[str, object]:
303
- from flowent.providers.gateway import gateway
304
-
305
- if req.provider_id is not None and not _has_draft_provider_fields(req):
306
- try:
307
- models = await run_in_threadpool(gateway.list_models_for, req.provider_id)
308
- return {
309
- "models": [
310
- serialize_discovered_model_catalog_entry(model) for model in models
311
- ]
312
- }
313
- except Exception as exc:
314
- logger.error(
315
- "Failed to list models for provider '{}': {}",
316
- req.provider_id,
317
- exc,
318
- )
319
- raise HTTPException(
320
- status_code=500,
321
- detail=_summarize_provider_error(exc),
322
- ) from exc
323
-
324
- provider = _resolve_provider_from_request(req)
325
-
326
- try:
327
- models = await run_in_threadpool(_list_models_with_provider, provider)
328
- return {
329
- "models": [
330
- serialize_discovered_model_catalog_entry(model) for model in models
331
- ]
332
- }
333
- except Exception as exc:
334
- logger.error(
335
- "Failed to list models for provider '{}': {}",
336
- provider.id or provider.name or provider.base_url,
337
- exc,
338
- )
339
- raise HTTPException(
340
- status_code=500, detail=_summarize_provider_error(exc)
341
- ) from exc
342
-
343
-
344
- @router.post("/api/providers/models/test")
345
- async def run_provider_model_test_route(
346
- req: ProviderModelTestRequest,
347
- ) -> dict[str, object]:
348
- model = req.model.strip()
349
- if not model:
350
- raise HTTPException(status_code=400, detail="model is required")
351
-
352
- provider = _resolve_provider_from_request(req)
353
- try:
354
- return await run_in_threadpool(_test_provider_model, provider, model)
355
- except Exception as exc:
356
- logger.error(
357
- "Failed to test model '{}' for provider '{}': {}",
358
- model,
359
- provider.id or provider.name or provider.base_url,
360
- exc,
361
- )
362
- return {
363
- "ok": False,
364
- "error_summary": _summarize_provider_error(exc),
365
- }
@@ -1,207 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from fastapi import APIRouter, HTTPException
4
- from pydantic import BaseModel, Field
5
-
6
- from flowent.role_management import (
7
- RoleConflictError,
8
- apply_role_update,
9
- build_role_config,
10
- ensure_role_name_available,
11
- find_role_by_name,
12
- normalize_optional_role_description,
13
- normalize_optional_role_name,
14
- remove_role,
15
- require_role_description,
16
- require_role_name,
17
- resolve_role_model,
18
- resolve_role_model_params,
19
- resolve_role_tool_config,
20
- sync_running_system_roles,
21
- validate_builtin_role_update,
22
- )
23
- from flowent.settings import (
24
- get_settings,
25
- is_builtin_role_name,
26
- save_settings,
27
- serialize_provider,
28
- serialize_role,
29
- )
30
-
31
- router = APIRouter()
32
-
33
-
34
- class RoleModelRequest(BaseModel):
35
- provider_id: str
36
- model: str
37
-
38
-
39
- class CreateRoleRequest(BaseModel):
40
- name: str
41
- description: str
42
- system_prompt: str
43
- model: RoleModelRequest | None = None
44
- model_params: dict[str, object] | None = None
45
- included_tools: list[str] = Field(default_factory=list)
46
- excluded_tools: list[str] = Field(default_factory=list)
47
-
48
-
49
- class UpdateRoleRequest(BaseModel):
50
- name: str | None = None
51
- description: str | None = None
52
- system_prompt: str | None = None
53
- model: RoleModelRequest | None = None
54
- model_params: dict[str, object] | None = None
55
- included_tools: list[str] | None = None
56
- excluded_tools: list[str] | None = None
57
-
58
-
59
- @router.get("/api/roles")
60
- async def list_roles() -> dict:
61
- settings = get_settings()
62
- return {"roles": [serialize_role(role) for role in settings.roles]}
63
-
64
-
65
- @router.get("/api/roles/bootstrap")
66
- async def get_roles_bootstrap() -> dict[str, object]:
67
- from flowent.tools import list_agent_visible_tool_descriptors
68
-
69
- settings = get_settings()
70
- return {
71
- "roles": [serialize_role(role) for role in settings.roles],
72
- "providers": [serialize_provider(provider) for provider in settings.providers],
73
- "tools": list_agent_visible_tool_descriptors(include_assistant_only=False),
74
- }
75
-
76
-
77
- @router.post("/api/roles")
78
- async def create_role(req: CreateRoleRequest) -> dict:
79
- from flowent.providers.gateway import gateway
80
-
81
- settings = get_settings()
82
- try:
83
- name = require_role_name(req.name)
84
- description = require_role_description(req.description)
85
- ensure_role_name_available(settings.roles, name)
86
- included_tools, excluded_tools = resolve_role_tool_config(
87
- None,
88
- req.included_tools,
89
- req.excluded_tools,
90
- )
91
- role = build_role_config(
92
- name=name,
93
- description=description,
94
- system_prompt=req.system_prompt,
95
- model=resolve_role_model(
96
- req.model,
97
- settings=settings,
98
- current=None,
99
- provided="model" in req.model_fields_set,
100
- invalid_type_error="Role model must be an object or null",
101
- missing_provider_id_error="Role model provider_id is required",
102
- missing_model_error="Role model is required",
103
- ),
104
- model_params=resolve_role_model_params(
105
- req.model_params,
106
- current=None,
107
- provided="model_params" in req.model_fields_set,
108
- ),
109
- included_tools=included_tools,
110
- excluded_tools=excluded_tools,
111
- )
112
- except RoleConflictError as exc:
113
- raise HTTPException(status_code=409, detail=str(exc)) from exc
114
- except ValueError as exc:
115
- raise HTTPException(status_code=400, detail=str(exc)) from exc
116
- settings.roles.append(role)
117
- save_settings(settings)
118
- gateway.invalidate_cache()
119
- return serialize_role(role)
120
-
121
-
122
- @router.put("/api/roles/{role_name:path}")
123
- async def update_role(role_name: str, req: UpdateRoleRequest) -> dict:
124
- from flowent.providers.gateway import gateway
125
-
126
- settings = get_settings()
127
- role = find_role_by_name(settings.roles, role_name)
128
- if role is None:
129
- raise HTTPException(status_code=404, detail="Role not found")
130
-
131
- try:
132
- included_tools, excluded_tools = resolve_role_tool_config(
133
- role,
134
- req.included_tools,
135
- req.excluded_tools,
136
- )
137
- next_name = normalize_optional_role_name(req.name)
138
- next_description = normalize_optional_role_description(req.description)
139
- if next_name is not None:
140
- ensure_role_name_available(
141
- settings.roles,
142
- next_name,
143
- current_name=role.name,
144
- )
145
- validate_builtin_role_update(
146
- role,
147
- next_name=next_name,
148
- next_description=next_description,
149
- next_system_prompt=req.system_prompt,
150
- next_included_tools=included_tools,
151
- next_excluded_tools=excluded_tools,
152
- )
153
- role = apply_role_update(
154
- settings=settings,
155
- role=role,
156
- next_name=next_name,
157
- next_description=next_description,
158
- next_system_prompt=req.system_prompt,
159
- next_model=resolve_role_model(
160
- req.model,
161
- settings=settings,
162
- current=role.model,
163
- provided="model" in req.model_fields_set,
164
- invalid_type_error="Role model must be an object or null",
165
- missing_provider_id_error="Role model provider_id is required",
166
- missing_model_error="Role model is required",
167
- ),
168
- update_model="model" in req.model_fields_set,
169
- next_model_params=resolve_role_model_params(
170
- req.model_params,
171
- current=role.model_params,
172
- provided="model_params" in req.model_fields_set,
173
- ),
174
- update_model_params="model_params" in req.model_fields_set,
175
- next_included_tools=included_tools,
176
- next_excluded_tools=excluded_tools,
177
- )
178
- except RoleConflictError as exc:
179
- raise HTTPException(status_code=409, detail=str(exc)) from exc
180
- except ValueError as exc:
181
- raise HTTPException(status_code=400, detail=str(exc)) from exc
182
-
183
- save_settings(settings)
184
- sync_running_system_roles()
185
- gateway.invalidate_cache()
186
- return serialize_role(role)
187
-
188
-
189
- @router.delete("/api/roles/{role_name:path}")
190
- async def delete_role(role_name: str) -> dict:
191
- from flowent.providers.gateway import gateway
192
-
193
- if is_builtin_role_name(role_name):
194
- raise HTTPException(
195
- status_code=400,
196
- detail=f"Cannot delete built-in role '{role_name}'",
197
- )
198
-
199
- settings = get_settings()
200
- role = find_role_by_name(settings.roles, role_name)
201
- if role is None:
202
- raise HTTPException(status_code=404, detail="Role not found")
203
- remove_role(settings, role)
204
- save_settings(settings)
205
- sync_running_system_roles()
206
- gateway.invalidate_cache()
207
- return {"status": "deleted"}