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.
- package/README.md +1 -1
- package/backend/README.md +1 -1
- package/backend/pyproject.toml +1 -1
- package/backend/src/flowent/__pycache__/__init__.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/_version.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/access.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/agent.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/assistant_commands.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/cli.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/config.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/events.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/graph_runtime.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/graph_service.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/image_assets.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/logging.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/main.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/model_metadata.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/network.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/observability_service.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/registry.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/role_management.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/runtime.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/sandbox.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/security.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/settings.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/settings_management.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/state_db.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/workspace_store.cpython-313.pyc +0 -0
- package/backend/src/flowent/agent.py +91 -8
- package/backend/src/flowent/channels/__pycache__/__init__.cpython-313.pyc +0 -0
- package/backend/src/flowent/channels/__pycache__/telegram.cpython-313.pyc +0 -0
- package/backend/src/flowent/graph_service.py +3 -110
- package/backend/src/flowent/models/__pycache__/__init__.cpython-313.pyc +0 -0
- package/backend/src/flowent/models/__pycache__/agent.cpython-313.pyc +0 -0
- package/backend/src/flowent/models/__pycache__/base.cpython-313.pyc +0 -0
- package/backend/src/flowent/models/__pycache__/blueprint.cpython-313.pyc +0 -0
- package/backend/src/flowent/models/__pycache__/content.cpython-313.pyc +0 -0
- package/backend/src/flowent/models/__pycache__/delta.cpython-313.pyc +0 -0
- package/backend/src/flowent/models/__pycache__/event.cpython-313.pyc +0 -0
- package/backend/src/flowent/models/__pycache__/graph.cpython-313.pyc +0 -0
- package/backend/src/flowent/models/__pycache__/history.cpython-313.pyc +0 -0
- package/backend/src/flowent/models/__pycache__/llm.cpython-313.pyc +0 -0
- package/backend/src/flowent/models/__pycache__/message.cpython-313.pyc +0 -0
- package/backend/src/flowent/models/__pycache__/tab.cpython-313.pyc +0 -0
- package/backend/src/flowent/models/__pycache__/todo.cpython-313.pyc +0 -0
- package/backend/src/flowent/prompts/__pycache__/__init__.cpython-313.pyc +0 -0
- package/backend/src/flowent/prompts/__pycache__/common.cpython-313.pyc +0 -0
- package/backend/src/flowent/prompts/__pycache__/steward.cpython-313.pyc +0 -0
- package/backend/src/flowent/providers/__pycache__/__init__.cpython-313.pyc +0 -0
- package/backend/src/flowent/providers/__pycache__/anthropic.cpython-313.pyc +0 -0
- package/backend/src/flowent/providers/__pycache__/base_url.cpython-313.pyc +0 -0
- package/backend/src/flowent/providers/__pycache__/configuration.cpython-313.pyc +0 -0
- package/backend/src/flowent/providers/__pycache__/content.cpython-313.pyc +0 -0
- package/backend/src/flowent/providers/__pycache__/errors.cpython-313.pyc +0 -0
- package/backend/src/flowent/providers/__pycache__/gateway.cpython-313.pyc +0 -0
- package/backend/src/flowent/providers/__pycache__/headers.cpython-313.pyc +0 -0
- package/backend/src/flowent/providers/__pycache__/management.cpython-313.pyc +0 -0
- package/backend/src/flowent/providers/__pycache__/openai.cpython-313.pyc +0 -0
- package/backend/src/flowent/providers/__pycache__/openai_responses.cpython-313.pyc +0 -0
- package/backend/src/flowent/providers/__pycache__/registry.cpython-313.pyc +0 -0
- package/backend/src/flowent/providers/__pycache__/sse.cpython-313.pyc +0 -0
- package/backend/src/flowent/providers/__pycache__/thinking.cpython-313.pyc +0 -0
- package/backend/src/flowent/role_management.py +9 -6
- package/backend/src/flowent/routes/__init__.py +0 -2
- package/backend/src/flowent/routes/__pycache__/__init__.cpython-313.pyc +0 -0
- package/backend/src/flowent/routes/__pycache__/access.cpython-313.pyc +0 -0
- package/backend/src/flowent/routes/__pycache__/assistant.cpython-313.pyc +0 -0
- package/backend/src/flowent/routes/__pycache__/image_assets.cpython-313.pyc +0 -0
- package/backend/src/flowent/routes/__pycache__/meta.cpython-313.pyc +0 -0
- package/backend/src/flowent/routes/__pycache__/nodes.cpython-313.pyc +0 -0
- package/backend/src/flowent/routes/__pycache__/prompts.cpython-313.pyc +0 -0
- package/backend/src/flowent/routes/__pycache__/providers_route.cpython-313.pyc +0 -0
- package/backend/src/flowent/routes/__pycache__/roles.cpython-313.pyc +0 -0
- package/backend/src/flowent/routes/__pycache__/settings.cpython-313.pyc +0 -0
- package/backend/src/flowent/routes/__pycache__/tabs.cpython-313.pyc +0 -0
- package/backend/src/flowent/routes/__pycache__/ws.cpython-313.pyc +0 -0
- package/backend/src/flowent/routes/assistant.py +3 -0
- package/backend/src/flowent/routes/nodes.py +11 -1
- package/backend/src/flowent/routes/settings.py +169 -118
- package/backend/src/flowent/routes/tabs.py +0 -12
- package/backend/src/flowent/runtime.py +0 -5
- package/backend/src/flowent/security.py +1 -21
- package/backend/src/flowent/settings.py +15 -421
- package/backend/src/flowent/settings_management.py +260 -164
- package/backend/src/flowent/state_db.py +2 -14
- package/backend/src/flowent/static/assets/AssistantPage-BW7XAd9I.js +1 -0
- package/backend/src/flowent/static/assets/ChannelsPage-tCJHgt6m.js +1 -0
- package/backend/src/flowent/static/assets/{PageScaffold-DteOA8V7.js → PageScaffold-f6g2l7XN.js} +1 -1
- package/backend/src/flowent/static/assets/PromptsPage-C3Sxn2D7.js +1 -0
- package/backend/src/flowent/static/assets/ProvidersPage-BfmdXmNt.js +3 -0
- package/backend/src/flowent/static/assets/RolesPage-DET8wO4r.js +1 -0
- package/backend/src/flowent/static/assets/SettingsPage-D-g3deMm.js +3 -0
- package/backend/src/flowent/static/assets/ToolsPage-CDmtE2g4.js +1 -0
- package/backend/src/flowent/static/assets/WorkspacePage-AZsJ0sD0.js +3 -0
- package/backend/src/flowent/static/assets/WorkspacePanels-CteCjolX.js +1 -0
- package/backend/src/flowent/static/assets/{alert-dialog-DIBUCmqM.js → alert-dialog-Duorp_S-.js} +1 -1
- package/backend/src/flowent/static/assets/{dialog-BOvHIBrg.js → dialog-C3ixjGjN.js} +1 -1
- package/backend/src/flowent/static/assets/index--o_0fv0N.css +1 -0
- package/backend/src/flowent/static/assets/index-C9HuekJm.js +10 -0
- package/backend/src/flowent/static/assets/{modelParams-DcEhGnu0.js → modelParams-DmnF2hwR.js} +1 -1
- package/backend/src/flowent/static/assets/providerTypes-DT3Ahwl_.js +1 -0
- package/backend/src/flowent/static/assets/roles-CuRT_chR.js +1 -0
- package/{dist/frontend/assets/select-D9SwnlXF.js → backend/src/flowent/static/assets/select-DCfeNu-F.js} +1 -1
- package/backend/src/flowent/static/assets/surface-pWwG5ogx.js +1 -0
- package/backend/src/flowent/static/assets/{ui-vendor-UazN8rcv.js → ui-vendor-C5pJa8N7.js} +15 -15
- package/backend/src/flowent/static/assets/useAppRoute-FgSHBKhV.js +1 -0
- package/backend/src/flowent/static/index.html +3 -3
- package/backend/src/flowent/tools/__init__.py +2 -101
- package/backend/src/flowent/tools/__pycache__/__init__.cpython-313.pyc +0 -0
- package/backend/src/flowent/tools/__pycache__/connect.cpython-313.pyc +0 -0
- package/backend/src/flowent/tools/__pycache__/contacts.cpython-313.pyc +0 -0
- package/backend/src/flowent/tools/__pycache__/create_agent.cpython-313.pyc +0 -0
- package/backend/src/flowent/tools/__pycache__/create_tab.cpython-313.pyc +0 -0
- package/backend/src/flowent/tools/__pycache__/delete_tab.cpython-313.pyc +0 -0
- package/backend/src/flowent/tools/__pycache__/edit.cpython-313.pyc +0 -0
- package/backend/src/flowent/tools/__pycache__/exec.cpython-313.pyc +0 -0
- package/backend/src/flowent/tools/__pycache__/fetch.cpython-313.pyc +0 -0
- package/backend/src/flowent/tools/__pycache__/idle.cpython-313.pyc +0 -0
- package/backend/src/flowent/tools/__pycache__/list_roles.cpython-313.pyc +0 -0
- package/backend/src/flowent/tools/__pycache__/list_tabs.cpython-313.pyc +0 -0
- package/backend/src/flowent/tools/__pycache__/list_tools.cpython-313.pyc +0 -0
- package/backend/src/flowent/tools/__pycache__/manage_prompts.cpython-313.pyc +0 -0
- package/backend/src/flowent/tools/__pycache__/manage_providers.cpython-313.pyc +0 -0
- package/backend/src/flowent/tools/__pycache__/manage_roles.cpython-313.pyc +0 -0
- package/backend/src/flowent/tools/__pycache__/manage_settings.cpython-313.pyc +0 -0
- package/backend/src/flowent/tools/__pycache__/read.cpython-313.pyc +0 -0
- package/backend/src/flowent/tools/__pycache__/send.cpython-313.pyc +0 -0
- package/backend/src/flowent/tools/__pycache__/set_permissions.cpython-313.pyc +0 -0
- package/backend/src/flowent/tools/__pycache__/sleep.cpython-313.pyc +0 -0
- package/backend/src/flowent/tools/__pycache__/todo.cpython-313.pyc +0 -0
- package/backend/src/flowent/tools/list_roles.py +2 -9
- package/backend/src/flowent/tools/manage_settings.py +134 -172
- package/backend/tests/__pycache__/__init__.cpython-313.pyc +0 -0
- package/backend/tests/__pycache__/conftest.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/integration/api/__pycache__/conftest.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/integration/api/__pycache__/test_access_api.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/integration/api/__pycache__/test_assistant_api.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/integration/api/__pycache__/test_frontend_mounting.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/integration/api/__pycache__/test_meta_api.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/integration/api/__pycache__/test_nodes_api.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/integration/api/__pycache__/test_prompts_api.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/integration/api/__pycache__/test_roles_api.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/integration/api/__pycache__/test_tabs_api.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/integration/api/test_assistant_api.py +68 -0
- package/backend/tests/integration/api/test_meta_api.py +0 -1
- package/backend/tests/integration/api/test_nodes_api.py +73 -8
- package/backend/tests/integration/api/test_tabs_api.py +0 -114
- package/backend/tests/unit/__pycache__/test_access.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/__pycache__/test_cli.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/__pycache__/test_graph_runtime.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/__pycache__/test_network.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/__pycache__/test_state_sqlite_storage.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/__pycache__/test_workspace_store.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/agent/__pycache__/test_agent_public_api.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/agent/__pycache__/test_agent_runtime.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/agent/test_agent_public_api.py +0 -15
- package/backend/tests/unit/agent/test_agent_runtime.py +148 -2
- package/backend/tests/unit/channels/__pycache__/test_telegram_channel.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/logging/__pycache__/test_logging.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/prompts/__pycache__/test_prompts.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/providers/__pycache__/test_anthropic_provider.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/providers/__pycache__/test_errors.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/providers/__pycache__/test_extract_delta_parts.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/providers/__pycache__/test_openai_provider.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/providers/__pycache__/test_openai_responses.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/providers/__pycache__/test_provider_gateway.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/providers/__pycache__/test_think_tag_parser.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/routes/__pycache__/test_prompts_routes.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/routes/__pycache__/test_providers_route.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/routes/__pycache__/test_roles_routes.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/routes/__pycache__/test_settings_routes.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/routes/test_prompts_routes.py +0 -22
- package/backend/tests/unit/routes/test_roles_routes.py +6 -2
- package/backend/tests/unit/routes/test_settings_routes.py +0 -19
- package/backend/tests/unit/runtime/__pycache__/test_bootstrap_runtime.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/sandbox/__pycache__/test_sandbox_tools.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/security/__pycache__/test_security.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/settings/__pycache__/test_settings_roles.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/settings/test_settings_roles.py +3 -51
- package/backend/tests/unit/test_cli.py +0 -22
- package/backend/tests/unit/test_state_sqlite_storage.py +27 -99
- package/backend/tests/unit/test_workspace_store.py +0 -3
- package/backend/tests/unit/tools/__pycache__/test_connect_tool.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/tools/__pycache__/test_create_agent_tool.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/tools/__pycache__/test_delete_tab_tool.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/tools/__pycache__/test_edit_tool.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/tools/__pycache__/test_exec_tool.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/tools/__pycache__/test_fetch_tool.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/tools/__pycache__/test_manage_prompts_tool.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/tools/__pycache__/test_manage_providers_tool.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/tools/__pycache__/test_manage_roles_tool.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/tools/__pycache__/test_manage_settings_tool.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/tools/__pycache__/test_read_tool.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/tools/__pycache__/test_set_permissions_tool.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/tools/__pycache__/test_todo_tool.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/tools/__pycache__/test_tool_registry.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/tools/test_create_agent_tool.py +0 -32
- package/backend/tests/unit/tools/test_manage_prompts_tool.py +5 -30
- package/backend/tests/unit/tools/test_tool_registry.py +45 -40
- package/backend/uv.lock +1 -1
- package/dist/frontend/assets/AssistantPage-BW7XAd9I.js +1 -0
- package/dist/frontend/assets/ChannelsPage-tCJHgt6m.js +1 -0
- package/dist/frontend/assets/{PageScaffold-DteOA8V7.js → PageScaffold-f6g2l7XN.js} +1 -1
- package/dist/frontend/assets/PromptsPage-C3Sxn2D7.js +1 -0
- package/dist/frontend/assets/ProvidersPage-BfmdXmNt.js +3 -0
- package/dist/frontend/assets/RolesPage-DET8wO4r.js +1 -0
- package/dist/frontend/assets/SettingsPage-D-g3deMm.js +3 -0
- package/dist/frontend/assets/ToolsPage-CDmtE2g4.js +1 -0
- package/dist/frontend/assets/WorkspacePage-AZsJ0sD0.js +3 -0
- package/dist/frontend/assets/WorkspacePanels-CteCjolX.js +1 -0
- package/dist/frontend/assets/{alert-dialog-DIBUCmqM.js → alert-dialog-Duorp_S-.js} +1 -1
- package/dist/frontend/assets/{dialog-BOvHIBrg.js → dialog-C3ixjGjN.js} +1 -1
- package/dist/frontend/assets/index--o_0fv0N.css +1 -0
- package/dist/frontend/assets/index-C9HuekJm.js +10 -0
- package/dist/frontend/assets/{modelParams-DcEhGnu0.js → modelParams-DmnF2hwR.js} +1 -1
- package/dist/frontend/assets/providerTypes-DT3Ahwl_.js +1 -0
- package/dist/frontend/assets/roles-CuRT_chR.js +1 -0
- package/{backend/src/flowent/static/assets/select-D9SwnlXF.js → dist/frontend/assets/select-DCfeNu-F.js} +1 -1
- package/dist/frontend/assets/surface-pWwG5ogx.js +1 -0
- package/dist/frontend/assets/{ui-vendor-UazN8rcv.js → ui-vendor-C5pJa8N7.js} +15 -15
- package/dist/frontend/assets/useAppRoute-FgSHBKhV.js +1 -0
- package/dist/frontend/index.html +3 -3
- package/package.json +1 -1
- package/backend/src/flowent/__pycache__/mcp_service.cpython-313.pyc +0 -0
- package/backend/src/flowent/mcp_service.py +0 -1918
- package/backend/src/flowent/routes/__pycache__/mcp.cpython-313.pyc +0 -0
- package/backend/src/flowent/routes/mcp.py +0 -125
- package/backend/src/flowent/static/assets/AssistantPage-VBohhz4d.js +0 -1
- package/backend/src/flowent/static/assets/ChannelsPage-CIydPZA_.js +0 -1
- package/backend/src/flowent/static/assets/McpPage-CHPm2TPY.js +0 -7
- package/backend/src/flowent/static/assets/PromptsPage-CSmJ3sZg.js +0 -1
- package/backend/src/flowent/static/assets/ProvidersPage-sl2jeG4e.js +0 -3
- package/backend/src/flowent/static/assets/RolesPage-DCe7W6Km.js +0 -1
- package/backend/src/flowent/static/assets/SettingsPage-Bix9e63E.js +0 -3
- package/backend/src/flowent/static/assets/ToolsPage-favNkj5C.js +0 -1
- package/backend/src/flowent/static/assets/WorkspaceCommandDialog-DRS6wiD6.js +0 -1
- package/backend/src/flowent/static/assets/WorkspacePage-KuaDjt_D.js +0 -3
- package/backend/src/flowent/static/assets/WorkspacePanels-BZxBw8M5.js +0 -1
- package/backend/src/flowent/static/assets/datetime-eJqd0V2S.js +0 -1
- package/backend/src/flowent/static/assets/index-Biio-CoI.js +0 -10
- package/backend/src/flowent/static/assets/index-CmQvO7sl.css +0 -1
- package/backend/src/flowent/static/assets/roles-BbIEIMeG.js +0 -1
- package/backend/src/flowent/static/assets/surface-Bzr1FRG4.js +0 -1
- package/backend/src/flowent/static/assets/triState-DgLlKdRR.js +0 -1
- package/backend/src/flowent/tools/__pycache__/mcp.cpython-313.pyc +0 -0
- package/backend/src/flowent/tools/mcp.py +0 -199
- package/backend/tests/integration/api/__pycache__/test_mcp_api.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/integration/api/test_mcp_api.py +0 -116
- package/dist/frontend/assets/AssistantPage-VBohhz4d.js +0 -1
- package/dist/frontend/assets/ChannelsPage-CIydPZA_.js +0 -1
- package/dist/frontend/assets/McpPage-CHPm2TPY.js +0 -7
- package/dist/frontend/assets/PromptsPage-CSmJ3sZg.js +0 -1
- package/dist/frontend/assets/ProvidersPage-sl2jeG4e.js +0 -3
- package/dist/frontend/assets/RolesPage-DCe7W6Km.js +0 -1
- package/dist/frontend/assets/SettingsPage-Bix9e63E.js +0 -3
- package/dist/frontend/assets/ToolsPage-favNkj5C.js +0 -1
- package/dist/frontend/assets/WorkspaceCommandDialog-DRS6wiD6.js +0 -1
- package/dist/frontend/assets/WorkspacePage-KuaDjt_D.js +0 -3
- package/dist/frontend/assets/WorkspacePanels-BZxBw8M5.js +0 -1
- package/dist/frontend/assets/datetime-eJqd0V2S.js +0 -1
- package/dist/frontend/assets/index-Biio-CoI.js +0 -10
- package/dist/frontend/assets/index-CmQvO7sl.css +0 -1
- package/dist/frontend/assets/roles-BbIEIMeG.js +0 -1
- package/dist/frontend/assets/surface-Bzr1FRG4.js +0 -1
- package/dist/frontend/assets/triState-DgLlKdRR.js +0 -1
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import time
|
|
4
4
|
from copy import deepcopy
|
|
5
|
+
from dataclasses import dataclass
|
|
5
6
|
|
|
6
7
|
from fastapi import APIRouter, HTTPException
|
|
7
8
|
from loguru import logger
|
|
@@ -62,77 +63,15 @@ class UpdateTelegramSettingsRequest(BaseModel):
|
|
|
62
63
|
bot_token: str | None = None
|
|
63
64
|
|
|
64
65
|
|
|
65
|
-
@
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
source_settings = get_settings()
|
|
71
|
-
current = deepcopy(source_settings)
|
|
72
|
-
next_access_code: str | None = None
|
|
73
|
-
reauth_required = False
|
|
66
|
+
@dataclass(frozen=True, slots=True)
|
|
67
|
+
class AssistantSettingsPatch:
|
|
68
|
+
role_name: str | None = None
|
|
69
|
+
allow_network: object = MISSING
|
|
70
|
+
write_dirs: object = MISSING
|
|
74
71
|
|
|
75
|
-
if req.access is not None:
|
|
76
|
-
raw_new_code = req.access.get("new_code", "")
|
|
77
|
-
raw_confirm_code = req.access.get("confirm_code", "")
|
|
78
|
-
if raw_new_code is not None and not isinstance(raw_new_code, str):
|
|
79
|
-
raise HTTPException(
|
|
80
|
-
status_code=400, detail="access.new_code must be a string"
|
|
81
|
-
)
|
|
82
|
-
if raw_confirm_code is not None and not isinstance(raw_confirm_code, str):
|
|
83
|
-
raise HTTPException(
|
|
84
|
-
status_code=400,
|
|
85
|
-
detail="access.confirm_code must be a string",
|
|
86
|
-
)
|
|
87
|
-
new_code = raw_new_code if isinstance(raw_new_code, str) else ""
|
|
88
|
-
confirm_code = raw_confirm_code if isinstance(raw_confirm_code, str) else ""
|
|
89
|
-
if new_code or confirm_code:
|
|
90
|
-
if not new_code.strip():
|
|
91
|
-
raise HTTPException(
|
|
92
|
-
status_code=400,
|
|
93
|
-
detail="access.new_code must not be empty",
|
|
94
|
-
)
|
|
95
|
-
if confirm_code != new_code:
|
|
96
|
-
raise HTTPException(
|
|
97
|
-
status_code=400,
|
|
98
|
-
detail="access.confirm_code must match access.new_code",
|
|
99
|
-
)
|
|
100
|
-
next_access_code = new_code
|
|
101
|
-
|
|
102
|
-
assistant_role_name: str | None = None
|
|
103
|
-
assistant_allow_network: object = MISSING
|
|
104
|
-
assistant_write_dirs: object = MISSING
|
|
105
|
-
if req.assistant is not None:
|
|
106
|
-
assistant_unknown_fields = sorted(
|
|
107
|
-
set(req.assistant) - {"role_name", "allow_network", "write_dirs"}
|
|
108
|
-
)
|
|
109
|
-
if assistant_unknown_fields:
|
|
110
|
-
raise HTTPException(
|
|
111
|
-
status_code=400,
|
|
112
|
-
detail=(
|
|
113
|
-
"Unknown assistant fields: " + ", ".join(assistant_unknown_fields)
|
|
114
|
-
),
|
|
115
|
-
)
|
|
116
|
-
if "allow_network" in req.assistant:
|
|
117
|
-
assistant_allow_network = req.assistant.get("allow_network")
|
|
118
|
-
if "write_dirs" in req.assistant:
|
|
119
|
-
assistant_write_dirs = req.assistant.get("write_dirs")
|
|
120
|
-
raw_role_name = req.assistant.get("role_name")
|
|
121
|
-
if isinstance(raw_role_name, str) and raw_role_name.strip():
|
|
122
|
-
assistant_role_name = raw_role_name
|
|
123
|
-
|
|
124
|
-
leader_role_name: str | None = None
|
|
125
|
-
if req.leader is not None:
|
|
126
|
-
raw_role_name = req.leader.get("role_name")
|
|
127
|
-
if isinstance(raw_role_name, str) and raw_role_name.strip():
|
|
128
|
-
leader_role_name = raw_role_name
|
|
129
|
-
|
|
130
|
-
timestamp_format: str | None = None
|
|
131
|
-
if req.event_log is not None:
|
|
132
|
-
raw_timestamp_format = req.event_log.get("timestamp_format")
|
|
133
|
-
if isinstance(raw_timestamp_format, str):
|
|
134
|
-
timestamp_format = raw_timestamp_format
|
|
135
72
|
|
|
73
|
+
@dataclass(frozen=True, slots=True)
|
|
74
|
+
class ModelSettingsPatch:
|
|
136
75
|
active_provider_id: str | None = None
|
|
137
76
|
active_model: str | None = None
|
|
138
77
|
context_window_tokens: object = MISSING
|
|
@@ -146,61 +85,173 @@ async def update_settings(req: UpdateSettingsRequest) -> dict[str, object]:
|
|
|
146
85
|
retry_max_delay_seconds: object = MISSING
|
|
147
86
|
retry_backoff_cap_retries: object = MISSING
|
|
148
87
|
auto_compact_token_limit: object = MISSING
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
88
|
+
params: object = MISSING
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def _extract_access_code_rotation(access: dict[str, object] | None) -> str | None:
|
|
92
|
+
if access is None:
|
|
93
|
+
return None
|
|
94
|
+
|
|
95
|
+
raw_new_code = access.get("new_code", "")
|
|
96
|
+
raw_confirm_code = access.get("confirm_code", "")
|
|
97
|
+
if raw_new_code is not None and not isinstance(raw_new_code, str):
|
|
98
|
+
raise HTTPException(status_code=400, detail="access.new_code must be a string")
|
|
99
|
+
if raw_confirm_code is not None and not isinstance(raw_confirm_code, str):
|
|
100
|
+
raise HTTPException(
|
|
101
|
+
status_code=400,
|
|
102
|
+
detail="access.confirm_code must be a string",
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
new_code = raw_new_code if isinstance(raw_new_code, str) else ""
|
|
106
|
+
confirm_code = raw_confirm_code if isinstance(raw_confirm_code, str) else ""
|
|
107
|
+
if not new_code and not confirm_code:
|
|
108
|
+
return None
|
|
109
|
+
if not new_code.strip():
|
|
110
|
+
raise HTTPException(
|
|
111
|
+
status_code=400,
|
|
112
|
+
detail="access.new_code must not be empty",
|
|
113
|
+
)
|
|
114
|
+
if confirm_code != new_code:
|
|
115
|
+
raise HTTPException(
|
|
116
|
+
status_code=400,
|
|
117
|
+
detail="access.confirm_code must match access.new_code",
|
|
118
|
+
)
|
|
119
|
+
return new_code
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def _extract_assistant_settings_patch(
|
|
123
|
+
assistant: dict[str, object] | None,
|
|
124
|
+
) -> AssistantSettingsPatch:
|
|
125
|
+
if assistant is None:
|
|
126
|
+
return AssistantSettingsPatch()
|
|
127
|
+
|
|
128
|
+
unknown_fields = sorted(
|
|
129
|
+
set(assistant) - {"role_name", "allow_network", "write_dirs"}
|
|
130
|
+
)
|
|
131
|
+
if unknown_fields:
|
|
132
|
+
raise HTTPException(
|
|
133
|
+
status_code=400,
|
|
134
|
+
detail="Unknown assistant fields: " + ", ".join(unknown_fields),
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
raw_role_name = assistant.get("role_name")
|
|
138
|
+
return AssistantSettingsPatch(
|
|
139
|
+
role_name=(
|
|
140
|
+
raw_role_name
|
|
141
|
+
if isinstance(raw_role_name, str) and raw_role_name.strip()
|
|
142
|
+
else None
|
|
143
|
+
),
|
|
144
|
+
allow_network=(
|
|
145
|
+
assistant.get("allow_network") if "allow_network" in assistant else MISSING
|
|
146
|
+
),
|
|
147
|
+
write_dirs=assistant.get("write_dirs")
|
|
148
|
+
if "write_dirs" in assistant
|
|
149
|
+
else MISSING,
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def _extract_role_name(payload: dict[str, object] | None) -> str | None:
|
|
154
|
+
if payload is None:
|
|
155
|
+
return None
|
|
156
|
+
raw_role_name = payload.get("role_name")
|
|
157
|
+
if isinstance(raw_role_name, str) and raw_role_name.strip():
|
|
158
|
+
return raw_role_name
|
|
159
|
+
return None
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def _extract_timestamp_format(payload: dict[str, object] | None) -> str | None:
|
|
163
|
+
if payload is None:
|
|
164
|
+
return None
|
|
165
|
+
raw_timestamp_format = payload.get("timestamp_format")
|
|
166
|
+
return raw_timestamp_format if isinstance(raw_timestamp_format, str) else None
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def _extract_model_settings_patch(
|
|
170
|
+
model: dict[str, object] | None,
|
|
171
|
+
) -> ModelSettingsPatch:
|
|
172
|
+
if model is None:
|
|
173
|
+
return ModelSettingsPatch()
|
|
174
|
+
|
|
175
|
+
raw_active_provider_id = model.get("active_provider_id")
|
|
176
|
+
raw_active_model = model.get("active_model")
|
|
177
|
+
return ModelSettingsPatch(
|
|
178
|
+
active_provider_id=(
|
|
179
|
+
raw_active_provider_id if isinstance(raw_active_provider_id, str) else None
|
|
180
|
+
),
|
|
181
|
+
active_model=raw_active_model if isinstance(raw_active_model, str) else None,
|
|
182
|
+
context_window_tokens=(
|
|
183
|
+
model.get("context_window_tokens")
|
|
184
|
+
if "context_window_tokens" in model
|
|
185
|
+
else MISSING
|
|
186
|
+
),
|
|
187
|
+
input_image=model.get("input_image") if "input_image" in model else MISSING,
|
|
188
|
+
output_image=model.get("output_image") if "output_image" in model else MISSING,
|
|
189
|
+
structured_output=(
|
|
190
|
+
model.get("structured_output") if "structured_output" in model else MISSING
|
|
191
|
+
),
|
|
192
|
+
timeout_ms=model.get("timeout_ms") if "timeout_ms" in model else MISSING,
|
|
193
|
+
retry_policy=model.get("retry_policy") if "retry_policy" in model else MISSING,
|
|
194
|
+
max_retries=model.get("max_retries") if "max_retries" in model else MISSING,
|
|
195
|
+
retry_initial_delay_seconds=(
|
|
196
|
+
model.get("retry_initial_delay_seconds")
|
|
197
|
+
if "retry_initial_delay_seconds" in model
|
|
198
|
+
else MISSING
|
|
199
|
+
),
|
|
200
|
+
retry_max_delay_seconds=(
|
|
201
|
+
model.get("retry_max_delay_seconds")
|
|
202
|
+
if "retry_max_delay_seconds" in model
|
|
203
|
+
else MISSING
|
|
204
|
+
),
|
|
205
|
+
retry_backoff_cap_retries=(
|
|
206
|
+
model.get("retry_backoff_cap_retries")
|
|
207
|
+
if "retry_backoff_cap_retries" in model
|
|
208
|
+
else MISSING
|
|
209
|
+
),
|
|
210
|
+
auto_compact_token_limit=(
|
|
211
|
+
model.get("auto_compact_token_limit")
|
|
212
|
+
if "auto_compact_token_limit" in model
|
|
213
|
+
else MISSING
|
|
214
|
+
),
|
|
215
|
+
params=model.get("params") if "params" in model else MISSING,
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
@router.post("/api/settings")
|
|
220
|
+
async def update_settings(req: UpdateSettingsRequest) -> dict[str, object]:
|
|
221
|
+
from flowent.graph_service import sync_assistant_role, sync_tab_leaders
|
|
222
|
+
from flowent.providers.gateway import gateway
|
|
223
|
+
|
|
224
|
+
source_settings = get_settings()
|
|
225
|
+
current = deepcopy(source_settings)
|
|
226
|
+
next_access_code = _extract_access_code_rotation(req.access)
|
|
227
|
+
reauth_required = False
|
|
228
|
+
assistant_patch = _extract_assistant_settings_patch(req.assistant)
|
|
229
|
+
leader_role_name = _extract_role_name(req.leader)
|
|
230
|
+
timestamp_format = _extract_timestamp_format(req.event_log)
|
|
231
|
+
model_patch = _extract_model_settings_patch(req.model)
|
|
181
232
|
|
|
182
233
|
try:
|
|
183
234
|
resolved = resolve_settings_update(
|
|
184
235
|
current,
|
|
185
236
|
working_dir=req.working_dir,
|
|
186
|
-
assistant_role_name=
|
|
187
|
-
assistant_allow_network=
|
|
188
|
-
assistant_write_dirs=
|
|
237
|
+
assistant_role_name=assistant_patch.role_name,
|
|
238
|
+
assistant_allow_network=assistant_patch.allow_network,
|
|
239
|
+
assistant_write_dirs=assistant_patch.write_dirs,
|
|
189
240
|
leader_role_name=leader_role_name,
|
|
190
|
-
active_provider_id=active_provider_id,
|
|
191
|
-
active_model=active_model,
|
|
192
|
-
context_window_tokens=context_window_tokens,
|
|
193
|
-
input_image=input_image,
|
|
194
|
-
output_image=output_image,
|
|
195
|
-
structured_output=structured_output,
|
|
196
|
-
max_retries=max_retries,
|
|
197
|
-
retry_policy=retry_policy,
|
|
198
|
-
timeout_ms=timeout_ms,
|
|
199
|
-
retry_initial_delay_seconds=retry_initial_delay_seconds,
|
|
200
|
-
retry_max_delay_seconds=retry_max_delay_seconds,
|
|
201
|
-
retry_backoff_cap_retries=retry_backoff_cap_retries,
|
|
202
|
-
auto_compact_token_limit=auto_compact_token_limit,
|
|
203
|
-
model_params=
|
|
241
|
+
active_provider_id=model_patch.active_provider_id,
|
|
242
|
+
active_model=model_patch.active_model,
|
|
243
|
+
context_window_tokens=model_patch.context_window_tokens,
|
|
244
|
+
input_image=model_patch.input_image,
|
|
245
|
+
output_image=model_patch.output_image,
|
|
246
|
+
structured_output=model_patch.structured_output,
|
|
247
|
+
max_retries=model_patch.max_retries,
|
|
248
|
+
retry_policy=model_patch.retry_policy,
|
|
249
|
+
timeout_ms=model_patch.timeout_ms,
|
|
250
|
+
retry_initial_delay_seconds=model_patch.retry_initial_delay_seconds,
|
|
251
|
+
retry_max_delay_seconds=model_patch.retry_max_delay_seconds,
|
|
252
|
+
retry_backoff_cap_retries=model_patch.retry_backoff_cap_retries,
|
|
253
|
+
auto_compact_token_limit=model_patch.auto_compact_token_limit,
|
|
254
|
+
model_params=model_patch.params,
|
|
204
255
|
timestamp_format=timestamp_format,
|
|
205
256
|
)
|
|
206
257
|
except ValueError as exc:
|
|
@@ -13,7 +13,6 @@ from flowent.graph_service import (
|
|
|
13
13
|
delete_agent_node,
|
|
14
14
|
delete_edge,
|
|
15
15
|
delete_tab,
|
|
16
|
-
duplicate_tab,
|
|
17
16
|
list_node_connection_ids,
|
|
18
17
|
list_tab_edges,
|
|
19
18
|
list_workflow_nodes,
|
|
@@ -125,17 +124,6 @@ async def create_workflow_route(req: CreateTabRequest) -> dict[str, object]:
|
|
|
125
124
|
return serialize_tab_summary(tab)
|
|
126
125
|
|
|
127
126
|
|
|
128
|
-
@router.post("/api/workflows/{tab_id}/duplicate")
|
|
129
|
-
async def duplicate_workflow_route(tab_id: str) -> dict[str, object]:
|
|
130
|
-
duplicated, error = duplicate_tab(tab_id=tab_id)
|
|
131
|
-
if error is not None or duplicated is None:
|
|
132
|
-
raise HTTPException(
|
|
133
|
-
status_code=404 if error and error.endswith("not found") else 400,
|
|
134
|
-
detail=error or "Failed to duplicate workflow",
|
|
135
|
-
)
|
|
136
|
-
return serialize_tab_summary(duplicated)
|
|
137
|
-
|
|
138
|
-
|
|
139
127
|
@router.post("/api/workflows/{tab_id}/activate")
|
|
140
128
|
async def activate_workflow_route(tab_id: str) -> dict[str, object]:
|
|
141
129
|
updated, errors, error = activate_tab(tab_id=tab_id, actor_id=tab_id)
|
|
@@ -50,7 +50,6 @@ def bootstrap_runtime() -> None:
|
|
|
50
50
|
ensure_tab_leaders,
|
|
51
51
|
resolve_effective_permissions_for_node_record,
|
|
52
52
|
)
|
|
53
|
-
from flowent.mcp_service import mcp_service
|
|
54
53
|
from flowent.models import AgentState, NodeConfig, NodeType
|
|
55
54
|
from flowent.settings import (
|
|
56
55
|
ensure_builtin_roles,
|
|
@@ -60,13 +59,11 @@ def bootstrap_runtime() -> None:
|
|
|
60
59
|
from flowent.workspace_store import workspace_store
|
|
61
60
|
|
|
62
61
|
workspace_store.reset_cache()
|
|
63
|
-
mcp_service.clear_runtime_state()
|
|
64
62
|
settings = get_settings()
|
|
65
63
|
settings_changed = ensure_builtin_roles(settings)
|
|
66
64
|
generated_access_code = ensure_access_bootstrap(settings)
|
|
67
65
|
if settings_changed or generated_access_code is not None:
|
|
68
66
|
save_settings(settings)
|
|
69
|
-
mcp_service.bootstrap()
|
|
70
67
|
assistant_tools = build_assistant_tools(settings=settings)
|
|
71
68
|
|
|
72
69
|
assistant_record = next(
|
|
@@ -146,12 +143,10 @@ def bootstrap_runtime() -> None:
|
|
|
146
143
|
|
|
147
144
|
|
|
148
145
|
def shutdown_runtime(timeout: float = SYSTEM_NODE_TIMEOUT) -> None:
|
|
149
|
-
from flowent.mcp_service import mcp_service
|
|
150
146
|
from flowent.models import NodeType
|
|
151
147
|
|
|
152
148
|
logger.info("Shutting down runtime")
|
|
153
149
|
_stop_telegram_channel()
|
|
154
|
-
mcp_service.clear_runtime_state()
|
|
155
150
|
persistent_agents = []
|
|
156
151
|
for agent in registry.get_all():
|
|
157
152
|
if agent.node_type == NodeType.ASSISTANT or agent.config.tab_id:
|
|
@@ -12,7 +12,6 @@ def authorize(tool_name: str, agent: Agent, args: dict[str, Any]) -> str | None:
|
|
|
12
12
|
from flowent.graph_service import resolve_effective_permissions_for_agent
|
|
13
13
|
from flowent.models import NodeType
|
|
14
14
|
from flowent.tools import (
|
|
15
|
-
is_assistant_only_mcp_tool_name,
|
|
16
15
|
is_assistant_only_tool_name,
|
|
17
16
|
)
|
|
18
17
|
|
|
@@ -22,26 +21,7 @@ def authorize(tool_name: str, agent: Agent, args: dict[str, Any]) -> str | None:
|
|
|
22
21
|
allow_network, write_dirs = resolve_effective_permissions_for_agent(agent)
|
|
23
22
|
|
|
24
23
|
if tool_name.startswith("mcp__"):
|
|
25
|
-
|
|
26
|
-
from flowent.settings import find_mcp_server, get_settings
|
|
27
|
-
|
|
28
|
-
descriptor = mcp_service.get_dynamic_tool_descriptor(tool_name)
|
|
29
|
-
if descriptor is None:
|
|
30
|
-
return f"MCP tool not found: {tool_name}"
|
|
31
|
-
if agent.node_type != NodeType.ASSISTANT and is_assistant_only_mcp_tool_name(
|
|
32
|
-
descriptor.tool_name
|
|
33
|
-
):
|
|
34
|
-
return "Ask the Assistant to manage workflows or settings"
|
|
35
|
-
server = find_mcp_server(get_settings(), descriptor.server_name)
|
|
36
|
-
if (
|
|
37
|
-
server is not None
|
|
38
|
-
and server.transport == "streamable_http"
|
|
39
|
-
and not allow_network
|
|
40
|
-
):
|
|
41
|
-
return "Network access is disabled for this workflow"
|
|
42
|
-
if descriptor.open_world_hint and not allow_network:
|
|
43
|
-
return "Network access is disabled for this workflow"
|
|
44
|
-
return None
|
|
24
|
+
return f"Tool not found: {tool_name}"
|
|
45
25
|
|
|
46
26
|
if tool_name == "edit":
|
|
47
27
|
if not write_dirs:
|