flock-core 0.4.543__py3-none-any.whl → 0.5.0__py3-none-any.whl
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.
Potentially problematic release.
This version of flock-core might be problematic. Click here for more details.
- flock/__init__.py +12 -217
- flock/agent.py +1079 -0
- flock/api/themes.py +71 -0
- flock/artifacts.py +86 -0
- flock/cli.py +147 -0
- flock/components.py +189 -0
- flock/dashboard/__init__.py +30 -0
- flock/dashboard/collector.py +559 -0
- flock/dashboard/events.py +188 -0
- flock/dashboard/graph_builder.py +563 -0
- flock/dashboard/launcher.py +235 -0
- flock/dashboard/models/graph.py +156 -0
- flock/dashboard/service.py +991 -0
- flock/dashboard/static_v2/assets/index-DFRnI_mt.js +111 -0
- flock/dashboard/static_v2/assets/index-fPLNdmp1.css +1 -0
- flock/dashboard/static_v2/index.html +13 -0
- flock/dashboard/websocket.py +246 -0
- flock/engines/__init__.py +6 -0
- flock/engines/dspy_engine.py +932 -0
- flock/examples.py +131 -0
- flock/frontend/README.md +778 -0
- flock/frontend/docs/DESIGN_SYSTEM.md +1980 -0
- flock/frontend/index.html +12 -0
- flock/frontend/package-lock.json +4337 -0
- flock/frontend/package.json +48 -0
- flock/frontend/src/App.tsx +139 -0
- flock/frontend/src/__tests__/integration/graph-snapshot.test.tsx +647 -0
- flock/frontend/src/__tests__/integration/indexeddb-persistence.test.tsx +699 -0
- flock/frontend/src/components/common/BuildInfo.tsx +39 -0
- flock/frontend/src/components/common/EmptyState.module.css +115 -0
- flock/frontend/src/components/common/EmptyState.tsx +128 -0
- flock/frontend/src/components/common/ErrorBoundary.module.css +169 -0
- flock/frontend/src/components/common/ErrorBoundary.tsx +118 -0
- flock/frontend/src/components/common/KeyboardShortcutsDialog.css +251 -0
- flock/frontend/src/components/common/KeyboardShortcutsDialog.tsx +151 -0
- flock/frontend/src/components/common/LoadingSpinner.module.css +97 -0
- flock/frontend/src/components/common/LoadingSpinner.tsx +29 -0
- flock/frontend/src/components/controls/PublishControl.css +547 -0
- flock/frontend/src/components/controls/PublishControl.test.tsx +543 -0
- flock/frontend/src/components/controls/PublishControl.tsx +432 -0
- flock/frontend/src/components/details/DetailWindowContainer.tsx +58 -0
- flock/frontend/src/components/details/LiveOutputTab.test.tsx +792 -0
- flock/frontend/src/components/details/LiveOutputTab.tsx +220 -0
- flock/frontend/src/components/details/MessageDetailWindow.tsx +439 -0
- flock/frontend/src/components/details/MessageHistoryTab.tsx +374 -0
- flock/frontend/src/components/details/NodeDetailWindow.test.tsx +501 -0
- flock/frontend/src/components/details/NodeDetailWindow.tsx +218 -0
- flock/frontend/src/components/details/RunStatusTab.tsx +348 -0
- flock/frontend/src/components/details/tabs.test.tsx +1015 -0
- flock/frontend/src/components/filters/ArtifactTypeFilter.tsx +21 -0
- flock/frontend/src/components/filters/CorrelationIDFilter.module.css +102 -0
- flock/frontend/src/components/filters/CorrelationIDFilter.test.tsx +197 -0
- flock/frontend/src/components/filters/CorrelationIDFilter.tsx +121 -0
- flock/frontend/src/components/filters/FilterFlyout.module.css +104 -0
- flock/frontend/src/components/filters/FilterFlyout.tsx +80 -0
- flock/frontend/src/components/filters/FilterPills.module.css +220 -0
- flock/frontend/src/components/filters/FilterPills.test.tsx +189 -0
- flock/frontend/src/components/filters/FilterPills.tsx +143 -0
- flock/frontend/src/components/filters/ProducerFilter.tsx +21 -0
- flock/frontend/src/components/filters/SavedFiltersControl.module.css +60 -0
- flock/frontend/src/components/filters/SavedFiltersControl.test.tsx +158 -0
- flock/frontend/src/components/filters/SavedFiltersControl.tsx +159 -0
- flock/frontend/src/components/filters/TagFilter.tsx +21 -0
- flock/frontend/src/components/filters/TimeRangeFilter.module.css +115 -0
- flock/frontend/src/components/filters/TimeRangeFilter.test.tsx +154 -0
- flock/frontend/src/components/filters/TimeRangeFilter.tsx +110 -0
- flock/frontend/src/components/filters/VisibilityFilter.tsx +21 -0
- flock/frontend/src/components/graph/AgentNode.test.tsx +77 -0
- flock/frontend/src/components/graph/AgentNode.tsx +324 -0
- flock/frontend/src/components/graph/GraphCanvas.tsx +613 -0
- flock/frontend/src/components/graph/MessageFlowEdge.tsx +128 -0
- flock/frontend/src/components/graph/MessageNode.test.tsx +64 -0
- flock/frontend/src/components/graph/MessageNode.tsx +129 -0
- flock/frontend/src/components/graph/MiniMap.tsx +47 -0
- flock/frontend/src/components/graph/TransformEdge.tsx +123 -0
- flock/frontend/src/components/layout/DashboardLayout.css +420 -0
- flock/frontend/src/components/layout/DashboardLayout.tsx +287 -0
- flock/frontend/src/components/layout/Header.module.css +88 -0
- flock/frontend/src/components/layout/Header.tsx +52 -0
- flock/frontend/src/components/modules/HistoricalArtifactsModule.module.css +288 -0
- flock/frontend/src/components/modules/HistoricalArtifactsModule.tsx +450 -0
- flock/frontend/src/components/modules/HistoricalArtifactsModuleWrapper.tsx +13 -0
- flock/frontend/src/components/modules/JsonAttributeRenderer.tsx +140 -0
- flock/frontend/src/components/modules/ModuleRegistry.test.ts +333 -0
- flock/frontend/src/components/modules/ModuleRegistry.ts +93 -0
- flock/frontend/src/components/modules/ModuleWindow.tsx +223 -0
- flock/frontend/src/components/modules/TraceModuleJaeger.tsx +1971 -0
- flock/frontend/src/components/modules/TraceModuleJaegerWrapper.tsx +13 -0
- flock/frontend/src/components/modules/registerModules.ts +29 -0
- flock/frontend/src/components/settings/AdvancedSettings.tsx +175 -0
- flock/frontend/src/components/settings/AppearanceSettings.tsx +185 -0
- flock/frontend/src/components/settings/GraphSettings.tsx +110 -0
- flock/frontend/src/components/settings/MultiSelect.tsx +235 -0
- flock/frontend/src/components/settings/SettingsPanel.css +327 -0
- flock/frontend/src/components/settings/SettingsPanel.tsx +131 -0
- flock/frontend/src/components/settings/ThemeSelector.tsx +298 -0
- flock/frontend/src/components/settings/TracingSettings.tsx +404 -0
- flock/frontend/src/hooks/useKeyboardShortcuts.ts +148 -0
- flock/frontend/src/hooks/useModulePersistence.test.ts +442 -0
- flock/frontend/src/hooks/useModulePersistence.ts +154 -0
- flock/frontend/src/hooks/useModules.ts +157 -0
- flock/frontend/src/hooks/usePersistence.ts +141 -0
- flock/frontend/src/main.tsx +13 -0
- flock/frontend/src/services/api.ts +337 -0
- flock/frontend/src/services/graphService.test.ts +330 -0
- flock/frontend/src/services/graphService.ts +75 -0
- flock/frontend/src/services/indexeddb.test.ts +793 -0
- flock/frontend/src/services/indexeddb.ts +848 -0
- flock/frontend/src/services/layout.test.ts +437 -0
- flock/frontend/src/services/layout.ts +357 -0
- flock/frontend/src/services/themeApplicator.ts +140 -0
- flock/frontend/src/services/themeService.ts +77 -0
- flock/frontend/src/services/websocket.ts +650 -0
- flock/frontend/src/store/filterStore.test.ts +250 -0
- flock/frontend/src/store/filterStore.ts +272 -0
- flock/frontend/src/store/graphStore.test.ts +570 -0
- flock/frontend/src/store/graphStore.ts +462 -0
- flock/frontend/src/store/moduleStore.test.ts +253 -0
- flock/frontend/src/store/moduleStore.ts +75 -0
- flock/frontend/src/store/settingsStore.ts +188 -0
- flock/frontend/src/store/streamStore.ts +68 -0
- flock/frontend/src/store/uiStore.test.ts +54 -0
- flock/frontend/src/store/uiStore.ts +122 -0
- flock/frontend/src/store/wsStore.ts +34 -0
- flock/frontend/src/styles/index.css +15 -0
- flock/frontend/src/styles/scrollbar.css +47 -0
- flock/frontend/src/styles/variables.css +488 -0
- flock/frontend/src/test/setup.ts +1 -0
- flock/frontend/src/types/filters.ts +47 -0
- flock/frontend/src/types/graph.ts +95 -0
- flock/frontend/src/types/modules.ts +10 -0
- flock/frontend/src/types/theme.ts +55 -0
- flock/frontend/src/utils/artifacts.ts +24 -0
- flock/frontend/src/utils/mockData.ts +98 -0
- flock/frontend/src/utils/performance.ts +16 -0
- flock/frontend/src/vite-env.d.ts +17 -0
- flock/frontend/tsconfig.json +27 -0
- flock/frontend/tsconfig.node.json +11 -0
- flock/frontend/vite.config.ts +25 -0
- flock/frontend/vitest.config.ts +11 -0
- flock/{core/util → helper}/cli_helper.py +9 -5
- flock/{core/logging → logging}/__init__.py +2 -3
- flock/logging/auto_trace.py +159 -0
- flock/{core/logging → logging}/formatters/enum_builder.py +3 -4
- flock/{core/logging → logging}/formatters/theme_builder.py +19 -44
- flock/{core/logging → logging}/formatters/themed_formatter.py +69 -107
- flock/{core/logging → logging}/logging.py +78 -61
- flock/{core/logging → logging}/telemetry.py +66 -26
- flock/{core/logging → logging}/telemetry_exporter/base_exporter.py +2 -2
- flock/logging/telemetry_exporter/duckdb_exporter.py +216 -0
- flock/{core/logging → logging}/telemetry_exporter/file_exporter.py +13 -10
- flock/{core/logging → logging}/telemetry_exporter/sqlite_exporter.py +2 -3
- flock/logging/trace_and_logged.py +304 -0
- flock/mcp/__init__.py +91 -0
- flock/{core/mcp/mcp_client.py → mcp/client.py} +131 -158
- flock/{core/mcp/mcp_config.py → mcp/config.py} +86 -132
- flock/mcp/manager.py +286 -0
- flock/mcp/servers/sse/__init__.py +1 -1
- flock/mcp/servers/sse/flock_sse_server.py +16 -58
- flock/mcp/servers/stdio/__init__.py +1 -1
- flock/mcp/servers/stdio/flock_stdio_server.py +13 -53
- flock/mcp/servers/streamable_http/flock_streamable_http_server.py +22 -67
- flock/mcp/servers/websockets/flock_websocket_server.py +12 -45
- flock/{core/mcp/flock_mcp_tool_base.py → mcp/tool.py} +24 -78
- flock/mcp/types/__init__.py +42 -0
- flock/{core/mcp → mcp}/types/callbacks.py +12 -15
- flock/{core/mcp → mcp}/types/factories.py +7 -6
- flock/{core/mcp → mcp}/types/handlers.py +13 -18
- flock/{core/mcp → mcp}/types/types.py +70 -74
- flock/{core/mcp → mcp}/util/helpers.py +3 -3
- flock/orchestrator.py +970 -0
- flock/registry.py +148 -0
- flock/runtime.py +262 -0
- flock/service.py +277 -0
- flock/store.py +1214 -0
- flock/subscription.py +111 -0
- flock/themes/andromeda.toml +1 -1
- flock/themes/apple-system-colors.toml +1 -1
- flock/themes/arcoiris.toml +1 -1
- flock/themes/atomonelight.toml +1 -1
- flock/themes/ayu copy.toml +1 -1
- flock/themes/ayu-light.toml +1 -1
- flock/themes/belafonte-day.toml +1 -1
- flock/themes/belafonte-night.toml +1 -1
- flock/themes/blulocodark.toml +1 -1
- flock/themes/breeze.toml +1 -1
- flock/themes/broadcast.toml +1 -1
- flock/themes/brogrammer.toml +1 -1
- flock/themes/builtin-dark.toml +1 -1
- flock/themes/builtin-pastel-dark.toml +1 -1
- flock/themes/catppuccin-latte.toml +1 -1
- flock/themes/catppuccin-macchiato.toml +1 -1
- flock/themes/catppuccin-mocha.toml +1 -1
- flock/themes/cga.toml +1 -1
- flock/themes/chalk.toml +1 -1
- flock/themes/ciapre.toml +1 -1
- flock/themes/coffee-theme.toml +1 -1
- flock/themes/cyberpunkscarletprotocol.toml +1 -1
- flock/themes/dark+.toml +1 -1
- flock/themes/darkermatrix.toml +1 -1
- flock/themes/darkmatrix.toml +2 -2
- flock/themes/darkside.toml +1 -1
- flock/themes/deep.toml +2 -2
- flock/themes/desert.toml +1 -1
- flock/themes/django.toml +1 -1
- flock/themes/djangosmooth.toml +1 -1
- flock/themes/doomone.toml +1 -1
- flock/themes/dotgov.toml +1 -1
- flock/themes/dracula+.toml +1 -1
- flock/themes/duckbones.toml +1 -1
- flock/themes/encom.toml +1 -1
- flock/themes/espresso.toml +1 -1
- flock/themes/everblush.toml +1 -1
- flock/themes/fairyfloss.toml +1 -1
- flock/themes/fideloper.toml +1 -1
- flock/themes/fishtank.toml +1 -1
- flock/themes/flexoki-light.toml +1 -1
- flock/themes/floraverse.toml +1 -1
- flock/themes/framer.toml +1 -1
- flock/themes/galizur.toml +1 -1
- flock/themes/github.toml +1 -1
- flock/themes/grass.toml +1 -1
- flock/themes/grey-green.toml +1 -1
- flock/themes/gruvboxlight.toml +1 -1
- flock/themes/guezwhoz.toml +1 -1
- flock/themes/harper.toml +1 -1
- flock/themes/hax0r-blue.toml +1 -1
- flock/themes/hopscotch.256.toml +1 -1
- flock/themes/ic-green-ppl.toml +1 -1
- flock/themes/iceberg-dark.toml +1 -1
- flock/themes/japanesque.toml +1 -1
- flock/themes/jubi.toml +1 -1
- flock/themes/kibble.toml +1 -1
- flock/themes/kolorit.toml +1 -1
- flock/themes/kurokula.toml +1 -1
- flock/themes/materialdesigncolors.toml +1 -1
- flock/themes/matrix.toml +1 -1
- flock/themes/mellifluous.toml +1 -1
- flock/themes/midnight-in-mojave.toml +1 -1
- flock/themes/monokai-remastered.toml +1 -1
- flock/themes/monokai-soda.toml +1 -1
- flock/themes/neon.toml +1 -1
- flock/themes/neopolitan.toml +5 -5
- flock/themes/nord-light.toml +1 -1
- flock/themes/ocean.toml +1 -1
- flock/themes/onehalfdark.toml +1 -1
- flock/themes/onehalflight.toml +1 -1
- flock/themes/palenighthc.toml +1 -1
- flock/themes/paulmillr.toml +1 -1
- flock/themes/pencildark.toml +1 -1
- flock/themes/pnevma.toml +1 -1
- flock/themes/purple-rain.toml +1 -1
- flock/themes/purplepeter.toml +1 -1
- flock/themes/raycast-dark.toml +1 -1
- flock/themes/red-sands.toml +1 -1
- flock/themes/relaxed.toml +1 -1
- flock/themes/retro.toml +1 -1
- flock/themes/rose-pine.toml +1 -1
- flock/themes/royal.toml +1 -1
- flock/themes/ryuuko.toml +1 -1
- flock/themes/sakura.toml +1 -1
- flock/themes/scarlet-protocol.toml +1 -1
- flock/themes/seoulbones-dark.toml +1 -1
- flock/themes/shades-of-purple.toml +1 -1
- flock/themes/smyck.toml +1 -1
- flock/themes/softserver.toml +1 -1
- flock/themes/solarized-darcula.toml +1 -1
- flock/themes/square.toml +1 -1
- flock/themes/sugarplum.toml +1 -1
- flock/themes/thayer-bright.toml +1 -1
- flock/themes/tokyonight.toml +1 -1
- flock/themes/tomorrow.toml +1 -1
- flock/themes/ubuntu.toml +1 -1
- flock/themes/ultradark.toml +1 -1
- flock/themes/ultraviolent.toml +1 -1
- flock/themes/unikitty.toml +1 -1
- flock/themes/urple.toml +1 -1
- flock/themes/vesper.toml +1 -1
- flock/themes/vimbones.toml +1 -1
- flock/themes/wildcherry.toml +1 -1
- flock/themes/wilmersdorf.toml +1 -1
- flock/themes/wryan.toml +1 -1
- flock/themes/xcodedarkhc.toml +1 -1
- flock/themes/xcodelight.toml +1 -1
- flock/themes/zenbones-light.toml +1 -1
- flock/themes/zenwritten-dark.toml +1 -1
- flock/utilities.py +301 -0
- flock/utility/output_utility_component.py +226 -0
- flock/visibility.py +107 -0
- flock_core-0.5.0.dist-info/METADATA +964 -0
- flock_core-0.5.0.dist-info/RECORD +525 -0
- flock_core-0.5.0.dist-info/entry_points.txt +2 -0
- {flock_core-0.4.543.dist-info → flock_core-0.5.0.dist-info}/licenses/LICENSE +1 -1
- flock/adapter/__init__.py +0 -14
- flock/adapter/azure_adapter.py +0 -68
- flock/adapter/chroma_adapter.py +0 -73
- flock/adapter/faiss_adapter.py +0 -97
- flock/adapter/pinecone_adapter.py +0 -51
- flock/adapter/vector_base.py +0 -47
- flock/cli/assets/release_notes.md +0 -140
- flock/cli/config.py +0 -8
- flock/cli/constants.py +0 -36
- flock/cli/create_agent.py +0 -1
- flock/cli/create_flock.py +0 -280
- flock/cli/execute_flock.py +0 -620
- flock/cli/load_agent.py +0 -1
- flock/cli/load_examples.py +0 -1
- flock/cli/load_flock.py +0 -192
- flock/cli/load_release_notes.py +0 -20
- flock/cli/loaded_flock_cli.py +0 -254
- flock/cli/manage_agents.py +0 -459
- flock/cli/registry_management.py +0 -889
- flock/cli/runner.py +0 -41
- flock/cli/settings.py +0 -857
- flock/cli/utils.py +0 -135
- flock/cli/view_results.py +0 -29
- flock/cli/yaml_editor.py +0 -396
- flock/config.py +0 -56
- flock/core/__init__.py +0 -44
- flock/core/api/__init__.py +0 -10
- flock/core/api/custom_endpoint.py +0 -45
- flock/core/api/endpoints.py +0 -262
- flock/core/api/main.py +0 -162
- flock/core/api/models.py +0 -101
- flock/core/api/run_store.py +0 -224
- flock/core/api/runner.py +0 -44
- flock/core/api/service.py +0 -214
- flock/core/config/flock_agent_config.py +0 -11
- flock/core/config/scheduled_agent_config.py +0 -40
- flock/core/context/context.py +0 -214
- flock/core/context/context_manager.py +0 -40
- flock/core/context/context_vars.py +0 -11
- flock/core/evaluation/utils.py +0 -395
- flock/core/execution/batch_executor.py +0 -369
- flock/core/execution/evaluation_executor.py +0 -438
- flock/core/execution/local_executor.py +0 -31
- flock/core/execution/opik_executor.py +0 -103
- flock/core/execution/temporal_executor.py +0 -166
- flock/core/flock.py +0 -1003
- flock/core/flock_agent.py +0 -1258
- flock/core/flock_evaluator.py +0 -60
- flock/core/flock_factory.py +0 -513
- flock/core/flock_module.py +0 -207
- flock/core/flock_registry.py +0 -702
- flock/core/flock_router.py +0 -83
- flock/core/flock_scheduler.py +0 -166
- flock/core/flock_server_manager.py +0 -136
- flock/core/interpreter/python_interpreter.py +0 -689
- flock/core/logging/live_capture.py +0 -137
- flock/core/logging/trace_and_logged.py +0 -59
- flock/core/mcp/__init__.py +0 -1
- flock/core/mcp/flock_mcp_server.py +0 -640
- flock/core/mcp/mcp_client_manager.py +0 -201
- flock/core/mcp/types/__init__.py +0 -1
- flock/core/mixin/dspy_integration.py +0 -445
- flock/core/mixin/prompt_parser.py +0 -125
- flock/core/serialization/__init__.py +0 -13
- flock/core/serialization/callable_registry.py +0 -52
- flock/core/serialization/flock_serializer.py +0 -854
- flock/core/serialization/json_encoder.py +0 -41
- flock/core/serialization/secure_serializer.py +0 -175
- flock/core/serialization/serializable.py +0 -342
- flock/core/serialization/serialization_utils.py +0 -409
- flock/core/util/file_path_utils.py +0 -223
- flock/core/util/hydrator.py +0 -309
- flock/core/util/input_resolver.py +0 -141
- flock/core/util/loader.py +0 -59
- flock/core/util/splitter.py +0 -219
- flock/di.py +0 -41
- flock/evaluators/__init__.py +0 -1
- flock/evaluators/declarative/__init__.py +0 -1
- flock/evaluators/declarative/declarative_evaluator.py +0 -217
- flock/evaluators/memory/memory_evaluator.py +0 -90
- flock/evaluators/test/test_case_evaluator.py +0 -38
- flock/evaluators/zep/zep_evaluator.py +0 -59
- flock/modules/__init__.py +0 -1
- flock/modules/assertion/__init__.py +0 -1
- flock/modules/assertion/assertion_module.py +0 -286
- flock/modules/callback/__init__.py +0 -1
- flock/modules/callback/callback_module.py +0 -91
- flock/modules/enterprise_memory/README.md +0 -99
- flock/modules/enterprise_memory/enterprise_memory_module.py +0 -526
- flock/modules/mem0/__init__.py +0 -1
- flock/modules/mem0/mem0_module.py +0 -126
- flock/modules/mem0_async/__init__.py +0 -1
- flock/modules/mem0_async/async_mem0_module.py +0 -126
- flock/modules/memory/__init__.py +0 -1
- flock/modules/memory/memory_module.py +0 -429
- flock/modules/memory/memory_parser.py +0 -125
- flock/modules/memory/memory_storage.py +0 -736
- flock/modules/output/__init__.py +0 -1
- flock/modules/output/output_module.py +0 -196
- flock/modules/performance/__init__.py +0 -1
- flock/modules/performance/metrics_module.py +0 -678
- flock/modules/zep/__init__.py +0 -1
- flock/modules/zep/zep_module.py +0 -192
- flock/platform/docker_tools.py +0 -49
- flock/platform/jaeger_install.py +0 -86
- flock/routers/__init__.py +0 -1
- flock/routers/agent/__init__.py +0 -1
- flock/routers/agent/agent_router.py +0 -236
- flock/routers/agent/handoff_agent.py +0 -58
- flock/routers/conditional/conditional_router.py +0 -486
- flock/routers/default/__init__.py +0 -1
- flock/routers/default/default_router.py +0 -80
- flock/routers/feedback/feedback_router.py +0 -114
- flock/routers/list_generator/list_generator_router.py +0 -166
- flock/routers/llm/__init__.py +0 -1
- flock/routers/llm/llm_router.py +0 -365
- flock/tools/__init__.py +0 -0
- flock/tools/azure_tools.py +0 -781
- flock/tools/code_tools.py +0 -167
- flock/tools/file_tools.py +0 -149
- flock/tools/github_tools.py +0 -157
- flock/tools/markdown_tools.py +0 -205
- flock/tools/system_tools.py +0 -9
- flock/tools/text_tools.py +0 -810
- flock/tools/web_tools.py +0 -92
- flock/tools/zendesk_tools.py +0 -501
- flock/webapp/__init__.py +0 -1
- flock/webapp/app/__init__.py +0 -0
- flock/webapp/app/api/__init__.py +0 -0
- flock/webapp/app/api/agent_management.py +0 -237
- flock/webapp/app/api/execution.py +0 -503
- flock/webapp/app/api/flock_management.py +0 -125
- flock/webapp/app/api/registry_viewer.py +0 -29
- flock/webapp/app/chat.py +0 -662
- flock/webapp/app/config.py +0 -104
- flock/webapp/app/dependencies.py +0 -117
- flock/webapp/app/main.py +0 -1086
- flock/webapp/app/middleware.py +0 -113
- flock/webapp/app/models_ui.py +0 -7
- flock/webapp/app/services/__init__.py +0 -0
- flock/webapp/app/services/feedback_file_service.py +0 -363
- flock/webapp/app/services/flock_service.py +0 -345
- flock/webapp/app/services/sharing_models.py +0 -81
- flock/webapp/app/services/sharing_store.py +0 -597
- flock/webapp/app/templates/theme_mapper.html +0 -326
- flock/webapp/app/theme_mapper.py +0 -811
- flock/webapp/app/utils.py +0 -85
- flock/webapp/run.py +0 -219
- flock/webapp/static/css/chat.css +0 -301
- flock/webapp/static/css/components.css +0 -167
- flock/webapp/static/css/header.css +0 -39
- flock/webapp/static/css/layout.css +0 -281
- flock/webapp/static/css/sidebar.css +0 -127
- flock/webapp/static/css/two-pane.css +0 -48
- flock/webapp/templates/base.html +0 -389
- flock/webapp/templates/chat.html +0 -152
- flock/webapp/templates/chat_settings.html +0 -19
- flock/webapp/templates/flock_editor.html +0 -16
- flock/webapp/templates/index.html +0 -12
- flock/webapp/templates/partials/_agent_detail_form.html +0 -93
- flock/webapp/templates/partials/_agent_list.html +0 -18
- flock/webapp/templates/partials/_agent_manager_view.html +0 -51
- flock/webapp/templates/partials/_agent_tools_checklist.html +0 -14
- flock/webapp/templates/partials/_chat_container.html +0 -15
- flock/webapp/templates/partials/_chat_messages.html +0 -57
- flock/webapp/templates/partials/_chat_settings_form.html +0 -85
- flock/webapp/templates/partials/_create_flock_form.html +0 -50
- flock/webapp/templates/partials/_dashboard_flock_detail.html +0 -17
- flock/webapp/templates/partials/_dashboard_flock_file_list.html +0 -16
- flock/webapp/templates/partials/_dashboard_flock_properties_preview.html +0 -28
- flock/webapp/templates/partials/_dashboard_upload_flock_form.html +0 -16
- flock/webapp/templates/partials/_dynamic_input_form_content.html +0 -22
- flock/webapp/templates/partials/_env_vars_table.html +0 -23
- flock/webapp/templates/partials/_execution_form.html +0 -127
- flock/webapp/templates/partials/_execution_view_container.html +0 -28
- flock/webapp/templates/partials/_flock_file_list.html +0 -23
- flock/webapp/templates/partials/_flock_properties_form.html +0 -52
- flock/webapp/templates/partials/_flock_upload_form.html +0 -16
- flock/webapp/templates/partials/_header_flock_status.html +0 -5
- flock/webapp/templates/partials/_live_logs.html +0 -13
- flock/webapp/templates/partials/_load_manager_view.html +0 -49
- flock/webapp/templates/partials/_registry_table.html +0 -25
- flock/webapp/templates/partials/_registry_viewer_content.html +0 -70
- flock/webapp/templates/partials/_results_display.html +0 -78
- flock/webapp/templates/partials/_settings_env_content.html +0 -9
- flock/webapp/templates/partials/_settings_theme_content.html +0 -14
- flock/webapp/templates/partials/_settings_view.html +0 -36
- flock/webapp/templates/partials/_share_chat_link_snippet.html +0 -11
- flock/webapp/templates/partials/_share_link_snippet.html +0 -35
- flock/webapp/templates/partials/_sidebar.html +0 -74
- flock/webapp/templates/partials/_structured_data_view.html +0 -40
- flock/webapp/templates/partials/_theme_preview.html +0 -36
- flock/webapp/templates/registry_viewer.html +0 -84
- flock/webapp/templates/shared_run_page.html +0 -140
- flock/workflow/__init__.py +0 -0
- flock/workflow/activities.py +0 -237
- flock/workflow/agent_activities.py +0 -24
- flock/workflow/agent_execution_activity.py +0 -240
- flock/workflow/flock_workflow.py +0 -225
- flock/workflow/temporal_config.py +0 -96
- flock/workflow/temporal_setup.py +0 -60
- flock_core-0.4.543.dist-info/METADATA +0 -676
- flock_core-0.4.543.dist-info/RECORD +0 -572
- flock_core-0.4.543.dist-info/entry_points.txt +0 -2
- /flock/{core/logging → logging}/formatters/themes.py +0 -0
- /flock/{core/logging → logging}/span_middleware/baggage_span_processor.py +0 -0
- /flock/{core/mcp → mcp}/util/__init__.py +0 -0
- {flock_core-0.4.543.dist-info → flock_core-0.5.0.dist-info}/WHEEL +0 -0
flock/core/flock.py
DELETED
|
@@ -1,1003 +0,0 @@
|
|
|
1
|
-
# src/flock/core/flock.py
|
|
2
|
-
"""High-level orchestrator for managing and executing agents within the Flock framework."""
|
|
3
|
-
|
|
4
|
-
from __future__ import annotations # Ensure forward references work
|
|
5
|
-
|
|
6
|
-
import asyncio
|
|
7
|
-
import contextvars
|
|
8
|
-
import os
|
|
9
|
-
import uuid
|
|
10
|
-
from collections.abc import Awaitable, Callable, Sequence
|
|
11
|
-
from concurrent.futures import ThreadPoolExecutor
|
|
12
|
-
from pathlib import Path
|
|
13
|
-
from typing import (
|
|
14
|
-
TYPE_CHECKING,
|
|
15
|
-
Any,
|
|
16
|
-
Literal,
|
|
17
|
-
TypeVar,
|
|
18
|
-
)
|
|
19
|
-
|
|
20
|
-
# Third-party imports
|
|
21
|
-
from box import Box
|
|
22
|
-
from temporalio import workflow
|
|
23
|
-
|
|
24
|
-
from flock.core.flock_server_manager import FlockServerManager
|
|
25
|
-
from flock.core.mcp.flock_mcp_server import FlockMCPServerBase
|
|
26
|
-
|
|
27
|
-
with workflow.unsafe.imports_passed_through():
|
|
28
|
-
from datasets import Dataset # type: ignore
|
|
29
|
-
|
|
30
|
-
# Assuming run_local_workflow is correctly placed and importable
|
|
31
|
-
from flock.core.execution.local_executor import (
|
|
32
|
-
run_local_workflow,
|
|
33
|
-
)
|
|
34
|
-
|
|
35
|
-
import opik
|
|
36
|
-
from opentelemetry import trace
|
|
37
|
-
from opentelemetry.baggage import get_baggage, set_baggage
|
|
38
|
-
from opik.integrations.dspy.callback import OpikCallback
|
|
39
|
-
from pandas import DataFrame # type: ignore
|
|
40
|
-
from pydantic import BaseModel, Field
|
|
41
|
-
|
|
42
|
-
# Flock core components & utilities
|
|
43
|
-
from flock.config import DEFAULT_MODEL, TELEMETRY
|
|
44
|
-
from flock.core.api.custom_endpoint import (
|
|
45
|
-
FlockEndpoint, # Keep for type hinting custom_endpoints
|
|
46
|
-
)
|
|
47
|
-
from flock.core.context.context import FlockContext
|
|
48
|
-
from flock.core.context.context_manager import initialize_context
|
|
49
|
-
|
|
50
|
-
# Assuming run_temporal_workflow is correctly placed and importable
|
|
51
|
-
from flock.core.execution.temporal_executor import run_temporal_workflow
|
|
52
|
-
from flock.core.flock_evaluator import FlockEvaluator # For type hint
|
|
53
|
-
from flock.core.logging.logging import get_logger
|
|
54
|
-
from flock.core.serialization.serializable import Serializable
|
|
55
|
-
from flock.core.util.cli_helper import init_console
|
|
56
|
-
from flock.workflow.temporal_config import TemporalWorkflowConfig
|
|
57
|
-
|
|
58
|
-
# Import FlockAgent using TYPE_CHECKING to avoid circular import at runtime
|
|
59
|
-
if TYPE_CHECKING:
|
|
60
|
-
# These imports are only for type hints
|
|
61
|
-
from flock.core.flock_agent import FlockAgent
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
# Registry
|
|
65
|
-
from flock.core.flock_registry import get_registry
|
|
66
|
-
|
|
67
|
-
try:
|
|
68
|
-
import pandas as pd # type: ignore
|
|
69
|
-
|
|
70
|
-
PANDAS_AVAILABLE = True
|
|
71
|
-
except ImportError:
|
|
72
|
-
pd = None # type: ignore
|
|
73
|
-
PANDAS_AVAILABLE = False
|
|
74
|
-
|
|
75
|
-
logger = get_logger("flock.api")
|
|
76
|
-
TELEMETRY.setup_tracing() # Setup OpenTelemetry
|
|
77
|
-
tracer = trace.get_tracer(__name__)
|
|
78
|
-
FlockRegistry = get_registry() # Get the registry instance
|
|
79
|
-
|
|
80
|
-
# Define TypeVar for generic class methods like from_dict
|
|
81
|
-
T = TypeVar("T", bound="Flock")
|
|
82
|
-
_R = TypeVar("_R")
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
class Flock(BaseModel, Serializable):
|
|
86
|
-
"""Orchestrator for managing and executing agent systems.
|
|
87
|
-
|
|
88
|
-
Manages agent definitions, context, and execution flow (local or Temporal).
|
|
89
|
-
Relies on FlockSerializer for serialization/deserialization logic.
|
|
90
|
-
Inherits from Pydantic BaseModel and Serializable.
|
|
91
|
-
"""
|
|
92
|
-
|
|
93
|
-
name: str | None = Field(
|
|
94
|
-
default_factory=lambda: f"flock_{uuid.uuid4().hex[:8]}",
|
|
95
|
-
description="A unique identifier for this Flock instance.",
|
|
96
|
-
)
|
|
97
|
-
model: str | None = Field(
|
|
98
|
-
default=DEFAULT_MODEL,
|
|
99
|
-
description="Default model identifier for agents if not specified otherwise.",
|
|
100
|
-
)
|
|
101
|
-
description: str | None = Field(
|
|
102
|
-
default=None,
|
|
103
|
-
description="A brief description of the purpose of this Flock configuration.",
|
|
104
|
-
)
|
|
105
|
-
enable_temporal: bool = Field(
|
|
106
|
-
default=False,
|
|
107
|
-
description="If True, execute workflows via Temporal; otherwise, run locally.",
|
|
108
|
-
)
|
|
109
|
-
enable_opik: bool = Field(
|
|
110
|
-
default=False,
|
|
111
|
-
description="If True, enable Opik for cost tracking and model management.",
|
|
112
|
-
)
|
|
113
|
-
show_flock_banner: bool = Field(
|
|
114
|
-
default=True,
|
|
115
|
-
description="If True, show the Flock banner on console interactions.",
|
|
116
|
-
)
|
|
117
|
-
# --- Temporal Configuration (Optional) ---
|
|
118
|
-
temporal_config: TemporalWorkflowConfig | None = Field(
|
|
119
|
-
default=None,
|
|
120
|
-
description="Optional Temporal settings specific to the workflow execution for this Flock.",
|
|
121
|
-
)
|
|
122
|
-
# --- Temporal Dev/Test Setting ---
|
|
123
|
-
temporal_start_in_process_worker: bool = Field(
|
|
124
|
-
default=True,
|
|
125
|
-
description="If True (default) and enable_temporal=True, start a temporary in-process worker for development/testing convenience. Set to False when using dedicated workers.",
|
|
126
|
-
)
|
|
127
|
-
|
|
128
|
-
benchmark_agent_name: str | None = Field(
|
|
129
|
-
default=None,
|
|
130
|
-
description="The name of the agent to use for the benchmark.",
|
|
131
|
-
)
|
|
132
|
-
benchmark_eval_field: str | None = Field(
|
|
133
|
-
default=None,
|
|
134
|
-
description="The output field to use for the benchmark.",
|
|
135
|
-
)
|
|
136
|
-
benchmark_input_field: str | None = Field(
|
|
137
|
-
default=None,
|
|
138
|
-
description="The input field to use for the benchmark.",
|
|
139
|
-
)
|
|
140
|
-
# Internal agent storage - not part of the Pydantic model for direct serialization
|
|
141
|
-
# Marked with underscore to indicate it's managed internally and accessed via property
|
|
142
|
-
_agents: dict[str, FlockAgent]
|
|
143
|
-
_start_agent_name: str | None = None # For potential pre-configuration
|
|
144
|
-
_start_input: dict = {} # For potential pre-configuration
|
|
145
|
-
|
|
146
|
-
# Internal server storage - not part of the Pydantic model for direct serialization
|
|
147
|
-
_servers: dict[str, FlockMCPServerBase]
|
|
148
|
-
|
|
149
|
-
# Async context-manager for startup and teardown of servers
|
|
150
|
-
# Not part of the pydantic model
|
|
151
|
-
_mgr: FlockServerManager
|
|
152
|
-
|
|
153
|
-
# Pydantic v2 model config
|
|
154
|
-
model_config = {
|
|
155
|
-
"arbitrary_types_allowed": True,
|
|
156
|
-
# Assuming FlockRegistry type might not be serializable by default
|
|
157
|
-
"ignored_types": (type(FlockRegistry),),
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
def _run_sync(self, coro: Awaitable[_R]) -> _R:
|
|
161
|
-
"""Execute *coro* synchronously.
|
|
162
|
-
|
|
163
|
-
* If no loop is running → ``asyncio.run``.
|
|
164
|
-
* Otherwise run ``asyncio.run`` inside a fresh thread **with**
|
|
165
|
-
context-vars propagation.
|
|
166
|
-
"""
|
|
167
|
-
try:
|
|
168
|
-
asyncio.get_running_loop()
|
|
169
|
-
except RuntimeError: # no loop → simple
|
|
170
|
-
return asyncio.run(coro)
|
|
171
|
-
|
|
172
|
-
# A loop is already running – Jupyter / ASGI / etc.
|
|
173
|
-
ctx = contextvars.copy_context() # propagate baggage
|
|
174
|
-
with ThreadPoolExecutor(max_workers=1) as pool:
|
|
175
|
-
future = pool.submit(ctx.run, asyncio.run, coro)
|
|
176
|
-
try:
|
|
177
|
-
return future.result()
|
|
178
|
-
finally:
|
|
179
|
-
if not future.done():
|
|
180
|
-
future.cancel()
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
def _patch_litellm_proxy_imports(self) -> None:
|
|
184
|
-
"""Stub litellm proxy_server to avoid optional proxy deps when not used.
|
|
185
|
-
|
|
186
|
-
Some litellm versions import `litellm.proxy.proxy_server` during standard logging
|
|
187
|
-
to read `general_settings`, which pulls in optional dependencies like `apscheduler`.
|
|
188
|
-
We provide a stub so imports succeed but cold storage remains disabled.
|
|
189
|
-
"""
|
|
190
|
-
try:
|
|
191
|
-
import sys
|
|
192
|
-
import types
|
|
193
|
-
|
|
194
|
-
if "litellm.proxy.proxy_server" not in sys.modules:
|
|
195
|
-
stub = types.ModuleType("litellm.proxy.proxy_server")
|
|
196
|
-
# Minimal surface that cold_storage_handler accesses
|
|
197
|
-
setattr(stub, "general_settings", {})
|
|
198
|
-
sys.modules["litellm.proxy.proxy_server"] = stub
|
|
199
|
-
except Exception as e:
|
|
200
|
-
# Safe to ignore; worst case litellm will log a warning
|
|
201
|
-
logger.debug(f"Failed to stub litellm proxy_server: {e}")
|
|
202
|
-
|
|
203
|
-
def __init__(
|
|
204
|
-
self,
|
|
205
|
-
name: str | None = None,
|
|
206
|
-
model: str | None = DEFAULT_MODEL,
|
|
207
|
-
description: str | None = None,
|
|
208
|
-
show_flock_banner: bool = True,
|
|
209
|
-
enable_temporal: bool = False,
|
|
210
|
-
enable_opik: bool = False,
|
|
211
|
-
agents: list[FlockAgent] | None = None,
|
|
212
|
-
servers: list[FlockMCPServerBase] | None = None,
|
|
213
|
-
temporal_config: TemporalWorkflowConfig | None = None,
|
|
214
|
-
temporal_start_in_process_worker: bool = True,
|
|
215
|
-
**kwargs,
|
|
216
|
-
):
|
|
217
|
-
"""Initialize the Flock orchestrator."""
|
|
218
|
-
# Use provided name or generate default BEFORE super init if needed elsewhere
|
|
219
|
-
effective_name = name or f"flock_{uuid.uuid4().hex[:8]}"
|
|
220
|
-
|
|
221
|
-
# Initialize Pydantic fields
|
|
222
|
-
super().__init__(
|
|
223
|
-
name=effective_name,
|
|
224
|
-
model=model,
|
|
225
|
-
description=description,
|
|
226
|
-
enable_temporal=enable_temporal,
|
|
227
|
-
enable_opik=enable_opik,
|
|
228
|
-
show_flock_banner=show_flock_banner,
|
|
229
|
-
temporal_config=temporal_config,
|
|
230
|
-
temporal_start_in_process_worker=temporal_start_in_process_worker,
|
|
231
|
-
**kwargs,
|
|
232
|
-
)
|
|
233
|
-
|
|
234
|
-
# Initialize runtime attributes AFTER super().__init__()
|
|
235
|
-
self._agents = {}
|
|
236
|
-
self._servers = {}
|
|
237
|
-
self._start_agent_name = None
|
|
238
|
-
self._start_input = {}
|
|
239
|
-
self._mgr = FlockServerManager()
|
|
240
|
-
|
|
241
|
-
self._patch_litellm_proxy_imports()
|
|
242
|
-
|
|
243
|
-
# Register passed servers
|
|
244
|
-
# (need to be registered first so that agents can retrieve them from the registry)
|
|
245
|
-
# This will also add them to the managed list of self._mgr
|
|
246
|
-
if servers:
|
|
247
|
-
from flock.core.mcp.flock_mcp_server import (
|
|
248
|
-
FlockMCPServerBase as ConcreteFlockMCPServer,
|
|
249
|
-
)
|
|
250
|
-
|
|
251
|
-
for server in servers:
|
|
252
|
-
if isinstance(server, ConcreteFlockMCPServer):
|
|
253
|
-
self.add_server(server)
|
|
254
|
-
else:
|
|
255
|
-
logger.warning(
|
|
256
|
-
f"Item provided in 'servers' list is not a FlockMCPServer: {type(server)}"
|
|
257
|
-
)
|
|
258
|
-
|
|
259
|
-
# Register passed agents
|
|
260
|
-
if agents:
|
|
261
|
-
from flock.core.flock_agent import (
|
|
262
|
-
FlockAgent as ConcreteFlockAgent, # Local import
|
|
263
|
-
)
|
|
264
|
-
|
|
265
|
-
for agent in agents:
|
|
266
|
-
if isinstance(agent, ConcreteFlockAgent):
|
|
267
|
-
self.add_agent(agent)
|
|
268
|
-
else:
|
|
269
|
-
logger.warning(
|
|
270
|
-
f"Item provided in 'agents' list is not a FlockAgent: {type(agent)}"
|
|
271
|
-
)
|
|
272
|
-
|
|
273
|
-
# Initialize console if needed for banner
|
|
274
|
-
if self.show_flock_banner: # Check instance attribute
|
|
275
|
-
init_console(clear_screen=True, show_banner=self.show_flock_banner)
|
|
276
|
-
|
|
277
|
-
# Set Temporal debug environment variable
|
|
278
|
-
self._set_temporal_debug_flag()
|
|
279
|
-
|
|
280
|
-
# Ensure session ID exists in baggage
|
|
281
|
-
self._ensure_session_id()
|
|
282
|
-
|
|
283
|
-
FlockRegistry.discover_and_register_components()
|
|
284
|
-
|
|
285
|
-
if self.enable_opik:
|
|
286
|
-
import dspy
|
|
287
|
-
|
|
288
|
-
opik.configure(use_local=True, automatic_approvals=True)
|
|
289
|
-
opik_callback = OpikCallback(project_name=self.name, log_graph=True)
|
|
290
|
-
dspy.settings.configure(
|
|
291
|
-
callbacks=[opik_callback],
|
|
292
|
-
)
|
|
293
|
-
|
|
294
|
-
logger.info(
|
|
295
|
-
"Flock instance initialized",
|
|
296
|
-
name=self.name,
|
|
297
|
-
model=self.model,
|
|
298
|
-
enable_temporal=self.enable_temporal,
|
|
299
|
-
)
|
|
300
|
-
|
|
301
|
-
def prepare_benchmark(
|
|
302
|
-
self,
|
|
303
|
-
agent: FlockAgent | str | None = None,
|
|
304
|
-
input_field: str | None = None,
|
|
305
|
-
eval_field: str | None = None,
|
|
306
|
-
):
|
|
307
|
-
"""Prepare a benchmark for the Flock instance."""
|
|
308
|
-
from flock.core.flock_agent import FlockAgent as ConcreteFlockAgent
|
|
309
|
-
|
|
310
|
-
logger.info(
|
|
311
|
-
f"Preparing benchmark for Flock instance '{self.name}' with agent '{agent}'."
|
|
312
|
-
)
|
|
313
|
-
|
|
314
|
-
name = agent.name if isinstance(agent, ConcreteFlockAgent) else agent
|
|
315
|
-
|
|
316
|
-
if self._agents.get(name) is None:
|
|
317
|
-
raise ValueError(
|
|
318
|
-
f"Agent '{name}' not found in Flock instance '{self.name}'."
|
|
319
|
-
)
|
|
320
|
-
|
|
321
|
-
self.benchmark_agent_name = name
|
|
322
|
-
self.benchmark_eval_field = eval_field
|
|
323
|
-
self.benchmark_input_field = input_field
|
|
324
|
-
|
|
325
|
-
def inspect(self):
|
|
326
|
-
"""Inspect the Flock instance."""
|
|
327
|
-
logger.info(
|
|
328
|
-
f"Inspecting Flock instance '{self.name}' with start agent '{self.benchmark_agent_name}' and input '{input}'."
|
|
329
|
-
)
|
|
330
|
-
|
|
331
|
-
async def run(input: dict[str, Any]) -> dict[str, Any]:
|
|
332
|
-
"""Inspect the Flock instance."""
|
|
333
|
-
logger.info(
|
|
334
|
-
f"Inspecting Flock instance '{self.name}' with start agent '{self.benchmark_agent_name}' and input '{input}'."
|
|
335
|
-
)
|
|
336
|
-
msg_content = input.get("messages")[0].get("content")
|
|
337
|
-
|
|
338
|
-
agent_input = {self.benchmark_input_field: msg_content}
|
|
339
|
-
|
|
340
|
-
result = await self.run_async(
|
|
341
|
-
start_agent=self.benchmark_agent_name,
|
|
342
|
-
input=agent_input,
|
|
343
|
-
box_result=False,
|
|
344
|
-
)
|
|
345
|
-
|
|
346
|
-
agent_output = result.get(
|
|
347
|
-
self.benchmark_eval_field, "No answer found"
|
|
348
|
-
)
|
|
349
|
-
|
|
350
|
-
return {
|
|
351
|
-
"output": agent_output,
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
return run
|
|
355
|
-
|
|
356
|
-
def _set_temporal_debug_flag(self):
|
|
357
|
-
"""Set or remove LOCAL_DEBUG env var based on enable_temporal."""
|
|
358
|
-
if not self.enable_temporal:
|
|
359
|
-
if "LOCAL_DEBUG" not in os.environ:
|
|
360
|
-
os.environ["LOCAL_DEBUG"] = "1"
|
|
361
|
-
logger.debug(
|
|
362
|
-
"Set LOCAL_DEBUG environment variable for local execution."
|
|
363
|
-
)
|
|
364
|
-
elif "LOCAL_DEBUG" in os.environ:
|
|
365
|
-
del os.environ["LOCAL_DEBUG"]
|
|
366
|
-
logger.debug(
|
|
367
|
-
"Removed LOCAL_DEBUG environment variable for Temporal execution."
|
|
368
|
-
)
|
|
369
|
-
|
|
370
|
-
def _ensure_session_id(self):
|
|
371
|
-
"""Ensure a session_id exists in the OpenTelemetry baggage."""
|
|
372
|
-
session_id = get_baggage("session_id")
|
|
373
|
-
if not session_id:
|
|
374
|
-
session_id = str(uuid.uuid4())
|
|
375
|
-
set_baggage("session_id", session_id)
|
|
376
|
-
logger.debug(f"Generated new session_id: {session_id}")
|
|
377
|
-
|
|
378
|
-
def add_server(self, server: FlockMCPServerBase) -> FlockMCPServerBase:
|
|
379
|
-
"""Adds a server instance to this Flock configuration and registry as well as set it up to be managed by self._mgr."""
|
|
380
|
-
from flock.core.mcp.flock_mcp_server import (
|
|
381
|
-
FlockMCPServerBase as ConcreteFlockMCPServer,
|
|
382
|
-
)
|
|
383
|
-
|
|
384
|
-
if not isinstance(server, ConcreteFlockMCPServer):
|
|
385
|
-
raise TypeError("Provided object is not a FlockMCPServer instance.")
|
|
386
|
-
if not server.config.name:
|
|
387
|
-
raise ValueError("Server must have a name.")
|
|
388
|
-
|
|
389
|
-
if server.config.name in self.servers:
|
|
390
|
-
raise ValueError(
|
|
391
|
-
f"Server with this name already exists. Name: '{server.config.name}'"
|
|
392
|
-
)
|
|
393
|
-
|
|
394
|
-
self._servers[server.config.name] = server
|
|
395
|
-
FlockRegistry.register_server(server) # Register globally.
|
|
396
|
-
|
|
397
|
-
# Make sure that the server is also added to
|
|
398
|
-
# the server_list managed by FlockServerManager
|
|
399
|
-
if not self._mgr:
|
|
400
|
-
self._mgr = FlockServerManager()
|
|
401
|
-
|
|
402
|
-
# Prepare server to be managed by the FlockServerManager
|
|
403
|
-
logger.info(f"Adding server '{server.config.name}' to managed list.")
|
|
404
|
-
self._mgr.add_server_sync(server=server)
|
|
405
|
-
logger.info(f"Server '{server.config.name}' is now on managed list.")
|
|
406
|
-
|
|
407
|
-
logger.info(
|
|
408
|
-
f"Server '{server.config.name}' added to Flock '{self.name}'"
|
|
409
|
-
)
|
|
410
|
-
return server
|
|
411
|
-
|
|
412
|
-
def add_agent(self, agent: FlockAgent) -> FlockAgent:
|
|
413
|
-
"""Adds an agent instance to this Flock configuration and registry.
|
|
414
|
-
|
|
415
|
-
This also registers all servers attached to the agent, if they have not been registered
|
|
416
|
-
beforehand.
|
|
417
|
-
"""
|
|
418
|
-
from flock.core.flock_agent import FlockAgent as ConcreteFlockAgent
|
|
419
|
-
|
|
420
|
-
if not isinstance(agent, ConcreteFlockAgent):
|
|
421
|
-
raise TypeError("Provided object is not a FlockAgent instance.")
|
|
422
|
-
if not agent.name:
|
|
423
|
-
raise ValueError("Agent must have a name.")
|
|
424
|
-
|
|
425
|
-
if agent.name in self._agents:
|
|
426
|
-
# Allow re-adding the same instance, but raise error for different instance with same name
|
|
427
|
-
if self._agents[agent.name] is not agent:
|
|
428
|
-
raise ValueError(
|
|
429
|
-
f"Agent with name '{agent.name}' already exists with a different instance."
|
|
430
|
-
)
|
|
431
|
-
else:
|
|
432
|
-
logger.debug(
|
|
433
|
-
f"Agent '{agent.name}' is already added. Skipping."
|
|
434
|
-
)
|
|
435
|
-
return agent # Return existing agent
|
|
436
|
-
|
|
437
|
-
self._agents[agent.name] = agent
|
|
438
|
-
FlockRegistry.register_agent(agent) # Register globally
|
|
439
|
-
|
|
440
|
-
# Set default model if agent doesn't have one
|
|
441
|
-
if agent.model is None:
|
|
442
|
-
if self.model:
|
|
443
|
-
agent.set_model(self.model)
|
|
444
|
-
logger.debug(
|
|
445
|
-
f"Agent '{agent.name}' using Flock default model: {self.model}"
|
|
446
|
-
)
|
|
447
|
-
else:
|
|
448
|
-
logger.warning(
|
|
449
|
-
f"Agent '{agent.name}' has no model and Flock default model is not set."
|
|
450
|
-
)
|
|
451
|
-
|
|
452
|
-
logger.info(f"Agent '{agent.name}' added to Flock '{self.name}'.")
|
|
453
|
-
return agent
|
|
454
|
-
|
|
455
|
-
@property
|
|
456
|
-
def agents(self) -> dict[str, FlockAgent]:
|
|
457
|
-
"""Returns the dictionary of agents managed by this Flock instance."""
|
|
458
|
-
return self._agents
|
|
459
|
-
|
|
460
|
-
@property
|
|
461
|
-
def servers(self) -> dict[str, FlockMCPServerBase]:
|
|
462
|
-
"""Returns the dictionary of servers managed by this Flock instance."""
|
|
463
|
-
return self._servers
|
|
464
|
-
|
|
465
|
-
def run(
|
|
466
|
-
self,
|
|
467
|
-
start_agent: FlockAgent | str | None = None,
|
|
468
|
-
input: dict | None = None,
|
|
469
|
-
context: FlockContext | None = None,
|
|
470
|
-
run_id: str = "",
|
|
471
|
-
box_result: bool = True,
|
|
472
|
-
agents: list[FlockAgent] | None = None,
|
|
473
|
-
servers: list[FlockMCPServerBase] | None = None,
|
|
474
|
-
memo: dict[str, Any] | None = None,
|
|
475
|
-
*,
|
|
476
|
-
use_production_tools: bool = False,
|
|
477
|
-
) -> Box | dict:
|
|
478
|
-
return self._run_sync(
|
|
479
|
-
self.run_async(
|
|
480
|
-
start_agent=start_agent,
|
|
481
|
-
input=input,
|
|
482
|
-
context=context,
|
|
483
|
-
run_id=run_id,
|
|
484
|
-
box_result=box_result,
|
|
485
|
-
agents=agents,
|
|
486
|
-
servers=servers,
|
|
487
|
-
memo=memo,
|
|
488
|
-
use_production_tools=use_production_tools,
|
|
489
|
-
)
|
|
490
|
-
)
|
|
491
|
-
|
|
492
|
-
async def run_async(
|
|
493
|
-
self,
|
|
494
|
-
start_agent: FlockAgent | str | None = None,
|
|
495
|
-
input: dict | None = None,
|
|
496
|
-
context: FlockContext | None = None,
|
|
497
|
-
run_id: str = "",
|
|
498
|
-
box_result: bool = True,
|
|
499
|
-
agents: list[FlockAgent] | None = None,
|
|
500
|
-
servers: list[FlockMCPServerBase] | None = None,
|
|
501
|
-
memo: dict[str, Any] | None = None,
|
|
502
|
-
*,
|
|
503
|
-
use_production_tools: bool = False,
|
|
504
|
-
) -> Box | dict:
|
|
505
|
-
"""Entry point for running an agent system asynchronously."""
|
|
506
|
-
# Import here to allow forward reference resolution
|
|
507
|
-
from flock.core.flock_agent import FlockAgent as ConcreteFlockAgent
|
|
508
|
-
from flock.core.mcp.flock_mcp_server import (
|
|
509
|
-
FlockMCPServerBase as ConcreteFlockServer,
|
|
510
|
-
)
|
|
511
|
-
|
|
512
|
-
with tracer.start_as_current_span("flock.run_async") as span:
|
|
513
|
-
# Add passed servers so that agents have access to them.
|
|
514
|
-
if servers:
|
|
515
|
-
for server_obj in servers:
|
|
516
|
-
if isinstance(server_obj, ConcreteFlockServer):
|
|
517
|
-
self.add_server(server=server_obj)
|
|
518
|
-
else:
|
|
519
|
-
logger.warning(
|
|
520
|
-
f"Item in 'servers' list is not a FlockMCPServer: {type(server_obj)}"
|
|
521
|
-
)
|
|
522
|
-
|
|
523
|
-
# Add passed agents
|
|
524
|
-
if agents:
|
|
525
|
-
for agent_obj in agents:
|
|
526
|
-
if isinstance(agent_obj, ConcreteFlockAgent):
|
|
527
|
-
self.add_agent(agent_obj)
|
|
528
|
-
else:
|
|
529
|
-
logger.warning(
|
|
530
|
-
f"Item in 'agents' list is not a FlockAgent: {type(agent_obj)}"
|
|
531
|
-
)
|
|
532
|
-
|
|
533
|
-
# Determine starting agent name
|
|
534
|
-
start_agent_name: str | None = None
|
|
535
|
-
if isinstance(start_agent, ConcreteFlockAgent):
|
|
536
|
-
start_agent_name = start_agent.name
|
|
537
|
-
if (
|
|
538
|
-
start_agent_name not in self._agents
|
|
539
|
-
): # Add if not already present
|
|
540
|
-
self.add_agent(start_agent)
|
|
541
|
-
elif isinstance(start_agent, str):
|
|
542
|
-
start_agent_name = start_agent
|
|
543
|
-
else: # start_agent is None
|
|
544
|
-
start_agent_name = self._start_agent_name
|
|
545
|
-
|
|
546
|
-
# Default to first agent if only one exists and none specified
|
|
547
|
-
if not start_agent_name and len(self._agents) == 1:
|
|
548
|
-
start_agent_name = next(iter(self._agents.keys()))
|
|
549
|
-
elif not start_agent_name:
|
|
550
|
-
raise ValueError(
|
|
551
|
-
"No start_agent specified and multiple/no agents exist in the Flock instance."
|
|
552
|
-
)
|
|
553
|
-
|
|
554
|
-
# Check if start_agent is in agents
|
|
555
|
-
if start_agent_name not in self._agents:
|
|
556
|
-
# Try loading from registry if not found locally yet
|
|
557
|
-
reg_agent = FlockRegistry.get_agent(start_agent_name)
|
|
558
|
-
if reg_agent:
|
|
559
|
-
self.add_agent(reg_agent)
|
|
560
|
-
logger.info(
|
|
561
|
-
f"Loaded start agent '{start_agent_name}' from registry."
|
|
562
|
-
)
|
|
563
|
-
else:
|
|
564
|
-
raise ValueError(
|
|
565
|
-
f"Start agent '{start_agent_name}' not found locally or in registry."
|
|
566
|
-
)
|
|
567
|
-
|
|
568
|
-
run_input = input if input is not None else self._start_input
|
|
569
|
-
effective_run_id = run_id or f"flockrun_{uuid.uuid4().hex[:8]}"
|
|
570
|
-
|
|
571
|
-
span.set_attribute("start_agent", start_agent_name)
|
|
572
|
-
span.set_attribute("input", str(run_input))
|
|
573
|
-
span.set_attribute("run_id", effective_run_id)
|
|
574
|
-
span.set_attribute("enable_temporal", self.enable_temporal)
|
|
575
|
-
logger.info(
|
|
576
|
-
f"Initiating Flock run '{self.name}'. Start Agent: '{start_agent_name}'. Temporal: {self.enable_temporal}."
|
|
577
|
-
)
|
|
578
|
-
|
|
579
|
-
try:
|
|
580
|
-
resolved_start_agent = self._agents.get(start_agent_name)
|
|
581
|
-
if not resolved_start_agent: # Should have been handled by now
|
|
582
|
-
raise ValueError(
|
|
583
|
-
f"Start agent '{start_agent_name}' not found after checks."
|
|
584
|
-
)
|
|
585
|
-
|
|
586
|
-
run_context = context if context else FlockContext()
|
|
587
|
-
set_baggage("run_id", effective_run_id) # Set for OpenTelemetry
|
|
588
|
-
|
|
589
|
-
initialize_context(
|
|
590
|
-
run_context,
|
|
591
|
-
start_agent_name,
|
|
592
|
-
run_input,
|
|
593
|
-
effective_run_id,
|
|
594
|
-
not self.enable_temporal, # local_debug is inverse of enable_temporal
|
|
595
|
-
self.model or resolved_start_agent.model or DEFAULT_MODEL,
|
|
596
|
-
use_production_tools,
|
|
597
|
-
)
|
|
598
|
-
# Add agent definitions to context for routing/serialization within workflow
|
|
599
|
-
for agent_name_iter, agent_instance_iter in self.agents.items():
|
|
600
|
-
agent_dict_repr = (
|
|
601
|
-
agent_instance_iter.to_dict()
|
|
602
|
-
) # Agents handle their own serialization
|
|
603
|
-
run_context.add_agent_definition(
|
|
604
|
-
agent_type=type(agent_instance_iter),
|
|
605
|
-
agent_name=agent_name_iter,
|
|
606
|
-
agent_data=agent_dict_repr,
|
|
607
|
-
)
|
|
608
|
-
|
|
609
|
-
# Add temporal config to context if enabled
|
|
610
|
-
if self.enable_temporal and self.temporal_config:
|
|
611
|
-
run_context.set_variable(
|
|
612
|
-
"flock.temporal_workflow_config",
|
|
613
|
-
self.temporal_config.model_dump(mode="json"),
|
|
614
|
-
)
|
|
615
|
-
|
|
616
|
-
# At this point, initial setup is done
|
|
617
|
-
# and flock is ready to execute it's agent_workflow.
|
|
618
|
-
# Befor that happens, the ServerManager needs to
|
|
619
|
-
# get the Servers up and running (Populate pools, build connections, start scripts, etc.)
|
|
620
|
-
async with self._mgr:
|
|
621
|
-
# Enter the manager's async context,
|
|
622
|
-
# running it's __aenter__ method and starting all registered servers
|
|
623
|
-
# after this block ends, self._mgr's __aexit__ will be called
|
|
624
|
-
# all servers will be torn down.
|
|
625
|
-
logger.info(
|
|
626
|
-
f"Entering managed server context. Servers starting up."
|
|
627
|
-
)
|
|
628
|
-
|
|
629
|
-
logger.info(
|
|
630
|
-
"Starting agent execution",
|
|
631
|
-
agent=start_agent_name,
|
|
632
|
-
enable_temporal=self.enable_temporal,
|
|
633
|
-
)
|
|
634
|
-
|
|
635
|
-
# Execute workflow
|
|
636
|
-
if not self.enable_temporal:
|
|
637
|
-
result = await run_local_workflow(
|
|
638
|
-
run_context,
|
|
639
|
-
box_result=False, # Boxing handled below
|
|
640
|
-
)
|
|
641
|
-
else:
|
|
642
|
-
result = await run_temporal_workflow(
|
|
643
|
-
self, # Pass the Flock instance
|
|
644
|
-
run_context,
|
|
645
|
-
box_result=False, # Boxing handled below
|
|
646
|
-
memo=memo,
|
|
647
|
-
)
|
|
648
|
-
|
|
649
|
-
span.set_attribute("result.type", str(type(result)))
|
|
650
|
-
result_str = str(result)
|
|
651
|
-
span.set_attribute(
|
|
652
|
-
"result.preview",
|
|
653
|
-
result_str[:1000]
|
|
654
|
-
+ ("..." if len(result_str) > 1000 else ""),
|
|
655
|
-
)
|
|
656
|
-
|
|
657
|
-
if box_result:
|
|
658
|
-
try:
|
|
659
|
-
logger.debug("Boxing final result.")
|
|
660
|
-
return Box(result)
|
|
661
|
-
except ImportError:
|
|
662
|
-
logger.warning(
|
|
663
|
-
"Box library not installed, returning raw dict."
|
|
664
|
-
)
|
|
665
|
-
return result
|
|
666
|
-
else:
|
|
667
|
-
return result
|
|
668
|
-
|
|
669
|
-
# The context of self._mgr ends here, meaning, that servers will
|
|
670
|
-
# be cleaned up and shut down.
|
|
671
|
-
|
|
672
|
-
except Exception as e:
|
|
673
|
-
logger.error(
|
|
674
|
-
f"Flock run '{self.name}' failed: {e}", exc_info=True
|
|
675
|
-
)
|
|
676
|
-
span.record_exception(e)
|
|
677
|
-
span.set_status(trace.Status(trace.StatusCode.ERROR, str(e)))
|
|
678
|
-
# Return a consistent error structure
|
|
679
|
-
error_output = {
|
|
680
|
-
"error": str(e),
|
|
681
|
-
"details": f"Flock run '{self.name}' failed.",
|
|
682
|
-
"run_id": effective_run_id,
|
|
683
|
-
"start_agent": start_agent_name,
|
|
684
|
-
}
|
|
685
|
-
return Box(error_output) if box_result else error_output
|
|
686
|
-
|
|
687
|
-
# --- Batch Processing (Delegation) ---
|
|
688
|
-
async def run_batch_async(
|
|
689
|
-
self,
|
|
690
|
-
start_agent: FlockAgent | str,
|
|
691
|
-
batch_inputs: list[dict[str, Any]] | DataFrame | str,
|
|
692
|
-
input_mapping: dict[str, str] | None = None,
|
|
693
|
-
static_inputs: dict[str, Any] | None = None,
|
|
694
|
-
parallel: bool = True,
|
|
695
|
-
max_workers: int = 5,
|
|
696
|
-
use_temporal: bool | None = None,
|
|
697
|
-
box_results: bool = True,
|
|
698
|
-
return_errors: bool = False,
|
|
699
|
-
silent_mode: bool = False,
|
|
700
|
-
write_to_csv: str | None = None,
|
|
701
|
-
hide_columns: list[str] | None = None,
|
|
702
|
-
delimiter: str = ",",
|
|
703
|
-
) -> list[Box | dict | None | Exception]:
|
|
704
|
-
"""Runs the specified agent/workflow for each item in a batch asynchronously (delegated)."""
|
|
705
|
-
# Import processor locally
|
|
706
|
-
from flock.core.execution.batch_executor import BatchProcessor
|
|
707
|
-
|
|
708
|
-
processor = BatchProcessor(self) # Pass self
|
|
709
|
-
return await processor.run_batch_async(
|
|
710
|
-
start_agent=start_agent,
|
|
711
|
-
batch_inputs=batch_inputs,
|
|
712
|
-
input_mapping=input_mapping,
|
|
713
|
-
static_inputs=static_inputs,
|
|
714
|
-
parallel=parallel,
|
|
715
|
-
max_workers=max_workers,
|
|
716
|
-
use_temporal=use_temporal,
|
|
717
|
-
box_results=box_results,
|
|
718
|
-
return_errors=return_errors,
|
|
719
|
-
silent_mode=silent_mode,
|
|
720
|
-
write_to_csv=write_to_csv,
|
|
721
|
-
hide_columns=hide_columns,
|
|
722
|
-
delimiter=delimiter,
|
|
723
|
-
)
|
|
724
|
-
|
|
725
|
-
def run_batch(
|
|
726
|
-
self,
|
|
727
|
-
start_agent: FlockAgent | str,
|
|
728
|
-
batch_inputs: list[dict[str, Any]] | DataFrame | str,
|
|
729
|
-
input_mapping: dict[str, str] | None = None,
|
|
730
|
-
static_inputs: dict[str, Any] | None = None,
|
|
731
|
-
parallel: bool = True,
|
|
732
|
-
max_workers: int = 5,
|
|
733
|
-
use_temporal: bool | None = None,
|
|
734
|
-
box_results: bool = True,
|
|
735
|
-
return_errors: bool = False,
|
|
736
|
-
silent_mode: bool = False,
|
|
737
|
-
write_to_csv: str | None = None,
|
|
738
|
-
hide_columns: list[str] | None = None,
|
|
739
|
-
delimiter: str = ",",
|
|
740
|
-
) -> list[Box | dict | None | Exception]:
|
|
741
|
-
return self._run_sync(
|
|
742
|
-
self.run_batch_async(
|
|
743
|
-
start_agent=start_agent,
|
|
744
|
-
batch_inputs=batch_inputs,
|
|
745
|
-
input_mapping=input_mapping,
|
|
746
|
-
static_inputs=static_inputs,
|
|
747
|
-
parallel=parallel,
|
|
748
|
-
max_workers=max_workers,
|
|
749
|
-
use_temporal=use_temporal,
|
|
750
|
-
box_results=box_results,
|
|
751
|
-
return_errors=return_errors,
|
|
752
|
-
silent_mode=silent_mode,
|
|
753
|
-
write_to_csv=write_to_csv,
|
|
754
|
-
hide_columns=hide_columns,
|
|
755
|
-
delimiter=delimiter,
|
|
756
|
-
)
|
|
757
|
-
)
|
|
758
|
-
|
|
759
|
-
# --- Evaluation (Delegation) ---
|
|
760
|
-
async def evaluate_async(
|
|
761
|
-
self,
|
|
762
|
-
dataset: str | Path | list[dict[str, Any]] | DataFrame | Dataset, # type: ignore
|
|
763
|
-
start_agent: FlockAgent | str,
|
|
764
|
-
input_mapping: dict[str, str],
|
|
765
|
-
answer_mapping: dict[str, str],
|
|
766
|
-
metrics: list[
|
|
767
|
-
str
|
|
768
|
-
| Callable[[Any, Any], bool | float | dict[str, Any]]
|
|
769
|
-
| FlockAgent # Type hint only
|
|
770
|
-
| FlockEvaluator # Type hint only
|
|
771
|
-
],
|
|
772
|
-
metric_configs: dict[str, dict[str, Any]] | None = None,
|
|
773
|
-
static_inputs: dict[str, Any] | None = None,
|
|
774
|
-
parallel: bool = True,
|
|
775
|
-
max_workers: int = 5,
|
|
776
|
-
use_temporal: bool | None = None,
|
|
777
|
-
error_handling: Literal["raise", "skip", "log"] = "log",
|
|
778
|
-
output_file: str | Path | None = None,
|
|
779
|
-
return_dataframe: bool = True,
|
|
780
|
-
silent_mode: bool = False,
|
|
781
|
-
metadata_columns: list[str] | None = None,
|
|
782
|
-
) -> DataFrame | list[dict[str, Any]]: # type: ignore
|
|
783
|
-
"""Evaluates the Flock's performance against a dataset (delegated)."""
|
|
784
|
-
# Import processor locally
|
|
785
|
-
from flock.core.execution.evaluation_executor import (
|
|
786
|
-
EvaluationExecutor,
|
|
787
|
-
)
|
|
788
|
-
|
|
789
|
-
processor = EvaluationExecutor(self) # Pass self
|
|
790
|
-
return await processor.evaluate_async(
|
|
791
|
-
dataset=dataset,
|
|
792
|
-
start_agent=start_agent,
|
|
793
|
-
input_mapping=input_mapping,
|
|
794
|
-
answer_mapping=answer_mapping,
|
|
795
|
-
metrics=metrics,
|
|
796
|
-
metric_configs=metric_configs,
|
|
797
|
-
static_inputs=static_inputs,
|
|
798
|
-
parallel=parallel,
|
|
799
|
-
max_workers=max_workers,
|
|
800
|
-
use_temporal=use_temporal,
|
|
801
|
-
error_handling=error_handling,
|
|
802
|
-
output_file=output_file,
|
|
803
|
-
return_dataframe=return_dataframe,
|
|
804
|
-
silent_mode=silent_mode,
|
|
805
|
-
metadata_columns=metadata_columns,
|
|
806
|
-
)
|
|
807
|
-
|
|
808
|
-
def evaluate(
|
|
809
|
-
self,
|
|
810
|
-
dataset: str | Path | list[dict[str, Any]] | DataFrame | Dataset, # type: ignore
|
|
811
|
-
start_agent: FlockAgent | str,
|
|
812
|
-
input_mapping: dict[str, str],
|
|
813
|
-
answer_mapping: dict[str, str],
|
|
814
|
-
metrics: list[
|
|
815
|
-
str
|
|
816
|
-
| Callable[[Any, Any], bool | float | dict[str, Any]]
|
|
817
|
-
| FlockAgent # Type hint only
|
|
818
|
-
| FlockEvaluator # Type hint only
|
|
819
|
-
],
|
|
820
|
-
metric_configs: dict[str, dict[str, Any]] | None = None,
|
|
821
|
-
static_inputs: dict[str, Any] | None = None,
|
|
822
|
-
parallel: bool = True,
|
|
823
|
-
max_workers: int = 5,
|
|
824
|
-
use_temporal: bool | None = None,
|
|
825
|
-
error_handling: Literal["raise", "skip", "log"] = "log",
|
|
826
|
-
output_file: str | Path | None = None,
|
|
827
|
-
return_dataframe: bool = True,
|
|
828
|
-
silent_mode: bool = False,
|
|
829
|
-
metadata_columns: list[str] | None = None,
|
|
830
|
-
) -> DataFrame | list[dict[str, Any]]: # type: ignore
|
|
831
|
-
return self._run_sync(
|
|
832
|
-
self.evaluate_async(
|
|
833
|
-
dataset=dataset,
|
|
834
|
-
start_agent=start_agent,
|
|
835
|
-
input_mapping=input_mapping,
|
|
836
|
-
answer_mapping=answer_mapping,
|
|
837
|
-
metrics=metrics,
|
|
838
|
-
metric_configs=metric_configs,
|
|
839
|
-
static_inputs=static_inputs,
|
|
840
|
-
parallel=parallel,
|
|
841
|
-
max_workers=max_workers,
|
|
842
|
-
use_temporal=use_temporal,
|
|
843
|
-
error_handling=error_handling,
|
|
844
|
-
output_file=output_file,
|
|
845
|
-
return_dataframe=return_dataframe,
|
|
846
|
-
silent_mode=silent_mode,
|
|
847
|
-
metadata_columns=metadata_columns,
|
|
848
|
-
)
|
|
849
|
-
)
|
|
850
|
-
|
|
851
|
-
# --- Server & CLI Starters (Delegation) ---
|
|
852
|
-
def start_api(
|
|
853
|
-
self,
|
|
854
|
-
host: str = "127.0.0.1",
|
|
855
|
-
port: int = 8344,
|
|
856
|
-
server_name: str = "Flock Server",
|
|
857
|
-
create_ui: bool = True, # Default to True for the integrated experience
|
|
858
|
-
ui_theme: str | None = None,
|
|
859
|
-
custom_endpoints: Sequence[FlockEndpoint]
|
|
860
|
-
| dict[tuple[str, list[str] | None], Callable[..., Any]]
|
|
861
|
-
| None = None,
|
|
862
|
-
) -> None:
|
|
863
|
-
"""Starts a unified REST API server and/or Web UI for this Flock instance."""
|
|
864
|
-
import warnings
|
|
865
|
-
|
|
866
|
-
warnings.warn(
|
|
867
|
-
"start_api() is deprecated and will be removed in a future release. "
|
|
868
|
-
"Use serve() instead.",
|
|
869
|
-
DeprecationWarning,
|
|
870
|
-
stacklevel=2,
|
|
871
|
-
)
|
|
872
|
-
# Delegate to the new serve() method (create_ui maps to ui)
|
|
873
|
-
return self.serve(
|
|
874
|
-
host=host,
|
|
875
|
-
port=port,
|
|
876
|
-
server_name=server_name,
|
|
877
|
-
ui=create_ui,
|
|
878
|
-
ui_theme=ui_theme,
|
|
879
|
-
custom_endpoints=custom_endpoints,
|
|
880
|
-
)
|
|
881
|
-
|
|
882
|
-
# ------------------------------------------------------------------
|
|
883
|
-
# New preferred method name
|
|
884
|
-
# ------------------------------------------------------------------
|
|
885
|
-
|
|
886
|
-
def serve(
|
|
887
|
-
self,
|
|
888
|
-
host: str = "127.0.0.1",
|
|
889
|
-
port: int = 8344,
|
|
890
|
-
server_name: str = "Flock Server",
|
|
891
|
-
ui: bool = True,
|
|
892
|
-
chat: bool = False,
|
|
893
|
-
chat_agent: str | None = None, # Reserved for future real agent chat
|
|
894
|
-
chat_message_key: str = "message",
|
|
895
|
-
chat_history_key: str = "history",
|
|
896
|
-
chat_response_key: str = "response",
|
|
897
|
-
ui_theme: str | None = None,
|
|
898
|
-
custom_endpoints: Sequence[FlockEndpoint]
|
|
899
|
-
| dict[tuple[str, list[str] | None], Callable[..., Any]]
|
|
900
|
-
| None = None,
|
|
901
|
-
) -> None:
|
|
902
|
-
"""Launch an HTTP server that exposes the core REST API and, optionally, the
|
|
903
|
-
browser-based UI.
|
|
904
|
-
|
|
905
|
-
Args:
|
|
906
|
-
host: Bind address for the server (default "127.0.0.1").
|
|
907
|
-
port: TCP port to listen on (default 8344).
|
|
908
|
-
server_name: Title shown in the OpenAPI docs / logs.
|
|
909
|
-
ui: If True (default) the Pico/HTMX web UI routes are included. If False
|
|
910
|
-
only the JSON API groups (core & custom) are served.
|
|
911
|
-
chat: If True, enable chat routes.
|
|
912
|
-
chat_agent: Name of the agent to use for chat.
|
|
913
|
-
chat_message_key: Key for chat message in input.
|
|
914
|
-
chat_history_key: Key for chat history in input.
|
|
915
|
-
chat_response_key: Key for chat response in output.
|
|
916
|
-
ui_theme: Optional UI theme name or "random".
|
|
917
|
-
custom_endpoints: Additional API routes to add, either as a list of
|
|
918
|
-
FlockEndpoint objects or the legacy dict format.
|
|
919
|
-
"""
|
|
920
|
-
try:
|
|
921
|
-
from flock.webapp.run import start_unified_server
|
|
922
|
-
except ImportError:
|
|
923
|
-
logger.error(
|
|
924
|
-
"Web application components not found (flock.webapp.run). "
|
|
925
|
-
"Cannot start HTTP server. Ensure webapp dependencies are installed."
|
|
926
|
-
)
|
|
927
|
-
return
|
|
928
|
-
|
|
929
|
-
logger.info(
|
|
930
|
-
f"Attempting to start server for Flock '{self.name}' on {host}:{port}. UI enabled: {ui}"
|
|
931
|
-
)
|
|
932
|
-
|
|
933
|
-
start_unified_server(
|
|
934
|
-
flock_instance=self,
|
|
935
|
-
host=host,
|
|
936
|
-
port=port,
|
|
937
|
-
server_title=server_name,
|
|
938
|
-
enable_ui_routes=ui,
|
|
939
|
-
enable_chat_routes=chat,
|
|
940
|
-
ui_theme=ui_theme,
|
|
941
|
-
custom_endpoints=custom_endpoints,
|
|
942
|
-
)
|
|
943
|
-
|
|
944
|
-
def start_cli(
|
|
945
|
-
self,
|
|
946
|
-
start_agent: FlockAgent
|
|
947
|
-
| str
|
|
948
|
-
| None = None, # Added start_agent to match method signature in file_26
|
|
949
|
-
server_name: str = "Flock CLI",
|
|
950
|
-
show_results: bool = False,
|
|
951
|
-
edit_mode: bool = False,
|
|
952
|
-
) -> None:
|
|
953
|
-
"""Starts an interactive CLI for this Flock instance."""
|
|
954
|
-
# Import runner locally
|
|
955
|
-
try:
|
|
956
|
-
from flock.cli.runner import start_flock_cli
|
|
957
|
-
except ImportError:
|
|
958
|
-
logger.error(
|
|
959
|
-
"CLI components not found. Cannot start CLI. "
|
|
960
|
-
"Ensure CLI dependencies are installed."
|
|
961
|
-
)
|
|
962
|
-
return
|
|
963
|
-
|
|
964
|
-
# The start_flock_cli function in file_50 doesn't take start_agent
|
|
965
|
-
# but the original docs for start_cli did.
|
|
966
|
-
# For now, I'll pass it through, assuming start_flock_cli will be updated or ignore it.
|
|
967
|
-
# If start_agent is crucial here, start_flock_cli needs to handle it.
|
|
968
|
-
logger.info(f"Starting CLI for Flock '{self.name}'...")
|
|
969
|
-
start_flock_cli(
|
|
970
|
-
flock=self, # Pass the Flock instance
|
|
971
|
-
# start_agent=start_agent, # This argument is not in the definition of start_flock_cli in file_50
|
|
972
|
-
server_name=server_name,
|
|
973
|
-
show_results=show_results,
|
|
974
|
-
edit_mode=edit_mode,
|
|
975
|
-
)
|
|
976
|
-
|
|
977
|
-
# --- Serialization Delegation Methods ---
|
|
978
|
-
def to_dict(self, path_type: str = "relative") -> dict[str, Any]:
|
|
979
|
-
"""Serialize Flock instance to dictionary using FlockSerializer."""
|
|
980
|
-
from flock.core.serialization.flock_serializer import FlockSerializer
|
|
981
|
-
|
|
982
|
-
return FlockSerializer.serialize(self, path_type=path_type)
|
|
983
|
-
|
|
984
|
-
@classmethod
|
|
985
|
-
def from_dict(cls: type[T], data: dict[str, Any]) -> T:
|
|
986
|
-
"""Deserialize Flock instance from dictionary using FlockSerializer."""
|
|
987
|
-
from flock.core.serialization.flock_serializer import FlockSerializer
|
|
988
|
-
|
|
989
|
-
return FlockSerializer.deserialize(cls, data)
|
|
990
|
-
|
|
991
|
-
# --- Static Method Loader (Delegates to loader module) ---
|
|
992
|
-
@staticmethod
|
|
993
|
-
def load_from_file(file_path: str) -> Flock: # Ensure return type is Flock
|
|
994
|
-
"""Load a Flock instance from various file formats (delegates to loader)."""
|
|
995
|
-
from flock.core.util.loader import load_flock_from_file
|
|
996
|
-
|
|
997
|
-
loaded_flock = load_flock_from_file(file_path)
|
|
998
|
-
# Ensure the loaded object is indeed a Flock instance
|
|
999
|
-
if not isinstance(loaded_flock, Flock):
|
|
1000
|
-
raise TypeError(
|
|
1001
|
-
f"Loaded object from {file_path} is not a Flock instance, but {type(loaded_flock)}"
|
|
1002
|
-
)
|
|
1003
|
-
return loaded_flock
|