flowent 0.0.7 → 0.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (387) hide show
  1. package/README.md +0 -3
  2. package/backend/README.md +0 -3
  3. package/backend/pyproject.toml +2 -8
  4. package/backend/src/flowent/__init__.py +6 -2
  5. package/backend/src/flowent/__pycache__/__init__.cpython-313.pyc +0 -0
  6. package/backend/src/flowent/__pycache__/agent.cpython-313.pyc +0 -0
  7. package/backend/src/flowent/__pycache__/context.cpython-313.pyc +0 -0
  8. package/backend/src/flowent/__pycache__/llm.cpython-313.pyc +0 -0
  9. package/backend/src/flowent/__pycache__/logging.cpython-313.pyc +0 -0
  10. package/backend/src/flowent/__pycache__/main.cpython-313.pyc +0 -0
  11. package/backend/src/flowent/__pycache__/patch.cpython-313.pyc +0 -0
  12. package/backend/src/flowent/__pycache__/paths.cpython-313.pyc +0 -0
  13. package/backend/src/flowent/__pycache__/sandbox.cpython-313.pyc +0 -0
  14. package/backend/src/flowent/__pycache__/storage.cpython-313.pyc +0 -0
  15. package/backend/src/flowent/__pycache__/tools.cpython-313.pyc +0 -0
  16. package/backend/src/flowent/agent.py +213 -3173
  17. package/backend/src/flowent/cli.py +19 -24
  18. package/backend/src/flowent/context.py +127 -0
  19. package/backend/src/flowent/llm.py +256 -0
  20. package/backend/src/flowent/logging.py +170 -129
  21. package/backend/src/flowent/main.py +321 -70
  22. package/backend/src/flowent/patch.py +182 -0
  23. package/backend/src/flowent/paths.py +11 -0
  24. package/backend/src/flowent/sandbox.py +214 -40
  25. package/backend/src/flowent/static/assets/geist-cyrillic-wght-normal-CHSlOQsW.woff2 +0 -0
  26. package/backend/src/flowent/static/assets/geist-latin-ext-wght-normal-DMtmJ5ZE.woff2 +0 -0
  27. package/backend/src/flowent/static/assets/geist-latin-wght-normal-Dm3htQBi.woff2 +0 -0
  28. package/backend/src/flowent/static/assets/index-C76K95ty.js +81 -0
  29. package/backend/src/flowent/static/assets/index-iUMNKvlU.css +2 -0
  30. package/backend/src/flowent/static/flowent.png +0 -0
  31. package/backend/src/flowent/static/index.html +5 -25
  32. package/backend/src/flowent/storage.py +302 -0
  33. package/backend/src/flowent/tools.py +376 -0
  34. package/backend/tests/__pycache__/test_agent_tools.cpython-313-pytest-9.0.3.pyc +0 -0
  35. package/backend/tests/__pycache__/test_health.cpython-313-pytest-9.0.3.pyc +0 -0
  36. package/backend/tests/__pycache__/test_llm_providers.cpython-313-pytest-9.0.3.pyc +0 -0
  37. package/backend/tests/__pycache__/test_logging.cpython-313-pytest-9.0.3.pyc +0 -0
  38. package/backend/tests/__pycache__/test_persistence.cpython-313-pytest-9.0.3.pyc +0 -0
  39. package/backend/tests/__pycache__/test_workspace_chat.cpython-313-pytest-9.0.3.pyc +0 -0
  40. package/backend/tests/test_agent_tools.py +477 -0
  41. package/backend/tests/test_health.py +12 -0
  42. package/backend/tests/test_llm_providers.py +113 -0
  43. package/backend/tests/test_logging.py +182 -0
  44. package/backend/tests/test_persistence.py +125 -0
  45. package/backend/tests/test_workspace_chat.py +578 -0
  46. package/backend/uv.lock +803 -99
  47. package/dist/frontend/assets/geist-cyrillic-wght-normal-CHSlOQsW.woff2 +0 -0
  48. package/dist/frontend/assets/geist-latin-ext-wght-normal-DMtmJ5ZE.woff2 +0 -0
  49. package/dist/frontend/assets/geist-latin-wght-normal-Dm3htQBi.woff2 +0 -0
  50. package/dist/frontend/assets/index-C76K95ty.js +81 -0
  51. package/dist/frontend/assets/index-iUMNKvlU.css +2 -0
  52. package/dist/frontend/flowent.png +0 -0
  53. package/dist/frontend/index.html +5 -25
  54. package/package.json +1 -2
  55. package/backend/src/flowent/__pycache__/_version.cpython-313.pyc +0 -0
  56. package/backend/src/flowent/__pycache__/access.cpython-313.pyc +0 -0
  57. package/backend/src/flowent/__pycache__/assistant_commands.cpython-313.pyc +0 -0
  58. package/backend/src/flowent/__pycache__/cli.cpython-313.pyc +0 -0
  59. package/backend/src/flowent/__pycache__/config.cpython-313.pyc +0 -0
  60. package/backend/src/flowent/__pycache__/events.cpython-313.pyc +0 -0
  61. package/backend/src/flowent/__pycache__/graph_runtime.cpython-313.pyc +0 -0
  62. package/backend/src/flowent/__pycache__/graph_service.cpython-313.pyc +0 -0
  63. package/backend/src/flowent/__pycache__/image_assets.cpython-313.pyc +0 -0
  64. package/backend/src/flowent/__pycache__/model_metadata.cpython-313.pyc +0 -0
  65. package/backend/src/flowent/__pycache__/network.cpython-313.pyc +0 -0
  66. package/backend/src/flowent/__pycache__/observability_service.cpython-313.pyc +0 -0
  67. package/backend/src/flowent/__pycache__/registry.cpython-313.pyc +0 -0
  68. package/backend/src/flowent/__pycache__/role_management.cpython-313.pyc +0 -0
  69. package/backend/src/flowent/__pycache__/runtime.cpython-313.pyc +0 -0
  70. package/backend/src/flowent/__pycache__/security.cpython-313.pyc +0 -0
  71. package/backend/src/flowent/__pycache__/settings.cpython-313.pyc +0 -0
  72. package/backend/src/flowent/__pycache__/settings_management.cpython-313.pyc +0 -0
  73. package/backend/src/flowent/__pycache__/state_db.cpython-313.pyc +0 -0
  74. package/backend/src/flowent/__pycache__/workspace_store.cpython-313.pyc +0 -0
  75. package/backend/src/flowent/access.py +0 -247
  76. package/backend/src/flowent/assistant_commands.py +0 -115
  77. package/backend/src/flowent/channels/__init__.py +0 -3
  78. package/backend/src/flowent/channels/__pycache__/__init__.cpython-313.pyc +0 -0
  79. package/backend/src/flowent/channels/__pycache__/telegram.cpython-313.pyc +0 -0
  80. package/backend/src/flowent/channels/telegram.py +0 -615
  81. package/backend/src/flowent/config.py +0 -14
  82. package/backend/src/flowent/dev.py +0 -3
  83. package/backend/src/flowent/events.py +0 -157
  84. package/backend/src/flowent/graph_runtime.py +0 -60
  85. package/backend/src/flowent/graph_service.py +0 -2401
  86. package/backend/src/flowent/image_assets.py +0 -356
  87. package/backend/src/flowent/model_metadata.py +0 -102
  88. package/backend/src/flowent/models/__init__.py +0 -125
  89. package/backend/src/flowent/models/__pycache__/__init__.cpython-313.pyc +0 -0
  90. package/backend/src/flowent/models/__pycache__/agent.cpython-313.pyc +0 -0
  91. package/backend/src/flowent/models/__pycache__/base.cpython-313.pyc +0 -0
  92. package/backend/src/flowent/models/__pycache__/blueprint.cpython-313.pyc +0 -0
  93. package/backend/src/flowent/models/__pycache__/content.cpython-313.pyc +0 -0
  94. package/backend/src/flowent/models/__pycache__/delta.cpython-313.pyc +0 -0
  95. package/backend/src/flowent/models/__pycache__/event.cpython-313.pyc +0 -0
  96. package/backend/src/flowent/models/__pycache__/graph.cpython-313.pyc +0 -0
  97. package/backend/src/flowent/models/__pycache__/history.cpython-313.pyc +0 -0
  98. package/backend/src/flowent/models/__pycache__/llm.cpython-313.pyc +0 -0
  99. package/backend/src/flowent/models/__pycache__/message.cpython-313.pyc +0 -0
  100. package/backend/src/flowent/models/__pycache__/tab.cpython-313.pyc +0 -0
  101. package/backend/src/flowent/models/__pycache__/todo.cpython-313.pyc +0 -0
  102. package/backend/src/flowent/models/agent.py +0 -34
  103. package/backend/src/flowent/models/base.py +0 -24
  104. package/backend/src/flowent/models/blueprint.py +0 -176
  105. package/backend/src/flowent/models/content.py +0 -164
  106. package/backend/src/flowent/models/delta.py +0 -44
  107. package/backend/src/flowent/models/event.py +0 -51
  108. package/backend/src/flowent/models/graph.py +0 -472
  109. package/backend/src/flowent/models/history.py +0 -272
  110. package/backend/src/flowent/models/llm.py +0 -62
  111. package/backend/src/flowent/models/message.py +0 -33
  112. package/backend/src/flowent/models/tab.py +0 -85
  113. package/backend/src/flowent/models/todo.py +0 -10
  114. package/backend/src/flowent/network.py +0 -146
  115. package/backend/src/flowent/observability_service.py +0 -218
  116. package/backend/src/flowent/prompts/__init__.py +0 -67
  117. package/backend/src/flowent/prompts/__pycache__/__init__.cpython-313.pyc +0 -0
  118. package/backend/src/flowent/prompts/__pycache__/common.cpython-313.pyc +0 -0
  119. package/backend/src/flowent/prompts/__pycache__/steward.cpython-313.pyc +0 -0
  120. package/backend/src/flowent/prompts/common.py +0 -250
  121. package/backend/src/flowent/prompts/steward.py +0 -64
  122. package/backend/src/flowent/providers/__init__.py +0 -23
  123. package/backend/src/flowent/providers/__pycache__/__init__.cpython-313.pyc +0 -0
  124. package/backend/src/flowent/providers/__pycache__/anthropic.cpython-313.pyc +0 -0
  125. package/backend/src/flowent/providers/__pycache__/base_url.cpython-313.pyc +0 -0
  126. package/backend/src/flowent/providers/__pycache__/configuration.cpython-313.pyc +0 -0
  127. package/backend/src/flowent/providers/__pycache__/content.cpython-313.pyc +0 -0
  128. package/backend/src/flowent/providers/__pycache__/errors.cpython-313.pyc +0 -0
  129. package/backend/src/flowent/providers/__pycache__/gateway.cpython-313.pyc +0 -0
  130. package/backend/src/flowent/providers/__pycache__/headers.cpython-313.pyc +0 -0
  131. package/backend/src/flowent/providers/__pycache__/management.cpython-313.pyc +0 -0
  132. package/backend/src/flowent/providers/__pycache__/openai.cpython-313.pyc +0 -0
  133. package/backend/src/flowent/providers/__pycache__/openai_responses.cpython-313.pyc +0 -0
  134. package/backend/src/flowent/providers/__pycache__/registry.cpython-313.pyc +0 -0
  135. package/backend/src/flowent/providers/__pycache__/sse.cpython-313.pyc +0 -0
  136. package/backend/src/flowent/providers/__pycache__/thinking.cpython-313.pyc +0 -0
  137. package/backend/src/flowent/providers/anthropic.py +0 -468
  138. package/backend/src/flowent/providers/base_url.py +0 -60
  139. package/backend/src/flowent/providers/configuration.py +0 -189
  140. package/backend/src/flowent/providers/content.py +0 -122
  141. package/backend/src/flowent/providers/errors.py +0 -223
  142. package/backend/src/flowent/providers/gateway.py +0 -169
  143. package/backend/src/flowent/providers/gemini.py +0 -447
  144. package/backend/src/flowent/providers/headers.py +0 -20
  145. package/backend/src/flowent/providers/management.py +0 -96
  146. package/backend/src/flowent/providers/ollama.py +0 -293
  147. package/backend/src/flowent/providers/openai.py +0 -422
  148. package/backend/src/flowent/providers/openai_responses.py +0 -655
  149. package/backend/src/flowent/providers/registry.py +0 -144
  150. package/backend/src/flowent/providers/sse.py +0 -31
  151. package/backend/src/flowent/providers/thinking.py +0 -79
  152. package/backend/src/flowent/registry.py +0 -73
  153. package/backend/src/flowent/role_management.py +0 -270
  154. package/backend/src/flowent/routes/__init__.py +0 -26
  155. package/backend/src/flowent/routes/__pycache__/__init__.cpython-313.pyc +0 -0
  156. package/backend/src/flowent/routes/__pycache__/access.cpython-313.pyc +0 -0
  157. package/backend/src/flowent/routes/__pycache__/assistant.cpython-313.pyc +0 -0
  158. package/backend/src/flowent/routes/__pycache__/image_assets.cpython-313.pyc +0 -0
  159. package/backend/src/flowent/routes/__pycache__/meta.cpython-313.pyc +0 -0
  160. package/backend/src/flowent/routes/__pycache__/nodes.cpython-313.pyc +0 -0
  161. package/backend/src/flowent/routes/__pycache__/prompts.cpython-313.pyc +0 -0
  162. package/backend/src/flowent/routes/__pycache__/providers_route.cpython-313.pyc +0 -0
  163. package/backend/src/flowent/routes/__pycache__/roles.cpython-313.pyc +0 -0
  164. package/backend/src/flowent/routes/__pycache__/settings.cpython-313.pyc +0 -0
  165. package/backend/src/flowent/routes/__pycache__/tabs.cpython-313.pyc +0 -0
  166. package/backend/src/flowent/routes/__pycache__/ws.cpython-313.pyc +0 -0
  167. package/backend/src/flowent/routes/access.py +0 -48
  168. package/backend/src/flowent/routes/assistant.py +0 -158
  169. package/backend/src/flowent/routes/image_assets.py +0 -33
  170. package/backend/src/flowent/routes/meta.py +0 -28
  171. package/backend/src/flowent/routes/nodes.py +0 -423
  172. package/backend/src/flowent/routes/prompts.py +0 -46
  173. package/backend/src/flowent/routes/providers_route.py +0 -365
  174. package/backend/src/flowent/routes/roles.py +0 -207
  175. package/backend/src/flowent/routes/settings.py +0 -379
  176. package/backend/src/flowent/routes/tabs.py +0 -298
  177. package/backend/src/flowent/routes/ws.py +0 -33
  178. package/backend/src/flowent/runtime.py +0 -160
  179. package/backend/src/flowent/security.py +0 -37
  180. package/backend/src/flowent/settings.py +0 -2112
  181. package/backend/src/flowent/settings_management.py +0 -394
  182. package/backend/src/flowent/state_db.py +0 -108
  183. package/backend/src/flowent/static/assets/AssistantPage-BW7XAd9I.js +0 -1
  184. package/backend/src/flowent/static/assets/ChannelsPage-tCJHgt6m.js +0 -1
  185. package/backend/src/flowent/static/assets/PageScaffold-f6g2l7XN.js +0 -1
  186. package/backend/src/flowent/static/assets/PromptsPage-C3Sxn2D7.js +0 -1
  187. package/backend/src/flowent/static/assets/ProvidersPage-BfmdXmNt.js +0 -3
  188. package/backend/src/flowent/static/assets/RolesPage-DET8wO4r.js +0 -1
  189. package/backend/src/flowent/static/assets/SettingsPage-D-g3deMm.js +0 -3
  190. package/backend/src/flowent/static/assets/ToolsPage-CDmtE2g4.js +0 -1
  191. package/backend/src/flowent/static/assets/WorkspacePage-AZsJ0sD0.js +0 -3
  192. package/backend/src/flowent/static/assets/WorkspacePanels-CteCjolX.js +0 -1
  193. package/backend/src/flowent/static/assets/alert-dialog-Duorp_S-.js +0 -1
  194. package/backend/src/flowent/static/assets/dialog-C3ixjGjN.js +0 -1
  195. package/backend/src/flowent/static/assets/elk-worker.min-C9JGDOE-.js +0 -6312
  196. package/backend/src/flowent/static/assets/graph-vendor-CHpVij2M.css +0 -1
  197. package/backend/src/flowent/static/assets/graph-vendor-DRq_-6fV.js +0 -7
  198. package/backend/src/flowent/static/assets/index--o_0fv0N.css +0 -1
  199. package/backend/src/flowent/static/assets/index-C9HuekJm.js +0 -10
  200. package/backend/src/flowent/static/assets/layout.worker-jMHqAFbP.js +0 -24
  201. package/backend/src/flowent/static/assets/markdown-vendor-C9RtvaJh.js +0 -29
  202. package/backend/src/flowent/static/assets/modelParams-DmnF2hwR.js +0 -1
  203. package/backend/src/flowent/static/assets/providerTypes-DT3Ahwl_.js +0 -1
  204. package/backend/src/flowent/static/assets/react-vendor-mEs_JJxa.js +0 -9
  205. package/backend/src/flowent/static/assets/roles-CuRT_chR.js +0 -1
  206. package/backend/src/flowent/static/assets/rolldown-runtime-BYbx6iT9.js +0 -1
  207. package/backend/src/flowent/static/assets/select-DCfeNu-F.js +0 -1
  208. package/backend/src/flowent/static/assets/surface-pWwG5ogx.js +0 -1
  209. package/backend/src/flowent/static/assets/ui-vendor-C5pJa8N7.js +0 -51
  210. package/backend/src/flowent/static/assets/useAppRoute-FgSHBKhV.js +0 -1
  211. package/backend/src/flowent/static/favicon.svg +0 -4
  212. package/backend/src/flowent/tools/__init__.py +0 -176
  213. package/backend/src/flowent/tools/__pycache__/__init__.cpython-313.pyc +0 -0
  214. package/backend/src/flowent/tools/__pycache__/connect.cpython-313.pyc +0 -0
  215. package/backend/src/flowent/tools/__pycache__/contacts.cpython-313.pyc +0 -0
  216. package/backend/src/flowent/tools/__pycache__/create_agent.cpython-313.pyc +0 -0
  217. package/backend/src/flowent/tools/__pycache__/create_tab.cpython-313.pyc +0 -0
  218. package/backend/src/flowent/tools/__pycache__/delete_tab.cpython-313.pyc +0 -0
  219. package/backend/src/flowent/tools/__pycache__/edit.cpython-313.pyc +0 -0
  220. package/backend/src/flowent/tools/__pycache__/exec.cpython-313.pyc +0 -0
  221. package/backend/src/flowent/tools/__pycache__/fetch.cpython-313.pyc +0 -0
  222. package/backend/src/flowent/tools/__pycache__/idle.cpython-313.pyc +0 -0
  223. package/backend/src/flowent/tools/__pycache__/list_roles.cpython-313.pyc +0 -0
  224. package/backend/src/flowent/tools/__pycache__/list_tabs.cpython-313.pyc +0 -0
  225. package/backend/src/flowent/tools/__pycache__/list_tools.cpython-313.pyc +0 -0
  226. package/backend/src/flowent/tools/__pycache__/manage_prompts.cpython-313.pyc +0 -0
  227. package/backend/src/flowent/tools/__pycache__/manage_providers.cpython-313.pyc +0 -0
  228. package/backend/src/flowent/tools/__pycache__/manage_roles.cpython-313.pyc +0 -0
  229. package/backend/src/flowent/tools/__pycache__/manage_settings.cpython-313.pyc +0 -0
  230. package/backend/src/flowent/tools/__pycache__/read.cpython-313.pyc +0 -0
  231. package/backend/src/flowent/tools/__pycache__/send.cpython-313.pyc +0 -0
  232. package/backend/src/flowent/tools/__pycache__/set_permissions.cpython-313.pyc +0 -0
  233. package/backend/src/flowent/tools/__pycache__/sleep.cpython-313.pyc +0 -0
  234. package/backend/src/flowent/tools/__pycache__/todo.cpython-313.pyc +0 -0
  235. package/backend/src/flowent/tools/connect.py +0 -100
  236. package/backend/src/flowent/tools/contacts.py +0 -22
  237. package/backend/src/flowent/tools/create_agent.py +0 -191
  238. package/backend/src/flowent/tools/create_tab.py +0 -61
  239. package/backend/src/flowent/tools/delete_tab.py +0 -39
  240. package/backend/src/flowent/tools/edit.py +0 -142
  241. package/backend/src/flowent/tools/exec.py +0 -118
  242. package/backend/src/flowent/tools/fetch.py +0 -85
  243. package/backend/src/flowent/tools/idle.py +0 -27
  244. package/backend/src/flowent/tools/list_roles.py +0 -68
  245. package/backend/src/flowent/tools/list_tabs.py +0 -100
  246. package/backend/src/flowent/tools/list_tools.py +0 -28
  247. package/backend/src/flowent/tools/manage_prompts.py +0 -102
  248. package/backend/src/flowent/tools/manage_providers.py +0 -220
  249. package/backend/src/flowent/tools/manage_roles.py +0 -275
  250. package/backend/src/flowent/tools/manage_settings.py +0 -326
  251. package/backend/src/flowent/tools/read.py +0 -152
  252. package/backend/src/flowent/tools/send.py +0 -68
  253. package/backend/src/flowent/tools/set_permissions.py +0 -99
  254. package/backend/src/flowent/tools/sleep.py +0 -41
  255. package/backend/src/flowent/tools/todo.py +0 -51
  256. package/backend/src/flowent/workspace_store.py +0 -479
  257. package/backend/tests/__init__.py +0 -0
  258. package/backend/tests/__pycache__/__init__.cpython-313.pyc +0 -0
  259. package/backend/tests/__pycache__/conftest.cpython-313-pytest-9.0.3.pyc +0 -0
  260. package/backend/tests/conftest.py +0 -6
  261. package/backend/tests/integration/api/__pycache__/conftest.cpython-313-pytest-9.0.3.pyc +0 -0
  262. package/backend/tests/integration/api/__pycache__/test_access_api.cpython-313-pytest-9.0.3.pyc +0 -0
  263. package/backend/tests/integration/api/__pycache__/test_assistant_api.cpython-313-pytest-9.0.3.pyc +0 -0
  264. package/backend/tests/integration/api/__pycache__/test_frontend_mounting.cpython-313-pytest-9.0.3.pyc +0 -0
  265. package/backend/tests/integration/api/__pycache__/test_meta_api.cpython-313-pytest-9.0.3.pyc +0 -0
  266. package/backend/tests/integration/api/__pycache__/test_nodes_api.cpython-313-pytest-9.0.3.pyc +0 -0
  267. package/backend/tests/integration/api/__pycache__/test_prompts_api.cpython-313-pytest-9.0.3.pyc +0 -0
  268. package/backend/tests/integration/api/__pycache__/test_roles_api.cpython-313-pytest-9.0.3.pyc +0 -0
  269. package/backend/tests/integration/api/__pycache__/test_tabs_api.cpython-313-pytest-9.0.3.pyc +0 -0
  270. package/backend/tests/integration/api/conftest.py +0 -29
  271. package/backend/tests/integration/api/test_access_api.py +0 -182
  272. package/backend/tests/integration/api/test_assistant_api.py +0 -422
  273. package/backend/tests/integration/api/test_frontend_mounting.py +0 -61
  274. package/backend/tests/integration/api/test_meta_api.py +0 -32
  275. package/backend/tests/integration/api/test_nodes_api.py +0 -787
  276. package/backend/tests/integration/api/test_prompts_api.py +0 -47
  277. package/backend/tests/integration/api/test_roles_api.py +0 -228
  278. package/backend/tests/integration/api/test_tabs_api.py +0 -688
  279. package/backend/tests/unit/__pycache__/test_access.cpython-313-pytest-9.0.3.pyc +0 -0
  280. package/backend/tests/unit/__pycache__/test_cli.cpython-313-pytest-9.0.3.pyc +0 -0
  281. package/backend/tests/unit/__pycache__/test_graph_runtime.cpython-313-pytest-9.0.3.pyc +0 -0
  282. package/backend/tests/unit/__pycache__/test_network.cpython-313-pytest-9.0.3.pyc +0 -0
  283. package/backend/tests/unit/__pycache__/test_state_sqlite_storage.cpython-313-pytest-9.0.3.pyc +0 -0
  284. package/backend/tests/unit/__pycache__/test_workspace_store.cpython-313-pytest-9.0.3.pyc +0 -0
  285. package/backend/tests/unit/agent/__pycache__/test_agent_public_api.cpython-313-pytest-9.0.3.pyc +0 -0
  286. package/backend/tests/unit/agent/__pycache__/test_agent_runtime.cpython-313-pytest-9.0.3.pyc +0 -0
  287. package/backend/tests/unit/agent/test_agent_public_api.py +0 -822
  288. package/backend/tests/unit/agent/test_agent_runtime.py +0 -3088
  289. package/backend/tests/unit/channels/__pycache__/test_telegram_channel.cpython-313-pytest-9.0.3.pyc +0 -0
  290. package/backend/tests/unit/channels/test_telegram_channel.py +0 -552
  291. package/backend/tests/unit/logging/__pycache__/test_logging.cpython-313-pytest-9.0.3.pyc +0 -0
  292. package/backend/tests/unit/logging/test_logging.py +0 -132
  293. package/backend/tests/unit/prompts/__pycache__/test_prompts.cpython-313-pytest-9.0.3.pyc +0 -0
  294. package/backend/tests/unit/prompts/test_prompts.py +0 -570
  295. package/backend/tests/unit/providers/__pycache__/test_anthropic_provider.cpython-313-pytest-9.0.3.pyc +0 -0
  296. package/backend/tests/unit/providers/__pycache__/test_errors.cpython-313-pytest-9.0.3.pyc +0 -0
  297. package/backend/tests/unit/providers/__pycache__/test_extract_delta_parts.cpython-313-pytest-9.0.3.pyc +0 -0
  298. package/backend/tests/unit/providers/__pycache__/test_openai_provider.cpython-313-pytest-9.0.3.pyc +0 -0
  299. package/backend/tests/unit/providers/__pycache__/test_openai_responses.cpython-313-pytest-9.0.3.pyc +0 -0
  300. package/backend/tests/unit/providers/__pycache__/test_provider_gateway.cpython-313-pytest-9.0.3.pyc +0 -0
  301. package/backend/tests/unit/providers/__pycache__/test_think_tag_parser.cpython-313-pytest-9.0.3.pyc +0 -0
  302. package/backend/tests/unit/providers/test_anthropic_provider.py +0 -185
  303. package/backend/tests/unit/providers/test_errors.py +0 -68
  304. package/backend/tests/unit/providers/test_extract_delta_parts.py +0 -22
  305. package/backend/tests/unit/providers/test_openai_provider.py +0 -139
  306. package/backend/tests/unit/providers/test_openai_responses.py +0 -402
  307. package/backend/tests/unit/providers/test_provider_gateway.py +0 -359
  308. package/backend/tests/unit/providers/test_think_tag_parser.py +0 -36
  309. package/backend/tests/unit/routes/__pycache__/test_prompts_routes.cpython-313-pytest-9.0.3.pyc +0 -0
  310. package/backend/tests/unit/routes/__pycache__/test_providers_route.cpython-313-pytest-9.0.3.pyc +0 -0
  311. package/backend/tests/unit/routes/__pycache__/test_roles_routes.cpython-313-pytest-9.0.3.pyc +0 -0
  312. package/backend/tests/unit/routes/__pycache__/test_settings_routes.cpython-313-pytest-9.0.3.pyc +0 -0
  313. package/backend/tests/unit/routes/test_prompts_routes.py +0 -82
  314. package/backend/tests/unit/routes/test_providers_route.py +0 -370
  315. package/backend/tests/unit/routes/test_roles_routes.py +0 -539
  316. package/backend/tests/unit/routes/test_settings_routes.py +0 -1123
  317. package/backend/tests/unit/runtime/__pycache__/test_bootstrap_runtime.cpython-313-pytest-9.0.3.pyc +0 -0
  318. package/backend/tests/unit/runtime/test_bootstrap_runtime.py +0 -1002
  319. package/backend/tests/unit/sandbox/__pycache__/test_sandbox_tools.cpython-313-pytest-9.0.3.pyc +0 -0
  320. package/backend/tests/unit/sandbox/test_sandbox_tools.py +0 -78
  321. package/backend/tests/unit/security/__pycache__/test_security.cpython-313-pytest-9.0.3.pyc +0 -0
  322. package/backend/tests/unit/security/test_security.py +0 -124
  323. package/backend/tests/unit/settings/__pycache__/test_settings_roles.cpython-313-pytest-9.0.3.pyc +0 -0
  324. package/backend/tests/unit/settings/test_settings_roles.py +0 -703
  325. package/backend/tests/unit/test_access.py +0 -45
  326. package/backend/tests/unit/test_cli.py +0 -102
  327. package/backend/tests/unit/test_graph_runtime.py +0 -72
  328. package/backend/tests/unit/test_network.py +0 -51
  329. package/backend/tests/unit/test_state_sqlite_storage.py +0 -87
  330. package/backend/tests/unit/test_workspace_store.py +0 -228
  331. package/backend/tests/unit/tools/__pycache__/test_connect_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  332. package/backend/tests/unit/tools/__pycache__/test_create_agent_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  333. package/backend/tests/unit/tools/__pycache__/test_delete_tab_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  334. package/backend/tests/unit/tools/__pycache__/test_edit_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  335. package/backend/tests/unit/tools/__pycache__/test_exec_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  336. package/backend/tests/unit/tools/__pycache__/test_fetch_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  337. package/backend/tests/unit/tools/__pycache__/test_manage_prompts_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  338. package/backend/tests/unit/tools/__pycache__/test_manage_providers_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  339. package/backend/tests/unit/tools/__pycache__/test_manage_roles_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  340. package/backend/tests/unit/tools/__pycache__/test_manage_settings_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  341. package/backend/tests/unit/tools/__pycache__/test_read_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  342. package/backend/tests/unit/tools/__pycache__/test_set_permissions_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  343. package/backend/tests/unit/tools/__pycache__/test_todo_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  344. package/backend/tests/unit/tools/__pycache__/test_tool_registry.cpython-313-pytest-9.0.3.pyc +0 -0
  345. package/backend/tests/unit/tools/test_connect_tool.py +0 -228
  346. package/backend/tests/unit/tools/test_create_agent_tool.py +0 -404
  347. package/backend/tests/unit/tools/test_delete_tab_tool.py +0 -116
  348. package/backend/tests/unit/tools/test_edit_tool.py +0 -115
  349. package/backend/tests/unit/tools/test_exec_tool.py +0 -81
  350. package/backend/tests/unit/tools/test_fetch_tool.py +0 -65
  351. package/backend/tests/unit/tools/test_manage_prompts_tool.py +0 -92
  352. package/backend/tests/unit/tools/test_manage_providers_tool.py +0 -460
  353. package/backend/tests/unit/tools/test_manage_roles_tool.py +0 -411
  354. package/backend/tests/unit/tools/test_manage_settings_tool.py +0 -611
  355. package/backend/tests/unit/tools/test_read_tool.py +0 -33
  356. package/backend/tests/unit/tools/test_set_permissions_tool.py +0 -595
  357. package/backend/tests/unit/tools/test_todo_tool.py +0 -37
  358. package/backend/tests/unit/tools/test_tool_registry.py +0 -199
  359. package/dist/frontend/assets/AssistantPage-BW7XAd9I.js +0 -1
  360. package/dist/frontend/assets/ChannelsPage-tCJHgt6m.js +0 -1
  361. package/dist/frontend/assets/PageScaffold-f6g2l7XN.js +0 -1
  362. package/dist/frontend/assets/PromptsPage-C3Sxn2D7.js +0 -1
  363. package/dist/frontend/assets/ProvidersPage-BfmdXmNt.js +0 -3
  364. package/dist/frontend/assets/RolesPage-DET8wO4r.js +0 -1
  365. package/dist/frontend/assets/SettingsPage-D-g3deMm.js +0 -3
  366. package/dist/frontend/assets/ToolsPage-CDmtE2g4.js +0 -1
  367. package/dist/frontend/assets/WorkspacePage-AZsJ0sD0.js +0 -3
  368. package/dist/frontend/assets/WorkspacePanels-CteCjolX.js +0 -1
  369. package/dist/frontend/assets/alert-dialog-Duorp_S-.js +0 -1
  370. package/dist/frontend/assets/dialog-C3ixjGjN.js +0 -1
  371. package/dist/frontend/assets/elk-worker.min-C9JGDOE-.js +0 -6312
  372. package/dist/frontend/assets/graph-vendor-CHpVij2M.css +0 -1
  373. package/dist/frontend/assets/graph-vendor-DRq_-6fV.js +0 -7
  374. package/dist/frontend/assets/index--o_0fv0N.css +0 -1
  375. package/dist/frontend/assets/index-C9HuekJm.js +0 -10
  376. package/dist/frontend/assets/layout.worker-jMHqAFbP.js +0 -24
  377. package/dist/frontend/assets/markdown-vendor-C9RtvaJh.js +0 -29
  378. package/dist/frontend/assets/modelParams-DmnF2hwR.js +0 -1
  379. package/dist/frontend/assets/providerTypes-DT3Ahwl_.js +0 -1
  380. package/dist/frontend/assets/react-vendor-mEs_JJxa.js +0 -9
  381. package/dist/frontend/assets/roles-CuRT_chR.js +0 -1
  382. package/dist/frontend/assets/rolldown-runtime-BYbx6iT9.js +0 -1
  383. package/dist/frontend/assets/select-DCfeNu-F.js +0 -1
  384. package/dist/frontend/assets/surface-pWwG5ogx.js +0 -1
  385. package/dist/frontend/assets/ui-vendor-C5pJa8N7.js +0 -51
  386. package/dist/frontend/assets/useAppRoute-FgSHBKhV.js +0 -1
  387. package/dist/frontend/favicon.svg +0 -4
