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.
- provekit-0.1.0/PKG-INFO +86 -0
- provekit-0.1.0/README.md +47 -0
- provekit-0.1.0/provekit/__init__.py +0 -0
- provekit-0.1.0/provekit/cli.py +256 -0
- provekit-0.1.0/provekit/config.py +77 -0
- provekit-0.1.0/provekit/database.py +132 -0
- provekit-0.1.0/provekit/main.py +115 -0
- provekit-0.1.0/provekit/migrations/env.py +40 -0
- provekit-0.1.0/provekit/migrations/script.py.mako +22 -0
- provekit-0.1.0/provekit/migrations/versions/323eb73d463c_user_email_verified.py +32 -0
- provekit-0.1.0/provekit/migrations/versions/49e8ab812556_baseline_schema.py +241 -0
- provekit-0.1.0/provekit/migrations/versions/819ed5ff183e_workspace_ingest_key.py +35 -0
- provekit-0.1.0/provekit/migrations/versions/a1b2c3d4e5f6_user_token_version.py +27 -0
- provekit-0.1.0/provekit/models.py +191 -0
- provekit-0.1.0/provekit/observability.py +154 -0
- provekit-0.1.0/provekit/routers/__init__.py +0 -0
- provekit-0.1.0/provekit/routers/auth.py +150 -0
- provekit-0.1.0/provekit/routers/connections.py +270 -0
- provekit-0.1.0/provekit/routers/deployments.py +161 -0
- provekit-0.1.0/provekit/routers/flows.py +188 -0
- provekit-0.1.0/provekit/routers/library.py +265 -0
- provekit-0.1.0/provekit/routers/prompts.py +72 -0
- provekit-0.1.0/provekit/routers/run.py +203 -0
- provekit-0.1.0/provekit/routers/runtime.py +103 -0
- provekit-0.1.0/provekit/routers/traces.py +65 -0
- provekit-0.1.0/provekit/routers/usage.py +42 -0
- provekit-0.1.0/provekit/services/__init__.py +0 -0
- provekit-0.1.0/provekit/services/assertions.py +135 -0
- provekit-0.1.0/provekit/services/auth.py +131 -0
- provekit-0.1.0/provekit/services/deploy.py +63 -0
- provekit-0.1.0/provekit/services/dispatch.py +313 -0
- provekit-0.1.0/provekit/services/email.py +38 -0
- provekit-0.1.0/provekit/services/flow.py +299 -0
- provekit-0.1.0/provekit/services/limits.py +109 -0
- provekit-0.1.0/provekit/services/masking.py +45 -0
- provekit-0.1.0/provekit/services/netguard.py +69 -0
- provekit-0.1.0/provekit/services/otel.py +146 -0
- provekit-0.1.0/provekit/services/promptfoo.py +92 -0
- provekit-0.1.0/provekit/services/providers/__init__.py +0 -0
- provekit-0.1.0/provekit/services/providers/a2a_client.py +110 -0
- provekit-0.1.0/provekit/services/providers/agent_http.py +55 -0
- provekit-0.1.0/provekit/services/providers/llm.py +364 -0
- provekit-0.1.0/provekit/services/providers/mcp_client.py +289 -0
- provekit-0.1.0/provekit/services/runstore.py +93 -0
- provekit-0.1.0/provekit/services/sealing.py +106 -0
- provekit-0.1.0/provekit/services/templates.py +69 -0
- provekit-0.1.0/provekit/services/testfile.py +122 -0
- provekit-0.1.0/provekit/services/tooling.py +194 -0
- provekit-0.1.0/provekit/services/workspace.py +91 -0
- provekit-0.1.0/provekit/templates/flows/_manifest.json +2594 -0
- provekit-0.1.0/provekit/templates/flows/banking-action-items.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/banking-answer.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/banking-classify-intent.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/banking-draft-critique-revise.yaml +75 -0
- provekit-0.1.0/provekit/templates/flows/banking-extract-to-json.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/banking-faq-match-answer.yaml +60 -0
- provekit-0.1.0/provekit/templates/flows/banking-keyword-extract.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/banking-language-route.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/banking-moderation-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/banking-redact-summarize.yaml +59 -0
- provekit-0.1.0/provekit/templates/flows/banking-score-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/banking-sentiment-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/banking-severity-tiers.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/banking-summarize-then-decide.yaml +88 -0
- provekit-0.1.0/provekit/templates/flows/banking-tag-enrich.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/banking-tone-rewrite.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/banking-translate-reply.yaml +58 -0
- provekit-0.1.0/provekit/templates/flows/banking-triage-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/community-forum-action-items.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/community-forum-answer.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/community-forum-classify-intent.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/community-forum-draft-critique-revise.yaml +75 -0
- provekit-0.1.0/provekit/templates/flows/community-forum-extract-to-json.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/community-forum-faq-match-answer.yaml +60 -0
- provekit-0.1.0/provekit/templates/flows/community-forum-keyword-extract.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/community-forum-language-route.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/community-forum-moderation-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/community-forum-redact-summarize.yaml +59 -0
- provekit-0.1.0/provekit/templates/flows/community-forum-score-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/community-forum-sentiment-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/community-forum-severity-tiers.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/community-forum-summarize-then-decide.yaml +88 -0
- provekit-0.1.0/provekit/templates/flows/community-forum-tag-enrich.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/community-forum-tone-rewrite.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/community-forum-translate-reply.yaml +58 -0
- provekit-0.1.0/provekit/templates/flows/community-forum-triage-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/content-moderation-action-items.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/content-moderation-answer.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/content-moderation-classify-intent.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/content-moderation-draft-critique-revise.yaml +75 -0
- provekit-0.1.0/provekit/templates/flows/content-moderation-extract-to-json.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/content-moderation-faq-match-answer.yaml +60 -0
- provekit-0.1.0/provekit/templates/flows/content-moderation-keyword-extract.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/content-moderation-language-route.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/content-moderation-moderation-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/content-moderation-redact-summarize.yaml +59 -0
- provekit-0.1.0/provekit/templates/flows/content-moderation-score-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/content-moderation-sentiment-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/content-moderation-severity-tiers.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/content-moderation-summarize-then-decide.yaml +88 -0
- provekit-0.1.0/provekit/templates/flows/content-moderation-tag-enrich.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/content-moderation-tone-rewrite.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/content-moderation-translate-reply.yaml +58 -0
- provekit-0.1.0/provekit/templates/flows/content-moderation-triage-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/customer-support-action-items.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/customer-support-answer.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/customer-support-classify-intent.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/customer-support-draft-critique-revise.yaml +75 -0
- provekit-0.1.0/provekit/templates/flows/customer-support-extract-to-json.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/customer-support-faq-match-answer.yaml +60 -0
- provekit-0.1.0/provekit/templates/flows/customer-support-keyword-extract.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/customer-support-language-route.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/customer-support-moderation-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/customer-support-redact-summarize.yaml +59 -0
- provekit-0.1.0/provekit/templates/flows/customer-support-score-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/customer-support-sentiment-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/customer-support-severity-tiers.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/customer-support-summarize-then-decide.yaml +88 -0
- provekit-0.1.0/provekit/templates/flows/customer-support-tag-enrich.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/customer-support-tone-rewrite.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/customer-support-translate-reply.yaml +58 -0
- provekit-0.1.0/provekit/templates/flows/customer-support-triage-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/developer-tooling-action-items.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/developer-tooling-answer.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/developer-tooling-classify-intent.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/developer-tooling-draft-critique-revise.yaml +75 -0
- provekit-0.1.0/provekit/templates/flows/developer-tooling-extract-to-json.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/developer-tooling-faq-match-answer.yaml +60 -0
- provekit-0.1.0/provekit/templates/flows/developer-tooling-keyword-extract.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/developer-tooling-language-route.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/developer-tooling-moderation-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/developer-tooling-redact-summarize.yaml +59 -0
- provekit-0.1.0/provekit/templates/flows/developer-tooling-score-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/developer-tooling-sentiment-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/developer-tooling-severity-tiers.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/developer-tooling-summarize-then-decide.yaml +88 -0
- provekit-0.1.0/provekit/templates/flows/developer-tooling-tag-enrich.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/developer-tooling-tone-rewrite.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/developer-tooling-translate-reply.yaml +58 -0
- provekit-0.1.0/provekit/templates/flows/developer-tooling-triage-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/devrel-action-items.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/devrel-answer.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/devrel-classify-intent.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/devrel-draft-critique-revise.yaml +75 -0
- provekit-0.1.0/provekit/templates/flows/devrel-extract-to-json.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/devrel-faq-match-answer.yaml +60 -0
- provekit-0.1.0/provekit/templates/flows/devrel-keyword-extract.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/devrel-language-route.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/devrel-moderation-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/devrel-redact-summarize.yaml +59 -0
- provekit-0.1.0/provekit/templates/flows/devrel-score-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/devrel-sentiment-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/devrel-severity-tiers.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/devrel-summarize-then-decide.yaml +88 -0
- provekit-0.1.0/provekit/templates/flows/devrel-tag-enrich.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/devrel-tone-rewrite.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/devrel-translate-reply.yaml +58 -0
- provekit-0.1.0/provekit/templates/flows/devrel-triage-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/e-commerce-action-items.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/e-commerce-answer.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/e-commerce-classify-intent.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/e-commerce-draft-critique-revise.yaml +75 -0
- provekit-0.1.0/provekit/templates/flows/e-commerce-extract-to-json.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/e-commerce-faq-match-answer.yaml +60 -0
- provekit-0.1.0/provekit/templates/flows/e-commerce-keyword-extract.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/e-commerce-language-route.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/e-commerce-moderation-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/e-commerce-redact-summarize.yaml +59 -0
- provekit-0.1.0/provekit/templates/flows/e-commerce-score-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/e-commerce-sentiment-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/e-commerce-severity-tiers.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/e-commerce-summarize-then-decide.yaml +88 -0
- provekit-0.1.0/provekit/templates/flows/e-commerce-tag-enrich.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/e-commerce-tone-rewrite.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/e-commerce-translate-reply.yaml +58 -0
- provekit-0.1.0/provekit/templates/flows/e-commerce-triage-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/education-action-items.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/education-answer.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/education-classify-intent.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/education-draft-critique-revise.yaml +75 -0
- provekit-0.1.0/provekit/templates/flows/education-extract-to-json.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/education-faq-match-answer.yaml +60 -0
- provekit-0.1.0/provekit/templates/flows/education-keyword-extract.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/education-language-route.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/education-moderation-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/education-redact-summarize.yaml +59 -0
- provekit-0.1.0/provekit/templates/flows/education-score-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/education-sentiment-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/education-severity-tiers.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/education-summarize-then-decide.yaml +88 -0
- provekit-0.1.0/provekit/templates/flows/education-tag-enrich.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/education-tone-rewrite.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/education-translate-reply.yaml +58 -0
- provekit-0.1.0/provekit/templates/flows/education-triage-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/finance-action-items.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/finance-answer.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/finance-classify-intent.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/finance-draft-critique-revise.yaml +75 -0
- provekit-0.1.0/provekit/templates/flows/finance-extract-to-json.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/finance-faq-match-answer.yaml +60 -0
- provekit-0.1.0/provekit/templates/flows/finance-keyword-extract.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/finance-language-route.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/finance-moderation-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/finance-redact-summarize.yaml +59 -0
- provekit-0.1.0/provekit/templates/flows/finance-score-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/finance-sentiment-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/finance-severity-tiers.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/finance-summarize-then-decide.yaml +88 -0
- provekit-0.1.0/provekit/templates/flows/finance-tag-enrich.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/finance-tone-rewrite.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/finance-translate-reply.yaml +58 -0
- provekit-0.1.0/provekit/templates/flows/finance-triage-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/food-delivery-action-items.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/food-delivery-answer.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/food-delivery-classify-intent.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/food-delivery-draft-critique-revise.yaml +75 -0
- provekit-0.1.0/provekit/templates/flows/food-delivery-extract-to-json.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/food-delivery-faq-match-answer.yaml +60 -0
- provekit-0.1.0/provekit/templates/flows/food-delivery-keyword-extract.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/food-delivery-language-route.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/food-delivery-moderation-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/food-delivery-redact-summarize.yaml +59 -0
- provekit-0.1.0/provekit/templates/flows/food-delivery-score-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/food-delivery-sentiment-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/food-delivery-severity-tiers.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/food-delivery-summarize-then-decide.yaml +88 -0
- provekit-0.1.0/provekit/templates/flows/food-delivery-tag-enrich.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/food-delivery-tone-rewrite.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/food-delivery-translate-reply.yaml +58 -0
- provekit-0.1.0/provekit/templates/flows/food-delivery-triage-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/gaming-support-action-items.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/gaming-support-answer.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/gaming-support-classify-intent.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/gaming-support-draft-critique-revise.yaml +75 -0
- provekit-0.1.0/provekit/templates/flows/gaming-support-extract-to-json.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/gaming-support-faq-match-answer.yaml +60 -0
- provekit-0.1.0/provekit/templates/flows/gaming-support-keyword-extract.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/gaming-support-language-route.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/gaming-support-moderation-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/gaming-support-redact-summarize.yaml +59 -0
- provekit-0.1.0/provekit/templates/flows/gaming-support-score-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/gaming-support-sentiment-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/gaming-support-severity-tiers.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/gaming-support-summarize-then-decide.yaml +88 -0
- provekit-0.1.0/provekit/templates/flows/gaming-support-tag-enrich.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/gaming-support-tone-rewrite.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/gaming-support-translate-reply.yaml +58 -0
- provekit-0.1.0/provekit/templates/flows/gaming-support-triage-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/healthcare-intake-action-items.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/healthcare-intake-answer.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/healthcare-intake-classify-intent.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/healthcare-intake-draft-critique-revise.yaml +75 -0
- provekit-0.1.0/provekit/templates/flows/healthcare-intake-extract-to-json.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/healthcare-intake-faq-match-answer.yaml +60 -0
- provekit-0.1.0/provekit/templates/flows/healthcare-intake-keyword-extract.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/healthcare-intake-language-route.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/healthcare-intake-moderation-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/healthcare-intake-redact-summarize.yaml +59 -0
- provekit-0.1.0/provekit/templates/flows/healthcare-intake-score-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/healthcare-intake-sentiment-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/healthcare-intake-severity-tiers.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/healthcare-intake-summarize-then-decide.yaml +88 -0
- provekit-0.1.0/provekit/templates/flows/healthcare-intake-tag-enrich.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/healthcare-intake-tone-rewrite.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/healthcare-intake-translate-reply.yaml +58 -0
- provekit-0.1.0/provekit/templates/flows/healthcare-intake-triage-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/hr-action-items.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/hr-answer.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/hr-classify-intent.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/hr-draft-critique-revise.yaml +75 -0
- provekit-0.1.0/provekit/templates/flows/hr-extract-to-json.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/hr-faq-match-answer.yaml +60 -0
- provekit-0.1.0/provekit/templates/flows/hr-keyword-extract.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/hr-language-route.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/hr-moderation-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/hr-redact-summarize.yaml +59 -0
- provekit-0.1.0/provekit/templates/flows/hr-score-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/hr-sentiment-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/hr-severity-tiers.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/hr-summarize-then-decide.yaml +88 -0
- provekit-0.1.0/provekit/templates/flows/hr-tag-enrich.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/hr-tone-rewrite.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/hr-translate-reply.yaml +58 -0
- provekit-0.1.0/provekit/templates/flows/hr-triage-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/insurance-action-items.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/insurance-answer.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/insurance-classify-intent.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/insurance-draft-critique-revise.yaml +75 -0
- provekit-0.1.0/provekit/templates/flows/insurance-extract-to-json.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/insurance-faq-match-answer.yaml +60 -0
- provekit-0.1.0/provekit/templates/flows/insurance-keyword-extract.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/insurance-language-route.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/insurance-moderation-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/insurance-redact-summarize.yaml +59 -0
- provekit-0.1.0/provekit/templates/flows/insurance-score-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/insurance-sentiment-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/insurance-severity-tiers.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/insurance-summarize-then-decide.yaml +88 -0
- provekit-0.1.0/provekit/templates/flows/insurance-tag-enrich.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/insurance-tone-rewrite.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/insurance-translate-reply.yaml +58 -0
- provekit-0.1.0/provekit/templates/flows/insurance-triage-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/it-helpdesk-action-items.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/it-helpdesk-answer.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/it-helpdesk-classify-intent.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/it-helpdesk-draft-critique-revise.yaml +75 -0
- provekit-0.1.0/provekit/templates/flows/it-helpdesk-extract-to-json.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/it-helpdesk-faq-match-answer.yaml +60 -0
- provekit-0.1.0/provekit/templates/flows/it-helpdesk-keyword-extract.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/it-helpdesk-language-route.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/it-helpdesk-moderation-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/it-helpdesk-redact-summarize.yaml +59 -0
- provekit-0.1.0/provekit/templates/flows/it-helpdesk-score-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/it-helpdesk-sentiment-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/it-helpdesk-severity-tiers.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/it-helpdesk-summarize-then-decide.yaml +88 -0
- provekit-0.1.0/provekit/templates/flows/it-helpdesk-tag-enrich.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/it-helpdesk-tone-rewrite.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/it-helpdesk-translate-reply.yaml +58 -0
- provekit-0.1.0/provekit/templates/flows/it-helpdesk-triage-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/legal-intake-action-items.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/legal-intake-answer.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/legal-intake-classify-intent.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/legal-intake-draft-critique-revise.yaml +75 -0
- provekit-0.1.0/provekit/templates/flows/legal-intake-extract-to-json.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/legal-intake-faq-match-answer.yaml +60 -0
- provekit-0.1.0/provekit/templates/flows/legal-intake-keyword-extract.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/legal-intake-language-route.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/legal-intake-moderation-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/legal-intake-redact-summarize.yaml +59 -0
- provekit-0.1.0/provekit/templates/flows/legal-intake-score-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/legal-intake-sentiment-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/legal-intake-severity-tiers.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/legal-intake-summarize-then-decide.yaml +88 -0
- provekit-0.1.0/provekit/templates/flows/legal-intake-tag-enrich.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/legal-intake-tone-rewrite.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/legal-intake-translate-reply.yaml +58 -0
- provekit-0.1.0/provekit/templates/flows/legal-intake-triage-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/logistics-action-items.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/logistics-answer.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/logistics-classify-intent.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/logistics-draft-critique-revise.yaml +75 -0
- provekit-0.1.0/provekit/templates/flows/logistics-extract-to-json.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/logistics-faq-match-answer.yaml +60 -0
- provekit-0.1.0/provekit/templates/flows/logistics-keyword-extract.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/logistics-language-route.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/logistics-moderation-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/logistics-redact-summarize.yaml +59 -0
- provekit-0.1.0/provekit/templates/flows/logistics-score-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/logistics-sentiment-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/logistics-severity-tiers.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/logistics-summarize-then-decide.yaml +88 -0
- provekit-0.1.0/provekit/templates/flows/logistics-tag-enrich.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/logistics-tone-rewrite.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/logistics-translate-reply.yaml +58 -0
- provekit-0.1.0/provekit/templates/flows/logistics-triage-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/marketing-action-items.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/marketing-answer.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/marketing-classify-intent.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/marketing-draft-critique-revise.yaml +75 -0
- provekit-0.1.0/provekit/templates/flows/marketing-extract-to-json.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/marketing-faq-match-answer.yaml +60 -0
- provekit-0.1.0/provekit/templates/flows/marketing-keyword-extract.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/marketing-language-route.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/marketing-moderation-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/marketing-redact-summarize.yaml +59 -0
- provekit-0.1.0/provekit/templates/flows/marketing-score-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/marketing-sentiment-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/marketing-severity-tiers.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/marketing-summarize-then-decide.yaml +88 -0
- provekit-0.1.0/provekit/templates/flows/marketing-tag-enrich.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/marketing-tone-rewrite.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/marketing-translate-reply.yaml +58 -0
- provekit-0.1.0/provekit/templates/flows/marketing-triage-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/nonprofit-action-items.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/nonprofit-answer.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/nonprofit-classify-intent.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/nonprofit-draft-critique-revise.yaml +75 -0
- provekit-0.1.0/provekit/templates/flows/nonprofit-extract-to-json.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/nonprofit-faq-match-answer.yaml +60 -0
- provekit-0.1.0/provekit/templates/flows/nonprofit-keyword-extract.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/nonprofit-language-route.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/nonprofit-moderation-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/nonprofit-redact-summarize.yaml +59 -0
- provekit-0.1.0/provekit/templates/flows/nonprofit-score-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/nonprofit-sentiment-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/nonprofit-severity-tiers.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/nonprofit-summarize-then-decide.yaml +88 -0
- provekit-0.1.0/provekit/templates/flows/nonprofit-tag-enrich.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/nonprofit-tone-rewrite.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/nonprofit-translate-reply.yaml +58 -0
- provekit-0.1.0/provekit/templates/flows/nonprofit-triage-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/real-estate-action-items.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/real-estate-answer.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/real-estate-classify-intent.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/real-estate-draft-critique-revise.yaml +75 -0
- provekit-0.1.0/provekit/templates/flows/real-estate-extract-to-json.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/real-estate-faq-match-answer.yaml +60 -0
- provekit-0.1.0/provekit/templates/flows/real-estate-keyword-extract.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/real-estate-language-route.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/real-estate-moderation-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/real-estate-redact-summarize.yaml +59 -0
- provekit-0.1.0/provekit/templates/flows/real-estate-score-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/real-estate-sentiment-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/real-estate-severity-tiers.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/real-estate-summarize-then-decide.yaml +88 -0
- provekit-0.1.0/provekit/templates/flows/real-estate-tag-enrich.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/real-estate-tone-rewrite.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/real-estate-translate-reply.yaml +58 -0
- provekit-0.1.0/provekit/templates/flows/real-estate-triage-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/recruiting-action-items.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/recruiting-answer.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/recruiting-classify-intent.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/recruiting-draft-critique-revise.yaml +75 -0
- provekit-0.1.0/provekit/templates/flows/recruiting-extract-to-json.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/recruiting-faq-match-answer.yaml +60 -0
- provekit-0.1.0/provekit/templates/flows/recruiting-keyword-extract.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/recruiting-language-route.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/recruiting-moderation-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/recruiting-redact-summarize.yaml +59 -0
- provekit-0.1.0/provekit/templates/flows/recruiting-score-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/recruiting-sentiment-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/recruiting-severity-tiers.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/recruiting-summarize-then-decide.yaml +88 -0
- provekit-0.1.0/provekit/templates/flows/recruiting-tag-enrich.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/recruiting-tone-rewrite.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/recruiting-translate-reply.yaml +58 -0
- provekit-0.1.0/provekit/templates/flows/recruiting-triage-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/research-action-items.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/research-answer.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/research-classify-intent.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/research-draft-critique-revise.yaml +75 -0
- provekit-0.1.0/provekit/templates/flows/research-extract-to-json.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/research-faq-match-answer.yaml +60 -0
- provekit-0.1.0/provekit/templates/flows/research-keyword-extract.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/research-language-route.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/research-moderation-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/research-redact-summarize.yaml +59 -0
- provekit-0.1.0/provekit/templates/flows/research-score-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/research-sentiment-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/research-severity-tiers.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/research-summarize-then-decide.yaml +88 -0
- provekit-0.1.0/provekit/templates/flows/research-tag-enrich.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/research-tone-rewrite.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/research-translate-reply.yaml +58 -0
- provekit-0.1.0/provekit/templates/flows/research-triage-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/sales-lead-action-items.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/sales-lead-answer.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/sales-lead-classify-intent.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/sales-lead-draft-critique-revise.yaml +75 -0
- provekit-0.1.0/provekit/templates/flows/sales-lead-extract-to-json.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/sales-lead-faq-match-answer.yaml +60 -0
- provekit-0.1.0/provekit/templates/flows/sales-lead-keyword-extract.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/sales-lead-language-route.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/sales-lead-moderation-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/sales-lead-redact-summarize.yaml +59 -0
- provekit-0.1.0/provekit/templates/flows/sales-lead-score-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/sales-lead-sentiment-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/sales-lead-severity-tiers.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/sales-lead-summarize-then-decide.yaml +88 -0
- provekit-0.1.0/provekit/templates/flows/sales-lead-tag-enrich.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/sales-lead-tone-rewrite.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/sales-lead-translate-reply.yaml +58 -0
- provekit-0.1.0/provekit/templates/flows/sales-lead-triage-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/travel-action-items.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/travel-answer.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/travel-classify-intent.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/travel-draft-critique-revise.yaml +75 -0
- provekit-0.1.0/provekit/templates/flows/travel-extract-to-json.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/travel-faq-match-answer.yaml +60 -0
- provekit-0.1.0/provekit/templates/flows/travel-keyword-extract.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/travel-language-route.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/travel-moderation-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/travel-redact-summarize.yaml +59 -0
- provekit-0.1.0/provekit/templates/flows/travel-score-gate.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/travel-sentiment-route.yaml +73 -0
- provekit-0.1.0/provekit/templates/flows/travel-severity-tiers.yaml +103 -0
- provekit-0.1.0/provekit/templates/flows/travel-summarize-then-decide.yaml +88 -0
- provekit-0.1.0/provekit/templates/flows/travel-tag-enrich.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/travel-tone-rewrite.yaml +43 -0
- provekit-0.1.0/provekit/templates/flows/travel-translate-reply.yaml +58 -0
- provekit-0.1.0/provekit/templates/flows/travel-triage-route.yaml +73 -0
- provekit-0.1.0/provekit.egg-info/PKG-INFO +86 -0
- provekit-0.1.0/provekit.egg-info/SOURCES.txt +516 -0
- provekit-0.1.0/provekit.egg-info/dependency_links.txt +1 -0
- provekit-0.1.0/provekit.egg-info/entry_points.txt +2 -0
- provekit-0.1.0/provekit.egg-info/requires.txt +18 -0
- provekit-0.1.0/provekit.egg-info/top_level.txt +1 -0
- provekit-0.1.0/pyproject.toml +89 -0
- provekit-0.1.0/setup.cfg +4 -0
- provekit-0.1.0/tests/test_a2a.py +81 -0
- provekit-0.1.0/tests/test_account_recovery.py +113 -0
- provekit-0.1.0/tests/test_auth.py +94 -0
- provekit-0.1.0/tests/test_auth_hardening.py +39 -0
- provekit-0.1.0/tests/test_cli.py +142 -0
- provekit-0.1.0/tests/test_connection_secrets.py +108 -0
- provekit-0.1.0/tests/test_cov_assertions.py +554 -0
- provekit-0.1.0/tests/test_cov_dispatch.py +573 -0
- provekit-0.1.0/tests/test_cov_flow.py +606 -0
- provekit-0.1.0/tests/test_cov_infra.py +1164 -0
- provekit-0.1.0/tests/test_cov_library_run.py +477 -0
- provekit-0.1.0/tests/test_cov_limits_auth.py +130 -0
- provekit-0.1.0/tests/test_cov_llm_mcp.py +660 -0
- provekit-0.1.0/tests/test_cov_routers.py +887 -0
- provekit-0.1.0/tests/test_deployments.py +156 -0
- provekit-0.1.0/tests/test_hardening_extra.py +70 -0
- provekit-0.1.0/tests/test_import_export.py +68 -0
- provekit-0.1.0/tests/test_limits.py +78 -0
- provekit-0.1.0/tests/test_llm_providers.py +174 -0
- provekit-0.1.0/tests/test_mcp_client.py +141 -0
- provekit-0.1.0/tests/test_observability.py +21 -0
- provekit-0.1.0/tests/test_otel.py +115 -0
- provekit-0.1.0/tests/test_runstore.py +64 -0
- provekit-0.1.0/tests/test_templates.py +66 -0
- provekit-0.1.0/tests/test_tenancy.py +65 -0
- provekit-0.1.0/tests/test_testfile.py +68 -0
- provekit-0.1.0/tests/test_tooling.py +520 -0
- provekit-0.1.0/tests/test_usage.py +27 -0
provekit-0.1.0/PKG-INFO
ADDED
|
@@ -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
|
provekit-0.1.0/README.md
ADDED
|
@@ -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")
|