flowent 0.0.6 → 0.0.7

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 (265) hide show
  1. package/README.md +1 -1
  2. package/backend/README.md +1 -1
  3. package/backend/pyproject.toml +1 -1
  4. package/backend/src/flowent/__pycache__/__init__.cpython-313.pyc +0 -0
  5. package/backend/src/flowent/__pycache__/_version.cpython-313.pyc +0 -0
  6. package/backend/src/flowent/__pycache__/access.cpython-313.pyc +0 -0
  7. package/backend/src/flowent/__pycache__/agent.cpython-313.pyc +0 -0
  8. package/backend/src/flowent/__pycache__/assistant_commands.cpython-313.pyc +0 -0
  9. package/backend/src/flowent/__pycache__/cli.cpython-313.pyc +0 -0
  10. package/backend/src/flowent/__pycache__/config.cpython-313.pyc +0 -0
  11. package/backend/src/flowent/__pycache__/events.cpython-313.pyc +0 -0
  12. package/backend/src/flowent/__pycache__/graph_runtime.cpython-313.pyc +0 -0
  13. package/backend/src/flowent/__pycache__/graph_service.cpython-313.pyc +0 -0
  14. package/backend/src/flowent/__pycache__/image_assets.cpython-313.pyc +0 -0
  15. package/backend/src/flowent/__pycache__/logging.cpython-313.pyc +0 -0
  16. package/backend/src/flowent/__pycache__/main.cpython-313.pyc +0 -0
  17. package/backend/src/flowent/__pycache__/model_metadata.cpython-313.pyc +0 -0
  18. package/backend/src/flowent/__pycache__/network.cpython-313.pyc +0 -0
  19. package/backend/src/flowent/__pycache__/observability_service.cpython-313.pyc +0 -0
  20. package/backend/src/flowent/__pycache__/registry.cpython-313.pyc +0 -0
  21. package/backend/src/flowent/__pycache__/role_management.cpython-313.pyc +0 -0
  22. package/backend/src/flowent/__pycache__/runtime.cpython-313.pyc +0 -0
  23. package/backend/src/flowent/__pycache__/sandbox.cpython-313.pyc +0 -0
  24. package/backend/src/flowent/__pycache__/security.cpython-313.pyc +0 -0
  25. package/backend/src/flowent/__pycache__/settings.cpython-313.pyc +0 -0
  26. package/backend/src/flowent/__pycache__/settings_management.cpython-313.pyc +0 -0
  27. package/backend/src/flowent/__pycache__/state_db.cpython-313.pyc +0 -0
  28. package/backend/src/flowent/__pycache__/workspace_store.cpython-313.pyc +0 -0
  29. package/backend/src/flowent/agent.py +91 -8
  30. package/backend/src/flowent/channels/__pycache__/__init__.cpython-313.pyc +0 -0
  31. package/backend/src/flowent/channels/__pycache__/telegram.cpython-313.pyc +0 -0
  32. package/backend/src/flowent/graph_service.py +3 -110
  33. package/backend/src/flowent/models/__pycache__/__init__.cpython-313.pyc +0 -0
  34. package/backend/src/flowent/models/__pycache__/agent.cpython-313.pyc +0 -0
  35. package/backend/src/flowent/models/__pycache__/base.cpython-313.pyc +0 -0
  36. package/backend/src/flowent/models/__pycache__/blueprint.cpython-313.pyc +0 -0
  37. package/backend/src/flowent/models/__pycache__/content.cpython-313.pyc +0 -0
  38. package/backend/src/flowent/models/__pycache__/delta.cpython-313.pyc +0 -0
  39. package/backend/src/flowent/models/__pycache__/event.cpython-313.pyc +0 -0
  40. package/backend/src/flowent/models/__pycache__/graph.cpython-313.pyc +0 -0
  41. package/backend/src/flowent/models/__pycache__/history.cpython-313.pyc +0 -0
  42. package/backend/src/flowent/models/__pycache__/llm.cpython-313.pyc +0 -0
  43. package/backend/src/flowent/models/__pycache__/message.cpython-313.pyc +0 -0
  44. package/backend/src/flowent/models/__pycache__/tab.cpython-313.pyc +0 -0
  45. package/backend/src/flowent/models/__pycache__/todo.cpython-313.pyc +0 -0
  46. package/backend/src/flowent/prompts/__pycache__/__init__.cpython-313.pyc +0 -0
  47. package/backend/src/flowent/prompts/__pycache__/common.cpython-313.pyc +0 -0
  48. package/backend/src/flowent/prompts/__pycache__/steward.cpython-313.pyc +0 -0
  49. package/backend/src/flowent/providers/__pycache__/__init__.cpython-313.pyc +0 -0
  50. package/backend/src/flowent/providers/__pycache__/anthropic.cpython-313.pyc +0 -0
  51. package/backend/src/flowent/providers/__pycache__/base_url.cpython-313.pyc +0 -0
  52. package/backend/src/flowent/providers/__pycache__/configuration.cpython-313.pyc +0 -0
  53. package/backend/src/flowent/providers/__pycache__/content.cpython-313.pyc +0 -0
  54. package/backend/src/flowent/providers/__pycache__/errors.cpython-313.pyc +0 -0
  55. package/backend/src/flowent/providers/__pycache__/gateway.cpython-313.pyc +0 -0
  56. package/backend/src/flowent/providers/__pycache__/headers.cpython-313.pyc +0 -0
  57. package/backend/src/flowent/providers/__pycache__/management.cpython-313.pyc +0 -0
  58. package/backend/src/flowent/providers/__pycache__/openai.cpython-313.pyc +0 -0
  59. package/backend/src/flowent/providers/__pycache__/openai_responses.cpython-313.pyc +0 -0
  60. package/backend/src/flowent/providers/__pycache__/registry.cpython-313.pyc +0 -0
  61. package/backend/src/flowent/providers/__pycache__/sse.cpython-313.pyc +0 -0
  62. package/backend/src/flowent/providers/__pycache__/thinking.cpython-313.pyc +0 -0
  63. package/backend/src/flowent/role_management.py +9 -6
  64. package/backend/src/flowent/routes/__init__.py +0 -2
  65. package/backend/src/flowent/routes/__pycache__/__init__.cpython-313.pyc +0 -0
  66. package/backend/src/flowent/routes/__pycache__/access.cpython-313.pyc +0 -0
  67. package/backend/src/flowent/routes/__pycache__/assistant.cpython-313.pyc +0 -0
  68. package/backend/src/flowent/routes/__pycache__/image_assets.cpython-313.pyc +0 -0
  69. package/backend/src/flowent/routes/__pycache__/meta.cpython-313.pyc +0 -0
  70. package/backend/src/flowent/routes/__pycache__/nodes.cpython-313.pyc +0 -0
  71. package/backend/src/flowent/routes/__pycache__/prompts.cpython-313.pyc +0 -0
  72. package/backend/src/flowent/routes/__pycache__/providers_route.cpython-313.pyc +0 -0
  73. package/backend/src/flowent/routes/__pycache__/roles.cpython-313.pyc +0 -0
  74. package/backend/src/flowent/routes/__pycache__/settings.cpython-313.pyc +0 -0
  75. package/backend/src/flowent/routes/__pycache__/tabs.cpython-313.pyc +0 -0
  76. package/backend/src/flowent/routes/__pycache__/ws.cpython-313.pyc +0 -0
  77. package/backend/src/flowent/routes/assistant.py +3 -0
  78. package/backend/src/flowent/routes/nodes.py +11 -1
  79. package/backend/src/flowent/routes/settings.py +169 -118
  80. package/backend/src/flowent/routes/tabs.py +0 -12
  81. package/backend/src/flowent/runtime.py +0 -5
  82. package/backend/src/flowent/security.py +1 -21
  83. package/backend/src/flowent/settings.py +15 -421
  84. package/backend/src/flowent/settings_management.py +260 -164
  85. package/backend/src/flowent/state_db.py +2 -14
  86. package/backend/src/flowent/static/assets/AssistantPage-BW7XAd9I.js +1 -0
  87. package/backend/src/flowent/static/assets/ChannelsPage-tCJHgt6m.js +1 -0
  88. package/backend/src/flowent/static/assets/{PageScaffold-DteOA8V7.js → PageScaffold-f6g2l7XN.js} +1 -1
  89. package/backend/src/flowent/static/assets/PromptsPage-C3Sxn2D7.js +1 -0
  90. package/backend/src/flowent/static/assets/ProvidersPage-BfmdXmNt.js +3 -0
  91. package/backend/src/flowent/static/assets/RolesPage-DET8wO4r.js +1 -0
  92. package/backend/src/flowent/static/assets/SettingsPage-D-g3deMm.js +3 -0
  93. package/backend/src/flowent/static/assets/ToolsPage-CDmtE2g4.js +1 -0
  94. package/backend/src/flowent/static/assets/WorkspacePage-AZsJ0sD0.js +3 -0
  95. package/backend/src/flowent/static/assets/WorkspacePanels-CteCjolX.js +1 -0
  96. package/backend/src/flowent/static/assets/{alert-dialog-DIBUCmqM.js → alert-dialog-Duorp_S-.js} +1 -1
  97. package/backend/src/flowent/static/assets/{dialog-BOvHIBrg.js → dialog-C3ixjGjN.js} +1 -1
  98. package/backend/src/flowent/static/assets/index--o_0fv0N.css +1 -0
  99. package/backend/src/flowent/static/assets/index-C9HuekJm.js +10 -0
  100. package/backend/src/flowent/static/assets/{modelParams-DcEhGnu0.js → modelParams-DmnF2hwR.js} +1 -1
  101. package/backend/src/flowent/static/assets/providerTypes-DT3Ahwl_.js +1 -0
  102. package/backend/src/flowent/static/assets/roles-CuRT_chR.js +1 -0
  103. package/{dist/frontend/assets/select-D9SwnlXF.js → backend/src/flowent/static/assets/select-DCfeNu-F.js} +1 -1
  104. package/backend/src/flowent/static/assets/surface-pWwG5ogx.js +1 -0
  105. package/backend/src/flowent/static/assets/{ui-vendor-UazN8rcv.js → ui-vendor-C5pJa8N7.js} +15 -15
  106. package/backend/src/flowent/static/assets/useAppRoute-FgSHBKhV.js +1 -0
  107. package/backend/src/flowent/static/index.html +3 -3
  108. package/backend/src/flowent/tools/__init__.py +2 -101
  109. package/backend/src/flowent/tools/__pycache__/__init__.cpython-313.pyc +0 -0
  110. package/backend/src/flowent/tools/__pycache__/connect.cpython-313.pyc +0 -0
  111. package/backend/src/flowent/tools/__pycache__/contacts.cpython-313.pyc +0 -0
  112. package/backend/src/flowent/tools/__pycache__/create_agent.cpython-313.pyc +0 -0
  113. package/backend/src/flowent/tools/__pycache__/create_tab.cpython-313.pyc +0 -0
  114. package/backend/src/flowent/tools/__pycache__/delete_tab.cpython-313.pyc +0 -0
  115. package/backend/src/flowent/tools/__pycache__/edit.cpython-313.pyc +0 -0
  116. package/backend/src/flowent/tools/__pycache__/exec.cpython-313.pyc +0 -0
  117. package/backend/src/flowent/tools/__pycache__/fetch.cpython-313.pyc +0 -0
  118. package/backend/src/flowent/tools/__pycache__/idle.cpython-313.pyc +0 -0
  119. package/backend/src/flowent/tools/__pycache__/list_roles.cpython-313.pyc +0 -0
  120. package/backend/src/flowent/tools/__pycache__/list_tabs.cpython-313.pyc +0 -0
  121. package/backend/src/flowent/tools/__pycache__/list_tools.cpython-313.pyc +0 -0
  122. package/backend/src/flowent/tools/__pycache__/manage_prompts.cpython-313.pyc +0 -0
  123. package/backend/src/flowent/tools/__pycache__/manage_providers.cpython-313.pyc +0 -0
  124. package/backend/src/flowent/tools/__pycache__/manage_roles.cpython-313.pyc +0 -0
  125. package/backend/src/flowent/tools/__pycache__/manage_settings.cpython-313.pyc +0 -0
  126. package/backend/src/flowent/tools/__pycache__/read.cpython-313.pyc +0 -0
  127. package/backend/src/flowent/tools/__pycache__/send.cpython-313.pyc +0 -0
  128. package/backend/src/flowent/tools/__pycache__/set_permissions.cpython-313.pyc +0 -0
  129. package/backend/src/flowent/tools/__pycache__/sleep.cpython-313.pyc +0 -0
  130. package/backend/src/flowent/tools/__pycache__/todo.cpython-313.pyc +0 -0
  131. package/backend/src/flowent/tools/list_roles.py +2 -9
  132. package/backend/src/flowent/tools/manage_settings.py +134 -172
  133. package/backend/tests/__pycache__/__init__.cpython-313.pyc +0 -0
  134. package/backend/tests/__pycache__/conftest.cpython-313-pytest-9.0.3.pyc +0 -0
  135. package/backend/tests/integration/api/__pycache__/conftest.cpython-313-pytest-9.0.3.pyc +0 -0
  136. package/backend/tests/integration/api/__pycache__/test_access_api.cpython-313-pytest-9.0.3.pyc +0 -0
  137. package/backend/tests/integration/api/__pycache__/test_assistant_api.cpython-313-pytest-9.0.3.pyc +0 -0
  138. package/backend/tests/integration/api/__pycache__/test_frontend_mounting.cpython-313-pytest-9.0.3.pyc +0 -0
  139. package/backend/tests/integration/api/__pycache__/test_meta_api.cpython-313-pytest-9.0.3.pyc +0 -0
  140. package/backend/tests/integration/api/__pycache__/test_nodes_api.cpython-313-pytest-9.0.3.pyc +0 -0
  141. package/backend/tests/integration/api/__pycache__/test_prompts_api.cpython-313-pytest-9.0.3.pyc +0 -0
  142. package/backend/tests/integration/api/__pycache__/test_roles_api.cpython-313-pytest-9.0.3.pyc +0 -0
  143. package/backend/tests/integration/api/__pycache__/test_tabs_api.cpython-313-pytest-9.0.3.pyc +0 -0
  144. package/backend/tests/integration/api/test_assistant_api.py +68 -0
  145. package/backend/tests/integration/api/test_meta_api.py +0 -1
  146. package/backend/tests/integration/api/test_nodes_api.py +73 -8
  147. package/backend/tests/integration/api/test_tabs_api.py +0 -114
  148. package/backend/tests/unit/__pycache__/test_access.cpython-313-pytest-9.0.3.pyc +0 -0
  149. package/backend/tests/unit/__pycache__/test_cli.cpython-313-pytest-9.0.3.pyc +0 -0
  150. package/backend/tests/unit/__pycache__/test_graph_runtime.cpython-313-pytest-9.0.3.pyc +0 -0
  151. package/backend/tests/unit/__pycache__/test_network.cpython-313-pytest-9.0.3.pyc +0 -0
  152. package/backend/tests/unit/__pycache__/test_state_sqlite_storage.cpython-313-pytest-9.0.3.pyc +0 -0
  153. package/backend/tests/unit/__pycache__/test_workspace_store.cpython-313-pytest-9.0.3.pyc +0 -0
  154. package/backend/tests/unit/agent/__pycache__/test_agent_public_api.cpython-313-pytest-9.0.3.pyc +0 -0
  155. package/backend/tests/unit/agent/__pycache__/test_agent_runtime.cpython-313-pytest-9.0.3.pyc +0 -0
  156. package/backend/tests/unit/agent/test_agent_public_api.py +0 -15
  157. package/backend/tests/unit/agent/test_agent_runtime.py +148 -2
  158. package/backend/tests/unit/channels/__pycache__/test_telegram_channel.cpython-313-pytest-9.0.3.pyc +0 -0
  159. package/backend/tests/unit/logging/__pycache__/test_logging.cpython-313-pytest-9.0.3.pyc +0 -0
  160. package/backend/tests/unit/prompts/__pycache__/test_prompts.cpython-313-pytest-9.0.3.pyc +0 -0
  161. package/backend/tests/unit/providers/__pycache__/test_anthropic_provider.cpython-313-pytest-9.0.3.pyc +0 -0
  162. package/backend/tests/unit/providers/__pycache__/test_errors.cpython-313-pytest-9.0.3.pyc +0 -0
  163. package/backend/tests/unit/providers/__pycache__/test_extract_delta_parts.cpython-313-pytest-9.0.3.pyc +0 -0
  164. package/backend/tests/unit/providers/__pycache__/test_openai_provider.cpython-313-pytest-9.0.3.pyc +0 -0
  165. package/backend/tests/unit/providers/__pycache__/test_openai_responses.cpython-313-pytest-9.0.3.pyc +0 -0
  166. package/backend/tests/unit/providers/__pycache__/test_provider_gateway.cpython-313-pytest-9.0.3.pyc +0 -0
  167. package/backend/tests/unit/providers/__pycache__/test_think_tag_parser.cpython-313-pytest-9.0.3.pyc +0 -0
  168. package/backend/tests/unit/routes/__pycache__/test_prompts_routes.cpython-313-pytest-9.0.3.pyc +0 -0
  169. package/backend/tests/unit/routes/__pycache__/test_providers_route.cpython-313-pytest-9.0.3.pyc +0 -0
  170. package/backend/tests/unit/routes/__pycache__/test_roles_routes.cpython-313-pytest-9.0.3.pyc +0 -0
  171. package/backend/tests/unit/routes/__pycache__/test_settings_routes.cpython-313-pytest-9.0.3.pyc +0 -0
  172. package/backend/tests/unit/routes/test_prompts_routes.py +0 -22
  173. package/backend/tests/unit/routes/test_roles_routes.py +6 -2
  174. package/backend/tests/unit/routes/test_settings_routes.py +0 -19
  175. package/backend/tests/unit/runtime/__pycache__/test_bootstrap_runtime.cpython-313-pytest-9.0.3.pyc +0 -0
  176. package/backend/tests/unit/sandbox/__pycache__/test_sandbox_tools.cpython-313-pytest-9.0.3.pyc +0 -0
  177. package/backend/tests/unit/security/__pycache__/test_security.cpython-313-pytest-9.0.3.pyc +0 -0
  178. package/backend/tests/unit/settings/__pycache__/test_settings_roles.cpython-313-pytest-9.0.3.pyc +0 -0
  179. package/backend/tests/unit/settings/test_settings_roles.py +3 -51
  180. package/backend/tests/unit/test_cli.py +0 -22
  181. package/backend/tests/unit/test_state_sqlite_storage.py +27 -99
  182. package/backend/tests/unit/test_workspace_store.py +0 -3
  183. package/backend/tests/unit/tools/__pycache__/test_connect_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  184. package/backend/tests/unit/tools/__pycache__/test_create_agent_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  185. package/backend/tests/unit/tools/__pycache__/test_delete_tab_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  186. package/backend/tests/unit/tools/__pycache__/test_edit_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  187. package/backend/tests/unit/tools/__pycache__/test_exec_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  188. package/backend/tests/unit/tools/__pycache__/test_fetch_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  189. package/backend/tests/unit/tools/__pycache__/test_manage_prompts_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  190. package/backend/tests/unit/tools/__pycache__/test_manage_providers_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  191. package/backend/tests/unit/tools/__pycache__/test_manage_roles_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  192. package/backend/tests/unit/tools/__pycache__/test_manage_settings_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  193. package/backend/tests/unit/tools/__pycache__/test_read_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  194. package/backend/tests/unit/tools/__pycache__/test_set_permissions_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  195. package/backend/tests/unit/tools/__pycache__/test_todo_tool.cpython-313-pytest-9.0.3.pyc +0 -0
  196. package/backend/tests/unit/tools/__pycache__/test_tool_registry.cpython-313-pytest-9.0.3.pyc +0 -0
  197. package/backend/tests/unit/tools/test_create_agent_tool.py +0 -32
  198. package/backend/tests/unit/tools/test_manage_prompts_tool.py +5 -30
  199. package/backend/tests/unit/tools/test_tool_registry.py +45 -40
  200. package/backend/uv.lock +1 -1
  201. package/dist/frontend/assets/AssistantPage-BW7XAd9I.js +1 -0
  202. package/dist/frontend/assets/ChannelsPage-tCJHgt6m.js +1 -0
  203. package/dist/frontend/assets/{PageScaffold-DteOA8V7.js → PageScaffold-f6g2l7XN.js} +1 -1
  204. package/dist/frontend/assets/PromptsPage-C3Sxn2D7.js +1 -0
  205. package/dist/frontend/assets/ProvidersPage-BfmdXmNt.js +3 -0
  206. package/dist/frontend/assets/RolesPage-DET8wO4r.js +1 -0
  207. package/dist/frontend/assets/SettingsPage-D-g3deMm.js +3 -0
  208. package/dist/frontend/assets/ToolsPage-CDmtE2g4.js +1 -0
  209. package/dist/frontend/assets/WorkspacePage-AZsJ0sD0.js +3 -0
  210. package/dist/frontend/assets/WorkspacePanels-CteCjolX.js +1 -0
  211. package/dist/frontend/assets/{alert-dialog-DIBUCmqM.js → alert-dialog-Duorp_S-.js} +1 -1
  212. package/dist/frontend/assets/{dialog-BOvHIBrg.js → dialog-C3ixjGjN.js} +1 -1
  213. package/dist/frontend/assets/index--o_0fv0N.css +1 -0
  214. package/dist/frontend/assets/index-C9HuekJm.js +10 -0
  215. package/dist/frontend/assets/{modelParams-DcEhGnu0.js → modelParams-DmnF2hwR.js} +1 -1
  216. package/dist/frontend/assets/providerTypes-DT3Ahwl_.js +1 -0
  217. package/dist/frontend/assets/roles-CuRT_chR.js +1 -0
  218. package/{backend/src/flowent/static/assets/select-D9SwnlXF.js → dist/frontend/assets/select-DCfeNu-F.js} +1 -1
  219. package/dist/frontend/assets/surface-pWwG5ogx.js +1 -0
  220. package/dist/frontend/assets/{ui-vendor-UazN8rcv.js → ui-vendor-C5pJa8N7.js} +15 -15
  221. package/dist/frontend/assets/useAppRoute-FgSHBKhV.js +1 -0
  222. package/dist/frontend/index.html +3 -3
  223. package/package.json +1 -1
  224. package/backend/src/flowent/__pycache__/mcp_service.cpython-313.pyc +0 -0
  225. package/backend/src/flowent/mcp_service.py +0 -1918
  226. package/backend/src/flowent/routes/__pycache__/mcp.cpython-313.pyc +0 -0
  227. package/backend/src/flowent/routes/mcp.py +0 -125
  228. package/backend/src/flowent/static/assets/AssistantPage-VBohhz4d.js +0 -1
  229. package/backend/src/flowent/static/assets/ChannelsPage-CIydPZA_.js +0 -1
  230. package/backend/src/flowent/static/assets/McpPage-CHPm2TPY.js +0 -7
  231. package/backend/src/flowent/static/assets/PromptsPage-CSmJ3sZg.js +0 -1
  232. package/backend/src/flowent/static/assets/ProvidersPage-sl2jeG4e.js +0 -3
  233. package/backend/src/flowent/static/assets/RolesPage-DCe7W6Km.js +0 -1
  234. package/backend/src/flowent/static/assets/SettingsPage-Bix9e63E.js +0 -3
  235. package/backend/src/flowent/static/assets/ToolsPage-favNkj5C.js +0 -1
  236. package/backend/src/flowent/static/assets/WorkspaceCommandDialog-DRS6wiD6.js +0 -1
  237. package/backend/src/flowent/static/assets/WorkspacePage-KuaDjt_D.js +0 -3
  238. package/backend/src/flowent/static/assets/WorkspacePanels-BZxBw8M5.js +0 -1
  239. package/backend/src/flowent/static/assets/datetime-eJqd0V2S.js +0 -1
  240. package/backend/src/flowent/static/assets/index-Biio-CoI.js +0 -10
  241. package/backend/src/flowent/static/assets/index-CmQvO7sl.css +0 -1
  242. package/backend/src/flowent/static/assets/roles-BbIEIMeG.js +0 -1
  243. package/backend/src/flowent/static/assets/surface-Bzr1FRG4.js +0 -1
  244. package/backend/src/flowent/static/assets/triState-DgLlKdRR.js +0 -1
  245. package/backend/src/flowent/tools/__pycache__/mcp.cpython-313.pyc +0 -0
  246. package/backend/src/flowent/tools/mcp.py +0 -199
  247. package/backend/tests/integration/api/__pycache__/test_mcp_api.cpython-313-pytest-9.0.3.pyc +0 -0
  248. package/backend/tests/integration/api/test_mcp_api.py +0 -116
  249. package/dist/frontend/assets/AssistantPage-VBohhz4d.js +0 -1
  250. package/dist/frontend/assets/ChannelsPage-CIydPZA_.js +0 -1
  251. package/dist/frontend/assets/McpPage-CHPm2TPY.js +0 -7
  252. package/dist/frontend/assets/PromptsPage-CSmJ3sZg.js +0 -1
  253. package/dist/frontend/assets/ProvidersPage-sl2jeG4e.js +0 -3
  254. package/dist/frontend/assets/RolesPage-DCe7W6Km.js +0 -1
  255. package/dist/frontend/assets/SettingsPage-Bix9e63E.js +0 -3
  256. package/dist/frontend/assets/ToolsPage-favNkj5C.js +0 -1
  257. package/dist/frontend/assets/WorkspaceCommandDialog-DRS6wiD6.js +0 -1
  258. package/dist/frontend/assets/WorkspacePage-KuaDjt_D.js +0 -3
  259. package/dist/frontend/assets/WorkspacePanels-BZxBw8M5.js +0 -1
  260. package/dist/frontend/assets/datetime-eJqd0V2S.js +0 -1
  261. package/dist/frontend/assets/index-Biio-CoI.js +0 -10
  262. package/dist/frontend/assets/index-CmQvO7sl.css +0 -1
  263. package/dist/frontend/assets/roles-BbIEIMeG.js +0 -1
  264. package/dist/frontend/assets/surface-Bzr1FRG4.js +0 -1
  265. package/dist/frontend/assets/triState-DgLlKdRR.js +0 -1
