pulse-engine 0.2.18__tar.gz → 0.2.19__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.
Files changed (178) hide show
  1. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/PKG-INFO +1 -1
  2. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/pyproject.toml +1 -1
  3. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/adapters/report_generator.py +3 -3
  4. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/reporting/models.py +3 -3
  5. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/reporting/tools.py +3 -1
  6. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/reporting/wiring.py +1 -0
  7. pulse_engine-0.2.19/src/pulse_engine/skills/seed.py +141 -0
  8. pulse_engine-0.2.19/src/pulse_engine/skills/seed_data/skill_files.json +975 -0
  9. pulse_engine-0.2.19/src/pulse_engine/skills/seed_data/skills.json +55 -0
  10. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/README.md +0 -0
  11. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/__init__.py +0 -0
  12. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/adapters/__init__.py +0 -0
  13. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/adapters/audio_transcription.py +0 -0
  14. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/adapters/batcher.py +0 -0
  15. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/adapters/digital_news.py +0 -0
  16. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/adapters/digital_news_metadata.py +0 -0
  17. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/adapters/exceptions.py +0 -0
  18. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/adapters/mart_export.py +0 -0
  19. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/adapters/models.py +0 -0
  20. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/adapters/opensearch_sql.py +0 -0
  21. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/adapters/opensearch_storage.py +0 -0
  22. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/adapters/speech_content.py +0 -0
  23. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/adapters/speech_metadata.py +0 -0
  24. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/adapters/transcription/__init__.py +0 -0
  25. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/adapters/transcription/base.py +0 -0
  26. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/adapters/transcription/config.py +0 -0
  27. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/adapters/transcription/factory.py +0 -0
  28. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/adapters/transcription/providers/__init__.py +0 -0
  29. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/adapters/transcription/providers/deepgram.py +0 -0
  30. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/adapters/transcription/providers/openai_whisper.py +0 -0
  31. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/adapters/transcription/providers/selfhosted_job.py +0 -0
  32. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/adapters/transcription/providers/youtube_captions.py +0 -0
  33. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/adapters/transcription/service.py +0 -0
  34. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/adapters/transcription/source.py +0 -0
  35. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/adapters/twitter.py +0 -0
  36. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/adapters/youtube_downloader.py +0 -0
  37. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/adapters/youtube_metadata.py +0 -0
  38. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/api/__init__.py +0 -0
  39. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/api/v1/__init__.py +0 -0
  40. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/api/v1/auth.py +0 -0
  41. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/api/v1/health.py +0 -0
  42. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/api/v1/router.py +0 -0
  43. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/cli/__init__.py +0 -0
  44. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/cli/main.py +0 -0
  45. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/cli/templates/cookiecutter.json +0 -0
  46. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/cli/templates/pulse-{{cookiecutter.product_name}}/.gitignore +0 -0
  47. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/cli/templates/pulse-{{cookiecutter.product_name}}/Dockerfile +0 -0
  48. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/cli/templates/pulse-{{cookiecutter.product_name}}/pipeline.yaml +0 -0
  49. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/cli/templates/pulse-{{cookiecutter.product_name}}/pyproject.toml +0 -0
  50. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/cli/templates/pulse-{{cookiecutter.product_name}}/src/pulse_{{cookiecutter.product_slug}}/__init__.py +0 -0
  51. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/cli/templates/pulse-{{cookiecutter.product_name}}/tests/__init__.py +0 -0
  52. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/cli/templates/pulse-{{cookiecutter.product_name}}/tests/unit/__init__.py +0 -0
  53. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/cli/templates/pulse-{{cookiecutter.product_name}}/tests/unit/test_manifest.py +0 -0
  54. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/client.py +0 -0
  55. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/config.py +0 -0
  56. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/core/__init__.py +0 -0
  57. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/core/error_handlers.py +0 -0
  58. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/core/exceptions.py +0 -0
  59. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/core/job_token.py +0 -0
  60. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/core/logging.py +0 -0
  61. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/core/scope.py +0 -0
  62. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/core/security.py +0 -0
  63. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/cron/__init__.py +0 -0
  64. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/cron/models.py +0 -0
  65. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/cron/pipeline_sync.py +0 -0
  66. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/cron/repository.py +0 -0
  67. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/cron/router.py +0 -0
  68. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/cron/runner.py +0 -0
  69. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/cron/schemas.py +0 -0
  70. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/cron/service.py +0 -0
  71. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/cron/tasks.py +0 -0
  72. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/cron/translator.py +0 -0
  73. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/database.py +0 -0
  74. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/dependencies.py +0 -0
  75. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/deployment/__init__.py +0 -0
  76. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/deployment/infra_provisioner.py +0 -0
  77. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/evolution/__init__.py +0 -0
  78. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/evolution/adapter.py +0 -0
  79. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/evolution/client.py +0 -0
  80. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/evolution/models.py +0 -0
  81. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/evolution/router.py +0 -0
  82. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/evolution/service.py +0 -0
  83. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/extractor/__init__.py +0 -0
  84. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/extractor/adapters/__init__.py +0 -0
  85. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/extractor/base.py +0 -0
  86. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/main.py +0 -0
  87. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/mcp/__init__.py +0 -0
  88. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/mcp/__main__.py +0 -0
  89. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/mcp/server.py +0 -0
  90. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/mcp/tools_kb.py +0 -0
  91. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/mcp/tools_modules.py +0 -0
  92. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/mcp/tools_pipelines.py +0 -0
  93. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/mcp/tools_processor.py +0 -0
  94. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/middleware/__init__.py +0 -0
  95. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/middleware/rate_limit.py +0 -0
  96. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/middleware/request_id.py +0 -0
  97. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/middleware/security_headers.py +0 -0
  98. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/middleware/tenant.py +0 -0
  99. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/notifications/__init__.py +0 -0
  100. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/notifications/apprise_notifier.py +0 -0
  101. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/pipeline/__init__.py +0 -0
  102. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/pipeline/config_parser.py +0 -0
  103. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/pipeline/expression.py +0 -0
  104. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/pipeline/models.py +0 -0
  105. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/pipeline/repositories.py +0 -0
  106. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/pipeline/router_modules.py +0 -0
  107. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/pipeline/router_pipelines.py +0 -0
  108. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/pipeline/schemas.py +0 -0
  109. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/pipeline/service.py +0 -0
  110. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/pipeline/translators/__init__.py +0 -0
  111. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/pipeline/translators/airflow_status.py +0 -0
  112. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/pipeline/translators/airflow_translator.py +0 -0
  113. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/pipeline/translators/base.py +0 -0
  114. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/pipeline/translators/prefect_status.py +0 -0
  115. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/pipeline/translators/prefect_translator.py +0 -0
  116. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/processor/__init__.py +0 -0
  117. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/processor/base.py +0 -0
  118. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/processor/core/__init__.py +0 -0
  119. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/processor/core/analysis.py +0 -0
  120. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/processor/core/chunking.py +0 -0
  121. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/processor/core/prompts.py +0 -0
  122. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/processor/core/topic_splitter.py +0 -0
  123. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/processor/defaults/__init__.py +0 -0
  124. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/processor/defaults/core_processor.py +0 -0
  125. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/processor/defaults/postprocessor.py +0 -0
  126. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/processor/defaults/preprocessor.py +0 -0
  127. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/processor/llm/__init__.py +0 -0
  128. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/processor/llm/provider.py +0 -0
  129. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/processor/ocr/gemini.py +0 -0
  130. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/processor/pipeline.py +0 -0
  131. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/processor/postprocessor/__init__.py +0 -0
  132. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/processor/postprocessor/embeddings.py +0 -0
  133. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/processor/postprocessor/tasks.py +0 -0
  134. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/processor/preprocessor/__init__.py +0 -0
  135. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/processor/preprocessor/tasks.py +0 -0
  136. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/processor/router.py +0 -0
  137. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/processor/schemas.py +0 -0
  138. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/registry.py +0 -0
  139. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/reporting/__init__.py +0 -0
  140. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/reporting/agent.py +0 -0
  141. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/reporting/fixtures.py +0 -0
  142. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/reporting/prompts.py +0 -0
  143. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/reporting/service.py +0 -0
  144. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/runners/__init__.py +0 -0
  145. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/runners/lambda_runner.py +0 -0
  146. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/runners/pipeline_runner.py +0 -0
  147. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/runners/prefect_pipeline_flow.py +0 -0
  148. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/runners/prefect_runner.py +0 -0
  149. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/s3.py +0 -0
  150. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/sandbox/__init__.py +0 -0
  151. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/sandbox/backend.py +0 -0
  152. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/sandbox/lambda_microvm.py +0 -0
  153. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/sandbox/microvm_agent/Dockerfile +0 -0
  154. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/sandbox/microvm_agent/__init__.py +0 -0
  155. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/sandbox/microvm_agent/server.py +0 -0
  156. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/sandbox/session.py +0 -0
  157. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/secrets.py +0 -0
  158. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/services/__init__.py +0 -0
  159. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/services/bootstrap.py +0 -0
  160. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/services/opensearch.py +0 -0
  161. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/skills/__init__.py +0 -0
  162. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/skills/catalog.py +0 -0
  163. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/skills/models.py +0 -0
  164. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/skills/repo.py +0 -0
  165. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/skills/sync.py +0 -0
  166. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/skills/tools.py +0 -0
  167. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/storage/__init__.py +0 -0
  168. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/storage/connectors/__init__.py +0 -0
  169. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/storage/connectors/athena.py +0 -0
  170. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/storage/connectors/base.py +0 -0
  171. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/storage/connectors/opensearch.py +0 -0
  172. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/storage/knowledge_base.py +0 -0
  173. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/storage/router.py +0 -0
  174. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/storage/schemas.py +0 -0
  175. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/testing/__init__.py +0 -0
  176. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/testing/fixtures.py +0 -0
  177. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/testing/mocks.py +0 -0
  178. {pulse_engine-0.2.18 → pulse_engine-0.2.19}/src/pulse_engine/worker.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pulse-engine
