@athenaintel/react 0.57.2 → 0.60.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 (852) hide show
  1. package/README.md +795 -12
  2. package/dist/agent-runtime/src/addressed-agents.cjs +16 -0
  3. package/dist/agent-runtime/src/addressed-agents.cjs.map +1 -0
  4. package/dist/agent-runtime/src/addressed-agents.d.ts +30 -0
  5. package/dist/agent-runtime/src/addressed-agents.js +16 -0
  6. package/dist/agent-runtime/src/addressed-agents.js.map +1 -0
  7. package/dist/agent-runtime/src/answer-label.cjs +4 -3
  8. package/dist/agent-runtime/src/answer-label.cjs.map +1 -1
  9. package/dist/agent-runtime/src/answer-label.d.ts +13 -6
  10. package/dist/agent-runtime/src/answer-label.js +4 -3
  11. package/dist/agent-runtime/src/answer-label.js.map +1 -1
  12. package/dist/agent-runtime/src/chat-outbox-attachments.cjs.map +1 -1
  13. package/dist/agent-runtime/src/chat-outbox-attachments.d.ts +1 -1
  14. package/dist/agent-runtime/src/chat-outbox-attachments.js.map +1 -1
  15. package/dist/agent-runtime/src/chat-outbox-entry.cjs +101 -0
  16. package/dist/agent-runtime/src/chat-outbox-entry.cjs.map +1 -0
  17. package/dist/agent-runtime/src/chat-outbox-entry.d.ts +99 -0
  18. package/dist/agent-runtime/src/chat-outbox-entry.js +101 -0
  19. package/dist/agent-runtime/src/chat-outbox-entry.js.map +1 -0
  20. package/dist/agent-runtime/src/chat-outbox-legacy.cjs +252 -0
  21. package/dist/agent-runtime/src/chat-outbox-legacy.cjs.map +1 -0
  22. package/dist/agent-runtime/src/chat-outbox-legacy.d.ts +96 -0
  23. package/dist/agent-runtime/src/chat-outbox-legacy.js +252 -0
  24. package/dist/agent-runtime/src/chat-outbox-legacy.js.map +1 -0
  25. package/dist/agent-runtime/src/chat-outbox-policy.cjs +30 -0
  26. package/dist/agent-runtime/src/chat-outbox-policy.cjs.map +1 -0
  27. package/dist/agent-runtime/src/chat-outbox-policy.d.ts +42 -0
  28. package/dist/agent-runtime/src/chat-outbox-policy.js +30 -0
  29. package/dist/agent-runtime/src/chat-outbox-policy.js.map +1 -0
  30. package/dist/agent-runtime/src/chat-outbox-storage.cjs +306 -0
  31. package/dist/agent-runtime/src/chat-outbox-storage.cjs.map +1 -0
  32. package/dist/agent-runtime/src/chat-outbox-storage.d.ts +194 -0
  33. package/dist/agent-runtime/src/chat-outbox-storage.js +306 -0
  34. package/dist/agent-runtime/src/chat-outbox-storage.js.map +1 -0
  35. package/dist/agent-runtime/src/chat-outbox-thread.cjs +21 -94
  36. package/dist/agent-runtime/src/chat-outbox-thread.cjs.map +1 -1
  37. package/dist/agent-runtime/src/chat-outbox-thread.d.ts +22 -18
  38. package/dist/agent-runtime/src/chat-outbox-thread.js +21 -94
  39. package/dist/agent-runtime/src/chat-outbox-thread.js.map +1 -1
  40. package/dist/agent-runtime/src/chat-outbox.cjs +492 -547
  41. package/dist/agent-runtime/src/chat-outbox.cjs.map +1 -1
  42. package/dist/agent-runtime/src/chat-outbox.d.ts +110 -142
  43. package/dist/agent-runtime/src/chat-outbox.js +492 -547
  44. package/dist/agent-runtime/src/chat-outbox.js.map +1 -1
  45. package/dist/agent-runtime/src/composer-markdown.cjs +0 -16
  46. package/dist/agent-runtime/src/composer-markdown.cjs.map +1 -1
  47. package/dist/agent-runtime/src/composer-markdown.d.ts +1 -1
  48. package/dist/agent-runtime/src/composer-markdown.js +1 -17
  49. package/dist/agent-runtime/src/composer-markdown.js.map +1 -1
  50. package/dist/agent-runtime/src/deep-agent-transport-recipe.cjs +3 -1
  51. package/dist/agent-runtime/src/deep-agent-transport-recipe.cjs.map +1 -1
  52. package/dist/agent-runtime/src/deep-agent-transport-recipe.d.ts +8 -1
  53. package/dist/agent-runtime/src/deep-agent-transport-recipe.js +3 -1
  54. package/dist/agent-runtime/src/deep-agent-transport-recipe.js.map +1 -1
  55. package/dist/agent-runtime/src/dictation-preferences.d.ts +356 -0
  56. package/dist/agent-runtime/src/dictation-record.d.ts +279 -0
  57. package/dist/agent-runtime/src/dictation-session.d.ts +106 -7
  58. package/dist/agent-runtime/src/dictation-snippets.d.ts +9 -0
  59. package/dist/agent-runtime/src/dictation-transfer.d.ts +142 -0
  60. package/dist/agent-runtime/src/edit-command.cjs.map +1 -1
  61. package/dist/agent-runtime/src/edit-command.d.ts +1 -1
  62. package/dist/agent-runtime/src/edit-command.js.map +1 -1
  63. package/dist/agent-runtime/src/errors.cjs +1 -0
  64. package/dist/agent-runtime/src/errors.cjs.map +1 -1
  65. package/dist/agent-runtime/src/errors.js +1 -0
  66. package/dist/agent-runtime/src/errors.js.map +1 -1
  67. package/dist/agent-runtime/src/generated/runconfig-contract.cjs +24 -0
  68. package/dist/agent-runtime/src/generated/runconfig-contract.cjs.map +1 -1
  69. package/dist/agent-runtime/src/generated/runconfig-contract.d.ts +3 -3
  70. package/dist/agent-runtime/src/generated/runconfig-contract.js +24 -0
  71. package/dist/agent-runtime/src/generated/runconfig-contract.js.map +1 -1
  72. package/dist/agent-runtime/src/index.d.ts +14 -8
  73. package/dist/agent-runtime/src/lane-follow.cjs +289 -0
  74. package/dist/agent-runtime/src/lane-follow.cjs.map +1 -0
  75. package/dist/agent-runtime/src/lane-follow.js +289 -0
  76. package/dist/agent-runtime/src/lane-follow.js.map +1 -0
  77. package/dist/agent-runtime/src/lane-images.cjs +387 -0
  78. package/dist/agent-runtime/src/lane-images.cjs.map +1 -0
  79. package/dist/agent-runtime/src/lane-images.js +387 -0
  80. package/dist/agent-runtime/src/lane-images.js.map +1 -0
  81. package/dist/agent-runtime/src/message-window.js +1 -1
  82. package/dist/agent-runtime/src/messages.cjs +19 -1
  83. package/dist/agent-runtime/src/messages.cjs.map +1 -1
  84. package/dist/agent-runtime/src/messages.d.ts +8 -0
  85. package/dist/agent-runtime/src/messages.js +21 -3
  86. package/dist/agent-runtime/src/messages.js.map +1 -1
  87. package/dist/agent-runtime/src/named-agents.cjs +301 -0
  88. package/dist/agent-runtime/src/named-agents.cjs.map +1 -0
  89. package/dist/agent-runtime/src/named-agents.d.ts +246 -0
  90. package/dist/agent-runtime/src/named-agents.js +301 -0
  91. package/dist/agent-runtime/src/named-agents.js.map +1 -0
  92. package/dist/agent-runtime/src/offline-status.cjs.map +1 -1
  93. package/dist/agent-runtime/src/offline-status.d.ts +93 -2
  94. package/dist/agent-runtime/src/offline-status.js.map +1 -1
  95. package/dist/agent-runtime/src/ptc-subcalls.cjs +41 -0
  96. package/dist/agent-runtime/src/ptc-subcalls.cjs.map +1 -0
  97. package/dist/agent-runtime/src/ptc-subcalls.js +41 -0
  98. package/dist/agent-runtime/src/ptc-subcalls.js.map +1 -0
  99. package/dist/agent-runtime/src/queue.cjs +2 -2
  100. package/dist/agent-runtime/src/queue.cjs.map +1 -1
  101. package/dist/agent-runtime/src/queue.d.ts +20 -25
  102. package/dist/agent-runtime/src/queue.js +2 -2
  103. package/dist/agent-runtime/src/queue.js.map +1 -1
  104. package/dist/agent-runtime/src/quota-safe-local-storage-session.cjs +314 -84
  105. package/dist/agent-runtime/src/quota-safe-local-storage-session.cjs.map +1 -1
  106. package/dist/agent-runtime/src/quota-safe-local-storage-session.d.ts +137 -40
  107. package/dist/agent-runtime/src/quota-safe-local-storage-session.js +318 -88
  108. package/dist/agent-runtime/src/quota-safe-local-storage-session.js.map +1 -1
  109. package/dist/agent-runtime/src/run-send.cjs +54 -0
  110. package/dist/agent-runtime/src/run-send.cjs.map +1 -0
  111. package/dist/agent-runtime/src/run-send.d.ts +51 -0
  112. package/dist/agent-runtime/src/run-send.js +54 -0
  113. package/dist/agent-runtime/src/run-send.js.map +1 -0
  114. package/dist/agent-runtime/src/running-tool-placeholder.cjs +6 -0
  115. package/dist/agent-runtime/src/running-tool-placeholder.cjs.map +1 -1
  116. package/dist/agent-runtime/src/running-tool-placeholder.js +6 -0
  117. package/dist/agent-runtime/src/running-tool-placeholder.js.map +1 -1
  118. package/dist/agent-runtime/src/runtime.d.ts +9 -5
  119. package/dist/agent-runtime/src/sealed-idb.cjs +64 -0
  120. package/dist/agent-runtime/src/sealed-idb.cjs.map +1 -1
  121. package/dist/agent-runtime/src/sealed-idb.d.ts +16 -0
  122. package/dist/agent-runtime/src/sealed-idb.js +64 -0
  123. package/dist/agent-runtime/src/sealed-idb.js.map +1 -1
  124. package/dist/agent-runtime/src/send-recovery.cjs +90 -118
  125. package/dist/agent-runtime/src/send-recovery.cjs.map +1 -1
  126. package/dist/agent-runtime/src/send-recovery.d.ts +25 -29
  127. package/dist/agent-runtime/src/send-recovery.js +90 -118
  128. package/dist/agent-runtime/src/send-recovery.js.map +1 -1
  129. package/dist/agent-runtime/src/statewire-diagnostics.d.ts +4 -1
  130. package/dist/agent-runtime/src/statewire-held-sends.cjs +191 -0
  131. package/dist/agent-runtime/src/statewire-held-sends.cjs.map +1 -0
  132. package/dist/agent-runtime/src/statewire-held-sends.d.ts +119 -0
  133. package/dist/agent-runtime/src/statewire-held-sends.js +191 -0
  134. package/dist/agent-runtime/src/statewire-held-sends.js.map +1 -0
  135. package/dist/agent-runtime/src/statewire-state.cjs +4 -0
  136. package/dist/agent-runtime/src/statewire-state.cjs.map +1 -1
  137. package/dist/agent-runtime/src/statewire-state.js +4 -0
  138. package/dist/agent-runtime/src/statewire-state.js.map +1 -1
  139. package/dist/agent-runtime/src/statewire-transport.cjs +8 -2
  140. package/dist/agent-runtime/src/statewire-transport.cjs.map +1 -1
  141. package/dist/agent-runtime/src/statewire-transport.d.ts +14 -5
  142. package/dist/agent-runtime/src/statewire-transport.js +8 -2
  143. package/dist/agent-runtime/src/statewire-transport.js.map +1 -1
  144. package/dist/agent-runtime/src/subagent-transcripts.cjs +1 -23
  145. package/dist/agent-runtime/src/subagent-transcripts.cjs.map +1 -1
  146. package/dist/agent-runtime/src/subagent-transcripts.js +3 -25
  147. package/dist/agent-runtime/src/subagent-transcripts.js.map +1 -1
  148. package/dist/agent-runtime/src/subagents.cjs +22 -29
  149. package/dist/agent-runtime/src/subagents.cjs.map +1 -1
  150. package/dist/agent-runtime/src/subagents.js +23 -30
  151. package/dist/agent-runtime/src/subagents.js.map +1 -1
  152. package/dist/agent-runtime/src/thread-extras.cjs +27 -19
  153. package/dist/agent-runtime/src/thread-extras.cjs.map +1 -1
  154. package/dist/agent-runtime/src/thread-extras.d.ts +19 -6
  155. package/dist/agent-runtime/src/thread-extras.js +27 -19
  156. package/dist/agent-runtime/src/thread-extras.js.map +1 -1
  157. package/dist/agent-runtime/src/thread-handoff-flow-machine.d.ts +8 -8
  158. package/dist/agent-runtime/src/tool-metadata.cjs +19 -0
  159. package/dist/agent-runtime/src/tool-metadata.cjs.map +1 -1
  160. package/dist/agent-runtime/src/tool-metadata.js +19 -0
  161. package/dist/agent-runtime/src/tool-metadata.js.map +1 -1
  162. package/dist/agent-runtime/src/tool-names.cjs +21 -0
  163. package/dist/agent-runtime/src/tool-names.cjs.map +1 -1
  164. package/dist/agent-runtime/src/tool-names.d.ts +8 -0
  165. package/dist/agent-runtime/src/tool-names.js +21 -0
  166. package/dist/agent-runtime/src/tool-names.js.map +1 -1
  167. package/dist/agent-runtime/src/typed-interrupt-kinds.cjs +247 -0
  168. package/dist/agent-runtime/src/typed-interrupt-kinds.cjs.map +1 -0
  169. package/dist/agent-runtime/src/typed-interrupt-kinds.d.ts +173 -0
  170. package/dist/agent-runtime/src/typed-interrupt-kinds.js +247 -0
  171. package/dist/agent-runtime/src/typed-interrupt-kinds.js.map +1 -0
  172. package/dist/agent-runtime/src/typed-interrupts.cjs +48 -0
  173. package/dist/agent-runtime/src/typed-interrupts.cjs.map +1 -0
  174. package/dist/agent-runtime/src/typed-interrupts.d.ts +75 -0
  175. package/dist/agent-runtime/src/typed-interrupts.js +48 -0
  176. package/dist/agent-runtime/src/typed-interrupts.js.map +1 -0
  177. package/dist/agent-runtime/src/types.d.ts +1 -1
  178. package/dist/agent-runtime/src/use-conversation-list.cjs +1 -0
  179. package/dist/agent-runtime/src/use-conversation-list.cjs.map +1 -1
  180. package/dist/agent-runtime/src/use-conversation-list.d.ts +7 -0
  181. package/dist/agent-runtime/src/use-conversation-list.js +1 -0
  182. package/dist/agent-runtime/src/use-conversation-list.js.map +1 -1
  183. package/dist/agent-runtime/src/use-deep-agent-chat-outbox.cjs +46 -29
  184. package/dist/agent-runtime/src/use-deep-agent-chat-outbox.cjs.map +1 -1
  185. package/dist/agent-runtime/src/use-deep-agent-chat-outbox.d.ts +14 -22
  186. package/dist/agent-runtime/src/use-deep-agent-chat-outbox.js +46 -29
  187. package/dist/agent-runtime/src/use-deep-agent-chat-outbox.js.map +1 -1
  188. package/dist/agent-runtime/src/use-deep-agent-runtime.cjs +78 -14
  189. package/dist/agent-runtime/src/use-deep-agent-runtime.cjs.map +1 -1
  190. package/dist/agent-runtime/src/use-deep-agent-runtime.d.ts +34 -7
  191. package/dist/agent-runtime/src/use-deep-agent-runtime.js +79 -15
  192. package/dist/agent-runtime/src/use-deep-agent-runtime.js.map +1 -1
  193. package/dist/agent-runtime/src/use-deep-agent-thread.cjs +16 -1
  194. package/dist/agent-runtime/src/use-deep-agent-thread.cjs.map +1 -1
  195. package/dist/agent-runtime/src/use-deep-agent-thread.d.ts +7 -2
  196. package/dist/agent-runtime/src/use-deep-agent-thread.js +16 -1
  197. package/dist/agent-runtime/src/use-deep-agent-thread.js.map +1 -1
  198. package/dist/agent-runtime/src/use-deep-agent-voice.cjs +30 -4
  199. package/dist/agent-runtime/src/use-deep-agent-voice.cjs.map +1 -1
  200. package/dist/agent-runtime/src/use-deep-agent-voice.d.ts +22 -4
  201. package/dist/agent-runtime/src/use-deep-agent-voice.js +30 -4
  202. package/dist/agent-runtime/src/use-deep-agent-voice.js.map +1 -1
  203. package/dist/agent-runtime/src/withdrawn-turns.d.ts +5 -4
  204. package/dist/agent-runtime/src/word-device-fit.d.ts +174 -0
  205. package/dist/agent-runtime/src/work-in.d.ts +127 -0
  206. package/dist/assets/AthenaAssetEmbed.cjs.map +1 -1
  207. package/dist/assets/AthenaAssetEmbed.d.ts +6 -1
  208. package/dist/assets/AthenaAssetEmbed.js.map +1 -1
  209. package/dist/assets/asset-panel-store.cjs +13 -5
  210. package/dist/assets/asset-panel-store.cjs.map +1 -1
  211. package/dist/assets/asset-panel-store.d.ts +33 -2
  212. package/dist/assets/asset-panel-store.js +13 -5
  213. package/dist/assets/asset-panel-store.js.map +1 -1
  214. package/dist/auth/AthenaCredentialSourceContext.cjs +11 -0
  215. package/dist/auth/AthenaCredentialSourceContext.cjs.map +1 -1
  216. package/dist/auth/AthenaCredentialSourceContext.d.ts +6 -0
  217. package/dist/auth/AthenaCredentialSourceContext.js +11 -0
  218. package/dist/auth/AthenaCredentialSourceContext.js.map +1 -1
  219. package/dist/auth/account-identity.cjs +13 -2
  220. package/dist/auth/account-identity.cjs.map +1 -1
  221. package/dist/auth/account-identity.d.ts +9 -0
  222. package/dist/auth/account-identity.js +13 -2
  223. package/dist/auth/account-identity.js.map +1 -1
  224. package/dist/auth/credential-source.cjs +20 -4
  225. package/dist/auth/credential-source.cjs.map +1 -1
  226. package/dist/auth/credential-source.d.ts +9 -0
  227. package/dist/auth/credential-source.js +20 -4
  228. package/dist/auth/credential-source.js.map +1 -1
  229. package/dist/catalog/chat-pickers.cjs +31 -0
  230. package/dist/catalog/chat-pickers.cjs.map +1 -1
  231. package/dist/catalog/chat-pickers.d.ts +17 -0
  232. package/dist/catalog/chat-pickers.js +33 -2
  233. package/dist/catalog/chat-pickers.js.map +1 -1
  234. package/dist/catalog/runtime-catalog.cjs +63 -3
  235. package/dist/catalog/runtime-catalog.cjs.map +1 -1
  236. package/dist/catalog/runtime-catalog.d.ts +63 -3
  237. package/dist/catalog/runtime-catalog.js +64 -4
  238. package/dist/catalog/runtime-catalog.js.map +1 -1
  239. package/dist/chat/AthenaChat.cjs +301 -98
  240. package/dist/chat/AthenaChat.cjs.map +1 -1
  241. package/dist/chat/AthenaChat.d.ts +80 -4
  242. package/dist/chat/AthenaChat.js +302 -99
  243. package/dist/chat/AthenaChat.js.map +1 -1
  244. package/dist/chat/StatewireApprovalCard.cjs +35 -5
  245. package/dist/chat/StatewireApprovalCard.cjs.map +1 -1
  246. package/dist/chat/StatewireApprovalCard.d.ts +55 -2
  247. package/dist/chat/StatewireApprovalCard.js +37 -7
  248. package/dist/chat/StatewireApprovalCard.js.map +1 -1
  249. package/dist/chat/StatewireQueuedMessages.cjs +17 -2
  250. package/dist/chat/StatewireQueuedMessages.cjs.map +1 -1
  251. package/dist/chat/StatewireQueuedMessages.d.ts +8 -45
  252. package/dist/chat/StatewireQueuedMessages.js +18 -3
  253. package/dist/chat/StatewireQueuedMessages.js.map +1 -1
  254. package/dist/chat/chat-agent-mentions.cjs +70 -0
  255. package/dist/chat/chat-agent-mentions.cjs.map +1 -0
  256. package/dist/chat/chat-agent-mentions.d.ts +13 -0
  257. package/dist/chat/chat-agent-mentions.js +70 -0
  258. package/dist/chat/chat-agent-mentions.js.map +1 -0
  259. package/dist/chat/composer-actions.cjs +12 -0
  260. package/dist/chat/composer-actions.cjs.map +1 -0
  261. package/dist/chat/composer-actions.d.ts +22 -0
  262. package/dist/chat/composer-actions.js +12 -0
  263. package/dist/chat/composer-actions.js.map +1 -0
  264. package/dist/chat/follow-up-suggestions.cjs +185 -0
  265. package/dist/chat/follow-up-suggestions.cjs.map +1 -0
  266. package/dist/chat/follow-up-suggestions.d.ts +64 -0
  267. package/dist/chat/follow-up-suggestions.js +185 -0
  268. package/dist/chat/follow-up-suggestions.js.map +1 -0
  269. package/dist/chat/super-grouping/ToolTimeline.cjs +4 -3
  270. package/dist/chat/super-grouping/ToolTimeline.cjs.map +1 -1
  271. package/dist/chat/super-grouping/ToolTimeline.d.ts +7 -3
  272. package/dist/chat/super-grouping/ToolTimeline.js +4 -3
  273. package/dist/chat/super-grouping/ToolTimeline.js.map +1 -1
  274. package/dist/chat/turn-changes.cjs +284 -0
  275. package/dist/chat/turn-changes.cjs.map +1 -0
  276. package/dist/chat/turn-changes.d.ts +130 -0
  277. package/dist/chat/turn-changes.js +284 -0
  278. package/dist/chat/turn-changes.js.map +1 -0
  279. package/dist/chat/typed-interrupts/StatewireTypedInterruptCard.cjs +31 -0
  280. package/dist/chat/typed-interrupts/StatewireTypedInterruptCard.cjs.map +1 -0
  281. package/dist/chat/typed-interrupts/StatewireTypedInterruptCard.d.ts +31 -0
  282. package/dist/chat/typed-interrupts/StatewireTypedInterruptCard.js +31 -0
  283. package/dist/chat/typed-interrupts/StatewireTypedInterruptCard.js.map +1 -0
  284. package/dist/chat/typed-interrupts/approval-cards.cjs +250 -0
  285. package/dist/chat/typed-interrupts/approval-cards.cjs.map +1 -0
  286. package/dist/chat/typed-interrupts/approval-cards.d.ts +22 -0
  287. package/dist/chat/typed-interrupts/approval-cards.js +250 -0
  288. package/dist/chat/typed-interrupts/approval-cards.js.map +1 -0
  289. package/dist/chat/typed-interrupts/form-cards.cjs +289 -0
  290. package/dist/chat/typed-interrupts/form-cards.cjs.map +1 -0
  291. package/dist/chat/typed-interrupts/form-cards.d.ts +6 -0
  292. package/dist/chat/typed-interrupts/form-cards.js +289 -0
  293. package/dist/chat/typed-interrupts/form-cards.js.map +1 -0
  294. package/dist/chat/typed-interrupts/interrupt-card-shell.cjs +182 -0
  295. package/dist/chat/typed-interrupts/interrupt-card-shell.cjs.map +1 -0
  296. package/dist/chat/typed-interrupts/interrupt-card-shell.d.ts +47 -0
  297. package/dist/chat/typed-interrupts/interrupt-card-shell.js +182 -0
  298. package/dist/chat/typed-interrupts/interrupt-card-shell.js.map +1 -0
  299. package/dist/chat/typed-interrupts/json-schema-form.cjs +388 -0
  300. package/dist/chat/typed-interrupts/json-schema-form.cjs.map +1 -0
  301. package/dist/chat/typed-interrupts/json-schema-form.d.ts +33 -0
  302. package/dist/chat/typed-interrupts/json-schema-form.js +388 -0
  303. package/dist/chat/typed-interrupts/json-schema-form.js.map +1 -0
  304. package/dist/chat/typed-interrupts/questionnaire-card.cjs +449 -0
  305. package/dist/chat/typed-interrupts/questionnaire-card.cjs.map +1 -0
  306. package/dist/chat/typed-interrupts/questionnaire-card.d.ts +20 -0
  307. package/dist/chat/typed-interrupts/questionnaire-card.js +449 -0
  308. package/dist/chat/typed-interrupts/questionnaire-card.js.map +1 -0
  309. package/dist/chat/typed-interrupts/request-file-card.cjs +159 -0
  310. package/dist/chat/typed-interrupts/request-file-card.cjs.map +1 -0
  311. package/dist/chat/typed-interrupts/request-file-card.d.ts +2 -0
  312. package/dist/chat/typed-interrupts/request-file-card.js +159 -0
  313. package/dist/chat/typed-interrupts/request-file-card.js.map +1 -0
  314. package/dist/chat/typed-interrupts/toolkit-selection-card.cjs +189 -0
  315. package/dist/chat/typed-interrupts/toolkit-selection-card.cjs.map +1 -0
  316. package/dist/chat/typed-interrupts/toolkit-selection-card.d.ts +23 -0
  317. package/dist/chat/typed-interrupts/toolkit-selection-card.js +189 -0
  318. package/dist/chat/typed-interrupts/toolkit-selection-card.js.map +1 -0
  319. package/dist/chat/typed-interrupts/typed-interrupt-body.cjs +26 -0
  320. package/dist/chat/typed-interrupts/typed-interrupt-body.cjs.map +1 -0
  321. package/dist/chat/typed-interrupts/typed-interrupt-body.d.ts +3 -0
  322. package/dist/chat/typed-interrupts/typed-interrupt-body.js +26 -0
  323. package/dist/chat/typed-interrupts/typed-interrupt-body.js.map +1 -0
  324. package/dist/chat/typed-interrupts/typed-interrupt-graphql.cjs +105 -0
  325. package/dist/chat/typed-interrupts/typed-interrupt-graphql.cjs.map +1 -0
  326. package/dist/chat/typed-interrupts/typed-interrupt-graphql.d.ts +29 -0
  327. package/dist/chat/typed-interrupts/typed-interrupt-graphql.js +105 -0
  328. package/dist/chat/typed-interrupts/typed-interrupt-graphql.js.map +1 -0
  329. package/dist/chat/typed-interrupts/typed-interrupt-notice.cjs +70 -0
  330. package/dist/chat/typed-interrupts/typed-interrupt-notice.cjs.map +1 -0
  331. package/dist/chat/typed-interrupts/typed-interrupt-notice.d.ts +45 -0
  332. package/dist/chat/typed-interrupts/typed-interrupt-notice.js +70 -0
  333. package/dist/chat/typed-interrupts/typed-interrupt-notice.js.map +1 -0
  334. package/dist/chat/typed-interrupts/typed-interrupt-panel.cjs +76 -0
  335. package/dist/chat/typed-interrupts/typed-interrupt-panel.cjs.map +1 -0
  336. package/dist/chat/typed-interrupts/typed-interrupt-panel.d.ts +11 -0
  337. package/dist/chat/typed-interrupts/typed-interrupt-panel.js +76 -0
  338. package/dist/chat/typed-interrupts/typed-interrupt-panel.js.map +1 -0
  339. package/dist/chat/typed-interrupts/typed-interrupt-types.d.ts +46 -0
  340. package/dist/chat/typed-interrupts/use-interrupt-draft.cjs +106 -0
  341. package/dist/chat/typed-interrupts/use-interrupt-draft.cjs.map +1 -0
  342. package/dist/chat/typed-interrupts/use-interrupt-draft.d.ts +29 -0
  343. package/dist/chat/typed-interrupts/use-interrupt-draft.js +106 -0
  344. package/dist/chat/typed-interrupts/use-interrupt-draft.js.map +1 -0
  345. package/dist/chat/typed-interrupts/use-statewire-typed-interrupt.cjs +231 -0
  346. package/dist/chat/typed-interrupts/use-statewire-typed-interrupt.cjs.map +1 -0
  347. package/dist/chat/typed-interrupts/use-statewire-typed-interrupt.d.ts +66 -0
  348. package/dist/chat/typed-interrupts/use-statewire-typed-interrupt.js +231 -0
  349. package/dist/chat/typed-interrupts/use-statewire-typed-interrupt.js.map +1 -0
  350. package/dist/chat-ui/composer/composer-named-agents.cjs +13 -0
  351. package/dist/chat-ui/composer/composer-named-agents.cjs.map +1 -0
  352. package/dist/chat-ui/composer/composer-named-agents.d.ts +20 -0
  353. package/dist/chat-ui/composer/composer-named-agents.js +13 -0
  354. package/dist/chat-ui/composer/composer-named-agents.js.map +1 -0
  355. package/dist/chat-ui/composer/slash-command-menu.cjs +143 -0
  356. package/dist/chat-ui/composer/slash-command-menu.cjs.map +1 -0
  357. package/dist/chat-ui/composer/slash-command-menu.d.ts +19 -0
  358. package/dist/chat-ui/composer/slash-command-menu.js +143 -0
  359. package/dist/chat-ui/composer/slash-command-menu.js.map +1 -0
  360. package/dist/chat-ui/composer/slash-commands-extension.cjs +51 -0
  361. package/dist/chat-ui/composer/slash-commands-extension.cjs.map +1 -0
  362. package/dist/chat-ui/composer/slash-commands-extension.d.ts +39 -0
  363. package/dist/chat-ui/composer/slash-commands-extension.js +51 -0
  364. package/dist/chat-ui/composer/slash-commands-extension.js.map +1 -0
  365. package/dist/chat-ui/composer/slash-commands.cjs +74 -0
  366. package/dist/chat-ui/composer/slash-commands.cjs.map +1 -0
  367. package/dist/chat-ui/composer/slash-commands.d.ts +82 -0
  368. package/dist/chat-ui/composer/slash-commands.js +74 -0
  369. package/dist/chat-ui/composer/slash-commands.js.map +1 -0
  370. package/dist/chat-ui/composer/tiptap-composer.cjs +135 -9
  371. package/dist/chat-ui/composer/tiptap-composer.cjs.map +1 -1
  372. package/dist/chat-ui/composer/tiptap-composer.d.ts +61 -2
  373. package/dist/chat-ui/composer/tiptap-composer.js +135 -9
  374. package/dist/chat-ui/composer/tiptap-composer.js.map +1 -1
  375. package/dist/chat-ui/index.cjs +5 -0
  376. package/dist/chat-ui/index.cjs.map +1 -1
  377. package/dist/chat-ui/index.d.ts +4 -2
  378. package/dist/chat-ui/index.js +5 -0
  379. package/dist/chat-ui/index.js.map +1 -1
  380. package/dist/chat-ui/mentions/mention-chip.cjs +10 -4
  381. package/dist/chat-ui/mentions/mention-chip.cjs.map +1 -1
  382. package/dist/chat-ui/mentions/mention-chip.js +11 -5
  383. package/dist/chat-ui/mentions/mention-chip.js.map +1 -1
  384. package/dist/chat-ui/mentions/mention-extension.cjs +8 -1
  385. package/dist/chat-ui/mentions/mention-extension.cjs.map +1 -1
  386. package/dist/chat-ui/mentions/mention-extension.js +8 -1
  387. package/dist/chat-ui/mentions/mention-extension.js.map +1 -1
  388. package/dist/chat-ui/mentions/suggestions/components/get-scope-name.cjs +1 -0
  389. package/dist/chat-ui/mentions/suggestions/components/get-scope-name.cjs.map +1 -1
  390. package/dist/chat-ui/mentions/suggestions/components/get-scope-name.js +1 -0
  391. package/dist/chat-ui/mentions/suggestions/components/get-scope-name.js.map +1 -1
  392. package/dist/chat-ui/mentions/suggestions/components/mention-icon.cjs +20 -2
  393. package/dist/chat-ui/mentions/suggestions/components/mention-icon.cjs.map +1 -1
  394. package/dist/chat-ui/mentions/suggestions/components/mention-icon.d.ts +10 -1
  395. package/dist/chat-ui/mentions/suggestions/components/mention-icon.js +22 -4
  396. package/dist/chat-ui/mentions/suggestions/components/mention-icon.js.map +1 -1
  397. package/dist/chat-ui/mentions/suggestions/components/menu-item.cjs +1 -1
  398. package/dist/chat-ui/mentions/suggestions/components/menu-item.cjs.map +1 -1
  399. package/dist/chat-ui/mentions/suggestions/components/menu-item.js +1 -1
  400. package/dist/chat-ui/mentions/suggestions/components/menu-item.js.map +1 -1
  401. package/dist/chat-ui/mentions/suggestions/data/api-client.cjs +45 -0
  402. package/dist/chat-ui/mentions/suggestions/data/api-client.cjs.map +1 -1
  403. package/dist/chat-ui/mentions/suggestions/data/api-client.d.ts +48 -0
  404. package/dist/chat-ui/mentions/suggestions/data/api-client.js +45 -0
  405. package/dist/chat-ui/mentions/suggestions/data/api-client.js.map +1 -1
  406. package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icon-names.generated.cjs +89 -0
  407. package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icon-names.generated.cjs.map +1 -0
  408. package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icon-names.generated.d.ts +8 -0
  409. package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icon-names.generated.js +89 -0
  410. package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icon-names.generated.js.map +1 -0
  411. package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icons.cjs +140 -116
  412. package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icons.cjs.map +1 -1
  413. package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icons.d.ts +46 -12
  414. package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icons.js +141 -117
  415. package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icons.js.map +1 -1
  416. package/dist/chat-ui/mentions/suggestions/data/sources/index.cjs +272 -25
  417. package/dist/chat-ui/mentions/suggestions/data/sources/index.cjs.map +1 -1
  418. package/dist/chat-ui/mentions/suggestions/data/sources/index.d.ts +88 -10
  419. package/dist/chat-ui/mentions/suggestions/data/sources/index.js +274 -27
  420. package/dist/chat-ui/mentions/suggestions/data/sources/index.js.map +1 -1
  421. package/dist/chat-ui/mentions/suggestions/data/types.cjs.map +1 -1
  422. package/dist/chat-ui/mentions/suggestions/data/types.d.ts +27 -1
  423. package/dist/chat-ui/mentions/suggestions/data/types.js.map +1 -1
  424. package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.cjs +56 -5
  425. package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.cjs.map +1 -1
  426. package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.d.ts +26 -6
  427. package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.js +57 -6
  428. package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.js.map +1 -1
  429. package/dist/chat-ui/mentions/suggestions/mention-suggestions.extension.cjs +34 -17
  430. package/dist/chat-ui/mentions/suggestions/mention-suggestions.extension.cjs.map +1 -1
  431. package/dist/chat-ui/mentions/suggestions/mention-suggestions.extension.d.ts +19 -1
  432. package/dist/chat-ui/mentions/suggestions/mention-suggestions.extension.js +35 -18
  433. package/dist/chat-ui/mentions/suggestions/mention-suggestions.extension.js.map +1 -1
  434. package/dist/chat-ui/mentions/use-asset-icon-app-url.cjs +12 -0
  435. package/dist/chat-ui/mentions/use-asset-icon-app-url.cjs.map +1 -0
  436. package/dist/chat-ui/mentions/use-asset-icon-app-url.d.ts +8 -0
  437. package/dist/chat-ui/mentions/use-asset-icon-app-url.js +12 -0
  438. package/dist/chat-ui/mentions/use-asset-icon-app-url.js.map +1 -0
  439. package/dist/chat-ui/statewire.d.ts +1 -1
  440. package/dist/chat-ui/thread/statewire-history-edge.cjs +15 -0
  441. package/dist/chat-ui/thread/statewire-history-edge.cjs.map +1 -1
  442. package/dist/chat-ui/thread/statewire-history-edge.d.ts +4 -1
  443. package/dist/chat-ui/thread/statewire-history-edge.js +15 -0
  444. package/dist/chat-ui/thread/statewire-history-edge.js.map +1 -1
  445. package/dist/collab/client.cjs +41 -6
  446. package/dist/collab/client.cjs.map +1 -1
  447. package/dist/collab/client.d.ts +38 -7
  448. package/dist/collab/client.js +41 -6
  449. package/dist/collab/client.js.map +1 -1
  450. package/dist/composer/ComposerAttachedReferences.cjs +119 -0
  451. package/dist/composer/ComposerAttachedReferences.cjs.map +1 -0
  452. package/dist/composer/ComposerAttachedReferences.d.ts +26 -0
  453. package/dist/composer/ComposerAttachedReferences.js +119 -0
  454. package/dist/composer/ComposerAttachedReferences.js.map +1 -0
  455. package/dist/composer/ComposerNamedAgents.cjs +63 -0
  456. package/dist/composer/ComposerNamedAgents.cjs.map +1 -0
  457. package/dist/composer/ComposerNamedAgents.d.ts +16 -0
  458. package/dist/composer/ComposerNamedAgents.js +63 -0
  459. package/dist/composer/ComposerNamedAgents.js.map +1 -0
  460. package/dist/composer/attached-references.cjs +159 -0
  461. package/dist/composer/attached-references.cjs.map +1 -0
  462. package/dist/composer/attached-references.d.ts +86 -0
  463. package/dist/composer/attached-references.js +159 -0
  464. package/dist/composer/attached-references.js.map +1 -0
  465. package/dist/composer/build-composed-message.cjs +14 -7
  466. package/dist/composer/build-composed-message.cjs.map +1 -1
  467. package/dist/composer/build-composed-message.d.ts +6 -1
  468. package/dist/composer/build-composed-message.js +14 -7
  469. package/dist/composer/build-composed-message.js.map +1 -1
  470. package/dist/composer/composer-handoff.cjs +6 -2
  471. package/dist/composer/composer-handoff.cjs.map +1 -1
  472. package/dist/composer/composer-handoff.d.ts +7 -1
  473. package/dist/composer/composer-handoff.js +6 -2
  474. package/dist/composer/composer-handoff.js.map +1 -1
  475. package/dist/composer/folder-upload.cjs +149 -0
  476. package/dist/composer/folder-upload.cjs.map +1 -0
  477. package/dist/composer/folder-upload.d.ts +79 -0
  478. package/dist/composer/folder-upload.js +149 -0
  479. package/dist/composer/folder-upload.js.map +1 -0
  480. package/dist/composer/index.d.ts +1 -1
  481. package/dist/composer/staged-message-metadata.cjs +12 -0
  482. package/dist/composer/staged-message-metadata.cjs.map +1 -0
  483. package/dist/composer/staged-message-metadata.d.ts +15 -0
  484. package/dist/composer/staged-message-metadata.js +12 -0
  485. package/dist/composer/staged-message-metadata.js.map +1 -0
  486. package/dist/composer/useAttachToChat.cjs +35 -0
  487. package/dist/composer/useAttachToChat.cjs.map +1 -0
  488. package/dist/composer/useAttachToChat.d.ts +54 -0
  489. package/dist/composer/useAttachToChat.js +35 -0
  490. package/dist/composer/useAttachToChat.js.map +1 -0
  491. package/dist/composer/useAttachedReferencesComposerProps.cjs +19 -0
  492. package/dist/composer/useAttachedReferencesComposerProps.cjs.map +1 -0
  493. package/dist/composer/useAttachedReferencesComposerProps.d.ts +12 -0
  494. package/dist/composer/useAttachedReferencesComposerProps.js +19 -0
  495. package/dist/composer/useAttachedReferencesComposerProps.js.map +1 -0
  496. package/dist/composer/useFileUpload.cjs +95 -7
  497. package/dist/composer/useFileUpload.cjs.map +1 -1
  498. package/dist/composer/useFileUpload.d.ts +21 -2
  499. package/dist/composer/useFileUpload.js +95 -7
  500. package/dist/composer/useFileUpload.js.map +1 -1
  501. package/dist/data/athena-api-error.cjs +125 -0
  502. package/dist/data/athena-api-error.cjs.map +1 -0
  503. package/dist/data/athena-api-error.d.ts +96 -0
  504. package/dist/data/athena-api-error.js +125 -0
  505. package/dist/data/athena-api-error.js.map +1 -0
  506. package/dist/data/athena-data-client.cjs +106 -0
  507. package/dist/data/athena-data-client.cjs.map +1 -0
  508. package/dist/data/athena-data-client.d.ts +74 -0
  509. package/dist/data/athena-data-client.js +106 -0
  510. package/dist/data/athena-data-client.js.map +1 -0
  511. package/dist/data/athena-member.cjs +93 -0
  512. package/dist/data/athena-member.cjs.map +1 -0
  513. package/dist/data/athena-member.d.ts +125 -0
  514. package/dist/data/athena-member.js +93 -0
  515. package/dist/data/athena-member.js.map +1 -0
  516. package/dist/data/athena-request.cjs +460 -0
  517. package/dist/data/athena-request.cjs.map +1 -0
  518. package/dist/data/athena-request.d.ts +120 -0
  519. package/dist/data/athena-request.js +460 -0
  520. package/dist/data/athena-request.js.map +1 -0
  521. package/dist/data/use-athena-fetch.cjs +14 -0
  522. package/dist/data/use-athena-fetch.cjs.map +1 -0
  523. package/dist/data/use-athena-fetch.d.ts +19 -0
  524. package/dist/data/use-athena-fetch.js +14 -0
  525. package/dist/data/use-athena-fetch.js.map +1 -0
  526. package/dist/data/use-athena-graphql.cjs +66 -0
  527. package/dist/data/use-athena-graphql.cjs.map +1 -0
  528. package/dist/data/use-athena-graphql.d.ts +56 -0
  529. package/dist/data/use-athena-graphql.js +66 -0
  530. package/dist/data/use-athena-graphql.js.map +1 -0
  531. package/dist/data/use-athena-rest.cjs +33 -0
  532. package/dist/data/use-athena-rest.cjs.map +1 -0
  533. package/dist/data/use-athena-rest.d.ts +21 -0
  534. package/dist/data/use-athena-rest.js +33 -0
  535. package/dist/data/use-athena-rest.js.map +1 -0
  536. package/dist/data/use-semantic-query.cjs +44 -0
  537. package/dist/data/use-semantic-query.cjs.map +1 -0
  538. package/dist/data/use-semantic-query.d.ts +92 -0
  539. package/dist/data/use-semantic-query.js +44 -0
  540. package/dist/data/use-semantic-query.js.map +1 -0
  541. package/dist/diagnostics/athena-diagnostics.cjs.map +1 -1
  542. package/dist/diagnostics/athena-diagnostics.d.ts +5 -1
  543. package/dist/diagnostics/athena-diagnostics.js.map +1 -1
  544. package/dist/diagnostics/errors.cjs +7 -0
  545. package/dist/diagnostics/errors.cjs.map +1 -1
  546. package/dist/diagnostics/errors.d.ts +7 -0
  547. package/dist/diagnostics/errors.js +7 -0
  548. package/dist/diagnostics/errors.js.map +1 -1
  549. package/dist/index.cjs +155 -11
  550. package/dist/index.cjs.map +1 -1
  551. package/dist/index.d.ts +72 -13
  552. package/dist/index.js +148 -4
  553. package/dist/index.js.map +1 -1
  554. package/dist/keryx-http/src/initial-sync.cjs +64 -16
  555. package/dist/keryx-http/src/initial-sync.cjs.map +1 -1
  556. package/dist/keryx-http/src/initial-sync.d.ts +31 -1
  557. package/dist/keryx-http/src/initial-sync.js +64 -16
  558. package/dist/keryx-http/src/initial-sync.js.map +1 -1
  559. package/dist/keryx-http/src/own-awareness.cjs +20 -0
  560. package/dist/keryx-http/src/own-awareness.cjs.map +1 -0
  561. package/dist/keryx-http/src/own-awareness.d.ts +50 -0
  562. package/dist/keryx-http/src/own-awareness.js +20 -0
  563. package/dist/keryx-http/src/own-awareness.js.map +1 -0
  564. package/dist/keryx-http/src/update-attributions.cjs +26 -1
  565. package/dist/keryx-http/src/update-attributions.cjs.map +1 -1
  566. package/dist/keryx-http/src/update-attributions.d.ts +10 -1
  567. package/dist/keryx-http/src/update-attributions.js +26 -1
  568. package/dist/keryx-http/src/update-attributions.js.map +1 -1
  569. package/dist/offline/chat-outbox.cjs +262 -26
  570. package/dist/offline/chat-outbox.cjs.map +1 -1
  571. package/dist/offline/chat-outbox.d.ts +90 -12
  572. package/dist/offline/chat-outbox.js +263 -27
  573. package/dist/offline/chat-outbox.js.map +1 -1
  574. package/dist/provider/AthenaProvider.cjs +60 -22
  575. package/dist/provider/AthenaProvider.cjs.map +1 -1
  576. package/dist/provider/AthenaProvider.d.ts +24 -8
  577. package/dist/provider/AthenaProvider.js +61 -23
  578. package/dist/provider/AthenaProvider.js.map +1 -1
  579. package/dist/react/package.json.cjs +1 -1
  580. package/dist/react/package.json.js +1 -1
  581. package/dist/references/src/anchors/parse.cjs +11 -1
  582. package/dist/references/src/anchors/parse.cjs.map +1 -1
  583. package/dist/references/src/anchors/parse.js +11 -1
  584. package/dist/references/src/anchors/parse.js.map +1 -1
  585. package/dist/references/src/anchors/schemas.d.ts +1 -0
  586. package/dist/references/src/anchors/serialize.cjs +1 -0
  587. package/dist/references/src/anchors/serialize.cjs.map +1 -1
  588. package/dist/references/src/anchors/serialize.js +1 -0
  589. package/dist/references/src/anchors/serialize.js.map +1 -1
  590. package/dist/references/src/anchors/types.cjs +5 -0
  591. package/dist/references/src/anchors/types.cjs.map +1 -1
  592. package/dist/references/src/anchors/types.d.ts +9 -0
  593. package/dist/references/src/anchors/types.js +5 -0
  594. package/dist/references/src/anchors/types.js.map +1 -1
  595. package/dist/references/src/attachable.cjs +149 -0
  596. package/dist/references/src/attachable.cjs.map +1 -0
  597. package/dist/references/src/attachable.d.ts +87 -0
  598. package/dist/references/src/attachable.js +149 -0
  599. package/dist/references/src/attachable.js.map +1 -0
  600. package/dist/references/src/schemas.d.ts +2 -0
  601. package/dist/runtime/StatewirePlanModeLaneSync.cjs +93 -0
  602. package/dist/runtime/StatewirePlanModeLaneSync.cjs.map +1 -0
  603. package/dist/runtime/StatewirePlanModeLaneSync.d.ts +34 -0
  604. package/dist/runtime/StatewirePlanModeLaneSync.js +93 -0
  605. package/dist/runtime/StatewirePlanModeLaneSync.js.map +1 -0
  606. package/dist/runtime/StatewireThreadConfigLaneSync.cjs +2 -0
  607. package/dist/runtime/StatewireThreadConfigLaneSync.cjs.map +1 -1
  608. package/dist/runtime/StatewireThreadConfigLaneSync.d.ts +4 -0
  609. package/dist/runtime/StatewireThreadConfigLaneSync.js +2 -0
  610. package/dist/runtime/StatewireThreadConfigLaneSync.js.map +1 -1
  611. package/dist/runtime/statewire-plan-mode.cjs +71 -0
  612. package/dist/runtime/statewire-plan-mode.cjs.map +1 -0
  613. package/dist/runtime/statewire-plan-mode.d.ts +88 -0
  614. package/dist/runtime/statewire-plan-mode.js +71 -0
  615. package/dist/runtime/statewire-plan-mode.js.map +1 -0
  616. package/dist/runtime/statewire-run-config.cjs +3 -1
  617. package/dist/runtime/statewire-run-config.cjs.map +1 -1
  618. package/dist/runtime/statewire-run-config.d.ts +7 -0
  619. package/dist/runtime/statewire-run-config.js +3 -1
  620. package/dist/runtime/statewire-run-config.js.map +1 -1
  621. package/dist/runtime/statewire-session-key.cjs +11 -5
  622. package/dist/runtime/statewire-session-key.cjs.map +1 -1
  623. package/dist/runtime/statewire-session-key.d.ts +22 -10
  624. package/dist/runtime/statewire-session-key.js +11 -5
  625. package/dist/runtime/statewire-session-key.js.map +1 -1
  626. package/dist/runtime/useAthenaStatewireRuntime.cjs +64 -9
  627. package/dist/runtime/useAthenaStatewireRuntime.cjs.map +1 -1
  628. package/dist/runtime/useAthenaStatewireRuntime.d.ts +26 -10
  629. package/dist/runtime/useAthenaStatewireRuntime.js +66 -11
  630. package/dist/runtime/useAthenaStatewireRuntime.js.map +1 -1
  631. package/dist/search/useAthenaAssets.cjs +394 -0
  632. package/dist/search/useAthenaAssets.cjs.map +1 -0
  633. package/dist/search/useAthenaAssets.d.ts +186 -0
  634. package/dist/search/useAthenaAssets.js +394 -0
  635. package/dist/search/useAthenaAssets.js.map +1 -0
  636. package/dist/sheet-range/index.cjs +4 -0
  637. package/dist/sheet-range/index.cjs.map +1 -1
  638. package/dist/sheet-range/index.d.ts +4 -2
  639. package/dist/sheet-range/index.js +4 -0
  640. package/dist/sheet-range/index.js.map +1 -1
  641. package/dist/sheet-range/query-range.cjs +102 -0
  642. package/dist/sheet-range/query-range.cjs.map +1 -0
  643. package/dist/sheet-range/query-range.d.ts +46 -0
  644. package/dist/sheet-range/query-range.js +102 -0
  645. package/dist/sheet-range/query-range.js.map +1 -0
  646. package/dist/styles.css +1 -1
  647. package/dist/subagents/index.cjs +49 -0
  648. package/dist/subagents/index.cjs.map +1 -0
  649. package/dist/subagents/index.d.ts +16 -0
  650. package/dist/subagents/index.js +49 -0
  651. package/dist/subagents/index.js.map +1 -0
  652. package/dist/subagents/lane-follow.cjs +19 -0
  653. package/dist/subagents/lane-follow.cjs.map +1 -0
  654. package/dist/subagents/lane-follow.d.ts +9 -0
  655. package/dist/subagents/lane-follow.js +19 -0
  656. package/dist/subagents/lane-follow.js.map +1 -0
  657. package/dist/subagents/lane-model.cjs +178 -0
  658. package/dist/subagents/lane-model.cjs.map +1 -0
  659. package/dist/subagents/lane-model.d.ts +140 -0
  660. package/dist/subagents/lane-model.js +178 -0
  661. package/dist/subagents/lane-model.js.map +1 -0
  662. package/dist/subagents/lane-parts.cjs +517 -0
  663. package/dist/subagents/lane-parts.cjs.map +1 -0
  664. package/dist/subagents/lane-parts.d.ts +130 -0
  665. package/dist/subagents/lane-parts.js +517 -0
  666. package/dist/subagents/lane-parts.js.map +1 -0
  667. package/dist/subagents/subagent-lane-group.cjs +215 -0
  668. package/dist/subagents/subagent-lane-group.cjs.map +1 -0
  669. package/dist/subagents/subagent-lane-group.d.ts +67 -0
  670. package/dist/subagents/subagent-lane-group.js +215 -0
  671. package/dist/subagents/subagent-lane-group.js.map +1 -0
  672. package/dist/subagents/subagent-transcript-drawer.cjs +431 -0
  673. package/dist/subagents/subagent-transcript-drawer.cjs.map +1 -0
  674. package/dist/subagents/subagent-transcript-drawer.d.ts +78 -0
  675. package/dist/subagents/subagent-transcript-drawer.js +431 -0
  676. package/dist/subagents/subagent-transcript-drawer.js.map +1 -0
  677. package/dist/subagents/task-subagent-group.cjs +115 -0
  678. package/dist/subagents/task-subagent-group.cjs.map +1 -0
  679. package/dist/subagents/task-subagent-group.d.ts +36 -0
  680. package/dist/subagents/task-subagent-group.js +115 -0
  681. package/dist/subagents/task-subagent-group.js.map +1 -0
  682. package/dist/subagents/use-omitted-images-in-view.cjs +68 -0
  683. package/dist/subagents/use-omitted-images-in-view.cjs.map +1 -0
  684. package/dist/subagents/use-omitted-images-in-view.d.ts +21 -0
  685. package/dist/subagents/use-omitted-images-in-view.js +68 -0
  686. package/dist/subagents/use-omitted-images-in-view.js.map +1 -0
  687. package/dist/threads/Inbox.cjs +2 -2
  688. package/dist/threads/Inbox.cjs.map +1 -1
  689. package/dist/threads/SessionList.cjs +6 -6
  690. package/dist/threads/SessionList.cjs.map +1 -1
  691. package/dist/threads/SessionsPage.cjs +13 -7
  692. package/dist/threads/SessionsPage.cjs.map +1 -1
  693. package/dist/threads/SessionsPage.d.ts +10 -1
  694. package/dist/threads/SessionsPage.js +9 -3
  695. package/dist/threads/SessionsPage.js.map +1 -1
  696. package/dist/threads/session-list-model.cjs.map +1 -1
  697. package/dist/threads/session-list-model.d.ts +2 -1
  698. package/dist/threads/session-list-model.js.map +1 -1
  699. package/dist/threads/session-row-parts.cjs +3 -3
  700. package/dist/threads/session-row-parts.cjs.map +1 -1
  701. package/dist/threads/sessions-page-model.cjs +13 -5
  702. package/dist/threads/sessions-page-model.cjs.map +1 -1
  703. package/dist/threads/sessions-page-model.d.ts +7 -0
  704. package/dist/threads/sessions-page-model.js +11 -3
  705. package/dist/threads/sessions-page-model.js.map +1 -1
  706. package/dist/threads/sessions-page-storage.cjs +8 -8
  707. package/dist/threads/sessions-page-storage.cjs.map +1 -1
  708. package/dist/threads/sessions-page-storage.d.ts +5 -1
  709. package/dist/threads/sessions-page-storage.js +8 -8
  710. package/dist/threads/sessions-page-storage.js.map +1 -1
  711. package/dist/threads/statewire-thread-list.cjs +14 -2
  712. package/dist/threads/statewire-thread-list.cjs.map +1 -1
  713. package/dist/threads/statewire-thread-list.d.ts +11 -2
  714. package/dist/threads/statewire-thread-list.js +14 -2
  715. package/dist/threads/statewire-thread-list.js.map +1 -1
  716. package/dist/threads/use-athena-sessions.cjs +1 -0
  717. package/dist/threads/use-athena-sessions.cjs.map +1 -1
  718. package/dist/threads/use-athena-sessions.d.ts +7 -0
  719. package/dist/threads/use-athena-sessions.js +1 -0
  720. package/dist/threads/use-athena-sessions.js.map +1 -1
  721. package/dist/threads/use-athena-thread-agent.cjs +31 -0
  722. package/dist/threads/use-athena-thread-agent.cjs.map +1 -0
  723. package/dist/threads/use-athena-thread-agent.d.ts +38 -0
  724. package/dist/threads/use-athena-thread-agent.js +31 -0
  725. package/dist/threads/use-athena-thread-agent.js.map +1 -0
  726. package/dist/threads/use-athena-thread-plan-mode.cjs +18 -0
  727. package/dist/threads/use-athena-thread-plan-mode.cjs.map +1 -0
  728. package/dist/threads/use-athena-thread-plan-mode.d.ts +18 -0
  729. package/dist/threads/use-athena-thread-plan-mode.js +18 -0
  730. package/dist/threads/use-athena-thread-plan-mode.js.map +1 -0
  731. package/dist/threads/use-rest-conversation-history.d.ts +1 -0
  732. package/dist/tools/agent-creations.cjs +97 -0
  733. package/dist/tools/agent-creations.cjs.map +1 -0
  734. package/dist/tools/agent-creations.d.ts +38 -0
  735. package/dist/tools/agent-creations.js +97 -0
  736. package/dist/tools/agent-creations.js.map +1 -0
  737. package/dist/tools/agent-highlights.cjs +100 -0
  738. package/dist/tools/agent-highlights.cjs.map +1 -0
  739. package/dist/tools/agent-highlights.d.ts +57 -0
  740. package/dist/tools/agent-highlights.js +100 -0
  741. package/dist/tools/agent-highlights.js.map +1 -0
  742. package/dist/tools/append-document-tool-ui.cjs +1 -0
  743. package/dist/tools/append-document-tool-ui.cjs.map +1 -1
  744. package/dist/tools/append-document-tool-ui.d.ts +7 -0
  745. package/dist/tools/append-document-tool-ui.js +2 -1
  746. package/dist/tools/append-document-tool-ui.js.map +1 -1
  747. package/dist/tools/auto-open-tools.cjs +144 -71
  748. package/dist/tools/auto-open-tools.cjs.map +1 -1
  749. package/dist/tools/auto-open-tools.d.ts +131 -1
  750. package/dist/tools/auto-open-tools.js +145 -72
  751. package/dist/tools/auto-open-tools.js.map +1 -1
  752. package/dist/tools/browser-tool-uis.cjs +594 -0
  753. package/dist/tools/browser-tool-uis.cjs.map +1 -0
  754. package/dist/tools/browser-tool-uis.d.ts +8 -0
  755. package/dist/tools/browser-tool-uis.js +594 -0
  756. package/dist/tools/browser-tool-uis.js.map +1 -0
  757. package/dist/tools/computer-asset-tool-uis.cjs +313 -0
  758. package/dist/tools/computer-asset-tool-uis.cjs.map +1 -0
  759. package/dist/tools/computer-asset-tool-uis.d.ts +5 -0
  760. package/dist/tools/computer-asset-tool-uis.js +313 -0
  761. package/dist/tools/computer-asset-tool-uis.js.map +1 -0
  762. package/dist/tools/document-edit-tool-uis.cjs +218 -0
  763. package/dist/tools/document-edit-tool-uis.cjs.map +1 -0
  764. package/dist/tools/document-edit-tool-uis.d.ts +40 -0
  765. package/dist/tools/document-edit-tool-uis.js +218 -0
  766. package/dist/tools/document-edit-tool-uis.js.map +1 -0
  767. package/dist/tools/drive-tool-uis.cjs +429 -0
  768. package/dist/tools/drive-tool-uis.cjs.map +1 -0
  769. package/dist/tools/drive-tool-uis.d.ts +121 -0
  770. package/dist/tools/drive-tool-uis.js +429 -0
  771. package/dist/tools/drive-tool-uis.js.map +1 -0
  772. package/dist/tools/email-calendar-tool-uis.cjs +789 -0
  773. package/dist/tools/email-calendar-tool-uis.cjs.map +1 -0
  774. package/dist/tools/email-calendar-tool-uis.d.ts +129 -0
  775. package/dist/tools/email-calendar-tool-uis.js +789 -0
  776. package/dist/tools/email-calendar-tool-uis.js.map +1 -0
  777. package/dist/tools/ontology-tool-uis.cjs +83 -0
  778. package/dist/tools/ontology-tool-uis.cjs.map +1 -0
  779. package/dist/tools/ontology-tool-uis.d.ts +9 -0
  780. package/dist/tools/ontology-tool-uis.js +83 -0
  781. package/dist/tools/ontology-tool-uis.js.map +1 -0
  782. package/dist/tools/orchestration-tool-uis.cjs +586 -0
  783. package/dist/tools/orchestration-tool-uis.cjs.map +1 -0
  784. package/dist/tools/orchestration-tool-uis.d.ts +141 -0
  785. package/dist/tools/orchestration-tool-uis.js +586 -0
  786. package/dist/tools/orchestration-tool-uis.js.map +1 -0
  787. package/dist/tools/presentation-edit-tool-uis.cjs +516 -0
  788. package/dist/tools/presentation-edit-tool-uis.cjs.map +1 -0
  789. package/dist/tools/presentation-edit-tool-uis.d.ts +73 -0
  790. package/dist/tools/presentation-edit-tool-uis.js +516 -0
  791. package/dist/tools/presentation-edit-tool-uis.js.map +1 -0
  792. package/dist/tools/project-tool-uis.cjs +213 -0
  793. package/dist/tools/project-tool-uis.cjs.map +1 -0
  794. package/dist/tools/project-tool-uis.d.ts +14 -0
  795. package/dist/tools/project-tool-uis.js +213 -0
  796. package/dist/tools/project-tool-uis.js.map +1 -0
  797. package/dist/tools/sandbox-tool-uis.cjs +491 -0
  798. package/dist/tools/sandbox-tool-uis.cjs.map +1 -0
  799. package/dist/tools/sandbox-tool-uis.d.ts +116 -0
  800. package/dist/tools/sandbox-tool-uis.js +491 -0
  801. package/dist/tools/sandbox-tool-uis.js.map +1 -0
  802. package/dist/tools/sheet-query-tool-ui.cjs +138 -0
  803. package/dist/tools/sheet-query-tool-ui.cjs.map +1 -0
  804. package/dist/tools/sheet-query-tool-ui.d.ts +15 -0
  805. package/dist/tools/sheet-query-tool-ui.js +138 -0
  806. package/dist/tools/sheet-query-tool-ui.js.map +1 -0
  807. package/dist/tools/studio-screenshot-tool-uis.cjs +262 -0
  808. package/dist/tools/studio-screenshot-tool-uis.cjs.map +1 -0
  809. package/dist/tools/studio-screenshot-tool-uis.d.ts +52 -0
  810. package/dist/tools/studio-screenshot-tool-uis.js +262 -0
  811. package/dist/tools/studio-screenshot-tool-uis.js.map +1 -0
  812. package/dist/tools/subagent-task-tool-ui.cjs +24 -475
  813. package/dist/tools/subagent-task-tool-ui.cjs.map +1 -1
  814. package/dist/tools/subagent-task-tool-ui.d.ts +19 -103
  815. package/dist/tools/subagent-task-tool-ui.js +28 -479
  816. package/dist/tools/subagent-task-tool-ui.js.map +1 -1
  817. package/dist/tools/tool-summary.cjs +36 -0
  818. package/dist/tools/tool-summary.cjs.map +1 -1
  819. package/dist/tools/tool-summary.js +36 -0
  820. package/dist/tools/tool-summary.js.map +1 -1
  821. package/dist/tools/tool-uis.cjs +181 -53
  822. package/dist/tools/tool-uis.cjs.map +1 -1
  823. package/dist/tools/tool-uis.d.ts +40 -0
  824. package/dist/tools/tool-uis.js +183 -55
  825. package/dist/tools/tool-uis.js.map +1 -1
  826. package/dist/typed-interrupts/index.cjs +15 -0
  827. package/dist/typed-interrupts/index.cjs.map +1 -0
  828. package/dist/typed-interrupts/index.d.ts +20 -0
  829. package/dist/typed-interrupts/index.js +15 -0
  830. package/dist/typed-interrupts/index.js.map +1 -0
  831. package/dist/version.cjs +4 -0
  832. package/dist/version.cjs.map +1 -1
  833. package/dist/version.d.ts +9 -0
  834. package/dist/version.js +4 -0
  835. package/dist/version.js.map +1 -1
  836. package/dist/workbench/live-desktop-api.cjs +2 -1
  837. package/dist/workbench/live-desktop-api.cjs.map +1 -1
  838. package/dist/workbench/live-desktop-api.js +2 -1
  839. package/dist/workbench/live-desktop-api.js.map +1 -1
  840. package/dist/workbench/session-workbench-panes.cjs +6 -6
  841. package/dist/workbench/session-workbench-panes.cjs.map +1 -1
  842. package/dist/workbench/session-workspace-api.cjs +7 -2
  843. package/dist/workbench/session-workspace-api.cjs.map +1 -1
  844. package/dist/workbench/session-workspace-api.d.ts +10 -0
  845. package/dist/workbench/session-workspace-api.js +7 -2
  846. package/dist/workbench/session-workspace-api.js.map +1 -1
  847. package/package.json +28 -6
  848. package/dist/agent-runtime/src/chat-outbox-store.cjs +0 -510
  849. package/dist/agent-runtime/src/chat-outbox-store.cjs.map +0 -1
  850. package/dist/agent-runtime/src/chat-outbox-store.d.ts +0 -210
  851. package/dist/agent-runtime/src/chat-outbox-store.js +0 -510
  852. package/dist/agent-runtime/src/chat-outbox-store.js.map +0 -1
