flowent 0.0.7 → 0.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -3
- package/backend/README.md +0 -3
- package/backend/pyproject.toml +2 -8
- package/backend/src/flowent/__pycache__/__init__.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/agent.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/cli.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/context.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/llm.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__/patch.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/paths.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/sandbox.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/storage.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/tools.cpython-313.pyc +0 -0
- package/backend/src/flowent/agent.py +213 -3173
- package/backend/src/flowent/cli.py +19 -24
- package/backend/src/flowent/context.py +127 -0
- package/backend/src/flowent/llm.py +256 -0
- package/backend/src/flowent/logging.py +170 -129
- package/backend/src/flowent/main.py +321 -70
- package/backend/src/flowent/patch.py +182 -0
- package/backend/src/flowent/paths.py +11 -0
- package/backend/src/flowent/sandbox.py +214 -40
- package/backend/src/flowent/static/assets/geist-cyrillic-wght-normal-CHSlOQsW.woff2 +0 -0
- package/backend/src/flowent/static/assets/geist-latin-ext-wght-normal-DMtmJ5ZE.woff2 +0 -0
- package/backend/src/flowent/static/assets/geist-latin-wght-normal-Dm3htQBi.woff2 +0 -0
- package/backend/src/flowent/static/assets/index-C76K95ty.js +81 -0
- package/backend/src/flowent/static/assets/index-iUMNKvlU.css +2 -0
- package/backend/src/flowent/static/flowent.png +0 -0
- package/backend/src/flowent/static/index.html +5 -25
- package/backend/src/flowent/storage.py +302 -0
- package/backend/src/flowent/tools.py +364 -0
- package/backend/tests/__pycache__/test_agent_tools.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/__pycache__/test_health.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/__pycache__/test_llm_providers.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/__pycache__/test_logging.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/__pycache__/test_persistence.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/__pycache__/test_workspace_chat.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/test_agent_tools.py +449 -0
- package/backend/tests/test_health.py +12 -0
- package/backend/tests/test_llm_providers.py +113 -0
- package/backend/tests/test_logging.py +182 -0
- package/backend/tests/test_persistence.py +125 -0
- package/backend/tests/test_workspace_chat.py +578 -0
- package/backend/uv.lock +803 -99
- package/dist/frontend/assets/geist-cyrillic-wght-normal-CHSlOQsW.woff2 +0 -0
- package/dist/frontend/assets/geist-latin-ext-wght-normal-DMtmJ5ZE.woff2 +0 -0
- package/dist/frontend/assets/geist-latin-wght-normal-Dm3htQBi.woff2 +0 -0
- package/dist/frontend/assets/index-C76K95ty.js +81 -0
- package/dist/frontend/assets/index-iUMNKvlU.css +2 -0
- package/dist/frontend/flowent.png +0 -0
- package/dist/frontend/index.html +5 -25
- package/package.json +1 -2
- 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__/assistant_commands.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__/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__/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/access.py +0 -247
- package/backend/src/flowent/assistant_commands.py +0 -115
- package/backend/src/flowent/channels/__init__.py +0 -3
- 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/channels/telegram.py +0 -615
- package/backend/src/flowent/config.py +0 -14
- package/backend/src/flowent/dev.py +0 -3
- package/backend/src/flowent/events.py +0 -157
- package/backend/src/flowent/graph_runtime.py +0 -60
- package/backend/src/flowent/graph_service.py +0 -2401
- package/backend/src/flowent/image_assets.py +0 -356
- package/backend/src/flowent/model_metadata.py +0 -102
- package/backend/src/flowent/models/__init__.py +0 -125
- 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/models/agent.py +0 -34
- package/backend/src/flowent/models/base.py +0 -24
- package/backend/src/flowent/models/blueprint.py +0 -176
- package/backend/src/flowent/models/content.py +0 -164
- package/backend/src/flowent/models/delta.py +0 -44
- package/backend/src/flowent/models/event.py +0 -51
- package/backend/src/flowent/models/graph.py +0 -472
- package/backend/src/flowent/models/history.py +0 -272
- package/backend/src/flowent/models/llm.py +0 -62
- package/backend/src/flowent/models/message.py +0 -33
- package/backend/src/flowent/models/tab.py +0 -85
- package/backend/src/flowent/models/todo.py +0 -10
- package/backend/src/flowent/network.py +0 -146
- package/backend/src/flowent/observability_service.py +0 -218
- package/backend/src/flowent/prompts/__init__.py +0 -67
- 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/prompts/common.py +0 -250
- package/backend/src/flowent/prompts/steward.py +0 -64
- package/backend/src/flowent/providers/__init__.py +0 -23
- 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/providers/anthropic.py +0 -468
- package/backend/src/flowent/providers/base_url.py +0 -60
- package/backend/src/flowent/providers/configuration.py +0 -189
- package/backend/src/flowent/providers/content.py +0 -122
- package/backend/src/flowent/providers/errors.py +0 -223
- package/backend/src/flowent/providers/gateway.py +0 -169
- package/backend/src/flowent/providers/gemini.py +0 -447
- package/backend/src/flowent/providers/headers.py +0 -20
- package/backend/src/flowent/providers/management.py +0 -96
- package/backend/src/flowent/providers/ollama.py +0 -293
- package/backend/src/flowent/providers/openai.py +0 -422
- package/backend/src/flowent/providers/openai_responses.py +0 -655
- package/backend/src/flowent/providers/registry.py +0 -144
- package/backend/src/flowent/providers/sse.py +0 -31
- package/backend/src/flowent/providers/thinking.py +0 -79
- package/backend/src/flowent/registry.py +0 -73
- package/backend/src/flowent/role_management.py +0 -270
- package/backend/src/flowent/routes/__init__.py +0 -26
- 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/access.py +0 -48
- package/backend/src/flowent/routes/assistant.py +0 -158
- package/backend/src/flowent/routes/image_assets.py +0 -33
- package/backend/src/flowent/routes/meta.py +0 -28
- package/backend/src/flowent/routes/nodes.py +0 -423
- package/backend/src/flowent/routes/prompts.py +0 -46
- package/backend/src/flowent/routes/providers_route.py +0 -365
- package/backend/src/flowent/routes/roles.py +0 -207
- package/backend/src/flowent/routes/settings.py +0 -379
- package/backend/src/flowent/routes/tabs.py +0 -298
- package/backend/src/flowent/routes/ws.py +0 -33
- package/backend/src/flowent/runtime.py +0 -160
- package/backend/src/flowent/security.py +0 -37
- package/backend/src/flowent/settings.py +0 -2112
- package/backend/src/flowent/settings_management.py +0 -394
- package/backend/src/flowent/state_db.py +0 -108
- package/backend/src/flowent/static/assets/AssistantPage-BW7XAd9I.js +0 -1
- package/backend/src/flowent/static/assets/ChannelsPage-tCJHgt6m.js +0 -1
- package/backend/src/flowent/static/assets/PageScaffold-f6g2l7XN.js +0 -1
- package/backend/src/flowent/static/assets/PromptsPage-C3Sxn2D7.js +0 -1
- package/backend/src/flowent/static/assets/ProvidersPage-BfmdXmNt.js +0 -3
- package/backend/src/flowent/static/assets/RolesPage-DET8wO4r.js +0 -1
- package/backend/src/flowent/static/assets/SettingsPage-D-g3deMm.js +0 -3
- package/backend/src/flowent/static/assets/ToolsPage-CDmtE2g4.js +0 -1
- package/backend/src/flowent/static/assets/WorkspacePage-AZsJ0sD0.js +0 -3
- package/backend/src/flowent/static/assets/WorkspacePanels-CteCjolX.js +0 -1
- package/backend/src/flowent/static/assets/alert-dialog-Duorp_S-.js +0 -1
- package/backend/src/flowent/static/assets/dialog-C3ixjGjN.js +0 -1
- package/backend/src/flowent/static/assets/elk-worker.min-C9JGDOE-.js +0 -6312
- package/backend/src/flowent/static/assets/graph-vendor-CHpVij2M.css +0 -1
- package/backend/src/flowent/static/assets/graph-vendor-DRq_-6fV.js +0 -7
- package/backend/src/flowent/static/assets/index--o_0fv0N.css +0 -1
- package/backend/src/flowent/static/assets/index-C9HuekJm.js +0 -10
- package/backend/src/flowent/static/assets/layout.worker-jMHqAFbP.js +0 -24
- package/backend/src/flowent/static/assets/markdown-vendor-C9RtvaJh.js +0 -29
- package/backend/src/flowent/static/assets/modelParams-DmnF2hwR.js +0 -1
- package/backend/src/flowent/static/assets/providerTypes-DT3Ahwl_.js +0 -1
- package/backend/src/flowent/static/assets/react-vendor-mEs_JJxa.js +0 -9
- package/backend/src/flowent/static/assets/roles-CuRT_chR.js +0 -1
- package/backend/src/flowent/static/assets/rolldown-runtime-BYbx6iT9.js +0 -1
- package/backend/src/flowent/static/assets/select-DCfeNu-F.js +0 -1
- package/backend/src/flowent/static/assets/surface-pWwG5ogx.js +0 -1
- package/backend/src/flowent/static/assets/ui-vendor-C5pJa8N7.js +0 -51
- package/backend/src/flowent/static/assets/useAppRoute-FgSHBKhV.js +0 -1
- package/backend/src/flowent/static/favicon.svg +0 -4
- package/backend/src/flowent/tools/__init__.py +0 -176
- 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/connect.py +0 -100
- package/backend/src/flowent/tools/contacts.py +0 -22
- package/backend/src/flowent/tools/create_agent.py +0 -191
- package/backend/src/flowent/tools/create_tab.py +0 -61
- package/backend/src/flowent/tools/delete_tab.py +0 -39
- package/backend/src/flowent/tools/edit.py +0 -142
- package/backend/src/flowent/tools/exec.py +0 -118
- package/backend/src/flowent/tools/fetch.py +0 -85
- package/backend/src/flowent/tools/idle.py +0 -27
- package/backend/src/flowent/tools/list_roles.py +0 -68
- package/backend/src/flowent/tools/list_tabs.py +0 -100
- package/backend/src/flowent/tools/list_tools.py +0 -28
- package/backend/src/flowent/tools/manage_prompts.py +0 -102
- package/backend/src/flowent/tools/manage_providers.py +0 -220
- package/backend/src/flowent/tools/manage_roles.py +0 -275
- package/backend/src/flowent/tools/manage_settings.py +0 -326
- package/backend/src/flowent/tools/read.py +0 -152
- package/backend/src/flowent/tools/send.py +0 -68
- package/backend/src/flowent/tools/set_permissions.py +0 -99
- package/backend/src/flowent/tools/sleep.py +0 -41
- package/backend/src/flowent/tools/todo.py +0 -51
- package/backend/src/flowent/workspace_store.py +0 -479
- package/backend/tests/__init__.py +0 -0
- 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/conftest.py +0 -6
- 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/conftest.py +0 -29
- package/backend/tests/integration/api/test_access_api.py +0 -182
- package/backend/tests/integration/api/test_assistant_api.py +0 -422
- package/backend/tests/integration/api/test_frontend_mounting.py +0 -61
- package/backend/tests/integration/api/test_meta_api.py +0 -32
- package/backend/tests/integration/api/test_nodes_api.py +0 -787
- package/backend/tests/integration/api/test_prompts_api.py +0 -47
- package/backend/tests/integration/api/test_roles_api.py +0 -228
- package/backend/tests/integration/api/test_tabs_api.py +0 -688
- 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 -822
- package/backend/tests/unit/agent/test_agent_runtime.py +0 -3088
- package/backend/tests/unit/channels/__pycache__/test_telegram_channel.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/channels/test_telegram_channel.py +0 -552
- package/backend/tests/unit/logging/__pycache__/test_logging.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/logging/test_logging.py +0 -132
- package/backend/tests/unit/prompts/__pycache__/test_prompts.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/prompts/test_prompts.py +0 -570
- 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/providers/test_anthropic_provider.py +0 -185
- package/backend/tests/unit/providers/test_errors.py +0 -68
- package/backend/tests/unit/providers/test_extract_delta_parts.py +0 -22
- package/backend/tests/unit/providers/test_openai_provider.py +0 -139
- package/backend/tests/unit/providers/test_openai_responses.py +0 -402
- package/backend/tests/unit/providers/test_provider_gateway.py +0 -359
- package/backend/tests/unit/providers/test_think_tag_parser.py +0 -36
- 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 -82
- package/backend/tests/unit/routes/test_providers_route.py +0 -370
- package/backend/tests/unit/routes/test_roles_routes.py +0 -539
- package/backend/tests/unit/routes/test_settings_routes.py +0 -1123
- package/backend/tests/unit/runtime/__pycache__/test_bootstrap_runtime.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/runtime/test_bootstrap_runtime.py +0 -1002
- package/backend/tests/unit/sandbox/__pycache__/test_sandbox_tools.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/sandbox/test_sandbox_tools.py +0 -78
- package/backend/tests/unit/security/__pycache__/test_security.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/security/test_security.py +0 -124
- 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 +0 -703
- package/backend/tests/unit/test_access.py +0 -45
- package/backend/tests/unit/test_cli.py +0 -102
- package/backend/tests/unit/test_graph_runtime.py +0 -72
- package/backend/tests/unit/test_network.py +0 -51
- package/backend/tests/unit/test_state_sqlite_storage.py +0 -87
- package/backend/tests/unit/test_workspace_store.py +0 -228
- 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_connect_tool.py +0 -228
- package/backend/tests/unit/tools/test_create_agent_tool.py +0 -404
- package/backend/tests/unit/tools/test_delete_tab_tool.py +0 -116
- package/backend/tests/unit/tools/test_edit_tool.py +0 -115
- package/backend/tests/unit/tools/test_exec_tool.py +0 -81
- package/backend/tests/unit/tools/test_fetch_tool.py +0 -65
- package/backend/tests/unit/tools/test_manage_prompts_tool.py +0 -92
- package/backend/tests/unit/tools/test_manage_providers_tool.py +0 -460
- package/backend/tests/unit/tools/test_manage_roles_tool.py +0 -411
- package/backend/tests/unit/tools/test_manage_settings_tool.py +0 -611
- package/backend/tests/unit/tools/test_read_tool.py +0 -33
- package/backend/tests/unit/tools/test_set_permissions_tool.py +0 -595
- package/backend/tests/unit/tools/test_todo_tool.py +0 -37
- package/backend/tests/unit/tools/test_tool_registry.py +0 -199
- package/dist/frontend/assets/AssistantPage-BW7XAd9I.js +0 -1
- package/dist/frontend/assets/ChannelsPage-tCJHgt6m.js +0 -1
- package/dist/frontend/assets/PageScaffold-f6g2l7XN.js +0 -1
- package/dist/frontend/assets/PromptsPage-C3Sxn2D7.js +0 -1
- package/dist/frontend/assets/ProvidersPage-BfmdXmNt.js +0 -3
- package/dist/frontend/assets/RolesPage-DET8wO4r.js +0 -1
- package/dist/frontend/assets/SettingsPage-D-g3deMm.js +0 -3
- package/dist/frontend/assets/ToolsPage-CDmtE2g4.js +0 -1
- package/dist/frontend/assets/WorkspacePage-AZsJ0sD0.js +0 -3
- package/dist/frontend/assets/WorkspacePanels-CteCjolX.js +0 -1
- package/dist/frontend/assets/alert-dialog-Duorp_S-.js +0 -1
- package/dist/frontend/assets/dialog-C3ixjGjN.js +0 -1
- package/dist/frontend/assets/elk-worker.min-C9JGDOE-.js +0 -6312
- package/dist/frontend/assets/graph-vendor-CHpVij2M.css +0 -1
- package/dist/frontend/assets/graph-vendor-DRq_-6fV.js +0 -7
- package/dist/frontend/assets/index--o_0fv0N.css +0 -1
- package/dist/frontend/assets/index-C9HuekJm.js +0 -10
- package/dist/frontend/assets/layout.worker-jMHqAFbP.js +0 -24
- package/dist/frontend/assets/markdown-vendor-C9RtvaJh.js +0 -29
- package/dist/frontend/assets/modelParams-DmnF2hwR.js +0 -1
- package/dist/frontend/assets/providerTypes-DT3Ahwl_.js +0 -1
- package/dist/frontend/assets/react-vendor-mEs_JJxa.js +0 -9
- package/dist/frontend/assets/roles-CuRT_chR.js +0 -1
- package/dist/frontend/assets/rolldown-runtime-BYbx6iT9.js +0 -1
- package/dist/frontend/assets/select-DCfeNu-F.js +0 -1
- package/dist/frontend/assets/surface-pWwG5ogx.js +0 -1
- package/dist/frontend/assets/ui-vendor-C5pJa8N7.js +0 -51
- package/dist/frontend/assets/useAppRoute-FgSHBKhV.js +0 -1
- package/dist/frontend/favicon.svg +0 -4
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from enum import StrEnum
|
|
4
|
-
from typing import Protocol
|
|
5
|
-
|
|
6
|
-
from flowent.providers import LLMProvider
|
|
7
|
-
from flowent.providers.base_url import resolve_provider_base_url
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class ProviderType(StrEnum):
|
|
11
|
-
OPENAI_COMPATIBLE = "openai_compatible"
|
|
12
|
-
OPENAI_RESPONSES = "openai_responses"
|
|
13
|
-
ANTHROPIC = "anthropic"
|
|
14
|
-
GEMINI = "gemini"
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
class ProviderFactory(Protocol):
|
|
18
|
-
def __call__(
|
|
19
|
-
self,
|
|
20
|
-
*,
|
|
21
|
-
provider_name: str,
|
|
22
|
-
api_base_url: str,
|
|
23
|
-
api_key: str,
|
|
24
|
-
headers: dict[str, str],
|
|
25
|
-
model: str,
|
|
26
|
-
request_timeout_seconds: float,
|
|
27
|
-
) -> LLMProvider: ...
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
def _build_openai_compatible_provider(
|
|
31
|
-
*,
|
|
32
|
-
provider_name: str,
|
|
33
|
-
api_base_url: str,
|
|
34
|
-
api_key: str,
|
|
35
|
-
headers: dict[str, str],
|
|
36
|
-
model: str,
|
|
37
|
-
request_timeout_seconds: float,
|
|
38
|
-
) -> LLMProvider:
|
|
39
|
-
from flowent.providers.openai import OpenAIProvider
|
|
40
|
-
|
|
41
|
-
return OpenAIProvider(
|
|
42
|
-
provider_name=provider_name,
|
|
43
|
-
api_base_url=api_base_url,
|
|
44
|
-
api_key=api_key,
|
|
45
|
-
headers=headers,
|
|
46
|
-
model=model,
|
|
47
|
-
request_timeout_seconds=request_timeout_seconds,
|
|
48
|
-
)
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
def _build_openai_responses_provider(
|
|
52
|
-
*,
|
|
53
|
-
provider_name: str,
|
|
54
|
-
api_base_url: str,
|
|
55
|
-
api_key: str,
|
|
56
|
-
headers: dict[str, str],
|
|
57
|
-
model: str,
|
|
58
|
-
request_timeout_seconds: float,
|
|
59
|
-
) -> LLMProvider:
|
|
60
|
-
from flowent.providers.openai_responses import OpenAIResponsesProvider
|
|
61
|
-
|
|
62
|
-
return OpenAIResponsesProvider(
|
|
63
|
-
provider_name=provider_name,
|
|
64
|
-
api_base_url=api_base_url,
|
|
65
|
-
api_key=api_key,
|
|
66
|
-
headers=headers,
|
|
67
|
-
model=model,
|
|
68
|
-
request_timeout_seconds=request_timeout_seconds,
|
|
69
|
-
)
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
def _build_anthropic_provider(
|
|
73
|
-
*,
|
|
74
|
-
provider_name: str,
|
|
75
|
-
api_base_url: str,
|
|
76
|
-
api_key: str,
|
|
77
|
-
headers: dict[str, str],
|
|
78
|
-
model: str,
|
|
79
|
-
request_timeout_seconds: float,
|
|
80
|
-
) -> LLMProvider:
|
|
81
|
-
from flowent.providers.anthropic import AnthropicProvider
|
|
82
|
-
|
|
83
|
-
return AnthropicProvider(
|
|
84
|
-
provider_name=provider_name,
|
|
85
|
-
api_base_url=api_base_url,
|
|
86
|
-
api_key=api_key,
|
|
87
|
-
headers=headers,
|
|
88
|
-
model=model,
|
|
89
|
-
request_timeout_seconds=request_timeout_seconds,
|
|
90
|
-
)
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
def _build_gemini_provider(
|
|
94
|
-
*,
|
|
95
|
-
provider_name: str,
|
|
96
|
-
api_base_url: str,
|
|
97
|
-
api_key: str,
|
|
98
|
-
headers: dict[str, str],
|
|
99
|
-
model: str,
|
|
100
|
-
request_timeout_seconds: float,
|
|
101
|
-
) -> LLMProvider:
|
|
102
|
-
from flowent.providers.gemini import GeminiProvider
|
|
103
|
-
|
|
104
|
-
return GeminiProvider(
|
|
105
|
-
provider_name=provider_name,
|
|
106
|
-
api_base_url=api_base_url,
|
|
107
|
-
api_key=api_key,
|
|
108
|
-
headers=headers,
|
|
109
|
-
model=model,
|
|
110
|
-
request_timeout_seconds=request_timeout_seconds,
|
|
111
|
-
)
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
PROVIDER_FACTORIES: dict[ProviderType, ProviderFactory] = {
|
|
115
|
-
ProviderType.OPENAI_COMPATIBLE: _build_openai_compatible_provider,
|
|
116
|
-
ProviderType.OPENAI_RESPONSES: _build_openai_responses_provider,
|
|
117
|
-
ProviderType.ANTHROPIC: _build_anthropic_provider,
|
|
118
|
-
ProviderType.GEMINI: _build_gemini_provider,
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
def create_provider(
|
|
123
|
-
provider_type: str,
|
|
124
|
-
base_url: str,
|
|
125
|
-
api_key: str = "",
|
|
126
|
-
headers: dict[str, str] | None = None,
|
|
127
|
-
model: str = "",
|
|
128
|
-
provider_name: str = "",
|
|
129
|
-
request_timeout_seconds: float = 120.0,
|
|
130
|
-
) -> LLMProvider:
|
|
131
|
-
try:
|
|
132
|
-
normalized_type = ProviderType(provider_type.lower())
|
|
133
|
-
except ValueError as exc:
|
|
134
|
-
raise ValueError(f"Unknown provider type: {provider_type}") from exc
|
|
135
|
-
|
|
136
|
-
resolved_base_url = resolve_provider_base_url(normalized_type, base_url)
|
|
137
|
-
return PROVIDER_FACTORIES[normalized_type](
|
|
138
|
-
provider_name=provider_name,
|
|
139
|
-
api_base_url=resolved_base_url,
|
|
140
|
-
api_key=api_key,
|
|
141
|
-
headers=headers or {},
|
|
142
|
-
model=model,
|
|
143
|
-
request_timeout_seconds=request_timeout_seconds,
|
|
144
|
-
)
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import json
|
|
4
|
-
from collections.abc import Iterator
|
|
5
|
-
from typing import Any
|
|
6
|
-
|
|
7
|
-
from flowent.network import iter_response_lines
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
def iter_sse_data(response: Any) -> Iterator[str]:
|
|
11
|
-
for line in iter_response_lines(response):
|
|
12
|
-
if not line or line.startswith(":"):
|
|
13
|
-
continue
|
|
14
|
-
if not line.startswith("data: "):
|
|
15
|
-
continue
|
|
16
|
-
yield line[6:]
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
def iter_sse_json(
|
|
20
|
-
response: Any,
|
|
21
|
-
done_token: str | None = None,
|
|
22
|
-
) -> Iterator[dict[str, Any]]:
|
|
23
|
-
for payload in iter_sse_data(response):
|
|
24
|
-
if done_token is not None and payload.strip() == done_token:
|
|
25
|
-
break
|
|
26
|
-
try:
|
|
27
|
-
parsed = json.loads(payload)
|
|
28
|
-
except json.JSONDecodeError:
|
|
29
|
-
continue
|
|
30
|
-
if isinstance(parsed, dict):
|
|
31
|
-
yield parsed
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class ThinkTagParser:
|
|
5
|
-
OPEN_TAG = "<think>"
|
|
6
|
-
CLOSE_TAG = "</think>"
|
|
7
|
-
|
|
8
|
-
def __init__(self) -> None:
|
|
9
|
-
self._inside = False
|
|
10
|
-
self._pending = ""
|
|
11
|
-
self._skip_newlines = False
|
|
12
|
-
|
|
13
|
-
def feed(self, text: str) -> list[tuple[str, str]]:
|
|
14
|
-
if self._skip_newlines:
|
|
15
|
-
text = text.lstrip("\n")
|
|
16
|
-
if not text:
|
|
17
|
-
return []
|
|
18
|
-
self._skip_newlines = False
|
|
19
|
-
self._pending += text
|
|
20
|
-
return self._drain()
|
|
21
|
-
|
|
22
|
-
def flush(self) -> list[tuple[str, str]]:
|
|
23
|
-
if not self._pending:
|
|
24
|
-
return []
|
|
25
|
-
chunk_type = "thinking" if self._inside else "content"
|
|
26
|
-
result = [(chunk_type, self._pending)]
|
|
27
|
-
self._pending = ""
|
|
28
|
-
return result
|
|
29
|
-
|
|
30
|
-
def _drain(self) -> list[tuple[str, str]]:
|
|
31
|
-
results: list[tuple[str, str]] = []
|
|
32
|
-
while self._pending:
|
|
33
|
-
tag = self.CLOSE_TAG if self._inside else self.OPEN_TAG
|
|
34
|
-
idx = self._pending.find(tag)
|
|
35
|
-
if idx >= 0:
|
|
36
|
-
before = self._pending[:idx]
|
|
37
|
-
if before:
|
|
38
|
-
chunk_type = "thinking" if self._inside else "content"
|
|
39
|
-
results.append((chunk_type, before))
|
|
40
|
-
self._pending = self._pending[idx + len(tag) :]
|
|
41
|
-
self._inside = not self._inside
|
|
42
|
-
self._pending = self._pending.lstrip("\n")
|
|
43
|
-
if not self._pending:
|
|
44
|
-
self._skip_newlines = True
|
|
45
|
-
continue
|
|
46
|
-
|
|
47
|
-
for n in range(min(len(tag) - 1, len(self._pending)), 0, -1):
|
|
48
|
-
if self._pending.endswith(tag[:n]):
|
|
49
|
-
safe = self._pending[:-n]
|
|
50
|
-
if safe:
|
|
51
|
-
chunk_type = "thinking" if self._inside else "content"
|
|
52
|
-
results.append((chunk_type, safe))
|
|
53
|
-
self._pending = self._pending[-n:]
|
|
54
|
-
return results
|
|
55
|
-
|
|
56
|
-
chunk_type = "thinking" if self._inside else "content"
|
|
57
|
-
results.append((chunk_type, self._pending))
|
|
58
|
-
self._pending = ""
|
|
59
|
-
|
|
60
|
-
return results
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
def split_thinking_content(text: str) -> tuple[str, str]:
|
|
64
|
-
parser = ThinkTagParser()
|
|
65
|
-
chunks = parser.feed(text)
|
|
66
|
-
chunks.extend(parser.flush())
|
|
67
|
-
|
|
68
|
-
content_parts: list[str] = []
|
|
69
|
-
thinking_parts: list[str] = []
|
|
70
|
-
|
|
71
|
-
for chunk_type, chunk_text in chunks:
|
|
72
|
-
if not chunk_text:
|
|
73
|
-
continue
|
|
74
|
-
if chunk_type == "thinking":
|
|
75
|
-
thinking_parts.append(chunk_text)
|
|
76
|
-
else:
|
|
77
|
-
content_parts.append(chunk_text)
|
|
78
|
-
|
|
79
|
-
return "".join(content_parts), "".join(thinking_parts)
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import threading
|
|
4
|
-
from typing import TYPE_CHECKING
|
|
5
|
-
|
|
6
|
-
from loguru import logger
|
|
7
|
-
|
|
8
|
-
from flowent.models import NodeType
|
|
9
|
-
|
|
10
|
-
if TYPE_CHECKING:
|
|
11
|
-
from flowent.agent import Agent
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class AgentRegistry:
|
|
15
|
-
def __init__(self) -> None:
|
|
16
|
-
self._agents: dict[str, Agent] = {}
|
|
17
|
-
self._lock = threading.Lock()
|
|
18
|
-
|
|
19
|
-
def register(self, agent: Agent) -> None:
|
|
20
|
-
with self._lock:
|
|
21
|
-
self._agents[agent.uuid] = agent
|
|
22
|
-
logger.info(
|
|
23
|
-
"Node registered: {} (type={})",
|
|
24
|
-
agent.uuid[:8],
|
|
25
|
-
agent.config.node_type.value,
|
|
26
|
-
)
|
|
27
|
-
|
|
28
|
-
def unregister(self, agent_id: str) -> None:
|
|
29
|
-
with self._lock:
|
|
30
|
-
removed = self._agents.pop(agent_id, None)
|
|
31
|
-
if removed:
|
|
32
|
-
logger.info("Node unregistered: {}", agent_id[:8])
|
|
33
|
-
|
|
34
|
-
def get(self, agent_id: str) -> Agent | None:
|
|
35
|
-
with self._lock:
|
|
36
|
-
return self._agents.get(agent_id)
|
|
37
|
-
|
|
38
|
-
def get_assistant(self) -> Agent | None:
|
|
39
|
-
with self._lock:
|
|
40
|
-
for agent in self._agents.values():
|
|
41
|
-
if agent.node_type == NodeType.ASSISTANT:
|
|
42
|
-
return agent
|
|
43
|
-
return None
|
|
44
|
-
|
|
45
|
-
def find_by_name(self, name: str) -> Agent | None:
|
|
46
|
-
with self._lock:
|
|
47
|
-
matches = [a for a in self._agents.values() if a.config.name == name]
|
|
48
|
-
if len(matches) == 1:
|
|
49
|
-
return matches[0]
|
|
50
|
-
return None
|
|
51
|
-
|
|
52
|
-
def find_by_uuid_prefix(self, prefix: str) -> Agent | None:
|
|
53
|
-
with self._lock:
|
|
54
|
-
matches = [
|
|
55
|
-
agent
|
|
56
|
-
for agent_id, agent in self._agents.items()
|
|
57
|
-
if agent_id.startswith(prefix)
|
|
58
|
-
]
|
|
59
|
-
if len(matches) == 1:
|
|
60
|
-
return matches[0]
|
|
61
|
-
return None
|
|
62
|
-
|
|
63
|
-
def get_all(self) -> list[Agent]:
|
|
64
|
-
with self._lock:
|
|
65
|
-
return list(self._agents.values())
|
|
66
|
-
|
|
67
|
-
def reset(self) -> None:
|
|
68
|
-
with self._lock:
|
|
69
|
-
self._agents.clear()
|
|
70
|
-
logger.debug("Registry reset")
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
registry = AgentRegistry()
|
|
@@ -1,270 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from flowent.settings import (
|
|
4
|
-
ModelParams,
|
|
5
|
-
RoleConfig,
|
|
6
|
-
RoleModelConfig,
|
|
7
|
-
Settings,
|
|
8
|
-
build_model_params_from_mapping,
|
|
9
|
-
clear_role_references,
|
|
10
|
-
find_provider,
|
|
11
|
-
is_builtin_role_name,
|
|
12
|
-
normalize_tool_names,
|
|
13
|
-
rename_role_references,
|
|
14
|
-
validate_role_tool_config,
|
|
15
|
-
)
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
class RoleConflictError(ValueError):
|
|
19
|
-
pass
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
def find_role_by_name(roles: list[RoleConfig], role_name: str) -> RoleConfig | None:
|
|
23
|
-
for role in roles:
|
|
24
|
-
if role.name == role_name:
|
|
25
|
-
return role
|
|
26
|
-
return None
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
def require_role_name(value: str) -> str:
|
|
30
|
-
name = value.strip()
|
|
31
|
-
if not name:
|
|
32
|
-
raise ValueError("Role name is required")
|
|
33
|
-
return name
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
def require_role_description(value: str) -> str:
|
|
37
|
-
description = value.strip()
|
|
38
|
-
if not description:
|
|
39
|
-
raise ValueError("Role description is required")
|
|
40
|
-
return description
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
def normalize_optional_role_name(value: str | None) -> str | None:
|
|
44
|
-
if value is None:
|
|
45
|
-
return None
|
|
46
|
-
return require_role_name(value)
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
def normalize_optional_role_description(value: str | None) -> str | None:
|
|
50
|
-
if value is None:
|
|
51
|
-
return None
|
|
52
|
-
return require_role_description(value)
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
def ensure_role_name_available(
|
|
56
|
-
roles: list[RoleConfig],
|
|
57
|
-
role_name: str,
|
|
58
|
-
*,
|
|
59
|
-
current_name: str | None = None,
|
|
60
|
-
) -> None:
|
|
61
|
-
if any(role.name == role_name and role.name != current_name for role in roles):
|
|
62
|
-
raise RoleConflictError(f"Role '{role_name}' already exists")
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
def resolve_role_tool_config(
|
|
66
|
-
current: RoleConfig | None,
|
|
67
|
-
included_tools: list[str] | None,
|
|
68
|
-
excluded_tools: list[str] | None,
|
|
69
|
-
) -> tuple[list[str], list[str]]:
|
|
70
|
-
from flowent.tools import is_assistant_only_tool_name
|
|
71
|
-
|
|
72
|
-
next_included = normalize_tool_names(
|
|
73
|
-
included_tools
|
|
74
|
-
if included_tools is not None
|
|
75
|
-
else current.included_tools
|
|
76
|
-
if current
|
|
77
|
-
else []
|
|
78
|
-
)
|
|
79
|
-
if included_tools is not None:
|
|
80
|
-
next_included = [
|
|
81
|
-
tool_name
|
|
82
|
-
for tool_name in next_included
|
|
83
|
-
if not tool_name.startswith("mcp__")
|
|
84
|
-
and not is_assistant_only_tool_name(tool_name)
|
|
85
|
-
]
|
|
86
|
-
next_excluded = normalize_tool_names(
|
|
87
|
-
excluded_tools
|
|
88
|
-
if excluded_tools is not None
|
|
89
|
-
else current.excluded_tools
|
|
90
|
-
if current
|
|
91
|
-
else []
|
|
92
|
-
)
|
|
93
|
-
if excluded_tools is not None:
|
|
94
|
-
next_excluded = [
|
|
95
|
-
tool_name
|
|
96
|
-
for tool_name in next_excluded
|
|
97
|
-
if not tool_name.startswith("mcp__")
|
|
98
|
-
]
|
|
99
|
-
validate_role_tool_config(next_included, next_excluded)
|
|
100
|
-
return next_included, next_excluded
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
def resolve_role_model(
|
|
104
|
-
requested: object,
|
|
105
|
-
*,
|
|
106
|
-
settings: Settings,
|
|
107
|
-
current: RoleModelConfig | None,
|
|
108
|
-
provided: bool,
|
|
109
|
-
invalid_type_error: str,
|
|
110
|
-
missing_provider_id_error: str,
|
|
111
|
-
missing_model_error: str,
|
|
112
|
-
) -> RoleModelConfig | None:
|
|
113
|
-
if not provided:
|
|
114
|
-
return current
|
|
115
|
-
if requested is None:
|
|
116
|
-
return None
|
|
117
|
-
|
|
118
|
-
extracted = _extract_role_model_fields(requested)
|
|
119
|
-
if extracted is None:
|
|
120
|
-
raise ValueError(invalid_type_error)
|
|
121
|
-
|
|
122
|
-
provider_id_value, model_value = extracted
|
|
123
|
-
if not isinstance(provider_id_value, str) or not provider_id_value.strip():
|
|
124
|
-
raise ValueError(missing_provider_id_error)
|
|
125
|
-
if not isinstance(model_value, str) or not model_value.strip():
|
|
126
|
-
raise ValueError(missing_model_error)
|
|
127
|
-
|
|
128
|
-
provider_id = provider_id_value.strip()
|
|
129
|
-
model = model_value.strip()
|
|
130
|
-
if find_provider(settings, provider_id) is None:
|
|
131
|
-
raise ValueError(f"Provider '{provider_id}' not found")
|
|
132
|
-
|
|
133
|
-
return RoleModelConfig(provider_id=provider_id, model=model)
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
def resolve_role_model_params(
|
|
137
|
-
requested: object,
|
|
138
|
-
*,
|
|
139
|
-
current: ModelParams | None,
|
|
140
|
-
provided: bool,
|
|
141
|
-
) -> ModelParams | None:
|
|
142
|
-
if not provided:
|
|
143
|
-
return current
|
|
144
|
-
return build_model_params_from_mapping(requested)
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
def validate_builtin_role_update(
|
|
148
|
-
role: RoleConfig,
|
|
149
|
-
*,
|
|
150
|
-
next_name: str | None,
|
|
151
|
-
next_description: str | None,
|
|
152
|
-
next_system_prompt: str | None,
|
|
153
|
-
next_included_tools: list[str],
|
|
154
|
-
next_excluded_tools: list[str],
|
|
155
|
-
) -> None:
|
|
156
|
-
if not is_builtin_role_name(role.name):
|
|
157
|
-
return
|
|
158
|
-
if next_name is not None and next_name != role.name:
|
|
159
|
-
raise ValueError(f"Cannot rename built-in role '{role.name}'")
|
|
160
|
-
if next_description is not None and next_description != role.description:
|
|
161
|
-
raise ValueError(
|
|
162
|
-
f"Cannot modify built-in role '{role.name}' fields other than "
|
|
163
|
-
"model or model_params"
|
|
164
|
-
)
|
|
165
|
-
if next_system_prompt is not None and next_system_prompt != role.system_prompt:
|
|
166
|
-
raise ValueError(
|
|
167
|
-
f"Cannot modify built-in role '{role.name}' fields other than "
|
|
168
|
-
"model or model_params"
|
|
169
|
-
)
|
|
170
|
-
if (
|
|
171
|
-
next_included_tools != role.included_tools
|
|
172
|
-
or next_excluded_tools != role.excluded_tools
|
|
173
|
-
):
|
|
174
|
-
raise ValueError(
|
|
175
|
-
f"Cannot modify built-in role '{role.name}' fields other than "
|
|
176
|
-
"model or model_params"
|
|
177
|
-
)
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
def build_role_config(
|
|
181
|
-
*,
|
|
182
|
-
name: str,
|
|
183
|
-
description: str,
|
|
184
|
-
system_prompt: str,
|
|
185
|
-
model: RoleModelConfig | None,
|
|
186
|
-
model_params: ModelParams | None,
|
|
187
|
-
included_tools: list[str],
|
|
188
|
-
excluded_tools: list[str],
|
|
189
|
-
) -> RoleConfig:
|
|
190
|
-
return RoleConfig(
|
|
191
|
-
name=name,
|
|
192
|
-
description=description,
|
|
193
|
-
system_prompt=system_prompt,
|
|
194
|
-
model=model,
|
|
195
|
-
model_params=model_params,
|
|
196
|
-
included_tools=included_tools,
|
|
197
|
-
excluded_tools=excluded_tools,
|
|
198
|
-
)
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
def apply_role_update(
|
|
202
|
-
*,
|
|
203
|
-
settings: Settings,
|
|
204
|
-
role: RoleConfig,
|
|
205
|
-
next_name: str | None,
|
|
206
|
-
next_description: str | None,
|
|
207
|
-
next_system_prompt: str | None,
|
|
208
|
-
next_model: RoleModelConfig | None,
|
|
209
|
-
update_model: bool,
|
|
210
|
-
next_model_params: ModelParams | None,
|
|
211
|
-
update_model_params: bool,
|
|
212
|
-
next_included_tools: list[str],
|
|
213
|
-
next_excluded_tools: list[str],
|
|
214
|
-
) -> RoleConfig:
|
|
215
|
-
previous_name = role.name
|
|
216
|
-
if next_name is not None:
|
|
217
|
-
role.name = next_name
|
|
218
|
-
rename_role_references(settings, previous_name, role.name)
|
|
219
|
-
if next_description is not None:
|
|
220
|
-
role.description = next_description
|
|
221
|
-
if next_system_prompt is not None:
|
|
222
|
-
role.system_prompt = next_system_prompt
|
|
223
|
-
if update_model:
|
|
224
|
-
role.model = next_model
|
|
225
|
-
if update_model_params:
|
|
226
|
-
role.model_params = next_model_params
|
|
227
|
-
role.included_tools = next_included_tools
|
|
228
|
-
role.excluded_tools = next_excluded_tools
|
|
229
|
-
return role
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
def remove_role(settings: Settings, role: RoleConfig) -> None:
|
|
233
|
-
settings.roles = [existing for existing in settings.roles if existing is not role]
|
|
234
|
-
clear_role_references(settings, role.name)
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
def sync_running_system_roles() -> None:
|
|
238
|
-
from flowent.graph_service import sync_assistant_role, sync_tab_leaders
|
|
239
|
-
|
|
240
|
-
sync_assistant_role(reason="assistant role updated")
|
|
241
|
-
sync_tab_leaders(reason="leader role updated")
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
def _extract_role_model_fields(requested: object) -> tuple[object, object] | None:
|
|
245
|
-
if isinstance(requested, dict):
|
|
246
|
-
return requested.get("provider_id"), requested.get("model")
|
|
247
|
-
provider_id = getattr(requested, "provider_id", None)
|
|
248
|
-
model = getattr(requested, "model", None)
|
|
249
|
-
if provider_id is None and model is None:
|
|
250
|
-
return None
|
|
251
|
-
return provider_id, model
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
__all__ = [
|
|
255
|
-
"RoleConflictError",
|
|
256
|
-
"apply_role_update",
|
|
257
|
-
"build_role_config",
|
|
258
|
-
"ensure_role_name_available",
|
|
259
|
-
"find_role_by_name",
|
|
260
|
-
"normalize_optional_role_description",
|
|
261
|
-
"normalize_optional_role_name",
|
|
262
|
-
"remove_role",
|
|
263
|
-
"require_role_description",
|
|
264
|
-
"require_role_name",
|
|
265
|
-
"resolve_role_model",
|
|
266
|
-
"resolve_role_model_params",
|
|
267
|
-
"resolve_role_tool_config",
|
|
268
|
-
"sync_running_system_roles",
|
|
269
|
-
"validate_builtin_role_update",
|
|
270
|
-
]
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
from fastapi import APIRouter
|
|
2
|
-
|
|
3
|
-
from flowent.routes.access import router as access_router
|
|
4
|
-
from flowent.routes.assistant import router as assistant_router
|
|
5
|
-
from flowent.routes.image_assets import router as image_assets_router
|
|
6
|
-
from flowent.routes.meta import router as meta_router
|
|
7
|
-
from flowent.routes.nodes import router as nodes_router
|
|
8
|
-
from flowent.routes.prompts import router as prompts_router
|
|
9
|
-
from flowent.routes.providers_route import router as providers_router
|
|
10
|
-
from flowent.routes.roles import router as roles_router
|
|
11
|
-
from flowent.routes.settings import router as settings_router
|
|
12
|
-
from flowent.routes.tabs import router as tabs_router
|
|
13
|
-
from flowent.routes.ws import router as ws_router
|
|
14
|
-
|
|
15
|
-
router = APIRouter()
|
|
16
|
-
router.include_router(access_router)
|
|
17
|
-
router.include_router(nodes_router)
|
|
18
|
-
router.include_router(assistant_router)
|
|
19
|
-
router.include_router(image_assets_router)
|
|
20
|
-
router.include_router(roles_router)
|
|
21
|
-
router.include_router(providers_router)
|
|
22
|
-
router.include_router(prompts_router)
|
|
23
|
-
router.include_router(settings_router)
|
|
24
|
-
router.include_router(tabs_router)
|
|
25
|
-
router.include_router(meta_router)
|
|
26
|
-
router.include_router(ws_router)
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|