flowent 0.0.0 → 0.0.4
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 +70 -10
- package/assets/flowent-banner.png +0 -0
- package/backend/.python-version +1 -0
- package/backend/pyproject.toml +57 -0
- package/backend/src/flowent/__init__.py +3 -0
- 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__/mcp_service.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__/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__/stats_service.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/workspace_store.cpython-313.pyc +0 -0
- package/backend/src/flowent/_version.py +7 -0
- package/backend/src/flowent/access.py +247 -0
- package/backend/src/flowent/agent.py +2808 -0
- package/backend/src/flowent/assistant_commands.py +106 -0
- package/backend/src/flowent/channels/__init__.py +3 -0
- 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 +615 -0
- package/backend/src/flowent/cli.py +85 -0
- package/backend/src/flowent/config.py +14 -0
- package/backend/src/flowent/dev.py +3 -0
- package/backend/src/flowent/events.py +157 -0
- package/backend/src/flowent/graph_runtime.py +60 -0
- package/backend/src/flowent/graph_service.py +1346 -0
- package/backend/src/flowent/image_assets.py +356 -0
- package/backend/src/flowent/logging.py +155 -0
- package/backend/src/flowent/main.py +124 -0
- package/backend/src/flowent/mcp_service.py +1904 -0
- package/backend/src/flowent/model_metadata.py +98 -0
- package/backend/src/flowent/models/__init__.py +121 -0
- 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 +33 -0
- package/backend/src/flowent/models/base.py +24 -0
- package/backend/src/flowent/models/blueprint.py +176 -0
- package/backend/src/flowent/models/content.py +164 -0
- package/backend/src/flowent/models/delta.py +44 -0
- package/backend/src/flowent/models/event.py +51 -0
- package/backend/src/flowent/models/graph.py +437 -0
- package/backend/src/flowent/models/history.py +214 -0
- package/backend/src/flowent/models/llm.py +61 -0
- package/backend/src/flowent/models/message.py +27 -0
- package/backend/src/flowent/models/tab.py +48 -0
- package/backend/src/flowent/models/todo.py +10 -0
- package/backend/src/flowent/network.py +146 -0
- package/backend/src/flowent/prompts/__init__.py +67 -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/prompts/common.py +250 -0
- package/backend/src/flowent/prompts/steward.py +64 -0
- package/backend/src/flowent/providers/__init__.py +23 -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/providers/anthropic.py +468 -0
- package/backend/src/flowent/providers/base_url.py +60 -0
- package/backend/src/flowent/providers/configuration.py +182 -0
- package/backend/src/flowent/providers/content.py +122 -0
- package/backend/src/flowent/providers/errors.py +223 -0
- package/backend/src/flowent/providers/gateway.py +169 -0
- package/backend/src/flowent/providers/gemini.py +447 -0
- package/backend/src/flowent/providers/headers.py +20 -0
- package/backend/src/flowent/providers/management.py +96 -0
- package/backend/src/flowent/providers/ollama.py +293 -0
- package/backend/src/flowent/providers/openai.py +422 -0
- package/backend/src/flowent/providers/openai_responses.py +655 -0
- package/backend/src/flowent/providers/registry.py +144 -0
- package/backend/src/flowent/providers/sse.py +31 -0
- package/backend/src/flowent/providers/thinking.py +79 -0
- package/backend/src/flowent/registry.py +73 -0
- package/backend/src/flowent/role_management.py +255 -0
- package/backend/src/flowent/routes/__init__.py +30 -0
- 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__/mcp.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__/stats.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 +48 -0
- package/backend/src/flowent/routes/assistant.py +155 -0
- package/backend/src/flowent/routes/image_assets.py +33 -0
- package/backend/src/flowent/routes/mcp.py +125 -0
- package/backend/src/flowent/routes/meta.py +28 -0
- package/backend/src/flowent/routes/nodes.py +365 -0
- package/backend/src/flowent/routes/prompts.py +46 -0
- package/backend/src/flowent/routes/providers_route.py +364 -0
- package/backend/src/flowent/routes/roles.py +207 -0
- package/backend/src/flowent/routes/settings.py +324 -0
- package/backend/src/flowent/routes/stats.py +229 -0
- package/backend/src/flowent/routes/tabs.py +292 -0
- package/backend/src/flowent/routes/ws.py +33 -0
- package/backend/src/flowent/runtime.py +188 -0
- package/backend/src/flowent/sandbox.py +45 -0
- package/backend/src/flowent/security.py +42 -0
- package/backend/src/flowent/settings.py +2467 -0
- package/backend/src/flowent/settings_management.py +286 -0
- package/backend/src/flowent/state_db.py +120 -0
- package/backend/src/flowent/static/assets/AssistantPage-B3Xc08AS.js +1 -0
- package/backend/src/flowent/static/assets/ChannelsPage-ByLd28xk.js +1 -0
- package/backend/src/flowent/static/assets/HomePage-C0hAx9_l.js +3 -0
- package/backend/src/flowent/static/assets/McpPage-DkrYLvBv.js +7 -0
- package/backend/src/flowent/static/assets/PageScaffold-D4jO9ooX.js +1 -0
- package/backend/src/flowent/static/assets/PromptsPage-DWA7rRJd.js +1 -0
- package/backend/src/flowent/static/assets/ProvidersPage-PUWT8seJ.js +3 -0
- package/backend/src/flowent/static/assets/RolesPage-CqcclGRw.js +1 -0
- package/backend/src/flowent/static/assets/SettingsPage-8tS2cJgX.js +3 -0
- package/backend/src/flowent/static/assets/StatsPage-BX9khYzu.js +1 -0
- package/backend/src/flowent/static/assets/ToolsPage-9Tl9FdeD.js +1 -0
- package/backend/src/flowent/static/assets/WorkspaceCommandDialog-CCXxjDL8.js +1 -0
- package/backend/src/flowent/static/assets/WorkspacePanels-aMdJ7ZH7.js +1 -0
- package/backend/src/flowent/static/assets/alert-dialog-kFYVQ7oX.js +1 -0
- package/backend/src/flowent/static/assets/badge-74-3jsCg.js +1 -0
- package/backend/src/flowent/static/assets/constants-XUzFf6i1.js +1 -0
- package/backend/src/flowent/static/assets/datetime-m6_O_Ci9.js +1 -0
- package/backend/src/flowent/static/assets/dialog-BeGSweF6.js +1 -0
- package/backend/src/flowent/static/assets/elk-worker.min-C9JGDOE-.js +6312 -0
- package/backend/src/flowent/static/assets/graph-vendor-CHpVij2M.css +1 -0
- package/backend/src/flowent/static/assets/graph-vendor-DRq_-6fV.js +7 -0
- package/backend/src/flowent/static/assets/index-BHC1Vhy8.css +1 -0
- package/backend/src/flowent/static/assets/index-CL1ALZ3r.js +10 -0
- package/backend/src/flowent/static/assets/layout.worker-jMHqAFbP.js +24 -0
- package/backend/src/flowent/static/assets/markdown-vendor-DVdy_w12.js +29 -0
- package/backend/src/flowent/static/assets/modelParams-CaHd0903.js +1 -0
- package/backend/src/flowent/static/assets/react-vendor-mEs_JJxa.js +9 -0
- package/backend/src/flowent/static/assets/roles-2OLDeTc5.js +1 -0
- package/backend/src/flowent/static/assets/rolldown-runtime-BYbx6iT9.js +1 -0
- package/backend/src/flowent/static/assets/select-DL_LPeDj.js +1 -0
- package/backend/src/flowent/static/assets/shared-CMxbpLeQ.js +1 -0
- package/backend/src/flowent/static/assets/triState-DEr3NkXV.js +1 -0
- package/backend/src/flowent/static/assets/ui-vendor-Dg9NNnWX.js +51 -0
- package/backend/src/flowent/static/index.html +36 -0
- package/backend/src/flowent/stats_service.py +218 -0
- package/backend/src/flowent/tools/__init__.py +201 -0
- 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__/mcp.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 +156 -0
- package/backend/src/flowent/tools/contacts.py +22 -0
- package/backend/src/flowent/tools/create_agent.py +270 -0
- package/backend/src/flowent/tools/create_tab.py +59 -0
- package/backend/src/flowent/tools/delete_tab.py +39 -0
- package/backend/src/flowent/tools/edit.py +142 -0
- package/backend/src/flowent/tools/exec.py +117 -0
- package/backend/src/flowent/tools/fetch.py +85 -0
- package/backend/src/flowent/tools/idle.py +27 -0
- package/backend/src/flowent/tools/list_roles.py +50 -0
- package/backend/src/flowent/tools/list_tabs.py +96 -0
- package/backend/src/flowent/tools/list_tools.py +24 -0
- package/backend/src/flowent/tools/manage_prompts.py +102 -0
- package/backend/src/flowent/tools/manage_providers.py +220 -0
- package/backend/src/flowent/tools/manage_roles.py +275 -0
- package/backend/src/flowent/tools/manage_settings.py +346 -0
- package/backend/src/flowent/tools/mcp.py +199 -0
- package/backend/src/flowent/tools/read.py +152 -0
- package/backend/src/flowent/tools/send.py +50 -0
- package/backend/src/flowent/tools/set_permissions.py +84 -0
- package/backend/src/flowent/tools/sleep.py +41 -0
- package/backend/src/flowent/tools/todo.py +51 -0
- package/backend/src/flowent/workspace_store.py +479 -0
- 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 +6 -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_mcp_api.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 +29 -0
- package/backend/tests/integration/api/test_access_api.py +182 -0
- package/backend/tests/integration/api/test_assistant_api.py +354 -0
- package/backend/tests/integration/api/test_frontend_mounting.py +61 -0
- package/backend/tests/integration/api/test_mcp_api.py +116 -0
- package/backend/tests/integration/api/test_meta_api.py +33 -0
- package/backend/tests/integration/api/test_nodes_api.py +486 -0
- package/backend/tests/integration/api/test_prompts_api.py +47 -0
- package/backend/tests/integration/api/test_roles_api.py +227 -0
- package/backend/tests/integration/api/test_tabs_api.py +501 -0
- 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 +746 -0
- package/backend/tests/unit/agent/test_agent_runtime.py +2726 -0
- 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 +552 -0
- 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 +132 -0
- 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 +569 -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/providers/test_anthropic_provider.py +185 -0
- package/backend/tests/unit/providers/test_errors.py +68 -0
- package/backend/tests/unit/providers/test_extract_delta_parts.py +22 -0
- package/backend/tests/unit/providers/test_openai_provider.py +139 -0
- package/backend/tests/unit/providers/test_openai_responses.py +402 -0
- package/backend/tests/unit/providers/test_provider_gateway.py +359 -0
- package/backend/tests/unit/providers/test_think_tag_parser.py +36 -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/__pycache__/test_stats_routes.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/unit/routes/test_prompts_routes.py +104 -0
- package/backend/tests/unit/routes/test_providers_route.py +368 -0
- package/backend/tests/unit/routes/test_roles_routes.py +426 -0
- package/backend/tests/unit/routes/test_settings_routes.py +1138 -0
- package/backend/tests/unit/routes/test_stats_routes.py +149 -0
- 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 +1012 -0
- 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 +78 -0
- 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 +110 -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 +711 -0
- package/backend/tests/unit/test_access.py +45 -0
- package/backend/tests/unit/test_cli.py +124 -0
- package/backend/tests/unit/test_graph_runtime.py +72 -0
- package/backend/tests/unit/test_network.py +51 -0
- package/backend/tests/unit/test_state_sqlite_storage.py +93 -0
- package/backend/tests/unit/test_workspace_store.py +231 -0
- 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 +229 -0
- package/backend/tests/unit/tools/test_create_agent_tool.py +524 -0
- package/backend/tests/unit/tools/test_delete_tab_tool.py +83 -0
- package/backend/tests/unit/tools/test_edit_tool.py +115 -0
- package/backend/tests/unit/tools/test_exec_tool.py +81 -0
- package/backend/tests/unit/tools/test_fetch_tool.py +65 -0
- package/backend/tests/unit/tools/test_manage_prompts_tool.py +117 -0
- package/backend/tests/unit/tools/test_manage_providers_tool.py +458 -0
- package/backend/tests/unit/tools/test_manage_roles_tool.py +411 -0
- package/backend/tests/unit/tools/test_manage_settings_tool.py +608 -0
- package/backend/tests/unit/tools/test_read_tool.py +33 -0
- package/backend/tests/unit/tools/test_set_permissions_tool.py +391 -0
- package/backend/tests/unit/tools/test_todo_tool.py +37 -0
- package/backend/tests/unit/tools/test_tool_registry.py +91 -0
- package/backend/uv.lock +1144 -0
- package/bin/flowent.mjs +62 -35
- package/dist/frontend/assets/AssistantPage-B3Xc08AS.js +1 -0
- package/dist/frontend/assets/ChannelsPage-ByLd28xk.js +1 -0
- package/dist/frontend/assets/HomePage-C0hAx9_l.js +3 -0
- package/dist/frontend/assets/McpPage-DkrYLvBv.js +7 -0
- package/dist/frontend/assets/PageScaffold-D4jO9ooX.js +1 -0
- package/dist/frontend/assets/PromptsPage-DWA7rRJd.js +1 -0
- package/dist/frontend/assets/ProvidersPage-PUWT8seJ.js +3 -0
- package/dist/frontend/assets/RolesPage-CqcclGRw.js +1 -0
- package/dist/frontend/assets/SettingsPage-8tS2cJgX.js +3 -0
- package/dist/frontend/assets/StatsPage-BX9khYzu.js +1 -0
- package/dist/frontend/assets/ToolsPage-9Tl9FdeD.js +1 -0
- package/dist/frontend/assets/WorkspaceCommandDialog-CCXxjDL8.js +1 -0
- package/dist/frontend/assets/WorkspacePanels-aMdJ7ZH7.js +1 -0
- package/dist/frontend/assets/alert-dialog-kFYVQ7oX.js +1 -0
- package/dist/frontend/assets/badge-74-3jsCg.js +1 -0
- package/dist/frontend/assets/constants-XUzFf6i1.js +1 -0
- package/dist/frontend/assets/datetime-m6_O_Ci9.js +1 -0
- package/dist/frontend/assets/dialog-BeGSweF6.js +1 -0
- package/dist/frontend/assets/elk-worker.min-C9JGDOE-.js +6312 -0
- package/dist/frontend/assets/graph-vendor-CHpVij2M.css +1 -0
- package/dist/frontend/assets/graph-vendor-DRq_-6fV.js +7 -0
- package/dist/frontend/assets/index-BHC1Vhy8.css +1 -0
- package/dist/frontend/assets/index-CL1ALZ3r.js +10 -0
- package/dist/frontend/assets/layout.worker-jMHqAFbP.js +24 -0
- package/dist/frontend/assets/markdown-vendor-DVdy_w12.js +29 -0
- package/dist/frontend/assets/modelParams-CaHd0903.js +1 -0
- package/dist/frontend/assets/react-vendor-mEs_JJxa.js +9 -0
- package/dist/frontend/assets/roles-2OLDeTc5.js +1 -0
- package/dist/frontend/assets/rolldown-runtime-BYbx6iT9.js +1 -0
- package/dist/frontend/assets/select-DL_LPeDj.js +1 -0
- package/dist/frontend/assets/shared-CMxbpLeQ.js +1 -0
- package/dist/frontend/assets/triState-DEr3NkXV.js +1 -0
- package/dist/frontend/assets/ui-vendor-Dg9NNnWX.js +51 -0
- package/dist/frontend/index.html +36 -0
- package/package.json +28 -41
- package/dist/.next/BUILD_ID +0 -1
- package/dist/.next/app-path-routes-manifest.json +0 -6
- package/dist/.next/build-manifest.json +0 -20
- package/dist/.next/package.json +0 -1
- package/dist/.next/prerender-manifest.json +0 -114
- package/dist/.next/required-server-files.json +0 -333
- package/dist/.next/routes-manifest.json +0 -69
- package/dist/.next/server/app/_global-error/page/app-paths-manifest.json +0 -3
- package/dist/.next/server/app/_global-error/page/build-manifest.json +0 -16
- package/dist/.next/server/app/_global-error/page/next-font-manifest.json +0 -6
- package/dist/.next/server/app/_global-error/page/react-loadable-manifest.json +0 -1
- package/dist/.next/server/app/_global-error/page/server-reference-manifest.json +0 -4
- package/dist/.next/server/app/_global-error/page.js +0 -9
- package/dist/.next/server/app/_global-error/page.js.map +0 -5
- package/dist/.next/server/app/_global-error/page.js.nft.json +0 -1
- package/dist/.next/server/app/_global-error/page_client-reference-manifest.js +0 -3
- package/dist/.next/server/app/_global-error.html +0 -1
- package/dist/.next/server/app/_global-error.meta +0 -15
- package/dist/.next/server/app/_global-error.rsc +0 -14
- package/dist/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +0 -5
- package/dist/.next/server/app/_global-error.segments/_full.segment.rsc +0 -14
- package/dist/.next/server/app/_global-error.segments/_head.segment.rsc +0 -5
- package/dist/.next/server/app/_global-error.segments/_index.segment.rsc +0 -5
- package/dist/.next/server/app/_global-error.segments/_tree.segment.rsc +0 -1
- package/dist/.next/server/app/_not-found/page/app-paths-manifest.json +0 -3
- package/dist/.next/server/app/_not-found/page/build-manifest.json +0 -16
- package/dist/.next/server/app/_not-found/page/next-font-manifest.json +0 -10
- package/dist/.next/server/app/_not-found/page/react-loadable-manifest.json +0 -1
- package/dist/.next/server/app/_not-found/page/server-reference-manifest.json +0 -4
- package/dist/.next/server/app/_not-found/page.js +0 -13
- package/dist/.next/server/app/_not-found/page.js.map +0 -5
- package/dist/.next/server/app/_not-found/page.js.nft.json +0 -1
- package/dist/.next/server/app/_not-found/page_client-reference-manifest.js +0 -3
- package/dist/.next/server/app/_not-found.html +0 -1
- package/dist/.next/server/app/_not-found.meta +0 -16
- package/dist/.next/server/app/_not-found.rsc +0 -16
- package/dist/.next/server/app/_not-found.segments/_full.segment.rsc +0 -16
- package/dist/.next/server/app/_not-found.segments/_head.segment.rsc +0 -6
- package/dist/.next/server/app/_not-found.segments/_index.segment.rsc +0 -5
- package/dist/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +0 -5
- package/dist/.next/server/app/_not-found.segments/_not-found.segment.rsc +0 -5
- package/dist/.next/server/app/_not-found.segments/_tree.segment.rsc +0 -2
- package/dist/.next/server/app/icon.svg/route/app-paths-manifest.json +0 -3
- package/dist/.next/server/app/icon.svg/route/build-manifest.json +0 -9
- package/dist/.next/server/app/icon.svg/route.js +0 -6
- package/dist/.next/server/app/icon.svg/route.js.map +0 -5
- package/dist/.next/server/app/icon.svg/route.js.nft.json +0 -1
- package/dist/.next/server/app/icon.svg.meta +0 -1
- package/dist/.next/server/app/index.html +0 -1
- package/dist/.next/server/app/index.meta +0 -14
- package/dist/.next/server/app/index.rsc +0 -15
- package/dist/.next/server/app/index.segments/__PAGE__.segment.rsc +0 -5
- package/dist/.next/server/app/index.segments/_full.segment.rsc +0 -15
- package/dist/.next/server/app/index.segments/_head.segment.rsc +0 -6
- package/dist/.next/server/app/index.segments/_index.segment.rsc +0 -5
- package/dist/.next/server/app/index.segments/_tree.segment.rsc +0 -3
- package/dist/.next/server/app/page/app-paths-manifest.json +0 -3
- package/dist/.next/server/app/page/build-manifest.json +0 -16
- package/dist/.next/server/app/page/next-font-manifest.json +0 -10
- package/dist/.next/server/app/page/react-loadable-manifest.json +0 -1
- package/dist/.next/server/app/page/server-reference-manifest.json +0 -4
- package/dist/.next/server/app/page.js +0 -14
- package/dist/.next/server/app/page.js.map +0 -5
- package/dist/.next/server/app/page.js.nft.json +0 -1
- package/dist/.next/server/app/page_client-reference-manifest.js +0 -3
- package/dist/.next/server/app-paths-manifest.json +0 -6
- package/dist/.next/server/chunks/[externals]_next_dist_0arv.vj._.js +0 -3
- package/dist/.next/server/chunks/[root-of-the-server]__0vcj1q1._.js +0 -13
- package/dist/.next/server/chunks/[turbopack]_runtime.js +0 -903
- package/dist/.next/server/chunks/_next-internal_server_app_icon_svg_route_actions_0-0ehc~.js +0 -3
- package/dist/.next/server/chunks/ssr/05w9_next_dist_0ihu0u9._.js +0 -6
- package/dist/.next/server/chunks/ssr/05w9_next_dist_client_components_12u3mib._.js +0 -3
- package/dist/.next/server/chunks/ssr/05w9_next_dist_client_components_builtin_forbidden_04fbe_..js +0 -3
- package/dist/.next/server/chunks/ssr/05w9_next_dist_client_components_builtin_global-error_0brpl_..js +0 -3
- package/dist/.next/server/chunks/ssr/05w9_next_dist_client_components_builtin_unauthorized_0~2g66g.js +0 -3
- package/dist/.next/server/chunks/ssr/05w9_next_dist_esm_build_templates_app-page_0~cyr1_.js +0 -4
- package/dist/.next/server/chunks/ssr/05w9_next_dist_esm_build_templates_app-page_1105emf.js +0 -4
- package/dist/.next/server/chunks/ssr/05w9_next_dist_esm_build_templates_app-page_11uhyqv.js +0 -4
- package/dist/.next/server/chunks/ssr/[root-of-the-server]__0.t9_75._.js +0 -33
- package/dist/.next/server/chunks/ssr/[root-of-the-server]__0c0ud_z._.js +0 -3
- package/dist/.next/server/chunks/ssr/[root-of-the-server]__0f9_8d4._.js +0 -3
- package/dist/.next/server/chunks/ssr/[root-of-the-server]__0l5ko41._.js +0 -19
- package/dist/.next/server/chunks/ssr/[root-of-the-server]__0mn6z7i._.js +0 -3
- package/dist/.next/server/chunks/ssr/[root-of-the-server]__0npxxst._.js +0 -33
- package/dist/.next/server/chunks/ssr/[root-of-the-server]__0qjhaca._.js +0 -3
- package/dist/.next/server/chunks/ssr/[root-of-the-server]__0rwgw3s._.js +0 -3
- package/dist/.next/server/chunks/ssr/[turbopack]_runtime.js +0 -903
- package/dist/.next/server/chunks/ssr/_next-internal_server_app__global-error_page_actions_0k77kol.js +0 -3
- package/dist/.next/server/chunks/ssr/_next-internal_server_app__not-found_page_actions_0eq97pa.js +0 -3
- package/dist/.next/server/chunks/ssr/_next-internal_server_app_page_actions_09-gtaw.js +0 -3
- package/dist/.next/server/chunks/ssr/node_modules__pnpm_056~6.6._.js +0 -3
- package/dist/.next/server/chunks/ssr/node_modules__pnpm_0~j0k.e._.js +0 -33
- package/dist/.next/server/functions-config-manifest.json +0 -4
- package/dist/.next/server/middleware-build-manifest.js +0 -20
- package/dist/.next/server/middleware-manifest.json +0 -6
- package/dist/.next/server/next-font-manifest.js +0 -1
- package/dist/.next/server/next-font-manifest.json +0 -13
- package/dist/.next/server/pages/404.html +0 -1
- package/dist/.next/server/pages/500.html +0 -1
- package/dist/.next/server/pages-manifest.json +0 -4
- package/dist/.next/server/prefetch-hints.json +0 -1
- package/dist/.next/server/server-reference-manifest.js +0 -1
- package/dist/.next/server/server-reference-manifest.json +0 -5
- package/dist/.next/static/7FFlzRe2eS-D0Lw5oEpmC/_buildManifest.js +0 -11
- package/dist/.next/static/7FFlzRe2eS-D0Lw5oEpmC/_clientMiddlewareManifest.js +0 -1
- package/dist/.next/static/7FFlzRe2eS-D0Lw5oEpmC/_ssgManifest.js +0 -1
- package/dist/.next/static/chunks/01qk2~bgf76vu.js +0 -1
- package/dist/.next/static/chunks/03~yq9q893hmn.js +0 -1
- package/dist/.next/static/chunks/080queev.r2uy.js +0 -31
- package/dist/.next/static/chunks/0v3lyuj75aq50.js +0 -1
- package/dist/.next/static/chunks/10b~xdx5c-i7s.js +0 -5
- package/dist/.next/static/chunks/15~9l5n.~r-.4.css +0 -2
- package/dist/.next/static/chunks/turbopack-0m-970~qvs7sc.js +0 -1
- package/dist/.next/static/media/7178b3e590c64307-s.11.cyxs5p-0z~.woff2 +0 -0
- package/dist/.next/static/media/8a480f0b521d4e75-s.06d3mdzz5bre_.woff2 +0 -0
- package/dist/.next/static/media/caa3a2e1cccd8315-s.p.16t1db8_9y2o~.woff2 +0 -0
- package/dist/package.json +0 -87
- package/dist/server.js +0 -38
- /package/{dist/.next/server/app/icon.svg.body → backend/src/flowent/static/favicon.svg} +0 -0
- /package/dist/{.next/static/media/icon.0.r~afrtrocz9.svg → frontend/favicon.svg} +0 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass, field
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclass
|
|
8
|
+
class ModelCapabilities:
|
|
9
|
+
input_image: bool = False
|
|
10
|
+
output_image: bool = False
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass
|
|
14
|
+
class ModelInfo:
|
|
15
|
+
id: str
|
|
16
|
+
capabilities: ModelCapabilities = field(default_factory=ModelCapabilities)
|
|
17
|
+
context_window_tokens: int | None = None
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@dataclass
|
|
21
|
+
class LLMUsage:
|
|
22
|
+
total_tokens: int
|
|
23
|
+
input_tokens: int | None = None
|
|
24
|
+
output_tokens: int | None = None
|
|
25
|
+
cached_input_tokens: int | None = None
|
|
26
|
+
cache_read_tokens: int | None = None
|
|
27
|
+
cache_write_tokens: int | None = None
|
|
28
|
+
details: dict[str, int] = field(default_factory=dict)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@dataclass
|
|
32
|
+
class ToolCallResult:
|
|
33
|
+
id: str
|
|
34
|
+
name: str
|
|
35
|
+
arguments: dict[str, Any]
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@dataclass
|
|
39
|
+
class LLMOutputTextPart:
|
|
40
|
+
text: str
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@dataclass
|
|
44
|
+
class LLMOutputImagePart:
|
|
45
|
+
data: bytes
|
|
46
|
+
mime_type: str
|
|
47
|
+
width: int | None = None
|
|
48
|
+
height: int | None = None
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
LLMOutputPart = LLMOutputTextPart | LLMOutputImagePart
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
@dataclass
|
|
55
|
+
class LLMResponse:
|
|
56
|
+
content: str | None = None
|
|
57
|
+
parts: list[LLMOutputPart] | None = None
|
|
58
|
+
tool_calls: list[ToolCallResult] | None = None
|
|
59
|
+
thinking: str | None = None
|
|
60
|
+
usage: LLMUsage | None = None
|
|
61
|
+
raw_usage: dict[str, Any] | None = None
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import time
|
|
4
|
+
from dataclasses import dataclass, field
|
|
5
|
+
|
|
6
|
+
from flowent.models.content import (
|
|
7
|
+
ContentPart,
|
|
8
|
+
content_parts_to_text,
|
|
9
|
+
deserialize_content_parts,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass
|
|
14
|
+
class Message:
|
|
15
|
+
from_id: str
|
|
16
|
+
to_id: str
|
|
17
|
+
parts: list[ContentPart] = field(default_factory=list)
|
|
18
|
+
content: str = ""
|
|
19
|
+
message_id: str | None = None
|
|
20
|
+
history_recorded: bool = False
|
|
21
|
+
timestamp: float = field(default_factory=time.time)
|
|
22
|
+
|
|
23
|
+
def __post_init__(self) -> None:
|
|
24
|
+
if self.parts and not self.content:
|
|
25
|
+
self.content = content_parts_to_text(self.parts)
|
|
26
|
+
elif self.content and not self.parts:
|
|
27
|
+
self.parts = deserialize_content_parts(None, fallback_text=self.content)
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import time
|
|
4
|
+
from dataclasses import dataclass, field
|
|
5
|
+
|
|
6
|
+
from flowent.models.graph import WorkflowDefinition
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@dataclass
|
|
10
|
+
class Tab:
|
|
11
|
+
id: str
|
|
12
|
+
title: str
|
|
13
|
+
leader_id: str | None = None
|
|
14
|
+
definition: WorkflowDefinition = field(default_factory=WorkflowDefinition)
|
|
15
|
+
created_at: float = field(default_factory=time.time)
|
|
16
|
+
updated_at: float = field(default_factory=time.time)
|
|
17
|
+
|
|
18
|
+
def serialize(self) -> dict[str, object]:
|
|
19
|
+
return {
|
|
20
|
+
"id": self.id,
|
|
21
|
+
"title": self.title,
|
|
22
|
+
"leader_id": self.leader_id,
|
|
23
|
+
"definition": self.definition.serialize(),
|
|
24
|
+
"created_at": self.created_at,
|
|
25
|
+
"updated_at": self.updated_at,
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@classmethod
|
|
29
|
+
def from_mapping(cls, data: dict[str, object]) -> Tab:
|
|
30
|
+
created_at = data.get("created_at")
|
|
31
|
+
updated_at = data.get("updated_at")
|
|
32
|
+
raw_definition = data.get("definition")
|
|
33
|
+
return cls(
|
|
34
|
+
id=str(data.get("id", "")),
|
|
35
|
+
title=str(data.get("title", "")),
|
|
36
|
+
leader_id=str(data["leader_id"])
|
|
37
|
+
if isinstance(data.get("leader_id"), str)
|
|
38
|
+
else None,
|
|
39
|
+
definition=WorkflowDefinition.from_mapping(
|
|
40
|
+
raw_definition if isinstance(raw_definition, dict) else None
|
|
41
|
+
),
|
|
42
|
+
created_at=created_at
|
|
43
|
+
if isinstance(created_at, (int, float))
|
|
44
|
+
else time.time(),
|
|
45
|
+
updated_at=updated_at
|
|
46
|
+
if isinstance(updated_at, (int, float))
|
|
47
|
+
else time.time(),
|
|
48
|
+
)
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Iterator
|
|
4
|
+
from typing import Any, Literal
|
|
5
|
+
|
|
6
|
+
from curl_cffi.requests import AsyncSession, Session
|
|
7
|
+
from curl_cffi.requests.exceptions import RequestException
|
|
8
|
+
|
|
9
|
+
DEFAULT_BROWSER_IMPERSONATE: Literal["chrome"] = "chrome"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def create_http_session(
|
|
13
|
+
*,
|
|
14
|
+
timeout: float,
|
|
15
|
+
impersonate_browser: bool = False,
|
|
16
|
+
) -> Session:
|
|
17
|
+
kwargs: dict[str, Any] = {"timeout": timeout}
|
|
18
|
+
if impersonate_browser:
|
|
19
|
+
kwargs["impersonate"] = DEFAULT_BROWSER_IMPERSONATE
|
|
20
|
+
return Session(**kwargs)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def create_async_http_session(
|
|
24
|
+
*,
|
|
25
|
+
timeout: float,
|
|
26
|
+
impersonate_browser: bool = False,
|
|
27
|
+
) -> AsyncSession:
|
|
28
|
+
kwargs: dict[str, Any] = {"timeout": timeout}
|
|
29
|
+
if impersonate_browser:
|
|
30
|
+
kwargs["impersonate"] = DEFAULT_BROWSER_IMPERSONATE
|
|
31
|
+
return AsyncSession(**kwargs)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def is_success_status(status_code: int) -> bool:
|
|
35
|
+
return 200 <= status_code < 300
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def iter_response_lines(response: Any) -> Iterator[str]:
|
|
39
|
+
for line in response.iter_lines():
|
|
40
|
+
normalized = _decode_to_text(line)
|
|
41
|
+
if normalized:
|
|
42
|
+
yield normalized
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def iter_response_text(response: Any) -> Iterator[str]:
|
|
46
|
+
iter_text = getattr(response, "iter_text", None)
|
|
47
|
+
if callable(iter_text):
|
|
48
|
+
for chunk in iter_text():
|
|
49
|
+
normalized = _decode_to_text(chunk)
|
|
50
|
+
if normalized:
|
|
51
|
+
yield normalized
|
|
52
|
+
return
|
|
53
|
+
|
|
54
|
+
for chunk in response.iter_content():
|
|
55
|
+
normalized = _decode_to_text(chunk)
|
|
56
|
+
if normalized:
|
|
57
|
+
yield normalized
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def read_response_text(response: Any) -> str:
|
|
61
|
+
text = getattr(response, "text", None)
|
|
62
|
+
if isinstance(text, str) and text:
|
|
63
|
+
return text
|
|
64
|
+
|
|
65
|
+
content = getattr(response, "content", None)
|
|
66
|
+
if isinstance(content, str) and content:
|
|
67
|
+
return content
|
|
68
|
+
if isinstance(content, (bytes, bytearray)) and content:
|
|
69
|
+
return bytes(content).decode("utf-8", errors="replace")
|
|
70
|
+
|
|
71
|
+
iter_text = getattr(response, "iter_text", None)
|
|
72
|
+
if callable(iter_text):
|
|
73
|
+
chunks = [_decode_to_text(chunk) for chunk in iter_text()]
|
|
74
|
+
if chunks:
|
|
75
|
+
return "".join(chunks)
|
|
76
|
+
|
|
77
|
+
iter_content = getattr(response, "iter_content", None)
|
|
78
|
+
if callable(iter_content):
|
|
79
|
+
chunks = [_decode_to_text(chunk) for chunk in iter_content()]
|
|
80
|
+
if chunks:
|
|
81
|
+
return "".join(chunks)
|
|
82
|
+
|
|
83
|
+
read = getattr(response, "read", None)
|
|
84
|
+
if callable(read):
|
|
85
|
+
payload = read()
|
|
86
|
+
if isinstance(payload, str):
|
|
87
|
+
return payload
|
|
88
|
+
if isinstance(payload, (bytes, bytearray)):
|
|
89
|
+
return bytes(payload).decode("utf-8", errors="replace")
|
|
90
|
+
|
|
91
|
+
return ""
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def get_response_header(response: Any, header_name: str) -> str | None:
|
|
95
|
+
headers = getattr(response, "headers", None)
|
|
96
|
+
if headers is None:
|
|
97
|
+
return None
|
|
98
|
+
getter = getattr(headers, "get", None)
|
|
99
|
+
if callable(getter):
|
|
100
|
+
value = getter(header_name)
|
|
101
|
+
if isinstance(value, str):
|
|
102
|
+
return value
|
|
103
|
+
if isinstance(headers, dict):
|
|
104
|
+
value = headers.get(header_name) or headers.get(header_name.lower())
|
|
105
|
+
if isinstance(value, str):
|
|
106
|
+
return value
|
|
107
|
+
return None
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def response_looks_like_html(response: Any) -> bool:
|
|
111
|
+
content_type = get_response_header(response, "content-type")
|
|
112
|
+
if not isinstance(content_type, str):
|
|
113
|
+
return False
|
|
114
|
+
normalized = content_type.lower()
|
|
115
|
+
return "text/html" in normalized or "application/xhtml+xml" in normalized
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def truncate_text(text: str, limit: int = 500) -> str:
|
|
119
|
+
if len(text) <= limit:
|
|
120
|
+
return text
|
|
121
|
+
return text[:limit]
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def _decode_to_text(value: Any) -> str:
|
|
125
|
+
if isinstance(value, str):
|
|
126
|
+
return value
|
|
127
|
+
if isinstance(value, (bytes, bytearray)):
|
|
128
|
+
return bytes(value).decode("utf-8", errors="replace")
|
|
129
|
+
return str(value)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
__all__ = [
|
|
133
|
+
"DEFAULT_BROWSER_IMPERSONATE",
|
|
134
|
+
"AsyncSession",
|
|
135
|
+
"RequestException",
|
|
136
|
+
"Session",
|
|
137
|
+
"create_async_http_session",
|
|
138
|
+
"create_http_session",
|
|
139
|
+
"get_response_header",
|
|
140
|
+
"is_success_status",
|
|
141
|
+
"iter_response_lines",
|
|
142
|
+
"iter_response_text",
|
|
143
|
+
"read_response_text",
|
|
144
|
+
"response_looks_like_html",
|
|
145
|
+
"truncate_text",
|
|
146
|
+
]
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from flowent.models import NodeConfig, NodeType
|
|
4
|
+
from flowent.prompts.common import DEFAULT_AGENT_ROLE_PROMPT, compose_system_prompt
|
|
5
|
+
from flowent.prompts.steward import STEWARD_ROLE_SYSTEM_PROMPT
|
|
6
|
+
from flowent.tools import MINIMUM_TOOLS
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def _get_assistant_role_prompt(*, settings, role_name: str) -> str:
|
|
10
|
+
from flowent.settings import STEWARD_ROLE_NAME, find_role
|
|
11
|
+
|
|
12
|
+
normalized_role_name = role_name.strip()
|
|
13
|
+
role = find_role(settings, normalized_role_name)
|
|
14
|
+
if role is None or normalized_role_name == STEWARD_ROLE_NAME:
|
|
15
|
+
return STEWARD_ROLE_SYSTEM_PROMPT
|
|
16
|
+
|
|
17
|
+
overlay_prompt = role.system_prompt.strip()
|
|
18
|
+
if not overlay_prompt:
|
|
19
|
+
return STEWARD_ROLE_SYSTEM_PROMPT
|
|
20
|
+
|
|
21
|
+
return "\n\n".join(
|
|
22
|
+
[
|
|
23
|
+
STEWARD_ROLE_SYSTEM_PROMPT.strip(),
|
|
24
|
+
f"""\
|
|
25
|
+
## Selected Role Overlay
|
|
26
|
+
|
|
27
|
+
The Assistant is currently configured to use the role "{role.name}" as an additional behavior template.
|
|
28
|
+
Use the selected role to adjust tone, specialization, model tendency, and any extra tool usage that fits the Assistant surface.
|
|
29
|
+
Do not follow any selected-role instruction that would redefine you as a Worker, Designer, Leader, or regular workflow node, or that would drop your Human-facing intake and workspace-boundary responsibilities.
|
|
30
|
+
|
|
31
|
+
### Selected Role Prompt
|
|
32
|
+
|
|
33
|
+
{overlay_prompt}""".strip(),
|
|
34
|
+
]
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def get_system_prompt(config: NodeConfig) -> str:
|
|
39
|
+
from flowent.settings import (
|
|
40
|
+
STEWARD_ROLE_NAME,
|
|
41
|
+
get_settings,
|
|
42
|
+
normalize_tool_names,
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
settings = get_settings()
|
|
46
|
+
tools = normalize_tool_names([*config.tools, *MINIMUM_TOOLS])
|
|
47
|
+
|
|
48
|
+
if config.node_type == NodeType.ASSISTANT:
|
|
49
|
+
role_name = (
|
|
50
|
+
config.role_name or settings.assistant.role_name or STEWARD_ROLE_NAME
|
|
51
|
+
)
|
|
52
|
+
prompt = _get_assistant_role_prompt(settings=settings, role_name=role_name)
|
|
53
|
+
else:
|
|
54
|
+
prompt = DEFAULT_AGENT_ROLE_PROMPT
|
|
55
|
+
if config.role_name:
|
|
56
|
+
from flowent.settings import find_role
|
|
57
|
+
|
|
58
|
+
role = find_role(settings, config.role_name)
|
|
59
|
+
if role:
|
|
60
|
+
prompt = role.system_prompt
|
|
61
|
+
|
|
62
|
+
return compose_system_prompt(
|
|
63
|
+
prompt,
|
|
64
|
+
custom_prompt=settings.custom_prompt,
|
|
65
|
+
is_assistant=config.node_type == NodeType.ASSISTANT,
|
|
66
|
+
tools=tools,
|
|
67
|
+
)
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
IDLE_TOOL_GUIDANCE = """\
|
|
2
|
+
## Idle Usage Rules
|
|
3
|
+
|
|
4
|
+
- `idle` means you are not taking another immediate action right now.
|
|
5
|
+
- Valid uses of `idle` include:
|
|
6
|
+
- you are temporarily waiting for a new message to continue, or
|
|
7
|
+
- you have finished the current task or step and there is no new task yet.
|
|
8
|
+
- Only use `idle` when the current step is complete, paused, or blocked.
|
|
9
|
+
- Do not use `idle` if you still have an immediate action you can take now.
|
|
10
|
+
- Do not use `idle` instead of replying to a newly received message.
|
|
11
|
+
- After calling `idle`, you will be re-activated when a new message arrives.
|
|
12
|
+
- When that happens, the new message will appear as a fresh input message, and `idle` will return the idle duration.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
SLEEP_TOOL_GUIDANCE = """\
|
|
16
|
+
## Sleep Usage Rules
|
|
17
|
+
|
|
18
|
+
- Use `sleep(seconds)` only for deliberate fixed-duration waiting.
|
|
19
|
+
- The `seconds` argument is measured in seconds and may be fractional.
|
|
20
|
+
- While `sleep` is in progress, incoming messages stay queued and are processed after the sleep finishes.
|
|
21
|
+
- Prefer `idle` when you are waiting for an unknown-duration incoming message or handoff.
|
|
22
|
+
- `sleep` returns the actual waited duration when it finishes.
|
|
23
|
+
- Do not use `sleep` instead of replying to a newly received message.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
TODO_TOOL_GUIDANCE = """\
|
|
27
|
+
## Todo Tool Rules
|
|
28
|
+
|
|
29
|
+
- Use `todo` to manage your task checklist and track the current plan or remaining work.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
CREATE_WORKFLOW_TOOL_GUIDANCE = """\
|
|
33
|
+
## Create Workflow Tool Rules
|
|
34
|
+
|
|
35
|
+
- Use `create_workflow` to open a persistent workflow before building a Workflow Graph for that task.
|
|
36
|
+
- A workflow is the user-visible home for one task. Keep the title concrete and easy to recognize later.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
DELETE_WORKFLOW_TOOL_GUIDANCE = """\
|
|
40
|
+
## Delete Workflow Tool Rules
|
|
41
|
+
|
|
42
|
+
- Use `delete_workflow` only when the Human explicitly asks to remove a workflow or when you are intentionally cleaning up a task workspace that should no longer exist.
|
|
43
|
+
- Deleting a workflow permanently removes the workflow and its persisted Workflow Graph after active nodes are terminated.
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
SET_PERMISSIONS_TOOL_GUIDANCE = """\
|
|
47
|
+
## Set Permissions Tool Rules
|
|
48
|
+
|
|
49
|
+
- Use `set_permissions` to patch a workflow's permission boundary after the workflow already exists.
|
|
50
|
+
- `set_permissions` updates the target workflow by writing directly to its bound Leader's `allow_network` and `write_dirs`.
|
|
51
|
+
- Treat `allow_network` and `write_dirs` as patch fields: omitted fields stay unchanged.
|
|
52
|
+
- When the Human asks to change a workflow's network or writable directory boundary, prefer `set_permissions` instead of delegating that change to the workflow's Leader.
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
CREATE_AGENT_TOOL_GUIDANCE = """\
|
|
56
|
+
## Create Agent Tool Rules
|
|
57
|
+
|
|
58
|
+
- Use `create_agent` to add a new agent node to the current workflow.
|
|
59
|
+
- Prefer creating the right set of agents up front. If you also have `connect`, wire workflow edges as needed.
|
|
60
|
+
- `create_agent` always creates the new peer in your current workflow. It does not take `workflow_id` or any other cross-workflow target parameter.
|
|
61
|
+
- Ordinary task nodes may use `create_agent` only when that tool was explicitly granted to them.
|
|
62
|
+
- `create_agent` can place the new node as a standalone node, after another node, or between two nodes in the current Workflow Graph.
|
|
63
|
+
- Creating an agent does not start work by itself; explicitly dispatch its first task with `send`.
|
|
64
|
+
- After creating multiple agents, dispatch tasks to all of them before calling `idle`.
|
|
65
|
+
- Do not insert unrelated tool calls or Human-facing text while some planned nodes are still waiting for their first task.
|
|
66
|
+
- When naming an agent via `create_agent`, use title case with spaces (e.g. "Web Researcher", "Code Reviewer", "Data Analyst"). Avoid snake_case, camelCase, or all-lowercase names.
|
|
67
|
+
"""
|
|
68
|
+
|
|
69
|
+
DELEGATION_GENERAL_GUIDANCE = """\
|
|
70
|
+
## Delegation Rules
|
|
71
|
+
|
|
72
|
+
- Treat delegation as a first-choice option, not a last resort.
|
|
73
|
+
- When a task is not really yours to own, your first reaction should be delegation or handoff, not solo execution.
|
|
74
|
+
- Once you conclude delegation is the better path, do it immediately instead of asking the Human whether you should delegate.
|
|
75
|
+
- If delegation can make progress on the Human's request, do not externalize your temporary limitation to the Human before delegating.
|
|
76
|
+
- Before doing the work yourself, first ask whether the task is outside your role, expertise, permissions, available tools, or comparative advantage.
|
|
77
|
+
- If a task is outside your role, expertise, permissions, or current toolset, your default move should be delegation rather than prolonged solo trial-and-error.
|
|
78
|
+
- If you cannot complete a task efficiently or confidently alone, delegate early instead of struggling alone.
|
|
79
|
+
- Do not ask the Human for permission to delegate just because delegation seems helpful; only ask first when the delegation itself would introduce destructive actions, material extra cost, permission risk, or the Human explicitly asked to approve delegation decisions.
|
|
80
|
+
- Do not turn delegation into a suggestion like "I can ask another agent if you want" when you can already delegate now.
|
|
81
|
+
- Do not keep pushing on execution-heavy or specialized work that obviously belongs to a more suitable agent.
|
|
82
|
+
- Do not start with repeated local retries when the better move is obvious delegation.
|
|
83
|
+
- Do not spend multiple turns persisting alone on a clear role mismatch; hand off with a concrete task, expected output, and relevant constraints.
|
|
84
|
+
- After creating or delegating to another agent, keep coordinating the work rather than duplicating the same task yourself.
|
|
85
|
+
- Before calling `idle`, check whether delegation, handoff, or creating another agent is the real next action.
|
|
86
|
+
"""
|
|
87
|
+
|
|
88
|
+
CONNECT_TOOL_GUIDANCE = """\
|
|
89
|
+
## Connect Tool Rules
|
|
90
|
+
|
|
91
|
+
- Use `connect` to create a directed workflow edge between node ports when the current Workflow Graph needs it.
|
|
92
|
+
"""
|
|
93
|
+
|
|
94
|
+
CONTACTS_TOOL_GUIDANCE = """\
|
|
95
|
+
## Contacts Tool Rules
|
|
96
|
+
|
|
97
|
+
- Use `contacts` to inspect the agents you can currently message directly.
|
|
98
|
+
"""
|
|
99
|
+
|
|
100
|
+
SEND_TOOL_GUIDANCE = """\
|
|
101
|
+
## Send Tool Rules
|
|
102
|
+
|
|
103
|
+
- Use `send` for every formal node-to-node message.
|
|
104
|
+
- `send` takes exactly one `target` and one ordered `parts` array.
|
|
105
|
+
- Use `contacts` before `send` when you need to inspect reachable target ids or names.
|
|
106
|
+
- `send.parts` preserves order. Keep text and image parts in the sequence you intend the receiver to see.
|
|
107
|
+
- `@target:` and similar text prefixes inside normal content do not send anything.
|
|
108
|
+
- If multiple nodes need messages in the same turn, call `send` multiple times in sequence.
|
|
109
|
+
"""
|
|
110
|
+
|
|
111
|
+
LIST_ROLES_TOOL_GUIDANCE = """\
|
|
112
|
+
## List Roles Tool Rules
|
|
113
|
+
|
|
114
|
+
- Use `list_roles` to inspect all registered roles and their included or optional tool configuration before choosing what nodes to create.
|
|
115
|
+
"""
|
|
116
|
+
|
|
117
|
+
LIST_WORKFLOWS_TOOL_GUIDANCE = """\
|
|
118
|
+
## List Workflows Tool Rules
|
|
119
|
+
|
|
120
|
+
- Use `list_workflows` to inspect the current persistent workflows.
|
|
121
|
+
- Pass `workflow_id` when you need the detailed node and edge structure for one workflow before changing or continuing its work.
|
|
122
|
+
"""
|
|
123
|
+
|
|
124
|
+
LIST_TOOLS_TOOL_GUIDANCE = """\
|
|
125
|
+
## List Tools Tool Rules
|
|
126
|
+
|
|
127
|
+
- Use `list_tools` to inspect all registered tools in the system, not just the tools currently available to you.
|
|
128
|
+
"""
|
|
129
|
+
|
|
130
|
+
MANAGE_TOOLS_GUIDANCE = """\
|
|
131
|
+
## Management Tool Rules
|
|
132
|
+
|
|
133
|
+
- `manage_providers` manages provider configuration and model catalogs.
|
|
134
|
+
- `manage_roles` manages role configuration.
|
|
135
|
+
- `manage_settings` reads and updates runtime defaults.
|
|
136
|
+
- `manage_prompts` reads and updates the global custom prompt and custom post prompt.
|
|
137
|
+
- `set_permissions` updates an existing workflow's permission boundary.
|
|
138
|
+
"""
|
|
139
|
+
|
|
140
|
+
COMMUNICATION_USAGE_GUIDANCE = """\
|
|
141
|
+
## Communication Rules
|
|
142
|
+
|
|
143
|
+
- Use plain content only for your own direct output. Plain content is never delivered to another node.
|
|
144
|
+
- Use `send` for every formal node-to-node message. Target selection belongs in `send.target`, not in the text body.
|
|
145
|
+
- `send` takes one target at a time. If multiple nodes need messages, call `send` multiple times in sequence.
|
|
146
|
+
- Use `contacts` to discover current contact names and ids before sending.
|
|
147
|
+
- When you finish your assigned task, use `send` to deliver the result to the correct destination before calling `idle`.
|
|
148
|
+
- `@target:` and similar `@name:` text inside normal content are just text. They do not send anything.
|
|
149
|
+
- Do NOT output content just to "think out loud" between tool calls. Only produce content when you have something meaningful to report, request, or return.
|
|
150
|
+
- You receive messages as: <message from="uuid">content</message>
|
|
151
|
+
- Your previously sent messages appear in context as: <message to="uuid">content</message>
|
|
152
|
+
- System context is injected as: <system>content</system>
|
|
153
|
+
"""
|
|
154
|
+
|
|
155
|
+
FILE_PATH_GUIDANCE = """\
|
|
156
|
+
## File Path Rules
|
|
157
|
+
|
|
158
|
+
- Always use relative paths for file operations (read, edit, exec). Do not guess absolute paths like /workspace or /home.
|
|
159
|
+
- If you need the absolute working directory, run `pwd` first.
|
|
160
|
+
"""
|
|
161
|
+
|
|
162
|
+
ASSISTANT_ONLY_PROMPT = """\
|
|
163
|
+
## Assistant-Only Communication Rules
|
|
164
|
+
|
|
165
|
+
- Your content is pushed directly to the frontend chat panel as your reply to the Human.
|
|
166
|
+
- Plain content is your reply to the Human.
|
|
167
|
+
- If you need to send a message to a connected node instead of the Human, use `send`.
|
|
168
|
+
- After replying directly to the Human, if you have no further immediate action, call `idle` in the same response instead of continuing with another text-only turn.
|
|
169
|
+
- Do not repeat or restate a Human-facing reply that you already sent unless you have genuinely new information or a correction.
|
|
170
|
+
- Entering a waiting state still requires an explicit `idle` tool call.
|
|
171
|
+
"""
|
|
172
|
+
|
|
173
|
+
DEFAULT_AGENT_ROLE_PROMPT = (
|
|
174
|
+
"You are a helpful agent. Complete the assigned task only when it clearly fits your role and capabilities, "
|
|
175
|
+
"and otherwise delegate or hand it off immediately to the right agent before reporting results back."
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
_MANAGEMENT_TOOL_NAMES = frozenset(
|
|
179
|
+
{
|
|
180
|
+
"manage_providers",
|
|
181
|
+
"manage_roles",
|
|
182
|
+
"manage_settings",
|
|
183
|
+
"manage_prompts",
|
|
184
|
+
}
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def _normalize_tools(tools: list[str]) -> set[str]:
|
|
189
|
+
return {tool_name.strip() for tool_name in tools if tool_name.strip()}
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def _build_conditional_tool_guidance(tools: list[str]) -> list[str]:
|
|
193
|
+
tool_names = _normalize_tools(tools)
|
|
194
|
+
parts: list[str] = []
|
|
195
|
+
|
|
196
|
+
if "idle" in tool_names:
|
|
197
|
+
parts.append(IDLE_TOOL_GUIDANCE.strip())
|
|
198
|
+
if "sleep" in tool_names:
|
|
199
|
+
parts.append(SLEEP_TOOL_GUIDANCE.strip())
|
|
200
|
+
if "todo" in tool_names:
|
|
201
|
+
parts.append(TODO_TOOL_GUIDANCE.strip())
|
|
202
|
+
if "create_workflow" in tool_names:
|
|
203
|
+
parts.append(CREATE_WORKFLOW_TOOL_GUIDANCE.strip())
|
|
204
|
+
if "delete_workflow" in tool_names:
|
|
205
|
+
parts.append(DELETE_WORKFLOW_TOOL_GUIDANCE.strip())
|
|
206
|
+
if "set_permissions" in tool_names:
|
|
207
|
+
parts.append(SET_PERMISSIONS_TOOL_GUIDANCE.strip())
|
|
208
|
+
if "create_agent" in tool_names:
|
|
209
|
+
parts.append(CREATE_AGENT_TOOL_GUIDANCE.strip())
|
|
210
|
+
if "create_agent" in tool_names:
|
|
211
|
+
parts.append(DELEGATION_GENERAL_GUIDANCE.strip())
|
|
212
|
+
if "connect" in tool_names:
|
|
213
|
+
parts.append(CONNECT_TOOL_GUIDANCE.strip())
|
|
214
|
+
if "contacts" in tool_names:
|
|
215
|
+
parts.append(CONTACTS_TOOL_GUIDANCE.strip())
|
|
216
|
+
if "send" in tool_names:
|
|
217
|
+
parts.append(SEND_TOOL_GUIDANCE.strip())
|
|
218
|
+
if "list_roles" in tool_names:
|
|
219
|
+
parts.append(LIST_ROLES_TOOL_GUIDANCE.strip())
|
|
220
|
+
if "list_workflows" in tool_names:
|
|
221
|
+
parts.append(LIST_WORKFLOWS_TOOL_GUIDANCE.strip())
|
|
222
|
+
if "list_tools" in tool_names:
|
|
223
|
+
parts.append(LIST_TOOLS_TOOL_GUIDANCE.strip())
|
|
224
|
+
if _MANAGEMENT_TOOL_NAMES & tool_names:
|
|
225
|
+
parts.append(MANAGE_TOOLS_GUIDANCE.strip())
|
|
226
|
+
return parts
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def compose_system_prompt(
|
|
230
|
+
role_prompt: str,
|
|
231
|
+
custom_prompt: str = "",
|
|
232
|
+
is_assistant: bool = False,
|
|
233
|
+
tools: list[str] | None = None,
|
|
234
|
+
) -> str:
|
|
235
|
+
custom_prompt_text = custom_prompt.strip()
|
|
236
|
+
role_specific_prompt = role_prompt.strip()
|
|
237
|
+
|
|
238
|
+
parts = [
|
|
239
|
+
COMMUNICATION_USAGE_GUIDANCE.strip(),
|
|
240
|
+
FILE_PATH_GUIDANCE.strip(),
|
|
241
|
+
]
|
|
242
|
+
if tools is not None:
|
|
243
|
+
parts.extend(_build_conditional_tool_guidance(tools))
|
|
244
|
+
if is_assistant:
|
|
245
|
+
parts.append(ASSISTANT_ONLY_PROMPT.strip())
|
|
246
|
+
if custom_prompt_text:
|
|
247
|
+
parts.append(custom_prompt_text)
|
|
248
|
+
if role_specific_prompt:
|
|
249
|
+
parts.append(role_specific_prompt)
|
|
250
|
+
return "\n\n".join(parts).strip()
|