@@ -20,6 +20,20 @@ export declare const INITIAL_SYNC_PARAM = "initialSync";
20
20
  export declare const INITIAL_SYNC_DIFF = "diff";
21
21
  /** The `GET /ydoc` response header with which a Keryx says it answers `?initialSync=diff`. */
22
22
  export declare const INITIAL_SYNC_CAPABILITY_HEADER = "x-keryx-initial-sync";
23
+ /**
24
+ * Which sockets of a room that opens HTTP-first ask for a diffed initial sync, while Keryx is known
25
+ * to answer it and the room holds no write Keryx has not echoed.
26
+ *
27
+ * - `every-socket` (Word documents): the socket after the room's read, every reconnect, and the
28
+ * first socket of a room opened from its local copy.
29
+ * - `after-read` (decks): only the socket that follows the room's own read. A room opened from its
30
+ * local copy, and every reconnect, get Keryx's whole document, as a room that does not open
31
+ * HTTP-first does. Keryx diffs a room that is not one compacted row against its whole merged
32
+ * document on every socket that asks (the `@y/hub` patch's `diffForClient`). On a fast link that
33
+ * costs a deck reopened from its copy more than the whole document does (the Midas smoke's
34
+ * 160-slide deck synced in 3.3 s, where the whole document took about 0.6 s).
35
+ */
36
+ export type DiffedInitialSync = 'every-socket' | 'after-read';
23
37
  /**
24
38
  * The `GET /ydoc` URL of the room a socket URL names: `wss://host/ws/<org>/<docId>` (or the
25
39
  * `/api/ws/v1/` spelling) becomes `https://host/api/ydoc/v1/<org>/<docId>?yauth=…&branch=…`. `null`
@@ -39,14 +53,30 @@ export interface RoomReadOverHttp {
39
53
  /** The decoded body's size. */