@@ -0,0 +1 @@
1
+ import{a as e}from"./rolldown-runtime-BYbx6iT9.js";import{d as t}from"./graph-vendor-DRq_-6fV.js";import{D as n,b as r}from"./index-C9HuekJm.js";var i=e(t(),1);function a(){return window.location.pathname}function o(e){return window.addEventListener(`popstate`,e),window.addEventListener(r,e),()=>{window.removeEventListener(`popstate`,e),window.removeEventListener(r,e)}}function s(){return(0,i.useSyncExternalStore)(o,a,a),n(window.location)}export{s as t};
@@ -21,13 +21,13 @@
21
21
  }
22
22
  })();
23
23
  </script>
24
- <script type="module" crossorigin src="/assets/index-Biio-CoI.js"></script>
24
+ <script type="module" crossorigin src="/assets/index-C9HuekJm.js"></script>
25
25
  <link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-BYbx6iT9.js">
26
26
  <link rel="modulepreload" crossorigin href="/assets/graph-vendor-DRq_-6fV.js">
27
27
  <link rel="modulepreload" crossorigin href="/assets/react-vendor-mEs_JJxa.js">
28
- <link rel="modulepreload" crossorigin href="/assets/ui-vendor-UazN8rcv.js">
28
+ <link rel="modulepreload" crossorigin href="/assets/ui-vendor-C5pJa8N7.js">
29
29
  <link rel="stylesheet" crossorigin href="/assets/graph-vendor-CHpVij2M.css">
