provekit 0.1.0__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 (518) hide show
  1. provekit-0.1.0/PKG-INFO +86 -0
  2. provekit-0.1.0/README.md +47 -0
  3. provekit-0.1.0/provekit/__init__.py +0 -0
  4. provekit-0.1.0/provekit/cli.py +256 -0
  5. provekit-0.1.0/provekit/config.py +77 -0
  6. provekit-0.1.0/provekit/database.py +132 -0
  7. provekit-0.1.0/provekit/main.py +115 -0
  8. provekit-0.1.0/provekit/migrations/env.py +40 -0
  9. provekit-0.1.0/provekit/migrations/script.py.mako +22 -0
  10. provekit-0.1.0/provekit/migrations/versions/323eb73d463c_user_email_verified.py +32 -0
  11. provekit-0.1.0/provekit/migrations/versions/49e8ab812556_baseline_schema.py +241 -0
  12. provekit-0.1.0/provekit/migrations/versions/819ed5ff183e_workspace_ingest_key.py +35 -0
  13. provekit-0.1.0/provekit/migrations/versions/a1b2c3d4e5f6_user_token_version.py +27 -0
  14. provekit-0.1.0/provekit/models.py +191 -0
  15. provekit-0.1.0/provekit/observability.py +154 -0
  16. provekit-0.1.0/provekit/routers/__init__.py +0 -0
  17. provekit-0.1.0/provekit/routers/auth.py +150 -0
  18. provekit-0.1.0/provekit/routers/connections.py +270 -0
  19. provekit-0.1.0/provekit/routers/deployments.py +161 -0
  20. provekit-0.1.0/provekit/routers/flows.py +188 -0
  21. provekit-0.1.0/provekit/routers/library.py +265 -0
  22. provekit-0.1.0/provekit/routers/prompts.py +72 -0
  23. provekit-0.1.0/provekit/routers/run.py +203 -0
  24. provekit-0.1.0/provekit/routers/runtime.py +103 -0
  25. provekit-0.1.0/provekit/routers/traces.py +65 -0
  26. provekit-0.1.0/provekit/routers/usage.py +42 -0
  27. provekit-0.1.0/provekit/services/__init__.py +0 -0
  28. provekit-0.1.0/provekit/services/assertions.py +135 -0
  29. provekit-0.1.0/provekit/services/auth.py +131 -0
  30. provekit-0.1.0/provekit/services/deploy.py +63 -0
  31. provekit-0.1.0/provekit/services/dispatch.py +313 -0
  32. provekit-0.1.0/provekit/services/email.py +38 -0
  33. provekit-0.1.0/provekit/services/flow.py +299 -0
  34. provekit-0.1.0/provekit/services/limits.py +109 -0
  35. provekit-0.1.0/provekit/services/masking.py +45 -0
  36. provekit-0.1.0/provekit/services/netguard.py +69 -0
  37. provekit-0.1.0/provekit/services/otel.py +146 -0
  38. provekit-0.1.0/provekit/services/promptfoo.py +92 -0
  39. provekit-0.1.0/provekit/services/providers/__init__.py +0 -0
  40. provekit-0.1.0/provekit/services/providers/a2a_client.py +110 -0
  41. provekit-0.1.0/provekit/services/providers/agent_http.py +55 -0
  42. provekit-0.1.0/provekit/services/providers/llm.py +364 -0
  43. provekit-0.1.0/provekit/services/providers/mcp_client.py +289 -0
  44. provekit-0.1.0/provekit/services/runstore.py +93 -0
  45. provekit-0.1.0/provekit/services/sealing.py +106 -0
  46. provekit-0.1.0/provekit/services/templates.py +69 -0
  47. provekit-0.1.0/provekit/services/testfile.py +122 -0
  48. provekit-0.1.0/provekit/services/tooling.py +194 -0
  49. provekit-0.1.0/provekit/services/workspace.py +91 -0
  50. provekit-0.1.0/provekit/templates/flows/_manifest.json +2594 -0
  51. provekit-0.1.0/provekit/templates/flows/banking-action-items.yaml +43 -0
  52. provekit-0.1.0/provekit/templates/flows/banking-answer.yaml +43 -0
  53. provekit-0.1.0/provekit/templates/flows/banking-classify-intent.yaml +43 -0
  54. provekit-0.1.0/provekit/templates/flows/banking-draft-critique-revise.yaml +75 -0
  55. provekit-0.1.0/provekit/templates/flows/banking-extract-to-json.yaml +43 -0
  56. provekit-0.1.0/provekit/templates/flows/banking-faq-match-answer.yaml +60 -0
  57. provekit-0.1.0/provekit/templates/flows/banking-keyword-extract.yaml +43 -0
  58. provekit-0.1.0/provekit/templates/flows/banking-language-route.yaml +103 -0
  59. provekit-0.1.0/provekit/templates/flows/banking-moderation-gate.yaml +73 -0
  60. provekit-0.1.0/provekit/templates/flows/banking-redact-summarize.yaml +59 -0
  61. provekit-0.1.0/provekit/templates/flows/banking-score-gate.yaml +73 -0
  62. provekit-0.1.0/provekit/templates/flows/banking-sentiment-route.yaml +73 -0
  63. provekit-0.1.0/provekit/templates/flows/banking-severity-tiers.yaml +103 -0
  64. provekit-0.1.0/provekit/templates/flows/banking-summarize-then-decide.yaml +88 -0
  65. provekit-0.1.0/provekit/templates/flows/banking-tag-enrich.yaml +43 -0
  66. provekit-0.1.0/provekit/templates/flows/banking-tone-rewrite.yaml +43 -0
  67. provekit-0.1.0/provekit/templates/flows/banking-translate-reply.yaml +58 -0
  68. provekit-0.1.0/provekit/templates/flows/banking-triage-route.yaml +73 -0
  69. provekit-0.1.0/provekit/templates/flows/community-forum-action-items.yaml +43 -0
  70. provekit-0.1.0/provekit/templates/flows/community-forum-answer.yaml +43 -0
  71. provekit-0.1.0/provekit/templates/flows/community-forum-classify-intent.yaml +43 -0
  72. provekit-0.1.0/provekit/templates/flows/community-forum-draft-critique-revise.yaml +75 -0
  73. provekit-0.1.0/provekit/templates/flows/community-forum-extract-to-json.yaml +43 -0
  74. provekit-0.1.0/provekit/templates/flows/community-forum-faq-match-answer.yaml +60 -0
  75. provekit-0.1.0/provekit/templates/flows/community-forum-keyword-extract.yaml +43 -0
  76. provekit-0.1.0/provekit/templates/flows/community-forum-language-route.yaml +103 -0
  77. provekit-0.1.0/provekit/templates/flows/community-forum-moderation-gate.yaml +73 -0
  78. provekit-0.1.0/provekit/templates/flows/community-forum-redact-summarize.yaml +59 -0
  79. provekit-0.1.0/provekit/templates/flows/community-forum-score-gate.yaml +73 -0
  80. provekit-0.1.0/provekit/templates/flows/community-forum-sentiment-route.yaml +73 -0
  81. provekit-0.1.0/provekit/templates/flows/community-forum-severity-tiers.yaml +103 -0
  82. provekit-0.1.0/provekit/templates/flows/community-forum-summarize-then-decide.yaml +88 -0
  83. provekit-0.1.0/provekit/templates/flows/community-forum-tag-enrich.yaml +43 -0
  84. provekit-0.1.0/provekit/templates/flows/community-forum-tone-rewrite.yaml +43 -0
  85. provekit-0.1.0/provekit/templates/flows/community-forum-translate-reply.yaml +58 -0
  86. provekit-0.1.0/provekit/templates/flows/community-forum-triage-route.yaml +73 -0
  87. provekit-0.1.0/provekit/templates/flows/content-moderation-action-items.yaml +43 -0
  88. provekit-0.1.0/provekit/templates/flows/content-moderation-answer.yaml +43 -0
  89. provekit-0.1.0/provekit/templates/flows/content-moderation-classify-intent.yaml +43 -0
  90. provekit-0.1.0/provekit/templates/flows/content-moderation-draft-critique-revise.yaml +75 -0
  91. provekit-0.1.0/provekit/templates/flows/content-moderation-extract-to-json.yaml +43 -0
  92. provekit-0.1.0/provekit/templates/flows/content-moderation-faq-match-answer.yaml +60 -0
  93. provekit-0.1.0/provekit/templates/flows/content-moderation-keyword-extract.yaml +43 -0
  94. provekit-0.1.0/provekit/templates/flows/content-moderation-language-route.yaml +103 -0
  95. provekit-0.1.0/provekit/templates/flows/content-moderation-moderation-gate.yaml +73 -0
  96. provekit-0.1.0/provekit/templates/flows/content-moderation-redact-summarize.yaml +59 -0
  97. provekit-0.1.0/provekit/templates/flows/content-moderation-score-gate.yaml +73 -0
  98. provekit-0.1.0/provekit/templates/flows/content-moderation-sentiment-route.yaml +73 -0
  99. provekit-0.1.0/provekit/templates/flows/content-moderation-severity-tiers.yaml +103 -0
  100. provekit-0.1.0/provekit/templates/flows/content-moderation-summarize-then-decide.yaml +88 -0
  101. provekit-0.1.0/provekit/templates/flows/content-moderation-tag-enrich.yaml +43 -0
  102. provekit-0.1.0/provekit/templates/flows/content-moderation-tone-rewrite.yaml +43 -0
  103. provekit-0.1.0/provekit/templates/flows/content-moderation-translate-reply.yaml +58 -0
  104. provekit-0.1.0/provekit/templates/flows/content-moderation-triage-route.yaml +73 -0
  105. provekit-0.1.0/provekit/templates/flows/customer-support-action-items.yaml +43 -0
  106. provekit-0.1.0/provekit/templates/flows/customer-support-answer.yaml +43 -0
  107. provekit-0.1.0/provekit/templates/flows/customer-support-classify-intent.yaml +43 -0
  108. provekit-0.1.0/provekit/templates/flows/customer-support-draft-critique-revise.yaml +75 -0
  109. provekit-0.1.0/provekit/templates/flows/customer-support-extract-to-json.yaml +43 -0
  110. provekit-0.1.0/provekit/templates/flows/customer-support-faq-match-answer.yaml +60 -0
  111. provekit-0.1.0/provekit/templates/flows/customer-support-keyword-extract.yaml +43 -0
  112. provekit-0.1.0/provekit/templates/flows/customer-support-language-route.yaml +103 -0
  113. provekit-0.1.0/provekit/templates/flows/customer-support-moderation-gate.yaml +73 -0
  114. provekit-0.1.0/provekit/templates/flows/customer-support-redact-summarize.yaml +59 -0
  115. provekit-0.1.0/provekit/templates/flows/customer-support-score-gate.yaml +73 -0
  116. provekit-0.1.0/provekit/templates/flows/customer-support-sentiment-route.yaml +73 -0
  117. provekit-0.1.0/provekit/templates/flows/customer-support-severity-tiers.yaml +103 -0
  118. provekit-0.1.0/provekit/templates/flows/customer-support-summarize-then-decide.yaml +88 -0
  119. provekit-0.1.0/provekit/templates/flows/customer-support-tag-enrich.yaml +43 -0
  120. provekit-0.1.0/provekit/templates/flows/customer-support-tone-rewrite.yaml +43 -0
  121. provekit-0.1.0/provekit/templates/flows/customer-support-translate-reply.yaml +58 -0
  122. provekit-0.1.0/provekit/templates/flows/customer-support-triage-route.yaml +73 -0
  123. provekit-0.1.0/provekit/templates/flows/developer-tooling-action-items.yaml +43 -0
  124. provekit-0.1.0/provekit/templates/flows/developer-tooling-answer.yaml +43 -0
  125. provekit-0.1.0/provekit/templates/flows/developer-tooling-classify-intent.yaml +43 -0
  126. provekit-0.1.0/provekit/templates/flows/developer-tooling-draft-critique-revise.yaml +75 -0
  127. provekit-0.1.0/provekit/templates/flows/developer-tooling-extract-to-json.yaml +43 -0
  128. provekit-0.1.0/provekit/templates/flows/developer-tooling-faq-match-answer.yaml +60 -0
  129. provekit-0.1.0/provekit/templates/flows/developer-tooling-keyword-extract.yaml +43 -0
  130. provekit-0.1.0/provekit/templates/flows/developer-tooling-language-route.yaml +103 -0
  131. provekit-0.1.0/provekit/templates/flows/developer-tooling-moderation-gate.yaml +73 -0
  132. provekit-0.1.0/provekit/templates/flows/developer-tooling-redact-summarize.yaml +59 -0
  133. provekit-0.1.0/provekit/templates/flows/developer-tooling-score-gate.yaml +73 -0
  134. provekit-0.1.0/provekit/templates/flows/developer-tooling-sentiment-route.yaml +73 -0
  135. provekit-0.1.0/provekit/templates/flows/developer-tooling-severity-tiers.yaml +103 -0
  136. provekit-0.1.0/provekit/templates/flows/developer-tooling-summarize-then-decide.yaml +88 -0
  137. provekit-0.1.0/provekit/templates/flows/developer-tooling-tag-enrich.yaml +43 -0
  138. provekit-0.1.0/provekit/templates/flows/developer-tooling-tone-rewrite.yaml +43 -0
  139. provekit-0.1.0/provekit/templates/flows/developer-tooling-translate-reply.yaml +58 -0
  140. provekit-0.1.0/provekit/templates/flows/developer-tooling-triage-route.yaml +73 -0
  141. provekit-0.1.0/provekit/templates/flows/devrel-action-items.yaml +43 -0
  142. provekit-0.1.0/provekit/templates/flows/devrel-answer.yaml +43 -0
  143. provekit-0.1.0/provekit/templates/flows/devrel-classify-intent.yaml +43 -0
  144. provekit-0.1.0/provekit/templates/flows/devrel-draft-critique-revise.yaml +75 -0
  145. provekit-0.1.0/provekit/templates/flows/devrel-extract-to-json.yaml +43 -0
  146. provekit-0.1.0/provekit/templates/flows/devrel-faq-match-answer.yaml +60 -0
  147. provekit-0.1.0/provekit/templates/flows/devrel-keyword-extract.yaml +43 -0
  148. provekit-0.1.0/provekit/templates/flows/devrel-language-route.yaml +103 -0
  149. provekit-0.1.0/provekit/templates/flows/devrel-moderation-gate.yaml +73 -0
  150. provekit-0.1.0/provekit/templates/flows/devrel-redact-summarize.yaml +59 -0
  151. provekit-0.1.0/provekit/templates/flows/devrel-score-gate.yaml +73 -0
  152. provekit-0.1.0/provekit/templates/flows/devrel-sentiment-route.yaml +73 -0
  153. provekit-0.1.0/provekit/templates/flows/devrel-severity-tiers.yaml +103 -0
  154. provekit-0.1.0/provekit/templates/flows/devrel-summarize-then-decide.yaml +88 -0
  155. provekit-0.1.0/provekit/templates/flows/devrel-tag-enrich.yaml +43 -0
  156. provekit-0.1.0/provekit/templates/flows/devrel-tone-rewrite.yaml +43 -0
  157. provekit-0.1.0/provekit/templates/flows/devrel-translate-reply.yaml +58 -0
  158. provekit-0.1.0/provekit/templates/flows/devrel-triage-route.yaml +73 -0
  159. provekit-0.1.0/provekit/templates/flows/e-commerce-action-items.yaml +43 -0
  160. provekit-0.1.0/provekit/templates/flows/e-commerce-answer.yaml +43 -0
  161. provekit-0.1.0/provekit/templates/flows/e-commerce-classify-intent.yaml +43 -0
  162. provekit-0.1.0/provekit/templates/flows/e-commerce-draft-critique-revise.yaml +75 -0
  163. provekit-0.1.0/provekit/templates/flows/e-commerce-extract-to-json.yaml +43 -0
  164. provekit-0.1.0/provekit/templates/flows/e-commerce-faq-match-answer.yaml +60 -0
  165. provekit-0.1.0/provekit/templates/flows/e-commerce-keyword-extract.yaml +43 -0
  166. provekit-0.1.0/provekit/templates/flows/e-commerce-language-route.yaml +103 -0
  167. provekit-0.1.0/provekit/templates/flows/e-commerce-moderation-gate.yaml +73 -0
  168. provekit-0.1.0/provekit/templates/flows/e-commerce-redact-summarize.yaml +59 -0
  169. provekit-0.1.0/provekit/templates/flows/e-commerce-score-gate.yaml +73 -0
  170. provekit-0.1.0/provekit/templates/flows/e-commerce-sentiment-route.yaml +73 -0
  171. provekit-0.1.0/provekit/templates/flows/e-commerce-severity-tiers.yaml +103 -0
  172. provekit-0.1.0/provekit/templates/flows/e-commerce-summarize-then-decide.yaml +88 -0
  173. provekit-0.1.0/provekit/templates/flows/e-commerce-tag-enrich.yaml +43 -0
  174. provekit-0.1.0/provekit/templates/flows/e-commerce-tone-rewrite.yaml +43 -0
  175. provekit-0.1.0/provekit/templates/flows/e-commerce-translate-reply.yaml +58 -0
  176. provekit-0.1.0/provekit/templates/flows/e-commerce-triage-route.yaml +73 -0
  177. provekit-0.1.0/provekit/templates/flows/education-action-items.yaml +43 -0
  178. provekit-0.1.0/provekit/templates/flows/education-answer.yaml +43 -0
  179. provekit-0.1.0/provekit/templates/flows/education-classify-intent.yaml +43 -0
  180. provekit-0.1.0/provekit/templates/flows/education-draft-critique-revise.yaml +75 -0
  181. provekit-0.1.0/provekit/templates/flows/education-extract-to-json.yaml +43 -0
  182. provekit-0.1.0/provekit/templates/flows/education-faq-match-answer.yaml +60 -0
  183. provekit-0.1.0/provekit/templates/flows/education-keyword-extract.yaml +43 -0
  184. provekit-0.1.0/provekit/templates/flows/education-language-route.yaml +103 -0
  185. provekit-0.1.0/provekit/templates/flows/education-moderation-gate.yaml +73 -0
  186. provekit-0.1.0/provekit/templates/flows/education-redact-summarize.yaml +59 -0
  187. provekit-0.1.0/provekit/templates/flows/education-score-gate.yaml +73 -0
  188. provekit-0.1.0/provekit/templates/flows/education-sentiment-route.yaml +73 -0
  189. provekit-0.1.0/provekit/templates/flows/education-severity-tiers.yaml +103 -0
  190. provekit-0.1.0/provekit/templates/flows/education-summarize-then-decide.yaml +88 -0
  191. provekit-0.1.0/provekit/templates/flows/education-tag-enrich.yaml +43 -0
  192. provekit-0.1.0/provekit/templates/flows/education-tone-rewrite.yaml +43 -0
  193. provekit-0.1.0/provekit/templates/flows/education-translate-reply.yaml +58 -0
  194. provekit-0.1.0/provekit/templates/flows/education-triage-route.yaml +73 -0
  195. provekit-0.1.0/provekit/templates/flows/finance-action-items.yaml +43 -0
  196. provekit-0.1.0/provekit/templates/flows/finance-answer.yaml +43 -0
  197. provekit-0.1.0/provekit/templates/flows/finance-classify-intent.yaml +43 -0
  198. provekit-0.1.0/provekit/templates/flows/finance-draft-critique-revise.yaml +75 -0
  199. provekit-0.1.0/provekit/templates/flows/finance-extract-to-json.yaml +43 -0
  200. provekit-0.1.0/provekit/templates/flows/finance-faq-match-answer.yaml +60 -0
  201. provekit-0.1.0/provekit/templates/flows/finance-keyword-extract.yaml +43 -0
  202. provekit-0.1.0/provekit/templates/flows/finance-language-route.yaml +103 -0
  203. provekit-0.1.0/provekit/templates/flows/finance-moderation-gate.yaml +73 -0
  204. provekit-0.1.0/provekit/templates/flows/finance-redact-summarize.yaml +59 -0
  205. provekit-0.1.0/provekit/templates/flows/finance-score-gate.yaml +73 -0
  206. provekit-0.1.0/provekit/templates/flows/finance-sentiment-route.yaml +73 -0
  207. provekit-0.1.0/provekit/templates/flows/finance-severity-tiers.yaml +103 -0
  208. provekit-0.1.0/provekit/templates/flows/finance-summarize-then-decide.yaml +88 -0
  209. provekit-0.1.0/provekit/templates/flows/finance-tag-enrich.yaml +43 -0
  210. provekit-0.1.0/provekit/templates/flows/finance-tone-rewrite.yaml +43 -0
  211. provekit-0.1.0/provekit/templates/flows/finance-translate-reply.yaml +58 -0
  212. provekit-0.1.0/provekit/templates/flows/finance-triage-route.yaml +73 -0
  213. provekit-0.1.0/provekit/templates/flows/food-delivery-action-items.yaml +43 -0
  214. provekit-0.1.0/provekit/templates/flows/food-delivery-answer.yaml +43 -0
  215. provekit-0.1.0/provekit/templates/flows/food-delivery-classify-intent.yaml +43 -0
  216. provekit-0.1.0/provekit/templates/flows/food-delivery-draft-critique-revise.yaml +75 -0
  217. provekit-0.1.0/provekit/templates/flows/food-delivery-extract-to-json.yaml +43 -0
  218. provekit-0.1.0/provekit/templates/flows/food-delivery-faq-match-answer.yaml +60 -0
  219. provekit-0.1.0/provekit/templates/flows/food-delivery-keyword-extract.yaml +43 -0
  220. provekit-0.1.0/provekit/templates/flows/food-delivery-language-route.yaml +103 -0
  221. provekit-0.1.0/provekit/templates/flows/food-delivery-moderation-gate.yaml +73 -0
  222. provekit-0.1.0/provekit/templates/flows/food-delivery-redact-summarize.yaml +59 -0
  223. provekit-0.1.0/provekit/templates/flows/food-delivery-score-gate.yaml +73 -0
  224. provekit-0.1.0/provekit/templates/flows/food-delivery-sentiment-route.yaml +73 -0
  225. provekit-0.1.0/provekit/templates/flows/food-delivery-severity-tiers.yaml +103 -0
  226. provekit-0.1.0/provekit/templates/flows/food-delivery-summarize-then-decide.yaml +88 -0
  227. provekit-0.1.0/provekit/templates/flows/food-delivery-tag-enrich.yaml +43 -0
  228. provekit-0.1.0/provekit/templates/flows/food-delivery-tone-rewrite.yaml +43 -0
  229. provekit-0.1.0/provekit/templates/flows/food-delivery-translate-reply.yaml +58 -0
  230. provekit-0.1.0/provekit/templates/flows/food-delivery-triage-route.yaml +73 -0
  231. provekit-0.1.0/provekit/templates/flows/gaming-support-action-items.yaml +43 -0
  232. provekit-0.1.0/provekit/templates/flows/gaming-support-answer.yaml +43 -0
  233. provekit-0.1.0/provekit/templates/flows/gaming-support-classify-intent.yaml +43 -0
  234. provekit-0.1.0/provekit/templates/flows/gaming-support-draft-critique-revise.yaml +75 -0
  235. provekit-0.1.0/provekit/templates/flows/gaming-support-extract-to-json.yaml +43 -0
  236. provekit-0.1.0/provekit/templates/flows/gaming-support-faq-match-answer.yaml +60 -0
  237. provekit-0.1.0/provekit/templates/flows/gaming-support-keyword-extract.yaml +43 -0
  238. provekit-0.1.0/provekit/templates/flows/gaming-support-language-route.yaml +103 -0
  239. provekit-0.1.0/provekit/templates/flows/gaming-support-moderation-gate.yaml +73 -0
  240. provekit-0.1.0/provekit/templates/flows/gaming-support-redact-summarize.yaml +59 -0
  241. provekit-0.1.0/provekit/templates/flows/gaming-support-score-gate.yaml +73 -0
  242. provekit-0.1.0/provekit/templates/flows/gaming-support-sentiment-route.yaml +73 -0
  243. provekit-0.1.0/provekit/templates/flows/gaming-support-severity-tiers.yaml +103 -0
  244. provekit-0.1.0/provekit/templates/flows/gaming-support-summarize-then-decide.yaml +88 -0
  245. provekit-0.1.0/provekit/templates/flows/gaming-support-tag-enrich.yaml +43 -0
  246. provekit-0.1.0/provekit/templates/flows/gaming-support-tone-rewrite.yaml +43 -0
  247. provekit-0.1.0/provekit/templates/flows/gaming-support-translate-reply.yaml +58 -0
  248. provekit-0.1.0/provekit/templates/flows/gaming-support-triage-route.yaml +73 -0
  249. provekit-0.1.0/provekit/templates/flows/healthcare-intake-action-items.yaml +43 -0
  250. provekit-0.1.0/provekit/templates/flows/healthcare-intake-answer.yaml +43 -0
  251. provekit-0.1.0/provekit/templates/flows/healthcare-intake-classify-intent.yaml +43 -0
  252. provekit-0.1.0/provekit/templates/flows/healthcare-intake-draft-critique-revise.yaml +75 -0
  253. provekit-0.1.0/provekit/templates/flows/healthcare-intake-extract-to-json.yaml +43 -0
  254. provekit-0.1.0/provekit/templates/flows/healthcare-intake-faq-match-answer.yaml +60 -0
  255. provekit-0.1.0/provekit/templates/flows/healthcare-intake-keyword-extract.yaml +43 -0
  256. provekit-0.1.0/provekit/templates/flows/healthcare-intake-language-route.yaml +103 -0
  257. provekit-0.1.0/provekit/templates/flows/healthcare-intake-moderation-gate.yaml +73 -0
  258. provekit-0.1.0/provekit/templates/flows/healthcare-intake-redact-summarize.yaml +59 -0
  259. provekit-0.1.0/provekit/templates/flows/healthcare-intake-score-gate.yaml +73 -0
  260. provekit-0.1.0/provekit/templates/flows/healthcare-intake-sentiment-route.yaml +73 -0
  261. provekit-0.1.0/provekit/templates/flows/healthcare-intake-severity-tiers.yaml +103 -0
  262. provekit-0.1.0/provekit/templates/flows/healthcare-intake-summarize-then-decide.yaml +88 -0
  263. provekit-0.1.0/provekit/templates/flows/healthcare-intake-tag-enrich.yaml +43 -0
  264. provekit-0.1.0/provekit/templates/flows/healthcare-intake-tone-rewrite.yaml +43 -0
  265. provekit-0.1.0/provekit/templates/flows/healthcare-intake-translate-reply.yaml +58 -0
  266. provekit-0.1.0/provekit/templates/flows/healthcare-intake-triage-route.yaml +73 -0
  267. provekit-0.1.0/provekit/templates/flows/hr-action-items.yaml +43 -0
  268. provekit-0.1.0/provekit/templates/flows/hr-answer.yaml +43 -0
  269. provekit-0.1.0/provekit/templates/flows/hr-classify-intent.yaml +43 -0
  270. provekit-0.1.0/provekit/templates/flows/hr-draft-critique-revise.yaml +75 -0
  271. provekit-0.1.0/provekit/templates/flows/hr-extract-to-json.yaml +43 -0
  272. provekit-0.1.0/provekit/templates/flows/hr-faq-match-answer.yaml +60 -0
  273. provekit-0.1.0/provekit/templates/flows/hr-keyword-extract.yaml +43 -0
  274. provekit-0.1.0/provekit/templates/flows/hr-language-route.yaml +103 -0
  275. provekit-0.1.0/provekit/templates/flows/hr-moderation-gate.yaml +73 -0
  276. provekit-0.1.0/provekit/templates/flows/hr-redact-summarize.yaml +59 -0
  277. provekit-0.1.0/provekit/templates/flows/hr-score-gate.yaml +73 -0
  278. provekit-0.1.0/provekit/templates/flows/hr-sentiment-route.yaml +73 -0
  279. provekit-0.1.0/provekit/templates/flows/hr-severity-tiers.yaml +103 -0
  280. provekit-0.1.0/provekit/templates/flows/hr-summarize-then-decide.yaml +88 -0
  281. provekit-0.1.0/provekit/templates/flows/hr-tag-enrich.yaml +43 -0
  282. provekit-0.1.0/provekit/templates/flows/hr-tone-rewrite.yaml +43 -0
  283. provekit-0.1.0/provekit/templates/flows/hr-translate-reply.yaml +58 -0
  284. provekit-0.1.0/provekit/templates/flows/hr-triage-route.yaml +73 -0
  285. provekit-0.1.0/provekit/templates/flows/insurance-action-items.yaml +43 -0
  286. provekit-0.1.0/provekit/templates/flows/insurance-answer.yaml +43 -0
  287. provekit-0.1.0/provekit/templates/flows/insurance-classify-intent.yaml +43 -0
  288. provekit-0.1.0/provekit/templates/flows/insurance-draft-critique-revise.yaml +75 -0
  289. provekit-0.1.0/provekit/templates/flows/insurance-extract-to-json.yaml +43 -0
  290. provekit-0.1.0/provekit/templates/flows/insurance-faq-match-answer.yaml +60 -0
  291. provekit-0.1.0/provekit/templates/flows/insurance-keyword-extract.yaml +43 -0
  292. provekit-0.1.0/provekit/templates/flows/insurance-language-route.yaml +103 -0
  293. provekit-0.1.0/provekit/templates/flows/insurance-moderation-gate.yaml +73 -0
  294. provekit-0.1.0/provekit/templates/flows/insurance-redact-summarize.yaml +59 -0
  295. provekit-0.1.0/provekit/templates/flows/insurance-score-gate.yaml +73 -0
  296. provekit-0.1.0/provekit/templates/flows/insurance-sentiment-route.yaml +73 -0
  297. provekit-0.1.0/provekit/templates/flows/insurance-severity-tiers.yaml +103 -0
  298. provekit-0.1.0/provekit/templates/flows/insurance-summarize-then-decide.yaml +88 -0
  299. provekit-0.1.0/provekit/templates/flows/insurance-tag-enrich.yaml +43 -0
  300. provekit-0.1.0/provekit/templates/flows/insurance-tone-rewrite.yaml +43 -0
  301. provekit-0.1.0/provekit/templates/flows/insurance-translate-reply.yaml +58 -0
  302. provekit-0.1.0/provekit/templates/flows/insurance-triage-route.yaml +73 -0
  303. provekit-0.1.0/provekit/templates/flows/it-helpdesk-action-items.yaml +43 -0
  304. provekit-0.1.0/provekit/templates/flows/it-helpdesk-answer.yaml +43 -0
  305. provekit-0.1.0/provekit/templates/flows/it-helpdesk-classify-intent.yaml +43 -0
  306. provekit-0.1.0/provekit/templates/flows/it-helpdesk-draft-critique-revise.yaml +75 -0
  307. provekit-0.1.0/provekit/templates/flows/it-helpdesk-extract-to-json.yaml +43 -0
  308. provekit-0.1.0/provekit/templates/flows/it-helpdesk-faq-match-answer.yaml +60 -0
  309. provekit-0.1.0/provekit/templates/flows/it-helpdesk-keyword-extract.yaml +43 -0
  310. provekit-0.1.0/provekit/templates/flows/it-helpdesk-language-route.yaml +103 -0
  311. provekit-0.1.0/provekit/templates/flows/it-helpdesk-moderation-gate.yaml +73 -0
  312. provekit-0.1.0/provekit/templates/flows/it-helpdesk-redact-summarize.yaml +59 -0
  313. provekit-0.1.0/provekit/templates/flows/it-helpdesk-score-gate.yaml +73 -0
  314. provekit-0.1.0/provekit/templates/flows/it-helpdesk-sentiment-route.yaml +73 -0
  315. provekit-0.1.0/provekit/templates/flows/it-helpdesk-severity-tiers.yaml +103 -0
  316. provekit-0.1.0/provekit/templates/flows/it-helpdesk-summarize-then-decide.yaml +88 -0
  317. provekit-0.1.0/provekit/templates/flows/it-helpdesk-tag-enrich.yaml +43 -0
  318. provekit-0.1.0/provekit/templates/flows/it-helpdesk-tone-rewrite.yaml +43 -0
  319. provekit-0.1.0/provekit/templates/flows/it-helpdesk-translate-reply.yaml +58 -0
  320. provekit-0.1.0/provekit/templates/flows/it-helpdesk-triage-route.yaml +73 -0
  321. provekit-0.1.0/provekit/templates/flows/legal-intake-action-items.yaml +43 -0
  322. provekit-0.1.0/provekit/templates/flows/legal-intake-answer.yaml +43 -0
  323. provekit-0.1.0/provekit/templates/flows/legal-intake-classify-intent.yaml +43 -0
  324. provekit-0.1.0/provekit/templates/flows/legal-intake-draft-critique-revise.yaml +75 -0
  325. provekit-0.1.0/provekit/templates/flows/legal-intake-extract-to-json.yaml +43 -0
  326. provekit-0.1.0/provekit/templates/flows/legal-intake-faq-match-answer.yaml +60 -0
  327. provekit-0.1.0/provekit/templates/flows/legal-intake-keyword-extract.yaml +43 -0
  328. provekit-0.1.0/provekit/templates/flows/legal-intake-language-route.yaml +103 -0
  329. provekit-0.1.0/provekit/templates/flows/legal-intake-moderation-gate.yaml +73 -0
  330. provekit-0.1.0/provekit/templates/flows/legal-intake-redact-summarize.yaml +59 -0
  331. provekit-0.1.0/provekit/templates/flows/legal-intake-score-gate.yaml +73 -0
  332. provekit-0.1.0/provekit/templates/flows/legal-intake-sentiment-route.yaml +73 -0
  333. provekit-0.1.0/provekit/templates/flows/legal-intake-severity-tiers.yaml +103 -0
  334. provekit-0.1.0/provekit/templates/flows/legal-intake-summarize-then-decide.yaml +88 -0
  335. provekit-0.1.0/provekit/templates/flows/legal-intake-tag-enrich.yaml +43 -0
  336. provekit-0.1.0/provekit/templates/flows/legal-intake-tone-rewrite.yaml +43 -0
  337. provekit-0.1.0/provekit/templates/flows/legal-intake-translate-reply.yaml +58 -0
  338. provekit-0.1.0/provekit/templates/flows/legal-intake-triage-route.yaml +73 -0
  339. provekit-0.1.0/provekit/templates/flows/logistics-action-items.yaml +43 -0
  340. provekit-0.1.0/provekit/templates/flows/logistics-answer.yaml +43 -0
  341. provekit-0.1.0/provekit/templates/flows/logistics-classify-intent.yaml +43 -0
  342. provekit-0.1.0/provekit/templates/flows/logistics-draft-critique-revise.yaml +75 -0
  343. provekit-0.1.0/provekit/templates/flows/logistics-extract-to-json.yaml +43 -0
  344. provekit-0.1.0/provekit/templates/flows/logistics-faq-match-answer.yaml +60 -0
  345. provekit-0.1.0/provekit/templates/flows/logistics-keyword-extract.yaml +43 -0
  346. provekit-0.1.0/provekit/templates/flows/logistics-language-route.yaml +103 -0
  347. provekit-0.1.0/provekit/templates/flows/logistics-moderation-gate.yaml +73 -0
  348. provekit-0.1.0/provekit/templates/flows/logistics-redact-summarize.yaml +59 -0
  349. provekit-0.1.0/provekit/templates/flows/logistics-score-gate.yaml +73 -0
  350. provekit-0.1.0/provekit/templates/flows/logistics-sentiment-route.yaml +73 -0
  351. provekit-0.1.0/provekit/templates/flows/logistics-severity-tiers.yaml +103 -0
  352. provekit-0.1.0/provekit/templates/flows/logistics-summarize-then-decide.yaml +88 -0
  353. provekit-0.1.0/provekit/templates/flows/logistics-tag-enrich.yaml +43 -0
  354. provekit-0.1.0/provekit/templates/flows/logistics-tone-rewrite.yaml +43 -0
  355. provekit-0.1.0/provekit/templates/flows/logistics-translate-reply.yaml +58 -0
  356. provekit-0.1.0/provekit/templates/flows/logistics-triage-route.yaml +73 -0
  357. provekit-0.1.0/provekit/templates/flows/marketing-action-items.yaml +43 -0
  358. provekit-0.1.0/provekit/templates/flows/marketing-answer.yaml +43 -0
  359. provekit-0.1.0/provekit/templates/flows/marketing-classify-intent.yaml +43 -0
  360. provekit-0.1.0/provekit/templates/flows/marketing-draft-critique-revise.yaml +75 -0
  361. provekit-0.1.0/provekit/templates/flows/marketing-extract-to-json.yaml +43 -0
  362. provekit-0.1.0/provekit/templates/flows/marketing-faq-match-answer.yaml +60 -0
  363. provekit-0.1.0/provekit/templates/flows/marketing-keyword-extract.yaml +43 -0
  364. provekit-0.1.0/provekit/templates/flows/marketing-language-route.yaml +103 -0
  365. provekit-0.1.0/provekit/templates/flows/marketing-moderation-gate.yaml +73 -0
  366. provekit-0.1.0/provekit/templates/flows/marketing-redact-summarize.yaml +59 -0
  367. provekit-0.1.0/provekit/templates/flows/marketing-score-gate.yaml +73 -0
  368. provekit-0.1.0/provekit/templates/flows/marketing-sentiment-route.yaml +73 -0
  369. provekit-0.1.0/provekit/templates/flows/marketing-severity-tiers.yaml +103 -0
  370. provekit-0.1.0/provekit/templates/flows/marketing-summarize-then-decide.yaml +88 -0
  371. provekit-0.1.0/provekit/templates/flows/marketing-tag-enrich.yaml +43 -0
  372. provekit-0.1.0/provekit/templates/flows/marketing-tone-rewrite.yaml +43 -0
  373. provekit-0.1.0/provekit/templates/flows/marketing-translate-reply.yaml +58 -0
  374. provekit-0.1.0/provekit/templates/flows/marketing-triage-route.yaml +73 -0
  375. provekit-0.1.0/provekit/templates/flows/nonprofit-action-items.yaml +43 -0
  376. provekit-0.1.0/provekit/templates/flows/nonprofit-answer.yaml +43 -0
  377. provekit-0.1.0/provekit/templates/flows/nonprofit-classify-intent.yaml +43 -0
  378. provekit-0.1.0/provekit/templates/flows/nonprofit-draft-critique-revise.yaml +75 -0
  379. provekit-0.1.0/provekit/templates/flows/nonprofit-extract-to-json.yaml +43 -0
  380. provekit-0.1.0/provekit/templates/flows/nonprofit-faq-match-answer.yaml +60 -0
  381. provekit-0.1.0/provekit/templates/flows/nonprofit-keyword-extract.yaml +43 -0
  382. provekit-0.1.0/provekit/templates/flows/nonprofit-language-route.yaml +103 -0
  383. provekit-0.1.0/provekit/templates/flows/nonprofit-moderation-gate.yaml +73 -0
  384. provekit-0.1.0/provekit/templates/flows/nonprofit-redact-summarize.yaml +59 -0
  385. provekit-0.1.0/provekit/templates/flows/nonprofit-score-gate.yaml +73 -0
  386. provekit-0.1.0/provekit/templates/flows/nonprofit-sentiment-route.yaml +73 -0
  387. provekit-0.1.0/provekit/templates/flows/nonprofit-severity-tiers.yaml +103 -0
  388. provekit-0.1.0/provekit/templates/flows/nonprofit-summarize-then-decide.yaml +88 -0
  389. provekit-0.1.0/provekit/templates/flows/nonprofit-tag-enrich.yaml +43 -0
  390. provekit-0.1.0/provekit/templates/flows/nonprofit-tone-rewrite.yaml +43 -0
  391. provekit-0.1.0/provekit/templates/flows/nonprofit-translate-reply.yaml +58 -0
  392. provekit-0.1.0/provekit/templates/flows/nonprofit-triage-route.yaml +73 -0
  393. provekit-0.1.0/provekit/templates/flows/real-estate-action-items.yaml +43 -0
  394. provekit-0.1.0/provekit/templates/flows/real-estate-answer.yaml +43 -0
  395. provekit-0.1.0/provekit/templates/flows/real-estate-classify-intent.yaml +43 -0
  396. provekit-0.1.0/provekit/templates/flows/real-estate-draft-critique-revise.yaml +75 -0
  397. provekit-0.1.0/provekit/templates/flows/real-estate-extract-to-json.yaml +43 -0
  398. provekit-0.1.0/provekit/templates/flows/real-estate-faq-match-answer.yaml +60 -0
  399. provekit-0.1.0/provekit/templates/flows/real-estate-keyword-extract.yaml +43 -0
  400. provekit-0.1.0/provekit/templates/flows/real-estate-language-route.yaml +103 -0
  401. provekit-0.1.0/provekit/templates/flows/real-estate-moderation-gate.yaml +73 -0
  402. provekit-0.1.0/provekit/templates/flows/real-estate-redact-summarize.yaml +59 -0
  403. provekit-0.1.0/provekit/templates/flows/real-estate-score-gate.yaml +73 -0
  404. provekit-0.1.0/provekit/templates/flows/real-estate-sentiment-route.yaml +73 -0
  405. provekit-0.1.0/provekit/templates/flows/real-estate-severity-tiers.yaml +103 -0
  406. provekit-0.1.0/provekit/templates/flows/real-estate-summarize-then-decide.yaml +88 -0
  407. provekit-0.1.0/provekit/templates/flows/real-estate-tag-enrich.yaml +43 -0
  408. provekit-0.1.0/provekit/templates/flows/real-estate-tone-rewrite.yaml +43 -0
  409. provekit-0.1.0/provekit/templates/flows/real-estate-translate-reply.yaml +58 -0
  410. provekit-0.1.0/provekit/templates/flows/real-estate-triage-route.yaml +73 -0
  411. provekit-0.1.0/provekit/templates/flows/recruiting-action-items.yaml +43 -0
  412. provekit-0.1.0/provekit/templates/flows/recruiting-answer.yaml +43 -0
  413. provekit-0.1.0/provekit/templates/flows/recruiting-classify-intent.yaml +43 -0
  414. provekit-0.1.0/provekit/templates/flows/recruiting-draft-critique-revise.yaml +75 -0
  415. provekit-0.1.0/provekit/templates/flows/recruiting-extract-to-json.yaml +43 -0
  416. provekit-0.1.0/provekit/templates/flows/recruiting-faq-match-answer.yaml +60 -0
  417. provekit-0.1.0/provekit/templates/flows/recruiting-keyword-extract.yaml +43 -0
  418. provekit-0.1.0/provekit/templates/flows/recruiting-language-route.yaml +103 -0
  419. provekit-0.1.0/provekit/templates/flows/recruiting-moderation-gate.yaml +73 -0
  420. provekit-0.1.0/provekit/templates/flows/recruiting-redact-summarize.yaml +59 -0
  421. provekit-0.1.0/provekit/templates/flows/recruiting-score-gate.yaml +73 -0
  422. provekit-0.1.0/provekit/templates/flows/recruiting-sentiment-route.yaml +73 -0
  423. provekit-0.1.0/provekit/templates/flows/recruiting-severity-tiers.yaml +103 -0
  424. provekit-0.1.0/provekit/templates/flows/recruiting-summarize-then-decide.yaml +88 -0
  425. provekit-0.1.0/provekit/templates/flows/recruiting-tag-enrich.yaml +43 -0
  426. provekit-0.1.0/provekit/templates/flows/recruiting-tone-rewrite.yaml +43 -0
  427. provekit-0.1.0/provekit/templates/flows/recruiting-translate-reply.yaml +58 -0
  428. provekit-0.1.0/provekit/templates/flows/recruiting-triage-route.yaml +73 -0
  429. provekit-0.1.0/provekit/templates/flows/research-action-items.yaml +43 -0
  430. provekit-0.1.0/provekit/templates/flows/research-answer.yaml +43 -0
  431. provekit-0.1.0/provekit/templates/flows/research-classify-intent.yaml +43 -0
  432. provekit-0.1.0/provekit/templates/flows/research-draft-critique-revise.yaml +75 -0
  433. provekit-0.1.0/provekit/templates/flows/research-extract-to-json.yaml +43 -0
  434. provekit-0.1.0/provekit/templates/flows/research-faq-match-answer.yaml +60 -0
  435. provekit-0.1.0/provekit/templates/flows/research-keyword-extract.yaml +43 -0
  436. provekit-0.1.0/provekit/templates/flows/research-language-route.yaml +103 -0
  437. provekit-0.1.0/provekit/templates/flows/research-moderation-gate.yaml +73 -0
  438. provekit-0.1.0/provekit/templates/flows/research-redact-summarize.yaml +59 -0
  439. provekit-0.1.0/provekit/templates/flows/research-score-gate.yaml +73 -0
  440. provekit-0.1.0/provekit/templates/flows/research-sentiment-route.yaml +73 -0
  441. provekit-0.1.0/provekit/templates/flows/research-severity-tiers.yaml +103 -0
  442. provekit-0.1.0/provekit/templates/flows/research-summarize-then-decide.yaml +88 -0
  443. provekit-0.1.0/provekit/templates/flows/research-tag-enrich.yaml +43 -0
  444. provekit-0.1.0/provekit/templates/flows/research-tone-rewrite.yaml +43 -0
  445. provekit-0.1.0/provekit/templates/flows/research-translate-reply.yaml +58 -0
  446. provekit-0.1.0/provekit/templates/flows/research-triage-route.yaml +73 -0
  447. provekit-0.1.0/provekit/templates/flows/sales-lead-action-items.yaml +43 -0
  448. provekit-0.1.0/provekit/templates/flows/sales-lead-answer.yaml +43 -0
  449. provekit-0.1.0/provekit/templates/flows/sales-lead-classify-intent.yaml +43 -0
  450. provekit-0.1.0/provekit/templates/flows/sales-lead-draft-critique-revise.yaml +75 -0
  451. provekit-0.1.0/provekit/templates/flows/sales-lead-extract-to-json.yaml +43 -0
  452. provekit-0.1.0/provekit/templates/flows/sales-lead-faq-match-answer.yaml +60 -0
  453. provekit-0.1.0/provekit/templates/flows/sales-lead-keyword-extract.yaml +43 -0
  454. provekit-0.1.0/provekit/templates/flows/sales-lead-language-route.yaml +103 -0
  455. provekit-0.1.0/provekit/templates/flows/sales-lead-moderation-gate.yaml +73 -0
  456. provekit-0.1.0/provekit/templates/flows/sales-lead-redact-summarize.yaml +59 -0
  457. provekit-0.1.0/provekit/templates/flows/sales-lead-score-gate.yaml +73 -0
  458. provekit-0.1.0/provekit/templates/flows/sales-lead-sentiment-route.yaml +73 -0
  459. provekit-0.1.0/provekit/templates/flows/sales-lead-severity-tiers.yaml +103 -0
  460. provekit-0.1.0/provekit/templates/flows/sales-lead-summarize-then-decide.yaml +88 -0
  461. provekit-0.1.0/provekit/templates/flows/sales-lead-tag-enrich.yaml +43 -0
  462. provekit-0.1.0/provekit/templates/flows/sales-lead-tone-rewrite.yaml +43 -0
  463. provekit-0.1.0/provekit/templates/flows/sales-lead-translate-reply.yaml +58 -0
  464. provekit-0.1.0/provekit/templates/flows/sales-lead-triage-route.yaml +73 -0
  465. provekit-0.1.0/provekit/templates/flows/travel-action-items.yaml +43 -0
  466. provekit-0.1.0/provekit/templates/flows/travel-answer.yaml +43 -0
  467. provekit-0.1.0/provekit/templates/flows/travel-classify-intent.yaml +43 -0
  468. provekit-0.1.0/provekit/templates/flows/travel-draft-critique-revise.yaml +75 -0
  469. provekit-0.1.0/provekit/templates/flows/travel-extract-to-json.yaml +43 -0
  470. provekit-0.1.0/provekit/templates/flows/travel-faq-match-answer.yaml +60 -0
  471. provekit-0.1.0/provekit/templates/flows/travel-keyword-extract.yaml +43 -0
  472. provekit-0.1.0/provekit/templates/flows/travel-language-route.yaml +103 -0
  473. provekit-0.1.0/provekit/templates/flows/travel-moderation-gate.yaml +73 -0
  474. provekit-0.1.0/provekit/templates/flows/travel-redact-summarize.yaml +59 -0
  475. provekit-0.1.0/provekit/templates/flows/travel-score-gate.yaml +73 -0
  476. provekit-0.1.0/provekit/templates/flows/travel-sentiment-route.yaml +73 -0
  477. provekit-0.1.0/provekit/templates/flows/travel-severity-tiers.yaml +103 -0
  478. provekit-0.1.0/provekit/templates/flows/travel-summarize-then-decide.yaml +88 -0
  479. provekit-0.1.0/provekit/templates/flows/travel-tag-enrich.yaml +43 -0
  480. provekit-0.1.0/provekit/templates/flows/travel-tone-rewrite.yaml +43 -0
  481. provekit-0.1.0/provekit/templates/flows/travel-translate-reply.yaml +58 -0
  482. provekit-0.1.0/provekit/templates/flows/travel-triage-route.yaml +73 -0
  483. provekit-0.1.0/provekit.egg-info/PKG-INFO +86 -0
  484. provekit-0.1.0/provekit.egg-info/SOURCES.txt +516 -0
  485. provekit-0.1.0/provekit.egg-info/dependency_links.txt +1 -0
  486. provekit-0.1.0/provekit.egg-info/entry_points.txt +2 -0
  487. provekit-0.1.0/provekit.egg-info/requires.txt +18 -0
  488. provekit-0.1.0/provekit.egg-info/top_level.txt +1 -0
  489. provekit-0.1.0/pyproject.toml +89 -0
  490. provekit-0.1.0/setup.cfg +4 -0
  491. provekit-0.1.0/tests/test_a2a.py +81 -0
  492. provekit-0.1.0/tests/test_account_recovery.py +113 -0
  493. provekit-0.1.0/tests/test_auth.py +94 -0
  494. provekit-0.1.0/tests/test_auth_hardening.py +39 -0
  495. provekit-0.1.0/tests/test_cli.py +142 -0
  496. provekit-0.1.0/tests/test_connection_secrets.py +108 -0
  497. provekit-0.1.0/tests/test_cov_assertions.py +554 -0
  498. provekit-0.1.0/tests/test_cov_dispatch.py +573 -0
  499. provekit-0.1.0/tests/test_cov_flow.py +606 -0
  500. provekit-0.1.0/tests/test_cov_infra.py +1164 -0
  501. provekit-0.1.0/tests/test_cov_library_run.py +477 -0
  502. provekit-0.1.0/tests/test_cov_limits_auth.py +130 -0
  503. provekit-0.1.0/tests/test_cov_llm_mcp.py +660 -0
  504. provekit-0.1.0/tests/test_cov_routers.py +887 -0
  505. provekit-0.1.0/tests/test_deployments.py +156 -0
  506. provekit-0.1.0/tests/test_hardening_extra.py +70 -0
  507. provekit-0.1.0/tests/test_import_export.py +68 -0
  508. provekit-0.1.0/tests/test_limits.py +78 -0
  509. provekit-0.1.0/tests/test_llm_providers.py +174 -0
  510. provekit-0.1.0/tests/test_mcp_client.py +141 -0
  511. provekit-0.1.0/tests/test_observability.py +21 -0
  512. provekit-0.1.0/tests/test_otel.py +115 -0
  513. provekit-0.1.0/tests/test_runstore.py +64 -0
  514. provekit-0.1.0/tests/test_templates.py +66 -0
  515. provekit-0.1.0/tests/test_tenancy.py +65 -0
  516. provekit-0.1.0/tests/test_testfile.py +68 -0
  517. provekit-0.1.0/tests/test_tooling.py +520 -0
  518. provekit-0.1.0/tests/test_usage.py +27 -0
