@mistriwork/mistri 1.0.0-rc.12 → 1.0.0-rc.13

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 (221) hide show
  1. package/README.md +4 -3
  2. package/dist/client/assets/LayoutBuilder-MPzkVU2e.js.map +1 -1
  3. package/dist/client/assets/index-D2dHI6hR.js.map +1 -1
  4. package/dist/client/assets/shell-TreN_uLs.js.map +1 -1
  5. package/dist/docs/access-model.md +1 -1
  6. package/dist/docs/build-and-deploy.md +0 -1
  7. package/dist/docs/cli.md +1 -1
  8. package/dist/docs/glossary.md +3 -3
  9. package/dist/docs/query.md +9 -21
  10. package/dist/docs/status.md +3 -3
  11. package/dist/embed/react/chunks/LayoutBuilder-Cbxa_wve.js.map +1 -1
  12. package/dist/embed/react/chunks/app-0UZ1Re1k.js.map +1 -1
  13. package/dist/embed/react/chunks/page-Bx4o1kpQ.js.map +1 -1
  14. package/dist/embed/react/chunks/palette-Bb7Lf6eo.js.map +1 -1
  15. package/dist/embed/react/chunks/shell-DZRACiB9.js.map +1 -1
  16. package/dist/embed/react/chunks/write-BQO4CFc9.js.map +1 -1
  17. package/dist/embed/react/index.js +1 -1
  18. package/dist/server/build/dockerfile.js +1 -1
  19. package/dist/server/cli/usage.js +2 -2
  20. package/dist/ui/index.js +2 -2
  21. package/dist/ui/page.js +2 -2
  22. package/dist/ui/{shared-N4Ej8yRD.js → shared-1PD7TOTJ.js} +5 -5
  23. package/dist/ui/{shared-N4Ej8yRD.js.map → shared-1PD7TOTJ.js.map} +1 -1
  24. package/dist/ui/{shared-D5m86-4o.js → shared-1gMnOu9J.js} +6 -6
  25. package/dist/ui/{shared-D5m86-4o.js.map → shared-1gMnOu9J.js.map} +1 -1
  26. package/dist/ui/{shared-Ctaj8mR2.js → shared-5RQMi4BR.js} +3 -3
  27. package/dist/ui/{shared-Ctaj8mR2.js.map → shared-5RQMi4BR.js.map} +1 -1
  28. package/dist/ui/{shared-DpLeIATZ.js → shared-B-BUF9fx.js} +2 -2
  29. package/dist/ui/{shared-DpLeIATZ.js.map → shared-B-BUF9fx.js.map} +1 -1
  30. package/dist/ui/{shared-DWYnjItP.js → shared-B-MhiPIN.js} +9 -9
  31. package/dist/ui/{shared-DWYnjItP.js.map → shared-B-MhiPIN.js.map} +1 -1
  32. package/dist/ui/{shared-0fNuhSbG.js → shared-B07qIMlE.js} +5 -5
  33. package/dist/ui/{shared-0fNuhSbG.js.map → shared-B07qIMlE.js.map} +1 -1
  34. package/dist/ui/{shared-lYtMadRU.js → shared-B1SAS_J-.js} +3 -3
  35. package/dist/ui/{shared-lYtMadRU.js.map → shared-B1SAS_J-.js.map} +1 -1
  36. package/dist/ui/{shared-CpI0Y8M5.js → shared-B4jgU8h9.js} +6 -6
  37. package/dist/ui/{shared-CpI0Y8M5.js.map → shared-B4jgU8h9.js.map} +1 -1
  38. package/dist/ui/{shared-Cxu1c35l.js → shared-B5aBCUi7.js} +30 -30
  39. package/dist/ui/{shared-Cxu1c35l.js.map → shared-B5aBCUi7.js.map} +1 -1
  40. package/dist/ui/{shared-CAe-US1q.js → shared-B9H7_Pji.js} +5 -5
  41. package/dist/ui/{shared-CAe-US1q.js.map → shared-B9H7_Pji.js.map} +1 -1
  42. package/dist/ui/{shared-Q2bgBaYo.js → shared-BAXr20S-.js} +4 -4
  43. package/dist/ui/{shared-Q2bgBaYo.js.map → shared-BAXr20S-.js.map} +1 -1
  44. package/dist/ui/{shared-CyEefFFb.js → shared-BDDUzH-f.js} +19 -19
  45. package/dist/ui/{shared-CyEefFFb.js.map → shared-BDDUzH-f.js.map} +1 -1
  46. package/dist/ui/{shared-BdhPI6dq.js → shared-BGmkeDeW.js} +3 -3
  47. package/dist/ui/{shared-BdhPI6dq.js.map → shared-BGmkeDeW.js.map} +1 -1
  48. package/dist/ui/{shared-DONIpq2q.js → shared-BHCQ60yN.js} +2 -2
  49. package/dist/ui/{shared-DONIpq2q.js.map → shared-BHCQ60yN.js.map} +1 -1
  50. package/dist/ui/{shared-CNmaAv64.js → shared-BHsjawAG.js} +8 -8
  51. package/dist/ui/{shared-CNmaAv64.js.map → shared-BHsjawAG.js.map} +1 -1
  52. package/dist/ui/{shared-DgjU9kOy.js → shared-BIQuK_nq.js} +4 -4
  53. package/dist/ui/{shared-DgjU9kOy.js.map → shared-BIQuK_nq.js.map} +1 -1
  54. package/dist/ui/{shared-icSQAj21.js → shared-BOe4W2FI.js} +3 -3
  55. package/dist/ui/{shared-icSQAj21.js.map → shared-BOe4W2FI.js.map} +1 -1
  56. package/dist/ui/{shared-BlxoOJSk.js → shared-BPpC08ip.js} +3 -3
  57. package/dist/ui/{shared-BlxoOJSk.js.map → shared-BPpC08ip.js.map} +1 -1
  58. package/dist/ui/{shared-BtiFL37J.js → shared-BdA3LPCB.js} +2 -2
  59. package/dist/ui/{shared-BtiFL37J.js.map → shared-BdA3LPCB.js.map} +1 -1
  60. package/dist/ui/{shared-CvR94vn4.js → shared-Be3nbWsd.js} +11 -11
  61. package/dist/ui/{shared-CvR94vn4.js.map → shared-Be3nbWsd.js.map} +1 -1
  62. package/dist/ui/{shared-Bl_nF_IH.js → shared-Bf30ZLoS.js} +8 -4
  63. package/dist/ui/shared-Bf30ZLoS.js.map +1 -0
  64. package/dist/ui/{shared-DijrJ_V-.js → shared-BguP_BaR.js} +7 -7
  65. package/dist/ui/{shared-DijrJ_V-.js.map → shared-BguP_BaR.js.map} +1 -1
  66. package/dist/ui/{shared-DPAVoWY0.js → shared-BoLbc2WD.js} +17 -2
  67. package/dist/ui/{shared-DPAVoWY0.js.map → shared-BoLbc2WD.js.map} +1 -1
  68. package/dist/ui/{shared-BkdBTYwx.js → shared-BttyOW4W.js} +3 -3
  69. package/dist/ui/{shared-BkdBTYwx.js.map → shared-BttyOW4W.js.map} +1 -1
  70. package/dist/ui/{shared-CQWLz8uT.js → shared-BumxsBlA.js} +10 -10
  71. package/dist/ui/{shared-CQWLz8uT.js.map → shared-BumxsBlA.js.map} +1 -1
  72. package/dist/ui/{shared-Dzu7tFiC.js → shared-Bw73ktBk.js} +3 -3
  73. package/dist/ui/{shared-Dzu7tFiC.js.map → shared-Bw73ktBk.js.map} +1 -1
  74. package/dist/ui/{shared-BhAYErSx.js → shared-C1B0GH0e.js} +4 -4
  75. package/dist/ui/{shared-BhAYErSx.js.map → shared-C1B0GH0e.js.map} +1 -1
  76. package/dist/ui/{shared-BQJQcGgj.js → shared-C2FsyYr7.js} +4 -4
  77. package/dist/ui/{shared-BQJQcGgj.js.map → shared-C2FsyYr7.js.map} +1 -1
  78. package/dist/ui/{shared-B9lw2Ryh.js → shared-C2RU1qjv.js} +4 -4
  79. package/dist/ui/{shared-B9lw2Ryh.js.map → shared-C2RU1qjv.js.map} +1 -1
  80. package/dist/ui/{shared-DQYNI9wO.js → shared-C42f07hJ.js} +5 -5
  81. package/dist/ui/{shared-DQYNI9wO.js.map → shared-C42f07hJ.js.map} +1 -1
  82. package/dist/ui/{shared-CqCZ8wMY.js → shared-C4LkPCU4.js} +3 -3
  83. package/dist/ui/{shared-CqCZ8wMY.js.map → shared-C4LkPCU4.js.map} +1 -1
  84. package/dist/ui/{shared-BhtpgOpa.js → shared-C4wSfz6k.js} +9 -9
  85. package/dist/ui/{shared-BhtpgOpa.js.map → shared-C4wSfz6k.js.map} +1 -1
  86. package/dist/ui/{shared-BHc2Izkj.js → shared-C9DZtSFH.js} +2 -2
  87. package/dist/ui/{shared-BHc2Izkj.js.map → shared-C9DZtSFH.js.map} +1 -1
  88. package/dist/ui/{shared-DW1YuiNS.js → shared-CA52ClGo.js} +2 -2
  89. package/dist/ui/{shared-DW1YuiNS.js.map → shared-CA52ClGo.js.map} +1 -1
  90. package/dist/ui/{shared-BbSbilkh.js → shared-CBciTwm6.js} +9 -9
  91. package/dist/ui/{shared-BbSbilkh.js.map → shared-CBciTwm6.js.map} +1 -1
  92. package/dist/ui/{shared-C-J32eBn.js → shared-CL3RLKDA.js} +16 -16
  93. package/dist/ui/{shared-C-J32eBn.js.map → shared-CL3RLKDA.js.map} +1 -1
  94. package/dist/ui/{shared-Ck8S4OxW.js → shared-CLq3-_hW.js} +3 -3
  95. package/dist/ui/{shared-Ck8S4OxW.js.map → shared-CLq3-_hW.js.map} +1 -1
  96. package/dist/ui/{shared-Q5WefT7G.js → shared-CMjK-Ucd.js} +3 -3
  97. package/dist/ui/{shared-Q5WefT7G.js.map → shared-CMjK-Ucd.js.map} +1 -1
  98. package/dist/ui/{shared-D3MAuEA3.js → shared-CPjpSFGh.js} +2 -2
  99. package/dist/ui/{shared-D3MAuEA3.js.map → shared-CPjpSFGh.js.map} +1 -1
  100. package/dist/ui/{shared-VshXGwXP.js → shared-CSPhENq3.js} +2 -2
  101. package/dist/ui/{shared-VshXGwXP.js.map → shared-CSPhENq3.js.map} +1 -1
  102. package/dist/ui/{shared-DJrJaE73.js → shared-CZJE4Bmp.js} +3 -3
  103. package/dist/ui/{shared-DJrJaE73.js.map → shared-CZJE4Bmp.js.map} +1 -1
  104. package/dist/ui/{shared-D7ONOwI7.js → shared-C_BhUL2I.js} +7 -7
  105. package/dist/ui/{shared-D7ONOwI7.js.map → shared-C_BhUL2I.js.map} +1 -1
  106. package/dist/ui/{shared-j-2peBIB.js → shared-CbeujwdU.js} +4 -4
  107. package/dist/ui/{shared-j-2peBIB.js.map → shared-CbeujwdU.js.map} +1 -1
  108. package/dist/ui/{shared-D5GrOEa2.js → shared-Cbf-o4Dt.js} +4 -4
  109. package/dist/ui/{shared-D5GrOEa2.js.map → shared-Cbf-o4Dt.js.map} +1 -1
  110. package/dist/ui/{shared-HwiPIajr.js → shared-CdNmeNHh.js} +3 -3
  111. package/dist/ui/{shared-HwiPIajr.js.map → shared-CdNmeNHh.js.map} +1 -1
  112. package/dist/ui/{shared-ZCFt-CPb.js → shared-CdQOMD8J.js} +3 -3
  113. package/dist/ui/{shared-ZCFt-CPb.js.map → shared-CdQOMD8J.js.map} +1 -1
  114. package/dist/ui/{shared-ClhXSGGK.js → shared-CdiPYlTh.js} +2 -2
  115. package/dist/ui/{shared-ClhXSGGK.js.map → shared-CdiPYlTh.js.map} +1 -1
  116. package/dist/ui/{shared-DA8_pVRZ.js → shared-CepLAhwm.js} +2 -2
  117. package/dist/ui/{shared-DA8_pVRZ.js.map → shared-CepLAhwm.js.map} +1 -1
  118. package/dist/ui/{shared-BrYKjrnM.js → shared-Ch82h_Fu.js} +6 -6
  119. package/dist/ui/{shared-BrYKjrnM.js.map → shared-Ch82h_Fu.js.map} +1 -1
  120. package/dist/ui/{shared-C4UrE8Fb.js → shared-Chp88all.js} +3 -3
  121. package/dist/ui/{shared-C4UrE8Fb.js.map → shared-Chp88all.js.map} +1 -1
  122. package/dist/ui/{shared-CWa80DTO.js → shared-Ci16s2rN.js} +9 -9
  123. package/dist/ui/{shared-CWa80DTO.js.map → shared-Ci16s2rN.js.map} +1 -1
  124. package/dist/ui/{shared-tksTLD6Q.js → shared-CiqNkoE1.js} +5 -5
  125. package/dist/ui/{shared-tksTLD6Q.js.map → shared-CiqNkoE1.js.map} +1 -1
  126. package/dist/ui/{shared-yt7DjSrq.js → shared-CpMhOq8F.js} +2 -2
  127. package/dist/ui/{shared-yt7DjSrq.js.map → shared-CpMhOq8F.js.map} +1 -1
  128. package/dist/ui/{shared-Dm0z5WUl.js → shared-CrWv5JKH.js} +6 -6
  129. package/dist/ui/{shared-Dm0z5WUl.js.map → shared-CrWv5JKH.js.map} +1 -1
  130. package/dist/ui/{shared-CQL3FGHc.js → shared-Csfi3Pti.js} +2 -2
  131. package/dist/ui/{shared-CQL3FGHc.js.map → shared-Csfi3Pti.js.map} +1 -1
  132. package/dist/ui/{shared-BKNRbm-V.js → shared-CuZt26rm.js} +2 -2
  133. package/dist/ui/{shared-BKNRbm-V.js.map → shared-CuZt26rm.js.map} +1 -1
  134. package/dist/ui/{shared-Guq3upiR.js → shared-Cws_z-TS.js} +2 -2
  135. package/dist/ui/{shared-Guq3upiR.js.map → shared-Cws_z-TS.js.map} +1 -1
  136. package/dist/ui/{shared-Bw_qZeIj.js → shared-D1KWuCg6.js} +2 -2
  137. package/dist/ui/{shared-Bw_qZeIj.js.map → shared-D1KWuCg6.js.map} +1 -1
  138. package/dist/ui/{shared-CuCZKwXW.js → shared-D66ju_Cb.js} +23 -23
  139. package/dist/ui/{shared-CuCZKwXW.js.map → shared-D66ju_Cb.js.map} +1 -1
  140. package/dist/ui/{shared-DYfX7NSM.js → shared-DGaQZXnw.js} +2 -2
  141. package/dist/ui/{shared-DYfX7NSM.js.map → shared-DGaQZXnw.js.map} +1 -1
  142. package/dist/ui/{shared-B3Hp8tOv.js → shared-DHy41sET.js} +6 -6
  143. package/dist/ui/{shared-B3Hp8tOv.js.map → shared-DHy41sET.js.map} +1 -1
  144. package/dist/ui/{shared-CXyd7IKi.js → shared-DKEOMQ6l.js} +2 -2
  145. package/dist/ui/{shared-CXyd7IKi.js.map → shared-DKEOMQ6l.js.map} +1 -1
  146. package/dist/ui/{shared-Ccmc8YO0.js → shared-DSUICuaJ.js} +33 -33
  147. package/dist/ui/{shared-Ccmc8YO0.js.map → shared-DSUICuaJ.js.map} +1 -1
  148. package/dist/ui/{shared-CL2iw_js.js → shared-DUPMRoO0.js} +13 -13
  149. package/dist/ui/{shared-CL2iw_js.js.map → shared-DUPMRoO0.js.map} +1 -1
  150. package/dist/ui/{shared-Dtp4eRul.js → shared-DVfdm6ah.js} +2 -2
  151. package/dist/ui/{shared-Dtp4eRul.js.map → shared-DVfdm6ah.js.map} +1 -1
  152. package/dist/ui/{shared-BJ5Ex32G.js → shared-DXM7d7lJ.js} +3 -3
  153. package/dist/ui/{shared-BJ5Ex32G.js.map → shared-DXM7d7lJ.js.map} +1 -1
  154. package/dist/ui/{shared-BFr6ld0e.js → shared-DXbMlcev.js} +2 -2
  155. package/dist/ui/{shared-BFr6ld0e.js.map → shared-DXbMlcev.js.map} +1 -1
  156. package/dist/ui/{shared-BUp3jv-N.js → shared-D_SkPtJ9.js} +6 -6
  157. package/dist/ui/{shared-BUp3jv-N.js.map → shared-D_SkPtJ9.js.map} +1 -1
  158. package/dist/ui/{shared-CdNomVzH.js → shared-Dd21k2ic.js} +4 -4
  159. package/dist/ui/{shared-CdNomVzH.js.map → shared-Dd21k2ic.js.map} +1 -1
  160. package/dist/ui/{shared-gRMbxmpu.js → shared-Dh0nHtLZ.js} +8 -8
  161. package/dist/ui/{shared-gRMbxmpu.js.map → shared-Dh0nHtLZ.js.map} +1 -1
  162. package/dist/ui/{shared-BKGJgjog.js → shared-DkOdSpSK.js} +3 -3
  163. package/dist/ui/{shared-BKGJgjog.js.map → shared-DkOdSpSK.js.map} +1 -1
  164. package/dist/ui/{shared-BMsh72Uq.js → shared-Dkph5ckT.js} +2 -2
  165. package/dist/ui/{shared-BMsh72Uq.js.map → shared-Dkph5ckT.js.map} +1 -1
  166. package/dist/ui/{shared-Be1HpDOB.js → shared-Dl1_Nx--.js} +3 -3
  167. package/dist/ui/{shared-Be1HpDOB.js.map → shared-Dl1_Nx--.js.map} +1 -1
  168. package/dist/ui/{shared-BQIZWOoJ.js → shared-Dm0IGbAf.js} +2 -2
  169. package/dist/ui/{shared-BQIZWOoJ.js.map → shared-Dm0IGbAf.js.map} +1 -1
  170. package/dist/ui/{shared-DSUtcU5S.js → shared-DnIkTpPr.js} +5 -5
  171. package/dist/ui/{shared-DSUtcU5S.js.map → shared-DnIkTpPr.js.map} +1 -1
  172. package/dist/ui/{shared-DsxGbYlV.js → shared-Docl_0tq.js} +3 -3
  173. package/dist/ui/{shared-DsxGbYlV.js.map → shared-Docl_0tq.js.map} +1 -1
  174. package/dist/ui/{shared-DZskrV26.js → shared-DprrHC72.js} +2 -2
  175. package/dist/ui/{shared-DZskrV26.js.map → shared-DprrHC72.js.map} +1 -1
  176. package/dist/ui/{shared-Bmw43Hwf.js → shared-DyKsJTZs.js} +2 -2
  177. package/dist/ui/{shared-Bmw43Hwf.js.map → shared-DyKsJTZs.js.map} +1 -1
  178. package/dist/ui/{shared-BLG88Pya.js → shared-FO7vfI3F.js} +4 -4
  179. package/dist/ui/{shared-BLG88Pya.js.map → shared-FO7vfI3F.js.map} +1 -1
  180. package/dist/ui/{shared-DLSd80D1.js → shared-HalAVHjv.js} +3 -3
  181. package/dist/ui/{shared-DLSd80D1.js.map → shared-HalAVHjv.js.map} +1 -1
  182. package/dist/ui/{shared-D1mMBLdj.js → shared-JvcI-LWp.js} +15 -15
  183. package/dist/ui/{shared-D1mMBLdj.js.map → shared-JvcI-LWp.js.map} +1 -1
  184. package/dist/ui/{shared-C6Hv_4O0.js → shared-K7Ym27yg.js} +2 -2
  185. package/dist/ui/{shared-C6Hv_4O0.js.map → shared-K7Ym27yg.js.map} +1 -1
  186. package/dist/ui/{shared-B39ln7oi.js → shared-SzlnwfJO.js} +3 -3
  187. package/dist/ui/{shared-B39ln7oi.js.map → shared-SzlnwfJO.js.map} +1 -1
  188. package/dist/ui/{shared-DgPn_Jll.js → shared-TrGbd1FY.js} +3 -3
  189. package/dist/ui/{shared-DgPn_Jll.js.map → shared-TrGbd1FY.js.map} +1 -1
  190. package/dist/ui/{shared-DrFb-XtA.js → shared-WhbuObEW.js} +2 -2
  191. package/dist/ui/{shared-DrFb-XtA.js.map → shared-WhbuObEW.js.map} +1 -1
  192. package/dist/ui/{shared-DiFQljcq.js → shared-XcSKDp6N.js} +11 -11
  193. package/dist/ui/{shared-DiFQljcq.js.map → shared-XcSKDp6N.js.map} +1 -1
  194. package/dist/ui/{shared-CMAg58rY.js → shared-Z4uBJU6I.js} +7 -6
  195. package/dist/ui/shared-Z4uBJU6I.js.map +1 -0
  196. package/dist/ui/{shared-BnUptuUp.js → shared-bAgeiRa5.js} +2 -2
  197. package/dist/ui/{shared-BnUptuUp.js.map → shared-bAgeiRa5.js.map} +1 -1
  198. package/dist/ui/{shared-BxMvSjey.js → shared-cgXG7OgZ.js} +5 -5
  199. package/dist/ui/{shared-BxMvSjey.js.map → shared-cgXG7OgZ.js.map} +1 -1
  200. package/dist/ui/{shared-u4CG2kQJ.js → shared-eZ0SB_zm.js} +2 -2
  201. package/dist/ui/{shared-u4CG2kQJ.js.map → shared-eZ0SB_zm.js.map} +1 -1
  202. package/dist/ui/{shared-L90bWW8e.js → shared-frKFb79C.js} +2 -2
  203. package/dist/ui/{shared-L90bWW8e.js.map → shared-frKFb79C.js.map} +1 -1
  204. package/dist/ui/{shared-Dd34nhkw.js → shared-hAayNSRA.js} +3 -3
  205. package/dist/ui/{shared-Dd34nhkw.js.map → shared-hAayNSRA.js.map} +1 -1
  206. package/dist/ui/{shared-DzC64cpp.js → shared-j_J16p2B.js} +2 -2
  207. package/dist/ui/{shared-DzC64cpp.js.map → shared-j_J16p2B.js.map} +1 -1
  208. package/dist/ui/{shared-DX7HRIV-.js → shared-tqpl5N3g.js} +6 -6
  209. package/dist/ui/{shared-DX7HRIV-.js.map → shared-tqpl5N3g.js.map} +1 -1
  210. package/dist/ui/{shared-BS5dBMpA.js → shared-y-6_ZDts.js} +2 -2
  211. package/dist/ui/{shared-BS5dBMpA.js.map → shared-y-6_ZDts.js.map} +1 -1
  212. package/dist/ui/{shared-Cv5v_MP1.js → shared-zG6e1Rhz.js} +13 -13
  213. package/dist/ui/{shared-Cv5v_MP1.js.map → shared-zG6e1Rhz.js.map} +1 -1
  214. package/dist/ui/testing.js +1 -1
  215. package/package.json +4 -4
  216. package/dist/docs/cli-browser.md +0 -232
  217. package/dist/docs/database-browser.md +0 -115
  218. package/dist/docs/keyboard.md +0 -63
  219. package/dist/docs/mcp.md +0 -86
  220. package/dist/ui/shared-Bl_nF_IH.js.map +0 -1
  221. package/dist/ui/shared-CMAg58rY.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"shared-CyEefFFb.js","names":["say","recordKey","checkedRecordKey","say","_Fragment","names","say","say","_Fragment","_Fragment","checkedRecordKey","CommandForm"],"sources":["../../../kit/src/client/components/recordKeys.ts","../../src/client/components/actionOrder.ts","../../../kit/src/client/copy/record/components/Actions.ts","../../src/client/components/Actions.tsx","../../src/shared/appAssistant.ts","../../src/client/components/assistantRequest.ts","../../src/client/components/assistantStream.ts","../../src/client/copy/shell/components/ConversationList.ts","../../src/client/components/ConversationList.tsx","../../src/client/copy/shell/components/AssistantPanel.ts","../../src/client/components/AssistantPanel.tsx"],"sourcesContent":["/**\n * A split view's single keys (`shortcuts: { e: 'escalate' }`): the picked record's\n * header reads them from here, so the verb that a key runs shows it as a hint\n * and the key runs the verb through the same bar a click does.\n */\nimport { createContext } from 'react';\n\n/** Key → action id. */\nexport const RecordKeys = createContext<Readonly<Record<string, string>>>({});\n","/**\n * Which of a record's verbs is the one filled button, and the order of the\n * rest (docs/design.md, the record head): the verb the record most needs\n * next first and filled — the header's `primary` where it names one that is\n * shown now, else the first that takes nothing away — the others after it\n * in the author's order, and the destructive ones last and quiet. A record\n * whose only verbs are destructive has no filled button: the one it would\n * fill would end it.\n */\nimport type { AppAction } from '../../shared/appModel.js';\n\ntype ActionIntent = 'primary' | 'secondary' | 'quiet';\n\n/** The verbs in the order they are drawn, each with how it is drawn. */\nexport function orderActions<A extends Pick<AppAction, 'id'>>(\n actions: readonly A[],\n destructive?: (action: A) => boolean,\n primary?: string,\n): Array<{ action: A; intent: ActionIntent }> {\n const ends = (action: A) => Boolean(destructive?.(action));\n const lead =\n actions.find((action) => !ends(action) && primary !== undefined && action.id === primary) ?? actions.find((action) => !ends(action));\n const rest = actions.filter((action) => action !== lead);\n return [\n ...(lead ? [{ action: lead, intent: 'primary' as const }] : []),\n ...rest.filter((action) => !ends(action)).map((action) => ({ action, intent: 'secondary' as const })),\n ...rest.filter(ends).map((action) => ({ action, intent: 'quiet' as const })),\n ];\n}\n","/** What Actions says, in the record page room (packages/kit/src/client/messages.ts says how the catalog is split). */\nimport { defineMessages } from '../../../messages.js';\n\nexport const say = defineMessages({\n thisActionBelongsToAPrevious: 'This action belongs to a previous record surface.',\n actionDone: '{label} — done',\n wasAppliedButTheRecord: '{label} was applied, but the record could not be refreshed.',\n nothingToDoForThisRecord: 'Nothing to do for this record now',\n moreActionsForThisRecord: 'More actions for this record',\n moreActions: 'More actions',\n sayWhyFor: 'Say why, for \"{label}\". ',\n sayWhy: 'Say why. ',\n theReasonIsKept: 'The reason is kept with the record.',\n reason: 'Reason',\n labelReason: '{label}: reason',\n});\n","/**\n * The app's own verbs for a record.\n *\n * Fixed edits use /api/update. Authored commands open their own form and\n * never enter the generic update or Undo path.\n * A verb with a `when` is shown only while the record satisfies it, which\n * is a question for the server; until it answers, the button is not\n * there, because a button that appears and then vanishes is worse than\n * one that arrives late.\n */\nimport { ownedBy } from '@mistriwork/kit/client/requestIdentity.js';\nimport { createContext, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore, useId } from 'react';\nimport { Modal } from '@mistriwork/ui/Modal.js';\nimport { RecordKeys } from '@mistriwork/kit/client/components/recordKeys.js';\nimport { takesSingleKeys } from '@mistriwork/kit/client/components/RecordTrailNav.js';\nimport { Button } from '@mistriwork/ui/Button.js';\nimport { useMutation, useQueryClient, useQueries } from '@tanstack/react-query';\nimport { refreshAfterCommand } from '@mistriwork/kit/client/recordWriteRefresh.js';\nimport { DropItem, DropMenu } from '@mistriwork/ui/DropMenu.js';\nimport { api, columnLabel, findTable, humanName, state, toast } from '@mistriwork/kit/client/core.js';\nimport { recordKey as checkedRecordKey } from '@mistriwork/kit/client/resourceRequests.js';\nimport { updateAttempts, updateOwnerKey, type UpdateOwner } from '@mistriwork/kit/client/updateAttempts.js';\nimport type { AppAction, AppCommandAction, AppUpdateAction } from '../../shared/app.js';\nimport type { TableMeta } from '@mistriwork/engine/shared/schema.js';\nimport { Value } from '@mistriwork/kit/client/components/Value.js';\nimport { onDemand } from '@mistriwork/kit/client/components/onDemand.js';\nimport { commandOperations, type CommandOperation, type CommandOwner } from '../commandState.js';\nimport { readyCommand, sendCommand } from '../commandSend.js';\nimport { commandFieldsDeep } from '../../shared/command.js';\nimport { sessionIdentity, subscribeSessionIdentity } from '@mistriwork/kit/client/sessionIdentity.js';\nimport { useCommandAnswers } from '../commandAvailability.js';\nimport type { ActionBarProps, RecordActions } from '@mistriwork/kit/client/components/pageContext.js';\nimport { orderActions } from './actionOrder.js';\nimport { say } from '@mistriwork/kit/client/copy/record/components/Actions.js';\nimport { addHostListener, removeHostListener } from '@mistriwork/kit/client/shellHost.js';\n\n/* A command's form is a dialog opened by a click: its chunk is fetched then, not with the first page. */\nconst CommandForm = onDemand(() => import('./CommandForm.js'), 'CommandForm', { quiet: true });\n\nexport type { ActionBarProps } from '@mistriwork/kit/client/components/pageContext.js';\n\n/** What became of a verb the person ran: applied, or refused with the server's sentence. */\nexport type ActionOutcome = { status: 'done' | 'failed'; detail?: string };\n/**\n * Who else is told when a verb drawn below this point has run, besides the\n * toast: the assistant's conversation, whose cards and tables draw the\n * record's own bar (AssistantPanel.tsx). The person's click, reported after\n * the fact; nothing here runs a verb.\n */\nexport const ActionOutcomes = createContext<\n ((report: { tableId: string; key: Record<string, unknown>; label: string; action: AppAction; outcome: ActionOutcome }) => void) | null\n>(null);\n\n/** How many verbs stay buttons on a wide screen before the rest fold into More. */\nconst INLINE = 3;\n\nconst said = (v: unknown, empty: string) => (v === null ? empty : String(v));\n/** One key per condition on one record, shared by a button and the bar that decides whether to fold. */\nconst whenKey = (tableId: string, recordKey: Record<string, unknown>, when: string | undefined, queryScope?: number) => [\n 'when',\n tableId,\n state.activeConnection,\n sessionIdentity().epoch,\n recordKey,\n when,\n ...(queryScope === undefined ? [] : [queryScope]),\n];\nconst isCommand = (action: AppAction): action is AppCommandAction => action.command !== undefined;\n\n/**\n * The values the record's own fixed edits can give `column` now: an edit\n * whose `set` is exactly that column, once its `when` holds — the board's\n * rule for a lane. It asks the bar's own questions under the bar's keys, so\n * nothing is asked twice. A command says nothing here: where it moves a\n * record is its code's to decide, not something the App declares.\n */\nexport function useReachable(\n tableId: string,\n recordKey: Record<string, unknown>,\n column: string | undefined,\n actions: RecordActions | undefined,\n): ReadonlySet<string> {\n const moves =\n column && actions\n ? actions.list.filter(\n (action): action is AppUpdateAction =>\n !isCommand(action) &&\n Object.keys(action.set).length === 1 &&\n column in action.set &&\n (actions.canUpdate !== false || Boolean(actions.grantedActions?.includes(action.id))),\n )\n : [];\n const asked = [...new Set(moves.flatMap((action) => (action.when ? [action.when] : [])))];\n const answers = useQueries({\n queries: asked.map((when) => ({\n queryKey: whenKey(tableId, recordKey, when, actions?.queryScope),\n queryFn: () => actions!.matches(when),\n })),\n });\n const answered = new Map(asked.map((when, i) => [when, answers[i]?.data]));\n return new Set(moves.filter((action) => !action.when || answered.get(action.when) === true).map((action) => String(action.set[column!])));\n}\n\nexport function ActionBar({\n tableId,\n actions,\n recordKey,\n label,\n matches,\n queryScope,\n onDone,\n canUpdate = true,\n grantedCommands = [],\n grantedActions = [],\n isCurrent: hostIsCurrent,\n compact = false,\n menuTail,\n menuOnly,\n destructive,\n primary,\n only,\n quiet = false,\n}: ActionBarProps) {\n type Submission = {\n action: AppUpdateAction;\n owner: UpdateOwner;\n values: AppUpdateAction['set'];\n current: () => boolean;\n done: () => void;\n };\n const [asking, setAsking] = useState<Submission | null>(null);\n const [reasoning, setReasoning] = useState<Submission | null>(null);\n const [sending, setSending] = useState(false);\n const [commandForm, setCommandForm] = useState<{ action: AppCommandAction; owner: CommandOwner; epoch: number } | null>(null);\n const identity = useSyncExternalStore(subscribeSessionIdentity, sessionIdentity, sessionIdentity);\n useSyncExternalStore(commandOperations.subscribe, commandOperations.version, commandOperations.version);\n useSyncExternalStore(updateAttempts.subscribe, updateAttempts.version, updateAttempts.version);\n const owner: UpdateOwner = { connection: state.activeConnection ?? null, table: tableId, key: recordKey };\n const currentOwner = useRef(owner);\n currentOwner.current = owner;\n const ownerText = updateOwnerKey(owner);\n const lifetime = useMemo(() => ({ identity, hostIsCurrent }), [identity, hostIsCurrent, ownerText, queryScope]);\n const activeLifetime = useRef(lifetime);\n activeLifetime.current = lifetime;\n const mounted = useRef(true);\n useEffect(() => {\n mounted.current = true;\n return () => {\n mounted.current = false;\n };\n }, []);\n const isCurrent = (submitted: UpdateOwner) => {\n try {\n return (\n mounted.current &&\n activeLifetime.current === lifetime &&\n identity === sessionIdentity() &&\n identity.mode !== 'locked' &&\n identity.mode !== 'unknown' &&\n submitted.connection === (state.activeConnection ?? null) &&\n updateOwnerKey(submitted) === updateOwnerKey(currentOwner.current) &&\n (hostIsCurrent === undefined || hostIsCurrent() === true)\n );\n } catch {\n return false;\n }\n };\n const client = useQueryClient();\n const tell = useContext(ActionOutcomes);\n const told = (action: AppAction, key: Record<string, unknown>, outcome: ActionOutcome) =>\n tell?.({ tableId, key: { ...key }, label, action, outcome });\n const write = useMutation({\n retry: false,\n mutationFn: async ({ action, owner: submitted, values, current, done }: Submission) => {\n if (!current()) return undefined;\n const key = checkedRecordKey(submitted.key);\n const outcome = await updateAttempts.run(submitted, values, () => {\n if (!current()) throw Object.assign(new Error(say('thisActionBelongsToAPrevious')), { outcome: 'not_applied' });\n return api('/api/update', { ...ownedBy(submitted.connection), table: submitted.table, key, values });\n });\n return { action, submitted, outcome, current, done };\n },\n onSuccess: (result) => {\n if (!result || !result.current()) return;\n const { action, outcome, done } = result;\n if (outcome.kind !== 'applied') {\n if (outcome.kind !== 'uncertain') {\n toast(outcome.message, 'error');\n told(action, result.submitted.key, { status: 'failed', detail: outcome.message });\n }\n return;\n }\n told(action, result.submitted.key, { status: 'done' });\n toast(say('actionDone', { label: action.label }), 'ok');\n void client.invalidateQueries({ queryKey: ['when', tableId] });\n try {\n if (result.current()) done();\n } catch {\n toast(say('wasAppliedButTheRecord', { label: action.label }), 'error');\n }\n },\n onError: (err: Error, submitted) => {\n if (!submitted.current()) return;\n toast(err.message, 'error');\n told(submitted.action, submitted.owner.key, { status: 'failed', detail: err.message });\n },\n });\n\n const commandOwner = (action: AppCommandAction): CommandOwner => ({\n connection: state.activeConnection ?? '',\n target: action.command.target,\n command: action.command.id,\n commandVersion: action.command.version,\n key: { ...recordKey },\n });\n const allowedCommand = (action: AppCommandAction) =>\n identity.mode === 'authenticated' &&\n identity.appId === state.activeConnection &&\n grantedCommands.includes(action.command.id) &&\n action.command.target === tableId &&\n Boolean(findTable(tableId)) &&\n // Every type the form draws; a reference, at any depth, only over a resource this person reads.\n [...commandFieldsDeep(action.command.input)].every(({ field }) => field.type !== 'reference' || Boolean(findTable(field.from)));\n /* A fixed action is offered where the reader writes the table, or where a\n role of theirs runs this one without write (the server judges it again). */\n const allowedUpdate = (action: AppUpdateAction) => canUpdate || grantedActions.includes(action.id);\n const visible = actions.filter((action) => (isCommand(action) ? allowedCommand(action) : allowedUpdate(action)));\n /* `header: false` is an action the App runs from its own place: not drawn here, nor asked about, and still\n resumed below when its form was left open, since it is still the record's. */\n const drawable = visible.filter((action) => action.header !== false);\n const checkedCommands = drawable.filter(isCommand);\n const { available: availability, asking: askingCommands } = useCommandAnswers(\n checkedCommands.map((action) => ({ command: action.command.id, commandVersion: action.command.version, key: recordKey })),\n isCurrent(owner),\n lifetime,\n );\n // By id, not identity: a verb said in its state's words (below) is a copy of the one asked about.\n const availableCommand = (action: AppCommandAction) =>\n availability[checkedCommands.findIndex((checked) => checked.id === action.id)] === true;\n // Navigation can unmount a page; reopening the same record resumes its exact operation. One a component sent through\n // `run` is its caller's to resolve, and opens its own form if its answer never arrives.\n const resumable = (action: AppCommandAction) => {\n const operation = commandOperations.get(commandOwner(action));\n return Boolean(operation && !operation.headless);\n };\n const resumed = visible.find((action): action is AppCommandAction => isCommand(action) && resumable(action));\n const form =\n commandForm?.epoch === identity.epoch &&\n commandForm.owner.connection === state.activeConnection &&\n updateOwnerKey({ connection: commandForm.owner.connection, table: commandForm.owner.target, key: commandForm.owner.key }) ===\n updateOwnerKey(owner)\n ? commandForm\n : resumed\n ? { action: resumed, owner: commandOwner(resumed), epoch: identity.epoch }\n : null;\n const operation = form && commandOperations.get(form.owner);\n /* What a command on this record changed, asked again once its receipt lands (recordWriteRefresh.ts, G173). */\n const refreshCommanded = () =>\n refreshAfterCommand(client, {\n connection: owner.connection ?? '',\n table: tableId,\n key: recordKey,\n ...(queryScope === undefined ? {} : { queryScope }),\n });\n /* A command that asks nothing runs on one click, as a fixed verb does, and a notice says it ran: a\n dialog with only a submit in it asked a question nobody had. `confirm` asks first, in its form. An answer that\n never arrived opens the form, which says so and offers to check, as after its own submit. */\n const runAtOnce = async (action: AppCommandAction) => {\n const submitted = commandOwner(action);\n const surface = { ...owner, key: { ...owner.key } };\n setSending(true);\n const sent = await sendCommand(\n action,\n submitted,\n {},\n {\n headless: true,\n current: () => isCurrent(surface),\n refresh: () => {\n if (isCurrent(surface)) refreshCommanded();\n },\n },\n );\n if (mounted.current) setSending(false);\n if ('refused' in sent) {\n toast(sent.refused, 'error');\n told(action, submitted.key, { status: 'failed', detail: sent.refused });\n return;\n }\n const { operation } = sent;\n if (operation.phase === 'success' || operation.phase === 'error') {\n commandOperations.forget(submitted);\n if (operation.phase === 'error') {\n toast(operation.message, 'error');\n told(action, submitted.key, { status: 'failed', detail: operation.message });\n return;\n }\n // The command's own words when it said any (\"Order #2461 is packed at SEC\"), as its form would have said them.\n toast(operation.said ?? say('actionDone', { label: action.label }), 'ok');\n told(action, submitted.key, { status: 'done' });\n if (isCurrent(surface)) onDone();\n return;\n }\n if (isCurrent(surface)) setCommandForm({ action, owner: submitted, epoch: identity.epoch });\n };\n /* A command that runs on one click has its revision asked as the pointer or focus comes to its button, so the click\n sends only the execute (commandSend.ts readyCommand). */\n const atOnce = (action: AppAction): action is AppCommandAction =>\n isCommand(action) &&\n !action.command.input.length &&\n !action.confirm &&\n allowedCommand(action) &&\n availableCommand(action) &&\n !commandOperations.get(commandOwner(action));\n const ready = (action: AppAction) => {\n if (isCurrent(owner) && !busy && atOnce(action)) readyCommand(commandOwner(action));\n };\n const run = (action: AppAction) => {\n if (!isCurrent(owner)) return;\n if (isCommand(action)) {\n if (!allowedCommand(action) || !availableCommand(action)) return;\n if (atOnce(action)) void runAtOnce(action);\n else setCommandForm({ action, owner: commandOwner(action), epoch: identity.epoch });\n return;\n }\n if (!allowedUpdate(action)) return;\n if (updateAttempts.get(owner)) return;\n const submitted = { ...owner, key: { ...owner.key } };\n const submission = { action, owner: submitted, values: action.set, current: () => isCurrent(submitted), done: onDone };\n /* A reason is data, and a confirmation a promise to the author: both asked in every mode. An App has no Undo\n (its writes go through the writer pool), so a confirmed verb that wrote on one click could not be taken back. */\n if (action.reason) setReasoning(submission);\n else if (action.confirm) setAsking(submission);\n else write.mutate(submission);\n };\n\n /* Which actions are shown, asked once here with the same keys each button\n asks with, so a phone's menu knows before it draws whether it has one\n item or several, and nothing is asked twice: one question per distinct\n condition. An action without one asks nothing — a disabled placeholder\n for each shared one key, which React Query reported as duplicates. */\n /* A machine's verb that says itself differently by state (\"Move to Proposal\") asks which state the record is in\n the same way: one condition per label, answered with the rest. */\n const asked = [\n ...new Set(\n drawable.flatMap((action) => (isCommand(action) ? (action.labels ?? []).map((said) => said.when) : action.when ? [action.when] : [])),\n ),\n ];\n const conditions = useQueries({\n queries: asked.map((when) => ({\n queryKey: whenKey(tableId, recordKey, when, queryScope),\n queryFn: () => matches(when),\n })),\n });\n const answered = new Map(asked.map((when, i) => [when, conditions[i]?.data]));\n // Command availability already checks its current target/when on the\n // server; do not add a second per-row visibility HTTP request here.\n /* A verb with per-state labels waits for its label, so it never arrives in one set of words and changes to another. */\n const said = (action: AppAction): AppAction => {\n if (!isCommand(action) || !action.labels) return action;\n const label = action.labels.find((candidate) => answered.get(candidate.when) === true)?.label;\n return label === undefined || label === action.label ? action : { ...action, label };\n };\n const available = drawable\n .filter((action) =>\n isCommand(action)\n ? availableCommand(action) && (action.labels ?? []).every((candidate) => answered.get(candidate.when) !== undefined)\n : !action.when || answered.get(action.when) === true,\n )\n .map(said);\n /* One filled verb, the forward one; the destructive last and quiet (actionOrder.ts). Without a\n reading of what is destructive — a list's row menu — the author's order, the first filled. */\n const arranged = destructive\n ? orderActions(available, destructive, primary)\n : available.map((action, i) => ({ action, intent: i === 0 ? ('primary' as const) : ('secondary' as const) }));\n /* A header's `actions` lead in the order the author named them, the filled one first; whatever it does not name\n follows, and is More's however few there are. */\n const named = only\n ? arranged.filter(({ action }) => only.includes(action.id)).sort((a, b) => only.indexOf(a.action.id) - only.indexOf(b.action.id))\n : undefined;\n const ordered = named\n ? [\n ...(() => {\n const lead = named.find(({ intent }) => intent === 'primary');\n if (lead) return [lead, ...named.filter((entry) => entry !== lead)];\n /* The verb the record most needs next is not among the ones named: the first of those named that\n takes nothing away is filled, so a header with verbs always has its one filled button. */\n const first = named.find(({ intent }) => intent !== 'quiet');\n return first ? [{ ...first, intent: 'primary' as const }, ...named.filter((entry) => entry !== first)] : named;\n })(),\n ...arranged.filter((entry) => !named.includes(entry)),\n ]\n : arranged;\n const shown = ordered.map(({ action }) => action);\n const intentOf = new Map(ordered.map(({ action, intent }) => [action, quiet ? ('secondary' as const) : intent]));\n const busy = write.isPending || Boolean(updateAttempts.get(owner)) || sending;\n /* A split view's keys: shown beside the verb they run, and run through this bar as a click is. */\n const keys = useContext(RecordKeys);\n const keyOf = (action: AppAction) => Object.entries(keys).find(([, id]) => id === action.id)?.[0];\n const pressed = useRef<(key: string) => void>(() => {});\n pressed.current = (key) => {\n const action = shown.find((candidate) => keys[key] === candidate.id);\n if (action && !busy) run(action);\n };\n useEffect(() => {\n if (!Object.keys(keys).length) return;\n const onKey = (event: KeyboardEvent) => {\n if (!Object.hasOwn(keys, event.key) || !takesSingleKeys(event)) return;\n event.preventDefault();\n pressed.current(event.key);\n };\n addHostListener(document, 'keydown', onKey);\n return () => removeHostListener(document, 'keydown', onKey);\n }, [keys]);\n /* The usual next step is filled and first; a few more stay one tap away\n as quiet buttons, and the rest — Delete always last — are one menu. A\n phone keeps one button, so the bar never wraps under the name. */\n const inline = menuOnly ? [] : shown.slice(0, compact ? 1 : named ? named.length : INLINE);\n const folded = shown.slice(inline.length);\n /* While the record's verbs are still being asked about, the first one's\n place is held, unseen: on a phone the bar is a row of its own under the\n name, and its arriving pushed every section down a line\n (test/built-client-vitals.mjs). */\n const unanswered = askingCommands || conditions.some((condition) => condition.isPending);\n const hold = !menuOnly && !inline.length && unanswered && drawable.length > 0;\n\n return (\n <>\n {hold && (\n <Button className=\"page-action\" aria-hidden=\"true\" tabIndex={-1} style={{ visibility: 'hidden' }}>\n {drawable[0].label}\n </Button>\n )}\n {inline.map((action) => (\n <ActionButton\n key={action.label}\n action={action}\n intent={intentOf.get(action) ?? 'secondary'}\n busy={busy}\n hint={keyOf(action)}\n onReady={() => ready(action)}\n onClick={() => run(action)}\n />\n ))}\n {menuOnly && (\n <DropMenu\n className=\"row-actions-menu\"\n triggerClassName=\"ghost row-actions-trigger\"\n triggerTitle={say('common.actions', { label: menuOnly.label })}\n triggerLabel={say('common.actions', { label: menuOnly.label })}\n label=\"⋯\"\n popupClassName=\"page-actions-popup\"\n align=\"end\"\n open={menuOnly.open}\n onOpenChange={menuOnly.onOpenChange}\n >\n {folded.map((action) => (\n <DropItem\n key={action.label}\n className={destructive?.(action) ? 'page-actions-item is-danger' : 'page-actions-item'}\n disabled={busy}\n onClick={() => run(action)}\n >\n {action.label}\n </DropItem>\n ))}\n {/* Conditions still being asked, or none that hold: said, not an empty box. */}\n {!folded.length && (\n <DropItem className=\"page-actions-item\" disabled onClick={() => {}}>\n {conditions.some((condition) => condition.isPending) ? say('common.checking') : say('nothingToDoForThisRecord')}\n </DropItem>\n )}\n </DropMenu>\n )}\n {!menuOnly && (folded.length > 0 || menuTail) && (\n <DropMenu\n className=\"page-actions-menu\"\n triggerClassName=\"ghost page-action\"\n triggerTitle={say('moreActionsForThisRecord')}\n // \"More\" alone is the app menu's name; this one says whose it is.\n triggerLabel={say('moreActions')}\n label={say('common.more')}\n popupClassName=\"page-actions-popup\"\n align=\"end\"\n >\n {folded.map((action) => (\n <DropItem\n key={action.label}\n className={destructive?.(action) ? 'page-actions-item is-danger' : 'page-actions-item'}\n disabled={busy}\n onClick={() => run(action)}\n >\n {action.label}\n {keyOf(action) && <kbd className=\"key-hint\">{keyOf(action)!.toUpperCase()}</kbd>}\n </DropItem>\n ))}\n {menuTail}\n </DropMenu>\n )}\n {form && (\n <CommandForm\n key={`${form.epoch}:${form.owner.command}:${JSON.stringify(form.owner.key)}`}\n action={operation?.action ?? form.action}\n owner={operation?.owner ?? form.owner}\n label={label}\n isCurrent={hostIsCurrent}\n onApplied={refreshCommanded}\n onClose={(closed?: CommandOperation) => {\n if (!isCurrent(owner)) return;\n setCommandForm(null);\n if (closed?.phase === 'error') told(form.action, form.owner.key, { status: 'failed', detail: closed.message });\n }}\n onDone={() => {\n if (!isCurrent(owner)) return;\n told(form.action, form.owner.key, { status: 'done' });\n onDone();\n }}\n />\n )}\n {asking && (\n <Confirm\n tableId={tableId}\n action={asking.action}\n label={label}\n onAnswer={(yes) => {\n setAsking(null);\n if (yes && asking.current()) write.mutate(asking);\n }}\n />\n )}\n {reasoning && (\n <ReasonForm\n action={reasoning.action}\n label={label}\n onAnswer={(reason) => {\n setReasoning(null);\n if (reason !== null && reasoning.current() && reasoning.action.reason) {\n write.mutate({ ...reasoning, values: { ...reasoning.action.set, [reasoning.action.reason]: reason } });\n }\n }}\n />\n )}\n </>\n );\n}\n\n/** A verb as a button: whether it is shown was asked once, by the bar. */\nfunction ActionButton({\n action,\n intent,\n busy,\n hint,\n onReady,\n onClick,\n}: {\n action: AppAction;\n intent: 'primary' | 'secondary' | 'quiet';\n busy: boolean;\n hint?: string;\n onReady?: () => void;\n onClick: () => void;\n}) {\n return (\n <Button\n intent={intent}\n className=\"page-action\"\n disabled={busy}\n title={\n action.command\n ? action.label\n : Object.entries(action.set)\n .map(([c, v]) => `${c} → ${said(typeof v === 'string' && v.startsWith('=') ? v.slice(1) : v, 'null')}`)\n .join(', ')\n }\n onClick={onClick}\n onPointerEnter={onReady}\n onFocus={onReady}\n {...(hint ? { 'aria-keyshortcuts': hint.toUpperCase() } : {})}\n >\n {action.label}\n {hint && <kbd className=\"key-hint\">{hint.toUpperCase()}</kbd>}\n </Button>\n );\n}\n\n/** Ask before writing, in the page's own dialog. */\nfunction Confirm({\n tableId,\n action,\n label,\n onAnswer,\n}: {\n tableId: string;\n action: AppUpdateAction;\n label: string;\n onAnswer: (yes: boolean) => void;\n}) {\n const table = findTable(tableId) as TableMeta | undefined;\n const answered = useRef(false);\n const answer = (yes: boolean) => {\n if (answered.current) return;\n answered.current = true;\n onAnswer(yes);\n };\n return (\n <Modal className=\"confirm action-confirm\" ariaLabel={`${action.label}?`} onClose={() => answer(false)}>\n <h2>{action.label}?</h2>\n <p>{label}</p>\n <table className=\"confirm-diff\">\n <tbody>\n {Object.entries(action.set).map(([column, value]) => (\n <tr key={column}>\n <th scope=\"row\" title={column}>\n {columnLabel(tableId, column) ?? humanName(column)}\n </th>\n {/* An expression the server works out as it writes ('=today + 14 days') is said as written. */}\n <td>\n {typeof value === 'string' && value.startsWith('=') ? (\n value.slice(1)\n ) : (\n <Value\n tableId={tableId}\n col={\n table?.columns.find((col) => col.name === column) ?? { name: column, type: 'TEXT', nullable: true, primaryKey: false }\n }\n value={value}\n compact\n />\n )}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n <div className=\"confirm-actions\">\n <Button intent=\"secondary\" onClick={() => answer(false)}>\n {say('common.cancel')}\n </Button>\n <Button intent=\"primary\" onClick={() => answer(true)}>\n {action.label}\n </Button>\n </div>\n </Modal>\n );\n}\n\n/**\n * An action that moves a record for a reason asks for it first, in the page's\n * own dialog. The note is written with the change, in the same update, so the\n * server can hold the move to it (appTransitions).\n */\nexport function ReasonForm({\n action,\n label,\n onAnswer,\n}: {\n action: AppUpdateAction;\n label: string;\n onAnswer: (reason: string | null) => void;\n}) {\n const [text, setText] = useState('');\n const answered = useRef(false);\n const field = useId();\n const answer = (reason: string | null) => {\n if (answered.current) return;\n answered.current = true;\n onAnswer(reason);\n };\n return (\n <Modal\n className=\"confirm action-confirm action-reason\"\n ariaLabel={say('labelReason', { label: action.label })}\n onClose={() => answer(null)}\n >\n <form\n onSubmit={(event) => {\n event.preventDefault();\n if (text.trim()) answer(text.trim());\n }}\n >\n <h2>{action.label}</h2>\n <p>\n {label ? say('sayWhyFor', { label }) : say('sayWhy')}\n {say('theReasonIsKept')}\n </p>\n <label className=\"action-reason-label\" htmlFor={field}>\n {say('reason')}\n </label>\n <textarea\n id={field}\n className=\"action-reason-text\"\n value={text}\n required\n rows={3}\n autoFocus\n onChange={(event) => setText(event.target.value)}\n />\n <div className=\"confirm-actions\">\n <Button intent=\"secondary\" onClick={() => answer(null)}>\n {say('common.cancel')}\n </Button>\n <Button intent=\"primary\" type=\"submit\" disabled={!text.trim()}>\n {action.label}\n </Button>\n </div>\n </form>\n </Modal>\n );\n}\n","/** An App's assistant, as declared: who is offered it, which of the fixed\n * tools and blocks it may use, which of the App's verbs it may never propose,\n * and what it may spend. The declaration only narrows: every read and every\n * proposal is still the person's own, under their grants (docs/assistant.md). */\n\n/** The tool core, the same for every App: discovery is a tool, not a preamble. */\nexport const ASSISTANT_TOOLS = ['find', 'describe', 'query', 'show', 'run'] as const;\ntype AssistantTool = (typeof ASSISTANT_TOOLS)[number];\n/** The blocks the model may compose: the App's own components, never markup. */\nexport const ASSISTANT_BLOCKS = ['table', 'metric', 'chart', 'breakdown', 'record'] as const;\ntype AssistantBlockKind = (typeof ASSISTANT_BLOCKS)[number];\n/** Where it is offered: a panel beside every room, with a record as its context, and a room of its own (`/{app}/assistant`). */\nexport const ASSISTANT_PLACEMENTS = ['panel', 'record', 'page'] as const;\nexport const ASSISTANT_EFFORTS = ['low', 'medium', 'high'] as const;\n/** The model an App gets unless it names one; the operator's key decides whether any is reachable. */\nconst DEFAULT_ASSISTANT_MODEL = 'claude-sonnet-5-5';\nconst LIMIT_KEYS = ['tokensPerTurn', 'tokensPerPersonPerDay', 'tokensPerDay'] as const;\n/** What one person may spend in a UTC day when the App names no figure: an assistant is a bill the operator pays,\n * so an open sign-up is not an open tab. A modest day's use fits; an App that expects more names its own\n * `limits.tokensPerPersonPerDay`. */\nexport const DEFAULT_TOKENS_PER_PERSON_PER_DAY = 200_000;\n/** How long a conversation untouched is kept, in days, when nothing says otherwise: every App's, and a tenant App's\n * unless its policy names `assistant.retentionDays`. */\nexport const ASSISTANT_RETENTION_DAYS = 90;\nconst KEYS = ['instructions', 'starters', 'model', 'effort', 'roles', 'tools', 'exclude', 'blocks', 'placement', 'limits'] as const;\n/** An empty conversation offers a few of the App's own questions, each a line the person sends with one press: at\n most six in any one place, however many the App declares for its different places. */\nconst MAX_STARTERS = 6;\nconst MAX_STARTER = 120;\nconst STARTER_KEYS = ['text', 'views', 'records'] as const;\n\n/**\n * A starter offered in some places only: in the named views (their own rooms, a list or a dashboard), on a record of\n * the named tables, or both. A starter that is a bare line is offered everywhere.\n *\n * starters: ['Find stale deals', { text: 'Summarize this ticket', records: ['incident'] }]\n */\nexport interface AssistantStarter {\n text: string;\n /** View keys: offered while one of these views is the room. */\n views?: string[];\n /** Table names: offered while a record of one of these tables is open. */\n records?: string[];\n}\n\ninterface AssistantLimits {\n /** Input and output tokens one turn may spend, every model call in it counted; a call's cached input (the turn so far,\n * read again) counts at a tenth, as it is billed. */\n tokensPerTurn?: number;\n /** One person's tokens in a UTC day, across their conversations; `DEFAULT_TOKENS_PER_PERSON_PER_DAY` when not named. */\n tokensPerPersonPerDay?: number;\n /** Every person's tokens in the App in a UTC day. */\n tokensPerDay?: number;\n}\n\nexport interface AppAssistant {\n /** What the App's assistant is for and how it should answer: the author's words, prefixed by the platform's own rules. */\n instructions?: string;\n /** Questions an empty conversation offers, in the App's words: each sent as the person's own when pressed. A bare\n line is offered everywhere, a starter with `views` or `records` only there. */\n starters: Array<string | AssistantStarter>;\n model: string;\n effort?: (typeof ASSISTANT_EFFORTS)[number];\n /** The roles offered the assistant; absent, everyone who may open the App. */\n roles?: string[];\n tools: AssistantTool[];\n /** Verbs it may never propose, as `resource.action` (an action's key, or `new` for the New form). */\n exclude: string[];\n blocks: AssistantBlockKind[];\n placement: Array<(typeof ASSISTANT_PLACEMENTS)[number]>;\n limits: AssistantLimits;\n}\n\ninterface AssistantContext {\n roles: readonly string[] | undefined;\n /** Each resource's action keys, so an exclusion names a verb that exists. */\n actions: Readonly<Record<string, readonly string[]>>;\n /** Each view's key and the table it shows, so a starter names a view that exists. */\n views?: Readonly<Record<string, string | undefined>>;\n /** The tables a record can be opened from: a list view's or a page's. */\n recordTables?: readonly string[];\n}\n\nfunction subset<T extends string>(raw: unknown, allowed: readonly T[], where: string): T[] {\n if (!Array.isArray(raw) || !raw.length) throw new Error(`${where} is a non-empty list of ${allowed.map((x) => `\"${x}\"`).join(', ')}.`);\n for (const value of raw) {\n if (!allowed.includes(value as T))\n throw new Error(`${where} names \"${String(value)}\"; it is one of ${allowed.map((x) => `\"${x}\"`).join(', ')}.`);\n }\n return [...new Set(raw as T[])];\n}\n\nexport function parseAppAssistant(raw: unknown, context: AssistantContext, where = 'assistant'): AppAssistant | undefined {\n if (raw === undefined) return undefined;\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) throw new Error(`${where} is an object: assistant({ instructions, ... }).`);\n const a = raw as Record<string, unknown>;\n /* Writes wait for the person, and an author cannot turn that off: the record text the model reads is not theirs.\n A key that could only restate it was dropped before 1.0, so it is refused with the reason, not as a stranger. */\n if (Object.hasOwn(a, 'confirm'))\n throw new Error(`${where}.confirm is gone: every write the assistant proposes waits for the person to confirm it. Delete it.`);\n for (const key of Object.keys(a)) {\n if (!(KEYS as readonly string[]).includes(key)) throw new Error(`${where} has an unknown key \"${key}\"; it takes ${KEYS.join(', ')}.`);\n }\n if (a.instructions !== undefined && (typeof a.instructions !== 'string' || !a.instructions.trim())) {\n throw new Error(`${where}.instructions is a non-empty string.`);\n }\n if (a.model !== undefined && (typeof a.model !== 'string' || !/^[a-z0-9][a-z0-9.-]*$/.test(a.model))) {\n throw new Error(`${where}.model is a model id, such as \"${DEFAULT_ASSISTANT_MODEL}\".`);\n }\n if (a.effort !== undefined && !(ASSISTANT_EFFORTS as readonly unknown[]).includes(a.effort)) {\n throw new Error(`${where}.effort is \"low\", \"medium\" or \"high\".`);\n }\n let roles: string[] | undefined;\n if (a.roles !== undefined) {\n if (!context.roles) throw new Error(`${where}.roles names roles, and the App declares no \"auth\" with roles.`);\n roles = subset(a.roles as unknown, context.roles as string[], `${where}.roles`);\n }\n const tools = a.tools === undefined ? [...ASSISTANT_TOOLS] : subset(a.tools, ASSISTANT_TOOLS, `${where}.tools`);\n const blocks = a.blocks === undefined ? [...ASSISTANT_BLOCKS] : subset(a.blocks, ASSISTANT_BLOCKS, `${where}.blocks`);\n // A page of its own is a room in the App's menu: the author's to add, so absent it is the panel and the record.\n const placement =\n a.placement === undefined\n ? (['panel', 'record'] as AppAssistant['placement'])\n : subset(a.placement, ASSISTANT_PLACEMENTS, `${where}.placement`);\n if (!placement.includes('panel'))\n throw new Error(`${where}.placement includes \"panel\": the record placement and the page open the same conversation.`);\n const starters = a.starters === undefined ? [] : parseStarters(a.starters, placement, context, `${where}.starters`);\n const exclude: string[] = [];\n if (a.exclude !== undefined) {\n if (!Array.isArray(a.exclude)) throw new Error(`${where}.exclude is a list of \"resource.action\".`);\n for (const entry of a.exclude) {\n const [resource, action, rest] = typeof entry === 'string' ? entry.split('.') : [];\n if (!resource || !action || rest !== undefined)\n throw new Error(`${where}.exclude has \"${String(entry)}\"; each is \"resource.action\", or \"resource.new\" for its New form.`);\n const actions = context.actions[resource];\n if (!actions) throw new Error(`${where}.exclude names \"${resource}\", which is not one of the App's resources.`);\n if (action !== 'new' && !actions.includes(action)) {\n throw new Error(\n `${where}.exclude names \"${entry}\"; resources.${resource} has no action \"${action}\"${actions.length ? ` (it has ${actions.join(', ')})` : ''}.`,\n );\n }\n exclude.push(entry);\n }\n }\n const limits: AssistantLimits = { tokensPerPersonPerDay: DEFAULT_TOKENS_PER_PERSON_PER_DAY };\n if (a.limits !== undefined) {\n if (!a.limits || typeof a.limits !== 'object' || Array.isArray(a.limits)) throw new Error(`${where}.limits is an object.`);\n for (const [key, value] of Object.entries(a.limits)) {\n if (!(LIMIT_KEYS as readonly string[]).includes(key))\n throw new Error(`${where}.limits has an unknown key \"${key}\"; it takes ${LIMIT_KEYS.join(', ')}.`);\n if (!Number.isSafeInteger(value) || (value as number) < 1000)\n throw new Error(`${where}.limits.${key} is a whole number of tokens, at least 1000.`);\n limits[key as keyof AssistantLimits] = value as number;\n }\n }\n return {\n ...(a.instructions === undefined ? {} : { instructions: (a.instructions as string).trim() }),\n starters,\n model: (a.model as string | undefined) ?? DEFAULT_ASSISTANT_MODEL,\n ...(a.effort === undefined ? {} : { effort: a.effort as AppAssistant['effort'] }),\n ...(roles ? { roles } : {}),\n tools,\n exclude,\n blocks,\n placement,\n limits,\n };\n}\n\nfunction nameList(raw: unknown, known: (name: string) => boolean, where: string, what: string, unknown: string): string[] {\n if (!Array.isArray(raw) || !raw.length || raw.some((name) => typeof name !== 'string' || !name))\n throw new Error(`${where} is a non-empty list of ${what}.`);\n for (const name of raw as string[]) if (!known(name)) throw new Error(`${where} names \"${name}\", which ${unknown}.`);\n return [...new Set(raw as string[])];\n}\n\nfunction parseStarters(\n raw: unknown,\n placement: AppAssistant['placement'],\n context: AssistantContext,\n where: string,\n): AppAssistant['starters'] {\n if (!Array.isArray(raw) || !raw.length)\n throw new Error(`${where} is a list of questions an empty conversation offers: a line, or { text, views, records }.`);\n const views = context.views ?? {};\n const tables = new Set(context.recordTables ?? Object.values(views).filter((table) => table !== undefined));\n const seen = new Set<string>();\n const starters = raw.map((entry, i): string | AssistantStarter => {\n const at = `${where}[${i}]`;\n const scoped = Boolean(entry) && typeof entry === 'object' && !Array.isArray(entry);\n const text = scoped ? (entry as Record<string, unknown>).text : entry;\n if (typeof text !== 'string' || !text.trim() || text.trim().length > MAX_STARTER || /[\\p{Cc}\\p{Cs}]/u.test(text))\n throw new Error(`${where} has ${JSON.stringify(text)}; each is one line of at most ${MAX_STARTER} characters.`);\n const line = text.trim();\n if (seen.has(line)) throw new Error(`${where} names \"${line}\" twice.`);\n seen.add(line);\n if (!scoped) return line;\n const starter = entry as Record<string, unknown>;\n for (const key of Object.keys(starter))\n if (!(STARTER_KEYS as readonly string[]).includes(key))\n throw new Error(`${at} has an unknown key \"${key}\"; a starter takes ${STARTER_KEYS.join(', ')}.`);\n if (starter.views === undefined && starter.records === undefined)\n throw new Error(`${at} names no place: give it views, records or both, or write the line alone to offer it everywhere.`);\n const out: AssistantStarter = { text: line };\n if (starter.views !== undefined)\n out.views = nameList(starter.views, (key) => Object.hasOwn(views, key), `${at}.views`, 'view keys', \"is not one of this App's views\");\n if (starter.records !== undefined) {\n // A record's starter speaks of the open record (\"Summarize this ticket\"), so the assistant must be handed it.\n if (!placement.includes('record'))\n throw new Error(\n `${at}.records offers it on an open record, and the assistant does not take the record as context: add \"record\" to placement.`,\n );\n out.records = nameList(\n starter.records,\n (table) => tables.has(table),\n `${at}.records`,\n 'table names',\n 'no list view or page of this App opens a record of',\n );\n }\n return out;\n });\n /* At most six in any one place: everywhere's, with a view's own or a record's own. */\n const everywhere = starters.filter((s) => typeof s === 'string').length;\n const places = [\n ['everywhere', everywhere] as const,\n ...Object.keys(views).map(\n (key) => [`in view \"${key}\"`, everywhere + starters.filter((s) => typeof s !== 'string' && s.views?.includes(key)).length] as const,\n ),\n ...[...tables].map(\n (table) =>\n [`on a ${table} record`, everywhere + starters.filter((s) => typeof s !== 'string' && s.records?.includes(table)).length] as const,\n ),\n ];\n const crowded = places.find(([, count]) => count > MAX_STARTERS);\n if (crowded) throw new Error(`${where} offers ${crowded[1]} starters ${crowded[0]}; at most ${MAX_STARTERS} are offered in one place.`);\n return starters;\n}\n\n/** Where the person is, as the starters read it: the view that is the room, the table of the record that is open. */\ninterface StarterPlace {\n view?: string;\n record?: string;\n}\n\n/** The starters offered here, in the App's order: every bare line, and a scoped one where its view or record is. */\nexport function startersHere(starters: readonly (string | AssistantStarter)[] | undefined, here: StarterPlace): string[] {\n return (starters ?? []).flatMap((starter) => {\n if (typeof starter === 'string') return [starter];\n const offered =\n (here.view !== undefined && starter.views?.includes(here.view)) ||\n (here.record !== undefined && starter.records?.includes(here.record));\n return offered ? [starter.text] : [];\n });\n}\n","/**\n * The assistant's requests, as its panel sends them. In an ordinary App they\n * are `api()`'s. In a tenant App they carry the tab's context lease and\n * nothing that names a tenant: the server recovers the lease and takes the\n * tenant from it alone (server tenant/tenantAssistant.ts), so a conversation\n * is always the current customer's. Kept in the assistant's own chunk.\n */\nimport { api } from '@mistriwork/kit/client/core.js';\nimport { captureSessionIdentity, captureTenantLease } from '@mistriwork/kit/client/sessionIdentity.js';\nimport { TENANT_HTTP_HEADERS as names } from '../../shared/tenantContext.js';\nimport { fetchServer } from '@mistriwork/kit/client/transport.js';\n\n/** The account, and in a tenant App the tab's lease: what the server admits an assistant request by. */\nexport function assistantHeaders(): Record<string, string> {\n const identity = captureSessionIdentity();\n if (identity.mode !== 'authenticated' || !identity.accountId) return {};\n const lease = identity.tenantRequired ? captureTenantLease(identity) : undefined;\n return {\n [names.account]: identity.accountId,\n ...(lease && identity.appId\n ? { [names.app]: identity.appId, [names.tab]: lease.tabId, [names.context]: lease.context, [names.revision]: String(lease.revision) }\n : {}),\n };\n}\n\n/**\n * Whose conversations the panel shows: the account's, in the lease's tenant, so the history switches with the customer\n * and with the person. The panel is kept while the page is, and a conversation it last showed was reopened for whoever\n * signed in next in that tab, who could only be refused it.\n */\nexport function assistantOwner(): string {\n const identity = captureSessionIdentity();\n const tenant = (identity.tenantRequired && captureTenantLease(identity)?.tenantId) || '';\n return `${identity.accountId ?? ''}\\n${tenant}`;\n}\n\nexport async function assistantApi(path: string, body?: Record<string, unknown>): Promise<unknown> {\n if (!captureSessionIdentity().tenantRequired) return api(path as never, ...((body === undefined ? [] : [body]) as never[]));\n const res = await fetchServer(path, {\n method: body === undefined ? 'GET' : 'POST',\n credentials: 'same-origin',\n cache: 'no-store',\n headers: { ...assistantHeaders(), ...(body === undefined ? {} : { 'content-type': 'application/json' }) },\n ...(body === undefined ? {} : { body: JSON.stringify(body) }),\n });\n let value: { error?: unknown } | null = null;\n try {\n value = (await res.json()) as { error?: unknown };\n } catch {\n /* The status is all there is to say. */\n }\n if (!res.ok) throw Object.assign(new Error(typeof value?.error === 'string' ? value.error : `${res.status}`), { status: res.status });\n return value;\n}\n","/**\n * The assistant panel's model, without React: the items a conversation is\n * drawn as, the server-sent events a turn streams, and how each event\n * changes the items. The server rebuilds the same items from what it stored\n * (assistantTurn.ts `itemsOf`), so a conversation reopened reads as it did\n * live; the one difference is that live text arrives a word at a time.\n *\n * Nothing here trusts the stream's shape: an event that does not read as its\n * kind is dropped rather than drawn.\n */\nimport { assistantHeaders } from './assistantRequest.js';\nimport { scopeApiRequest } from '@mistriwork/kit/client/requestIdentity.js';\nimport { state } from '@mistriwork/kit/client/core.js';\nimport { fetchServer } from '@mistriwork/kit/client/transport.js';\n\nexport type ProposalOutcome = { status: 'done' | 'declined' | 'failed'; detail?: string };\nexport interface Proposal {\n id: string;\n kind: 'set' | 'command' | 'new';\n resource: string;\n action: string;\n label: string;\n key?: Record<string, unknown>;\n record?: string;\n address?: string;\n values: Record<string, unknown>;\n why?: string;\n}\nexport type AssistantBlock =\n | { kind: 'section'; section: Record<string, unknown> }\n | { kind: 'record'; table: string; key: Record<string, unknown>; title: string; values: Record<string, unknown>; address?: string };\n\nexport type PanelItem =\n /** `seq` is the stored event's, once the server has said it; edit names it. */\n | { type: 'person'; seq?: number; text: string }\n /** `open` while the model is still writing it. */\n | { type: 'text'; text: string; open?: true }\n | { type: 'note'; text: string }\n | { type: 'step'; id: string; tool: string; label: string; failed?: true }\n | { type: 'block'; id: string; block: AssistantBlock }\n | { type: 'proposal'; id: string; proposal: Proposal; outcome?: ProposalOutcome };\n\nexport interface StreamEvent {\n event: string;\n data: Record<string, unknown>;\n}\n\nconst record = (value: unknown): value is Record<string, unknown> => Boolean(value) && typeof value === 'object' && !Array.isArray(value);\n\n/** A run of the model's words: plain, bold, code, or a link to an address inside the App. */\nexport type Run = { text: string; mark?: 'strong' | 'code' } | { text: string; link: string };\nexport type Paragraph = { list: false; lines: Run[][] } | { list: true; lines: Run[][] };\n\n/* An inside address only: a path, never a scheme or another host. */\nexport const inside = (href: string): boolean => /^\\/(?!\\/)[^\\s\\\\]*$/.test(href);\n\n/**\n * The model's words as paragraphs and lists of runs, read with three marks\n * and nothing else. Text, never markup: a link to anywhere but a path in the\n * App is said as its words alone.\n */\nexport function wordsOf(text: string): Paragraph[] {\n const runs = (line: string): Run[] => {\n const found: Run[] = [];\n const pattern = /\\[([^\\]\\n]+)\\]\\(([^)\\s]+)\\)|\\*\\*([^*\\n]+)\\*\\*|`([^`\\n]+)`/g;\n let from = 0;\n for (let match = pattern.exec(line); match; match = pattern.exec(line)) {\n if (match.index > from) found.push({ text: line.slice(from, match.index) });\n if (match[1] !== undefined) found.push(inside(match[2]) ? { text: match[1], link: match[2] } : { text: match[1] });\n else if (match[3] !== undefined) found.push({ text: match[3], mark: 'strong' });\n else found.push({ text: match[4], mark: 'code' });\n from = match.index + match[0].length;\n }\n if (from < line.length) found.push({ text: line.slice(from) });\n return found;\n };\n return text\n .trim()\n .split(/\\n{2,}/)\n .filter(Boolean)\n .map((paragraph) => {\n const lines = paragraph.split('\\n');\n const list = lines.every((line) => /^\\s*[-*] /.test(line));\n return { list, lines: lines.map((line) => runs(list ? line.replace(/^\\s*[-*] /, '') : line)) };\n });\n}\n\n/** The events of a `text/event-stream` body, each handed on as it completes. */\nexport async function readEvents(body: ReadableStream<Uint8Array>, onEvent: (event: StreamEvent) => void): Promise<void> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n for (;;) {\n const { done, value } = await reader.read();\n buffer += done ? decoder.decode() : decoder.decode(value, { stream: true });\n let end: number;\n while ((end = buffer.indexOf('\\n\\n')) >= 0) {\n const chunk = buffer.slice(0, end);\n buffer = buffer.slice(end + 2);\n let event = 'message';\n const data: string[] = [];\n for (const line of chunk.split('\\n')) {\n if (line.startsWith('event:')) event = line.slice(6).trim();\n else if (line.startsWith('data:')) data.push(line.slice(5).trimStart());\n }\n try {\n const parsed: unknown = JSON.parse(data.join('\\n'));\n if (record(parsed)) onEvent({ event, data: parsed });\n } catch {\n /* Not an event this panel reads. */\n }\n }\n if (done) return;\n }\n}\n\n/** The items after one event. Pure: the panel keeps the result as its state. */\nexport function applyEvent(items: readonly PanelItem[], { event, data }: StreamEvent): PanelItem[] {\n const next = items.map((item) =>\n item.type === 'text' && item.open && event !== 'text' ? { type: 'text' as const, text: item.text } : item,\n );\n const last = next[next.length - 1];\n switch (event) {\n case 'conversation':\n // The person's words as stored: the seq an edit names from now on.\n if (typeof data.person === 'number')\n for (let at = next.length - 1; at >= 0; at--) {\n const item = next[at];\n if (item.type === 'person') {\n next[at] = { ...item, seq: data.person };\n break;\n }\n }\n return next;\n case 'text':\n if (typeof data.delta !== 'string') return next;\n if (last?.type === 'text' && last.open) next[next.length - 1] = { type: 'text', text: last.text + data.delta, open: true };\n else next.push({ type: 'text', text: data.delta, open: true });\n return next;\n case 'step':\n if (typeof data.id === 'string' && typeof data.tool === 'string' && typeof data.label === 'string')\n next.push({\n type: 'step',\n id: data.id,\n tool: data.tool,\n label: data.label,\n ...(data.failed === true ? { failed: true as const } : {}),\n });\n return next;\n case 'block':\n if (typeof data.id === 'string' && record(data.block)) next.push({ type: 'block', id: data.id, block: data.block as AssistantBlock });\n return next;\n case 'proposal':\n if (typeof data.id === 'string' && record(data.proposal))\n next.push({ type: 'proposal', id: data.id, proposal: data.proposal as unknown as Proposal });\n return next;\n case 'note':\n if (typeof data.text === 'string') next.push({ type: 'note', text: data.text });\n return next;\n default:\n return next;\n }\n}\n\n/** The items cut back to before the person's words at `at`, for an edit or a retry. */\nexport function cutAt(items: readonly PanelItem[], at: number): PanelItem[] {\n return items.slice(0, at);\n}\n\n/** The proposal still waiting for the person: the last one, if it has no outcome. */\nexport function waitingProposal(items: readonly PanelItem[]): Proposal | undefined {\n for (let at = items.length - 1; at >= 0; at--) {\n const item = items[at];\n if (item.type === 'person') return undefined;\n if (item.type === 'proposal') return item.outcome ? undefined : item.proposal;\n }\n return undefined;\n}\n\n/** The items grouped for drawing: consecutive steps fold into one group. */\ntype DrawnItem =\n | { type: 'steps'; steps: Extract<PanelItem, { type: 'step' }>[]; at: number }\n | { type: 'item'; item: PanelItem; at: number };\nexport function grouped(items: readonly PanelItem[]): DrawnItem[] {\n const drawn: DrawnItem[] = [];\n items.forEach((item, at) => {\n const last = drawn[drawn.length - 1];\n if (item.type === 'step' && last?.type === 'steps') last.steps.push(item);\n else if (item.type === 'step') drawn.push({ type: 'steps', steps: [item], at });\n else drawn.push({ type: 'item', item, at });\n });\n return drawn;\n}\n\n/**\n * A turn whose connection to the server dropped before the answer finished: the network went, the server restarted,\n * or a proxy answered in its place (\"Container suddenly disconnected\" as a bare 500, a field report). There is no\n * sentence of the server's to say, only that the turn can be tried again.\n */\nclass ConnectionLost extends Error {\n // The panel says it in its own words (connectionLost); there is no sentence here to show.\n readonly lost = true;\n}\n\n/**\n * A turn: POSTed as `api()` posts (the App named, the account said), read\n * as a stream. Resolves when the stream ends; a refusal before it starts\n * throws with the server's sentence, and a turn cut off on the way throws\n * ConnectionLost.\n */\nexport async function stream(\n path: '/api/assistant/turn' | '/api/assistant/resolve',\n body: Record<string, unknown>,\n onEvent: (event: StreamEvent) => void,\n signal: AbortSignal,\n): Promise<void> {\n const { url, payload } = scopeApiRequest(path, body, state.activeConnection);\n // A stop is the person's own, never a lost connection.\n const cut = (error: unknown): never => {\n throw signal.aborted ? error : new ConnectionLost();\n };\n const res = await fetchServer(url, {\n method: 'POST',\n credentials: 'same-origin',\n cache: 'no-store',\n signal,\n // The account, and in a tenant App the tab's lease, from which alone the server takes the tenant.\n headers: { 'content-type': 'application/json', ...assistantHeaders() },\n body: JSON.stringify(payload),\n }).catch(cut);\n if (!res.ok || !res.body) {\n let message: string | undefined;\n try {\n const said = (await res.json()) as { error?: unknown };\n if (typeof said.error === 'string') message = said.error;\n } catch {\n /* Not the server's own answer. */\n }\n // A server error without the server's sentence was said by whatever stood between: a gateway, a proxy.\n if (message === undefined && res.status >= 500) throw new ConnectionLost();\n throw Object.assign(new Error(message ?? `${res.status}`), { status: res.status });\n }\n // Every turn the server finishes ends in `done`; a stream that closes before it was cut off.\n let finished = false;\n await readEvents(res.body, (event) => {\n if (event.event === 'done') finished = true;\n onEvent(event);\n }).catch(cut);\n if (!finished && !signal.aborted) throw new ConnectionLost();\n}\n","/** What ConversationList says, in the shell room (packages/kit/src/client/messages.ts says how the catalog is split). */\nimport { defineMessages } from '@mistriwork/kit/client/messages.js';\n\nexport const say = defineMessages({\n newConversation: 'New conversation',\n noConversations: 'No conversations yet.',\n deleteConversation: 'Delete “{title}”',\n untitled: 'Untitled conversation',\n filterConversations: 'Filter conversations',\n clearSearch: 'Clear the search',\n searchResults: 'Conversations that match',\n noMatches: 'No conversations match',\n conversationActions: 'Actions for “{title}”',\n rename: 'Rename',\n renameLabel: 'Rename “{title}”',\n delete: 'Delete',\n deleteConversationTerms: 'Its messages are deleted for good. Records it showed or changed stay as they are.',\n waitingShort: 'Waiting for you',\n workingShort: 'Working',\n day_today: 'Today',\n day_yesterday: 'Yesterday',\n group_waiting: 'Waiting for you',\n group_today: 'Today',\n group_yesterday: 'Yesterday',\n group_week: 'Earlier this week',\n group_older: 'Older',\n});\n","/**\n * The assistant's conversations, one list for the room's rail and the panel's\n * Conversations view (AssistantPanel.tsx): what needs the person first — a\n * change waiting for them to confirm — then the rest by when they were last\n * touched, a quiet line each.\n *\n * Search is two answers to one box. Titles are filtered as the person types,\n * from the list already here; a moment after they stop, the server is asked\n * for the conversations whose words hold it (`/api/assistant/search` — theirs\n * and the model's, never a tool's result, and only their own), and those\n * come back with the line they were found in.\n *\n * Nothing here moves on its own: a turn still running is a word in the faint\n * ink where the time would be, not a pulse (docs/design.md, motion).\n */\nimport { useEffect, useMemo, useRef, useState, type KeyboardEvent, type ReactNode } from 'react';\nimport { useQuery } from '@tanstack/react-query';\nimport { assistantApi, assistantOwner } from './assistantRequest.js';\nimport { formatLocale, formatTimezone } from '@mistriwork/kit/client/locale.js';\nimport { Button } from '@mistriwork/ui/Button.js';\nimport { DropItem, DropMenu } from '@mistriwork/ui/DropMenu.js';\nimport { Modal, type ModalHandle } from '@mistriwork/ui/Modal.js';\nimport { say } from '../copy/shell/components/ConversationList.js';\n\nexport interface ConversationSummary {\n id: string;\n title: string;\n updatedAt: string;\n /** `awaiting`: a change the model proposed is waiting for the person. */\n state?: 'idle' | 'awaiting';\n /** The line a search found it by. */\n snippet?: string;\n}\n\ninterface ListProps {\n app: string;\n conversations: readonly ConversationSummary[];\n current: string | null;\n /** The conversation whose turn is running here, if one is. */\n working?: string | null;\n onOpen: (id: string) => void;\n onNew: () => void;\n onRename: (id: string, title: string) => Promise<void>;\n onDelete: (id: string) => Promise<void>;\n /** The clock the groups are read against; the browser's, but a test's own. */\n now?: Date;\n}\n\nconst DAY = 86_400_000;\n\ntype Group = 'waiting' | 'today' | 'yesterday' | 'week' | 'older';\nconst GROUPS: readonly Group[] = ['waiting', 'today', 'yesterday', 'week', 'older'];\n\nconst headingOf = (group: Group): string =>\n ({\n waiting: say('group_waiting'),\n today: say('group_today'),\n yesterday: say('group_yesterday'),\n week: say('group_week'),\n older: say('group_older'),\n })[group];\n\n/* The App's zone when it names one this runtime knows (`ui.timezone`, which the payload always fills), else the\n reader's own: \"today\" is the day the App's dates already mean, as formatRelativeDay reads it (locale.ts). */\nconst zones = new Map<string, Intl.DateTimeFormat>();\nfunction dayParts(zone: string | undefined): Intl.DateTimeFormat {\n const key = zone ?? '';\n let format = zones.get(key);\n if (!format) {\n format = new Intl.DateTimeFormat('en-US', { timeZone: zone, year: 'numeric', month: 'numeric', day: 'numeric' });\n zones.set(key, format);\n }\n return format;\n}\nfunction zoneOf(): string | undefined {\n const zone = formatTimezone();\n if (!zone) return undefined;\n try {\n dayParts(zone);\n return zone;\n } catch {\n return undefined;\n }\n}\n/** The calendar day an instant falls on in `zone`, as a UTC midnight: a ruler for counting days, never a moment. */\nfunction dayOn(at: Date, zone: string | undefined): number {\n const parts = dayParts(zone).formatToParts(at);\n const get = (type: string) => Number(parts.find((part) => part.type === type)?.value);\n return Date.UTC(get('year'), get('month') - 1, get('day'));\n}\n/** How many calendar days before today (in the App's zone) a conversation was last touched; NaN for no date. */\nfunction daysBefore(updatedAt: string, now: Date, zone: string | undefined): number {\n const at = new Date(updatedAt);\n if (!Number.isFinite(at.getTime()) || !Number.isFinite(now.getTime())) return Number.NaN;\n return Math.round((dayOn(now, zone) - dayOn(at, zone)) / DAY);\n}\n\n/** Which heading a conversation sits under: waiting first, then by its last change's calendar day. */\nfunction groupOf(conversation: ConversationSummary, now: Date, zone: string | undefined): Group {\n if (conversation.state === 'awaiting') return 'waiting';\n const days = daysBefore(conversation.updatedAt, now, zone);\n if (!(days > 0)) return Number.isNaN(days) ? 'older' : 'today';\n if (days === 1) return 'yesterday';\n if (days < 7) return 'week';\n return 'older';\n}\n\n/** Its day, said as the headings say days: \"Today\", \"Yesterday\", a weekday within the week, then the date (\"Sep 4\"). */\nfunction dayLabel(updatedAt: string, now: Date, zone: string | undefined): string {\n const days = daysBefore(updatedAt, now, zone);\n if (Number.isNaN(days)) return '';\n if (days <= 0) return say('day_today');\n if (days === 1) return say('day_yesterday');\n const at = new Date(updatedAt);\n const locale = formatLocale();\n if (days < 7) return new Intl.DateTimeFormat(locale, { weekday: 'short', timeZone: zone }).format(at);\n const sameYear = new Date(dayOn(at, zone)).getUTCFullYear() === new Date(dayOn(now, zone)).getUTCFullYear();\n return new Intl.DateTimeFormat(locale, {\n month: 'short',\n day: 'numeric',\n timeZone: zone,\n ...(sameYear ? {} : { year: 'numeric' }),\n }).format(at);\n}\n\n/** The time the list is read against: the browser's, read afresh each render and at least each minute, so a list\n left open over midnight moves its rows to Yesterday. A test passes its own. */\nfunction useNow(given: Date | undefined): Date {\n const [, tick] = useState(0);\n useEffect(() => {\n if (given) return;\n const every = window.setInterval(() => tick((was) => was + 1), 60_000);\n return () => window.clearInterval(every);\n }, [given]);\n return given ?? new Date();\n}\n\n/** The words a search found, marked where they are. */\nfunction Marked({ text, words }: { text: string; words: string }) {\n const at = words ? text.toLowerCase().indexOf(words.toLowerCase()) : -1;\n if (at < 0) return <>{text}</>;\n return (\n <>\n {text.slice(0, at)}\n <mark>{text.slice(at, at + words.length)}</mark>\n {text.slice(at + words.length)}\n </>\n );\n}\n\n/* A funnel: the rail's box narrows this list, and is not the App's search. */\nfunction Funnel() {\n return (\n <svg\n className=\"assistant-convs-find-icon\"\n viewBox=\"0 0 16 16\"\n width=\"12\"\n height=\"12\"\n aria-hidden=\"true\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M2.5 3.5h11l-4.25 5v4l-2.5 1v-5z\" />\n </svg>\n );\n}\n\nfunction Plus() {\n return (\n <svg className=\"icon\" viewBox=\"0 0 16 16\" width=\"14\" height=\"14\" aria-hidden=\"true\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\">\n <path d=\"M8 3v10M3 8h10\" />\n </svg>\n );\n}\n\nexport function ConversationList({ app, conversations, current, working, onOpen, onNew, onRename, onDelete, now: given }: ListProps) {\n const now = useNow(given);\n const zone = zoneOf();\n const [words, setWords] = useState('');\n const [asked, setAsked] = useState('');\n const [renaming, setRenaming] = useState<string | null>(null);\n const [deleting, setDeleting] = useState<ConversationSummary | null>(null);\n const term = words.trim();\n\n /* The server is asked once the person stops typing for a moment; titles answer at once meanwhile. */\n useEffect(() => {\n const wait = window.setTimeout(() => setAsked(term), 250);\n return () => window.clearTimeout(wait);\n }, [term]);\n const searched = useQuery({\n queryKey: ['assistant-search', app, assistantOwner(), asked],\n enabled: asked.length > 0,\n staleTime: 10_000,\n queryFn: async () =>\n (await assistantApi(`/api/assistant/search?app=${encodeURIComponent(app)}&q=${encodeURIComponent(asked)}`)) as {\n conversations: ConversationSummary[];\n },\n });\n\n const shown = useMemo(() => {\n if (!term) return conversations;\n const lower = term.toLowerCase();\n const found = asked === term ? (searched.data?.conversations ?? []) : [];\n const snippets = new Map(found.map((each) => [each.id, each.snippet]));\n const byTitle = conversations\n .filter((each) => each.title.toLowerCase().includes(lower))\n .map((each) => ({ ...each, snippet: snippets.get(each.id) }));\n const seen = new Set(byTitle.map((each) => each.id));\n return [...byTitle, ...found.filter((each) => !seen.has(each.id))];\n }, [conversations, term, asked, searched.data]);\n\n const groups = useMemo(() => {\n const out = new Map<Group, ConversationSummary[]>();\n for (const each of shown) {\n const group = groupOf(each, now, zone);\n out.set(group, [...(out.get(group) ?? []), each]);\n }\n return GROUPS.filter((group) => out.has(group)).map((group) => ({ group, rows: out.get(group)! }));\n // Grouped again when the day turns, not each render: today's day is what the clock changes.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [shown, zone, Number.isFinite(now.getTime()) ? dayOn(now, zone) : 0]);\n\n const onSearchKey = (event: KeyboardEvent<HTMLInputElement>) => {\n if (event.key === 'Escape' && words) {\n // The box empties first; the panel's own Escape is the next press's.\n event.preventDefault();\n event.stopPropagation();\n setWords('');\n }\n };\n const settling = Boolean(term) && (asked !== term || searched.isFetching);\n\n const row = (each: ConversationSummary): ReactNode => {\n const here = each.id === current;\n const waiting = each.state === 'awaiting';\n return (\n <li key={each.id} className={`assistant-conv${here ? ' assistant-conv-current' : ''}${waiting ? ' assistant-conv-waiting' : ''}`}>\n {renaming === each.id ? (\n <RenameField\n title={each.title}\n onDone={(title) => {\n setRenaming(null);\n if (title && title !== each.title) void onRename(each.id, title);\n }}\n />\n ) : (\n <button type=\"button\" className=\"assistant-conv-open\" aria-current={here ? 'true' : undefined} onClick={() => onOpen(each.id)}>\n <span className=\"assistant-conv-line\">\n {waiting && <span className=\"assistant-conv-dot\" aria-label={say('waitingShort')} role=\"img\" />}\n <span className=\"assistant-conv-title\" title={each.title || undefined}>\n <Marked text={each.title || say('untitled')} words={term} />\n </span>\n <span className=\"assistant-conv-when\">{working === each.id ? say('workingShort') : dayLabel(each.updatedAt, now, zone)}</span>\n </span>\n {term && each.snippet && (\n <span className=\"assistant-conv-snippet\">\n <Marked text={each.snippet} words={term} />\n </span>\n )}\n </button>\n )}\n {renaming !== each.id && (\n <DropMenu\n className=\"assistant-conv-menu\"\n triggerClassName=\"assistant-conv-more\"\n triggerTitle={say('conversationActions', { title: each.title })}\n triggerLabel={say('conversationActions', { title: each.title })}\n label=\"⋯\"\n popupClassName=\"page-actions-popup\"\n align=\"end\"\n >\n <DropItem className=\"page-actions-item\" onClick={() => setRenaming(each.id)}>\n {say('rename')}\n </DropItem>\n <DropItem className=\"page-actions-item\" onClick={() => setDeleting(each)}>\n {say('delete')}\n </DropItem>\n </DropMenu>\n )}\n </li>\n );\n };\n\n return (\n <div className=\"assistant-convs\">\n <div className=\"assistant-convs-head\">\n <button type=\"button\" className=\"assistant-convs-new\" onClick={onNew}>\n <Plus />\n {say('newConversation')}\n </button>\n <div className=\"assistant-convs-find\">\n <Funnel />\n <input\n type=\"search\"\n className=\"assistant-convs-search\"\n value={words}\n placeholder={say('filterConversations')}\n aria-label={say('filterConversations')}\n onChange={(event) => setWords(event.target.value)}\n onKeyDown={onSearchKey}\n />\n {words && (\n <button\n type=\"button\"\n className=\"assistant-convs-clear\"\n aria-label={say('clearSearch')}\n title={say('clearSearch')}\n onClick={() => setWords('')}\n >\n <svg viewBox=\"0 0 16 16\" width=\"12\" height=\"12\" aria-hidden=\"true\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\">\n <path d=\"M4 4l8 8M12 4l-8 8\" />\n </svg>\n </button>\n )}\n </div>\n </div>\n {conversations.length === 0 && !term ? (\n <p className=\"assistant-empty\">{say('noConversations')}</p>\n ) : shown.length === 0 ? (\n <p className=\"assistant-empty\" role=\"status\">\n {settling ? '' : say('noMatches')}\n </p>\n ) : term ? (\n <ul className=\"assistant-conv-list\" aria-label={say('searchResults')}>\n {shown.map(row)}\n </ul>\n ) : (\n groups.map(({ group, rows }) => (\n <section key={group} className=\"assistant-conv-group\" aria-labelledby={`assistant-conv-${group}`}>\n <h3 id={`assistant-conv-${group}`} className=\"assistant-conv-heading\">\n {headingOf(group)}\n </h3>\n <ul className=\"assistant-conv-list\">{rows.map(row)}</ul>\n </section>\n ))\n )}\n {deleting && (\n <DeleteConversation\n conversation={deleting}\n onClose={() => setDeleting(null)}\n onConfirm={() => {\n const id = deleting.id;\n setDeleting(null);\n void onDelete(id);\n }}\n />\n )}\n </div>\n );\n}\n\n/** The title, edited where it is drawn: Enter keeps it, Escape leaves it as it was. */\nexport function RenameField({ title, onDone }: { title: string; onDone: (title: string | null) => void }) {\n const [value, setValue] = useState(title);\n const field = useRef<HTMLInputElement>(null);\n const done = useRef(false);\n const finish = (next: string | null) => {\n if (done.current) return;\n done.current = true;\n onDone(next === null ? null : next.replace(/\\s+/g, ' ').trim().slice(0, 200));\n };\n useEffect(() => {\n field.current?.focus();\n field.current?.select();\n }, []);\n return (\n <input\n ref={field}\n className=\"assistant-conv-rename\"\n value={value}\n maxLength={200}\n aria-label={say('renameLabel', { title })}\n onChange={(event) => setValue(event.target.value)}\n onBlur={() => finish(value)}\n onKeyDown={(event) => {\n if (event.key === 'Enter') {\n event.preventDefault();\n finish(value);\n } else if (event.key === 'Escape') {\n event.preventDefault();\n event.stopPropagation();\n finish(null);\n }\n }}\n />\n );\n}\n\n/* As a record's delete asks (DeleteButton.tsx): an App keeps no undo, so the person says so first. */\nexport function DeleteConversation({\n conversation,\n onClose,\n onConfirm,\n}: {\n conversation: ConversationSummary;\n onClose: () => void;\n onConfirm: () => void;\n}) {\n const dialog = useRef<ModalHandle>(null);\n return (\n <Modal\n className=\"confirm\"\n ref={dialog}\n onClose={onClose}\n fullscreen={false}\n ariaLabel={say('deleteConversation', { title: conversation.title })}\n >\n <h2>{say('deleteConversation', { title: conversation.title })}</h2>\n <p>{say('deleteConversationTerms')}</p>\n <div className=\"confirm-actions\">\n <Button intent=\"secondary\" onClick={() => dialog.current?.close()}>\n {say('common.cancel')}\n </Button>\n <Button intent=\"danger\" onClick={onConfirm}>\n {say('delete')}\n </Button>\n </div>\n </Modal>\n );\n}\n","/** What AssistantPanel says, in the shell room (packages/kit/src/client/messages.ts says how the catalog is split). */\nimport { defineMessages } from '@mistriwork/kit/client/messages.js';\n\nexport const say = defineMessages({\n assistant: 'Assistant',\n conversations: 'Conversations',\n newConversation: 'New conversation',\n emptyHint: 'Ask about your records: find them, sum them up, show them as a table or a chart. Changes are proposed for you to confirm.',\n about: 'About {label}',\n leaveOutRecord: 'Leave {label} out',\n message: 'Message the assistant',\n send: 'Send',\n stop: 'Stop',\n retry: 'Retry',\n tryAgain: 'Try again',\n edit: 'Edit',\n cancelEdit: 'Cancel edit',\n editing: 'Editing your message.',\n working: 'Working…',\n steps: { one: '{count} step', other: '{count} steps' },\n confirm: 'Confirm',\n review: 'Review and confirm',\n decline: 'Decline',\n reason: 'Reason',\n proposedChange: 'Proposed change',\n applied: 'Applied.',\n declined: 'Declined.',\n failed: 'Not applied: {detail}',\n failedPlain: 'Not applied.',\n waitingForYou: 'Waiting for you to confirm or decline.',\n stopped: 'Stopped.',\n couldNotAnswer: 'The assistant could not answer: {message}',\n connectionLost: 'The connection to the server dropped before the answer finished.',\n couldNotOpen: 'This conversation could not be opened: {message}',\n noModel: 'The assistant is not set up on this server yet.',\n close: 'Close the assistant',\n newRecord: 'New {resource}',\n expand: 'Full screen',\n collapse: 'Back to the side panel',\n starters: 'Try asking',\n editRecord: 'Edit',\n editRecordLabel: 'Edit {label}',\n recordActions: 'What you can do with {label}',\n conversationActions: 'Actions for “{title}”',\n rename: 'Rename',\n delete: 'Delete',\n});\n","/**\n * The in-App assistant (docs/assistant.md): a panel beside the page, not over\n * it — the person keeps reading and clicking the App while it answers — and\n * the whole page on a phone, where there is no beside.\n *\n * What it draws is data. The model's words are plain text with three marks\n * (bold, code, a link), and a link is followed only to an address inside the\n * App; its tables, figures and charts are dashboard sections the server\n * validated, drawn by the dashboard's own components; a record is the\n * record's values in the record form's shape. Nothing the model writes is\n * markup.\n *\n * Nothing it proposes happens here unasked. A proposal is a card; Confirm\n * runs it through the path the record's own button uses — a fixed edit\n * through /api/update, a command through its form, a new record through the\n * New form filled in — under the same checks, and the outcome is told back\n * to the assistant, which carries on.\n *\n * What it shows can be acted on as the App's own screens are: a record's card\n * carries the record's bar (Actions.tsx), and a table's rows the list's row\n * menu — the same verbs, the same grants, the same forms. Those are the\n * person's clicks; the model never makes them. What came of one is told to\n * the conversation (`/api/assistant/acted`), so the model reads it next turn.\n *\n * One component, three places: the panel beside the page, the panel full\n * screen over the content (remembered per person), and the App's assistant\n * room (`placement: 'page'`, `/{app}/assistant`) with the conversations as a\n * rail. Its chunk is loaded when the trigger is first pressed\n * (AssistantTrigger.tsx), or the room is first opened (Content.tsx).\n */\nimport {\n createElement,\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useId,\n useRef,\n useState,\n type KeyboardEvent,\n type ReactNode,\n} from 'react';\nimport { useQuery, useQueryClient } from '@tanstack/react-query';\nimport type { AppAction, AppCommandAction } from '../../shared/app.js';\nimport type { AppPayloadApp } from '../../shared/appPayload.js';\nimport { shown } from '@mistriwork/kit/client/addressMount.js';\nimport { activeApp } from '../appState.js';\nimport {\n api,\n columnLabel,\n currentEntry,\n findTable,\n go,\n humanName,\n labelPath,\n state,\n viewportBox,\n viewportSize,\n writeAllowed,\n} from '@mistriwork/kit/client/core.js';\nimport { grantedActionIds, mayRunAny } from '@mistriwork/kit/client/actionGrants.js';\nimport { sessionIdentity } from '@mistriwork/kit/client/sessionIdentity.js';\nimport { syncHash } from '@mistriwork/kit/client/url.js';\nimport { pageBridge } from '@mistriwork/kit/client/uiBridge.js';\nimport { assistantEntry } from '../publicAddress.js';\nimport type { TableMeta } from '@mistriwork/engine/shared/schema.js';\nimport { ActionBar, ActionOutcomes, type ActionOutcome as ActionOutcomeReport } from './Actions.js';\nimport { ASSISTANT_PAGE, dashViewKey, formViewKey, resourceOf } from '@mistriwork/kit/client/components/appRooms.js';\nimport { startersHere } from '../../shared/appAssistant.js';\nimport { rootMatches } from '@mistriwork/kit/client/components/pageModel.js';\nimport { formProps } from '@mistriwork/kit/client/insert.js';\nimport { ownedBy } from '@mistriwork/kit/client/requestIdentity.js';\nimport { pathEqualityFilter, recordKey as checkedRecordKey } from '@mistriwork/kit/client/resourceRequests.js';\nimport { updateAttempts } from '@mistriwork/kit/client/updateAttempts.js';\nimport type { CommandOperation } from '../commandState.js';\nimport {\n applyEvent,\n cutAt,\n grouped,\n inside,\n stream,\n waitingProposal,\n wordsOf,\n type AssistantBlock,\n type Run,\n type PanelItem,\n type Proposal,\n type ProposalOutcome,\n type StreamEvent,\n} from './assistantStream.js';\nimport { Button } from '@mistriwork/ui/Button.js';\nimport { assistantApi, assistantOwner } from './assistantRequest.js';\nimport { ConversationList, DeleteConversation, RenameField, type ConversationSummary } from './ConversationList.js';\nimport { DropItem, DropMenu } from '@mistriwork/ui/DropMenu.js';\nimport { CommandForm } from './CommandForm.js';\nimport { mount, unmount } from '@mistriwork/kit/client/components/mount.js';\nimport { NewRecordDialog } from '@mistriwork/kit/client/components/NewRecord.js';\nimport { onDemand } from '@mistriwork/kit/client/components/onDemand.js';\nimport { useWalk } from '@mistriwork/kit/client/components/walk.js';\nimport { RefJump, Value } from '@mistriwork/kit/client/components/Value.js';\nimport { referenceProjection } from '@mistriwork/engine/shared/referenceModel.js';\nimport type { DashboardDef } from '@mistriwork/kit/client/components/dashboardModel.js';\nimport { say } from '../copy/shell/components/AssistantPanel.js';\nimport './AssistantPanel.css';\nimport { addHostListener, navFollow, portalRoot, removeHostListener, shellById } from '@mistriwork/kit/client/shellHost.js';\n\nconst Dashboard = onDemand(() => import('./Dashboard.js'), 'Dashboard');\n\ntype Summary = ConversationSummary;\n\n/* Where the person was, kept while the page is: closing the panel and opening it again returns to the same conversation. */\n/* The panel reopens on the conversation it last showed, for the person and in the customer it was shown to. */\nlet lastConversation: { owner: string; id: string | null } = { owner: '', id: null };\n\nconst LIST_QUERY = 'assistant-conversations';\nconst phone = () => typeof window.matchMedia === 'function' && window.matchMedia('(max-width: 640px)').matches;\n\n/** An address inside the App, followed without a reload: the shell's own navigation listener paints it. */\nfunction follow(address: string): void {\n navFollow(shown(address));\n}\n\n/** Follows an inside link in the page; a modified click is the browser's (a new tab). */\nfunction Link({ to, children, onFollow }: { to: string; children: ReactNode; onFollow: (address: string) => void }) {\n return (\n <a\n href={shown(to)}\n onClick={(event) => {\n if (event.metaKey || event.ctrlKey || event.shiftKey || event.button !== 0) return;\n event.preventDefault();\n onFollow(to);\n }}\n >\n {children}\n </a>\n );\n}\n\n/** The model's words, drawn from their runs (assistantStream.ts `wordsOf`). */\nfunction Words({ text, onFollow }: { text: string; onFollow: (address: string) => void }) {\n const draw = (runs: Run[]) =>\n runs.map((run, at) =>\n 'link' in run ? (\n <Link key={at} to={run.link} onFollow={onFollow}>\n {run.text}\n </Link>\n ) : run.mark === 'strong' ? (\n <strong key={at}>{run.text}</strong>\n ) : run.mark === 'code' ? (\n <code key={at}>{run.text}</code>\n ) : (\n run.text\n ),\n );\n return (\n <>\n {wordsOf(text).map((paragraph, p) =>\n paragraph.list ? (\n <ul key={p}>\n {paragraph.lines.map((line, l) => (\n <li key={l}>{draw(line)}</li>\n ))}\n </ul>\n ) : (\n <p key={p}>{paragraph.lines.flatMap((line, l) => (l ? [<br key={`br${l}`} />, ...draw(line)] : draw(line)))}</p>\n ),\n )}\n </>\n );\n}\n\n/** Whether the App's list over a table offers a menu on each row (`rowActions`): a chat table of it offers the same. */\n/* A table drawn here offers its rows' menus where one of the App's views over it does, and only to a reader with a verb to run. */\nfunction rowActionsOn(tableId: unknown): boolean {\n const app = activeApp() as AppPayloadApp | null;\n if (typeof tableId !== 'string') return false;\n return (\n Object.values(app?.views ?? {}).some(\n (view) => (view as { table?: string; rowActions?: true }).table === tableId && (view as { rowActions?: true }).rowActions === true,\n ) && mayRunAny(app, tableId, (resourceOf(app, tableId)?.actions ?? []) as AppAction[])\n );\n}\n\n/** A block the server validated, drawn by the App's own components. */\nfunction Block({ block, onFollow }: { block: AssistantBlock; onFollow: (address: string) => void }) {\n const dashboard = useMemo(() => {\n if (block.kind !== 'section') return null;\n /* A table's rows open their records, and — where the App's list over the table offers it — carry the list's own row menu. */\n const section =\n block.section.kind === 'rows' && rowActionsOn(block.section.table) ? { ...block.section, rowActions: true } : block.section;\n return { id: 'assistant', label: String(section.title ?? ''), sections: [section] } as unknown as DashboardDef;\n }, [block]);\n if (dashboard) {\n return (\n <div className=\"assistant-block assistant-section\">\n <Dashboard dashboard={dashboard} />\n </div>\n );\n }\n if (block.kind !== 'record') return null;\n return <RecordCard block={block} onFollow={onFollow} />;\n}\n\n/**\n * One record, as the peek card draws it, with the record's own bar under it:\n * the verbs its page would offer this person for its state now, each through\n * the page's own path (Actions.tsx), and Edit where they may write it — the\n * record's own form, in its dialog. After a verb the card reads the record\n * again, so it says what the record now is.\n */\n/* A field on a record card: a reference by its record's name (as the glance\n draws it), a long single line cut with an ellipsis and its whole in the\n title (as the grid does), anything else as the record page says it. */\nfunction CardValue({\n column,\n table,\n name,\n value,\n label,\n tableId,\n row,\n}: {\n column: TableMeta['columns'][number] | undefined;\n table: TableMeta | undefined;\n name: string;\n value: unknown;\n label: unknown;\n tableId: string;\n row: Record<string, unknown>;\n}) {\n if (column?.references && table && value !== null && value !== undefined && String(value) !== '')\n return <RefJump references={column.references} value={value} label={label} table={table} column={name} row={row} />;\n return <Value col={column} value={value} tableId={tableId} compact links={false} />;\n}\n\nfunction RecordCard({ block, onFollow }: { block: Extract<AssistantBlock, { kind: 'record' }>; onFollow: (address: string) => void }) {\n const app = activeApp() as AppPayloadApp | null;\n const table = findTable(block.table) as TableMeta | undefined;\n const queryClient = useQueryClient();\n const connection = state.activeConnection ?? undefined;\n const actions = (resourceOf(app, block.table)?.actions ?? []) as AppAction[];\n const editable = Boolean(table) && writeAllowed(block.table);\n const runnable = mayRunAny(app, block.table, actions);\n /* The card reads its record the way a glance does (PeekPanel): the fields\n it shows plus each reference's name, one row by its key. An action or an\n edit invalidates every query, this one with them, so the card re-reads\n to what the record is now. Until the read lands it says what the tool said. */\n const names = Object.keys(block.values);\n const projection = table ? referenceProjection(state.schema, table, names, true, labelPath) : undefined;\n const read = useQuery<Record<string, unknown> | null>({\n queryKey: ['assistant-record', connection ?? '', block.table, JSON.stringify(block.key)],\n enabled: Boolean(table && projection),\n queryFn: async () => {\n const data = (await api('/api/view/run', {\n view: {\n id: `assistant:${block.table}`,\n name: table!.name,\n base: table!.id,\n columns: projection!.fetched.map((path) => ({ path })),\n filter: pathEqualityFilter(block.key),\n limit: 1,\n },\n })) as { rows?: Array<Record<string, unknown>> };\n return data.rows?.[0] ?? null;\n },\n retry: false,\n });\n const row = read.data ?? undefined;\n const values = row\n ? Object.fromEntries(names.map((name) => [name, Object.hasOwn(row, name) ? row[name] : block.values[name]]))\n : block.values;\n const refLabel = (name: string) => {\n const at = projection?.labels.get(name);\n return row && at !== undefined ? row[at] : undefined;\n };\n const reread = () => void queryClient.invalidateQueries();\n // Big ids arrive as strings and stay strings (CLAUDE.md, values that are not numbers).\n const columns = table?.columns ?? [];\n const fields = Object.entries(values)\n .filter(([name]) => !columns.find((column) => column.name === name)?.primaryKey)\n .slice(0, 10);\n return (\n <div className=\"assistant-block assistant-record\">\n <div className=\"assistant-record-title\">\n {block.address && inside(block.address) ? (\n <Link to={block.address} onFollow={onFollow}>\n {block.title}\n </Link>\n ) : (\n block.title\n )}\n </div>\n <dl className=\"peekpanel-fields\">\n {fields.map(([name, value]) => (\n <div className=\"field\" key={name}>\n <dt>{columnLabel(block.table, name) ?? humanName(name)}</dt>\n <dd title={typeof value === 'string' && !columns.find((column) => column.name === name)?.references ? value : undefined}>\n <CardValue\n column={columns.find((column) => column.name === name)}\n table={table}\n name={name}\n value={value}\n label={refLabel(name)}\n tableId={block.table}\n row={values}\n />\n </dd>\n </div>\n ))}\n </dl>\n {table && (editable || runnable) && (\n <div className=\"assistant-record-actions\" role=\"group\" aria-label={say('recordActions', { label: block.title })}>\n {actions.length > 0 && (\n <ActionBar\n tableId={block.table}\n actions={actions}\n recordKey={block.key}\n label={block.title}\n matches={(when) => rootMatches(table, block.key, when, connection)}\n canUpdate={writeAllowed(block.table)}\n grantedCommands={app?.grantedCommands ?? []}\n grantedActions={grantedActionIds(app, block.table)}\n onDone={reread}\n />\n )}\n {editable && pageBridge.openPeek && (\n <Button\n className=\"page-action\"\n aria-label={say('editRecordLabel', { label: block.title })}\n onClick={() => pageBridge.openPeek!(block.table, { ...block.key }, block.title, 'modal')}\n >\n {say('editRecord')}\n </Button>\n )}\n </div>\n )}\n </div>\n );\n}\n\nfunction Steps({ steps, running }: { steps: Extract<PanelItem, { type: 'step' }>[]; running?: string }) {\n return (\n <details className=\"assistant-steps\">\n <summary>{running ?? say('steps', { count: steps.length })}</summary>\n <ol>\n {steps.map((step) => (\n <li key={step.id} className={step.failed ? 'assistant-step-failed' : undefined}>\n {step.label}\n </li>\n ))}\n </ol>\n </details>\n );\n}\n\nconst outcomeWords = (outcome: ProposalOutcome) =>\n outcome.status === 'done'\n ? say('applied')\n : outcome.status === 'declined'\n ? say('declined')\n : outcome.detail\n ? say('failed', { detail: outcome.detail })\n : say('failedPlain');\n\ninterface CardProps {\n proposal: Proposal;\n outcome?: ProposalOutcome;\n live: boolean;\n onResolve: (outcome: ProposalOutcome) => void;\n onFollow: (address: string) => void;\n}\n\n/** A proposed change: what, to which record, and why — and nothing done until Confirm. */\nfunction ProposalCard({ proposal, outcome, live, onResolve, onFollow }: CardProps) {\n const app = activeApp() as AppPayloadApp | null;\n const action = (app?.resources[proposal.resource]?.actions as AppAction[] | undefined)?.find((each) => each.id === proposal.action);\n const reasonColumn =\n action && !action.command && typeof (action as { reason?: unknown }).reason === 'string'\n ? (action as { reason: string }).reason\n : undefined;\n const [reason, setReason] = useState(() =>\n reasonColumn && typeof proposal.values[reasonColumn] === 'string' ? String(proposal.values[reasonColumn]) : '',\n );\n const [busy, setBusy] = useState(false);\n const [commandOpen, setCommandOpen] = useState(false);\n const queryClient = useQueryClient();\n const settled = (result: ProposalOutcome) => {\n setBusy(false);\n if (result.status === 'done') void queryClient.invalidateQueries();\n onResolve(result);\n };\n\n const confirmSet = async () => {\n if (!action || action.command || !proposal.key) return settled({ status: 'failed', detail: say('failedPlain') });\n const values = {\n ...(action as { set: Record<string, string | number | boolean | null> }).set,\n ...(reasonColumn ? { [reasonColumn]: reason.trim() } : {}),\n };\n const owner = { connection: state.activeConnection ?? null, table: proposal.resource, key: { ...proposal.key } };\n setBusy(true);\n try {\n const key = checkedRecordKey(owner.key);\n const result = await updateAttempts.run(owner, values, () =>\n api('/api/update', { ...ownedBy(owner.connection), table: owner.table, key, values }),\n );\n settled(result.kind === 'applied' ? { status: 'done' } : { status: 'failed', detail: result.message });\n } catch (error) {\n settled({ status: 'failed', detail: error instanceof Error ? error.message : undefined });\n }\n };\n\n const confirmNew = () => {\n const table = findTable(proposal.resource);\n if (!table) return settled({ status: 'failed', detail: say('failedPlain') });\n const view = Object.values(app?.views ?? {}).find(\n (each) => (each as { table?: string; form?: unknown }).table === proposal.resource && (each as { form?: unknown }).form,\n ) as { form?: { defaults?: Record<string, unknown> } } | undefined;\n const form = { ...(view?.form ?? {}), defaults: { ...(view?.form?.defaults ?? {}), ...proposal.values } };\n const host = document.createElement('div');\n host.className = 'insert-host';\n portalRoot().append(host);\n let added = false;\n setBusy(true);\n const close = () => {\n unmount(host);\n host.remove();\n // The form closes before it reports what it added; a close with nothing added is the person stepping back.\n queueMicrotask(() => {\n if (!added) setBusy(false);\n });\n };\n mount(\n host,\n createElement(\n NewRecordDialog,\n formProps(\n table,\n form as never,\n host,\n close,\n () => {\n added = true;\n settled({ status: 'done' });\n },\n { app: true },\n ),\n ),\n );\n };\n\n const confirm = () => {\n if (proposal.kind === 'set') void confirmSet();\n else if (proposal.kind === 'command') setCommandOpen(true);\n else confirmNew();\n };\n const command = action?.command ? (action as AppCommandAction) : undefined;\n const values = Object.entries(proposal.values).filter(([name]) => name !== reasonColumn);\n return (\n <section className={`assistant-proposal${outcome ? ` assistant-proposal-${outcome.status}` : ''}`} aria-label={say('proposedChange')}>\n <div className=\"assistant-proposal-head\">\n <span className=\"assistant-proposal-verb\">\n {proposal.kind === 'new'\n ? say('newRecord', { resource: findTable(proposal.resource)?.name ?? proposal.resource })\n : proposal.label}\n </span>\n {proposal.record &&\n (proposal.address && inside(proposal.address) ? (\n <Link to={proposal.address} onFollow={onFollow}>\n {proposal.record}\n </Link>\n ) : (\n <span>{proposal.record}</span>\n ))}\n </div>\n {proposal.why && <p className=\"assistant-proposal-why\">{proposal.why}</p>}\n {values.length > 0 && (\n <dl className=\"assistant-proposal-values\">\n {values.map(([name, value]) => (\n <div key={name}>\n <dt>{columnLabel(proposal.resource, name) ?? humanName(name)}</dt>\n <dd>\n <Value\n col={findTable(proposal.resource)?.columns.find((column) => column.name === name)}\n value={value}\n tableId={proposal.resource}\n compact\n links={false}\n />\n </dd>\n </div>\n ))}\n </dl>\n )}\n {outcome ? (\n <p className=\"assistant-proposal-outcome\">{outcomeWords(outcome)}</p>\n ) : live ? (\n <>\n {reasonColumn && (\n <label className=\"assistant-proposal-reason\">\n <span>{columnLabel(proposal.resource, reasonColumn) ?? say('reason')}</span>\n <textarea rows={2} value={reason} onChange={(event) => setReason(event.target.value)} disabled={busy} />\n </label>\n )}\n <div className=\"assistant-proposal-actions\">\n <Button intent=\"primary\" onClick={confirm} disabled={busy || (reasonColumn !== undefined && !reason.trim())}>\n {proposal.kind === 'set' ? say('confirm') : say('review')}\n </Button>\n <Button onClick={() => settled({ status: 'declined' })} disabled={busy}>\n {say('decline')}\n </Button>\n </div>\n </>\n ) : null}\n {commandOpen && command && proposal.key && (\n <CommandForm\n action={command}\n owner={{\n connection: state.activeConnection ?? '',\n target: command.command.target,\n command: command.command.id,\n commandVersion: command.command.version,\n key: { ...proposal.key },\n }}\n label={proposal.record ?? proposal.label}\n initial={proposal.values}\n onDone={() => {}}\n onClose={(operation?: CommandOperation) => {\n setCommandOpen(false);\n if (operation?.phase === 'success') settled({ status: 'done' });\n else if (operation?.phase === 'error') settled({ status: 'failed', detail: operation.message });\n }}\n />\n )}\n </section>\n );\n}\n\n/* Full screen is a per-person preference, kept on this device: the panel opens the way it was last left. */\nconst expandedKey = (app: string) => `mistri.assistant.expanded.${app}.${sessionIdentity().accountId ?? 'local'}`;\nfunction readExpanded(app: string): boolean {\n try {\n return window.localStorage.getItem(expandedKey(app)) === '1';\n } catch {\n return false;\n }\n}\nfunction writeExpanded(app: string, on: boolean): void {\n try {\n if (on) window.localStorage.setItem(expandedKey(app), '1');\n else window.localStorage.removeItem(expandedKey(app));\n } catch {\n /* Remembered where the browser lets it be; the panel works either way. */\n }\n}\n\n/** Whether the screen is a phone's, kept current as it turns or resizes. */\nfunction usePhone(): boolean {\n const [on, setOn] = useState(phone);\n useEffect(() => {\n if (typeof window.matchMedia !== 'function') return;\n const query = window.matchMedia('(max-width: 640px)');\n const changed = () => setOn(query.matches);\n query.addEventListener?.('change', changed);\n return () => query.removeEventListener?.('change', changed);\n }, []);\n return on;\n}\n\n/* Full screen's mark, drawn here so it rides this chunk and nothing of it is in a first page: corners out, or back in. */\nfunction Corners({ inward }: { inward: boolean }) {\n return (\n <svg className=\"icon\" viewBox=\"0 0 16 16\" width=\"16\" height=\"16\" aria-hidden=\"true\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\">\n <path\n d={inward ? 'M6 2.5V6H2.5M10 2.5V6h3.5M13.5 10H10v3.5M2.5 10H6v3.5' : 'M2.5 6V2.5H6M10 2.5h3.5V6M13.5 10v3.5H10M6 13.5H2.5V10'}\n />\n </svg>\n );\n}\n\n/* The room's Conversations control on a phone: a pane with its list at the side, drawn here so it rides this chunk. */\nfunction ListMark() {\n return (\n <svg className=\"icon\" viewBox=\"0 0 16 16\" width=\"16\" height=\"16\" aria-hidden=\"true\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\">\n <rect x=\"2\" y=\"2.75\" width=\"12\" height=\"10.5\" rx=\"1.5\" />\n <path d=\"M6.25 2.75v10.5\" />\n </svg>\n );\n}\n\n/* The composer grows with what is typed, from one line to about eight, then scrolls. */\nconst COMPOSE_MAX = 192;\n\ninterface AssistantProps {\n app: string;\n /** The App lets the assistant read the open record as the turn's context. */\n record: boolean;\n /** Beside the page (the trigger's), or the App's assistant room. */\n mode: 'panel' | 'page';\n /** The panel's close; the room has none, it is left as any room is. */\n onClose?: () => void;\n /** The room's conversation, from its address; the panel keeps the last one it showed. */\n conversation?: string;\n}\n\n/** The trigger's panel, beside the page or full screen over its content. */\nexport function AssistantPanel({ app, record, onClose }: { app: string; record: boolean; onClose: () => void }) {\n // Another customer, or another person, is another history: the panel starts again in it.\n return <Assistant key={assistantOwner()} app={app} record={record} mode=\"panel\" onClose={onClose} />;\n}\n\n/** The App's assistant room (`placement: 'page'`), on the conversation its address names. */\nexport function AssistantRoom({ conversation }: { conversation?: string }) {\n const app = activeApp() as AppPayloadApp | null;\n if (!app?.assistant?.page) return null;\n return (\n <Assistant key={`${assistantOwner()}\\n${conversation ?? ''}`} app={app.id} record={false} mode=\"page\" conversation={conversation} />\n );\n}\n\nfunction Assistant({ app, record, mode, onClose, conversation: addressed }: AssistantProps) {\n const room = mode === 'page';\n const owner = assistantOwner();\n const [conversation, setConversation] = useState<string | null>(\n room ? (addressed ?? null) : lastConversation.owner === owner ? lastConversation.id : null,\n );\n const [started, setStarted] = useState<string | null>(null);\n const [items, setItems] = useState<PanelItem[]>([]);\n const [listing, setListing] = useState(false);\n const [text, setText] = useState('');\n const [editing, setEditing] = useState<number | null>(null);\n const [busy, setBusy] = useState(false);\n const [running, setRunning] = useState<string | undefined>();\n /* What went wrong, and the way on from it: `again` for a turn cut off on the way, `fresh` for a conversation this\n person may not open (a field report's panel stayed blank over a 403 it never said). */\n const [problem, setProblem] = useState<{ text: string; again?: true; fresh?: true } | null>(null);\n /* The last turn sent, and whether the server had kept the person's words before it was cut off: kept, it is retried\n from them; not, the same request is sent again. */\n const sent = useRef<{ path: '/api/assistant/turn' | '/api/assistant/resolve'; request: Record<string, unknown>; kept: boolean } | null>(\n null,\n );\n const [withRecord, setWithRecord] = useState(true);\n const [renamingTitle, setRenamingTitle] = useState(false);\n const [deletingOpen, setDeletingOpen] = useState(false);\n const [expanded, setExpanded] = useState(() => !room && readExpanded(app));\n const onPhone = usePhone();\n const wide = room || (expanded && !onPhone);\n const stop = useRef<AbortController | null>(null);\n const body = useRef<HTMLDivElement>(null);\n const box = useRef<HTMLTextAreaElement>(null);\n const frame = useRef<HTMLElement>(null);\n const queryClient = useQueryClient();\n const walk = useWalk();\n const top = walk[walk.length - 1];\n const context =\n record && (top?.kind === 'row' || top?.kind === 'page') && top.table && top.key\n ? { resource: top.table, key: top.key, label: top.label ?? top.table }\n : undefined;\n /* The App's starters for where the person is: its bare lines everywhere, a scoped one in its view's room or on a\n record of its table (appAssistant.ts). The room is the walk's top: a list's view, a dashboard's or a form's page. */\n const starters = startersHere((activeApp() as AppPayloadApp | null)?.assistant?.starters, {\n ...(top?.kind === 'table' && top.view ? { view: top.view } : {}),\n ...(top?.kind === 'page' && !top.key ? { view: dashViewKey(top.pageId) ?? formViewKey(top.pageId) } : {}),\n ...((top?.kind === 'row' || top?.kind === 'page') && top.table && top.key ? { record: top.table } : {}),\n });\n\n const conversations = useQuery({\n queryKey: [LIST_QUERY, app, owner],\n queryFn: async () =>\n (await assistantApi(`/api/assistant?app=${encodeURIComponent(app)}`)) as { conversations: Summary[]; ready: boolean },\n });\n const opened = useQuery({\n queryKey: ['assistant-conversation', app, owner, conversation],\n // Not the one this panel's own turn just started: its items are already here.\n enabled: conversation !== null && conversation !== started,\n staleTime: Infinity,\n queryFn: async () =>\n (await assistantApi(`/api/assistant/conversation?app=${encodeURIComponent(app)}&id=${encodeURIComponent(conversation!)}`)) as {\n items: PanelItem[];\n },\n });\n useEffect(() => {\n if (opened.data && Array.isArray(opened.data.items) && !busy) setItems(opened.data.items);\n // Only when a conversation is (re)opened: a live turn's items are the panel's own.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [opened.data]);\n useEffect(() => {\n if (!room) lastConversation = { owner, id: conversation };\n }, [room, conversation]);\n // A conversation that is gone (deleted in another tab, or another account's) starts a new one —\n // unless this panel's own turn has since answered for it. One refused is said, with the way out.\n useEffect(() => {\n if (!opened.isError || conversation === started) return;\n if ((opened.error as { status?: number } | null)?.status !== 404) {\n setProblem({ text: say('couldNotOpen', { message: opened.error.message }), fresh: true });\n return;\n }\n if (room) go(assistantEntry(), 'replace');\n else setConversation(null);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [opened.isError, room]);\n useEffect(() => () => stop.current?.abort(), []);\n useEffect(() => {\n box.current?.focus();\n }, [conversation, listing]);\n // The newest words stay in view while they arrive, unless the person has scrolled up to read.\n const pinned = useRef(true);\n useEffect(() => {\n const view = body.current;\n if (view && pinned.current) view.scrollTop = view.scrollHeight;\n }, [items, running]);\n /* A block's rows, a card's fields and the composer's note arrive after the words do; a reader at the foot stays\n at the foot as they settle, rather than left reading whatever they pushed up. */\n useEffect(() => {\n const view = body.current;\n if (!view || typeof ResizeObserver !== 'function') return;\n const keep = new ResizeObserver(() => {\n if (pinned.current) view.scrollTop = view.scrollHeight;\n });\n keep.observe(view);\n for (const child of view.children) keep.observe(child);\n return () => keep.disconnect();\n }, [items]);\n\n /* The box is as tall as its words, to a limit: measured from its content each time they change. */\n useLayoutEffect(() => {\n const field = box.current;\n if (!field) return;\n field.style.height = '';\n const natural = field.scrollHeight;\n if (!natural) return;\n field.style.height = `${Math.min(natural + field.offsetHeight - field.clientHeight, COMPOSE_MAX)}px`;\n field.style.overflowY = natural > COMPOSE_MAX ? 'auto' : 'hidden';\n }, [text]);\n\n /* Full screen fills the content column — beside the App's menu, never over it — and the page beneath does\n not move: the panel is fixed, and only its own left edge changes. Measured on the zoom-aware ruler. */\n useLayoutEffect(() => {\n const panel = frame.current;\n if (room || !panel) return;\n if (!wide) {\n panel.style.removeProperty('--assistant-left');\n return;\n }\n const place = () => {\n const content = shellById('content');\n panel.style.setProperty('--assistant-left', `${content ? Math.max(0, Math.round(viewportBox(content).left)) : 0}px`);\n };\n place();\n addHostListener(window, 'resize', place);\n return () => removeHostListener(window, 'resize', place);\n }, [room, wide]);\n /* The room stands from where it begins to the foot of the window, so the composer sits at the bottom. */\n useLayoutEffect(() => {\n const panel = frame.current;\n if (!room || !panel) return;\n const fit = () => {\n panel.style.height = `${Math.max(320, Math.floor(viewportSize().height - viewportBox(panel).top))}px`;\n };\n fit();\n addHostListener(window, 'resize', fit);\n return () => removeHostListener(window, 'resize', fit);\n }, [room]);\n\n const toggleExpanded = () => {\n setExpanded((was) => {\n writeExpanded(app, !was);\n return !was;\n });\n };\n\n /* A conversation this room's own turn started: the address says it from now on, without leaving the room. */\n const adopt = (id: string) => {\n setStarted(id);\n setConversation(id);\n if (!room) return;\n const here = currentEntry() as { kind?: string; pageId?: string; tab?: string } | undefined;\n if (here?.kind === 'page' && here.pageId === ASSISTANT_PAGE && here.tab !== id) {\n here.tab = id;\n syncHash();\n }\n };\n\n const run = useCallback(\n async (path: '/api/assistant/turn' | '/api/assistant/resolve', request: Record<string, unknown>) => {\n const controller = new AbortController();\n stop.current = controller;\n const turn = { path, request, kept: false };\n sent.current = turn;\n setBusy(true);\n setProblem(null);\n /* Said at once and kept still: the server reads the App and the catalog before its first event, and a field\n report waited seventy seconds under a bare question. Then each tool says what it is doing as it runs. */\n setRunning(say('working'));\n pinned.current = true;\n try {\n await stream(\n path,\n { app, ...request },\n (event: StreamEvent) => {\n if (event.event === 'conversation' && typeof event.data.id === 'string') adopt(event.data.id);\n if (event.event === 'conversation' && typeof event.data.person === 'number') turn.kept = true;\n if (event.event === 'running') setRunning(typeof event.data.label === 'string' ? event.data.label : say('working'));\n // Between steps the model is at work again; once it writes, its words are the sign.\n if (event.event === 'step') setRunning(say('working'));\n if (event.event === 'text' || event.event === 'done') setRunning(undefined);\n if (event.event === 'error' && typeof event.data.message === 'string')\n setProblem({ text: say('couldNotAnswer', { message: event.data.message }) });\n setItems((now) => applyEvent(now, event));\n },\n controller.signal,\n );\n } catch (error) {\n if (!controller.signal.aborted)\n setProblem(\n (error as { lost?: boolean } | null)?.lost\n ? { text: say('connectionLost'), again: true }\n : { text: say('couldNotAnswer', { message: error instanceof Error ? error.message : String(error) }) },\n );\n } finally {\n if (controller.signal.aborted)\n setItems((now) => [...applyEvent(now, { event: 'done', data: {} }), { type: 'note', text: say('stopped') }]);\n stop.current = null;\n setBusy(false);\n setRunning(undefined);\n void queryClient.invalidateQueries({ queryKey: [LIST_QUERY, app] });\n }\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [app, queryClient, room],\n );\n\n const say_ = (said: string) => {\n if (!said || busy) return;\n let next = items;\n const request: Record<string, unknown> = { text: said, ...(conversation ? { conversation } : {}) };\n if (editing !== null) {\n const at = items.findIndex((item) => item.type === 'person' && item.seq === editing);\n if (at >= 0) next = cutAt(items, at);\n request.edit = editing;\n }\n if (context && withRecord) request.context = { resource: context.resource, key: context.key };\n setItems([...next, { type: 'person', text: said }]);\n setText('');\n setEditing(null);\n void run('/api/assistant/turn', request);\n };\n const send = () => say_(text.trim());\n const retry = () => {\n const at = items.map((item) => item.type).lastIndexOf('person');\n if (at < 0 || !conversation) return;\n setItems([...cutAt(items, at), items[at]]);\n void run('/api/assistant/turn', { conversation, text: (items[at] as { text: string }).text, retry: true });\n };\n /* A turn cut off on the way, tried again: from the person's words if the server kept them, else sent as it was. */\n const again = () => {\n const turn = sent.current;\n if (!turn || busy) return;\n if (turn.path === '/api/assistant/turn' && turn.kept && conversation) return retry();\n void run(turn.path, turn.request);\n };\n const resolve = (proposal: Proposal, outcome: ProposalOutcome) => {\n if (!conversation) return;\n setItems((now) => now.map((item) => (item.type === 'proposal' && item.id === proposal.id ? { ...item, outcome } : item)));\n void run('/api/assistant/resolve', {\n conversation,\n proposal: proposal.id,\n outcome: outcome.status,\n ...(outcome.detail ? { detail: outcome.detail } : {}),\n });\n };\n /* A verb the person ran from a card or a row here: told to the conversation, drawn as its note. */\n const live = useRef(conversation);\n live.current = conversation;\n const acted = useCallback(\n (report: { tableId: string; key: Record<string, unknown>; label: string; action: AppAction; outcome: ActionOutcomeReport }) => {\n const id = live.current;\n if (!id) return;\n void (async () => {\n try {\n const answer = (await assistantApi('/api/assistant/acted', {\n app,\n conversation: id,\n resource: report.tableId,\n action: report.action.id,\n key: report.key,\n record: report.label,\n outcome: report.outcome.status,\n ...(report.outcome.detail ? { detail: report.outcome.detail } : {}),\n })) as { item?: PanelItem };\n if (answer.item && live.current === id) {\n pinned.current = true;\n setItems((now) => [...now, answer.item!]);\n }\n } catch {\n /* The verb ran or did not on its own; only the conversation's note of it is missing. */\n }\n })();\n },\n [app],\n );\n const open = (id: string) => {\n stop.current?.abort();\n setListing(false);\n if (room) {\n go(assistantEntry(id), 'push');\n return;\n }\n setStarted(null);\n setConversation(id);\n void queryClient.invalidateQueries({ queryKey: ['assistant-conversation', app, owner, id] });\n };\n const startNew = () => {\n stop.current?.abort();\n setListing(false);\n if (room) {\n if (conversation) go(assistantEntry(), 'push');\n return;\n }\n setConversation(null);\n setItems([]);\n setEditing(null);\n setProblem(null);\n };\n const remove = async (id: string) => {\n await assistantApi('/api/assistant/delete', { app, conversation: id });\n if (id === conversation) {\n if (room) go(assistantEntry(), 'replace');\n else startNew();\n }\n void queryClient.invalidateQueries({ queryKey: [LIST_QUERY, app] });\n void queryClient.invalidateQueries({ queryKey: ['assistant-search', app] });\n };\n const rename = async (id: string, title: string) => {\n // Drawn at once; the list read again says what the server kept.\n queryClient.setQueryData([LIST_QUERY, app, owner], (was: { conversations: Summary[]; ready: boolean } | undefined) =>\n was ? { ...was, conversations: was.conversations.map((each) => (each.id === id ? { ...each, title } : each)) } : was,\n );\n try {\n await assistantApi('/api/assistant/rename', { app, conversation: id, title });\n } finally {\n void queryClient.invalidateQueries({ queryKey: [LIST_QUERY, app] });\n void queryClient.invalidateQueries({ queryKey: ['assistant-search', app] });\n }\n };\n const onFollow = (address: string) => {\n follow(address);\n if (!room && (onPhone || wide)) onClose?.();\n };\n const onKey = (event: KeyboardEvent<HTMLTextAreaElement>) => {\n if (event.key === 'Enter' && !event.shiftKey && !event.nativeEvent.isComposing) {\n event.preventDefault();\n send();\n } else if (event.key === 'ArrowUp' && !text) {\n // Up in an empty box takes the last thing said back to edit, as a chat does.\n const last = [...items].reverse().find((item): item is Extract<PanelItem, { type: 'person' }> => item.type === 'person');\n if (last?.seq !== undefined && !busy && !waitingProposal(items)) {\n event.preventDefault();\n setEditing(last.seq);\n setText(last.text);\n }\n }\n };\n const onPanelKey = (event: KeyboardEvent<HTMLElement>) => {\n if (event.key !== 'Escape' || event.defaultPrevented) return;\n if (busy) {\n event.preventDefault();\n stop.current?.abort();\n } else if (editing !== null) {\n event.preventDefault();\n setEditing(null);\n setText('');\n } else if (listing) {\n event.preventDefault();\n setListing(false);\n } else if (!room && wide) {\n // Full screen steps back to the side panel first, the focus where it was.\n event.preventDefault();\n toggleExpanded();\n } else if (!room) {\n event.preventDefault();\n onClose?.();\n }\n };\n\n const waiting = waitingProposal(items);\n const waitingNote = useId();\n const lastPerson = items.map((item) => item.type).lastIndexOf('person');\n const ready = conversations.data?.ready !== false;\n const drawn = grouped(items);\n const list = (\n <ConversationList\n app={app}\n conversations={conversations.data?.conversations ?? []}\n current={conversation}\n working={busy ? conversation : null}\n onOpen={open}\n onNew={startNew}\n onRename={rename}\n onDelete={remove}\n />\n );\n const Frame = room ? 'section' : 'aside';\n const Title = room ? 'h1' : 'h2';\n /* The room is headed by the conversation it shows, once it has one; a new one is the Assistant. */\n const titled = room && conversation ? conversations.data?.conversations.find((each) => each.id === conversation) : undefined;\n const heading = titled?.title || say('assistant');\n const starting = ready && items.length === 0 && !(conversation && opened.isPending);\n const canSend = Boolean(text.trim()) && ready && !waiting;\n return (\n <Frame\n ref={frame as never}\n id={room ? 'assistant-room' : 'assistant-panel'}\n className={`${room ? 'assistant-room' : 'assistant-panel'}${wide ? ' assistant-wide' : ''}${!room && wide ? ' assistant-panel-expanded' : ''}${room && listing ? ' assistant-room-listing' : ''}${(starting || !ready) && !(listing && !room) ? ' assistant-starting' : ''}`}\n {...(room ? {} : { role: 'complementary' })}\n aria-label={say('assistant')}\n onKeyDown={onPanelKey}\n >\n {room && (\n <nav className=\"assistant-rail\" aria-label={say('conversations')}>\n {list}\n </nav>\n )}\n {/* On a phone the rail is a sheet over the conversation, which stays in sight; a press beside it closes it. */}\n {room && listing && <div className=\"assistant-rail-scrim\" aria-hidden=\"true\" onClick={() => setListing(false)} />}\n <div className=\"assistant-main\">\n <div className=\"assistant-head\">\n {/* The room's conversations on a phone, where the rail is a sheet: the head's first control, as a drawer's is. */}\n {room && (\n <button\n type=\"button\"\n className=\"btn ghost btn-compact assistant-rail-toggle\"\n aria-pressed={listing}\n title={say('conversations')}\n onClick={() => setListing((was) => !was)}\n >\n <ListMark />\n <span className=\"visually-hidden\">{say('conversations')}</span>\n </button>\n )}\n {room && titled && renamingTitle ? (\n <RenameField\n title={titled.title}\n onDone={(title) => {\n setRenamingTitle(false);\n if (title && title !== titled.title) void rename(titled.id, title);\n }}\n />\n ) : (\n <Title className=\"assistant-title\">\n <span className=\"assistant-title-words\" title={titled ? heading : undefined}>\n {heading}\n </span>\n </Title>\n )}\n {room && titled && !renamingTitle && (\n <DropMenu\n className=\"assistant-title-menu\"\n triggerClassName=\"assistant-conv-more\"\n triggerTitle={say('conversationActions', { title: titled.title })}\n triggerLabel={say('conversationActions', { title: titled.title })}\n label=\"⋯\"\n popupClassName=\"page-actions-popup\"\n align=\"start\"\n >\n <DropItem className=\"page-actions-item\" onClick={() => setRenamingTitle(true)}>\n {say('rename')}\n </DropItem>\n <DropItem className=\"page-actions-item\" onClick={() => setDeletingOpen(true)}>\n {say('delete')}\n </DropItem>\n </DropMenu>\n )}\n {!room && (\n <button type=\"button\" className=\"icon-button\" aria-pressed={listing} onClick={() => setListing((was) => !was)}>\n {say('conversations')}\n </button>\n )}\n {!room && !listing && (\n <button type=\"button\" className=\"icon-button\" onClick={startNew}>\n {say('newConversation')}\n </button>\n )}\n {!room && (\n <button\n type=\"button\"\n className=\"icon-button assistant-expand\"\n aria-pressed={expanded}\n aria-label={say('expand')}\n title={expanded ? say('collapse') : say('expand')}\n onClick={toggleExpanded}\n >\n <Corners inward={expanded} />\n </button>\n )}\n {!room && (\n <button type=\"button\" className=\"peekpanel-close\" aria-label={say('close')} title={say('close')} onClick={onClose}>\n ×\n </button>\n )}\n </div>\n {listing && !room ? (\n <div className=\"assistant-body\">{list}</div>\n ) : (\n <ActionOutcomes.Provider value={acted}>\n <div\n className=\"assistant-body\"\n ref={body}\n aria-live=\"polite\"\n aria-busy={busy}\n onScroll={(event) => {\n const view = event.currentTarget;\n pinned.current = view.scrollHeight - view.scrollTop - view.clientHeight < 24;\n }}\n >\n {!ready && <p className=\"assistant-empty\">{say('noModel')}</p>}\n {starting && (\n <div className=\"assistant-start\">\n <p className=\"assistant-empty\">{say('emptyHint')}</p>\n {starters.length > 0 && (\n <div className=\"assistant-starters\" role=\"group\" aria-label={say('starters')}>\n {starters.map((starter) => (\n <button key={starter} type=\"button\" className=\"assistant-starter\" disabled={busy} onClick={() => say_(starter)}>\n {starter}\n </button>\n ))}\n </div>\n )}\n </div>\n )}\n {drawn.map((entry, index) => {\n if (entry.type === 'steps')\n return (\n <Steps key={`s${entry.at}`} steps={entry.steps} running={busy && index === drawn.length - 1 ? running : undefined} />\n );\n const { item, at } = entry;\n if (item.type === 'person')\n return (\n <div\n key={`p${at}`}\n className={`assistant-person${editing !== null && item.seq === editing ? ' assistant-person-editing' : ''}`}\n >\n <p>{item.text}</p>\n {!busy && !waiting && (\n <div className=\"assistant-person-tools\">\n {item.seq !== undefined && (\n <button\n type=\"button\"\n onClick={() => {\n setEditing(item.seq!);\n setText(item.text);\n box.current?.focus();\n }}\n >\n {say('edit')}\n </button>\n )}\n {at === lastPerson && conversation && (\n <button type=\"button\" onClick={retry}>\n {say('retry')}\n </button>\n )}\n </div>\n )}\n </div>\n );\n if (item.type === 'text')\n return (\n <div key={`t${at}`} className=\"assistant-text\">\n <Words text={item.text} onFollow={onFollow} />\n </div>\n );\n if (item.type === 'note')\n return (\n <p key={`n${at}`} className=\"assistant-note\">\n {item.text}\n </p>\n );\n if (item.type === 'block') return <Block key={`b${at}`} block={item.block} onFollow={onFollow} />;\n if (item.type === 'proposal')\n return (\n <ProposalCard\n key={`c${item.id}`}\n proposal={item.proposal}\n outcome={item.outcome}\n live={!busy && waiting?.id === item.id}\n onResolve={(outcome) => resolve(item.proposal, outcome)}\n onFollow={onFollow}\n />\n );\n return null;\n })}\n {busy && (drawn.length === 0 || drawn[drawn.length - 1].type !== 'steps') && running && (\n <p className=\"assistant-working\">{running}</p>\n )}\n {problem && (\n <div className=\"assistant-problem\" role=\"alert\">\n <p>{problem.text}</p>\n {problem.again && !busy && (\n <button type=\"button\" onClick={again}>\n {say('tryAgain')}\n </button>\n )}\n {problem.fresh && (\n <button type=\"button\" onClick={startNew}>\n {say('newConversation')}\n </button>\n )}\n </div>\n )}\n </div>\n </ActionOutcomes.Provider>\n )}\n <div className=\"assistant-foot\">\n {context && withRecord && !listing && (\n <div className=\"assistant-context\">\n <span>{say('about', { label: context.label })}</span>\n <button\n type=\"button\"\n className=\"ghost\"\n aria-label={say('leaveOutRecord', { label: context.label })}\n title={say('leaveOutRecord', { label: context.label })}\n onClick={() => setWithRecord(false)}\n >\n ×\n </button>\n </div>\n )}\n {editing !== null && (\n <div className=\"assistant-context\">\n <span>{say('editing')}</span>\n <button\n type=\"button\"\n className=\"ghost\"\n onClick={() => {\n setEditing(null);\n setText('');\n }}\n >\n {say('cancelEdit')}\n </button>\n </div>\n )}\n {/* A change waiting for the person is said in the field itself, and the field says it is why it is shut. */}\n <div className=\"assistant-compose\">\n {waiting && !busy && (\n <p className=\"assistant-waiting\" id={waitingNote}>\n <span className=\"assistant-waiting-dot\" aria-hidden=\"true\" />\n {say('waitingForYou')}\n </p>\n )}\n <div className=\"assistant-compose-row\">\n <textarea\n ref={box}\n rows={1}\n value={text}\n aria-label={say('message')}\n aria-describedby={waiting && !busy ? waitingNote : undefined}\n placeholder={say('message')}\n disabled={!ready || Boolean(waiting && !busy)}\n onChange={(event) => setText(event.target.value)}\n onKeyDown={onKey}\n />\n {busy ? (\n <Button onClick={() => stop.current?.abort()}>{say('stop')}</Button>\n ) : (\n <Button intent={canSend ? 'primary' : 'secondary'} onClick={send} disabled={!canSend}>\n {say('send')}\n </Button>\n )}\n </div>\n </div>\n </div>\n </div>\n {deletingOpen && titled && (\n <DeleteConversation\n conversation={titled}\n onClose={() => setDeletingOpen(false)}\n onConfirm={() => {\n setDeletingOpen(false);\n void remove(titled.id);\n }}\n />\n )}\n </Frame>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"shared-BDDUzH-f.js","names":["say","recordKey","checkedRecordKey","say","_Fragment","names","say","say","_Fragment","_Fragment","checkedRecordKey","CommandForm"],"sources":["../../../kit/src/client/components/recordKeys.ts","../../src/client/components/actionOrder.ts","../../../kit/src/client/copy/record/components/Actions.ts","../../src/client/components/Actions.tsx","../../src/shared/appAssistant.ts","../../src/client/components/assistantRequest.ts","../../src/client/components/assistantStream.ts","../../src/client/copy/shell/components/ConversationList.ts","../../src/client/components/ConversationList.tsx","../../src/client/copy/shell/components/AssistantPanel.ts","../../src/client/components/AssistantPanel.tsx"],"sourcesContent":["/**\n * A split view's single keys (`shortcuts: { e: 'escalate' }`): the picked record's\n * header reads them from here, so the verb that a key runs shows it as a hint\n * and the key runs the verb through the same bar a click does.\n */\nimport { createContext } from 'react';\n\n/** Key → action id. */\nexport const RecordKeys = createContext<Readonly<Record<string, string>>>({});\n","/**\n * Which of a record's verbs is the one filled button, and the order of the\n * rest (docs/design.md, the record head): the verb the record most needs\n * next first and filled — the header's `primary` where it names one that is\n * shown now, else the first that takes nothing away — the others after it\n * in the author's order, and the destructive ones last and quiet. A record\n * whose only verbs are destructive has no filled button: the one it would\n * fill would end it.\n */\nimport type { AppAction } from '../../shared/appModel.js';\n\ntype ActionIntent = 'primary' | 'secondary' | 'quiet';\n\n/** The verbs in the order they are drawn, each with how it is drawn. */\nexport function orderActions<A extends Pick<AppAction, 'id'>>(\n actions: readonly A[],\n destructive?: (action: A) => boolean,\n primary?: string,\n): Array<{ action: A; intent: ActionIntent }> {\n const ends = (action: A) => Boolean(destructive?.(action));\n const lead =\n actions.find((action) => !ends(action) && primary !== undefined && action.id === primary) ?? actions.find((action) => !ends(action));\n const rest = actions.filter((action) => action !== lead);\n return [\n ...(lead ? [{ action: lead, intent: 'primary' as const }] : []),\n ...rest.filter((action) => !ends(action)).map((action) => ({ action, intent: 'secondary' as const })),\n ...rest.filter(ends).map((action) => ({ action, intent: 'quiet' as const })),\n ];\n}\n","/** What Actions says, in the record page room (packages/kit/src/client/messages.ts says how the catalog is split). */\nimport { defineMessages } from '../../../messages.js';\n\nexport const say = defineMessages({\n thisActionBelongsToAPrevious: 'This action belongs to a previous record surface.',\n actionDone: '{label} — done',\n wasAppliedButTheRecord: '{label} was applied, but the record could not be refreshed.',\n nothingToDoForThisRecord: 'Nothing to do for this record now',\n moreActionsForThisRecord: 'More actions for this record',\n moreActions: 'More actions',\n sayWhyFor: 'Say why, for \"{label}\". ',\n sayWhy: 'Say why. ',\n theReasonIsKept: 'The reason is kept with the record.',\n reason: 'Reason',\n labelReason: '{label}: reason',\n});\n","/**\n * The app's own verbs for a record.\n *\n * Fixed edits use /api/update. Authored commands open their own form and\n * never enter the generic update or Undo path.\n * A verb with a `when` is shown only while the record satisfies it, which\n * is a question for the server; until it answers, the button is not\n * there, because a button that appears and then vanishes is worse than\n * one that arrives late.\n */\nimport { ownedBy } from '@mistriwork/kit/client/requestIdentity.js';\nimport { createContext, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore, useId } from 'react';\nimport { Modal } from '@mistriwork/ui/Modal.js';\nimport { RecordKeys } from '@mistriwork/kit/client/components/recordKeys.js';\nimport { takesSingleKeys } from '@mistriwork/kit/client/components/RecordTrailNav.js';\nimport { Button } from '@mistriwork/ui/Button.js';\nimport { useMutation, useQueryClient, useQueries } from '@tanstack/react-query';\nimport { refreshAfterCommand } from '@mistriwork/kit/client/recordWriteRefresh.js';\nimport { DropItem, DropMenu } from '@mistriwork/ui/DropMenu.js';\nimport { api, columnLabel, findTable, humanName, state, toast } from '@mistriwork/kit/client/core.js';\nimport { recordKey as checkedRecordKey } from '@mistriwork/kit/client/resourceRequests.js';\nimport { updateAttempts, updateOwnerKey, type UpdateOwner } from '@mistriwork/kit/client/updateAttempts.js';\nimport type { AppAction, AppCommandAction, AppUpdateAction } from '../../shared/app.js';\nimport type { TableMeta } from '@mistriwork/engine/shared/schema.js';\nimport { Value } from '@mistriwork/kit/client/components/Value.js';\nimport { onDemand } from '@mistriwork/kit/client/components/onDemand.js';\nimport { commandOperations, type CommandOperation, type CommandOwner } from '../commandState.js';\nimport { readyCommand, sendCommand } from '../commandSend.js';\nimport { commandFieldsDeep } from '../../shared/command.js';\nimport { sessionIdentity, subscribeSessionIdentity } from '@mistriwork/kit/client/sessionIdentity.js';\nimport { useCommandAnswers } from '../commandAvailability.js';\nimport type { ActionBarProps, RecordActions } from '@mistriwork/kit/client/components/pageContext.js';\nimport { orderActions } from './actionOrder.js';\nimport { say } from '@mistriwork/kit/client/copy/record/components/Actions.js';\nimport { addHostListener, removeHostListener } from '@mistriwork/kit/client/shellHost.js';\n\n/* A command's form is a dialog opened by a click: its chunk is fetched then, not with the first page. */\nconst CommandForm = onDemand(() => import('./CommandForm.js'), 'CommandForm', { quiet: true });\n\nexport type { ActionBarProps } from '@mistriwork/kit/client/components/pageContext.js';\n\n/** What became of a verb the person ran: applied, or refused with the server's sentence. */\nexport type ActionOutcome = { status: 'done' | 'failed'; detail?: string };\n/**\n * Who else is told when a verb drawn below this point has run, besides the\n * toast: the assistant's conversation, whose cards and tables draw the\n * record's own bar (AssistantPanel.tsx). The person's click, reported after\n * the fact; nothing here runs a verb.\n */\nexport const ActionOutcomes = createContext<\n ((report: { tableId: string; key: Record<string, unknown>; label: string; action: AppAction; outcome: ActionOutcome }) => void) | null\n>(null);\n\n/** How many verbs stay buttons on a wide screen before the rest fold into More. */\nconst INLINE = 3;\n\nconst said = (v: unknown, empty: string) => (v === null ? empty : String(v));\n/** One key per condition on one record, shared by a button and the bar that decides whether to fold. */\nconst whenKey = (tableId: string, recordKey: Record<string, unknown>, when: string | undefined, queryScope?: number) => [\n 'when',\n tableId,\n state.activeConnection,\n sessionIdentity().epoch,\n recordKey,\n when,\n ...(queryScope === undefined ? [] : [queryScope]),\n];\nconst isCommand = (action: AppAction): action is AppCommandAction => action.command !== undefined;\n\n/**\n * The values the record's own fixed edits can give `column` now: an edit\n * whose `set` is exactly that column, once its `when` holds — the board's\n * rule for a lane. It asks the bar's own questions under the bar's keys, so\n * nothing is asked twice. A command says nothing here: where it moves a\n * record is its code's to decide, not something the App declares.\n */\nexport function useReachable(\n tableId: string,\n recordKey: Record<string, unknown>,\n column: string | undefined,\n actions: RecordActions | undefined,\n): ReadonlySet<string> {\n const moves =\n column && actions\n ? actions.list.filter(\n (action): action is AppUpdateAction =>\n !isCommand(action) &&\n Object.keys(action.set).length === 1 &&\n column in action.set &&\n (actions.canUpdate !== false || Boolean(actions.grantedActions?.includes(action.id))),\n )\n : [];\n const asked = [...new Set(moves.flatMap((action) => (action.when ? [action.when] : [])))];\n const answers = useQueries({\n queries: asked.map((when) => ({\n queryKey: whenKey(tableId, recordKey, when, actions?.queryScope),\n queryFn: () => actions!.matches(when),\n })),\n });\n const answered = new Map(asked.map((when, i) => [when, answers[i]?.data]));\n return new Set(moves.filter((action) => !action.when || answered.get(action.when) === true).map((action) => String(action.set[column!])));\n}\n\nexport function ActionBar({\n tableId,\n actions,\n recordKey,\n label,\n matches,\n queryScope,\n onDone,\n canUpdate = true,\n grantedCommands = [],\n grantedActions = [],\n isCurrent: hostIsCurrent,\n compact = false,\n menuTail,\n menuOnly,\n destructive,\n primary,\n only,\n quiet = false,\n}: ActionBarProps) {\n type Submission = {\n action: AppUpdateAction;\n owner: UpdateOwner;\n values: AppUpdateAction['set'];\n current: () => boolean;\n done: () => void;\n };\n const [asking, setAsking] = useState<Submission | null>(null);\n const [reasoning, setReasoning] = useState<Submission | null>(null);\n const [sending, setSending] = useState(false);\n const [commandForm, setCommandForm] = useState<{ action: AppCommandAction; owner: CommandOwner; epoch: number } | null>(null);\n const identity = useSyncExternalStore(subscribeSessionIdentity, sessionIdentity, sessionIdentity);\n useSyncExternalStore(commandOperations.subscribe, commandOperations.version, commandOperations.version);\n useSyncExternalStore(updateAttempts.subscribe, updateAttempts.version, updateAttempts.version);\n const owner: UpdateOwner = { connection: state.activeConnection ?? null, table: tableId, key: recordKey };\n const currentOwner = useRef(owner);\n currentOwner.current = owner;\n const ownerText = updateOwnerKey(owner);\n const lifetime = useMemo(() => ({ identity, hostIsCurrent }), [identity, hostIsCurrent, ownerText, queryScope]);\n const activeLifetime = useRef(lifetime);\n activeLifetime.current = lifetime;\n const mounted = useRef(true);\n useEffect(() => {\n mounted.current = true;\n return () => {\n mounted.current = false;\n };\n }, []);\n const isCurrent = (submitted: UpdateOwner) => {\n try {\n return (\n mounted.current &&\n activeLifetime.current === lifetime &&\n identity === sessionIdentity() &&\n identity.mode !== 'locked' &&\n identity.mode !== 'unknown' &&\n submitted.connection === (state.activeConnection ?? null) &&\n updateOwnerKey(submitted) === updateOwnerKey(currentOwner.current) &&\n (hostIsCurrent === undefined || hostIsCurrent() === true)\n );\n } catch {\n return false;\n }\n };\n const client = useQueryClient();\n const tell = useContext(ActionOutcomes);\n const told = (action: AppAction, key: Record<string, unknown>, outcome: ActionOutcome) =>\n tell?.({ tableId, key: { ...key }, label, action, outcome });\n const write = useMutation({\n retry: false,\n mutationFn: async ({ action, owner: submitted, values, current, done }: Submission) => {\n if (!current()) return undefined;\n const key = checkedRecordKey(submitted.key);\n const outcome = await updateAttempts.run(submitted, values, () => {\n if (!current()) throw Object.assign(new Error(say('thisActionBelongsToAPrevious')), { outcome: 'not_applied' });\n return api('/api/update', { ...ownedBy(submitted.connection), table: submitted.table, key, values });\n });\n return { action, submitted, outcome, current, done };\n },\n onSuccess: (result) => {\n if (!result || !result.current()) return;\n const { action, outcome, done } = result;\n if (outcome.kind !== 'applied') {\n if (outcome.kind !== 'uncertain') {\n toast(outcome.message, 'error');\n told(action, result.submitted.key, { status: 'failed', detail: outcome.message });\n }\n return;\n }\n told(action, result.submitted.key, { status: 'done' });\n toast(say('actionDone', { label: action.label }), 'ok');\n void client.invalidateQueries({ queryKey: ['when', tableId] });\n try {\n if (result.current()) done();\n } catch {\n toast(say('wasAppliedButTheRecord', { label: action.label }), 'error');\n }\n },\n onError: (err: Error, submitted) => {\n if (!submitted.current()) return;\n toast(err.message, 'error');\n told(submitted.action, submitted.owner.key, { status: 'failed', detail: err.message });\n },\n });\n\n const commandOwner = (action: AppCommandAction): CommandOwner => ({\n connection: state.activeConnection ?? '',\n target: action.command.target,\n command: action.command.id,\n commandVersion: action.command.version,\n key: { ...recordKey },\n });\n const allowedCommand = (action: AppCommandAction) =>\n identity.mode === 'authenticated' &&\n identity.appId === state.activeConnection &&\n grantedCommands.includes(action.command.id) &&\n action.command.target === tableId &&\n Boolean(findTable(tableId)) &&\n // Every type the form draws; a reference, at any depth, only over a resource this person reads.\n [...commandFieldsDeep(action.command.input)].every(({ field }) => field.type !== 'reference' || Boolean(findTable(field.from)));\n /* A fixed action is offered where the reader writes the table, or where a\n role of theirs runs this one without write (the server judges it again). */\n const allowedUpdate = (action: AppUpdateAction) => canUpdate || grantedActions.includes(action.id);\n const visible = actions.filter((action) => (isCommand(action) ? allowedCommand(action) : allowedUpdate(action)));\n /* `header: false` is an action the App runs from its own place: not drawn here, nor asked about, and still\n resumed below when its form was left open, since it is still the record's. */\n const drawable = visible.filter((action) => action.header !== false);\n const checkedCommands = drawable.filter(isCommand);\n const { available: availability, asking: askingCommands } = useCommandAnswers(\n checkedCommands.map((action) => ({ command: action.command.id, commandVersion: action.command.version, key: recordKey })),\n isCurrent(owner),\n lifetime,\n );\n // By id, not identity: a verb said in its state's words (below) is a copy of the one asked about.\n const availableCommand = (action: AppCommandAction) =>\n availability[checkedCommands.findIndex((checked) => checked.id === action.id)] === true;\n // Navigation can unmount a page; reopening the same record resumes its exact operation. One a component sent through\n // `run` is its caller's to resolve, and opens its own form if its answer never arrives.\n const resumable = (action: AppCommandAction) => {\n const operation = commandOperations.get(commandOwner(action));\n return Boolean(operation && !operation.headless);\n };\n const resumed = visible.find((action): action is AppCommandAction => isCommand(action) && resumable(action));\n const form =\n commandForm?.epoch === identity.epoch &&\n commandForm.owner.connection === state.activeConnection &&\n updateOwnerKey({ connection: commandForm.owner.connection, table: commandForm.owner.target, key: commandForm.owner.key }) ===\n updateOwnerKey(owner)\n ? commandForm\n : resumed\n ? { action: resumed, owner: commandOwner(resumed), epoch: identity.epoch }\n : null;\n const operation = form && commandOperations.get(form.owner);\n /* What a command on this record changed, asked again once its receipt lands (recordWriteRefresh.ts, G173). */\n const refreshCommanded = () =>\n refreshAfterCommand(client, {\n connection: owner.connection ?? '',\n table: tableId,\n key: recordKey,\n ...(queryScope === undefined ? {} : { queryScope }),\n });\n /* A command that asks nothing runs on one click, as a fixed verb does, and a notice says it ran: a\n dialog with only a submit in it asked a question nobody had. `confirm` asks first, in its form. An answer that\n never arrived opens the form, which says so and offers to check, as after its own submit. */\n const runAtOnce = async (action: AppCommandAction) => {\n const submitted = commandOwner(action);\n const surface = { ...owner, key: { ...owner.key } };\n setSending(true);\n const sent = await sendCommand(\n action,\n submitted,\n {},\n {\n headless: true,\n current: () => isCurrent(surface),\n refresh: () => {\n if (isCurrent(surface)) refreshCommanded();\n },\n },\n );\n if (mounted.current) setSending(false);\n if ('refused' in sent) {\n toast(sent.refused, 'error');\n told(action, submitted.key, { status: 'failed', detail: sent.refused });\n return;\n }\n const { operation } = sent;\n if (operation.phase === 'success' || operation.phase === 'error') {\n commandOperations.forget(submitted);\n if (operation.phase === 'error') {\n toast(operation.message, 'error');\n told(action, submitted.key, { status: 'failed', detail: operation.message });\n return;\n }\n // The command's own words when it said any (\"Order #2461 is packed at SEC\"), as its form would have said them.\n toast(operation.said ?? say('actionDone', { label: action.label }), 'ok');\n told(action, submitted.key, { status: 'done' });\n if (isCurrent(surface)) onDone();\n return;\n }\n if (isCurrent(surface)) setCommandForm({ action, owner: submitted, epoch: identity.epoch });\n };\n /* A command that runs on one click has its revision asked as the pointer or focus comes to its button, so the click\n sends only the execute (commandSend.ts readyCommand). */\n const atOnce = (action: AppAction): action is AppCommandAction =>\n isCommand(action) &&\n !action.command.input.length &&\n !action.confirm &&\n allowedCommand(action) &&\n availableCommand(action) &&\n !commandOperations.get(commandOwner(action));\n const ready = (action: AppAction) => {\n if (isCurrent(owner) && !busy && atOnce(action)) readyCommand(commandOwner(action));\n };\n const run = (action: AppAction) => {\n if (!isCurrent(owner)) return;\n if (isCommand(action)) {\n if (!allowedCommand(action) || !availableCommand(action)) return;\n if (atOnce(action)) void runAtOnce(action);\n else setCommandForm({ action, owner: commandOwner(action), epoch: identity.epoch });\n return;\n }\n if (!allowedUpdate(action)) return;\n if (updateAttempts.get(owner)) return;\n const submitted = { ...owner, key: { ...owner.key } };\n const submission = { action, owner: submitted, values: action.set, current: () => isCurrent(submitted), done: onDone };\n /* A reason is data, and a confirmation a promise to the author: both asked in every mode. An App has no Undo\n (its writes go through the writer pool), so a confirmed verb that wrote on one click could not be taken back. */\n if (action.reason) setReasoning(submission);\n else if (action.confirm) setAsking(submission);\n else write.mutate(submission);\n };\n\n /* Which actions are shown, asked once here with the same keys each button\n asks with, so a phone's menu knows before it draws whether it has one\n item or several, and nothing is asked twice: one question per distinct\n condition. An action without one asks nothing — a disabled placeholder\n for each shared one key, which React Query reported as duplicates. */\n /* A machine's verb that says itself differently by state (\"Move to Proposal\") asks which state the record is in\n the same way: one condition per label, answered with the rest. */\n const asked = [\n ...new Set(\n drawable.flatMap((action) => (isCommand(action) ? (action.labels ?? []).map((said) => said.when) : action.when ? [action.when] : [])),\n ),\n ];\n const conditions = useQueries({\n queries: asked.map((when) => ({\n queryKey: whenKey(tableId, recordKey, when, queryScope),\n queryFn: () => matches(when),\n })),\n });\n const answered = new Map(asked.map((when, i) => [when, conditions[i]?.data]));\n // Command availability already checks its current target/when on the\n // server; do not add a second per-row visibility HTTP request here.\n /* A verb with per-state labels waits for its label, so it never arrives in one set of words and changes to another. */\n const said = (action: AppAction): AppAction => {\n if (!isCommand(action) || !action.labels) return action;\n const label = action.labels.find((candidate) => answered.get(candidate.when) === true)?.label;\n return label === undefined || label === action.label ? action : { ...action, label };\n };\n const available = drawable\n .filter((action) =>\n isCommand(action)\n ? availableCommand(action) && (action.labels ?? []).every((candidate) => answered.get(candidate.when) !== undefined)\n : !action.when || answered.get(action.when) === true,\n )\n .map(said);\n /* One filled verb, the forward one; the destructive last and quiet (actionOrder.ts). Without a\n reading of what is destructive — a list's row menu — the author's order, the first filled. */\n const arranged = destructive\n ? orderActions(available, destructive, primary)\n : available.map((action, i) => ({ action, intent: i === 0 ? ('primary' as const) : ('secondary' as const) }));\n /* A header's `actions` lead in the order the author named them, the filled one first; whatever it does not name\n follows, and is More's however few there are. */\n const named = only\n ? arranged.filter(({ action }) => only.includes(action.id)).sort((a, b) => only.indexOf(a.action.id) - only.indexOf(b.action.id))\n : undefined;\n const ordered = named\n ? [\n ...(() => {\n const lead = named.find(({ intent }) => intent === 'primary');\n if (lead) return [lead, ...named.filter((entry) => entry !== lead)];\n /* The verb the record most needs next is not among the ones named: the first of those named that\n takes nothing away is filled, so a header with verbs always has its one filled button. */\n const first = named.find(({ intent }) => intent !== 'quiet');\n return first ? [{ ...first, intent: 'primary' as const }, ...named.filter((entry) => entry !== first)] : named;\n })(),\n ...arranged.filter((entry) => !named.includes(entry)),\n ]\n : arranged;\n const shown = ordered.map(({ action }) => action);\n const intentOf = new Map(ordered.map(({ action, intent }) => [action, quiet ? ('secondary' as const) : intent]));\n const busy = write.isPending || Boolean(updateAttempts.get(owner)) || sending;\n /* A split view's keys: shown beside the verb they run, and run through this bar as a click is. */\n const keys = useContext(RecordKeys);\n const keyOf = (action: AppAction) => Object.entries(keys).find(([, id]) => id === action.id)?.[0];\n const pressed = useRef<(key: string) => void>(() => {});\n pressed.current = (key) => {\n const action = shown.find((candidate) => keys[key] === candidate.id);\n if (action && !busy) run(action);\n };\n useEffect(() => {\n if (!Object.keys(keys).length) return;\n const onKey = (event: KeyboardEvent) => {\n if (!Object.hasOwn(keys, event.key) || !takesSingleKeys(event)) return;\n event.preventDefault();\n pressed.current(event.key);\n };\n addHostListener(document, 'keydown', onKey);\n return () => removeHostListener(document, 'keydown', onKey);\n }, [keys]);\n /* The usual next step is filled and first; a few more stay one tap away\n as quiet buttons, and the rest — Delete always last — are one menu. A\n phone keeps one button, so the bar never wraps under the name. */\n const inline = menuOnly ? [] : shown.slice(0, compact ? 1 : named ? named.length : INLINE);\n const folded = shown.slice(inline.length);\n /* While the record's verbs are still being asked about, the first one's\n place is held, unseen: on a phone the bar is a row of its own under the\n name, and its arriving pushed every section down a line\n (test/built-client-vitals.mjs). */\n const unanswered = askingCommands || conditions.some((condition) => condition.isPending);\n const hold = !menuOnly && !inline.length && unanswered && drawable.length > 0;\n\n return (\n <>\n {hold && (\n <Button className=\"page-action\" aria-hidden=\"true\" tabIndex={-1} style={{ visibility: 'hidden' }}>\n {drawable[0].label}\n </Button>\n )}\n {inline.map((action) => (\n <ActionButton\n key={action.label}\n action={action}\n intent={intentOf.get(action) ?? 'secondary'}\n busy={busy}\n hint={keyOf(action)}\n onReady={() => ready(action)}\n onClick={() => run(action)}\n />\n ))}\n {menuOnly && (\n <DropMenu\n className=\"row-actions-menu\"\n triggerClassName=\"ghost row-actions-trigger\"\n triggerTitle={say('common.actions', { label: menuOnly.label })}\n triggerLabel={say('common.actions', { label: menuOnly.label })}\n label=\"⋯\"\n popupClassName=\"page-actions-popup\"\n align=\"end\"\n open={menuOnly.open}\n onOpenChange={menuOnly.onOpenChange}\n >\n {folded.map((action) => (\n <DropItem\n key={action.label}\n className={destructive?.(action) ? 'page-actions-item is-danger' : 'page-actions-item'}\n disabled={busy}\n onClick={() => run(action)}\n >\n {action.label}\n </DropItem>\n ))}\n {/* Conditions still being asked, or none that hold: said, not an empty box. */}\n {!folded.length && (\n <DropItem className=\"page-actions-item\" disabled onClick={() => {}}>\n {conditions.some((condition) => condition.isPending) ? say('common.checking') : say('nothingToDoForThisRecord')}\n </DropItem>\n )}\n </DropMenu>\n )}\n {!menuOnly && (folded.length > 0 || menuTail) && (\n <DropMenu\n className=\"page-actions-menu\"\n triggerClassName=\"ghost page-action\"\n triggerTitle={say('moreActionsForThisRecord')}\n // \"More\" alone is the app menu's name; this one says whose it is.\n triggerLabel={say('moreActions')}\n label={say('common.more')}\n popupClassName=\"page-actions-popup\"\n align=\"end\"\n >\n {folded.map((action) => (\n <DropItem\n key={action.label}\n className={destructive?.(action) ? 'page-actions-item is-danger' : 'page-actions-item'}\n disabled={busy}\n onClick={() => run(action)}\n >\n {action.label}\n {keyOf(action) && <kbd className=\"key-hint\">{keyOf(action)!.toUpperCase()}</kbd>}\n </DropItem>\n ))}\n {menuTail}\n </DropMenu>\n )}\n {form && (\n <CommandForm\n key={`${form.epoch}:${form.owner.command}:${JSON.stringify(form.owner.key)}`}\n action={operation?.action ?? form.action}\n owner={operation?.owner ?? form.owner}\n label={label}\n isCurrent={hostIsCurrent}\n onApplied={refreshCommanded}\n onClose={(closed?: CommandOperation) => {\n if (!isCurrent(owner)) return;\n setCommandForm(null);\n if (closed?.phase === 'error') told(form.action, form.owner.key, { status: 'failed', detail: closed.message });\n }}\n onDone={() => {\n if (!isCurrent(owner)) return;\n told(form.action, form.owner.key, { status: 'done' });\n onDone();\n }}\n />\n )}\n {asking && (\n <Confirm\n tableId={tableId}\n action={asking.action}\n label={label}\n onAnswer={(yes) => {\n setAsking(null);\n if (yes && asking.current()) write.mutate(asking);\n }}\n />\n )}\n {reasoning && (\n <ReasonForm\n action={reasoning.action}\n label={label}\n onAnswer={(reason) => {\n setReasoning(null);\n if (reason !== null && reasoning.current() && reasoning.action.reason) {\n write.mutate({ ...reasoning, values: { ...reasoning.action.set, [reasoning.action.reason]: reason } });\n }\n }}\n />\n )}\n </>\n );\n}\n\n/** A verb as a button: whether it is shown was asked once, by the bar. */\nfunction ActionButton({\n action,\n intent,\n busy,\n hint,\n onReady,\n onClick,\n}: {\n action: AppAction;\n intent: 'primary' | 'secondary' | 'quiet';\n busy: boolean;\n hint?: string;\n onReady?: () => void;\n onClick: () => void;\n}) {\n return (\n <Button\n intent={intent}\n className=\"page-action\"\n disabled={busy}\n title={\n action.command\n ? action.label\n : Object.entries(action.set)\n .map(([c, v]) => `${c} → ${said(typeof v === 'string' && v.startsWith('=') ? v.slice(1) : v, 'null')}`)\n .join(', ')\n }\n onClick={onClick}\n onPointerEnter={onReady}\n onFocus={onReady}\n {...(hint ? { 'aria-keyshortcuts': hint.toUpperCase() } : {})}\n >\n {action.label}\n {hint && <kbd className=\"key-hint\">{hint.toUpperCase()}</kbd>}\n </Button>\n );\n}\n\n/** Ask before writing, in the page's own dialog. */\nfunction Confirm({\n tableId,\n action,\n label,\n onAnswer,\n}: {\n tableId: string;\n action: AppUpdateAction;\n label: string;\n onAnswer: (yes: boolean) => void;\n}) {\n const table = findTable(tableId) as TableMeta | undefined;\n const answered = useRef(false);\n const answer = (yes: boolean) => {\n if (answered.current) return;\n answered.current = true;\n onAnswer(yes);\n };\n return (\n <Modal className=\"confirm action-confirm\" ariaLabel={`${action.label}?`} onClose={() => answer(false)}>\n <h2>{action.label}?</h2>\n <p>{label}</p>\n <table className=\"confirm-diff\">\n <tbody>\n {Object.entries(action.set).map(([column, value]) => (\n <tr key={column}>\n <th scope=\"row\" title={column}>\n {columnLabel(tableId, column) ?? humanName(column)}\n </th>\n {/* An expression the server works out as it writes ('=today + 14 days') is said as written. */}\n <td>\n {typeof value === 'string' && value.startsWith('=') ? (\n value.slice(1)\n ) : (\n <Value\n tableId={tableId}\n col={\n table?.columns.find((col) => col.name === column) ?? { name: column, type: 'TEXT', nullable: true, primaryKey: false }\n }\n value={value}\n compact\n />\n )}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n <div className=\"confirm-actions\">\n <Button intent=\"secondary\" onClick={() => answer(false)}>\n {say('common.cancel')}\n </Button>\n <Button intent=\"primary\" onClick={() => answer(true)}>\n {action.label}\n </Button>\n </div>\n </Modal>\n );\n}\n\n/**\n * An action that moves a record for a reason asks for it first, in the page's\n * own dialog. The note is written with the change, in the same update, so the\n * server can hold the move to it (appTransitions).\n */\nexport function ReasonForm({\n action,\n label,\n onAnswer,\n}: {\n action: AppUpdateAction;\n label: string;\n onAnswer: (reason: string | null) => void;\n}) {\n const [text, setText] = useState('');\n const answered = useRef(false);\n const field = useId();\n const answer = (reason: string | null) => {\n if (answered.current) return;\n answered.current = true;\n onAnswer(reason);\n };\n return (\n <Modal\n className=\"confirm action-confirm action-reason\"\n ariaLabel={say('labelReason', { label: action.label })}\n onClose={() => answer(null)}\n >\n <form\n onSubmit={(event) => {\n event.preventDefault();\n if (text.trim()) answer(text.trim());\n }}\n >\n <h2>{action.label}</h2>\n <p>\n {label ? say('sayWhyFor', { label }) : say('sayWhy')}\n {say('theReasonIsKept')}\n </p>\n <label className=\"action-reason-label\" htmlFor={field}>\n {say('reason')}\n </label>\n <textarea\n id={field}\n className=\"action-reason-text\"\n value={text}\n required\n rows={3}\n autoFocus\n onChange={(event) => setText(event.target.value)}\n />\n <div className=\"confirm-actions\">\n <Button intent=\"secondary\" onClick={() => answer(null)}>\n {say('common.cancel')}\n </Button>\n <Button intent=\"primary\" type=\"submit\" disabled={!text.trim()}>\n {action.label}\n </Button>\n </div>\n </form>\n </Modal>\n );\n}\n","/** An App's assistant, as declared: who is offered it, which of the fixed\n * tools and blocks it may use, which of the App's verbs it may never propose,\n * and what it may spend. The declaration only narrows: every read and every\n * proposal is still the person's own, under their grants (docs/assistant.md). */\n\n/** The tool core, the same for every App: discovery is a tool, not a preamble. */\nexport const ASSISTANT_TOOLS = ['find', 'describe', 'query', 'show', 'run'] as const;\ntype AssistantTool = (typeof ASSISTANT_TOOLS)[number];\n/** The blocks the model may compose: the App's own components, never markup. */\nexport const ASSISTANT_BLOCKS = ['table', 'metric', 'chart', 'breakdown', 'record'] as const;\ntype AssistantBlockKind = (typeof ASSISTANT_BLOCKS)[number];\n/** Where it is offered: a panel beside every room, with a record as its context, and a room of its own (`/{app}/assistant`). */\nexport const ASSISTANT_PLACEMENTS = ['panel', 'record', 'page'] as const;\nexport const ASSISTANT_EFFORTS = ['low', 'medium', 'high'] as const;\n/** The model an App gets unless it names one; the operator's key decides whether any is reachable. */\nconst DEFAULT_ASSISTANT_MODEL = 'claude-sonnet-5-5';\nconst LIMIT_KEYS = ['tokensPerTurn', 'tokensPerPersonPerDay', 'tokensPerDay'] as const;\n/** What one person may spend in a UTC day when the App names no figure: an assistant is a bill the operator pays,\n * so an open sign-up is not an open tab. A modest day's use fits; an App that expects more names its own\n * `limits.tokensPerPersonPerDay`. */\nexport const DEFAULT_TOKENS_PER_PERSON_PER_DAY = 200_000;\n/** How long a conversation untouched is kept, in days, when nothing says otherwise: every App's, and a tenant App's\n * unless its policy names `assistant.retentionDays`. */\nexport const ASSISTANT_RETENTION_DAYS = 90;\nconst KEYS = ['instructions', 'starters', 'model', 'effort', 'roles', 'tools', 'exclude', 'blocks', 'placement', 'limits'] as const;\n/** An empty conversation offers a few of the App's own questions, each a line the person sends with one press: at\n most six in any one place, however many the App declares for its different places. */\nconst MAX_STARTERS = 6;\nconst MAX_STARTER = 120;\nconst STARTER_KEYS = ['text', 'views', 'records'] as const;\n\n/**\n * A starter offered in some places only: in the named views (their own rooms, a list or a dashboard), on a record of\n * the named tables, or both. A starter that is a bare line is offered everywhere.\n *\n * starters: ['Find stale deals', { text: 'Summarize this ticket', records: ['incident'] }]\n */\nexport interface AssistantStarter {\n text: string;\n /** View keys: offered while one of these views is the room. */\n views?: string[];\n /** Table names: offered while a record of one of these tables is open. */\n records?: string[];\n}\n\ninterface AssistantLimits {\n /** Input and output tokens one turn may spend, every model call in it counted; a call's cached input (the turn so far,\n * read again) counts at a tenth, as it is billed. */\n tokensPerTurn?: number;\n /** One person's tokens in a UTC day, across their conversations; `DEFAULT_TOKENS_PER_PERSON_PER_DAY` when not named. */\n tokensPerPersonPerDay?: number;\n /** Every person's tokens in the App in a UTC day. */\n tokensPerDay?: number;\n}\n\nexport interface AppAssistant {\n /** What the App's assistant is for and how it should answer: the author's words, prefixed by the platform's own rules. */\n instructions?: string;\n /** Questions an empty conversation offers, in the App's words: each sent as the person's own when pressed. A bare\n line is offered everywhere, a starter with `views` or `records` only there. */\n starters: Array<string | AssistantStarter>;\n model: string;\n effort?: (typeof ASSISTANT_EFFORTS)[number];\n /** The roles offered the assistant; absent, everyone who may open the App. */\n roles?: string[];\n tools: AssistantTool[];\n /** Verbs it may never propose, as `resource.action` (an action's key, or `new` for the New form). */\n exclude: string[];\n blocks: AssistantBlockKind[];\n placement: Array<(typeof ASSISTANT_PLACEMENTS)[number]>;\n limits: AssistantLimits;\n}\n\ninterface AssistantContext {\n roles: readonly string[] | undefined;\n /** Each resource's action keys, so an exclusion names a verb that exists. */\n actions: Readonly<Record<string, readonly string[]>>;\n /** Each view's key and the table it shows, so a starter names a view that exists. */\n views?: Readonly<Record<string, string | undefined>>;\n /** The tables a record can be opened from: a list view's or a page's. */\n recordTables?: readonly string[];\n}\n\nfunction subset<T extends string>(raw: unknown, allowed: readonly T[], where: string): T[] {\n if (!Array.isArray(raw) || !raw.length) throw new Error(`${where} is a non-empty list of ${allowed.map((x) => `\"${x}\"`).join(', ')}.`);\n for (const value of raw) {\n if (!allowed.includes(value as T))\n throw new Error(`${where} names \"${String(value)}\"; it is one of ${allowed.map((x) => `\"${x}\"`).join(', ')}.`);\n }\n return [...new Set(raw as T[])];\n}\n\nexport function parseAppAssistant(raw: unknown, context: AssistantContext, where = 'assistant'): AppAssistant | undefined {\n if (raw === undefined) return undefined;\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) throw new Error(`${where} is an object: assistant({ instructions, ... }).`);\n const a = raw as Record<string, unknown>;\n /* Writes wait for the person, and an author cannot turn that off: the record text the model reads is not theirs.\n A key that could only restate it was dropped before 1.0, so it is refused with the reason, not as a stranger. */\n if (Object.hasOwn(a, 'confirm'))\n throw new Error(`${where}.confirm is gone: every write the assistant proposes waits for the person to confirm it. Delete it.`);\n for (const key of Object.keys(a)) {\n if (!(KEYS as readonly string[]).includes(key)) throw new Error(`${where} has an unknown key \"${key}\"; it takes ${KEYS.join(', ')}.`);\n }\n if (a.instructions !== undefined && (typeof a.instructions !== 'string' || !a.instructions.trim())) {\n throw new Error(`${where}.instructions is a non-empty string.`);\n }\n if (a.model !== undefined && (typeof a.model !== 'string' || !/^[a-z0-9][a-z0-9.-]*$/.test(a.model))) {\n throw new Error(`${where}.model is a model id, such as \"${DEFAULT_ASSISTANT_MODEL}\".`);\n }\n if (a.effort !== undefined && !(ASSISTANT_EFFORTS as readonly unknown[]).includes(a.effort)) {\n throw new Error(`${where}.effort is \"low\", \"medium\" or \"high\".`);\n }\n let roles: string[] | undefined;\n if (a.roles !== undefined) {\n if (!context.roles) throw new Error(`${where}.roles names roles, and the App declares no \"auth\" with roles.`);\n roles = subset(a.roles as unknown, context.roles as string[], `${where}.roles`);\n }\n const tools = a.tools === undefined ? [...ASSISTANT_TOOLS] : subset(a.tools, ASSISTANT_TOOLS, `${where}.tools`);\n const blocks = a.blocks === undefined ? [...ASSISTANT_BLOCKS] : subset(a.blocks, ASSISTANT_BLOCKS, `${where}.blocks`);\n // A page of its own is a room in the App's menu: the author's to add, so absent it is the panel and the record.\n const placement =\n a.placement === undefined\n ? (['panel', 'record'] as AppAssistant['placement'])\n : subset(a.placement, ASSISTANT_PLACEMENTS, `${where}.placement`);\n if (!placement.includes('panel'))\n throw new Error(`${where}.placement includes \"panel\": the record placement and the page open the same conversation.`);\n const starters = a.starters === undefined ? [] : parseStarters(a.starters, placement, context, `${where}.starters`);\n const exclude: string[] = [];\n if (a.exclude !== undefined) {\n if (!Array.isArray(a.exclude)) throw new Error(`${where}.exclude is a list of \"resource.action\".`);\n for (const entry of a.exclude) {\n const [resource, action, rest] = typeof entry === 'string' ? entry.split('.') : [];\n if (!resource || !action || rest !== undefined)\n throw new Error(`${where}.exclude has \"${String(entry)}\"; each is \"resource.action\", or \"resource.new\" for its New form.`);\n const actions = context.actions[resource];\n if (!actions) throw new Error(`${where}.exclude names \"${resource}\", which is not one of the App's resources.`);\n if (action !== 'new' && !actions.includes(action)) {\n throw new Error(\n `${where}.exclude names \"${entry}\"; resources.${resource} has no action \"${action}\"${actions.length ? ` (it has ${actions.join(', ')})` : ''}.`,\n );\n }\n exclude.push(entry);\n }\n }\n const limits: AssistantLimits = { tokensPerPersonPerDay: DEFAULT_TOKENS_PER_PERSON_PER_DAY };\n if (a.limits !== undefined) {\n if (!a.limits || typeof a.limits !== 'object' || Array.isArray(a.limits)) throw new Error(`${where}.limits is an object.`);\n for (const [key, value] of Object.entries(a.limits)) {\n if (!(LIMIT_KEYS as readonly string[]).includes(key))\n throw new Error(`${where}.limits has an unknown key \"${key}\"; it takes ${LIMIT_KEYS.join(', ')}.`);\n if (!Number.isSafeInteger(value) || (value as number) < 1000)\n throw new Error(`${where}.limits.${key} is a whole number of tokens, at least 1000.`);\n limits[key as keyof AssistantLimits] = value as number;\n }\n }\n return {\n ...(a.instructions === undefined ? {} : { instructions: (a.instructions as string).trim() }),\n starters,\n model: (a.model as string | undefined) ?? DEFAULT_ASSISTANT_MODEL,\n ...(a.effort === undefined ? {} : { effort: a.effort as AppAssistant['effort'] }),\n ...(roles ? { roles } : {}),\n tools,\n exclude,\n blocks,\n placement,\n limits,\n };\n}\n\nfunction nameList(raw: unknown, known: (name: string) => boolean, where: string, what: string, unknown: string): string[] {\n if (!Array.isArray(raw) || !raw.length || raw.some((name) => typeof name !== 'string' || !name))\n throw new Error(`${where} is a non-empty list of ${what}.`);\n for (const name of raw as string[]) if (!known(name)) throw new Error(`${where} names \"${name}\", which ${unknown}.`);\n return [...new Set(raw as string[])];\n}\n\nfunction parseStarters(\n raw: unknown,\n placement: AppAssistant['placement'],\n context: AssistantContext,\n where: string,\n): AppAssistant['starters'] {\n if (!Array.isArray(raw) || !raw.length)\n throw new Error(`${where} is a list of questions an empty conversation offers: a line, or { text, views, records }.`);\n const views = context.views ?? {};\n const tables = new Set(context.recordTables ?? Object.values(views).filter((table) => table !== undefined));\n const seen = new Set<string>();\n const starters = raw.map((entry, i): string | AssistantStarter => {\n const at = `${where}[${i}]`;\n const scoped = Boolean(entry) && typeof entry === 'object' && !Array.isArray(entry);\n const text = scoped ? (entry as Record<string, unknown>).text : entry;\n if (typeof text !== 'string' || !text.trim() || text.trim().length > MAX_STARTER || /[\\p{Cc}\\p{Cs}]/u.test(text))\n throw new Error(`${where} has ${JSON.stringify(text)}; each is one line of at most ${MAX_STARTER} characters.`);\n const line = text.trim();\n if (seen.has(line)) throw new Error(`${where} names \"${line}\" twice.`);\n seen.add(line);\n if (!scoped) return line;\n const starter = entry as Record<string, unknown>;\n for (const key of Object.keys(starter))\n if (!(STARTER_KEYS as readonly string[]).includes(key))\n throw new Error(`${at} has an unknown key \"${key}\"; a starter takes ${STARTER_KEYS.join(', ')}.`);\n if (starter.views === undefined && starter.records === undefined)\n throw new Error(`${at} names no place: give it views, records or both, or write the line alone to offer it everywhere.`);\n const out: AssistantStarter = { text: line };\n if (starter.views !== undefined)\n out.views = nameList(starter.views, (key) => Object.hasOwn(views, key), `${at}.views`, 'view keys', \"is not one of this App's views\");\n if (starter.records !== undefined) {\n // A record's starter speaks of the open record (\"Summarize this ticket\"), so the assistant must be handed it.\n if (!placement.includes('record'))\n throw new Error(\n `${at}.records offers it on an open record, and the assistant does not take the record as context: add \"record\" to placement.`,\n );\n out.records = nameList(\n starter.records,\n (table) => tables.has(table),\n `${at}.records`,\n 'table names',\n 'no list view or page of this App opens a record of',\n );\n }\n return out;\n });\n /* At most six in any one place: everywhere's, with a view's own or a record's own. */\n const everywhere = starters.filter((s) => typeof s === 'string').length;\n const places = [\n ['everywhere', everywhere] as const,\n ...Object.keys(views).map(\n (key) => [`in view \"${key}\"`, everywhere + starters.filter((s) => typeof s !== 'string' && s.views?.includes(key)).length] as const,\n ),\n ...[...tables].map(\n (table) =>\n [`on a ${table} record`, everywhere + starters.filter((s) => typeof s !== 'string' && s.records?.includes(table)).length] as const,\n ),\n ];\n const crowded = places.find(([, count]) => count > MAX_STARTERS);\n if (crowded) throw new Error(`${where} offers ${crowded[1]} starters ${crowded[0]}; at most ${MAX_STARTERS} are offered in one place.`);\n return starters;\n}\n\n/** Where the person is, as the starters read it: the view that is the room, the table of the record that is open. */\ninterface StarterPlace {\n view?: string;\n record?: string;\n}\n\n/** The starters offered here, in the App's order: every bare line, and a scoped one where its view or record is. */\nexport function startersHere(starters: readonly (string | AssistantStarter)[] | undefined, here: StarterPlace): string[] {\n return (starters ?? []).flatMap((starter) => {\n if (typeof starter === 'string') return [starter];\n const offered =\n (here.view !== undefined && starter.views?.includes(here.view)) ||\n (here.record !== undefined && starter.records?.includes(here.record));\n return offered ? [starter.text] : [];\n });\n}\n","/**\n * The assistant's requests, as its panel sends them. In an ordinary App they\n * are `api()`'s. In a tenant App they carry the tab's context lease and\n * nothing that names a tenant: the server recovers the lease and takes the\n * tenant from it alone (server tenant/tenantAssistant.ts), so a conversation\n * is always the current customer's. Kept in the assistant's own chunk.\n */\nimport { api } from '@mistriwork/kit/client/core.js';\nimport { captureSessionIdentity, captureTenantLease } from '@mistriwork/kit/client/sessionIdentity.js';\nimport { TENANT_HTTP_HEADERS as names } from '../../shared/tenantContext.js';\nimport { fetchServer } from '@mistriwork/kit/client/transport.js';\n\n/** The account, and in a tenant App the tab's lease: what the server admits an assistant request by. */\nexport function assistantHeaders(): Record<string, string> {\n const identity = captureSessionIdentity();\n if (identity.mode !== 'authenticated' || !identity.accountId) return {};\n const lease = identity.tenantRequired ? captureTenantLease(identity) : undefined;\n return {\n [names.account]: identity.accountId,\n ...(lease && identity.appId\n ? { [names.app]: identity.appId, [names.tab]: lease.tabId, [names.context]: lease.context, [names.revision]: String(lease.revision) }\n : {}),\n };\n}\n\n/**\n * Whose conversations the panel shows: the account's, in the lease's tenant, so the history switches with the customer\n * and with the person. The panel is kept while the page is, and a conversation it last showed was reopened for whoever\n * signed in next in that tab, who could only be refused it.\n */\nexport function assistantOwner(): string {\n const identity = captureSessionIdentity();\n const tenant = (identity.tenantRequired && captureTenantLease(identity)?.tenantId) || '';\n return `${identity.accountId ?? ''}\\n${tenant}`;\n}\n\nexport async function assistantApi(path: string, body?: Record<string, unknown>): Promise<unknown> {\n if (!captureSessionIdentity().tenantRequired) return api(path as never, ...((body === undefined ? [] : [body]) as never[]));\n const res = await fetchServer(path, {\n method: body === undefined ? 'GET' : 'POST',\n credentials: 'same-origin',\n cache: 'no-store',\n headers: { ...assistantHeaders(), ...(body === undefined ? {} : { 'content-type': 'application/json' }) },\n ...(body === undefined ? {} : { body: JSON.stringify(body) }),\n });\n let value: { error?: unknown } | null = null;\n try {\n value = (await res.json()) as { error?: unknown };\n } catch {\n /* The status is all there is to say. */\n }\n if (!res.ok) throw Object.assign(new Error(typeof value?.error === 'string' ? value.error : `${res.status}`), { status: res.status });\n return value;\n}\n","/**\n * The assistant panel's model, without React: the items a conversation is\n * drawn as, the server-sent events a turn streams, and how each event\n * changes the items. The server rebuilds the same items from what it stored\n * (assistantTurn.ts `itemsOf`), so a conversation reopened reads as it did\n * live; the one difference is that live text arrives a word at a time.\n *\n * Nothing here trusts the stream's shape: an event that does not read as its\n * kind is dropped rather than drawn.\n */\nimport { assistantHeaders } from './assistantRequest.js';\nimport { scopeApiRequest } from '@mistriwork/kit/client/requestIdentity.js';\nimport { state } from '@mistriwork/kit/client/core.js';\nimport { fetchServer } from '@mistriwork/kit/client/transport.js';\n\nexport type ProposalOutcome = { status: 'done' | 'declined' | 'failed'; detail?: string };\nexport interface Proposal {\n id: string;\n kind: 'set' | 'command' | 'new';\n resource: string;\n action: string;\n label: string;\n key?: Record<string, unknown>;\n record?: string;\n address?: string;\n values: Record<string, unknown>;\n why?: string;\n}\nexport type AssistantBlock =\n | { kind: 'section'; section: Record<string, unknown> }\n | { kind: 'record'; table: string; key: Record<string, unknown>; title: string; values: Record<string, unknown>; address?: string };\n\nexport type PanelItem =\n /** `seq` is the stored event's, once the server has said it; edit names it. */\n | { type: 'person'; seq?: number; text: string }\n /** `open` while the model is still writing it. */\n | { type: 'text'; text: string; open?: true }\n | { type: 'note'; text: string }\n | { type: 'step'; id: string; tool: string; label: string; failed?: true }\n | { type: 'block'; id: string; block: AssistantBlock }\n | { type: 'proposal'; id: string; proposal: Proposal; outcome?: ProposalOutcome };\n\nexport interface StreamEvent {\n event: string;\n data: Record<string, unknown>;\n}\n\nconst record = (value: unknown): value is Record<string, unknown> => Boolean(value) && typeof value === 'object' && !Array.isArray(value);\n\n/** A run of the model's words: plain, bold, code, or a link to an address inside the App. */\nexport type Run = { text: string; mark?: 'strong' | 'code' } | { text: string; link: string };\nexport type Paragraph = { list: false; lines: Run[][] } | { list: true; lines: Run[][] };\n\n/* An inside address only: a path, never a scheme or another host. */\nexport const inside = (href: string): boolean => /^\\/(?!\\/)[^\\s\\\\]*$/.test(href);\n\n/**\n * The model's words as paragraphs and lists of runs, read with three marks\n * and nothing else. Text, never markup: a link to anywhere but a path in the\n * App is said as its words alone.\n */\nexport function wordsOf(text: string): Paragraph[] {\n const runs = (line: string): Run[] => {\n const found: Run[] = [];\n const pattern = /\\[([^\\]\\n]+)\\]\\(([^)\\s]+)\\)|\\*\\*([^*\\n]+)\\*\\*|`([^`\\n]+)`/g;\n let from = 0;\n for (let match = pattern.exec(line); match; match = pattern.exec(line)) {\n if (match.index > from) found.push({ text: line.slice(from, match.index) });\n if (match[1] !== undefined) found.push(inside(match[2]) ? { text: match[1], link: match[2] } : { text: match[1] });\n else if (match[3] !== undefined) found.push({ text: match[3], mark: 'strong' });\n else found.push({ text: match[4], mark: 'code' });\n from = match.index + match[0].length;\n }\n if (from < line.length) found.push({ text: line.slice(from) });\n return found;\n };\n return text\n .trim()\n .split(/\\n{2,}/)\n .filter(Boolean)\n .map((paragraph) => {\n const lines = paragraph.split('\\n');\n const list = lines.every((line) => /^\\s*[-*] /.test(line));\n return { list, lines: lines.map((line) => runs(list ? line.replace(/^\\s*[-*] /, '') : line)) };\n });\n}\n\n/** The events of a `text/event-stream` body, each handed on as it completes. */\nexport async function readEvents(body: ReadableStream<Uint8Array>, onEvent: (event: StreamEvent) => void): Promise<void> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n for (;;) {\n const { done, value } = await reader.read();\n buffer += done ? decoder.decode() : decoder.decode(value, { stream: true });\n let end: number;\n while ((end = buffer.indexOf('\\n\\n')) >= 0) {\n const chunk = buffer.slice(0, end);\n buffer = buffer.slice(end + 2);\n let event = 'message';\n const data: string[] = [];\n for (const line of chunk.split('\\n')) {\n if (line.startsWith('event:')) event = line.slice(6).trim();\n else if (line.startsWith('data:')) data.push(line.slice(5).trimStart());\n }\n try {\n const parsed: unknown = JSON.parse(data.join('\\n'));\n if (record(parsed)) onEvent({ event, data: parsed });\n } catch {\n /* Not an event this panel reads. */\n }\n }\n if (done) return;\n }\n}\n\n/** The items after one event. Pure: the panel keeps the result as its state. */\nexport function applyEvent(items: readonly PanelItem[], { event, data }: StreamEvent): PanelItem[] {\n const next = items.map((item) =>\n item.type === 'text' && item.open && event !== 'text' ? { type: 'text' as const, text: item.text } : item,\n );\n const last = next[next.length - 1];\n switch (event) {\n case 'conversation':\n // The person's words as stored: the seq an edit names from now on.\n if (typeof data.person === 'number')\n for (let at = next.length - 1; at >= 0; at--) {\n const item = next[at];\n if (item.type === 'person') {\n next[at] = { ...item, seq: data.person };\n break;\n }\n }\n return next;\n case 'text':\n if (typeof data.delta !== 'string') return next;\n if (last?.type === 'text' && last.open) next[next.length - 1] = { type: 'text', text: last.text + data.delta, open: true };\n else next.push({ type: 'text', text: data.delta, open: true });\n return next;\n case 'step':\n if (typeof data.id === 'string' && typeof data.tool === 'string' && typeof data.label === 'string')\n next.push({\n type: 'step',\n id: data.id,\n tool: data.tool,\n label: data.label,\n ...(data.failed === true ? { failed: true as const } : {}),\n });\n return next;\n case 'block':\n if (typeof data.id === 'string' && record(data.block)) next.push({ type: 'block', id: data.id, block: data.block as AssistantBlock });\n return next;\n case 'proposal':\n if (typeof data.id === 'string' && record(data.proposal))\n next.push({ type: 'proposal', id: data.id, proposal: data.proposal as unknown as Proposal });\n return next;\n case 'note':\n if (typeof data.text === 'string') next.push({ type: 'note', text: data.text });\n return next;\n default:\n return next;\n }\n}\n\n/** The items cut back to before the person's words at `at`, for an edit or a retry. */\nexport function cutAt(items: readonly PanelItem[], at: number): PanelItem[] {\n return items.slice(0, at);\n}\n\n/** The proposal still waiting for the person: the last one, if it has no outcome. */\nexport function waitingProposal(items: readonly PanelItem[]): Proposal | undefined {\n for (let at = items.length - 1; at >= 0; at--) {\n const item = items[at];\n if (item.type === 'person') return undefined;\n if (item.type === 'proposal') return item.outcome ? undefined : item.proposal;\n }\n return undefined;\n}\n\n/** The items grouped for drawing: consecutive steps fold into one group. */\ntype DrawnItem =\n | { type: 'steps'; steps: Extract<PanelItem, { type: 'step' }>[]; at: number }\n | { type: 'item'; item: PanelItem; at: number };\nexport function grouped(items: readonly PanelItem[]): DrawnItem[] {\n const drawn: DrawnItem[] = [];\n items.forEach((item, at) => {\n const last = drawn[drawn.length - 1];\n if (item.type === 'step' && last?.type === 'steps') last.steps.push(item);\n else if (item.type === 'step') drawn.push({ type: 'steps', steps: [item], at });\n else drawn.push({ type: 'item', item, at });\n });\n return drawn;\n}\n\n/**\n * A turn whose connection to the server dropped before the answer finished: the network went, the server restarted,\n * or a proxy answered in its place (\"Container suddenly disconnected\" as a bare 500, a field report). There is no\n * sentence of the server's to say, only that the turn can be tried again.\n */\nclass ConnectionLost extends Error {\n // The panel says it in its own words (connectionLost); there is no sentence here to show.\n readonly lost = true;\n}\n\n/**\n * A turn: POSTed as `api()` posts (the App named, the account said), read\n * as a stream. Resolves when the stream ends; a refusal before it starts\n * throws with the server's sentence, and a turn cut off on the way throws\n * ConnectionLost.\n */\nexport async function stream(\n path: '/api/assistant/turn' | '/api/assistant/resolve',\n body: Record<string, unknown>,\n onEvent: (event: StreamEvent) => void,\n signal: AbortSignal,\n): Promise<void> {\n const { url, payload } = scopeApiRequest(path, body, state.activeConnection);\n // A stop is the person's own, never a lost connection.\n const cut = (error: unknown): never => {\n throw signal.aborted ? error : new ConnectionLost();\n };\n const res = await fetchServer(url, {\n method: 'POST',\n credentials: 'same-origin',\n cache: 'no-store',\n signal,\n // The account, and in a tenant App the tab's lease, from which alone the server takes the tenant.\n headers: { 'content-type': 'application/json', ...assistantHeaders() },\n body: JSON.stringify(payload),\n }).catch(cut);\n if (!res.ok || !res.body) {\n let message: string | undefined;\n try {\n const said = (await res.json()) as { error?: unknown };\n if (typeof said.error === 'string') message = said.error;\n } catch {\n /* Not the server's own answer. */\n }\n // A server error without the server's sentence was said by whatever stood between: a gateway, a proxy.\n if (message === undefined && res.status >= 500) throw new ConnectionLost();\n throw Object.assign(new Error(message ?? `${res.status}`), { status: res.status });\n }\n // Every turn the server finishes ends in `done`; a stream that closes before it was cut off.\n let finished = false;\n await readEvents(res.body, (event) => {\n if (event.event === 'done') finished = true;\n onEvent(event);\n }).catch(cut);\n if (!finished && !signal.aborted) throw new ConnectionLost();\n}\n","/** What ConversationList says, in the shell room (packages/kit/src/client/messages.ts says how the catalog is split). */\nimport { defineMessages } from '@mistriwork/kit/client/messages.js';\n\nexport const say = defineMessages({\n newConversation: 'New conversation',\n noConversations: 'No conversations yet.',\n deleteConversation: 'Delete “{title}”',\n untitled: 'Untitled conversation',\n filterConversations: 'Filter conversations',\n clearSearch: 'Clear the search',\n searchResults: 'Conversations that match',\n noMatches: 'No conversations match',\n conversationActions: 'Actions for “{title}”',\n rename: 'Rename',\n renameLabel: 'Rename “{title}”',\n delete: 'Delete',\n deleteConversationTerms: 'Its messages are deleted for good. Records it showed or changed stay as they are.',\n waitingShort: 'Waiting for you',\n workingShort: 'Working',\n day_today: 'Today',\n day_yesterday: 'Yesterday',\n group_waiting: 'Waiting for you',\n group_today: 'Today',\n group_yesterday: 'Yesterday',\n group_week: 'Earlier this week',\n group_older: 'Older',\n});\n","/**\n * The assistant's conversations, one list for the room's rail and the panel's\n * Conversations view (AssistantPanel.tsx): what needs the person first — a\n * change waiting for them to confirm — then the rest by when they were last\n * touched, a quiet line each.\n *\n * Search is two answers to one box. Titles are filtered as the person types,\n * from the list already here; a moment after they stop, the server is asked\n * for the conversations whose words hold it (`/api/assistant/search` — theirs\n * and the model's, never a tool's result, and only their own), and those\n * come back with the line they were found in.\n *\n * Nothing here moves on its own: a turn still running is a word in the faint\n * ink where the time would be, not a pulse (docs/design.md, motion).\n */\nimport { useEffect, useMemo, useRef, useState, type KeyboardEvent, type ReactNode } from 'react';\nimport { useQuery } from '@tanstack/react-query';\nimport { assistantApi, assistantOwner } from './assistantRequest.js';\nimport { formatLocale, formatTimezone } from '@mistriwork/kit/client/locale.js';\nimport { Button } from '@mistriwork/ui/Button.js';\nimport { DropItem, DropMenu } from '@mistriwork/ui/DropMenu.js';\nimport { Modal, type ModalHandle } from '@mistriwork/ui/Modal.js';\nimport { say } from '../copy/shell/components/ConversationList.js';\n\nexport interface ConversationSummary {\n id: string;\n title: string;\n updatedAt: string;\n /** `awaiting`: a change the model proposed is waiting for the person. */\n state?: 'idle' | 'awaiting';\n /** The line a search found it by. */\n snippet?: string;\n}\n\ninterface ListProps {\n app: string;\n conversations: readonly ConversationSummary[];\n current: string | null;\n /** The conversation whose turn is running here, if one is. */\n working?: string | null;\n onOpen: (id: string) => void;\n onNew: () => void;\n onRename: (id: string, title: string) => Promise<void>;\n onDelete: (id: string) => Promise<void>;\n /** The clock the groups are read against; the browser's, but a test's own. */\n now?: Date;\n}\n\nconst DAY = 86_400_000;\n\ntype Group = 'waiting' | 'today' | 'yesterday' | 'week' | 'older';\nconst GROUPS: readonly Group[] = ['waiting', 'today', 'yesterday', 'week', 'older'];\n\nconst headingOf = (group: Group): string =>\n ({\n waiting: say('group_waiting'),\n today: say('group_today'),\n yesterday: say('group_yesterday'),\n week: say('group_week'),\n older: say('group_older'),\n })[group];\n\n/* The App's zone when it names one this runtime knows (`ui.timezone`, which the payload always fills), else the\n reader's own: \"today\" is the day the App's dates already mean, as formatRelativeDay reads it (locale.ts). */\nconst zones = new Map<string, Intl.DateTimeFormat>();\nfunction dayParts(zone: string | undefined): Intl.DateTimeFormat {\n const key = zone ?? '';\n let format = zones.get(key);\n if (!format) {\n format = new Intl.DateTimeFormat('en-US', { timeZone: zone, year: 'numeric', month: 'numeric', day: 'numeric' });\n zones.set(key, format);\n }\n return format;\n}\nfunction zoneOf(): string | undefined {\n const zone = formatTimezone();\n if (!zone) return undefined;\n try {\n dayParts(zone);\n return zone;\n } catch {\n return undefined;\n }\n}\n/** The calendar day an instant falls on in `zone`, as a UTC midnight: a ruler for counting days, never a moment. */\nfunction dayOn(at: Date, zone: string | undefined): number {\n const parts = dayParts(zone).formatToParts(at);\n const get = (type: string) => Number(parts.find((part) => part.type === type)?.value);\n return Date.UTC(get('year'), get('month') - 1, get('day'));\n}\n/** How many calendar days before today (in the App's zone) a conversation was last touched; NaN for no date. */\nfunction daysBefore(updatedAt: string, now: Date, zone: string | undefined): number {\n const at = new Date(updatedAt);\n if (!Number.isFinite(at.getTime()) || !Number.isFinite(now.getTime())) return Number.NaN;\n return Math.round((dayOn(now, zone) - dayOn(at, zone)) / DAY);\n}\n\n/** Which heading a conversation sits under: waiting first, then by its last change's calendar day. */\nfunction groupOf(conversation: ConversationSummary, now: Date, zone: string | undefined): Group {\n if (conversation.state === 'awaiting') return 'waiting';\n const days = daysBefore(conversation.updatedAt, now, zone);\n if (!(days > 0)) return Number.isNaN(days) ? 'older' : 'today';\n if (days === 1) return 'yesterday';\n if (days < 7) return 'week';\n return 'older';\n}\n\n/** Its day, said as the headings say days: \"Today\", \"Yesterday\", a weekday within the week, then the date (\"Sep 4\"). */\nfunction dayLabel(updatedAt: string, now: Date, zone: string | undefined): string {\n const days = daysBefore(updatedAt, now, zone);\n if (Number.isNaN(days)) return '';\n if (days <= 0) return say('day_today');\n if (days === 1) return say('day_yesterday');\n const at = new Date(updatedAt);\n const locale = formatLocale();\n if (days < 7) return new Intl.DateTimeFormat(locale, { weekday: 'short', timeZone: zone }).format(at);\n const sameYear = new Date(dayOn(at, zone)).getUTCFullYear() === new Date(dayOn(now, zone)).getUTCFullYear();\n return new Intl.DateTimeFormat(locale, {\n month: 'short',\n day: 'numeric',\n timeZone: zone,\n ...(sameYear ? {} : { year: 'numeric' }),\n }).format(at);\n}\n\n/** The time the list is read against: the browser's, read afresh each render and at least each minute, so a list\n left open over midnight moves its rows to Yesterday. A test passes its own. */\nfunction useNow(given: Date | undefined): Date {\n const [, tick] = useState(0);\n useEffect(() => {\n if (given) return;\n const every = window.setInterval(() => tick((was) => was + 1), 60_000);\n return () => window.clearInterval(every);\n }, [given]);\n return given ?? new Date();\n}\n\n/** The words a search found, marked where they are. */\nfunction Marked({ text, words }: { text: string; words: string }) {\n const at = words ? text.toLowerCase().indexOf(words.toLowerCase()) : -1;\n if (at < 0) return <>{text}</>;\n return (\n <>\n {text.slice(0, at)}\n <mark>{text.slice(at, at + words.length)}</mark>\n {text.slice(at + words.length)}\n </>\n );\n}\n\n/* A funnel: the rail's box narrows this list, and is not the App's search. */\nfunction Funnel() {\n return (\n <svg\n className=\"assistant-convs-find-icon\"\n viewBox=\"0 0 16 16\"\n width=\"12\"\n height=\"12\"\n aria-hidden=\"true\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M2.5 3.5h11l-4.25 5v4l-2.5 1v-5z\" />\n </svg>\n );\n}\n\nfunction Plus() {\n return (\n <svg className=\"icon\" viewBox=\"0 0 16 16\" width=\"14\" height=\"14\" aria-hidden=\"true\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\">\n <path d=\"M8 3v10M3 8h10\" />\n </svg>\n );\n}\n\nexport function ConversationList({ app, conversations, current, working, onOpen, onNew, onRename, onDelete, now: given }: ListProps) {\n const now = useNow(given);\n const zone = zoneOf();\n const [words, setWords] = useState('');\n const [asked, setAsked] = useState('');\n const [renaming, setRenaming] = useState<string | null>(null);\n const [deleting, setDeleting] = useState<ConversationSummary | null>(null);\n const term = words.trim();\n\n /* The server is asked once the person stops typing for a moment; titles answer at once meanwhile. */\n useEffect(() => {\n const wait = window.setTimeout(() => setAsked(term), 250);\n return () => window.clearTimeout(wait);\n }, [term]);\n const searched = useQuery({\n queryKey: ['assistant-search', app, assistantOwner(), asked],\n enabled: asked.length > 0,\n staleTime: 10_000,\n queryFn: async () =>\n (await assistantApi(`/api/assistant/search?app=${encodeURIComponent(app)}&q=${encodeURIComponent(asked)}`)) as {\n conversations: ConversationSummary[];\n },\n });\n\n const shown = useMemo(() => {\n if (!term) return conversations;\n const lower = term.toLowerCase();\n const found = asked === term ? (searched.data?.conversations ?? []) : [];\n const snippets = new Map(found.map((each) => [each.id, each.snippet]));\n const byTitle = conversations\n .filter((each) => each.title.toLowerCase().includes(lower))\n .map((each) => ({ ...each, snippet: snippets.get(each.id) }));\n const seen = new Set(byTitle.map((each) => each.id));\n return [...byTitle, ...found.filter((each) => !seen.has(each.id))];\n }, [conversations, term, asked, searched.data]);\n\n const groups = useMemo(() => {\n const out = new Map<Group, ConversationSummary[]>();\n for (const each of shown) {\n const group = groupOf(each, now, zone);\n out.set(group, [...(out.get(group) ?? []), each]);\n }\n return GROUPS.filter((group) => out.has(group)).map((group) => ({ group, rows: out.get(group)! }));\n // Grouped again when the day turns, not each render: today's day is what the clock changes.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [shown, zone, Number.isFinite(now.getTime()) ? dayOn(now, zone) : 0]);\n\n const onSearchKey = (event: KeyboardEvent<HTMLInputElement>) => {\n if (event.key === 'Escape' && words) {\n // The box empties first; the panel's own Escape is the next press's.\n event.preventDefault();\n event.stopPropagation();\n setWords('');\n }\n };\n const settling = Boolean(term) && (asked !== term || searched.isFetching);\n\n const row = (each: ConversationSummary): ReactNode => {\n const here = each.id === current;\n const waiting = each.state === 'awaiting';\n return (\n <li key={each.id} className={`assistant-conv${here ? ' assistant-conv-current' : ''}${waiting ? ' assistant-conv-waiting' : ''}`}>\n {renaming === each.id ? (\n <RenameField\n title={each.title}\n onDone={(title) => {\n setRenaming(null);\n if (title && title !== each.title) void onRename(each.id, title);\n }}\n />\n ) : (\n <button type=\"button\" className=\"assistant-conv-open\" aria-current={here ? 'true' : undefined} onClick={() => onOpen(each.id)}>\n <span className=\"assistant-conv-line\">\n {waiting && <span className=\"assistant-conv-dot\" aria-label={say('waitingShort')} role=\"img\" />}\n <span className=\"assistant-conv-title\" title={each.title || undefined}>\n <Marked text={each.title || say('untitled')} words={term} />\n </span>\n <span className=\"assistant-conv-when\">{working === each.id ? say('workingShort') : dayLabel(each.updatedAt, now, zone)}</span>\n </span>\n {term && each.snippet && (\n <span className=\"assistant-conv-snippet\">\n <Marked text={each.snippet} words={term} />\n </span>\n )}\n </button>\n )}\n {renaming !== each.id && (\n <DropMenu\n className=\"assistant-conv-menu\"\n triggerClassName=\"assistant-conv-more\"\n triggerTitle={say('conversationActions', { title: each.title })}\n triggerLabel={say('conversationActions', { title: each.title })}\n label=\"⋯\"\n popupClassName=\"page-actions-popup\"\n align=\"end\"\n >\n <DropItem className=\"page-actions-item\" onClick={() => setRenaming(each.id)}>\n {say('rename')}\n </DropItem>\n <DropItem className=\"page-actions-item\" onClick={() => setDeleting(each)}>\n {say('delete')}\n </DropItem>\n </DropMenu>\n )}\n </li>\n );\n };\n\n return (\n <div className=\"assistant-convs\">\n <div className=\"assistant-convs-head\">\n <button type=\"button\" className=\"assistant-convs-new\" onClick={onNew}>\n <Plus />\n {say('newConversation')}\n </button>\n <div className=\"assistant-convs-find\">\n <Funnel />\n <input\n type=\"search\"\n className=\"assistant-convs-search\"\n value={words}\n placeholder={say('filterConversations')}\n aria-label={say('filterConversations')}\n onChange={(event) => setWords(event.target.value)}\n onKeyDown={onSearchKey}\n />\n {words && (\n <button\n type=\"button\"\n className=\"assistant-convs-clear\"\n aria-label={say('clearSearch')}\n title={say('clearSearch')}\n onClick={() => setWords('')}\n >\n <svg viewBox=\"0 0 16 16\" width=\"12\" height=\"12\" aria-hidden=\"true\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\">\n <path d=\"M4 4l8 8M12 4l-8 8\" />\n </svg>\n </button>\n )}\n </div>\n </div>\n {conversations.length === 0 && !term ? (\n <p className=\"assistant-empty\">{say('noConversations')}</p>\n ) : shown.length === 0 ? (\n <p className=\"assistant-empty\" role=\"status\">\n {settling ? '' : say('noMatches')}\n </p>\n ) : term ? (\n <ul className=\"assistant-conv-list\" aria-label={say('searchResults')}>\n {shown.map(row)}\n </ul>\n ) : (\n groups.map(({ group, rows }) => (\n <section key={group} className=\"assistant-conv-group\" aria-labelledby={`assistant-conv-${group}`}>\n <h3 id={`assistant-conv-${group}`} className=\"assistant-conv-heading\">\n {headingOf(group)}\n </h3>\n <ul className=\"assistant-conv-list\">{rows.map(row)}</ul>\n </section>\n ))\n )}\n {deleting && (\n <DeleteConversation\n conversation={deleting}\n onClose={() => setDeleting(null)}\n onConfirm={() => {\n const id = deleting.id;\n setDeleting(null);\n void onDelete(id);\n }}\n />\n )}\n </div>\n );\n}\n\n/** The title, edited where it is drawn: Enter keeps it, Escape leaves it as it was. */\nexport function RenameField({ title, onDone }: { title: string; onDone: (title: string | null) => void }) {\n const [value, setValue] = useState(title);\n const field = useRef<HTMLInputElement>(null);\n const done = useRef(false);\n const finish = (next: string | null) => {\n if (done.current) return;\n done.current = true;\n onDone(next === null ? null : next.replace(/\\s+/g, ' ').trim().slice(0, 200));\n };\n useEffect(() => {\n field.current?.focus();\n field.current?.select();\n }, []);\n return (\n <input\n ref={field}\n className=\"assistant-conv-rename\"\n value={value}\n maxLength={200}\n aria-label={say('renameLabel', { title })}\n onChange={(event) => setValue(event.target.value)}\n onBlur={() => finish(value)}\n onKeyDown={(event) => {\n if (event.key === 'Enter') {\n event.preventDefault();\n finish(value);\n } else if (event.key === 'Escape') {\n event.preventDefault();\n event.stopPropagation();\n finish(null);\n }\n }}\n />\n );\n}\n\n/* As a record's delete asks (DeleteButton.tsx): an App keeps no undo, so the person says so first. */\nexport function DeleteConversation({\n conversation,\n onClose,\n onConfirm,\n}: {\n conversation: ConversationSummary;\n onClose: () => void;\n onConfirm: () => void;\n}) {\n const dialog = useRef<ModalHandle>(null);\n return (\n <Modal\n className=\"confirm\"\n ref={dialog}\n onClose={onClose}\n fullscreen={false}\n ariaLabel={say('deleteConversation', { title: conversation.title })}\n >\n <h2>{say('deleteConversation', { title: conversation.title })}</h2>\n <p>{say('deleteConversationTerms')}</p>\n <div className=\"confirm-actions\">\n <Button intent=\"secondary\" onClick={() => dialog.current?.close()}>\n {say('common.cancel')}\n </Button>\n <Button intent=\"danger\" onClick={onConfirm}>\n {say('delete')}\n </Button>\n </div>\n </Modal>\n );\n}\n","/** What AssistantPanel says, in the shell room (packages/kit/src/client/messages.ts says how the catalog is split). */\nimport { defineMessages } from '@mistriwork/kit/client/messages.js';\n\nexport const say = defineMessages({\n assistant: 'Assistant',\n conversations: 'Conversations',\n newConversation: 'New conversation',\n emptyHint: 'Ask about your records: find them, sum them up, show them as a table or a chart. Changes are proposed for you to confirm.',\n about: 'About {label}',\n leaveOutRecord: 'Leave {label} out',\n message: 'Message the assistant',\n send: 'Send',\n stop: 'Stop',\n retry: 'Retry',\n tryAgain: 'Try again',\n edit: 'Edit',\n cancelEdit: 'Cancel edit',\n editing: 'Editing your message.',\n working: 'Working…',\n steps: { one: '{count} step', other: '{count} steps' },\n confirm: 'Confirm',\n review: 'Review and confirm',\n decline: 'Decline',\n reason: 'Reason',\n proposedChange: 'Proposed change',\n applied: 'Applied.',\n declined: 'Declined.',\n failed: 'Not applied: {detail}',\n failedPlain: 'Not applied.',\n waitingForYou: 'Waiting for you to confirm or decline.',\n stopped: 'Stopped.',\n couldNotAnswer: 'The assistant could not answer: {message}',\n connectionLost: 'The connection to the server dropped before the answer finished.',\n couldNotOpen: 'This conversation could not be opened: {message}',\n noModel: 'The assistant is not set up on this server yet.',\n close: 'Close the assistant',\n newRecord: 'New {resource}',\n expand: 'Full screen',\n collapse: 'Back to the side panel',\n starters: 'Try asking',\n editRecord: 'Edit',\n editRecordLabel: 'Edit {label}',\n recordActions: 'What you can do with {label}',\n conversationActions: 'Actions for “{title}”',\n rename: 'Rename',\n delete: 'Delete',\n});\n","/**\n * The in-App assistant (docs/assistant.md): a panel beside the page, not over\n * it — the person keeps reading and clicking the App while it answers — and\n * the whole page on a phone, where there is no beside.\n *\n * What it draws is data. The model's words are plain text with three marks\n * (bold, code, a link), and a link is followed only to an address inside the\n * App; its tables, figures and charts are dashboard sections the server\n * validated, drawn by the dashboard's own components; a record is the\n * record's values in the record form's shape. Nothing the model writes is\n * markup.\n *\n * Nothing it proposes happens here unasked. A proposal is a card; Confirm\n * runs it through the path the record's own button uses — a fixed edit\n * through /api/update, a command through its form, a new record through the\n * New form filled in — under the same checks, and the outcome is told back\n * to the assistant, which carries on.\n *\n * What it shows can be acted on as the App's own screens are: a record's card\n * carries the record's bar (Actions.tsx), and a table's rows the list's row\n * menu — the same verbs, the same grants, the same forms. Those are the\n * person's clicks; the model never makes them. What came of one is told to\n * the conversation (`/api/assistant/acted`), so the model reads it next turn.\n *\n * One component, three places: the panel beside the page, the panel full\n * screen over the content (remembered per person), and the App's assistant\n * room (`placement: 'page'`, `/{app}/assistant`) with the conversations as a\n * rail. Its chunk is loaded when the trigger is first pressed\n * (AssistantTrigger.tsx), or the room is first opened (Content.tsx).\n */\nimport {\n createElement,\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useId,\n useRef,\n useState,\n type KeyboardEvent,\n type ReactNode,\n} from 'react';\nimport { useQuery, useQueryClient } from '@tanstack/react-query';\nimport type { AppAction, AppCommandAction } from '../../shared/app.js';\nimport type { AppPayloadApp } from '../../shared/appPayload.js';\nimport { shown } from '@mistriwork/kit/client/addressMount.js';\nimport { activeApp } from '../appState.js';\nimport {\n api,\n columnLabel,\n currentEntry,\n findTable,\n go,\n humanName,\n labelPath,\n state,\n viewportBox,\n viewportSize,\n writeAllowed,\n} from '@mistriwork/kit/client/core.js';\nimport { grantedActionIds, mayRunAny } from '@mistriwork/kit/client/actionGrants.js';\nimport { sessionIdentity } from '@mistriwork/kit/client/sessionIdentity.js';\nimport { syncHash } from '@mistriwork/kit/client/url.js';\nimport { pageBridge } from '@mistriwork/kit/client/uiBridge.js';\nimport { assistantEntry } from '../publicAddress.js';\nimport type { TableMeta } from '@mistriwork/engine/shared/schema.js';\nimport { ActionBar, ActionOutcomes, type ActionOutcome as ActionOutcomeReport } from './Actions.js';\nimport { ASSISTANT_PAGE, dashViewKey, formViewKey, resourceOf } from '@mistriwork/kit/client/components/appRooms.js';\nimport { startersHere } from '../../shared/appAssistant.js';\nimport { rootMatches } from '@mistriwork/kit/client/components/pageModel.js';\nimport { formProps } from '@mistriwork/kit/client/insert.js';\nimport { ownedBy } from '@mistriwork/kit/client/requestIdentity.js';\nimport { pathEqualityFilter, recordKey as checkedRecordKey } from '@mistriwork/kit/client/resourceRequests.js';\nimport { updateAttempts } from '@mistriwork/kit/client/updateAttempts.js';\nimport type { CommandOperation } from '../commandState.js';\nimport {\n applyEvent,\n cutAt,\n grouped,\n inside,\n stream,\n waitingProposal,\n wordsOf,\n type AssistantBlock,\n type Run,\n type PanelItem,\n type Proposal,\n type ProposalOutcome,\n type StreamEvent,\n} from './assistantStream.js';\nimport { Button } from '@mistriwork/ui/Button.js';\nimport { assistantApi, assistantOwner } from './assistantRequest.js';\nimport { ConversationList, DeleteConversation, RenameField, type ConversationSummary } from './ConversationList.js';\nimport { DropItem, DropMenu } from '@mistriwork/ui/DropMenu.js';\nimport { CommandForm } from './CommandForm.js';\nimport { mount, unmount } from '@mistriwork/kit/client/components/mount.js';\nimport { NewRecordDialog } from '@mistriwork/kit/client/components/NewRecord.js';\nimport { onDemand } from '@mistriwork/kit/client/components/onDemand.js';\nimport { useWalk } from '@mistriwork/kit/client/components/walk.js';\nimport { RefJump, Value } from '@mistriwork/kit/client/components/Value.js';\nimport { referenceProjection } from '@mistriwork/engine/shared/referenceModel.js';\nimport type { DashboardDef } from '@mistriwork/kit/client/components/dashboardModel.js';\nimport { say } from '../copy/shell/components/AssistantPanel.js';\nimport './AssistantPanel.css';\nimport { addHostListener, navFollow, portalRoot, removeHostListener, shellById } from '@mistriwork/kit/client/shellHost.js';\n\nconst Dashboard = onDemand(() => import('./Dashboard.js'), 'Dashboard');\n\ntype Summary = ConversationSummary;\n\n/* Where the person was, kept while the page is: closing the panel and opening it again returns to the same conversation. */\n/* The panel reopens on the conversation it last showed, for the person and in the customer it was shown to. */\nlet lastConversation: { owner: string; id: string | null } = { owner: '', id: null };\n\nconst LIST_QUERY = 'assistant-conversations';\nconst phone = () => typeof window.matchMedia === 'function' && window.matchMedia('(max-width: 640px)').matches;\n\n/** An address inside the App, followed without a reload: the shell's own navigation listener paints it. */\nfunction follow(address: string): void {\n navFollow(shown(address));\n}\n\n/** Follows an inside link in the page; a modified click is the browser's (a new tab). */\nfunction Link({ to, children, onFollow }: { to: string; children: ReactNode; onFollow: (address: string) => void }) {\n return (\n <a\n href={shown(to)}\n onClick={(event) => {\n if (event.metaKey || event.ctrlKey || event.shiftKey || event.button !== 0) return;\n event.preventDefault();\n onFollow(to);\n }}\n >\n {children}\n </a>\n );\n}\n\n/** The model's words, drawn from their runs (assistantStream.ts `wordsOf`). */\nfunction Words({ text, onFollow }: { text: string; onFollow: (address: string) => void }) {\n const draw = (runs: Run[]) =>\n runs.map((run, at) =>\n 'link' in run ? (\n <Link key={at} to={run.link} onFollow={onFollow}>\n {run.text}\n </Link>\n ) : run.mark === 'strong' ? (\n <strong key={at}>{run.text}</strong>\n ) : run.mark === 'code' ? (\n <code key={at}>{run.text}</code>\n ) : (\n run.text\n ),\n );\n return (\n <>\n {wordsOf(text).map((paragraph, p) =>\n paragraph.list ? (\n <ul key={p}>\n {paragraph.lines.map((line, l) => (\n <li key={l}>{draw(line)}</li>\n ))}\n </ul>\n ) : (\n <p key={p}>{paragraph.lines.flatMap((line, l) => (l ? [<br key={`br${l}`} />, ...draw(line)] : draw(line)))}</p>\n ),\n )}\n </>\n );\n}\n\n/** Whether the App's list over a table offers a menu on each row (`rowActions`): a chat table of it offers the same. */\n/* A table drawn here offers its rows' menus where one of the App's views over it does, and only to a reader with a verb to run. */\nfunction rowActionsOn(tableId: unknown): boolean {\n const app = activeApp() as AppPayloadApp | null;\n if (typeof tableId !== 'string') return false;\n return (\n Object.values(app?.views ?? {}).some(\n (view) => (view as { table?: string; rowActions?: true }).table === tableId && (view as { rowActions?: true }).rowActions === true,\n ) && mayRunAny(app, tableId, (resourceOf(app, tableId)?.actions ?? []) as AppAction[])\n );\n}\n\n/** A block the server validated, drawn by the App's own components. */\nfunction Block({ block, onFollow }: { block: AssistantBlock; onFollow: (address: string) => void }) {\n const dashboard = useMemo(() => {\n if (block.kind !== 'section') return null;\n /* A table's rows open their records, and — where the App's list over the table offers it — carry the list's own row menu. */\n const section =\n block.section.kind === 'rows' && rowActionsOn(block.section.table) ? { ...block.section, rowActions: true } : block.section;\n return { id: 'assistant', label: String(section.title ?? ''), sections: [section] } as unknown as DashboardDef;\n }, [block]);\n if (dashboard) {\n return (\n <div className=\"assistant-block assistant-section\">\n <Dashboard dashboard={dashboard} />\n </div>\n );\n }\n if (block.kind !== 'record') return null;\n return <RecordCard block={block} onFollow={onFollow} />;\n}\n\n/**\n * One record, as the peek card draws it, with the record's own bar under it:\n * the verbs its page would offer this person for its state now, each through\n * the page's own path (Actions.tsx), and Edit where they may write it — the\n * record's own form, in its dialog. After a verb the card reads the record\n * again, so it says what the record now is.\n */\n/* A field on a record card: a reference by its record's name (as the glance\n draws it), a long single line cut with an ellipsis and its whole in the\n title (as the grid does), anything else as the record page says it. */\nfunction CardValue({\n column,\n table,\n name,\n value,\n label,\n tableId,\n row,\n}: {\n column: TableMeta['columns'][number] | undefined;\n table: TableMeta | undefined;\n name: string;\n value: unknown;\n label: unknown;\n tableId: string;\n row: Record<string, unknown>;\n}) {\n if (column?.references && table && value !== null && value !== undefined && String(value) !== '')\n return <RefJump references={column.references} value={value} label={label} table={table} column={name} row={row} />;\n return <Value col={column} value={value} tableId={tableId} compact links={false} />;\n}\n\nfunction RecordCard({ block, onFollow }: { block: Extract<AssistantBlock, { kind: 'record' }>; onFollow: (address: string) => void }) {\n const app = activeApp() as AppPayloadApp | null;\n const table = findTable(block.table) as TableMeta | undefined;\n const queryClient = useQueryClient();\n const connection = state.activeConnection ?? undefined;\n const actions = (resourceOf(app, block.table)?.actions ?? []) as AppAction[];\n const editable = Boolean(table) && writeAllowed(block.table);\n const runnable = mayRunAny(app, block.table, actions);\n /* The card reads its record the way a glance does (PeekPanel): the fields\n it shows plus each reference's name, one row by its key. An action or an\n edit invalidates every query, this one with them, so the card re-reads\n to what the record is now. Until the read lands it says what the tool said. */\n const names = Object.keys(block.values);\n const projection = table ? referenceProjection(state.schema, table, names, true, labelPath) : undefined;\n const read = useQuery<Record<string, unknown> | null>({\n queryKey: ['assistant-record', connection ?? '', block.table, JSON.stringify(block.key)],\n enabled: Boolean(table && projection),\n queryFn: async () => {\n const data = (await api('/api/view/run', {\n view: {\n id: `assistant:${block.table}`,\n name: table!.name,\n base: table!.id,\n columns: projection!.fetched.map((path) => ({ path })),\n filter: pathEqualityFilter(block.key),\n limit: 1,\n },\n })) as { rows?: Array<Record<string, unknown>> };\n return data.rows?.[0] ?? null;\n },\n retry: false,\n });\n const row = read.data ?? undefined;\n const values = row\n ? Object.fromEntries(names.map((name) => [name, Object.hasOwn(row, name) ? row[name] : block.values[name]]))\n : block.values;\n const refLabel = (name: string) => {\n const at = projection?.labels.get(name);\n return row && at !== undefined ? row[at] : undefined;\n };\n const reread = () => void queryClient.invalidateQueries();\n // Big ids arrive as strings and stay strings (CLAUDE.md, values that are not numbers).\n const columns = table?.columns ?? [];\n const fields = Object.entries(values)\n .filter(([name]) => !columns.find((column) => column.name === name)?.primaryKey)\n .slice(0, 10);\n return (\n <div className=\"assistant-block assistant-record\">\n <div className=\"assistant-record-title\">\n {block.address && inside(block.address) ? (\n <Link to={block.address} onFollow={onFollow}>\n {block.title}\n </Link>\n ) : (\n block.title\n )}\n </div>\n <dl className=\"peekpanel-fields\">\n {fields.map(([name, value]) => (\n <div className=\"field\" key={name}>\n <dt>{columnLabel(block.table, name) ?? humanName(name)}</dt>\n <dd title={typeof value === 'string' && !columns.find((column) => column.name === name)?.references ? value : undefined}>\n <CardValue\n column={columns.find((column) => column.name === name)}\n table={table}\n name={name}\n value={value}\n label={refLabel(name)}\n tableId={block.table}\n row={values}\n />\n </dd>\n </div>\n ))}\n </dl>\n {table && (editable || runnable) && (\n <div className=\"assistant-record-actions\" role=\"group\" aria-label={say('recordActions', { label: block.title })}>\n {actions.length > 0 && (\n <ActionBar\n tableId={block.table}\n actions={actions}\n recordKey={block.key}\n label={block.title}\n matches={(when) => rootMatches(table, block.key, when, connection)}\n canUpdate={writeAllowed(block.table)}\n grantedCommands={app?.grantedCommands ?? []}\n grantedActions={grantedActionIds(app, block.table)}\n onDone={reread}\n />\n )}\n {editable && pageBridge.openPeek && (\n <Button\n className=\"page-action\"\n aria-label={say('editRecordLabel', { label: block.title })}\n onClick={() => pageBridge.openPeek!(block.table, { ...block.key }, block.title, 'modal')}\n >\n {say('editRecord')}\n </Button>\n )}\n </div>\n )}\n </div>\n );\n}\n\nfunction Steps({ steps, running }: { steps: Extract<PanelItem, { type: 'step' }>[]; running?: string }) {\n return (\n <details className=\"assistant-steps\">\n <summary>{running ?? say('steps', { count: steps.length })}</summary>\n <ol>\n {steps.map((step) => (\n <li key={step.id} className={step.failed ? 'assistant-step-failed' : undefined}>\n {step.label}\n </li>\n ))}\n </ol>\n </details>\n );\n}\n\nconst outcomeWords = (outcome: ProposalOutcome) =>\n outcome.status === 'done'\n ? say('applied')\n : outcome.status === 'declined'\n ? say('declined')\n : outcome.detail\n ? say('failed', { detail: outcome.detail })\n : say('failedPlain');\n\ninterface CardProps {\n proposal: Proposal;\n outcome?: ProposalOutcome;\n live: boolean;\n onResolve: (outcome: ProposalOutcome) => void;\n onFollow: (address: string) => void;\n}\n\n/** A proposed change: what, to which record, and why — and nothing done until Confirm. */\nfunction ProposalCard({ proposal, outcome, live, onResolve, onFollow }: CardProps) {\n const app = activeApp() as AppPayloadApp | null;\n const action = (app?.resources[proposal.resource]?.actions as AppAction[] | undefined)?.find((each) => each.id === proposal.action);\n const reasonColumn =\n action && !action.command && typeof (action as { reason?: unknown }).reason === 'string'\n ? (action as { reason: string }).reason\n : undefined;\n const [reason, setReason] = useState(() =>\n reasonColumn && typeof proposal.values[reasonColumn] === 'string' ? String(proposal.values[reasonColumn]) : '',\n );\n const [busy, setBusy] = useState(false);\n const [commandOpen, setCommandOpen] = useState(false);\n const queryClient = useQueryClient();\n const settled = (result: ProposalOutcome) => {\n setBusy(false);\n if (result.status === 'done') void queryClient.invalidateQueries();\n onResolve(result);\n };\n\n const confirmSet = async () => {\n if (!action || action.command || !proposal.key) return settled({ status: 'failed', detail: say('failedPlain') });\n const values = {\n ...(action as { set: Record<string, string | number | boolean | null> }).set,\n ...(reasonColumn ? { [reasonColumn]: reason.trim() } : {}),\n };\n const owner = { connection: state.activeConnection ?? null, table: proposal.resource, key: { ...proposal.key } };\n setBusy(true);\n try {\n const key = checkedRecordKey(owner.key);\n const result = await updateAttempts.run(owner, values, () =>\n api('/api/update', { ...ownedBy(owner.connection), table: owner.table, key, values }),\n );\n settled(result.kind === 'applied' ? { status: 'done' } : { status: 'failed', detail: result.message });\n } catch (error) {\n settled({ status: 'failed', detail: error instanceof Error ? error.message : undefined });\n }\n };\n\n const confirmNew = () => {\n const table = findTable(proposal.resource);\n if (!table) return settled({ status: 'failed', detail: say('failedPlain') });\n const view = Object.values(app?.views ?? {}).find(\n (each) => (each as { table?: string; form?: unknown }).table === proposal.resource && (each as { form?: unknown }).form,\n ) as { form?: { defaults?: Record<string, unknown> } } | undefined;\n const form = { ...(view?.form ?? {}), defaults: { ...(view?.form?.defaults ?? {}), ...proposal.values } };\n const host = document.createElement('div');\n host.className = 'insert-host';\n portalRoot().append(host);\n let added = false;\n setBusy(true);\n const close = () => {\n unmount(host);\n host.remove();\n // The form closes before it reports what it added; a close with nothing added is the person stepping back.\n queueMicrotask(() => {\n if (!added) setBusy(false);\n });\n };\n mount(\n host,\n createElement(\n NewRecordDialog,\n formProps(\n table,\n form as never,\n host,\n close,\n () => {\n added = true;\n settled({ status: 'done' });\n },\n { app: true },\n ),\n ),\n );\n };\n\n const confirm = () => {\n if (proposal.kind === 'set') void confirmSet();\n else if (proposal.kind === 'command') setCommandOpen(true);\n else confirmNew();\n };\n const command = action?.command ? (action as AppCommandAction) : undefined;\n const values = Object.entries(proposal.values).filter(([name]) => name !== reasonColumn);\n return (\n <section className={`assistant-proposal${outcome ? ` assistant-proposal-${outcome.status}` : ''}`} aria-label={say('proposedChange')}>\n <div className=\"assistant-proposal-head\">\n <span className=\"assistant-proposal-verb\">\n {proposal.kind === 'new'\n ? say('newRecord', { resource: findTable(proposal.resource)?.name ?? proposal.resource })\n : proposal.label}\n </span>\n {proposal.record &&\n (proposal.address && inside(proposal.address) ? (\n <Link to={proposal.address} onFollow={onFollow}>\n {proposal.record}\n </Link>\n ) : (\n <span>{proposal.record}</span>\n ))}\n </div>\n {proposal.why && <p className=\"assistant-proposal-why\">{proposal.why}</p>}\n {values.length > 0 && (\n <dl className=\"assistant-proposal-values\">\n {values.map(([name, value]) => (\n <div key={name}>\n <dt>{columnLabel(proposal.resource, name) ?? humanName(name)}</dt>\n <dd>\n <Value\n col={findTable(proposal.resource)?.columns.find((column) => column.name === name)}\n value={value}\n tableId={proposal.resource}\n compact\n links={false}\n />\n </dd>\n </div>\n ))}\n </dl>\n )}\n {outcome ? (\n <p className=\"assistant-proposal-outcome\">{outcomeWords(outcome)}</p>\n ) : live ? (\n <>\n {reasonColumn && (\n <label className=\"assistant-proposal-reason\">\n <span>{columnLabel(proposal.resource, reasonColumn) ?? say('reason')}</span>\n <textarea rows={2} value={reason} onChange={(event) => setReason(event.target.value)} disabled={busy} />\n </label>\n )}\n <div className=\"assistant-proposal-actions\">\n <Button intent=\"primary\" onClick={confirm} disabled={busy || (reasonColumn !== undefined && !reason.trim())}>\n {proposal.kind === 'set' ? say('confirm') : say('review')}\n </Button>\n <Button onClick={() => settled({ status: 'declined' })} disabled={busy}>\n {say('decline')}\n </Button>\n </div>\n </>\n ) : null}\n {commandOpen && command && proposal.key && (\n <CommandForm\n action={command}\n owner={{\n connection: state.activeConnection ?? '',\n target: command.command.target,\n command: command.command.id,\n commandVersion: command.command.version,\n key: { ...proposal.key },\n }}\n label={proposal.record ?? proposal.label}\n initial={proposal.values}\n onDone={() => {}}\n onClose={(operation?: CommandOperation) => {\n setCommandOpen(false);\n if (operation?.phase === 'success') settled({ status: 'done' });\n else if (operation?.phase === 'error') settled({ status: 'failed', detail: operation.message });\n }}\n />\n )}\n </section>\n );\n}\n\n/* Full screen is a per-person preference, kept on this device: the panel opens the way it was last left. */\nconst expandedKey = (app: string) => `mistri.assistant.expanded.${app}.${sessionIdentity().accountId ?? 'local'}`;\nfunction readExpanded(app: string): boolean {\n try {\n return window.localStorage.getItem(expandedKey(app)) === '1';\n } catch {\n return false;\n }\n}\nfunction writeExpanded(app: string, on: boolean): void {\n try {\n if (on) window.localStorage.setItem(expandedKey(app), '1');\n else window.localStorage.removeItem(expandedKey(app));\n } catch {\n /* Remembered where the browser lets it be; the panel works either way. */\n }\n}\n\n/** Whether the screen is a phone's, kept current as it turns or resizes. */\nfunction usePhone(): boolean {\n const [on, setOn] = useState(phone);\n useEffect(() => {\n if (typeof window.matchMedia !== 'function') return;\n const query = window.matchMedia('(max-width: 640px)');\n const changed = () => setOn(query.matches);\n query.addEventListener?.('change', changed);\n return () => query.removeEventListener?.('change', changed);\n }, []);\n return on;\n}\n\n/* Full screen's mark, drawn here so it rides this chunk and nothing of it is in a first page: corners out, or back in. */\nfunction Corners({ inward }: { inward: boolean }) {\n return (\n <svg className=\"icon\" viewBox=\"0 0 16 16\" width=\"16\" height=\"16\" aria-hidden=\"true\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\">\n <path\n d={inward ? 'M6 2.5V6H2.5M10 2.5V6h3.5M13.5 10H10v3.5M2.5 10H6v3.5' : 'M2.5 6V2.5H6M10 2.5h3.5V6M13.5 10v3.5H10M6 13.5H2.5V10'}\n />\n </svg>\n );\n}\n\n/* The room's Conversations control on a phone: a pane with its list at the side, drawn here so it rides this chunk. */\nfunction ListMark() {\n return (\n <svg className=\"icon\" viewBox=\"0 0 16 16\" width=\"16\" height=\"16\" aria-hidden=\"true\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\">\n <rect x=\"2\" y=\"2.75\" width=\"12\" height=\"10.5\" rx=\"1.5\" />\n <path d=\"M6.25 2.75v10.5\" />\n </svg>\n );\n}\n\n/* The composer grows with what is typed, from one line to about eight, then scrolls. */\nconst COMPOSE_MAX = 192;\n\ninterface AssistantProps {\n app: string;\n /** The App lets the assistant read the open record as the turn's context. */\n record: boolean;\n /** Beside the page (the trigger's), or the App's assistant room. */\n mode: 'panel' | 'page';\n /** The panel's close; the room has none, it is left as any room is. */\n onClose?: () => void;\n /** The room's conversation, from its address; the panel keeps the last one it showed. */\n conversation?: string;\n}\n\n/** The trigger's panel, beside the page or full screen over its content. */\nexport function AssistantPanel({ app, record, onClose }: { app: string; record: boolean; onClose: () => void }) {\n // Another customer, or another person, is another history: the panel starts again in it.\n return <Assistant key={assistantOwner()} app={app} record={record} mode=\"panel\" onClose={onClose} />;\n}\n\n/** The App's assistant room (`placement: 'page'`), on the conversation its address names. */\nexport function AssistantRoom({ conversation }: { conversation?: string }) {\n const app = activeApp() as AppPayloadApp | null;\n if (!app?.assistant?.page) return null;\n return (\n <Assistant key={`${assistantOwner()}\\n${conversation ?? ''}`} app={app.id} record={false} mode=\"page\" conversation={conversation} />\n );\n}\n\nfunction Assistant({ app, record, mode, onClose, conversation: addressed }: AssistantProps) {\n const room = mode === 'page';\n const owner = assistantOwner();\n const [conversation, setConversation] = useState<string | null>(\n room ? (addressed ?? null) : lastConversation.owner === owner ? lastConversation.id : null,\n );\n const [started, setStarted] = useState<string | null>(null);\n const [items, setItems] = useState<PanelItem[]>([]);\n const [listing, setListing] = useState(false);\n const [text, setText] = useState('');\n const [editing, setEditing] = useState<number | null>(null);\n const [busy, setBusy] = useState(false);\n const [running, setRunning] = useState<string | undefined>();\n /* What went wrong, and the way on from it: `again` for a turn cut off on the way, `fresh` for a conversation this\n person may not open (a field report's panel stayed blank over a 403 it never said). */\n const [problem, setProblem] = useState<{ text: string; again?: true; fresh?: true } | null>(null);\n /* The last turn sent, and whether the server had kept the person's words before it was cut off: kept, it is retried\n from them; not, the same request is sent again. */\n const sent = useRef<{ path: '/api/assistant/turn' | '/api/assistant/resolve'; request: Record<string, unknown>; kept: boolean } | null>(\n null,\n );\n const [withRecord, setWithRecord] = useState(true);\n const [renamingTitle, setRenamingTitle] = useState(false);\n const [deletingOpen, setDeletingOpen] = useState(false);\n const [expanded, setExpanded] = useState(() => !room && readExpanded(app));\n const onPhone = usePhone();\n const wide = room || (expanded && !onPhone);\n const stop = useRef<AbortController | null>(null);\n const body = useRef<HTMLDivElement>(null);\n const box = useRef<HTMLTextAreaElement>(null);\n const frame = useRef<HTMLElement>(null);\n const queryClient = useQueryClient();\n const walk = useWalk();\n const top = walk[walk.length - 1];\n const context =\n record && (top?.kind === 'row' || top?.kind === 'page') && top.table && top.key\n ? { resource: top.table, key: top.key, label: top.label ?? top.table }\n : undefined;\n /* The App's starters for where the person is: its bare lines everywhere, a scoped one in its view's room or on a\n record of its table (appAssistant.ts). The room is the walk's top: a list's view, a dashboard's or a form's page. */\n const starters = startersHere((activeApp() as AppPayloadApp | null)?.assistant?.starters, {\n ...(top?.kind === 'table' && top.view ? { view: top.view } : {}),\n ...(top?.kind === 'page' && !top.key ? { view: dashViewKey(top.pageId) ?? formViewKey(top.pageId) } : {}),\n ...((top?.kind === 'row' || top?.kind === 'page') && top.table && top.key ? { record: top.table } : {}),\n });\n\n const conversations = useQuery({\n queryKey: [LIST_QUERY, app, owner],\n queryFn: async () =>\n (await assistantApi(`/api/assistant?app=${encodeURIComponent(app)}`)) as { conversations: Summary[]; ready: boolean },\n });\n const opened = useQuery({\n queryKey: ['assistant-conversation', app, owner, conversation],\n // Not the one this panel's own turn just started: its items are already here.\n enabled: conversation !== null && conversation !== started,\n staleTime: Infinity,\n queryFn: async () =>\n (await assistantApi(`/api/assistant/conversation?app=${encodeURIComponent(app)}&id=${encodeURIComponent(conversation!)}`)) as {\n items: PanelItem[];\n },\n });\n useEffect(() => {\n if (opened.data && Array.isArray(opened.data.items) && !busy) setItems(opened.data.items);\n // Only when a conversation is (re)opened: a live turn's items are the panel's own.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [opened.data]);\n useEffect(() => {\n if (!room) lastConversation = { owner, id: conversation };\n }, [room, conversation]);\n // A conversation that is gone (deleted in another tab, or another account's) starts a new one —\n // unless this panel's own turn has since answered for it. One refused is said, with the way out.\n useEffect(() => {\n if (!opened.isError || conversation === started) return;\n if ((opened.error as { status?: number } | null)?.status !== 404) {\n setProblem({ text: say('couldNotOpen', { message: opened.error.message }), fresh: true });\n return;\n }\n if (room) go(assistantEntry(), 'replace');\n else setConversation(null);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [opened.isError, room]);\n useEffect(() => () => stop.current?.abort(), []);\n useEffect(() => {\n box.current?.focus();\n }, [conversation, listing]);\n // The newest words stay in view while they arrive, unless the person has scrolled up to read.\n const pinned = useRef(true);\n useEffect(() => {\n const view = body.current;\n if (view && pinned.current) view.scrollTop = view.scrollHeight;\n }, [items, running]);\n /* A block's rows, a card's fields and the composer's note arrive after the words do; a reader at the foot stays\n at the foot as they settle, rather than left reading whatever they pushed up. */\n useEffect(() => {\n const view = body.current;\n if (!view || typeof ResizeObserver !== 'function') return;\n const keep = new ResizeObserver(() => {\n if (pinned.current) view.scrollTop = view.scrollHeight;\n });\n keep.observe(view);\n for (const child of view.children) keep.observe(child);\n return () => keep.disconnect();\n }, [items]);\n\n /* The box is as tall as its words, to a limit: measured from its content each time they change. */\n useLayoutEffect(() => {\n const field = box.current;\n if (!field) return;\n field.style.height = '';\n const natural = field.scrollHeight;\n if (!natural) return;\n field.style.height = `${Math.min(natural + field.offsetHeight - field.clientHeight, COMPOSE_MAX)}px`;\n field.style.overflowY = natural > COMPOSE_MAX ? 'auto' : 'hidden';\n }, [text]);\n\n /* Full screen fills the content column — beside the App's menu, never over it — and the page beneath does\n not move: the panel is fixed, and only its own left edge changes. Measured on the zoom-aware ruler. */\n useLayoutEffect(() => {\n const panel = frame.current;\n if (room || !panel) return;\n if (!wide) {\n panel.style.removeProperty('--assistant-left');\n return;\n }\n const place = () => {\n const content = shellById('content');\n panel.style.setProperty('--assistant-left', `${content ? Math.max(0, Math.round(viewportBox(content).left)) : 0}px`);\n };\n place();\n addHostListener(window, 'resize', place);\n return () => removeHostListener(window, 'resize', place);\n }, [room, wide]);\n /* The room stands from where it begins to the foot of the window, so the composer sits at the bottom. */\n useLayoutEffect(() => {\n const panel = frame.current;\n if (!room || !panel) return;\n const fit = () => {\n panel.style.height = `${Math.max(320, Math.floor(viewportSize().height - viewportBox(panel).top))}px`;\n };\n fit();\n addHostListener(window, 'resize', fit);\n return () => removeHostListener(window, 'resize', fit);\n }, [room]);\n\n const toggleExpanded = () => {\n setExpanded((was) => {\n writeExpanded(app, !was);\n return !was;\n });\n };\n\n /* A conversation this room's own turn started: the address says it from now on, without leaving the room. */\n const adopt = (id: string) => {\n setStarted(id);\n setConversation(id);\n if (!room) return;\n const here = currentEntry() as { kind?: string; pageId?: string; tab?: string } | undefined;\n if (here?.kind === 'page' && here.pageId === ASSISTANT_PAGE && here.tab !== id) {\n here.tab = id;\n syncHash();\n }\n };\n\n const run = useCallback(\n async (path: '/api/assistant/turn' | '/api/assistant/resolve', request: Record<string, unknown>) => {\n const controller = new AbortController();\n stop.current = controller;\n const turn = { path, request, kept: false };\n sent.current = turn;\n setBusy(true);\n setProblem(null);\n /* Said at once and kept still: the server reads the App and the catalog before its first event, and a field\n report waited seventy seconds under a bare question. Then each tool says what it is doing as it runs. */\n setRunning(say('working'));\n pinned.current = true;\n try {\n await stream(\n path,\n { app, ...request },\n (event: StreamEvent) => {\n if (event.event === 'conversation' && typeof event.data.id === 'string') adopt(event.data.id);\n if (event.event === 'conversation' && typeof event.data.person === 'number') turn.kept = true;\n if (event.event === 'running') setRunning(typeof event.data.label === 'string' ? event.data.label : say('working'));\n // Between steps the model is at work again; once it writes, its words are the sign.\n if (event.event === 'step') setRunning(say('working'));\n if (event.event === 'text' || event.event === 'done') setRunning(undefined);\n if (event.event === 'error' && typeof event.data.message === 'string')\n setProblem({ text: say('couldNotAnswer', { message: event.data.message }) });\n setItems((now) => applyEvent(now, event));\n },\n controller.signal,\n );\n } catch (error) {\n if (!controller.signal.aborted)\n setProblem(\n (error as { lost?: boolean } | null)?.lost\n ? { text: say('connectionLost'), again: true }\n : { text: say('couldNotAnswer', { message: error instanceof Error ? error.message : String(error) }) },\n );\n } finally {\n if (controller.signal.aborted)\n setItems((now) => [...applyEvent(now, { event: 'done', data: {} }), { type: 'note', text: say('stopped') }]);\n stop.current = null;\n setBusy(false);\n setRunning(undefined);\n void queryClient.invalidateQueries({ queryKey: [LIST_QUERY, app] });\n }\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [app, queryClient, room],\n );\n\n const say_ = (said: string) => {\n if (!said || busy) return;\n let next = items;\n const request: Record<string, unknown> = { text: said, ...(conversation ? { conversation } : {}) };\n if (editing !== null) {\n const at = items.findIndex((item) => item.type === 'person' && item.seq === editing);\n if (at >= 0) next = cutAt(items, at);\n request.edit = editing;\n }\n if (context && withRecord) request.context = { resource: context.resource, key: context.key };\n setItems([...next, { type: 'person', text: said }]);\n setText('');\n setEditing(null);\n void run('/api/assistant/turn', request);\n };\n const send = () => say_(text.trim());\n const retry = () => {\n const at = items.map((item) => item.type).lastIndexOf('person');\n if (at < 0 || !conversation) return;\n setItems([...cutAt(items, at), items[at]]);\n void run('/api/assistant/turn', { conversation, text: (items[at] as { text: string }).text, retry: true });\n };\n /* A turn cut off on the way, tried again: from the person's words if the server kept them, else sent as it was. */\n const again = () => {\n const turn = sent.current;\n if (!turn || busy) return;\n if (turn.path === '/api/assistant/turn' && turn.kept && conversation) return retry();\n void run(turn.path, turn.request);\n };\n const resolve = (proposal: Proposal, outcome: ProposalOutcome) => {\n if (!conversation) return;\n setItems((now) => now.map((item) => (item.type === 'proposal' && item.id === proposal.id ? { ...item, outcome } : item)));\n void run('/api/assistant/resolve', {\n conversation,\n proposal: proposal.id,\n outcome: outcome.status,\n ...(outcome.detail ? { detail: outcome.detail } : {}),\n });\n };\n /* A verb the person ran from a card or a row here: told to the conversation, drawn as its note. */\n const live = useRef(conversation);\n live.current = conversation;\n const acted = useCallback(\n (report: { tableId: string; key: Record<string, unknown>; label: string; action: AppAction; outcome: ActionOutcomeReport }) => {\n const id = live.current;\n if (!id) return;\n void (async () => {\n try {\n const answer = (await assistantApi('/api/assistant/acted', {\n app,\n conversation: id,\n resource: report.tableId,\n action: report.action.id,\n key: report.key,\n record: report.label,\n outcome: report.outcome.status,\n ...(report.outcome.detail ? { detail: report.outcome.detail } : {}),\n })) as { item?: PanelItem };\n if (answer.item && live.current === id) {\n pinned.current = true;\n setItems((now) => [...now, answer.item!]);\n }\n } catch {\n /* The verb ran or did not on its own; only the conversation's note of it is missing. */\n }\n })();\n },\n [app],\n );\n const open = (id: string) => {\n stop.current?.abort();\n setListing(false);\n if (room) {\n go(assistantEntry(id), 'push');\n return;\n }\n setStarted(null);\n setConversation(id);\n void queryClient.invalidateQueries({ queryKey: ['assistant-conversation', app, owner, id] });\n };\n const startNew = () => {\n stop.current?.abort();\n setListing(false);\n if (room) {\n if (conversation) go(assistantEntry(), 'push');\n return;\n }\n setConversation(null);\n setItems([]);\n setEditing(null);\n setProblem(null);\n };\n const remove = async (id: string) => {\n await assistantApi('/api/assistant/delete', { app, conversation: id });\n if (id === conversation) {\n if (room) go(assistantEntry(), 'replace');\n else startNew();\n }\n void queryClient.invalidateQueries({ queryKey: [LIST_QUERY, app] });\n void queryClient.invalidateQueries({ queryKey: ['assistant-search', app] });\n };\n const rename = async (id: string, title: string) => {\n // Drawn at once; the list read again says what the server kept.\n queryClient.setQueryData([LIST_QUERY, app, owner], (was: { conversations: Summary[]; ready: boolean } | undefined) =>\n was ? { ...was, conversations: was.conversations.map((each) => (each.id === id ? { ...each, title } : each)) } : was,\n );\n try {\n await assistantApi('/api/assistant/rename', { app, conversation: id, title });\n } finally {\n void queryClient.invalidateQueries({ queryKey: [LIST_QUERY, app] });\n void queryClient.invalidateQueries({ queryKey: ['assistant-search', app] });\n }\n };\n const onFollow = (address: string) => {\n follow(address);\n if (!room && (onPhone || wide)) onClose?.();\n };\n const onKey = (event: KeyboardEvent<HTMLTextAreaElement>) => {\n if (event.key === 'Enter' && !event.shiftKey && !event.nativeEvent.isComposing) {\n event.preventDefault();\n send();\n } else if (event.key === 'ArrowUp' && !text) {\n // Up in an empty box takes the last thing said back to edit, as a chat does.\n const last = [...items].reverse().find((item): item is Extract<PanelItem, { type: 'person' }> => item.type === 'person');\n if (last?.seq !== undefined && !busy && !waitingProposal(items)) {\n event.preventDefault();\n setEditing(last.seq);\n setText(last.text);\n }\n }\n };\n const onPanelKey = (event: KeyboardEvent<HTMLElement>) => {\n if (event.key !== 'Escape' || event.defaultPrevented) return;\n if (busy) {\n event.preventDefault();\n stop.current?.abort();\n } else if (editing !== null) {\n event.preventDefault();\n setEditing(null);\n setText('');\n } else if (listing) {\n event.preventDefault();\n setListing(false);\n } else if (!room && wide) {\n // Full screen steps back to the side panel first, the focus where it was.\n event.preventDefault();\n toggleExpanded();\n } else if (!room) {\n event.preventDefault();\n onClose?.();\n }\n };\n\n const waiting = waitingProposal(items);\n const waitingNote = useId();\n const lastPerson = items.map((item) => item.type).lastIndexOf('person');\n const ready = conversations.data?.ready !== false;\n const drawn = grouped(items);\n const list = (\n <ConversationList\n app={app}\n conversations={conversations.data?.conversations ?? []}\n current={conversation}\n working={busy ? conversation : null}\n onOpen={open}\n onNew={startNew}\n onRename={rename}\n onDelete={remove}\n />\n );\n const Frame = room ? 'section' : 'aside';\n const Title = room ? 'h1' : 'h2';\n /* The room is headed by the conversation it shows, once it has one; a new one is the Assistant. */\n const titled = room && conversation ? conversations.data?.conversations.find((each) => each.id === conversation) : undefined;\n const heading = titled?.title || say('assistant');\n const starting = ready && items.length === 0 && !(conversation && opened.isPending);\n const canSend = Boolean(text.trim()) && ready && !waiting;\n return (\n <Frame\n ref={frame as never}\n id={room ? 'assistant-room' : 'assistant-panel'}\n className={`${room ? 'assistant-room' : 'assistant-panel'}${wide ? ' assistant-wide' : ''}${!room && wide ? ' assistant-panel-expanded' : ''}${room && listing ? ' assistant-room-listing' : ''}${(starting || !ready) && !(listing && !room) ? ' assistant-starting' : ''}`}\n {...(room ? {} : { role: 'complementary' })}\n aria-label={say('assistant')}\n onKeyDown={onPanelKey}\n >\n {room && (\n <nav className=\"assistant-rail\" aria-label={say('conversations')}>\n {list}\n </nav>\n )}\n {/* On a phone the rail is a sheet over the conversation, which stays in sight; a press beside it closes it. */}\n {room && listing && <div className=\"assistant-rail-scrim\" aria-hidden=\"true\" onClick={() => setListing(false)} />}\n <div className=\"assistant-main\">\n <div className=\"assistant-head\">\n {/* The room's conversations on a phone, where the rail is a sheet: the head's first control, as a drawer's is. */}\n {room && (\n <button\n type=\"button\"\n className=\"btn ghost btn-compact assistant-rail-toggle\"\n aria-pressed={listing}\n title={say('conversations')}\n onClick={() => setListing((was) => !was)}\n >\n <ListMark />\n <span className=\"visually-hidden\">{say('conversations')}</span>\n </button>\n )}\n {room && titled && renamingTitle ? (\n <RenameField\n title={titled.title}\n onDone={(title) => {\n setRenamingTitle(false);\n if (title && title !== titled.title) void rename(titled.id, title);\n }}\n />\n ) : (\n <Title className=\"assistant-title\">\n <span className=\"assistant-title-words\" title={titled ? heading : undefined}>\n {heading}\n </span>\n </Title>\n )}\n {room && titled && !renamingTitle && (\n <DropMenu\n className=\"assistant-title-menu\"\n triggerClassName=\"assistant-conv-more\"\n triggerTitle={say('conversationActions', { title: titled.title })}\n triggerLabel={say('conversationActions', { title: titled.title })}\n label=\"⋯\"\n popupClassName=\"page-actions-popup\"\n align=\"start\"\n >\n <DropItem className=\"page-actions-item\" onClick={() => setRenamingTitle(true)}>\n {say('rename')}\n </DropItem>\n <DropItem className=\"page-actions-item\" onClick={() => setDeletingOpen(true)}>\n {say('delete')}\n </DropItem>\n </DropMenu>\n )}\n {!room && (\n <button type=\"button\" className=\"icon-button\" aria-pressed={listing} onClick={() => setListing((was) => !was)}>\n {say('conversations')}\n </button>\n )}\n {!room && !listing && (\n <button type=\"button\" className=\"icon-button\" onClick={startNew}>\n {say('newConversation')}\n </button>\n )}\n {!room && (\n <button\n type=\"button\"\n className=\"icon-button assistant-expand\"\n aria-pressed={expanded}\n aria-label={say('expand')}\n title={expanded ? say('collapse') : say('expand')}\n onClick={toggleExpanded}\n >\n <Corners inward={expanded} />\n </button>\n )}\n {!room && (\n <button type=\"button\" className=\"peekpanel-close\" aria-label={say('close')} title={say('close')} onClick={onClose}>\n ×\n </button>\n )}\n </div>\n {listing && !room ? (\n <div className=\"assistant-body\">{list}</div>\n ) : (\n <ActionOutcomes.Provider value={acted}>\n <div\n className=\"assistant-body\"\n ref={body}\n aria-live=\"polite\"\n aria-busy={busy}\n onScroll={(event) => {\n const view = event.currentTarget;\n pinned.current = view.scrollHeight - view.scrollTop - view.clientHeight < 24;\n }}\n >\n {!ready && <p className=\"assistant-empty\">{say('noModel')}</p>}\n {starting && (\n <div className=\"assistant-start\">\n <p className=\"assistant-empty\">{say('emptyHint')}</p>\n {starters.length > 0 && (\n <div className=\"assistant-starters\" role=\"group\" aria-label={say('starters')}>\n {starters.map((starter) => (\n <button key={starter} type=\"button\" className=\"assistant-starter\" disabled={busy} onClick={() => say_(starter)}>\n {starter}\n </button>\n ))}\n </div>\n )}\n </div>\n )}\n {drawn.map((entry, index) => {\n if (entry.type === 'steps')\n return (\n <Steps key={`s${entry.at}`} steps={entry.steps} running={busy && index === drawn.length - 1 ? running : undefined} />\n );\n const { item, at } = entry;\n if (item.type === 'person')\n return (\n <div\n key={`p${at}`}\n className={`assistant-person${editing !== null && item.seq === editing ? ' assistant-person-editing' : ''}`}\n >\n <p>{item.text}</p>\n {!busy && !waiting && (\n <div className=\"assistant-person-tools\">\n {item.seq !== undefined && (\n <button\n type=\"button\"\n onClick={() => {\n setEditing(item.seq!);\n setText(item.text);\n box.current?.focus();\n }}\n >\n {say('edit')}\n </button>\n )}\n {at === lastPerson && conversation && (\n <button type=\"button\" onClick={retry}>\n {say('retry')}\n </button>\n )}\n </div>\n )}\n </div>\n );\n if (item.type === 'text')\n return (\n <div key={`t${at}`} className=\"assistant-text\">\n <Words text={item.text} onFollow={onFollow} />\n </div>\n );\n if (item.type === 'note')\n return (\n <p key={`n${at}`} className=\"assistant-note\">\n {item.text}\n </p>\n );\n if (item.type === 'block') return <Block key={`b${at}`} block={item.block} onFollow={onFollow} />;\n if (item.type === 'proposal')\n return (\n <ProposalCard\n key={`c${item.id}`}\n proposal={item.proposal}\n outcome={item.outcome}\n live={!busy && waiting?.id === item.id}\n onResolve={(outcome) => resolve(item.proposal, outcome)}\n onFollow={onFollow}\n />\n );\n return null;\n })}\n {busy && (drawn.length === 0 || drawn[drawn.length - 1].type !== 'steps') && running && (\n <p className=\"assistant-working\">{running}</p>\n )}\n {problem && (\n <div className=\"assistant-problem\" role=\"alert\">\n <p>{problem.text}</p>\n {problem.again && !busy && (\n <button type=\"button\" onClick={again}>\n {say('tryAgain')}\n </button>\n )}\n {problem.fresh && (\n <button type=\"button\" onClick={startNew}>\n {say('newConversation')}\n </button>\n )}\n </div>\n )}\n </div>\n </ActionOutcomes.Provider>\n )}\n <div className=\"assistant-foot\">\n {context && withRecord && !listing && (\n <div className=\"assistant-context\">\n <span>{say('about', { label: context.label })}</span>\n <button\n type=\"button\"\n className=\"ghost\"\n aria-label={say('leaveOutRecord', { label: context.label })}\n title={say('leaveOutRecord', { label: context.label })}\n onClick={() => setWithRecord(false)}\n >\n ×\n </button>\n </div>\n )}\n {editing !== null && (\n <div className=\"assistant-context\">\n <span>{say('editing')}</span>\n <button\n type=\"button\"\n className=\"ghost\"\n onClick={() => {\n setEditing(null);\n setText('');\n }}\n >\n {say('cancelEdit')}\n </button>\n </div>\n )}\n {/* A change waiting for the person is said in the field itself, and the field says it is why it is shut. */}\n <div className=\"assistant-compose\">\n {waiting && !busy && (\n <p className=\"assistant-waiting\" id={waitingNote}>\n <span className=\"assistant-waiting-dot\" aria-hidden=\"true\" />\n {say('waitingForYou')}\n </p>\n )}\n <div className=\"assistant-compose-row\">\n <textarea\n ref={box}\n rows={1}\n value={text}\n aria-label={say('message')}\n aria-describedby={waiting && !busy ? waitingNote : undefined}\n placeholder={say('message')}\n disabled={!ready || Boolean(waiting && !busy)}\n onChange={(event) => setText(event.target.value)}\n onKeyDown={onKey}\n />\n {busy ? (\n <Button onClick={() => stop.current?.abort()}>{say('stop')}</Button>\n ) : (\n <Button intent={canSend ? 'primary' : 'secondary'} onClick={send} disabled={!canSend}>\n {say('send')}\n </Button>\n )}\n </div>\n </div>\n </div>\n </div>\n {deletingOpen && titled && (\n <DeleteConversation\n conversation={titled}\n onClose={() => setDeletingOpen(false)}\n onConfirm={() => {\n setDeletingOpen(false);\n void remove(titled.id);\n }}\n />\n )}\n </Frame>\n );\n}\n"],"mappings":"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"}