flowent 0.0.6 → 0.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (398) hide show
  1. package/README.md +1 -4
  2. package/backend/README.md +1 -4
  3. package/backend/pyproject.toml +2 -8
  4. package/backend/src/flowent/__pycache__/__init__.cpython-313.pyc +0 -0
  5. package/backend/src/flowent/__pycache__/agent.cpython-313.pyc +0 -0
  6. package/backend/src/flowent/__pycache__/cli.cpython-313.pyc +0 -0
  7. package/backend/src/flowent/__pycache__/context.cpython-313.pyc +0 -0
  8. package/backend/src/flowent/__pycache__/llm.cpython-313.pyc +0 -0
  9. package/backend/src/flowent/__pycache__/logging.cpython-313.pyc +0 -0
  10. package/backend/src/flowent/__pycache__/main.cpython-313.pyc +0 -0
  11. package/backend/src/flowent/__pycache__/patch.cpython-313.pyc +0 -0
  12. package/backend/src/flowent/__pycache__/paths.cpython-313.pyc +0 -0
  13. package/backend/src/flowent/__pycache__/sandbox.cpython-313.pyc +0 -0
  14. package/backend/src/flowent/__pycache__/storage.cpython-313.pyc +0 -0
  15. package/backend/src/flowent/__pycache__/tools.cpython-313.pyc +0 -0
  16. package/backend/src/flowent/agent.py +217 -3094
  17. package/backend/src/flowent/cli.py +19 -24
  18. package/backend/src/flowent/context.py +127 -0
  19. package/backend/src/flowent/llm.py +256 -0
  20. package/backend/src/flowent/logging.py +170 -129
  21. package/backend/src/flowent/main.py +321 -70
  22. package/backend/src/flowent/patch.py +182 -0
  23. package/backend/src/flowent/paths.py +11 -0
  24. package/backend/src/flowent/sandbox.py +214 -40
  25. package/backend/src/flowent/static/assets/geist-cyrillic-wght-normal-CHSlOQsW.woff2 +0 -0
  26. package/backend/src/flowent/static/assets/geist-latin-ext-wght-normal-DMtmJ5ZE.woff2 +0 -0
  27. package/backend/src/flowent/static/assets/geist-latin-wght-normal-Dm3htQBi.woff2 +0 -0
  28. package/backend/src/flowent/static/assets/index-C76K95ty.js +81 -0
  29. package/backend/src/flowent/static/assets/index-iUMNKvlU.css +2 -0
  30. package/backend/src/flowent/static/flowent.png +0 -0
  31. package/backend/src/flowent/static/index.html +5 -25
  32. package/backend/src/flowent/storage.py +302 -0
  33. package/backend/src/flowent/tools.py +364 -0
  34. package/backend/tests/__pycache__/test_agent_tools.cpython-313-pytest-9.0.3.pyc +0 -0
  35. package/backend/tests/__pycache__/test_health.cpython-313-pytest-9.0.3.pyc +0 -0
  36. package/backend/tests/__pycache__/test_llm_providers.cpython-313-pytest-9.0.3.pyc +0 -0
  37. package/backend/tests/__pycache__/test_logging.cpython-313-pytest-9.0.3.pyc +0 -0
  38. package/backend/tests/__pycache__/test_persistence.cpython-313-pytest-9.0.3.pyc +0 -0
  39. package/backend/tests/__pycache__/test_workspace_chat.cpython-313-pytest-9.0.3.pyc +0 -0
  40. package/backend/tests/test_agent_tools.py +449 -0
  41. package/backend/tests/test_health.py +12 -0
  42. package/backend/tests/test_llm_providers.py +113 -0
  43. package/backend/tests/test_logging.py +182 -0
  44. package/backend/tests/test_persistence.py +125 -0
  45. package/backend/tests/test_workspace_chat.py +578 -0
  46. package/backend/uv.lock +803 -99
  47. package/dist/frontend/assets/geist-cyrillic-wght-normal-CHSlOQsW.woff2 +0 -0
  48. package/dist/frontend/assets/geist-latin-ext-wght-normal-DMtmJ5ZE.woff2 +0 -0
  49. package/dist/frontend/assets/geist-latin-wght-normal-Dm3htQBi.woff2 +0 -0
  50. package/dist/frontend/assets/index-C76K95ty.js +81 -0
  51. package/dist/frontend/assets/index-iUMNKvlU.css +2 -0
  52. package/dist/frontend/flowent.png +0 -0
  53. package/dist/frontend/index.html +5 -25
  54. package/package.json +1 -2
  55. package/backend/src/flowent/__pycache__/_version.cpython-313.pyc +0 -0
  56. package/backend/src/flowent/__pycache__/access.cpython-313.pyc +0 -0
  57. package/backend/src/flowent/__pycache__/assistant_commands.cpython-313.pyc +0 -0
  58. package/backend/src/flowent/__pycache__/config.cpython-313.pyc +0 -0
  59. package/backend/src/flowent/__pycache__/events.cpython-313.pyc +0 -0
  60. package/backend/src/flowent/__pycache__/graph_runtime.cpython-313.pyc +0 -0
  61. package/backend/src/flowent/__pycache__/graph_service.cpython-313.pyc +0 -0
  62. package/backend/src/flowent/__pycache__/image_assets.cpython-313.pyc +0 -0
  63. package/backend/src/flowent/__pycache__/mcp_service.cpython-313.pyc +0 -0
  64. package/backend/src/flowent/__pycache__/model_metadata.cpython-313.pyc +0 -0
  65. package/backend/src/flowent/__pycache__/network.cpython-313.pyc +0 -0
  66. package/backend/src/flowent/__pycache__/observability_service.cpython-313.pyc +0 -0
  67. package/backend/src/flowent/__pycache__/registry.cpython-313.pyc +0 -0
  68. package/backend/src/flowent/__pycache__/role_management.cpython-313.pyc +0 -0
  69. package/backend/src/flowent/__pycache__/runtime.cpython-313.pyc +0 -0
  70. package/backend/src/flowent/__pycache__/security.cpython-313.pyc +0 -0
  71. package/backend/src/flowent/__pycache__/settings.cpython-313.pyc +0 -0
  72. package/backend/src/flowent/__pycache__/settings_management.cpython-313.pyc +0 -0
  73. package/backend/src/flowent/__pycache__/state_db.cpython-313.pyc +0 -0
  74. package/backend/src/flowent/__pycache__/workspace_store.cpython-313.pyc +0 -0
  75. package/backend/src/flowent/access.py +0 -247
  76. package/backend/src/flowent/assistant_commands.py +0 -115
  77. package/backend/src/flowent/channels/__init__.py +0 -3
  78. package/backend/src/flowent/channels/__pycache__/__init__.cpython-313.pyc +0 -0
  79. package/backend/src/flowent/channels/__pycache__/telegram.cpython-313.pyc +0 -0
  80. package/backend/src/flowent/channels/telegram.py +0 -615
  81. package/backend/src/flowent/config.py +0 -14
  82. package/backend/src/flowent/dev.py +0 -3
  83. package/backend/src/flowent/events.py +0 -157
  84. package/backend/src/flowent/graph_runtime.py +0 -60
  85. package/backend/src/flowent/graph_service.py +0 -2508
  86. package/backend/src/flowent/image_assets.py +0 -356
  87. package/backend/src/flowent/mcp_service.py +0 -1918
  88. package/backend/src/flowent/model_metadata.py +0 -102
  89. package/backend/src/flowent/models/__init__.py +0 -125
  90. package/backend/src/flowent/models/__pycache__/__init__.cpython-313.pyc +0 -0
  91. package/backend/src/flowent/models/__pycache__/agent.cpython-313.pyc +0 -0
  92. package/backend/src/flowent/models/__pycache__/base.cpython-313.pyc +0 -0
  93. package/backend/src/flowent/models/__pycache__/blueprint.cpython-313.pyc +0 -0
  94. package/backend/src/flowent/models/__pycache__/content.cpython-313.pyc +0 -0
  95. package/backend/src/flowent/models/__pycache__/delta.cpython-313.pyc +0 -0
  96. package/backend/src/flowent/models/__pycache__/event.cpython-313.pyc +0 -0
  97. package/backend/src/flowent/models/__pycache__/graph.cpython-313.pyc +0 -0
  98. package/backend/src/flowent/models/__pycache__/history.cpython-313.pyc +0 -0
  99. package/backend/src/flowent/models/__pycache__/llm.cpython-313.pyc +0 -0
  100. package/backend/src/flowent/models/__pycache__/message.cpython-313.pyc +0 -0
  101. package/backend/src/flowent/models/__pycache__/tab.cpython-313.pyc +0 -0
  102. package/backend/src/flowent/models/__pycache__/todo.cpython-313.pyc +0 -0
  103. package/backend/src/flowent/models/agent.py +0 -34
  104. package/backend/src/flowent/models/base.py +0 -24
  105. package/backend/src/flowent/models/blueprint.py +0 -176
  106. package/backend/src/flowent/models/content.py +0 -164
  107. package/backend/src/flowent/models/delta.py +0 -44
  108. package/backend/src/flowent/models/event.py +0 -51
  109. package/backend/src/flowent/models/graph.py +0 -472
  110. package/backend/src/flowent/models/history.py +0 -272
  111. package/backend/src/flowent/models/llm.py +0 -62
  112. package/backend/src/flowent/models/message.py +0 -33
  113. package/backend/src/flowent/models/tab.py +0 -85
  114. package/backend/src/flowent/models/todo.py +0 -10
  115. package/backend/src/flowent/network.py +0 -146
  116. package/backend/src/flowent/observability_service.py +0 -218
  117. package/backend/src/flowent/prompts/__init__.py +0 -67
  118. package/backend/src/flowent/prompts/__pycache__/__init__.cpython-313.pyc +0 -0
  119. package/backend/src/flowent/prompts/__pycache__/common.cpython-313.pyc +0 -0
  120. package/backend/src/flowent/prompts/__pycache__/steward.cpython-313.pyc +0 -0
  121. package/backend/src/flowent/prompts/common.py +0 -250
  122. package/backend/src/flowent/prompts/steward.py +0 -64
  123. package/backend/src/flowent/providers/__init__.py +0 -23
  124. package/backend/src/flowent/providers/__pycache__/__init__.cpython-313.pyc +0 -0
  125. package/backend/src/flowent/providers/__pycache__/anthropic.cpython-313.pyc +0 -0
  126. package/backend/src/flowent/providers/__pycache__/base_url.cpython-313.pyc +0 -0
  127. package/backend/src/flowent/providers/__pycache__/configuration.cpython-313.pyc +0 -0
  128. package/backend/src/flowent/providers/__pycache__/content.cpython-313.pyc +0 -0
  129. package/backend/src/flowent/providers/__pycache__/errors.cpython-313.pyc +0 -0
  130. package/backend/src/flowent/providers/__pycache__/gateway.cpython-313.pyc +0 -0
  131. package/backend/src/flowent/providers/__pycache__/headers.cpython-313.pyc +0 -0
  132. package/backend/src/flowent/providers/__pycache__/management.cpython-313.pyc +0 -0
  133. package/backend/src/flowent/providers/__pycache__/openai.cpython-313.pyc +0 -0
  134. package/backend/src/flowent/providers/__pycache__/openai_responses.cpython-313.pyc +0 -0
  135. package/backend/src/flowent/providers/__pycache__/registry.cpython-313.pyc +0 -0
  136. package/backend/src/flowent/providers/__pycache__/sse.cpython-313.pyc +0 -0
  137. package/backend/src/flowent/providers/__pycache__/thinking.cpython-313.pyc +0 -0
  138. package/backend/src/flowent/providers/anthropic.py +0 -468
  139. package/backend/src/flowent/providers/base_url.py +0 -60
  140. package/backend/src/flowent/providers/configuration.py +0 -189
  141. package/backend/src/flowent/providers/content.py +0 -122
  142. package/backend/src/flowent/providers/errors.py +0 -223
  143. package/backend/src/flowent/providers/gateway.py +0 -169
  144. package/backend/src/flowent/providers/gemini.py +0 -447
  145. package/backend/src/flowent/providers/headers.py +0 -20
  146. package/backend/src/flowent/providers/management.py +0 -96
  147. package/backend/src/flowent/providers/ollama.py +0 -293
  148. package/backend/src/flowent/providers/openai.py +0 -422
  149. package/backend/src/flowent/providers/openai_responses.py +0 -655
  150. package/backend/src/flowent/providers/registry.py +0 -144
  151. package/backend/src/flowent/providers/sse.py +0 -31
  152. package/backend/src/flowent/providers/thinking.py +0 -79
  153. package/backend/src/flowent/registry.py +0 -73
  154. package/backend/src/flowent/role_management.py +0 -267
  155. package/backend/src/flowent/routes/__init__.py +0 -28
  156. package/backend/src/flowent/routes/__pycache__/__init__.cpython-313.pyc +0 -0
  157. package/backend/src/flowent/routes/__pycache__/access.cpython-313.pyc +0 -0
  158. package/backend/src/flowent/routes/__pycache__/assistant.cpython-313.pyc +0 -0
  159. package/backend/src/flowent/routes/__pycache__/image_assets.cpython-313.pyc +0 -0
  160. package/backend/src/flowent/routes/__pycache__/mcp.cpython-313.pyc +0 -0
  161. package/backend/src/flowent/routes/__pycache__/meta.cpython-313.pyc +0 -0
  162. package/backend/src/flowent/routes/__pycache__/nodes.cpython-313.pyc +0 -0
  163. package/backend/src/flowent/routes/__pycache__/prompts.cpython-313.pyc +0 -0
  164. package/backend/src/flowent/routes/__pycache__/providers_route.cpython-313.pyc +0 -0
  165. package/backend/src/flowent/routes/__pycache__/roles.cpython-313.pyc +0 -0
  166. package/backend/src/flowent/routes/__pycache__/settings.cpython-313.pyc +0 -0
  167. package/backend/src/flowent/routes/__pycache__/tabs.cpython-313.pyc +0 -0
  168. package/backend/src/flowent/routes/__pycache__/ws.cpython-313.pyc +0 -0
  169. package/backend/src/flowent/routes/access.py +0 -48
  170. package/backend/src/flowent/routes/assistant.py +0 -155
  171. package/backend/src/flowent/routes/image_assets.py +0 -33
  172. package/backend/src/flowent/routes/mcp.py +0 -125
  173. package/backend/src/flowent/routes/meta.py +0 -28
  174. package/backend/src/flowent/routes/nodes.py +0 -413
  175. package/backend/src/flowent/routes/prompts.py +0 -46
  176. package/backend/src/flowent/routes/providers_route.py +0 -365
  177. package/backend/src/flowent/routes/roles.py +0 -207
  178. package/backend/src/flowent/routes/settings.py +0 -328
  179. package/backend/src/flowent/routes/tabs.py +0 -310
  180. package/backend/src/flowent/routes/ws.py +0 -33
  181. package/backend/src/flowent/runtime.py +0 -165
  182. package/backend/src/flowent/security.py +0 -57
  183. package/backend/src/flowent/settings.py +0 -2518
  184. package/backend/src/flowent/settings_management.py +0 -298
  185. package/backend/src/flowent/state_db.py +0 -120
  186. package/backend/src/flowent/static/assets/AssistantPage-VBohhz4d.js +0 -1
  187. package/backend/src/flowent/static/assets/ChannelsPage-CIydPZA_.js +0 -1
  188. package/backend/src/flowent/static/assets/McpPage-CHPm2TPY.js +0 -7
  189. package/backend/src/flowent/static/assets/PageScaffold-DteOA8V7.js +0 -1
  190. package/backend/src/flowent/static/assets/PromptsPage-CSmJ3sZg.js +0 -1
  191. package/backend/src/flowent/static/assets/ProvidersPage-sl2jeG4e.js +0 -3
  192. package/backend/src/flowent/static/assets/RolesPage-DCe7W6Km.js +0 -1
  193. package/backend/src/flowent/static/assets/SettingsPage-Bix9e63E.js +0 -3
  194. package/backend/src/flowent/static/assets/ToolsPage-favNkj5C.js +0 -1
  195. package/backend/src/flowent/static/assets/WorkspaceCommandDialog-DRS6wiD6.js +0 -1
  196. package/backend/src/flowent/static/assets/WorkspacePage-KuaDjt_D.js +0 -3
  197. package/backend/src/flowent/static/assets/WorkspacePanels-BZxBw8M5.js +0 -1
  198. package/backend/src/flowent/static/assets/alert-dialog-DIBUCmqM.js +0 -1
  199. package/backend/src/flowent/static/assets/datetime-eJqd0V2S.js +0 -1
  200. package/backend/src/flowent/static/assets/dialog-BOvHIBrg.js +0 -1
  201. package/backend/src/flowent/static/assets/elk-worker.min-C9JGDOE-.js +0 -6312
  202. package/backend/src/flowent/static/assets/graph-vendor-CHpVij2M.css +0 -1
  203. package/backend/src/flowent/static/assets/graph-vendor-DRq_-6fV.js +0 -7
  204. package/backend/src/flowent/static/assets/index-Biio-CoI.js +0 -10
  205. package/backend/src/flowent/static/assets/index-CmQvO7sl.css +0 -1
  206. package/backend/src/flowent/static/assets/layout.worker-jMHqAFbP.js +0 -24
  207. package/backend/src/flowent/static/assets/markdown-vendor-C9RtvaJh.js +0 -29
  208. package/backend/src/flowent/static/assets/modelParams-DcEhGnu0.js +0 -1
  209. package/backend/src/flowent/static/assets/react-vendor-mEs_JJxa.js +0 -9
  210. package/backend/src/flowent/static/assets/roles-BbIEIMeG.js +0 -1
  211. package/backend/src/flowent/static/assets/rolldown-runtime-BYbx6iT9.js +0 -1
  212. package/backend/src/flowent/static/assets/select-D9SwnlXF.js +0 -1
  213. package/backend/src/flowent/static/assets/surface-Bzr1FRG4.js +0 -1
  214. package/backend/src/flowent/static/assets/triState-DgLlKdRR.js +0 -1
  215. package/backend/src/flowent/static/assets/ui-vendor-UazN8rcv.js +0 -51
  216. package/backend/src/flowent/static/favicon.svg +0 -4
  217. package/backend/src/flowent/tools/__init__.py +0 -275
  218. package/backend/src/flowent/tools/__pycache__/__init__.cpython-313.pyc +0 -0
  219. package/backend/src/flowent/tools/__pycache__/connect.cpython-313.pyc +0 -0
  220. package/backend/src/flowent/tools/__pycache__/contacts.cpython-313.pyc +0 -0
  221. package/backend/src/flowent/tools/__pycache__/create_agent.cpython-313.pyc +0 -0
  222. package/backend/src/flowent/tools/__pycache__/create_tab.cpython-313.pyc +0 -0
  223. package/backend/src/flowent/tools/__pycache__/delete_tab.cpython-313.pyc +0 -0
  224. package/backend/src/flowent/tools/__pycache__/edit.cpython-313.pyc +0 -0
  225. package/backend/src/flowent/tools/__pycache__/exec.cpython-313.pyc +0 -0
  226. package/backend/src/flowent/tools/__pycache__/fetch.cpython-313.pyc +0 -0
  227. package/backend/src/flowent/tools/__pycache__/idle.cpython-313.pyc +0 -0
  228. package/backend/src/flowent/tools/__pycache__/list_roles.cpython-313.pyc +0 -0
  229. package/backend/src/flowent/tools/__pycache__/list_tabs.cpython-313.pyc +0 -0
  230. package/backend/src/flowent/tools/__pycache__/list_tools.cpython-313.pyc +0 -0
  231. package/backend/src/flowent/tools/__pycache__/manage_prompts.cpython-313.pyc +0 -0
  232. package/backend/src/flowent/tools/__pycache__/manage_providers.cpython-313.pyc +0 -0
  233. package/backend/src/flowent/tools/__pycache__/manage_roles.cpython-313.pyc +0 -0
  234. package/backend/src/flowent/tools/__pycache__/manage_settings.cpython-313.pyc +0 -0
  235. package/backend/src/flowent/tools/__pycache__/mcp.cpython-313.pyc +0 -0
  236. package/backend/src/flowent/tools/__pycache__/read.cpython-313.pyc +0 -0
  237. package/backend/src/flowent/tools/__pycache__/send.cpython-313.pyc +0 -0
  238. package/backend/src/flowent/tools/__pycache__/set_permissions.cpython-313.pyc +0 -0
  239. package/backend/src/flowent/tools/__pycache__/sleep.cpython-313.pyc +0 -0
  240. package/backend/src/flowent/tools/__pycache__/todo.cpython-313.pyc +0 -0
  241. package/backend/src/flowent/tools/connect.py +0 -100
  242. package/backend/src/flowent/tools/contacts.py +0 -22
  243. package/backend/src/flowent/tools/create_agent.py +0 -191
  244. package/backend/src/flowent/tools/create_tab.py +0 -61
  245. package/backend/src/flowent/tools/delete_tab.py +0 -39
  246. package/backend/src/flowent/tools/edit.py +0 -142
  247. package/backend/src/flowent/tools/exec.py +0 -118
  248. package/backend/src/flowent/tools/fetch.py +0 -85
  249. package/backend/src/flowent/tools/idle.py +0 -27
  250. package/backend/src/flowent/tools/list_roles.py +0 -75
  251. package/backend/src/flowent/tools/list_tabs.py +0 -100
  252. package/backend/src/flowent/tools/list_tools.py +0 -28
  253. package/backend/src/flowent/tools/manage_prompts.py +0 -102
  254. package/backend/src/flowent/tools/manage_providers.py +0 -220
  255. package/backend/src/flowent/tools/manage_roles.py +0 -275
  256. package/backend/src/flowent/tools/manage_settings.py +0 -364
  257. package/backend/src/flowent/tools/mcp.py +0 -199
  258. package/backend/src/flowent/tools/read.py +0 -152
  259. package/backend/src/flowent/tools/send.py +0 -68
  260. package/backend/src/flowent/tools/set_permissions.py +0 -99
  261. package/backend/src/flowent/tools/sleep.py +0 -41
  262. package/backend/src/flowent/tools/todo.py +0 -51
  263. package/backend/src/flowent/workspace_store.py +0 -479
  264. package/backend/tests/__init__.py +0 -0
  265. package/backend/tests/__pycache__/__init__.cpython-313.pyc +0 -0
  266. package/backend/tests/__pycache__/conftest.cpython-313-pytest-9.0.3.pyc +0 -0
  267. package/backend/tests/conftest.py +0 -6
  268. package/backend/tests/integration/api/__pycache__/conftest.cpython-313-pytest-9.0.3.pyc +0 -0
  269. package/backend/tests/integration/api/__pycache__/test_access_api.cpython-313-pytest-9.0.3.pyc +0 -0
  270. package/backend/tests/integration/api/__pycache__/test_assistant_api.cpython-313-pytest-9.0.3.pyc +0 -0
  271. package/backend/tests/integration/api/__pycache__/test_frontend_mounting.cpython-313-pytest-9.0.3.pyc +0 -0
  272. package/backend/tests/integration/api/__pycache__/test_mcp_api.cpython-313-pytest-9.0.3.pyc +0 -0
  273. package/backend/tests/integration/api/__pycache__/test_meta_api.cpython-313-pytest-9.0.3.pyc +0 -0
  274. package/backend/tests/integration/api/__pycache__/test_nodes_api.cpython-313-pytest-9.0.3.pyc +0 -0
  275. package/backend/tests/integration/api/__pycache__/test_prompts_api.cpython-313-pytest-9.0.3.pyc +0 -0
  276. package/backend/tests/integration/api/__pycache__/test_roles_api.cpython-313-pytest-9.0.3.pyc +0 -0
  277. package/backend/tests/integration/api/__pycache__/test_tabs_api.cpython-313-pytest-9.0.3.pyc +0 -0
  278. package/backend/tests/integration/api/conftest.py +0 -29
  279. package/backend/tests/integration/api/test_access_api.py +0 -182
  280. package/backend/tests/integration/api/test_assistant_api.py +0 -354
  281. package/backend/tests/integration/api/test_frontend_mounting.py +0 -61
  282. package/backend/tests/integration/api/test_mcp_api.py +0 -116
  283. package/backend/tests/integration/api/test_meta_api.py +0 -33
  284. package/backend/tests/integration/api/test_nodes_api.py +0 -722
  285. package/backend/tests/integration/api/test_prompts_api.py +0 -47
  286. package/backend/tests/integration/api/test_roles_api.py +0 -228
  287. package/backend/tests/integration/api/test_tabs_api.py +0 -802
  288. package/backend/tests/unit/__pycache__/test_access.cpython-313-pytest-9.0.3.pyc +0 -0
  289. package/backend/tests/unit/__pycache__/test_cli.cpython-313-pytest-9.0.3.pyc +0 -0
  290. package/backend/tests/unit/__pycache__/test_graph_runtime.cpython-313-pytest-9.0.3.pyc +0 -0
  291. package/backend/tests/unit/__pycache__/test_network.cpython-313-pytest-9.0.3.pyc +0 -0
  292. package/backend/tests/unit/__pycache__/test_state_sqlite_storage.cpython-313-pytest-9.0.3.pyc +0 -0
  293. package/backend/tests/unit/__pycache__/test_workspace_store.cpython-313-pytest-9.0.3.pyc +0 -0
  294. package/backend/tests/unit/agent/__pycache__/test_agent_public_api.cpython-313-pytest-9.0.3.pyc +0 -0
  295. package/backend/tests/unit/agent/__pycache__/test_agent_runtime.cpython-313-pytest-9.0.3.pyc +0 -0
  296. package/backend/tests/unit/agent/test_agent_public_api.py +0 -837
  297. package/backend/tests/unit/agent/test_agent_runtime.py +0 -2942
  298. package/backend/tests/unit/channels/__pycache__/test_telegram_channel.cpython-313-pytest-9.0.3.pyc +0 -0
  299. package/backend/tests/unit/channels/test_telegram_channel.py +0 -552
  300. package/backend/tests/unit/logging/__pycache__/test_logging.cpython-313-pytest-9.0.3.pyc +0 -0
  301. package/backend/tests/unit/logging/test_logging.py +0 -132
  302. package/backend/tests/unit/prompts/__pycache__/test_prompts.cpython-313-pytest-9.0.3.pyc +0 -0
  303. package/backend/tests/unit/prompts/test_prompts.py +0 -570
  304. package/backend/tests/unit/providers/__pycache__/test_anthropic_provider.cpython-313-pytest-9.0.3.pyc +0 -0
  305. package/backend/tests/unit/providers/__pycache__/test_errors.cpython-313-pytest-9.0.3.pyc +0 -0
  306. package/backend/tests/unit/providers/__pycache__/test_extract_delta_parts.cpython-313-pytest-9.0.3.pyc +0 -0
  307. package/backend/tests/unit/providers/__pycache__/test_openai_provider.cpython-313-pytest-9.0.3.pyc +0 -0
  308. package/backend/tests/unit/providers/__pycache__/test_openai_responses.cpython-313-pytest-9.0.3.pyc +0 -0
  309. package/backend/tests/unit/providers/__pycache__/test_provider_gateway.cpython-313-pytest-9.0.3.pyc +0 -0
  310. package/backend/tests/unit/providers/__pycache__/test_think_tag_parser.cpython-313-pytest-9.0.3.pyc +0 -0
  311. package/backend/tests/unit/providers/test_anthropic_provider.py +0 -185
  312. package/backend/tests/unit/providers/test_errors.py +0 -68
  313. package/backend/tests/unit/providers/test_extract_delta_parts.py +0 -22
  314. package/backend/tests/unit/providers/test_openai_provider.py +0 -139
  315. package/backend/tests/unit/providers/test_openai_responses.py +0 -402
  316. package/backend/tests/unit/providers/test_provider_gateway.py +0 -359
  317. package/backend/tests/unit/providers/test_think_tag_parser.py +0 -36
  318. package/backend/tests/unit/routes/__pycache__/test_prompts_routes.cpython-313-pytest-9.0.3.pyc +0 -0
  319. package/backend/tests/unit/routes/__pycache__/test_providers_route.cpython-313-pytest-9.0.3.pyc +0 -0
  320. package/backend/tests/unit/routes/__pycache__/test_roles_routes.cpython-313-pytest-9.0.3.pyc +0 -0
  321. package/backend/tests/unit/routes/__pycache__/test_settings_routes.cpython-313-pytest-9.0.3.pyc +0 -0
  322. package/backend/tests/unit/routes/test_prompts_routes.py +0 -104
  323. package/backend/tests/unit/routes/test_providers_route.py +0 -370
  324. package/backend/tests/unit/routes/test_roles_routes.py +0 -535
  325. package/backend/tests/unit/routes/test_settings_routes.py +0 -1142
  326. package/backend/tests/unit/runtime/__pycache__/test_bootstrap_runtime.cpython-313-pytest-9.0.3.pyc +0 -0
  327. package/backend/tests/unit/runtime/test_bootstrap_runtime.py +0 -1002
  328. package/backend/tests/unit/sandbox/__pycache__/test_sandbox_tools.cpython-313-pytest-9.0.3.pyc +0 -0
  329. package/backend/tests/unit/sandbox/test_sandbox_tools.py +0 -78
  330. package/backend/tests/unit/security/__pycache__/test_security.cpython-313-pytest-9.0.3.pyc +0 -0
  331. package/backend/tests/unit/security/test_security.py +0 -124
  332. package/backend/tests/unit/settings/__pycache__/test_settings_roles.cpython-313-pytest-9.0.3.pyc +0 -0
  333. package/backend/tests/unit/settings/test_settings_roles.py +0 -751
  334. package/backend/tests/unit/test_access.py +0 -45
  335. package/backend/tests/unit/test_cli.py +0 -124
  336. package/backend/tests/unit/test_graph_runtime.py +0 -72
  337. package/backend/tests/unit/test_network.py +0 -51
  338. package/backend/tests/unit/test_state_sqlite_storage.py +0 -159
  339. package/backend/tests/unit/test_workspace_store.py +0 -231
  340. package/backend/tests/unit/tools/__pycache__/test_connect_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  341. package/backend/tests/unit/tools/__pycache__/test_create_agent_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  342. package/backend/tests/unit/tools/__pycache__/test_delete_tab_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  343. package/backend/tests/unit/tools/__pycache__/test_edit_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  344. package/backend/tests/unit/tools/__pycache__/test_exec_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  345. package/backend/tests/unit/tools/__pycache__/test_fetch_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  346. package/backend/tests/unit/tools/__pycache__/test_manage_prompts_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  347. package/backend/tests/unit/tools/__pycache__/test_manage_providers_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  348. package/backend/tests/unit/tools/__pycache__/test_manage_roles_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  349. package/backend/tests/unit/tools/__pycache__/test_manage_settings_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  350. package/backend/tests/unit/tools/__pycache__/test_read_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  351. package/backend/tests/unit/tools/__pycache__/test_set_permissions_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  352. package/backend/tests/unit/tools/__pycache__/test_todo_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  353. package/backend/tests/unit/tools/__pycache__/test_tool_registry.cpython-313-pytest-9.0.3.pyc +0 -0
  354. package/backend/tests/unit/tools/test_connect_tool.py +0 -228
  355. package/backend/tests/unit/tools/test_create_agent_tool.py +0 -436
  356. package/backend/tests/unit/tools/test_delete_tab_tool.py +0 -116
  357. package/backend/tests/unit/tools/test_edit_tool.py +0 -115
  358. package/backend/tests/unit/tools/test_exec_tool.py +0 -81
  359. package/backend/tests/unit/tools/test_fetch_tool.py +0 -65
  360. package/backend/tests/unit/tools/test_manage_prompts_tool.py +0 -117
  361. package/backend/tests/unit/tools/test_manage_providers_tool.py +0 -460
  362. package/backend/tests/unit/tools/test_manage_roles_tool.py +0 -411
  363. package/backend/tests/unit/tools/test_manage_settings_tool.py +0 -611
  364. package/backend/tests/unit/tools/test_read_tool.py +0 -33
  365. package/backend/tests/unit/tools/test_set_permissions_tool.py +0 -595
  366. package/backend/tests/unit/tools/test_todo_tool.py +0 -37
  367. package/backend/tests/unit/tools/test_tool_registry.py +0 -194
  368. package/dist/frontend/assets/AssistantPage-VBohhz4d.js +0 -1
  369. package/dist/frontend/assets/ChannelsPage-CIydPZA_.js +0 -1
  370. package/dist/frontend/assets/McpPage-CHPm2TPY.js +0 -7
  371. package/dist/frontend/assets/PageScaffold-DteOA8V7.js +0 -1
  372. package/dist/frontend/assets/PromptsPage-CSmJ3sZg.js +0 -1
  373. package/dist/frontend/assets/ProvidersPage-sl2jeG4e.js +0 -3
  374. package/dist/frontend/assets/RolesPage-DCe7W6Km.js +0 -1
  375. package/dist/frontend/assets/SettingsPage-Bix9e63E.js +0 -3
  376. package/dist/frontend/assets/ToolsPage-favNkj5C.js +0 -1
  377. package/dist/frontend/assets/WorkspaceCommandDialog-DRS6wiD6.js +0 -1
  378. package/dist/frontend/assets/WorkspacePage-KuaDjt_D.js +0 -3
  379. package/dist/frontend/assets/WorkspacePanels-BZxBw8M5.js +0 -1
  380. package/dist/frontend/assets/alert-dialog-DIBUCmqM.js +0 -1
  381. package/dist/frontend/assets/datetime-eJqd0V2S.js +0 -1
  382. package/dist/frontend/assets/dialog-BOvHIBrg.js +0 -1
  383. package/dist/frontend/assets/elk-worker.min-C9JGDOE-.js +0 -6312
  384. package/dist/frontend/assets/graph-vendor-CHpVij2M.css +0 -1
  385. package/dist/frontend/assets/graph-vendor-DRq_-6fV.js +0 -7
  386. package/dist/frontend/assets/index-Biio-CoI.js +0 -10
  387. package/dist/frontend/assets/index-CmQvO7sl.css +0 -1
  388. package/dist/frontend/assets/layout.worker-jMHqAFbP.js +0 -24
  389. package/dist/frontend/assets/markdown-vendor-C9RtvaJh.js +0 -29
  390. package/dist/frontend/assets/modelParams-DcEhGnu0.js +0 -1
  391. package/dist/frontend/assets/react-vendor-mEs_JJxa.js +0 -9
  392. package/dist/frontend/assets/roles-BbIEIMeG.js +0 -1
  393. package/dist/frontend/assets/rolldown-runtime-BYbx6iT9.js +0 -1
  394. package/dist/frontend/assets/select-D9SwnlXF.js +0 -1
  395. package/dist/frontend/assets/surface-Bzr1FRG4.js +0 -1
  396. package/dist/frontend/assets/triState-DgLlKdRR.js +0 -1
  397. package/dist/frontend/assets/ui-vendor-UazN8rcv.js +0 -51
  398. package/dist/frontend/favicon.svg +0 -4