@@ -1,45 +0,0 @@
1
- from loguru import logger
2
-
3
- from flowent.access import (
4
- ensure_access_bootstrap,
5
- is_access_configured,
6
- set_access_code,
7
- )
8
- from flowent.settings import Settings
9
-
10
-
11
- def test_ensure_access_bootstrap_generates_and_logs_access_code() -> None:
12
- settings = Settings()
13
- messages: list[str] = []
14
- sink_id = logger.add(messages.append, format="{message}")
15
-
16
- try:
17
- generated_code = ensure_access_bootstrap(settings)
18
- finally:
19
- logger.remove(sink_id)
20
-
21
- assert generated_code
22
- assert settings.access.code == generated_code
23
- assert is_access_configured(settings.access)
24
- assert any(
25
- f"Flowent admin access code: {generated_code}" in message
26
- for message in messages
27
- )
28
-
29
-
30
- def test_ensure_access_bootstrap_logs_existing_persisted_access_code() -> None:
31
- settings = Settings()
32
- set_access_code(settings, "TEST-ACCESS-CODE")
33
- messages: list[str] = []
34
- sink_id = logger.add(messages.append, format="{message}")
35
-
36
- try:
37
- generated_code = ensure_access_bootstrap(settings)
38
- finally:
39
- logger.remove(sink_id)
40
-
41
- assert generated_code is None
42
- assert settings.access.code == "TEST-ACCESS-CODE"
43
- assert any(
44
- "Flowent admin access code: TEST-ACCESS-CODE" in message for message in messages
45
- )
@@ -1,102 +0,0 @@
1
- import os
2
-
3
- import pytest
4
-
5
- from flowent.access import is_access_configured, set_access_code, verify_access_code
6
- from flowent.cli import APP_DATA_DIR_ENV_VAR, main
7
-
8
-
9
- def test_access_refresh_command_generates_new_persisted_access_code(
10
- monkeypatch, tmp_path, capsys
11
- ):
12
- import flowent.settings as settings_module
13
-
14
- settings_file = tmp_path / "settings.json"
15
- monkeypatch.setattr(settings_module, "_SETTINGS_FILE", settings_file)
16
- monkeypatch.setattr(settings_module, "_cached_settings", None)
17
-
18
- settings = settings_module.Settings()
19
- set_access_code(settings, "OLD-ACCESS-CODE")
20
- settings_module.save_settings(settings)
21
- monkeypatch.setattr(settings_module, "_cached_settings", None)
22
-
23
- main(["access", "refresh"])
24
-
25
- output = capsys.readouterr().out.strip()
26
- reloaded_settings = settings_module.load_settings()
27
-
28
- assert output.startswith("Generated new access code: ")
29
- next_code = output.removeprefix("Generated new access code: ").strip()
30
- assert next_code
31
- assert reloaded_settings.access.code == next_code
32
- assert verify_access_code(reloaded_settings.access, next_code)
33
- assert not verify_access_code(reloaded_settings.access, "OLD-ACCESS-CODE")
34
-
35
-
36
- def test_access_reset_command_clears_persisted_access_code(
37
- monkeypatch, tmp_path, capsys
38
- ):
39
- import flowent.settings as settings_module
40
-
41
- settings_file = tmp_path / "settings.json"
42
- monkeypatch.setattr(settings_module, "_SETTINGS_FILE", settings_file)
43
- monkeypatch.setattr(settings_module, "_cached_settings", None)
44
-
45
- settings = settings_module.Settings()
46
- set_access_code(settings, "TEST-ACCESS-CODE")
47
- settings_module.save_settings(settings)
48
- monkeypatch.setattr(settings_module, "_cached_settings", None)
49
-
50
- main(["access", "reset"])
51
-
52
- output = capsys.readouterr().out.strip()
53
- reloaded_settings = settings_module.load_settings()
54
-
55
- assert output == (
56
- "Access configuration cleared. Restart Flowent to generate a new access code."
57
- )
58
- assert reloaded_settings.access.code == ""
59
- assert not is_access_configured(reloaded_settings.access)
60
-
61
-
62
- def test_version_short_option_matches_version_output(capsys):
63
- with pytest.raises(SystemExit) as exc:
64
- main(["-v"])
65
-
66
- assert exc.value.code == 0
67
- assert capsys.readouterr().out.startswith("flowent ")
68
-
69
-
70
- def test_server_options_accept_npm_wrapper_aliases(monkeypatch):
71
- called: dict[str, object] = {}
72
-
73
- monkeypatch.setattr(
74
- "uvicorn.run",
75
- lambda app, *, host, port: called.update(
76
- {"app": app, "host": host, "port": port}
77
- ),
78
- )
79
-
80
- main(["--hostname", "127.0.0.1", "-p", "7000"])
81
-
82
- assert called == {
83
- "app": "flowent.main:app",
84
- "host": "127.0.0.1",
85
- "port": 7000,
86
- }
87
-
88
-
89
- def test_cli_sets_app_data_dir_env_before_dispatch(monkeypatch, tmp_path, capsys):
90
- monkeypatch.delenv(APP_DATA_DIR_ENV_VAR, raising=False)
91
- called: list[str] = []
92
-
93
- monkeypatch.setattr(
94
- "flowent.access.refresh_local_access",
95
- lambda: called.append("refresh") or "Generated new access code: TEST",
96
- )
97
-
98
- main(["--app-data-dir", str(tmp_path), "access", "refresh"])
99
-
100
- assert called == ["refresh"]
101
- assert os.environ[APP_DATA_DIR_ENV_VAR] == str(tmp_path)
102
- assert capsys.readouterr().out.strip() == "Generated new access code: TEST"
@@ -1,72 +0,0 @@
1
- from flowent.agent import Agent
2
- from flowent.graph_runtime import resolve_node_ref
3
- from flowent.models import NodeConfig, NodeType
4
- from flowent.registry import registry
5
-
6
-
7
- def setup_function():
8
- registry.reset()
9
-
10
-
11
- def teardown_function():
12
- registry.reset()
13
-
14
-
15
- def test_resolve_node_ref_matches_exact_uuid():
16
- planner = Agent(
17
- NodeConfig(node_type=NodeType.AGENT),
18
- uuid="12345678-aaaa-bbbb-cccc-ddddeeeeffff",
19
- )
20
- registry.register(planner)
21
-
22
- assert resolve_node_ref("12345678-aaaa-bbbb-cccc-ddddeeeeffff") is planner
23
-
24
-
25
- def test_resolve_node_ref_matches_exact_name():
26
- planner = Agent(
27
- NodeConfig(node_type=NodeType.AGENT, name="Planner"),
28
- uuid="12345678-aaaa-bbbb-cccc-ddddeeeeffff",
29
- )
30
- registry.register(planner)
31
-
32
- assert resolve_node_ref("Planner") is planner
33
-
34
-
35
- def test_resolve_node_ref_matches_short_uuid_prefix():
36
- planner = Agent(
37
- NodeConfig(node_type=NodeType.AGENT),
38
- uuid="12345678-aaaa-bbbb-cccc-ddddeeeeffff",
39
- )
40
- reviewer = Agent(
41
- NodeConfig(node_type=NodeType.AGENT),
42
- uuid="87654321-aaaa-bbbb-cccc-ddddeeeeffff",
43
- )
44
- registry.register(planner)
45
- registry.register(reviewer)
46
-
47
- assert resolve_node_ref("12345678") is planner
48
-
49
-
50
- def test_resolve_node_ref_rejects_ambiguous_prefix():
51
- planner = Agent(
52
- NodeConfig(node_type=NodeType.AGENT),
53
- uuid="1234aaaa-aaaa-bbbb-cccc-ddddeeeeffff",
54
- )
55
- reviewer = Agent(
56
- NodeConfig(node_type=NodeType.AGENT),
57
- uuid="1234bbbb-aaaa-bbbb-cccc-ddddeeeeffff",
58
- )
59
- registry.register(planner)
60
- registry.register(reviewer)
61
-
62
- assert resolve_node_ref("1234") is None
63
-
64
-
65
- def test_resolve_node_ref_rejects_too_short_prefix():
66
- planner = Agent(
67
- NodeConfig(node_type=NodeType.AGENT),
68
- uuid="12345678-aaaa-bbbb-cccc-ddddeeeeffff",
69
- )
70
- registry.register(planner)
71
-
72
- assert resolve_node_ref("123") is None
@@ -1,51 +0,0 @@
1
- import socket
2
- import threading
3
- import time
4
-
5
- from flowent.network import create_http_session
6
-
7
-
8
- def _capture_raw_request() -> str:
9
- captured: dict[str, str] = {}
10
- ready = threading.Event()
11
-
12
- def serve() -> None:
13
- with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server:
14
- server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
15
- server.bind(("127.0.0.1", 18084))
16
- server.listen(1)
17
- ready.set()
18
- connection, _ = server.accept()
19
- with connection:
20
- payload = b""
21
- connection.settimeout(2)
22
- while b"\r\n\r\n" not in payload:
23
- chunk = connection.recv(4096)
24
- if not chunk:
25
- break
26
- payload += chunk
27
- captured["request"] = payload.decode("latin1", errors="replace")
28
- body = b"{}"
29
- connection.sendall(
30
- b"HTTP/1.1 200 OK\r\n"
31
- b"Content-Type: application/json\r\n"
32
- b"Content-Length: 2\r\n"
33
- b"Connection: close\r\n\r\n" + body
34
- )
35
-
36
- server_thread = threading.Thread(target=serve, daemon=True)
37
- server_thread.start()
38
- ready.wait()
39
- time.sleep(0.05)
40
-
41
- with create_http_session(timeout=5) as client:
42
- response = client.post("http://127.0.0.1:18084/v1/messages", json={"x": 1})
43
- assert response.status_code == 200
44
- return captured["request"]
45
-
46
-
47
- def test_create_http_session_does_not_send_upgrade_by_default():
48
- request = _capture_raw_request()
49
-
50
- assert "Upgrade: h2c" not in request
51
- assert "Connection: Upgrade" not in request
@@ -1,87 +0,0 @@
1
- import base64
2
- import sqlite3
3
-
4
- import flowent.settings as settings_module
5
- from flowent.image_assets import create_image_asset
6
-
7
- _ONE_PIXEL_PNG = base64.b64decode(
8
- "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+aF9sAAAAASUVORK5CYII="
9
- )
10
-
11
-
12
- def test_create_image_asset_persists_metadata_in_state_sqlite(monkeypatch, tmp_path):
13
- settings_file = tmp_path / "settings.json"
14
- settings_file.write_text("{}", encoding="utf-8")
15
- monkeypatch.setattr(settings_module, "_SETTINGS_FILE", settings_file)
16
- monkeypatch.setattr(settings_module, "_cached_settings", None)
17
-
18
- asset = create_image_asset(
19
- _ONE_PIXEL_PNG,
20
- mime_type="image/png",
21
- original_name="pixel.png",
22
- )
23
-
24
- assert asset.file_path == tmp_path / "assets" / "images" / asset.stored_name
25
- assert asset.file_path.is_file()
26
- connection = sqlite3.connect(tmp_path / "state.sqlite")
27
- connection.row_factory = sqlite3.Row
28
- try:
29
- row = connection.execute(
30
- """
31
- SELECT stored_name, mime_type, width, height, original_name
32
- FROM image_assets
33
- WHERE id = ?
34
- """,
35
- (asset.id,),
36
- ).fetchone()
37
- finally:
38
- connection.close()
39
- assert row is not None
40
- assert row["stored_name"] == asset.stored_name
41
- assert row["mime_type"] == "image/png"
42
- assert row["width"] == 1
43
- assert row["height"] == 1
44
- assert row["original_name"] == "pixel.png"
45
-
46
-
47
- def test_state_schema_removes_retired_connection_tables(monkeypatch, tmp_path):
48
- settings_file = tmp_path / "settings.json"
49
- settings_file.write_text("{}", encoding="utf-8")
50
- monkeypatch.setattr(settings_module, "_SETTINGS_FILE", settings_file)
51
- monkeypatch.setattr(settings_module, "_cached_settings", None)
52
-
53
- db_path = tmp_path / "state.sqlite"
54
- connection = sqlite3.connect(db_path)
55
- try:
56
- connection.executescript(
57
- """
58
- CREATE TABLE mcp_snapshots (id TEXT PRIMARY KEY);
59
- CREATE TABLE mcp_activities (id TEXT PRIMARY KEY);
60
- """
61
- )
62
- finally:
63
- connection.close()
64
-
65
- create_image_asset(
66
- _ONE_PIXEL_PNG,
67
- mime_type="image/png",
68
- original_name="pixel.png",
69
- )
70
-
71
- connection = sqlite3.connect(db_path)
72
- try:
73
- existing_tables = {
74
- row[0]
75
- for row in connection.execute(
76
- """
77
- SELECT name
78
- FROM sqlite_master
79
- WHERE type = 'table'
80
- """
81
- ).fetchall()
82
- }
83
- finally:
84
- connection.close()
85
-
86
- assert "mcp_snapshots" not in existing_tables
87
- assert "mcp_activities" not in existing_tables
@@ -1,228 +0,0 @@
1
- import json
2
- import sqlite3
3
-
4
- from flowent.settings import Settings
5
- from flowent.state_db import open_state_db
6
- from flowent.workspace_store import workspace_store
7
-
8
-
9
- def test_workspace_store_normalizes_relative_write_dirs_on_load(
10
- monkeypatch,
11
- tmp_path,
12
- ):
13
- import flowent.settings as settings_module
14
-
15
- settings_file = tmp_path / "settings.json"
16
- workspace_file = tmp_path / "workspace.json"
17
- working_dir = tmp_path / "workspace-root"
18
- working_dir.mkdir()
19
- workspace_file.write_text(
20
- json.dumps(
21
- {
22
- "tabs": [],
23
- "nodes": [
24
- {
25
- "id": "node-1",
26
- "config": {
27
- "node_type": "agent",
28
- "role_name": "Worker",
29
- "tab_id": "tab-1",
30
- "name": "Worker",
31
- "tools": ["read"],
32
- "write_dirs": ["./out"],
33
- "allow_network": False,
34
- },
35
- "state": "idle",
36
- "todos": [],
37
- "history": [],
38
- }
39
- ],
40
- "edges": [],
41
- }
42
- ),
43
- encoding="utf-8",
44
- )
45
-
46
- monkeypatch.setattr(settings_module, "_SETTINGS_FILE", settings_file)
47
- monkeypatch.setattr(
48
- settings_module,
49
- "get_settings",
50
- lambda: Settings(working_dir=str(working_dir)),
51
- )
52
- workspace_store.reset_cache()
53
-
54
- record = workspace_store.get_node_record("node-1")
55
-
56
- assert record is not None
57
- assert record.config.write_dirs == [str((working_dir / "out").resolve())]
58
- connection = open_state_db(create=False)
59
- assert connection is not None
60
- try:
61
- row = connection.execute(
62
- "SELECT payload FROM nodes WHERE id = ?",
63
- ("node-1",),
64
- ).fetchone()
65
- finally:
66
- connection.close()
67
- assert row is not None
68
- persisted = json.loads(row["payload"])
69
- assert persisted["config"]["write_dirs"] == [str((working_dir / "out").resolve())]
70
- workspace_store.reset_cache()
71
-
72
-
73
- def test_workspace_store_prefers_legacy_workspace_data_when_state_db_is_still_empty(
74
- monkeypatch,
75
- tmp_path,
76
- ):
77
- import flowent.settings as settings_module
78
-
79
- settings_file = tmp_path / "settings.json"
80
- workspace_file = tmp_path / "workspace.json"
81
- state_db_file = tmp_path / "state.sqlite"
82
- settings_file.write_text("{}", encoding="utf-8")
83
- workspace_file.write_text(
84
- json.dumps(
85
- {
86
- "tabs": [],
87
- "nodes": [
88
- {
89
- "id": "node-legacy",
90
- "config": {
91
- "node_type": "agent",
92
- "role_name": "Worker",
93
- "tab_id": "tab-1",
94
- "name": "Worker",
95
- "tools": ["read"],
96
- "write_dirs": [],
97
- "allow_network": False,
98
- },
99
- "state": "idle",
100
- "todos": [],
101
- "history": [],
102
- }
103
- ],
104
- "edges": [],
105
- }
106
- ),
107
- encoding="utf-8",
108
- )
109
- sqlite3.connect(state_db_file).close()
110
-
111
- monkeypatch.setattr(settings_module, "_SETTINGS_FILE", settings_file)
112
- monkeypatch.setattr(settings_module, "_cached_settings", None)
113
- monkeypatch.setattr(
114
- settings_module,
115
- "get_settings",
116
- lambda: Settings(working_dir=str(tmp_path)),
117
- )
118
- workspace_store.reset_cache()
119
-
120
- record = workspace_store.get_node_record("node-legacy")
121
-
122
- assert record is not None
123
- assert record.id == "node-legacy"
124
- workspace_store.reset_cache()
125
-
126
-
127
- def test_workspace_store_does_not_overwrite_state_db_with_legacy_workspace_data(
128
- monkeypatch,
129
- tmp_path,
130
- ):
131
- import flowent.settings as settings_module
132
-
133
- settings_file = tmp_path / "settings.json"
134
- workspace_file = tmp_path / "workspace.json"
135
- settings_file.write_text("{}", encoding="utf-8")
136
- workspace_file.write_text(
137
- json.dumps(
138
- {
139
- "tabs": [],
140
- "nodes": [
141
- {
142
- "id": "node-legacy",
143
- "config": {
144
- "node_type": "agent",
145
- "role_name": "Worker",
146
- "tab_id": "tab-1",
147
- "name": "Legacy",
148
- "tools": ["read"],
149
- "write_dirs": [],
150
- "allow_network": False,
151
- },
152
- "state": "idle",
153
- "todos": [],
154
- "history": [],
155
- }
156
- ],
157
- "edges": [],
158
- }
159
- ),
160
- encoding="utf-8",
161
- )
162
-
163
- monkeypatch.setattr(settings_module, "_SETTINGS_FILE", settings_file)
164
- monkeypatch.setattr(settings_module, "_cached_settings", None)
165
- monkeypatch.setattr(
166
- settings_module,
167
- "get_settings",
168
- lambda: Settings(working_dir=str(tmp_path)),
169
- )
170
- connection = open_state_db(create=True)
171
- assert connection is not None
172
- try:
173
- with connection:
174
- connection.execute(
175
- """
176
- INSERT INTO nodes (id, payload, tab_id, node_type, updated_at)
177
- VALUES (?, ?, ?, ?, ?)
178
- """,
179
- (
180
- "node-sqlite",
181
- json.dumps(
182
- {
183
- "id": "node-sqlite",
184
- "config": {
185
- "node_type": "agent",
186
- "role_name": "Worker",
187
- "tab_id": "tab-1",
188
- "name": "SQLite",
189
- "tools": ["read"],
190
- "write_dirs": [],
191
- "allow_network": False,
192
- },
193
- "state": "idle",
194
- "todos": [],
195
- "history": [],
196
- }
197
- ),
198
- "tab-1",
199
- "agent",
200
- 1.0,
201
- ),
202
- )
203
- finally:
204
- connection.close()
205
-
206
- workspace_store.reset_cache()
207
-
208
- sqlite_record = workspace_store.get_node_record("node-sqlite")
209
- legacy_record = workspace_store.get_node_record("node-legacy")
210
-
211
- assert sqlite_record is not None
212
- assert legacy_record is None
213
- connection = open_state_db(create=False)
214
- assert connection is not None
215
- try:
216
- sqlite_row = connection.execute(
217
- "SELECT id FROM nodes WHERE id = ?",
218
- ("node-sqlite",),
219
- ).fetchone()
220
- legacy_row = connection.execute(
221
- "SELECT id FROM nodes WHERE id = ?",
222
- ("node-legacy",),
223
- ).fetchone()
224
- finally:
225
- connection.close()
226
- assert sqlite_row is not None
227
- assert legacy_row is None
228
- workspace_store.reset_cache()