failproofai 1.0.12-beta.2 → 1.0.13-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 +13 -13
- package/.next/standalone/.next/prerender-manifest.json +3 -3
- package/.next/standalone/.next/required-server-files.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page/build-manifest.json +2 -2
- 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 -1
- 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 +2 -2
- package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found/page/build-manifest.json +2 -2
- 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 +4 -3
- 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 +3 -3
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/api/audit/invite/route.js +6 -5
- 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 +27 -26
- 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 +4 -3
- 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 +6 -5
- 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 +6 -5
- 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 +6 -5
- 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 +6 -5
- 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 +4 -3
- package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/audit/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
- package/.next/standalone/.next/server/app/audit/page.js +7 -6
- 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 +3 -3
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/page.js +6 -5
- 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/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +14 -14
- 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/build-manifest.json +2 -2
- 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 +21 -20
- 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/build-manifest.json +2 -2
- 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 +10 -9
- 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/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/projects/page.js +7 -6
- 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/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +8 -8
- package/.next/standalone/.next/server/app/settings/page.js +6 -5
- 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]__0vt9i6fqinjne._.js → [externals]__1h83uo-b1b6-2._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[externals]__214wn4wh2x79y._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[externals]__1rlxpymm37wel._.js → [root-of-the-server]__031qp1lkow_kc._.js} +2 -2
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__038kwryp970nh._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0_hsnj_a2mvl_._.js → [root-of-the-server]__03s1za0hn71yp._.js} +2 -2
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0wg9dk8x8bnau._.js → [root-of-the-server]__07a0sa6fuw5_b._.js} +2 -2
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__08atcie7jzswm._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__08dchfudh2_4f._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0car70pylmvor._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0spt0kv8azrpl._.js +1 -1
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__12kq3x-h7t7i1._.js → [root-of-the-server]__0yvyp5b7jmlc4._.js} +2 -2
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__02vous7mpi2xm._.js → [root-of-the-server]__145vo_drnuvas._.js} +2 -2
- package/.next/standalone/.next/server/chunks/{[externals]__0h0p9dmv_e7r7._.js → [root-of-the-server]__1a2d0ewycsp6k._.js} +2 -2
- package/.next/standalone/.next/server/chunks/{[externals]__1_407huhlmj1m._.js → [root-of-the-server]__1am_1tz0o0aqz._.js} +2 -2
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__03i5o4a840guz._.js → [root-of-the-server]__1gxfzuvpyw30j._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1j6kfp0vzu5rw._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1l0ayum_hqqsw._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1lh8c0mmhdrbj._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1o9rznwc0w7og._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0f_4g-vazrvxv._.js → [root-of-the-server]__1o_622x0fglpr._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1oclamblhzhrf._.js +68 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1v1-l-83czzsr._.js +63 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__1a5zkndjwlc13._.js → [root-of-the-server]__1wwi53kkqhnfi._.js} +1 -1
- package/.next/standalone/.next/server/chunks/{_1y590mjzpkbos._.js → _02sa8fcu9_9xo._.js} +2 -2
- package/.next/standalone/.next/server/chunks/_0tovk6q0miud6._.js +1 -1
- package/.next/standalone/.next/server/chunks/_0trp3ycqv17cl._.js +1 -1
- package/.next/standalone/.next/server/chunks/_1-2owkp-1_987._.js +1 -1
- package/.next/standalone/.next/server/chunks/_13ltj8a9z92o8._.js +1 -1
- package/.next/standalone/.next/server/chunks/_15k37au70vjvg._.js +1 -1
- package/.next/standalone/.next/server/chunks/_18rfu4__wjhwb._.js +1 -1
- package/.next/standalone/.next/server/chunks/_1ek68lnh2daur._.js +2 -2
- package/.next/standalone/.next/server/chunks/_1fz8m31sndkcu._.js +1 -1
- package/.next/standalone/.next/server/chunks/_1ogwigfb0163w._.js +1 -1
- package/.next/standalone/.next/server/chunks/_1vslkoe35wok6._.js +1 -1
- package/.next/standalone/.next/server/chunks/node_modules_@opentelemetry_api_build_esm_index_0oo58a7rymoxh.js +3 -0
- package/.next/standalone/.next/server/chunks/node_modules_@opentelemetry_api_build_esm_index_1jp9ij0_ddtgk.js +3 -0
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_01r25oigsgz07._.js +2 -2
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_09z9-p77cu37y._.js +2 -2
- package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4vkpxxu7._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0ffu2-38y03ic._.js → [root-of-the-server]__021vebe-4il8s._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__075uro8t92s0_._.js +14 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__08ch3staq3ejw._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[externals]__12qr51qgrrt6o._.js → [root-of-the-server]__097i34ct1o88x._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0alpzjn3450sr._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0aup10z2o8zc1._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0bigvy9xmv2ka._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0bioghlkjf7s7._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__01j58mdcdw0vn._.js → [root-of-the-server]__0ed1zh4scn7-k._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0naevg4bcoh54._.js → [root-of-the-server]__0evgy902m9h5e._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0h86bl2qf0k_o._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__00l2u6j86cb8y._.js → [root-of-the-server]__0mhtkwwx1pxcq._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0nhm28v58ty9z._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0pia5h3p8re4c._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0vse4qi496ol-._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__17r4zrwanhp6r._.js → [root-of-the-server]__0yb3u36xjy3b9._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0g8b0kyorya-t._.js → [root-of-the-server]__0ywj2u6ovfm_5._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1-ey9fgesfbc0._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0zn1d4blhd3bu._.js → [root-of-the-server]__10v5cyxvj64j4._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__15usvs-ms-0hf._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__16gb3_92zvk5x._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__190xwrr5zrfi3._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1avi2kypusyb_._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1vx7o8ukefudh._.js → [root-of-the-server]__1guwlpkyurdn9._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1k96jctukf65_._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1r7drlqli-ado._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1sj-wn2jp6va5._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1vofkb2oq7p7e._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1s2-ck3k3rsoo._.js → [root-of-the-server]__20dt376-socef._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1lnfv02ucky7m._.js → [root-of-the-server]__2158020r_amn9._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{_1fw0_nzkae5ao._.js → _0bc4f4quq6w47._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/_0bseae9u7g98r._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_0eoura3_9gjb-._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_0mouhaflye1ro._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_0ouu886szh6yj._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_0pedwblqdoh58._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_1_ozgifqv1ssi._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_1djqs9i27e4kg._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_20hn4gn87nsjc._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_policies_page_actions_1sp2-yo5_vm5f.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/app_actions_get-scheduled-audit_ts_0ei9snixb5fd-._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47q0xq5w._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_components_project-list_tsx_1ke6anr0vt64h._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x33jqb6._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpcz0uxur._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_settings_02tf1h47jmhhd._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules_09s4n108bqreq._.js → node_modules_0ptcnmeaxvd_a._.js} +22 -2
- package/.next/standalone/.next/server/chunks/ssr/node_modules_@opentelemetry_api_build_esm_index_0ntwr8lzj6p2i.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{node_modules_html-to-image_es_index_1fv03uigni8s5.js → node_modules_html-to-image_es_index_1jwgv0pf-gy96.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_0bz67659f5z-3._.js +32 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_0janj0i6dqko7._.js +3 -3
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_0ocrceo0c9psx._.js +32 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_1alv566ojmz5j._.js +32 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_1khq67j4vo9y4._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_shared_lib_0ftnv26hg1lry._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_posthog-node_dist_entrypoints_index_node_mjs_0dagmbznysrc2._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_posthog-node_dist_entrypoints_index_node_mjs_11bnuznb72p7z._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/package_json_[json]_cjs_013tntikdft59._.js +1 -1
- package/.next/standalone/.next/server/middleware-build-manifest.js +13 -13
- package/.next/standalone/.next/server/middleware.js +2 -2
- 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/preview-props.json +3 -3
- package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.json +23 -23
- package/.next/standalone/.next/static/chunks/0cbom4-ijx_a_.js +1 -0
- package/.next/standalone/.next/static/chunks/0u5weo5jdn2s8.js +1 -0
- package/.next/standalone/.next/static/chunks/{1c_jf6g5wnslk.js → 18-icoqze51kl.js} +1 -1
- package/.next/standalone/.next/static/chunks/2d-u90dt4-8rd.js +6 -0
- package/.next/standalone/.next/static/chunks/2n-bzb7pxe7hu.js +1 -0
- package/.next/standalone/.next/static/chunks/{2o6d37j425uci.js → 2zc7lg-jq353g.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0tbm3vjm62h-2.js → 33djjf12bhcsv.js} +1 -1
- package/.next/standalone/.next/static/chunks/{42xptz88mtq3x.js → 38u_i3j5funpi.js} +1 -1
- package/.next/standalone/.next/static/chunks/{20py8k1gd_i1m.js → 3symuj7t4js-c.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0ay__-d2h1xb5.js → 3vzut6zpdrvtx.js} +1 -1
- package/.next/standalone/.next/static/chunks/{063al_q720fkj.js → 3xgxl1s_in776.js} +2 -2
- package/.next/standalone/SECURITY.md +20 -4
- package/.next/standalone/fp-cloud-cli/CHANGELOG.md +34 -1
- package/.next/standalone/fp-cloud-cli/README.md +120 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/_version.py +1 -1
- package/.next/standalone/fp-cloud-cli/fp_cli/app.py +15 -1
- package/.next/standalone/fp-cloud-cli/fp_cli/client.py +198 -7
- package/.next/standalone/fp-cloud-cli/fp_cli/cloud_output.py +523 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/_cloud.py +45 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/_write.py +3 -1
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/account_cmds.py +171 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/agent_cmds.py +80 -7
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/alerts_cmds.py +23 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/audits_cmds.py +2 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/contracts_cmds.py +67 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/dashboards_cmds.py +159 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/evaluators_cmds.py +380 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/events_cmds.py +14 -1
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/incidents_cmds.py +82 -6
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/list_cmds.py +4 -1
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/orgs_cmds.py +17 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/policies_cmds.py +143 -1
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/queries_cmds.py +70 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/sentiment_cmds.py +49 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/sessions_cmds.py +95 -1
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/settings_cmds.py +2 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/usage_cmds.py +21 -1
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/users_cmds.py +14 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/errors.py +3 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/evaluator_spec.py +266 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/output.py +187 -81
- package/.next/standalone/fp-cloud-cli/fp_cli/theme.py +21 -24
- package/.next/standalone/fp-cloud-cli/skill/SKILL.md +124 -23
- package/.next/standalone/fp-cloud-cli/skill/agents/openai.yaml +2 -1
- package/.next/standalone/fp-cloud-cli/skill/references/commands.md +168 -16
- package/.next/standalone/fp-cloud-cli/tests/fake_cloud_smoke.py +312 -0
- package/.next/standalone/fp-cloud-cli/tests/test_cloud_account.py +125 -0
- package/.next/standalone/fp-cloud-cli/tests/test_cloud_agent.py +253 -0
- package/.next/standalone/fp-cloud-cli/tests/test_cloud_human_views.py +287 -0
- package/.next/standalone/fp-cloud-cli/tests/test_cloud_observability.py +116 -0
- package/.next/standalone/fp-cloud-cli/tests/test_cloud_transport.py +141 -0
- package/.next/standalone/fp-cloud-cli/tests/test_commands.py +3 -3
- package/.next/standalone/fp-cloud-cli/tests/test_dashboards_agent.py +3 -3
- package/.next/standalone/fp-cloud-cli/tests/test_evaluator_authoring.py +449 -0
- package/.next/standalone/fp-cloud-cli/tests/test_facets.py +1 -1
- package/.next/standalone/fp-cloud-cli/tests/test_help_table_coverage.py +15 -0
- package/.next/standalone/fp-cloud-cli/tests/test_operator.py +1 -1
- package/.next/standalone/fp-cloud-cli/tests/test_orgs.py +1 -1
- package/.next/standalone/fp-cloud-cli/tests/test_output.py +37 -37
- package/.next/standalone/fp-cloud-cli/tests/test_round4_behaviour.py +144 -0
- package/.next/standalone/fp-cloud-cli/tests/test_screen_language.py +80 -0
- package/.next/standalone/fp-cloud-cli/tests/test_session_reevaluate.py +33 -0
- package/.next/standalone/fp-cloud-cli/tests/test_staging_parity.py +198 -0
- package/.next/standalone/fp-cloud-cli/tests/test_whoami.py +1 -1
- package/.next/standalone/fp-cloud-cli/uv.lock +4 -4
- package/.next/standalone/hermes-plugin/plugin.yaml +1 -1
- package/.next/standalone/node_modules/@next/env/package.json +1 -1
- package/.next/standalone/node_modules/next/dist/build/swc/index.js +1 -1
- package/.next/standalone/node_modules/next/dist/compiled/next-server/app-page-turbo-experimental.runtime.prod.js +24 -24
- package/.next/standalone/node_modules/next/dist/compiled/next-server/app-page-turbo.runtime.prod.js +26 -26
- package/.next/standalone/node_modules/next/dist/compiled/next-server/app-route-turbo.runtime.prod.js +3 -3
- package/.next/standalone/node_modules/next/dist/compiled/next-server/pages-turbo.runtime.prod.js +13 -13
- package/.next/standalone/node_modules/next/dist/lib/patch-incorrect-lockfile.js +3 -3
- package/.next/standalone/node_modules/next/dist/server/app-render/app-render.js +41 -40
- package/.next/standalone/node_modules/next/dist/server/app-render/async-local-storage.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/app-render/dynamic-rendering-validation.js +814 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/dynamic-rendering.js +1 -799
- package/.next/standalone/node_modules/next/dist/server/base-server.js +39 -5
- package/.next/standalone/node_modules/next/dist/server/config.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/dev/hot-reloader-turbopack.js +2 -2
- package/.next/standalone/node_modules/next/dist/server/dev/hot-reloader-webpack.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/lib/app-info-log.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/lib/dedupe-fetch.js +4 -43
- package/.next/standalone/node_modules/next/dist/server/lib/patch-fetch-symbol.js +13 -0
- package/.next/standalone/node_modules/next/dist/server/lib/patch-fetch.js +3 -7
- package/.next/standalone/node_modules/next/dist/server/lib/router-server.js +3 -3
- package/.next/standalone/node_modules/next/dist/server/lib/router-utils/instrumentation-globals.external.js +77 -12
- package/.next/standalone/node_modules/next/dist/server/lib/start-server.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/lib/trace/constants.js +12 -0
- package/.next/standalone/node_modules/next/dist/server/lib/trace/tracer.js +30 -14
- package/.next/standalone/node_modules/next/dist/server/next-server.js +10 -11
- package/.next/standalone/node_modules/next/dist/server/route-modules/pages/pages-handler.js +29 -23
- package/.next/standalone/node_modules/next/dist/server/route-modules/route-module.js +85 -8
- package/.next/standalone/node_modules/next/dist/server/use-cache/use-cache-wrapper.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/web/adapter.js +124 -65
- package/.next/standalone/node_modules/next/dist/server/web/forward-trace-context.js +102 -0
- package/.next/standalone/node_modules/next/dist/telemetry/anonymous-meta.js +1 -1
- package/.next/standalone/node_modules/next/dist/telemetry/events/swc-load-failure.js +1 -1
- package/.next/standalone/node_modules/next/dist/telemetry/events/version.js +2 -2
- package/.next/standalone/node_modules/next/package.json +10 -10
- package/.next/standalone/node_modules/react/cjs/react.production.js +1 -1
- package/.next/standalone/node_modules/react/package.json +1 -1
- package/.next/standalone/node_modules/react-dom/cjs/react-dom-server-legacy.browser.production.js +1 -1
- package/.next/standalone/node_modules/react-dom/cjs/react-dom-server-legacy.node.production.js +1 -1
- package/.next/standalone/node_modules/react-dom/cjs/react-dom-server.browser.production.js +31 -27
- package/.next/standalone/node_modules/react-dom/cjs/react-dom-server.edge.production.js +33 -27
- package/.next/standalone/node_modules/react-dom/cjs/react-dom-server.node.production.js +38 -30
- package/.next/standalone/node_modules/react-dom/cjs/react-dom.production.js +1 -1
- package/.next/standalone/node_modules/react-dom/package.json +2 -2
- package/.next/standalone/package.json +10 -10
- package/.next/standalone/sdk/python/CHANGELOG.md +8 -4
- package/.next/standalone/sdk/python/failproofai_sdk/evaluator/source.py +2 -2
- package/.next/standalone/sdk/python/pyproject.toml +2 -7
- package/.next/standalone/sdk/python/skill/references/frameworks.md +0 -15
- package/.next/standalone/sdk/python/tests/test_docs.py +1 -4
- package/.next/standalone/sdk/python/tests/test_evaluator_source.py +1 -1
- package/.next/standalone/sdk/python/tests/test_packaging.py +4 -7
- package/.next/standalone/sdk/python/tests/test_zero_dependencies.py +2 -13
- package/.next/standalone/sdk/python/uv.lock +43 -905
- package/.next/standalone/sdk/typescript/CHANGELOG.md +52 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-5/package-lock.json +7 -7
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-5/package.json +2 -2
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-6/package-lock.json +7 -7
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-6/package.json +1 -1
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-7/package-lock.json +7 -7
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-7/package.json +1 -1
- package/.next/standalone/sdk/typescript/integration/fixtures/langchain-1/package-lock.json +4 -4
- package/.next/standalone/sdk/typescript/integration/fixtures/langchain-1/package.json +1 -1
- package/.next/standalone/sdk/typescript/integration/fixtures/langchain-dup-core/package-lock.json +4 -4
- package/.next/standalone/sdk/typescript/integration/fixtures/langchain-dup-core/package.json +1 -1
- package/.next/standalone/sdk/typescript/integration/fixtures/llamaindex-0.11/package-lock.json +3 -3
- package/.next/standalone/sdk/typescript/integration/fixtures/llamaindex-0.11/package.json +3 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/llamaindex-0.12/package-lock.json +4 -4
- package/.next/standalone/sdk/typescript/integration/fixtures/llamaindex-0.12/package.json +1 -1
- package/.next/standalone/sdk/typescript/integration/fixtures/mastra-0/package-lock.json +25 -25
- package/.next/standalone/sdk/typescript/integration/fixtures/mastra-0/package.json +1 -1
- package/.next/standalone/sdk/typescript/integration/fixtures/mastra-1/package-lock.json +34 -22
- package/.next/standalone/sdk/typescript/integration/fixtures/mastra-1/package.json +3 -2
- package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/package-lock.json +10 -10
- package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/package.json +1 -1
- package/.next/standalone/sdk/typescript/integration/fixtures/runtimes/deno-npm.ts +1 -1
- package/.next/standalone/sdk/typescript/integration/fixtures/runtimes/package-lock.json +7 -7
- package/.next/standalone/sdk/typescript/integration/fixtures/runtimes/package.json +1 -1
- package/.next/standalone/server.js +1 -1
- package/README.md +0 -6
- package/dist/cli.mjs +87 -38
- package/dist/worker.mjs +73 -28
- package/hermes-plugin/plugin.yaml +1 -1
- package/openclaw-plugin/daemon-client.js +254 -0
- package/openclaw-plugin/hooks.js +187 -0
- package/openclaw-plugin/index.js +17 -211
- package/package.json +10 -10
- package/scripts/sync-agent-cli-harnesses-prompt.md +26 -31
- package/src/hooks/agent-skill.ts +3 -0
- package/src/hooks/enforcement-capability.ts +1 -1
- package/src/hooks/fp-home.ts +1 -1
- package/src/hooks/handler.ts +22 -3
- package/src/hooks/integrations.ts +5 -2
- package/src/hooks/semantic/intent.ts +127 -24
- package/src/hooks/semantic/jev-review.ts +21 -2
- package/.next/standalone/.codex/hooks.json +0 -76
- package/.next/standalone/.cursor/hooks.json +0 -47
- package/.next/standalone/.factory/hooks.json +0 -112
- package/.next/standalone/.next/server/chunks/[externals]__1x24dzcbbq6-g._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0__a_je8fsn65._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0l-oi4gdtmlo5._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0t9ufnv5hi2hq._.js +0 -327
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1aaw59g-5uty7._.js +0 -322
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1hqpg6vgmfexv._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[externals]__0ilfh9mfnzsth._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[externals]__0ohnuzsaozaca._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0pwj2h2efe5f-._.js +0 -14
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_0zuikgt2xho-v._.js +0 -271
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_158jo-9mwvgad._.js +0 -291
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_19r82zsxo2jj1._.js +0 -291
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_1dupwucoqt5qm._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_shared_lib_03w27x2kh17_8._.js +0 -23
- package/.next/standalone/.next/static/chunks/1my3-5p47t7r-.js +0 -1
- package/.next/standalone/.next/static/chunks/21hckpmsc4g70.js +0 -6
- package/.next/standalone/.next/static/chunks/2hmex93ppj1ke.js +0 -1
- package/.next/standalone/.next/static/chunks/40oworn_-x12p.js +0 -1
- package/.next/standalone/.opencode/opencode.json +0 -4
- package/.next/standalone/.opencode/plugins/failproofai.mjs +0 -210
- package/.next/standalone/.pi/settings.json +0 -5
- package/.next/standalone/node_modules/react/cjs/react.development.js +0 -1330
- package/scripts/dev-hook.mjs +0 -333
- /package/.next/standalone/.next/static/{LHCtFxVG0mdvd4lsXAOFC → 1n2dyfTQb0MDajeqlipJy}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{LHCtFxVG0mdvd4lsXAOFC → 1n2dyfTQb0MDajeqlipJy}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{LHCtFxVG0mdvd4lsXAOFC → 1n2dyfTQb0MDajeqlipJy}/_ssgManifest.js +0 -0
|
@@ -56,8 +56,9 @@ The gate above scans the lockfiles it is *given* (the `--lockfile` list in the
|
|
|
56
56
|
workflow). GitHub's dependency graph reads **every** lockfile in the repository, so
|
|
57
57
|
Dependabot alerts cover trees the gate does not — in particular the TypeScript SDK's
|
|
58
58
|
integration fixtures, `sdk/typescript/integration/fixtures/*/package-lock.json`.
|
|
59
|
-
Those are not in the scanner's list and
|
|
60
|
-
[`.github/dependabot.yml`](.github/dependabot.yml)
|
|
59
|
+
Those are not in the scanner's list and get no Dependabot *version* updates either
|
|
60
|
+
(the four floor fixtures have entries in [`.github/dependabot.yml`](.github/dependabot.yml),
|
|
61
|
+
but only to restrain its security updates; see below), so an alert is the only
|
|
61
62
|
thing that will ever mention them. Treat the alert list as authoritative for those
|
|
62
63
|
paths, and see *Triaging a Dependabot alert in an integration fixture* below for how
|
|
63
64
|
to resolve one.
|
|
@@ -118,17 +119,32 @@ That splits an alert in one of these lockfiles into two cases:
|
|
|
118
119
|
the scanner does not read these lockfiles, so an `[[IgnoredVulns]]` entry for one
|
|
119
120
|
would filter nothing and be reported as an unused ignore.
|
|
120
121
|
|
|
122
|
+
Dependabot's own security updates know neither case. Given a case-2 advisory they
|
|
123
|
+
reach the fix by moving the framework, which is how #838, #931 and #935 happened
|
|
124
|
+
(#935 opened three minutes after #934 put the pins back). So each floor fixture —
|
|
125
|
+
`ai-4`, `langchain-0.3`, `llamaindex-0.11`, `mastra-0` — has a security-updates-only
|
|
126
|
+
entry in [`.github/dependabot.yml`](.github/dependabot.yml)
|
|
127
|
+
(`open-pull-requests-limit: 0`) whose `ignore` ranges hold its framework on its
|
|
128
|
+
line, and zod on 3 where that framework requires it; a fix that stays on the line
|
|
129
|
+
still arrives. A new floor fixture needs its own entry, and
|
|
130
|
+
`__tests__/ci/ts-sdk-fixture-pins.test.ts` fails without one. A Dependabot PR that
|
|
131
|
+
moves a pin anyway fails that same test: close it rather than merge it.
|
|
132
|
+
|
|
121
133
|
### Accepted, with no fix available
|
|
122
134
|
|
|
123
135
|
| Advisory | Package | Fixtures | Why it stays |
|
|
124
136
|
|---|---|---|---|
|
|
125
137
|
| [GHSA-rwvc-j5jr-mgvh](https://github.com/advisories/GHSA-rwvc-j5jr-mgvh) (low, CVSS 3.7) | `ai@4.3.19` | `ai-4`, `mastra-0` | A filetype-whitelist bypass on **file upload**. Fixed in `ai@5.0.52` — the major the `ai-4` fixture exists to stay below, and one `@mastra/core@0.24.9` cannot take either (it requires `ai@^4`). Neither fixture uploads a file or exposes an upload surface; each runs one scripted agent against an in-process model. |
|
|
126
138
|
| [GHSA-866g-f22w-33x8](https://github.com/advisories/GHSA-866g-f22w-33x8) (low, CVSS 4.3) | `@ai-sdk/provider-utils@2.2.8` | `ai-4`, `mastra-0` | Unbounded response-body reads in `createJsonResponseHandler` and its siblings. Fixed in `3.0.28`; `2.2.8` ships *inside* `ai@4.3.19`, which uses the v2 API, so the fix is the same blocked major as the row above. Exploiting it needs a hostile **model-provider HTTP response**; these fixtures never call one. |
|
|
139
|
+
| [GHSA-mrhx-c7xc-m3w5](https://github.com/advisories/GHSA-mrhx-c7xc-m3w5) (high, CVSS 7.5) | `zod@3.25.76` | `ai-4`, `langchain-0.3`, `llamaindex-0.11`; nested in `langchain-dup-core` and `mastra-0` | An array schema keeps every failing element's validation issues, uncapped, so one oversized input can exhaust memory. Fixed only in `4.6.6`: no zod 3 release carries the fix, and `3.25.76` is the newest. Each copy is held to `^3` by the release its fixture pins — `ai@4.3.19` and its `@ai-sdk/*` packages peer on `^3.23.8`, `@langchain/core@0.3.80` (in `langchain-dup-core`, the vendored provider's own copy) and `@langchain/langgraph@0.4.10` depend on `^3.25.32`, `@llamaindex/core@0.6.8` and `@llamaindex/workflow@1.1.5` need `^3.23.8`, and in `mastra-0`, `zod-from-json-schema-v3` (`zod-from-json-schema@0.0.5`, which builds zod 3 schemas for `@mastra/core` and `@mastra/mcp`) depends on `^3.24.2`. Exploiting it needs untrusted input validated against one of those schemas; each fixture validates only its own scripted tool arguments. |
|
|
127
140
|
|
|
128
|
-
|
|
141
|
+
Every row is bounded by the same facts: these are test fixtures — `"private": true`,
|
|
129
142
|
never published, installed with `--ignore-scripts`, and run only in CI against
|
|
130
143
|
scripted in-process models. Re-check them whenever the supported framework floor
|
|
131
|
-
moves
|
|
144
|
+
moves. The first two rows retire once `ai` 4.x has left the matrix, which takes
|
|
145
|
+
`mastra-0` as well as `ai-4`, because `@mastra/core@0.24.9` requires `ai@^4`. The
|
|
146
|
+
zod row retires only once `ai` 4.x, LangChain 0.3, LlamaIndex 0.11 and Mastra 0.x
|
|
147
|
+
have all left it.
|
|
132
148
|
|
|
133
149
|
## Maintainer setup (one-time)
|
|
134
150
|
|
|
@@ -1,9 +1,32 @@
|
|
|
1
1
|
# Changelog — `fp` CLI
|
|
2
2
|
|
|
3
|
-
## 0.0.
|
|
3
|
+
## 0.0.3b0 — 2026-10-25
|
|
4
|
+
|
|
5
|
+
Open for the next release. `0.0.2` published on 2026-10-25 and the `bump` job
|
|
6
|
+
moved the version here automatically; nothing has landed against `0.0.3b0` yet.
|
|
7
|
+
Add entries as changes merge — this section becomes the GitHub Release body when
|
|
8
|
+
it ships.
|
|
9
|
+
|
|
10
|
+
## 0.0.2 — 2026-10-25
|
|
11
|
+
|
|
12
|
+
**Stable release.** The `0.0.2b0` line the `bump` job opened after `0.0.1` is cut stable
|
|
13
|
+
here rather than published, because the server endpoints these commands drive are now
|
|
14
|
+
deployed to FailproofAI Cloud and the CLI should not trail them as a pre-release.
|
|
15
|
+
|
|
16
|
+
Nothing about the command surface changes at the cut: the entries below are the entire
|
|
17
|
+
diff from `0.0.1`, and the `bump` job opens `0.0.3b0` after the upload.
|
|
4
18
|
|
|
5
19
|
### Added
|
|
6
20
|
|
|
21
|
+
- Hosted evaluator authoring for code, LLM judge and Jev: create/deploy, AI draft specs, dry-run, labels, toggles, instances, schema, jobs and backfill.
|
|
22
|
+
- Dashboards and tiles; session overview/export/history/re-evaluate; latency and sentiment; query composition/export; alert recipients/issues and agent contracts.
|
|
23
|
+
- Policy author/backtest/candidacy, assistant artifact tables, fail-closed interactive write approvals, and agent-curated home briefs.
|
|
24
|
+
- Organization creation, permission-set roles, member deletion/defaults, usage windows, offers/trial, model context windows, OTEL and Slack controls.
|
|
25
|
+
- `fp policies backtest` covers every policy kind: a published `jev`/`both` policy, or `--semantic checks.json` (with or without a source file), runs the dashboard's every-kind backtest — a free estimate by default, `--run [--sample N]` to spend Jev allowance. New `--kind --semantic --hours --agent-id --env --run --sample`; a regex file or id still uses the module backtest.
|
|
26
|
+
- `fp policies author --kind regex|jev|both` asks the assistant for Jev checks or a hybrid policy.
|
|
27
|
+
- `fp issues list|count` take the inbox filters (`--agent-id --env --machine --source --audit-id --assignee --archived --search --since`, and `count --alert-id`); new `fp issues facets` lists the values they can take.
|
|
28
|
+
- `fp sessions import FILE...` imports Claude Code transcripts, Codex rollouts or event JSONL (`--format --env --dry-run`), as the dashboard's import dialog does.
|
|
29
|
+
- `fp list trigger_events`, `fp list eval_envs` and `fp list metric_keys`.
|
|
7
30
|
- `fp fleet deploy --target POLICY=INTEGRATION[/agt_ID]` scopes a machine's assignment; repeat the flag to include multiple alternatives. `--all-agents POLICY` explicitly clears its scope. Deploy plans, show, history, rollback and JSON readback retain assignment targets.
|
|
8
31
|
- `fp policies publish <id> --kind regex|jev|both [--source f.mjs] [--semantic f.json]`: a
|
|
9
32
|
FailproofAI Cloud policy can carry Jev checks — `jev` (declarations only, no JavaScript) or
|
|
@@ -41,6 +64,9 @@
|
|
|
41
64
|
|
|
42
65
|
### Changed
|
|
43
66
|
|
|
67
|
+
- New Cloud API families work in key mode; unsupported session-only commands deny before HTTP and unknown-route 404s exit 6 with an availability message.
|
|
68
|
+
- Shared screens use the mint/pink wordmark and grey labels, without boxes/rules or shortened ids; existing JSON contracts are unchanged.
|
|
69
|
+
- The agent skill, command reference, README and Cloud CLI docs include end-to-end evaluator workflows. No version bump or release is performed.
|
|
44
70
|
- `fp policies publish`'s refusal of Jev fields in the JavaScript now says where Jev checks go:
|
|
45
71
|
the policy's own declarations, `--kind both --semantic checks.json`.
|
|
46
72
|
- `fp guardrails summary` shows how many machines run Jev in each mode, reading the summary's
|
|
@@ -56,6 +82,13 @@
|
|
|
56
82
|
|
|
57
83
|
### Fixed
|
|
58
84
|
|
|
85
|
+
- Remove the unused colour-keyed permission rank, document full-id rendering, emit UTC `Z` timestamps for deploy backfills, and report approval-answer failures without a traceback while restoring the terminal (#885).
|
|
86
|
+
- Reject natural-language binary judge steps, distinguish unknown routes from missing records on 404, normalize standalone backfill ranges to UTC `Z`, expose all subcommands in help, and render artifact headers before titles with consistent session-only wording (#885).
|
|
87
|
+
- New Cloud commands use deliberate human summaries/tables and actionable empty states at 80/140 columns without raw response blobs. Evaluator previews display before writes and require explicit `--force` after failures; plan/claim deny key mode, deploy specs can omit the positional key, and older settings-route 404s degrade clearly. Existing JSON payloads stay unchanged (#885).
|
|
88
|
+
- `fp evaluators deploy` keeps the previous version's condition and labels unless `--condition`/`--label` change them, so a new version no longer silently widens to every session (#885).
|
|
89
|
+
- Evaluation backfill covers code, LLM judge and Jev evaluators, as FailproofAI Cloud now does: `fp evaluators deploy --backfill` no longer refuses judge/Jev, and both commands warn that judge/Jev backfills spend model budget instead of saying they are skipped.
|
|
90
|
+
- `fp usage windows` says it needs an API key (the dashboard has no session route for it) instead of reporting the route as unavailable.
|
|
91
|
+
- `fp issues close --help` no longer claims exit 9 for an issue that already ended: it is exit 1, as it always was, and it names `fp audits dismiss` rather than a command that does not exist.
|
|
59
92
|
- `fp fleet history` keeps `gen`, `when` and `jev` visible at 80 columns (rollback needs `gen`): the policy list is shortened, then dropped, and `change` wraps first.
|
|
60
93
|
- `fp fleet show` and `fp fleet history` name an exact-profile target by the profile label the machine reports (`claude/.claude-work`, with the `agt_…` id kept in `show`), falling back to the bare id.
|
|
61
94
|
|
|
@@ -211,6 +211,126 @@ These commands are **session-only** (`fp login`). They are absent from the
|
|
|
211
211
|
versioned API an API key authenticates against, so `--api-key` exits 2 with the
|
|
212
212
|
reason rather than failing at the request.
|
|
213
213
|
|
|
214
|
+
## Author an evaluator
|
|
215
|
+
|
|
216
|
+
`fp evaluators` authors hosted definitions; `fp evals` continues to read results.
|
|
217
|
+
Creation enables a definition by default. Check `fp evaluators instances` first:
|
|
218
|
+
Cloud needs an enabled managed instance. Writes need `evaluations:trigger`;
|
|
219
|
+
session dry-runs and `evaluators schema` also need `events:read`.
|
|
220
|
+
|
|
221
|
+
Write `error_free.py` as a restricted Python expression (no imports or functions):
|
|
222
|
+
|
|
223
|
+
```python
|
|
224
|
+
EvalResult(score=Score(1.0 if session.count("error") == 0 else 0.0), reasoning="Error-free session")
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
```bash
|
|
228
|
+
fp --json evaluators create --key error_free --name "Error free" --code error_free.py \
|
|
229
|
+
--result-kind score --dry-run-on run-001
|
|
230
|
+
fp --json evaluators dry-run --code error_free.py --session run-001
|
|
231
|
+
fp --json evaluators deploy error_free --code error_free.py --version 2 --dry-run-on run-001
|
|
232
|
+
fp --json evaluators list --key error_free --all
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
LLM judge (Cloud selects the model; judge dry-runs are refused):
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
fp --json evaluators create --key relevance --name Relevance --judge \
|
|
239
|
+
--criteria "Grade how directly the answer addresses the request" --threshold 0.7
|
|
240
|
+
fp --json evaluators deploy relevance --version 2 --judge \
|
|
241
|
+
--criteria "Grade relevance and completeness" --threshold 0.8
|
|
242
|
+
fp --json sessions re-evaluate run-001
|
|
243
|
+
fp --json sessions history run-001
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
Jev binary or graded rubric:
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
fp --json evaluators create --key resolved --name Resolved --jev noul \
|
|
250
|
+
--instructions "Was the request resolved?" --true "Resolved" --false "Unresolved"
|
|
251
|
+
fp --json evaluators dry-run --jev noul --instructions "Was the request resolved?" \
|
|
252
|
+
--true "Resolved" --false "Unresolved" --session run-001
|
|
253
|
+
fp --json evaluators deploy resolved --version 2 --jev score \
|
|
254
|
+
--instructions "Grade resolution quality" \
|
|
255
|
+
--level "Unresolved" --level "Partly resolved" --level "Fully resolved"
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
Jev dry-runs spend model budget. Rubrics need 3–5 distinct levels, worst first.
|
|
259
|
+
Thresholds are 0–1; judge/Jev always return a score. `deploy` creates the new
|
|
260
|
+
immutable version before disabling older enabled versions. If disabling fails,
|
|
261
|
+
the CLI names the published id; inspect `list --all` and recover explicitly.
|
|
262
|
+
`--backfill 7d` works for every kind (judge/Jev spend model budget); `evaluators backfill --from T --to T` accepts ≤90 days and `--dry-run` counts the work first.
|
|
263
|
+
|
|
264
|
+
Human output shows each `--dry-run-on` session's outcome before creation or
|
|
265
|
+
deployment. Any failed run stops the write; after reviewing the failure, an
|
|
266
|
+
explicit `--force` overrides this guard. Existing `--json` response shapes stay
|
|
267
|
+
unchanged.
|
|
268
|
+
|
|
269
|
+
AI drafting is session-only and writes an API spec that create/deploy accept:
|
|
270
|
+
|
|
271
|
+
```bash
|
|
272
|
+
fp login
|
|
273
|
+
fp --json evaluators draft "Measure error-free sessions with code" --kind code --out evaluator.json
|
|
274
|
+
# Review the spec, especially eval_key and evaluator_source, before enabling it.
|
|
275
|
+
fp --json evaluators create --file evaluator.json --dry-run-on run-001
|
|
276
|
+
fp --json evaluators dry-run --file evaluator.json
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
Spec fields: `eval_key`, `display_name`, `eval_version`, `result_kind`, `labels`,
|
|
280
|
+
`condition_source`, `evaluator_source`, `timeout_seconds`. Judge/Jev sources are
|
|
281
|
+
JSON envelope **strings**, not nested objects. `--file` is exclusive with discrete
|
|
282
|
+
spec flags; deploy may override a file's version. Files written by the CLI are
|
|
283
|
+
created exclusively, so existing files are never silently replaced.
|
|
284
|
+
See [the command reference](skill/references/commands.md#author-an-evaluator).
|
|
285
|
+
|
|
286
|
+
## Dashboard parity
|
|
287
|
+
|
|
288
|
+
```text
|
|
289
|
+
fp dashboards list|show|create|update|delete
|
|
290
|
+
fp dashboards tiles <id> list|add|update|remove|layout
|
|
291
|
+
fp sessions show|export|history|re-evaluate <id>
|
|
292
|
+
fp events latency
|
|
293
|
+
fp sentiment summary|messages|sessions|session <id>
|
|
294
|
+
fp query compose "question" [--run] # session
|
|
295
|
+
fp query export [<id>] [--sql SQL] --format csv|json [--out FILE]
|
|
296
|
+
fp alerts recipients
|
|
297
|
+
fp alerts issues <id> [--create --title ... --summary ...]
|
|
298
|
+
fp audits contracts list|show|create|update
|
|
299
|
+
fp policies author "intent"|backtest <file-or-id>|candidacy --issue <id> # session
|
|
300
|
+
fp agent brief [--range 24h|7d] # session
|
|
301
|
+
fp orgs create --name N [--slug S] # session
|
|
302
|
+
fp roles list|show|create|update|delete
|
|
303
|
+
fp users delete <id>
|
|
304
|
+
fp users defaults
|
|
305
|
+
fp usage windows
|
|
306
|
+
fp plan # session
|
|
307
|
+
fp plan claim <offer> # session
|
|
308
|
+
fp settings context-windows list|set <model> <tokens>|delete <model>
|
|
309
|
+
fp otel status|enable|disable
|
|
310
|
+
fp slack status|disconnect # session
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
`fp agent ask` runs artifact SQL through the permission-gated query runner and
|
|
314
|
+
renders tables/stats. It prompts before approving a write on a terminal.
|
|
315
|
+
Scripts and `--json` **decline** unless you explicitly pass `--approve`.
|
|
316
|
+
Normal create/update commands keep their existing non-interactive confirmation
|
|
317
|
+
behavior; assistant approvals are a separate safety boundary.
|
|
318
|
+
|
|
319
|
+
All new commands accept the global `--json` before the command. Session-only
|
|
320
|
+
commands fail before HTTP in API-key mode, with exit 2 and a `fp login` hint.
|
|
321
|
+
Unknown-route 404s exit 6 with “not available on this FailproofAI Cloud yet”.
|
|
322
|
+
Missing-record 404s also exit 6 but report that the record was not found.
|
|
323
|
+
`plan` and `plan claim` require a signed-in person and deny API-key mode before
|
|
324
|
+
HTTP with the standard `fp login` message.
|
|
325
|
+
Human screens use the mint/pink wordmark, grey labels, open tables and full ids;
|
|
326
|
+
existing JSON shapes are unchanged.
|
|
327
|
+
|
|
328
|
+
Human commands show summaries, tables and wrapped text rather than response
|
|
329
|
+
objects. Use global `--json` for raw API results. For `sessions export` or
|
|
330
|
+
`query export --format json`, use `--out FILE` to save the JSON; without either
|
|
331
|
+
option, the terminal shows a readable session or query view. CSV exports remain
|
|
332
|
+
plain CSV for piping.
|
|
333
|
+
|
|
214
334
|
## Configuration
|
|
215
335
|
|
|
216
336
|
| Setting | Flag | Env var | Default |
|
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.0.
|
|
1
|
+
__version__ = "0.0.3b0"
|
|
@@ -17,12 +17,15 @@ from . import orgs as orgsmod
|
|
|
17
17
|
from ._context import AppState
|
|
18
18
|
from ._version import __version__
|
|
19
19
|
from .commands import (
|
|
20
|
+
account_cmds,
|
|
20
21
|
agent_cmds,
|
|
21
22
|
alerts_cmds,
|
|
22
23
|
audits_cmds,
|
|
23
24
|
auth_cmds,
|
|
25
|
+
dashboards_cmds,
|
|
24
26
|
errors_cmds,
|
|
25
27
|
evals_cmds,
|
|
28
|
+
evaluators_cmds,
|
|
26
29
|
events_cmds,
|
|
27
30
|
fleet_cmds,
|
|
28
31
|
guardrails_cmds,
|
|
@@ -33,6 +36,7 @@ from .commands import (
|
|
|
33
36
|
policies_cmds,
|
|
34
37
|
queries_cmds,
|
|
35
38
|
sessions_cmds,
|
|
39
|
+
sentiment_cmds,
|
|
36
40
|
settings_cmds,
|
|
37
41
|
usage_cmds,
|
|
38
42
|
users_cmds,
|
|
@@ -128,6 +132,12 @@ app = typer.Typer(
|
|
|
128
132
|
# function Typer calls for this; falls back silently if its internals change.
|
|
129
133
|
try: # pragma: no cover - exercised via real command output, not unit assertions
|
|
130
134
|
import typer.rich_utils as _rich_utils
|
|
135
|
+
# Keep generated subcommand help on the same shared screen primitives.
|
|
136
|
+
_rich_utils.Panel = output.Panel
|
|
137
|
+
_rich_utils.Table = output.Table
|
|
138
|
+
_rich_utils.STYLE_OPTION = output.theme.PINK
|
|
139
|
+
_rich_utils.STYLE_COMMANDS_TABLE_FIRST_COLUMN = output.theme.PINK
|
|
140
|
+
_rich_utils.STYLE_OPTION_ENVVAR = output.theme.LABEL
|
|
131
141
|
|
|
132
142
|
import re as _re
|
|
133
143
|
|
|
@@ -327,7 +337,7 @@ def main(
|
|
|
327
337
|
"must be a positive number of seconds.", param_hint="--timeout"
|
|
328
338
|
)
|
|
329
339
|
cfg = cfgmod.load_config()
|
|
330
|
-
output.configure(no_color=no_color, quiet=quiet, json=json_output)
|
|
340
|
+
output.configure(no_color=no_color, quiet=quiet, json=json_output, context=ctx.invoked_subcommand or "Cloud")
|
|
331
341
|
# Resolve the credential BEFORE telemetry starts: the distinct-id depends on it.
|
|
332
342
|
# `get_parameter_source` is what separates a flag from its env var — the values
|
|
333
343
|
# alone cannot, and the precedence rules differ between the two (see resolve_auth).
|
|
@@ -452,6 +462,9 @@ orgs_cmds.register(app)
|
|
|
452
462
|
events_cmds.register(app)
|
|
453
463
|
sessions_cmds.register(app)
|
|
454
464
|
evals_cmds.register(app)
|
|
465
|
+
evaluators_cmds.register(app)
|
|
466
|
+
dashboards_cmds.register(app)
|
|
467
|
+
sentiment_cmds.register(app)
|
|
455
468
|
errors_cmds.register(app)
|
|
456
469
|
usage_cmds.register(app)
|
|
457
470
|
list_cmds.register(app)
|
|
@@ -466,6 +479,7 @@ agent_cmds.register(app)
|
|
|
466
479
|
policies_cmds.register(app)
|
|
467
480
|
fleet_cmds.register(app)
|
|
468
481
|
guardrails_cmds.register(app)
|
|
482
|
+
account_cmds.register(app)
|
|
469
483
|
|
|
470
484
|
|
|
471
485
|
def _elapsed_ms(start: float) -> int:
|
|
@@ -31,6 +31,7 @@ from .errors import (
|
|
|
31
31
|
ApiError,
|
|
32
32
|
AuthError,
|
|
33
33
|
ForbiddenError,
|
|
34
|
+
FpCliError,
|
|
34
35
|
KeyModeUnsupportedError,
|
|
35
36
|
NetworkError,
|
|
36
37
|
NotFoundError,
|
|
@@ -134,6 +135,14 @@ _V1_MECHANICAL_FAMILIES = frozenset(
|
|
|
134
135
|
"alerts",
|
|
135
136
|
"audits",
|
|
136
137
|
"evaluations",
|
|
138
|
+
"evaluator-definitions",
|
|
139
|
+
"evaluator-instances",
|
|
140
|
+
"evaluator-schema-profile",
|
|
141
|
+
"evaluation-jobs",
|
|
142
|
+
"dashboards",
|
|
143
|
+
"otel",
|
|
144
|
+
"offers",
|
|
145
|
+
"team-trial",
|
|
137
146
|
"events",
|
|
138
147
|
"issues",
|
|
139
148
|
"keys",
|
|
@@ -152,6 +161,7 @@ _V1_MECHANICAL_FAMILIES = frozenset(
|
|
|
152
161
|
# family rule, which is why this must stay exact-match.
|
|
153
162
|
_V1_RENAMED = {
|
|
154
163
|
"/api/evaluations/score-keys": "/v1/evaluations/score_keys",
|
|
164
|
+
"/api/evaluations/metric-keys": "/v1/evaluations/metric_keys",
|
|
155
165
|
}
|
|
156
166
|
|
|
157
167
|
# Families with no `/v1` route, and why — the message a user actually sees.
|
|
@@ -173,6 +183,8 @@ _V1_NO_EQUIVALENT = {
|
|
|
173
183
|
"cloud-managed policies are an operator surface — the fleet routes are "
|
|
174
184
|
"deliberately absent from /v1, which is internet-facing"
|
|
175
185
|
),
|
|
186
|
+
"integrations": "dashboard integration routes need a signed-in session",
|
|
187
|
+
"orgs": "organization creation needs a signed-in user",
|
|
176
188
|
}
|
|
177
189
|
|
|
178
190
|
|
|
@@ -375,6 +387,40 @@ def _required_permission(response: httpx.Response) -> Optional[str]:
|
|
|
375
387
|
return None
|
|
376
388
|
|
|
377
389
|
|
|
390
|
+
def _unknown_route_response(response: httpx.Response) -> Optional[bool]:
|
|
391
|
+
"""Use explicit 404 details first; an empty/generic reply is ambiguous."""
|
|
392
|
+
try:
|
|
393
|
+
data = response.json()
|
|
394
|
+
except ValueError:
|
|
395
|
+
return None
|
|
396
|
+
if not isinstance(data, dict):
|
|
397
|
+
return None
|
|
398
|
+
code = data.get("code") or data.get("error_code") or data.get("error") or ""
|
|
399
|
+
if isinstance(code, dict):
|
|
400
|
+
code = code.get("code", "")
|
|
401
|
+
code = str(code).lower()
|
|
402
|
+
if code in ("unknown_route", "route_not_found", "unknown_endpoint", "endpoint_not_found"):
|
|
403
|
+
return True
|
|
404
|
+
if code in ("record_not_found", "resource_not_found", "entity_not_found", "session_not_found", "query_not_found"):
|
|
405
|
+
return False
|
|
406
|
+
message = _extract_error(response)
|
|
407
|
+
if not message:
|
|
408
|
+
return None
|
|
409
|
+
lower = message.lower().strip().rstrip(".")
|
|
410
|
+
if re.search(
|
|
411
|
+
r"\b(?:unknown|unrecognized|unsupported|missing|no such)\s+(?:api\s+)?(?:route|endpoint)\b"
|
|
412
|
+
r"|\b(?:route|endpoint)\b.*\b(?:not found|not available|does not exist|absent|unknown)\b"
|
|
413
|
+
r"|\bcannot (?:get|post|put|patch|delete)\s+/",
|
|
414
|
+
lower,
|
|
415
|
+
):
|
|
416
|
+
return True
|
|
417
|
+
if lower in ("not found", "not_found", "404", "404 not found"):
|
|
418
|
+
return None
|
|
419
|
+
# A specific response ("session not found", "offer expired", etc.) came
|
|
420
|
+
# from a handler, rather than the router. Do not replace its useful detail.
|
|
421
|
+
return False
|
|
422
|
+
|
|
423
|
+
|
|
378
424
|
def _raise_for_status(response: httpx.Response, ctx: ClientContext) -> None:
|
|
379
425
|
key_mode = ctx.auth_mode is AuthMode.API_KEY
|
|
380
426
|
if response.status_code < 400:
|
|
@@ -474,7 +520,9 @@ def _raise_for_status(response: httpx.Response, ctx: ClientContext) -> None:
|
|
|
474
520
|
request_id=request_id,
|
|
475
521
|
hint="point --base-url at the server itself, e.g. http://localhost:8080",
|
|
476
522
|
)
|
|
477
|
-
|
|
523
|
+
error = NotFoundError(message or "Not found.", request_id=request_id)
|
|
524
|
+
error.route_unknown = _unknown_route_response(response)
|
|
525
|
+
raise error
|
|
478
526
|
if response.status_code == 429:
|
|
479
527
|
retry_after = response.headers.get("retry-after")
|
|
480
528
|
wait = f" Retry after {retry_after}s." if retry_after else " Please wait a moment and try again."
|
|
@@ -606,6 +654,121 @@ def _delete(ctx: ClientContext, path: str) -> Any:
|
|
|
606
654
|
return _request_json(ctx, "DELETE", path)
|
|
607
655
|
|
|
608
656
|
|
|
657
|
+
def cloud_request(
|
|
658
|
+
ctx: ClientContext, method: str, path: str, *,
|
|
659
|
+
body: Any = None, params: Optional[Dict[str, Any]] = None,
|
|
660
|
+
) -> Any:
|
|
661
|
+
"""New Cloud capabilities, with a predictable older-deployment failure.
|
|
662
|
+
|
|
663
|
+
Existing callers retain their response and error contracts. Paths still pass
|
|
664
|
+
through the credential and identifier guards; this is not a second transport.
|
|
665
|
+
"""
|
|
666
|
+
try:
|
|
667
|
+
if method == "GET":
|
|
668
|
+
return _get_json(ctx, path, params)
|
|
669
|
+
return _request_json(ctx, method, path, json_body=body, params=params)
|
|
670
|
+
except (NotFoundError, ApiError) as exc:
|
|
671
|
+
if isinstance(exc, ApiError) and exc.status != 404:
|
|
672
|
+
raise
|
|
673
|
+
raise _cloud_not_found(exc, path, body=body, params=params) from exc
|
|
674
|
+
|
|
675
|
+
|
|
676
|
+
def _cloud_not_found(exc: FpCliError, path: str, *, body=None, params=None) -> NotFoundError:
|
|
677
|
+
"""Classify ambiguous 404s from the request; never claim a record is a route.
|
|
678
|
+
|
|
679
|
+
Top-level collections and named capability endpoints have no record segment.
|
|
680
|
+
Scoped collections (/dashboards/ID/tiles) and actions on records default to a
|
|
681
|
+
missing record unless the response explicitly says the route is unknown.
|
|
682
|
+
"""
|
|
683
|
+
route_unknown = getattr(exc, "route_unknown", None)
|
|
684
|
+
if isinstance(exc, ApiError):
|
|
685
|
+
# The transport only raises HTTP 404 ApiError for an HTML front door.
|
|
686
|
+
route_unknown = True
|
|
687
|
+
if route_unknown is None:
|
|
688
|
+
segments = path.removeprefix("/api/").split("/")
|
|
689
|
+
family = segments[0]
|
|
690
|
+
capability = len(segments) == 1 or (
|
|
691
|
+
family == "agent" and len(segments) == 2
|
|
692
|
+
or family == "otel" and segments == ["otel", "status"]
|
|
693
|
+
or family == "offers" and segments[1:] in (["me"], ["claim"])
|
|
694
|
+
or family == "team-trial" and segments == ["team-trial", "me"]
|
|
695
|
+
or family == "integrations" and segments == ["integrations", "slack"]
|
|
696
|
+
or family == "events" and segments in (
|
|
697
|
+
["events", "summary"], ["events", "latency_aggregate"],
|
|
698
|
+
["events", "sentiment"], ["events", "sentiment", "messages"],
|
|
699
|
+
["events", "sentiment", "sessions"],
|
|
700
|
+
)
|
|
701
|
+
or family == "evaluator-definitions" and segments == ["evaluator-definitions", "dry-run"]
|
|
702
|
+
or family == "evaluations" and segments == ["evaluations", "backfill"]
|
|
703
|
+
or family == "queries" and segments[1:] in (["run"], ["schema"])
|
|
704
|
+
or family == "audits" and segments == ["audits", "contracts"]
|
|
705
|
+
or family == "alerts" and segments == ["alerts", "recipients"]
|
|
706
|
+
or family == "users" and segments == ["users", "defaults"]
|
|
707
|
+
or family == "usage" and segments == ["usage", "windows"]
|
|
708
|
+
or family == "settings" and segments == ["settings", "model-context-windows"]
|
|
709
|
+
or family == "settings" and len(segments) == 2
|
|
710
|
+
)
|
|
711
|
+
# Some collection operations name their target in a query or body.
|
|
712
|
+
request_body = body if isinstance(body, dict) else {}
|
|
713
|
+
record_selected = (
|
|
714
|
+
(params or {}).get("session_id") or (params or {}).get("model")
|
|
715
|
+
or request_body.get("query_id") or request_body.get("callId")
|
|
716
|
+
or request_body.get("session_ids") or request_body.get("offer_key")
|
|
717
|
+
or request_body.get("conversationId")
|
|
718
|
+
)
|
|
719
|
+
route_unknown = capability and not record_selected
|
|
720
|
+
if route_unknown:
|
|
721
|
+
return NotFoundError(
|
|
722
|
+
"not available on this FailproofAI Cloud yet",
|
|
723
|
+
hint="upgrade your Cloud deployment to use this route",
|
|
724
|
+
request_id=exc.request_id,
|
|
725
|
+
)
|
|
726
|
+
message = exc.message
|
|
727
|
+
if message.lower().strip().rstrip(".") in (
|
|
728
|
+
"not found", "not_found", "record_not_found", "resource_not_found",
|
|
729
|
+
"entity_not_found", "session_not_found", "query_not_found",
|
|
730
|
+
):
|
|
731
|
+
message = f"Record not found at {path}"
|
|
732
|
+
return NotFoundError(message, request_id=exc.request_id)
|
|
733
|
+
|
|
734
|
+
|
|
735
|
+
def import_events_file(
|
|
736
|
+
ctx: ClientContext, data: bytes, params: Dict[str, Any],
|
|
737
|
+
) -> Any:
|
|
738
|
+
"""POST /api/events/import — one file's bytes (gzip accepted), as the dashboard's
|
|
739
|
+
import dialog sends it. ``params``: format, path, environment, dry_run, existing_before."""
|
|
740
|
+
clean = {k: v for k, v in params.items() if v is not None} or None
|
|
741
|
+
url = _path(ctx, "/api/events/import")
|
|
742
|
+
try:
|
|
743
|
+
with _client(ctx) as client:
|
|
744
|
+
response = client.request(
|
|
745
|
+
"POST", url, content=data, params=clean,
|
|
746
|
+
headers={"Content-Type": "application/octet-stream"},
|
|
747
|
+
)
|
|
748
|
+
except httpx.RequestError as exc:
|
|
749
|
+
raise NetworkError(
|
|
750
|
+
f"Cannot reach FailproofAI Cloud at {ctx.base_url}: {exc}",
|
|
751
|
+
request_id=_sent_request_id(exc),
|
|
752
|
+
)
|
|
753
|
+
_raise_for_status(response, ctx)
|
|
754
|
+
if not response.content:
|
|
755
|
+
return {}
|
|
756
|
+
try:
|
|
757
|
+
return response.json()
|
|
758
|
+
except ValueError:
|
|
759
|
+
raise ApiError("The dashboard returned an invalid import response.")
|
|
760
|
+
|
|
761
|
+
|
|
762
|
+
def cloud_stream(ctx: ClientContext, path: str, body: Dict[str, Any]) -> Iterator[Dict[str, Any]]:
|
|
763
|
+
"""Dashboard SSE with the same additive-capability 404 contract."""
|
|
764
|
+
try:
|
|
765
|
+
yield from _stream_sse(ctx, path, body)
|
|
766
|
+
except (NotFoundError, ApiError) as exc:
|
|
767
|
+
if isinstance(exc, ApiError) and exc.status != 404:
|
|
768
|
+
raise
|
|
769
|
+
raise _cloud_not_found(exc, path, body=body) from exc
|
|
770
|
+
|
|
771
|
+
|
|
609
772
|
# --- Auth / identity --------------------------------------------------------
|
|
610
773
|
|
|
611
774
|
|
|
@@ -793,6 +956,10 @@ _FACET_PATHS = {
|
|
|
793
956
|
# Evaluation score keys (a distinct endpoint, not /api/events) — the source for
|
|
794
957
|
# the sessions-page score-filter dropdown; needs `evaluations:read`.
|
|
795
958
|
"score_filters": "/api/evaluations/score-keys",
|
|
959
|
+
# Evaluation-side facets: environments with evaluation results, and metric
|
|
960
|
+
# keys (the server returns {name, unit, count}; `list` shows the names).
|
|
961
|
+
"eval_environments": "/api/evaluations/environments",
|
|
962
|
+
"metric_keys": "/api/evaluations/metric-keys",
|
|
796
963
|
}
|
|
797
964
|
FACET_KINDS = tuple(_FACET_PATHS.keys())
|
|
798
965
|
|
|
@@ -800,7 +967,9 @@ FACET_KINDS = tuple(_FACET_PATHS.keys())
|
|
|
800
967
|
def list_facet(ctx: ClientContext, kind: str) -> List[str]:
|
|
801
968
|
"""GET /api/events/<kind> — distinct facet values (a bare JSON array)."""
|
|
802
969
|
data = _get_json(ctx, _FACET_PATHS[kind])
|
|
803
|
-
|
|
970
|
+
if not isinstance(data, list):
|
|
971
|
+
return []
|
|
972
|
+
return [str(x.get("name", "")) if isinstance(x, dict) else str(x) for x in data]
|
|
804
973
|
|
|
805
974
|
|
|
806
975
|
def get_usage(ctx: ClientContext) -> Dict[str, Any]:
|
|
@@ -1195,20 +1364,28 @@ def list_incidents(
|
|
|
1195
1364
|
state: Optional[str] = None,
|
|
1196
1365
|
alert_id: Optional[str] = None,
|
|
1197
1366
|
limit: Optional[int] = None,
|
|
1367
|
+
filters: Optional[Dict[str, Any]] = None,
|
|
1198
1368
|
) -> List[Incident]:
|
|
1199
1369
|
"""GET /api/issues (or /api/alerts/{id}/issues when alert_id given). The
|
|
1200
1370
|
alert-scoped path honours ``state``/``limit`` too — pass them so the filters aren't silently
|
|
1201
1371
|
dropped on that path (``_get_json`` omits None params)."""
|
|
1202
|
-
if
|
|
1372
|
+
extra = {k: v for k, v in (filters or {}).items() if v is not None}
|
|
1373
|
+
if alert_id and not extra:
|
|
1203
1374
|
data = _get_json(ctx, f"/api/alerts/{alert_id}/issues", {"state": state, "limit": limit})
|
|
1375
|
+
elif alert_id:
|
|
1376
|
+
# The board's own filters live on /issues, which takes alert_id as one of them.
|
|
1377
|
+
data = _get_json(ctx, "/api/issues", {"state": state, "limit": limit, "alert_id": alert_id, **extra})
|
|
1204
1378
|
else:
|
|
1205
|
-
data = _get_json(ctx, "/api/issues", {"state": state, "limit": limit})
|
|
1379
|
+
data = _get_json(ctx, "/api/issues", {"state": state, "limit": limit, **extra})
|
|
1206
1380
|
return [Incident.from_dict(i) for i in (data if isinstance(data, list) else [])]
|
|
1207
1381
|
|
|
1208
1382
|
|
|
1209
|
-
def count_incidents(
|
|
1383
|
+
def count_incidents(
|
|
1384
|
+
ctx: ClientContext, *, state: Optional[str] = None, filters: Optional[Dict[str, Any]] = None,
|
|
1385
|
+
) -> int:
|
|
1210
1386
|
"""GET /api/issues/count — {count}."""
|
|
1211
|
-
|
|
1387
|
+
extra = {k: v for k, v in (filters or {}).items() if v is not None}
|
|
1388
|
+
data = _get_json(ctx, "/api/issues/count", {"state": state, **extra})
|
|
1212
1389
|
if not isinstance(data, dict):
|
|
1213
1390
|
return 0
|
|
1214
1391
|
try:
|
|
@@ -1532,6 +1709,8 @@ def agent_chat_oneshot(
|
|
|
1532
1709
|
conversation_id: Optional[str] = None,
|
|
1533
1710
|
page_context: Optional[str] = None,
|
|
1534
1711
|
model: Optional[str] = None,
|
|
1712
|
+
on_ask_user: Optional[Callable[[Dict[str, Any]], None]] = None,
|
|
1713
|
+
on_artifact: Optional[Callable[[Dict[str, Any]], None]] = None,
|
|
1535
1714
|
) -> Dict[str, Any]:
|
|
1536
1715
|
"""POST /api/agent/chat — accumulate the streamed answer.
|
|
1537
1716
|
|
|
@@ -1551,20 +1730,32 @@ def agent_chat_oneshot(
|
|
|
1551
1730
|
body["pageContext"] = page_context
|
|
1552
1731
|
if model:
|
|
1553
1732
|
body["model"] = model
|
|
1733
|
+
if on_artifact:
|
|
1734
|
+
body["pageActions"] = [{"action": "open_artifact"}, {"action": "home"}]
|
|
1554
1735
|
parts: List[str] = []
|
|
1555
1736
|
tools: List[str] = []
|
|
1556
1737
|
interrupted = False
|
|
1557
1738
|
error: Optional[str] = None
|
|
1558
|
-
for ev in
|
|
1739
|
+
for ev in cloud_stream(ctx, "/api/agent/chat", body):
|
|
1559
1740
|
kind = ev.get("type")
|
|
1560
1741
|
if kind == "text-delta":
|
|
1561
1742
|
parts.append(str(ev.get("text", "")))
|
|
1562
1743
|
elif kind == "tool-start":
|
|
1563
1744
|
tools.append(str(ev.get("tool", "")))
|
|
1564
1745
|
elif kind == "ask-user":
|
|
1746
|
+
if on_ask_user and ev.get("callId"):
|
|
1747
|
+
on_ask_user(ev)
|
|
1748
|
+
continue
|
|
1565
1749
|
interrupted = True
|
|
1566
1750
|
error = str(ev.get("question") or "the assistant needs interactive input")
|
|
1567
1751
|
break
|
|
1752
|
+
elif kind == "ui-action" and on_artifact:
|
|
1753
|
+
if ev.get("action") == "open_artifact" and isinstance(ev.get("artifact"), dict):
|
|
1754
|
+
on_artifact(ev["artifact"])
|
|
1755
|
+
elif ev.get("action") == "home" and isinstance(ev.get("home"), dict):
|
|
1756
|
+
for block in ev["home"].get("blocks", []):
|
|
1757
|
+
if isinstance(block, dict):
|
|
1758
|
+
on_artifact(block)
|
|
1568
1759
|
elif kind == "error":
|
|
1569
1760
|
error = str(ev.get("message", "assistant error"))
|
|
1570
1761
|
elif kind == "done":
|