failproofai 1.0.4 → 1.0.5-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 (168) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/build-manifest.json +6 -6
  3. package/.next/standalone/.next/prerender-manifest.json +4 -4
  4. package/.next/standalone/.next/required-server-files.json +1 -1
  5. package/.next/standalone/.next/server/app/_global-error/page/build-manifest.json +3 -3
  6. package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
  7. package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
  8. package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  9. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  10. package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
  11. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +6 -6
  12. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
  13. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  14. package/.next/standalone/.next/server/app/_not-found/page/build-manifest.json +3 -3
  15. package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  16. package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  17. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  18. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  19. package/.next/standalone/.next/server/app/_not-found.rsc +14 -14
  20. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +14 -14
  21. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +13 -13
  22. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  23. package/.next/standalone/.next/server/app/api/audit/invite/route.js.nft.json +1 -1
  24. package/.next/standalone/.next/server/app/api/audit/run/route.js +4 -4
  25. package/.next/standalone/.next/server/app/api/audit/run/route.js.nft.json +1 -1
  26. package/.next/standalone/.next/server/app/api/audit/status/route.js.nft.json +1 -1
  27. package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -1
  28. package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -1
  29. package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
  30. package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -1
  31. package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js +1 -1
  32. package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
  33. package/.next/standalone/.next/server/app/audit/page/build-manifest.json +3 -3
  34. package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
  35. package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
  36. package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
  37. package/.next/standalone/.next/server/app/index.html +1 -1
  38. package/.next/standalone/.next/server/app/index.rsc +14 -14
  39. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +13 -13
  40. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +14 -14
  41. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  42. package/.next/standalone/.next/server/app/page/build-manifest.json +3 -3
  43. package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
  44. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  45. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  46. package/.next/standalone/.next/server/app/policies/page/build-manifest.json +3 -3
  47. package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +14 -14
  48. package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
  49. package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
  50. package/.next/standalone/.next/server/app/project/[name]/page/build-manifest.json +3 -3
  51. package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
  52. package/.next/standalone/.next/server/app/project/[name]/page.js +2 -2
  53. package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
  54. package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
  55. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/build-manifest.json +3 -3
  56. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
  57. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
  58. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js +2 -2
  59. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
  60. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
  61. package/.next/standalone/.next/server/app/projects/page/build-manifest.json +3 -3
  62. package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
  63. package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
  64. package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  65. package/.next/standalone/.next/server/app/settings/page/build-manifest.json +3 -3
  66. package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +4 -4
  67. package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -1
  68. package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  69. package/.next/standalone/.next/server/chunks/{[externals]__0-9ti7z._.js → [externals]__1_bftcl._.js} +1 -1
  70. package/.next/standalone/.next/server/chunks/{[externals]__0u3wrvq._.js → [externals]__1msfs-h._.js} +1 -1
  71. package/.next/standalone/.next/server/chunks/[root-of-the-server]__08dchfu._.js +1 -1
  72. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0faqz9x._.js +22 -0
  73. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0o07qi9._.js +1 -1
  74. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0zyc_nm._.js +3 -0
  75. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__1p-qi2t._.js → [root-of-the-server]__112b4go._.js} +22 -3
  76. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1l71g3y._.js +22 -0
  77. package/.next/standalone/.next/server/chunks/_0tovk6q._.js +1 -1
  78. package/.next/standalone/.next/server/chunks/_0trp3yc._.js +1 -1
  79. package/.next/standalone/.next/server/chunks/{_1-akg6w._.js → _1c3k-8x._.js} +2 -2
  80. package/.next/standalone/.next/server/chunks/_1ek68ln._.js +1 -1
  81. package/.next/standalone/.next/server/chunks/lib_openclaw-projects_ts_0gc-p24._.js +3 -0
  82. package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
  83. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__00y9ww2._.js +22 -0
  84. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__013jr2b._.js +2 -2
  85. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__01wy8d-._.js +2 -2
  86. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__02npjtd._.js +2 -2
  87. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__09flfsx._.js → [root-of-the-server]__05g1k7_._.js} +2 -2
  88. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0da85px._.js +2 -2
  89. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ftmoxc._.js +2 -2
  90. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0oa1lav._.js +1 -1
  91. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0p-5p8u._.js +2 -2
  92. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0s740oi._.js +2 -2
  93. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0sz_5na._.js +3 -0
  94. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1ctpynv._.js +1 -1
  95. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1kaotix._.js +22 -0
  96. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1p2otjt._.js +2 -2
  97. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1u6sn69._.js +3 -0
  98. package/.next/standalone/.next/server/chunks/ssr/_08x1r5t._.js +1 -1
  99. package/.next/standalone/.next/server/chunks/ssr/{_02yoeej._.js → _0iv28v5._.js} +1 -1
  100. package/.next/standalone/.next/server/chunks/ssr/{_1if9ixi._.js → _14c6q09._.js} +21 -2
  101. package/.next/standalone/.next/server/chunks/ssr/{_04rbnaq._.js → _17noq1a._.js} +2 -2
  102. package/.next/standalone/.next/server/chunks/ssr/_1u8-lu2._.js +1 -1
  103. package/.next/standalone/.next/server/chunks/ssr/_1zopuov._.js +1 -1
  104. package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_policies_page_actions_1sp2-yo.js +2 -2
  105. package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +1 -1
  106. package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x._.js +1 -1
  107. package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpc._.js +1 -1
  108. package/.next/standalone/.next/server/chunks/ssr/app_settings_settings-client_tsx_20lq-mq._.js +1 -1
  109. package/.next/standalone/.next/server/chunks/ssr/lib_codex-projects_ts_0pqlw37._.js +1 -1
  110. package/.next/standalone/.next/server/chunks/ssr/lib_openclaw-projects_ts_0qxq3bp._.js +1 -1
  111. package/.next/standalone/.next/server/middleware-build-manifest.js +6 -6
  112. package/.next/standalone/.next/server/pages/404.html +1 -1
  113. package/.next/standalone/.next/server/pages/500.html +1 -1
  114. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  115. package/.next/standalone/.next/server/server-reference-manifest.json +19 -19
  116. package/.next/standalone/.next/static/chunks/{3tjji451hrgc0.js → 074xcclgow3yh.js} +1 -1
  117. package/.next/standalone/.next/static/chunks/{31u94yukw9fz-.js → 0qytob94jbzs6.js} +1 -1
  118. package/.next/standalone/.next/static/chunks/25cn9xpv4r1ow.js +1 -0
  119. package/.next/standalone/.next/static/chunks/{1j6o9min_6qa9.js → 26tf_lpco5n-v.js} +1 -1
  120. package/.next/standalone/.next/static/chunks/{0-tyrpwuc3lla.js → 2b014kj28p0vz.js} +1 -1
  121. package/.next/standalone/.next/static/chunks/{2lwipmv5etc8m.js → 3_fnbc-v5r-9e.js} +1 -1
  122. package/.next/standalone/.next/static/chunks/{1c6aptmytnu6q.js → 3kltzmx9k_t6x.js} +1 -1
  123. package/.next/standalone/.next/static/chunks/{27cl8h-c2w7cd.js → 3pmi7qhtmniku.js} +1 -1
  124. package/.next/standalone/.next/static/chunks/{2u8vh73tpw28_.js → 3q1rji38vuvr4.js} +1 -1
  125. package/.next/standalone/.next/static/chunks/{0ca7octhod0g2.js → 3qxl_gibq3bas.js} +1 -1
  126. package/.next/standalone/.next/static/chunks/{3p9_8x5ezce-9.js → 3vjaz4hld9oo8.js} +1 -1
  127. package/.next/standalone/.next/static/chunks/{2zafgs90r_leq.js → 41ejnuj2d9g7_.js} +1 -1
  128. package/.next/standalone/.next/static/chunks/{turbopack-3p73obe0xmrxm.js → turbopack-1xgsp63yhrdu5.js} +1 -1
  129. package/.next/standalone/fp-cloud-cli/CHANGELOG.md +7 -0
  130. package/.next/standalone/fp-cloud-cli/fp_cli/_version.py +1 -1
  131. package/.next/standalone/lib/download-session.ts +58 -13
  132. package/.next/standalone/lib/openclaw-db.ts +271 -0
  133. package/.next/standalone/lib/openclaw-projects.ts +54 -18
  134. package/.next/standalone/lib/openclaw-sessions.ts +75 -17
  135. package/.next/standalone/package.json +9 -9
  136. package/.next/standalone/sdk/python/CHANGELOG.md +38 -8
  137. package/.next/standalone/sdk/python/failproofai_sdk/_events.py +20 -0
  138. package/.next/standalone/sdk/python/failproofai_sdk/_redact.py +233 -0
  139. package/.next/standalone/sdk/python/failproofai_sdk/_version.py +1 -1
  140. package/.next/standalone/sdk/python/failproofai_sdk/_writer.py +4 -1
  141. package/.next/standalone/sdk/python/failproofai_sdk/integrations/llama_index.py +5 -5
  142. package/.next/standalone/sdk/python/tests/integrations/test_llama_index.py +2 -2
  143. package/.next/standalone/sdk/python/tests/test_redaction.py +140 -0
  144. package/.next/standalone/sdk/python/tests/test_sdk.py +87 -0
  145. package/.next/standalone/sdk/python/tests/test_server_contract.py +60 -0
  146. package/.next/standalone/sdk/python/tests/test_site_docs.py +2 -2
  147. package/.next/standalone/server.js +1 -1
  148. package/dist/cli.mjs +466 -255
  149. package/dist/worker.mjs +301 -90
  150. package/lib/download-session.ts +58 -13
  151. package/lib/openclaw-db.ts +271 -0
  152. package/lib/openclaw-projects.ts +54 -18
  153. package/lib/openclaw-sessions.ts +75 -17
  154. package/openclaw-plugin/index.js +10 -6
  155. package/openclaw-plugin/instruct-retry-gate.js +89 -0
  156. package/package.json +9 -9
  157. package/src/hooks/policy-evaluator.ts +22 -3
  158. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0-219ec._.js +0 -3
  159. package/.next/standalone/.next/server/chunks/[root-of-the-server]__04_h-a5._.js +0 -3
  160. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1le9jqc._.js +0 -3
  161. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__00-s7h8._.js +0 -3
  162. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__190won8._.js +0 -3
  163. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1nq7ivq._.js +0 -3
  164. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1sc84bb._.js +0 -3
  165. package/.next/standalone/.next/static/chunks/2pd16tn5qmx13.js +0 -1
  166. /package/.next/standalone/.next/static/{dg8VQ7Ejlo0Qsh_x92oIt → Qexks15mjEoPt6cN3D2jb}/_buildManifest.js +0 -0
  167. /package/.next/standalone/.next/static/{dg8VQ7Ejlo0Qsh_x92oIt → Qexks15mjEoPt6cN3D2jb}/_clientMiddlewareManifest.js +0 -0
  168. /package/.next/standalone/.next/static/{dg8VQ7Ejlo0Qsh_x92oIt → Qexks15mjEoPt6cN3D2jb}/_ssgManifest.js +0 -0
