failproofai 1.0.1 → 1.0.2-beta.1
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]__0l4748x._.js +3 -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]__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/_08x1r5t._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_0bwu160._.js +23 -0
- package/.next/standalone/.next/server/chunks/ssr/{_0u5zauv._.js → _0ns6k3a._.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/{3c808qrfcq0im.js → 01u1cf8js2yd6.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0k5050ezjvv49.js → 0izgu7nqh2zp-.js} +1 -1
- package/.next/standalone/.next/static/chunks/0u4-org_e7zde.js +1 -0
- package/.next/standalone/.next/static/chunks/1mfzsja6ftim5.css +2 -0
- package/.next/standalone/.next/static/chunks/{2zpp1we2jv6tb.js → 1tynnrrh711lr.js} +1 -1
- package/.next/standalone/.next/static/chunks/{1ide1wl2f7zi1.js → 22rqvlr7p_1mv.js} +13 -13
- package/.next/standalone/.next/static/chunks/{31s1smp-g7gks.js → 2whxqyskpirbk.js} +1 -1
- package/.next/standalone/.next/static/chunks/31mwk8k0q3_3g.js +6 -0
- package/.next/standalone/.next/static/chunks/3ms6gxfm82t6s.js +1 -0
- package/.next/standalone/.next/static/chunks/{37fcpc36x9gpe.js → 3tbbs_d8xrvyp.js} +1 -1
- package/.next/standalone/.next/static/chunks/43nlc236oo898.js +1 -0
- 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 +163 -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 -15
- 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 +27 -21
- 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 +579 -306
- package/dist/cli.mjs +6499 -3662
- package/dist/index.js +5 -5
- package/dist/worker.mjs +2390 -1978
- package/package.json +27 -21
- 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 +56 -369
- package/src/hooks/custom-hooks-loader.ts +89 -6
- package/src/hooks/fp-home.ts +92 -4
- package/src/hooks/fp-reset.ts +34 -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 +424 -172
- package/src/hooks/migrations.ts +2 -2
- package/src/hooks/pack-cli.ts +885 -0
- package/src/hooks/pack-failclosed.ts +189 -0
- package/src/hooks/pack-manifest.ts +352 -0
- package/src/hooks/pack-store.ts +891 -0
- package/src/hooks/policy-catalog.ts +535 -0
- package/src/hooks/policy-evaluator.ts +24 -16
- 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 +695 -39
- 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]__07tbbf3._.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/server/chunks/ssr/_0lvyuv4._.js +0 -23
- package/.next/standalone/.next/static/chunks/2_2lhuojq2xop.js +0 -1
- package/.next/standalone/.next/static/chunks/36fw6yk1s6x_f.js +0 -1
- package/.next/standalone/.next/static/chunks/3k7mxbp9hiom0.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/src/hooks/policy-presets.ts +0 -135
- /package/.next/standalone/.next/static/{ZklXxyA5ygsWSQz2u_zii → I5kEb9kSgYS63j4iqfVLO}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{ZklXxyA5ygsWSQz2u_zii → I5kEb9kSgYS63j4iqfVLO}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{ZklXxyA5ygsWSQz2u_zii → I5kEb9kSgYS63j4iqfVLO}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
"""orgs list / orgs switch / orgs current — discover, select, and inspect the active tenant.
|
|
2
|
+
|
|
3
|
+
Org membership comes from the session (no dedicated list endpoint), so the
|
|
4
|
+
listing reads it via ``GET /api/auth/session``. ``switch`` persists the chosen
|
|
5
|
+
slug to ``~/.failproofai/fpcli/cli-auth.json`` so later commands send it as the
|
|
6
|
+
``X-AgentEye-Org`` header; ``current`` reports the tenant in effect right now.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import difflib
|
|
12
|
+
from typing import Optional
|
|
13
|
+
|
|
14
|
+
import typer
|
|
15
|
+
|
|
16
|
+
from .. import _click_compat as click # the Click Typer is running; see _click_compat
|
|
17
|
+
from .. import analytics
|
|
18
|
+
from .. import config as cfgmod
|
|
19
|
+
from .. import orgs as orgsmod
|
|
20
|
+
from .. import output
|
|
21
|
+
from .. import select as selectmod
|
|
22
|
+
from .._context import GLOBALS_EPILOG, AppState, build_context, deny_in_key_mode
|
|
23
|
+
from ..client import get_session_user, org_is_accessible
|
|
24
|
+
from ..errors import AuthError
|
|
25
|
+
|
|
26
|
+
# Every subcommand here reads or writes the SESSION's org memberships, which an API key
|
|
27
|
+
# does not have: memberships belong to a person, and `GET /auth/session` (their only
|
|
28
|
+
# source) is deliberately absent from the versioned API. Refuse before any network call
|
|
29
|
+
# rather than let a 404 on a path that does not exist explain it.
|
|
30
|
+
_KEY_MODE_REASON = (
|
|
31
|
+
"org membership belongs to a signed-in user; a key already acts for one org "
|
|
32
|
+
"(pass --org <slug> to target another)"
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _require_session(state: AppState):
|
|
37
|
+
"""Fetch the session user, or emit a friendly 'not logged in' and exit 4-style."""
|
|
38
|
+
if not state.token:
|
|
39
|
+
raise AuthError("Not logged in. Run fp login.")
|
|
40
|
+
return get_session_user(build_context(state))
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def _active_org(state: AppState, user) -> Optional[str]:
|
|
44
|
+
"""The effective active org: the explicit/saved value, else your sole org."""
|
|
45
|
+
active = state.org
|
|
46
|
+
if not active and len(user.memberships) == 1:
|
|
47
|
+
active = user.memberships[0].org_slug
|
|
48
|
+
return active
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _persist_org(state: AppState, slug: str) -> None:
|
|
52
|
+
"""Persist ``slug`` as the active tenant (no rendering — the caller chooses the output)."""
|
|
53
|
+
state.config.org = slug
|
|
54
|
+
cfgmod.save_config(state.config)
|
|
55
|
+
analytics.capture("org_selected")
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def _switch_to(state: AppState, slug: str, *, prev: Optional[str], perm_count: Optional[int]) -> None:
|
|
59
|
+
"""Persist the chosen org and render the result — the boxed 'switched org' card (or the
|
|
60
|
+
``{"active_org"}`` payload under ``--json``). Shared by the positional + interactive paths so
|
|
61
|
+
both render identically."""
|
|
62
|
+
_persist_org(state, slug)
|
|
63
|
+
if state.json:
|
|
64
|
+
output.emit_json({"active_org": slug})
|
|
65
|
+
else:
|
|
66
|
+
output.render_switched_org(slug=slug, prev_slug=prev, perm_count=perm_count)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def _render_orgs(state: AppState) -> None:
|
|
70
|
+
"""Shared body of ``orgs list`` — your orgs + your role in each."""
|
|
71
|
+
user = _require_session(state)
|
|
72
|
+
active = _active_org(state, user)
|
|
73
|
+
|
|
74
|
+
if state.json:
|
|
75
|
+
output.emit_json(
|
|
76
|
+
{
|
|
77
|
+
"active_org": active,
|
|
78
|
+
"is_instance_admin": user.is_instance_admin,
|
|
79
|
+
"orgs": [
|
|
80
|
+
{
|
|
81
|
+
"org_slug": m.org_slug,
|
|
82
|
+
"org_name": m.org_name,
|
|
83
|
+
"permission_set": m.permission_set,
|
|
84
|
+
"permissions": m.permissions,
|
|
85
|
+
"active": m.org_slug == active,
|
|
86
|
+
}
|
|
87
|
+
for m in user.memberships
|
|
88
|
+
],
|
|
89
|
+
}
|
|
90
|
+
)
|
|
91
|
+
return
|
|
92
|
+
|
|
93
|
+
if not user.memberships:
|
|
94
|
+
output.info(" You are not a member of any org.")
|
|
95
|
+
if user.is_instance_admin:
|
|
96
|
+
output.hint(" Instance admin — pass --org <slug> to act in a specific org.")
|
|
97
|
+
return
|
|
98
|
+
output.render_orgs_list([
|
|
99
|
+
{
|
|
100
|
+
"is_active": m.org_slug == active,
|
|
101
|
+
"slug": m.org_slug,
|
|
102
|
+
"name": m.org_name,
|
|
103
|
+
"role": m.permission_set or "custom",
|
|
104
|
+
"perms": len(m.permissions),
|
|
105
|
+
}
|
|
106
|
+
for m in user.memberships
|
|
107
|
+
])
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
# ── commands ────────────────────────────────────────────────────────────────
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def org_list(ctx: typer.Context) -> None:
|
|
114
|
+
"""List the orgs you belong to, with your role in each (the active one is marked).
|
|
115
|
+
|
|
116
|
+
Reads your memberships from the current session — for each org it shows the org
|
|
117
|
+
slug + name, your permission set (role), and how many permissions you hold there.
|
|
118
|
+
The active org (`--org`/`FP_ORG`/saved, or your sole org) is marked `●`. With
|
|
119
|
+
`--json`: `{"active_org", "is_instance_admin", "orgs":[{"org_slug","org_name",
|
|
120
|
+
"permission_set","permissions","active"}]}`.
|
|
121
|
+
|
|
122
|
+
Example:
|
|
123
|
+
|
|
124
|
+
* `fp orgs list`
|
|
125
|
+
* `fp --json orgs list`
|
|
126
|
+
"""
|
|
127
|
+
deny_in_key_mode(ctx.obj, "orgs list", _KEY_MODE_REASON)
|
|
128
|
+
_render_orgs(ctx.obj)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def _active_membership(user, active):
|
|
132
|
+
"""The membership for the active org (or None — e.g. an instance admin acting via --org)."""
|
|
133
|
+
return next((m for m in user.memberships if m.org_slug == active), None)
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def org_current(ctx: typer.Context) -> None:
|
|
137
|
+
"""Show the org/tenant you're acting as right now — a compact identity card.
|
|
138
|
+
|
|
139
|
+
The active org is the global `--org`/`FP_ORG`, else the saved default, else your sole
|
|
140
|
+
org if you belong to just one. The card shows the slug + name, your role, your permission
|
|
141
|
+
count, and the signed-in email; see the permissions themselves with `fp orgs perms`.
|
|
142
|
+
If you haven't picked an org it tells you to run `fp orgs switch`. With `--json`:
|
|
143
|
+
`{"slug", "name", "role", "permission_count", "user_email"}`.
|
|
144
|
+
|
|
145
|
+
Example:
|
|
146
|
+
|
|
147
|
+
* `fp orgs current`
|
|
148
|
+
* `fp --json orgs current`
|
|
149
|
+
"""
|
|
150
|
+
state: AppState = ctx.obj
|
|
151
|
+
deny_in_key_mode(state, "orgs current", _KEY_MODE_REASON)
|
|
152
|
+
user = _require_session(state)
|
|
153
|
+
active = _active_org(state, user)
|
|
154
|
+
m = _active_membership(user, active)
|
|
155
|
+
role = (m.permission_set or "custom") if m else ("instance admin (not a member)" if active else None)
|
|
156
|
+
perm_count = len(m.permissions) if m else 0
|
|
157
|
+
|
|
158
|
+
if state.json:
|
|
159
|
+
output.emit_json(
|
|
160
|
+
{
|
|
161
|
+
"slug": active,
|
|
162
|
+
"name": m.org_name if m else None,
|
|
163
|
+
"role": role,
|
|
164
|
+
"permission_count": perm_count,
|
|
165
|
+
"user_email": user.email,
|
|
166
|
+
}
|
|
167
|
+
)
|
|
168
|
+
return
|
|
169
|
+
|
|
170
|
+
if not active:
|
|
171
|
+
output.info(" No active org selected.")
|
|
172
|
+
output.hint(" Run fp orgs switch to choose one.")
|
|
173
|
+
return
|
|
174
|
+
output.render_current_org(
|
|
175
|
+
slug=active, name=m.org_name if m else None, role=role or "—",
|
|
176
|
+
permission_count=perm_count, email=user.email,
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def org_perms(ctx: typer.Context) -> None:
|
|
181
|
+
"""Show your permissions in the active org — grouped by resource, coloured by risk.
|
|
182
|
+
|
|
183
|
+
The same grouped view as `fp whoami`, scoped to the active org: one row per resource
|
|
184
|
+
with its actions (read = green, create/modify = pink, invoke = amber, destructive = red).
|
|
185
|
+
With `--json`: `{"slug", "role", "permissions", "permission_count"}` (the flat grant list).
|
|
186
|
+
|
|
187
|
+
Example:
|
|
188
|
+
|
|
189
|
+
* `fp orgs perms`
|
|
190
|
+
* `fp --json orgs perms`
|
|
191
|
+
"""
|
|
192
|
+
state: AppState = ctx.obj
|
|
193
|
+
deny_in_key_mode(state, "orgs perms", _KEY_MODE_REASON)
|
|
194
|
+
user = _require_session(state)
|
|
195
|
+
active = _active_org(state, user)
|
|
196
|
+
m = _active_membership(user, active)
|
|
197
|
+
|
|
198
|
+
if state.json:
|
|
199
|
+
output.emit_json(
|
|
200
|
+
{
|
|
201
|
+
"slug": active,
|
|
202
|
+
"role": (m.permission_set or "custom") if m else None,
|
|
203
|
+
"permissions": m.permissions if m else [],
|
|
204
|
+
"permission_count": len(m.permissions) if m else 0,
|
|
205
|
+
}
|
|
206
|
+
)
|
|
207
|
+
return
|
|
208
|
+
|
|
209
|
+
if not active:
|
|
210
|
+
output.info(" No active org selected.")
|
|
211
|
+
output.hint(" Run fp orgs switch to choose one.")
|
|
212
|
+
return
|
|
213
|
+
if not m:
|
|
214
|
+
output.info(f" You are not a member of '{active}' (acting as instance admin).")
|
|
215
|
+
output.hint(" Instance admins hold no per-org grants; switch to an org you belong to.")
|
|
216
|
+
return
|
|
217
|
+
output.render_org_perms(slug=active, role=m.permission_set or "custom",
|
|
218
|
+
permissions=m.permissions, name=m.org_name)
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def org_switch(
|
|
222
|
+
ctx: typer.Context,
|
|
223
|
+
slug: Optional[str] = typer.Argument(
|
|
224
|
+
None, help="Org/tenant slug to switch to. Omit it to pick from an arrow-key list (in a terminal)."
|
|
225
|
+
),
|
|
226
|
+
) -> None:
|
|
227
|
+
"""Switch the active org/tenant — pass a slug, or omit it to pick one interactively.
|
|
228
|
+
|
|
229
|
+
`fp orgs switch acme` switches straight to `acme`. `fp orgs switch` with no slug
|
|
230
|
+
opens an arrow-key picker (↑↓ to move, ⏎ to select, esc to cancel) starting on your current
|
|
231
|
+
org; if you belong to exactly one org there's nothing to switch to. Either way the result is
|
|
232
|
+
a boxed `switched org` card, and the choice is persisted to
|
|
233
|
+
`~/.failproofai/fpcli/cli-auth.json` so later
|
|
234
|
+
commands send it as the active tenant.
|
|
235
|
+
|
|
236
|
+
A non-interactive run (piped stdin / CI) falls back to a numbered prompt. With `--json` a slug
|
|
237
|
+
is required and the output is just `{"active_org": "<slug>"}` — no card.
|
|
238
|
+
|
|
239
|
+
Examples:
|
|
240
|
+
|
|
241
|
+
* `fp orgs switch acme` — switch straight to acme
|
|
242
|
+
* `fp orgs switch` — pick from an arrow-key list
|
|
243
|
+
* `fp --json orgs switch acme | jq` — switch and capture the active org
|
|
244
|
+
"""
|
|
245
|
+
state: AppState = ctx.obj
|
|
246
|
+
deny_in_key_mode(state, "orgs switch", _KEY_MODE_REASON)
|
|
247
|
+
user = _require_session(state)
|
|
248
|
+
current = _active_org(state, user)
|
|
249
|
+
|
|
250
|
+
def _perms_for(s: str) -> Optional[int]:
|
|
251
|
+
return next((len(m.permissions) for m in user.memberships if m.org_slug == s), None)
|
|
252
|
+
|
|
253
|
+
# ── positional form: resolve + switch directly (same card as the picker) ──
|
|
254
|
+
if slug is not None:
|
|
255
|
+
accessible = slug in user.org_slugs or (
|
|
256
|
+
user.is_instance_admin
|
|
257
|
+
and orgsmod.is_valid_org_slug(slug)
|
|
258
|
+
and org_is_accessible(build_context(state), slug)
|
|
259
|
+
)
|
|
260
|
+
if not accessible:
|
|
261
|
+
# Raise a usage error (exit 2) the central chokepoint renders the same way under
|
|
262
|
+
# --json (a JSON envelope on stdout) and for humans (a red box on stderr) — the old
|
|
263
|
+
# code emitted nothing under --json, so a script got a bare exit 2 with no reason.
|
|
264
|
+
match = difflib.get_close_matches(slug, user.org_slugs, n=1, cutoff=0.6)
|
|
265
|
+
err = click.UsageError(f"no org named {slug}")
|
|
266
|
+
err.hint = (
|
|
267
|
+
f"did you mean {match[0]}" if match else "run `fp orgs list` to see your orgs"
|
|
268
|
+
)
|
|
269
|
+
raise err
|
|
270
|
+
if slug == current:
|
|
271
|
+
output.emit_json({"active_org": slug}) if state.json else output.org_already_on(slug)
|
|
272
|
+
return
|
|
273
|
+
_switch_to(state, slug, prev=current, perm_count=_perms_for(slug))
|
|
274
|
+
return
|
|
275
|
+
|
|
276
|
+
# ── no slug → discover ──
|
|
277
|
+
slugs = user.org_slugs
|
|
278
|
+
if not slugs:
|
|
279
|
+
output.emit_json({"active_org": current}) if state.json else \
|
|
280
|
+
output.org_none_available(instance_admin=user.is_instance_admin)
|
|
281
|
+
return
|
|
282
|
+
if len(slugs) == 1:
|
|
283
|
+
_persist_org(state, slugs[0])
|
|
284
|
+
output.emit_json({"active_org": slugs[0]}) if state.json else output.org_only_one(slugs[0])
|
|
285
|
+
return
|
|
286
|
+
if state.json:
|
|
287
|
+
# No card to render in json mode and no way to pick → require an explicit slug.
|
|
288
|
+
raise typer.BadParameter(
|
|
289
|
+
"No org given. With --json pass a slug, e.g. `fp --json orgs switch <slug>`."
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
# Pick: an arrow-key picker on a real TTY, else a numbered prompt (reads piped input;
|
|
293
|
+
# aborts cleanly on empty stdin) — both inside choose_org_interactive.
|
|
294
|
+
orgs_view = [{"slug": m.org_slug, "is_current": m.org_slug == current} for m in user.memberships]
|
|
295
|
+
chosen = selectmod.choose_org_interactive(orgs_view, current_slug=current)
|
|
296
|
+
if chosen is None:
|
|
297
|
+
output.org_switch_cancelled(current)
|
|
298
|
+
return
|
|
299
|
+
if chosen == current:
|
|
300
|
+
output.org_already_on(chosen)
|
|
301
|
+
return
|
|
302
|
+
_switch_to(state, chosen, prev=current, perm_count=_perms_for(chosen))
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
def register(app: typer.Typer) -> None:
|
|
306
|
+
_ctx = {"help_option_names": ["-h", "--help"]}
|
|
307
|
+
|
|
308
|
+
# A single `orgs` group holding all tenant functionality.
|
|
309
|
+
orgs_app = typer.Typer(
|
|
310
|
+
no_args_is_help=True,
|
|
311
|
+
rich_markup_mode="markdown",
|
|
312
|
+
context_settings=_ctx,
|
|
313
|
+
help="Inspect and select the active org/tenant. Subcommands: **list**, **switch**, **current**, **perms**.",
|
|
314
|
+
)
|
|
315
|
+
orgs_app.command("list", epilog=GLOBALS_EPILOG)(org_list)
|
|
316
|
+
orgs_app.command("switch", epilog=GLOBALS_EPILOG)(org_switch)
|
|
317
|
+
orgs_app.command("current", epilog=GLOBALS_EPILOG)(org_current)
|
|
318
|
+
orgs_app.command("perms", epilog=GLOBALS_EPILOG)(org_perms)
|
|
319
|
+
app.add_typer(orgs_app, name="orgs")
|