@@ -0,0 +1,86 @@
1
+ Metadata-Version: 2.4
2
+ Name: provekit
3
+ Version: 0.1.0
4
+ Summary: Prove your agent works — test any AI agent (LLM/MCP/HTTP/A2A) and run the suite in CI.
5
+ Author: ProveKit contributors
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/MobirizerServices/ProveKit
8
+ Project-URL: Repository, https://github.com/MobirizerServices/ProveKit
9
+ Project-URL: Issues, https://github.com/MobirizerServices/ProveKit/issues
10
+ Keywords: agent,llm,testing,evals,mcp,ci,prompt,openai,anthropic
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Topic :: Software Development :: Testing
19
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
20
+ Requires-Python: >=3.11
21
+ Description-Content-Type: text/markdown
22
+ Requires-Dist: fastapi==0.115.6
23
+ Requires-Dist: uvicorn[standard]==0.34.0
24
+ Requires-Dist: sqlalchemy==2.0.36
25
+ Requires-Dist: pydantic==2.10.4
26
+ Requires-Dist: pydantic-settings==2.7.1
27
+ Requires-Dist: httpx==0.28.1
28
+ Requires-Dist: jsonschema==4.23.0
29
+ Requires-Dist: cryptography==49.0.0
30
+ Requires-Dist: pyyaml==6.0.3
31
+ Requires-Dist: alembic==1.18.5
32
+ Requires-Dist: psycopg[binary]==3.3.4
33
+ Requires-Dist: email-validator==2.2.0
34
+ Requires-Dist: redis==5.2.1
35
+ Requires-Dist: sentry-sdk[fastapi]==2.20.0
36
+ Provides-Extra: dev
37
+ Requires-Dist: pytest==9.1.1; extra == "dev"
38
+ Requires-Dist: ruff==0.9.2; extra == "dev"
39
+
40
+ # ProveKit
41
+
42
+ **Prove your agent works.** ProveKit tests any AI agent — an LLM API, an MCP server, an
43
+ HTTP agent, or an A2A agent — turns a run into a regression test, and runs the suite
44
+ headless in CI. Open-source, local-first, no account.
45
+
46
+ This package is the **`provekit` CLI** — the headless test runner. The full visual app
47
+ (console, flow builder, live step-debugger) runs as a server; see the
48
+ [repo](https://github.com/MobirizerServices/ProveKit).
49
+
50
+ ## Install
51
+
52
+ ```bash
53
+ pip install provekit
54
+ ```
55
+
56
+ ## Use in CI
57
+
58
+ Write plain-text, git-diffable tests under `.provekit/` (connections referenced by name,
59
+ secrets via `${ENV_VAR}` — never in the files), commit them, and run:
60
+
61
+ ```bash
62
+ provekit run .provekit/tests/ # pretty output, non-zero exit on failure
63
+ provekit run .provekit/tests/ --format junit -o results.xml
64
+ provekit import-promptfoo promptfooconfig.yaml -o .provekit/tests/ # migrate from promptfoo
65
+ ```
66
+
67
+ Connections resolve from `.provekit/connections.yaml`:
68
+
69
+ ```yaml
70
+ connections:
71
+ OpenAI (prod):
72
+ provider: openai
73
+ api_key: ${OPENAI_API_KEY}
74
+ models: [gpt-4o-mini]
75
+ ```
76
+
77
+ ## Assertions
78
+
79
+ `contains` · `equals` · `regex` · `json_path` · `json_schema` · `tool_called` ·
80
+ `latency_lt` · `llm_judge` — pass/fail per assertion, non-zero exit on failure.
81
+
82
+ ## Links
83
+
84
+ - Repository & full app: https://github.com/MobirizerServices/ProveKit
85
+ - File format: see `docs/FILE_FORMAT.md` in the repo
86
+ - License: MIT
@@ -0,0 +1,47 @@
1
+ # ProveKit
2
+
3
+ **Prove your agent works.** ProveKit tests any AI agent — an LLM API, an MCP server, an
4
+ HTTP agent, or an A2A agent — turns a run into a regression test, and runs the suite
5
+ headless in CI. Open-source, local-first, no account.
6
+
7
+ This package is the **`provekit` CLI** — the headless test runner. The full visual app
8
+ (console, flow builder, live step-debugger) runs as a server; see the
9
+ [repo](https://github.com/MobirizerServices/ProveKit).
10
+
11
+ ## Install
12
+
13
+ ```bash
14
+ pip install provekit
15
+ ```
16
+
17
+ ## Use in CI
18
+
19
+ Write plain-text, git-diffable tests under `.provekit/` (connections referenced by name,
20
+ secrets via `${ENV_VAR}` — never in the files), commit them, and run:
21
+
22
+ ```bash
23
+ provekit run .provekit/tests/ # pretty output, non-zero exit on failure
24
+ provekit run .provekit/tests/ --format junit -o results.xml
25
+ provekit import-promptfoo promptfooconfig.yaml -o .provekit/tests/ # migrate from promptfoo
26
+ ```
27
+
28
+ Connections resolve from `.provekit/connections.yaml`:
29
+
30
+ ```yaml
31
+ connections:
32
+ OpenAI (prod):
33
+ provider: openai
34
+ api_key: ${OPENAI_API_KEY}
35
+ models: [gpt-4o-mini]
36
+ ```
37
+
38
+ ## Assertions
39
+
40
+ `contains` · `equals` · `regex` · `json_path` · `json_schema` · `tool_called` ·
41
+ `latency_lt` · `llm_judge` — pass/fail per assertion, non-zero exit on failure.
42
+
43
+ ## Links
44
+
45
+ - Repository & full app: https://github.com/MobirizerServices/ProveKit
46
+ - File format: see `docs/FILE_FORMAT.md` in the repo
47
+ - License: MIT
File without changes
@@ -0,0 +1,256 @@
1
+ """`provekit` — headless runner for .provekit test files (CI).
2
+
3
+ provekit run .provekit/tests/ # run every test file under a dir
4
+ provekit run support-bot.yaml --format junit -o results.xml
5
+ provekit import-promptfoo promptfooconfig.yaml -o .provekit/tests/
6
+
7
+ Connections resolve from a local file (default: .provekit/connections.yaml, then
8
+ ~/.provekit/connections.yaml), NEVER from the test files. Secrets in that file may
9
+ be written as ${ENV_VAR} and are expanded from the environment at run time.
10
+
11
+ Exit code is non-zero when any assertion fails or any run errors — so CI gates on it.
12
+ """
13
+ from __future__ import annotations
14
+
15
+ import argparse
16
+ import os
17
+ import re
18
+ import sys
19
+ from pathlib import Path
20
+ from xml.sax.saxutils import escape
21
+
22
+ import yaml
23
+
24
+ from .services import assertions as ae
25
+ from .services import dispatch, testfile
26
+ from .services.promptfoo import import_promptfoo
27
+
28
+ _ENV_REF = re.compile(r"\$\{([A-Za-z_][A-Za-z0-9_]*)\}")
29
+
30
+
31
+ # ---- local connection registry (stands in for the DB in CLI mode) ----
32
+ class _Conn:
33
+ def __init__(self, config):
34
+ self.config = config
35
+
36
+
37
+ class _Registry:
38
+ """Minimal object graph dispatch/assertions expect from a `db`: `.get(model, id)`."""
39
+ def __init__(self, by_name: dict):
40
+ self._by_name = by_name
41
+ self._ids = {name: i + 1 for i, name in enumerate(by_name)}
42
+ self._by_id = {i: _Conn(by_name[name]) for name, i in self._ids.items()}
43
+
44
+ def id_of(self, name: str) -> int | None:
45
+ return self._ids.get(name)
46
+
47
+ def get(self, _model, cid):
48
+ return self._by_id.get(cid)
49
+
50
+
51
+ def _expand_env(obj):
52
+ if isinstance(obj, str):
53
+ return _ENV_REF.sub(lambda m: os.environ.get(m.group(1), ""), obj)
54
+ if isinstance(obj, dict):
55
+ return {k: _expand_env(v) for k, v in obj.items()}
56
+ if isinstance(obj, list):
57
+ return [_expand_env(v) for v in obj]
58
+ return obj
59
+
60
+
61
+ def _load_connections(explicit: str | None) -> _Registry:
62
+ paths = [explicit] if explicit else [".provekit/connections.yaml",
63
+ str(Path.home() / ".provekit/connections.yaml")]
64
+ for p in paths:
65
+ if p and Path(p).exists():
66
+ doc = yaml.safe_load(Path(p).read_text()) or {}
67
+ return _Registry(_expand_env(doc.get("connections") or {}))
68
+ return _Registry({})
69
+
70
+
71
+ # ---- running ----
72
+ def _run_case(reg, request, variables):
73
+ rd = _collect(reg, request, variables)
74
+ asserts = ae.evaluate(reg, request.get("assertions") or [], rd)
75
+ ok = all(a["ok"] for a in asserts) if asserts else rd["status"] == "completed"
76
+ return {"status": rd["status"], "error": rd["error"], "duration_ms": rd["duration_ms"],
77
+ "text": rd["result"].get("text"), "assertions": asserts, "ok": ok}
78
+
79
+
80
+ def _collect(reg, req, variables):
81
+ # dispatch is async; the CLI is sync, so drive it via the sync bridge (its own loop).
82
+ r = dispatch.run_collect_sync(reg, req, variables)
83
+ return {"result": {"text": r["text"], "output": r["output"], "meta": r["meta"]},
84
+ "status": r["status"], "error": r["error"], "duration_ms": r.get("duration_ms", 0)}
85
+
86
+
87
+ def _resolve_request(doc, reg) -> tuple[dict, str | None]:
88
+ """Build the runnable request from a test doc; returns (request, unresolved_connection)."""
89
+ req = dict(doc["request"])
90
+ name = doc.get("connection")
91
+ cid = reg.id_of(name) if name else None
92
+ if cid:
93
+ req["connection_id"] = cid
94
+ if doc.get("assertions"):
95
+ req["assertions"] = doc["assertions"]
96
+ # llm_judge assertions may name their own judge connection
97
+ for a in req.get("assertions") or []:
98
+ if a.get("type") == "llm_judge" and a.get("connection"):
99
+ a["connection_id"] = reg.id_of(a["connection"])
100
+ return req, (name if name and not cid else None)
101
+
102
+
103
+ def _iter_test_files(paths):
104
+ for p in paths:
105
+ path = Path(p)
106
+ if path.is_dir():
107
+ yield from sorted(path.rglob("*.yaml"))
108
+ yield from sorted(path.rglob("*.yml"))
109
+ elif path.exists():
110
+ yield path
111
+ else:
112
+ print(f"warning: path not found: {p}", file=sys.stderr)
113
+
114
+
115
+ def cmd_run(args) -> int:
116
+ reg = _load_connections(args.connections)
117
+ cli_vars = dict(kv.split("=", 1) for kv in args.env) if args.env else {}
118
+ files = list(_iter_test_files(args.paths))
119
+ if not files:
120
+ print("no .provekit test files found", file=sys.stderr)
121
+ return 2
122
+
123
+ suites = []
124
+ for f in files:
125
+ try:
126
+ doc = testfile.load(f.read_text())
127
+ except ValueError as exc:
128
+ suites.append({"file": str(f), "error": f"parse error: {exc}", "cases": []})
129
+ continue
130
+ if doc.get("kind") != "test":
131
+ continue # flows aren't CI test units
132
+ request, unresolved = _resolve_request(doc, reg)
133
+ rows = doc.get("dataset") or [{"name": None, "variables": {}}]
134
+ cases = []
135
+ for i, row in enumerate(rows):
136
+ variables = {**cli_vars, **(row.get("variables") or {})}
137
+ res = _run_case(reg, request, variables)
138
+ res["name"] = row.get("name") or (f"row {i + 1}" if len(rows) > 1 else doc["name"])
139
+ cases.append(res)
140
+ suites.append({"file": str(f), "name": doc["name"], "cases": cases,
141
+ "error": (f"connection '{unresolved}' not found" if unresolved else None)})
142
+
143
+ _render(suites, args.format, args.output)
144
+ failed = sum(1 for s in suites for c in s["cases"] if not c["ok"]) + \
145
+ sum(1 for s in suites if s.get("error"))
146
+ return 1 if failed else 0
147
+
148
+
149
+ # ---- output renderers ----
150
+ _G, _R, _Y, _D, _X = "\033[32m", "\033[31m", "\033[33m", "\033[2m", "\033[0m"
151
+
152
+
153
+ def _color(on: bool):
154
+ return ("", "", "", "", "") if not on else (_G, _R, _Y, _D, _X)
155
+
156
+
157
+ def _render(suites, fmt, output):
158
+ if fmt == "json":
159
+ import json
160
+ text = json.dumps({"suites": suites}, indent=2)
161
+ elif fmt == "junit":
162
+ text = _junit(suites)
163
+ else:
164
+ text = _pretty(suites, color=output is None and sys.stdout.isatty())
165
+ if output:
166
+ Path(output).write_text(text)
167
+ print(f"wrote {fmt} report to {output}", file=sys.stderr)
168
+ else:
169
+ print(text)
170
+
171
+
172
+ def _pretty(suites, color: bool) -> str:
173
+ g, r, y, d, x = _color(color)
174
+ lines, total, passed = [], 0, 0
175
+ for s in suites:
176
+ if s.get("error") and not s["cases"]:
177
+ lines.append(f"{r}✕{x} {s['file']} — {s['error']}")
178
+ continue
179
+ lines.append(f"{d}{s['file']}{x}")
180
+ if s.get("error"):
181
+ lines.append(f" {y}! {s['error']}{x}")
182
+ for c in s["cases"]:
183
+ total += 1; passed += c["ok"]
184
+ mark = f"{g}✓{x}" if c["ok"] else f"{r}✕{x}"
185
+ lines.append(f" {mark} {c['name']} {d}{c['duration_ms']}ms{x}")
186
+ for a in c["assertions"]:
187
+ am = f"{g}✓{x}" if a["ok"] else f"{r}✕{x}"
188
+ lines.append(f" {am} {a['type']}: {a['detail']}")
189
+ if c["error"]:
190
+ lines.append(f" {r}error: {c['error']}{x}")
191
+ head = f"{g if passed == total else r}{passed}/{total} passed{x}"
192
+ lines.append("")
193
+ lines.append(head)
194
+ return "\n".join(lines)
195
+
196
+
197
+ def _junit(suites) -> str:
198
+ out = ['<?xml version="1.0" encoding="UTF-8"?>', "<testsuites>"]
199
+ for s in suites:
200
+ cases = s["cases"]
201
+ fails = sum(1 for c in cases if not c["ok"])
202
+ errs = 1 if s.get("error") and not cases else 0
203
+ out.append(f' <testsuite name="{escape(s.get("name") or s["file"])}" '
204
+ f'tests="{len(cases)}" failures="{fails}" errors="{errs}">')
205
+ if errs:
206
+ out.append(f' <testcase name="{escape(s["file"])}">'
207
+ f'<error message="{escape(s["error"])}"/></testcase>')
208
+ for c in cases:
209
+ t = (c["duration_ms"] or 0) / 1000
210
+ out.append(f' <testcase name="{escape(c["name"])}" time="{t:.3f}">')
211
+ if not c["ok"]:
212
+ detail = c["error"] or "; ".join(f"{a['type']}: {a['detail']}"
213
+ for a in c["assertions"] if not a["ok"])
214
+ out.append(f' <failure message="{escape(detail)}"/>')
215
+ out.append(" </testcase>")
216
+ out.append(" </testsuite>")
217
+ out.append("</testsuites>")
218
+ return "\n".join(out)
219
+
220
+
221
+ def cmd_import_promptfoo(args) -> int:
222
+ docs, warnings = import_promptfoo(Path(args.config).read_text())
223
+ outdir = Path(args.output or ".")
224
+ outdir.mkdir(parents=True, exist_ok=True)
225
+ for name, text in docs:
226
+ (outdir / name).write_text(text)
227
+ print(f"wrote {outdir / name}")
228
+ for w in warnings: # never drop anything silently
229
+ print(f"warning: {w}", file=sys.stderr)
230
+ print(f"imported {len(docs)} test(s) from {args.config}", file=sys.stderr)
231
+ return 0
232
+
233
+
234
+ def main(argv=None) -> int:
235
+ parser = argparse.ArgumentParser(prog="provekit", description="Run .provekit agent tests.")
236
+ sub = parser.add_subparsers(dest="cmd", required=True)
237
+
238
+ run = sub.add_parser("run", help="run test files or directories")
239
+ run.add_argument("paths", nargs="+")
240
+ run.add_argument("--connections", help="connections YAML (default: .provekit/connections.yaml)")
241
+ run.add_argument("--env", action="append", metavar="KEY=VAL", help="extra template variables")
242
+ run.add_argument("--format", choices=["pretty", "json", "junit"], default="pretty")
243
+ run.add_argument("-o", "--output", help="write the report to a file instead of stdout")
244
+ run.set_defaults(func=cmd_run)
245
+
246
+ imp = sub.add_parser("import-promptfoo", help="convert a promptfoo config to .provekit tests")
247
+ imp.add_argument("config")
248
+ imp.add_argument("-o", "--output", help="output directory (default: cwd)")
249
+ imp.set_defaults(func=cmd_import_promptfoo)
250
+
251
+ args = parser.parse_args(argv)
252
+ return args.func(args)
253
+
254
+
255
+ if __name__ == "__main__":
256
+ sys.exit(main())
@@ -0,0 +1,77 @@
1
+ """ProveKit configuration."""
2
+ from functools import lru_cache
3
+
4
+ from pydantic_settings import BaseSettings, SettingsConfigDict
5
+
6
+
7
+ class Settings(BaseSettings):
8
+ model_config = SettingsConfigDict(env_file=".env", extra="ignore")
9
+
10
+ database_url: str = "sqlite:///./provekit.db"
11
+ cors_origins: str = "http://localhost:3001,http://localhost:3000"
12
+
13
+ # Hosted mode: stricter outbound-URL guarding (block private/internal ranges).
14
+ # Leave false for local single-user use.
15
+ hosted: bool = False
16
+
17
+ # Encryption key for secrets at rest (any string; derived to a Fernet key).
18
+ # Optional for local SQLite (a key file is auto-generated next to the db);
19
+ # required for any other database.
20
+ secret_key: str = ""
21
+
22
+ # Optional OTLP/HTTP collector to mirror ProveKit's own runs as gen_ai spans.
23
+ otel_export_url: str = ""
24
+
25
+ # Public base URL shown in deployment endpoints (where /v1/d/{slug} is reachable).
26
+ public_base_url: str = "http://localhost:8100"
27
+
28
+ # Wall-clock cap for a single deployment invocation (seconds); 0 disables.
29
+ deployment_timeout_s: float = 120.0
30
+
31
+ # Optional Sentry DSN for error reporting (off when unset).
32
+ sentry_dsn: str = ""
33
+
34
+ # Web app base URL (for links in emails). Same-origin in prod.
35
+ web_base_url: str = "http://localhost:3001"
36
+
37
+ # Email (account recovery/verification). No SMTP host → links are logged, not sent.
38
+ smtp_host: str = ""
39
+ smtp_port: int = 587
40
+ smtp_user: str = ""
41
+ smtp_password: str = ""
42
+ smtp_from: str = ""
43
+ smtp_starttls: bool = True
44
+ require_email_verification: bool = False
45
+
46
+ # Optional Redis for paused flow-run contexts (survives workers/restarts).
47
+ # Unset → in-memory (single-process local use).
48
+ redis_url: str = ""
49
+
50
+ # Max concurrent sync workers (streams run in this threadpool). Lifts Starlette's
51
+ # ~40-token default so many more streams run at once without an async rewrite.
52
+ thread_pool_size: int = 200
53
+
54
+ # Quotas (protect shared infra). 0 disables a given limit.
55
+ rate_limit_per_min: int = 120 # run requests per workspace per minute
56
+ login_attempts_per_min: int = 10 # login attempts per email+IP per minute
57
+ dataset_max_rows: int = 200 # rows per dataset run
58
+ max_tokens_cap: int = 0 # hard cap on prompt max_tokens (0 = no cap)
59
+ runs_retention: int = 1000 # keep last N runs per workspace
60
+ max_body_bytes: int = 2_000_000 # reject request bodies larger than this
61
+ max_flow_nodes: int = 200 # cap nodes per flow
62
+
63
+ # Seed empty OpenAI + Anthropic example connections on first run. The keyless
64
+ # "Demo Assistant (mock)" connection is seeded regardless of this setting.
65
+ seed_examples: bool = True
66
+
67
+ # A default OpenAI key can be provided to prefill the example LLM connection.
68
+ openai_api_key: str = ""
69
+
70
+ @property
71
+ def cors_origin_list(self) -> list[str]:
72
+ return [o.strip() for o in self.cors_origins.split(",") if o.strip()]
73
+
74
+
75
+ @lru_cache
76
+ def get_settings() -> Settings:
77
+ return Settings()
@@ -0,0 +1,132 @@
1
+ """SQLAlchemy engine + session (SQLite)."""
2
+ from sqlalchemy import MetaData, create_engine, event
3
+ from sqlalchemy.orm import DeclarativeBase, sessionmaker
4
+
5
+ from .config import get_settings
6
+
7
+ settings = get_settings()
8
+ _is_sqlite = settings.database_url.startswith("sqlite")
9
+ connect_args = {"check_same_thread": False} if _is_sqlite else {}
10
+ # A concurrent stream holds a pooled connection for its lifetime; if the pool is exhausted,
11
+ # the next (synchronous) checkout blocks the event loop. Size the pool to the stream
12
+ # concurrency so checkouts never block the loop.
13
+ if _is_sqlite and ":memory:" in settings.database_url:
14
+ _pool = {}
15
+ else:
16
+ _pool = {"pool_size": 20, "max_overflow": max(10, settings.thread_pool_size)}
17
+ if not _is_sqlite:
18
+ _pool["pool_pre_ping"] = True # Postgres: drop stale connections (harmful w/ SQLite WAL pragma)
19
+ engine = create_engine(settings.database_url, connect_args=connect_args, **_pool)
20
+ SessionLocal = sessionmaker(bind=engine, autoflush=False, autocommit=False)
21
+
22
+ if _is_sqlite:
23
+ @event.listens_for(engine, "connect")
24
+ def _sqlite_pragmas(dbapi_conn, _record):
25
+ # WAL lets readers and a writer coexist; busy_timeout makes a contended write wait
26
+ # briefly instead of erroring — important now that many async streams write runs.
27
+ cur = dbapi_conn.cursor()
28
+ cur.execute("PRAGMA journal_mode=WAL")
29
+ cur.execute("PRAGMA busy_timeout=5000")
30
+ cur.close()
31
+
32
+ # Named constraints so Alembic's SQLite batch mode (ALTER via table-rebuild) can re-add them.
33
+ _NAMING = {
34
+ "ix": "ix_%(column_0_label)s",
35
+ "uq": "uq_%(table_name)s_%(column_0_name)s",
36
+ "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
37
+ "pk": "pk_%(table_name)s",
38
+ }
39
+
40
+
41
+ class Base(DeclarativeBase):
42
+ metadata = MetaData(naming_convention=_NAMING)
43
+
44
+
45
+ def get_db():
46
+ db = SessionLocal()
47
+ try:
48
+ yield db
49
+ finally:
50
+ db.close()
51
+
52
+
53
+ def init_db() -> None:
54
+ from . import models # noqa: F401
55
+ if settings.database_url.startswith("sqlite") and ":memory:" in settings.database_url:
56
+ # Ephemeral in-memory DB (tests only): create_all is fast and needs no migration tooling.
57
+ Base.metadata.create_all(bind=engine)
58
+ else:
59
+ # Every persistent DB — file-based SQLite included — is owned by Alembic so that
60
+ # future column/index changes actually apply on upgrade. create_all only ever adds
61
+ # whole tables and would silently skip new columns on an existing local database.
62
+ _run_migrations()
63
+
64
+
65
+ # Revision that first introduced each column, newest first — used to adopt a pre-migration
66
+ # database (built by the old create_all path) at the revision matching its actual columns.
67
+ _ADOPT_BY_COLUMN = [
68
+ ("users", "token_version", "a1b2c3d4e5f6"),
69
+ ("users", "email_verified", "323eb73d463c"),
70
+ ("workspaces", "ingest_key_hash", "819ed5ff183e"),
71
+ ]
72
+ _BASELINE_REVISION = "49e8ab812556"
73
+
74
+
75
+ # Postgres advisory-lock key ("AGMN") used to serialize migrations across uvicorn workers.
76
+ _MIGRATION_LOCK_ID = 0x4147_4D4E
77
+
78
+
79
+ def _migration_config():
80
+ """Alembic config built in code rather than read from alembic.ini.
81
+
82
+ The migrations ship *inside* the package, so script_location is resolved absolutely
83
+ from `__file__`. Reading alembic.ini instead would only work when the process runs
84
+ from a source checkout — a `pip install`ed wheel has no alembic.ini next to the
85
+ package, and the app would fail to boot. alembic.ini stays for `alembic` CLI use.
86
+ """
87
+ import os
88
+
89
+ from alembic.config import Config
90
+
91
+ cfg = Config()
92
+ cfg.set_main_option("script_location", os.path.join(os.path.dirname(__file__), "migrations"))
93
+ # No sqlalchemy.url here on purpose: env.py reads it from settings and builds the engine
94
+ # itself, which keeps a '%' in the password out of ConfigParser's interpolation.
95
+ return cfg
96
+
97
+
98
+ def _run_migrations() -> None:
99
+ cfg = _migration_config()
100
+ if settings.database_url.startswith("sqlite"):
101
+ _migrate_to_head(cfg) # single process — no cross-worker race
102
+ return
103
+ # With `--workers N` every worker runs the lifespan and would race through upgrade
104
+ # (DuplicateTable / duplicate alembic_version). A Postgres session advisory lock lets
105
+ # exactly one run at a time; the rest block, then find the schema already at head.
106
+ with engine.connect().execution_options(isolation_level="AUTOCOMMIT") as conn:
107
+ conn.exec_driver_sql("SELECT pg_advisory_lock(%s)", (_MIGRATION_LOCK_ID,))
108
+ try:
109
+ _migrate_to_head(cfg)
110
+ finally:
111
+ conn.exec_driver_sql("SELECT pg_advisory_unlock(%s)", (_MIGRATION_LOCK_ID,))
112
+
113
+
114
+ def _migrate_to_head(cfg) -> None:
115
+ from alembic import command
116
+ from alembic.runtime.migration import MigrationContext
117
+ from sqlalchemy import inspect
118
+
119
+ insp = inspect(engine)
120
+ with engine.connect() as conn:
121
+ current = MigrationContext.configure(conn).get_current_revision()
122
+ if current is None and insp.has_table("users"):
123
+ # A database created by create_all before migrations existed has the tables but no
124
+ # alembic version. Stamp it at the revision matching its columns so `upgrade` applies
125
+ # only what's genuinely missing instead of trying to re-create existing tables.
126
+ stamp_at = _BASELINE_REVISION
127
+ for table, column, revision in _ADOPT_BY_COLUMN:
128
+ if any(c["name"] == column for c in insp.get_columns(table)):
129
+ stamp_at = revision
130
+ break
131
+ command.stamp(cfg, stamp_at)
132
+ command.upgrade(cfg, "head")