40
54
  bytes: number;
41
55
  }
56
+ /**
57
+ * How long a room's HTTP-first read may receive nothing (no answer yet, or no byte of its body)
58
+ * before the room gives it up and syncs over its socket instead: the minute every read was allowed
59
+ * in all before, so no read is given up sooner than it was.
60
+ */
61
+ export declare const HTTP_FIRST_READ_IDLE_TIMEOUT_MS = 60000;
62
+ /**
63
+ * How long a room's HTTP-first read may take in all, however steadily its bytes come. A read still
64
+ * downloading is otherwise never thrown away: the socket's whole-document sync it would fall back to
65
+ * carries the same bytes, restarted from the first one on every reconnect (a large deck on a slow
66
+ * link took 39 s to 550 s that way, `@athenaintel/decks`' `deck-open-watchdog`).
67
+ */
68
+ export declare const HTTP_FIRST_READ_TIMEOUT_MS: number;
42
69
  /**
43
70
  * Read a room over `GET /ydoc` (`url` from {@link keryxRoomReadUrl}). The runtime's `fetch` names
44
71
  * and decodes the content codings. Throws on a non-2xx answer or a body that is not a lib0 `{ doc }`.
72
+ * With `idleTimeoutMs`, a read that receives nothing for that long (no answer, or no byte of its
73
+ * body) is given up with a `TimeoutError`; one whose bytes keep coming runs as long as they do.
45
74
  */
