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.
Files changed (310) hide show
  1. package/.next/standalone/.codex/hooks.json +6 -6
  2. package/.next/standalone/.cursor/hooks.json +6 -6
  3. package/.next/standalone/.factory/hooks.json +112 -0
  4. package/.next/standalone/.next/BUILD_ID +1 -1
  5. package/.next/standalone/.next/build-manifest.json +5 -5
  6. package/.next/standalone/.next/prerender-manifest.json +3 -3
  7. package/.next/standalone/.next/required-server-files.json +1 -1
  8. package/.next/standalone/.next/server/app/_global-error/page/build-manifest.json +2 -2
  9. package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
  10. package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
  11. package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  12. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  13. package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
  14. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +2 -2
  15. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
  16. package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +3 -3
  17. package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +3 -3
  18. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  19. package/.next/standalone/.next/server/app/_not-found/page/build-manifest.json +2 -2
  20. package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  21. package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  22. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  23. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  24. package/.next/standalone/.next/server/app/_not-found.rsc +15 -15
  25. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +15 -15
  26. package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
  27. package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +10 -10
  28. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
  29. package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
  30. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  31. package/.next/standalone/.next/server/app/api/audit/invite/route.js.nft.json +1 -1
  32. package/.next/standalone/.next/server/app/api/audit/run/route.js +3 -3
  33. package/.next/standalone/.next/server/app/api/audit/run/route.js.nft.json +1 -1
  34. package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -1
  35. package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -1
  36. package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
  37. package/.next/standalone/.next/server/app/api/auth/reminder/route.js.nft.json +1 -1
  38. package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -1
  39. package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js +2 -1
  40. package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
  41. package/.next/standalone/.next/server/app/audit/page/build-manifest.json +2 -2
  42. package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
  43. package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
  44. package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
  45. package/.next/standalone/.next/server/app/index.html +1 -1
  46. package/.next/standalone/.next/server/app/index.rsc +15 -15
  47. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  48. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +15 -15
  49. package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +4 -4
  50. package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +10 -10
  51. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  52. package/.next/standalone/.next/server/app/page/build-manifest.json +2 -2
  53. package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
  54. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  55. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  56. package/.next/standalone/.next/server/app/policies/page/build-manifest.json +2 -2
  57. package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +8 -8
  58. package/.next/standalone/.next/server/app/policies/page.js +1 -1
  59. package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
  60. package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
  61. package/.next/standalone/.next/server/app/project/[name]/page/build-manifest.json +2 -2
  62. package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
  63. package/.next/standalone/.next/server/app/project/[name]/page.js +3 -2
  64. package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
  65. package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
  66. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/build-manifest.json +2 -2
  67. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
  68. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
  69. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js +5 -3
  70. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
  71. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
  72. package/.next/standalone/.next/server/app/projects/page/build-manifest.json +2 -2
  73. package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
  74. package/.next/standalone/.next/server/app/projects/page.js +1 -1
  75. package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
  76. package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  77. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0--lkk6._.js +3 -0
  78. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0-219ec._.js +3 -0
  79. package/.next/standalone/.next/server/chunks/[root-of-the-server]__04_h-a5._.js +3 -0
  80. package/.next/standalone/.next/server/chunks/[root-of-the-server]__06cuf1y._.js +3 -0
  81. package/.next/standalone/.next/server/chunks/[root-of-the-server]__08w4wmd._.js +3 -0
  82. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0g6bbuw._.js +3 -0
  83. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0jllheg._.js +3 -0
  84. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0jnjf2t._.js +3 -0
  85. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0q-v9z2._.js +1 -1
  86. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0q0qzx1._.js +3 -0
  87. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0q2nbsl._.js +3 -0
  88. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0rv7m0k._.js +1 -1
  89. package/.next/standalone/.next/server/chunks/[root-of-the-server]__16le-kd._.js +3 -0
  90. package/.next/standalone/.next/server/chunks/[root-of-the-server]__17g9wh7._.js +1 -1
  91. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1d9qen3._.js +3 -0
  92. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1ffkmds._.js +3 -0
  93. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1fwl2mz._.js +1 -1
  94. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1legmza._.js +1 -1
  95. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1mrihkj._.js +1 -1
  96. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1myjm-d._.js +1 -1
  97. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1qb590j._.js +3 -0
  98. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1qxztj-._.js +1 -1
  99. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1shcqgr._.js +3 -0
  100. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1xuedea._.js +3 -0
  101. package/.next/standalone/.next/server/chunks/{_1z062h5._.js → _1vslkoe._.js} +2 -2
  102. package/.next/standalone/.next/server/chunks/lib_factory-projects_ts_1eo_bk-._.js +3 -0
  103. package/.next/standalone/.next/server/chunks/lib_openclaw-projects_ts_0gc-p24._.js +3 -0
  104. package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_17k9e3w.js +24 -12
  105. package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_01r25oi._.js +1 -1
  106. package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_09z9-p7._.js +1 -1
  107. package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
  108. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__00cz9as._.js +3 -0
  109. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__015_i4t._.js +2 -2
  110. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__030k0c6._.js +3 -0
  111. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__03lv-pe._.js +2 -2
  112. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__042d3cd._.js +3 -0
  113. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__05r_17v._.js +3 -0
  114. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__09q1168._.js +3 -0
  115. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__108slqn._.js → [root-of-the-server]__0brjczq._.js} +2 -2
  116. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0e2l3c1._.js +3 -0
  117. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0hci7t3._.js +3 -0
  118. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0hdsupo._.js +2 -2
  119. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0p84xee._.js +3 -0
  120. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0qeuy9c._.js +2 -2
  121. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0s89hoe._.js +2 -2
  122. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__07iom4f._.js → [root-of-the-server]__0wp9w6i._.js} +2 -2
  123. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ynf7tx._.js +2 -2
  124. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__170799-._.js +12 -9
  125. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__17ai7sy._.js +4 -0
  126. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1d8omgc._.js +1 -1
  127. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1nq7ivq._.js +3 -0
  128. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1tkjqka._.js +2 -2
  129. package/.next/standalone/.next/server/chunks/ssr/_05whahf._.js +1 -1
  130. package/.next/standalone/.next/server/chunks/ssr/_0_9_ytf._.js +3 -0
  131. package/.next/standalone/.next/server/chunks/ssr/_11_p9y8._.js +1 -1
  132. package/.next/standalone/.next/server/chunks/ssr/{_0ul5rf_._.js → _1_ozgif._.js} +2 -2
  133. package/.next/standalone/.next/server/chunks/ssr/_1p0-leb._.js +1 -1
  134. package/.next/standalone/.next/server/chunks/ssr/app_087bt9w._.js +1 -1
  135. package/.next/standalone/.next/server/chunks/ssr/app_1fvisnp._.js +1 -1
  136. package/.next/standalone/.next/server/chunks/ssr/app_209u41o._.js +1 -1
  137. package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +2 -2
  138. package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x._.js +1 -1
  139. package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpc._.js +1 -1
  140. package/.next/standalone/.next/server/chunks/ssr/lib_0xkhw_v._.js +3 -0
  141. package/.next/standalone/.next/server/chunks/ssr/lib_antigravity-projects_ts_0_6zf11._.js +3 -0
  142. package/.next/standalone/.next/server/chunks/ssr/lib_devin-projects_ts_0a64qdy._.js +3 -0
  143. package/.next/standalone/.next/server/chunks/ssr/lib_factory-projects_ts_1uyaahq._.js +3 -0
  144. package/.next/standalone/.next/server/chunks/ssr/lib_goose-projects_ts_0zkscri._.js +3 -0
  145. package/.next/standalone/.next/server/chunks/ssr/lib_openclaw-projects_ts_0qxq3bp._.js +3 -0
  146. 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
  147. package/.next/standalone/.next/server/chunks/ssr/node_modules_posthog-node_dist_entrypoints_index_node_mjs_11bnuzn._.js +1 -1
  148. package/.next/standalone/.next/server/chunks/ssr/src_hooks_1ezd2jf._.js +1 -1
  149. package/.next/standalone/.next/server/chunks/ssr/src_hooks_1tnuifj._.js +1 -1
  150. package/.next/standalone/.next/server/middleware-build-manifest.js +5 -5
  151. package/.next/standalone/.next/server/pages/404.html +1 -1
  152. package/.next/standalone/.next/server/pages/500.html +1 -1
  153. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  154. package/.next/standalone/.next/server/server-reference-manifest.json +10 -10
  155. package/.next/standalone/.next/static/chunks/{13f1kmjea-0md.js → 02jcotghcxrbu.js} +1 -1
  156. package/.next/standalone/.next/static/chunks/{30ysv-_8jj052.js → 0d5lypu1zs21r.js} +1 -1
  157. package/.next/standalone/.next/static/chunks/0emg30_6svycu.js +1 -0
  158. package/.next/standalone/.next/static/chunks/0o9wpnze1ey8y.js +6 -0
  159. package/.next/standalone/.next/static/chunks/{05apzuand0c22.js → 1359o5785rmve.js} +2 -2
  160. package/.next/standalone/.next/static/chunks/20tuctw38jbgw.js +1 -0
  161. package/.next/standalone/.next/static/chunks/{0vc0eak148vo6.js → 2ldhnaweu9ew3.js} +1 -1
  162. package/.next/standalone/.next/static/chunks/{23c7v2svx90dp.js → 2vav_x0_336ds.js} +1 -1
  163. package/.next/standalone/.next/static/chunks/3-ogr79xqbw0h.js +1 -0
  164. package/.next/standalone/.next/static/chunks/36j05kb2x323i.css +2 -0
  165. package/.next/standalone/.next/static/chunks/3cg7x0joi2b98.js +1 -0
  166. package/.next/standalone/.next/static/chunks/{36wdtkgdf0zrd.js → 3k87p-tijud-4.js} +1 -1
  167. package/.next/standalone/.next/static/chunks/{2cejn75gug3j8.js → 3kmaqcp7rldad.js} +1 -1
  168. package/.next/standalone/.next/static/chunks/{turbopack-0vavqo2d-tlt3.js → turbopack-10hj8t5pf33tu.js} +1 -1
  169. package/.next/standalone/.opencode/plugins/failproofai.mjs +30 -11
  170. package/.next/standalone/app/api/audit/run/route.ts +2 -0
  171. package/.next/standalone/app/audit/_components/empty-state.tsx +1 -1
  172. package/.next/standalone/app/components/global-error-listeners.tsx +27 -0
  173. package/.next/standalone/app/globals.css +25 -1
  174. package/.next/standalone/app/policies/hooks-client.tsx +2 -4
  175. package/.next/standalone/app/project/[name]/page.tsx +30 -10
  176. package/.next/standalone/app/project/[name]/session/[sessionId]/page.tsx +71 -21
  177. package/.next/standalone/assets/logos/antigravity.svg +1 -0
  178. package/.next/standalone/assets/logos/devin.svg +1 -0
  179. package/.next/standalone/assets/logos/factory-dark.png +0 -0
  180. package/.next/standalone/assets/logos/factory-light.png +0 -0
  181. package/.next/standalone/assets/logos/goose-dark.svg +1 -0
  182. package/.next/standalone/assets/logos/goose-light.svg +1 -0
  183. package/.next/standalone/assets/logos/openclaw.svg +22 -0
  184. package/.next/standalone/ci/cli-integration/Dockerfile +47 -0
  185. package/.next/standalone/ci/cli-integration/README.md +69 -0
  186. package/.next/standalone/ci/cli-integration/canary-policies.mjs +45 -0
  187. package/.next/standalone/ci/cli-integration/capture-tokens.sh +48 -0
  188. package/.next/standalone/ci/cli-integration/inject-tokens.sh +44 -0
  189. package/.next/standalone/ci/cli-integration/install-clis.sh +91 -0
  190. package/.next/standalone/ci/cli-integration/probe-cli.sh +208 -0
  191. package/.next/standalone/ci/cli-integration/report.js +74 -0
  192. package/.next/standalone/ci/cli-integration/run.sh +107 -0
  193. package/.next/standalone/components/navbar.tsx +5 -11
  194. package/.next/standalone/components/reach-developers.tsx +2 -2
  195. package/.next/standalone/docker-hook-sync/Dockerfile +8 -4
  196. package/.next/standalone/lib/antigravity-projects.ts +224 -0
  197. package/.next/standalone/lib/antigravity-sessions.ts +283 -0
  198. package/.next/standalone/lib/cli-registry.ts +26 -6
  199. package/.next/standalone/lib/devin-projects.ts +141 -0
  200. package/.next/standalone/lib/devin-sessions.ts +343 -0
  201. package/.next/standalone/lib/download-session.ts +56 -5
  202. package/.next/standalone/lib/error-origin.ts +67 -0
  203. package/.next/standalone/lib/factory-projects.ts +109 -0
  204. package/.next/standalone/lib/factory-sessions.ts +312 -0
  205. package/.next/standalone/lib/goose-projects.ts +148 -0
  206. package/.next/standalone/lib/goose-sessions.ts +296 -0
  207. package/.next/standalone/lib/install-check.ts +231 -0
  208. package/.next/standalone/lib/openclaw-projects.ts +182 -0
  209. package/.next/standalone/lib/openclaw-sessions.ts +284 -0
  210. package/.next/standalone/lib/projects.ts +33 -9
  211. package/.next/standalone/lib/telemetry-sanitize.ts +43 -0
  212. package/.next/standalone/openclaw-plugin/index.js +223 -0
  213. package/.next/standalone/openclaw-plugin/openclaw.plugin.json +6 -0
  214. package/.next/standalone/openclaw-plugin/package.json +12 -0
  215. package/.next/standalone/package.json +2 -3
  216. package/.next/standalone/server.js +1 -1
  217. package/README.md +94 -62
  218. package/bin/failproofai.mjs +98 -30
  219. package/dist/cli.mjs +12499 -9243
  220. package/lib/antigravity-projects.ts +224 -0
  221. package/lib/antigravity-sessions.ts +283 -0
  222. package/lib/cli-registry.ts +26 -6
  223. package/lib/devin-projects.ts +141 -0
  224. package/lib/devin-sessions.ts +343 -0
  225. package/lib/download-session.ts +56 -5
  226. package/lib/error-origin.ts +67 -0
  227. package/lib/factory-projects.ts +109 -0
  228. package/lib/factory-sessions.ts +312 -0
  229. package/lib/goose-projects.ts +148 -0
  230. package/lib/goose-sessions.ts +296 -0
  231. package/lib/install-check.ts +231 -0
  232. package/lib/openclaw-projects.ts +182 -0
  233. package/lib/openclaw-sessions.ts +284 -0
  234. package/lib/projects.ts +33 -9
  235. package/lib/telemetry-sanitize.ts +43 -0
  236. package/openclaw-plugin/index.js +223 -0
  237. package/openclaw-plugin/openclaw.plugin.json +6 -0
  238. package/openclaw-plugin/package.json +12 -0
  239. package/package.json +2 -3
  240. package/scripts/dev-hook.mjs +292 -0
  241. package/scripts/install-diagnosis.mjs +5 -8
  242. package/scripts/install-telemetry.mjs +12 -4
  243. package/scripts/launch.ts +4 -8
  244. package/scripts/sync-agent-cli-harnesses-prompt.md +7 -10
  245. package/scripts/translate-docs/cli.ts +120 -53
  246. package/scripts/translate-docs/config.ts +57 -13
  247. package/scripts/translate-docs/mdx-translator.ts +177 -28
  248. package/scripts/translate-docs/mintlify-nav.ts +91 -10
  249. package/scripts/translate-docs/readme-translator.ts +13 -5
  250. package/scripts/translate-docs/translator.ts +38 -2
  251. package/scripts/translate-docs/types.ts +3 -0
  252. package/scripts/validate-mdx.ts +12 -4
  253. package/src/audit/cli-adapters/antigravity.ts +87 -0
  254. package/src/audit/cli-adapters/devin.ts +53 -0
  255. package/src/audit/cli-adapters/factory.ts +75 -0
  256. package/src/audit/cli-adapters/goose.ts +53 -0
  257. package/src/audit/cli-adapters/index.ts +30 -6
  258. package/src/audit/cli-adapters/openclaw.ts +56 -0
  259. package/src/audit/cli.ts +83 -8
  260. package/src/audit/report.ts +1 -1
  261. package/src/audit/types.ts +1 -1
  262. package/src/hooks/builtin-policies.ts +5 -5
  263. package/src/hooks/configure-wizard.ts +356 -0
  264. package/src/hooks/handler.ts +283 -218
  265. package/src/hooks/hook-telemetry.ts +43 -3
  266. package/src/hooks/install-prompt.ts +92 -173
  267. package/src/hooks/integrations.ts +739 -138
  268. package/src/hooks/manager.ts +46 -2
  269. package/src/hooks/policy-evaluator.ts +301 -121
  270. package/src/hooks/policy-presets.ts +71 -0
  271. package/src/hooks/resolve-cwd.ts +1 -1
  272. package/src/hooks/resolve-permission-mode.ts +1 -5
  273. package/src/hooks/resolve-transcript-path.ts +25 -7
  274. package/src/hooks/tool-name-canonicalize.ts +36 -3
  275. package/src/hooks/tui.ts +578 -0
  276. package/src/hooks/types.ts +447 -109
  277. package/.next/standalone/.gemini/settings.json +0 -147
  278. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0cag8qd._.js +0 -3
  279. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0cefjd9._.js +0 -3
  280. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ekj92q._.js +0 -3
  281. package/.next/standalone/.next/server/chunks/[root-of-the-server]__12v-lma._.js +0 -3
  282. package/.next/standalone/.next/server/chunks/[root-of-the-server]__136y39g._.js +0 -3
  283. package/.next/standalone/.next/server/chunks/[root-of-the-server]__13h8pzr._.js +0 -3
  284. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1hgv_75._.js +0 -3
  285. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__04bqvos._.js +0 -3
  286. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0dqgs96._.js +0 -3
  287. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0q5rfxg._.js +0 -3
  288. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0qukut7._.js +0 -4
  289. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1ql-mch._.js +0 -3
  290. package/.next/standalone/.next/server/chunks/ssr/_11v0g3z._.js +0 -3
  291. package/.next/standalone/.next/server/chunks/ssr/lib_gemini-projects_ts_1c7bgx-._.js +0 -3
  292. package/.next/standalone/.next/static/chunks/0fa7j157kg9_d.js +0 -1
  293. package/.next/standalone/.next/static/chunks/0nrah-qv6smeg.js +0 -6
  294. package/.next/standalone/.next/static/chunks/0wtagd8a5gwq-.js +0 -1
  295. package/.next/standalone/.next/static/chunks/1c8i78p7t1i-5.js +0 -1
  296. package/.next/standalone/.next/static/chunks/25qr0e6ez0ei0.js +0 -1
  297. package/.next/standalone/.next/static/chunks/25s52un3k_wht.css +0 -2
  298. package/.next/standalone/assets/logos/gemini-dark.svg +0 -13
  299. package/.next/standalone/assets/logos/gemini-light.svg +0 -13
  300. package/.next/standalone/lib/gemini-projects.ts +0 -243
  301. package/.next/standalone/lib/gemini-sessions.ts +0 -365
  302. package/lib/gemini-projects.ts +0 -243
  303. package/lib/gemini-sessions.ts +0 -365
  304. package/scripts/postinstall.mjs +0 -243
  305. package/scripts/preuninstall.mjs +0 -131
  306. package/src/audit/cli-adapters/gemini.ts +0 -51
  307. package/src/hooks/first-run-nudge.ts +0 -146
  308. /package/.next/standalone/.next/static/{kmzdjTLVs6LqsfyOaUf69 → LkN-JjmhKGmL-WklH7WVi}/_buildManifest.js +0 -0
  309. /package/.next/standalone/.next/static/{kmzdjTLVs6LqsfyOaUf69 → LkN-JjmhKGmL-WklH7WVi}/_clientMiddlewareManifest.js +0 -0
  310. /package/.next/standalone/.next/static/{kmzdjTLVs6LqsfyOaUf69 → LkN-JjmhKGmL-WklH7WVi}/_ssgManifest.js +0 -0
