penguiflow 1.0.0__py3-none-any.whl → 1.0.2__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 penguiflow might be problematic. Click here for more details.

penguiflow/__init__.py CHANGED
@@ -40,4 +40,4 @@ __all__ = [
40
40
  "create",
41
41
  ]
42
42
 
43
- __version__ = "1.0.0"
43
+ __version__ = "1.0.2"
penguiflow/core.py CHANGED
@@ -288,6 +288,8 @@ class PenguiFlow:
288
288
  raise RuntimeError("PenguiFlow already running")
289
289
  self._running = True
290
290
  self._registry = registry
291
+ if registry is not None:
292
+ self._ensure_registry_covers_nodes(registry)
291
293
  loop = asyncio.get_running_loop()
292
294
 
293
295
  for node in self._nodes:
@@ -542,6 +544,26 @@ class PenguiFlow:
542
544
  },
543
545
  )
544
546
 
547
+ def _ensure_registry_covers_nodes(self, registry: ModelRegistry) -> None:
548
+ missing: list[str] = []
549
+ for node in self._nodes:
550
+ if node.policy.validate == "none":
551
+ continue
552
+ node_name = node.name
553
+ if node_name is None:
554
+ continue
555
+ try:
556
+ registry.adapters(node_name)
557
+ except KeyError:
558
+ missing.append(node_name)
559
+
560
+ if missing:
561
+ formatted = ", ".join(sorted(missing))
562
+ raise RuntimeError(
563
+ "ModelRegistry is missing entries for nodes requiring validation: "
564
+ f"{formatted}"
565
+ )
566
+
545
567
 
546
568
  PlaybookFactory = Callable[[], tuple["PenguiFlow", ModelRegistry | None]]
547
569
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: penguiflow
3
- Version: 1.0.0
3
+ Version: 1.0.2
4
4
  Summary: Async agent orchestration primitives.
5
5
  Author: PenguiFlow Team
6
6
  License: MIT License
@@ -147,11 +147,13 @@ await flow.stop()
147
147
  * Flows are orchestrators, mostly I/O-bound.
148
148
  * Async tasks are cheap, predictable, and cancellable.
149
149
  * Heavy CPU work should be offloaded inside a node (process pool, Ray, etc.), not in PenguiFlow itself.
150
+ * v1 intentionally stays in-process; scaling out or persisting state will arrive with future pluggable backends.
150
151
 
151
152
  2. **Typed contracts.**
152
153
 
153
154
  * In/out models per node are defined with Pydantic.
154
155
  * Validated at runtime via cached `TypeAdapter`s.
156
+ * `flow.run(registry=...)` verifies every validating node is registered so misconfigurations fail fast.
155
157
 
156
158
  3. **Reliability first.**
157
159
 
@@ -331,6 +333,16 @@ flow focused on high-level orchestration logic.
331
333
  * **NodePolicy**: set validation scope plus per-node timeout, retries, and backoff curves.
332
334
  * **Structured logs**: enrich every node event with `{ts, trace_id, node_name, event, latency_ms, q_depth_in, attempt}`.
333
335
  * **Middleware hooks**: subscribe observers (e.g., MLflow) to the structured event stream.
336
+ * See `examples/reliability_middleware/` for a concrete timeout + retry walkthrough.
337
+
338
+ ---
339
+
340
+ ## ⚠️ Current Constraints
341
+
342
+ - **In-process runtime**: there is no built-in distribution layer yet. Long-running CPU work should be delegated to your own pools or services.
343
+ - **Registry-driven typing**: nodes default to validation. Provide a `ModelRegistry` when calling `flow.run(...)` or set `validate="none"` explicitly for untyped hops.
344
+ - **Observability**: structured logs + middleware hooks are available, but integrations with third-party stacks (OTel, Prometheus) are DIY for now.
345
+ - **Roadmap**: v2 targets streaming, distributed backends, richer observability, and test harnesses. Contributions and proposals are welcome!
334
346
 
335
347
  ---
336
348
 
@@ -1,13 +1,13 @@
1
- penguiflow/__init__.py,sha256=wT0yYO6DsV4x1uLwSXbhcXPP3g9YI9x3mcUWxhX5kis,874
2
- penguiflow/core.py,sha256=ljXFsmVtWj2UTCxWNok-ZRGrPho0wJN3OWP5IgnfhDU,20143
1
+ penguiflow/__init__.py,sha256=BIBAYJZtOHQ7AZMBWD0g7d1RTCR9qWLQGwcUuKa5GMo,874
2
+ penguiflow/core.py,sha256=fO5GXF7Hih-gEcUPbyXVJilgUmwbvd72j337r5oOWME,20908
3
3
  penguiflow/middlewares.py,sha256=LUlK4FrMScK3oaNSrAYNw3s4KcAZ716DTLAUqvsOkL8,319
4
4
  penguiflow/node.py,sha256=0NOs3rU6t1tHNNwwJopqzM2ufGcp82JpzhckynWBRqs,3563
5
5
  penguiflow/patterns.py,sha256=Ivuuy0on0OMsdYd5DRFZm1EgujXKPEaIIMH0ZWlJ1s0,4199
6
6
  penguiflow/registry.py,sha256=4lrGDMFjM7c8pfZFc_YG0YHg-F80JyF4c-j0UbAf150,1419
7
7
  penguiflow/types.py,sha256=QV2JvB_QnohfBATSaviPWm0HSR9B6dTc3UOwFIYyaqg,1154
8
8
  penguiflow/viz.py,sha256=_puIEJevq2DrfNuydm3DG1V1o4PgICxd5pA-Es_IyWY,112
9
- penguiflow-1.0.0.dist-info/licenses/LICENSE,sha256=JSvodvLXxSct_kI9IBsZOBpVKoESQTB_AGbkClwZ7HI,1065
10
- penguiflow-1.0.0.dist-info/METADATA,sha256=MhOA10s6CxVM1UbbKPMEkA9FKS-DJMLU7MEYG748g1U,12143
11
- penguiflow-1.0.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
12
- penguiflow-1.0.0.dist-info/top_level.txt,sha256=F-5jgzPP4Mo_ErgtzGDFJdRT4CIfFjFBnxxcn-RpWBU,11
13
- penguiflow-1.0.0.dist-info/RECORD,,
9
+ penguiflow-1.0.2.dist-info/licenses/LICENSE,sha256=JSvodvLXxSct_kI9IBsZOBpVKoESQTB_AGbkClwZ7HI,1065
10
+ penguiflow-1.0.2.dist-info/METADATA,sha256=SBuhdqSVKIwo9_vVV2bW2IsmGiia84q59ESqHl8zgR0,13090
11
+ penguiflow-1.0.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
12
+ penguiflow-1.0.2.dist-info/top_level.txt,sha256=F-5jgzPP4Mo_ErgtzGDFJdRT4CIfFjFBnxxcn-RpWBU,11
13
+ penguiflow-1.0.2.dist-info/RECORD,,