@recombine-ai/bosun 0.16.0 → 0.16.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/build/client/_app/immutable/assets/0.Rrc0O--C.css +1 -0
- package/build/client/_app/immutable/assets/0.Rrc0O--C.css.br +0 -0
- package/build/client/_app/immutable/assets/0.Rrc0O--C.css.gz +0 -0
- package/build/client/_app/immutable/assets/2.DtxQDOXx.css +1 -0
- package/build/client/_app/immutable/assets/2.DtxQDOXx.css.br +0 -0
- package/build/client/_app/immutable/assets/2.DtxQDOXx.css.gz +0 -0
- package/build/client/_app/immutable/assets/ReadOnlyMonacoDiff.iiWNRlR-.css +1 -0
- package/build/client/_app/immutable/assets/ReadOnlyMonacoDiff.iiWNRlR-.css.br +0 -0
- package/build/client/_app/immutable/assets/ReadOnlyMonacoDiff.iiWNRlR-.css.gz +0 -0
- package/build/client/_app/immutable/chunks/{Cyai3SOj.js → B1HdnQRQ.js} +1 -1
- package/build/client/_app/immutable/chunks/B1HdnQRQ.js.br +0 -0
- package/build/client/_app/immutable/chunks/B1HdnQRQ.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{uLGP0py1.js → B5zf3x62.js} +1 -1
- package/build/client/_app/immutable/chunks/B5zf3x62.js.br +0 -0
- package/build/client/_app/immutable/chunks/B5zf3x62.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{Buo-57fF.js → BHHfrjbV.js} +1 -1
- package/build/client/_app/immutable/chunks/BHHfrjbV.js.br +2 -0
- package/build/client/_app/immutable/chunks/BHHfrjbV.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BbGYcfPY.js +3 -0
- package/build/client/_app/immutable/chunks/BbGYcfPY.js.br +0 -0
- package/build/client/_app/immutable/chunks/BbGYcfPY.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{CX0Ekq8t.js → Bmd5zhWC.js} +1 -1
- package/build/client/_app/immutable/chunks/Bmd5zhWC.js.br +0 -0
- package/build/client/_app/immutable/chunks/Bmd5zhWC.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{Dslf9OwW.js → BnqH7p3U.js} +1 -1
- package/build/client/_app/immutable/chunks/BnqH7p3U.js.br +0 -0
- package/build/client/_app/immutable/chunks/BnqH7p3U.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{CJYOmGlC.js → Bog028VR.js} +1 -1
- package/build/client/_app/immutable/chunks/Bog028VR.js.br +0 -0
- package/build/client/_app/immutable/chunks/Bog028VR.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{iAhzu4tv.js → Bv1mNXs0.js} +1 -1
- package/build/client/_app/immutable/chunks/Bv1mNXs0.js.br +0 -0
- package/build/client/_app/immutable/chunks/Bv1mNXs0.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{BD9x_mnu.js → BvjXTrOz.js} +1 -1
- package/build/client/_app/immutable/chunks/BvjXTrOz.js.br +0 -0
- package/build/client/_app/immutable/chunks/BvjXTrOz.js.gz +0 -0
- package/build/client/_app/immutable/chunks/C1R-s4aD.js +1 -0
- package/build/client/_app/immutable/chunks/C1R-s4aD.js.br +0 -0
- package/build/client/_app/immutable/chunks/C1R-s4aD.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{DCuEIs0S.js → CC1OcqhR.js} +1 -1
- package/build/client/_app/immutable/chunks/CC1OcqhR.js.br +0 -0
- package/build/client/_app/immutable/chunks/CC1OcqhR.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CEHsomMo.js +1 -0
- package/build/client/_app/immutable/chunks/CEHsomMo.js.br +0 -0
- package/build/client/_app/immutable/chunks/CEHsomMo.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{CVlsAO8k.js → CJcZ2GVC.js} +1 -1
- package/build/client/_app/immutable/chunks/CJcZ2GVC.js.br +0 -0
- package/build/client/_app/immutable/chunks/CJcZ2GVC.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{DJriQKD9.js → CN555stc.js} +1 -1
- package/build/client/_app/immutable/chunks/CN555stc.js.br +0 -0
- package/build/client/_app/immutable/chunks/CN555stc.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CQg2Mme0.js +9 -0
- package/build/client/_app/immutable/chunks/CQg2Mme0.js.br +0 -0
- package/build/client/_app/immutable/chunks/CQg2Mme0.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{CXESoUel.js → Cp_st-64.js} +1 -1
- package/build/client/_app/immutable/chunks/Cp_st-64.js.br +0 -0
- package/build/client/_app/immutable/chunks/Cp_st-64.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{CPXdAKdv.js → D8mA-uZ4.js} +1 -1
- package/build/client/_app/immutable/chunks/D8mA-uZ4.js.br +0 -0
- package/build/client/_app/immutable/chunks/D8mA-uZ4.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{Ca197UDq.js → DCXjBDmY.js} +1 -1
- package/build/client/_app/immutable/chunks/{Ca197UDq.js.br → DCXjBDmY.js.br} +0 -0
- package/build/client/_app/immutable/chunks/DCXjBDmY.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DSLyVE1P.js +1 -0
- package/build/client/_app/immutable/chunks/DSLyVE1P.js.br +0 -0
- package/build/client/_app/immutable/chunks/DSLyVE1P.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{07xNIa59.js → Ddv5LgEc.js} +1 -1
- package/build/client/_app/immutable/chunks/Ddv5LgEc.js.br +0 -0
- package/build/client/_app/immutable/chunks/Ddv5LgEc.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{nYD9wsyN.js → DfcDjAv-.js} +1 -1
- package/build/client/_app/immutable/chunks/DfcDjAv-.js.br +0 -0
- package/build/client/_app/immutable/chunks/DfcDjAv-.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{D-B5X35l.js → Dg0A8wPA.js} +1 -1
- package/build/client/_app/immutable/chunks/Dg0A8wPA.js.br +0 -0
- package/build/client/_app/immutable/chunks/Dg0A8wPA.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{BPNEONy5.js → Dm49pcMm.js} +1 -1
- package/build/client/_app/immutable/chunks/Dm49pcMm.js.br +0 -0
- package/build/client/_app/immutable/chunks/Dm49pcMm.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{BI42X8h_.js → DneQQ7D5.js} +1 -1
- package/build/client/_app/immutable/chunks/DneQQ7D5.js.br +0 -0
- package/build/client/_app/immutable/chunks/DneQQ7D5.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{C39ai1md.js → DoD3q5w5.js} +1 -1
- package/build/client/_app/immutable/chunks/DoD3q5w5.js.br +0 -0
- package/build/client/_app/immutable/chunks/DoD3q5w5.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{BLu86SbA.js → DtXXy94i.js} +1 -1
- package/build/client/_app/immutable/chunks/DtXXy94i.js.br +0 -0
- package/build/client/_app/immutable/chunks/DtXXy94i.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{CAjPRvNs.js → Dy2CFyD6.js} +1 -1
- package/build/client/_app/immutable/chunks/Dy2CFyD6.js.br +0 -0
- package/build/client/_app/immutable/chunks/Dy2CFyD6.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DyBwTDJp.js +2 -0
- package/build/client/_app/immutable/chunks/DyBwTDJp.js.br +0 -0
- package/build/client/_app/immutable/chunks/DyBwTDJp.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{BsDZe4N6.js → ILTCveYH.js} +1 -1
- package/build/client/_app/immutable/chunks/ILTCveYH.js.br +0 -0
- package/build/client/_app/immutable/chunks/ILTCveYH.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{Bj8jfBTi.js → UqjCSZmA.js} +1 -1
- package/build/client/_app/immutable/chunks/UqjCSZmA.js.br +0 -0
- package/build/client/_app/immutable/chunks/UqjCSZmA.js.gz +0 -0
- package/build/client/_app/immutable/chunks/_YcrHZ6P.js +1 -0
- package/build/client/_app/immutable/chunks/_YcrHZ6P.js.br +2 -0
- package/build/client/_app/immutable/chunks/_YcrHZ6P.js.gz +0 -0
- package/build/client/_app/immutable/chunks/i6ygh6h8.js +1 -0
- package/build/client/_app/immutable/chunks/i6ygh6h8.js.br +2 -0
- package/build/client/_app/immutable/chunks/i6ygh6h8.js.gz +0 -0
- package/build/client/_app/immutable/chunks/oRi68ch3.js +1 -0
- package/build/client/_app/immutable/chunks/oRi68ch3.js.br +0 -0
- package/build/client/_app/immutable/chunks/oRi68ch3.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{BJTwdUYr.js → pPpIn6tB.js} +1 -1
- package/build/client/_app/immutable/chunks/pPpIn6tB.js.br +0 -0
- package/build/client/_app/immutable/chunks/pPpIn6tB.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{C7he4XPB.js → r0sHOWrM.js} +1 -1
- package/build/client/_app/immutable/chunks/r0sHOWrM.js.br +0 -0
- package/build/client/_app/immutable/chunks/r0sHOWrM.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{CaHl3dME.js → wcTQUnZO.js} +1 -1
- package/build/client/_app/immutable/chunks/wcTQUnZO.js.br +0 -0
- package/build/client/_app/immutable/chunks/wcTQUnZO.js.gz +0 -0
- package/build/client/_app/immutable/entry/{app.Du7JgOF0.js → app.DdO0gkPg.js} +2 -2
- package/build/client/_app/immutable/entry/app.DdO0gkPg.js.br +0 -0
- package/build/client/_app/immutable/entry/app.DdO0gkPg.js.gz +0 -0
- package/build/client/_app/immutable/entry/start.eAjDq0c9.js +1 -0
- package/build/client/_app/immutable/entry/start.eAjDq0c9.js.br +2 -0
- package/build/client/_app/immutable/entry/start.eAjDq0c9.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{0.EJrjlOP2.js → 0.nG3DdvIX.js} +1 -1
- package/build/client/_app/immutable/nodes/0.nG3DdvIX.js.br +0 -0
- package/build/client/_app/immutable/nodes/0.nG3DdvIX.js.gz +0 -0
- package/build/client/_app/immutable/nodes/1.Ceu0XS6v.js +1 -0
- package/build/client/_app/immutable/nodes/1.Ceu0XS6v.js.br +0 -0
- package/build/client/_app/immutable/nodes/1.Ceu0XS6v.js.gz +0 -0
- package/build/client/_app/immutable/nodes/10.dm2dgy31.js +13 -0
- package/build/client/_app/immutable/nodes/10.dm2dgy31.js.br +0 -0
- package/build/client/_app/immutable/nodes/10.dm2dgy31.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{15.BFy4oAT6.js → 15.D2I0y3ys.js} +1 -1
- package/build/client/_app/immutable/nodes/15.D2I0y3ys.js.br +0 -0
- package/build/client/_app/immutable/nodes/15.D2I0y3ys.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{17.DQQN2LTu.js → 17.CKxGp0E7.js} +1 -1
- package/build/client/_app/immutable/nodes/17.CKxGp0E7.js.br +0 -0
- package/build/client/_app/immutable/nodes/17.CKxGp0E7.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{18.Dx1VeGYs.js → 18.DHJxyQpw.js} +1 -1
- package/build/client/_app/immutable/nodes/18.DHJxyQpw.js.br +0 -0
- package/build/client/_app/immutable/nodes/18.DHJxyQpw.js.gz +0 -0
- package/build/client/_app/immutable/nodes/2.DesR2keg.js +35 -0
- package/build/client/_app/immutable/nodes/2.DesR2keg.js.br +0 -0
- package/build/client/_app/immutable/nodes/2.DesR2keg.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{3.D2P9M-PP.js → 3.BUKrXGR_.js} +1 -1
- package/build/client/_app/immutable/nodes/3.BUKrXGR_.js.br +0 -0
- package/build/client/_app/immutable/nodes/3.BUKrXGR_.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{4.Cx97sxk5.js → 4.C8VxVbVn.js} +1 -1
- package/build/client/_app/immutable/nodes/4.C8VxVbVn.js.br +0 -0
- package/build/client/_app/immutable/nodes/4.C8VxVbVn.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{5.BAliV6Wc.js → 5.BjrnKYaA.js} +1 -1
- package/build/client/_app/immutable/nodes/5.BjrnKYaA.js.br +0 -0
- package/build/client/_app/immutable/nodes/5.BjrnKYaA.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{6.CmUnus-n.js → 6.C_hEzPrU.js} +1 -1
- package/build/client/_app/immutable/nodes/6.C_hEzPrU.js.br +0 -0
- package/build/client/_app/immutable/nodes/6.C_hEzPrU.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{8.DLYtZXzs.js → 8.BTYaOiDC.js} +1 -1
- package/build/client/_app/immutable/nodes/8.BTYaOiDC.js.br +0 -0
- package/build/client/_app/immutable/nodes/8.BTYaOiDC.js.gz +0 -0
- package/build/client/_app/immutable/nodes/9.DVspuDYY.js +2 -0
- package/build/client/_app/immutable/nodes/9.DVspuDYY.js.br +0 -0
- package/build/client/_app/immutable/nodes/9.DVspuDYY.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-D_duQDWy.js +9 -0
- package/build/server/chunks/0-D_duQDWy.js.map +1 -0
- package/build/server/chunks/1-C0HdTvXW.js +9 -0
- package/build/server/chunks/{1-kigiZghR.js.map → 1-C0HdTvXW.js.map} +1 -1
- package/build/server/chunks/10-DcfhCR4R.js +9 -0
- package/build/server/chunks/10-DcfhCR4R.js.map +1 -0
- package/build/server/chunks/15-BQcb9C_y.js +9 -0
- package/build/server/chunks/{15-BRw8wtLp.js.map → 15-BQcb9C_y.js.map} +1 -1
- package/build/server/chunks/17-DuVCTioj.js +9 -0
- package/build/server/chunks/17-DuVCTioj.js.map +1 -0
- package/build/server/chunks/18-CT0VFW_p.js +9 -0
- package/build/server/chunks/18-CT0VFW_p.js.map +1 -0
- package/build/server/chunks/2-DgTzKQAP.js +9 -0
- package/build/server/chunks/2-DgTzKQAP.js.map +1 -0
- package/build/server/chunks/3-eQMSMzXP.js +9 -0
- package/build/server/chunks/3-eQMSMzXP.js.map +1 -0
- package/build/server/chunks/4-OaAJtDqP.js +9 -0
- package/build/server/chunks/4-OaAJtDqP.js.map +1 -0
- package/build/server/chunks/5-CBdMutbv.js +9 -0
- package/build/server/chunks/{5-Cumig7Am.js.map → 5-CBdMutbv.js.map} +1 -1
- package/build/server/chunks/6-FoEi7ggm.js +9 -0
- package/build/server/chunks/{6-Ez7v6PpX.js.map → 6-FoEi7ggm.js.map} +1 -1
- package/build/server/chunks/8-B44yRkfX.js +9 -0
- package/build/server/chunks/8-B44yRkfX.js.map +1 -0
- package/build/server/chunks/9-eUjFpHzI.js +9 -0
- package/build/server/chunks/9-eUjFpHzI.js.map +1 -0
- package/build/server/chunks/{AgentSidebar-C--dGIV5.js → AgentSidebar-BWBnqHnV.js} +4 -4
- package/build/server/chunks/{AgentSidebar-C--dGIV5.js.map → AgentSidebar-BWBnqHnV.js.map} +1 -1
- package/build/server/chunks/{Button-oIUr2LUP.js → Button-DH7gdU0s.js} +2 -2
- package/build/server/chunks/{Button-oIUr2LUP.js.map → Button-DH7gdU0s.js.map} +1 -1
- package/build/server/chunks/{ChatStepTrace-CX2Zolmp.js → ChatStepTrace-BivoNYOY.js} +6 -4
- package/build/server/chunks/ChatStepTrace-BivoNYOY.js.map +1 -0
- package/build/server/chunks/{Dropdown-DfCyYHqi.js → Dropdown-DnARl86Q.js} +2 -2
- package/build/server/chunks/{Dropdown-DfCyYHqi.js.map → Dropdown-DnARl86Q.js.map} +1 -1
- package/build/server/chunks/{Icon-DadJPtVP.js → Icon-DP1YKCRV.js} +2 -2
- package/build/server/chunks/{Icon-DadJPtVP.js.map → Icon-DP1YKCRV.js.map} +1 -1
- package/build/server/chunks/{Input-R74u4cO5.js → Input-CUJ9Cg7b.js} +2 -2
- package/build/server/chunks/{Input-R74u4cO5.js.map → Input-CUJ9Cg7b.js.map} +1 -1
- package/build/server/chunks/{Modal-CAzVFw5x.js → Modal-CGJuNpZ0.js} +21 -9
- package/build/server/chunks/{Modal-CAzVFw5x.js.map → Modal-CGJuNpZ0.js.map} +1 -1
- package/build/server/chunks/{Panel-D0IY1AzO.js → Panel-zvjxe036.js} +2 -2
- package/build/server/chunks/{Panel-D0IY1AzO.js.map → Panel-zvjxe036.js.map} +1 -1
- package/build/server/chunks/{Tab-D13L_Up5.js → Tab-CUkyLqbN.js} +4 -4
- package/build/server/chunks/{Tab-D13L_Up5.js.map → Tab-CUkyLqbN.js.map} +1 -1
- package/build/server/chunks/{_layout.svelte-D4EOIHJJ.js → _layout.svelte-B-0DHjLB.js} +8 -8
- package/build/server/chunks/{_layout.svelte-D4EOIHJJ.js.map → _layout.svelte-B-0DHjLB.js.map} +1 -1
- package/build/server/chunks/{_layout.svelte-Blfto3jh.js → _layout.svelte-B88WMyk0.js} +681 -31
- package/build/server/chunks/_layout.svelte-B88WMyk0.js.map +1 -0
- package/build/server/chunks/{_layout.svelte-Dk-9LkfL.js → _layout.svelte-BnrWYuLv.js} +10 -10
- package/build/server/chunks/{_layout.svelte-Dk-9LkfL.js.map → _layout.svelte-BnrWYuLv.js.map} +1 -1
- package/build/server/chunks/{_layout.svelte-BIMexfnk.js → _layout.svelte-wi6o5Ecu.js} +14 -14
- package/build/server/chunks/{_layout.svelte-BIMexfnk.js.map → _layout.svelte-wi6o5Ecu.js.map} +1 -1
- package/build/server/chunks/{_page.svelte-DZvcjON6.js → _page.svelte-57pyhszV.js} +10 -10
- package/build/server/chunks/{_page.svelte-DZvcjON6.js.map → _page.svelte-57pyhszV.js.map} +1 -1
- package/build/server/chunks/{_page.svelte-DhhqK6z3.js → _page.svelte-BSVJ2d2G.js} +13 -12
- package/build/server/chunks/_page.svelte-BSVJ2d2G.js.map +1 -0
- package/build/server/chunks/{_page.svelte-B1erTzoN.js → _page.svelte-BoHt2cpr.js} +5 -5
- package/build/server/chunks/{_page.svelte-B1erTzoN.js.map → _page.svelte-BoHt2cpr.js.map} +1 -1
- package/build/server/chunks/{_page.svelte-CeO_ScC8.js → _page.svelte-CHgQjBQj.js} +2 -2
- package/build/server/chunks/{_page.svelte-CeO_ScC8.js.map → _page.svelte-CHgQjBQj.js.map} +1 -1
- package/build/server/chunks/{_page.svelte-CoCBnE2l.js → _page.svelte-CeS_21Ho.js} +11 -11
- package/build/server/chunks/{_page.svelte-CoCBnE2l.js.map → _page.svelte-CeS_21Ho.js.map} +1 -1
- package/build/server/chunks/{_page.svelte-D5S0QjlI.js → _page.svelte-DHSYVLoj.js} +12 -12
- package/build/server/chunks/{_page.svelte-D5S0QjlI.js.map → _page.svelte-DHSYVLoj.js.map} +1 -1
- package/build/server/chunks/{_page.svelte-xf-0yXQM.js → _page.svelte-DhFNFMnl.js} +21 -19
- package/build/server/chunks/_page.svelte-DhFNFMnl.js.map +1 -0
- package/build/server/chunks/{_page.svelte-YoDx7gDL.js → _page.svelte-h_J4lNT9.js} +6 -6
- package/build/server/chunks/{_page.svelte-YoDx7gDL.js.map → _page.svelte-h_J4lNT9.js.map} +1 -1
- package/build/server/chunks/{agents-context-w03Lz_6n.js → agents-context-CbFsZmi5.js} +2 -2
- package/build/server/chunks/{agents-context-w03Lz_6n.js.map → agents-context-CbFsZmi5.js.map} +1 -1
- package/build/server/chunks/{client-WFEvX_be.js → client-DO-hqMbT.js} +4 -4
- package/build/server/chunks/{client-WFEvX_be.js.map → client-DO-hqMbT.js.map} +1 -1
- package/build/server/chunks/{conversation-view-memory-B0PllWRL.js → conversation-view-memory-CtbUZd_L.js} +2 -2
- package/build/server/chunks/{conversation-view-memory-B0PllWRL.js.map → conversation-view-memory-CtbUZd_L.js.map} +1 -1
- package/build/server/chunks/{edit-workspace-context-biaZqjOf.js → edit-workspace-context-tyHBPujC.js} +2 -2
- package/build/server/chunks/{edit-workspace-context-biaZqjOf.js.map → edit-workspace-context-tyHBPujC.js.map} +1 -1
- package/build/server/chunks/error.svelte-DmKKN1RU.js +15 -0
- package/build/server/chunks/{error.svelte-BjIDhioc.js.map → error.svelte-DmKKN1RU.js.map} +1 -1
- package/build/server/chunks/{index-rHCWxLFZ.js → index-LMsd1ih2.js} +2 -2
- package/build/server/chunks/{index-rHCWxLFZ.js.map → index-LMsd1ih2.js.map} +1 -1
- package/build/server/chunks/{index-server-BMxlf3ZC.js → index-server-BRr5mZEq.js} +2 -2
- package/build/server/chunks/{index-server-BMxlf3ZC.js.map → index-server-BRr5mZEq.js.map} +1 -1
- package/build/server/chunks/{index2-DdOgqE2_.js → index2-ClgfzZ89.js} +3 -3
- package/build/server/chunks/{index2-DdOgqE2_.js.map → index2-ClgfzZ89.js.map} +1 -1
- package/build/server/chunks/{index3-DC4GTqD1.js → index3-BdRUAffj.js} +2 -2
- package/build/server/chunks/{index3-DC4GTqD1.js.map → index3-BdRUAffj.js.map} +1 -1
- package/build/server/chunks/{root-UeqiktJA.js → root-4q2Pr7ck.js} +2 -2
- package/build/server/chunks/{root-UeqiktJA.js.map → root-4q2Pr7ck.js.map} +1 -1
- package/build/server/chunks/{state.svelte-CLOYXiU6.js → state.svelte-Bd1i-u49.js} +3 -3
- package/build/server/chunks/{state.svelte-CLOYXiU6.js.map → state.svelte-Bd1i-u49.js.map} +1 -1
- package/build/server/index.js +4 -4
- 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 +1 -1
- package/src/backend/lib/apply-v4a-diff.spec.ts +45 -0
- package/src/backend/lib/apply-v4a-diff.ts +167 -0
- package/src/backend/roleplay/agents.ts +16 -2
- package/src/backend/roleplay/old-server.ts +18 -4
- package/src/backend/roleplay/prompt-edit-progress.ts +36 -0
- package/src/backend/roleplay/prompt-edit-proposals.ts +38 -0
- package/src/backend/roleplay/router.ts +63 -15
- package/src/backend/roleplay/step-registry.spec.ts +20 -0
- package/src/backend/roleplay/step-registry.ts +13 -2
- package/src/backend/roleplay/suggest-prompt-edit.ts +163 -0
- package/src/backend/roleplay/variants.ts +8 -4
- package/src/backend/tests/academy-json.spec.ts +32 -0
- package/src/backend/tests/academy.ts +10 -2
- package/src/backend/tests/data.ts +1 -0
- package/src/backend/tests/emulate-agents.spec.ts +106 -0
- package/src/backend/tests/emulate-agents.ts +42 -4
- package/src/backend/tests/json-field-match.ts +29 -8
- package/src/backend/tests/pii-sanitizer.spec.ts +122 -6
- package/src/backend/tests/pii-sanitizer.ts +140 -29
- package/src/backend/tests/router.ts +22 -3
- package/src/backend/tests/suite.spec.ts +20 -0
- package/src/backend/tests/suite.ts +7 -2
- package/src/lib/components/Modal.svelte +42 -13
- package/src/lib/components/Textarea.svelte +41 -0
- package/src/lib/edit/edit-workspace-context.ts +12 -0
- package/src/lib/ws-message.ts +7 -0
- package/build/client/_app/immutable/assets/0.FwR3B_mV.css +0 -1
- package/build/client/_app/immutable/assets/0.FwR3B_mV.css.br +0 -0
- package/build/client/_app/immutable/assets/0.FwR3B_mV.css.gz +0 -0
- package/build/client/_app/immutable/assets/2.DxwYfh1z.css +0 -1
- package/build/client/_app/immutable/assets/2.DxwYfh1z.css.br +0 -0
- package/build/client/_app/immutable/assets/2.DxwYfh1z.css.gz +0 -0
- package/build/client/_app/immutable/assets/Modal.tn0RQdqM.css +0 -0
- package/build/client/_app/immutable/assets/Modal.tn0RQdqM.css.br +0 -1
- package/build/client/_app/immutable/assets/Modal.tn0RQdqM.css.gz +0 -0
- 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/BD9x_mnu.js.br +0 -0
- package/build/client/_app/immutable/chunks/BD9x_mnu.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BDl2QuyN.js +0 -1
- 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/BI42X8h_.js.br +0 -0
- package/build/client/_app/immutable/chunks/BI42X8h_.js.gz +0 -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.br +0 -0
- package/build/client/_app/immutable/chunks/BLu86SbA.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BNifnXkO.js +0 -1
- package/build/client/_app/immutable/chunks/BNifnXkO.js.br +0 -2
- package/build/client/_app/immutable/chunks/BNifnXkO.js.gz +0 -0
- 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 +0 -2
- 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.br +0 -0
- package/build/client/_app/immutable/chunks/Bj8jfBTi.js.gz +0 -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/Buo-57fF.js.br +0 -0
- package/build/client/_app/immutable/chunks/Buo-57fF.js.gz +0 -0
- 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.br +0 -0
- package/build/client/_app/immutable/chunks/C7he4XPB.js.gz +0 -0
- 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.br +0 -0
- package/build/client/_app/immutable/chunks/CJYOmGlC.js.gz +0 -0
- 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.br +0 -0
- package/build/client/_app/immutable/chunks/CVlsAO8k.js.gz +0 -0
- 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/CXESoUel.js.br +0 -0
- package/build/client/_app/immutable/chunks/CXESoUel.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Ca197UDq.js.gz +0 -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 +0 -1
- package/build/client/_app/immutable/chunks/Cql_e8Of.js.br +0 -2
- package/build/client/_app/immutable/chunks/Cql_e8Of.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CxLomzuE.js +0 -1
- package/build/client/_app/immutable/chunks/CxLomzuE.js.br +0 -0
- package/build/client/_app/immutable/chunks/CxLomzuE.js.gz +0 -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/CyvQWZoe.js +0 -8
- 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 +0 -1
- package/build/client/_app/immutable/chunks/CzXNWL4m.js.br +0 -1
- package/build/client/_app/immutable/chunks/CzXNWL4m.js.gz +0 -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/DCuEIs0S.js.br +0 -0
- package/build/client/_app/immutable/chunks/DCuEIs0S.js.gz +0 -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/Dslf9OwW.js.br +0 -0
- package/build/client/_app/immutable/chunks/Dslf9OwW.js.gz +0 -0
- package/build/client/_app/immutable/chunks/QpaC6J6s.js +0 -1
- 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/_U9sB4BM.js +0 -3
- package/build/client/_app/immutable/chunks/_U9sB4BM.js.br +0 -0
- package/build/client/_app/immutable/chunks/_U9sB4BM.js.gz +0 -0
- 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/nYD9wsyN.js.br +0 -0
- package/build/client/_app/immutable/chunks/nYD9wsyN.js.gz +0 -0
- 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.Du7JgOF0.js.br +0 -0
- package/build/client/_app/immutable/entry/app.Du7JgOF0.js.gz +0 -0
- package/build/client/_app/immutable/entry/start.BssSvo4L.js +0 -1
- package/build/client/_app/immutable/entry/start.BssSvo4L.js.br +0 -2
- package/build/client/_app/immutable/entry/start.BssSvo4L.js.gz +0 -0
- package/build/client/_app/immutable/nodes/0.EJrjlOP2.js.br +0 -0
- package/build/client/_app/immutable/nodes/0.EJrjlOP2.js.gz +0 -0
- package/build/client/_app/immutable/nodes/1.BX3yW9Ki.js +0 -1
- package/build/client/_app/immutable/nodes/1.BX3yW9Ki.js.br +0 -0
- package/build/client/_app/immutable/nodes/1.BX3yW9Ki.js.gz +0 -0
- package/build/client/_app/immutable/nodes/10.HnX8Jhtn.js +0 -13
- package/build/client/_app/immutable/nodes/10.HnX8Jhtn.js.br +0 -0
- package/build/client/_app/immutable/nodes/10.HnX8Jhtn.js.gz +0 -0
- 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.DQQN2LTu.js.br +0 -0
- package/build/client/_app/immutable/nodes/17.DQQN2LTu.js.gz +0 -0
- package/build/client/_app/immutable/nodes/18.Dx1VeGYs.js.br +0 -0
- package/build/client/_app/immutable/nodes/18.Dx1VeGYs.js.gz +0 -0
- package/build/client/_app/immutable/nodes/2.BSZUitGm.js +0 -35
- package/build/client/_app/immutable/nodes/2.BSZUitGm.js.br +0 -0
- package/build/client/_app/immutable/nodes/2.BSZUitGm.js.gz +0 -0
- package/build/client/_app/immutable/nodes/3.D2P9M-PP.js.br +0 -0
- package/build/client/_app/immutable/nodes/3.D2P9M-PP.js.gz +0 -0
- package/build/client/_app/immutable/nodes/4.Cx97sxk5.js.br +0 -0
- package/build/client/_app/immutable/nodes/4.Cx97sxk5.js.gz +0 -0
- package/build/client/_app/immutable/nodes/5.BAliV6Wc.js.br +0 -0
- package/build/client/_app/immutable/nodes/5.BAliV6Wc.js.gz +0 -0
- package/build/client/_app/immutable/nodes/6.CmUnus-n.js.br +0 -0
- package/build/client/_app/immutable/nodes/6.CmUnus-n.js.gz +0 -0
- package/build/client/_app/immutable/nodes/8.DLYtZXzs.js.br +0 -0
- package/build/client/_app/immutable/nodes/8.DLYtZXzs.js.gz +0 -0
- package/build/client/_app/immutable/nodes/9.DQ0jyQBU.js +0 -2
- package/build/client/_app/immutable/nodes/9.DQ0jyQBU.js.br +0 -0
- package/build/client/_app/immutable/nodes/9.DQ0jyQBU.js.gz +0 -0
- package/build/server/chunks/0-DB4bFp_f.js +0 -9
- package/build/server/chunks/0-DB4bFp_f.js.map +0 -1
- package/build/server/chunks/1-kigiZghR.js +0 -9
- package/build/server/chunks/10-C49_L5kn.js +0 -9
- package/build/server/chunks/10-C49_L5kn.js.map +0 -1
- package/build/server/chunks/15-BRw8wtLp.js +0 -9
- package/build/server/chunks/17-Dbb76ckK.js +0 -9
- package/build/server/chunks/17-Dbb76ckK.js.map +0 -1
- package/build/server/chunks/18-CvqluQBN.js +0 -9
- package/build/server/chunks/18-CvqluQBN.js.map +0 -1
- package/build/server/chunks/2-JGarRt-z.js +0 -9
- package/build/server/chunks/2-JGarRt-z.js.map +0 -1
- package/build/server/chunks/3-CnXV_OO3.js +0 -9
- package/build/server/chunks/3-CnXV_OO3.js.map +0 -1
- package/build/server/chunks/4-B-XLuotH.js +0 -9
- package/build/server/chunks/4-B-XLuotH.js.map +0 -1
- package/build/server/chunks/5-Cumig7Am.js +0 -9
- package/build/server/chunks/6-Ez7v6PpX.js +0 -9
- package/build/server/chunks/8-COGeKy3N.js +0 -9
- package/build/server/chunks/8-COGeKy3N.js.map +0 -1
- package/build/server/chunks/9-DlMHnRdZ.js +0 -9
- package/build/server/chunks/9-DlMHnRdZ.js.map +0 -1
- package/build/server/chunks/ChatStepTrace-CX2Zolmp.js.map +0 -1
- package/build/server/chunks/_layout.svelte-Blfto3jh.js.map +0 -1
- package/build/server/chunks/_page.svelte-DhhqK6z3.js.map +0 -1
- package/build/server/chunks/_page.svelte-xf-0yXQM.js.map +0 -1
- package/build/server/chunks/error.svelte-BjIDhioc.js +0 -15
|
@@ -1,11 +1,22 @@
|
|
|
1
1
|
import type { Logger, StepDef } from '@recombine-ai/engine'
|
|
2
2
|
|
|
3
|
-
export
|
|
3
|
+
export type PromptOverrides = Record<string, string>
|
|
4
|
+
|
|
5
|
+
export function createStepRegistry(logger: Logger, initialOverrides: PromptOverrides = {}) {
|
|
4
6
|
const steps: StepDef[] = []
|
|
7
|
+
let promptOverrides = { ...initialOverrides }
|
|
5
8
|
return {
|
|
6
9
|
addStep(def: StepDef) {
|
|
10
|
+
const originalContent = def.prompt.content.bind(def.prompt)
|
|
11
|
+
def.prompt.content = async () => {
|
|
12
|
+
const override = promptOverrides[def.name]
|
|
13
|
+
return typeof override === 'string' ? override : originalContent()
|
|
14
|
+
}
|
|
7
15
|
steps.push(def)
|
|
8
16
|
},
|
|
9
|
-
getSteps: () => steps
|
|
17
|
+
getSteps: () => steps,
|
|
18
|
+
setPromptOverrides(next: PromptOverrides) {
|
|
19
|
+
promptOverrides = { ...next }
|
|
20
|
+
}
|
|
10
21
|
}
|
|
11
22
|
}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import OpenAI from 'openai'
|
|
2
|
+
|
|
3
|
+
import { applyV4ADiff } from '../lib/apply-v4a-diff'
|
|
4
|
+
import type { PromptEditProgressPhase } from './prompt-edit-progress'
|
|
5
|
+
|
|
6
|
+
const MODEL = 'gpt-5.4'
|
|
7
|
+
const VIRTUAL_PROMPT_PATH = 'prompt.md'
|
|
8
|
+
const MAX_PATCH_ROUNDS = 8
|
|
9
|
+
|
|
10
|
+
type ApplyPatchCall = {
|
|
11
|
+
type: 'apply_patch_call'
|
|
12
|
+
call_id: string
|
|
13
|
+
operation: {
|
|
14
|
+
type: 'create_file' | 'update_file' | 'delete_file'
|
|
15
|
+
path: string
|
|
16
|
+
diff?: string
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export async function suggestPromptEdit(input: {
|
|
21
|
+
request: string
|
|
22
|
+
originalPrompt: string
|
|
23
|
+
onProgress?: (progress: {
|
|
24
|
+
phase: PromptEditProgressPhase
|
|
25
|
+
activity: number
|
|
26
|
+
summary: string
|
|
27
|
+
}) => void
|
|
28
|
+
}): Promise<string> {
|
|
29
|
+
const apiKey = process.env.OPENAI_API_KEY
|
|
30
|
+
if (!apiKey) throw new Error('OPENAI_API_KEY is not set')
|
|
31
|
+
|
|
32
|
+
const client = new OpenAI({ apiKey })
|
|
33
|
+
let virtualPrompt = input.originalPrompt
|
|
34
|
+
let activity = 0
|
|
35
|
+
let modelRound = 0
|
|
36
|
+
let reasoningSummary = ''
|
|
37
|
+
const handleEvent = (event: any) => {
|
|
38
|
+
activity += 1
|
|
39
|
+
if (
|
|
40
|
+
event?.type === 'response.reasoning_summary_text.delta' &&
|
|
41
|
+
typeof event.delta === 'string'
|
|
42
|
+
) {
|
|
43
|
+
reasoningSummary += event.delta
|
|
44
|
+
}
|
|
45
|
+
input.onProgress?.({
|
|
46
|
+
phase: progressPhase(event, modelRound),
|
|
47
|
+
activity,
|
|
48
|
+
summary: reasoningSummary.trim()
|
|
49
|
+
})
|
|
50
|
+
}
|
|
51
|
+
let response = await createResponse(client, {
|
|
52
|
+
input: buildPrompt(input.request, input.originalPrompt),
|
|
53
|
+
onEvent: handleEvent
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
for (let patchRound = 0; patchRound < MAX_PATCH_ROUNDS; patchRound += 1) {
|
|
57
|
+
const patchCalls = (response.output as unknown as ApplyPatchCall[]).filter(
|
|
58
|
+
(item) => item?.type === 'apply_patch_call'
|
|
59
|
+
)
|
|
60
|
+
if (!patchCalls.length) return virtualPrompt
|
|
61
|
+
|
|
62
|
+
const outputs = patchCalls.map((call) => {
|
|
63
|
+
try {
|
|
64
|
+
virtualPrompt = applyPromptOperation(virtualPrompt, call.operation)
|
|
65
|
+
return {
|
|
66
|
+
type: 'apply_patch_call_output',
|
|
67
|
+
call_id: call.call_id,
|
|
68
|
+
status: 'completed',
|
|
69
|
+
output: `Updated ${VIRTUAL_PROMPT_PATH} in memory`
|
|
70
|
+
}
|
|
71
|
+
} catch (error) {
|
|
72
|
+
return {
|
|
73
|
+
type: 'apply_patch_call_output',
|
|
74
|
+
call_id: call.call_id,
|
|
75
|
+
status: 'failed',
|
|
76
|
+
output: error instanceof Error ? error.message : String(error)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
reasoningSummary = ''
|
|
82
|
+
input.onProgress?.({ phase: 'reviewing', activity, summary: '' })
|
|
83
|
+
modelRound += 1
|
|
84
|
+
response = await createResponse(client, {
|
|
85
|
+
previousResponseId: response.id,
|
|
86
|
+
input: outputs,
|
|
87
|
+
onEvent: handleEvent
|
|
88
|
+
})
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
throw new Error('The model did not finish editing the prompt')
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function buildPrompt(request: string, originalPrompt: string): string {
|
|
95
|
+
return `The user is asking you to modify an LLM prompt given below. Try and make minimal changes. You are not allowed to change the shape of variables, their names or their set - this is set outside.
|
|
96
|
+
|
|
97
|
+
This is their request:
|
|
98
|
+
${request}
|
|
99
|
+
|
|
100
|
+
This is the original prompt:
|
|
101
|
+
${originalPrompt}
|
|
102
|
+
`
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
async function createResponse(
|
|
106
|
+
client: OpenAI,
|
|
107
|
+
input: { input: unknown; previousResponseId?: string; onEvent: (event: any) => void }
|
|
108
|
+
): Promise<any> {
|
|
109
|
+
const stream = await (client.responses.create as any)({
|
|
110
|
+
model: MODEL,
|
|
111
|
+
instructions:
|
|
112
|
+
'The original prompt is the existing virtual file prompt.md. Use the Apply Patch tool to make the requested edit to that file. Do not create, delete, or modify any other file.',
|
|
113
|
+
input: input.input,
|
|
114
|
+
...(input.previousResponseId ? { previous_response_id: input.previousResponseId } : {}),
|
|
115
|
+
tools: [{ type: 'apply_patch' }],
|
|
116
|
+
reasoning: { effort: 'xhigh', summary: 'auto' },
|
|
117
|
+
text: { verbosity: 'low' },
|
|
118
|
+
stream: true
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
let completedResponse: any = null
|
|
122
|
+
for await (const event of stream as AsyncIterable<any>) {
|
|
123
|
+
input.onEvent(event)
|
|
124
|
+
if (event?.type === 'response.completed') completedResponse = event.response
|
|
125
|
+
if (event?.type === 'response.failed') {
|
|
126
|
+
throw new Error(event.response?.error?.message || 'OpenAI failed to suggest prompt edits')
|
|
127
|
+
}
|
|
128
|
+
if (event?.type === 'response.incomplete') {
|
|
129
|
+
throw new Error('OpenAI returned an incomplete prompt edit')
|
|
130
|
+
}
|
|
131
|
+
if (event?.type === 'error') throw new Error(event.message || 'OpenAI streaming failed')
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (!completedResponse) throw new Error('OpenAI stream ended before the prompt edit completed')
|
|
135
|
+
return completedResponse
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function progressPhase(event: any, round: number): PromptEditProgressPhase {
|
|
139
|
+
const eventType = String(event?.type || '')
|
|
140
|
+
const itemType = String(event?.item?.type || '')
|
|
141
|
+
if (eventType.includes('apply_patch') || itemType === 'apply_patch_call') return 'drafting'
|
|
142
|
+
return round > 0 ? 'reviewing' : 'thinking'
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function applyPromptOperation(
|
|
146
|
+
currentPrompt: string,
|
|
147
|
+
operation: ApplyPatchCall['operation']
|
|
148
|
+
): string {
|
|
149
|
+
const normalizedPath = String(operation.path || '')
|
|
150
|
+
.replace(/\\/g, '/')
|
|
151
|
+
.replace(/^\.\//, '')
|
|
152
|
+
.replace(/^\//, '')
|
|
153
|
+
if (normalizedPath !== VIRTUAL_PROMPT_PATH) {
|
|
154
|
+
throw new Error(`Only ${VIRTUAL_PROMPT_PATH} may be edited`)
|
|
155
|
+
}
|
|
156
|
+
if (operation.type !== 'update_file') {
|
|
157
|
+
throw new Error(`${VIRTUAL_PROMPT_PATH} already exists and may only be updated`)
|
|
158
|
+
}
|
|
159
|
+
if (typeof operation.diff !== 'string' || !operation.diff.trim()) {
|
|
160
|
+
throw new Error('Apply Patch returned an empty diff')
|
|
161
|
+
}
|
|
162
|
+
return applyV4ADiff(currentPrompt, operation.diff)
|
|
163
|
+
}
|
|
@@ -18,6 +18,7 @@ import type { AgentState } from './agents'
|
|
|
18
18
|
import { createLogger } from './logger'
|
|
19
19
|
import { createScheduler } from './scheduler'
|
|
20
20
|
import { createStepRegistry } from './step-registry'
|
|
21
|
+
import type { PromptOverrides } from './step-registry'
|
|
21
22
|
|
|
22
23
|
export type GeneratedVariant = {
|
|
23
24
|
text: string
|
|
@@ -30,8 +31,9 @@ export async function generateReplyVariants(props: {
|
|
|
30
31
|
states: AgentState[]
|
|
31
32
|
count: number
|
|
32
33
|
context: Record<string, any>
|
|
34
|
+
promptOverrides?: PromptOverrides
|
|
33
35
|
}): Promise<GeneratedVariant[]> {
|
|
34
|
-
const { agentId, region, states, count, context } = props
|
|
36
|
+
const { agentId, region, states, count, context, promptOverrides = {} } = props
|
|
35
37
|
if (!Number.isFinite(count) || count <= 0) return []
|
|
36
38
|
const targetState = states.at(-1)
|
|
37
39
|
if (!targetState) throw new Error('No saved roleplay state found for variants')
|
|
@@ -61,7 +63,8 @@ export async function generateReplyVariants(props: {
|
|
|
61
63
|
context,
|
|
62
64
|
prevState,
|
|
63
65
|
statesById,
|
|
64
|
-
message
|
|
66
|
+
message,
|
|
67
|
+
promptOverrides
|
|
65
68
|
})
|
|
66
69
|
)
|
|
67
70
|
)
|
|
@@ -161,8 +164,9 @@ async function generateSingleReplyVariant(props: {
|
|
|
161
164
|
prevState: AgentState | null
|
|
162
165
|
statesById: Map<string, AgentState>
|
|
163
166
|
message: Message
|
|
167
|
+
promptOverrides: PromptOverrides
|
|
164
168
|
}): Promise<GeneratedVariant> {
|
|
165
|
-
const { index, factory, region, context, prevState, statesById, message } = props
|
|
169
|
+
const { index, factory, region, context, prevState, statesById, message, promptOverrides } = props
|
|
166
170
|
|
|
167
171
|
const state = createVariantState(prevState?.id ?? null, index)
|
|
168
172
|
const scheduleSeed = clone(prevState?.schedule ?? {})
|
|
@@ -179,7 +183,7 @@ async function generateSingleReplyVariant(props: {
|
|
|
179
183
|
logger,
|
|
180
184
|
onUpdate: () => {}
|
|
181
185
|
})
|
|
182
|
-
const stepRegistry = createStepRegistry(logger)
|
|
186
|
+
const stepRegistry = createStepRegistry(logger, promptOverrides)
|
|
183
187
|
const stepTracer: StepTracer = {
|
|
184
188
|
addStepTrace: (trace: StepTrace) => {
|
|
185
189
|
state.history.push({
|
|
@@ -3,6 +3,38 @@ import { describe, expect, it } from 'vitest'
|
|
|
3
3
|
import { gradeJsonExpectedFields } from './json-field-match'
|
|
4
4
|
|
|
5
5
|
describe('gradeJsonExpectedFields', () => {
|
|
6
|
+
it('compares string values case-insensitively by default', () => {
|
|
7
|
+
expect(
|
|
8
|
+
gradeJsonExpectedFields(
|
|
9
|
+
'{"result":{"outcome":"NO_ANSWER","message":"Call Back Later"}}',
|
|
10
|
+
'{"result":{"outcome":"no_answer","message":"call back later"}}'
|
|
11
|
+
)
|
|
12
|
+
).toMatchObject({ pass: true, score: 1 })
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
it('compares string values case-sensitively when enabled', () => {
|
|
16
|
+
expect(
|
|
17
|
+
gradeJsonExpectedFields(
|
|
18
|
+
'{"result":{"outcome":"NO_ANSWER"}}',
|
|
19
|
+
'{"result":{"outcome":"no_answer"}}',
|
|
20
|
+
true
|
|
21
|
+
)
|
|
22
|
+
).toMatchObject({
|
|
23
|
+
pass: false,
|
|
24
|
+
score: 0,
|
|
25
|
+
reason: expect.stringContaining('$.result.outcome')
|
|
26
|
+
})
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
it('always treats object field names as case-sensitive', () => {
|
|
30
|
+
expect(
|
|
31
|
+
gradeJsonExpectedFields('{"Result":{"outcome":"NO_ANSWER"}}', '{"result":{}}')
|
|
32
|
+
).toMatchObject({
|
|
33
|
+
pass: false,
|
|
34
|
+
reason: expect.stringContaining('Missing expected field $.result')
|
|
35
|
+
})
|
|
36
|
+
})
|
|
37
|
+
|
|
6
38
|
it('ignores object key order and formatting', () => {
|
|
7
39
|
expect(
|
|
8
40
|
gradeJsonExpectedFields(
|
|
@@ -36,6 +36,7 @@ interface CsvRow {
|
|
|
36
36
|
conversation: string
|
|
37
37
|
expected_output: string
|
|
38
38
|
evaluation_mode?: string
|
|
39
|
+
case_sensitive?: boolean
|
|
39
40
|
context_mode?: string
|
|
40
41
|
similarity_threshold: number | string
|
|
41
42
|
pinned: 'TRUE' | 'FALSE'
|
|
@@ -139,13 +140,15 @@ export function cancelPromptTests(suiteKey: string): boolean {
|
|
|
139
140
|
export async function runPromptTestsManaged(
|
|
140
141
|
suite: SuiteSelection,
|
|
141
142
|
selection: PromptTestsSelection,
|
|
142
|
-
requestedConfig: PromptTestsRunConfig
|
|
143
|
+
requestedConfig: PromptTestsRunConfig,
|
|
144
|
+
promptOverrides: Record<string, string> = {}
|
|
143
145
|
): Promise<WrittenRunReport> {
|
|
144
146
|
const run = activeRuns.start(suite.suiteKey)
|
|
145
147
|
if (!run) throw new Error('Tests already running for this agent')
|
|
146
148
|
try {
|
|
147
149
|
return await runPromptTests(suite, selection, requestedConfig, {
|
|
148
150
|
signal: run.controller.signal,
|
|
151
|
+
promptOverrides,
|
|
149
152
|
setProgress: (progress) => activeRuns.setProgress(suite.suiteKey, run, progress)
|
|
150
153
|
})
|
|
151
154
|
} finally {
|
|
@@ -242,7 +245,8 @@ function toTestInputs(
|
|
|
242
245
|
? [
|
|
243
246
|
{
|
|
244
247
|
type: 'javascript',
|
|
245
|
-
value: (output: string) =>
|
|
248
|
+
value: (output: string) =>
|
|
249
|
+
gradeJsonExpectedFields(output, row.expected_output, row.case_sensitive === true)
|
|
246
250
|
}
|
|
247
251
|
]
|
|
248
252
|
: [
|
|
@@ -301,6 +305,7 @@ export class RecombineAgentProvider implements ApiProvider {
|
|
|
301
305
|
context: Context
|
|
302
306
|
mocks?: Context
|
|
303
307
|
step?: string
|
|
308
|
+
promptOverrides?: Record<string, string>
|
|
304
309
|
}
|
|
305
310
|
const testId = String(vars.testId ?? '')
|
|
306
311
|
if (testId) this.onTestStarted?.(testId)
|
|
@@ -413,6 +418,7 @@ export class RecombineAgentProvider implements ApiProvider {
|
|
|
413
418
|
logger,
|
|
414
419
|
context: vars.context || {},
|
|
415
420
|
mocks: vars.mocks,
|
|
421
|
+
promptOverrides: vars.promptOverrides,
|
|
416
422
|
abortSignal: this.abortSignal,
|
|
417
423
|
...(isMainStepName(targetStep)
|
|
418
424
|
? {}
|
|
@@ -612,6 +618,7 @@ export async function runPromptTests(
|
|
|
612
618
|
requestedConfig: PromptTestsRunConfig,
|
|
613
619
|
opts?: {
|
|
614
620
|
signal?: AbortSignal
|
|
621
|
+
promptOverrides?: Record<string, string>
|
|
615
622
|
setProgress?: (progress: MutablePromptTestsProgress) => boolean
|
|
616
623
|
}
|
|
617
624
|
): Promise<WrittenRunReport> {
|
|
@@ -684,6 +691,7 @@ export async function runPromptTests(
|
|
|
684
691
|
...(suite.region ? { region: suite.region } : {}),
|
|
685
692
|
context: test.context,
|
|
686
693
|
step: test.step,
|
|
694
|
+
promptOverrides: opts?.promptOverrides ?? {},
|
|
687
695
|
...(typeof test.mocks !== 'undefined' ? { mocks: test.mocks } : {}),
|
|
688
696
|
conversation: test.conversation,
|
|
689
697
|
stringifiedConversation: test.stringifiedConversation,
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import type { TestAgentFactory, TestAgentFactoryProps } from '@recombine-ai/bosun-lib'
|
|
2
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
3
|
+
|
|
4
|
+
const getAgentFactories = vi.hoisted(() => vi.fn())
|
|
5
|
+
|
|
6
|
+
vi.mock('../lib/get-agent-factories', () => ({ getAgentFactories }))
|
|
7
|
+
vi.mock('../lib/get-import-nonce', () => ({ getImportNonce: () => 1 }))
|
|
8
|
+
vi.mock('../lib/get-root-path', () => ({ getRootPath: async () => '/project/workflows.ts' }))
|
|
9
|
+
|
|
10
|
+
import { loadAgents } from './emulate-agents'
|
|
11
|
+
|
|
12
|
+
function textAgent(start: () => Promise<void>) {
|
|
13
|
+
return {
|
|
14
|
+
start,
|
|
15
|
+
respondToMessage: async () => {},
|
|
16
|
+
reactOnMessage: async () => {},
|
|
17
|
+
isAssigned: async () => true,
|
|
18
|
+
onFatalError: async () => {}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async function run(factory: TestAgentFactory, props: Partial<Parameters<typeof loadAgents>[0]>) {
|
|
23
|
+
getAgentFactories.mockResolvedValue({ factories: { agent: factory } })
|
|
24
|
+
await loadAgents({
|
|
25
|
+
agentId: 'agent',
|
|
26
|
+
getMessages: () => [{ sender: 'user', text: 'Hello' }],
|
|
27
|
+
sendMessage: async () => {},
|
|
28
|
+
stepTracer: { addStepTrace: () => {}, flush: async () => {} },
|
|
29
|
+
...props
|
|
30
|
+
})
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
describe('test agent context lifecycle', () => {
|
|
34
|
+
beforeEach(() => getAgentFactories.mockReset())
|
|
35
|
+
|
|
36
|
+
it('seeds trace context before creating the adapter factory', async () => {
|
|
37
|
+
let factoryContext: Record<string, unknown> | undefined
|
|
38
|
+
let lifecycleContext: Record<string, unknown> | undefined
|
|
39
|
+
const traceContext = {
|
|
40
|
+
meta: { bookingId: 'trace-booking' },
|
|
41
|
+
state: { customerName: 'Trace customer' }
|
|
42
|
+
}
|
|
43
|
+
const factory: TestAgentFactory = async (props) => {
|
|
44
|
+
factoryContext = structuredClone(props.ctx.get())
|
|
45
|
+
props.ctx.set({ meta: { bookingId: 'adapter-default' } })
|
|
46
|
+
return textAgent(async () => {
|
|
47
|
+
lifecycleContext = structuredClone(props.ctx.get())
|
|
48
|
+
})
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
await run(factory, { context: traceContext, region: 'en-gb' })
|
|
52
|
+
|
|
53
|
+
expect(factoryContext).toEqual({
|
|
54
|
+
...traceContext,
|
|
55
|
+
recombineRegion: 'en-gb'
|
|
56
|
+
})
|
|
57
|
+
expect(lifecycleContext).toEqual(factoryContext)
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
it('restores test agent data after factory initialization and retains adapter mocks', async () => {
|
|
61
|
+
let lifecycleContext: Record<string, unknown> | undefined
|
|
62
|
+
const adapterMocks = { getJob: { status: 200 } }
|
|
63
|
+
const traceContext = {
|
|
64
|
+
state: {
|
|
65
|
+
jobCard: { 'Mobile or Base booking': 'M' },
|
|
66
|
+
currentDate: '2026-08-07'
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const factory: TestAgentFactory = async (props: TestAgentFactoryProps<Record<string, any>>) => {
|
|
70
|
+
props.ctx.set(['state', 'jobCard', 'Mobile or Base booking'], 'adapter-mutated')
|
|
71
|
+
props.ctx.set({
|
|
72
|
+
state: { jobCard: {}, currentDate: '2025-10-26' },
|
|
73
|
+
mocks: adapterMocks
|
|
74
|
+
})
|
|
75
|
+
return textAgent(async () => {
|
|
76
|
+
lifecycleContext = props.ctx.get()
|
|
77
|
+
})
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
await run(factory, { context: traceContext })
|
|
81
|
+
|
|
82
|
+
expect(lifecycleContext).toEqual({ ...traceContext, mocks: adapterMocks })
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
it('keeps explicit test mocks authoritative in split context', async () => {
|
|
86
|
+
let factoryContext: Record<string, unknown> | undefined
|
|
87
|
+
let lifecycleContext: Record<string, unknown> | undefined
|
|
88
|
+
const traceContext = { meta: { bookingId: 'trace-booking' } }
|
|
89
|
+
const testMocks = { getBooking: { id: 'trace-booking' } }
|
|
90
|
+
const factory: TestAgentFactory = async (props) => {
|
|
91
|
+
factoryContext = structuredClone(props.ctx.get())
|
|
92
|
+
props.ctx.set({
|
|
93
|
+
context: { meta: { bookingId: 'adapter-default' } },
|
|
94
|
+
mocks: { getBooking: { id: 'adapter-default' } }
|
|
95
|
+
})
|
|
96
|
+
return textAgent(async () => {
|
|
97
|
+
lifecycleContext = structuredClone(props.ctx.get())
|
|
98
|
+
})
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
await run(factory, { context: traceContext, mocks: testMocks })
|
|
102
|
+
|
|
103
|
+
expect(factoryContext).toEqual({ context: traceContext, mocks: testMocks })
|
|
104
|
+
expect(lifecycleContext).toEqual(factoryContext)
|
|
105
|
+
})
|
|
106
|
+
})
|
|
@@ -21,6 +21,7 @@ export async function loadAgents(props: {
|
|
|
21
21
|
logger?: Logger
|
|
22
22
|
context?: Record<string, unknown>
|
|
23
23
|
mocks?: Record<string, unknown>
|
|
24
|
+
promptOverrides?: Record<string, string>
|
|
24
25
|
abortSignal?: AbortSignal
|
|
25
26
|
onBeforeTestResponse?: () => void
|
|
26
27
|
testStep?: {
|
|
@@ -38,6 +39,7 @@ export async function loadAgents(props: {
|
|
|
38
39
|
logger: providedLogger,
|
|
39
40
|
context,
|
|
40
41
|
mocks,
|
|
42
|
+
promptOverrides = {},
|
|
41
43
|
abortSignal,
|
|
42
44
|
onBeforeTestResponse,
|
|
43
45
|
testStep
|
|
@@ -61,7 +63,13 @@ export async function loadAgents(props: {
|
|
|
61
63
|
|
|
62
64
|
const testSteps = new Map<string, RegisteredTestStep>()
|
|
63
65
|
const stepRegistry: TestStepRegistry = {
|
|
64
|
-
addStep
|
|
66
|
+
addStep(step) {
|
|
67
|
+
const originalContent = step.prompt.content.bind(step.prompt)
|
|
68
|
+
step.prompt.content = async () => {
|
|
69
|
+
const override = promptOverrides[step.name]
|
|
70
|
+
return typeof override === 'string' ? override : originalContent()
|
|
71
|
+
}
|
|
72
|
+
},
|
|
65
73
|
addTestStep(step: RegisteredTestStep) {
|
|
66
74
|
// Step names are the current test identity. Preserve the first registration until
|
|
67
75
|
// workflow IDs become part of the persisted target.
|
|
@@ -74,14 +82,19 @@ export async function loadAgents(props: {
|
|
|
74
82
|
mocks !== null &&
|
|
75
83
|
typeof mocks === 'object' &&
|
|
76
84
|
!Array.isArray(mocks)
|
|
77
|
-
const providedContext = context
|
|
78
|
-
const
|
|
85
|
+
const providedContext = isRecord(context) ? clone(context) : {}
|
|
86
|
+
const testContext = region
|
|
79
87
|
? {
|
|
80
88
|
...providedContext,
|
|
81
89
|
recombineRegion: providedContext.recombineRegion ?? region
|
|
82
90
|
}
|
|
83
91
|
: providedContext
|
|
84
|
-
const
|
|
92
|
+
const testMocks = hasSplitContext ? clone(mocks) : undefined
|
|
93
|
+
// The factory may mutate nested values in place, so seed it with a separate clone from the
|
|
94
|
+
// authoritative test snapshot that will be restored before the agent lifecycle starts.
|
|
95
|
+
const ctx = createContext(
|
|
96
|
+
hasSplitContext ? { context: clone(testContext), mocks: clone(testMocks) } : clone(testContext)
|
|
97
|
+
)
|
|
85
98
|
|
|
86
99
|
// Maintain in-run history so sendMessage appends to it, mirroring backend behavior
|
|
87
100
|
let history: Message[] = []
|
|
@@ -112,6 +125,23 @@ export async function loadAgents(props: {
|
|
|
112
125
|
})
|
|
113
126
|
)
|
|
114
127
|
|
|
128
|
+
// Project factories need the test context while they are being created (for example, to
|
|
129
|
+
// resolve regional config), but some factories also install their own default context. Keep
|
|
130
|
+
// only an adapter-provided mocks namespace and make the test case authoritative for agent data.
|
|
131
|
+
const factoryRuntime = isRecord(ctx.get()) ? ctx.get() : {}
|
|
132
|
+
if (hasSplitContext) {
|
|
133
|
+
ctx.swap({ context: clone(testContext), mocks: clone(testMocks) })
|
|
134
|
+
} else if (isRecord(factoryRuntime.mocks)) {
|
|
135
|
+
const restoredContext = clone(testContext)
|
|
136
|
+
ctx.swap(
|
|
137
|
+
isRecord(factoryRuntime.context)
|
|
138
|
+
? { context: restoredContext, mocks: factoryRuntime.mocks }
|
|
139
|
+
: { ...restoredContext, mocks: factoryRuntime.mocks }
|
|
140
|
+
)
|
|
141
|
+
} else {
|
|
142
|
+
ctx.swap(clone(testContext))
|
|
143
|
+
}
|
|
144
|
+
|
|
115
145
|
const withAbort = wrapAbort(abortSignal)
|
|
116
146
|
|
|
117
147
|
try {
|
|
@@ -170,6 +200,14 @@ function isVoiceAgent(agent: TestAgent): agent is TestVoiceAgent {
|
|
|
170
200
|
return 'streamResponse' in agent
|
|
171
201
|
}
|
|
172
202
|
|
|
203
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
204
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value)
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function clone<T>(value: T): T {
|
|
208
|
+
return structuredClone(value)
|
|
209
|
+
}
|
|
210
|
+
|
|
173
211
|
function wrapAbort(abortSignal: AbortSignal | undefined) {
|
|
174
212
|
return async <T>(p: Promise<T>): Promise<T> => {
|
|
175
213
|
if (!abortSignal) return p
|
|
@@ -6,7 +6,12 @@ function isRecord(value: unknown): value is Record<string, unknown> {
|
|
|
6
6
|
return typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
function matchExpectedJsonFields(
|
|
9
|
+
function matchExpectedJsonFields(
|
|
10
|
+
actual: unknown,
|
|
11
|
+
expected: unknown,
|
|
12
|
+
caseSensitive: boolean,
|
|
13
|
+
path = '$'
|
|
14
|
+
): MatchResult {
|
|
10
15
|
if (isRecord(expected)) {
|
|
11
16
|
if (!isRecord(actual)) return { pass: false, reason: `Expected an object at ${path}` }
|
|
12
17
|
|
|
@@ -14,7 +19,12 @@ function matchExpectedJsonFields(actual: unknown, expected: unknown, path = '$')
|
|
|
14
19
|
if (!Object.prototype.hasOwnProperty.call(actual, key)) {
|
|
15
20
|
return { pass: false, reason: `Missing expected field ${path}.${key}` }
|
|
16
21
|
}
|
|
17
|
-
const result = matchExpectedJsonFields(
|
|
22
|
+
const result = matchExpectedJsonFields(
|
|
23
|
+
actual[key],
|
|
24
|
+
expectedValue,
|
|
25
|
+
caseSensitive,
|
|
26
|
+
`${path}.${key}`
|
|
27
|
+
)
|
|
18
28
|
if (!result.pass) return result
|
|
19
29
|
}
|
|
20
30
|
return { pass: true }
|
|
@@ -29,18 +39,29 @@ function matchExpectedJsonFields(actual: unknown, expected: unknown, path = '$')
|
|
|
29
39
|
}
|
|
30
40
|
}
|
|
31
41
|
for (let index = 0; index < expected.length; index += 1) {
|
|
32
|
-
const result = matchExpectedJsonFields(
|
|
42
|
+
const result = matchExpectedJsonFields(
|
|
43
|
+
actual[index],
|
|
44
|
+
expected[index],
|
|
45
|
+
caseSensitive,
|
|
46
|
+
`${path}[${index}]`
|
|
47
|
+
)
|
|
33
48
|
if (!result.pass) return result
|
|
34
49
|
}
|
|
35
50
|
return { pass: true }
|
|
36
51
|
}
|
|
37
52
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
53
|
+
const valuesMatch =
|
|
54
|
+
typeof actual === 'string' && typeof expected === 'string' && !caseSensitive
|
|
55
|
+
? actual.toLowerCase() === expected.toLowerCase()
|
|
56
|
+
: isDeepStrictEqual(actual, expected)
|
|
57
|
+
return valuesMatch ? { pass: true } : { pass: false, reason: `Value differs at ${path}` }
|
|
41
58
|
}
|
|
42
59
|
|
|
43
|
-
export function gradeJsonExpectedFields(
|
|
60
|
+
export function gradeJsonExpectedFields(
|
|
61
|
+
output: string,
|
|
62
|
+
expectedOutput: string,
|
|
63
|
+
caseSensitive = false
|
|
64
|
+
) {
|
|
44
65
|
let actual: unknown
|
|
45
66
|
let expected: unknown
|
|
46
67
|
try {
|
|
@@ -62,7 +83,7 @@ export function gradeJsonExpectedFields(output: string, expectedOutput: string)
|
|
|
62
83
|
}
|
|
63
84
|
}
|
|
64
85
|
|
|
65
|
-
const result = matchExpectedJsonFields(actual, expected)
|
|
86
|
+
const result = matchExpectedJsonFields(actual, expected, caseSensitive)
|
|
66
87
|
return {
|
|
67
88
|
pass: result.pass,
|
|
68
89
|
score: result.pass ? 1 : 0,
|