claude-mux 0.30.13 → 0.30.14

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 (361) hide show
  1. package/CLAUDE.md +14 -3
  2. package/dist/fleet-places.d.ts +7 -1
  3. package/dist/fleet-places.d.ts.map +1 -1
  4. package/dist/fleet-places.js +14 -1
  5. package/dist/fleet-places.js.map +1 -1
  6. package/dist/server/dictation-marks.d.ts.map +1 -1
  7. package/dist/server/dictation-marks.js +23 -1
  8. package/dist/server/dictation-marks.js.map +1 -1
  9. package/dist/transcript/parser.d.ts +7 -0
  10. package/dist/transcript/parser.d.ts.map +1 -1
  11. package/dist/transcript/parser.js +19 -3
  12. package/dist/transcript/parser.js.map +1 -1
  13. package/dist/transcript/past-sessions.d.ts.map +1 -1
  14. package/dist/transcript/past-sessions.js +4 -1
  15. package/dist/transcript/past-sessions.js.map +1 -1
  16. package/dist/utils/version.d.ts +1 -1
  17. package/dist/utils/version.js +1 -1
  18. package/dist/web/client/_app/immutable/chunks/{sULMfRFG.js → B4FaHfAQ.js} +2 -2
  19. package/dist/web/client/_app/immutable/chunks/{sULMfRFG.js.map → B4FaHfAQ.js.map} +1 -1
  20. package/dist/web/client/_app/immutable/chunks/{W5_HMZ5E.js → B5Hkb2u5.js} +2 -2
  21. package/dist/web/client/_app/immutable/chunks/{W5_HMZ5E.js.map → B5Hkb2u5.js.map} +1 -1
  22. package/{web/.svelte-kit/output/client/_app/immutable/chunks/BQzv8cqz.js → dist/web/client/_app/immutable/chunks/BOpEbBRb.js} +2 -2
  23. package/{web/.svelte-kit/output/client/_app/immutable/chunks/BQzv8cqz.js.map → dist/web/client/_app/immutable/chunks/BOpEbBRb.js.map} +1 -1
  24. package/dist/web/client/_app/immutable/chunks/{Q5yhzux8.js → BeYjnogg.js} +2 -2
  25. package/{web/.svelte-kit/output/client/_app/immutable/chunks/Q5yhzux8.js.map → dist/web/client/_app/immutable/chunks/BeYjnogg.js.map} +1 -1
  26. package/dist/web/client/_app/immutable/chunks/{VceCNUd7.js → C00rm3mY.js} +2 -2
  27. package/{web/.svelte-kit/output/client/_app/immutable/chunks/VceCNUd7.js.map → dist/web/client/_app/immutable/chunks/C00rm3mY.js.map} +1 -1
  28. package/dist/web/client/_app/immutable/chunks/{CtjkAirr.js → CKg7gbPm.js} +9 -9
  29. package/dist/web/client/_app/immutable/chunks/CKg7gbPm.js.map +1 -0
  30. package/dist/web/client/_app/immutable/chunks/CPEphjdk.js +4 -0
  31. package/dist/web/client/_app/immutable/chunks/CPEphjdk.js.map +1 -0
  32. package/dist/web/client/_app/immutable/chunks/{BQQ3-rqs.js → CPlFo88J.js} +2 -2
  33. package/dist/web/client/_app/immutable/chunks/{BQQ3-rqs.js.map → CPlFo88J.js.map} +1 -1
  34. package/dist/web/client/_app/immutable/chunks/{BvX4FYxp.js → CtnjySwS.js} +2 -2
  35. package/dist/web/client/_app/immutable/chunks/{BvX4FYxp.js.map → CtnjySwS.js.map} +1 -1
  36. package/dist/web/client/_app/immutable/chunks/{XgSsj0QY.js → D3EW0jRH.js} +2 -2
  37. package/{web/.svelte-kit/output/client/_app/immutable/chunks/XgSsj0QY.js.map → dist/web/client/_app/immutable/chunks/D3EW0jRH.js.map} +1 -1
  38. package/dist/web/client/_app/immutable/chunks/{CtlIfY1C.js → D3umr-Qr.js} +2 -2
  39. package/{web/.svelte-kit/output/client/_app/immutable/chunks/CtlIfY1C.js.map → dist/web/client/_app/immutable/chunks/D3umr-Qr.js.map} +1 -1
  40. package/dist/web/client/_app/immutable/chunks/{CM0CI9GL.js → D8-_Y-M6.js} +3 -3
  41. package/dist/web/client/_app/immutable/chunks/{CM0CI9GL.js.map → D8-_Y-M6.js.map} +1 -1
  42. package/dist/web/client/_app/immutable/chunks/{cvsGFvDx.js → DDvK7Qo9.js} +2 -2
  43. package/{web/.svelte-kit/output/client/_app/immutable/chunks/cvsGFvDx.js.map → dist/web/client/_app/immutable/chunks/DDvK7Qo9.js.map} +1 -1
  44. package/dist/web/client/_app/immutable/chunks/{CiU8KBun.js → _VFi-7U7.js} +2 -2
  45. package/dist/web/client/_app/immutable/chunks/{CiU8KBun.js.map → _VFi-7U7.js.map} +1 -1
  46. package/dist/web/client/_app/immutable/chunks/{DlENCZqZ.js → mQ6hkLuy.js} +2 -2
  47. package/dist/web/client/_app/immutable/chunks/{DlENCZqZ.js.map → mQ6hkLuy.js.map} +1 -1
  48. package/dist/web/client/_app/immutable/entry/{app.BwTbN8wB.js → app.CTFza_OS.js} +3 -3
  49. package/{web/.svelte-kit/output/client/_app/immutable/entry/app.BwTbN8wB.js.map → dist/web/client/_app/immutable/entry/app.CTFza_OS.js.map} +1 -1
  50. package/dist/web/client/_app/immutable/entry/start.B-zlkyrt.js +2 -0
  51. package/dist/web/client/_app/immutable/entry/start.B-zlkyrt.js.map +1 -0
  52. package/{web/.svelte-kit/output/client/_app/immutable/nodes/0.BnHV-ElR.js → dist/web/client/_app/immutable/nodes/0.Cztuq8Ih.js} +2 -2
  53. package/dist/web/client/_app/immutable/nodes/{0.BnHV-ElR.js.map → 0.Cztuq8Ih.js.map} +1 -1
  54. package/dist/web/client/_app/immutable/nodes/{1.Dc3ryOCf.js → 1.BOOL0V7K.js} +2 -2
  55. package/dist/web/client/_app/immutable/nodes/{1.Dc3ryOCf.js.map → 1.BOOL0V7K.js.map} +1 -1
  56. package/dist/web/client/_app/immutable/nodes/{2.DUrpAceY.js → 2.CArUpZNe.js} +2 -2
  57. package/dist/web/client/_app/immutable/nodes/{2.DUrpAceY.js.map → 2.CArUpZNe.js.map} +1 -1
  58. package/dist/web/client/_app/immutable/nodes/{3.BaCofjAn.js → 3.DSvIWalA.js} +2 -2
  59. package/dist/web/client/_app/immutable/nodes/{3.BaCofjAn.js.map → 3.DSvIWalA.js.map} +1 -1
  60. package/dist/web/client/_app/immutable/nodes/{4.v1wYkrvS.js → 4.H6RMG_cy.js} +2 -2
  61. package/dist/web/client/_app/immutable/nodes/{4.v1wYkrvS.js.map → 4.H6RMG_cy.js.map} +1 -1
  62. package/dist/web/client/_app/immutable/nodes/{5.Bn4A77jK.js → 5.BHSt0Suo.js} +2 -2
  63. package/dist/web/client/_app/immutable/nodes/{5.Bn4A77jK.js.map → 5.BHSt0Suo.js.map} +1 -1
  64. package/dist/web/client/_app/immutable/nodes/{6.C2hEoITj.js → 6.CzLoA0w7.js} +2 -2
  65. package/dist/web/client/_app/immutable/nodes/{6.C2hEoITj.js.map → 6.CzLoA0w7.js.map} +1 -1
  66. package/dist/web/client/_app/immutable/nodes/{7.BcHOjWdp.js → 7.fqq2vVa9.js} +2 -2
  67. package/dist/web/client/_app/immutable/nodes/{7.BcHOjWdp.js.map → 7.fqq2vVa9.js.map} +1 -1
  68. package/dist/web/client/_app/immutable/nodes/{8.D7NtqIYy.js → 8.DNFFjTla.js} +2 -2
  69. package/dist/web/client/_app/immutable/nodes/{8.D7NtqIYy.js.map → 8.DNFFjTla.js.map} +1 -1
  70. package/dist/web/client/_app/immutable/nodes/{9.D-211z9-.js → 9.0kMPrp2-.js} +2 -2
  71. package/dist/web/client/_app/immutable/nodes/{9.D-211z9-.js.map → 9.0kMPrp2-.js.map} +1 -1
  72. package/dist/web/client/_app/version.json +1 -1
  73. package/dist/web/server/chunks/{0-CvglVGCY.js → 0-B_KxXX-N.js} +14 -14
  74. package/dist/web/server/chunks/{0-CvglVGCY.js.map → 0-B_KxXX-N.js.map} +1 -1
  75. package/dist/web/server/chunks/{1-D-gJDFrG.js → 1-BmEKuUDK.js} +4 -4
  76. package/dist/web/server/chunks/{1-D-gJDFrG.js.map → 1-BmEKuUDK.js.map} +1 -1
  77. package/dist/web/server/chunks/{2-BCmEU5Qq.js → 2-BJ3dzws2.js} +13 -13
  78. package/dist/web/server/chunks/{2-BCmEU5Qq.js.map → 2-BJ3dzws2.js.map} +1 -1
  79. package/dist/web/server/chunks/{3-CHn5Kw-T.js → 3-CLYKGzT3.js} +10 -10
  80. package/dist/web/server/chunks/{3-CHn5Kw-T.js.map → 3-CLYKGzT3.js.map} +1 -1
  81. package/dist/web/server/chunks/{4-Cxg7VcZ7.js → 4-CsoWHVgX.js} +12 -12
  82. package/dist/web/server/chunks/{4-Cxg7VcZ7.js.map → 4-CsoWHVgX.js.map} +1 -1
  83. package/dist/web/server/chunks/{5-DSgvnHF_.js → 5-oPM6ncgT.js} +9 -9
  84. package/dist/web/server/chunks/{5-DSgvnHF_.js.map → 5-oPM6ncgT.js.map} +1 -1
  85. package/dist/web/server/chunks/{6-B0rymWRR.js → 6-gvgju2ZN.js} +5 -5
  86. package/dist/web/server/chunks/{6-B0rymWRR.js.map → 6-gvgju2ZN.js.map} +1 -1
  87. package/dist/web/server/chunks/{7-CNomBJux.js → 7-D8hylKrz.js} +10 -10
  88. package/dist/web/server/chunks/{7-CNomBJux.js.map → 7-D8hylKrz.js.map} +1 -1
  89. package/dist/web/server/chunks/{8-TYbX-1bO.js → 8-Br4hTtby.js} +12 -12
  90. package/dist/web/server/chunks/{8-TYbX-1bO.js.map → 8-Br4hTtby.js.map} +1 -1
  91. package/dist/web/server/chunks/{9-XGQQvTLc.js → 9-9uvmfsEs.js} +9 -9
  92. package/dist/web/server/chunks/{9-XGQQvTLc.js.map → 9-9uvmfsEs.js.map} +1 -1
  93. package/dist/web/server/chunks/{_layout.svelte-yrPX5VFm.js → _layout.svelte-DamAAFpK.js} +58 -37
  94. package/dist/web/server/chunks/_layout.svelte-DamAAFpK.js.map +1 -0
  95. package/dist/web/server/chunks/{_page.svelte-C_kFA0Lq.js → _page.svelte-DFE4jmT9.js} +4 -4
  96. package/dist/web/server/chunks/{_page.svelte-C_kFA0Lq.js.map → _page.svelte-DFE4jmT9.js.map} +1 -1
  97. package/dist/web/server/chunks/{_page.svelte-DvxpwsgS.js → _page.svelte-DHPGbCS1.js} +6 -6
  98. package/dist/web/server/chunks/{_page.svelte-DvxpwsgS.js.map → _page.svelte-DHPGbCS1.js.map} +1 -1
  99. package/dist/web/server/chunks/{_server.ts-Dz01Gvhk.js → _server.ts-0RT4n9LX.js} +2 -2
  100. package/dist/web/server/chunks/{_server.ts-Dz01Gvhk.js.map → _server.ts-0RT4n9LX.js.map} +1 -1
  101. package/dist/web/server/chunks/{_server.ts-D2Tvcncu.js → _server.ts-3kbpguQ1.js} +3 -3
  102. package/dist/web/server/chunks/{_server.ts-D2Tvcncu.js.map → _server.ts-3kbpguQ1.js.map} +1 -1
  103. package/dist/web/server/chunks/{_server.ts-TN_Ka6cR.js → _server.ts-4m17ESHV.js} +2 -2
  104. package/dist/web/server/chunks/{_server.ts-TN_Ka6cR.js.map → _server.ts-4m17ESHV.js.map} +1 -1
  105. package/dist/web/server/chunks/{_server.ts-Bj1Eewby.js → _server.ts-8Bs2jUgD.js} +2 -2
  106. package/dist/web/server/chunks/{_server.ts-Bj1Eewby.js.map → _server.ts-8Bs2jUgD.js.map} +1 -1
  107. package/dist/web/server/chunks/{_server.ts-BWVtnpJh.js → _server.ts-95cbXKdT.js} +3 -3
  108. package/dist/web/server/chunks/{_server.ts-BWVtnpJh.js.map → _server.ts-95cbXKdT.js.map} +1 -1
  109. package/dist/web/server/chunks/{_server.ts-CyOA1rOq.js → _server.ts-B56-XF-Z.js} +3 -3
  110. package/dist/web/server/chunks/{_server.ts-CyOA1rOq.js.map → _server.ts-B56-XF-Z.js.map} +1 -1
  111. package/dist/web/server/chunks/{_server.ts-1ZhqL5o8.js → _server.ts-BAC_No-1.js} +2 -2
  112. package/dist/web/server/chunks/{_server.ts-1ZhqL5o8.js.map → _server.ts-BAC_No-1.js.map} +1 -1
  113. package/dist/web/server/chunks/{_server.ts-ji7L8HUR.js → _server.ts-BCpfYsYw.js} +3 -3
  114. package/dist/web/server/chunks/{_server.ts-ji7L8HUR.js.map → _server.ts-BCpfYsYw.js.map} +1 -1
  115. package/dist/web/server/chunks/{_server.ts-9iRpDv9e.js → _server.ts-BGToJuLp.js} +2 -2
  116. package/dist/web/server/chunks/{_server.ts-9iRpDv9e.js.map → _server.ts-BGToJuLp.js.map} +1 -1
  117. package/dist/web/server/chunks/{_server.ts-DQJ-tygD.js → _server.ts-BW87LYkE.js} +2 -2
  118. package/dist/web/server/chunks/{_server.ts-DQJ-tygD.js.map → _server.ts-BW87LYkE.js.map} +1 -1
  119. package/dist/web/server/chunks/{_server.ts-VgbTPrqV.js → _server.ts-BXjUy61V.js} +2 -2
  120. package/dist/web/server/chunks/{_server.ts-VgbTPrqV.js.map → _server.ts-BXjUy61V.js.map} +1 -1
  121. package/dist/web/server/chunks/{_server.ts-FoPsfjo3.js → _server.ts-BYyaN7ik.js} +2 -2
  122. package/dist/web/server/chunks/{_server.ts-FoPsfjo3.js.map → _server.ts-BYyaN7ik.js.map} +1 -1
  123. package/dist/web/server/chunks/{_server.ts-CNBy2p2U.js → _server.ts-Bjzi1JAu.js} +2 -2
  124. package/dist/web/server/chunks/{_server.ts-CNBy2p2U.js.map → _server.ts-Bjzi1JAu.js.map} +1 -1
  125. package/dist/web/server/chunks/{_server.ts-CSK1ReRS.js → _server.ts-CBU5vhD8.js} +2 -2
  126. package/dist/web/server/chunks/{_server.ts-CSK1ReRS.js.map → _server.ts-CBU5vhD8.js.map} +1 -1
  127. package/dist/web/server/chunks/{_server.ts-Cv8SUkC5.js → _server.ts-CG-7TORV.js} +3 -3
  128. package/dist/web/server/chunks/{_server.ts-Cv8SUkC5.js.map → _server.ts-CG-7TORV.js.map} +1 -1
  129. package/dist/web/server/chunks/{_server.ts-DPctaiWC.js → _server.ts-COCrEIiW.js} +2 -2
  130. package/dist/web/server/chunks/{_server.ts-DPctaiWC.js.map → _server.ts-COCrEIiW.js.map} +1 -1
  131. package/dist/web/server/chunks/{_server.ts-C7uhdF7Y.js → _server.ts-CPCsEz_B.js} +4 -4
  132. package/dist/web/server/chunks/{_server.ts-C7uhdF7Y.js.map → _server.ts-CPCsEz_B.js.map} +1 -1
  133. package/dist/web/server/chunks/{_server.ts-DsyqZudf.js → _server.ts-CPGa_LDW.js} +2 -2
  134. package/dist/web/server/chunks/{_server.ts-DsyqZudf.js.map → _server.ts-CPGa_LDW.js.map} +1 -1
  135. package/dist/web/server/chunks/{_server.ts-B9RfKfyc.js → _server.ts-CT1m86tm.js} +2 -2
  136. package/dist/web/server/chunks/{_server.ts-B9RfKfyc.js.map → _server.ts-CT1m86tm.js.map} +1 -1
  137. package/dist/web/server/chunks/{_server.ts-CwFbAWCg.js → _server.ts-CXzAFIps.js} +2 -2
  138. package/dist/web/server/chunks/{_server.ts-CwFbAWCg.js.map → _server.ts-CXzAFIps.js.map} +1 -1
  139. package/dist/web/server/chunks/{_server.ts-DHuyjZQx.js → _server.ts-C_H2gKKu.js} +2 -2
  140. package/dist/web/server/chunks/{_server.ts-DHuyjZQx.js.map → _server.ts-C_H2gKKu.js.map} +1 -1
  141. package/dist/web/server/chunks/{_server.ts-DVgdt6Zu.js → _server.ts-CjH9MxGk.js} +3 -3
  142. package/dist/web/server/chunks/{_server.ts-DVgdt6Zu.js.map → _server.ts-CjH9MxGk.js.map} +1 -1
  143. package/dist/web/server/chunks/{_server.ts-DrFiP32b.js → _server.ts-CrQk3PtI.js} +3 -3
  144. package/dist/web/server/chunks/{_server.ts-DrFiP32b.js.map → _server.ts-CrQk3PtI.js.map} +1 -1
  145. package/dist/web/server/chunks/{_server.ts-CA8nszPb.js → _server.ts-Cy5Matw4.js} +3 -3
  146. package/dist/web/server/chunks/{_server.ts-CA8nszPb.js.map → _server.ts-Cy5Matw4.js.map} +1 -1
  147. package/dist/web/server/chunks/{_server.ts-CovkmnvY.js → _server.ts-D9PPu5p4.js} +3 -3
  148. package/dist/web/server/chunks/{_server.ts-CovkmnvY.js.map → _server.ts-D9PPu5p4.js.map} +1 -1
  149. package/dist/web/server/chunks/{_server.ts-vhti5VvF.js → _server.ts-DGvNQ4Mq.js} +3 -3
  150. package/dist/web/server/chunks/{_server.ts-vhti5VvF.js.map → _server.ts-DGvNQ4Mq.js.map} +1 -1
  151. package/dist/web/server/chunks/{_server.ts-iK8ih9Bi.js → _server.ts-DJOSnwXV.js} +2 -2
  152. package/dist/web/server/chunks/{_server.ts-iK8ih9Bi.js.map → _server.ts-DJOSnwXV.js.map} +1 -1
  153. package/dist/web/server/chunks/{_server.ts-DK-6ddNq.js → _server.ts-DPoluZc6.js} +3 -3
  154. package/dist/web/server/chunks/{_server.ts-DK-6ddNq.js.map → _server.ts-DPoluZc6.js.map} +1 -1
  155. package/dist/web/server/chunks/{_server.ts-BozsVs8t.js → _server.ts-DS6kibxL.js} +2 -2
  156. package/dist/web/server/chunks/{_server.ts-BozsVs8t.js.map → _server.ts-DS6kibxL.js.map} +1 -1
  157. package/dist/web/server/chunks/{_server.ts-DozhhYwq.js → _server.ts-DUl0ucUP.js} +3 -3
  158. package/dist/web/server/chunks/{_server.ts-DozhhYwq.js.map → _server.ts-DUl0ucUP.js.map} +1 -1
  159. package/dist/web/server/chunks/{_server.ts-78nODRDJ.js → _server.ts-DWj22oj9.js} +2 -2
  160. package/dist/web/server/chunks/{_server.ts-78nODRDJ.js.map → _server.ts-DWj22oj9.js.map} +1 -1
  161. package/dist/web/server/chunks/{_server.ts-CA1j9wWk.js → _server.ts-DZrVaelC.js} +2 -2
  162. package/dist/web/server/chunks/{_server.ts-CA1j9wWk.js.map → _server.ts-DZrVaelC.js.map} +1 -1
  163. package/dist/web/server/chunks/{_server.ts-CzcknkWq.js → _server.ts-DrG3j6Ao.js} +2 -2
  164. package/dist/web/server/chunks/{_server.ts-CzcknkWq.js.map → _server.ts-DrG3j6Ao.js.map} +1 -1
  165. package/dist/web/server/chunks/{_server.ts-AAllMdwT.js → _server.ts-Dwy38J9J.js} +2 -2
  166. package/dist/web/server/chunks/{_server.ts-AAllMdwT.js.map → _server.ts-Dwy38J9J.js.map} +1 -1
  167. package/dist/web/server/chunks/{_server.ts-CgChlIKq.js → _server.ts-DxGjRezI.js} +2 -2
  168. package/dist/web/server/chunks/{_server.ts-CgChlIKq.js.map → _server.ts-DxGjRezI.js.map} +1 -1
  169. package/dist/web/server/chunks/{_server.ts-KbQyErIR.js → _server.ts-XMUjHO61.js} +2 -2
  170. package/dist/web/server/chunks/{_server.ts-KbQyErIR.js.map → _server.ts-XMUjHO61.js.map} +1 -1
  171. package/dist/web/server/chunks/{_server.ts-DGTSZoLn.js → _server.ts-dvT2bXEB.js} +2 -2
  172. package/dist/web/server/chunks/{_server.ts-DGTSZoLn.js.map → _server.ts-dvT2bXEB.js.map} +1 -1
  173. package/dist/web/server/chunks/{_server.ts-BxscGs8D.js → _server.ts-m835uDm6.js} +2 -2
  174. package/dist/web/server/chunks/{_server.ts-BxscGs8D.js.map → _server.ts-m835uDm6.js.map} +1 -1
  175. package/dist/web/server/chunks/{checkbox-DiJTAtHi.js → checkbox-BYzlWW56.js} +2 -2
  176. package/dist/web/server/chunks/{checkbox-DiJTAtHi.js.map → checkbox-BYzlWW56.js.map} +1 -1
  177. package/dist/web/server/chunks/{create-id-DpoSQWrl.js → create-id-s6T_m-1j.js} +3 -3
  178. package/dist/web/server/chunks/{create-id-DpoSQWrl.js.map → create-id-s6T_m-1j.js.map} +1 -1
  179. package/dist/web/server/chunks/{discover-DjR28OqK.js → discover-DykzHz0t.js} +2 -2
  180. package/dist/web/server/chunks/{discover-DjR28OqK.js.map → discover-DykzHz0t.js.map} +1 -1
  181. package/dist/web/server/chunks/{drafts.svelte-DsFAtH-s.js → drafts.svelte-c94J-DBB.js} +3 -3
  182. package/dist/web/server/chunks/{drafts.svelte-DsFAtH-s.js.map → drafts.svelte-c94J-DBB.js.map} +1 -1
  183. package/dist/web/server/chunks/{end-session-BbBa9yD0.js → end-session-Czy_WW42.js} +2 -2
  184. package/dist/web/server/chunks/{end-session-BbBa9yD0.js.map → end-session-Czy_WW42.js.map} +1 -1
  185. package/dist/web/server/chunks/{files-4i3igWea.js → files-DNH191y7.js} +2 -2
  186. package/dist/web/server/chunks/{files-4i3igWea.js.map → files-DNH191y7.js.map} +1 -1
  187. package/dist/web/server/chunks/{fleet-DZJSFWuH.js → fleet-CWHlZjSd.js} +4 -4
  188. package/dist/web/server/chunks/{fleet-DZJSFWuH.js.map → fleet-CWHlZjSd.js.map} +1 -1
  189. package/dist/web/server/chunks/{git-D9dLEKUF.js → git-CHO9UIOQ.js} +13 -5
  190. package/dist/web/server/chunks/git-CHO9UIOQ.js.map +1 -0
  191. package/dist/web/server/chunks/{git-history-De9t0yF-.js → git-history-CxyH4jQb.js} +2 -2
  192. package/dist/web/server/chunks/{git-history-De9t0yF-.js.map → git-history-CxyH4jQb.js.map} +1 -1
  193. package/dist/web/server/chunks/{hooks.server-C3Uglne7.js → hooks.server-DgHxEf6H.js} +6 -6
  194. package/dist/web/server/chunks/{hooks.server-C3Uglne7.js.map → hooks.server-DgHxEf6H.js.map} +1 -1
  195. package/dist/web/server/chunks/{message-queue-sFcJCRjz.js → message-queue-DhLshpoF.js} +13 -2
  196. package/dist/web/server/chunks/message-queue-DhLshpoF.js.map +1 -0
  197. package/dist/web/server/chunks/{project-CbPa8Mu7.js → project-CBPdIh2n.js} +2 -2
  198. package/dist/web/server/chunks/{project-CbPa8Mu7.js.map → project-CBPdIh2n.js.map} +1 -1
  199. package/dist/web/server/chunks/{project-icons-CSb1bfT9.js → project-icons-bWhaFSVy.js} +4 -4
  200. package/dist/web/server/chunks/{project-icons-CSb1bfT9.js.map → project-icons-bWhaFSVy.js.map} +1 -1
  201. package/dist/web/server/chunks/{push-BJ7P9DGd.js → push-LMlCp4Lc.js} +5 -5
  202. package/dist/web/server/chunks/{push-BJ7P9DGd.js.map → push-LMlCp4Lc.js.map} +1 -1
  203. package/dist/web/server/chunks/{remote-control-C1d9R3w4.js → remote-control-BvYkVDhx.js} +2 -2
  204. package/dist/web/server/chunks/{remote-control-C1d9R3w4.js.map → remote-control-BvYkVDhx.js.map} +1 -1
  205. package/dist/web/server/chunks/{start-session-CKbupnLS.js → start-session-HljgutDe.js} +3 -3
  206. package/dist/web/server/chunks/{start-session-CKbupnLS.js.map → start-session-HljgutDe.js.map} +1 -1
  207. package/dist/web/server/chunks/{version-BqEJmw2g.js → version-ox9yLZ0P.js} +2 -2
  208. package/dist/web/server/chunks/version-ox9yLZ0P.js.map +1 -0
  209. package/dist/web/server/chunks/{web-preview-Bi5fjydK.js → web-preview-H5eiWlBD.js} +2 -2
  210. package/dist/web/server/chunks/{web-preview-Bi5fjydK.js.map → web-preview-H5eiWlBD.js.map} +1 -1
  211. package/dist/web/server/chunks/{ws-handlers-zemeJ8Si.js → ws-handlers-k_sOue-0.js} +6 -5
  212. package/dist/web/server/chunks/ws-handlers-k_sOue-0.js.map +1 -0
  213. package/dist/web/server/chunks/{ws-managers-C5VXKb_r.js → ws-managers-D2qC6Gla.js} +2 -2
  214. package/dist/web/server/chunks/{ws-managers-C5VXKb_r.js.map → ws-managers-D2qC6Gla.js.map} +1 -1
  215. package/dist/web/server/chunks/{ws-messages-jOSwT1Yq.js → ws-messages-B81v2RXg.js} +7 -2
  216. package/dist/web/server/chunks/ws-messages-B81v2RXg.js.map +1 -0
  217. package/dist/web/server/index.js +2 -2
  218. package/dist/web/server/index.js.map +1 -1
  219. package/dist/web/server/manifest.js +53 -53
  220. package/dist/web/server/manifest.js.map +1 -1
  221. package/package.json +1 -1
  222. package/src/fleet-places.ts +17 -1
  223. package/src/server/dictation-marks.ts +24 -1
  224. package/src/transcript/parser.ts +20 -3
  225. package/src/transcript/past-sessions.ts +3 -1
  226. package/src/utils/version.ts +1 -1
  227. package/tests/fleet-places.test.ts +20 -0
  228. package/tests/server/dictation-marks.test.ts +16 -0
  229. package/tests/transcript/parser.test.ts +34 -0
  230. package/tests/transcript/past-sessions.test.ts +5 -0
  231. package/web/.svelte-kit/adapter-bun/chunks/git.js +13 -4
  232. package/web/.svelte-kit/adapter-bun/chunks/git.js.map +1 -1
  233. package/web/.svelte-kit/adapter-bun/chunks/internal2.js +1 -1
  234. package/web/.svelte-kit/adapter-bun/chunks/internal2.js.map +1 -1
  235. package/web/.svelte-kit/adapter-bun/chunks/message-queue.js +14 -1
  236. package/web/.svelte-kit/adapter-bun/chunks/message-queue.js.map +1 -1
  237. package/web/.svelte-kit/adapter-bun/chunks/version.js +1 -1
  238. package/web/.svelte-kit/adapter-bun/chunks/version.js.map +1 -1
  239. package/web/.svelte-kit/adapter-bun/chunks/ws-handlers.js +2 -1
  240. package/web/.svelte-kit/adapter-bun/chunks/ws-handlers.js.map +1 -1
  241. package/web/.svelte-kit/adapter-bun/chunks/ws-messages.js +6 -1
  242. package/web/.svelte-kit/adapter-bun/chunks/ws-messages.js.map +1 -1
  243. package/web/.svelte-kit/adapter-bun/entries/pages/_layout.svelte.js +72 -45
  244. package/web/.svelte-kit/adapter-bun/entries/pages/_layout.svelte.js.map +1 -1
  245. package/web/.svelte-kit/adapter-bun/manifest-full.js +1 -1
  246. package/web/.svelte-kit/adapter-bun/manifest.js +1 -1
  247. package/web/.svelte-kit/adapter-bun/nodes/0.js +1 -1
  248. package/web/.svelte-kit/adapter-bun/nodes/1.js +1 -1
  249. package/web/.svelte-kit/adapter-bun/nodes/2.js +1 -1
  250. package/web/.svelte-kit/adapter-bun/nodes/3.js +1 -1
  251. package/web/.svelte-kit/adapter-bun/nodes/4.js +1 -1
  252. package/web/.svelte-kit/adapter-bun/nodes/5.js +1 -1
  253. package/web/.svelte-kit/adapter-bun/nodes/6.js +1 -1
  254. package/web/.svelte-kit/adapter-bun/nodes/7.js +1 -1
  255. package/web/.svelte-kit/adapter-bun/nodes/8.js +1 -1
  256. package/web/.svelte-kit/adapter-bun/nodes/9.js +1 -1
  257. package/web/.svelte-kit/generated/server/internal.js +1 -1
  258. package/web/.svelte-kit/output/client/.vite/manifest.json +237 -237
  259. package/web/.svelte-kit/output/client/_app/immutable/chunks/{sULMfRFG.js → B4FaHfAQ.js} +2 -2
  260. package/web/.svelte-kit/output/client/_app/immutable/chunks/{sULMfRFG.js.map → B4FaHfAQ.js.map} +1 -1
  261. package/web/.svelte-kit/output/client/_app/immutable/chunks/{W5_HMZ5E.js → B5Hkb2u5.js} +2 -2
  262. package/web/.svelte-kit/output/client/_app/immutable/chunks/{W5_HMZ5E.js.map → B5Hkb2u5.js.map} +1 -1
  263. package/{dist/web/client/_app/immutable/chunks/BQzv8cqz.js → web/.svelte-kit/output/client/_app/immutable/chunks/BOpEbBRb.js} +2 -2
  264. package/{dist/web/client/_app/immutable/chunks/BQzv8cqz.js.map → web/.svelte-kit/output/client/_app/immutable/chunks/BOpEbBRb.js.map} +1 -1
  265. package/web/.svelte-kit/output/client/_app/immutable/chunks/{Q5yhzux8.js → BeYjnogg.js} +2 -2
  266. package/{dist/web/client/_app/immutable/chunks/Q5yhzux8.js.map → web/.svelte-kit/output/client/_app/immutable/chunks/BeYjnogg.js.map} +1 -1
  267. package/web/.svelte-kit/output/client/_app/immutable/chunks/{VceCNUd7.js → C00rm3mY.js} +2 -2
  268. package/{dist/web/client/_app/immutable/chunks/VceCNUd7.js.map → web/.svelte-kit/output/client/_app/immutable/chunks/C00rm3mY.js.map} +1 -1
  269. package/web/.svelte-kit/output/client/_app/immutable/chunks/{CtjkAirr.js → CKg7gbPm.js} +9 -9
  270. package/web/.svelte-kit/output/client/_app/immutable/chunks/CKg7gbPm.js.map +1 -0
  271. package/web/.svelte-kit/output/client/_app/immutable/chunks/CPEphjdk.js +4 -0
  272. package/web/.svelte-kit/output/client/_app/immutable/chunks/CPEphjdk.js.map +1 -0
  273. package/web/.svelte-kit/output/client/_app/immutable/chunks/{BQQ3-rqs.js → CPlFo88J.js} +2 -2
  274. package/web/.svelte-kit/output/client/_app/immutable/chunks/{BQQ3-rqs.js.map → CPlFo88J.js.map} +1 -1
  275. package/web/.svelte-kit/output/client/_app/immutable/chunks/{BvX4FYxp.js → CtnjySwS.js} +2 -2
  276. package/web/.svelte-kit/output/client/_app/immutable/chunks/{BvX4FYxp.js.map → CtnjySwS.js.map} +1 -1
  277. package/web/.svelte-kit/output/client/_app/immutable/chunks/{XgSsj0QY.js → D3EW0jRH.js} +2 -2
  278. package/{dist/web/client/_app/immutable/chunks/XgSsj0QY.js.map → web/.svelte-kit/output/client/_app/immutable/chunks/D3EW0jRH.js.map} +1 -1
  279. package/web/.svelte-kit/output/client/_app/immutable/chunks/{CtlIfY1C.js → D3umr-Qr.js} +2 -2
  280. package/{dist/web/client/_app/immutable/chunks/CtlIfY1C.js.map → web/.svelte-kit/output/client/_app/immutable/chunks/D3umr-Qr.js.map} +1 -1
  281. package/web/.svelte-kit/output/client/_app/immutable/chunks/{CM0CI9GL.js → D8-_Y-M6.js} +3 -3
  282. package/web/.svelte-kit/output/client/_app/immutable/chunks/{CM0CI9GL.js.map → D8-_Y-M6.js.map} +1 -1
  283. package/web/.svelte-kit/output/client/_app/immutable/chunks/{cvsGFvDx.js → DDvK7Qo9.js} +2 -2
  284. package/{dist/web/client/_app/immutable/chunks/cvsGFvDx.js.map → web/.svelte-kit/output/client/_app/immutable/chunks/DDvK7Qo9.js.map} +1 -1
  285. package/web/.svelte-kit/output/client/_app/immutable/chunks/{CiU8KBun.js → _VFi-7U7.js} +2 -2
  286. package/web/.svelte-kit/output/client/_app/immutable/chunks/{CiU8KBun.js.map → _VFi-7U7.js.map} +1 -1
  287. package/web/.svelte-kit/output/client/_app/immutable/chunks/{DlENCZqZ.js → mQ6hkLuy.js} +2 -2
  288. package/web/.svelte-kit/output/client/_app/immutable/chunks/{DlENCZqZ.js.map → mQ6hkLuy.js.map} +1 -1
  289. package/web/.svelte-kit/output/client/_app/immutable/entry/{app.BwTbN8wB.js → app.CTFza_OS.js} +3 -3
  290. package/{dist/web/client/_app/immutable/entry/app.BwTbN8wB.js.map → web/.svelte-kit/output/client/_app/immutable/entry/app.CTFza_OS.js.map} +1 -1
  291. package/web/.svelte-kit/output/client/_app/immutable/entry/start.B-zlkyrt.js +2 -0
  292. package/web/.svelte-kit/output/client/_app/immutable/entry/start.B-zlkyrt.js.map +1 -0
  293. package/{dist/web/client/_app/immutable/nodes/0.BnHV-ElR.js → web/.svelte-kit/output/client/_app/immutable/nodes/0.Cztuq8Ih.js} +2 -2
  294. package/web/.svelte-kit/output/client/_app/immutable/nodes/{0.BnHV-ElR.js.map → 0.Cztuq8Ih.js.map} +1 -1
  295. package/web/.svelte-kit/output/client/_app/immutable/nodes/{1.Dc3ryOCf.js → 1.BOOL0V7K.js} +2 -2
  296. package/web/.svelte-kit/output/client/_app/immutable/nodes/{1.Dc3ryOCf.js.map → 1.BOOL0V7K.js.map} +1 -1
  297. package/web/.svelte-kit/output/client/_app/immutable/nodes/{2.DUrpAceY.js → 2.CArUpZNe.js} +2 -2
  298. package/web/.svelte-kit/output/client/_app/immutable/nodes/{2.DUrpAceY.js.map → 2.CArUpZNe.js.map} +1 -1
  299. package/web/.svelte-kit/output/client/_app/immutable/nodes/{3.BaCofjAn.js → 3.DSvIWalA.js} +2 -2
  300. package/web/.svelte-kit/output/client/_app/immutable/nodes/{3.BaCofjAn.js.map → 3.DSvIWalA.js.map} +1 -1
  301. package/web/.svelte-kit/output/client/_app/immutable/nodes/4.H6RMG_cy.js +2 -0
  302. package/web/.svelte-kit/output/client/_app/immutable/nodes/{4.v1wYkrvS.js.map → 4.H6RMG_cy.js.map} +1 -1
  303. package/web/.svelte-kit/output/client/_app/immutable/nodes/5.BHSt0Suo.js +2 -0
  304. package/web/.svelte-kit/output/client/_app/immutable/nodes/{5.Bn4A77jK.js.map → 5.BHSt0Suo.js.map} +1 -1
  305. package/web/.svelte-kit/output/client/_app/immutable/nodes/{6.C2hEoITj.js → 6.CzLoA0w7.js} +2 -2
  306. package/web/.svelte-kit/output/client/_app/immutable/nodes/{6.C2hEoITj.js.map → 6.CzLoA0w7.js.map} +1 -1
  307. package/web/.svelte-kit/output/client/_app/immutable/nodes/{7.BcHOjWdp.js → 7.fqq2vVa9.js} +2 -2
  308. package/web/.svelte-kit/output/client/_app/immutable/nodes/{7.BcHOjWdp.js.map → 7.fqq2vVa9.js.map} +1 -1
  309. package/web/.svelte-kit/output/client/_app/immutable/nodes/8.DNFFjTla.js +2 -0
  310. package/web/.svelte-kit/output/client/_app/immutable/nodes/{8.D7NtqIYy.js.map → 8.DNFFjTla.js.map} +1 -1
  311. package/web/.svelte-kit/output/client/_app/immutable/nodes/9.0kMPrp2-.js +2 -0
  312. package/web/.svelte-kit/output/client/_app/immutable/nodes/{9.D-211z9-.js.map → 9.0kMPrp2-.js.map} +1 -1
  313. package/web/.svelte-kit/output/client/_app/version.json +1 -1
  314. package/web/.svelte-kit/output/server/chunks/git.js +13 -4
  315. package/web/.svelte-kit/output/server/chunks/git.js.map +1 -1
  316. package/web/.svelte-kit/output/server/chunks/internal2.js +1 -1
  317. package/web/.svelte-kit/output/server/chunks/internal2.js.map +1 -1
  318. package/web/.svelte-kit/output/server/chunks/message-queue.js +14 -1
  319. package/web/.svelte-kit/output/server/chunks/message-queue.js.map +1 -1
  320. package/web/.svelte-kit/output/server/chunks/version.js +1 -1
  321. package/web/.svelte-kit/output/server/chunks/version.js.map +1 -1
  322. package/web/.svelte-kit/output/server/chunks/ws-handlers.js +2 -1
  323. package/web/.svelte-kit/output/server/chunks/ws-handlers.js.map +1 -1
  324. package/web/.svelte-kit/output/server/chunks/ws-messages.js +6 -1
  325. package/web/.svelte-kit/output/server/chunks/ws-messages.js.map +1 -1
  326. package/web/.svelte-kit/output/server/entries/pages/_layout.svelte.js +72 -45
  327. package/web/.svelte-kit/output/server/entries/pages/_layout.svelte.js.map +1 -1
  328. package/web/.svelte-kit/output/server/manifest-full.js +1 -1
  329. package/web/.svelte-kit/output/server/manifest.js +1 -1
  330. package/web/.svelte-kit/output/server/nodes/0.js +1 -1
  331. package/web/.svelte-kit/output/server/nodes/1.js +1 -1
  332. package/web/.svelte-kit/output/server/nodes/2.js +1 -1
  333. package/web/.svelte-kit/output/server/nodes/3.js +1 -1
  334. package/web/.svelte-kit/output/server/nodes/4.js +1 -1
  335. package/web/.svelte-kit/output/server/nodes/5.js +1 -1
  336. package/web/.svelte-kit/output/server/nodes/6.js +1 -1
  337. package/web/.svelte-kit/output/server/nodes/7.js +1 -1
  338. package/web/.svelte-kit/output/server/nodes/8.js +1 -1
  339. package/web/.svelte-kit/output/server/nodes/9.js +1 -1
  340. package/web/src/lib/components/AllSessionsPanel.svelte +9 -1
  341. package/web/src/lib/components/FolderPicker.svelte +49 -21
  342. package/dist/web/client/_app/immutable/chunks/CtjkAirr.js.map +0 -1
  343. package/dist/web/client/_app/immutable/chunks/Dck--FBb.js +0 -4
  344. package/dist/web/client/_app/immutable/chunks/Dck--FBb.js.map +0 -1
  345. package/dist/web/client/_app/immutable/entry/start.B2ZPizAt.js +0 -2
  346. package/dist/web/client/_app/immutable/entry/start.B2ZPizAt.js.map +0 -1
  347. package/dist/web/server/chunks/_layout.svelte-yrPX5VFm.js.map +0 -1
  348. package/dist/web/server/chunks/git-D9dLEKUF.js.map +0 -1
  349. package/dist/web/server/chunks/message-queue-sFcJCRjz.js.map +0 -1
  350. package/dist/web/server/chunks/version-BqEJmw2g.js.map +0 -1
  351. package/dist/web/server/chunks/ws-handlers-zemeJ8Si.js.map +0 -1
  352. package/dist/web/server/chunks/ws-messages-jOSwT1Yq.js.map +0 -1
  353. package/web/.svelte-kit/output/client/_app/immutable/chunks/CtjkAirr.js.map +0 -1
  354. package/web/.svelte-kit/output/client/_app/immutable/chunks/Dck--FBb.js +0 -4
  355. package/web/.svelte-kit/output/client/_app/immutable/chunks/Dck--FBb.js.map +0 -1
  356. package/web/.svelte-kit/output/client/_app/immutable/entry/start.B2ZPizAt.js +0 -2
  357. package/web/.svelte-kit/output/client/_app/immutable/entry/start.B2ZPizAt.js.map +0 -1
  358. package/web/.svelte-kit/output/client/_app/immutable/nodes/4.v1wYkrvS.js +0 -2
  359. package/web/.svelte-kit/output/client/_app/immutable/nodes/5.Bn4A77jK.js +0 -2
  360. package/web/.svelte-kit/output/client/_app/immutable/nodes/8.D7NtqIYy.js +0 -2
  361. package/web/.svelte-kit/output/client/_app/immutable/nodes/9.D-211z9-.js +0 -2
