flowent 0.0.7 → 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 (386) 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/__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 +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 +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__/model_metadata.cpython-313.pyc +0 -0
  64. package/backend/src/flowent/__pycache__/network.cpython-313.pyc +0 -0
  65. package/backend/src/flowent/__pycache__/observability_service.cpython-313.pyc +0 -0
  66. package/backend/src/flowent/__pycache__/registry.cpython-313.pyc +0 -0
  67. package/backend/src/flowent/__pycache__/role_management.cpython-313.pyc +0 -0
  68. package/backend/src/flowent/__pycache__/runtime.cpython-313.pyc +0 -0
  69. package/backend/src/flowent/__pycache__/security.cpython-313.pyc +0 -0
  70. package/backend/src/flowent/__pycache__/settings.cpython-313.pyc +0 -0
  71. package/backend/src/flowent/__pycache__/settings_management.cpython-313.pyc +0 -0
  72. package/backend/src/flowent/__pycache__/state_db.cpython-313.pyc +0 -0
  73. package/backend/src/flowent/__pycache__/workspace_store.cpython-313.pyc +0 -0
  74. package/backend/src/flowent/access.py +0 -247
  75. package/backend/src/flowent/assistant_commands.py +0 -115
  76. package/backend/src/flowent/channels/__init__.py +0 -3
  77. package/backend/src/flowent/channels/__pycache__/__init__.cpython-313.pyc +0 -0
  78. package/backend/src/flowent/channels/__pycache__/telegram.cpython-313.pyc +0 -0
  79. package/backend/src/flowent/channels/telegram.py +0 -615
  80. package/backend/src/flowent/config.py +0 -14
  81. package/backend/src/flowent/dev.py +0 -3
  82. package/backend/src/flowent/events.py +0 -157
  83. package/backend/src/flowent/graph_runtime.py +0 -60
  84. package/backend/src/flowent/graph_service.py +0 -2401
  85. package/backend/src/flowent/image_assets.py +0 -356
  86. package/backend/src/flowent/model_metadata.py +0 -102
  87. package/backend/src/flowent/models/__init__.py +0 -125
  88. package/backend/src/flowent/models/__pycache__/__init__.cpython-313.pyc +0 -0
  89. package/backend/src/flowent/models/__pycache__/agent.cpython-313.pyc +0 -0
  90. package/backend/src/flowent/models/__pycache__/base.cpython-313.pyc +0 -0
  91. package/backend/src/flowent/models/__pycache__/blueprint.cpython-313.pyc +0 -0
  92. package/backend/src/flowent/models/__pycache__/content.cpython-313.pyc +0 -0
  93. package/backend/src/flowent/models/__pycache__/delta.cpython-313.pyc +0 -0
  94. package/backend/src/flowent/models/__pycache__/event.cpython-313.pyc +0 -0
  95. package/backend/src/flowent/models/__pycache__/graph.cpython-313.pyc +0 -0
  96. package/backend/src/flowent/models/__pycache__/history.cpython-313.pyc +0 -0
  97. package/backend/src/flowent/models/__pycache__/llm.cpython-313.pyc +0 -0
  98. package/backend/src/flowent/models/__pycache__/message.cpython-313.pyc +0 -0
  99. package/backend/src/flowent/models/__pycache__/tab.cpython-313.pyc +0 -0
  100. package/backend/src/flowent/models/__pycache__/todo.cpython-313.pyc +0 -0
  101. package/backend/src/flowent/models/agent.py +0 -34
  102. package/backend/src/flowent/models/base.py +0 -24
  103. package/backend/src/flowent/models/blueprint.py +0 -176
  104. package/backend/src/flowent/models/content.py +0 -164
  105. package/backend/src/flowent/models/delta.py +0 -44
  106. package/backend/src/flowent/models/event.py +0 -51
  107. package/backend/src/flowent/models/graph.py +0 -472
  108. package/backend/src/flowent/models/history.py +0 -272
  109. package/backend/src/flowent/models/llm.py +0 -62
  110. package/backend/src/flowent/models/message.py +0 -33
  111. package/backend/src/flowent/models/tab.py +0 -85
  112. package/backend/src/flowent/models/todo.py +0 -10
  113. package/backend/src/flowent/network.py +0 -146
  114. package/backend/src/flowent/observability_service.py +0 -218
  115. package/backend/src/flowent/prompts/__init__.py +0 -67
  116. package/backend/src/flowent/prompts/__pycache__/__init__.cpython-313.pyc +0 -0
  117. package/backend/src/flowent/prompts/__pycache__/common.cpython-313.pyc +0 -0
  118. package/backend/src/flowent/prompts/__pycache__/steward.cpython-313.pyc +0 -0
  119. package/backend/src/flowent/prompts/common.py +0 -250
  120. package/backend/src/flowent/prompts/steward.py +0 -64
  121. package/backend/src/flowent/providers/__init__.py +0 -23
  122. package/backend/src/flowent/providers/__pycache__/__init__.cpython-313.pyc +0 -0
  123. package/backend/src/flowent/providers/__pycache__/anthropic.cpython-313.pyc +0 -0
  124. package/backend/src/flowent/providers/__pycache__/base_url.cpython-313.pyc +0 -0
  125. package/backend/src/flowent/providers/__pycache__/configuration.cpython-313.pyc +0 -0
  126. package/backend/src/flowent/providers/__pycache__/content.cpython-313.pyc +0 -0
  127. package/backend/src/flowent/providers/__pycache__/errors.cpython-313.pyc +0 -0
  128. package/backend/src/flowent/providers/__pycache__/gateway.cpython-313.pyc +0 -0
  129. package/backend/src/flowent/providers/__pycache__/headers.cpython-313.pyc +0 -0
  130. package/backend/src/flowent/providers/__pycache__/management.cpython-313.pyc +0 -0
  131. package/backend/src/flowent/providers/__pycache__/openai.cpython-313.pyc +0 -0
  132. package/backend/src/flowent/providers/__pycache__/openai_responses.cpython-313.pyc +0 -0
  133. package/backend/src/flowent/providers/__pycache__/registry.cpython-313.pyc +0 -0
  134. package/backend/src/flowent/providers/__pycache__/sse.cpython-313.pyc +0 -0
  135. package/backend/src/flowent/providers/__pycache__/thinking.cpython-313.pyc +0 -0
  136. package/backend/src/flowent/providers/anthropic.py +0 -468
  137. package/backend/src/flowent/providers/base_url.py +0 -60
  138. package/backend/src/flowent/providers/configuration.py +0 -189
  139. package/backend/src/flowent/providers/content.py +0 -122
  140. package/backend/src/flowent/providers/errors.py +0 -223
  141. package/backend/src/flowent/providers/gateway.py +0 -169
  142. package/backend/src/flowent/providers/gemini.py +0 -447
  143. package/backend/src/flowent/providers/headers.py +0 -20
  144. package/backend/src/flowent/providers/management.py +0 -96
  145. package/backend/src/flowent/providers/ollama.py +0 -293
  146. package/backend/src/flowent/providers/openai.py +0 -422
  147. package/backend/src/flowent/providers/openai_responses.py +0 -655
  148. package/backend/src/flowent/providers/registry.py +0 -144
  149. package/backend/src/flowent/providers/sse.py +0 -31
  150. package/backend/src/flowent/providers/thinking.py +0 -79
  151. package/backend/src/flowent/registry.py +0 -73
  152. package/backend/src/flowent/role_management.py +0 -270
  153. package/backend/src/flowent/routes/__init__.py +0 -26
  154. package/backend/src/flowent/routes/__pycache__/__init__.cpython-313.pyc +0 -0
  155. package/backend/src/flowent/routes/__pycache__/access.cpython-313.pyc +0 -0
  156. package/backend/src/flowent/routes/__pycache__/assistant.cpython-313.pyc +0 -0
  157. package/backend/src/flowent/routes/__pycache__/image_assets.cpython-313.pyc +0 -0
  158. package/backend/src/flowent/routes/__pycache__/meta.cpython-313.pyc +0 -0
  159. package/backend/src/flowent/routes/__pycache__/nodes.cpython-313.pyc +0 -0
  160. package/backend/src/flowent/routes/__pycache__/prompts.cpython-313.pyc +0 -0
  161. package/backend/src/flowent/routes/__pycache__/providers_route.cpython-313.pyc +0 -0
  162. package/backend/src/flowent/routes/__pycache__/roles.cpython-313.pyc +0 -0
  163. package/backend/src/flowent/routes/__pycache__/settings.cpython-313.pyc +0 -0
  164. package/backend/src/flowent/routes/__pycache__/tabs.cpython-313.pyc +0 -0
  165. package/backend/src/flowent/routes/__pycache__/ws.cpython-313.pyc +0 -0
  166. package/backend/src/flowent/routes/access.py +0 -48
  167. package/backend/src/flowent/routes/assistant.py +0 -158
  168. package/backend/src/flowent/routes/image_assets.py +0 -33
  169. package/backend/src/flowent/routes/meta.py +0 -28
  170. package/backend/src/flowent/routes/nodes.py +0 -423
  171. package/backend/src/flowent/routes/prompts.py +0 -46
  172. package/backend/src/flowent/routes/providers_route.py +0 -365
  173. package/backend/src/flowent/routes/roles.py +0 -207
  174. package/backend/src/flowent/routes/settings.py +0 -379
  175. package/backend/src/flowent/routes/tabs.py +0 -298
  176. package/backend/src/flowent/routes/ws.py +0 -33
  177. package/backend/src/flowent/runtime.py +0 -160
  178. package/backend/src/flowent/security.py +0 -37
  179. package/backend/src/flowent/settings.py +0 -2112
  180. package/backend/src/flowent/settings_management.py +0 -394
  181. package/backend/src/flowent/state_db.py +0 -108
  182. package/backend/src/flowent/static/assets/AssistantPage-BW7XAd9I.js +0 -1
  183. package/backend/src/flowent/static/assets/ChannelsPage-tCJHgt6m.js +0 -1
  184. package/backend/src/flowent/static/assets/PageScaffold-f6g2l7XN.js +0 -1
  185. package/backend/src/flowent/static/assets/PromptsPage-C3Sxn2D7.js +0 -1
  186. package/backend/src/flowent/static/assets/ProvidersPage-BfmdXmNt.js +0 -3
  187. package/backend/src/flowent/static/assets/RolesPage-DET8wO4r.js +0 -1
  188. package/backend/src/flowent/static/assets/SettingsPage-D-g3deMm.js +0 -3
  189. package/backend/src/flowent/static/assets/ToolsPage-CDmtE2g4.js +0 -1
  190. package/backend/src/flowent/static/assets/WorkspacePage-AZsJ0sD0.js +0 -3
  191. package/backend/src/flowent/static/assets/WorkspacePanels-CteCjolX.js +0 -1
  192. package/backend/src/flowent/static/assets/alert-dialog-Duorp_S-.js +0 -1
  193. package/backend/src/flowent/static/assets/dialog-C3ixjGjN.js +0 -1
  194. package/backend/src/flowent/static/assets/elk-worker.min-C9JGDOE-.js +0 -6312
  195. package/backend/src/flowent/static/assets/graph-vendor-CHpVij2M.css +0 -1
  196. package/backend/src/flowent/static/assets/graph-vendor-DRq_-6fV.js +0 -7
  197. package/backend/src/flowent/static/assets/index--o_0fv0N.css +0 -1
  198. package/backend/src/flowent/static/assets/index-C9HuekJm.js +0 -10
  199. package/backend/src/flowent/static/assets/layout.worker-jMHqAFbP.js +0 -24
  200. package/backend/src/flowent/static/assets/markdown-vendor-C9RtvaJh.js +0 -29
  201. package/backend/src/flowent/static/assets/modelParams-DmnF2hwR.js +0 -1
  202. package/backend/src/flowent/static/assets/providerTypes-DT3Ahwl_.js +0 -1
  203. package/backend/src/flowent/static/assets/react-vendor-mEs_JJxa.js +0 -9
  204. package/backend/src/flowent/static/assets/roles-CuRT_chR.js +0 -1
  205. package/backend/src/flowent/static/assets/rolldown-runtime-BYbx6iT9.js +0 -1
  206. package/backend/src/flowent/static/assets/select-DCfeNu-F.js +0 -1
  207. package/backend/src/flowent/static/assets/surface-pWwG5ogx.js +0 -1
  208. package/backend/src/flowent/static/assets/ui-vendor-C5pJa8N7.js +0 -51
  209. package/backend/src/flowent/static/assets/useAppRoute-FgSHBKhV.js +0 -1
  210. package/backend/src/flowent/static/favicon.svg +0 -4
  211. package/backend/src/flowent/tools/__init__.py +0 -176
  212. package/backend/src/flowent/tools/__pycache__/__init__.cpython-313.pyc +0 -0
  213. package/backend/src/flowent/tools/__pycache__/connect.cpython-313.pyc +0 -0
  214. package/backend/src/flowent/tools/__pycache__/contacts.cpython-313.pyc +0 -0
  215. package/backend/src/flowent/tools/__pycache__/create_agent.cpython-313.pyc +0 -0
  216. package/backend/src/flowent/tools/__pycache__/create_tab.cpython-313.pyc +0 -0
  217. package/backend/src/flowent/tools/__pycache__/delete_tab.cpython-313.pyc +0 -0
  218. package/backend/src/flowent/tools/__pycache__/edit.cpython-313.pyc +0 -0
  219. package/backend/src/flowent/tools/__pycache__/exec.cpython-313.pyc +0 -0
  220. package/backend/src/flowent/tools/__pycache__/fetch.cpython-313.pyc +0 -0
  221. package/backend/src/flowent/tools/__pycache__/idle.cpython-313.pyc +0 -0
  222. package/backend/src/flowent/tools/__pycache__/list_roles.cpython-313.pyc +0 -0
  223. package/backend/src/flowent/tools/__pycache__/list_tabs.cpython-313.pyc +0 -0
  224. package/backend/src/flowent/tools/__pycache__/list_tools.cpython-313.pyc +0 -0
  225. package/backend/src/flowent/tools/__pycache__/manage_prompts.cpython-313.pyc +0 -0
  226. package/backend/src/flowent/tools/__pycache__/manage_providers.cpython-313.pyc +0 -0
  227. package/backend/src/flowent/tools/__pycache__/manage_roles.cpython-313.pyc +0 -0
  228. package/backend/src/flowent/tools/__pycache__/manage_settings.cpython-313.pyc +0 -0
  229. package/backend/src/flowent/tools/__pycache__/read.cpython-313.pyc +0 -0
  230. package/backend/src/flowent/tools/__pycache__/send.cpython-313.pyc +0 -0
  231. package/backend/src/flowent/tools/__pycache__/set_permissions.cpython-313.pyc +0 -0
  232. package/backend/src/flowent/tools/__pycache__/sleep.cpython-313.pyc +0 -0
  233. package/backend/src/flowent/tools/__pycache__/todo.cpython-313.pyc +0 -0
  234. package/backend/src/flowent/tools/connect.py +0 -100
  235. package/backend/src/flowent/tools/contacts.py +0 -22
  236. package/backend/src/flowent/tools/create_agent.py +0 -191
  237. package/backend/src/flowent/tools/create_tab.py +0 -61
  238. package/backend/src/flowent/tools/delete_tab.py +0 -39
  239. package/backend/src/flowent/tools/edit.py +0 -142
  240. package/backend/src/flowent/tools/exec.py +0 -118
  241. package/backend/src/flowent/tools/fetch.py +0 -85
  242. package/backend/src/flowent/tools/idle.py +0 -27
  243. package/backend/src/flowent/tools/list_roles.py +0 -68
  244. package/backend/src/flowent/tools/list_tabs.py +0 -100
  245. package/backend/src/flowent/tools/list_tools.py +0 -28
  246. package/backend/src/flowent/tools/manage_prompts.py +0 -102
  247. package/backend/src/flowent/tools/manage_providers.py +0 -220
  248. package/backend/src/flowent/tools/manage_roles.py +0 -275
  249. package/backend/src/flowent/tools/manage_settings.py +0 -326
  250. package/backend/src/flowent/tools/read.py +0 -152
  251. package/backend/src/flowent/tools/send.py +0 -68
  252. package/backend/src/flowent/tools/set_permissions.py +0 -99
  253. package/backend/src/flowent/tools/sleep.py +0 -41
  254. package/backend/src/flowent/tools/todo.py +0 -51
  255. package/backend/src/flowent/workspace_store.py +0 -479
  256. package/backend/tests/__init__.py +0 -0
  257. package/backend/tests/__pycache__/__init__.cpython-313.pyc +0 -0
  258. package/backend/tests/__pycache__/conftest.cpython-313-pytest-9.0.3.pyc +0 -0
  259. package/backend/tests/conftest.py +0 -6
  260. package/backend/tests/integration/api/__pycache__/conftest.cpython-313-pytest-9.0.3.pyc +0 -0
  261. package/backend/tests/integration/api/__pycache__/test_access_api.cpython-313-pytest-9.0.3.pyc +0 -0
  262. package/backend/tests/integration/api/__pycache__/test_assistant_api.cpython-313-pytest-9.0.3.pyc +0 -0
  263. package/backend/tests/integration/api/__pycache__/test_frontend_mounting.cpython-313-pytest-9.0.3.pyc +0 -0
  264. package/backend/tests/integration/api/__pycache__/test_meta_api.cpython-313-pytest-9.0.3.pyc +0 -0
  265. package/backend/tests/integration/api/__pycache__/test_nodes_api.cpython-313-pytest-9.0.3.pyc +0 -0
  266. package/backend/tests/integration/api/__pycache__/test_prompts_api.cpython-313-pytest-9.0.3.pyc +0 -0
  267. package/backend/tests/integration/api/__pycache__/test_roles_api.cpython-313-pytest-9.0.3.pyc +0 -0
  268. package/backend/tests/integration/api/__pycache__/test_tabs_api.cpython-313-pytest-9.0.3.pyc +0 -0
  269. package/backend/tests/integration/api/conftest.py +0 -29
  270. package/backend/tests/integration/api/test_access_api.py +0 -182
  271. package/backend/tests/integration/api/test_assistant_api.py +0 -422
  272. package/backend/tests/integration/api/test_frontend_mounting.py +0 -61
  273. package/backend/tests/integration/api/test_meta_api.py +0 -32
  274. package/backend/tests/integration/api/test_nodes_api.py +0 -787
  275. package/backend/tests/integration/api/test_prompts_api.py +0 -47
  276. package/backend/tests/integration/api/test_roles_api.py +0 -228
  277. package/backend/tests/integration/api/test_tabs_api.py +0 -688
  278. package/backend/tests/unit/__pycache__/test_access.cpython-313-pytest-9.0.3.pyc +0 -0
  279. package/backend/tests/unit/__pycache__/test_cli.cpython-313-pytest-9.0.3.pyc +0 -0
  280. package/backend/tests/unit/__pycache__/test_graph_runtime.cpython-313-pytest-9.0.3.pyc +0 -0
  281. package/backend/tests/unit/__pycache__/test_network.cpython-313-pytest-9.0.3.pyc +0 -0
  282. package/backend/tests/unit/__pycache__/test_state_sqlite_storage.cpython-313-pytest-9.0.3.pyc +0 -0
  283. package/backend/tests/unit/__pycache__/test_workspace_store.cpython-313-pytest-9.0.3.pyc +0 -0
  284. package/backend/tests/unit/agent/__pycache__/test_agent_public_api.cpython-313-pytest-9.0.3.pyc +0 -0
  285. package/backend/tests/unit/agent/__pycache__/test_agent_runtime.cpython-313-pytest-9.0.3.pyc +0 -0
  286. package/backend/tests/unit/agent/test_agent_public_api.py +0 -822
  287. package/backend/tests/unit/agent/test_agent_runtime.py +0 -3088
  288. package/backend/tests/unit/channels/__pycache__/test_telegram_channel.cpython-313-pytest-9.0.3.pyc +0 -0
  289. package/backend/tests/unit/channels/test_telegram_channel.py +0 -552
  290. package/backend/tests/unit/logging/__pycache__/test_logging.cpython-313-pytest-9.0.3.pyc +0 -0
  291. package/backend/tests/unit/logging/test_logging.py +0 -132
  292. package/backend/tests/unit/prompts/__pycache__/test_prompts.cpython-313-pytest-9.0.3.pyc +0 -0
  293. package/backend/tests/unit/prompts/test_prompts.py +0 -570
  294. package/backend/tests/unit/providers/__pycache__/test_anthropic_provider.cpython-313-pytest-9.0.3.pyc +0 -0
  295. package/backend/tests/unit/providers/__pycache__/test_errors.cpython-313-pytest-9.0.3.pyc +0 -0
  296. package/backend/tests/unit/providers/__pycache__/test_extract_delta_parts.cpython-313-pytest-9.0.3.pyc +0 -0
  297. package/backend/tests/unit/providers/__pycache__/test_openai_provider.cpython-313-pytest-9.0.3.pyc +0 -0
  298. package/backend/tests/unit/providers/__pycache__/test_openai_responses.cpython-313-pytest-9.0.3.pyc +0 -0
  299. package/backend/tests/unit/providers/__pycache__/test_provider_gateway.cpython-313-pytest-9.0.3.pyc +0 -0
  300. package/backend/tests/unit/providers/__pycache__/test_think_tag_parser.cpython-313-pytest-9.0.3.pyc +0 -0
  301. package/backend/tests/unit/providers/test_anthropic_provider.py +0 -185
  302. package/backend/tests/unit/providers/test_errors.py +0 -68
  303. package/backend/tests/unit/providers/test_extract_delta_parts.py +0 -22
  304. package/backend/tests/unit/providers/test_openai_provider.py +0 -139
  305. package/backend/tests/unit/providers/test_openai_responses.py +0 -402
  306. package/backend/tests/unit/providers/test_provider_gateway.py +0 -359
  307. package/backend/tests/unit/providers/test_think_tag_parser.py +0 -36
  308. package/backend/tests/unit/routes/__pycache__/test_prompts_routes.cpython-313-pytest-9.0.3.pyc +0 -0
  309. package/backend/tests/unit/routes/__pycache__/test_providers_route.cpython-313-pytest-9.0.3.pyc +0 -0
  310. package/backend/tests/unit/routes/__pycache__/test_roles_routes.cpython-313-pytest-9.0.3.pyc +0 -0
  311. package/backend/tests/unit/routes/__pycache__/test_settings_routes.cpython-313-pytest-9.0.3.pyc +0 -0
  312. package/backend/tests/unit/routes/test_prompts_routes.py +0 -82
  313. package/backend/tests/unit/routes/test_providers_route.py +0 -370
  314. package/backend/tests/unit/routes/test_roles_routes.py +0 -539
  315. package/backend/tests/unit/routes/test_settings_routes.py +0 -1123
  316. package/backend/tests/unit/runtime/__pycache__/test_bootstrap_runtime.cpython-313-pytest-9.0.3.pyc +0 -0
  317. package/backend/tests/unit/runtime/test_bootstrap_runtime.py +0 -1002
  318. package/backend/tests/unit/sandbox/__pycache__/test_sandbox_tools.cpython-313-pytest-9.0.3.pyc +0 -0
  319. package/backend/tests/unit/sandbox/test_sandbox_tools.py +0 -78
  320. package/backend/tests/unit/security/__pycache__/test_security.cpython-313-pytest-9.0.3.pyc +0 -0
  321. package/backend/tests/unit/security/test_security.py +0 -124
  322. package/backend/tests/unit/settings/__pycache__/test_settings_roles.cpython-313-pytest-9.0.3.pyc +0 -0
  323. package/backend/tests/unit/settings/test_settings_roles.py +0 -703
  324. package/backend/tests/unit/test_access.py +0 -45
  325. package/backend/tests/unit/test_cli.py +0 -102
  326. package/backend/tests/unit/test_graph_runtime.py +0 -72
  327. package/backend/tests/unit/test_network.py +0 -51
  328. package/backend/tests/unit/test_state_sqlite_storage.py +0 -87
  329. package/backend/tests/unit/test_workspace_store.py +0 -228
  330. package/backend/tests/unit/tools/__pycache__/test_connect_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  331. package/backend/tests/unit/tools/__pycache__/test_create_agent_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  332. package/backend/tests/unit/tools/__pycache__/test_delete_tab_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  333. package/backend/tests/unit/tools/__pycache__/test_edit_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  334. package/backend/tests/unit/tools/__pycache__/test_exec_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  335. package/backend/tests/unit/tools/__pycache__/test_fetch_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  336. package/backend/tests/unit/tools/__pycache__/test_manage_prompts_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  337. package/backend/tests/unit/tools/__pycache__/test_manage_providers_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  338. package/backend/tests/unit/tools/__pycache__/test_manage_roles_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  339. package/backend/tests/unit/tools/__pycache__/test_manage_settings_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  340. package/backend/tests/unit/tools/__pycache__/test_read_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  341. package/backend/tests/unit/tools/__pycache__/test_set_permissions_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  342. package/backend/tests/unit/tools/__pycache__/test_todo_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  343. package/backend/tests/unit/tools/__pycache__/test_tool_registry.cpython-313-pytest-9.0.3.pyc +0 -0
  344. package/backend/tests/unit/tools/test_connect_tool.py +0 -228
  345. package/backend/tests/unit/tools/test_create_agent_tool.py +0 -404
  346. package/backend/tests/unit/tools/test_delete_tab_tool.py +0 -116
  347. package/backend/tests/unit/tools/test_edit_tool.py +0 -115
  348. package/backend/tests/unit/tools/test_exec_tool.py +0 -81
  349. package/backend/tests/unit/tools/test_fetch_tool.py +0 -65
  350. package/backend/tests/unit/tools/test_manage_prompts_tool.py +0 -92
  351. package/backend/tests/unit/tools/test_manage_providers_tool.py +0 -460
  352. package/backend/tests/unit/tools/test_manage_roles_tool.py +0 -411
  353. package/backend/tests/unit/tools/test_manage_settings_tool.py +0 -611
  354. package/backend/tests/unit/tools/test_read_tool.py +0 -33
  355. package/backend/tests/unit/tools/test_set_permissions_tool.py +0 -595
  356. package/backend/tests/unit/tools/test_todo_tool.py +0 -37
  357. package/backend/tests/unit/tools/test_tool_registry.py +0 -199
  358. package/dist/frontend/assets/AssistantPage-BW7XAd9I.js +0 -1
  359. package/dist/frontend/assets/ChannelsPage-tCJHgt6m.js +0 -1
  360. package/dist/frontend/assets/PageScaffold-f6g2l7XN.js +0 -1
  361. package/dist/frontend/assets/PromptsPage-C3Sxn2D7.js +0 -1
  362. package/dist/frontend/assets/ProvidersPage-BfmdXmNt.js +0 -3
  363. package/dist/frontend/assets/RolesPage-DET8wO4r.js +0 -1
  364. package/dist/frontend/assets/SettingsPage-D-g3deMm.js +0 -3
  365. package/dist/frontend/assets/ToolsPage-CDmtE2g4.js +0 -1
  366. package/dist/frontend/assets/WorkspacePage-AZsJ0sD0.js +0 -3
  367. package/dist/frontend/assets/WorkspacePanels-CteCjolX.js +0 -1
  368. package/dist/frontend/assets/alert-dialog-Duorp_S-.js +0 -1
  369. package/dist/frontend/assets/dialog-C3ixjGjN.js +0 -1
  370. package/dist/frontend/assets/elk-worker.min-C9JGDOE-.js +0 -6312
  371. package/dist/frontend/assets/graph-vendor-CHpVij2M.css +0 -1
  372. package/dist/frontend/assets/graph-vendor-DRq_-6fV.js +0 -7
  373. package/dist/frontend/assets/index--o_0fv0N.css +0 -1
  374. package/dist/frontend/assets/index-C9HuekJm.js +0 -10
  375. package/dist/frontend/assets/layout.worker-jMHqAFbP.js +0 -24
  376. package/dist/frontend/assets/markdown-vendor-C9RtvaJh.js +0 -29
  377. package/dist/frontend/assets/modelParams-DmnF2hwR.js +0 -1
  378. package/dist/frontend/assets/providerTypes-DT3Ahwl_.js +0 -1
  379. package/dist/frontend/assets/react-vendor-mEs_JJxa.js +0 -9
  380. package/dist/frontend/assets/roles-CuRT_chR.js +0 -1
  381. package/dist/frontend/assets/rolldown-runtime-BYbx6iT9.js +0 -1
  382. package/dist/frontend/assets/select-DCfeNu-F.js +0 -1
  383. package/dist/frontend/assets/surface-pWwG5ogx.js +0 -1
  384. package/dist/frontend/assets/ui-vendor-C5pJa8N7.js +0 -51
  385. package/dist/frontend/assets/useAppRoute-FgSHBKhV.js +0 -1
  386. 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()