provekit 0.1.0__tar.gz → 0.2.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.2.0/PKG-INFO +94 -0
- provekit-0.2.0/README.md +49 -0
- {provekit-0.1.0 → provekit-0.2.0}/provekit/database.py +0 -26
- {provekit-0.1.0 → provekit-0.2.0}/provekit/main.py +6 -28
- provekit-0.2.0/provekit/migrations/versions/9d2c06bfa4e6_baseline.py +121 -0
- provekit-0.2.0/provekit/models.py +100 -0
- provekit-0.2.0/provekit/routers/apikeys.py +57 -0
- provekit-0.2.0/provekit/routers/traces.py +125 -0
- provekit-0.2.0/provekit/services/apikey.py +38 -0
- provekit-0.2.0/provekit/services/deploy.py +20 -0
- {provekit-0.1.0 → provekit-0.2.0}/provekit/services/otel.py +28 -16
- provekit-0.2.0/provekit/services/workspace.py +27 -0
- provekit-0.2.0/provekit/trace.py +216 -0
- provekit-0.2.0/provekit.egg-info/PKG-INFO +94 -0
- provekit-0.2.0/provekit.egg-info/SOURCES.txt +45 -0
- provekit-0.2.0/provekit.egg-info/requires.txt +26 -0
- provekit-0.2.0/pyproject.toml +114 -0
- provekit-0.2.0/tests/test_apikeys.py +59 -0
- provekit-0.2.0/tests/test_autoinstrument.py +64 -0
- provekit-0.2.0/tests/test_netguard.py +34 -0
- {provekit-0.1.0 → provekit-0.2.0}/tests/test_otel.py +20 -5
- provekit-0.2.0/tests/test_trace_sdk.py +176 -0
- provekit-0.2.0/tests/test_traces_tree.py +40 -0
- provekit-0.1.0/PKG-INFO +0 -86
- provekit-0.1.0/README.md +0 -47
- provekit-0.1.0/provekit/cli.py +0 -256
- provekit-0.1.0/provekit/migrations/versions/323eb73d463c_user_email_verified.py +0 -32
- provekit-0.1.0/provekit/migrations/versions/49e8ab812556_baseline_schema.py +0 -241
- provekit-0.1.0/provekit/migrations/versions/819ed5ff183e_workspace_ingest_key.py +0 -35
- provekit-0.1.0/provekit/migrations/versions/a1b2c3d4e5f6_user_token_version.py +0 -27
- provekit-0.1.0/provekit/models.py +0 -191
- provekit-0.1.0/provekit/routers/connections.py +0 -270
- provekit-0.1.0/provekit/routers/deployments.py +0 -161
- provekit-0.1.0/provekit/routers/flows.py +0 -188
- provekit-0.1.0/provekit/routers/library.py +0 -265
- provekit-0.1.0/provekit/routers/prompts.py +0 -72
- provekit-0.1.0/provekit/routers/run.py +0 -203
- provekit-0.1.0/provekit/routers/runtime.py +0 -103
- provekit-0.1.0/provekit/routers/traces.py +0 -65
- provekit-0.1.0/provekit/routers/usage.py +0 -42
- provekit-0.1.0/provekit/services/assertions.py +0 -135
- provekit-0.1.0/provekit/services/deploy.py +0 -63
- provekit-0.1.0/provekit/services/dispatch.py +0 -313
- provekit-0.1.0/provekit/services/flow.py +0 -299
- provekit-0.1.0/provekit/services/promptfoo.py +0 -92
- provekit-0.1.0/provekit/services/providers/__init__.py +0 -0
- provekit-0.1.0/provekit/services/providers/a2a_client.py +0 -110
- provekit-0.1.0/provekit/services/providers/agent_http.py +0 -55
- provekit-0.1.0/provekit/services/providers/llm.py +0 -364
- provekit-0.1.0/provekit/services/providers/mcp_client.py +0 -289
- provekit-0.1.0/provekit/services/templates.py +0 -69
- provekit-0.1.0/provekit/services/testfile.py +0 -122
- provekit-0.1.0/provekit/services/tooling.py +0 -194
- provekit-0.1.0/provekit/services/workspace.py +0 -91
- provekit-0.1.0/provekit/templates/flows/_manifest.json +0 -2594
- provekit-0.1.0/provekit/templates/flows/banking-action-items.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/banking-answer.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/banking-classify-intent.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/banking-draft-critique-revise.yaml +0 -75
- provekit-0.1.0/provekit/templates/flows/banking-extract-to-json.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/banking-faq-match-answer.yaml +0 -60
- provekit-0.1.0/provekit/templates/flows/banking-keyword-extract.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/banking-language-route.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/banking-moderation-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/banking-redact-summarize.yaml +0 -59
- provekit-0.1.0/provekit/templates/flows/banking-score-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/banking-sentiment-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/banking-severity-tiers.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/banking-summarize-then-decide.yaml +0 -88
- provekit-0.1.0/provekit/templates/flows/banking-tag-enrich.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/banking-tone-rewrite.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/banking-translate-reply.yaml +0 -58
- provekit-0.1.0/provekit/templates/flows/banking-triage-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/community-forum-action-items.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/community-forum-answer.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/community-forum-classify-intent.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/community-forum-draft-critique-revise.yaml +0 -75
- provekit-0.1.0/provekit/templates/flows/community-forum-extract-to-json.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/community-forum-faq-match-answer.yaml +0 -60
- provekit-0.1.0/provekit/templates/flows/community-forum-keyword-extract.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/community-forum-language-route.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/community-forum-moderation-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/community-forum-redact-summarize.yaml +0 -59
- provekit-0.1.0/provekit/templates/flows/community-forum-score-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/community-forum-sentiment-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/community-forum-severity-tiers.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/community-forum-summarize-then-decide.yaml +0 -88
- provekit-0.1.0/provekit/templates/flows/community-forum-tag-enrich.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/community-forum-tone-rewrite.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/community-forum-translate-reply.yaml +0 -58
- provekit-0.1.0/provekit/templates/flows/community-forum-triage-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/content-moderation-action-items.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/content-moderation-answer.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/content-moderation-classify-intent.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/content-moderation-draft-critique-revise.yaml +0 -75
- provekit-0.1.0/provekit/templates/flows/content-moderation-extract-to-json.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/content-moderation-faq-match-answer.yaml +0 -60
- provekit-0.1.0/provekit/templates/flows/content-moderation-keyword-extract.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/content-moderation-language-route.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/content-moderation-moderation-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/content-moderation-redact-summarize.yaml +0 -59
- provekit-0.1.0/provekit/templates/flows/content-moderation-score-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/content-moderation-sentiment-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/content-moderation-severity-tiers.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/content-moderation-summarize-then-decide.yaml +0 -88
- provekit-0.1.0/provekit/templates/flows/content-moderation-tag-enrich.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/content-moderation-tone-rewrite.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/content-moderation-translate-reply.yaml +0 -58
- provekit-0.1.0/provekit/templates/flows/content-moderation-triage-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/customer-support-action-items.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/customer-support-answer.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/customer-support-classify-intent.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/customer-support-draft-critique-revise.yaml +0 -75
- provekit-0.1.0/provekit/templates/flows/customer-support-extract-to-json.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/customer-support-faq-match-answer.yaml +0 -60
- provekit-0.1.0/provekit/templates/flows/customer-support-keyword-extract.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/customer-support-language-route.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/customer-support-moderation-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/customer-support-redact-summarize.yaml +0 -59
- provekit-0.1.0/provekit/templates/flows/customer-support-score-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/customer-support-sentiment-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/customer-support-severity-tiers.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/customer-support-summarize-then-decide.yaml +0 -88
- provekit-0.1.0/provekit/templates/flows/customer-support-tag-enrich.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/customer-support-tone-rewrite.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/customer-support-translate-reply.yaml +0 -58
- provekit-0.1.0/provekit/templates/flows/customer-support-triage-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/developer-tooling-action-items.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/developer-tooling-answer.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/developer-tooling-classify-intent.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/developer-tooling-draft-critique-revise.yaml +0 -75
- provekit-0.1.0/provekit/templates/flows/developer-tooling-extract-to-json.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/developer-tooling-faq-match-answer.yaml +0 -60
- provekit-0.1.0/provekit/templates/flows/developer-tooling-keyword-extract.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/developer-tooling-language-route.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/developer-tooling-moderation-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/developer-tooling-redact-summarize.yaml +0 -59
- provekit-0.1.0/provekit/templates/flows/developer-tooling-score-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/developer-tooling-sentiment-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/developer-tooling-severity-tiers.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/developer-tooling-summarize-then-decide.yaml +0 -88
- provekit-0.1.0/provekit/templates/flows/developer-tooling-tag-enrich.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/developer-tooling-tone-rewrite.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/developer-tooling-translate-reply.yaml +0 -58
- provekit-0.1.0/provekit/templates/flows/developer-tooling-triage-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/devrel-action-items.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/devrel-answer.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/devrel-classify-intent.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/devrel-draft-critique-revise.yaml +0 -75
- provekit-0.1.0/provekit/templates/flows/devrel-extract-to-json.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/devrel-faq-match-answer.yaml +0 -60
- provekit-0.1.0/provekit/templates/flows/devrel-keyword-extract.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/devrel-language-route.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/devrel-moderation-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/devrel-redact-summarize.yaml +0 -59
- provekit-0.1.0/provekit/templates/flows/devrel-score-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/devrel-sentiment-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/devrel-severity-tiers.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/devrel-summarize-then-decide.yaml +0 -88
- provekit-0.1.0/provekit/templates/flows/devrel-tag-enrich.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/devrel-tone-rewrite.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/devrel-translate-reply.yaml +0 -58
- provekit-0.1.0/provekit/templates/flows/devrel-triage-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/e-commerce-action-items.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/e-commerce-answer.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/e-commerce-classify-intent.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/e-commerce-draft-critique-revise.yaml +0 -75
- provekit-0.1.0/provekit/templates/flows/e-commerce-extract-to-json.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/e-commerce-faq-match-answer.yaml +0 -60
- provekit-0.1.0/provekit/templates/flows/e-commerce-keyword-extract.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/e-commerce-language-route.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/e-commerce-moderation-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/e-commerce-redact-summarize.yaml +0 -59
- provekit-0.1.0/provekit/templates/flows/e-commerce-score-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/e-commerce-sentiment-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/e-commerce-severity-tiers.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/e-commerce-summarize-then-decide.yaml +0 -88
- provekit-0.1.0/provekit/templates/flows/e-commerce-tag-enrich.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/e-commerce-tone-rewrite.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/e-commerce-translate-reply.yaml +0 -58
- provekit-0.1.0/provekit/templates/flows/e-commerce-triage-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/education-action-items.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/education-answer.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/education-classify-intent.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/education-draft-critique-revise.yaml +0 -75
- provekit-0.1.0/provekit/templates/flows/education-extract-to-json.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/education-faq-match-answer.yaml +0 -60
- provekit-0.1.0/provekit/templates/flows/education-keyword-extract.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/education-language-route.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/education-moderation-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/education-redact-summarize.yaml +0 -59
- provekit-0.1.0/provekit/templates/flows/education-score-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/education-sentiment-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/education-severity-tiers.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/education-summarize-then-decide.yaml +0 -88
- provekit-0.1.0/provekit/templates/flows/education-tag-enrich.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/education-tone-rewrite.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/education-translate-reply.yaml +0 -58
- provekit-0.1.0/provekit/templates/flows/education-triage-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/finance-action-items.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/finance-answer.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/finance-classify-intent.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/finance-draft-critique-revise.yaml +0 -75
- provekit-0.1.0/provekit/templates/flows/finance-extract-to-json.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/finance-faq-match-answer.yaml +0 -60
- provekit-0.1.0/provekit/templates/flows/finance-keyword-extract.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/finance-language-route.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/finance-moderation-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/finance-redact-summarize.yaml +0 -59
- provekit-0.1.0/provekit/templates/flows/finance-score-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/finance-sentiment-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/finance-severity-tiers.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/finance-summarize-then-decide.yaml +0 -88
- provekit-0.1.0/provekit/templates/flows/finance-tag-enrich.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/finance-tone-rewrite.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/finance-translate-reply.yaml +0 -58
- provekit-0.1.0/provekit/templates/flows/finance-triage-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/food-delivery-action-items.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/food-delivery-answer.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/food-delivery-classify-intent.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/food-delivery-draft-critique-revise.yaml +0 -75
- provekit-0.1.0/provekit/templates/flows/food-delivery-extract-to-json.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/food-delivery-faq-match-answer.yaml +0 -60
- provekit-0.1.0/provekit/templates/flows/food-delivery-keyword-extract.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/food-delivery-language-route.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/food-delivery-moderation-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/food-delivery-redact-summarize.yaml +0 -59
- provekit-0.1.0/provekit/templates/flows/food-delivery-score-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/food-delivery-sentiment-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/food-delivery-severity-tiers.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/food-delivery-summarize-then-decide.yaml +0 -88
- provekit-0.1.0/provekit/templates/flows/food-delivery-tag-enrich.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/food-delivery-tone-rewrite.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/food-delivery-translate-reply.yaml +0 -58
- provekit-0.1.0/provekit/templates/flows/food-delivery-triage-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/gaming-support-action-items.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/gaming-support-answer.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/gaming-support-classify-intent.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/gaming-support-draft-critique-revise.yaml +0 -75
- provekit-0.1.0/provekit/templates/flows/gaming-support-extract-to-json.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/gaming-support-faq-match-answer.yaml +0 -60
- provekit-0.1.0/provekit/templates/flows/gaming-support-keyword-extract.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/gaming-support-language-route.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/gaming-support-moderation-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/gaming-support-redact-summarize.yaml +0 -59
- provekit-0.1.0/provekit/templates/flows/gaming-support-score-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/gaming-support-sentiment-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/gaming-support-severity-tiers.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/gaming-support-summarize-then-decide.yaml +0 -88
- provekit-0.1.0/provekit/templates/flows/gaming-support-tag-enrich.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/gaming-support-tone-rewrite.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/gaming-support-translate-reply.yaml +0 -58
- provekit-0.1.0/provekit/templates/flows/gaming-support-triage-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/healthcare-intake-action-items.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/healthcare-intake-answer.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/healthcare-intake-classify-intent.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/healthcare-intake-draft-critique-revise.yaml +0 -75
- provekit-0.1.0/provekit/templates/flows/healthcare-intake-extract-to-json.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/healthcare-intake-faq-match-answer.yaml +0 -60
- provekit-0.1.0/provekit/templates/flows/healthcare-intake-keyword-extract.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/healthcare-intake-language-route.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/healthcare-intake-moderation-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/healthcare-intake-redact-summarize.yaml +0 -59
- provekit-0.1.0/provekit/templates/flows/healthcare-intake-score-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/healthcare-intake-sentiment-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/healthcare-intake-severity-tiers.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/healthcare-intake-summarize-then-decide.yaml +0 -88
- provekit-0.1.0/provekit/templates/flows/healthcare-intake-tag-enrich.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/healthcare-intake-tone-rewrite.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/healthcare-intake-translate-reply.yaml +0 -58
- provekit-0.1.0/provekit/templates/flows/healthcare-intake-triage-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/hr-action-items.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/hr-answer.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/hr-classify-intent.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/hr-draft-critique-revise.yaml +0 -75
- provekit-0.1.0/provekit/templates/flows/hr-extract-to-json.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/hr-faq-match-answer.yaml +0 -60
- provekit-0.1.0/provekit/templates/flows/hr-keyword-extract.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/hr-language-route.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/hr-moderation-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/hr-redact-summarize.yaml +0 -59
- provekit-0.1.0/provekit/templates/flows/hr-score-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/hr-sentiment-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/hr-severity-tiers.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/hr-summarize-then-decide.yaml +0 -88
- provekit-0.1.0/provekit/templates/flows/hr-tag-enrich.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/hr-tone-rewrite.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/hr-translate-reply.yaml +0 -58
- provekit-0.1.0/provekit/templates/flows/hr-triage-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/insurance-action-items.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/insurance-answer.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/insurance-classify-intent.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/insurance-draft-critique-revise.yaml +0 -75
- provekit-0.1.0/provekit/templates/flows/insurance-extract-to-json.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/insurance-faq-match-answer.yaml +0 -60
- provekit-0.1.0/provekit/templates/flows/insurance-keyword-extract.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/insurance-language-route.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/insurance-moderation-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/insurance-redact-summarize.yaml +0 -59
- provekit-0.1.0/provekit/templates/flows/insurance-score-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/insurance-sentiment-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/insurance-severity-tiers.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/insurance-summarize-then-decide.yaml +0 -88
- provekit-0.1.0/provekit/templates/flows/insurance-tag-enrich.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/insurance-tone-rewrite.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/insurance-translate-reply.yaml +0 -58
- provekit-0.1.0/provekit/templates/flows/insurance-triage-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/it-helpdesk-action-items.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/it-helpdesk-answer.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/it-helpdesk-classify-intent.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/it-helpdesk-draft-critique-revise.yaml +0 -75
- provekit-0.1.0/provekit/templates/flows/it-helpdesk-extract-to-json.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/it-helpdesk-faq-match-answer.yaml +0 -60
- provekit-0.1.0/provekit/templates/flows/it-helpdesk-keyword-extract.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/it-helpdesk-language-route.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/it-helpdesk-moderation-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/it-helpdesk-redact-summarize.yaml +0 -59
- provekit-0.1.0/provekit/templates/flows/it-helpdesk-score-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/it-helpdesk-sentiment-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/it-helpdesk-severity-tiers.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/it-helpdesk-summarize-then-decide.yaml +0 -88
- provekit-0.1.0/provekit/templates/flows/it-helpdesk-tag-enrich.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/it-helpdesk-tone-rewrite.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/it-helpdesk-translate-reply.yaml +0 -58
- provekit-0.1.0/provekit/templates/flows/it-helpdesk-triage-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/legal-intake-action-items.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/legal-intake-answer.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/legal-intake-classify-intent.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/legal-intake-draft-critique-revise.yaml +0 -75
- provekit-0.1.0/provekit/templates/flows/legal-intake-extract-to-json.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/legal-intake-faq-match-answer.yaml +0 -60
- provekit-0.1.0/provekit/templates/flows/legal-intake-keyword-extract.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/legal-intake-language-route.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/legal-intake-moderation-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/legal-intake-redact-summarize.yaml +0 -59
- provekit-0.1.0/provekit/templates/flows/legal-intake-score-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/legal-intake-sentiment-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/legal-intake-severity-tiers.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/legal-intake-summarize-then-decide.yaml +0 -88
- provekit-0.1.0/provekit/templates/flows/legal-intake-tag-enrich.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/legal-intake-tone-rewrite.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/legal-intake-translate-reply.yaml +0 -58
- provekit-0.1.0/provekit/templates/flows/legal-intake-triage-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/logistics-action-items.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/logistics-answer.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/logistics-classify-intent.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/logistics-draft-critique-revise.yaml +0 -75
- provekit-0.1.0/provekit/templates/flows/logistics-extract-to-json.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/logistics-faq-match-answer.yaml +0 -60
- provekit-0.1.0/provekit/templates/flows/logistics-keyword-extract.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/logistics-language-route.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/logistics-moderation-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/logistics-redact-summarize.yaml +0 -59
- provekit-0.1.0/provekit/templates/flows/logistics-score-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/logistics-sentiment-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/logistics-severity-tiers.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/logistics-summarize-then-decide.yaml +0 -88
- provekit-0.1.0/provekit/templates/flows/logistics-tag-enrich.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/logistics-tone-rewrite.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/logistics-translate-reply.yaml +0 -58
- provekit-0.1.0/provekit/templates/flows/logistics-triage-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/marketing-action-items.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/marketing-answer.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/marketing-classify-intent.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/marketing-draft-critique-revise.yaml +0 -75
- provekit-0.1.0/provekit/templates/flows/marketing-extract-to-json.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/marketing-faq-match-answer.yaml +0 -60
- provekit-0.1.0/provekit/templates/flows/marketing-keyword-extract.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/marketing-language-route.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/marketing-moderation-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/marketing-redact-summarize.yaml +0 -59
- provekit-0.1.0/provekit/templates/flows/marketing-score-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/marketing-sentiment-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/marketing-severity-tiers.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/marketing-summarize-then-decide.yaml +0 -88
- provekit-0.1.0/provekit/templates/flows/marketing-tag-enrich.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/marketing-tone-rewrite.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/marketing-translate-reply.yaml +0 -58
- provekit-0.1.0/provekit/templates/flows/marketing-triage-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/nonprofit-action-items.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/nonprofit-answer.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/nonprofit-classify-intent.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/nonprofit-draft-critique-revise.yaml +0 -75
- provekit-0.1.0/provekit/templates/flows/nonprofit-extract-to-json.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/nonprofit-faq-match-answer.yaml +0 -60
- provekit-0.1.0/provekit/templates/flows/nonprofit-keyword-extract.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/nonprofit-language-route.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/nonprofit-moderation-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/nonprofit-redact-summarize.yaml +0 -59
- provekit-0.1.0/provekit/templates/flows/nonprofit-score-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/nonprofit-sentiment-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/nonprofit-severity-tiers.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/nonprofit-summarize-then-decide.yaml +0 -88
- provekit-0.1.0/provekit/templates/flows/nonprofit-tag-enrich.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/nonprofit-tone-rewrite.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/nonprofit-translate-reply.yaml +0 -58
- provekit-0.1.0/provekit/templates/flows/nonprofit-triage-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/real-estate-action-items.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/real-estate-answer.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/real-estate-classify-intent.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/real-estate-draft-critique-revise.yaml +0 -75
- provekit-0.1.0/provekit/templates/flows/real-estate-extract-to-json.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/real-estate-faq-match-answer.yaml +0 -60
- provekit-0.1.0/provekit/templates/flows/real-estate-keyword-extract.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/real-estate-language-route.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/real-estate-moderation-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/real-estate-redact-summarize.yaml +0 -59
- provekit-0.1.0/provekit/templates/flows/real-estate-score-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/real-estate-sentiment-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/real-estate-severity-tiers.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/real-estate-summarize-then-decide.yaml +0 -88
- provekit-0.1.0/provekit/templates/flows/real-estate-tag-enrich.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/real-estate-tone-rewrite.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/real-estate-translate-reply.yaml +0 -58
- provekit-0.1.0/provekit/templates/flows/real-estate-triage-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/recruiting-action-items.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/recruiting-answer.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/recruiting-classify-intent.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/recruiting-draft-critique-revise.yaml +0 -75
- provekit-0.1.0/provekit/templates/flows/recruiting-extract-to-json.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/recruiting-faq-match-answer.yaml +0 -60
- provekit-0.1.0/provekit/templates/flows/recruiting-keyword-extract.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/recruiting-language-route.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/recruiting-moderation-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/recruiting-redact-summarize.yaml +0 -59
- provekit-0.1.0/provekit/templates/flows/recruiting-score-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/recruiting-sentiment-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/recruiting-severity-tiers.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/recruiting-summarize-then-decide.yaml +0 -88
- provekit-0.1.0/provekit/templates/flows/recruiting-tag-enrich.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/recruiting-tone-rewrite.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/recruiting-translate-reply.yaml +0 -58
- provekit-0.1.0/provekit/templates/flows/recruiting-triage-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/research-action-items.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/research-answer.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/research-classify-intent.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/research-draft-critique-revise.yaml +0 -75
- provekit-0.1.0/provekit/templates/flows/research-extract-to-json.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/research-faq-match-answer.yaml +0 -60
- provekit-0.1.0/provekit/templates/flows/research-keyword-extract.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/research-language-route.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/research-moderation-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/research-redact-summarize.yaml +0 -59
- provekit-0.1.0/provekit/templates/flows/research-score-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/research-sentiment-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/research-severity-tiers.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/research-summarize-then-decide.yaml +0 -88
- provekit-0.1.0/provekit/templates/flows/research-tag-enrich.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/research-tone-rewrite.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/research-translate-reply.yaml +0 -58
- provekit-0.1.0/provekit/templates/flows/research-triage-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/sales-lead-action-items.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/sales-lead-answer.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/sales-lead-classify-intent.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/sales-lead-draft-critique-revise.yaml +0 -75
- provekit-0.1.0/provekit/templates/flows/sales-lead-extract-to-json.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/sales-lead-faq-match-answer.yaml +0 -60
- provekit-0.1.0/provekit/templates/flows/sales-lead-keyword-extract.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/sales-lead-language-route.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/sales-lead-moderation-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/sales-lead-redact-summarize.yaml +0 -59
- provekit-0.1.0/provekit/templates/flows/sales-lead-score-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/sales-lead-sentiment-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/sales-lead-severity-tiers.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/sales-lead-summarize-then-decide.yaml +0 -88
- provekit-0.1.0/provekit/templates/flows/sales-lead-tag-enrich.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/sales-lead-tone-rewrite.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/sales-lead-translate-reply.yaml +0 -58
- provekit-0.1.0/provekit/templates/flows/sales-lead-triage-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/travel-action-items.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/travel-answer.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/travel-classify-intent.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/travel-draft-critique-revise.yaml +0 -75
- provekit-0.1.0/provekit/templates/flows/travel-extract-to-json.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/travel-faq-match-answer.yaml +0 -60
- provekit-0.1.0/provekit/templates/flows/travel-keyword-extract.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/travel-language-route.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/travel-moderation-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/travel-redact-summarize.yaml +0 -59
- provekit-0.1.0/provekit/templates/flows/travel-score-gate.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/travel-sentiment-route.yaml +0 -73
- provekit-0.1.0/provekit/templates/flows/travel-severity-tiers.yaml +0 -103
- provekit-0.1.0/provekit/templates/flows/travel-summarize-then-decide.yaml +0 -88
- provekit-0.1.0/provekit/templates/flows/travel-tag-enrich.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/travel-tone-rewrite.yaml +0 -43
- provekit-0.1.0/provekit/templates/flows/travel-translate-reply.yaml +0 -58
- provekit-0.1.0/provekit/templates/flows/travel-triage-route.yaml +0 -73
- provekit-0.1.0/provekit.egg-info/PKG-INFO +0 -86
- provekit-0.1.0/provekit.egg-info/SOURCES.txt +0 -516
- provekit-0.1.0/provekit.egg-info/entry_points.txt +0 -2
- provekit-0.1.0/provekit.egg-info/requires.txt +0 -18
- provekit-0.1.0/pyproject.toml +0 -89
- provekit-0.1.0/tests/test_a2a.py +0 -81
- provekit-0.1.0/tests/test_cli.py +0 -142
- provekit-0.1.0/tests/test_connection_secrets.py +0 -108
- provekit-0.1.0/tests/test_cov_assertions.py +0 -554
- provekit-0.1.0/tests/test_cov_dispatch.py +0 -573
- provekit-0.1.0/tests/test_cov_flow.py +0 -606
- provekit-0.1.0/tests/test_cov_infra.py +0 -1164
- provekit-0.1.0/tests/test_cov_library_run.py +0 -477
- provekit-0.1.0/tests/test_cov_llm_mcp.py +0 -660
- provekit-0.1.0/tests/test_cov_routers.py +0 -887
- provekit-0.1.0/tests/test_deployments.py +0 -156
- provekit-0.1.0/tests/test_hardening_extra.py +0 -70
- provekit-0.1.0/tests/test_import_export.py +0 -68
- provekit-0.1.0/tests/test_limits.py +0 -78
- provekit-0.1.0/tests/test_llm_providers.py +0 -174
- provekit-0.1.0/tests/test_mcp_client.py +0 -141
- provekit-0.1.0/tests/test_templates.py +0 -66
- provekit-0.1.0/tests/test_tenancy.py +0 -65
- provekit-0.1.0/tests/test_testfile.py +0 -68
- provekit-0.1.0/tests/test_tooling.py +0 -520
- provekit-0.1.0/tests/test_usage.py +0 -27
- {provekit-0.1.0 → provekit-0.2.0}/provekit/__init__.py +0 -0
- {provekit-0.1.0 → provekit-0.2.0}/provekit/config.py +0 -0
- {provekit-0.1.0 → provekit-0.2.0}/provekit/migrations/env.py +0 -0
- {provekit-0.1.0 → provekit-0.2.0}/provekit/migrations/script.py.mako +0 -0
- {provekit-0.1.0 → provekit-0.2.0}/provekit/observability.py +0 -0
- {provekit-0.1.0 → provekit-0.2.0}/provekit/routers/__init__.py +0 -0
- {provekit-0.1.0 → provekit-0.2.0}/provekit/routers/auth.py +0 -0
- {provekit-0.1.0 → provekit-0.2.0}/provekit/services/__init__.py +0 -0
- {provekit-0.1.0 → provekit-0.2.0}/provekit/services/auth.py +0 -0
- {provekit-0.1.0 → provekit-0.2.0}/provekit/services/email.py +0 -0
- {provekit-0.1.0 → provekit-0.2.0}/provekit/services/limits.py +0 -0
- {provekit-0.1.0 → provekit-0.2.0}/provekit/services/masking.py +0 -0
- {provekit-0.1.0 → provekit-0.2.0}/provekit/services/netguard.py +0 -0
- {provekit-0.1.0 → provekit-0.2.0}/provekit/services/runstore.py +0 -0
- {provekit-0.1.0 → provekit-0.2.0}/provekit/services/sealing.py +0 -0
- {provekit-0.1.0 → provekit-0.2.0}/provekit.egg-info/dependency_links.txt +0 -0
- {provekit-0.1.0 → provekit-0.2.0}/provekit.egg-info/top_level.txt +0 -0
- {provekit-0.1.0 → provekit-0.2.0}/setup.cfg +0 -0
- {provekit-0.1.0 → provekit-0.2.0}/tests/test_account_recovery.py +0 -0
- {provekit-0.1.0 → provekit-0.2.0}/tests/test_auth.py +0 -0
- {provekit-0.1.0 → provekit-0.2.0}/tests/test_auth_hardening.py +0 -0
- {provekit-0.1.0 → provekit-0.2.0}/tests/test_cov_limits_auth.py +0 -0
- {provekit-0.1.0 → provekit-0.2.0}/tests/test_observability.py +0 -0
- {provekit-0.1.0 → provekit-0.2.0}/tests/test_runstore.py +0 -0
provekit-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: provekit
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Drop-in agent tracing — add one decorator, get a project key, review every run your agent makes.
|
|
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,tracing,observability,opentelemetry,openai,anthropic,otel
|
|
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 :: System :: Monitoring
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
20
|
+
Requires-Python: >=3.11
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
Requires-Dist: httpx<1,>=0.28
|
|
23
|
+
Provides-Extra: server
|
|
24
|
+
Requires-Dist: fastapi<1,>=0.115; extra == "server"
|
|
25
|
+
Requires-Dist: uvicorn[standard]<1,>=0.34; extra == "server"
|
|
26
|
+
Requires-Dist: sqlalchemy<3,>=2.0; extra == "server"
|
|
27
|
+
Requires-Dist: pydantic<3,>=2.10; extra == "server"
|
|
28
|
+
Requires-Dist: pydantic-settings<3,>=2.7; extra == "server"
|
|
29
|
+
Requires-Dist: cryptography<50,>=42; extra == "server"
|
|
30
|
+
Requires-Dist: anyio<5,>=4; extra == "server"
|
|
31
|
+
Requires-Dist: alembic<2,>=1.18; extra == "server"
|
|
32
|
+
Requires-Dist: psycopg[binary]<4,>=3.3; extra == "server"
|
|
33
|
+
Requires-Dist: email-validator<3,>=2.2; extra == "server"
|
|
34
|
+
Requires-Dist: redis<6,>=5.2; extra == "server"
|
|
35
|
+
Requires-Dist: sentry-sdk[fastapi]<3,>=2.20; extra == "server"
|
|
36
|
+
Provides-Extra: trace
|
|
37
|
+
Requires-Dist: opentelemetry-api<2,>=1.20; extra == "trace"
|
|
38
|
+
Requires-Dist: opentelemetry-sdk<2,>=1.20; extra == "trace"
|
|
39
|
+
Requires-Dist: openinference-instrumentation-openai>=0.1; extra == "trace"
|
|
40
|
+
Requires-Dist: openinference-instrumentation-anthropic>=0.1; extra == "trace"
|
|
41
|
+
Provides-Extra: dev
|
|
42
|
+
Requires-Dist: pytest==9.1.1; extra == "dev"
|
|
43
|
+
Requires-Dist: pytest-cov==6.0.0; extra == "dev"
|
|
44
|
+
Requires-Dist: ruff==0.9.2; extra == "dev"
|
|
45
|
+
|
|
46
|
+
# ProveKit
|
|
47
|
+
|
|
48
|
+
**One decorator. The whole agent flow.** Add one `@pk.trace` at your agent's entrypoint and
|
|
49
|
+
review every run — the model calls, tools, and steps — as a nested flow in your ProveKit
|
|
50
|
+
portal. OpenAI/Anthropic calls capture themselves. Open source, self-hostable, no framework
|
|
51
|
+
lock-in.
|
|
52
|
+
|
|
53
|
+
## Install
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
pip install "provekit[trace]"
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Use
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
import provekit.trace as pk
|
|
63
|
+
|
|
64
|
+
# .env
|
|
65
|
+
# PROVEKIT_API_KEY=pk_... (create a project + key in the portal)
|
|
66
|
+
# PROVEKIT_ENDPOINT=https://your-provekit-host
|
|
67
|
+
|
|
68
|
+
@pk.trace(name="support-agent")
|
|
69
|
+
def run_agent(question: str) -> str:
|
|
70
|
+
docs = retrieve(question) # wrap sub-steps with `with pk.span("retrieve"):`
|
|
71
|
+
return chat(question, docs) # the OpenAI/Anthropic call captures itself
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Run your agent, open **Traces** in the portal, and every run shows up as a nested waterfall
|
|
75
|
+
with per-span input, output, and token usage.
|
|
76
|
+
|
|
77
|
+
It's OpenTelemetry under the hood, so your data is portable and nothing is locked in — but
|
|
78
|
+
you never have to touch OTel. Fail-open by design: if the key/endpoint are unset or the
|
|
79
|
+
portal is unreachable, your app runs completely unaffected.
|
|
80
|
+
|
|
81
|
+
## Run the portal (self-host)
|
|
82
|
+
|
|
83
|
+
The web app + ingest server ship in the same package:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
pip install "provekit[server]"
|
|
87
|
+
uvicorn provekit.main:app --port 8100
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
See the [repo](https://github.com/MobirizerServices/ProveKit) for Docker/compose and the
|
|
91
|
+
full [tracing guide](https://github.com/MobirizerServices/ProveKit/blob/main/docs/TRACING.md).
|
|
92
|
+
|
|
93
|
+
- Repository: https://github.com/MobirizerServices/ProveKit
|
|
94
|
+
- License: MIT
|
provekit-0.2.0/README.md
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# ProveKit
|
|
2
|
+
|
|
3
|
+
**One decorator. The whole agent flow.** Add one `@pk.trace` at your agent's entrypoint and
|
|
4
|
+
review every run — the model calls, tools, and steps — as a nested flow in your ProveKit
|
|
5
|
+
portal. OpenAI/Anthropic calls capture themselves. Open source, self-hostable, no framework
|
|
6
|
+
lock-in.
|
|
7
|
+
|
|
8
|
+
## Install
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
pip install "provekit[trace]"
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Use
|
|
15
|
+
|
|
16
|
+
```python
|
|
17
|
+
import provekit.trace as pk
|
|
18
|
+
|
|
19
|
+
# .env
|
|
20
|
+
# PROVEKIT_API_KEY=pk_... (create a project + key in the portal)
|
|
21
|
+
# PROVEKIT_ENDPOINT=https://your-provekit-host
|
|
22
|
+
|
|
23
|
+
@pk.trace(name="support-agent")
|
|
24
|
+
def run_agent(question: str) -> str:
|
|
25
|
+
docs = retrieve(question) # wrap sub-steps with `with pk.span("retrieve"):`
|
|
26
|
+
return chat(question, docs) # the OpenAI/Anthropic call captures itself
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Run your agent, open **Traces** in the portal, and every run shows up as a nested waterfall
|
|
30
|
+
with per-span input, output, and token usage.
|
|
31
|
+
|
|
32
|
+
It's OpenTelemetry under the hood, so your data is portable and nothing is locked in — but
|
|
33
|
+
you never have to touch OTel. Fail-open by design: if the key/endpoint are unset or the
|
|
34
|
+
portal is unreachable, your app runs completely unaffected.
|
|
35
|
+
|
|
36
|
+
## Run the portal (self-host)
|
|
37
|
+
|
|
38
|
+
The web app + ingest server ship in the same package:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
pip install "provekit[server]"
|
|
42
|
+
uvicorn provekit.main:app --port 8100
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
See the [repo](https://github.com/MobirizerServices/ProveKit) for Docker/compose and the
|
|
46
|
+
full [tracing guide](https://github.com/MobirizerServices/ProveKit/blob/main/docs/TRACING.md).
|
|
47
|
+
|
|
48
|
+
- Repository: https://github.com/MobirizerServices/ProveKit
|
|
49
|
+
- License: MIT
|
|
@@ -62,16 +62,6 @@ def init_db() -> None:
|
|
|
62
62
|
_run_migrations()
|
|
63
63
|
|
|
64
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
65
|
# Postgres advisory-lock key ("AGMN") used to serialize migrations across uvicorn workers.
|
|
76
66
|
_MIGRATION_LOCK_ID = 0x4147_4D4E
|
|
77
67
|
|
|
@@ -113,20 +103,4 @@ def _run_migrations() -> None:
|
|
|
113
103
|
|
|
114
104
|
def _migrate_to_head(cfg) -> None:
|
|
115
105
|
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
106
|
command.upgrade(cfg, "head")
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
"""ProveKit —
|
|
2
|
-
|
|
1
|
+
"""ProveKit — drop-in agent tracing. Add one decorator, get a project key, and review
|
|
2
|
+
every run your agent makes. No connections to configure, no SDK to swap."""
|
|
3
3
|
import logging
|
|
4
4
|
from contextlib import asynccontextmanager
|
|
5
5
|
|
|
@@ -7,8 +7,7 @@ from fastapi import FastAPI
|
|
|
7
7
|
from fastapi.middleware.cors import CORSMiddleware
|
|
8
8
|
|
|
9
9
|
from .config import get_settings
|
|
10
|
-
from .database import
|
|
11
|
-
from .models import Connection
|
|
10
|
+
from .database import init_db
|
|
12
11
|
from .observability import (
|
|
13
12
|
BodySizeLimitMiddleware,
|
|
14
13
|
RequestIDMiddleware,
|
|
@@ -17,7 +16,7 @@ from .observability import (
|
|
|
17
16
|
init_sentry,
|
|
18
17
|
setup_logging,
|
|
19
18
|
)
|
|
20
|
-
from .routers import
|
|
19
|
+
from .routers import apikeys, auth, traces
|
|
21
20
|
|
|
22
21
|
logging.basicConfig(level=logging.INFO)
|
|
23
22
|
settings = get_settings()
|
|
@@ -25,16 +24,6 @@ setup_logging()
|
|
|
25
24
|
init_sentry()
|
|
26
25
|
|
|
27
26
|
|
|
28
|
-
def _reseal_connections(db) -> None:
|
|
29
|
-
"""Upgrade plaintext secrets from older databases to encrypted-at-rest: force each
|
|
30
|
-
config back through SealedJSON's bind processor (flag_modified beats SQLAlchemy's
|
|
31
|
-
equal-value change suppression). Idempotent — already-sealed values stay sealed."""
|
|
32
|
-
from sqlalchemy.orm.attributes import flag_modified
|
|
33
|
-
for c in db.query(Connection).all():
|
|
34
|
-
flag_modified(c, "config")
|
|
35
|
-
db.commit()
|
|
36
|
-
|
|
37
|
-
|
|
38
27
|
_WEAK_KEYS = {"", "dev-only-change-me", "change-me", "changeme", "secret"}
|
|
39
28
|
|
|
40
29
|
|
|
@@ -67,11 +56,6 @@ async def lifespan(app: FastAPI):
|
|
|
67
56
|
except Exception:
|
|
68
57
|
pass
|
|
69
58
|
init_db()
|
|
70
|
-
db = SessionLocal()
|
|
71
|
-
try:
|
|
72
|
-
_reseal_connections(db) # per-workspace seeding happens on first workspace access
|
|
73
|
-
finally:
|
|
74
|
-
db.close()
|
|
75
59
|
yield
|
|
76
60
|
|
|
77
61
|
|
|
@@ -93,16 +77,10 @@ app.add_middleware(
|
|
|
93
77
|
)
|
|
94
78
|
|
|
95
79
|
app.include_router(auth.router)
|
|
96
|
-
app.include_router(
|
|
97
|
-
app.include_router(library.router)
|
|
98
|
-
app.include_router(prompts.router)
|
|
99
|
-
app.include_router(flows.router)
|
|
100
|
-
app.include_router(run.router)
|
|
80
|
+
app.include_router(apikeys.router)
|
|
101
81
|
app.include_router(traces.router)
|
|
102
82
|
app.include_router(traces.ws_router)
|
|
103
|
-
app.include_router(
|
|
104
|
-
app.include_router(runtime.router)
|
|
105
|
-
app.include_router(usage.router)
|
|
83
|
+
app.include_router(traces.runs_router)
|
|
106
84
|
|
|
107
85
|
|
|
108
86
|
@app.get("/")
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"""baseline
|
|
2
|
+
|
|
3
|
+
Revision ID: 9d2c06bfa4e6
|
|
4
|
+
Revises:
|
|
5
|
+
Create Date: 2026-07-18 22:58:47.035691
|
|
6
|
+
"""
|
|
7
|
+
from alembic import op
|
|
8
|
+
import sqlalchemy as sa
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
revision = '9d2c06bfa4e6'
|
|
12
|
+
down_revision = None
|
|
13
|
+
branch_labels = None
|
|
14
|
+
depends_on = None
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def upgrade() -> None:
|
|
18
|
+
# ### commands auto generated by Alembic - please adjust! ###
|
|
19
|
+
op.create_table('users',
|
|
20
|
+
sa.Column('id', sa.Integer(), nullable=False),
|
|
21
|
+
sa.Column('email', sa.String(length=255), nullable=False),
|
|
22
|
+
sa.Column('name', sa.String(length=160), nullable=False),
|
|
23
|
+
sa.Column('password_hash', sa.String(length=255), nullable=False),
|
|
24
|
+
sa.Column('auth_provider', sa.String(length=32), nullable=False),
|
|
25
|
+
sa.Column('email_verified', sa.Boolean(), nullable=False),
|
|
26
|
+
sa.Column('token_version', sa.Integer(), nullable=False),
|
|
27
|
+
sa.Column('created_at', sa.DateTime(), nullable=False),
|
|
28
|
+
sa.PrimaryKeyConstraint('id', name=op.f('pk_users')),
|
|
29
|
+
sa.UniqueConstraint('email', name=op.f('uq_users_email'))
|
|
30
|
+
)
|
|
31
|
+
op.create_table('workspaces',
|
|
32
|
+
sa.Column('id', sa.Integer(), nullable=False),
|
|
33
|
+
sa.Column('name', sa.String(length=160), nullable=False),
|
|
34
|
+
sa.Column('owner_user_id', sa.Integer(), nullable=False),
|
|
35
|
+
sa.Column('ingest_key_hash', sa.String(length=128), nullable=False),
|
|
36
|
+
sa.Column('created_at', sa.DateTime(), nullable=False),
|
|
37
|
+
sa.ForeignKeyConstraint(['owner_user_id'], ['users.id'], name=op.f('fk_workspaces_owner_user_id_users')),
|
|
38
|
+
sa.PrimaryKeyConstraint('id', name=op.f('pk_workspaces'))
|
|
39
|
+
)
|
|
40
|
+
with op.batch_alter_table('workspaces', schema=None) as batch_op:
|
|
41
|
+
batch_op.create_index(batch_op.f('ix_workspaces_ingest_key_hash'), ['ingest_key_hash'], unique=False)
|
|
42
|
+
batch_op.create_index(batch_op.f('ix_workspaces_owner_user_id'), ['owner_user_id'], unique=False)
|
|
43
|
+
|
|
44
|
+
op.create_table('api_keys',
|
|
45
|
+
sa.Column('id', sa.Integer(), nullable=False),
|
|
46
|
+
sa.Column('workspace_id', sa.Integer(), nullable=True),
|
|
47
|
+
sa.Column('name', sa.String(length=120), nullable=False),
|
|
48
|
+
sa.Column('prefix', sa.String(length=16), nullable=False),
|
|
49
|
+
sa.Column('key_hash', sa.String(length=128), nullable=False),
|
|
50
|
+
sa.Column('last_used_at', sa.DateTime(), nullable=True),
|
|
51
|
+
sa.Column('revoked', sa.Boolean(), nullable=False),
|
|
52
|
+
sa.Column('created_at', sa.DateTime(), nullable=False),
|
|
53
|
+
sa.ForeignKeyConstraint(['workspace_id'], ['workspaces.id'], name=op.f('fk_api_keys_workspace_id_workspaces')),
|
|
54
|
+
sa.PrimaryKeyConstraint('id', name=op.f('pk_api_keys'))
|
|
55
|
+
)
|
|
56
|
+
with op.batch_alter_table('api_keys', schema=None) as batch_op:
|
|
57
|
+
batch_op.create_index(batch_op.f('ix_api_keys_key_hash'), ['key_hash'], unique=False)
|
|
58
|
+
batch_op.create_index(batch_op.f('ix_api_keys_workspace_id'), ['workspace_id'], unique=False)
|
|
59
|
+
|
|
60
|
+
op.create_table('runs',
|
|
61
|
+
sa.Column('id', sa.Integer(), nullable=False),
|
|
62
|
+
sa.Column('workspace_id', sa.Integer(), nullable=True),
|
|
63
|
+
sa.Column('type', sa.String(length=16), nullable=False),
|
|
64
|
+
sa.Column('label', sa.String(length=200), nullable=False),
|
|
65
|
+
sa.Column('request', sa.JSON(), nullable=False),
|
|
66
|
+
sa.Column('result', sa.JSON(), nullable=False),
|
|
67
|
+
sa.Column('status', sa.String(length=16), nullable=False),
|
|
68
|
+
sa.Column('duration_ms', sa.Integer(), nullable=False),
|
|
69
|
+
sa.Column('error', sa.Text(), nullable=False),
|
|
70
|
+
sa.Column('trace_id', sa.String(length=32), nullable=False),
|
|
71
|
+
sa.Column('span_id', sa.String(length=16), nullable=False),
|
|
72
|
+
sa.Column('parent_span_id', sa.String(length=16), nullable=False),
|
|
73
|
+
sa.Column('created_at', sa.DateTime(), nullable=False),
|
|
74
|
+
sa.ForeignKeyConstraint(['workspace_id'], ['workspaces.id'], name=op.f('fk_runs_workspace_id_workspaces')),
|
|
75
|
+
sa.PrimaryKeyConstraint('id', name=op.f('pk_runs'))
|
|
76
|
+
)
|
|
77
|
+
with op.batch_alter_table('runs', schema=None) as batch_op:
|
|
78
|
+
batch_op.create_index(batch_op.f('ix_runs_trace_id'), ['trace_id'], unique=False)
|
|
79
|
+
batch_op.create_index(batch_op.f('ix_runs_workspace_id'), ['workspace_id'], unique=False)
|
|
80
|
+
|
|
81
|
+
op.create_table('workspace_members',
|
|
82
|
+
sa.Column('id', sa.Integer(), nullable=False),
|
|
83
|
+
sa.Column('workspace_id', sa.Integer(), nullable=False),
|
|
84
|
+
sa.Column('user_id', sa.Integer(), nullable=False),
|
|
85
|
+
sa.Column('role', sa.String(length=16), nullable=False),
|
|
86
|
+
sa.ForeignKeyConstraint(['user_id'], ['users.id'], name=op.f('fk_workspace_members_user_id_users')),
|
|
87
|
+
sa.ForeignKeyConstraint(['workspace_id'], ['workspaces.id'], name=op.f('fk_workspace_members_workspace_id_workspaces')),
|
|
88
|
+
sa.PrimaryKeyConstraint('id', name=op.f('pk_workspace_members')),
|
|
89
|
+
sa.UniqueConstraint('workspace_id', 'user_id', name='uq_member')
|
|
90
|
+
)
|
|
91
|
+
with op.batch_alter_table('workspace_members', schema=None) as batch_op:
|
|
92
|
+
batch_op.create_index(batch_op.f('ix_workspace_members_user_id'), ['user_id'], unique=False)
|
|
93
|
+
batch_op.create_index(batch_op.f('ix_workspace_members_workspace_id'), ['workspace_id'], unique=False)
|
|
94
|
+
|
|
95
|
+
# ### end Alembic commands ###
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def downgrade() -> None:
|
|
99
|
+
# ### commands auto generated by Alembic - please adjust! ###
|
|
100
|
+
with op.batch_alter_table('workspace_members', schema=None) as batch_op:
|
|
101
|
+
batch_op.drop_index(batch_op.f('ix_workspace_members_workspace_id'))
|
|
102
|
+
batch_op.drop_index(batch_op.f('ix_workspace_members_user_id'))
|
|
103
|
+
|
|
104
|
+
op.drop_table('workspace_members')
|
|
105
|
+
with op.batch_alter_table('runs', schema=None) as batch_op:
|
|
106
|
+
batch_op.drop_index(batch_op.f('ix_runs_workspace_id'))
|
|
107
|
+
batch_op.drop_index(batch_op.f('ix_runs_trace_id'))
|
|
108
|
+
|
|
109
|
+
op.drop_table('runs')
|
|
110
|
+
with op.batch_alter_table('api_keys', schema=None) as batch_op:
|
|
111
|
+
batch_op.drop_index(batch_op.f('ix_api_keys_workspace_id'))
|
|
112
|
+
batch_op.drop_index(batch_op.f('ix_api_keys_key_hash'))
|
|
113
|
+
|
|
114
|
+
op.drop_table('api_keys')
|
|
115
|
+
with op.batch_alter_table('workspaces', schema=None) as batch_op:
|
|
116
|
+
batch_op.drop_index(batch_op.f('ix_workspaces_owner_user_id'))
|
|
117
|
+
batch_op.drop_index(batch_op.f('ix_workspaces_ingest_key_hash'))
|
|
118
|
+
|
|
119
|
+
op.drop_table('workspaces')
|
|
120
|
+
op.drop_table('users')
|
|
121
|
+
# ### end Alembic commands ###
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"""ProveKit data model: accounts, projects (workspaces), project keys, and captured
|
|
2
|
+
runs (the spans of an agent trace)."""
|
|
3
|
+
from datetime import datetime, timezone
|
|
4
|
+
|
|
5
|
+
from sqlalchemy import DateTime, ForeignKey, Integer, JSON, String, Text, UniqueConstraint
|
|
6
|
+
from sqlalchemy.orm import Mapped, mapped_column
|
|
7
|
+
|
|
8
|
+
from .database import Base
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def _ws_fk() -> Mapped[int]:
|
|
12
|
+
"""Workspace FK shared by every tenant-scoped table (indexed for per-workspace queries)."""
|
|
13
|
+
return mapped_column(ForeignKey("workspaces.id"), index=True, nullable=True)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _now() -> datetime:
|
|
17
|
+
return datetime.now(timezone.utc)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def iso_utc(dt: datetime | None) -> str | None:
|
|
21
|
+
"""Serialize a stored timestamp as ISO-8601 with an explicit UTC offset. Timestamps
|
|
22
|
+
are written in UTC (_now), but SQLite hands them back naive — without the offset the
|
|
23
|
+
browser would parse them as local time."""
|
|
24
|
+
if dt is None:
|
|
25
|
+
return None
|
|
26
|
+
if dt.tzinfo is None:
|
|
27
|
+
dt = dt.replace(tzinfo=timezone.utc)
|
|
28
|
+
return dt.isoformat()
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class User(Base):
|
|
32
|
+
"""An account. password_hash is null for OAuth-only users."""
|
|
33
|
+
__tablename__ = "users"
|
|
34
|
+
id: Mapped[int] = mapped_column(primary_key=True)
|
|
35
|
+
email: Mapped[str] = mapped_column(String(255), unique=True)
|
|
36
|
+
name: Mapped[str] = mapped_column(String(160), default="")
|
|
37
|
+
password_hash: Mapped[str] = mapped_column(String(255), default="")
|
|
38
|
+
auth_provider: Mapped[str] = mapped_column(String(32), default="password") # password | github | local
|
|
39
|
+
email_verified: Mapped[bool] = mapped_column(default=False)
|
|
40
|
+
# Bumped on password reset to revoke every previously-issued token (sessions + the
|
|
41
|
+
# just-used reset link): tokens embed the version and are rejected once it moves on.
|
|
42
|
+
token_version: Mapped[int] = mapped_column(default=0)
|
|
43
|
+
created_at: Mapped[datetime] = mapped_column(DateTime, default=_now)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class Workspace(Base):
|
|
47
|
+
"""A project — a tenant boundary. Every user gets a default one; teams share one later."""
|
|
48
|
+
__tablename__ = "workspaces"
|
|
49
|
+
id: Mapped[int] = mapped_column(primary_key=True)
|
|
50
|
+
name: Mapped[str] = mapped_column(String(160), default="My project")
|
|
51
|
+
owner_user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), index=True)
|
|
52
|
+
# Bearer token for unattended OTLP trace ingest (exporters can't send cookies).
|
|
53
|
+
ingest_key_hash: Mapped[str] = mapped_column(String(128), default="", index=True)
|
|
54
|
+
created_at: Mapped[datetime] = mapped_column(DateTime, default=_now)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class WorkspaceMember(Base):
|
|
58
|
+
__tablename__ = "workspace_members"
|
|
59
|
+
id: Mapped[int] = mapped_column(primary_key=True)
|
|
60
|
+
workspace_id: Mapped[int] = mapped_column(ForeignKey("workspaces.id"), index=True)
|
|
61
|
+
user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), index=True)
|
|
62
|
+
role: Mapped[str] = mapped_column(String(16), default="member") # owner | member
|
|
63
|
+
__table_args__ = (UniqueConstraint("workspace_id", "user_id", name="uq_member"),)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class ApiKey(Base):
|
|
67
|
+
"""A named, revocable project key (a pk_ bearer key) for shipping traces.
|
|
68
|
+
|
|
69
|
+
Unlike the single per-workspace `ingest_key_hash`, a project can hold many of these —
|
|
70
|
+
one per app or environment — each revocable on its own. Only the SHA-256 hash is
|
|
71
|
+
stored; the plaintext (`pk_…`) is shown exactly once, at creation."""
|
|
72
|
+
__tablename__ = "api_keys"
|
|
73
|
+
id: Mapped[int] = mapped_column(primary_key=True)
|
|
74
|
+
workspace_id: Mapped[int] = _ws_fk()
|
|
75
|
+
name: Mapped[str] = mapped_column(String(120), default="")
|
|
76
|
+
prefix: Mapped[str] = mapped_column(String(16), default="") # e.g. "pk_A1b2C3d4" for display
|
|
77
|
+
key_hash: Mapped[str] = mapped_column(String(128), index=True)
|
|
78
|
+
last_used_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
|
|
79
|
+
revoked: Mapped[bool] = mapped_column(default=False)
|
|
80
|
+
created_at: Mapped[datetime] = mapped_column(DateTime, default=_now)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class Run(Base):
|
|
84
|
+
"""One captured span. A trace's spans share a trace_id; the tree is rebuilt from
|
|
85
|
+
span_id / parent_span_id."""
|
|
86
|
+
__tablename__ = "runs"
|
|
87
|
+
id: Mapped[int] = mapped_column(primary_key=True)
|
|
88
|
+
workspace_id: Mapped[int] = _ws_fk()
|
|
89
|
+
type: Mapped[str] = mapped_column(String(16)) # agent | llm | tool | step
|
|
90
|
+
label: Mapped[str] = mapped_column(String(200), default="")
|
|
91
|
+
request: Mapped[dict] = mapped_column(JSON, default=dict) # {type, provider, model, operation, input}
|
|
92
|
+
result: Mapped[dict] = mapped_column(JSON, default=dict) # {text, output, meta}
|
|
93
|
+
status: Mapped[str] = mapped_column(String(16), default="completed")
|
|
94
|
+
duration_ms: Mapped[int] = mapped_column(Integer, default=0)
|
|
95
|
+
error: Mapped[str] = mapped_column(Text, default="")
|
|
96
|
+
# OTel span identity — lets the portal rebuild spans of one run into a nested tree.
|
|
97
|
+
trace_id: Mapped[str] = mapped_column(String(32), default="", index=True)
|
|
98
|
+
span_id: Mapped[str] = mapped_column(String(16), default="")
|
|
99
|
+
parent_span_id: Mapped[str] = mapped_column(String(16), default="")
|
|
100
|
+
created_at: Mapped[datetime] = mapped_column(DateTime, default=_now)
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"""API keys: named, revocable `pk_` bearer keys for machine access (trace ingest, CI, CLI).
|
|
2
|
+
|
|
3
|
+
The plaintext key is returned exactly once, from POST — the portal shows it, the user drops
|
|
4
|
+
it in their `.env`, and it's never retrievable again (only the SHA-256 hash is stored).
|
|
5
|
+
Listing shows the display prefix + last-used so stale keys are obvious.
|
|
6
|
+
"""
|
|
7
|
+
from fastapi import APIRouter, Depends, HTTPException
|
|
8
|
+
from pydantic import BaseModel
|
|
9
|
+
from sqlalchemy.orm import Session
|
|
10
|
+
|
|
11
|
+
from ..database import get_db
|
|
12
|
+
from ..models import ApiKey, Workspace, iso_utc
|
|
13
|
+
from ..services import apikey
|
|
14
|
+
from ..services.workspace import current_workspace
|
|
15
|
+
|
|
16
|
+
router = APIRouter(prefix="/api/api-keys", tags=["api-keys"])
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _public(k: ApiKey) -> dict:
|
|
20
|
+
return {"id": k.id, "name": k.name, "prefix": k.prefix, "revoked": k.revoked,
|
|
21
|
+
"last_used_at": iso_utc(k.last_used_at), "created_at": iso_utc(k.created_at)}
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class KeyIn(BaseModel):
|
|
25
|
+
name: str = ""
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@router.get("")
|
|
29
|
+
def list_keys(db: Session = Depends(get_db), ws: Workspace = Depends(current_workspace)):
|
|
30
|
+
keys = (db.query(ApiKey).filter(ApiKey.workspace_id == ws.id)
|
|
31
|
+
.order_by(ApiKey.created_at.desc()).all())
|
|
32
|
+
return [_public(k) for k in keys]
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@router.post("")
|
|
36
|
+
def create_key(body: KeyIn, db: Session = Depends(get_db),
|
|
37
|
+
ws: Workspace = Depends(current_workspace)):
|
|
38
|
+
"""Mint a key. The plaintext `key` in the response is shown once and never again."""
|
|
39
|
+
plaintext, key_hash, prefix = apikey.mint()
|
|
40
|
+
row = ApiKey(workspace_id=ws.id, name=(body.name or "").strip(),
|
|
41
|
+
key_hash=key_hash, prefix=prefix)
|
|
42
|
+
db.add(row)
|
|
43
|
+
db.commit()
|
|
44
|
+
db.refresh(row)
|
|
45
|
+
return {**_public(row), "key": plaintext}
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@router.delete("/{key_id}")
|
|
49
|
+
def revoke_key(key_id: int, db: Session = Depends(get_db),
|
|
50
|
+
ws: Workspace = Depends(current_workspace)):
|
|
51
|
+
"""Revoke a key (soft — the row stays so last_used history survives). 404 across workspaces."""
|
|
52
|
+
row = db.get(ApiKey, key_id)
|
|
53
|
+
if not row or row.workspace_id != ws.id:
|
|
54
|
+
raise HTTPException(404, "API key not found")
|
|
55
|
+
row.revoked = True
|
|
56
|
+
db.commit()
|
|
57
|
+
return {"ok": True}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"""OTLP/HTTP trace ingest — point any OpenTelemetry GenAI exporter at /v1/traces and
|
|
2
|
+
its LLM/agent spans show up in ProveKit's history, no SDK swap required.
|
|
3
|
+
|
|
4
|
+
Auth: a workspace ingest key via `Authorization: Bearer <key>` (what real exporters can
|
|
5
|
+
send), or a session cookie for interactive/local use. Mint the key from
|
|
6
|
+
POST /api/workspace/ingest-key."""
|
|
7
|
+
from fastapi import APIRouter, Depends, Header, HTTPException, Request
|
|
8
|
+
from pydantic import BaseModel
|
|
9
|
+
from sqlalchemy import func
|
|
10
|
+
from sqlalchemy.orm import Session
|
|
11
|
+
|
|
12
|
+
from ..database import get_db
|
|
13
|
+
from ..models import Run, Workspace, iso_utc
|
|
14
|
+
from ..services import apikey, deploy, otel
|
|
15
|
+
from ..services.workspace import current_workspace
|
|
16
|
+
|
|
17
|
+
router = APIRouter(prefix="/v1", tags=["traces"])
|
|
18
|
+
ws_router = APIRouter(prefix="/api/workspace", tags=["workspace"])
|
|
19
|
+
runs_router = APIRouter(prefix="/api", tags=["runs"])
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _resolve_ingest_ws(db: Session, request: Request, authorization: str | None) -> Workspace:
|
|
23
|
+
"""Bearer ingest key first (exporters), else fall back to the session cookie."""
|
|
24
|
+
if authorization and authorization.lower().startswith("bearer "):
|
|
25
|
+
key = authorization[7:].strip()
|
|
26
|
+
# A named pk_ key (portal-issued, revocable) first, then the legacy per-workspace
|
|
27
|
+
# ingest key. Both are SHA-256 bearer keys; either resolves the same workspace.
|
|
28
|
+
ws = apikey.resolve_workspace(db, key)
|
|
29
|
+
if ws:
|
|
30
|
+
return ws
|
|
31
|
+
ws = db.query(Workspace).filter(Workspace.ingest_key_hash == deploy.hash_key(key)).first()
|
|
32
|
+
if ws:
|
|
33
|
+
return ws
|
|
34
|
+
raise HTTPException(403, "Invalid ingest key")
|
|
35
|
+
# No bearer key: only allowed via a logged-in session (or local mode's default user).
|
|
36
|
+
from ..services.auth import get_current_user
|
|
37
|
+
from ..services.workspace import get_or_create_default_workspace
|
|
38
|
+
user = get_current_user(request, db)
|
|
39
|
+
return get_or_create_default_workspace(db, user)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@router.post("/traces")
|
|
43
|
+
async def ingest_traces(request: Request, db: Session = Depends(get_db),
|
|
44
|
+
authorization: str | None = Header(default=None)):
|
|
45
|
+
"""Accept an OTLP ExportTraceServiceRequest (JSON) and persist gen_ai spans as runs.
|
|
46
|
+
Returns the OTLP success shape so standard exporters are satisfied."""
|
|
47
|
+
ws = _resolve_ingest_ws(db, request, authorization)
|
|
48
|
+
try:
|
|
49
|
+
payload = await request.json()
|
|
50
|
+
except Exception:
|
|
51
|
+
return {"partialSuccess": {"rejectedSpans": 0, "errorMessage": "invalid JSON"}}
|
|
52
|
+
rows = otel.ingest(payload)
|
|
53
|
+
for kw in rows:
|
|
54
|
+
db.add(Run(workspace_id=ws.id, **kw))
|
|
55
|
+
if rows:
|
|
56
|
+
db.commit()
|
|
57
|
+
return {"partialSuccess": {}}
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class _KeyOut(BaseModel):
|
|
61
|
+
ingest_key: str
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@ws_router.post("/ingest-key", response_model=_KeyOut)
|
|
65
|
+
def rotate_ingest_key(db: Session = Depends(get_db), ws: Workspace = Depends(current_workspace)):
|
|
66
|
+
"""Mint/rotate this workspace's OTLP ingest key (shown once; stored hashed)."""
|
|
67
|
+
plaintext, key_hash = deploy.new_api_key()
|
|
68
|
+
ws.ingest_key_hash = key_hash
|
|
69
|
+
db.commit()
|
|
70
|
+
return {"ingest_key": plaintext}
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
# ---- captured runs (what the Traces view reads) ----
|
|
74
|
+
@runs_router.get("/runs")
|
|
75
|
+
def list_runs(limit: int = 50, db: Session = Depends(get_db),
|
|
76
|
+
ws: Workspace = Depends(current_workspace)):
|
|
77
|
+
limit = max(1, min(limit, 200))
|
|
78
|
+
rows = (db.query(Run).filter(Run.workspace_id == ws.id)
|
|
79
|
+
.order_by(Run.id.desc()).limit(limit).all())
|
|
80
|
+
return [{"id": r.id, "type": r.type, "label": r.label, "status": r.status,
|
|
81
|
+
"duration_ms": r.duration_ms, "created_at": iso_utc(r.created_at)} for r in rows]
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
@runs_router.get("/runs/{rid}")
|
|
85
|
+
def get_run(rid: int, db: Session = Depends(get_db), ws: Workspace = Depends(current_workspace)):
|
|
86
|
+
r = db.get(Run, rid)
|
|
87
|
+
if not r or r.workspace_id != ws.id:
|
|
88
|
+
raise HTTPException(404, "Run not found")
|
|
89
|
+
return {"id": r.id, "type": r.type, "label": r.label, "request": r.request,
|
|
90
|
+
"result": r.result, "status": r.status, "duration_ms": r.duration_ms,
|
|
91
|
+
"error": r.error, "created_at": iso_utc(r.created_at)}
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
# ---- traces (spans grouped into a nested tree) ----
|
|
95
|
+
@runs_router.get("/traces")
|
|
96
|
+
def list_traces(limit: int = 50, db: Session = Depends(get_db),
|
|
97
|
+
ws: Workspace = Depends(current_workspace)):
|
|
98
|
+
"""One row per trace: its root span (the decorated entrypoint), with a span count."""
|
|
99
|
+
limit = max(1, min(limit, 200))
|
|
100
|
+
roots = (db.query(Run)
|
|
101
|
+
.filter(Run.workspace_id == ws.id, Run.parent_span_id == "")
|
|
102
|
+
.order_by(Run.id.desc()).limit(limit).all())
|
|
103
|
+
counts = dict(db.query(Run.trace_id, func.count(Run.id))
|
|
104
|
+
.filter(Run.workspace_id == ws.id)
|
|
105
|
+
.group_by(Run.trace_id).all())
|
|
106
|
+
return [{"id": r.id, "trace_id": r.trace_id, "label": r.label, "type": r.type,
|
|
107
|
+
"status": r.status, "duration_ms": r.duration_ms,
|
|
108
|
+
"span_count": counts.get(r.trace_id, 1) if r.trace_id else 1,
|
|
109
|
+
"created_at": iso_utc(r.created_at)} for r in roots]
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
@runs_router.get("/traces/{trace_id}")
|
|
113
|
+
def get_trace(trace_id: str, db: Session = Depends(get_db),
|
|
114
|
+
ws: Workspace = Depends(current_workspace)):
|
|
115
|
+
"""All spans of one trace, in start order — the client rebuilds the tree from
|
|
116
|
+
span_id / parent_span_id."""
|
|
117
|
+
spans = (db.query(Run)
|
|
118
|
+
.filter(Run.workspace_id == ws.id, Run.trace_id == trace_id)
|
|
119
|
+
.order_by(Run.id.asc()).all())
|
|
120
|
+
if not spans:
|
|
121
|
+
raise HTTPException(404, "Trace not found")
|
|
122
|
+
return [{"id": s.id, "span_id": s.span_id, "parent_span_id": s.parent_span_id,
|
|
123
|
+
"type": s.type, "label": s.label, "status": s.status, "duration_ms": s.duration_ms,
|
|
124
|
+
"request": s.request, "result": s.result, "error": s.error,
|
|
125
|
+
"created_at": iso_utc(s.created_at)} for s in spans]
|