@recombine-ai/platform 0.4.0 → 0.5.0-test.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/build/agent/agent-analytics.d.ts +14 -0
- package/build/agent/agent-analytics.d.ts.map +1 -0
- package/build/agent/agent-analytics.js +29 -0
- package/build/agent/index.d.ts +1 -0
- package/build/agent/index.d.ts.map +1 -1
- package/build/agent/text-agent.d.ts +4 -3
- package/build/agent/text-agent.d.ts.map +1 -1
- package/build/agent/text-agent.js +8 -1
- package/build/agent/voice-agent.d.ts +4 -3
- package/build/agent/voice-agent.d.ts.map +1 -1
- package/build/agent/voice-agent.js +8 -1
- package/build/analytics/analytics.d.ts +49 -0
- package/build/analytics/analytics.d.ts.map +1 -0
- package/build/analytics/analytics.js +223 -0
- package/build/analytics/index.d.ts +7 -0
- package/build/analytics/index.d.ts.map +1 -0
- package/build/analytics/index.js +3 -0
- package/build/analytics/postgres-analytics-query.d.ts +117 -0
- package/build/analytics/postgres-analytics-query.d.ts.map +1 -0
- package/build/analytics/postgres-analytics-query.js +504 -0
- package/build/analytics/postgres-analytics.d.ts +33 -0
- package/build/analytics/postgres-analytics.d.ts.map +1 -0
- package/build/analytics/postgres-analytics.js +310 -0
- package/build/bosun/std-mocks/platform.d.ts.map +1 -1
- package/build/bosun/std-mocks/platform.js +2 -0
- package/build/bosun/test-agent.d.ts.map +1 -1
- package/build/bosun/test-agent.js +2 -1
- package/build/bosun-app/frontend/client/_app/immutable/assets/0.BhaOIA8N.css +1 -0
- package/build/bosun-app/frontend/client/_app/immutable/assets/0.BhaOIA8N.css.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/assets/0.BhaOIA8N.css.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/-ZTJLlC3.js +2 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/-ZTJLlC3.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/-ZTJLlC3.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/0Q6TVg1G.js +1 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/0Q6TVg1G.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/0Q6TVg1G.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/{DEz15oJb.js → 4OgEIyh1.js} +1 -1
- package/build/bosun-app/frontend/client/_app/immutable/chunks/4OgEIyh1.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/4OgEIyh1.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/8bHWYDyT.js +1 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/8bHWYDyT.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/8bHWYDyT.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/{C0rPkxmP.js → 9pOOTteE.js} +1 -1
- package/build/bosun-app/frontend/client/_app/immutable/chunks/9pOOTteE.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/9pOOTteE.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/AlWqjAqK.js +1 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/AlWqjAqK.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/AlWqjAqK.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/{B9pMb6OP.js → B9e8MCJ2.js} +1 -1
- package/build/bosun-app/frontend/client/_app/immutable/chunks/B9e8MCJ2.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/B9e8MCJ2.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/{BEdAvgYp.js → BDIIq0ko.js} +1 -1
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BDIIq0ko.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BDIIq0ko.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BFiP5U7M.js +3 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BFiP5U7M.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BFiP5U7M.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/{DnMQeiTY.js → BHU9AXbn.js} +1 -1
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BHU9AXbn.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BHU9AXbn.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/{Bp8N7Z1t.js → BHwgmBN2.js} +1 -1
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BHwgmBN2.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BHwgmBN2.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BOlSQbHE.js +2 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BOlSQbHE.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BOlSQbHE.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BXO2WwQx.js +1 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BXO2WwQx.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BXO2WwQx.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/{BQIf5msi.js → BZeEhZ9x.js} +1 -1
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BZeEhZ9x.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BZeEhZ9x.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BbB1C_YH.js +1 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BbB1C_YH.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BbB1C_YH.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/{DJnDF3d9.js → BtJ1grIE.js} +1 -1
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BtJ1grIE.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BtJ1grIE.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/C5z36vOP.js +8 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/C5z36vOP.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/C5z36vOP.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/CHNsNZYZ.js +1 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/CHNsNZYZ.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/CHNsNZYZ.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/{BEtU89l8.js → CINamuM5.js} +1 -1
- package/build/bosun-app/frontend/client/_app/immutable/chunks/CINamuM5.js.br +1 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/CINamuM5.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/CR6hF_YT.js +1 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/CR6hF_YT.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/CR6hF_YT.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/CbXT0Qet.js +1 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/CbXT0Qet.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/CbXT0Qet.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/{sKHuRf4Z.js → CkCJ1-zx.js} +1 -1
- package/build/bosun-app/frontend/client/_app/immutable/chunks/CkCJ1-zx.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/CkCJ1-zx.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/Cm25Ihk6.js +1 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/Cm25Ihk6.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/Cm25Ihk6.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/CmJrlnQL.js +64 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/CmJrlnQL.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/CmJrlnQL.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/CofRL0YY.js +2 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/CofRL0YY.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/CofRL0YY.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/{joiJcRPz.js → Csai_DUZ.js} +1 -1
- package/build/bosun-app/frontend/client/_app/immutable/chunks/Csai_DUZ.js.br +6 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/Csai_DUZ.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/{CCYriF4C.js → D24F_tet.js} +1 -1
- package/build/bosun-app/frontend/client/_app/immutable/chunks/D24F_tet.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/D24F_tet.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/{DNvczHUR.js → D35JKLYq.js} +1 -1
- package/build/bosun-app/frontend/client/_app/immutable/chunks/D35JKLYq.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/D35JKLYq.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/{BcbX6huO.js → D6r2pB3T.js} +1 -1
- package/build/bosun-app/frontend/client/_app/immutable/chunks/D6r2pB3T.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/D6r2pB3T.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/{ClLUwVGq.js → DJFKRYxi.js} +1 -1
- package/build/bosun-app/frontend/client/_app/immutable/chunks/DJFKRYxi.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/DJFKRYxi.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/{BW6P0Ecp.js → DOVgTfHj.js} +1 -1
- package/build/bosun-app/frontend/client/_app/immutable/chunks/DOVgTfHj.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/DOVgTfHj.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/DPfKTQVx.js +1 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/DPfKTQVx.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/DPfKTQVx.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/{ouMvMh56.js → DSFEfk-V.js} +1 -1
- package/build/bosun-app/frontend/client/_app/immutable/chunks/DSFEfk-V.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/DSFEfk-V.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/DbY589nb.js +1 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/DbY589nb.js.br +2 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/DbY589nb.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/DfEgi1lN.js +1 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/DfEgi1lN.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/DfEgi1lN.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/{BJ9KKLWf.js → DsRUoWL6.js} +1 -1
- package/build/bosun-app/frontend/client/_app/immutable/chunks/DsRUoWL6.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/DsRUoWL6.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/{DjujL8K1.js → FLx39vZ1.js} +1 -1
- package/build/bosun-app/frontend/client/_app/immutable/chunks/FLx39vZ1.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/FLx39vZ1.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/{BBk8_Xpk.js → NwoUwoIi.js} +2 -2
- package/build/bosun-app/frontend/client/_app/immutable/chunks/NwoUwoIi.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/NwoUwoIi.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/{C9yBjdYI.js → VLxbY_3V.js} +1 -1
- package/build/bosun-app/frontend/client/_app/immutable/chunks/VLxbY_3V.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/VLxbY_3V.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/uEzaTD9T.js +1 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/uEzaTD9T.js.br +2 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/uEzaTD9T.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/entry/app.fITODAfp.js +2 -0
- package/build/bosun-app/frontend/client/_app/immutable/entry/app.fITODAfp.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/entry/app.fITODAfp.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/entry/start.CuqUO5EQ.js +1 -0
- package/build/bosun-app/frontend/client/_app/immutable/entry/start.CuqUO5EQ.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/entry/start.CuqUO5EQ.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/{0.BrSNCmq3.js → 0.sWxZKx1V.js} +1 -1
- package/build/bosun-app/frontend/client/_app/immutable/nodes/0.sWxZKx1V.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/0.sWxZKx1V.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/1.PQXY4edq.js +1 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/1.PQXY4edq.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/1.PQXY4edq.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/{10.BI2Z0Is-.js → 10.BP2gctlm.js} +7 -7
- package/build/bosun-app/frontend/client/_app/immutable/nodes/10.BP2gctlm.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/10.BP2gctlm.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/{15.drIyAxl2.js → 15.D4h0JT65.js} +1 -1
- package/build/bosun-app/frontend/client/_app/immutable/nodes/15.D4h0JT65.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/15.D4h0JT65.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/17.D5wsHo5R.js +3 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/17.D5wsHo5R.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/17.D5wsHo5R.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/18.CZp-IBH8.js +11 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/18.CZp-IBH8.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/18.CZp-IBH8.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/{2.BYBSEm-Y.js → 2.DaZm8LbH.js} +3 -3
- package/build/bosun-app/frontend/client/_app/immutable/nodes/2.DaZm8LbH.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/2.DaZm8LbH.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/3.Bk3buFqf.js +1 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/3.Bk3buFqf.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/3.Bk3buFqf.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/{4.Dlg932RB.js → 4.BWY-PEkr.js} +1 -1
- package/build/bosun-app/frontend/client/_app/immutable/nodes/4.BWY-PEkr.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/4.BWY-PEkr.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/{5.BWt6bVnz.js → 5.Cl70jzrZ.js} +1 -1
- package/build/bosun-app/frontend/client/_app/immutable/nodes/5.Cl70jzrZ.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/5.Cl70jzrZ.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/{6.DL1bd1xV.js → 6.Cfkc99si.js} +1 -1
- package/build/bosun-app/frontend/client/_app/immutable/nodes/6.Cfkc99si.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/6.Cfkc99si.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/{8.BJXaarvf.js → 8.CmB3ZvKy.js} +1 -1
- package/build/bosun-app/frontend/client/_app/immutable/nodes/8.CmB3ZvKy.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/8.CmB3ZvKy.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/{9.DZnil4g8.js → 9.8UAsXj0n.js} +1 -1
- package/build/bosun-app/frontend/client/_app/immutable/nodes/9.8UAsXj0n.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/9.8UAsXj0n.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/version.json +1 -1
- package/build/bosun-app/frontend/client/_app/version.json.br +0 -0
- package/build/bosun-app/frontend/client/_app/version.json.gz +0 -0
- package/build/bosun-app/frontend/handler.js +4 -4
- package/build/bosun-app/frontend/index.js +4 -4
- package/build/bosun-app/frontend/server/chunks/chunks/{internal.js-Bu4L_cnE.js → internal.js-BYUssiWE.js} +2 -2
- package/build/bosun-app/frontend/server/chunks/chunks/{internal.js-Bu4L_cnE.js.map → internal.js-BYUssiWE.js.map} +1 -1
- package/build/bosun-app/frontend/server/chunks/chunks/{schemas.js-W-DP3mDr.js → schemas.js-b9Mui_5N.js} +187 -2
- package/build/bosun-app/frontend/server/chunks/chunks/schemas.js-b9Mui_5N.js.map +1 -0
- package/build/bosun-app/frontend/server/chunks/chunks/{source-selection.js-Cc6RX6-m.js → source-selection.js-BpCr9ar-.js} +47 -4
- package/build/bosun-app/frontend/server/chunks/chunks/source-selection.js-BpCr9ar-.js.map +1 -0
- package/build/bosun-app/frontend/server/chunks/chunks/{sources.server.js-B6fpC51P.js → sources.server.js-DIj2VjCx.js} +2 -2
- package/build/bosun-app/frontend/server/chunks/chunks/{sources.server.js-B6fpC51P.js.map → sources.server.js-DIj2VjCx.js.map} +1 -1
- package/build/bosun-app/frontend/server/chunks/entries/endpoints/traces/api/latency/_conversationId_/{_server.ts.js-hHR2eFvt.js → _server.ts.js-mL82mAit.js} +2 -2
- package/build/bosun-app/frontend/server/chunks/entries/endpoints/traces/api/latency/_conversationId_/{_server.ts.js-hHR2eFvt.js.map → _server.ts.js-mL82mAit.js.map} +1 -1
- package/build/bosun-app/frontend/server/chunks/entries/endpoints/traces/api/proxy/_...path_/{_server.ts.js-CHrOiduq.js → _server.ts.js-DDDiZFhL.js} +17 -10
- package/build/bosun-app/frontend/server/chunks/entries/endpoints/traces/api/proxy/_...path_/_server.ts.js-DDDiZFhL.js.map +1 -0
- package/build/bosun-app/frontend/server/chunks/entries/endpoints/traces/api/sources/{_server.ts.js-C2FIU8Kr.js → _server.ts.js-D_UoR_Ph.js} +3 -3
- package/build/bosun-app/frontend/server/chunks/entries/endpoints/traces/api/sources/{_server.ts.js-C2FIU8Kr.js.map → _server.ts.js-D_UoR_Ph.js.map} +1 -1
- package/build/bosun-app/frontend/server/chunks/entries/pages/traces/conversations/_conversationId_/latency/{_page.svelte.js-tdUdTo4m.js → _page.svelte.js-DXMXSrkC.js} +5 -5
- package/build/bosun-app/frontend/server/chunks/entries/pages/traces/conversations/_conversationId_/latency/_page.svelte.js-DXMXSrkC.js.map +1 -0
- package/build/bosun-app/frontend/server/chunks/entries/pages/traces/conversations/_conversationId_/traces/{_page.svelte.js-Ca79DBzJ.js → _page.svelte.js-CZkbHRGl.js} +28 -9
- package/build/bosun-app/frontend/server/chunks/entries/pages/traces/conversations/_conversationId_/traces/_page.svelte.js-CZkbHRGl.js.map +1 -0
- package/build/bosun-app/frontend/server/chunks/entries/pages/traces/conversations/{_layout.svelte.js-Dvn3tfM7.js → _layout.svelte.js-B4Yws-GS.js} +328 -35
- package/build/bosun-app/frontend/server/chunks/entries/pages/traces/conversations/_layout.svelte.js-B4Yws-GS.js.map +1 -0
- package/build/bosun-app/frontend/server/chunks/{handler-Caqo1h-B.js → handler-B-UxYyko.js} +3 -3
- package/build/bosun-app/frontend/server/chunks/{handler-Caqo1h-B.js.map → handler-B-UxYyko.js.map} +1 -1
- package/build/bosun-app/frontend/server/chunks/{index.js-B6JFIJIn.js → index.js-CleJzVFo.js} +2 -2
- package/build/bosun-app/frontend/server/chunks/{index.js-B6JFIJIn.js.map → index.js-CleJzVFo.js.map} +1 -1
- package/build/bosun-app/frontend/server/chunks/{manifest.js-BQmpznei.js → manifest.js-C8NquSUu.js} +18 -18
- package/build/bosun-app/frontend/server/chunks/{manifest.js-BQmpznei.js.map → manifest.js-C8NquSUu.js.map} +1 -1
- package/build/bosun-app/frontend/server/chunks/nodes/0.js-BUVJh5Uv.js +9 -0
- package/build/bosun-app/frontend/server/chunks/nodes/0.js-BUVJh5Uv.js.map +1 -0
- package/build/bosun-app/frontend/server/chunks/nodes/1.js-BKMg62KW.js +9 -0
- package/build/bosun-app/frontend/server/chunks/nodes/{1.js-BujyKhW9.js.map → 1.js-BKMg62KW.js.map} +1 -1
- package/build/bosun-app/frontend/server/chunks/nodes/10.js-Bz0enUzA.js +9 -0
- package/build/bosun-app/frontend/server/chunks/nodes/10.js-Bz0enUzA.js.map +1 -0
- package/build/bosun-app/frontend/server/chunks/nodes/{15.js-cNd06B9T.js → 15.js-nE6nl5S8.js} +2 -2
- package/build/bosun-app/frontend/server/chunks/nodes/{15.js-cNd06B9T.js.map → 15.js-nE6nl5S8.js.map} +1 -1
- package/build/bosun-app/frontend/server/chunks/nodes/17.js-CplX6Ruz.js +9 -0
- package/build/bosun-app/frontend/server/chunks/nodes/17.js-CplX6Ruz.js.map +1 -0
- package/build/bosun-app/frontend/server/chunks/nodes/18.js-cGVVSoEn.js +9 -0
- package/build/bosun-app/frontend/server/chunks/nodes/18.js-cGVVSoEn.js.map +1 -0
- package/build/bosun-app/frontend/server/chunks/nodes/2.js-CliMdUrH.js +9 -0
- package/build/bosun-app/frontend/server/chunks/nodes/2.js-CliMdUrH.js.map +1 -0
- package/build/bosun-app/frontend/server/chunks/nodes/3.js-BQpmmrUv.js +9 -0
- package/build/bosun-app/frontend/server/chunks/nodes/3.js-BQpmmrUv.js.map +1 -0
- package/build/bosun-app/frontend/server/chunks/nodes/4.js-BgSyMW3D.js +9 -0
- package/build/bosun-app/frontend/server/chunks/nodes/4.js-BgSyMW3D.js.map +1 -0
- package/build/bosun-app/frontend/server/chunks/nodes/5.js-CqRWSoO5.js +9 -0
- package/build/bosun-app/frontend/server/chunks/nodes/{5.js-C3vjOcSE.js.map → 5.js-CqRWSoO5.js.map} +1 -1
- package/build/bosun-app/frontend/server/chunks/nodes/6.js-CrEQ411L.js +9 -0
- package/build/bosun-app/frontend/server/chunks/nodes/6.js-CrEQ411L.js.map +1 -0
- package/build/bosun-app/frontend/server/chunks/nodes/8.js-CiOj2-c5.js +9 -0
- package/build/bosun-app/frontend/server/chunks/nodes/8.js-CiOj2-c5.js.map +1 -0
- package/build/bosun-app/frontend/server/chunks/nodes/9.js-BMwqRSfy.js +9 -0
- package/build/bosun-app/frontend/server/chunks/nodes/9.js-BMwqRSfy.js.map +1 -0
- package/build/build/build.d.ts.map +1 -1
- package/build/build/build.js +3 -1
- package/build/build/common.d.ts +1 -0
- package/build/build/common.d.ts.map +1 -1
- package/build/build/common.js +12 -0
- package/build/call-control/types.d.ts +1 -1
- package/build/call-control/types.d.ts.map +1 -1
- package/build/core/make-text-platform.d.ts +3 -1
- package/build/core/make-text-platform.d.ts.map +1 -1
- package/build/core/make-text-platform.js +3 -1
- package/build/core/make-voice-platform.d.ts +3 -1
- package/build/core/make-voice-platform.d.ts.map +1 -1
- package/build/core/make-voice-platform.js +3 -1
- package/build/core/platform.d.ts +2 -0
- package/build/core/platform.d.ts.map +1 -1
- package/build/voice-agent-api/call-end.d.ts +19 -0
- package/build/voice-agent-api/call-end.d.ts.map +1 -0
- package/build/voice-agent-api/call-end.js +58 -0
- package/build/voice-agent-api/voice-http.d.ts +3 -1
- package/build/voice-agent-api/voice-http.d.ts.map +1 -1
- package/build/voice-agent-api/voice-http.js +27 -7
- package/package.json +5 -1
- package/build/bosun-app/frontend/client/_app/immutable/assets/0.B5fEz2jr.css +0 -1
- package/build/bosun-app/frontend/client/_app/immutable/assets/0.B5fEz2jr.css.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/assets/0.B5fEz2jr.css.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/9mOMnnWN.js +0 -1
- package/build/bosun-app/frontend/client/_app/immutable/chunks/9mOMnnWN.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/9mOMnnWN.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/B0nqNj93.js +0 -2
- package/build/bosun-app/frontend/client/_app/immutable/chunks/B0nqNj93.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/B0nqNj93.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/B1dhmiqQ.js +0 -1
- package/build/bosun-app/frontend/client/_app/immutable/chunks/B1dhmiqQ.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/B1dhmiqQ.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/B9pMb6OP.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/B9pMb6OP.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BBk8_Xpk.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BBk8_Xpk.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BEdAvgYp.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BEdAvgYp.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BEtU89l8.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BEtU89l8.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BJ9KKLWf.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BJ9KKLWf.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BOj6p3qj.js +0 -3
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BOj6p3qj.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BOj6p3qj.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BQIf5msi.js.br +0 -1
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BQIf5msi.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BVp4hYzT.js +0 -1
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BVp4hYzT.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BVp4hYzT.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BW6P0Ecp.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BW6P0Ecp.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BcbX6huO.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BcbX6huO.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BoX_BZZY.js +0 -1
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BoX_BZZY.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/BoX_BZZY.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/Bp8N7Z1t.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/Bp8N7Z1t.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/C0rPkxmP.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/C0rPkxmP.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/C3cROXCy.js +0 -9
- package/build/bosun-app/frontend/client/_app/immutable/chunks/C3cROXCy.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/C3cROXCy.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/C9yBjdYI.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/C9yBjdYI.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/CCYriF4C.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/CCYriF4C.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/CHCMKZAC.js +0 -1
- package/build/bosun-app/frontend/client/_app/immutable/chunks/CHCMKZAC.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/CHCMKZAC.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/CNWRsnQ2.js +0 -1
- package/build/bosun-app/frontend/client/_app/immutable/chunks/CNWRsnQ2.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/CNWRsnQ2.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/CR-uVjxM.js +0 -1
- package/build/bosun-app/frontend/client/_app/immutable/chunks/CR-uVjxM.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/CR-uVjxM.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/CR5IRTqC.js +0 -1
- package/build/bosun-app/frontend/client/_app/immutable/chunks/CR5IRTqC.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/CR5IRTqC.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/ClLUwVGq.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/ClLUwVGq.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/DEz15oJb.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/DEz15oJb.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/DJnDF3d9.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/DJnDF3d9.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/DNvczHUR.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/DNvczHUR.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/DXsF11_5.js +0 -1
- package/build/bosun-app/frontend/client/_app/immutable/chunks/DXsF11_5.js.br +0 -2
- package/build/bosun-app/frontend/client/_app/immutable/chunks/DXsF11_5.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/Dba0_Upf.js +0 -1
- package/build/bosun-app/frontend/client/_app/immutable/chunks/Dba0_Upf.js.br +0 -2
- package/build/bosun-app/frontend/client/_app/immutable/chunks/Dba0_Upf.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/DjujL8K1.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/DjujL8K1.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/DnMQeiTY.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/DnMQeiTY.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/DuQdgMax.js +0 -1
- package/build/bosun-app/frontend/client/_app/immutable/chunks/DuQdgMax.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/DuQdgMax.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/OERrxy3_.js +0 -64
- package/build/bosun-app/frontend/client/_app/immutable/chunks/OERrxy3_.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/OERrxy3_.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/ddC1NP9R.js +0 -2
- package/build/bosun-app/frontend/client/_app/immutable/chunks/ddC1NP9R.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/ddC1NP9R.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/joiJcRPz.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/joiJcRPz.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/ouMvMh56.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/ouMvMh56.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/qiSVE_6c.js +0 -1
- package/build/bosun-app/frontend/client/_app/immutable/chunks/qiSVE_6c.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/qiSVE_6c.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/sKHuRf4Z.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/sKHuRf4Z.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/zpyNGpfC.js +0 -1
- package/build/bosun-app/frontend/client/_app/immutable/chunks/zpyNGpfC.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/chunks/zpyNGpfC.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/entry/app.DJfhEB0w.js +0 -2
- package/build/bosun-app/frontend/client/_app/immutable/entry/app.DJfhEB0w.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/entry/app.DJfhEB0w.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/entry/start.CvCep2Ct.js +0 -1
- package/build/bosun-app/frontend/client/_app/immutable/entry/start.CvCep2Ct.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/entry/start.CvCep2Ct.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/0.BrSNCmq3.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/0.BrSNCmq3.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/1.br7GI-g3.js +0 -1
- package/build/bosun-app/frontend/client/_app/immutable/nodes/1.br7GI-g3.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/1.br7GI-g3.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/10.BI2Z0Is-.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/10.BI2Z0Is-.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/15.drIyAxl2.js.br +0 -1
- package/build/bosun-app/frontend/client/_app/immutable/nodes/15.drIyAxl2.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/17.BpaLQSZh.js +0 -3
- package/build/bosun-app/frontend/client/_app/immutable/nodes/17.BpaLQSZh.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/17.BpaLQSZh.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/18.CYbvSJai.js +0 -11
- package/build/bosun-app/frontend/client/_app/immutable/nodes/18.CYbvSJai.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/18.CYbvSJai.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/2.BYBSEm-Y.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/2.BYBSEm-Y.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/3.BuP4tAto.js +0 -1
- package/build/bosun-app/frontend/client/_app/immutable/nodes/3.BuP4tAto.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/3.BuP4tAto.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/4.Dlg932RB.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/4.Dlg932RB.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/5.BWt6bVnz.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/5.BWt6bVnz.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/6.DL1bd1xV.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/6.DL1bd1xV.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/8.BJXaarvf.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/8.BJXaarvf.js.gz +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/9.DZnil4g8.js.br +0 -0
- package/build/bosun-app/frontend/client/_app/immutable/nodes/9.DZnil4g8.js.gz +0 -0
- package/build/bosun-app/frontend/server/chunks/chunks/schemas.js-W-DP3mDr.js.map +0 -1
- package/build/bosun-app/frontend/server/chunks/chunks/source-selection.js-Cc6RX6-m.js.map +0 -1
- package/build/bosun-app/frontend/server/chunks/entries/endpoints/traces/api/proxy/_...path_/_server.ts.js-CHrOiduq.js.map +0 -1
- package/build/bosun-app/frontend/server/chunks/entries/pages/traces/conversations/_conversationId_/latency/_page.svelte.js-tdUdTo4m.js.map +0 -1
- package/build/bosun-app/frontend/server/chunks/entries/pages/traces/conversations/_conversationId_/traces/_page.svelte.js-Ca79DBzJ.js.map +0 -1
- package/build/bosun-app/frontend/server/chunks/entries/pages/traces/conversations/_layout.svelte.js-Dvn3tfM7.js.map +0 -1
- package/build/bosun-app/frontend/server/chunks/nodes/0.js-DFPCfgZg.js +0 -9
- package/build/bosun-app/frontend/server/chunks/nodes/0.js-DFPCfgZg.js.map +0 -1
- package/build/bosun-app/frontend/server/chunks/nodes/1.js-BujyKhW9.js +0 -9
- package/build/bosun-app/frontend/server/chunks/nodes/10.js-Dbiu4FpX.js +0 -9
- package/build/bosun-app/frontend/server/chunks/nodes/10.js-Dbiu4FpX.js.map +0 -1
- package/build/bosun-app/frontend/server/chunks/nodes/17.js-9Acvxo6X.js +0 -9
- package/build/bosun-app/frontend/server/chunks/nodes/17.js-9Acvxo6X.js.map +0 -1
- package/build/bosun-app/frontend/server/chunks/nodes/18.js-D294qrHb.js +0 -9
- package/build/bosun-app/frontend/server/chunks/nodes/18.js-D294qrHb.js.map +0 -1
- package/build/bosun-app/frontend/server/chunks/nodes/2.js-DiVDZRco.js +0 -9
- package/build/bosun-app/frontend/server/chunks/nodes/2.js-DiVDZRco.js.map +0 -1
- package/build/bosun-app/frontend/server/chunks/nodes/3.js-DiaPSM0a.js +0 -9
- package/build/bosun-app/frontend/server/chunks/nodes/3.js-DiaPSM0a.js.map +0 -1
- package/build/bosun-app/frontend/server/chunks/nodes/4.js-DQhC-gZ_.js +0 -9
- package/build/bosun-app/frontend/server/chunks/nodes/4.js-DQhC-gZ_.js.map +0 -1
- package/build/bosun-app/frontend/server/chunks/nodes/5.js-C3vjOcSE.js +0 -9
- package/build/bosun-app/frontend/server/chunks/nodes/6.js-DpCeETlI.js +0 -9
- package/build/bosun-app/frontend/server/chunks/nodes/6.js-DpCeETlI.js.map +0 -1
- package/build/bosun-app/frontend/server/chunks/nodes/8.js-BjNCuX0D.js +0 -9
- package/build/bosun-app/frontend/server/chunks/nodes/8.js-BjNCuX0D.js.map +0 -1
- package/build/bosun-app/frontend/server/chunks/nodes/9.js-BuUuEII0.js +0 -9
- package/build/bosun-app/frontend/server/chunks/nodes/9.js-BuUuEII0.js.map +0 -1
- /package/build/bosun-app/frontend/client/_app/immutable/assets/{ReadOnlyMonacoDiff.iiWNRlR-.css → Modal.iiWNRlR-.css} +0 -0
- /package/build/bosun-app/frontend/client/_app/immutable/assets/{ReadOnlyMonacoDiff.iiWNRlR-.css.br → Modal.iiWNRlR-.css.br} +0 -0
- /package/build/bosun-app/frontend/client/_app/immutable/assets/{ReadOnlyMonacoDiff.iiWNRlR-.css.gz → Modal.iiWNRlR-.css.gz} +0 -0
|
@@ -0,0 +1,504 @@
|
|
|
1
|
+
import { Pool } from 'pg';
|
|
2
|
+
export class AnalyticsQueryError extends Error {
|
|
3
|
+
name = 'AnalyticsQueryError';
|
|
4
|
+
}
|
|
5
|
+
export class AnalyticsFieldNotFoundError extends Error {
|
|
6
|
+
agentId;
|
|
7
|
+
field;
|
|
8
|
+
name = 'AnalyticsFieldNotFoundError';
|
|
9
|
+
constructor(agentId, field) {
|
|
10
|
+
super(`Analytics field '${field}' does not exist for agent '${agentId}'`);
|
|
11
|
+
this.agentId = agentId;
|
|
12
|
+
this.field = field;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export class PostgresAnalyticsQueryService {
|
|
16
|
+
database;
|
|
17
|
+
constructor(database) {
|
|
18
|
+
this.database = database;
|
|
19
|
+
}
|
|
20
|
+
async getConversation(conversationId) {
|
|
21
|
+
const result = await this.database.query(`SELECT c.conversation_id, c.agent_id, c.channel, c.region, c.started_at,
|
|
22
|
+
c.ended_at, c.analytics,
|
|
23
|
+
p.phone_number, p.recording_url, p.duration_seconds
|
|
24
|
+
FROM conversations c
|
|
25
|
+
LEFT JOIN phone_calls p ON p.conversation_id = c.conversation_id
|
|
26
|
+
WHERE c.conversation_id = $1`, [conversationId]);
|
|
27
|
+
const row = result.rows[0];
|
|
28
|
+
return row?.agent_id ? conversationRowToJson(row) : undefined;
|
|
29
|
+
}
|
|
30
|
+
async getConversations(query) {
|
|
31
|
+
const parsedLimit = Number.parseInt(optionalString(query.limit, 'limit') ?? '10', 10);
|
|
32
|
+
const requestedLimit = Number.isFinite(parsedLimit)
|
|
33
|
+
? Math.min(100, Math.max(1, parsedLimit))
|
|
34
|
+
: 10;
|
|
35
|
+
const cursor = parseConversationCursor(optionalString(query.lastConversationId, 'lastConversationId'));
|
|
36
|
+
const filters = parseAnalyticsFilterQuery(query.filters);
|
|
37
|
+
const { bind, conditions, values } = buildConversationConditions(query, filters, filters.length > 0);
|
|
38
|
+
if (cursor) {
|
|
39
|
+
conditions.push(`(c.started_at, c.conversation_id) < (${bind(cursor.startedAt)}, ${bind(cursor.conversationId)})`);
|
|
40
|
+
}
|
|
41
|
+
const where = conditions.length ? `WHERE ${conditions.join(' AND ')}` : '';
|
|
42
|
+
const limitParameter = bind(requestedLimit + 1);
|
|
43
|
+
const result = await this.database.query(`SELECT c.conversation_id, c.agent_id, c.channel, c.region, c.started_at,
|
|
44
|
+
c.ended_at, c.analytics,
|
|
45
|
+
p.phone_number, p.recording_url, p.duration_seconds
|
|
46
|
+
FROM conversations c
|
|
47
|
+
LEFT JOIN phone_calls p ON p.conversation_id = c.conversation_id
|
|
48
|
+
${where}
|
|
49
|
+
ORDER BY c.started_at DESC, c.conversation_id DESC
|
|
50
|
+
LIMIT ${limitParameter}`, values);
|
|
51
|
+
const hasNextPage = result.rows.length > requestedLimit;
|
|
52
|
+
const rows = result.rows.slice(0, requestedLimit);
|
|
53
|
+
return {
|
|
54
|
+
limit: requestedLimit,
|
|
55
|
+
items: rows.map(conversationRowToJson),
|
|
56
|
+
lastConversationId: hasNextPage && rows.length > 0 ? makeConversationCursor(rows.at(-1)) : undefined,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
async getAnalyticsFields(query) {
|
|
60
|
+
const agentId = requiredString(query.agentId, 'agentId');
|
|
61
|
+
const result = await this.database.query(`SELECT entry.key AS field,
|
|
62
|
+
MIN(jsonb_typeof(entry.value)) AS type,
|
|
63
|
+
COUNT(DISTINCT entry.value)::bigint AS distinct_value_count,
|
|
64
|
+
COUNT(DISTINCT jsonb_typeof(entry.value))::integer AS type_count
|
|
65
|
+
FROM conversations c
|
|
66
|
+
CROSS JOIN LATERAL jsonb_each(c.analytics) AS entry(key, value)
|
|
67
|
+
WHERE c.agent_id = $1
|
|
68
|
+
AND jsonb_typeof(entry.value) IN ('boolean', 'number', 'string')
|
|
69
|
+
GROUP BY entry.key
|
|
70
|
+
ORDER BY field ASC`, [agentId]);
|
|
71
|
+
return {
|
|
72
|
+
items: result.rows.map((row) => {
|
|
73
|
+
if (Number(row.type_count) !== 1) {
|
|
74
|
+
throw new AnalyticsQueryError(`Analytics field '${row.field}' has inconsistent stored types`);
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
field: row.field,
|
|
78
|
+
type: row.type,
|
|
79
|
+
distinctValueCount: Number(row.distinct_value_count),
|
|
80
|
+
};
|
|
81
|
+
}),
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
async getAnalyticsFieldValues(field, query) {
|
|
85
|
+
const validatedField = validateFieldName(field, 'Field');
|
|
86
|
+
const agentId = requiredString(query.agentId, 'agentId');
|
|
87
|
+
const limit = parsePageLimit(query.limit);
|
|
88
|
+
const cursor = parseAnalyticsFieldValueCursor(optionalString(query.cursor, 'cursor'));
|
|
89
|
+
const values = [agentId, validatedField];
|
|
90
|
+
const bind = (value) => {
|
|
91
|
+
values.push(value);
|
|
92
|
+
return `$${values.length}`;
|
|
93
|
+
};
|
|
94
|
+
let cursorCondition = '';
|
|
95
|
+
if (cursor) {
|
|
96
|
+
const count = bind(cursor.count);
|
|
97
|
+
const value = bind(JSON.stringify(cursor.value));
|
|
98
|
+
cursorCondition =
|
|
99
|
+
`WHERE occurrence_count < ${count}::bigint OR ` +
|
|
100
|
+
`(occurrence_count = ${count}::bigint AND value > ${value}::jsonb)`;
|
|
101
|
+
}
|
|
102
|
+
const pageLimit = bind(limit + 1);
|
|
103
|
+
const result = await this.database.query(`WITH value_counts AS (
|
|
104
|
+
SELECT entry.value AS value,
|
|
105
|
+
COUNT(*)::bigint AS occurrence_count
|
|
106
|
+
FROM conversations c
|
|
107
|
+
CROSS JOIN LATERAL jsonb_each(c.analytics) AS entry(key, value)
|
|
108
|
+
WHERE c.agent_id = $1
|
|
109
|
+
AND entry.key = $2
|
|
110
|
+
AND jsonb_typeof(entry.value) IN ('boolean', 'number', 'string')
|
|
111
|
+
GROUP BY entry.value
|
|
112
|
+
),
|
|
113
|
+
page AS (
|
|
114
|
+
SELECT value, occurrence_count
|
|
115
|
+
FROM value_counts
|
|
116
|
+
${cursorCondition}
|
|
117
|
+
ORDER BY occurrence_count DESC, value ASC
|
|
118
|
+
LIMIT ${pageLimit}
|
|
119
|
+
)
|
|
120
|
+
SELECT page.value,
|
|
121
|
+
page.occurrence_count,
|
|
122
|
+
EXISTS (SELECT 1 FROM value_counts) AS field_exists
|
|
123
|
+
FROM (SELECT TRUE) AS seed
|
|
124
|
+
LEFT JOIN page ON TRUE
|
|
125
|
+
ORDER BY page.occurrence_count DESC, page.value ASC`, values);
|
|
126
|
+
if (!result.rows[0]?.field_exists) {
|
|
127
|
+
throw new AnalyticsFieldNotFoundError(agentId, validatedField);
|
|
128
|
+
}
|
|
129
|
+
const rows = result.rows.filter((row) => row.value !== null && row.occurrence_count !== null);
|
|
130
|
+
const hasNextPage = rows.length > limit;
|
|
131
|
+
const page = rows.slice(0, limit);
|
|
132
|
+
return {
|
|
133
|
+
items: page.map((row) => ({
|
|
134
|
+
value: row.value,
|
|
135
|
+
count: Number(row.occurrence_count),
|
|
136
|
+
})),
|
|
137
|
+
nextCursor: hasNextPage && page.length > 0 ? makeAnalyticsFieldValueCursor(page.at(-1)) : null,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
async getTimeSeries(request) {
|
|
141
|
+
const query = validateRequestObject(request);
|
|
142
|
+
const metric = parseMetric(query.metric);
|
|
143
|
+
const granularity = requiredString(query.granularity, 'granularity');
|
|
144
|
+
if (!['hour', 'day', 'week', 'month'].includes(granularity)) {
|
|
145
|
+
throw new AnalyticsQueryError('granularity must be hour, day, week, or month');
|
|
146
|
+
}
|
|
147
|
+
const filters = validateAnalyticsFilters(query.filters);
|
|
148
|
+
if (metric.operation === 'average' || metric.operation === 'sum') {
|
|
149
|
+
await this.assertNumericAnalyticsField(requiredString(query.agentId, 'agentId'), metric.field);
|
|
150
|
+
}
|
|
151
|
+
const { bind, conditions, from, to, values } = buildConversationConditions(query, filters);
|
|
152
|
+
if (!from || !to) {
|
|
153
|
+
throw new AnalyticsQueryError('from and to are required for a time series');
|
|
154
|
+
}
|
|
155
|
+
const bucketExpression = `date_trunc(${bind(granularity)}::text, c.started_at, 'UTC')`;
|
|
156
|
+
let valueExpression;
|
|
157
|
+
let numeratorExpression = 'NULL::bigint';
|
|
158
|
+
if (metric.operation === 'count') {
|
|
159
|
+
valueExpression = 'COUNT(*)::double precision';
|
|
160
|
+
}
|
|
161
|
+
else if (metric.operation === 'rate') {
|
|
162
|
+
const predicate = makeAnalyticsPredicate(metric.filter, bind);
|
|
163
|
+
numeratorExpression = `COUNT(*) FILTER (WHERE ${predicate})::bigint`;
|
|
164
|
+
valueExpression =
|
|
165
|
+
`COUNT(*) FILTER (WHERE ${predicate})::double precision / ` + 'NULLIF(COUNT(*), 0)';
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
const field = bind(metric.field);
|
|
169
|
+
const numericValue = `CASE WHEN jsonb_typeof(c.analytics -> (${field}::text)) = 'number' ` +
|
|
170
|
+
`THEN (c.analytics ->> (${field}::text))::double precision END`;
|
|
171
|
+
valueExpression =
|
|
172
|
+
metric.operation === 'average' ? `AVG(${numericValue})` : `SUM(${numericValue})`;
|
|
173
|
+
}
|
|
174
|
+
const where = conditions.length ? `WHERE ${conditions.join(' AND ')}` : '';
|
|
175
|
+
const result = await this.database.query(`SELECT ${bucketExpression} AS bucket_start,
|
|
176
|
+
${valueExpression} AS metric_value,
|
|
177
|
+
${numeratorExpression} AS numerator,
|
|
178
|
+
COUNT(*)::bigint AS denominator
|
|
179
|
+
FROM conversations c
|
|
180
|
+
LEFT JOIN phone_calls p ON p.conversation_id = c.conversation_id
|
|
181
|
+
${where}
|
|
182
|
+
GROUP BY bucket_start
|
|
183
|
+
ORDER BY bucket_start ASC`, values);
|
|
184
|
+
return {
|
|
185
|
+
metric,
|
|
186
|
+
granularity,
|
|
187
|
+
from: from.toISOString(),
|
|
188
|
+
to: to.toISOString(),
|
|
189
|
+
items: result.rows.map((row) => ({
|
|
190
|
+
startAt: new Date(row.bucket_start).toISOString(),
|
|
191
|
+
value: row.metric_value === null ? null : Number(row.metric_value),
|
|
192
|
+
...(metric.operation === 'rate'
|
|
193
|
+
? {
|
|
194
|
+
numerator: Number(row.numerator),
|
|
195
|
+
denominator: Number(row.denominator),
|
|
196
|
+
}
|
|
197
|
+
: {}),
|
|
198
|
+
})),
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
async assertNumericAnalyticsField(agentId, field) {
|
|
202
|
+
const result = await this.database.query(`SELECT ARRAY_AGG(DISTINCT jsonb_typeof(c.analytics -> $2::text)) AS types
|
|
203
|
+
FROM conversations c
|
|
204
|
+
WHERE c.agent_id = $1
|
|
205
|
+
AND c.analytics ? ($2::text)`, [agentId, field]);
|
|
206
|
+
const types = result.rows[0]?.types ?? [];
|
|
207
|
+
if (types.length !== 1 || types[0] !== 'number') {
|
|
208
|
+
throw new AnalyticsQueryError(`Metric field '${field}' must be numeric`);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
export function createPostgresAnalyticsQueryServices(config) {
|
|
213
|
+
const pool = new Pool(config);
|
|
214
|
+
return {
|
|
215
|
+
queries: new PostgresAnalyticsQueryService(pool),
|
|
216
|
+
close: () => pool.end(),
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
function optionalString(value, name) {
|
|
220
|
+
if (value === undefined)
|
|
221
|
+
return undefined;
|
|
222
|
+
if (typeof value !== 'string') {
|
|
223
|
+
throw new AnalyticsQueryError(`${name} must be a string`);
|
|
224
|
+
}
|
|
225
|
+
return value;
|
|
226
|
+
}
|
|
227
|
+
function requiredString(value, name) {
|
|
228
|
+
const result = optionalString(value, name);
|
|
229
|
+
if (!result || result.trim() === '') {
|
|
230
|
+
throw new AnalyticsQueryError(`${name} is required`);
|
|
231
|
+
}
|
|
232
|
+
return result;
|
|
233
|
+
}
|
|
234
|
+
function validateRequestObject(value) {
|
|
235
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
236
|
+
throw new AnalyticsQueryError('request must be an object');
|
|
237
|
+
}
|
|
238
|
+
return value;
|
|
239
|
+
}
|
|
240
|
+
function parseDateFilter(value, name) {
|
|
241
|
+
if (value === undefined)
|
|
242
|
+
return undefined;
|
|
243
|
+
if (typeof value !== 'string' && typeof value !== 'number') {
|
|
244
|
+
throw new AnalyticsQueryError(`${name} must be a string or number`);
|
|
245
|
+
}
|
|
246
|
+
const date = typeof value === 'number' || /^\d+$/.test(value) ? new Date(Number(value)) : new Date(value);
|
|
247
|
+
if (Number.isNaN(date.getTime())) {
|
|
248
|
+
throw new AnalyticsQueryError(`${name} must be a valid date`);
|
|
249
|
+
}
|
|
250
|
+
return date;
|
|
251
|
+
}
|
|
252
|
+
function parseDurationFilter(value, name) {
|
|
253
|
+
if (value === undefined)
|
|
254
|
+
return undefined;
|
|
255
|
+
if (typeof value !== 'string' && typeof value !== 'number') {
|
|
256
|
+
throw new AnalyticsQueryError(`${name} must be a number`);
|
|
257
|
+
}
|
|
258
|
+
const duration = Number(value);
|
|
259
|
+
if (!Number.isFinite(duration) || duration < 0) {
|
|
260
|
+
throw new AnalyticsQueryError(`${name} must be a non-negative number`);
|
|
261
|
+
}
|
|
262
|
+
return duration;
|
|
263
|
+
}
|
|
264
|
+
function parseAnalyticsFilterQuery(value) {
|
|
265
|
+
const stringValue = optionalString(value, 'filters');
|
|
266
|
+
if (!stringValue)
|
|
267
|
+
return [];
|
|
268
|
+
let filters;
|
|
269
|
+
try {
|
|
270
|
+
filters = JSON.parse(stringValue);
|
|
271
|
+
}
|
|
272
|
+
catch {
|
|
273
|
+
throw new AnalyticsQueryError('filters must be valid JSON');
|
|
274
|
+
}
|
|
275
|
+
return validateAnalyticsFilters(filters);
|
|
276
|
+
}
|
|
277
|
+
function validateAnalyticsFilters(value) {
|
|
278
|
+
if (value === undefined)
|
|
279
|
+
return [];
|
|
280
|
+
if (!Array.isArray(value)) {
|
|
281
|
+
throw new AnalyticsQueryError('filters must be an array');
|
|
282
|
+
}
|
|
283
|
+
return value.map(validateAnalyticsFilter);
|
|
284
|
+
}
|
|
285
|
+
function validateAnalyticsFilter(value) {
|
|
286
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
287
|
+
throw new AnalyticsQueryError('Each filter must be an object');
|
|
288
|
+
}
|
|
289
|
+
const filter = value;
|
|
290
|
+
const field = validateFieldName(filter.field, 'Filter field');
|
|
291
|
+
if (!['eq', 'exists', 'gt', 'gte', 'in', 'lt', 'lte'].includes(String(filter.operator))) {
|
|
292
|
+
throw new AnalyticsQueryError(`Filter '${field}' has an invalid operator`);
|
|
293
|
+
}
|
|
294
|
+
const operator = filter.operator;
|
|
295
|
+
if (operator === 'exists') {
|
|
296
|
+
return { field, operator };
|
|
297
|
+
}
|
|
298
|
+
if (operator === 'in') {
|
|
299
|
+
if (!Array.isArray(filter.values) || filter.values.length === 0) {
|
|
300
|
+
throw new AnalyticsQueryError(`Filter '${field}' has invalid values`);
|
|
301
|
+
}
|
|
302
|
+
const values = filter.values.map((item) => validateAnalyticsScalar(item, field));
|
|
303
|
+
const type = typeof values[0];
|
|
304
|
+
if (values.some((item) => typeof item !== type)) {
|
|
305
|
+
throw new AnalyticsQueryError(`Filter '${field}' has invalid values`);
|
|
306
|
+
}
|
|
307
|
+
return { field, operator, values };
|
|
308
|
+
}
|
|
309
|
+
if (operator === 'eq') {
|
|
310
|
+
return { field, operator, value: validateAnalyticsScalar(filter.value, field) };
|
|
311
|
+
}
|
|
312
|
+
if (typeof filter.value !== 'number' || !Number.isFinite(filter.value)) {
|
|
313
|
+
throw new AnalyticsQueryError(`Filter '${field}' has an invalid value`);
|
|
314
|
+
}
|
|
315
|
+
return { field, operator, value: filter.value };
|
|
316
|
+
}
|
|
317
|
+
function validateAnalyticsScalar(value, field) {
|
|
318
|
+
if (typeof value !== 'boolean' &&
|
|
319
|
+
typeof value !== 'string' &&
|
|
320
|
+
(typeof value !== 'number' || !Number.isFinite(value))) {
|
|
321
|
+
throw new AnalyticsQueryError(`Filter '${field}' has an invalid value`);
|
|
322
|
+
}
|
|
323
|
+
return value;
|
|
324
|
+
}
|
|
325
|
+
function validateFieldName(value, name) {
|
|
326
|
+
if (typeof value !== 'string' || !/^[A-Za-z0-9_.:-]{1,128}$/.test(value)) {
|
|
327
|
+
throw new AnalyticsQueryError(`${name} is invalid`);
|
|
328
|
+
}
|
|
329
|
+
return value;
|
|
330
|
+
}
|
|
331
|
+
function parseMetric(metric) {
|
|
332
|
+
if (!metric || typeof metric !== 'object' || Array.isArray(metric)) {
|
|
333
|
+
throw new AnalyticsQueryError('metric must be an object');
|
|
334
|
+
}
|
|
335
|
+
const record = metric;
|
|
336
|
+
if (!['count', 'rate', 'average', 'sum'].includes(String(record.operation))) {
|
|
337
|
+
throw new AnalyticsQueryError('metric operation is invalid');
|
|
338
|
+
}
|
|
339
|
+
if (record.operation === 'rate') {
|
|
340
|
+
return { operation: 'rate', filter: validateAnalyticsFilter(record.filter) };
|
|
341
|
+
}
|
|
342
|
+
if (record.operation === 'average' || record.operation === 'sum') {
|
|
343
|
+
return {
|
|
344
|
+
operation: record.operation,
|
|
345
|
+
field: validateFieldName(record.field, 'Metric field'),
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
return { operation: 'count' };
|
|
349
|
+
}
|
|
350
|
+
function parseConversationCursor(value) {
|
|
351
|
+
if (!value)
|
|
352
|
+
return undefined;
|
|
353
|
+
try {
|
|
354
|
+
const cursor = JSON.parse(Buffer.from(value, 'base64url').toString('utf8'));
|
|
355
|
+
const startedAt = new Date(String(cursor.startedAt));
|
|
356
|
+
if (Number.isNaN(startedAt.getTime()) ||
|
|
357
|
+
typeof cursor.conversationId !== 'string' ||
|
|
358
|
+
cursor.conversationId === '') {
|
|
359
|
+
throw new Error('invalid cursor');
|
|
360
|
+
}
|
|
361
|
+
return { startedAt, conversationId: cursor.conversationId };
|
|
362
|
+
}
|
|
363
|
+
catch {
|
|
364
|
+
throw new AnalyticsQueryError('lastConversationId is invalid');
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
function makeConversationCursor(row) {
|
|
368
|
+
return Buffer.from(JSON.stringify({
|
|
369
|
+
startedAt: new Date(row.started_at).toISOString(),
|
|
370
|
+
conversationId: row.conversation_id,
|
|
371
|
+
})).toString('base64url');
|
|
372
|
+
}
|
|
373
|
+
function parsePageLimit(value) {
|
|
374
|
+
const stringValue = optionalString(value, 'limit');
|
|
375
|
+
if (stringValue === undefined)
|
|
376
|
+
return 50;
|
|
377
|
+
if (!/^\d+$/.test(stringValue)) {
|
|
378
|
+
throw new AnalyticsQueryError('limit must be an integer from 1 to 100');
|
|
379
|
+
}
|
|
380
|
+
const limit = Number(stringValue);
|
|
381
|
+
if (limit < 1 || limit > 100) {
|
|
382
|
+
throw new AnalyticsQueryError('limit must be an integer from 1 to 100');
|
|
383
|
+
}
|
|
384
|
+
return limit;
|
|
385
|
+
}
|
|
386
|
+
function parseAnalyticsFieldValueCursor(value) {
|
|
387
|
+
if (!value)
|
|
388
|
+
return undefined;
|
|
389
|
+
try {
|
|
390
|
+
const cursor = JSON.parse(Buffer.from(value, 'base64url').toString('utf8'));
|
|
391
|
+
if (!Number.isSafeInteger(cursor.count) || Number(cursor.count) < 1) {
|
|
392
|
+
throw new Error('invalid cursor');
|
|
393
|
+
}
|
|
394
|
+
return {
|
|
395
|
+
count: Number(cursor.count),
|
|
396
|
+
value: validateCursorScalar(cursor.value),
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
catch {
|
|
400
|
+
throw new AnalyticsQueryError('cursor is invalid');
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
function validateCursorScalar(value) {
|
|
404
|
+
if (typeof value !== 'boolean' &&
|
|
405
|
+
typeof value !== 'string' &&
|
|
406
|
+
(typeof value !== 'number' || !Number.isFinite(value))) {
|
|
407
|
+
throw new Error('invalid cursor');
|
|
408
|
+
}
|
|
409
|
+
return value;
|
|
410
|
+
}
|
|
411
|
+
function makeAnalyticsFieldValueCursor(row) {
|
|
412
|
+
return Buffer.from(JSON.stringify({
|
|
413
|
+
count: Number(row.occurrence_count),
|
|
414
|
+
value: row.value,
|
|
415
|
+
})).toString('base64url');
|
|
416
|
+
}
|
|
417
|
+
function conversationRowToJson(row) {
|
|
418
|
+
return {
|
|
419
|
+
conversationId: row.conversation_id,
|
|
420
|
+
medium: row.channel,
|
|
421
|
+
agentId: row.agent_id,
|
|
422
|
+
region: row.region || undefined,
|
|
423
|
+
phoneNumber: row.phone_number || undefined,
|
|
424
|
+
duration: row.duration_seconds ?? undefined,
|
|
425
|
+
audioUrl: row.recording_url || undefined,
|
|
426
|
+
createdAt: new Date(row.started_at).getTime(),
|
|
427
|
+
endedAt: row.ended_at ? new Date(row.ended_at).getTime() : undefined,
|
|
428
|
+
analytics: analyticsScalars(row.analytics),
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
function analyticsScalars(values) {
|
|
432
|
+
return Object.fromEntries(Object.entries(values ?? {}).filter((entry) => {
|
|
433
|
+
const value = entry[1];
|
|
434
|
+
return (typeof value === 'boolean' ||
|
|
435
|
+
typeof value === 'string' ||
|
|
436
|
+
(typeof value === 'number' && Number.isFinite(value)));
|
|
437
|
+
}));
|
|
438
|
+
}
|
|
439
|
+
function buildConversationConditions(query, filters = parseAnalyticsFilterQuery(query.filters), requireAgentId = true) {
|
|
440
|
+
const values = [];
|
|
441
|
+
const bind = (value) => {
|
|
442
|
+
values.push(value);
|
|
443
|
+
return `$${values.length}`;
|
|
444
|
+
};
|
|
445
|
+
const conditions = [];
|
|
446
|
+
const from = parseDateFilter(query.from, 'from');
|
|
447
|
+
const to = parseDateFilter(query.to, 'to');
|
|
448
|
+
if (from && to && from >= to) {
|
|
449
|
+
throw new AnalyticsQueryError('from must be earlier than to');
|
|
450
|
+
}
|
|
451
|
+
const agentId = optionalString(query.agentId, 'agentId');
|
|
452
|
+
if (requireAgentId && (!agentId || agentId.trim() === '')) {
|
|
453
|
+
throw new AnalyticsQueryError('agentId is required');
|
|
454
|
+
}
|
|
455
|
+
if (agentId !== undefined && agentId.trim() === '') {
|
|
456
|
+
throw new AnalyticsQueryError('agentId is required');
|
|
457
|
+
}
|
|
458
|
+
const region = optionalString(query.region, 'region');
|
|
459
|
+
const channel = optionalString(query.channel, 'channel');
|
|
460
|
+
const phoneNumber = optionalString(query.phoneNumber, 'phoneNumber');
|
|
461
|
+
if (agentId)
|
|
462
|
+
conditions.push(`c.agent_id = ${bind(agentId)}`);
|
|
463
|
+
if (region)
|
|
464
|
+
conditions.push(`c.region = ${bind(region)}`);
|
|
465
|
+
if (channel)
|
|
466
|
+
conditions.push(`c.channel = ${bind(channel)}`);
|
|
467
|
+
if (phoneNumber)
|
|
468
|
+
conditions.push(`p.phone_number = ${bind(phoneNumber)}`);
|
|
469
|
+
if (from)
|
|
470
|
+
conditions.push(`c.started_at >= ${bind(from)}`);
|
|
471
|
+
if (to)
|
|
472
|
+
conditions.push(`c.started_at < ${bind(to)}`);
|
|
473
|
+
const minDuration = parseDurationFilter(query.minDurationSeconds, 'minDurationSeconds');
|
|
474
|
+
const maxDuration = parseDurationFilter(query.maxDurationSeconds, 'maxDurationSeconds');
|
|
475
|
+
if (minDuration !== undefined)
|
|
476
|
+
conditions.push(`p.duration_seconds >= ${bind(minDuration)}`);
|
|
477
|
+
if (maxDuration !== undefined)
|
|
478
|
+
conditions.push(`p.duration_seconds <= ${bind(maxDuration)}`);
|
|
479
|
+
if (minDuration !== undefined && maxDuration !== undefined && minDuration > maxDuration) {
|
|
480
|
+
throw new AnalyticsQueryError('minDurationSeconds must not exceed maxDurationSeconds');
|
|
481
|
+
}
|
|
482
|
+
for (const filter of filters) {
|
|
483
|
+
conditions.push(makeAnalyticsPredicate(filter, bind));
|
|
484
|
+
}
|
|
485
|
+
return { bind, conditions, from, to, values };
|
|
486
|
+
}
|
|
487
|
+
function makeAnalyticsPredicate(filter, bind) {
|
|
488
|
+
const field = bind(filter.field);
|
|
489
|
+
if (filter.operator === 'exists') {
|
|
490
|
+
return `c.analytics ? (${field}::text)`;
|
|
491
|
+
}
|
|
492
|
+
if (filter.operator === 'eq') {
|
|
493
|
+
return `c.analytics @> jsonb_build_object(${field}::text, ${bind(JSON.stringify(filter.value))}::jsonb)`;
|
|
494
|
+
}
|
|
495
|
+
if (filter.operator === 'in') {
|
|
496
|
+
return `(${filter.values
|
|
497
|
+
.map((value) => `c.analytics @> jsonb_build_object(${field}::text, ${bind(JSON.stringify(value))}::jsonb)`)
|
|
498
|
+
.join(' OR ')})`;
|
|
499
|
+
}
|
|
500
|
+
const operator = { gt: '>', gte: '>=', lt: '<', lte: '<=' }[filter.operator];
|
|
501
|
+
return (`(CASE WHEN jsonb_typeof(c.analytics -> (${field}::text)) = 'number' THEN ` +
|
|
502
|
+
`(c.analytics ->> (${field}::text))::double precision ${operator} ${bind(filter.value)} ` +
|
|
503
|
+
'ELSE false END)');
|
|
504
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Pool, PoolConfig, QueryResult } from 'pg';
|
|
2
|
+
import { AnalyticsScalar, AnalyticsStore, ConversationRecord, ConversationRepository, PhoneCallRecord } from './analytics';
|
|
3
|
+
import { PostgresAnalyticsQueryService } from './postgres-analytics-query';
|
|
4
|
+
interface Queryable {
|
|
5
|
+
query<TResult extends Record<string, unknown> = Record<string, unknown>>(text: string, values?: unknown[]): Promise<QueryResult<TResult>>;
|
|
6
|
+
}
|
|
7
|
+
export declare class PostgresAnalytics implements AnalyticsStore {
|
|
8
|
+
private readonly database;
|
|
9
|
+
constructor(database: Queryable);
|
|
10
|
+
set(conversationId: string, agentId: string, values: Readonly<Record<string, AnalyticsScalar>>): Promise<void>;
|
|
11
|
+
clear(conversationId: string, agentId: string, fieldNames: readonly string[]): Promise<void>;
|
|
12
|
+
get(conversationId: string, agentId: string, fieldName: string): Promise<unknown>;
|
|
13
|
+
}
|
|
14
|
+
export declare class PostgresConversationRepository implements ConversationRepository {
|
|
15
|
+
private readonly pool;
|
|
16
|
+
constructor(pool: Pool);
|
|
17
|
+
saveConversation(conversation: ConversationRecord, phoneCall?: PhoneCallRecord): Promise<{
|
|
18
|
+
changed: boolean;
|
|
19
|
+
created: boolean;
|
|
20
|
+
}>;
|
|
21
|
+
private upsertConversation;
|
|
22
|
+
private upsertPhoneCall;
|
|
23
|
+
}
|
|
24
|
+
export declare function migrateAnalyticsDatabase(pool: Pool): Promise<void>;
|
|
25
|
+
export interface PostgresAnalyticsServices {
|
|
26
|
+
analytics: PostgresAnalytics;
|
|
27
|
+
conversations: PostgresConversationRepository;
|
|
28
|
+
queries: PostgresAnalyticsQueryService;
|
|
29
|
+
close(): Promise<void>;
|
|
30
|
+
}
|
|
31
|
+
export declare function createPostgresAnalyticsServices(config: PoolConfig): Promise<PostgresAnalyticsServices>;
|
|
32
|
+
export {};
|
|
33
|
+
//# sourceMappingURL=postgres-analytics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postgres-analytics.d.ts","sourceRoot":"","sources":["../../src/analytics/postgres-analytics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAc,UAAU,EAAE,WAAW,EAAE,MAAM,IAAI,CAAA;AAE9D,OAAO,EACH,eAAe,EACf,cAAc,EACd,kBAAkB,EAClB,sBAAsB,EACtB,eAAe,EAElB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,6BAA6B,EAAE,MAAM,4BAA4B,CAAA;AAI1E,UAAU,SAAS;IACf,KAAK,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnE,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,OAAO,EAAE,GACnB,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAA;CACnC;AAID,qBAAa,iBAAkB,YAAW,cAAc;IACxC,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,SAAS;IAE1C,GAAG,CACL,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,GAClD,OAAO,CAAC,IAAI,CAAC;IAiBV,KAAK,CACP,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,SAAS,MAAM,EAAE,GAC9B,OAAO,CAAC,IAAI,CAAC;IAYV,GAAG,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAc1F;AAgBD,qBAAa,8BAA+B,YAAW,sBAAsB;IAC7D,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,IAAI;IAEjC,gBAAgB,CAClB,YAAY,EAAE,kBAAkB,EAChC,SAAS,CAAC,EAAE,eAAe,GAC5B,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;YAuBpC,kBAAkB;YAkElB,eAAe;CAwChC;AA2FD,wBAAsB,wBAAwB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAgDxE;AA6BD,MAAM,WAAW,yBAAyB;IACtC,SAAS,EAAE,iBAAiB,CAAA;IAC5B,aAAa,EAAE,8BAA8B,CAAA;IAC7C,OAAO,EAAE,6BAA6B,CAAA;IACtC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACzB;AAID,wBAAsB,+BAA+B,CACjD,MAAM,EAAE,UAAU,GACnB,OAAO,CAAC,yBAAyB,CAAC,CAgBpC"}
|