30
- <link rel="stylesheet" crossorigin href="/assets/index-CmQvO7sl.css">
30
+ <link rel="stylesheet" crossorigin href="/assets/index--o_0fv0N.css">
31
31
  </head>
32
32
  <body class="min-h-dvh bg-background text-foreground">
33
33
  <div id="root"></div>
@@ -16,14 +16,6 @@ MINIMUM_TOOLS = (
16
16
  "send",
17
17
  )
18
18
 
19
- MCP_BROWSING_TOOLS = (
20
- "list_mcp_resources",
21
- "list_mcp_resource_templates",
22
- "read_mcp_resource",
23
- "list_mcp_prompts",
24
- "get_mcp_prompt",
25
- )
26
-
27
19
  ASSISTANT_ONLY_TOOLS = frozenset(
28
20
  {
29
21
  "create_workflow",
@@ -36,49 +28,11 @@ ASSISTANT_ONLY_TOOLS = frozenset(
36
28
  }
37
29
  )
38
30
 
39
- ASSISTANT_ONLY_MCP_TOOL_NAMES = frozenset(
40
- {
41
- "create_workflow",
42
- "create_workflows",
43
- "delete_workflow",
44
- "delete_workflows",
45
- "duplicate_workflow",
46
- "duplicate_workflows",
47
- "copy_workflow",
48
- "copy_workflows",
49
- "list_workflow",
50
- "list_workflows",
51
- "select_workflow",
52
- "select_workflows",
53
- "switch_workflow",
54
- "switch_workflows",
55
- "manage_provider",
56
- "manage_providers",
57
- "manage_role",
58
- "manage_roles",
59
- "manage_setting",
60
- "manage_settings",
61
- "manage_prompt",
62
- "manage_prompts",
63
- }
64
- )
65
-
66
31
 
67
32
  def is_assistant_only_tool_name(tool_name: str) -> bool:
68
33
  return tool_name in ASSISTANT_ONLY_TOOLS
69
34
 
70
35
 
71
- def is_assistant_only_mcp_tool_name(tool_name: str) -> bool:
72
- normalized = tool_name.strip().lower().replace("-", "_")
73
- candidate = (
74
- normalized.rsplit("__", 1)[-1] if normalized.startswith("mcp__") else normalized
75
- )
76
- return (
77
- normalized in ASSISTANT_ONLY_MCP_TOOL_NAMES
78
- or candidate in ASSISTANT_ONLY_MCP_TOOL_NAMES
79
- )
80
-
81
-
82
36
  class Tool(ABC):
83
37
  name: str
84
38
  description: str
@@ -117,36 +71,17 @@ class ToolRegistry:
117
71
  self._tools[tool.name] = tool
118
72
 
119
73
  def get(self, name: str) -> Tool | None:
120
- tool = self._tools.get(name)
121
- if tool is not None:
122
- return tool
123
- from flowent.mcp_service import mcp_service
124
- from flowent.tools.mcp import DynamicMCPTool
125
-
126
- descriptor = mcp_service.get_dynamic_tool_descriptor(name)
127
- if descriptor is None:
128
- return None
129
- return DynamicMCPTool(descriptor=descriptor)
74
+ return self._tools.get(name)
130
75
 
131
76
  def list_tools(self, *, agent_visible_only: bool = False) -> list[Tool]:
132
77
  tools = list(self._tools.values())
133
- from flowent.mcp_service import mcp_service
134
- from flowent.tools.mcp import DynamicMCPTool
135
-
136
- dynamic_tools = [
137
- DynamicMCPTool(descriptor=descriptor)
138
- for descriptor in mcp_service.list_discovered_tools()
139
- ]
140
- tools.extend(dynamic_tools)
141
78
  if not agent_visible_only:
142
79
  return tools
143
80
  return [tool for tool in tools if tool.agent_visible]
144
81
 
145
82
  def get_tools_for_agent(self, agent: Agent) -> list[Tool]:
146
- from flowent.mcp_service import mcp_service
147
83
  from flowent.models import NodeType
148
84
  from flowent.settings import find_role, get_settings
149
- from flowent.tools.mcp import DynamicMCPTool
150
85
 
151
86
  allowed = set(agent.config.tools) | set(MINIMUM_TOOLS)
152
87
  if agent.node_type != NodeType.ASSISTANT:
@@ -156,17 +91,7 @@ class ToolRegistry:
156
91
  ]
