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
|
@@ -14,13 +14,12 @@ import logging
|
|
|
14
14
|
import sys
|
|
15
15
|
from typing import Literal
|
|
16
16
|
|
|
17
|
-
from opentelemetry import trace
|
|
18
|
-
|
|
19
17
|
# Always import Temporal workflow (since it's part of the project)
|
|
20
|
-
from temporalio import workflow
|
|
18
|
+
# from temporalio import workflow
|
|
19
|
+
# with workflow.unsafe.imports_passed_through():
|
|
20
|
+
from loguru import logger as loguru_logger
|
|
21
|
+
from opentelemetry import trace
|
|
21
22
|
|
|
22
|
-
with workflow.unsafe.imports_passed_through():
|
|
23
|
-
from loguru import logger as loguru_logger
|
|
24
23
|
|
|
25
24
|
# ENABLED_FLOCK_LOGGER_LEVELS constant removed
|
|
26
25
|
|
|
@@ -42,13 +41,14 @@ def in_workflow_context() -> bool:
|
|
|
42
41
|
It does this by attempting to call workflow.info() and returning True
|
|
43
42
|
if successful. Otherwise, it returns False.
|
|
44
43
|
"""
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
44
|
+
return False
|
|
45
|
+
# try:
|
|
46
|
+
# workflow.logger.debug("Checking if in workflow context...")
|
|
47
|
+
# # loguru_logger.debug("Checking if in workflow context...")
|
|
48
|
+
# # This call will succeed only if we're in a workflow context.
|
|
49
|
+
# return bool(hasattr(workflow.info(), "is_replaying"))
|
|
50
|
+
# except Exception:
|
|
51
|
+
# return False
|
|
52
52
|
|
|
53
53
|
|
|
54
54
|
def get_current_trace_id() -> str:
|
|
@@ -108,7 +108,7 @@ COLOR_MAP = {
|
|
|
108
108
|
|
|
109
109
|
LOGGERS = [
|
|
110
110
|
"flock", # Core Flock orchestration
|
|
111
|
-
"flock.api",
|
|
111
|
+
"flock.api", # Flock API specific logs
|
|
112
112
|
"agent", # General agent operations
|
|
113
113
|
"context", # Context management
|
|
114
114
|
"registry", # Unified registry operations (new)
|
|
@@ -177,9 +177,7 @@ def custom_format(record):
|
|
|
177
177
|
# MAX_LENGTH = 500 # Example value
|
|
178
178
|
if len(message) > MAX_LENGTH:
|
|
179
179
|
truncated_chars = len(message) - MAX_LENGTH
|
|
180
|
-
message = (
|
|
181
|
-
message[:MAX_LENGTH] + f"<yellow>...+({truncated_chars} chars)</yellow>"
|
|
182
|
-
)
|
|
180
|
+
message = message[:MAX_LENGTH] + f"<yellow>...+({truncated_chars} chars)</yellow>"
|
|
183
181
|
|
|
184
182
|
# Determine if category needs bolding (can refine this logic)
|
|
185
183
|
needs_bold = category in BOLD_CATEGORIES
|
|
@@ -247,7 +245,6 @@ class PrintAndFlushSink:
|
|
|
247
245
|
|
|
248
246
|
Already flushed on every write call.
|
|
249
247
|
"""
|
|
250
|
-
pass
|
|
251
248
|
|
|
252
249
|
|
|
253
250
|
# Configure Loguru for non-workflow (local/worker) contexts.
|
|
@@ -264,7 +261,9 @@ logging.basicConfig(level=LOG_LEVELS["ERROR"]) # Default to ERROR level for fal
|
|
|
264
261
|
# loguru_logger.add("logs/flock.log", rotation="100 MB", retention="30 days", level="DEBUG")
|
|
265
262
|
|
|
266
263
|
|
|
267
|
-
def get_default_severity(
|
|
264
|
+
def get_default_severity(
|
|
265
|
+
level: Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL", "NO_LOGS", "SUCCESS"] | int,
|
|
266
|
+
) -> int:
|
|
268
267
|
"""Get the default severity for a given level."""
|
|
269
268
|
if isinstance(level, str):
|
|
270
269
|
level_str = level.upper()
|
|
@@ -272,9 +271,17 @@ def get_default_severity(level: Literal["DEBUG", "INFO", "WARNING", "ERROR", "CR
|
|
|
272
271
|
return level
|
|
273
272
|
|
|
274
273
|
|
|
275
|
-
def configure_logging(
|
|
276
|
-
|
|
277
|
-
|
|
274
|
+
def configure_logging(
|
|
275
|
+
flock_level: Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL", "NO_LOGS", "SUCCESS"]
|
|
276
|
+
| int,
|
|
277
|
+
external_level: Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL", "NO_LOGS", "SUCCESS"]
|
|
278
|
+
| int,
|
|
279
|
+
specific_levels: dict[
|
|
280
|
+
str,
|
|
281
|
+
Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL", "NO_LOGS", "SUCCESS"] | int,
|
|
282
|
+
]
|
|
283
|
+
| None = None,
|
|
284
|
+
) -> None:
|
|
278
285
|
"""Configure both external and internal Flock logging systems.
|
|
279
286
|
|
|
280
287
|
Args:
|
|
@@ -283,19 +290,21 @@ def configure_logging(flock_level: Literal["DEBUG", "INFO", "WARNING", "ERROR",
|
|
|
283
290
|
specific_levels (dict[str, str | int] | None, optional): A dictionary mapping
|
|
284
291
|
logger names to their specific logging levels. Defaults to None.
|
|
285
292
|
"""
|
|
286
|
-
|
|
293
|
+
global _DEFAULT_FLOCK_SEVERITY, _SPECIFIC_SEVERITIES
|
|
287
294
|
|
|
295
|
+
# Get default severity
|
|
288
296
|
external_severity = get_default_severity(external_level)
|
|
289
297
|
logging.basicConfig(level=external_severity)
|
|
290
298
|
|
|
291
|
-
|
|
292
299
|
flock_severity = get_default_severity(flock_level)
|
|
300
|
+
_DEFAULT_FLOCK_SEVERITY = flock_severity # Store for future loggers
|
|
293
301
|
|
|
294
302
|
specific_severities = {}
|
|
295
303
|
if specific_levels:
|
|
296
304
|
for name, logger_level in specific_levels.items():
|
|
297
305
|
severity = get_default_severity(logger_level)
|
|
298
306
|
specific_severities[name] = severity
|
|
307
|
+
_SPECIFIC_SEVERITIES[name] = severity # Store for future loggers
|
|
299
308
|
|
|
300
309
|
# Apply to all cached loggers
|
|
301
310
|
for logger_name, log_instance in _LOGGER_CACHE.items():
|
|
@@ -306,28 +315,26 @@ def configure_logging(flock_level: Literal["DEBUG", "INFO", "WARNING", "ERROR",
|
|
|
306
315
|
log_instance.min_level_severity = target_severity
|
|
307
316
|
|
|
308
317
|
|
|
309
|
-
|
|
310
|
-
|
|
311
318
|
# Define a dummy logger that does nothing
|
|
312
319
|
class DummyLogger:
|
|
313
320
|
"""A dummy logger that does nothing when called."""
|
|
314
321
|
|
|
315
|
-
def debug(self, *args, **kwargs):
|
|
322
|
+
def debug(self, *args, **kwargs):
|
|
316
323
|
pass
|
|
317
324
|
|
|
318
|
-
def info(self, *args, **kwargs):
|
|
325
|
+
def info(self, *args, **kwargs):
|
|
319
326
|
pass
|
|
320
327
|
|
|
321
|
-
def warning(self, *args, **kwargs):
|
|
328
|
+
def warning(self, *args, **kwargs):
|
|
322
329
|
pass
|
|
323
330
|
|
|
324
|
-
def error(self, *args, **kwargs):
|
|
331
|
+
def error(self, *args, **kwargs):
|
|
325
332
|
pass
|
|
326
333
|
|
|
327
|
-
def exception(self, *args, **kwargs):
|
|
334
|
+
def exception(self, *args, **kwargs):
|
|
328
335
|
pass
|
|
329
336
|
|
|
330
|
-
def success(self, *args, **kwargs):
|
|
337
|
+
def success(self, *args, **kwargs):
|
|
331
338
|
pass
|
|
332
339
|
|
|
333
340
|
|
|
@@ -357,9 +364,9 @@ class FlockLogger:
|
|
|
357
364
|
self.min_level_severity = initial_min_level_severity
|
|
358
365
|
|
|
359
366
|
def _get_logger(self):
|
|
360
|
-
if in_workflow_context():
|
|
361
|
-
|
|
362
|
-
|
|
367
|
+
# if in_workflow_context():
|
|
368
|
+
# # Use Temporal's workflow.logger inside a workflow context.
|
|
369
|
+
# return workflow.logger
|
|
363
370
|
# Bind our logger with category and trace_id
|
|
364
371
|
return loguru_logger.bind(
|
|
365
372
|
name=self.name,
|
|
@@ -371,9 +378,7 @@ class FlockLogger:
|
|
|
371
378
|
"""Truncate a message if it exceeds max_length and add truncation indicator."""
|
|
372
379
|
if len(message) > max_length:
|
|
373
380
|
truncated_chars = len(message) - max_length
|
|
374
|
-
return (
|
|
375
|
-
message[:max_length] + f"...<yellow>+({truncated_chars} chars)</yellow>"
|
|
376
|
-
)
|
|
381
|
+
return message[:max_length] + f"...<yellow>+({truncated_chars} chars)</yellow>"
|
|
377
382
|
return message
|
|
378
383
|
|
|
379
384
|
def debug(
|
|
@@ -385,8 +390,10 @@ class FlockLogger:
|
|
|
385
390
|
**kwargs,
|
|
386
391
|
) -> None:
|
|
387
392
|
current_method_severity = LOG_LEVELS["DEBUG"]
|
|
388
|
-
if
|
|
389
|
-
|
|
393
|
+
if (
|
|
394
|
+
self.min_level_severity == LOG_LEVELS["NO_LOGS"]
|
|
395
|
+
or current_method_severity < self.min_level_severity
|
|
396
|
+
):
|
|
390
397
|
return
|
|
391
398
|
"""Debug a message.
|
|
392
399
|
|
|
@@ -407,8 +414,10 @@ class FlockLogger:
|
|
|
407
414
|
**kwargs,
|
|
408
415
|
) -> None:
|
|
409
416
|
current_method_severity = LOG_LEVELS["INFO"]
|
|
410
|
-
if
|
|
411
|
-
|
|
417
|
+
if (
|
|
418
|
+
self.min_level_severity == LOG_LEVELS["NO_LOGS"]
|
|
419
|
+
or current_method_severity < self.min_level_severity
|
|
420
|
+
):
|
|
412
421
|
return
|
|
413
422
|
"""Info a message.
|
|
414
423
|
|
|
@@ -429,8 +438,10 @@ class FlockLogger:
|
|
|
429
438
|
**kwargs,
|
|
430
439
|
) -> None:
|
|
431
440
|
current_method_severity = LOG_LEVELS["WARNING"]
|
|
432
|
-
if
|
|
433
|
-
|
|
441
|
+
if (
|
|
442
|
+
self.min_level_severity == LOG_LEVELS["NO_LOGS"]
|
|
443
|
+
or current_method_severity < self.min_level_severity
|
|
444
|
+
):
|
|
434
445
|
return
|
|
435
446
|
"""Warning a message.
|
|
436
447
|
|
|
@@ -451,8 +462,10 @@ class FlockLogger:
|
|
|
451
462
|
**kwargs,
|
|
452
463
|
) -> None:
|
|
453
464
|
current_method_severity = LOG_LEVELS["ERROR"]
|
|
454
|
-
if
|
|
455
|
-
|
|
465
|
+
if (
|
|
466
|
+
self.min_level_severity == LOG_LEVELS["NO_LOGS"]
|
|
467
|
+
or current_method_severity < self.min_level_severity
|
|
468
|
+
):
|
|
456
469
|
return
|
|
457
470
|
"""Error a message.
|
|
458
471
|
|
|
@@ -472,9 +485,11 @@ class FlockLogger:
|
|
|
472
485
|
max_length: int = MAX_LENGTH,
|
|
473
486
|
**kwargs,
|
|
474
487
|
) -> None:
|
|
475
|
-
current_method_severity = LOG_LEVELS["ERROR"]
|
|
476
|
-
if
|
|
477
|
-
|
|
488
|
+
current_method_severity = LOG_LEVELS["ERROR"] # Exception implies ERROR level
|
|
489
|
+
if (
|
|
490
|
+
self.min_level_severity == LOG_LEVELS["NO_LOGS"]
|
|
491
|
+
or current_method_severity < self.min_level_severity
|
|
492
|
+
):
|
|
478
493
|
return
|
|
479
494
|
"""Exception a message.
|
|
480
495
|
|
|
@@ -495,8 +510,10 @@ class FlockLogger:
|
|
|
495
510
|
**kwargs,
|
|
496
511
|
) -> None:
|
|
497
512
|
current_method_severity = LOG_LEVELS["SUCCESS"]
|
|
498
|
-
if
|
|
499
|
-
|
|
513
|
+
if (
|
|
514
|
+
self.min_level_severity == LOG_LEVELS["NO_LOGS"]
|
|
515
|
+
or current_method_severity < self.min_level_severity
|
|
516
|
+
):
|
|
500
517
|
return
|
|
501
518
|
"""Success a message.
|
|
502
519
|
|
|
@@ -510,21 +527,22 @@ class FlockLogger:
|
|
|
510
527
|
|
|
511
528
|
|
|
512
529
|
_LOGGER_CACHE: dict[str, FlockLogger] = {}
|
|
530
|
+
_DEFAULT_FLOCK_SEVERITY: int = LOG_LEVELS["ERROR"]
|
|
531
|
+
_SPECIFIC_SEVERITIES: dict[str, int] = {}
|
|
513
532
|
|
|
514
533
|
|
|
515
534
|
def get_logger(name: str = "flock") -> FlockLogger:
|
|
516
535
|
"""Return a cached FlockLogger instance for the given name.
|
|
517
536
|
|
|
518
|
-
If the logger doesn't exist, it is created
|
|
519
|
-
|
|
520
|
-
the `configure_logging()` function.
|
|
537
|
+
If the logger doesn't exist, it is created using the configured severity level
|
|
538
|
+
from configure_logging() (default: ERROR). Respects specific_levels if configured.
|
|
521
539
|
If a logger with the given name already exists in the cache, its 'min_level_severity'
|
|
522
540
|
state is NOT modified by this function; it's simply returned.
|
|
523
541
|
"""
|
|
524
542
|
if name not in _LOGGER_CACHE:
|
|
525
|
-
#
|
|
526
|
-
|
|
527
|
-
_LOGGER_CACHE[name] = FlockLogger(name,
|
|
543
|
+
# Check if there's a specific severity configured for this logger
|
|
544
|
+
severity = _SPECIFIC_SEVERITIES.get(name, _DEFAULT_FLOCK_SEVERITY)
|
|
545
|
+
_LOGGER_CACHE[name] = FlockLogger(name, severity)
|
|
528
546
|
# The min_level_severity state of existing or newly created loggers
|
|
529
547
|
# should be managed by the configure_logging() function.
|
|
530
548
|
return _LOGGER_CACHE[name]
|
|
@@ -544,15 +562,13 @@ def truncate_for_logging(obj, max_item_length=100, max_items=10):
|
|
|
544
562
|
"""Truncate large data structures for logging purposes."""
|
|
545
563
|
if isinstance(obj, str) and len(obj) > max_item_length:
|
|
546
564
|
return obj[:max_item_length] + f"... ({len(obj) - max_item_length} more chars)"
|
|
547
|
-
|
|
565
|
+
if isinstance(obj, dict):
|
|
548
566
|
if len(obj) > max_items:
|
|
549
567
|
return {
|
|
550
|
-
k: truncate_for_logging(v)
|
|
551
|
-
for i, (k, v) in enumerate(obj.items())
|
|
552
|
-
if i < max_items
|
|
568
|
+
k: truncate_for_logging(v) for i, (k, v) in enumerate(obj.items()) if i < max_items
|
|
553
569
|
}
|
|
554
570
|
return {k: truncate_for_logging(v) for k, v in obj.items()}
|
|
555
|
-
|
|
571
|
+
if isinstance(obj, list):
|
|
556
572
|
if len(obj) > max_items:
|
|
557
573
|
return [truncate_for_logging(item) for item in obj[:max_items]] + [
|
|
558
574
|
f"... ({len(obj) - max_items} more items)"
|
|
@@ -7,19 +7,19 @@ from opentelemetry import trace
|
|
|
7
7
|
from opentelemetry.sdk.resources import Resource
|
|
8
8
|
from opentelemetry.sdk.trace import TracerProvider
|
|
9
9
|
from opentelemetry.sdk.trace.export import SimpleSpanProcessor
|
|
10
|
-
from temporalio import workflow
|
|
11
10
|
|
|
12
|
-
from
|
|
11
|
+
# from temporalio import workflow
|
|
12
|
+
from flock.logging.span_middleware.baggage_span_processor import (
|
|
13
13
|
BaggageAttributeSpanProcessor,
|
|
14
14
|
)
|
|
15
15
|
|
|
16
|
-
with workflow.unsafe.imports_passed_through():
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
16
|
+
# with workflow.unsafe.imports_passed_through():
|
|
17
|
+
from flock.logging.telemetry_exporter.file_exporter import (
|
|
18
|
+
FileSpanExporter,
|
|
19
|
+
)
|
|
20
|
+
from flock.logging.telemetry_exporter.sqlite_exporter import (
|
|
21
|
+
SqliteTelemetryExporter,
|
|
22
|
+
)
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
class TelemetryConfig:
|
|
@@ -73,7 +73,12 @@ class TelemetryConfig:
|
|
|
73
73
|
|
|
74
74
|
def _should_setup(self) -> bool:
|
|
75
75
|
# Respect explicit disable flag for tests and minimal setups
|
|
76
|
-
if os.environ.get("FLOCK_DISABLE_TELEMETRY_AUTOSETUP", "").lower() in {
|
|
76
|
+
if os.environ.get("FLOCK_DISABLE_TELEMETRY_AUTOSETUP", "").lower() in {
|
|
77
|
+
"1",
|
|
78
|
+
"true",
|
|
79
|
+
"yes",
|
|
80
|
+
"on",
|
|
81
|
+
}:
|
|
77
82
|
return False
|
|
78
83
|
try:
|
|
79
84
|
# If a provider is already installed (typically by user/tests), don't override it
|
|
@@ -122,13 +127,10 @@ class TelemetryConfig:
|
|
|
122
127
|
collector_endpoint=self.jaeger_endpoint,
|
|
123
128
|
)
|
|
124
129
|
else:
|
|
125
|
-
raise ValueError(
|
|
126
|
-
"Invalid JAEGER_TRANSPORT specified. Use 'grpc' or 'http'."
|
|
127
|
-
)
|
|
130
|
+
raise ValueError("Invalid JAEGER_TRANSPORT specified. Use 'grpc' or 'http'.")
|
|
128
131
|
|
|
129
132
|
span_processors.append(SimpleSpanProcessor(jaeger_exporter))
|
|
130
133
|
|
|
131
|
-
|
|
132
134
|
if self.enable_otlp:
|
|
133
135
|
if self.otlp_protocol == "grpc":
|
|
134
136
|
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import (
|
|
@@ -156,16 +158,12 @@ class TelemetryConfig:
|
|
|
156
158
|
|
|
157
159
|
# If a file path is provided, add the custom file exporter.
|
|
158
160
|
if self.file_export_name and self.enable_file:
|
|
159
|
-
file_exporter = FileSpanExporter(
|
|
160
|
-
self.local_logging_dir, self.file_export_name
|
|
161
|
-
)
|
|
161
|
+
file_exporter = FileSpanExporter(self.local_logging_dir, self.file_export_name)
|
|
162
162
|
span_processors.append(SimpleSpanProcessor(file_exporter))
|
|
163
163
|
|
|
164
164
|
# If a SQLite database path is provided, ensure the DB exists and add the SQLite exporter.
|
|
165
165
|
if self.sqlite_db_name and self.enable_sql:
|
|
166
|
-
sqlite_exporter = SqliteTelemetryExporter(
|
|
167
|
-
self.local_logging_dir, self.sqlite_db_name
|
|
168
|
-
)
|
|
166
|
+
sqlite_exporter = SqliteTelemetryExporter(self.local_logging_dir, self.sqlite_db_name)
|
|
169
167
|
span_processors.append(SimpleSpanProcessor(sqlite_exporter))
|
|
170
168
|
|
|
171
169
|
# Register all span processors with the provider.
|
|
@@ -190,10 +188,6 @@ class TelemetryConfig:
|
|
|
190
188
|
return
|
|
191
189
|
|
|
192
190
|
# Use OpenTelemetry to record the exception
|
|
193
|
-
with self.global_tracer.start_as_current_span(
|
|
194
|
-
"UnhandledException"
|
|
195
|
-
) as span:
|
|
191
|
+
with self.global_tracer.start_as_current_span("UnhandledException") as span:
|
|
196
192
|
span.record_exception(exc_value)
|
|
197
|
-
span.set_status(
|
|
198
|
-
trace.Status(trace.StatusCode.ERROR, str(exc_value))
|
|
199
|
-
)
|
|
193
|
+
span.set_status(trace.Status(trace.StatusCode.ERROR, str(exc_value)))
|
|
@@ -25,14 +25,14 @@ class TelemetryExporter(SpanExporter, ABC):
|
|
|
25
25
|
self.shutdown()
|
|
26
26
|
|
|
27
27
|
@abstractmethod
|
|
28
|
-
def export(self, spans) -> SpanExportResult
|
|
28
|
+
def export(self, spans) -> SpanExportResult: # type: ignore[override]
|
|
29
29
|
"""Export spans to the configured backend.
|
|
30
30
|
|
|
31
31
|
To be implemented by subclasses.
|
|
32
|
+
May return SUCCESS, FAILURE, or None (handled by _export wrapper).
|
|
32
33
|
"""
|
|
33
34
|
raise NotImplementedError("Subclasses must implement the export method")
|
|
34
35
|
|
|
35
36
|
@abstractmethod
|
|
36
37
|
def shutdown(self):
|
|
37
38
|
"""Cleanup resources, if any. Optional for subclasses."""
|
|
38
|
-
pass
|
|
@@ -2,17 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
4
|
|
|
5
|
+
# with workflow.unsafe.imports_passed_through():
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
5
8
|
from opentelemetry.sdk.trace.export import SpanExportResult
|
|
6
9
|
from opentelemetry.trace import Status, StatusCode
|
|
7
|
-
from temporalio import workflow
|
|
8
10
|
|
|
9
|
-
from
|
|
11
|
+
# from temporalio import workflow
|
|
12
|
+
from flock.logging.telemetry_exporter.base_exporter import (
|
|
10
13
|
TelemetryExporter,
|
|
11
14
|
)
|
|
12
15
|
|
|
13
|
-
with workflow.unsafe.imports_passed_through():
|
|
14
|
-
from pathlib import Path
|
|
15
|
-
|
|
16
16
|
|
|
17
17
|
class FileSpanExporter(TelemetryExporter):
|
|
18
18
|
"""A simple exporter that writes span data as JSON lines into a file."""
|
|
@@ -63,10 +63,7 @@ class FileSpanExporter(TelemetryExporter):
|
|
|
63
63
|
}
|
|
64
64
|
for link in span.links
|
|
65
65
|
],
|
|
66
|
-
"resource":
|
|
67
|
-
attr_key: attr_value
|
|
68
|
-
for attr_key, attr_value in span.resource.attributes.items()
|
|
69
|
-
},
|
|
66
|
+
"resource": dict(span.resource.attributes.items()),
|
|
70
67
|
}
|
|
71
68
|
|
|
72
69
|
def export(self, spans):
|
|
@@ -7,7 +7,7 @@ from typing import Any
|
|
|
7
7
|
|
|
8
8
|
from opentelemetry.sdk.trace.export import SpanExportResult
|
|
9
9
|
|
|
10
|
-
from flock.
|
|
10
|
+
from flock.logging.telemetry_exporter.base_exporter import (
|
|
11
11
|
TelemetryExporter,
|
|
12
12
|
)
|
|
13
13
|
|
|
@@ -77,7 +77,7 @@ class SqliteTelemetryExporter(TelemetryExporter):
|
|
|
77
77
|
trace_id = format(span.context.trace_id, "032x")
|
|
78
78
|
cursor.execute(
|
|
79
79
|
"""
|
|
80
|
-
INSERT OR REPLACE INTO spans
|
|
80
|
+
INSERT OR REPLACE INTO spans
|
|
81
81
|
(id, name, trace_id, span_id, start_time, end_time, attributes, status)
|
|
82
82
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
83
83
|
""",
|
|
@@ -100,4 +100,3 @@ class SqliteTelemetryExporter(TelemetryExporter):
|
|
|
100
100
|
|
|
101
101
|
def shutdown(self) -> None:
|
|
102
102
|
"""Cleanup resources."""
|
|
103
|
-
pass
|
|
@@ -5,7 +5,8 @@ import inspect
|
|
|
5
5
|
|
|
6
6
|
from opentelemetry import trace
|
|
7
7
|
|
|
8
|
-
from flock.
|
|
8
|
+
from flock.logging.logging import get_logger
|
|
9
|
+
|
|
9
10
|
|
|
10
11
|
logger = get_logger("tools")
|
|
11
12
|
tracer = trace.get_tracer(__name__)
|
|
@@ -27,33 +28,28 @@ def traced_and_logged(func):
|
|
|
27
28
|
try:
|
|
28
29
|
result = await func(*args, **kwargs)
|
|
29
30
|
span.set_attribute("result", str(result))
|
|
30
|
-
logger.debug(
|
|
31
|
-
f"{func.__name__} executed successfully", result=result
|
|
32
|
-
)
|
|
31
|
+
logger.debug(f"{func.__name__} executed successfully", result=result)
|
|
33
32
|
return result
|
|
34
33
|
except Exception as e:
|
|
35
|
-
logger.
|
|
34
|
+
logger.exception(f"Error in {func.__name__}", error=str(e))
|
|
36
35
|
span.record_exception(e)
|
|
37
36
|
raise
|
|
38
37
|
|
|
39
38
|
return async_wrapper
|
|
40
|
-
else:
|
|
41
|
-
|
|
42
|
-
@functools.wraps(func)
|
|
43
|
-
def wrapper(*args, **kwargs):
|
|
44
|
-
with tracer.start_as_current_span(func.__name__) as span:
|
|
45
|
-
span.set_attribute("args", str(args))
|
|
46
|
-
span.set_attribute("kwargs", str(kwargs))
|
|
47
|
-
try:
|
|
48
|
-
result = func(*args, **kwargs)
|
|
49
|
-
span.set_attribute("result", str(result))
|
|
50
|
-
logger.debug(
|
|
51
|
-
f"{func.__name__} executed successfully", result=result
|
|
52
|
-
)
|
|
53
|
-
return result
|
|
54
|
-
except Exception as e:
|
|
55
|
-
logger.error(f"Error in {func.__name__}", error=str(e))
|
|
56
|
-
span.record_exception(e)
|
|
57
|
-
raise
|
|
58
39
|
|
|
59
|
-
|
|
40
|
+
@functools.wraps(func)
|
|
41
|
+
def wrapper(*args, **kwargs):
|
|
42
|
+
with tracer.start_as_current_span(func.__name__) as span:
|
|
43
|
+
span.set_attribute("args", str(args))
|
|
44
|
+
span.set_attribute("kwargs", str(kwargs))
|
|
45
|
+
try:
|
|
46
|
+
result = func(*args, **kwargs)
|
|
47
|
+
span.set_attribute("result", str(result))
|
|
48
|
+
logger.debug(f"{func.__name__} executed successfully", result=result)
|
|
49
|
+
return result
|
|
50
|
+
except Exception as e:
|
|
51
|
+
logger.exception(f"Error in {func.__name__}", error=str(e))
|
|
52
|
+
span.record_exception(e)
|
|
53
|
+
raise
|
|
54
|
+
|
|
55
|
+
return wrapper
|
flock/mcp/__init__.py
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"""MCP (Model Context Protocol) Integration for Flock-Flow.
|
|
2
|
+
|
|
3
|
+
This package provides integration with MCP servers, enabling agents to
|
|
4
|
+
dynamically discover and use external tools following the Model Context Protocol.
|
|
5
|
+
|
|
6
|
+
Architecture Decisions:
|
|
7
|
+
- AD001: Two-Level Architecture (orchestrator + agent)
|
|
8
|
+
- AD003: Tool Namespacing ({server}__{tool})
|
|
9
|
+
- AD004: Per-(agent_id, run_id) Connection Isolation
|
|
10
|
+
- AD005: Lazy Connection Establishment
|
|
11
|
+
- AD007: Graceful Degradation on MCP Failures
|
|
12
|
+
|
|
13
|
+
Key Components:
|
|
14
|
+
- FlockMCPConfiguration: Server configuration
|
|
15
|
+
- FlockMCPClient: Individual server connection
|
|
16
|
+
- FlockMCPClientManager: Connection pooling and lifecycle
|
|
17
|
+
- FlockMCPTool: MCP tool wrapper compatible with DSPy
|
|
18
|
+
|
|
19
|
+
Example Usage:
|
|
20
|
+
```python
|
|
21
|
+
from flock import Flock
|
|
22
|
+
from flock.mcp import StdioServerParameters
|
|
23
|
+
|
|
24
|
+
# Create orchestrator
|
|
25
|
+
orchestrator = Flock()
|
|
26
|
+
|
|
27
|
+
# Register MCP server
|
|
28
|
+
orchestrator.add_mcp(
|
|
29
|
+
name="filesystem",
|
|
30
|
+
connection_params=StdioServerParameters(
|
|
31
|
+
command="uvx",
|
|
32
|
+
args=["mcp-server-filesystem", "/tmp"]
|
|
33
|
+
)
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
# Build agent with MCP access
|
|
37
|
+
agent = (
|
|
38
|
+
orchestrator.agent("file_agent")
|
|
39
|
+
.with_mcps(["filesystem"])
|
|
40
|
+
.build()
|
|
41
|
+
)
|
|
42
|
+
```
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
from flock.mcp.client import FlockMCPClient
|
|
46
|
+
from flock.mcp.config import (
|
|
47
|
+
FlockMCPCachingConfiguration,
|
|
48
|
+
FlockMCPCallbackConfiguration,
|
|
49
|
+
FlockMCPConfiguration,
|
|
50
|
+
FlockMCPConnectionConfiguration,
|
|
51
|
+
FlockMCPFeatureConfiguration,
|
|
52
|
+
)
|
|
53
|
+
from flock.mcp.manager import FlockMCPClientManager
|
|
54
|
+
from flock.mcp.tool import FlockMCPTool
|
|
55
|
+
from flock.mcp.types import (
|
|
56
|
+
FlockListRootsMCPCallback,
|
|
57
|
+
FlockLoggingMCPCallback,
|
|
58
|
+
FlockMessageHandlerMCPCallback,
|
|
59
|
+
FlockSamplingMCPCallback,
|
|
60
|
+
MCPRoot,
|
|
61
|
+
ServerParameters,
|
|
62
|
+
SseServerParameters,
|
|
63
|
+
StdioServerParameters,
|
|
64
|
+
StreamableHttpServerParameters,
|
|
65
|
+
WebsocketServerParameters,
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
__all__ = [
|
|
70
|
+
"FlockListRootsMCPCallback",
|
|
71
|
+
"FlockLoggingMCPCallback",
|
|
72
|
+
"FlockMCPCachingConfiguration",
|
|
73
|
+
"FlockMCPCallbackConfiguration",
|
|
74
|
+
# Client and Manager
|
|
75
|
+
"FlockMCPClient",
|
|
76
|
+
"FlockMCPClientManager",
|
|
77
|
+
# Configuration
|
|
78
|
+
"FlockMCPConfiguration",
|
|
79
|
+
"FlockMCPConnectionConfiguration",
|
|
80
|
+
"FlockMCPFeatureConfiguration",
|
|
81
|
+
"FlockMCPTool",
|
|
82
|
+
"FlockMessageHandlerMCPCallback",
|
|
83
|
+
"FlockSamplingMCPCallback",
|
|
84
|
+
"MCPRoot",
|
|
85
|
+
# Types
|
|
86
|
+
"ServerParameters",
|
|
87
|
+
"SseServerParameters",
|
|
88
|
+
"StdioServerParameters",
|
|
89
|
+
"StreamableHttpServerParameters",
|
|
90
|
+
"WebsocketServerParameters",
|
|
91
|
+
]
|