@@ -1,102 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from flowent.models import ModelCapabilities, ModelInfo
4
-
5
- _STATIC_CONTEXT_WINDOWS: tuple[tuple[tuple[str, ...], int], ...] = (
6
- (("gpt-5", "gpt-4.1", "gpt-4o", "o1", "o3"), 128_000),
7
- (("claude-3", "claude-sonnet-4", "claude-opus-4"), 200_000),
8
- (("gemini-2.5", "gemini-2.0"), 1_000_000),
9
- )
10
- _STATIC_INPUT_IMAGE_PREFIXES: tuple[str, ...] = (
11
- "gpt-5",
12
- "gpt-4.1",
13
- "gpt-4o",
14
- "claude-3",
15
- "claude-sonnet-4",
16
- "claude-opus-4",
17
- "gemini-2.5",
18
- "gemini-2.0",
19
- )
20
- _STATIC_OPENAI_RESPONSES_OUTPUT_IMAGE_PREFIXES: tuple[str, ...] = (
21
- "gpt-5",
22
- "gpt-4.1",
23
- "gpt-4o",
24
- )
25
-
26
-
27
- def _normalize_model_id(model_id: str) -> str:
28
- return model_id.strip().lower()
29
-
30
-
31
- def infer_model_capabilities(
32
- *,
33
- provider_type: str,
34
- model_id: str,
35
- input_image: bool | None = None,
36
- output_image: bool | None = None,
37
- structured_output: bool | None = None,
38
- ) -> ModelCapabilities:
39
- normalized_model_id = _normalize_model_id(model_id)
40
- inferred_input_image = any(
41
- normalized_model_id.startswith(prefix)
42
- for prefix in _STATIC_INPUT_IMAGE_PREFIXES
43
- )
44
- if provider_type == "gemini":
45
- inferred_input_image = True
46
- inferred_output_image = False
47
- if provider_type == "openai_responses":
48
- inferred_output_image = any(
49
- normalized_model_id.startswith(prefix)
50
- for prefix in _STATIC_OPENAI_RESPONSES_OUTPUT_IMAGE_PREFIXES
51
- )
52
- elif provider_type == "gemini":
53
- inferred_output_image = "image" in normalized_model_id
54
- return ModelCapabilities(
55
- input_image=inferred_input_image if input_image is None else input_image,
56
- output_image=(inferred_output_image if output_image is None else output_image),
57
- structured_output=False if structured_output is None else structured_output,
58
- )
59
-
60
-
61
- def infer_context_window_tokens(
62
- *,
63
- provider_type: str,
64
- model_id: str,
65
- context_window_tokens: int | None = None,
66
- ) -> int | None:
67
- if isinstance(context_window_tokens, int) and context_window_tokens > 0:
68
- return context_window_tokens
69
-
70
- normalized_model_id = _normalize_model_id(model_id)
71
- for prefixes, inferred_limit in _STATIC_CONTEXT_WINDOWS:
72
- if any(normalized_model_id.startswith(prefix) for prefix in prefixes):
73
- return inferred_limit
74
- if provider_type == "gemini" and normalized_model_id:
75
- return 1_000_000
76
- return None
77
-
78
-
79
- def build_model_info(
80
- *,
81
- provider_type: str,
82
- model_id: str,
83
- input_image: bool | None = None,
84
- output_image: bool | None = None,
85
- structured_output: bool | None = None,
86
- context_window_tokens: int | None = None,
87
- ) -> ModelInfo:
88
- return ModelInfo(
89
- id=model_id,
90
- capabilities=infer_model_capabilities(
91
- provider_type=provider_type,
92
- model_id=model_id,
93
- input_image=input_image,
94
- output_image=output_image,
95
- structured_output=structured_output,
96
- ),
97
- context_window_tokens=infer_context_window_tokens(
98
- provider_type=provider_type,
99
- model_id=model_id,
100
- context_window_tokens=context_window_tokens,
101
- ),
102
- )
@@ -1,125 +0,0 @@
1
- from flowent.models.agent import AgentState, NodeConfig, NodeType
2
- from flowent.models.base import Serializable
3
- from flowent.models.blueprint import (
4
- AgentBlueprint,
5
- BlueprintEdge,
6
- BlueprintSlot,
7
- BlueprintVersionSummary,
8
- )
9
- from flowent.models.content import (
10
- ContentPart,
11
- ImagePart,
12
- TextPart,
13
- content_parts_to_text,
14
- deserialize_content_parts,
15
- has_image_parts,
16
- parse_content_parts_payload,
17
- )
18
- from flowent.models.delta import (
19
- ContentDelta,
20
- ReceivedMessageDelta,
21
- SentMessageDelta,
22
- StreamingDelta,
23
- ThinkingDelta,
24
- ToolResultDelta,
25
- )
26
- from flowent.models.event import DISPLAY_EVENTS, Event, EventType
27
- from flowent.models.graph import (
28
- EdgeKind,
29
- GraphEdge,
30
- GraphNodeRecord,
31
- NodePosition,
32
- PortDirection,
33
- PortType,
34
- WorkflowActivationState,
35
- WorkflowDefinition,
36
- WorkflowNodeDefinition,
37
- WorkflowNodeKind,
38
- WorkflowPort,
39
- WorkflowViewDefinition,
40
- )
41
- from flowent.models.history import (
42
- AssistantText,
43
- AssistantThinking,
44
- CommandResultEntry,
45
- ErrorEntry,
46
- HistoryEntry,
47
- PortInboundEntry,
48
- ReceivedMessage,
49
- SentMessage,
50
- SystemEntry,
51
- ToolCall,
52
- )
53
- from flowent.models.llm import (
54
- LLMOutputImagePart,
55
- LLMOutputPart,
56
- LLMOutputTextPart,
57
- LLMResponse,
58
- LLMUsage,
59
- ModelCapabilities,
60
- ModelInfo,
61
- ToolCallResult,
62
- )
63
- from flowent.models.message import Message
64
- from flowent.models.tab import Tab
65
- from flowent.models.todo import TodoItem
66
-
67
- __all__ = [
68
- "DISPLAY_EVENTS",
69
- "AgentBlueprint",
70
- "AgentState",
71
- "AssistantText",
72
- "AssistantThinking",
73
- "BlueprintEdge",
74
- "BlueprintSlot",
75
- "BlueprintVersionSummary",
76
- "CommandResultEntry",
77
- "ContentDelta",
78
- "ContentPart",
79
- "EdgeKind",
80
- "ErrorEntry",
81
- "Event",
82
- "EventType",
83
- "GraphEdge",
84
- "GraphNodeRecord",
85
- "HistoryEntry",
86
- "ImagePart",
87
- "LLMOutputImagePart",
88
- "LLMOutputPart",
89
- "LLMOutputTextPart",
90
- "LLMResponse",
91
- "LLMUsage",
92
- "Message",
93
- "ModelCapabilities",
94
- "ModelInfo",
95
- "NodeConfig",
96
- "NodePosition",
97
- "NodeType",
98
- "PortDirection",
99
- "PortInboundEntry",
100
- "PortType",
101
- "ReceivedMessage",
102
- "ReceivedMessageDelta",
103
- "SentMessage",
104
- "SentMessageDelta",
105
- "Serializable",
106
- "StreamingDelta",
107
- "SystemEntry",
108
- "Tab",
109
- "TextPart",
110
- "ThinkingDelta",
111
- "TodoItem",
112
- "ToolCall",
113
- "ToolCallResult",
114
- "ToolResultDelta",
115
- "WorkflowActivationState",
116
- "WorkflowDefinition",
117
- "WorkflowNodeDefinition",
118
- "WorkflowNodeKind",
119
- "WorkflowPort",
120
- "WorkflowViewDefinition",
121
- "content_parts_to_text",
122
- "deserialize_content_parts",
123
- "has_image_parts",
124
- "parse_content_parts_payload",
125
- ]
@@ -1,34 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from dataclasses import dataclass, field
4
- from enum import StrEnum
5
-
6
-
7
- class NodeType(StrEnum):
8
- ASSISTANT = "assistant"
9
- AGENT = "agent"
10
- LLM = "llm"
11
- TRIGGER = "trigger"
12
- CODE = "code"
13
- IF = "if"
14
- MERGE = "merge"
15
-
16
-
17
- class AgentState(StrEnum):
18
- INITIALIZING = "initializing"
19
- IDLE = "idle"
20
- SLEEPING = "sleeping"
21
- RUNNING = "running"
22
- ERROR = "error"
23
- TERMINATED = "terminated"
24
-
25
-
26
- @dataclass
27
- class NodeConfig:
28
- node_type: NodeType
29
- role_name: str | None = None
30
- tab_id: str | None = None
31
- name: str | None = None
32
- tools: list[str] = field(default_factory=list)
33
- write_dirs: list[str] = field(default_factory=list)
34
- allow_network: bool = False
@@ -1,24 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from dataclasses import dataclass
4
- from typing import Any
5
-
6
-
7
- @dataclass
8
- class Serializable:
9
- def serialize(self) -> dict[str, Any]:
10
- fields: dict[str, Any] = {}
11
- for k, v in self.__dict__.items():
12
- if k.startswith("_"):
13
- continue
14
- if isinstance(v, Serializable):
15
- fields[k] = v.serialize()
16
- elif isinstance(v, list):
17
- fields[k] = [
18
- item.serialize() if isinstance(item, Serializable) else item
19
- for item in v
20
- ]
21
- else:
22
- fields[k] = v
23
- fields["type"] = self.__class__.__name__
24
- return fields
@@ -1,176 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import time
4
- from dataclasses import dataclass, field
5
-
6
-
7
- @dataclass
8
- class BlueprintSlot:
9
- id: str
10
- role_name: str
11
- display_name: str | None = None
12
-
13
- def serialize(self) -> dict[str, object]:
14
- return {
15
- "id": self.id,
16
- "role_name": self.role_name,
17
- "display_name": self.display_name,
18
- }
19
-
20
- @classmethod
21
- def from_mapping(cls, data: dict[str, object]) -> BlueprintSlot | None:
22
- slot_id = data.get("id")
23
- role_name = data.get("role_name")
24
- if not isinstance(slot_id, str) or not slot_id.strip():
25
- return None
26
- if not isinstance(role_name, str) or not role_name.strip():
27
- return None
28
- raw_display_name = data.get("display_name")
29
- return cls(
30
- id=slot_id.strip(),
31
- role_name=role_name.strip(),
32
- display_name=(
33
- raw_display_name.strip()
34
- if isinstance(raw_display_name, str) and raw_display_name.strip()
35
- else None
36
- ),
37
- )
38
-
39
-
40
- @dataclass
41
- class BlueprintEdge:
42
- from_slot_id: str
43
- to_slot_id: str
44
-
45
- def serialize(self) -> dict[str, object]:
46
- return {
47
- "from_slot_id": self.from_slot_id,
48
- "to_slot_id": self.to_slot_id,
49
- }
50
-
51
- @classmethod
52
- def from_mapping(cls, data: dict[str, object]) -> BlueprintEdge | None:
53
- from_slot_id = data.get("from_slot_id")
54
- to_slot_id = data.get("to_slot_id")
55
- if not isinstance(from_slot_id, str) or not from_slot_id.strip():
56
- return None
57
- if not isinstance(to_slot_id, str) or not to_slot_id.strip():
58
- return None
59
- return cls(
60
- from_slot_id=from_slot_id.strip(),
61
- to_slot_id=to_slot_id.strip(),
62
- )
63
-
64
-
65
- @dataclass
66
- class BlueprintVersionSummary:
67
- version: int
68
- updated_at: float
69
-
70
- def serialize(self) -> dict[str, object]:
71
- return {
72
- "version": self.version,
73
- "updated_at": self.updated_at,
74
- }
75
-
76
- @classmethod
77
- def from_mapping(
78
- cls,
79
- data: dict[str, object],
80
- ) -> BlueprintVersionSummary | None:
81
- version = data.get("version")
82
- updated_at = data.get("updated_at")
83
- if not isinstance(version, int) or version <= 0:
84
- return None
85
- if not isinstance(updated_at, (int, float)):
86
- return None
87
- return cls(version=version, updated_at=updated_at)
88
-
89
-
90
- @dataclass
91
- class AgentBlueprint:
92
- id: str
93
- name: str
94
- description: str = ""
95
- version: int = 1
96
- slots: list[BlueprintSlot] = field(default_factory=list)
97
- edges: list[BlueprintEdge] = field(default_factory=list)
98
- created_at: float = field(default_factory=time.time)
99
- updated_at: float = field(default_factory=time.time)
100
- version_history: list[BlueprintVersionSummary] = field(default_factory=list)
101
-
102
- def serialize(self) -> dict[str, object]:
103
- return {
104
- "id": self.id,
105
- "name": self.name,
106
- "description": self.description,
107
- "version": self.version,
108
- "slots": [slot.serialize() for slot in self.slots],
109
- "edges": [edge.serialize() for edge in self.edges],
110
- "created_at": self.created_at,
111
- "updated_at": self.updated_at,
112
- "version_history": [item.serialize() for item in self.version_history],
113
- }
114
-
115
- @classmethod
116
- def from_mapping(cls, data: dict[str, object]) -> AgentBlueprint:
117
- created_at = data.get("created_at")
118
- updated_at = data.get("updated_at")
119
- raw_slots = data.get("slots")
120
- raw_edges = data.get("edges")
121
- raw_version_history = data.get("version_history")
122
- slots = [
123
- slot
124
- for slot in (
125
- BlueprintSlot.from_mapping(item)
126
- for item in (raw_slots if isinstance(raw_slots, list) else [])
127
- if isinstance(item, dict)
128
- )
129
- if slot is not None
130
- ]
131
- edges = [
132
- edge
133
- for edge in (
134
- BlueprintEdge.from_mapping(item)
135
- for item in (raw_edges if isinstance(raw_edges, list) else [])
136
- if isinstance(item, dict)
137
- )
138
- if edge is not None
139
- ]
140
- raw_version = data.get("version")
141
- normalized_created_at = (
142
- created_at if isinstance(created_at, (int, float)) else time.time()
143
- )
144
- normalized_updated_at = (
145
- updated_at if isinstance(updated_at, (int, float)) else time.time()
146
- )
147
- version = raw_version if isinstance(raw_version, int) and raw_version > 0 else 1
148
- version_history = [
149
- item
150
- for item in (
151
- BlueprintVersionSummary.from_mapping(entry)
152
- for entry in (
153
- raw_version_history if isinstance(raw_version_history, list) else []
154
- )
155
- if isinstance(entry, dict)
156
- )
157
- if item is not None
158
- ]
159
- if not version_history:
160
- version_history = [
161
- BlueprintVersionSummary(
162
- version=version,
163
- updated_at=normalized_updated_at,
164
- )
165
- ]
166
- return cls(
167
- id=str(data.get("id", "")),
168
- name=str(data.get("name", "")),
169
- description=str(data.get("description", "")),
170
- version=version,
171
- slots=slots,
172
- edges=edges,
173
- created_at=normalized_created_at,
174
- updated_at=normalized_updated_at,
175
- version_history=version_history,
176
- )
@@ -1,164 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from dataclasses import dataclass
4
- from typing import Any
5
-
6
- from flowent.models.base import Serializable
7
-
8
-
9
- @dataclass
10
- class TextPart(Serializable):
11
- text: str
12
-
13
- def serialize(self) -> dict[str, Any]:
14
- return {"type": "text", "text": self.text}
15
-
16
-
17
- @dataclass
18
- class ImagePart(Serializable):
19
- asset_id: str
20
- mime_type: str | None = None
21
- width: int | None = None
22
- height: int | None = None
23
- alt: str | None = None
24
-
25
- def serialize(self) -> dict[str, Any]:
26
- return {
27
- "type": "image",
28
- "asset_id": self.asset_id,
29
- "mime_type": self.mime_type,
30
- "width": self.width,
31
- "height": self.height,
32
- "alt": self.alt,
33
- }
34
-
35
-
36
- ContentPart = TextPart | ImagePart
37
-
38
-
39
- def fallback_text_parts(content: str | None) -> list[ContentPart]:
40
- if not isinstance(content, str) or not content:
41
- return []
42
- return [TextPart(text=content)]
43
-
44
-
45
- def deserialize_content_parts(
46
- raw_parts: Any,
47
- *,
48
- fallback_text: str | None = None,
49
- ) -> list[ContentPart]:
50
- if not isinstance(raw_parts, list):
51
- return fallback_text_parts(fallback_text)
52
-
53
- parts: list[ContentPart] = []
54
- for raw_part in raw_parts:
55
- if not isinstance(raw_part, dict):
56
- continue
57
- part_type = raw_part.get("type")
58
- if part_type == "TextPart":
59
- part_type = "text"
60
- if part_type == "ImagePart":
61
- part_type = "image"
62
-
63
- if part_type == "text":
64
- text = raw_part.get("text")
65
- if isinstance(text, str):
66
- parts.append(TextPart(text=text))
67
- continue
68
-
69
- if part_type == "image":
70
- asset_id = raw_part.get("asset_id")
71
- if not isinstance(asset_id, str) or not asset_id:
72
- continue
73
- width = raw_part.get("width")
74
- height = raw_part.get("height")
75
- parts.append(
76
- ImagePart(
77
- asset_id=asset_id,
78
- mime_type=(
79
- str(raw_part["mime_type"])
80
- if isinstance(raw_part.get("mime_type"), str)
81
- else None
82
- ),
83
- width=width if isinstance(width, int) else None,
84
- height=height if isinstance(height, int) else None,
85
- alt=(
86
- str(raw_part["alt"])
87
- if isinstance(raw_part.get("alt"), str)
88
- else None
89
- ),
90
- )
91
- )
92
-
93
- if parts:
94
- return parts
95
- return fallback_text_parts(fallback_text)
96
-
97
-
98
- def parse_content_parts_payload(raw_parts: Any) -> list[ContentPart]:
99
- if not isinstance(raw_parts, list) or not raw_parts:
100
- raise ValueError("send.parts must be a non-empty array")
101
-
102
- parts: list[ContentPart] = []
103
- for index, raw_part in enumerate(raw_parts):
104
- if not isinstance(raw_part, dict):
105
- raise ValueError(f"send.parts[{index}] must be an object")
106
-
107
- part_type = raw_part.get("type")
108
- if part_type == "text":
109
- text = raw_part.get("text")
110
- if not isinstance(text, str):
111
- raise ValueError(f"send.parts[{index}].text must be a string")
112
- parts.append(TextPart(text=text))
113
- continue
114
-
115
- if part_type == "image":
116
- asset_id = raw_part.get("asset_id")
117
- if not isinstance(asset_id, str) or not asset_id:
118
- raise ValueError(
119
- f"send.parts[{index}].asset_id must be a non-empty string"
120
- )
121
- width = raw_part.get("width")
122
- height = raw_part.get("height")
123
- if width is not None and not isinstance(width, int):
124
- raise ValueError(f"send.parts[{index}].width must be an integer")
125
- if height is not None and not isinstance(height, int):
126
- raise ValueError(f"send.parts[{index}].height must be an integer")
127
- mime_type = raw_part.get("mime_type")
128
- if mime_type is not None and not isinstance(mime_type, str):
129
- raise ValueError(f"send.parts[{index}].mime_type must be a string")
130
- alt = raw_part.get("alt")
131
- if alt is not None and not isinstance(alt, str):
132
- raise ValueError(f"send.parts[{index}].alt must be a string")
133
- parts.append(
134
- ImagePart(
135
- asset_id=asset_id,
136
- mime_type=mime_type,
137
- width=width,
138
- height=height,
139
- alt=alt,
140
- )
141
- )
142
- continue
143
-
144
- raise ValueError(f"send.parts[{index}].type must be either `text` or `image`")
145
-
146
- return parts
147
-
148
-
149
- def content_parts_to_text(parts: list[ContentPart]) -> str:
150
- text_parts: list[str] = []
151
- for part in parts:
152
- if isinstance(part, TextPart):
153
- text_parts.append(part.text)
154
- continue
155
- if isinstance(part, ImagePart):
156
- if part.alt:
157
- text_parts.append(f"[image: {part.alt}]")
158
- else:
159
- text_parts.append("[image]")
160
- return "".join(text_parts)
161
-
162
-
163
- def has_image_parts(parts: list[ContentPart]) -> bool:
164
- return any(isinstance(part, ImagePart) for part in parts)