dominds 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (273) hide show
  1. package/LICENSE +157 -0
  2. package/README.md +250 -0
  3. package/README.zh.md +161 -0
  4. package/dist/access-control.js +253 -0
  5. package/dist/cli/create.js +263 -0
  6. package/dist/cli/read.js +84 -0
  7. package/dist/cli/tui.js +199 -0
  8. package/dist/cli/webui.js +169 -0
  9. package/dist/cli.js +227 -0
  10. package/dist/dialog-factory.js +53 -0
  11. package/dist/dialog-global-registry.js +68 -0
  12. package/dist/dialog-instance-registry.js +78 -0
  13. package/dist/dialog-run-state.js +198 -0
  14. package/dist/dialog.js +1024 -0
  15. package/dist/evt-registry.js +103 -0
  16. package/dist/index.js +8 -0
  17. package/dist/llm/client.js +69 -0
  18. package/dist/llm/defaults.yaml +386 -0
  19. package/dist/llm/driver.js +3214 -0
  20. package/dist/llm/gen/anthropic.js +611 -0
  21. package/dist/llm/gen/codex.js +375 -0
  22. package/dist/llm/gen/mock.js +326 -0
  23. package/dist/llm/gen/openai.js +470 -0
  24. package/dist/llm/gen/registry.js +26 -0
  25. package/dist/llm/gen.js +2 -0
  26. package/dist/llm/tools-projection.js +37 -0
  27. package/dist/log.js +228 -0
  28. package/dist/mcp/config.js +230 -0
  29. package/dist/mcp/sdk-client.js +129 -0
  30. package/dist/mcp/server-runtime.js +57 -0
  31. package/dist/mcp/stdio-client.js +280 -0
  32. package/dist/mcp/supervisor.js +979 -0
  33. package/dist/mcp/tool-names.js +109 -0
  34. package/dist/minds/builtin/cmdr/persona.md +3 -0
  35. package/dist/minds/builtin/dijiang/knowledge.md +287 -0
  36. package/dist/minds/builtin/dijiang/persona.md +7 -0
  37. package/dist/minds/builtin/fuxi/persona.en.md +59 -0
  38. package/dist/minds/builtin/fuxi/persona.zh.md +49 -0
  39. package/dist/minds/builtin/pangu/persona.en.md +78 -0
  40. package/dist/minds/builtin/pangu/persona.zh.md +71 -0
  41. package/dist/minds/load.js +617 -0
  42. package/dist/minds/minds-i18n.js +131 -0
  43. package/dist/minds/system-prompt.js +281 -0
  44. package/dist/persistence.js +3128 -0
  45. package/dist/problems.js +109 -0
  46. package/dist/server/api-routes.js +1031 -0
  47. package/dist/server/auth.js +180 -0
  48. package/dist/server/mime-types.js +32 -0
  49. package/dist/server/prompts-routes.js +543 -0
  50. package/dist/server/server-core.js +235 -0
  51. package/dist/server/setup-routes.js +697 -0
  52. package/dist/server/static-server.js +132 -0
  53. package/dist/server/websocket-handler.js +1011 -0
  54. package/dist/server.js +164 -0
  55. package/dist/shared/async-fifo-mutex.js +36 -0
  56. package/dist/shared/diligence.js +20 -0
  57. package/dist/shared/dotenv.js +144 -0
  58. package/dist/shared/evt.js +195 -0
  59. package/dist/shared/i18n/driver-messages.js +267 -0
  60. package/dist/shared/i18n/text.js +9 -0
  61. package/dist/shared/i18n/tool-result-messages.js +51 -0
  62. package/dist/shared/rtws-cli.js +73 -0
  63. package/dist/shared/runtime-language.js +47 -0
  64. package/dist/shared/team-mgmt-manual.js +116 -0
  65. package/dist/shared/types/context-health.js +2 -0
  66. package/dist/shared/types/dialog.js +11 -0
  67. package/dist/shared/types/i18n.js +2 -0
  68. package/dist/shared/types/index.js +26 -0
  69. package/dist/shared/types/language.js +40 -0
  70. package/dist/shared/types/problems.js +2 -0
  71. package/dist/shared/types/prompts.js +2 -0
  72. package/dist/shared/types/q4h.js +7 -0
  73. package/dist/shared/types/run-state.js +8 -0
  74. package/dist/shared/types/setup.js +2 -0
  75. package/dist/shared/types/storage.js +10 -0
  76. package/dist/shared/types/tellask.js +8 -0
  77. package/dist/shared/types/tools-registry.js +2 -0
  78. package/dist/shared/types/wire.js +12 -0
  79. package/dist/shared/utils/fmt.js +9 -0
  80. package/dist/shared/utils/html.js +20 -0
  81. package/dist/shared/utils/id.js +18 -0
  82. package/dist/shared/utils/inter-dialog-format.js +101 -0
  83. package/dist/shared/utils/time.js +13 -0
  84. package/dist/static/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  85. package/dist/static/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  86. package/dist/static/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  87. package/dist/static/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  88. package/dist/static/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  89. package/dist/static/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  90. package/dist/static/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  91. package/dist/static/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  92. package/dist/static/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  93. package/dist/static/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  94. package/dist/static/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  95. package/dist/static/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  96. package/dist/static/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  97. package/dist/static/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  98. package/dist/static/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  99. package/dist/static/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  100. package/dist/static/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  101. package/dist/static/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  102. package/dist/static/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  103. package/dist/static/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  104. package/dist/static/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  105. package/dist/static/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  106. package/dist/static/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  107. package/dist/static/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  108. package/dist/static/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  109. package/dist/static/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  110. package/dist/static/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  111. package/dist/static/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  112. package/dist/static/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  113. package/dist/static/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  114. package/dist/static/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  115. package/dist/static/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  116. package/dist/static/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  117. package/dist/static/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  118. package/dist/static/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  119. package/dist/static/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  120. package/dist/static/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  121. package/dist/static/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  122. package/dist/static/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  123. package/dist/static/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  124. package/dist/static/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  125. package/dist/static/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  126. package/dist/static/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  127. package/dist/static/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  128. package/dist/static/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  129. package/dist/static/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  130. package/dist/static/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  131. package/dist/static/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  132. package/dist/static/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  133. package/dist/static/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  134. package/dist/static/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  135. package/dist/static/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  136. package/dist/static/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  137. package/dist/static/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  138. package/dist/static/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  139. package/dist/static/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  140. package/dist/static/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  141. package/dist/static/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  142. package/dist/static/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  143. package/dist/static/assets/_baseUniq-Crfl3d5Y.js +661 -0
  144. package/dist/static/assets/_baseUniq-Crfl3d5Y.js.map +1 -0
  145. package/dist/static/assets/arc-CbA_x9GD.js +132 -0
  146. package/dist/static/assets/arc-CbA_x9GD.js.map +1 -0
  147. package/dist/static/assets/architectureDiagram-VXUJARFQ-lcFS8ZQJ.js +8685 -0
  148. package/dist/static/assets/architectureDiagram-VXUJARFQ-lcFS8ZQJ.js.map +1 -0
  149. package/dist/static/assets/blockDiagram-VD42YOAC-B3Q36qRc.js +3608 -0
  150. package/dist/static/assets/blockDiagram-VD42YOAC-B3Q36qRc.js.map +1 -0
  151. package/dist/static/assets/c4Diagram-YG6GDRKO-Mt-aq3VH.js +2482 -0
  152. package/dist/static/assets/c4Diagram-YG6GDRKO-Mt-aq3VH.js.map +1 -0
  153. package/dist/static/assets/channel-BVr1Yke-.js +8 -0
  154. package/dist/static/assets/channel-BVr1Yke-.js.map +1 -0
  155. package/dist/static/assets/chunk-4BX2VUAB-qCIn5Iic.js +17 -0
  156. package/dist/static/assets/chunk-4BX2VUAB-qCIn5Iic.js.map +1 -0
  157. package/dist/static/assets/chunk-55IACEB6-q172NeCV.js +14 -0
  158. package/dist/static/assets/chunk-55IACEB6-q172NeCV.js.map +1 -0
  159. package/dist/static/assets/chunk-B4BG7PRW-CMJmtYzq.js +1827 -0
  160. package/dist/static/assets/chunk-B4BG7PRW-CMJmtYzq.js.map +1 -0
  161. package/dist/static/assets/chunk-DI55MBZ5-DiuwwZPL.js +1916 -0
  162. package/dist/static/assets/chunk-DI55MBZ5-DiuwwZPL.js.map +1 -0
  163. package/dist/static/assets/chunk-FMBD7UC4-06sqZTTn.js +20 -0
  164. package/dist/static/assets/chunk-FMBD7UC4-06sqZTTn.js.map +1 -0
  165. package/dist/static/assets/chunk-QN33PNHL-CnpBNkpP.js +25 -0
  166. package/dist/static/assets/chunk-QN33PNHL-CnpBNkpP.js.map +1 -0
  167. package/dist/static/assets/chunk-QZHKN3VN-CNgjMR-e.js +18 -0
  168. package/dist/static/assets/chunk-QZHKN3VN-CNgjMR-e.js.map +1 -0
  169. package/dist/static/assets/chunk-TZMSLE5B-BxtzW6--.js +109 -0
  170. package/dist/static/assets/chunk-TZMSLE5B-BxtzW6--.js.map +1 -0
  171. package/dist/static/assets/classDiagram-2ON5EDUG-29huvmn-.js +23 -0
  172. package/dist/static/assets/classDiagram-2ON5EDUG-29huvmn-.js.map +1 -0
  173. package/dist/static/assets/classDiagram-v2-WZHVMYZB-29huvmn-.js +23 -0
  174. package/dist/static/assets/classDiagram-v2-WZHVMYZB-29huvmn-.js.map +1 -0
  175. package/dist/static/assets/clone-D2OgLSSn.js +9 -0
  176. package/dist/static/assets/clone-D2OgLSSn.js.map +1 -0
  177. package/dist/static/assets/cose-bilkent-S5V4N54A-BNegDCxl.js +4943 -0
  178. package/dist/static/assets/cose-bilkent-S5V4N54A-BNegDCxl.js.map +1 -0
  179. package/dist/static/assets/cytoscape.esm-Bm8DJGmZ.js +30240 -0
  180. package/dist/static/assets/cytoscape.esm-Bm8DJGmZ.js.map +1 -0
  181. package/dist/static/assets/dagre-6UL2VRFP-f1XrTRSn.js +695 -0
  182. package/dist/static/assets/dagre-6UL2VRFP-f1XrTRSn.js.map +1 -0
  183. package/dist/static/assets/defaultLocale-DVr69WTU.js +207 -0
  184. package/dist/static/assets/defaultLocale-DVr69WTU.js.map +1 -0
  185. package/dist/static/assets/diagram-PSM6KHXK-8w1WbeDi.js +849 -0
  186. package/dist/static/assets/diagram-PSM6KHXK-8w1WbeDi.js.map +1 -0
  187. package/dist/static/assets/diagram-QEK2KX5R-CF4wtMmR.js +303 -0
  188. package/dist/static/assets/diagram-QEK2KX5R-CF4wtMmR.js.map +1 -0
  189. package/dist/static/assets/diagram-S2PKOQOG-8p3Avgn2.js +213 -0
  190. package/dist/static/assets/diagram-S2PKOQOG-8p3Avgn2.js.map +1 -0
  191. package/dist/static/assets/erDiagram-Q2GNP2WA-BMKLxlM9.js +1159 -0
  192. package/dist/static/assets/erDiagram-Q2GNP2WA-BMKLxlM9.js.map +1 -0
  193. package/dist/static/assets/favicon-Cmg5RbCj.svg +8 -0
  194. package/dist/static/assets/flowDiagram-NV44I4VS-CgEuPNK2.js +2332 -0
  195. package/dist/static/assets/flowDiagram-NV44I4VS-CgEuPNK2.js.map +1 -0
  196. package/dist/static/assets/ganttDiagram-JELNMOA3-bJkDCf-9.js +3681 -0
  197. package/dist/static/assets/ganttDiagram-JELNMOA3-bJkDCf-9.js.map +1 -0
  198. package/dist/static/assets/gitGraphDiagram-NY62KEGX-4QE9kesp.js +1206 -0
  199. package/dist/static/assets/gitGraphDiagram-NY62KEGX-4QE9kesp.js.map +1 -0
  200. package/dist/static/assets/graph-CS0Pmm7c.js +597 -0
  201. package/dist/static/assets/graph-CS0Pmm7c.js.map +1 -0
  202. package/dist/static/assets/index-BS6HnGzC.js +112303 -0
  203. package/dist/static/assets/index-BS6HnGzC.js.map +1 -0
  204. package/dist/static/assets/index-DaIsSzC_.css +483 -0
  205. package/dist/static/assets/infoDiagram-WHAUD3N6-ypBcKfUs.js +34 -0
  206. package/dist/static/assets/infoDiagram-WHAUD3N6-ypBcKfUs.js.map +1 -0
  207. package/dist/static/assets/init-ZxktEp_H.js +17 -0
  208. package/dist/static/assets/init-ZxktEp_H.js.map +1 -0
  209. package/dist/static/assets/journeyDiagram-XKPGCS4Q-QnrxDowJ.js +1255 -0
  210. package/dist/static/assets/journeyDiagram-XKPGCS4Q-QnrxDowJ.js.map +1 -0
  211. package/dist/static/assets/kanban-definition-3W4ZIXB7-CfvEc4z5.js +1048 -0
  212. package/dist/static/assets/kanban-definition-3W4ZIXB7-CfvEc4z5.js.map +1 -0
  213. package/dist/static/assets/layout-8TGxpm23.js +2218 -0
  214. package/dist/static/assets/layout-8TGxpm23.js.map +1 -0
  215. package/dist/static/assets/linear-BATBPQQv.js +341 -0
  216. package/dist/static/assets/linear-BATBPQQv.js.map +1 -0
  217. package/dist/static/assets/min-B3oVH3AC.js +42 -0
  218. package/dist/static/assets/min-B3oVH3AC.js.map +1 -0
  219. package/dist/static/assets/mindmap-definition-VGOIOE7T-L7VLwwF8.js +1127 -0
  220. package/dist/static/assets/mindmap-definition-VGOIOE7T-L7VLwwF8.js.map +1 -0
  221. package/dist/static/assets/ordinal-CxptdPJm.js +77 -0
  222. package/dist/static/assets/ordinal-CxptdPJm.js.map +1 -0
  223. package/dist/static/assets/pieDiagram-ADFJNKIX-CFW3zIhM.js +241 -0
  224. package/dist/static/assets/pieDiagram-ADFJNKIX-CFW3zIhM.js.map +1 -0
  225. package/dist/static/assets/quadrantDiagram-AYHSOK5B-B7ssen3E.js +1338 -0
  226. package/dist/static/assets/quadrantDiagram-AYHSOK5B-B7ssen3E.js.map +1 -0
  227. package/dist/static/assets/requirementDiagram-UZGBJVZJ-D0v5BArv.js +1162 -0
  228. package/dist/static/assets/requirementDiagram-UZGBJVZJ-D0v5BArv.js.map +1 -0
  229. package/dist/static/assets/sankeyDiagram-TZEHDZUN-B7slncJe.js +1195 -0
  230. package/dist/static/assets/sankeyDiagram-TZEHDZUN-B7slncJe.js.map +1 -0
  231. package/dist/static/assets/sequenceDiagram-WL72ISMW-oXU2lRh_.js +3875 -0
  232. package/dist/static/assets/sequenceDiagram-WL72ISMW-oXU2lRh_.js.map +1 -0
  233. package/dist/static/assets/stateDiagram-FKZM4ZOC-CFYsEd0x.js +452 -0
  234. package/dist/static/assets/stateDiagram-FKZM4ZOC-CFYsEd0x.js.map +1 -0
  235. package/dist/static/assets/stateDiagram-v2-4FDKWEC3-C0UWaNA7.js +22 -0
  236. package/dist/static/assets/stateDiagram-v2-4FDKWEC3-C0UWaNA7.js.map +1 -0
  237. package/dist/static/assets/timeline-definition-IT6M3QCI-C3KODUrh.js +1223 -0
  238. package/dist/static/assets/timeline-definition-IT6M3QCI-C3KODUrh.js.map +1 -0
  239. package/dist/static/assets/treemap-KMMF4GRG-DAGDLhj2.js +18753 -0
  240. package/dist/static/assets/treemap-KMMF4GRG-DAGDLhj2.js.map +1 -0
  241. package/dist/static/assets/xychartDiagram-PRI3JC2R-C0J9iwTO.js +1888 -0
  242. package/dist/static/assets/xychartDiagram-PRI3JC2R-C0J9iwTO.js.map +1 -0
  243. package/dist/static/index.html +71 -0
  244. package/dist/static/testing/dom-observation-utils.js +425 -0
  245. package/dist/static/testing/e2e-test-helper.js +3119 -0
  246. package/dist/team.js +1160 -0
  247. package/dist/tellask.js +431 -0
  248. package/dist/tool.js +150 -0
  249. package/dist/tools/apply-patch.js +542 -0
  250. package/dist/tools/builtins.js +196 -0
  251. package/dist/tools/context-health.js +177 -0
  252. package/dist/tools/ctrl.js +478 -0
  253. package/dist/tools/diag.js +583 -0
  254. package/dist/tools/env.js +184 -0
  255. package/dist/tools/fs.js +818 -0
  256. package/dist/tools/mcp.js +138 -0
  257. package/dist/tools/mem.js +349 -0
  258. package/dist/tools/os.js +751 -0
  259. package/dist/tools/prompts/team_mgmt.en.md +70 -0
  260. package/dist/tools/prompts/team_mgmt.zh.md +70 -0
  261. package/dist/tools/prompts/ws_mod.en.md +86 -0
  262. package/dist/tools/prompts/ws_mod.zh.md +87 -0
  263. package/dist/tools/registry-snapshot.js +31 -0
  264. package/dist/tools/registry.js +121 -0
  265. package/dist/tools/ripgrep.js +678 -0
  266. package/dist/tools/team-mgmt.js +3300 -0
  267. package/dist/tools/txt.js +3178 -0
  268. package/dist/utils/id.js +72 -0
  269. package/dist/utils/task-doc.js +236 -0
  270. package/dist/utils/task-package.js +522 -0
  271. package/dist/utils/taskdoc-search.js +280 -0
  272. package/dist/utils/taskdoc.js +400 -0
  273. package/package.json +69 -0
