failproofai 1.0.1 → 1.0.2-beta.0
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.
- package/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/build-manifest.json +3 -3
- package/.next/standalone/.next/prerender-manifest.json +6 -6
- package/.next/standalone/.next/required-server-files.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page.js +2 -2
- package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_global-error.html +1 -1
- package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +6 -6
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page.js +2 -2
- package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +1 -1
- package/.next/standalone/.next/server/app/_not-found.rsc +15 -15
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +15 -15
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +14 -14
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/api/audit/invite/route.js +3 -2
- package/.next/standalone/.next/server/app/api/audit/invite/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/audit/run/route.js +5 -4
- package/.next/standalone/.next/server/app/api/audit/run/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/audit/status/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/login-request/route.js +2 -2
- package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/login-verify/route.js +4 -3
- package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/logout/route.js +4 -4
- package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/status/route.js +4 -4
- package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
- package/.next/standalone/.next/server/app/audit/page.js +2 -2
- package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/index.html +1 -1
- package/.next/standalone/.next/server/app/index.rsc +15 -15
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +14 -14
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +15 -15
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/page.js +2 -2
- package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +66 -22
- package/.next/standalone/.next/server/app/policies/page.js +5 -4
- package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page.js +2 -2
- package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/projects/page.js +2 -2
- package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +4 -4
- package/.next/standalone/.next/server/app/settings/page.js +1 -1
- package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/chunks/{[externals]__1qzqcio._.js → [externals]__0e32-7c._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[externals]__1s462yl._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__01eqny5._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0_0xu5z._.js +1 -1
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__1p8poxd._.js → [root-of-the-server]__0igxt32._.js} +2 -2
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0neqlu-._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0o07qi9._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0t9oqnn._.js +3 -0
- package/.next/standalone/.next/server/chunks/_0bs-v8p._.js +3 -0
- package/.next/standalone/.next/server/chunks/_0tovk6q._.js +3 -0
- package/.next/standalone/.next/server/chunks/_0trp3yc._.js +3 -0
- package/.next/standalone/.next/server/chunks/_185gyk9._.js +3 -0
- package/.next/standalone/.next/server/chunks/_1ek68ln._.js +5 -6
- package/.next/standalone/.next/server/chunks/lib_telemetry-id_ts_1k8gj9o._.js +3 -0
- package/.next/standalone/.next/server/chunks/{node_modules_posthog-node_dist_entrypoints_index_node_mjs_09d5c79._.js → node_modules_posthog-node_dist_entrypoints_index_node_mjs_04op_ou._.js} +1 -1
- package/.next/standalone/.next/server/chunks/{node_modules_posthog-node_dist_entrypoints_index_node_mjs_1d2g73o._.js → node_modules_posthog-node_dist_entrypoints_index_node_mjs_0dr20uz._.js} +1 -1
- package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
- package/.next/standalone/.next/server/chunks/src_hooks_0xbw3bu._.js +12 -0
- package/.next/standalone/.next/server/chunks/src_hooks_fp-home_ts_09kv0bn._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__013jr2b._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__01wy8d-._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__02npjtd._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0spkm68._.js → [root-of-the-server]__07gm3zl._.js} +21 -20
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0da85px._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ftmoxc._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0oa1lav._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0p-5p8u._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0s740oi._.js +6 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__07tbbf3._.js → [root-of-the-server]__0zig5sv._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__192nhvh._.js +5 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1p2otjt._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/{_0lvyuv4._.js → _00e9tnf._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/_08x1r5t._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{_0u5zauv._.js → _12l4a_k._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_1u8-lu2._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_1zopuov._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +13 -13
- package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpc._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/app_settings_settings-client_tsx_20lq-mq._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_08o7bqo._.js +10 -0
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_builtin-policies_ts_09j2ndl._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_fp-home_ts_0je3xkv._.js +1 -1
- package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
- package/.next/standalone/.next/server/middleware.js +1 -1
- package/.next/standalone/.next/server/pages/404.html +1 -1
- package/.next/standalone/.next/server/pages/500.html +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.json +71 -27
- package/.next/standalone/.next/static/chunks/{37fcpc36x9gpe.js → 0eqky-7n7dgdm.js} +1 -1
- package/.next/standalone/.next/static/chunks/{1ide1wl2f7zi1.js → 0sa9v5mhc8861.js} +13 -13
- package/.next/standalone/.next/static/chunks/1mfzsja6ftim5.css +2 -0
- package/.next/standalone/.next/static/chunks/{3k7mxbp9hiom0.js → 1nuqytbta44af.js} +1 -1
- package/.next/standalone/.next/static/chunks/1sl2xmn9inx3y.js +6 -0
- package/.next/standalone/.next/static/chunks/{2_2lhuojq2xop.js → 2aawsjld9ied_.js} +1 -1
- package/.next/standalone/.next/static/chunks/2gn7ut4svofm2.js +1 -0
- package/.next/standalone/.next/static/chunks/{31s1smp-g7gks.js → 2hs7ycvsav7v2.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0k5050ezjvv49.js → 2i2yt3hzjredm.js} +1 -1
- package/.next/standalone/.next/static/chunks/{3c808qrfcq0im.js → 35xg6retpe6rp.js} +1 -1
- package/.next/standalone/.next/static/chunks/{2zpp1we2jv6tb.js → 3y54nw0i7dsjl.js} +1 -1
- package/.next/standalone/SECURITY.md +5 -4
- package/.next/standalone/app/actions/get-hooks-config.ts +108 -17
- package/.next/standalone/app/actions/pack-actions.ts +153 -0
- package/.next/standalone/app/audit/_components/run-progress.tsx +1 -1
- package/.next/standalone/app/audit/_components/share-templates.ts +13 -13
- package/.next/standalone/app/policies/hooks-client.tsx +320 -14
- package/.next/standalone/components/navbar.tsx +2 -28
- package/.next/standalone/components/reach-developers.tsx +8 -1
- package/.next/standalone/docs-old/agenteye/python-sdk-skill.mdx +1 -1
- package/.next/standalone/docs-old/agenteye/python-sdk.mdx +59 -35
- package/.next/standalone/docs-old/i18n/README.ar.md +1 -0
- package/.next/standalone/docs-old/i18n/README.de.md +1 -0
- package/.next/standalone/docs-old/i18n/README.es.md +1 -0
- package/.next/standalone/docs-old/i18n/README.fr.md +1 -0
- package/.next/standalone/docs-old/i18n/README.he.md +1 -0
- package/.next/standalone/docs-old/i18n/README.hi.md +1 -0
- package/.next/standalone/docs-old/i18n/README.it.md +1 -0
- package/.next/standalone/docs-old/i18n/README.ja.md +1 -0
- package/.next/standalone/docs-old/i18n/README.ko.md +1 -0
- package/.next/standalone/docs-old/i18n/README.pt-br.md +1 -0
- package/.next/standalone/docs-old/i18n/README.ru.md +1 -0
- package/.next/standalone/docs-old/i18n/README.tr.md +1 -0
- package/.next/standalone/docs-old/i18n/README.vi.md +1 -0
- package/.next/standalone/docs-old/i18n/README.zh.md +1 -0
- package/.next/standalone/fp-cloud-cli/CHANGELOG.md +431 -0
- package/.next/standalone/fp-cloud-cli/LICENSE +42 -0
- package/.next/standalone/fp-cloud-cli/MANIFEST.in +10 -0
- package/.next/standalone/fp-cloud-cli/README.md +259 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/__init__.py +10 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/__main__.py +4 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/_click_compat.py +64 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/_context.py +332 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/_version.py +1 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/analytics.py +432 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/analytics_config.py +77 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/analytics_registry.py +83 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/app.py +492 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/auth.py +160 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/client.py +1694 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/__init__.py +0 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/_write.py +214 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/agent_cmds.py +407 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/alerts_cmds.py +445 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/audits_cmds.py +1054 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/auth_cmds.py +512 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/errors_cmds.py +190 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/evals_cmds.py +161 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/events_cmds.py +159 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/fleet_cmds.py +416 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/guardrails_cmds.py +148 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/incidents_cmds.py +472 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/keys_cmds.py +407 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/list_cmds.py +63 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/orgs_cmds.py +319 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/policies_cmds.py +499 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/queries_cmds.py +378 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/sessions_cmds.py +151 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/settings_cmds.py +150 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/usage_cmds.py +35 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/users_cmds.py +404 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/config.py +330 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/dates.py +78 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/enforcement.py +345 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/errors.py +98 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/models.py +891 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/orgs.py +30 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/output.py +6593 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/permissions.py +208 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/policy_check.py +290 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/py.typed +0 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/select.py +322 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/theme.py +53 -0
- package/.next/standalone/fp-cloud-cli/pyproject.toml +106 -0
- package/.next/standalone/fp-cloud-cli/skill/SKILL.md +302 -0
- package/.next/standalone/fp-cloud-cli/skill/agents/openai.yaml +8 -0
- package/.next/standalone/fp-cloud-cli/skill/references/commands.md +254 -0
- package/.next/standalone/fp-cloud-cli/tests/__init__.py +0 -0
- package/.next/standalone/fp-cloud-cli/tests/conftest.py +92 -0
- package/.next/standalone/fp-cloud-cli/tests/test_alerting.py +644 -0
- package/.next/standalone/fp-cloud-cli/tests/test_analytics.py +385 -0
- package/.next/standalone/fp-cloud-cli/tests/test_audits.py +950 -0
- package/.next/standalone/fp-cloud-cli/tests/test_auth.py +98 -0
- package/.next/standalone/fp-cloud-cli/tests/test_auth_mode.py +272 -0
- package/.next/standalone/fp-cloud-cli/tests/test_click_compat.py +118 -0
- package/.next/standalone/fp-cloud-cli/tests/test_client.py +299 -0
- package/.next/standalone/fp-cloud-cli/tests/test_commands.py +814 -0
- package/.next/standalone/fp-cloud-cli/tests/test_config.py +99 -0
- package/.next/standalone/fp-cloud-cli/tests/test_dashboards_agent.py +340 -0
- package/.next/standalone/fp-cloud-cli/tests/test_dates.py +76 -0
- package/.next/standalone/fp-cloud-cli/tests/test_enforcement_logic.py +481 -0
- package/.next/standalone/fp-cloud-cli/tests/test_facets.py +170 -0
- package/.next/standalone/fp-cloud-cli/tests/test_failproofai_home.py +722 -0
- package/.next/standalone/fp-cloud-cli/tests/test_fp_home_contract.py +198 -0
- package/.next/standalone/fp-cloud-cli/tests/test_hardening.py +186 -0
- package/.next/standalone/fp-cloud-cli/tests/test_help_table_coverage.py +127 -0
- package/.next/standalone/fp-cloud-cli/tests/test_keys_queries.py +496 -0
- package/.next/standalone/fp-cloud-cli/tests/test_list.py +59 -0
- package/.next/standalone/fp-cloud-cli/tests/test_multivalue.py +183 -0
- package/.next/standalone/fp-cloud-cli/tests/test_no_customer_identifiers.py +168 -0
- package/.next/standalone/fp-cloud-cli/tests/test_operator.py +492 -0
- package/.next/standalone/fp-cloud-cli/tests/test_orgs.py +692 -0
- package/.next/standalone/fp-cloud-cli/tests/test_output.py +1732 -0
- package/.next/standalone/fp-cloud-cli/tests/test_policy_check.py +191 -0
- package/.next/standalone/fp-cloud-cli/tests/test_readme_matches_reality.py +125 -0
- package/.next/standalone/fp-cloud-cli/tests/test_review_fixes.py +161 -0
- package/.next/standalone/fp-cloud-cli/tests/test_telemetry_completeness.py +90 -0
- package/.next/standalone/fp-cloud-cli/tests/test_usage.py +115 -0
- package/.next/standalone/fp-cloud-cli/tests/test_v1_origin_diagnostic.py +70 -0
- package/.next/standalone/fp-cloud-cli/tests/test_v1_routing.py +214 -0
- package/.next/standalone/fp-cloud-cli/tests/test_whoami.py +104 -0
- package/.next/standalone/fp-cloud-cli/uv.lock +552 -0
- package/.next/standalone/package.json +29 -22
- package/.next/standalone/sdk/python/CHANGELOG.md +70 -0
- package/.next/standalone/sdk/python/LICENSE +42 -0
- package/.next/standalone/sdk/python/MANIFEST.in +21 -0
- package/.next/standalone/sdk/python/README.md +466 -0
- package/.next/standalone/sdk/python/docs/README.md +249 -0
- package/.next/standalone/sdk/python/docs/_shared/README.md +43 -0
- package/.next/standalone/sdk/python/docs/_shared/__init__.py +195 -0
- package/.next/standalone/sdk/python/docs/crewai/README.md +328 -0
- package/.next/standalone/sdk/python/docs/crewai/examples/quickstart.py +61 -0
- package/.next/standalone/sdk/python/docs/crewai/examples/research_crew.py +92 -0
- package/.next/standalone/sdk/python/docs/langgraph/README.md +481 -0
- package/.next/standalone/sdk/python/docs/langgraph/examples/quickstart.py +51 -0
- package/.next/standalone/sdk/python/docs/langgraph/examples/research_agent.py +86 -0
- package/.next/standalone/sdk/python/docs/langgraph/examples/supervisor_handoff.py +83 -0
- package/.next/standalone/sdk/python/docs/llama_index/README.md +332 -0
- package/.next/standalone/sdk/python/docs/llama_index/examples/quickstart.py +62 -0
- package/.next/standalone/sdk/python/docs/llama_index/examples/research_agent.py +93 -0
- package/.next/standalone/sdk/python/docs/manual/README.md +491 -0
- package/.next/standalone/sdk/python/docs/manual/examples/quickstart.py +57 -0
- package/.next/standalone/sdk/python/docs/manual/examples/research_agent.py +133 -0
- package/.next/standalone/sdk/python/docs/pydantic_ai/README.md +323 -0
- package/.next/standalone/sdk/python/docs/pydantic_ai/examples/quickstart.py +48 -0
- package/.next/standalone/sdk/python/docs/pydantic_ai/examples/research_agent.py +94 -0
- package/.next/standalone/sdk/python/failproofai_sdk/__init__.py +131 -0
- package/.next/standalone/sdk/python/failproofai_sdk/_context.py +218 -0
- package/.next/standalone/sdk/python/failproofai_sdk/_environment.py +78 -0
- package/.next/standalone/sdk/python/failproofai_sdk/_events.py +752 -0
- package/.next/standalone/sdk/python/failproofai_sdk/_resolver.py +118 -0
- package/.next/standalone/sdk/python/failproofai_sdk/_runtime.py +21 -0
- package/.next/standalone/sdk/python/failproofai_sdk/_schema.py +317 -0
- package/.next/standalone/sdk/python/failproofai_sdk/_scopes.py +422 -0
- package/.next/standalone/sdk/python/failproofai_sdk/_version.py +1 -0
- package/.next/standalone/sdk/python/failproofai_sdk/_writer.py +750 -0
- package/.next/standalone/sdk/python/failproofai_sdk/integrations/__init__.py +274 -0
- package/.next/standalone/sdk/python/failproofai_sdk/integrations/_compat.py +247 -0
- package/.next/standalone/sdk/python/failproofai_sdk/integrations/_core.py +1076 -0
- package/.next/standalone/sdk/python/failproofai_sdk/integrations/crewai.py +1669 -0
- package/.next/standalone/sdk/python/failproofai_sdk/integrations/langchain.py +2151 -0
- package/.next/standalone/sdk/python/failproofai_sdk/integrations/llama_index.py +1588 -0
- package/.next/standalone/sdk/python/failproofai_sdk/integrations/pydantic_ai.py +977 -0
- package/.next/standalone/sdk/python/failproofai_sdk/py.typed +0 -0
- package/.next/standalone/sdk/python/pyproject.toml +92 -0
- package/.next/standalone/sdk/python/skill/SKILL.md +399 -0
- package/.next/standalone/sdk/python/skill/agents/openai.yaml +8 -0
- package/.next/standalone/sdk/python/skill/references/events.md +234 -0
- package/.next/standalone/sdk/python/skill/references/frameworks.md +314 -0
- package/.next/standalone/sdk/python/skill/references/install.md +100 -0
- package/.next/standalone/sdk/python/skill/references/integration.md +352 -0
- package/.next/standalone/sdk/python/tests/__init__.py +0 -0
- package/.next/standalone/sdk/python/tests/conftest.py +169 -0
- package/.next/standalone/sdk/python/tests/integrations/__init__.py +6 -0
- package/.next/standalone/sdk/python/tests/integrations/test_crewai.py +1299 -0
- package/.next/standalone/sdk/python/tests/integrations/test_langchain.py +2338 -0
- package/.next/standalone/sdk/python/tests/integrations/test_llama_index.py +1576 -0
- package/.next/standalone/sdk/python/tests/integrations/test_pydantic_ai.py +1102 -0
- package/.next/standalone/sdk/python/tests/test_context.py +410 -0
- package/.next/standalone/sdk/python/tests/test_docs.py +411 -0
- package/.next/standalone/sdk/python/tests/test_durability.py +1352 -0
- package/.next/standalone/sdk/python/tests/test_encoding.py +571 -0
- package/.next/standalone/sdk/python/tests/test_integrations.py +1127 -0
- package/.next/standalone/sdk/python/tests/test_no_customer_identifiers.py +214 -0
- package/.next/standalone/sdk/python/tests/test_packaging.py +185 -0
- package/.next/standalone/sdk/python/tests/test_resolver_umbrella.py +178 -0
- package/.next/standalone/sdk/python/tests/test_scopes.py +487 -0
- package/.next/standalone/sdk/python/tests/test_sdk.py +923 -0
- package/.next/standalone/sdk/python/tests/test_server_contract.py +650 -0
- package/.next/standalone/sdk/python/tests/test_site_docs.py +371 -0
- package/.next/standalone/sdk/python/tests/test_skill_snippets.py +165 -0
- package/.next/standalone/sdk/python/tests/test_spool_contract.py +287 -0
- package/.next/standalone/sdk/python/tests/test_spool_creation.py +360 -0
- package/.next/standalone/sdk/python/tests/test_wire_format.py +279 -0
- package/.next/standalone/sdk/python/tests/test_zero_dependencies.py +378 -0
- package/.next/standalone/sdk/python/uv.lock +6005 -0
- package/.next/standalone/server.js +1 -1
- package/README.md +77 -21
- package/bin/failproofai.mjs +145 -11
- package/dist/cli.mjs +4482 -2205
- package/dist/index.js +5 -5
- package/dist/worker.mjs +2399 -1978
- package/package.json +29 -22
- package/policy-pack/SHA256SUMS +2 -0
- package/policy-pack/failproofai-pack.json +732 -0
- package/policy-pack/failproofai-pack.mjs +2017 -0
- package/scripts/build-policy-pack.mjs +121 -0
- package/scripts/changelog-section.py +77 -0
- package/scripts/prune-standalone.mjs +3 -0
- package/scripts/python-version.py +232 -0
- package/scripts/translate-docs/cli.ts +21 -0
- package/scripts/translate-docs/mintlify-nav.ts +85 -13
- package/scripts/translate-docs/translator.ts +66 -11
- package/src/audit/cache.ts +40 -3
- package/src/audit/cli.ts +1 -1
- package/src/audit/index.ts +1 -1
- package/src/audit/replay.ts +89 -3
- package/src/audit/report.ts +5 -5
- package/src/audit/schedule-cli.ts +49 -53
- package/src/hooks/builtin-policies.ts +217 -579
- package/src/hooks/cloud-enrollment-cli.ts +66 -27
- package/src/hooks/cloud-managed-policies.ts +6 -1
- package/src/hooks/configure-wizard.ts +1 -1
- package/src/hooks/custom-hooks-loader.ts +89 -6
- package/src/hooks/fp-home.ts +92 -4
- package/src/hooks/fp-reset.ts +26 -2
- package/src/hooks/handler.ts +181 -11
- package/src/hooks/harness-cli.ts +79 -25
- package/src/hooks/hook-activity-store.ts +13 -3
- package/src/hooks/install-prompt.ts +25 -3
- package/src/hooks/manager.ts +418 -172
- package/src/hooks/migrations.ts +2 -2
- package/src/hooks/pack-cli.ts +505 -0
- package/src/hooks/pack-failclosed.ts +189 -0
- package/src/hooks/pack-manifest.ts +344 -0
- package/src/hooks/pack-store.ts +930 -0
- package/src/hooks/policy-catalog.ts +535 -0
- package/src/hooks/policy-evaluator.ts +24 -16
- package/src/hooks/policy-presets.ts +4 -2
- package/src/hooks/policy-registry.ts +8 -2
- package/src/hooks/policy-types.ts +26 -0
- package/src/hooks/session-pause-cli.ts +33 -9
- package/src/hooks/tui.ts +570 -0
- package/src/hooks/types.ts +15 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0_usx0j._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0_zk340._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0agdw2a._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0d1u_na._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0oy4kxb._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0zf034w._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1tvn4wf._.js +0 -3
- package/.next/standalone/.next/server/chunks/_0lxbzdq._.js +0 -3
- package/.next/standalone/.next/server/chunks/_1ger0a2._.js +0 -3
- package/.next/standalone/.next/server/chunks/_1zuiiy3._.js +0 -3
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_1iiwm5e._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0kc8_v5._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0kgy9da._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0mhqk5a._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0pltpn8._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0qkcyf-._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0w0x_ok._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1_dfocn._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1bfex62._.js +0 -5
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1kzapg5._.js +0 -6
- package/.next/standalone/.next/static/chunks/36fw6yk1s6x_f.js +0 -1
- package/.next/standalone/.next/static/chunks/3tzq0260n17ae.js +0 -6
- package/.next/standalone/.next/static/chunks/3wq9x0c-7ld5d.css +0 -2
- /package/.next/standalone/.next/static/{ZklXxyA5ygsWSQz2u_zii → nwbyWT06Ud0XdXOrVJyvS}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{ZklXxyA5ygsWSQz2u_zii → nwbyWT06Ud0XdXOrVJyvS}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{ZklXxyA5ygsWSQz2u_zii → nwbyWT06Ud0XdXOrVJyvS}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
"""Interactive selection helpers (TTY pickers), shared across commands.
|
|
2
|
+
|
|
3
|
+
Kept in one place so the org picker used at ``login`` and at ``orgs switch`` reads
|
|
4
|
+
and behaves identically. Pure presentation + input; no network, no persistence.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import os
|
|
10
|
+
import sys
|
|
11
|
+
from typing import List, Optional, Sequence
|
|
12
|
+
|
|
13
|
+
from . import output
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def stdin_is_tty() -> bool: # noqa: D401
|
|
17
|
+
"""True iff stdin is an interactive terminal (so we may prompt for a choice).
|
|
18
|
+
|
|
19
|
+
Factored out so it can be stubbed in tests — the CliRunner's stdin is not a
|
|
20
|
+
TTY, so the interactive pickers are otherwise unreachable under test.
|
|
21
|
+
"""
|
|
22
|
+
try:
|
|
23
|
+
return sys.stdin.isatty()
|
|
24
|
+
except Exception:
|
|
25
|
+
return False
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def choose_org(slugs: Sequence[str], default: Optional[str] = None) -> str:
|
|
29
|
+
"""Render ``slugs`` and prompt until the user picks one (by slug or number).
|
|
30
|
+
|
|
31
|
+
``default`` (only if it is one of ``slugs``) is the Enter-to-keep choice and is
|
|
32
|
+
marked ``· current`` in the list. Re-prompts on any out-of-range / unknown input,
|
|
33
|
+
so the return value is always one of ``slugs`` — a non-member slug can never be
|
|
34
|
+
selected through the picker.
|
|
35
|
+
"""
|
|
36
|
+
slugs = list(slugs)
|
|
37
|
+
output.org_picker(slugs, current=default)
|
|
38
|
+
prompt_default = default if (default in slugs) else None
|
|
39
|
+
while True:
|
|
40
|
+
choice = str(output.prompt("org", default=prompt_default)).strip()
|
|
41
|
+
if choice in slugs:
|
|
42
|
+
return choice
|
|
43
|
+
if choice.isdigit() and 1 <= int(choice) <= len(slugs):
|
|
44
|
+
return slugs[int(choice) - 1]
|
|
45
|
+
output.warn(f" '{choice}' is not one of your orgs — try again.")
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
# ── orgs switch — arrow-key picker (raw mode) + numbered fallback ─────────────
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _supports_raw_picker() -> bool:
|
|
52
|
+
"""True iff we can run the raw-mode arrow picker: a real interactive TTY on both stdin
|
|
53
|
+
(we read keys) and stderr (we draw the menu), and POSIX ``termios`` is importable.
|
|
54
|
+
Anything else — pipes, CI, the test runner, Windows — falls back to the numbered prompt
|
|
55
|
+
(so the picker never hangs or crashes off a TTY, per the handoff spec §3/§7)."""
|
|
56
|
+
try:
|
|
57
|
+
import termios # noqa: F401
|
|
58
|
+
except Exception:
|
|
59
|
+
return False
|
|
60
|
+
try:
|
|
61
|
+
return bool(sys.stdin.isatty() and sys.stderr.isatty())
|
|
62
|
+
except Exception:
|
|
63
|
+
return False
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def _read_key(fd: int) -> str:
|
|
67
|
+
"""Read one logical keypress from a raw-mode ``fd`` → a token: ``UP``/``DOWN``/``ENTER``/
|
|
68
|
+
``ESC``/``EOF`` or the raw character. Distinguishes a lone Esc from an arrow escape
|
|
69
|
+
sequence (``\\x1b[A``) with a tiny ``select`` timeout so Esc never blocks."""
|
|
70
|
+
import select as _sel
|
|
71
|
+
|
|
72
|
+
ch = os.read(fd, 1)
|
|
73
|
+
if not ch:
|
|
74
|
+
return "EOF"
|
|
75
|
+
if ch == b"\x1b": # Esc, or the start of an arrow escape sequence
|
|
76
|
+
r, _, _ = _sel.select([fd], [], [], 0.0008)
|
|
77
|
+
if not r:
|
|
78
|
+
return "ESC"
|
|
79
|
+
seq = os.read(fd, 2)
|
|
80
|
+
return {b"[A": "UP", b"[B": "DOWN", b"[C": "RIGHT", b"[D": "LEFT"}.get(seq, "ESC")
|
|
81
|
+
if ch in (b"\r", b"\n"):
|
|
82
|
+
return "ENTER"
|
|
83
|
+
if ch == b"\x03": # Ctrl-C (also raised as KeyboardInterrupt under cbreak)
|
|
84
|
+
return "CTRL_C"
|
|
85
|
+
return ch.decode("utf-8", "ignore")
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def _numbered_pick(orgs: Sequence[dict], *, current: Optional[str]) -> str:
|
|
89
|
+
"""Non-TTY fallback: a boxed numbered list + a typed choice (slug or number). Re-prompts on
|
|
90
|
+
bad input, so the return is always one of the orgs' slugs. Default is the current org. With
|
|
91
|
+
no input at all (closed/empty stdin, e.g. CI) the prompt aborts → a clean usage error so the
|
|
92
|
+
run never hangs."""
|
|
93
|
+
import typer
|
|
94
|
+
|
|
95
|
+
from . import _click_compat as click # the Click Typer is running
|
|
96
|
+
|
|
97
|
+
slugs: List[str] = [o["slug"] for o in orgs]
|
|
98
|
+
output.render_org_picker_numbered(orgs, current=current)
|
|
99
|
+
default = current if current in slugs else None
|
|
100
|
+
while True:
|
|
101
|
+
try:
|
|
102
|
+
choice = str(output.prompt("org", default=default)).strip()
|
|
103
|
+
except (click.Abort, EOFError):
|
|
104
|
+
raise typer.BadParameter(
|
|
105
|
+
"No org selected and no interactive terminal. "
|
|
106
|
+
"Pass a slug, e.g. `fp orgs switch <slug>`."
|
|
107
|
+
)
|
|
108
|
+
if choice in slugs:
|
|
109
|
+
return choice
|
|
110
|
+
if choice.isdigit() and 1 <= int(choice) <= len(slugs):
|
|
111
|
+
return slugs[int(choice) - 1]
|
|
112
|
+
output.warn(f" '{choice}' is not one of your orgs — try again.")
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def choose_org_interactive(orgs: Sequence[dict], *, current_slug: Optional[str] = None) -> Optional[str]:
|
|
116
|
+
"""Pick an org to switch to. ``orgs`` is a list of ``{"slug", "is_current"}`` dicts. Returns
|
|
117
|
+
the chosen slug, or ``None`` if the user cancelled (Esc / Ctrl-C). On a real TTY this is an
|
|
118
|
+
in-place arrow-key menu (cursor starts on the current org); otherwise it falls back to a
|
|
119
|
+
numbered prompt (which can't cancel — it always returns a slug)."""
|
|
120
|
+
orgs = list(orgs)
|
|
121
|
+
if not _supports_raw_picker():
|
|
122
|
+
return _numbered_pick(orgs, current=current_slug)
|
|
123
|
+
|
|
124
|
+
import termios
|
|
125
|
+
import tty
|
|
126
|
+
|
|
127
|
+
from rich.live import Live
|
|
128
|
+
|
|
129
|
+
idx = next((i for i, o in enumerate(orgs) if o.get("is_current")), 0)
|
|
130
|
+
fd = sys.stdin.fileno()
|
|
131
|
+
old = termios.tcgetattr(fd)
|
|
132
|
+
try:
|
|
133
|
+
tty.setcbreak(fd)
|
|
134
|
+
with Live(output.org_picker_frame(orgs, idx), console=output._stderr,
|
|
135
|
+
auto_refresh=False, transient=True) as live:
|
|
136
|
+
while True:
|
|
137
|
+
key = _read_key(fd)
|
|
138
|
+
if key in ("UP", "k"):
|
|
139
|
+
idx = (idx - 1) % len(orgs)
|
|
140
|
+
elif key in ("DOWN", "j"):
|
|
141
|
+
idx = (idx + 1) % len(orgs)
|
|
142
|
+
elif key == "ENTER":
|
|
143
|
+
return orgs[idx]["slug"]
|
|
144
|
+
elif key in ("ESC", "CTRL_C", "q", "EOF"):
|
|
145
|
+
return None
|
|
146
|
+
else:
|
|
147
|
+
continue
|
|
148
|
+
live.update(output.org_picker_frame(orgs, idx))
|
|
149
|
+
live.refresh()
|
|
150
|
+
except KeyboardInterrupt:
|
|
151
|
+
return None
|
|
152
|
+
finally:
|
|
153
|
+
termios.tcsetattr(fd, termios.TCSADRAIN, old)
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
# ── login — the single-box interactive flow (one Live panel, raw-mode in-box input) ──
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
class LoginCancelled(Exception):
|
|
160
|
+
"""The user pressed Esc / Ctrl-C during the login flow (calm cancel, not an error)."""
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def login_box_supported() -> bool:
|
|
164
|
+
"""True iff the single-box interactive login can run (real TTY on stdin+stderr + termios) —
|
|
165
|
+
otherwise ``login`` uses the plain prompt flow (tests, pipes, CI, ``--json``)."""
|
|
166
|
+
return _supports_raw_picker()
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
class LoginBox:
|
|
170
|
+
"""Drives the single-box ``login``: ONE Rich ``Live`` panel redrawn in place as steps advance.
|
|
171
|
+
email/code are read in **raw mode** (echo off) and rendered INSIDE the frame; the org step is the
|
|
172
|
+
shared arrow picker as a nested inset. Restores the terminal on exit. Used only on a real TTY —
|
|
173
|
+
the non-interactive path keeps the plain prompts."""
|
|
174
|
+
|
|
175
|
+
def __init__(self) -> None:
|
|
176
|
+
self.done: List = [] # collapsed ✓ steps: (label, value)
|
|
177
|
+
self.active: Optional[str] = None
|
|
178
|
+
self._fd = sys.stdin.fileno()
|
|
179
|
+
self._old = None
|
|
180
|
+
self._live = None
|
|
181
|
+
|
|
182
|
+
def __enter__(self) -> "LoginBox":
|
|
183
|
+
import termios
|
|
184
|
+
import tty
|
|
185
|
+
|
|
186
|
+
from rich.live import Live
|
|
187
|
+
|
|
188
|
+
self._old = termios.tcgetattr(self._fd)
|
|
189
|
+
tty.setcbreak(self._fd) # canonical + echo off, signals on (Ctrl-C → KeyboardInterrupt)
|
|
190
|
+
self._live = Live(output.render_login_frame(self.done, None), console=output._stderr,
|
|
191
|
+
auto_refresh=False, transient=False)
|
|
192
|
+
self._live.__enter__()
|
|
193
|
+
return self
|
|
194
|
+
|
|
195
|
+
def __exit__(self, *exc) -> None:
|
|
196
|
+
import termios
|
|
197
|
+
|
|
198
|
+
try:
|
|
199
|
+
if self._live is not None:
|
|
200
|
+
self._live.__exit__(*exc)
|
|
201
|
+
finally:
|
|
202
|
+
termios.tcsetattr(self._fd, termios.TCSADRAIN, self._old)
|
|
203
|
+
|
|
204
|
+
def _draw(self, **kw) -> None:
|
|
205
|
+
self._live.update(output.render_login_frame(self.done, self.active, **kw))
|
|
206
|
+
self._live.refresh()
|
|
207
|
+
|
|
208
|
+
def _read_line(self, *, helper, slots, error) -> str:
|
|
209
|
+
"""Read one line in raw mode, redrawing the frame on every keystroke so the typed text
|
|
210
|
+
appears INSIDE the box (echo is off). Backspace edits; Enter accepts; Esc / Ctrl-C / EOF
|
|
211
|
+
cancel (an arrow escape-sequence mid-type is swallowed, not a cancel). A ``slots`` field
|
|
212
|
+
accepts digits only, capped at ``slots``."""
|
|
213
|
+
import select as _sel
|
|
214
|
+
|
|
215
|
+
buf = ""
|
|
216
|
+
self._draw(active_value=buf, active_slots=slots, helper=helper, error=error)
|
|
217
|
+
while True:
|
|
218
|
+
try:
|
|
219
|
+
ch = os.read(self._fd, 1)
|
|
220
|
+
except KeyboardInterrupt:
|
|
221
|
+
raise LoginCancelled()
|
|
222
|
+
if not ch:
|
|
223
|
+
raise LoginCancelled()
|
|
224
|
+
if ch in (b"\r", b"\n"):
|
|
225
|
+
return buf
|
|
226
|
+
if ch == b"\x03": # Ctrl-C as a byte (if signals were off)
|
|
227
|
+
raise LoginCancelled()
|
|
228
|
+
if ch == b"\x1b": # Esc, or the start of an arrow escape sequence
|
|
229
|
+
r, _, _ = _sel.select([self._fd], [], [], 0.0008)
|
|
230
|
+
if r:
|
|
231
|
+
os.read(self._fd, 2) # swallow the arrow/sequence — don't cancel mid-type
|
|
232
|
+
continue
|
|
233
|
+
raise LoginCancelled()
|
|
234
|
+
if ch in (b"\x7f", b"\x08"): # backspace / delete
|
|
235
|
+
buf = buf[:-1]
|
|
236
|
+
self._draw(active_value=buf, active_slots=slots, helper=helper, error=None)
|
|
237
|
+
continue
|
|
238
|
+
try:
|
|
239
|
+
c = ch.decode("utf-8")
|
|
240
|
+
except UnicodeDecodeError:
|
|
241
|
+
continue
|
|
242
|
+
if not c.isprintable():
|
|
243
|
+
continue
|
|
244
|
+
if slots and (not c.isdigit() or len(buf) >= slots):
|
|
245
|
+
continue # the code field is digits-only, capped
|
|
246
|
+
buf += c
|
|
247
|
+
self._draw(active_value=buf, active_slots=slots, helper=helper, error=None)
|
|
248
|
+
|
|
249
|
+
def text_step(self, label: str, *, helper=None, slots=None, validate=None,
|
|
250
|
+
error_msg=None, hidden_value: bool = False, collapse: bool = True,
|
|
251
|
+
initial_error=None) -> str:
|
|
252
|
+
"""Run one bright ``❯ {label}`` input step; on a failed ``validate`` show the error sub-line
|
|
253
|
+
and re-prompt. On accept it collapses to a dim ``✓ {label} {value}`` line (the value is
|
|
254
|
+
omitted when ``hidden_value``). With ``collapse=False`` it returns the value WITHOUT adding
|
|
255
|
+
the ✓ line (the caller verifies it over the network first, then calls ``note``); ``initial_error``
|
|
256
|
+
seeds the error sub-line on the first draw (a re-prompt after a wrong code)."""
|
|
257
|
+
self.active = label
|
|
258
|
+
error = initial_error
|
|
259
|
+
while True:
|
|
260
|
+
buf = self._read_line(helper=helper, slots=slots, error=error).strip()
|
|
261
|
+
if validate is None or validate(buf):
|
|
262
|
+
self.active = None
|
|
263
|
+
if collapse:
|
|
264
|
+
self.done.append((label, "" if hidden_value else buf))
|
|
265
|
+
self._draw()
|
|
266
|
+
return buf
|
|
267
|
+
error = error_msg or "that doesn't look right"
|
|
268
|
+
|
|
269
|
+
def note(self, label: str, value=None) -> None:
|
|
270
|
+
"""Add a completed ✓ line that wasn't an input step (e.g. ``✓ code sent``)."""
|
|
271
|
+
self.done.append((label, value))
|
|
272
|
+
self._draw()
|
|
273
|
+
|
|
274
|
+
def working(self, text: str) -> None:
|
|
275
|
+
"""Show a transient dim ``· {text}`` line (e.g. while a network call runs)."""
|
|
276
|
+
self._draw(note=text)
|
|
277
|
+
|
|
278
|
+
def retry_text(self, message: str) -> None:
|
|
279
|
+
"""Re-arm the code step with an error sub-line (used after a wrong code)."""
|
|
280
|
+
# text_step's own loop shows the error; this is for the verify-fail re-prompt path.
|
|
281
|
+
self._draw(error=message)
|
|
282
|
+
|
|
283
|
+
def pick(self, slugs: Sequence[str], *, default: Optional[str] = None) -> str:
|
|
284
|
+
"""The nested org-picker inset: arrow keys move the cursor, Enter selects (collapses to
|
|
285
|
+
``✓ org {slug}``), Esc / Ctrl-C raise ``LoginCancelled``."""
|
|
286
|
+
slugs = list(slugs)
|
|
287
|
+
idx = slugs.index(default) if default in slugs else 0
|
|
288
|
+
self.active = None
|
|
289
|
+
self._draw(inset=output.login_inset(slugs, idx))
|
|
290
|
+
while True:
|
|
291
|
+
try:
|
|
292
|
+
key = _read_key(self._fd)
|
|
293
|
+
except KeyboardInterrupt:
|
|
294
|
+
raise LoginCancelled()
|
|
295
|
+
if key in ("UP", "k"):
|
|
296
|
+
idx = (idx - 1) % len(slugs)
|
|
297
|
+
elif key in ("DOWN", "j"):
|
|
298
|
+
idx = (idx + 1) % len(slugs)
|
|
299
|
+
elif key == "ENTER":
|
|
300
|
+
chosen = slugs[idx]
|
|
301
|
+
self.done.append(("org", chosen))
|
|
302
|
+
self._draw()
|
|
303
|
+
return chosen
|
|
304
|
+
elif key in ("ESC", "CTRL_C", "q", "EOF"):
|
|
305
|
+
raise LoginCancelled()
|
|
306
|
+
else:
|
|
307
|
+
continue
|
|
308
|
+
self._draw(inset=output.login_inset(slugs, idx))
|
|
309
|
+
|
|
310
|
+
def finish(self, email: str, org: Optional[str]) -> None:
|
|
311
|
+
"""Final state: the outer border + legend flip SUCCESS green; ``● signed in`` + email + org."""
|
|
312
|
+
self._draw(signed_in=(email, org))
|
|
313
|
+
|
|
314
|
+
def cancel(self, persisted: bool) -> None:
|
|
315
|
+
"""Render the calm close — ``○ cancelled — not signed in`` (or ``○ signed in · pick an org …``
|
|
316
|
+
when the session was already persisted)."""
|
|
317
|
+
self._draw(cancelled=bool(persisted))
|
|
318
|
+
|
|
319
|
+
def fail(self, message: str, hint: Optional[str] = None) -> None:
|
|
320
|
+
"""Render a failure INSIDE the box (red border + ``✗ {message}`` + an optional hint) — e.g.
|
|
321
|
+
a wrong/expired code — instead of a separate error box below the frame."""
|
|
322
|
+
self._draw(failed=(message, hint))
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""Shared brand color tokens + the permission action→color map.
|
|
2
|
+
|
|
3
|
+
Truecolor hex; Rich downgrades to the nearest supported color automatically and drops color
|
|
4
|
+
entirely under ``NO_COLOR`` / non-color terminals.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
ACCENT = "#9d7bff" # brand mark, box borders, active org, command names in hints
|
|
10
|
+
TEXT = "#d8d2dd" # primary values
|
|
11
|
+
TEXT_DIM = "#7d7488" # ids, resource names, org names
|
|
12
|
+
LABEL = "#6b6478" # field labels, header cells, hints
|
|
13
|
+
FAINT = "#5a5266" # separators, inactive markers
|
|
14
|
+
THIN_RULE = "#2e2435" # the faint rule beneath a list-panel header
|
|
15
|
+
BAR_EMPTY = "#2a2530" # the unfilled cells of a mini-bar (e.g. the aggregate avg bar)
|
|
16
|
+
INSET_BG = "#231e2d" # a hair-lighter fill for a nested inset box (the login org picker)
|
|
17
|
+
|
|
18
|
+
# Errors theme — the one per-command border deviation (the `errors` list + aggregate card).
|
|
19
|
+
# Always red, regardless of error count, so the two views read as one consistent family.
|
|
20
|
+
BORDER_ERROR = "#e2564a" # red → the errors panel border (same as ERROR; consistent, not count-dependent)
|
|
21
|
+
TITLE_ERROR_DIM = "#6e3530" # dim red → the errors title's non-name part + card separators
|
|
22
|
+
RULE_ERROR = "#3a2d2d" # dim red → the errors list header rule (vs the neutral THIN_RULE)
|
|
23
|
+
|
|
24
|
+
# Semantic value colors — for run/job states and score thresholds. (They coincide with
|
|
25
|
+
# the perm risk colors below; named separately so the two uses can diverge later.)
|
|
26
|
+
SUCCESS = "#5dcaa5" # green → run status: done/passed
|
|
27
|
+
AMBER = "#ef9f27" # amber → run status: running/pending · score band .50–.80
|
|
28
|
+
ERROR = "#e2564a" # red → run status: failed/error · score band < .50
|
|
29
|
+
SCORE_HIGH = "#3ddbb8" # cyan-green → score band ≥ .80 (distinct from status green)
|
|
30
|
+
BLUE = "#6b86d8" # blue → schema uuid/timestamp type category
|
|
31
|
+
PINK = "#d4537e" # pink → numeric values (query run cells / scalar card) + numeric type category
|
|
32
|
+
|
|
33
|
+
# Permission verb colors — by ACTION (the part after `:`), never by resource.
|
|
34
|
+
PERM_READ = "#5dcaa5" # green → read
|
|
35
|
+
PERM_WRITE = "#d4537e" # pink → add, create, write, update
|
|
36
|
+
PERM_ACTION = "#ef9f27" # amber → use, trigger, run, ack
|
|
37
|
+
PERM_DANGER = "#e2564a" # red → delete, disable, regenerate
|
|
38
|
+
|
|
39
|
+
PERM_COLORS = {
|
|
40
|
+
"read": PERM_READ,
|
|
41
|
+
"add": PERM_WRITE, "create": PERM_WRITE, "write": PERM_WRITE, "update": PERM_WRITE,
|
|
42
|
+
"use": PERM_ACTION, "trigger": PERM_ACTION, "run": PERM_ACTION, "ack": PERM_ACTION,
|
|
43
|
+
"delete": PERM_DANGER, "disable": PERM_DANGER, "regenerate": PERM_DANGER,
|
|
44
|
+
}
|
|
45
|
+
DEFAULT_PERM_COLOR = LABEL # any unmapped action → neutral dim (never crash / guess a risk)
|
|
46
|
+
|
|
47
|
+
# Risk rank for ordering actions within a row: read → modify → invoke → destroy.
|
|
48
|
+
PERM_RANK = {PERM_READ: 0, PERM_WRITE: 1, PERM_ACTION: 2, PERM_DANGER: 3}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def perm_color(action: str) -> str:
|
|
52
|
+
"""The color for a permission action, or the neutral default if it's unmapped."""
|
|
53
|
+
return PERM_COLORS.get(action, DEFAULT_PERM_COLOR)
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "fp-cloud-cli"
|
|
7
|
+
dynamic = ["version"]
|
|
8
|
+
requires-python = ">=3.10"
|
|
9
|
+
description = "Command line client for FailproofAI Cloud — sessions, events, evaluations and audits from your terminal"
|
|
10
|
+
readme = "README.md"
|
|
11
|
+
license = { file = "LICENSE" }
|
|
12
|
+
authors = [{ name = "Failproof AI", email = "failproofai@exosphere.host" }]
|
|
13
|
+
keywords = ["agents", "observability", "ai", "monitoring", "failproofai", "cli"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 4 - Beta",
|
|
16
|
+
"Environment :: Console",
|
|
17
|
+
"Intended Audience :: Developers",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Programming Language :: Python :: 3.10",
|
|
20
|
+
"Programming Language :: Python :: 3.11",
|
|
21
|
+
"Programming Language :: Python :: 3.12",
|
|
22
|
+
"Programming Language :: Python :: 3.13",
|
|
23
|
+
"Typing :: Typed",
|
|
24
|
+
]
|
|
25
|
+
dependencies = [
|
|
26
|
+
"httpx>=0.27",
|
|
27
|
+
# This range spans typer's Click split: 0.26 vendored Click into `typer/_click` and
|
|
28
|
+
# dropped the `click` dependency, so Typer's command runner catches ITS Click's
|
|
29
|
+
# exceptions, not the pip `click` ones. `fp_cli/_click_compat` resolves whichever
|
|
30
|
+
# Click the installed typer is running, and everything raises, subclasses and inspects
|
|
31
|
+
# through that — which is what makes both sides of the split work. Import Click from
|
|
32
|
+
# there and nowhere else; `tests/test_click_compat.py` enforces it, because every way
|
|
33
|
+
# this breaks is silent (typed errors collapse to exit 1 with an empty stderr, and the
|
|
34
|
+
# telemetry flag catalog empties). Suite verified against 0.25.1 and 0.27.0.
|
|
35
|
+
#
|
|
36
|
+
# The floor is 0.13, not 0.12, because 0.12 cannot BUILD this app: the global
|
|
37
|
+
# `--insecure/--secure` option in `app.py` is an `Optional[bool]` with a
|
|
38
|
+
# secondary flag, which 0.12's Click reaches as a non-boolean flag and
|
|
39
|
+
# rejects with `TypeError: Secondary flag is not valid for non-boolean flag`.
|
|
40
|
+
# That fires while the command tree is constructed, before any parsing, so
|
|
41
|
+
# `fp --version`, `fp --help` and every subcommand die identically — an
|
|
42
|
+
# installed CLI that cannot run one command. `uv.lock` pins 0.27.1, so
|
|
43
|
+
# neither CI nor the publish smoke test ever installed the broken part of the
|
|
44
|
+
# range. Measured across 0.12.0/0.12.3/0.12.5 (all fail) and 0.13.0 upward
|
|
45
|
+
# (all pass).
|
|
46
|
+
"typer>=0.13,<0.28",
|
|
47
|
+
# `click` is what `_click_compat` falls back to when typer is < 0.26 (0.26+ brings its
|
|
48
|
+
# own), and `pygments` is imported directly. Both are declared rather than relied on
|
|
49
|
+
# transitively: modern `typer` no longer installs `click`, and `rich` could likewise
|
|
50
|
+
# drop `pygments`.
|
|
51
|
+
"click>=8.1",
|
|
52
|
+
"rich>=13",
|
|
53
|
+
"pygments>=2.13",
|
|
54
|
+
"posthog>=3.5,<8",
|
|
55
|
+
]
|
|
56
|
+
|
|
57
|
+
# The distribution is `fp-cloud-cli`; the command is `fp`; the import package is
|
|
58
|
+
# `fp_cli`. All three differ, and each for its own reason:
|
|
59
|
+
#
|
|
60
|
+
# `fp` was already registered on PyPI by someone else.
|
|
61
|
+
# `fp-cli` was the next choice and is ALSO unusable: PyPI refuses a name
|
|
62
|
+
# "too similar to an existing project", and its similarity check
|
|
63
|
+
# strips separators — so `fp-cli` collides with `fpcli`, a real
|
|
64
|
+
# package with 42 releases. It is not a squat, so there is no
|
|
65
|
+
# PEP 541 claim to make; the name simply is not available.
|
|
66
|
+
# `fp-cloud-cli` is what pip resolves, and says what this talks to: the Cloud
|
|
67
|
+
# dashboard's API, never the Rust server directly.
|
|
68
|
+
# `fp_cli` stays as the import package. Nobody imports it — this is an
|
|
69
|
+
# application, not a library, and the console script above is the
|
|
70
|
+
# entire public surface — so renaming it would churn every module
|
|
71
|
+
# and every test to change a string no user ever types.
|
|
72
|
+
#
|
|
73
|
+
# `~/.failproofai/fpcli/` keeps its name for a harder reason: it is an on-disk
|
|
74
|
+
# contract with `src/hooks/fp-home.ts` (`fpcliDir`/`fpcliAuthFile`), and moving it
|
|
75
|
+
# would sign every existing user out.
|
|
76
|
+
[project.scripts]
|
|
77
|
+
fp = "fp_cli.app:main_entry"
|
|
78
|
+
|
|
79
|
+
[project.urls]
|
|
80
|
+
Homepage = "https://befailproof.ai"
|
|
81
|
+
# The live route. `/agenteye/cli` is a 404 — those pages moved to `docs-old/`,
|
|
82
|
+
# which the docs build does not publish and `docs/docs.json` does not reference,
|
|
83
|
+
# and there are no `redirects`. PyPI bakes project URLs into published metadata,
|
|
84
|
+
# so a wrong one here needs a version bump to correct.
|
|
85
|
+
Documentation = "https://docs.befailproof.ai/reference/cloud-cli"
|
|
86
|
+
Source = "https://github.com/FailproofAI/failproofai"
|
|
87
|
+
# PyPI gives "Changelog" its own sidebar slot and icon. Without it the only
|
|
88
|
+
# thing a visitor to the project page can read is the README, and there is no
|
|
89
|
+
# route at all from an installed version to what changed in it.
|
|
90
|
+
Changelog = "https://github.com/FailproofAI/failproofai/blob/main/fp-cloud-cli/CHANGELOG.md"
|
|
91
|
+
|
|
92
|
+
[project.optional-dependencies]
|
|
93
|
+
dev = ["pytest>=7", "respx>=0.21"]
|
|
94
|
+
|
|
95
|
+
[tool.setuptools.dynamic]
|
|
96
|
+
version = { attr = "fp_cli._version.__version__" }
|
|
97
|
+
|
|
98
|
+
[tool.setuptools.packages.find]
|
|
99
|
+
where = ["."]
|
|
100
|
+
include = ["fp_cli*"]
|
|
101
|
+
|
|
102
|
+
[tool.setuptools.package-data]
|
|
103
|
+
fp_cli = ["py.typed"]
|
|
104
|
+
|
|
105
|
+
[tool.pytest.ini_options]
|
|
106
|
+
testpaths = ["tests"]
|