@pasko70/pibo 2.1.1 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (375) hide show
  1. package/dist/agent-runtime/capabilities.js +68 -0
  2. package/dist/agent-runtime/context-build.js +13 -5
  3. package/dist/agent-runtime/portable-history.js +526 -0
  4. package/dist/agent-runtime/profile-validation.js +13 -7
  5. package/dist/agent-runtime/resource-files.js +26 -10
  6. package/dist/agent-runtime/resource-service.js +216 -13
  7. package/dist/agent-runtimes/codex-native/adapter.js +38 -1
  8. package/dist/agent-runtimes/codex-native/auth.js +24 -3
  9. package/dist/agent-runtimes/codex-native/portable-history.js +73 -0
  10. package/dist/agent-runtimes/codex-native/process.js +38 -27
  11. package/dist/agent-runtimes/codex-native/resource-delivery.js +39 -16
  12. package/dist/agent-runtimes/codex-native/turn.js +68 -5
  13. package/dist/agent-runtimes/omp/adapter.js +43 -8
  14. package/dist/agent-runtimes/omp/process.js +26 -10
  15. package/dist/agent-runtimes/omp/resource-delivery.js +150 -84
  16. package/dist/agent-runtimes/pi/adapter.js +32 -1
  17. package/dist/agent-runtimes/pi/auth.js +34 -29
  18. package/dist/agent-runtimes/pi/credentials.js +43 -0
  19. package/dist/agent-runtimes/pi/model-catalog.js +7 -3
  20. package/dist/agent-runtimes/pi/portable-history.js +99 -0
  21. package/dist/agent-runtimes/pi/routed-session.js +1 -1
  22. package/dist/agent-runtimes/pi/runtime.js +31 -15
  23. package/dist/apps/chat/agent-profiles.js +1 -0
  24. package/dist/apps/chat/agent-store.js +20 -7
  25. package/dist/apps/chat/chat-files.js +19 -6
  26. package/dist/apps/chat/chat-request-normalizers.js +13 -0
  27. package/dist/apps/chat/web-app.js +55 -6
  28. package/dist/apps/chat-ui/assets/{apl-14BqhLYK.js → apl-gfMMiTNf.js} +1 -1
  29. package/dist/apps/chat-ui/assets/asciiarmor-C_eisQCp.js +1 -0
  30. package/dist/apps/{context-files-ui/assets/asn1-Bg4FbdCg.js → chat-ui/assets/asn1-DCl_8MCW.js} +1 -1
  31. package/dist/apps/{context-files-ui/assets/asterisk-B2MO-X4d.js → chat-ui/assets/asterisk-BEn0Cwpx.js} +1 -1
  32. package/dist/apps/chat-ui/assets/clike-D_6L3tnO.js +1 -0
  33. package/dist/apps/chat-ui/assets/cmake-84nbDH0I.js +1 -0
  34. package/dist/apps/chat-ui/assets/cobol-DHLQUbN7.js +1 -0
  35. package/dist/apps/chat-ui/assets/coffeescript-De_zI4J0.js +1 -0
  36. package/dist/apps/chat-ui/assets/commonlisp-DgAKBe0r.js +1 -0
  37. package/dist/apps/chat-ui/assets/crystal-Bsdphhtm.js +1 -0
  38. package/dist/apps/chat-ui/assets/css-CnaYoQib.js +1 -0
  39. package/dist/apps/chat-ui/assets/{d-TPqSVaHM.js → d-DWkQyNnU.js} +1 -1
  40. package/dist/apps/{context-files-ui/assets/dist-DxEGebCR.js → chat-ui/assets/dist-BB8loWTa.js} +1 -1
  41. package/dist/apps/chat-ui/assets/dist-BJ-TIk3N.js +1 -0
  42. package/dist/apps/chat-ui/assets/dist-CBPDkWd4.js +1 -0
  43. package/dist/apps/chat-ui/assets/dist-CHInEWhr.js +1 -0
  44. package/dist/apps/chat-ui/assets/dist-CqM4On9D.js +13 -0
  45. package/dist/apps/chat-ui/assets/dist-CswnpKik.js +1 -0
  46. package/dist/apps/{context-files-ui/assets/dist-B7gXtTZC.js → chat-ui/assets/dist-CwS16H7k.js} +1 -1
  47. package/dist/apps/chat-ui/assets/dist-DHvUPfrF.js +1 -0
  48. package/dist/apps/chat-ui/assets/dist-DLJCGrGQ.js +1 -0
  49. package/dist/apps/chat-ui/assets/{dist-DLMjd26T.js → dist-DMiglryg.js} +1 -1
  50. package/dist/apps/chat-ui/assets/dist-DTeLDijr.js +9 -0
  51. package/dist/apps/chat-ui/assets/{dist-DKoyMSNr.js → dist-DpF08Yd7.js} +1 -1
  52. package/dist/apps/chat-ui/assets/dist-LCx98fA_.js +11 -0
  53. package/dist/apps/chat-ui/assets/{dist-DotDq_kD.js → dist-RKTRnzGb.js} +1 -1
  54. package/dist/apps/chat-ui/assets/dist-S3zJGntM.js +1 -0
  55. package/dist/apps/{context-files-ui/assets/dist-BkUONE3N.js → chat-ui/assets/dist-XVYGiB-c.js} +1 -1
  56. package/dist/apps/chat-ui/assets/dist-eddbbGyw.js +1 -0
  57. package/dist/apps/chat-ui/assets/dist-fPhZsAUX.js +1 -0
  58. package/dist/apps/chat-ui/assets/dist-mpRGeo_R.js +2 -0
  59. package/dist/apps/chat-ui/assets/{dist-sZgJkWZb.js → dist-nU3BVpFi.js} +1 -1
  60. package/dist/apps/chat-ui/assets/{dockerfile-CJb2sekW.js → dockerfile-DJkHQgkl.js} +1 -1
  61. package/dist/apps/chat-ui/assets/{dylan-08Azy1NK.js → dylan-BCDoL_-p.js} +1 -1
  62. package/dist/apps/chat-ui/assets/{ecl-dhxjHL8y.js → ecl-BVIeWmwY.js} +1 -1
  63. package/dist/apps/{context-files-ui/assets/erlang-BD5LkVkR.js → chat-ui/assets/erlang-BV0c4Hdn.js} +1 -1
  64. package/dist/apps/chat-ui/assets/{factor-B2EMQZkP.js → factor-LKH5gN8L.js} +1 -1
  65. package/dist/apps/chat-ui/assets/groovy-CUpZ7dEl.js +1 -0
  66. package/dist/apps/chat-ui/assets/{haxe-BJVKtprM.js → haxe-DjVOVvNP.js} +1 -1
  67. package/dist/apps/chat-ui/assets/index-CQuka3bs.js +226 -0
  68. package/dist/apps/chat-ui/assets/index-DUXboQnI.css +1 -0
  69. package/dist/apps/chat-ui/assets/javascript-DoL9Wb-Q.js +1 -0
  70. package/dist/apps/chat-ui/assets/{lua-BxuTHaF7.js → lua-CiA1ziua.js} +1 -1
  71. package/dist/apps/chat-ui/assets/{mumps-Ds_ZaumL.js → mumps-BSzj6Xyz.js} +1 -1
  72. package/dist/apps/{context-files-ui/assets/nsis-DOo3SJmd.js → chat-ui/assets/nsis-CfSuhXs5.js} +1 -1
  73. package/dist/apps/chat-ui/assets/{ntriples-DLHGTvHs.js → ntriples-B9h1VB_g.js} +1 -1
  74. package/dist/apps/chat-ui/assets/perl-BkSkiI9m.js +1 -0
  75. package/dist/apps/chat-ui/assets/{powershell-B4IPkVxR.js → powershell-BcIto6Sf.js} +1 -1
  76. package/dist/apps/{context-files-ui/assets/pug-QU72BPAa.js → chat-ui/assets/pug-Gsm0M45u.js} +1 -1
  77. package/dist/apps/chat-ui/assets/puppet-BZyAS7I4.js +1 -0
  78. package/dist/apps/chat-ui/assets/python-B_1Jd8HM.js +1 -0
  79. package/dist/apps/chat-ui/assets/r-CxDmU1I4.js +1 -0
  80. package/dist/apps/chat-ui/assets/ruby-BjXV7-Qa.js +1 -0
  81. package/dist/apps/chat-ui/assets/scheme-D9qYN0V5.js +1 -0
  82. package/dist/apps/chat-ui/assets/{shell-BjiMLAaM.js → shell-DwuoZtxw.js} +1 -1
  83. package/dist/apps/chat-ui/assets/{simple-mode-DnMbQuKW.js → simple-mode-DXiLM1-G.js} +1 -1
  84. package/dist/apps/chat-ui/assets/sql-DuQMFDvy.js +1 -0
  85. package/dist/apps/chat-ui/assets/{stex-BCRT8IJ3.js → stex-DNzd62Q_.js} +1 -1
  86. package/dist/apps/chat-ui/assets/{stylus-CARoeVE9.js → stylus-BOVgKnng.js} +1 -1
  87. package/dist/apps/chat-ui/assets/textile-C4jVoHG1.js +1 -0
  88. package/dist/apps/chat-ui/assets/tiki-AK6FwT8q.js +1 -0
  89. package/dist/apps/chat-ui/assets/toml-BPTmHmyx.js +1 -0
  90. package/dist/apps/chat-ui/assets/{ttcn-GvRgs2AT.js → ttcn-PPSTk1ow.js} +1 -1
  91. package/dist/apps/chat-ui/assets/{ttcn-cfg-CGCXz7Vo.js → ttcn-cfg-2b4Gb5sE.js} +1 -1
  92. package/dist/apps/chat-ui/assets/turtle-Cx3rYX2g.js +1 -0
  93. package/dist/apps/chat-ui/assets/{verilog-DVCHmufx.js → verilog-7LoJAqYT.js} +1 -1
  94. package/dist/apps/chat-ui/assets/vhdl-kS471soi.js +1 -0
  95. package/dist/apps/{context-files-ui/assets/xquery-5f0hn7cg.js → chat-ui/assets/xquery-BKJx4mf9.js} +1 -1
  96. package/dist/apps/chat-ui/assets/z80-Co3PbHdE.js +1 -0
  97. package/dist/apps/chat-ui/index.html +5 -3
  98. package/dist/apps/chat-vscode-web/assets/index-CF1-9PKU.css +2 -0
  99. package/dist/apps/chat-vscode-web/assets/index-Dp1TzeRL.js +41 -0
  100. package/dist/apps/chat-vscode-web/index.html +2 -2
  101. package/dist/apps/context-files-ui/assets/{apl-14BqhLYK.js → apl-gfMMiTNf.js} +1 -1
  102. package/dist/apps/context-files-ui/assets/asciiarmor-C_eisQCp.js +1 -0
  103. package/dist/apps/{chat-ui/assets/asn1-Bg4FbdCg.js → context-files-ui/assets/asn1-DCl_8MCW.js} +1 -1
  104. package/dist/apps/{chat-ui/assets/asterisk-B2MO-X4d.js → context-files-ui/assets/asterisk-BEn0Cwpx.js} +1 -1
  105. package/dist/apps/context-files-ui/assets/clike-D_6L3tnO.js +1 -0
  106. package/dist/apps/context-files-ui/assets/cmake-84nbDH0I.js +1 -0
  107. package/dist/apps/context-files-ui/assets/cobol-DHLQUbN7.js +1 -0
  108. package/dist/apps/context-files-ui/assets/coffeescript-De_zI4J0.js +1 -0
  109. package/dist/apps/context-files-ui/assets/commonlisp-DgAKBe0r.js +1 -0
  110. package/dist/apps/context-files-ui/assets/crystal-Bsdphhtm.js +1 -0
  111. package/dist/apps/context-files-ui/assets/css-CnaYoQib.js +1 -0
  112. package/dist/apps/context-files-ui/assets/{d-TPqSVaHM.js → d-DWkQyNnU.js} +1 -1
  113. package/dist/apps/{chat-ui/assets/dist-C6LPDFXU.js → context-files-ui/assets/dist-BAqbgxUS.js} +1 -1
  114. package/dist/apps/context-files-ui/assets/dist-BJ-TIk3N.js +1 -0
  115. package/dist/apps/context-files-ui/assets/dist-BcauuFwf.js +1 -0
  116. package/dist/apps/context-files-ui/assets/dist-BecMXs79.js +1 -0
  117. package/dist/apps/context-files-ui/assets/{dist-C-Jm45P4.js → dist-Ci2NSlf1.js} +1 -1
  118. package/dist/apps/context-files-ui/assets/dist-CqM4On9D.js +13 -0
  119. package/dist/apps/context-files-ui/assets/dist-CswnpKik.js +1 -0
  120. package/dist/apps/{chat-ui/assets/dist-I26VB0QO.js → context-files-ui/assets/dist-D-xpsbZI.js} +1 -1
  121. package/dist/apps/context-files-ui/assets/dist-DHvUPfrF.js +1 -0
  122. package/dist/apps/context-files-ui/assets/dist-DLJCGrGQ.js +1 -0
  123. package/dist/apps/context-files-ui/assets/{dist-DLMjd26T.js → dist-DMiglryg.js} +1 -1
  124. package/dist/apps/context-files-ui/assets/dist-DTeLDijr.js +9 -0
  125. package/dist/apps/context-files-ui/assets/{dist-DKoyMSNr.js → dist-DpF08Yd7.js} +1 -1
  126. package/dist/apps/context-files-ui/assets/dist-LCx98fA_.js +11 -0
  127. package/dist/apps/context-files-ui/assets/{dist-DotDq_kD.js → dist-RKTRnzGb.js} +1 -1
  128. package/dist/apps/context-files-ui/assets/dist-S3zJGntM.js +1 -0
  129. package/dist/apps/{chat-ui/assets/dist-BkUONE3N.js → context-files-ui/assets/dist-XVYGiB-c.js} +1 -1
  130. package/dist/apps/context-files-ui/assets/dist-eddbbGyw.js +1 -0
  131. package/dist/apps/context-files-ui/assets/dist-fPhZsAUX.js +1 -0
  132. package/dist/apps/context-files-ui/assets/dist-mpRGeo_R.js +2 -0
  133. package/dist/apps/context-files-ui/assets/{dockerfile-CJb2sekW.js → dockerfile-DJkHQgkl.js} +1 -1
  134. package/dist/apps/context-files-ui/assets/{dylan-08Azy1NK.js → dylan-BCDoL_-p.js} +1 -1
  135. package/dist/apps/context-files-ui/assets/{ecl-dhxjHL8y.js → ecl-BVIeWmwY.js} +1 -1
  136. package/dist/apps/{chat-ui/assets/erlang-BD5LkVkR.js → context-files-ui/assets/erlang-BV0c4Hdn.js} +1 -1
  137. package/dist/apps/context-files-ui/assets/{factor-B2EMQZkP.js → factor-LKH5gN8L.js} +1 -1
  138. package/dist/apps/context-files-ui/assets/groovy-CUpZ7dEl.js +1 -0
  139. package/dist/apps/context-files-ui/assets/{haxe-BJVKtprM.js → haxe-DjVOVvNP.js} +1 -1
  140. package/dist/apps/context-files-ui/assets/index-CkWXlBNn.js +191 -0
  141. package/dist/apps/context-files-ui/assets/{index-Cs4XQITe.css → index-D8TsUizd.css} +1 -1
  142. package/dist/apps/context-files-ui/assets/javascript-DoL9Wb-Q.js +1 -0
  143. package/dist/apps/context-files-ui/assets/{lua-BxuTHaF7.js → lua-CiA1ziua.js} +1 -1
  144. package/dist/apps/context-files-ui/assets/{mumps-Ds_ZaumL.js → mumps-BSzj6Xyz.js} +1 -1
  145. package/dist/apps/{chat-ui/assets/nsis-DOo3SJmd.js → context-files-ui/assets/nsis-CfSuhXs5.js} +1 -1
  146. package/dist/apps/context-files-ui/assets/{ntriples-DLHGTvHs.js → ntriples-B9h1VB_g.js} +1 -1
  147. package/dist/apps/context-files-ui/assets/perl-BkSkiI9m.js +1 -0
  148. package/dist/apps/context-files-ui/assets/{powershell-B4IPkVxR.js → powershell-BcIto6Sf.js} +1 -1
  149. package/dist/apps/{chat-ui/assets/pug-QU72BPAa.js → context-files-ui/assets/pug-Gsm0M45u.js} +1 -1
  150. package/dist/apps/context-files-ui/assets/puppet-BZyAS7I4.js +1 -0
  151. package/dist/apps/context-files-ui/assets/python-B_1Jd8HM.js +1 -0
  152. package/dist/apps/context-files-ui/assets/r-CxDmU1I4.js +1 -0
  153. package/dist/apps/context-files-ui/assets/ruby-BjXV7-Qa.js +1 -0
  154. package/dist/apps/context-files-ui/assets/scheme-D9qYN0V5.js +1 -0
  155. package/dist/apps/context-files-ui/assets/{shell-BjiMLAaM.js → shell-DwuoZtxw.js} +1 -1
  156. package/dist/apps/context-files-ui/assets/{simple-mode-DnMbQuKW.js → simple-mode-DXiLM1-G.js} +1 -1
  157. package/dist/apps/context-files-ui/assets/sql-DuQMFDvy.js +1 -0
  158. package/dist/apps/context-files-ui/assets/{stex-BCRT8IJ3.js → stex-DNzd62Q_.js} +1 -1
  159. package/dist/apps/context-files-ui/assets/{stylus-CARoeVE9.js → stylus-BOVgKnng.js} +1 -1
  160. package/dist/apps/context-files-ui/assets/textile-C4jVoHG1.js +1 -0
  161. package/dist/apps/context-files-ui/assets/tiki-AK6FwT8q.js +1 -0
  162. package/dist/apps/context-files-ui/assets/toml-BPTmHmyx.js +1 -0
  163. package/dist/apps/context-files-ui/assets/{ttcn-GvRgs2AT.js → ttcn-PPSTk1ow.js} +1 -1
  164. package/dist/apps/context-files-ui/assets/{ttcn-cfg-CGCXz7Vo.js → ttcn-cfg-2b4Gb5sE.js} +1 -1
  165. package/dist/apps/context-files-ui/assets/turtle-Cx3rYX2g.js +1 -0
  166. package/dist/apps/context-files-ui/assets/{verilog-DVCHmufx.js → verilog-7LoJAqYT.js} +1 -1
  167. package/dist/apps/context-files-ui/assets/vhdl-kS471soi.js +1 -0
  168. package/dist/apps/{chat-ui/assets/xquery-5f0hn7cg.js → context-files-ui/assets/xquery-BKJx4mf9.js} +1 -1
  169. package/dist/apps/context-files-ui/assets/z80-Co3PbHdE.js +1 -0
  170. package/dist/apps/context-files-ui/index.html +5 -3
  171. package/dist/apps/vscode-artifacts/latest.vsix +0 -0
  172. package/dist/apps/vscode-artifacts/pibo-vscode-ext-2.2.0.vsix +0 -0
  173. package/dist/auth/better-auth.js +223 -30
  174. package/dist/auth/cli.js +10 -1
  175. package/dist/auth/machine-keys.js +8 -4
  176. package/dist/auth/openai-codex-usage.js +4 -4
  177. package/dist/cli-session/fakeSessionSource.js +2 -2
  178. package/dist/cli-session/localSessionSource.js +2 -2
  179. package/dist/cli.js +3 -1
  180. package/dist/config/config.js +9 -4
  181. package/dist/core/compaction-prompt.js +3 -1
  182. package/dist/core/context-build.js +1 -0
  183. package/dist/core/pibo-home.js +24 -1
  184. package/dist/core/private-path.js +146 -0
  185. package/dist/core/profiles.js +8 -0
  186. package/dist/core/sensitive-data-redaction.js +36 -0
  187. package/dist/core/session-model.js +1 -0
  188. package/dist/core/session-router.js +219 -29
  189. package/dist/data/pibo-store.js +5 -1
  190. package/dist/gateway/server.js +9 -0
  191. package/dist/plugins/context-files.js +11 -0
  192. package/dist/plugins/registry.js +1 -0
  193. package/dist/providers/openai-gpt56.js +0 -11
  194. package/dist/reliability/store.js +5 -1
  195. package/dist/resources/lifecycle.js +13 -3
  196. package/dist/runs/resource-isolation.js +159 -8
  197. package/dist/runs/tools.js +44 -1
  198. package/dist/sessions/pibo-data-store.js +3 -0
  199. package/dist/tools/codex-browser-node-repl.js +4 -2
  200. package/dist/tools/codex-browser.js +1 -1
  201. package/dist/tools/codex-image-generation.js +4 -4
  202. package/dist/tools/runtime/node-backend.js +4 -1
  203. package/dist/tools/runtime/python-backend.js +4 -1
  204. package/dist/web-annotations/api.js +22 -2
  205. package/npm-shrinkwrap.json +16707 -0
  206. package/package.json +19 -14
  207. package/dist/apps/chat-ui/assets/asciiarmor-WLvjqI7d.js +0 -1
  208. package/dist/apps/chat-ui/assets/clike-CjmcUpt6.js +0 -1
  209. package/dist/apps/chat-ui/assets/cmake-i2VDNaRq.js +0 -1
  210. package/dist/apps/chat-ui/assets/cobol-BwO6DF08.js +0 -1
  211. package/dist/apps/chat-ui/assets/coffeescript-BtivDvRz.js +0 -1
  212. package/dist/apps/chat-ui/assets/commonlisp-DFkEQdLP.js +0 -1
  213. package/dist/apps/chat-ui/assets/crystal-CU0NkcVL.js +0 -1
  214. package/dist/apps/chat-ui/assets/css-CbMZAQ1W.js +0 -1
  215. package/dist/apps/chat-ui/assets/dist-9v2ZXT6V.js +0 -11
  216. package/dist/apps/chat-ui/assets/dist-B1LVAytl.js +0 -9
  217. package/dist/apps/chat-ui/assets/dist-B5PTVnox.js +0 -1
  218. package/dist/apps/chat-ui/assets/dist-B5ZAfwf5.js +0 -1
  219. package/dist/apps/chat-ui/assets/dist-D1KyNDg5.js +0 -13
  220. package/dist/apps/chat-ui/assets/dist-DVtXxfHc.js +0 -1
  221. package/dist/apps/chat-ui/assets/dist-DW4Qrfbd.js +0 -2
  222. package/dist/apps/chat-ui/assets/dist-DmbsHdMC.js +0 -1
  223. package/dist/apps/chat-ui/assets/dist-DyvwuSFO.js +0 -1
  224. package/dist/apps/chat-ui/assets/dist-QQuDy4KA.js +0 -1
  225. package/dist/apps/chat-ui/assets/dist-RtHbJRPV.js +0 -1
  226. package/dist/apps/chat-ui/assets/groovy-Cmduloe1.js +0 -1
  227. package/dist/apps/chat-ui/assets/index-BPbNvcZe.css +0 -1
  228. package/dist/apps/chat-ui/assets/index-CIOf2uL2.js +0 -237
  229. package/dist/apps/chat-ui/assets/javascript-C5pDVaoP.js +0 -1
  230. package/dist/apps/chat-ui/assets/perl-D6YJObi_.js +0 -1
  231. package/dist/apps/chat-ui/assets/puppet-B_0GFuyD.js +0 -1
  232. package/dist/apps/chat-ui/assets/python-Cs7sNzy_.js +0 -1
  233. package/dist/apps/chat-ui/assets/r-CN5s4f3o.js +0 -1
  234. package/dist/apps/chat-ui/assets/ruby-BVPradRk.js +0 -1
  235. package/dist/apps/chat-ui/assets/scheme-CvNgHAnh.js +0 -1
  236. package/dist/apps/chat-ui/assets/sql-DYI2GwJR.js +0 -1
  237. package/dist/apps/chat-ui/assets/textile-Yg_UWn-t.js +0 -1
  238. package/dist/apps/chat-ui/assets/tiki-CC_ic8g0.js +0 -1
  239. package/dist/apps/chat-ui/assets/toml-B7gGzVkJ.js +0 -1
  240. package/dist/apps/chat-ui/assets/turtle-CwIpz2yy.js +0 -1
  241. package/dist/apps/chat-ui/assets/vhdl-BGDk4f1d.js +0 -1
  242. package/dist/apps/chat-ui/assets/z80-B7Dfb4UO.js +0 -1
  243. package/dist/apps/chat-vscode-web/assets/index-1ivRyjFs.js +0 -41
  244. package/dist/apps/chat-vscode-web/assets/index-Dupu1DzQ.css +0 -2
  245. package/dist/apps/context-files-ui/assets/asciiarmor-WLvjqI7d.js +0 -1
  246. package/dist/apps/context-files-ui/assets/clike-CjmcUpt6.js +0 -1
  247. package/dist/apps/context-files-ui/assets/cmake-i2VDNaRq.js +0 -1
  248. package/dist/apps/context-files-ui/assets/cobol-BwO6DF08.js +0 -1
  249. package/dist/apps/context-files-ui/assets/coffeescript-BtivDvRz.js +0 -1
  250. package/dist/apps/context-files-ui/assets/commonlisp-DFkEQdLP.js +0 -1
  251. package/dist/apps/context-files-ui/assets/crystal-CU0NkcVL.js +0 -1
  252. package/dist/apps/context-files-ui/assets/css-CbMZAQ1W.js +0 -1
  253. package/dist/apps/context-files-ui/assets/dist-B5PTVnox.js +0 -1
  254. package/dist/apps/context-files-ui/assets/dist-B5ZAfwf5.js +0 -1
  255. package/dist/apps/context-files-ui/assets/dist-BD262Ouw.js +0 -1
  256. package/dist/apps/context-files-ui/assets/dist-BKuGdcnX.js +0 -9
  257. package/dist/apps/context-files-ui/assets/dist-CHdx1Jri.js +0 -1
  258. package/dist/apps/context-files-ui/assets/dist-CULMH-fB.js +0 -11
  259. package/dist/apps/context-files-ui/assets/dist-Cjq6RWEt.js +0 -1
  260. package/dist/apps/context-files-ui/assets/dist-CntqFySz.js +0 -1
  261. package/dist/apps/context-files-ui/assets/dist-D1KyNDg5.js +0 -13
  262. package/dist/apps/context-files-ui/assets/dist-QQuDy4KA.js +0 -1
  263. package/dist/apps/context-files-ui/assets/dist-kPuQud7t.js +0 -2
  264. package/dist/apps/context-files-ui/assets/groovy-Cmduloe1.js +0 -1
  265. package/dist/apps/context-files-ui/assets/index-DZWsbuvg.js +0 -202
  266. package/dist/apps/context-files-ui/assets/javascript-C5pDVaoP.js +0 -1
  267. package/dist/apps/context-files-ui/assets/perl-D6YJObi_.js +0 -1
  268. package/dist/apps/context-files-ui/assets/puppet-B_0GFuyD.js +0 -1
  269. package/dist/apps/context-files-ui/assets/python-Cs7sNzy_.js +0 -1
  270. package/dist/apps/context-files-ui/assets/r-CN5s4f3o.js +0 -1
  271. package/dist/apps/context-files-ui/assets/ruby-BVPradRk.js +0 -1
  272. package/dist/apps/context-files-ui/assets/scheme-CvNgHAnh.js +0 -1
  273. package/dist/apps/context-files-ui/assets/sql-DYI2GwJR.js +0 -1
  274. package/dist/apps/context-files-ui/assets/textile-Yg_UWn-t.js +0 -1
  275. package/dist/apps/context-files-ui/assets/tiki-CC_ic8g0.js +0 -1
  276. package/dist/apps/context-files-ui/assets/toml-B7gGzVkJ.js +0 -1
  277. package/dist/apps/context-files-ui/assets/turtle-CwIpz2yy.js +0 -1
  278. package/dist/apps/context-files-ui/assets/vhdl-BGDk4f1d.js +0 -1
  279. package/dist/apps/context-files-ui/assets/z80-B7Dfb4UO.js +0 -1
  280. /package/dist/apps/chat-ui/assets/{brainfuck-CV9kufud.js → brainfuck-D5EjA2JK.js} +0 -0
  281. /package/dist/apps/chat-ui/assets/{clojure-De3QGfx6.js → clojure-BflJGmDX.js} +0 -0
  282. /package/dist/apps/chat-ui/assets/{cypher-Dke5QOzv.js → cypher-p9eYesGn.js} +0 -0
  283. /package/dist/apps/chat-ui/assets/{diff-B365LSoZ.js → diff-ChtP43wD.js} +0 -0
  284. /package/dist/apps/chat-ui/assets/{dtd-CBMymJ7O.js → dtd-DTF72YNO.js} +0 -0
  285. /package/dist/apps/chat-ui/assets/{ebnf-Dkum_1J8.js → ebnf-D4c0_ac3.js} +0 -0
  286. /package/dist/apps/chat-ui/assets/{eiffel-C446m6dI.js → eiffel-BEjRio4Q.js} +0 -0
  287. /package/dist/apps/chat-ui/assets/{elm-po1E9de0.js → elm-Cshzl8qu.js} +0 -0
  288. /package/dist/apps/chat-ui/assets/{fcl-DkEOamHd.js → fcl-ClOhbFR7.js} +0 -0
  289. /package/dist/apps/chat-ui/assets/{forth-dCg2_HVB.js → forth-Cezjo90N.js} +0 -0
  290. /package/dist/apps/chat-ui/assets/{fortran-3ZpXLFh1.js → fortran-Bt6PBEDR.js} +0 -0
  291. /package/dist/apps/chat-ui/assets/{gas-DMmxLZRI.js → gas-BHEdbvp9.js} +0 -0
  292. /package/dist/apps/chat-ui/assets/{gherkin-DUSFg2R6.js → gherkin-oBAE_ms0.js} +0 -0
  293. /package/dist/apps/chat-ui/assets/{haskell-Cyr255R9.js → haskell-BRsoo5mP.js} +0 -0
  294. /package/dist/apps/chat-ui/assets/{http-DszHFpc-.js → http-CLVgA2GD.js} +0 -0
  295. /package/dist/apps/chat-ui/assets/{idl-Cati9Nrv.js → idl-BUZw3wgd.js} +0 -0
  296. /package/dist/apps/chat-ui/assets/{julia-DlqY1cTU.js → julia-CQfgDRfP.js} +0 -0
  297. /package/dist/apps/chat-ui/assets/{livescript-C6p8-2W1.js → livescript-BXxG0Yva.js} +0 -0
  298. /package/dist/apps/chat-ui/assets/{mathematica-nDHZUMJT.js → mathematica-u8YMmbU0.js} +0 -0
  299. /package/dist/apps/chat-ui/assets/{mbox-DAaR0Hcz.js → mbox-BEMVcqjs.js} +0 -0
  300. /package/dist/apps/chat-ui/assets/{mirc-CCA0FRfl.js → mirc-C9zpzAZU.js} +0 -0
  301. /package/dist/apps/chat-ui/assets/{mllike-Cw3Iccsb.js → mllike-B45xgp2S.js} +0 -0
  302. /package/dist/apps/chat-ui/assets/{modelica-Czx80fNR.js → modelica-CqHI_q-D.js} +0 -0
  303. /package/dist/apps/chat-ui/assets/{mscgen-BmfuTbzG.js → mscgen-qgSLujhx.js} +0 -0
  304. /package/dist/apps/chat-ui/assets/{nginx-D9M2PQ4U.js → nginx-BMaDbqW3.js} +0 -0
  305. /package/dist/apps/chat-ui/assets/{octave-8jj96JiC.js → octave-D2Q8cUp1.js} +0 -0
  306. /package/dist/apps/chat-ui/assets/{oz-BmMq7iC4.js → oz-BwTct_5T.js} +0 -0
  307. /package/dist/apps/chat-ui/assets/{pascal-BgMr6XpT.js → pascal-Dp_KdFgX.js} +0 -0
  308. /package/dist/apps/chat-ui/assets/{pig-nx7uchs8.js → pig-AF4Hwhju.js} +0 -0
  309. /package/dist/apps/chat-ui/assets/{properties-CoavQdLC.js → properties-C357ku5U.js} +0 -0
  310. /package/dist/apps/chat-ui/assets/{protobuf-D5EWhcmc.js → protobuf-D1ij_kNL.js} +0 -0
  311. /package/dist/apps/chat-ui/assets/{q-BIB9pPtI.js → q-B9NhS7L_.js} +0 -0
  312. /package/dist/apps/chat-ui/assets/{rpm-Ct_Ck8mQ.js → rpm-gpDK5sbt.js} +0 -0
  313. /package/dist/apps/chat-ui/assets/{sas-DN4j74IF.js → sas-C2OyD2Y6.js} +0 -0
  314. /package/dist/apps/chat-ui/assets/{sieve-C2U1O5Z4.js → sieve-BAxa3IjF.js} +0 -0
  315. /package/dist/apps/chat-ui/assets/{smalltalk-DkYwYufV.js → smalltalk-BLp5-jwC.js} +0 -0
  316. /package/dist/apps/chat-ui/assets/{solr-BopnSD-v.js → solr-BBopId9w.js} +0 -0
  317. /package/dist/apps/chat-ui/assets/{sparql-Cpg3YQfd.js → sparql-Dz-mlCAC.js} +0 -0
  318. /package/dist/apps/chat-ui/assets/{spreadsheet-kRxtVt9J.js → spreadsheet-CTIncYxj.js} +0 -0
  319. /package/dist/apps/chat-ui/assets/{swift-DKNaLAK6.js → swift-DKB6_1j6.js} +0 -0
  320. /package/dist/apps/chat-ui/assets/{tcl-CQyXkgMH.js → tcl-BGfruO1u.js} +0 -0
  321. /package/dist/apps/chat-ui/assets/{tiddlywiki-dqVbkfX4.js → tiddlywiki-VlUiK86J.js} +0 -0
  322. /package/dist/apps/chat-ui/assets/{troff-Bq3z6oAu.js → troff-C2dAgh7P.js} +0 -0
  323. /package/dist/apps/chat-ui/assets/{vb-BmcHUM2C.js → vb-BthdM_4N.js} +0 -0
  324. /package/dist/apps/chat-ui/assets/{vbscript-Cs9dylre.js → vbscript-D9f6rSsU.js} +0 -0
  325. /package/dist/apps/chat-ui/assets/{velocity-CBWU0VCy.js → velocity-CqftRsjg.js} +0 -0
  326. /package/dist/apps/chat-ui/assets/{webidl-egXQEWlC.js → webidl-D5jiJvOU.js} +0 -0
  327. /package/dist/apps/chat-ui/assets/{yacas-DNs9XkmQ.js → yacas-CXXgtw0p.js} +0 -0
  328. /package/dist/apps/context-files-ui/assets/{brainfuck-CV9kufud.js → brainfuck-D5EjA2JK.js} +0 -0
  329. /package/dist/apps/context-files-ui/assets/{clojure-De3QGfx6.js → clojure-BflJGmDX.js} +0 -0
  330. /package/dist/apps/context-files-ui/assets/{cypher-Dke5QOzv.js → cypher-p9eYesGn.js} +0 -0
  331. /package/dist/apps/context-files-ui/assets/{diff-B365LSoZ.js → diff-ChtP43wD.js} +0 -0
  332. /package/dist/apps/context-files-ui/assets/{dtd-CBMymJ7O.js → dtd-DTF72YNO.js} +0 -0
  333. /package/dist/apps/context-files-ui/assets/{ebnf-Dkum_1J8.js → ebnf-D4c0_ac3.js} +0 -0
  334. /package/dist/apps/context-files-ui/assets/{eiffel-C446m6dI.js → eiffel-BEjRio4Q.js} +0 -0
  335. /package/dist/apps/context-files-ui/assets/{elm-po1E9de0.js → elm-Cshzl8qu.js} +0 -0
  336. /package/dist/apps/context-files-ui/assets/{fcl-DkEOamHd.js → fcl-ClOhbFR7.js} +0 -0
  337. /package/dist/apps/context-files-ui/assets/{forth-dCg2_HVB.js → forth-Cezjo90N.js} +0 -0
  338. /package/dist/apps/context-files-ui/assets/{fortran-3ZpXLFh1.js → fortran-Bt6PBEDR.js} +0 -0
  339. /package/dist/apps/context-files-ui/assets/{gas-DMmxLZRI.js → gas-BHEdbvp9.js} +0 -0
  340. /package/dist/apps/context-files-ui/assets/{gherkin-DUSFg2R6.js → gherkin-oBAE_ms0.js} +0 -0
  341. /package/dist/apps/context-files-ui/assets/{haskell-Cyr255R9.js → haskell-BRsoo5mP.js} +0 -0
  342. /package/dist/apps/context-files-ui/assets/{http-DszHFpc-.js → http-CLVgA2GD.js} +0 -0
  343. /package/dist/apps/context-files-ui/assets/{idl-Cati9Nrv.js → idl-BUZw3wgd.js} +0 -0
  344. /package/dist/apps/context-files-ui/assets/{julia-DlqY1cTU.js → julia-CQfgDRfP.js} +0 -0
  345. /package/dist/apps/context-files-ui/assets/{livescript-C6p8-2W1.js → livescript-BXxG0Yva.js} +0 -0
  346. /package/dist/apps/context-files-ui/assets/{mathematica-nDHZUMJT.js → mathematica-u8YMmbU0.js} +0 -0
  347. /package/dist/apps/context-files-ui/assets/{mbox-DAaR0Hcz.js → mbox-BEMVcqjs.js} +0 -0
  348. /package/dist/apps/context-files-ui/assets/{mirc-CCA0FRfl.js → mirc-C9zpzAZU.js} +0 -0
  349. /package/dist/apps/context-files-ui/assets/{mllike-Cw3Iccsb.js → mllike-B45xgp2S.js} +0 -0
  350. /package/dist/apps/context-files-ui/assets/{modelica-Czx80fNR.js → modelica-CqHI_q-D.js} +0 -0
  351. /package/dist/apps/context-files-ui/assets/{mscgen-BmfuTbzG.js → mscgen-qgSLujhx.js} +0 -0
  352. /package/dist/apps/context-files-ui/assets/{nginx-D9M2PQ4U.js → nginx-BMaDbqW3.js} +0 -0
  353. /package/dist/apps/context-files-ui/assets/{octave-8jj96JiC.js → octave-D2Q8cUp1.js} +0 -0
  354. /package/dist/apps/context-files-ui/assets/{oz-BmMq7iC4.js → oz-BwTct_5T.js} +0 -0
  355. /package/dist/apps/context-files-ui/assets/{pascal-BgMr6XpT.js → pascal-Dp_KdFgX.js} +0 -0
  356. /package/dist/apps/context-files-ui/assets/{pig-nx7uchs8.js → pig-AF4Hwhju.js} +0 -0
  357. /package/dist/apps/context-files-ui/assets/{properties-CoavQdLC.js → properties-C357ku5U.js} +0 -0
  358. /package/dist/apps/context-files-ui/assets/{protobuf-D5EWhcmc.js → protobuf-D1ij_kNL.js} +0 -0
  359. /package/dist/apps/context-files-ui/assets/{q-BIB9pPtI.js → q-B9NhS7L_.js} +0 -0
  360. /package/dist/apps/context-files-ui/assets/{rpm-Ct_Ck8mQ.js → rpm-gpDK5sbt.js} +0 -0
  361. /package/dist/apps/context-files-ui/assets/{sas-DN4j74IF.js → sas-C2OyD2Y6.js} +0 -0
  362. /package/dist/apps/context-files-ui/assets/{sieve-C2U1O5Z4.js → sieve-BAxa3IjF.js} +0 -0
  363. /package/dist/apps/context-files-ui/assets/{smalltalk-DkYwYufV.js → smalltalk-BLp5-jwC.js} +0 -0
  364. /package/dist/apps/context-files-ui/assets/{solr-BopnSD-v.js → solr-BBopId9w.js} +0 -0
  365. /package/dist/apps/context-files-ui/assets/{sparql-Cpg3YQfd.js → sparql-Dz-mlCAC.js} +0 -0
  366. /package/dist/apps/context-files-ui/assets/{spreadsheet-kRxtVt9J.js → spreadsheet-CTIncYxj.js} +0 -0
  367. /package/dist/apps/context-files-ui/assets/{swift-DKNaLAK6.js → swift-DKB6_1j6.js} +0 -0
  368. /package/dist/apps/context-files-ui/assets/{tcl-CQyXkgMH.js → tcl-BGfruO1u.js} +0 -0
  369. /package/dist/apps/context-files-ui/assets/{tiddlywiki-dqVbkfX4.js → tiddlywiki-VlUiK86J.js} +0 -0
  370. /package/dist/apps/context-files-ui/assets/{troff-Bq3z6oAu.js → troff-C2dAgh7P.js} +0 -0
  371. /package/dist/apps/context-files-ui/assets/{vb-BmcHUM2C.js → vb-BthdM_4N.js} +0 -0
  372. /package/dist/apps/context-files-ui/assets/{vbscript-Cs9dylre.js → vbscript-D9f6rSsU.js} +0 -0
  373. /package/dist/apps/context-files-ui/assets/{velocity-CBWU0VCy.js → velocity-CqftRsjg.js} +0 -0
  374. /package/dist/apps/context-files-ui/assets/{webidl-egXQEWlC.js → webidl-D5jiJvOU.js} +0 -0
  375. /package/dist/apps/context-files-ui/assets/{yacas-DNs9XkmQ.js → yacas-CXXgtw0p.js} +0 -0
