failproofai 0.0.13-beta.2 → 0.0.14-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/standalone/.factory/hooks.json +112 -0
- package/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/build-manifest.json +3 -3
- 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/server-reference-manifest.json +1 -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 +7 -7
- 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 +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +1 -1
- package/.next/standalone/.next/server/app/_not-found.rsc +15 -15
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +15 -15
- package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +10 -10
- 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/_not-found.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/api/audit/invite/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/audit/run/route.js +3 -3
- package/.next/standalone/.next/server/app/api/audit/run/route.js.nft.json +1 -1
- 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.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/reminder/route.js.nft.json +1 -1
- 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 +2 -1
- package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
- package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/index.html +1 -1
- package/.next/standalone/.next/server/app/index.rsc +15 -15
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +15 -15
- package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +10 -10
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +8 -8
- package/.next/standalone/.next/server/app/policies/page.js +1 -1
- package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page.js +3 -2
- package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js +5 -3
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/projects/page.js +1 -1
- 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/chunks/[root-of-the-server]__0--lkk6._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0-219ec._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__04_h-a5._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__06cuf1y._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__08w4wmd._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0g6bbuw._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0jllheg._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0jnjf2t._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0q-v9z2._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0q0qzx1._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0q2nbsl._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0rv7m0k._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0xuaoik._.js +3 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__16le-kd._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__17g9wh7._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1d9qen3._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1ffkmds._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1fwl2mz._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1legmza._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1mrihkj._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1myjm-d._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1qb590j._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1qxztj-._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1shcqgr._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1xuedea._.js +3 -0
- package/.next/standalone/.next/server/chunks/{_1z062h5._.js → _1vslkoe._.js} +2 -2
- package/.next/standalone/.next/server/chunks/lib_factory-projects_ts_1eo_bk-._.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_openclaw-projects_ts_0gc-p24._.js +3 -0
- package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_17k9e3w.js +24 -12
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_01r25oi._.js +1 -1
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_09z9-p7._.js +1 -1
- 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]__00cz9as._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__015_i4t._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__030k0c6._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__03lv-pe._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__042d3cd._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__05r_17v._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1rlmypf._.js → [root-of-the-server]__07qfsfa._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__09q1168._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0e2l3c1._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__09u1pcy._.js → [root-of-the-server]__0ge8e7w._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0h12me5._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0hci7t3._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0hdsupo._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0p84xee._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0qeuy9c._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0s89hoe._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ynf7tx._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__11rtg6s._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__14dd6h8._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__170799-._.js +12 -9
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__17ai7sy._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1d8omgc._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1dky4g0._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1nq7ivq._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1tkjqka._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__212nf49._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_05whahf._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_0_9_ytf._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_11_p9y8._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{_0ul5rf_._.js → _1_ozgif._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/_1p0-leb._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +2 -2
- 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/lib_0xkhw_v._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/lib_antigravity-projects_ts_0_6zf11._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/lib_devin-projects_ts_0a64qdy._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/lib_factory-projects_ts_1uyaahq._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/lib_goose-projects_ts_0zkscri._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/lib_openclaw-projects_ts_0qxq3bp._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{node_modules_html-to-image_es_index_09fe3kb.js → node_modules_html-to-image_es_index_0g5r64e.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0-uvagv.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_03c7gi5.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_09p-8om.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0v-kfiu.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0xrgzyz.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_1806lsc.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_1j6dd-e.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_1sa65r-.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_posthog-node_dist_entrypoints_index_node_mjs_11bnuzn._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_1ezd2jf._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_1tnuifj._.js +1 -1
- package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
- 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 +10 -10
- package/.next/standalone/.next/static/chunks/003uz088wbmz7.js +1 -0
- package/.next/standalone/.next/static/chunks/{0l2n5ftar65ox.js → 0405htbxay9vd.js} +1 -1
- package/.next/standalone/.next/static/chunks/0iinhn4417nk1.js +1 -0
- package/.next/standalone/.next/static/chunks/1374x9bv_s_vg.js +6 -0
- package/.next/standalone/.next/static/chunks/{06cw8nbn5c4_r.js → 17sdztgbcc0fi.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0i0joc040j999.js → 2m_tbl39fcedn.js} +1 -1
- package/.next/standalone/.next/static/chunks/{25qvspmcbb_5y.js → 2o3ql0n5owqsw.js} +1 -1
- package/.next/standalone/.next/static/chunks/{2a-k91nsa1lgf.js → 2ufuwhv03yvtb.js} +1 -1
- package/.next/standalone/.next/static/chunks/35-90m9py64d4.js +1 -0
- package/.next/standalone/.next/static/chunks/3r--yyjkp9_7b.css +2 -0
- package/.next/standalone/.next/static/chunks/{23t-i9s-q--nu.js → 43weu8f59tlix.js} +1 -1
- package/.next/standalone/.next/static/chunks/{2oz8ok8fzxaj3.js → 454dyizqik6t9.js} +2 -2
- package/.next/standalone/app/api/audit/run/route.ts +2 -0
- package/.next/standalone/app/audit/_components/empty-state.tsx +1 -1
- package/.next/standalone/app/globals.css +25 -1
- package/.next/standalone/app/policies/hooks-client.tsx +2 -4
- package/.next/standalone/app/project/[name]/page.tsx +30 -10
- package/.next/standalone/app/project/[name]/session/[sessionId]/page.tsx +71 -21
- package/.next/standalone/assets/logos/antigravity.svg +1 -0
- package/.next/standalone/assets/logos/devin.svg +1 -0
- package/.next/standalone/assets/logos/factory-dark.png +0 -0
- package/.next/standalone/assets/logos/factory-light.png +0 -0
- package/.next/standalone/assets/logos/goose-dark.svg +1 -0
- package/.next/standalone/assets/logos/goose-light.svg +1 -0
- package/.next/standalone/assets/logos/openclaw.svg +22 -0
- package/.next/standalone/components/navbar.tsx +5 -11
- package/.next/standalone/components/reach-developers.tsx +1 -1
- package/.next/standalone/lib/antigravity-projects.ts +224 -0
- package/.next/standalone/lib/antigravity-sessions.ts +283 -0
- package/.next/standalone/lib/cli-registry.ts +26 -6
- package/.next/standalone/lib/devin-projects.ts +141 -0
- package/.next/standalone/lib/devin-sessions.ts +343 -0
- package/.next/standalone/lib/download-session.ts +56 -5
- package/.next/standalone/lib/factory-projects.ts +109 -0
- package/.next/standalone/lib/factory-sessions.ts +312 -0
- package/.next/standalone/lib/goose-projects.ts +148 -0
- package/.next/standalone/lib/goose-sessions.ts +296 -0
- package/.next/standalone/lib/openclaw-projects.ts +182 -0
- package/.next/standalone/lib/openclaw-sessions.ts +284 -0
- package/.next/standalone/lib/projects.ts +33 -9
- package/.next/standalone/lib/telemetry-sanitize.ts +43 -0
- package/.next/standalone/openclaw-plugin/index.js +223 -0
- package/.next/standalone/openclaw-plugin/openclaw.plugin.json +6 -0
- package/.next/standalone/openclaw-plugin/package.json +12 -0
- package/.next/standalone/package.json +4 -3
- package/.next/standalone/server.js +1 -1
- package/README.md +105 -57
- package/bin/failproofai.mjs +87 -29
- package/dist/cli.mjs +12803 -9809
- package/lib/antigravity-projects.ts +224 -0
- package/lib/antigravity-sessions.ts +283 -0
- package/lib/cli-registry.ts +26 -6
- package/lib/devin-projects.ts +141 -0
- package/lib/devin-sessions.ts +343 -0
- package/lib/download-session.ts +56 -5
- package/lib/factory-projects.ts +109 -0
- package/lib/factory-sessions.ts +312 -0
- package/lib/goose-projects.ts +148 -0
- package/lib/goose-sessions.ts +296 -0
- package/lib/openclaw-projects.ts +182 -0
- package/lib/openclaw-sessions.ts +284 -0
- package/lib/projects.ts +33 -9
- package/lib/telemetry-sanitize.ts +43 -0
- package/openclaw-plugin/index.js +223 -0
- package/openclaw-plugin/openclaw.plugin.json +6 -0
- package/openclaw-plugin/package.json +12 -0
- package/package.json +4 -3
- package/scripts/launch.ts +4 -8
- package/scripts/postinstall.mjs +3 -4
- package/scripts/sync-agent-cli-harnesses-prompt.md +7 -10
- package/scripts/translate-docs/cli.ts +73 -52
- package/scripts/translate-docs/config.ts +57 -13
- package/scripts/translate-docs/mdx-translator.ts +51 -31
- package/scripts/translate-docs/mintlify-nav.ts +91 -10
- package/scripts/translate-docs/types.ts +3 -0
- package/src/audit/cli-adapters/antigravity.ts +87 -0
- package/src/audit/cli-adapters/devin.ts +53 -0
- package/src/audit/cli-adapters/factory.ts +75 -0
- package/src/audit/cli-adapters/goose.ts +53 -0
- package/src/audit/cli-adapters/index.ts +30 -6
- package/src/audit/cli-adapters/openclaw.ts +56 -0
- package/src/audit/cli.ts +44 -1
- package/src/audit/report.ts +1 -1
- package/src/audit/types.ts +1 -1
- package/src/hooks/builtin-policies.ts +5 -5
- package/src/hooks/configure-wizard.ts +356 -0
- package/src/hooks/handler.ts +283 -218
- package/src/hooks/hook-telemetry.ts +43 -3
- package/src/hooks/install-prompt.ts +92 -173
- package/src/hooks/integrations.ts +739 -138
- package/src/hooks/manager.ts +46 -2
- package/src/hooks/policy-evaluator.ts +301 -121
- package/src/hooks/policy-presets.ts +71 -0
- package/src/hooks/resolve-cwd.ts +1 -1
- package/src/hooks/resolve-permission-mode.ts +1 -5
- package/src/hooks/resolve-transcript-path.ts +25 -7
- package/src/hooks/tool-name-canonicalize.ts +36 -3
- package/src/hooks/tui.ts +578 -0
- package/src/hooks/types.ts +447 -109
- package/.next/standalone/.gemini/settings.json +0 -147
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0cag8qd._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0cefjd9._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ekj92q._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__12v-lma._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__136y39g._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__13h8pzr._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1hgv_75._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__04bqvos._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0dqgs96._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0q5rfxg._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0qukut7._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1ql-mch._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_11v0g3z._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/lib_gemini-projects_ts_1c7bgx-._.js +0 -3
- package/.next/standalone/.next/static/chunks/0fa7j157kg9_d.js +0 -1
- package/.next/standalone/.next/static/chunks/1c8i78p7t1i-5.js +0 -1
- package/.next/standalone/.next/static/chunks/1sg8kx5szx42y.js +0 -6
- package/.next/standalone/.next/static/chunks/25s52un3k_wht.css +0 -2
- package/.next/standalone/.next/static/chunks/2rkvn4znvuy4o.js +0 -1
- package/.next/standalone/assets/logos/gemini-dark.svg +0 -13
- package/.next/standalone/assets/logos/gemini-light.svg +0 -13
- package/.next/standalone/lib/gemini-projects.ts +0 -243
- package/.next/standalone/lib/gemini-sessions.ts +0 -365
- package/lib/gemini-projects.ts +0 -243
- package/lib/gemini-sessions.ts +0 -365
- package/src/audit/cli-adapters/gemini.ts +0 -51
- package/src/hooks/first-run-nudge.ts +0 -146
- /package/.next/standalone/.next/static/{HgG0mizCfOM3XyN1EW-sL → MNJWFb2jLRrxRKGFNK6Hy}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{HgG0mizCfOM3XyN1EW-sL → MNJWFb2jLRrxRKGFNK6Hy}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{HgG0mizCfOM3XyN1EW-sL → MNJWFb2jLRrxRKGFNK6Hy}/_ssgManifest.js +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { readFileSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { dirname, join } from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
|
-
import { NAV_TRANSLATIONS, LANGUAGES } from "./config";
|
|
4
|
+
import { getLanguageByCode, NAV_TRANSLATIONS, LANGUAGES } from "./config";
|
|
5
5
|
|
|
6
6
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
7
7
|
const DOCS_JSON_PATH = join(__dirname, "..", "..", "docs", "docs.json");
|
|
@@ -21,6 +21,57 @@ interface LanguageNav {
|
|
|
21
21
|
tabs: NavTab[];
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
export interface NavigationPageReference {
|
|
25
|
+
page: string;
|
|
26
|
+
language?: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Collect page references from flat, localized, or multi-product navigation. */
|
|
30
|
+
export function getNavigationPageReferences(
|
|
31
|
+
navigation: unknown,
|
|
32
|
+
): NavigationPageReference[] {
|
|
33
|
+
const references: NavigationPageReference[] = [];
|
|
34
|
+
const childKeys = [
|
|
35
|
+
"products",
|
|
36
|
+
"languages",
|
|
37
|
+
"tabs",
|
|
38
|
+
"groups",
|
|
39
|
+
"anchors",
|
|
40
|
+
"dropdowns",
|
|
41
|
+
"versions",
|
|
42
|
+
"menu",
|
|
43
|
+
];
|
|
44
|
+
|
|
45
|
+
function walk(value: unknown, inheritedLanguage?: string): void {
|
|
46
|
+
if (Array.isArray(value)) {
|
|
47
|
+
for (const item of value) walk(item, inheritedLanguage);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (!value || typeof value !== "object") return;
|
|
51
|
+
|
|
52
|
+
const entry = value as Record<string, unknown>;
|
|
53
|
+
const language =
|
|
54
|
+
typeof entry.language === "string" ? entry.language : inheritedLanguage;
|
|
55
|
+
|
|
56
|
+
if (Array.isArray(entry.pages)) {
|
|
57
|
+
for (const page of entry.pages) {
|
|
58
|
+
if (typeof page === "string") {
|
|
59
|
+
references.push({ page, language });
|
|
60
|
+
} else {
|
|
61
|
+
walk(page, language);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
for (const key of childKeys) {
|
|
67
|
+
if (key !== "pages" && entry[key]) walk(entry[key], language);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
walk(navigation);
|
|
72
|
+
return references;
|
|
73
|
+
}
|
|
74
|
+
|
|
24
75
|
/**
|
|
25
76
|
* Build a navigation entry for a specific language by transforming the
|
|
26
77
|
* English navigation structure.
|
|
@@ -54,7 +105,10 @@ export function buildLanguageNav(
|
|
|
54
105
|
})),
|
|
55
106
|
}));
|
|
56
107
|
|
|
57
|
-
return {
|
|
108
|
+
return {
|
|
109
|
+
language: getLanguageByCode(lang)?.mintlifyCode ?? lang,
|
|
110
|
+
tabs,
|
|
111
|
+
};
|
|
58
112
|
}
|
|
59
113
|
|
|
60
114
|
/**
|
|
@@ -78,6 +132,28 @@ export function generateLanguagesArray(
|
|
|
78
132
|
return [english, ...others];
|
|
79
133
|
}
|
|
80
134
|
|
|
135
|
+
/** Localize every product that has English tabs or an English language entry. */
|
|
136
|
+
export function localizeProductsNavigation(
|
|
137
|
+
products: unknown[],
|
|
138
|
+
langCodes: string[],
|
|
139
|
+
): Record<string, unknown>[] {
|
|
140
|
+
return products.map((value) => {
|
|
141
|
+
const product = value as Record<string, unknown>;
|
|
142
|
+
const existingLanguages = product.languages as LanguageNav[] | undefined;
|
|
143
|
+
const englishTabs = existingLanguages
|
|
144
|
+
? existingLanguages.find((entry) => entry.language === "en")?.tabs
|
|
145
|
+
: (product.tabs as NavTab[] | undefined);
|
|
146
|
+
|
|
147
|
+
if (!englishTabs) return product;
|
|
148
|
+
|
|
149
|
+
const { tabs: _tabs, ...rest } = product;
|
|
150
|
+
return {
|
|
151
|
+
...rest,
|
|
152
|
+
languages: generateLanguagesArray(englishTabs, langCodes),
|
|
153
|
+
};
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
|
|
81
157
|
/**
|
|
82
158
|
* Update docs.json to use the languages array structure.
|
|
83
159
|
*/
|
|
@@ -85,18 +161,23 @@ export function updateDocsJson(langCodes: string[]): void {
|
|
|
85
161
|
const config = readDocsConfig();
|
|
86
162
|
const nav = config.navigation as Record<string, unknown>;
|
|
87
163
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
164
|
+
if (Array.isArray(nav.products)) {
|
|
165
|
+
nav.products = localizeProductsNavigation(nav.products, langCodes);
|
|
166
|
+
config.navigation = nav;
|
|
167
|
+
writeFileSync(DOCS_JSON_PATH, JSON.stringify(config, null, 2) + "\n");
|
|
168
|
+
return;
|
|
92
169
|
}
|
|
93
170
|
|
|
94
|
-
|
|
95
|
-
const
|
|
171
|
+
const existingLanguages = nav.languages as LanguageNav[] | undefined;
|
|
172
|
+
const englishTabs = existingLanguages
|
|
173
|
+
? existingLanguages.find((entry) => entry.language === "en")?.tabs
|
|
174
|
+
: (nav.tabs as NavTab[] | undefined);
|
|
175
|
+
if (!englishTabs) {
|
|
176
|
+
throw new Error("No English navigation tabs found in docs.json");
|
|
177
|
+
}
|
|
96
178
|
|
|
97
|
-
// Replace tabs with languages, preserve global
|
|
98
179
|
const newNav: Record<string, unknown> = {
|
|
99
|
-
languages,
|
|
180
|
+
languages: generateLanguagesArray(englishTabs, langCodes),
|
|
100
181
|
};
|
|
101
182
|
if (nav.global) {
|
|
102
183
|
newNav.global = nav.global;
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
export interface LanguageConfig {
|
|
2
|
+
/** Internal code used for folders, cache keys, and translation routing. */
|
|
2
3
|
code: string;
|
|
4
|
+
/** Mintlify locale when its canonical casing differs from `code`. */
|
|
5
|
+
mintlifyCode?: string;
|
|
3
6
|
name: string;
|
|
4
7
|
nativeName: string;
|
|
5
8
|
tier: 1 | 2 | 3;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Antigravity (agy) transcript adapter — AUDIT (Pillar 2).
|
|
3
|
+
*
|
|
4
|
+
* Antigravity writes plain-JSONL transcripts at
|
|
5
|
+
* `~/.gemini/antigravity-cli/brain/<conversationId>/.system_generated/logs/transcript_full.jsonl`
|
|
6
|
+
* (one step per line), with a SQLite conversation index at
|
|
7
|
+
* `conversation_summaries.db`. Verified live against agy v1.1.2.
|
|
8
|
+
* lib/antigravity-sessions.ts enumerates + parses the transcripts into the
|
|
9
|
+
* shared LogEntry[] shape; lib/antigravity-projects.ts reads the SQLite index
|
|
10
|
+
* for cwd/title enrichment. `logEntriesToEvents` handles the rest (tool-name +
|
|
11
|
+
* tool-input canonicalization via the ANTIGRAVITY_* maps).
|
|
12
|
+
*/
|
|
13
|
+
import { readFile } from "node:fs/promises";
|
|
14
|
+
import {
|
|
15
|
+
listAntigravityTranscripts,
|
|
16
|
+
antigravityLinesToLogEntries,
|
|
17
|
+
} from "../../../lib/antigravity-sessions";
|
|
18
|
+
import { getAntigravityIndex } from "../../../lib/antigravity-projects";
|
|
19
|
+
import { parseRawLines } from "../../../lib/log-entries";
|
|
20
|
+
import { encodeFolderName } from "../../../lib/paths";
|
|
21
|
+
import type { NormalizedToolEvent, TranscriptMetadata } from "../types";
|
|
22
|
+
import type { ListOpts } from "./claude";
|
|
23
|
+
import { logEntriesToEvents } from "./shared";
|
|
24
|
+
|
|
25
|
+
export async function listAntigravityTranscriptMetadata(
|
|
26
|
+
opts: ListOpts = {},
|
|
27
|
+
): Promise<TranscriptMetadata[]> {
|
|
28
|
+
const projectFilter = opts.projects ? new Set(opts.projects) : null;
|
|
29
|
+
const sinceMs = opts.sinceMs ?? 0;
|
|
30
|
+
const out: TranscriptMetadata[] = [];
|
|
31
|
+
|
|
32
|
+
const index = await getAntigravityIndex();
|
|
33
|
+
|
|
34
|
+
for (const t of listAntigravityTranscripts()) {
|
|
35
|
+
if (t.mtimeMs < sinceMs) continue;
|
|
36
|
+
const cwd = index.get(t.conversationId)?.cwd;
|
|
37
|
+
// `audit --project <cwd>` filters on the conversation's workspace cwd.
|
|
38
|
+
if (projectFilter && (!cwd || !projectFilter.has(cwd))) continue;
|
|
39
|
+
out.push({
|
|
40
|
+
cli: "antigravity",
|
|
41
|
+
projectName: cwd ? encodeFolderName(cwd) : "antigravity",
|
|
42
|
+
sessionId: t.conversationId,
|
|
43
|
+
transcriptPath: t.transcriptPath,
|
|
44
|
+
mtimeMs: t.mtimeMs,
|
|
45
|
+
sizeBytes: t.sizeBytes,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
return out;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export async function streamAntigravityEvents(
|
|
52
|
+
meta: TranscriptMetadata,
|
|
53
|
+
): Promise<NormalizedToolEvent[]> {
|
|
54
|
+
let content: string;
|
|
55
|
+
try {
|
|
56
|
+
content = await readFile(meta.transcriptPath, "utf-8");
|
|
57
|
+
} catch {
|
|
58
|
+
return [];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const rawLines = parseRawLines(content, "session");
|
|
62
|
+
const entries = antigravityLinesToLogEntries(rawLines, "session");
|
|
63
|
+
|
|
64
|
+
// Recover cwd from the transcript's first run_command Cwd (falls back to "").
|
|
65
|
+
let cwd = "";
|
|
66
|
+
for (const line of rawLines) {
|
|
67
|
+
if (!line || typeof line !== "object") continue;
|
|
68
|
+
const calls = (line as Record<string, unknown>).tool_calls;
|
|
69
|
+
if (!Array.isArray(calls)) continue;
|
|
70
|
+
for (const call of calls) {
|
|
71
|
+
const args = call && typeof call === "object" ? (call as Record<string, unknown>).args : undefined;
|
|
72
|
+
const c = args && typeof args === "object" ? (args as Record<string, unknown>).Cwd : undefined;
|
|
73
|
+
if (typeof c === "string" && c.length > 0) {
|
|
74
|
+
cwd = c;
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (cwd) break;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return logEntriesToEvents(entries, {
|
|
82
|
+
cli: "antigravity",
|
|
83
|
+
sessionId: meta.sessionId,
|
|
84
|
+
transcriptPath: meta.transcriptPath,
|
|
85
|
+
cwd,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Devin CLI (Cognition) transcript adapter — AUDIT-ONLY (Pillar 2).
|
|
3
|
+
*
|
|
4
|
+
* Devin keeps every session in one SQLite DB at
|
|
5
|
+
* `~/.local/share/devin/cli/sessions.db`. We read it directly via the bundled
|
|
6
|
+
* sql.js reader (lib/devin-projects.ts enumerates the `sessions` table;
|
|
7
|
+
* lib/devin-sessions.ts parses each session's `message_nodes`), producing the
|
|
8
|
+
* same LogEntry[] shape the other adapters do — so `logEntriesToEvents` handles
|
|
9
|
+
* the rest. Unlike Hermes, each Devin session carries a real
|
|
10
|
+
* `working_directory`, so `audit --project <cwd>` filters work.
|
|
11
|
+
*/
|
|
12
|
+
import { getDevinSessions } from "../../../lib/devin-projects";
|
|
13
|
+
import { getDevinSessionLog } from "../../../lib/devin-sessions";
|
|
14
|
+
import type { NormalizedToolEvent, TranscriptMetadata } from "../types";
|
|
15
|
+
import type { ListOpts } from "./claude";
|
|
16
|
+
import { logEntriesToEvents } from "./shared";
|
|
17
|
+
|
|
18
|
+
export async function listDevinTranscriptMetadata(
|
|
19
|
+
opts: ListOpts = {},
|
|
20
|
+
): Promise<TranscriptMetadata[]> {
|
|
21
|
+
const projectFilter = opts.projects ? new Set(opts.projects) : null;
|
|
22
|
+
const sinceMs = opts.sinceMs ?? 0;
|
|
23
|
+
const sessions = await getDevinSessions();
|
|
24
|
+
const out: TranscriptMetadata[] = [];
|
|
25
|
+
for (const s of sessions) {
|
|
26
|
+
if (s.mtimeMs < sinceMs) continue;
|
|
27
|
+
// `audit --project <cwd>` filters on the session's working directory.
|
|
28
|
+
if (projectFilter && (!s.cwd || !projectFilter.has(s.cwd))) continue;
|
|
29
|
+
out.push({
|
|
30
|
+
cli: "devin",
|
|
31
|
+
projectName: s.projectName,
|
|
32
|
+
sessionId: s.sessionId,
|
|
33
|
+
transcriptPath: `devin-db://${s.sessionId}`,
|
|
34
|
+
mtimeMs: s.mtimeMs,
|
|
35
|
+
// mtime advances on each message, so (mtime) forms a real cache key.
|
|
36
|
+
sizeBytes: 0,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
return out;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export async function streamDevinEvents(
|
|
43
|
+
meta: TranscriptMetadata,
|
|
44
|
+
): Promise<NormalizedToolEvent[]> {
|
|
45
|
+
const log = await getDevinSessionLog(meta.sessionId);
|
|
46
|
+
if (!log) return [];
|
|
47
|
+
return logEntriesToEvents(log.entries, {
|
|
48
|
+
cli: "devin",
|
|
49
|
+
sessionId: meta.sessionId,
|
|
50
|
+
transcriptPath: meta.transcriptPath,
|
|
51
|
+
cwd: log.cwd ?? "",
|
|
52
|
+
});
|
|
53
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Factory (droid) transcript adapter — AUDIT (Pillar 2).
|
|
3
|
+
*
|
|
4
|
+
* droid writes real JSONL transcripts at
|
|
5
|
+
* `~/.factory/sessions/<encoded-cwd>/<sessionId>.jsonl` (Claude-style
|
|
6
|
+
* encoded-cwd folders; verified live against droid v0.171.0).
|
|
7
|
+
* lib/factory-sessions.ts enumerates and parses them into the shared
|
|
8
|
+
* LogEntry[] shape, so `logEntriesToEvents` handles the rest.
|
|
9
|
+
*/
|
|
10
|
+
import { readFile } from "node:fs/promises";
|
|
11
|
+
import {
|
|
12
|
+
listFactoryTranscripts,
|
|
13
|
+
factoryLinesToLogEntries,
|
|
14
|
+
} from "../../../lib/factory-sessions";
|
|
15
|
+
import { parseRawLines } from "../../../lib/log-entries";
|
|
16
|
+
import type { NormalizedToolEvent, TranscriptMetadata } from "../types";
|
|
17
|
+
import type { ListOpts } from "./claude";
|
|
18
|
+
import { logEntriesToEvents } from "./shared";
|
|
19
|
+
|
|
20
|
+
export async function listFactoryTranscriptMetadata(
|
|
21
|
+
opts: ListOpts = {},
|
|
22
|
+
): Promise<TranscriptMetadata[]> {
|
|
23
|
+
const projectFilter = opts.projects ? new Set(opts.projects) : null;
|
|
24
|
+
const sinceMs = opts.sinceMs ?? 0;
|
|
25
|
+
const out: TranscriptMetadata[] = [];
|
|
26
|
+
|
|
27
|
+
for (const t of listFactoryTranscripts()) {
|
|
28
|
+
if (t.mtimeMs < sinceMs) continue;
|
|
29
|
+
// `audit --project <cwd>` filters on the decoded working directory.
|
|
30
|
+
if (projectFilter && !projectFilter.has(t.cwd)) continue;
|
|
31
|
+
out.push({
|
|
32
|
+
cli: "factory",
|
|
33
|
+
projectName: t.projectName,
|
|
34
|
+
sessionId: t.sessionId,
|
|
35
|
+
transcriptPath: t.transcriptPath,
|
|
36
|
+
mtimeMs: t.mtimeMs,
|
|
37
|
+
sizeBytes: t.sizeBytes,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
return out;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export async function streamFactoryEvents(
|
|
44
|
+
meta: TranscriptMetadata,
|
|
45
|
+
): Promise<NormalizedToolEvent[]> {
|
|
46
|
+
let content: string;
|
|
47
|
+
try {
|
|
48
|
+
content = await readFile(meta.transcriptPath, "utf-8");
|
|
49
|
+
} catch {
|
|
50
|
+
return [];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const rawLines = parseRawLines(content, "session");
|
|
54
|
+
const entries = factoryLinesToLogEntries(rawLines, "session");
|
|
55
|
+
|
|
56
|
+
// cwd lives on the `type:"session_start"` header line — recover the canonical
|
|
57
|
+
// value rather than re-decoding the (lossy) folder name.
|
|
58
|
+
let cwd = "";
|
|
59
|
+
for (const line of rawLines) {
|
|
60
|
+
if (line && typeof line === "object" && (line as Record<string, unknown>).type === "session_start") {
|
|
61
|
+
const c = (line as Record<string, unknown>).cwd;
|
|
62
|
+
if (typeof c === "string" && c.length > 0) {
|
|
63
|
+
cwd = c;
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return logEntriesToEvents(entries, {
|
|
70
|
+
cli: "factory",
|
|
71
|
+
sessionId: meta.sessionId,
|
|
72
|
+
transcriptPath: meta.transcriptPath,
|
|
73
|
+
cwd,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Goose (codename goose, Block) transcript adapter — AUDIT-ONLY (Pillar 2).
|
|
3
|
+
*
|
|
4
|
+
* Goose keeps every session in one SQLite DB at
|
|
5
|
+
* `~/.local/share/goose/sessions/sessions.db`. We read it directly via the
|
|
6
|
+
* bundled sql.js reader (lib/goose-projects.ts enumerates the `sessions` table;
|
|
7
|
+
* lib/goose-sessions.ts parses each session's `messages`), producing the same
|
|
8
|
+
* LogEntry[] shape the other adapters do — so `logEntriesToEvents` handles the
|
|
9
|
+
* rest. Like Devin, each Goose session carries a real `working_dir`, so
|
|
10
|
+
* `audit --project <cwd>` filters work (unlike the cwd-less Hermes gateway).
|
|
11
|
+
*/
|
|
12
|
+
import { getGooseSessions } from "../../../lib/goose-projects";
|
|
13
|
+
import { getGooseSessionLog } from "../../../lib/goose-sessions";
|
|
14
|
+
import type { NormalizedToolEvent, TranscriptMetadata } from "../types";
|
|
15
|
+
import type { ListOpts } from "./claude";
|
|
16
|
+
import { logEntriesToEvents } from "./shared";
|
|
17
|
+
|
|
18
|
+
export async function listGooseTranscriptMetadata(
|
|
19
|
+
opts: ListOpts = {},
|
|
20
|
+
): Promise<TranscriptMetadata[]> {
|
|
21
|
+
const projectFilter = opts.projects ? new Set(opts.projects) : null;
|
|
22
|
+
const sinceMs = opts.sinceMs ?? 0;
|
|
23
|
+
const sessions = await getGooseSessions();
|
|
24
|
+
const out: TranscriptMetadata[] = [];
|
|
25
|
+
for (const s of sessions) {
|
|
26
|
+
if (s.mtimeMs < sinceMs) continue;
|
|
27
|
+
// `audit --project <cwd>` filters on the session's working directory.
|
|
28
|
+
if (projectFilter && (!s.cwd || !projectFilter.has(s.cwd))) continue;
|
|
29
|
+
out.push({
|
|
30
|
+
cli: "goose",
|
|
31
|
+
projectName: s.projectName,
|
|
32
|
+
sessionId: s.sessionId,
|
|
33
|
+
transcriptPath: `goose-db://${s.sessionId}`,
|
|
34
|
+
mtimeMs: s.mtimeMs,
|
|
35
|
+
// mtime advances on each message, so (mtime) forms a real cache key.
|
|
36
|
+
sizeBytes: 0,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
return out;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export async function streamGooseEvents(
|
|
43
|
+
meta: TranscriptMetadata,
|
|
44
|
+
): Promise<NormalizedToolEvent[]> {
|
|
45
|
+
const log = await getGooseSessionLog(meta.sessionId);
|
|
46
|
+
if (!log) return [];
|
|
47
|
+
return logEntriesToEvents(log.entries, {
|
|
48
|
+
cli: "goose",
|
|
49
|
+
sessionId: meta.sessionId,
|
|
50
|
+
transcriptPath: meta.transcriptPath,
|
|
51
|
+
cwd: log.cwd ?? "",
|
|
52
|
+
});
|
|
53
|
+
}
|
|
@@ -17,8 +17,12 @@ import { listCopilotTranscriptMetadata, streamCopilotEvents } from "./copilot";
|
|
|
17
17
|
import { listCursorTranscriptMetadata, streamCursorEvents } from "./cursor";
|
|
18
18
|
import { listOpenCodeTranscriptMetadata, streamOpenCodeEvents } from "./opencode";
|
|
19
19
|
import { listPiTranscriptMetadata, streamPiEvents } from "./pi";
|
|
20
|
-
import { listGeminiTranscriptMetadata, streamGeminiEvents } from "./gemini";
|
|
21
20
|
import { listHermesTranscriptMetadata, streamHermesEvents } from "./hermes";
|
|
21
|
+
import { listOpenClawTranscriptMetadata, streamOpenClawEvents } from "./openclaw";
|
|
22
|
+
import { listFactoryTranscriptMetadata, streamFactoryEvents } from "./factory";
|
|
23
|
+
import { listAntigravityTranscriptMetadata, streamAntigravityEvents } from "./antigravity";
|
|
24
|
+
import { listDevinTranscriptMetadata, streamDevinEvents } from "./devin";
|
|
25
|
+
import { listGooseTranscriptMetadata, streamGooseEvents } from "./goose";
|
|
22
26
|
|
|
23
27
|
export type { ListOpts };
|
|
24
28
|
|
|
@@ -59,16 +63,36 @@ export const ADAPTERS: Record<IntegrationType, CliAdapter> = {
|
|
|
59
63
|
listTranscripts: listPiTranscriptMetadata,
|
|
60
64
|
streamEvents: streamPiEvents,
|
|
61
65
|
},
|
|
62
|
-
gemini: {
|
|
63
|
-
cli: "gemini",
|
|
64
|
-
listTranscripts: listGeminiTranscriptMetadata,
|
|
65
|
-
streamEvents: streamGeminiEvents,
|
|
66
|
-
},
|
|
67
66
|
hermes: {
|
|
68
67
|
cli: "hermes",
|
|
69
68
|
listTranscripts: listHermesTranscriptMetadata,
|
|
70
69
|
streamEvents: streamHermesEvents,
|
|
71
70
|
},
|
|
71
|
+
openclaw: {
|
|
72
|
+
cli: "openclaw",
|
|
73
|
+
listTranscripts: listOpenClawTranscriptMetadata,
|
|
74
|
+
streamEvents: streamOpenClawEvents,
|
|
75
|
+
},
|
|
76
|
+
factory: {
|
|
77
|
+
cli: "factory",
|
|
78
|
+
listTranscripts: listFactoryTranscriptMetadata,
|
|
79
|
+
streamEvents: streamFactoryEvents,
|
|
80
|
+
},
|
|
81
|
+
devin: {
|
|
82
|
+
cli: "devin",
|
|
83
|
+
listTranscripts: listDevinTranscriptMetadata,
|
|
84
|
+
streamEvents: streamDevinEvents,
|
|
85
|
+
},
|
|
86
|
+
antigravity: {
|
|
87
|
+
cli: "antigravity",
|
|
88
|
+
listTranscripts: listAntigravityTranscriptMetadata,
|
|
89
|
+
streamEvents: streamAntigravityEvents,
|
|
90
|
+
},
|
|
91
|
+
goose: {
|
|
92
|
+
cli: "goose",
|
|
93
|
+
listTranscripts: listGooseTranscriptMetadata,
|
|
94
|
+
streamEvents: streamGooseEvents,
|
|
95
|
+
},
|
|
72
96
|
};
|
|
73
97
|
|
|
74
98
|
export function getAdapter(cli: IntegrationType): CliAdapter {
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenClaw (openclaw gateway) transcript adapter — AUDIT (Pillar 2).
|
|
3
|
+
*
|
|
4
|
+
* OpenClaw writes real JSONL transcripts at
|
|
5
|
+
* `~/.openclaw/agents/<agentId>/sessions/<uuid>.jsonl` (verified live against
|
|
6
|
+
* v2026.7.1). lib/openclaw-sessions.ts enumerates and parses them into the
|
|
7
|
+
* shared LogEntry[] shape, so `logEntriesToEvents` handles the rest.
|
|
8
|
+
*
|
|
9
|
+
* Gateway sessions run in the container workspace, not a host repo, so they
|
|
10
|
+
* group by agentId (`openclaw:<agentId>`) and contribute nothing to a
|
|
11
|
+
* cwd-scoped audit.
|
|
12
|
+
*/
|
|
13
|
+
import {
|
|
14
|
+
listOpenClawTranscripts,
|
|
15
|
+
getOpenClawSessionLog,
|
|
16
|
+
} from "../../../lib/openclaw-sessions";
|
|
17
|
+
import type { NormalizedToolEvent, TranscriptMetadata } from "../types";
|
|
18
|
+
import type { ListOpts } from "./claude";
|
|
19
|
+
import { logEntriesToEvents } from "./shared";
|
|
20
|
+
|
|
21
|
+
export async function listOpenClawTranscriptMetadata(
|
|
22
|
+
opts: ListOpts = {},
|
|
23
|
+
): Promise<TranscriptMetadata[]> {
|
|
24
|
+
// `audit --project <cwd>` filters on working directory; gateway sessions run
|
|
25
|
+
// in the container workspace, not a host repo, so OpenClaw contributes
|
|
26
|
+
// nothing to a cwd-scoped audit.
|
|
27
|
+
if (opts.projects && opts.projects.length > 0) return [];
|
|
28
|
+
|
|
29
|
+
const sinceMs = opts.sinceMs ?? 0;
|
|
30
|
+
const out: TranscriptMetadata[] = [];
|
|
31
|
+
for (const t of listOpenClawTranscripts()) {
|
|
32
|
+
if (t.mtimeMs < sinceMs) continue;
|
|
33
|
+
out.push({
|
|
34
|
+
cli: "openclaw",
|
|
35
|
+
projectName: `openclaw:${t.agentId}`,
|
|
36
|
+
sessionId: t.sessionId,
|
|
37
|
+
transcriptPath: t.transcriptPath,
|
|
38
|
+
mtimeMs: t.mtimeMs,
|
|
39
|
+
sizeBytes: t.sizeBytes,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
return out;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export async function streamOpenClawEvents(
|
|
46
|
+
meta: TranscriptMetadata,
|
|
47
|
+
): Promise<NormalizedToolEvent[]> {
|
|
48
|
+
const log = await getOpenClawSessionLog(meta.sessionId);
|
|
49
|
+
if (!log) return [];
|
|
50
|
+
return logEntriesToEvents(log.entries, {
|
|
51
|
+
cli: "openclaw",
|
|
52
|
+
sessionId: meta.sessionId,
|
|
53
|
+
transcriptPath: meta.transcriptPath,
|
|
54
|
+
cwd: log.cwd ?? "",
|
|
55
|
+
});
|
|
56
|
+
}
|
package/src/audit/cli.ts
CHANGED
|
@@ -20,6 +20,7 @@ import { writeDashboardCache } from "./dashboard-cache";
|
|
|
20
20
|
import type { AuditResult, RunAuditOptions } from "./types";
|
|
21
21
|
import { trackHookEvent } from "../hooks/hook-telemetry";
|
|
22
22
|
import { getInstanceId } from "../../lib/telemetry-id";
|
|
23
|
+
import { sanitizeErrorMessage } from "../../lib/telemetry-sanitize";
|
|
23
24
|
import { openWhenReady } from "./open-browser";
|
|
24
25
|
|
|
25
26
|
/** Port the bundled dashboard binds to. Matches `scripts/launch.ts`'s default
|
|
@@ -49,7 +50,7 @@ USAGE
|
|
|
49
50
|
|
|
50
51
|
WHAT IT DOES
|
|
51
52
|
1. Scans past sessions from every installed agent CLI (Claude, Codex, Cursor,
|
|
52
|
-
Copilot, OpenCode, Pi
|
|
53
|
+
Copilot, OpenCode, Pi) — entirely on your machine.
|
|
53
54
|
2. Starts the local dashboard and opens
|
|
54
55
|
http://localhost:${DASHBOARD_PORT}/audit with your results.
|
|
55
56
|
|
|
@@ -236,6 +237,47 @@ function printSummary(result: AuditResult): void {
|
|
|
236
237
|
for (const line of buildSummary(result)) process.stdout.write(` ${line}\n`);
|
|
237
238
|
}
|
|
238
239
|
|
|
240
|
+
// ── Post-setup background audit ────────────────────────────────────────────────
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Run the audit *pipeline* (scan + cache write + summary) once the setup flow
|
|
244
|
+
* completes, right before the dashboard boots. Pre-warms
|
|
245
|
+
* `~/.failproofai/audit-dashboard.json` so the dashboard renders instantly, and
|
|
246
|
+
* immediately shows the user what's slipping through.
|
|
247
|
+
*
|
|
248
|
+
* Shows the same animated stages as `failproofai audit`. The scan runs to
|
|
249
|
+
* completion; Ctrl+C interrupts it the usual way (default SIGINT). Best-effort:
|
|
250
|
+
* never throws, never exits the process; the caller boots the dashboard
|
|
251
|
+
* afterward. Opt out with `FAILPROOFAI_NO_AUTO_AUDIT=1`.
|
|
252
|
+
*/
|
|
253
|
+
export async function runPostSetupAudit(): Promise<void> {
|
|
254
|
+
if (process.env.FAILPROOFAI_NO_AUTO_AUDIT === "1") return;
|
|
255
|
+
|
|
256
|
+
process.stdout.write(
|
|
257
|
+
`\n ${c(PINK, "✦")} ${c(BOLD, "failproofai audit now running")} ${c(DIM, "· ctrl+c to stop")}\n\n`,
|
|
258
|
+
);
|
|
259
|
+
|
|
260
|
+
let result: AuditResult;
|
|
261
|
+
try {
|
|
262
|
+
result = await runWithProgress({});
|
|
263
|
+
} catch {
|
|
264
|
+
process.stdout.write(
|
|
265
|
+
` ${c(PINK, "!")} ${c(DIM, "audit couldn't finish — run")} ${c(CYAN, "failproofai audit")} ${c(DIM, "later.")}\n\n`,
|
|
266
|
+
);
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
if (result.eventsScanned === 0) {
|
|
271
|
+
process.stdout.write(
|
|
272
|
+
`\n ${c(DIM, "no agent sessions to audit yet — come back after using your agent.")}\n\n`,
|
|
273
|
+
);
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
writeDashboardCache({}, result);
|
|
277
|
+
printSummary(result);
|
|
278
|
+
process.stdout.write("\n");
|
|
279
|
+
}
|
|
280
|
+
|
|
239
281
|
// ── Entry point ──────────────────────────────────────────────────────────────
|
|
240
282
|
|
|
241
283
|
export async function runAuditCli(args: string[]): Promise<void> {
|
|
@@ -275,6 +317,7 @@ export async function runAuditCli(args: string[]): Promise<void> {
|
|
|
275
317
|
await trackHookEvent(instanceId, "cli_audit_failed", {
|
|
276
318
|
source: "cli",
|
|
277
319
|
error_type: err instanceof Error ? err.name : "unknown",
|
|
320
|
+
error_message: sanitizeErrorMessage(err),
|
|
278
321
|
});
|
|
279
322
|
die(`Audit failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
280
323
|
}
|
package/src/audit/report.ts
CHANGED
|
@@ -273,7 +273,7 @@ export function formatMarkdown(result: AuditResult): string {
|
|
|
273
273
|
);
|
|
274
274
|
}
|
|
275
275
|
out.push("");
|
|
276
|
-
out.push("> [failproofai](https://github.com/FailproofAI/failproofai) is a hook-based policy engine for Claude Code, Codex, Copilot, Cursor, OpenCode,
|
|
276
|
+
out.push("> [failproofai](https://github.com/FailproofAI/failproofai) is a hook-based policy engine for Claude Code, Codex, Copilot, Cursor, OpenCode, and Pi. The `audit` command replays past agent sessions through every builtin policy to surface patterns that were (or could've been) stopped.");
|
|
277
277
|
out.push("");
|
|
278
278
|
|
|
279
279
|
if (totalHits === 0) return out.join("\n");
|
package/src/audit/types.ts
CHANGED
|
@@ -24,7 +24,7 @@ export interface NormalizedToolEvent {
|
|
|
24
24
|
toolName: string;
|
|
25
25
|
/** Canonicalized tool input (snake_case keys for OpenCode/Pi). */
|
|
26
26
|
toolInput: Record<string, unknown>;
|
|
27
|
-
/** Pre-canonicalization tool name (e.g. "
|
|
27
|
+
/** Pre-canonicalization tool name (e.g. "exec" for OpenClaw). */
|
|
28
28
|
rawToolName: string;
|
|
29
29
|
/**
|
|
30
30
|
* Result text from the matching tool_result block, if present in the
|
|
@@ -53,9 +53,9 @@ function isAgentInternalPath(resolved: string): boolean {
|
|
|
53
53
|
* • Pi: `.pi/settings.json` (project) and `.pi/agent/settings.json`
|
|
54
54
|
* (user); also the Pi-managed extension dir
|
|
55
55
|
* `.pi/extensions/` / `.pi/agent/extensions/`.
|
|
56
|
-
* •
|
|
57
|
-
*
|
|
58
|
-
*
|
|
56
|
+
* • Antigravity CLI (agy): reuses `~/.gemini/` — `~/.gemini/settings.json`
|
|
57
|
+
* and the customization-root hook config
|
|
58
|
+
* `~/.gemini/config/hooks.json`.
|
|
59
59
|
* These must NEVER be edited by the agent itself — that would let it disable
|
|
60
60
|
* its own protections.
|
|
61
61
|
*/
|
|
@@ -74,9 +74,9 @@ function isAgentSettingsFile(resolved: string): boolean {
|
|
|
74
74
|
// Pi: settings + extensions dirs (project and user-scope variants).
|
|
75
75
|
if (/[\\/]\.pi[\\/](?:agent[\\/])?settings\.json$/.test(resolved)) return true;
|
|
76
76
|
if (/[\\/]\.pi[\\/](?:agent[\\/])?extensions[\\/]/.test(resolved)) return true;
|
|
77
|
-
//
|
|
77
|
+
// Antigravity (agy) reuses ~/.gemini/: settings.json + the customization-root hooks.json.
|
|
78
78
|
if (/[\\/]\.gemini[\\/]settings\.json$/.test(resolved)) return true;
|
|
79
|
-
if (/[\\/]\.gemini[\\/]
|
|
79
|
+
if (/[\\/]\.gemini[\\/]config[\\/]hooks\.json$/.test(resolved)) return true;
|
|
80
80
|
return false;
|
|
81
81
|
}
|
|
82
82
|
|