@@ -1 +1 @@
1
- {"version":3,"file":"git.js","sources":["../../../../../src/transcript/parser.ts","../../../../../src/server/watcher.ts","../../../../../src/transcript/changes.ts","../../../../../src/server/git.ts"],"sourcesContent":["/**\n * Incremental parser for Claude Code session JSONL transcripts.\n *\n * The JSONL format is an undocumented internal of Claude Code and changes\n * between versions (see docs/adr/0003). The parser is deliberately tolerant:\n * unknown line types and malformed lines are skipped, never thrown on.\n *\n * Folding rules discovered from live session files:\n * - The streamer writes one `assistant` line per content block; lines from the\n * same API response share `message.id`.\n * - A real user prompt has `message.content` as a plain string (or text\n * blocks) and `origin.kind === \"human\"`; tool results come back as `user`\n * lines whose content is an array of `tool_result` blocks.\n * - `toolUseResult` is a structured sidecar on tool_result lines, richer than\n * the in-message content (stdout/stderr for Bash, file data for Read, ...).\n */\n\nimport { readContextUsage, type ContextUsage } from \"./context.js\";\nimport { ForkTracker } from \"./forks.js\";\nimport { asRecord, readString } from \"./json.js\";\nimport { parseMcpToolName } from \"./mcp.js\";\n\nexport type TranscriptEntry = (\n | {\n kind: \"user\";\n id: string;\n ts: number;\n text: string;\n /**\n * Set when the prompt was a slash command, so the UI can style it.\n * `output` is what a local command printed back — \"Set model to Fable\" —\n * which the log records as a user line of its own, wrapped in\n * <local-command-stdout>, right after the command.\n */\n command?: { name: string; args?: string; output?: string };\n /** Set when the prompt was dictated by voice (see dictation-marks). */\n dictated?: boolean;\n }\n /** A prompt typed mid-turn. By the time its queued_command line reaches the\n * file it has already been seen by the agent — most never get a user line\n * of their own (the harness injects them into tool results instead), so\n * this IS the user turn. `delivered` marks the rare double-delivery case\n * where a real user line with the same text follows; the UI hides those. */\n | { kind: \"queued\"; id: string; ts: number; text: string; delivered?: boolean; dictated?: boolean }\n /** A cross-session (agent-to-agent) message from another Claude session. */\n | { kind: \"peer\"; id: string; ts: number; text: string; from?: string }\n /**\n * Claude Code's own record that the user pressed Escape. It is logged as a\n * user line but is the harness's note, not something anyone typed.\n */\n | { kind: \"interrupt\"; id: string; ts: number; text: string }\n /**\n * The conversation was compacted here: everything above was folded into\n * the summary Claude Code wrote, which arrives as the next user line and\n * is attached to this entry rather than shown as a prompt.\n */\n | {\n kind: \"compact\";\n id: string;\n ts: number;\n /** \"manual\" for /compact, \"auto\" when the context window filled. */\n trigger: string;\n preTokens?: number;\n postTokens?: number;\n summary?: string;\n }\n /** An AskUserQuestion dialog: interactive while unanswered. */\n | {\n kind: \"ask\";\n id: string;\n ts: number;\n questions: AskQuestion[];\n /** question text -> chosen answer, from toolUseResult.answers. */\n answers?: Record<string, string>;\n rejected?: boolean;\n }\n | { kind: \"text\"; id: string; ts: number; text: string }\n | { kind: \"thinking\"; id: string; ts: number; text: string }\n | {\n kind: \"tool\";\n id: string;\n ts: number;\n name: string;\n summary: string;\n input: string;\n /** `images` are files Claude Code saved for image results (screenshots). */\n result?: { ok: boolean; output: string; images?: string[] };\n /** Git-style hunks from the Edit/Write sidecar's structuredPatch. */\n patch?: { file: string; hunks: PatchHunk[] };\n }\n) & {\n /** Set on everything a later rewind went back past: a branch the conversation no longer follows. */\n rewound?: boolean;\n};\n\nexport interface AskQuestion {\n header: string;\n question: string;\n multiSelect: boolean;\n /** `preview` is the panel the dialog draws beside the option while it is highlighted. */\n options: { label: string; description?: string; preview?: string }[];\n}\n\n/** The tags Claude Code wraps a slash command in; \\1 pairs open with close. */\nconst COMMAND_TAG = /<command-(name|message|args)>([\\s\\S]*?)<\\/command-\\1>/g;\n\n/**\n * A slash command reaches the log as a user line whose whole content is a\n * bundle of <command-name>/<command-message>/<command-args> tags. Read the\n * command out of it so the transcript shows \"/simplify e push\" instead of the\n * raw markup.\n */\nexport function parseSlashCommand(content: string): { name: string; args?: string } | null {\n const trimmed = content.trim();\n // Cheap reject first: every other prompt in the file skips the regex.\n if (!trimmed.startsWith(\"<command-\")) return null;\n const tags: Record<string, string> = {};\n // Tag order varies by Claude Code version (name-first in older logs,\n // message-first in newer ones), so collect by name rather than by position.\n for (const match of trimmed.matchAll(COMMAND_TAG)) tags[match[1]] = match[2].trim();\n const name = tags.name;\n // No <command-name> means this is not a command line after all — leave the\n // content alone rather than rendering a half-parsed guess.\n if (!name) return null;\n // <command-message> is the harness's own echo of the name; it adds nothing\n // the UI can show, and empty <command-args> must not become a trailing space.\n return { name, ...(tags.args ? { args: tags.args } : {}) };\n}\n\n/** What a local command printed, as the log wraps it; \\1 pairs open with close. */\nconst LOCAL_OUTPUT_TAG = /^<local-command-(stdout|stderr)>([\\s\\S]*?)<\\/local-command-\\1>/;\n\n/** A terminal styling sequence (colour, dim, reset) left in logged output. */\n// eslint-disable-next-line no-control-regex\nconst ANSI_SGR = /\\x1b\\[[0-9;]*m/g;\n\n/**\n * The caveat the harness writes ahead of a local command's lines. It is meant\n * for the model, not the reader, and is usually flagged isMeta — but not in\n * every version, so it is recognised by shape too.\n */\nconst LOCAL_CAVEAT = /^<local-command-caveat>/;\n\n/** What Claude Code logs when Escape stops a turn, with or without \"for tool use\". */\nconst INTERRUPT_MARKER = /^\\[Request interrupted (by user[^\\]]*)\\]$/;\n\n/** The note an interrupt marker reads as, or null when the text is not one. */\nexport function interruptNote(text: string): string | null {\n const m = INTERRUPT_MARKER.exec(text.trim());\n return m ? `Interrupted ${m[1]}` : null;\n}\n\n/**\n * Read what a local command printed out of the user line that carries it.\n *\n * A local command (`/model`, `/cost`, `/context`) never reaches the model:\n * the harness runs it and logs three user lines — a caveat, the command, and\n * its output wrapped in <local-command-stdout>. The output belongs under the\n * command it answers, not in a turn of its own dressed as a prompt.\n *\n * @returns The output's text, or null when the line is something else.\n */\nfunction parseLocalOutput(content: string): string | null {\n const trimmed = content.trim();\n if (!trimmed.startsWith(\"<local-command-\")) return null;\n const chunks: string[] = [];\n let rest = trimmed;\n for (let m = rest.match(LOCAL_OUTPUT_TAG); m; m = rest.match(LOCAL_OUTPUT_TAG)) {\n // Some commands print styled — `/compact` dims its line — and the log\n // keeps the escape codes.\n const text = m[2].replace(ANSI_SGR, \"\").trim();\n if (text) chunks.push(m[1] === \"stderr\" ? `[stderr]\\n${text}` : text);\n rest = rest.slice(m[0].length).trimStart();\n }\n // Not an output line after all — leave it to the caller.\n if (chunks.length === 0 && !LOCAL_OUTPUT_TAG.test(trimmed)) return null;\n return chunks.join(\"\\n\");\n}\n\nfunction parseAskQuestions(input: Record<string, unknown>): AskQuestion[] {\n const raw = input.questions;\n if (!Array.isArray(raw)) return [];\n const questions: AskQuestion[] = [];\n for (const entry of raw) {\n const q = asRecord(entry);\n if (!q) continue;\n const options = Array.isArray(q.options)\n ? q.options\n .map((o) => asRecord(o))\n .filter((o): o is Record<string, unknown> => o !== null)\n .map((o) => ({\n label: readString(o.label) ?? \"\",\n ...(readString(o.description) ? { description: readString(o.description)! } : {}),\n ...(readString(o.preview) ? { preview: readString(o.preview)! } : {}),\n }))\n .filter((o) => o.label.length > 0)\n : [];\n questions.push({\n header: readString(q.header) ?? \"\",\n question: readString(q.question) ?? \"\",\n multiSelect: q.multiSelect === true,\n options,\n });\n }\n return questions;\n}\n\nexport interface PatchHunk {\n header: string;\n /** Unified-diff lines, first char is \"+\", \"-\" or \" \". */\n lines: string[];\n}\n\nconst PATCH_LINE_LIMIT = 400;\n\n/**\n * A sidecar's `structuredPatch` as hunks, with at most `limit` lines kept\n * across them and a note standing in for the rest.\n */\nexport function readStructuredPatch(raw: unknown, limit = Infinity): PatchHunk[] {\n if (!Array.isArray(raw)) return [];\n const hunks: PatchHunk[] = [];\n let total = 0;\n for (const entry of raw) {\n const hunk = asRecord(entry);\n if (!hunk || !Array.isArray(hunk.lines)) continue;\n const lines = hunk.lines.filter((line): line is string => typeof line === \"string\");\n if (lines.length === 0) continue;\n const kept = lines.slice(0, Math.max(0, limit - total));\n if (kept.length < lines.length) kept.push(`… ${lines.length - kept.length} more lines`);\n total += kept.length;\n hunks.push({\n header: `@@ -${hunk.oldStart ?? \"?\"},${hunk.oldLines ?? \"?\"} +${hunk.newStart ?? \"?\"},${hunk.newLines ?? \"?\"} @@`,\n lines: kept,\n });\n if (total >= limit) break;\n }\n return hunks;\n}\n\nfunction extractPatch(sidecar: unknown): { file: string; hunks: PatchHunk[] } | undefined {\n const sc = asRecord(sidecar);\n const hunks = readStructuredPatch(sc?.structuredPatch, PATCH_LINE_LIMIT);\n if (hunks.length === 0) return undefined;\n return { file: readString(sc?.filePath) ?? \"\", hunks };\n}\n\nconst INPUT_CHAR_LIMIT = 4_000;\nconst RESULT_CHAR_LIMIT = 8_000;\nconst TEXT_CHAR_LIMIT = 64_000;\n\nfunction truncate(text: string, limit: number): string {\n if (text.length <= limit) return text;\n return `${text.slice(0, limit)}\\n… [truncated, ${text.length - limit} more chars]`;\n}\n\nfunction parseTimestamp(value: unknown): number {\n const ts = typeof value === \"string\" ? Date.parse(value) : NaN;\n return Number.isFinite(ts) ? ts : Date.now();\n}\n\n/** Arguments that name what a built-in tool call acts on, best first. */\nconst BUILTIN_KEY_ARGS = [\n \"command\",\n \"file_path\",\n \"pattern\",\n \"url\",\n \"query\",\n \"description\",\n \"prompt\",\n \"skill\",\n];\n/** Arguments that say most about an MCP call, best first. */\nconst MCP_KEY_ARGS = [\n \"url\",\n \"uid\",\n \"key\",\n \"function\",\n \"query\",\n \"command\",\n \"file_path\",\n \"path\",\n \"selector\",\n \"text\",\n \"name\",\n \"title\",\n];\n/** The fallback argument is the first string short enough to read at a glance. */\nconst MCP_SHORT_ARG = 80;\n\nfunction firstString(input: Record<string, unknown>, keys: string[]): string | null {\n for (const key of keys) {\n const value = readString(input[key]);\n if (value?.trim()) return value;\n }\n return null;\n}\n\nfunction shortString(input: Record<string, unknown>): string | null {\n for (const value of Object.values(input)) {\n if (typeof value === \"string\" && value.trim() && value.length <= MCP_SHORT_ARG) return value;\n }\n return null;\n}\n\n/**\n * One-line human summary of a tool invocation: name + its key argument. An\n * MCP tool reads as its bare tool name; the server is left to the caller,\n * which can parse it out of the raw name with parseMcpToolName.\n */\nexport function summarizeToolUse(rawName: string, input: Record<string, unknown>): string {\n const mcp = parseMcpToolName(rawName);\n const name = mcp?.tool ?? rawName;\n const key = mcp\n ? (firstString(input, MCP_KEY_ARGS) ?? shortString(input))\n : firstString(input, BUILTIN_KEY_ARGS);\n if (!key) return name;\n const flat = key.replace(/\\s+/g, \" \").trim();\n return `${name}: ${flat.length > 120 ? `${flat.slice(0, 117)}...` : flat}`;\n}\n\n/** Claude Code saves an image result to disk and says where in a text part. */\nconst IMAGE_SOURCE = /^\\[Image: source: (.+?)(?:, original [^\\]]*)?\\]/;\n\n/** The saved files behind a tool result's images, in order. */\nfunction toolResultImages(blockContent: unknown): string[] {\n if (!Array.isArray(blockContent)) return [];\n const paths: string[] = [];\n for (const part of blockContent) {\n const match = IMAGE_SOURCE.exec(readString(asRecord(part)?.text) ?? \"\");\n if (match) paths.push(match[1].trim());\n }\n return paths;\n}\n\n/** Flatten a tool_result / toolUseResult payload into displayable text. */\nfunction toolResultText(sidecar: unknown, blockContent: unknown): string {\n const sc = asRecord(sidecar);\n if (sc) {\n const stdout = readString(sc.stdout);\n const stderr = readString(sc.stderr);\n if (stdout !== null || stderr !== null) {\n return [stdout, stderr && stderr.length > 0 ? `[stderr]\\n${stderr}` : null]\n .filter((part): part is string => part !== null && part.length > 0)\n .join(\"\\n\");\n }\n }\n if (typeof blockContent === \"string\") return blockContent;\n if (Array.isArray(blockContent)) {\n // An image Claude Code saved to disk travels as `images` and is drawn as\n // one, so neither it nor the note naming its file belongs in the text.\n const saved = toolResultImages(blockContent).length;\n let unsaved = blockContent.filter((part) => asRecord(part)?.type === \"image\").length - saved;\n const parts = blockContent\n .map((part) => {\n const rec = asRecord(part);\n const text = readString(rec?.text) ?? \"\";\n // Screenshots and other image results carry no text; name the file the\n // sidecar saved instead of rendering an empty result.\n if (rec?.type === \"image\") {\n return unsaved-- > 0 ? (readString(sc?.file) ?? \"[image]\") : \"\";\n }\n return IMAGE_SOURCE.test(text) ? \"\" : text;\n })\n .filter((text) => text.length > 0);\n if (parts.length > 0 || saved > 0) return parts.join(\"\\n\");\n }\n if (sc) {\n try {\n return JSON.stringify(sc, null, 2);\n } catch {\n return \"\";\n }\n }\n return \"\";\n}\n\n/**\n * Stateful builder: feed raw JSONL lines in file order, read `entries` out.\n * `feed` returns the ids of entries it added or updated so a streaming caller\n * can broadcast only the delta.\n */\nexport class TranscriptBuilder {\n readonly entries: TranscriptEntry[] = [];\n /**\n * Subagents the harness has reported as finished. Background agents give no\n * other completion signal — their launching tool call returns immediately —\n * so this notification is the authoritative end, keyed by agent id.\n */\n readonly finishedAgents = new Set<string>();\n /**\n * Context-window usage of the most recent API response, or null before the\n * first one. Compaction needs no special handling: the response that\n * follows it reports the smaller context on its own.\n */\n context: ContextUsage | null = null;\n /** The model that wrote the latest assistant line, as the API names it. */\n model: string | null = null;\n /** The compaction logged last, whose summary is the next user line. */\n private lastCompactId: string | null = null;\n private indexById = new Map<string, number>();\n /** The slash command logged last, which a local command's output belongs to. */\n private lastCommandId: string | null = null;\n /** Queued prompts awaiting a possible re-delivery as a real user line. */\n private pendingQueued: { text: string; id: string }[] = [];\n private forks = new ForkTracker();\n /** The position of the line being fed, and of the line that first made each entry. */\n private seq = -1;\n private seqById = new Map<string, number>();\n\n /**\n * @param sidechain true when reading a subagent's own file, where every line\n * is marked `isSidechain` — the main transcript skips those, since subagent\n * work lives in its own file.\n * @param isDictated tells a prompt injected by voice from a typed one. The\n * JSONL carries no origin for this, so the caller re-derives it (by text and\n * time, see dictation-marks) and the builder stamps `dictated` at parse\n * time, where the flag survives re-upserts of the same entry.\n */\n constructor(\n private readonly sidechain = false,\n private readonly isDictated?: (text: string, ts: number) => boolean\n ) {}\n\n private dictatedFlag(text: string, ts: number): { dictated: true } | undefined {\n return this.isDictated?.(text, ts) ? { dictated: true } : undefined;\n }\n\n /** Position of an entry in `entries`, or undefined if it is not one. */\n indexOf(id: string): number | undefined {\n return this.indexById.get(id);\n }\n\n feed(line: string): string[] {\n const trimmed = line.trim();\n if (trimmed.length === 0) return [];\n let record: Record<string, unknown> | null;\n try {\n record = asRecord(JSON.parse(trimmed));\n } catch {\n return [];\n }\n if (!record) return [];\n if ((record.isSidechain === true) !== this.sidechain) return [];\n const uuid = readString(record.uuid);\n if (uuid) this.seq = this.forks.see(uuid, record.type);\n\n switch (record.type) {\n case \"user\":\n return this.feedUser(record);\n case \"assistant\":\n return this.feedAssistant(record);\n case \"attachment\":\n return this.feedAttachment(record);\n case \"system\":\n return this.feedSystem(record);\n default:\n return [];\n }\n }\n\n /**\n * The most recent user turn, when it is plain text reading exactly `text`\n * and nothing has been said since but the harness's own bookkeeping — the\n * compaction a `/compact` triggers, for one.\n */\n private recentPlainUserLine(text: string): Extract<TranscriptEntry, { kind: \"user\" }> | null {\n for (let i = this.entries.length - 1, seen = 0; i >= 0 && seen < 4; i--, seen++) {\n const entry = this.entries[i];\n if (entry.kind === \"compact\") continue;\n if (entry.kind !== \"user\") return null;\n return !entry.command && entry.text === text ? entry : null;\n }\n return null;\n }\n\n /**\n * A system line. The only one with a place in the transcript is the\n * compaction boundary: the reader needs to know where the conversation was\n * folded, or the summary that follows reads as a prompt they never typed.\n */\n private feedSystem(record: Record<string, unknown>): string[] {\n if (record.subtype !== \"compact_boundary\") return [];\n const uuid = readString(record.uuid) ?? `compact-${this.entries.length}`;\n const meta = asRecord(record.compactMetadata);\n const pre = typeof meta?.preTokens === \"number\" ? meta.preTokens : undefined;\n const post = typeof meta?.postTokens === \"number\" ? meta.postTokens : undefined;\n this.lastCompactId = uuid;\n return [\n this.upsert({\n kind: \"compact\",\n id: uuid,\n ts: parseTimestamp(record.timestamp),\n trigger: readString(meta?.trigger) ?? \"auto\",\n ...(pre !== undefined ? { preTokens: pre } : {}),\n ...(post !== undefined ? { postTokens: post } : {}),\n }),\n ];\n }\n\n private feedAttachment(record: Record<string, unknown>): string[] {\n const attachment = asRecord(record.attachment);\n if (!attachment || attachment.type !== \"queued_command\") return [];\n // Only human-typed prompts; system notifications also arrive queued.\n if (asRecord(attachment.origin)?.kind !== \"human\") return [];\n const prompt = readString(attachment.prompt);\n if (!prompt || prompt.trim().length === 0) return [];\n const uuid = readString(record.uuid) ?? `queued-${this.entries.length}`;\n const ts = parseTimestamp(record.timestamp ?? attachment.timestamp);\n this.pendingQueued.push({ text: prompt.trim(), id: uuid });\n return [\n this.upsert({\n kind: \"queued\",\n id: uuid,\n ts,\n text: truncate(prompt, TEXT_CHAR_LIMIT),\n ...this.dictatedFlag(prompt, ts),\n }),\n ];\n }\n\n /** Record a finished subagent from a harness task-notification. */\n private noteAgentFinished(text: string): void {\n const agentId = text.match(/<task-id>([^<]+)<\\/task-id>/)?.[1];\n const status = text.match(/<status>([^<]+)<\\/status>/)?.[1];\n if (agentId && status && status !== \"running\") this.finishedAgents.add(agentId);\n }\n\n /** Hide queued entries that a real user line re-delivers. The delivered\n * text may embed the queued prompt (harness wrapping), so match on exact\n * equality or prefix, not just identity. */\n private deliverQueued(text: string): string[] {\n const delivered = text.trim();\n const changed: string[] = [];\n this.pendingQueued = this.pendingQueued.filter((pending) => {\n if (delivered !== pending.text && !delivered.startsWith(pending.text)) return true;\n const entry = this.getEntry(pending.id);\n if (entry && entry.kind === \"queued\") {\n changed.push(this.upsert({ ...entry, delivered: true }));\n }\n return false;\n });\n return changed;\n }\n\n private upsert(entry: TranscriptEntry): string {\n const existing = this.indexById.get(entry.id);\n if (existing !== undefined) {\n this.entries[existing] = entry;\n } else {\n this.seqById.set(entry.id, this.seq);\n this.indexById.set(entry.id, this.entries.length);\n this.entries.push(entry);\n }\n return entry.id;\n }\n\n /**\n * A prompt that went back past what came before it (see ForkTracker): mark\n * every entry the old branch made as rewound, and answer their ids.\n */\n private rewindTo(record: Record<string, unknown>): string[] {\n const after = this.forks.abandonedAfter(readString(record.parentUuid));\n if (after === null) return [];\n const changed: string[] = [];\n this.entries.forEach((entry, i) => {\n const seq = this.seqById.get(entry.id);\n if (seq === undefined || seq <= after || entry.rewound) return;\n this.entries[i] = { ...entry, rewound: true };\n changed.push(entry.id);\n });\n return changed;\n }\n\n getEntry(id: string): TranscriptEntry | undefined {\n const index = this.indexById.get(id);\n return index === undefined ? undefined : this.entries[index];\n }\n\n private feedUser(record: Record<string, unknown>): string[] {\n const message = asRecord(record.message);\n if (!message) return [];\n const uuid = readString(record.uuid) ?? `user-${this.entries.length}`;\n const ts = parseTimestamp(record.timestamp);\n const content = message.content;\n\n // Cross-session (A2A) messages arrive as meta user lines with\n // origin.kind \"peer\"; origin.body is the clean text (message.content is\n // the harness-wrapped form) and origin.name the sender.\n const origin = asRecord(record.origin);\n if (origin?.kind === \"peer\") {\n const body =\n readString(origin.body) ?? (typeof content === \"string\" ? content : null);\n if (!body || body.trim().length === 0) return [];\n const from = readString(origin.name) ?? undefined;\n return [\n this.upsert({\n kind: \"peer\",\n id: uuid,\n ts,\n text: truncate(body, TEXT_CHAR_LIMIT),\n ...(from ? { from } : {}),\n }),\n ];\n }\n\n // The summary Claude Code wrote when it compacted: what the model reads\n // in place of the folded conversation, not something the user said.\n if (record.isCompactSummary === true && typeof content === \"string\") {\n const owner = this.lastCompactId ? this.getEntry(this.lastCompactId) : undefined;\n if (owner?.kind === \"compact\") {\n return [this.upsert({ ...owner, summary: truncate(content, TEXT_CHAR_LIMIT) })];\n }\n return [];\n }\n\n if (record.isMeta === true) return [];\n\n if (typeof content === \"string\") {\n if (content.trim().length === 0) return [];\n // Only human prompts render as turns. System-injected user lines (task\n // notifications, reminders) carry origin.kind !== \"human\"; when origin\n // is absent (older versions) fall back to sniffing system markers.\n const originKind = asRecord(record.origin)?.kind;\n if (originKind === \"task-notification\") {\n this.noteAgentFinished(content);\n return [];\n }\n if (originKind !== undefined && originKind !== \"human\") return [];\n if (originKind === undefined && /^<(task-notification|system-reminder)/.test(content.trim()))\n return [];\n if (LOCAL_CAVEAT.test(content.trimStart())) return [];\n const interrupt = interruptNote(content);\n if (interrupt) return [this.upsert({ kind: \"interrupt\", id: uuid, ts, text: interrupt })];\n // A local command's output rides under the command it answers, which is\n // the line logged just before it.\n const output = parseLocalOutput(content);\n if (output !== null) {\n if (output.length === 0) return [];\n const owner = this.lastCommandId ? this.getEntry(this.lastCommandId) : undefined;\n if (owner?.kind === \"user\" && owner.command) {\n return [\n this.upsert({\n ...owner,\n command: { ...owner.command, output: truncate(output, TEXT_CHAR_LIMIT) },\n }),\n ];\n }\n return [this.upsert({ kind: \"user\", id: uuid, ts, text: truncate(output, TEXT_CHAR_LIMIT) })];\n }\n // `text` stays the human-readable form of the turn either way, so search,\n // truncation and the queued-prompt matching below need no special case.\n const command = parseSlashCommand(content);\n if (command) {\n // A command pasted into the prompt is logged twice: first as the plain\n // text the user sent, then as the harness's own bundle once it ran.\n // Fold the bundle into that first line rather than showing a second.\n const spelled = `${command.name}${command.args ? ` ${command.args}` : \"\"}`;\n const typed = this.recentPlainUserLine(spelled);\n if (typed) {\n this.lastCommandId = typed.id;\n return [this.upsert({ ...typed, command })];\n }\n }\n this.lastCommandId = command ? uuid : null;\n const text = command\n ? `${command.name}${command.args ? ` ${command.args}` : \"\"}`\n : content;\n return [\n ...this.rewindTo(record),\n ...this.deliverQueued(content),\n this.upsert({\n kind: \"user\",\n id: uuid,\n ts,\n text: truncate(text, TEXT_CHAR_LIMIT),\n ...(command ? { command } : {}),\n ...this.dictatedFlag(text, ts),\n }),\n ];\n }\n\n if (!Array.isArray(content)) return [];\n const changed: string[] = [];\n const promptTexts: string[] = [];\n for (const block of content) {\n const rec = asRecord(block);\n if (!rec) continue;\n if (rec.type === \"tool_result\") {\n // Tool and ask entries are keyed by their tool_use id.\n const toolUseId = readString(rec.tool_use_id);\n const entry = toolUseId ? this.getEntry(toolUseId) : undefined;\n if (!entry) continue;\n if (entry.kind === \"ask\") {\n const sidecar = asRecord(record.toolUseResult);\n const answersRaw = asRecord(sidecar?.answers);\n if (answersRaw) {\n const answers: Record<string, string> = {};\n for (const [q, a] of Object.entries(answersRaw)) {\n if (typeof a === \"string\") answers[q] = a;\n }\n changed.push(this.upsert({ ...entry, answers }));\n } else {\n changed.push(this.upsert({ ...entry, rejected: true }));\n }\n continue;\n }\n if (entry.kind !== \"tool\") continue;\n const patch = extractPatch(record.toolUseResult);\n // With a patch the textual output is redundant boilerplate — keep it\n // only for failures.\n const output =\n patch && rec.is_error !== true ? \"\" : toolResultText(record.toolUseResult, rec.content);\n const images = toolResultImages(rec.content);\n changed.push(\n this.upsert({\n ...entry,\n result: {\n ok: rec.is_error !== true,\n output: truncate(output, RESULT_CHAR_LIMIT),\n ...(images.length > 0 ? { images } : {}),\n },\n ...(patch ? { patch } : {}),\n }),\n );\n } else if (rec.type === \"text\") {\n const text = readString(rec.text);\n if (text && text.trim().length > 0) promptTexts.push(text);\n }\n }\n const interrupt = promptTexts.length === 1 ? interruptNote(promptTexts[0]) : null;\n if (interrupt) {\n changed.push(this.upsert({ kind: \"interrupt\", id: uuid, ts, text: interrupt }));\n } else if (promptTexts.length > 0) {\n changed.push(\n ...this.rewindTo(record),\n this.upsert({\n kind: \"user\",\n id: uuid,\n ts,\n text: truncate(promptTexts.join(\"\\n\\n\"), TEXT_CHAR_LIMIT),\n ...this.dictatedFlag(promptTexts.join(\"\\n\\n\"), ts),\n }),\n );\n }\n return changed;\n }\n\n private feedAssistant(record: Record<string, unknown>): string[] {\n const message = asRecord(record.message);\n if (message) this.context = readContextUsage(message) ?? this.context;\n if (message) this.model = readString(message.model) ?? this.model;\n const content = message?.content;\n if (!Array.isArray(content)) return [];\n const uuid = readString(record.uuid) ?? `assistant-${this.entries.length}`;\n const ts = parseTimestamp(record.timestamp);\n const changed: string[] = [];\n\n for (let i = 0; i < content.length; i++) {\n const block = asRecord(content[i]);\n if (!block) continue;\n const blockId = `${uuid}:${i}`;\n switch (block.type) {\n case \"text\": {\n const text = readString(block.text);\n if (text && text.trim().length > 0) {\n changed.push(\n this.upsert({ kind: \"text\", id: blockId, ts, text: truncate(text, TEXT_CHAR_LIMIT) }),\n );\n }\n break;\n }\n case \"thinking\": {\n const text = readString(block.thinking);\n // Thinking lines can carry only a signature with empty text — skip those.\n if (text && text.trim().length > 0) {\n changed.push(\n this.upsert({\n kind: \"thinking\",\n id: blockId,\n ts,\n text: truncate(text, TEXT_CHAR_LIMIT),\n }),\n );\n }\n break;\n }\n case \"tool_use\": {\n const toolUseId = readString(block.id) ?? blockId;\n const name = readString(block.name) ?? \"tool\";\n const input = asRecord(block.input) ?? {};\n if (name === \"AskUserQuestion\") {\n const questions = parseAskQuestions(input);\n if (questions.length > 0) {\n changed.push(this.upsert({ kind: \"ask\", id: toolUseId, ts, questions }));\n break;\n }\n }\n let inputText: string;\n try {\n inputText = JSON.stringify(input, null, 2);\n } catch {\n inputText = \"{}\";\n }\n changed.push(\n this.upsert({\n kind: \"tool\",\n id: toolUseId,\n ts,\n name,\n summary: summarizeToolUse(name, input),\n input: truncate(inputText, INPUT_CHAR_LIMIT),\n }),\n );\n break;\n }\n }\n }\n return changed;\n }\n}\n","import { readdirSync, statSync } from \"fs\";\nimport { SESSIONS_DIR } from \"../utils/paths.js\";\nimport { join } from \"path\";\n\nexport interface WatcherCallback {\n /** `changed` holds the ids of the sessions whose JSON was added, changed or removed. */\n (changed: ReadonlySet<string>): void;\n}\n\n/** A session's JSON is named after its id. */\nfunction sessionIdOf(file: string): string {\n return file.slice(0, -\".json\".length);\n}\n\n/**\n * Simple polling-based file watcher for session JSON files.\n * More reliable than inotify for long-running processes.\n */\nclass SessionWatcher {\n private subscribers = new Set<WatcherCallback>();\n private pollTimer: ReturnType<typeof setInterval> | null = null;\n private lastState = new Map<string, number>(); // filename -> mtime\n private readonly pollInterval = 500;\n\n private start(): void {\n if (this.pollTimer) return;\n\n console.log(\"[watcher] Started polling\", SESSIONS_DIR, `(${this.pollInterval}ms)`);\n\n // Initialize state\n this.updateState();\n\n this.pollTimer = setInterval(() => {\n const changed = this.checkForChanges();\n if (changed.size > 0) {\n this.notifySubscribers(changed);\n }\n }, this.pollInterval);\n }\n\n private updateState(): void {\n this.lastState.clear();\n try {\n const files = readdirSync(SESSIONS_DIR);\n for (const file of files) {\n if (!file.endsWith(\".json\")) continue;\n try {\n const stat = statSync(join(SESSIONS_DIR, file));\n this.lastState.set(file, stat.mtimeMs);\n } catch {\n // File may have been deleted\n }\n }\n } catch {\n // Directory may not exist yet\n }\n }\n\n private checkForChanges(): Set<string> {\n const newState = new Map<string, number>();\n const changed = new Set<string>();\n\n try {\n const files = readdirSync(SESSIONS_DIR);\n for (const file of files) {\n if (!file.endsWith(\".json\")) continue;\n try {\n const stat = statSync(join(SESSIONS_DIR, file));\n newState.set(file, stat.mtimeMs);\n\n const oldMtime = this.lastState.get(file);\n if (oldMtime !== stat.mtimeMs) {\n console.log(`[watcher] File ${oldMtime === undefined ? \"added\" : \"changed\"}:`, file);\n changed.add(sessionIdOf(file));\n }\n } catch {\n // File may have been deleted during iteration\n }\n }\n\n // Check for deleted files\n for (const file of this.lastState.keys()) {\n if (!newState.has(file)) {\n console.log(\"[watcher] File removed:\", file);\n changed.add(sessionIdOf(file));\n }\n }\n } catch {\n // Directory may not exist\n }\n\n this.lastState = newState;\n return changed;\n }\n\n private notifySubscribers(changed: ReadonlySet<string>): void {\n console.log(\"[watcher] Notifying\", this.subscribers.size, \"subscribers\");\n for (const callback of this.subscribers) {\n try {\n callback(changed);\n } catch (error) {\n console.error(\"[watcher] Subscriber error:\", error);\n }\n }\n }\n\n subscribe(callback: WatcherCallback): () => void {\n this.subscribers.add(callback);\n if (this.subscribers.size === 1) {\n this.start();\n }\n return () => {\n this.subscribers.delete(callback);\n if (this.subscribers.size === 0) {\n this.stop();\n }\n };\n }\n\n private stop(): void {\n if (this.pollTimer) {\n clearInterval(this.pollTimer);\n this.pollTimer = null;\n }\n this.lastState.clear();\n console.log(\"[watcher] Stopped\");\n }\n}\n\nexport const sessionWatcher = new SessionWatcher();\n","/**\n * What a session changed, read off its own log.\n *\n * Every Edit, Write, MultiEdit and NotebookEdit result carries a sidecar\n * (`toolUseResult`) with the file it touched and the patch it applied, as\n * git-style hunks in `structuredPatch`. A Write that created the file says\n * `type: \"create\"` and leaves the patch empty, so its whole `content` is the\n * addition. Nothing here reads the disk: the log is the record, which is what\n * lets this source cover files outside any repo — and what makes it blind to\n * changes made through Bash.\n *\n * The collector groups changes by turn — a prompt the user typed (or a slash\n * command they ran) up to the next one — keyed by that prompt line's uuid, the\n * same id the transcript gives the prompt's entry.\n */\n\nimport { asRecord, readString } from \"./json.js\";\nimport { peekTranscriptPath } from \"./context-peek.js\";\nimport { JsonlTailer } from \"./tailer.js\";\nimport { ForkTracker } from \"./forks.js\";\nimport { interruptNote, parseSlashCommand, readStructuredPatch, type PatchHunk } from \"./parser.js\";\n\nexport type FileChangeKind = \"added\" | \"modified\" | \"deleted\";\n\n/** One tool call's change to one file. */\nexport interface FileChange {\n file: string;\n kind: FileChangeKind;\n additions: number;\n deletions: number;\n hunks: PatchHunk[];\n}\n\n/** A file's change as counted, without its hunks — what a list draws. */\nexport type FileChangeCount = Omit<FileChange, \"hunks\">;\n\nexport interface TurnChanges {\n /** The prompt line's uuid, or null for changes logged before any prompt. */\n id: string | null;\n /** The turn's place in the session, counting every prompt from 1; 0 before the first. */\n n: number;\n ts: number;\n /** The prompt, cut to a line, so a list can say which turn this was. */\n prompt: string;\n files: FileChangeCount[];\n}\n\nexport interface ChangesSummary {\n files: number;\n additions: number;\n deletions: number;\n}\n\n/** Totals over a list of counted files. */\nexport function summarize(files: { additions: number; deletions: number }[]): ChangesSummary {\n return {\n files: files.length,\n additions: files.reduce((n, f) => n + f.additions, 0),\n deletions: files.reduce((n, f) => n + f.deletions, 0),\n };\n}\n\n/** Edit and MultiEdit name the file `filePath`; NotebookEdit names it `notebook_path`. */\nfunction sidecarFile(sc: Record<string, unknown>): string | null {\n return readString(sc.filePath) ?? readString(sc.notebook_path);\n}\n\nfunction countLines(hunks: PatchHunk[]): { additions: number; deletions: number } {\n let additions = 0;\n let deletions = 0;\n for (const hunk of hunks) {\n for (const line of hunk.lines) {\n if (line.startsWith(\"+\")) additions++;\n else if (line.startsWith(\"-\")) deletions++;\n }\n }\n return { additions, deletions };\n}\n\n/** A new file's content as the one hunk that adds it. */\nfunction creationHunk(content: string): PatchHunk[] {\n const lines = content.split(\"\\n\");\n if (lines[lines.length - 1] === \"\") lines.pop();\n if (lines.length === 0) return [];\n return [{ header: `@@ -0,0 +1,${lines.length} @@`, lines: lines.map((line) => `+${line}`) }];\n}\n\n/**\n * The change a tool result's sidecar records, or null when the sidecar is not\n * a file edit. A Write counts as adding the file when it says it created it,\n * or when it carries content but no `originalFile` to have changed.\n */\nexport function fileChangeFromSidecar(sidecar: unknown): FileChange | null {\n const sc = asRecord(sidecar);\n if (!sc || !(\"structuredPatch\" in sc)) return null;\n const file = sidecarFile(sc);\n if (!file) return null;\n const content = readString(sc.content);\n const created =\n sc.type === \"create\" || (sc.type === undefined && content !== null && !(\"originalFile\" in sc));\n let hunks = readStructuredPatch(sc.structuredPatch);\n if (created && hunks.length === 0 && content !== null) hunks = creationHunk(content);\n return { file, kind: created ? \"added\" : \"modified\", ...countLines(hunks), hunks };\n}\n\n/** Prompts the harness wrote rather than a person: notifications, reminders, a local command's lines. */\nconst HARNESS_PROMPT = /^<(task-notification|system-reminder|local-command-)/;\n\n/** The text that opens a turn, or null when the line is not a prompt. */\nexport function promptText(record: Record<string, unknown>): string | null {\n if (record.isMeta === true || record.isCompactSummary === true) return null;\n const kind = asRecord(record.origin)?.kind;\n if (kind !== undefined && kind !== \"human\") return null;\n const content = asRecord(record.message)?.content;\n let text: string;\n if (typeof content === \"string\") text = content;\n else if (Array.isArray(content)) {\n const parts: string[] = [];\n for (const block of content) {\n const rec = asRecord(block);\n if (rec?.type === \"tool_result\") return null;\n const part = rec?.type === \"text\" ? readString(rec.text) : null;\n if (part) parts.push(part);\n }\n text = parts.join(\"\\n\");\n } else return null;\n text = text.trim();\n if (!text || HARNESS_PROMPT.test(text) || interruptNote(text)) return null;\n const command = parseSlashCommand(text);\n if (command) text = command.args ? `${command.name} ${command.args}` : command.name;\n const firstLine = text.split(\"\\n\", 1)[0];\n return firstLine.length > 120 ? `${firstLine.slice(0, 117)}...` : firstLine;\n}\n\n/** Whether a prompt line is the harness's record of a slash command. */\nfunction isCommand(record: Record<string, unknown>): boolean {\n const content = asRecord(record.message)?.content;\n return typeof content === \"string\" && parseSlashCommand(content.trim()) !== null;\n}\n\nexport function parseTs(value: unknown): number {\n const ts = typeof value === \"string\" ? Date.parse(value) : NaN;\n return Number.isFinite(ts) ? ts : 0;\n}\n\ninterface Turn {\n id: string | null;\n /** The prompt line's position in the log, for telling which turns a rewind left behind. */\n seq: number;\n n: number;\n ts: number;\n prompt: string;\n /** Per file, every change in order. */\n changes: Map<string, FileChange[]>;\n}\n\n/** Fold several changes to one file into a single count. */\nfunction count(file: string, changes: FileChange[]): FileChangeCount {\n return {\n file,\n // Created at some point in the run means new to whoever reads the run.\n kind: changes[0].kind,\n additions: changes.reduce((n, c) => n + c.additions, 0),\n deletions: changes.reduce((n, c) => n + c.deletions, 0),\n };\n}\n\n/** Fold several changes to one file into a single change, hunks and all. */\nfunction merge(file: string, changes: FileChange[]): FileChange {\n return { ...count(file, changes), hunks: changes.flatMap((c) => c.hunks) };\n}\n\n/**\n * Feed a session's JSONL lines in file order; read the changes out per turn\n * or per session. Lines that cannot carry a change or open a turn are passed\n * over before parsing, so catching up on a long log costs little more than\n * reading it.\n */\nexport class ChangesCollector {\n private turns: Turn[] = [];\n /** tool_use ids already counted, so a line written twice is counted once. */\n private seen = new Set<string>();\n private forks = new ForkTracker();\n\n feed(line: string): void {\n // A tool result without a patch can neither change a file nor open a turn,\n // but every line of the conversation (which opens with its parentUuid) has\n // to be placed for a rewind to be told from a prompt that follows on.\n const carriesChange = line.includes('\"structuredPatch\"');\n const mayOpen = line.includes('\"type\":\"user\"') && !line.includes('\"tool_result\"');\n if (!carriesChange && !mayOpen && !line.startsWith('{\"parentUuid\"')) return;\n let record: Record<string, unknown> | null;\n try {\n record = asRecord(JSON.parse(line));\n } catch {\n return;\n }\n if (!record || record.isSidechain === true) return;\n const uuid = readString(record.uuid);\n const seq = uuid ? this.forks.see(uuid, record.type) : -1;\n if (record.type !== \"user\" || (!carriesChange && !mayOpen)) return;\n\n if (carriesChange) {\n const change = fileChangeFromSidecar(record.toolUseResult);\n if (!change) return;\n const content = asRecord(record.message)?.content;\n const result = Array.isArray(content)\n ? content.map(asRecord).find((block) => block?.type === \"tool_result\")\n : undefined;\n const toolUseId = readString(result?.tool_use_id);\n if (toolUseId) {\n if (this.seen.has(toolUseId)) return;\n this.seen.add(toolUseId);\n }\n let turn = this.turns[this.turns.length - 1];\n if (!turn) {\n turn = { id: null, seq: -1, n: 0, ts: parseTs(record.timestamp), prompt: \"\", changes: new Map() };\n this.turns.push(turn);\n }\n const list = turn.changes.get(change.file);\n if (list) list.push(change);\n else turn.changes.set(change.file, [change]);\n return;\n }\n\n const prompt = promptText(record);\n if (prompt === null) return;\n // A command pasted into the prompt is logged twice: the text as typed, then\n // the harness's bundle once it ran. The transcript folds the bundle into the\n // first line, and so does this: one turn, under the first line's id.\n const last = this.turns[this.turns.length - 1];\n if (last && last.changes.size === 0 && last.prompt === prompt && isCommand(record)) return;\n // A rewind went back past the turns after its point, and with them their\n // changes, which Claude Code restored when it was asked to.\n const after = this.forks.abandonedAfter(readString(record.parentUuid));\n if (after !== null) this.turns = this.turns.filter((turn) => turn.seq <= after);\n this.turns.push({\n id: uuid,\n seq,\n n: (this.turns[this.turns.length - 1]?.n ?? 0) + 1,\n ts: parseTs(record.timestamp),\n prompt,\n changes: new Map(),\n });\n }\n\n /** The id of every turn's prompt, changed something or not, oldest first. */\n promptIds(): string[] {\n return this.turns.flatMap((turn) => (turn.id ? [turn.id] : []));\n }\n\n /** The turns that changed something, oldest first. */\n byTurn(): TurnChanges[] {\n return this.turns\n .filter((turn) => turn.changes.size > 0)\n .map((turn) => ({\n id: turn.id,\n n: turn.n,\n ts: turn.ts,\n prompt: turn.prompt,\n files: [...turn.changes].map(([file, list]) => count(file, list)),\n }));\n }\n\n /** Every change to each file over every turn, in the order first touched. */\n private perFile(): Map<string, FileChange[]> {\n const all = new Map<string, FileChange[]>();\n for (const turn of this.turns) {\n for (const [file, list] of turn.changes) {\n const prior = all.get(file);\n if (prior) prior.push(...list);\n else all.set(file, [...list]);\n }\n }\n return all;\n }\n\n /** Each file the session changed, folded over every turn, in the order first touched. */\n files(): FileChange[] {\n return [...this.perFile()].map(([file, list]) => merge(file, list));\n }\n\n /** As `files()`, counted without folding any hunks. */\n counts(): FileChangeCount[] {\n return [...this.perFile()].map(([file, list]) => count(file, list));\n }\n\n /** One file's change: over the whole session, or within the turn `turnId` names. */\n file(file: string, turnId?: string | null): FileChange | null {\n const list =\n turnId === undefined\n ? this.perFile().get(file)\n : this.turns.find((turn) => turn.id === turnId)?.changes.get(file);\n return list ? merge(file, list) : null;\n }\n\n summary(): ChangesSummary {\n return summarize(this.counts());\n }\n}\n\n// ---------------------------------------------------------------------------\n// One collector per transcript, caught up from where it last read.\n// ---------------------------------------------------------------------------\n\ninterface Tracked {\n tailer: JsonlTailer;\n collector: ChangesCollector;\n usedAt: number;\n}\n\n/** A log nobody has asked about for this long is dropped, hunks and all. */\nconst FORGET_MS = 10 * 60_000;\n\nconst tracked = new Map<string, Tracked>();\n\n/** Forget everything — for tests. */\nexport function resetChangesCache(): void {\n tracked.clear();\n}\n\n/**\n * The session's changes as its log has them now, or null when it has no log\n * yet. The first call reads the whole file; later ones read only what was\n * appended since.\n */\nexport function sessionChanges(session: {\n id: string;\n cwd: string;\n transcript_path?: string | null;\n}): ChangesCollector | null {\n const path = peekTranscriptPath(session);\n if (!path) return null;\n const now = Date.now();\n for (const [other, entry] of tracked) if (now - entry.usedAt > FORGET_MS) tracked.delete(other);\n let t = tracked.get(path);\n if (!t) {\n t = { tailer: new JsonlTailer(path), collector: new ChangesCollector(), usedAt: now };\n tracked.set(path, t);\n }\n t.usedAt = now;\n for (;;) {\n const read = t.tailer.read();\n if (read.status === \"reset\") {\n t.collector = new ChangesCollector();\n continue;\n }\n if (read.status === \"lines\") for (const line of read.lines) t.collector.feed(line);\n return t.collector;\n }\n}\n","/**\n * What git says changed in the repo a session works in — the \"Current\"\n * source of the Changes panel, which catches edits made through Bash that\n * the session's log never records.\n *\n * Every call goes through `execFile` with an argument list, never a shell,\n * and every path a caller names is checked against the repo root before git\n * sees it. Status is cached per repo and re-read only when a session in the\n * repo writes its JSON (each hook event does), and then at most once every\n * REFRESH_MS: there is no timer polling git.\n */\n\nimport { execFile } from 'child_process';\nimport { closeSync, openSync, readSync, statSync } from 'fs';\nimport { isAbsolute, relative, resolve, sep } from 'path';\nimport type { PatchHunk } from '../transcript/parser.js';\nimport { summarize, type ChangesSummary } from '../transcript/changes.js';\nimport { getSession } from '../db/sessions-json.js';\nimport { sessionWatcher } from './watcher.js';\n\nexport type GitFileKind = 'added' | 'modified' | 'deleted' | 'renamed';\n\nexport interface GitFileStatus {\n\t/** Relative to the repo root, `/`-separated as git prints it. */\n\tfile: string;\n\t/** Where a renamed or copied file came from. */\n\toldPath?: string;\n\tkind: GitFileKind;\n\tuntracked?: true;\n\tbinary?: true;\n\tadditions: number;\n\tdeletions: number;\n}\n\nexport interface GitChanges {\n\troot: string;\n\tfiles: GitFileStatus[];\n\t/** What the counts are taken against: HEAD, or the empty tree before the first commit. */\n\tbase: string;\n}\n\nexport interface GitDiff {\n\tfile: string;\n\tbinary: boolean;\n\thunks: PatchHunk[];\n}\n\n/** A file's line counts, as numstat gives them or as counted off an untracked file. */\ninterface LineCount {\n\tadditions: number;\n\tdeletions: number;\n\tbinary: boolean;\n}\n\n/** The fastest a repo is re-read, however often its sessions change. */\nconst REFRESH_MS = 2_000;\n/** A repo nobody has asked about for this long is dropped. */\nconst FORGET_MS = 10 * 60_000;\n/** A directory found not to be in a work tree is asked again only this often. */\nconst NO_REPO_RETRY_MS = 60_000;\n/** Untracked files bigger than this are listed without counting their lines. */\nconst COUNT_LIMIT_BYTES = 2 * 1024 * 1024;\n/** What git writes for an empty tree, to diff against in a repo with no commits yet. */\nconst EMPTY_TREE = '4b825dc642cb6eb9a060e54bf8d69288fbee4904';\n\n/** Run git in `cwd` with paths unquoted; null on an exit code outside `okCodes`. */\nexport function git(\n\targs: string[],\n\tcwd: string,\n\tokCodes: number[] = [0]\n): Promise<string | null> {\n\treturn new Promise((done) => {\n\t\texecFile(\n\t\t\t'git',\n\t\t\t['-c', 'core.quotepath=off', ...args],\n\t\t\t{ cwd, timeout: 20_000, maxBuffer: 64 * 1024 * 1024 },\n\t\t\t(err, stdout) => {\n\t\t\t\tconst code = err ? (typeof err.code === 'number' ? err.code : -1) : 0;\n\t\t\t\tdone(okCodes.includes(code) ? stdout : null);\n\t\t\t}\n\t\t);\n\t});\n}\n\n// ---------------------------------------------------------------------------\n// Parsing\n// ---------------------------------------------------------------------------\n\n/**\n * Parse `git status --porcelain=v2 -z`. Ordinary entries (`1`) carry one path,\n * renames and copies (`2`) a second NUL-terminated field with the old path,\n * unmerged entries (`u`) count as modified, and untracked ones (`?`) as added.\n * Ignored entries (`!`) and headers (`#`) are dropped.\n */\nexport function parsePorcelainV2(out: string): Omit<GitFileStatus, 'additions' | 'deletions'>[] {\n\tconst fields = out.split('\\0');\n\tconst files: Omit<GitFileStatus, 'additions' | 'deletions'>[] = [];\n\tfor (let i = 0; i < fields.length; i++) {\n\t\tconst field = fields[i];\n\t\tif (!field) continue;\n\t\tconst type = field[0];\n\t\tif (type === '?') {\n\t\t\tfiles.push({ file: field.slice(2), kind: 'added', untracked: true });\n\t\t} else if (type === '1') {\n\t\t\t// 1 <XY> <sub> <mH> <mI> <mW> <hH> <hI> <path>\n\t\t\tconst parts = field.split(' ');\n\t\t\tfiles.push({ file: parts.slice(8).join(' '), kind: kindOf(parts[1]) });\n\t\t} else if (type === '2') {\n\t\t\t// 2 <XY> <sub> <mH> <mI> <mW> <hH> <hI> <X><score> <path>\\0<origPath>\n\t\t\tconst parts = field.split(' ');\n\t\t\tconst oldPath = fields[++i] ?? '';\n\t\t\tconst file = parts.slice(9).join(' ');\n\t\t\tfiles.push({ file, oldPath, kind: parts[8].startsWith('C') ? 'added' : 'renamed' });\n\t\t} else if (type === 'u') {\n\t\t\t// u <XY> <sub> <m1> <m2> <m3> <mW> <h1> <h2> <h3> <path>\n\t\t\tfiles.push({ file: field.split(' ').slice(10).join(' '), kind: 'modified' });\n\t\t}\n\t}\n\treturn files;\n}\n\n/** The kind an ordinary entry's XY reads as; the worktree column wins over the index. */\nfunction kindOf(xy: string): GitFileKind {\n\tif (xy.includes('D')) return 'deleted';\n\tif (xy[0] === 'A') return 'added';\n\treturn 'modified';\n}\n\n/**\n * Parse `git diff --numstat -z`: `add\\tdel\\tpath\\0`, or for a rename\n * `add\\tdel\\t\\0old\\0new\\0`. A binary file counts as `-\\t-`.\n */\nexport function parseNumstat(out: string): Map<string, LineCount> {\n\tconst counts = new Map<string, LineCount>();\n\tconst fields = out.split('\\0');\n\tfor (let i = 0; i < fields.length; i++) {\n\t\tconst field = fields[i];\n\t\tif (!field) continue;\n\t\tconst [add, del, path] = field.split('\\t');\n\t\tif (del === undefined) continue;\n\t\t// A rename leaves the path empty and spells old and new in the next fields.\n\t\tconst file = path ? path : (i += 2, fields[i] ?? '');\n\t\tconst binary = add === '-' && del === '-';\n\t\tcounts.set(file, {\n\t\t\tadditions: binary ? 0 : Number(add) || 0,\n\t\t\tdeletions: binary ? 0 : Number(del) || 0,\n\t\t\tbinary\n\t\t});\n\t}\n\treturn counts;\n}\n\n/** Split a unified diff into hunks, dropping the file headers above the first. */\nexport function parseUnifiedDiff(out: string): { binary: boolean; hunks: PatchHunk[] } {\n\tconst hunks: PatchHunk[] = [];\n\tlet binary = false;\n\tlet current: PatchHunk | null = null;\n\tfor (const line of out.split('\\n')) {\n\t\tif (line.startsWith('diff ')) {\n\t\t\t// A second file section (a rename git no longer pairs): its headers are not hunk lines.\n\t\t\tcurrent = null;\n\t\t} else if (line.startsWith('@@')) {\n\t\t\tcurrent = { header: line.replace(/^(@@[^@]*@@).*$/, '$1'), lines: [] };\n\t\t\thunks.push(current);\n\t\t} else if (current && /^[ +\\-\\\\]/.test(line)) {\n\t\t\tcurrent.lines.push(line);\n\t\t} else if (!current && /^Binary files .* differ$|^GIT binary patch$/.test(line)) {\n\t\t\tbinary = true;\n\t\t}\n\t}\n\treturn { binary, hunks };\n}\n\n// ---------------------------------------------------------------------------\n// Paths\n// ---------------------------------------------------------------------------\n\n/**\n * The repo-relative form of `file` when it names something inside `root`,\n * or null when it climbs out or is absolute elsewhere.\n */\nexport function confinePath(root: string, file: string): string | null {\n\tif (!file || file.includes('\\0')) return null;\n\tconst abs = isAbsolute(file) ? resolve(file) : resolve(root, file);\n\tconst rel = relative(root, abs);\n\tif (!rel || rel === '..' || rel.startsWith('..' + sep) || isAbsolute(rel)) return null;\n\treturn rel.split(sep).join('/');\n}\n\n// ---------------------------------------------------------------------------\n// Reading a repo\n// ---------------------------------------------------------------------------\n\n/** Untracked counts by path, kept while the file's size and mtime hold. */\nconst untrackedCounts = new Map<string, { size: number; mtimeMs: number; count: LineCount | null }>();\n\n/** Lines in a file git does not know yet, or binary when it holds a NUL. */\nfunction countUntracked(path: string): LineCount | null {\n\ttry {\n\t\tconst { size, mtimeMs } = statSync(path);\n\t\tconst memo = untrackedCounts.get(path);\n\t\tif (memo && memo.size === size && memo.mtimeMs === mtimeMs) return memo.count;\n\t\tconst count = readLineCount(path, size);\n\t\tuntrackedCounts.set(path, { size, mtimeMs, count });\n\t\treturn count;\n\t} catch {\n\t\tuntrackedCounts.delete(path);\n\t\treturn null;\n\t}\n}\n\nfunction readLineCount(path: string, size: number): LineCount | null {\n\ttry {\n\t\tif (size > COUNT_LIMIT_BYTES) return null;\n\t\tconst buffer = Buffer.alloc(size);\n\t\tconst fd = openSync(path, 'r');\n\t\ttry {\n\t\t\treadSync(fd, buffer, 0, size, 0);\n\t\t} finally {\n\t\t\tcloseSync(fd);\n\t\t}\n\t\tif (buffer.subarray(0, 8000).includes(0)) return { additions: 0, deletions: 0, binary: true };\n\t\tlet lines = 0;\n\t\tfor (let i = buffer.indexOf(0x0a); i !== -1; i = buffer.indexOf(0x0a, i + 1)) lines++;\n\t\tif (size > 0 && buffer[size - 1] !== 0x0a) lines++;\n\t\treturn { additions: lines, deletions: 0, binary: false };\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/** HEAD, or the empty tree when the repo has no commits yet. */\nasync function baseRev(root: string): Promise<string> {\n\treturn (await git(['rev-parse', '--verify', '-q', 'HEAD'], root)) ? 'HEAD' : EMPTY_TREE;\n}\n\nasync function readChanges(root: string): Promise<GitChanges | null> {\n\tconst [status, base] = await Promise.all([\n\t\tgit(['status', '--porcelain=v2', '-z', '--untracked-files=all'], root),\n\t\tbaseRev(root)\n\t]);\n\tif (status === null) return null;\n\tconst numstat = (await git(['diff', '--numstat', '-z', '-M', base], root)) ?? '';\n\tconst counts = parseNumstat(numstat);\n\tconst entries = parsePorcelainV2(status);\n\t// Drop memoised counts for files under this root that are no longer untracked.\n\tconst untracked = new Set(entries.filter((e) => e.untracked).map((e) => resolve(root, e.file)));\n\tfor (const path of untrackedCounts.keys()) {\n\t\tif (path.startsWith(root + sep) && !untracked.has(path)) untrackedCounts.delete(path);\n\t}\n\tconst files = entries.map((entry): GitFileStatus => {\n\t\tconst count = entry.untracked\n\t\t\t? countUntracked(resolve(root, entry.file))\n\t\t\t: counts.get(entry.file);\n\t\treturn {\n\t\t\t...entry,\n\t\t\tadditions: count?.additions ?? 0,\n\t\t\tdeletions: count?.deletions ?? 0,\n\t\t\t...(count?.binary ? { binary: true as const } : {})\n\t\t};\n\t});\n\treturn { root, files, base };\n}\n\n// ---------------------------------------------------------------------------\n// Cache\n// ---------------------------------------------------------------------------\n\ninterface RepoState {\n\tchanges: GitChanges | null;\n\trefreshedAt: number;\n\tdirty: boolean;\n\tinflight: Promise<GitChanges | null> | null;\n\ttrailing: ReturnType<typeof setTimeout> | null;\n\taskedAt: number;\n}\n\n/** cwd → repo root, or null when the cwd is in no work tree (with when that was found). */\nconst roots = new Map<string, { root: string | null; at: number }>();\n/** Lookups in flight, so a tick that comes round first does not ask twice. */\nconst resolving = new Map<string, Promise<string | null>>();\nconst repos = new Map<string, RepoState>();\nlet unsubscribe: (() => void) | null = null;\n\n/** Forget everything — for tests. */\nexport function resetGitCache(): void {\n\tfor (const repo of repos.values()) if (repo.trailing) clearTimeout(repo.trailing);\n\troots.clear();\n\tresolving.clear();\n\tuntrackedCounts.clear();\n\trepos.clear();\n\tunsubscribe?.();\n\tunsubscribe = null;\n}\n\n/** The work tree `cwd` sits in, or null outside one. */\nexport async function repoRoot(cwd: string): Promise<string | null> {\n\tconst known = roots.get(cwd);\n\tif (known && (known.root !== null || Date.now() - known.at < NO_REPO_RETRY_MS)) return known.root;\n\tlet pending = resolving.get(cwd);\n\tif (!pending) {\n\t\tpending = git(['rev-parse', '--show-toplevel'], cwd).then((out) => {\n\t\t\tconst root = out ? out.trim() || null : null;\n\t\t\troots.set(cwd, { root, at: Date.now() });\n\t\t\tresolving.delete(cwd);\n\t\t\treturn root;\n\t\t});\n\t\tresolving.set(cwd, pending);\n\t}\n\treturn pending;\n}\n\n/**\n * A session's JSON changed, which a hook does on every event it handles:\n * the repo it works in may have changed on disk too.\n */\nfunction noteSessionChanged(cwd: string): void {\n\t// git prints the root with symlinks resolved, so a cwd reached through one matches only by lookup.\n\tconst known = roots.get(cwd)?.root;\n\tfor (const [root, repo] of repos) {\n\t\tif (root === known || cwd === root || cwd.startsWith(root + '/')) {\n\t\t\trepo.dirty = true;\n\t\t\tschedule(root, repo);\n\t\t}\n\t}\n}\n\nfunction watch(): void {\n\tif (unsubscribe) return;\n\tunsubscribe = sessionWatcher.subscribe((changed) => {\n\t\tfor (const id of changed) {\n\t\t\tconst cwd = getSession(id)?.cwd;\n\t\t\tif (cwd) noteSessionChanged(cwd);\n\t\t}\n\t});\n}\n\nfunction refresh(root: string, repo: RepoState): Promise<GitChanges | null> {\n\tif (repo.inflight) return repo.inflight;\n\trepo.dirty = false;\n\trepo.refreshedAt = Date.now();\n\trepo.inflight = readChanges(root)\n\t\t.then((changes) => {\n\t\t\trepo.changes = changes;\n\t\t\treturn changes;\n\t\t})\n\t\t.finally(() => {\n\t\t\trepo.inflight = null;\n\t\t\t// A hook landed while git was reading: what it changed may be missing.\n\t\t\tif (repo.dirty) schedule(root, repo);\n\t\t});\n\treturn repo.inflight;\n}\n\n/** Re-read a dirty repo now, or as soon as the throttle allows. */\nfunction schedule(root: string, repo: RepoState): void {\n\tif (Date.now() - repo.askedAt > FORGET_MS) {\n\t\tif (repo.trailing) clearTimeout(repo.trailing);\n\t\trepos.delete(root);\n\t\treturn;\n\t}\n\tif (repo.inflight || repo.trailing) return;\n\tconst wait = repo.refreshedAt + REFRESH_MS - Date.now();\n\tif (wait <= 0) {\n\t\tvoid refresh(root, repo);\n\t\treturn;\n\t}\n\trepo.trailing = setTimeout(() => {\n\t\trepo.trailing = null;\n\t\tif (repo.dirty) void refresh(root, repo);\n\t}, wait);\n}\n\nfunction stateFor(root: string): RepoState {\n\tlet repo = repos.get(root);\n\tif (!repo) {\n\t\trepo = { changes: null, refreshedAt: 0, dirty: true, inflight: null, trailing: null, askedAt: Date.now() };\n\t\trepos.set(root, repo);\n\t}\n\trepo.askedAt = Date.now();\n\twatch();\n\treturn repo;\n}\n\n/**\n * The repo's changes, read fresh when a hook has touched it since the last\n * read (or it was never read) and the throttle allows; otherwise cached.\n * Null outside a work tree.\n */\nexport async function gitChanges(cwd: string): Promise<GitChanges | null> {\n\tconst root = await repoRoot(cwd);\n\tif (!root) return null;\n\tconst repo = stateFor(root);\n\tif (repo.inflight) return repo.inflight;\n\tif (repo.changes && (!repo.dirty || Date.now() - repo.refreshedAt < REFRESH_MS)) {\n\t\tif (repo.dirty) schedule(root, repo);\n\t\treturn repo.changes;\n\t}\n\treturn refresh(root, repo);\n}\n\n/**\n * What the broadcast shows for a cwd, without waiting on git: the last read\n * when there is one, null when the cwd is in no repo, undefined while that is\n * still being found out. Kicks off the read it needs.\n */\nexport function peekGitSummary(cwd: string): ChangesSummary | null | undefined {\n\t// The root last resolved, without asking git; undefined when not asked yet.\n\tconst root = roots.get(cwd)?.root;\n\tif (root === undefined) {\n\t\tvoid gitChanges(cwd);\n\t\treturn undefined;\n\t}\n\tif (root === null) {\n\t\t// Asks git again once the retry window has passed, so a later `git init` is noticed.\n\t\tvoid repoRoot(cwd);\n\t\treturn null;\n\t}\n\tconst repo = stateFor(root);\n\tif (!repo.changes) {\n\t\tschedule(root, repo);\n\t\treturn repo.refreshedAt ? null : undefined;\n\t}\n\treturn summarize(repo.changes.files);\n}\n\n/**\n * One file's diff against HEAD, working tree included. `file` is checked\n * against the repo root and must be one the status lists; null otherwise.\n */\nexport async function gitFileDiff(cwd: string, file: string): Promise<GitDiff | null> {\n\tconst changes = await gitChanges(cwd);\n\tif (!changes) return null;\n\tconst rel = confinePath(changes.root, file);\n\tif (!rel) return null;\n\tconst entry = changes.files.find((f) => f.file === rel);\n\tif (!entry) return null;\n\tconst out = entry.untracked\n\t\t? // --no-index exits 1 when the files differ, which they always do here.\n\t\t\tawait git(['diff', '--no-index', '--', '/dev/null', rel], changes.root, [0, 1])\n\t\t: await git(\n\t\t\t\t['diff', '-M', changes.base, '--', ...(entry.oldPath ? [entry.oldPath] : []), rel],\n\t\t\t\tchanges.root\n\t\t\t);\n\tif (out === null) return null;\n\tconst parsed = parseUnifiedDiff(out);\n\treturn { file: rel, binary: parsed.binary || entry.binary === true, hunks: parsed.hunks };\n}\n\n/** The branch checked out at `root`, or null on a detached HEAD or outside a repo. */\nexport async function currentBranch(root: string): Promise<string | null> {\n\tconst out = await git(['symbolic-ref', '--short', '-q', 'HEAD'], root);\n\treturn out?.trim() || null;\n}\n"],"names":["interrupt","FORGET_MS","count"],"mappings":"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"}
1
+ {"version":3,"file":"git.js","sources":["../../../../../src/transcript/parser.ts","../../../../../src/server/watcher.ts","../../../../../src/transcript/changes.ts","../../../../../src/server/git.ts"],"sourcesContent":["/**\n * Incremental parser for Claude Code session JSONL transcripts.\n *\n * The JSONL format is an undocumented internal of Claude Code and changes\n * between versions (see docs/adr/0003). The parser is deliberately tolerant:\n * unknown line types and malformed lines are skipped, never thrown on.\n *\n * Folding rules discovered from live session files:\n * - The streamer writes one `assistant` line per content block; lines from the\n * same API response share `message.id`.\n * - A real user prompt has `message.content` as a plain string (or text\n * blocks) and `origin.kind === \"human\"`; tool results come back as `user`\n * lines whose content is an array of `tool_result` blocks.\n * - `toolUseResult` is a structured sidecar on tool_result lines, richer than\n * the in-message content (stdout/stderr for Bash, file data for Read, ...).\n */\n\nimport { readContextUsage, type ContextUsage } from \"./context.js\";\nimport { ForkTracker } from \"./forks.js\";\nimport { asRecord, readString } from \"./json.js\";\nimport { parseMcpToolName } from \"./mcp.js\";\n\nexport type TranscriptEntry = (\n | {\n kind: \"user\";\n id: string;\n ts: number;\n text: string;\n /**\n * Set when the prompt was a slash command, so the UI can style it.\n * `output` is what a local command printed back — \"Set model to Fable\" —\n * which the log records as a user line of its own, wrapped in\n * <local-command-stdout>, right after the command.\n */\n command?: { name: string; args?: string; output?: string };\n /** Set when the prompt was dictated by voice (see dictation-marks). */\n dictated?: boolean;\n }\n /** A prompt typed mid-turn. By the time its queued_command line reaches the\n * file it has already been seen by the agent — most never get a user line\n * of their own (the harness injects them into tool results instead), so\n * this IS the user turn. `delivered` marks the rare double-delivery case\n * where a real user line with the same text follows; the UI hides those. */\n | { kind: \"queued\"; id: string; ts: number; text: string; delivered?: boolean; dictated?: boolean }\n /** A cross-session (agent-to-agent) message from another Claude session. */\n | { kind: \"peer\"; id: string; ts: number; text: string; from?: string }\n /**\n * Claude Code's own record that the user pressed Escape. It is logged as a\n * user line but is the harness's note, not something anyone typed.\n */\n | { kind: \"interrupt\"; id: string; ts: number; text: string }\n /**\n * The conversation was compacted here: everything above was folded into\n * the summary Claude Code wrote, which arrives as the next user line and\n * is attached to this entry rather than shown as a prompt.\n */\n | {\n kind: \"compact\";\n id: string;\n ts: number;\n /** \"manual\" for /compact, \"auto\" when the context window filled. */\n trigger: string;\n preTokens?: number;\n postTokens?: number;\n summary?: string;\n }\n /** An AskUserQuestion dialog: interactive while unanswered. */\n | {\n kind: \"ask\";\n id: string;\n ts: number;\n questions: AskQuestion[];\n /** question text -> chosen answer, from toolUseResult.answers. */\n answers?: Record<string, string>;\n rejected?: boolean;\n }\n | { kind: \"text\"; id: string; ts: number; text: string }\n | { kind: \"thinking\"; id: string; ts: number; text: string }\n | {\n kind: \"tool\";\n id: string;\n ts: number;\n name: string;\n summary: string;\n input: string;\n /** `images` are files Claude Code saved for image results (screenshots). */\n result?: { ok: boolean; output: string; images?: string[] };\n /** Git-style hunks from the Edit/Write sidecar's structuredPatch. */\n patch?: { file: string; hunks: PatchHunk[] };\n }\n) & {\n /** Set on everything a later rewind went back past: a branch the conversation no longer follows. */\n rewound?: boolean;\n};\n\nexport interface AskQuestion {\n header: string;\n question: string;\n multiSelect: boolean;\n /** `preview` is the panel the dialog draws beside the option while it is highlighted. */\n options: { label: string; description?: string; preview?: string }[];\n}\n\n/** The tags Claude Code wraps a slash command in; \\1 pairs open with close. */\nconst COMMAND_TAG = /<command-(name|message|args)>([\\s\\S]*?)<\\/command-\\1>/g;\n\n/**\n * A slash command reaches the log as a user line whose whole content is a\n * bundle of <command-name>/<command-message>/<command-args> tags. Read the\n * command out of it so the transcript shows \"/simplify e push\" instead of the\n * raw markup.\n */\nexport function parseSlashCommand(content: string): { name: string; args?: string } | null {\n const trimmed = content.trim();\n // Cheap reject first: every other prompt in the file skips the regex.\n if (!trimmed.startsWith(\"<command-\")) return null;\n const tags: Record<string, string> = {};\n // Tag order varies by Claude Code version (name-first in older logs,\n // message-first in newer ones), so collect by name rather than by position.\n for (const match of trimmed.matchAll(COMMAND_TAG)) tags[match[1]] = match[2].trim();\n const name = tags.name;\n // No <command-name> means this is not a command line after all — leave the\n // content alone rather than rendering a half-parsed guess.\n if (!name) return null;\n // <command-message> is the harness's own echo of the name; it adds nothing\n // the UI can show, and empty <command-args> must not become a trailing space.\n return { name, ...(tags.args ? { args: tags.args } : {}) };\n}\n\n/** What a local command printed, as the log wraps it; \\1 pairs open with close. */\nconst LOCAL_OUTPUT_TAG = /^<local-command-(stdout|stderr)>([\\s\\S]*?)<\\/local-command-\\1>/;\n\n/** A terminal styling sequence (colour, dim, reset) left in logged output. */\n// eslint-disable-next-line no-control-regex\nconst ANSI_SGR = /\\x1b\\[[0-9;]*m/g;\n\n/**\n * The caveat the harness writes ahead of a local command's lines. It is meant\n * for the model, not the reader, and is usually flagged isMeta — but not in\n * every version, so it is recognised by shape too.\n */\nconst LOCAL_CAVEAT = /^<local-command-caveat>/;\n\n/** What Claude Code logs when Escape stops a turn, with or without \"for tool use\". */\nconst INTERRUPT_MARKER = /^\\[Request interrupted (by user[^\\]]*)\\]$/;\n\n/** The note an interrupt marker reads as, or null when the text is not one. */\nexport function interruptNote(text: string): string | null {\n const m = INTERRUPT_MARKER.exec(text.trim());\n return m ? `Interrupted ${m[1]}` : null;\n}\n\n/**\n * Read what a local command printed out of the user line that carries it.\n *\n * A local command (`/model`, `/cost`, `/context`) never reaches the model:\n * the harness runs it and logs three user lines — a caveat, the command, and\n * its output wrapped in <local-command-stdout>. The output belongs under the\n * command it answers, not in a turn of its own dressed as a prompt.\n *\n * @returns The output's text, or null when the line is something else.\n */\nfunction parseLocalOutput(content: string): string | null {\n const trimmed = content.trim();\n if (!trimmed.startsWith(\"<local-command-\")) return null;\n const chunks: string[] = [];\n let rest = trimmed;\n for (let m = rest.match(LOCAL_OUTPUT_TAG); m; m = rest.match(LOCAL_OUTPUT_TAG)) {\n // Some commands print styled — `/compact` dims its line — and the log\n // keeps the escape codes.\n const text = m[2].replace(ANSI_SGR, \"\").trim();\n if (text) chunks.push(m[1] === \"stderr\" ? `[stderr]\\n${text}` : text);\n rest = rest.slice(m[0].length).trimStart();\n }\n // Not an output line after all — leave it to the caller.\n if (chunks.length === 0 && !LOCAL_OUTPUT_TAG.test(trimmed)) return null;\n return chunks.join(\"\\n\");\n}\n\n/** The wrapper Claude Code logs around a long paste: `<pasted_content id=\"c2b8\">` … `</pasted_content id=\"c2b8\">`. */\nconst PASTED_OPEN = /<pasted_content id=\"[^\"]*\">\\n?/g;\nconst PASTED_CLOSE = /\\n?<\\/pasted_content id=\"[^\"]*\">\\n?/g;\n\n/**\n * A prompt as it was pasted. Claude Code logs a long paste inside a\n * `<pasted_content>` wrapper (with a blank line before it when nothing was\n * typed ahead of it); the person sent the text, not the tags, and the\n * dictation and queued-message matching compare against the text.\n */\nexport function unwrapPasted(text: string): string {\n if (!text.includes(\"<pasted_content id=\")) return text;\n return text.replace(PASTED_OPEN, \"\").replace(PASTED_CLOSE, \"\\n\").trim();\n}\n\nfunction parseAskQuestions(input: Record<string, unknown>): AskQuestion[] {\n const raw = input.questions;\n if (!Array.isArray(raw)) return [];\n const questions: AskQuestion[] = [];\n for (const entry of raw) {\n const q = asRecord(entry);\n if (!q) continue;\n const options = Array.isArray(q.options)\n ? q.options\n .map((o) => asRecord(o))\n .filter((o): o is Record<string, unknown> => o !== null)\n .map((o) => ({\n label: readString(o.label) ?? \"\",\n ...(readString(o.description) ? { description: readString(o.description)! } : {}),\n ...(readString(o.preview) ? { preview: readString(o.preview)! } : {}),\n }))\n .filter((o) => o.label.length > 0)\n : [];\n questions.push({\n header: readString(q.header) ?? \"\",\n question: readString(q.question) ?? \"\",\n multiSelect: q.multiSelect === true,\n options,\n });\n }\n return questions;\n}\n\nexport interface PatchHunk {\n header: string;\n /** Unified-diff lines, first char is \"+\", \"-\" or \" \". */\n lines: string[];\n}\n\nconst PATCH_LINE_LIMIT = 400;\n\n/**\n * A sidecar's `structuredPatch` as hunks, with at most `limit` lines kept\n * across them and a note standing in for the rest.\n */\nexport function readStructuredPatch(raw: unknown, limit = Infinity): PatchHunk[] {\n if (!Array.isArray(raw)) return [];\n const hunks: PatchHunk[] = [];\n let total = 0;\n for (const entry of raw) {\n const hunk = asRecord(entry);\n if (!hunk || !Array.isArray(hunk.lines)) continue;\n const lines = hunk.lines.filter((line): line is string => typeof line === \"string\");\n if (lines.length === 0) continue;\n const kept = lines.slice(0, Math.max(0, limit - total));\n if (kept.length < lines.length) kept.push(`… ${lines.length - kept.length} more lines`);\n total += kept.length;\n hunks.push({\n header: `@@ -${hunk.oldStart ?? \"?\"},${hunk.oldLines ?? \"?\"} +${hunk.newStart ?? \"?\"},${hunk.newLines ?? \"?\"} @@`,\n lines: kept,\n });\n if (total >= limit) break;\n }\n return hunks;\n}\n\nfunction extractPatch(sidecar: unknown): { file: string; hunks: PatchHunk[] } | undefined {\n const sc = asRecord(sidecar);\n const hunks = readStructuredPatch(sc?.structuredPatch, PATCH_LINE_LIMIT);\n if (hunks.length === 0) return undefined;\n return { file: readString(sc?.filePath) ?? \"\", hunks };\n}\n\nconst INPUT_CHAR_LIMIT = 4_000;\nconst RESULT_CHAR_LIMIT = 8_000;\nconst TEXT_CHAR_LIMIT = 64_000;\n\nfunction truncate(text: string, limit: number): string {\n if (text.length <= limit) return text;\n return `${text.slice(0, limit)}\\n… [truncated, ${text.length - limit} more chars]`;\n}\n\nfunction parseTimestamp(value: unknown): number {\n const ts = typeof value === \"string\" ? Date.parse(value) : NaN;\n return Number.isFinite(ts) ? ts : Date.now();\n}\n\n/** Arguments that name what a built-in tool call acts on, best first. */\nconst BUILTIN_KEY_ARGS = [\n \"command\",\n \"file_path\",\n \"pattern\",\n \"url\",\n \"query\",\n \"description\",\n \"prompt\",\n \"skill\",\n];\n/** Arguments that say most about an MCP call, best first. */\nconst MCP_KEY_ARGS = [\n \"url\",\n \"uid\",\n \"key\",\n \"function\",\n \"query\",\n \"command\",\n \"file_path\",\n \"path\",\n \"selector\",\n \"text\",\n \"name\",\n \"title\",\n];\n/** The fallback argument is the first string short enough to read at a glance. */\nconst MCP_SHORT_ARG = 80;\n\nfunction firstString(input: Record<string, unknown>, keys: string[]): string | null {\n for (const key of keys) {\n const value = readString(input[key]);\n if (value?.trim()) return value;\n }\n return null;\n}\n\nfunction shortString(input: Record<string, unknown>): string | null {\n for (const value of Object.values(input)) {\n if (typeof value === \"string\" && value.trim() && value.length <= MCP_SHORT_ARG) return value;\n }\n return null;\n}\n\n/**\n * One-line human summary of a tool invocation: name + its key argument. An\n * MCP tool reads as its bare tool name; the server is left to the caller,\n * which can parse it out of the raw name with parseMcpToolName.\n */\nexport function summarizeToolUse(rawName: string, input: Record<string, unknown>): string {\n const mcp = parseMcpToolName(rawName);\n const name = mcp?.tool ?? rawName;\n const key = mcp\n ? (firstString(input, MCP_KEY_ARGS) ?? shortString(input))\n : firstString(input, BUILTIN_KEY_ARGS);\n if (!key) return name;\n const flat = key.replace(/\\s+/g, \" \").trim();\n return `${name}: ${flat.length > 120 ? `${flat.slice(0, 117)}...` : flat}`;\n}\n\n/** Claude Code saves an image result to disk and says where in a text part. */\nconst IMAGE_SOURCE = /^\\[Image: source: (.+?)(?:, original [^\\]]*)?\\]/;\n\n/** The saved files behind a tool result's images, in order. */\nfunction toolResultImages(blockContent: unknown): string[] {\n if (!Array.isArray(blockContent)) return [];\n const paths: string[] = [];\n for (const part of blockContent) {\n const match = IMAGE_SOURCE.exec(readString(asRecord(part)?.text) ?? \"\");\n if (match) paths.push(match[1].trim());\n }\n return paths;\n}\n\n/** Flatten a tool_result / toolUseResult payload into displayable text. */\nfunction toolResultText(sidecar: unknown, blockContent: unknown): string {\n const sc = asRecord(sidecar);\n if (sc) {\n const stdout = readString(sc.stdout);\n const stderr = readString(sc.stderr);\n if (stdout !== null || stderr !== null) {\n return [stdout, stderr && stderr.length > 0 ? `[stderr]\\n${stderr}` : null]\n .filter((part): part is string => part !== null && part.length > 0)\n .join(\"\\n\");\n }\n }\n if (typeof blockContent === \"string\") return blockContent;\n if (Array.isArray(blockContent)) {\n // An image Claude Code saved to disk travels as `images` and is drawn as\n // one, so neither it nor the note naming its file belongs in the text.\n const saved = toolResultImages(blockContent).length;\n let unsaved = blockContent.filter((part) => asRecord(part)?.type === \"image\").length - saved;\n const parts = blockContent\n .map((part) => {\n const rec = asRecord(part);\n const text = readString(rec?.text) ?? \"\";\n // Screenshots and other image results carry no text; name the file the\n // sidecar saved instead of rendering an empty result.\n if (rec?.type === \"image\") {\n return unsaved-- > 0 ? (readString(sc?.file) ?? \"[image]\") : \"\";\n }\n return IMAGE_SOURCE.test(text) ? \"\" : text;\n })\n .filter((text) => text.length > 0);\n if (parts.length > 0 || saved > 0) return parts.join(\"\\n\");\n }\n if (sc) {\n try {\n return JSON.stringify(sc, null, 2);\n } catch {\n return \"\";\n }\n }\n return \"\";\n}\n\n/**\n * Stateful builder: feed raw JSONL lines in file order, read `entries` out.\n * `feed` returns the ids of entries it added or updated so a streaming caller\n * can broadcast only the delta.\n */\nexport class TranscriptBuilder {\n readonly entries: TranscriptEntry[] = [];\n /**\n * Subagents the harness has reported as finished. Background agents give no\n * other completion signal — their launching tool call returns immediately —\n * so this notification is the authoritative end, keyed by agent id.\n */\n readonly finishedAgents = new Set<string>();\n /**\n * Context-window usage of the most recent API response, or null before the\n * first one. Compaction needs no special handling: the response that\n * follows it reports the smaller context on its own.\n */\n context: ContextUsage | null = null;\n /** The model that wrote the latest assistant line, as the API names it. */\n model: string | null = null;\n /** The compaction logged last, whose summary is the next user line. */\n private lastCompactId: string | null = null;\n private indexById = new Map<string, number>();\n /** The slash command logged last, which a local command's output belongs to. */\n private lastCommandId: string | null = null;\n /** Queued prompts awaiting a possible re-delivery as a real user line. */\n private pendingQueued: { text: string; id: string }[] = [];\n private forks = new ForkTracker();\n /** The position of the line being fed, and of the line that first made each entry. */\n private seq = -1;\n private seqById = new Map<string, number>();\n\n /**\n * @param sidechain true when reading a subagent's own file, where every line\n * is marked `isSidechain` — the main transcript skips those, since subagent\n * work lives in its own file.\n * @param isDictated tells a prompt injected by voice from a typed one. The\n * JSONL carries no origin for this, so the caller re-derives it (by text and\n * time, see dictation-marks) and the builder stamps `dictated` at parse\n * time, where the flag survives re-upserts of the same entry.\n */\n constructor(\n private readonly sidechain = false,\n private readonly isDictated?: (text: string, ts: number) => boolean\n ) {}\n\n private dictatedFlag(text: string, ts: number): { dictated: true } | undefined {\n return this.isDictated?.(text, ts) ? { dictated: true } : undefined;\n }\n\n /** Position of an entry in `entries`, or undefined if it is not one. */\n indexOf(id: string): number | undefined {\n return this.indexById.get(id);\n }\n\n feed(line: string): string[] {\n const trimmed = line.trim();\n if (trimmed.length === 0) return [];\n let record: Record<string, unknown> | null;\n try {\n record = asRecord(JSON.parse(trimmed));\n } catch {\n return [];\n }\n if (!record) return [];\n if ((record.isSidechain === true) !== this.sidechain) return [];\n const uuid = readString(record.uuid);\n if (uuid) this.seq = this.forks.see(uuid, record.type);\n\n switch (record.type) {\n case \"user\":\n return this.feedUser(record);\n case \"assistant\":\n return this.feedAssistant(record);\n case \"attachment\":\n return this.feedAttachment(record);\n case \"system\":\n return this.feedSystem(record);\n default:\n return [];\n }\n }\n\n /**\n * The most recent user turn, when it is plain text reading exactly `text`\n * and nothing has been said since but the harness's own bookkeeping — the\n * compaction a `/compact` triggers, for one.\n */\n private recentPlainUserLine(text: string): Extract<TranscriptEntry, { kind: \"user\" }> | null {\n for (let i = this.entries.length - 1, seen = 0; i >= 0 && seen < 4; i--, seen++) {\n const entry = this.entries[i];\n if (entry.kind === \"compact\") continue;\n if (entry.kind !== \"user\") return null;\n return !entry.command && entry.text === text ? entry : null;\n }\n return null;\n }\n\n /**\n * A system line. The only one with a place in the transcript is the\n * compaction boundary: the reader needs to know where the conversation was\n * folded, or the summary that follows reads as a prompt they never typed.\n */\n private feedSystem(record: Record<string, unknown>): string[] {\n if (record.subtype !== \"compact_boundary\") return [];\n const uuid = readString(record.uuid) ?? `compact-${this.entries.length}`;\n const meta = asRecord(record.compactMetadata);\n const pre = typeof meta?.preTokens === \"number\" ? meta.preTokens : undefined;\n const post = typeof meta?.postTokens === \"number\" ? meta.postTokens : undefined;\n this.lastCompactId = uuid;\n return [\n this.upsert({\n kind: \"compact\",\n id: uuid,\n ts: parseTimestamp(record.timestamp),\n trigger: readString(meta?.trigger) ?? \"auto\",\n ...(pre !== undefined ? { preTokens: pre } : {}),\n ...(post !== undefined ? { postTokens: post } : {}),\n }),\n ];\n }\n\n private feedAttachment(record: Record<string, unknown>): string[] {\n const attachment = asRecord(record.attachment);\n if (!attachment || attachment.type !== \"queued_command\") return [];\n // Only human-typed prompts; system notifications also arrive queued.\n if (asRecord(attachment.origin)?.kind !== \"human\") return [];\n const raw = readString(attachment.prompt);\n const prompt = raw === null ? null : unwrapPasted(raw);\n if (!prompt || prompt.trim().length === 0) return [];\n const uuid = readString(record.uuid) ?? `queued-${this.entries.length}`;\n const ts = parseTimestamp(record.timestamp ?? attachment.timestamp);\n this.pendingQueued.push({ text: prompt.trim(), id: uuid });\n return [\n this.upsert({\n kind: \"queued\",\n id: uuid,\n ts,\n text: truncate(prompt, TEXT_CHAR_LIMIT),\n ...this.dictatedFlag(prompt, ts),\n }),\n ];\n }\n\n /** Record a finished subagent from a harness task-notification. */\n private noteAgentFinished(text: string): void {\n const agentId = text.match(/<task-id>([^<]+)<\\/task-id>/)?.[1];\n const status = text.match(/<status>([^<]+)<\\/status>/)?.[1];\n if (agentId && status && status !== \"running\") this.finishedAgents.add(agentId);\n }\n\n /** Hide queued entries that a real user line re-delivers. The delivered\n * text may embed the queued prompt (harness wrapping), so match on exact\n * equality or prefix, not just identity. */\n private deliverQueued(text: string): string[] {\n const delivered = text.trim();\n const changed: string[] = [];\n this.pendingQueued = this.pendingQueued.filter((pending) => {\n if (delivered !== pending.text && !delivered.startsWith(pending.text)) return true;\n const entry = this.getEntry(pending.id);\n if (entry && entry.kind === \"queued\") {\n changed.push(this.upsert({ ...entry, delivered: true }));\n }\n return false;\n });\n return changed;\n }\n\n private upsert(entry: TranscriptEntry): string {\n const existing = this.indexById.get(entry.id);\n if (existing !== undefined) {\n this.entries[existing] = entry;\n } else {\n this.seqById.set(entry.id, this.seq);\n this.indexById.set(entry.id, this.entries.length);\n this.entries.push(entry);\n }\n return entry.id;\n }\n\n /**\n * A prompt that went back past what came before it (see ForkTracker): mark\n * every entry the old branch made as rewound, and answer their ids.\n */\n private rewindTo(record: Record<string, unknown>): string[] {\n const after = this.forks.abandonedAfter(readString(record.parentUuid));\n if (after === null) return [];\n const changed: string[] = [];\n this.entries.forEach((entry, i) => {\n const seq = this.seqById.get(entry.id);\n if (seq === undefined || seq <= after || entry.rewound) return;\n this.entries[i] = { ...entry, rewound: true };\n changed.push(entry.id);\n });\n return changed;\n }\n\n getEntry(id: string): TranscriptEntry | undefined {\n const index = this.indexById.get(id);\n return index === undefined ? undefined : this.entries[index];\n }\n\n private feedUser(record: Record<string, unknown>): string[] {\n const message = asRecord(record.message);\n if (!message) return [];\n const uuid = readString(record.uuid) ?? `user-${this.entries.length}`;\n const ts = parseTimestamp(record.timestamp);\n const content = typeof message.content === \"string\" ? unwrapPasted(message.content) : message.content;\n\n // Cross-session (A2A) messages arrive as meta user lines with\n // origin.kind \"peer\"; origin.body is the clean text (message.content is\n // the harness-wrapped form) and origin.name the sender.\n const origin = asRecord(record.origin);\n if (origin?.kind === \"peer\") {\n const body =\n readString(origin.body) ?? (typeof content === \"string\" ? content : null);\n if (!body || body.trim().length === 0) return [];\n const from = readString(origin.name) ?? undefined;\n return [\n this.upsert({\n kind: \"peer\",\n id: uuid,\n ts,\n text: truncate(body, TEXT_CHAR_LIMIT),\n ...(from ? { from } : {}),\n }),\n ];\n }\n\n // The summary Claude Code wrote when it compacted: what the model reads\n // in place of the folded conversation, not something the user said.\n if (record.isCompactSummary === true && typeof content === \"string\") {\n const owner = this.lastCompactId ? this.getEntry(this.lastCompactId) : undefined;\n if (owner?.kind === \"compact\") {\n return [this.upsert({ ...owner, summary: truncate(content, TEXT_CHAR_LIMIT) })];\n }\n return [];\n }\n\n if (record.isMeta === true) return [];\n\n if (typeof content === \"string\") {\n if (content.trim().length === 0) return [];\n // Only human prompts render as turns. System-injected user lines (task\n // notifications, reminders) carry origin.kind !== \"human\"; when origin\n // is absent (older versions) fall back to sniffing system markers.\n const originKind = asRecord(record.origin)?.kind;\n if (originKind === \"task-notification\") {\n this.noteAgentFinished(content);\n return [];\n }\n if (originKind !== undefined && originKind !== \"human\") return [];\n if (originKind === undefined && /^<(task-notification|system-reminder)/.test(content.trim()))\n return [];\n if (LOCAL_CAVEAT.test(content.trimStart())) return [];\n const interrupt = interruptNote(content);\n if (interrupt) return [this.upsert({ kind: \"interrupt\", id: uuid, ts, text: interrupt })];\n // A local command's output rides under the command it answers, which is\n // the line logged just before it.\n const output = parseLocalOutput(content);\n if (output !== null) {\n if (output.length === 0) return [];\n const owner = this.lastCommandId ? this.getEntry(this.lastCommandId) : undefined;\n if (owner?.kind === \"user\" && owner.command) {\n return [\n this.upsert({\n ...owner,\n command: { ...owner.command, output: truncate(output, TEXT_CHAR_LIMIT) },\n }),\n ];\n }\n return [this.upsert({ kind: \"user\", id: uuid, ts, text: truncate(output, TEXT_CHAR_LIMIT) })];\n }\n // `text` stays the human-readable form of the turn either way, so search,\n // truncation and the queued-prompt matching below need no special case.\n const command = parseSlashCommand(content);\n if (command) {\n // A command pasted into the prompt is logged twice: first as the plain\n // text the user sent, then as the harness's own bundle once it ran.\n // Fold the bundle into that first line rather than showing a second.\n const spelled = `${command.name}${command.args ? ` ${command.args}` : \"\"}`;\n const typed = this.recentPlainUserLine(spelled);\n if (typed) {\n this.lastCommandId = typed.id;\n return [this.upsert({ ...typed, command })];\n }\n }\n this.lastCommandId = command ? uuid : null;\n const text = command\n ? `${command.name}${command.args ? ` ${command.args}` : \"\"}`\n : content;\n return [\n ...this.rewindTo(record),\n ...this.deliverQueued(content),\n this.upsert({\n kind: \"user\",\n id: uuid,\n ts,\n text: truncate(text, TEXT_CHAR_LIMIT),\n ...(command ? { command } : {}),\n ...this.dictatedFlag(text, ts),\n }),\n ];\n }\n\n if (!Array.isArray(content)) return [];\n const changed: string[] = [];\n const promptTexts: string[] = [];\n for (const block of content) {\n const rec = asRecord(block);\n if (!rec) continue;\n if (rec.type === \"tool_result\") {\n // Tool and ask entries are keyed by their tool_use id.\n const toolUseId = readString(rec.tool_use_id);\n const entry = toolUseId ? this.getEntry(toolUseId) : undefined;\n if (!entry) continue;\n if (entry.kind === \"ask\") {\n const sidecar = asRecord(record.toolUseResult);\n const answersRaw = asRecord(sidecar?.answers);\n if (answersRaw) {\n const answers: Record<string, string> = {};\n for (const [q, a] of Object.entries(answersRaw)) {\n if (typeof a === \"string\") answers[q] = a;\n }\n changed.push(this.upsert({ ...entry, answers }));\n } else {\n changed.push(this.upsert({ ...entry, rejected: true }));\n }\n continue;\n }\n if (entry.kind !== \"tool\") continue;\n const patch = extractPatch(record.toolUseResult);\n // With a patch the textual output is redundant boilerplate — keep it\n // only for failures.\n const output =\n patch && rec.is_error !== true ? \"\" : toolResultText(record.toolUseResult, rec.content);\n const images = toolResultImages(rec.content);\n changed.push(\n this.upsert({\n ...entry,\n result: {\n ok: rec.is_error !== true,\n output: truncate(output, RESULT_CHAR_LIMIT),\n ...(images.length > 0 ? { images } : {}),\n },\n ...(patch ? { patch } : {}),\n }),\n );\n } else if (rec.type === \"text\") {\n const raw = readString(rec.text);\n const text = raw === null ? null : unwrapPasted(raw);\n if (text && text.trim().length > 0) promptTexts.push(text);\n }\n }\n const interrupt = promptTexts.length === 1 ? interruptNote(promptTexts[0]) : null;\n if (interrupt) {\n changed.push(this.upsert({ kind: \"interrupt\", id: uuid, ts, text: interrupt }));\n } else if (promptTexts.length > 0) {\n changed.push(\n ...this.rewindTo(record),\n this.upsert({\n kind: \"user\",\n id: uuid,\n ts,\n text: truncate(promptTexts.join(\"\\n\\n\"), TEXT_CHAR_LIMIT),\n ...this.dictatedFlag(promptTexts.join(\"\\n\\n\"), ts),\n }),\n );\n }\n return changed;\n }\n\n private feedAssistant(record: Record<string, unknown>): string[] {\n const message = asRecord(record.message);\n if (message) this.context = readContextUsage(message) ?? this.context;\n if (message) this.model = readString(message.model) ?? this.model;\n const content = message?.content;\n if (!Array.isArray(content)) return [];\n const uuid = readString(record.uuid) ?? `assistant-${this.entries.length}`;\n const ts = parseTimestamp(record.timestamp);\n const changed: string[] = [];\n\n for (let i = 0; i < content.length; i++) {\n const block = asRecord(content[i]);\n if (!block) continue;\n const blockId = `${uuid}:${i}`;\n switch (block.type) {\n case \"text\": {\n const text = readString(block.text);\n if (text && text.trim().length > 0) {\n changed.push(\n this.upsert({ kind: \"text\", id: blockId, ts, text: truncate(text, TEXT_CHAR_LIMIT) }),\n );\n }\n break;\n }\n case \"thinking\": {\n const text = readString(block.thinking);\n // Thinking lines can carry only a signature with empty text — skip those.\n if (text && text.trim().length > 0) {\n changed.push(\n this.upsert({\n kind: \"thinking\",\n id: blockId,\n ts,\n text: truncate(text, TEXT_CHAR_LIMIT),\n }),\n );\n }\n break;\n }\n case \"tool_use\": {\n const toolUseId = readString(block.id) ?? blockId;\n const name = readString(block.name) ?? \"tool\";\n const input = asRecord(block.input) ?? {};\n if (name === \"AskUserQuestion\") {\n const questions = parseAskQuestions(input);\n if (questions.length > 0) {\n changed.push(this.upsert({ kind: \"ask\", id: toolUseId, ts, questions }));\n break;\n }\n }\n let inputText: string;\n try {\n inputText = JSON.stringify(input, null, 2);\n } catch {\n inputText = \"{}\";\n }\n changed.push(\n this.upsert({\n kind: \"tool\",\n id: toolUseId,\n ts,\n name,\n summary: summarizeToolUse(name, input),\n input: truncate(inputText, INPUT_CHAR_LIMIT),\n }),\n );\n break;\n }\n }\n }\n return changed;\n }\n}\n","import { readdirSync, statSync } from \"fs\";\nimport { SESSIONS_DIR } from \"../utils/paths.js\";\nimport { join } from \"path\";\n\nexport interface WatcherCallback {\n /** `changed` holds the ids of the sessions whose JSON was added, changed or removed. */\n (changed: ReadonlySet<string>): void;\n}\n\n/** A session's JSON is named after its id. */\nfunction sessionIdOf(file: string): string {\n return file.slice(0, -\".json\".length);\n}\n\n/**\n * Simple polling-based file watcher for session JSON files.\n * More reliable than inotify for long-running processes.\n */\nclass SessionWatcher {\n private subscribers = new Set<WatcherCallback>();\n private pollTimer: ReturnType<typeof setInterval> | null = null;\n private lastState = new Map<string, number>(); // filename -> mtime\n private readonly pollInterval = 500;\n\n private start(): void {\n if (this.pollTimer) return;\n\n console.log(\"[watcher] Started polling\", SESSIONS_DIR, `(${this.pollInterval}ms)`);\n\n // Initialize state\n this.updateState();\n\n this.pollTimer = setInterval(() => {\n const changed = this.checkForChanges();\n if (changed.size > 0) {\n this.notifySubscribers(changed);\n }\n }, this.pollInterval);\n }\n\n private updateState(): void {\n this.lastState.clear();\n try {\n const files = readdirSync(SESSIONS_DIR);\n for (const file of files) {\n if (!file.endsWith(\".json\")) continue;\n try {\n const stat = statSync(join(SESSIONS_DIR, file));\n this.lastState.set(file, stat.mtimeMs);\n } catch {\n // File may have been deleted\n }\n }\n } catch {\n // Directory may not exist yet\n }\n }\n\n private checkForChanges(): Set<string> {\n const newState = new Map<string, number>();\n const changed = new Set<string>();\n\n try {\n const files = readdirSync(SESSIONS_DIR);\n for (const file of files) {\n if (!file.endsWith(\".json\")) continue;\n try {\n const stat = statSync(join(SESSIONS_DIR, file));\n newState.set(file, stat.mtimeMs);\n\n const oldMtime = this.lastState.get(file);\n if (oldMtime !== stat.mtimeMs) {\n console.log(`[watcher] File ${oldMtime === undefined ? \"added\" : \"changed\"}:`, file);\n changed.add(sessionIdOf(file));\n }\n } catch {\n // File may have been deleted during iteration\n }\n }\n\n // Check for deleted files\n for (const file of this.lastState.keys()) {\n if (!newState.has(file)) {\n console.log(\"[watcher] File removed:\", file);\n changed.add(sessionIdOf(file));\n }\n }\n } catch {\n // Directory may not exist\n }\n\n this.lastState = newState;\n return changed;\n }\n\n private notifySubscribers(changed: ReadonlySet<string>): void {\n console.log(\"[watcher] Notifying\", this.subscribers.size, \"subscribers\");\n for (const callback of this.subscribers) {\n try {\n callback(changed);\n } catch (error) {\n console.error(\"[watcher] Subscriber error:\", error);\n }\n }\n }\n\n subscribe(callback: WatcherCallback): () => void {\n this.subscribers.add(callback);\n if (this.subscribers.size === 1) {\n this.start();\n }\n return () => {\n this.subscribers.delete(callback);\n if (this.subscribers.size === 0) {\n this.stop();\n }\n };\n }\n\n private stop(): void {\n if (this.pollTimer) {\n clearInterval(this.pollTimer);\n this.pollTimer = null;\n }\n this.lastState.clear();\n console.log(\"[watcher] Stopped\");\n }\n}\n\nexport const sessionWatcher = new SessionWatcher();\n","/**\n * What a session changed, read off its own log.\n *\n * Every Edit, Write, MultiEdit and NotebookEdit result carries a sidecar\n * (`toolUseResult`) with the file it touched and the patch it applied, as\n * git-style hunks in `structuredPatch`. A Write that created the file says\n * `type: \"create\"` and leaves the patch empty, so its whole `content` is the\n * addition. Nothing here reads the disk: the log is the record, which is what\n * lets this source cover files outside any repo — and what makes it blind to\n * changes made through Bash.\n *\n * The collector groups changes by turn — a prompt the user typed (or a slash\n * command they ran) up to the next one — keyed by that prompt line's uuid, the\n * same id the transcript gives the prompt's entry.\n */\n\nimport { asRecord, readString } from \"./json.js\";\nimport { peekTranscriptPath } from \"./context-peek.js\";\nimport { JsonlTailer } from \"./tailer.js\";\nimport { ForkTracker } from \"./forks.js\";\nimport { interruptNote, parseSlashCommand, readStructuredPatch, type PatchHunk } from \"./parser.js\";\n\nexport type FileChangeKind = \"added\" | \"modified\" | \"deleted\";\n\n/** One tool call's change to one file. */\nexport interface FileChange {\n file: string;\n kind: FileChangeKind;\n additions: number;\n deletions: number;\n hunks: PatchHunk[];\n}\n\n/** A file's change as counted, without its hunks — what a list draws. */\nexport type FileChangeCount = Omit<FileChange, \"hunks\">;\n\nexport interface TurnChanges {\n /** The prompt line's uuid, or null for changes logged before any prompt. */\n id: string | null;\n /** The turn's place in the session, counting every prompt from 1; 0 before the first. */\n n: number;\n ts: number;\n /** The prompt, cut to a line, so a list can say which turn this was. */\n prompt: string;\n files: FileChangeCount[];\n}\n\nexport interface ChangesSummary {\n files: number;\n additions: number;\n deletions: number;\n}\n\n/** Totals over a list of counted files. */\nexport function summarize(files: { additions: number; deletions: number }[]): ChangesSummary {\n return {\n files: files.length,\n additions: files.reduce((n, f) => n + f.additions, 0),\n deletions: files.reduce((n, f) => n + f.deletions, 0),\n };\n}\n\n/** Edit and MultiEdit name the file `filePath`; NotebookEdit names it `notebook_path`. */\nfunction sidecarFile(sc: Record<string, unknown>): string | null {\n return readString(sc.filePath) ?? readString(sc.notebook_path);\n}\n\nfunction countLines(hunks: PatchHunk[]): { additions: number; deletions: number } {\n let additions = 0;\n let deletions = 0;\n for (const hunk of hunks) {\n for (const line of hunk.lines) {\n if (line.startsWith(\"+\")) additions++;\n else if (line.startsWith(\"-\")) deletions++;\n }\n }\n return { additions, deletions };\n}\n\n/** A new file's content as the one hunk that adds it. */\nfunction creationHunk(content: string): PatchHunk[] {\n const lines = content.split(\"\\n\");\n if (lines[lines.length - 1] === \"\") lines.pop();\n if (lines.length === 0) return [];\n return [{ header: `@@ -0,0 +1,${lines.length} @@`, lines: lines.map((line) => `+${line}`) }];\n}\n\n/**\n * The change a tool result's sidecar records, or null when the sidecar is not\n * a file edit. A Write counts as adding the file when it says it created it,\n * or when it carries content but no `originalFile` to have changed.\n */\nexport function fileChangeFromSidecar(sidecar: unknown): FileChange | null {\n const sc = asRecord(sidecar);\n if (!sc || !(\"structuredPatch\" in sc)) return null;\n const file = sidecarFile(sc);\n if (!file) return null;\n const content = readString(sc.content);\n const created =\n sc.type === \"create\" || (sc.type === undefined && content !== null && !(\"originalFile\" in sc));\n let hunks = readStructuredPatch(sc.structuredPatch);\n if (created && hunks.length === 0 && content !== null) hunks = creationHunk(content);\n return { file, kind: created ? \"added\" : \"modified\", ...countLines(hunks), hunks };\n}\n\n/** Prompts the harness wrote rather than a person: notifications, reminders, a local command's lines. */\nconst HARNESS_PROMPT = /^<(task-notification|system-reminder|local-command-)/;\n\n/** The text that opens a turn, or null when the line is not a prompt. */\nexport function promptText(record: Record<string, unknown>): string | null {\n if (record.isMeta === true || record.isCompactSummary === true) return null;\n const kind = asRecord(record.origin)?.kind;\n if (kind !== undefined && kind !== \"human\") return null;\n const content = asRecord(record.message)?.content;\n let text: string;\n if (typeof content === \"string\") text = content;\n else if (Array.isArray(content)) {\n const parts: string[] = [];\n for (const block of content) {\n const rec = asRecord(block);\n if (rec?.type === \"tool_result\") return null;\n const part = rec?.type === \"text\" ? readString(rec.text) : null;\n if (part) parts.push(part);\n }\n text = parts.join(\"\\n\");\n } else return null;\n text = text.trim();\n if (!text || HARNESS_PROMPT.test(text) || interruptNote(text)) return null;\n const command = parseSlashCommand(text);\n if (command) text = command.args ? `${command.name} ${command.args}` : command.name;\n const firstLine = text.split(\"\\n\", 1)[0];\n return firstLine.length > 120 ? `${firstLine.slice(0, 117)}...` : firstLine;\n}\n\n/** Whether a prompt line is the harness's record of a slash command. */\nfunction isCommand(record: Record<string, unknown>): boolean {\n const content = asRecord(record.message)?.content;\n return typeof content === \"string\" && parseSlashCommand(content.trim()) !== null;\n}\n\nexport function parseTs(value: unknown): number {\n const ts = typeof value === \"string\" ? Date.parse(value) : NaN;\n return Number.isFinite(ts) ? ts : 0;\n}\n\ninterface Turn {\n id: string | null;\n /** The prompt line's position in the log, for telling which turns a rewind left behind. */\n seq: number;\n n: number;\n ts: number;\n prompt: string;\n /** Per file, every change in order. */\n changes: Map<string, FileChange[]>;\n}\n\n/** Fold several changes to one file into a single count. */\nfunction count(file: string, changes: FileChange[]): FileChangeCount {\n return {\n file,\n // Created at some point in the run means new to whoever reads the run.\n kind: changes[0].kind,\n additions: changes.reduce((n, c) => n + c.additions, 0),\n deletions: changes.reduce((n, c) => n + c.deletions, 0),\n };\n}\n\n/** Fold several changes to one file into a single change, hunks and all. */\nfunction merge(file: string, changes: FileChange[]): FileChange {\n return { ...count(file, changes), hunks: changes.flatMap((c) => c.hunks) };\n}\n\n/**\n * Feed a session's JSONL lines in file order; read the changes out per turn\n * or per session. Lines that cannot carry a change or open a turn are passed\n * over before parsing, so catching up on a long log costs little more than\n * reading it.\n */\nexport class ChangesCollector {\n private turns: Turn[] = [];\n /** tool_use ids already counted, so a line written twice is counted once. */\n private seen = new Set<string>();\n private forks = new ForkTracker();\n\n feed(line: string): void {\n // A tool result without a patch can neither change a file nor open a turn,\n // but every line of the conversation (which opens with its parentUuid) has\n // to be placed for a rewind to be told from a prompt that follows on.\n const carriesChange = line.includes('\"structuredPatch\"');\n const mayOpen = line.includes('\"type\":\"user\"') && !line.includes('\"tool_result\"');\n if (!carriesChange && !mayOpen && !line.startsWith('{\"parentUuid\"')) return;\n let record: Record<string, unknown> | null;\n try {\n record = asRecord(JSON.parse(line));\n } catch {\n return;\n }\n if (!record || record.isSidechain === true) return;\n const uuid = readString(record.uuid);\n const seq = uuid ? this.forks.see(uuid, record.type) : -1;\n if (record.type !== \"user\" || (!carriesChange && !mayOpen)) return;\n\n if (carriesChange) {\n const change = fileChangeFromSidecar(record.toolUseResult);\n if (!change) return;\n const content = asRecord(record.message)?.content;\n const result = Array.isArray(content)\n ? content.map(asRecord).find((block) => block?.type === \"tool_result\")\n : undefined;\n const toolUseId = readString(result?.tool_use_id);\n if (toolUseId) {\n if (this.seen.has(toolUseId)) return;\n this.seen.add(toolUseId);\n }\n let turn = this.turns[this.turns.length - 1];\n if (!turn) {\n turn = { id: null, seq: -1, n: 0, ts: parseTs(record.timestamp), prompt: \"\", changes: new Map() };\n this.turns.push(turn);\n }\n const list = turn.changes.get(change.file);\n if (list) list.push(change);\n else turn.changes.set(change.file, [change]);\n return;\n }\n\n const prompt = promptText(record);\n if (prompt === null) return;\n // A command pasted into the prompt is logged twice: the text as typed, then\n // the harness's bundle once it ran. The transcript folds the bundle into the\n // first line, and so does this: one turn, under the first line's id.\n const last = this.turns[this.turns.length - 1];\n if (last && last.changes.size === 0 && last.prompt === prompt && isCommand(record)) return;\n // A rewind went back past the turns after its point, and with them their\n // changes, which Claude Code restored when it was asked to.\n const after = this.forks.abandonedAfter(readString(record.parentUuid));\n if (after !== null) this.turns = this.turns.filter((turn) => turn.seq <= after);\n this.turns.push({\n id: uuid,\n seq,\n n: (this.turns[this.turns.length - 1]?.n ?? 0) + 1,\n ts: parseTs(record.timestamp),\n prompt,\n changes: new Map(),\n });\n }\n\n /** The id of every turn's prompt, changed something or not, oldest first. */\n promptIds(): string[] {\n return this.turns.flatMap((turn) => (turn.id ? [turn.id] : []));\n }\n\n /** The turns that changed something, oldest first. */\n byTurn(): TurnChanges[] {\n return this.turns\n .filter((turn) => turn.changes.size > 0)\n .map((turn) => ({\n id: turn.id,\n n: turn.n,\n ts: turn.ts,\n prompt: turn.prompt,\n files: [...turn.changes].map(([file, list]) => count(file, list)),\n }));\n }\n\n /** Every change to each file over every turn, in the order first touched. */\n private perFile(): Map<string, FileChange[]> {\n const all = new Map<string, FileChange[]>();\n for (const turn of this.turns) {\n for (const [file, list] of turn.changes) {\n const prior = all.get(file);\n if (prior) prior.push(...list);\n else all.set(file, [...list]);\n }\n }\n return all;\n }\n\n /** Each file the session changed, folded over every turn, in the order first touched. */\n files(): FileChange[] {\n return [...this.perFile()].map(([file, list]) => merge(file, list));\n }\n\n /** As `files()`, counted without folding any hunks. */\n counts(): FileChangeCount[] {\n return [...this.perFile()].map(([file, list]) => count(file, list));\n }\n\n /** One file's change: over the whole session, or within the turn `turnId` names. */\n file(file: string, turnId?: string | null): FileChange | null {\n const list =\n turnId === undefined\n ? this.perFile().get(file)\n : this.turns.find((turn) => turn.id === turnId)?.changes.get(file);\n return list ? merge(file, list) : null;\n }\n\n summary(): ChangesSummary {\n return summarize(this.counts());\n }\n}\n\n// ---------------------------------------------------------------------------\n// One collector per transcript, caught up from where it last read.\n// ---------------------------------------------------------------------------\n\ninterface Tracked {\n tailer: JsonlTailer;\n collector: ChangesCollector;\n usedAt: number;\n}\n\n/** A log nobody has asked about for this long is dropped, hunks and all. */\nconst FORGET_MS = 10 * 60_000;\n\nconst tracked = new Map<string, Tracked>();\n\n/** Forget everything — for tests. */\nexport function resetChangesCache(): void {\n tracked.clear();\n}\n\n/**\n * The session's changes as its log has them now, or null when it has no log\n * yet. The first call reads the whole file; later ones read only what was\n * appended since.\n */\nexport function sessionChanges(session: {\n id: string;\n cwd: string;\n transcript_path?: string | null;\n}): ChangesCollector | null {\n const path = peekTranscriptPath(session);\n if (!path) return null;\n const now = Date.now();\n for (const [other, entry] of tracked) if (now - entry.usedAt > FORGET_MS) tracked.delete(other);\n let t = tracked.get(path);\n if (!t) {\n t = { tailer: new JsonlTailer(path), collector: new ChangesCollector(), usedAt: now };\n tracked.set(path, t);\n }\n t.usedAt = now;\n for (;;) {\n const read = t.tailer.read();\n if (read.status === \"reset\") {\n t.collector = new ChangesCollector();\n continue;\n }\n if (read.status === \"lines\") for (const line of read.lines) t.collector.feed(line);\n return t.collector;\n }\n}\n","/**\n * What git says changed in the repo a session works in — the \"Current\"\n * source of the Changes panel, which catches edits made through Bash that\n * the session's log never records.\n *\n * Every call goes through `execFile` with an argument list, never a shell,\n * and every path a caller names is checked against the repo root before git\n * sees it. Status is cached per repo and re-read only when a session in the\n * repo writes its JSON (each hook event does), and then at most once every\n * REFRESH_MS: there is no timer polling git.\n */\n\nimport { execFile } from 'child_process';\nimport { closeSync, openSync, readSync, statSync } from 'fs';\nimport { isAbsolute, relative, resolve, sep } from 'path';\nimport type { PatchHunk } from '../transcript/parser.js';\nimport { summarize, type ChangesSummary } from '../transcript/changes.js';\nimport { getSession } from '../db/sessions-json.js';\nimport { sessionWatcher } from './watcher.js';\n\nexport type GitFileKind = 'added' | 'modified' | 'deleted' | 'renamed';\n\nexport interface GitFileStatus {\n\t/** Relative to the repo root, `/`-separated as git prints it. */\n\tfile: string;\n\t/** Where a renamed or copied file came from. */\n\toldPath?: string;\n\tkind: GitFileKind;\n\tuntracked?: true;\n\tbinary?: true;\n\tadditions: number;\n\tdeletions: number;\n}\n\nexport interface GitChanges {\n\troot: string;\n\tfiles: GitFileStatus[];\n\t/** What the counts are taken against: HEAD, or the empty tree before the first commit. */\n\tbase: string;\n}\n\nexport interface GitDiff {\n\tfile: string;\n\tbinary: boolean;\n\thunks: PatchHunk[];\n}\n\n/** A file's line counts, as numstat gives them or as counted off an untracked file. */\ninterface LineCount {\n\tadditions: number;\n\tdeletions: number;\n\tbinary: boolean;\n}\n\n/** The fastest a repo is re-read, however often its sessions change. */\nconst REFRESH_MS = 2_000;\n/** A repo nobody has asked about for this long is dropped. */\nconst FORGET_MS = 10 * 60_000;\n/** A directory found not to be in a work tree is asked again only this often. */\nconst NO_REPO_RETRY_MS = 60_000;\n/** Untracked files bigger than this are listed without counting their lines. */\nconst COUNT_LIMIT_BYTES = 2 * 1024 * 1024;\n/** What git writes for an empty tree, to diff against in a repo with no commits yet. */\nconst EMPTY_TREE = '4b825dc642cb6eb9a060e54bf8d69288fbee4904';\n\n/** Run git in `cwd` with paths unquoted; null on an exit code outside `okCodes`. */\nexport function git(\n\targs: string[],\n\tcwd: string,\n\tokCodes: number[] = [0]\n): Promise<string | null> {\n\treturn new Promise((done) => {\n\t\texecFile(\n\t\t\t'git',\n\t\t\t['-c', 'core.quotepath=off', ...args],\n\t\t\t{ cwd, timeout: 20_000, maxBuffer: 64 * 1024 * 1024 },\n\t\t\t(err, stdout) => {\n\t\t\t\tconst code = err ? (typeof err.code === 'number' ? err.code : -1) : 0;\n\t\t\t\tdone(okCodes.includes(code) ? stdout : null);\n\t\t\t}\n\t\t);\n\t});\n}\n\n// ---------------------------------------------------------------------------\n// Parsing\n// ---------------------------------------------------------------------------\n\n/**\n * Parse `git status --porcelain=v2 -z`. Ordinary entries (`1`) carry one path,\n * renames and copies (`2`) a second NUL-terminated field with the old path,\n * unmerged entries (`u`) count as modified, and untracked ones (`?`) as added.\n * Ignored entries (`!`) and headers (`#`) are dropped.\n */\nexport function parsePorcelainV2(out: string): Omit<GitFileStatus, 'additions' | 'deletions'>[] {\n\tconst fields = out.split('\\0');\n\tconst files: Omit<GitFileStatus, 'additions' | 'deletions'>[] = [];\n\tfor (let i = 0; i < fields.length; i++) {\n\t\tconst field = fields[i];\n\t\tif (!field) continue;\n\t\tconst type = field[0];\n\t\tif (type === '?') {\n\t\t\tfiles.push({ file: field.slice(2), kind: 'added', untracked: true });\n\t\t} else if (type === '1') {\n\t\t\t// 1 <XY> <sub> <mH> <mI> <mW> <hH> <hI> <path>\n\t\t\tconst parts = field.split(' ');\n\t\t\tfiles.push({ file: parts.slice(8).join(' '), kind: kindOf(parts[1]) });\n\t\t} else if (type === '2') {\n\t\t\t// 2 <XY> <sub> <mH> <mI> <mW> <hH> <hI> <X><score> <path>\\0<origPath>\n\t\t\tconst parts = field.split(' ');\n\t\t\tconst oldPath = fields[++i] ?? '';\n\t\t\tconst file = parts.slice(9).join(' ');\n\t\t\tfiles.push({ file, oldPath, kind: parts[8].startsWith('C') ? 'added' : 'renamed' });\n\t\t} else if (type === 'u') {\n\t\t\t// u <XY> <sub> <m1> <m2> <m3> <mW> <h1> <h2> <h3> <path>\n\t\t\tfiles.push({ file: field.split(' ').slice(10).join(' '), kind: 'modified' });\n\t\t}\n\t}\n\treturn files;\n}\n\n/** The kind an ordinary entry's XY reads as; the worktree column wins over the index. */\nfunction kindOf(xy: string): GitFileKind {\n\tif (xy.includes('D')) return 'deleted';\n\tif (xy[0] === 'A') return 'added';\n\treturn 'modified';\n}\n\n/**\n * Parse `git diff --numstat -z`: `add\\tdel\\tpath\\0`, or for a rename\n * `add\\tdel\\t\\0old\\0new\\0`. A binary file counts as `-\\t-`.\n */\nexport function parseNumstat(out: string): Map<string, LineCount> {\n\tconst counts = new Map<string, LineCount>();\n\tconst fields = out.split('\\0');\n\tfor (let i = 0; i < fields.length; i++) {\n\t\tconst field = fields[i];\n\t\tif (!field) continue;\n\t\tconst [add, del, path] = field.split('\\t');\n\t\tif (del === undefined) continue;\n\t\t// A rename leaves the path empty and spells old and new in the next fields.\n\t\tconst file = path ? path : (i += 2, fields[i] ?? '');\n\t\tconst binary = add === '-' && del === '-';\n\t\tcounts.set(file, {\n\t\t\tadditions: binary ? 0 : Number(add) || 0,\n\t\t\tdeletions: binary ? 0 : Number(del) || 0,\n\t\t\tbinary\n\t\t});\n\t}\n\treturn counts;\n}\n\n/** Split a unified diff into hunks, dropping the file headers above the first. */\nexport function parseUnifiedDiff(out: string): { binary: boolean; hunks: PatchHunk[] } {\n\tconst hunks: PatchHunk[] = [];\n\tlet binary = false;\n\tlet current: PatchHunk | null = null;\n\tfor (const line of out.split('\\n')) {\n\t\tif (line.startsWith('diff ')) {\n\t\t\t// A second file section (a rename git no longer pairs): its headers are not hunk lines.\n\t\t\tcurrent = null;\n\t\t} else if (line.startsWith('@@')) {\n\t\t\tcurrent = { header: line.replace(/^(@@[^@]*@@).*$/, '$1'), lines: [] };\n\t\t\thunks.push(current);\n\t\t} else if (current && /^[ +\\-\\\\]/.test(line)) {\n\t\t\tcurrent.lines.push(line);\n\t\t} else if (!current && /^Binary files .* differ$|^GIT binary patch$/.test(line)) {\n\t\t\tbinary = true;\n\t\t}\n\t}\n\treturn { binary, hunks };\n}\n\n// ---------------------------------------------------------------------------\n// Paths\n// ---------------------------------------------------------------------------\n\n/**\n * The repo-relative form of `file` when it names something inside `root`,\n * or null when it climbs out or is absolute elsewhere.\n */\nexport function confinePath(root: string, file: string): string | null {\n\tif (!file || file.includes('\\0')) return null;\n\tconst abs = isAbsolute(file) ? resolve(file) : resolve(root, file);\n\tconst rel = relative(root, abs);\n\tif (!rel || rel === '..' || rel.startsWith('..' + sep) || isAbsolute(rel)) return null;\n\treturn rel.split(sep).join('/');\n}\n\n// ---------------------------------------------------------------------------\n// Reading a repo\n// ---------------------------------------------------------------------------\n\n/** Untracked counts by path, kept while the file's size and mtime hold. */\nconst untrackedCounts = new Map<string, { size: number; mtimeMs: number; count: LineCount | null }>();\n\n/** Lines in a file git does not know yet, or binary when it holds a NUL. */\nfunction countUntracked(path: string): LineCount | null {\n\ttry {\n\t\tconst { size, mtimeMs } = statSync(path);\n\t\tconst memo = untrackedCounts.get(path);\n\t\tif (memo && memo.size === size && memo.mtimeMs === mtimeMs) return memo.count;\n\t\tconst count = readLineCount(path, size);\n\t\tuntrackedCounts.set(path, { size, mtimeMs, count });\n\t\treturn count;\n\t} catch {\n\t\tuntrackedCounts.delete(path);\n\t\treturn null;\n\t}\n}\n\nfunction readLineCount(path: string, size: number): LineCount | null {\n\ttry {\n\t\tif (size > COUNT_LIMIT_BYTES) return null;\n\t\tconst buffer = Buffer.alloc(size);\n\t\tconst fd = openSync(path, 'r');\n\t\ttry {\n\t\t\treadSync(fd, buffer, 0, size, 0);\n\t\t} finally {\n\t\t\tcloseSync(fd);\n\t\t}\n\t\tif (buffer.subarray(0, 8000).includes(0)) return { additions: 0, deletions: 0, binary: true };\n\t\tlet lines = 0;\n\t\tfor (let i = buffer.indexOf(0x0a); i !== -1; i = buffer.indexOf(0x0a, i + 1)) lines++;\n\t\tif (size > 0 && buffer[size - 1] !== 0x0a) lines++;\n\t\treturn { additions: lines, deletions: 0, binary: false };\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/** HEAD, or the empty tree when the repo has no commits yet. */\nasync function baseRev(root: string): Promise<string> {\n\treturn (await git(['rev-parse', '--verify', '-q', 'HEAD'], root)) ? 'HEAD' : EMPTY_TREE;\n}\n\nasync function readChanges(root: string): Promise<GitChanges | null> {\n\tconst [status, base] = await Promise.all([\n\t\tgit(['status', '--porcelain=v2', '-z', '--untracked-files=all'], root),\n\t\tbaseRev(root)\n\t]);\n\tif (status === null) return null;\n\tconst numstat = (await git(['diff', '--numstat', '-z', '-M', base], root)) ?? '';\n\tconst counts = parseNumstat(numstat);\n\tconst entries = parsePorcelainV2(status);\n\t// Drop memoised counts for files under this root that are no longer untracked.\n\tconst untracked = new Set(entries.filter((e) => e.untracked).map((e) => resolve(root, e.file)));\n\tfor (const path of untrackedCounts.keys()) {\n\t\tif (path.startsWith(root + sep) && !untracked.has(path)) untrackedCounts.delete(path);\n\t}\n\tconst files = entries.map((entry): GitFileStatus => {\n\t\tconst count = entry.untracked\n\t\t\t? countUntracked(resolve(root, entry.file))\n\t\t\t: counts.get(entry.file);\n\t\treturn {\n\t\t\t...entry,\n\t\t\tadditions: count?.additions ?? 0,\n\t\t\tdeletions: count?.deletions ?? 0,\n\t\t\t...(count?.binary ? { binary: true as const } : {})\n\t\t};\n\t});\n\treturn { root, files, base };\n}\n\n// ---------------------------------------------------------------------------\n// Cache\n// ---------------------------------------------------------------------------\n\ninterface RepoState {\n\tchanges: GitChanges | null;\n\trefreshedAt: number;\n\tdirty: boolean;\n\tinflight: Promise<GitChanges | null> | null;\n\ttrailing: ReturnType<typeof setTimeout> | null;\n\taskedAt: number;\n}\n\n/** cwd → repo root, or null when the cwd is in no work tree (with when that was found). */\nconst roots = new Map<string, { root: string | null; at: number }>();\n/** Lookups in flight, so a tick that comes round first does not ask twice. */\nconst resolving = new Map<string, Promise<string | null>>();\nconst repos = new Map<string, RepoState>();\nlet unsubscribe: (() => void) | null = null;\n\n/** Forget everything — for tests. */\nexport function resetGitCache(): void {\n\tfor (const repo of repos.values()) if (repo.trailing) clearTimeout(repo.trailing);\n\troots.clear();\n\tresolving.clear();\n\tuntrackedCounts.clear();\n\trepos.clear();\n\tunsubscribe?.();\n\tunsubscribe = null;\n}\n\n/** The work tree `cwd` sits in, or null outside one. */\nexport async function repoRoot(cwd: string): Promise<string | null> {\n\tconst known = roots.get(cwd);\n\tif (known && (known.root !== null || Date.now() - known.at < NO_REPO_RETRY_MS)) return known.root;\n\tlet pending = resolving.get(cwd);\n\tif (!pending) {\n\t\tpending = git(['rev-parse', '--show-toplevel'], cwd).then((out) => {\n\t\t\tconst root = out ? out.trim() || null : null;\n\t\t\troots.set(cwd, { root, at: Date.now() });\n\t\t\tresolving.delete(cwd);\n\t\t\treturn root;\n\t\t});\n\t\tresolving.set(cwd, pending);\n\t}\n\treturn pending;\n}\n\n/**\n * A session's JSON changed, which a hook does on every event it handles:\n * the repo it works in may have changed on disk too.\n */\nfunction noteSessionChanged(cwd: string): void {\n\t// git prints the root with symlinks resolved, so a cwd reached through one matches only by lookup.\n\tconst known = roots.get(cwd)?.root;\n\tfor (const [root, repo] of repos) {\n\t\tif (root === known || cwd === root || cwd.startsWith(root + '/')) {\n\t\t\trepo.dirty = true;\n\t\t\tschedule(root, repo);\n\t\t}\n\t}\n}\n\nfunction watch(): void {\n\tif (unsubscribe) return;\n\tunsubscribe = sessionWatcher.subscribe((changed) => {\n\t\tfor (const id of changed) {\n\t\t\tconst cwd = getSession(id)?.cwd;\n\t\t\tif (cwd) noteSessionChanged(cwd);\n\t\t}\n\t});\n}\n\nfunction refresh(root: string, repo: RepoState): Promise<GitChanges | null> {\n\tif (repo.inflight) return repo.inflight;\n\trepo.dirty = false;\n\trepo.refreshedAt = Date.now();\n\trepo.inflight = readChanges(root)\n\t\t.then((changes) => {\n\t\t\trepo.changes = changes;\n\t\t\treturn changes;\n\t\t})\n\t\t.finally(() => {\n\t\t\trepo.inflight = null;\n\t\t\t// A hook landed while git was reading: what it changed may be missing.\n\t\t\tif (repo.dirty) schedule(root, repo);\n\t\t});\n\treturn repo.inflight;\n}\n\n/** Re-read a dirty repo now, or as soon as the throttle allows. */\nfunction schedule(root: string, repo: RepoState): void {\n\tif (Date.now() - repo.askedAt > FORGET_MS) {\n\t\tif (repo.trailing) clearTimeout(repo.trailing);\n\t\trepos.delete(root);\n\t\treturn;\n\t}\n\tif (repo.inflight || repo.trailing) return;\n\tconst wait = repo.refreshedAt + REFRESH_MS - Date.now();\n\tif (wait <= 0) {\n\t\tvoid refresh(root, repo);\n\t\treturn;\n\t}\n\trepo.trailing = setTimeout(() => {\n\t\trepo.trailing = null;\n\t\tif (repo.dirty) void refresh(root, repo);\n\t}, wait);\n}\n\nfunction stateFor(root: string): RepoState {\n\tlet repo = repos.get(root);\n\tif (!repo) {\n\t\trepo = { changes: null, refreshedAt: 0, dirty: true, inflight: null, trailing: null, askedAt: Date.now() };\n\t\trepos.set(root, repo);\n\t}\n\trepo.askedAt = Date.now();\n\twatch();\n\treturn repo;\n}\n\n/**\n * The repo's changes, read fresh when a hook has touched it since the last\n * read (or it was never read) and the throttle allows; otherwise cached.\n * Null outside a work tree.\n */\nexport async function gitChanges(cwd: string): Promise<GitChanges | null> {\n\tconst root = await repoRoot(cwd);\n\tif (!root) return null;\n\tconst repo = stateFor(root);\n\tif (repo.inflight) return repo.inflight;\n\tif (repo.changes && (!repo.dirty || Date.now() - repo.refreshedAt < REFRESH_MS)) {\n\t\tif (repo.dirty) schedule(root, repo);\n\t\treturn repo.changes;\n\t}\n\treturn refresh(root, repo);\n}\n\n/**\n * What the broadcast shows for a cwd, without waiting on git: the last read\n * when there is one, null when the cwd is in no repo, undefined while that is\n * still being found out. Kicks off the read it needs.\n */\nexport function peekGitSummary(cwd: string): ChangesSummary | null | undefined {\n\t// The root last resolved, without asking git; undefined when not asked yet.\n\tconst root = roots.get(cwd)?.root;\n\tif (root === undefined) {\n\t\tvoid gitChanges(cwd);\n\t\treturn undefined;\n\t}\n\tif (root === null) {\n\t\t// Asks git again once the retry window has passed, so a later `git init` is noticed.\n\t\tvoid repoRoot(cwd);\n\t\treturn null;\n\t}\n\tconst repo = stateFor(root);\n\tif (!repo.changes) {\n\t\tschedule(root, repo);\n\t\treturn repo.refreshedAt ? null : undefined;\n\t}\n\treturn summarize(repo.changes.files);\n}\n\n/**\n * One file's diff against HEAD, working tree included. `file` is checked\n * against the repo root and must be one the status lists; null otherwise.\n */\nexport async function gitFileDiff(cwd: string, file: string): Promise<GitDiff | null> {\n\tconst changes = await gitChanges(cwd);\n\tif (!changes) return null;\n\tconst rel = confinePath(changes.root, file);\n\tif (!rel) return null;\n\tconst entry = changes.files.find((f) => f.file === rel);\n\tif (!entry) return null;\n\tconst out = entry.untracked\n\t\t? // --no-index exits 1 when the files differ, which they always do here.\n\t\t\tawait git(['diff', '--no-index', '--', '/dev/null', rel], changes.root, [0, 1])\n\t\t: await git(\n\t\t\t\t['diff', '-M', changes.base, '--', ...(entry.oldPath ? [entry.oldPath] : []), rel],\n\t\t\t\tchanges.root\n\t\t\t);\n\tif (out === null) return null;\n\tconst parsed = parseUnifiedDiff(out);\n\treturn { file: rel, binary: parsed.binary || entry.binary === true, hunks: parsed.hunks };\n}\n\n/** The branch checked out at `root`, or null on a detached HEAD or outside a repo. */\nexport async function currentBranch(root: string): Promise<string | null> {\n\tconst out = await git(['symbolic-ref', '--short', '-q', 'HEAD'], root);\n\treturn out?.trim() || null;\n}\n"],"names":["interrupt","FORGET_MS","count"],"mappings":"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"}
@@ -98,7 +98,7 @@ const options = {
98
98
  app: ({ head, body, assets, nonce, env }) => '<!doctype html>\n<html lang="en" class="dark">\n <head>\n <meta charset="utf-8" />\n <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />\n <meta name="theme-color" content="#111111" />\n <!-- PWA / iOS home-screen: open fullscreen (standalone) instead of inside the browser chrome -->\n <link rel="manifest" href="/manifest.webmanifest" />\n <meta name="mobile-web-app-capable" content="yes" />\n <meta name="apple-mobile-web-app-capable" content="yes" />\n <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />\n <meta name="apple-mobile-web-app-title" content="claude-mux" />\n <link rel="apple-touch-icon" href="/apple-touch-icon.png" />\n <link rel="icon" type="image/svg+xml" href="/favicon.svg" />\n ' + head + '\n </head>\n <body data-sveltekit-preload-data="hover">\n <div style="display: contents">' + body + "</div>\n </body>\n</html>\n",
99
99
  error
100
100
  },