157
92
  role = find_role(get_settings(), agent.config.role_name or "")
158
93
  excluded = set(role.excluded_tools) if role is not None else set()
159
- dynamic_tools = [
160
- DynamicMCPTool(descriptor=descriptor)
161
- for descriptor in mcp_service.list_agent_dynamic_tools(agent)
162
- if descriptor.fully_qualified_id in allowed
163
- and descriptor.fully_qualified_id not in excluded
164
- and (
165
- agent.node_type == NodeType.ASSISTANT
166
- or not is_assistant_only_mcp_tool_name(descriptor.tool_name)
167
- )
168
- ]
169
- return [*visible_tools, *dynamic_tools]
94
+ return [tool for tool in visible_tools if tool.name not in excluded]
170
95
 
171
96
  def get_tools_schema(self, agent: Agent) -> list[dict[str, Any]]:
172
97
  return [t.to_schema() for t in self.get_tools_for_agent(agent)]
@@ -189,13 +114,6 @@ def build_tool_registry() -> ToolRegistry:
189
114
  from flowent.tools.manage_providers import ManageProvidersTool
190
115
  from flowent.tools.manage_roles import ManageRolesTool
191
116
  from flowent.tools.manage_settings import ManageSettingsTool
192
- from flowent.tools.mcp import (
193
- GetMCPPromptTool,
194
- ListMCPPromptsTool,
195
- ListMCPResourcesTool,
196
- ListMCPResourceTemplatesTool,
197
- ReadMCPResourceTool,
198
- )
199
117
  from flowent.tools.read import ReadTool