@@ -21,6 +21,13 @@ const BOOLEAN_CAPABILITY_PATHS = [
21
21
  "output.diffs",
22
22
  "output.rawNativeEvents",
23
23
  "mcp.statusInspection",
24
+ "contextDiscovery.supported",
25
+ "contextDiscovery.configurable",
26
+ "contextDiscovery.enabledByDefault",
27
+ "nativeSubagents.supported",
28
+ "nativeSubagents.configurable",
29
+ "nativeSubagents.enabledByDefault",
30
+ "historyImport",
24
31
  "auth.status",
25
32
  "auth.cancel",
26
33
  "auth.logout",
@@ -51,6 +58,13 @@ function readPath(value, path) {
51
58
  }
52
59
  return current;
53
60
  }
61
+ function safeDeclaredRelativePath(value) {
62
+ const normalized = value.replaceAll("\\", "/");
63
+ return !normalized.startsWith("/")
64
+ && !/^[A-Za-z]:/.test(normalized)
65
+ && !normalized.includes("\0")
66
+ && normalized.split("/").every((segment) => segment !== "..");
67
+ }
54
68
  function validateDelivery(path, value, errors) {
55
69
  if (!value || typeof value !== "object" || Array.isArray(value)) {
56
70
  errors.push(`${path} must be a capability-delivery object`);
@@ -107,6 +121,49 @@ export function validateAgentRuntimeCapabilities(value) {
107
121
  if (reasoningSupported === false && Array.isArray(reasoningValues) && reasoningValues.length > 0) {
108
122
  errors.push("reasoning.values must be omitted or empty when reasoning is unsupported");
109
123
  }
124
+ for (const feature of ["contextDiscovery", "nativeSubagents"]) {
125
+ const supported = readPath(value, `${feature}.supported`);
126
+ const configurable = readPath(value, `${feature}.configurable`);
127
+ const enabledByDefault = readPath(value, `${feature}.enabledByDefault`);
128
+ if (configurable === true && supported !== true) {
129
+ errors.push(`${feature}.configurable requires ${feature}.supported`);
130
+ }
131
+ if (enabledByDefault === true && supported !== true) {
132
+ errors.push(`${feature}.enabledByDefault requires ${feature}.supported`);
133
+ }
134
+ }
135
+ const contextDiscoveryStrategy = readPath(value, "contextDiscovery.strategy");
136
+ if (contextDiscoveryStrategy !== undefined
137
+ && !["filesystem-ancestors", "codex-project", "omp-project"].includes(String(contextDiscoveryStrategy))) {
138
+ errors.push("contextDiscovery.strategy must be filesystem-ancestors, codex-project, or omp-project when provided");
139
+ }
140
+ if (contextDiscoveryStrategy !== undefined && readPath(value, "contextDiscovery.supported") !== true) {
141
+ errors.push("contextDiscovery.strategy requires contextDiscovery.supported");
142
+ }
143
+ for (const field of ["knownFileNames", "knownUserRelativePaths", "knownCwdRelativePaths", "knownRelativePaths", "knownAncestorRelativePaths"]) {
144
+ const knownContextPaths = readPath(value, `contextDiscovery.${field}`);
145
+ if (knownContextPaths === undefined)
146
+ continue;
147
+ if (!Array.isArray(knownContextPaths)) {
148
+ errors.push(`contextDiscovery.${field} must be an array of non-empty strings when provided`);
149
+ continue;
150
+ }
151
+ if (knownContextPaths.some((name) => typeof name !== "string" || !name.trim())) {
152
+ errors.push(`contextDiscovery.${field} must be an array of non-empty strings when provided`);
153
+ }
154
+ else if (new Set(knownContextPaths).size !== knownContextPaths.length) {
155
+ errors.push(`contextDiscovery.${field} must not contain duplicates`);
156
+ }
157
+ else if (field === "knownFileNames" && knownContextPaths.some((name) => name.includes("/") || name.includes("\\") || name === "." || name === "..")) {
158
+ errors.push("contextDiscovery.knownFileNames entries must be plain filenames");
159
+ }
160
+ else if (field !== "knownFileNames" && knownContextPaths.some((path) => !safeDeclaredRelativePath(path))) {
161
+ errors.push(`contextDiscovery.${field} entries must be safe relative paths`);
162
+ }
163
+ if (readPath(value, "contextDiscovery.supported") !== true && knownContextPaths.length > 0) {
164
+ errors.push(`contextDiscovery.${field} requires contextDiscovery.supported`);
165
+ }
166
+ }
110
167
  const authMethods = readPath(value, "auth.methods");
111
168
  if (!Array.isArray(authMethods)) {
112
169
  errors.push("auth.methods must be an array");
@@ -193,6 +250,17 @@ export function createMinimalAgentRuntimeCapabilities() {
193
250
  },
194
251
  skills: unavailable,
195
252
  context: unavailable,
253
+ contextDiscovery: {
254
+ supported: false,
255
+ configurable: false,
256
+ enabledByDefault: false,
257
+ },
258
+ nativeSubagents: {
259
+ supported: false,
260
+ configurable: false,
261
+ enabledByDefault: false,
262
+ },
263
+ historyImport: false,
196
264
  auth: {
197
265
  status: false,
198
266
  methods: [],
@@ -5,12 +5,12 @@ export function profileWithRuntimeInstance(profile, runtimeInstanceId) {
5
5
  return new InitialSessionContext({
6
6
  profileName: profile.profileName,
7
7
  runtimeInstanceId,
8
- runtimeOptions: profile.runtimeOptions,
8
+ runtimeOptions: {},
9
9
  sessionId: profile.sessionId,
10
10
  parentSessionId: profile.parentSessionId,
11
- model: profile.model,
12
- mainModel: profile.mainModel,
13
- subagentModel: profile.subagentModel,
11
+ model: undefined,
12
+ mainModel: undefined,
13
+ subagentModel: undefined,
14
14
  thinkingLevel: profile.thinkingLevel,
15
15
  mainThinkingLevel: profile.mainThinkingLevel,
16
16
  subagentThinkingLevel: profile.subagentThinkingLevel,
@@ -26,6 +26,7 @@ export function profileWithRuntimeInstance(profile, runtimeInstanceId) {
26
26
  builtinTools: profile.builtinTools,
27
27
  builtinToolNames: profile.builtinToolNames,
28
28
  autoContextFiles: profile.autoContextFiles,
29
+ nativeSubagents: undefined,
29
30
  toolPackages: profile.toolPackages,
30
31
  });
31
32
  }
@@ -105,7 +106,12 @@ export function buildPortableRuntimeContextSnapshot(input) {
105
106
  else {
106
107
  addRuntimeContributionGroup(nodes, "skills", "Skills", profile.skills.filter((skill) => skill.enabled !== false).map((skill) => skill.name), input.runtime.capabilities.skills);
107
108
  addRuntimeContributionGroup(nodes, "context", "Context", [
108
- ...(profile.autoContextFiles ? ["automatic:AGENTS.md/CLAUDE.md"] : []),
109
+ ...(input.runtime.capabilities.contextDiscovery.supported
110
+ && (input.runtime.capabilities.contextDiscovery.configurable
111
+ ? profile.autoContextFiles
112
+ : input.runtime.capabilities.contextDiscovery.enabledByDefault)
113
+ ? ["automatic:runtime project context discovery"]
114
+ : []),
109
115
  ...profile.contextFiles.filter((file) => file.enabled !== false).map((file) => file.key ?? file.path),
110
116
  ], input.runtime.capabilities.context);
111
117
  addRuntimeContributionGroup(nodes, "mcp", "External MCP Servers", [...profile.mcpServers], input.runtime.capabilities.mcp.externalServers);
@@ -138,6 +144,8 @@ export function buildPortableRuntimeContextSnapshot(input) {
138
144
  subagentFast: profile.subagentFast ?? profile.fast,
139
145
  builtinTools: profile.builtinTools,
140
146
  builtinToolNames: profile.builtinToolNames,
147
+ nativeSubagents: profile.nativeSubagents
148
+ ?? input.runtime.capabilities.nativeSubagents.enabledByDefault,
141
149
  },
142
150
  });
143
151
  for (const [index, diagnostic] of input.runtime.diagnostics.entries()) {
@@ -0,0 +1,526 @@
1
+ import { createHash } from "node:crypto";
2
+ import { redactSensitiveText, redactSensitiveValue } from "../core/sensitive-data-redaction.js";
3
+ export const PORTABLE_HISTORY_HANDOFF_METADATA_KEY = "portableHistoryHandoff";
4
+ export const PORTABLE_HISTORY_LAST_IMPORT_METADATA_KEY = "portableHistoryLastImport";
5
+ const PORTABLE_HISTORY_VERSION = 1;
6
+ const MAX_SOURCE_ROWS = 4_000;
7
+ const MAX_HISTORY_ENTRIES = 1_000;
8
+ const MAX_HISTORY_BYTES = 1024 * 1024;
9
+ const MAX_ENTRY_BYTES = 256 * 1024;
10
+ const MAX_HISTORY_ENVELOPE_RESERVE_BYTES = 16 * 1024;
11
+ function validBoundedIdentifier(value) {
12
+ return typeof value === "string" && value.trim().length > 0 && value.length <= 256;
13
+ }
14
+ function validTimestamp(value) {
15
+ return typeof value === "string" && value.length <= 128 && Number.isFinite(Date.parse(value));
16
+ }
17
+ function parseObject(value) {
18
+ try {
19
+ const parsed = JSON.parse(value);
20
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed)
21
+ ? parsed
22
+ : {};
23
+ }
24
+ catch {
25
+ return {};
26
+ }
27
+ }
28
+ function jsonValue(value) {
29
+ if (value === undefined)
30
+ return undefined;
31
+ try {
32
+ return JSON.parse(JSON.stringify(redactSensitiveValue(value)));
33
+ }
34
+ catch {
35
+ return undefined;
36
+ }
37
+ }
38
+ function boundedIdentifierText(value, fallback, maxLength = 512) {
39
+ const normalized = value.trim();
40
+ const redacted = redactSensitiveText(normalized).replace(/[\r\n]+/g, " ").trim();
41
+ const needsHash = redacted !== normalized || redacted.length > maxLength;
42
+ const suffix = needsHash ? `-${createHash("sha256").update(value).digest("hex").slice(0, 12)}` : "";
43
+ const selected = (redacted || fallback).slice(0, Math.max(1, maxLength - suffix.length));
44
+ return `${selected}${suffix}`;
45
+ }
46
+ function optionalBoundedIdentifierText(value) {
47
+ return value ? boundedIdentifierText(value, "portable-id") : undefined;
48
+ }
49
+ function boundedText(value, maxBytes = MAX_ENTRY_BYTES) {
50
+ if (Buffer.byteLength(value, "utf8") <= maxBytes)
51
+ return value;
52
+ const suffix = "\n\n[Portable history entry truncated by Pibo.]";
53
+ const suffixBytes = Buffer.byteLength(suffix, "utf8");
54
+ const buffer = Buffer.from(value, "utf8");
55
+ return `${buffer.subarray(0, Math.max(0, maxBytes - suffixBytes)).toString("utf8")}${suffix}`;
56
+ }
57
+ function stringContent(entry) {
58
+ if (entry.type !== "message")
59
+ return entry.name;
60
+ if (typeof entry.content === "string")
61
+ return entry.content;
62
+ return entry.content.map((part) => {
63
+ if (part.type === "text" || part.type === "reasoning")
64
+ return part.text;
65
+ return `${part.toolName}:${JSON.stringify(part.input ?? null)}`;
66
+ }).join("\n");
67
+ }
68
+ function entryBytes(entry) {
69
+ return Buffer.byteLength(JSON.stringify(entry), "utf8");
70
+ }
71
+ function historyRole(value) {
72
+ return value === "user" || value === "assistant" || value === "system" ? value : undefined;
73
+ }
74
+ function historyStatus(value) {
75
+ if (value === "running" || value === "streaming" || value === "in_progress")
76
+ return "running";
77
+ if (value === "error" || value === "failed")
78
+ return "error";
79
+ return "complete";
80
+ }
81
+ export class PiboDataPortableHistoryProvider {
82
+ store;
83
+ constructor(store) {
84
+ this.store = store;
85
+ }
86
+ createCheckpoint(piboSessionId) {
87
+ const row = this.store.db.prepare(`
88
+ SELECT COALESCE(MAX(session_sequence), 0) AS max_sequence
89
+ FROM event_log
90
+ WHERE session_id = ?
91
+ `).get(piboSessionId);
92
+ return {
93
+ maxSessionSequence: Number(row.max_sequence ?? 0),
94
+ createdAt: new Date().toISOString(),
95
+ };
96
+ }
97
+ read(input) {
98
+ const messages = this.readMessages(input.piboSession.id, input.checkpoint, this.readRoutedUserMessages(input.piboSession.id, input.checkpoint));
99
+ const tools = this.readToolEntries(input.piboSession.id, input.checkpoint);
100
+ const nonPortableCount = this.nonPortableEntryCount(input.piboSession.id, input.checkpoint);
101
+ const modelEntries = [...messages, ...tools]
102
+ .sort((left, right) => (left.sequence ?? 0) - (right.sequence ?? 0) || left.createdAt.localeCompare(right.createdAt));
103
+ const contextEntry = {
104
+ id: "portable:pibo-context",
105
+ type: "message",
106
+ source: "product",
107
+ createdAt: input.checkpoint.createdAt,
108
+ sequence: 0,
109
+ role: "system",
110
+ content: [
111
+ "Pibo portable conversation handoff.",
112
+ `Pibo Session ID: ${input.piboSession.id}`,
113
+ `Pibo Room ID: ${typeof input.piboSession.metadata?.chatRoomId === "string" ? input.piboSession.metadata.chatRoomId : "unknown"}`,
114
+ `Profile: ${input.piboSession.profile}`,
115
+ `Source runtime: ${input.sourceBinding.runtimeInstanceId} (${input.sourceBinding.adapterId})`,
116
+ "The following entries are model-relevant product history. Private reasoning and runtime-private metadata are intentionally omitted.",
117
+ ].join("\n"),
118
+ status: "complete",
119
+ };
120
+ const nonPortableEntry = nonPortableCount > 0
121
+ ? {
122
+ id: "portable:nonportable-fallback",
123
+ type: "message",
124
+ source: "product",
125
+ createdAt: input.checkpoint.createdAt,
126
+ sequence: 0,
127
+ role: "system",
128
+ content: `${nonPortableCount} runtime-specific history entr${nonPortableCount === 1 ? "y was" : "ies were"} retained by Pibo but omitted from the portable model context because no safe cross-runtime representation exists.`,
129
+ status: "complete",
130
+ }
131
+ : undefined;
132
+ const bounded = boundEntries(modelEntries, {
133
+ maxEntries: MAX_HISTORY_ENTRIES - (nonPortableEntry ? 3 : 2),
134
+ maxBytes: Math.max(0, MAX_HISTORY_BYTES
135
+ - entryBytes(contextEntry)
136
+ - (nonPortableEntry ? entryBytes(nonPortableEntry) : 0)
137
+ - MAX_HISTORY_ENVELOPE_RESERVE_BYTES),
138
+ });
139
+ const retained = [...bounded.entries];
140
+ let additionallyOmitted = 0;
141
+ while (true) {
142
+ const omittedEntries = bounded.omittedEntries + additionallyOmitted;
143
+ const entries = [contextEntry];
144
+ if (nonPortableEntry)
145
+ entries.push(nonPortableEntry);
146
+ if (omittedEntries > 0) {
147
+ entries.push({
148
+ id: "portable:bounded-fallback",
149
+ type: "message",
150
+ source: "product",
151
+ createdAt: input.checkpoint.createdAt,
152
+ sequence: 0,
153
+ role: "system",
154
+ content: `${omittedEntries} older portable history entr${omittedEntries === 1 ? "y was" : "ies were"} omitted to stay within the bounded cross-runtime handoff limit. The most recent conversation context follows.`,
155
+ status: "complete",
156
+ });
157
+ }
158
+ entries.push(...normalizeToolPairs(retained));
159
+ const history = {
160
+ version: PORTABLE_HISTORY_VERSION,
161
+ piboSessionId: input.piboSession.id,
162
+ sourceRuntimeInstanceId: input.sourceBinding.runtimeInstanceId,
163
+ sourceAdapterId: input.sourceBinding.adapterId,
164
+ checkpoint: { ...input.checkpoint },
165
+ entries,
166
+ truncated: omittedEntries > 0,
167
+ omittedEntries,
168
+ };
169
+ const serializedBytes = Buffer.byteLength(JSON.stringify(history), "utf8");
170
+ if (serializedBytes <= MAX_HISTORY_BYTES)
171
+ return history;
172
+ if (retained.length === 0) {
173
+ throw new Error("Portable history metadata exceeds the aggregate handoff limit.");
174
+ }
175
+ const excessBytes = serializedBytes - MAX_HISTORY_BYTES;
176
+ const averageEntryBytes = Math.max(1, Math.floor(retained.reduce((sum, entry) => sum + entryBytes(entry), 0) / retained.length));
177
+ const removeCount = Math.min(retained.length, Math.max(1, Math.ceil(excessBytes / averageEntryBytes)));
178
+ retained.splice(0, removeCount);
179
+ additionallyOmitted += removeCount;
180
+ }
181
+ }
182
+ readMessages(piboSessionId, checkpoint, routedUserMessages) {
183
+ const rows = this.store.db.prepare(`
184
+ SELECT m.*, e.session_sequence AS event_sequence
185
+ FROM chat_messages m
186
+ LEFT JOIN event_log e ON e.stream_id = m.source_stream_id
187
+ WHERE m.session_id = ?
188
+ AND m.role IN ('user', 'assistant', 'system')
189
+ AND ((e.session_sequence IS NOT NULL AND e.session_sequence <= ?) OR (e.session_sequence IS NULL AND m.created_at <= ?))
190
+ ORDER BY COALESCE(e.session_sequence, m.sequence) DESC
191
+ LIMIT ?
192
+ `).all(piboSessionId, checkpoint.maxSessionSequence, checkpoint.createdAt, MAX_SOURCE_ROWS);
193
+ return rows.reverse().flatMap((row) => {
194
+ const role = historyRole(row.role);
195
+ if (!role)
196
+ return [];
197
+ const attributes = parseObject(row.attributes_json);
198
+ const clientTxnId = typeof attributes.clientTxnId === "string" ? attributes.clientTxnId : undefined;
199
+ if (role === "user") {
200
+ if (clientTxnId && !routedUserMessages.turnIds.has(clientTxnId))
201
+ return [];
202
+ if (!clientTxnId && row.source_stream_id !== null && !routedUserMessages.sourceStreamIds.has(row.source_stream_id))
203
+ return [];
204
+ }
205
+ let text = typeof attributes.inlineText === "string" ? attributes.inlineText : row.content_preview ?? "";
206
+ if (row.content_payload_ref) {
207
+ const payload = this.store.payloads.getPayload(row.content_payload_ref);
208
+ if (payload && payload.byteSize <= MAX_ENTRY_BYTES) {
209
+ text = this.store.payloads.readPayloadText(row.content_payload_ref);
210
+ }
211
+ }
212
+ return [{
213
+ id: `portable:message:${row.id}`,
214
+ type: "message",
215
+ source: "product",
216
+ createdAt: row.created_at,
217
+ sequence: row.event_sequence ?? row.sequence,
218
+ turnId: optionalBoundedIdentifierText(row.turn_id),
219
+ role,
220
+ content: boundedText(redactSensitiveText(text)),
221
+ status: historyStatus(row.status),
222
+ }];
223
+ });
224
+ }
225
+ readRoutedUserMessages(piboSessionId, checkpoint) {
226
+ const routedRows = this.store.db.prepare(`
227
+ SELECT DISTINCT turn_id
228
+ FROM event_log
229
+ WHERE session_id = ?
230
+ AND session_sequence <= ?
231
+ AND turn_id IS NOT NULL
232
+ AND type IN ('message_queued', 'message_steered', 'message_started')
233
+ `).all(piboSessionId, checkpoint.maxSessionSequence);
234
+ const acceptedRows = this.store.db.prepare(`
235
+ SELECT accepted.stream_id
236
+ FROM event_log accepted
237
+ WHERE accepted.session_id = ?
238
+ AND accepted.type = 'user.message.accepted'
239
+ AND accepted.session_sequence <= ?
240
+ AND EXISTS (
241
+ SELECT 1
242
+ FROM event_log routed
243
+ WHERE routed.session_id = accepted.session_id
244
+ AND routed.session_sequence > accepted.session_sequence
245
+ AND routed.session_sequence <= ?
246
+ AND routed.type IN ('message_queued', 'message_steered', 'message_started')
247
+ AND NOT EXISTS (
248
+ SELECT 1
249
+ FROM event_log next_user
250
+ WHERE next_user.session_id = accepted.session_id
251
+ AND next_user.type = 'user.message.accepted'
252
+ AND next_user.session_sequence > accepted.session_sequence
253
+ AND next_user.session_sequence < routed.session_sequence
254
+ )
255
+ )
256
+ `).all(piboSessionId, checkpoint.maxSessionSequence, checkpoint.maxSessionSequence);
257
+ return {
258
+ turnIds: new Set(routedRows.map((row) => row.turn_id)),
259
+ sourceStreamIds: new Set(acceptedRows.map((row) => row.stream_id)),
260
+ };
261
+ }
262
+ readToolEntries(piboSessionId, checkpoint) {
263
+ const rows = this.store.db.prepare(`
264
+ SELECT stream_id, session_sequence, type, turn_id, tool_call_id, payload_ref, preview_text, attributes_json, created_at
265
+ FROM event_log
266
+ WHERE session_id = ?
267
+ AND session_sequence <= ?
268
+ AND type IN ('tool_call', 'tool_execution_finished')
269
+ ORDER BY session_sequence DESC
270
+ LIMIT ?
271
+ `).all(piboSessionId, checkpoint.maxSessionSequence, MAX_SOURCE_ROWS).reverse();
272
+ const calls = new Map();
273
+ const results = new Map();
274
+ for (const row of rows) {
275
+ if (!row.tool_call_id)
276
+ continue;
277
+ if (row.type === "tool_call") {
278
+ const attributes = parseObject(row.attributes_json);
279
+ const existing = calls.get(row.tool_call_id);
280
+ if (!existing || attributes.argsComplete === true)
281
+ calls.set(row.tool_call_id, row);
282
+ }
283
+ else {
284
+ results.set(row.tool_call_id, row);
285
+ }
286
+ }
287
+ const entries = [];
288
+ for (const [toolCallId, row] of calls) {
289
+ const attributes = parseObject(row.attributes_json);
290
+ const portableToolCallId = boundedIdentifierText(toolCallId, `tool-call-${row.stream_id}`);
291
+ const toolName = boundedIdentifierText(typeof attributes.toolName === "string" ? attributes.toolName : row.preview_text ?? "tool", "tool", 256);
292
+ const part = {
293
+ type: "tool_call",
294
+ toolCallId: portableToolCallId,
295
+ toolName,
296
+ input: this.readEventPayload(row),
297
+ };
298
+ entries.push({
299
+ id: `portable:tool-call:${row.stream_id}`,
300
+ type: "message",
301
+ source: "product",
302
+ createdAt: row.created_at,
303
+ sequence: row.session_sequence,
304
+ turnId: optionalBoundedIdentifierText(row.turn_id),
305
+ role: "assistant",
306
+ content: [part],
307
+ status: "complete",
308
+ toolCallId: portableToolCallId,
309
+ toolName,
310
+ });
311
+ }
312
+ for (const [toolCallId, row] of results) {
313
+ const attributes = parseObject(row.attributes_json);
314
+ const portableToolCallId = boundedIdentifierText(toolCallId, `tool-call-${row.stream_id}`);
315
+ const toolName = boundedIdentifierText(typeof attributes.toolName === "string" ? attributes.toolName : row.preview_text ?? "tool", "tool", 256);
316
+ const result = this.readEventPayload(row) ?? null;
317
+ entries.push({
318
+ id: `portable:tool-result:${row.stream_id}`,
319
+ type: "message",
320
+ source: "product",
321
+ createdAt: row.created_at,
322
+ sequence: row.session_sequence,
323
+ turnId: optionalBoundedIdentifierText(row.turn_id),
324
+ role: "tool",
325
+ content: boundedText(JSON.stringify(result)),
326
+ status: attributes.isError === true ? "error" : "complete",
327
+ toolCallId: portableToolCallId,
328
+ toolName,
329
+ result,
330
+ isError: attributes.isError === true,
331
+ });
332
+ }
333
+ return entries;
334
+ }
335
+ readEventPayload(row) {
336
+ const attributes = parseObject(row.attributes_json);
337
+ if (attributes.inlinePayload !== undefined)
338
+ return jsonValue(attributes.inlinePayload);
339
+ if (!row.payload_ref)
340
+ return undefined;
341
+ const payload = this.store.payloads.getPayload(row.payload_ref);
342
+ if (!payload)
343
+ return { portableFallback: "Tool payload is no longer available in Pibo history." };
344
+ if (payload.byteSize > MAX_ENTRY_BYTES) {
345
+ return {
346
+ portableFallback: "Tool payload exceeded the per-entry portable history limit.",
347
+ preview: redactSensitiveText(payload.previewText ?? row.preview_text ?? ""),
348
+ };
349
+ }
350
+ try {
351
+ return jsonValue(payload.contentType.includes("json")
352
+ ? this.store.payloads.readPayloadJson(row.payload_ref)
353
+ : this.store.payloads.readPayloadText(row.payload_ref));
354
+ }
355
+ catch {
356
+ return { portableFallback: "Tool payload could not be read from Pibo history." };
357
+ }
358
+ }
359
+ nonPortableEntryCount(piboSessionId, checkpoint) {
360
+ const row = this.store.db.prepare(`
361
+ SELECT COUNT(*) AS count
362
+ FROM event_log
363
+ WHERE session_id = ?
364
+ AND session_sequence <= ?
365
+ AND (type = 'pi_event' OR type LIKE 'thinking_%' OR type = 'subagent_session')
366
+ `).get(piboSessionId, checkpoint.maxSessionSequence);
367
+ return Number(row.count ?? 0);
368
+ }
369
+ }
370
+ function normalizeToolPairs(entries) {
371
+ const callIds = new Set();
372
+ const resultIds = new Set();
373
+ for (const entry of entries) {
374
+ if (entry.type !== "message")
375
+ continue;
376
+ if (entry.role === "tool" && entry.toolCallId)
377
+ resultIds.add(entry.toolCallId);
378
+ if (!Array.isArray(entry.content))
379
+ continue;
380
+ for (const part of entry.content) {
381
+ if (part.type === "tool_call")
382
+ callIds.add(part.toolCallId);
383
+ }
384
+ }
385
+ return entries.map((entry) => {
386
+ if (entry.type !== "message")
387
+ return entry;
388
+ if (entry.role === "tool" && entry.toolCallId && !callIds.has(entry.toolCallId)) {
389
+ return {
390
+ ...entry,
391
+ role: "user",
392
+ content: [
393
+ `[Portable fallback: result from tool "${entry.toolName ?? "tool"}" had no retained matching call.]`,
394
+ typeof entry.content === "string" ? entry.content : JSON.stringify(entry.result ?? null),
395
+ ].join("\n"),
396
+ toolCallId: undefined,
397
+ toolName: undefined,
398
+ result: undefined,
399
+ isError: undefined,
400
+ };
401
+ }
402
+ if (entry.role !== "assistant" || !Array.isArray(entry.content))
403
+ return entry;
404
+ const content = entry.content.map((part) => {
405
+ if (part.type !== "tool_call" || resultIds.has(part.toolCallId))
406
+ return part;
407
+ return {
408
+ type: "text",
409
+ text: `[Portable fallback: tool call "${part.toolName}" had no retained result.]\nInput: ${JSON.stringify(part.input ?? null)}`,
410
+ };
411
+ });
412
+ return content.some((part) => part.type === "tool_call")
413
+ ? { ...entry, content }
414
+ : { ...entry, content, toolCallId: undefined, toolName: undefined };
415
+ });
416
+ }
417
+ function boundEntries(entries, limits) {
418
+ const selected = [];
419
+ let bytes = 0;
420
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
421
+ const entry = entries[index];
422
+ const normalized = normalizeEntrySize(entry);
423
+ const size = entryBytes(normalized);
424
+ if (selected.length >= limits.maxEntries || bytes + size > limits.maxBytes)
425
+ continue;
426
+ selected.push(normalized);
427
+ bytes += size;
428
+ }
429
+ selected.reverse();
430
+ return { entries: selected, omittedEntries: entries.length - selected.length };
431
+ }
432
+ function normalizeEntrySize(entry) {
433
+ if (entry.type !== "message")
434
+ return entry;
435
+ if (typeof entry.content === "string")
436
+ return { ...entry, content: boundedText(entry.content) };
437
+ if (entryBytes(entry) <= MAX_ENTRY_BYTES)
438
+ return entry;
439
+ return {
440
+ ...entry,
441
+ content: boundedText(stringContent(entry)),
442
+ result: entry.result === undefined ? undefined : {
443
+ portableFallback: "Structured history content exceeded the per-entry limit.",
444
+ },
445
+ };
446
+ }
447
+ export function createPortableHistoryHandoffMetadata(input) {
448
+ return {
449
+ version: PORTABLE_HISTORY_VERSION,
450
+ status: "pending",
451
+ mode: input.mode,
452
+ sourceRuntimeInstanceId: input.sourceBinding.runtimeInstanceId,
453
+ sourceAdapterId: input.sourceBinding.adapterId,
454
+ targetRuntimeInstanceId: input.targetBinding.runtimeInstanceId,
455
+ targetAdapterId: input.targetBinding.adapterId,
456
+ requestedAt: new Date().toISOString(),
457
+ ...(input.checkpoint ? { checkpoint: { ...input.checkpoint } } : {}),
458
+ };
459
+ }
460
+ export function readPortableHistoryHandoffMetadata(metadata) {
461
+ const value = metadata?.[PORTABLE_HISTORY_HANDOFF_METADATA_KEY];
462
+ if (!value || typeof value !== "object" || Array.isArray(value))
463
+ return undefined;
464
+ const record = value;
465
+ if (record.version !== PORTABLE_HISTORY_VERSION || record.status !== "pending" || (record.mode !== "import" && record.mode !== "fresh"))
466
+ return undefined;
467
+ if (!validBoundedIdentifier(record.sourceRuntimeInstanceId)
468
+ || !validBoundedIdentifier(record.sourceAdapterId)
469
+ || !validBoundedIdentifier(record.targetRuntimeInstanceId)
470
+ || !validBoundedIdentifier(record.targetAdapterId)
471
+ || !validTimestamp(record.requestedAt))
472
+ return undefined;
473
+ let checkpoint;
474
+ if (record.mode === "import") {
475
+ const raw = record.checkpoint;
476
+ if (!raw || typeof raw !== "object" || Array.isArray(raw))
477
+ return undefined;
478
+ const selected = raw;
479
+ if (!Number.isSafeInteger(selected.maxSessionSequence) || Number(selected.maxSessionSequence) < 0 || !validTimestamp(selected.createdAt))
480
+ return undefined;
481
+ checkpoint = {
482
+ maxSessionSequence: Number(selected.maxSessionSequence),
483
+ createdAt: selected.createdAt,
484
+ };
485
+ }
486
+ return {
487
+ version: PORTABLE_HISTORY_VERSION,
488
+ status: "pending",
489
+ mode: record.mode,
490
+ sourceRuntimeInstanceId: record.sourceRuntimeInstanceId,
491
+ sourceAdapterId: record.sourceAdapterId,
492
+ targetRuntimeInstanceId: record.targetRuntimeInstanceId,
493
+ targetAdapterId: record.targetAdapterId,
494
+ requestedAt: record.requestedAt,
495
+ ...(checkpoint ? { checkpoint } : {}),
496
+ };
497
+ }
498
+ export function withPortableHistoryHandoffMetadata(metadata, handoff) {
499
+ return {
500
+ ...(metadata ?? {}),
501
+ [PORTABLE_HISTORY_HANDOFF_METADATA_KEY]: handoff,
502
+ };
503
+ }
504
+ export function withoutPortableHistoryHandoffMetadata(input) {
505
+ const { [PORTABLE_HISTORY_HANDOFF_METADATA_KEY]: _handoff, ...metadata } = input.metadata ?? {};
506
+ return {
507
+ ...metadata,
508
+ [PORTABLE_HISTORY_LAST_IMPORT_METADATA_KEY]: {
509
+ version: PORTABLE_HISTORY_VERSION,
510
+ status: "completed",
511
+ mode: input.handoff.mode,
512
+ sourceRuntimeInstanceId: input.handoff.sourceRuntimeInstanceId,
513
+ sourceAdapterId: input.handoff.sourceAdapterId,
514
+ targetRuntimeInstanceId: input.handoff.targetRuntimeInstanceId,
515
+ targetAdapterId: input.handoff.targetAdapterId,
516
+ requestedAt: input.handoff.requestedAt,
517
+ ...(input.handoff.checkpoint ? { checkpoint: { ...input.handoff.checkpoint } } : {}),
518
+ completedAt: new Date().toISOString(),
519
+ ...(input.history ? {
520
+ entryCount: input.history.entries.length,
521
+ truncated: input.history.truncated,
522
+ omittedEntries: input.history.omittedEntries,
523
+ } : {}),
524
+ },
525
+ };
526
+ }