flowent 0.0.6 → 0.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (398) hide show
  1. package/README.md +1 -4
  2. package/backend/README.md +1 -4
  3. package/backend/pyproject.toml +2 -8
  4. package/backend/src/flowent/__pycache__/__init__.cpython-313.pyc +0 -0
  5. package/backend/src/flowent/__pycache__/agent.cpython-313.pyc +0 -0
  6. package/backend/src/flowent/__pycache__/cli.cpython-313.pyc +0 -0
  7. package/backend/src/flowent/__pycache__/context.cpython-313.pyc +0 -0
  8. package/backend/src/flowent/__pycache__/llm.cpython-313.pyc +0 -0
  9. package/backend/src/flowent/__pycache__/logging.cpython-313.pyc +0 -0
  10. package/backend/src/flowent/__pycache__/main.cpython-313.pyc +0 -0
  11. package/backend/src/flowent/__pycache__/patch.cpython-313.pyc +0 -0
  12. package/backend/src/flowent/__pycache__/paths.cpython-313.pyc +0 -0
  13. package/backend/src/flowent/__pycache__/sandbox.cpython-313.pyc +0 -0
  14. package/backend/src/flowent/__pycache__/storage.cpython-313.pyc +0 -0
  15. package/backend/src/flowent/__pycache__/tools.cpython-313.pyc +0 -0
  16. package/backend/src/flowent/agent.py +217 -3094
  17. package/backend/src/flowent/cli.py +19 -24
  18. package/backend/src/flowent/context.py +127 -0
  19. package/backend/src/flowent/llm.py +256 -0
  20. package/backend/src/flowent/logging.py +170 -129
  21. package/backend/src/flowent/main.py +321 -70
  22. package/backend/src/flowent/patch.py +182 -0
  23. package/backend/src/flowent/paths.py +11 -0
  24. package/backend/src/flowent/sandbox.py +214 -40
  25. package/backend/src/flowent/static/assets/geist-cyrillic-wght-normal-CHSlOQsW.woff2 +0 -0
  26. package/backend/src/flowent/static/assets/geist-latin-ext-wght-normal-DMtmJ5ZE.woff2 +0 -0
  27. package/backend/src/flowent/static/assets/geist-latin-wght-normal-Dm3htQBi.woff2 +0 -0
  28. package/backend/src/flowent/static/assets/index-C76K95ty.js +81 -0
  29. package/backend/src/flowent/static/assets/index-iUMNKvlU.css +2 -0
  30. package/backend/src/flowent/static/flowent.png +0 -0
  31. package/backend/src/flowent/static/index.html +5 -25
  32. package/backend/src/flowent/storage.py +302 -0
  33. package/backend/src/flowent/tools.py +364 -0
  34. package/backend/tests/__pycache__/test_agent_tools.cpython-313-pytest-9.0.3.pyc +0 -0
  35. package/backend/tests/__pycache__/test_health.cpython-313-pytest-9.0.3.pyc +0 -0
  36. package/backend/tests/__pycache__/test_llm_providers.cpython-313-pytest-9.0.3.pyc +0 -0
  37. package/backend/tests/__pycache__/test_logging.cpython-313-pytest-9.0.3.pyc +0 -0
  38. package/backend/tests/__pycache__/test_persistence.cpython-313-pytest-9.0.3.pyc +0 -0
  39. package/backend/tests/__pycache__/test_workspace_chat.cpython-313-pytest-9.0.3.pyc +0 -0
  40. package/backend/tests/test_agent_tools.py +449 -0
  41. package/backend/tests/test_health.py +12 -0
  42. package/backend/tests/test_llm_providers.py +113 -0
  43. package/backend/tests/test_logging.py +182 -0
  44. package/backend/tests/test_persistence.py +125 -0
  45. package/backend/tests/test_workspace_chat.py +578 -0
  46. package/backend/uv.lock +803 -99
  47. package/dist/frontend/assets/geist-cyrillic-wght-normal-CHSlOQsW.woff2 +0 -0
  48. package/dist/frontend/assets/geist-latin-ext-wght-normal-DMtmJ5ZE.woff2 +0 -0
  49. package/dist/frontend/assets/geist-latin-wght-normal-Dm3htQBi.woff2 +0 -0
  50. package/dist/frontend/assets/index-C76K95ty.js +81 -0
  51. package/dist/frontend/assets/index-iUMNKvlU.css +2 -0
  52. package/dist/frontend/flowent.png +0 -0
  53. package/dist/frontend/index.html +5 -25
  54. package/package.json +1 -2
  55. package/backend/src/flowent/__pycache__/_version.cpython-313.pyc +0 -0
  56. package/backend/src/flowent/__pycache__/access.cpython-313.pyc +0 -0
  57. package/backend/src/flowent/__pycache__/assistant_commands.cpython-313.pyc +0 -0
  58. package/backend/src/flowent/__pycache__/config.cpython-313.pyc +0 -0
  59. package/backend/src/flowent/__pycache__/events.cpython-313.pyc +0 -0
  60. package/backend/src/flowent/__pycache__/graph_runtime.cpython-313.pyc +0 -0
  61. package/backend/src/flowent/__pycache__/graph_service.cpython-313.pyc +0 -0
  62. package/backend/src/flowent/__pycache__/image_assets.cpython-313.pyc +0 -0
  63. package/backend/src/flowent/__pycache__/mcp_service.cpython-313.pyc +0 -0
  64. package/backend/src/flowent/__pycache__/model_metadata.cpython-313.pyc +0 -0
  65. package/backend/src/flowent/__pycache__/network.cpython-313.pyc +0 -0
  66. package/backend/src/flowent/__pycache__/observability_service.cpython-313.pyc +0 -0
  67. package/backend/src/flowent/__pycache__/registry.cpython-313.pyc +0 -0
  68. package/backend/src/flowent/__pycache__/role_management.cpython-313.pyc +0 -0
  69. package/backend/src/flowent/__pycache__/runtime.cpython-313.pyc +0 -0
  70. package/backend/src/flowent/__pycache__/security.cpython-313.pyc +0 -0
  71. package/backend/src/flowent/__pycache__/settings.cpython-313.pyc +0 -0
  72. package/backend/src/flowent/__pycache__/settings_management.cpython-313.pyc +0 -0
  73. package/backend/src/flowent/__pycache__/state_db.cpython-313.pyc +0 -0
  74. package/backend/src/flowent/__pycache__/workspace_store.cpython-313.pyc +0 -0
  75. package/backend/src/flowent/access.py +0 -247
  76. package/backend/src/flowent/assistant_commands.py +0 -115
  77. package/backend/src/flowent/channels/__init__.py +0 -3
  78. package/backend/src/flowent/channels/__pycache__/__init__.cpython-313.pyc +0 -0
  79. package/backend/src/flowent/channels/__pycache__/telegram.cpython-313.pyc +0 -0
  80. package/backend/src/flowent/channels/telegram.py +0 -615
  81. package/backend/src/flowent/config.py +0 -14
  82. package/backend/src/flowent/dev.py +0 -3
  83. package/backend/src/flowent/events.py +0 -157
  84. package/backend/src/flowent/graph_runtime.py +0 -60
  85. package/backend/src/flowent/graph_service.py +0 -2508
  86. package/backend/src/flowent/image_assets.py +0 -356
  87. package/backend/src/flowent/mcp_service.py +0 -1918
  88. package/backend/src/flowent/model_metadata.py +0 -102
  89. package/backend/src/flowent/models/__init__.py +0 -125
  90. package/backend/src/flowent/models/__pycache__/__init__.cpython-313.pyc +0 -0
  91. package/backend/src/flowent/models/__pycache__/agent.cpython-313.pyc +0 -0
  92. package/backend/src/flowent/models/__pycache__/base.cpython-313.pyc +0 -0
  93. package/backend/src/flowent/models/__pycache__/blueprint.cpython-313.pyc +0 -0
  94. package/backend/src/flowent/models/__pycache__/content.cpython-313.pyc +0 -0
  95. package/backend/src/flowent/models/__pycache__/delta.cpython-313.pyc +0 -0
  96. package/backend/src/flowent/models/__pycache__/event.cpython-313.pyc +0 -0
  97. package/backend/src/flowent/models/__pycache__/graph.cpython-313.pyc +0 -0
  98. package/backend/src/flowent/models/__pycache__/history.cpython-313.pyc +0 -0
  99. package/backend/src/flowent/models/__pycache__/llm.cpython-313.pyc +0 -0
  100. package/backend/src/flowent/models/__pycache__/message.cpython-313.pyc +0 -0
  101. package/backend/src/flowent/models/__pycache__/tab.cpython-313.pyc +0 -0
  102. package/backend/src/flowent/models/__pycache__/todo.cpython-313.pyc +0 -0
  103. package/backend/src/flowent/models/agent.py +0 -34
  104. package/backend/src/flowent/models/base.py +0 -24
  105. package/backend/src/flowent/models/blueprint.py +0 -176
  106. package/backend/src/flowent/models/content.py +0 -164
  107. package/backend/src/flowent/models/delta.py +0 -44
  108. package/backend/src/flowent/models/event.py +0 -51
  109. package/backend/src/flowent/models/graph.py +0 -472
  110. package/backend/src/flowent/models/history.py +0 -272
  111. package/backend/src/flowent/models/llm.py +0 -62
  112. package/backend/src/flowent/models/message.py +0 -33
  113. package/backend/src/flowent/models/tab.py +0 -85
  114. package/backend/src/flowent/models/todo.py +0 -10
  115. package/backend/src/flowent/network.py +0 -146
  116. package/backend/src/flowent/observability_service.py +0 -218
  117. package/backend/src/flowent/prompts/__init__.py +0 -67
  118. package/backend/src/flowent/prompts/__pycache__/__init__.cpython-313.pyc +0 -0
  119. package/backend/src/flowent/prompts/__pycache__/common.cpython-313.pyc +0 -0
  120. package/backend/src/flowent/prompts/__pycache__/steward.cpython-313.pyc +0 -0
  121. package/backend/src/flowent/prompts/common.py +0 -250
  122. package/backend/src/flowent/prompts/steward.py +0 -64
  123. package/backend/src/flowent/providers/__init__.py +0 -23
  124. package/backend/src/flowent/providers/__pycache__/__init__.cpython-313.pyc +0 -0
  125. package/backend/src/flowent/providers/__pycache__/anthropic.cpython-313.pyc +0 -0
  126. package/backend/src/flowent/providers/__pycache__/base_url.cpython-313.pyc +0 -0
  127. package/backend/src/flowent/providers/__pycache__/configuration.cpython-313.pyc +0 -0
  128. package/backend/src/flowent/providers/__pycache__/content.cpython-313.pyc +0 -0
  129. package/backend/src/flowent/providers/__pycache__/errors.cpython-313.pyc +0 -0
  130. package/backend/src/flowent/providers/__pycache__/gateway.cpython-313.pyc +0 -0
  131. package/backend/src/flowent/providers/__pycache__/headers.cpython-313.pyc +0 -0
  132. package/backend/src/flowent/providers/__pycache__/management.cpython-313.pyc +0 -0
  133. package/backend/src/flowent/providers/__pycache__/openai.cpython-313.pyc +0 -0
  134. package/backend/src/flowent/providers/__pycache__/openai_responses.cpython-313.pyc +0 -0
  135. package/backend/src/flowent/providers/__pycache__/registry.cpython-313.pyc +0 -0
  136. package/backend/src/flowent/providers/__pycache__/sse.cpython-313.pyc +0 -0
  137. package/backend/src/flowent/providers/__pycache__/thinking.cpython-313.pyc +0 -0
  138. package/backend/src/flowent/providers/anthropic.py +0 -468
  139. package/backend/src/flowent/providers/base_url.py +0 -60
  140. package/backend/src/flowent/providers/configuration.py +0 -189
  141. package/backend/src/flowent/providers/content.py +0 -122
  142. package/backend/src/flowent/providers/errors.py +0 -223
  143. package/backend/src/flowent/providers/gateway.py +0 -169
  144. package/backend/src/flowent/providers/gemini.py +0 -447
  145. package/backend/src/flowent/providers/headers.py +0 -20
  146. package/backend/src/flowent/providers/management.py +0 -96
  147. package/backend/src/flowent/providers/ollama.py +0 -293
  148. package/backend/src/flowent/providers/openai.py +0 -422
  149. package/backend/src/flowent/providers/openai_responses.py +0 -655
  150. package/backend/src/flowent/providers/registry.py +0 -144
  151. package/backend/src/flowent/providers/sse.py +0 -31
  152. package/backend/src/flowent/providers/thinking.py +0 -79
  153. package/backend/src/flowent/registry.py +0 -73
  154. package/backend/src/flowent/role_management.py +0 -267
  155. package/backend/src/flowent/routes/__init__.py +0 -28
  156. package/backend/src/flowent/routes/__pycache__/__init__.cpython-313.pyc +0 -0
  157. package/backend/src/flowent/routes/__pycache__/access.cpython-313.pyc +0 -0
  158. package/backend/src/flowent/routes/__pycache__/assistant.cpython-313.pyc +0 -0
  159. package/backend/src/flowent/routes/__pycache__/image_assets.cpython-313.pyc +0 -0
  160. package/backend/src/flowent/routes/__pycache__/mcp.cpython-313.pyc +0 -0
  161. package/backend/src/flowent/routes/__pycache__/meta.cpython-313.pyc +0 -0
  162. package/backend/src/flowent/routes/__pycache__/nodes.cpython-313.pyc +0 -0
  163. package/backend/src/flowent/routes/__pycache__/prompts.cpython-313.pyc +0 -0
  164. package/backend/src/flowent/routes/__pycache__/providers_route.cpython-313.pyc +0 -0
  165. package/backend/src/flowent/routes/__pycache__/roles.cpython-313.pyc +0 -0
  166. package/backend/src/flowent/routes/__pycache__/settings.cpython-313.pyc +0 -0
  167. package/backend/src/flowent/routes/__pycache__/tabs.cpython-313.pyc +0 -0
  168. package/backend/src/flowent/routes/__pycache__/ws.cpython-313.pyc +0 -0
  169. package/backend/src/flowent/routes/access.py +0 -48
  170. package/backend/src/flowent/routes/assistant.py +0 -155
  171. package/backend/src/flowent/routes/image_assets.py +0 -33
  172. package/backend/src/flowent/routes/mcp.py +0 -125
  173. package/backend/src/flowent/routes/meta.py +0 -28
  174. package/backend/src/flowent/routes/nodes.py +0 -413
  175. package/backend/src/flowent/routes/prompts.py +0 -46
  176. package/backend/src/flowent/routes/providers_route.py +0 -365
  177. package/backend/src/flowent/routes/roles.py +0 -207
  178. package/backend/src/flowent/routes/settings.py +0 -328
  179. package/backend/src/flowent/routes/tabs.py +0 -310
  180. package/backend/src/flowent/routes/ws.py +0 -33
  181. package/backend/src/flowent/runtime.py +0 -165
  182. package/backend/src/flowent/security.py +0 -57
  183. package/backend/src/flowent/settings.py +0 -2518
  184. package/backend/src/flowent/settings_management.py +0 -298
  185. package/backend/src/flowent/state_db.py +0 -120
  186. package/backend/src/flowent/static/assets/AssistantPage-VBohhz4d.js +0 -1
  187. package/backend/src/flowent/static/assets/ChannelsPage-CIydPZA_.js +0 -1
  188. package/backend/src/flowent/static/assets/McpPage-CHPm2TPY.js +0 -7
  189. package/backend/src/flowent/static/assets/PageScaffold-DteOA8V7.js +0 -1
  190. package/backend/src/flowent/static/assets/PromptsPage-CSmJ3sZg.js +0 -1
  191. package/backend/src/flowent/static/assets/ProvidersPage-sl2jeG4e.js +0 -3
  192. package/backend/src/flowent/static/assets/RolesPage-DCe7W6Km.js +0 -1
  193. package/backend/src/flowent/static/assets/SettingsPage-Bix9e63E.js +0 -3
  194. package/backend/src/flowent/static/assets/ToolsPage-favNkj5C.js +0 -1
  195. package/backend/src/flowent/static/assets/WorkspaceCommandDialog-DRS6wiD6.js +0 -1
  196. package/backend/src/flowent/static/assets/WorkspacePage-KuaDjt_D.js +0 -3
  197. package/backend/src/flowent/static/assets/WorkspacePanels-BZxBw8M5.js +0 -1
  198. package/backend/src/flowent/static/assets/alert-dialog-DIBUCmqM.js +0 -1
  199. package/backend/src/flowent/static/assets/datetime-eJqd0V2S.js +0 -1
  200. package/backend/src/flowent/static/assets/dialog-BOvHIBrg.js +0 -1
  201. package/backend/src/flowent/static/assets/elk-worker.min-C9JGDOE-.js +0 -6312
  202. package/backend/src/flowent/static/assets/graph-vendor-CHpVij2M.css +0 -1
  203. package/backend/src/flowent/static/assets/graph-vendor-DRq_-6fV.js +0 -7
  204. package/backend/src/flowent/static/assets/index-Biio-CoI.js +0 -10
  205. package/backend/src/flowent/static/assets/index-CmQvO7sl.css +0 -1
  206. package/backend/src/flowent/static/assets/layout.worker-jMHqAFbP.js +0 -24
  207. package/backend/src/flowent/static/assets/markdown-vendor-C9RtvaJh.js +0 -29
  208. package/backend/src/flowent/static/assets/modelParams-DcEhGnu0.js +0 -1
  209. package/backend/src/flowent/static/assets/react-vendor-mEs_JJxa.js +0 -9
  210. package/backend/src/flowent/static/assets/roles-BbIEIMeG.js +0 -1
  211. package/backend/src/flowent/static/assets/rolldown-runtime-BYbx6iT9.js +0 -1
  212. package/backend/src/flowent/static/assets/select-D9SwnlXF.js +0 -1
  213. package/backend/src/flowent/static/assets/surface-Bzr1FRG4.js +0 -1
  214. package/backend/src/flowent/static/assets/triState-DgLlKdRR.js +0 -1
  215. package/backend/src/flowent/static/assets/ui-vendor-UazN8rcv.js +0 -51
  216. package/backend/src/flowent/static/favicon.svg +0 -4
  217. package/backend/src/flowent/tools/__init__.py +0 -275
  218. package/backend/src/flowent/tools/__pycache__/__init__.cpython-313.pyc +0 -0
  219. package/backend/src/flowent/tools/__pycache__/connect.cpython-313.pyc +0 -0
  220. package/backend/src/flowent/tools/__pycache__/contacts.cpython-313.pyc +0 -0
  221. package/backend/src/flowent/tools/__pycache__/create_agent.cpython-313.pyc +0 -0
  222. package/backend/src/flowent/tools/__pycache__/create_tab.cpython-313.pyc +0 -0
  223. package/backend/src/flowent/tools/__pycache__/delete_tab.cpython-313.pyc +0 -0
  224. package/backend/src/flowent/tools/__pycache__/edit.cpython-313.pyc +0 -0
  225. package/backend/src/flowent/tools/__pycache__/exec.cpython-313.pyc +0 -0
  226. package/backend/src/flowent/tools/__pycache__/fetch.cpython-313.pyc +0 -0
  227. package/backend/src/flowent/tools/__pycache__/idle.cpython-313.pyc +0 -0
  228. package/backend/src/flowent/tools/__pycache__/list_roles.cpython-313.pyc +0 -0
  229. package/backend/src/flowent/tools/__pycache__/list_tabs.cpython-313.pyc +0 -0
  230. package/backend/src/flowent/tools/__pycache__/list_tools.cpython-313.pyc +0 -0
  231. package/backend/src/flowent/tools/__pycache__/manage_prompts.cpython-313.pyc +0 -0
  232. package/backend/src/flowent/tools/__pycache__/manage_providers.cpython-313.pyc +0 -0
  233. package/backend/src/flowent/tools/__pycache__/manage_roles.cpython-313.pyc +0 -0
  234. package/backend/src/flowent/tools/__pycache__/manage_settings.cpython-313.pyc +0 -0
  235. package/backend/src/flowent/tools/__pycache__/mcp.cpython-313.pyc +0 -0
  236. package/backend/src/flowent/tools/__pycache__/read.cpython-313.pyc +0 -0
  237. package/backend/src/flowent/tools/__pycache__/send.cpython-313.pyc +0 -0
  238. package/backend/src/flowent/tools/__pycache__/set_permissions.cpython-313.pyc +0 -0
  239. package/backend/src/flowent/tools/__pycache__/sleep.cpython-313.pyc +0 -0
  240. package/backend/src/flowent/tools/__pycache__/todo.cpython-313.pyc +0 -0
  241. package/backend/src/flowent/tools/connect.py +0 -100
  242. package/backend/src/flowent/tools/contacts.py +0 -22
  243. package/backend/src/flowent/tools/create_agent.py +0 -191
  244. package/backend/src/flowent/tools/create_tab.py +0 -61
  245. package/backend/src/flowent/tools/delete_tab.py +0 -39
  246. package/backend/src/flowent/tools/edit.py +0 -142
  247. package/backend/src/flowent/tools/exec.py +0 -118
  248. package/backend/src/flowent/tools/fetch.py +0 -85
  249. package/backend/src/flowent/tools/idle.py +0 -27
  250. package/backend/src/flowent/tools/list_roles.py +0 -75
  251. package/backend/src/flowent/tools/list_tabs.py +0 -100
  252. package/backend/src/flowent/tools/list_tools.py +0 -28
  253. package/backend/src/flowent/tools/manage_prompts.py +0 -102
  254. package/backend/src/flowent/tools/manage_providers.py +0 -220
  255. package/backend/src/flowent/tools/manage_roles.py +0 -275
  256. package/backend/src/flowent/tools/manage_settings.py +0 -364
  257. package/backend/src/flowent/tools/mcp.py +0 -199
  258. package/backend/src/flowent/tools/read.py +0 -152
  259. package/backend/src/flowent/tools/send.py +0 -68
  260. package/backend/src/flowent/tools/set_permissions.py +0 -99
  261. package/backend/src/flowent/tools/sleep.py +0 -41
  262. package/backend/src/flowent/tools/todo.py +0 -51
  263. package/backend/src/flowent/workspace_store.py +0 -479
  264. package/backend/tests/__init__.py +0 -0
  265. package/backend/tests/__pycache__/__init__.cpython-313.pyc +0 -0
  266. package/backend/tests/__pycache__/conftest.cpython-313-pytest-9.0.3.pyc +0 -0
  267. package/backend/tests/conftest.py +0 -6
  268. package/backend/tests/integration/api/__pycache__/conftest.cpython-313-pytest-9.0.3.pyc +0 -0
  269. package/backend/tests/integration/api/__pycache__/test_access_api.cpython-313-pytest-9.0.3.pyc +0 -0
  270. package/backend/tests/integration/api/__pycache__/test_assistant_api.cpython-313-pytest-9.0.3.pyc +0 -0
  271. package/backend/tests/integration/api/__pycache__/test_frontend_mounting.cpython-313-pytest-9.0.3.pyc +0 -0
  272. package/backend/tests/integration/api/__pycache__/test_mcp_api.cpython-313-pytest-9.0.3.pyc +0 -0
  273. package/backend/tests/integration/api/__pycache__/test_meta_api.cpython-313-pytest-9.0.3.pyc +0 -0
  274. package/backend/tests/integration/api/__pycache__/test_nodes_api.cpython-313-pytest-9.0.3.pyc +0 -0
  275. package/backend/tests/integration/api/__pycache__/test_prompts_api.cpython-313-pytest-9.0.3.pyc +0 -0
  276. package/backend/tests/integration/api/__pycache__/test_roles_api.cpython-313-pytest-9.0.3.pyc +0 -0
  277. package/backend/tests/integration/api/__pycache__/test_tabs_api.cpython-313-pytest-9.0.3.pyc +0 -0
  278. package/backend/tests/integration/api/conftest.py +0 -29
  279. package/backend/tests/integration/api/test_access_api.py +0 -182
  280. package/backend/tests/integration/api/test_assistant_api.py +0 -354
  281. package/backend/tests/integration/api/test_frontend_mounting.py +0 -61
  282. package/backend/tests/integration/api/test_mcp_api.py +0 -116
  283. package/backend/tests/integration/api/test_meta_api.py +0 -33
  284. package/backend/tests/integration/api/test_nodes_api.py +0 -722
  285. package/backend/tests/integration/api/test_prompts_api.py +0 -47
  286. package/backend/tests/integration/api/test_roles_api.py +0 -228
  287. package/backend/tests/integration/api/test_tabs_api.py +0 -802
  288. package/backend/tests/unit/__pycache__/test_access.cpython-313-pytest-9.0.3.pyc +0 -0
  289. package/backend/tests/unit/__pycache__/test_cli.cpython-313-pytest-9.0.3.pyc +0 -0
  290. package/backend/tests/unit/__pycache__/test_graph_runtime.cpython-313-pytest-9.0.3.pyc +0 -0
  291. package/backend/tests/unit/__pycache__/test_network.cpython-313-pytest-9.0.3.pyc +0 -0
  292. package/backend/tests/unit/__pycache__/test_state_sqlite_storage.cpython-313-pytest-9.0.3.pyc +0 -0
  293. package/backend/tests/unit/__pycache__/test_workspace_store.cpython-313-pytest-9.0.3.pyc +0 -0
  294. package/backend/tests/unit/agent/__pycache__/test_agent_public_api.cpython-313-pytest-9.0.3.pyc +0 -0
  295. package/backend/tests/unit/agent/__pycache__/test_agent_runtime.cpython-313-pytest-9.0.3.pyc +0 -0
  296. package/backend/tests/unit/agent/test_agent_public_api.py +0 -837
  297. package/backend/tests/unit/agent/test_agent_runtime.py +0 -2942
  298. package/backend/tests/unit/channels/__pycache__/test_telegram_channel.cpython-313-pytest-9.0.3.pyc +0 -0
  299. package/backend/tests/unit/channels/test_telegram_channel.py +0 -552
  300. package/backend/tests/unit/logging/__pycache__/test_logging.cpython-313-pytest-9.0.3.pyc +0 -0
  301. package/backend/tests/unit/logging/test_logging.py +0 -132
  302. package/backend/tests/unit/prompts/__pycache__/test_prompts.cpython-313-pytest-9.0.3.pyc +0 -0
  303. package/backend/tests/unit/prompts/test_prompts.py +0 -570
  304. package/backend/tests/unit/providers/__pycache__/test_anthropic_provider.cpython-313-pytest-9.0.3.pyc +0 -0
  305. package/backend/tests/unit/providers/__pycache__/test_errors.cpython-313-pytest-9.0.3.pyc +0 -0
  306. package/backend/tests/unit/providers/__pycache__/test_extract_delta_parts.cpython-313-pytest-9.0.3.pyc +0 -0
  307. package/backend/tests/unit/providers/__pycache__/test_openai_provider.cpython-313-pytest-9.0.3.pyc +0 -0
  308. package/backend/tests/unit/providers/__pycache__/test_openai_responses.cpython-313-pytest-9.0.3.pyc +0 -0
  309. package/backend/tests/unit/providers/__pycache__/test_provider_gateway.cpython-313-pytest-9.0.3.pyc +0 -0
  310. package/backend/tests/unit/providers/__pycache__/test_think_tag_parser.cpython-313-pytest-9.0.3.pyc +0 -0
  311. package/backend/tests/unit/providers/test_anthropic_provider.py +0 -185
  312. package/backend/tests/unit/providers/test_errors.py +0 -68
  313. package/backend/tests/unit/providers/test_extract_delta_parts.py +0 -22
  314. package/backend/tests/unit/providers/test_openai_provider.py +0 -139
  315. package/backend/tests/unit/providers/test_openai_responses.py +0 -402
  316. package/backend/tests/unit/providers/test_provider_gateway.py +0 -359
  317. package/backend/tests/unit/providers/test_think_tag_parser.py +0 -36
  318. package/backend/tests/unit/routes/__pycache__/test_prompts_routes.cpython-313-pytest-9.0.3.pyc +0 -0
  319. package/backend/tests/unit/routes/__pycache__/test_providers_route.cpython-313-pytest-9.0.3.pyc +0 -0
  320. package/backend/tests/unit/routes/__pycache__/test_roles_routes.cpython-313-pytest-9.0.3.pyc +0 -0
  321. package/backend/tests/unit/routes/__pycache__/test_settings_routes.cpython-313-pytest-9.0.3.pyc +0 -0
  322. package/backend/tests/unit/routes/test_prompts_routes.py +0 -104
  323. package/backend/tests/unit/routes/test_providers_route.py +0 -370
  324. package/backend/tests/unit/routes/test_roles_routes.py +0 -535
  325. package/backend/tests/unit/routes/test_settings_routes.py +0 -1142
  326. package/backend/tests/unit/runtime/__pycache__/test_bootstrap_runtime.cpython-313-pytest-9.0.3.pyc +0 -0
  327. package/backend/tests/unit/runtime/test_bootstrap_runtime.py +0 -1002
  328. package/backend/tests/unit/sandbox/__pycache__/test_sandbox_tools.cpython-313-pytest-9.0.3.pyc +0 -0
  329. package/backend/tests/unit/sandbox/test_sandbox_tools.py +0 -78
  330. package/backend/tests/unit/security/__pycache__/test_security.cpython-313-pytest-9.0.3.pyc +0 -0
  331. package/backend/tests/unit/security/test_security.py +0 -124
  332. package/backend/tests/unit/settings/__pycache__/test_settings_roles.cpython-313-pytest-9.0.3.pyc +0 -0
  333. package/backend/tests/unit/settings/test_settings_roles.py +0 -751
  334. package/backend/tests/unit/test_access.py +0 -45
  335. package/backend/tests/unit/test_cli.py +0 -124
  336. package/backend/tests/unit/test_graph_runtime.py +0 -72
  337. package/backend/tests/unit/test_network.py +0 -51
  338. package/backend/tests/unit/test_state_sqlite_storage.py +0 -159
  339. package/backend/tests/unit/test_workspace_store.py +0 -231
  340. package/backend/tests/unit/tools/__pycache__/test_connect_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  341. package/backend/tests/unit/tools/__pycache__/test_create_agent_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  342. package/backend/tests/unit/tools/__pycache__/test_delete_tab_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  343. package/backend/tests/unit/tools/__pycache__/test_edit_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  344. package/backend/tests/unit/tools/__pycache__/test_exec_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  345. package/backend/tests/unit/tools/__pycache__/test_fetch_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  346. package/backend/tests/unit/tools/__pycache__/test_manage_prompts_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  347. package/backend/tests/unit/tools/__pycache__/test_manage_providers_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  348. package/backend/tests/unit/tools/__pycache__/test_manage_roles_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  349. package/backend/tests/unit/tools/__pycache__/test_manage_settings_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  350. package/backend/tests/unit/tools/__pycache__/test_read_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  351. package/backend/tests/unit/tools/__pycache__/test_set_permissions_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  352. package/backend/tests/unit/tools/__pycache__/test_todo_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  353. package/backend/tests/unit/tools/__pycache__/test_tool_registry.cpython-313-pytest-9.0.3.pyc +0 -0
  354. package/backend/tests/unit/tools/test_connect_tool.py +0 -228
  355. package/backend/tests/unit/tools/test_create_agent_tool.py +0 -436
  356. package/backend/tests/unit/tools/test_delete_tab_tool.py +0 -116
  357. package/backend/tests/unit/tools/test_edit_tool.py +0 -115
  358. package/backend/tests/unit/tools/test_exec_tool.py +0 -81
  359. package/backend/tests/unit/tools/test_fetch_tool.py +0 -65
  360. package/backend/tests/unit/tools/test_manage_prompts_tool.py +0 -117
  361. package/backend/tests/unit/tools/test_manage_providers_tool.py +0 -460
  362. package/backend/tests/unit/tools/test_manage_roles_tool.py +0 -411
  363. package/backend/tests/unit/tools/test_manage_settings_tool.py +0 -611
  364. package/backend/tests/unit/tools/test_read_tool.py +0 -33
  365. package/backend/tests/unit/tools/test_set_permissions_tool.py +0 -595
  366. package/backend/tests/unit/tools/test_todo_tool.py +0 -37
  367. package/backend/tests/unit/tools/test_tool_registry.py +0 -194
  368. package/dist/frontend/assets/AssistantPage-VBohhz4d.js +0 -1
  369. package/dist/frontend/assets/ChannelsPage-CIydPZA_.js +0 -1
  370. package/dist/frontend/assets/McpPage-CHPm2TPY.js +0 -7
  371. package/dist/frontend/assets/PageScaffold-DteOA8V7.js +0 -1
  372. package/dist/frontend/assets/PromptsPage-CSmJ3sZg.js +0 -1
  373. package/dist/frontend/assets/ProvidersPage-sl2jeG4e.js +0 -3
  374. package/dist/frontend/assets/RolesPage-DCe7W6Km.js +0 -1
  375. package/dist/frontend/assets/SettingsPage-Bix9e63E.js +0 -3
  376. package/dist/frontend/assets/ToolsPage-favNkj5C.js +0 -1
  377. package/dist/frontend/assets/WorkspaceCommandDialog-DRS6wiD6.js +0 -1
  378. package/dist/frontend/assets/WorkspacePage-KuaDjt_D.js +0 -3
  379. package/dist/frontend/assets/WorkspacePanels-BZxBw8M5.js +0 -1
  380. package/dist/frontend/assets/alert-dialog-DIBUCmqM.js +0 -1
  381. package/dist/frontend/assets/datetime-eJqd0V2S.js +0 -1
  382. package/dist/frontend/assets/dialog-BOvHIBrg.js +0 -1
  383. package/dist/frontend/assets/elk-worker.min-C9JGDOE-.js +0 -6312
  384. package/dist/frontend/assets/graph-vendor-CHpVij2M.css +0 -1
  385. package/dist/frontend/assets/graph-vendor-DRq_-6fV.js +0 -7
  386. package/dist/frontend/assets/index-Biio-CoI.js +0 -10
  387. package/dist/frontend/assets/index-CmQvO7sl.css +0 -1
  388. package/dist/frontend/assets/layout.worker-jMHqAFbP.js +0 -24
  389. package/dist/frontend/assets/markdown-vendor-C9RtvaJh.js +0 -29
  390. package/dist/frontend/assets/modelParams-DcEhGnu0.js +0 -1
  391. package/dist/frontend/assets/react-vendor-mEs_JJxa.js +0 -9
  392. package/dist/frontend/assets/roles-BbIEIMeG.js +0 -1
  393. package/dist/frontend/assets/rolldown-runtime-BYbx6iT9.js +0 -1
  394. package/dist/frontend/assets/select-D9SwnlXF.js +0 -1
  395. package/dist/frontend/assets/surface-Bzr1FRG4.js +0 -1
  396. package/dist/frontend/assets/triState-DgLlKdRR.js +0 -1
  397. package/dist/frontend/assets/ui-vendor-UazN8rcv.js +0 -51
  398. package/dist/frontend/favicon.svg +0 -4
