avtomatika 1.0b8__py3-none-any.whl → 1.0b10__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.
avtomatika/ws_manager.py CHANGED
@@ -4,15 +4,19 @@ from typing import Any
4
4
 
5
5
  from aiohttp import web
6
6
 
7
+ from .constants import MSG_TYPE_PROGRESS
8
+ from .storage.base import StorageBackend
9
+
7
10
  logger = getLogger(__name__)
8
11
 
9
12
 
10
13
  class WebSocketManager:
11
14
  """Manages active WebSocket connections from workers."""
12
15
 
13
- def __init__(self) -> None:
16
+ def __init__(self, storage: StorageBackend) -> None:
14
17
  self._connections: dict[str, web.WebSocketResponse] = {}
15
18
  self._lock = Lock()
19
+ self.storage = storage
16
20
 
17
21
  async def register(self, worker_id: str, ws: web.WebSocketResponse) -> None:
18
22
  """Registers a new WebSocket connection for a worker."""
@@ -46,17 +50,21 @@ class WebSocketManager:
46
50
  logger.warning(f"Cannot send command: No active WebSocket connection for worker {worker_id}.")
47
51
  return False
48
52
 
49
- @staticmethod
50
- async def handle_message(worker_id: str, message: dict[str, Any]) -> None:
53
+ async def handle_message(self, worker_id: str, message: dict[str, Any]) -> None:
51
54
  """Handles an incoming message from a worker."""
52
55
  event_type = message.get("event")
53
- if event_type == "progress_update":
54
- # In a real application, you'd likely forward this to a history store
55
- # or a pub/sub system for real-time UI updates.
56
+ if event_type == MSG_TYPE_PROGRESS:
57
+ job_id = message.get("job_id")
58
+ progress = message.get("progress", 0)
59
+ msg_text = message.get("message", "")
56
60
  logger.info(
57
- f"Received progress update from worker {worker_id} for job {message.get('job_id')}: "
58
- f"{message.get('progress', 0) * 100:.0f}% - {message.get('message', '')}"
61
+ f"Received progress update from worker {worker_id} for job {job_id}: {progress * 100:.0f}% - {msg_text}"
59
62
  )
63
+ if job_id:
64
+ try:
65
+ await self.storage.update_job_state(job_id, {"progress": progress, "progress_message": msg_text})
66
+ except Exception as e:
67
+ logger.error(f"Failed to update progress for job {job_id}: {e}")
60
68
  else:
61
69
  logger.debug(f"Received unhandled event from worker {worker_id}: {event_type}")
62
70
 
@@ -1,16 +1,21 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: avtomatika
3
- Version: 1.0b8
3
+ Version: 1.0b10
4
4
  Summary: A state-machine based orchestrator for long-running AI and other jobs.
5
+ Author-email: Dmitrii Gagarin <madgagarin@gmail.com>
5
6
  Project-URL: Homepage, https://github.com/avtomatika-ai/avtomatika
6
7
  Project-URL: Bug Tracker, https://github.com/avtomatika-ai/avtomatika/issues
8
+ Keywords: orchestrator,state-machine,workflow,distributed,ai,llm,rxon,hln
7
9
  Classifier: Development Status :: 4 - Beta
10
+ Classifier: Intended Audience :: Developers
8
11
  Classifier: Programming Language :: Python :: 3
9
12
  Classifier: License :: OSI Approved :: MIT License
10
13
  Classifier: Operating System :: OS Independent
14
+ Classifier: Typing :: Typed
11
15
  Requires-Python: >=3.11
12
16
  Description-Content-Type: text/markdown
13
17
  License-File: LICENSE
18
+ Requires-Dist: rxon==1.0b2
14
19
  Requires-Dist: aiohttp~=3.12
15
20
  Requires-Dist: python-json-logger~=4.0
16
21
  Requires-Dist: graphviz~=0.21
@@ -22,7 +27,7 @@ Provides-Extra: redis
22
27
  Requires-Dist: redis~=7.1; extra == "redis"
23
28
  Provides-Extra: s3
24
29
  Requires-Dist: obstore>=0.2; extra == "s3"
