@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,179 @@
1
+ import type { AuthorNativeAnchor, AuthorRequestRecord } from '../lib/authorViewportTypes.ts';
2
+
3
+ const STATUS_LABELS: Record<AuthorRequestRecord['status'], string> = {
4
+ REQUESTED: 'Request queued',
5
+ CHANGING: 'Agent working',
6
+ CHANGED: 'Change ready',
7
+ COMPLETE: 'Request completed',
8
+ FAILED: 'Request failed',
9
+ CANCELLED: 'Request cancelled',
10
+ };
11
+
12
+ const STATUS_STYLES: Record<AuthorRequestRecord['status'], string> = {
13
+ REQUESTED: 'border-doom-yellow/35 bg-doom-yellow/5 text-doom-yellow',
14
+ CHANGING: 'border-doom-magenta/45 bg-doom-magenta/10 text-doom-yellow',
15
+ CHANGED: 'border-doom-cyan/40 bg-doom-cyan/5 text-doom-cyan',
16
+ COMPLETE: 'border-doom-green/40 bg-doom-green/5 text-doom-green',
17
+ FAILED: 'border-doom-red/45 bg-doom-red/10 text-doom-red',
18
+ CANCELLED: 'border-doom-border bg-doom-panel text-doom-dim',
19
+ };
20
+
21
+ function requestInstruction(requestText: string): string {
22
+ const referencedContext = requestText.search(/(?:^|\s+)Referenced context "/u);
23
+ return requestText
24
+ .slice(0, referencedContext < 0 ? undefined : referencedContext)
25
+ .replace(/^Please address the attached feedback\.\s*Request ID: \S+\s*/u, '')
26
+ .trim();
27
+ }
28
+
29
+ function documentName(path: string): string {
30
+ return path.replaceAll('\\', '/').split('/').at(-1) || path;
31
+ }
32
+
33
+ function anchorLabel(anchor: AuthorNativeAnchor): string {
34
+ switch (anchor.kind) {
35
+ case 'text-range':
36
+ return anchor.startLine === anchor.endLine
37
+ ? `Line ${anchor.startLine}`
38
+ : `Lines ${anchor.startLine}–${anchor.endLine}`;
39
+ case 'cell':
40
+ return [anchor.sheet, anchor.location].filter(Boolean).join(' · ');
41
+ case 'slide-element':
42
+ return `Slide ${anchor.slide} · ${anchor.location}`;
43
+ case 'image-rect':
44
+ return 'Image region';
45
+ case 'pdf-page-rect':
46
+ return `Page ${anchor.page}`;
47
+ case 'video-time-rect': {
48
+ const minutes = Math.floor(anchor.timeSeconds / 60);
49
+ const seconds = Math.floor(anchor.timeSeconds % 60)
50
+ .toString()
51
+ .padStart(2, '0');
52
+ return `Video ${minutes}:${seconds}`;
53
+ }
54
+ }
55
+ }
56
+
57
+ function progressLabel(request: AuthorRequestRecord): string {
58
+ const total = request.regions.length;
59
+ const pending = request.pendingRegions?.length;
60
+ if (request.status === 'CHANGING' && request.currentOperation === 'Agent is working on this request')
61
+ return 'Processing request';
62
+ if (request.status === 'CHANGING' && pending !== undefined) return `${total - pending} of ${total} regions applied`;
63
+ if (request.status === 'CHANGED') return 'Changes applied · awaiting save';
64
+ if (request.status === 'COMPLETE') return 'Agent finished processing this request';
65
+ if (request.status === 'FAILED') return 'Stopped with an error';
66
+ if (request.status === 'CANCELLED') return 'Stopped before completion';
67
+ return `${total} region${total === 1 ? '' : 's'} queued`;
68
+ }
69
+
70
+ function RequestRecord({ request, prominent = false }: { request: AuthorRequestRecord; prominent?: boolean }) {
71
+ const instruction = requestInstruction(request.requestText);
72
+ return (
73
+ <article data-testid={prominent ? 'author-active-request' : undefined} className="space-y-3">
74
+ <header className="border-b border-doom-border-soft pb-3">
75
+ <p className="text-[9px] font-bold tracking-[0.18em] text-doom-faint">DOCUMENT CONTEXT</p>
76
+ <p className="mt-2 flex items-center gap-2 truncate text-[13px] font-bold text-doom-hi">
77
+ <span aria-hidden className="text-doom-magenta">
78
+
79
+ </span>
80
+ {documentName(request.documentPath)}
81
+ </p>
82
+ </header>
83
+
84
+ <section aria-label="Request locations" className="rounded border border-doom-border bg-doom-panel p-3">
85
+ <ol className="space-y-3">
86
+ {request.regions.map((region, index) => (
87
+ <li key={region.id} className="space-y-2">
88
+ <p className="font-mono text-[9px] font-bold uppercase tracking-[0.14em] text-doom-yellow">
89
+ WHERE · {request.regions.length > 1 ? `${index + 1} · ` : ''}
90
+ {documentName(request.documentPath)} / {anchorLabel(region.anchor)} · rev {request.revision}
91
+ </p>
92
+ {region.quote ? (
93
+ <blockquote className="line-clamp-3 text-[11px] italic leading-relaxed text-doom-text">
94
+ “{region.quote}”
95
+ </blockquote>
96
+ ) : null}
97
+ <p className="text-[10px] leading-relaxed text-doom-dim">{region.comment}</p>
98
+ </li>
99
+ ))}
100
+ </ol>
101
+ </section>
102
+
103
+ <section
104
+ data-testid={prominent ? 'author-operation-card' : undefined}
105
+ className={`rounded border p-3 ${STATUS_STYLES[request.status]}`}
106
+ >
107
+ <p className="font-mono text-[10px] font-bold tracking-[0.14em]">
108
+ ●{' '}
109
+ {request.status === 'CHANGING'
110
+ ? 'WORKING'
111
+ : request.status === 'COMPLETE'
112
+ ? 'COMPLETED'
113
+ : request.status === 'FAILED'
114
+ ? 'ERROR'
115
+ : request.status}
116
+ </p>
117
+ <p className="mt-2 text-[12px] leading-relaxed text-doom-hi">
118
+ {request.currentOperation || STATUS_LABELS[request.status]}
119
+ </p>
120
+ {request.error ? <p className="mt-2 text-[10px] leading-relaxed text-doom-red">{request.error}</p> : null}
121
+ {request.before !== undefined || request.after !== undefined ? (
122
+ <details className="mt-2 border-t border-current/20 pt-2 text-[10px] text-doom-dim">
123
+ <summary className="cursor-pointer select-none">change preview</summary>
124
+ {request.before !== undefined ? (
125
+ <pre className="mt-2 max-h-28 overflow-auto whitespace-pre-wrap break-words font-mono">
126
+ before: {request.before}
127
+ </pre>
128
+ ) : null}
129
+ {request.after !== undefined ? (
130
+ <pre className="mt-2 max-h-28 overflow-auto whitespace-pre-wrap break-words font-mono">
131
+ after: {request.after}
132
+ </pre>
133
+ ) : null}
134
+ </details>
135
+ ) : null}
136
+ </section>
137
+
138
+ <section className="space-y-2">
139
+ <p className="text-[9px] font-bold tracking-[0.18em] text-doom-faint">REQUEST · HOW TO CHANGE</p>
140
+ <div className="rounded border border-doom-border bg-doom-deep p-3">
141
+ <p className="whitespace-pre-wrap text-[11px] leading-relaxed text-doom-text">
142
+ {instruction || 'No additional instruction.'}
143
+ </p>
144
+ </div>
145
+ </section>
146
+
147
+ <footer className="font-mono text-[9px] text-doom-dim">{progressLabel(request)}</footer>
148
+ </article>
149
+ );
150
+ }
151
+
152
+ export function AuthorRequestLog({ requests }: { requests: readonly AuthorRequestRecord[] }) {
153
+ const latest = requests.at(-1);
154
+ const earlier = requests.slice(0, -1).toReversed();
155
+ return (
156
+ <section data-testid="author-request-history" className="space-y-3">
157
+ <h3 className="text-[9px] font-bold tracking-[0.18em] text-doom-faint">AUTHORING</h3>
158
+ {latest === undefined ? (
159
+ <p className="text-[11px] leading-relaxed text-doom-dim">No requests or changes yet.</p>
160
+ ) : (
161
+ <RequestRecord request={latest} prominent />
162
+ )}
163
+ {earlier.length > 0 ? (
164
+ <details className="border-t border-doom-border-soft pt-3" data-testid="author-earlier-requests">
165
+ <summary className="cursor-pointer select-none text-[9px] font-bold tracking-[0.14em] text-doom-faint">
166
+ EARLIER REQUESTS ({earlier.length})
167
+ </summary>
168
+ <ol className="mt-3 space-y-5">
169
+ {earlier.map((request) => (
170
+ <li key={request.id}>
171
+ <RequestRecord request={request} />
172
+ </li>
173
+ ))}
174
+ </ol>
175
+ </details>
176
+ ) : null}
177
+ </section>
178
+ );
179
+ }
@@ -0,0 +1,121 @@
1
+ import { Button } from '@agimon-ai/doompi-web-components';
2
+ import { useEffect } from 'react';
3
+ import type { DocumentFragment } from '../../types/structuredDocuments.ts';
4
+ import type { AuthorDisplayedRegion } from '../lib/authorViewportTypes.ts';
5
+ import { registerAuthorGridResolver } from '../lib/authorGrid.ts';
6
+ import {
7
+ reviseAuthorFragment,
8
+ setAuthorRegionCandidate,
9
+ type AuthorWorkspaceDocument,
10
+ } from '../stores/authorWorkspaceStore.ts';
11
+
12
+ export function AuthorStructuredView({
13
+ sessionId,
14
+ document,
15
+ displayedRegions,
16
+ }: {
17
+ sessionId: string;
18
+ document: AuthorWorkspaceDocument;
19
+ displayedRegions: readonly AuthorDisplayedRegion[];
20
+ }) {
21
+ useEffect(
22
+ () =>
23
+ registerAuthorGridResolver(sessionId, (cell, geometry) => {
24
+ const { originX = 0, originY = 0, width, height } = geometry.viewport;
25
+ const element = window.document.elementFromPoint(
26
+ originX + cell.center.x * width,
27
+ originY + cell.center.y * height,
28
+ );
29
+ const fragmentId = element?.closest<HTMLElement>('[data-author-fragment]')?.dataset.authorFragment;
30
+ const fragment = document.fragments?.find((candidate) => candidate.id === fragmentId);
31
+ if (fragment === undefined || fragment.readOnly === true) return undefined;
32
+ if (document.kind === 'csv' || document.kind === 'xlsx') {
33
+ return {
34
+ anchor: { kind: 'cell', fragmentId: fragment.id, location: fragment.location },
35
+ quote: fragment.text,
36
+ };
37
+ }
38
+ const slide = Number(fragment.location.match(/(?:slide\s*|slides\/slide)(\d+)/u)?.[1]);
39
+ if (!Number.isSafeInteger(slide)) return undefined;
40
+ return {
41
+ anchor: { kind: 'slide-element', fragmentId: fragment.id, location: fragment.location, slide },
42
+ quote: fragment.text,
43
+ };
44
+ }),
45
+ [document.fragments, document.kind, document.version, sessionId],
46
+ );
47
+ const displayedByFragment = new Map(
48
+ displayedRegions.flatMap(({ ordinal, region }) =>
49
+ region.anchor.kind === 'cell' || region.anchor.kind === 'slide-element'
50
+ ? [[region.anchor.fragmentId, ordinal] as const]
51
+ : [],
52
+ ),
53
+ );
54
+ const cells = document.kind === 'csv' || document.kind === 'xlsx';
55
+ const groups = new Map<string, DocumentFragment[]>();
56
+ for (const fragment of document.fragments ?? []) {
57
+ const key = cells
58
+ ? document.kind === 'csv'
59
+ ? fragment.location.split(',')[0]!
60
+ : fragment.location.replace(/![A-Z]+(\d+)$/, '!row $1')
61
+ : fragment.location;
62
+ const group = groups.get(key) ?? [];
63
+ group.push(fragment);
64
+ groups.set(key, group);
65
+ }
66
+ return (
67
+ <div data-testid="author-structured" className="min-h-0 flex-1 space-y-3 overflow-auto p-4">
68
+ {!cells ? <p className="text-[10px] text-doom-faint">Slide text view, not a layout-faithful rendering.</p> : null}
69
+ {[...groups].map(([location, fragments]) => (
70
+ <section key={location} className="space-y-1">
71
+ <h3 className="text-[10px] text-doom-faint">{location}</h3>
72
+ <div className={cells ? 'flex gap-1' : 'space-y-2'}>
73
+ {fragments.map((fragment) => (
74
+ <div
75
+ key={fragment.id}
76
+ data-author-fragment={fragment.id}
77
+ data-author-region={displayedByFragment.get(fragment.id)}
78
+ className={`${cells ? 'w-40 shrink-0' : ''} relative rounded ${displayedByFragment.has(fragment.id) ? 'ring-1 ring-doom-yellow' : ''}`}
79
+ >
80
+ {displayedByFragment.has(fragment.id) ? (
81
+ <span className="absolute -left-1 -top-1 z-10 flex h-4 min-w-4 items-center justify-center rounded-full bg-doom-yellow px-1 text-[9px] font-bold text-doom-deep">
82
+ {displayedByFragment.get(fragment.id)}
83
+ </span>
84
+ ) : null}
85
+ <Button
86
+ size="xs"
87
+ variant="ghost"
88
+ onClick={(event) => {
89
+ const bounds = event.currentTarget.getBoundingClientRect();
90
+ const slide = Number(fragment.location.match(/(?:slide\s*|slides\/slide)(\d+)/)?.[1]);
91
+ if (!cells && !Number.isSafeInteger(slide)) return;
92
+ setAuthorRegionCandidate(sessionId, {
93
+ documentPath: document.path,
94
+ revision: document.version,
95
+ sourceSha256: document.sourceSha256,
96
+ quote: fragment.text,
97
+ anchor: cells
98
+ ? { kind: 'cell', fragmentId: fragment.id, location: fragment.location }
99
+ : { kind: 'slide-element', fragmentId: fragment.id, location: fragment.location, slide },
100
+ viewport: { width: bounds.width, height: bounds.height },
101
+ createdAt: Date.now(),
102
+ });
103
+ }}
104
+ >
105
+ mark {fragment.location}
106
+ </Button>
107
+ <textarea
108
+ aria-label={fragment.location}
109
+ value={fragment.text}
110
+ readOnly={fragment.readOnly === true}
111
+ className="w-full rounded border border-doom-border bg-doom-deep p-2 text-[11px] text-doom-text"
112
+ onChange={(event) => reviseAuthorFragment(sessionId, document.path, fragment.id, event.target.value)}
113
+ />
114
+ </div>
115
+ ))}
116
+ </div>
117
+ </section>
118
+ ))}
119
+ </div>
120
+ );
121
+ }
@@ -0,0 +1,97 @@
1
+ import { CodeEditor, Markdown, type CodeEditorController } from '@agimon-ai/doompi-web-components';
2
+ import { useEffect, useRef } from 'react';
3
+ import type { AuthorDisplayedRegion } from '../lib/authorViewportTypes.ts';
4
+ import { registerAuthorGridResolver } from '../lib/authorGrid.ts';
5
+ import {
6
+ authorDocument,
7
+ reviseAuthorDocument,
8
+ setAuthorRegionCandidate,
9
+ type AuthorWorkspaceDocument,
10
+ } from '../stores/authorWorkspaceStore.ts';
11
+
12
+ export function AuthorTextView({
13
+ sessionId,
14
+ document,
15
+ preview,
16
+ displayedRegions,
17
+ }: {
18
+ sessionId: string;
19
+ document: AuthorWorkspaceDocument;
20
+ preview: boolean;
21
+ displayedRegions: readonly AuthorDisplayedRegion[];
22
+ }) {
23
+ const host = useRef<HTMLDivElement>(null);
24
+ const editor = useRef<CodeEditorController>(null);
25
+ useEffect(
26
+ () =>
27
+ registerAuthorGridResolver(sessionId, (cell, geometry) => {
28
+ if (preview || editor.current === null) return undefined;
29
+ const { originX = 0, originY = 0, width, height } = geometry.viewport;
30
+ const range = editor.current.resolveViewportRegion({
31
+ left: originX + cell.rect.x * width,
32
+ top: originY + cell.rect.y * height,
33
+ right: originX + (cell.rect.x + cell.rect.width) * width,
34
+ bottom: originY + (cell.rect.y + cell.rect.height) * height,
35
+ });
36
+ if (range === null || range.from === range.to) return undefined;
37
+ return {
38
+ anchor: {
39
+ kind: 'text-range',
40
+ startOffset: range.from,
41
+ endOffset: range.to,
42
+ startLine: range.startLine,
43
+ endLine: range.endLine,
44
+ },
45
+ quote: range.text,
46
+ };
47
+ }),
48
+ [preview, sessionId],
49
+ );
50
+ useEffect(() => {
51
+ editor.current?.setMarkedRanges(
52
+ displayedRegions.flatMap(({ ordinal, region }) =>
53
+ region.anchor.kind === 'text-range'
54
+ ? [{ from: region.anchor.startOffset, to: region.anchor.endOffset, label: String(ordinal) }]
55
+ : [],
56
+ ),
57
+ );
58
+ }, [displayedRegions]);
59
+ return (
60
+ <div ref={host} className="flex min-h-0 flex-1 flex-col">
61
+ {preview ? (
62
+ <div data-testid="author-markdown" className="min-h-0 flex-1 overflow-auto p-4 text-[12px] text-doom-text">
63
+ <Markdown text={document.content ?? ''} />
64
+ </div>
65
+ ) : (
66
+ <CodeEditor
67
+ value={document.content ?? ''}
68
+ path={document.path}
69
+ data-testid="author-editor"
70
+ controllerRef={editor}
71
+ className="min-h-0 flex-1"
72
+ onChange={(content) => reviseAuthorDocument(sessionId, document.path, content)}
73
+ onSelect={(range) => {
74
+ const current = authorDocument(sessionId, document.path);
75
+ const bounds = host.current?.getBoundingClientRect();
76
+ if (!current || !bounds || range.from === range.to) return;
77
+ setAuthorRegionCandidate(sessionId, {
78
+ documentPath: current.path,
79
+ revision: current.version,
80
+ sourceSha256: current.sourceSha256,
81
+ quote: range.text,
82
+ anchor: {
83
+ kind: 'text-range',
84
+ startOffset: range.from,
85
+ endOffset: range.to,
86
+ startLine: range.startLine,
87
+ endLine: range.endLine,
88
+ },
89
+ viewport: { width: bounds.width, height: bounds.height },
90
+ createdAt: Date.now(),
91
+ });
92
+ }}
93
+ />
94
+ )}
95
+ </div>
96
+ );
97
+ }
@@ -0,0 +1,103 @@
1
+ import { Button } from '@agimon-ai/doompi-web-components';
2
+ import { useState } from 'react';
3
+ import type { AuthorDocumentKind, AuthorToolMode } from '../lib/authorViewportTypes.ts';
4
+ import {
5
+ authorDocument,
6
+ authorSessionWorkspace,
7
+ reviseAuthorDocument,
8
+ setAuthorRegionCandidate,
9
+ setAuthorToolMode,
10
+ } from '../stores/authorWorkspaceStore.ts';
11
+
12
+ export function AuthorToolPalette({
13
+ sessionId,
14
+ kind,
15
+ activeTool,
16
+ }: {
17
+ sessionId: string;
18
+ kind: AuthorDocumentKind;
19
+ activeTool: AuthorToolMode;
20
+ }) {
21
+ const [error, setError] = useState<string>();
22
+ const format = (style: 'Bold' | 'Heading' | 'Link' | 'List') => {
23
+ const session = authorSessionWorkspace(sessionId);
24
+ const selected = session.candidate;
25
+ const document = selected && authorDocument(sessionId, selected.documentPath);
26
+ if (
27
+ !selected ||
28
+ !document ||
29
+ selected.anchor.kind !== 'text-range' ||
30
+ selected.revision !== document.version ||
31
+ selected.sourceSha256 !== document.sourceSha256
32
+ ) {
33
+ setError('Select text in the document first.');
34
+ return;
35
+ }
36
+ const { startOffset, endOffset } = selected.anchor;
37
+ const content = document.content ?? '';
38
+ const text = content.slice(startOffset, endOffset);
39
+ const replacement =
40
+ style === 'Bold'
41
+ ? `**${text}**`
42
+ : style === 'Link'
43
+ ? `[${text}](https://)`
44
+ : text
45
+ .split('\n')
46
+ .map((line) => `${style === 'Heading' ? '## ' : '- '}${line}`)
47
+ .join('\n');
48
+ reviseAuthorDocument(
49
+ sessionId,
50
+ document.path,
51
+ content.slice(0, startOffset) + replacement + content.slice(endOffset),
52
+ );
53
+ setAuthorRegionCandidate(sessionId, undefined);
54
+ setError(undefined);
55
+ };
56
+ const tools = [
57
+ {
58
+ label: 'Region',
59
+ glyph: '⌗',
60
+ action: () => setAuthorToolMode(sessionId, activeTool === 'mark' ? 'select' : 'mark'),
61
+ active: activeTool === 'mark',
62
+ },
63
+ ...(kind === 'markdown'
64
+ ? [
65
+ { label: 'Bold', glyph: 'B', action: () => format('Bold') },
66
+ { label: 'Heading', glyph: 'H', action: () => format('Heading') },
67
+ { label: 'Link', glyph: '↗', action: () => format('Link') },
68
+ { label: 'List', glyph: '≡', action: () => format('List') },
69
+ ]
70
+ : []),
71
+ { label: 'Comment', glyph: '□', action: () => setAuthorToolMode(sessionId, 'mark') },
72
+ ];
73
+ return (
74
+ <section data-testid="author-tool-palette" className="space-y-2 border-b border-doom-border-soft pb-3">
75
+ <div className="flex justify-between text-xs text-doom-dim">
76
+ <h3 className="font-bold tracking-widest">TOOLS</h3>
77
+ <span>focused tab</span>
78
+ </div>
79
+ <div className="grid grid-cols-3 gap-1.5">
80
+ {tools.map((tool) => (
81
+ <Button
82
+ key={tool.label}
83
+ size="md"
84
+ variant="outline"
85
+ aria-label={tool.label === 'Region' ? 'mark region' : tool.label}
86
+ aria-pressed={tool.active}
87
+ onClick={tool.action}
88
+ className={`min-h-11 min-w-11 gap-1.5 rounded border text-sm [@media(pointer:fine)]:min-h-8 sm:text-xs ${tool.active ? 'border-doom-red bg-doom-red/10 text-doom-red hover:bg-doom-red/15' : 'border-doom-border bg-doom-panel text-doom-dim'}`}
89
+ >
90
+ <span aria-hidden="true">{tool.glyph}</span>
91
+ {tool.label}
92
+ </Button>
93
+ ))}
94
+ </div>
95
+ <p className="text-sm leading-normal text-doom-dim sm:text-xs">
96
+ {activeTool === 'mark'
97
+ ? 'Drag over the document to mark a region.'
98
+ : 'Choose Region to mark an area for a comment.'}
99
+ </p>
100
+ {error ? <output className="block text-sm text-doom-red">{error}</output> : null}
101
+ </section>
102
+ );
103
+ }
@@ -0,0 +1,111 @@
1
+ import { Button, type MediaPlaybackState } from '@agimon-ai/doompi-web-components';
2
+ import { useState } from 'react';
3
+
4
+ export function videoTimeLabel(seconds: number): string {
5
+ const milliseconds = Math.max(0, Math.round((Number.isFinite(seconds) ? seconds : 0) * 1000));
6
+ return `${String(Math.floor(milliseconds / 60000)).padStart(2, '0')}:${String(Math.floor(milliseconds / 1000) % 60).padStart(2, '0')}.${String(milliseconds % 1000).padStart(3, '0')}`;
7
+ }
8
+
9
+ export function AuthorVideoControls({
10
+ playback,
11
+ ready,
12
+ locked,
13
+ marking,
14
+ onSeek,
15
+ onToggle,
16
+ onAnnotate,
17
+ }: {
18
+ playback: MediaPlaybackState;
19
+ ready: boolean;
20
+ locked: boolean;
21
+ marking: boolean;
22
+ onSeek: (seconds: number) => void;
23
+ onToggle: () => void;
24
+ onAnnotate: () => void;
25
+ }) {
26
+ const [seconds, setSeconds] = useState('');
27
+ const duration = playback.duration;
28
+ const invalid =
29
+ seconds.trim() === '' || !Number.isFinite(Number(seconds)) || Number(seconds) < 0 || Number(seconds) > duration;
30
+ const buttonClass = 'min-h-11 px-3 text-sm [@media(pointer:fine)]:min-h-8 sm:text-xs';
31
+ return (
32
+ <section
33
+ aria-label="Video annotation controls"
34
+ className="mt-2 space-y-2 rounded border border-doom-border bg-doom-panel p-2.5 text-sm text-doom-text sm:text-xs"
35
+ >
36
+ <div className="flex flex-wrap items-center justify-between gap-3">
37
+ <output aria-label="Playback position" className="font-mono text-sm tabular-nums">
38
+ {videoTimeLabel(playback.currentTime)} / {videoTimeLabel(duration)}
39
+ </output>
40
+ <span className="text-doom-dim">
41
+ {locked
42
+ ? 'Annotation draft: add or discard it before seeking.'
43
+ : marking
44
+ ? 'Frame paused. Drag a region on the video.'
45
+ : 'Seek to a moment, then choose Annotate this frame.'}
46
+ </span>
47
+ </div>
48
+ <input
49
+ aria-label="Video timeline"
50
+ type="range"
51
+ min={0}
52
+ max={duration || 0}
53
+ step={0.001}
54
+ value={Math.min(playback.currentTime, duration)}
55
+ disabled={locked || duration <= 0}
56
+ onChange={(event) => onSeek(Number(event.target.value))}
57
+ className="h-11 w-full cursor-pointer accent-doom-blue [@media(pointer:fine)]:h-6"
58
+ />
59
+ <div className="flex flex-wrap items-center gap-2">
60
+ <Button className={buttonClass} disabled={locked || duration <= 0} onClick={onToggle}>
61
+ {playback.playing ? 'Pause' : 'Play'}
62
+ </Button>
63
+ <Button
64
+ className={buttonClass}
65
+ disabled={locked || duration <= 0}
66
+ onClick={() => onSeek(Math.max(0, playback.currentTime - 0.1))}
67
+ aria-label="Seek back 0.1 seconds"
68
+ >
69
+ −0.1s
70
+ </Button>
71
+ <Button
72
+ className={buttonClass}
73
+ disabled={locked || duration <= 0}
74
+ onClick={() => onSeek(Math.min(duration, playback.currentTime + 0.1))}
75
+ aria-label="Seek forward 0.1 seconds"
76
+ >
77
+ +0.1s
78
+ </Button>
79
+ <Button variant="primary" className={buttonClass} disabled={locked || !ready} onClick={onAnnotate}>
80
+ Annotate this frame
81
+ </Button>
82
+ <form
83
+ className="flex flex-wrap items-center gap-2 sm:ml-auto"
84
+ onSubmit={(event) => {
85
+ event.preventDefault();
86
+ if (!invalid && !locked) onSeek(Number(seconds));
87
+ }}
88
+ >
89
+ <label htmlFor="author-video-seconds" className="text-doom-dim">
90
+ Go to seconds
91
+ </label>
92
+ <input
93
+ id="author-video-seconds"
94
+ type="number"
95
+ min={0}
96
+ max={duration}
97
+ step={0.001}
98
+ value={seconds}
99
+ onChange={(event) => setSeconds(event.target.value)}
100
+ disabled={locked || duration <= 0}
101
+ placeholder="1.250"
102
+ className="h-11 w-24 rounded border border-doom-border bg-doom-deep px-2 text-base [@media(pointer:fine)]:h-8 sm:text-xs"
103
+ />
104
+ <Button type="submit" className={buttonClass} disabled={locked || duration <= 0 || invalid}>
105
+ Go
106
+ </Button>
107
+ </form>
108
+ </div>
109
+ </section>
110
+ );
111
+ }
@@ -0,0 +1,50 @@
1
+ import {
2
+ collapseLines,
3
+ MessageItem,
4
+ MessageItemBody,
5
+ MessageItemHeader,
6
+ MessageItemStatus,
7
+ MessageLines,
8
+ toolTone,
9
+ } from '@agimon-ai/doompi-web-components';
10
+ import type { ToolMessageRenderProps } from '@agimon-ai/doompi-web-contracts';
11
+ import {
12
+ describeAuthorToolsCallSummary,
13
+ describeAuthorToolsCollapsedLines,
14
+ describeAuthorToolsResultLines,
15
+ } from '../lib/describeAuthorToolsToolRender.ts';
16
+
17
+ /**
18
+ * The describe_author_tools tool's timeline item: Describe the current Author viewport capabilities. The shell owns
19
+ * the frame, the outcome tone, the status badge, and the expand toggle; this
20
+ * card supplies the header summary and the body lines, and says whether it
21
+ * hides any so the toggle appears only when it reveals something.
22
+ */
23
+ export function DescribeAuthorToolsToolCard({ toolName, args, result, running, isError }: ToolMessageRenderProps) {
24
+ const lines = describeAuthorToolsResultLines(result);
25
+ const collapsed = collapseLines(lines, describeAuthorToolsCollapsedLines, false);
26
+ return (
27
+ <MessageItem tone={toolTone({ running, isError })} expandable={collapsed.hidden > 0}>
28
+ {({ expanded }) => {
29
+ const view = expanded ? collapseLines(lines, describeAuthorToolsCollapsedLines, true) : collapsed;
30
+ return (
31
+ <>
32
+ <MessageItemHeader title={toolName}>
33
+ <span data-testid={`tool-call-${toolName}`} className="min-w-0 flex-1 truncate text-doom-text">
34
+ {describeAuthorToolsCallSummary(args)}
35
+ </span>
36
+ </MessageItemHeader>
37
+ {view.shown.length > 0 || running || isError ? (
38
+ <MessageItemBody data-testid={`tool-result-${toolName}`} className="flex flex-col gap-1">
39
+ {view.shown.length > 0 ? <MessageLines lines={view.shown} /> : null}
40
+ {view.hidden > 0 ? <MessageItemStatus expands>{view.hidden} more line(s)</MessageItemStatus> : null}
41
+ {running ? <MessageItemStatus tone="running">running</MessageItemStatus> : null}
42
+ {isError ? <MessageItemStatus tone="error">failed</MessageItemStatus> : null}
43
+ </MessageItemBody>
44
+ ) : null}
45
+ </>
46
+ );
47
+ }}
48
+ </MessageItem>
49
+ );
50
+ }