puffinflow 2.dev0__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.
Files changed (55) hide show
  1. puffinflow/__init__.py +132 -0
  2. puffinflow/core/__init__.py +110 -0
  3. puffinflow/core/agent/__init__.py +320 -0
  4. puffinflow/core/agent/base.py +1635 -0
  5. puffinflow/core/agent/checkpoint.py +50 -0
  6. puffinflow/core/agent/context.py +521 -0
  7. puffinflow/core/agent/decorators/__init__.py +90 -0
  8. puffinflow/core/agent/decorators/builder.py +454 -0
  9. puffinflow/core/agent/decorators/flexible.py +714 -0
  10. puffinflow/core/agent/decorators/inspection.py +144 -0
  11. puffinflow/core/agent/dependencies.py +57 -0
  12. puffinflow/core/agent/scheduling/__init__.py +21 -0
  13. puffinflow/core/agent/scheduling/builder.py +160 -0
  14. puffinflow/core/agent/scheduling/exceptions.py +35 -0
  15. puffinflow/core/agent/scheduling/inputs.py +137 -0
  16. puffinflow/core/agent/scheduling/parser.py +209 -0
  17. puffinflow/core/agent/scheduling/scheduler.py +413 -0
  18. puffinflow/core/agent/state.py +141 -0
  19. puffinflow/core/config.py +62 -0
  20. puffinflow/core/coordination/__init__.py +137 -0
  21. puffinflow/core/coordination/agent_group.py +359 -0
  22. puffinflow/core/coordination/agent_pool.py +629 -0
  23. puffinflow/core/coordination/agent_team.py +577 -0
  24. puffinflow/core/coordination/coordinator.py +720 -0
  25. puffinflow/core/coordination/deadlock.py +1759 -0
  26. puffinflow/core/coordination/fluent_api.py +421 -0
  27. puffinflow/core/coordination/primitives.py +478 -0
  28. puffinflow/core/coordination/rate_limiter.py +520 -0
  29. puffinflow/core/observability/__init__.py +47 -0
  30. puffinflow/core/observability/agent.py +139 -0
  31. puffinflow/core/observability/alerting.py +73 -0
  32. puffinflow/core/observability/config.py +127 -0
  33. puffinflow/core/observability/context.py +88 -0
  34. puffinflow/core/observability/core.py +147 -0
  35. puffinflow/core/observability/decorators.py +105 -0
  36. puffinflow/core/observability/events.py +71 -0
  37. puffinflow/core/observability/interfaces.py +196 -0
  38. puffinflow/core/observability/metrics.py +137 -0
  39. puffinflow/core/observability/tracing.py +209 -0
  40. puffinflow/core/reliability/__init__.py +27 -0
  41. puffinflow/core/reliability/bulkhead.py +96 -0
  42. puffinflow/core/reliability/circuit_breaker.py +149 -0
  43. puffinflow/core/reliability/leak_detector.py +122 -0
  44. puffinflow/core/resources/__init__.py +77 -0
  45. puffinflow/core/resources/allocation.py +790 -0
  46. puffinflow/core/resources/pool.py +645 -0
  47. puffinflow/core/resources/quotas.py +567 -0
  48. puffinflow/core/resources/requirements.py +217 -0
  49. puffinflow/version.py +21 -0
  50. puffinflow-2.dev0.dist-info/METADATA +334 -0
  51. puffinflow-2.dev0.dist-info/RECORD +55 -0
  52. puffinflow-2.dev0.dist-info/WHEEL +5 -0
  53. puffinflow-2.dev0.dist-info/entry_points.txt +3 -0
  54. puffinflow-2.dev0.dist-info/licenses/LICENSE +21 -0
  55. puffinflow-2.dev0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,454 @@