@@ -0,0 +1,425 @@
1
+ /**
2
+ * DOM Observation Utilities for E2E Testing
3
+ *
4
+ * Provides MutationObserver-based wait utilities that respond immediately
5
+ * when DOM changes occur, replacing inefficient polling with event-driven waits.
6
+ */
7
+
8
+ /**
9
+ * Core wait function that uses MutationObserver to detect DOM changes.
10
+ *
11
+ * @param {Function} conditionFn - Function that returns truthy when condition is met
12
+ * @param {Object} options - Configuration options
13
+ * @param {number} options.timeoutMs - Maximum wait time (default: 10000)
14
+ * @param {MutationObserverInit} options.observeOptions - What to observe (default: { childList: true, subtree: true })
15
+ * @param {Node} options.root - Root node to observe (default: document.body)
16
+ * @returns {Promise<any>} The truthy value from conditionFn, or throws on timeout
17
+ */
18
+ async function waitForDomChange(conditionFn, options = {}) {
19
+ const {
20
+ timeoutMs = 10000,
21
+ observeOptions = { childList: true, subtree: true },
22
+ root = document.body,
23
+ } = options;
24
+
25
+ const startTime = Date.now();
26
+
27
+ return new Promise((resolve, reject) => {
28
+ // Check immediately first - avoids observer overhead if already satisfied
29
+ try {
30
+ const result = conditionFn();
31
+ if (result) {
32
+ resolve(result);
33
+ return;
34
+ }
35
+ } catch (err) {
36
+ // Condition function may throw while DOM is unstable
37
+ }
38
+
39
+ const observer = new MutationObserver(() => {
40
+ try {
41
+ const result = conditionFn();
42
+ if (result) {
43
+ observer.disconnect();
44
+ resolve(result);
45
+ }
46
+ } catch (err) {
47
+ // Ignore errors during mutation checking
48
+ }
49
+ });
50
+
51
+ observer.observe(root, observeOptions);
52
+
53
+ // Fallback timeout to prevent hanging
54
+ const timeoutId = setTimeout(() => {
55
+ observer.disconnect();
56
+ try {
57
+ const result = conditionFn();
58
+ if (result) {
59
+ resolve(result);
60
+ } else {
61
+ reject(new Error(`waitForDomChange timed out after ${timeoutMs}ms`));
62
+ }
63
+ } catch (err) {
64
+ reject(new Error(`waitForDomChange timed out after ${timeoutMs}ms`));
65
+ }
66
+ }, timeoutMs);
67
+
68
+ // Clean up timeout if observer resolves first
69
+ observer.callback = () => {
70
+ // This is a no-op; actual logic is in the observer callback above
71
+ // The real cleanup happens in the resolve/reject paths
72
+ };
73
+ });
74
+ }
75
+
76
+ /**
77
+ * Wait for an element to appear in the DOM.
78
+ *
79
+ * @param {string} selector - CSS selector for the element
80
+ * @param {Object} options - waitForDomChange options
81
+ * @returns {Promise<Element|null>} The found element, or null if timeout
82
+ */
83
+ async function waitForElement(selector, options = {}) {
84
+ const timeoutMs = options.timeoutMs ?? 5000;
85
+ try {
86
+ return await waitForDomChange(() => document.querySelector(selector), {
87
+ ...options,
88
+ timeoutMs,
89
+ });
90
+ } catch (err) {
91
+ return null;
92
+ }
93
+ }
94
+
95
+ /**
96
+ * Wait for an element to be added to the DOM (throws on timeout).
97
+ *
98
+ * @param {string} selector - CSS selector for the element
99
+ * @param {Object} options - waitForDomChange options
100
+ * @returns {Promise<Element>} The found element
101
+ * @throws {Error} If element not found within timeout
102
+ */
103
+ async function waitForElementAdded(selector, options = {}) {
104
+ const timeoutMs = options.timeoutMs ?? 5000;
105
+ return waitForDomChange(
106
+ () => {
107
+ const el = document.querySelector(selector);
108
+ if (!el) return false;
109
+ // Element exists and is connected to DOM
110
+ return el.isConnected ? el : false;
111
+ },
112
+ { ...options, timeoutMs },
113
+ );
114
+ }
115
+
116
+ /**
117
+ * Wait for an element to be removed from the DOM.
118
+ *
119
+ * @param {string} selector - CSS selector for the element
120
+ * @param {Object} options - waitForDomChange options
121
+ * @returns {Promise<boolean>} True when element is gone
122
+ */
123
+ async function waitForElementGone(selector, options = {}) {
124
+ const timeoutMs = options.timeoutMs ?? 5000;
125
+ return waitForDomChange(() => !document.querySelector(selector), { ...options, timeoutMs });
126
+ }
127
+
128
+ /**
129
+ * Wait for an element's attribute to have a specific value.
130
+ *
131
+ * @param {string} selector - CSS selector for the element
132
+ * @param {string} attributeName - Attribute to watch
133
+ * @param {string|Function} expectedValue - Expected value or predicate function
134
+ * @param {Object} options - waitForDomChange options
135
+ * @returns {Promise<string>} The attribute value when matched
136
+ */
137
+ async function waitForAttribute(selector, attributeName, expectedValue, options = {}) {
138
+ const isFunc = typeof expectedValue === 'function';
139
+ const timeoutMs = options.timeoutMs ?? 5000;
140
+
141
+ return waitForDomChange(
142
+ () => {
143
+ const el = document.querySelector(selector);
144
+ if (!el) return false;
145
+
146
+ const value = el.getAttribute(attributeName);
147
+ if (isFunc) {
148
+ return expectedValue(value) ? value : false;
149
+ }
150
+ return value === expectedValue ? value : false;
151
+ },
152
+ {
153
+ ...options,
154
+ timeoutMs,
155
+ observeOptions: { attributes: true, subtree: true },
156
+ },
157
+ );
158
+ }
159
+
160
+ /**
161
+ * Wait for an element to have a specific class.
162
+ *
163
+ * @param {string} selector - CSS selector for the element
164
+ * @param {string} className - Class name to wait for
165
+ * @param {Object} options - waitForDomChange options
166
+ * @returns {Promise<boolean>} True when class is present
167
+ */
168
+ async function waitForClass(selector, className, options = {}) {
169
+ return waitForAttribute(selector, 'class', (cls) => cls && cls.includes(className), options);
170
+ }
171
+
172
+ /**
173
+ * Wait for an element to be visible (has dimensions and not display:none).
174
+ *
175
+ * @param {string} selector - CSS selector for the element
176
+ * @param {Object} options - waitForDomChange options
177
+ * @returns {Promise<Element>} The visible element
178
+ */
179
+ async function waitForVisible(selector, options = {}) {
180
+ const timeoutMs = options.timeoutMs ?? 5000;
181
+ return waitForDomChange(
182
+ () => {
183
+ const el = document.querySelector(selector);
184
+ if (!el) return false;
185
+
186
+ const style = window.getComputedStyle(el);
187
+ const isVisible =
188
+ style.display !== 'none' &&
189
+ style.visibility !== 'hidden' &&
190
+ style.opacity !== '0' &&
191
+ el.offsetWidth > 0 &&
192
+ el.offsetHeight > 0;
193
+
194
+ return isVisible ? el : false;
195
+ },
196
+ { ...options, timeoutMs, observeOptions: { attributes: true, childList: true, subtree: true } },
197
+ );
198
+ }
199
+
200
+ /**
201
+ * Wait for an element to be hidden (display:none or visibility:hidden).
202
+ *
203
+ * @param {string} selector - CSS selector for the element
204
+ * @param {Object} options - waitForDomChange options
205
+ * @returns {Promise<boolean>} True when element is hidden
206
+ */
207
+ async function waitForHidden(selector, options = {}) {
208
+ const timeoutMs = options.timeoutMs ?? 5000;
209
+ return waitForDomChange(
210
+ () => {
211
+ const el = document.querySelector(selector);
212
+ if (!el) return true; // Element is gone = hidden
213
+
214
+ const style = window.getComputedStyle(el);
215
+ const isHidden =
216
+ style.display === 'none' || style.visibility === 'hidden' || style.opacity === '0';
217
+
218
+ return isHidden;
219
+ },
220
+ { ...options, timeoutMs, observeOptions: { attributes: true, childList: true, subtree: true } },
221
+ );
222
+ }
223
+
224
+ /**
225
+ * Wait for text content to appear in an element.
226
+ *
227
+ * @param {string} selector - CSS selector for the element
228
+ * @param {string|RegExp|Function} text - Text to wait for
229
+ * @param {Object} options - waitForDomChange options
230
+ * @returns {Promise<string>} The matched text
231
+ */
232
+ async function waitForText(selector, text, options = {}) {
233
+ const isFunction = typeof text === 'function';
234
+ const isRegex = text instanceof RegExp;
235
+ const timeoutMs = options.timeoutMs ?? 5000;
236
+
237
+ return waitForDomChange(
238
+ () => {
239
+ const el = document.querySelector(selector);
240
+ if (!el) return false;
241
+
242
+ const content = el.textContent || '';
243
+ if (isFunction) {
244
+ return text(content) ? content : false;
245
+ }
246
+ if (isRegex) {
247
+ return text.test(content) ? content : false;
248
+ }
249
+ return content.includes(text) ? content : false;
250
+ },
251
+ {
252
+ ...options,
253
+ timeoutMs,
254
+ observeOptions: { characterData: true, childList: true, subtree: true },
255
+ },
256
+ );
257
+ }
258
+
259
+ // ============================================
260
+ // Modal-Specific Utilities
261
+ // ============================================
262
+
263
+ /**
264
+ * Wait for a modal dialog to open (appear in DOM).
265
+ *
266
+ * @param {string} modalSelector - CSS selector for the modal
267
+ * @param {Object} options - waitForDomChange options
268
+ * @returns {Promise<Element>} The opened modal element
269
+ */
270
+ async function waitForModalOpen(modalSelector, options = {}) {
271
+ return waitForElementAdded(modalSelector, options);
272
+ }
273
+
274
+ /**
275
+ * Wait for a modal dialog to close (removed from DOM or hidden).
276
+ *
277
+ * @param {string} modalSelector - CSS selector for the modal
278
+ * @param {Object} options - waitForDomChange options
279
+ * @returns {Promise<boolean>} True when modal is closed
280
+ */
281
+ async function waitForModalClose(modalSelector, options = {}) {
282
+ const timeoutMs = options.timeoutMs ?? 5000;
283
+
284
+ // First try: check if element is gone
285
+ const elementGone = await waitForElementGone(modalSelector, {
286
+ ...options,
287
+ timeoutMs: Math.min(timeoutMs, 2000),
288
+ });
289
+ if (elementGone) return true;
290
+
291
+ // Second try: check if element is hidden
292
+ return waitForHidden(modalSelector, { ...options, timeoutMs: timeoutMs - 2000 });
293
+ }
294
+
295
+ /**
296
+ * Wait for a select element's value to change to the expected value.
297
+ *
298
+ * @param {string} selectSelector - CSS selector for the select element
299
+ * @param {string} expectedValue - Expected option value
300
+ * @param {Object} options - waitForDomChange options
301
+ * @returns {Promise<string>} The selected value
302
+ */
303
+ async function waitForSelectValue(selectSelector, expectedValue, options = {}) {
304
+ return waitForAttribute(selectSelector, 'value', expectedValue, options);
305
+ }
306
+
307
+ // ============================================
308
+ // Shadow DOM Utilities
309
+ // ============================================
310
+
311
+ /**
312
+ * Wait for an element in Shadow DOM to appear.
313
+ *
314
+ * @param {string} hostSelector - CSS selector for the shadow host
315
+ * @param {string} shadowSelector - CSS selector within shadow DOM
316
+ * @param {Object} options - waitForDomChange options
317
+ * @returns {Promise<Element|null>} The found element in shadow DOM
318
+ */
319
+ async function waitForShadowElement(hostSelector, shadowSelector, options = {}) {
320
+ const timeoutMs = options.timeoutMs ?? 5000;
321
+ try {
322
+ return await waitForDomChange(
323
+ () => {
324
+ const host = document.querySelector(hostSelector);
325
+ if (!host || !host.shadowRoot) return false;
326
+ return host.shadowRoot.querySelector(shadowSelector);
327
+ },
328
+ { ...options, timeoutMs },
329
+ );
330
+ } catch (err) {
331
+ return null;
332
+ }
333
+ }
334
+
335
+ /**
336
+ * Wait for an element in nested Shadow DOM (double-shadow).
337
+ *
338
+ * @param {string[]} hostSelectors - Array of selectors for each shadow host level
339
+ * @param {string} targetSelector - Final selector within deepest shadow DOM
340
+ * @param {Object} options - waitForDomChange options
341
+ * @returns {Promise<Element|null>} The found element
342
+ */
343
+ async function waitForNestedShadowElement(hostSelectors, targetSelector, options = {}) {
344
+ const timeoutMs = options.timeoutMs ?? 5000;
345
+
346
+ return waitForDomChange(
347
+ () => {
348
+ let current = document;
349
+
350
+ for (const selector of hostSelectors) {
351
+ if (current instanceof Document) {
352
+ current = current.querySelector(selector);
353
+ } else if (current instanceof HTMLElement && current.shadowRoot) {
354
+ current = current.shadowRoot.querySelector(selector);
355
+ }
356
+ if (!current) return false;
357
+ }
358
+
359
+ if (current instanceof HTMLElement && current.shadowRoot) {
360
+ return current.shadowRoot.querySelector(targetSelector);
361
+ }
362
+ return false;
363
+ },
364
+ { ...options, timeoutMs },
365
+ );
366
+ }
367
+
368
+ /**
369
+ * Wait for an element in Shadow DOM to be hidden (not found or display:none).
370
+ *
371
+ * @param {string} hostSelector - CSS selector for the shadow host
372
+ * @param {string} shadowSelector - CSS selector within shadow DOM
373
+ * @param {Object} options - waitForDomChange options
374
+ * @returns {Promise<boolean>} True when element is hidden/not found
375
+ */
376
+ async function waitForShadowElementHidden(hostSelector, shadowSelector, options = {}) {
377
+ const timeoutMs = options.timeoutMs ?? 5000;
378
+ return waitForDomChange(
379
+ () => {
380
+ const host = document.querySelector(hostSelector);
381
+ if (!host || !host.shadowRoot) return true; // Host gone = hidden
382
+ const el = host.shadowRoot.querySelector(shadowSelector);
383
+ if (!el) return true; // Element not found = hidden
384
+
385
+ // Check if element is hidden via styles
386
+ const style = window.getComputedStyle(el);
387
+ const isHidden =
388
+ style.display === 'none' || style.visibility === 'hidden' || style.opacity === '0';
389
+ return isHidden;
390
+ },
391
+ { ...options, timeoutMs },
392
+ );
393
+ }
394
+
395
+ // ============================================
396
+ // Export
397
+ // ============================================
398
+
399
+ const domObservationUtils = {
400
+ waitForDomChange,
401
+ waitForElement,
402
+ waitForElementAdded,
403
+ waitForElementGone,
404
+ waitForAttribute,
405
+ waitForClass,
406
+ waitForVisible,
407
+ waitForHidden,
408
+ waitForText,
409
+ waitForModalOpen,
410
+ waitForModalClose,
411
+ waitForSelectValue,
412
+ waitForShadowElement,
413
+ waitForNestedShadowElement,
414
+ waitForShadowElementHidden,
415
+ };
416
+
417
+ // Export to window for E2E testing
418
+ if (typeof window !== 'undefined') {
419
+ window.__domObservation__ = domObservationUtils;
420
+ }
421
+
422
+ // Also export as module for bundlers
423
+ if (typeof module !== 'undefined' && module.exports) {
424
+ module.exports = domObservationUtils;
425
+ }