@agimon-ai/doompi-author 0.0.1-alpha.2

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 (282) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +37 -0
  3. package/dist/_virtual/_rolldown/runtime.cjs +1 -0
  4. package/dist/adapters/authorApi.cjs +2 -0
  5. package/dist/adapters/authorApi.cjs.map +1 -0
  6. package/dist/adapters/authorBridgeApi.cjs +2 -0
  7. package/dist/adapters/authorBridgeApi.cjs.map +1 -0
  8. package/dist/adapters/authorDocumentApi.cjs +2 -0
  9. package/dist/adapters/authorDocumentApi.cjs.map +1 -0
  10. package/dist/adapters/pi/authorBridgeClient.cjs +2 -0
  11. package/dist/adapters/pi/authorBridgeClient.cjs.map +1 -0
  12. package/dist/adapters/pi/authorTools.cjs +2 -0
  13. package/dist/adapters/pi/authorTools.cjs.map +1 -0
  14. package/dist/adapters/pi/extension.cjs +2 -0
  15. package/dist/adapters/pi/extension.cjs.map +1 -0
  16. package/dist/adapters/structuredDocuments/common.cjs +2 -0
  17. package/dist/adapters/structuredDocuments/common.cjs.map +1 -0
  18. package/dist/adapters/structuredDocuments/csv.cjs +7 -0
  19. package/dist/adapters/structuredDocuments/csv.cjs.map +1 -0
  20. package/dist/adapters/structuredDocuments/index.cjs +2 -0
  21. package/dist/adapters/structuredDocuments/index.cjs.map +1 -0
  22. package/dist/adapters/structuredDocuments/markdownSlides.cjs +6 -0
  23. package/dist/adapters/structuredDocuments/markdownSlides.cjs.map +1 -0
  24. package/dist/adapters/structuredDocuments/ooxmlArchive.cjs +2 -0
  25. package/dist/adapters/structuredDocuments/ooxmlArchive.cjs.map +1 -0
  26. package/dist/adapters/structuredDocuments/pptx.cjs +2 -0
  27. package/dist/adapters/structuredDocuments/pptx.cjs.map +1 -0
  28. package/dist/adapters/structuredDocuments/xlsx.cjs +2 -0
  29. package/dist/adapters/structuredDocuments/xlsx.cjs.map +1 -0
  30. package/dist/adapters/structuredDocuments/xmlText.cjs +2 -0
  31. package/dist/adapters/structuredDocuments/xmlText.cjs.map +1 -0
  32. package/dist/adapters/webAuthorChannel.cjs +2 -0
  33. package/dist/adapters/webAuthorChannel.cjs.map +1 -0
  34. package/dist/commands/doomAuthorCommand.cjs +2 -0
  35. package/dist/commands/doomAuthorCommand.cjs.map +1 -0
  36. package/dist/container/index.cjs +2 -0
  37. package/dist/container/index.cjs.map +1 -0
  38. package/dist/extensions/pi.cjs +1 -0
  39. package/dist/extensions/pi.d.cts +2 -0
  40. package/dist/extensions/pi.d.mts +2 -0
  41. package/dist/extensions/pi.mjs +1 -0
  42. package/dist/index.cjs +1 -0
  43. package/dist/index.d.cts +21 -0
  44. package/dist/index.d.mts +21 -0
  45. package/dist/index.mjs +1 -0
  46. package/dist/node_modules/.pnpm/typebox@1.3.25/node_modules/typebox/build/type/engine/helpers/union.d.cts +6 -0
  47. package/dist/node_modules/.pnpm/typebox@1.3.25/node_modules/typebox/build/type/engine/helpers/union.d.cts.map +1 -0
  48. package/dist/node_modules/.pnpm/typebox@1.3.25/node_modules/typebox/build/type/engine/helpers/union.d.mts +6 -0
  49. package/dist/node_modules/.pnpm/typebox@1.3.25/node_modules/typebox/build/type/engine/helpers/union.d.mts.map +1 -0
  50. package/dist/node_modules/.pnpm/typebox@1.3.25/node_modules/typebox/build/type/types/_optional.d.cts +7 -0
  51. package/dist/node_modules/.pnpm/typebox@1.3.25/node_modules/typebox/build/type/types/_optional.d.cts.map +1 -0
  52. package/dist/node_modules/.pnpm/typebox@1.3.25/node_modules/typebox/build/type/types/_optional.d.mts +7 -0
  53. package/dist/node_modules/.pnpm/typebox@1.3.25/node_modules/typebox/build/type/types/_optional.d.mts.map +1 -0
  54. package/dist/node_modules/.pnpm/typebox@1.3.25/node_modules/typebox/build/type/types/object.d.cts +12 -0
  55. package/dist/node_modules/.pnpm/typebox@1.3.25/node_modules/typebox/build/type/types/object.d.cts.map +1 -0
  56. package/dist/node_modules/.pnpm/typebox@1.3.25/node_modules/typebox/build/type/types/object.d.mts +12 -0
  57. package/dist/node_modules/.pnpm/typebox@1.3.25/node_modules/typebox/build/type/types/object.d.mts.map +1 -0
  58. package/dist/node_modules/.pnpm/typebox@1.3.25/node_modules/typebox/build/type/types/properties.d.cts +12 -0
  59. package/dist/node_modules/.pnpm/typebox@1.3.25/node_modules/typebox/build/type/types/properties.d.cts.map +1 -0
  60. package/dist/node_modules/.pnpm/typebox@1.3.25/node_modules/typebox/build/type/types/properties.d.mts +12 -0
  61. package/dist/node_modules/.pnpm/typebox@1.3.25/node_modules/typebox/build/type/types/properties.d.mts.map +1 -0
  62. package/dist/node_modules/.pnpm/typebox@1.3.25/node_modules/typebox/build/type/types/record.d.cts +9 -0
  63. package/dist/node_modules/.pnpm/typebox@1.3.25/node_modules/typebox/build/type/types/record.d.cts.map +1 -0
  64. package/dist/node_modules/.pnpm/typebox@1.3.25/node_modules/typebox/build/type/types/record.d.mts +9 -0
  65. package/dist/node_modules/.pnpm/typebox@1.3.25/node_modules/typebox/build/type/types/record.d.mts.map +1 -0
  66. package/dist/node_modules/.pnpm/typebox@1.3.25/node_modules/typebox/build/type/types/schema.d.cts +4 -0
  67. package/dist/node_modules/.pnpm/typebox@1.3.25/node_modules/typebox/build/type/types/schema.d.cts.map +1 -0
  68. package/dist/node_modules/.pnpm/typebox@1.3.25/node_modules/typebox/build/type/types/schema.d.mts +4 -0
  69. package/dist/node_modules/.pnpm/typebox@1.3.25/node_modules/typebox/build/type/types/schema.d.mts.map +1 -0
  70. package/dist/node_modules/.pnpm/typebox@1.3.25/node_modules/typebox/build/type/types/string.d.cts +9 -0
  71. package/dist/node_modules/.pnpm/typebox@1.3.25/node_modules/typebox/build/type/types/string.d.cts.map +1 -0
  72. package/dist/node_modules/.pnpm/typebox@1.3.25/node_modules/typebox/build/type/types/string.d.mts +9 -0
  73. package/dist/node_modules/.pnpm/typebox@1.3.25/node_modules/typebox/build/type/types/string.d.mts.map +1 -0
  74. package/dist/node_modules/.pnpm/typebox@1.3.25/node_modules/typebox/build/type/types/unknown.d.cts +8 -0
  75. package/dist/node_modules/.pnpm/typebox@1.3.25/node_modules/typebox/build/type/types/unknown.d.cts.map +1 -0
  76. package/dist/node_modules/.pnpm/typebox@1.3.25/node_modules/typebox/build/type/types/unknown.d.mts +8 -0
  77. package/dist/node_modules/.pnpm/typebox@1.3.25/node_modules/typebox/build/type/types/unknown.d.mts.map +1 -0
  78. package/dist/packages/minor/doompi-author/src/adapters/authorApi.d.cts +15 -0
  79. package/dist/packages/minor/doompi-author/src/adapters/authorApi.d.cts.map +1 -0
  80. package/dist/packages/minor/doompi-author/src/adapters/authorApi.d.mts +15 -0
  81. package/dist/packages/minor/doompi-author/src/adapters/authorApi.d.mts.map +1 -0
  82. package/dist/packages/minor/doompi-author/src/adapters/authorApi.mjs +2 -0
  83. package/dist/packages/minor/doompi-author/src/adapters/authorApi.mjs.map +1 -0
  84. package/dist/packages/minor/doompi-author/src/adapters/authorBridgeApi.d.cts +6 -0
  85. package/dist/packages/minor/doompi-author/src/adapters/authorBridgeApi.d.cts.map +1 -0
  86. package/dist/packages/minor/doompi-author/src/adapters/authorBridgeApi.d.mts +6 -0
  87. package/dist/packages/minor/doompi-author/src/adapters/authorBridgeApi.d.mts.map +1 -0
  88. package/dist/packages/minor/doompi-author/src/adapters/authorBridgeApi.mjs +2 -0
  89. package/dist/packages/minor/doompi-author/src/adapters/authorBridgeApi.mjs.map +1 -0
  90. package/dist/packages/minor/doompi-author/src/adapters/authorDocumentApi.d.cts +11 -0
  91. package/dist/packages/minor/doompi-author/src/adapters/authorDocumentApi.d.cts.map +1 -0
  92. package/dist/packages/minor/doompi-author/src/adapters/authorDocumentApi.d.mts +11 -0
  93. package/dist/packages/minor/doompi-author/src/adapters/authorDocumentApi.d.mts.map +1 -0
  94. package/dist/packages/minor/doompi-author/src/adapters/authorDocumentApi.mjs +2 -0
  95. package/dist/packages/minor/doompi-author/src/adapters/authorDocumentApi.mjs.map +1 -0
  96. package/dist/packages/minor/doompi-author/src/adapters/pi/authorBridgeClient.d.cts +18 -0
  97. package/dist/packages/minor/doompi-author/src/adapters/pi/authorBridgeClient.d.cts.map +1 -0
  98. package/dist/packages/minor/doompi-author/src/adapters/pi/authorBridgeClient.d.mts +18 -0
  99. package/dist/packages/minor/doompi-author/src/adapters/pi/authorBridgeClient.d.mts.map +1 -0
  100. package/dist/packages/minor/doompi-author/src/adapters/pi/authorBridgeClient.mjs +2 -0
  101. package/dist/packages/minor/doompi-author/src/adapters/pi/authorBridgeClient.mjs.map +1 -0
  102. package/dist/packages/minor/doompi-author/src/adapters/pi/authorTools.d.cts +9 -0
  103. package/dist/packages/minor/doompi-author/src/adapters/pi/authorTools.d.cts.map +1 -0
  104. package/dist/packages/minor/doompi-author/src/adapters/pi/authorTools.d.mts +9 -0
  105. package/dist/packages/minor/doompi-author/src/adapters/pi/authorTools.d.mts.map +1 -0
  106. package/dist/packages/minor/doompi-author/src/adapters/pi/authorTools.mjs +2 -0
  107. package/dist/packages/minor/doompi-author/src/adapters/pi/authorTools.mjs.map +1 -0
  108. package/dist/packages/minor/doompi-author/src/adapters/pi/extension.d.cts +19 -0
  109. package/dist/packages/minor/doompi-author/src/adapters/pi/extension.d.cts.map +1 -0
  110. package/dist/packages/minor/doompi-author/src/adapters/pi/extension.d.mts +19 -0
  111. package/dist/packages/minor/doompi-author/src/adapters/pi/extension.d.mts.map +1 -0
  112. package/dist/packages/minor/doompi-author/src/adapters/pi/extension.mjs +2 -0
  113. package/dist/packages/minor/doompi-author/src/adapters/pi/extension.mjs.map +1 -0
  114. package/dist/packages/minor/doompi-author/src/adapters/structuredDocuments/common.mjs +2 -0
  115. package/dist/packages/minor/doompi-author/src/adapters/structuredDocuments/common.mjs.map +1 -0
  116. package/dist/packages/minor/doompi-author/src/adapters/structuredDocuments/csv.d.cts +7 -0
  117. package/dist/packages/minor/doompi-author/src/adapters/structuredDocuments/csv.d.cts.map +1 -0
  118. package/dist/packages/minor/doompi-author/src/adapters/structuredDocuments/csv.d.mts +7 -0
  119. package/dist/packages/minor/doompi-author/src/adapters/structuredDocuments/csv.d.mts.map +1 -0
  120. package/dist/packages/minor/doompi-author/src/adapters/structuredDocuments/csv.mjs +7 -0
  121. package/dist/packages/minor/doompi-author/src/adapters/structuredDocuments/csv.mjs.map +1 -0
  122. package/dist/packages/minor/doompi-author/src/adapters/structuredDocuments/index.d.cts +13 -0
  123. package/dist/packages/minor/doompi-author/src/adapters/structuredDocuments/index.d.cts.map +1 -0
  124. package/dist/packages/minor/doompi-author/src/adapters/structuredDocuments/index.d.mts +13 -0
  125. package/dist/packages/minor/doompi-author/src/adapters/structuredDocuments/index.d.mts.map +1 -0
  126. package/dist/packages/minor/doompi-author/src/adapters/structuredDocuments/index.mjs +2 -0
  127. package/dist/packages/minor/doompi-author/src/adapters/structuredDocuments/index.mjs.map +1 -0
  128. package/dist/packages/minor/doompi-author/src/adapters/structuredDocuments/markdownSlides.d.cts +7 -0
  129. package/dist/packages/minor/doompi-author/src/adapters/structuredDocuments/markdownSlides.d.cts.map +1 -0
  130. package/dist/packages/minor/doompi-author/src/adapters/structuredDocuments/markdownSlides.d.mts +7 -0
  131. package/dist/packages/minor/doompi-author/src/adapters/structuredDocuments/markdownSlides.d.mts.map +1 -0
  132. package/dist/packages/minor/doompi-author/src/adapters/structuredDocuments/markdownSlides.mjs +6 -0
  133. package/dist/packages/minor/doompi-author/src/adapters/structuredDocuments/markdownSlides.mjs.map +1 -0
  134. package/dist/packages/minor/doompi-author/src/adapters/structuredDocuments/ooxmlArchive.d.cts +13 -0
  135. package/dist/packages/minor/doompi-author/src/adapters/structuredDocuments/ooxmlArchive.d.cts.map +1 -0
  136. package/dist/packages/minor/doompi-author/src/adapters/structuredDocuments/ooxmlArchive.d.mts +13 -0
  137. package/dist/packages/minor/doompi-author/src/adapters/structuredDocuments/ooxmlArchive.d.mts.map +1 -0
  138. package/dist/packages/minor/doompi-author/src/adapters/structuredDocuments/ooxmlArchive.mjs +2 -0
  139. package/dist/packages/minor/doompi-author/src/adapters/structuredDocuments/ooxmlArchive.mjs.map +1 -0
  140. package/dist/packages/minor/doompi-author/src/adapters/structuredDocuments/pptx.d.cts +7 -0
  141. package/dist/packages/minor/doompi-author/src/adapters/structuredDocuments/pptx.d.cts.map +1 -0
  142. package/dist/packages/minor/doompi-author/src/adapters/structuredDocuments/pptx.d.mts +7 -0
  143. package/dist/packages/minor/doompi-author/src/adapters/structuredDocuments/pptx.d.mts.map +1 -0
  144. package/dist/packages/minor/doompi-author/src/adapters/structuredDocuments/pptx.mjs +2 -0
  145. package/dist/packages/minor/doompi-author/src/adapters/structuredDocuments/pptx.mjs.map +1 -0
  146. package/dist/packages/minor/doompi-author/src/adapters/structuredDocuments/xlsx.d.cts +7 -0
  147. package/dist/packages/minor/doompi-author/src/adapters/structuredDocuments/xlsx.d.cts.map +1 -0
  148. package/dist/packages/minor/doompi-author/src/adapters/structuredDocuments/xlsx.d.mts +7 -0
  149. package/dist/packages/minor/doompi-author/src/adapters/structuredDocuments/xlsx.d.mts.map +1 -0
  150. package/dist/packages/minor/doompi-author/src/adapters/structuredDocuments/xlsx.mjs +2 -0
  151. package/dist/packages/minor/doompi-author/src/adapters/structuredDocuments/xlsx.mjs.map +1 -0
  152. package/dist/packages/minor/doompi-author/src/adapters/structuredDocuments/xmlText.mjs +2 -0
  153. package/dist/packages/minor/doompi-author/src/adapters/structuredDocuments/xmlText.mjs.map +1 -0
  154. package/dist/packages/minor/doompi-author/src/adapters/webAuthorChannel.d.cts +6 -0
  155. package/dist/packages/minor/doompi-author/src/adapters/webAuthorChannel.d.cts.map +1 -0
  156. package/dist/packages/minor/doompi-author/src/adapters/webAuthorChannel.d.mts +6 -0
  157. package/dist/packages/minor/doompi-author/src/adapters/webAuthorChannel.d.mts.map +1 -0
  158. package/dist/packages/minor/doompi-author/src/adapters/webAuthorChannel.mjs +2 -0
  159. package/dist/packages/minor/doompi-author/src/adapters/webAuthorChannel.mjs.map +1 -0
  160. package/dist/packages/minor/doompi-author/src/commands/doomAuthorCommand.mjs +2 -0
  161. package/dist/packages/minor/doompi-author/src/commands/doomAuthorCommand.mjs.map +1 -0
  162. package/dist/packages/minor/doompi-author/src/container/index.d.cts +5 -0
  163. package/dist/packages/minor/doompi-author/src/container/index.d.cts.map +1 -0
  164. package/dist/packages/minor/doompi-author/src/container/index.d.mts +5 -0
  165. package/dist/packages/minor/doompi-author/src/container/index.d.mts.map +1 -0
  166. package/dist/packages/minor/doompi-author/src/container/index.mjs +2 -0
  167. package/dist/packages/minor/doompi-author/src/container/index.mjs.map +1 -0
  168. package/dist/packages/minor/doompi-author/src/schemas/authorTools.d.cts +16 -0
  169. package/dist/packages/minor/doompi-author/src/schemas/authorTools.d.cts.map +1 -0
  170. package/dist/packages/minor/doompi-author/src/schemas/authorTools.d.mts +16 -0
  171. package/dist/packages/minor/doompi-author/src/schemas/authorTools.d.mts.map +1 -0
  172. package/dist/packages/minor/doompi-author/src/schemas/authorTools.mjs +2 -0
  173. package/dist/packages/minor/doompi-author/src/schemas/authorTools.mjs.map +1 -0
  174. package/dist/packages/minor/doompi-author/src/services/authorBridgeState.d.cts +31 -0
  175. package/dist/packages/minor/doompi-author/src/services/authorBridgeState.d.cts.map +1 -0
  176. package/dist/packages/minor/doompi-author/src/services/authorBridgeState.d.mts +31 -0
  177. package/dist/packages/minor/doompi-author/src/services/authorBridgeState.d.mts.map +1 -0
  178. package/dist/packages/minor/doompi-author/src/services/authorBridgeState.mjs +2 -0
  179. package/dist/packages/minor/doompi-author/src/services/authorBridgeState.mjs.map +1 -0
  180. package/dist/packages/minor/doompi-author/src/services/authorCatalog.d.cts +10 -0
  181. package/dist/packages/minor/doompi-author/src/services/authorCatalog.d.cts.map +1 -0
  182. package/dist/packages/minor/doompi-author/src/services/authorCatalog.d.mts +10 -0
  183. package/dist/packages/minor/doompi-author/src/services/authorCatalog.d.mts.map +1 -0
  184. package/dist/packages/minor/doompi-author/src/services/authorMode.d.cts +19 -0
  185. package/dist/packages/minor/doompi-author/src/services/authorMode.d.cts.map +1 -0
  186. package/dist/packages/minor/doompi-author/src/services/authorMode.d.mts +19 -0
  187. package/dist/packages/minor/doompi-author/src/services/authorMode.d.mts.map +1 -0
  188. package/dist/packages/minor/doompi-author/src/services/authorMode.mjs +3 -0
  189. package/dist/packages/minor/doompi-author/src/services/authorMode.mjs.map +1 -0
  190. package/dist/packages/minor/doompi-author/src/services/extensionService.d.cts +7 -0
  191. package/dist/packages/minor/doompi-author/src/services/extensionService.d.cts.map +1 -0
  192. package/dist/packages/minor/doompi-author/src/services/extensionService.d.mts +7 -0
  193. package/dist/packages/minor/doompi-author/src/services/extensionService.d.mts.map +1 -0
  194. package/dist/packages/minor/doompi-author/src/services/extensionService.mjs +2 -0
  195. package/dist/packages/minor/doompi-author/src/services/extensionService.mjs.map +1 -0
  196. package/dist/packages/minor/doompi-author/src/types/author.d.cts +39 -0
  197. package/dist/packages/minor/doompi-author/src/types/author.d.cts.map +1 -0
  198. package/dist/packages/minor/doompi-author/src/types/author.d.mts +39 -0
  199. package/dist/packages/minor/doompi-author/src/types/author.d.mts.map +1 -0
  200. package/dist/packages/minor/doompi-author/src/types/author.mjs +2 -0
  201. package/dist/packages/minor/doompi-author/src/types/author.mjs.map +1 -0
  202. package/dist/packages/minor/doompi-author/src/types/authorApi.d.cts +23 -0
  203. package/dist/packages/minor/doompi-author/src/types/authorApi.d.cts.map +1 -0
  204. package/dist/packages/minor/doompi-author/src/types/authorApi.d.mts +23 -0
  205. package/dist/packages/minor/doompi-author/src/types/authorApi.d.mts.map +1 -0
  206. package/dist/packages/minor/doompi-author/src/types/authorApi.mjs +2 -0
  207. package/dist/packages/minor/doompi-author/src/types/authorApi.mjs.map +1 -0
  208. package/dist/packages/minor/doompi-author/src/types/extension.d.cts +16 -0
  209. package/dist/packages/minor/doompi-author/src/types/extension.d.cts.map +1 -0
  210. package/dist/packages/minor/doompi-author/src/types/extension.d.mts +16 -0
  211. package/dist/packages/minor/doompi-author/src/types/extension.d.mts.map +1 -0
  212. package/dist/packages/minor/doompi-author/src/types/structuredDocuments.d.cts +60 -0
  213. package/dist/packages/minor/doompi-author/src/types/structuredDocuments.d.cts.map +1 -0
  214. package/dist/packages/minor/doompi-author/src/types/structuredDocuments.d.mts +60 -0
  215. package/dist/packages/minor/doompi-author/src/types/structuredDocuments.d.mts.map +1 -0
  216. package/dist/packages/minor/doompi-author/src/types/webAuthor.d.cts +67 -0
  217. package/dist/packages/minor/doompi-author/src/types/webAuthor.d.cts.map +1 -0
  218. package/dist/packages/minor/doompi-author/src/types/webAuthor.d.mts +67 -0
  219. package/dist/packages/minor/doompi-author/src/types/webAuthor.d.mts.map +1 -0
  220. package/dist/packages/minor/doompi-author/src/types/webAuthor.mjs +2 -0
  221. package/dist/packages/minor/doompi-author/src/types/webAuthor.mjs.map +1 -0
  222. package/dist/schemas/authorTools.cjs +2 -0
  223. package/dist/schemas/authorTools.cjs.map +1 -0
  224. package/dist/services/authorBridgeState.cjs +2 -0
  225. package/dist/services/authorBridgeState.cjs.map +1 -0
  226. package/dist/services/authorMode.cjs +3 -0
  227. package/dist/services/authorMode.cjs.map +1 -0
  228. package/dist/services/extensionService.cjs +2 -0
  229. package/dist/services/extensionService.cjs.map +1 -0
  230. package/dist/sessionApi.cjs +1 -0
  231. package/dist/sessionApi.d.cts +7 -0
  232. package/dist/sessionApi.d.mts +7 -0
  233. package/dist/sessionApi.mjs +1 -0
  234. package/dist/types/author.cjs +2 -0
  235. package/dist/types/author.cjs.map +1 -0
  236. package/dist/types/authorApi.cjs +2 -0
  237. package/dist/types/authorApi.cjs.map +1 -0
  238. package/dist/types/webAuthor.cjs +2 -0
  239. package/dist/types/webAuthor.cjs.map +1 -0
  240. package/dist/webHub.cjs +1 -0
  241. package/dist/webHub.d.cts +2 -0
  242. package/dist/webHub.d.mts +2 -0
  243. package/dist/webHub.mjs +1 -0
  244. package/llms.txt +11 -0
  245. package/package.json +140 -0
  246. package/src/exports/webClient.ts +76 -0
  247. package/src/prompts/doompi-use-author/SKILL.md +17 -0
  248. package/src/types/author.ts +45 -0
  249. package/src/types/structuredDocuments.ts +63 -0
  250. package/src/types/webAuthor.ts +85 -0
  251. package/src/web/api/authorBroker.ts +14 -0
  252. package/src/web/api/authorBrowserBridge.ts +225 -0
  253. package/src/web/api/authorFiles.ts +219 -0
  254. package/src/web/api/authorMedia.ts +19 -0
  255. package/src/web/api/authorRuntime.ts +164 -0
  256. package/src/web/components/AuthorDocumentPanel.tsx +232 -0
  257. package/src/web/components/AuthorGridOverlay.tsx +81 -0
  258. package/src/web/components/AuthorMediaPreview.tsx +41 -0
  259. package/src/web/components/AuthorMediaView.tsx +356 -0
  260. package/src/web/components/AuthorPanel.tsx +105 -0
  261. package/src/web/components/AuthorRegionDrafts.tsx +102 -0
  262. package/src/web/components/AuthorRequestLog.tsx +179 -0
  263. package/src/web/components/AuthorStructuredView.tsx +121 -0
  264. package/src/web/components/AuthorTextView.tsx +97 -0
  265. package/src/web/components/AuthorToolPalette.tsx +103 -0
  266. package/src/web/components/AuthorVideoControls.tsx +111 -0
  267. package/src/web/components/DescribeAuthorToolsToolCard.tsx +50 -0
  268. package/src/web/components/OpenAuthoringFileToolCard.tsx +66 -0
  269. package/src/web/components/UseAuthorToolsToolCard.tsx +50 -0
  270. package/src/web/index.ts +68 -0
  271. package/src/web/lib/authorGrid.ts +124 -0
  272. package/src/web/lib/authorRegions.ts +30 -0
  273. package/src/web/lib/authorViewportTypes.ts +202 -0
  274. package/src/web/lib/describeAuthorToolsToolRender.ts +20 -0
  275. package/src/web/lib/useAuthorToolsToolRender.ts +20 -0
  276. package/src/web/stores/authorCapture.ts +322 -0
  277. package/src/web/stores/authorGridTools.ts +316 -0
  278. package/src/web/stores/authorProfiles.ts +130 -0
  279. package/src/web/stores/authorRequestLifecycle.ts +82 -0
  280. package/src/web/stores/authorStore.ts +60 -0
  281. package/src/web/stores/authorWorkspaceStore.ts +525 -0
  282. package/src/web/tsconfig.json +22 -0
