dominds 1.17.7 → 1.18.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 (140) hide show
  1. package/dist/dialog-fork.js +11 -5
  2. package/dist/dialog-instance-registry.js +1 -18
  3. package/dist/dialog.d.ts +21 -31
  4. package/dist/dialog.js +207 -56
  5. package/dist/docs/dialog-system.md +3 -2
  6. package/dist/docs/dialog-system.zh.md +3 -2
  7. package/dist/docs/tellask-collab.md +2 -1
  8. package/dist/docs/tellask-collab.zh.md +2 -1
  9. package/dist/llm/defaults.yaml +43 -0
  10. package/dist/llm/gen/anthropic.js +153 -12
  11. package/dist/llm/gen/codex.js +160 -10
  12. package/dist/llm/gen/openai-compatible.js +141 -81
  13. package/dist/llm/gen/openai.js +178 -12
  14. package/dist/llm/gen/tool-result-image-ingest.d.ts +17 -8
  15. package/dist/llm/gen/tool-result-image-ingest.js +127 -27
  16. package/dist/llm/gen.d.ts +13 -0
  17. package/dist/llm/kernel-driver/drive.js +79 -15
  18. package/dist/llm/kernel-driver/flow.js +158 -41
  19. package/dist/llm/kernel-driver/reply-guidance.d.ts +6 -6
  20. package/dist/llm/kernel-driver/reply-guidance.js +169 -2
  21. package/dist/llm/kernel-driver/runtime.d.ts +2 -2
  22. package/dist/llm/kernel-driver/subdialog.js +4 -0
  23. package/dist/llm/kernel-driver/tellask-special.d.ts +2 -0
  24. package/dist/llm/kernel-driver/tellask-special.js +11 -6
  25. package/dist/llm/kernel-driver/types.d.ts +14 -24
  26. package/dist/minds/system-prompt.js +8 -8
  27. package/dist/persistence.d.ts +6 -5
  28. package/dist/persistence.js +198 -39
  29. package/dist/priming.js +98 -3
  30. package/dist/runtime/driver-messages.d.ts +1 -0
  31. package/dist/runtime/driver-messages.js +32 -10
  32. package/dist/runtime/reply-prompt-copy.js +4 -4
  33. package/dist/server/api-routes.js +11 -43
  34. package/dist/server/websocket-handler.js +155 -10
  35. package/dist/tools/builtins.js +10 -4
  36. package/dist/tools/cmd-runner.js +110 -49
  37. package/dist/tools/picture.d.ts +3 -0
  38. package/dist/tools/picture.js +344 -0
  39. package/dist/tools/prompts/control/en/principles.md +4 -2
  40. package/dist/tools/prompts/control/en/scenarios.md +2 -1
  41. package/dist/tools/prompts/control/en/tools.md +6 -6
  42. package/dist/tools/prompts/control/zh/principles.md +4 -2
  43. package/dist/tools/prompts/control/zh/scenarios.md +2 -1
  44. package/dist/tools/prompts/control/zh/tools.md +1 -1
  45. package/dist/tools/prompts/ws_mod.en.md +1 -0
  46. package/dist/tools/prompts/ws_mod.zh.md +1 -0
  47. package/dist/tools/prompts/ws_read/en/tools.md +25 -5
  48. package/dist/tools/prompts/ws_read/zh/tools.md +25 -5
  49. package/package.json +4 -4
  50. package/webapp/dist/assets/{_basePickBy-u7tNFRWr.js → _basePickBy-BPJaiZdW.js} +3 -3
  51. package/webapp/dist/assets/{_basePickBy-u7tNFRWr.js.map → _basePickBy-BPJaiZdW.js.map} +1 -1
  52. package/webapp/dist/assets/{_baseUniq-CH9LRkiH.js → _baseUniq-BEetT15i.js} +2 -2
  53. package/webapp/dist/assets/{_baseUniq-CH9LRkiH.js.map → _baseUniq-BEetT15i.js.map} +1 -1
  54. package/webapp/dist/assets/{arc-Bo0Lw3ZP.js → arc-Dm7Zf36f.js} +2 -2
  55. package/webapp/dist/assets/{arc-Bo0Lw3ZP.js.map → arc-Dm7Zf36f.js.map} +1 -1
  56. package/webapp/dist/assets/{architectureDiagram-VXUJARFQ-Ckyr89Iw.js → architectureDiagram-VXUJARFQ-BpTPtkuo.js} +7 -7
  57. package/webapp/dist/assets/{architectureDiagram-VXUJARFQ-Ckyr89Iw.js.map → architectureDiagram-VXUJARFQ-BpTPtkuo.js.map} +1 -1
  58. package/webapp/dist/assets/{blockDiagram-VD42YOAC-BSXoLLq_.js → blockDiagram-VD42YOAC-C8fLN0iu.js} +7 -7
  59. package/webapp/dist/assets/{blockDiagram-VD42YOAC-BSXoLLq_.js.map → blockDiagram-VD42YOAC-C8fLN0iu.js.map} +1 -1
  60. package/webapp/dist/assets/{c4Diagram-YG6GDRKO-CgCG1cP0.js → c4Diagram-YG6GDRKO-BpPr62CH.js} +3 -3
  61. package/webapp/dist/assets/{c4Diagram-YG6GDRKO-CgCG1cP0.js.map → c4Diagram-YG6GDRKO-BpPr62CH.js.map} +1 -1
  62. package/webapp/dist/assets/{channel-Crbz0zgt.js → channel-EMYoPjW3.js} +2 -2
  63. package/webapp/dist/assets/{channel-Crbz0zgt.js.map → channel-EMYoPjW3.js.map} +1 -1
  64. package/webapp/dist/assets/{chunk-4BX2VUAB-BIIEb_5S.js → chunk-4BX2VUAB-CefNtjWG.js} +2 -2
  65. package/webapp/dist/assets/{chunk-4BX2VUAB-BIIEb_5S.js.map → chunk-4BX2VUAB-CefNtjWG.js.map} +1 -1
  66. package/webapp/dist/assets/{chunk-55IACEB6-CaJzGgc9.js → chunk-55IACEB6-C_X7T43V.js} +2 -2
  67. package/webapp/dist/assets/{chunk-55IACEB6-CaJzGgc9.js.map → chunk-55IACEB6-C_X7T43V.js.map} +1 -1
  68. package/webapp/dist/assets/{chunk-B4BG7PRW-DHQwhO9F.js → chunk-B4BG7PRW-BRe3_2oA.js} +5 -5
  69. package/webapp/dist/assets/{chunk-B4BG7PRW-DHQwhO9F.js.map → chunk-B4BG7PRW-BRe3_2oA.js.map} +1 -1
  70. package/webapp/dist/assets/{chunk-DI55MBZ5-CG1lO0R8.js → chunk-DI55MBZ5-CbvrsI_w.js} +4 -4
  71. package/webapp/dist/assets/{chunk-DI55MBZ5-CG1lO0R8.js.map → chunk-DI55MBZ5-CbvrsI_w.js.map} +1 -1
  72. package/webapp/dist/assets/{chunk-FMBD7UC4-DAUsTLPS.js → chunk-FMBD7UC4-ORmtkrtS.js} +2 -2
  73. package/webapp/dist/assets/{chunk-FMBD7UC4-DAUsTLPS.js.map → chunk-FMBD7UC4-ORmtkrtS.js.map} +1 -1
  74. package/webapp/dist/assets/{chunk-QN33PNHL-BfQs-QHE.js → chunk-QN33PNHL-LTAOVhWu.js} +2 -2
  75. package/webapp/dist/assets/{chunk-QN33PNHL-BfQs-QHE.js.map → chunk-QN33PNHL-LTAOVhWu.js.map} +1 -1
  76. package/webapp/dist/assets/{chunk-QZHKN3VN-C5iKQ6mQ.js → chunk-QZHKN3VN-ZoUM_4u5.js} +2 -2
  77. package/webapp/dist/assets/{chunk-QZHKN3VN-C5iKQ6mQ.js.map → chunk-QZHKN3VN-ZoUM_4u5.js.map} +1 -1
  78. package/webapp/dist/assets/{chunk-TZMSLE5B-CBShDwy2.js → chunk-TZMSLE5B-Gao4qrq7.js} +2 -2
  79. package/webapp/dist/assets/{chunk-TZMSLE5B-CBShDwy2.js.map → chunk-TZMSLE5B-Gao4qrq7.js.map} +1 -1
  80. package/webapp/dist/assets/{classDiagram-2ON5EDUG-DrfJDzYO.js → classDiagram-2ON5EDUG-uha1vIGN.js} +6 -6
  81. package/webapp/dist/assets/{classDiagram-2ON5EDUG-DrfJDzYO.js.map → classDiagram-2ON5EDUG-uha1vIGN.js.map} +1 -1
  82. package/webapp/dist/assets/{classDiagram-v2-WZHVMYZB-DrfJDzYO.js → classDiagram-v2-WZHVMYZB-uha1vIGN.js} +6 -6
  83. package/webapp/dist/assets/{classDiagram-v2-WZHVMYZB-DrfJDzYO.js.map → classDiagram-v2-WZHVMYZB-uha1vIGN.js.map} +1 -1
  84. package/webapp/dist/assets/{clone-Cd-48URG.js → clone-_9Ayb1Gp.js} +2 -2
  85. package/webapp/dist/assets/{clone-Cd-48URG.js.map → clone-_9Ayb1Gp.js.map} +1 -1
  86. package/webapp/dist/assets/{cose-bilkent-S5V4N54A-CCji0YN3.js → cose-bilkent-S5V4N54A-C8wDw3NY.js} +2 -2
  87. package/webapp/dist/assets/{cose-bilkent-S5V4N54A-CCji0YN3.js.map → cose-bilkent-S5V4N54A-C8wDw3NY.js.map} +1 -1
  88. package/webapp/dist/assets/{dagre-6UL2VRFP-B94p-Dpl.js → dagre-6UL2VRFP-BUSeNot0.js} +7 -7
  89. package/webapp/dist/assets/{dagre-6UL2VRFP-B94p-Dpl.js.map → dagre-6UL2VRFP-BUSeNot0.js.map} +1 -1
  90. package/webapp/dist/assets/{diagram-PSM6KHXK-DP-zGmAS.js → diagram-PSM6KHXK-CMZAksVC.js} +8 -8
  91. package/webapp/dist/assets/{diagram-PSM6KHXK-DP-zGmAS.js.map → diagram-PSM6KHXK-CMZAksVC.js.map} +1 -1
  92. package/webapp/dist/assets/{diagram-QEK2KX5R-DquJirs4.js → diagram-QEK2KX5R-BQKoRtwy.js} +7 -7
  93. package/webapp/dist/assets/{diagram-QEK2KX5R-DquJirs4.js.map → diagram-QEK2KX5R-BQKoRtwy.js.map} +1 -1
  94. package/webapp/dist/assets/{diagram-S2PKOQOG-Dt5W2t6V.js → diagram-S2PKOQOG-DjMG97kd.js} +7 -7
  95. package/webapp/dist/assets/{diagram-S2PKOQOG-Dt5W2t6V.js.map → diagram-S2PKOQOG-DjMG97kd.js.map} +1 -1
  96. package/webapp/dist/assets/{erDiagram-Q2GNP2WA-Bs0-2Rfj.js → erDiagram-Q2GNP2WA-BujwA137.js} +5 -5
  97. package/webapp/dist/assets/{erDiagram-Q2GNP2WA-Bs0-2Rfj.js.map → erDiagram-Q2GNP2WA-BujwA137.js.map} +1 -1
  98. package/webapp/dist/assets/{flowDiagram-NV44I4VS-cJjXWAlK.js → flowDiagram-NV44I4VS-DgwPjg4y.js} +6 -6
  99. package/webapp/dist/assets/{flowDiagram-NV44I4VS-cJjXWAlK.js.map → flowDiagram-NV44I4VS-DgwPjg4y.js.map} +1 -1
  100. package/webapp/dist/assets/{ganttDiagram-JELNMOA3-Du1AUaKm.js → ganttDiagram-JELNMOA3-Db2ykf3E.js} +3 -3
  101. package/webapp/dist/assets/{ganttDiagram-JELNMOA3-Du1AUaKm.js.map → ganttDiagram-JELNMOA3-Db2ykf3E.js.map} +1 -1
  102. package/webapp/dist/assets/{gitGraphDiagram-V2S2FVAM-D_jVOYOK.js → gitGraphDiagram-V2S2FVAM-D_gSifkv.js} +8 -8
  103. package/webapp/dist/assets/{gitGraphDiagram-V2S2FVAM-D_jVOYOK.js.map → gitGraphDiagram-V2S2FVAM-D_gSifkv.js.map} +1 -1
  104. package/webapp/dist/assets/{graph-CuF_sq4r.js → graph-BHjCU5xP.js} +3 -3
  105. package/webapp/dist/assets/{graph-CuF_sq4r.js.map → graph-BHjCU5xP.js.map} +1 -1
  106. package/webapp/dist/assets/{index-DAShQcjb.js → index-DLajsIDJ.js} +1363 -248
  107. package/webapp/dist/assets/{index-DAShQcjb.js.map → index-DLajsIDJ.js.map} +1 -1
  108. package/webapp/dist/assets/{infoDiagram-HS3SLOUP-CEFlo_Hl.js → infoDiagram-HS3SLOUP-BDba5pKs.js} +6 -6
  109. package/webapp/dist/assets/{infoDiagram-HS3SLOUP-CEFlo_Hl.js.map → infoDiagram-HS3SLOUP-BDba5pKs.js.map} +1 -1
  110. package/webapp/dist/assets/{journeyDiagram-XKPGCS4Q-zc2Q4Se9.js → journeyDiagram-XKPGCS4Q-CmJAbmlm.js} +5 -5
  111. package/webapp/dist/assets/{journeyDiagram-XKPGCS4Q-zc2Q4Se9.js.map → journeyDiagram-XKPGCS4Q-CmJAbmlm.js.map} +1 -1
  112. package/webapp/dist/assets/{kanban-definition-3W4ZIXB7-oT42RM2a.js → kanban-definition-3W4ZIXB7-DxQeBTDk.js} +3 -3
  113. package/webapp/dist/assets/{kanban-definition-3W4ZIXB7-oT42RM2a.js.map → kanban-definition-3W4ZIXB7-DxQeBTDk.js.map} +1 -1
  114. package/webapp/dist/assets/{layout-BvaOu3k2.js → layout-DteV_yE8.js} +5 -5
  115. package/webapp/dist/assets/{layout-BvaOu3k2.js.map → layout-DteV_yE8.js.map} +1 -1
  116. package/webapp/dist/assets/{linear-Cg-CjocS.js → linear-zItbPrND.js} +2 -2
  117. package/webapp/dist/assets/{linear-Cg-CjocS.js.map → linear-zItbPrND.js.map} +1 -1
  118. package/webapp/dist/assets/{mindmap-definition-VGOIOE7T-CVFVrU22.js → mindmap-definition-VGOIOE7T-BJXI7UqO.js} +4 -4
  119. package/webapp/dist/assets/{mindmap-definition-VGOIOE7T-CVFVrU22.js.map → mindmap-definition-VGOIOE7T-BJXI7UqO.js.map} +1 -1
  120. package/webapp/dist/assets/{pieDiagram-ADFJNKIX-Bai5CMos.js → pieDiagram-ADFJNKIX-BpM-aH2p.js} +8 -8
  121. package/webapp/dist/assets/{pieDiagram-ADFJNKIX-Bai5CMos.js.map → pieDiagram-ADFJNKIX-BpM-aH2p.js.map} +1 -1
  122. package/webapp/dist/assets/{quadrantDiagram-AYHSOK5B-BPXDO_2E.js → quadrantDiagram-AYHSOK5B-NXdIpA15.js} +3 -3
  123. package/webapp/dist/assets/{quadrantDiagram-AYHSOK5B-BPXDO_2E.js.map → quadrantDiagram-AYHSOK5B-NXdIpA15.js.map} +1 -1
  124. package/webapp/dist/assets/{requirementDiagram-UZGBJVZJ-Dgj9X9cE.js → requirementDiagram-UZGBJVZJ-D1AICAA0.js} +4 -4
  125. package/webapp/dist/assets/{requirementDiagram-UZGBJVZJ-Dgj9X9cE.js.map → requirementDiagram-UZGBJVZJ-D1AICAA0.js.map} +1 -1
  126. package/webapp/dist/assets/{sankeyDiagram-TZEHDZUN-Dc0mO4OD.js → sankeyDiagram-TZEHDZUN-WiReDPfo.js} +2 -2
  127. package/webapp/dist/assets/{sankeyDiagram-TZEHDZUN-Dc0mO4OD.js.map → sankeyDiagram-TZEHDZUN-WiReDPfo.js.map} +1 -1
  128. package/webapp/dist/assets/{sequenceDiagram-WL72ISMW-DZJTga0d.js → sequenceDiagram-WL72ISMW-Cw76oP8t.js} +4 -4
  129. package/webapp/dist/assets/{sequenceDiagram-WL72ISMW-DZJTga0d.js.map → sequenceDiagram-WL72ISMW-Cw76oP8t.js.map} +1 -1
  130. package/webapp/dist/assets/{stateDiagram-FKZM4ZOC-RNxYatKM.js → stateDiagram-FKZM4ZOC-QjCeRczs.js} +9 -9
  131. package/webapp/dist/assets/{stateDiagram-FKZM4ZOC-RNxYatKM.js.map → stateDiagram-FKZM4ZOC-QjCeRczs.js.map} +1 -1
  132. package/webapp/dist/assets/{stateDiagram-v2-4FDKWEC3-ADxYqWzo.js → stateDiagram-v2-4FDKWEC3-IClqxQ4s.js} +5 -5
  133. package/webapp/dist/assets/{stateDiagram-v2-4FDKWEC3-ADxYqWzo.js.map → stateDiagram-v2-4FDKWEC3-IClqxQ4s.js.map} +1 -1
  134. package/webapp/dist/assets/{timeline-definition-IT6M3QCI-Qx_h1e-i.js → timeline-definition-IT6M3QCI-BfyfTY7m.js} +3 -3
  135. package/webapp/dist/assets/{timeline-definition-IT6M3QCI-Qx_h1e-i.js.map → timeline-definition-IT6M3QCI-BfyfTY7m.js.map} +1 -1
  136. package/webapp/dist/assets/{treemap-GDKQZRPO-BHzYvXGn.js → treemap-GDKQZRPO-C5MiL6--.js} +5 -5
  137. package/webapp/dist/assets/{treemap-GDKQZRPO-BHzYvXGn.js.map → treemap-GDKQZRPO-C5MiL6--.js.map} +1 -1
  138. package/webapp/dist/assets/{xychartDiagram-PRI3JC2R-DGdjkYQQ.js → xychartDiagram-PRI3JC2R-ybaJrSry.js} +3 -3
  139. package/webapp/dist/assets/{xychartDiagram-PRI3JC2R-DGdjkYQQ.js.map → xychartDiagram-PRI3JC2R-ybaJrSry.js.map} +1 -1
  140. package/webapp/dist/index.html +1 -1
@@ -1,4 +1,4 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/dagre-6UL2VRFP-B94p-Dpl.js","assets/graph-CuF_sq4r.js","assets/_baseUniq-CH9LRkiH.js","assets/layout-BvaOu3k2.js","assets/_basePickBy-u7tNFRWr.js","assets/clone-Cd-48URG.js","assets/cose-bilkent-S5V4N54A-CCji0YN3.js","assets/cytoscape.esm-Bm8DJGmZ.js","assets/c4Diagram-YG6GDRKO-CgCG1cP0.js","assets/chunk-TZMSLE5B-CBShDwy2.js","assets/flowDiagram-NV44I4VS-cJjXWAlK.js","assets/chunk-FMBD7UC4-DAUsTLPS.js","assets/chunk-55IACEB6-CaJzGgc9.js","assets/chunk-QN33PNHL-BfQs-QHE.js","assets/channel-Crbz0zgt.js","assets/erDiagram-Q2GNP2WA-Bs0-2Rfj.js","assets/gitGraphDiagram-V2S2FVAM-D_jVOYOK.js","assets/chunk-4BX2VUAB-BIIEb_5S.js","assets/chunk-QZHKN3VN-C5iKQ6mQ.js","assets/treemap-GDKQZRPO-BHzYvXGn.js","assets/ganttDiagram-JELNMOA3-Du1AUaKm.js","assets/linear-Cg-CjocS.js","assets/init-ZxktEp_H.js","assets/defaultLocale-B2RvLBDe.js","assets/infoDiagram-HS3SLOUP-CEFlo_Hl.js","assets/pieDiagram-ADFJNKIX-Bai5CMos.js","assets/arc-Bo0Lw3ZP.js","assets/ordinal-CxptdPJm.js","assets/quadrantDiagram-AYHSOK5B-BPXDO_2E.js","assets/xychartDiagram-PRI3JC2R-DGdjkYQQ.js","assets/requirementDiagram-UZGBJVZJ-Dgj9X9cE.js","assets/sequenceDiagram-WL72ISMW-DZJTga0d.js","assets/classDiagram-2ON5EDUG-DrfJDzYO.js","assets/chunk-B4BG7PRW-DHQwhO9F.js","assets/classDiagram-v2-WZHVMYZB-DrfJDzYO.js","assets/stateDiagram-FKZM4ZOC-RNxYatKM.js","assets/chunk-DI55MBZ5-CG1lO0R8.js","assets/stateDiagram-v2-4FDKWEC3-ADxYqWzo.js","assets/journeyDiagram-XKPGCS4Q-zc2Q4Se9.js","assets/timeline-definition-IT6M3QCI-Qx_h1e-i.js","assets/mindmap-definition-VGOIOE7T-CVFVrU22.js","assets/kanban-definition-3W4ZIXB7-oT42RM2a.js","assets/sankeyDiagram-TZEHDZUN-Dc0mO4OD.js","assets/diagram-S2PKOQOG-Dt5W2t6V.js","assets/diagram-QEK2KX5R-DquJirs4.js","assets/blockDiagram-VD42YOAC-BSXoLLq_.js","assets/architectureDiagram-VXUJARFQ-Ckyr89Iw.js","assets/diagram-PSM6KHXK-DP-zGmAS.js"])))=>i.map(i=>d[i]);
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/dagre-6UL2VRFP-BUSeNot0.js","assets/graph-BHjCU5xP.js","assets/_baseUniq-BEetT15i.js","assets/layout-DteV_yE8.js","assets/_basePickBy-BPJaiZdW.js","assets/clone-_9Ayb1Gp.js","assets/cose-bilkent-S5V4N54A-C8wDw3NY.js","assets/cytoscape.esm-Bm8DJGmZ.js","assets/c4Diagram-YG6GDRKO-BpPr62CH.js","assets/chunk-TZMSLE5B-Gao4qrq7.js","assets/flowDiagram-NV44I4VS-DgwPjg4y.js","assets/chunk-FMBD7UC4-ORmtkrtS.js","assets/chunk-55IACEB6-C_X7T43V.js","assets/chunk-QN33PNHL-LTAOVhWu.js","assets/channel-EMYoPjW3.js","assets/erDiagram-Q2GNP2WA-BujwA137.js","assets/gitGraphDiagram-V2S2FVAM-D_gSifkv.js","assets/chunk-4BX2VUAB-CefNtjWG.js","assets/chunk-QZHKN3VN-ZoUM_4u5.js","assets/treemap-GDKQZRPO-C5MiL6--.js","assets/ganttDiagram-JELNMOA3-Db2ykf3E.js","assets/linear-zItbPrND.js","assets/init-ZxktEp_H.js","assets/defaultLocale-B2RvLBDe.js","assets/infoDiagram-HS3SLOUP-BDba5pKs.js","assets/pieDiagram-ADFJNKIX-BpM-aH2p.js","assets/arc-Dm7Zf36f.js","assets/ordinal-CxptdPJm.js","assets/quadrantDiagram-AYHSOK5B-NXdIpA15.js","assets/xychartDiagram-PRI3JC2R-ybaJrSry.js","assets/requirementDiagram-UZGBJVZJ-D1AICAA0.js","assets/sequenceDiagram-WL72ISMW-Cw76oP8t.js","assets/classDiagram-2ON5EDUG-uha1vIGN.js","assets/chunk-B4BG7PRW-BRe3_2oA.js","assets/classDiagram-v2-WZHVMYZB-uha1vIGN.js","assets/stateDiagram-FKZM4ZOC-QjCeRczs.js","assets/chunk-DI55MBZ5-CbvrsI_w.js","assets/stateDiagram-v2-4FDKWEC3-IClqxQ4s.js","assets/journeyDiagram-XKPGCS4Q-CmJAbmlm.js","assets/timeline-definition-IT6M3QCI-BfyfTY7m.js","assets/mindmap-definition-VGOIOE7T-BJXI7UqO.js","assets/kanban-definition-3W4ZIXB7-DxQeBTDk.js","assets/sankeyDiagram-TZEHDZUN-WiReDPfo.js","assets/diagram-S2PKOQOG-DjMG97kd.js","assets/diagram-QEK2KX5R-BQKoRtwy.js","assets/blockDiagram-VD42YOAC-C8fLN0iu.js","assets/architectureDiagram-VXUJARFQ-BpTPtkuo.js","assets/diagram-PSM6KHXK-CMZAksVC.js"])))=>i.map(i=>d[i]);
2
2
  var __defProp = Object.defineProperty;
