agent-recipes 0.0.5__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 (270) hide show
  1. agent_recipes/__init__.py +27 -0
  2. agent_recipes/recipe_runtime/__init__.py +28 -0
  3. agent_recipes/recipe_runtime/core.py +385 -0
  4. agent_recipes/templates/ai-ab-hook-tester/recipe.yaml +45 -0
  5. agent_recipes/templates/ai-ab-hook-tester/tools.py +169 -0
  6. agent_recipes/templates/ai-angle-generator/recipe.yaml +49 -0
  7. agent_recipes/templates/ai-angle-generator/tools.py +182 -0
  8. agent_recipes/templates/ai-api-doc-generator/README.md +59 -0
  9. agent_recipes/templates/ai-api-doc-generator/TEMPLATE.yaml +29 -0
  10. agent_recipes/templates/ai-api-tester/README.md +60 -0
  11. agent_recipes/templates/ai-api-tester/TEMPLATE.yaml +29 -0
  12. agent_recipes/templates/ai-audio-enhancer/README.md +59 -0
  13. agent_recipes/templates/ai-audio-enhancer/TEMPLATE.yaml +28 -0
  14. agent_recipes/templates/ai-audio-normalizer/README.md +13 -0
  15. agent_recipes/templates/ai-audio-normalizer/TEMPLATE.yaml +44 -0
  16. agent_recipes/templates/ai-audio-splitter/README.md +14 -0
  17. agent_recipes/templates/ai-audio-splitter/TEMPLATE.yaml +47 -0
  18. agent_recipes/templates/ai-background-music-generator/README.md +59 -0
  19. agent_recipes/templates/ai-background-music-generator/TEMPLATE.yaml +28 -0
  20. agent_recipes/templates/ai-background-remover/README.md +60 -0
  21. agent_recipes/templates/ai-background-remover/TEMPLATE.yaml +27 -0
  22. agent_recipes/templates/ai-barcode-scanner/README.md +60 -0
  23. agent_recipes/templates/ai-barcode-scanner/TEMPLATE.yaml +26 -0
  24. agent_recipes/templates/ai-blog-generator/README.md +59 -0
  25. agent_recipes/templates/ai-blog-generator/TEMPLATE.yaml +28 -0
  26. agent_recipes/templates/ai-brief-generator/recipe.yaml +52 -0
  27. agent_recipes/templates/ai-brief-generator/tools.py +231 -0
  28. agent_recipes/templates/ai-broll-builder/recipe.yaml +47 -0
  29. agent_recipes/templates/ai-broll-builder/tools.py +204 -0
  30. agent_recipes/templates/ai-calendar-scheduler/README.md +60 -0
  31. agent_recipes/templates/ai-calendar-scheduler/TEMPLATE.yaml +29 -0
  32. agent_recipes/templates/ai-changelog-generator/README.md +14 -0
  33. agent_recipes/templates/ai-changelog-generator/TEMPLATE.yaml +46 -0
  34. agent_recipes/templates/ai-chart-generator/README.md +61 -0
  35. agent_recipes/templates/ai-chart-generator/TEMPLATE.yaml +32 -0
  36. agent_recipes/templates/ai-code-documenter/README.md +12 -0
  37. agent_recipes/templates/ai-code-documenter/TEMPLATE.yaml +37 -0
  38. agent_recipes/templates/ai-code-refactorer/README.md +59 -0
  39. agent_recipes/templates/ai-code-refactorer/TEMPLATE.yaml +28 -0
  40. agent_recipes/templates/ai-code-reviewer/README.md +59 -0
  41. agent_recipes/templates/ai-code-reviewer/TEMPLATE.yaml +31 -0
  42. agent_recipes/templates/ai-color-palette-extractor/README.md +60 -0
  43. agent_recipes/templates/ai-color-palette-extractor/TEMPLATE.yaml +27 -0
  44. agent_recipes/templates/ai-comment-miner/recipe.yaml +40 -0
  45. agent_recipes/templates/ai-comment-miner/tools.py +141 -0
  46. agent_recipes/templates/ai-commit-message-generator/README.md +59 -0
  47. agent_recipes/templates/ai-commit-message-generator/TEMPLATE.yaml +31 -0
  48. agent_recipes/templates/ai-content-calendar/recipe.yaml +43 -0
  49. agent_recipes/templates/ai-content-calendar/tools.py +170 -0
  50. agent_recipes/templates/ai-context-enricher/recipe.yaml +48 -0
  51. agent_recipes/templates/ai-context-enricher/tools.py +258 -0
  52. agent_recipes/templates/ai-contract-analyzer/README.md +60 -0
  53. agent_recipes/templates/ai-contract-analyzer/TEMPLATE.yaml +34 -0
  54. agent_recipes/templates/ai-csv-cleaner/README.md +13 -0
  55. agent_recipes/templates/ai-csv-cleaner/TEMPLATE.yaml +45 -0
  56. agent_recipes/templates/ai-cta-generator/recipe.yaml +54 -0
  57. agent_recipes/templates/ai-cta-generator/tools.py +174 -0
  58. agent_recipes/templates/ai-daily-news-show/recipe.yaml +103 -0
  59. agent_recipes/templates/ai-daily-news-show/tools.py +308 -0
  60. agent_recipes/templates/ai-data-anonymizer/README.md +60 -0
  61. agent_recipes/templates/ai-data-anonymizer/TEMPLATE.yaml +31 -0
  62. agent_recipes/templates/ai-data-profiler/README.md +14 -0
  63. agent_recipes/templates/ai-data-profiler/TEMPLATE.yaml +42 -0
  64. agent_recipes/templates/ai-dependency-auditor/README.md +12 -0
  65. agent_recipes/templates/ai-dependency-auditor/TEMPLATE.yaml +37 -0
  66. agent_recipes/templates/ai-doc-translator/README.md +12 -0
  67. agent_recipes/templates/ai-doc-translator/TEMPLATE.yaml +41 -0
  68. agent_recipes/templates/ai-duplicate-finder/README.md +59 -0
  69. agent_recipes/templates/ai-duplicate-finder/TEMPLATE.yaml +28 -0
  70. agent_recipes/templates/ai-ebook-converter/README.md +60 -0
  71. agent_recipes/templates/ai-ebook-converter/TEMPLATE.yaml +27 -0
  72. agent_recipes/templates/ai-email-parser/README.md +59 -0
  73. agent_recipes/templates/ai-email-parser/TEMPLATE.yaml +29 -0
  74. agent_recipes/templates/ai-etl-pipeline/README.md +60 -0
  75. agent_recipes/templates/ai-etl-pipeline/TEMPLATE.yaml +30 -0
  76. agent_recipes/templates/ai-excel-formula-generator/README.md +59 -0
  77. agent_recipes/templates/ai-excel-formula-generator/TEMPLATE.yaml +28 -0
  78. agent_recipes/templates/ai-face-blur/README.md +60 -0
  79. agent_recipes/templates/ai-face-blur/TEMPLATE.yaml +28 -0
  80. agent_recipes/templates/ai-fact-checker/recipe.yaml +52 -0
  81. agent_recipes/templates/ai-fact-checker/tools.py +279 -0
  82. agent_recipes/templates/ai-faq-generator/README.md +59 -0
  83. agent_recipes/templates/ai-faq-generator/TEMPLATE.yaml +28 -0
  84. agent_recipes/templates/ai-file-organizer/README.md +59 -0
  85. agent_recipes/templates/ai-file-organizer/TEMPLATE.yaml +29 -0
  86. agent_recipes/templates/ai-folder-packager/README.md +15 -0
  87. agent_recipes/templates/ai-folder-packager/TEMPLATE.yaml +48 -0
  88. agent_recipes/templates/ai-form-filler/README.md +60 -0
  89. agent_recipes/templates/ai-form-filler/TEMPLATE.yaml +30 -0
  90. agent_recipes/templates/ai-hashtag-optimizer/recipe.yaml +45 -0
  91. agent_recipes/templates/ai-hashtag-optimizer/tools.py +134 -0
  92. agent_recipes/templates/ai-hook-generator/recipe.yaml +50 -0
  93. agent_recipes/templates/ai-hook-generator/tools.py +177 -0
  94. agent_recipes/templates/ai-image-captioner/README.md +59 -0
  95. agent_recipes/templates/ai-image-captioner/TEMPLATE.yaml +28 -0
  96. agent_recipes/templates/ai-image-cataloger/README.md +13 -0
  97. agent_recipes/templates/ai-image-cataloger/TEMPLATE.yaml +39 -0
  98. agent_recipes/templates/ai-image-optimizer/README.md +13 -0
  99. agent_recipes/templates/ai-image-optimizer/TEMPLATE.yaml +43 -0
  100. agent_recipes/templates/ai-image-resizer/README.md +12 -0
  101. agent_recipes/templates/ai-image-resizer/TEMPLATE.yaml +39 -0
  102. agent_recipes/templates/ai-image-tagger/README.md +59 -0
  103. agent_recipes/templates/ai-image-tagger/TEMPLATE.yaml +28 -0
  104. agent_recipes/templates/ai-image-upscaler/README.md +60 -0
  105. agent_recipes/templates/ai-image-upscaler/TEMPLATE.yaml +27 -0
  106. agent_recipes/templates/ai-invoice-processor/README.md +60 -0
  107. agent_recipes/templates/ai-invoice-processor/TEMPLATE.yaml +34 -0
  108. agent_recipes/templates/ai-json-to-csv/README.md +12 -0
  109. agent_recipes/templates/ai-json-to-csv/TEMPLATE.yaml +36 -0
  110. agent_recipes/templates/ai-log-analyzer/README.md +59 -0
  111. agent_recipes/templates/ai-log-analyzer/TEMPLATE.yaml +28 -0
  112. agent_recipes/templates/ai-markdown-to-pdf/README.md +12 -0
  113. agent_recipes/templates/ai-markdown-to-pdf/TEMPLATE.yaml +40 -0
  114. agent_recipes/templates/ai-meeting-summarizer/README.md +59 -0
  115. agent_recipes/templates/ai-meeting-summarizer/TEMPLATE.yaml +32 -0
  116. agent_recipes/templates/ai-meta-tag-generator/README.md +59 -0
  117. agent_recipes/templates/ai-meta-tag-generator/TEMPLATE.yaml +28 -0
  118. agent_recipes/templates/ai-news-capture-pack/recipe.yaml +42 -0
  119. agent_recipes/templates/ai-news-capture-pack/tools.py +150 -0
  120. agent_recipes/templates/ai-news-crawler/recipe.yaml +99 -0
  121. agent_recipes/templates/ai-news-crawler/tools.py +417 -0
  122. agent_recipes/templates/ai-news-deduper/recipe.yaml +47 -0
  123. agent_recipes/templates/ai-news-deduper/tools.py +235 -0
  124. agent_recipes/templates/ai-newsletter-generator/README.md +59 -0
  125. agent_recipes/templates/ai-newsletter-generator/TEMPLATE.yaml +28 -0
  126. agent_recipes/templates/ai-note-summarizer/README.md +59 -0
  127. agent_recipes/templates/ai-note-summarizer/TEMPLATE.yaml +28 -0
  128. agent_recipes/templates/ai-pdf-summarizer/README.md +12 -0
  129. agent_recipes/templates/ai-pdf-summarizer/TEMPLATE.yaml +40 -0
  130. agent_recipes/templates/ai-pdf-to-markdown/README.md +19 -0
  131. agent_recipes/templates/ai-pdf-to-markdown/TEMPLATE.yaml +63 -0
  132. agent_recipes/templates/ai-performance-analyzer/recipe.yaml +45 -0
  133. agent_recipes/templates/ai-performance-analyzer/tools.py +159 -0
  134. agent_recipes/templates/ai-podcast-cleaner/README.md +117 -0
  135. agent_recipes/templates/ai-podcast-cleaner/TEMPLATE.yaml +117 -0
  136. agent_recipes/templates/ai-podcast-cleaner/agents.yaml +59 -0
  137. agent_recipes/templates/ai-podcast-cleaner/workflow.yaml +77 -0
  138. agent_recipes/templates/ai-podcast-transcriber/README.md +59 -0
  139. agent_recipes/templates/ai-podcast-transcriber/TEMPLATE.yaml +32 -0
  140. agent_recipes/templates/ai-post-copy-generator/recipe.yaml +41 -0
  141. agent_recipes/templates/ai-post-copy-generator/tools.py +105 -0
  142. agent_recipes/templates/ai-product-description-generator/README.md +59 -0
  143. agent_recipes/templates/ai-product-description-generator/TEMPLATE.yaml +28 -0
  144. agent_recipes/templates/ai-publisher-pack/recipe.yaml +44 -0
  145. agent_recipes/templates/ai-publisher-pack/tools.py +252 -0
  146. agent_recipes/templates/ai-qr-code-generator/README.md +60 -0
  147. agent_recipes/templates/ai-qr-code-generator/TEMPLATE.yaml +26 -0
  148. agent_recipes/templates/ai-regex-generator/README.md +59 -0
  149. agent_recipes/templates/ai-regex-generator/TEMPLATE.yaml +28 -0
  150. agent_recipes/templates/ai-repo-readme/README.md +13 -0
  151. agent_recipes/templates/ai-repo-readme/TEMPLATE.yaml +42 -0
  152. agent_recipes/templates/ai-report-generator/README.md +61 -0
  153. agent_recipes/templates/ai-report-generator/TEMPLATE.yaml +32 -0
  154. agent_recipes/templates/ai-resume-parser/README.md +60 -0
  155. agent_recipes/templates/ai-resume-parser/TEMPLATE.yaml +33 -0
  156. agent_recipes/templates/ai-rss-aggregator/README.md +60 -0
  157. agent_recipes/templates/ai-rss-aggregator/TEMPLATE.yaml +30 -0
  158. agent_recipes/templates/ai-schema-generator/README.md +12 -0
  159. agent_recipes/templates/ai-schema-generator/TEMPLATE.yaml +34 -0
  160. agent_recipes/templates/ai-screen-recorder/recipe.yaml +43 -0
  161. agent_recipes/templates/ai-screen-recorder/tools.py +184 -0
  162. agent_recipes/templates/ai-screenshot-capture/recipe.yaml +45 -0
  163. agent_recipes/templates/ai-screenshot-capture/tools.py +231 -0
  164. agent_recipes/templates/ai-screenshot-ocr/README.md +12 -0
  165. agent_recipes/templates/ai-screenshot-ocr/TEMPLATE.yaml +37 -0
  166. agent_recipes/templates/ai-script-writer/recipe.yaml +58 -0
  167. agent_recipes/templates/ai-script-writer/tools.py +297 -0
  168. agent_recipes/templates/ai-sentiment-analyzer/README.md +59 -0
  169. agent_recipes/templates/ai-sentiment-analyzer/TEMPLATE.yaml +28 -0
  170. agent_recipes/templates/ai-seo-optimizer/README.md +59 -0
  171. agent_recipes/templates/ai-seo-optimizer/TEMPLATE.yaml +28 -0
  172. agent_recipes/templates/ai-signal-ranker/recipe.yaml +54 -0
  173. agent_recipes/templates/ai-signal-ranker/tools.py +256 -0
  174. agent_recipes/templates/ai-sitemap-generator/README.md +59 -0
  175. agent_recipes/templates/ai-sitemap-generator/TEMPLATE.yaml +26 -0
  176. agent_recipes/templates/ai-sitemap-scraper/README.md +13 -0
  177. agent_recipes/templates/ai-sitemap-scraper/TEMPLATE.yaml +41 -0
  178. agent_recipes/templates/ai-slide-generator/README.md +60 -0
  179. agent_recipes/templates/ai-slide-generator/TEMPLATE.yaml +29 -0
  180. agent_recipes/templates/ai-slide-to-notes/README.md +12 -0
  181. agent_recipes/templates/ai-slide-to-notes/TEMPLATE.yaml +37 -0
  182. agent_recipes/templates/ai-social-media-generator/README.md +59 -0
  183. agent_recipes/templates/ai-social-media-generator/TEMPLATE.yaml +28 -0
  184. agent_recipes/templates/ai-sql-generator/README.md +59 -0
  185. agent_recipes/templates/ai-sql-generator/TEMPLATE.yaml +28 -0
  186. agent_recipes/templates/ai-subtitle-generator/README.md +59 -0
  187. agent_recipes/templates/ai-subtitle-generator/TEMPLATE.yaml +31 -0
  188. agent_recipes/templates/ai-test-generator/README.md +59 -0
  189. agent_recipes/templates/ai-test-generator/TEMPLATE.yaml +28 -0
  190. agent_recipes/templates/ai-translation-batch/README.md +59 -0
  191. agent_recipes/templates/ai-translation-batch/TEMPLATE.yaml +28 -0
  192. agent_recipes/templates/ai-url-to-markdown/README.md +14 -0
  193. agent_recipes/templates/ai-url-to-markdown/TEMPLATE.yaml +44 -0
  194. agent_recipes/templates/ai-video-chapter-generator/README.md +59 -0
  195. agent_recipes/templates/ai-video-chapter-generator/TEMPLATE.yaml +32 -0
  196. agent_recipes/templates/ai-video-compressor/README.md +59 -0
  197. agent_recipes/templates/ai-video-compressor/TEMPLATE.yaml +28 -0
  198. agent_recipes/templates/ai-video-editor/README.md +254 -0
  199. agent_recipes/templates/ai-video-editor/TEMPLATE.yaml +139 -0
  200. agent_recipes/templates/ai-video-editor/agents.yaml +36 -0
  201. agent_recipes/templates/ai-video-editor/requirements.txt +8 -0
  202. agent_recipes/templates/ai-video-editor/scripts/run.sh +10 -0
  203. agent_recipes/templates/ai-video-editor/src/ai_video_editor/__init__.py +45 -0
  204. agent_recipes/templates/ai-video-editor/src/ai_video_editor/__main__.py +8 -0
  205. agent_recipes/templates/ai-video-editor/src/ai_video_editor/__pycache__/__init__.cpython-312.pyc +0 -0
  206. agent_recipes/templates/ai-video-editor/src/ai_video_editor/__pycache__/cli.cpython-312.pyc +0 -0
  207. agent_recipes/templates/ai-video-editor/src/ai_video_editor/__pycache__/config.cpython-312.pyc +0 -0
  208. agent_recipes/templates/ai-video-editor/src/ai_video_editor/__pycache__/ffmpeg_probe.cpython-312.pyc +0 -0
  209. agent_recipes/templates/ai-video-editor/src/ai_video_editor/__pycache__/heuristics.cpython-312.pyc +0 -0
  210. agent_recipes/templates/ai-video-editor/src/ai_video_editor/__pycache__/llm_plan.cpython-312.pyc +0 -0
  211. agent_recipes/templates/ai-video-editor/src/ai_video_editor/__pycache__/models.cpython-312.pyc +0 -0
  212. agent_recipes/templates/ai-video-editor/src/ai_video_editor/__pycache__/pipeline.cpython-312.pyc +0 -0
  213. agent_recipes/templates/ai-video-editor/src/ai_video_editor/__pycache__/render.cpython-312.pyc +0 -0
  214. agent_recipes/templates/ai-video-editor/src/ai_video_editor/__pycache__/timeline.cpython-312.pyc +0 -0
  215. agent_recipes/templates/ai-video-editor/src/ai_video_editor/__pycache__/transcribe.cpython-312.pyc +0 -0
  216. agent_recipes/templates/ai-video-editor/src/ai_video_editor/__pycache__/utils.cpython-312.pyc +0 -0
  217. agent_recipes/templates/ai-video-editor/src/ai_video_editor/cli.py +343 -0
  218. agent_recipes/templates/ai-video-editor/src/ai_video_editor/config.py +102 -0
  219. agent_recipes/templates/ai-video-editor/src/ai_video_editor/ffmpeg_probe.py +92 -0
  220. agent_recipes/templates/ai-video-editor/src/ai_video_editor/heuristics.py +119 -0
  221. agent_recipes/templates/ai-video-editor/src/ai_video_editor/llm_plan.py +277 -0
  222. agent_recipes/templates/ai-video-editor/src/ai_video_editor/models.py +343 -0
  223. agent_recipes/templates/ai-video-editor/src/ai_video_editor/pipeline.py +287 -0
  224. agent_recipes/templates/ai-video-editor/src/ai_video_editor/render.py +274 -0
  225. agent_recipes/templates/ai-video-editor/src/ai_video_editor/timeline.py +278 -0
  226. agent_recipes/templates/ai-video-editor/src/ai_video_editor/transcribe.py +233 -0
  227. agent_recipes/templates/ai-video-editor/src/ai_video_editor/utils.py +222 -0
  228. agent_recipes/templates/ai-video-editor/src/input.mov +0 -0
  229. agent_recipes/templates/ai-video-editor/src/out.mp4 +0 -0
  230. agent_recipes/templates/ai-video-editor/tests/test_heuristics.py +130 -0
  231. agent_recipes/templates/ai-video-editor/tests/test_models.py +152 -0
  232. agent_recipes/templates/ai-video-editor/tests/test_timeline.py +105 -0
  233. agent_recipes/templates/ai-video-editor/workflow.yaml +51 -0
  234. agent_recipes/templates/ai-video-highlight-extractor/README.md +60 -0
  235. agent_recipes/templates/ai-video-highlight-extractor/TEMPLATE.yaml +33 -0
  236. agent_recipes/templates/ai-video-merger/recipe.yaml +40 -0
  237. agent_recipes/templates/ai-video-merger/tools.py +172 -0
  238. agent_recipes/templates/ai-video-thumbnails/README.md +16 -0
  239. agent_recipes/templates/ai-video-thumbnails/TEMPLATE.yaml +53 -0
  240. agent_recipes/templates/ai-video-to-gif/README.md +14 -0
  241. agent_recipes/templates/ai-video-to-gif/TEMPLATE.yaml +64 -0
  242. agent_recipes/templates/ai-voice-cloner/README.md +59 -0
  243. agent_recipes/templates/ai-voice-cloner/TEMPLATE.yaml +31 -0
  244. agent_recipes/templates/ai-voiceover-generator/recipe.yaml +41 -0
  245. agent_recipes/templates/ai-voiceover-generator/tools.py +194 -0
  246. agent_recipes/templates/ai-watermark-adder/README.md +59 -0
  247. agent_recipes/templates/ai-watermark-adder/TEMPLATE.yaml +26 -0
  248. agent_recipes/templates/ai-watermark-remover/README.md +60 -0
  249. agent_recipes/templates/ai-watermark-remover/TEMPLATE.yaml +32 -0
  250. agent_recipes/templates/data-transformer/README.md +75 -0
  251. agent_recipes/templates/data-transformer/TEMPLATE.yaml +63 -0
  252. agent_recipes/templates/data-transformer/agents.yaml +70 -0
  253. agent_recipes/templates/data-transformer/workflow.yaml +92 -0
  254. agent_recipes/templates/shorts-generator/README.md +61 -0
  255. agent_recipes/templates/shorts-generator/TEMPLATE.yaml +65 -0
  256. agent_recipes/templates/shorts-generator/agents.yaml +66 -0
  257. agent_recipes/templates/shorts-generator/workflow.yaml +86 -0
  258. agent_recipes/templates/transcript-generator/README.md +103 -0
  259. agent_recipes/templates/transcript-generator/TEMPLATE.yaml +57 -0
  260. agent_recipes/templates/transcript-generator/agents.yaml +62 -0
  261. agent_recipes/templates/transcript-generator/workflow.yaml +82 -0
  262. agent_recipes/templates/video-editor/README.md +70 -0
  263. agent_recipes/templates/video-editor/TEMPLATE.yaml +55 -0
  264. agent_recipes/templates/video-editor/agents.yaml +68 -0
  265. agent_recipes/templates/video-editor/workflow.yaml +92 -0
  266. agent_recipes-0.0.5.dist-info/METADATA +145 -0
  267. agent_recipes-0.0.5.dist-info/RECORD +269 -0
  268. agent_recipes-0.0.5.dist-info/WHEEL +5 -0
  269. agent_recipes-0.0.5.dist-info/top_level.txt +1 -0
  270. /236/326/177nE/243/231/214/232/265/322m/201/253/353/022C/372/321/266/b/225^=/272/017t/262/3337/310@/315wb/341pB/277z/216/330/314/004/265B/213/375/236/203/026/373/307/354z41/347#/374q/262/22589/032/276 /277/244Vh/322/017/004/224/215/004/367/377/375/335/n +0 -0