3
- Version: 0.2.18
3
+ Version: 0.2.19
4
4
  Summary: Pulse Engine — Hybrid framework for building Pulse products
5
5
  Author: Pulse Team
6
6
  Requires-Python: >=3.11,<3.13
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "pulse-engine"
3
- version = "0.2.18"
3
+ version = "0.2.19"
4
4
  description = "Pulse Engine — Hybrid framework for building Pulse products"
5
5
  authors = ["Pulse Team"]
6
6
  readme = "README.md"
@@ -104,9 +104,9 @@ class ReportGeneratorAdapter:
104
104
  version_number?}) pins a skill; omit it to let the engine's agent auto-select
105
105
  from the tenant's active catalog. ``marts`` (list of mart-name stems) restricts
106
106
  which staged fixtures the agent may read; omit for all. ``artifact_type``
107
- (html|pdf|docx|xlsx|pptx) pins the output format; omit to let the agent decide.
108
- The fixture source is derived from ``tenant_id`` inside the service — never
109
- caller-supplied.
107
+ (html|pdf|docx|xlsx|pptx|md) pins the output format; omit to let the agent
108
+ decide. The fixture source is derived from ``tenant_id`` inside the service —
109
+ never caller-supplied.
110
110
  """
111
111
  from pulse_engine.reporting.models import ReportRequest
112
112
 
@@ -8,7 +8,7 @@ from typing import Literal
8
8
  from pydantic import BaseModel, Field, field_validator
9
9
 
10
10
  # The artifact formats the reporting pipeline can emit (mirrors wiring._CONTENT_TYPES).
11
- ArtifactType = Literal["html", "pdf", "docx", "xlsx", "pptx"]
11
+ ArtifactType = Literal["html", "pdf", "docx", "xlsx", "pptx", "md"]
12
12
 
13
13
 
14
14
  class SkillRef(BaseModel):
@@ -38,7 +38,7 @@ class ReportRequest(BaseModel):
38
38
  # injected into the kickoff and the run fails if the agent emits a different type.
39
39
  artifact_type: ArtifactType | None = Field(
40
40
  default=None,
41
- description="Output format (html|pdf|docx|xlsx|pptx); None = agent decides",
41
+ description="Output format (html|pdf|docx|xlsx|pptx|md); None = agent decides",
42
42
  )
43
43
  # NOTE: the fixture source is derived server-side from the authenticated tenant
44
44
  # (see wiring.make_reader). It is deliberately NOT caller-supplied — accepting a
@@ -54,7 +54,7 @@ class ReportRequest(BaseModel):
54
54
 
55
55
  class ReportResult(BaseModel):
56
56
  artifact_url: str
57
- artifact_type: str # "html" (v1 default) | "pdf" | "docx" | "xlsx" | "pptx"
57
+ artifact_type: str # "html" (v1 default) | "pdf" | "docx" | "xlsx" | "pptx" | "md"
58
58
  skill_id: str
59
59
  skill_version: int | None
60
60
  tokens: int
@@ -33,7 +33,9 @@ class _WriteReportInput(BaseModel):
33
33
  path: str = Field(
34
34
  ..., description="Absolute path of the finished artifact in the sandbox"
35
35
  )
36
- artifact_type: str = Field("html", description="html | pdf | docx | xlsx | pptx")
36
+ artifact_type: str = Field(
37
+ "html", description="html | pdf | docx | xlsx | pptx | md"
38
+ )
37
39
 
38
40
 
39
41
  def build_report_tools(
@@ -46,6 +46,7 @@ _CONTENT_TYPES = {
46
46
  "pptx": (
47
47
  "application/vnd.openxmlformats-officedocument.presentationml.presentation"
48
48
  ),
49
+ "md": "text/markdown",
49
50
  }
50
51
 
51
52
 
@@ -0,0 +1,141 @@
1
+ """Idempotent seeding of the Agent Skills catalog from captured JSON snapshots.
2
+
3
+ Extracted from Alembic migration ``0017`` (see DD-0xx). The migration only ever
4
+ inserted rows if absent (``ON CONFLICT (id) DO NOTHING``), so once seeded the
5
+ catalog could never be refreshed without authoring a new migration. This seeder
6
+ **upserts** by primary key instead: re-running inserts missing rows and refreshes
7
+ existing ones, so the catalog stays current independently of schema versioning.
8
+
9
+ Schema lives in migration ``0016``; this module owns the data. The catalog is
10
+ reference content, not per-tenant data, so a single global seed is correct.
11
+
12
+ Run it with ``make seed`` or ``python -m pulse_engine.skills.seed``.
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ import json
18
+ from dataclasses import dataclass
19
+ from pathlib import Path
20
+ from typing import Any, cast
21
+
22
+ from sqlalchemy.ext.asyncio import AsyncSession
23
+
24
+ from pulse_engine.skills.models import Skill, SkillFile
25
+
26
+ # Columns each snapshot row carries (mirror migration 0017's table constructs).
27
+ # ``id`` is handled separately as the conflict key; created_at/updated_at are left
28
+ # to their server defaults / onupdate so refreshes never clobber creation time.
29
+ _SKILL_COLS = ("frontmatter", "body_content", "is_active", "visibility")
30
+ _FILE_COLS = ("skill_id", "relative_path", "s3_key", "content_type")
31
+
32
+ DEFAULT_DATA_DIR = Path(__file__).resolve().parent / "seed_data"
33
+
34
+
35
+ @dataclass
36
+ class SeedResult:
37
+ """Counts from one seed run — insufficient to be interesting, handy for logs."""
38
+
39
+ skills_inserted: int = 0
40
+ skills_updated: int = 0
41
+ files_inserted: int = 0
42
+ files_updated: int = 0
43
+
44
+
45
+ def _load(data_dir: Path, name: str) -> list[dict[str, Any]]:
46
+ return cast("list[dict[str, Any]]", json.loads((data_dir / name).read_text()))
47
+
48
+
49
+ async def _upsert(
50
+ session: AsyncSession,
51
+ model: type[Skill] | type[SkillFile],
52
+ rows: list[dict[str, Any]],
53
+ cols: tuple[str, ...],
54
+ ) -> tuple[int, int]:
55
+ """Insert-or-refresh ``rows`` by primary key; return (inserted, updated).
56
+
57
+ ORM get-then-set rather than a dialect-specific ``ON CONFLICT`` so the same
58
+ path runs on Postgres (prod) and SQLite (tests). The row count (~150) makes
59
+ per-row SELECTs irrelevant to performance. Flushes at the end so a subsequent
60
+ child upsert sees the parents (FK order).
61
+ """
62
+ inserted = updated = 0
63
+ for row in rows:
64
+ existing = await session.get(model, row["id"])
65
+ if existing is None:
66
+ session.add(model(id=row["id"], **{c: row[c] for c in cols}))
67
+ inserted += 1
68
+ else:
69
+ for c in cols:
70
+ setattr(existing, c, row[c])
71
+ updated += 1
72
+ await session.flush()
73
+ return inserted, updated
74
+
75
+
76
+ async def seed_skills(
77
+ session: AsyncSession, *, data_dir: Path = DEFAULT_DATA_DIR
78
+ ) -> SeedResult:
79
+ """Upsert the skills + skill_files catalog. Idempotent; refreshes on re-run.
80
+
81
+ Parents (``skills``) are upserted before children (``skill_files``) to satisfy
82
+ the FK. The caller owns the transaction — commit (or roll back) after this
83
+ returns. ``skill_versions`` is intentionally not seeded (empty at capture).
84
+ """
85
+ skills_inserted, skills_updated = await _upsert(
86
+ session, Skill, _load(data_dir, "skills.json"), _SKILL_COLS
87
+ )
88
+ files_inserted, files_updated = await _upsert(
89
+ session, SkillFile, _load(data_dir, "skill_files.json"), _FILE_COLS
90
+ )
91
+ return SeedResult(
92
+ skills_inserted=skills_inserted,
93
+ skills_updated=skills_updated,
94
+ files_inserted=files_inserted,
95
+ files_updated=files_updated,
96
+ )
97
+
98
+
99
+ async def _run(data_dir: Path) -> SeedResult:
100
+ from pulse_engine.config import get_settings
101
+ from pulse_engine.database import build_async_engine, build_session_factory
102
+
103
+ settings = get_settings()
104
+ if not settings.database_url:
105
+ raise SystemExit("DATABASE_URL is required to seed the skills catalog")
106
+
107
+ engine = build_async_engine(settings.database_url)
108
+ try:
109
+ maker = build_session_factory(engine)
110
+ async with maker() as session:
111
+ result = await seed_skills(session, data_dir=data_dir)
112
+ await session.commit()
113
+ return result
114
+ finally:
115
+ await engine.dispose()
116
+
117
+
118
+ def main() -> None:
119
+ import argparse
120
+ import asyncio
121
+
122
+ parser = argparse.ArgumentParser(
123
+ description="Seed/refresh the Agent Skills catalog (idempotent upsert)"
124
+ )
125
+ parser.add_argument(
126
+ "--data-dir",
127
+ type=Path,
128
+ default=DEFAULT_DATA_DIR,
129
+ help="Directory holding skills.json + skill_files.json "
130
+ f"(default: {DEFAULT_DATA_DIR})",
131
+ )
132
+ args = parser.parse_args()
133
+ result = asyncio.run(_run(args.data_dir))
134
+ print(
135
+ f"skills: +{result.skills_inserted} ~{result.skills_updated} "
136
+ f"skill_files: +{result.files_inserted} ~{result.files_updated}"
137
+ )
138
+
139
+
140
+ if __name__ == "__main__":
141
+ main()