failproofai 1.0.3 → 1.0.4-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 (251) hide show
  1. package/.next/standalone/.grok/hooks/failproofai.json +172 -0
  2. package/.next/standalone/.next/BUILD_ID +1 -1
  3. package/.next/standalone/.next/build-manifest.json +5 -5
  4. package/.next/standalone/.next/prerender-manifest.json +4 -4
  5. package/.next/standalone/.next/required-server-files.json +1 -1
  6. package/.next/standalone/.next/server/app/_global-error/page/build-manifest.json +2 -2
  7. package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
  8. package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
  9. package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  10. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  11. package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
  12. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +6 -6
  13. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
  14. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  15. package/.next/standalone/.next/server/app/_not-found/page/build-manifest.json +2 -2
  16. package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  17. package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  18. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  19. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  20. package/.next/standalone/.next/server/app/_not-found.rsc +15 -15
  21. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +15 -15
  22. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +14 -14
  23. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  24. package/.next/standalone/.next/server/app/api/audit/invite/route.js.nft.json +1 -1
  25. package/.next/standalone/.next/server/app/api/audit/run/route.js +4 -4
  26. package/.next/standalone/.next/server/app/api/audit/run/route.js.nft.json +1 -1
  27. package/.next/standalone/.next/server/app/api/audit/status/route.js.nft.json +1 -1
  28. package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -1
  29. package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -1
  30. package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
  31. package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -1
  32. package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js +1 -1
  33. package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
  34. package/.next/standalone/.next/server/app/audit/page/build-manifest.json +2 -2
  35. package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
  36. package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
  37. package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
  38. package/.next/standalone/.next/server/app/index.html +1 -1
  39. package/.next/standalone/.next/server/app/index.rsc +15 -15
  40. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +14 -14
  41. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +15 -15
  42. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  43. package/.next/standalone/.next/server/app/page/build-manifest.json +2 -2
  44. package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
  45. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  46. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  47. package/.next/standalone/.next/server/app/policies/page/build-manifest.json +2 -2
  48. package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +14 -14
  49. package/.next/standalone/.next/server/app/policies/page.js +1 -1
  50. package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
  51. package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
  52. package/.next/standalone/.next/server/app/project/[name]/page/build-manifest.json +2 -2
  53. package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
  54. package/.next/standalone/.next/server/app/project/[name]/page.js +3 -3
  55. package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
  56. package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
  57. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/build-manifest.json +2 -2
  58. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
  59. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
  60. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js +2 -2
  61. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
  62. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
  63. package/.next/standalone/.next/server/app/projects/page/build-manifest.json +2 -2
  64. package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
  65. package/.next/standalone/.next/server/app/projects/page.js +1 -1
  66. package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
  67. package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  68. package/.next/standalone/.next/server/app/settings/page/build-manifest.json +2 -2
  69. package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +4 -4
  70. package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -1
  71. package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  72. package/.next/standalone/.next/server/chunks/{[externals]__0u3wrvq._.js → [externals]__0_gzk8q._.js} +1 -1
  73. package/.next/standalone/.next/server/chunks/{[externals]__0-9ti7z._.js → [externals]__1zndo1i._.js} +1 -1
  74. package/.next/standalone/.next/server/chunks/[root-of-the-server]__07hor7h._.js +5 -0
  75. package/.next/standalone/.next/server/chunks/[root-of-the-server]__08dchfu._.js +1 -1
  76. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0cuho4x._.js +1 -1
  77. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0elsuli._.js +3 -0
  78. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0gnj_qa._.js +3 -0
  79. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ljuzm_._.js +3 -0
  80. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0o07qi9._.js +1 -1
  81. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0w23bpg._.js +3 -0
  82. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0x5c7sh._.js +3 -0
  83. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0yik9_w._.js +3 -0
  84. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1adacul._.js +1 -1
  85. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1jg6s9m._.js +3 -0
  86. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1s6qci9._.js +3 -0
  87. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1xfm05z._.js +3 -0
  88. package/.next/standalone/.next/server/chunks/_09dz7xv._.js +1 -1
  89. package/.next/standalone/.next/server/chunks/_0tdy_6l._.js +3 -0
  90. package/.next/standalone/.next/server/chunks/_0tovk6q._.js +1 -1
  91. package/.next/standalone/.next/server/chunks/_0trp3yc._.js +1 -1
  92. package/.next/standalone/.next/server/chunks/_1ek68ln._.js +21 -14
  93. package/.next/standalone/.next/server/chunks/lib_grok-projects_ts_1i2epl_._.js +3 -0
  94. package/.next/standalone/.next/server/chunks/lib_qwen-projects_ts_0wu_a8e._.js +3 -0
  95. package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_01r25oi._.js +2 -2
  96. package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_09z9-p7._.js +2 -2
  97. package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
  98. package/.next/standalone/.next/server/chunks/src_hooks_0iu54mz._.js +1 -1
  99. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__013jr2b._.js +2 -2
  100. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__01wy8d-._.js +2 -2
  101. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__02npjtd._.js +2 -2
  102. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0_4gcz8._.js +3 -0
  103. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0d--wmy._.js +3 -0
  104. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0da85px._.js +2 -2
  105. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ftmoxc._.js +2 -2
  106. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0oa1lav._.js +1 -1
  107. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0p-5p8u._.js +2 -2
  108. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0qqrlf_._.js +3 -0
  109. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0s11fx1._.js +3 -0
  110. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0s740oi._.js +2 -2
  111. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0n_lxhg._.js → [root-of-the-server]__0wvusu0._.js} +2 -2
  112. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1b5jzxr._.js → [root-of-the-server]__16gamwq._.js} +2 -2
  113. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1bbk-si._.js +3 -0
  114. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1c3ybxr._.js +3 -0
  115. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1izi7zn._.js +3 -0
  116. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1p2otjt._.js +2 -2
  117. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1qapotl._.js +1 -1
  118. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1zl_r0t._.js +1 -1
  119. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__21bj7uw._.js +3 -0
  120. package/.next/standalone/.next/server/chunks/ssr/_0-yi74u._.js +1 -1
  121. package/.next/standalone/.next/server/chunks/ssr/{_0v8eebd._.js → _00z5uuq._.js} +1 -1
  122. package/.next/standalone/.next/server/chunks/ssr/{_1if9ixi._.js → _08f0jd2._.js} +1 -1
  123. package/.next/standalone/.next/server/chunks/ssr/_08x1r5t._.js +1 -1
  124. package/.next/standalone/.next/server/chunks/ssr/_0wso5d3._.js +1 -1
  125. package/.next/standalone/.next/server/chunks/ssr/{_0j6gd_k._.js → _1byck5v._.js} +2 -2
  126. package/.next/standalone/.next/server/chunks/ssr/_1es2j7i._.js +155 -1
  127. package/.next/standalone/.next/server/chunks/ssr/_1u8-lu2._.js +1 -1
  128. package/.next/standalone/.next/server/chunks/ssr/_1zopuov._.js +1 -1
  129. package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_policies_page_actions_1sp2-yo.js +2 -2
  130. package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +1 -1
  131. package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x._.js +1 -1
  132. package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpc._.js +1 -1
  133. package/.next/standalone/.next/server/chunks/ssr/app_settings_settings-client_tsx_20lq-mq._.js +1 -1
  134. package/.next/standalone/.next/server/chunks/ssr/lib_cline-projects_ts_13_hbdd._.js +3 -0
  135. package/.next/standalone/.next/server/chunks/ssr/lib_grok-projects_ts_0rc-d0o._.js +3 -0
  136. package/.next/standalone/.next/server/chunks/ssr/lib_ori-projects_ts_04tofqo._.js +3 -0
  137. package/.next/standalone/.next/server/chunks/ssr/lib_qwen-projects_ts_0w3i9o7._.js +3 -0
  138. package/.next/standalone/.next/server/chunks/ssr/node_modules_posthog-node_dist_entrypoints_index_node_mjs_11bnuzn._.js +2 -2
  139. package/.next/standalone/.next/server/chunks/ssr/src_hooks_builtin-policies_ts_09j2ndl._.js +1 -1
  140. package/.next/standalone/.next/server/middleware-build-manifest.js +5 -5
  141. package/.next/standalone/.next/server/pages/404.html +1 -1
  142. package/.next/standalone/.next/server/pages/500.html +1 -1
  143. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  144. package/.next/standalone/.next/server/server-reference-manifest.json +19 -19
  145. package/.next/standalone/.next/static/chunks/{0ollg-nnu3t3e.js → 00gv0v91mycm-.js} +1 -1
  146. package/.next/standalone/.next/static/chunks/{354-n7p7labpn.js → 01hvwwrhvbzyh.js} +1 -1
  147. package/.next/standalone/.next/static/chunks/0hzmxwb2pvk5p.js +6 -0
  148. package/.next/standalone/.next/static/chunks/{0nm11ysn0153h.js → 0j884dwnwtyrt.js} +1 -1
  149. package/.next/standalone/.next/static/chunks/0mr9dg3bnloa1.js +1 -0
  150. package/.next/standalone/.next/static/chunks/0qn9khv0oo9ex.js +1 -0
  151. package/.next/standalone/.next/static/chunks/{2xm5mj1d21b4n.js → 1_2jsatfuthrw.js} +1 -1
  152. package/.next/standalone/.next/static/chunks/1_bxotmf9qngs.js +1 -0
  153. package/.next/standalone/.next/static/chunks/1eyl7fzkmnkf_.js +1 -0
  154. package/.next/standalone/.next/static/chunks/{42yfkhekx440s.js → 1po3lirgk2riw.js} +1 -1
  155. package/.next/standalone/.next/static/chunks/{40lpt2o2b283e.js → 2bnf_4pgyk1rq.js} +1 -1
  156. package/.next/standalone/.next/static/chunks/{1a6u7l3giejch.js → 2bvwsyu6x__ia.js} +1 -1
  157. package/.next/standalone/.next/static/chunks/{3l36d73kj18zw.js → 3_--3ibia6ba1.js} +1 -1
  158. package/.next/standalone/.next/static/chunks/3gf1jg-5m-u1t.css +2 -0
  159. package/.next/standalone/.next/static/chunks/{3pibxnbhjza7n.js → 3ws7eljkq25wg.js} +1 -1
  160. package/.next/standalone/.next/static/chunks/{turbopack-2x-o099q64i8h.js → turbopack-18qf4jodtft6b.js} +1 -1
  161. package/.next/standalone/.qwen/settings.json +251 -0
  162. package/.next/standalone/app/project/[name]/page.tsx +24 -4
  163. package/.next/standalone/assets/logos/cline.png +0 -0
  164. package/.next/standalone/assets/logos/grok-dark.svg +1 -0
  165. package/.next/standalone/assets/logos/grok-light.svg +1 -0
  166. package/.next/standalone/assets/logos/ori-dark.svg +1 -0
  167. package/.next/standalone/assets/logos/ori-light.svg +1 -0
  168. package/.next/standalone/assets/logos/qwen.svg +1 -0
  169. package/.next/standalone/lib/cli-registry.ts +33 -1
  170. package/.next/standalone/lib/cline-projects.ts +155 -0
  171. package/.next/standalone/lib/cline-sessions.ts +268 -0
  172. package/.next/standalone/lib/download-session.ts +37 -0
  173. package/.next/standalone/lib/grok-projects.ts +123 -0
  174. package/.next/standalone/lib/grok-sessions.ts +355 -0
  175. package/.next/standalone/lib/ori-projects.ts +141 -0
  176. package/.next/standalone/lib/ori-sessions.ts +221 -0
  177. package/.next/standalone/lib/projects.ts +27 -3
  178. package/.next/standalone/lib/qwen-projects.ts +106 -0
  179. package/.next/standalone/lib/qwen-sessions.ts +313 -0
  180. package/.next/standalone/node_modules/@next/env/package.json +1 -1
  181. package/.next/standalone/node_modules/next/dist/build/swc/index.js +1 -1
  182. package/.next/standalone/node_modules/next/dist/compiled/next-server/app-page-turbo-experimental.runtime.prod.js +1 -1
  183. package/.next/standalone/node_modules/next/dist/compiled/next-server/app-page-turbo.runtime.prod.js +1 -1
  184. package/.next/standalone/node_modules/next/dist/compiled/next-server/app-route-turbo.runtime.prod.js +1 -1
  185. package/.next/standalone/node_modules/next/dist/compiled/next-server/pages-turbo.runtime.prod.js +5 -5
  186. package/.next/standalone/node_modules/next/dist/lib/patch-incorrect-lockfile.js +3 -3
  187. package/.next/standalone/node_modules/next/dist/server/config.js +1 -1
  188. package/.next/standalone/node_modules/next/dist/server/dev/hot-reloader-turbopack.js +2 -2
  189. package/.next/standalone/node_modules/next/dist/server/dev/hot-reloader-webpack.js +1 -1
  190. package/.next/standalone/node_modules/next/dist/server/image-optimizer.js +2 -2
  191. package/.next/standalone/node_modules/next/dist/server/lib/app-info-log.js +1 -1
  192. package/.next/standalone/node_modules/next/dist/server/lib/incremental-cache/file-system-cache.js +17 -4
  193. package/.next/standalone/node_modules/next/dist/server/lib/start-server.js +1 -1
  194. package/.next/standalone/node_modules/next/dist/shared/lib/router/utils/escape-path-delimiters.js +1 -1
  195. package/.next/standalone/node_modules/next/dist/telemetry/anonymous-meta.js +1 -1
  196. package/.next/standalone/node_modules/next/dist/telemetry/events/swc-load-failure.js +1 -1
  197. package/.next/standalone/node_modules/next/dist/telemetry/events/version.js +2 -2
  198. package/.next/standalone/node_modules/next/package.json +10 -10
  199. package/.next/standalone/package.json +11 -11
  200. package/.next/standalone/sdk/python/uv.lock +29 -29
  201. package/.next/standalone/server.js +1 -1
  202. package/README.md +38 -7
  203. package/bin/failproofai.mjs +24 -7
  204. package/dist/cli.mjs +20313 -17756
  205. package/dist/worker.mjs +8521 -6768
  206. package/lib/cli-registry.ts +33 -1
  207. package/lib/cline-projects.ts +155 -0
  208. package/lib/cline-sessions.ts +268 -0
  209. package/lib/download-session.ts +37 -0
  210. package/lib/grok-projects.ts +123 -0
  211. package/lib/grok-sessions.ts +355 -0
  212. package/lib/ori-projects.ts +141 -0
  213. package/lib/ori-sessions.ts +221 -0
  214. package/lib/projects.ts +27 -3
  215. package/lib/qwen-projects.ts +106 -0
  216. package/lib/qwen-sessions.ts +313 -0
  217. package/package.json +11 -11
  218. package/src/audit/cli-adapters/cline.ts +50 -0
  219. package/src/audit/cli-adapters/grok.ts +70 -0
  220. package/src/audit/cli-adapters/index.ts +24 -0
  221. package/src/audit/cli-adapters/ori.ts +55 -0
  222. package/src/audit/cli-adapters/qwen.ts +71 -0
  223. package/src/hooks/batch-expand.ts +380 -0
  224. package/src/hooks/batch-fanout.ts +142 -0
  225. package/src/hooks/builtin-policies.ts +6 -4
  226. package/src/hooks/enforcement-capability.ts +97 -0
  227. package/src/hooks/handler.ts +61 -5
  228. package/src/hooks/harness-cli.ts +3 -1
  229. package/src/hooks/integrations.ts +756 -2
  230. package/src/hooks/normalize-cli-payload.ts +126 -0
  231. package/src/hooks/policy-evaluator.ts +297 -6
  232. package/src/hooks/resolve-transcript-path.ts +10 -0
  233. package/src/hooks/risk-patterns.ts +26 -0
  234. package/src/hooks/tool-name-canonicalize.ts +64 -0
  235. package/src/hooks/types.ts +533 -2
  236. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1le9jqc._.js +0 -3
  237. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1p-qi2t._.js +0 -5
  238. package/.next/standalone/.next/server/chunks/_1-akg6w._.js +0 -3
  239. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__00-s7h8._.js +0 -3
  240. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__190won8._.js +0 -3
  241. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1ctpynv._.js +0 -3
  242. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1sc84bb._.js +0 -3
  243. package/.next/standalone/.next/static/chunks/03slu0c8_71y7.js +0 -1
  244. package/.next/standalone/.next/static/chunks/1-_zkmnm-jwei.js +0 -1
  245. package/.next/standalone/.next/static/chunks/1r9676mkvihto.js +0 -1
  246. package/.next/standalone/.next/static/chunks/30pct5s734jua.js +0 -6
  247. package/.next/standalone/.next/static/chunks/40nr6ehj4p3cw.css +0 -2
  248. package/.next/standalone/.next/static/chunks/41b5ptaocvi_l.js +0 -1
  249. /package/.next/standalone/.next/static/{JBYgkXkA1PS48m9P_hKNw → qJx3mbOQV-5ElrcRb4Sp7}/_buildManifest.js +0 -0
  250. /package/.next/standalone/.next/static/{JBYgkXkA1PS48m9P_hKNw → qJx3mbOQV-5ElrcRb4Sp7}/_clientMiddlewareManifest.js +0 -0
  251. /package/.next/standalone/.next/static/{JBYgkXkA1PS48m9P_hKNw → qJx3mbOQV-5ElrcRb4Sp7}/_ssgManifest.js +0 -0
