@recombine-ai/bosun 0.16.2-cloud-1 → 0.16.2-cloud-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/_app/immutable/assets/0.CDmx-FLf.css +1 -0
- package/build/_app/immutable/assets/0.CDmx-FLf.css.br +0 -0
- package/build/_app/immutable/assets/0.CDmx-FLf.css.gz +0 -0
- package/build/_app/immutable/assets/{2.Dc5_ru9X.css → 2.C-ckNQUz.css} +1 -1
- package/build/_app/immutable/assets/2.C-ckNQUz.css.br +0 -0
- package/build/_app/immutable/assets/2.C-ckNQUz.css.gz +0 -0
- package/build/_app/immutable/chunks/12bfCwgn.js +2 -0
- package/build/_app/immutable/chunks/12bfCwgn.js.br +0 -0
- package/build/_app/immutable/chunks/12bfCwgn.js.gz +0 -0
- package/build/_app/immutable/chunks/{C-Qcqb3K.js → 6OCsQ6r7.js} +2 -2
- package/build/_app/immutable/chunks/6OCsQ6r7.js.br +0 -0
- package/build/_app/immutable/chunks/6OCsQ6r7.js.gz +0 -0
- package/build/_app/immutable/chunks/AvXp07rr.js +1 -0
- package/build/_app/immutable/chunks/AvXp07rr.js.br +2 -0
- package/build/_app/immutable/chunks/AvXp07rr.js.gz +0 -0
- package/build/_app/immutable/chunks/{OYhYuonT.js → B434V0h8.js} +1 -1
- package/build/_app/immutable/chunks/B434V0h8.js.br +0 -0
- package/build/_app/immutable/chunks/B434V0h8.js.gz +0 -0
- package/build/_app/immutable/chunks/BJqZY8o2.js +1 -0
- package/build/_app/immutable/chunks/BJqZY8o2.js.br +0 -0
- package/build/_app/immutable/chunks/BJqZY8o2.js.gz +0 -0
- package/build/_app/immutable/chunks/{DHvIizf-.js → BKQbRSey.js} +1 -1
- package/build/_app/immutable/chunks/BKQbRSey.js.br +0 -0
- package/build/_app/immutable/chunks/BKQbRSey.js.gz +0 -0
- package/build/_app/immutable/chunks/BOHUKGg_.js +1 -0
- package/build/_app/immutable/chunks/BOHUKGg_.js.br +0 -0
- package/build/_app/immutable/chunks/BOHUKGg_.js.gz +0 -0
- package/build/_app/immutable/chunks/BP0Xadq7.js +5 -0
- package/build/_app/immutable/chunks/BP0Xadq7.js.br +0 -0
- package/build/_app/immutable/chunks/BP0Xadq7.js.gz +0 -0
- package/build/_app/immutable/chunks/BT98u4gR.js +35 -0
- package/build/_app/immutable/chunks/BT98u4gR.js.br +0 -0
- package/build/_app/immutable/chunks/BT98u4gR.js.gz +0 -0
- package/build/_app/immutable/chunks/{DjqcYvLr.js → Bc1oIj2c.js} +1 -1
- package/build/_app/immutable/chunks/Bc1oIj2c.js.br +0 -0
- package/build/_app/immutable/chunks/Bc1oIj2c.js.gz +0 -0
- package/build/_app/immutable/chunks/{CWB6mNDX.js → BiDy9-HP.js} +1 -1
- package/build/_app/immutable/chunks/BiDy9-HP.js.br +0 -0
- package/build/_app/immutable/chunks/BiDy9-HP.js.gz +0 -0
- package/build/_app/immutable/chunks/{BEa3nvFX.js → By9tvIIw.js} +1 -1
- package/build/_app/immutable/chunks/By9tvIIw.js.br +0 -0
- package/build/_app/immutable/chunks/By9tvIIw.js.gz +0 -0
- package/build/_app/immutable/chunks/Byx1piFp.js +3 -0
- package/build/_app/immutable/chunks/Byx1piFp.js.br +0 -0
- package/build/_app/immutable/chunks/Byx1piFp.js.gz +0 -0
- package/build/_app/immutable/chunks/{DSaIAZ57.js → C1TsmEOe.js} +1 -1
- package/build/_app/immutable/chunks/C1TsmEOe.js.br +0 -0
- package/build/_app/immutable/chunks/C1TsmEOe.js.gz +0 -0
- package/build/_app/immutable/chunks/CGV7fMmX.js +1 -0
- package/build/_app/immutable/chunks/CGV7fMmX.js.br +0 -0
- package/build/_app/immutable/chunks/CGV7fMmX.js.gz +0 -0
- package/build/_app/immutable/chunks/CL717zGu.js +2 -0
- package/build/_app/immutable/chunks/CL717zGu.js.br +0 -0
- package/build/_app/immutable/chunks/CL717zGu.js.gz +0 -0
- package/build/_app/immutable/chunks/{DrOC9WNt.js → CPCsWwEy.js} +1 -1
- package/build/_app/immutable/chunks/CPCsWwEy.js.br +0 -0
- package/build/_app/immutable/chunks/{DrOC9WNt.js.gz → CPCsWwEy.js.gz} +0 -0
- package/build/_app/immutable/chunks/{Ds1yKsjr.js → CUZn05nQ.js} +2 -2
- package/build/_app/immutable/chunks/CUZn05nQ.js.br +0 -0
- package/build/_app/immutable/chunks/{Ds1yKsjr.js.gz → CUZn05nQ.js.gz} +0 -0
- package/build/_app/immutable/chunks/{ClP8OL3G.js → CZMMlaMl.js} +1 -1
- package/build/_app/immutable/chunks/CZMMlaMl.js.br +0 -0
- package/build/_app/immutable/chunks/CZMMlaMl.js.gz +0 -0
- package/build/_app/immutable/chunks/{DLL_0B-9.js → C_yvzB4Z.js} +1 -1
- package/build/_app/immutable/chunks/C_yvzB4Z.js.br +0 -0
- package/build/_app/immutable/chunks/{DLL_0B-9.js.gz → C_yvzB4Z.js.gz} +0 -0
- package/build/_app/immutable/chunks/{DC_-4bAG.js → CdnbUlBq.js} +1 -1
- package/build/_app/immutable/chunks/CdnbUlBq.js.br +0 -0
- package/build/_app/immutable/chunks/CdnbUlBq.js.gz +0 -0
- package/build/_app/immutable/chunks/Cf3l6QEG.js +2 -0
- package/build/_app/immutable/chunks/Cf3l6QEG.js.br +0 -0
- package/build/_app/immutable/chunks/Cf3l6QEG.js.gz +0 -0
- package/build/_app/immutable/chunks/CfzHeBbL.js +1 -0
- package/build/_app/immutable/chunks/CfzHeBbL.js.br +1 -0
- package/build/_app/immutable/chunks/CfzHeBbL.js.gz +0 -0
- package/build/_app/immutable/chunks/{BzyUIe1_.js → D1-opoqB.js} +1 -1
- package/build/_app/immutable/chunks/D1-opoqB.js.br +0 -0
- package/build/_app/immutable/chunks/D1-opoqB.js.gz +0 -0
- package/build/_app/immutable/chunks/D3fLfD-Y.js +1 -0
- package/build/_app/immutable/chunks/D3fLfD-Y.js.br +0 -0
- package/build/_app/immutable/chunks/D3fLfD-Y.js.gz +0 -0
- package/build/_app/immutable/chunks/DDZ8GqHh.js +1 -0
- package/build/_app/immutable/chunks/DDZ8GqHh.js.br +0 -0
- package/build/_app/immutable/chunks/DDZ8GqHh.js.gz +0 -0
- package/build/_app/immutable/chunks/{CH4VrfW2.js → DD_fL9ig.js} +1 -1
- package/build/_app/immutable/chunks/DD_fL9ig.js.br +0 -0
- package/build/_app/immutable/chunks/DD_fL9ig.js.gz +0 -0
- package/build/_app/immutable/chunks/{ByU1nS5x.js → DVZC5aEW.js} +1 -1
- package/build/_app/immutable/chunks/DVZC5aEW.js.br +0 -0
- package/build/_app/immutable/chunks/DVZC5aEW.js.gz +0 -0
- package/build/_app/immutable/chunks/D_MTg6YY.js +1 -0
- package/build/_app/immutable/chunks/D_MTg6YY.js.br +0 -0
- package/build/_app/immutable/chunks/D_MTg6YY.js.gz +0 -0
- package/build/_app/immutable/chunks/{C78K0g2i.js → DbZCwjKq.js} +1 -1
- package/build/_app/immutable/chunks/DbZCwjKq.js.br +0 -0
- package/build/_app/immutable/chunks/DbZCwjKq.js.gz +0 -0
- package/build/_app/immutable/chunks/Dc2hpeC4.js +1 -0
- package/build/_app/immutable/chunks/Dc2hpeC4.js.br +2 -0
- package/build/_app/immutable/chunks/Dc2hpeC4.js.gz +0 -0
- package/build/_app/immutable/chunks/{NZcW2kfJ.js → DjxKCxwY.js} +1 -1
- package/build/_app/immutable/chunks/DjxKCxwY.js.br +0 -0
- package/build/_app/immutable/chunks/DjxKCxwY.js.gz +0 -0
- package/build/_app/immutable/chunks/{DeiSJRh0.js → DkJi5BM4.js} +1 -1
- package/build/_app/immutable/chunks/DkJi5BM4.js.br +0 -0
- package/build/_app/immutable/chunks/DkJi5BM4.js.gz +0 -0
- package/build/_app/immutable/chunks/Dne1wF_T.js +1 -0
- package/build/_app/immutable/chunks/Dne1wF_T.js.br +0 -0
- package/build/_app/immutable/chunks/Dne1wF_T.js.gz +0 -0
- package/build/_app/immutable/chunks/{BlwlkbCs.js → Dt1k81ic.js} +1 -1
- package/build/_app/immutable/chunks/Dt1k81ic.js.br +0 -0
- package/build/_app/immutable/chunks/Dt1k81ic.js.gz +0 -0
- package/build/_app/immutable/chunks/{CKf4QksN.js → DugeGFnl.js} +1 -1
- package/build/_app/immutable/chunks/DugeGFnl.js.br +0 -0
- package/build/_app/immutable/chunks/DugeGFnl.js.gz +0 -0
- package/build/_app/immutable/chunks/{D5UNd3Zp.js → MIEISUXS.js} +1 -1
- package/build/_app/immutable/chunks/MIEISUXS.js.br +0 -0
- package/build/_app/immutable/chunks/MIEISUXS.js.gz +0 -0
- package/build/_app/immutable/chunks/{lyi4TUVm.js → Vn-6xHGu.js} +1 -1
- package/build/_app/immutable/chunks/Vn-6xHGu.js.br +0 -0
- package/build/_app/immutable/chunks/Vn-6xHGu.js.gz +0 -0
- package/build/_app/immutable/chunks/{jk4Hz_9M.js → krcqaNpB.js} +1 -1
- package/build/_app/immutable/chunks/krcqaNpB.js.br +0 -0
- package/build/_app/immutable/chunks/krcqaNpB.js.gz +0 -0
- package/build/_app/immutable/chunks/oarl--hZ.js +1 -0
- package/build/_app/immutable/chunks/oarl--hZ.js.br +0 -0
- package/build/_app/immutable/chunks/oarl--hZ.js.gz +0 -0
- package/build/_app/immutable/chunks/{CfbKmr1m.js → qrpS1hNb.js} +1 -1
- package/build/_app/immutable/chunks/qrpS1hNb.js.br +0 -0
- package/build/_app/immutable/chunks/qrpS1hNb.js.gz +0 -0
- package/build/_app/immutable/entry/app.D_IBy7uS.js +2 -0
- package/build/_app/immutable/entry/app.D_IBy7uS.js.br +0 -0
- package/build/_app/immutable/entry/app.D_IBy7uS.js.gz +0 -0
- package/build/_app/immutable/entry/start.DbNkBLf5.js +1 -0
- package/build/_app/immutable/entry/start.DbNkBLf5.js.br +0 -0
- package/build/_app/immutable/entry/start.DbNkBLf5.js.gz +0 -0
- package/build/_app/immutable/nodes/0.CS5BBLx9.js +3 -0
- package/build/_app/immutable/nodes/0.CS5BBLx9.js.br +0 -0
- package/build/_app/immutable/nodes/0.CS5BBLx9.js.gz +0 -0
- package/build/_app/immutable/nodes/1.Bx_DOFs1.js +1 -0
- package/build/_app/immutable/nodes/1.Bx_DOFs1.js.br +1 -0
- package/build/_app/immutable/nodes/1.Bx_DOFs1.js.gz +0 -0
- package/build/_app/immutable/nodes/14.DSu8i_qz.js +1 -0
- package/build/_app/immutable/nodes/14.DSu8i_qz.js.br +0 -0
- package/build/_app/immutable/nodes/14.DSu8i_qz.js.gz +0 -0
- package/build/_app/immutable/nodes/16.Cev9Grgc.js +3 -0
- package/build/_app/immutable/nodes/16.Cev9Grgc.js.br +0 -0
- package/build/_app/immutable/nodes/16.Cev9Grgc.js.gz +0 -0
- package/build/_app/immutable/nodes/17.C869oOf4.js +10 -0
- package/build/_app/immutable/nodes/17.C869oOf4.js.br +0 -0
- package/build/_app/immutable/nodes/17.C869oOf4.js.gz +0 -0
- package/build/_app/immutable/nodes/2.DdU1kSNu.js +35 -0
- package/build/_app/immutable/nodes/2.DdU1kSNu.js.br +0 -0
- package/build/_app/immutable/nodes/2.DdU1kSNu.js.gz +0 -0
- package/build/_app/immutable/nodes/3.C5QPqWTE.js +1 -0
- package/build/_app/immutable/nodes/3.C5QPqWTE.js.br +0 -0
- package/build/_app/immutable/nodes/3.C5QPqWTE.js.gz +0 -0
- package/build/_app/immutable/nodes/4.CNS3NZ4Z.js +1 -0
- package/build/_app/immutable/nodes/4.CNS3NZ4Z.js.br +0 -0
- package/build/_app/immutable/nodes/4.CNS3NZ4Z.js.gz +0 -0
- package/build/_app/immutable/nodes/5.B1H9pyMk.js +1 -0
- package/build/_app/immutable/nodes/5.B1H9pyMk.js.br +0 -0
- package/build/_app/immutable/nodes/5.B1H9pyMk.js.gz +0 -0
- package/build/_app/immutable/nodes/6.h6Y1Z_zh.js +1 -0
- package/build/_app/immutable/nodes/6.h6Y1Z_zh.js.br +0 -0
- package/build/_app/immutable/nodes/6.h6Y1Z_zh.js.gz +0 -0
- package/build/_app/immutable/nodes/8.BCatMgwB.js +2 -0
- package/build/_app/immutable/nodes/8.BCatMgwB.js.br +0 -0
- package/build/_app/immutable/nodes/8.BCatMgwB.js.gz +0 -0
- package/build/_app/immutable/nodes/9.BUnel48-.js +24 -0
- package/build/_app/immutable/nodes/9.BUnel48-.js.br +0 -0
- package/build/_app/immutable/nodes/9.BUnel48-.js.gz +0 -0
- package/build/_app/immutable/workers/{css.worker-DflDYzxC.js → css.worker-D61Wlo1y.js} +1 -1
- package/build/_app/immutable/workers/css.worker-D61Wlo1y.js.br +0 -0
- package/build/_app/immutable/workers/{css.worker-DflDYzxC.js.gz → css.worker-D61Wlo1y.js.gz} +0 -0
- package/build/_app/immutable/workers/{editor.worker-DbG82rLA.js → editor.worker-BaAK1IVA.js} +1 -1
- package/build/_app/immutable/workers/editor.worker-BaAK1IVA.js.br +0 -0
- package/build/_app/immutable/workers/{editor.worker-DbG82rLA.js.gz → editor.worker-BaAK1IVA.js.gz} +0 -0
- package/build/_app/immutable/workers/{html.worker-Bn6S4v1s.js → html.worker-i4ABlmR0.js} +1 -1
- package/build/_app/immutable/workers/html.worker-i4ABlmR0.js.br +0 -0
- package/build/_app/immutable/workers/{html.worker-Bn6S4v1s.js.gz → html.worker-i4ABlmR0.js.gz} +0 -0
- package/build/_app/immutable/workers/{json.worker-CfS7sFxM.js → json.worker-C-kBQgxp.js} +1 -1
- package/build/_app/immutable/workers/json.worker-C-kBQgxp.js.br +0 -0
- package/build/_app/immutable/workers/{json.worker-CfS7sFxM.js.gz → json.worker-C-kBQgxp.js.gz} +0 -0
- package/build/_app/immutable/workers/{ts.worker-Bqwj6xoy.js → ts.worker-KJ4wGYue.js} +2 -2
- package/build/_app/immutable/workers/ts.worker-KJ4wGYue.js.br +0 -0
- package/build/_app/immutable/workers/{ts.worker-Bqwj6xoy.js.gz → ts.worker-KJ4wGYue.js.gz} +0 -0
- package/build/_app/version.json +1 -1
- package/build/_app/version.json.br +0 -0
- package/build/_app/version.json.gz +0 -0
- package/build/index.html +13 -13
- package/build/index.html.br +0 -0
- package/build/index.html.gz +0 -0
- package/dist/index.js +616 -106
- package/dist/index.js.map +4 -4
- package/dist/types/backend/roleplay/prompt-edit-proposals.d.ts +13 -1
- package/dist/types/backend/roleplay/prompt-file.d.ts +8 -0
- package/dist/types/backend/roleplay/router.d.ts +29 -0
- package/dist/types/backend/roleplay/suggest-file-edit.d.ts +13 -0
- package/dist/types/backend/roleplay/suggest-test-fix.d.ts +29 -0
- package/dist/types/backend/server.d.ts +116 -0
- package/dist/types/backend/telescope/router.d.ts +23 -0
- package/dist/types/backend/tests/academy.d.ts +9 -1
- package/dist/types/backend/tests/data.d.ts +13 -1
- package/dist/types/backend/tests/router.d.ts +64 -0
- package/dist/types/backend/tests/suggest-test-history-edit.d.ts +21 -0
- package/dist/types/backend/tests/test-edit-source.d.ts +4 -0
- package/dist/types/backend/tests/test-history-edit-proposals.d.ts +24 -0
- package/dist/types/lib/api-telescope/types.d.ts +38 -0
- package/dist/types/lib/edit/test-ai-edit.d.ts +12 -0
- package/dist/types/lib/tests/assertion-types.d.ts +6 -0
- package/package.json +1 -1
- package/build/_app/immutable/assets/0.CyF-TaEi.css +0 -1
- package/build/_app/immutable/assets/0.CyF-TaEi.css.br +0 -0
- package/build/_app/immutable/assets/0.CyF-TaEi.css.gz +0 -0
- package/build/_app/immutable/assets/2.Dc5_ru9X.css.br +0 -0
- package/build/_app/immutable/assets/2.Dc5_ru9X.css.gz +0 -0
- package/build/_app/immutable/chunks/0Yl3erOE.js +0 -2
- package/build/_app/immutable/chunks/0Yl3erOE.js.br +0 -0
- package/build/_app/immutable/chunks/0Yl3erOE.js.gz +0 -0
- package/build/_app/immutable/chunks/797NXciN.js +0 -1
- package/build/_app/immutable/chunks/797NXciN.js.br +0 -0
- package/build/_app/immutable/chunks/797NXciN.js.gz +0 -0
- package/build/_app/immutable/chunks/9JriNUvn.js +0 -1
- package/build/_app/immutable/chunks/9JriNUvn.js.br +0 -0
- package/build/_app/immutable/chunks/9JriNUvn.js.gz +0 -0
- package/build/_app/immutable/chunks/BEa3nvFX.js.br +0 -0
- package/build/_app/immutable/chunks/BEa3nvFX.js.gz +0 -0
- package/build/_app/immutable/chunks/BOL6qRLe.js +0 -3
- package/build/_app/immutable/chunks/BOL6qRLe.js.br +0 -0
- package/build/_app/immutable/chunks/BOL6qRLe.js.gz +0 -0
- package/build/_app/immutable/chunks/BYkIDsVz.js +0 -1
- package/build/_app/immutable/chunks/BYkIDsVz.js.br +0 -0
- package/build/_app/immutable/chunks/BYkIDsVz.js.gz +0 -0
- package/build/_app/immutable/chunks/BlwlkbCs.js.br +0 -0
- package/build/_app/immutable/chunks/BlwlkbCs.js.gz +0 -0
- package/build/_app/immutable/chunks/ByU1nS5x.js.br +0 -0
- package/build/_app/immutable/chunks/ByU1nS5x.js.gz +0 -0
- package/build/_app/immutable/chunks/BzyUIe1_.js.br +0 -0
- package/build/_app/immutable/chunks/BzyUIe1_.js.gz +0 -0
- package/build/_app/immutable/chunks/C-Qcqb3K.js.br +0 -0
- package/build/_app/immutable/chunks/C-Qcqb3K.js.gz +0 -0
- package/build/_app/immutable/chunks/C-qso1Pb.js +0 -2
- package/build/_app/immutable/chunks/C-qso1Pb.js.br +0 -0
- package/build/_app/immutable/chunks/C-qso1Pb.js.gz +0 -0
- package/build/_app/immutable/chunks/C78K0g2i.js.br +0 -0
- package/build/_app/immutable/chunks/C78K0g2i.js.gz +0 -0
- package/build/_app/immutable/chunks/C970FsJW.js +0 -1
- package/build/_app/immutable/chunks/C970FsJW.js.br +0 -0
- package/build/_app/immutable/chunks/C970FsJW.js.gz +0 -0
- package/build/_app/immutable/chunks/CBzPmXSf.js +0 -1
- package/build/_app/immutable/chunks/CBzPmXSf.js.br +0 -0
- package/build/_app/immutable/chunks/CBzPmXSf.js.gz +0 -0
- package/build/_app/immutable/chunks/CH4VrfW2.js.br +0 -0
- package/build/_app/immutable/chunks/CH4VrfW2.js.gz +0 -0
- package/build/_app/immutable/chunks/CKf4QksN.js.br +0 -0
- package/build/_app/immutable/chunks/CKf4QksN.js.gz +0 -0
- package/build/_app/immutable/chunks/CPnjcwfB.js +0 -1
- package/build/_app/immutable/chunks/CPnjcwfB.js.br +0 -0
- package/build/_app/immutable/chunks/CPnjcwfB.js.gz +0 -0
- package/build/_app/immutable/chunks/CWB6mNDX.js.br +0 -0
- package/build/_app/immutable/chunks/CWB6mNDX.js.gz +0 -0
- package/build/_app/immutable/chunks/CcZs-N7g.js +0 -6
- package/build/_app/immutable/chunks/CcZs-N7g.js.br +0 -0
- package/build/_app/immutable/chunks/CcZs-N7g.js.gz +0 -0
- package/build/_app/immutable/chunks/CfbKmr1m.js.br +0 -0
- package/build/_app/immutable/chunks/CfbKmr1m.js.gz +0 -0
- package/build/_app/immutable/chunks/ClP8OL3G.js.br +0 -0
- package/build/_app/immutable/chunks/ClP8OL3G.js.gz +0 -0
- package/build/_app/immutable/chunks/D5UNd3Zp.js.br +0 -0
- package/build/_app/immutable/chunks/D5UNd3Zp.js.gz +0 -0
- package/build/_app/immutable/chunks/D6ibSY3A.js +0 -1
- package/build/_app/immutable/chunks/D6ibSY3A.js.br +0 -1
- package/build/_app/immutable/chunks/D6ibSY3A.js.gz +0 -0
- package/build/_app/immutable/chunks/DC_-4bAG.js.br +0 -1
- package/build/_app/immutable/chunks/DC_-4bAG.js.gz +0 -0
- package/build/_app/immutable/chunks/DHvIizf-.js.br +0 -0
- package/build/_app/immutable/chunks/DHvIizf-.js.gz +0 -0
- package/build/_app/immutable/chunks/DLL_0B-9.js.br +0 -0
- package/build/_app/immutable/chunks/DSaIAZ57.js.br +0 -0
- package/build/_app/immutable/chunks/DSaIAZ57.js.gz +0 -0
- package/build/_app/immutable/chunks/DeiSJRh0.js.br +0 -0
- package/build/_app/immutable/chunks/DeiSJRh0.js.gz +0 -0
- package/build/_app/immutable/chunks/DjqcYvLr.js.br +0 -0
- package/build/_app/immutable/chunks/DjqcYvLr.js.gz +0 -0
- package/build/_app/immutable/chunks/DrOC9WNt.js.br +0 -0
- package/build/_app/immutable/chunks/Ds1yKsjr.js.br +0 -0
- package/build/_app/immutable/chunks/NZcW2kfJ.js.br +0 -0
- package/build/_app/immutable/chunks/NZcW2kfJ.js.gz +0 -0
- package/build/_app/immutable/chunks/OPRu0_Dd.js +0 -1
- package/build/_app/immutable/chunks/OPRu0_Dd.js.br +0 -2
- package/build/_app/immutable/chunks/OPRu0_Dd.js.gz +0 -0
- package/build/_app/immutable/chunks/OYhYuonT.js.br +0 -0
- package/build/_app/immutable/chunks/OYhYuonT.js.gz +0 -0
- package/build/_app/immutable/chunks/VR9lxEL5.js +0 -1
- package/build/_app/immutable/chunks/VR9lxEL5.js.br +0 -0
- package/build/_app/immutable/chunks/VR9lxEL5.js.gz +0 -0
- package/build/_app/immutable/chunks/_lbjRyAo.js +0 -35
- package/build/_app/immutable/chunks/_lbjRyAo.js.br +0 -0
- package/build/_app/immutable/chunks/_lbjRyAo.js.gz +0 -0
- package/build/_app/immutable/chunks/arxGXJ5w.js +0 -1
- package/build/_app/immutable/chunks/arxGXJ5w.js.br +0 -2
- package/build/_app/immutable/chunks/arxGXJ5w.js.gz +0 -0
- package/build/_app/immutable/chunks/cVn7fglh.js +0 -1
- package/build/_app/immutable/chunks/cVn7fglh.js.br +0 -1
- package/build/_app/immutable/chunks/cVn7fglh.js.gz +0 -0
- package/build/_app/immutable/chunks/jk4Hz_9M.js.br +0 -0
- package/build/_app/immutable/chunks/jk4Hz_9M.js.gz +0 -0
- package/build/_app/immutable/chunks/lyi4TUVm.js.br +0 -0
- package/build/_app/immutable/chunks/lyi4TUVm.js.gz +0 -0
- package/build/_app/immutable/entry/app.D01tWdhc.js +0 -2
- package/build/_app/immutable/entry/app.D01tWdhc.js.br +0 -0
- package/build/_app/immutable/entry/app.D01tWdhc.js.gz +0 -0
- package/build/_app/immutable/entry/start.Dkgn2MUA.js +0 -1
- package/build/_app/immutable/entry/start.Dkgn2MUA.js.br +0 -0
- package/build/_app/immutable/entry/start.Dkgn2MUA.js.gz +0 -0
- package/build/_app/immutable/nodes/0.t2rvsaQV.js +0 -3
- package/build/_app/immutable/nodes/0.t2rvsaQV.js.br +0 -0
- package/build/_app/immutable/nodes/0.t2rvsaQV.js.gz +0 -0
- package/build/_app/immutable/nodes/1.B8XtGxov.js +0 -1
- package/build/_app/immutable/nodes/1.B8XtGxov.js.br +0 -2
- package/build/_app/immutable/nodes/1.B8XtGxov.js.gz +0 -0
- package/build/_app/immutable/nodes/14.uj6UKEKM.js +0 -1
- package/build/_app/immutable/nodes/14.uj6UKEKM.js.br +0 -0
- package/build/_app/immutable/nodes/14.uj6UKEKM.js.gz +0 -0
- package/build/_app/immutable/nodes/16.C4g9w36Y.js +0 -3
- package/build/_app/immutable/nodes/16.C4g9w36Y.js.br +0 -0
- package/build/_app/immutable/nodes/16.C4g9w36Y.js.gz +0 -0
- package/build/_app/immutable/nodes/17.DQrHVfP-.js +0 -10
- package/build/_app/immutable/nodes/17.DQrHVfP-.js.br +0 -0
- package/build/_app/immutable/nodes/17.DQrHVfP-.js.gz +0 -0
- package/build/_app/immutable/nodes/2.DFs_rmXb.js +0 -35
- package/build/_app/immutable/nodes/2.DFs_rmXb.js.br +0 -0
- package/build/_app/immutable/nodes/2.DFs_rmXb.js.gz +0 -0
- package/build/_app/immutable/nodes/3.CmzGRE5R.js +0 -1
- package/build/_app/immutable/nodes/3.CmzGRE5R.js.br +0 -0
- package/build/_app/immutable/nodes/3.CmzGRE5R.js.gz +0 -0
- package/build/_app/immutable/nodes/4.D6TiMacd.js +0 -1
- package/build/_app/immutable/nodes/4.D6TiMacd.js.br +0 -0
- package/build/_app/immutable/nodes/4.D6TiMacd.js.gz +0 -0
- package/build/_app/immutable/nodes/5.C3QbUkKf.js +0 -1
- package/build/_app/immutable/nodes/5.C3QbUkKf.js.br +0 -0
- package/build/_app/immutable/nodes/5.C3QbUkKf.js.gz +0 -0
- package/build/_app/immutable/nodes/6.UWx6wdAE.js +0 -1
- package/build/_app/immutable/nodes/6.UWx6wdAE.js.br +0 -0
- package/build/_app/immutable/nodes/6.UWx6wdAE.js.gz +0 -0
- package/build/_app/immutable/nodes/8.bZ206KXo.js +0 -2
- package/build/_app/immutable/nodes/8.bZ206KXo.js.br +0 -0
- package/build/_app/immutable/nodes/8.bZ206KXo.js.gz +0 -0
- package/build/_app/immutable/nodes/9.CCSxSizl.js +0 -24
- package/build/_app/immutable/nodes/9.CCSxSizl.js.br +0 -0
- package/build/_app/immutable/nodes/9.CCSxSizl.js.gz +0 -0
- package/build/_app/immutable/workers/css.worker-DflDYzxC.js.br +0 -0
- package/build/_app/immutable/workers/editor.worker-DbG82rLA.js.br +0 -0
- package/build/_app/immutable/workers/html.worker-Bn6S4v1s.js.br +0 -0
- package/build/_app/immutable/workers/json.worker-CfS7sFxM.js.br +0 -0
- package/build/_app/immutable/workers/ts.worker-Bqwj6xoy.js.br +0 -0
- /package/build/_app/immutable/assets/{ReadOnlyMonacoDiff.Ba-kUPX7.css → Modal.Ba-kUPX7.css} +0 -0
- /package/build/_app/immutable/assets/{ReadOnlyMonacoDiff.Ba-kUPX7.css.br → Modal.Ba-kUPX7.css.br} +0 -0
- /package/build/_app/immutable/assets/{ReadOnlyMonacoDiff.Ba-kUPX7.css.gz → Modal.Ba-kUPX7.css.gz} +0 -0
package/dist/index.js
CHANGED
|
@@ -627,8 +627,6 @@ function toText(event) {
|
|
|
627
627
|
}
|
|
628
628
|
|
|
629
629
|
// src/backend/roleplay/router.ts
|
|
630
|
-
import fs3 from "fs";
|
|
631
|
-
import path8 from "path";
|
|
632
630
|
import { z as z4 } from "zod";
|
|
633
631
|
|
|
634
632
|
// src/backend/lib/trpc-context.ts
|
|
@@ -646,7 +644,7 @@ function writeProcedure(t2) {
|
|
|
646
644
|
import "openai";
|
|
647
645
|
|
|
648
646
|
// src/backend/tests/data.ts
|
|
649
|
-
import { createHash, randomUUID as randomUUID2 } from "node:crypto";
|
|
647
|
+
import { createHash as createHash2, randomUUID as randomUUID2 } from "node:crypto";
|
|
650
648
|
import { readdir as readdir2, readFile as readFile3, stat, writeFile as writeFile2 } from "node:fs/promises";
|
|
651
649
|
import path7 from "node:path";
|
|
652
650
|
|
|
@@ -927,6 +925,33 @@ function queueReportCompression(filePath) {
|
|
|
927
925
|
return compression;
|
|
928
926
|
}
|
|
929
927
|
|
|
928
|
+
// src/backend/tests/test-edit-source.ts
|
|
929
|
+
import { createHash } from "node:crypto";
|
|
930
|
+
function canonicalize(value) {
|
|
931
|
+
if (Array.isArray(value)) return value.map(canonicalize);
|
|
932
|
+
if (!value || typeof value !== "object") return value;
|
|
933
|
+
return Object.fromEntries(
|
|
934
|
+
Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, entry]) => [key, canonicalize(entry)])
|
|
935
|
+
);
|
|
936
|
+
}
|
|
937
|
+
function testEditSourceFingerprint(test, overrides) {
|
|
938
|
+
const source = canonicalize({
|
|
939
|
+
step: test.step,
|
|
940
|
+
evaluationMode: test.evaluation_mode,
|
|
941
|
+
assertionType: test.assertion_type,
|
|
942
|
+
assertionValue: test.assertion_value,
|
|
943
|
+
caseSensitive: test.case_sensitive,
|
|
944
|
+
contextMode: test.context_mode,
|
|
945
|
+
conversation: overrides?.conversation ?? test.conversation,
|
|
946
|
+
expectedOutput: test.expected_output,
|
|
947
|
+
timeout: test.timeout,
|
|
948
|
+
similarityThreshold: test.similarity_threshold,
|
|
949
|
+
context: test.context,
|
|
950
|
+
mocks: test.mocks ?? null
|
|
951
|
+
});
|
|
952
|
+
return createHash("sha256").update(JSON.stringify(source)).digest("hex");
|
|
953
|
+
}
|
|
954
|
+
|
|
930
955
|
// src/backend/tests/data.ts
|
|
931
956
|
var defaultTestRow = {
|
|
932
957
|
order: 0,
|
|
@@ -983,7 +1008,7 @@ async function loadTests(ctx, agent) {
|
|
|
983
1008
|
"context",
|
|
984
1009
|
"mocks"
|
|
985
1010
|
];
|
|
986
|
-
const workspaceId =
|
|
1011
|
+
const workspaceId = createHash2("sha256").update(process.cwd()).digest("hex").slice(0, 16);
|
|
987
1012
|
return { rows, headers, settingsKey: `bosun:test-settings:${workspaceId}:${agent}` };
|
|
988
1013
|
});
|
|
989
1014
|
}
|
|
@@ -999,6 +1024,22 @@ async function patchTest(ctx, agent, id, patch) {
|
|
|
999
1024
|
return updated;
|
|
1000
1025
|
});
|
|
1001
1026
|
}
|
|
1027
|
+
async function patchTestConversationIfCurrent(ctx, agent, id, expectedConversation, conversation, allowedSourceFingerprints) {
|
|
1028
|
+
return withSuiteMutationLock(agent, async () => {
|
|
1029
|
+
const suite = await readSuite(ctx, agent);
|
|
1030
|
+
const current = suite.tests.find((row) => row.id === id);
|
|
1031
|
+
if (!current) return { status: "not-found" };
|
|
1032
|
+
if (current.conversation !== expectedConversation || allowedSourceFingerprints && !allowedSourceFingerprints.includes(testEditSourceFingerprint(current))) {
|
|
1033
|
+
return { status: "stale", currentConversation: current.conversation };
|
|
1034
|
+
}
|
|
1035
|
+
const updated = preparePatch(current, { conversation });
|
|
1036
|
+
await writeSuite(ctx, agent, {
|
|
1037
|
+
...suite,
|
|
1038
|
+
tests: suite.tests.map((row) => row.id === id ? updated : row)
|
|
1039
|
+
});
|
|
1040
|
+
return { status: "changed", test: updated };
|
|
1041
|
+
});
|
|
1042
|
+
}
|
|
1002
1043
|
function preparePatch(current, patch) {
|
|
1003
1044
|
const updated = {
|
|
1004
1045
|
...defaultTestRow,
|
|
@@ -1029,7 +1070,7 @@ async function patchTestsBatch(ctx, agent, updates) {
|
|
|
1029
1070
|
return updatedRows;
|
|
1030
1071
|
});
|
|
1031
1072
|
}
|
|
1032
|
-
async function addTest(ctx, agent, seed) {
|
|
1073
|
+
async function addTest(ctx, agent, seed, options = {}) {
|
|
1033
1074
|
return withSuiteMutationLock(agent, async () => {
|
|
1034
1075
|
const suite = await loadSuiteOrEmpty(ctx, agent);
|
|
1035
1076
|
const id = randomUUID2();
|
|
@@ -1037,17 +1078,37 @@ async function addTest(ctx, agent, seed) {
|
|
|
1037
1078
|
(minimum, row) => Math.min(minimum, row.order),
|
|
1038
1079
|
Number.POSITIVE_INFINITY
|
|
1039
1080
|
);
|
|
1081
|
+
let existingTests = suite.tests;
|
|
1082
|
+
let order = Number.isFinite(firstOrder) ? firstOrder - 1024 : 0;
|
|
1083
|
+
if (options.beforeTestId) {
|
|
1084
|
+
const beforeTest = suite.tests.find((row) => row.id === options.beforeTestId);
|
|
1085
|
+
if (!beforeTest) throw new Error(`Test '${options.beforeTestId}' was not found`);
|
|
1086
|
+
const stepTests = suite.tests.filter((row) => row.step === beforeTest.step);
|
|
1087
|
+
const beforeIndex = stepTests.findIndex((row) => row.id === beforeTest.id);
|
|
1088
|
+
const previousTest = stepTests[beforeIndex - 1];
|
|
1089
|
+
const candidate = previousTest ? previousTest.order + (beforeTest.order - previousTest.order) / 2 : beforeTest.order - 1024;
|
|
1090
|
+
if (Number.isFinite(candidate) && candidate < beforeTest.order && (!previousTest || candidate > previousTest.order)) {
|
|
1091
|
+
order = candidate;
|
|
1092
|
+
} else {
|
|
1093
|
+
const rebalancedOrders = new Map(stepTests.map((row, index) => [row.id, index * 1024]));
|
|
1094
|
+
existingTests = suite.tests.map((row) => {
|
|
1095
|
+
const rebalancedOrder = rebalancedOrders.get(row.id);
|
|
1096
|
+
return typeof rebalancedOrder === "number" ? { ...row, order: rebalancedOrder } : row;
|
|
1097
|
+
});
|
|
1098
|
+
order = beforeIndex === 0 ? -1024 : beforeIndex * 1024 - 512;
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1040
1101
|
const newRow = {
|
|
1041
1102
|
...defaultTestRow,
|
|
1042
1103
|
id,
|
|
1043
|
-
order: Number.isFinite(firstOrder) ? firstOrder - 1024 : 0,
|
|
1044
1104
|
...seed,
|
|
1105
|
+
order,
|
|
1045
1106
|
context: makeContext(seed?.context)
|
|
1046
1107
|
};
|
|
1047
1108
|
if (typeof seed?.mocks !== "undefined") {
|
|
1048
1109
|
newRow.mocks = makeContext(seed.mocks);
|
|
1049
1110
|
}
|
|
1050
|
-
await writeSuite(ctx, agent, { tests: [newRow, ...
|
|
1111
|
+
await writeSuite(ctx, agent, { tests: [newRow, ...existingTests] });
|
|
1051
1112
|
return newRow;
|
|
1052
1113
|
});
|
|
1053
1114
|
}
|
|
@@ -1828,6 +1889,52 @@ function envIntOrDefault(key, defaultValue, opts) {
|
|
|
1828
1889
|
return Math.max(opts.min, Math.min(opts.max, rounded));
|
|
1829
1890
|
}
|
|
1830
1891
|
|
|
1892
|
+
// src/backend/roleplay/prompt-file.ts
|
|
1893
|
+
import fs3 from "node:fs";
|
|
1894
|
+
import path8 from "node:path";
|
|
1895
|
+
var promptMutationQueue = /* @__PURE__ */ new Map();
|
|
1896
|
+
async function resolveEditablePrompt(ctx, agentId, stepName) {
|
|
1897
|
+
const { basePath, steps } = await getAgentSteps(ctx, agentId);
|
|
1898
|
+
const targetStep = steps.find((step) => step?.name === stepName);
|
|
1899
|
+
if (!targetStep || targetStep?.prompt?.type !== "file") {
|
|
1900
|
+
throw new Error(`Step '${stepName}' does not have an editable file prompt`);
|
|
1901
|
+
}
|
|
1902
|
+
return {
|
|
1903
|
+
promptPath: path8.resolve(basePath, targetStep.prompt.path),
|
|
1904
|
+
readContent: () => targetStep.prompt.content()
|
|
1905
|
+
};
|
|
1906
|
+
}
|
|
1907
|
+
async function readEditablePrompt(ctx, agentId, stepName) {
|
|
1908
|
+
const { readContent } = await resolveEditablePrompt(ctx, agentId, stepName);
|
|
1909
|
+
return readContent();
|
|
1910
|
+
}
|
|
1911
|
+
async function withPromptFileLock(ctx, agentId, stepName, operation) {
|
|
1912
|
+
const { promptPath } = await resolveEditablePrompt(ctx, agentId, stepName);
|
|
1913
|
+
const canonicalPath = await fs3.promises.realpath(promptPath);
|
|
1914
|
+
const previous = promptMutationQueue.get(canonicalPath) ?? Promise.resolve();
|
|
1915
|
+
let release;
|
|
1916
|
+
const gate = new Promise((resolve) => {
|
|
1917
|
+
release = resolve;
|
|
1918
|
+
});
|
|
1919
|
+
const queued = previous.catch(() => {
|
|
1920
|
+
}).then(() => gate);
|
|
1921
|
+
promptMutationQueue.set(canonicalPath, queued);
|
|
1922
|
+
await previous.catch(() => {
|
|
1923
|
+
});
|
|
1924
|
+
try {
|
|
1925
|
+
return await operation({
|
|
1926
|
+
path: canonicalPath,
|
|
1927
|
+
read: () => fs3.promises.readFile(canonicalPath, "utf-8"),
|
|
1928
|
+
write: (prompt) => fs3.promises.writeFile(canonicalPath, prompt, "utf-8")
|
|
1929
|
+
});
|
|
1930
|
+
} finally {
|
|
1931
|
+
release();
|
|
1932
|
+
if (promptMutationQueue.get(canonicalPath) === queued) {
|
|
1933
|
+
promptMutationQueue.delete(canonicalPath);
|
|
1934
|
+
}
|
|
1935
|
+
}
|
|
1936
|
+
}
|
|
1937
|
+
|
|
1831
1938
|
// src/backend/roleplay/variants.ts
|
|
1832
1939
|
async function generateReplyVariants(ctx, props) {
|
|
1833
1940
|
const { conversation, count } = props;
|
|
@@ -1874,12 +1981,24 @@ function createPromptEditProposal(proposal) {
|
|
|
1874
1981
|
removeExpiredPromptEditProposals();
|
|
1875
1982
|
const stored = { ...proposal, id: randomUUID3(), createdAt: Date.now() };
|
|
1876
1983
|
proposals.set(stored.id, stored);
|
|
1877
|
-
return
|
|
1984
|
+
return publicProposal(stored);
|
|
1878
1985
|
}
|
|
1879
1986
|
function getPromptEditProposal(id) {
|
|
1880
1987
|
removeExpiredPromptEditProposals();
|
|
1881
1988
|
const proposal = proposals.get(id);
|
|
1882
|
-
return proposal ?
|
|
1989
|
+
return proposal ? publicProposal(proposal) : null;
|
|
1990
|
+
}
|
|
1991
|
+
function getPromptEditProposalForAcceptance(id) {
|
|
1992
|
+
removeExpiredPromptEditProposals();
|
|
1993
|
+
const proposal = proposals.get(id);
|
|
1994
|
+
return proposal ? {
|
|
1995
|
+
...proposal,
|
|
1996
|
+
testSourceGuard: proposal.testSourceGuard ? {
|
|
1997
|
+
suiteKey: proposal.testSourceGuard.suiteKey,
|
|
1998
|
+
testId: proposal.testSourceGuard.testId,
|
|
1999
|
+
allowedFingerprints: [...proposal.testSourceGuard.allowedFingerprints]
|
|
2000
|
+
} : void 0
|
|
2001
|
+
} : null;
|
|
1883
2002
|
}
|
|
1884
2003
|
function deletePromptEditProposal(id) {
|
|
1885
2004
|
return proposals.delete(id);
|
|
@@ -1889,8 +2008,12 @@ function removeExpiredPromptEditProposals(now = Date.now()) {
|
|
|
1889
2008
|
if (proposal.createdAt + PROPOSAL_TTL_MS <= now) proposals.delete(id);
|
|
1890
2009
|
}
|
|
1891
2010
|
}
|
|
2011
|
+
function publicProposal(proposal) {
|
|
2012
|
+
const { testSourceGuard: _testSourceGuard, ...result } = proposal;
|
|
2013
|
+
return { ...result };
|
|
2014
|
+
}
|
|
1892
2015
|
|
|
1893
|
-
// src/backend/roleplay/suggest-
|
|
2016
|
+
// src/backend/roleplay/suggest-file-edit.ts
|
|
1894
2017
|
import "openai";
|
|
1895
2018
|
|
|
1896
2019
|
// src/backend/lib/apply-v4a-diff.ts
|
|
@@ -2026,13 +2149,12 @@ function applyChunks(input, chunks) {
|
|
|
2026
2149
|
return output.join("\n");
|
|
2027
2150
|
}
|
|
2028
2151
|
|
|
2029
|
-
// src/backend/roleplay/suggest-
|
|
2152
|
+
// src/backend/roleplay/suggest-file-edit.ts
|
|
2030
2153
|
var MODEL = "gpt-5.4";
|
|
2031
|
-
var VIRTUAL_PROMPT_PATH = "prompt.md";
|
|
2032
2154
|
var MAX_PATCH_ROUNDS = 8;
|
|
2033
|
-
async function
|
|
2155
|
+
async function suggestFileEdit(ctx, input) {
|
|
2034
2156
|
const client = ctx.openai;
|
|
2035
|
-
let
|
|
2157
|
+
let virtualContent = input.originalContent;
|
|
2036
2158
|
let activity = 0;
|
|
2037
2159
|
let modelRound = 0;
|
|
2038
2160
|
let reasoningSummary = "";
|
|
@@ -2048,22 +2170,23 @@ async function suggestPromptEdit(ctx, input) {
|
|
|
2048
2170
|
});
|
|
2049
2171
|
};
|
|
2050
2172
|
let response = await createResponse(client, {
|
|
2051
|
-
input:
|
|
2173
|
+
input: input.request,
|
|
2174
|
+
instructions: input.instructions,
|
|
2052
2175
|
onEvent: handleEvent
|
|
2053
2176
|
});
|
|
2054
2177
|
for (let patchRound = 0; patchRound < MAX_PATCH_ROUNDS; patchRound += 1) {
|
|
2055
2178
|
const patchCalls = response.output.filter(
|
|
2056
2179
|
(item) => item?.type === "apply_patch_call"
|
|
2057
2180
|
);
|
|
2058
|
-
if (!patchCalls.length) return
|
|
2181
|
+
if (!patchCalls.length) return virtualContent;
|
|
2059
2182
|
const outputs = patchCalls.map((call) => {
|
|
2060
2183
|
try {
|
|
2061
|
-
|
|
2184
|
+
virtualContent = applyFileOperation(virtualContent, input.virtualPath, call.operation);
|
|
2062
2185
|
return {
|
|
2063
2186
|
type: "apply_patch_call_output",
|
|
2064
2187
|
call_id: call.call_id,
|
|
2065
2188
|
status: "completed",
|
|
2066
|
-
output: `Updated ${
|
|
2189
|
+
output: `Updated ${input.virtualPath} in memory`
|
|
2067
2190
|
};
|
|
2068
2191
|
} catch (error) {
|
|
2069
2192
|
return {
|
|
@@ -2080,29 +2203,20 @@ async function suggestPromptEdit(ctx, input) {
|
|
|
2080
2203
|
response = await createResponse(client, {
|
|
2081
2204
|
previousResponseId: response.id,
|
|
2082
2205
|
input: outputs,
|
|
2206
|
+
instructions: input.instructions,
|
|
2083
2207
|
onEvent: handleEvent
|
|
2084
2208
|
});
|
|
2085
2209
|
}
|
|
2086
|
-
throw new Error(
|
|
2087
|
-
}
|
|
2088
|
-
function buildPrompt(request, originalPrompt) {
|
|
2089
|
-
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. Note that this is a Nunjucks template and it will be rendered according to context. You can change/append the template logic if necessary.
|
|
2090
|
-
|
|
2091
|
-
This is their request:
|
|
2092
|
-
${request}
|
|
2093
|
-
|
|
2094
|
-
This is the original prompt:
|
|
2095
|
-
${originalPrompt}
|
|
2096
|
-
`;
|
|
2210
|
+
throw new Error(`The model did not finish editing ${input.virtualPath}`);
|
|
2097
2211
|
}
|
|
2098
2212
|
async function createResponse(client, input) {
|
|
2099
2213
|
const stream = await client.responses.create({
|
|
2100
2214
|
model: MODEL,
|
|
2101
|
-
instructions:
|
|
2215
|
+
instructions: input.instructions,
|
|
2102
2216
|
input: input.input,
|
|
2103
2217
|
...input.previousResponseId ? { previous_response_id: input.previousResponseId } : {},
|
|
2104
2218
|
tools: [{ type: "apply_patch" }],
|
|
2105
|
-
reasoning: { effort: "
|
|
2219
|
+
reasoning: { effort: "high", summary: "auto" },
|
|
2106
2220
|
text: { verbosity: "low" },
|
|
2107
2221
|
stream: true
|
|
2108
2222
|
});
|
|
@@ -2111,14 +2225,14 @@ async function createResponse(client, input) {
|
|
|
2111
2225
|
input.onEvent(event);
|
|
2112
2226
|
if (event?.type === "response.completed") completedResponse = event.response;
|
|
2113
2227
|
if (event?.type === "response.failed") {
|
|
2114
|
-
throw new Error(event.response?.error?.message || "OpenAI failed to suggest
|
|
2228
|
+
throw new Error(event.response?.error?.message || "OpenAI failed to suggest edits");
|
|
2115
2229
|
}
|
|
2116
2230
|
if (event?.type === "response.incomplete") {
|
|
2117
|
-
throw new Error("OpenAI returned an incomplete
|
|
2231
|
+
throw new Error("OpenAI returned an incomplete edit");
|
|
2118
2232
|
}
|
|
2119
2233
|
if (event?.type === "error") throw new Error(event.message || "OpenAI streaming failed");
|
|
2120
2234
|
}
|
|
2121
|
-
if (!completedResponse) throw new Error("OpenAI stream ended before the
|
|
2235
|
+
if (!completedResponse) throw new Error("OpenAI stream ended before the edit completed");
|
|
2122
2236
|
return completedResponse;
|
|
2123
2237
|
}
|
|
2124
2238
|
function progressPhase(event, round) {
|
|
@@ -2127,18 +2241,140 @@ function progressPhase(event, round) {
|
|
|
2127
2241
|
if (eventType.includes("apply_patch") || itemType === "apply_patch_call") return "drafting";
|
|
2128
2242
|
return round > 0 ? "reviewing" : "thinking";
|
|
2129
2243
|
}
|
|
2130
|
-
function
|
|
2244
|
+
function applyFileOperation(currentContent, virtualPath, operation) {
|
|
2131
2245
|
const normalizedPath = String(operation.path || "").replace(/\\/g, "/").replace(/^\.\//, "").replace(/^\//, "");
|
|
2132
|
-
if (normalizedPath !==
|
|
2133
|
-
throw new Error(`Only ${
|
|
2246
|
+
if (normalizedPath !== virtualPath) {
|
|
2247
|
+
throw new Error(`Only ${virtualPath} may be edited`);
|
|
2134
2248
|
}
|
|
2135
2249
|
if (operation.type !== "update_file") {
|
|
2136
|
-
throw new Error(`${
|
|
2250
|
+
throw new Error(`${virtualPath} already exists and may only be updated`);
|
|
2137
2251
|
}
|
|
2138
2252
|
if (typeof operation.diff !== "string" || !operation.diff.trim()) {
|
|
2139
2253
|
throw new Error("Apply Patch returned an empty diff");
|
|
2140
2254
|
}
|
|
2141
|
-
return applyV4ADiff(
|
|
2255
|
+
return applyV4ADiff(currentContent, operation.diff);
|
|
2256
|
+
}
|
|
2257
|
+
|
|
2258
|
+
// src/backend/roleplay/suggest-prompt-edit.ts
|
|
2259
|
+
var VIRTUAL_PROMPT_PATH = "prompt.md";
|
|
2260
|
+
async function suggestPromptEdit(ctx, input) {
|
|
2261
|
+
return suggestFileEdit(ctx, {
|
|
2262
|
+
request: buildPrompt(input.request, input.originalPrompt),
|
|
2263
|
+
originalContent: input.originalPrompt,
|
|
2264
|
+
virtualPath: VIRTUAL_PROMPT_PATH,
|
|
2265
|
+
instructions: "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.",
|
|
2266
|
+
onProgress: input.onProgress
|
|
2267
|
+
});
|
|
2268
|
+
}
|
|
2269
|
+
function buildPrompt(request, originalPrompt) {
|
|
2270
|
+
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. Note that this is a Nunjucks template and it will be rendered according to context. You can change/append the template logic if necessary.
|
|
2271
|
+
|
|
2272
|
+
This is their request:
|
|
2273
|
+
${request}
|
|
2274
|
+
|
|
2275
|
+
This is the original prompt:
|
|
2276
|
+
${originalPrompt}
|
|
2277
|
+
`;
|
|
2278
|
+
}
|
|
2279
|
+
|
|
2280
|
+
// src/lib/edit/test-ai-edit.ts
|
|
2281
|
+
function formatTestFixAssertion(label, value) {
|
|
2282
|
+
const normalizedLabel = label.trim() === "LLM" ? "" : label.trim();
|
|
2283
|
+
return [normalizedLabel, value.trim()].filter(Boolean).join(" ");
|
|
2284
|
+
}
|
|
2285
|
+
function buildTestFixRequest(input) {
|
|
2286
|
+
const assertion = formatTestFixAssertion(input.assertionLabel, input.assertionValue);
|
|
2287
|
+
return `You will be given the context, the conversation and the desired output and assertion about it. First, find why the prompt is not producing the correct result. It's usually one concrete instruction within the relevant section, or a contradiction. Then, change the prompt minimally so this will work, but keeping the prompt clean and comprehensive is more important. Try to provide as general solution as possible. Try to change just one part of the prompt, not multiple parts. Avoid adding exceptions and overrides. Avoid duplicating information that already exists in the prompt.
|
|
2288
|
+
|
|
2289
|
+
Context:
|
|
2290
|
+
${input.context.trim()}
|
|
2291
|
+
|
|
2292
|
+
Conversation:
|
|
2293
|
+
${input.conversation.trim()}
|
|
2294
|
+
|
|
2295
|
+
Desired outcome:
|
|
2296
|
+
${input.expectedOutput.trim()}
|
|
2297
|
+
|
|
2298
|
+
Assertion about outcome:
|
|
2299
|
+
${assertion}
|
|
2300
|
+
|
|
2301
|
+
Current incorrect outcome:
|
|
2302
|
+
${input.currentIncorrectOutcome.trim()}`;
|
|
2303
|
+
}
|
|
2304
|
+
function buildPromptFixRequest(enteredRequest, input, originalConversation) {
|
|
2305
|
+
const canonicalOriginal = buildTestFixRequest({ ...input, conversation: originalConversation });
|
|
2306
|
+
const canonicalCorrected = buildTestFixRequest(input);
|
|
2307
|
+
if (enteredRequest.trim() === canonicalOriginal.trim()) return canonicalCorrected;
|
|
2308
|
+
return `${enteredRequest.trim()}
|
|
2309
|
+
|
|
2310
|
+
The conversation history has now been checked and may have been corrected. Use the following test case as authoritative instead of any earlier version included above:
|
|
2311
|
+
|
|
2312
|
+
${canonicalCorrected}`;
|
|
2313
|
+
}
|
|
2314
|
+
|
|
2315
|
+
// src/backend/tests/suggest-test-history-edit.ts
|
|
2316
|
+
var VIRTUAL_HISTORY_PATH = "history.md";
|
|
2317
|
+
async function suggestTestHistoryEdit(ctx, input) {
|
|
2318
|
+
return suggestFileEdit(ctx, {
|
|
2319
|
+
request: buildTestHistoryPrompt(input),
|
|
2320
|
+
originalContent: input.conversation,
|
|
2321
|
+
virtualPath: VIRTUAL_HISTORY_PATH,
|
|
2322
|
+
instructions: "The conversation history is the existing virtual file history.md. Decide whether it conflicts with the current LLM prompt or contains agent behaviour that the current prompt would not produce. If it does, use the Apply Patch tool to update history.md minimally. Otherwise, do not call Apply Patch. Preserve the test intent and never add or change the expected outcome. Do not create, delete, or modify any other file.",
|
|
2323
|
+
onProgress: input.onProgress
|
|
2324
|
+
});
|
|
2325
|
+
}
|
|
2326
|
+
function buildTestHistoryPrompt(input) {
|
|
2327
|
+
return `The user wants you to update an LLM test's conversation history when needed. The history must reflect behaviour that is valid under the current prompt. Make the smallest useful change. The expected outcome is immutable and is provided only so you can preserve the test's intent.
|
|
2328
|
+
|
|
2329
|
+
This is the user's request:
|
|
2330
|
+
${input.request}
|
|
2331
|
+
|
|
2332
|
+
This is the current LLM prompt:
|
|
2333
|
+
${input.prompt}
|
|
2334
|
+
|
|
2335
|
+
This is the test context:
|
|
2336
|
+
${input.context}
|
|
2337
|
+
|
|
2338
|
+
This is the conversation history in history.md:
|
|
2339
|
+
${input.conversation}
|
|
2340
|
+
|
|
2341
|
+
This is the immutable expected outcome:
|
|
2342
|
+
${input.expectedOutput}
|
|
2343
|
+
`;
|
|
2344
|
+
}
|
|
2345
|
+
|
|
2346
|
+
// src/backend/roleplay/suggest-test-fix.ts
|
|
2347
|
+
var defaultDependencies = {
|
|
2348
|
+
suggestHistory: suggestTestHistoryEdit,
|
|
2349
|
+
suggestPrompt: suggestPromptEdit
|
|
2350
|
+
};
|
|
2351
|
+
async function suggestTestFix(ctx, input, dependencies = defaultDependencies) {
|
|
2352
|
+
const suggestedConversation = await dependencies.suggestHistory(ctx, {
|
|
2353
|
+
request: input.request,
|
|
2354
|
+
prompt: input.originalPrompt,
|
|
2355
|
+
context: input.context,
|
|
2356
|
+
conversation: input.conversation,
|
|
2357
|
+
expectedOutput: input.expectedOutput,
|
|
2358
|
+
onProgress: input.onProgress
|
|
2359
|
+
});
|
|
2360
|
+
const promptRequest = buildPromptFixRequest(
|
|
2361
|
+
input.request,
|
|
2362
|
+
{
|
|
2363
|
+
context: input.context,
|
|
2364
|
+
conversation: suggestedConversation,
|
|
2365
|
+
expectedOutput: input.expectedOutput,
|
|
2366
|
+
assertionLabel: input.assertionLabel,
|
|
2367
|
+
assertionValue: input.assertionValue,
|
|
2368
|
+
currentIncorrectOutcome: input.currentIncorrectOutcome
|
|
2369
|
+
},
|
|
2370
|
+
input.conversation
|
|
2371
|
+
);
|
|
2372
|
+
const suggestedPrompt = await dependencies.suggestPrompt(ctx, {
|
|
2373
|
+
request: promptRequest,
|
|
2374
|
+
originalPrompt: input.originalPrompt,
|
|
2375
|
+
onProgress: input.onProgress
|
|
2376
|
+
});
|
|
2377
|
+
return { suggestedConversation, suggestedPrompt };
|
|
2142
2378
|
}
|
|
2143
2379
|
|
|
2144
2380
|
// src/backend/roleplay/prompt-edit-progress.ts
|
|
@@ -2159,6 +2395,107 @@ function removeExpiredProgress(now = Date.now()) {
|
|
|
2159
2395
|
}
|
|
2160
2396
|
}
|
|
2161
2397
|
|
|
2398
|
+
// src/backend/tests/test-history-edit-proposals.ts
|
|
2399
|
+
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
2400
|
+
var proposals2 = /* @__PURE__ */ new Map();
|
|
2401
|
+
var PROPOSAL_TTL_MS2 = 12 * 60 * 60 * 1e3;
|
|
2402
|
+
function createTestHistoryEditProposal(proposal) {
|
|
2403
|
+
removeExpiredTestHistoryEditProposals();
|
|
2404
|
+
const stored = { ...proposal, id: randomUUID4(), createdAt: Date.now() };
|
|
2405
|
+
proposals2.set(stored.id, stored);
|
|
2406
|
+
return publicProposal2(stored);
|
|
2407
|
+
}
|
|
2408
|
+
function getTestHistoryEditProposalForAcceptance(id) {
|
|
2409
|
+
removeExpiredTestHistoryEditProposals();
|
|
2410
|
+
const proposal = proposals2.get(id);
|
|
2411
|
+
return proposal ? {
|
|
2412
|
+
...proposal,
|
|
2413
|
+
sourceGuard: {
|
|
2414
|
+
suiteKey: proposal.sourceGuard.suiteKey,
|
|
2415
|
+
allowedTestFingerprints: [...proposal.sourceGuard.allowedTestFingerprints],
|
|
2416
|
+
allowedPromptContents: [...proposal.sourceGuard.allowedPromptContents]
|
|
2417
|
+
}
|
|
2418
|
+
} : null;
|
|
2419
|
+
}
|
|
2420
|
+
function deleteTestHistoryEditProposal(id) {
|
|
2421
|
+
return proposals2.delete(id);
|
|
2422
|
+
}
|
|
2423
|
+
function removeExpiredTestHistoryEditProposals(now = Date.now()) {
|
|
2424
|
+
for (const [id, proposal] of proposals2) {
|
|
2425
|
+
if (proposal.createdAt + PROPOSAL_TTL_MS2 <= now) proposals2.delete(id);
|
|
2426
|
+
}
|
|
2427
|
+
}
|
|
2428
|
+
function publicProposal2(proposal) {
|
|
2429
|
+
const { sourceGuard: _sourceGuard, ...result } = proposal;
|
|
2430
|
+
return { ...result };
|
|
2431
|
+
}
|
|
2432
|
+
|
|
2433
|
+
// src/lib/tests/assertion-types.ts
|
|
2434
|
+
var baseAssertionTypes = [
|
|
2435
|
+
{ value: "llm-rubric", label: "LLM" },
|
|
2436
|
+
{ value: "answer-relevance", label: "Answer Relevance (LLM)" },
|
|
2437
|
+
{ value: "context-faithfulness", label: "Context Faithfulness (LLM)" },
|
|
2438
|
+
{ value: "context-recall", label: "Context Recall (LLM)" },
|
|
2439
|
+
{ value: "context-relevance", label: "Context Relevance (LLM)" },
|
|
2440
|
+
{ value: "model-graded-closedqa", label: "Model-Graded Closed QA" },
|
|
2441
|
+
{ value: "model-graded-factuality", label: "Model-Graded Factuality" },
|
|
2442
|
+
{ value: "moderation", label: "Moderation" },
|
|
2443
|
+
{ value: "classifier", label: "Classifier" },
|
|
2444
|
+
{ value: "g-eval", label: "G-Eval" },
|
|
2445
|
+
{ value: "factuality", label: "Factuality" },
|
|
2446
|
+
{ value: "conversation-relevance", label: "Conversation Relevance" },
|
|
2447
|
+
{ value: "equals", label: "Equals" },
|
|
2448
|
+
{ value: "contains", label: "Contains" },
|
|
2449
|
+
{ value: "icontains", label: "Contains (case-insensitive)" },
|
|
2450
|
+
{ value: "contains-all", label: "Contains All" },
|
|
2451
|
+
{ value: "contains-any", label: "Contains Any" },
|
|
2452
|
+
{ value: "icontains-all", label: "Contains All (iCase)" },
|
|
2453
|
+
{ value: "icontains-any", label: "Contains Any (iCase)" },
|
|
2454
|
+
{ value: "starts-with", label: "Starts With" },
|
|
2455
|
+
{ value: "regex", label: "Regex" },
|
|
2456
|
+
{ value: "levenshtein", label: "Levenshtein Distance" },
|
|
2457
|
+
{ value: "is-refusal", label: "Is Refusal" },
|
|
2458
|
+
{ value: "is-html", label: "Is HTML" },
|
|
2459
|
+
{ value: "contains-html", label: "Contains HTML" },
|
|
2460
|
+
{ value: "is-json", label: "Is JSON" },
|
|
2461
|
+
{ value: "contains-json", label: "Contains JSON" },
|
|
2462
|
+
{ value: "is-xml", label: "Is XML" },
|
|
2463
|
+
{ value: "contains-xml", label: "Contains XML" },
|
|
2464
|
+
{ value: "is-sql", label: "Is SQL" },
|
|
2465
|
+
{ value: "contains-sql", label: "Contains SQL" },
|
|
2466
|
+
{ value: "similar", label: "Semantic Similarity" },
|
|
2467
|
+
{ value: "rouge-n", label: "ROUGE-N" },
|
|
2468
|
+
{ value: "bleu", label: "BLEU" },
|
|
2469
|
+
{ value: "gleu", label: "GLEU" },
|
|
2470
|
+
{ value: "meteor", label: "METEOR" },
|
|
2471
|
+
{ value: "perplexity", label: "Perplexity" },
|
|
2472
|
+
{ value: "perplexity-score", label: "Perplexity Score" },
|
|
2473
|
+
{ value: "latency", label: "Latency" },
|
|
2474
|
+
{ value: "cost", label: "Cost" },
|
|
2475
|
+
{ value: "finish-reason", label: "Finish Reason" },
|
|
2476
|
+
{ value: "trace-error-spans", label: "Trace Error Spans" },
|
|
2477
|
+
{ value: "trace-span-count", label: "Trace Span Count" },
|
|
2478
|
+
{ value: "trace-span-duration", label: "Trace Span Duration" },
|
|
2479
|
+
{ value: "is-valid-function-call", label: "Is Valid Function Call" },
|
|
2480
|
+
{ value: "is-valid-openai-function-call", label: "Is Valid OpenAI Function Call" },
|
|
2481
|
+
{ value: "is-valid-openai-tools-call", label: "Is Valid OpenAI Tools Call" },
|
|
2482
|
+
{ value: "guardrails", label: "Guardrails" },
|
|
2483
|
+
{ value: "javascript", label: "JavaScript (custom)" },
|
|
2484
|
+
{ value: "python", label: "Python (custom)" },
|
|
2485
|
+
{ value: "webhook", label: "Webhook (custom)" },
|
|
2486
|
+
{ value: "pi", label: "Pi Scorer" }
|
|
2487
|
+
];
|
|
2488
|
+
var assertionTypes = [
|
|
2489
|
+
...baseAssertionTypes,
|
|
2490
|
+
...baseAssertionTypes.map((option) => ({
|
|
2491
|
+
value: `not-${option.value}`,
|
|
2492
|
+
label: `Not ${option.label}`
|
|
2493
|
+
}))
|
|
2494
|
+
];
|
|
2495
|
+
function assertionLabel(value) {
|
|
2496
|
+
return assertionTypes.find((option) => option.value === value)?.label ?? value;
|
|
2497
|
+
}
|
|
2498
|
+
|
|
2162
2499
|
// src/backend/roleplay/router.ts
|
|
2163
2500
|
var AgentIdSchema = z4.string().trim().min(1).max(512);
|
|
2164
2501
|
var ConversationIdSchema = z4.string().trim().min(1).max(64);
|
|
@@ -2232,7 +2569,7 @@ function createRolePlayRouter(t2) {
|
|
|
2232
2569
|
prompt: z4.string().max(1e6)
|
|
2233
2570
|
})
|
|
2234
2571
|
).mutation(async ({ input, ctx }) => {
|
|
2235
|
-
await
|
|
2572
|
+
await withPromptFileLock(ctx, input.agentId, input.step, (file) => file.write(input.prompt));
|
|
2236
2573
|
return { ok: true };
|
|
2237
2574
|
}),
|
|
2238
2575
|
suggestPromptEdit: t2.procedure.input(
|
|
@@ -2258,12 +2595,109 @@ function createRolePlayRouter(t2) {
|
|
|
2258
2595
|
});
|
|
2259
2596
|
return { status: "changed", proposal };
|
|
2260
2597
|
}),
|
|
2598
|
+
suggestTestFix: t2.procedure.input(
|
|
2599
|
+
z4.object({
|
|
2600
|
+
agentId: AgentIdSchema,
|
|
2601
|
+
testId: z4.string(),
|
|
2602
|
+
step: z4.string().trim().min(1).max(512),
|
|
2603
|
+
request: z4.string().trim().min(1).max(1e5),
|
|
2604
|
+
prompt: z4.string().max(1e6),
|
|
2605
|
+
basePrompt: z4.string().max(1e6),
|
|
2606
|
+
currentIncorrectOutcome: z4.string().max(1e6),
|
|
2607
|
+
progressId: z4.string().uuid()
|
|
2608
|
+
})
|
|
2609
|
+
).mutation(async ({ input, ctx }) => {
|
|
2610
|
+
const suiteKey = input.agentId;
|
|
2611
|
+
const test = (await readSuite(ctx, suiteKey)).tests.find((row) => row.id === input.testId);
|
|
2612
|
+
if (!test) throw new Error("This test is no longer available.");
|
|
2613
|
+
await withPromptFileLock(ctx, input.agentId, input.step, async (file) => {
|
|
2614
|
+
const currentPrompt = await file.read();
|
|
2615
|
+
if (currentPrompt !== input.basePrompt && currentPrompt !== input.prompt) {
|
|
2616
|
+
throw new Error(
|
|
2617
|
+
"The prompt changed before Bosun could start this Fix. Check the prompt, then try again."
|
|
2618
|
+
);
|
|
2619
|
+
}
|
|
2620
|
+
if (currentPrompt !== input.prompt) await file.write(input.prompt);
|
|
2621
|
+
});
|
|
2622
|
+
const originalPrompt = input.prompt;
|
|
2623
|
+
const context = JSON.stringify(test.context ?? {});
|
|
2624
|
+
const assertionLabel2 = test.evaluation_mode === "json-deep-equal" ? "" : assertionLabel(test.assertion_type);
|
|
2625
|
+
const assertionValue = test.evaluation_mode === "json-deep-equal" ? "" : test.assertion_value;
|
|
2626
|
+
const suggestion = await suggestTestFix(ctx, {
|
|
2627
|
+
request: input.request,
|
|
2628
|
+
originalPrompt,
|
|
2629
|
+
context,
|
|
2630
|
+
conversation: test.conversation,
|
|
2631
|
+
expectedOutput: test.expected_output,
|
|
2632
|
+
assertionLabel: assertionLabel2,
|
|
2633
|
+
assertionValue,
|
|
2634
|
+
currentIncorrectOutcome: input.currentIncorrectOutcome,
|
|
2635
|
+
onProgress: (progress) => updatePromptEditProgress(input.progressId, progress)
|
|
2636
|
+
});
|
|
2637
|
+
const originalTestFingerprint = testEditSourceFingerprint(test);
|
|
2638
|
+
const historyTestFingerprint = testEditSourceFingerprint(test, {
|
|
2639
|
+
conversation: suggestion.suggestedConversation
|
|
2640
|
+
});
|
|
2641
|
+
const history = suggestion.suggestedConversation === test.conversation ? { status: "unchanged" } : {
|
|
2642
|
+
status: "changed",
|
|
2643
|
+
proposal: createTestHistoryEditProposal({
|
|
2644
|
+
agentId: input.agentId,
|
|
2645
|
+
testId: input.testId,
|
|
2646
|
+
step: input.step,
|
|
2647
|
+
originalConversation: test.conversation,
|
|
2648
|
+
suggestedConversation: suggestion.suggestedConversation,
|
|
2649
|
+
expectedOutput: test.expected_output,
|
|
2650
|
+
sourceGuard: {
|
|
2651
|
+
suiteKey,
|
|
2652
|
+
allowedTestFingerprints: [originalTestFingerprint],
|
|
2653
|
+
allowedPromptContents: [originalPrompt, suggestion.suggestedPrompt]
|
|
2654
|
+
}
|
|
2655
|
+
})
|
|
2656
|
+
};
|
|
2657
|
+
const prompt = suggestion.suggestedPrompt === originalPrompt ? { status: "unchanged" } : {
|
|
2658
|
+
status: "changed",
|
|
2659
|
+
proposal: createPromptEditProposal({
|
|
2660
|
+
agentId: input.agentId,
|
|
2661
|
+
step: input.step,
|
|
2662
|
+
originalPrompt,
|
|
2663
|
+
suggestedPrompt: suggestion.suggestedPrompt,
|
|
2664
|
+
testSourceGuard: {
|
|
2665
|
+
suiteKey,
|
|
2666
|
+
testId: input.testId,
|
|
2667
|
+
allowedFingerprints: [originalTestFingerprint, historyTestFingerprint]
|
|
2668
|
+
}
|
|
2669
|
+
})
|
|
2670
|
+
};
|
|
2671
|
+
return { history, prompt };
|
|
2672
|
+
}),
|
|
2261
2673
|
promptEditProgress: t2.procedure.input(z4.object({ id: z4.string().uuid() })).query(({ input }) => getPromptEditProgress(input.id)),
|
|
2262
2674
|
promptEditProposal: t2.procedure.input(z4.object({ id: z4.string().uuid() })).query(({ input }) => getPromptEditProposal(input.id)),
|
|
2263
2675
|
acceptPromptEdit: write.input(z4.object({ id: z4.string().uuid() })).mutation(async ({ input, ctx }) => {
|
|
2264
|
-
const proposal =
|
|
2676
|
+
const proposal = getPromptEditProposalForAcceptance(input.id);
|
|
2265
2677
|
if (!proposal) throw new Error("This prompt suggestion is no longer available");
|
|
2266
|
-
await
|
|
2678
|
+
await withPromptFileLock(ctx, proposal.agentId, proposal.step, async (file) => {
|
|
2679
|
+
if (await file.read() !== proposal.originalPrompt) {
|
|
2680
|
+
throw new Error(
|
|
2681
|
+
"The prompt changed while this suggestion was open. Reject this suggestion, then ask Bosun to create a new one."
|
|
2682
|
+
);
|
|
2683
|
+
}
|
|
2684
|
+
const guard = proposal.testSourceGuard;
|
|
2685
|
+
if (!guard) {
|
|
2686
|
+
await file.write(proposal.suggestedPrompt);
|
|
2687
|
+
return;
|
|
2688
|
+
}
|
|
2689
|
+
await withSuiteMutationLock(guard.suiteKey, async () => {
|
|
2690
|
+
const test = (await readSuite(ctx, guard.suiteKey)).tests.find(
|
|
2691
|
+
(row) => row.id === guard.testId
|
|
2692
|
+
);
|
|
2693
|
+
if (!test || !guard.allowedFingerprints.includes(testEditSourceFingerprint(test))) {
|
|
2694
|
+
throw new Error(
|
|
2695
|
+
"This test changed while the suggestion was open. Reject this suggestion, then ask Bosun to create a new one."
|
|
2696
|
+
);
|
|
2697
|
+
}
|
|
2698
|
+
await file.write(proposal.suggestedPrompt);
|
|
2699
|
+
});
|
|
2700
|
+
});
|
|
2267
2701
|
deletePromptEditProposal(proposal.id);
|
|
2268
2702
|
return { ok: true, prompt: proposal.suggestedPrompt };
|
|
2269
2703
|
}),
|
|
@@ -2309,12 +2743,7 @@ function createRolePlayRouter(t2) {
|
|
|
2309
2743
|
promptOverrides: input.promptOverrides ?? {}
|
|
2310
2744
|
});
|
|
2311
2745
|
}),
|
|
2312
|
-
commitVariant: write.input(
|
|
2313
|
-
z4.object({
|
|
2314
|
-
conversationId: ConversationIdSchema,
|
|
2315
|
-
entries: z4.array(z4.any())
|
|
2316
|
-
})
|
|
2317
|
-
).mutation(async ({ input, ctx }) => {
|
|
2746
|
+
commitVariant: write.input(z4.object({ conversationId: ConversationIdSchema, entries: z4.array(z4.any()) })).mutation(async ({ input, ctx }) => {
|
|
2318
2747
|
const conversation = await loadConversation(ctx, input.conversationId);
|
|
2319
2748
|
const turn = lastTurn(conversation);
|
|
2320
2749
|
if (!turn) throw new Error("This conversation has no reply to replace");
|
|
@@ -2333,21 +2762,6 @@ function createRolePlayRouter(t2) {
|
|
|
2333
2762
|
})
|
|
2334
2763
|
});
|
|
2335
2764
|
}
|
|
2336
|
-
async function persistPromptUpdate(ctx, agentId, stepName, prompt) {
|
|
2337
|
-
const { basePath, steps } = await getAgentSteps(ctx, agentId);
|
|
2338
|
-
const targetStep = steps.find((step) => step?.name === stepName);
|
|
2339
|
-
if (!targetStep || targetStep?.prompt?.type !== "file") return;
|
|
2340
|
-
const promptPath = path8.resolve(basePath, targetStep.prompt.path);
|
|
2341
|
-
await fs3.promises.writeFile(promptPath, prompt, "utf-8");
|
|
2342
|
-
}
|
|
2343
|
-
async function readEditablePrompt(ctx, agentId, stepName) {
|
|
2344
|
-
const { steps } = await getAgentSteps(ctx, agentId);
|
|
2345
|
-
const targetStep = steps.find((step) => step?.name === stepName);
|
|
2346
|
-
if (!targetStep || targetStep?.prompt?.type !== "file") {
|
|
2347
|
-
throw new Error(`Step '${stepName}' does not have an editable file prompt`);
|
|
2348
|
-
}
|
|
2349
|
-
return targetStep.prompt.content();
|
|
2350
|
-
}
|
|
2351
2765
|
|
|
2352
2766
|
// src/backend/roleplay/conversations-router.ts
|
|
2353
2767
|
import { z as z5 } from "zod";
|
|
@@ -2405,7 +2819,7 @@ import "@recombine-ai/telescope";
|
|
|
2405
2819
|
|
|
2406
2820
|
// src/backend/prompt-cache.ts
|
|
2407
2821
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2408
|
-
import { randomUUID as
|
|
2822
|
+
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
2409
2823
|
var cacheBustContext = new AsyncLocalStorage();
|
|
2410
2824
|
function withTestPromptCacheBust(run) {
|
|
2411
2825
|
return cacheBustContext.run(true, run);
|
|
@@ -2423,7 +2837,7 @@ function wrapCreate(resource) {
|
|
|
2423
2837
|
return Reflect.apply(originalCreate, this, [body, ...args]);
|
|
2424
2838
|
}
|
|
2425
2839
|
return Reflect.apply(originalCreate, this, [
|
|
2426
|
-
{ ...body, prompt_cache_key: `bosun-test-${
|
|
2840
|
+
{ ...body, prompt_cache_key: `bosun-test-${randomUUID5()}` },
|
|
2427
2841
|
...args
|
|
2428
2842
|
]);
|
|
2429
2843
|
};
|
|
@@ -2774,6 +3188,12 @@ function gradeJsonExpectedFields(output, expectedOutput, caseSensitive = false)
|
|
|
2774
3188
|
}
|
|
2775
3189
|
|
|
2776
3190
|
// src/backend/tests/academy.ts
|
|
3191
|
+
function applyTestHistoryOverrides(rows, overrides) {
|
|
3192
|
+
return rows.map((row) => {
|
|
3193
|
+
const override = overrides[typeof row.id === "string" ? row.id : ""];
|
|
3194
|
+
return override ? { ...row, conversation: override.conversation } : row;
|
|
3195
|
+
});
|
|
3196
|
+
}
|
|
2777
3197
|
var activeRuns = new ActiveTestRuns();
|
|
2778
3198
|
function getPromptTestsProgress(suiteKey) {
|
|
2779
3199
|
const progress = activeRuns.getProgress(suiteKey);
|
|
@@ -2787,13 +3207,14 @@ function getPromptTestsProgress(suiteKey) {
|
|
|
2787
3207
|
function cancelPromptTests(suiteKey) {
|
|
2788
3208
|
return activeRuns.cancel(suiteKey);
|
|
2789
3209
|
}
|
|
2790
|
-
async function runPromptTestsManaged(ctx, suite, selection, requestedConfig, promptOverrides = {}) {
|
|
3210
|
+
async function runPromptTestsManaged(ctx, suite, selection, requestedConfig, promptOverrides = {}, testHistoryOverrides = {}) {
|
|
2791
3211
|
const run = activeRuns.start(suite.suiteKey);
|
|
2792
3212
|
if (!run) throw new Error("Tests already running for this agent");
|
|
2793
3213
|
try {
|
|
2794
3214
|
return await runPromptTests(ctx, suite, selection, requestedConfig, {
|
|
2795
3215
|
signal: run.controller.signal,
|
|
2796
3216
|
promptOverrides,
|
|
3217
|
+
testHistoryOverrides,
|
|
2797
3218
|
setProgress: (progress) => activeRuns.setProgress(suite.suiteKey, run, progress)
|
|
2798
3219
|
});
|
|
2799
3220
|
} finally {
|
|
@@ -2863,12 +3284,7 @@ function toTestInputs(rows, selection = { scope: "pinned" }) {
|
|
|
2863
3284
|
type: "javascript",
|
|
2864
3285
|
value: (output) => gradeJsonExpectedFields(output, row.expected_output, row.case_sensitive === true)
|
|
2865
3286
|
}
|
|
2866
|
-
] : [
|
|
2867
|
-
{
|
|
2868
|
-
type: row.assertion_type,
|
|
2869
|
-
value: row.assertion_value
|
|
2870
|
-
}
|
|
2871
|
-
];
|
|
3287
|
+
] : [{ type: row.assertion_type, value: row.assertion_value }];
|
|
2872
3288
|
return {
|
|
2873
3289
|
id: row.id,
|
|
2874
3290
|
scenario: row.scenario,
|
|
@@ -3118,7 +3534,7 @@ async function runPromptTests(ctx, suite, selection, requestedConfig, opts) {
|
|
|
3118
3534
|
const onlyTestId = "testId" in selection ? selection.testId : void 0;
|
|
3119
3535
|
const suiteKey = suite.suiteKey;
|
|
3120
3536
|
const loadedSuite = await readSuite(ctx, suiteKey);
|
|
3121
|
-
const rows = loadedSuite.tests;
|
|
3537
|
+
const rows = applyTestHistoryOverrides(loadedSuite.tests, opts?.testHistoryOverrides ?? {});
|
|
3122
3538
|
const repeats = Math.min(500, Math.max(1, Math.floor(Number(requestedConfig.repeats) || 1)));
|
|
3123
3539
|
const concurrency = Math.min(
|
|
3124
3540
|
75,
|
|
@@ -3140,9 +3556,7 @@ async function runPromptTests(ctx, suite, selection, requestedConfig, opts) {
|
|
|
3140
3556
|
completedRunsByTestId: /* @__PURE__ */ new Map()
|
|
3141
3557
|
};
|
|
3142
3558
|
if (opts?.setProgress && !opts.setProgress(progress)) throw new Error("Operation cancelled");
|
|
3143
|
-
const providerInstance = new RecombineAgentProvider(ctx, {
|
|
3144
|
-
id: "recombine-agent"
|
|
3145
|
-
});
|
|
3559
|
+
const providerInstance = new RecombineAgentProvider(ctx, { id: "recombine-agent" });
|
|
3146
3560
|
providerInstance.setAbortSignal(signal);
|
|
3147
3561
|
providerInstance.setOnTestStarted((testId) => {
|
|
3148
3562
|
if (progress.completedTestIds.includes(testId)) return;
|
|
@@ -3207,10 +3621,7 @@ async function runPromptTests(ctx, suite, selection, requestedConfig, opts) {
|
|
|
3207
3621
|
await rename3(tmpPath, outPath);
|
|
3208
3622
|
}
|
|
3209
3623
|
}
|
|
3210
|
-
const runConfig = {
|
|
3211
|
-
repeats,
|
|
3212
|
-
concurrency
|
|
3213
|
-
};
|
|
3624
|
+
const runConfig = { repeats, concurrency };
|
|
3214
3625
|
const body = {
|
|
3215
3626
|
agent: suiteKey,
|
|
3216
3627
|
run_timestamp: iso,
|
|
@@ -3571,7 +3982,7 @@ var PIIFindingSchema = z7.object({
|
|
|
3571
3982
|
}).strict();
|
|
3572
3983
|
|
|
3573
3984
|
// src/backend/tests/pii-sanitized-test-drafts.ts
|
|
3574
|
-
import { randomUUID as
|
|
3985
|
+
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
3575
3986
|
|
|
3576
3987
|
// src/backend/tests/pii-sanitizer.ts
|
|
3577
3988
|
import { z as z8 } from "zod";
|
|
@@ -3795,7 +4206,7 @@ async function createPIISanitizedTestDraft(ctx, input, dependencies = {}) {
|
|
|
3795
4206
|
pruneExpiredDrafts(dependencies.now?.() ?? Date.now());
|
|
3796
4207
|
const seed = TraceTestSeedSchema.parse(input.seed);
|
|
3797
4208
|
const sanitized = await (dependencies.sanitize ?? ((s) => sanitizeTraceTestSeed(ctx, s)))(seed);
|
|
3798
|
-
const draftId =
|
|
4209
|
+
const draftId = randomUUID6();
|
|
3799
4210
|
const expiresAt = (dependencies.now?.() ?? Date.now()) + DRAFT_TTL_MS;
|
|
3800
4211
|
drafts.set(draftId, {
|
|
3801
4212
|
suiteKey: input.suiteKey,
|
|
@@ -3863,12 +4274,7 @@ function createTestsRouter(t2) {
|
|
|
3863
4274
|
latestResult: t2.procedure.input(z9.object({ agent: z9.string() })).query(async ({ input, ctx }) => loadLatestResultsByTest(ctx, input.agent)),
|
|
3864
4275
|
runProgress: t2.procedure.input(z9.object({ agent: z9.string() })).query(async ({ input }) => getPromptTestsProgress(input.agent)),
|
|
3865
4276
|
historyList: t2.procedure.input(z9.object({ agent: z9.string() })).query(async ({ input, ctx }) => listRunHistory(ctx, input.agent)),
|
|
3866
|
-
historyRun: t2.procedure.input(
|
|
3867
|
-
z9.object({
|
|
3868
|
-
agent: z9.string(),
|
|
3869
|
-
timestamp: z9.string()
|
|
3870
|
-
})
|
|
3871
|
-
).query(async ({ input, ctx }) => getRunHistory(ctx, input.agent, input.timestamp)),
|
|
4277
|
+
historyRun: t2.procedure.input(z9.object({ agent: z9.string(), timestamp: z9.string() })).query(async ({ input, ctx }) => getRunHistory(ctx, input.agent, input.timestamp)),
|
|
3872
4278
|
resultEntry: t2.procedure.input(
|
|
3873
4279
|
z9.object({
|
|
3874
4280
|
agent: z9.string(),
|
|
@@ -3903,28 +4309,59 @@ function createTestsRouter(t2) {
|
|
|
3903
4309
|
timestamp: input.timestamp
|
|
3904
4310
|
});
|
|
3905
4311
|
}),
|
|
3906
|
-
findPromptIssues: t2.procedure.input(
|
|
4312
|
+
findPromptIssues: t2.procedure.input(z9.object({ agent: z9.string(), step: z9.string(), prompt: z9.string() })).mutation(async ({ input, ctx }) => {
|
|
4313
|
+
return findPromptIssues(ctx, input);
|
|
4314
|
+
}),
|
|
4315
|
+
suggestHistoryEdit: t2.procedure.input(
|
|
3907
4316
|
z9.object({
|
|
3908
4317
|
agent: z9.string(),
|
|
3909
|
-
|
|
3910
|
-
|
|
4318
|
+
testId: z9.string(),
|
|
4319
|
+
step: z9.string().trim().min(1).max(512),
|
|
4320
|
+
request: z9.string().trim().min(1).max(1e5),
|
|
4321
|
+
prompt: z9.string().max(1e6),
|
|
4322
|
+
basePrompt: z9.string().max(1e6),
|
|
4323
|
+
progressId: z9.string().uuid()
|
|
3911
4324
|
})
|
|
3912
4325
|
).mutation(async ({ input, ctx }) => {
|
|
3913
|
-
|
|
4326
|
+
const suiteKey = input.agent;
|
|
4327
|
+
const test = (await readSuite(ctx, suiteKey)).tests.find((row) => row.id === input.testId);
|
|
4328
|
+
if (!test) throw new Error("This test is no longer available.");
|
|
4329
|
+
const suggestedConversation = await suggestTestHistoryEdit(ctx, {
|
|
4330
|
+
request: input.request,
|
|
4331
|
+
prompt: input.prompt,
|
|
4332
|
+
context: JSON.stringify(test.context ?? {}, null, 2),
|
|
4333
|
+
conversation: test.conversation,
|
|
4334
|
+
expectedOutput: test.expected_output,
|
|
4335
|
+
onProgress: (progress) => updatePromptEditProgress(input.progressId, progress)
|
|
4336
|
+
});
|
|
4337
|
+
return suggestedConversation === test.conversation ? { status: "unchanged" } : {
|
|
4338
|
+
status: "changed",
|
|
4339
|
+
proposal: createTestHistoryEditProposal({
|
|
4340
|
+
agentId: input.agent,
|
|
4341
|
+
testId: input.testId,
|
|
4342
|
+
step: input.step,
|
|
4343
|
+
originalConversation: test.conversation,
|
|
4344
|
+
suggestedConversation,
|
|
4345
|
+
expectedOutput: test.expected_output,
|
|
4346
|
+
sourceGuard: {
|
|
4347
|
+
suiteKey,
|
|
4348
|
+
allowedTestFingerprints: [testEditSourceFingerprint(test)],
|
|
4349
|
+
allowedPromptContents: [input.basePrompt, input.prompt]
|
|
4350
|
+
}
|
|
4351
|
+
})
|
|
4352
|
+
};
|
|
3914
4353
|
}),
|
|
3915
4354
|
suite: t2.procedure.input(z9.object({ agent: z9.string() })).query(async ({ input, ctx }) => readSuite(ctx, input.agent)),
|
|
3916
4355
|
addTest: write.input(
|
|
3917
4356
|
z9.object({
|
|
3918
4357
|
agent: z9.string(),
|
|
4358
|
+
beforeTestId: z9.string().optional(),
|
|
3919
4359
|
seed: TestRowSchema.omit({ id: true, order: true }).partial()
|
|
3920
4360
|
})
|
|
3921
|
-
).mutation(
|
|
3922
|
-
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
seed: TraceTestSeedSchema
|
|
3926
|
-
})
|
|
3927
|
-
).mutation(async ({ input, ctx }) => {
|
|
4361
|
+
).mutation(
|
|
4362
|
+
async ({ input, ctx }) => addTest(ctx, input.agent, input.seed, { beforeTestId: input.beforeTestId })
|
|
4363
|
+
),
|
|
4364
|
+
createPIISanitizedTestDraft: t2.procedure.input(z9.object({ agent: z9.string(), seed: TraceTestSeedSchema })).mutation(async ({ input, ctx }) => {
|
|
3928
4365
|
try {
|
|
3929
4366
|
const draft = await createPIISanitizedTestDraft(ctx, {
|
|
3930
4367
|
suiteKey: input.agent,
|
|
@@ -3960,6 +4397,41 @@ function createTestsRouter(t2) {
|
|
|
3960
4397
|
patch: TestRowSchema.omit({ id: true, order: true }).partial()
|
|
3961
4398
|
})
|
|
3962
4399
|
).mutation(async ({ input, ctx }) => patchTest(ctx, input.agent, input.id, input.patch)),
|
|
4400
|
+
acceptHistoryEdit: write.input(z9.object({ id: z9.string().uuid() })).mutation(async ({ input, ctx }) => {
|
|
4401
|
+
const proposal = getTestHistoryEditProposalForAcceptance(input.id);
|
|
4402
|
+
if (!proposal) throw new Error("This test history suggestion is no longer available.");
|
|
4403
|
+
const result = await withPromptFileLock(
|
|
4404
|
+
ctx,
|
|
4405
|
+
proposal.agentId,
|
|
4406
|
+
proposal.step,
|
|
4407
|
+
async (file) => {
|
|
4408
|
+
if (!proposal.sourceGuard.allowedPromptContents.includes(await file.read())) {
|
|
4409
|
+
throw new Error(
|
|
4410
|
+
"The prompt changed while this suggestion was open. Reject this suggestion, then ask Bosun to create a new one."
|
|
4411
|
+
);
|
|
4412
|
+
}
|
|
4413
|
+
return patchTestConversationIfCurrent(
|
|
4414
|
+
ctx,
|
|
4415
|
+
proposal.sourceGuard.suiteKey,
|
|
4416
|
+
proposal.testId,
|
|
4417
|
+
proposal.originalConversation,
|
|
4418
|
+
proposal.suggestedConversation,
|
|
4419
|
+
proposal.sourceGuard.allowedTestFingerprints
|
|
4420
|
+
);
|
|
4421
|
+
}
|
|
4422
|
+
);
|
|
4423
|
+
if (result.status === "not-found") {
|
|
4424
|
+
throw new Error("This test is no longer available.");
|
|
4425
|
+
}
|
|
4426
|
+
if (result.status === "stale") {
|
|
4427
|
+
throw new Error(
|
|
4428
|
+
"This test changed while the suggestion was open. Reject this suggestion, then ask Bosun to create a new one."
|
|
4429
|
+
);
|
|
4430
|
+
}
|
|
4431
|
+
deleteTestHistoryEditProposal(proposal.id);
|
|
4432
|
+
return { ok: true, test: result.test };
|
|
4433
|
+
}),
|
|
4434
|
+
rejectHistoryEdit: t2.procedure.input(z9.object({ id: z9.string().uuid() })).mutation(({ input }) => ({ ok: deleteTestHistoryEditProposal(input.id) })),
|
|
3963
4435
|
patchTestsBatch: write.input(
|
|
3964
4436
|
z9.object({
|
|
3965
4437
|
agent: z9.string(),
|
|
@@ -3980,6 +4452,7 @@ function createTestsRouter(t2) {
|
|
|
3980
4452
|
step: z9.string(),
|
|
3981
4453
|
scope: z9.enum(["pinned", "all"]).optional(),
|
|
3982
4454
|
promptOverrides: z9.record(z9.string(), z9.string().max(1e6)).optional(),
|
|
4455
|
+
testHistoryOverrides: z9.record(z9.string(), z9.object({ conversation: z9.string().max(1e6) }).strict()).optional(),
|
|
3983
4456
|
repeats: z9.number().int().min(1).max(500),
|
|
3984
4457
|
concurrency: z9.number().int().min(1).max(75)
|
|
3985
4458
|
}).strict(),
|
|
@@ -3987,6 +4460,7 @@ function createTestsRouter(t2) {
|
|
|
3987
4460
|
agent: z9.string(),
|
|
3988
4461
|
testId: z9.string(),
|
|
3989
4462
|
promptOverrides: z9.record(z9.string(), z9.string().max(1e6)).optional(),
|
|
4463
|
+
testHistoryOverrides: z9.record(z9.string(), z9.object({ conversation: z9.string().max(1e6) }).strict()).optional(),
|
|
3990
4464
|
repeats: z9.number().int().min(1).max(500),
|
|
3991
4465
|
concurrency: z9.number().int().min(1).max(75)
|
|
3992
4466
|
}).strict()
|
|
@@ -4000,18 +4474,17 @@ function createTestsRouter(t2) {
|
|
|
4000
4474
|
selection,
|
|
4001
4475
|
{ testId: input.testId },
|
|
4002
4476
|
runConfig,
|
|
4003
|
-
input.promptOverrides
|
|
4477
|
+
input.promptOverrides,
|
|
4478
|
+
input.testHistoryOverrides
|
|
4004
4479
|
);
|
|
4005
4480
|
}
|
|
4006
4481
|
return runPromptTestsManaged(
|
|
4007
4482
|
ctx,
|
|
4008
4483
|
selection,
|
|
4009
|
-
{
|
|
4010
|
-
scope: input.scope ?? "pinned",
|
|
4011
|
-
step: input.step
|
|
4012
|
-
},
|
|
4484
|
+
{ scope: input.scope ?? "pinned", step: input.step },
|
|
4013
4485
|
runConfig,
|
|
4014
|
-
input.promptOverrides
|
|
4486
|
+
input.promptOverrides,
|
|
4487
|
+
input.testHistoryOverrides
|
|
4015
4488
|
);
|
|
4016
4489
|
}),
|
|
4017
4490
|
cancelRun: t2.procedure.input(z9.object({ agent: z9.string() })).mutation(async ({ input }) => cancelPromptTests(input.agent))
|
|
@@ -4047,6 +4520,21 @@ var PaginatedConversationsResponseSchema = z10.object({
|
|
|
4047
4520
|
items: z10.array(ConversationSchema),
|
|
4048
4521
|
lastConversationId: z10.string().optional()
|
|
4049
4522
|
});
|
|
4523
|
+
var AnalyticsScalarSchema = z10.union([z10.boolean(), z10.number(), z10.string()]);
|
|
4524
|
+
var AnalyticsFieldSchema = z10.object({
|
|
4525
|
+
key: z10.string(),
|
|
4526
|
+
type: z10.enum(["boolean", "number", "string"]),
|
|
4527
|
+
variantCount: z10.number(),
|
|
4528
|
+
values: z10.array(
|
|
4529
|
+
z10.object({
|
|
4530
|
+
value: AnalyticsScalarSchema,
|
|
4531
|
+
count: z10.number()
|
|
4532
|
+
})
|
|
4533
|
+
)
|
|
4534
|
+
});
|
|
4535
|
+
var AnalyticsFieldsResponseSchema = z10.object({
|
|
4536
|
+
items: z10.array(AnalyticsFieldSchema)
|
|
4537
|
+
});
|
|
4050
4538
|
var LlmUsageSchema = z10.object({
|
|
4051
4539
|
promptTokens: z10.number().optional(),
|
|
4052
4540
|
completionTokens: z10.number().optional(),
|
|
@@ -4130,6 +4618,11 @@ var PaginatedLatencyTracesResponseSchema = z10.object({
|
|
|
4130
4618
|
var SourceIdSchema = z11.string().trim().max(128).optional();
|
|
4131
4619
|
var ConversationIdSchema3 = z11.string().trim().min(1).max(256);
|
|
4132
4620
|
var LimitSchema = z11.number().int().positive().max(1e3).optional();
|
|
4621
|
+
var AnalyticsFilterSchema = z11.object({
|
|
4622
|
+
key: z11.string().trim().min(1).max(256),
|
|
4623
|
+
type: z11.enum(["boolean", "number", "string"]),
|
|
4624
|
+
values: z11.array(AnalyticsScalarSchema).min(1)
|
|
4625
|
+
});
|
|
4133
4626
|
var ConversationsPageSchema = PaginatedConversationsResponseSchema.extend({
|
|
4134
4627
|
items: z11.array(ConversationSchema).optional()
|
|
4135
4628
|
});
|
|
@@ -4160,13 +4653,20 @@ function createTelescopeRouter(t2) {
|
|
|
4160
4653
|
limit: LimitSchema,
|
|
4161
4654
|
lastConversationId: z11.string().trim().min(1).optional(),
|
|
4162
4655
|
phoneNumber: z11.string().trim().min(1).optional(),
|
|
4163
|
-
agentId: z11.string().trim().min(1).optional()
|
|
4656
|
+
agentId: z11.string().trim().min(1).optional(),
|
|
4657
|
+
analyticsFilters: z11.array(AnalyticsFilterSchema).optional()
|
|
4164
4658
|
})
|
|
4165
4659
|
).query(async ({ input, ctx }) => {
|
|
4166
4660
|
const search = new URLSearchParams({ limit: String(input.limit ?? 10) });
|
|
4167
4661
|
if (input.lastConversationId) search.set("lastConversationId", input.lastConversationId);
|
|
4168
4662
|
if (input.phoneNumber) search.set("phoneNumber", input.phoneNumber);
|
|
4169
4663
|
if (input.agentId) search.set("agentId", input.agentId);
|
|
4664
|
+
if (input.analyticsFilters?.length) {
|
|
4665
|
+
search.set(
|
|
4666
|
+
"filters",
|
|
4667
|
+
JSON.stringify(input.analyticsFilters.map((filter) => ({ ...filter, operator: "in" })))
|
|
4668
|
+
);
|
|
4669
|
+
}
|
|
4170
4670
|
const page = await get(ctx, {
|
|
4171
4671
|
sourceId: input.sourceId,
|
|
4172
4672
|
path: "conversations",
|
|
@@ -4182,6 +4682,16 @@ function createTelescopeRouter(t2) {
|
|
|
4182
4682
|
}))
|
|
4183
4683
|
};
|
|
4184
4684
|
}),
|
|
4685
|
+
analyticsFields: t2.procedure.input(z11.object({ sourceId: SourceIdSchema, agentId: z11.string().trim().min(1).optional() })).query(({ input, ctx }) => {
|
|
4686
|
+
const search = new URLSearchParams();
|
|
4687
|
+
if (input.agentId) search.set("agentId", input.agentId);
|
|
4688
|
+
return get(ctx, {
|
|
4689
|
+
sourceId: input.sourceId,
|
|
4690
|
+
path: "analytics/fields",
|
|
4691
|
+
search,
|
|
4692
|
+
schema: AnalyticsFieldsResponseSchema
|
|
4693
|
+
});
|
|
4694
|
+
}),
|
|
4185
4695
|
conversation: t2.procedure.input(z11.object({ sourceId: SourceIdSchema, conversationId: ConversationIdSchema3 })).query(
|
|
4186
4696
|
({ input, ctx }) => get(ctx, {
|
|
4187
4697
|
sourceId: input.sourceId,
|