@@ -0,0 +1,27 @@
1
+ """
2
+ Agent Recipes - Real-world AI agent templates for PraisonAI
3
+
4
+ This package provides ready-to-use templates for common AI agent workflows.
5
+ """
6
+
7
+ __version__ = "0.1.0"
8
+ __all__ = ["get_template_path", "list_templates"]
9
+
10
+ from pathlib import Path
11
+
12
+
13
+ def get_template_path(template_name: str) -> Path:
14
+ """Get the path to a template directory."""
15
+ templates_dir = Path(__file__).parent / "templates"
16
+ template_path = templates_dir / template_name
17
+ if not template_path.exists():
18
+ raise ValueError(f"Template not found: {template_name}")
19
+ return template_path
20
+
21
+
22
+ def list_templates() -> list:
23
+ """List all available templates."""
24
+ templates_dir = Path(__file__).parent / "templates"
25
+ if not templates_dir.exists():
26
+ return []
27
+ return [d.name for d in templates_dir.iterdir() if d.is_dir() and not d.name.startswith(".")]
@@ -0,0 +1,28 @@
1
+ """
2
+ Recipe Runtime - Shared utilities for all Agent-Recipes.
3
+
4
+ Provides:
5
+ - Output directory management
6
+ - run.json generation
7
+ - Logging setup
8
+ - Dry-run support
9
+ - Safety defaults
10
+ """
11
+
12
+ from .core import (
13
+ RecipeRunner,
14
+ RecipeConfig,
15
+ RecipeResult,
16
+ create_output_dir,
17
+ write_run_json,
18
+ setup_logging,
19
+ )
20
+
21
+ __all__ = [
22
+ "RecipeRunner",
23
+ "RecipeConfig",
24
+ "RecipeResult",
25
+ "create_output_dir",
26
+ "write_run_json",
27
+ "setup_logging",
28
+ ]
@@ -0,0 +1,385 @@
1
+ """
2
+ Core recipe runtime utilities.
3
+
4
+ Provides the foundation for all recipe execution including:
5
+ - Output directory management with timestamps
6
+ - run.json generation and validation
7
+ - Logging setup
8
+ - Dry-run support
9
+ - Safety defaults (no overwrites, resource limits)
10
+ """
11
+
12
+ import hashlib
13
+ import json
14
+ import logging
15
+ import time
16
+ from dataclasses import dataclass, field
17
+ from datetime import datetime, timezone
18
+ from pathlib import Path
19
+ from typing import Any, Dict, List, Optional, Union
20
+
21
+ logger = logging.getLogger(__name__)
22
+
23
+
24
+ @dataclass
25
+ class RecipeConfig:
26
+ """Configuration for a recipe run."""
27
+ recipe_name: str
28
+ input_path: str
29
+ output_dir: Optional[str] = None
30
+ preset: Optional[str] = None
31
+ dry_run: bool = False
32
+ force: bool = False
33
+ verbose: bool = False
34
+ config_file: Optional[str] = None
35
+ extra: Dict[str, Any] = field(default_factory=dict)
36
+
37
+ def to_dict(self) -> Dict[str, Any]:
38
+ """Convert to dictionary for run.json."""
39
+ return {
40
+ "recipe_name": self.recipe_name,
41
+ "input_path": self.input_path,
42
+ "output_dir": self.output_dir,
43
+ "preset": self.preset,
44
+ "dry_run": self.dry_run,
45
+ "force": self.force,
46
+ "verbose": self.verbose,
47
+ **self.extra,
48
+ }
49
+
50
+
51
+ @dataclass
52
+ class OutputFile:
53
+ """Information about an output file."""
54
+ name: str
55
+ path: str
56
+ size: int
57
+ sha256: Optional[str] = None
58
+
59
+ def to_dict(self) -> Dict[str, Any]:
60
+ return {
61
+ "name": self.name,
62
+ "path": self.path,
63
+ "size": self.size,
64
+ "sha256": self.sha256,
65
+ }
66
+
67
+
68
+ @dataclass
69
+ class RecipeResult:
70
+ """Result of a recipe execution."""
71
+ recipe: str
72
+ version: str
73
+ status: str # success, failed, dry_run
74
+ started_at: str
75
+ completed_at: Optional[str] = None
76
+ input_path: str = ""
77
+ output_dir: str = ""
78
+ config: Dict[str, Any] = field(default_factory=dict)
79
+ outputs: List[OutputFile] = field(default_factory=list)
80
+ metrics: Dict[str, Any] = field(default_factory=dict)
81
+ logs: str = ""
82
+ error: Optional[str] = None
83
+
84
+ def to_dict(self) -> Dict[str, Any]:
85
+ """Convert to dictionary for run.json."""
86
+ return {
87
+ "recipe": self.recipe,
88
+ "version": self.version,
89
+ "started_at": self.started_at,
90
+ "completed_at": self.completed_at,
91
+ "status": self.status,
92
+ "input": self.input_path,
93
+ "output_dir": self.output_dir,
94
+ "config": self.config,
95
+ "outputs": [o.to_dict() for o in self.outputs],
96
+ "metrics": self.metrics,
97
+ "logs": self.logs,
98
+ "error": self.error,
99
+ }
100
+
101
+
102
+ def get_timestamp() -> str:
103
+ """Get current timestamp in ISO 8601 format."""
104
+ return datetime.now(timezone.utc).isoformat()
105
+
106
+
107
+ def get_timestamp_dir() -> str:
108
+ """Get timestamp string for directory naming."""
109
+ return datetime.now().strftime("%Y%m%d-%H%M%S")
110
+
111
+
112
+ def create_output_dir(
113
+ recipe_name: str,
114
+ base_dir: Optional[Union[str, Path]] = None,
115
+ force: bool = False,
116
+ ) -> Path:
117
+ """
118
+ Create output directory for a recipe run.
119
+
120
+ Args:
121
+ recipe_name: Name of the recipe
122
+ base_dir: Base output directory (default: ./outputs)
123
+ force: Allow overwriting existing directory
124
+
125
+ Returns:
126
+ Path to created output directory
127
+ """
128
+ if base_dir is None:
129
+ base_dir = Path("./outputs")
130
+ else:
131
+ base_dir = Path(base_dir)
132
+
133
+ # Create timestamped directory
134
+ timestamp = get_timestamp_dir()
135
+ output_dir = base_dir / recipe_name / timestamp
136
+
137
+ if output_dir.exists() and not force:
138
+ raise FileExistsError(
139
+ f"Output directory already exists: {output_dir}. "
140
+ "Use --force to overwrite."
141
+ )
142
+
143
+ output_dir.mkdir(parents=True, exist_ok=True)
144
+ return output_dir
145
+
146
+
147
+ def calculate_sha256(path: Path) -> str:
148
+ """Calculate SHA256 hash of a file."""
149
+ sha256 = hashlib.sha256()
150
+ with open(path, "rb") as f:
151
+ for chunk in iter(lambda: f.read(8192), b""):
152
+ sha256.update(chunk)
153
+ return sha256.hexdigest()
154
+
155
+
156
+ def collect_outputs(output_dir: Path, include_hash: bool = True) -> List[OutputFile]:
157
+ """
158
+ Collect information about output files.
159
+
160
+ Args:
161
+ output_dir: Output directory to scan
162
+ include_hash: Calculate SHA256 hashes
163
+
164
+ Returns:
165
+ List of OutputFile objects
166
+ """
167
+ outputs = []
168
+
169
+ for path in output_dir.rglob("*"):
170
+ if path.is_file() and path.name != "run.json" and path.name != "run.log":
171
+ rel_path = path.relative_to(output_dir)
172
+ sha256 = calculate_sha256(path) if include_hash else None
173
+
174
+ outputs.append(OutputFile(
175
+ name=path.name,
176
+ path=str(rel_path),
177
+ size=path.stat().st_size,
178
+ sha256=sha256,
179
+ ))
180
+
181
+ return outputs
182
+
183
+
184
+ def write_run_json(
185
+ output_dir: Path,
186
+ result: RecipeResult,
187
+ ) -> Path:
188
+ """
189
+ Write run.json to output directory.
190
+
191
+ Args:
192
+ output_dir: Output directory
193
+ result: Recipe result
194
+
195
+ Returns:
196
+ Path to run.json
197
+ """
198
+ run_json_path = output_dir / "run.json"
199
+
200
+ with open(run_json_path, "w", encoding="utf-8") as f:
201
+ json.dump(result.to_dict(), f, indent=2)
202
+
203
+ return run_json_path
204
+
205
+
206
+ def setup_logging(
207
+ output_dir: Path,
208
+ verbose: bool = False,
209
+ ) -> Path:
210
+ """
211
+ Setup logging for a recipe run.
212
+
213
+ Args:
214
+ output_dir: Output directory for log file
215
+ verbose: Enable verbose logging
216
+
217
+ Returns:
218
+ Path to log file
219
+ """
220
+ log_path = output_dir / "run.log"
221
+
222
+ # Configure logging
223
+ level = logging.DEBUG if verbose else logging.INFO
224
+
225
+ # Create file handler
226
+ file_handler = logging.FileHandler(log_path)
227
+ file_handler.setLevel(level)
228
+ file_handler.setFormatter(logging.Formatter(
229
+ "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
230
+ ))
231
+
232
+ # Add to root logger
233
+ root_logger = logging.getLogger()
234
+ root_logger.addHandler(file_handler)
235
+
236
+ if verbose:
237
+ root_logger.setLevel(logging.DEBUG)
238
+
239
+ return log_path
240
+
241
+
242
+ class RecipeRunner:
243
+ """
244
+ Base class for running recipes with standard safety defaults.
245
+
246
+ Handles:
247
+ - Output directory creation
248
+ - run.json generation
249
+ - Logging
250
+ - Dry-run mode
251
+ - Error handling
252
+ """
253
+
254
+ def __init__(
255
+ self,
256
+ recipe_name: str,
257
+ version: str = "1.0.0",
258
+ ):
259
+ self.recipe_name = recipe_name
260
+ self.version = version
261
+ self._start_time: Optional[float] = None
262
+ self._result: Optional[RecipeResult] = None
263
+ self._output_dir: Optional[Path] = None
264
+ self._log_path: Optional[Path] = None
265
+
266
+ def run(self, config: RecipeConfig) -> RecipeResult:
267
+ """
268
+ Execute the recipe with the given configuration.
269
+
270
+ Args:
271
+ config: Recipe configuration
272
+
273
+ Returns:
274
+ RecipeResult with execution details
275
+ """
276
+ self._start_time = time.time()
277
+ started_at = get_timestamp()
278
+
279
+ # Initialize result
280
+ self._result = RecipeResult(
281
+ recipe=self.recipe_name,
282
+ version=self.version,
283
+ status="running",
284
+ started_at=started_at,
285
+ input_path=config.input_path,
286
+ config=config.to_dict(),
287
+ )
288
+
289
+ try:
290
+ # Validate input
291
+ self._validate_input(config)
292
+
293
+ # Create output directory
294
+ if config.output_dir:
295
+ self._output_dir = Path(config.output_dir)
296
+ self._output_dir.mkdir(parents=True, exist_ok=config.force)
297
+ else:
298
+ self._output_dir = create_output_dir(
299
+ self.recipe_name,
300
+ force=config.force,
301
+ )
302
+
303
+ self._result.output_dir = str(self._output_dir)
304
+
305
+ # Setup logging
306
+ self._log_path = setup_logging(self._output_dir, config.verbose)
307
+ self._result.logs = str(self._log_path)
308
+
309
+ logger.info(f"Starting recipe: {self.recipe_name}")
310
+ logger.info(f"Input: {config.input_path}")
311
+ logger.info(f"Output: {self._output_dir}")
312
+
313
+ if config.dry_run:
314
+ # Dry run - just plan, don't execute
315
+ self._result.status = "dry_run"
316
+ logger.info("DRY RUN - no files will be created")
317
+ self._plan(config)
318
+ else:
319
+ # Execute the recipe
320
+ self._execute(config)
321
+
322
+ # Collect outputs
323
+ self._result.outputs = collect_outputs(self._output_dir)
324
+ self._result.status = "success"
325
+
326
+ except Exception as e:
327
+ self._result.status = "failed"
328
+ self._result.error = str(e)
329
+ logger.exception(f"Recipe failed: {e}")
330
+ raise
331
+
332
+ finally:
333
+ # Finalize result
334
+ self._result.completed_at = get_timestamp()
335
+
336
+ # Calculate metrics
337
+ duration = time.time() - self._start_time
338
+ self._result.metrics = {
339
+ "duration_sec": round(duration, 2),
340
+ }
341
+
342
+ # Write run.json
343
+ if self._output_dir:
344
+ write_run_json(self._output_dir, self._result)
345
+
346
+ return self._result
347
+
348
+ def _validate_input(self, config: RecipeConfig) -> None:
349
+ """Validate input path exists."""
350
+ input_path = Path(config.input_path)
351
+
352
+ # Allow URLs
353
+ if config.input_path.startswith(("http://", "https://")):
354
+ return
355
+
356
+ if not input_path.exists():
357
+ raise FileNotFoundError(f"Input not found: {config.input_path}")
358
+
359
+ def _plan(self, config: RecipeConfig) -> None:
360
+ """
361
+ Plan the recipe execution (for dry-run).
362
+
363
+ Override in subclasses to provide planning output.
364
+ """
365
+ logger.info("Planning recipe execution...")
366
+ logger.info(f"Would process: {config.input_path}")
367
+ logger.info(f"Would output to: {self._output_dir}")
368
+
369
+ def _execute(self, config: RecipeConfig) -> None:
370
+ """
371
+ Execute the recipe.
372
+
373
+ Override in subclasses to implement recipe logic.
374
+ """
375
+ raise NotImplementedError("Subclasses must implement _execute()")
376
+
377
+ @property
378
+ def output_dir(self) -> Optional[Path]:
379
+ """Get the output directory."""
380
+ return self._output_dir
381
+
382
+ @property
383
+ def result(self) -> Optional[RecipeResult]:
384
+ """Get the current result."""
385
+ return self._result
@@ -0,0 +1,45 @@
1
+ name: ai-ab-hook-tester
2
+ version: 1.0.0
3
+ description: Generate A/B test variants for hooks with tracking plan
4
+ author: PraisonAI
5
+ tags:
6
+ - testing
7
+ - ab-test
8
+ - hooks
9
+ - optimization
10
+
11
+ config:
12
+ num_variants: 3
13
+ test_duration_days: 7
14
+ metrics_to_track:
15
+ - ctr
16
+ - watch_time
17
+ - engagement
18
+
19
+ input:
20
+ type: object
21
+ properties:
22
+ original_hook:
23
+ type: string
24
+ topic:
25
+ type: string
26
+
27
+ output:
28
+ type: object
29
+ properties:
30
+ variants:
31
+ type: array
32
+ tracking_plan:
33
+ type: object
34
+
35
+ requires:
36
+ env:
37
+ - OPENAI_API_KEY
38
+
39
+ workflow:
40
+ agents:
41
+ - name: ab_tester
42
+ role: A/B Test Specialist
43
+ tools:
44
+ - generate_test_variants
45
+ - create_tracking_plan
@@ -0,0 +1,169 @@
1
+ """
2
+ AI A/B Hook Tester Tools
3
+
4
+ Generate test variants and tracking plans for hook optimization.
5
+ """
6
+
7
+ import logging
8
+ import os
9
+ from datetime import datetime, timedelta, timezone
10
+ from typing import Any, Dict, List
11
+
12
+ logger = logging.getLogger(__name__)
13
+
14
+
15
+ def call_llm(prompt: str, max_tokens: int = 600) -> str:
16
+ """Call OpenAI API."""
17
+ import requests
18
+ api_key = os.environ.get("OPENAI_API_KEY")
19
+ if not api_key:
20
+ raise ValueError("OPENAI_API_KEY not set")
21
+ response = requests.post(
22
+ "https://api.openai.com/v1/chat/completions",
23
+ headers={"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"},
24
+ json={"model": "gpt-4o-mini", "messages": [{"role": "user", "content": prompt}], "max_tokens": max_tokens},
25
+ timeout=60,
26
+ )
27
+ response.raise_for_status()
28
+ return response.json()["choices"][0]["message"]["content"]
29
+
30
+
31
+ def generate_test_variants(
32
+ original_hook: str,
33
+ topic: str,
34
+ num_variants: int = 3,
35
+ ) -> Dict[str, Any]:
36
+ """
37
+ Generate A/B test variants for a hook.
38
+
39
+ Args:
40
+ original_hook: Original hook text
41
+ topic: Content topic
42
+ num_variants: Number of variants to generate
43
+
44
+ Returns:
45
+ Dictionary with variants
46
+ """
47
+ prompt = f"""Create {num_variants} A/B test variants for this video hook:
48
+
49
+ Original Hook: "{original_hook}"
50
+ Topic: {topic}
51
+
52
+ For each variant:
53
+ 1. Use a different psychological trigger (curiosity, fear, benefit, controversy)
54
+ 2. Keep it under 15 words
55
+ 3. Make it distinctly different from the original
56
+
57
+ Format each variant as:
58
+ VARIANT [number]: [hook text]
59
+ TRIGGER: [psychological trigger used]
60
+ HYPOTHESIS: [why this might perform better]"""
61
+
62
+ try:
63
+ result = call_llm(prompt, max_tokens=500)
64
+
65
+ variants = []
66
+ current_variant = {}
67
+
68
+ for line in result.split("\n"):
69
+ line = line.strip()
70
+ if line.startswith("VARIANT"):
71
+ if current_variant:
72
+ variants.append(current_variant)
73
+ current_variant = {"text": line.split(":", 1)[-1].strip()}
74
+ elif line.startswith("TRIGGER:"):
75
+ current_variant["trigger"] = line.split(":", 1)[-1].strip()
76
+ elif line.startswith("HYPOTHESIS:"):
77
+ current_variant["hypothesis"] = line.split(":", 1)[-1].strip()
78
+
79
+ if current_variant:
80
+ variants.append(current_variant)
81
+
82
+ # Add control (original)
83
+ all_variants = [
84
+ {"text": original_hook, "trigger": "control", "hypothesis": "Original baseline"}
85
+ ] + variants[:num_variants]
86
+
87
+ return {
88
+ "variants": all_variants,
89
+ "original": original_hook,
90
+ "total_variants": len(all_variants),
91
+ }
92
+ except Exception as e:
93
+ logger.error(f"Error generating variants: {e}")
94
+ return {"error": str(e)}
95
+
96
+
97
+ def create_tracking_plan(
98
+ variants: List[Dict[str, Any]],
99
+ test_duration_days: int = 7,
100
+ metrics: List[str] = None,
101
+ ) -> Dict[str, Any]:
102
+ """
103
+ Create a tracking plan for A/B test.
104
+
105
+ Args:
106
+ variants: List of variant dictionaries
107
+ test_duration_days: Test duration in days
108
+ metrics: Metrics to track
109
+
110
+ Returns:
111
+ Tracking plan
112
+ """
113
+ metrics = metrics or ["ctr", "watch_time", "engagement"]
114
+
115
+ start_date = datetime.now(timezone.utc)
116
+ end_date = start_date + timedelta(days=test_duration_days)
117
+
118
+ tracking_plan = {
119
+ "test_id": f"ab_test_{start_date.strftime('%Y%m%d_%H%M%S')}",
120
+ "start_date": start_date.isoformat(),
121
+ "end_date": end_date.isoformat(),
122
+ "duration_days": test_duration_days,
123
+ "variants": [
124
+ {
125
+ "id": f"variant_{i}",
126
+ "text": v.get("text", ""),
127
+ "trigger": v.get("trigger", ""),
128
+ }
129
+ for i, v in enumerate(variants)
130
+ ],
131
+ "metrics": {
132
+ m: {"description": _get_metric_description(m), "target": _get_metric_target(m)}
133
+ for m in metrics
134
+ },
135
+ "sample_size_per_variant": 1000,
136
+ "statistical_significance": 0.95,
137
+ "instructions": [
138
+ "Run each variant for equal time/impressions",
139
+ "Track all specified metrics",
140
+ "Wait for statistical significance before declaring winner",
141
+ "Document any external factors that might affect results",
142
+ ],
143
+ }
144
+
145
+ return {"tracking_plan": tracking_plan}
146
+
147
+
148
+ def _get_metric_description(metric: str) -> str:
149
+ """Get description for a metric."""
150
+ descriptions = {
151
+ "ctr": "Click-through rate from thumbnail/title",
152
+ "watch_time": "Average watch time in seconds",
153
+ "engagement": "Likes + comments + shares",
154
+ "retention": "Percentage of video watched",
155
+ "conversion": "Desired action completion rate",
156
+ }
157
+ return descriptions.get(metric, metric)
158
+
159
+
160
+ def _get_metric_target(metric: str) -> str:
161
+ """Get target for a metric."""
162
+ targets = {
163
+ "ctr": ">5%",
164
+ "watch_time": ">60 seconds",
165
+ "engagement": ">3%",
166
+ "retention": ">50%",
167
+ "conversion": ">2%",
168
+ }
169
+ return targets.get(metric, "improve over control")
@@ -0,0 +1,49 @@
1
+ name: ai-angle-generator
2
+ version: 1.0.0
3
+ description: Generate multiple content angles for a topic - controversial, educational, business, risk, future prediction
4
+ author: PraisonAI
5
+ tags:
6
+ - content
7
+ - angles
8
+ - strategy
9
+ - ideation
10
+
11
+ config:
12
+ angle_types:
13
+ - controversial
14
+ - educational
15
+ - business
16
+ - risk
17
+ - future_prediction
18
+ - personal_story
19
+ - comparison
20
+ num_angles: 5
21
+
22
+ input:
23
+ type: object
24
+ properties:
25
+ topic:
26
+ type: string
27
+ angle_types:
28
+ type: array
29
+ num_angles:
30
+ type: integer
31
+
32
+ output:
33
+ type: object
34
+ properties:
35
+ angles:
36
+ type: array
37
+
38
+ requires:
39
+ env:
40
+ - OPENAI_API_KEY
41
+
42
+ workflow:
43
+ agents:
44
+ - name: angle_generator
45
+ role: Content Strategist
46
+ goal: Generate diverse content angles
47
+ tools:
48
+ - generate_angles
49
+ - evaluate_angles