flock-core 0.5.0b14__py3-none-any.whl → 0.5.0b15__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 CHANGED
@@ -5,7 +5,7 @@ import os
5
5
  import sys
6
6
 
7
7
 
8
- def main():
8
+ def main(): # noqa: C901
9
9
  """Main function."""
10
10
  # Parse command line arguments
11
11
  parser = argparse.ArgumentParser(
@@ -103,7 +103,7 @@ def main():
103
103
  from rich.panel import Panel
104
104
 
105
105
  from flock.cli.config import init_config_file, load_config_file
106
- from flock.cli.constants import (
106
+ from flock.cli.constants import ( # noqa: F401
107
107
  CLI_CFG_FILE,
108
108
  CLI_CREATE_AGENT,
109
109
  CLI_CREATE_FLOCK,
flock/config.py CHANGED
@@ -1,3 +1,8 @@
1
+ """Global configuration for Flock.
2
+
3
+ Reads environment via `decouple` and exposes constants used across the codebase.
4
+ """
5
+
1
6
  # flock/config.py
2
7
  import os
3
8
 
flock/core/__init__.py CHANGED
@@ -1,48 +1,30 @@
1
- """This module contains the core classes of the flock package."""
2
-
3
- from flock.core.component import (
4
- AgentComponent,
5
- AgentComponentConfig,
6
- EvaluationComponent,
7
- RoutingComponent,
8
- UtilityComponent,
9
- )
10
- from flock.core.context.context import FlockContext
11
- from flock.core.flock import Flock
12
- from flock.core.flock_agent import FlockAgent
13
- from flock.core.flock_factory import FlockFactory
14
- from flock.core.mcp.flock_mcp_server import (
15
- FlockMCPServer,
16
- )
17
- from flock.core.mcp.flock_mcp_tool import FlockMCPTool
18
- from flock.core.mcp.mcp_client import FlockMCPClient
19
- from flock.core.mcp.mcp_client_manager import FlockMCPClientManager
20
- from flock.core.registry import (
21
- RegistryHub as FlockRegistry, # Keep FlockRegistry name for API compatibility
22
- flock_callable,
23
- flock_component,
24
- flock_tool,
25
- flock_type,
26
- get_registry,
27
- )
1
+ """Core package public API with lazy imports.
2
+
3
+ This module exposes key symbols while avoiding heavy imports at package import time.
4
+ Symbols are imported lazily on first access via ``__getattr__``.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from typing import Any
28
10
 
29
11
  __all__ = [
30
12
  "Flock",
31
13
  "FlockAgent",
32
14
  "FlockContext",
33
15
  "FlockFactory",
34
- # Components
16
+ # Components
35
17
  "AgentComponent",
36
18
  "AgentComponentConfig",
37
19
  "EvaluationComponent",
38
20
  "RoutingComponent",
39
21
  "UtilityComponent",
40
-
22
+ # MCP
41
23
  "FlockMCPClient",
42
24
  "FlockMCPClientManager",
43
25
  "FlockMCPServer",
44
- "FlockMCPServerConfig",
45
26
  "FlockMCPTool",
27
+ # Registry
46
28
  "FlockRegistry",
47
29
  "flock_callable",
48
30
  "flock_component",
@@ -50,3 +32,74 @@ __all__ = [
50
32
  "flock_type",
51
33
  "get_registry",
52
34
  ]
35
+
36
+
37
+ def __getattr__(name: str) -> Any: # pragma: no cover - thin loader
38
+ if name == "Flock":
39
+ from .flock import Flock
40
+
41
+ return Flock
42
+ if name == "FlockAgent":
43
+ from .flock_agent import FlockAgent
44
+
45
+ return FlockAgent
46
+ if name == "FlockContext":
47
+ from .context.context import FlockContext
48
+
49
+ return FlockContext
50
+ if name == "FlockFactory":
51
+ from .flock_factory import FlockFactory
52
+
53
+ return FlockFactory
54
+ if name in {"AgentComponent", "AgentComponentConfig", "EvaluationComponent", "RoutingComponent", "UtilityComponent"}:
55
+ from .component import (
56
+ AgentComponent,
57
+ AgentComponentConfig,
58
+ EvaluationComponent,
59
+ RoutingComponent,
60
+ UtilityComponent,
61
+ )
62
+
63
+ return {
64
+ "AgentComponent": AgentComponent,
65
+ "AgentComponentConfig": AgentComponentConfig,
66
+ "EvaluationComponent": EvaluationComponent,
67
+ "RoutingComponent": RoutingComponent,
68
+ "UtilityComponent": UtilityComponent,
69
+ }[name]
70
+ if name in {"FlockMCPClient", "FlockMCPClientManager", "FlockMCPServer", "FlockMCPTool"}:
71
+ if name == "FlockMCPClient":
72
+ from .mcp.mcp_client import FlockMCPClient
73
+
74
+ return FlockMCPClient
75
+ if name == "FlockMCPClientManager":
76
+ from .mcp.mcp_client_manager import FlockMCPClientManager
77
+
78
+ return FlockMCPClientManager
79
+ if name == "FlockMCPServer":
80
+ from .mcp.flock_mcp_server import FlockMCPServer
81
+
82
+ return FlockMCPServer
83
+ if name == "FlockMCPTool":
84
+ from .mcp.flock_mcp_tool import FlockMCPTool
85
+
86
+ return FlockMCPTool
87
+ if name in {"FlockRegistry", "flock_callable", "flock_component", "flock_tool", "flock_type", "get_registry"}:
88
+ from .registry import (
89
+ RegistryHub as FlockRegistry,
90
+ flock_callable,
91
+ flock_component,
92
+ flock_tool,
93
+ flock_type,
94
+ get_registry,
95
+ )
96
+
97
+ return {
98
+ "FlockRegistry": FlockRegistry,
99
+ "flock_callable": flock_callable,
100
+ "flock_component": flock_component,
101
+ "flock_tool": flock_tool,
102
+ "flock_type": flock_type,
103
+ "get_registry": get_registry,
104
+ }[name]
105
+ raise AttributeError(name)
flock/core/flock.py CHANGED
@@ -19,8 +19,14 @@ from temporalio import workflow
19
19
 
20
20
  from flock.core.mcp.flock_mcp_server import FlockMCPServer
21
21
 
22
- with workflow.unsafe.imports_passed_through():
23
- from datasets import Dataset # type: ignore
22
+ # Guard datasets import to avoid heavy side effects during tests (pyarrow extensions)
23
+ from typing import Any as _Any
24
+ try:
25
+ with workflow.unsafe.imports_passed_through():
26
+ from datasets import Dataset as _HF_Dataset # type: ignore
27
+ Dataset = _HF_Dataset # type: ignore
28
+ except Exception:
29
+ Dataset = _Any # type: ignore
24
30
 
25
31
  from opentelemetry import trace
26
32
  from pandas import DataFrame # type: ignore
@@ -2,6 +2,7 @@
2
2
 
3
3
  import sys
4
4
 
5
+ import os
5
6
  from opentelemetry import trace
6
7
  from opentelemetry.sdk.resources import Resource
7
8
  from opentelemetry.sdk.trace import TracerProvider
@@ -68,9 +69,31 @@ class TelemetryConfig:
68
69
  self.otlp_protocol = otlp_protocol
69
70
  self.otlp_endpoint = otlp_endpoint
70
71
  self.global_tracer = None
72
+ self._configured: bool = False
73
+
74
+ def _should_setup(self) -> bool:
75
+ # Respect explicit disable flag for tests and minimal setups
76
+ if os.environ.get("FLOCK_DISABLE_TELEMETRY_AUTOSETUP", "").lower() in {"1", "true", "yes", "on"}:
77
+ return False
78
+ try:
79
+ # If a provider is already installed (typically by user/tests), don't override it
80
+ from opentelemetry.sdk.trace import TracerProvider as SDKTracerProvider # type: ignore
81
+
82
+ current = trace.get_tracer_provider()
83
+ if isinstance(current, SDKTracerProvider):
84
+ return False
85
+ except Exception:
86
+ # If SDK isn't available or introspection fails, fall back to enabling
87
+ pass
88
+ return True
71
89
 
72
90
  def setup_tracing(self):
73
91
  """Set up OpenTelemetry tracing with the specified exporters."""
92
+ if self._configured:
93
+ return
94
+ if not self._should_setup():
95
+ return
96
+
74
97
  # Create a Resource with the service name.
75
98
  resource = Resource(attributes={"service.name": self.service_name})
76
99
  provider = TracerProvider(resource=resource)
@@ -150,8 +173,9 @@ class TelemetryConfig:
150
173
  provider.add_span_processor(
151
174
  BaggageAttributeSpanProcessor(baggage_keys=["session_id", "run_id"])
152
175
  )
153
- # self.global_tracer = trace.get_tracer("flock")
176
+ self.global_tracer = trace.get_tracer("flock")
154
177
  sys.excepthook = self.log_exception_to_otel
178
+ self._configured = True
155
179
 
156
180
  def log_exception_to_otel(self, exc_type, exc_value, exc_traceback):
157
181
  """Log unhandled exceptions to OpenTelemetry."""
@@ -1,16 +1,13 @@
1
1
  # src/flock/core/orchestration/__init__.py
2
- """Orchestration components for Flock."""
2
+ """Orchestration package public API.
3
3
 
4
- from .flock_batch_processor import FlockBatchProcessor
5
- from .flock_evaluator import FlockEvaluator
6
- from .flock_execution import FlockExecution
7
- from .flock_initialization import FlockInitialization
8
- from .flock_server_manager import FlockServerManager
9
- from .flock_web_server import FlockWebServer
4
+ Avoid importing submodules at package import time to prevent heavy side effects
5
+ and keep tests fast and deterministic. Import modules directly where needed.
6
+ """
10
7
 
11
8
  __all__ = [
12
9
  "FlockExecution",
13
- "FlockServerManager",
10
+ "FlockServerManager",
14
11
  "FlockBatchProcessor",
15
12
  "FlockEvaluator",
16
13
  "FlockWebServer",
flock/di.py CHANGED
@@ -1,30 +1,16 @@
1
- from __future__ import annotations
1
+ """Flock - Dependency-Injection helpers.
2
2
 
3
- """Flock Dependency-Injection helpers.
4
-
5
- This module provides a very small façade over the `wd.di` container so that
6
- other parts of the codebase do not need to know where the active container is
7
- stored. The bootstrap code – usually located in the runner initialisation –
8
- should store the `ServiceProvider` instance (returned by ``ServiceCollection.
9
- build()``) on the `FlockContext` under the key ``di.container``.
10
-
11
- Example
12
- -------
13
- >>> from wd.di import ServiceCollection
14
- >>> sc = ServiceCollection()
15
- >>> sc.add_singleton(str, lambda _: "hello")
16
- >>> container = sc.build()
17
- >>> ctx = FlockContext()
18
- >>> ctx.set_variable("di.container", container)
19
- >>> from flock.di import get_current_container
20
- >>> assert get_current_container(ctx).get_service(str) == "hello"
3
+ This module provides a small facade over `wd.di` so other parts of the
4
+ codebase do not need to know where the active container is stored.
21
5
  """
22
6
 
7
+ from __future__ import annotations
8
+
23
9
  from typing import TYPE_CHECKING
24
10
 
25
11
  if TYPE_CHECKING: # pragma: no cover
26
12
  from wd.di.container import (
27
- ServiceProvider, # noqa: F401 import only for typing
13
+ ServiceProvider, # noqa: F401 - import only for typing
28
14
  )
29
15
 
30
16
  from flock.core.context.context import FlockContext
flock/webapp/app/main.py CHANGED
@@ -986,12 +986,18 @@ async def htmx_theme_preview(request: Request, theme: str = Query(None)):
986
986
  theme_path_candidate = resolved_themes_dir / theme_filename_to_load
987
987
  resolved_theme_path = theme_path_candidate.resolve()
988
988
 
989
- if not str(resolved_theme_path).startswith(str(resolved_themes_dir)) or \
990
- resolved_theme_path.name != theme_filename_to_load:
989
+ try:
990
+ resolved_theme_path.relative_to(resolved_themes_dir)
991
+ except ValueError:
991
992
  logger.warning(f"Invalid theme path access attempt for '{theme_name_for_display}'. "
992
993
  f"Original input: '{chosen_theme_name_input}', Sanitized filename: '{theme_filename_to_load}', "
993
994
  f"Attempted path: '{theme_path_candidate}', Resolved to: '{resolved_theme_path}'")
994
995
  return HTMLResponse(f"<p>Invalid theme name or path for '{theme_name_for_display}'.</p>", status_code=400)
996
+ if resolved_theme_path.name != theme_filename_to_load:
997
+ logger.warning(f"Invalid theme filename for '{theme_name_for_display}'. "
998
+ f"Original input: '{chosen_theme_name_input}', Sanitized filename: '{theme_filename_to_load}', "
999
+ f"Attempted path: '{theme_path_candidate}', Resolved to: '{resolved_theme_path}'")
1000
+ return HTMLResponse(f"<p>Invalid theme name or path for '{theme_name_for_display}'.</p>", status_code=400)
995
1001
 
996
1002
  if not resolved_theme_path.is_file():
997
1003
  logger.info(f"Theme preview: Theme file '{theme_filename_to_load}' not found at '{resolved_theme_path}'.")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flock-core
3
- Version: 0.5.0b14
3
+ Version: 0.5.0b15
4
4
  Summary: Declarative LLM Orchestration at Scale
5
5
  Author-email: Andre Ratzenberger <andre.ratzenberger@whiteduck.de>
6
6
  License-File: LICENSE
@@ -1,6 +1,6 @@
1
- flock/__init__.py,sha256=jg2kcXIi1isxTtYdoQGgk0NYSA-BC0J6Xqy41viWpFg,7834
2
- flock/config.py,sha256=FJZaxSXYdIqCDyyTMAsXk4Ks1fwZywzBjh_XEg3zeOU,1930
3
- flock/di.py,sha256=47taQXcE2RSZ4yhqhQizJdPCdRcy4OvseuH9siVTx54,1384
1
+ flock/__init__.py,sha256=aL5j5sn-hEvaETQooVkCPJyqKagIlOAaKZWV5xmjLQk,7862
2
+ flock/config.py,sha256=Y_QaPGG2KQBAJMYJw4P5Qd21e3jPkpal-OTgOgJOtHk,2052
3
+ flock/di.py,sha256=MX6I0IvAzq0-Jsbk-n_Pt3ZOAsmggUp6ctehepj9ZpY,795
4
4
  flock/adapter/__init__.py,sha256=TAHmnom6H2pbv-A0DbhqOSqnBi_egR8WvFGxfOlDPOM,345
5
5
  flock/adapter/azure_adapter.py,sha256=DuBlRHv-sACOZmbRaueR4edpJj6HvtKb6AhPgosEpnw,2092
6
6
  flock/adapter/chroma_adapter.py,sha256=4cFa0Cv3liT_tGYZpeioHN5CqfrJjzXPjEhICYt8So8,2269
@@ -36,8 +36,8 @@ flock/components/utility/__init__.py,sha256=JRj932upddjzZMWs1avOupEFr_GZNu21ac66
36
36
  flock/components/utility/memory_utility_component.py,sha256=4Vpt6_McEPpN5lNTcXmj7JeZTBOT6rHI0uQE2Qy-3Gc,20103
37
37
  flock/components/utility/metrics_utility_component.py,sha256=u3Bys0dP7FmTeyZOi4XdMhZHCRYc5miXXJ690-qS1Us,24440
38
38
  flock/components/utility/output_utility_component.py,sha256=c4K_PL3bGqdyy_v6dnOrmTqV-MkWKAB2w0HS8kzg82k,7613
39
- flock/core/__init__.py,sha256=ntCQ_wlgvRVNFph3drbFvyaqgtN30487V18YoJzcIFE,1332
40
- flock/core/flock.py,sha256=dN-asYsN2QOolZtYM5U8bRWEWkGckKRyhyy2n1xQ9b8,23148
39
+ flock/core/__init__.py,sha256=CdHczlgrUYEJlKvErX3JbC9i7FAVX-SdwET4NEDfOfQ,3097
40
+ flock/core/flock.py,sha256=wRycQlGeaq-Vd75mFpPe02qyWTOEyXthT873iBhA3TI,23388
41
41
  flock/core/flock_agent.py,sha256=5n4Khlyc-xRaV65JFnCavNXeUCXMuL3PNS9T1tsTl7U,12023
42
42
  flock/core/flock_factory.py,sha256=-a4buSge2cdp1FwTjer283wbamSEyLeUQs_-MeM-S2Y,20049
43
43
  flock/core/flock_scheduler.py,sha256=ng_s7gyijmc-AmYvBn5rtg61CSUZiIkXPRSlA1xO6VQ,8766
@@ -75,7 +75,7 @@ flock/core/execution/temporal_executor.py,sha256=dHcb0xuzPFWU_wbwTgI7glLNyyppei9
75
75
  flock/core/interpreter/python_interpreter.py,sha256=4-wRsxC6-gToEdRr_pp-n2idWwe_Y2zN0o3TbzUPhy0,26632
76
76
  flock/core/logging/__init__.py,sha256=xn5fC-8IgsdIv0ywe_cICK1KVhTrVD8t-jYORg0ETUA,155
77
77
  flock/core/logging/logging.py,sha256=y-V4XPxiwtWCjiAN_YoIRAUP1ialMSH_kT_TYircGjQ,19870
78
- flock/core/logging/telemetry.py,sha256=Trssqx02SBovTL843YwY3L-ZGj3KvcfMHLMU7Syk8L0,6561
78
+ flock/core/logging/telemetry.py,sha256=5hz48PClJgB4l2eatS5eNR9Qswv3wYVVfl5ZWeJWm3E,7471
79
79
  flock/core/logging/trace_and_logged.py,sha256=5vNrK1kxuPMoPJ0-QjQg-EDJL1oiEzvU6UNi6X8FiMs,2117
80
80
  flock/core/logging/formatters/enum_builder.py,sha256=LgEYXUv84wK5vwHflZ5h8HBGgvLH3sByvUQe8tZiyY0,981
81
81
  flock/core/logging/formatters/theme_builder.py,sha256=Wnaal3HuUDA4HFg9tdql1BxYwK83ACOZBBQy-DXnxcA,17342
@@ -100,7 +100,7 @@ flock/core/mcp/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSu
100
100
  flock/core/mcp/util/helpers.py,sha256=Xlf4iKW_lZxsVMTRoOnV29JsJfAppfmEJrb6sIcoCH4,636
101
101
  flock/core/mixin/dspy_integration.py,sha256=jS_hJvDK3YReyI5Y9tmNQQrVdW1t1zFtnDqjRVQovPo,17720
102
102
  flock/core/mixin/prompt_parser.py,sha256=eOqI-FK3y17gVqpc_y5GF-WmK1Jv8mFlkZxTcgweoxI,5121
103
- flock/core/orchestration/__init__.py,sha256=lu6VgCpza0c34lDVhTdtFBY9gCuXx-sdadGqxLlfHuQ,543
103
+ flock/core/orchestration/__init__.py,sha256=zS3gvSeuAxhmXER7uCKjZuKl_FIJm8F_onGCAy_8elw,403
104
104
  flock/core/orchestration/flock_batch_processor.py,sha256=2vqSOHd-Zk871UTai3jGXvITgcwSowaCNjvDkSWbkLg,3357
105
105
  flock/core/orchestration/flock_evaluator.py,sha256=_Ctub0P5VOnePpaPQgb7Qw-gvJerns8uO8u2QVOyGYA,4082
106
106
  flock/core/orchestration/flock_execution.py,sha256=NNzihOCdHfSp1XWQa_yMKbrO4ah58Sk2c7TQviakdYg,11416
@@ -482,7 +482,7 @@ flock/webapp/app/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,
482
482
  flock/webapp/app/chat.py,sha256=SH5yUJKRysuK_v8VlYGsfBymPSIHKcBWsJUCL_O49Ck,30748
483
483
  flock/webapp/app/config.py,sha256=lqmneujnNZk-EFJV5cWpvxkqisxH3T3zT_YOI0JYThE,4809
484
484
  flock/webapp/app/dependencies.py,sha256=JUcwY1N6SZplU141lMN2wk9dOC9er5HCedrKTJN9wJk,5533
485
- flock/webapp/app/main.py,sha256=GSCx_trZGSma11BiDCLrdm_zU1VIsIUDbOZuQD1wbMk,58671
485
+ flock/webapp/app/main.py,sha256=egLW53e-qCdI5WaYS_R5yCkO3NAAQ4UsWhNoySmiJf4,59133
486
486
  flock/webapp/app/middleware.py,sha256=5gkM-gqD7C6-JrsoTB1_UWpf05JI1N8KIWajn60QZk0,5721
487
487
  flock/webapp/app/models_ui.py,sha256=vrEBLbhEp6FziAgBSFOLT1M7ckwadsTdT7qus5_NduE,329
488
488
  flock/webapp/app/theme_mapper.py,sha256=QzWwLWpED78oYp3FjZ9zxv1KxCyj43m8MZ0fhfzz37w,34302
@@ -550,8 +550,8 @@ flock/workflow/agent_execution_activity.py,sha256=CzTkbjGqrPoAbldaQOS_doesosDK9m
550
550
  flock/workflow/flock_workflow.py,sha256=ZhAF82ewNRY2vvDjNpXT1D9lCVQsLOSMTaZVzdcogJc,9674
551
551
  flock/workflow/temporal_config.py,sha256=3_8O7SDEjMsSMXsWJBfnb6XTp0TFaz39uyzSlMTSF_I,3988
552
552
  flock/workflow/temporal_setup.py,sha256=YIHnSBntzOchHfMSh8hoLeNXrz3B1UbR14YrR6soM7A,1606
553
- flock_core-0.5.0b14.dist-info/METADATA,sha256=lgPu-j6u9envD7uigX2Yr1Ukw3LbqTod4NmHx5l3t0o,10026
554
- flock_core-0.5.0b14.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
555
- flock_core-0.5.0b14.dist-info/entry_points.txt,sha256=rWaS5KSpkTmWySURGFZk6PhbJ87TmvcFQDi2uzjlagQ,37
556
- flock_core-0.5.0b14.dist-info/licenses/LICENSE,sha256=iYEqWy0wjULzM9GAERaybP4LBiPeu7Z1NEliLUdJKSc,1072
557
- flock_core-0.5.0b14.dist-info/RECORD,,
553
+ flock_core-0.5.0b15.dist-info/METADATA,sha256=4gCI7ya_Gy5QeHKEDArbDyYDFLV2ksmJztbHR7C_q7g,10026
554
+ flock_core-0.5.0b15.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
555
+ flock_core-0.5.0b15.dist-info/entry_points.txt,sha256=rWaS5KSpkTmWySURGFZk6PhbJ87TmvcFQDi2uzjlagQ,37
556
+ flock_core-0.5.0b15.dist-info/licenses/LICENSE,sha256=iYEqWy0wjULzM9GAERaybP4LBiPeu7Z1NEliLUdJKSc,1072
557
+ flock_core-0.5.0b15.dist-info/RECORD,,