@@ -0,0 +1,525 @@
1
+ import { defineGlobalStore } from '@agimon-ai/doompi-web-contracts';
2
+ import type {
3
+ AuthorAnnotation,
4
+ AuthorCrop,
5
+ AuthorDocumentInput,
6
+ AuthorDraftRevision,
7
+ AuthorFocusedDocument,
8
+ AuthorRegionCandidate,
9
+ AuthorRegionDraft,
10
+ AuthorRequestRecord,
11
+ AuthorRequestStatus,
12
+ AuthorToolMode,
13
+ } from '../lib/authorViewportTypes.ts';
14
+
15
+ export const AUTHOR_REGION_LIMIT = 16;
16
+ export const AUTHOR_HISTORY_RECORD_LIMIT = 100;
17
+ export const AUTHOR_HISTORY_BYTE_LIMIT = 512 * 1024;
18
+ const TERMINAL_REQUEST_STATUSES: ReadonlySet<AuthorRequestStatus> = new Set(['COMPLETE', 'FAILED', 'CANCELLED']);
19
+
20
+ export interface AuthorWorkspaceDocument extends AuthorDocumentInput {
21
+ path: string;
22
+ annotations: readonly AuthorAnnotation[];
23
+ revisions: readonly AuthorDraftRevision[];
24
+ crop?: AuthorCrop;
25
+ saveRequest: number;
26
+ version: number;
27
+ savedVersion: number;
28
+ savingVersion?: number;
29
+ }
30
+
31
+ export interface AuthorSessionWorkspace {
32
+ generation: number;
33
+ focusedDocument?: AuthorFocusedDocument;
34
+ activeTool: AuthorToolMode;
35
+ candidate?: AuthorRegionCandidate;
36
+ videoSeekRequest?: { path: string; generation: number; timeSeconds: number; sequence: number };
37
+ regions: readonly AuthorRegionDraft[];
38
+ requests: readonly AuthorRequestRecord[];
39
+ }
40
+
41
+ export interface AuthorWorkspaceState {
42
+ documents: Readonly<Record<string, AuthorWorkspaceDocument>>;
43
+ sessions: Readonly<Record<string, AuthorSessionWorkspace>>;
44
+ }
45
+
46
+ const EMPTY_SESSION: AuthorSessionWorkspace = { generation: 0, activeTool: 'select', regions: [], requests: [] };
47
+
48
+ export function normalizeAuthorPath(path: string): string {
49
+ const parts: string[] = [];
50
+ for (const part of path.trim().replaceAll('\\', '/').split('/')) {
51
+ if (part === '' || part === '.') continue;
52
+ if (part === '..') parts.pop();
53
+ else parts.push(part);
54
+ }
55
+ return parts.join('/');
56
+ }
57
+
58
+ export function authorDocumentKey(sessionId: string, path: string): string {
59
+ return `${sessionId}\n${normalizeAuthorPath(path)}`;
60
+ }
61
+
62
+ export const authorWorkspace = defineGlobalStore<AuthorWorkspaceState>({ documents: {}, sessions: {} });
63
+
64
+ export function authorDocument(sessionId: string | null, path: string): AuthorWorkspaceDocument | undefined {
65
+ if (sessionId === null) return undefined;
66
+ return authorWorkspace.store.state.documents[authorDocumentKey(sessionId, path)];
67
+ }
68
+
69
+ export function authorSessionWorkspace(sessionId: string | null): AuthorSessionWorkspace {
70
+ if (sessionId === null) return EMPTY_SESSION;
71
+ return authorWorkspace.store.state.sessions[sessionId] ?? EMPTY_SESSION;
72
+ }
73
+
74
+ export function putAuthorDocument(sessionId: string, input: AuthorDocumentInput): AuthorWorkspaceDocument {
75
+ const path = normalizeAuthorPath(input.path);
76
+ if (path === '') throw new Error('Author document path must not be empty');
77
+ const key = authorDocumentKey(sessionId, path);
78
+ const staleThumbnails: string[] = [];
79
+ let result!: AuthorWorkspaceDocument;
80
+ authorWorkspace.update((state) => {
81
+ const previous = state.documents[key];
82
+ const sourceChanged =
83
+ previous?.sourceSha256 !== undefined &&
84
+ input.sourceSha256 !== undefined &&
85
+ previous.sourceSha256 !== input.sourceSha256;
86
+ const baselineVersion = sourceChanged ? previous.version + 1 : (previous?.version ?? 0);
87
+ result = {
88
+ ...input,
89
+ path,
90
+ annotations: sourceChanged ? [] : (previous?.annotations ?? []),
91
+ revisions: sourceChanged ? [] : (previous?.revisions ?? []),
92
+ saveRequest: previous?.saveRequest ?? 0,
93
+ version: baselineVersion,
94
+ savedVersion: sourceChanged ? baselineVersion : (previous?.savedVersion ?? 0),
95
+ ...(sourceChanged || previous?.crop === undefined ? {} : { crop: previous.crop }),
96
+ };
97
+ const session = state.sessions[sessionId];
98
+ let sessions = state.sessions;
99
+ if (sourceChanged && session?.focusedDocument?.path === path) {
100
+ staleThumbnails.push(
101
+ ...(session.candidate?.thumbnailUrl === undefined ? [] : [session.candidate.thumbnailUrl]),
102
+ ...session.regions.flatMap((region) => (region.thumbnailUrl === undefined ? [] : [region.thumbnailUrl])),
103
+ );
104
+ const now = Date.now();
105
+ const generation = session.generation + 1;
106
+ sessions = {
107
+ ...sessions,
108
+ [sessionId]: {
109
+ ...session,
110
+ generation,
111
+ focusedDocument: {
112
+ path,
113
+ generation,
114
+ revision: baselineVersion,
115
+ sourceSha256: input.sourceSha256,
116
+ focusedAt: now,
117
+ },
118
+ regions: [],
119
+ candidate: undefined,
120
+ requests: session.requests.map((request) =>
121
+ request.documentPath === path &&
122
+ (request.status === 'REQUESTED' || request.status === 'CHANGING' || request.status === 'CHANGED')
123
+ ? {
124
+ ...request,
125
+ status: 'FAILED',
126
+ currentOperation: undefined,
127
+ error: 'The document source changed before the request completed.',
128
+ updatedAt: now,
129
+ }
130
+ : request,
131
+ ),
132
+ },
133
+ };
134
+ }
135
+ return { documents: { ...state.documents, [key]: result }, sessions };
136
+ });
137
+ staleThumbnails.forEach(revokeThumbnail);
138
+ return result;
139
+ }
140
+
141
+ /** Claims focus and returns a generation token that makes cleanup race-safe. */
142
+ export function focusAuthorDocument(sessionId: string, path: string, revision: number, sourceSha256?: string): number {
143
+ const normalized = normalizeAuthorPath(path);
144
+ const staleThumbnails: string[] = [];
145
+ let generation = 0;
146
+ authorWorkspace.update((state) => {
147
+ const session = state.sessions[sessionId] ?? EMPTY_SESSION;
148
+ generation = session.generation + 1;
149
+ const keepRegions = session.focusedDocument?.path === normalized;
150
+ if (!keepRegions) {
151
+ staleThumbnails.push(
152
+ ...(session.candidate?.thumbnailUrl === undefined ? [] : [session.candidate.thumbnailUrl]),
153
+ ...session.regions.flatMap((region) => (region.thumbnailUrl === undefined ? [] : [region.thumbnailUrl])),
154
+ );
155
+ }
156
+ return {
157
+ ...state,
158
+ sessions: {
159
+ ...state.sessions,
160
+ [sessionId]: {
161
+ ...session,
162
+ generation,
163
+ focusedDocument: {
164
+ path: normalized,
165
+ generation,
166
+ revision,
167
+ sourceSha256,
168
+ focusedAt: Date.now(),
169
+ },
170
+ regions: keepRegions ? session.regions : [],
171
+ candidate: keepRegions ? session.candidate : undefined,
172
+ },
173
+ },
174
+ };
175
+ });
176
+ staleThumbnails.forEach(revokeThumbnail);
177
+ return generation;
178
+ }
179
+
180
+ export function syncAuthorDocumentFocus(
181
+ sessionId: string,
182
+ generation: number,
183
+ revision: number,
184
+ sourceSha256?: string,
185
+ ): void {
186
+ updateSession(sessionId, (session) => {
187
+ const focused = session.focusedDocument;
188
+ if (focused === undefined || focused.generation !== generation) return session;
189
+ if (focused.revision === revision && focused.sourceSha256 === sourceSha256) return session;
190
+ return { ...session, focusedDocument: { ...focused, revision, sourceSha256 } };
191
+ });
192
+ }
193
+
194
+ export function releaseAuthorDocumentFocus(sessionId: string, generation: number): void {
195
+ const staleThumbnails: string[] = [];
196
+ updateSession(sessionId, (session) => {
197
+ if (session.focusedDocument?.generation !== generation) return session;
198
+ staleThumbnails.push(
199
+ ...(session.candidate?.thumbnailUrl === undefined ? [] : [session.candidate.thumbnailUrl]),
200
+ ...session.regions.flatMap((region) => (region.thumbnailUrl === undefined ? [] : [region.thumbnailUrl])),
201
+ );
202
+ return { ...session, focusedDocument: undefined, candidate: undefined, regions: [] };
203
+ });
204
+ staleThumbnails.forEach(revokeThumbnail);
205
+ }
206
+
207
+ export function seekAuthorVideo(sessionId: string, timeSeconds: number): boolean {
208
+ const workspace = authorSessionWorkspace(sessionId);
209
+ const focused = workspace.focusedDocument;
210
+ if (
211
+ !focused ||
212
+ workspace.candidate ||
213
+ !Number.isFinite(timeSeconds) ||
214
+ timeSeconds < 0 ||
215
+ authorDocument(sessionId, focused.path)?.kind !== 'video'
216
+ )
217
+ return false;
218
+ updateSession(sessionId, (session) => ({
219
+ ...session,
220
+ activeTool: 'select',
221
+ videoSeekRequest: {
222
+ path: focused.path,
223
+ generation: focused.generation,
224
+ timeSeconds,
225
+ sequence: (session.videoSeekRequest?.sequence ?? 0) + 1,
226
+ },
227
+ }));
228
+ return true;
229
+ }
230
+
231
+ export function setAuthorToolMode(sessionId: string, activeTool: AuthorToolMode): void {
232
+ updateSession(sessionId, (session) => (session.activeTool === activeTool ? session : { ...session, activeTool }));
233
+ }
234
+
235
+ export function setAuthorRegionCandidate(sessionId: string, candidate: AuthorRegionCandidate | undefined): void {
236
+ let staleThumbnail: string | undefined;
237
+ updateSession(sessionId, (session) => {
238
+ const focused = session.focusedDocument;
239
+ if (candidate !== undefined) {
240
+ if (focused === undefined || focused.path !== normalizeAuthorPath(candidate.documentPath)) {
241
+ throw new Error('The Author selection does not belong to the focused document.');
242
+ }
243
+ if (focused.revision !== candidate.revision || focused.sourceSha256 !== candidate.sourceSha256) {
244
+ throw new Error('The Author selection is stale for the focused document.');
245
+ }
246
+ }
247
+ staleThumbnail = session.candidate?.thumbnailUrl;
248
+ return { ...session, candidate: candidate === undefined ? undefined : structuredClone(candidate) };
249
+ });
250
+ if (staleThumbnail !== undefined && staleThumbnail !== candidate?.thumbnailUrl) revokeThumbnail(staleThumbnail);
251
+ }
252
+
253
+ export function commitAuthorRegion(sessionId: string, comment: string): string {
254
+ const id = crypto.randomUUID();
255
+ const session = authorSessionWorkspace(sessionId);
256
+ if (session.candidate === undefined) throw new Error('Select a document region before adding a comment.');
257
+ addAuthorRegion(sessionId, { ...session.candidate, id, comment });
258
+ updateSession(sessionId, (current) => ({ ...current, candidate: undefined }));
259
+ return id;
260
+ }
261
+
262
+ export function addAuthorRegion(sessionId: string, region: AuthorRegionDraft): void {
263
+ if (region.comment.trim() === '') throw new Error('Every Author region requires a comment.');
264
+ updateSession(sessionId, (session) => {
265
+ const focused = session.focusedDocument;
266
+ if (focused === undefined || focused.path !== normalizeAuthorPath(region.documentPath)) {
267
+ throw new Error('The Author region does not belong to the focused document.');
268
+ }
269
+ if (focused.revision !== region.revision || focused.sourceSha256 !== region.sourceSha256) {
270
+ throw new Error('The Author region is stale for the focused document.');
271
+ }
272
+ if (session.regions.length >= AUTHOR_REGION_LIMIT)
273
+ throw new Error(`Author requests support at most ${AUTHOR_REGION_LIMIT} regions.`);
274
+ if (session.regions.some((candidate) => candidate.id === region.id))
275
+ throw new Error(`Author region '${region.id}' already exists.`);
276
+ return { ...session, regions: [...session.regions, copyRegion(region)] };
277
+ });
278
+ }
279
+
280
+ export function removeAuthorRegion(sessionId: string, regionId: string): void {
281
+ let thumbnail: string | undefined;
282
+ updateSession(sessionId, (session) => {
283
+ const region = session.regions.find((candidate) => candidate.id === regionId);
284
+ thumbnail = region?.thumbnailUrl;
285
+ const regions = session.regions.filter((candidate) => candidate.id !== regionId);
286
+ return regions.length === session.regions.length ? session : { ...session, regions };
287
+ });
288
+ if (thumbnail !== undefined) revokeThumbnail(thumbnail);
289
+ }
290
+
291
+ export function updateAuthorRegionComment(sessionId: string, regionId: string, comment: string): void {
292
+ if (comment.trim() === '') throw new Error('Every Author region requires a comment.');
293
+ updateSession(sessionId, (session) => ({
294
+ ...session,
295
+ regions: session.regions.map((region) => (region.id === regionId ? { ...region, comment } : region)),
296
+ }));
297
+ }
298
+
299
+ export function putAuthorRequest(sessionId: string, record: AuthorRequestRecord): void {
300
+ if (record.requestText.trim() === '') throw new Error('An Author request requires verbatim request text.');
301
+ if (record.regions.length === 0 || record.regions.some((region) => region.comment.trim() === '')) {
302
+ throw new Error('An Author request requires at least one commented region.');
303
+ }
304
+ updateSession(sessionId, (session) => {
305
+ if (session.requests.some((request) => request.id === record.id))
306
+ throw new Error(`Author request '${record.id}' already exists.`);
307
+ return { ...session, requests: boundHistory([...session.requests, copyRequest(record)]) };
308
+ });
309
+ }
310
+
311
+ export function updateAuthorRequest(
312
+ sessionId: string,
313
+ requestId: string,
314
+ update: (record: AuthorRequestRecord) => AuthorRequestRecord,
315
+ ): void {
316
+ updateSession(sessionId, (session) => ({
317
+ ...session,
318
+ requests: boundHistory(
319
+ session.requests.map((request) => (request.id === requestId ? copyRequest(update(request)) : request)),
320
+ ),
321
+ }));
322
+ }
323
+
324
+ export function reviseAuthorDocument(sessionId: string, path: string, content: string): void {
325
+ updateDocument(sessionId, path, (document) => {
326
+ if (document.content === content) return document;
327
+ const version = document.version + 1;
328
+ return {
329
+ ...document,
330
+ content,
331
+ version,
332
+ revisions: [...document.revisions, { revision: version, content }],
333
+ };
334
+ });
335
+ }
336
+
337
+ export function reviseAuthorFragment(sessionId: string, path: string, fragmentId: string, text: string): void {
338
+ updateDocument(sessionId, path, (document) => {
339
+ const fragment = document.fragments?.find((candidate) => candidate.id === fragmentId);
340
+ if (fragment === undefined || fragment.text === text) return document;
341
+ const version = document.version + 1;
342
+ return {
343
+ ...document,
344
+ fragments: document.fragments?.map((fragment) => (fragment.id === fragmentId ? { ...fragment, text } : fragment)),
345
+ version,
346
+ revisions: [...document.revisions, { revision: version, content: text }],
347
+ };
348
+ });
349
+ }
350
+
351
+ export function addAuthorAnnotation(sessionId: string, path: string, annotation: AuthorAnnotation): void {
352
+ updateDocument(sessionId, path, (document) => ({ ...document, annotations: [...document.annotations, annotation] }));
353
+ }
354
+
355
+ export function setAuthorCrop(sessionId: string, path: string, crop: AuthorCrop | undefined): void {
356
+ updateDocument(sessionId, path, (document) => {
357
+ const version = document.version + 1;
358
+ return {
359
+ ...document,
360
+ ...(crop === undefined ? { crop: undefined } : { crop }),
361
+ version,
362
+ revisions: [...document.revisions, { revision: version, content: JSON.stringify(crop ?? null) }],
363
+ };
364
+ });
365
+ }
366
+
367
+ export function requestAuthorSave(sessionId: string, path: string): void {
368
+ updateDocument(sessionId, path, (document) => ({
369
+ ...document,
370
+ saveRequest: document.saveRequest + 1,
371
+ savingVersion: document.version,
372
+ }));
373
+ }
374
+
375
+ export function failAuthorSave(sessionId: string, path: string, savingVersion: number): void {
376
+ updateDocument(sessionId, path, (document) =>
377
+ document.savingVersion === savingVersion ? { ...document, savingVersion: undefined } : document,
378
+ );
379
+ }
380
+
381
+ export function completeAuthorSave(
382
+ sessionId: string,
383
+ path: string,
384
+ sourceSha256: string,
385
+ savedVersion: number,
386
+ savedFragments: AuthorDocumentInput['fragments'],
387
+ ): void {
388
+ updateDocument(sessionId, path, (document) => {
389
+ if (savedVersion < document.savedVersion) return document;
390
+ return {
391
+ ...document,
392
+ sourceSha256,
393
+ savedVersion,
394
+ savingVersion: document.savingVersion === savedVersion ? undefined : document.savingVersion,
395
+ originalFragments: savedFragments?.map((fragment) => ({ ...fragment })),
396
+ ...(document.version === savedVersion ? { crop: undefined } : {}),
397
+ revisions: document.revisions.filter((revision) => revision.revision > savedVersion),
398
+ };
399
+ });
400
+ const now = Date.now();
401
+ updateSession(sessionId, (session) => ({
402
+ ...session,
403
+ requests: boundHistory(
404
+ session.requests.map((request) =>
405
+ request.documentPath === normalizeAuthorPath(path) &&
406
+ request.status === 'CHANGED' &&
407
+ request.revision <= savedVersion
408
+ ? { ...request, status: 'COMPLETE', currentOperation: undefined, updatedAt: now }
409
+ : request,
410
+ ),
411
+ ),
412
+ }));
413
+ }
414
+
415
+ export function dropAuthorSession(sessionId: string): void {
416
+ const prefix = `${sessionId}\n`;
417
+ const session = authorWorkspace.store.state.sessions[sessionId];
418
+ if (session?.candidate?.thumbnailUrl !== undefined) revokeThumbnail(session.candidate.thumbnailUrl);
419
+ session?.regions.forEach((region) => {
420
+ if (region.thumbnailUrl !== undefined) revokeThumbnail(region.thumbnailUrl);
421
+ });
422
+ authorWorkspace.update((state) => {
423
+ const sessions = { ...state.sessions };
424
+ delete sessions[sessionId];
425
+ return {
426
+ documents: Object.fromEntries(Object.entries(state.documents).filter(([key]) => !key.startsWith(prefix))),
427
+ sessions,
428
+ };
429
+ });
430
+ }
431
+
432
+ function updateDocument(
433
+ sessionId: string,
434
+ path: string,
435
+ update: (document: AuthorWorkspaceDocument) => AuthorWorkspaceDocument,
436
+ ): void {
437
+ const key = authorDocumentKey(sessionId, path);
438
+ const staleThumbnails: string[] = [];
439
+ authorWorkspace.update((state) => {
440
+ const document = state.documents[key];
441
+ if (document === undefined) return state;
442
+ const next = update(document);
443
+ const session = state.sessions[sessionId];
444
+ const focused = session?.focusedDocument;
445
+ const identityChanged =
446
+ focused?.path === document.path &&
447
+ (focused.revision !== next.version || focused.sourceSha256 !== next.sourceSha256);
448
+ if (identityChanged) {
449
+ staleThumbnails.push(
450
+ ...(session.candidate?.thumbnailUrl === undefined ? [] : [session.candidate.thumbnailUrl]),
451
+ ...session.regions.flatMap((region) => (region.thumbnailUrl === undefined ? [] : [region.thumbnailUrl])),
452
+ );
453
+ }
454
+ const sessions = identityChanged
455
+ ? {
456
+ ...state.sessions,
457
+ [sessionId]: {
458
+ ...session,
459
+ focusedDocument: { ...focused, revision: next.version, sourceSha256: next.sourceSha256 },
460
+ candidate: undefined,
461
+ regions: [],
462
+ },
463
+ }
464
+ : state.sessions;
465
+ return { documents: { ...state.documents, [key]: next }, sessions };
466
+ });
467
+ staleThumbnails.forEach(revokeThumbnail);
468
+ }
469
+
470
+ function updateSession(sessionId: string, update: (session: AuthorSessionWorkspace) => AuthorSessionWorkspace): void {
471
+ authorWorkspace.update((state) => {
472
+ const session = state.sessions[sessionId] ?? EMPTY_SESSION;
473
+ const next = update(session);
474
+ return next === session ? state : { ...state, sessions: { ...state.sessions, [sessionId]: next } };
475
+ });
476
+ }
477
+
478
+ function copyRegion(region: AuthorRegionDraft): AuthorRegionDraft {
479
+ const anchor = 'rect' in region.anchor ? { ...region.anchor, rect: { ...region.anchor.rect } } : { ...region.anchor };
480
+ return {
481
+ ...region,
482
+ anchor,
483
+ viewport: { ...region.viewport },
484
+ voiceGrid: region.voiceGrid && { ...region.voiceGrid },
485
+ };
486
+ }
487
+
488
+ function boundedHistoryText(value: string | undefined): string | undefined {
489
+ if (value === undefined) return undefined;
490
+ const encoder = new TextEncoder();
491
+ if (encoder.encode(value).byteLength <= 16 * 1024) return value;
492
+ let end = value.length;
493
+ while (end > 0 && encoder.encode(value.slice(0, end)).byteLength > 16 * 1024) end -= 256;
494
+ return value.slice(0, end);
495
+ }
496
+
497
+ function copyRequest(record: AuthorRequestRecord): AuthorRequestRecord {
498
+ return {
499
+ ...record,
500
+ before: boundedHistoryText(record.before),
501
+ after: boundedHistoryText(record.after),
502
+ regions: record.regions.map(copyRegion),
503
+ pendingRegions: record.pendingRegions?.map(copyRegion),
504
+ };
505
+ }
506
+
507
+ function boundHistory(records: readonly AuthorRequestRecord[]): readonly AuthorRequestRecord[] {
508
+ const next = [...records];
509
+ const bytes = (): number => new TextEncoder().encode(JSON.stringify(next)).byteLength;
510
+ while (next.length > AUTHOR_HISTORY_RECORD_LIMIT || bytes() > AUTHOR_HISTORY_BYTE_LIMIT) {
511
+ const terminal = next.findIndex((record) => TERMINAL_REQUEST_STATUSES.has(record.status));
512
+ if (terminal < 0) throw new Error('Author request history is full while active requests are still running.');
513
+ next.splice(terminal, 1);
514
+ }
515
+ return next;
516
+ }
517
+
518
+ function revokeThumbnail(url: string): void {
519
+ if (!url.startsWith('blob:')) return;
520
+ try {
521
+ URL.revokeObjectURL(url);
522
+ } catch {
523
+ // Thumbnail cleanup must not make session teardown fail.
524
+ }
525
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "lib": ["ES2023", "DOM", "DOM.Iterable"],
5
+ "module": "ESNext",
6
+ "moduleResolution": "Bundler",
7
+ "jsx": "react-jsx",
8
+ "strict": true,
9
+ "noImplicitAny": true,
10
+ "noUnusedLocals": true,
11
+ "noUnusedParameters": true,
12
+ "noImplicitReturns": true,
13
+ "noFallthroughCasesInSwitch": true,
14
+ "noEmit": true,
15
+ "resolveJsonModule": true,
16
+ "esModuleInterop": true,
17
+ "skipLibCheck": true,
18
+ "allowImportingTsExtensions": true,
19
+ "forceConsistentCasingInFileNames": true
20
+ },
21
+ "include": [".", "../types", "../exports/webClient.ts", "../../tests/web"]
22
+ }