@@ -1,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,124 +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_help_output_no_longer_lists_mcp_command(capsys):
63
- with pytest.raises(SystemExit) as exc:
64
- main(["--help"])
65
-
66
- assert exc.value.code == 0
67
- output = capsys.readouterr().out
68
-
69
- assert "access" in output
70
- assert "mcp" not in output
71
-
72
-
73
- def test_version_short_option_matches_version_output(capsys):
74
- with pytest.raises(SystemExit) as exc:
75
- main(["-v"])
76
-
77
- assert exc.value.code == 0
78
- assert capsys.readouterr().out.startswith("flowent ")
79
-
80
-
81
- def test_server_options_accept_npm_wrapper_aliases(monkeypatch):
82
- called: dict[str, object] = {}
83
-
84
- monkeypatch.setattr(
85
- "uvicorn.run",
86
- lambda app, *, host, port: called.update(
87
- {"app": app, "host": host, "port": port}
88
- ),
89
- )
90
-
91
- main(["--hostname", "127.0.0.1", "-p", "7000"])
92
-
93
- assert called == {
94
- "app": "flowent.main:app",
95
- "host": "127.0.0.1",
96
- "port": 7000,
97
- }
98
-
99
-
100
- def test_removed_mcp_command_is_rejected(capsys):
101
- with pytest.raises(SystemExit) as exc:
102
- main(["mcp", "serve"])
103
-
104
- assert exc.value.code == 2
105
- error_output = capsys.readouterr().err
106
-
107
- assert "invalid choice" in error_output
108
- assert "'mcp'" in error_output
109
-
110
-
111
- def test_cli_sets_app_data_dir_env_before_dispatch(monkeypatch, tmp_path, capsys):
112
- monkeypatch.delenv(APP_DATA_DIR_ENV_VAR, raising=False)
113
- called: list[str] = []
114
-
115
- monkeypatch.setattr(
116
- "flowent.access.refresh_local_access",
117
- lambda: called.append("refresh") or "Generated new access code: TEST",
118
- )
119
-
120
- main(["--app-data-dir", str(tmp_path), "access", "refresh"])
121
-
122
- assert called == ["refresh"]
123
- assert os.environ[APP_DATA_DIR_ENV_VAR] == str(tmp_path)
124
- 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,159 +0,0 @@
1
- import base64
2
- import sqlite3
3
- import time
4
-
5
- import flowent.settings as settings_module
6
- from flowent.agent import Agent
7
- from flowent.image_assets import create_image_asset
8
- from flowent.mcp_service import MCPDiscoverySnapshot, MCPToolDescriptor, mcp_service
9
- from flowent.models import NodeConfig, NodeType
10
- from flowent.settings import MCPServerConfig, Settings
11
-
12
- _ONE_PIXEL_PNG = base64.b64decode(
13
- "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+aF9sAAAAASUVORK5CYII="
14
- )
15
-
16
-
17
- def test_create_image_asset_persists_metadata_in_state_sqlite(monkeypatch, tmp_path):
18
- settings_file = tmp_path / "settings.json"
19
- settings_file.write_text("{}", encoding="utf-8")
20
- monkeypatch.setattr(settings_module, "_SETTINGS_FILE", settings_file)
21
- monkeypatch.setattr(settings_module, "_cached_settings", None)
22
-
23
- asset = create_image_asset(
24
- _ONE_PIXEL_PNG,
25
- mime_type="image/png",
26
- original_name="pixel.png",
27
- )
28
-
29
- assert asset.file_path == tmp_path / "assets" / "images" / asset.stored_name
30
- assert asset.file_path.is_file()
31
- connection = sqlite3.connect(tmp_path / "state.sqlite")
32
- connection.row_factory = sqlite3.Row
33
- try:
34
- row = connection.execute(
35
- """
36
- SELECT stored_name, mime_type, width, height, original_name
37
- FROM image_assets
38
- WHERE id = ?
39
- """,
40
- (asset.id,),
41
- ).fetchone()
42
- finally:
43
- connection.close()
44
- assert row is not None
45
- assert row["stored_name"] == asset.stored_name
46
- assert row["mime_type"] == "image/png"
47
- assert row["width"] == 1
48
- assert row["height"] == 1
49
- assert row["original_name"] == "pixel.png"
50
-
51
-
52
- def test_mcp_service_restores_persisted_snapshot_and_activity_after_runtime_clear(
53
- monkeypatch,
54
- tmp_path,
55
- ):
56
- settings_file = tmp_path / "settings.json"
57
- settings_file.write_text("{}", encoding="utf-8")
58
- monkeypatch.setattr(settings_module, "_SETTINGS_FILE", settings_file)
59
- monkeypatch.setattr(settings_module, "_cached_settings", None)
60
- mcp_service.reset()
61
- now = time.time()
62
-
63
- try:
64
- mcp_service._set_snapshot(
65
- MCPDiscoverySnapshot(
66
- server_name="filesystem",
67
- transport="stdio",
68
- status="connected",
69
- auth_status="unsupported",
70
- last_refresh_result="success",
71
- )
72
- )
73
- mcp_service._record_activity(
74
- server_name="filesystem",
75
- action="refresh",
76
- actor_node_id=None,
77
- tab_id=None,
78
- started_at=now - 2.0,
79
- ended_at=now,
80
- result="success",
81
- summary="Capabilities refreshed",
82
- )
83
-
84
- mcp_service.clear_runtime_state()
85
-
86
- restored_snapshot = mcp_service._get_snapshot("filesystem")
87
- restored_activities = mcp_service.list_activities(server_name="filesystem")
88
-
89
- assert restored_snapshot is not None
90
- assert restored_snapshot.status == "connected"
91
- assert restored_snapshot.last_refresh_result == "success"
92
- assert len(restored_activities) == 1
93
- assert restored_activities[0].server_name == "filesystem"
94
- assert restored_activities[0].summary == "Capabilities refreshed"
95
- finally:
96
- mcp_service.reset()
97
-
98
-
99
- def test_mcp_service_filters_workflow_management_tools_for_non_assistant(
100
- monkeypatch,
101
- tmp_path,
102
- ):
103
- settings_file = tmp_path / "settings.json"
104
- settings_file.write_text("{}", encoding="utf-8")
105
- monkeypatch.setattr(settings_module, "_SETTINGS_FILE", settings_file)
106
- monkeypatch.setattr(settings_module, "_cached_settings", None)
107
- monkeypatch.setattr(
108
- "flowent.mcp_service.get_settings",
109
- lambda: Settings(
110
- mcp_servers=[
111
- MCPServerConfig(
112
- name="flowent",
113
- transport="stdio",
114
- )
115
- ]
116
- ),
117
- )
118
- mcp_service.reset()
119
-
120
- try:
121
- mcp_service._set_snapshot(
122
- MCPDiscoverySnapshot(
123
- server_name="flowent",
124
- transport="stdio",
125
- status="connected",
126
- auth_status="unsupported",
127
- tools=[
128
- MCPToolDescriptor(
129
- server_name="flowent",
130
- tool_name="list_workflows",
131
- fully_qualified_id="mcp__flowent__list_workflows",
132
- ),
133
- MCPToolDescriptor(
134
- server_name="flowent",
135
- tool_name="search_notes",
136
- fully_qualified_id="mcp__flowent__search_notes",
137
- ),
138
- ],
139
- )
140
- )
141
- worker = Agent(NodeConfig(node_type=NodeType.AGENT), uuid="worker")
142
- assistant = Agent(NodeConfig(node_type=NodeType.ASSISTANT), uuid="assistant")
143
-
144
- worker_tools = {
145
- descriptor.fully_qualified_id
146
- for descriptor in mcp_service.list_agent_dynamic_tools(worker)
147
- }
148
- assistant_tools = {
149
- descriptor.fully_qualified_id
150
- for descriptor in mcp_service.list_agent_dynamic_tools(assistant)
151
- }
152
-
153
- assert worker_tools == {"mcp__flowent__search_notes"}
154
- assert assistant_tools == {
155
- "mcp__flowent__list_workflows",
156
- "mcp__flowent__search_notes",
157
- }
158
- finally:
159
- mcp_service.reset()
@@ -1,231 +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
- "blueprints": [],
42
- }
43
- ),
44
- encoding="utf-8",
45
- )
46
-
47
- monkeypatch.setattr(settings_module, "_SETTINGS_FILE", settings_file)
48
- monkeypatch.setattr(
49
- settings_module,
50
- "get_settings",
51
- lambda: Settings(working_dir=str(working_dir)),
52
- )
53
- workspace_store.reset_cache()
54
-
55
- record = workspace_store.get_node_record("node-1")
56
-
57
- assert record is not None
58
- assert record.config.write_dirs == [str((working_dir / "out").resolve())]
59
- connection = open_state_db(create=False)
60
- assert connection is not None
61
- try:
62
- row = connection.execute(
63
- "SELECT payload FROM nodes WHERE id = ?",
64
- ("node-1",),
65
- ).fetchone()
66
- finally:
67
- connection.close()
68
- assert row is not None
69
- persisted = json.loads(row["payload"])
70
- assert persisted["config"]["write_dirs"] == [str((working_dir / "out").resolve())]
71
- workspace_store.reset_cache()
72
-
73
-
74
- def test_workspace_store_prefers_legacy_workspace_data_when_state_db_is_still_empty(
75
- monkeypatch,
76
- tmp_path,
77
- ):
78
- import flowent.settings as settings_module
79
-
80
- settings_file = tmp_path / "settings.json"
81
- workspace_file = tmp_path / "workspace.json"
82
- state_db_file = tmp_path / "state.sqlite"
83
- settings_file.write_text("{}", encoding="utf-8")
84
- workspace_file.write_text(
85
- json.dumps(
86
- {
87
- "tabs": [],
88
- "nodes": [
89
- {
90
- "id": "node-legacy",
91
- "config": {
92
- "node_type": "agent",
93
- "role_name": "Worker",
94
- "tab_id": "tab-1",
95
- "name": "Worker",
96
- "tools": ["read"],
97
- "write_dirs": [],
98
- "allow_network": False,
99
- },
100
- "state": "idle",
101
- "todos": [],
102
- "history": [],
103
- }
104
- ],
105
- "edges": [],
106
- "blueprints": [],
107
- }
108
- ),
109
- encoding="utf-8",
110
- )
111
- sqlite3.connect(state_db_file).close()
112
-
113
- monkeypatch.setattr(settings_module, "_SETTINGS_FILE", settings_file)
114
- monkeypatch.setattr(settings_module, "_cached_settings", None)
115
- monkeypatch.setattr(
116
- settings_module,
117
- "get_settings",
118
- lambda: Settings(working_dir=str(tmp_path)),
119
- )
120
- workspace_store.reset_cache()
121
-
122
- record = workspace_store.get_node_record("node-legacy")
123
-
124
- assert record is not None
125
- assert record.id == "node-legacy"
126
- workspace_store.reset_cache()
127
-
128
-
129
- def test_workspace_store_does_not_overwrite_state_db_with_legacy_workspace_data(
130
- monkeypatch,
131
- tmp_path,
132
- ):
133
- import flowent.settings as settings_module
134
-
135
- settings_file = tmp_path / "settings.json"
136
- workspace_file = tmp_path / "workspace.json"
137
- settings_file.write_text("{}", encoding="utf-8")
138
- workspace_file.write_text(
139
- json.dumps(
140
- {
141
- "tabs": [],
142
- "nodes": [
143
- {
144
- "id": "node-legacy",
145
- "config": {
146
- "node_type": "agent",
147
- "role_name": "Worker",
148
- "tab_id": "tab-1",
149
- "name": "Legacy",
150
- "tools": ["read"],
151
- "write_dirs": [],
152
- "allow_network": False,
153
- },
154
- "state": "idle",
155
- "todos": [],
156
- "history": [],
157
- }
158
- ],
159
- "edges": [],
160
- "blueprints": [],
161
- }
162
- ),
163
- encoding="utf-8",
164
- )
165
-
166
- monkeypatch.setattr(settings_module, "_SETTINGS_FILE", settings_file)
167
- monkeypatch.setattr(settings_module, "_cached_settings", None)
168
- monkeypatch.setattr(
169
- settings_module,
170
- "get_settings",
171
- lambda: Settings(working_dir=str(tmp_path)),
172
- )
173
- connection = open_state_db(create=True)
174
- assert connection is not None
175
- try:
176
- with connection:
177
- connection.execute(
178
- """
179
- INSERT INTO nodes (id, payload, tab_id, node_type, updated_at)
180
- VALUES (?, ?, ?, ?, ?)
181
- """,
182
- (
183
- "node-sqlite",
184
- json.dumps(
185
- {
186
- "id": "node-sqlite",
187
- "config": {
188
- "node_type": "agent",
189
- "role_name": "Worker",
190
- "tab_id": "tab-1",
191
- "name": "SQLite",
192
- "tools": ["read"],
193
- "write_dirs": [],
194
- "allow_network": False,
195
- },
196
- "state": "idle",
197
- "todos": [],
198
- "history": [],
199
- }
200
- ),
201
- "tab-1",
202
- "agent",
203
- 1.0,
204
- ),
205
- )
206
- finally:
207
- connection.close()
208
-
209
- workspace_store.reset_cache()
210
-
211
- sqlite_record = workspace_store.get_node_record("node-sqlite")
212
- legacy_record = workspace_store.get_node_record("node-legacy")
213
-
214
- assert sqlite_record is not None
215
- assert legacy_record is None
216
- connection = open_state_db(create=False)
217
- assert connection is not None
218
- try:
219
- sqlite_row = connection.execute(
220
- "SELECT id FROM nodes WHERE id = ?",
221
- ("node-sqlite",),
222
- ).fetchone()
223
- legacy_row = connection.execute(
224
- "SELECT id FROM nodes WHERE id = ?",
225
- ("node-legacy",),
226
- ).fetchone()
227
- finally:
228
- connection.close()
229
- assert sqlite_row is not None
230
- assert legacy_row is None
231
- workspace_store.reset_cache()