25
- Requires-Dist: aiofiles~=23.2; extra == "s3"
30
+ Requires-Dist: aiofiles~=25.1; extra == "s3"
26
31
  Provides-Extra: history
27
32
  Requires-Dist: aiosqlite~=0.22; extra == "history"
28
33
  Requires-Dist: asyncpg~=0.30; extra == "history"
@@ -41,7 +46,7 @@ Requires-Dist: aioresponses~=0.7; extra == "test"
41
46
  Requires-Dist: backports.zstd~=1.2; extra == "test"
42
47
  Requires-Dist: opentelemetry-instrumentation-aiohttp-client; extra == "test"
43
48
  Requires-Dist: obstore>=0.2; extra == "test"
44
- Requires-Dist: aiofiles~=23.2; extra == "test"
49
+ Requires-Dist: aiofiles~=25.1; extra == "test"
45
50
  Provides-Extra: all
46
51
  Requires-Dist: avtomatika[redis]; extra == "all"
47
52
  Requires-Dist: avtomatika[history]; extra == "all"
@@ -51,6 +56,11 @@ Dynamic: license-file
51
56
 
52
57
  # Avtomatika Orchestrator
53
58
 
59
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
60
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/release/python-3110/)
61
+ [![Tests](https://github.com/avtomatika-ai/avtomatika/actions/workflows/ci.yml/badge.svg)](https://github.com/avtomatika-ai/avtomatika/actions/workflows/ci.yml)
62
+ [![Code Style: Ruff](https://img.shields.io/badge/code%20style-ruff-000000.svg)](https://github.com/astral-sh/ruff)
63
+
54
64
  Avtomatika is a powerful, state-driven engine for managing complex asynchronous workflows in Python. It provides a robust framework for building scalable and resilient applications by separating process logic from execution logic.
55
65
 
56
66
  This document serves as a comprehensive guide for developers looking to build pipelines (blueprints) and embed the Orchestrator into their applications.
@@ -88,8 +98,9 @@ The project is based on a simple yet powerful architectural pattern that separat
88
98
 
89
99
  Avtomatika is part of a larger ecosystem:
90
100
 
101
+ * **[Avtomatika Protocol](https://github.com/avtomatika-ai/rxon)**: Shared package containing protocol definitions, data models, and utilities ensuring consistency across all components.
91
102
  * **[Avtomatika Worker SDK](https://github.com/avtomatika-ai/avtomatika-worker)**: The official Python SDK for building workers that connect to this engine.
92
- * **[RCA Protocol](https://github.com/avtomatika-ai/rca)**: The architectural specification and manifesto behind the system.
103
+ * **[HLN Protocol](https://github.com/avtomatika-ai/hln)**: The architectural specification and manifesto behind the system (Hierarchical Logic Network).
93
104
  * **[Full Example](https://github.com/avtomatika-ai/avtomatika-full-example)**: A complete reference project demonstrating the engine and workers in action.
94
105
 
95
106
  ## Installation
@@ -140,7 +151,7 @@ storage = MemoryStorage()
140
151
  config = Config() # Loads configuration from environment variables
141
152
 
142
153
  # Explicitly set tokens for this example
143
- # Client token must be sent in the 'X-Avtomatika-Token' header.
154
+ # Client token must be sent in the 'X-Client-Token' header.
144
155
  config.CLIENT_TOKEN = "my-secret-client-token"
145
156
  # Worker token must be sent in the 'X-Worker-Token' header.
146
157
  config.GLOBAL_WORKER_TOKEN = "my-secret-worker-token"
@@ -268,12 +279,18 @@ async def publish_handler_old_style(context):
268
279
 
269
280
  Avtomatika is engineered for high-load environments with thousands of concurrent workers.
270
281
 
271
- * **O(1) Dispatcher**: Uses advanced Redis Set intersections to find suitable workers instantly, regardless of the cluster size. No O(N) scanning.
282
+ * **O(1) Dispatcher**: Uses advanced Redis Set intersections to find suitable workers instantly.
283
+ * **Zero Trust Security**:
284
+ * **mTLS (Mutual TLS)**: Mutual authentication between Orchestrator and Workers using certificates.
285
+ * **STS (Security Token Service)**: Token rotation mechanism with short-lived access tokens.
286
+ * **Identity Extraction**: Automatically maps Certificate Common Name (CN) to Worker ID.
287
+ * **Data Integrity**:
288
+ * **End-to-End Validation**: Automatic verification of file size and ETag (hash) during S3 transfers.
289
+ * **Audit Trail**: File metadata is logged in history for full traceability.
290
+ * **Protocol Layer**: Built on top of `rxon`, a strict contract defining interactions, ensuring forward compatibility and allowing transport evolution (e.g., to gRPC).
272
291
  * **Non-Blocking I/O**:
273
- * **Webhooks**: Sent via a bounded background queue to prevent backpressure.
274
- * **History Logging**: Writes to SQL databases are buffered and asynchronous, ensuring the main execution loop never blocks.
275
- * **Redis Streams**: Uses blocking reads to eliminate busy-waiting and reduce CPU usage.
276
- * **Memory Safety**: S3 file transfers use streaming to handle multi-gigabyte files with constant, low RAM usage.
292
+ * **Webhooks**: Sent via a bounded background queue.
293
+ * **S3 Streaming**: Constant memory usage regardless of file size.
277
294
 
278
295
  ## Blueprint Cookbook: Key Features
279
296
 
@@ -477,10 +494,16 @@ For detailed specifications and examples, please refer to the [**Configuration G
477
494
 
478
495
  The orchestrator has built-in mechanisms for handling failures based on the `error.code` field in a worker's response.
479
496
 
480
- * **TRANSIENT_ERROR**: A temporary error (e.g., network failure, rate limit). The orchestrator will automatically retry the task several times.
481
- * **PERMANENT_ERROR**: A permanent error (e.g., a corrupted file). The task will be immediately sent to quarantine for manual investigation.
497
+ * **TRANSIENT_ERROR**: A temporary error (e.g., network failure). The orchestrator will automatically retry the task several times.
498
+ * **RESOURCE_EXHAUSTED_ERROR / TIMEOUT_ERROR / INTERNAL_ERROR**: Treated as transient errors and retried.
499
+ * **PERMANENT_ERROR**: A permanent error. The task will be immediately sent to quarantine.
500
+ * **SECURITY_ERROR / DEPENDENCY_ERROR**: Treated as permanent errors (e.g., security violation or missing model). Immediate quarantine.
482
501
  * **INVALID_INPUT_ERROR**: An error in the input data. The entire pipeline (Job) will be immediately moved to the failed state.
483
502
 
503
+ ### Progress Tracking
504
+
505
+ Workers can report real-time execution progress (0-100%) and status messages. This information is automatically persisted by the Orchestrator and exposed via the Job Status API (`GET /api/v1/jobs/{job_id}`).
506
+
484
507
  ### Concurrency & Performance
485
508
 
486
509
  To prevent system overload during high traffic, the Orchestrator implements a backpressure mechanism for its internal job processing logic.
@@ -525,13 +548,18 @@ By default, the engine uses in-memory storage. For production, you must configur
525
548
 
526
549
  The orchestrator uses tokens to authenticate API requests.
527
550
 
528
- * **Client Authentication**: All API clients must provide a token in the `X-Avtomatika-Token` header. The orchestrator validates this token against client configurations.
551
+ * **Client Authentication**: All API clients must provide a token in the `X-Client-Token` header. The orchestrator validates this token against client configurations.
529
552
  * **Worker Authentication**: Workers must provide a token in the `X-Worker-Token` header.
530
553
  * `GLOBAL_WORKER_TOKEN`: You can set a global token for all workers using this environment variable. For development and testing, it defaults to `"secure-worker-token"`.
531
554
  * **Individual Tokens**: For production, it is recommended to define individual tokens for each worker in a separate configuration file and provide its path via the `WORKERS_CONFIG_PATH` environment variable. Tokens from this file are stored in a hashed format for security.
532
555
 
533
556
  > **Note on Dynamic Reloading:** The worker configuration file can be reloaded without restarting the orchestrator by sending an authenticated `POST` request to the `/api/v1/admin/reload-workers` endpoint. This allows for dynamic updates of worker tokens.
534
557
 
558
+ ### Pure Holon Mode
559
+ For high-security environments or when operating as a Compound Holon within an HLN, you can disable the public client API.
560
+ * **Enable/Disable**: Set `ENABLE_CLIENT_API="false"` (default: `true`).
561
+ * **Effect**: The Orchestrator will stop listening on `/api/v1/jobs/...`. It will only accept tasks via the Worker Protocol (RXON) from its parent.
562
+
535
563
  ### Observability
536
564
 
537
565
  When installed with the telemetry dependency, the system automatically provides:
@@ -543,7 +571,11 @@ When installed with the telemetry dependency, the system automatically provides:
543
571
  ### Setup Environment
544
572
 
545
573
  * Clone the repository.
546
- * Install the package in editable mode with all dependencies:
574
+ * **For local development**, install the protocol package first:
575
+ ```bash
576
+ pip install -e ../rxon
577
+ ```
578
+ * Then install the engine in editable mode with all dependencies:
547
579
  ```bash
548
580
  pip install -e ".[all,test]"
549
581
  ```
@@ -561,7 +593,7 @@ When installed with the telemetry dependency, the system automatically provides:
561
593
 
562
594
  To run the `avtomatika` test suite:
563
595
  ```bash
564
- pytest avtomatika/tests/
596
+ pytest tests/
565
597
  ```
566
598
 
567
599
  ### Interactive API Documentation
@@ -0,0 +1,48 @@
1
+ avtomatika/__init__.py,sha256=D5r3L-H06uxsY_wgfh7u9YR29QvZMer1BlvzjW9Umfo,701
2
+ avtomatika/api.html,sha256=6Sj0vwAUZsbLKwlB58ONAttCB52e8h3fidspLOwMMGE,32894
3
+ avtomatika/app_keys.py,sha256=Zd2TaGPduzyEFJgdPvgSH1skdBx2mX-Prj1ma9fAXRo,1275
4
+ avtomatika/blueprint.py,sha256=ZRMis9LOtBwZ9MMHqMF7WAgfMxE0M6-xP5s1IwLgpow,11875
5
+ avtomatika/client_config_loader.py,sha256=zVVHZlxSqZUaNpZ4zoU0T1CFYXdxy-3vKSmPcaFuHSY,2772
6
+ avtomatika/compression.py,sha256=bhA1kw4YrCR3I3kdquZSY0fAzCrRrjtz55uepzLUDKI,2498
7
+ avtomatika/config.py,sha256=27ov8BNbiUpkZ1sjtx3pifRavwcxJ_zUgIdkL_pgqv8,3595
8
+ avtomatika/constants.py,sha256=j9fkZ1NWLTwl5IcmO9VoMf1N2Okqk0wYfyDybfRi-Fc,2081
9
+ avtomatika/context.py,sha256=T6Ux4Fb1DwWRGTpMNeukM51MQDQbGk2HS6Cwpc0dc1s,4248
10
+ avtomatika/data_types.py,sha256=D_IUzMW8zMz-_MaqVp9MG53rG37Cb3McyRZuIXxvdlE,1108
11
+ avtomatika/datastore.py,sha256=gJjhZ5kxjF8pmbbPQb_qu3HPUpfy2c6T75KZ-smb_zg,545
12
+ avtomatika/dispatcher.py,sha256=5J5GBWFfaGCGXUkM-2fhMeg2n2nTO0BH3ffkzsnSsaE,8784
13
+ avtomatika/engine.py,sha256=Hb6MLanMjx1GDAfkbNJU-K4RXMuPZQP7_HA_0VR8WMw,20916
14
+ avtomatika/executor.py,sha256=X5AU7hWflH8rSYKxl_wh2RhdYhpyktynmK8mcfJgT-8,24218
15
+ avtomatika/health_checker.py,sha256=jXYSH4BPeZ4LCxSZV4uXM4BZhGJYgpoAOWQXE8yojLo,2078
16
+ avtomatika/logging_config.py,sha256=cVY8aOeaWncsvkN015WgC74NTF6r55-OA3E1ux8P824,3347
17
+ avtomatika/metrics.py,sha256=tiksK1fFSOMlz8zFu6GT19JTduvxMTNlLu0QFrTHoQI,1866
18
+ avtomatika/py.typed,sha256=CT_L7gw2MLcQY-X0vs-xB5Vr0wzvGo7GuQYPI_qwJE8,65
19
+ avtomatika/quota.py,sha256=DNcaL6k0J1REeP8sVqbY9FprY_3BSr2SxM2Vf4mEqdw,1612
20
+ avtomatika/ratelimit.py,sha256=hFGW5oN9G6_W_jnHmopXW8bRjjzlvanY19MLghsNLE8,1306
21
+ avtomatika/reputation.py,sha256=pK-x9FrPN2Oc2gtPa1AZJHlhvkd7xlRe4orxM2auJJc,3979
22
+ avtomatika/s3.py,sha256=I0fDw5I44RJAqSv4tREvwHp2cxB0mGY_l2cVZWpe3As,14110
23
+ avtomatika/scheduler.py,sha256=F5Kv5Rx34nDd0mE5jxjwpjRg8duDZBEr91N5Y6CNR24,4231
24
+ avtomatika/scheduler_config_loader.py,sha256=38x-4G4yRrhSrLdmZ4aTb7WggE-BcGblKZO7x97nW6Y,1352
25
+ avtomatika/security.py,sha256=eENEUc0OsHm6wN2H-ckGmiaV9qrZSbYsHFCWyYb3aLs,3271
26
+ avtomatika/telemetry.py,sha256=17QVxb2vqx3vCkhvzL0JFYc6zvTFndUyZ5balj5wXuA,2504
27
+ avtomatika/watcher.py,sha256=IKBqJ_r52ya0wiH8Gb0qFRMC8DFsusdRzPHjruWvFh4,3558
28
+ avtomatika/worker_config_loader.py,sha256=n0j8gfuJDacWONr8744RsHTCWpc_1ZTRMC-rJZh6P6A,2249
29
+ avtomatika/ws_manager.py,sha256=0-vo7_IaDJbD58omTSrHm4SZHjePIlVLxEpiVTgNvbQ,3491
30
+ avtomatika/api/handlers.py,sha256=D8oEWsRG7YqJCwXVQaSbLHA35AKm-HahFKM_FDqfqCE,11701
31
+ avtomatika/api/routes.py,sha256=MrtcRNjybxODmKhab0FCzgZGPRcfznwpFtDCdgh8RT4,3937
32
+ avtomatika/history/base.py,sha256=RsCvCkHK1teHjXSk9ZHVEtpQlIjz8kWsfKYHVnapf6c,3848
33
+ avtomatika/history/noop.py,sha256=hLzt0RblsrKUtoyQNauOni6jCi-IYCWEPsiR0vh7tho,1226
34
+ avtomatika/history/postgres.py,sha256=T0XpDurnh48pPI-2JhB285GdNIexNkCSu8ExhLJzcxc,9538
35
+ avtomatika/history/sqlite.py,sha256=txWax9RVzBQzIZuU-SjHnEXEzBmGzIjqzoVsK2oyiAQ,9252
36
+ avtomatika/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
37
+ avtomatika/services/worker_service.py,sha256=cPik-DUYPka0lOT38fvmVpEnmt1_n2p44z9emyikdLg,11518
38
+ avtomatika/storage/__init__.py,sha256=mGRj_40dWZ7R7uYbqC6gCsUWCKHAbZz4ZVIhYg5dT_E,262
39
+ avtomatika/storage/base.py,sha256=Tb_4fF0Vr10cgoXepA-1YUSgi27qYKQ7Qz1Y87XiRII,13375
40
+ avtomatika/storage/memory.py,sha256=23eNAcEleM6Yqi_kSn-dLEBJRMzrhlgRHVgxrVhZPrk,14560
41
+ avtomatika/storage/redis.py,sha256=MPSQRuAzWNtKQZco_5ExvCpaWbs5_80or5QVrU1GcIM,20235
42
+ avtomatika/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
43
+ avtomatika/utils/webhook_sender.py,sha256=LoJ6z_1p-OngjPYl9Pk1N1t9xrP6-v-7xOg_AmWPuVc,3644
44
+ avtomatika-1.0b10.dist-info/licenses/LICENSE,sha256=tqCjw9Y1vbU-hLcWi__7wQstLbt2T1XWPdbQYqCxuWY,1072
45
+ avtomatika-1.0b10.dist-info/METADATA,sha256=iFXea4IsLOM9dqBBcMDPqbEZDGTMbLcQoV-7SDpk_xQ,28593
46
+ avtomatika-1.0b10.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
47
+ avtomatika-1.0b10.dist-info/top_level.txt,sha256=gLDWhA_wxHj0I6fG5X8vw9fE0HSN4hTE2dEJzeVS2x8,11
48
+ avtomatika-1.0b10.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: setuptools (80.10.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,46 +0,0 @@
1
- avtomatika/__init__.py,sha256=D5r3L-H06uxsY_wgfh7u9YR29QvZMer1BlvzjW9Umfo,701
2
- avtomatika/api.html,sha256=RLx-D1uFCSAXIf_2WgFlSTWrWPcmonNYM-9oNanKXBg,32835
3
- avtomatika/app_keys.py,sha256=XL9Q1Ef5JYa_JG8LM3jzb3cOQjnKaM6ypwqXWnUKeDU,1212
4
- avtomatika/blueprint.py,sha256=AJ8hZkzvqkdu9aPmlJeFzuSj57L6Xm41KS9kBMGB4Vg,11827
5
- avtomatika/client_config_loader.py,sha256=zVVHZlxSqZUaNpZ4zoU0T1CFYXdxy-3vKSmPcaFuHSY,2772
6
- avtomatika/compression.py,sha256=bhA1kw4YrCR3I3kdquZSY0fAzCrRrjtz55uepzLUDKI,2498
7
- avtomatika/config.py,sha256=zqaZrt44Zd_ppvWPDkSth1nJydhAsK0jQLDo0QIW77A,3103
8
- avtomatika/constants.py,sha256=WL58Nh-EY6baM9Ur_tR9merwPRGb41_klUG2V-yUUaA,963
9
- avtomatika/context.py,sha256=T6Ux4Fb1DwWRGTpMNeukM51MQDQbGk2HS6Cwpc0dc1s,4248
10
- avtomatika/data_types.py,sha256=nm9pLhLLx8fngjvAE8d3nQZkD8Y3Q28RHch9kjYAG2Y,1447
11
- avtomatika/datastore.py,sha256=gJjhZ5kxjF8pmbbPQb_qu3HPUpfy2c6T75KZ-smb_zg,545
12
- avtomatika/dispatcher.py,sha256=CKqniknJZe7gjY7QmGlODJc5X8B6qWjtr2UxRivUbuY,8603
13
- avtomatika/engine.py,sha256=VUw5s65Q403a1JgkRtF1KeSiVx1W6MFmukxZpYN-f00,16175
14
- avtomatika/executor.py,sha256=K7RGGxWz_4n6q0m8tW0oNtUJm90b-4O2U9lTB_yLX-k,24461
15
- avtomatika/health_checker.py,sha256=jXYSH4BPeZ4LCxSZV4uXM4BZhGJYgpoAOWQXE8yojLo,2078
16
- avtomatika/logging_config.py,sha256=Zb6f9Nri9WVWhlpuBg6Lpi5SWRLGIUmS8Dc3xD1Gg0g,2993
17
- avtomatika/metrics.py,sha256=tiksK1fFSOMlz8zFu6GT19JTduvxMTNlLu0QFrTHoQI,1866
18
- avtomatika/py.typed,sha256=CT_L7gw2MLcQY-X0vs-xB5Vr0wzvGo7GuQYPI_qwJE8,65
19
- avtomatika/quota.py,sha256=DNcaL6k0J1REeP8sVqbY9FprY_3BSr2SxM2Vf4mEqdw,1612
20
- avtomatika/ratelimit.py,sha256=hFGW5oN9G6_W_jnHmopXW8bRjjzlvanY19MLghsNLE8,1306
21
- avtomatika/reputation.py,sha256=pK-x9FrPN2Oc2gtPa1AZJHlhvkd7xlRe4orxM2auJJc,3979
22
- avtomatika/s3.py,sha256=d-zyqdS0dV6K_92BbOH4Lo0Um0AvrMxfSFoD5QFPBSo,11941
23
- avtomatika/scheduler.py,sha256=F5Kv5Rx34nDd0mE5jxjwpjRg8duDZBEr91N5Y6CNR24,4231
24
- avtomatika/scheduler_config_loader.py,sha256=F6mLM8yPRgG4bMHV_WnXX7UOrXD8fCXJT30bbEuQ2mk,1311
25
- avtomatika/security.py,sha256=kkU68YmLWq1ClMUdEW98pS9WsEwHinHoZcdMoPm63Uk,4417
26
- avtomatika/telemetry.py,sha256=ZBt1_xJ36PzDSz-zdCXeNp58NiezUgbqvMctTG25PT0,2352
27
- avtomatika/watcher.py,sha256=-oqyUKq4WYtFYe0PjfDkAjjTUxpyN79JTnOzwlg-Z84,3467
28
- avtomatika/worker_config_loader.py,sha256=n0j8gfuJDacWONr8744RsHTCWpc_1ZTRMC-rJZh6P6A,2249
29
- avtomatika/ws_manager.py,sha256=fjIGWZF_L5j5QEpTdNT2Qz4N5ut9pjKlgEKI0sY2GOc,3148
30
- avtomatika/api/handlers.py,sha256=MO6QkbT001jj4latUXGT0hGOmQf_6TkRkmwx19OcXeQ,22176
31
- avtomatika/api/routes.py,sha256=vSwj2jJlmftZrjrctt-mNYLF23CfCtlUfaMoZzNOqCk,4895
32
- avtomatika/history/base.py,sha256=RsCvCkHK1teHjXSk9ZHVEtpQlIjz8kWsfKYHVnapf6c,3848
33
- avtomatika/history/noop.py,sha256=hLzt0RblsrKUtoyQNauOni6jCi-IYCWEPsiR0vh7tho,1226
34
- avtomatika/history/postgres.py,sha256=T0XpDurnh48pPI-2JhB285GdNIexNkCSu8ExhLJzcxc,9538
35
- avtomatika/history/sqlite.py,sha256=txWax9RVzBQzIZuU-SjHnEXEzBmGzIjqzoVsK2oyiAQ,9252
36
- avtomatika/storage/__init__.py,sha256=mGRj_40dWZ7R7uYbqC6gCsUWCKHAbZz4ZVIhYg5dT_E,262
37
- avtomatika/storage/base.py,sha256=l6ppbvbIshb5cD0yByDAeCSePBWp05iuaovbi4gaWww,12939
38
- avtomatika/storage/memory.py,sha256=cZRVHqXRn3Gm06jJirBOk2IgB-ocqaJQSmzUEsCmK-M,14009
39
- avtomatika/storage/redis.py,sha256=WrUbDq1wC9fpFjMM0IqkbYAvmwm9-s3DmEFo8sO18FA,18664
40
- avtomatika/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
41
- avtomatika/utils/webhook_sender.py,sha256=4Ud2Tz18yV4kzfGQyDO2by8s2EIEwHkv1vtIUis9kVQ,3606
42
- avtomatika-1.0b8.dist-info/licenses/LICENSE,sha256=tqCjw9Y1vbU-hLcWi__7wQstLbt2T1XWPdbQYqCxuWY,1072
43
- avtomatika-1.0b8.dist-info/METADATA,sha256=AV7TG3pNVxvHyj7eyS5OTo7BXrBigb4mFCfJvtZqzTM,26382
44
- avtomatika-1.0b8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
45
- avtomatika-1.0b8.dist-info/top_level.txt,sha256=gLDWhA_wxHj0I6fG5X8vw9fE0HSN4hTE2dEJzeVS2x8,11
46
- avtomatika-1.0b8.dist-info/RECORD,,