failproofai 1.0.10 → 1.0.11-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 +6 -6
- package/.next/standalone/.next/prerender-manifest.json +4 -4
- package/.next/standalone/.next/required-server-files.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page/build-manifest.json +3 -3
- 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 +4 -4
- 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.meta +8 -0
- 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/build-manifest.json +3 -3
- 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 -4
- 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.meta +8 -0
- package/.next/standalone/.next/server/app/_not-found.rsc +14 -14
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +14 -14
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +13 -13
- 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 +4 -4
- 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 +4 -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 +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 -4
- 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 +3 -3
- 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 +3 -3
- 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 +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/build-manifest.json +3 -3
- package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
- package/.next/standalone/.next/server/app/audit/page.js +4 -4
- 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.meta +8 -0
- package/.next/standalone/.next/server/app/index.rsc +14 -14
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +13 -13
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +14 -14
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/page/build-manifest.json +3 -3
- package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/page.js +4 -4
- 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 +3 -3
- package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +14 -14
- package/.next/standalone/.next/server/app/policies/page.js +8 -8
- 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 +3 -3
- 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 +5 -5
- 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 +3 -3
- 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 +5 -5
- 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 +3 -3
- package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/projects/page.js +5 -5
- 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 +3 -3
- package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +8 -8
- package/.next/standalone/.next/server/app/settings/page.js +9 -9
- 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]__0qxhecv._.js → [externals]__0d7i9ea._.js} +2 -2
- package/.next/standalone/.next/server/chunks/{[externals]__0sg9-3p._.js → [externals]__0hjaw70._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[externals]__1_9ze9b._.js +3 -0
- package/.next/standalone/.next/server/chunks/[externals]__1oenfmn._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__08dchfu._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ga9hs7._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0l3yhx4._.js +2 -2
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0moxohc._.js +22 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0o07qi9._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0z2ll-a._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1adacul._.js +11 -11
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1autwno._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1v25n-6._.js +3 -0
- package/.next/standalone/.next/server/chunks/_09dz7xv._.js +1 -1
- package/.next/standalone/.next/server/chunks/_0tovk6q._.js +1 -1
- package/.next/standalone/.next/server/chunks/_0trp3yc._.js +1 -1
- package/.next/standalone/.next/server/chunks/_1ek68ln._.js +2 -2
- package/.next/standalone/.next/server/chunks/_1fz8m31._.js +1 -1
- package/.next/standalone/.next/server/chunks/_1jrv3hg._.js +3 -0
- package/.next/standalone/.next/server/chunks/_1nx8fim._.js +3 -0
- package/.next/standalone/.next/server/chunks/_1ogwigf._.js +1 -1
- package/.next/standalone/.next/server/chunks/{_1q5i8mb._.js → _1q27azx._.js} +2 -2
- package/.next/standalone/.next/server/chunks/lib_telemetry_ts_0dctyyw._.js +1 -1
- package/.next/standalone/.next/server/chunks/{node_modules_posthog-node_dist_entrypoints_index_node_mjs_0el6rg8._.js → node_modules_posthog-node_dist_entrypoints_index_node_mjs_0ol5pa3._.js} +2 -2
- package/.next/standalone/.next/server/chunks/{node_modules_posthog-node_dist_entrypoints_index_node_mjs_04op_ou._.js → node_modules_posthog-node_dist_entrypoints_index_node_mjs_1rqmk27._.js} +2 -2
- package/.next/standalone/.next/server/chunks/{node_modules_posthog-node_dist_entrypoints_index_node_mjs_0dr20uz._.js → node_modules_posthog-node_dist_entrypoints_index_node_mjs_1w7tiq4._.js} +2 -2
- package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0oqrl71._.js → [root-of-the-server]__042u-jn._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__04usis8._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1-bm5zf._.js → [root-of-the-server]__0502lat._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0_gn5iz._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0f765xr._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__01bmjsj._.js → [root-of-the-server]__0h38gzz._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0hoaz1g._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1ouobn4._.js → [root-of-the-server]__0mxmwtx._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__19evfi8._.js → [root-of-the-server]__0uescqv._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__13d-wb6._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1484zv2._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1mf3zp6._.js → [root-of-the-server]__19dutr7._.js} +4 -4
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1u6sn69._.js → [root-of-the-server]__1ab4ifb._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1fbrk56._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1pprgri._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1um4yxn._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1wb4yt2._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1y3n3cn._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/_08x1r5t._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_0bqoto4._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{_0yq5_3a._.js → _1ffxwxz._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_1gb0ifp._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{_042cgl1._.js → _1o95rf0._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{_1zopuov._.js → _1thr5rf._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{_16pa9ht._.js → _1v1o2ya._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_policies_page_actions_1sp2-yo.js +12 -14
- package/.next/standalone/.next/server/chunks/ssr/app_actions_get-scheduled-audit_ts_0ei9sni._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +1 -1
- 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 +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_settings_02tf1h4._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_1hl81y4._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_0nkkbfv._.js +6 -0
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_fp-config_ts_04t589g._.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 +6 -6
- 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 +23 -23
- package/.next/standalone/.next/static/chunks/08tmc_7n-rba1.js +1 -0
- package/.next/standalone/.next/static/chunks/{3mjfvng11xnoo.js → 09tlrmucn6oq3.js} +1 -1
- package/.next/standalone/.next/static/chunks/{078dofaxvjgpd.js → 0i69k917myh7b.js} +1 -1
- package/.next/standalone/.next/static/chunks/{03h3b-uomi7_d.js → 0u_nhsujkactp.js} +1 -1
- package/.next/standalone/.next/static/chunks/{2j92xul6y24_v.js → 0zp51hzx62i-u.js} +1 -1
- package/.next/standalone/.next/static/chunks/{3u1s8dsqiean5.js → 1fz7q0gtnmeod.js} +1 -1
- package/.next/standalone/.next/static/chunks/{3ob2161ap37ul.js → 1j75le8wln-26.js} +1 -1
- package/.next/standalone/.next/static/chunks/{2kj826h1w9r47.js → 1z4km7tw0_50h.js} +1 -1
- package/.next/standalone/.next/static/chunks/{1fqukzzowjflt.js → 239ay_80-xr8z.js} +1 -1
- package/.next/standalone/.next/static/chunks/{3nkc2jlgyygda.js → 2c9pc5xco6rnu.js} +1 -1
- package/.next/standalone/.next/static/chunks/{3i8rg2fv9nd6e.js → 3n46e45atic-m.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0542cuk_va8g1.js → 3sg07wnn969xq.js} +1 -1
- package/.next/standalone/.next/static/chunks/{turbopack-11dn2pegmg9_9.js → turbopack-1opxka4dtjbc5.js} +1 -1
- package/.next/standalone/app/actions/install-hooks-web.ts +10 -2
- 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/hash.js/sha256/256.js +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/hash.js/sha256/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/next-server/app-page-turbo-experimental.runtime.prod.js +17 -17
- package/.next/standalone/node_modules/next/dist/compiled/next-server/app-page-turbo.runtime.prod.js +18 -18
- 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/base-server.js +1 -2
- 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/image-optimizer.js +265 -53
- package/.next/standalone/node_modules/next/dist/server/lib/app-info-log.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/lib/incremental-cache/file-system-cache.js +177 -19
- package/.next/standalone/node_modules/next/dist/server/lib/incremental-cache/index.js +36 -17
- package/.next/standalone/node_modules/next/dist/server/lib/incremental-cache/shared-cache-controls.external.js +14 -6
- package/.next/standalone/node_modules/next/dist/server/lib/match-next-data-pathname.js +3 -1
- package/.next/standalone/node_modules/next/dist/server/lib/node-fs-methods.js +14 -0
- package/.next/standalone/node_modules/next/dist/server/lib/route-cache-key.js +77 -0
- package/.next/standalone/node_modules/next/dist/server/lib/router-utils/block-cross-site-dev.js +9 -11
- package/.next/standalone/node_modules/next/dist/server/lib/start-server.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/mcp/get-mcp-middleware.js +4 -2
- package/.next/standalone/node_modules/next/dist/server/next-server.js +7 -3
- package/.next/standalone/node_modules/next/dist/server/response-cache/index.js +32 -16
- package/.next/standalone/node_modules/next/dist/server/route-matcher-providers/app-page-route-matcher-provider.js +2 -2
- package/.next/standalone/node_modules/next/dist/server/route-modules/pages/pages-handler.js +6 -1
- package/.next/standalone/node_modules/next/dist/server/route-modules/route-module.js +9 -2
- package/.next/standalone/node_modules/next/dist/server/use-cache/use-cache-wrapper.js +30 -29
- package/.next/standalone/node_modules/next/dist/shared/lib/router/utils/app-paths.js +18 -1
- 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/package.json +14 -11
- package/.next/standalone/sdk/python/README.md +41 -0
- package/.next/standalone/sdk/python/docs/README.md +1 -0
- package/.next/standalone/sdk/python/docs/otel/README.md +36 -0
- package/.next/standalone/sdk/python/docs/otel/examples/agent_trace.py +30 -0
- package/.next/standalone/sdk/python/docs/otel/examples/quickstart.py +22 -0
- package/.next/standalone/sdk/python/failproofai_sdk/__init__.py +8 -0
- package/.next/standalone/sdk/python/failproofai_sdk/integrations/__init__.py +3 -0
- package/.next/standalone/sdk/python/failproofai_sdk/integrations/otel.py +189 -0
- package/.next/standalone/sdk/python/pyproject.toml +2 -1
- package/.next/standalone/sdk/python/tests/test_docs.py +16 -3
- package/.next/standalone/sdk/python/tests/test_integrations.py +1 -1
- package/.next/standalone/sdk/python/tests/test_otel.py +147 -0
- package/.next/standalone/sdk/python/tests/test_zero_dependencies.py +4 -1
- package/.next/standalone/sdk/python/uv.lock +258 -147
- package/.next/standalone/sdk/typescript/README.md +43 -0
- package/.next/standalone/sdk/typescript/integration/ai.test.ts +9 -2
- package/.next/standalone/sdk/typescript/package-lock.json +57 -5
- package/.next/standalone/sdk/typescript/package.json +2 -0
- package/.next/standalone/sdk/typescript/src/edge/index.ts +9 -0
- package/.next/standalone/sdk/typescript/src/index.ts +2 -0
- package/.next/standalone/sdk/typescript/src/integrations/index.ts +4 -1
- package/.next/standalone/sdk/typescript/src/integrations/otel.ts +204 -0
- package/.next/standalone/sdk/typescript/test/integrations.test.ts +1 -1
- package/.next/standalone/sdk/typescript/test/otel.test.ts +125 -0
- package/.next/standalone/server.js +1 -1
- package/bin/failproofai.mjs +653 -1077
- package/dist/cli.mjs +8174 -3930
- package/dist/worker.mjs +170 -62
- package/hermes-plugin/plugin.yaml +1 -1
- package/package.json +14 -11
- package/scripts/launch-facts.ts +157 -0
- package/scripts/launch-ready.ts +228 -0
- package/scripts/launch-screen.ts +202 -0
- package/scripts/launch.ts +106 -49
- package/scripts/skew-log-filter.ts +42 -0
- package/src/audit/cli-login.ts +39 -59
- package/src/audit/cli.ts +308 -228
- package/src/audit/index.ts +45 -2
- package/src/audit/schedule-cli.ts +83 -120
- package/src/audit/types.ts +31 -0
- package/src/hooks/agent-selection.ts +155 -0
- package/src/hooks/backfill-cli.ts +151 -137
- package/src/hooks/backfill-request.ts +149 -0
- package/src/hooks/cloud-connection.ts +1 -1
- package/src/hooks/cloud-enrollment-cli.ts +78 -28
- package/src/hooks/cloud-introspect.ts +3 -0
- package/src/hooks/collector-config.ts +10 -1
- package/src/hooks/config-status.ts +606 -0
- package/src/hooks/configure-wizard.ts +915 -989
- package/src/hooks/daemon-service.ts +16 -6
- package/src/hooks/did-you-mean.ts +185 -0
- package/src/hooks/flush-cli.ts +33 -7
- package/src/hooks/fp-config.ts +96 -0
- package/src/hooks/fp-home.ts +11 -0
- package/src/hooks/fp-reset.ts +102 -95
- package/src/hooks/handler.ts +4 -0
- package/src/hooks/harness-cli.ts +87 -138
- package/src/hooks/install-prompt.ts +38 -477
- package/src/hooks/integrations.ts +1 -1
- package/src/hooks/jev-cli.ts +183 -196
- package/src/hooks/manager.ts +554 -358
- package/src/hooks/onboarding-attempt.ts +11 -9
- package/src/hooks/otel-cli.ts +344 -0
- package/src/hooks/otel-output.ts +24 -0
- package/src/hooks/otel-writers.ts +225 -0
- package/src/hooks/pack-cli.ts +219 -204
- package/src/hooks/report-body.ts +50 -0
- package/src/hooks/safe-config-write.ts +4 -2
- package/src/hooks/session-pause-cli.ts +93 -73
- package/src/hooks/tui.ts +849 -389
- package/src/hooks/uninstall-cli.ts +136 -149
- package/src/hooks/untraced-note.ts +52 -0
- package/.next/standalone/.next/server/chunks/[externals]__19_pzeq._.js +0 -3
- package/.next/standalone/.next/server/chunks/[externals]__20kzpkf._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__01eqny5._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__05ja_05._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0igxt32._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0zyc_nm._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1ttrwnd._.js +0 -22
- package/.next/standalone/.next/server/chunks/_0bs-v8p._.js +0 -3
- package/.next/standalone/.next/server/chunks/_185gyk9._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__056wjo4._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0n0xg95._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0rwtwpm._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0yrsbd_._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__11mayhe._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__15578wp._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1m_svbe._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1q4p5b8._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_1n3w9lb._.js +0 -6
- package/.next/standalone/.next/static/chunks/1lyg_puttohbc.js +0 -1
- /package/.next/standalone/.next/static/{ECs8__hcNabYV58WfDh-3 → UZKCiP4Q2TeU8zOB-h9Xj}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{ECs8__hcNabYV58WfDh-3 → UZKCiP4Q2TeU8zOB-h9Xj}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{ECs8__hcNabYV58WfDh-3 → UZKCiP4Q2TeU8zOB-h9Xj}/_ssgManifest.js +0 -0
|
@@ -82,6 +82,49 @@ is unreachable.
|
|
|
82
82
|
|
|
83
83
|
### 2. Adapters
|
|
84
84
|
|
|
85
|
+
#### OpenTelemetry (opt in)
|
|
86
|
+
|
|
87
|
+
If your app already emits OpenTelemetry spans, send them through FailproofAI Cloud
|
|
88
|
+
without replacing its framework adapters. Install OpenTelemetry separately:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
npm install @opentelemetry/api @opentelemetry/sdk-trace-base
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
import * as failproofai from "@failproofai/sdk";
|
|
96
|
+
import { BasicTracerProvider } from "@opentelemetry/sdk-trace-base";
|
|
97
|
+
import type { SpanProcessor } from "@opentelemetry/sdk-trace-base";
|
|
98
|
+
|
|
99
|
+
const spanProcessors: SpanProcessor[] = []; // include your existing processors
|
|
100
|
+
await failproofai.instrument("otel", { spanProcessors });
|
|
101
|
+
const provider = new BasicTracerProvider({ spanProcessors });
|
|
102
|
+
const tracer = provider.getTracer("my-agent");
|
|
103
|
+
const span = tracer.startSpan("agent", {
|
|
104
|
+
attributes: { "gen_ai.operation.name": "invoke_agent" },
|
|
105
|
+
});
|
|
106
|
+
span.end();
|
|
107
|
+
await provider.forceFlush();
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
With no options, `instrument("otel")` creates a provider only if none is registered.
|
|
111
|
+
For an existing OpenTelemetry v2 provider, add the processor before constructing
|
|
112
|
+
the provider, as above. For providers exposing `addSpanProcessor`, pass `{ provider }`.
|
|
113
|
+
You can also supply `new failproofai.OtelSpanExporter()` to your own span processor.
|
|
114
|
+
`uninstrument("otel")` disables only FailproofAI's processor; other exporters keep working.
|
|
115
|
+
|
|
116
|
+
The exporter writes OTLP/JSON export requests durably into the local relay spool
|
|
117
|
+
(`$FAILPROOFAI_HOME/state/spool-otlp`, otherwise `~/.failproofai/state/spool-otlp`).
|
|
118
|
+
It never sends HTTP or reads the Cloud key. Connect the daemon with `failproofai config`
|
|
119
|
+
and ask an admin to enable Settings → OpenTelemetry. No local TCP listener is
|
|
120
|
+
needed for SDK exports. `spoolDir` is an explicit override for tests or managed
|
|
121
|
+
deployments. `configure({ baseDir })` still applies only to the existing event adapters.
|
|
122
|
+
|
|
123
|
+
OTEL is never auto-enabled by a bare `instrument()`. The SDK still declares zero
|
|
124
|
+
hard runtime dependencies. Your spans control content capture; do not export
|
|
125
|
+
sensitive attributes unless intended. Export related spans together for complete
|
|
126
|
+
agent traces; call `provider.forceFlush()` before a short-lived process exits.
|
|
127
|
+
|
|
85
128
|
```ts
|
|
86
129
|
await failproofai.instrument(); // whatever it can find
|
|
87
130
|
await failproofai.instrument("langchain"); // exactly one
|
|
@@ -258,8 +258,15 @@ describe.each(FIXTURES)("%s", (fixture) => {
|
|
|
258
258
|
};
|
|
259
259
|
expect(report.text).toBe("It is 20C in Paris.");
|
|
260
260
|
if (major >= 7) {
|
|
261
|
-
// v7 has no OpenTelemetry dependency
|
|
262
|
-
|
|
261
|
+
// v7 has no OpenTelemetry dependency of its own. The optional OTEL
|
|
262
|
+
// exporter's dev tests can make it resolvable from the parent SDK
|
|
263
|
+
// project; when present, their provider must still own the global slot
|
|
264
|
+
// and receive only their service span (ai 7 emits no OTEL spans).
|
|
265
|
+
if (report.customer !== "absent") {
|
|
266
|
+
expect(report.customer, describeTrace(result)).toEqual({
|
|
267
|
+
registered: true, ended: ["http.request"],
|
|
268
|
+
});
|
|
269
|
+
}
|
|
263
270
|
expect(shape(result.events), describeTrace(result)).toEqual(GEN);
|
|
264
271
|
return;
|
|
265
272
|
}
|
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@failproofai/sdk",
|
|
3
|
-
"version": "0.0.1-beta.
|
|
3
|
+
"version": "0.0.1-beta.1",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@failproofai/sdk",
|
|
9
|
-
"version": "0.0.1-beta.
|
|
9
|
+
"version": "0.0.1-beta.1",
|
|
10
10
|
"license": "SEE LICENSE IN LICENSE",
|
|
11
11
|
"bin": {
|
|
12
12
|
"failproofai-evaluator": "dist/esm/evaluator/cli.js"
|
|
13
13
|
},
|
|
14
14
|
"devDependencies": {
|
|
15
15
|
"@eslint/js": "^9.38.0",
|
|
16
|
+
"@opentelemetry/api": "^1.9.0",
|
|
17
|
+
"@opentelemetry/sdk-trace-base": "^2.12.0",
|
|
16
18
|
"@types/node": "^22.10.2",
|
|
17
19
|
"eslint": "^9.38.0",
|
|
18
20
|
"typescript": "^5.9.2",
|
|
@@ -281,6 +283,56 @@
|
|
|
281
283
|
"@jridgewell/sourcemap-codec": "^1.4.14"
|
|
282
284
|
}
|
|
283
285
|
},
|
|
286
|
+
"node_modules/@opentelemetry/api": {
|
|
287
|
+
"version": "1.9.1",
|
|
288
|
+
"resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.1.tgz",
|
|
289
|
+
"integrity": "sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q==",
|
|
290
|
+
"dev": true,
|
|
291
|
+
"engines": { "node": ">=8.0.0" }
|
|
292
|
+
},
|
|
293
|
+
"node_modules/@opentelemetry/core": {
|
|
294
|
+
"version": "2.12.0",
|
|
295
|
+
"resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.12.0.tgz",
|
|
296
|
+
"integrity": "sha512-1HsSAuvT4/my0QrXWsyXFdWjKaPeCHsismKZgEEIb8NK13LP6DrMRlsUbvD/0F9mDWK3xDom9AMv3IscxgOnOQ==",
|
|
297
|
+
"dev": true,
|
|
298
|
+
"dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" },
|
|
299
|
+
"peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" },
|
|
300
|
+
"engines": { "node": "^18.19.0 || >=20.6.0" }
|
|
301
|
+
},
|
|
302
|
+
"node_modules/@opentelemetry/resources": {
|
|
303
|
+
"version": "2.12.0",
|
|
304
|
+
"resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.12.0.tgz",
|
|
305
|
+
"integrity": "sha512-+rSRoOdln6NhXTVcBdHSlZxJDNzwxadeweK2ltZO3tVtfp6aklABc06xclDk6ovRR+EiGgIcSbh/6NgjFhnb3A==",
|
|
306
|
+
"dev": true,
|
|
307
|
+
"dependencies": { "@opentelemetry/core": "2.12.0", "@opentelemetry/semantic-conventions": "^1.29.0" },
|
|
308
|
+
"peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" },
|
|
309
|
+
"engines": { "node": "^18.19.0 || >=20.6.0" }
|
|
310
|
+
},
|
|
311
|
+
"node_modules/@opentelemetry/sdk-trace": {
|
|
312
|
+
"version": "2.12.0",
|
|
313
|
+
"resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace/-/sdk-trace-2.12.0.tgz",
|
|
314
|
+
"integrity": "sha512-ImVuRQ6faOsTi1Wna88s2avgrrf/iDgXPigIeynkUhjstMuoQUDOJXgkez2j1mlU4btjXcXBGa+q7qKFYR3GsA==",
|
|
315
|
+
"dev": true,
|
|
316
|
+
"dependencies": { "@opentelemetry/core": "2.12.0", "@opentelemetry/resources": "2.12.0", "@opentelemetry/semantic-conventions": "^1.29.0" },
|
|
317
|
+
"peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" },
|
|
318
|
+
"engines": { "node": "^18.19.0 || >=20.6.0" }
|
|
319
|
+
},
|
|
320
|
+
"node_modules/@opentelemetry/sdk-trace-base": {
|
|
321
|
+
"version": "2.12.0",
|
|
322
|
+
"resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.12.0.tgz",
|
|
323
|
+
"integrity": "sha512-JOERgZCxRM06FEJ5kEWxlSRChah6MmXDx3KwCruqEv/iEyLkTokCSemf2y1w8oIHtfrr8EVTpzebq/31vn2Cpg==",
|
|
324
|
+
"dev": true,
|
|
325
|
+
"dependencies": { "@opentelemetry/core": "2.12.0", "@opentelemetry/resources": "2.12.0", "@opentelemetry/sdk-trace": "2.12.0", "@opentelemetry/semantic-conventions": "^1.29.0" },
|
|
326
|
+
"peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" },
|
|
327
|
+
"engines": { "node": "^18.19.0 || >=20.6.0" }
|
|
328
|
+
},
|
|
329
|
+
"node_modules/@opentelemetry/semantic-conventions": {
|
|
330
|
+
"version": "1.43.0",
|
|
331
|
+
"resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.43.0.tgz",
|
|
332
|
+
"integrity": "sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg==",
|
|
333
|
+
"dev": true,
|
|
334
|
+
"engines": { "node": ">=14" }
|
|
335
|
+
},
|
|
284
336
|
"node_modules/@oxc-project/types": {
|
|
285
337
|
"version": "0.150.0",
|
|
286
338
|
"resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.150.0.tgz",
|
|
@@ -2250,9 +2302,9 @@
|
|
|
2250
2302
|
"license": "ISC"
|
|
2251
2303
|
},
|
|
2252
2304
|
"node_modules/source-map-js": {
|
|
2253
|
-
"version": "1.2.
|
|
2254
|
-
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.
|
|
2255
|
-
"integrity": "sha512-
|
|
2305
|
+
"version": "1.2.2",
|
|
2306
|
+
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.2.tgz",
|
|
2307
|
+
"integrity": "sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==",
|
|
2256
2308
|
"dev": true,
|
|
2257
2309
|
"license": "BSD-3-Clause",
|
|
2258
2310
|
"peer": true,
|
|
@@ -42,6 +42,15 @@ import { notice } from "./notice.js";
|
|
|
42
42
|
export { VERSION as version };
|
|
43
43
|
|
|
44
44
|
export const DEFAULT_AGENT_ID = "main";
|
|
45
|
+
/** File export is unavailable at the Edge, like the other telemetry surfaces. */
|
|
46
|
+
export class OtelSpanExporter {
|
|
47
|
+
export(_spans: unknown[], callback: (result: { code: number }) => void): void {
|
|
48
|
+
notice();
|
|
49
|
+
callback({ code: 0 });
|
|
50
|
+
}
|
|
51
|
+
forceFlush(): Promise<void> { return Promise.resolve(); }
|
|
52
|
+
shutdown(): Promise<void> { return Promise.resolve(); }
|
|
53
|
+
}
|
|
45
54
|
/** The same registered symbol as the Node build's, so comparisons still hold. */
|
|
46
55
|
export const AUTO: unique symbol = Symbol.for("failproofai.AUTO") as never;
|
|
47
56
|
|
|
@@ -88,6 +88,8 @@ export {
|
|
|
88
88
|
uninstrument,
|
|
89
89
|
} from "./integrations/index.js";
|
|
90
90
|
export type { FrameworkName, InstrumentOptions } from "./integrations/index.js";
|
|
91
|
+
export { OtelSpanExporter } from "./integrations/otel.js";
|
|
92
|
+
export type { OtelReadableSpan, OtelSpanExporterOptions } from "./integrations/otel.js";
|
|
91
93
|
|
|
92
94
|
export interface ConfigureOptions {
|
|
93
95
|
/**
|
|
@@ -52,13 +52,14 @@ import * as compat from "./compat.js";
|
|
|
52
52
|
import type { Adapter } from "./core.js";
|
|
53
53
|
import * as core from "./core.js";
|
|
54
54
|
|
|
55
|
-
export type FrameworkName = "langchain" | "ai" | "mastra" | "llamaindex";
|
|
55
|
+
export type FrameworkName = "langchain" | "ai" | "mastra" | "llamaindex" | "otel";
|
|
56
56
|
|
|
57
57
|
const REGISTRY: Record<FrameworkName, () => Promise<{ adapter: Adapter }>> = {
|
|
58
58
|
langchain: () => import("./langchain.js"),
|
|
59
59
|
ai: () => import("./ai.js"),
|
|
60
60
|
mastra: () => import("./mastra.js"),
|
|
61
61
|
llamaindex: () => import("./llamaindex.js"),
|
|
62
|
+
otel: () => import("./otel.js"),
|
|
62
63
|
};
|
|
63
64
|
|
|
64
65
|
/**
|
|
@@ -90,6 +91,8 @@ const DETECT: Record<FrameworkName, readonly string[]> = {
|
|
|
90
91
|
ai: ["ai"],
|
|
91
92
|
mastra: ["@mastra/core"],
|
|
92
93
|
llamaindex: ["llamaindex", "@llamaindex/core"],
|
|
94
|
+
// Never auto-enable a second reporting path on an existing application.
|
|
95
|
+
otel: [],
|
|
93
96
|
};
|
|
94
97
|
|
|
95
98
|
const active = new Map<FrameworkName, Adapter>();
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Opt-in OTLP/JSON SpanExporter. Only disk I/O: the daemon authenticates and
|
|
3
|
+
* delivers opaque batches. No OpenTelemetry import until instrument("otel").
|
|
4
|
+
*/
|
|
5
|
+
import { randomUUID } from "node:crypto";
|
|
6
|
+
import { closeSync, fsyncSync, mkdirSync, openSync, renameSync, rmSync, writeSync } from "node:fs";
|
|
7
|
+
import { homedir } from "node:os";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
import { importModule, resolveFrom, tryRequire } from "../node-require.js";
|
|
10
|
+
import type { Adapter } from "./core.js";
|
|
11
|
+
|
|
12
|
+
type ObjectValue = Record<string, unknown>;
|
|
13
|
+
export interface OtelReadableSpan {
|
|
14
|
+
name: string;
|
|
15
|
+
kind: number;
|
|
16
|
+
spanContext(): { traceId: string; spanId: string; traceFlags?: number; traceState?: { serialize(): string } };
|
|
17
|
+
parentSpanId?: string;
|
|
18
|
+
parentSpanContext?: { spanId: string };
|
|
19
|
+
startTime: readonly [number, number];
|
|
20
|
+
endTime: readonly [number, number];
|
|
21
|
+
attributes: ObjectValue;
|
|
22
|
+
status: { code: number; message?: string };
|
|
23
|
+
resource?: { attributes: ObjectValue; schemaUrl?: string };
|
|
24
|
+
instrumentationScope?: { name: string; version?: string; schemaUrl?: string };
|
|
25
|
+
instrumentationLibrary?: { name: string; version?: string; schemaUrl?: string };
|
|
26
|
+
events?: readonly { name: string; time: readonly [number, number]; attributes?: ObjectValue; droppedAttributesCount?: number }[];
|
|
27
|
+
links?: readonly { context: { traceId: string; spanId: string; traceFlags?: number; traceState?: { serialize(): string } }; attributes?: ObjectValue; droppedAttributesCount?: number }[];
|
|
28
|
+
droppedAttributesCount?: number;
|
|
29
|
+
droppedEventsCount?: number;
|
|
30
|
+
droppedLinksCount?: number;
|
|
31
|
+
}
|
|
32
|
+
export interface OtelExportResult { code: number; error?: Error }
|
|
33
|
+
export interface OtelSpanExporterOptions { spoolDir?: string }
|
|
34
|
+
const MAX_BYTES = 8 * 1024 * 1024;
|
|
35
|
+
const metadata = '{"path":"/v1/traces","content_type":"application/json","encoding":null}\n';
|
|
36
|
+
|
|
37
|
+
function anyValue(value: unknown): ObjectValue {
|
|
38
|
+
if (typeof value === "string") return { stringValue: value };
|
|
39
|
+
if (typeof value === "boolean") return { boolValue: value };
|
|
40
|
+
if (typeof value === "bigint") return { intValue: value.toString() };
|
|
41
|
+
if (typeof value === "number") {
|
|
42
|
+
if (!Number.isFinite(value)) return { doubleValue: String(value) };
|
|
43
|
+
return Number.isInteger(value) ? { intValue: String(value) } : { doubleValue: value };
|
|
44
|
+
}
|
|
45
|
+
if (value instanceof Uint8Array) return { bytesValue: Buffer.from(value).toString("base64") };
|
|
46
|
+
if (Array.isArray(value)) return { arrayValue: { values: value.map(anyValue) } };
|
|
47
|
+
if (value && typeof value === "object") return { kvlistValue: { values: attributes(value as ObjectValue) } };
|
|
48
|
+
return {};
|
|
49
|
+
}
|
|
50
|
+
function attributes(value: ObjectValue = {}): ObjectValue[] {
|
|
51
|
+
return Object.entries(value).filter(([, v]) => v !== undefined && v !== null)
|
|
52
|
+
.map(([key, v]) => ({ key, value: anyValue(v) }));
|
|
53
|
+
}
|
|
54
|
+
function nanos(time: readonly [number, number]): string {
|
|
55
|
+
return (BigInt(time[0]) * 1_000_000_000n + BigInt(time[1])).toString();
|
|
56
|
+
}
|
|
57
|
+
function resourceSpan(span: OtelReadableSpan): ObjectValue {
|
|
58
|
+
const context = span.spanContext();
|
|
59
|
+
const scope = span.instrumentationScope ?? span.instrumentationLibrary;
|
|
60
|
+
return {
|
|
61
|
+
resource: { attributes: attributes(span.resource?.attributes) },
|
|
62
|
+
...(span.resource?.schemaUrl ? { schemaUrl: span.resource.schemaUrl } : {}),
|
|
63
|
+
scopeSpans: [{
|
|
64
|
+
scope: { name: scope?.name ?? "", ...(scope?.version ? { version: scope.version } : {}) },
|
|
65
|
+
...(scope?.schemaUrl ? { schemaUrl: scope.schemaUrl } : {}),
|
|
66
|
+
spans: [{
|
|
67
|
+
traceId: context.traceId, spanId: context.spanId,
|
|
68
|
+
...(span.parentSpanContext?.spanId || span.parentSpanId ? { parentSpanId: span.parentSpanContext?.spanId ?? span.parentSpanId } : {}),
|
|
69
|
+
...(context.traceState ? { traceState: context.traceState.serialize() } : {}),
|
|
70
|
+
flags: context.traceFlags ?? 0, name: span.name, kind: span.kind + 1,
|
|
71
|
+
startTimeUnixNano: nanos(span.startTime), endTimeUnixNano: nanos(span.endTime),
|
|
72
|
+
attributes: attributes(span.attributes), status: span.status,
|
|
73
|
+
droppedAttributesCount: span.droppedAttributesCount ?? 0,
|
|
74
|
+
droppedEventsCount: span.droppedEventsCount ?? 0, droppedLinksCount: span.droppedLinksCount ?? 0,
|
|
75
|
+
events: (span.events ?? []).map(event => ({
|
|
76
|
+
name: event.name, timeUnixNano: nanos(event.time), attributes: attributes(event.attributes),
|
|
77
|
+
droppedAttributesCount: event.droppedAttributesCount ?? 0,
|
|
78
|
+
})),
|
|
79
|
+
links: (span.links ?? []).map(link => ({
|
|
80
|
+
traceId: link.context.traceId, spanId: link.context.spanId, flags: link.context.traceFlags ?? 0,
|
|
81
|
+
...(link.context.traceState ? { traceState: link.context.traceState.serialize() } : {}),
|
|
82
|
+
attributes: attributes(link.attributes), droppedAttributesCount: link.droppedAttributesCount ?? 0,
|
|
83
|
+
})),
|
|
84
|
+
}],
|
|
85
|
+
}],
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** Structural implementation of OpenTelemetry's SpanExporter; zero hard deps. */
|
|
90
|
+
export class OtelSpanExporter {
|
|
91
|
+
private stopped = false;
|
|
92
|
+
private readonly directory?: string;
|
|
93
|
+
constructor(options: OtelSpanExporterOptions = {}) { this.directory = options.spoolDir; }
|
|
94
|
+
|
|
95
|
+
export(spans: readonly OtelReadableSpan[], callback: (result: OtelExportResult) => void): void {
|
|
96
|
+
let result: OtelExportResult = { code: 0 };
|
|
97
|
+
try {
|
|
98
|
+
if (this.stopped) throw new Error("OTEL exporter has shut down.");
|
|
99
|
+
const dir = this.directory ?? join(process.env.FAILPROOFAI_HOME || join(homedir(), ".failproofai"), "state", "spool-otlp");
|
|
100
|
+
// Encode each span once and split batches at the relay's request limit.
|
|
101
|
+
const chunks: string[] = [];
|
|
102
|
+
let items: string[] = [];
|
|
103
|
+
let size = Buffer.byteLength('{"resourceSpans":[]}');
|
|
104
|
+
for (const span of spans) {
|
|
105
|
+
const encoded = JSON.stringify(resourceSpan(span));
|
|
106
|
+
const bytes = Buffer.byteLength(encoded);
|
|
107
|
+
if (bytes + 20 > MAX_BYTES) throw new Error("OTEL span exceeds the 8 MiB relay limit.");
|
|
108
|
+
if (size + bytes + 1 > MAX_BYTES) {
|
|
109
|
+
chunks.push(`{"resourceSpans":[${items.join(",")}]}`); items = []; size = 20;
|
|
110
|
+
}
|
|
111
|
+
items.push(encoded); size += bytes + 1;
|
|
112
|
+
}
|
|
113
|
+
if (items.length) chunks.push(`{"resourceSpans":[${items.join(",")}]}`);
|
|
114
|
+
for (const body of chunks) this.publish(dir, body);
|
|
115
|
+
} catch (error) {
|
|
116
|
+
result = { code: 1, error: error instanceof Error ? error : new Error(String(error)) };
|
|
117
|
+
}
|
|
118
|
+
callback(result);
|
|
119
|
+
}
|
|
120
|
+
private publish(dir: string, body: string): void {
|
|
121
|
+
mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
122
|
+
const name = `otlp-sdk-${randomUUID()}`;
|
|
123
|
+
const temp = join(dir, `.${name}.tmp`);
|
|
124
|
+
let fd: number | undefined;
|
|
125
|
+
try {
|
|
126
|
+
fd = openSync(temp, "wx", 0o600);
|
|
127
|
+
const bytes = Buffer.from(metadata + body);
|
|
128
|
+
let offset = 0;
|
|
129
|
+
while (offset < bytes.length) offset += writeSync(fd, bytes, offset, bytes.length - offset);
|
|
130
|
+
fsyncSync(fd); closeSync(fd); fd = undefined;
|
|
131
|
+
renameSync(temp, join(dir, `${name}.jsonl`));
|
|
132
|
+
if (process.platform !== "win32") {
|
|
133
|
+
const directory = openSync(dir, "r");
|
|
134
|
+
try { fsyncSync(directory); } finally { closeSync(directory); }
|
|
135
|
+
}
|
|
136
|
+
} finally {
|
|
137
|
+
if (fd !== undefined) closeSync(fd);
|
|
138
|
+
rmSync(temp, { force: true });
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
forceFlush(): Promise<void> { return Promise.resolve(); }
|
|
142
|
+
shutdown(): Promise<void> { this.stopped = true; return Promise.resolve(); }
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
interface Processor {
|
|
146
|
+
onStart(...args: unknown[]): void;
|
|
147
|
+
onEnd(...args: unknown[]): void;
|
|
148
|
+
shutdown(): Promise<void>;
|
|
149
|
+
forceFlush(): Promise<void>;
|
|
150
|
+
}
|
|
151
|
+
interface Provider { addSpanProcessor(processor: Processor): void }
|
|
152
|
+
interface TraceSdk {
|
|
153
|
+
BatchSpanProcessor: new (exporter: OtelSpanExporter) => Processor;
|
|
154
|
+
BasicTracerProvider: new (options: { spanProcessors: Processor[] }) => unknown;
|
|
155
|
+
}
|
|
156
|
+
interface TraceApi { trace: { setGlobalTracerProvider(provider: unknown): boolean } }
|
|
157
|
+
let installed: { enabled: boolean; processor: Processor; list?: Processor[] } | null = null;
|
|
158
|
+
export const adapter: Adapter = {
|
|
159
|
+
name: "otel",
|
|
160
|
+
async install(options = {}) {
|
|
161
|
+
const provider = options.provider as Provider | undefined;
|
|
162
|
+
const list = options.spanProcessors as Processor[] | undefined;
|
|
163
|
+
if (provider && typeof provider.addSpanProcessor !== "function") {
|
|
164
|
+
throw new Error('instrument("otel") needs { spanProcessors } before constructing an OTEL v2 provider, or a provider with addSpanProcessor().');
|
|
165
|
+
}
|
|
166
|
+
const path = resolveFrom("@opentelemetry/sdk-trace-base");
|
|
167
|
+
if (!path) throw new Error('Install @opentelemetry/sdk-trace-base to use instrument("otel").');
|
|
168
|
+
const module = tryRequire<TraceSdk>("@opentelemetry/sdk-trace-base") ??
|
|
169
|
+
await importModule(path) as TraceSdk;
|
|
170
|
+
const exporter = new OtelSpanExporter({ spoolDir: options.spoolDir as string | undefined });
|
|
171
|
+
const batch = new module.BatchSpanProcessor(exporter);
|
|
172
|
+
const state = { enabled: true, processor: batch, list };
|
|
173
|
+
// Providers have no portable remove API. A gate makes uninstall effective
|
|
174
|
+
// without shutting down anybody else's processors or provider.
|
|
175
|
+
const gate: Processor = {
|
|
176
|
+
onStart: (...args) => { if (state.enabled) batch.onStart(...args); },
|
|
177
|
+
onEnd: (...args) => { if (state.enabled) batch.onEnd(...args); },
|
|
178
|
+
forceFlush: () => state.enabled ? batch.forceFlush() : Promise.resolve(),
|
|
179
|
+
shutdown: () => batch.shutdown(),
|
|
180
|
+
};
|
|
181
|
+
installed = state;
|
|
182
|
+
if (Array.isArray(list)) { list.push(gate); state.processor = gate; }
|
|
183
|
+
else if (provider) { provider.addSpanProcessor(gate); state.processor = gate; }
|
|
184
|
+
else {
|
|
185
|
+
state.processor = gate;
|
|
186
|
+
const apiPath = resolveFrom("@opentelemetry/api");
|
|
187
|
+
if (!apiPath) throw new Error("Install @opentelemetry/api to register the OTEL provider.");
|
|
188
|
+
const api = tryRequire<TraceApi>("@opentelemetry/api") ?? await importModule(apiPath) as TraceApi;
|
|
189
|
+
if (!api.trace.setGlobalTracerProvider(new module.BasicTracerProvider({ spanProcessors: [gate] }))) {
|
|
190
|
+
throw new Error('An OTEL provider is already registered; use instrument("otel", { spanProcessors }) before constructing it.');
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
uninstall() {
|
|
195
|
+
if (!installed) return;
|
|
196
|
+
installed.enabled = false;
|
|
197
|
+
if (installed.list) {
|
|
198
|
+
const index = installed.list.indexOf(installed.processor);
|
|
199
|
+
if (index >= 0) installed.list.splice(index, 1);
|
|
200
|
+
}
|
|
201
|
+
void installed.processor.shutdown().catch(() => { /* SDK teardown never throws into the app. */ });
|
|
202
|
+
installed = null;
|
|
203
|
+
},
|
|
204
|
+
};
|
|
@@ -324,7 +324,7 @@ describe("RunTracker", () => {
|
|
|
324
324
|
|
|
325
325
|
describe("the registry", () => {
|
|
326
326
|
it("lists the frameworks it can instrument", () => {
|
|
327
|
-
expect(available()).toEqual(["ai", "langchain", "llamaindex", "mastra"]);
|
|
327
|
+
expect(available()).toEqual(["ai", "langchain", "llamaindex", "mastra", "otel"]);
|
|
328
328
|
});
|
|
329
329
|
|
|
330
330
|
it("throws on an unknown name, listing the valid ones", async () => {
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
2
|
+
import { mkdtempSync, readdirSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { BasicTracerProvider, SimpleSpanProcessor } from "@opentelemetry/sdk-trace-base";
|
|
6
|
+
import type { SpanProcessor, ReadableSpan } from "@opentelemetry/sdk-trace-base";
|
|
7
|
+
import { ROOT_CONTEXT, SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
|
|
8
|
+
import { OtelSpanExporter } from "../src/index.js";
|
|
9
|
+
import { instrument, uninstrument, activeFrameworks } from "../src/integrations/index.js";
|
|
10
|
+
import { setStrict } from "../src/integrations/core.js";
|
|
11
|
+
|
|
12
|
+
let home: string;
|
|
13
|
+
let previousHome: string | undefined;
|
|
14
|
+
beforeEach(() => {
|
|
15
|
+
home = mkdtempSync(join(tmpdir(), "fpai-otel-sdk-"));
|
|
16
|
+
previousHome = process.env.FAILPROOFAI_HOME;
|
|
17
|
+
process.env.FAILPROOFAI_HOME = home;
|
|
18
|
+
});
|
|
19
|
+
afterEach(() => {
|
|
20
|
+
uninstrument("otel");
|
|
21
|
+
setStrict(null);
|
|
22
|
+
if (previousHome === undefined) delete process.env.FAILPROOFAI_HOME;
|
|
23
|
+
else process.env.FAILPROOFAI_HOME = previousHome;
|
|
24
|
+
rmSync(home, { recursive: true, force: true });
|
|
25
|
+
});
|
|
26
|
+
function files() { return readdirSync(join(home, "state/spool-otlp")); }
|
|
27
|
+
function body(name: string) {
|
|
28
|
+
const text = readFileSync(join(home, "state/spool-otlp", name), "utf8");
|
|
29
|
+
const split = text.indexOf("\n");
|
|
30
|
+
expect(JSON.parse(text.slice(0, split))).toEqual({
|
|
31
|
+
path: "/v1/traces", content_type: "application/json", encoding: null,
|
|
32
|
+
});
|
|
33
|
+
return JSON.parse(text.slice(split + 1)) as { resourceSpans: Array<{
|
|
34
|
+
resource: { attributes: unknown[] };
|
|
35
|
+
scopeSpans: Array<{ scope: { name: string }; spans: Array<Record<string, unknown>> }>;
|
|
36
|
+
}> };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
describe("OTLP/JSON SpanExporter", () => {
|
|
40
|
+
it("exports real ended spans, links, events, precise nanos, status and typed attributes durably without network", async () => {
|
|
41
|
+
const exporter = new OtelSpanExporter();
|
|
42
|
+
const provider = new BasicTracerProvider({ spanProcessors: [new SimpleSpanProcessor(exporter)] });
|
|
43
|
+
const tracer = provider.getTracer("test-scope", "1.0");
|
|
44
|
+
const parent = tracer.startSpan("agent", { startTime: [1780000000, 123], attributes: { "gen_ai.operation.name": "invoke_agent" } });
|
|
45
|
+
const child = tracer.startSpan("chat", {
|
|
46
|
+
startTime: [1780000000, 456], kind: SpanKind.CLIENT,
|
|
47
|
+
attributes: { "gen_ai.operation.name": "chat", count: 42, enabled: true, decimal: 1.5, values: ["a", "b"] },
|
|
48
|
+
links: [{ context: parent.spanContext(), attributes: { linked: true } }],
|
|
49
|
+
}, trace.setSpanContext(ROOT_CONTEXT, parent.spanContext()));
|
|
50
|
+
child.addEvent("prompt", { text: "hello" }, [1780000000, 789]);
|
|
51
|
+
child.setStatus({ code: SpanStatusCode.ERROR, message: "failed" });
|
|
52
|
+
child.end([1780000001, 12]); parent.end([1780000001, 13]);
|
|
53
|
+
await provider.forceFlush();
|
|
54
|
+
expect(files()).toHaveLength(2);
|
|
55
|
+
const spans = files().flatMap(name => body(name).resourceSpans.flatMap(r => r.scopeSpans.flatMap(s => s.spans)));
|
|
56
|
+
const output = spans.find(span => span.name === "chat")!;
|
|
57
|
+
expect(output).toMatchObject({
|
|
58
|
+
traceId: child.spanContext().traceId, spanId: child.spanContext().spanId,
|
|
59
|
+
parentSpanId: parent.spanContext().spanId, kind: 3,
|
|
60
|
+
startTimeUnixNano: "1780000000000000456", endTimeUnixNano: "1780000001000000012",
|
|
61
|
+
status: { code: 2, message: "failed" },
|
|
62
|
+
events: [{ name: "prompt", timeUnixNano: "1780000000000000789" }],
|
|
63
|
+
links: [{ traceId: parent.spanContext().traceId, spanId: parent.spanContext().spanId }],
|
|
64
|
+
});
|
|
65
|
+
expect(output.attributes).toContainEqual({ key: "count", value: { intValue: "42" } });
|
|
66
|
+
expect(output.attributes).toContainEqual({ key: "values", value: { arrayValue: { values: [{ stringValue: "a" }, { stringValue: "b" }] } } });
|
|
67
|
+
for (const name of files()) {
|
|
68
|
+
expect(name).toMatch(/^otlp-sdk-.*\.jsonl$/);
|
|
69
|
+
expect(statSync(join(home, "state/spool-otlp", name)).mode & 0o777).toBe(0o600);
|
|
70
|
+
}
|
|
71
|
+
await provider.shutdown();
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("reports disk and post-shutdown failures through the callback, once", async () => {
|
|
75
|
+
const file = join(home, "not-a-directory");
|
|
76
|
+
writeFileSync(file, "x");
|
|
77
|
+
const exporter = new OtelSpanExporter({ spoolDir: file });
|
|
78
|
+
const provider = new BasicTracerProvider();
|
|
79
|
+
const span = provider.getTracer("test").startSpan("test");
|
|
80
|
+
span.end();
|
|
81
|
+
const results: number[] = [];
|
|
82
|
+
exporter.export([span as unknown as ReadableSpan], result => results.push(result.code));
|
|
83
|
+
await exporter.shutdown();
|
|
84
|
+
exporter.export([], result => results.push(result.code));
|
|
85
|
+
expect(results).toEqual([1, 1]);
|
|
86
|
+
await provider.shutdown();
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it("splits an export above 8 MiB into complete bounded requests", async () => {
|
|
90
|
+
const provider = new BasicTracerProvider({ spanLimits: { attributeValueLengthLimit: 10_000_000 } });
|
|
91
|
+
const span = provider.getTracer("test").startSpan("big", { attributes: { content: "x".repeat(4 * 1024 * 1024) } });
|
|
92
|
+
span.end();
|
|
93
|
+
const results: number[] = [];
|
|
94
|
+
new OtelSpanExporter().export([span as unknown as ReadableSpan, span as unknown as ReadableSpan], result => results.push(result.code));
|
|
95
|
+
expect(results).toEqual([0]);
|
|
96
|
+
expect(files()).toHaveLength(2);
|
|
97
|
+
for (const name of files()) expect(body(name).resourceSpans).toHaveLength(1);
|
|
98
|
+
await provider.shutdown();
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it("instrument('otel') adds one gated processor and leaves other exporters unchanged", async () => {
|
|
102
|
+
setStrict(true);
|
|
103
|
+
const processors: SpanProcessor[] = [];
|
|
104
|
+
expect(await instrument("otel", { spanProcessors: processors })).toEqual(["otel"]);
|
|
105
|
+
expect(await instrument("otel", { spanProcessors: processors })).toEqual([]);
|
|
106
|
+
const observed: string[] = [];
|
|
107
|
+
const existing: SpanProcessor = {
|
|
108
|
+
onStart() {}, onEnd(span) { observed.push(span.name); },
|
|
109
|
+
forceFlush: () => Promise.resolve(), shutdown: () => Promise.resolve(),
|
|
110
|
+
};
|
|
111
|
+
const provider = new BasicTracerProvider({ spanProcessors: [existing, ...processors] });
|
|
112
|
+
const tracer = provider.getTracer("app");
|
|
113
|
+
tracer.startSpan("before").end();
|
|
114
|
+
await provider.forceFlush();
|
|
115
|
+
expect(files()).toHaveLength(1);
|
|
116
|
+
expect(activeFrameworks()).toContain("otel");
|
|
117
|
+
expect(uninstrument("otel")).toEqual(["otel"]);
|
|
118
|
+
tracer.startSpan("after").end();
|
|
119
|
+
await provider.forceFlush();
|
|
120
|
+
expect(files()).toHaveLength(1);
|
|
121
|
+
expect(observed).toEqual(["before", "after"]);
|
|
122
|
+
expect(processors).toHaveLength(0);
|
|
123
|
+
await provider.shutdown();
|
|
124
|
+
});
|
|
125
|
+
});
|
|
@@ -9,7 +9,7 @@ const currentPort = parseInt(process.env.PORT, 10) || 3000
|
|
|
9
9
|
const hostname = process.env.HOSTNAME || '0.0.0.0'
|
|
10
10
|
|
|
11
11
|
let keepAliveTimeout = parseInt(process.env.KEEP_ALIVE_TIMEOUT, 10)
|
|
12
|
-
const nextConfig = {"env":{"NEXT_PUBLIC_APP_VERSION":"1.0.
|
|
12
|
+
const nextConfig = {"env":{"NEXT_PUBLIC_APP_VERSION":"1.0.11-beta.1"},"typescript":{"ignoreBuildErrors":false},"typedRoutes":false,"distDir":"./.next","cleanDistDir":true,"assetPrefix":"","cacheMaxMemorySize":52428800,"configOrigin":"next.config.ts","useFileSystemPublicRoutes":true,"generateEtags":true,"pageExtensions":["tsx","ts","jsx","js"],"instrumentationClientInject":[],"poweredByHeader":true,"compress":true,"images":{"deviceSizes":[640,750,828,1080,1200,1920,2048,3840],"imageSizes":[32,48,64,96,128,256,384],"path":"/_next/image","loader":"default","loaderFile":"","domains":[],"disableStaticImages":false,"minimumCacheTTL":14400,"formats":["image/webp"],"maximumRedirects":3,"maximumResponseBody":50000000,"dangerouslyAllowLocalIP":false,"dangerouslyAllowSVG":false,"contentSecurityPolicy":"script-src 'none'; frame-src 'none'; sandbox;","contentDispositionType":"attachment","localPatterns":[{"pathname":"**","search":""}],"remotePatterns":[],"qualities":[75],"unoptimized":true,"customCacheHandler":false},"devIndicators":{"position":"bottom-left"},"onDemandEntries":{"maxInactiveAge":60000,"pagesBufferLength":5},"basePath":"","sassOptions":{},"trailingSlash":false,"i18n":null,"productionBrowserSourceMaps":false,"excludeDefaultMomentLocales":true,"reactProductionProfiling":false,"reactStrictMode":null,"reactMaxHeadersLength":6000,"httpAgentOptions":{"keepAlive":true},"logging":{"serverFunctions":true,"browserToTerminal":"warn"},"compiler":{},"expireTime":31536000,"staticPageGenerationTimeout":60,"output":"standalone","modularizeImports":{"@mui/icons-material":{"transform":"@mui/icons-material/{{member}}"},"lodash":{"transform":"lodash/{{member}}"}},"outputFileTracingRoot":"/home/runner/work/failproofai/failproofai","enablePrerenderSourceMaps":true,"cacheComponents":false,"cacheLife":{"default":{"stale":300,"revalidate":900,"expire":4294967294},"seconds":{"stale":30,"revalidate":1,"expire":60},"minutes":{"stale":300,"revalidate":60,"expire":3600},"hours":{"stale":300,"revalidate":3600,"expire":86400},"days":{"stale":300,"revalidate":86400,"expire":604800},"weeks":{"stale":300,"revalidate":604800,"expire":2592000},"max":{"stale":300,"revalidate":2592000,"expire":31536000}},"cacheHandlers":{},"experimental":{"appNewScrollHandler":true,"coldCacheBadge":false,"devValidationWorker":true,"useSkewCookie":false,"cssChunking":true,"multiZoneDraftMode":false,"appNavFailHandling":false,"prerenderEarlyExit":true,"serverMinification":true,"linkNoTouchStart":false,"caseSensitiveRoutes":false,"cachedNavigations":false,"dynamicOnHover":false,"useOffline":false,"varyParams":true,"optimisticRouting":true,"instrumentationClientRouterTransitionEvents":false,"prefetchInlining":{"maxSize":2048,"maxBundleSize":10240},"preloadEntriesOnStart":true,"clientRouterFilter":true,"clientRouterFilterRedirects":false,"fetchCacheKeyPrefix":"","proxyPrefetch":"flexible","optimisticClientCache":true,"manualClientBasePath":false,"cpus":3,"memoryBasedWorkersCount":false,"imgOptConcurrency":null,"imgOptOperationCache":null,"imgOptTimeoutInSeconds":7,"imgOptMaxInputPixels":268402689,"imgOptSequentialRead":null,"isrFlushToDisk":true,"workerThreads":false,"optimizeCss":false,"nextScriptWorkers":false,"scrollRestoration":false,"externalDir":false,"devMemoryThresholdRestart":true,"disableOptimizedLoading":false,"gzipSize":true,"craCompat":false,"esmExternals":true,"fullySpecified":false,"swcTraceProfiling":false,"forceSwcTransforms":false,"requestInsights":false,"largePageDataBytes":128000,"typedEnv":false,"parallelServerCompiles":false,"parallelServerBuildTraces":false,"ppr":false,"authInterrupts":false,"webpackMemoryOptimizations":false,"optimizeServerReact":true,"strictRouteTypes":false,"useTypeScriptCli":true,"removeUncaughtErrorAndRejectionListeners":false,"validateRSCRequestHeaders":true,"staleTimes":{"dynamic":0,"static":300},"reactDebugChannel":true,"serverComponentsHmrCache":true,"serverComponentsHmrCancellation":false,"staticGenerationMaxConcurrency":8,"staticGenerationMinPagesPerWorker":25,"transitionIndicator":false,"gestureTransition":false,"inlineCss":false,"useCache":false,"globalNotFound":false,"browserDebugInfoInTerminal":"warn","lockDistDir":true,"proxyClientMaxBodySize":10485760,"hideLogsAfterAbort":false,"mcpServer":true,"turbopackFileSystemCacheForDev":true,"turbopackFileSystemCacheForBuild":true,"turbopackInferModuleSideEffects":true,"turbopackPluginRuntimeStrategy":"childProcesses","turbopackMemoryEvictionMode":"auto","optimizePackageImports":["lucide-react","date-fns","lodash-es","ramda","antd","react-bootstrap","ahooks","@ant-design/icons","@headlessui/react","@headlessui-float/react","@heroicons/react/20/solid","@heroicons/react/24/solid","@heroicons/react/24/outline","@visx/visx","@tremor/react","rxjs","@mui/material","@mui/icons-material","recharts","react-use","effect","@effect/schema","@effect/platform","@effect/platform-node","@effect/platform-browser","@effect/platform-bun","@effect/sql","@effect/sql-mssql","@effect/sql-mysql2","@effect/sql-pg","@effect/sql-sqlite-node","@effect/sql-sqlite-bun","@effect/sql-sqlite-wasm","@effect/sql-sqlite-react-native","@effect/rpc","@effect/rpc-http","@effect/typeclass","@effect/experimental","@effect/opentelemetry","@material-ui/core","@material-ui/icons","@tabler/icons-react","mui-core","react-icons/ai","react-icons/bi","react-icons/bs","react-icons/cg","react-icons/ci","react-icons/di","react-icons/fa","react-icons/fa6","react-icons/fc","react-icons/fi","react-icons/gi","react-icons/go","react-icons/gr","react-icons/hi","react-icons/hi2","react-icons/im","react-icons/io","react-icons/io5","react-icons/lia","react-icons/lib","react-icons/lu","react-icons/md","react-icons/pi","react-icons/ri","react-icons/rx","react-icons/si","react-icons/sl","react-icons/tb","react-icons/tfi","react-icons/ti","react-icons/vsc","react-icons/wi"],"useCacheTimeout":54,"instantInsights":{"validationLevel":"warning"},"trustHostHeader":false,"isExperimentalCompile":false},"htmlLimitedBots":"[\\w-]+-Google|Google-[\\w-]+|Chrome-Lighthouse|Slurp|DuckDuckBot|baiduspider|yandex|sogou|bitlybot|tumblr|vkShare|quora link preview|redditbot|ia_archiver|Bingbot|BingPreview|applebot|facebookexternalhit|facebookcatalog|Twitterbot|LinkedInBot|Slackbot|Discordbot|WhatsApp|SkypeUriPreview|Yeti|googleweblight","bundlePagesRouterDependencies":false,"configFileName":"next.config.ts","outputFileTracingExcludes":{"*":["node_modules/@img/**","node_modules/sharp/**"]},"turbopack":{"root":"/home/runner/work/failproofai/failproofai"},"repoRoot":"/home/runner/work/failproofai/failproofai","distDirRoot":".next"}
|
|
13
13
|
|
|
14
14
|
process.env.__NEXT_PRIVATE_STANDALONE_CONFIG = JSON.stringify(nextConfig)
|
|
15
15
|
|