failproofai 0.0.13 → 0.0.14-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/.codex/hooks.json +6 -6
- package/.next/standalone/.cursor/hooks.json +6 -6
- package/.next/standalone/.factory/hooks.json +112 -0
- package/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/build-manifest.json +5 -5
- package/.next/standalone/.next/prerender-manifest.json +3 -3
- package/.next/standalone/.next/required-server-files.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page.js.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/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page.js.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/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
- package/.next/standalone/.next/server/app/audit/page.js.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/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/policies/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +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/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page.js +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/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js +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/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/projects/page.js +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]__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]__09q1168._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__108slqn._.js → [root-of-the-server]__0brjczq._.js} +2 -2
- 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]__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]__07iom4f._.js → [root-of-the-server]__0wp9w6i._.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]__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]__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/_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_087bt9w._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_1fvisnp._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_209u41o._.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_13p7zob.js → node_modules_html-to-image_es_index_12rjfea.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 +5 -5
- 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/{13f1kmjea-0md.js → 02jcotghcxrbu.js} +1 -1
- package/.next/standalone/.next/static/chunks/{30ysv-_8jj052.js → 0d5lypu1zs21r.js} +1 -1
- package/.next/standalone/.next/static/chunks/0emg30_6svycu.js +1 -0
- package/.next/standalone/.next/static/chunks/0o9wpnze1ey8y.js +6 -0
- package/.next/standalone/.next/static/chunks/{05apzuand0c22.js → 1359o5785rmve.js} +2 -2
- package/.next/standalone/.next/static/chunks/20tuctw38jbgw.js +1 -0
- package/.next/standalone/.next/static/chunks/{0vc0eak148vo6.js → 2ldhnaweu9ew3.js} +1 -1
- package/.next/standalone/.next/static/chunks/{23c7v2svx90dp.js → 2vav_x0_336ds.js} +1 -1
- package/.next/standalone/.next/static/chunks/3-ogr79xqbw0h.js +1 -0
- package/.next/standalone/.next/static/chunks/36j05kb2x323i.css +2 -0
- package/.next/standalone/.next/static/chunks/3cg7x0joi2b98.js +1 -0
- package/.next/standalone/.next/static/chunks/{36wdtkgdf0zrd.js → 3k87p-tijud-4.js} +1 -1
- package/.next/standalone/.next/static/chunks/{2cejn75gug3j8.js → 3kmaqcp7rldad.js} +1 -1
- package/.next/standalone/.next/static/chunks/{turbopack-0vavqo2d-tlt3.js → turbopack-10hj8t5pf33tu.js} +1 -1
- package/.next/standalone/.opencode/plugins/failproofai.mjs +30 -11
- 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/components/global-error-listeners.tsx +27 -0
- 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/ci/cli-integration/Dockerfile +47 -0
- package/.next/standalone/ci/cli-integration/README.md +69 -0
- package/.next/standalone/ci/cli-integration/canary-policies.mjs +45 -0
- package/.next/standalone/ci/cli-integration/capture-tokens.sh +48 -0
- package/.next/standalone/ci/cli-integration/inject-tokens.sh +44 -0
- package/.next/standalone/ci/cli-integration/install-clis.sh +91 -0
- package/.next/standalone/ci/cli-integration/probe-cli.sh +208 -0
- package/.next/standalone/ci/cli-integration/report.js +74 -0
- package/.next/standalone/ci/cli-integration/run.sh +107 -0
- package/.next/standalone/components/navbar.tsx +5 -11
- package/.next/standalone/components/reach-developers.tsx +2 -2
- package/.next/standalone/docker-hook-sync/Dockerfile +8 -4
- 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/error-origin.ts +67 -0
- 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/install-check.ts +231 -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 +2 -3
- package/.next/standalone/server.js +1 -1
- package/README.md +94 -62
- package/bin/failproofai.mjs +98 -30
- package/dist/cli.mjs +12499 -9243
- 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/error-origin.ts +67 -0
- 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/install-check.ts +231 -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 +2 -3
- package/scripts/dev-hook.mjs +292 -0
- package/scripts/install-diagnosis.mjs +5 -8
- package/scripts/install-telemetry.mjs +12 -4
- package/scripts/launch.ts +4 -8
- package/scripts/sync-agent-cli-harnesses-prompt.md +7 -10
- package/scripts/translate-docs/cli.ts +120 -53
- package/scripts/translate-docs/config.ts +57 -13
- package/scripts/translate-docs/mdx-translator.ts +177 -28
- package/scripts/translate-docs/mintlify-nav.ts +91 -10
- package/scripts/translate-docs/readme-translator.ts +13 -5
- package/scripts/translate-docs/translator.ts +38 -2
- package/scripts/translate-docs/types.ts +3 -0
- package/scripts/validate-mdx.ts +12 -4
- 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 +83 -8
- 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/0nrah-qv6smeg.js +0 -6
- package/.next/standalone/.next/static/chunks/0wtagd8a5gwq-.js +0 -1
- package/.next/standalone/.next/static/chunks/1c8i78p7t1i-5.js +0 -1
- package/.next/standalone/.next/static/chunks/25qr0e6ez0ei0.js +0 -1
- package/.next/standalone/.next/static/chunks/25s52un3k_wht.css +0 -2
- 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/scripts/postinstall.mjs +0 -243
- package/scripts/preuninstall.mjs +0 -131
- package/src/audit/cli-adapters/gemini.ts +0 -51
- package/src/hooks/first-run-nudge.ts +0 -146
- /package/.next/standalone/.next/static/{kmzdjTLVs6LqsfyOaUf69 → LkN-JjmhKGmL-WklH7WVi}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{kmzdjTLVs6LqsfyOaUf69 → LkN-JjmhKGmL-WklH7WVi}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{kmzdjTLVs6LqsfyOaUf69 → LkN-JjmhKGmL-WklH7WVi}/_ssgManifest.js +0 -0
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
readFileSync,
|
|
3
|
+
writeFileSync,
|
|
4
|
+
mkdirSync,
|
|
5
|
+
readdirSync,
|
|
6
|
+
statSync,
|
|
7
|
+
existsSync,
|
|
8
|
+
rmSync,
|
|
9
|
+
} from "node:fs";
|
|
2
10
|
import { dirname, join, relative } from "node:path";
|
|
3
11
|
import { fileURLToPath } from "node:url";
|
|
4
12
|
import { getLanguageByCode } from "./config";
|
|
@@ -8,6 +16,7 @@ import {
|
|
|
8
16
|
writeCache,
|
|
9
17
|
isCached,
|
|
10
18
|
setCacheEntry,
|
|
19
|
+
getCacheKey,
|
|
11
20
|
} from "./cache";
|
|
12
21
|
import type { TranslationResult, TranslationCache } from "./types";
|
|
13
22
|
|
|
@@ -93,33 +102,82 @@ export function stripStrayTrailingFence(content: string): string {
|
|
|
93
102
|
return lines.join("\n");
|
|
94
103
|
}
|
|
95
104
|
|
|
105
|
+
/**
|
|
106
|
+
* Convert HTML comments (`<!-- ... -->`) into MDX brace-slash-star comments.
|
|
107
|
+
*
|
|
108
|
+
* Mintlify parses every page as MDX, where a top-level HTML comment is a hard
|
|
109
|
+
* syntax error ("Unexpected character `!` (U+0021) before name …") that fails
|
|
110
|
+
* the whole deployment — the remedy Mintlify itself suggests is switching to
|
|
111
|
+
* MDX's own comment form. The root README keeps HTML-comment syntax (GitHub
|
|
112
|
+
* renders it invisibly), so its translated copies under docs/i18n/ have to be
|
|
113
|
+
* rewritten to the MDX form or the docs deploy breaks.
|
|
114
|
+
*
|
|
115
|
+
* Comments inside fenced code blocks are left untouched — there `<!-- -->` is
|
|
116
|
+
* literal sample text (e.g. the plist snippet in the AgentEye collector docs),
|
|
117
|
+
* not a comment to convert. Any `*`+`/` sequence inside a body is broken up so
|
|
118
|
+
* the generated JS block comment can't be terminated early.
|
|
119
|
+
*/
|
|
120
|
+
export function convertHtmlComments(content: string): string {
|
|
121
|
+
// Map out fenced-code ranges so comments inside them stay literal. Per
|
|
122
|
+
// CommonMark, a fence opens with ≥3 backticks or tildes and closes only on a
|
|
123
|
+
// later line using the SAME character and at least the same length. A naive
|
|
124
|
+
// "any ``` toggles" counter misfires on a ```` block that embeds ``` or on
|
|
125
|
+
// mixed ```/~~~ fences — the toggle desyncs and a real top-level comment
|
|
126
|
+
// after the block would be left unconverted (breaking the deploy we fix here).
|
|
127
|
+
const fenceRanges: Array<[number, number]> = [];
|
|
128
|
+
const fenceRe = /^[ \t]*(`{3,}|~{3,})/gm;
|
|
129
|
+
let fenceMatch: RegExpExecArray | null;
|
|
130
|
+
let open: { char: string; length: number; start: number } | null = null;
|
|
131
|
+
while ((fenceMatch = fenceRe.exec(content)) !== null) {
|
|
132
|
+
const marker = fenceMatch[1];
|
|
133
|
+
if (!open) {
|
|
134
|
+
open = { char: marker[0], length: marker.length, start: fenceMatch.index };
|
|
135
|
+
} else if (marker[0] === open.char && marker.length >= open.length) {
|
|
136
|
+
const lineEnd = content.indexOf("\n", fenceRe.lastIndex);
|
|
137
|
+
fenceRanges.push([open.start, lineEnd === -1 ? content.length : lineEnd]);
|
|
138
|
+
open = null;
|
|
139
|
+
}
|
|
140
|
+
// A different char or shorter marker while a fence is open is inner content.
|
|
141
|
+
}
|
|
142
|
+
// An unterminated fence runs to the end of the document.
|
|
143
|
+
if (open) fenceRanges.push([open.start, content.length]);
|
|
144
|
+
|
|
145
|
+
const isInsideFence = (offset: number): boolean =>
|
|
146
|
+
fenceRanges.some(([start, end]) => offset >= start && offset < end);
|
|
147
|
+
|
|
148
|
+
return content.replace(
|
|
149
|
+
/<!--([\s\S]*?)-->/g,
|
|
150
|
+
(match: string, body: string, offset: number) => {
|
|
151
|
+
if (isInsideFence(offset)) return match;
|
|
152
|
+
// Neutralize any `*/` so it can't close the JS block comment early.
|
|
153
|
+
const safeBody = body.replace(/\*\//g, "* /");
|
|
154
|
+
return `{/*${safeBody}*/}`;
|
|
155
|
+
},
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
|
|
96
159
|
/**
|
|
97
160
|
* Rewrite internal doc links to include the language prefix.
|
|
98
161
|
* e.g. href="/built-in-policies" -> href="/es/built-in-policies"
|
|
99
162
|
* [Getting started](/getting-started) -> [Getting started](/es/getting-started)
|
|
100
163
|
*/
|
|
101
|
-
export function rewriteInternalLinks(
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
164
|
+
export function rewriteInternalLinks(content: string, lang: string): string {
|
|
165
|
+
const shouldPreservePath = (path: string): boolean =>
|
|
166
|
+
path.startsWith("/http") ||
|
|
167
|
+
path === "/" ||
|
|
168
|
+
/\.(?:png|jpe?g|gif|svg|webp|ico)(?:#.*)?$/i.test(path);
|
|
169
|
+
|
|
105
170
|
// Rewrite MDX component href attributes pointing to internal paths
|
|
106
|
-
let result = content.replace(
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
if (path.startsWith("/http") || path === "/") return `href="${path}"`;
|
|
111
|
-
return `href="/${lang}${path}"`;
|
|
112
|
-
},
|
|
113
|
-
);
|
|
171
|
+
let result = content.replace(/href="(\/[^"]*?)"/g, (_match, path: string) => {
|
|
172
|
+
if (shouldPreservePath(path)) return `href="${path}"`;
|
|
173
|
+
return `href="/${lang}${path}"`;
|
|
174
|
+
});
|
|
114
175
|
|
|
115
176
|
// Rewrite Markdown links with internal paths
|
|
116
|
-
result = result.replace(
|
|
117
|
-
|
|
118
|
-
(
|
|
119
|
-
|
|
120
|
-
return `](/${lang}${path})`;
|
|
121
|
-
},
|
|
122
|
-
);
|
|
177
|
+
result = result.replace(/\]\((\/[^)]*?)\)/g, (_match, path: string) => {
|
|
178
|
+
if (shouldPreservePath(path)) return `](${path})`;
|
|
179
|
+
return `](/${lang}${path})`;
|
|
180
|
+
});
|
|
123
181
|
|
|
124
182
|
return result;
|
|
125
183
|
}
|
|
@@ -130,7 +188,12 @@ export function rewriteInternalLinks(
|
|
|
130
188
|
export async function translateMdxPage(
|
|
131
189
|
sourcePath: string,
|
|
132
190
|
lang: string,
|
|
133
|
-
options: {
|
|
191
|
+
options: {
|
|
192
|
+
force?: boolean;
|
|
193
|
+
dryRun?: boolean;
|
|
194
|
+
model?: string;
|
|
195
|
+
cache?: TranslationCache;
|
|
196
|
+
} = {},
|
|
134
197
|
): Promise<TranslationResult> {
|
|
135
198
|
const relPath = relative(DOCS_DIR, sourcePath);
|
|
136
199
|
const outputPath = join(DOCS_DIR, lang, relPath);
|
|
@@ -174,9 +237,11 @@ export async function translateMdxPage(
|
|
|
174
237
|
);
|
|
175
238
|
|
|
176
239
|
// Strip stray quote artifacts from JSX attribute values, drop any
|
|
177
|
-
// unmatched trailing code fence the model sometimes hallucinates,
|
|
178
|
-
// rewrite links.
|
|
179
|
-
const sanitized =
|
|
240
|
+
// unmatched trailing code fence the model sometimes hallucinates, convert
|
|
241
|
+
// any HTML comments to MDX comments, then rewrite links.
|
|
242
|
+
const sanitized = convertHtmlComments(
|
|
243
|
+
stripStrayTrailingFence(sanitizeJsxAttributes(translated)),
|
|
244
|
+
);
|
|
180
245
|
const withLinks = rewriteInternalLinks(sanitized, lang);
|
|
181
246
|
|
|
182
247
|
// Write output
|
|
@@ -186,7 +251,14 @@ export async function translateMdxPage(
|
|
|
186
251
|
// Update cache — skip if caller manages the cache (batch write)
|
|
187
252
|
if (!options.cache) {
|
|
188
253
|
const cache = readCache();
|
|
189
|
-
setCacheEntry(
|
|
254
|
+
setCacheEntry(
|
|
255
|
+
cache,
|
|
256
|
+
relPath,
|
|
257
|
+
lang,
|
|
258
|
+
sourceContent,
|
|
259
|
+
inputTokens,
|
|
260
|
+
outputTokens,
|
|
261
|
+
);
|
|
190
262
|
writeCache(cache);
|
|
191
263
|
}
|
|
192
264
|
|
|
@@ -213,7 +285,7 @@ export function getEnglishMdxPages(): string[] {
|
|
|
213
285
|
if (statSync(full).isDirectory()) {
|
|
214
286
|
// Skip language directories at the top level
|
|
215
287
|
if (!prefix && isLanguageDir(entry)) continue;
|
|
216
|
-
// Skip non-
|
|
288
|
+
// Skip non-page asset and localization directories.
|
|
217
289
|
if (!prefix && (entry === "logo" || entry === "i18n")) continue;
|
|
218
290
|
walk(full, rel);
|
|
219
291
|
} else if (entry.endsWith(".mdx")) {
|
|
@@ -226,10 +298,87 @@ export function getEnglishMdxPages(): string[] {
|
|
|
226
298
|
return results.sort();
|
|
227
299
|
}
|
|
228
300
|
|
|
301
|
+
/** Every `.mdx` file under `dir`, recursively. */
|
|
302
|
+
function collectMdxFiles(dir: string): string[] {
|
|
303
|
+
const results: string[] = [];
|
|
304
|
+
for (const entry of readdirSync(dir)) {
|
|
305
|
+
const full = join(dir, entry);
|
|
306
|
+
if (statSync(full).isDirectory()) {
|
|
307
|
+
results.push(...collectMdxFiles(full));
|
|
308
|
+
} else if (entry.endsWith(".mdx")) {
|
|
309
|
+
results.push(full);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
return results;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Delete translated pages whose English source no longer exists, and drop
|
|
317
|
+
* their cache entries.
|
|
318
|
+
*
|
|
319
|
+
* Translation only ever moves forward: `getEnglishMdxPages()` drives what gets
|
|
320
|
+
* written, so when an English page is deleted upstream (the agenteye sync does
|
|
321
|
+
* this routinely) its 14 translations are simply never revisited. They linger
|
|
322
|
+
* on disk and `--update-nav` drops them from `docs.json`, which hides them from
|
|
323
|
+
* the sidebar but does *not* unpublish them — Mintlify still serves and indexes
|
|
324
|
+
* any `.mdx` present, so non-English readers can land on a page documenting a
|
|
325
|
+
* removed feature with no navigation out. Left unpruned these also accumulate
|
|
326
|
+
* as permanent `validate:mdx` surface area for content no English source can
|
|
327
|
+
* ever correct.
|
|
328
|
+
*
|
|
329
|
+
* Returns the docs-dir-relative paths that were (or, when `dryRun`, would be)
|
|
330
|
+
* removed.
|
|
331
|
+
*/
|
|
332
|
+
export function pruneOrphanedTranslations(
|
|
333
|
+
langCodes: string[],
|
|
334
|
+
options: {
|
|
335
|
+
dryRun?: boolean;
|
|
336
|
+
cache?: TranslationCache;
|
|
337
|
+
/** Override the docs root. Tests point this at a fixture tree. */
|
|
338
|
+
docsDir?: string;
|
|
339
|
+
} = {},
|
|
340
|
+
): string[] {
|
|
341
|
+
const docsDir = options.docsDir ?? DOCS_DIR;
|
|
342
|
+
const removed: string[] = [];
|
|
343
|
+
|
|
344
|
+
for (const lang of langCodes) {
|
|
345
|
+
const langDir = join(docsDir, lang);
|
|
346
|
+
if (!existsSync(langDir)) continue;
|
|
347
|
+
|
|
348
|
+
for (const file of collectMdxFiles(langDir)) {
|
|
349
|
+
// docs/zh/agenteye/foo.mdx -> agenteye/foo.mdx -> docs/agenteye/foo.mdx
|
|
350
|
+
const relPath = relative(langDir, file);
|
|
351
|
+
if (existsSync(join(docsDir, relPath))) continue;
|
|
352
|
+
|
|
353
|
+
removed.push(relative(docsDir, file));
|
|
354
|
+
if (!options.dryRun) {
|
|
355
|
+
rmSync(file);
|
|
356
|
+
if (options.cache) {
|
|
357
|
+
delete options.cache.translations[getCacheKey(relPath, lang)];
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
return removed.sort();
|
|
364
|
+
}
|
|
365
|
+
|
|
229
366
|
function isLanguageDir(name: string): boolean {
|
|
230
367
|
const langCodes = [
|
|
231
|
-
"zh",
|
|
232
|
-
"
|
|
368
|
+
"zh",
|
|
369
|
+
"ja",
|
|
370
|
+
"ko",
|
|
371
|
+
"es",
|
|
372
|
+
"pt-br",
|
|
373
|
+
"de",
|
|
374
|
+
"fr",
|
|
375
|
+
"ru",
|
|
376
|
+
"hi",
|
|
377
|
+
"tr",
|
|
378
|
+
"vi",
|
|
379
|
+
"it",
|
|
380
|
+
"ar",
|
|
381
|
+
"he",
|
|
233
382
|
];
|
|
234
383
|
return langCodes.includes(name);
|
|
235
384
|
}
|
|
@@ -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;
|
|
@@ -3,7 +3,11 @@ import { dirname, join } from "node:path";
|
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
import { LANGUAGES, getLanguageByCode } from "./config";
|
|
5
5
|
import { translateContent } from "./translator";
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
stripStrayTrailingFence,
|
|
8
|
+
convertHtmlComments,
|
|
9
|
+
sanitizeJsxAttributes,
|
|
10
|
+
} from "./mdx-translator";
|
|
7
11
|
import { readCache, writeCache, isCached, setCacheEntry } from "./cache";
|
|
8
12
|
import type { TranslationResult, TranslationCache } from "./types";
|
|
9
13
|
|
|
@@ -103,10 +107,14 @@ export async function translateReadme(
|
|
|
103
107
|
const rtlOpen = langConfig.rtl ? `<div dir="rtl">\n\n` : "";
|
|
104
108
|
const rtlClose = langConfig.rtl ? `\n\n</div>` : "";
|
|
105
109
|
|
|
106
|
-
//
|
|
107
|
-
//
|
|
108
|
-
//
|
|
109
|
-
|
|
110
|
+
// Run the same MDX sanitizers as translateMdxPage — the README emits JSX
|
|
111
|
+
// (the logo table), so its output has to satisfy Mintlify's MDX parser too:
|
|
112
|
+
// strip stray quote artifacts from JSX attributes, drop any unmatched
|
|
113
|
+
// trailing code fence the model hallucinates (which would swallow the RTL
|
|
114
|
+
// `</div>` wrapper), and convert HTML comments to MDX comments.
|
|
115
|
+
const cleaned = convertHtmlComments(
|
|
116
|
+
stripStrayTrailingFence(sanitizeJsxAttributes(translated)),
|
|
117
|
+
);
|
|
110
118
|
|
|
111
119
|
const output = `${disclaimer}\n\n${langSelector}\n\n---\n${rtlOpen}\n${cleaned}\n${rtlClose}`;
|
|
112
120
|
|
|
@@ -3,6 +3,28 @@ import { DO_NOT_TRANSLATE } from "./config";
|
|
|
3
3
|
|
|
4
4
|
let client: Anthropic | null = null;
|
|
5
5
|
|
|
6
|
+
// Output-token ceiling for a single translation. The largest English docs
|
|
7
|
+
// (e.g. agenteye/kubernetes-deployment.mdx at ~1400 lines) translate to well
|
|
8
|
+
// beyond the old 16384 cap for verbose target languages. When a response hit
|
|
9
|
+
// that cap it was silently truncated mid-MDX — leaving an unbalanced `{` or an
|
|
10
|
+
// unterminated JSX expression — and the partial output was written to disk and
|
|
11
|
+
// the cache, only to fail `mintlify validate` later in the consolidate job
|
|
12
|
+
// (or, for the very largest pages, to trip the proxy with a "stream ended"
|
|
13
|
+
// error). 64000 is Claude Haiku 4.5's max output (Tier 2/3 languages) and well
|
|
14
|
+
// inside Claude Sonnet 4.6's 128000 (Tier 1), with headroom over the largest
|
|
15
|
+
// observed translation; max_tokens is only a ceiling, so smaller pages still
|
|
16
|
+
// stop at `end_turn` and cost the same. Streaming (below) is what keeps an
|
|
17
|
+
// output this large safe from the SDK's HTTP timeout.
|
|
18
|
+
// Override via TRANSLATE_MAX_TOKENS (integer >= 1; otherwise default).
|
|
19
|
+
const parsedMaxTokens = Number.parseInt(
|
|
20
|
+
process.env.TRANSLATE_MAX_TOKENS ?? "",
|
|
21
|
+
10,
|
|
22
|
+
);
|
|
23
|
+
const MAX_TOKENS =
|
|
24
|
+
Number.isInteger(parsedMaxTokens) && parsedMaxTokens > 0
|
|
25
|
+
? parsedMaxTokens
|
|
26
|
+
: 64000;
|
|
27
|
+
|
|
6
28
|
function getClient(): Anthropic {
|
|
7
29
|
if (!client) {
|
|
8
30
|
// Default 5 retries (up from SDK default of 2) so transient
|
|
@@ -61,7 +83,7 @@ export async function translateContent(
|
|
|
61
83
|
// as `messages.create(...)`, so the rest of the pipeline is unchanged.
|
|
62
84
|
const response = await anthropic.messages.stream({
|
|
63
85
|
model,
|
|
64
|
-
max_tokens:
|
|
86
|
+
max_tokens: MAX_TOKENS,
|
|
65
87
|
system: [{ type: "text", text: SYSTEM_PROMPT, cache_control: { type: "ephemeral" } }],
|
|
66
88
|
messages: [
|
|
67
89
|
{
|
|
@@ -71,8 +93,22 @@ export async function translateContent(
|
|
|
71
93
|
],
|
|
72
94
|
}).finalMessage();
|
|
73
95
|
|
|
96
|
+
// A truncated translation is worse than a failed one: the model stops
|
|
97
|
+
// mid-MDX, and that partial would otherwise be written to disk and cached as
|
|
98
|
+
// if complete, surfacing only as an unbalanced-brace parse error in
|
|
99
|
+
// `mintlify validate`. Fail loudly instead so the caller (cli.ts) records an
|
|
100
|
+
// error, never caches the partial, and excludes this language from the
|
|
101
|
+
// consolidate publish step. If a page ever legitimately needs more than
|
|
102
|
+
// MAX_TOKENS, raise TRANSLATE_MAX_TOKENS or split the source.
|
|
103
|
+
if (response.stop_reason === "max_tokens") {
|
|
104
|
+
throw new Error(
|
|
105
|
+
`translation truncated at max_tokens=${MAX_TOKENS} ` +
|
|
106
|
+
`(output ${response.usage.output_tokens} tokens) — source too large to translate in one request`,
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
74
110
|
const translated =
|
|
75
|
-
response.content[0]
|
|
111
|
+
response.content[0]?.type === "text" ? response.content[0].text : "";
|
|
76
112
|
|
|
77
113
|
return {
|
|
78
114
|
translated,
|
|
@@ -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;
|
package/scripts/validate-mdx.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Validate that every docs
|
|
3
|
-
* runs at deploy time.
|
|
2
|
+
* Validate that every docs page (`.mdx` and `.md` — Mintlify parses both as
|
|
3
|
+
* MDX) parses with the same MDX engine Mintlify runs at deploy time.
|
|
4
4
|
*
|
|
5
5
|
* Why this exists: `mintlify validate` (the existing `docs` CI job) only checks
|
|
6
6
|
* `docs.json` structure and nav-link resolution — it does NOT parse page
|
|
@@ -91,12 +91,20 @@ export function encodeAnnotation(value: string): string {
|
|
|
91
91
|
.replace(/\n/g, "%0A");
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
|
|
94
|
+
/**
|
|
95
|
+
* Collect every Mintlify content page under `dir`. Mintlify runs BOTH `.mdx`
|
|
96
|
+
* and `.md` files through the same MDX pipeline at deploy time, so a `.md` page
|
|
97
|
+
* with an MDX syntax error (e.g. an HTML `<!-- -->` comment, which MDX rejects)
|
|
98
|
+
* fails the deploy exactly like a broken `.mdx` would. The docs/i18n README
|
|
99
|
+
* translations are `.md`, so restricting this walk to `.mdx` let their breakage
|
|
100
|
+
* sail past this safety net and reach the post-merge deploy — collect both.
|
|
101
|
+
*/
|
|
102
|
+
export function collectMdxFiles(dir: string): string[] {
|
|
95
103
|
const out: string[] = [];
|
|
96
104
|
for (const entry of readdirSync(dir)) {
|
|
97
105
|
const full = join(dir, entry);
|
|
98
106
|
if (statSync(full).isDirectory()) out.push(...collectMdxFiles(full));
|
|
99
|
-
else if (entry.endsWith(".mdx")) out.push(full);
|
|
107
|
+
else if (entry.endsWith(".mdx") || entry.endsWith(".md")) out.push(full);
|
|
100
108
|
}
|
|
101
109
|
return out;
|
|
102
110
|
}
|
|
@@ -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
|
+
}
|