@@ -1,4 +1,12 @@
1
- import { readFileSync, writeFileSync, mkdirSync, readdirSync, statSync } from "node:fs";
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
- content: string,
103
- lang: string,
104
- ): string {
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
- /href="(\/[^"]*?)"/g,
108
- (_match, path: string) => {
109
- // Skip external URLs and anchors
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
- /\]\((\/[^)]*?)\)/g,
118
- (_match, path: string) => {
119
- if (path.startsWith("/http") || path === "/") return `](${path})`;
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: { force?: boolean; dryRun?: boolean; model?: string; cache?: TranslationCache } = {},
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, then
178
- // rewrite links.
179
- const sanitized = stripStrayTrailingFence(sanitizeJsxAttributes(translated));
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(cache, relPath, lang, sourceContent, inputTokens, outputTokens);
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-doc directories like logo, i18n
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", "ja", "ko", "es", "pt-br", "de", "fr",
232
- "ru", "hi", "tr", "vi", "it", "ar", "he",
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 { language: lang, tabs };
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
- // Extract existing English tabs
89
- const englishTabs = nav.tabs as NavTab[];
90
- if (!englishTabs) {
91
- throw new Error("docs.json navigation.tabs not found is this already using the languages format?");
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
- // Build languages array
95
- const languages = generateLanguagesArray(englishTabs, langCodes);
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 { stripStrayTrailingFence } from "./mdx-translator";
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
- // Drop any stray trailing fence the model hallucinated would otherwise
107
- // open an unclosed code block that swallows the wrapping `</div>` for RTL
108
- // pages and break Mintlify's MDX parser.
109
- const cleaned = stripStrayTrailingFence(translated);
110
+ // Run the same MDX sanitizers as translateMdxPagethe 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: 16384,
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].type === "text" ? response.content[0].text : "";
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;
@@ -1,6 +1,6 @@
1
1
  /**
2
- * Validate that every docs MDX page parses with the same MDX engine Mintlify
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
- function collectMdxFiles(dir: string): string[] {
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
+ }