@recombine-ai/bosun 0.10.1 → 0.11.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -0
- package/bin/bosun.js +3 -44
- package/build/client/_app/immutable/assets/0.CH-WU4JN.css +1 -0
- package/build/client/_app/immutable/assets/0.CH-WU4JN.css.br +0 -0
- package/build/client/_app/immutable/assets/0.CH-WU4JN.css.gz +0 -0
- package/build/client/_app/immutable/assets/{10.BX46PfEJ.css → 10.DIVePEYf.css} +1 -1
- package/build/client/_app/immutable/assets/10.DIVePEYf.css.br +0 -0
- package/build/client/_app/immutable/assets/10.DIVePEYf.css.gz +0 -0
- package/build/client/_app/immutable/chunks/{Dp760K13.js → 07xNIa59.js} +2 -2
- package/build/client/_app/immutable/chunks/07xNIa59.js.br +0 -0
- package/build/client/_app/immutable/chunks/07xNIa59.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BDl2QuyN.js +1 -0
- package/build/client/_app/immutable/chunks/BDl2QuyN.js.br +0 -0
- package/build/client/_app/immutable/chunks/BDl2QuyN.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{CqxCTxvJ.js → BI42X8h_.js} +1 -1
- package/build/client/_app/immutable/chunks/BI42X8h_.js.br +0 -0
- package/build/client/_app/immutable/chunks/BI42X8h_.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BJTwdUYr.js +1 -0
- package/build/client/_app/immutable/chunks/BJTwdUYr.js.br +0 -0
- package/build/client/_app/immutable/chunks/BJTwdUYr.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BLu86SbA.js +1 -0
- package/build/client/_app/immutable/chunks/BLu86SbA.js.br +0 -0
- package/build/client/_app/immutable/chunks/BLu86SbA.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BNifnXkO.js +1 -0
- package/build/client/_app/immutable/chunks/BNifnXkO.js.br +2 -0
- package/build/client/_app/immutable/chunks/BNifnXkO.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{BM0jKynj.js → BPNEONy5.js} +1 -1
- package/build/client/_app/immutable/chunks/BPNEONy5.js.br +0 -0
- package/build/client/_app/immutable/chunks/BPNEONy5.js.gz +0 -0
- package/build/client/_app/immutable/chunks/B_K7D6rX.js +2 -0
- package/build/client/_app/immutable/chunks/B_K7D6rX.js.br +0 -0
- package/build/client/_app/immutable/chunks/B_K7D6rX.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Bj8jfBTi.js +1 -0
- package/build/client/_app/immutable/chunks/Bj8jfBTi.js.br +0 -0
- package/build/client/_app/immutable/chunks/Bj8jfBTi.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BoPSJr4b.js +1 -0
- package/build/client/_app/immutable/chunks/BoPSJr4b.js.br +0 -0
- package/build/client/_app/immutable/chunks/BoPSJr4b.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BsDZe4N6.js +1 -0
- package/build/client/_app/immutable/chunks/BsDZe4N6.js.br +0 -0
- package/build/client/_app/immutable/chunks/BsDZe4N6.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{CXo2BVs0.js → Buo-57fF.js} +1 -1
- package/build/client/_app/immutable/chunks/Buo-57fF.js.br +0 -0
- package/build/client/_app/immutable/chunks/Buo-57fF.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{C-whEtKd.js → C39ai1md.js} +1 -1
- package/build/client/_app/immutable/chunks/C39ai1md.js.br +0 -0
- package/build/client/_app/immutable/chunks/C39ai1md.js.gz +0 -0
- package/build/client/_app/immutable/chunks/C7he4XPB.js +1 -0
- package/build/client/_app/immutable/chunks/C7he4XPB.js.br +0 -0
- package/build/client/_app/immutable/chunks/C7he4XPB.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{DYhTBLDc.js → CAjPRvNs.js} +2 -2
- package/build/client/_app/immutable/chunks/CAjPRvNs.js.br +0 -0
- package/build/client/_app/immutable/chunks/CAjPRvNs.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CJYOmGlC.js +1 -0
- package/build/client/_app/immutable/chunks/CJYOmGlC.js.br +0 -0
- package/build/client/_app/immutable/chunks/CJYOmGlC.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{CNLU4B3p.js → CMQRtcOV.js} +1 -1
- package/build/client/_app/immutable/chunks/CMQRtcOV.js.br +0 -0
- package/build/client/_app/immutable/chunks/CMQRtcOV.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{HJHYLHDn.js → CPXdAKdv.js} +1 -1
- package/build/client/_app/immutable/chunks/CPXdAKdv.js.br +0 -0
- package/build/client/_app/immutable/chunks/CPXdAKdv.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CVlsAO8k.js +11 -0
- package/build/client/_app/immutable/chunks/CVlsAO8k.js.br +0 -0
- package/build/client/_app/immutable/chunks/CVlsAO8k.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{DNLcpWO_.js → CX0Ekq8t.js} +1 -1
- package/build/client/_app/immutable/chunks/CX0Ekq8t.js.br +0 -0
- package/build/client/_app/immutable/chunks/CX0Ekq8t.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Ca197UDq.js +1 -0
- package/build/client/_app/immutable/chunks/Ca197UDq.js.br +0 -0
- package/build/client/_app/immutable/chunks/Ca197UDq.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CaHl3dME.js +1 -0
- package/build/client/_app/immutable/chunks/CaHl3dME.js.br +0 -0
- package/build/client/_app/immutable/chunks/CaHl3dME.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Cql_e8Of.js +1 -0
- package/build/client/_app/immutable/chunks/Cql_e8Of.js.br +2 -0
- package/build/client/_app/immutable/chunks/Cql_e8Of.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{Dv8m1cTI.js → CxLomzuE.js} +1 -1
- package/build/client/_app/immutable/chunks/CxLomzuE.js.br +0 -0
- package/build/client/_app/immutable/chunks/{Dv8m1cTI.js.gz → CxLomzuE.js.gz} +0 -0
- package/build/client/_app/immutable/chunks/Cyai3SOj.js +1 -0
- package/build/client/_app/immutable/chunks/Cyai3SOj.js.br +0 -0
- package/build/client/_app/immutable/chunks/Cyai3SOj.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{DTXUDKH5.js → CyvQWZoe.js} +4 -4
- package/build/client/_app/immutable/chunks/CyvQWZoe.js.br +0 -0
- package/build/client/_app/immutable/chunks/CyvQWZoe.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CzXNWL4m.js +1 -0
- package/build/client/_app/immutable/chunks/CzXNWL4m.js.br +1 -0
- package/build/client/_app/immutable/chunks/CzXNWL4m.js.gz +0 -0
- package/build/client/_app/immutable/chunks/D-B5X35l.js +1 -0
- package/build/client/_app/immutable/chunks/D-B5X35l.js.br +0 -0
- package/build/client/_app/immutable/chunks/D-B5X35l.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DJriQKD9.js +2 -0
- package/build/client/_app/immutable/chunks/DJriQKD9.js.br +0 -0
- package/build/client/_app/immutable/chunks/DJriQKD9.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DXUXXCDA.js +1 -0
- package/build/client/_app/immutable/chunks/DXUXXCDA.js.br +0 -0
- package/build/client/_app/immutable/chunks/DXUXXCDA.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{CZLNSMhF.js → Dslf9OwW.js} +10 -10
- package/build/client/_app/immutable/chunks/Dslf9OwW.js.br +0 -0
- package/build/client/_app/immutable/chunks/Dslf9OwW.js.gz +0 -0
- package/build/client/_app/immutable/chunks/QpaC6J6s.js +1 -0
- package/build/client/_app/immutable/chunks/QpaC6J6s.js.br +0 -0
- package/build/client/_app/immutable/chunks/QpaC6J6s.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{HXxIsSOO.js → iAhzu4tv.js} +1 -1
- package/build/client/_app/immutable/chunks/iAhzu4tv.js.br +0 -0
- package/build/client/_app/immutable/chunks/iAhzu4tv.js.gz +0 -0
- package/build/client/_app/immutable/chunks/i_5fJYKS.js +3 -0
- package/build/client/_app/immutable/chunks/i_5fJYKS.js.br +0 -0
- package/build/client/_app/immutable/chunks/i_5fJYKS.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{CF66fWJN.js → nYD9wsyN.js} +1 -1
- package/build/client/_app/immutable/chunks/nYD9wsyN.js.br +0 -0
- package/build/client/_app/immutable/chunks/nYD9wsyN.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{BIpSIzUr.js → uLGP0py1.js} +1 -1
- package/build/client/_app/immutable/chunks/uLGP0py1.js.br +0 -0
- package/build/client/_app/immutable/chunks/uLGP0py1.js.gz +0 -0
- package/build/client/_app/immutable/entry/app.Cr7CMG-3.js +2 -0
- package/build/client/_app/immutable/entry/app.Cr7CMG-3.js.br +0 -0
- package/build/client/_app/immutable/entry/app.Cr7CMG-3.js.gz +0 -0
- package/build/client/_app/immutable/entry/start.CDNd0Bml.js +1 -0
- package/build/client/_app/immutable/entry/start.CDNd0Bml.js.br +2 -0
- package/build/client/_app/immutable/entry/start.CDNd0Bml.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{0.BCmKHiYo.js → 0.AyqKXI2h.js} +2 -2
- package/build/client/_app/immutable/nodes/0.AyqKXI2h.js.br +0 -0
- package/build/client/_app/immutable/nodes/0.AyqKXI2h.js.gz +0 -0
- package/build/client/_app/immutable/nodes/1.BRmfm-nN.js +1 -0
- package/build/client/_app/immutable/nodes/1.BRmfm-nN.js.br +0 -0
- package/build/client/_app/immutable/nodes/1.BRmfm-nN.js.gz +0 -0
- package/build/client/_app/immutable/nodes/10.D03jjkr4.js +7 -0
- package/build/client/_app/immutable/nodes/10.D03jjkr4.js.br +0 -0
- package/build/client/_app/immutable/nodes/10.D03jjkr4.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{15.Wmhj7gOy.js → 15.BFy4oAT6.js} +1 -1
- package/build/client/_app/immutable/nodes/15.BFy4oAT6.js.br +0 -0
- package/build/client/_app/immutable/nodes/15.BFy4oAT6.js.gz +0 -0
- package/build/client/_app/immutable/nodes/17.BOYU_WTT.js +3 -0
- package/build/client/_app/immutable/nodes/17.BOYU_WTT.js.br +0 -0
- package/build/client/_app/immutable/nodes/17.BOYU_WTT.js.gz +0 -0
- package/build/client/_app/immutable/nodes/18.Ddx80a4f.js +11 -0
- package/build/client/_app/immutable/nodes/18.Ddx80a4f.js.br +0 -0
- package/build/client/_app/immutable/nodes/18.Ddx80a4f.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{2.BdQ4KFOK.js → 2.CZEboQjo.js} +20 -20
- package/build/client/_app/immutable/nodes/2.CZEboQjo.js.br +0 -0
- package/build/client/_app/immutable/nodes/2.CZEboQjo.js.gz +0 -0
- package/build/client/_app/immutable/nodes/3.dAV7FviN.js +1 -0
- package/build/client/_app/immutable/nodes/3.dAV7FviN.js.br +0 -0
- package/build/client/_app/immutable/nodes/3.dAV7FviN.js.gz +0 -0
- package/build/client/_app/immutable/nodes/4.Cm_vMAEA.js +1 -0
- package/build/client/_app/immutable/nodes/4.Cm_vMAEA.js.br +0 -0
- package/build/client/_app/immutable/nodes/4.Cm_vMAEA.js.gz +0 -0
- package/build/client/_app/immutable/nodes/5.DPWuTlaI.js +1 -0
- package/build/client/_app/immutable/nodes/5.DPWuTlaI.js.br +0 -0
- package/build/client/_app/immutable/nodes/5.DPWuTlaI.js.gz +0 -0
- package/build/client/_app/immutable/nodes/6.DY-NLaRW.js +1 -0
- package/build/client/_app/immutable/nodes/6.DY-NLaRW.js.br +0 -0
- package/build/client/_app/immutable/nodes/6.DY-NLaRW.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{8.DWNYX1kH.js → 8.Chuqhf8W.js} +1 -1
- package/build/client/_app/immutable/nodes/8.Chuqhf8W.js.br +0 -0
- package/build/client/_app/immutable/nodes/8.Chuqhf8W.js.gz +0 -0
- package/build/client/_app/immutable/nodes/9.BOEM8f6B.js +2 -0
- package/build/client/_app/immutable/nodes/9.BOEM8f6B.js.br +0 -0
- package/build/client/_app/immutable/nodes/9.BOEM8f6B.js.gz +0 -0
- package/build/client/_app/version.json +1 -1
- package/build/client/_app/version.json.br +0 -0
- package/build/client/_app/version.json.gz +0 -0
- package/build/server/chunks/0-TQkJBtAu.js +9 -0
- package/build/server/chunks/0-TQkJBtAu.js.map +1 -0
- package/build/server/chunks/1-CKxKlw1l.js +9 -0
- package/build/server/chunks/{1-C1mGPV-S.js.map → 1-CKxKlw1l.js.map} +1 -1
- package/build/server/chunks/10-Bly5Nk7M.js +9 -0
- package/build/server/chunks/10-Bly5Nk7M.js.map +1 -0
- package/build/server/chunks/{15-CZBxPMAc.js → 15-BMEAVslz.js} +2 -2
- package/build/server/chunks/{15-CZBxPMAc.js.map → 15-BMEAVslz.js.map} +1 -1
- package/build/server/chunks/17-C8CYQOYP.js +9 -0
- package/build/server/chunks/17-C8CYQOYP.js.map +1 -0
- package/build/server/chunks/18-CtXVGBbS.js +9 -0
- package/build/server/chunks/18-CtXVGBbS.js.map +1 -0
- package/build/server/chunks/2-DvD0dAh0.js +9 -0
- package/build/server/chunks/2-DvD0dAh0.js.map +1 -0
- package/build/server/chunks/3-DBzpRDK8.js +9 -0
- package/build/server/chunks/3-DBzpRDK8.js.map +1 -0
- package/build/server/chunks/4-BUNytyC2.js +9 -0
- package/build/server/chunks/4-BUNytyC2.js.map +1 -0
- package/build/server/chunks/5-DNo8_tFS.js +9 -0
- package/build/server/chunks/{5-DblV-OAd.js.map → 5-DNo8_tFS.js.map} +1 -1
- package/build/server/chunks/6-DUMdIfbf.js +9 -0
- package/build/server/chunks/6-DUMdIfbf.js.map +1 -0
- package/build/server/chunks/8-DxTJ555u.js +9 -0
- package/build/server/chunks/8-DxTJ555u.js.map +1 -0
- package/build/server/chunks/9-B4-5k50d.js +9 -0
- package/build/server/chunks/9-B4-5k50d.js.map +1 -0
- package/build/server/chunks/{AgentSidebar-XdGj1sqT.js → AgentSidebar-DvIlda-E.js} +5 -6
- package/build/server/chunks/AgentSidebar-DvIlda-E.js.map +1 -0
- package/build/server/chunks/{Button-Dsy3QY7B.js → Button-BLigKkGG.js} +2 -2
- package/build/server/chunks/Button-BLigKkGG.js.map +1 -0
- package/build/server/chunks/{ChatStepTrace-1q74tVYO.js → ChatStepTrace-CqqIjRLU.js} +47 -11
- package/build/server/chunks/ChatStepTrace-CqqIjRLU.js.map +1 -0
- package/build/server/chunks/{Input-CHFlfduw.js → Input-OdQKNdS6.js} +1 -2
- package/build/server/chunks/Input-OdQKNdS6.js.map +1 -0
- package/build/server/chunks/MockGenerator-GEpXTgX0.js +117 -0
- package/build/server/chunks/MockGenerator-GEpXTgX0.js.map +1 -0
- package/build/server/chunks/Modal-DtVsRmmO.js.map +1 -1
- package/build/server/chunks/{_layout.svelte-DJ4kDgDL.js → _layout.svelte-B-CkD4a0.js} +14 -8
- package/build/server/chunks/_layout.svelte-B-CkD4a0.js.map +1 -0
- package/build/server/chunks/{_layout.svelte-B2lwUacy.js → _layout.svelte-BBFCF-xw.js} +8 -4
- package/build/server/chunks/_layout.svelte-BBFCF-xw.js.map +1 -0
- package/build/server/chunks/{_layout.svelte-C7JgNCIu.js → _layout.svelte-cPhmW5bZ.js} +3 -1
- package/build/server/chunks/_layout.svelte-cPhmW5bZ.js.map +1 -0
- package/build/server/chunks/{_page.svelte-FufhMKh4.js → _page.svelte-0J2xaeyC.js} +71 -16
- package/build/server/chunks/_page.svelte-0J2xaeyC.js.map +1 -0
- package/build/server/chunks/{_page.svelte-BpRksNEG.js → _page.svelte-BgoX8Y6N.js} +2 -2
- package/build/server/chunks/{_page.svelte-BpRksNEG.js.map → _page.svelte-BgoX8Y6N.js.map} +1 -1
- package/build/server/chunks/{_page.svelte-GaxktsuT.js → _page.svelte-C_S_qUgZ.js} +480 -72
- package/build/server/chunks/_page.svelte-C_S_qUgZ.js.map +1 -0
- package/build/server/chunks/{_page.svelte-DDpBtd3X.js → _page.svelte-CqGOvPRO.js} +3 -4
- package/build/server/chunks/_page.svelte-CqGOvPRO.js.map +1 -0
- package/build/server/chunks/{_page.svelte-CA3-vgl2.js → _page.svelte-Cxh9_vUl.js} +151 -100
- package/build/server/chunks/_page.svelte-Cxh9_vUl.js.map +1 -0
- package/build/server/chunks/_page.svelte-zOI_s_3J.js +2151 -0
- package/build/server/chunks/_page.svelte-zOI_s_3J.js.map +1 -0
- package/build/server/chunks/agents-context-rV2narXG.js.map +1 -1
- package/build/server/chunks/conversation-view-memory-BZguFlTt.js +20 -0
- package/build/server/chunks/conversation-view-memory-BZguFlTt.js.map +1 -0
- package/build/server/chunks/edit-workspace-context-B1nYQ5hD.js.map +1 -1
- package/build/server/chunks/index-CSpGrMM2.js.map +1 -1
- package/build/server/chunks/{client-DzvEkq51.js → source-selection-CcN1cgXc.js} +122 -117
- package/build/server/chunks/source-selection-CcN1cgXc.js.map +1 -0
- package/build/server/index.js +1 -1
- package/build/server/index.js.map +1 -1
- package/build/server/manifest.js +14 -14
- package/build/server/manifest.js.map +1 -1
- package/package.json +4 -4
- package/src/backend/lib/get-agent-factories.spec.ts +59 -0
- package/src/backend/lib/get-agent-factories.ts +31 -1
- package/src/backend/lib/voice-agent-lifecycle.test.ts +31 -0
- package/src/backend/lib/voice-agent-lifecycle.ts +16 -0
- package/src/backend/roleplay/agents.ts +189 -69
- package/src/backend/roleplay/message-dispatcher.ts +0 -7
- package/src/backend/roleplay/router.ts +14 -17
- package/src/backend/roleplay/trace-serialization.spec.ts +35 -0
- package/src/backend/roleplay/trace-serialization.ts +57 -0
- package/src/backend/roleplay/variants.ts +33 -49
- package/src/backend/tests/academy.ts +202 -100
- package/src/backend/tests/analyze.ts +0 -3
- package/src/backend/tests/data.spec.ts +139 -0
- package/src/backend/tests/data.ts +452 -68
- package/src/backend/tests/emulate-agents.ts +60 -44
- package/src/backend/tests/openai-prompt-cache.ts +68 -0
- package/src/backend/tests/promptfoo-runtime.spec.ts +41 -0
- package/src/backend/tests/promptfoo-runtime.ts +27 -0
- package/src/backend/tests/report-files.spec.ts +42 -0
- package/src/backend/tests/report-files.ts +101 -0
- package/src/backend/tests/router.ts +28 -2
- package/src/backend/tests/suite.ts +13 -4
- package/build/client/_app/immutable/assets/0.B4t3dozz.css +0 -1
- package/build/client/_app/immutable/assets/0.B4t3dozz.css.br +0 -0
- package/build/client/_app/immutable/assets/0.B4t3dozz.css.gz +0 -0
- package/build/client/_app/immutable/assets/10.BX46PfEJ.css.br +0 -0
- package/build/client/_app/immutable/assets/10.BX46PfEJ.css.gz +0 -0
- package/build/client/_app/immutable/chunks/7E8m6dwk.js +0 -1
- package/build/client/_app/immutable/chunks/7E8m6dwk.js.br +0 -0
- package/build/client/_app/immutable/chunks/7E8m6dwk.js.gz +0 -0
- package/build/client/_app/immutable/chunks/7qRqthsa.js +0 -1
- package/build/client/_app/immutable/chunks/7qRqthsa.js.br +0 -2
- package/build/client/_app/immutable/chunks/7qRqthsa.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Ajb1KYIn.js +0 -1
- package/build/client/_app/immutable/chunks/Ajb1KYIn.js.br +0 -0
- package/build/client/_app/immutable/chunks/Ajb1KYIn.js.gz +0 -0
- package/build/client/_app/immutable/chunks/B0iEglSe.js +0 -1
- package/build/client/_app/immutable/chunks/B0iEglSe.js.br +0 -0
- package/build/client/_app/immutable/chunks/B0iEglSe.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BIpSIzUr.js.br +0 -0
- package/build/client/_app/immutable/chunks/BIpSIzUr.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BM0jKynj.js.br +0 -0
- package/build/client/_app/immutable/chunks/BM0jKynj.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BTvePR6r.js +0 -1
- package/build/client/_app/immutable/chunks/BTvePR6r.js.br +0 -2
- package/build/client/_app/immutable/chunks/BTvePR6r.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Bcu62lFq.js +0 -1
- package/build/client/_app/immutable/chunks/Bcu62lFq.js.br +0 -0
- package/build/client/_app/immutable/chunks/Bcu62lFq.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BwtfALfL.js +0 -11
- package/build/client/_app/immutable/chunks/BwtfALfL.js.br +0 -0
- package/build/client/_app/immutable/chunks/BwtfALfL.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BxsDwlgp.js +0 -4
- package/build/client/_app/immutable/chunks/BxsDwlgp.js.br +0 -0
- package/build/client/_app/immutable/chunks/BxsDwlgp.js.gz +0 -0
- package/build/client/_app/immutable/chunks/C-whEtKd.js.br +0 -2
- package/build/client/_app/immutable/chunks/C-whEtKd.js.gz +0 -0
- package/build/client/_app/immutable/chunks/C1WqE8CP.js +0 -1
- package/build/client/_app/immutable/chunks/C1WqE8CP.js.br +0 -2
- package/build/client/_app/immutable/chunks/C1WqE8CP.js.gz +0 -0
- package/build/client/_app/immutable/chunks/C4D-JXnS.js +0 -1
- package/build/client/_app/immutable/chunks/C4D-JXnS.js.br +0 -0
- package/build/client/_app/immutable/chunks/C4D-JXnS.js.gz +0 -0
- package/build/client/_app/immutable/chunks/C4SnSfql.js +0 -1
- package/build/client/_app/immutable/chunks/C4SnSfql.js.br +0 -0
- package/build/client/_app/immutable/chunks/C4SnSfql.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CF66fWJN.js.br +0 -0
- package/build/client/_app/immutable/chunks/CF66fWJN.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CNLU4B3p.js.br +0 -0
- package/build/client/_app/immutable/chunks/CNLU4B3p.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CXo2BVs0.js.br +0 -0
- package/build/client/_app/immutable/chunks/CXo2BVs0.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CZLNSMhF.js.br +0 -0
- package/build/client/_app/immutable/chunks/CZLNSMhF.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CqO5tR2_.js +0 -1
- package/build/client/_app/immutable/chunks/CqO5tR2_.js.br +0 -0
- package/build/client/_app/immutable/chunks/CqO5tR2_.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CqxCTxvJ.js.br +0 -0
- package/build/client/_app/immutable/chunks/CqxCTxvJ.js.gz +0 -0
- package/build/client/_app/immutable/chunks/D-wf2QNc.js +0 -1
- package/build/client/_app/immutable/chunks/D-wf2QNc.js.br +0 -0
- package/build/client/_app/immutable/chunks/D-wf2QNc.js.gz +0 -0
- package/build/client/_app/immutable/chunks/D4obUD_s.js +0 -1
- package/build/client/_app/immutable/chunks/D4obUD_s.js.br +0 -0
- package/build/client/_app/immutable/chunks/D4obUD_s.js.gz +0 -0
- package/build/client/_app/immutable/chunks/D8e7SQh9.js +0 -1
- package/build/client/_app/immutable/chunks/D8e7SQh9.js.br +0 -0
- package/build/client/_app/immutable/chunks/D8e7SQh9.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DNLcpWO_.js.br +0 -0
- package/build/client/_app/immutable/chunks/DNLcpWO_.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DTXUDKH5.js.br +0 -0
- package/build/client/_app/immutable/chunks/DTXUDKH5.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DYhTBLDc.js.br +0 -0
- package/build/client/_app/immutable/chunks/DYhTBLDc.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DhBm2Vx9.js +0 -1
- package/build/client/_app/immutable/chunks/DhBm2Vx9.js.br +0 -0
- package/build/client/_app/immutable/chunks/DhBm2Vx9.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Dp760K13.js.br +0 -0
- package/build/client/_app/immutable/chunks/Dp760K13.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Dv0gjm25.js +0 -1
- package/build/client/_app/immutable/chunks/Dv0gjm25.js.br +0 -0
- package/build/client/_app/immutable/chunks/Dv0gjm25.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Dv8m1cTI.js.br +0 -0
- package/build/client/_app/immutable/chunks/HJHYLHDn.js.br +0 -0
- package/build/client/_app/immutable/chunks/HJHYLHDn.js.gz +0 -0
- package/build/client/_app/immutable/chunks/HXxIsSOO.js.br +0 -0
- package/build/client/_app/immutable/chunks/HXxIsSOO.js.gz +0 -0
- package/build/client/_app/immutable/chunks/_yZg6Sf-.js +0 -2
- package/build/client/_app/immutable/chunks/_yZg6Sf-.js.br +0 -0
- package/build/client/_app/immutable/chunks/_yZg6Sf-.js.gz +0 -0
- package/build/client/_app/immutable/chunks/xebNt8-Z.js +0 -1
- package/build/client/_app/immutable/chunks/xebNt8-Z.js.br +0 -0
- package/build/client/_app/immutable/chunks/xebNt8-Z.js.gz +0 -0
- package/build/client/_app/immutable/entry/app.C4wJtvtH.js +0 -2
- package/build/client/_app/immutable/entry/app.C4wJtvtH.js.br +0 -0
- package/build/client/_app/immutable/entry/app.C4wJtvtH.js.gz +0 -0
- package/build/client/_app/immutable/entry/start.BId2vqhS.js +0 -1
- package/build/client/_app/immutable/entry/start.BId2vqhS.js.br +0 -2
- package/build/client/_app/immutable/entry/start.BId2vqhS.js.gz +0 -0
- package/build/client/_app/immutable/nodes/0.BCmKHiYo.js.br +0 -0
- package/build/client/_app/immutable/nodes/0.BCmKHiYo.js.gz +0 -0
- package/build/client/_app/immutable/nodes/1.8skEZBEw.js +0 -1
- package/build/client/_app/immutable/nodes/1.8skEZBEw.js.br +0 -0
- package/build/client/_app/immutable/nodes/1.8skEZBEw.js.gz +0 -0
- package/build/client/_app/immutable/nodes/10.YgmBfSWN.js +0 -5
- package/build/client/_app/immutable/nodes/10.YgmBfSWN.js.br +0 -0
- package/build/client/_app/immutable/nodes/10.YgmBfSWN.js.gz +0 -0
- package/build/client/_app/immutable/nodes/15.Wmhj7gOy.js.br +0 -0
- package/build/client/_app/immutable/nodes/15.Wmhj7gOy.js.gz +0 -0
- package/build/client/_app/immutable/nodes/17.D8ydco6g.js +0 -3
- package/build/client/_app/immutable/nodes/17.D8ydco6g.js.br +0 -0
- package/build/client/_app/immutable/nodes/17.D8ydco6g.js.gz +0 -0
- package/build/client/_app/immutable/nodes/18.C67CqGm5.js +0 -11
- package/build/client/_app/immutable/nodes/18.C67CqGm5.js.br +0 -0
- package/build/client/_app/immutable/nodes/18.C67CqGm5.js.gz +0 -0
- package/build/client/_app/immutable/nodes/2.BdQ4KFOK.js.br +0 -0
- package/build/client/_app/immutable/nodes/2.BdQ4KFOK.js.gz +0 -0
- package/build/client/_app/immutable/nodes/3.nCmkz6kS.js +0 -1
- package/build/client/_app/immutable/nodes/3.nCmkz6kS.js.br +0 -0
- package/build/client/_app/immutable/nodes/3.nCmkz6kS.js.gz +0 -0
- package/build/client/_app/immutable/nodes/4.DAwO0_Am.js +0 -1
- package/build/client/_app/immutable/nodes/4.DAwO0_Am.js.br +0 -0
- package/build/client/_app/immutable/nodes/4.DAwO0_Am.js.gz +0 -0
- package/build/client/_app/immutable/nodes/5.C_SvvZjG.js +0 -1
- package/build/client/_app/immutable/nodes/5.C_SvvZjG.js.br +0 -0
- package/build/client/_app/immutable/nodes/5.C_SvvZjG.js.gz +0 -0
- package/build/client/_app/immutable/nodes/6.DfOe9lph.js +0 -1
- package/build/client/_app/immutable/nodes/6.DfOe9lph.js.br +0 -0
- package/build/client/_app/immutable/nodes/6.DfOe9lph.js.gz +0 -0
- package/build/client/_app/immutable/nodes/8.DWNYX1kH.js.br +0 -0
- package/build/client/_app/immutable/nodes/8.DWNYX1kH.js.gz +0 -0
- package/build/client/_app/immutable/nodes/9.D7SG4T7Z.js +0 -2
- package/build/client/_app/immutable/nodes/9.D7SG4T7Z.js.br +0 -0
- package/build/client/_app/immutable/nodes/9.D7SG4T7Z.js.gz +0 -0
- package/build/server/chunks/0-D5BNSI7t.js +0 -9
- package/build/server/chunks/0-D5BNSI7t.js.map +0 -1
- package/build/server/chunks/1-C1mGPV-S.js +0 -9
- package/build/server/chunks/10-BUo1e_HG.js +0 -9
- package/build/server/chunks/10-BUo1e_HG.js.map +0 -1
- package/build/server/chunks/17-iNFqG1My.js +0 -9
- package/build/server/chunks/17-iNFqG1My.js.map +0 -1
- package/build/server/chunks/18-u8T5X6fM.js +0 -9
- package/build/server/chunks/18-u8T5X6fM.js.map +0 -1
- package/build/server/chunks/2-tLlSByHA.js +0 -9
- package/build/server/chunks/2-tLlSByHA.js.map +0 -1
- package/build/server/chunks/3-D1KY9yVZ.js +0 -9
- package/build/server/chunks/3-D1KY9yVZ.js.map +0 -1
- package/build/server/chunks/4-7zu0cJha.js +0 -9
- package/build/server/chunks/4-7zu0cJha.js.map +0 -1
- package/build/server/chunks/5-DblV-OAd.js +0 -9
- package/build/server/chunks/6-BDC5budM.js +0 -9
- package/build/server/chunks/6-BDC5budM.js.map +0 -1
- package/build/server/chunks/8-DhmD-opq.js +0 -9
- package/build/server/chunks/8-DhmD-opq.js.map +0 -1
- package/build/server/chunks/9-BGj28GI6.js +0 -9
- package/build/server/chunks/9-BGj28GI6.js.map +0 -1
- package/build/server/chunks/AgentSidebar-XdGj1sqT.js.map +0 -1
- package/build/server/chunks/Button-Dsy3QY7B.js.map +0 -1
- package/build/server/chunks/ChatStepTrace-1q74tVYO.js.map +0 -1
- package/build/server/chunks/Input-CHFlfduw.js.map +0 -1
- package/build/server/chunks/_layout.svelte-B2lwUacy.js.map +0 -1
- package/build/server/chunks/_layout.svelte-C7JgNCIu.js.map +0 -1
- package/build/server/chunks/_layout.svelte-DJ4kDgDL.js.map +0 -1
- package/build/server/chunks/_page.svelte-Bl1WcAXy.js +0 -671
- package/build/server/chunks/_page.svelte-Bl1WcAXy.js.map +0 -1
- package/build/server/chunks/_page.svelte-CA3-vgl2.js.map +0 -1
- package/build/server/chunks/_page.svelte-DDpBtd3X.js.map +0 -1
- package/build/server/chunks/_page.svelte-FufhMKh4.js.map +0 -1
- package/build/server/chunks/_page.svelte-GaxktsuT.js.map +0 -1
- package/build/server/chunks/client-DzvEkq51.js.map +0 -1
- package/build/server/chunks/source-selection-eA--VEKo.js +0 -124
- package/build/server/chunks/source-selection-eA--VEKo.js.map +0 -1
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { j as escape_html, l as derived, n as ensure_array_like, q as attr_style, o as attr_class, az as clsx } from './index-CSpGrMM2.js';
|
|
2
2
|
import { o as onDestroy } from './index-server-DsYEXu5n.js';
|
|
3
3
|
import { p as page } from './index2-DO4B3D-P.js';
|
|
4
|
-
import { B as Button } from './Button-
|
|
5
|
-
import { g as getPersistedTelescopeSourceId } from './source-selection-
|
|
4
|
+
import { B as Button } from './Button-BLigKkGG.js';
|
|
5
|
+
import { g as getPersistedTelescopeSourceId, T as TelescopeClient } from './source-selection-CcN1cgXc.js';
|
|
6
6
|
import { b as buildResponseLatencySpans, f as findResponseLatencyUserTurn, R as RESPONSE_LATENCY_THRESHOLD_MS } from './latency--f3JYIRg.js';
|
|
7
|
+
import { g as getConversationViewMemory, c as conversationViewMemoryKey } from './conversation-view-memory-BZguFlTt.js';
|
|
7
8
|
import './state.svelte-DT7cgvTK.js';
|
|
8
9
|
import './root-CDJwhpIB.js';
|
|
9
10
|
import './events-BQ65tUJo.js';
|
|
@@ -23,6 +24,8 @@ function _page($$renderer, $$props) {
|
|
|
23
24
|
const SPEECH_BUBBLE_PLAYBACK_SPAN_MATCH_AFTER_MS = 2500;
|
|
24
25
|
const SPEECH_BUBBLE_AGENT_PLAYBACK_MATCH_WINDOW_MS = 3e4;
|
|
25
26
|
const RESPONSE_LATENCY_TRACE_MATCH_TOLERANCE_MS = 250;
|
|
27
|
+
const GUIDE_ROW_LABELS = /* @__PURE__ */ new Set(["VAD", "Playback"]);
|
|
28
|
+
const client = new TelescopeClient(fetch);
|
|
26
29
|
const BOSUN_COLORS = {
|
|
27
30
|
blue: "#569cd6",
|
|
28
31
|
green: "#93FF6D",
|
|
@@ -223,26 +226,65 @@ function _page($$renderer, $$props) {
|
|
|
223
226
|
}
|
|
224
227
|
];
|
|
225
228
|
const SPAN_RULE_BY_START = new Map(SPAN_RULES.map((rule) => [rule.startEventType, rule]));
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
229
|
+
function emptyRecordingResponse() {
|
|
230
|
+
return {
|
|
231
|
+
exists: false,
|
|
232
|
+
audioUrl: null,
|
|
233
|
+
fileName: null,
|
|
234
|
+
mimeType: null,
|
|
235
|
+
size: null,
|
|
236
|
+
uploadedAt: null,
|
|
237
|
+
alignmentOffsetMs: 0
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
const viewMemory = getConversationViewMemory();
|
|
241
|
+
const initialSourceId = getPersistedTelescopeSourceId() ?? "";
|
|
242
|
+
const initialConversationId = page.params.conversationId ?? "";
|
|
243
|
+
const initialMemoryKey = conversationViewMemoryKey(initialConversationId, initialSourceId);
|
|
244
|
+
const initialMemory = viewMemory.latency.get(initialMemoryKey);
|
|
245
|
+
client.setSourceId(initialSourceId || void 0);
|
|
246
|
+
let sourceId = initialSourceId;
|
|
247
|
+
let conversation = initialMemory?.conversation ?? null;
|
|
248
|
+
let traces = initialMemory?.traces ?? [];
|
|
249
|
+
let conversationTraces = initialMemory?.conversationTraces ?? [];
|
|
250
|
+
let dataLoaded = initialMemory?.dataLoaded ?? false;
|
|
251
|
+
let error = initialMemory?.error ?? null;
|
|
252
|
+
let recording = initialMemory?.recording ?? emptyRecordingResponse();
|
|
253
|
+
let recordingLoaded = initialMemory?.recordingLoaded ?? false;
|
|
254
|
+
let recordingError = initialMemory?.recordingError ?? null;
|
|
233
255
|
let uploadInFlight = false;
|
|
234
|
-
let
|
|
256
|
+
let waveform = initialMemory?.waveform ?? null;
|
|
257
|
+
let waveformError = initialMemory?.waveformError ?? null;
|
|
258
|
+
let playbackPositionMs = initialMemory?.playbackPositionMs ?? 0;
|
|
235
259
|
let playbackPlaying = false;
|
|
260
|
+
let playbackError = null;
|
|
261
|
+
let alignmentSaving = false;
|
|
262
|
+
let alignmentError = null;
|
|
263
|
+
let viewDirty = initialMemory?.viewDirty ?? false;
|
|
236
264
|
let viewportStartMs = null;
|
|
237
265
|
let viewportEndMs = null;
|
|
266
|
+
let scrollViewportEl = null;
|
|
238
267
|
let fileInputEl = null;
|
|
239
|
-
let humanSpeechBubbleReservedLevels = 1;
|
|
268
|
+
let humanSpeechBubbleReservedLevels = initialMemory?.humanSpeechBubbleReservedLevels ?? 1;
|
|
240
269
|
let copyLatencyState = "idle";
|
|
270
|
+
let loadKey = "";
|
|
271
|
+
let playbackFrame = 0;
|
|
272
|
+
let playbackAudioBuffer = initialMemory?.playbackAudioBuffer ?? null;
|
|
241
273
|
let playbackAudioContext = null;
|
|
242
274
|
let playbackSourceNode = null;
|
|
243
275
|
let playbackStartedAtMs = null;
|
|
244
276
|
let playbackStartedAtContextTime = null;
|
|
245
277
|
const conversationId = derived(() => page.params.conversationId);
|
|
278
|
+
function buildRecordingApiUrlFor(cid, nextSourceId) {
|
|
279
|
+
const params = new URLSearchParams();
|
|
280
|
+
if (nextSourceId) params.set("source", nextSourceId);
|
|
281
|
+
const search = params.toString();
|
|
282
|
+
return `/traces/api/latency/${encodeURIComponent(cid)}${search ? `?${search}` : ""}`;
|
|
283
|
+
}
|
|
284
|
+
const recordingApiUrl = derived(() => {
|
|
285
|
+
if (!conversationId()) return "";
|
|
286
|
+
return buildRecordingApiUrlFor(conversationId(), sourceId);
|
|
287
|
+
});
|
|
246
288
|
const timelineOriginMs = derived(() => {
|
|
247
289
|
let min = Number.POSITIVE_INFINITY;
|
|
248
290
|
for (const trace of traces) {
|
|
@@ -250,20 +292,31 @@ function _page($$renderer, $$props) {
|
|
|
250
292
|
min = Math.min(min, trace.atMs);
|
|
251
293
|
}
|
|
252
294
|
if (Number.isFinite(min)) return min;
|
|
295
|
+
if (typeof conversation?.createdAt === "number" && Number.isFinite(conversation.createdAt)) {
|
|
296
|
+
return conversation.createdAt;
|
|
297
|
+
}
|
|
253
298
|
return Number.isFinite(min) ? min : 0;
|
|
254
299
|
});
|
|
255
300
|
const callSegments = derived(() => buildCallLatencySegments(traces));
|
|
256
301
|
const latencyTraceCount = derived(() => traces.length);
|
|
257
|
-
const
|
|
258
|
-
const
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
302
|
+
const aiResponses = derived(() => buildAiResponses());
|
|
303
|
+
const playbackSpeechMatches = derived(() => buildPlaybackSpeechMatches(callSegments(), aiResponses()));
|
|
304
|
+
const timelineSegments = derived(() => {
|
|
305
|
+
const playbackSegments = callSegments().map((segment) => {
|
|
306
|
+
const speech = playbackSpeechMatches().bySegmentId.get(segment.id);
|
|
307
|
+
if (!speech || segment.row !== "Playback" || segment.durationMs <= 0) return segment;
|
|
308
|
+
return {
|
|
309
|
+
...segment,
|
|
310
|
+
speechText: speech.text,
|
|
311
|
+
speechFullText: speech.fullText,
|
|
312
|
+
speechTraceLabel: speech.traceLabel
|
|
313
|
+
};
|
|
314
|
+
});
|
|
315
|
+
return [
|
|
316
|
+
...playbackSegments,
|
|
317
|
+
...buildStandaloneWaitSegments(aiResponses(), playbackSpeechMatches().responseIds)
|
|
318
|
+
];
|
|
319
|
+
});
|
|
267
320
|
const timelineRows = derived(() => {
|
|
268
321
|
const grouped = /* @__PURE__ */ new Map();
|
|
269
322
|
for (const segment of timelineSegments()) {
|
|
@@ -285,7 +338,8 @@ function _page($$renderer, $$props) {
|
|
|
285
338
|
const waveformRowHeightPx = derived(() => waveformRowVisible() ? TIMELINE_ROW_GAP_PX + WAVEFORM_ROW_HEIGHT_PX : 0);
|
|
286
339
|
const guideLines = derived(() => buildGuideLines(timelineRows()));
|
|
287
340
|
const recordingStartMs = derived(() => {
|
|
288
|
-
return null;
|
|
341
|
+
if (!waveform) return null;
|
|
342
|
+
return timelineOriginMs() + recording.alignmentOffsetMs;
|
|
289
343
|
});
|
|
290
344
|
const timelinePlotHeightPx = derived(() => TIMELINE_RULER_HEIGHT_PX + timelineRowsHeightPx() + traceRowsToBubbleGapPx() + speechBubbleAreaHeightPx() + waveformRowHeightPx());
|
|
291
345
|
const playbackAbsoluteMs = derived(() => {
|
|
@@ -322,6 +376,10 @@ function _page($$renderer, $$props) {
|
|
|
322
376
|
min = Math.min(min, segment.start);
|
|
323
377
|
max = Math.max(max, segment.end);
|
|
324
378
|
}
|
|
379
|
+
if (waveform && recordingStartMs() != null) {
|
|
380
|
+
min = Math.min(min, recordingStartMs());
|
|
381
|
+
max = Math.max(max, recordingStartMs() + waveform.durationMs);
|
|
382
|
+
}
|
|
325
383
|
if (!Number.isFinite(min) || !Number.isFinite(max)) return null;
|
|
326
384
|
if (max <= min) max = min + 1;
|
|
327
385
|
return { min, max };
|
|
@@ -347,7 +405,39 @@ function _page($$renderer, $$props) {
|
|
|
347
405
|
if (viewportStartMs == null || viewportEndMs == null) return [];
|
|
348
406
|
return buildTicks(viewportStartMs, viewportEndMs, timelineOriginMs());
|
|
349
407
|
});
|
|
408
|
+
function saveViewMemory(key = loadKey) {
|
|
409
|
+
if (!key) return;
|
|
410
|
+
const previous = viewMemory.latency.get(key);
|
|
411
|
+
const memory = {
|
|
412
|
+
conversation,
|
|
413
|
+
traces,
|
|
414
|
+
conversationTraces,
|
|
415
|
+
dataLoaded,
|
|
416
|
+
error,
|
|
417
|
+
recording,
|
|
418
|
+
recordingLoaded,
|
|
419
|
+
recordingError,
|
|
420
|
+
waveform,
|
|
421
|
+
waveformError,
|
|
422
|
+
playbackAudioBuffer,
|
|
423
|
+
playbackPositionMs,
|
|
424
|
+
viewportStartMs,
|
|
425
|
+
viewportEndMs,
|
|
426
|
+
viewportOriginMs: timelineOriginMs(),
|
|
427
|
+
viewDirty,
|
|
428
|
+
humanSpeechBubbleReservedLevels,
|
|
429
|
+
scrollTop: previous?.scrollTop ?? scrollViewportEl?.scrollTop ?? 0,
|
|
430
|
+
scrollLeft: previous?.scrollLeft ?? scrollViewportEl?.scrollLeft ?? 0
|
|
431
|
+
};
|
|
432
|
+
viewMemory.latency.set(key, memory);
|
|
433
|
+
const cid = conversationId();
|
|
434
|
+
const currentSourceId = getPersistedTelescopeSourceId() ?? "";
|
|
435
|
+
if (cid && currentSourceId && key === conversationViewMemoryKey(cid, "")) {
|
|
436
|
+
viewMemory.latency.set(conversationViewMemoryKey(cid, currentSourceId), memory);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
350
439
|
onDestroy(() => {
|
|
440
|
+
saveViewMemory();
|
|
351
441
|
stopPlayback(false);
|
|
352
442
|
void closePlaybackAudioContext();
|
|
353
443
|
});
|
|
@@ -377,7 +467,7 @@ function _page($$renderer, $$props) {
|
|
|
377
467
|
return `#${clampByte(r + (target - r) * t).toString(16).padStart(2, "0")}${clampByte(g + (target - g) * t).toString(16).padStart(2, "0")}${clampByte(b + (target - b) * t).toString(16).padStart(2, "0")}`;
|
|
378
468
|
}
|
|
379
469
|
function fmtSignedMs(value) {
|
|
380
|
-
if (!Number.isFinite(value)) return "0 ms";
|
|
470
|
+
if (value == null || !Number.isFinite(value)) return "0 ms";
|
|
381
471
|
const rounded = Math.round(value);
|
|
382
472
|
if (rounded === 0) return "0 ms";
|
|
383
473
|
return `${rounded > 0 ? "+" : ""}${rounded} ms`;
|
|
@@ -677,21 +767,20 @@ function _page($$renderer, $$props) {
|
|
|
677
767
|
function isFinalSttLatencyTrace(trace) {
|
|
678
768
|
return trace.eventType === "stt.final" || trace.eventType === "stt.final_transcript";
|
|
679
769
|
}
|
|
680
|
-
function
|
|
770
|
+
function bubbleText(value) {
|
|
681
771
|
const text = normalizeNonEmptyString(value);
|
|
682
772
|
if (!text) return null;
|
|
683
|
-
|
|
684
|
-
return cleaned || null;
|
|
773
|
+
return text.replace(/\s+/g, " ").trim() || null;
|
|
685
774
|
}
|
|
686
775
|
function latencyTranscriptText(trace) {
|
|
687
776
|
const payload = latencyPayload(trace);
|
|
688
|
-
const text =
|
|
777
|
+
const text = bubbleText(payload.text) ?? bubbleText(payload.transcript) ?? bubbleText(payload.finalTranscript) ?? bubbleText(payload.final_transcript) ?? bubbleText(payload.message);
|
|
689
778
|
if (text) return text;
|
|
690
779
|
const alternatives = payload.alternatives;
|
|
691
780
|
if (Array.isArray(alternatives)) {
|
|
692
781
|
for (const alternative of alternatives) {
|
|
693
782
|
if (!alternative || typeof alternative !== "object") continue;
|
|
694
|
-
const alternativeText =
|
|
783
|
+
const alternativeText = bubbleText(alternative.text);
|
|
695
784
|
if (alternativeText) return alternativeText;
|
|
696
785
|
}
|
|
697
786
|
}
|
|
@@ -747,13 +836,11 @@ function _page($$renderer, $$props) {
|
|
|
747
836
|
if (candidates[0]) return candidates[0];
|
|
748
837
|
return playbackSegments.find((segment) => !usedSegmentIds.has(segment.id) && segment.start <= span.end + SPEECH_BUBBLE_PLAYBACK_SPAN_MATCH_AFTER_MS && segment.end >= span.end - SPEECH_BUBBLE_PLAYBACK_SPAN_MATCH_BEFORE_MS) ?? null;
|
|
749
838
|
}
|
|
750
|
-
function
|
|
751
|
-
const traceTime = ms(trace.createdAt);
|
|
752
|
-
if (traceTime == null) return null;
|
|
839
|
+
function findPlaybackSegmentForResponse(responseTime, playbackSegments, usedSegmentIds) {
|
|
753
840
|
const candidates = playbackSegments.filter((segment) => {
|
|
754
841
|
if (usedSegmentIds.has(segment.id)) return false;
|
|
755
|
-
return segment.end >=
|
|
756
|
-
}).sort((a, b) => segmentDistanceFromTime(a,
|
|
842
|
+
return segment.end >= responseTime - SPEECH_BUBBLE_AGENT_PLAYBACK_MATCH_WINDOW_MS && segment.start <= responseTime + SPEECH_BUBBLE_AGENT_PLAYBACK_MATCH_WINDOW_MS;
|
|
843
|
+
}).sort((a, b) => segmentDistanceFromTime(a, responseTime) - segmentDistanceFromTime(b, responseTime));
|
|
757
844
|
return candidates[0] ?? null;
|
|
758
845
|
}
|
|
759
846
|
function callStartTime() {
|
|
@@ -768,6 +855,85 @@ function _page($$renderer, $$props) {
|
|
|
768
855
|
if (lastPlayback.end <= anchorTime) return Math.min(lastPlayback.end, anchorTime);
|
|
769
856
|
return Math.min(lastPlayback.start, anchorTime);
|
|
770
857
|
}
|
|
858
|
+
function isTagOnlyResponse(value) {
|
|
859
|
+
return value.replace(/<[^>]+>/g, "").trim() === "";
|
|
860
|
+
}
|
|
861
|
+
function isWaitResponse(value) {
|
|
862
|
+
return /<WAIT\b[^>]*\/?\s*>/i.test(value);
|
|
863
|
+
}
|
|
864
|
+
function isMainStepResponse(trace) {
|
|
865
|
+
return trace.traceType === "STEP" && trace.name === "main" && normalizeNonEmptyString(trace.response) != null;
|
|
866
|
+
}
|
|
867
|
+
function responseTextWithoutTags(value) {
|
|
868
|
+
return value.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
|
|
869
|
+
}
|
|
870
|
+
function isEquivalentAiResponseText(a, b) {
|
|
871
|
+
if (a === b) return true;
|
|
872
|
+
const spokenA = responseTextWithoutTags(a);
|
|
873
|
+
const spokenB = responseTextWithoutTags(b);
|
|
874
|
+
return spokenA !== "" && spokenA === spokenB;
|
|
875
|
+
}
|
|
876
|
+
function responseTurnBounds(createdAt) {
|
|
877
|
+
let start = createdAt - SPEECH_BUBBLE_AGENT_PLAYBACK_MATCH_WINDOW_MS;
|
|
878
|
+
let end = createdAt + SPEECH_BUBBLE_AGENT_PLAYBACK_MATCH_WINDOW_MS;
|
|
879
|
+
for (const trace of conversationTraces) {
|
|
880
|
+
if (!isUserConversationalTrace(trace)) continue;
|
|
881
|
+
if (trace.createdAt <= createdAt) start = trace.createdAt;
|
|
882
|
+
else {
|
|
883
|
+
end = trace.createdAt;
|
|
884
|
+
break;
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
return { start, end };
|
|
888
|
+
}
|
|
889
|
+
function findStepResponseForAgentTrace(agentTrace, stepResponses, usedStepTraceIds) {
|
|
890
|
+
const bounds = responseTurnBounds(agentTrace.createdAt);
|
|
891
|
+
return stepResponses.filter((trace) => !usedStepTraceIds.has(traceKey(trace)) && trace.createdAt >= bounds.start && trace.createdAt < bounds.end).sort((a, b) => Math.abs(a.createdAt - agentTrace.createdAt) - Math.abs(b.createdAt - agentTrace.createdAt))[0] ?? null;
|
|
892
|
+
}
|
|
893
|
+
function buildAiResponses() {
|
|
894
|
+
const built = [];
|
|
895
|
+
const usedStepTraceIds = /* @__PURE__ */ new Set();
|
|
896
|
+
const stepResponses = conversationTraces.filter(isMainStepResponse).sort(compareConversationTraces);
|
|
897
|
+
const agentTraces = conversationTraces.filter(isAgentConversationalTrace).sort(compareConversationTraces);
|
|
898
|
+
for (const agentTrace of agentTraces) {
|
|
899
|
+
const stepTrace = findStepResponseForAgentTrace(agentTrace, stepResponses, usedStepTraceIds);
|
|
900
|
+
const stepFullText = stepTrace ? normalizeNonEmptyString(stepTrace.response) : null;
|
|
901
|
+
const fullText = stepFullText ?? normalizeNonEmptyString(agentTrace.content);
|
|
902
|
+
const text = bubbleText(fullText);
|
|
903
|
+
if (!text || !fullText) continue;
|
|
904
|
+
const duplicate = built.find((response) => response.agentTraceIds.size > 0 && Math.abs(response.createdAt - agentTrace.createdAt) <= 1e3 && isEquivalentAiResponseText(response.fullText, fullText));
|
|
905
|
+
if (duplicate) {
|
|
906
|
+
duplicate.agentTraceIds.add(conversationalTraceKey(agentTrace));
|
|
907
|
+
if (stepTrace) usedStepTraceIds.add(traceKey(stepTrace));
|
|
908
|
+
continue;
|
|
909
|
+
}
|
|
910
|
+
if (stepTrace) usedStepTraceIds.add(traceKey(stepTrace));
|
|
911
|
+
built.push({
|
|
912
|
+
id: stepTrace ? `response:step:${traceKey(stepTrace)}` : `response:agent:${conversationalTraceKey(agentTrace)}`,
|
|
913
|
+
text,
|
|
914
|
+
fullText,
|
|
915
|
+
createdAt: agentTrace.createdAt,
|
|
916
|
+
agentTraceIds: /* @__PURE__ */ new Set([conversationalTraceKey(agentTrace)]),
|
|
917
|
+
traceLabel: describeTrace(stepTrace ?? agentTrace)
|
|
918
|
+
});
|
|
919
|
+
}
|
|
920
|
+
for (const stepTrace of stepResponses) {
|
|
921
|
+
const stepTraceId = traceKey(stepTrace);
|
|
922
|
+
if (usedStepTraceIds.has(stepTraceId)) continue;
|
|
923
|
+
const fullText = normalizeNonEmptyString(stepTrace.response);
|
|
924
|
+
const text = bubbleText(fullText);
|
|
925
|
+
if (!text || !fullText) continue;
|
|
926
|
+
built.push({
|
|
927
|
+
id: `response:step:${stepTraceId}`,
|
|
928
|
+
text,
|
|
929
|
+
fullText,
|
|
930
|
+
createdAt: stepTrace.createdAt,
|
|
931
|
+
agentTraceIds: /* @__PURE__ */ new Set(),
|
|
932
|
+
traceLabel: describeTrace(stepTrace)
|
|
933
|
+
});
|
|
934
|
+
}
|
|
935
|
+
return built.sort((a, b) => a.createdAt - b.createdAt || a.id.localeCompare(b.id));
|
|
936
|
+
}
|
|
771
937
|
function traceKey(trace) {
|
|
772
938
|
return normalizeNonEmptyString(trace.traceId) ?? `${trace.seq ?? "?"}:${trace.createdAt ?? "?"}`;
|
|
773
939
|
}
|
|
@@ -776,7 +942,7 @@ function _page($$renderer, $$props) {
|
|
|
776
942
|
if (trace.eventType !== "tts.text.first_sent" && trace.eventType !== "tts.text.completed") {
|
|
777
943
|
return [];
|
|
778
944
|
}
|
|
779
|
-
const text =
|
|
945
|
+
const text = bubbleText(latencyText(trace));
|
|
780
946
|
return text ? [{ trace, text }] : [];
|
|
781
947
|
});
|
|
782
948
|
}
|
|
@@ -789,11 +955,11 @@ function _page($$renderer, $$props) {
|
|
|
789
955
|
}).sort((a, b) => Math.abs(a.trace.atMs - playbackSegment.start) - Math.abs(b.trace.atMs - playbackSegment.start));
|
|
790
956
|
return candidates[0] ?? null;
|
|
791
957
|
}
|
|
792
|
-
function
|
|
793
|
-
const
|
|
958
|
+
function buildPlaybackSpeechMatches(inputSegments, responses) {
|
|
959
|
+
const bySegmentId = /* @__PURE__ */ new Map();
|
|
794
960
|
const playbackSegments = inputSegments.filter((segment) => segment.row === "Playback" && segment.durationMs > 0).sort((a, b) => a.start - b.start || a.end - b.end);
|
|
795
|
-
const
|
|
796
|
-
const
|
|
961
|
+
const usedAgentPlaybackSegmentIds = /* @__PURE__ */ new Set();
|
|
962
|
+
const usedResponseIds = /* @__PURE__ */ new Set();
|
|
797
963
|
const usedTtsTextTraceIds = /* @__PURE__ */ new Set();
|
|
798
964
|
const ttsTextEvents = buildTtsTextEvents();
|
|
799
965
|
let previousPlaybackEnd = callStartTime();
|
|
@@ -801,35 +967,71 @@ function _page($$renderer, $$props) {
|
|
|
801
967
|
const ttsText = findTtsTextForPlayback(playbackSegment, ttsTextEvents, usedTtsTextTraceIds, previousPlaybackEnd);
|
|
802
968
|
previousPlaybackEnd = Math.max(previousPlaybackEnd, playbackSegment.end);
|
|
803
969
|
if (!ttsText) continue;
|
|
804
|
-
usedPlaybackSegmentIds.add(playbackSegment.id);
|
|
805
970
|
usedTtsTextTraceIds.add(traceKey(ttsText.trace));
|
|
806
|
-
|
|
971
|
+
bySegmentId.set(playbackSegment.id, {
|
|
972
|
+
text: ttsText.text,
|
|
973
|
+
fullText: ttsText.text,
|
|
974
|
+
traceLabel: describeTrace(ttsText.trace)
|
|
975
|
+
});
|
|
807
976
|
}
|
|
808
977
|
for (const span of buildResponseLatencySpans(traces)) {
|
|
809
978
|
if (findResponseLatencyUserTurn(conversationTraces, span) == null) continue;
|
|
810
979
|
const agentTrace = findResponseLatencyAgentTrace(conversationTraces, span);
|
|
811
980
|
if (!agentTrace) continue;
|
|
812
|
-
const
|
|
813
|
-
if (!
|
|
814
|
-
|
|
981
|
+
const response = responses.find((candidate) => candidate.agentTraceIds.has(conversationalTraceKey(agentTrace)));
|
|
982
|
+
if (!response) continue;
|
|
983
|
+
if (usedResponseIds.has(response.id)) continue;
|
|
984
|
+
if (isTagOnlyResponse(response.fullText)) continue;
|
|
985
|
+
const playbackSegment = findPlaybackSegmentForSpan(span, playbackSegments, usedAgentPlaybackSegmentIds);
|
|
815
986
|
if (!playbackSegment) continue;
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
987
|
+
usedAgentPlaybackSegmentIds.add(playbackSegment.id);
|
|
988
|
+
usedResponseIds.add(response.id);
|
|
989
|
+
bySegmentId.set(playbackSegment.id, {
|
|
990
|
+
text: response.text,
|
|
991
|
+
fullText: response.fullText,
|
|
992
|
+
traceLabel: response.traceLabel
|
|
993
|
+
});
|
|
819
994
|
}
|
|
820
|
-
const
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
const text = cleanBubbleText(agentTrace.content);
|
|
825
|
-
if (!text) continue;
|
|
826
|
-
const playbackSegment = findPlaybackSegmentForAgentTrace(agentTrace, playbackSegments, usedPlaybackSegmentIds);
|
|
995
|
+
for (const response of responses) {
|
|
996
|
+
if (usedResponseIds.has(response.id)) continue;
|
|
997
|
+
if (isTagOnlyResponse(response.fullText)) continue;
|
|
998
|
+
const playbackSegment = findPlaybackSegmentForResponse(response.createdAt, playbackSegments, usedAgentPlaybackSegmentIds);
|
|
827
999
|
if (!playbackSegment) continue;
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
1000
|
+
usedAgentPlaybackSegmentIds.add(playbackSegment.id);
|
|
1001
|
+
usedResponseIds.add(response.id);
|
|
1002
|
+
bySegmentId.set(playbackSegment.id, {
|
|
1003
|
+
text: response.text,
|
|
1004
|
+
fullText: response.fullText,
|
|
1005
|
+
traceLabel: response.traceLabel
|
|
1006
|
+
});
|
|
831
1007
|
}
|
|
832
|
-
return
|
|
1008
|
+
return { bySegmentId, responseIds: usedResponseIds };
|
|
1009
|
+
}
|
|
1010
|
+
function buildStandaloneWaitSegments(responses, usedResponseIds) {
|
|
1011
|
+
return responses.flatMap((response) => {
|
|
1012
|
+
if (usedResponseIds.has(response.id) || !isWaitResponse(response.fullText)) return [];
|
|
1013
|
+
const end = findWaitResponseEnd(response.createdAt);
|
|
1014
|
+
return [
|
|
1015
|
+
{
|
|
1016
|
+
...makeSegment({
|
|
1017
|
+
id: `playback:wait:${response.id}`,
|
|
1018
|
+
row: "Playback",
|
|
1019
|
+
start: response.createdAt,
|
|
1020
|
+
end,
|
|
1021
|
+
colorKey: "playback",
|
|
1022
|
+
label: "WAIT response",
|
|
1023
|
+
traceLabel: response.traceLabel
|
|
1024
|
+
}),
|
|
1025
|
+
speechText: response.text,
|
|
1026
|
+
speechFullText: response.fullText,
|
|
1027
|
+
speechTraceLabel: response.traceLabel
|
|
1028
|
+
}
|
|
1029
|
+
];
|
|
1030
|
+
});
|
|
1031
|
+
}
|
|
1032
|
+
function findWaitResponseEnd(start) {
|
|
1033
|
+
const nextActivity = traces.filter((trace) => trace.atMs > start && (trace.eventType === "audio.playback.started" || trace.eventType === "stt.started" || trace.eventType === "vad.activated" || trace.eventType === "call.ended")).sort((a, b) => a.atMs - b.atMs || a.seq - b.seq)[0];
|
|
1034
|
+
return nextActivity ? nextActivity.atMs : start + 1;
|
|
833
1035
|
}
|
|
834
1036
|
function buildSpeechBubbleCandidates() {
|
|
835
1037
|
const built = [];
|
|
@@ -862,10 +1064,10 @@ function _page($$renderer, $$props) {
|
|
|
862
1064
|
if (bubble.role !== role) continue;
|
|
863
1065
|
maxLevel = Math.max(maxLevel, bubble.level);
|
|
864
1066
|
}
|
|
865
|
-
return
|
|
1067
|
+
return maxLevel + 1;
|
|
866
1068
|
}
|
|
867
1069
|
function speechBubbleLaneHeightPx(levelCount) {
|
|
868
|
-
return Math.max(
|
|
1070
|
+
return Math.max(0, levelCount) * SPEECH_BUBBLE_LEVEL_HEIGHT_PX;
|
|
869
1071
|
}
|
|
870
1072
|
function compactSpeechBubbleLayouts(bubbles) {
|
|
871
1073
|
const bubbleAreaTopPx = speechBubbleAreaTopPx();
|
|
@@ -914,6 +1116,7 @@ function _page($$renderer, $$props) {
|
|
|
914
1116
|
explain: input.explain ?? null,
|
|
915
1117
|
text: input.text ?? null,
|
|
916
1118
|
speechText: null,
|
|
1119
|
+
speechFullText: null,
|
|
917
1120
|
speechTraceLabel: null,
|
|
918
1121
|
traceLabel: input.traceLabel,
|
|
919
1122
|
eventMarker: input.eventMarker ?? null
|
|
@@ -981,6 +1184,41 @@ function _page($$renderer, $$props) {
|
|
|
981
1184
|
const derivedSegments = buildDerivedSegments(events);
|
|
982
1185
|
return [...derivedSegments, ...pointSegments].sort((a, b) => a.start - b.start || (a.durationMs === 0 ? 1 : 0) - (b.durationMs === 0 ? 1 : 0) || a.end - b.end || a.row.localeCompare(b.row));
|
|
983
1186
|
}
|
|
1187
|
+
function buildRecordingResponse(raw) {
|
|
1188
|
+
const next = raw && typeof raw === "object" ? raw : {};
|
|
1189
|
+
const audioUrl = typeof next.audioUrl === "string" && next.audioUrl.trim() ? next.audioUrl : null;
|
|
1190
|
+
return {
|
|
1191
|
+
exists: next.exists === true && audioUrl != null,
|
|
1192
|
+
audioUrl,
|
|
1193
|
+
fileName: typeof next.fileName === "string" ? next.fileName : null,
|
|
1194
|
+
mimeType: typeof next.mimeType === "string" ? next.mimeType : null,
|
|
1195
|
+
size: typeof next.size === "number" && Number.isFinite(next.size) ? next.size : null,
|
|
1196
|
+
uploadedAt: typeof next.uploadedAt === "string" ? next.uploadedAt : null,
|
|
1197
|
+
alignmentOffsetMs: typeof next.alignmentOffsetMs === "number" && Number.isFinite(next.alignmentOffsetMs) ? next.alignmentOffsetMs : 0
|
|
1198
|
+
};
|
|
1199
|
+
}
|
|
1200
|
+
function getResponseError(payload, fallback) {
|
|
1201
|
+
const next = payload && typeof payload === "object" ? payload : {};
|
|
1202
|
+
if (typeof next.error === "string" && next.error.trim()) return next.error;
|
|
1203
|
+
if (typeof next.message === "string" && next.message.trim()) return next.message;
|
|
1204
|
+
return fallback;
|
|
1205
|
+
}
|
|
1206
|
+
async function readResponsePayload(response) {
|
|
1207
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
1208
|
+
if (contentType.includes("application/json")) {
|
|
1209
|
+
return response.json().catch(() => ({}));
|
|
1210
|
+
}
|
|
1211
|
+
const text = (await response.text().catch(() => "")).trim();
|
|
1212
|
+
if (!text) return {};
|
|
1213
|
+
if (contentType.includes("text/html")) {
|
|
1214
|
+
const titleMatch = text.match(/<title>([^<]+)<\/title>/i);
|
|
1215
|
+
const headingMatch = text.match(/<h1[^>]*>([^<]+)<\/h1>/i);
|
|
1216
|
+
return {
|
|
1217
|
+
message: titleMatch?.[1]?.trim() || headingMatch?.[1]?.trim() || `${response.status} ${response.statusText}`.trim()
|
|
1218
|
+
};
|
|
1219
|
+
}
|
|
1220
|
+
return { message: text };
|
|
1221
|
+
}
|
|
984
1222
|
function isPlaybackTraceBubble(segment) {
|
|
985
1223
|
return segment.row === "Playback" && !segment.eventMarker && segment.durationMs > 0;
|
|
986
1224
|
}
|
|
@@ -1037,7 +1275,44 @@ function _page($$renderer, $$props) {
|
|
|
1037
1275
|
return `${base} -translate-x-1/2`;
|
|
1038
1276
|
}
|
|
1039
1277
|
function buildGuideLines(rows) {
|
|
1040
|
-
return [];
|
|
1278
|
+
if (!recording.exists || viewportStartMs == null || viewportEndMs == null) return [];
|
|
1279
|
+
const rangeStartMs = viewportStartMs;
|
|
1280
|
+
const rangeEndMs = viewportEndMs;
|
|
1281
|
+
const durationMs = rangeEndMs - rangeStartMs;
|
|
1282
|
+
if (!Number.isFinite(durationMs) || durationMs <= 0) return [];
|
|
1283
|
+
const waveformBottomPx = timelinePlotHeightPx();
|
|
1284
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1285
|
+
const built = [];
|
|
1286
|
+
rows.forEach((row, rowIndex) => {
|
|
1287
|
+
if (!GUIDE_ROW_LABELS.has(row.label)) return;
|
|
1288
|
+
const rowTopPx = TIMELINE_RULER_HEIGHT_PX + rowIndex * (TIMELINE_ROW_HEIGHT_PX + TIMELINE_ROW_GAP_PX);
|
|
1289
|
+
const rowAnchorPx = rowTopPx + Math.round(TIMELINE_ROW_HEIGHT_PX / 2);
|
|
1290
|
+
row.segments.forEach((segment) => {
|
|
1291
|
+
if (segment.id.startsWith("playback:wait:")) return;
|
|
1292
|
+
const color = tintHex(COLOR_BY_KEY[segment.colorKey] ?? BOSUN_COLORS.gray, 0.15);
|
|
1293
|
+
const times = segment.end === segment.start ? segment.start >= rangeStartMs && segment.start <= rangeEndMs ? [segment.start] : [] : (() => {
|
|
1294
|
+
const visibleStart = Math.max(segment.start, rangeStartMs);
|
|
1295
|
+
const visibleEnd = Math.min(segment.end, rangeEndMs);
|
|
1296
|
+
return visibleEnd < visibleStart ? [] : [visibleStart, visibleEnd];
|
|
1297
|
+
})();
|
|
1298
|
+
for (const timeMs of times) {
|
|
1299
|
+
const roundedTime = Math.round(timeMs);
|
|
1300
|
+
const key = `${row.label}:${roundedTime}`;
|
|
1301
|
+
if (seen.has(key)) continue;
|
|
1302
|
+
seen.add(key);
|
|
1303
|
+
const leftPercent = clamp((timeMs - rangeStartMs) / durationMs * 100, 0, 100);
|
|
1304
|
+
built.push({
|
|
1305
|
+
id: `${segment.id}:${roundedTime}`,
|
|
1306
|
+
leftPercent,
|
|
1307
|
+
topPx: rowAnchorPx,
|
|
1308
|
+
heightPx: Math.max(1, waveformBottomPx - rowAnchorPx),
|
|
1309
|
+
color,
|
|
1310
|
+
opacity: row.label === "VAD" ? 0.62 : 0.48
|
|
1311
|
+
});
|
|
1312
|
+
}
|
|
1313
|
+
});
|
|
1314
|
+
});
|
|
1315
|
+
return built;
|
|
1041
1316
|
}
|
|
1042
1317
|
function chooseTickStep(durationMs) {
|
|
1043
1318
|
const approx = durationMs / 7;
|
|
@@ -1064,6 +1339,18 @@ function _page($$renderer, $$props) {
|
|
|
1064
1339
|
}
|
|
1065
1340
|
return ticks;
|
|
1066
1341
|
}
|
|
1342
|
+
function createAudioContext() {
|
|
1343
|
+
const next = window.AudioContext ?? window.webkitAudioContext;
|
|
1344
|
+
if (!next) {
|
|
1345
|
+
throw new Error("Web Audio is not available in this browser");
|
|
1346
|
+
}
|
|
1347
|
+
return new next();
|
|
1348
|
+
}
|
|
1349
|
+
function stopPlaybackTicker() {
|
|
1350
|
+
if (!playbackFrame) return;
|
|
1351
|
+
window.cancelAnimationFrame(playbackFrame);
|
|
1352
|
+
playbackFrame = 0;
|
|
1353
|
+
}
|
|
1067
1354
|
async function closePlaybackAudioContext() {
|
|
1068
1355
|
const context = playbackAudioContext;
|
|
1069
1356
|
playbackAudioContext = null;
|
|
@@ -1071,6 +1358,15 @@ function _page($$renderer, $$props) {
|
|
|
1071
1358
|
await context.close().catch(() => {
|
|
1072
1359
|
});
|
|
1073
1360
|
}
|
|
1361
|
+
async function ensurePlaybackAudioContext() {
|
|
1362
|
+
if (!playbackAudioContext || playbackAudioContext.state === "closed") {
|
|
1363
|
+
playbackAudioContext = createAudioContext();
|
|
1364
|
+
}
|
|
1365
|
+
if (playbackAudioContext.state === "suspended") {
|
|
1366
|
+
await playbackAudioContext.resume();
|
|
1367
|
+
}
|
|
1368
|
+
return playbackAudioContext;
|
|
1369
|
+
}
|
|
1074
1370
|
function getPlaybackPositionMs() {
|
|
1075
1371
|
const durationMs = getRecordingDurationMs();
|
|
1076
1372
|
if (playbackPlaying && playbackAudioContext && playbackStartedAtMs != null && playbackStartedAtContextTime != null) {
|
|
@@ -1089,6 +1385,7 @@ function _page($$renderer, $$props) {
|
|
|
1089
1385
|
playbackStartedAtMs = null;
|
|
1090
1386
|
playbackStartedAtContextTime = null;
|
|
1091
1387
|
playbackPlaying = false;
|
|
1388
|
+
stopPlaybackTicker();
|
|
1092
1389
|
if (!source) return;
|
|
1093
1390
|
source.onended = null;
|
|
1094
1391
|
try {
|
|
@@ -1097,11 +1394,72 @@ function _page($$renderer, $$props) {
|
|
|
1097
1394
|
}
|
|
1098
1395
|
source.disconnect();
|
|
1099
1396
|
}
|
|
1397
|
+
function startPlaybackTicker() {
|
|
1398
|
+
stopPlaybackTicker();
|
|
1399
|
+
const tick = () => {
|
|
1400
|
+
if (!playbackPlaying) {
|
|
1401
|
+
playbackFrame = 0;
|
|
1402
|
+
return;
|
|
1403
|
+
}
|
|
1404
|
+
playbackPositionMs = getPlaybackPositionMs();
|
|
1405
|
+
playbackFrame = window.requestAnimationFrame(tick);
|
|
1406
|
+
};
|
|
1407
|
+
playbackFrame = window.requestAnimationFrame(tick);
|
|
1408
|
+
}
|
|
1100
1409
|
function getRecordingDurationMs() {
|
|
1410
|
+
if (waveform && Number.isFinite(waveform.durationMs)) {
|
|
1411
|
+
return Math.max(0, waveform.durationMs);
|
|
1412
|
+
}
|
|
1413
|
+
if (playbackAudioBuffer && Number.isFinite(playbackAudioBuffer.duration)) {
|
|
1414
|
+
return Math.max(0, playbackAudioBuffer.duration * 1e3);
|
|
1415
|
+
}
|
|
1101
1416
|
return 0;
|
|
1102
1417
|
}
|
|
1103
1418
|
async function togglePlayback() {
|
|
1104
|
-
return;
|
|
1419
|
+
if (!recording.exists || !recording.audioUrl) return;
|
|
1420
|
+
playbackError = null;
|
|
1421
|
+
if (playbackPlaying) {
|
|
1422
|
+
stopPlayback(true);
|
|
1423
|
+
return;
|
|
1424
|
+
}
|
|
1425
|
+
await startPlaybackAtMs(playbackPositionMs);
|
|
1426
|
+
}
|
|
1427
|
+
async function startPlaybackAtMs(nextMs) {
|
|
1428
|
+
const buffer = playbackAudioBuffer;
|
|
1429
|
+
if (!buffer) {
|
|
1430
|
+
playbackError = "Failed to decode recording for playback";
|
|
1431
|
+
return;
|
|
1432
|
+
}
|
|
1433
|
+
const durationMs = Math.max(0, buffer.duration * 1e3);
|
|
1434
|
+
const startMs = durationMs > 0 ? nextMs >= durationMs ? 0 : clamp(nextMs, 0, durationMs) : Math.max(0, nextMs);
|
|
1435
|
+
stopPlayback(false);
|
|
1436
|
+
playbackPositionMs = startMs;
|
|
1437
|
+
try {
|
|
1438
|
+
const context = await ensurePlaybackAudioContext();
|
|
1439
|
+
const source = context.createBufferSource();
|
|
1440
|
+
source.buffer = buffer;
|
|
1441
|
+
source.connect(context.destination);
|
|
1442
|
+
source.onended = () => {
|
|
1443
|
+
if (playbackSourceNode !== source) return;
|
|
1444
|
+
playbackSourceNode = null;
|
|
1445
|
+
playbackStartedAtMs = null;
|
|
1446
|
+
playbackStartedAtContextTime = null;
|
|
1447
|
+
playbackPlaying = false;
|
|
1448
|
+
playbackPositionMs = durationMs;
|
|
1449
|
+
stopPlaybackTicker();
|
|
1450
|
+
};
|
|
1451
|
+
playbackSourceNode = source;
|
|
1452
|
+
playbackStartedAtMs = startMs;
|
|
1453
|
+
playbackStartedAtContextTime = context.currentTime;
|
|
1454
|
+
playbackPlaying = true;
|
|
1455
|
+
playbackError = null;
|
|
1456
|
+
startPlaybackTicker();
|
|
1457
|
+
source.start(0, startMs / 1e3);
|
|
1458
|
+
} catch (reason) {
|
|
1459
|
+
stopPlayback(false);
|
|
1460
|
+
playbackPlaying = false;
|
|
1461
|
+
playbackError = reason instanceof Error ? reason.message : "Failed to play recording";
|
|
1462
|
+
}
|
|
1105
1463
|
}
|
|
1106
1464
|
function compareConversationTraces(a, b) {
|
|
1107
1465
|
return a.createdAt - b.createdAt || String(a.traceId ?? "").localeCompare(String(b.traceId ?? ""));
|
|
@@ -1112,6 +1470,7 @@ function _page($$renderer, $$props) {
|
|
|
1112
1470
|
const originMs = timelineOriginMs();
|
|
1113
1471
|
viewportStartMs = originMs;
|
|
1114
1472
|
viewportEndMs = Math.max(originMs + 1e3, extent.max);
|
|
1473
|
+
viewDirty = markDirty;
|
|
1115
1474
|
}
|
|
1116
1475
|
function clampViewport(startMs, endMs) {
|
|
1117
1476
|
const extent = contentExtent();
|
|
@@ -1152,10 +1511,41 @@ function _page($$renderer, $$props) {
|
|
|
1152
1511
|
const nextFocusRatio = clamp(focusRatio, 0, 1);
|
|
1153
1512
|
const focusMs = viewportStartMs + currentDuration * nextFocusRatio;
|
|
1154
1513
|
const nextStartMs = focusMs - nextDuration * nextFocusRatio;
|
|
1514
|
+
viewDirty = true;
|
|
1155
1515
|
setViewport(nextStartMs, nextStartMs + nextDuration);
|
|
1156
1516
|
}
|
|
1517
|
+
function setLocalAlignmentOffset(nextOffsetMs) {
|
|
1518
|
+
recording = { ...recording, alignmentOffsetMs: Math.round(nextOffsetMs) };
|
|
1519
|
+
}
|
|
1520
|
+
async function persistAlignmentOffset() {
|
|
1521
|
+
if (!recording.exists || !recordingApiUrl()) return;
|
|
1522
|
+
alignmentSaving = true;
|
|
1523
|
+
alignmentError = null;
|
|
1524
|
+
try {
|
|
1525
|
+
const response = await fetch(recordingApiUrl(), {
|
|
1526
|
+
method: "PATCH",
|
|
1527
|
+
headers: {
|
|
1528
|
+
accept: "application/json",
|
|
1529
|
+
"content-type": "application/json"
|
|
1530
|
+
},
|
|
1531
|
+
body: JSON.stringify({ alignmentOffsetMs: recording.alignmentOffsetMs })
|
|
1532
|
+
});
|
|
1533
|
+
const payload = await readResponsePayload(response);
|
|
1534
|
+
if (!response.ok) {
|
|
1535
|
+
throw new Error(getResponseError(payload, "Failed to save alignment offset"));
|
|
1536
|
+
}
|
|
1537
|
+
recording = buildRecordingResponse(payload);
|
|
1538
|
+
} catch (reason) {
|
|
1539
|
+
alignmentError = reason instanceof Error ? reason.message : String(reason);
|
|
1540
|
+
} finally {
|
|
1541
|
+
alignmentSaving = false;
|
|
1542
|
+
}
|
|
1543
|
+
}
|
|
1157
1544
|
async function resetAlignment() {
|
|
1158
|
-
return;
|
|
1545
|
+
if (!recording.exists) return;
|
|
1546
|
+
viewDirty = true;
|
|
1547
|
+
setLocalAlignmentOffset(0);
|
|
1548
|
+
await persistAlignmentOffset();
|
|
1159
1549
|
}
|
|
1160
1550
|
$$renderer2.push(`<div class="flex h-full min-h-0 flex-col bg-rc-gray-700"><div class="flex-none border-b border-rc-gray-300/40 p-4"><div class="flex flex-wrap items-start justify-between gap-3"><div><h2 class="text-lg font-semibold text-rc-gray-100">Latency `);
|
|
1161
1551
|
if (conversationId()) {
|
|
@@ -1165,7 +1555,10 @@ function _page($$renderer, $$props) {
|
|
|
1165
1555
|
$$renderer2.push("<!--[-1-->");
|
|
1166
1556
|
}
|
|
1167
1557
|
$$renderer2.push(`<!--]--></h2> <div class="mt-2 flex flex-wrap gap-x-5 gap-y-1 text-xs text-rc-gray-300"><div><span class="text-rc-gray-400">Latency events:</span> <span class="font-mono text-rc-gray-100">${escape_html(latencyTraceCount())}</span></div> <div><span class="text-rc-gray-400">Timeline items:</span> <span class="font-mono text-rc-gray-100">${escape_html(callSegments().length)}</span></div> <div><span class="text-rc-gray-400">Recording offset:</span> <span class="font-mono text-rc-gray-100">${escape_html(fmtSignedMs(recording.alignmentOffsetMs))}</span></div> `);
|
|
1168
|
-
{
|
|
1558
|
+
if (recording.exists && playbackAbsoluteMs() != null) {
|
|
1559
|
+
$$renderer2.push("<!--[0-->");
|
|
1560
|
+
$$renderer2.push(`<div><span class="text-rc-gray-400">Playhead:</span> <span class="font-mono text-rc-gray-100">${escape_html(formatRelativeTime(playbackAbsoluteMs() - timelineOriginMs()))}</span></div>`);
|
|
1561
|
+
} else {
|
|
1169
1562
|
$$renderer2.push("<!--[-1-->");
|
|
1170
1563
|
}
|
|
1171
1564
|
$$renderer2.push(`<!--]--> `);
|
|
@@ -1182,7 +1575,7 @@ function _page($$renderer, $$props) {
|
|
|
1182
1575
|
disabled: uploadInFlight,
|
|
1183
1576
|
onclick: () => fileInputEl?.click(),
|
|
1184
1577
|
children: ($$renderer3) => {
|
|
1185
|
-
$$renderer3.push(`<!---->${escape_html("Upload WAV")}`);
|
|
1578
|
+
$$renderer3.push(`<!---->${escape_html(recording.exists ? "Replace WAV" : "Upload WAV")}`);
|
|
1186
1579
|
},
|
|
1187
1580
|
$$slots: { default: true }
|
|
1188
1581
|
});
|
|
@@ -1190,7 +1583,7 @@ function _page($$renderer, $$props) {
|
|
|
1190
1583
|
Button($$renderer2, {
|
|
1191
1584
|
variant: "secondary",
|
|
1192
1585
|
size: "small",
|
|
1193
|
-
disabled:
|
|
1586
|
+
disabled: !recording.exists,
|
|
1194
1587
|
onclick: () => void togglePlayback(),
|
|
1195
1588
|
children: ($$renderer3) => {
|
|
1196
1589
|
$$renderer3.push(`<!---->${escape_html(playbackPlaying ? "Pause" : "Play")}`);
|
|
@@ -1234,7 +1627,7 @@ function _page($$renderer, $$props) {
|
|
|
1234
1627
|
Button($$renderer2, {
|
|
1235
1628
|
variant: "secondary",
|
|
1236
1629
|
size: "small",
|
|
1237
|
-
disabled:
|
|
1630
|
+
disabled: !recording.exists || alignmentSaving,
|
|
1238
1631
|
onclick: resetAlignment,
|
|
1239
1632
|
children: ($$renderer3) => {
|
|
1240
1633
|
$$renderer3.push(`<!---->Reset alignment`);
|
|
@@ -1257,19 +1650,31 @@ function _page($$renderer, $$props) {
|
|
|
1257
1650
|
$$renderer2.push("<!--[-1-->");
|
|
1258
1651
|
}
|
|
1259
1652
|
$$renderer2.push(`<!--]--> `);
|
|
1260
|
-
{
|
|
1653
|
+
if (error) {
|
|
1654
|
+
$$renderer2.push("<!--[0-->");
|
|
1655
|
+
$$renderer2.push(`<div class="mt-2 text-sm text-red-300">Failed to load latency traces: ${escape_html(error)}</div>`);
|
|
1656
|
+
} else {
|
|
1261
1657
|
$$renderer2.push("<!--[-1-->");
|
|
1262
1658
|
}
|
|
1263
1659
|
$$renderer2.push(`<!--]--> `);
|
|
1264
|
-
{
|
|
1660
|
+
if (recordingError) {
|
|
1661
|
+
$$renderer2.push("<!--[0-->");
|
|
1662
|
+
$$renderer2.push(`<div class="mt-2 text-sm text-red-300">Recording error: ${escape_html(recordingError)}</div>`);
|
|
1663
|
+
} else {
|
|
1265
1664
|
$$renderer2.push("<!--[-1-->");
|
|
1266
1665
|
}
|
|
1267
1666
|
$$renderer2.push(`<!--]--> `);
|
|
1268
|
-
{
|
|
1667
|
+
if (alignmentError) {
|
|
1668
|
+
$$renderer2.push("<!--[0-->");
|
|
1669
|
+
$$renderer2.push(`<div class="mt-2 text-sm text-red-300">Alignment error: ${escape_html(alignmentError)}</div>`);
|
|
1670
|
+
} else {
|
|
1269
1671
|
$$renderer2.push("<!--[-1-->");
|
|
1270
1672
|
}
|
|
1271
1673
|
$$renderer2.push(`<!--]--> `);
|
|
1272
|
-
{
|
|
1674
|
+
if (playbackError) {
|
|
1675
|
+
$$renderer2.push("<!--[0-->");
|
|
1676
|
+
$$renderer2.push(`<div class="mt-2 text-sm text-red-300">Playback error: ${escape_html(playbackError)}</div>`);
|
|
1677
|
+
} else {
|
|
1273
1678
|
$$renderer2.push("<!--[-1-->");
|
|
1274
1679
|
}
|
|
1275
1680
|
$$renderer2.push(`<!--]--></div> <div class="rc-scroll min-h-0 flex-1 overflow-auto p-4"><div class="flex flex-col gap-4"><div class="rounded-md border border-rc-gray-650 p-3">`);
|
|
@@ -1378,7 +1783,10 @@ function _page($$renderer, $$props) {
|
|
|
1378
1783
|
if (waveformRowVisible()) {
|
|
1379
1784
|
$$renderer2.push("<!--[0-->");
|
|
1380
1785
|
$$renderer2.push(`<div class="relative z-0 overflow-hidden rounded-b border-x border-b border-t border-rc-gray-700/60"${attr_style(`height:${WAVEFORM_ROW_HEIGHT_PX}px;margin-top:${TIMELINE_ROW_GAP_PX}px;`)}>`);
|
|
1381
|
-
{
|
|
1786
|
+
if (waveformError) {
|
|
1787
|
+
$$renderer2.push("<!--[1-->");
|
|
1788
|
+
$$renderer2.push(`<div class="absolute inset-0 flex items-center justify-center px-4 text-sm text-red-300">Failed to decode waveform: ${escape_html(waveformError)}</div>`);
|
|
1789
|
+
} else {
|
|
1382
1790
|
$$renderer2.push("<!--[-1-->");
|
|
1383
1791
|
$$renderer2.push(`<canvas class="absolute inset-0 h-full w-full"></canvas>`);
|
|
1384
1792
|
}
|
|
@@ -1407,4 +1815,4 @@ function _page($$renderer, $$props) {
|
|
|
1407
1815
|
}
|
|
1408
1816
|
|
|
1409
1817
|
export { _page as default };
|
|
1410
|
-
//# sourceMappingURL=_page.svelte-
|
|
1818
|
+
//# sourceMappingURL=_page.svelte-C_S_qUgZ.js.map
|