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
flock/core/api/run_store.py
DELETED
|
@@ -1,224 +0,0 @@
|
|
|
1
|
-
# src/flock/core/api/run_store.py
|
|
2
|
-
"""Manages the state of active and completed Flock runs."""
|
|
3
|
-
|
|
4
|
-
import threading
|
|
5
|
-
from datetime import datetime
|
|
6
|
-
from typing import Any
|
|
7
|
-
|
|
8
|
-
from flock.core.logging.logging import get_logger
|
|
9
|
-
|
|
10
|
-
from .models import ( # Import from the models file
|
|
11
|
-
FlockAPIResponse,
|
|
12
|
-
FlockBatchResponse,
|
|
13
|
-
)
|
|
14
|
-
|
|
15
|
-
logger = get_logger("api.run_store")
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
class RunStore:
|
|
19
|
-
"""Stores and manages the state of Flock runs."""
|
|
20
|
-
|
|
21
|
-
def __init__(self):
|
|
22
|
-
self._runs: dict[str, FlockAPIResponse] = {}
|
|
23
|
-
self._batches: dict[str, FlockBatchResponse] = {}
|
|
24
|
-
self._lock = threading.Lock() # Basic lock for thread safety
|
|
25
|
-
|
|
26
|
-
def create_run(self, run_id: str) -> FlockAPIResponse:
|
|
27
|
-
"""Creates a new run record with 'starting' status."""
|
|
28
|
-
with self._lock:
|
|
29
|
-
if run_id in self._runs:
|
|
30
|
-
logger.warning(f"Run ID {run_id} already exists. Overwriting.")
|
|
31
|
-
response = FlockAPIResponse(
|
|
32
|
-
run_id=run_id, status="starting", started_at=datetime.now()
|
|
33
|
-
)
|
|
34
|
-
self._runs[run_id] = response
|
|
35
|
-
logger.debug(f"Created run record for run_id: {run_id}")
|
|
36
|
-
return response
|
|
37
|
-
|
|
38
|
-
def get_run(self, run_id: str) -> FlockAPIResponse | None:
|
|
39
|
-
"""Gets the status of a run."""
|
|
40
|
-
with self._lock:
|
|
41
|
-
return self._runs.get(run_id)
|
|
42
|
-
|
|
43
|
-
def update_run_status(
|
|
44
|
-
self, run_id: str, status: str, error: str | None = None
|
|
45
|
-
):
|
|
46
|
-
"""Updates the status and potentially error of a run."""
|
|
47
|
-
with self._lock:
|
|
48
|
-
if run_id in self._runs:
|
|
49
|
-
self._runs[run_id].status = status
|
|
50
|
-
if error:
|
|
51
|
-
self._runs[run_id].error = error
|
|
52
|
-
if status in ["completed", "failed"]:
|
|
53
|
-
self._runs[run_id].completed_at = datetime.now()
|
|
54
|
-
logger.debug(f"Updated status for run_id {run_id} to {status}")
|
|
55
|
-
else:
|
|
56
|
-
logger.warning(
|
|
57
|
-
f"Attempted to update status for non-existent run_id: {run_id}"
|
|
58
|
-
)
|
|
59
|
-
|
|
60
|
-
def update_run_result(self, run_id: str, result: dict):
|
|
61
|
-
"""Updates the result of a completed run."""
|
|
62
|
-
with self._lock:
|
|
63
|
-
if run_id in self._runs:
|
|
64
|
-
# Ensure result is serializable (e.g., convert Box)
|
|
65
|
-
final_result = (
|
|
66
|
-
dict(result) if hasattr(result, "to_dict") else result
|
|
67
|
-
)
|
|
68
|
-
self._runs[run_id].result = final_result
|
|
69
|
-
self._runs[run_id].status = "completed"
|
|
70
|
-
self._runs[run_id].completed_at = datetime.now()
|
|
71
|
-
logger.debug(f"Updated result for completed run_id: {run_id}")
|
|
72
|
-
else:
|
|
73
|
-
logger.warning(
|
|
74
|
-
f"Attempted to update result for non-existent run_id: {run_id}"
|
|
75
|
-
)
|
|
76
|
-
|
|
77
|
-
def create_batch(self, batch_id: str) -> FlockBatchResponse:
|
|
78
|
-
"""Creates a new batch record with 'starting' status."""
|
|
79
|
-
with self._lock:
|
|
80
|
-
if batch_id in self._batches:
|
|
81
|
-
logger.warning(
|
|
82
|
-
f"Batch ID {batch_id} already exists. Overwriting."
|
|
83
|
-
)
|
|
84
|
-
response = FlockBatchResponse(
|
|
85
|
-
batch_id=batch_id,
|
|
86
|
-
status="starting",
|
|
87
|
-
results=[],
|
|
88
|
-
started_at=datetime.now(),
|
|
89
|
-
total_items=0,
|
|
90
|
-
completed_items=0,
|
|
91
|
-
progress_percentage=0.0,
|
|
92
|
-
)
|
|
93
|
-
self._batches[batch_id] = response
|
|
94
|
-
logger.debug(f"Created batch record for batch_id: {batch_id}")
|
|
95
|
-
return response
|
|
96
|
-
|
|
97
|
-
def get_batch(self, batch_id: str) -> FlockBatchResponse | None:
|
|
98
|
-
"""Gets the status of a batch run."""
|
|
99
|
-
with self._lock:
|
|
100
|
-
return self._batches.get(batch_id)
|
|
101
|
-
|
|
102
|
-
def update_batch_status(
|
|
103
|
-
self, batch_id: str, status: str, error: str | None = None
|
|
104
|
-
):
|
|
105
|
-
"""Updates the status and potentially error of a batch run."""
|
|
106
|
-
with self._lock:
|
|
107
|
-
if batch_id in self._batches:
|
|
108
|
-
self._batches[batch_id].status = status
|
|
109
|
-
if error:
|
|
110
|
-
self._batches[batch_id].error = error
|
|
111
|
-
if status in ["completed", "failed"]:
|
|
112
|
-
self._batches[batch_id].completed_at = datetime.now()
|
|
113
|
-
# When completed, ensure progress is 100%
|
|
114
|
-
if (
|
|
115
|
-
status == "completed"
|
|
116
|
-
and self._batches[batch_id].total_items > 0
|
|
117
|
-
):
|
|
118
|
-
self._batches[batch_id].completed_items = self._batches[
|
|
119
|
-
batch_id
|
|
120
|
-
].total_items
|
|
121
|
-
self._batches[batch_id].progress_percentage = 100.0
|
|
122
|
-
logger.debug(
|
|
123
|
-
f"Updated status for batch_id {batch_id} to {status}"
|
|
124
|
-
)
|
|
125
|
-
else:
|
|
126
|
-
logger.warning(
|
|
127
|
-
f"Attempted to update status for non-existent batch_id: {batch_id}"
|
|
128
|
-
)
|
|
129
|
-
|
|
130
|
-
def update_batch_result(self, batch_id: str, results: list[Any]):
|
|
131
|
-
"""Updates the results of a completed batch run."""
|
|
132
|
-
with self._lock:
|
|
133
|
-
if batch_id in self._batches:
|
|
134
|
-
# Ensure results are serializable
|
|
135
|
-
final_results = [
|
|
136
|
-
dict(r) if hasattr(r, "to_dict") else r for r in results
|
|
137
|
-
]
|
|
138
|
-
self._batches[batch_id].results = final_results
|
|
139
|
-
self._batches[batch_id].status = "completed"
|
|
140
|
-
self._batches[batch_id].completed_at = datetime.now()
|
|
141
|
-
|
|
142
|
-
# Update progress tracking
|
|
143
|
-
self._batches[batch_id].completed_items = len(final_results)
|
|
144
|
-
self._batches[batch_id].total_items = len(final_results)
|
|
145
|
-
self._batches[batch_id].progress_percentage = 100.0
|
|
146
|
-
|
|
147
|
-
logger.debug(
|
|
148
|
-
f"Updated results for completed batch_id: {batch_id}"
|
|
149
|
-
)
|
|
150
|
-
else:
|
|
151
|
-
logger.warning(
|
|
152
|
-
f"Attempted to update results for non-existent batch_id: {batch_id}"
|
|
153
|
-
)
|
|
154
|
-
|
|
155
|
-
def set_batch_total_items(self, batch_id: str, total_items: int):
|
|
156
|
-
"""Sets the total number of items in a batch."""
|
|
157
|
-
try:
|
|
158
|
-
with self._lock:
|
|
159
|
-
if batch_id in self._batches:
|
|
160
|
-
self._batches[batch_id].total_items = total_items
|
|
161
|
-
# Recalculate percentage
|
|
162
|
-
if total_items > 0:
|
|
163
|
-
self._batches[batch_id].progress_percentage = (
|
|
164
|
-
self._batches[batch_id].completed_items
|
|
165
|
-
/ total_items
|
|
166
|
-
* 100.0
|
|
167
|
-
)
|
|
168
|
-
logger.debug(
|
|
169
|
-
f"Set total_items for batch_id {batch_id} to {total_items}"
|
|
170
|
-
)
|
|
171
|
-
else:
|
|
172
|
-
logger.warning(
|
|
173
|
-
f"Attempted to set total_items for non-existent batch_id: {batch_id}"
|
|
174
|
-
)
|
|
175
|
-
except Exception as e:
|
|
176
|
-
logger.error(f"Error setting batch total items: {e}", exc_info=True)
|
|
177
|
-
|
|
178
|
-
def update_batch_progress(
|
|
179
|
-
self,
|
|
180
|
-
batch_id: str,
|
|
181
|
-
completed_items: int,
|
|
182
|
-
partial_results: list[Any] = None,
|
|
183
|
-
):
|
|
184
|
-
"""Updates the progress of a batch run and optionally adds partial results.
|
|
185
|
-
|
|
186
|
-
Args:
|
|
187
|
-
batch_id: The ID of the batch to update
|
|
188
|
-
completed_items: The number of items that have been completed
|
|
189
|
-
partial_results: Optional list of results for completed items to add to the batch
|
|
190
|
-
"""
|
|
191
|
-
try:
|
|
192
|
-
with self._lock:
|
|
193
|
-
if batch_id in self._batches:
|
|
194
|
-
self._batches[batch_id].completed_items = completed_items
|
|
195
|
-
|
|
196
|
-
# Calculate percentage if we have a total
|
|
197
|
-
if self._batches[batch_id].total_items > 0:
|
|
198
|
-
self._batches[batch_id].progress_percentage = (
|
|
199
|
-
completed_items
|
|
200
|
-
/ self._batches[batch_id].total_items
|
|
201
|
-
* 100.0
|
|
202
|
-
)
|
|
203
|
-
|
|
204
|
-
# Add partial results if provided
|
|
205
|
-
if partial_results:
|
|
206
|
-
# Ensure results are serializable
|
|
207
|
-
final_results = [
|
|
208
|
-
dict(r) if hasattr(r, "to_dict") else r
|
|
209
|
-
for r in partial_results
|
|
210
|
-
]
|
|
211
|
-
self._batches[batch_id].results = final_results
|
|
212
|
-
|
|
213
|
-
logger.debug(
|
|
214
|
-
f"Updated progress for batch_id {batch_id}: {completed_items}/{self._batches[batch_id].total_items} "
|
|
215
|
-
f"({self._batches[batch_id].progress_percentage:.1f}%)"
|
|
216
|
-
)
|
|
217
|
-
else:
|
|
218
|
-
logger.warning(
|
|
219
|
-
f"Attempted to update progress for non-existent batch_id: {batch_id}"
|
|
220
|
-
)
|
|
221
|
-
except Exception as e:
|
|
222
|
-
logger.error(f"Error updating batch progress: {e}", exc_info=True)
|
|
223
|
-
|
|
224
|
-
# Add methods for cleanup, persistence, etc. later
|
flock/core/api/runner.py
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
# src/flock/api/runner.py
|
|
2
|
-
"""Provides functionality to start the Flock API server."""
|
|
3
|
-
|
|
4
|
-
from collections.abc import Callable, Sequence
|
|
5
|
-
from typing import TYPE_CHECKING, Any
|
|
6
|
-
|
|
7
|
-
from flock.core.api.custom_endpoint import FlockEndpoint
|
|
8
|
-
from flock.core.logging.logging import get_logger
|
|
9
|
-
|
|
10
|
-
if TYPE_CHECKING:
|
|
11
|
-
from flock.core.flock import Flock
|
|
12
|
-
|
|
13
|
-
logger = get_logger("api.runner")
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
def start_flock_api(
|
|
17
|
-
flock: "Flock",
|
|
18
|
-
host: str = "127.0.0.1",
|
|
19
|
-
port: int = 8344,
|
|
20
|
-
server_name: str = "Flock API",
|
|
21
|
-
create_ui: bool = False,
|
|
22
|
-
custom_endpoints: Sequence[FlockEndpoint] | dict[tuple[str, list[str] | None], Callable[..., Any]] | None = None,
|
|
23
|
-
) -> None:
|
|
24
|
-
"""Start a REST API server for the given Flock instance."""
|
|
25
|
-
try:
|
|
26
|
-
# Import API class locally to avoid making it a hard dependency for core flock
|
|
27
|
-
from flock.core.api import FlockAPI
|
|
28
|
-
except ImportError:
|
|
29
|
-
logger.error(
|
|
30
|
-
"API components not found. Cannot start API. "
|
|
31
|
-
"Ensure 'fastapi' and 'uvicorn' are installed."
|
|
32
|
-
)
|
|
33
|
-
return
|
|
34
|
-
|
|
35
|
-
logger.info(
|
|
36
|
-
f"Preparing to start API server for Flock '{flock.name}' on {host}:{port} {'with UI' if create_ui else 'without UI'}"
|
|
37
|
-
)
|
|
38
|
-
api_instance = FlockAPI(flock, custom_endpoints=custom_endpoints) # Pass the Flock instance to the API
|
|
39
|
-
api_instance.start(
|
|
40
|
-
host=host,
|
|
41
|
-
port=port,
|
|
42
|
-
server_name=server_name,
|
|
43
|
-
create_ui=create_ui,
|
|
44
|
-
)
|
flock/core/api/service.py
DELETED
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
# flock/core/api/service.py
|
|
2
|
-
from typing import TYPE_CHECKING, Any
|
|
3
|
-
|
|
4
|
-
if TYPE_CHECKING:
|
|
5
|
-
from flock.core.api.endpoints import FlockBatchRequest
|
|
6
|
-
from flock.core.api.run_store import RunStore
|
|
7
|
-
from flock.core.flock import Flock
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
from flock.core.logging.logging import get_logger
|
|
11
|
-
|
|
12
|
-
logger = get_logger("flock.api")
|
|
13
|
-
|
|
14
|
-
class FlockApiService:
|
|
15
|
-
def __init__(self, flock_instance: "Flock", run_store_instance: "RunStore"):
|
|
16
|
-
self.flock = flock_instance
|
|
17
|
-
self.run_store = run_store_instance
|
|
18
|
-
# You would move the _run_flock, _run_batch, _type_convert_inputs methods here
|
|
19
|
-
# from the old FlockAPI class.
|
|
20
|
-
async def _run_flock(
|
|
21
|
-
self, run_id: str, agent_name: str, inputs: dict[str, Any]
|
|
22
|
-
):
|
|
23
|
-
"""Executes a flock workflow run (internal helper)."""
|
|
24
|
-
try:
|
|
25
|
-
if agent_name not in self.flock.agents:
|
|
26
|
-
raise ValueError(f"Starting agent '{agent_name}' not found")
|
|
27
|
-
|
|
28
|
-
typed_inputs = self._type_convert_inputs(agent_name, inputs)
|
|
29
|
-
|
|
30
|
-
logger.debug(
|
|
31
|
-
f"Executing flock workflow starting with '{agent_name}' (run_id: {run_id})",
|
|
32
|
-
inputs=typed_inputs,
|
|
33
|
-
)
|
|
34
|
-
# Flock.run_async now handles context creation and execution
|
|
35
|
-
result = await self.flock.run_async(
|
|
36
|
-
agent=agent_name, input=typed_inputs
|
|
37
|
-
)
|
|
38
|
-
self.run_store.update_run_result(run_id, result)
|
|
39
|
-
|
|
40
|
-
final_agent_name = (
|
|
41
|
-
result.get("agent_name", "N/A") if isinstance(result, dict) else "N/A"
|
|
42
|
-
) # Handle if result is not a dict (e.g. Box)
|
|
43
|
-
logger.info(
|
|
44
|
-
f"Flock workflow completed (run_id: {run_id})",
|
|
45
|
-
final_agent=final_agent_name,
|
|
46
|
-
)
|
|
47
|
-
except Exception as e:
|
|
48
|
-
logger.error(
|
|
49
|
-
f"Error in flock run {run_id} (started with '{agent_name}'): {e!s}",
|
|
50
|
-
exc_info=True,
|
|
51
|
-
)
|
|
52
|
-
self.run_store.update_run_status(run_id, "failed", str(e))
|
|
53
|
-
raise
|
|
54
|
-
|
|
55
|
-
async def _run_batch(self, batch_id: str, request: "FlockBatchRequest"):
|
|
56
|
-
"""Executes a batch of runs (internal helper)."""
|
|
57
|
-
try:
|
|
58
|
-
if request.agent_name not in self.flock.agents:
|
|
59
|
-
raise ValueError(f"Agent '{request.agent_name}' not found")
|
|
60
|
-
|
|
61
|
-
logger.debug(
|
|
62
|
-
f"Executing batch run starting with '{request.agent_name}' (batch_id: {batch_id})",
|
|
63
|
-
batch_size=len(request.batch_inputs)
|
|
64
|
-
if isinstance(request.batch_inputs, list)
|
|
65
|
-
else "CSV/DataFrame",
|
|
66
|
-
)
|
|
67
|
-
|
|
68
|
-
# --- Re-integrating the threaded batch execution from Flock.run_batch_async ---
|
|
69
|
-
import asyncio
|
|
70
|
-
import threading
|
|
71
|
-
from concurrent.futures import ThreadPoolExecutor
|
|
72
|
-
|
|
73
|
-
def run_batch_sync_in_thread():
|
|
74
|
-
loop = asyncio.new_event_loop()
|
|
75
|
-
asyncio.set_event_loop(loop)
|
|
76
|
-
try:
|
|
77
|
-
batch_size = (
|
|
78
|
-
len(request.batch_inputs)
|
|
79
|
-
if isinstance(request.batch_inputs, list)
|
|
80
|
-
else 0 # Or attempt to get from DataFrame/CSV load
|
|
81
|
-
)
|
|
82
|
-
if batch_size > 0:
|
|
83
|
-
self.run_store.set_batch_total_items(batch_id, batch_size)
|
|
84
|
-
|
|
85
|
-
class ProgressTracker:
|
|
86
|
-
def __init__(self, store, b_id, total_size):
|
|
87
|
-
self.store, self.batch_id, self.total_size = store, b_id, total_size
|
|
88
|
-
self.current_count, self.partial_results, self._lock = 0, [], threading.Lock()
|
|
89
|
-
def increment(self, res=None):
|
|
90
|
-
with self._lock:
|
|
91
|
-
self.current_count += 1
|
|
92
|
-
if res is not None: self.partial_results.append(res)
|
|
93
|
-
try: self.store.update_batch_progress(self.batch_id, self.current_count, self.partial_results)
|
|
94
|
-
except Exception as e_prog: logger.error(f"Error updating progress: {e_prog}")
|
|
95
|
-
return self.current_count
|
|
96
|
-
|
|
97
|
-
progress_tracker = ProgressTracker(self.run_store, batch_id, batch_size)
|
|
98
|
-
|
|
99
|
-
async def progress_aware_worker(index, item_inputs):
|
|
100
|
-
try:
|
|
101
|
-
# Call Flock's run_async for a single item
|
|
102
|
-
item_result = await self.flock.run_async(
|
|
103
|
-
agent=request.agent_name,
|
|
104
|
-
input=item_inputs,
|
|
105
|
-
box_result=request.box_results,
|
|
106
|
-
)
|
|
107
|
-
progress_tracker.increment(item_result)
|
|
108
|
-
return item_result
|
|
109
|
-
except Exception as item_err:
|
|
110
|
-
logger.error(f"Error processing batch item {index}: {item_err}")
|
|
111
|
-
progress_tracker.increment(item_err if request.return_errors else None)
|
|
112
|
-
if request.return_errors: return item_err
|
|
113
|
-
return None
|
|
114
|
-
|
|
115
|
-
batch_inputs_list = request.batch_inputs
|
|
116
|
-
actual_results_list = []
|
|
117
|
-
|
|
118
|
-
if isinstance(batch_inputs_list, list):
|
|
119
|
-
tasks = []
|
|
120
|
-
for i, item_inputs in enumerate(batch_inputs_list):
|
|
121
|
-
full_inputs = {**(request.static_inputs or {}), **item_inputs}
|
|
122
|
-
tasks.append(progress_aware_worker(i, full_inputs))
|
|
123
|
-
|
|
124
|
-
if request.parallel and request.max_workers > 1:
|
|
125
|
-
semaphore = asyncio.Semaphore(request.max_workers)
|
|
126
|
-
async def bounded_worker(idx, inputs_item):
|
|
127
|
-
async with semaphore: return await progress_aware_worker(idx, inputs_item)
|
|
128
|
-
bounded_tasks = [bounded_worker(i, {**(request.static_inputs or {}), **item}) for i, item in enumerate(batch_inputs_list)]
|
|
129
|
-
actual_results_list = loop.run_until_complete(asyncio.gather(*bounded_tasks, return_exceptions=request.return_errors))
|
|
130
|
-
else:
|
|
131
|
-
for i, item_inputs in enumerate(batch_inputs_list):
|
|
132
|
-
full_inputs = {**(request.static_inputs or {}), **item_inputs}
|
|
133
|
-
actual_results_list.append(loop.run_until_complete(progress_aware_worker(i, full_inputs)))
|
|
134
|
-
else: # DataFrame or CSV path - let Flock's batch processor handle this directly
|
|
135
|
-
# This path relies on self.flock.run_batch_async being able to run within this new event loop.
|
|
136
|
-
# It might be simpler to always convert DataFrame/CSV to list of dicts before this point.
|
|
137
|
-
actual_results_list = loop.run_until_complete(
|
|
138
|
-
self.flock.run_batch_async(
|
|
139
|
-
start_agent=request.agent_name,
|
|
140
|
-
batch_inputs=request.batch_inputs, # DataFrame or path
|
|
141
|
-
input_mapping=request.input_mapping,
|
|
142
|
-
static_inputs=request.static_inputs,
|
|
143
|
-
parallel=request.parallel, # Will be re-evaluated by internal BatchProcessor
|
|
144
|
-
max_workers=request.max_workers,
|
|
145
|
-
use_temporal=request.use_temporal, # Will be re-evaluated
|
|
146
|
-
box_results=request.box_results,
|
|
147
|
-
return_errors=request.return_errors,
|
|
148
|
-
silent_mode=True, # Internal batch runs silently for API
|
|
149
|
-
write_to_csv=None # API handles CSV output separately if needed
|
|
150
|
-
)
|
|
151
|
-
)
|
|
152
|
-
# Progress for DataFrame/CSV would need integration into BatchProcessor or this loop
|
|
153
|
-
if actual_results_list:
|
|
154
|
-
self.run_store.set_batch_total_items(batch_id, len(actual_results_list))
|
|
155
|
-
self.run_store.update_batch_progress(batch_id, len(actual_results_list), actual_results_list)
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
self.run_store.update_batch_result(batch_id, actual_results_list)
|
|
159
|
-
logger.info(f"Batch run completed (batch_id: {batch_id})", num_results=len(actual_results_list))
|
|
160
|
-
return actual_results_list
|
|
161
|
-
except Exception as thread_err:
|
|
162
|
-
logger.error(f"Error in batch run thread {batch_id}: {thread_err!s}", exc_info=True)
|
|
163
|
-
self.run_store.update_batch_status(batch_id, "failed", str(thread_err))
|
|
164
|
-
return None
|
|
165
|
-
finally:
|
|
166
|
-
loop.close()
|
|
167
|
-
# --- End of re-integrated threaded batch execution ---
|
|
168
|
-
|
|
169
|
-
# Submit the synchronous function to a thread pool from the main event loop
|
|
170
|
-
main_loop = asyncio.get_running_loop()
|
|
171
|
-
with ThreadPoolExecutor(thread_name_prefix="flock-api-batch") as pool:
|
|
172
|
-
await main_loop.run_in_executor(pool, run_batch_sync_in_thread)
|
|
173
|
-
|
|
174
|
-
except Exception as e:
|
|
175
|
-
logger.error(
|
|
176
|
-
f"Error setting up batch run {batch_id} (started with '{request.agent_name}'): {e!s}",
|
|
177
|
-
exc_info=True,
|
|
178
|
-
)
|
|
179
|
-
self.run_store.update_batch_status(batch_id, "failed", str(e))
|
|
180
|
-
raise
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
def _type_convert_inputs(
|
|
187
|
-
self, agent_name: str, inputs: dict[str, Any]
|
|
188
|
-
) -> dict[str, Any]:
|
|
189
|
-
"""Converts input values (esp. from forms) to expected Python types."""
|
|
190
|
-
typed_inputs = {}
|
|
191
|
-
agent_def = self.flock.agents.get(agent_name)
|
|
192
|
-
if not agent_def or not agent_def.input or not isinstance(agent_def.input, str):
|
|
193
|
-
return inputs # Return original if no spec or spec is not a string
|
|
194
|
-
|
|
195
|
-
parsed_fields = self._parse_input_spec(agent_def.input) # Relies on the old UI helper
|
|
196
|
-
field_types = {f["name"]: f["type"] for f in parsed_fields}
|
|
197
|
-
|
|
198
|
-
for k, v in inputs.items():
|
|
199
|
-
target_type_str = field_types.get(k)
|
|
200
|
-
if target_type_str:
|
|
201
|
-
if target_type_str.startswith("bool"):
|
|
202
|
-
typed_inputs[k] = str(v).lower() in ["true", "on", "1", "yes"] if isinstance(v, str) else bool(v)
|
|
203
|
-
elif target_type_str.startswith("int"):
|
|
204
|
-
try: typed_inputs[k] = int(v)
|
|
205
|
-
except (ValueError, TypeError): logger.warning(f"Could not convert '{k}' value '{v}' to int for agent '{agent_name}'"); typed_inputs[k] = v
|
|
206
|
-
elif target_type_str.startswith("float"):
|
|
207
|
-
try: typed_inputs[k] = float(v)
|
|
208
|
-
except (ValueError, TypeError): logger.warning(f"Could not convert '{k}' value '{v}' to float for agent '{agent_name}'"); typed_inputs[k] = v
|
|
209
|
-
# TODO: Add list/dict parsing (e.g., json.loads) if type_str indicates these,
|
|
210
|
-
# especially if inputs come from HTML forms as strings.
|
|
211
|
-
else: typed_inputs[k] = v
|
|
212
|
-
else:
|
|
213
|
-
typed_inputs[k] = v
|
|
214
|
-
return typed_inputs
|
flock/core/component/__init__.py
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
# src/flock/core/component/__init__.py
|
|
2
|
-
"""Unified component system for Flock agents."""
|
|
3
|
-
|
|
4
|
-
from .agent_component_base import AgentComponent, AgentComponentConfig
|
|
5
|
-
from .evaluation_component import EvaluationComponent
|
|
6
|
-
from .routing_component import RoutingComponent
|
|
7
|
-
from .utility_component import UtilityComponent
|
|
8
|
-
|
|
9
|
-
__all__ = [
|
|
10
|
-
"AgentComponent",
|
|
11
|
-
"AgentComponentConfig",
|
|
12
|
-
"EvaluationComponent",
|
|
13
|
-
"RoutingComponent",
|
|
14
|
-
"UtilityComponent",
|
|
15
|
-
]
|