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,381 +0,0 @@
|
|
|
1
|
-
# src/flock/core/agent/flock_agent_serialization.py
|
|
2
|
-
"""Serialization functionality for FlockAgent."""
|
|
3
|
-
|
|
4
|
-
import json
|
|
5
|
-
import os
|
|
6
|
-
from datetime import datetime
|
|
7
|
-
from typing import TYPE_CHECKING, Any, TypeVar
|
|
8
|
-
|
|
9
|
-
# Legacy component imports removed
|
|
10
|
-
from flock.core.logging.logging import get_logger
|
|
11
|
-
from flock.core.mcp.flock_mcp_server import FlockMCPServer
|
|
12
|
-
from flock.core.serialization.json_encoder import FlockJSONEncoder
|
|
13
|
-
from flock.core.serialization.serialization_utils import (
|
|
14
|
-
deserialize_component,
|
|
15
|
-
serialize_item,
|
|
16
|
-
)
|
|
17
|
-
|
|
18
|
-
if TYPE_CHECKING:
|
|
19
|
-
from flock.core.flock_agent import FlockAgent
|
|
20
|
-
|
|
21
|
-
logger = get_logger("agent.serialization")
|
|
22
|
-
T = TypeVar("T", bound="FlockAgent")
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
class FlockAgentSerialization:
|
|
26
|
-
"""Handles serialization and deserialization for FlockAgent."""
|
|
27
|
-
|
|
28
|
-
def __init__(self, agent: "FlockAgent"):
|
|
29
|
-
self.agent = agent
|
|
30
|
-
|
|
31
|
-
def _save_output(self, agent_name: str, result: dict[str, Any]) -> None:
|
|
32
|
-
"""Save output to file if configured."""
|
|
33
|
-
if not self.agent.config.write_to_file:
|
|
34
|
-
return
|
|
35
|
-
|
|
36
|
-
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
37
|
-
filename = f"{agent_name}_output_{timestamp}.json"
|
|
38
|
-
filepath = os.path.join(".flock/output/", filename)
|
|
39
|
-
os.makedirs(".flock/output/", exist_ok=True)
|
|
40
|
-
|
|
41
|
-
output_data = {
|
|
42
|
-
"agent": agent_name,
|
|
43
|
-
"timestamp": timestamp,
|
|
44
|
-
"output": result,
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
try:
|
|
48
|
-
with open(filepath, "w") as f:
|
|
49
|
-
json.dump(output_data, f, indent=2, cls=FlockJSONEncoder)
|
|
50
|
-
except Exception as e:
|
|
51
|
-
logger.warning(f"Failed to save output to file: {e}")
|
|
52
|
-
|
|
53
|
-
def to_dict(self) -> dict[str, Any]:
|
|
54
|
-
"""Convert instance to dictionary representation suitable for serialization."""
|
|
55
|
-
from flock.core.registry import get_registry
|
|
56
|
-
|
|
57
|
-
registry = get_registry()
|
|
58
|
-
|
|
59
|
-
exclude = [
|
|
60
|
-
"context",
|
|
61
|
-
"components",
|
|
62
|
-
"tools",
|
|
63
|
-
"servers",
|
|
64
|
-
]
|
|
65
|
-
|
|
66
|
-
is_description_callable = False
|
|
67
|
-
is_input_callable = False
|
|
68
|
-
is_output_callable = False
|
|
69
|
-
is_next_agent_callable = False
|
|
70
|
-
# if self.agent.description is a callable, exclude it
|
|
71
|
-
if callable(self.agent.description_spec):
|
|
72
|
-
is_description_callable = True
|
|
73
|
-
exclude.append("description_spec")
|
|
74
|
-
# if self.agent.input is a callable, exclude it
|
|
75
|
-
if callable(self.agent.input_spec):
|
|
76
|
-
is_input_callable = True
|
|
77
|
-
exclude.append("input_spec")
|
|
78
|
-
# if self.agent.output is a callable, exclude it
|
|
79
|
-
if callable(self.agent.output_spec):
|
|
80
|
-
is_output_callable = True
|
|
81
|
-
exclude.append("output_spec")
|
|
82
|
-
if callable(self.agent.next_agent_spec):
|
|
83
|
-
is_next_agent_callable = True
|
|
84
|
-
exclude.append("next_agent_spec")
|
|
85
|
-
|
|
86
|
-
logger.debug(f"Serializing agent '{self.agent.name}' to dict.")
|
|
87
|
-
# Use Pydantic's dump, exclude manually handled fields and runtime context
|
|
88
|
-
data = self.agent.model_dump(
|
|
89
|
-
exclude=exclude,
|
|
90
|
-
mode="json", # Use json mode for better handling of standard types by Pydantic
|
|
91
|
-
exclude_none=True, # Exclude None values for cleaner output
|
|
92
|
-
)
|
|
93
|
-
logger.debug(f"Base agent data for '{self.agent.name}': {list(data.keys())}")
|
|
94
|
-
|
|
95
|
-
# Serialize components list using unified architecture
|
|
96
|
-
if self.agent.components:
|
|
97
|
-
serialized_components = []
|
|
98
|
-
for component in self.agent.components:
|
|
99
|
-
try:
|
|
100
|
-
comp_type = type(component)
|
|
101
|
-
type_name = registry.get_component_type_name(comp_type)
|
|
102
|
-
if type_name:
|
|
103
|
-
component_data = serialize_item(component)
|
|
104
|
-
if isinstance(component_data, dict):
|
|
105
|
-
component_data["type"] = type_name
|
|
106
|
-
serialized_components.append(component_data)
|
|
107
|
-
else:
|
|
108
|
-
logger.warning(f"Component {component.name} serialization failed")
|
|
109
|
-
else:
|
|
110
|
-
logger.warning(f"Component {component.name} type not registered")
|
|
111
|
-
except Exception as e:
|
|
112
|
-
logger.error(f"Failed to serialize component {component.name}: {e}")
|
|
113
|
-
|
|
114
|
-
if serialized_components:
|
|
115
|
-
data["components"] = serialized_components
|
|
116
|
-
logger.debug(f"Added {len(serialized_components)} components to agent '{self.agent.name}'")
|
|
117
|
-
|
|
118
|
-
# --- Serialize Servers ---
|
|
119
|
-
if self.agent.servers:
|
|
120
|
-
logger.debug(
|
|
121
|
-
f"Serializing {len(self.agent.servers)} servers for agent '{self.agent.name}'"
|
|
122
|
-
)
|
|
123
|
-
serialized_servers = []
|
|
124
|
-
for server in self.agent.servers:
|
|
125
|
-
if isinstance(server, FlockMCPServer):
|
|
126
|
-
serialized_servers.append(server.config.name)
|
|
127
|
-
else:
|
|
128
|
-
# Write it down as a list of server names.
|
|
129
|
-
serialized_servers.append(server)
|
|
130
|
-
|
|
131
|
-
if serialized_servers:
|
|
132
|
-
data["mcp_servers"] = serialized_servers
|
|
133
|
-
logger.debug(
|
|
134
|
-
f"Added {len(serialized_servers)} servers to agent '{self.agent.name}'"
|
|
135
|
-
)
|
|
136
|
-
|
|
137
|
-
# --- Serialize Tools (Callables) ---
|
|
138
|
-
if self.agent.tools:
|
|
139
|
-
logger.debug(
|
|
140
|
-
f"Serializing {len(self.agent.tools)} tools for agent '{self.agent.name}'"
|
|
141
|
-
)
|
|
142
|
-
serialized_tools = []
|
|
143
|
-
for tool in self.agent.tools:
|
|
144
|
-
if callable(tool) and not isinstance(tool, type):
|
|
145
|
-
path_str = registry.get_callable_path_string(tool)
|
|
146
|
-
if path_str:
|
|
147
|
-
# Get just the function name from the path string
|
|
148
|
-
# If it's a namespaced path like module.submodule.function_name
|
|
149
|
-
# Just use the function_name part
|
|
150
|
-
func_name = path_str.split(".")[-1]
|
|
151
|
-
serialized_tools.append(func_name)
|
|
152
|
-
logger.debug(
|
|
153
|
-
f"Added tool '{func_name}' (from path '{path_str}') to agent '{self.agent.name}'"
|
|
154
|
-
)
|
|
155
|
-
else:
|
|
156
|
-
logger.warning(
|
|
157
|
-
f"Could not get path string for tool {tool} in agent '{self.agent.name}'. Skipping."
|
|
158
|
-
)
|
|
159
|
-
else:
|
|
160
|
-
logger.warning(
|
|
161
|
-
f"Non-callable item found in tools list for agent '{self.agent.name}': {tool}. Skipping."
|
|
162
|
-
)
|
|
163
|
-
if serialized_tools:
|
|
164
|
-
data["tools"] = serialized_tools
|
|
165
|
-
logger.debug(
|
|
166
|
-
f"Added {len(serialized_tools)} tools to agent '{self.agent.name}'"
|
|
167
|
-
)
|
|
168
|
-
|
|
169
|
-
if is_description_callable:
|
|
170
|
-
path_str = registry.get_callable_path_string(self.agent.description_spec)
|
|
171
|
-
if path_str:
|
|
172
|
-
func_name = path_str.split(".")[-1]
|
|
173
|
-
data["description_callable"] = func_name
|
|
174
|
-
logger.debug(
|
|
175
|
-
f"Added description '{func_name}' (from path '{path_str}') to agent '{self.agent.name}'"
|
|
176
|
-
)
|
|
177
|
-
else:
|
|
178
|
-
logger.warning(
|
|
179
|
-
f"Could not get path string for description {self.agent.description_spec} in agent '{self.agent.name}'. Skipping."
|
|
180
|
-
)
|
|
181
|
-
|
|
182
|
-
if is_input_callable:
|
|
183
|
-
path_str = registry.get_callable_path_string(self.agent.input_spec)
|
|
184
|
-
if path_str:
|
|
185
|
-
func_name = path_str.split(".")[-1]
|
|
186
|
-
data["input_callable"] = func_name
|
|
187
|
-
logger.debug(
|
|
188
|
-
f"Added input '{func_name}' (from path '{path_str}') to agent '{self.agent.name}'"
|
|
189
|
-
)
|
|
190
|
-
else:
|
|
191
|
-
logger.warning(
|
|
192
|
-
f"Could not get path string for input {self.agent.input_spec} in agent '{self.agent.name}'. Skipping."
|
|
193
|
-
)
|
|
194
|
-
|
|
195
|
-
if is_output_callable:
|
|
196
|
-
path_str = registry.get_callable_path_string(self.agent.output_spec)
|
|
197
|
-
if path_str:
|
|
198
|
-
func_name = path_str.split(".")[-1]
|
|
199
|
-
data["output_callable"] = func_name
|
|
200
|
-
logger.debug(
|
|
201
|
-
f"Added output '{func_name}' (from path '{path_str}') to agent '{self.agent.name}'"
|
|
202
|
-
)
|
|
203
|
-
else:
|
|
204
|
-
logger.warning(
|
|
205
|
-
f"Could not get path string for output {self.agent.output_spec} in agent '{self.agent.name}'. Skipping."
|
|
206
|
-
)
|
|
207
|
-
|
|
208
|
-
if is_next_agent_callable:
|
|
209
|
-
path_str = registry.get_callable_path_string(self.agent.next_agent_spec)
|
|
210
|
-
if path_str:
|
|
211
|
-
func_name = path_str.split(".")[-1]
|
|
212
|
-
data["next_agent_callable"] = func_name
|
|
213
|
-
logger.debug(
|
|
214
|
-
f"Added next_agent '{func_name}' (from path '{path_str}') to agent '{self.agent.name}'"
|
|
215
|
-
)
|
|
216
|
-
else:
|
|
217
|
-
logger.warning(
|
|
218
|
-
f"Could not get path string for next_agent {self.agent.next_agent_spec} in agent '{self.agent.name}'. Skipping."
|
|
219
|
-
)
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
logger.info(
|
|
223
|
-
f"Serialization of agent '{self.agent.name}' complete with {len(data)} fields"
|
|
224
|
-
)
|
|
225
|
-
return data
|
|
226
|
-
|
|
227
|
-
@classmethod
|
|
228
|
-
def from_dict(cls, agent_class: type[T], data: dict[str, Any]) -> T:
|
|
229
|
-
"""Deserialize the agent from a dictionary, including components, tools, and callables."""
|
|
230
|
-
from flock.core.component.agent_component_base import AgentComponent
|
|
231
|
-
from flock.core.registry import get_registry
|
|
232
|
-
|
|
233
|
-
registry = get_registry()
|
|
234
|
-
logger.debug(
|
|
235
|
-
f"Deserializing agent from dict. Keys: {list(data.keys())}"
|
|
236
|
-
)
|
|
237
|
-
|
|
238
|
-
# --- Separate Data ---
|
|
239
|
-
components_data = data.pop("components", [])
|
|
240
|
-
callable_configs = {}
|
|
241
|
-
tool_config = data.pop("tools", [])
|
|
242
|
-
servers_config = data.pop("mcp_servers", [])
|
|
243
|
-
|
|
244
|
-
callable_keys = [
|
|
245
|
-
"description_callable",
|
|
246
|
-
"input_callable",
|
|
247
|
-
"output_callable",
|
|
248
|
-
"next_agent_callable",
|
|
249
|
-
]
|
|
250
|
-
|
|
251
|
-
for key in callable_keys:
|
|
252
|
-
if key in data and data[key] is not None:
|
|
253
|
-
callable_configs[key] = data.pop(key)
|
|
254
|
-
|
|
255
|
-
# --- Deserialize Base Agent ---
|
|
256
|
-
# Ensure required fields like 'name' are present if needed by __init__
|
|
257
|
-
if "name" not in data:
|
|
258
|
-
raise ValueError(
|
|
259
|
-
"Agent data must include a 'name' field for deserialization."
|
|
260
|
-
)
|
|
261
|
-
agent_name_log = data["name"] # For logging
|
|
262
|
-
logger.info(f"Deserializing base agent data for '{agent_name_log}'")
|
|
263
|
-
|
|
264
|
-
# Pydantic should handle base fields based on type hints in __init__
|
|
265
|
-
agent = agent_class(**data)
|
|
266
|
-
logger.debug(f"Base agent '{agent.name}' instantiated.")
|
|
267
|
-
|
|
268
|
-
# --- Deserialize Components ---
|
|
269
|
-
logger.debug(f"Deserializing components for '{agent.name}'")
|
|
270
|
-
if components_data:
|
|
271
|
-
for component_data in components_data:
|
|
272
|
-
try:
|
|
273
|
-
# Use the existing deserialize_component function
|
|
274
|
-
component = deserialize_component(component_data, AgentComponent)
|
|
275
|
-
if component:
|
|
276
|
-
agent.add_component(component)
|
|
277
|
-
logger.debug(f"Deserialized and added component '{component.name}' for '{agent.name}'")
|
|
278
|
-
except Exception as e:
|
|
279
|
-
logger.error(f"Failed to deserialize component: {e}")
|
|
280
|
-
|
|
281
|
-
# --- Deserialize Tools ---
|
|
282
|
-
agent.tools = [] # Initialize tools list
|
|
283
|
-
if tool_config:
|
|
284
|
-
logger.debug(
|
|
285
|
-
f"Deserializing {len(tool_config)} tools for '{agent.name}'"
|
|
286
|
-
)
|
|
287
|
-
# Use get_callable to find each tool
|
|
288
|
-
for tool_name_or_path in tool_config:
|
|
289
|
-
try:
|
|
290
|
-
found_tool = registry.get_callable(tool_name_or_path)
|
|
291
|
-
if found_tool and callable(found_tool):
|
|
292
|
-
agent.tools.append(found_tool)
|
|
293
|
-
logger.debug(
|
|
294
|
-
f"Resolved and added tool '{tool_name_or_path}' for agent '{agent.name}'"
|
|
295
|
-
)
|
|
296
|
-
else:
|
|
297
|
-
# Should not happen if get_callable returns successfully but just in case
|
|
298
|
-
logger.warning(
|
|
299
|
-
f"Registry returned non-callable for tool '{tool_name_or_path}' for agent '{agent.name}'. Skipping."
|
|
300
|
-
)
|
|
301
|
-
except (
|
|
302
|
-
ValueError
|
|
303
|
-
) as e: # get_callable raises ValueError if not found/ambiguous
|
|
304
|
-
logger.warning(
|
|
305
|
-
f"Could not resolve tool '{tool_name_or_path}' for agent '{agent.name}': {e}. Skipping."
|
|
306
|
-
)
|
|
307
|
-
except Exception as e:
|
|
308
|
-
logger.error(
|
|
309
|
-
f"Unexpected error resolving tool '{tool_name_or_path}' for agent '{agent.name}': {e}. Skipping.",
|
|
310
|
-
exc_info=True,
|
|
311
|
-
)
|
|
312
|
-
|
|
313
|
-
# --- Deserialize Servers ---
|
|
314
|
-
agent.servers = [] # Initialize Servers list.
|
|
315
|
-
if servers_config:
|
|
316
|
-
logger.debug(
|
|
317
|
-
f"Deserializing {len(servers_config)} servers for '{agent.name}'"
|
|
318
|
-
)
|
|
319
|
-
# Agents keep track of server by getting a list of server names.
|
|
320
|
-
# The server instances will be retrieved during runtime from the registry. (default behavior)
|
|
321
|
-
|
|
322
|
-
for server_name in servers_config:
|
|
323
|
-
if isinstance(server_name, str):
|
|
324
|
-
# Case 1 (default behavior): A server name is passed.
|
|
325
|
-
agent.servers.append(server_name)
|
|
326
|
-
elif isinstance(server_name, FlockMCPServer):
|
|
327
|
-
# Case 2 (highly unlikely): If someone somehow manages to pass
|
|
328
|
-
# an instance of a server during the deserialization step (however that might be achieved)
|
|
329
|
-
# check the registry, if the server is already registered, if not, register it
|
|
330
|
-
# and store the name in the servers list
|
|
331
|
-
server_exists = (
|
|
332
|
-
registry.get_server(server_name.config.name)
|
|
333
|
-
is not None
|
|
334
|
-
)
|
|
335
|
-
if server_exists:
|
|
336
|
-
agent.servers.append(server_name.config.name)
|
|
337
|
-
else:
|
|
338
|
-
registry.register_server(
|
|
339
|
-
server=server_name
|
|
340
|
-
) # register it.
|
|
341
|
-
agent.servers.append(server_name.config.name)
|
|
342
|
-
|
|
343
|
-
# --- Deserialize Callables ---
|
|
344
|
-
logger.debug(f"Deserializing callable fields for '{agent.name}'")
|
|
345
|
-
|
|
346
|
-
def resolve_and_assign(field_name: str, callable_key: str):
|
|
347
|
-
if callable_key in callable_configs:
|
|
348
|
-
callable_name = callable_configs[callable_key]
|
|
349
|
-
try:
|
|
350
|
-
# Use get_callable to find the signature function
|
|
351
|
-
found_callable = registry.get_callable(callable_name)
|
|
352
|
-
if found_callable and callable(found_callable):
|
|
353
|
-
setattr(agent, field_name, found_callable)
|
|
354
|
-
logger.debug(
|
|
355
|
-
f"Resolved callable '{callable_name}' for field '{field_name}' on agent '{agent.name}'"
|
|
356
|
-
)
|
|
357
|
-
else:
|
|
358
|
-
logger.warning(
|
|
359
|
-
f"Registry returned non-callable for name '{callable_name}' for field '{field_name}' on agent '{agent.name}'. Field remains default."
|
|
360
|
-
)
|
|
361
|
-
except (
|
|
362
|
-
ValueError
|
|
363
|
-
) as e: # get_callable raises ValueError if not found/ambiguous
|
|
364
|
-
logger.warning(
|
|
365
|
-
f"Could not resolve callable '{callable_name}' in registry for field '{field_name}' on agent '{agent.name}': {e}. Field remains default."
|
|
366
|
-
)
|
|
367
|
-
except Exception as e:
|
|
368
|
-
logger.error(
|
|
369
|
-
f"Unexpected error resolving callable '{callable_name}' for field '{field_name}' on agent '{agent.name}': {e}. Field remains default.",
|
|
370
|
-
exc_info=True,
|
|
371
|
-
)
|
|
372
|
-
# Else: key not present, field retains its default value from __init__
|
|
373
|
-
|
|
374
|
-
resolve_and_assign("description", "description_callable")
|
|
375
|
-
resolve_and_assign("input", "input_callable")
|
|
376
|
-
resolve_and_assign("output", "output_callable")
|
|
377
|
-
resolve_and_assign("next_agent", "next_agent_callable")
|
|
378
|
-
# --- Finalize ---
|
|
379
|
-
|
|
380
|
-
logger.info(f"Successfully deserialized agent '{agent.name}'.")
|
|
381
|
-
return agent
|
flock/core/api/__init__.py
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
"""Lightweight helper object for declaring additional REST routes.
|
|
2
|
-
|
|
3
|
-
Developers can pass instances of :class:`FlockEndpoint` to
|
|
4
|
-
``Flock.start_api(custom_endpoints=[...])`` instead of the terse dictionary
|
|
5
|
-
syntax. The class carries optional Pydantic request/response models plus
|
|
6
|
-
OpenAPI metadata so the generated docs look perfect.
|
|
7
|
-
"""
|
|
8
|
-
from __future__ import annotations
|
|
9
|
-
|
|
10
|
-
from collections.abc import Callable
|
|
11
|
-
from typing import Any
|
|
12
|
-
|
|
13
|
-
from pydantic import BaseModel
|
|
14
|
-
|
|
15
|
-
__all__ = [
|
|
16
|
-
"FlockEndpoint",
|
|
17
|
-
]
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
class FlockEndpoint(BaseModel):
|
|
21
|
-
"""Declarative description of an extra API route."""
|
|
22
|
-
|
|
23
|
-
path: str
|
|
24
|
-
methods: list[str] = ["GET"]
|
|
25
|
-
callback: Callable[..., Any]
|
|
26
|
-
|
|
27
|
-
# Optional schema models
|
|
28
|
-
request_model: type[BaseModel] | None = None
|
|
29
|
-
response_model: type[BaseModel] | None = None
|
|
30
|
-
# Query-string parameters as a Pydantic model (treated as Depends())
|
|
31
|
-
query_model: type[BaseModel] | None = None
|
|
32
|
-
|
|
33
|
-
# OpenAPI / Swagger metadata
|
|
34
|
-
summary: str | None = None
|
|
35
|
-
description: str | None = None
|
|
36
|
-
name: str | None = None # Route name in FastAPI
|
|
37
|
-
include_in_schema: bool = True
|
|
38
|
-
|
|
39
|
-
# FastAPI dependency injections (e.g. security)
|
|
40
|
-
dependencies: list[Any] | None = None
|
|
41
|
-
|
|
42
|
-
model_config = {
|
|
43
|
-
"arbitrary_types_allowed": True,
|
|
44
|
-
"validate_default": True,
|
|
45
|
-
}
|