46
- export declare function readRoomOverHttp({ url, signal, fetchImpl, }: {
75
+ export declare function readRoomOverHttp({ url, signal, fetchImpl, idleTimeoutMs, }: {
47
76
  url: string;
48
77
  signal?: AbortSignal;
49
78
  fetchImpl?: typeof fetch;
79
+ idleTimeoutMs?: number;
50
80
  }): Promise<RoomReadOverHttp>;
51
81
  /** Where {@link rememberInitialSyncSupport} keeps what it learned: `localStorage`'s surface. */
52
82
  export interface InitialSyncSupportStorage {
@@ -23,28 +23,74 @@ function keryxRoomReadUrl({
23
23
  read.searchParams.set("branch", branch);
24
24
  return read.toString();
25
25
  }
26
+ const HTTP_FIRST_READ_IDLE_TIMEOUT_MS = 6e4;
27
+ const HTTP_FIRST_READ_TIMEOUT_MS = 10 * 6e4;
28
+ async function readBody({ response, onChunk }) {
29
+ const stream = response.body;
30
+ if (stream === null) return new Uint8Array(await response.arrayBuffer());
31
+ const reader = stream.getReader();
32
+ const chunks = [];
33
+ let length = 0;
34
+ for (; ; ) {
35
+ const { done, value } = await reader.read();
36
+ if (done) break;
37
+ chunks.push(value);
38
+ length += value.byteLength;
39
+ onChunk();
40
+ }
41
+ const body = new Uint8Array(length);
42
+ let offset = 0;
43
+ for (const chunk of chunks) {
44
+ body.set(chunk, offset);
45
+ offset += chunk.byteLength;
46
+ }
47
+ return body;
48
+ }
26
49
  async function readRoomOverHttp({
27
50
  url,
28
51
  signal,
29
- fetchImpl = fetch
52
+ fetchImpl = fetch,
53
+ idleTimeoutMs
30
54
  }) {
31
55
  var _a;
32
- const response = await fetchImpl(url, { headers: { Accept: "application/octet-stream" }, signal });
33
- if (!response.ok) {
34
- await ((_a = response.body) == null ? void 0 : _a.cancel().catch(() => void 0));
35
- throw new Error(`GET /ydoc answered ${response.status}`);
36
- }
37
- const body = new Uint8Array(await response.arrayBuffer());
38
- const decoded = decoding.readAny(decoding.createDecoder(body));
39
- if (decoded === null || typeof decoded !== "object" || !(decoded.doc instanceof Uint8Array)) {
40
- throw new Error("GET /ydoc answered a body without a document");
41
- }
42
- return {
43
- // a copy: lib0 hands out a view into the body
44
- update: new Uint8Array(decoded.doc),
45
- answersSyncStep1: response.headers.get(INITIAL_SYNC_CAPABILITY_HEADER) === INITIAL_SYNC_DIFF,
46
- bytes: body.byteLength
56
+ const reading = new AbortController();
57
+ const stop = () => reading.abort(signal == null ? void 0 : signal.reason);
58
+ if (signal == null ? void 0 : signal.aborted) stop();
59
+ else signal == null ? void 0 : signal.addEventListener("abort", stop, { once: true });
60
+ let idle = null;
61
+ const stillReceiving = () => {
62
+ if (idle !== null) clearTimeout(idle);
63
+ idle = setTimeout(
64
+ () => reading.abort(new DOMException(`GET /ydoc received nothing for ${idleTimeoutMs} ms`, "TimeoutError")),
65
+ idleTimeoutMs
66
+ );
47
67
  };
68
+ stillReceiving();
69
+ try {
70
+ const response = await fetchImpl(url, { headers: { Accept: "application/octet-stream" }, signal: reading.signal });
71
+ if (!response.ok) {
72
+ await ((_a = response.body) == null ? void 0 : _a.cancel().catch(() => void 0));
73
+ throw new Error(`GET /ydoc answered ${response.status}`);
74
+ }
75
+ stillReceiving();
76
+ const body = await readBody({ response, onChunk: stillReceiving });
77
+ const decoded = decoding.readAny(decoding.createDecoder(body));
78
+ if (decoded === null || typeof decoded !== "object" || !(decoded.doc instanceof Uint8Array)) {
79
+ throw new Error("GET /ydoc answered a body without a document");
80
+ }
81
+ return {
82
+ // a copy: lib0 hands out a view into the body
83
+ update: new Uint8Array(decoded.doc),
84
+ answersSyncStep1: response.headers.get(INITIAL_SYNC_CAPABILITY_HEADER) === INITIAL_SYNC_DIFF,
85
+ bytes: body.byteLength
86
+ };
87
+ } catch (error) {
88
+ if (reading.signal.aborted && !(signal == null ? void 0 : signal.aborted)) throw reading.signal.reason;
89
+ throw error;
90
+ } finally {
91
+ if (idle !== null) clearTimeout(idle);
92
+ signal == null ? void 0 : signal.removeEventListener("abort", stop);
93
+ }
48
94
  }
49
95
  const MEMO_PREFIX = "keryx-initial-sync:";
50
96
  const INITIAL_SYNC_UNSUPPORTED_TTL_MS = 60 * 60 * 1e3;
@@ -90,6 +136,8 @@ function knownInitialSyncSupport({
90
136
  }
91
137
  }
92
138
  export {
139
+ HTTP_FIRST_READ_IDLE_TIMEOUT_MS,
140
+ HTTP_FIRST_READ_TIMEOUT_MS,
93
141
  INITIAL_SYNC_CAPABILITY_HEADER,
94
142
  INITIAL_SYNC_DIFF,
95
143
  INITIAL_SYNC_PARAM,
@@ -1 +1 @@
1
- {"version":3,"file":"initial-sync.js","sources":["../../../../keryx-http/src/initial-sync.ts"],"sourcesContent":["/**\n * Opening a big room HTTP-first (Word at scale, 2026-11-02).\n *\n * A Keryx socket's initial sync step 2 is the whole document, sent as one frame that uWS deflates on\n * Keryx's event loop: 1.4-1.8 s for a 132 MiB Word room, during which no other room on that server\n * is served, then 17 MiB on the wire. A Keryx that carries the `@y/hub` patch's diffed initial sync\n * answers a socket that connects with `?initialSync=diff` with only what the client lacks past its\n * own sync step 1, and serves `GET /ydoc` compressed (zstd, brotli or gzip, as the browser names\n * them) from a kept copy. So a client opening a big room reads it over HTTP first - decoded by the\n * browser as it downloads - applies it as the server's state, and opens its socket asking for the\n * rest: usually just the delete set.\n *\n * A Keryx says it answers that way in its `GET /ydoc` answer to a browser\n * (`X-Keryx-Initial-Sync: diff`, exposed to cross-origin readers). A Keryx without the patch says\n * nothing: its document is then not used, the socket opens as before, and the origin is remembered\n * as one that does not answer, so the next open skips the read.\n */\n\nimport * as decoding from 'lib0/decoding';\n\n/** The socket query parameter, and its one value, that ask for a diffed initial sync. */\nexport const INITIAL_SYNC_PARAM = 'initialSync';\nexport const INITIAL_SYNC_DIFF = 'diff';\n\n/** The `GET /ydoc` response header with which a Keryx says it answers `?initialSync=diff`. */\nexport const INITIAL_SYNC_CAPABILITY_HEADER = 'x-keryx-initial-sync';\n\n/**\n * The `GET /ydoc` URL of the room a socket URL names: `wss://host/ws/<org>/<docId>` (or the\n * `/api/ws/v1/` spelling) becomes `https://host/api/ydoc/v1/<org>/<docId>?yauth=…&branch=…`. `null`\n * for a URL of any other shape.\n */\nexport function keryxRoomReadUrl({\n wsUrl,\n token,\n branch,\n}: {\n wsUrl: string;\n token: string;\n branch: string;\n}): string | null {\n let parsed: URL;\n try {\n parsed = new URL(wsUrl);\n } catch {\n return null;\n }\n const scheme = parsed.protocol === 'wss:' ? 'https:' : parsed.protocol === 'ws:' ? 'http:' : null;\n if (scheme === null) return null;\n const match = /^(.*?)\\/(?:api\\/ws\\/v1|ws)\\/([^/]+)\\/([^/]+)\\/?$/.exec(parsed.pathname);\n if (match === null) return null;\n const [, prefix = '', org = '', docId = ''] = match;\n const read = new URL(`${scheme}//${parsed.host}${prefix}/api/ydoc/v1/${org}/${docId}`);\n read.searchParams.set('yauth', token);\n read.searchParams.set('branch', branch);\n return read.toString();\n}\n\n/** A room read over HTTP. */\nexport interface RoomReadOverHttp {\n /** The room's state as one update (empty for a room never written). */\n update: Uint8Array;\n /** Keryx said it answers a socket's sync step 1 (`INITIAL_SYNC_CAPABILITY_HEADER`). */\n answersSyncStep1: boolean;\n /** The decoded body's size. */\n bytes: number;\n}\n\n/**\n * Read a room over `GET /ydoc` (`url` from {@link keryxRoomReadUrl}). The runtime's `fetch` names\n * and decodes the content codings. Throws on a non-2xx answer or a body that is not a lib0 `{ doc }`.\n */\nexport async function readRoomOverHttp({\n url,\n signal,\n fetchImpl = fetch,\n}: {\n url: string;\n signal?: AbortSignal;\n fetchImpl?: typeof fetch;\n}): Promise<RoomReadOverHttp> {\n const response = await fetchImpl(url, { headers: { Accept: 'application/octet-stream' }, signal });\n if (!response.ok) {\n await response.body?.cancel().catch(() => undefined);\n throw new Error(`GET /ydoc answered ${response.status}`);\n }\n const body = new Uint8Array(await response.arrayBuffer());\n const decoded = decoding.readAny(decoding.createDecoder(body)) as { doc?: unknown } | null;\n if (decoded === null || typeof decoded !== 'object' || !(decoded.doc instanceof Uint8Array)) {\n throw new Error('GET /ydoc answered a body without a document');\n }\n return {\n // a copy: lib0 hands out a view into the body\n update: new Uint8Array(decoded.doc),\n answersSyncStep1: response.headers.get(INITIAL_SYNC_CAPABILITY_HEADER) === INITIAL_SYNC_DIFF,\n bytes: body.byteLength,\n };\n}\n\n/** Where {@link rememberInitialSyncSupport} keeps what it learned: `localStorage`'s surface. */\nexport interface InitialSyncSupportStorage {\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n}\n\nconst MEMO_PREFIX = 'keryx-initial-sync:';\n/** A Keryx that answered without the header is asked again an hour later: it may have been upgraded. */\nexport const INITIAL_SYNC_UNSUPPORTED_TTL_MS = 60 * 60 * 1000;\n/** A Keryx that answers is believed for a week; one rolled back meanwhile just sends whole documents. */\nexport const INITIAL_SYNC_SUPPORTED_TTL_MS = 7 * 24 * 60 * 60 * 1000;\n\n/** The origin a socket URL connects to, as the memo keys it (`wss://host`). */\nexport function keryxOriginOf(wsUrl: string): string | null {\n try {\n const parsed = new URL(wsUrl);\n return `${parsed.protocol}//${parsed.host}`;\n } catch {\n return null;\n }\n}\n\n/** Remember whether the Keryx at `origin` answered with the capability header. */\nexport function rememberInitialSyncSupport({\n storage,\n origin,\n supported,\n now = Date.now(),\n}: {\n storage: InitialSyncSupportStorage | null;\n origin: string;\n supported: boolean;\n now?: number;\n}): void {\n try {\n storage?.setItem(`${MEMO_PREFIX}${origin}`, JSON.stringify({ supported, at: now }));\n } catch {\n // a full or refused storage only costs the next open a read\n }\n}\n\n/**\n * What is known of the Keryx at `origin`: `true` (it answers a socket's sync step 1), `false` (it\n * did not, within the last hour) or `null` (not known: read it and see).\n */\nexport function knownInitialSyncSupport({\n storage,\n origin,\n now = Date.now(),\n}: {\n storage: InitialSyncSupportStorage | null;\n origin: string;\n now?: number;\n}): boolean | null {\n let raw: string | null = null;\n try {\n raw = storage?.getItem(`${MEMO_PREFIX}${origin}`) ?? null;\n } catch {\n return null;\n }\n if (raw === null) return null;\n try {\n const memo = JSON.parse(raw) as { supported?: unknown; at?: unknown };\n if (typeof memo.supported !== 'boolean' || typeof memo.at !== 'number') return null;\n const ttl = memo.supported ? INITIAL_SYNC_SUPPORTED_TTL_MS : INITIAL_SYNC_UNSUPPORTED_TTL_MS;\n return now - memo.at <= ttl ? memo.supported : null;\n } catch {\n return null;\n }\n}\n"],"names":[],"mappings":";AAqBO,MAAM,qBAAqB;AAC3B,MAAM,oBAAoB;AAG1B,MAAM,iCAAiC;AAOvC,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AACF,GAIkB;AAChB,MAAI;AACJ,MAAI;AACF,aAAS,IAAI,IAAI,KAAK;AAAA,EACxB,QAAQ;AACN,WAAO;AAAA,EACT;AACA,QAAM,SAAS,OAAO,aAAa,SAAS,WAAW,OAAO,aAAa,QAAQ,UAAU;AAC7F,MAAI,WAAW,KAAM,QAAO;AAC5B,QAAM,QAAQ,mDAAmD,KAAK,OAAO,QAAQ;AACrF,MAAI,UAAU,KAAM,QAAO;AAC3B,QAAM,CAAA,EAAG,SAAS,IAAI,MAAM,IAAI,QAAQ,EAAE,IAAI;AAC9C,QAAM,OAAO,IAAI,IAAI,GAAG,MAAM,KAAK,OAAO,IAAI,GAAG,MAAM,gBAAgB,GAAG,IAAI,KAAK,EAAE;AACrF,OAAK,aAAa,IAAI,SAAS,KAAK;AACpC,OAAK,aAAa,IAAI,UAAU,MAAM;AACtC,SAAO,KAAK,SAAA;AACd;AAgBA,eAAsB,iBAAiB;AAAA,EACrC;AAAA,EACA;AAAA,EACA,YAAY;AACd,GAI8B;;AAC5B,QAAM,WAAW,MAAM,UAAU,KAAK,EAAE,SAAS,EAAE,QAAQ,8BAA8B,QAAQ;AACjG,MAAI,CAAC,SAAS,IAAI;AAChB,YAAM,cAAS,SAAT,mBAAe,SAAS,MAAM,MAAM;AAC1C,UAAM,IAAI,MAAM,sBAAsB,SAAS,MAAM,EAAE;AAAA,EACzD;AACA,QAAM,OAAO,IAAI,WAAW,MAAM,SAAS,aAAa;AACxD,QAAM,UAAU,SAAS,QAAQ,SAAS,cAAc,IAAI,CAAC;AAC7D,MAAI,YAAY,QAAQ,OAAO,YAAY,YAAY,EAAE,QAAQ,eAAe,aAAa;AAC3F,UAAM,IAAI,MAAM,8CAA8C;AAAA,EAChE;AACA,SAAO;AAAA;AAAA,IAEL,QAAQ,IAAI,WAAW,QAAQ,GAAG;AAAA,IAClC,kBAAkB,SAAS,QAAQ,IAAI,8BAA8B,MAAM;AAAA,IAC3E,OAAO,KAAK;AAAA,EAAA;AAEhB;AAQA,MAAM,cAAc;AAEb,MAAM,kCAAkC,KAAK,KAAK;AAElD,MAAM,gCAAgC,IAAI,KAAK,KAAK,KAAK;AAGzD,SAAS,cAAc,OAA8B;AAC1D,MAAI;AACF,UAAM,SAAS,IAAI,IAAI,KAAK;AAC5B,WAAO,GAAG,OAAO,QAAQ,KAAK,OAAO,IAAI;AAAA,EAC3C,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGO,SAAS,2BAA2B;AAAA,EACzC;AAAA,EACA;AAAA,EACA;AAAA,EACA,MAAM,KAAK,IAAA;AACb,GAKS;AACP,MAAI;AACF,uCAAS,QAAQ,GAAG,WAAW,GAAG,MAAM,IAAI,KAAK,UAAU,EAAE,WAAW,IAAI,IAAA,CAAK;AAAA,EACnF,QAAQ;AAAA,EAER;AACF;AAMO,SAAS,wBAAwB;AAAA,EACtC;AAAA,EACA;AAAA,EACA,MAAM,KAAK,IAAA;AACb,GAImB;AACjB,MAAI,MAAqB;AACzB,MAAI;AACF,WAAM,mCAAS,QAAQ,GAAG,WAAW,GAAG,MAAM,QAAO;AAAA,EACvD,QAAQ;AACN,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,KAAM,QAAO;AACzB,MAAI;AACF,UAAM,OAAO,KAAK,MAAM,GAAG;AAC3B,QAAI,OAAO,KAAK,cAAc,aAAa,OAAO,KAAK,OAAO,SAAU,QAAO;AAC/E,UAAM,MAAM,KAAK,YAAY,gCAAgC;AAC7D,WAAO,MAAM,KAAK,MAAM,MAAM,KAAK,YAAY;AAAA,EACjD,QAAQ;AACN,WAAO;AAAA,EACT;AACF;"}
1
+ {"version":3,"file":"initial-sync.js","sources":["../../../../keryx-http/src/initial-sync.ts"],"sourcesContent":["/**\n * Opening a big room HTTP-first (Word at scale, 2026-11-02).\n *\n * A Keryx socket's initial sync step 2 is the whole document, sent as one frame that uWS deflates on\n * Keryx's event loop: 1.4-1.8 s for a 132 MiB Word room, during which no other room on that server\n * is served, then 17 MiB on the wire. A Keryx that carries the `@y/hub` patch's diffed initial sync\n * answers a socket that connects with `?initialSync=diff` with only what the client lacks past its\n * own sync step 1, and serves `GET /ydoc` compressed (zstd, brotli or gzip, as the browser names\n * them) from a kept copy. So a client opening a big room reads it over HTTP first - decoded by the\n * browser as it downloads - applies it as the server's state, and opens its socket asking for the\n * rest: usually just the delete set.\n *\n * A Keryx says it answers that way in its `GET /ydoc` answer to a browser\n * (`X-Keryx-Initial-Sync: diff`, exposed to cross-origin readers). A Keryx without the patch says\n * nothing: its document is then not used, the socket opens as before, and the origin is remembered\n * as one that does not answer, so the next open skips the read.\n */\n\nimport * as decoding from 'lib0/decoding';\n\n/** The socket query parameter, and its one value, that ask for a diffed initial sync. */\nexport const INITIAL_SYNC_PARAM = 'initialSync';\nexport const INITIAL_SYNC_DIFF = 'diff';\n\n/** The `GET /ydoc` response header with which a Keryx says it answers `?initialSync=diff`. */\nexport const INITIAL_SYNC_CAPABILITY_HEADER = 'x-keryx-initial-sync';\n\n/**\n * Which sockets of a room that opens HTTP-first ask for a diffed initial sync, while Keryx is known\n * to answer it and the room holds no write Keryx has not echoed.\n *\n * - `every-socket` (Word documents): the socket after the room's read, every reconnect, and the\n * first socket of a room opened from its local copy.\n * - `after-read` (decks): only the socket that follows the room's own read. A room opened from its\n * local copy, and every reconnect, get Keryx's whole document, as a room that does not open\n * HTTP-first does. Keryx diffs a room that is not one compacted row against its whole merged\n * document on every socket that asks (the `@y/hub` patch's `diffForClient`). On a fast link that\n * costs a deck reopened from its copy more than the whole document does (the Midas smoke's\n * 160-slide deck synced in 3.3 s, where the whole document took about 0.6 s).\n */\nexport type DiffedInitialSync = 'every-socket' | 'after-read';\n\n/**\n * The `GET /ydoc` URL of the room a socket URL names: `wss://host/ws/<org>/<docId>` (or the\n * `/api/ws/v1/` spelling) becomes `https://host/api/ydoc/v1/<org>/<docId>?yauth=…&branch=…`. `null`\n * for a URL of any other shape.\n */\nexport function keryxRoomReadUrl({\n wsUrl,\n token,\n branch,\n}: {\n wsUrl: string;\n token: string;\n branch: string;\n}): string | null {\n let parsed: URL;\n try {\n parsed = new URL(wsUrl);\n } catch {\n return null;\n }\n const scheme = parsed.protocol === 'wss:' ? 'https:' : parsed.protocol === 'ws:' ? 'http:' : null;\n if (scheme === null) return null;\n const match = /^(.*?)\\/(?:api\\/ws\\/v1|ws)\\/([^/]+)\\/([^/]+)\\/?$/.exec(parsed.pathname);\n if (match === null) return null;\n const [, prefix = '', org = '', docId = ''] = match;\n const read = new URL(`${scheme}//${parsed.host}${prefix}/api/ydoc/v1/${org}/${docId}`);\n read.searchParams.set('yauth', token);\n read.searchParams.set('branch', branch);\n return read.toString();\n}\n\n/** A room read over HTTP. */\nexport interface RoomReadOverHttp {\n /** The room's state as one update (empty for a room never written). */\n update: Uint8Array;\n /** Keryx said it answers a socket's sync step 1 (`INITIAL_SYNC_CAPABILITY_HEADER`). */\n answersSyncStep1: boolean;\n /** The decoded body's size. */\n bytes: number;\n}\n\n/**\n * How long a room's HTTP-first read may receive nothing (no answer yet, or no byte of its body)\n * before the room gives it up and syncs over its socket instead: the minute every read was allowed\n * in all before, so no read is given up sooner than it was.\n */\nexport const HTTP_FIRST_READ_IDLE_TIMEOUT_MS = 60_000;\n\n/**\n * How long a room's HTTP-first read may take in all, however steadily its bytes come. A read still\n * downloading is otherwise never thrown away: the socket's whole-document sync it would fall back to\n * carries the same bytes, restarted from the first one on every reconnect (a large deck on a slow\n * link took 39 s to 550 s that way, `@athenaintel/decks`' `deck-open-watchdog`).\n */\nexport const HTTP_FIRST_READ_TIMEOUT_MS = 10 * 60_000;\n\n/** The body, read as it arrives: `onChunk` hears each piece. */\nasync function readBody({ response, onChunk }: { response: Response; onChunk: () => void }): Promise<Uint8Array> {\n const stream = response.body;\n if (stream === null) return new Uint8Array(await response.arrayBuffer());\n const reader = stream.getReader();\n const chunks: Uint8Array[] = [];\n let length = 0;\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n chunks.push(value);\n length += value.byteLength;\n onChunk();\n }\n const body = new Uint8Array(length);\n let offset = 0;\n for (const chunk of chunks) {\n body.set(chunk, offset);\n offset += chunk.byteLength;\n }\n return body;\n}\n\n/**\n * Read a room over `GET /ydoc` (`url` from {@link keryxRoomReadUrl}). The runtime's `fetch` names\n * and decodes the content codings. Throws on a non-2xx answer or a body that is not a lib0 `{ doc }`.\n * With `idleTimeoutMs`, a read that receives nothing for that long (no answer, or no byte of its\n * body) is given up with a `TimeoutError`; one whose bytes keep coming runs as long as they do.\n */\nexport async function readRoomOverHttp({\n url,\n signal,\n fetchImpl = fetch,\n idleTimeoutMs,\n}: {\n url: string;\n signal?: AbortSignal;\n fetchImpl?: typeof fetch;\n idleTimeoutMs?: number;\n}): Promise<RoomReadOverHttp> {\n const reading = new AbortController();\n const stop = () => reading.abort(signal?.reason);\n if (signal?.aborted) stop();\n else signal?.addEventListener('abort', stop, { once: true });\n let idle: ReturnType<typeof setTimeout> | null = null;\n const stillReceiving = () => {\n if (idleTimeoutMs === undefined) return;\n if (idle !== null) clearTimeout(idle);\n idle = setTimeout(\n () => reading.abort(new DOMException(`GET /ydoc received nothing for ${idleTimeoutMs} ms`, 'TimeoutError')),\n idleTimeoutMs\n );\n };\n stillReceiving();\n try {\n const response = await fetchImpl(url, { headers: { Accept: 'application/octet-stream' }, signal: reading.signal });\n if (!response.ok) {\n await response.body?.cancel().catch(() => undefined);\n throw new Error(`GET /ydoc answered ${response.status}`);\n }\n stillReceiving();\n const body = await readBody({ response, onChunk: stillReceiving });\n const decoded = decoding.readAny(decoding.createDecoder(body)) as { doc?: unknown } | null;\n if (decoded === null || typeof decoded !== 'object' || !(decoded.doc instanceof Uint8Array)) {\n throw new Error('GET /ydoc answered a body without a document');\n }\n return {\n // a copy: lib0 hands out a view into the body\n update: new Uint8Array(decoded.doc),\n answersSyncStep1: response.headers.get(INITIAL_SYNC_CAPABILITY_HEADER) === INITIAL_SYNC_DIFF,\n bytes: body.byteLength,\n };\n } catch (error) {\n // The idle timeout's own reason, whatever the runtime's fetch rejected the stopped read with\n if (reading.signal.aborted && !signal?.aborted) throw reading.signal.reason;\n throw error;\n } finally {\n if (idle !== null) clearTimeout(idle);\n signal?.removeEventListener('abort', stop);\n }\n}\n\n/** Where {@link rememberInitialSyncSupport} keeps what it learned: `localStorage`'s surface. */\nexport interface InitialSyncSupportStorage {\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n}\n\nconst MEMO_PREFIX = 'keryx-initial-sync:';\n/** A Keryx that answered without the header is asked again an hour later: it may have been upgraded. */\nexport const INITIAL_SYNC_UNSUPPORTED_TTL_MS = 60 * 60 * 1000;\n/** A Keryx that answers is believed for a week; one rolled back meanwhile just sends whole documents. */\nexport const INITIAL_SYNC_SUPPORTED_TTL_MS = 7 * 24 * 60 * 60 * 1000;\n\n/** The origin a socket URL connects to, as the memo keys it (`wss://host`). */\nexport function keryxOriginOf(wsUrl: string): string | null {\n try {\n const parsed = new URL(wsUrl);\n return `${parsed.protocol}//${parsed.host}`;\n } catch {\n return null;\n }\n}\n\n/** Remember whether the Keryx at `origin` answered with the capability header. */\nexport function rememberInitialSyncSupport({\n storage,\n origin,\n supported,\n now = Date.now(),\n}: {\n storage: InitialSyncSupportStorage | null;\n origin: string;\n supported: boolean;\n now?: number;\n}): void {\n try {\n storage?.setItem(`${MEMO_PREFIX}${origin}`, JSON.stringify({ supported, at: now }));\n } catch {\n // a full or refused storage only costs the next open a read\n }\n}\n\n/**\n * What is known of the Keryx at `origin`: `true` (it answers a socket's sync step 1), `false` (it\n * did not, within the last hour) or `null` (not known: read it and see).\n */\nexport function knownInitialSyncSupport({\n storage,\n origin,\n now = Date.now(),\n}: {\n storage: InitialSyncSupportStorage | null;\n origin: string;\n now?: number;\n}): boolean | null {\n let raw: string | null = null;\n try {\n raw = storage?.getItem(`${MEMO_PREFIX}${origin}`) ?? null;\n } catch {\n return null;\n }\n if (raw === null) return null;\n try {\n const memo = JSON.parse(raw) as { supported?: unknown; at?: unknown };\n if (typeof memo.supported !== 'boolean' || typeof memo.at !== 'number') return null;\n const ttl = memo.supported ? INITIAL_SYNC_SUPPORTED_TTL_MS : INITIAL_SYNC_UNSUPPORTED_TTL_MS;\n return now - memo.at <= ttl ? memo.supported : null;\n } catch {\n return null;\n }\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ function publishOwnAwarenessOnly({
4
+ transport
5
+ }) {
6
+ const send = transport._awarenessUpdateHandler;
7
+ if (typeof send !== "function") return;
8
+ const { awareness } = transport;
9
+ const ownOnly = (clientIds) => clientIds.filter((clientId) => clientId === awareness.clientID);
10
+ const sendOwn = ({ added, updated, removed }, origin) => {
11
+ const own = { added: ownOnly(added), updated: ownOnly(updated), removed: ownOnly(removed) };
12
+ if (own.added.length + own.updated.length + own.removed.length === 0) return;
13
+ send(own, origin);
14
+ };
15
+ awareness.off("update", send);
16
+ awareness.on("update", sendOwn);
17
+ transport._awarenessUpdateHandler = sendOwn;
18
+ }
19
+ exports.publishOwnAwarenessOnly = publishOwnAwarenessOnly;
20
+ //# sourceMappingURL=own-awareness.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"own-awareness.cjs","sources":["../../../../keryx-http/src/own-awareness.ts"],"sourcesContent":["/**\n * The awareness a Keryx room's socket sends: this client's own entry, never another client's.\n * Olympus's rooms (`KeryxYjsProviderV14`, and the workspace-awareness and user-notify rooms' bare\n * transport), `@athenaintel/react/collab`'s `connectGenericDoc` and the Office add-in's rooms put it\n * on every `@y/websocket` transport they open.\n *\n * `@y/websocket` sends, for every awareness `update` event, the state of every client the event\n * names (`_awarenessUpdateHandler`), whatever caused it. Most events name other clients: each peer\n * state the transport applies from Keryx (a peer's 15 s renewal, and the whole roster Keryx sends a\n * socket as it opens) and each peer the awareness drops on its own 30 s timer (a `null` entry). So\n * every client sent every peer's entry straight back to Keryx, which already holds and relays it:\n * - a workspace-awareness socket's token attests the one client id it may publish, and Keryx drops\n * every other entry it sends (`foreign_client_id`, `keryx/src/presence-ingress.ts`): in a room\n * where n tabs read the roster that is n × (n − 1) entries every 15 seconds, and every tab's whole\n * roster again each time the sockets reconnect, a Keryx roll included;\n * - a document room drops a re-sent agent slot (`agent_from_browser_token`) and a re-sent departure\n * (`foreign_departure`), and stores and relays every other re-sent entry a second time.\n *\n * What still goes out is everything about this client: its state when it changes, its 15 s renewal,\n * its departure (a `setLocalState(null)`; `disconnect()` sends its own), and its answer to a peer that\n * marked it gone (the awareness raises its own clock and the event names it). A peer's departure is\n * this client's business alone: each client drops a silent peer on its own timer, and Keryx\n * announces the departure of every client a closed socket published. Keryx never asks a socket for\n * its awareness (`messageQueryAwareness`), whose answer `@y/websocket` would build from every state\n * it holds.\n */\nimport type { Awareness } from '@y/protocols/awareness';\n\n/** The clients an awareness `update` event names. */\nexport interface AwarenessChanges {\n added: number[];\n updated: number[];\n removed: number[];\n}\n\n/** The part of `@y/websocket`'s `WebsocketProvider` that sends awareness. */\nexport interface AwarenessSendingTransport {\n readonly awareness: Awareness;\n /**\n * Sends the clients an awareness `update` event names; the transport listens with it from its\n * constructor and stops in `destroy()`.\n */\n _awarenessUpdateHandler: (changes: AwarenessChanges, origin: unknown) => void;\n}\n\n/**\n * Has `transport` send only its own client's awareness entry: every `update` event reaches the\n * transport's sender narrowed to this client, and none that names only other clients does. Call it\n * as the transport is made, before its socket opens.\n */\nexport function publishOwnAwarenessOnly({\n transport,\n}: {\n transport: AwarenessSendingTransport;\n}): void {\n const send = transport._awarenessUpdateHandler;\n // No sender (a test's stand-in for `@y/websocket`): nothing leaves to narrow. Each transport's\n // suite runs the real one, so a release that renamed the sender fails there.\n if (typeof send !== 'function') return;\n const { awareness } = transport;\n const ownOnly = (clientIds: number[]): number[] =>\n clientIds.filter((clientId) => clientId === awareness.clientID);\n const sendOwn = ({ added, updated, removed }: AwarenessChanges, origin: unknown): void => {\n const own = { added: ownOnly(added), updated: ownOnly(updated), removed: ownOnly(removed) };\n if (own.added.length + own.updated.length + own.removed.length === 0) return;\n send(own, origin);\n };\n awareness.off('update', send);\n awareness.on('update', sendOwn);\n // `destroy()` stops the listener this field holds.\n transport._awarenessUpdateHandler = sendOwn;\n}\n"],"names":[],"mappings":";;AAkDO,SAAS,wBAAwB;AAAA,EACtC;AACF,GAES;AACP,QAAM,OAAO,UAAU;AAGvB,MAAI,OAAO,SAAS,WAAY;AAChC,QAAM,EAAE,cAAc;AACtB,QAAM,UAAU,CAAC,cACf,UAAU,OAAO,CAAC,aAAa,aAAa,UAAU,QAAQ;AAChE,QAAM,UAAU,CAAC,EAAE,OAAO,SAAS,QAAA,GAA6B,WAA0B;AACxF,UAAM,MAAM,EAAE,OAAO,QAAQ,KAAK,GAAG,SAAS,QAAQ,OAAO,GAAG,SAAS,QAAQ,OAAO,EAAA;AACxF,QAAI,IAAI,MAAM,SAAS,IAAI,QAAQ,SAAS,IAAI,QAAQ,WAAW,EAAG;AACtE,SAAK,KAAK,MAAM;AAAA,EAClB;AACA,YAAU,IAAI,UAAU,IAAI;AAC5B,YAAU,GAAG,UAAU,OAAO;AAE9B,YAAU,0BAA0B;AACtC;;"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * The awareness a Keryx room's socket sends: this client's own entry, never another client's.
3
+ * Olympus's rooms (`KeryxYjsProviderV14`, and the workspace-awareness and user-notify rooms' bare
4
+ * transport), `@athenaintel/react/collab`'s `connectGenericDoc` and the Office add-in's rooms put it
5
+ * on every `@y/websocket` transport they open.
6
+ *
7
+ * `@y/websocket` sends, for every awareness `update` event, the state of every client the event
8
+ * names (`_awarenessUpdateHandler`), whatever caused it. Most events name other clients: each peer
9
+ * state the transport applies from Keryx (a peer's 15 s renewal, and the whole roster Keryx sends a
10
+ * socket as it opens) and each peer the awareness drops on its own 30 s timer (a `null` entry). So
11
+ * every client sent every peer's entry straight back to Keryx, which already holds and relays it:
12
+ * - a workspace-awareness socket's token attests the one client id it may publish, and Keryx drops
13
+ * every other entry it sends (`foreign_client_id`, `keryx/src/presence-ingress.ts`): in a room
14
+ * where n tabs read the roster that is n × (n − 1) entries every 15 seconds, and every tab's whole
15
+ * roster again each time the sockets reconnect, a Keryx roll included;
16
+ * - a document room drops a re-sent agent slot (`agent_from_browser_token`) and a re-sent departure
17
+ * (`foreign_departure`), and stores and relays every other re-sent entry a second time.
18
+ *
19
+ * What still goes out is everything about this client: its state when it changes, its 15 s renewal,
20
+ * its departure (a `setLocalState(null)`; `disconnect()` sends its own), and its answer to a peer that
21
+ * marked it gone (the awareness raises its own clock and the event names it). A peer's departure is
22
+ * this client's business alone: each client drops a silent peer on its own timer, and Keryx
23
+ * announces the departure of every client a closed socket published. Keryx never asks a socket for
24
+ * its awareness (`messageQueryAwareness`), whose answer `@y/websocket` would build from every state
25
+ * it holds.
26
+ */
27
+ import type { Awareness } from '@y/protocols/awareness';
28
+ /** The clients an awareness `update` event names. */
29
+ export interface AwarenessChanges {
30
+ added: number[];
31
+ updated: number[];
32
+ removed: number[];
33
+ }
34
+ /** The part of `@y/websocket`'s `WebsocketProvider` that sends awareness. */
35
+ export interface AwarenessSendingTransport {
36
+ readonly awareness: Awareness;
37
+ /**
38
+ * Sends the clients an awareness `update` event names; the transport listens with it from its
39
+ * constructor and stops in `destroy()`.
40
+ */
41
+ _awarenessUpdateHandler: (changes: AwarenessChanges, origin: unknown) => void;
42
+ }
43
+ /**
44
+ * Has `transport` send only its own client's awareness entry: every `update` event reaches the
45
+ * transport's sender narrowed to this client, and none that names only other clients does. Call it
46
+ * as the transport is made, before its socket opens.
47
+ */
48
+ export declare function publishOwnAwarenessOnly({ transport, }: {
49
+ transport: AwarenessSendingTransport;
50
+ }): void;
@@ -0,0 +1,20 @@
1
+ function publishOwnAwarenessOnly({
2
+ transport
3
+ }) {
4
+ const send = transport._awarenessUpdateHandler;
5
+ if (typeof send !== "function") return;
6
+ const { awareness } = transport;
7
+ const ownOnly = (clientIds) => clientIds.filter((clientId) => clientId === awareness.clientID);
8
+ const sendOwn = ({ added, updated, removed }, origin) => {
9
+ const own = { added: ownOnly(added), updated: ownOnly(updated), removed: ownOnly(removed) };
10
+ if (own.added.length + own.updated.length + own.removed.length === 0) return;
11
+ send(own, origin);
12
+ };
13
+ awareness.off("update", send);
14
+ awareness.on("update", sendOwn);
15
+ transport._awarenessUpdateHandler = sendOwn;
16
+ }
17
+ export {
18
+ publishOwnAwarenessOnly
19
+ };
20
+ //# sourceMappingURL=own-awareness.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"own-awareness.js","sources":["../../../../keryx-http/src/own-awareness.ts"],"sourcesContent":["/**\n * The awareness a Keryx room's socket sends: this client's own entry, never another client's.\n * Olympus's rooms (`KeryxYjsProviderV14`, and the workspace-awareness and user-notify rooms' bare\n * transport), `@athenaintel/react/collab`'s `connectGenericDoc` and the Office add-in's rooms put it\n * on every `@y/websocket` transport they open.\n *\n * `@y/websocket` sends, for every awareness `update` event, the state of every client the event\n * names (`_awarenessUpdateHandler`), whatever caused it. Most events name other clients: each peer\n * state the transport applies from Keryx (a peer's 15 s renewal, and the whole roster Keryx sends a\n * socket as it opens) and each peer the awareness drops on its own 30 s timer (a `null` entry). So\n * every client sent every peer's entry straight back to Keryx, which already holds and relays it:\n * - a workspace-awareness socket's token attests the one client id it may publish, and Keryx drops\n * every other entry it sends (`foreign_client_id`, `keryx/src/presence-ingress.ts`): in a room\n * where n tabs read the roster that is n × (n − 1) entries every 15 seconds, and every tab's whole\n * roster again each time the sockets reconnect, a Keryx roll included;\n * - a document room drops a re-sent agent slot (`agent_from_browser_token`) and a re-sent departure\n * (`foreign_departure`), and stores and relays every other re-sent entry a second time.\n *\n * What still goes out is everything about this client: its state when it changes, its 15 s renewal,\n * its departure (a `setLocalState(null)`; `disconnect()` sends its own), and its answer to a peer that\n * marked it gone (the awareness raises its own clock and the event names it). A peer's departure is\n * this client's business alone: each client drops a silent peer on its own timer, and Keryx\n * announces the departure of every client a closed socket published. Keryx never asks a socket for\n * its awareness (`messageQueryAwareness`), whose answer `@y/websocket` would build from every state\n * it holds.\n */\nimport type { Awareness } from '@y/protocols/awareness';\n\n/** The clients an awareness `update` event names. */\nexport interface AwarenessChanges {\n added: number[];\n updated: number[];\n removed: number[];\n}\n\n/** The part of `@y/websocket`'s `WebsocketProvider` that sends awareness. */\nexport interface AwarenessSendingTransport {\n readonly awareness: Awareness;\n /**\n * Sends the clients an awareness `update` event names; the transport listens with it from its\n * constructor and stops in `destroy()`.\n */\n _awarenessUpdateHandler: (changes: AwarenessChanges, origin: unknown) => void;\n}\n\n/**\n * Has `transport` send only its own client's awareness entry: every `update` event reaches the\n * transport's sender narrowed to this client, and none that names only other clients does. Call it\n * as the transport is made, before its socket opens.\n */\nexport function publishOwnAwarenessOnly({\n transport,\n}: {\n transport: AwarenessSendingTransport;\n}): void {\n const send = transport._awarenessUpdateHandler;\n // No sender (a test's stand-in for `@y/websocket`): nothing leaves to narrow. Each transport's\n // suite runs the real one, so a release that renamed the sender fails there.\n if (typeof send !== 'function') return;\n const { awareness } = transport;\n const ownOnly = (clientIds: number[]): number[] =>\n clientIds.filter((clientId) => clientId === awareness.clientID);\n const sendOwn = ({ added, updated, removed }: AwarenessChanges, origin: unknown): void => {\n const own = { added: ownOnly(added), updated: ownOnly(updated), removed: ownOnly(removed) };\n if (own.added.length + own.updated.length + own.removed.length === 0) return;\n send(own, origin);\n };\n awareness.off('update', send);\n awareness.on('update', sendOwn);\n // `destroy()` stops the listener this field holds.\n transport._awarenessUpdateHandler = sendOwn;\n}\n"],"names":[],"mappings":"AAkDO,SAAS,wBAAwB;AAAA,EACtC;AACF,GAES;AACP,QAAM,OAAO,UAAU;AAGvB,MAAI,OAAO,SAAS,WAAY;AAChC,QAAM,EAAE,cAAc;AACtB,QAAM,UAAU,CAAC,cACf,UAAU,OAAO,CAAC,aAAa,aAAa,UAAU,QAAQ;AAChE,QAAM,UAAU,CAAC,EAAE,OAAO,SAAS,QAAA,GAA6B,WAA0B;AACxF,UAAM,MAAM,EAAE,OAAO,QAAQ,KAAK,GAAG,SAAS,QAAQ,OAAO,GAAG,SAAS,QAAQ,OAAO,EAAA;AACxF,QAAI,IAAI,MAAM,SAAS,IAAI,QAAQ,SAAS,IAAI,QAAQ,WAAW,EAAG;AACtE,SAAK,KAAK,MAAM;AAAA,EAClB;AACA,YAAU,IAAI,UAAU,IAAI;AAC5B,YAAU,GAAG,UAAU,OAAO;AAE9B,YAAU,0BAA0B;AACtC;"}
@@ -11,6 +11,27 @@ function docScopes() {
11
11
  const host = globalThis;
12
12
  return host[DOC_SCOPES] ?? (host[DOC_SCOPES] = /* @__PURE__ */ new WeakMap());
13
13
  }
14
+ const TRANSACTION_MARKS = Symbol.for("@athenaintel/keryx-http/update-attribution-transactions");
15
+ function transactionMarks() {
16
+ const host = globalThis;
17
+ return host[TRANSACTION_MARKS] ?? (host[TRANSACTION_MARKS] = { marked: /* @__PURE__ */ new WeakMap(), emitting: /* @__PURE__ */ new WeakMap(), followed: /* @__PURE__ */ new WeakSet() });
18
+ }
19
+ function hasTransactionEvents(doc) {
20
+ const events = doc;
21
+ return typeof events.on === "function" && typeof events.off === "function";
22
+ }
23
+ function markTransactionsBegun(doc, attributions) {
24
+ if (!hasTransactionEvents(doc)) return null;
25
+ const marks = transactionMarks();
26
+ if (!marks.followed.has(doc)) {
27
+ marks.followed.add(doc);
28
+ doc.on("afterTransactionCleanup", (transaction) => marks.emitting.set(doc, transaction));
29
+ doc.on("afterAllTransactions", () => marks.emitting.delete(doc));
30
+ }
31
+ const mark = (transaction) => marks.marked.set(transaction, attributions);
32
+ doc.on("beforeTransaction", mark);
33
+ return () => doc.off("beforeTransaction", mark);
34
+ }
14
35
  function runWithDocUpdateAttributions({
15
36
  doc,
16
37
  attributions,
@@ -19,15 +40,19 @@ function runWithDocUpdateAttributions({
19
40
  const scopes = docScopes();
20
41
  const outer = scopes.get(doc);
21
42
  scopes.set(doc, attributions);
43
+ const stopMarking = markTransactionsBegun(doc, attributions);
22
44
  try {
23
45
  return run();
24
46
  } finally {
47
+ stopMarking == null ? void 0 : stopMarking();
25
48
  if (outer === void 0) scopes.delete(doc);
26
49
  else scopes.set(doc, outer);
27
50
  }
28
51
  }
29
52
  function docUpdateAttributions(doc) {
30
- return docScopes().get(doc);
53
+ const marks = transactionMarks();
54
+ const emitting = marks.emitting.get(doc);
55
+ return (emitting === void 0 ? void 0 : marks.marked.get(emitting)) ?? docScopes().get(doc);
31
56
  }
32
57
  function readVarUint({
33
58
  bytes,
@@ -1 +1 @@
1
- {"version":3,"file":"update-attributions.cjs","sources":["../../../../keryx-http/src/update-attributions.ts"],"sourcesContent":["/**\n * Attributions one Keryx socket update carries of its own.\n *\n * A Keryx connection's attributions are fixed when its socket opens, so every update a client\n * sends is attributed to the person whose client it is. A write the client makes on its own (the\n * sheet leader re-issuing `=AOP` formulas or re-pushing `=IMPORTRANGE` values, a restored result,\n * an editor binding re-keying what an older binding stored) read as that person's edit and woke\n * \"people only\" subscriptions. Keryx reads a trailer after the update in a sync update message\n * (`readUpdateAttributions` in `patches/@y%2Fhub@0.10.1.patch`): `varUint(1)`, `varUint(n)`, then\n * `n` pairs of `varString` key and value. It accepts only `origin: background`, which it counts as\n * system work (`actorOf` in `keryx/src/compaction-activity.ts`), and the pairs that name a Quick\n * Edit step (`@athenaintel/keryx-http/quick-edit`: `session_id`/`run_kind` on the apply,\n * `quick_edit_undo`/`quick_edit_redo` with `quick_edit_op` on an undo or redo), each value in\n * exactly its shape. A Keryx without that hunk reads the update and ignores the bytes after it, so\n * a trailer never costs an update; a pair it does not allow is dropped and the rest kept.\n *\n * A writer marks its writes by making them inside {@link runWithDocUpdateAttributions} for the\n * doc; the transport's socket ({@link attributingWebSocket}) appends the trailer to each sync\n * update it sends while that scope is open. Both Keryx transports wrap their sockets with it:\n * Olympus's rooms (`KeryxYjsProviderV14`) and `@athenaintel/react/collab`'s `connectGenericDoc`\n * (Midas, the phone's editor page). y-websocket sends a local update from inside the doc's\n * `update` event, which fires inside the write itself, so the trailer always rides on the update\n * the scope wrote. A write made while the socket is closed is not sent then: it reaches Keryx in\n * the reconnect's sync step 2, which can carry no trailer. A transport that hands its socket the\n * room's {@link UnconfirmedAttributedWrites} (`@athenaintel/keryx-http/unconfirmed-update-attributions`)\n * sends each such write ahead of that sync step 2 as its own marked update; without one it stays\n * the person's.\n */\n\n/** One custom attribution, as Keryx stores it on the items an update wrote. */\nexport interface UpdateAttribution {\n k: string;\n v: string;\n}\n\n/** The pair a housekeeping write carries; Agora and Keryx spell it the same way. */\nexport const BACKGROUND_UPDATE_ATTRIBUTIONS: readonly UpdateAttribution[] = [\n { k: 'origin', v: 'background' },\n];\n\n/** The trailer format Keryx reads (`updateAttributionsTrailerV1`). */\nexport const UPDATE_ATTRIBUTIONS_TRAILER_V1 = 1;\n\n/** y-protocols: a sync message, and its update sub-type. */\nconst MESSAGE_SYNC = 0;\nconst MESSAGE_SYNC_UPDATE = 2;\n\n/**\n * The open scopes live on `globalThis`, not in module scope, because two copies of this module can\n * run in one page: `@athenaintel/react` bundles it into its dist (this package is private, so the\n * published SDK must inline it) while a host may import it from this package. A scope a writer\n * opens through one copy must be the one the transport's socket reads through the other.\n */\nconst DOC_SCOPES = Symbol.for('@athenaintel/keryx-http/update-attribution-scopes');\n\ntype DocScopesHost = typeof globalThis & {\n [DOC_SCOPES]?: WeakMap<object, readonly UpdateAttribution[]>;\n};\n\n// process-local: browser-only scopes, each keyed by the doc it guards and cleared in the same synchronous call that set it\nfunction docScopes(): WeakMap<object, readonly UpdateAttribution[]> {\n const host = globalThis as DocScopesHost;\n return (host[DOC_SCOPES] ??= new WeakMap());\n}\n\n/**\n * Run `run` with every update it writes into `doc` marked with `attributions`. Synchronous only:\n * the scope ends when `run` returns. Nested scopes restore the outer one.\n */\nexport function runWithDocUpdateAttributions<T>({\n doc,\n attributions,\n run,\n}: {\n doc: object;\n attributions: readonly UpdateAttribution[];\n run: () => T;\n}): T {\n const scopes = docScopes();\n const outer = scopes.get(doc);\n scopes.set(doc, attributions);\n try {\n return run();\n } finally {\n if (outer === undefined) scopes.delete(doc);\n else scopes.set(doc, outer);\n }\n}\n\n/** The attributions the update being written into `doc` right now carries, if any. */\nexport function docUpdateAttributions(doc: object): readonly UpdateAttribution[] | undefined {\n return docScopes().get(doc);\n}\n\n/** The lib0 varUint at `start` in `bytes` and where the next field begins; `null` past the end. */\nexport function readVarUint({\n bytes,\n start,\n}: {\n bytes: Uint8Array;\n start: number;\n}): { value: number; next: number } | null {\n let value = 0;\n let multiplier = 1;\n for (let pos = start; pos < bytes.length; pos += 1) {\n const byte = bytes[pos];\n if (byte === undefined) return null;\n value += (byte & 0x7f) * multiplier;\n if (byte < 0x80) return { value, next: pos + 1 };\n multiplier *= 0x80;\n if (multiplier > Number.MAX_SAFE_INTEGER) return null;\n }\n return null;\n}\n\n/** Append `value` to `out` as a lib0 varUint. */\nexport function writeVarUint({ out, value }: { out: number[]; value: number }): void {\n let rest = value;\n while (rest > 0x7f) {\n out.push(0x80 | (rest % 0x80));\n rest = Math.floor(rest / 0x80);\n }\n out.push(rest);\n}\n\n/** Exactly one sync update message, with nothing after the update. */\nfunction isBareSyncUpdate(message: Uint8Array): boolean {\n const type = readVarUint({ bytes: message, start: 0 });\n if (type?.value !== MESSAGE_SYNC) return false;\n const syncType = readVarUint({ bytes: message, start: type.next });\n if (syncType?.value !== MESSAGE_SYNC_UPDATE) return false;\n const length = readVarUint({ bytes: message, start: syncType.next });\n return length !== null && length.next + length.value === message.length;\n}\n\n/**\n * `message` with the trailer for `attributions` appended, when it is a bare sync update message;\n * any other message (sync step 1 or 2, awareness, one that already ends in a trailer) is returned\n * as it is.\n */\nexport function withUpdateAttributionsTrailer({\n message,\n attributions,\n}: {\n message: Uint8Array;\n attributions: readonly UpdateAttribution[];\n}): Uint8Array {\n if (attributions.length === 0 || !isBareSyncUpdate(message)) return message;\n const trailer: number[] = [];\n writeVarUint({ out: trailer, value: UPDATE_ATTRIBUTIONS_TRAILER_V1 });\n writeVarUint({ out: trailer, value: attributions.length });\n const utf8 = new TextEncoder();\n for (const { k, v } of attributions) {\n for (const text of [k, v]) {\n const bytes = utf8.encode(text);\n writeVarUint({ out: trailer, value: bytes.length });\n for (const byte of bytes) trailer.push(byte);\n }\n }\n const out = new Uint8Array(message.length + trailer.length);\n out.set(message, 0);\n out.set(trailer, message.length);\n return out;\n}\n\n/** What {@link attributingWebSocket} needs of a socket: the `send` y-websocket writes frames with. */\nexport interface SendingSocket {\n send(data: string | ArrayBufferLike | Blob | ArrayBufferView): void;\n}\n\n/** One socket of a room, as the room's attributed writes Keryx has not acknowledged see it. */\nexport interface AttributedWritesSocket {\n /** Keryx sent `frame` on the socket: what it carries, Keryx holds. */\n received(frame: Uint8Array): void;\n /** The socket sends `frame` (now, or once Keryx has sent what it holds; see the implementation). */\n send(frame: Uint8Array): void;\n}\n\n/**\n * The room's attributed writes Keryx has not acknowledged yet, as its sockets see them\n * (`UnconfirmedUpdateAttributions` in `@athenaintel/keryx-http/unconfirmed-update-attributions`).\n */\nexport interface UnconfirmedAttributedWrites {\n /**\n * A socket opened, sending through `send`. `hears`: the socket hands it every frame Keryx sends\n * (`received`), ahead of the transport.\n */\n connect(params: { send: (frame: Uint8Array) => void; hears: boolean }): AttributedWritesSocket;\n}\n\n/** The bytes of a binary frame a socket received, or `null` for one that is not (a string, a `Blob`). */\nfunction receivedBytes(data: unknown): Uint8Array | null {\n if (data instanceof ArrayBuffer) return new Uint8Array(data);\n if (ArrayBuffer.isView(data))\n return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);\n return null;\n}\n\n/**\n * Hands `onFrame` every binary frame `socket` receives; whether it can. A listener added before\n * y-websocket sets `onmessage` runs ahead of it. A socket without `addEventListener` hands nothing.\n */\nfunction listenToFrames({\n socket,\n onFrame,\n}: {\n socket: SendingSocket;\n onFrame: (frame: Uint8Array) => void;\n}): boolean {\n if (!('addEventListener' in socket) || typeof socket.addEventListener !== 'function') {\n return false;\n }\n socket.addEventListener('message', (event: { data?: unknown }) => {\n const frame = receivedBytes(event.data);\n if (frame) onFrame(frame);\n });\n return true;\n}\n\n/**\n * `Base` with `send` appending the trailer of `attributionsFor()` to each sync update it sends.\n * With the room's `unconfirmed` attributed writes, each socket also tells them every frame Keryx\n * sends and sends its frames through them, so a sync step 2 goes out behind the kept writes it\n * carries. A `Proxy` keeps the constructor's statics and type, so it drops in as y-websocket's\n * `WebSocketPolyfill`.\n */\nexport function attributingWebSocket<TBase extends new (...args: never[]) => SendingSocket>({\n Base,\n attributionsFor,\n unconfirmed,\n}: {\n Base: TBase;\n attributionsFor: () => readonly UpdateAttribution[] | undefined;\n unconfirmed?: UnconfirmedAttributedWrites;\n}): TBase {\n // No WebSocket where the provider is built (server render, a test without one): nothing to wrap,\n // and the transport fails at connect as it always did.\n if (typeof Base !== 'function') return Base;\n return new Proxy(Base, {\n construct(target, args) {\n const socket: SendingSocket = Reflect.construct(target, args);\n const send = socket.send.bind(socket);\n let connection: AttributedWritesSocket | null = null;\n if (unconfirmed) {\n const hears = listenToFrames({ socket, onFrame: (frame) => connection?.received(frame) });\n connection = unconfirmed.connect({ send, hears });\n }\n socket.send = (data) => {\n if (!(data instanceof Uint8Array)) {\n send(data);\n return;\n }\n const attributions = attributionsFor();\n const message = attributions\n ? withUpdateAttributionsTrailer({ message: data, attributions })\n : data;\n if (connection) connection.send(message);\n else send(message);\n };\n return socket;\n },\n });\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"update-attributions.cjs","sources":["../../../../keryx-http/src/update-attributions.ts"],"sourcesContent":["/**\n * Attributions one Keryx socket update carries of its own.\n *\n * A Keryx connection's attributions are fixed when its socket opens, so every update a client\n * sends is attributed to the person whose client it is. A write the client makes on its own (the\n * sheet leader re-issuing `=AOP` formulas or re-pushing `=IMPORTRANGE` values, a restored result,\n * an editor binding re-keying what an older binding stored) read as that person's edit and woke\n * \"people only\" subscriptions. Keryx reads a trailer after the update in a sync update message\n * (`readUpdateAttributions` in `patches/@y%2Fhub@0.10.1.patch`): `varUint(1)`, `varUint(n)`, then\n * `n` pairs of `varString` key and value. It accepts only `origin: background`, which it counts as\n * system work (`actorOf` in `keryx/src/compaction-activity.ts`), and the pairs that name a Quick\n * Edit step (`@athenaintel/keryx-http/quick-edit`: `session_id`/`run_kind` on the apply,\n * `quick_edit_undo`/`quick_edit_redo` with `quick_edit_op` on an undo or redo), each value in\n * exactly its shape. A Keryx without that hunk reads the update and ignores the bytes after it, so\n * a trailer never costs an update; a pair it does not allow is dropped and the rest kept.\n *\n * A writer marks its writes by making them inside {@link runWithDocUpdateAttributions} for the\n * doc; the transport's socket ({@link attributingWebSocket}) appends the trailer to each sync\n * update it sends while that scope is open. Both Keryx transports wrap their sockets with it:\n * Olympus's rooms (`KeryxYjsProviderV14`) and `@athenaintel/react/collab`'s `connectGenericDoc`\n * (Midas, the phone's editor page). y-websocket sends a local update from inside the doc's\n * `update` event, which fires inside the write itself, so the trailer always rides on the update\n * the scope wrote. A write made while the socket is closed is not sent then: it reaches Keryx in\n * the reconnect's sync step 2, which can carry no trailer. A transport that hands its socket the\n * room's {@link UnconfirmedAttributedWrites} (`@athenaintel/keryx-http/unconfirmed-update-attributions`)\n * sends each such write ahead of that sync step 2 as its own marked update; without one it stays\n * the person's.\n */\n\n/** One custom attribution, as Keryx stores it on the items an update wrote. */\nexport interface UpdateAttribution {\n k: string;\n v: string;\n}\n\n/** The pair a housekeeping write carries; Agora and Keryx spell it the same way. */\nexport const BACKGROUND_UPDATE_ATTRIBUTIONS: readonly UpdateAttribution[] = [\n { k: 'origin', v: 'background' },\n];\n\n/** The trailer format Keryx reads (`updateAttributionsTrailerV1`). */\nexport const UPDATE_ATTRIBUTIONS_TRAILER_V1 = 1;\n\n/** y-protocols: a sync message, and its update sub-type. */\nconst MESSAGE_SYNC = 0;\nconst MESSAGE_SYNC_UPDATE = 2;\n\n/**\n * The open scopes live on `globalThis`, not in module scope, because two copies of this module can\n * run in one page: `@athenaintel/react` bundles it into its dist (this package is private, so the\n * published SDK must inline it) while a host may import it from this package. A scope a writer\n * opens through one copy must be the one the transport's socket reads through the other.\n */\nconst DOC_SCOPES = Symbol.for('@athenaintel/keryx-http/update-attribution-scopes');\n\ntype DocScopesHost = typeof globalThis & {\n [DOC_SCOPES]?: WeakMap<object, readonly UpdateAttribution[]>;\n};\n\n// process-local: browser-only scopes, each keyed by the doc it guards and cleared in the same synchronous call that set it\nfunction docScopes(): WeakMap<object, readonly UpdateAttribution[]> {\n const host = globalThis as DocScopesHost;\n return (host[DOC_SCOPES] ??= new WeakMap());\n}\n\n/**\n * The transactions a scope began, by the attributions their update carries, and the transaction\n * whose update each doc is emitting now: on `globalThis` for the same reason as {@link DOC_SCOPES}.\n */\nconst TRANSACTION_MARKS = Symbol.for('@athenaintel/keryx-http/update-attribution-transactions');\n\ninterface TransactionMarks {\n /** A transaction a scope began, by the attributions its update carries. */\n readonly marked: WeakMap<object, readonly UpdateAttribution[]>;\n /** The transaction whose update each doc emits now (from its cleanup to the end of the drain). */\n readonly emitting: WeakMap<object, object>;\n /** The docs whose emitting transaction is followed. */\n readonly followed: WeakSet<object>;\n}\n\ntype TransactionMarksHost = typeof globalThis & { [TRANSACTION_MARKS]?: TransactionMarks };\n\n// process-local: browser-only, keyed weakly by the doc and its transactions, which drop them with them\nfunction transactionMarks(): TransactionMarks {\n const host = globalThis as TransactionMarksHost;\n return (host[TRANSACTION_MARKS] ??= { marked: new WeakMap(), emitting: new WeakMap(), followed: new WeakSet() });\n}\n\n/** What a scope listens to on a doc: Yjs 13's and `@y/y`'s `on`/`off` alike. */\ninterface TransactionEvents {\n on(name: string, listener: (transaction: object) => void): void;\n off(name: string, listener: (transaction: object) => void): void;\n}\n\nfunction hasTransactionEvents(doc: object): doc is TransactionEvents {\n const events = doc as Partial<TransactionEvents>;\n return typeof events.on === 'function' && typeof events.off === 'function';\n}\n\n/**\n * Mark every transaction of `doc` that begins until the returned function is called with\n * `attributions`, and follow which transaction's update `doc` emits. Yjs emits a transaction's\n * update right after its `afterTransactionCleanup`, and sends none outside a drain.\n */\nfunction markTransactionsBegun(doc: object, attributions: readonly UpdateAttribution[]): (() => void) | null {\n if (!hasTransactionEvents(doc)) return null;\n const marks = transactionMarks();\n if (!marks.followed.has(doc)) {\n marks.followed.add(doc);\n doc.on('afterTransactionCleanup', (transaction) => marks.emitting.set(doc, transaction));\n doc.on('afterAllTransactions', () => marks.emitting.delete(doc));\n }\n const mark = (transaction: object) => marks.marked.set(transaction, attributions);\n doc.on('beforeTransaction', mark);\n return () => doc.off('beforeTransaction', mark);\n}\n\n/**\n * Run `run` with every update it writes into `doc` marked with `attributions`. Synchronous only:\n * the scope ends when `run` returns. Nested scopes restore the outer one.\n *\n * A transaction `run` begins while another transaction's events are delivered (an editor binding\n * writing the fix a remote change needs, from inside that change's observers) is queued by Yjs, and\n * its update is emitted, and sent, after `run` returns. Such a transaction is marked as it begins,\n * so its update carries `attributions` too: a housekeeping write never goes out as the person's.\n */\nexport function runWithDocUpdateAttributions<T>({\n doc,\n attributions,\n run,\n}: {\n doc: object;\n attributions: readonly UpdateAttribution[];\n run: () => T;\n}): T {\n const scopes = docScopes();\n const outer = scopes.get(doc);\n scopes.set(doc, attributions);\n const stopMarking = markTransactionsBegun(doc, attributions);\n try {\n return run();\n } finally {\n stopMarking?.();\n if (outer === undefined) scopes.delete(doc);\n else scopes.set(doc, outer);\n }\n}\n\n/**\n * The attributions the update being written into `doc` right now carries, if any: those of the\n * scope that began the transaction whose update `doc` is emitting, else those of the scope open\n * now.\n */\nexport function docUpdateAttributions(doc: object): readonly UpdateAttribution[] | undefined {\n const marks = transactionMarks();\n const emitting = marks.emitting.get(doc);\n return (emitting === undefined ? undefined : marks.marked.get(emitting)) ?? docScopes().get(doc);\n}\n\n/** The lib0 varUint at `start` in `bytes` and where the next field begins; `null` past the end. */\nexport function readVarUint({\n bytes,\n start,\n}: {\n bytes: Uint8Array;\n start: number;\n}): { value: number; next: number } | null {\n let value = 0;\n let multiplier = 1;\n for (let pos = start; pos < bytes.length; pos += 1) {\n const byte = bytes[pos];\n if (byte === undefined) return null;\n value += (byte & 0x7f) * multiplier;\n if (byte < 0x80) return { value, next: pos + 1 };\n multiplier *= 0x80;\n if (multiplier > Number.MAX_SAFE_INTEGER) return null;\n }\n return null;\n}\n\n/** Append `value` to `out` as a lib0 varUint. */\nexport function writeVarUint({ out, value }: { out: number[]; value: number }): void {\n let rest = value;\n while (rest > 0x7f) {\n out.push(0x80 | (rest % 0x80));\n rest = Math.floor(rest / 0x80);\n }\n out.push(rest);\n}\n\n/** Exactly one sync update message, with nothing after the update. */\nfunction isBareSyncUpdate(message: Uint8Array): boolean {\n const type = readVarUint({ bytes: message, start: 0 });\n if (type?.value !== MESSAGE_SYNC) return false;\n const syncType = readVarUint({ bytes: message, start: type.next });\n if (syncType?.value !== MESSAGE_SYNC_UPDATE) return false;\n const length = readVarUint({ bytes: message, start: syncType.next });\n return length !== null && length.next + length.value === message.length;\n}\n\n/**\n * `message` with the trailer for `attributions` appended, when it is a bare sync update message;\n * any other message (sync step 1 or 2, awareness, one that already ends in a trailer) is returned\n * as it is.\n */\nexport function withUpdateAttributionsTrailer({\n message,\n attributions,\n}: {\n message: Uint8Array;\n attributions: readonly UpdateAttribution[];\n}): Uint8Array {\n if (attributions.length === 0 || !isBareSyncUpdate(message)) return message;\n const trailer: number[] = [];\n writeVarUint({ out: trailer, value: UPDATE_ATTRIBUTIONS_TRAILER_V1 });\n writeVarUint({ out: trailer, value: attributions.length });\n const utf8 = new TextEncoder();\n for (const { k, v } of attributions) {\n for (const text of [k, v]) {\n const bytes = utf8.encode(text);\n writeVarUint({ out: trailer, value: bytes.length });\n for (const byte of bytes) trailer.push(byte);\n }\n }\n const out = new Uint8Array(message.length + trailer.length);\n out.set(message, 0);\n out.set(trailer, message.length);\n return out;\n}\n\n/** What {@link attributingWebSocket} needs of a socket: the `send` y-websocket writes frames with. */\nexport interface SendingSocket {\n send(data: string | ArrayBufferLike | Blob | ArrayBufferView): void;\n}\n\n/** One socket of a room, as the room's attributed writes Keryx has not acknowledged see it. */\nexport interface AttributedWritesSocket {\n /** Keryx sent `frame` on the socket: what it carries, Keryx holds. */\n received(frame: Uint8Array): void;\n /** The socket sends `frame` (now, or once Keryx has sent what it holds; see the implementation). */\n send(frame: Uint8Array): void;\n}\n\n/**\n * The room's attributed writes Keryx has not acknowledged yet, as its sockets see them\n * (`UnconfirmedUpdateAttributions` in `@athenaintel/keryx-http/unconfirmed-update-attributions`).\n */\nexport interface UnconfirmedAttributedWrites {\n /**\n * A socket opened, sending through `send`. `hears`: the socket hands it every frame Keryx sends\n * (`received`), ahead of the transport.\n */\n connect(params: { send: (frame: Uint8Array) => void; hears: boolean }): AttributedWritesSocket;\n}\n\n/** The bytes of a binary frame a socket received, or `null` for one that is not (a string, a `Blob`). */\nfunction receivedBytes(data: unknown): Uint8Array | null {\n if (data instanceof ArrayBuffer) return new Uint8Array(data);\n if (ArrayBuffer.isView(data))\n return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);\n return null;\n}\n\n/**\n * Hands `onFrame` every binary frame `socket` receives; whether it can. A listener added before\n * y-websocket sets `onmessage` runs ahead of it. A socket without `addEventListener` hands nothing.\n */\nfunction listenToFrames({\n socket,\n onFrame,\n}: {\n socket: SendingSocket;\n onFrame: (frame: Uint8Array) => void;\n}): boolean {\n if (!('addEventListener' in socket) || typeof socket.addEventListener !== 'function') {\n return false;\n }\n socket.addEventListener('message', (event: { data?: unknown }) => {\n const frame = receivedBytes(event.data);\n if (frame) onFrame(frame);\n });\n return true;\n}\n\n/**\n * `Base` with `send` appending the trailer of `attributionsFor()` to each sync update it sends.\n * With the room's `unconfirmed` attributed writes, each socket also tells them every frame Keryx\n * sends and sends its frames through them, so a sync step 2 goes out behind the kept writes it\n * carries. A `Proxy` keeps the constructor's statics and type, so it drops in as y-websocket's\n * `WebSocketPolyfill`.\n */\nexport function attributingWebSocket<TBase extends new (...args: never[]) => SendingSocket>({\n Base,\n attributionsFor,\n unconfirmed,\n}: {\n Base: TBase;\n attributionsFor: () => readonly UpdateAttribution[] | undefined;\n unconfirmed?: UnconfirmedAttributedWrites;\n}): TBase {\n // No WebSocket where the provider is built (server render, a test without one): nothing to wrap,\n // and the transport fails at connect as it always did.\n if (typeof Base !== 'function') return Base;\n return new Proxy(Base, {\n construct(target, args) {\n const socket: SendingSocket = Reflect.construct(target, args);\n const send = socket.send.bind(socket);\n let connection: AttributedWritesSocket | null = null;\n if (unconfirmed) {\n const hears = listenToFrames({ socket, onFrame: (frame) => connection?.received(frame) });\n connection = unconfirmed.connect({ send, hears });\n }\n socket.send = (data) => {\n if (!(data instanceof Uint8Array)) {\n send(data);\n return;\n }\n const attributions = attributionsFor();\n const message = attributions\n ? withUpdateAttributionsTrailer({ message: data, attributions })\n : data;\n if (connection) connection.send(message);\n else send(message);\n };\n return socket;\n },\n });\n}\n"],"names":[],"mappings":"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"}
@@ -38,13 +38,22 @@ export declare const UPDATE_ATTRIBUTIONS_TRAILER_V1 = 1;
38
38
  /**
39
39
  * Run `run` with every update it writes into `doc` marked with `attributions`. Synchronous only:
40
40
  * the scope ends when `run` returns. Nested scopes restore the outer one.
41
+ *
42
+ * A transaction `run` begins while another transaction's events are delivered (an editor binding
43
+ * writing the fix a remote change needs, from inside that change's observers) is queued by Yjs, and
44
+ * its update is emitted, and sent, after `run` returns. Such a transaction is marked as it begins,
45
+ * so its update carries `attributions` too: a housekeeping write never goes out as the person's.
41
46
  */
42
47
  export declare function runWithDocUpdateAttributions<T>({ doc, attributions, run, }: {
43
48
  doc: object;
44
49
  attributions: readonly UpdateAttribution[];
45
50
  run: () => T;
46
51
  }): T;
47
- /** The attributions the update being written into `doc` right now carries, if any. */
52
+ /**
53
+ * The attributions the update being written into `doc` right now carries, if any: those of the
54
+ * scope that began the transaction whose update `doc` is emitting, else those of the scope open
55
+ * now.
56
+ */
48
57
  export declare function docUpdateAttributions(doc: object): readonly UpdateAttribution[] | undefined;
49
58
  /** The lib0 varUint at `start` in `bytes` and where the next field begins; `null` past the end. */
50
59
  export declare function readVarUint({ bytes, start, }: {
@@ -9,6 +9,27 @@ function docScopes() {
9
9
  const host = globalThis;
10
10
  return host[DOC_SCOPES] ?? (host[DOC_SCOPES] = /* @__PURE__ */ new WeakMap());
11
11
  }
12
+ const TRANSACTION_MARKS = Symbol.for("@athenaintel/keryx-http/update-attribution-transactions");
13
+ function transactionMarks() {
14
+ const host = globalThis;
15
+ return host[TRANSACTION_MARKS] ?? (host[TRANSACTION_MARKS] = { marked: /* @__PURE__ */ new WeakMap(), emitting: /* @__PURE__ */ new WeakMap(), followed: /* @__PURE__ */ new WeakSet() });
16
+ }
17
+ function hasTransactionEvents(doc) {
18
+ const events = doc;
19
+ return typeof events.on === "function" && typeof events.off === "function";
20
+ }
21
+ function markTransactionsBegun(doc, attributions) {
22
+ if (!hasTransactionEvents(doc)) return null;
23
+ const marks = transactionMarks();
24
+ if (!marks.followed.has(doc)) {
25
+ marks.followed.add(doc);
26
+ doc.on("afterTransactionCleanup", (transaction) => marks.emitting.set(doc, transaction));
27
+ doc.on("afterAllTransactions", () => marks.emitting.delete(doc));
28
+ }
29
+ const mark = (transaction) => marks.marked.set(transaction, attributions);
30
+ doc.on("beforeTransaction", mark);
31
+ return () => doc.off("beforeTransaction", mark);
32
+ }
12
33
  function runWithDocUpdateAttributions({
13
34
  doc,
14
35
  attributions,
@@ -17,15 +38,19 @@ function runWithDocUpdateAttributions({
17
38
  const scopes = docScopes();
18
39
  const outer = scopes.get(doc);
19
40
  scopes.set(doc, attributions);
41
+ const stopMarking = markTransactionsBegun(doc, attributions);
20
42
  try {
21
43
  return run();
22
44
  } finally {
45
+ stopMarking == null ? void 0 : stopMarking();
23
46
  if (outer === void 0) scopes.delete(doc);
24
47
  else scopes.set(doc, outer);
25
48
  }
26
49
  }
27
50
  function docUpdateAttributions(doc) {
28
- return docScopes().get(doc);
51
+ const marks = transactionMarks();
52
+ const emitting = marks.emitting.get(doc);
53
+ return (emitting === void 0 ? void 0 : marks.marked.get(emitting)) ?? docScopes().get(doc);
29
54
  }
30
55
  function readVarUint({
31
56
  bytes,
@@ -1 +1 @@
1
- {"version":3,"file":"update-attributions.js","sources":["../../../../keryx-http/src/update-attributions.ts"],"sourcesContent":["/**\n * Attributions one Keryx socket update carries of its own.\n *\n * A Keryx connection's attributions are fixed when its socket opens, so every update a client\n * sends is attributed to the person whose client it is. A write the client makes on its own (the\n * sheet leader re-issuing `=AOP` formulas or re-pushing `=IMPORTRANGE` values, a restored result,\n * an editor binding re-keying what an older binding stored) read as that person's edit and woke\n * \"people only\" subscriptions. Keryx reads a trailer after the update in a sync update message\n * (`readUpdateAttributions` in `patches/@y%2Fhub@0.10.1.patch`): `varUint(1)`, `varUint(n)`, then\n * `n` pairs of `varString` key and value. It accepts only `origin: background`, which it counts as\n * system work (`actorOf` in `keryx/src/compaction-activity.ts`), and the pairs that name a Quick\n * Edit step (`@athenaintel/keryx-http/quick-edit`: `session_id`/`run_kind` on the apply,\n * `quick_edit_undo`/`quick_edit_redo` with `quick_edit_op` on an undo or redo), each value in\n * exactly its shape. A Keryx without that hunk reads the update and ignores the bytes after it, so\n * a trailer never costs an update; a pair it does not allow is dropped and the rest kept.\n *\n * A writer marks its writes by making them inside {@link runWithDocUpdateAttributions} for the\n * doc; the transport's socket ({@link attributingWebSocket}) appends the trailer to each sync\n * update it sends while that scope is open. Both Keryx transports wrap their sockets with it:\n * Olympus's rooms (`KeryxYjsProviderV14`) and `@athenaintel/react/collab`'s `connectGenericDoc`\n * (Midas, the phone's editor page). y-websocket sends a local update from inside the doc's\n * `update` event, which fires inside the write itself, so the trailer always rides on the update\n * the scope wrote. A write made while the socket is closed is not sent then: it reaches Keryx in\n * the reconnect's sync step 2, which can carry no trailer. A transport that hands its socket the\n * room's {@link UnconfirmedAttributedWrites} (`@athenaintel/keryx-http/unconfirmed-update-attributions`)\n * sends each such write ahead of that sync step 2 as its own marked update; without one it stays\n * the person's.\n */\n\n/** One custom attribution, as Keryx stores it on the items an update wrote. */\nexport interface UpdateAttribution {\n k: string;\n v: string;\n}\n\n/** The pair a housekeeping write carries; Agora and Keryx spell it the same way. */\nexport const BACKGROUND_UPDATE_ATTRIBUTIONS: readonly UpdateAttribution[] = [\n { k: 'origin', v: 'background' },\n];\n\n/** The trailer format Keryx reads (`updateAttributionsTrailerV1`). */\nexport const UPDATE_ATTRIBUTIONS_TRAILER_V1 = 1;\n\n/** y-protocols: a sync message, and its update sub-type. */\nconst MESSAGE_SYNC = 0;\nconst MESSAGE_SYNC_UPDATE = 2;\n\n/**\n * The open scopes live on `globalThis`, not in module scope, because two copies of this module can\n * run in one page: `@athenaintel/react` bundles it into its dist (this package is private, so the\n * published SDK must inline it) while a host may import it from this package. A scope a writer\n * opens through one copy must be the one the transport's socket reads through the other.\n */\nconst DOC_SCOPES = Symbol.for('@athenaintel/keryx-http/update-attribution-scopes');\n\ntype DocScopesHost = typeof globalThis & {\n [DOC_SCOPES]?: WeakMap<object, readonly UpdateAttribution[]>;\n};\n\n// process-local: browser-only scopes, each keyed by the doc it guards and cleared in the same synchronous call that set it\nfunction docScopes(): WeakMap<object, readonly UpdateAttribution[]> {\n const host = globalThis as DocScopesHost;\n return (host[DOC_SCOPES] ??= new WeakMap());\n}\n\n/**\n * Run `run` with every update it writes into `doc` marked with `attributions`. Synchronous only:\n * the scope ends when `run` returns. Nested scopes restore the outer one.\n */\nexport function runWithDocUpdateAttributions<T>({\n doc,\n attributions,\n run,\n}: {\n doc: object;\n attributions: readonly UpdateAttribution[];\n run: () => T;\n}): T {\n const scopes = docScopes();\n const outer = scopes.get(doc);\n scopes.set(doc, attributions);\n try {\n return run();\n } finally {\n if (outer === undefined) scopes.delete(doc);\n else scopes.set(doc, outer);\n }\n}\n\n/** The attributions the update being written into `doc` right now carries, if any. */\nexport function docUpdateAttributions(doc: object): readonly UpdateAttribution[] | undefined {\n return docScopes().get(doc);\n}\n\n/** The lib0 varUint at `start` in `bytes` and where the next field begins; `null` past the end. */\nexport function readVarUint({\n bytes,\n start,\n}: {\n bytes: Uint8Array;\n start: number;\n}): { value: number; next: number } | null {\n let value = 0;\n let multiplier = 1;\n for (let pos = start; pos < bytes.length; pos += 1) {\n const byte = bytes[pos];\n if (byte === undefined) return null;\n value += (byte & 0x7f) * multiplier;\n if (byte < 0x80) return { value, next: pos + 1 };\n multiplier *= 0x80;\n if (multiplier > Number.MAX_SAFE_INTEGER) return null;\n }\n return null;\n}\n\n/** Append `value` to `out` as a lib0 varUint. */\nexport function writeVarUint({ out, value }: { out: number[]; value: number }): void {\n let rest = value;\n while (rest > 0x7f) {\n out.push(0x80 | (rest % 0x80));\n rest = Math.floor(rest / 0x80);\n }\n out.push(rest);\n}\n\n/** Exactly one sync update message, with nothing after the update. */\nfunction isBareSyncUpdate(message: Uint8Array): boolean {\n const type = readVarUint({ bytes: message, start: 0 });\n if (type?.value !== MESSAGE_SYNC) return false;\n const syncType = readVarUint({ bytes: message, start: type.next });\n if (syncType?.value !== MESSAGE_SYNC_UPDATE) return false;\n const length = readVarUint({ bytes: message, start: syncType.next });\n return length !== null && length.next + length.value === message.length;\n}\n\n/**\n * `message` with the trailer for `attributions` appended, when it is a bare sync update message;\n * any other message (sync step 1 or 2, awareness, one that already ends in a trailer) is returned\n * as it is.\n */\nexport function withUpdateAttributionsTrailer({\n message,\n attributions,\n}: {\n message: Uint8Array;\n attributions: readonly UpdateAttribution[];\n}): Uint8Array {\n if (attributions.length === 0 || !isBareSyncUpdate(message)) return message;\n const trailer: number[] = [];\n writeVarUint({ out: trailer, value: UPDATE_ATTRIBUTIONS_TRAILER_V1 });\n writeVarUint({ out: trailer, value: attributions.length });\n const utf8 = new TextEncoder();\n for (const { k, v } of attributions) {\n for (const text of [k, v]) {\n const bytes = utf8.encode(text);\n writeVarUint({ out: trailer, value: bytes.length });\n for (const byte of bytes) trailer.push(byte);\n }\n }\n const out = new Uint8Array(message.length + trailer.length);\n out.set(message, 0);\n out.set(trailer, message.length);\n return out;\n}\n\n/** What {@link attributingWebSocket} needs of a socket: the `send` y-websocket writes frames with. */\nexport interface SendingSocket {\n send(data: string | ArrayBufferLike | Blob | ArrayBufferView): void;\n}\n\n/** One socket of a room, as the room's attributed writes Keryx has not acknowledged see it. */\nexport interface AttributedWritesSocket {\n /** Keryx sent `frame` on the socket: what it carries, Keryx holds. */\n received(frame: Uint8Array): void;\n /** The socket sends `frame` (now, or once Keryx has sent what it holds; see the implementation). */\n send(frame: Uint8Array): void;\n}\n\n/**\n * The room's attributed writes Keryx has not acknowledged yet, as its sockets see them\n * (`UnconfirmedUpdateAttributions` in `@athenaintel/keryx-http/unconfirmed-update-attributions`).\n */\nexport interface UnconfirmedAttributedWrites {\n /**\n * A socket opened, sending through `send`. `hears`: the socket hands it every frame Keryx sends\n * (`received`), ahead of the transport.\n */\n connect(params: { send: (frame: Uint8Array) => void; hears: boolean }): AttributedWritesSocket;\n}\n\n/** The bytes of a binary frame a socket received, or `null` for one that is not (a string, a `Blob`). */\nfunction receivedBytes(data: unknown): Uint8Array | null {\n if (data instanceof ArrayBuffer) return new Uint8Array(data);\n if (ArrayBuffer.isView(data))\n return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);\n return null;\n}\n\n/**\n * Hands `onFrame` every binary frame `socket` receives; whether it can. A listener added before\n * y-websocket sets `onmessage` runs ahead of it. A socket without `addEventListener` hands nothing.\n */\nfunction listenToFrames({\n socket,\n onFrame,\n}: {\n socket: SendingSocket;\n onFrame: (frame: Uint8Array) => void;\n}): boolean {\n if (!('addEventListener' in socket) || typeof socket.addEventListener !== 'function') {\n return false;\n }\n socket.addEventListener('message', (event: { data?: unknown }) => {\n const frame = receivedBytes(event.data);\n if (frame) onFrame(frame);\n });\n return true;\n}\n\n/**\n * `Base` with `send` appending the trailer of `attributionsFor()` to each sync update it sends.\n * With the room's `unconfirmed` attributed writes, each socket also tells them every frame Keryx\n * sends and sends its frames through them, so a sync step 2 goes out behind the kept writes it\n * carries. A `Proxy` keeps the constructor's statics and type, so it drops in as y-websocket's\n * `WebSocketPolyfill`.\n */\nexport function attributingWebSocket<TBase extends new (...args: never[]) => SendingSocket>({\n Base,\n attributionsFor,\n unconfirmed,\n}: {\n Base: TBase;\n attributionsFor: () => readonly UpdateAttribution[] | undefined;\n unconfirmed?: UnconfirmedAttributedWrites;\n}): TBase {\n // No WebSocket where the provider is built (server render, a test without one): nothing to wrap,\n // and the transport fails at connect as it always did.\n if (typeof Base !== 'function') return Base;\n return new Proxy(Base, {\n construct(target, args) {\n const socket: SendingSocket = Reflect.construct(target, args);\n const send = socket.send.bind(socket);\n let connection: AttributedWritesSocket | null = null;\n if (unconfirmed) {\n const hears = listenToFrames({ socket, onFrame: (frame) => connection?.received(frame) });\n connection = unconfirmed.connect({ send, hears });\n }\n socket.send = (data) => {\n if (!(data instanceof Uint8Array)) {\n send(data);\n return;\n }\n const attributions = attributionsFor();\n const message = attributions\n ? withUpdateAttributionsTrailer({ message: data, attributions })\n : data;\n if (connection) connection.send(message);\n else send(message);\n };\n return socket;\n },\n });\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"update-attributions.js","sources":["../../../../keryx-http/src/update-attributions.ts"],"sourcesContent":["/**\n * Attributions one Keryx socket update carries of its own.\n *\n * A Keryx connection's attributions are fixed when its socket opens, so every update a client\n * sends is attributed to the person whose client it is. A write the client makes on its own (the\n * sheet leader re-issuing `=AOP` formulas or re-pushing `=IMPORTRANGE` values, a restored result,\n * an editor binding re-keying what an older binding stored) read as that person's edit and woke\n * \"people only\" subscriptions. Keryx reads a trailer after the update in a sync update message\n * (`readUpdateAttributions` in `patches/@y%2Fhub@0.10.1.patch`): `varUint(1)`, `varUint(n)`, then\n * `n` pairs of `varString` key and value. It accepts only `origin: background`, which it counts as\n * system work (`actorOf` in `keryx/src/compaction-activity.ts`), and the pairs that name a Quick\n * Edit step (`@athenaintel/keryx-http/quick-edit`: `session_id`/`run_kind` on the apply,\n * `quick_edit_undo`/`quick_edit_redo` with `quick_edit_op` on an undo or redo), each value in\n * exactly its shape. A Keryx without that hunk reads the update and ignores the bytes after it, so\n * a trailer never costs an update; a pair it does not allow is dropped and the rest kept.\n *\n * A writer marks its writes by making them inside {@link runWithDocUpdateAttributions} for the\n * doc; the transport's socket ({@link attributingWebSocket}) appends the trailer to each sync\n * update it sends while that scope is open. Both Keryx transports wrap their sockets with it:\n * Olympus's rooms (`KeryxYjsProviderV14`) and `@athenaintel/react/collab`'s `connectGenericDoc`\n * (Midas, the phone's editor page). y-websocket sends a local update from inside the doc's\n * `update` event, which fires inside the write itself, so the trailer always rides on the update\n * the scope wrote. A write made while the socket is closed is not sent then: it reaches Keryx in\n * the reconnect's sync step 2, which can carry no trailer. A transport that hands its socket the\n * room's {@link UnconfirmedAttributedWrites} (`@athenaintel/keryx-http/unconfirmed-update-attributions`)\n * sends each such write ahead of that sync step 2 as its own marked update; without one it stays\n * the person's.\n */\n\n/** One custom attribution, as Keryx stores it on the items an update wrote. */\nexport interface UpdateAttribution {\n k: string;\n v: string;\n}\n\n/** The pair a housekeeping write carries; Agora and Keryx spell it the same way. */\nexport const BACKGROUND_UPDATE_ATTRIBUTIONS: readonly UpdateAttribution[] = [\n { k: 'origin', v: 'background' },\n];\n\n/** The trailer format Keryx reads (`updateAttributionsTrailerV1`). */\nexport const UPDATE_ATTRIBUTIONS_TRAILER_V1 = 1;\n\n/** y-protocols: a sync message, and its update sub-type. */\nconst MESSAGE_SYNC = 0;\nconst MESSAGE_SYNC_UPDATE = 2;\n\n/**\n * The open scopes live on `globalThis`, not in module scope, because two copies of this module can\n * run in one page: `@athenaintel/react` bundles it into its dist (this package is private, so the\n * published SDK must inline it) while a host may import it from this package. A scope a writer\n * opens through one copy must be the one the transport's socket reads through the other.\n */\nconst DOC_SCOPES = Symbol.for('@athenaintel/keryx-http/update-attribution-scopes');\n\ntype DocScopesHost = typeof globalThis & {\n [DOC_SCOPES]?: WeakMap<object, readonly UpdateAttribution[]>;\n};\n\n// process-local: browser-only scopes, each keyed by the doc it guards and cleared in the same synchronous call that set it\nfunction docScopes(): WeakMap<object, readonly UpdateAttribution[]> {\n const host = globalThis as DocScopesHost;\n return (host[DOC_SCOPES] ??= new WeakMap());\n}\n\n/**\n * The transactions a scope began, by the attributions their update carries, and the transaction\n * whose update each doc is emitting now: on `globalThis` for the same reason as {@link DOC_SCOPES}.\n */\nconst TRANSACTION_MARKS = Symbol.for('@athenaintel/keryx-http/update-attribution-transactions');\n\ninterface TransactionMarks {\n /** A transaction a scope began, by the attributions its update carries. */\n readonly marked: WeakMap<object, readonly UpdateAttribution[]>;\n /** The transaction whose update each doc emits now (from its cleanup to the end of the drain). */\n readonly emitting: WeakMap<object, object>;\n /** The docs whose emitting transaction is followed. */\n readonly followed: WeakSet<object>;\n}\n\ntype TransactionMarksHost = typeof globalThis & { [TRANSACTION_MARKS]?: TransactionMarks };\n\n// process-local: browser-only, keyed weakly by the doc and its transactions, which drop them with them\nfunction transactionMarks(): TransactionMarks {\n const host = globalThis as TransactionMarksHost;\n return (host[TRANSACTION_MARKS] ??= { marked: new WeakMap(), emitting: new WeakMap(), followed: new WeakSet() });\n}\n\n/** What a scope listens to on a doc: Yjs 13's and `@y/y`'s `on`/`off` alike. */\ninterface TransactionEvents {\n on(name: string, listener: (transaction: object) => void): void;\n off(name: string, listener: (transaction: object) => void): void;\n}\n\nfunction hasTransactionEvents(doc: object): doc is TransactionEvents {\n const events = doc as Partial<TransactionEvents>;\n return typeof events.on === 'function' && typeof events.off === 'function';\n}\n\n/**\n * Mark every transaction of `doc` that begins until the returned function is called with\n * `attributions`, and follow which transaction's update `doc` emits. Yjs emits a transaction's\n * update right after its `afterTransactionCleanup`, and sends none outside a drain.\n */\nfunction markTransactionsBegun(doc: object, attributions: readonly UpdateAttribution[]): (() => void) | null {\n if (!hasTransactionEvents(doc)) return null;\n const marks = transactionMarks();\n if (!marks.followed.has(doc)) {\n marks.followed.add(doc);\n doc.on('afterTransactionCleanup', (transaction) => marks.emitting.set(doc, transaction));\n doc.on('afterAllTransactions', () => marks.emitting.delete(doc));\n }\n const mark = (transaction: object) => marks.marked.set(transaction, attributions);\n doc.on('beforeTransaction', mark);\n return () => doc.off('beforeTransaction', mark);\n}\n\n/**\n * Run `run` with every update it writes into `doc` marked with `attributions`. Synchronous only:\n * the scope ends when `run` returns. Nested scopes restore the outer one.\n *\n * A transaction `run` begins while another transaction's events are delivered (an editor binding\n * writing the fix a remote change needs, from inside that change's observers) is queued by Yjs, and\n * its update is emitted, and sent, after `run` returns. Such a transaction is marked as it begins,\n * so its update carries `attributions` too: a housekeeping write never goes out as the person's.\n */\nexport function runWithDocUpdateAttributions<T>({\n doc,\n attributions,\n run,\n}: {\n doc: object;\n attributions: readonly UpdateAttribution[];\n run: () => T;\n}): T {\n const scopes = docScopes();\n const outer = scopes.get(doc);\n scopes.set(doc, attributions);\n const stopMarking = markTransactionsBegun(doc, attributions);\n try {\n return run();\n } finally {\n stopMarking?.();\n if (outer === undefined) scopes.delete(doc);\n else scopes.set(doc, outer);\n }\n}\n\n/**\n * The attributions the update being written into `doc` right now carries, if any: those of the\n * scope that began the transaction whose update `doc` is emitting, else those of the scope open\n * now.\n */\nexport function docUpdateAttributions(doc: object): readonly UpdateAttribution[] | undefined {\n const marks = transactionMarks();\n const emitting = marks.emitting.get(doc);\n return (emitting === undefined ? undefined : marks.marked.get(emitting)) ?? docScopes().get(doc);\n}\n\n/** The lib0 varUint at `start` in `bytes` and where the next field begins; `null` past the end. */\nexport function readVarUint({\n bytes,\n start,\n}: {\n bytes: Uint8Array;\n start: number;\n}): { value: number; next: number } | null {\n let value = 0;\n let multiplier = 1;\n for (let pos = start; pos < bytes.length; pos += 1) {\n const byte = bytes[pos];\n if (byte === undefined) return null;\n value += (byte & 0x7f) * multiplier;\n if (byte < 0x80) return { value, next: pos + 1 };\n multiplier *= 0x80;\n if (multiplier > Number.MAX_SAFE_INTEGER) return null;\n }\n return null;\n}\n\n/** Append `value` to `out` as a lib0 varUint. */\nexport function writeVarUint({ out, value }: { out: number[]; value: number }): void {\n let rest = value;\n while (rest > 0x7f) {\n out.push(0x80 | (rest % 0x80));\n rest = Math.floor(rest / 0x80);\n }\n out.push(rest);\n}\n\n/** Exactly one sync update message, with nothing after the update. */\nfunction isBareSyncUpdate(message: Uint8Array): boolean {\n const type = readVarUint({ bytes: message, start: 0 });\n if (type?.value !== MESSAGE_SYNC) return false;\n const syncType = readVarUint({ bytes: message, start: type.next });\n if (syncType?.value !== MESSAGE_SYNC_UPDATE) return false;\n const length = readVarUint({ bytes: message, start: syncType.next });\n return length !== null && length.next + length.value === message.length;\n}\n\n/**\n * `message` with the trailer for `attributions` appended, when it is a bare sync update message;\n * any other message (sync step 1 or 2, awareness, one that already ends in a trailer) is returned\n * as it is.\n */\nexport function withUpdateAttributionsTrailer({\n message,\n attributions,\n}: {\n message: Uint8Array;\n attributions: readonly UpdateAttribution[];\n}): Uint8Array {\n if (attributions.length === 0 || !isBareSyncUpdate(message)) return message;\n const trailer: number[] = [];\n writeVarUint({ out: trailer, value: UPDATE_ATTRIBUTIONS_TRAILER_V1 });\n writeVarUint({ out: trailer, value: attributions.length });\n const utf8 = new TextEncoder();\n for (const { k, v } of attributions) {\n for (const text of [k, v]) {\n const bytes = utf8.encode(text);\n writeVarUint({ out: trailer, value: bytes.length });\n for (const byte of bytes) trailer.push(byte);\n }\n }\n const out = new Uint8Array(message.length + trailer.length);\n out.set(message, 0);\n out.set(trailer, message.length);\n return out;\n}\n\n/** What {@link attributingWebSocket} needs of a socket: the `send` y-websocket writes frames with. */\nexport interface SendingSocket {\n send(data: string | ArrayBufferLike | Blob | ArrayBufferView): void;\n}\n\n/** One socket of a room, as the room's attributed writes Keryx has not acknowledged see it. */\nexport interface AttributedWritesSocket {\n /** Keryx sent `frame` on the socket: what it carries, Keryx holds. */\n received(frame: Uint8Array): void;\n /** The socket sends `frame` (now, or once Keryx has sent what it holds; see the implementation). */\n send(frame: Uint8Array): void;\n}\n\n/**\n * The room's attributed writes Keryx has not acknowledged yet, as its sockets see them\n * (`UnconfirmedUpdateAttributions` in `@athenaintel/keryx-http/unconfirmed-update-attributions`).\n */\nexport interface UnconfirmedAttributedWrites {\n /**\n * A socket opened, sending through `send`. `hears`: the socket hands it every frame Keryx sends\n * (`received`), ahead of the transport.\n */\n connect(params: { send: (frame: Uint8Array) => void; hears: boolean }): AttributedWritesSocket;\n}\n\n/** The bytes of a binary frame a socket received, or `null` for one that is not (a string, a `Blob`). */\nfunction receivedBytes(data: unknown): Uint8Array | null {\n if (data instanceof ArrayBuffer) return new Uint8Array(data);\n if (ArrayBuffer.isView(data))\n return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);\n return null;\n}\n\n/**\n * Hands `onFrame` every binary frame `socket` receives; whether it can. A listener added before\n * y-websocket sets `onmessage` runs ahead of it. A socket without `addEventListener` hands nothing.\n */\nfunction listenToFrames({\n socket,\n onFrame,\n}: {\n socket: SendingSocket;\n onFrame: (frame: Uint8Array) => void;\n}): boolean {\n if (!('addEventListener' in socket) || typeof socket.addEventListener !== 'function') {\n return false;\n }\n socket.addEventListener('message', (event: { data?: unknown }) => {\n const frame = receivedBytes(event.data);\n if (frame) onFrame(frame);\n });\n return true;\n}\n\n/**\n * `Base` with `send` appending the trailer of `attributionsFor()` to each sync update it sends.\n * With the room's `unconfirmed` attributed writes, each socket also tells them every frame Keryx\n * sends and sends its frames through them, so a sync step 2 goes out behind the kept writes it\n * carries. A `Proxy` keeps the constructor's statics and type, so it drops in as y-websocket's\n * `WebSocketPolyfill`.\n */\nexport function attributingWebSocket<TBase extends new (...args: never[]) => SendingSocket>({\n Base,\n attributionsFor,\n unconfirmed,\n}: {\n Base: TBase;\n attributionsFor: () => readonly UpdateAttribution[] | undefined;\n unconfirmed?: UnconfirmedAttributedWrites;\n}): TBase {\n // No WebSocket where the provider is built (server render, a test without one): nothing to wrap,\n // and the transport fails at connect as it always did.\n if (typeof Base !== 'function') return Base;\n return new Proxy(Base, {\n construct(target, args) {\n const socket: SendingSocket = Reflect.construct(target, args);\n const send = socket.send.bind(socket);\n let connection: AttributedWritesSocket | null = null;\n if (unconfirmed) {\n const hears = listenToFrames({ socket, onFrame: (frame) => connection?.received(frame) });\n connection = unconfirmed.connect({ send, hears });\n }\n socket.send = (data) => {\n if (!(data instanceof Uint8Array)) {\n send(data);\n return;\n }\n const attributions = attributionsFor();\n const message = attributions\n ? withUpdateAttributionsTrailer({ message: data, attributions })\n : data;\n if (connection) connection.send(message);\n else send(message);\n };\n return socket;\n },\n });\n}\n"],"names":[],"mappings":"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"}