flock-core 0.5.0b28__py3-none-any.whl → 0.5.56b0__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 +678 -0
- flock/api/themes.py +71 -0
- flock/artifacts.py +79 -0
- flock/cli.py +75 -0
- flock/components.py +173 -0
- flock/dashboard/__init__.py +28 -0
- flock/dashboard/collector.py +283 -0
- flock/dashboard/events.py +182 -0
- flock/dashboard/launcher.py +230 -0
- flock/dashboard/service.py +537 -0
- flock/dashboard/websocket.py +235 -0
- flock/engines/__init__.py +6 -0
- flock/engines/dspy_engine.py +856 -0
- flock/examples.py +128 -0
- flock/{core/util → helper}/cli_helper.py +4 -3
- flock/{core/logging → logging}/__init__.py +2 -3
- 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 -115
- flock/{core/logging → logging}/logging.py +77 -61
- flock/{core/logging → logging}/telemetry.py +20 -26
- flock/{core/logging → logging}/telemetry_exporter/base_exporter.py +2 -2
- flock/{core/logging → logging}/telemetry_exporter/file_exporter.py +6 -9
- flock/{core/logging → logging}/telemetry_exporter/sqlite_exporter.py +2 -3
- flock/{core/logging → logging}/trace_and_logged.py +20 -24
- flock/mcp/__init__.py +91 -0
- flock/{core/mcp/mcp_client.py → mcp/client.py} +103 -154
- flock/{core/mcp/mcp_config.py → mcp/config.py} +62 -117
- flock/mcp/manager.py +255 -0
- flock/mcp/servers/sse/__init__.py +1 -1
- flock/mcp/servers/sse/flock_sse_server.py +11 -53
- flock/mcp/servers/stdio/__init__.py +1 -1
- flock/mcp/servers/stdio/flock_stdio_server.py +8 -48
- flock/mcp/servers/streamable_http/flock_streamable_http_server.py +17 -62
- flock/mcp/servers/websockets/flock_websocket_server.py +7 -40
- flock/{core/mcp/flock_mcp_tool.py → mcp/tool.py} +16 -26
- flock/mcp/types/__init__.py +42 -0
- flock/{core/mcp → mcp}/types/callbacks.py +9 -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 +1 -1
- flock/orchestrator.py +645 -0
- flock/registry.py +148 -0
- flock/runtime.py +262 -0
- flock/service.py +140 -0
- flock/store.py +69 -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/darkside.toml +1 -1
- 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 +1 -1
- 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/{components/utility → utility}/output_utility_component.py +68 -53
- flock/visibility.py +107 -0
- flock_core-0.5.56b0.dist-info/METADATA +747 -0
- flock_core-0.5.56b0.dist-info/RECORD +398 -0
- flock_core-0.5.56b0.dist-info/entry_points.txt +2 -0
- {flock_core-0.5.0b28.dist-info → flock_core-0.5.56b0.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/components/__init__.py +0 -30
- flock/components/evaluation/__init__.py +0 -9
- flock/components/evaluation/declarative_evaluation_component.py +0 -606
- flock/components/routing/__init__.py +0 -15
- flock/components/routing/conditional_routing_component.py +0 -494
- flock/components/routing/default_routing_component.py +0 -103
- flock/components/routing/llm_routing_component.py +0 -206
- flock/components/utility/__init__.py +0 -22
- flock/components/utility/example_utility_component.py +0 -250
- flock/components/utility/feedback_utility_component.py +0 -206
- flock/components/utility/memory_utility_component.py +0 -550
- flock/components/utility/metrics_utility_component.py +0 -700
- flock/config.py +0 -61
- flock/core/__init__.py +0 -110
- flock/core/agent/__init__.py +0 -16
- flock/core/agent/default_agent.py +0 -216
- flock/core/agent/flock_agent_components.py +0 -104
- flock/core/agent/flock_agent_execution.py +0 -101
- flock/core/agent/flock_agent_integration.py +0 -260
- flock/core/agent/flock_agent_lifecycle.py +0 -186
- flock/core/agent/flock_agent_serialization.py +0 -381
- flock/core/api/__init__.py +0 -10
- flock/core/api/custom_endpoint.py +0 -45
- flock/core/api/endpoints.py +0 -254
- flock/core/api/main.py +0 -162
- flock/core/api/models.py +0 -97
- flock/core/api/run_store.py +0 -224
- flock/core/api/runner.py +0 -44
- flock/core/api/service.py +0 -214
- flock/core/component/__init__.py +0 -15
- flock/core/component/agent_component_base.py +0 -309
- flock/core/component/evaluation_component.py +0 -62
- flock/core/component/routing_component.py +0 -74
- flock/core/component/utility_component.py +0 -69
- flock/core/config/flock_agent_config.py +0 -58
- flock/core/config/scheduled_agent_config.py +0 -40
- flock/core/context/context.py +0 -213
- flock/core/context/context_manager.py +0 -37
- flock/core/context/context_vars.py +0 -10
- flock/core/evaluation/utils.py +0 -396
- 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 -164
- flock/core/flock.py +0 -634
- flock/core/flock_agent.py +0 -336
- flock/core/flock_factory.py +0 -613
- 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/mcp/__init__.py +0 -1
- flock/core/mcp/flock_mcp_server.py +0 -680
- flock/core/mcp/mcp_client_manager.py +0 -201
- flock/core/mcp/types/__init__.py +0 -1
- flock/core/mixin/dspy_integration.py +0 -403
- flock/core/mixin/prompt_parser.py +0 -125
- flock/core/orchestration/__init__.py +0 -15
- flock/core/orchestration/flock_batch_processor.py +0 -94
- flock/core/orchestration/flock_evaluator.py +0 -113
- flock/core/orchestration/flock_execution.py +0 -295
- flock/core/orchestration/flock_initialization.py +0 -149
- flock/core/orchestration/flock_server_manager.py +0 -67
- flock/core/orchestration/flock_web_server.py +0 -117
- flock/core/registry/__init__.py +0 -45
- flock/core/registry/agent_registry.py +0 -69
- flock/core/registry/callable_registry.py +0 -139
- flock/core/registry/component_discovery.py +0 -142
- flock/core/registry/component_registry.py +0 -64
- flock/core/registry/config_mapping.py +0 -64
- flock/core/registry/decorators.py +0 -137
- flock/core/registry/registry_hub.py +0 -205
- flock/core/registry/server_registry.py +0 -57
- flock/core/registry/type_registry.py +0 -86
- flock/core/serialization/__init__.py +0 -13
- flock/core/serialization/callable_registry.py +0 -52
- flock/core/serialization/flock_serializer.py +0 -832
- 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 -412
- flock/core/util/file_path_utils.py +0 -223
- flock/core/util/hydrator.py +0 -309
- flock/core/util/input_resolver.py +0 -164
- flock/core/util/loader.py +0 -59
- flock/core/util/splitter.py +0 -219
- flock/di.py +0 -27
- flock/platform/docker_tools.py +0 -49
- flock/platform/jaeger_install.py +0 -86
- 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 -241
- flock/webapp/app/api/execution.py +0 -709
- flock/webapp/app/api/flock_management.py +0 -129
- flock/webapp/app/api/registry_viewer.py +0 -30
- flock/webapp/app/chat.py +0 -665
- flock/webapp/app/config.py +0 -104
- flock/webapp/app/dependencies.py +0 -117
- flock/webapp/app/main.py +0 -1070
- 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 -337
- flock/webapp/app/services/sharing_models.py +0 -81
- flock/webapp/app/services/sharing_store.py +0 -762
- flock/webapp/app/templates/theme_mapper.html +0 -326
- flock/webapp/app/theme_mapper.py +0 -812
- flock/webapp/app/utils.py +0 -85
- flock/webapp/run.py +0 -215
- 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 -46
- flock/webapp/static/css/sidebar.css +0 -127
- flock/webapp/static/css/two-pane.css +0 -48
- flock/webapp/templates/base.html +0 -200
- 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 -118
- 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/_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/_streaming_results_container.html +0 -195
- 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 -196
- flock/workflow/agent_activities.py +0 -24
- flock/workflow/agent_execution_activity.py +0 -202
- flock/workflow/flock_workflow.py +0 -214
- flock/workflow/temporal_config.py +0 -96
- flock/workflow/temporal_setup.py +0 -68
- flock_core-0.5.0b28.dist-info/METADATA +0 -274
- flock_core-0.5.0b28.dist-info/RECORD +0 -561
- flock_core-0.5.0b28.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.5.0b28.dist-info → flock_core-0.5.56b0.dist-info}/WHEEL +0 -0
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
"""A mixin class for parsing agent prompts and building clean signatures for DSPy."""
|
|
2
|
-
|
|
3
|
-
# DEPRECATED! This mixin is no longer used in the current version of Flock. It was used to parse agent prompts and build clean signatures for DSPy.
|
|
4
|
-
# TODO: DELETE THIS FILE!
|
|
5
|
-
|
|
6
|
-
from flock.core.util.input_resolver import split_top_level
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class PromptParserMixin:
|
|
10
|
-
"""A mixin class for parsing agent prompts and building clean signatures for DSPy."""
|
|
11
|
-
|
|
12
|
-
def _parse_key_descriptions(self, keys_str: str) -> list[tuple[str, str]]:
|
|
13
|
-
"""Parse a comma-separated string into a list of (key, description) tuples.
|
|
14
|
-
|
|
15
|
-
This function processes a configuration string that defines one or more keys, where each key may
|
|
16
|
-
include a type hint and an optional human-readable description. The expected format for each key is:
|
|
17
|
-
|
|
18
|
-
key: type_hint | description
|
|
19
|
-
|
|
20
|
-
If the pipe symbol ("|") is absent, the description is set to an empty string.
|
|
21
|
-
|
|
22
|
-
The splitting is performed using split_top_level() so that commas inside type hints are preserved.
|
|
23
|
-
|
|
24
|
-
For example, given:
|
|
25
|
-
"query: str | The search query, context: dict | The full conversation context"
|
|
26
|
-
it returns:
|
|
27
|
-
[("query", "The search query"), ("context", "The full conversation context")]
|
|
28
|
-
|
|
29
|
-
Args:
|
|
30
|
-
keys_str (str): A comma-separated string of key definitions.
|
|
31
|
-
|
|
32
|
-
Returns:
|
|
33
|
-
List[Tuple[str, str]]: A list of (key, description) tuples.
|
|
34
|
-
"""
|
|
35
|
-
key_descs = []
|
|
36
|
-
for part in split_top_level(keys_str):
|
|
37
|
-
if not part:
|
|
38
|
-
continue
|
|
39
|
-
if "|" in part:
|
|
40
|
-
key_type_part, desc = part.split("|", 1)
|
|
41
|
-
desc = desc.strip()
|
|
42
|
-
else:
|
|
43
|
-
key_type_part = part
|
|
44
|
-
desc = ""
|
|
45
|
-
key = key_type_part.split(":", 1)[0].strip()
|
|
46
|
-
key_descs.append((key, desc))
|
|
47
|
-
return key_descs
|
|
48
|
-
|
|
49
|
-
def _build_clean_signature(self, keys_str: str) -> str:
|
|
50
|
-
"""Build a clean signature string from the configuration string by removing the description parts.
|
|
51
|
-
|
|
52
|
-
Given a string like:
|
|
53
|
-
"query: str | The search query, context: dict | The full conversation context"
|
|
54
|
-
this method returns:
|
|
55
|
-
"query: str, context: dict"
|
|
56
|
-
|
|
57
|
-
This function uses split_top_level() to avoid splitting on commas that are inside type hints.
|
|
58
|
-
|
|
59
|
-
Args:
|
|
60
|
-
keys_str (str): The configuration string containing keys, type hints, and optional descriptions.
|
|
61
|
-
|
|
62
|
-
Returns:
|
|
63
|
-
str: A clean signature string with only keys and type hints.
|
|
64
|
-
"""
|
|
65
|
-
parts = []
|
|
66
|
-
for part in split_top_level(keys_str):
|
|
67
|
-
if not part:
|
|
68
|
-
continue
|
|
69
|
-
if "|" in part:
|
|
70
|
-
clean_part = part.split("|", 1)[0].strip()
|
|
71
|
-
else:
|
|
72
|
-
clean_part = part.strip()
|
|
73
|
-
parts.append(clean_part)
|
|
74
|
-
return ", ".join(parts)
|
|
75
|
-
|
|
76
|
-
def _build_descriptions(self) -> tuple[dict[str, str], dict[str, str]]:
|
|
77
|
-
"""Build dictionaries of input and output descriptions from the agent's configuration.
|
|
78
|
-
|
|
79
|
-
Returns:
|
|
80
|
-
A tuple containing:
|
|
81
|
-
- input_desc: A dictionary mapping each input key (without type hints) to its description.
|
|
82
|
-
- output_desc: A dictionary mapping each output key (without type hints) to its description.
|
|
83
|
-
"""
|
|
84
|
-
input_desc: dict[str, str] = {}
|
|
85
|
-
if self.input:
|
|
86
|
-
for key, desc in self._parse_key_descriptions(self.input):
|
|
87
|
-
input_desc[key] = desc
|
|
88
|
-
|
|
89
|
-
output_desc: dict[str, str] = {}
|
|
90
|
-
if self.output:
|
|
91
|
-
for key, desc in self._parse_key_descriptions(self.output):
|
|
92
|
-
output_desc[key] = desc
|
|
93
|
-
|
|
94
|
-
return input_desc, output_desc
|
|
95
|
-
|
|
96
|
-
def _build_prompt(
|
|
97
|
-
self, input_desc: dict[str, str], output_desc: dict[str, str]
|
|
98
|
-
) -> str:
|
|
99
|
-
"""Build a clean signature prompt from the agent's configuration.
|
|
100
|
-
|
|
101
|
-
This method uses the original input and output strings (removing the description parts)
|
|
102
|
-
to create a signature string that is passed to DSPy. For example, if:
|
|
103
|
-
- self.input is "query: str | The search query, context: dict | The full conversation context"
|
|
104
|
-
- self.output is "result: str | The result"
|
|
105
|
-
then the prompt will be:
|
|
106
|
-
"query: str, context: dict -> result: str"
|
|
107
|
-
|
|
108
|
-
**Note:** The descriptive metadata is preserved in the dictionaries obtained from _build_descriptions,
|
|
109
|
-
which are passed separately to DSPy.
|
|
110
|
-
|
|
111
|
-
Args:
|
|
112
|
-
input_desc: Dictionary of input key descriptions (for metadata only).
|
|
113
|
-
output_desc: Dictionary of output key descriptions (for metadata only).
|
|
114
|
-
|
|
115
|
-
Returns:
|
|
116
|
-
A clean signature string for DSPy.
|
|
117
|
-
"""
|
|
118
|
-
clean_input = (
|
|
119
|
-
self._build_clean_signature(self.input) if self.input else ""
|
|
120
|
-
)
|
|
121
|
-
clean_output = (
|
|
122
|
-
self._build_clean_signature(self.output) if self.output else ""
|
|
123
|
-
)
|
|
124
|
-
# Combine the clean input and output signatures using "->"
|
|
125
|
-
return f"{clean_input} -> {clean_output}"
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
# src/flock/core/orchestration/__init__.py
|
|
2
|
-
"""Orchestration package public API.
|
|
3
|
-
|
|
4
|
-
Avoid importing submodules at package import time to prevent heavy side effects
|
|
5
|
-
and keep tests fast and deterministic. Import modules directly where needed.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
__all__ = [
|
|
9
|
-
"FlockExecution",
|
|
10
|
-
"FlockServerManager",
|
|
11
|
-
"FlockBatchProcessor",
|
|
12
|
-
"FlockEvaluator",
|
|
13
|
-
"FlockWebServer",
|
|
14
|
-
"FlockInitialization",
|
|
15
|
-
]
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
# src/flock/core/orchestration/flock_batch_processor.py
|
|
2
|
-
"""Batch processing functionality for Flock orchestrator."""
|
|
3
|
-
|
|
4
|
-
from typing import TYPE_CHECKING, Any
|
|
5
|
-
|
|
6
|
-
from box import Box
|
|
7
|
-
from pandas import DataFrame
|
|
8
|
-
|
|
9
|
-
from flock.core.logging.logging import get_logger
|
|
10
|
-
|
|
11
|
-
if TYPE_CHECKING:
|
|
12
|
-
from flock.core.flock import Flock
|
|
13
|
-
from flock.core.flock_agent import FlockAgent
|
|
14
|
-
|
|
15
|
-
logger = get_logger("flock.batch_processor")
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
class FlockBatchProcessor:
|
|
19
|
-
"""Handles batch processing functionality for Flock orchestrator."""
|
|
20
|
-
|
|
21
|
-
def __init__(self, flock: "Flock"):
|
|
22
|
-
self.flock = flock
|
|
23
|
-
|
|
24
|
-
async def run_batch_async(
|
|
25
|
-
self,
|
|
26
|
-
start_agent: "FlockAgent | str",
|
|
27
|
-
batch_inputs: list[dict[str, Any]] | DataFrame | str,
|
|
28
|
-
input_mapping: dict[str, str] | None = None,
|
|
29
|
-
static_inputs: dict[str, Any] | None = None,
|
|
30
|
-
parallel: bool = True,
|
|
31
|
-
max_workers: int = 5,
|
|
32
|
-
use_temporal: bool | None = None,
|
|
33
|
-
box_results: bool = True,
|
|
34
|
-
return_errors: bool = False,
|
|
35
|
-
silent_mode: bool = False,
|
|
36
|
-
write_to_csv: str | None = None,
|
|
37
|
-
hide_columns: list[str] | None = None,
|
|
38
|
-
delimiter: str = ",",
|
|
39
|
-
) -> list[Box | dict | None | Exception]:
|
|
40
|
-
"""Runs the specified agent/workflow for each item in a batch asynchronously (delegated)."""
|
|
41
|
-
# Import processor locally
|
|
42
|
-
from flock.core.execution.batch_executor import BatchProcessor
|
|
43
|
-
|
|
44
|
-
processor = BatchProcessor(self.flock) # Pass flock instance
|
|
45
|
-
return await processor.run_batch_async(
|
|
46
|
-
start_agent=start_agent,
|
|
47
|
-
batch_inputs=batch_inputs,
|
|
48
|
-
input_mapping=input_mapping,
|
|
49
|
-
static_inputs=static_inputs,
|
|
50
|
-
parallel=parallel,
|
|
51
|
-
max_workers=max_workers,
|
|
52
|
-
use_temporal=use_temporal,
|
|
53
|
-
box_results=box_results,
|
|
54
|
-
return_errors=return_errors,
|
|
55
|
-
silent_mode=silent_mode,
|
|
56
|
-
write_to_csv=write_to_csv,
|
|
57
|
-
hide_columns=hide_columns,
|
|
58
|
-
delimiter=delimiter,
|
|
59
|
-
)
|
|
60
|
-
|
|
61
|
-
def run_batch(
|
|
62
|
-
self,
|
|
63
|
-
start_agent: "FlockAgent | str",
|
|
64
|
-
batch_inputs: list[dict[str, Any]] | DataFrame | str,
|
|
65
|
-
input_mapping: dict[str, str] | None = None,
|
|
66
|
-
static_inputs: dict[str, Any] | None = None,
|
|
67
|
-
parallel: bool = True,
|
|
68
|
-
max_workers: int = 5,
|
|
69
|
-
use_temporal: bool | None = None,
|
|
70
|
-
box_results: bool = True,
|
|
71
|
-
return_errors: bool = False,
|
|
72
|
-
silent_mode: bool = False,
|
|
73
|
-
write_to_csv: str | None = None,
|
|
74
|
-
hide_columns: list[str] | None = None,
|
|
75
|
-
delimiter: str = ",",
|
|
76
|
-
) -> list[Box | dict | None | Exception]:
|
|
77
|
-
"""Synchronous wrapper for batch processing."""
|
|
78
|
-
return self.flock._execution._run_sync(
|
|
79
|
-
self.run_batch_async(
|
|
80
|
-
start_agent=start_agent,
|
|
81
|
-
batch_inputs=batch_inputs,
|
|
82
|
-
input_mapping=input_mapping,
|
|
83
|
-
static_inputs=static_inputs,
|
|
84
|
-
parallel=parallel,
|
|
85
|
-
max_workers=max_workers,
|
|
86
|
-
use_temporal=use_temporal,
|
|
87
|
-
box_results=box_results,
|
|
88
|
-
return_errors=return_errors,
|
|
89
|
-
silent_mode=silent_mode,
|
|
90
|
-
write_to_csv=write_to_csv,
|
|
91
|
-
hide_columns=hide_columns,
|
|
92
|
-
delimiter=delimiter,
|
|
93
|
-
)
|
|
94
|
-
)
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
# src/flock/core/orchestration/flock_evaluator.py
|
|
2
|
-
"""Evaluation functionality for Flock orchestrator."""
|
|
3
|
-
|
|
4
|
-
from collections.abc import Callable
|
|
5
|
-
from pathlib import Path
|
|
6
|
-
from typing import TYPE_CHECKING, Any, Literal
|
|
7
|
-
|
|
8
|
-
from datasets import Dataset
|
|
9
|
-
from pandas import DataFrame
|
|
10
|
-
|
|
11
|
-
from flock.core.flock_agent import FlockAgent
|
|
12
|
-
from flock.core.logging.logging import get_logger
|
|
13
|
-
|
|
14
|
-
if TYPE_CHECKING:
|
|
15
|
-
from flock.core.flock import Flock
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
logger = get_logger("flock.evaluator")
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
class FlockEvaluator:
|
|
22
|
-
"""Handles evaluation functionality for Flock orchestrator."""
|
|
23
|
-
|
|
24
|
-
def __init__(self, flock: "Flock"):
|
|
25
|
-
self.flock = flock
|
|
26
|
-
|
|
27
|
-
async def evaluate_async(
|
|
28
|
-
self,
|
|
29
|
-
dataset: str | Path | list[dict[str, Any]] | DataFrame | Dataset,
|
|
30
|
-
start_agent: FlockAgent | str,
|
|
31
|
-
input_mapping: dict[str, str],
|
|
32
|
-
answer_mapping: dict[str, str],
|
|
33
|
-
metrics: list[
|
|
34
|
-
str
|
|
35
|
-
| Callable[[Any, Any], bool | float | dict[str, Any]]
|
|
36
|
-
| FlockAgent
|
|
37
|
-
],
|
|
38
|
-
metric_configs: dict[str, dict[str, Any]] | None = None,
|
|
39
|
-
static_inputs: dict[str, Any] | None = None,
|
|
40
|
-
parallel: bool = True,
|
|
41
|
-
max_workers: int = 5,
|
|
42
|
-
use_temporal: bool | None = None,
|
|
43
|
-
error_handling: Literal["raise", "skip", "log"] = "log",
|
|
44
|
-
output_file: str | Path | None = None,
|
|
45
|
-
return_dataframe: bool = True,
|
|
46
|
-
silent_mode: bool = False,
|
|
47
|
-
metadata_columns: list[str] | None = None,
|
|
48
|
-
) -> "DataFrame | list[dict[str, Any]]":
|
|
49
|
-
"""Evaluates the Flock's performance against a dataset (delegated)."""
|
|
50
|
-
# Import processor locally
|
|
51
|
-
from flock.core.execution.evaluation_executor import EvaluationExecutor
|
|
52
|
-
|
|
53
|
-
processor = EvaluationExecutor(self.flock) # Pass flock instance
|
|
54
|
-
return await processor.evaluate_async(
|
|
55
|
-
dataset=dataset,
|
|
56
|
-
start_agent=start_agent,
|
|
57
|
-
input_mapping=input_mapping,
|
|
58
|
-
answer_mapping=answer_mapping,
|
|
59
|
-
metrics=metrics,
|
|
60
|
-
metric_configs=metric_configs,
|
|
61
|
-
static_inputs=static_inputs,
|
|
62
|
-
parallel=parallel,
|
|
63
|
-
max_workers=max_workers,
|
|
64
|
-
use_temporal=use_temporal,
|
|
65
|
-
error_handling=error_handling,
|
|
66
|
-
output_file=output_file,
|
|
67
|
-
return_dataframe=return_dataframe,
|
|
68
|
-
silent_mode=silent_mode,
|
|
69
|
-
metadata_columns=metadata_columns,
|
|
70
|
-
)
|
|
71
|
-
|
|
72
|
-
def evaluate(
|
|
73
|
-
self,
|
|
74
|
-
dataset: str | Path | list[dict[str, Any]] | DataFrame | Dataset,
|
|
75
|
-
start_agent: FlockAgent | str,
|
|
76
|
-
input_mapping: dict[str, str],
|
|
77
|
-
answer_mapping: dict[str, str],
|
|
78
|
-
metrics: list[
|
|
79
|
-
str
|
|
80
|
-
| Callable[[Any, Any], bool | float | dict[str, Any]]
|
|
81
|
-
| FlockAgent
|
|
82
|
-
],
|
|
83
|
-
metric_configs: dict[str, dict[str, Any]] | None = None,
|
|
84
|
-
static_inputs: dict[str, Any] | None = None,
|
|
85
|
-
parallel: bool = True,
|
|
86
|
-
max_workers: int = 5,
|
|
87
|
-
use_temporal: bool | None = None,
|
|
88
|
-
error_handling: Literal["raise", "skip", "log"] = "log",
|
|
89
|
-
output_file: str | Path | None = None,
|
|
90
|
-
return_dataframe: bool = True,
|
|
91
|
-
silent_mode: bool = False,
|
|
92
|
-
metadata_columns: list[str] | None = None,
|
|
93
|
-
) -> "DataFrame | list[dict[str, Any]]":
|
|
94
|
-
"""Synchronous wrapper for evaluation."""
|
|
95
|
-
return self.flock._execution._run_sync(
|
|
96
|
-
self.evaluate_async(
|
|
97
|
-
dataset=dataset,
|
|
98
|
-
start_agent=start_agent,
|
|
99
|
-
input_mapping=input_mapping,
|
|
100
|
-
answer_mapping=answer_mapping,
|
|
101
|
-
metrics=metrics,
|
|
102
|
-
metric_configs=metric_configs,
|
|
103
|
-
static_inputs=static_inputs,
|
|
104
|
-
parallel=parallel,
|
|
105
|
-
max_workers=max_workers,
|
|
106
|
-
use_temporal=use_temporal,
|
|
107
|
-
error_handling=error_handling,
|
|
108
|
-
output_file=output_file,
|
|
109
|
-
return_dataframe=return_dataframe,
|
|
110
|
-
silent_mode=silent_mode,
|
|
111
|
-
metadata_columns=metadata_columns,
|
|
112
|
-
)
|
|
113
|
-
)
|
|
@@ -1,295 +0,0 @@
|
|
|
1
|
-
# src/flock/core/orchestration/flock_execution.py
|
|
2
|
-
"""Execution management functionality for Flock orchestrator."""
|
|
3
|
-
|
|
4
|
-
import asyncio
|
|
5
|
-
import contextvars
|
|
6
|
-
import uuid
|
|
7
|
-
from concurrent.futures import ThreadPoolExecutor
|
|
8
|
-
from typing import TYPE_CHECKING, Any, TypeVar
|
|
9
|
-
|
|
10
|
-
from box import Box
|
|
11
|
-
from opentelemetry import trace
|
|
12
|
-
from opentelemetry.baggage import set_baggage
|
|
13
|
-
|
|
14
|
-
from flock.config import DEFAULT_MODEL
|
|
15
|
-
from flock.core.context.context import FlockContext
|
|
16
|
-
from flock.core.context.context_manager import initialize_context
|
|
17
|
-
from flock.core.execution.local_executor import run_local_workflow
|
|
18
|
-
from flock.core.execution.temporal_executor import run_temporal_workflow
|
|
19
|
-
from flock.core.logging.logging import get_logger
|
|
20
|
-
|
|
21
|
-
if TYPE_CHECKING:
|
|
22
|
-
from flock.core.flock import Flock
|
|
23
|
-
from flock.core.flock_agent import FlockAgent
|
|
24
|
-
|
|
25
|
-
logger = get_logger("flock.execution")
|
|
26
|
-
tracer = trace.get_tracer(__name__)
|
|
27
|
-
_R = TypeVar("_R")
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
class FlockExecution:
|
|
31
|
-
"""Handles execution management for Flock including run, run_async, and execution coordination."""
|
|
32
|
-
|
|
33
|
-
def __init__(self, flock: "Flock"):
|
|
34
|
-
self.flock = flock
|
|
35
|
-
|
|
36
|
-
def _run_sync(self, coro) -> _R:
|
|
37
|
-
"""Execute *coro* synchronously.
|
|
38
|
-
|
|
39
|
-
* If no loop is running → ``asyncio.run``.
|
|
40
|
-
* Otherwise run ``asyncio.run`` inside a fresh thread **with**
|
|
41
|
-
context-vars propagation.
|
|
42
|
-
"""
|
|
43
|
-
try:
|
|
44
|
-
asyncio.get_running_loop()
|
|
45
|
-
except RuntimeError: # no loop → simple
|
|
46
|
-
return asyncio.run(coro)
|
|
47
|
-
|
|
48
|
-
# A loop is already running – Jupyter / ASGI / etc.
|
|
49
|
-
ctx = contextvars.copy_context() # propagate baggage
|
|
50
|
-
with ThreadPoolExecutor(max_workers=1) as pool:
|
|
51
|
-
future = pool.submit(ctx.run, asyncio.run, coro)
|
|
52
|
-
try:
|
|
53
|
-
return future.result()
|
|
54
|
-
finally:
|
|
55
|
-
if not future.done():
|
|
56
|
-
future.cancel()
|
|
57
|
-
|
|
58
|
-
def run(
|
|
59
|
-
self,
|
|
60
|
-
agent: "FlockAgent | str | None" = None,
|
|
61
|
-
input: dict | None = None,
|
|
62
|
-
context: FlockContext | None = None,
|
|
63
|
-
run_id: str = "",
|
|
64
|
-
box_result: bool = True,
|
|
65
|
-
agents: list["FlockAgent"] | None = None,
|
|
66
|
-
servers: list[Any] | None = None,
|
|
67
|
-
memo: dict[str, Any] | None = None,
|
|
68
|
-
) -> Box | dict:
|
|
69
|
-
"""Synchronous execution wrapper."""
|
|
70
|
-
return self._run_sync(
|
|
71
|
-
self.run_async(
|
|
72
|
-
agent=agent,
|
|
73
|
-
input=input,
|
|
74
|
-
context=context,
|
|
75
|
-
run_id=run_id,
|
|
76
|
-
box_result=box_result,
|
|
77
|
-
agents=agents,
|
|
78
|
-
servers=servers,
|
|
79
|
-
memo=memo,
|
|
80
|
-
)
|
|
81
|
-
)
|
|
82
|
-
|
|
83
|
-
async def run_async(
|
|
84
|
-
self,
|
|
85
|
-
agent: "FlockAgent | str | None" = None,
|
|
86
|
-
input: dict | None = None,
|
|
87
|
-
context: FlockContext | None = None,
|
|
88
|
-
run_id: str = "",
|
|
89
|
-
box_result: bool = True,
|
|
90
|
-
agents: list["FlockAgent"] | None = None,
|
|
91
|
-
servers: list[Any] | None = None,
|
|
92
|
-
memo: dict[str, Any] | None = None,
|
|
93
|
-
) -> Box | dict:
|
|
94
|
-
"""Entry point for running an agent system asynchronously."""
|
|
95
|
-
# Import here to allow forward reference resolution
|
|
96
|
-
from flock.core.flock_agent import FlockAgent as ConcreteFlockAgent
|
|
97
|
-
from flock.core.mcp.flock_mcp_server import (
|
|
98
|
-
FlockMCPServer as ConcreteFlockServer,
|
|
99
|
-
)
|
|
100
|
-
|
|
101
|
-
with tracer.start_as_current_span("flock.run_async") as span:
|
|
102
|
-
# Add passed servers so that agents have access to them.
|
|
103
|
-
if servers:
|
|
104
|
-
for server_obj in servers:
|
|
105
|
-
if isinstance(server_obj, ConcreteFlockServer):
|
|
106
|
-
self.flock.add_server(server=server_obj)
|
|
107
|
-
else:
|
|
108
|
-
logger.warning(
|
|
109
|
-
f"Item in 'servers' list is not a FlockMCPServer: {type(server_obj)}"
|
|
110
|
-
)
|
|
111
|
-
|
|
112
|
-
# Add passed agents
|
|
113
|
-
if agents:
|
|
114
|
-
for agent_obj in agents:
|
|
115
|
-
if isinstance(agent_obj, ConcreteFlockAgent):
|
|
116
|
-
self.flock.add_agent(agent_obj)
|
|
117
|
-
else:
|
|
118
|
-
logger.warning(
|
|
119
|
-
f"Item in 'agents' list is not a FlockAgent: {type(agent_obj)}"
|
|
120
|
-
)
|
|
121
|
-
|
|
122
|
-
# Determine starting agent name
|
|
123
|
-
start_agent_name = self._resolve_start_agent(agent)
|
|
124
|
-
|
|
125
|
-
# Setup execution context and input
|
|
126
|
-
run_input = input if input is not None else self.flock._start_input
|
|
127
|
-
# Accept Pydantic BaseModel instances as input by converting to dict
|
|
128
|
-
try:
|
|
129
|
-
from pydantic import BaseModel as _BM
|
|
130
|
-
if not isinstance(run_input, dict) and isinstance(run_input, _BM):
|
|
131
|
-
run_input = run_input.model_dump(exclude_none=True) # type: ignore[attr-defined]
|
|
132
|
-
except Exception:
|
|
133
|
-
pass
|
|
134
|
-
effective_run_id = run_id or f"flockrun_{uuid.uuid4().hex[:8]}"
|
|
135
|
-
|
|
136
|
-
# Set span attributes
|
|
137
|
-
span.set_attribute("start_agent", start_agent_name)
|
|
138
|
-
span.set_attribute("input", str(run_input))
|
|
139
|
-
span.set_attribute("run_id", effective_run_id)
|
|
140
|
-
span.set_attribute("enable_temporal", self.flock.enable_temporal)
|
|
141
|
-
|
|
142
|
-
logger.info(
|
|
143
|
-
f"Initiating Flock run '{self.flock.name}'. Model: '{self.flock.model}'. Start Agent: '{start_agent_name}'. Temporal: {self.flock.enable_temporal}."
|
|
144
|
-
)
|
|
145
|
-
|
|
146
|
-
try:
|
|
147
|
-
# Setup execution context
|
|
148
|
-
run_context = self._setup_execution_context(
|
|
149
|
-
context, start_agent_name, run_input, effective_run_id
|
|
150
|
-
)
|
|
151
|
-
|
|
152
|
-
# Execute workflow with server management
|
|
153
|
-
async with self.flock._mgr:
|
|
154
|
-
logger.info("Entering managed server context. Servers starting up.")
|
|
155
|
-
logger.info(
|
|
156
|
-
"Starting agent execution",
|
|
157
|
-
agent=start_agent_name,
|
|
158
|
-
enable_temporal=self.flock.enable_temporal,
|
|
159
|
-
)
|
|
160
|
-
|
|
161
|
-
# Execute workflow using appropriate engine
|
|
162
|
-
result = await self._execute_workflow(run_context, memo)
|
|
163
|
-
|
|
164
|
-
# Set result attributes on span
|
|
165
|
-
span.set_attribute("result.type", str(type(result)))
|
|
166
|
-
result_str = str(result)
|
|
167
|
-
span.set_attribute(
|
|
168
|
-
"result.preview",
|
|
169
|
-
result_str[:1000] + ("..." if len(result_str) > 1000 else ""),
|
|
170
|
-
)
|
|
171
|
-
|
|
172
|
-
# Format and return result
|
|
173
|
-
return self._format_result(result, box_result)
|
|
174
|
-
|
|
175
|
-
except Exception as e:
|
|
176
|
-
logger.error(f"Flock run '{self.flock.name}' failed: {e}", exc_info=True)
|
|
177
|
-
span.record_exception(e)
|
|
178
|
-
span.set_status(trace.Status(trace.StatusCode.ERROR, str(e)))
|
|
179
|
-
|
|
180
|
-
# Return a consistent error structure
|
|
181
|
-
error_output = {
|
|
182
|
-
"error": str(e),
|
|
183
|
-
"details": f"Flock run '{self.flock.name}' failed.",
|
|
184
|
-
"run_id": effective_run_id,
|
|
185
|
-
"start_agent": start_agent_name,
|
|
186
|
-
}
|
|
187
|
-
return Box(error_output) if box_result else error_output
|
|
188
|
-
|
|
189
|
-
def _resolve_start_agent(self, agent: "FlockAgent | str | None") -> str:
|
|
190
|
-
"""Resolve the start agent name from various input types."""
|
|
191
|
-
from flock.core.flock_agent import FlockAgent as ConcreteFlockAgent
|
|
192
|
-
from flock.core.registry import get_registry
|
|
193
|
-
|
|
194
|
-
registry = get_registry()
|
|
195
|
-
|
|
196
|
-
# Determine starting agent name
|
|
197
|
-
start_agent_name: str | None = None
|
|
198
|
-
if isinstance(agent, ConcreteFlockAgent):
|
|
199
|
-
start_agent_name = agent.name
|
|
200
|
-
if start_agent_name not in self.flock._agents: # Add if not already present
|
|
201
|
-
self.flock.add_agent(agent)
|
|
202
|
-
elif isinstance(agent, str):
|
|
203
|
-
start_agent_name = agent
|
|
204
|
-
else: # start_agent is None
|
|
205
|
-
start_agent_name = self.flock._start_agent_name
|
|
206
|
-
|
|
207
|
-
# Default to first agent if only one exists and none specified
|
|
208
|
-
if not start_agent_name and len(self.flock._agents) == 1:
|
|
209
|
-
start_agent_name = next(iter(self.flock._agents.keys()))
|
|
210
|
-
elif not start_agent_name:
|
|
211
|
-
raise ValueError(
|
|
212
|
-
"No start_agent specified and multiple/no agents exist in the Flock instance."
|
|
213
|
-
)
|
|
214
|
-
|
|
215
|
-
# Check if start_agent is in agents
|
|
216
|
-
if start_agent_name not in self.flock._agents:
|
|
217
|
-
# Try loading from registry if not found locally yet
|
|
218
|
-
reg_agent = registry.get_agent(start_agent_name)
|
|
219
|
-
if reg_agent:
|
|
220
|
-
self.flock.add_agent(reg_agent)
|
|
221
|
-
logger.info(f"Loaded start agent '{start_agent_name}' from registry.")
|
|
222
|
-
else:
|
|
223
|
-
raise ValueError(
|
|
224
|
-
f"Start agent '{start_agent_name}' not found locally or in registry."
|
|
225
|
-
)
|
|
226
|
-
|
|
227
|
-
return start_agent_name
|
|
228
|
-
|
|
229
|
-
def _setup_execution_context(
|
|
230
|
-
self,
|
|
231
|
-
context: FlockContext | None,
|
|
232
|
-
start_agent_name: str,
|
|
233
|
-
run_input: dict,
|
|
234
|
-
run_id: str,
|
|
235
|
-
) -> FlockContext:
|
|
236
|
-
"""Setup the execution context for the workflow."""
|
|
237
|
-
resolved_start_agent = self.flock._agents.get(start_agent_name)
|
|
238
|
-
if not resolved_start_agent: # Should have been handled by now
|
|
239
|
-
raise ValueError(f"Start agent '{start_agent_name}' not found after checks.")
|
|
240
|
-
|
|
241
|
-
run_context = context if context else FlockContext()
|
|
242
|
-
set_baggage("run_id", run_id) # Set for OpenTelemetry
|
|
243
|
-
|
|
244
|
-
initialize_context(
|
|
245
|
-
run_context,
|
|
246
|
-
start_agent_name,
|
|
247
|
-
run_input,
|
|
248
|
-
run_id,
|
|
249
|
-
not self.flock.enable_temporal, # local_debug is inverse of enable_temporal
|
|
250
|
-
self.flock.model or resolved_start_agent.model or DEFAULT_MODEL,
|
|
251
|
-
)
|
|
252
|
-
|
|
253
|
-
# Add agent definitions to context for routing/serialization within workflow
|
|
254
|
-
for agent_name_iter, agent_instance_iter in self.flock.agents.items():
|
|
255
|
-
agent_dict_repr = agent_instance_iter.to_dict() # Agents handle their own serialization
|
|
256
|
-
run_context.add_agent_definition(
|
|
257
|
-
agent_type=type(agent_instance_iter),
|
|
258
|
-
agent_name=agent_name_iter,
|
|
259
|
-
agent_data=agent_dict_repr,
|
|
260
|
-
)
|
|
261
|
-
|
|
262
|
-
# Add temporal config to context if enabled
|
|
263
|
-
if self.flock.enable_temporal and self.flock.temporal_config:
|
|
264
|
-
run_context.set_variable(
|
|
265
|
-
"flock.temporal_workflow_config",
|
|
266
|
-
self.flock.temporal_config.model_dump(mode="json"),
|
|
267
|
-
)
|
|
268
|
-
|
|
269
|
-
return run_context
|
|
270
|
-
|
|
271
|
-
async def _execute_workflow(
|
|
272
|
-
self, run_context: FlockContext, memo: dict[str, Any] | None = None
|
|
273
|
-
) -> dict[str, Any]:
|
|
274
|
-
"""Execute the workflow using the appropriate execution engine."""
|
|
275
|
-
if not self.flock.enable_temporal:
|
|
276
|
-
return await run_local_workflow(run_context, box_result=False)
|
|
277
|
-
else:
|
|
278
|
-
return await run_temporal_workflow(
|
|
279
|
-
self.flock, # Pass the Flock instance
|
|
280
|
-
run_context,
|
|
281
|
-
box_result=False,
|
|
282
|
-
memo=memo,
|
|
283
|
-
)
|
|
284
|
-
|
|
285
|
-
def _format_result(self, result: dict[str, Any], box_result: bool) -> Box | dict:
|
|
286
|
-
"""Format the execution result."""
|
|
287
|
-
if box_result:
|
|
288
|
-
try:
|
|
289
|
-
logger.debug("Boxing final result.")
|
|
290
|
-
return Box(result)
|
|
291
|
-
except ImportError:
|
|
292
|
-
logger.warning("Box library not installed, returning raw dict.")
|
|
293
|
-
return result
|
|
294
|
-
else:
|
|
295
|
-
return result
|