200
118
  from flowent.tools.send import SendTool
201
119
  from flowent.tools.set_permissions import SetPermissionsTool
@@ -225,11 +143,6 @@ def build_tool_registry() -> ToolRegistry:
225
143
  ListRolesTool,
226
144
  ListTabsTool,
227
145
  ListToolsTool,
228
- ListMCPResourcesTool,
229
- ListMCPResourceTemplatesTool,
230
- ReadMCPResourceTool,
231
- ListMCPPromptsTool,
232
- GetMCPPromptTool,
233
146
  ]:
234
147
  reg.register(tool_cls()) # type: ignore[abstract]
235
148
  return reg
@@ -240,12 +153,9 @@ def list_agent_visible_tool_descriptors(
240
153
  include_assistant_only: bool = True,
241
154
  ) -> list[dict[str, Any]]:
242
155
  registry = build_tool_registry()
243
- from flowent.mcp_service import mcp_service
244
156
 
245
157
  descriptors: list[dict[str, Any]] = []
246
158
  for tool in registry.list_tools(agent_visible_only=True):
247
- if tool.name.startswith("mcp__"):
248
- continue
249
159
  if not include_assistant_only and is_assistant_only_tool_name(tool.name):
250
160
  continue
251
161
  schema = tool.to_schema()
