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,447 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import base64
4
- import json
5
- import time
6
- import uuid
7
- from collections.abc import Callable
8
- from typing import Any
9
-
10
- from loguru import logger
11
-
12
- from flowent.model_metadata import build_model_info
13
- from flowent.models import (
14
- LLMOutputImagePart,
15
- LLMOutputTextPart,
16
- LLMResponse,
17
- LLMUsage,
18
- ModelInfo,
19
- )
20
- from flowent.models import ToolCallResult as ToolCall
21
- from flowent.network import (
22
- RequestException,
23
- create_http_session,
24
- read_response_text,
25
- response_looks_like_html,
26
- truncate_text,
27
- )
28
- from flowent.providers import LLMProvider
29
- from flowent.providers.content import collapse_parts_to_text, to_gemini_parts
30
- from flowent.providers.errors import (
31
- build_access_blocked_error,
32
- build_network_error,
33
- build_status_error,
34
- )
35
- from flowent.providers.headers import merge_headers
36
- from flowent.providers.sse import iter_sse_json
37
- from flowent.settings import ModelParams
38
-
39
-
40
- def _extract_usage_metadata_value(
41
- usage_metadata: dict[str, Any],
42
- key: str,
43
- ) -> int | None:
44
- value = usage_metadata.get(key)
45
- if isinstance(value, bool) or not isinstance(value, int):
46
- return None
47
- return value
48
-
49
-
50
- class GeminiProvider(LLMProvider):
51
- def __init__(
52
- self,
53
- provider_name: str,
54
- api_base_url: str,
55
- api_key: str = "",
56
- headers: dict[str, str] | None = None,
57
- model: str = "",
58
- request_timeout_seconds: float = 120.0,
59
- ) -> None:
60
- self._provider_name = provider_name
61
- self._api_base_url = api_base_url.rstrip("/")
62
- self._api_key = api_key
63
- self._header_overrides = dict(headers or {})
64
- self._model = model
65
- self._request_timeout_seconds = request_timeout_seconds
66
- self._client = create_http_session(timeout=self._request_timeout_seconds)
67
-
68
- def _headers(self) -> dict[str, str]:
69
- return merge_headers(
70
- {"Content-Type": "application/json"},
71
- self._header_overrides,
72
- )
73
-
74
- def _convert_messages(
75
- self,
76
- messages: list[dict[str, Any]],
77
- ) -> tuple[dict[str, Any] | None, list[dict[str, Any]]]:
78
- system_parts: list[str] = []
79
- contents: list[dict[str, Any]] = []
80
- tool_call_names: dict[str, str] = {}
81
-
82
- for msg in messages:
83
- role = msg.get("role", "")
84
- content = msg.get("content")
85
-
86
- if role == "system":
87
- system_text = collapse_parts_to_text(content)
88
- if system_text:
89
- system_parts.append(system_text)
90
- continue
91
-
92
- if role == "user":
93
- contents.append(
94
- {
95
- "role": "user",
96
- "parts": to_gemini_parts(content, allow_images=True),
97
- },
98
- )
99
- continue
100
-
101
- if role == "assistant":
102
- parts: list[dict[str, Any]] = []
103
-
104
- assistant_text = collapse_parts_to_text(content)
105
- if assistant_text:
106
- parts.append({"text": assistant_text})
107
-
108
- for tc in msg.get("tool_calls", []) or []:
109
- fn = tc.get("function", {})
110
- name = fn.get("name", "")
111
- call_id = tc.get("id", "")
112
- if call_id and name:
113
- tool_call_names[call_id] = name
114
-
115
- raw_args = fn.get("arguments", {})
116
- if isinstance(raw_args, str):
117
- try:
118
- args = json.loads(raw_args) if raw_args else {}
119
- except json.JSONDecodeError:
120
- args = {}
121
- elif isinstance(raw_args, dict):
122
- args = raw_args
123
- else:
124
- args = {}
125
-
126
- if not isinstance(args, dict):
127
- args = {}
128
-
129
- parts.append(
130
- {
131
- "functionCall": {
132
- "name": name,
133
- "args": args,
134
- }
135
- },
136
- )
137
-
138
- if parts:
139
- contents.append(
140
- {
141
- "role": "model",
142
- "parts": parts,
143
- },
144
- )
145
- continue
146
-
147
- if role == "tool":
148
- tool_call_id = msg.get("tool_call_id", "")
149
- name = tool_call_names.get(tool_call_id, msg.get("name", ""))
150
- contents.append(
151
- {
152
- "role": "user",
153
- "parts": [
154
- {
155
- "functionResponse": {
156
- "name": name,
157
- "response": {"content": content or ""},
158
- }
159
- }
160
- ],
161
- },
162
- )
163
-
164
- system_instruction = None
165
- if system_parts:
166
- system_instruction = {"parts": [{"text": "\n\n".join(system_parts)}]}
167
-
168
- return system_instruction, contents
169
-
170
- def _convert_tools(self, tools: list[dict[str, Any]]) -> list[dict[str, Any]]:
171
- declarations = []
172
- for tool in tools:
173
- fn = tool.get("function", {})
174
- decl: dict[str, Any] = {
175
- "name": fn.get("name", ""),
176
- "description": fn.get("description", ""),
177
- }
178
- params = fn.get("parameters")
179
- if params:
180
- decl["parameters"] = params
181
- declarations.append(decl)
182
- return [{"function_declarations": declarations}]
183
-
184
- def chat(
185
- self,
186
- messages: list[dict[str, Any]],
187
- tools: list[dict[str, Any]] | None = None,
188
- on_chunk: Callable[[str, str], None] | None = None,
189
- register_interrupt: Callable[[Callable[[], None] | None], None] | None = None,
190
- model_params: ModelParams | None = None,
191
- ) -> LLMResponse:
192
- url = (
193
- f"{self._api_base_url}/v1beta/models/{self._model}"
194
- f":streamGenerateContent?alt=sse&key={self._api_key}"
195
- )
196
-
197
- system_instruction, contents = self._convert_messages(messages)
198
-
199
- payload: dict[str, Any] = {"contents": contents}
200
- if model_params is not None:
201
- generation_config: dict[str, Any] = {}
202
- if model_params.max_output_tokens is not None:
203
- generation_config["maxOutputTokens"] = model_params.max_output_tokens
204
- if model_params.temperature is not None:
205
- generation_config["temperature"] = model_params.temperature
206
- if model_params.top_p is not None:
207
- generation_config["topP"] = model_params.top_p
208
- if generation_config:
209
- payload["generationConfig"] = generation_config
210
- if system_instruction:
211
- payload["system_instruction"] = system_instruction
212
- if tools:
213
- payload["tools"] = self._convert_tools(tools)
214
-
215
- logger.debug(
216
- "[{}] Gemini chat request: model={}, messages={}, tools={}",
217
- self._provider_name,
218
- self._model,
219
- len(contents),
220
- len(tools) if tools else 0,
221
- )
222
-
223
- t0 = time.perf_counter()
224
-
225
- content_parts: list[str] = []
226
- output_parts: list[LLMOutputTextPart | LLMOutputImagePart] = []
227
- tool_calls_list: list[ToolCall] = []
228
- chunk_count = 0
229
- usage: LLMUsage | None = None
230
- raw_usage: dict[str, Any] | None = None
231
- client = self._client
232
- if register_interrupt is not None:
233
- register_interrupt(client.close)
234
-
235
- try:
236
- with client.stream(
237
- "POST",
238
- url,
239
- headers=self._headers(),
240
- json=payload,
241
- ) as response:
242
- if register_interrupt is not None:
243
- register_interrupt(response.close)
244
- if response_looks_like_html(response):
245
- raise build_access_blocked_error(
246
- provider_name=self._provider_name,
247
- provider_type="gemini",
248
- model=self._model,
249
- base_url=self._api_base_url,
250
- status_code=response.status_code,
251
- detail=truncate_text(read_response_text(response)),
252
- )
253
- if response.status_code != 200:
254
- body = truncate_text(read_response_text(response))
255
- elapsed = time.perf_counter() - t0
256
- logger.error(
257
- "LLM API error [provider={}, model={}, type=gemini]: {} - {} ({:.2f}s)",
258
- self._provider_name,
259
- self._model,
260
- response.status_code,
261
- body[:500],
262
- elapsed,
263
- )
264
- raise build_status_error(
265
- provider_name=self._provider_name,
266
- provider_type="gemini",
267
- model=self._model,
268
- base_url=self._api_base_url,
269
- status_code=response.status_code,
270
- body=body,
271
- )
272
-
273
- for chunk in iter_sse_json(response):
274
- chunk_count += 1
275
- usage_metadata = chunk.get("usageMetadata", {})
276
- if isinstance(usage_metadata, dict):
277
- raw_usage = dict(usage_metadata)
278
- input_tokens = _extract_usage_metadata_value(
279
- usage_metadata, "promptTokenCount"
280
- )
281
- output_tokens = _extract_usage_metadata_value(
282
- usage_metadata, "candidatesTokenCount"
283
- )
284
- total_tokens = _extract_usage_metadata_value(
285
- usage_metadata, "totalTokenCount"
286
- )
287
- cached_input_tokens = _extract_usage_metadata_value(
288
- usage_metadata, "cachedContentTokenCount"
289
- )
290
- details = {
291
- key: value
292
- for key in (
293
- "toolUsePromptTokenCount",
294
- "thoughtsTokenCount",
295
- )
296
- if (
297
- value := _extract_usage_metadata_value(
298
- usage_metadata, key
299
- )
300
- )
301
- is not None
302
- }
303
- if total_tokens is not None:
304
- usage = LLMUsage(
305
- total_tokens=total_tokens,
306
- input_tokens=input_tokens,
307
- output_tokens=output_tokens,
308
- cached_input_tokens=cached_input_tokens,
309
- cache_read_tokens=cached_input_tokens,
310
- details=details,
311
- )
312
- candidates = chunk.get("candidates", [])
313
- if not candidates:
314
- continue
315
-
316
- parts = candidates[0].get("content", {}).get("parts", [])
317
- for part in parts:
318
- if "text" in part:
319
- text = part["text"]
320
- content_parts.append(text)
321
- output_parts.append(LLMOutputTextPart(text=text))
322
- if on_chunk:
323
- on_chunk("content", text)
324
- elif "inlineData" in part:
325
- inline_data = part["inlineData"]
326
- mime_type = inline_data.get("mimeType")
327
- encoded_data = inline_data.get("data")
328
- if (
329
- isinstance(mime_type, str)
330
- and mime_type.startswith("image/")
331
- and isinstance(encoded_data, str)
332
- ):
333
- try:
334
- image_data = base64.b64decode(encoded_data)
335
- except ValueError:
336
- continue
337
- output_parts.append(
338
- LLMOutputImagePart(
339
- data=image_data,
340
- mime_type=mime_type,
341
- )
342
- )
343
- elif "functionCall" in part:
344
- fc = part["functionCall"]
345
- tool_calls_list.append(
346
- ToolCall(
347
- id=str(uuid.uuid4()),
348
- name=fc.get("name", ""),
349
- arguments=fc.get("args", {}),
350
- ),
351
- )
352
- except RequestException as exc:
353
- elapsed = time.perf_counter() - t0
354
- logger.warning(
355
- "LLM API transport error [provider={}, model={}, type=gemini]: {} ({:.2f}s)",
356
- self._provider_name,
357
- self._model,
358
- exc,
359
- elapsed,
360
- )
361
- raise build_network_error(
362
- provider_name=self._provider_name,
363
- provider_type="gemini",
364
- model=self._model,
365
- base_url=self._api_base_url,
366
- error=exc,
367
- ) from exc
368
- finally:
369
- close_client = getattr(client, "close", None)
370
- if callable(close_client):
371
- close_client()
372
- self._client = create_http_session(
373
- timeout=self._request_timeout_seconds
374
- )
375
-
376
- elapsed = time.perf_counter() - t0
377
- content = "".join(content_parts) or None
378
-
379
- logger.debug(
380
- "[{}] Gemini chat done: {:.2f}s, chunks={}, content_len={}, tool_calls={}",
381
- self._provider_name,
382
- elapsed,
383
- chunk_count,
384
- len(content) if content else 0,
385
- len(tool_calls_list),
386
- )
387
-
388
- if tool_calls_list:
389
- return LLMResponse(
390
- content=content,
391
- parts=output_parts or None,
392
- tool_calls=tool_calls_list,
393
- usage=usage,
394
- raw_usage=raw_usage,
395
- )
396
-
397
- return LLMResponse(
398
- content=content or "",
399
- parts=output_parts or None,
400
- usage=usage,
401
- raw_usage=raw_usage,
402
- )
403
-
404
- def list_models(
405
- self,
406
- register_interrupt: Callable[[Callable[[], None] | None], None] | None = None,
407
- ) -> list[ModelInfo]:
408
- url = f"{self._api_base_url}/v1beta/models?key={self._api_key}"
409
- client = self._client
410
- close_client = getattr(client, "close", None)
411
- if register_interrupt is not None and callable(close_client):
412
- register_interrupt(close_client)
413
- try:
414
- resp = client.get(url, headers=self._headers())
415
- resp.raise_for_status()
416
- data = resp.json()
417
- models = data.get("models", [])
418
- result = []
419
- for m in models:
420
- methods = m.get("supportedGenerationMethods", [])
421
- if "generateContent" in methods:
422
- model_id = m.get("name", "").removeprefix("models/")
423
- result.append(
424
- build_model_info(
425
- provider_type="gemini",
426
- model_id=model_id,
427
- context_window_tokens=(
428
- m.get("inputTokenLimit")
429
- if isinstance(m.get("inputTokenLimit"), int)
430
- else None
431
- ),
432
- )
433
- )
434
- return result
435
- except Exception as e:
436
- logger.error(
437
- "Failed to list models [provider={}, type=gemini]: {}",
438
- self._provider_name,
439
- e,
440
- )
441
- return []
442
- finally:
443
- if callable(close_client):
444
- close_client()
445
- self._client = create_http_session(
446
- timeout=self._request_timeout_seconds
447
- )
@@ -1,20 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from collections.abc import Mapping
4
-
5
-
6
- def merge_headers(
7
- builtins: Mapping[str, str],
8
- overrides: Mapping[str, str],
9
- ) -> dict[str, str]:
10
- headers = dict(builtins)
11
- names = {name.lower(): name for name in headers}
12
-
13
- for name, value in overrides.items():
14
- existing = names.get(name.lower())
15
- if existing is not None:
16
- headers.pop(existing, None)
17
- headers[name] = value
18
- names[name.lower()] = name
19
-
20
- return headers
@@ -1,96 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import uuid
4
-
5
- from flowent.providers.configuration import (
6
- apply_provider_update,
7
- build_provider_config,
8
- serialize_provider,
9
- )
10
- from flowent.settings import (
11
- ProviderConfig,
12
- ProviderModelCatalogEntry,
13
- Settings,
14
- clear_provider_references,
15
- find_provider,
16
- )
17
-
18
-
19
- class ProviderNotFoundError(LookupError):
20
- def __init__(self, provider_id: str) -> None:
21
- super().__init__(provider_id)
22
- self.provider_id = provider_id
23
-
24
-
25
- def list_provider_payloads(
26
- settings: Settings,
27
- *,
28
- include_api_key: bool = True,
29
- ) -> list[dict[str, object]]:
30
- return [
31
- serialize_provider(provider, include_api_key=include_api_key)
32
- for provider in settings.providers
33
- ]
34
-
35
-
36
- def create_provider_entry(
37
- settings: Settings,
38
- *,
39
- name: str,
40
- provider_type: str,
41
- base_url: str,
42
- api_key: str = "",
43
- raw_headers: object = None,
44
- raw_retry_429_delay_seconds: object = 0,
45
- models: list[ProviderModelCatalogEntry] | None = None,
46
- base_url_required_message: str = "base_url is required",
47
- ) -> ProviderConfig:
48
- provider = build_provider_config(
49
- provider_id=str(uuid.uuid4()),
50
- name=name,
51
- provider_type=provider_type,
52
- base_url=base_url,
53
- api_key=api_key,
54
- raw_headers=raw_headers,
55
- raw_retry_429_delay_seconds=raw_retry_429_delay_seconds,
56
- models=models,
57
- base_url_required_message=base_url_required_message,
58
- )
59
- settings.providers.append(provider)
60
- return provider
61
-
62
-
63
- def update_provider_entry(
64
- settings: Settings,
65
- provider_id: str,
66
- *,
67
- name: str | None = None,
68
- provider_type: str | None = None,
69
- base_url: str | None = None,
70
- api_key: str | None = None,
71
- raw_headers: object | None = None,
72
- raw_retry_429_delay_seconds: object | None = None,
73
- models: list[ProviderModelCatalogEntry] | None = None,
74
- ) -> ProviderConfig:
75
- provider = find_provider(settings, provider_id)
76
- if provider is None:
77
- raise ProviderNotFoundError(provider_id)
78
- apply_provider_update(
79
- provider,
80
- name=name,
81
- provider_type=provider_type,
82
- base_url=base_url,
83
- api_key=api_key,
84
- raw_headers=raw_headers,
85
- raw_retry_429_delay_seconds=raw_retry_429_delay_seconds,
86
- models=models,
87
- )
88
- return provider
89
-
90
-
91
- def delete_provider_entry(settings: Settings, provider_id: str) -> None:
92
- provider = find_provider(settings, provider_id)
93
- if provider is None:
94
- raise ProviderNotFoundError(provider_id)
95
- settings.providers = [item for item in settings.providers if item.id != provider_id]
96
- clear_provider_references(settings, provider_id)