pulse-engine 0.2.26__tar.gz → 0.2.27__tar.gz
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.
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/PKG-INFO +1 -1
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/pyproject.toml +1 -1
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/adapters/models.py +3 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/adapters/transcription/providers/youtube_captions.py +30 -11
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/adapters/transcription/service.py +13 -3
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/adapters/youtube_downloader.py +56 -19
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/cron/runner.py +1 -1
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/deployment/infra_provisioner.py +90 -6
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/pipeline/router_pipelines.py +1 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/pipeline/schemas.py +1 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/pipeline/service.py +3 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/runners/prefect_pipeline_flow.py +21 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/README.md +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/__init__.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/adapters/__init__.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/adapters/audio_transcription.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/adapters/batcher.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/adapters/digital_news.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/adapters/digital_news_metadata.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/adapters/document_event_campaign_mapper.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/adapters/exceptions.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/adapters/mart_export.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/adapters/opensearch_sql.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/adapters/opensearch_storage.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/adapters/prompts.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/adapters/report_generator.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/adapters/speech_content.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/adapters/speech_metadata.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/adapters/transcription/__init__.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/adapters/transcription/base.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/adapters/transcription/config.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/adapters/transcription/factory.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/adapters/transcription/providers/__init__.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/adapters/transcription/providers/deepgram.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/adapters/transcription/providers/openai_whisper.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/adapters/transcription/providers/selfhosted_job.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/adapters/transcription/source.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/adapters/twitter.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/adapters/youtube_metadata.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/api/__init__.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/api/v1/__init__.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/api/v1/auth.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/api/v1/health.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/api/v1/router.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/cli/__init__.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/cli/main.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/cli/templates/cookiecutter.json +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/cli/templates/pulse-{{cookiecutter.product_name}}/.gitignore +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/cli/templates/pulse-{{cookiecutter.product_name}}/Dockerfile +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/cli/templates/pulse-{{cookiecutter.product_name}}/pipeline.yaml +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/cli/templates/pulse-{{cookiecutter.product_name}}/pyproject.toml +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/cli/templates/pulse-{{cookiecutter.product_name}}/src/pulse_{{cookiecutter.product_slug}}/__init__.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/cli/templates/pulse-{{cookiecutter.product_name}}/tests/__init__.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/cli/templates/pulse-{{cookiecutter.product_name}}/tests/unit/__init__.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/cli/templates/pulse-{{cookiecutter.product_name}}/tests/unit/test_manifest.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/client.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/config.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/core/__init__.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/core/error_handlers.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/core/exceptions.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/core/job_token.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/core/logging.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/core/scope.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/core/security.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/cron/__init__.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/cron/models.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/cron/pipeline_sync.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/cron/repository.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/cron/router.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/cron/schemas.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/cron/service.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/cron/tasks.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/cron/translator.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/database.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/dependencies.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/deployment/__init__.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/evolution/__init__.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/evolution/adapter.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/evolution/client.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/evolution/models.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/evolution/router.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/evolution/service.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/extractor/__init__.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/extractor/adapters/__init__.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/extractor/base.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/main.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/mcp/__init__.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/mcp/__main__.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/mcp/server.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/mcp/tools_kb.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/mcp/tools_modules.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/mcp/tools_pipelines.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/mcp/tools_processor.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/middleware/__init__.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/middleware/rate_limit.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/middleware/request_id.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/middleware/security_headers.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/middleware/tenant.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/notifications/__init__.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/notifications/apprise_notifier.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/pipeline/__init__.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/pipeline/config_parser.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/pipeline/expression.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/pipeline/models.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/pipeline/repositories.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/pipeline/router_modules.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/pipeline/translators/__init__.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/pipeline/translators/airflow_status.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/pipeline/translators/airflow_translator.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/pipeline/translators/base.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/pipeline/translators/prefect_status.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/pipeline/translators/prefect_translator.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/processor/__init__.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/processor/base.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/processor/core/__init__.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/processor/core/analysis.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/processor/core/chunking.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/processor/core/prompts.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/processor/core/topic_splitter.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/processor/defaults/__init__.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/processor/defaults/core_processor.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/processor/defaults/postprocessor.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/processor/defaults/preprocessor.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/processor/llm/__init__.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/processor/llm/provider.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/processor/ocr/gemini.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/processor/pipeline.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/processor/postprocessor/__init__.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/processor/postprocessor/embeddings.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/processor/postprocessor/tasks.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/processor/preprocessor/__init__.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/processor/preprocessor/tasks.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/processor/router.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/processor/schemas.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/registry.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/reporting/__init__.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/reporting/agent.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/reporting/fixtures.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/reporting/models.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/reporting/prompts.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/reporting/service.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/reporting/tools.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/reporting/wiring.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/runners/__init__.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/runners/lambda_runner.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/runners/pipeline_runner.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/runners/prefect_runner.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/s3.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/sandbox/__init__.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/sandbox/backend.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/sandbox/lambda_microvm.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/sandbox/microvm_agent/Dockerfile +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/sandbox/microvm_agent/__init__.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/sandbox/microvm_agent/server.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/sandbox/session.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/secrets.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/services/__init__.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/services/bootstrap.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/services/opensearch.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/skills/__init__.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/skills/catalog.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/skills/models.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/skills/repo.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/skills/seed.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/skills/seed_data/skill_files.json +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/skills/seed_data/skills.json +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/skills/sync.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/skills/tools.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/storage/__init__.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/storage/connectors/__init__.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/storage/connectors/athena.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/storage/connectors/base.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/storage/connectors/opensearch.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/storage/knowledge_base.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/storage/router.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/storage/schemas.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/testing/__init__.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/testing/fixtures.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/testing/mocks.py +0 -0
- {pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/worker.py +0 -0
|
@@ -215,6 +215,23 @@ class YouTubeCaptionsProvider(TranscriptionProvider):
|
|
|
215
215
|
raise TranscriptionUnavailable("yt-dlp not installed")
|
|
216
216
|
|
|
217
217
|
video_id = source.video_id
|
|
218
|
+
proxy = os.environ.get("YT_DLP_PROXY", "").strip()
|
|
219
|
+
|
|
220
|
+
try:
|
|
221
|
+
result = await self._attempt(video_id, language, use_proxy=False)
|
|
222
|
+
result.used_proxy = False
|
|
223
|
+
return result
|
|
224
|
+
except TranscriptionUnavailable:
|
|
225
|
+
if not (proxy and self._cookies_secret_id):
|
|
226
|
+
raise
|
|
227
|
+
logger.info("youtube_captions_retry_with_proxy", video_id=video_id)
|
|
228
|
+
result = await self._attempt(video_id, language, use_proxy=True)
|
|
229
|
+
result.used_proxy = True
|
|
230
|
+
return result
|
|
231
|
+
|
|
232
|
+
async def _attempt(
|
|
233
|
+
self, video_id: str, language: str, use_proxy: bool
|
|
234
|
+
) -> VideoAudio:
|
|
218
235
|
raw_clients = os.environ.get("YT_DLP_PLAYER_CLIENTS", "").strip()
|
|
219
236
|
clients: list[str] = (
|
|
220
237
|
[c.strip() for c in raw_clients.split(",") if c.strip()]
|
|
@@ -236,17 +253,19 @@ class YouTubeCaptionsProvider(TranscriptionProvider):
|
|
|
236
253
|
|
|
237
254
|
# Optional residential/mobile proxy — YouTube bot-gates datacenter
|
|
238
255
|
# IPs regardless of cookies, so caption fetches from cloud runs need
|
|
239
|
-
# the same proxy the audio downloader uses.
|
|
240
|
-
|
|
241
|
-
if
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
256
|
+
# the same proxy the audio downloader uses. Only used on retry
|
|
257
|
+
# after a direct (no-proxy, no-cookies) attempt fails.
|
|
258
|
+
if use_proxy:
|
|
259
|
+
proxy = os.environ.get("YT_DLP_PROXY", "").strip()
|
|
260
|
+
if proxy:
|
|
261
|
+
base_opts["proxy"] = proxy
|
|
262
|
+
|
|
263
|
+
cookies = await self._resolve_cookies()
|
|
264
|
+
if cookies:
|
|
265
|
+
cookies_path = tmp / "cookies.txt"
|
|
266
|
+
cookies_path.write_text(cookies, encoding="utf-8")
|
|
267
|
+
cookies_path.chmod(0o600)
|
|
268
|
+
base_opts["cookiefile"] = str(cookies_path)
|
|
250
269
|
|
|
251
270
|
try:
|
|
252
271
|
manual_langs, auto_langs = await self._list_available_langs(
|
{pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/adapters/transcription/service.py
RENAMED
|
@@ -40,22 +40,32 @@ class TranscriptionService:
|
|
|
40
40
|
audio_resolver=audio_resolver,
|
|
41
41
|
)
|
|
42
42
|
|
|
43
|
+
last_error: str | None = None
|
|
43
44
|
for name in chain:
|
|
44
45
|
try:
|
|
45
46
|
provider = self._factory.get(name)
|
|
46
|
-
|
|
47
|
+
result = await provider.transcribe(source, cfg.language)
|
|
48
|
+
result.provider = name
|
|
49
|
+
return result
|
|
47
50
|
except TranscriptionUnavailable as exc:
|
|
51
|
+
last_error = str(exc)
|
|
48
52
|
logger.info(
|
|
49
53
|
"transcription_provider_unavailable",
|
|
50
54
|
provider=name,
|
|
51
55
|
reason=str(exc),
|
|
52
56
|
)
|
|
53
57
|
continue
|
|
54
|
-
except Exception:
|
|
58
|
+
except Exception as exc:
|
|
59
|
+
last_error = str(exc)
|
|
55
60
|
logger.warning(
|
|
56
61
|
"transcription_provider_failed", provider=name, exc_info=True
|
|
57
62
|
)
|
|
58
63
|
continue
|
|
59
64
|
|
|
60
65
|
logger.warning("transcription_all_providers_failed", chain=chain)
|
|
61
|
-
return VideoAudio(
|
|
66
|
+
return VideoAudio(
|
|
67
|
+
transcript="",
|
|
68
|
+
language=cfg.language,
|
|
69
|
+
segments=[],
|
|
70
|
+
error=f"all providers failed ({', '.join(chain)}): {last_error}",
|
|
71
|
+
)
|
|
@@ -4,6 +4,7 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import asyncio
|
|
6
6
|
import os
|
|
7
|
+
from dataclasses import dataclass
|
|
7
8
|
from pathlib import Path
|
|
8
9
|
from typing import Any
|
|
9
10
|
|
|
@@ -17,6 +18,20 @@ logger = structlog.get_logger(__name__)
|
|
|
17
18
|
# age-restricted videos when cookies are provided. Override via YT_DLP_PLAYER_CLIENTS.
|
|
18
19
|
_DEFAULT_PLAYER_CLIENTS = ["tv_embedded", "web"]
|
|
19
20
|
|
|
21
|
+
# Cap fragment/segment retries on the proxy path — a flaky proxy shouldn't
|
|
22
|
+
# re-pull fragments repeatedly on the metered egress. Direct-path retries are
|
|
23
|
+
# unaffected (governed entirely by the caller's `extra` overrides).
|
|
24
|
+
_PROXY_MAX_RETRIES = 1
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass
|
|
28
|
+
class DownloadResult:
|
|
29
|
+
"""Outcome of a `YouTubeDownloader.download()` call."""
|
|
30
|
+
|
|
31
|
+
path: Path | None
|
|
32
|
+
used_proxy: bool
|
|
33
|
+
error: str | None = None
|
|
34
|
+
|
|
20
35
|
|
|
21
36
|
def _build_yt_dlp_opts(
|
|
22
37
|
output_template: str,
|
|
@@ -36,8 +51,9 @@ def _build_yt_dlp_opts(
|
|
|
36
51
|
opts: dict[str, Any] = {
|
|
37
52
|
# Cap source bitrate — output is always re-encoded to 64kbps mp3, so
|
|
38
53
|
# pulling a higher-bitrate stream just to downsample it wastes egress
|
|
39
|
-
# (metered on the proxy path).
|
|
40
|
-
|
|
54
|
+
# (metered on the proxy path). Capped to match the 64kbps mp3 output
|
|
55
|
+
# exactly; fallback chain keeps degrading gracefully if unavailable.
|
|
56
|
+
"format": "bestaudio[abr<=64]/bestaudio/best",
|
|
41
57
|
"outtmpl": output_template,
|
|
42
58
|
"postprocessors": [
|
|
43
59
|
{
|
|
@@ -87,6 +103,17 @@ def _build_yt_dlp_opts(
|
|
|
87
103
|
merged[k] = v
|
|
88
104
|
opts["extractor_args"] = merged
|
|
89
105
|
|
|
106
|
+
if use_proxy and "proxy" in opts:
|
|
107
|
+
# Cap retries on the metered proxy path regardless of caller overrides
|
|
108
|
+
# (e.g. feed's hardening opts default retries=2) — a flaky proxy
|
|
109
|
+
# shouldn't re-pull fragments repeatedly on billed egress.
|
|
110
|
+
opts["retries"] = min(
|
|
111
|
+
opts.get("retries", _PROXY_MAX_RETRIES), _PROXY_MAX_RETRIES
|
|
112
|
+
)
|
|
113
|
+
opts["fragment_retries"] = min(
|
|
114
|
+
opts.get("fragment_retries", _PROXY_MAX_RETRIES), _PROXY_MAX_RETRIES
|
|
115
|
+
)
|
|
116
|
+
|
|
90
117
|
if clip_start is not None or clip_end is not None:
|
|
91
118
|
from yt_dlp.utils import download_range_func
|
|
92
119
|
|
|
@@ -129,31 +156,33 @@ class YouTubeDownloader:
|
|
|
129
156
|
output_dir: str,
|
|
130
157
|
start: float | None = None,
|
|
131
158
|
end: float | None = None,
|
|
132
|
-
) ->
|
|
133
|
-
"""Download audio for *video_id* into *output_dir
|
|
159
|
+
) -> DownloadResult:
|
|
160
|
+
"""Download audio for *video_id* into *output_dir*.
|
|
134
161
|
|
|
135
|
-
Returns
|
|
162
|
+
Returns a `DownloadResult` — `path` is `None` if the download failed
|
|
163
|
+
for any reason, with `used_proxy`/`error` describing which attempt
|
|
164
|
+
ran and why it failed.
|
|
136
165
|
"""
|
|
137
166
|
url = f"https://www.youtube.com/watch?v={video_id}"
|
|
138
167
|
logger.info("youtube_download_started", video_id=video_id)
|
|
139
168
|
|
|
140
|
-
|
|
169
|
+
path, error = await self._download_audio(
|
|
141
170
|
url, output_dir, start=start, end=end, use_proxy=False, use_cookies=False
|
|
142
171
|
)
|
|
143
172
|
|
|
144
|
-
|
|
173
|
+
used_proxy = False
|
|
174
|
+
if path is None and self._proxy_configured and self._cookies_secret_id:
|
|
145
175
|
logger.info("youtube_download_retry_with_proxy", video_id=video_id)
|
|
146
|
-
|
|
176
|
+
used_proxy = True
|
|
177
|
+
path, error = await self._download_audio(
|
|
147
178
|
url, output_dir, start=start, end=end, use_proxy=True, use_cookies=True
|
|
148
179
|
)
|
|
149
180
|
|
|
150
|
-
if
|
|
181
|
+
if path is None:
|
|
151
182
|
logger.warning("youtube_download_failed", video_id=video_id)
|
|
152
183
|
else:
|
|
153
|
-
logger.info(
|
|
154
|
-
|
|
155
|
-
)
|
|
156
|
-
return result
|
|
184
|
+
logger.info("youtube_download_completed", video_id=video_id, path=str(path))
|
|
185
|
+
return DownloadResult(path=path, used_proxy=used_proxy, error=error)
|
|
157
186
|
|
|
158
187
|
# ------------------------------------------------------------------
|
|
159
188
|
# Private helpers
|
|
@@ -207,13 +236,17 @@ class YouTubeDownloader:
|
|
|
207
236
|
end: float | None = None,
|
|
208
237
|
use_proxy: bool = False,
|
|
209
238
|
use_cookies: bool = False,
|
|
210
|
-
) -> Path | None:
|
|
211
|
-
"""Download audio from a YouTube URL to *output_dir* via yt-dlp.
|
|
239
|
+
) -> tuple[Path | None, str | None]:
|
|
240
|
+
"""Download audio from a YouTube URL to *output_dir* via yt-dlp.
|
|
241
|
+
|
|
242
|
+
Returns `(path, error)` — `path` is `None` on failure, with `error`
|
|
243
|
+
carrying the failure reason (`None` on success).
|
|
244
|
+
"""
|
|
212
245
|
try:
|
|
213
246
|
import yt_dlp
|
|
214
247
|
except ImportError:
|
|
215
248
|
logger.warning("yt_dlp_not_installed", url=url)
|
|
216
|
-
return None
|
|
249
|
+
return None, "yt-dlp not installed"
|
|
217
250
|
|
|
218
251
|
output_template = str(Path(output_dir) / "%(id)s.%(ext)s")
|
|
219
252
|
ydl_opts = _build_yt_dlp_opts(
|
|
@@ -245,7 +278,11 @@ class YouTubeDownloader:
|
|
|
245
278
|
return candidate if candidate.exists() else None
|
|
246
279
|
|
|
247
280
|
try:
|
|
248
|
-
|
|
249
|
-
except Exception:
|
|
281
|
+
path = await asyncio.to_thread(_download)
|
|
282
|
+
except Exception as exc:
|
|
250
283
|
logger.warning("youtube_audio_download_failed", url=url, exc_info=True)
|
|
251
|
-
return None
|
|
284
|
+
return None, str(exc)
|
|
285
|
+
|
|
286
|
+
if path is None:
|
|
287
|
+
return None, "download completed but output file not found"
|
|
288
|
+
return path, None
|
|
@@ -81,7 +81,7 @@ def cron_job_flow(
|
|
|
81
81
|
try:
|
|
82
82
|
method = (webhook_method or "POST").upper()
|
|
83
83
|
if method == "GET":
|
|
84
|
-
resp = httpx.get(webhook_url, headers=webhook_headers, timeout=
|
|
84
|
+
resp = httpx.get(webhook_url, headers=webhook_headers, timeout=1800.0)
|
|
85
85
|
else:
|
|
86
86
|
resp = httpx.post(
|
|
87
87
|
webhook_url,
|
{pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/deployment/infra_provisioner.py
RENAMED
|
@@ -13,6 +13,8 @@ Prerequisites (created by Terraform once):
|
|
|
13
13
|
from __future__ import annotations
|
|
14
14
|
|
|
15
15
|
import logging
|
|
16
|
+
import random
|
|
17
|
+
import time
|
|
16
18
|
from typing import Any
|
|
17
19
|
|
|
18
20
|
import boto3
|
|
@@ -20,6 +22,14 @@ from botocore.exceptions import ClientError
|
|
|
20
22
|
|
|
21
23
|
logger = logging.getLogger(__name__)
|
|
22
24
|
|
|
25
|
+
# ECS throttles concurrent register_task_definition calls against the same
|
|
26
|
+
# family with this exact message. Retried with backoff since it's transient.
|
|
27
|
+
_ECS_CONCURRENT_REVISION_MESSAGE = (
|
|
28
|
+
"Too many concurrent attempts to create a new revision"
|
|
29
|
+
)
|
|
30
|
+
_ECS_REGISTER_MAX_RETRIES = 5
|
|
31
|
+
_ECS_REGISTER_BASE_DELAY_SECONDS = 1.0
|
|
32
|
+
|
|
23
33
|
|
|
24
34
|
class InfraProvisioner:
|
|
25
35
|
"""Auto-provisions AWS infrastructure for pipeline step containers.
|
|
@@ -101,6 +111,36 @@ class InfraProvisioner:
|
|
|
101
111
|
except ClientError as e:
|
|
102
112
|
if e.response["Error"]["Code"] != "ClientException":
|
|
103
113
|
raise
|
|
114
|
+
else:
|
|
115
|
+
# A specific image was requested — reuse the latest revision if
|
|
116
|
+
# it already matches (same image/cpu/memory) instead of blindly
|
|
117
|
+
# registering a new one every call. Concurrent pipeline runs
|
|
118
|
+
# otherwise all race to create new revisions of the same shared
|
|
119
|
+
# family, which ECS throttles with a ClientException.
|
|
120
|
+
try:
|
|
121
|
+
resp = ecs.describe_task_definition(taskDefinition=family)
|
|
122
|
+
existing = resp["taskDefinition"]
|
|
123
|
+
existing_containers = existing.get("containerDefinitions", [])
|
|
124
|
+
existing_image = (
|
|
125
|
+
existing_containers[0]["image"] if existing_containers else None
|
|
126
|
+
)
|
|
127
|
+
if (
|
|
128
|
+
existing_image == image
|
|
129
|
+
and existing.get("cpu") == cpu
|
|
130
|
+
and existing.get("memory") == memory
|
|
131
|
+
):
|
|
132
|
+
result_arn = str(existing["taskDefinitionArn"])
|
|
133
|
+
logger.info(
|
|
134
|
+
"Reusing matching ECS task definition: %s (rev %s, image=%s)",
|
|
135
|
+
family,
|
|
136
|
+
existing["revision"],
|
|
137
|
+
image,
|
|
138
|
+
)
|
|
139
|
+
self._ecs_task_def_cache[cache_key] = result_arn
|
|
140
|
+
return result_arn
|
|
141
|
+
except ClientError as e:
|
|
142
|
+
if e.response["Error"]["Code"] != "ClientException":
|
|
143
|
+
raise
|
|
104
144
|
|
|
105
145
|
# Register new task definition with the specified (or placeholder) image
|
|
106
146
|
container_def: dict[str, Any] = {
|
|
@@ -124,15 +164,12 @@ class InfraProvisioner:
|
|
|
124
164
|
},
|
|
125
165
|
}
|
|
126
166
|
|
|
127
|
-
resp =
|
|
167
|
+
resp = self._register_task_definition_with_retry(
|
|
168
|
+
ecs,
|
|
128
169
|
family=family,
|
|
129
|
-
networkMode="awsvpc",
|
|
130
|
-
requiresCompatibilities=["FARGATE"],
|
|
131
170
|
cpu=cpu,
|
|
132
171
|
memory=memory,
|
|
133
|
-
|
|
134
|
-
taskRoleArn=self._task_role_arn,
|
|
135
|
-
containerDefinitions=[container_def],
|
|
172
|
+
container_def=container_def,
|
|
136
173
|
)
|
|
137
174
|
|
|
138
175
|
result_arn = str(resp["taskDefinition"]["taskDefinitionArn"])
|
|
@@ -140,6 +177,53 @@ class InfraProvisioner:
|
|
|
140
177
|
self._ecs_task_def_cache[cache_key] = result_arn
|
|
141
178
|
return result_arn
|
|
142
179
|
|
|
180
|
+
def _register_task_definition_with_retry(
|
|
181
|
+
self,
|
|
182
|
+
ecs: Any,
|
|
183
|
+
*,
|
|
184
|
+
family: str,
|
|
185
|
+
cpu: str,
|
|
186
|
+
memory: str,
|
|
187
|
+
container_def: dict[str, Any],
|
|
188
|
+
) -> dict[str, Any]:
|
|
189
|
+
"""Call register_task_definition, retrying with backoff+jitter on the
|
|
190
|
+
ECS "too many concurrent attempts" throttle for this family."""
|
|
191
|
+
for attempt in range(1, _ECS_REGISTER_MAX_RETRIES + 1):
|
|
192
|
+
try:
|
|
193
|
+
return ecs.register_task_definition( # type: ignore[no-any-return]
|
|
194
|
+
family=family,
|
|
195
|
+
networkMode="awsvpc",
|
|
196
|
+
requiresCompatibilities=["FARGATE"],
|
|
197
|
+
cpu=cpu,
|
|
198
|
+
memory=memory,
|
|
199
|
+
executionRoleArn=self._exec_role_arn,
|
|
200
|
+
taskRoleArn=self._task_role_arn,
|
|
201
|
+
containerDefinitions=[container_def],
|
|
202
|
+
)
|
|
203
|
+
except ClientError as e:
|
|
204
|
+
error = e.response.get("Error", {})
|
|
205
|
+
is_concurrent_revision_throttle = (
|
|
206
|
+
error.get("Code") == "ClientException"
|
|
207
|
+
and _ECS_CONCURRENT_REVISION_MESSAGE in error.get("Message", "")
|
|
208
|
+
)
|
|
209
|
+
if (
|
|
210
|
+
not is_concurrent_revision_throttle
|
|
211
|
+
or attempt == _ECS_REGISTER_MAX_RETRIES
|
|
212
|
+
):
|
|
213
|
+
raise
|
|
214
|
+
delay = _ECS_REGISTER_BASE_DELAY_SECONDS * (2 ** (attempt - 1))
|
|
215
|
+
delay += random.uniform(0, delay * 0.5)
|
|
216
|
+
logger.warning(
|
|
217
|
+
"ECS register_task_definition throttled for family %s "
|
|
218
|
+
"(attempt %d/%d), retrying in %.1fs",
|
|
219
|
+
family,
|
|
220
|
+
attempt,
|
|
221
|
+
_ECS_REGISTER_MAX_RETRIES,
|
|
222
|
+
delay,
|
|
223
|
+
)
|
|
224
|
+
time.sleep(delay)
|
|
225
|
+
raise AssertionError("unreachable") # loop always returns or raises
|
|
226
|
+
|
|
143
227
|
# ------------------------------------------------------------------
|
|
144
228
|
# Lambda Function
|
|
145
229
|
# ------------------------------------------------------------------
|
|
@@ -192,6 +192,7 @@ async def init_pipeline_run(
|
|
|
192
192
|
config_snapshot=body.config_snapshot,
|
|
193
193
|
global_config=body.global_config,
|
|
194
194
|
orchestrator=body.orchestrator,
|
|
195
|
+
orchestrator_run_id=body.orchestrator_run_id,
|
|
195
196
|
)
|
|
196
197
|
return InitRunResponse(run_id=run_id, token=token)
|
|
197
198
|
|
|
@@ -244,6 +244,7 @@ class InitRunRequest(BaseModel):
|
|
|
244
244
|
config_snapshot: dict[str, Any]
|
|
245
245
|
global_config: dict[str, Any] = Field(default_factory=dict)
|
|
246
246
|
orchestrator: str = "prefect"
|
|
247
|
+
orchestrator_run_id: str | None = None
|
|
247
248
|
|
|
248
249
|
|
|
249
250
|
class InitRunResponse(BaseModel):
|
|
@@ -315,6 +315,7 @@ class PipelineService:
|
|
|
315
315
|
config_snapshot: dict[str, Any],
|
|
316
316
|
global_config: dict[str, Any],
|
|
317
317
|
orchestrator: str = "prefect",
|
|
318
|
+
orchestrator_run_id: str | None = None,
|
|
318
319
|
) -> tuple[str, str]:
|
|
319
320
|
"""Register a fresh pipeline run for a cron-triggered execution.
|
|
320
321
|
|
|
@@ -330,6 +331,8 @@ class PipelineService:
|
|
|
330
331
|
global_config=global_config,
|
|
331
332
|
)
|
|
332
333
|
now = datetime.now(tz=UTC)
|
|
334
|
+
if orchestrator_run_id is not None:
|
|
335
|
+
await self._run_repo.set_orchestrator_run_id(run.id, orchestrator_run_id)
|
|
333
336
|
await self._run_repo.update_status(run.id, "running", started_at=now)
|
|
334
337
|
|
|
335
338
|
# Cron/scheduled per-execution runs may retry or run for days after the
|
{pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/runners/prefect_pipeline_flow.py
RENAMED
|
@@ -15,6 +15,8 @@ import asyncio
|
|
|
15
15
|
import json
|
|
16
16
|
import logging
|
|
17
17
|
import os
|
|
18
|
+
import re
|
|
19
|
+
import uuid
|
|
18
20
|
from collections import deque
|
|
19
21
|
from collections.abc import Callable
|
|
20
22
|
from typing import Any, TypeVar
|
|
@@ -521,6 +523,13 @@ async def _dispatch_vm(
|
|
|
521
523
|
step_name = env.get("STEP_NAME", "unknown")
|
|
522
524
|
pipeline_run_id_val = env.get("PIPELINE_RUN_ID", "unknown")
|
|
523
525
|
|
|
526
|
+
# Give the container a stable, greppable name instead of Docker's random
|
|
527
|
+
# adjective_scientist default, so it shows up correctly in log shipping
|
|
528
|
+
# (promtail relabels containers named "pulse-*" to job=pulse-engine-logs).
|
|
529
|
+
_name_safe = re.sub(r"[^a-zA-Z0-9_.-]", "-", f"{step_name}-{pipeline_run_id_val}")
|
|
530
|
+
_short_id = uuid.uuid4().hex[:8]
|
|
531
|
+
container_name = f"pulse-engine-{_name_safe}-{_short_id}"[:128]
|
|
532
|
+
|
|
524
533
|
try:
|
|
525
534
|
from pulse_engine.config import get_settings
|
|
526
535
|
|
|
@@ -608,6 +617,7 @@ async def _dispatch_vm(
|
|
|
608
617
|
"subprocess.run(['docker', 'pull', image], check=True)\n"
|
|
609
618
|
"docker_cmd = [\n"
|
|
610
619
|
" 'docker', 'run', '--rm',\n"
|
|
620
|
+
f" '--name', {repr(container_name)},\n"
|
|
611
621
|
" '--memory', f'{memory_mb}m',\n"
|
|
612
622
|
" '--cpus', str(cpu_count),\n"
|
|
613
623
|
"]\n"
|
|
@@ -726,6 +736,16 @@ async def _dispatch_container(
|
|
|
726
736
|
# ---------------------------------------------------------------------------
|
|
727
737
|
|
|
728
738
|
|
|
739
|
+
def _current_flow_run_id() -> str | None:
|
|
740
|
+
"""Best-effort Prefect flow-run id for the flow currently executing."""
|
|
741
|
+
try:
|
|
742
|
+
from prefect.runtime import flow_run
|
|
743
|
+
|
|
744
|
+
return str(flow_run.id) if flow_run.id else None
|
|
745
|
+
except Exception:
|
|
746
|
+
return None
|
|
747
|
+
|
|
748
|
+
|
|
729
749
|
def _init_cron_run(
|
|
730
750
|
pulse_engine_url: str,
|
|
731
751
|
pulse_api_token: str,
|
|
@@ -744,6 +764,7 @@ def _init_cron_run(
|
|
|
744
764
|
"product": product,
|
|
745
765
|
"config_snapshot": config_snapshot,
|
|
746
766
|
"global_config": global_config,
|
|
767
|
+
"orchestrator_run_id": _current_flow_run_id(),
|
|
747
768
|
},
|
|
748
769
|
headers={"Authorization": f"Bearer {pulse_api_token}"},
|
|
749
770
|
timeout=30.0,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/adapters/audio_transcription.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/adapters/digital_news_metadata.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/adapters/transcription/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/adapters/transcription/config.py
RENAMED
|
File without changes
|
{pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/adapters/transcription/factory.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/adapters/transcription/source.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/cli/templates/cookiecutter.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/notifications/apprise_notifier.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/pipeline/translators/__init__.py
RENAMED
|
File without changes
|
{pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/pipeline/translators/airflow_status.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/pipeline/translators/prefect_status.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/processor/core/topic_splitter.py
RENAMED
|
File without changes
|
|
File without changes
|
{pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/processor/defaults/core_processor.py
RENAMED
|
File without changes
|
{pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/processor/defaults/postprocessor.py
RENAMED
|
File without changes
|
{pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/processor/defaults/preprocessor.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/processor/postprocessor/__init__.py
RENAMED
|
File without changes
|
{pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/processor/postprocessor/embeddings.py
RENAMED
|
File without changes
|
{pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/processor/postprocessor/tasks.py
RENAMED
|
File without changes
|
{pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/processor/preprocessor/__init__.py
RENAMED
|
File without changes
|
{pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/processor/preprocessor/tasks.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/sandbox/microvm_agent/Dockerfile
RENAMED
|
File without changes
|
{pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/sandbox/microvm_agent/__init__.py
RENAMED
|
File without changes
|
{pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/sandbox/microvm_agent/server.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/skills/seed_data/skill_files.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pulse_engine-0.2.26 → pulse_engine-0.2.27}/src/pulse_engine/storage/connectors/opensearch.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|