101
- version_hash: "1pkl9hv"
101
+ version_hash: "1y4ccu3"
102
102
  };
103
103
  async function get_hooks() {
104
104
  let handle;
@@ -1 +1 @@
1
- {"version":3,"file":"internal2.js","sources":["../../../generated/shared/error-template.js","../../../generated/server/internal.js"],"sourcesContent":["export default ({ status, message }) => \"<!doctype html>\\n<html lang=\\\"en\\\">\\n\\t<head>\\n\\t\\t<meta charset=\\\"utf-8\\\" />\\n\\t\\t<title>\" + message + \"</title>\\n\\n\\t\\t<style>\\n\\t\\t\\tbody {\\n\\t\\t\\t\\t--bg: white;\\n\\t\\t\\t\\t--fg: #222;\\n\\t\\t\\t\\t--divider: #ccc;\\n\\t\\t\\t\\tbackground: var(--bg);\\n\\t\\t\\t\\tcolor: var(--fg);\\n\\t\\t\\t\\tfont-family:\\n\\t\\t\\t\\t\\tsystem-ui,\\n\\t\\t\\t\\t\\t-apple-system,\\n\\t\\t\\t\\t\\tBlinkMacSystemFont,\\n\\t\\t\\t\\t\\t'Segoe UI',\\n\\t\\t\\t\\t\\tRoboto,\\n\\t\\t\\t\\t\\tOxygen,\\n\\t\\t\\t\\t\\tUbuntu,\\n\\t\\t\\t\\t\\tCantarell,\\n\\t\\t\\t\\t\\t'Open Sans',\\n\\t\\t\\t\\t\\t'Helvetica Neue',\\n\\t\\t\\t\\t\\tsans-serif;\\n\\t\\t\\t\\tdisplay: flex;\\n\\t\\t\\t\\talign-items: center;\\n\\t\\t\\t\\tjustify-content: center;\\n\\t\\t\\t\\theight: 100vh;\\n\\t\\t\\t\\tmargin: 0;\\n\\t\\t\\t}\\n\\n\\t\\t\\t.error {\\n\\t\\t\\t\\tdisplay: flex;\\n\\t\\t\\t\\talign-items: center;\\n\\t\\t\\t\\tmax-width: 32rem;\\n\\t\\t\\t\\tmargin: 0 1rem;\\n\\t\\t\\t}\\n\\n\\t\\t\\t.status {\\n\\t\\t\\t\\tfont-weight: 200;\\n\\t\\t\\t\\tfont-size: 3rem;\\n\\t\\t\\t\\tline-height: 1;\\n\\t\\t\\t\\tposition: relative;\\n\\t\\t\\t\\ttop: -0.05rem;\\n\\t\\t\\t}\\n\\n\\t\\t\\t.message {\\n\\t\\t\\t\\tborder-left: 1px solid var(--divider);\\n\\t\\t\\t\\tpadding: 0 0 0 1rem;\\n\\t\\t\\t\\tmargin: 0 0 0 1rem;\\n\\t\\t\\t\\tmin-height: 2.5rem;\\n\\t\\t\\t\\tdisplay: flex;\\n\\t\\t\\t\\talign-items: center;\\n\\t\\t\\t}\\n\\n\\t\\t\\t.message h1 {\\n\\t\\t\\t\\tfont-weight: 400;\\n\\t\\t\\t\\tfont-size: 1em;\\n\\t\\t\\t\\tmargin: 0;\\n\\t\\t\\t}\\n\\n\\t\\t\\t@media (prefers-color-scheme: dark) {\\n\\t\\t\\t\\tbody {\\n\\t\\t\\t\\t\\t--bg: #222;\\n\\t\\t\\t\\t\\t--fg: #ddd;\\n\\t\\t\\t\\t\\t--divider: #666;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t</style>\\n\\t</head>\\n\\t<body>\\n\\t\\t<div class=\\\"error\\\">\\n\\t\\t\\t<span class=\\\"status\\\">\" + status + \"</span>\\n\\t\\t\\t<div class=\\\"message\\\">\\n\\t\\t\\t\\t<h1>\" + message + \"</h1>\\n\\t\\t\\t</div>\\n\\t\\t</div>\\n\\t</body>\\n</html>\\n\";","\nimport root from '../root.js';\nimport { set_building, set_prerendering } from '$app/env/internal';\nimport { set_assets } from '$app/paths/internal/server';\nimport { set_manifest, set_read_implementation } from '__sveltekit/server';\nimport { set_private_env, set_public_env } from '../../../../node_modules/.bun/@sveltejs+kit@2.70.3+106f9c5330cbe027/node_modules/@sveltejs/kit/src/runtime/shared-server.js';\nimport error from '../shared/error-template.js';\n\nexport const options = {\n\tapp_template_contains_nonce: false,\n\tasync: false,\n\tcsp: {\"mode\":\"auto\",\"directives\":{\"upgrade-insecure-requests\":false,\"block-all-mixed-content\":false},\"reportOnly\":{\"upgrade-insecure-requests\":false,\"block-all-mixed-content\":false}},\n\tcsrf_check_origin: true,\n\tcsrf_trusted_origins: [],\n\tembedded: false,\n\tenv_public_prefix: 'PUBLIC_',\n\tenv_private_prefix: '',\n\thash_routing: false,\n\thooks: null, // added lazily, via `get_hooks`\n\tpreload_strategy: \"modulepreload\",\n\troot,\n\tservice_worker: true,\n\tservice_worker_options: undefined,\n\tserver_error_boundaries: false,\n\ttemplates: {\n\t\tapp: ({ head, body, assets, nonce, env }) => \"<!doctype html>\\n<html lang=\\\"en\\\" class=\\\"dark\\\">\\n\\t<head>\\n\\t\\t<meta charset=\\\"utf-8\\\" />\\n\\t\\t<meta name=\\\"viewport\\\" content=\\\"width=device-width, initial-scale=1, viewport-fit=cover\\\" />\\n\\t\\t<meta name=\\\"theme-color\\\" content=\\\"#111111\\\" />\\n\\t\\t<!-- PWA / iOS home-screen: open fullscreen (standalone) instead of inside the browser chrome -->\\n\\t\\t<link rel=\\\"manifest\\\" href=\\\"/manifest.webmanifest\\\" />\\n\\t\\t<meta name=\\\"mobile-web-app-capable\\\" content=\\\"yes\\\" />\\n\\t\\t<meta name=\\\"apple-mobile-web-app-capable\\\" content=\\\"yes\\\" />\\n\\t\\t<meta name=\\\"apple-mobile-web-app-status-bar-style\\\" content=\\\"black-translucent\\\" />\\n\\t\\t<meta name=\\\"apple-mobile-web-app-title\\\" content=\\\"claude-mux\\\" />\\n\\t\\t<link rel=\\\"apple-touch-icon\\\" href=\\\"/apple-touch-icon.png\\\" />\\n\\t\\t<link rel=\\\"icon\\\" type=\\\"image/svg+xml\\\" href=\\\"/favicon.svg\\\" />\\n\\t\\t\" + head + \"\\n\\t</head>\\n\\t<body data-sveltekit-preload-data=\\\"hover\\\">\\n\\t\\t<div style=\\\"display: contents\\\">\" + body + \"</div>\\n\\t</body>\\n</html>\\n\",\n\t\terror\n\t},\n\tversion_hash: \"1pkl9hv\"\n};\n\nexport async function get_hooks() {\n\tlet handle;\n\tlet handleFetch;\n\tlet handleError;\n\tlet handleValidationError;\n\tlet init;\n\t({ handle, handleFetch, handleError, handleValidationError, init } = await import(\"../../../src/hooks.server.ts\"));\n\n\tlet reroute;\n\tlet transport;\n\t\n\n\treturn {\n\t\thandle,\n\t\thandleFetch,\n\t\thandleError,\n\t\thandleValidationError,\n\t\tinit,\n\t\treroute,\n\t\ttransport\n\t};\n}\n\nexport { set_assets, set_building, set_manifest, set_prerendering, set_private_env, set_public_env, set_read_implementation };\n"],"names":[],"mappings":";;;;;;;;;AAAA,MAAA,QAAe,CAAC,EAAE,QAAQ,QAAO,MAAO,sFAA+F,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,4BAA+6C,SAAS,gDAAyD,UAAU;ACQhoD,MAAC,UAAU;AAAA,EACtB,6BAA6B;AAAA,EAC7B,OAAO;AAAA,EACP,KAAK,EAAC,QAAO,QAAO,cAAa,EAAC,6BAA4B,OAAM,2BAA0B,MAAK,GAAE,cAAa,EAAC,6BAA4B,OAAM,2BAA0B,MAAK,EAAC;AAAA,EACrL,mBAAmB;AAAA,EACnB,sBAAsB,CAAA;AAAA,EACtB,UAAU;AAAA,EACV,mBAAmB;AAAA,EACnB,oBAAoB;AAAA,EACpB,cAAc;AAAA,EACd,OAAO;AAAA;AAAA,EACP,kBAAkB;AAAA,EAClB;AAAA,EACA,gBAAgB;AAAA,EAChB,wBAAwB;AAAA,EACxB,yBAAyB;AAAA,EACzB,WAAW;AAAA,IACV,KAAK,CAAC,EAAE,MAAM,MAAM,QAAQ,OAAO,IAAG,MAAO,sxBAA21B,OAAO,+FAAuG,OAAO;AAAA,IAC7/B;AAAA,EACF;AAAA,EACC,cAAc;AACf;AAEO,eAAe,YAAY;AACjC,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,GAAC,EAAE,QAAQ,aAAa,aAAa,uBAAuB,KAAI,IAAK,MAAM,OAAO,4BAA8B;AAEhH,MAAI;AACJ,MAAI;AAGJ,SAAO;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA;"}
1
+ {"version":3,"file":"internal2.js","sources":["../../../generated/shared/error-template.js","../../../generated/server/internal.js"],"sourcesContent":["export default ({ status, message }) => \"<!doctype html>\\n<html lang=\\\"en\\\">\\n\\t<head>\\n\\t\\t<meta charset=\\\"utf-8\\\" />\\n\\t\\t<title>\" + message + \"</title>\\n\\n\\t\\t<style>\\n\\t\\t\\tbody {\\n\\t\\t\\t\\t--bg: white;\\n\\t\\t\\t\\t--fg: #222;\\n\\t\\t\\t\\t--divider: #ccc;\\n\\t\\t\\t\\tbackground: var(--bg);\\n\\t\\t\\t\\tcolor: var(--fg);\\n\\t\\t\\t\\tfont-family:\\n\\t\\t\\t\\t\\tsystem-ui,\\n\\t\\t\\t\\t\\t-apple-system,\\n\\t\\t\\t\\t\\tBlinkMacSystemFont,\\n\\t\\t\\t\\t\\t'Segoe UI',\\n\\t\\t\\t\\t\\tRoboto,\\n\\t\\t\\t\\t\\tOxygen,\\n\\t\\t\\t\\t\\tUbuntu,\\n\\t\\t\\t\\t\\tCantarell,\\n\\t\\t\\t\\t\\t'Open Sans',\\n\\t\\t\\t\\t\\t'Helvetica Neue',\\n\\t\\t\\t\\t\\tsans-serif;\\n\\t\\t\\t\\tdisplay: flex;\\n\\t\\t\\t\\talign-items: center;\\n\\t\\t\\t\\tjustify-content: center;\\n\\t\\t\\t\\theight: 100vh;\\n\\t\\t\\t\\tmargin: 0;\\n\\t\\t\\t}\\n\\n\\t\\t\\t.error {\\n\\t\\t\\t\\tdisplay: flex;\\n\\t\\t\\t\\talign-items: center;\\n\\t\\t\\t\\tmax-width: 32rem;\\n\\t\\t\\t\\tmargin: 0 1rem;\\n\\t\\t\\t}\\n\\n\\t\\t\\t.status {\\n\\t\\t\\t\\tfont-weight: 200;\\n\\t\\t\\t\\tfont-size: 3rem;\\n\\t\\t\\t\\tline-height: 1;\\n\\t\\t\\t\\tposition: relative;\\n\\t\\t\\t\\ttop: -0.05rem;\\n\\t\\t\\t}\\n\\n\\t\\t\\t.message {\\n\\t\\t\\t\\tborder-left: 1px solid var(--divider);\\n\\t\\t\\t\\tpadding: 0 0 0 1rem;\\n\\t\\t\\t\\tmargin: 0 0 0 1rem;\\n\\t\\t\\t\\tmin-height: 2.5rem;\\n\\t\\t\\t\\tdisplay: flex;\\n\\t\\t\\t\\talign-items: center;\\n\\t\\t\\t}\\n\\n\\t\\t\\t.message h1 {\\n\\t\\t\\t\\tfont-weight: 400;\\n\\t\\t\\t\\tfont-size: 1em;\\n\\t\\t\\t\\tmargin: 0;\\n\\t\\t\\t}\\n\\n\\t\\t\\t@media (prefers-color-scheme: dark) {\\n\\t\\t\\t\\tbody {\\n\\t\\t\\t\\t\\t--bg: #222;\\n\\t\\t\\t\\t\\t--fg: #ddd;\\n\\t\\t\\t\\t\\t--divider: #666;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t</style>\\n\\t</head>\\n\\t<body>\\n\\t\\t<div class=\\\"error\\\">\\n\\t\\t\\t<span class=\\\"status\\\">\" + status + \"</span>\\n\\t\\t\\t<div class=\\\"message\\\">\\n\\t\\t\\t\\t<h1>\" + message + \"</h1>\\n\\t\\t\\t</div>\\n\\t\\t</div>\\n\\t</body>\\n</html>\\n\";","\nimport root from '../root.js';\nimport { set_building, set_prerendering } from '$app/env/internal';\nimport { set_assets } from '$app/paths/internal/server';\nimport { set_manifest, set_read_implementation } from '__sveltekit/server';\nimport { set_private_env, set_public_env } from '../../../../node_modules/.bun/@sveltejs+kit@2.70.3+106f9c5330cbe027/node_modules/@sveltejs/kit/src/runtime/shared-server.js';\nimport error from '../shared/error-template.js';\n\nexport const options = {\n\tapp_template_contains_nonce: false,\n\tasync: false,\n\tcsp: {\"mode\":\"auto\",\"directives\":{\"upgrade-insecure-requests\":false,\"block-all-mixed-content\":false},\"reportOnly\":{\"upgrade-insecure-requests\":false,\"block-all-mixed-content\":false}},\n\tcsrf_check_origin: true,\n\tcsrf_trusted_origins: [],\n\tembedded: false,\n\tenv_public_prefix: 'PUBLIC_',\n\tenv_private_prefix: '',\n\thash_routing: false,\n\thooks: null, // added lazily, via `get_hooks`\n\tpreload_strategy: \"modulepreload\",\n\troot,\n\tservice_worker: true,\n\tservice_worker_options: undefined,\n\tserver_error_boundaries: false,\n\ttemplates: {\n\t\tapp: ({ head, body, assets, nonce, env }) => \"<!doctype html>\\n<html lang=\\\"en\\\" class=\\\"dark\\\">\\n\\t<head>\\n\\t\\t<meta charset=\\\"utf-8\\\" />\\n\\t\\t<meta name=\\\"viewport\\\" content=\\\"width=device-width, initial-scale=1, viewport-fit=cover\\\" />\\n\\t\\t<meta name=\\\"theme-color\\\" content=\\\"#111111\\\" />\\n\\t\\t<!-- PWA / iOS home-screen: open fullscreen (standalone) instead of inside the browser chrome -->\\n\\t\\t<link rel=\\\"manifest\\\" href=\\\"/manifest.webmanifest\\\" />\\n\\t\\t<meta name=\\\"mobile-web-app-capable\\\" content=\\\"yes\\\" />\\n\\t\\t<meta name=\\\"apple-mobile-web-app-capable\\\" content=\\\"yes\\\" />\\n\\t\\t<meta name=\\\"apple-mobile-web-app-status-bar-style\\\" content=\\\"black-translucent\\\" />\\n\\t\\t<meta name=\\\"apple-mobile-web-app-title\\\" content=\\\"claude-mux\\\" />\\n\\t\\t<link rel=\\\"apple-touch-icon\\\" href=\\\"/apple-touch-icon.png\\\" />\\n\\t\\t<link rel=\\\"icon\\\" type=\\\"image/svg+xml\\\" href=\\\"/favicon.svg\\\" />\\n\\t\\t\" + head + \"\\n\\t</head>\\n\\t<body data-sveltekit-preload-data=\\\"hover\\\">\\n\\t\\t<div style=\\\"display: contents\\\">\" + body + \"</div>\\n\\t</body>\\n</html>\\n\",\n\t\terror\n\t},\n\tversion_hash: \"1y4ccu3\"\n};\n\nexport async function get_hooks() {\n\tlet handle;\n\tlet handleFetch;\n\tlet handleError;\n\tlet handleValidationError;\n\tlet init;\n\t({ handle, handleFetch, handleError, handleValidationError, init } = await import(\"../../../src/hooks.server.ts\"));\n\n\tlet reroute;\n\tlet transport;\n\t\n\n\treturn {\n\t\thandle,\n\t\thandleFetch,\n\t\thandleError,\n\t\thandleValidationError,\n\t\tinit,\n\t\treroute,\n\t\ttransport\n\t};\n}\n\nexport { set_assets, set_building, set_manifest, set_prerendering, set_private_env, set_public_env, set_read_implementation };\n"],"names":[],"mappings":";;;;;;;;;AAAA,MAAA,QAAe,CAAC,EAAE,QAAQ,QAAO,MAAO,sFAA+F,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,4BAA+6C,SAAS,gDAAyD,UAAU;ACQhoD,MAAC,UAAU;AAAA,EACtB,6BAA6B;AAAA,EAC7B,OAAO;AAAA,EACP,KAAK,EAAC,QAAO,QAAO,cAAa,EAAC,6BAA4B,OAAM,2BAA0B,MAAK,GAAE,cAAa,EAAC,6BAA4B,OAAM,2BAA0B,MAAK,EAAC;AAAA,EACrL,mBAAmB;AAAA,EACnB,sBAAsB,CAAA;AAAA,EACtB,UAAU;AAAA,EACV,mBAAmB;AAAA,EACnB,oBAAoB;AAAA,EACpB,cAAc;AAAA,EACd,OAAO;AAAA;AAAA,EACP,kBAAkB;AAAA,EAClB;AAAA,EACA,gBAAgB;AAAA,EAChB,wBAAwB;AAAA,EACxB,yBAAyB;AAAA,EACzB,WAAW;AAAA,IACV,KAAK,CAAC,EAAE,MAAM,MAAM,QAAQ,OAAO,IAAG,MAAO,sxBAA21B,OAAO,+FAAuG,OAAO;AAAA,IAC7/B;AAAA,EACF;AAAA,EACC,cAAc;AACf;AAEO,eAAe,YAAY;AACjC,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,GAAC,EAAE,QAAQ,aAAa,aAAa,uBAAuB,KAAI,IAAK,MAAM,OAAO,4BAA8B;AAEhH,MAAI;AACJ,MAAI;AAGJ,SAAO;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA;"}
@@ -62,7 +62,20 @@ function isDictated(sessionId, text, ts) {
62
62
  if (!list || list.length === 0) return false;
63
63
  const normalized = normalize(text);
64
64
  if (!normalized) return false;
65
- return list.some((m) => m.text === normalized && Math.abs(ts - m.at) <= MATCH_WINDOW_MS);
65
+ const near = list.filter((m) => Math.abs(ts - m.at) <= MATCH_WINDOW_MS);
66
+ if (near.some((m) => m.text === normalized)) return true;
67
+ return isMadeOf(normalized, near.map((m) => m.text));
68
+ }
69
+ function isMadeOf(text, parts) {
70
+ if (parts.length < 2) return false;
71
+ const sorted = [...new Set(parts)].sort((a, b) => b.length - a.length);
72
+ const reach = (rest) => {
73
+ if (rest === "") return true;
74
+ return sorted.some(
75
+ (part) => rest.startsWith(part) && (rest.length === part.length || rest[part.length] === " ") && reach(rest.slice(part.length).trimStart())
76
+ );
77
+ };
78
+ return reach(text);
66
79
  }
67
80
  function promptOf(message) {
68
81
  return composePromptWithAttachments(message.text, message.attachments ?? []);