@@ -0,0 +1,355 @@
1
+ /**
2
+ * grok CLI session transcript loader + parser.
3
+ *
4
+ * AUDIT-ONLY (Pillar 2). grok stores one DIRECTORY per session at
5
+ * `~/.grok/sessions/<percent-encoded-cwd>/<sessionId>/`, holding
6
+ * `chat_history.jsonl` (the turns), `events.jsonl` (a telemetry stream),
7
+ * `summary.json` (title + cwd + counts), and assorted lock/state files we
8
+ * ignore. Verified live against grok 1.0.3 (1a29d5bc12).
9
+ *
10
+ * TWO things differ from every other JSONL adapter, and both are load-bearing:
11
+ *
12
+ * 1. **The cwd folder is PERCENT-encoded** (`%2Fhome%2Fyou%2Frepo`), not
13
+ * dash-encoded like Claude/Factory/Qwen — so this module decodes with
14
+ * `decodeURIComponent`, NOT `decodeFolderName`. Using the shared helper
15
+ * here would silently yield a cwd of literal "%2Fhome%2F…" and every
16
+ * project grouping would be wrong.
17
+ *
18
+ * 2. **`chat_history.jsonl` carries NO timestamps.** Per-event times live in
19
+ * `events.jsonl`, which is not 1:1 with the turns. Rather than mis-pair
20
+ * them, `grokLinesToLogEntries` takes an explicit `startMs` (the session's
21
+ * `created_at` from summary.json) and lays the turns out one millisecond
22
+ * apart from there. That keeps ordering exact and the session's absolute
23
+ * position on the timeline right, while being honest that per-turn
24
+ * wall-clock times are synthesized, not recorded.
25
+ *
26
+ * Line shapes (OpenAI-ish, discriminated by `type`):
27
+ * {type:"system", content:string} — prompt, skipped
28
+ * {type:"user", content:[{type:"text",text}], prompt_index?} — see below
29
+ * {type:"reasoning", summary:[{type:"summary_text",text}], …} — skipped
30
+ * {type:"assistant", content:string, tool_calls:[{id,name,arguments:string}]}
31
+ * {type:"tool_result", tool_call_id, content:string}
32
+ *
33
+ * `tool_calls[].arguments` is a JSON **string**, not an object — it is parsed
34
+ * here so tool inputs are inspectable like every other CLI's.
35
+ *
36
+ * Only user lines carrying `prompt_index` are treated as real user turns. grok
37
+ * also writes the environment preamble and `synthetic_reason` reminder
38
+ * injections as `user` lines; surfacing those as if the operator typed them
39
+ * would make an audit read like the user pasted grok's own boilerplate.
40
+ * `prompt_history.jsonl` (a per-cwd sibling) records exactly the same set,
41
+ * which is the cross-check that this filter is the right one.
42
+ *
43
+ * Home override: set `GROK_HOME` (used by tests / to point at a copied
44
+ * sessions dir).
45
+ */
46
+ import { readFile } from "node:fs/promises";
47
+ import { readFileSync, readdirSync, statSync } from "node:fs";
48
+ import { homedir } from "node:os";
49
+ import { join } from "node:path";
50
+ import { runtimeCache } from "./runtime-cache";
51
+ import {
52
+ baseEntry,
53
+ formatTimestamp,
54
+ parseRawLines,
55
+ type LogEntry,
56
+ type UserEntry,
57
+ type AssistantEntry,
58
+ type GenericEntry,
59
+ type ContentBlock,
60
+ type ToolUseBlock,
61
+ type LogSource,
62
+ } from "./log-entries";
63
+ import { formatDuration } from "./format-duration";
64
+
65
+ /** grok session directories are UUID-named (UUIDv7 in practice). */
66
+ export const GROK_SESSION_ID_RE =
67
+ /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
68
+
69
+ /** Absolute path to grok's config home (override with GROK_HOME). */
70
+ export function grokHome(): string {
71
+ return process.env.GROK_HOME || join(homedir(), ".grok");
72
+ }
73
+
74
+ /** Absolute path to the grok sessions root. */
75
+ export function grokSessionsRoot(): string {
76
+ return join(grokHome(), "sessions");
77
+ }
78
+
79
+ /**
80
+ * Decode grok's percent-encoded cwd folder name. Deliberately NOT
81
+ * `decodeFolderName` — see the module header. Falls back to the raw name when
82
+ * the folder is not valid percent-encoding, so a malformed dir degrades to a
83
+ * visible label instead of throwing mid-listing.
84
+ */
85
+ export function decodeGrokProjectDir(name: string): string {
86
+ try {
87
+ return decodeURIComponent(name);
88
+ } catch {
89
+ return name;
90
+ }
91
+ }
92
+
93
+ // ── Parsing helpers ──
94
+
95
+ function isPlainObject(v: unknown): v is Record<string, unknown> {
96
+ return !!v && typeof v === "object" && !Array.isArray(v);
97
+ }
98
+
99
+ /** Text from a `content` field that is either a string or an array of
100
+ * `{type:"text",text}` blocks. */
101
+ function extractText(content: unknown): string {
102
+ if (typeof content === "string") return content;
103
+ if (Array.isArray(content)) {
104
+ return content
105
+ .map((c) => (isPlainObject(c) && typeof c.text === "string" ? (c.text as string) : ""))
106
+ .filter(Boolean)
107
+ .join("\n");
108
+ }
109
+ return "";
110
+ }
111
+
112
+ /** grok serializes tool args as a JSON string; parse it, tolerating garbage. */
113
+ function parseArguments(args: unknown): Record<string, unknown> {
114
+ if (isPlainObject(args)) return args;
115
+ if (typeof args === "string") {
116
+ try {
117
+ const parsed = JSON.parse(args) as unknown;
118
+ if (isPlainObject(parsed)) return parsed;
119
+ } catch {
120
+ // fall through — keep the raw string so the audit still shows something
121
+ }
122
+ return { arguments: args };
123
+ }
124
+ return {};
125
+ }
126
+
127
+ // ── Pure parser: transcript lines → LogEntry[] ──
128
+
129
+ /**
130
+ * Convert grok `chat_history.jsonl` lines (parsed objects, in file order) into
131
+ * `LogEntry[]`.
132
+ *
133
+ * `startMs` anchors the synthesized timeline — pass the session's `created_at`
134
+ * (from summary.json). Turns are laid out 1ms apart in file order. Pure —
135
+ * unit-testable with plain line objects.
136
+ */
137
+ export function grokLinesToLogEntries(
138
+ lines: Record<string, unknown>[],
139
+ startMs: number = Date.now(),
140
+ source: LogSource = "session",
141
+ ): LogEntry[] {
142
+ const entries: LogEntry[] = [];
143
+ const toolUseById = new Map<string, ToolUseBlock>();
144
+ const toolUseStartMs = new Map<string, number>();
145
+
146
+ for (let i = 0; i < lines.length; i++) {
147
+ const line = lines[i];
148
+ if (!isPlainObject(line)) continue;
149
+ const type = typeof line.type === "string" ? line.type : "";
150
+ // The system prompt and the model's private reasoning are not turns.
151
+ if (type === "system" || type === "reasoning") continue;
152
+
153
+ const date = new Date(startMs + i);
154
+ const timestamp = date.toISOString();
155
+ const raw: Record<string, unknown> = {
156
+ uuid: line.id != null ? String(line.id) : `grok-${i}`,
157
+ parentUuid: null,
158
+ };
159
+ const base = baseEntry(raw, timestamp, date, source);
160
+
161
+ if (type === "assistant") {
162
+ const blocks: ContentBlock[] = [];
163
+ const text = extractText(line.content);
164
+ if (text) blocks.push({ type: "text", text });
165
+ const calls = Array.isArray(line.tool_calls) ? line.tool_calls : [];
166
+ for (const c of calls) {
167
+ if (!isPlainObject(c)) continue;
168
+ const id = typeof c.id === "string" ? c.id : `${String(c.name ?? "tool")}-${blocks.length}`;
169
+ const name = typeof c.name === "string" ? c.name : "tool";
170
+ const block: ToolUseBlock = {
171
+ type: "tool_use",
172
+ id,
173
+ name,
174
+ input: parseArguments(c.arguments),
175
+ };
176
+ blocks.push(block);
177
+ toolUseById.set(id, block);
178
+ toolUseStartMs.set(id, date.getTime());
179
+ }
180
+ if (blocks.length === 0) continue;
181
+ entries.push({
182
+ type: "assistant",
183
+ ...base,
184
+ message: {
185
+ role: "assistant",
186
+ content: blocks,
187
+ model: typeof line.model_id === "string" ? line.model_id : undefined,
188
+ },
189
+ } satisfies AssistantEntry);
190
+ continue;
191
+ }
192
+
193
+ if (type === "tool_result") {
194
+ const callId = typeof line.tool_call_id === "string" ? line.tool_call_id : undefined;
195
+ const block = callId ? toolUseById.get(callId) : undefined;
196
+ if (block) {
197
+ const started = (callId && toolUseStartMs.get(callId)) || date.getTime();
198
+ const durationMs = Math.max(0, date.getTime() - started);
199
+ block.result = {
200
+ timestamp,
201
+ timestampFormatted: formatTimestamp(date),
202
+ content: extractText(line.content),
203
+ durationMs,
204
+ durationFormatted: formatDuration(durationMs),
205
+ };
206
+ continue;
207
+ }
208
+ entries.push({ type: "system", ...base, raw } satisfies GenericEntry);
209
+ continue;
210
+ }
211
+
212
+ if (type === "user") {
213
+ // Real operator prompts only — see the module header on prompt_index.
214
+ if (line.prompt_index === undefined || line.synthetic_reason !== undefined) continue;
215
+ entries.push({
216
+ type: "user",
217
+ ...base,
218
+ message: { role: "user", content: extractText(line.content) },
219
+ } satisfies UserEntry);
220
+ continue;
221
+ }
222
+
223
+ entries.push({ type: "system", ...base, raw } satisfies GenericEntry);
224
+ }
225
+
226
+ entries.sort((a, b) => a.timestampMs - b.timestampMs);
227
+ return entries;
228
+ }
229
+
230
+ // ── Discovery + file loader ──
231
+
232
+ export interface GrokTranscriptFile {
233
+ /** Percent-encoded folder name on disk (e.g. "%2Fhome%2Fuser%2Frepo"). */
234
+ projectName: string;
235
+ /** Decoded cwd of the project. */
236
+ cwd: string;
237
+ sessionId: string;
238
+ /** Path to chat_history.jsonl inside the session directory. */
239
+ transcriptPath: string;
240
+ mtimeMs: number;
241
+ sizeBytes: number;
242
+ /** Session title from summary.json, when present. */
243
+ title?: string;
244
+ /** created_at from summary.json (ms), used to anchor synthesized timestamps. */
245
+ createdAtMs?: number;
246
+ }
247
+
248
+ /** Read the optional per-session summary.json sidecar. Never throws. */
249
+ function readSummary(sessionDir: string): {
250
+ cwd?: string;
251
+ title?: string;
252
+ createdAtMs?: number;
253
+ } {
254
+ try {
255
+ const raw = JSON.parse(readFileSync(join(sessionDir, "summary.json"), "utf-8")) as unknown;
256
+ if (!isPlainObject(raw)) return {};
257
+ const info = isPlainObject(raw.info) ? raw.info : undefined;
258
+ const createdAt = typeof raw.created_at === "string" ? Date.parse(raw.created_at) : NaN;
259
+ return {
260
+ cwd: info && typeof info.cwd === "string" ? info.cwd : undefined,
261
+ title: typeof raw.session_summary === "string" ? raw.session_summary : undefined,
262
+ createdAtMs: Number.isNaN(createdAt) ? undefined : createdAt,
263
+ };
264
+ } catch {
265
+ return {};
266
+ }
267
+ }
268
+
269
+ /** Enumerate `sessions/<encoded-cwd>/<uuid>/chat_history.jsonl` transcripts. */
270
+ export function listGrokTranscripts(): GrokTranscriptFile[] {
271
+ const root = grokSessionsRoot();
272
+ const out: GrokTranscriptFile[] = [];
273
+ let projectDirs: import("node:fs").Dirent[];
274
+ try {
275
+ projectDirs = readdirSync(root, { withFileTypes: true }).filter((d) => d.isDirectory());
276
+ } catch {
277
+ return out;
278
+ }
279
+ for (const dir of projectDirs) {
280
+ const projectName = dir.name;
281
+ const projectPath = join(root, projectName);
282
+ let sessionDirs: import("node:fs").Dirent[];
283
+ try {
284
+ sessionDirs = readdirSync(projectPath, { withFileTypes: true }).filter((d) => d.isDirectory());
285
+ } catch {
286
+ continue;
287
+ }
288
+ for (const sd of sessionDirs) {
289
+ const sessionId = sd.name;
290
+ if (!GROK_SESSION_ID_RE.test(sessionId)) continue;
291
+ const sessionDir = join(projectPath, sessionId);
292
+ const transcriptPath = join(sessionDir, "chat_history.jsonl");
293
+ let st: import("node:fs").Stats;
294
+ try {
295
+ st = statSync(transcriptPath);
296
+ } catch {
297
+ continue; // a session dir with no chat history yet
298
+ }
299
+ const summary = readSummary(sessionDir);
300
+ out.push({
301
+ projectName,
302
+ // summary.json's info.cwd is canonical; the folder name is the fallback.
303
+ cwd: summary.cwd ?? decodeGrokProjectDir(projectName),
304
+ sessionId,
305
+ transcriptPath,
306
+ mtimeMs: st.mtimeMs,
307
+ sizeBytes: st.size,
308
+ title: summary.title,
309
+ createdAtMs: summary.createdAtMs,
310
+ });
311
+ }
312
+ }
313
+ return out;
314
+ }
315
+
316
+ /** Resolve a session UUID to its chat_history.jsonl path (host-side). Guards
317
+ * against traversal by requiring a UUID directory name. Synchronous so the
318
+ * hook hot path can call it without awaits. */
319
+ export function findGrokTranscript(sessionId: string): string | null {
320
+ if (!GROK_SESSION_ID_RE.test(sessionId)) return null;
321
+ for (const t of listGrokTranscripts()) {
322
+ if (t.sessionId === sessionId) return t.transcriptPath;
323
+ }
324
+ return null;
325
+ }
326
+
327
+ export interface GrokSessionLogData {
328
+ entries: LogEntry[];
329
+ rawLines: Record<string, unknown>[];
330
+ cwd?: string;
331
+ filePath: string;
332
+ }
333
+
334
+ /** Load and parse one session transcript by UUID. Returns `null` when the file
335
+ * is missing/unreadable or the id fails validation. */
336
+ export async function getGrokSessionLog(sessionId: string): Promise<GrokSessionLogData | null> {
337
+ if (!GROK_SESSION_ID_RE.test(sessionId)) return null;
338
+ const meta = listGrokTranscripts().find((t) => t.sessionId === sessionId);
339
+ if (!meta) return null;
340
+ let content: string;
341
+ try {
342
+ content = await readFile(meta.transcriptPath, "utf-8");
343
+ } catch {
344
+ return null;
345
+ }
346
+ const rawLines = parseRawLines(content, "session");
347
+ const entries = grokLinesToLogEntries(rawLines, meta.createdAtMs ?? meta.mtimeMs, "session");
348
+ return { entries, rawLines, cwd: meta.cwd, filePath: meta.transcriptPath };
349
+ }
350
+
351
+ export const getCachedGrokSessionLog = runtimeCache(
352
+ (sessionId: string) => getGrokSessionLog(sessionId),
353
+ 60,
354
+ { maxSize: 50 },
355
+ );
@@ -0,0 +1,141 @@
1
+ /**
2
+ * Ori (OpenRouter's ori) session enumeration — AUDIT-ONLY.
3
+ *
4
+ * Reads `ori_agent_loop_sessions` from ori's global state DB (see
5
+ * lib/ori-sessions.ts for why that is the only real transcript store). Each row
6
+ * carries a real `cwd`, so ori sessions group by project like Claude / Factory /
7
+ * Devin / Goose rather than landing in one cwd-less bucket the way the Hermes
8
+ * gateway does.
9
+ *
10
+ * `archived = 1` rows are excluded: ori's own `history` command hides them
11
+ * behind `--archived`, so surfacing them by default would show a user sessions
12
+ * their agent CLI considers put away. `parent_session_id` marks a forked child
13
+ * session; it is kept (not filtered) so subagent work still appears.
14
+ */
15
+ import { openSqliteReadonly } from "./sqlite-reader";
16
+ import { oriDbPath, oriTimestampToMs } from "./ori-sessions";
17
+ import { encodeFolderName } from "./paths";
18
+ import { runtimeCache } from "./runtime-cache";
19
+ import type { ProjectFolder, SessionFile } from "./projects";
20
+ import { formatDate } from "./format-date";
21
+
22
+ export interface OriSessionRef {
23
+ sessionId: string;
24
+ cwd?: string;
25
+ title?: string;
26
+ model?: string;
27
+ /** Encoded-cwd folder slug (matches Claude's `-home-user-project` scheme). */
28
+ projectName: string;
29
+ /** From `updated_at` — epoch ms. */
30
+ mtimeMs: number;
31
+ }
32
+
33
+ interface OriSessionRow {
34
+ session_id: string;
35
+ title: string | null;
36
+ cwd: string | null;
37
+ model: string | null;
38
+ first_prompt: string | null;
39
+ archived: number | null;
40
+ updated_at: string | null;
41
+ }
42
+
43
+ /**
44
+ * List every ori session. Returns `[]` when the DB is missing or unreadable
45
+ * (fail-open — the audit just skips ori).
46
+ */
47
+ export async function getOriSessions(): Promise<OriSessionRef[]> {
48
+ const db = await openSqliteReadonly(oriDbPath());
49
+ if (!db) return [];
50
+ try {
51
+ const rows = db.query<OriSessionRow>(
52
+ "SELECT session_id, title, cwd, model, first_prompt, archived, updated_at " +
53
+ "FROM ori_agent_loop_sessions ORDER BY updated_at DESC",
54
+ );
55
+ return rows
56
+ .filter((r) => r.archived !== 1)
57
+ .map((r) => {
58
+ const cwd = r.cwd ?? undefined;
59
+ const title = (r.title && r.title.length > 0 ? r.title : r.first_prompt) ?? undefined;
60
+ return {
61
+ sessionId: r.session_id,
62
+ cwd,
63
+ title: title && title.length > 0 ? title : undefined,
64
+ model: r.model ?? undefined,
65
+ projectName: cwd ? encodeFolderName(cwd) : "ori",
66
+ mtimeMs: oriTimestampToMs(r.updated_at),
67
+ };
68
+ });
69
+ } catch {
70
+ return [];
71
+ } finally {
72
+ db.close();
73
+ }
74
+ }
75
+
76
+ export const getCachedOriSessions = runtimeCache(getOriSessions, 2);
77
+
78
+ // ── Dashboard history browser (projects list + project-detail sessions) ──
79
+
80
+ /** One `ProjectFolder` per encoded-cwd discovered in the ori DB. */
81
+ export async function getOriProjects(): Promise<ProjectFolder[]> {
82
+ const sessions = await getOriSessions();
83
+ const byName = new Map<string, { latest: number; cwd: string; name: string }>();
84
+ for (const s of sessions) {
85
+ if (!s.cwd) continue;
86
+ const existing = byName.get(s.projectName);
87
+ if (!existing || s.mtimeMs > existing.latest) {
88
+ byName.set(s.projectName, { latest: s.mtimeMs, cwd: s.cwd, name: s.projectName });
89
+ }
90
+ }
91
+ const folders: ProjectFolder[] = [];
92
+ for (const { name, cwd, latest } of byName.values()) {
93
+ const lastModified = new Date(latest);
94
+ folders.push({
95
+ name,
96
+ path: cwd,
97
+ isDirectory: true,
98
+ lastModified,
99
+ lastModifiedFormatted: formatDate(lastModified),
100
+ cli: ["ori"],
101
+ });
102
+ }
103
+ folders.sort((a, b) => b.lastModified.getTime() - a.lastModified.getTime());
104
+ return folders;
105
+ }
106
+
107
+ export interface OriProjectByName {
108
+ cwd: string | null;
109
+ sessions: SessionFile[];
110
+ }
111
+
112
+ /** Resolve the ori sessions for a project URL slug (the encoded-cwd folder). */
113
+ export async function getOriSessionsByEncodedName(name: string): Promise<OriProjectByName> {
114
+ const sessions = await getOriSessions();
115
+ const matched = sessions.filter((s) => s.cwd && s.projectName === name);
116
+ if (matched.length === 0) return { cwd: null, sessions: [] };
117
+
118
+ const sorted = [...matched].sort((a, b) => b.mtimeMs - a.mtimeMs);
119
+ const cwd = sorted[0].cwd ?? null;
120
+ return {
121
+ cwd,
122
+ sessions: sorted.map((s) => {
123
+ const lastModified = new Date(s.mtimeMs);
124
+ return {
125
+ name: s.title ?? s.sessionId,
126
+ path: `ori-db://${s.sessionId}`,
127
+ lastModified,
128
+ lastModifiedFormatted: formatDate(lastModified),
129
+ sessionId: s.sessionId,
130
+ cli: "ori" as const,
131
+ };
132
+ }),
133
+ };
134
+ }
135
+
136
+ export const getCachedOriProjects = runtimeCache(getOriProjects, 2);
137
+ export const getCachedOriSessionsByEncodedName = runtimeCache(
138
+ (name: string) => getOriSessionsByEncodedName(name),
139
+ 2,
140
+ { maxSize: 50 },
141
+ );