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,479 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import json
4
- import threading
5
- import time
6
- from dataclasses import dataclass, field
7
-
8
- from flowent.models import (
9
- AgentBlueprint,
10
- BlueprintVersionSummary,
11
- GraphEdge,
12
- GraphNodeRecord,
13
- NodeType,
14
- Tab,
15
- WorkflowDefinition,
16
- WorkflowNodeKind,
17
- )
18
- from flowent.state_db import get_legacy_workspace_file_path, open_state_db
19
-
20
-
21
- @dataclass
22
- class WorkspaceSnapshot:
23
- tabs: dict[str, Tab] = field(default_factory=dict)
24
- nodes: dict[str, GraphNodeRecord] = field(default_factory=dict)
25
- edges: dict[str, GraphEdge] = field(default_factory=dict)
26
- blueprints: dict[str, AgentBlueprint] = field(default_factory=dict)
27
-
28
- def serialize(self) -> dict[str, object]:
29
- return {
30
- "tabs": [tab.serialize() for tab in self.tabs.values()],
31
- "nodes": [node.serialize() for node in self.nodes.values()],
32
- "edges": [edge.serialize() for edge in self.edges.values()],
33
- "blueprints": [
34
- blueprint.serialize() for blueprint in self.blueprints.values()
35
- ],
36
- }
37
-
38
- @classmethod
39
- def from_mapping(cls, data: dict[str, object]) -> WorkspaceSnapshot:
40
- from flowent.graph_service import build_workflow_node_definition
41
-
42
- raw_tabs = data.get("tabs")
43
- raw_nodes = data.get("nodes")
44
- raw_edges = data.get("edges")
45
- raw_blueprints = data.get("blueprints")
46
- tabs = {
47
- tab.id: tab
48
- for tab in (
49
- Tab.from_mapping(item)
50
- for item in (raw_tabs if isinstance(raw_tabs, list) else [])
51
- if isinstance(item, dict)
52
- )
53
- }
54
- nodes = {
55
- node.id: node
56
- for node in (
57
- GraphNodeRecord.from_mapping(item)
58
- for item in (raw_nodes if isinstance(raw_nodes, list) else [])
59
- if isinstance(item, dict)
60
- )
61
- }
62
- edges = {
63
- edge.id: edge
64
- for edge in (
65
- GraphEdge.from_mapping(item)
66
- for item in (raw_edges if isinstance(raw_edges, list) else [])
67
- if isinstance(item, dict)
68
- )
69
- }
70
- blueprints = {
71
- blueprint.id: blueprint
72
- for blueprint in (
73
- AgentBlueprint.from_mapping(item)
74
- for item in (raw_blueprints if isinstance(raw_blueprints, list) else [])
75
- if isinstance(item, dict)
76
- )
77
- if blueprint.id
78
- }
79
- for tab in tabs.values():
80
- if not isinstance(tab.definition, WorkflowDefinition):
81
- tab.definition = WorkflowDefinition()
82
- tab_node_records = sorted(
83
- [
84
- node
85
- for node in nodes.values()
86
- if node.config.tab_id == tab.id and tab.leader_id != node.id
87
- ],
88
- key=lambda node: (node.created_at, node.id),
89
- )
90
- if not tab.definition.nodes:
91
- migrated_nodes = []
92
- for node in tab_node_records:
93
- if node.config.node_type != NodeType.AGENT:
94
- continue
95
- migrated_nodes.append(
96
- build_workflow_node_definition(
97
- node_id=node.id,
98
- node_kind=WorkflowNodeKind.AGENT,
99
- config={
100
- "role_name": node.config.role_name or "",
101
- **(
102
- {"name": node.config.name}
103
- if node.config.name is not None
104
- else {}
105
- ),
106
- },
107
- )
108
- )
109
- tab.definition.nodes = migrated_nodes
110
- known_node_ids = {node.id for node in tab.definition.nodes}
111
- if not tab.definition.edges:
112
- tab.definition.edges = [
113
- GraphEdge(
114
- id=edge.id,
115
- tab_id=tab.id,
116
- from_node_id=edge.from_node_id,
117
- from_port_key=edge.from_port_key,
118
- to_node_id=edge.to_node_id,
119
- to_port_key=edge.to_port_key,
120
- kind=edge.kind,
121
- created_at=edge.created_at,
122
- )
123
- for edge in edges.values()
124
- if edge.tab_id == tab.id
125
- and edge.from_node_id in known_node_ids
126
- and edge.to_node_id in known_node_ids
127
- ]
128
- for node in tab_node_records:
129
- if node.position is None:
130
- continue
131
- tab.definition.view.positions[node.id] = node.position
132
- return cls(tabs=tabs, nodes=nodes, edges=edges, blueprints=blueprints)
133
-
134
-
135
- class WorkspaceStore:
136
- def __init__(self) -> None:
137
- self._lock = threading.Lock()
138
- self._snapshot: WorkspaceSnapshot | None = None
139
-
140
- def _load_snapshot(self) -> WorkspaceSnapshot:
141
- if self._snapshot is not None:
142
- return self._snapshot
143
- snapshot = self._load_snapshot_from_state_db()
144
- legacy_snapshot = self._load_snapshot_from_legacy_file()
145
- if self._snapshot_has_content(
146
- legacy_snapshot
147
- ) and not self._snapshot_has_content(snapshot):
148
- assert legacy_snapshot is not None
149
- snapshot = legacy_snapshot
150
- self._persist_snapshot(snapshot)
151
- if snapshot is None:
152
- snapshot = (
153
- legacy_snapshot if legacy_snapshot is not None else WorkspaceSnapshot()
154
- )
155
- self._snapshot = snapshot
156
- return snapshot
157
-
158
- def _load_snapshot_from_state_db(self) -> WorkspaceSnapshot | None:
159
- connection = open_state_db(create=False)
160
- if connection is None:
161
- return None
162
- try:
163
- raw: dict[str, object] = {
164
- "tabs": self._read_payload_rows(connection, "tabs"),
165
- "nodes": self._read_payload_rows(connection, "nodes"),
166
- "edges": self._read_payload_rows(connection, "edges"),
167
- "blueprints": self._read_payload_rows(connection, "blueprints"),
168
- }
169
- finally:
170
- connection.close()
171
- snapshot = WorkspaceSnapshot.from_mapping(raw)
172
- if snapshot.serialize() != raw:
173
- self._persist_snapshot(snapshot)
174
- return snapshot
175
-
176
- def _load_snapshot_from_legacy_file(self) -> WorkspaceSnapshot | None:
177
- workspace_file = get_legacy_workspace_file_path()
178
- if not workspace_file.exists():
179
- return None
180
- raw = json.loads(workspace_file.read_text(encoding="utf-8"))
181
- if not isinstance(raw, dict):
182
- return WorkspaceSnapshot()
183
- return WorkspaceSnapshot.from_mapping(raw)
184
-
185
- def _snapshot_has_content(self, snapshot: WorkspaceSnapshot | None) -> bool:
186
- return bool(
187
- snapshot is not None
188
- and (
189
- snapshot.tabs or snapshot.nodes or snapshot.edges or snapshot.blueprints
190
- )
191
- )
192
-
193
- def _read_payload_rows(
194
- self,
195
- connection,
196
- table_name: str,
197
- ) -> list[dict[str, object]]:
198
- try:
199
- rows = connection.execute(
200
- f"SELECT payload FROM {table_name} ORDER BY rowid"
201
- ).fetchall()
202
- except Exception as exc:
203
- raise RuntimeError(
204
- f"Failed to read workspace table `{table_name}` from state store: {exc}"
205
- ) from exc
206
- payloads: list[dict[str, object]] = []
207
- for row in rows:
208
- payload = row["payload"]
209
- if not isinstance(payload, str):
210
- continue
211
- parsed = json.loads(payload)
212
- if isinstance(parsed, dict):
213
- payloads.append(parsed)
214
- return payloads
215
-
216
- def _persist_snapshot(self, snapshot: WorkspaceSnapshot) -> None:
217
- connection = open_state_db(create=True)
218
- assert connection is not None
219
- try:
220
- with connection:
221
- connection.execute("DELETE FROM tabs")
222
- connection.execute("DELETE FROM nodes")
223
- connection.execute("DELETE FROM edges")
224
- connection.execute("DELETE FROM blueprints")
225
- connection.executemany(
226
- "INSERT INTO tabs (id, payload, updated_at) VALUES (?, ?, ?)",
227
- [
228
- (
229
- tab.id,
230
- json.dumps(tab.serialize(), ensure_ascii=False),
231
- tab.updated_at,
232
- )
233
- for tab in snapshot.tabs.values()
234
- ],
235
- )
236
- connection.executemany(
237
- """
238
- INSERT INTO nodes (id, payload, tab_id, node_type, updated_at)
239
- VALUES (?, ?, ?, ?, ?)
240
- """,
241
- [
242
- (
243
- record.id,
244
- json.dumps(record.serialize(), ensure_ascii=False),
245
- record.config.tab_id,
246
- record.config.node_type.value,
247
- record.updated_at,
248
- )
249
- for record in snapshot.nodes.values()
250
- ],
251
- )
252
- connection.executemany(
253
- "INSERT INTO edges (id, payload, tab_id) VALUES (?, ?, ?)",
254
- [
255
- (
256
- edge.id,
257
- json.dumps(edge.serialize(), ensure_ascii=False),
258
- edge.tab_id,
259
- )
260
- for tab in snapshot.tabs.values()
261
- for edge in (
262
- GraphEdge(
263
- id=item.id,
264
- tab_id=tab.id,
265
- from_node_id=item.from_node_id,
266
- from_port_key=item.from_port_key,
267
- to_node_id=item.to_node_id,
268
- to_port_key=item.to_port_key,
269
- kind=item.kind,
270
- created_at=item.created_at,
271
- )
272
- for item in tab.definition.edges
273
- )
274
- ],
275
- )
276
- connection.executemany(
277
- "INSERT INTO blueprints (id, payload, updated_at) VALUES (?, ?, ?)",
278
- [
279
- (
280
- blueprint.id,
281
- json.dumps(blueprint.serialize(), ensure_ascii=False),
282
- blueprint.updated_at,
283
- )
284
- for blueprint in snapshot.blueprints.values()
285
- ],
286
- )
287
- finally:
288
- connection.close()
289
-
290
- def reset_cache(self) -> None:
291
- with self._lock:
292
- self._snapshot = None
293
-
294
- def list_tabs(self) -> list[Tab]:
295
- with self._lock:
296
- return list(self._load_snapshot().tabs.values())
297
-
298
- def get_tab(self, tab_id: str) -> Tab | None:
299
- with self._lock:
300
- return self._load_snapshot().tabs.get(tab_id)
301
-
302
- def upsert_tab(self, tab: Tab) -> None:
303
- with self._lock:
304
- snapshot = self._load_snapshot()
305
- tab.updated_at = time.time()
306
- snapshot.tabs[tab.id] = tab
307
- self._persist_snapshot(snapshot)
308
-
309
- def delete_tab(self, tab_id: str) -> None:
310
- with self._lock:
311
- snapshot = self._load_snapshot()
312
- snapshot.tabs.pop(tab_id, None)
313
- node_ids = [
314
- node_id
315
- for node_id, node in snapshot.nodes.items()
316
- if node.config.tab_id == tab_id
317
- ]
318
- for node_id in node_ids:
319
- snapshot.nodes.pop(node_id, None)
320
- edge_ids = [
321
- edge_id
322
- for edge_id, edge in snapshot.edges.items()
323
- if edge.tab_id == tab_id
324
- or edge.from_node_id in node_ids
325
- or edge.to_node_id in node_ids
326
- ]
327
- for edge_id in edge_ids:
328
- snapshot.edges.pop(edge_id, None)
329
- self._persist_snapshot(snapshot)
330
-
331
- def list_node_records(self, tab_id: str | None = None) -> list[GraphNodeRecord]:
332
- with self._lock:
333
- nodes = list(self._load_snapshot().nodes.values())
334
- if tab_id is None:
335
- return nodes
336
- return [node for node in nodes if node.config.tab_id == tab_id]
337
-
338
- def get_node_record(self, node_id: str) -> GraphNodeRecord | None:
339
- with self._lock:
340
- return self._load_snapshot().nodes.get(node_id)
341
-
342
- def upsert_node_record(self, record: GraphNodeRecord) -> None:
343
- with self._lock:
344
- snapshot = self._load_snapshot()
345
- record.updated_at = time.time()
346
- snapshot.nodes[record.id] = record
347
- if record.config.tab_id and record.config.tab_id in snapshot.tabs:
348
- snapshot.tabs[record.config.tab_id].updated_at = record.updated_at
349
- self._persist_snapshot(snapshot)
350
-
351
- def delete_node_record(self, node_id: str) -> None:
352
- with self._lock:
353
- snapshot = self._load_snapshot()
354
- record = snapshot.nodes.pop(node_id, None)
355
- if record is None:
356
- return
357
- edge_ids = [
358
- edge_id
359
- for edge_id, edge in snapshot.edges.items()
360
- if edge.from_node_id == node_id or edge.to_node_id == node_id
361
- ]
362
- for edge_id in edge_ids:
363
- snapshot.edges.pop(edge_id, None)
364
- if record.config.tab_id and record.config.tab_id in snapshot.tabs:
365
- snapshot.tabs[record.config.tab_id].updated_at = time.time()
366
- self._persist_snapshot(snapshot)
367
-
368
- def list_edges(self, tab_id: str | None = None) -> list[GraphEdge]:
369
- with self._lock:
370
- snapshot = self._load_snapshot()
371
- result: list[GraphEdge] = []
372
- for tab in snapshot.tabs.values():
373
- if tab_id is not None and tab.id != tab_id:
374
- continue
375
- result.extend(
376
- GraphEdge(
377
- id=edge.id,
378
- tab_id=tab.id,
379
- from_node_id=edge.from_node_id,
380
- from_port_key=edge.from_port_key,
381
- to_node_id=edge.to_node_id,
382
- to_port_key=edge.to_port_key,
383
- kind=edge.kind,
384
- created_at=edge.created_at,
385
- )
386
- for edge in tab.definition.edges
387
- )
388
- return result
389
-
390
- def get_edge(self, edge_id: str) -> GraphEdge | None:
391
- with self._lock:
392
- snapshot = self._load_snapshot()
393
- for tab in snapshot.tabs.values():
394
- edge = next(
395
- (item for item in tab.definition.edges if item.id == edge_id),
396
- None,
397
- )
398
- if edge is None:
399
- continue
400
- return GraphEdge(
401
- id=edge.id,
402
- tab_id=tab.id,
403
- from_node_id=edge.from_node_id,
404
- from_port_key=edge.from_port_key,
405
- to_node_id=edge.to_node_id,
406
- to_port_key=edge.to_port_key,
407
- kind=edge.kind,
408
- created_at=edge.created_at,
409
- )
410
- return None
411
-
412
- def upsert_edge(self, edge: GraphEdge) -> None:
413
- with self._lock:
414
- snapshot = self._load_snapshot()
415
- if edge.tab_id is None or edge.tab_id not in snapshot.tabs:
416
- return
417
- tab = snapshot.tabs[edge.tab_id]
418
- tab.definition.edges = [
419
- item for item in tab.definition.edges if item.id != edge.id
420
- ]
421
- tab.definition.edges.append(edge)
422
- tab.updated_at = time.time()
423
- self._persist_snapshot(snapshot)
424
-
425
- def delete_edge(self, edge_id: str) -> None:
426
- with self._lock:
427
- snapshot = self._load_snapshot()
428
- for tab in snapshot.tabs.values():
429
- original_size = len(tab.definition.edges)
430
- tab.definition.edges = [
431
- edge for edge in tab.definition.edges if edge.id != edge_id
432
- ]
433
- if len(tab.definition.edges) == original_size:
434
- continue
435
- tab.updated_at = time.time()
436
- break
437
- self._persist_snapshot(snapshot)
438
-
439
- def list_blueprints(self) -> list[AgentBlueprint]:
440
- with self._lock:
441
- return list(self._load_snapshot().blueprints.values())
442
-
443
- def get_blueprint(self, blueprint_id: str) -> AgentBlueprint | None:
444
- with self._lock:
445
- return self._load_snapshot().blueprints.get(blueprint_id)
446
-
447
- def upsert_blueprint(self, blueprint: AgentBlueprint) -> None:
448
- with self._lock:
449
- snapshot = self._load_snapshot()
450
- updated_at = time.time()
451
- blueprint.updated_at = updated_at
452
- if not blueprint.version_history:
453
- blueprint.version_history.append(
454
- BlueprintVersionSummary(
455
- version=blueprint.version,
456
- updated_at=updated_at,
457
- )
458
- )
459
- elif blueprint.version_history[-1].version == blueprint.version:
460
- blueprint.version_history[-1].updated_at = updated_at
461
- else:
462
- blueprint.version_history.append(
463
- BlueprintVersionSummary(
464
- version=blueprint.version,
465
- updated_at=updated_at,
466
- )
467
- )
468
- snapshot.blueprints[blueprint.id] = blueprint
469
- self._persist_snapshot(snapshot)
470
-
471
- def delete_blueprint(self, blueprint_id: str) -> None:
472
- with self._lock:
473
- snapshot = self._load_snapshot()
474
- if snapshot.blueprints.pop(blueprint_id, None) is None:
475
- return
476
- self._persist_snapshot(snapshot)
477
-
478
-
479
- workspace_store = WorkspaceStore()
File without changes
@@ -1,6 +0,0 @@
1
- import os
2
- import tempfile
3
-
4
- if not os.environ.get("FLOWENT_APP_DATA_DIR"):
5
- _APP_DATA_DIR = tempfile.TemporaryDirectory(prefix="flowent-pytest-")
6
- os.environ["FLOWENT_APP_DATA_DIR"] = _APP_DATA_DIR.name
@@ -1,29 +0,0 @@
1
- import pytest
2
- from fastapi.testclient import TestClient
3
-
4
-
5
- @pytest.fixture
6
- def client(monkeypatch, tmp_path):
7
- import flowent.settings as settings_module
8
- from flowent.access import set_access_code
9
-
10
- settings_file = tmp_path / "settings.json"
11
- monkeypatch.setattr(settings_module, "_SETTINGS_FILE", settings_file)
12
- monkeypatch.setattr(settings_module, "_cached_settings", None)
13
-
14
- settings = settings_module.Settings()
15
- set_access_code(settings, "TEST-ACCESS-CODE")
16
- settings_module.save_settings(settings)
17
- monkeypatch.setattr(settings_module, "_cached_settings", None)
18
-
19
- from flowent.main import app
20
-
21
- with TestClient(app) as client:
22
- login_response = client.post(
23
- "/api/access/login",
24
- json={"code": "TEST-ACCESS-CODE"},
25
- )
26
- assert login_response.status_code == 200
27
- yield client
28
-
29
- monkeypatch.setattr(settings_module, "_cached_settings", None)