1
+ """
2
+ Builder pattern for constructing state configurations.
3
+ """
4
+
5
+ from typing import Any, Callable, Optional, Union
6
+
7
+ from ..state import Priority
8
+
9
+
10
+ class StateBuilder:
11
+ """Builder pattern for constructing state configurations."""
12
+
13
+ def __init__(self) -> None:
14
+ self._config: dict[str, Any] = {}
15
+
16
+ # Resource methods
17
+ def cpu(self, units: float) -> "StateBuilder":
18
+ """Set CPU units."""
19
+ self._config["cpu"] = units
20
+ return self
21
+
22
+ def memory(self, mb: float) -> "StateBuilder":
23
+ """Set memory in MB."""
24
+ self._config["memory"] = mb
25
+ return self
26
+
27
+ def gpu(self, units: float) -> "StateBuilder":
28
+ """Set GPU units."""
29
+ self._config["gpu"] = units
30
+ return self
31
+
32
+ def io(self, weight: float) -> "StateBuilder":
33
+ """Set I/O weight."""
34
+ self._config["io"] = weight
35
+ return self
36
+
37
+ def network(self, weight: float) -> "StateBuilder":
38
+ """Set network weight."""
39
+ self._config["network"] = weight
40
+ return self
41
+
42
+ def resources(
43
+ self,
44
+ cpu: Optional[float] = None,
45
+ memory: Optional[float] = None,
46
+ gpu: Optional[float] = None,
47
+ io: Optional[float] = None,
48
+ network: Optional[float] = None,
49
+ ) -> "StateBuilder":
50
+ """Set multiple resources at once."""
51
+ if cpu is not None:
52
+ self._config["cpu"] = cpu
53
+ if memory is not None:
54
+ self._config["memory"] = memory
55
+ if gpu is not None:
56
+ self._config["gpu"] = gpu
57
+ if io is not None:
58
+ self._config["io"] = io
59
+ if network is not None:
60
+ self._config["network"] = network
61
+ return self
62
+
63
+ # Priority and timing
64
+ def priority(self, level: Union[Priority, int, str]) -> "StateBuilder":
65
+ """Set priority level."""
66
+ self._config["priority"] = level
67
+ return self
68
+
69
+ def high_priority(self) -> "StateBuilder":
70
+ """Set high priority."""
71
+ self._config["priority"] = Priority.HIGH
72
+ return self
73
+
74
+ def critical_priority(self) -> "StateBuilder":
75
+ """Set critical priority."""
76
+ self._config["priority"] = Priority.CRITICAL
77
+ return self
78
+
79
+ def low_priority(self) -> "StateBuilder":
80
+ """Set low priority."""
81
+ self._config["priority"] = Priority.LOW
82
+ return self
83
+
84
+ def timeout(self, seconds: float) -> "StateBuilder":
85
+ """Set execution timeout."""
86
+ self._config["timeout"] = seconds
87
+ return self
88
+
89
+ # Rate limiting
90
+ def rate_limit(self, rate: float, burst: Optional[int] = None) -> "StateBuilder":
91
+ """Set rate limiting."""
92
+ self._config["rate_limit"] = rate
93
+ if burst:
94
+ self._config["burst_limit"] = burst
95
+ return self
96
+
97
+ def throttle(self, rate: float) -> "StateBuilder":
98
+ """Alias for rate_limit."""
99
+ return self.rate_limit(rate)
100
+
101
+ # Coordination
102
+ def mutex(self) -> "StateBuilder":
103
+ """Enable mutual exclusion."""
104
+ self._config["mutex"] = True
105
+ return self
106
+
107
+ def exclusive(self) -> "StateBuilder":
108
+ """Alias for mutex."""
109
+ return self.mutex()
110
+
111
+ def semaphore(self, count: int) -> "StateBuilder":
112
+ """Enable semaphore with count."""
113
+ self._config["semaphore"] = count
114
+ return self
115
+
116
+ def concurrent(self, max_concurrent: int) -> "StateBuilder":
117
+ """Alias for semaphore."""
118
+ return self.semaphore(max_concurrent)
119
+
120
+ def barrier(self, parties: int) -> "StateBuilder":
121
+ """Enable barrier synchronization."""
122
+ self._config["barrier"] = parties
123
+ return self
124
+
125
+ def synchronized(self, parties: int) -> "StateBuilder":
126
+ """Alias for barrier."""
127
+ return self.barrier(parties)
128
+
129
+ def lease(self, duration: float) -> "StateBuilder":
130
+ """Enable time-based lease."""
131
+ self._config["lease"] = duration
132
+ return self
133
+
134
+ def quota(self, limit: float) -> "StateBuilder":
135
+ """Enable quota management."""
136
+ self._config["quota"] = limit
137
+ return self
138
+
139
+ # Dependencies
140
+ def depends_on(self, *states: str) -> "StateBuilder":
141
+ """Set state dependencies."""
142
+ self._config["depends_on"] = list(states)
143
+ return self
144
+
145
+ def after(self, *states: str) -> "StateBuilder":
146
+ """Alias for depends_on."""
147
+ return self.depends_on(*states)
148
+
149
+ # Retry configuration
150
+ def retry(
151
+ self,
152
+ max_retries: int,
153
+ initial_delay: float = 1.0,
154
+ exponential_base: float = 2.0,
155
+ jitter: bool = True,
156
+ dead_letter: bool = True,
157
+ circuit_breaker: bool = False,
158
+ ) -> "StateBuilder":
159
+ """Set retry configuration with dead letter options and circuit breaker integration"""
160
+ self._config["retry_config"] = {
161
+ "max_retries": max_retries,
162
+ "initial_delay": initial_delay,
163
+ "exponential_base": exponential_base,
164
+ "jitter": jitter,
165
+ "dead_letter_on_max_retries": dead_letter,
166
+ "dead_letter_on_timeout": dead_letter,
167
+ }
168
+
169
+ # Enable circuit breaker if requested for retry scenarios
170
+ if circuit_breaker:
171
+ self._config["circuit_breaker"] = True
172
+
173
+ return self
174
+
175
+ def retries(self, count: int) -> "StateBuilder":
176
+ """Set simple retry count."""
177
+ self._config["max_retries"] = count
178
+ return self
179
+
180
+ def no_retry(self) -> "StateBuilder":
181
+ """Disable retries."""
182
+ self._config["max_retries"] = 0
183
+ return self
184
+
185
+ # Dead letter configuration
186
+ def enable_dead_letter(self) -> "StateBuilder":
187
+ """Enable dead letter queue on failure"""
188
+ self._config["dead_letter"] = True
189
+ return self
190
+
191
+ def disable_dead_letter(self) -> "StateBuilder":
192
+ """Disable dead letter queue - fail permanently instead"""
193
+ self._config["no_dead_letter"] = True
194
+ return self
195
+
196
+ def no_dlq(self) -> "StateBuilder":
197
+ """Alias for disable_dead_letter"""
198
+ return self.disable_dead_letter()
199
+
200
+ def with_dead_letter(self, enabled: bool = True) -> "StateBuilder":
201
+ """Configure dead letter behavior"""
202
+ self._config["dead_letter"] = enabled
203
+ return self
204
+
205
+ # NEW: Circuit Breaker methods
206
+ def circuit_breaker(
207
+ self,
208
+ enabled: bool = True,
209
+ failure_threshold: int = 5,
210
+ recovery_timeout: float = 60.0,
211
+ success_threshold: int = 3,
212
+ ) -> "StateBuilder":
213
+ """Enable circuit breaker with configuration"""
214
+ self._config["circuit_breaker"] = enabled
215
+ if enabled:
216
+ self._config["circuit_breaker_config"] = {
217
+ "failure_threshold": failure_threshold,
218
+ "recovery_timeout": recovery_timeout,
219
+ "success_threshold": success_threshold,
220
+ }
221
+ return self
222
+
223
+ def with_circuit_breaker(self, **config: Any) -> "StateBuilder":
224
+ """Enable circuit breaker with custom configuration"""
225
+ self._config["circuit_breaker"] = True
226
+ self._config["circuit_breaker_config"] = config
227
+ return self
228
+
229
+ def protected(
230
+ self, failure_threshold: int = 3, recovery_timeout: float = 30.0
231
+ ) -> "StateBuilder":
232
+ """Enable circuit breaker with sensible defaults for protection"""
233
+ return self.circuit_breaker(True, failure_threshold, recovery_timeout)
234
+
235
+ def fragile(
236
+ self, failure_threshold: int = 2, recovery_timeout: float = 120.0
237
+ ) -> "StateBuilder":
238
+ """Enable circuit breaker for fragile operations (low threshold, long recovery)"""
239
+ return self.circuit_breaker(True, failure_threshold, recovery_timeout)
240
+
241
+ # NEW: Bulkhead methods
242
+ def bulkhead(
243
+ self,
244
+ enabled: bool = True,
245
+ max_concurrent: int = 5,
246
+ max_queue_size: int = 100,
247
+ timeout: float = 30.0,
248
+ ) -> "StateBuilder":
249
+ """Enable bulkhead with configuration"""
250
+ self._config["bulkhead"] = enabled
251
+ if enabled:
252
+ self._config["bulkhead_config"] = {
253
+ "max_concurrent": max_concurrent,
254
+ "max_queue_size": max_queue_size,
255
+ "timeout": timeout,
256
+ }
257
+ return self
258
+
259
+ def with_bulkhead(self, **config: Any) -> "StateBuilder":
260
+ """Enable bulkhead with custom configuration"""
261
+ self._config["bulkhead"] = True
262
+ self._config["bulkhead_config"] = config
263
+ return self
264
+
265
+ def isolated(self, max_concurrent: int = 3) -> "StateBuilder":
266
+ """Enable bulkhead with isolation (limited concurrency)"""
267
+ return self.bulkhead(True, max_concurrent)
268
+
269
+ def single_threaded(self) -> "StateBuilder":
270
+ """Enable bulkhead with single thread execution"""
271
+ return self.bulkhead(True, max_concurrent=1)
272
+
273
+ def highly_concurrent(self, max_concurrent: int = 20) -> "StateBuilder":
274
+ """Enable bulkhead allowing high concurrency"""
275
+ return self.bulkhead(True, max_concurrent)
276
+
277
+ # NEW: Leak Detection methods
278
+ def leak_detection(self, enabled: bool = True) -> "StateBuilder":
279
+ """Configure resource leak detection"""
280
+ self._config["leak_detection"] = enabled
281
+ return self
282
+
283
+ def no_leak_detection(self) -> "StateBuilder":
284
+ """Disable resource leak detection"""
285
+ self._config["leak_detection"] = False
286
+ return self
287
+
288
+ # NEW: Combined reliability methods
289
+ def fault_tolerant(
290
+ self,
291
+ circuit_breaker: bool = True,
292
+ bulkhead: bool = True,
293
+ max_concurrent: int = 3,
294
+ failure_threshold: int = 3,
295
+ ) -> "StateBuilder":
296
+ """Enable comprehensive fault tolerance"""
297
+ if circuit_breaker:
298
+ self.circuit_breaker(True, failure_threshold)
299
+ if bulkhead:
300
+ self.bulkhead(True, max_concurrent)
301
+ return self.retry(5, dead_letter=True, circuit_breaker=circuit_breaker)
302
+
303
+ def production_ready(self) -> "StateBuilder":
304
+ """Apply production-ready reliability patterns"""
305
+ return (
306
+ self.circuit_breaker(True, failure_threshold=5, recovery_timeout=60.0)
307
+ .bulkhead(True, max_concurrent=5)
308
+ .retry(3, dead_letter=True)
309
+ .leak_detection(True)
310
+ )
311
+
312
+ def external_call(self, timeout: float = 30.0) -> "StateBuilder":
313
+ """Configure for external service calls"""
314
+ return (
315
+ self.circuit_breaker(True, failure_threshold=2, recovery_timeout=30.0)
316
+ .bulkhead(True, max_concurrent=10)
317
+ .timeout(timeout)
318
+ .retry(3, dead_letter=True)
319
+ )
320
+
321
+ # Metadata
322
+ def tag(self, key: str, value: Any) -> "StateBuilder":
323
+ """Add a tag."""
324
+ if "tags" not in self._config:
325
+ self._config["tags"] = {}
326
+ self._config["tags"][key] = value
327
+ return self
328
+
329
+ def tags(self, **tags: Any) -> "StateBuilder":
330
+ """Add multiple tags."""
331
+ if "tags" not in self._config:
332
+ self._config["tags"] = {}
333
+ self._config["tags"].update(tags)
334
+ return self
335
+
336
+ def description(self, desc: str) -> "StateBuilder":
337
+ """Set description."""
338
+ self._config["description"] = desc
339
+ return self
340
+
341
+ def describe(self, desc: str) -> "StateBuilder":
342
+ """Alias for description."""
343
+ return self.description(desc)
344
+
345
+ # Profile application
346
+ def profile(self, name: str) -> "StateBuilder":
347
+ """Apply a profile."""
348
+ self._config["profile"] = name
349
+ return self
350
+
351
+ def like(self, name: str) -> "StateBuilder":
352
+ """Alias for profile."""
353
+ return self.profile(name)
354
+
355
+ # Advanced options
356
+ def preemptible(self, value: bool = True) -> "StateBuilder":
357
+ """Set preemptible flag."""
358
+ self._config["preemptible"] = value
359
+ return self
360
+
361
+ def checkpoint_every(self, seconds: float) -> "StateBuilder":
362
+ """Set checkpoint interval."""
363
+ self._config["checkpoint_interval"] = seconds
364
+ return self
365
+
366
+ def cleanup_on_failure(self, value: bool = True) -> "StateBuilder":
367
+ """Set cleanup on failure flag."""
368
+ self._config["cleanup_on_failure"] = value
369
+ return self
370
+
371
+ # Build methods
372
+ def build(self) -> dict[str, Any]:
373
+ """Build and return the configuration dictionary."""
374
+ return self._config.copy()
375
+
376
+ def __call__(self, func: Callable[..., Any]) -> Callable[..., Any]:
377
+ """Use as decorator."""
378
+ from .flexible import state
379
+
380
+ decorator = state(config=self._config)
381
+ return decorator(func) # type: ignore[no-any-return]
382
+
383
+ def decorator(self) -> Callable[..., Any]:
384
+ """Get decorator function."""
385
+ from .flexible import state
386
+
387
+ return state(config=self._config)
388
+
389
+
390
+ def build_state() -> StateBuilder:
391
+ """Create a new state builder."""
392
+ return StateBuilder()
393
+
394
+
395
+ # Convenience builder functions
396
+ def cpu_state(units: float) -> StateBuilder:
397
+ """Start building a CPU-intensive state."""
398
+ return StateBuilder().cpu(units)
399
+
400
+
401
+ def memory_state(mb: float) -> StateBuilder:
402
+ """Start building a memory-intensive state."""
403
+ return StateBuilder().memory(mb)
404
+
405
+
406
+ def gpu_state(units: float) -> StateBuilder:
407
+ """Start building a GPU state."""
408
+ return StateBuilder().gpu(units)
409
+
410
+
411
+ def exclusive_state() -> StateBuilder:
412
+ """Start building an exclusive state."""
413
+ return StateBuilder().mutex()
414
+
415
+
416
+ def concurrent_state(max_concurrent: int) -> StateBuilder:
417
+ """Start building a concurrent state."""
418
+ return StateBuilder().semaphore(max_concurrent)
419
+
420
+
421
+ def high_priority_state() -> StateBuilder:
422
+ """Start building a high priority state."""
423
+ return StateBuilder().high_priority()
424
+
425
+
426
+ def critical_state() -> StateBuilder:
427
+ """Start building a critical state."""
428
+ return StateBuilder().critical_priority()
429
+
430
+
431
+ # NEW: Reliability-focused builders
432
+ def fault_tolerant_state() -> StateBuilder:
433
+ """Start building a fault-tolerant state."""
434
+ return StateBuilder().fault_tolerant()
435
+
436
+
437
+ def external_service_state(timeout: float = 30.0) -> StateBuilder:
438
+ """Start building a state for external service calls."""
439
+ return StateBuilder().external_call(timeout)
440
+
441
+
442
+ def production_state() -> StateBuilder:
443
+ """Start building a production-ready state."""
444
+ return StateBuilder().production_ready()
445
+
446
+
447
+ def protected_state(failure_threshold: int = 3) -> StateBuilder:
448
+ """Start building a circuit breaker protected state."""
449
+ return StateBuilder().protected(failure_threshold)
450
+
451
+
452
+ def isolated_state(max_concurrent: int = 3) -> StateBuilder:
453
+ """Start building an isolated (bulkhead) state."""
454
+ return StateBuilder().isolated(max_concurrent)