@@ -1 +1 @@
1
- (globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,{otherChunks:["static/chunks/1c6aptmytnu6q.js","static/chunks/2yuzx8716maf0.js","static/chunks/3i8rg2fv9nd6e.js","static/chunks/2zafgs90r_leq.js"],runtimeModuleIds:[94553]}]),(()=>{let e;if(!Array.isArray(globalThis.TURBOPACK))return;var t,r=function(){if(null!=self.TURBOPACK_ASSET_SUFFIX)return self.TURBOPACK_ASSET_SUFFIX;let e=document?.currentScript?.getAttribute?.("src")??"",t=e.indexOf("?");return t>=0?e.slice(t):""}(),n=((t=n||{})[t.Runtime=0]="Runtime",t[t.Parent=1]="Parent",t[t.Update=2]="Update",t);let o=new WeakMap;function l(e,t){this.m=e,this.e=t}let i=l.prototype,u=Object.prototype.hasOwnProperty,s="u">typeof Symbol&&Symbol.toStringTag;function c(e,t,r){u.call(e,t)||Object.defineProperty(e,t,r)}function a(e,t){let r=e[t];return r||(r=f(t),e[t]=r),r}function f(e){return{exports:{},error:void 0,id:e,namespaceObject:void 0}}function p(e,t,r){c(e,"__esModule",{value:!0}),s&&c(e,s,{value:"Module"});let n=0;for(;n<t.length;){let r=t[n++],o=t[n++];if("number"==typeof o)if(0===o)c(e,r,{value:t[n++],enumerable:!0,writable:!1});else throw Error(`unexpected tag: ${o}`);else"function"==typeof t[n]?c(e,r,{get:o,set:t[n++],enumerable:!0}):c(e,r,{get:o,enumerable:!0})}r||Object.seal(e)}function h(e,t){(null!=t?a(this.c,t):this.m).exports=e}i.s=function(e,t,r){let n,o;null!=t?o=(n=a(this.c,t)).exports:(n=this.m,o=this.e),n.namespaceObject=o,p(o,e,r)},i.j=function(e,t){let r,n;null!=t?n=(r=a(this.c,t)).exports:(r=this.m,n=this.e);let l=function(e,t){let r=o.get(e);if(!r){o.set(e,r=[]);let n=e=>{if("default"!==e){for(let t of r)if(u.call(t,e))return t}};e.exports=e.namespaceObject=new Proxy(t,{get(e,t){if(u.call(e,t)||"default"===t||"__esModule"===t)return Reflect.get(e,t);let r=n(t);return r&&Reflect.get(r,t)},set:()=>!1,defineProperty:()=>!1,deleteProperty:()=>!1,has:(e,t)=>!!Reflect.has(e,t)||"default"!==t&&"__esModule"!==t&&void 0!==n(t),ownKeys(e){let t=Reflect.ownKeys(e);for(let e of r)for(let r of Reflect.ownKeys(e))"default"===r||t.includes(r)||t.push(r);return t},getOwnPropertyDescriptor(e,t){let r=Reflect.getOwnPropertyDescriptor(e,t);if(r||"default"===t||"__esModule"===t)return r;let o=n(t);if(o)return{enumerable:!0,configurable:!0,get:()=>Reflect.get(o,t)}}})}return r}(r,n);"object"==typeof e&&null!==e&&l.push(e)},i.v=h,i.n=function(e,t){let r;(r=null!=t?a(this.c,t):this.m).exports=r.namespaceObject=e};let d=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,m=[null,d({}),d([]),d(d)];function y(e,t,r){let n=[],o=-1;for(let t=e;("object"==typeof t||"function"==typeof t)&&!m.includes(t);t=d(t))for(let r of Object.getOwnPropertyNames(t))n.push(r,function(e,t){return()=>e[t]}(e,r)),-1===o&&"default"===r&&(o=n.length-1);return r&&o>=0||(o>=0?n.splice(o,1,0,e):n.push("default",0,e)),p(t,n),t}function g(e){let t=K(e,this.m);if(t.namespaceObject)return t.namespaceObject;let r=t.exports;return t.namespaceObject=y(r,"function"==typeof r?function(...e){return r.apply(this,e)}:Object.create(null),r&&r.__esModule)}function b(e){let t=e.indexOf("#");-1!==t&&(e=e.substring(0,t));let r=e.indexOf("?");return -1!==r&&(e=e.substring(0,r)),e}i.i=g,i.A=function(e){return this.r(e)(g.bind(this))},i.t="function"==typeof require?require:function(){throw Error("Unexpected use of runtime require")},i.r=function(e){return K(e,this.m).exports},i.f=function(e){function t(t){if(t=b(t),u.call(e,t))return e[t].module();let r=Error(`Cannot find module '${t}'`);throw r.code="MODULE_NOT_FOUND",r}return t.keys=()=>Object.keys(e),t.resolve=t=>{if(t=b(t),u.call(e,t))return e[t].id();let r=Error(`Cannot find module '${t}'`);throw r.code="MODULE_NOT_FOUND",r},t.import=async e=>await t(e),t};let O=function(e){let t=new URL(e,"x:/"),r={};for(let e in t)r[e]=t[e];for(let t in r.href=e,r.pathname=e.replace(/[?#].*/,""),r.origin=r.protocol="",r.toString=r.toJSON=(...t)=>e,r)Object.defineProperty(this,t,{enumerable:!0,configurable:!0,value:r[t]})};function w(e,t){throw Error(`Invariant: ${t(e)}`)}O.prototype=URL.prototype,i.U=O,i.z=function(e){throw Error("dynamic usage of require is not supported")},i.g=globalThis;let R=l.prototype,k="string"==typeof TURBOPACK_CHUNK_BASE_PATH?TURBOPACK_CHUNK_BASE_PATH:"/_next/",U=new Map;i.M=U;let _=new Map,v=new Map,P=new Map;async function C(e,t,r){let n;if("string"==typeof r)return function(e,t,r){return A(e,t,r)}(e,t,E(r));let o=r.included||[],l=o.map(e=>!!U.has(e)||_.get(e));if(l.length>0&&l.every(e=>e))return void await Promise.all(l);for(let l of(n=A(e,t,E(r.path)),o))_.has(l)||_.set(l,n);await n}R.l=function(e){return C(n.Parent,this.m.id,e)};let j=Promise.resolve(void 0),$=new WeakMap;function A(t,r,o){let l=e.loadChunkCached(t,o),i=$.get(l);if(void 0===i){let e=$.set.bind($,l,j);i=l.then(e).catch(e=>{let l;switch(t){case n.Runtime:l=`as a runtime dependency of chunk ${r}`;break;case n.Parent:l=`from module ${r}`;break;case n.Update:l="from an HMR update";break;default:w(t,e=>`Unknown source type: ${e}`)}let i=Error(`Failed to load chunk ${o} ${l}${e?`: ${e}`:""}`,e?{cause:e}:void 0);throw i.name="ChunkLoadError",i}),$.set(l,i)}return i}R.L=function(e){var t,r;return t=n.Parent,r=this.m.id,A(t,r,e)};R.R=function(e){let t=this.r(e);return t?.default??t},R.P=function(e){return`/ROOT/${e??""}`},R.F=function(e){return e?`file:///ROOT/${e.split("/").map(encodeURIComponent).join("/")}`:"file:///ROOT/"},R.q=function(e,t){h.call(this,`${e}${r}`,t)};let T=/[^A-Za-z0-9\-_.!~*'()/]/;function E(e,t=k){let n=T.test(e)?e.split("/").map(encodeURIComponent).join("/"):e;return`${t}${n}${r}`}function S(e,t){let r,n=e.indexOf("?");if(-1!==n)r=n;else{let t=e.indexOf("#");r=-1!==t?t:e.length}return r>=t.length&&e.startsWith(t,r-t.length)}R.b=k,R.X=r,R.h=E;function M(e){return S(e,".css")}let x={};i.c=x;let K=(e,t)=>{let r=x[e];if(r){if(r.error)throw r.error;return r}return N(e,n.Parent,t.id)};function N(e,t,r){let n=U.get(e);if("function"!=typeof n)throw Error(function(e,t,r){let n;switch(t){case 0:n=`as a runtime entry of chunk ${r}`;break;case 1:n=`because it was required from module ${r}`;break;case 2:n="because of an HMR update";break;default:w(t,e=>`Unknown source type: ${e}`)}return`Module ${e} was instantiated ${n}, but the module factory is not available.`}(e,t,r));let o=f(e),i=o.exports;x[e]=o;let u=new l(o,i);try{n(u,o,i)}catch(e){throw o.error=e,e}return o.namespaceObject&&o.exports!==o.namespaceObject&&y(o.exports,o.namespaceObject),o}function B(t){let r;if(!Array.isArray(t))return e.registerChunk(void 0,t);let n=function(e){if("string"==typeof e)return e;if(e)return{src:e.getAttribute("src")};if("u">typeof TURBOPACK_NEXT_CHUNK_URLS)return{src:TURBOPACK_NEXT_CHUNK_URLS.pop()};throw Error("chunk path empty but not in a worker")}(t[0]);return 2===t.length?r=t[1]:(r=void 0,!function(e,t){let r=1;for(;r<e.length;){let n,o=r+1;for(;o<e.length&&"function"!=typeof e[o];)o++;if(o===e.length)throw Error("malformed chunk format, expected a factory function");let l=e[o];for(let l=r;l<o;l++){let r=e[l],o=t.get(r);if(o){n=o;break}}let i=n??l,u=!1;for(let n=r;n<o;n++){let r=e[n];t.has(r)||(u||(i===l&&Object.defineProperty(l,"name",{value:"module evaluation"}),u=!0),t.set(r,i))}r=o+1}}(t,U)),e.registerChunk(n,r)}let L=new Map;function q(e){let t=L.get(e);if(!t){let r,n;t={resolved:!1,loadingStarted:!1,retryAttempts:0,promise:new Promise((e,t)=>{r=e,n=t}),resolve:()=>{t.resolved=!0,r()},reject:n},L.set(e,t)}return t}function I(e,t,r,n,o){!(null==n||n instanceof DOMException&&"NetworkError"===n.name)||r.retryAttempts>=1||L.get(t)!==r?(L.get(t)===r&&L.delete(t),r.reject(n)):(r.retryAttempts++,setTimeout(()=>{r.resolved||L.get(t)!==r||(o?o():(r.loadingStarted=!1,H(e,t)))},200+Math.floor(401*Math.random())))}function H(e,t){let r=q(t);if(r.loadingStarted)return r.promise;if(e===n.Runtime)return r.loadingStarted=!0,M(t)&&r.resolve(),r.promise;if("function"==typeof importScripts)if(M(t));else if(S(t,".js")){self.TURBOPACK_NEXT_CHUNK_URLS.push(t);try{importScripts(t)}catch(n){I(e,t,r,n)}}else throw Error(`can't infer type of chunk from URL ${t} in worker`);else{let n=decodeURI(t);if(M(t))if(document.querySelectorAll(`link[rel=stylesheet][href="${t}"],link[rel=stylesheet][href^="${t}?"],link[rel=stylesheet][href="${n}"],link[rel=stylesheet][href^="${n}?"]`).length>0)r.resolve();else{let n=()=>{let o=document.createElement("link");return o.rel="stylesheet",o.crossOrigin=null,o.href=t,o.onerror=()=>{let l=document.createComment("");o.replaceWith(l),I(e,t,r,void 0,()=>l.replaceWith(n()))},o.onload=()=>{r.resolve()},o};document.head.appendChild(n())}else if(S(t,".js")){let o=document.querySelectorAll(`script[src="${t}"],script[src^="${t}?"],script[src="${n}"],script[src^="${n}?"]`);if(o.length>0)for(let n of Array.from(o))n.addEventListener("error",()=>{n.remove(),I(e,t,r)},{once:!0});else{let n=document.createElement("script");n.crossOrigin=null,n.src=t,n.onerror=()=>{n.remove(),I(e,t,r)},document.head.appendChild(n)}}else throw Error(`can't infer type of chunk from URL ${t}`)}return r.loadingStarted=!0,r.promise}e={async registerChunk(e,t){let r;if(null!=e&&(r=function(e){if("string"==typeof e)return e;let t=decodeURIComponent(e.src.replace(/[?#].*$/,""));return t.startsWith(k)?t.slice(k.length):t}(e),q("string"==typeof e?E(e):e.src).resolve()),null!=t){for(let e of t.otherChunks)q(E("string"==typeof e?e:e.path));if(await Promise.all(t.otherChunks.map(e=>{var t;return t=r,C(n.Runtime,t,e)})),t.runtimeModuleIds.length>0)for(let e of t.runtimeModuleIds)!function(e,t){let r=x[t];if(r){if(r.error)throw r.error;return}N(t,n.Runtime,e)}(r,e)}},loadChunkCached:(e,t)=>H(e,t)};var F=globalThis.TURBOPACK;globalThis.TURBOPACK={push:B},F.forEach(B)})();
1
+ (globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,{otherChunks:["static/chunks/3kltzmx9k_t6x.js","static/chunks/2yuzx8716maf0.js","static/chunks/3i8rg2fv9nd6e.js","static/chunks/41ejnuj2d9g7_.js"],runtimeModuleIds:[94553]}]),(()=>{let e;if(!Array.isArray(globalThis.TURBOPACK))return;var t,r=function(){if(null!=self.TURBOPACK_ASSET_SUFFIX)return self.TURBOPACK_ASSET_SUFFIX;let e=document?.currentScript?.getAttribute?.("src")??"",t=e.indexOf("?");return t>=0?e.slice(t):""}(),n=((t=n||{})[t.Runtime=0]="Runtime",t[t.Parent=1]="Parent",t[t.Update=2]="Update",t);let o=new WeakMap;function l(e,t){this.m=e,this.e=t}let i=l.prototype,u=Object.prototype.hasOwnProperty,s="u">typeof Symbol&&Symbol.toStringTag;function c(e,t,r){u.call(e,t)||Object.defineProperty(e,t,r)}function a(e,t){let r=e[t];return r||(r=f(t),e[t]=r),r}function f(e){return{exports:{},error:void 0,id:e,namespaceObject:void 0}}function p(e,t,r){c(e,"__esModule",{value:!0}),s&&c(e,s,{value:"Module"});let n=0;for(;n<t.length;){let r=t[n++],o=t[n++];if("number"==typeof o)if(0===o)c(e,r,{value:t[n++],enumerable:!0,writable:!1});else throw Error(`unexpected tag: ${o}`);else"function"==typeof t[n]?c(e,r,{get:o,set:t[n++],enumerable:!0}):c(e,r,{get:o,enumerable:!0})}r||Object.seal(e)}function d(e,t){(null!=t?a(this.c,t):this.m).exports=e}i.s=function(e,t,r){let n,o;null!=t?o=(n=a(this.c,t)).exports:(n=this.m,o=this.e),n.namespaceObject=o,p(o,e,r)},i.j=function(e,t){let r,n;null!=t?n=(r=a(this.c,t)).exports:(r=this.m,n=this.e);let l=function(e,t){let r=o.get(e);if(!r){o.set(e,r=[]);let n=e=>{if("default"!==e){for(let t of r)if(u.call(t,e))return t}};e.exports=e.namespaceObject=new Proxy(t,{get(e,t){if(u.call(e,t)||"default"===t||"__esModule"===t)return Reflect.get(e,t);let r=n(t);return r&&Reflect.get(r,t)},set:()=>!1,defineProperty:()=>!1,deleteProperty:()=>!1,has:(e,t)=>!!Reflect.has(e,t)||"default"!==t&&"__esModule"!==t&&void 0!==n(t),ownKeys(e){let t=Reflect.ownKeys(e);for(let e of r)for(let r of Reflect.ownKeys(e))"default"===r||t.includes(r)||t.push(r);return t},getOwnPropertyDescriptor(e,t){let r=Reflect.getOwnPropertyDescriptor(e,t);if(r||"default"===t||"__esModule"===t)return r;let o=n(t);if(o)return{enumerable:!0,configurable:!0,get:()=>Reflect.get(o,t)}}})}return r}(r,n);"object"==typeof e&&null!==e&&l.push(e)},i.v=d,i.n=function(e,t){let r;(r=null!=t?a(this.c,t):this.m).exports=r.namespaceObject=e};let h=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,m=[null,h({}),h([]),h(h)];function y(e,t,r){let n=[],o=-1;for(let t=e;("object"==typeof t||"function"==typeof t)&&!m.includes(t);t=h(t))for(let r of Object.getOwnPropertyNames(t))n.push(r,function(e,t){return()=>e[t]}(e,r)),-1===o&&"default"===r&&(o=n.length-1);return r&&o>=0||(o>=0?n.splice(o,1,0,e):n.push("default",0,e)),p(t,n),t}function g(e){let t=K(e,this.m);if(t.namespaceObject)return t.namespaceObject;let r=t.exports;return t.namespaceObject=y(r,"function"==typeof r?function(...e){return r.apply(this,e)}:Object.create(null),r&&r.__esModule)}function b(e){let t=e.indexOf("#");-1!==t&&(e=e.substring(0,t));let r=e.indexOf("?");return -1!==r&&(e=e.substring(0,r)),e}i.i=g,i.A=function(e){return this.r(e)(g.bind(this))},i.t="function"==typeof require?require:function(){throw Error("Unexpected use of runtime require")},i.r=function(e){return K(e,this.m).exports},i.f=function(e){function t(t){if(t=b(t),u.call(e,t))return e[t].module();let r=Error(`Cannot find module '${t}'`);throw r.code="MODULE_NOT_FOUND",r}return t.keys=()=>Object.keys(e),t.resolve=t=>{if(t=b(t),u.call(e,t))return e[t].id();let r=Error(`Cannot find module '${t}'`);throw r.code="MODULE_NOT_FOUND",r},t.import=async e=>await t(e),t};let O=function(e){let t=new URL(e,"x:/"),r={};for(let e in t)r[e]=t[e];for(let t in r.href=e,r.pathname=e.replace(/[?#].*/,""),r.origin=r.protocol="",r.toString=r.toJSON=(...t)=>e,r)Object.defineProperty(this,t,{enumerable:!0,configurable:!0,value:r[t]})};function w(e,t){throw Error(`Invariant: ${t(e)}`)}O.prototype=URL.prototype,i.U=O,i.z=function(e){throw Error("dynamic usage of require is not supported")},i.g=globalThis;let k=l.prototype,R="string"==typeof TURBOPACK_CHUNK_BASE_PATH?TURBOPACK_CHUNK_BASE_PATH:"/_next/",U=new Map;i.M=U;let _=new Map,v=new Map,P=new Map;async function j(e,t,r){let n;if("string"==typeof r)return function(e,t,r){return A(e,t,r)}(e,t,E(r));let o=r.included||[],l=o.map(e=>!!U.has(e)||_.get(e));if(l.length>0&&l.every(e=>e))return void await Promise.all(l);for(let l of(n=A(e,t,E(r.path)),o))_.has(l)||_.set(l,n);await n}k.l=function(e){return j(n.Parent,this.m.id,e)};let C=Promise.resolve(void 0),$=new WeakMap;function A(t,r,o){let l=e.loadChunkCached(t,o),i=$.get(l);if(void 0===i){let e=$.set.bind($,l,C);i=l.then(e).catch(e=>{let l;switch(t){case n.Runtime:l=`as a runtime dependency of chunk ${r}`;break;case n.Parent:l=`from module ${r}`;break;case n.Update:l="from an HMR update";break;default:w(t,e=>`Unknown source type: ${e}`)}let i=Error(`Failed to load chunk ${o} ${l}${e?`: ${e}`:""}`,e?{cause:e}:void 0);throw i.name="ChunkLoadError",i}),$.set(l,i)}return i}k.L=function(e){var t,r;return t=n.Parent,r=this.m.id,A(t,r,e)};k.R=function(e){let t=this.r(e);return t?.default??t},k.P=function(e){return`/ROOT/${e??""}`},k.F=function(e){return e?`file:///ROOT/${e.split("/").map(encodeURIComponent).join("/")}`:"file:///ROOT/"},k.q=function(e,t){d.call(this,`${e}${r}`,t)};let T=/[^A-Za-z0-9\-_.!~*'()/]/;function E(e,t=R){let n=T.test(e)?e.split("/").map(encodeURIComponent).join("/"):e;return`${t}${n}${r}`}function S(e,t){let r,n=e.indexOf("?");if(-1!==n)r=n;else{let t=e.indexOf("#");r=-1!==t?t:e.length}return r>=t.length&&e.startsWith(t,r-t.length)}k.b=R,k.X=r,k.h=E;function x(e){return S(e,".css")}let M={};i.c=M;let K=(e,t)=>{let r=M[e];if(r){if(r.error)throw r.error;return r}return N(e,n.Parent,t.id)};function N(e,t,r){let n=U.get(e);if("function"!=typeof n)throw Error(function(e,t,r){let n;switch(t){case 0:n=`as a runtime entry of chunk ${r}`;break;case 1:n=`because it was required from module ${r}`;break;case 2:n="because of an HMR update";break;default:w(t,e=>`Unknown source type: ${e}`)}return`Module ${e} was instantiated ${n}, but the module factory is not available.`}(e,t,r));let o=f(e),i=o.exports;M[e]=o;let u=new l(o,i);try{n(u,o,i)}catch(e){throw o.error=e,e}return o.namespaceObject&&o.exports!==o.namespaceObject&&y(o.exports,o.namespaceObject),o}function B(t){let r;if(!Array.isArray(t))return e.registerChunk(void 0,t);let n=function(e){if("string"==typeof e)return e;if(e)return{src:e.getAttribute("src")};if("u">typeof TURBOPACK_NEXT_CHUNK_URLS)return{src:TURBOPACK_NEXT_CHUNK_URLS.pop()};throw Error("chunk path empty but not in a worker")}(t[0]);return 2===t.length?r=t[1]:(r=void 0,!function(e,t){let r=1;for(;r<e.length;){let n,o=r+1;for(;o<e.length&&"function"!=typeof e[o];)o++;if(o===e.length)throw Error("malformed chunk format, expected a factory function");let l=e[o];for(let l=r;l<o;l++){let r=e[l],o=t.get(r);if(o){n=o;break}}let i=n??l,u=!1;for(let n=r;n<o;n++){let r=e[n];t.has(r)||(u||(i===l&&Object.defineProperty(l,"name",{value:"module evaluation"}),u=!0),t.set(r,i))}r=o+1}}(t,U)),e.registerChunk(n,r)}let L=new Map;function I(e){let t=L.get(e);if(!t){let r,n;t={resolved:!1,loadingStarted:!1,retryAttempts:0,promise:new Promise((e,t)=>{r=e,n=t}),resolve:()=>{t.resolved=!0,r()},reject:n},L.set(e,t)}return t}function H(e,t,r,n,o){!(null==n||n instanceof DOMException&&"NetworkError"===n.name)||r.retryAttempts>=1||L.get(t)!==r?(L.get(t)===r&&L.delete(t),r.reject(n)):(r.retryAttempts++,setTimeout(()=>{r.resolved||L.get(t)!==r||(o?o():(r.loadingStarted=!1,q(e,t)))},200+Math.floor(401*Math.random())))}function q(e,t){let r=I(t);if(r.loadingStarted)return r.promise;if(e===n.Runtime)return r.loadingStarted=!0,x(t)&&r.resolve(),r.promise;if("function"==typeof importScripts)if(x(t));else if(S(t,".js")){self.TURBOPACK_NEXT_CHUNK_URLS.push(t);try{importScripts(t)}catch(n){H(e,t,r,n)}}else throw Error(`can't infer type of chunk from URL ${t} in worker`);else{let n=decodeURI(t);if(x(t))if(document.querySelectorAll(`link[rel=stylesheet][href="${t}"],link[rel=stylesheet][href^="${t}?"],link[rel=stylesheet][href="${n}"],link[rel=stylesheet][href^="${n}?"]`).length>0)r.resolve();else{let n=()=>{let o=document.createElement("link");return o.rel="stylesheet",o.crossOrigin=null,o.href=t,o.onerror=()=>{let l=document.createComment("");o.replaceWith(l),H(e,t,r,void 0,()=>l.replaceWith(n()))},o.onload=()=>{r.resolve()},o};document.head.appendChild(n())}else if(S(t,".js")){let o=document.querySelectorAll(`script[src="${t}"],script[src^="${t}?"],script[src="${n}"],script[src^="${n}?"]`);if(o.length>0)for(let n of Array.from(o))n.addEventListener("error",()=>{n.remove(),H(e,t,r)},{once:!0});else{let n=document.createElement("script");n.crossOrigin=null,n.src=t,n.onerror=()=>{n.remove(),H(e,t,r)},document.head.appendChild(n)}}else throw Error(`can't infer type of chunk from URL ${t}`)}return r.loadingStarted=!0,r.promise}e={async registerChunk(e,t){let r;if(null!=e&&(r=function(e){if("string"==typeof e)return e;let t=decodeURIComponent(e.src.replace(/[?#].*$/,""));return t.startsWith(R)?t.slice(R.length):t}(e),I("string"==typeof e?E(e):e.src).resolve()),null!=t){for(let e of t.otherChunks)I(E("string"==typeof e?e:e.path));if(await Promise.all(t.otherChunks.map(e=>{var t;return t=r,j(n.Runtime,t,e)})),t.runtimeModuleIds.length>0)for(let e of t.runtimeModuleIds)!function(e,t){let r=M[t];if(r){if(r.error)throw r.error;return}N(t,n.Runtime,e)}(r,e)}},loadChunkCached:(e,t)=>q(e,t)};var F=globalThis.TURBOPACK;globalThis.TURBOPACK={push:B},F.forEach(B)})();
@@ -1,5 +1,12 @@
1
1
  # Changelog — `fp` CLI
2
2
 
3
+ ## 0.0.1b3 — 2026-09-12
4
+
5
+ Open for the next release. `0.0.1b2` published on 2026-09-12 and the `bump` job
6
+ moved the version here automatically; nothing has landed against `0.0.1b3` yet.
7
+ Add entries as changes merge — this section becomes the GitHub Release body when
8
+ it ships.
9
+
3
10
  ## 0.0.1b2 — 2026-08-25
4
11
 
5
12
  Open for the next release. `0.0.1b1` published on 2026-08-24 and the `bump` job
@@ -1 +1 @@
1
- __version__ = "0.0.1b2"
1
+ __version__ = "0.0.1b3"
@@ -2,8 +2,8 @@
2
2
  * Per-CLI dispatcher for the dashboard's Download Logs endpoint.
3
3
  *
4
4
  * Returns either a real on-disk path (so the route can `createReadStream` and
5
- * stream the bytes verbatim) or a synthesized JSONL body (used only by
6
- * OpenCode, whose transcripts live in SQLite rather than on disk).
5
+ * stream the bytes verbatim) or a synthesized JSON/JSONL body for agents whose
6
+ * transcripts live in SQLite.
7
7
  *
8
8
  * Per-CLI session loaders / transcript finders already exist in their own
9
9
  * files; this module is the thin glue that picks the right one. Imports of
@@ -34,7 +34,12 @@ export const GOOSE_SESSION_RE = /^\d{8}_\d+$/;
34
34
 
35
35
  export type DownloadSource =
36
36
  | { kind: "file"; path: string }
37
- | { kind: "synthesized"; body: string; contentType: string; extension: string };
37
+ | {
38
+ kind: "synthesized";
39
+ body: string;
40
+ contentType: string;
41
+ extension: string;
42
+ };
38
43
 
39
44
  /** Validate a session ID against the per-CLI shape. OpenCode uses `ses_*`
40
45
  * prefixes; everyone else is a UUID. */
@@ -98,7 +103,12 @@ export async function resolveDownloadSource(
98
103
  const result = await getOpenCodeSessionExport(sessionId);
99
104
  if (!result) return null;
100
105
  const body = JSON.stringify(result, null, 2) + "\n";
101
- return { kind: "synthesized", body, contentType: "application/json", extension: "json" };
106
+ return {
107
+ kind: "synthesized",
108
+ body,
109
+ contentType: "application/json",
110
+ extension: "json",
111
+ };
102
112
  }
103
113
 
104
114
  if (cli === "hermes") {
@@ -107,13 +117,35 @@ export async function resolveDownloadSource(
107
117
  const { getHermesSessionLog } = await import("./hermes-sessions");
108
118
  const result = await getHermesSessionLog(sessionId);
109
119
  if (!result) return null;
110
- const body = result.rawLines.map((r) => JSON.stringify(r)).join("\n") + "\n";
111
- return { kind: "synthesized", body, contentType: "application/x-ndjson", extension: "jsonl" };
120
+ const body =
121
+ result.rawLines.map((r) => JSON.stringify(r)).join("\n") + "\n";
122
+ return {
123
+ kind: "synthesized",
124
+ body,
125
+ contentType: "application/x-ndjson",
126
+ extension: "jsonl",
127
+ };
112
128
  }
113
129
 
114
130
  if (cli === "openclaw") {
115
- // OpenClaw writes real JSONL transcripts on disk stream the file verbatim.
116
- const { findOpenClawTranscript } = await import("./openclaw-sessions");
131
+ // New OpenClaw versions keep live transcripts in SQLite. Export the exact
132
+ // event_json rows as JSONL; fall back to streaming archived JSONL files.
133
+ const { findOpenClawTranscript, listOpenClawAgents, openclawHome } =
134
+ await import("./openclaw-sessions");
135
+ const { readOpenClawSqliteTranscript } = await import("./openclaw-db");
136
+ const sqlite = await readOpenClawSqliteTranscript(
137
+ openclawHome(),
138
+ listOpenClawAgents(),
139
+ sessionId,
140
+ );
141
+ if (sqlite) {
142
+ return {
143
+ kind: "synthesized",
144
+ body: sqlite.eventJsonLines.join("\n") + "\n",
145
+ contentType: "application/x-ndjson",
146
+ extension: "jsonl",
147
+ };
148
+ }
117
149
  const path = findOpenClawTranscript(sessionId);
118
150
  return path ? { kind: "file", path } : null;
119
151
  }
@@ -131,13 +163,20 @@ export async function resolveDownloadSource(
131
163
  const { getDevinSessionLog } = await import("./devin-sessions");
132
164
  const result = await getDevinSessionLog(sessionId);
133
165
  if (!result) return null;
134
- const body = result.rawLines.map((r) => JSON.stringify(r)).join("\n") + "\n";
135
- return { kind: "synthesized", body, contentType: "application/x-ndjson", extension: "jsonl" };
166
+ const body =
167
+ result.rawLines.map((r) => JSON.stringify(r)).join("\n") + "\n";
168
+ return {
169
+ kind: "synthesized",
170
+ body,
171
+ contentType: "application/x-ndjson",
172
+ extension: "jsonl",
173
+ };
136
174
  }
137
175
 
138
176
  if (cli === "antigravity") {
139
177
  // Antigravity (agy) writes real JSONL transcripts on disk — stream verbatim.
140
- const { findAntigravityTranscript } = await import("./antigravity-sessions");
178
+ const { findAntigravityTranscript } =
179
+ await import("./antigravity-sessions");
141
180
  const path = findAntigravityTranscript(sessionId);
142
181
  return path ? { kind: "file", path } : null;
143
182
  }
@@ -148,8 +187,14 @@ export async function resolveDownloadSource(
148
187
  const { getGooseSessionLog } = await import("./goose-sessions");
149
188
  const result = await getGooseSessionLog(sessionId);
150
189
  if (!result) return null;
151
- const body = result.rawLines.map((r) => JSON.stringify(r)).join("\n") + "\n";
152
- return { kind: "synthesized", body, contentType: "application/x-ndjson", extension: "jsonl" };
190
+ const body =
191
+ result.rawLines.map((r) => JSON.stringify(r)).join("\n") + "\n";
192
+ return {
193
+ kind: "synthesized",
194
+ body,
195
+ contentType: "application/x-ndjson",
196
+ extension: "jsonl",
197
+ };
153
198
  }
154
199
 
155
200
  // Exhaustive — but TypeScript can't always see CliId is exhausted across the
@@ -0,0 +1,271 @@
1
+ /**
2
+ * Read OpenClaw 2026.9.2+ transcripts from the per-agent SQLite databases at
3
+ * `agents/<agentId>/agent/openclaw-agent.sqlite`.
4
+ *
5
+ * `event_json` is the exact logical JSONL record, so the dashboard can feed it
6
+ * through the same parser and download format used by archived JSONL files.
7
+ */
8
+ import { existsSync } from "node:fs";
9
+ import { join } from "node:path";
10
+ import { openSqliteReadonly, type SqliteReader } from "./sqlite-reader";
11
+
12
+ const DB_NAME = "openclaw-agent.sqlite";
13
+
14
+ export interface OpenClawSqliteSession {
15
+ sessionId: string;
16
+ agentId: string;
17
+ dbPath: string;
18
+ transcriptPath: string;
19
+ mtimeMs: number;
20
+ sizeBytes: number;
21
+ channel: string;
22
+ label?: string;
23
+ chatId?: string;
24
+ chatType?: string;
25
+ }
26
+
27
+ export interface OpenClawSqliteTranscript {
28
+ agentId: string;
29
+ dbPath: string;
30
+ filePath: string;
31
+ rawLines: Record<string, unknown>[];
32
+ eventJsonLines: string[];
33
+ }
34
+
35
+ interface WindowRow {
36
+ session_id: string;
37
+ session_key: string;
38
+ updated_at: number;
39
+ transcript_updated_at: number | null;
40
+ ended_at: number | null;
41
+ channel: string | null;
42
+ chat_type: string | null;
43
+ display_name: string | null;
44
+ event_updated_at: number;
45
+ size_bytes: number;
46
+ }
47
+
48
+ interface NodeRow {
49
+ current_session_id: string;
50
+ entry_json: string;
51
+ label: string | null;
52
+ display_name: string | null;
53
+ }
54
+
55
+ interface ConversationRow {
56
+ session_id: string;
57
+ channel: string;
58
+ kind: string;
59
+ peer_id: string;
60
+ delivery_target: string;
61
+ label: string | null;
62
+ }
63
+
64
+ interface EventRow {
65
+ event_json: string;
66
+ }
67
+
68
+ interface SessionMeta {
69
+ channel?: string;
70
+ label?: string;
71
+ chatId?: string;
72
+ chatType?: string;
73
+ }
74
+
75
+ function str(value: unknown): string | undefined {
76
+ return typeof value === "string" && value.length > 0 ? value : undefined;
77
+ }
78
+
79
+ function parseObject(value: string): Record<string, unknown> | undefined {
80
+ try {
81
+ const parsed: unknown = JSON.parse(value);
82
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed)
83
+ ? (parsed as Record<string, unknown>)
84
+ : undefined;
85
+ } catch {
86
+ return undefined;
87
+ }
88
+ }
89
+
90
+ function syntheticPath(agentId: string, sessionId: string): string {
91
+ return `openclaw-sqlite://${encodeURIComponent(agentId)}/${sessionId}`;
92
+ }
93
+
94
+ /** Existing per-agent SQLite databases, derived from the configured agents. */
95
+ export function listOpenClawDatabases(
96
+ home: string,
97
+ agentIds: string[],
98
+ ): Array<{ agentId: string; dbPath: string }> {
99
+ const out: Array<{ agentId: string; dbPath: string }> = [];
100
+ for (const agentId of agentIds) {
101
+ const dbPath = join(home, "agents", agentId, "agent", DB_NAME);
102
+ if (existsSync(dbPath)) out.push({ agentId, dbPath });
103
+ }
104
+ return out;
105
+ }
106
+
107
+ function readNodeMetadata(db: SqliteReader): Map<string, SessionMeta> {
108
+ const out = new Map<string, SessionMeta>();
109
+ let rows: NodeRow[];
110
+ try {
111
+ rows = db.query<NodeRow>(
112
+ `SELECT current_session_id, entry_json, label, display_name
113
+ FROM session_nodes`,
114
+ );
115
+ } catch {
116
+ return out;
117
+ }
118
+ for (const row of rows) {
119
+ const entry = parseObject(row.entry_json) ?? {};
120
+ const origin =
121
+ entry.origin &&
122
+ typeof entry.origin === "object" &&
123
+ !Array.isArray(entry.origin)
124
+ ? (entry.origin as Record<string, unknown>)
125
+ : {};
126
+ out.set(row.current_session_id, {
127
+ channel:
128
+ str(entry.lastChannel) ?? str(origin.provider) ?? str(origin.surface),
129
+ label:
130
+ str(row.label) ??
131
+ str(row.display_name) ??
132
+ str(entry.displayName) ??
133
+ str(origin.label),
134
+ chatId: str(entry.lastTo) ?? str(origin.from),
135
+ chatType: str(entry.chatType) ?? str(origin.chatType),
136
+ });
137
+ }
138
+ return out;
139
+ }
140
+
141
+ function readConversationMetadata(db: SqliteReader): Map<string, SessionMeta> {
142
+ const out = new Map<string, SessionMeta>();
143
+ let rows: ConversationRow[];
144
+ try {
145
+ rows = db.query<ConversationRow>(
146
+ `SELECT sc.session_id, c.channel, c.kind, c.peer_id,
147
+ c.delivery_target, c.label
148
+ FROM session_conversations sc
149
+ JOIN conversations c ON c.conversation_id = sc.conversation_id
150
+ ORDER BY CASE sc.role WHEN 'primary' THEN 0 ELSE 1 END, sc.last_seen_at DESC`,
151
+ );
152
+ } catch {
153
+ return out;
154
+ }
155
+ for (const row of rows) {
156
+ if (out.has(row.session_id)) continue;
157
+ out.set(row.session_id, {
158
+ channel: str(row.channel),
159
+ label: str(row.label),
160
+ chatId: str(row.delivery_target) ?? str(row.peer_id),
161
+ chatType: str(row.kind),
162
+ });
163
+ }
164
+ return out;
165
+ }
166
+
167
+ /** List every transcript-bearing session in all per-agent databases. */
168
+ export async function listOpenClawSqliteSessions(
169
+ home: string,
170
+ agentIds: string[],
171
+ ): Promise<OpenClawSqliteSession[]> {
172
+ const sessions: OpenClawSqliteSession[] = [];
173
+ for (const { agentId, dbPath } of listOpenClawDatabases(home, agentIds)) {
174
+ const db = await openSqliteReadonly(dbPath);
175
+ if (!db) continue;
176
+ try {
177
+ let rows: WindowRow[];
178
+ try {
179
+ rows = db.query<WindowRow>(
180
+ `SELECT w.session_id, w.session_key, w.updated_at,
181
+ w.transcript_updated_at, w.ended_at, w.channel,
182
+ w.chat_type, w.display_name,
183
+ COALESCE((SELECT MAX(e.created_at)
184
+ FROM transcript_events e
185
+ WHERE e.session_id = w.session_id), 0) AS event_updated_at,
186
+ COALESCE((SELECT SUM(length(e.event_json) + 1)
187
+ FROM transcript_events e
188
+ WHERE e.session_id = w.session_id), 0) AS size_bytes
189
+ FROM session_windows w
190
+ WHERE EXISTS (SELECT 1 FROM transcript_events e
191
+ WHERE e.session_id = w.session_id)`,
192
+ );
193
+ } catch {
194
+ continue;
195
+ }
196
+
197
+ const nodes = readNodeMetadata(db);
198
+ const conversations = readConversationMetadata(db);
199
+ for (const row of rows) {
200
+ const node = nodes.get(row.session_id);
201
+ const conversation = conversations.get(row.session_id);
202
+ sessions.push({
203
+ sessionId: row.session_id,
204
+ agentId,
205
+ dbPath,
206
+ transcriptPath: syntheticPath(agentId, row.session_id),
207
+ mtimeMs: Math.max(
208
+ Number(row.updated_at) || 0,
209
+ Number(row.transcript_updated_at) || 0,
210
+ Number(row.ended_at) || 0,
211
+ Number(row.event_updated_at) || 0,
212
+ ),
213
+ sizeBytes: Number(row.size_bytes) || 0,
214
+ channel:
215
+ str(row.channel) ??
216
+ conversation?.channel ??
217
+ node?.channel ??
218
+ "local",
219
+ label: str(row.display_name) ?? conversation?.label ?? node?.label,
220
+ chatId: conversation?.chatId ?? node?.chatId,
221
+ chatType:
222
+ str(row.chat_type) ?? conversation?.chatType ?? node?.chatType,
223
+ });
224
+ }
225
+ } finally {
226
+ db.close();
227
+ }
228
+ }
229
+ return sessions;
230
+ }
231
+
232
+ /** Read one SQLite transcript by UUID. The first matching agent wins. */
233
+ export async function readOpenClawSqliteTranscript(
234
+ home: string,
235
+ agentIds: string[],
236
+ sessionId: string,
237
+ ): Promise<OpenClawSqliteTranscript | null> {
238
+ for (const { agentId, dbPath } of listOpenClawDatabases(home, agentIds)) {
239
+ const db = await openSqliteReadonly(dbPath);
240
+ if (!db) continue;
241
+ try {
242
+ let rows: EventRow[];
243
+ try {
244
+ rows = db.query<EventRow>(
245
+ `SELECT event_json
246
+ FROM transcript_events
247
+ WHERE session_id = ?
248
+ ORDER BY seq ASC`,
249
+ [sessionId],
250
+ );
251
+ } catch {
252
+ continue;
253
+ }
254
+ if (rows.length === 0) continue;
255
+ const eventJsonLines = rows.map((row) => row.event_json);
256
+ const rawLines = eventJsonLines
257
+ .map(parseObject)
258
+ .filter((line): line is Record<string, unknown> => line !== undefined);
259
+ return {
260
+ agentId,
261
+ dbPath,
262
+ filePath: syntheticPath(agentId, sessionId),
263
+ rawLines,
264
+ eventJsonLines,
265
+ };
266
+ } finally {
267
+ db.close();
268
+ }
269
+ }
270
+ return null;
271
+ }
@@ -1,18 +1,21 @@
1
1
  /**
2
2
  * OpenClaw (openclaw gateway) session enumeration — AUDIT-ONLY.
3
3
  *
4
- * Surfaces the on-disk transcripts (agents/<agentId>/sessions/<uuid>.jsonl) as
5
- * synthetic dashboard "projects" grouped by (agentId, channel). The per-agent
6
- * `sessions.json` index maps sessionKey → {sessionId, timestamps}; we read it to
7
- * recover the sessionKey (which encodes the channel for gateway sessions) and a
8
- * reliable last-activity time. Verified live against openclaw v2026.7.1.
4
+ * Surfaces both legacy JSONL transcripts and OpenClaw 2026.9.2+ per-agent
5
+ * SQLite transcripts as synthetic dashboard "projects" grouped by
6
+ * (agentId, channel).
9
7
  */
10
8
  import { readFileSync } from "node:fs";
11
9
  import { join } from "node:path";
12
10
  import { runtimeCache } from "./runtime-cache";
13
- import { listOpenClawAgents, listOpenClawTranscripts, openclawHome } from "./openclaw-sessions";
11
+ import {
12
+ listOpenClawAgents,
13
+ listOpenClawTranscripts,
14
+ openclawHome,
15
+ } from "./openclaw-sessions";
14
16
  import type { ProjectFolder, SessionFile } from "./projects";
15
17
  import { formatDate } from "./format-date";
18
+ import { listOpenClawSqliteSessions } from "./openclaw-db";
16
19
 
17
20
  export interface OpenClawSessionRef {
18
21
  sessionId: string;
@@ -51,7 +54,13 @@ function str(v: unknown): string | undefined {
51
54
  * than in the key — verified live against v2026.7.1. */
52
55
  function readSessionsIndex(agentId: string): Map<string, SessionIndexMeta> {
53
56
  const out = new Map<string, SessionIndexMeta>();
54
- const indexPath = join(openclawHome(), "agents", agentId, "sessions", "sessions.json");
57
+ const indexPath = join(
58
+ openclawHome(),
59
+ "agents",
60
+ agentId,
61
+ "sessions",
62
+ "sessions.json",
63
+ );
55
64
  let raw: unknown;
56
65
  try {
57
66
  raw = JSON.parse(readFileSync(indexPath, "utf-8"));
@@ -64,7 +73,9 @@ function readSessionsIndex(agentId: string): Map<string, SessionIndexMeta> {
64
73
  const e = v as Record<string, unknown>;
65
74
  const sessionId = str(e.sessionId);
66
75
  if (!sessionId) continue;
67
- const origin = (e.origin && typeof e.origin === "object" ? e.origin : {}) as Record<string, unknown>;
76
+ const origin = (
77
+ e.origin && typeof e.origin === "object" ? e.origin : {}
78
+ ) as Record<string, unknown>;
68
79
  const lastMs =
69
80
  typeof e.lastInteractionAt === "number"
70
81
  ? e.lastInteractionAt
@@ -73,7 +84,8 @@ function readSessionsIndex(agentId: string): Map<string, SessionIndexMeta> {
73
84
  : undefined;
74
85
  out.set(sessionId, {
75
86
  lastMs,
76
- channel: str(e.lastChannel) ?? str(origin.provider) ?? str(origin.surface),
87
+ channel:
88
+ str(e.lastChannel) ?? str(origin.provider) ?? str(origin.surface),
77
89
  chatType: str(e.chatType) ?? str(origin.chatType),
78
90
  label: str(origin.label),
79
91
  chatId: str(e.lastTo) ?? str(origin.from),
@@ -86,7 +98,7 @@ function readSessionsIndex(agentId: string): Map<string, SessionIndexMeta> {
86
98
  export async function getOpenClawSessions(): Promise<OpenClawSessionRef[]> {
87
99
  const transcripts = listOpenClawTranscripts();
88
100
  const indexByAgent = new Map<string, Map<string, SessionIndexMeta>>();
89
- const refs: OpenClawSessionRef[] = [];
101
+ const refs = new Map<string, OpenClawSessionRef>();
90
102
  for (const t of transcripts) {
91
103
  let idx = indexByAgent.get(t.agentId);
92
104
  if (!idx) {
@@ -94,7 +106,7 @@ export async function getOpenClawSessions(): Promise<OpenClawSessionRef[]> {
94
106
  indexByAgent.set(t.agentId, idx);
95
107
  }
96
108
  const meta = idx.get(t.sessionId);
97
- refs.push({
109
+ refs.set(`${t.agentId}\0${t.sessionId}`, {
98
110
  sessionId: t.sessionId,
99
111
  agentId: t.agentId,
100
112
  // Gateway sessions group by channel; CLI/local runs have none.
@@ -107,8 +119,18 @@ export async function getOpenClawSessions(): Promise<OpenClawSessionRef[]> {
107
119
  sizeBytes: t.sizeBytes,
108
120
  });
109
121
  }
110
- refs.sort((a, b) => b.mtimeMs - a.mtimeMs);
111
- return refs;
122
+
123
+ // SQLite is the live source on OpenClaw 2026.9.2+. Insert it second so it
124
+ // replaces an archived JSONL copy of the same agent/session.
125
+ const sqliteSessions = await listOpenClawSqliteSessions(
126
+ openclawHome(),
127
+ listOpenClawAgents(),
128
+ );
129
+ for (const s of sqliteSessions) {
130
+ refs.set(`${s.agentId}\0${s.sessionId}`, s);
131
+ }
132
+
133
+ return [...refs.values()].sort((a, b) => b.mtimeMs - a.mtimeMs);
112
134
  }
113
135
 
114
136
  export const getCachedOpenClawSessions = runtimeCache(getOpenClawSessions, 2);
@@ -145,7 +167,9 @@ export interface OpenClawNameSplit {
145
167
  * form (`agentId: null`), so links shared before agents became part of the name
146
168
  * keep resolving — to every agent on that channel, which is what they meant.
147
169
  */
148
- export function openClawProjectNameCandidates(name: string): OpenClawNameSplit[] {
170
+ export function openClawProjectNameCandidates(
171
+ name: string,
172
+ ): OpenClawNameSplit[] {
149
173
  if (!name.startsWith("openclaw-")) return [];
150
174
  const rest = name.slice("openclaw-".length);
151
175
  if (!rest) return [];
@@ -163,7 +187,9 @@ export function openClawProjectNameCandidates(name: string): OpenClawNameSplit[]
163
187
  }
164
188
 
165
189
  /** The best-guess split for a project name — `null` if it isn't an OpenClaw one. */
166
- export function parseOpenClawProjectName(name: string): OpenClawNameSplit | null {
190
+ export function parseOpenClawProjectName(
191
+ name: string,
192
+ ): OpenClawNameSplit | null {
167
193
  return openClawProjectNameCandidates(name)[0] ?? null;
168
194
  }
169
195
 
@@ -190,7 +216,12 @@ export async function getOpenClawProjects(): Promise<ProjectFolder[]> {
190
216
  prev.latest = Math.max(prev.latest, s.mtimeMs);
191
217
  prev.count += 1;
192
218
  } else {
193
- groups.set(key, { agentId: s.agentId, channel: s.channel, latest: s.mtimeMs, count: 1 });
219
+ groups.set(key, {
220
+ agentId: s.agentId,
221
+ channel: s.channel,
222
+ latest: s.mtimeMs,
223
+ count: 1,
224
+ });
194
225
  }
195
226
  }
196
227
  const out: ProjectFolder[] = [];
@@ -228,7 +259,9 @@ export async function getOpenClawSessionsByEncodedName(
228
259
  const sessions = await getOpenClawSessions();
229
260
  const matching = (split: OpenClawNameSplit) =>
230
261
  sessions.filter(
231
- (s) => s.channel === split.channel && (split.agentId === null || s.agentId === split.agentId),
262
+ (s) =>
263
+ s.channel === split.channel &&
264
+ (split.agentId === null || s.agentId === split.agentId),
232
265
  );
233
266
 
234
267
  // Take the first split that actually owns sessions — length alone picks the
@@ -250,7 +283,10 @@ export async function getOpenClawSessionsByEncodedName(
250
283
  return {
251
284
  // Legacy channel-only names keep their old cwd label, since they really do
252
285
  // span every agent on that channel.
253
- cwd: agentId === null ? `openclaw:${channel}` : openClawProjectPath(agentId, channel),
286
+ cwd:
287
+ agentId === null
288
+ ? `openclaw:${channel}`
289
+ : openClawProjectPath(agentId, channel),
254
290
  sessions: matched.map((s) => {
255
291
  const lastModified = new Date(s.mtimeMs);
256
292
  return {