@@ -263,13 +173,4 @@ def list_agent_visible_tool_descriptors(
263
173
  "source": "builtin",
264
174
  }
265
175
  )
266
- for descriptor in mcp_service.list_discovered_tool_descriptors():
267
- tool_name = descriptor.get("tool_name")
268
- if (
269
- not include_assistant_only
270
- and isinstance(tool_name, str)
271
- and is_assistant_only_mcp_tool_name(tool_name)
272
- ):
273
- continue
274
- descriptors.append(descriptor)
275
176
  return descriptors
@@ -24,7 +24,6 @@ class ListRolesTool(Tool):
24
24
  from flowent.tools import (
25
25
  MINIMUM_TOOLS,
26
26
  build_tool_registry,
27
- is_assistant_only_mcp_tool_name,
28
27
  is_assistant_only_tool_name,
29
28
  )
30
29
 
@@ -32,12 +31,6 @@ class ListRolesTool(Tool):
32
31
  tool_registry = build_tool_registry()
33
32
  all_tool_names: list[str] = []
34
33
  for tool in tool_registry.list_tools(agent_visible_only=True):
35
- descriptor = getattr(tool, "_descriptor", None)
36
- descriptor_tool_name = getattr(descriptor, "tool_name", None)
37
- if isinstance(
38
- descriptor_tool_name, str
39
- ) and is_assistant_only_mcp_tool_name(descriptor_tool_name):
40
- continue
41
34
  all_tool_names.append(tool.name)
42
35
  if agent.node_type != NodeType.ASSISTANT:
