@cursor/july 0.1.111 → 0.1.113
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/dist/bin/agent-serve.js +20 -4
- package/dist/channels/checks.d.ts +10 -0
- package/dist/channels/checks.d.ts.map +1 -1
- package/dist/channels/github/github-channel.d.ts +29 -19
- package/dist/channels/github/github-channel.d.ts.map +1 -1
- package/dist/channels/github/github-channel.js +29 -19
- package/dist/channels/origin/checks.d.ts +1 -1
- package/dist/channels/origin/checks.d.ts.map +1 -1
- package/dist/channels/slack/agentic-delivery.d.ts.map +1 -1
- package/dist/channels/slack/agentic-delivery.js +2 -0
- package/dist/channels/slack/dispatch.d.ts +11 -1
- package/dist/channels/slack/dispatch.d.ts.map +1 -1
- package/dist/channels/slack/dispatch.js +146 -39
- package/dist/channels/slack/placeholder.d.ts +26 -0
- package/dist/channels/slack/placeholder.d.ts.map +1 -1
- package/dist/channels/slack/placeholder.js +28 -0
- package/dist/channels/slack/slack-channel.d.ts.map +1 -1
- package/dist/channels/slack/slack-channel.js +9 -16
- package/dist/docs/404.html +2 -2
- package/dist/docs/assets/{app.Drol6mi6.js → app.CAeK13eM.js} +4 -4
- package/dist/docs/assets/building-with-agents.md.BBCx0AUo.js +9 -0
- package/dist/docs/assets/building-with-agents.md.BBCx0AUo.lean.js +1 -0
- package/dist/docs/assets/chunks/@localSearchIndexroot.Ck9E52Ls.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.CdqoBZJX.js → VPLocalSearchBox.C9LbPHod.js} +1 -1
- package/dist/docs/assets/chunks/{arc.BVX3ycTn.js → arc.CmMq2zmS.js} +1 -1
- package/dist/docs/assets/chunks/{architectureDiagram-Q4EWVU46.CcChnMxX.js → architectureDiagram-Q4EWVU46.CCXB8Uj5.js} +1 -1
- package/dist/docs/assets/chunks/{baseUniq.xwtXO-yt.js → baseUniq.CyQo6eLe.js} +1 -1
- package/dist/docs/assets/chunks/{blockDiagram-DXYQGD6D.CijZ_taK.js → blockDiagram-DXYQGD6D.JYq6w91N.js} +1 -1
- package/dist/docs/assets/chunks/{c4Diagram-AHTNJAMY.0FBvwBvK.js → c4Diagram-AHTNJAMY.BRV8GPJJ.js} +1 -1
- package/dist/docs/assets/chunks/channel.BHiYmnZ4.js +1 -0
- package/dist/docs/assets/chunks/{chunk-4BX2VUAB.CELMmMDA.js → chunk-4BX2VUAB.Bv4ooYQR.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-4TB4RGXK.C4bhFtSm.js → chunk-4TB4RGXK.t4JtKPcj.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-55IACEB6.ZnQ9gRRQ.js → chunk-55IACEB6.34lCHj9Y.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-EDXVE4YY.DPlmglG-.js → chunk-EDXVE4YY.BSwrPNrt.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-FMBD7UC4.BrUk8pff.js → chunk-FMBD7UC4.Beeun-R-.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-OYMX7WX6.CcmWIncu.js → chunk-OYMX7WX6.BUUFUcJc.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-QZHKN3VN.D65-cs8I.js → chunk-QZHKN3VN.B2XjHzN_.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-YZCP3GAM.qoXZpG9F.js → chunk-YZCP3GAM.CLYG8znk.js} +1 -1
- package/dist/docs/assets/chunks/classDiagram-6PBFFD2Q.Degh8l90.js +1 -0
- package/dist/docs/assets/chunks/classDiagram-v2-HSJHXN6E.Degh8l90.js +1 -0
- package/dist/docs/assets/chunks/clone.BIywbczV.js +1 -0
- package/dist/docs/assets/chunks/{cose-bilkent-S5V4N54A.8rYtqudO.js → cose-bilkent-S5V4N54A.DVEa6fZp.js} +1 -1
- package/dist/docs/assets/chunks/{dagre-KV5264BT.DrRP1fOh.js → dagre-KV5264BT.C9PZQK-S.js} +1 -1
- package/dist/docs/assets/chunks/{diagram-5BDNPKRD.DHj_xA2_.js → diagram-5BDNPKRD.DoN0uv3Y.js} +1 -1
- package/dist/docs/assets/chunks/{diagram-G4DWMVQ6.Bz_6nAKj.js → diagram-G4DWMVQ6.Czv3duqx.js} +1 -1
- package/dist/docs/assets/chunks/{diagram-MMDJMWI5.BWA0xSW9.js → diagram-MMDJMWI5.BinJ5kWb.js} +1 -1
- package/dist/docs/assets/chunks/{diagram-TYMM5635.CpTJLNJI.js → diagram-TYMM5635.DW326M4K.js} +1 -1
- package/dist/docs/assets/chunks/{erDiagram-SMLLAGMA.-7AWWSrP.js → erDiagram-SMLLAGMA.U2pR_OA7.js} +1 -1
- package/dist/docs/assets/chunks/{flowDiagram-DWJPFMVM.BTnQ742_.js → flowDiagram-DWJPFMVM.ByWJXeYK.js} +1 -1
- package/dist/docs/assets/chunks/framework.BNw1pucY.js +19 -0
- package/dist/docs/assets/chunks/{ganttDiagram-T4ZO3ILL.B5_HiiQ5.js → ganttDiagram-T4ZO3ILL.OquF0Rtg.js} +1 -1
- package/dist/docs/assets/chunks/{gitGraphDiagram-UUTBAWPF.CZcNTFZd.js → gitGraphDiagram-UUTBAWPF.Bpn01P7X.js} +1 -1
- package/dist/docs/assets/chunks/{graph.V2GLaab4.js → graph.CNRB6ETL.js} +1 -1
- package/dist/docs/assets/chunks/{infoDiagram-42DDH7IO.7pZOkCCU.js → infoDiagram-42DDH7IO.CqhknMWi.js} +1 -1
- package/dist/docs/assets/chunks/{ishikawaDiagram-UXIWVN3A.DSMo3Qa3.js → ishikawaDiagram-UXIWVN3A.C6xpR2af.js} +1 -1
- package/dist/docs/assets/chunks/{journeyDiagram-VCZTEJTY.BNEgWN1S.js → journeyDiagram-VCZTEJTY.Cg5f7oB3.js} +1 -1
- package/dist/docs/assets/chunks/{kanban-definition-6JOO6SKY.B-4d4tC7.js → kanban-definition-6JOO6SKY.Cx9YTwlU.js} +1 -1
- package/dist/docs/assets/chunks/{layout.Dvbn9nSb.js → layout.ljS-wFtK.js} +1 -1
- package/dist/docs/assets/chunks/{linear.D2GM4p4b.js → linear.jSxNrsFC.js} +1 -1
- package/dist/docs/assets/chunks/{min.DVBtLK-B.js → min.Cum8AlQw.js} +1 -1
- package/dist/docs/assets/chunks/{mindmap-definition-QFDTVHPH.CnJRI55x.js → mindmap-definition-QFDTVHPH.BLiysLpe.js} +1 -1
- package/dist/docs/assets/chunks/{pieDiagram-DEJITSTG.CtoaTFlA.js → pieDiagram-DEJITSTG.BoIDyuKF.js} +1 -1
- package/dist/docs/assets/chunks/{quadrantDiagram-34T5L4WZ.DtT24_vN.js → quadrantDiagram-34T5L4WZ.DLkpDytR.js} +1 -1
- package/dist/docs/assets/chunks/{requirementDiagram-MS252O5E.CjSO4o8f.js → requirementDiagram-MS252O5E.DqTVqSu2.js} +1 -1
- package/dist/docs/assets/chunks/{sankeyDiagram-XADWPNL6.-wWiIVWa.js → sankeyDiagram-XADWPNL6.CG_6FF7j.js} +1 -1
- package/dist/docs/assets/chunks/{sequenceDiagram-FGHM5R23.DSk8s4gX.js → sequenceDiagram-FGHM5R23.BIp9602K.js} +1 -1
- package/dist/docs/assets/chunks/{stateDiagram-FHFEXIEX.BFKAsdkN.js → stateDiagram-FHFEXIEX.COSXsD9I.js} +1 -1
- package/dist/docs/assets/chunks/stateDiagram-v2-QKLJ7IA2.qrxrbFsX.js +1 -0
- package/dist/docs/assets/chunks/{theme.C0MctGaz.js → theme.CXJ7PNwy.js} +2 -2
- package/dist/docs/assets/chunks/{timeline-definition-GMOUNBTQ.TUNJbAFe.js → timeline-definition-GMOUNBTQ.CXdVqkLq.js} +1 -1
- package/dist/docs/assets/chunks/{vennDiagram-DHZGUBPP.C-RGNnk4.js → vennDiagram-DHZGUBPP.CZxGuc4r.js} +1 -1
- package/dist/docs/assets/chunks/{wardley-RL74JXVD.g5efOWmT.js → wardley-RL74JXVD.3oVgfqQk.js} +1 -1
- package/dist/docs/assets/chunks/{wardleyDiagram-NUSXRM2D.DH4zt73Y.js → wardleyDiagram-NUSXRM2D.6_irCgGJ.js} +1 -1
- package/dist/docs/assets/chunks/{xychartDiagram-5P7HB3ND.B-3k6bF6.js → xychartDiagram-5P7HB3ND.TRPe92m3.js} +1 -1
- package/dist/docs/assets/deployment.md.D2jQZuFx.js +32 -0
- package/dist/docs/assets/deployment.md.D2jQZuFx.lean.js +1 -0
- package/dist/docs/assets/evals.md.D3Y3Aixt.js +72 -0
- package/dist/docs/assets/evals.md.D3Y3Aixt.lean.js +1 -0
- package/dist/docs/assets/guides_agent-to-agent.md.CD4T5FIl.js +41 -0
- package/dist/docs/assets/guides_agent-to-agent.md.CD4T5FIl.lean.js +1 -0
- package/dist/docs/assets/guides_bitbucket.md.mpevW-VP.js +145 -0
- package/dist/docs/assets/guides_bitbucket.md.mpevW-VP.lean.js +1 -0
- package/dist/docs/assets/guides_cloud-agents.md.Cp1O3u-X.js +15 -0
- package/dist/docs/assets/guides_cloud-agents.md.Cp1O3u-X.lean.js +1 -0
- package/dist/docs/assets/guides_convert-automation.md.CqEyfP6Y.js +43 -0
- package/dist/docs/assets/guides_convert-automation.md.CqEyfP6Y.lean.js +1 -0
- package/dist/docs/assets/guides_github.md.BwpBp3ed.js +156 -0
- package/dist/docs/assets/guides_github.md.BwpBp3ed.lean.js +1 -0
- package/dist/docs/assets/guides_gitlab.md.DaEC3nMk.js +153 -0
- package/dist/docs/assets/guides_gitlab.md.DaEC3nMk.lean.js +1 -0
- package/dist/docs/assets/guides_grokbot-agents.md.CMhZNdEU.js +16 -0
- package/dist/docs/assets/guides_grokbot-agents.md.CMhZNdEU.lean.js +1 -0
- package/dist/docs/assets/guides_improve.md.Bnp4F99w.js +22 -0
- package/dist/docs/assets/guides_improve.md.Bnp4F99w.lean.js +1 -0
- package/dist/docs/assets/guides_jev.md.F5fAkkfN.js +189 -0
- package/dist/docs/assets/guides_jev.md.F5fAkkfN.lean.js +1 -0
- package/dist/docs/assets/guides_mcp-oauth.md.bSFakfCY.js +50 -0
- package/dist/docs/assets/guides_mcp-oauth.md.bSFakfCY.lean.js +1 -0
- package/dist/docs/assets/guides_opentelemetry.md.BKDxQmmd.js +35 -0
- package/dist/docs/assets/guides_opentelemetry.md.BKDxQmmd.lean.js +1 -0
- package/dist/docs/assets/guides_slack.md.Bo96y42E.js +70 -0
- package/dist/docs/assets/guides_slack.md.Bo96y42E.lean.js +1 -0
- package/dist/docs/assets/guides_webhooks.md.1A72_VEE.js +92 -0
- package/dist/docs/assets/guides_webhooks.md.1A72_VEE.lean.js +1 -0
- package/dist/docs/assets/hillclimbing.md.D4E1o5Sa.js +7 -0
- package/dist/docs/assets/hillclimbing.md.D4E1o5Sa.lean.js +1 -0
- package/dist/docs/assets/{index.md.BFVyY2KT.js → index.md.C-t81M5J.js} +2 -2
- package/dist/docs/assets/{index.md.BFVyY2KT.lean.js → index.md.C-t81M5J.lean.js} +1 -1
- package/dist/docs/assets/{quickstart.md.D3MjSZN-.js → quickstart.md.DAvVhuuU.js} +1 -1
- package/dist/docs/assets/{quickstart.md.D3MjSZN-.lean.js → quickstart.md.DAvVhuuU.lean.js} +1 -1
- package/dist/docs/assets/{reference_agent-config.md.CfVA-LZJ.js → reference_agent-config.md.DGPyw7ms.js} +1 -1
- package/dist/docs/assets/{reference_agent-config.md.CfVA-LZJ.lean.js → reference_agent-config.md.DGPyw7ms.lean.js} +1 -1
- package/dist/docs/assets/{reference_artifacts.md.Vf7qyIZ-.js → reference_artifacts.md.Bu_4HmsD.js} +1 -1
- package/dist/docs/assets/{reference_artifacts.md.Vf7qyIZ-.lean.js → reference_artifacts.md.Bu_4HmsD.lean.js} +1 -1
- package/dist/docs/assets/{reference_channels.md.icqLKcTc.js → reference_channels.md.nFWbzAic.js} +1 -1
- package/dist/docs/assets/{reference_channels.md.icqLKcTc.lean.js → reference_channels.md.nFWbzAic.lean.js} +1 -1
- package/dist/docs/assets/{reference_cli.md.B2dBL6L8.js → reference_cli.md.DLWDz9ij.js} +3 -1
- package/dist/docs/assets/{reference_cli.md.B2dBL6L8.lean.js → reference_cli.md.DLWDz9ij.lean.js} +1 -1
- package/dist/docs/assets/{reference_connections.md.Cb3U_c8n.js → reference_connections.md.Je9dMsdd.js} +2 -2
- package/dist/docs/assets/{reference_connections.md.Cb3U_c8n.lean.js → reference_connections.md.Je9dMsdd.lean.js} +1 -1
- package/dist/docs/assets/reference_evals.md.DNJzM_yf.js +57 -0
- package/dist/docs/assets/reference_evals.md.DNJzM_yf.lean.js +1 -0
- package/dist/docs/assets/reference_extensions.md.Cv5aLCz_.js +58 -0
- package/dist/docs/assets/reference_extensions.md.Cv5aLCz_.lean.js +1 -0
- package/dist/docs/assets/{reference_hooks.md.CZuynAxj.js → reference_hooks.md.B7uzNENk.js} +2 -2
- package/dist/docs/assets/{reference_hooks.md.CZuynAxj.lean.js → reference_hooks.md.B7uzNENk.lean.js} +1 -1
- package/dist/docs/assets/{reference_http-api.md.DTKcYE6L.js → reference_http-api.md.CduHavZ2.js} +1 -1
- package/dist/docs/assets/{reference_http-api.md.DTKcYE6L.lean.js → reference_http-api.md.CduHavZ2.lean.js} +1 -1
- package/dist/docs/assets/{reference_instructions.md.D7gkckK-.js → reference_instructions.md.CU1My5My.js} +1 -1
- package/dist/docs/assets/{reference_instructions.md.D7gkckK-.lean.js → reference_instructions.md.CU1My5My.lean.js} +1 -1
- package/dist/docs/assets/{reference_playground.md.D2YExv5K.js → reference_playground.md.Ch2d0Iqi.js} +1 -1
- package/dist/docs/assets/{reference_playground.md.D2YExv5K.lean.js → reference_playground.md.Ch2d0Iqi.lean.js} +1 -1
- package/dist/docs/assets/{reference_project-layout.md.DPxbUJyt.js → reference_project-layout.md.BGhgpy9V.js} +1 -1
- package/dist/docs/assets/{reference_project-layout.md.DPxbUJyt.lean.js → reference_project-layout.md.BGhgpy9V.lean.js} +1 -1
- package/dist/docs/assets/{reference_prompt.md.BQ5uAv1F.js → reference_prompt.md.Ccp0R53H.js} +1 -1
- package/dist/docs/assets/{reference_prompt.md.BQ5uAv1F.lean.js → reference_prompt.md.Ccp0R53H.lean.js} +1 -1
- package/dist/docs/assets/{reference_schedules.md.BasfZWO-.js → reference_schedules.md.B2Nm6FaD.js} +1 -1
- package/dist/docs/assets/{reference_schedules.md.BasfZWO-.lean.js → reference_schedules.md.B2Nm6FaD.lean.js} +1 -1
- package/dist/docs/assets/{reference_sessions.md.YKvIsWAx.js → reference_sessions.md.1_6Vyv7x.js} +1 -1
- package/dist/docs/assets/{reference_sessions.md.YKvIsWAx.lean.js → reference_sessions.md.1_6Vyv7x.lean.js} +1 -1
- package/dist/docs/assets/{reference_skills.md.rNgpsGd0.js → reference_skills.md.DjQkRefx.js} +1 -1
- package/dist/docs/assets/{reference_skills.md.rNgpsGd0.lean.js → reference_skills.md.DjQkRefx.lean.js} +1 -1
- package/dist/docs/assets/{reference_subagents.md.e5qitjJt.js → reference_subagents.md.Dl16gcBj.js} +2 -2
- package/dist/docs/assets/{reference_subagents.md.e5qitjJt.lean.js → reference_subagents.md.Dl16gcBj.lean.js} +1 -1
- package/dist/docs/assets/{reference_tools.md.BdCO2aHZ.js → reference_tools.md.B1dH1lpa.js} +3 -3
- package/dist/docs/assets/{reference_tools.md.BdCO2aHZ.lean.js → reference_tools.md.B1dH1lpa.lean.js} +1 -1
- package/dist/docs/assets/{templates_agentic-owners.md.Da_AGDlH.js → templates_agentic-owners.md.9M575F5C.js} +1 -1
- package/dist/docs/assets/{templates_agentic-owners.md.Da_AGDlH.lean.js → templates_agentic-owners.md.9M575F5C.lean.js} +1 -1
- package/dist/docs/assets/{templates_pr-autofixer.md.DqxocIGh.js → templates_pr-autofixer.md.ws0DDXDy.js} +1 -1
- package/dist/docs/assets/{templates_pr-autofixer.md.DqxocIGh.lean.js → templates_pr-autofixer.md.ws0DDXDy.lean.js} +1 -1
- package/dist/docs/assets/{templates_security-reviewer.md.Bhnvd8VE.js → templates_security-reviewer.md.KEFYXzfK.js} +1 -1
- package/dist/docs/assets/{templates_security-reviewer.md.Bhnvd8VE.lean.js → templates_security-reviewer.md.KEFYXzfK.lean.js} +1 -1
- package/dist/docs/assets/templates_thermo-quality-review.md.VNJ_mohX.js +3 -0
- package/dist/docs/assets/templates_thermo-quality-review.md.VNJ_mohX.lean.js +1 -0
- package/dist/docs/assets/templates_thermo-review.md.Hi3zWOkP.js +3 -0
- package/dist/docs/assets/templates_thermo-review.md.Hi3zWOkP.lean.js +1 -0
- package/dist/docs/assets/{templates_triage.md.BdBWO9Ic.js → templates_triage.md.CVGe_FG6.js} +1 -1
- package/dist/docs/assets/{templates_triage.md.BdBWO9Ic.lean.js → templates_triage.md.CVGe_FG6.lean.js} +1 -1
- package/dist/docs/assets/troubleshooting.md.mnfFG2Em.js +1 -0
- package/dist/docs/assets/troubleshooting.md.mnfFG2Em.lean.js +1 -0
- package/dist/docs/building-with-agents.html +44 -48
- package/dist/docs/building-with-agents.md +94 -82
- package/dist/docs/deployment.html +59 -78
- package/dist/docs/deployment.md +117 -363
- package/dist/docs/evals.html +85 -224
- package/dist/docs/evals.md +149 -673
- package/dist/docs/guides/agent-to-agent.html +74 -47
- package/dist/docs/guides/agent-to-agent.md +128 -46
- package/dist/docs/guides/bitbucket.html +179 -44
- package/dist/docs/guides/bitbucket.md +249 -48
- package/dist/docs/guides/cloud-agents.html +46 -40
- package/dist/docs/guides/cloud-agents.md +119 -66
- package/dist/docs/guides/convert-automation.html +80 -49
- package/dist/docs/guides/convert-automation.md +156 -147
- package/dist/docs/guides/github.html +184 -92
- package/dist/docs/guides/github.md +260 -245
- package/dist/docs/guides/gitlab.html +184 -45
- package/dist/docs/guides/gitlab.md +249 -50
- package/dist/docs/guides/grokbot-agents.html +48 -41
- package/dist/docs/guides/grokbot-agents.md +99 -53
- package/dist/docs/guides/improve.html +48 -40
- package/dist/docs/guides/improve.md +111 -58
- package/dist/docs/guides/jev.html +248 -0
- package/dist/docs/guides/jev.md +348 -0
- package/dist/docs/guides/mcp-oauth.html +74 -52
- package/dist/docs/guides/mcp-oauth.md +111 -121
- package/dist/docs/guides/opentelemetry.html +63 -54
- package/dist/docs/guides/opentelemetry.md +96 -165
- package/dist/docs/guides/slack.html +83 -59
- package/dist/docs/guides/slack.md +157 -227
- package/dist/docs/guides/webhooks.html +97 -230
- package/dist/docs/guides/webhooks.md +154 -385
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +44 -38
- package/dist/docs/hillclimbing.md +101 -55
- package/dist/docs/index.html +38 -38
- package/dist/docs/index.md +2 -0
- package/dist/docs/llms-full.txt +3490 -3146
- package/dist/docs/llms.txt +22 -18
- package/dist/docs/quickstart.html +37 -37
- package/dist/docs/reference/agent-config.html +37 -37
- package/dist/docs/reference/artifacts.html +38 -38
- package/dist/docs/reference/channels.html +37 -37
- package/dist/docs/reference/cli.html +39 -37
- package/dist/docs/reference/cli.md +2 -0
- package/dist/docs/reference/connections.html +38 -38
- package/dist/docs/reference/connections.md +1 -1
- package/dist/docs/reference/evals.html +116 -0
- package/dist/docs/reference/evals.md +293 -0
- package/dist/docs/reference/extensions.html +80 -84
- package/dist/docs/reference/extensions.md +131 -202
- package/dist/docs/reference/hooks.html +39 -39
- package/dist/docs/reference/hooks.md +34 -34
- package/dist/docs/reference/http-api.html +37 -37
- package/dist/docs/reference/instructions.html +37 -37
- package/dist/docs/reference/playground.html +37 -37
- package/dist/docs/reference/project-layout.html +37 -37
- package/dist/docs/reference/prompt.html +37 -37
- package/dist/docs/reference/schedules.html +37 -37
- package/dist/docs/reference/sessions.html +37 -37
- package/dist/docs/reference/skills.html +37 -37
- package/dist/docs/reference/subagents.html +38 -38
- package/dist/docs/reference/subagents.md +1 -1
- package/dist/docs/reference/tools.html +38 -38
- package/dist/docs/reference/tools.md +4 -0
- package/dist/docs/templates/agentic-owners.html +38 -38
- package/dist/docs/templates/pr-autofixer.html +37 -37
- package/dist/docs/templates/security-reviewer.html +38 -38
- package/dist/docs/templates/thermo-quality-review.html +62 -0
- package/dist/docs/templates/thermo-quality-review.md +75 -0
- package/dist/docs/templates/thermo-review.html +62 -0
- package/dist/docs/templates/thermo-review.md +74 -0
- package/dist/docs/templates/triage.html +37 -37
- package/dist/docs/troubleshooting.html +38 -38
- package/dist/docs/troubleshooting.md +97 -66
- package/dist/extensions/cursor-cloud-agents/skills/handoff.md +3 -7
- package/dist/extensions/improve/extension.d.ts +3 -1
- package/dist/extensions/improve/extension.d.ts.map +1 -1
- package/dist/extensions/improve/extension.js +4 -2
- package/dist/extensions/improve/skills/yourself.js +1 -1
- package/dist/extensions/jev/extension.d.ts +43 -0
- package/dist/extensions/jev/extension.d.ts.map +1 -0
- package/dist/extensions/jev/extension.js +47 -0
- package/dist/extensions/jev/lib/evaluate.d.ts +101 -0
- package/dist/extensions/jev/lib/evaluate.d.ts.map +1 -0
- package/dist/extensions/jev/lib/evaluate.js +167 -0
- package/dist/extensions/jev/skills/gated-write.md +25 -0
- package/dist/extensions/jev/skills/questions.md +33 -0
- package/dist/extensions/jev/tools/evaluate.d.ts +4 -0
- package/dist/extensions/jev/tools/evaluate.d.ts.map +1 -0
- package/dist/extensions/jev/tools/evaluate.js +88 -0
- package/dist/extensions.d.ts +1 -1
- package/dist/extensions.d.ts.map +1 -1
- package/dist/extensions.js +2 -0
- package/dist/filesystem.d.ts +46 -2
- package/dist/filesystem.d.ts.map +1 -1
- package/dist/filesystem.js +149 -102
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/internal/advertise-tools.d.ts.map +1 -1
- package/dist/internal/advertise-tools.js +6 -0
- package/dist/internal/cli-ax.d.ts +6 -0
- package/dist/internal/cli-ax.d.ts.map +1 -1
- package/dist/internal/cli-ax.js +72 -14
- package/dist/internal/continuation-identity.d.ts.map +1 -1
- package/dist/internal/continuation-identity.js +1 -0
- package/dist/internal/cursor-agent-template.d.ts +1 -1
- package/dist/internal/cursor-agent-template.d.ts.map +1 -1
- package/dist/internal/cursor-agent-template.js +2 -0
- package/dist/internal/discovery/connections.d.ts.map +1 -1
- package/dist/internal/discovery/connections.js +18 -0
- package/dist/internal/discovery/extensions.d.ts.map +1 -1
- package/dist/internal/discovery/extensions.js +8 -4
- package/dist/internal/discovery/info.d.ts.map +1 -1
- package/dist/internal/discovery/info.js +1 -0
- package/dist/internal/filesystem/tools.d.ts.map +1 -1
- package/dist/internal/filesystem/tools.js +2 -2
- package/dist/internal/filesystem/walk.d.ts +7 -4
- package/dist/internal/filesystem/walk.d.ts.map +1 -1
- package/dist/internal/filesystem/walk.js +34 -11
- package/dist/internal/hosted-admission-adapter.d.ts +3 -0
- package/dist/internal/hosted-admission-adapter.d.ts.map +1 -1
- package/dist/internal/hosted-delivery-protocol.d.ts +20 -0
- package/dist/internal/hosted-delivery-protocol.d.ts.map +1 -1
- package/dist/internal/hosted-delivery-protocol.js +51 -1
- package/dist/internal/hosted-delivery.d.ts.map +1 -1
- package/dist/internal/hosted-delivery.js +23 -25
- package/dist/internal/hosted-execution-diag.d.ts +12 -4
- package/dist/internal/hosted-execution-diag.d.ts.map +1 -1
- package/dist/internal/hosted-execution-diag.js +26 -4
- package/dist/internal/hosted-execution-flush.d.ts +1 -0
- package/dist/internal/hosted-execution-flush.d.ts.map +1 -1
- package/dist/internal/hosted-execution-flush.js +4 -2
- package/dist/internal/init-project.d.ts.map +1 -1
- package/dist/internal/init-project.js +4 -0
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +111 -48
- package/dist/internal/session-engine.d.ts +4 -1
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +39 -9
- package/dist/internal/skill-catalog.d.ts +28 -0
- package/dist/internal/skill-catalog.d.ts.map +1 -0
- package/dist/internal/skill-catalog.js +44 -0
- package/dist/playground/assets/index-DSMAewbx.css +1 -0
- package/dist/playground/assets/index-De_lpFxE.js +67 -0
- package/dist/playground/index.html +2 -2
- package/dist/types.d.ts +32 -3
- package/dist/types.d.ts.map +1 -1
- package/docs/README.md +2 -0
- package/docs/building-with-agents.md +96 -84
- package/docs/deployment.md +118 -364
- package/docs/evals.md +149 -673
- package/docs/guides/agent-to-agent.md +130 -48
- package/docs/guides/bitbucket.md +250 -49
- package/docs/guides/cloud-agents.md +119 -67
- package/docs/guides/convert-automation.md +157 -148
- package/docs/guides/github.md +261 -246
- package/docs/guides/gitlab.md +250 -51
- package/docs/guides/grokbot-agents.md +100 -55
- package/docs/guides/improve.md +112 -59
- package/docs/guides/jev.md +353 -0
- package/docs/guides/mcp-oauth.md +112 -122
- package/docs/guides/opentelemetry.md +97 -166
- package/docs/guides/slack.md +158 -228
- package/docs/guides/webhooks.md +155 -386
- package/docs/hillclimbing.md +102 -56
- package/docs/reference/cli.md +2 -0
- package/docs/reference/connections.md +1 -1
- package/docs/reference/evals.md +298 -0
- package/docs/reference/extensions.md +132 -203
- package/docs/reference/hooks.md +34 -34
- package/docs/reference/subagents.md +1 -1
- package/docs/reference/tools.md +4 -0
- package/docs/templates/thermo-quality-review.md +80 -0
- package/docs/templates/thermo-review.md +79 -0
- package/docs/troubleshooting.md +98 -67
- package/package.json +8 -1
- package/skills/github/SKILL.md +21 -13
- package/src/bin/agent-serve.ts +24 -3
- package/src/channels/checks.ts +8 -0
- package/src/channels/github/github-channel.ts +29 -19
- package/src/channels/origin/checks.ts +3 -1
- package/src/channels/slack/agentic-delivery.ts +2 -0
- package/src/channels/slack/dispatch.ts +131 -4
- package/src/channels/slack/placeholder.ts +51 -0
- package/src/channels/slack/slack-channel.ts +9 -2
- package/src/extensions/cursor-cloud-agents/skills/handoff.md +3 -7
- package/src/extensions/improve/extension.ts +4 -2
- package/src/extensions/improve/skills/yourself.ts +1 -1
- package/src/extensions/jev/extension.ts +95 -0
- package/src/extensions/jev/lib/evaluate.ts +289 -0
- package/src/extensions/jev/skills/gated-write.md +25 -0
- package/src/extensions/jev/skills/questions.md +33 -0
- package/src/extensions/jev/tools/evaluate.ts +90 -0
- package/src/extensions.ts +2 -0
- package/src/filesystem.ts +168 -65
- package/src/index.ts +3 -0
- package/src/internal/advertise-tools.ts +6 -0
- package/src/internal/cli-ax.ts +88 -15
- package/src/internal/continuation-identity.ts +1 -0
- package/src/internal/cursor-agent-template.ts +2 -0
- package/src/internal/discovery/connections.ts +21 -0
- package/src/internal/discovery/extensions.ts +12 -4
- package/src/internal/discovery/info.ts +1 -0
- package/src/internal/filesystem/tools.ts +2 -0
- package/src/internal/filesystem/walk.ts +60 -15
- package/src/internal/hosted-admission-adapter.ts +3 -0
- package/src/internal/hosted-delivery-protocol.ts +82 -1
- package/src/internal/hosted-delivery.ts +23 -0
- package/src/internal/hosted-execution-diag.ts +33 -4
- package/src/internal/hosted-execution-flush.ts +4 -0
- package/src/internal/init-project.ts +4 -0
- package/src/internal/server.ts +130 -53
- package/src/internal/session-engine.ts +46 -8
- package/src/internal/skill-catalog.ts +69 -0
- package/src/types.ts +33 -3
- package/templates/thermo-quality-review/README.md +35 -0
- package/templates/thermo-quality-review/agent/agent.ts +8 -0
- package/templates/thermo-quality-review/agent/channels/github.ts +42 -0
- package/templates/thermo-quality-review/agent/instructions.md +43 -0
- package/templates/thermo-quality-review/agent/tools/post_findings.ts +70 -0
- package/templates/thermo-quality-review/evals/evals.config.ts +5 -0
- package/templates/thermo-quality-review/evals/review.eval.ts +62 -0
- package/templates/thermo-quality-review/package.json +18 -0
- package/templates/thermo-quality-review/tsconfig.json +12 -0
- package/templates/thermo-review/README.md +35 -0
- package/templates/thermo-review/agent/agent.ts +8 -0
- package/templates/thermo-review/agent/channels/github.ts +42 -0
- package/templates/thermo-review/agent/instructions.md +40 -0
- package/templates/thermo-review/agent/tools/post_findings.ts +70 -0
- package/templates/thermo-review/evals/evals.config.ts +5 -0
- package/templates/thermo-review/evals/review.eval.ts +53 -0
- package/templates/thermo-review/package.json +18 -0
- package/templates/thermo-review/tsconfig.json +12 -0
- package/dist/docs/assets/building-with-agents.md.CEGVXkmO.js +0 -13
- package/dist/docs/assets/building-with-agents.md.CEGVXkmO.lean.js +0 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.DtXk1hy-.js +0 -1
- package/dist/docs/assets/chunks/channel.Bkv1N-gK.js +0 -1
- package/dist/docs/assets/chunks/classDiagram-6PBFFD2Q.CZDco1o8.js +0 -1
- package/dist/docs/assets/chunks/classDiagram-v2-HSJHXN6E.CZDco1o8.js +0 -1
- package/dist/docs/assets/chunks/clone.YSt_40_s.js +0 -1
- package/dist/docs/assets/chunks/framework.dypDpWZ3.js +0 -19
- package/dist/docs/assets/chunks/stateDiagram-v2-QKLJ7IA2.C4CLm481.js +0 -1
- package/dist/docs/assets/deployment.md.Dm4Qo3hp.js +0 -51
- package/dist/docs/assets/deployment.md.Dm4Qo3hp.lean.js +0 -1
- package/dist/docs/assets/evals.md.BLDRt5LH.js +0 -211
- package/dist/docs/assets/evals.md.BLDRt5LH.lean.js +0 -1
- package/dist/docs/assets/guides_agent-to-agent.md.BI0xclmy.js +0 -14
- package/dist/docs/assets/guides_agent-to-agent.md.BI0xclmy.lean.js +0 -1
- package/dist/docs/assets/guides_bitbucket.md.CTpCl__f.js +0 -10
- package/dist/docs/assets/guides_bitbucket.md.CTpCl__f.lean.js +0 -1
- package/dist/docs/assets/guides_cloud-agents.md.lSE_l7lH.js +0 -9
- package/dist/docs/assets/guides_cloud-agents.md.lSE_l7lH.lean.js +0 -1
- package/dist/docs/assets/guides_convert-automation.md.Ck6Cr68A.js +0 -12
- package/dist/docs/assets/guides_convert-automation.md.Ck6Cr68A.lean.js +0 -1
- package/dist/docs/assets/guides_github.md.D6ER29dG.js +0 -64
- package/dist/docs/assets/guides_github.md.D6ER29dG.lean.js +0 -1
- package/dist/docs/assets/guides_gitlab.md.P-TjBnS5.js +0 -14
- package/dist/docs/assets/guides_gitlab.md.P-TjBnS5.lean.js +0 -1
- package/dist/docs/assets/guides_grokbot-agents.md.WBZIOvkz.js +0 -9
- package/dist/docs/assets/guides_grokbot-agents.md.WBZIOvkz.lean.js +0 -1
- package/dist/docs/assets/guides_improve.md.BKaDuKKK.js +0 -14
- package/dist/docs/assets/guides_improve.md.BKaDuKKK.lean.js +0 -1
- package/dist/docs/assets/guides_mcp-oauth.md.DMNMpXtO.js +0 -28
- package/dist/docs/assets/guides_mcp-oauth.md.DMNMpXtO.lean.js +0 -1
- package/dist/docs/assets/guides_opentelemetry.md._CRfDyzH.js +0 -26
- package/dist/docs/assets/guides_opentelemetry.md._CRfDyzH.lean.js +0 -1
- package/dist/docs/assets/guides_slack.md.DdT8rmsj.js +0 -46
- package/dist/docs/assets/guides_slack.md.DdT8rmsj.lean.js +0 -1
- package/dist/docs/assets/guides_webhooks.md.aQW10HRe.js +0 -225
- package/dist/docs/assets/guides_webhooks.md.aQW10HRe.lean.js +0 -1
- package/dist/docs/assets/hillclimbing.md.Dq4kkVIL.js +0 -1
- package/dist/docs/assets/hillclimbing.md.Dq4kkVIL.lean.js +0 -1
- package/dist/docs/assets/reference_extensions.md.wlFD3cUR.js +0 -62
- package/dist/docs/assets/reference_extensions.md.wlFD3cUR.lean.js +0 -1
- package/dist/docs/assets/troubleshooting.md.BcgNoYtJ.js +0 -1
- package/dist/docs/assets/troubleshooting.md.BcgNoYtJ.lean.js +0 -1
- package/dist/playground/assets/index-BLlKgZtI.css +0 -1
- package/dist/playground/assets/index-CDS5p9sR.js +0 -67
package/dist/docs/evals.md
CHANGED
|
@@ -1,778 +1,254 @@
|
|
|
1
1
|
# Evals
|
|
2
2
|
|
|
3
|
-
An eval sends a fixed
|
|
4
|
-
trajectory
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
month's fix still holds.
|
|
8
|
-
|
|
9
|
-
Nothing is mocked. The runner starts (or targets) a real agent server,
|
|
10
|
-
drives sessions over the public API, and grades the events it gets
|
|
11
|
-
back. The model runs and server tools execute, so
|
|
12
|
-
[keep side effects out of eval sessions](#keep-side-effects-out-of-eval-sessions)
|
|
13
|
-
before you point an eval at an agent that posts anywhere.
|
|
3
|
+
An eval sends a fixed input to the real agent and checks the resulting
|
|
4
|
+
trajectory: whether the turn succeeded, which tools ran, and what shape
|
|
5
|
+
the answer took. Use evals to protect behavior you already understand,
|
|
6
|
+
not to discover what the prompt should do.
|
|
14
7
|
|
|
15
|
-
|
|
8
|
+
Evals run real model turns and real tools. Guard external writes before
|
|
9
|
+
running a suite against an agent that can post, merge, or deploy.
|
|
16
10
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
| Gate one fixed input's behavior, locally and in CI | Evals (this page) |
|
|
23
|
-
| Observe every live session: metrics, audit, alerts | [Hooks](/docs/reference/hooks.md) |
|
|
24
|
-
| Improve an agent one measured round at a time | [Hillclimbing](/docs/hillclimbing.md); each kept win lands an eval |
|
|
25
|
-
|
|
26
|
-
[Hooks, channel events, or evals?](/docs/reference/hooks.md#hooks-channel-events-or-evals)
|
|
27
|
-
has the side-by-side table.
|
|
28
|
-
|
|
29
|
-
### When not to write an eval
|
|
30
|
-
|
|
31
|
-
- Test a server tool's own logic with
|
|
32
|
-
`agent-sdk call <tool> --dir . --input '{...}'` or a unit test. No
|
|
33
|
-
model turn, no credential.
|
|
34
|
-
- Explore a prompt with `agent-sdk run --dir . --message "..."` and
|
|
35
|
-
read the trajectory. Write the eval once you know which decision to
|
|
36
|
-
gate.
|
|
37
|
-
- Stop a bad turn while it runs with
|
|
38
|
-
[`needsApproval`](/docs/reference/tools.md#gate-a-tool-on-human-approval)
|
|
39
|
-
on the tool or `defineResult`. Evals grade
|
|
40
|
-
after the fact.
|
|
41
|
-
|
|
42
|
-
## Write your first eval
|
|
43
|
-
|
|
44
|
-
Evals live under the project-root `evals/` directory, a sibling of
|
|
45
|
-
`agent/`. `agent/evals/` is silently ignored. Discovery loads every
|
|
46
|
-
`.eval.ts` (or `.eval.js`) file under `evals/`, plus one config file.
|
|
47
|
-
|
|
48
|
-
```text
|
|
49
|
-
my-agent/
|
|
50
|
-
agent/
|
|
51
|
-
agent.ts
|
|
52
|
-
tools/inspect_pr.ts
|
|
53
|
-
evals/
|
|
54
|
-
evals.config.ts # required to run: maxConcurrency
|
|
55
|
-
readiness.eval.ts # id: readiness
|
|
56
|
-
prs.eval.ts # cases: prs/checkout, prs/search
|
|
57
|
-
```
|
|
11
|
+
## Protect a tool decision
|
|
12
|
+
|
|
13
|
+
This smoke case asks for a PR verdict, requires the read-only inspection
|
|
14
|
+
tool, and fails if the agent tries to approve. The CLI reports all three
|
|
15
|
+
decisions together instead of stopping at the first miss.
|
|
58
16
|
|
|
59
|
-
|
|
60
|
-
|
|
17
|
+
Use the [Jev extension](/docs/guides/jev.md) when host code needs a typed
|
|
18
|
+
choice, score, or boolean before it writes.
|
|
61
19
|
|
|
62
20
|
```ts
|
|
63
21
|
// evals/readiness.eval.ts
|
|
64
22
|
import { defineEval, includes } from "@cursor/july/evals";
|
|
65
23
|
|
|
66
24
|
export default defineEval({
|
|
67
|
-
description: "Inspects a PR without approving it.",
|
|
68
25
|
tags: ["smoke"],
|
|
69
|
-
timeoutMs: 120_000,
|
|
70
26
|
async test(t) {
|
|
71
27
|
await t.send(
|
|
72
28
|
"Is https://github.com/acme/checkout/pull/42 ready to approve?"
|
|
73
29
|
);
|
|
30
|
+
|
|
74
31
|
t.succeeded();
|
|
75
32
|
t.calledTool("inspect_pr");
|
|
76
33
|
t.notCalledTool("approve_pr");
|
|
77
|
-
t.check(t.reply, includes(/ready|approve/i));
|
|
34
|
+
t.check(t.reply, includes(/ready|blocked|approve/i));
|
|
78
35
|
},
|
|
79
36
|
});
|
|
80
37
|
```
|
|
81
38
|
|
|
39
|
+
Evals live in the project-root `evals/` directory, beside `agent/`.
|
|
40
|
+
Add the required concurrency config once:
|
|
41
|
+
|
|
82
42
|
```ts
|
|
83
43
|
// evals/evals.config.ts
|
|
84
44
|
import { defineEvalConfig } from "@cursor/july/evals";
|
|
85
45
|
|
|
86
|
-
export default defineEvalConfig({
|
|
46
|
+
export default defineEvalConfig({
|
|
47
|
+
maxConcurrency: 20,
|
|
48
|
+
});
|
|
87
49
|
```
|
|
88
50
|
|
|
89
|
-
Run it under Node 22.13 or newer (never Bun) with a Cursor credential
|
|
90
|
-
in place; see [Credentials](#credentials):
|
|
91
|
-
|
|
92
51
|
```bash
|
|
93
52
|
agent-sdk eval --dir . --list
|
|
94
|
-
agent-sdk eval --dir .
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
```text
|
|
98
|
-
PASS readiness (14.2s) — Inspects a PR without approving it.
|
|
99
|
-
✓ succeeded
|
|
100
|
-
✓ calledTool(inspect_pr)
|
|
101
|
-
✓ notCalledTool(approve_pr)
|
|
102
|
-
✓ check(includes)
|
|
103
|
-
|
|
104
|
-
1 passed, 0 failed, 1 total
|
|
105
|
-
artifacts: <project state directory>/evals/2026-09-11T15-02-11-402Z
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
Every local run writes each case's assertions, inputs, tool calls, and
|
|
109
|
-
`t.log` lines under that artifacts directory. Open
|
|
110
|
-
`evals/<case-id>.json` there when a case fails; see
|
|
111
|
-
[Where results land](#where-results-land).
|
|
112
|
-
|
|
113
|
-
## Name cases by path
|
|
114
|
-
|
|
115
|
-
The file path is the eval's identity, so you don't author an id.
|
|
116
|
-
`evals/builds/api.eval.ts` becomes `builds/api`. An `index` filename
|
|
117
|
-
collapses to its directory: `evals/builds/index.eval.ts` becomes
|
|
118
|
-
`builds`.
|
|
119
|
-
|
|
120
|
-
One file can hold several datapoints through `cases`. Provide either
|
|
121
|
-
`test` or `cases`, not both. Each case id becomes `<fileId>/<case.id>`:
|
|
122
|
-
|
|
123
|
-
```ts
|
|
124
|
-
// evals/prs.eval.ts: prs/checkout, prs/search
|
|
125
|
-
export default defineEval({
|
|
126
|
-
tags: ["smoke", "prs"],
|
|
127
|
-
cases: [
|
|
128
|
-
{
|
|
129
|
-
id: "checkout",
|
|
130
|
-
description: "Checkout PR readiness.",
|
|
131
|
-
async test(t) {
|
|
132
|
-
await t.send(
|
|
133
|
-
"Is https://github.com/acme/checkout/pull/42 ready to approve?"
|
|
134
|
-
);
|
|
135
|
-
t.succeeded();
|
|
136
|
-
t.calledTool("inspect_pr");
|
|
137
|
-
},
|
|
138
|
-
},
|
|
139
|
-
{
|
|
140
|
-
id: "search",
|
|
141
|
-
async test(t) {
|
|
142
|
-
await t.send(
|
|
143
|
-
"Check https://github.com/acme/search/pull/7 before approval."
|
|
144
|
-
);
|
|
145
|
-
t.succeeded();
|
|
146
|
-
t.calledTool("inspect_pr");
|
|
147
|
-
},
|
|
148
|
-
},
|
|
149
|
-
],
|
|
150
|
-
});
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
Case ids are single path segments, unique within the file. A case can
|
|
154
|
-
set its own `description`, `tags`, `timeoutMs`, `iterations`, `judge`,
|
|
155
|
-
`reporters`, and `metadata`. A case-level value replaces the file-level
|
|
156
|
-
one for that datapoint, except `metadata`, which merges with case keys
|
|
157
|
-
winning, and `reporters`, which adds to the file's list. `metadata` is
|
|
158
|
-
free-form data carried onto the result and every reporter.
|
|
159
|
-
|
|
160
|
-
A file may instead export an array of `defineEval` calls to fan out
|
|
161
|
-
over a dataset. Ids are then the file id plus a zero-padded index
|
|
162
|
-
(`sql/0000`, `sql/0001`, ...); see [Load a dataset](#load-a-dataset).
|
|
163
|
-
Prefer `cases` when datapoints are hand-written and deserve stable
|
|
164
|
-
names.
|
|
165
|
-
|
|
166
|
-
### Iterations
|
|
167
|
-
|
|
168
|
-
`iterations` (file or case, default `1`, cap `100`) runs a datapoint
|
|
169
|
-
repeatedly. Discovery expands `iterations: 3` on case `nyc` to runnable
|
|
170
|
-
ids `weather/nyc/1`, `weather/nyc/2`, and `weather/nyc/3`. The filter
|
|
171
|
-
`weather/nyc` still selects all three. Each expanded case exposes
|
|
172
|
-
`t.iteration` and `t.iterations`.
|
|
173
|
-
|
|
174
|
-
`maxConcurrency` counts authored datapoints, not expanded iterations.
|
|
175
|
-
Iterations of one datapoint share a concurrency slot and run in
|
|
176
|
-
sequence, so a suite of 11 cases with 3 iterations each and
|
|
177
|
-
`maxConcurrency: 20` has at most 11 cases in flight.
|
|
178
|
-
|
|
179
|
-
## Drive the agent with `t.send`
|
|
180
|
-
|
|
181
|
-
`t.send(message, options?)` runs one turn and waits for it to settle:
|
|
182
|
-
complete, park on an approval request, or fail. Several sends in one
|
|
183
|
-
case share the session, which is how you write multi-turn evals.
|
|
184
|
-
|
|
185
|
-
Each send resolves to a turn result: `message` (the assistant text),
|
|
186
|
-
`sessionId`, `events`, `toolCalls` (tool names in order), `ok`, and
|
|
187
|
-
`index`. The turn carries the same assertion vocabulary as `t`, scoped
|
|
188
|
-
to that turn, so you can grade an intermediate turn before the next
|
|
189
|
-
send overwrites `t.reply`. `turn.expectOk()` throws when the turn
|
|
190
|
-
failed, for later steps that depend on it.
|
|
191
|
-
|
|
192
|
-
Read the whole case with `t.reply` (last assistant text), `t.events`
|
|
193
|
-
(every event so far), `t.turns` (settled turns, oldest first), and
|
|
194
|
-
`t.sessionId`. `t.signal` aborts when the case hits its timeout; pass
|
|
195
|
-
it to your own async work.
|
|
196
|
-
|
|
197
|
-
Three options apply on the first send only, because they shape session
|
|
198
|
-
creation:
|
|
199
|
-
|
|
200
|
-
| Option | Effect |
|
|
201
|
-
| --- | --- |
|
|
202
|
-
| `workspaceFiles` | `{ path: contents }` seeded into the local session workspace. Prefer this over machine-local paths |
|
|
203
|
-
| `workspaceDir` | Absolute harness cwd for the local runtime |
|
|
204
|
-
| `cloud` | Per-session cloud options merged over the agent's static `cloud` config. Pin a fixture repo here for cloud evals instead of on the agent's default `cloud.repos`. On the cloud runtime, seeded files reach the agent as described under [Choose a runtime](/docs/reference/agent-config.md#choose-a-runtime) |
|
|
205
|
-
|
|
206
|
-
```ts
|
|
207
|
-
await t.send("Review pr/diff.patch and post findings.", {
|
|
208
|
-
workspaceFiles: {
|
|
209
|
-
"pr/diff.patch": [
|
|
210
|
-
"diff --git a/app/routes/search.ts b/app/routes/search.ts",
|
|
211
|
-
"+res.send(`<h1>Results for ${req.query.q}</h1>`);",
|
|
212
|
-
].join("\n"),
|
|
213
|
-
},
|
|
214
|
-
});
|
|
215
|
-
```
|
|
216
|
-
|
|
217
|
-
## Assert over the trajectory
|
|
218
|
-
|
|
219
|
-
Assertions record; they never throw. One run reports every failure
|
|
220
|
-
instead of dying on the first. Assertions on `t` read the whole run.
|
|
221
|
-
Assertions on a turn read only that turn.
|
|
222
|
-
|
|
223
|
-
| Gate | Checks |
|
|
224
|
-
| --- | --- |
|
|
225
|
-
| `t.succeeded()` | the run did not fail and is not parked on an unanswered approval |
|
|
226
|
-
| `t.parked()` | the run cleanly parked on an unanswered approval request |
|
|
227
|
-
| `t.messageIncludes(token)` | the joined assistant text matches a string or `RegExp` |
|
|
228
|
-
| `t.calledTool(name, matcher?)` | a matching call to `name` happened |
|
|
229
|
-
| `t.notCalledTool(name)` | no request for `name`, in any lifecycle state |
|
|
230
|
-
| `t.loadedSkill(name)` | the agent opened `skills/<name>/SKILL.md` (read, grep, or shell `cat`) |
|
|
231
|
-
| `t.toolOrder(names)` | tool requests appear in this relative order; extra calls allowed |
|
|
232
|
-
| `t.usedNoTools()` | no tool calls at all |
|
|
233
|
-
| `t.maxToolCalls(max)` | at most `max` tool calls |
|
|
234
|
-
| `t.noFailedActions()` | no tool call reported an error |
|
|
235
|
-
| `t.calledSubagent(name, matcher?)` | a matching subagent delegation happened |
|
|
236
|
-
| `t.taggedArtifact(kind?, predicate?)` | at least one [artifact](/docs/reference/artifacts.md) was tagged |
|
|
237
|
-
| `t.event(type, matcher?)` | at least one matching [event](/docs/reference/sessions.md#which-events-can-i-stream) of `type` |
|
|
238
|
-
| `t.notEvent(type, matcher?)` | no matching event of `type` |
|
|
239
|
-
| `t.eventOrder(matchers)` | matching event groups occur in this relative order |
|
|
240
|
-
| `t.eventsSatisfy(label, predicate)` | your predicate over the typed event stream |
|
|
241
|
-
| `t.check(value, expectation)` | any value, against a [builder](#grade-values-with-expectation-builders) |
|
|
242
|
-
| `t.score(name, value)` | a 0-1 score you computed; soft until you add a bar |
|
|
243
|
-
|
|
244
|
-
Three more assertions gate and return the matched fact. They stop the
|
|
245
|
-
test body when nothing matches, without a duplicate execution error.
|
|
246
|
-
`t.requireToolCall(name, matcher?)` returns the call so later code can
|
|
247
|
-
read its `input` and `output`. `t.requireInputRequest(filter?)` returns
|
|
248
|
-
the single pending approval request. `await t.require(value, expectation)`
|
|
249
|
-
does the same for a value check.
|
|
250
|
-
|
|
251
|
-
A case with no assertions passes when at least one turn completed. Add
|
|
252
|
-
`t.succeeded()` and behavior gates anyway. They make the contract
|
|
253
|
-
visible in review.
|
|
254
|
-
|
|
255
|
-
### What good cases assert
|
|
256
|
-
|
|
257
|
-
Gate decisions and shape, not prose. Model wording varies run to run.
|
|
258
|
-
Tool choice, tool avoidance, and output structure are the stable
|
|
259
|
-
contract.
|
|
260
|
-
|
|
261
|
-
1. `t.succeeded()`: always, first.
|
|
262
|
-
2. The tool decision: `calledTool` for the intended path,
|
|
263
|
-
`notCalledTool` for the likely wrong alternative. The pair is
|
|
264
|
-
stronger than either alone.
|
|
265
|
-
3. Output shape: a regex for the contract (`/ready|blocked/i`, a JSON
|
|
266
|
-
marker, a findings-block fence), never exact sentences.
|
|
267
|
-
4. For structured output, parse `t.reply` and check fields with
|
|
268
|
-
`matches` or `satisfies` instead of substring-matching JSON.
|
|
269
|
-
|
|
270
|
-
The common failure modes: asserting exact phrasing, packing more than
|
|
271
|
-
about five gates into one case (split it), and cases that depend on
|
|
272
|
-
live external state that drifts (pin the input).
|
|
273
|
-
|
|
274
|
-
### Narrow tool assertions with matchers
|
|
275
|
-
|
|
276
|
-
With no matcher, `calledTool` is request-based: a requested call counts
|
|
277
|
-
even before its result arrives. A matcher narrows it:
|
|
278
|
-
|
|
279
|
-
```ts
|
|
280
|
-
t.calledTool("inspect_pr", { status: "completed" });
|
|
281
|
-
t.calledTool("apply_agents", { input: { verdict: "update" } });
|
|
282
|
-
t.calledTool("bash", { input: { command: /^gh pr view/ }, count: 1 });
|
|
283
|
-
t.calledTool("read_file", {
|
|
284
|
-
output: (value) => String(value).includes("TODO"),
|
|
285
|
-
});
|
|
53
|
+
agent-sdk eval --dir . --tag smoke
|
|
286
54
|
```
|
|
287
55
|
|
|
288
|
-
|
|
289
|
-
predicate. Object literals partial-deep-match, so `{ verdict: "update" }`
|
|
290
|
-
matches arguments that also carry other keys. `status` is one of
|
|
291
|
-
`completed`, `failed`, `pending`, or `rejected` (a human denied the
|
|
292
|
-
approval). `calledSubagent` takes `{ output, status, count, callId }`.
|
|
293
|
-
`event`, `notEvent`, and `eventOrder` take `{ data, count }`.
|
|
56
|
+
## Check answer shape or quality
|
|
294
57
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
JSON field, a tool's output.
|
|
299
|
-
|
|
300
|
-
| Builder | Checks | Severity |
|
|
301
|
-
| --- | --- | --- |
|
|
302
|
-
| `includes(string \| RegExp)` | substring or match; structured values are stringified first | gate |
|
|
303
|
-
| `equals(value)` | deep equality | gate |
|
|
304
|
-
| `matches(schema)` | a Standard Schema (Zod, Valibot, ...) or anything with `safeParse` | gate |
|
|
305
|
-
| `similarity(expected)` | normalized text similarity, 0-1 | soft |
|
|
306
|
-
| `satisfies(predicate, label)` | your predicate; `label` is the failure detail | gate |
|
|
58
|
+
Prefer a deterministic shape check when the output has a contract. The
|
|
59
|
+
failure tells you which field was wrong, and the case remains stable
|
|
60
|
+
when the model changes its wording.
|
|
307
61
|
|
|
308
62
|
```ts
|
|
309
|
-
import { matches
|
|
63
|
+
import { matches } from "@cursor/july/evals";
|
|
310
64
|
import { z } from "zod";
|
|
311
65
|
|
|
312
66
|
const verdict = JSON.parse(t.reply ?? "{}");
|
|
313
67
|
t.check(
|
|
314
68
|
verdict,
|
|
315
|
-
matches(
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
69
|
+
matches(
|
|
70
|
+
z.object({
|
|
71
|
+
ready: z.boolean(),
|
|
72
|
+
blockers: z.array(z.string()),
|
|
73
|
+
})
|
|
74
|
+
)
|
|
320
75
|
);
|
|
321
76
|
```
|
|
322
77
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
### Record without gating
|
|
327
|
-
|
|
328
|
-
- `t.metric(name, value)` records a structured score or label. It shows
|
|
329
|
-
on the CLI result, the playground case card, JUnit output, and
|
|
330
|
-
artifacts.
|
|
331
|
-
- `t.log(message)` records a debug line, streamed under `--verbose`.
|
|
332
|
-
- `t.skip(reason)` ends the case as skipped. Skipped cases report
|
|
333
|
-
separately and never change the exit code. Call it before sending
|
|
334
|
-
messages.
|
|
335
|
-
|
|
336
|
-
## Gates, soft scores, and verdicts
|
|
337
|
-
|
|
338
|
-
Every assertion returns a handle, so severity rides on the assertion
|
|
339
|
-
instead of a separate thresholds map:
|
|
340
|
-
|
|
341
|
-
```ts
|
|
342
|
-
t.succeeded(); // gate (default)
|
|
343
|
-
t.calledTool("get_weather").soft(); // tracked, never fails
|
|
344
|
-
t.check(t.reply, similarity("Sunny, 72°F")).atLeast(0.8); // soft, with a bar
|
|
345
|
-
t.judge.closedQA("cites a source").gate(0.8); // promoted to a gate
|
|
346
|
-
```
|
|
347
|
-
|
|
348
|
-
- `.gate(threshold?)` is hard. A miss fails the case and `eval` exits 1.
|
|
349
|
-
- `.soft(threshold?)` is tracked. With no threshold it never fails.
|
|
350
|
-
- `.atLeast(threshold)` is soft with a bar. A miss marks the case
|
|
351
|
-
`scored`.
|
|
352
|
-
|
|
353
|
-
Each case ends with one verdict:
|
|
354
|
-
|
|
355
|
-
| Verdict | Meaning | Exit code |
|
|
356
|
-
| --- | --- | --- |
|
|
357
|
-
| `passed` | every gate passed and no soft bar was missed | 0 |
|
|
358
|
-
| `failed` | a gate failed, or the test body threw | 1 |
|
|
359
|
-
| `scored` | only soft bars were missed | 0, or 1 under `--strict` |
|
|
360
|
-
| `skipped` | `t.skip(reason)`, or a judge with no credentials | 0 |
|
|
361
|
-
|
|
362
|
-
The CLI prints soft misses as `~` and gate misses as `✗`. Start a new
|
|
363
|
-
benchmark with `t.score("recall", recall)` and `.atLeast()` so its
|
|
364
|
-
number reports for a while without blocking merges. Add `--strict`
|
|
365
|
-
once the bars are trustworthy.
|
|
366
|
-
|
|
367
|
-
## Judge free-form output
|
|
368
|
-
|
|
369
|
-
When wording matters and no regex captures it, `t.judge` grades with an
|
|
370
|
-
LLM. The graders are `factuality(expected)`, `summarizes(expected)`,
|
|
371
|
-
`closedQA(criteria)`, and `sql(expected)`. Each scores `t.reply` by
|
|
372
|
-
default; pass `{ on }` to grade another value.
|
|
78
|
+
Use a judge when correctness depends on meaning that a schema, regex, or
|
|
79
|
+
known value cannot capture:
|
|
373
80
|
|
|
374
81
|
```ts
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
82
|
+
t.judge
|
|
83
|
+
.factuality("The lint step failed on src/sidebar.ts.")
|
|
84
|
+
.atLeast(0.8);
|
|
378
85
|
```
|
|
379
86
|
|
|
380
|
-
Judge
|
|
381
|
-
|
|
382
|
-
|
|
87
|
+
Judge checks are tracked scores until you give them a hard gate.
|
|
88
|
+
Configure the judge model in `evals.config.ts`. The
|
|
89
|
+
[Evals reference](/docs/reference/evals.md#judges) owns grader options and
|
|
90
|
+
severity rules.
|
|
383
91
|
|
|
384
|
-
|
|
385
|
-
`defineEval({ judge })`, a case-level `judge`, or a per-call
|
|
386
|
-
`{ model }`. The nearest one wins. A judge call with no model
|
|
387
|
-
configured fails the case. A judge that cannot reach a model (no
|
|
388
|
-
credential) ends the case as `skipped`, unless a deterministic gate
|
|
389
|
-
already failed.
|
|
92
|
+
## Test a conversation or approval
|
|
390
93
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
`t.check`. Anything derived from the agent under test is untrusted
|
|
395
|
-
input to your prompt: wrap it with `fenceUntrusted` and include
|
|
396
|
-
`EVAL_JUDGE_INJECTION_GUARD`, as the built-in graders do.
|
|
94
|
+
Several `t.send` calls in one case share a session. Assertions on a
|
|
95
|
+
returned turn inspect only that turn, while assertions on `t` inspect
|
|
96
|
+
the whole conversation.
|
|
397
97
|
|
|
398
98
|
```ts
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
fenceUntrusted,
|
|
402
|
-
} from "@cursor/july/evals";
|
|
403
|
-
|
|
404
|
-
const gold = ["XSS in search.ts", "open redirect in login.ts"];
|
|
405
|
-
const reply = await t.judge.model(
|
|
406
|
-
[
|
|
407
|
-
"For each GOLD finding, answer whether SUBMISSION reports it.",
|
|
408
|
-
"Reply with one line per finding: <index> YES|NO.",
|
|
409
|
-
EVAL_JUDGE_INJECTION_GUARD,
|
|
410
|
-
fenceUntrusted("GOLD", gold.map((g, i) => `${i + 1}. ${g}`).join("\n")),
|
|
411
|
-
fenceUntrusted("SUBMISSION", t.reply ?? ""),
|
|
412
|
-
].join("\n\n")
|
|
413
|
-
);
|
|
414
|
-
const hits = reply.match(/\bYES\b/g)?.length ?? 0;
|
|
415
|
-
t.score("recall", hits / gold.length).atLeast(0.5);
|
|
416
|
-
```
|
|
417
|
-
|
|
418
|
-
## Keep side effects out of eval sessions
|
|
99
|
+
const first = await t.send("Inspect PR 42.");
|
|
100
|
+
first.calledTool("inspect_pr");
|
|
419
101
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
tool, hook, or result handler that actuates:
|
|
425
|
-
|
|
426
|
-
```ts
|
|
427
|
-
// agent/tools/post_findings.ts
|
|
428
|
-
async execute({ findings }, ctx) {
|
|
429
|
-
if (ctx.session.purpose === "eval") {
|
|
430
|
-
return { posted: false, reason: "eval", count: findings.length };
|
|
431
|
-
}
|
|
432
|
-
// post the review
|
|
433
|
-
}
|
|
102
|
+
const followUp = await t.send("Now summarize only the blockers.");
|
|
103
|
+
followUp.usedNoTools();
|
|
104
|
+
t.check(followUp.message, includes(/blocker/i));
|
|
105
|
+
t.succeeded();
|
|
434
106
|
```
|
|
435
107
|
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
The same check belongs in [hooks](/docs/reference/hooks.md) that meter or
|
|
439
|
-
page and in `defineResult` commits.
|
|
440
|
-
|
|
441
|
-
## Worked examples
|
|
442
|
-
|
|
443
|
-
### Multi-turn: grade each turn
|
|
108
|
+
For a tool that requires approval, the expected result is a parked turn
|
|
109
|
+
instead of a completed one:
|
|
444
110
|
|
|
445
111
|
```ts
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
description: "Introduces itself once; a repeat mention gets a short ack.",
|
|
451
|
-
async test(t) {
|
|
452
|
-
const intro = await t.send("Meet Jenny! @Jenny introduce yourself.");
|
|
453
|
-
intro.expectOk();
|
|
454
|
-
t.check(intro.message, includes(/jenny/i));
|
|
455
|
-
|
|
456
|
-
const repeat = await t.send("Meet, @Jenny!");
|
|
457
|
-
t.succeeded();
|
|
458
|
-
repeat.usedNoTools();
|
|
459
|
-
t.check(
|
|
460
|
-
repeat.message,
|
|
461
|
-
satisfies((r) => (r as string).trim().length <= 280, "short ack")
|
|
462
|
-
);
|
|
463
|
-
t.check(
|
|
464
|
-
repeat.message,
|
|
465
|
-
satisfies((r) => !/what i can do/i.test(r as string), "no second intro")
|
|
466
|
-
);
|
|
467
|
-
},
|
|
112
|
+
await t.send("Apply the approved policy update.");
|
|
113
|
+
t.parked();
|
|
114
|
+
t.calledTool("apply_policy", {
|
|
115
|
+
input: { verdict: "update" },
|
|
468
116
|
});
|
|
469
117
|
```
|
|
470
118
|
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
119
|
+
Pair an approval case with a safe branch that calls
|
|
120
|
+
`t.notCalledTool("apply_policy")`, so both sides of the decision stay
|
|
121
|
+
protected.
|
|
474
122
|
|
|
475
|
-
|
|
123
|
+
## Pin realistic inputs
|
|
476
124
|
|
|
477
|
-
|
|
478
|
-
|
|
125
|
+
A useful eval changes only when the agent changes. Freeze canonical chat
|
|
126
|
+
prompts, seed workspace evidence directly, and save webhook payloads
|
|
127
|
+
instead of depending on a developer's checkout or live external state.
|
|
479
128
|
|
|
480
129
|
```ts
|
|
481
|
-
|
|
482
|
-
{
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
workspaceFiles: {
|
|
488
|
-
"week/prs.md": RULE,
|
|
489
|
-
"week/slack.md": SLACK,
|
|
490
|
-
"week/tree/AGENTS.md.txt": "# API\n\nKeep handlers thin.\n",
|
|
491
|
-
},
|
|
492
|
-
});
|
|
493
|
-
t.parked();
|
|
494
|
-
t.calledTool("apply_agents", { input: { verdict: "update" } });
|
|
130
|
+
await t.send("Review pr/diff.patch and report blockers.", {
|
|
131
|
+
workspaceFiles: {
|
|
132
|
+
"pr/diff.patch": [
|
|
133
|
+
"diff --git a/app/routes/search.ts b/app/routes/search.ts",
|
|
134
|
+
"+res.send(`<h1>Results for ${req.query.q}</h1>`);",
|
|
135
|
+
].join("\n"),
|
|
495
136
|
},
|
|
496
|
-
},
|
|
497
|
-
```
|
|
498
|
-
|
|
499
|
-
`t.parked()` and `t.succeeded()` are exclusive: a parked run is a clean
|
|
500
|
-
stop on an unanswered approval, not a completed one. Pair the parked
|
|
501
|
-
case with a sibling that expects `verdict: "skip"` and `t.succeeded()`,
|
|
502
|
-
so both branches stay pinned.
|
|
503
|
-
|
|
504
|
-
## Pin fixtures
|
|
505
|
-
|
|
506
|
-
A fixed input is what makes an eval repeatable. Pick the fixture by the
|
|
507
|
-
surface under test.
|
|
508
|
-
|
|
509
|
-
| Agent surface | Fixture |
|
|
510
|
-
| --- | --- |
|
|
511
|
-
| Chat or domain assistant | One canonical prompt string, chosen once and frozen |
|
|
512
|
-
| Tool-heavy | Run `agent-sdk call <tool>` first to pin what the tool returns, then freeze the prompt that triggers it |
|
|
513
|
-
| GitHub webhook | `agent-sdk github replay <pr> --events '*' --dry-run --out fixtures/github` snapshots real payloads for offline replay ([GitHub guide](/docs/guides/github.md#test-with-github-replay)) |
|
|
514
|
-
| PR reviewer with host preparation | Diff, metadata, and gold labels pinned to commit SHAs; keep any live PR matrix small |
|
|
515
|
-
| Workspace-dependent | `workspaceFiles` on the first `t.send`, never developer-machine paths |
|
|
516
|
-
|
|
517
|
-
Tag the fast, reliably passing core `smoke` and run `--tag smoke` in
|
|
518
|
-
the inner loop. Leave slow or drift-prone cases untagged for explicit
|
|
519
|
-
runs.
|
|
520
|
-
|
|
521
|
-
### Materialize API-backed fixtures
|
|
522
|
-
|
|
523
|
-
An input that only points at external data (a pull request URL, a
|
|
524
|
-
snapshot id, a pair of commit SHAs) is not self-contained. Fetch it once
|
|
525
|
-
and commit the rendered fixture before you expand the suite:
|
|
526
|
-
|
|
527
|
-
1. Save the diff, metadata, and labels under `fixtures/` at pinned
|
|
528
|
-
revisions.
|
|
529
|
-
2. Seed those files with `workspaceFiles`, or read them from the
|
|
530
|
-
fixture directory.
|
|
531
|
-
3. Assert decisions and output shape against the saved evidence.
|
|
532
|
-
4. Keep a small `smoke` subset for any remaining live checks.
|
|
533
|
-
|
|
534
|
-
`maxConcurrency` limits parallel datapoints, not the model or API
|
|
535
|
-
fan-out inside one datapoint. Materialized fixtures keep a large suite
|
|
536
|
-
from exhausting provider and GitHub rate limits.
|
|
537
|
-
|
|
538
|
-
### Load a dataset
|
|
539
|
-
|
|
540
|
-
Read committed fixtures with `loadJson`, `loadJsonl`, and `loadYaml`
|
|
541
|
-
from `@cursor/july/evals/loaders`. Relative paths resolve against the
|
|
542
|
-
project root the runner discovered, not the cwd the CLI ran from. Eval
|
|
543
|
-
files are ES modules, so top-level `await` can load a dataset and fan
|
|
544
|
-
one file out over it:
|
|
545
|
-
|
|
546
|
-
```ts
|
|
547
|
-
// evals/sql.eval.ts: sql/0000, sql/0001, ...
|
|
548
|
-
import { defineEval, equals } from "@cursor/july/evals";
|
|
549
|
-
import { loadYaml } from "@cursor/july/evals/loaders";
|
|
550
|
-
|
|
551
|
-
const rows = await loadYaml<{ task: string; prompt: string; sql: string }[]>(
|
|
552
|
-
"evals/data/cases.yaml"
|
|
553
|
-
);
|
|
554
|
-
|
|
555
|
-
export default rows.map((row) =>
|
|
556
|
-
defineEval({
|
|
557
|
-
description: row.task,
|
|
558
|
-
async test(t) {
|
|
559
|
-
await t.send(row.prompt);
|
|
560
|
-
t.succeeded();
|
|
561
|
-
t.check(t.reply, equals(row.sql));
|
|
562
|
-
},
|
|
563
|
-
})
|
|
564
|
-
);
|
|
565
|
-
```
|
|
566
|
-
|
|
567
|
-
## Configure eval runs
|
|
568
|
-
|
|
569
|
-
`evals/evals.config.ts` (or `.js`) holds project-wide defaults. It must
|
|
570
|
-
set `maxConcurrency`. Each case issues real model requests, so
|
|
571
|
-
concurrency is hard-capped at 200; the templates use 10.
|
|
572
|
-
`eval --list` works without the file. Running a case does not.
|
|
573
|
-
|
|
574
|
-
```ts
|
|
575
|
-
import { defineEvalConfig } from "@cursor/july/evals";
|
|
576
|
-
|
|
577
|
-
export default defineEvalConfig({
|
|
578
|
-
maxConcurrency: 20,
|
|
579
|
-
timeoutMs: 180_000,
|
|
580
|
-
judge: { model: "gpt-5.4-mini" },
|
|
581
137
|
});
|
|
582
138
|
```
|
|
583
139
|
|
|
584
|
-
|
|
585
|
-
| --- | --- | --- |
|
|
586
|
-
| `maxConcurrency` | required | Datapoints in flight at once, 1-200 |
|
|
587
|
-
| `timeoutMs` | `180_000` | Per-case timeout. Precedence: case or file `timeoutMs`, then `--timeout-ms`, then this value |
|
|
588
|
-
| `judge` | unset | Default judge model for `t.judge.*` |
|
|
589
|
-
| `reporters` | unset | Destinations that observe every case; `--skip-report` suppresses them |
|
|
590
|
-
| `maxPlaygroundRuns` | `20` | Batches kept in playground history (cap 500). Counts `--prod` and `--url` batches, not the default local run |
|
|
591
|
-
|
|
592
|
-
Reporters ship results somewhere; the runner still does the grading.
|
|
593
|
-
`JUnit({ filePath, suiteName? })` writes JUnit XML and
|
|
594
|
-
`Artifacts({ dir })` writes per-case files, both from
|
|
595
|
-
`@cursor/july/evals/reporters`. A custom reporter is an object with any
|
|
596
|
-
of `onRunStart`, `onEvalComplete`, and `onRunComplete`. A reporter that
|
|
597
|
-
throws is logged and never fails the run. CI usually attaches the
|
|
598
|
-
built-in two with `--junit` and `--artifacts` instead of `reporters`,
|
|
599
|
-
so output paths stay with the pipeline, not the eval author.
|
|
600
|
-
|
|
601
|
-
Playground batches survive restarts when the project configures
|
|
602
|
-
durable storage. Otherwise they live in process
|
|
603
|
-
memory until `serve` exits.
|
|
604
|
-
|
|
605
|
-
## Run evals from the CLI
|
|
140
|
+
For GitHub agents, snapshot a PR into committed fixtures:
|
|
606
141
|
|
|
607
142
|
```bash
|
|
608
|
-
agent-sdk
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
agent-sdk eval --dir . --tag smoke --tag pull-request # any matching tag
|
|
613
|
-
agent-sdk eval --dir . --verbose # t.log lines + reply snippets
|
|
614
|
-
agent-sdk eval --dir . --timeout-ms 300000 # override the per-case timeout
|
|
143
|
+
agent-sdk github replay acme/checkout#42 \
|
|
144
|
+
--events '*' \
|
|
145
|
+
--dry-run \
|
|
146
|
+
--out fixtures/github
|
|
615
147
|
```
|
|
616
148
|
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
and
|
|
149
|
+
Keep a small, fast `smoke` set for every change. Put larger datasets and
|
|
150
|
+
drift-prone live cases behind an explicit selection. See
|
|
151
|
+
[Datasets and fixtures](/docs/reference/evals.md#datasets-and-fixtures) for
|
|
152
|
+
loaders and case expansion.
|
|
621
153
|
|
|
622
|
-
|
|
623
|
-
cases don't inherit your checkout's `AGENTS.md` and session state stays
|
|
624
|
-
out of the project. Artifacts still land in the project state
|
|
625
|
-
directory; see [Where results land](#where-results-land). `--slug`
|
|
626
|
-
picks the target in a multi-agent directory.
|
|
154
|
+
## Run and debug a regression suite
|
|
627
155
|
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
`--artifacts`, `--max-concurrency`, `--skip-report`) do not apply. See
|
|
632
|
-
[Run evals in the playground or on a deployment](#run-evals-in-the-playground-or-on-a-deployment).
|
|
156
|
+
Run one case while iterating, then the smoke suite before review. A
|
|
157
|
+
failure artifact records the input, assertions, tool calls, and final
|
|
158
|
+
text, making it the first place to look before changing the prompt.
|
|
633
159
|
|
|
634
160
|
```bash
|
|
635
|
-
agent-sdk eval --
|
|
636
|
-
|
|
161
|
+
agent-sdk eval --dir . readiness
|
|
162
|
+
agent-sdk eval --dir . --tag smoke
|
|
163
|
+
agent-sdk eval --dir . --json
|
|
637
164
|
```
|
|
638
165
|
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
166
|
+
By default, results land under `evals/<stamp>/` in the project state
|
|
167
|
+
directory. Open `evals/<case-id>.json` inside that run directory for the
|
|
168
|
+
failed case. This artifact location is independent of `--state-root`;
|
|
169
|
+
pass `--artifacts <dir>` to choose another destination.
|
|
642
170
|
|
|
643
|
-
Model turns need a
|
|
644
|
-
|
|
645
|
-
`
|
|
646
|
-
`agent-sdk login`. The judge uses the same one. `eval --list` needs
|
|
647
|
-
none.
|
|
648
|
-
|
|
649
|
-
### Where results land
|
|
650
|
-
|
|
651
|
-
Every local run writes artifacts to a timestamped directory under
|
|
652
|
-
`evals/` in the project state directory, whatever `--state-root` says.
|
|
653
|
-
`--artifacts <dir>` chooses the path and `--no-artifacts` skips them.
|
|
654
|
-
The directory holds `summary.json`,
|
|
655
|
-
`results.jsonl`, and `evals/<case-id>.json` with every assertion, the
|
|
656
|
-
inputs, tool calls with arguments and output, the final text, and
|
|
657
|
-
`t.log` lines. Start there when a case fails. `--out <file>` also
|
|
658
|
-
writes the full results JSON to a path of your choice.
|
|
659
|
-
|
|
660
|
-
The artifact does not include the session's event stream. Pass
|
|
661
|
-
`--state-root <path>` to keep the ephemeral server's
|
|
662
|
-
[session data](/docs/reference/sessions.md#where-does-the-agent-sdk-store-session-data)
|
|
663
|
-
on disk when you need the raw events.
|
|
171
|
+
Model turns need a credential. Resolution checks `CURSOR_API_KEY`,
|
|
172
|
+
`CURSOR_API_KEY_FILE`, `CURSOR_SERVICE_ACCOUNT_KEY`, then a saved
|
|
173
|
+
`agent-sdk login`. `eval --list` only discovers cases and needs none.
|
|
664
174
|
|
|
665
175
|
## Run evals in CI
|
|
666
176
|
|
|
667
|
-
|
|
668
|
-
|
|
177
|
+
Write machine-readable output and JUnit annotations, then let a failed
|
|
178
|
+
gate fail the job:
|
|
669
179
|
|
|
670
180
|
```bash
|
|
671
|
-
# CURSOR_API_KEY comes from the CI secret store
|
|
181
|
+
# CURSOR_API_KEY comes from the CI secret store.
|
|
672
182
|
agent-sdk eval --dir . --json --no-stream \
|
|
673
183
|
--junit reports/evals.xml \
|
|
674
184
|
--artifacts reports/evals \
|
|
675
185
|
> reports/evals.json
|
|
676
186
|
```
|
|
677
187
|
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
setting, for example to run lower on a shared runner.
|
|
682
|
-
|
|
683
|
-
The JSON on stdout carries the totals and one result per case:
|
|
684
|
-
|
|
685
|
-
```json
|
|
686
|
-
{
|
|
687
|
-
"ok": true,
|
|
688
|
-
"passed": 1,
|
|
689
|
-
"failed": 0,
|
|
690
|
-
"scored": 0,
|
|
691
|
-
"skipped": 0,
|
|
692
|
-
"strict": false,
|
|
693
|
-
"artifactsDir": "/work/my-agent/reports/evals",
|
|
694
|
-
"results": [
|
|
695
|
-
{
|
|
696
|
-
"id": "readiness",
|
|
697
|
-
"verdict": "passed",
|
|
698
|
-
"ok": true,
|
|
699
|
-
"assertions": [
|
|
700
|
-
{ "name": "succeeded", "passed": true },
|
|
701
|
-
{ "name": "calledTool(inspect_pr)", "passed": true }
|
|
702
|
-
],
|
|
703
|
-
"sessionId": "ses_123",
|
|
704
|
-
"inputs": ["Is https://github.com/acme/checkout/pull/42 ready to approve?"],
|
|
705
|
-
"toolCalls": [{ "toolName": "inspect_pr", "isError": false }],
|
|
706
|
-
"metrics": {},
|
|
707
|
-
"logs": [],
|
|
708
|
-
"durationMs": 12340
|
|
709
|
-
}
|
|
710
|
-
]
|
|
711
|
-
}
|
|
712
|
-
```
|
|
713
|
-
|
|
714
|
-
Each result can also include `description`, `finalText`, `tools`,
|
|
715
|
-
`error`, `skipReason`, `metadata`, `tags`, and tool `args` and `output`.
|
|
716
|
-
A soft miss shows as `"severity": "soft"` with `score` and `threshold`
|
|
717
|
-
on the assertion. This shape lets CI report the failed assertion
|
|
718
|
-
without parsing terminal text.
|
|
188
|
+
Run `--tag smoke` on pull requests and the full suite on a schedule when
|
|
189
|
+
cost or latency makes every-push coverage impractical. Use soft scores
|
|
190
|
+
for a new probabilistic benchmark until its threshold is trustworthy.
|
|
719
191
|
|
|
720
|
-
|
|
192
|
+
The [CLI reference](/docs/reference/cli.md#eval) covers selectors, hosted
|
|
193
|
+
runs, exit codes, and JSON output.
|
|
721
194
|
|
|
722
|
-
|
|
723
|
-
- For probabilistic behavior, use `iterations` and a soft bar instead
|
|
724
|
-
of one hard gate.
|
|
195
|
+
## Keep side effects out of eval sessions
|
|
725
196
|
|
|
726
|
-
|
|
197
|
+
Eval sessions carry `purpose: "eval"`. Check it at the deterministic
|
|
198
|
+
write boundary and return the decision without performing the external
|
|
199
|
+
action:
|
|
727
200
|
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
201
|
+
```ts
|
|
202
|
+
async execute({ findings }, ctx) {
|
|
203
|
+
if (ctx.session.purpose === "eval") {
|
|
204
|
+
return {
|
|
205
|
+
posted: false,
|
|
206
|
+
reason: "eval",
|
|
207
|
+
count: findings.length,
|
|
208
|
+
};
|
|
209
|
+
}
|
|
732
210
|
|
|
733
|
-
|
|
734
|
-
|
|
211
|
+
return await postFindings(findings);
|
|
212
|
+
}
|
|
735
213
|
```
|
|
736
214
|
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
server's playground history:
|
|
215
|
+
This preserves the tool call in the trajectory, so the eval can still
|
|
216
|
+
assert that the agent chose to post.
|
|
740
217
|
|
|
741
|
-
|
|
742
|
-
agent-sdk eval --prod --slug vulnerability-scanner --tag deepsec
|
|
743
|
-
# Eval ID: <evalId>
|
|
744
|
-
# Playground: <deployment>/playground?view=evals&evalRunId=<evalId>
|
|
745
|
-
agent-sdk eval status <evalId> --prod --slug vulnerability-scanner
|
|
746
|
-
agent-sdk eval cancel <evalId> --prod --slug vulnerability-scanner
|
|
747
|
-
```
|
|
218
|
+
## Evals, hooks, or hillclimbing?
|
|
748
219
|
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
[Playground eval routes](/docs/reference/http-api.md#playground-eval-routes).
|
|
220
|
+
Use an eval to gate one fixed input. Use a
|
|
221
|
+
[hook](/docs/reference/hooks.md) to observe every live session for metrics,
|
|
222
|
+
auditing, or alerts. Use [hillclimbing](/docs/hillclimbing.md) to decide
|
|
223
|
+
which source change improves a fixed set of inputs; every kept
|
|
224
|
+
hillclimb change should add an eval.
|
|
755
225
|
|
|
756
|
-
##
|
|
226
|
+
## Gates and scores
|
|
757
227
|
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
228
|
+
`t.succeeded()`, tool assertions, and deterministic checks are hard
|
|
229
|
+
gates by default. A failed gate fails the case. `.soft()` records a
|
|
230
|
+
measurement without blocking, while `.atLeast(threshold)` records a
|
|
231
|
+
score and marks a miss as `scored`.
|
|
232
|
+
|
|
233
|
+
Start with decisions and output shape: the intended tool, the tempting
|
|
234
|
+
wrong tool, and one structural check. Exact prose is rarely a stable
|
|
235
|
+
contract.
|
|
236
|
+
|
|
237
|
+
## Keep improvements with regression evals
|
|
763
238
|
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
239
|
+
Every kept improvement needs an eval that would have failed before the
|
|
240
|
+
change. A tool-choice gate, bounded `maxToolCalls`, or output-shape check
|
|
241
|
+
turns the improvement into a durable contract.
|
|
767
242
|
|
|
768
|
-
|
|
243
|
+
Never weaken an existing gate to make a new implementation pass. That
|
|
244
|
+
moves the freeze line instead of proving the change.
|
|
769
245
|
|
|
770
|
-
|
|
246
|
+
## Related
|
|
771
247
|
|
|
772
|
-
- [
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
- [Sessions
|
|
778
|
-
|
|
248
|
+
- [Evals reference](/docs/reference/evals.md): complete authoring and runner
|
|
249
|
+
contracts
|
|
250
|
+
- [`skills/evals/SKILL.md`](https://github.com/cursor/cursor/blob/main/packages/agent-serve/skills/evals/SKILL.md): author and seed
|
|
251
|
+
cases with a coding agent
|
|
252
|
+
- [Hillclimbing](/docs/hillclimbing.md): measure a change and lock the win
|
|
253
|
+
- [Sessions](/docs/reference/sessions.md): events available to trajectory
|
|
254
|
+
assertions
|