3
3
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
4
4
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
@@ -384,6 +384,7 @@ function getUiStrings(language2) {
384
384
  q4hSelectedQuestionStaleToastPrefix: "已选问题已失效:",
385
385
  q4hMessageEmptyToast: "消息内容不能为空。",
386
386
  q4hNoRoutableTargetToast: "没有可路由的目标:请选择一个 Q4H 问题或活跃对话。",
387
+ q4hConnectionUnavailableToast: "当前未连接到后端,消息尚未发送。",
387
388
  q4hSendFailedToast: "发送消息失败。",
388
389
  teammateAssignmentBubbleTitle: "定位到任务安排气泡",
389
390
  teammateRequesterCallSiteTitle: "在新标签打开诉请发起点",
@@ -745,6 +746,7 @@ function getUiStrings(language2) {
745
746
  q4hSelectedQuestionStaleToastPrefix: "Selected Q4H question is stale: ",
746
747
  q4hMessageEmptyToast: "Message content is empty.",
747
748
  q4hNoRoutableTargetToast: "No routable target: select a Q4H question or an active dialog.",
749
+ q4hConnectionUnavailableToast: "Not connected to the backend; the message was not sent.",
748
750
  q4hSendFailedToast: "Failed to send message.",
749
751
  teammateAssignmentBubbleTitle: "Go to assignment bubble",
750
752
  teammateRequesterCallSiteTitle: "Open requester call site in new tab",
@@ -2308,18 +2310,32 @@ class WebSocketManager {
2308
2310
  console.debug("WebSocket connection already in progress");
2309
2311
  return;
2310
2312
  }
2311
- this.updateConnectionState({ status: "connecting" });
2313
+ this.updateConnectionState({ status: "connecting", error: void 0 });
2312
2314
  try {
2313
2315
  const wsUrl = this.config.url.replace(/^http/, "ws");
2314
- this.ws = new WebSocket(wsUrl, this.config.protocols);
2315
- this.ws.onopen = this.handleOpen.bind(this);
2316
- this.ws.onmessage = this.handleMessage.bind(this);
2317
- this.ws.onclose = this.handleClose.bind(this);
2318
- this.ws.onerror = this.handleError.bind(this);
2316
+ const ws = new WebSocket(wsUrl, this.config.protocols);
2317
+ this.ws = ws;
2318
+ ws.onopen = () => {
2319
+ if (this.ws !== ws) return;
2320
+ this.handleOpen();
2321
+ };
2322
+ ws.onmessage = (event) => {
2323
+ if (this.ws !== ws) return;
2324
+ this.handleMessage(event);
2325
+ };
2326
+ ws.onclose = (event) => {
2327
+ if (this.ws !== ws) return;
2328
+ this.handleClose(event);
2329
+ };
2330
+ ws.onerror = (event) => {
2331
+ if (this.ws !== ws) return;
2332
+ this.handleError(event);
2333
+ };
2319
2334
  setTimeout(() => {
2320
- if (this.ws?.readyState === WebSocket.CONNECTING) {
2335
+ if (this.ws === ws && ws.readyState === WebSocket.CONNECTING) {
2321
2336
  console.warn("WebSocket connection timeout");
2322
2337
  this.handleError(new Error("Connection timeout"));
2338
+ ws.close(4e3, "Connection timeout");
2323
2339
  }
2324
2340
  }, 5e3);
2325
2341
  } catch (error2) {
@@ -2347,7 +2363,7 @@ class WebSocketManager {
2347
2363
  this.ws.close(1e3, "Client disconnect");
2348
2364
  this.ws = null;
2349
2365
  }
2350
- this.updateConnectionState({ status: "disconnected", reconnectAttempts: 0 });
2366
+ this.updateConnectionState({ status: "disconnected", reconnectAttempts: 0, error: void 0 });
2351
2367
  }
2352
2368
  /**
2353
2369
  * Send a raw message to the server
@@ -2398,7 +2414,8 @@ class WebSocketManager {
2398
2414
  this.updateConnectionState({
2399
2415
  status: "connected",
2400
2416
  lastConnected: /* @__PURE__ */ new Date(),
2401
- reconnectAttempts: 0
2417
+ reconnectAttempts: 0,
2418
+ error: void 0
2402
2419
  });
2403
2420
  if (this.uiLanguage) {
2404
2421
  this.sendRaw({ type: "set_ui_language", uiLanguage: this.uiLanguage });
@@ -2417,11 +2434,12 @@ class WebSocketManager {
2417
2434
  clearInterval(this.heartbeatTimer);
2418
2435
  this.heartbeatTimer = null;
2419
2436
  }
2437
+ this.ws = null;
2420
2438
  if (event.code === 4401 || event.reason === "unauthorized") {
2421
2439
  this.updateConnectionState({ status: "error", error: "Unauthorized" });
2422
2440
  return;
2423
2441
  }
2424
- this.updateConnectionState({ status: "disconnected" });
2442
+ this.updateConnectionState({ status: "disconnected", error: void 0 });
2425
2443
  if (event.code !== 1e3) {
2426
2444
  console.warn("Abnormal close detected, scheduling reconnect");
2427
2445
  this.scheduleReconnect();
@@ -2463,21 +2481,27 @@ class WebSocketManager {
2463
2481
  this.backendEvtsChan.write(message);
2464
2482
  }
2465
2483
  updateConnectionState(updates) {
2466
- ({ ...this.connectionState });
2467
2484
  this.connectionState = { ...this.connectionState, ...updates };
2468
2485
  this.connPubChan.write({ ...this.connectionState });
2469
2486
  }
2470
2487
  scheduleReconnect() {
2488
+ if (this.reconnectTimer) {
2489
+ return;
2490
+ }
2471
2491
  if (this.connectionState.reconnectAttempts >= this.connectionState.maxReconnectAttempts) {
2472
- console.error("Max reconnection attempts reached");
2492
+ const errorMessage = "Max reconnection attempts reached";
2493
+ console.error(errorMessage);
2494
+ this.updateConnectionState({ status: "error", error: errorMessage });
2473
2495
  return;
2474
2496
  }
2475
2497
  const delay = Math.min(1e3 * Math.pow(2, this.connectionState.reconnectAttempts), 3e4);
2476
2498
  this.updateConnectionState({
2477
2499
  status: "reconnecting",
2478
- reconnectAttempts: this.connectionState.reconnectAttempts + 1
2500
+ reconnectAttempts: this.connectionState.reconnectAttempts + 1,
2501
+ error: void 0
2479
2502
  });
2480
2503
  this.reconnectTimer = setTimeout(() => {
2504
+ this.reconnectTimer = null;
2481
2505
  this.connect();
2482
2506
  }, delay);
2483
2507
  }
@@ -2895,9 +2919,10 @@ const _ArchivedDialogList = class _ArchivedDialogList extends HTMLElement {
2895
2919
  if (patch.subdialogCount !== void 0 && targetSelf === rootId) {
2896
2920
  const countEl = entry.el.querySelector(".dialog-count");
2897
2921
  if (countEl instanceof HTMLElement) {
2898
- countEl.textContent = String(
2899
- typeof next2.subdialogCount === "number" ? next2.subdialogCount : 0
2900
- );
2922
+ if (typeof next2.subdialogCount !== "number" || !Number.isInteger(next2.subdialogCount) || next2.subdialogCount < 0) {
2923
+ throw new Error(`Root dialog ${rootId} received invalid backend subdialogCount`);
2924
+ }
2925
+ countEl.textContent = String(next2.subdialogCount);
2901
2926
  }
2902
2927
  }
2903
2928
  return true;
@@ -3031,6 +3056,14 @@ const _ArchivedDialogList = class _ArchivedDialogList extends HTMLElement {
3031
3056
  }
3032
3057
  return max2;
3033
3058
  }
3059
+ getRootSubdialogCount(rootGroup) {
3060
+ if (!rootGroup.root) return rootGroup.subdialogs.length;
3061
+ const backendCount = rootGroup.root.subdialogCount;
3062
+ if (typeof backendCount !== "number" || !Number.isInteger(backendCount) || backendCount < 0) {
3063
+ throw new Error(`Root dialog ${rootGroup.rootId} is missing backend subdialogCount`);
3064
+ }
3065
+ return backendCount;
3066
+ }
3034
3067
  render() {
3035
3068
  if (!this.shadowRoot) return;
3036
3069
  const style2 = this.getStyles();
@@ -3267,7 +3300,7 @@ const _ArchivedDialogList = class _ArchivedDialogList extends HTMLElement {
3267
3300
  const rootRowHtml = rootGroup.root ? this.renderRootRow(
3268
3301
  rootGroup.root,
3269
3302
  this.renderToggleIcon(rootCollapsed),
3270
- rootGroup.subdialogs.length
3303
+ this.getRootSubdialogCount(rootGroup)
3271
3304
  ) : this.renderMissingRootRow(rootGroup, rootCollapsed);
3272
3305
  const existingRootRow = rootNode.querySelector(
3273
3306
  ":scope > .dialog-item.root-dialog"
@@ -63355,6 +63388,8 @@ const HighlightJS = /* @__PURE__ */ getDefaultExportFromCjs(libExports);
63355
63388
  const PROGRESSIVE_EXPAND_INITIAL_MAX_HEIGHT_PX = 120;
63356
63389
  const PROGRESSIVE_EXPAND_STEP_PARENT_RATIO = 1 / 3;
63357
63390
  const PROGRESSIVE_EXPAND_STEP_PARENT_ATTR = "data-progressive-expand-step-parent";
63391
+ const PROGRESSIVE_EXPAND_CLICK_COMMIT_DELAY_MS = 220;
63392
+ const PROGRESSIVE_EXPAND_OVERFLOW_OBSERVER_SLACK_PX = 1;
63358
63393
  function sameProgressiveExpandState(left, right) {
63359
63394
  if (left.kind !== right.kind) return false;
63360
63395
  if (left.kind !== "partial" || right.kind !== "partial") return true;
@@ -63375,6 +63410,7 @@ function getProgressiveExpandLabel(language2) {
63375
63410
  class ProgressiveExpandableComponent {
63376
63411
  constructor(options) {
63377
63412
  this.overflowObserver = null;
63413
+ this.pendingClickCommitTimeout = null;
63378
63414
  this.boundOnNestedGrowth = (event) => {
63379
63415
  if (!(event instanceof CustomEvent)) return;
63380
63416
  if (event.type !== "progressive-expand-content-grown") return;
@@ -63384,17 +63420,18 @@ class ProgressiveExpandableComponent {
63384
63420
  this.refreshExpandFooter();
63385
63421
  });
63386
63422
  };
63387
- this.boundOnClick = () => {
63388
- const stepPx = computeProgressiveExpandStepPx(this.stepParent);
63389
- const currentMaxHeightPx = this.currentState.kind === "partial" ? Math.max(this.currentState.maxHeightPx, this.target.clientHeight) : Math.max(this.target.clientHeight, PROGRESSIVE_EXPAND_INITIAL_MAX_HEIGHT_PX);
63390
- const nextMaxHeightPx = currentMaxHeightPx + stepPx;
63391
- this.collapseToHeight(nextMaxHeightPx);
63392
- this.updateState({ kind: "partial", maxHeightPx: nextMaxHeightPx });
63393
- requestAnimationFrame(() => {
63394
- this.refreshExpandFooter();
63395
- this.emitContentGrown("expand-step");
63396
- this.onAfterExpandStep?.();
63397
- });
63423
+ this.boundOnClick = (event) => {
63424
+ this.cancelPendingClickCommit();
63425
+ if (event.detail >= 3) {
63426
+ this.autoExpandFromNowOn();
63427
+ this.queueAfterExpansionEffects();
63428
+ return;
63429
+ }
63430
+ const clickAction = event.detail <= 1 ? () => this.expandOneStep() : () => this.expandToCurrentMaximum();
63431
+ this.pendingClickCommitTimeout = window.setTimeout(() => {
63432
+ this.pendingClickCommitTimeout = null;
63433
+ clickAction();
63434
+ }, PROGRESSIVE_EXPAND_CLICK_COMMIT_DELAY_MS);
63398
63435
  };
63399
63436
  this.target = options.target;
63400
63437
  this.footer = options.footer;
@@ -63403,11 +63440,11 @@ class ProgressiveExpandableComponent {
63403
63440
  this.label = options.label;
63404
63441
  this.observeTargetUntilOverflow = options.observeTargetUntilOverflow === true;
63405
63442
  this.onStateChange = options.onStateChange;
63406
- this.onAfterExpandStep = options.onAfterExpandStep;
63443
+ this.onAfterExpand = options.onAfterExpand;
63407
63444
  this.currentState = options.state ?? { kind: "initial" };
63408
63445
  this.button.setAttribute("aria-label", this.label.text);
63409
63446
  this.button.title = this.label.title;
63410
- this.button.onclick = this.boundOnClick;
63447
+ this.button.addEventListener("click", this.boundOnClick);
63411
63448
  this.target.addEventListener(
63412
63449
  "progressive-expand-content-grown",
63413
63450
  this.boundOnNestedGrowth
@@ -63419,9 +63456,21 @@ class ProgressiveExpandableComponent {
63419
63456
  this.refreshExpandFooter();
63420
63457
  });
63421
63458
  }
63459
+ expandOneStep() {
63460
+ if (this.currentState.kind === "full") {
63461
+ return;
63462
+ }
63463
+ const stepPx = computeProgressiveExpandStepPx(this.stepParent);
63464
+ const currentMaxHeightPx = this.currentState.kind === "partial" ? Math.max(this.currentState.maxHeightPx, this.target.clientHeight) : Math.max(this.target.clientHeight, PROGRESSIVE_EXPAND_INITIAL_MAX_HEIGHT_PX);
63465
+ const nextMaxHeightPx = currentMaxHeightPx + stepPx;
63466
+ this.collapseToHeight(nextMaxHeightPx);
63467
+ this.updateState({ kind: "partial", maxHeightPx: nextMaxHeightPx });
63468
+ this.queueAfterExpansionEffects();
63469
+ }
63422
63470
  cleanup() {
63471
+ this.cancelPendingClickCommit();
63423
63472
  this.disconnectOverflowObserver();
63424
- this.button.onclick = null;
63473
+ this.button.removeEventListener("click", this.boundOnClick);
63425
63474
  this.target.removeEventListener(
63426
63475
  "progressive-expand-content-grown",
63427
63476
  this.boundOnNestedGrowth
@@ -63444,6 +63493,11 @@ class ProgressiveExpandableComponent {
63444
63493
  this.target.style.maxHeight = `${Math.max(PROGRESSIVE_EXPAND_INITIAL_MAX_HEIGHT_PX, heightPx)}px`;
63445
63494
  this.target.style.overflowY = "hidden";
63446
63495
  }
63496
+ cancelPendingClickCommit() {
63497
+ if (this.pendingClickCommitTimeout === null) return;
63498
+ window.clearTimeout(this.pendingClickCommitTimeout);
63499
+ this.pendingClickCommitTimeout = null;
63500
+ }
63447
63501
  collapseToInitial() {
63448
63502
  this.collapseToHeight(PROGRESSIVE_EXPAND_INITIAL_MAX_HEIGHT_PX);
63449
63503
  }
@@ -63455,12 +63509,33 @@ class ProgressiveExpandableComponent {
63455
63509
  this.overflowObserver?.disconnect();
63456
63510
  this.overflowObserver = null;
63457
63511
  }
63458
- expandFully() {
63512
+ autoExpandFromNowOn() {
63459
63513
  this.showCurrentContentFully();
63460
63514
  this.footer.classList.add("is-hidden");
63461
63515
  this.disconnectOverflowObserver();
63462
63516
  this.updateState({ kind: "full" });
63463
63517
  }
63518
+ expandToCurrentMaximum() {
63519
+ if (this.currentState.kind === "full") {
63520
+ return;
63521
+ }
63522
+ const currentMaxHeightPx = Math.max(
63523
+ this.target.scrollHeight + PROGRESSIVE_EXPAND_OVERFLOW_OBSERVER_SLACK_PX,
63524
+ this.target.clientHeight,
63525
+ PROGRESSIVE_EXPAND_INITIAL_MAX_HEIGHT_PX
63526
+ );
63527
+ this.collapseToHeight(currentMaxHeightPx);
63528
+ this.updateState({ kind: "partial", maxHeightPx: currentMaxHeightPx });
63529
+ this.queueAfterExpansionEffects();
63530
+ }
63531
+ queueAfterExpansionEffects() {
63532
+ requestAnimationFrame(() => {
63533
+ if (!this.target.isConnected) return;
63534
+ this.refreshExpandFooter();
63535
+ this.emitContentGrown("expand-step");
63536
+ this.onAfterExpand?.();
63537
+ });
63538
+ }
63464
63539
  applyCurrentState() {
63465
63540
  switch (this.currentState.kind) {
63466
63541
  case "initial":
@@ -63470,15 +63545,16 @@ class ProgressiveExpandableComponent {
63470
63545
  this.collapseToHeight(this.currentState.maxHeightPx);
63471
63546
  return;
63472
63547
  case "full":
63473
- this.expandFully();
63548
+ this.autoExpandFromNowOn();
63474
63549
  return;
63475
63550
  }
63476
63551
  }
63477
63552
  attachOverflowObserverIfNeeded() {
63478
- this.disconnectOverflowObserver();
63479
- if (!this.observeTargetUntilOverflow || this.currentState.kind !== "initial" || typeof ResizeObserver === "undefined") {
63553
+ if (!this.observeTargetUntilOverflow || this.currentState.kind === "full" || typeof ResizeObserver === "undefined") {
63554
+ this.disconnectOverflowObserver();
63480
63555
  return;
63481
63556
  }
63557
+ if (this.overflowObserver !== null) return;
63482
63558
  this.overflowObserver = new ResizeObserver(() => {
63483
63559
  this.refreshExpandFooter();
63484
63560
  this.emitContentGrown("content-growth");
@@ -63497,6 +63573,12 @@ class ProgressiveExpandableComponent {
63497
63573
  }
63498
63574
  this.footer.classList.add("is-hidden");
63499
63575
  this.showCurrentContentFully();
63576
+ this.attachOverflowObserverIfNeeded();
63577
+ return;
63578
+ }
63579
+ if (this.currentState.kind === "full") {
63580
+ this.showCurrentContentFully();
63581
+ this.footer.classList.add("is-hidden");
63500
63582
  return;
63501
63583
  }
63502
63584
  const overflow = this.target.scrollHeight > this.target.clientHeight + 1;
@@ -63506,7 +63588,18 @@ class ProgressiveExpandableComponent {
63506
63588
  return;
63507
63589
  }
63508
63590
  this.footer.classList.add("is-hidden");
63509
- this.expandFully();
63591
+ this.ensurePartialOverflowObserverSlack();
63592
+ this.attachOverflowObserverIfNeeded();
63593
+ }
63594
+ ensurePartialOverflowObserverSlack() {
63595
+ if (this.currentState.kind !== "partial") return;
63596
+ const nextMaxHeightPx = Math.max(
63597
+ this.currentState.maxHeightPx,
63598
+ this.target.scrollHeight + PROGRESSIVE_EXPAND_OVERFLOW_OBSERVER_SLACK_PX
63599
+ );
63600
+ if (nextMaxHeightPx === this.currentState.maxHeightPx) return;
63601
+ this.collapseToHeight(nextMaxHeightPx);
63602
+ this.updateState({ kind: "partial", maxHeightPx: nextMaxHeightPx });
63510
63603
  }
63511
63604
  }
63512
63605
  function setupProgressiveExpandBehavior(options) {
@@ -63733,8 +63826,7 @@ class DomindsCodeBlock extends HTMLElement {
63733
63826
  stepParent,
63734
63827
  label: getProgressiveExpandLabel(language2),
63735
63828
  // Code blocks can keep growing while streaming output arrives. Observe only the code block
63736
- // itself until it first crosses the initial clamp threshold; never infer or observe parent
63737
- // containers here.
63829
+ // itself while its expand footer is hidden; never infer or observe parent containers here.
63738
63830
  observeTargetUntilOverflow: true,
63739
63831
  state: this.progressiveExpandState,
63740
63832
  onStateChange: (state2) => {
@@ -98444,12 +98536,12 @@ var registerDefaultLayoutLoaders = /* @__PURE__ */ __name(() => {
98444
98536
  registerLayoutLoaders([
98445
98537
  {
98446
98538
  name: "dagre",
98447
- loader: /* @__PURE__ */ __name(async () => await __vitePreload(() => import("./dagre-6UL2VRFP-B94p-Dpl.js"), true ? __vite__mapDeps([0,1,2,3,4,5]) : void 0), "loader")
98539
+ loader: /* @__PURE__ */ __name(async () => await __vitePreload(() => import("./dagre-6UL2VRFP-BUSeNot0.js"), true ? __vite__mapDeps([0,1,2,3,4,5]) : void 0), "loader")
98448
98540
  },
98449
98541
  ...[
98450
98542
  {
98451
98543
  name: "cose-bilkent",
98452
- loader: /* @__PURE__ */ __name(async () => await __vitePreload(() => import("./cose-bilkent-S5V4N54A-CCji0YN3.js"), true ? __vite__mapDeps([6,7]) : void 0), "loader")
98544
+ loader: /* @__PURE__ */ __name(async () => await __vitePreload(() => import("./cose-bilkent-S5V4N54A-C8wDw3NY.js"), true ? __vite__mapDeps([6,7]) : void 0), "loader")
98453
98545
  }
98454
98546
  ]
98455
98547
  ]);
@@ -98889,7 +98981,7 @@ var detector = /* @__PURE__ */ __name((txt) => {
98889
98981
  }, "detector");
98890
98982
  var loader = /* @__PURE__ */ __name(async () => {
98891
98983
  const { diagram: diagram2 } = await __vitePreload(async () => {
98892
- const { diagram: diagram22 } = await import("./c4Diagram-YG6GDRKO-CgCG1cP0.js");
98984
+ const { diagram: diagram22 } = await import("./c4Diagram-YG6GDRKO-BpPr62CH.js");
98893
98985
  return { diagram: diagram22 };
98894
98986
  }, true ? __vite__mapDeps([8,9]) : void 0);
98895
98987
  return { id: id$1, diagram: diagram2 };
@@ -98909,7 +99001,7 @@ var detector2 = /* @__PURE__ */ __name((txt, config2) => {
98909
99001
  }, "detector");
98910
99002
  var loader2 = /* @__PURE__ */ __name(async () => {
98911
99003
  const { diagram: diagram2 } = await __vitePreload(async () => {
98912
- const { diagram: diagram22 } = await import("./flowDiagram-NV44I4VS-cJjXWAlK.js");
99004
+ const { diagram: diagram22 } = await import("./flowDiagram-NV44I4VS-DgwPjg4y.js");
98913
99005
  return { diagram: diagram22 };
98914
99006
  }, true ? __vite__mapDeps([10,11,12,13,14]) : void 0);
98915
99007
  return { id: id2, diagram: diagram2 };
@@ -98935,7 +99027,7 @@ var detector3 = /* @__PURE__ */ __name((txt, config2) => {
98935
99027
  }, "detector");
98936
99028
  var loader3 = /* @__PURE__ */ __name(async () => {
98937
99029
  const { diagram: diagram2 } = await __vitePreload(async () => {
98938
- const { diagram: diagram22 } = await import("./flowDiagram-NV44I4VS-cJjXWAlK.js");
99030
+ const { diagram: diagram22 } = await import("./flowDiagram-NV44I4VS-DgwPjg4y.js");
98939
99031
  return { diagram: diagram22 };
98940
99032
  }, true ? __vite__mapDeps([10,11,12,13,14]) : void 0);
98941
99033
  return { id: id3, diagram: diagram2 };
@@ -98952,7 +99044,7 @@ var detector4 = /* @__PURE__ */ __name((txt) => {
98952
99044
  }, "detector");
98953
99045
  var loader4 = /* @__PURE__ */ __name(async () => {
98954
99046
  const { diagram: diagram2 } = await __vitePreload(async () => {
98955
- const { diagram: diagram22 } = await import("./erDiagram-Q2GNP2WA-Bs0-2Rfj.js");
99047
+ const { diagram: diagram22 } = await import("./erDiagram-Q2GNP2WA-BujwA137.js");
98956
99048
  return { diagram: diagram22 };
98957
99049
  }, true ? __vite__mapDeps([15,12,13,14]) : void 0);
98958
99050
  return { id: id4, diagram: diagram2 };
@@ -98969,7 +99061,7 @@ var detector5 = /* @__PURE__ */ __name((txt) => {
98969
99061
  }, "detector");
98970
99062
  var loader5 = /* @__PURE__ */ __name(async () => {
98971
99063
  const { diagram: diagram2 } = await __vitePreload(async () => {
98972
- const { diagram: diagram22 } = await import("./gitGraphDiagram-V2S2FVAM-D_jVOYOK.js");
99064
+ const { diagram: diagram22 } = await import("./gitGraphDiagram-V2S2FVAM-D_gSifkv.js");
98973
99065
  return { diagram: diagram22 };
98974
99066
  }, true ? __vite__mapDeps([16,17,18,19,2,4,5]) : void 0);
98975
99067
  return { id: id5, diagram: diagram2 };
@@ -98986,7 +99078,7 @@ var detector6 = /* @__PURE__ */ __name((txt) => {
98986
99078
  }, "detector");
98987
99079
  var loader6 = /* @__PURE__ */ __name(async () => {
98988
99080
  const { diagram: diagram2 } = await __vitePreload(async () => {
98989
- const { diagram: diagram22 } = await import("./ganttDiagram-JELNMOA3-Du1AUaKm.js");
99081
+ const { diagram: diagram22 } = await import("./ganttDiagram-JELNMOA3-Db2ykf3E.js");
98990
99082
  return { diagram: diagram22 };
98991
99083
  }, true ? __vite__mapDeps([20,21,22,23]) : void 0);
98992
99084
  return { id: id6, diagram: diagram2 };
@@ -99003,7 +99095,7 @@ var detector7 = /* @__PURE__ */ __name((txt) => {
99003
99095
  }, "detector");
99004
99096
  var loader7 = /* @__PURE__ */ __name(async () => {
99005
99097
  const { diagram: diagram2 } = await __vitePreload(async () => {
99006
- const { diagram: diagram22 } = await import("./infoDiagram-HS3SLOUP-CEFlo_Hl.js");
99098
+ const { diagram: diagram22 } = await import("./infoDiagram-HS3SLOUP-BDba5pKs.js");
99007
99099
  return { diagram: diagram22 };
99008
99100
  }, true ? __vite__mapDeps([24,19,2,4,5]) : void 0);
99009
99101
  return { id: id7, diagram: diagram2 };
@@ -99019,7 +99111,7 @@ var detector8 = /* @__PURE__ */ __name((txt) => {
99019
99111
  }, "detector");
99020
99112
  var loader8 = /* @__PURE__ */ __name(async () => {
99021
99113
  const { diagram: diagram2 } = await __vitePreload(async () => {
99022
- const { diagram: diagram22 } = await import("./pieDiagram-ADFJNKIX-Bai5CMos.js");
99114
+ const { diagram: diagram22 } = await import("./pieDiagram-ADFJNKIX-BpM-aH2p.js");
99023
99115
  return { diagram: diagram22 };
99024
99116
  }, true ? __vite__mapDeps([25,17,19,2,4,5,26,27,22]) : void 0);
99025
99117
  return { id: id8, diagram: diagram2 };
@@ -99035,7 +99127,7 @@ var detector9 = /* @__PURE__ */ __name((txt) => {
99035
99127
  }, "detector");
99036
99128
  var loader9 = /* @__PURE__ */ __name(async () => {
99037
99129
  const { diagram: diagram2 } = await __vitePreload(async () => {
99038
- const { diagram: diagram22 } = await import("./quadrantDiagram-AYHSOK5B-BPXDO_2E.js");
99130
+ const { diagram: diagram22 } = await import("./quadrantDiagram-AYHSOK5B-NXdIpA15.js");
99039
99131
  return { diagram: diagram22 };
99040
99132
  }, true ? __vite__mapDeps([28,21,22,23]) : void 0);
99041
99133
  return { id: id9, diagram: diagram2 };
@@ -99052,7 +99144,7 @@ var detector10 = /* @__PURE__ */ __name((txt) => {
99052
99144
  }, "detector");
99053
99145
  var loader10 = /* @__PURE__ */ __name(async () => {
99054
99146
  const { diagram: diagram2 } = await __vitePreload(async () => {
99055
- const { diagram: diagram22 } = await import("./xychartDiagram-PRI3JC2R-DGdjkYQQ.js");
99147
+ const { diagram: diagram22 } = await import("./xychartDiagram-PRI3JC2R-ybaJrSry.js");
99056
99148
  return { diagram: diagram22 };
99057
99149
  }, true ? __vite__mapDeps([29,22,27,21,23]) : void 0);
99058
99150
  return { id: id10, diagram: diagram2 };
@@ -99069,7 +99161,7 @@ var detector11 = /* @__PURE__ */ __name((txt) => {
99069
99161
  }, "detector");
99070
99162
  var loader11 = /* @__PURE__ */ __name(async () => {
99071
99163
  const { diagram: diagram2 } = await __vitePreload(async () => {
99072
- const { diagram: diagram22 } = await import("./requirementDiagram-UZGBJVZJ-Dgj9X9cE.js");
99164
+ const { diagram: diagram22 } = await import("./requirementDiagram-UZGBJVZJ-D1AICAA0.js");
99073
99165
  return { diagram: diagram22 };
99074
99166
  }, true ? __vite__mapDeps([30,12,13]) : void 0);
99075
99167
  return { id: id11, diagram: diagram2 };
@@ -99086,7 +99178,7 @@ var detector12 = /* @__PURE__ */ __name((txt) => {
99086
99178
  }, "detector");
99087
99179
  var loader12 = /* @__PURE__ */ __name(async () => {
99088
99180
  const { diagram: diagram2 } = await __vitePreload(async () => {
99089
- const { diagram: diagram22 } = await import("./sequenceDiagram-WL72ISMW-DZJTga0d.js");
99181
+ const { diagram: diagram22 } = await import("./sequenceDiagram-WL72ISMW-Cw76oP8t.js");
99090
99182
  return { diagram: diagram22 };
99091
99183
  }, true ? __vite__mapDeps([31,9,18]) : void 0);
99092
99184
  return { id: id12, diagram: diagram2 };
@@ -99106,7 +99198,7 @@ var detector13 = /* @__PURE__ */ __name((txt, config2) => {
99106
99198
  }, "detector");
99107
99199
  var loader13 = /* @__PURE__ */ __name(async () => {
99108
99200
  const { diagram: diagram2 } = await __vitePreload(async () => {
99109
- const { diagram: diagram22 } = await import("./classDiagram-2ON5EDUG-DrfJDzYO.js");
99201
+ const { diagram: diagram22 } = await import("./classDiagram-2ON5EDUG-uha1vIGN.js");
99110
99202
  return { diagram: diagram22 };
99111
99203
  }, true ? __vite__mapDeps([32,33,11,12,13]) : void 0);
99112
99204
  return { id: id13, diagram: diagram2 };
@@ -99126,7 +99218,7 @@ var detector14 = /* @__PURE__ */ __name((txt, config2) => {
99126
99218
  }, "detector");
99127
99219
  var loader14 = /* @__PURE__ */ __name(async () => {
99128
99220
  const { diagram: diagram2 } = await __vitePreload(async () => {
99129
- const { diagram: diagram22 } = await import("./classDiagram-v2-WZHVMYZB-DrfJDzYO.js");
99221
+ const { diagram: diagram22 } = await import("./classDiagram-v2-WZHVMYZB-uha1vIGN.js");
99130
99222
  return { diagram: diagram22 };
99131
99223
  }, true ? __vite__mapDeps([34,33,11,12,13]) : void 0);
99132
99224
  return { id: id14, diagram: diagram2 };
@@ -99146,7 +99238,7 @@ var detector15 = /* @__PURE__ */ __name((txt, config2) => {
99146
99238
  }, "detector");
99147
99239
  var loader15 = /* @__PURE__ */ __name(async () => {
99148
99240
  const { diagram: diagram2 } = await __vitePreload(async () => {
99149
- const { diagram: diagram22 } = await import("./stateDiagram-FKZM4ZOC-RNxYatKM.js");
99241
+ const { diagram: diagram22 } = await import("./stateDiagram-FKZM4ZOC-QjCeRczs.js");
99150
99242
  return { diagram: diagram22 };
99151
99243
  }, true ? __vite__mapDeps([35,36,12,13,1,2,3,4]) : void 0);
99152
99244
  return { id: id15, diagram: diagram2 };
@@ -99169,7 +99261,7 @@ var detector16 = /* @__PURE__ */ __name((txt, config2) => {
99169
99261
  }, "detector");
99170
99262
  var loader16 = /* @__PURE__ */ __name(async () => {
99171
99263
  const { diagram: diagram2 } = await __vitePreload(async () => {
99172
- const { diagram: diagram22 } = await import("./stateDiagram-v2-4FDKWEC3-ADxYqWzo.js");
99264
+ const { diagram: diagram22 } = await import("./stateDiagram-v2-4FDKWEC3-IClqxQ4s.js");
99173
99265
  return { diagram: diagram22 };
99174
99266
  }, true ? __vite__mapDeps([37,36,12,13]) : void 0);
99175
99267
  return { id: id16, diagram: diagram2 };
@@ -99186,7 +99278,7 @@ var detector17 = /* @__PURE__ */ __name((txt) => {
99186
99278
  }, "detector");
99187
99279
  var loader17 = /* @__PURE__ */ __name(async () => {
99188
99280
  const { diagram: diagram2 } = await __vitePreload(async () => {
99189
- const { diagram: diagram22 } = await import("./journeyDiagram-XKPGCS4Q-zc2Q4Se9.js");
99281
+ const { diagram: diagram22 } = await import("./journeyDiagram-XKPGCS4Q-CmJAbmlm.js");
99190
99282
  return { diagram: diagram22 };
99191
99283
  }, true ? __vite__mapDeps([38,9,11,26]) : void 0);
99192
99284
  return { id: id17, diagram: diagram2 };
@@ -99256,7 +99348,7 @@ var detector18 = /* @__PURE__ */ __name((txt, config2 = {}) => {
99256
99348
  }, "detector");
99257
99349
  var loader18 = /* @__PURE__ */ __name(async () => {
99258
99350
  const { diagram: diagram2 } = await __vitePreload(async () => {
99259
- const { diagram: diagram22 } = await import("./flowDiagram-NV44I4VS-cJjXWAlK.js");
99351
+ const { diagram: diagram22 } = await import("./flowDiagram-NV44I4VS-DgwPjg4y.js");
99260
99352
  return { diagram: diagram22 };
99261
99353
  }, true ? __vite__mapDeps([10,11,12,13,14]) : void 0);
99262
99354
  return { id: id18, diagram: diagram2 };
@@ -99273,7 +99365,7 @@ var detector19 = /* @__PURE__ */ __name((txt) => {
99273
99365
  }, "detector");
99274
99366
  var loader19 = /* @__PURE__ */ __name(async () => {
99275
99367
  const { diagram: diagram2 } = await __vitePreload(async () => {
99276
- const { diagram: diagram22 } = await import("./timeline-definition-IT6M3QCI-Qx_h1e-i.js");
99368
+ const { diagram: diagram22 } = await import("./timeline-definition-IT6M3QCI-BfyfTY7m.js");
99277
99369
  return { diagram: diagram22 };
99278
99370
  }, true ? __vite__mapDeps([39,26]) : void 0);
99279
99371
  return { id: id19, diagram: diagram2 };
@@ -99290,7 +99382,7 @@ var detector20 = /* @__PURE__ */ __name((txt) => {
99290
99382
  }, "detector");
99291
99383
  var loader20 = /* @__PURE__ */ __name(async () => {
99292
99384
  const { diagram: diagram2 } = await __vitePreload(async () => {
99293
- const { diagram: diagram22 } = await import("./mindmap-definition-VGOIOE7T-CVFVrU22.js");
99385
+ const { diagram: diagram22 } = await import("./mindmap-definition-VGOIOE7T-BJXI7UqO.js");
99294
99386
  return { diagram: diagram22 };
99295
99387
  }, true ? __vite__mapDeps([40,12,13]) : void 0);
99296
99388
  return { id: id20, diagram: diagram2 };
@@ -99307,7 +99399,7 @@ var detector21 = /* @__PURE__ */ __name((txt) => {
99307
99399
  }, "detector");
99308
99400
  var loader21 = /* @__PURE__ */ __name(async () => {
99309
99401
  const { diagram: diagram2 } = await __vitePreload(async () => {
99310
- const { diagram: diagram22 } = await import("./kanban-definition-3W4ZIXB7-oT42RM2a.js");
99402
+ const { diagram: diagram22 } = await import("./kanban-definition-3W4ZIXB7-DxQeBTDk.js");
99311
99403
  return { diagram: diagram22 };
99312
99404
  }, true ? __vite__mapDeps([41,11]) : void 0);
99313
99405
  return { id: id21, diagram: diagram2 };
@@ -99324,7 +99416,7 @@ var detector22 = /* @__PURE__ */ __name((txt) => {
99324
99416
  }, "detector");
99325
99417
  var loader22 = /* @__PURE__ */ __name(async () => {
99326
99418
  const { diagram: diagram2 } = await __vitePreload(async () => {
99327
- const { diagram: diagram22 } = await import("./sankeyDiagram-TZEHDZUN-Dc0mO4OD.js");
99419
+ const { diagram: diagram22 } = await import("./sankeyDiagram-TZEHDZUN-WiReDPfo.js");
99328
99420
  return { diagram: diagram22 };
99329
99421
  }, true ? __vite__mapDeps([42,27,22]) : void 0);
99330
99422
  return { id: id22, diagram: diagram2 };
@@ -99341,7 +99433,7 @@ var detector23 = /* @__PURE__ */ __name((txt) => {
99341
99433
  }, "detector");
99342
99434
  var loader23 = /* @__PURE__ */ __name(async () => {
99343
99435
  const { diagram: diagram2 } = await __vitePreload(async () => {
99344
- const { diagram: diagram22 } = await import("./diagram-S2PKOQOG-Dt5W2t6V.js");
99436
+ const { diagram: diagram22 } = await import("./diagram-S2PKOQOG-DjMG97kd.js");
99345
99437
  return { diagram: diagram22 };
99346
99438
  }, true ? __vite__mapDeps([43,17,19,2,4,5]) : void 0);
99347
99439
  return { id: id23, diagram: diagram2 };
@@ -99357,7 +99449,7 @@ var detector24 = /* @__PURE__ */ __name((txt) => {
99357
99449
  }, "detector");
99358
99450
  var loader24 = /* @__PURE__ */ __name(async () => {
99359
99451
  const { diagram: diagram2 } = await __vitePreload(async () => {
99360
- const { diagram: diagram22 } = await import("./diagram-QEK2KX5R-DquJirs4.js");
99452
+ const { diagram: diagram22 } = await import("./diagram-QEK2KX5R-BQKoRtwy.js");
99361
99453
  return { diagram: diagram22 };
99362
99454
  }, true ? __vite__mapDeps([44,17,19,2,4,5]) : void 0);
99363
99455
  return { id: id24, diagram: diagram2 };
@@ -99373,7 +99465,7 @@ var detector25 = /* @__PURE__ */ __name((txt) => {
99373
99465
  }, "detector");
99374
99466
  var loader25 = /* @__PURE__ */ __name(async () => {
99375
99467
  const { diagram: diagram2 } = await __vitePreload(async () => {
99376
- const { diagram: diagram22 } = await import("./blockDiagram-VD42YOAC-BSXoLLq_.js");
99468
+ const { diagram: diagram22 } = await import("./blockDiagram-VD42YOAC-C8fLN0iu.js");
99377
99469
  return { diagram: diagram22 };
99378
99470
  }, true ? __vite__mapDeps([45,11,5,2,1,14]) : void 0);
99379
99471
  return { id: id25, diagram: diagram2 };
@@ -99390,7 +99482,7 @@ var detector26 = /* @__PURE__ */ __name((txt) => {
99390
99482
  }, "detector");
99391
99483
  var loader26 = /* @__PURE__ */ __name(async () => {
99392
99484
  const { diagram: diagram2 } = await __vitePreload(async () => {
99393
- const { diagram: diagram22 } = await import("./architectureDiagram-VXUJARFQ-Ckyr89Iw.js");
99485
+ const { diagram: diagram22 } = await import("./architectureDiagram-VXUJARFQ-BpTPtkuo.js");
99394
99486
  return { diagram: diagram22 };
99395
99487
  }, true ? __vite__mapDeps([46,17,19,2,4,5,7]) : void 0);
99396
99488
  return { id: id26, diagram: diagram2 };
@@ -99407,7 +99499,7 @@ var detector27 = /* @__PURE__ */ __name((txt) => {
99407
99499
  }, "detector");
99408
99500
  var loader27 = /* @__PURE__ */ __name(async () => {
99409
99501
  const { diagram: diagram2 } = await __vitePreload(async () => {
99410
- const { diagram: diagram22 } = await import("./diagram-PSM6KHXK-DP-zGmAS.js");
99502
+ const { diagram: diagram22 } = await import("./diagram-PSM6KHXK-CMZAksVC.js");
99411
99503
  return { diagram: diagram22 };
99412
99504
  }, true ? __vite__mapDeps([47,13,17,19,2,4,5,23,27,22]) : void 0);
99413
99505
  return { id: id27, diagram: diagram2 };
@@ -100747,7 +100839,15 @@ function unwrapAnchor(anchor2) {
100747
100839
  function postprocessRenderedDomindsMarkdown(root2) {
100748
100840
  if (typeof window === "undefined") return;
100749
100841
  if (!("querySelectorAll" in root2)) return;
100750
- const anchors = root2.querySelectorAll("a");
100842
+ const anchors = [];
100843
+ if (root2 instanceof HTMLAnchorElement) {
100844
+ anchors.push(root2);
100845
+ }
100846
+ for (const anchorNode of Array.from(root2.querySelectorAll("a"))) {
100847
+ if (anchorNode instanceof HTMLAnchorElement) {
100848
+ anchors.push(anchorNode);
100849
+ }
100850
+ }
100751
100851
  const previewAnchorsByPath = /* @__PURE__ */ new Map();
100752
100852
  for (const anchorNode of anchors) {
100753
100853
  if (!(anchorNode instanceof HTMLAnchorElement)) continue;
@@ -100787,6 +100887,57 @@ function postprocessRenderedDomindsMarkdown(root2) {
100787
100887
  }
100788
100888
  });
100789
100889
  }
100890
+ function isCodeBlockElement(node2) {
100891
+ return node2 instanceof HTMLElement && node2.tagName === "DOMINDS-CODE-BLOCK" && typeof node2.code === "string";
100892
+ }
100893
+ function isMermaidBlockElement(node2) {
100894
+ return node2 instanceof HTMLElement && node2.tagName === "DOMINDS-MERMAID-BLOCK" && typeof node2.definition === "string";
100895
+ }
100896
+ function isMathBlockElement(node2) {
100897
+ return node2 instanceof HTMLElement && node2.tagName === "DOMINDS-MATH-BLOCK" && typeof node2.tex === "string";
100898
+ }
100899
+ function syncElementAttributes(live, next2) {
100900
+ let changed = false;
100901
+ for (const attr of Array.from(live.attributes)) {
100902
+ if (!next2.hasAttribute(attr.name)) {
100903
+ live.removeAttribute(attr.name);
100904
+ changed = true;
100905
+ }
100906
+ }
100907
+ for (const attr of Array.from(next2.attributes)) {
100908
+ if (live.getAttribute(attr.name) !== attr.value) {
100909
+ live.setAttribute(attr.name, attr.value);
100910
+ changed = true;
100911
+ }
100912
+ }
100913
+ return changed;
100914
+ }
100915
+ function syncOptionalAttribute(element, name, nextValue) {
100916
+ if (nextValue === null) {
100917
+ if (element.hasAttribute(name)) {
100918
+ element.removeAttribute(name);
100919
+ return true;
100920
+ }
100921
+ return false;
100922
+ }
100923
+ if (element.getAttribute(name) !== nextValue) {
100924
+ element.setAttribute(name, nextValue);
100925
+ return true;
100926
+ }
100927
+ return false;
100928
+ }
100929
+ function cloneRenderedNode(node2) {
100930
+ return node2.cloneNode(true);
100931
+ }
100932
+ function maybeAddPostprocessTarget(targets, node2) {
100933
+ if (node2 instanceof HTMLAnchorElement) {
100934
+ targets.add(node2);
100935
+ return;
100936
+ }
100937
+ if (node2 instanceof Element) {
100938
+ targets.add(node2);
100939
+ }
100940
+ }
100790
100941
  class DomindsMarkdownSection extends HTMLElement {
100791
100942
  constructor() {
100792
100943
  super();
@@ -100794,39 +100945,176 @@ class DomindsMarkdownSection extends HTMLElement {
100794
100945
  this.classList.add("markdown-section");
100795
100946
  this.innerHTML = '<div class="markdown-content"></div>';
100796
100947
  }
100797
- /**
100798
- * Public API: Append a markdown chunk and re-render
100799
- */
100800
100948
  appendChunk(chunk) {
100801
100949
  this.accumulatedRawMarkdown += chunk;
100802
100950
  this.render();
100803
100951
  }
100804
- /**
100805
- * Public API: Get the accumulated raw markdown
100806
- */
100807
100952
  getRawMarkdown() {
100808
100953
  return this.accumulatedRawMarkdown;
100809
100954
  }
100810
- /**
100811
- * Public API: Set the raw markdown directly (e.g. for reconstruction)
100812
- */
100813
100955
  setRawMarkdown(markdown) {
100814
100956
  this.accumulatedRawMarkdown = markdown;
100815
100957
  this.render();
100816
100958
  }
100817
- /**
100818
- * Internal render logic
100819
- */
100959
+ canReuseNode(live, next2) {
100960
+ if (live.nodeType !== next2.nodeType) return false;
100961
+ if (live instanceof Text && next2 instanceof Text) return true;
100962
+ if (live instanceof HTMLElement && next2 instanceof HTMLElement) {
100963
+ return live.tagName === next2.tagName;
100964
+ }
100965
+ return false;
100966
+ }
100967
+ canSkipNode(live, next2) {
100968
+ if (!this.canReuseNode(live, next2)) return false;
100969
+ if (live instanceof Text && next2 instanceof Text) {
100970
+ return live.data === next2.data;
100971
+ }
100972
+ if (!(live instanceof HTMLElement) || !(next2 instanceof HTMLElement)) {
100973
+ return false;
100974
+ }
100975
+ if (isCodeBlockElement(live) && isCodeBlockElement(next2)) {
100976
+ return (live.getAttribute("language") ?? "") === (next2.getAttribute("language") ?? "") && live.code === (next2.textContent ?? "");
100977
+ }
100978
+ if (isMermaidBlockElement(live) && isMermaidBlockElement(next2)) {
100979
+ return live.definition === (next2.textContent ?? "");
100980
+ }
100981
+ if (isMathBlockElement(live) && isMathBlockElement(next2)) {
100982
+ return (live.getAttribute("display") ?? "") === (next2.getAttribute("display") ?? "") && live.tex === (next2.textContent ?? "");
100983
+ }
100984
+ return live.isEqualNode(next2);
100985
+ }
100986
+ reconcileCustomElement(live, next2) {
100987
+ if (isCodeBlockElement(live) && isCodeBlockElement(next2)) {
100988
+ const attrChanged = syncOptionalAttribute(live, "language", next2.getAttribute("language"));
100989
+ const nextCode = next2.textContent ?? "";
100990
+ if (live.code !== nextCode) {
100991
+ live.code = nextCode;
100992
+ return "changed";
100993
+ }
100994
+ return attrChanged ? "changed" : "unchanged";
100995
+ }
100996
+ if (isMermaidBlockElement(live) && isMermaidBlockElement(next2)) {
100997
+ const nextDefinition = next2.textContent ?? "";
100998
+ if (live.definition !== nextDefinition) {
100999
+ live.definition = nextDefinition;
101000
+ return "changed";
101001
+ }
101002
+ return "unchanged";
101003
+ }
101004
+ if (isMathBlockElement(live) && isMathBlockElement(next2)) {
101005
+ const attrChanged = syncOptionalAttribute(live, "display", next2.getAttribute("display"));
101006
+ const nextTex = next2.textContent ?? "";
101007
+ if (live.tex !== nextTex) {
101008
+ live.tex = nextTex;
101009
+ return "changed";
101010
+ }
101011
+ return attrChanged ? "changed" : "unchanged";
101012
+ }
101013
+ return "not-custom";
101014
+ }
101015
+ reconcileNode(live, next2, postprocessTargets) {
101016
+ if (live instanceof Text && next2 instanceof Text) {
101017
+ if (live.data !== next2.data) {
101018
+ live.data = next2.data;
101019
+ return true;
101020
+ }
101021
+ return false;
101022
+ }
101023
+ if (!(live instanceof HTMLElement) || !(next2 instanceof HTMLElement)) {
101024
+ return false;
101025
+ }
101026
+ if (this.canSkipNode(live, next2)) {
101027
+ return false;
101028
+ }
101029
+ const customResult = this.reconcileCustomElement(live, next2);
101030
+ if (customResult !== "not-custom") {
101031
+ return customResult === "changed";
101032
+ }
101033
+ const attrChanged = syncElementAttributes(live, next2);
101034
+ const childrenChanged = this.reconcileChildren(live, next2, postprocessTargets);
101035
+ if (attrChanged || childrenChanged) {
101036
+ if (live instanceof HTMLAnchorElement) {
101037
+ postprocessTargets.add(live);
101038
+ }
101039
+ return true;
101040
+ }
101041
+ return false;
101042
+ }
101043
+ reconcileChildren(liveParent, nextParent, postprocessTargets) {
101044
+ const liveChildren = Array.from(liveParent.childNodes);
101045
+ const nextChildren = Array.from(nextParent.childNodes);
101046
+ let prefixLength = 0;
101047
+ while (prefixLength < liveChildren.length && prefixLength < nextChildren.length && this.canSkipNode(liveChildren[prefixLength], nextChildren[prefixLength])) {
101048
+ prefixLength += 1;
101049
+ }
101050
+ let liveTailIndex = liveChildren.length - 1;
101051
+ let nextTailIndex = nextChildren.length - 1;
101052
+ while (liveTailIndex >= prefixLength && nextTailIndex >= prefixLength && this.canSkipNode(liveChildren[liveTailIndex], nextChildren[nextTailIndex])) {
101053
+ liveTailIndex -= 1;
101054
+ nextTailIndex -= 1;
101055
+ }
101056
+ const tailReference = liveTailIndex + 1 < liveChildren.length ? liveChildren[liveTailIndex + 1] ?? null : null;
101057
+ let changed = false;
101058
+ const limit = Math.max(liveTailIndex - prefixLength + 1, nextTailIndex - prefixLength + 1);
101059
+ for (let index = 0; index < limit; index += 1) {
101060
+ const logicalIndex = prefixLength + index;
101061
+ const live = logicalIndex <= liveTailIndex ? liveChildren[logicalIndex] ?? null : null;
101062
+ const next2 = logicalIndex <= nextTailIndex ? nextChildren[logicalIndex] ?? null : null;
101063
+ if (live === null && next2 !== null) {
101064
+ const clone2 = cloneRenderedNode(next2);
101065
+ liveParent.insertBefore(clone2, tailReference);
101066
+ maybeAddPostprocessTarget(postprocessTargets, clone2);
101067
+ changed = true;
101068
+ continue;
101069
+ }
101070
+ if (live !== null && next2 === null) {
101071
+ live.remove();
101072
+ changed = true;
101073
+ continue;
101074
+ }
101075
+ if (live === null || next2 === null) {
101076
+ continue;
101077
+ }
101078
+ if (!this.canReuseNode(live, next2)) {
101079
+ const clone2 = cloneRenderedNode(next2);
101080
+ live.replaceWith(clone2);
101081
+ maybeAddPostprocessTarget(postprocessTargets, clone2);
101082
+ changed = true;
101083
+ continue;
101084
+ }
101085
+ if (this.reconcileNode(live, next2, postprocessTargets)) {
101086
+ changed = true;
101087
+ }
101088
+ }
101089
+ return changed;
101090
+ }
101091
+ normalizePostprocessTargets(targets) {
101092
+ const allTargets = Array.from(targets);
101093
+ return allTargets.filter((target) => {
101094
+ for (const other of allTargets) {
101095
+ if (other === target) continue;
101096
+ if (other.contains(target)) {
101097
+ return false;
101098
+ }
101099
+ }
101100
+ return true;
101101
+ });
101102
+ }
100820
101103
  render() {
100821
101104
  const contentEl = this.querySelector(".markdown-content");
100822
- if (contentEl) {
100823
- contentEl.innerHTML = renderDomindsMarkdown(this.accumulatedRawMarkdown, {
100824
- kind: "chat",
100825
- allowRelativeWorkspaceLinks: true
100826
- });
100827
- postprocessRenderedDomindsMarkdown(contentEl);
100828
- contentEl.setAttribute("data-raw-md", this.accumulatedRawMarkdown);
101105
+ if (!contentEl) return;
101106
+ const rendered = renderDomindsMarkdown(this.accumulatedRawMarkdown, {
101107
+ kind: "chat",
101108
+ allowRelativeWorkspaceLinks: true
101109
+ });
101110
+ const nextTree = document.createElement("div");
101111
+ nextTree.innerHTML = rendered;
101112
+ const postprocessTargets = /* @__PURE__ */ new Set();
101113
+ this.reconcileChildren(contentEl, nextTree, postprocessTargets);
101114
+ for (const target of this.normalizePostprocessTargets(postprocessTargets)) {
101115
+ postprocessRenderedDomindsMarkdown(target);
100829
101116
  }
101117
+ contentEl.setAttribute("data-raw-md", this.accumulatedRawMarkdown);
100830
101118
  }
100831
101119
  }
100832
101120
  if (!customElements.get("dominds-markdown-section")) {
@@ -100844,6 +101132,7 @@ const AUTO_SCROLL_WHEEL_RESISTANCE_PX = 56;
100844
101132
  const AUTO_SCROLL_WHEEL_DECAY_MS = 520;
100845
101133
  const AUTO_SCROLL_WHEEL_MAX_RESISTANCE = 1.8;
100846
101134
  const AUTO_SCROLL_WHEEL_IDLE_EPSILON = 0.03;
101135
+ const STREAM_CHUNK_FLUSH_INTERVAL_MS = 200;
100847
101136
  class DomindsDialogContainer extends HTMLElement {
100848
101137
  constructor() {
100849
101138
  super();
@@ -100852,6 +101141,12 @@ class DomindsDialogContainer extends HTMLElement {
100852
101141
  this.serverWorkLanguage = "en";
100853
101142
  this.displayState = null;
100854
101143
  this.suppressEvents = false;
101144
+ this.pendingThinkingChunkBuffer = "";
101145
+ this.pendingThinkingChunkFlushTimer = null;
101146
+ this.pendingThinkingChunkFlushRaf = null;
101147
+ this.pendingMarkdownChunkBuffer = "";
101148
+ this.pendingMarkdownChunkFlushTimer = null;
101149
+ this.pendingMarkdownChunkFlushRaf = null;
100855
101150
  this.autoScrollMode = "following";
100856
101151
  this.autoScrollPinnedToBottom = true;
100857
101152
  this.autoScrollLastRemainingPx = 0;
@@ -100882,6 +101177,9 @@ class DomindsDialogContainer extends HTMLElement {
100882
101177
  this.toolResultImageStatusByKey = /* @__PURE__ */ new Map();
100883
101178
  this.toolResultImageStatusElByKey = /* @__PURE__ */ new Map();
100884
101179
  this.queuedUserBubbleByMsgId = /* @__PURE__ */ new Map();
101180
+ this.queuedUserContentItemsByMsgId = /* @__PURE__ */ new Map();
101181
+ this.userImageStatusByKey = /* @__PURE__ */ new Map();
101182
+ this.userImageStatusElByKey = /* @__PURE__ */ new Map();
100885
101183
  this.pendingTellaskCallAnchorByGenseq = /* @__PURE__ */ new Map();
100886
101184
  this.progressiveExpandCleanupByTarget = /* @__PURE__ */ new Map();
100887
101185
  this.viewportPanelState = { kind: "hidden" };
@@ -100921,6 +101219,24 @@ class DomindsDialogContainer extends HTMLElement {
100921
101219
  this.pendingScrollRequest = { kind: "by_genseq", course: detail.course, genseq: detail.genseq };
100922
101220
  this.maybeApplyPendingScrollRequest();
100923
101221
  };
101222
+ this.enqueueThinkingChunkFlushRaf = () => {
101223
+ this.pendingThinkingChunkFlushTimer = null;
101224
+ if (this.pendingThinkingChunkBuffer.length < 1) return;
101225
+ if (this.pendingThinkingChunkFlushRaf !== null) return;
101226
+ this.pendingThinkingChunkFlushRaf = requestAnimationFrame(() => {
101227
+ this.pendingThinkingChunkFlushRaf = null;
101228
+ this.flushPendingThinkingChunks();
101229
+ });
101230
+ };
101231
+ this.enqueueMarkdownChunkFlushRaf = () => {
101232
+ this.pendingMarkdownChunkFlushTimer = null;
101233
+ if (this.pendingMarkdownChunkBuffer.length < 1) return;
101234
+ if (this.pendingMarkdownChunkFlushRaf !== null) return;
101235
+ this.pendingMarkdownChunkFlushRaf = requestAnimationFrame(() => {
101236
+ this.pendingMarkdownChunkFlushRaf = null;
101237
+ this.flushPendingMarkdownChunks();
101238
+ });
101239
+ };
100924
101240
  this.attachShadow({ mode: "open" });
100925
101241
  }
100926
101242
  setServerWorkLanguage(language2) {
@@ -101598,6 +101914,7 @@ class DomindsDialogContainer extends HTMLElement {
101598
101914
  this.stopAutoScrollObservation();
101599
101915
  this.resetAutoScrollTransientState();
101600
101916
  this.clearViewportPanel();
101917
+ this.resetPendingStreamChunkFlush();
101601
101918
  this.generationBubble = void 0;
101602
101919
  this.thinkingSection = void 0;
101603
101920
  this.markdownSection = void 0;
@@ -101614,6 +101931,9 @@ class DomindsDialogContainer extends HTMLElement {
101614
101931
  this.toolResultImageStatusByKey.clear();
101615
101932
  this.toolResultImageStatusElByKey.clear();
101616
101933
  this.queuedUserBubbleByMsgId.clear();
101934
+ this.queuedUserContentItemsByMsgId.clear();
101935
+ this.userImageStatusByKey.clear();
101936
+ this.userImageStatusElByKey.clear();
101617
101937
  this.pendingTellaskCallAnchorByGenseq.clear();
101618
101938
  const messages = this.shadowRoot?.querySelector(".messages");
101619
101939
  if (messages) {
@@ -101626,6 +101946,7 @@ class DomindsDialogContainer extends HTMLElement {
101626
101946
  cleanup();
101627
101947
  }
101628
101948
  this.progressiveExpandCleanupByTarget.clear();
101949
+ this.resetPendingStreamChunkFlush();
101629
101950
  this.stopAutoScrollObservation();
101630
101951
  this.resetAutoScrollTransientState();
101631
101952
  this.clearViewportPanel();
@@ -101647,12 +101968,121 @@ class DomindsDialogContainer extends HTMLElement {
101647
101968
  this.toolResultImageStatusByKey.clear();
101648
101969
  this.toolResultImageStatusElByKey.clear();
101649
101970
  this.queuedUserBubbleByMsgId.clear();
101971
+ this.queuedUserContentItemsByMsgId.clear();
101972
+ this.userImageStatusByKey.clear();
101973
+ this.userImageStatusElByKey.clear();
101650
101974
  this.pendingTellaskCallAnchorByGenseq.clear();
101651
101975
  const messages = this.shadowRoot?.querySelector(".messages");
101652
101976
  if (messages) {
101653
101977
  messages.innerHTML = "";
101654
101978
  }
101655
101979
  }
101980
+ clearPendingThinkingChunkFlushTimer() {
101981
+ if (this.pendingThinkingChunkFlushTimer === null) return;
101982
+ window.clearTimeout(this.pendingThinkingChunkFlushTimer);
101983
+ this.pendingThinkingChunkFlushTimer = null;
101984
+ }
101985
+ clearPendingThinkingChunkFlushRaf() {
101986
+ if (this.pendingThinkingChunkFlushRaf === null) return;
101987
+ cancelAnimationFrame(this.pendingThinkingChunkFlushRaf);
101988
+ this.pendingThinkingChunkFlushRaf = null;
101989
+ }
101990
+ clearPendingMarkdownChunkFlushTimer() {
101991
+ if (this.pendingMarkdownChunkFlushTimer === null) return;
101992
+ window.clearTimeout(this.pendingMarkdownChunkFlushTimer);
101993
+ this.pendingMarkdownChunkFlushTimer = null;
101994
+ }
101995
+ clearPendingMarkdownChunkFlushRaf() {
101996
+ if (this.pendingMarkdownChunkFlushRaf === null) return;
101997
+ cancelAnimationFrame(this.pendingMarkdownChunkFlushRaf);
101998
+ this.pendingMarkdownChunkFlushRaf = null;
101999
+ }
102000
+ resetPendingStreamChunkFlush() {
102001
+ this.clearPendingThinkingChunkFlushTimer();
102002
+ this.clearPendingThinkingChunkFlushRaf();
102003
+ this.clearPendingMarkdownChunkFlushTimer();
102004
+ this.clearPendingMarkdownChunkFlushRaf();
102005
+ this.pendingThinkingChunkBuffer = "";
102006
+ this.pendingMarkdownChunkBuffer = "";
102007
+ }
102008
+ flushPendingThinkingChunks() {
102009
+ this.clearPendingThinkingChunkFlushTimer();
102010
+ this.clearPendingThinkingChunkFlushRaf();
102011
+ if (this.pendingThinkingChunkBuffer.length < 1) return;
102012
+ const section = this.thinkingSection;
102013
+ if (!section) {
102014
+ this.pendingThinkingChunkBuffer = "";
102015
+ return;
102016
+ }
102017
+ const contentEl = section.querySelector(".thinking-content");
102018
+ if (!contentEl) {
102019
+ this.pendingThinkingChunkBuffer = "";
102020
+ return;
102021
+ }
102022
+ contentEl.textContent += this.pendingThinkingChunkBuffer;
102023
+ this.pendingThinkingChunkBuffer = "";
102024
+ this.scrollToBottom();
102025
+ }
102026
+ flushPendingMarkdownChunks() {
102027
+ this.clearPendingMarkdownChunkFlushTimer();
102028
+ this.clearPendingMarkdownChunkFlushRaf();
102029
+ if (this.pendingMarkdownChunkBuffer.length < 1) return;
102030
+ const section = this.markdownSection;
102031
+ if (!section) {
102032
+ this.pendingMarkdownChunkBuffer = "";
102033
+ return;
102034
+ }
102035
+ section.appendChunk(this.pendingMarkdownChunkBuffer);
102036
+ this.pendingMarkdownChunkBuffer = "";
102037
+ this.scrollToBottom();
102038
+ }
102039
+ scheduleThinkingChunkFlush() {
102040
+ if (this.pendingThinkingChunkFlushTimer !== null) return;
102041
+ if (this.pendingThinkingChunkFlushRaf !== null) return;
102042
+ this.pendingThinkingChunkFlushTimer = window.setTimeout(() => {
102043
+ this.enqueueThinkingChunkFlushRaf();
102044
+ }, STREAM_CHUNK_FLUSH_INTERVAL_MS);
102045
+ }
102046
+ scheduleMarkdownChunkFlush() {
102047
+ if (this.pendingMarkdownChunkFlushTimer !== null) return;
102048
+ if (this.pendingMarkdownChunkFlushRaf !== null) return;
102049
+ this.pendingMarkdownChunkFlushTimer = window.setTimeout(() => {
102050
+ this.enqueueMarkdownChunkFlushRaf();
102051
+ }, STREAM_CHUNK_FLUSH_INTERVAL_MS);
102052
+ }
102053
+ completeThinkingSection() {
102054
+ const thinkingSection = this.thinkingSection;
102055
+ if (!thinkingSection) {
102056
+ console.warn("thinking_finish_evt received without active thinking section, skipping");
102057
+ return;
102058
+ }
102059
+ thinkingSection.classList.add("completed");
102060
+ this.thinkingSection = void 0;
102061
+ }
102062
+ completeMarkdownSection() {
102063
+ if (!this.markdownSection) {
102064
+ console.warn("markdown_finish_evt received without active markdown section, skipping");
102065
+ return;
102066
+ }
102067
+ this.markdownSection.classList.add("completed");
102068
+ this.markdownSection = void 0;
102069
+ }
102070
+ requestImmediateThinkingChunkFlushForFinish() {
102071
+ this.clearPendingThinkingChunkFlushTimer();
102072
+ if (this.pendingThinkingChunkBuffer.length < 1) return false;
102073
+ this.clearPendingThinkingChunkFlushRaf();
102074
+ this.flushPendingThinkingChunks();
102075
+ this.completeThinkingSection();
102076
+ return true;
102077
+ }
102078
+ requestImmediateMarkdownChunkFlushForFinish() {
102079
+ this.clearPendingMarkdownChunkFlushTimer();
102080
+ if (this.pendingMarkdownChunkBuffer.length < 1) return false;
102081
+ this.clearPendingMarkdownChunkFlushRaf();
102082
+ this.flushPendingMarkdownChunks();
102083
+ this.completeMarkdownSection();
102084
+ return true;
102085
+ }
101656
102086
  stopAutoScrollObservation() {
101657
102087
  if (this.autoScrollRealignRaf !== null) {
101658
102088
  cancelAnimationFrame(this.autoScrollRealignRaf);
@@ -101836,7 +102266,8 @@ class DomindsDialogContainer extends HTMLElement {
101836
102266
  // === FUNCTION CALLS (non-streaming mode - direct tool execution) ===
101837
102267
  case "func_call_requested_evt": {
101838
102268
  const ev = event;
101839
- this.handleFuncCallRequested(ev.funcId, ev.funcName, ev.arguments);
102269
+ const timestamp2 = "timestamp" in ev && typeof ev.timestamp === "string" ? ev.timestamp : (/* @__PURE__ */ new Date()).toISOString().slice(0, 19).replace("T", " ");
102270
+ this.handleFuncCallRequested(ev.genseq, ev.funcId, ev.funcName, ev.arguments, timestamp2);
101840
102271
  break;
101841
102272
  }
101842
102273
  case "web_search_call_evt":
@@ -101848,9 +102279,12 @@ class DomindsDialogContainer extends HTMLElement {
101848
102279
  case "tool_result_image_ingest_evt":
101849
102280
  this.handleToolResultImageIngest(event);
101850
102281
  break;
102282
+ case "user_image_ingest_evt":
102283
+ this.handleUserImageIngest(event);
102284
+ break;
101851
102285
  // Function results
101852
102286
  case "func_result_evt":
101853
- if (this.generationBubble && this.currentCourse !== event.course) {
102287
+ if (this.generationBubble && this.generationBubble.getAttribute("data-seq") === String(event.genseq) && this.currentCourse !== event.course) {
101854
102288
  this.handleProtocolError("func_result event.course mismatch with active generation");
101855
102289
  console.error("Function result mismatch", {
101856
102290
  activeSeq: this.activeGenSeq,
@@ -101881,28 +102315,34 @@ class DomindsDialogContainer extends HTMLElement {
101881
102315
  this.handleFullRemindersUpdate(event);
101882
102316
  break;
101883
102317
  case "stream_error_evt":
101884
- if (!this.generationBubble) {
101885
- const host = this.getRootNode()?.host;
101886
- const t2 = getUiStrings(this.uiLanguage);
101887
- const detail = {
101888
- message: String(event.error || t2.unknownStreamErrorToast),
101889
- kind: "error"
101890
- };
101891
- if (host) {
101892
- dispatchDomindsEvent(host, "ui-toast", detail, { bubbles: true, composed: true });
102318
+ {
102319
+ const container = this.shadowRoot?.querySelector(".messages");
102320
+ const targetBubble = event.genseq !== void 0 ? this.generationBubble && this.generationBubble.getAttribute("data-seq") === String(event.genseq) ? this.generationBubble : container ? container.querySelector(
102321
+ `.generation-bubble[data-seq="${String(event.genseq)}"]`
102322
+ ) : null : this.generationBubble;
102323
+ if (!targetBubble) {
102324
+ const host = this.getRootNode()?.host;
102325
+ const t2 = getUiStrings(this.uiLanguage);
102326
+ const detail = {
102327
+ message: String(event.error || t2.unknownStreamErrorToast),
102328
+ kind: "error"
102329
+ };
102330
+ if (host) {
102331
+ dispatchDomindsEvent(host, "ui-toast", detail, { bubbles: true, composed: true });
102332
+ }
102333
+ break;
101893
102334
  }
101894
- break;
101895
- }
101896
- if (event.genseq !== void 0 && (this.activeGenSeq === void 0 || this.activeGenSeq !== event.genseq)) {
101897
- this.handleProtocolError("stream_error_evt event.genseq mismatch");
101898
- console.error("Stream error mismatch", {
101899
- activeSeq: this.activeGenSeq,
101900
- seq: event.genseq,
101901
- course: this.currentCourse,
101902
- evtCourse: event.course
101903
- });
102335
+ if (event.genseq !== void 0 && this.generationBubble && this.generationBubble.getAttribute("data-seq") === String(event.genseq) && (this.activeGenSeq === void 0 || this.activeGenSeq !== event.genseq)) {
102336
+ this.handleProtocolError("stream_error_evt event.genseq mismatch");
102337
+ console.error("Stream error mismatch", {
102338
+ activeSeq: this.activeGenSeq,
102339
+ seq: event.genseq,
102340
+ course: this.currentCourse,
102341
+ evtCourse: event.course
102342
+ });
102343
+ }
102344
+ this.handleError(String(event.error), targetBubble);
101904
102345
  }
101905
- this.handleError(String(event.error));
101906
102346
  break;
101907
102347
  // Historical stream events removed; only stream_error_evt may appear and is handled elsewhere
101908
102348
  default:
@@ -101932,6 +102372,7 @@ class DomindsDialogContainer extends HTMLElement {
101932
102372
  this.generationBubble = void 0;
101933
102373
  };
101934
102374
  const queuedMsgId = typeof msgId === "string" ? msgId.trim() : "";
102375
+ const queuedContentItems = queuedMsgId === "" ? void 0 : this.queuedUserContentItemsByMsgId.get(queuedMsgId);
101935
102376
  const queuedBubble = queuedMsgId === "" ? void 0 : this.takeQueuedUserBubble(queuedMsgId);
101936
102377
  const existingBubble = this.generationBubble;
101937
102378
  if (queuedBubble) {
@@ -101943,7 +102384,8 @@ class DomindsDialogContainer extends HTMLElement {
101943
102384
  queuedBubble,
101944
102385
  seq2,
101945
102386
  timestamp2,
101946
- queuedMsgId
102387
+ queuedMsgId,
102388
+ queuedContentItems
101947
102389
  );
101948
102390
  if (typeof this.currentCourse === "number") {
101949
102391
  bubble2.setAttribute("data-course", String(this.currentCourse));
@@ -102025,6 +102467,7 @@ class DomindsDialogContainer extends HTMLElement {
102025
102467
  let bubble = this.queuedUserBubbleByMsgId.get(msgId);
102026
102468
  if (bubble && !bubble.isConnected) {
102027
102469
  this.queuedUserBubbleByMsgId.delete(msgId);
102470
+ this.queuedUserContentItemsByMsgId.delete(msgId);
102028
102471
  bubble = void 0;
102029
102472
  }
102030
102473
  if (!bubble) {
@@ -102047,7 +102490,12 @@ class DomindsDialogContainer extends HTMLElement {
102047
102490
  }
102048
102491
  this.setBubbleTimestamp(bubble, event.timestamp);
102049
102492
  }
102493
+ const contentHost = bubble.querySelector(".content");
102494
+ if (contentHost) {
102495
+ this.upsertUserContentItems(contentHost, event.contentItems, event.msgId);
102496
+ }
102050
102497
  this.queuedUserBubbleByMsgId.set(msgId, bubble);
102498
+ this.queuedUserContentItemsByMsgId.set(msgId, event.contentItems);
102051
102499
  this.insertRealtimeBubbleAfterActiveGeneration(container, bubble);
102052
102500
  this.scrollToBottom();
102053
102501
  }
@@ -102114,8 +102562,10 @@ class DomindsDialogContainer extends HTMLElement {
102114
102562
  const tracked = this.queuedUserBubbleByMsgId.get(msgId);
102115
102563
  if (tracked) {
102116
102564
  this.queuedUserBubbleByMsgId.delete(msgId);
102565
+ this.queuedUserContentItemsByMsgId.delete(msgId);
102117
102566
  if (tracked.isConnected) return tracked;
102118
102567
  }
102568
+ this.queuedUserContentItemsByMsgId.delete(msgId);
102119
102569
  const container = this.shadowRoot?.querySelector(".messages");
102120
102570
  if (!container) return void 0;
102121
102571
  for (const node2 of Array.from(
@@ -102126,7 +102576,7 @@ class DomindsDialogContainer extends HTMLElement {
102126
102576
  }
102127
102577
  return void 0;
102128
102578
  }
102129
- reuseQueuedUserBubbleForGeneration(queuedBubble, seq2, timestamp2, msgId) {
102579
+ reuseQueuedUserBubbleForGeneration(queuedBubble, seq2, timestamp2, msgId, contentItems) {
102130
102580
  const queuedContentEl = queuedBubble.querySelector(".user-message");
102131
102581
  const queuedRawContent = queuedContentEl?.textContent ?? "";
102132
102582
  const bubble = this.createGenerationBubble(timestamp2);
@@ -102146,6 +102596,7 @@ class DomindsDialogContainer extends HTMLElement {
102146
102596
  divider2.className = "user-response-divider";
102147
102597
  body.appendChild(divider2);
102148
102598
  this.upsertUserPlainTextMessage(body, queuedRawContent);
102599
+ this.upsertUserContentItems(body, contentItems, msgId, seq2);
102149
102600
  bubble.setAttribute("data-raw-user-msg", queuedRawContent);
102150
102601
  }
102151
102602
  }
@@ -102158,8 +102609,10 @@ class DomindsDialogContainer extends HTMLElement {
102158
102609
  const tracked = this.queuedUserBubbleByMsgId.get(msgId);
102159
102610
  if (tracked) {
102160
102611
  this.queuedUserBubbleByMsgId.delete(msgId);
102612
+ this.queuedUserContentItemsByMsgId.delete(msgId);
102161
102613
  if (tracked.isConnected) tracked.remove();
102162
102614
  }
102615
+ this.queuedUserContentItemsByMsgId.delete(msgId);
102163
102616
  const container = this.shadowRoot?.querySelector(".messages");
102164
102617
  if (!container) return;
102165
102618
  for (const node2 of Array.from(
@@ -102170,7 +102623,11 @@ class DomindsDialogContainer extends HTMLElement {
102170
102623
  }
102171
102624
  }
102172
102625
  handleGeneratingFinish(seq2, llmGenModel) {
102173
- const bubble = this.generationBubble;
102626
+ const container = this.shadowRoot?.querySelector(".messages");
102627
+ const activeBubble = this.generationBubble;
102628
+ const bubble = activeBubble && activeBubble.getAttribute("data-seq") === String(seq2) ? activeBubble : container ? container.querySelector(
102629
+ `.generation-bubble[data-seq="${String(seq2)}"]`
102630
+ ) : null;
102174
102631
  if (!bubble) {
102175
102632
  if (this.activeGenSeq === seq2) {
102176
102633
  console.warn(
@@ -102186,6 +102643,7 @@ class DomindsDialogContainer extends HTMLElement {
102186
102643
  }
102187
102644
  return;
102188
102645
  }
102646
+ const finalizingActiveBubble = bubble === activeBubble;
102189
102647
  if (typeof llmGenModel === "string") {
102190
102648
  const trimmed = llmGenModel.trim();
102191
102649
  if (trimmed.length > 0) {
@@ -102204,14 +102662,30 @@ class DomindsDialogContainer extends HTMLElement {
102204
102662
  bubble.classList.remove("generating");
102205
102663
  bubble.classList.add("completed");
102206
102664
  bubble.setAttribute("data-finalized", "true");
102665
+ if (finalizingActiveBubble) {
102666
+ this.clearPendingThinkingChunkFlushTimer();
102667
+ this.clearPendingThinkingChunkFlushRaf();
102668
+ this.clearPendingMarkdownChunkFlushTimer();
102669
+ this.clearPendingMarkdownChunkFlushRaf();
102670
+ this.flushPendingThinkingChunks();
102671
+ this.flushPendingMarkdownChunks();
102672
+ if (this.thinkingSection) {
102673
+ this.completeThinkingSection();
102674
+ }
102675
+ if (this.markdownSection) {
102676
+ this.completeMarkdownSection();
102677
+ }
102678
+ }
102207
102679
  if (this.viewportPanelState.kind !== "hidden" && this.viewportPanelState.genseq === seq2) {
102208
102680
  this.clearViewportPanel();
102209
102681
  }
102210
- this.thinkingSection = void 0;
102211
- this.markdownSection = void 0;
102212
- this.callingSection = void 0;
102213
- this.generationBubble = void 0;
102214
- this.previousDialog = void 0;
102682
+ if (finalizingActiveBubble) {
102683
+ this.thinkingSection = void 0;
102684
+ this.markdownSection = void 0;
102685
+ this.callingSection = void 0;
102686
+ this.generationBubble = void 0;
102687
+ this.previousDialog = void 0;
102688
+ }
102215
102689
  }
102216
102690
  handleGenerationDiscard(seq2) {
102217
102691
  const container = this.shadowRoot?.querySelector(".messages");
@@ -102219,12 +102693,15 @@ class DomindsDialogContainer extends HTMLElement {
102219
102693
  const targetBubble = activeBubble && activeBubble.getAttribute("data-seq") === String(seq2) ? activeBubble : container ? container.querySelector(
102220
102694
  `.generation-bubble[data-seq="${String(seq2)}"]`
102221
102695
  ) : null;
102696
+ const discardingActiveBubble = targetBubble !== null && targetBubble === activeBubble;
102222
102697
  if (targetBubble) {
102223
102698
  this.resetGenerationBubbleForRetry(targetBubble);
102224
- this.generationBubble = targetBubble;
102225
- this.thinkingSection = void 0;
102226
- this.markdownSection = void 0;
102227
- this.callingSection = void 0;
102699
+ if (discardingActiveBubble) {
102700
+ this.generationBubble = targetBubble;
102701
+ this.thinkingSection = void 0;
102702
+ this.markdownSection = void 0;
102703
+ this.callingSection = void 0;
102704
+ }
102228
102705
  }
102229
102706
  this.tellaskCallingSectionBySeq.delete(seq2);
102230
102707
  this.webSearchSectionBySeq.delete(seq2);
@@ -102282,9 +102759,19 @@ class DomindsDialogContainer extends HTMLElement {
102282
102759
  const body = bubble.querySelector(".bubble-body");
102283
102760
  (body || bubble).appendChild(thinkingSection);
102284
102761
  this.thinkingSection = thinkingSection;
102762
+ this.pendingThinkingChunkBuffer = "";
102763
+ this.clearPendingThinkingChunkFlushTimer();
102764
+ this.clearPendingThinkingChunkFlushRaf();
102285
102765
  this.scrollToBottom();
102286
102766
  }
102287
102767
  handleThinkingChunk(genseq, chunk, timestamp2) {
102768
+ if (this.generationBubble && this.generationBubble.getAttribute("data-seq") !== String(genseq) && this.thinkingSection) {
102769
+ console.warn("thinking_chunk_evt genseq mismatch with active thinking section, skipping", {
102770
+ activeSeq: this.generationBubble.getAttribute("data-seq"),
102771
+ genseq
102772
+ });
102773
+ return;
102774
+ }
102288
102775
  const thinkingSection = this.thinkingSection;
102289
102776
  if (!thinkingSection) {
102290
102777
  if (!this.generationBubble || this.generationBubble.getAttribute("data-seq") !== String(genseq)) {
@@ -102296,21 +102783,23 @@ class DomindsDialogContainer extends HTMLElement {
102296
102783
  console.warn("thinking_chunk_evt received without thinking section, auto-creating");
102297
102784
  this.handleThinkingStart(genseq, timestamp2);
102298
102785
  }
102299
- const section = this.thinkingSection;
102300
- const contentEl = section.querySelector(".thinking-content");
102301
- if (contentEl) {
102302
- contentEl.textContent += chunk;
102303
- this.scrollToBottom();
102786
+ if (!this.thinkingSection) {
102787
+ console.warn("thinking_chunk_evt received without thinking section, skipping");
102788
+ return;
102304
102789
  }
102790
+ this.pendingThinkingChunkBuffer += chunk;
102791
+ this.scheduleThinkingChunkFlush();
102305
102792
  }
102306
- handleThinkingFinish(_genseq) {
102307
- const thinkingSection = this.thinkingSection;
102308
- if (!thinkingSection) {
102309
- console.warn("thinking_finish_evt received without active thinking section, skipping");
102793
+ handleThinkingFinish(genseq) {
102794
+ if (this.generationBubble && this.generationBubble.getAttribute("data-seq") !== String(genseq) && this.thinkingSection) {
102795
+ console.warn("thinking_finish_evt genseq mismatch with active thinking section, skipping", {
102796
+ activeSeq: this.generationBubble.getAttribute("data-seq"),
102797
+ genseq
102798
+ });
102310
102799
  return;
102311
102800
  }
102312
- thinkingSection.classList.add("completed");
102313
- this.thinkingSection = void 0;
102801
+ if (this.requestImmediateThinkingChunkFlushForFinish()) return;
102802
+ this.completeThinkingSection();
102314
102803
  }
102315
102804
  // === MARKDOWN EVENTS (Inside Generation Bubble) ===
102316
102805
  handleMarkdownStart(genseq, timestamp2) {
@@ -102328,9 +102817,19 @@ class DomindsDialogContainer extends HTMLElement {
102328
102817
  const body = bubble.querySelector(".bubble-body");
102329
102818
  (body || bubble).appendChild(markdownSection);
102330
102819
  this.markdownSection = markdownSection;
102820
+ this.pendingMarkdownChunkBuffer = "";
102821
+ this.clearPendingMarkdownChunkFlushTimer();
102822
+ this.clearPendingMarkdownChunkFlushRaf();
102331
102823
  this.scrollToBottom();
102332
102824
  }
102333
102825
  handleMarkdownChunk(genseq, chunk, timestamp2) {
102826
+ if (this.generationBubble && this.generationBubble.getAttribute("data-seq") !== String(genseq) && this.markdownSection) {
102827
+ console.warn("markdown_chunk_evt genseq mismatch with active markdown section, skipping", {
102828
+ activeSeq: this.generationBubble.getAttribute("data-seq"),
102829
+ genseq
102830
+ });
102831
+ return;
102832
+ }
102334
102833
  if (!this.markdownSection) {
102335
102834
  this.handleMarkdownStart(genseq, timestamp2);
102336
102835
  }
@@ -102338,16 +102837,19 @@ class DomindsDialogContainer extends HTMLElement {
102338
102837
  console.warn("markdown_chunk_evt received without markdown section, skipping");
102339
102838
  return;
102340
102839
  }
102341
- this.markdownSection.appendChunk(chunk);
102342
- this.scrollToBottom();
102840
+ this.pendingMarkdownChunkBuffer += chunk;
102841
+ this.scheduleMarkdownChunkFlush();
102343
102842
  }
102344
- handleMarkdownFinish(_genseq) {
102345
- if (!this.markdownSection) {
102346
- console.warn("markdown_finish_evt received without active markdown section, skipping");
102843
+ handleMarkdownFinish(genseq) {
102844
+ if (this.generationBubble && this.generationBubble.getAttribute("data-seq") !== String(genseq) && this.markdownSection) {
102845
+ console.warn("markdown_finish_evt genseq mismatch with active markdown section, skipping", {
102846
+ activeSeq: this.generationBubble.getAttribute("data-seq"),
102847
+ genseq
102848
+ });
102347
102849
  return;
102348
102850
  }
102349
- this.markdownSection.classList.add("completed");
102350
- this.markdownSection = void 0;
102851
+ if (this.requestImmediateMarkdownChunkFlushForFinish()) return;
102852
+ this.completeMarkdownSection();
102351
102853
  }
102352
102854
  handleUiOnlyMarkdown(event) {
102353
102855
  const content = typeof event.content === "string" ? event.content.trim() : "";
@@ -102368,17 +102870,16 @@ class DomindsDialogContainer extends HTMLElement {
102368
102870
  this.scrollToBottom();
102369
102871
  }
102370
102872
  // === FUNCTION CALL EVENTS (Non-streaming mode) ===
102371
- handleFuncCallRequested(funcId, funcName, argumentsStr) {
102372
- if (!this.generationBubble) {
102873
+ handleFuncCallRequested(genseq, funcId, funcName, argumentsStr, timestamp2) {
102874
+ const bubble = this.ensureGenerationBubbleForSeq(genseq, timestamp2);
102875
+ if (!bubble) {
102373
102876
  console.warn("func_call_requested_evt received without generation bubble, skipping");
102374
102877
  return;
102375
102878
  }
102376
102879
  const funcCallSection = this.createFuncCallSection(funcId, funcName, argumentsStr);
102377
- if (typeof this.activeGenSeq === "number") {
102378
- funcCallSection.setAttribute("data-genseq", String(this.activeGenSeq));
102379
- }
102380
- const body = this.generationBubble.querySelector(".bubble-body");
102381
- (body || this.generationBubble).appendChild(funcCallSection);
102880
+ funcCallSection.setAttribute("data-genseq", String(genseq));
102881
+ const body = bubble.querySelector(".bubble-body");
102882
+ (body || bubble).appendChild(funcCallSection);
102382
102883
  this.setupFuncCallArgsProgressiveExpand(funcCallSection);
102383
102884
  this.scrollToBottom();
102384
102885
  }
@@ -102846,9 +103347,9 @@ itemId: ${itemId}` : ""}` : `itemId: ${itemId}`;
102846
103347
  stepParent,
102847
103348
  label,
102848
103349
  // Dialog blocks can still grow after first render while content streams in. Observe only
102849
- // the target itself and stop as soon as the first overflow threshold is crossed.
103350
+ // the target itself while its expand footer is hidden.
102850
103351
  observeTargetUntilOverflow: true,
102851
- onAfterExpandStep: () => {
103352
+ onAfterExpand: () => {
102852
103353
  this.scrollToBottom();
102853
103354
  }
102854
103355
  });
@@ -102984,6 +103485,9 @@ itemId: ${itemId}` : ""}` : `itemId: ${itemId}`;
102984
103485
  makeToolResultImageStatusKey(genseq, toolCallId, relPath) {
102985
103486
  return `${String(genseq)}::${toolCallId}::${relPath}`;
102986
103487
  }
103488
+ makeUserImageStatusKey(genseq, relPath) {
103489
+ return `${String(genseq)}::${relPath}`;
103490
+ }
102987
103491
  updateToolResultImageStatusDisplay(args) {
102988
103492
  const key = this.makeToolResultImageStatusKey(args.genseq, args.toolCallId, args.relPath);
102989
103493
  this.toolResultImageStatusByKey.set(key, {
@@ -103005,12 +103509,35 @@ itemId: ${itemId}` : ""}` : `itemId: ${itemId}`;
103005
103509
  disposition: event.disposition
103006
103510
  });
103007
103511
  }
103512
+ updateUserImageStatusDisplay(args) {
103513
+ const key = this.makeUserImageStatusKey(args.genseq, args.relPath);
103514
+ this.userImageStatusByKey.set(key, {
103515
+ message: args.message,
103516
+ disposition: args.disposition,
103517
+ genseq: args.genseq
103518
+ });
103519
+ const existing = this.userImageStatusElByKey.get(key);
103520
+ if (!existing) return;
103521
+ existing.textContent = args.message;
103522
+ existing.setAttribute("data-image-ingest-disposition", args.disposition);
103523
+ }
103524
+ handleUserImageIngest(event) {
103525
+ this.updateUserImageStatusDisplay({
103526
+ genseq: event.genseq,
103527
+ relPath: event.artifact.relPath,
103528
+ message: event.message,
103529
+ disposition: event.disposition
103530
+ });
103531
+ }
103008
103532
  // === FUNCTION RESULTS ===
103009
103533
  handleFuncResult(event) {
103010
103534
  if (event.id) {
103011
- const funcCallSection = this.generationBubble?.querySelector(
103012
- `.func-call-section[data-func-id="${event.id}"]`
103013
- );
103535
+ const activeBubble = this.generationBubble;
103536
+ const funcCallSection = activeBubble && activeBubble.getAttribute("data-seq") === String(event.genseq) ? activeBubble.querySelector(
103537
+ `.func-call-section[data-func-id="${event.id}"][data-genseq="${String(event.genseq)}"]`
103538
+ ) : this.shadowRoot?.querySelector(
103539
+ `.func-call-section[data-func-id="${event.id}"][data-genseq="${String(event.genseq)}"]`
103540
+ ) ?? null;
103014
103541
  if (funcCallSection) {
103015
103542
  const resultEl = funcCallSection.querySelector(".func-call-result");
103016
103543
  if (resultEl) {
@@ -103071,44 +103598,11 @@ itemId: ${itemId}` : ""}` : `itemId: ${itemId}`;
103071
103598
  figure.appendChild(img);
103072
103599
  figure.appendChild(ingestStatus);
103073
103600
  resultEl.appendChild(figure);
103074
- const api = getApiClient();
103075
- const params = new URLSearchParams();
103076
- params.set("path", item.artifact.relPath);
103077
- params.set(
103078
- "status",
103079
- item.artifact.status ?? this.currentDialog?.status ?? "running"
103080
- );
103081
- const endpoint = `/api/dialogs/${encodeURIComponent(item.artifact.rootId)}/${encodeURIComponent(
103082
- item.artifact.selfId
103083
- )}/artifact?${params.toString()}`;
103084
- void (async () => {
103085
- try {
103086
- const response = await api.fetchBlob(endpoint);
103087
- if (!response.success || !response.data) {
103088
- placeholder.textContent = response.error ? `Failed to load image: ${response.error}` : "Failed to load image";
103089
- return;
103090
- }
103091
- const objectUrl = URL.createObjectURL(response.data);
103092
- img.src = objectUrl;
103093
- placeholder.remove();
103094
- img.addEventListener(
103095
- "load",
103096
- () => {
103097
- URL.revokeObjectURL(objectUrl);
103098
- },
103099
- { once: true }
103100
- );
103101
- img.addEventListener(
103102
- "error",
103103
- () => {
103104
- URL.revokeObjectURL(objectUrl);
103105
- },
103106
- { once: true }
103107
- );
103108
- } catch (err) {
103109
- placeholder.textContent = `Failed to load image: ${err instanceof Error ? err.message : String(err)}`;
103110
- }
103111
- })();
103601
+ this.loadArtifactImageIntoElement({
103602
+ img,
103603
+ placeholder,
103604
+ endpoint: this.buildDialogArtifactEndpoint(item)
103605
+ });
103112
103606
  continue;
103113
103607
  }
103114
103608
  }
@@ -103994,6 +104488,89 @@ ${event.content}`;
103994
104488
  upsertUserPlainTextMessage(body, rawContent) {
103995
104489
  this.upsertUserMessageByOrigin(body, rawContent, "user");
103996
104490
  }
104491
+ buildDialogArtifactEndpoint(item) {
104492
+ const params = new URLSearchParams();
104493
+ params.set("path", item.artifact.relPath);
104494
+ params.set("status", item.artifact.status ?? this.currentDialog?.status ?? "running");
104495
+ return `/api/dialogs/${encodeURIComponent(item.artifact.rootId)}/${encodeURIComponent(
104496
+ item.artifact.selfId
104497
+ )}/artifact?${params.toString()}`;
104498
+ }
104499
+ loadArtifactImageIntoElement(args) {
104500
+ const api = getApiClient();
104501
+ void (async () => {
104502
+ try {
104503
+ const response = await api.fetchBlob(args.endpoint);
104504
+ if (!response.success || !response.data) {
104505
+ args.placeholder.textContent = response.error ? `Failed to load image: ${response.error}` : "Failed to load image";
104506
+ return;
104507
+ }
104508
+ const objectUrl = URL.createObjectURL(response.data);
104509
+ args.img.src = objectUrl;
104510
+ args.placeholder.remove();
104511
+ args.img.addEventListener(
104512
+ "load",
104513
+ () => {
104514
+ URL.revokeObjectURL(objectUrl);
104515
+ },
104516
+ { once: true }
104517
+ );
104518
+ args.img.addEventListener(
104519
+ "error",
104520
+ () => {
104521
+ URL.revokeObjectURL(objectUrl);
104522
+ },
104523
+ { once: true }
104524
+ );
104525
+ } catch (err) {
104526
+ args.placeholder.textContent = `Failed to load image: ${err instanceof Error ? err.message : String(err)}`;
104527
+ }
104528
+ })();
104529
+ }
104530
+ upsertUserContentItems(body, contentItems, msgId, genseq) {
104531
+ const divider2 = body.querySelector(".user-response-divider");
104532
+ body.querySelectorAll(".user-attachment-strip").forEach((node2) => node2.remove());
104533
+ if (!Array.isArray(contentItems) || contentItems.length === 0) return;
104534
+ const imageItems = contentItems.filter((item) => item.type === "input_image");
104535
+ if (imageItems.length === 0) return;
104536
+ const strip = document.createElement("div");
104537
+ strip.className = "user-attachment-strip";
104538
+ for (const item of imageItems) {
104539
+ const figure = document.createElement("figure");
104540
+ figure.className = "tool-result-image user-attachment-image";
104541
+ figure.setAttribute("data-user-msg-id", msgId);
104542
+ figure.setAttribute("data-artifact-rel-path", item.artifact.relPath);
104543
+ const img = document.createElement("img");
104544
+ img.alt = "attached image";
104545
+ const placeholder = document.createElement("span");
104546
+ placeholder.textContent = `Loading image (${item.mimeType}, ${String(item.byteLength)} bytes)…`;
104547
+ const ingestStatus = document.createElement("figcaption");
104548
+ ingestStatus.className = "tool-result-image-ingest-status";
104549
+ if (typeof genseq === "number") {
104550
+ const imageStatusKey = this.makeUserImageStatusKey(genseq, item.artifact.relPath);
104551
+ this.userImageStatusElByKey.set(imageStatusKey, ingestStatus);
104552
+ const existingStatus = this.userImageStatusByKey.get(imageStatusKey);
104553
+ if (existingStatus) {
104554
+ ingestStatus.textContent = existingStatus.message;
104555
+ ingestStatus.setAttribute("data-image-ingest-disposition", existingStatus.disposition);
104556
+ }
104557
+ }
104558
+ figure.appendChild(placeholder);
104559
+ figure.appendChild(img);
104560
+ figure.appendChild(ingestStatus);
104561
+ strip.appendChild(figure);
104562
+ this.loadArtifactImageIntoElement({
104563
+ img,
104564
+ placeholder,
104565
+ endpoint: this.buildDialogArtifactEndpoint(item)
104566
+ });
104567
+ }
104568
+ if (divider2 instanceof HTMLElement) {
104569
+ body.insertBefore(strip, divider2);
104570
+ return;
104571
+ }
104572
+ body.appendChild(strip);
104573
+ }
103997
104574
  upsertUserMessageByOrigin(body, rawContent, origin) {
103998
104575
  const renderAsPlainText = origin === "user" || origin === void 0;
103999
104576
  let divider2 = null;
@@ -104092,6 +104669,7 @@ ${event.content}`;
104092
104669
  }
104093
104670
  if (body.querySelector(".user-response-divider")) {
104094
104671
  this.upsertUserMessageByOrigin(body, event.content, event.origin);
104672
+ this.upsertUserContentItems(body, event.contentItems, event.msgId, event.genseq);
104095
104673
  bubble.setAttribute("data-user-msg-id", event.msgId);
104096
104674
  bubble.setAttribute("data-raw-user-msg", event.content);
104097
104675
  bubble.setAttribute("data-user-msg-origin", event.origin);
@@ -104120,6 +104698,7 @@ ${event.content}`;
104120
104698
  divider2.className = "user-response-divider";
104121
104699
  body.appendChild(divider2);
104122
104700
  this.upsertUserMessageByOrigin(body, event.content, event.origin);
104701
+ this.upsertUserContentItems(body, event.contentItems, event.msgId, event.genseq);
104123
104702
  bubble.setAttribute("data-user-msg-id", event.msgId);
104124
104703
  bubble.setAttribute("data-raw-user-msg", event.content);
104125
104704
  bubble.setAttribute("data-user-msg-origin", event.origin);
@@ -104319,8 +104898,9 @@ ${event.content}`;
104319
104898
  `;
104320
104899
  return el;
104321
104900
  }
104322
- handleError(err) {
104323
- if (!this.generationBubble) return;
104901
+ handleError(err, bubble) {
104902
+ const targetBubble = bubble ?? this.generationBubble ?? void 0;
104903
+ if (!targetBubble) return;
104324
104904
  const el = document.createElement("div");
104325
104905
  el.className = "error-section";
104326
104906
  el.innerHTML = `
@@ -104330,8 +104910,8 @@ ${event.content}`;
104330
104910
  </div>
104331
104911
  <div class="error-content">${err}</div>
104332
104912
  `;
104333
- const body = this.generationBubble.querySelector(".bubble-body");
104334
- (body || this.generationBubble).appendChild(el);
104913
+ const body = targetBubble.querySelector(".bubble-body");
104914
+ (body || targetBubble).appendChild(el);
104335
104915
  this.scrollToBottom();
104336
104916
  }
104337
104917
  summarizeRetryError(raw) {
@@ -104938,6 +105518,15 @@ ${event.content}`;
104938
105518
  margin: 6px 0;
104939
105519
  }
104940
105520
 
105521
+ .user-attachment-strip {
105522
+ display: block;
105523
+ padding: 2px 3px 2px 6px;
105524
+ }
105525
+
105526
+ .user-attachment-image {
105527
+ max-width: min(100%, 520px);
105528
+ }
105529
+
104941
105530
  .user-answer-callsite-actions {
104942
105531
  display: inline-flex;
104943
105532
  align-items: center;
@@ -105517,14 +106106,15 @@ ${event.content}`;
105517
106106
  }
105518
106107
 
105519
106108
  .tool-result-image-ingest-status {
105520
- margin-top: 6px;
105521
- font-size: var(--dominds-font-size-xs, 11px);
105522
- line-height: 1.45;
106109
+ margin-top: 8px;
106110
+ font-size: 12px;
106111
+ line-height: 1.6;
105523
106112
  color: var(--dominds-fg-muted, var(--color-fg-tertiary, #64748b));
105524
106113
  }
105525
106114
 
105526
106115
  .tool-result-image-ingest-status[data-image-ingest-disposition^='filtered_'] {
105527
106116
  color: var(--color-warning-strong, #b45309);
106117
+ font-weight: 500;
105528
106118
  }
105529
106119
 
105530
106120
  .func-call-section.failed {
@@ -106391,6 +106981,28 @@ const RESIZE_HANDLE_ARIA_LABEL_I18N = {
106391
106981
  zh: "调整输入区高度",
106392
106982
  en: "Resize input height"
106393
106983
  };
106984
+ const IMAGE_ATTACHMENT_I18N = {
106985
+ zh: {
106986
+ remove: "移除图片",
106987
+ preview: "查看图片",
106988
+ close: "关闭图片预览",
106989
+ tooMany: "最多只能添加 10 张图片",
106990
+ tooLarge: "单张图片不能超过 10 MB",
106991
+ unsupported: "只支持 PNG、JPEG、WebP、GIF 图片",
106992
+ readFailed: "读取图片失败",
106993
+ imageOnlyPrompt: "请看附件图片。"
106994
+ },
106995
+ en: {
106996
+ remove: "Remove image",
106997
+ preview: "View image",
106998
+ close: "Close image preview",
106999
+ tooMany: "You can attach up to 10 images",
107000
+ tooLarge: "Each image must be 10 MB or smaller",
107001
+ unsupported: "Only PNG, JPEG, WebP, and GIF images are supported",
107002
+ readFailed: "Failed to read image",
107003
+ imageOnlyPrompt: "Please inspect the attached image."
107004
+ }
107005
+ };
106394
107006
  const _DomindsQ4HInput = class _DomindsQ4HInput extends HTMLElement {
106395
107007
  constructor() {
106396
107008
  super();
@@ -106414,6 +107026,9 @@ const _DomindsQ4HInput = class _DomindsQ4HInput extends HTMLElement {
106414
107026
  this.inputHistory = [];
106415
107027
  this.inputHistoryCursor = null;
106416
107028
  this.inputHistoryDraft = null;
107029
+ this.imageAttachments = [];
107030
+ this.openImageAttachmentId = null;
107031
+ this.imageDragDepth = 0;
106417
107032
  this.manualHeightPx = null;
106418
107033
  this.autoResizeBaseHostHeightPx = null;
106419
107034
  this.autoResizeCaptureArmed = false;
@@ -106468,6 +107083,7 @@ const _DomindsQ4HInput = class _DomindsQ4HInput extends HTMLElement {
106468
107083
  window.cancelAnimationFrame(this.inputUiRafId);
106469
107084
  this.inputUiRafId = null;
106470
107085
  }
107086
+ this.revokeImageAttachments();
106471
107087
  this.finishManualResize(false);
106472
107088
  if (this.boundOnWindowResize) {
106473
107089
  window.removeEventListener("resize", this.boundOnWindowResize);
@@ -106599,6 +107215,137 @@ const _DomindsQ4HInput = class _DomindsQ4HInput extends HTMLElement {
106599
107215
  measurer.value = value.length > 0 ? value : " ";
106600
107216
  return measurer.scrollHeight;
106601
107217
  }
107218
+ getAttachmentStripHeightPx() {
107219
+ const strip = this.shadowRoot?.querySelector(".attachment-strip");
107220
+ if (!(strip instanceof HTMLElement)) {
107221
+ return 0;
107222
+ }
107223
+ const rect2 = strip.getBoundingClientRect();
107224
+ if (rect2.height > 0) {
107225
+ return rect2.height;
107226
+ }
107227
+ return strip.offsetHeight;
107228
+ }
107229
+ static escapeHtml(value) {
107230
+ return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
107231
+ }
107232
+ revokeImageAttachments() {
107233
+ for (const attachment of this.imageAttachments) {
107234
+ URL.revokeObjectURL(attachment.objectUrl);
107235
+ }
107236
+ this.imageAttachments = [];
107237
+ this.openImageAttachmentId = null;
107238
+ }
107239
+ isSupportedImageMimeType(mimeType) {
107240
+ return mimeType === "image/png" || mimeType === "image/jpeg" || mimeType === "image/webp" || mimeType === "image/gif";
107241
+ }
107242
+ makeAttachmentId() {
107243
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
107244
+ return crypto.randomUUID();
107245
+ }
107246
+ return `img_${Date.now()}_${Math.random().toString(16).slice(2)}`;
107247
+ }
107248
+ async fileToBase64(file) {
107249
+ return await new Promise((resolve, reject) => {
107250
+ const reader = new FileReader();
107251
+ reader.onload = () => {
107252
+ const result = reader.result;
107253
+ if (typeof result !== "string") {
107254
+ reject(new Error("FileReader returned non-string result"));
107255
+ return;
107256
+ }
107257
+ const commaIndex = result.indexOf(",");
107258
+ if (commaIndex < 0) {
107259
+ reject(new Error("FileReader data URL missing payload"));
107260
+ return;
107261
+ }
107262
+ resolve(result.slice(commaIndex + 1));
107263
+ };
107264
+ reader.onerror = () => reject(reader.error ?? new Error("FileReader failed"));
107265
+ reader.readAsDataURL(file);
107266
+ });
107267
+ }
107268
+ async addImageFiles(files) {
107269
+ const t2 = IMAGE_ATTACHMENT_I18N[this.uiLanguage];
107270
+ const imageFiles = files.filter((file) => file.type.startsWith("image/"));
107271
+ if (imageFiles.length === 0) return;
107272
+ if (this.imageAttachments.length + imageFiles.length > _DomindsQ4HInput.IMAGE_ATTACHMENT_MAX_COUNT) {
107273
+ throw new Error(t2.tooMany);
107274
+ }
107275
+ const nextAttachments = [];
107276
+ try {
107277
+ for (const file of imageFiles) {
107278
+ if (!this.isSupportedImageMimeType(file.type)) {
107279
+ throw new Error(t2.unsupported);
107280
+ }
107281
+ if (file.size <= 0 || file.size > _DomindsQ4HInput.IMAGE_ATTACHMENT_MAX_BYTES) {
107282
+ throw new Error(t2.tooLarge);
107283
+ }
107284
+ nextAttachments.push({
107285
+ id: this.makeAttachmentId(),
107286
+ mimeType: file.type,
107287
+ byteLength: file.size,
107288
+ dataBase64: await this.fileToBase64(file),
107289
+ objectUrl: URL.createObjectURL(file),
107290
+ name: file.name.trim() || file.type
107291
+ });
107292
+ }
107293
+ } catch (error2) {
107294
+ for (const attachment of nextAttachments) {
107295
+ URL.revokeObjectURL(attachment.objectUrl);
107296
+ }
107297
+ throw error2;
107298
+ }
107299
+ this.imageAttachments = [...this.imageAttachments, ...nextAttachments];
107300
+ this.safeRender();
107301
+ this.scheduleInputUiUpdate();
107302
+ }
107303
+ hasDraggedFiles(event) {
107304
+ const dataTransfer = event.dataTransfer;
107305
+ if (dataTransfer === null) return false;
107306
+ return Array.from(dataTransfer.types).includes("Files");
107307
+ }
107308
+ setImageDropActive(active) {
107309
+ this.inputWrapper.classList.toggle("image-drop-active", active && !this.props.disabled);
107310
+ }
107311
+ resetImageDragState() {
107312
+ this.imageDragDepth = 0;
107313
+ if (this.inputWrapper) {
107314
+ this.inputWrapper.classList.remove("image-drop-active");
107315
+ }
107316
+ }
107317
+ handleDroppedImageFiles(files) {
107318
+ if (this.props.disabled) {
107319
+ const t2 = getUiStrings(this.uiLanguage);
107320
+ this.showError(t2.inputNotAvailableToast);
107321
+ return;
107322
+ }
107323
+ void this.addImageFiles(files).catch((error2) => {
107324
+ console.error("Failed to add dropped image:", error2);
107325
+ const t2 = IMAGE_ATTACHMENT_I18N[this.uiLanguage];
107326
+ this.showError(error2 instanceof Error ? error2.message : t2.readFailed);
107327
+ });
107328
+ }
107329
+ removeImageAttachment(id28) {
107330
+ const existing = this.imageAttachments.find((attachment) => attachment.id === id28);
107331
+ if (existing) {
107332
+ URL.revokeObjectURL(existing.objectUrl);
107333
+ }
107334
+ this.imageAttachments = this.imageAttachments.filter((attachment) => attachment.id !== id28);
107335
+ if (this.openImageAttachmentId === id28) {
107336
+ this.openImageAttachmentId = null;
107337
+ }
107338
+ this.safeRender();
107339
+ this.scheduleInputUiUpdate();
107340
+ }
107341
+ getOutgoingAttachments() {
107342
+ return this.imageAttachments.map((attachment) => ({
107343
+ kind: "image",
107344
+ mimeType: attachment.mimeType,
107345
+ byteLength: attachment.byteLength,
107346
+ dataBase64: attachment.dataBase64
107347
+ }));
107348
+ }
106602
107349
  setUiLanguage(language2) {
106603
107350
  this.uiLanguage = language2;
106604
107351
  const t2 = getUiStrings(language2);
@@ -106679,7 +107426,7 @@ const _DomindsQ4HInput = class _DomindsQ4HInput extends HTMLElement {
106679
107426
  resolvePrimaryActionMode() {
106680
107427
  if (this.hasSelectedQ4HTarget()) return "send";
106681
107428
  if (this.currentDialog === null) return "send";
106682
- const hasContent = (this.textInput?.value ?? "").trim().length > 0;
107429
+ const hasContent = (this.textInput?.value ?? "").trim().length > 0 || this.imageAttachments.length > 0;
106683
107430
  const state2 = this.displayState;
106684
107431
  if (state2 === null) return "send";
106685
107432
  if (state2.kind === "proceeding_stop_requested") return "stopping";
@@ -106814,8 +107561,10 @@ const _DomindsQ4HInput = class _DomindsQ4HInput extends HTMLElement {
106814
107561
  if (this.textInput) {
106815
107562
  this.textInput.value = "";
106816
107563
  this.resetInputHistoryNavigation();
107564
+ this.revokeImageAttachments();
106817
107565
  this.updateSendButton();
106818
107566
  this.autoResizeTextarea();
107567
+ this.safeRender();
106819
107568
  }
106820
107569
  }
106821
107570
  getValue() {
@@ -106882,16 +107631,22 @@ const _DomindsQ4HInput = class _DomindsQ4HInput extends HTMLElement {
106882
107631
  if (!this.textInput) return;
106883
107632
  const previousHostHeightPx = this.getCurrentHostHeightPx();
106884
107633
  const hostChromeHeightPx = this.getHostChromeHeightPx();
106885
- const minHeight = Math.max(0, this.manualResizeMinPx - hostChromeHeightPx);
107634
+ const attachmentStripHeightPx = this.getAttachmentStripHeightPx();
107635
+ const minHeight = Math.max(
107636
+ 0,
107637
+ this.manualResizeMinPx - hostChromeHeightPx - attachmentStripHeightPx
107638
+ );
106886
107639
  const maxHeight = Math.max(
106887
107640
  minHeight,
106888
- Math.floor(window.innerHeight * _DomindsQ4HInput.AUTO_RESIZE_MAX_VIEWPORT_RATIO) - hostChromeHeightPx
107641
+ Math.floor(window.innerHeight * _DomindsQ4HInput.AUTO_RESIZE_MAX_VIEWPORT_RATIO) - hostChromeHeightPx - attachmentStripHeightPx
106889
107642
  );
106890
107643
  this.textInput.style.height = "";
106891
107644
  const scrollHeight = this.getMeasuredTextareaScrollHeightPx();
106892
107645
  const desiredTextHeight = scrollHeight <= minHeight + 1 ? minHeight : scrollHeight + _DomindsQ4HInput.AUTO_RESIZE_EXTRA_GAP_PX;
106893
107646
  const nextHeight = Math.max(minHeight, Math.min(desiredTextHeight, maxHeight));
106894
- const desiredHostHeightPx = Math.ceil(hostChromeHeightPx + nextHeight);
107647
+ const desiredHostHeightPx = Math.ceil(
107648
+ hostChromeHeightPx + attachmentStripHeightPx + nextHeight
107649
+ );
106895
107650
  const baselineHostHeightPx = this.getBaselineHostHeightPx();
106896
107651
  if (baselineHostHeightPx !== null) {
106897
107652
  this.autoResizeCaptureArmed = true;
@@ -106967,6 +107722,18 @@ const _DomindsQ4HInput = class _DomindsQ4HInput extends HTMLElement {
106967
107722
  }
106968
107723
  this.scheduleInputUiUpdate();
106969
107724
  });
107725
+ this.textInput.addEventListener("paste", (event) => {
107726
+ const items = event.clipboardData?.items;
107727
+ if (!items || items.length === 0) return;
107728
+ const files = Array.from(items).filter((item) => item.kind === "file" && item.type.startsWith("image/")).map((item) => item.getAsFile()).filter((file) => file !== null);
107729
+ if (files.length === 0) return;
107730
+ event.preventDefault();
107731
+ void this.addImageFiles(files).catch((error2) => {
107732
+ console.error("Failed to add pasted image:", error2);
107733
+ const t2 = IMAGE_ATTACHMENT_I18N[this.uiLanguage];
107734
+ this.showError(error2 instanceof Error ? error2.message : t2.readFailed);
107735
+ });
107736
+ });
106970
107737
  this.textInput.addEventListener("keydown", (e2) => {
106971
107738
  const isIme = this.isComposing || e2.isComposing || e2.keyCode === 229;
106972
107739
  if (!isIme && e2.key === "ArrowUp") {
@@ -106992,7 +107759,7 @@ const _DomindsQ4HInput = class _DomindsQ4HInput extends HTMLElement {
106992
107759
  }
106993
107760
  if (e2.key === "Escape") {
106994
107761
  if (isIme) return;
106995
- const hasContent = this.textInput.value.length > 0;
107762
+ const hasContent = this.textInput.value.length > 0 || this.imageAttachments.length > 0;
106996
107763
  if (!hasContent) {
106997
107764
  this.escPrimedAtMs = null;
106998
107765
  return;
@@ -107036,6 +107803,44 @@ const _DomindsQ4HInput = class _DomindsQ4HInput extends HTMLElement {
107036
107803
  }
107037
107804
  });
107038
107805
  }
107806
+ if (this.inputWrapper) {
107807
+ this.inputWrapper.addEventListener("dragenter", (event) => {
107808
+ if (!this.hasDraggedFiles(event)) return;
107809
+ event.preventDefault();
107810
+ event.stopPropagation();
107811
+ this.imageDragDepth += 1;
107812
+ this.setImageDropActive(true);
107813
+ });
107814
+ this.inputWrapper.addEventListener("dragover", (event) => {
107815
+ if (!this.hasDraggedFiles(event)) return;
107816
+ event.preventDefault();
107817
+ event.stopPropagation();
107818
+ const dataTransfer = event.dataTransfer;
107819
+ if (dataTransfer !== null) {
107820
+ dataTransfer.dropEffect = this.props.disabled ? "none" : "copy";
107821
+ }
107822
+ this.setImageDropActive(true);
107823
+ });
107824
+ this.inputWrapper.addEventListener("dragleave", (event) => {
107825
+ if (!this.hasDraggedFiles(event)) return;
107826
+ event.preventDefault();
107827
+ event.stopPropagation();
107828
+ this.imageDragDepth = Math.max(0, this.imageDragDepth - 1);
107829
+ if (this.imageDragDepth === 0) {
107830
+ this.setImageDropActive(false);
107831
+ }
107832
+ });
107833
+ this.inputWrapper.addEventListener("drop", (event) => {
107834
+ if (!this.hasDraggedFiles(event)) return;
107835
+ event.preventDefault();
107836
+ event.stopPropagation();
107837
+ const dataTransfer = event.dataTransfer;
107838
+ const files = dataTransfer === null ? [] : Array.from(dataTransfer.files);
107839
+ this.resetImageDragState();
107840
+ if (files.length === 0) return;
107841
+ this.handleDroppedImageFiles(files);
107842
+ });
107843
+ }
107039
107844
  const toggleBtn = this.shadowRoot.querySelector(".send-on-enter-toggle");
107040
107845
  if (toggleBtn) {
107041
107846
  toggleBtn.addEventListener("click", () => {
@@ -107101,6 +107906,33 @@ const _DomindsQ4HInput = class _DomindsQ4HInput extends HTMLElement {
107101
107906
  this.resizeHandle.addEventListener("lostpointercapture", this.boundManualLostCapture);
107102
107907
  });
107103
107908
  }
107909
+ this.shadowRoot.querySelectorAll(".attachment-thumb").forEach((button) => {
107910
+ button.addEventListener("click", () => {
107911
+ const id28 = button.dataset.attachmentId;
107912
+ if (typeof id28 !== "string") return;
107913
+ this.openImageAttachmentId = id28;
107914
+ this.safeRender();
107915
+ });
107916
+ });
107917
+ this.shadowRoot.querySelectorAll(".attachment-remove").forEach((button) => {
107918
+ button.addEventListener("click", (event) => {
107919
+ event.preventDefault();
107920
+ event.stopPropagation();
107921
+ const id28 = button.dataset.attachmentId;
107922
+ if (typeof id28 !== "string") return;
107923
+ this.removeImageAttachment(id28);
107924
+ });
107925
+ });
107926
+ const modalCloseTargets = this.shadowRoot.querySelectorAll(
107927
+ ".image-modal-backdrop, .image-modal-close"
107928
+ );
107929
+ modalCloseTargets.forEach((target) => {
107930
+ target.addEventListener("click", () => {
107931
+ this.openImageAttachmentId = null;
107932
+ this.safeRender();
107933
+ this.focusInput();
107934
+ });
107935
+ });
107104
107936
  }
107105
107937
  async requestDeclareDeath() {
107106
107938
  const t2 = getUiStrings(this.uiLanguage);
@@ -107118,6 +107950,9 @@ const _DomindsQ4HInput = class _DomindsQ4HInput extends HTMLElement {
107118
107950
  if (this.props.disabled) {
107119
107951
  throw new Error(t2.inputNotAvailableToast);
107120
107952
  }
107953
+ if (!this.wsManager.isConnected()) {
107954
+ throw new Error(t2.q4hConnectionUnavailableToast);
107955
+ }
107121
107956
  const ok = window.confirm(this.getDeclareDeathConfirmText());
107122
107957
  if (!ok) return;
107123
107958
  const note2 = this.textInput ? this.textInput.value : "";
@@ -107177,7 +108012,11 @@ const _DomindsQ4HInput = class _DomindsQ4HInput extends HTMLElement {
107177
108012
  }
107178
108013
  async sendMessage() {
107179
108014
  const t2 = getUiStrings(this.uiLanguage);
107180
- const content = this.textInput.value.trim();
108015
+ const attachmentI18n = IMAGE_ATTACHMENT_I18N[this.uiLanguage];
108016
+ const hasAttachments = this.imageAttachments.length > 0;
108017
+ const typedContent = this.textInput.value.trim();
108018
+ const content = typedContent || (hasAttachments ? attachmentI18n.imageOnlyPrompt : "");
108019
+ const attachments = this.getOutgoingAttachments();
107181
108020
  const answeredQuestionId = this.selectedQuestionId;
107182
108021
  const answeredQuestion = answeredQuestionId !== null ? this.questions.find((q2) => q2.id === answeredQuestionId) ?? null : null;
107183
108022
  if (answeredQuestionId !== null && answeredQuestion === null) {
@@ -107187,7 +108026,7 @@ const _DomindsQ4HInput = class _DomindsQ4HInput extends HTMLElement {
107187
108026
  selfId: answeredQuestion.dialogContext.selfId,
107188
108027
  rootId: answeredQuestion.dialogContext.rootId
107189
108028
  } : this.currentDialog;
107190
- if (!content) {
108029
+ if (!content && attachments.length === 0) {
107191
108030
  throw new Error(t2.q4hMessageEmptyToast);
107192
108031
  }
107193
108032
  if (!targetDialog) {
@@ -107196,6 +108035,9 @@ const _DomindsQ4HInput = class _DomindsQ4HInput extends HTMLElement {
107196
108035
  if (this.props.disabled) {
107197
108036
  throw new Error(t2.inputNotAvailableToast);
107198
108037
  }
108038
+ if (!this.wsManager.isConnected()) {
108039
+ throw new Error(t2.q4hConnectionUnavailableToast);
108040
+ }
107199
108041
  const msgId = idExports.generateShortId();
107200
108042
  try {
107201
108043
  const sr = this.shadowRoot;
@@ -107205,6 +108047,7 @@ const _DomindsQ4HInput = class _DomindsQ4HInput extends HTMLElement {
107205
108047
  this.sendHumanReply({
107206
108048
  targetDialog,
107207
108049
  content,
108050
+ attachments,
107208
108051
  msgId,
107209
108052
  questionId: answeredQuestion.id
107210
108053
  });
@@ -107214,11 +108057,12 @@ const _DomindsQ4HInput = class _DomindsQ4HInput extends HTMLElement {
107214
108057
  type: "drive_dlg_by_user_msg",
107215
108058
  dialog: targetDialog,
107216
108059
  content,
108060
+ attachments,
107217
108061
  msgId,
107218
108062
  userLanguageCode: this.uiLanguage
107219
108063
  });
107220
108064
  }
107221
- this.recordInputHistoryEntry(content);
108065
+ this.recordInputHistoryEntry(typedContent);
107222
108066
  if (answeredQuestion !== null) {
107223
108067
  this.selectQuestion(null);
107224
108068
  const dialogId = answeredQuestion.dialogContext.selfId;
@@ -107259,6 +108103,7 @@ const _DomindsQ4HInput = class _DomindsQ4HInput extends HTMLElement {
107259
108103
  type: "drive_dialog_by_user_answer",
107260
108104
  dialog: args.targetDialog,
107261
108105
  content: args.content,
108106
+ attachments: args.attachments,
107262
108107
  msgId: args.msgId,
107263
108108
  questionId: args.questionId,
107264
108109
  continuationType: "answer",
@@ -107287,7 +108132,7 @@ const _DomindsQ4HInput = class _DomindsQ4HInput extends HTMLElement {
107287
108132
  this.sendButton.disabled = mode === "stopping" || !canStop;
107288
108133
  return;
107289
108134
  }
107290
- const hasContent = this.textInput.value.trim().length > 0;
108135
+ const hasContent = this.textInput.value.trim().length > 0 || this.imageAttachments.length > 0;
107291
108136
  const hasSelectedQ4H = this.hasSelectedQ4HTarget();
107292
108137
  const hasCurrentDialog = this.currentDialog !== null;
107293
108138
  const hasRoutableTarget = hasSelectedQ4H || hasCurrentDialog;
@@ -107334,6 +108179,50 @@ const _DomindsQ4HInput = class _DomindsQ4HInput extends HTMLElement {
107334
108179
  this.inputWrapper = this.shadowRoot.querySelector(".input-wrapper");
107335
108180
  this.resizeHandle = this.shadowRoot.querySelector(".input-resize-handle");
107336
108181
  }
108182
+ renderAttachmentStrip() {
108183
+ if (this.imageAttachments.length === 0) return "";
108184
+ const t2 = IMAGE_ATTACHMENT_I18N[this.uiLanguage];
108185
+ const items = this.imageAttachments.map((attachment) => {
108186
+ const id28 = _DomindsQ4HInput.escapeHtml(attachment.id);
108187
+ const name = _DomindsQ4HInput.escapeHtml(attachment.name);
108188
+ const src = _DomindsQ4HInput.escapeHtml(attachment.objectUrl);
108189
+ return `
108190
+ <div class="attachment-item">
108191
+ <button class="attachment-thumb" type="button" data-attachment-id="${id28}" title="${_DomindsQ4HInput.escapeHtml(
108192
+ t2.preview
108193
+ )}" aria-label="${_DomindsQ4HInput.escapeHtml(t2.preview)}">
108194
+ <img src="${src}" alt="${name}">
108195
+ </button>
108196
+ <button class="attachment-remove" type="button" data-attachment-id="${id28}" title="${_DomindsQ4HInput.escapeHtml(
108197
+ t2.remove
108198
+ )}" aria-label="${_DomindsQ4HInput.escapeHtml(t2.remove)}">
108199
+ <span class="icon-mask attachment-remove-icon" aria-hidden="true"></span>
108200
+ </button>
108201
+ </div>
108202
+ `;
108203
+ }).join("");
108204
+ return `<div class="attachment-strip">${items}</div>`;
108205
+ }
108206
+ renderImageModal() {
108207
+ const attachment = this.openImageAttachmentId === null ? null : this.imageAttachments.find((item) => item.id === this.openImageAttachmentId) ?? null;
108208
+ if (attachment === null) return "";
108209
+ const t2 = IMAGE_ATTACHMENT_I18N[this.uiLanguage];
108210
+ return `
108211
+ <div class="image-modal" role="dialog" aria-modal="true">
108212
+ <div class="image-modal-backdrop"></div>
108213
+ <div class="image-modal-content">
108214
+ <button class="image-modal-close" type="button" title="${_DomindsQ4HInput.escapeHtml(
108215
+ t2.close
108216
+ )}" aria-label="${_DomindsQ4HInput.escapeHtml(t2.close)}">
108217
+ <span class="icon-mask image-modal-close-icon" aria-hidden="true"></span>
108218
+ </button>
108219
+ <img src="${_DomindsQ4HInput.escapeHtml(attachment.objectUrl)}" alt="${_DomindsQ4HInput.escapeHtml(
108220
+ attachment.name
108221
+ )}">
108222
+ </div>
108223
+ </div>
108224
+ `;
108225
+ }
107337
108226
  getComponentHTML() {
107338
108227
  const t2 = getUiStrings(this.uiLanguage);
107339
108228
  const mode = this.resolvePrimaryActionMode();
@@ -107350,13 +108239,16 @@ const _DomindsQ4HInput = class _DomindsQ4HInput extends HTMLElement {
107350
108239
  <div class="input-section">
107351
108240
  <div class="input-resize-handle" role="separator" aria-orientation="horizontal" aria-label="${RESIZE_HANDLE_ARIA_LABEL_I18N[this.uiLanguage]}"></div>
107352
108241
  <div class="input-wrapper ${this.selectedQuestionId !== null ? "q4h-active" : ""} ${this.props.disabled ? "disabled" : ""}">
107353
- <textarea id="human-input"
107354
- class="message-input"
107355
- placeholder="${this.props.placeholder}"
107356
- maxlength="${this.props.maxLength}"
107357
- rows="2"
107358
- ${this.props.disabled ? "disabled" : ""}
107359
- ></textarea>
108242
+ <div class="input-body">
108243
+ <textarea id="human-input"
108244
+ class="message-input"
108245
+ placeholder="${this.props.placeholder}"
108246
+ maxlength="${this.props.maxLength}"
108247
+ rows="2"
108248
+ ${this.props.disabled ? "disabled" : ""}
108249
+ ></textarea>
108250
+ ${this.renderAttachmentStrip()}
108251
+ </div>
107360
108252
  <div class="input-actions">
107361
108253
  <button
107362
108254
  class="send-on-enter-toggle ${this.sendOnEnter ? "active" : ""}"
@@ -107378,6 +108270,7 @@ const _DomindsQ4HInput = class _DomindsQ4HInput extends HTMLElement {
107378
108270
  </div>
107379
108271
  </div>
107380
108272
  </div>
108273
+ ${this.renderImageModal()}
107381
108274
  </div>
107382
108275
  `;
107383
108276
  }
@@ -107495,6 +108388,14 @@ const _DomindsQ4HInput = class _DomindsQ4HInput extends HTMLElement {
107495
108388
  padding-bottom: 6px;
107496
108389
  }
107497
108390
 
108391
+ .input-body {
108392
+ display: flex;
108393
+ flex: 1;
108394
+ min-width: 0;
108395
+ min-height: 0;
108396
+ flex-direction: column;
108397
+ }
108398
+
107498
108399
  .declare-death-button {
107499
108400
  display: inline-flex;
107500
108401
  align-items: center;
@@ -107563,6 +108464,16 @@ const _DomindsQ4HInput = class _DomindsQ4HInput extends HTMLElement {
107563
108464
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--dominds-focus, #007acc) 20%, transparent);
107564
108465
  }
107565
108466
 
108467
+ .input-wrapper.image-drop-active {
108468
+ border-color: var(--dominds-focus, #007acc);
108469
+ background: color-mix(in srgb, var(--dominds-focus, #007acc) 10%, var(--dominds-input-bg, #f8f9fa));
108470
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--dominds-focus, #007acc) 22%, transparent);
108471
+ }
108472
+
108473
+ .input-wrapper.image-drop-active .message-input {
108474
+ cursor: copy;
108475
+ }
108476
+
107566
108477
  .input-wrapper.disabled {
107567
108478
  opacity: 0.6;
107568
108479
  background: color-mix(in srgb, var(--dominds-primary, #007acc) 3%, var(--color-bg-secondary, #f8f9fa));
@@ -107586,6 +108497,117 @@ const _DomindsQ4HInput = class _DomindsQ4HInput extends HTMLElement {
107586
108497
  overflow-y: auto;
107587
108498
  }
107588
108499
 
108500
+ .attachment-strip {
108501
+ display: flex;
108502
+ gap: 6px;
108503
+ flex-wrap: wrap;
108504
+ padding: 0 8px 8px 12px;
108505
+ min-height: 44px;
108506
+ align-items: center;
108507
+ }
108508
+
108509
+ .attachment-item {
108510
+ position: relative;
108511
+ width: 44px;
108512
+ height: 44px;
108513
+ flex: 0 0 44px;
108514
+ }
108515
+
108516
+ .attachment-thumb {
108517
+ appearance: none;
108518
+ width: 44px;
108519
+ height: 44px;
108520
+ padding: 0;
108521
+ border: 1px solid var(--dominds-border, #e0e0e0);
108522
+ border-radius: 6px;
108523
+ overflow: hidden;
108524
+ background: var(--dominds-bg-secondary, #ffffff);
108525
+ cursor: pointer;
108526
+ }
108527
+
108528
+ .attachment-thumb img {
108529
+ display: block;
108530
+ width: 100%;
108531
+ height: 100%;
108532
+ object-fit: cover;
108533
+ }
108534
+
108535
+ .attachment-remove {
108536
+ appearance: none;
108537
+ position: absolute;
108538
+ top: -5px;
108539
+ right: -5px;
108540
+ width: 18px;
108541
+ height: 18px;
108542
+ padding: 0;
108543
+ border: 1px solid var(--dominds-border, #e0e0e0);
108544
+ border-radius: 50%;
108545
+ background: var(--dominds-bg-secondary, #ffffff);
108546
+ color: var(--dominds-fg, #333333);
108547
+ display: inline-flex;
108548
+ align-items: center;
108549
+ justify-content: center;
108550
+ cursor: pointer;
108551
+ box-shadow: 0 1px 4px rgba(0, 0, 0, 0.18);
108552
+ }
108553
+
108554
+ .attachment-remove-icon,
108555
+ .image-modal-close-icon {
108556
+ --icon-mask: ${ICON_MASK_URLS.close};
108557
+ width: 12px;
108558
+ height: 12px;
108559
+ }
108560
+
108561
+ .image-modal {
108562
+ position: fixed;
108563
+ inset: 0;
108564
+ z-index: var(--dominds-z-overlay-modal, 2000);
108565
+ display: flex;
108566
+ align-items: center;
108567
+ justify-content: center;
108568
+ }
108569
+
108570
+ .image-modal-backdrop {
108571
+ position: absolute;
108572
+ inset: 0;
108573
+ background: rgba(0, 0, 0, 0.62);
108574
+ }
108575
+
108576
+ .image-modal-content {
108577
+ position: relative;
108578
+ max-width: min(92vw, 1100px);
108579
+ max-height: min(88vh, 900px);
108580
+ display: flex;
108581
+ align-items: center;
108582
+ justify-content: center;
108583
+ }
108584
+
108585
+ .image-modal-content img {
108586
+ display: block;
108587
+ max-width: 100%;
108588
+ max-height: min(88vh, 900px);
108589
+ object-fit: contain;
108590
+ border-radius: 6px;
108591
+ background: #111111;
108592
+ }
108593
+
108594
+ .image-modal-close {
108595
+ appearance: none;
108596
+ position: absolute;
108597
+ top: -10px;
108598
+ right: -10px;
108599
+ width: 28px;
108600
+ height: 28px;
108601
+ border: 1px solid rgba(255, 255, 255, 0.55);
108602
+ border-radius: 50%;
108603
+ background: rgba(0, 0, 0, 0.74);
108604
+ color: #ffffff;
108605
+ display: inline-flex;
108606
+ align-items: center;
108607
+ justify-content: center;
108608
+ cursor: pointer;
108609
+ }
108610
+
107589
108611
  .message-input::placeholder {
107590
108612
  color: var(--dominds-muted, #666666);
107591
108613
  }
@@ -107681,6 +108703,8 @@ _DomindsQ4HInput.SEND_ON_ENTER_STORAGE_KEY = "dominds-send-on-enter";
107681
108703
  _DomindsQ4HInput.INPUT_HISTORY_STORAGE_KEY = "dominds-user-input-history-v1";
107682
108704
  _DomindsQ4HInput.INPUT_HISTORY_MAX = 100;
107683
108705
  _DomindsQ4HInput.MANUAL_HEIGHT_STORAGE_KEY = "dominds-q4h-input-height-px-v1";
108706
+ _DomindsQ4HInput.IMAGE_ATTACHMENT_MAX_COUNT = 10;
108707
+ _DomindsQ4HInput.IMAGE_ATTACHMENT_MAX_BYTES = 10 * 1024 * 1024;
107684
108708
  let DomindsQ4HInput = _DomindsQ4HInput;
107685
108709
  if (!customElements.get("dominds-q4h-input")) {
107686
108710
  customElements.define("dominds-q4h-input", DomindsQ4HInput);
@@ -110844,9 +111868,10 @@ const _DoneDialogList = class _DoneDialogList extends HTMLElement {
110844
111868
  if (patch.subdialogCount !== void 0 && targetSelf === rootId) {
110845
111869
  const countEl = entry.el.querySelector(".dialog-count");
110846
111870
  if (countEl instanceof HTMLElement) {
110847
- countEl.textContent = String(
110848
- typeof next2.subdialogCount === "number" ? next2.subdialogCount : 0
110849
- );
111871
+ if (typeof next2.subdialogCount !== "number" || !Number.isInteger(next2.subdialogCount) || next2.subdialogCount < 0) {
111872
+ throw new Error(`Root dialog ${rootId} received invalid backend subdialogCount`);
111873
+ }
111874
+ countEl.textContent = String(next2.subdialogCount);
110850
111875
  }
110851
111876
  }
110852
111877
  return true;
@@ -110980,6 +112005,14 @@ const _DoneDialogList = class _DoneDialogList extends HTMLElement {
110980
112005
  }
110981
112006
  return max2;
110982
112007
  }
112008
+ getRootSubdialogCount(rootGroup) {
112009
+ if (!rootGroup.root) return rootGroup.subdialogs.length;
112010
+ const backendCount = rootGroup.root.subdialogCount;
112011
+ if (typeof backendCount !== "number" || !Number.isInteger(backendCount) || backendCount < 0) {
112012
+ throw new Error(`Root dialog ${rootGroup.rootId} is missing backend subdialogCount`);
112013
+ }
112014
+ return backendCount;
112015
+ }
110983
112016
  render() {
110984
112017
  if (!this.shadowRoot) return;
110985
112018
  const style2 = this.getStyles();
@@ -111219,7 +112252,7 @@ const _DoneDialogList = class _DoneDialogList extends HTMLElement {
111219
112252
  const rootRowHtml = rootGroup.root ? this.renderRootRow(
111220
112253
  rootGroup.root,
111221
112254
  this.renderToggleIcon(rootCollapsed),
111222
- rootGroup.subdialogs.length
112255
+ this.getRootSubdialogCount(rootGroup)
111223
112256
  ) : this.renderMissingRootRow(rootGroup, rootCollapsed);
111224
112257
  const existingRootRow = rootNode.querySelector(
111225
112258
  ":scope > .dialog-item.root-dialog"
@@ -112444,9 +113477,10 @@ const _RunningDialogList = class _RunningDialogList extends HTMLElement {
112444
113477
  if (patch.subdialogCount !== void 0 && targetSelf === rootId) {
112445
113478
  const countEl = entry.el.querySelector(".dialog-count");
112446
113479
  if (countEl instanceof HTMLElement) {
112447
- countEl.textContent = String(
112448
- typeof next2.subdialogCount === "number" ? next2.subdialogCount : 0
112449
- );
113480
+ if (typeof next2.subdialogCount !== "number" || !Number.isInteger(next2.subdialogCount) || next2.subdialogCount < 0) {
113481
+ throw new Error(`Root dialog ${rootId} received invalid backend subdialogCount`);
113482
+ }
113483
+ countEl.textContent = String(next2.subdialogCount);
112450
113484
  }
112451
113485
  }
112452
113486
  return true;
@@ -112675,6 +113709,14 @@ const _RunningDialogList = class _RunningDialogList extends HTMLElement {
112675
113709
  }
112676
113710
  return max2;
112677
113711
  }
113712
+ getRootSubdialogCount(rootGroup) {
113713
+ if (!rootGroup.root) return rootGroup.subdialogs.length;
113714
+ const backendCount = rootGroup.root.subdialogCount;
113715
+ if (typeof backendCount !== "number" || !Number.isInteger(backendCount) || backendCount < 0) {
113716
+ throw new Error(`Root dialog ${rootGroup.rootId} is missing backend subdialogCount`);
113717
+ }
113718
+ return backendCount;
113719
+ }
112678
113720
  render() {
112679
113721
  if (!this.shadowRoot) return;
112680
113722
  const style2 = this.getStyles();
@@ -112914,7 +113956,7 @@ const _RunningDialogList = class _RunningDialogList extends HTMLElement {
112914
113956
  const rootRowHtml = rootGroup.root ? this.renderRootRow(
112915
113957
  rootGroup.root,
112916
113958
  this.renderToggleIcon(rootCollapsed),
112917
- rootGroup.subdialogs.length
113959
+ this.getRootSubdialogCount(rootGroup)
112918
113960
  ) : this.renderMissingRootRow(rootGroup, rootCollapsed);
112919
113961
  const existingRootRow = rootNode.querySelector(
112920
113962
  ":scope > .dialog-item.root-dialog"
@@ -114002,6 +115044,8 @@ const _DomindsApp = class _DomindsApp extends HTMLElement {
114002
115044
  this.wsManager = getWebSocketManager();
114003
115045
  this.apiClient = getApiClient();
114004
115046
  this.connectionState = this.wsManager.getConnectionState();
115047
+ this.wsConnectionOutageEligibleForHistory = this.connectionState.status === "connected";
115048
+ this.wsConnectionErrorHistoryRecorded = false;
114005
115049
  this.authState = { kind: "uninitialized" };
114006
115050
  this.urlAuthPresent = false;
114007
115051
  this.rootDialogsByStatus = {
@@ -116096,6 +117140,11 @@ ${currentVersion}`;
116096
117140
  `CRITICAL: dialog-list subdialog node returned root dialog for rootId=${rootId} selfId=${selfId}`
116097
117141
  );
116098
117142
  }
117143
+ if (!Number.isInteger(node2.rootSubdialogCount) || node2.rootSubdialogCount < 0) {
117144
+ throw new Error(
117145
+ `CRITICAL: dialog-list subdialog node returned invalid rootSubdialogCount=${String(node2.rootSubdialogCount)} rootId=${rootId} selfId=${selfId}`
117146
+ );
117147
+ }
116099
117148
  if (node2.status !== status) {
116100
117149
  throw new Error(
116101
117150
  `CRITICAL: dialog-list subdialog node status mismatch. expected=${status} actual=${node2.status} rootId=${rootId} selfId=${selfId}`
@@ -116131,9 +117180,18 @@ ${currentVersion}`;
116131
117180
  if (rootDialog) {
116132
117181
  const nodeUpdatedAtMs = timeExports.parseUnifiedTimestampMs(node2.lastModified);
116133
117182
  const rootUpdatedAtMs = timeExports.parseUnifiedTimestampMs(rootDialog.lastModified);
116134
- const nextSubdialogCount = Math.max(rootDialog.subdialogCount ?? 0, existing.length + 1);
117183
+ const visibleCountFloor = existing.length + 1;
117184
+ if (node2.rootSubdialogCount < visibleCountFloor) {
117185
+ throw new Error(
117186
+ `CRITICAL: dialog-list subdialog node rootSubdialogCount under visible count. rootId=${rootId} selfId=${selfId} backend=${node2.rootSubdialogCount} visible=${visibleCountFloor}`
117187
+ );
117188
+ }
117189
+ const nextSubdialogCount = node2.rootSubdialogCount;
117190
+ if (typeof rootDialog.subdialogCount !== "number" || !Number.isInteger(rootDialog.subdialogCount) || rootDialog.subdialogCount < 0) {
117191
+ throw new Error(`Root dialog ${rootId} has invalid backend subdialogCount`);
117192
+ }
116135
117193
  const nextLastModified = nodeUpdatedAtMs !== null && (rootUpdatedAtMs === null || nodeUpdatedAtMs > rootUpdatedAtMs) ? node2.lastModified : rootDialog.lastModified;
116136
- if (nextSubdialogCount !== (rootDialog.subdialogCount ?? 0) || nextLastModified !== rootDialog.lastModified) {
117194
+ if (nextSubdialogCount !== rootDialog.subdialogCount || nextLastModified !== rootDialog.lastModified) {
116137
117195
  this.upsertRootDialogSnapshot({
116138
117196
  ...rootDialog,
116139
117197
  subdialogCount: nextSubdialogCount,
@@ -121650,6 +122708,11 @@ ${content}`;
121650
122708
  if (!Array.isArray(h2.subdialogs)) {
121651
122709
  throw new Error(`Hierarchy response for ${rootId} has invalid subdialogs payload`);
121652
122710
  }
122711
+ if (!Number.isInteger(h2.root.subdialogCount) || h2.root.subdialogCount < 0) {
122712
+ throw new Error(
122713
+ `Hierarchy response for ${rootId} has invalid root subdialogCount=${String(h2.root.subdialogCount)}`
122714
+ );
122715
+ }
121653
122716
  const cachedRootDisplayState = this.dialogDisplayStatesByKey.get(
121654
122717
  this.dialogKey(rootId, rootId)
121655
122718
  );
@@ -121708,6 +122771,11 @@ ${content}`;
121708
122771
  rootId,
121709
122772
  newSubdialogs
121710
122773
  );
122774
+ if (h2.root.subdialogCount < mergedSubdialogs.length) {
122775
+ throw new Error(
122776
+ `Hierarchy response for ${rootId} has root subdialogCount below loaded subdialog count. backend=${h2.root.subdialogCount} loaded=${mergedSubdialogs.length}`
122777
+ );
122778
+ }
121711
122779
  const nextRoot = {
121712
122780
  rootId,
121713
122781
  agentId: h2.root.agentId,
@@ -121718,7 +122786,7 @@ ${content}`;
121718
122786
  lastModified: h2.root.lastModified,
121719
122787
  displayState: rootDisplayState ?? rootEntry?.displayState,
121720
122788
  waitingForFreshBootsReasoning: h2.root.waitingForFreshBootsReasoning === true,
121721
- subdialogCount: typeof rootEntry?.subdialogCount === "number" ? Math.max(rootEntry.subdialogCount, mergedSubdialogs.length) : mergedSubdialogs.length
122789
+ subdialogCount: h2.root.subdialogCount
121722
122790
  };
121723
122791
  this.upsertRootDialogSnapshot(nextRoot);
121724
122792
  this.setVisibleSubdialogsForRoot(rootId, mergedSubdialogs);
@@ -122674,11 +123742,15 @@ ${content}`;
122674
123742
  async ensureSubdialogsLoaded(rootId) {
122675
123743
  if (!rootId) return false;
122676
123744
  const rootDialog = this.getRootDialog(rootId);
122677
- const expectedCount = typeof rootDialog?.subdialogCount === "number" ? rootDialog.subdialogCount : 0;
123745
+ if (!rootDialog) return false;
123746
+ if (typeof rootDialog.subdialogCount !== "number" || !Number.isInteger(rootDialog.subdialogCount) || rootDialog.subdialogCount < 0) {
123747
+ throw new Error(`Root dialog ${rootId} has invalid backend subdialogCount`);
123748
+ }
123749
+ const expectedCount = rootDialog.subdialogCount;
122678
123750
  if (expectedCount === 0) return true;
122679
123751
  const alreadyLoaded = this.getVisibleSubdialogsForRoot(rootId).length > 0;
122680
123752
  if (alreadyLoaded) return true;
122681
- const status = this.toPersistableStatus(rootDialog?.status);
123753
+ const status = this.toPersistableStatus(rootDialog.status);
122682
123754
  if (status === null) return false;
122683
123755
  await this.loadRootHierarchyForKnownStatus(rootId, status);
122684
123756
  return this.getVisibleSubdialogsForRoot(rootId).length > 0;
@@ -122688,6 +123760,8 @@ ${content}`;
122688
123760
  this.connectionState = state2;
122689
123761
  this.updateConnectionStatus();
122690
123762
  if (state2.status === "connected") {
123763
+ this.wsConnectionOutageEligibleForHistory = false;
123764
+ this.wsConnectionErrorHistoryRecorded = false;
122691
123765
  this.wsManager.setUiLanguage(this.uiLanguage);
122692
123766
  this.wsManager.sendRaw({
122693
123767
  type: "get_q4h_state"
@@ -122695,12 +123769,25 @@ ${content}`;
122695
123769
  if (previousStatus !== "connected") {
122696
123770
  this.restoreCurrentDialogAfterReconnectInBackground();
122697
123771
  }
122698
- } else if (state2.status === "error") {
123772
+ } else {
123773
+ if (previousStatus === "connected") {
123774
+ this.wsConnectionOutageEligibleForHistory = true;
123775
+ this.wsConnectionErrorHistoryRecorded = false;
123776
+ }
123777
+ if (state2.status !== "error") {
123778
+ return;
123779
+ }
122699
123780
  if (state2.error === "Unauthorized") {
122700
123781
  this.onAuthRejected("ws");
122701
123782
  return;
122702
123783
  }
122703
- this.showError(state2.error || "Connection error");
123784
+ const persistHistory = this.wsConnectionOutageEligibleForHistory && !this.wsConnectionErrorHistoryRecorded;
123785
+ if (persistHistory) {
123786
+ this.wsConnectionErrorHistoryRecorded = true;
123787
+ }
123788
+ this.showError(state2.error || "Connection error", "error", {
123789
+ history: persistHistory ? "persist" : "skip"
123790
+ });
122704
123791
  }
122705
123792
  }
122706
123793
  async reopenCurrentDialogAfterReconnect() {
@@ -122763,6 +123850,8 @@ ${content}`;
122763
123850
  statusEl.setAttribute("status", this.connectionState.status);
122764
123851
  if (this.connectionState.error) {
122765
123852
  statusEl.setAttribute("error", this.connectionState.error);
123853
+ } else {
123854
+ statusEl.removeAttribute("error");
122766
123855
  }
122767
123856
  }
122768
123857
  }
@@ -122774,9 +123863,9 @@ ${content}`;
122774
123863
  this.showWarning("No team members component available");
122775
123864
  }
122776
123865
  }
122777
- showError(message, type2 = "error") {
123866
+ showError(message, type2 = "error", options) {
122778
123867
  console.error(`[${type2.toUpperCase()}] ${message}`);
122779
- this.showToast(message, type2);
123868
+ this.showToast(message, type2, options);
122780
123869
  }
122781
123870
  showSuccess(message) {
122782
123871
  this.showToast(message, "info", { history: "skip" });
@@ -122838,10 +123927,10 @@ ${content}`;
122838
123927
  if (typeof item !== "object" || item === null) continue;
122839
123928
  const rec = item;
122840
123929
  const id28 = typeof rec["id"] === "string" ? rec["id"] : "";
122841
- const timestamp2 = typeof rec["timestamp"] === "string" ? rec["timestamp"] : "";
123930
+ const timestamp2 = typeof rec["timestamp"] === "string" ? rec["timestamp"].trim() : "";
122842
123931
  const kind = rec["kind"];
122843
123932
  const message = typeof rec["message"] === "string" ? rec["message"] : "";
122844
- if (!id28 || !timestamp2 || !message) continue;
123933
+ if (!id28 || !_DomindsApp.UNIFIED_TIMESTAMP_PATTERN.test(timestamp2) || !message) continue;
122845
123934
  if (kind !== "error" && kind !== "warning" && kind !== "info") continue;
122846
123935
  next2.push({ id: id28, timestamp: timestamp2, kind, message });
122847
123936
  }
@@ -122865,7 +123954,7 @@ ${content}`;
122865
123954
  if (trimmed === "") return;
122866
123955
  const next2 = {
122867
123956
  id: id28,
122868
- timestamp: now2.toISOString(),
123957
+ timestamp: timeExports.formatUnifiedTimestamp(now2),
122869
123958
  kind: entry.kind,
122870
123959
  message: trimmed
122871
123960
  };
@@ -123762,23 +124851,38 @@ ${content}`;
123762
124851
  `CRITICAL: subdialog_created event for unknown rootId=${node2.rootId} selfId=${node2.selfId}`
123763
124852
  );
123764
124853
  }
123765
- const prevCount = typeof rootDialog.subdialogCount === "number" ? rootDialog.subdialogCount : 0;
123766
- const visibleCountFloor = hadLoadedSubdialogs || rootExpandedInDom ? this.getVisibleSubdialogsForRoot(node2.rootId).length + 1 : 1;
123767
- const nextCount = Math.max(prevCount + 1, visibleCountFloor, 1);
124854
+ if (!Number.isInteger(subdialogEvent.rootSubdialogCount) || subdialogEvent.rootSubdialogCount < 0) {
124855
+ throw new Error(
124856
+ `CRITICAL: subdialog_created event returned invalid rootSubdialogCount=${String(subdialogEvent.rootSubdialogCount)} rootId=${node2.rootId} selfId=${node2.selfId}`
124857
+ );
124858
+ }
124859
+ const existingSubdialogs = this.getVisibleSubdialogsForRoot(node2.rootId);
124860
+ const alreadyVisible = existingSubdialogs.some(
124861
+ (subdialog) => subdialog.selfId === incomingSubdialog.selfId
124862
+ );
124863
+ const visibleCountFloor = hadLoadedSubdialogs || rootExpandedInDom ? existingSubdialogs.length + (alreadyVisible ? 0 : 1) : 1;
124864
+ if (subdialogEvent.rootSubdialogCount < visibleCountFloor) {
124865
+ throw new Error(
124866
+ `CRITICAL: subdialog_created event rootSubdialogCount under visible count. rootId=${node2.rootId} selfId=${node2.selfId} backend=${subdialogEvent.rootSubdialogCount} visible=${visibleCountFloor}`
124867
+ );
124868
+ }
124869
+ const nextCount = subdialogEvent.rootSubdialogCount;
123768
124870
  this.upsertRootDialogSnapshot({
123769
124871
  ...rootDialog,
123770
124872
  subdialogCount: nextCount,
123771
124873
  lastModified: node2.lastModified || rootDialog.lastModified
123772
124874
  });
123773
124875
  if (hadLoadedSubdialogs || rootExpandedInDom) {
123774
- const existing = this.getVisibleSubdialogsForRoot(node2.rootId);
123775
- const idx = existing.findIndex((d2) => d2.selfId === incomingSubdialog.selfId);
124876
+ const idx = existingSubdialogs.findIndex((d2) => d2.selfId === incomingSubdialog.selfId);
123776
124877
  if (idx >= 0) {
123777
- const updated = [...existing];
124878
+ const updated = [...existingSubdialogs];
123778
124879
  updated[idx] = incomingSubdialog;
123779
124880
  this.setVisibleSubdialogsForRoot(node2.rootId, updated);
123780
124881
  } else {
123781
- this.setVisibleSubdialogsForRoot(node2.rootId, [...existing, incomingSubdialog]);
124882
+ this.setVisibleSubdialogsForRoot(node2.rootId, [
124883
+ ...existingSubdialogs,
124884
+ incomingSubdialog
124885
+ ]);
123782
124886
  }
123783
124887
  }
123784
124888
  if (hadLoadedSubdialogs || rootExpandedInDom || node2.status !== "running") {
@@ -124314,8 +125418,8 @@ ${content}`;
124314
125418
  stepParent: widgetContent,
124315
125419
  label: getProgressiveExpandLabel(this.uiLanguage),
124316
125420
  // Reminder bodies can become long after first paint when a nested code block is expanded.
124317
- // Track only target self-growth until the first outer overflow appears; never track widget
124318
- // parent resize for this.
125421
+ // Track only target self-growth while the expand footer is hidden; never track widget parent
125422
+ // resize for this.
124319
125423
  observeTargetUntilOverflow: true
124320
125424
  });
124321
125425
  this.reminderProgressiveExpandCleanupByKey.set(key, cleanup);
@@ -124696,8 +125800,9 @@ ${content}`;
124696
125800
  // Resize handle removed: input is resized via a dedicated handle inside `dominds-q4h-input`.
124697
125801
  };
124698
125802
  _DomindsApp.DEFAULT_BROWSER_TITLE = "Dominds - DevOps Mindsets";
124699
- _DomindsApp.TOAST_HISTORY_STORAGE_KEY = "dominds-toast-history-v1";
125803
+ _DomindsApp.TOAST_HISTORY_STORAGE_KEY = "dominds-toast-history-v2";
124700
125804
  _DomindsApp.TOAST_HISTORY_MAX = 200;
125805
+ _DomindsApp.UNIFIED_TIMESTAMP_PATTERN = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/;
124701
125806
  _DomindsApp.SIDEBAR_WIDTH_STORAGE_KEY = "dominds-sidebar-width-px-v1";
124702
125807
  _DomindsApp.BOTTOM_PANEL_HEIGHT_STORAGE_KEY = "dominds-bottom-panel-height-px-v2";
124703
125808
  _DomindsApp.REMINDERS_WIDGET_SIZE_STORAGE_KEY = "dominds-reminders-widget-size-v1";
@@ -124715,6 +125820,7 @@ const _DomindsConnectionStatus = class _DomindsConnectionStatus extends HTMLElem
124715
125820
  this.mountedAtMs = 0;
124716
125821
  this.firstConnStateEventSeen = false;
124717
125822
  this.initialStatusRefreshTimer = null;
125823
+ this.connStateCancel = null;
124718
125824
  this.attachShadow({ mode: "open" });
124719
125825
  }
124720
125826
  connectedCallback() {
@@ -124726,15 +125832,20 @@ const _DomindsConnectionStatus = class _DomindsConnectionStatus extends HTMLElem
124726
125832
  const parsed = languageExports.normalizeLanguageCode(raw);
124727
125833
  this.uiLanguage = parsed ?? "en";
124728
125834
  const initial = this.wsManager.getConnectionState();
124729
- if (!this.hasAttribute("status")) {
124730
- this.setAttribute("status", initial.status);
124731
- }
124732
- if (initial.error && !this.hasAttribute("error")) {
125835
+ this.setAttribute("status", initial.status);
125836
+ if (initial.error) {
124733
125837
  this.setAttribute("error", initial.error);
125838
+ } else if (!initial.error && this.hasAttribute("error")) {
125839
+ this.removeAttribute("error");
124734
125840
  }
124735
125841
  this.updateDisplay();
124736
125842
  this.scheduleInitialStatusRefresh();
125843
+ if (this.connStateCancel) {
125844
+ this.connStateCancel();
125845
+ this.connStateCancel = null;
125846
+ }
124737
125847
  const sub2 = this.wsManager.subscribeToConnectionState();
125848
+ this.connStateCancel = sub2.cancel;
124738
125849
  (async () => {
124739
125850
  for await (const state2 of sub2.stream()) {
124740
125851
  this.firstConnStateEventSeen = true;
@@ -124749,6 +125860,10 @@ const _DomindsConnectionStatus = class _DomindsConnectionStatus extends HTMLElem
124749
125860
  clearTimeout(this.initialStatusRefreshTimer);
124750
125861
  this.initialStatusRefreshTimer = null;
124751
125862
  }
125863
+ if (this.connStateCancel) {
125864
+ this.connStateCancel();
125865
+ this.connStateCancel = null;
125866
+ }
124752
125867
  }
124753
125868
  static get observedAttributes() {
124754
125869
  return ["status", "error", "ui-language"];
@@ -126673,4 +127788,4 @@ export {
126673
127788
  clear$2 as y,
126674
127789
  defaultConfig2 as z
126675
127790
  };
126676
- //# sourceMappingURL=index-DAShQcjb.js.map
127791
+ //# sourceMappingURL=index-DLajsIDJ.js.map