43
36
  all_tool_names = [
@@ -53,8 +46,8 @@ class ListRolesTool(Tool):
53
46
  builtin_tools = [
54
47
  tool_name
55
48
  for tool_name in builtin_tools
56
- if not is_assistant_only_tool_name(tool_name)
57
- and not is_assistant_only_mcp_tool_name(tool_name)
49
+ if not tool_name.startswith("mcp__")
50
+ and not is_assistant_only_tool_name(tool_name)
58
51
  ]
59
52
  optional_tools = [
60
53
  tool_name
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import json
4
+ from collections.abc import Callable
4
5
  from typing import TYPE_CHECKING, Any, ClassVar
5
6
 
6
7
  if TYPE_CHECKING:
@@ -15,6 +16,99 @@ from flowent.settings_management import (
15
16
  from flowent.tools import Tool
16
17
 
17
18
 
19
+ def _error(message: str) -> str:
20
+ return json.dumps({"error": message})
21
+
22
+
23
+ def _validate_optional_string(value: object, field_name: str) -> str | None:
24
+ if value is not None and not isinstance(value, str):
25
+ return f"{field_name} must be a string"
26
+ return None
27
+
28
+
29
+ def _validate_manage_settings_args(args: dict[str, Any]) -> str | None:
30
+ from flowent.settings import (
31
+ build_model_auto_compact_token_limit,
32
+ build_model_context_window_tokens,
33
+ build_model_input_image,
34
+ build_model_max_retries,
35
+ build_model_output_image,
36
+ build_model_retry_backoff_cap_retries,
37
+ build_model_retry_initial_delay_seconds,
38
+ build_model_retry_max_delay_seconds,
39
+ build_model_retry_policy,
40
+ build_model_structured_output,
41
+ build_model_timeout_ms,
42
+ )
43
+
44
+ action = args.get("action")
45
+ if not isinstance(action, str):
46
+ return "action must be a string"
47
+
48
+ for field_name in (
49
+ "assistant_role_name",
50
+ "working_dir",
51
+ "leader_role_name",
52
+ "active_provider_id",
53
+ "active_model",
54
+ "timestamp_format",
55
+ ):
56
+ error = _validate_optional_string(args.get(field_name), field_name)
57
+ if error is not None:
58
+ return error
59
+
60
+ assistant_allow_network = args.get("assistant_allow_network")
61
+ if assistant_allow_network is not None and not isinstance(
62
+ assistant_allow_network, bool
63
+ ):
64
+ return "assistant_allow_network must be a boolean"
65
+
66
+ assistant_write_dirs = args.get("assistant_write_dirs")
67
+ if assistant_write_dirs is not None and not isinstance(assistant_write_dirs, list):
68
+ return "assistant_write_dirs must be an array of strings"
69
+
70
+ builders: tuple[tuple[str, Callable[..., object]], ...] = (
71
+ ("retry_policy", build_model_retry_policy),
72
+ ("timeout_ms", build_model_timeout_ms),
73
+ ("max_retries", build_model_max_retries),
74
+ ("retry_initial_delay_seconds", build_model_retry_initial_delay_seconds),
75
+ ("retry_max_delay_seconds", build_model_retry_max_delay_seconds),
76
+ ("retry_backoff_cap_retries", build_model_retry_backoff_cap_retries),
77
+ )
78
+ for field_name, builder in builders:
79
+ if args.get(field_name) is None:
80
+ continue
81
+ try:
82
+ builder(args.get(field_name), field_name=field_name)
83
+ except ValueError as exc:
84
+ return str(exc)
85
+
86
+ optional_builders: tuple[tuple[str, Callable[..., object]], ...] = (
87
+ ("input_image", build_model_input_image),
88
+ ("output_image", build_model_output_image),
89
+ ("structured_output", build_model_structured_output),
90
+ ("context_window_tokens", build_model_context_window_tokens),
91
+ ("auto_compact_token_limit", build_model_auto_compact_token_limit),
92
+ )
93
+ for field_name, builder in optional_builders:
94
+ if field_name not in args:
95
+ continue
96
+ try:
97
+ builder(args.get(field_name), field_name=field_name)
98
+ except ValueError as exc:
99
+ return str(exc)
100
+
101
+ model_params = args.get("model_params")
102
+ if model_params is not None and not isinstance(model_params, (dict, type(None))):
103
+ return "model_params must be an object or null"
104
+
105
+ return None
106
+
107
+
108
+ def _provided(args: dict[str, Any], field_name: str) -> object:
109
+ return args.get(field_name, MISSING)
110
+
111
+
18
112
  class ManageSettingsTool(Tool):
19
113
  name = "manage_settings"
20
114
  description = (
@@ -133,146 +227,12 @@ class ManageSettingsTool(Tool):
133
227
  def execute(self, agent: Agent, args: dict[str, Any], **_kwargs: Any) -> str:
134
228
  from flowent.graph_service import sync_assistant_role, sync_tab_leaders
135
229
  from flowent.providers.gateway import gateway
136
- from flowent.settings import (
137
- build_model_auto_compact_token_limit,
138
- build_model_context_window_tokens,
139
- build_model_input_image,
140
- build_model_max_retries,
141
- build_model_output_image,
142
- build_model_retry_backoff_cap_retries,
143
- build_model_retry_initial_delay_seconds,
144
- build_model_retry_max_delay_seconds,
145
- build_model_retry_policy,
146
- build_model_structured_output,
147
- build_model_timeout_ms,
148
- get_settings,
149
- save_settings,
150
- )
230
+ from flowent.settings import get_settings, save_settings
151
231
 
152
232
  action = args.get("action")
153
- assistant_role_name = args.get("assistant_role_name")
154
- assistant_allow_network = args.get("assistant_allow_network")
155
- assistant_write_dirs = args.get("assistant_write_dirs")
156
- working_dir = args.get("working_dir")
157
- leader_role_name = args.get("leader_role_name")
158
- active_provider_id = args.get("active_provider_id")
159
- active_model = args.get("active_model")
160
- timeout_ms = args.get("timeout_ms")
161
- retry_policy = args.get("retry_policy")
162
- max_retries = args.get("max_retries")
163
- retry_initial_delay_seconds = args.get("retry_initial_delay_seconds")
164
- retry_max_delay_seconds = args.get("retry_max_delay_seconds")
165
- retry_backoff_cap_retries = args.get("retry_backoff_cap_retries")
166
- context_window_tokens = args.get("context_window_tokens")
167
- input_image = args.get("input_image")
168
- output_image = args.get("output_image")
169
- structured_output = args.get("structured_output")
170
- auto_compact_token_limit = args.get("auto_compact_token_limit")
171
- model_params = args.get("model_params")
172
- timestamp_format = args.get("timestamp_format")
173
-
174
- if not isinstance(action, str):
175
- return json.dumps({"error": "action must be a string"})
176
-
177
- if assistant_role_name is not None and not isinstance(assistant_role_name, str):
178
- return json.dumps({"error": "assistant_role_name must be a string"})
179
- if assistant_allow_network is not None and not isinstance(
180
- assistant_allow_network, bool
181
- ):
182
- return json.dumps({"error": "assistant_allow_network must be a boolean"})
183
- if assistant_write_dirs is not None and not isinstance(
184
- assistant_write_dirs, list
185
- ):
186
- return json.dumps(
187
- {"error": "assistant_write_dirs must be an array of strings"}
188
- )
189
- if working_dir is not None and not isinstance(working_dir, str):
190
- return json.dumps({"error": "working_dir must be a string"})
191
- if leader_role_name is not None and not isinstance(leader_role_name, str):
192
- return json.dumps({"error": "leader_role_name must be a string"})
193
- if active_provider_id is not None and not isinstance(active_provider_id, str):
194
- return json.dumps({"error": "active_provider_id must be a string"})
195
- if active_model is not None and not isinstance(active_model, str):
196
- return json.dumps({"error": "active_model must be a string"})
197
- if retry_policy is not None:
198
- try:
199
- build_model_retry_policy(retry_policy, field_name="retry_policy")
200
- except ValueError as exc:
201
- return json.dumps({"error": str(exc)})
202
- if timeout_ms is not None:
203
- try:
204
- build_model_timeout_ms(timeout_ms, field_name="timeout_ms")
205
- except ValueError as exc:
206
- return json.dumps({"error": str(exc)})
207
- if max_retries is not None:
208
- try:
209
- build_model_max_retries(max_retries, field_name="max_retries")
210
- except ValueError as exc:
211
- return json.dumps({"error": str(exc)})
212
- if retry_initial_delay_seconds is not None:
213
- try:
214
- build_model_retry_initial_delay_seconds(
215
- retry_initial_delay_seconds,
216
- field_name="retry_initial_delay_seconds",
217
- )
218
- except ValueError as exc:
219
- return json.dumps({"error": str(exc)})
220
- if retry_max_delay_seconds is not None:
221
- try:
222
- build_model_retry_max_delay_seconds(
223
- retry_max_delay_seconds,
224
- field_name="retry_max_delay_seconds",
225
- )
226
- except ValueError as exc:
227
- return json.dumps({"error": str(exc)})
228
- if retry_backoff_cap_retries is not None:
229
- try:
230
- build_model_retry_backoff_cap_retries(
231
- retry_backoff_cap_retries,
232
- field_name="retry_backoff_cap_retries",
233
- )
234
- except ValueError as exc:
235
- return json.dumps({"error": str(exc)})
236
- if "input_image" in args:
237
- try:
238
- build_model_input_image(input_image, field_name="input_image")
239
- except ValueError as exc:
240
- return json.dumps({"error": str(exc)})
241
- if "output_image" in args:
242
- try:
243
- build_model_output_image(output_image, field_name="output_image")
244
- except ValueError as exc:
245
- return json.dumps({"error": str(exc)})
246
- if "structured_output" in args:
247
- try:
248
- build_model_structured_output(
249
- structured_output,
250
- field_name="structured_output",
251
- )
252
- except ValueError as exc:
253
- return json.dumps({"error": str(exc)})
254
- if "context_window_tokens" in args:
255
- try:
256
- build_model_context_window_tokens(
257
- context_window_tokens,
258
- field_name="context_window_tokens",
259
- )
260
- except ValueError as exc:
261
- return json.dumps({"error": str(exc)})
262
- if "auto_compact_token_limit" in args:
263
- try:
264
- build_model_auto_compact_token_limit(
265
- auto_compact_token_limit,
266
- field_name="auto_compact_token_limit",
267
- )
268
- except ValueError as exc:
269
- return json.dumps({"error": str(exc)})
270
- if model_params is not None and not isinstance(
271
- model_params, (dict, type(None))
272
- ):
273
- return json.dumps({"error": "model_params must be an object or null"})
274
- if timestamp_format is not None and not isinstance(timestamp_format, str):
275
- return json.dumps({"error": "timestamp_format must be a string"})
233
+ validation_error = _validate_manage_settings_args(args)
234
+ if validation_error is not None:
235
+ return _error(validation_error)
276
236
 
277
237
  settings = get_settings()
278
238
 
@@ -280,61 +240,63 @@ class ManageSettingsTool(Tool):
280
240
  return json.dumps(serialize_manage_settings(settings))
281
241
 
282
242
  if action != "update":
283
- return json.dumps({"error": f"Unsupported action: {action}"})
243
+ return _error(f"Unsupported action: {action}")
284
244
 
285
245
  try:
286
246
  resolved = resolve_settings_update(
287
247
  settings,
288
- working_dir=working_dir,
289
- assistant_role_name=assistant_role_name,
248
+ working_dir=args.get("working_dir"),
249
+ assistant_role_name=args.get("assistant_role_name"),
290
250
  assistant_allow_network=(
291
- assistant_allow_network
292
- if assistant_allow_network is not None
251
+ args.get("assistant_allow_network")
252
+ if args.get("assistant_allow_network") is not None
293
253
  else MISSING
294
254
  ),
295
255
  assistant_write_dirs=(
296
- assistant_write_dirs
297
- if assistant_write_dirs is not None
256
+ args.get("assistant_write_dirs")
257
+ if args.get("assistant_write_dirs") is not None
298
258
  else MISSING
299
259
  ),
300
- leader_role_name=leader_role_name,
301
- active_provider_id=active_provider_id,
302
- active_model=active_model,
303
- context_window_tokens=(
304
- context_window_tokens
305
- if "context_window_tokens" in args
260
+ leader_role_name=args.get("leader_role_name"),
261
+ active_provider_id=args.get("active_provider_id"),
262
+ active_model=args.get("active_model"),
263
+ context_window_tokens=_provided(args, "context_window_tokens"),
264
+ input_image=_provided(args, "input_image"),
265
+ output_image=_provided(args, "output_image"),
266
+ structured_output=_provided(args, "structured_output"),
267
+ max_retries=(
268
+ args.get("max_retries")
269
+ if args.get("max_retries") is not None
306
270
  else MISSING
307
271
  ),
308
- input_image=input_image if "input_image" in args else MISSING,
309
- output_image=output_image if "output_image" in args else MISSING,
310
- structured_output=(
311
- structured_output if "structured_output" in args else MISSING
272
+ retry_policy=(
273
+ args.get("retry_policy")
274
+ if args.get("retry_policy") is not None
275
+ else MISSING
276
+ ),
277
+ timeout_ms=(
278
+ args.get("timeout_ms")
279
+ if args.get("timeout_ms") is not None
280
+ else MISSING
312
281
  ),
313
- max_retries=max_retries if max_retries is not None else MISSING,
314
- retry_policy=retry_policy if retry_policy is not None else MISSING,
315
- timeout_ms=timeout_ms if timeout_ms is not None else MISSING,
316
282
  retry_initial_delay_seconds=(
317
- retry_initial_delay_seconds
318
- if retry_initial_delay_seconds is not None
283
+ args.get("retry_initial_delay_seconds")
284
+ if args.get("retry_initial_delay_seconds") is not None
319
285
  else MISSING
320
286
  ),
321
287
  retry_max_delay_seconds=(
322
- retry_max_delay_seconds
323
- if retry_max_delay_seconds is not None
288
+ args.get("retry_max_delay_seconds")
289
+ if args.get("retry_max_delay_seconds") is not None
324
290
  else MISSING
325
291
  ),
326
292
  retry_backoff_cap_retries=(
327
- retry_backoff_cap_retries
328
- if retry_backoff_cap_retries is not None
329
- else MISSING
330
- ),
331
- auto_compact_token_limit=(
332
- auto_compact_token_limit
333
- if "auto_compact_token_limit" in args
293
+ args.get("retry_backoff_cap_retries")
294
+ if args.get("retry_backoff_cap_retries") is not None
334
295
  else MISSING
335
296
  ),
336
- model_params=model_params if "model_params" in args else MISSING,
337
- timestamp_format=timestamp_format,
297
+ auto_compact_token_limit=_provided(args, "auto_compact_token_limit"),
298
+ model_params=_provided(args, "model_params"),
299
+ timestamp_format=args.get("timestamp_format"),
338
300
  assistant_role_field_name="assistant_role_name",
339
301
  assistant_allow_network_field_name="assistant_allow_network",
340
302
  assistant_write_dirs_field_name="assistant_write_dirs",
@@ -353,7 +315,7 @@ class ManageSettingsTool(Tool):
353
315
  auto_compact_token_limit_field_name="auto_compact_token_limit",
354
316
  )
355
317
  except ValueError as exc:
356
- return json.dumps({"error": str(exc)})
318
+ return _error(str(exc))
357
319
 
358
320
  apply_resolved_settings_update(settings, resolved)
359
321