@cursor/bdk 0.2.24 → 0.2.26
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/AGENTS.md +4 -18
- package/CHANGELOG.md +3 -0
- package/dist/artifacts.d.ts +1 -1
- package/dist/artifacts.js +1 -1
- package/dist/bin/agent-serve.d.ts +1 -1
- package/dist/bin/agent-serve.js +71 -31
- package/dist/channels/bitbucket/api.d.ts +2 -2
- package/dist/channels/bitbucket/api.d.ts.map +1 -1
- package/dist/channels/bitbucket/bitbucket-channel.js +1 -1
- package/dist/channels/bitbucket/bitbucket-webhook.d.ts +5 -4
- package/dist/channels/bitbucket/bitbucket-webhook.d.ts.map +1 -1
- package/dist/channels/bitbucket/bitbucket-webhook.js +14 -9
- package/dist/channels/change-monitors/change-monitors-channel.js +1 -1
- package/dist/channels/deployments/deployments-channel.js +1 -1
- package/dist/channels/github/cursor-account.d.ts +7 -0
- package/dist/channels/github/cursor-account.d.ts.map +1 -1
- package/dist/channels/github/cursor-account.js +22 -5
- package/dist/channels/github/github-channel.d.ts.map +1 -1
- package/dist/channels/github/github-channel.js +10 -19
- package/dist/channels/github/replay.d.ts +1 -1
- package/dist/channels/github/replay.d.ts.map +1 -1
- package/dist/channels/gitlab/api.d.ts +2 -2
- package/dist/channels/gitlab/api.d.ts.map +1 -1
- package/dist/channels/gitlab/gitlab-channel.js +1 -1
- package/dist/channels/issues/issues-channel.js +1 -1
- package/dist/channels/origin/api.d.ts +4 -4
- package/dist/channels/origin/api.d.ts.map +1 -1
- package/dist/channels/origin/origin-channel.js +1 -1
- package/dist/channels/origin/origin-webhook.d.ts +3 -3
- package/dist/channels/origin/origin-webhook.d.ts.map +1 -1
- package/dist/channels/pagerduty/api.d.ts +74 -0
- package/dist/channels/pagerduty/api.d.ts.map +1 -0
- package/dist/channels/pagerduty/api.js +101 -0
- package/dist/channels/pagerduty/defaults.d.ts +42 -0
- package/dist/channels/pagerduty/defaults.d.ts.map +1 -0
- package/dist/channels/pagerduty/defaults.js +132 -0
- package/dist/channels/pagerduty/events.d.ts +24 -0
- package/dist/channels/pagerduty/events.d.ts.map +1 -0
- package/dist/channels/pagerduty/events.js +38 -0
- package/dist/channels/pagerduty/index.d.ts +31 -0
- package/dist/channels/pagerduty/index.d.ts.map +1 -0
- package/dist/channels/pagerduty/index.js +30 -0
- package/dist/channels/pagerduty/pagerduty-channel.d.ts +64 -0
- package/dist/channels/pagerduty/pagerduty-channel.d.ts.map +1 -0
- package/dist/channels/pagerduty/pagerduty-channel.js +195 -0
- package/dist/channels/pagerduty/pagerduty-webhook.d.ts +70 -0
- package/dist/channels/pagerduty/pagerduty-webhook.d.ts.map +1 -0
- package/dist/channels/pagerduty/pagerduty-webhook.js +280 -0
- package/dist/channels/pagerduty/payload.d.ts +33 -0
- package/dist/channels/pagerduty/payload.d.ts.map +1 -0
- package/dist/channels/pagerduty/payload.js +150 -0
- package/dist/channels/pagerduty/replay.d.ts +35 -0
- package/dist/channels/pagerduty/replay.d.ts.map +1 -0
- package/dist/channels/pagerduty/replay.js +115 -0
- package/dist/channels/pagerduty/secrets.d.ts +16 -0
- package/dist/channels/pagerduty/secrets.d.ts.map +1 -0
- package/dist/channels/pagerduty/secrets.js +23 -0
- package/dist/channels/pagerduty/self-user.d.ts +51 -0
- package/dist/channels/pagerduty/self-user.d.ts.map +1 -0
- package/dist/channels/pagerduty/self-user.js +157 -0
- package/dist/channels/pagerduty/state.d.ts +31 -0
- package/dist/channels/pagerduty/state.d.ts.map +1 -0
- package/dist/channels/pagerduty/state.js +30 -0
- package/dist/channels/pagerduty/types.d.ts +217 -0
- package/dist/channels/pagerduty/types.d.ts.map +1 -0
- package/dist/channels/pagerduty/types.js +1 -0
- package/dist/channels/runs/runs-channel.js +1 -1
- package/dist/channels/slack/agentic-delivery.d.ts +2 -1
- package/dist/channels/slack/agentic-delivery.d.ts.map +1 -1
- package/dist/channels/slack/agentic-delivery.js +6 -10
- package/dist/channels/slack/agentic-signals.d.ts +2 -7
- package/dist/channels/slack/agentic-signals.d.ts.map +1 -1
- package/dist/channels/slack/agentic-signals.js +4 -3
- package/dist/channels/slack/api.d.ts +1 -0
- package/dist/channels/slack/api.d.ts.map +1 -1
- package/dist/channels/slack/api.js +3 -0
- package/dist/channels/slack/constants.d.ts +2 -0
- package/dist/channels/slack/constants.d.ts.map +1 -1
- package/dist/channels/slack/constants.js +2 -0
- package/dist/channels/slack/defaults.d.ts.map +1 -1
- package/dist/channels/slack/defaults.js +3 -2
- package/dist/channels/slack/dispatch.d.ts +9 -0
- package/dist/channels/slack/dispatch.d.ts.map +1 -1
- package/dist/channels/slack/dispatch.js +3 -0
- package/dist/channels/slack/inbound.d.ts.map +1 -1
- package/dist/channels/slack/inbound.js +24 -20
- package/dist/channels/slack/interactive.d.ts +2 -0
- package/dist/channels/slack/interactive.d.ts.map +1 -1
- package/dist/channels/slack/interactive.js +1 -0
- package/dist/channels/slack/live-delivery.d.ts +3 -0
- package/dist/channels/slack/live-delivery.d.ts.map +1 -1
- package/dist/channels/slack/live-delivery.js +5 -0
- package/dist/channels/slack/reply-options.d.ts +9 -0
- package/dist/channels/slack/reply-options.d.ts.map +1 -1
- package/dist/channels/slack/reply-options.js +31 -1
- package/dist/channels/slack/slack-channel.d.ts.map +1 -1
- package/dist/channels/slack/slack-channel.js +7 -0
- package/dist/channels/slack/stream.d.ts +5 -1
- package/dist/channels/slack/stream.d.ts.map +1 -1
- package/dist/channels/slack/types.d.ts +29 -0
- package/dist/channels/slack/types.d.ts.map +1 -1
- package/dist/channels.d.ts +7 -1
- package/dist/channels.d.ts.map +1 -1
- package/dist/channels.js +12 -24
- package/dist/docs/404.html +3 -3
- package/dist/docs/assets/{app.DTIg0uKK.js → app.BITbgXMP.js} +4 -4
- package/dist/docs/assets/changelog.md.sdD6ctqK.js +1 -0
- package/dist/docs/assets/changelog.md.sdD6ctqK.lean.js +1 -0
- package/dist/docs/assets/chunks/@localSearchIndexroot.B45uCZp9.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.BpJoSaxi.js → VPLocalSearchBox.3qo4-bX9.js} +2 -2
- package/dist/docs/assets/chunks/{arc.ylgNvRNq.js → arc.CTrZocKU.js} +1 -1
- package/dist/docs/assets/chunks/{architectureDiagram-Q4EWVU46.BMrNJqYk.js → architectureDiagram-Q4EWVU46.BkgIqxrv.js} +1 -1
- package/dist/docs/assets/chunks/{baseUniq.BBWUEqf9.js → baseUniq.5w0JfVgo.js} +1 -1
- package/dist/docs/assets/chunks/{blockDiagram-DXYQGD6D.DFMu-Vza.js → blockDiagram-DXYQGD6D.BVLtPjQc.js} +1 -1
- package/dist/docs/assets/chunks/{c4Diagram-AHTNJAMY.8nkAAxWv.js → c4Diagram-AHTNJAMY.CQ7neZTW.js} +1 -1
- package/dist/docs/assets/chunks/channel.Cv2w64wj.js +1 -0
- package/dist/docs/assets/chunks/{chunk-4BX2VUAB.sO-z2Bag.js → chunk-4BX2VUAB.D-hJ7uKM.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-4TB4RGXK.BMROzTMq.js → chunk-4TB4RGXK.RBYX5ywX.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-55IACEB6.X81urwg7.js → chunk-55IACEB6.Br05HoEb.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-EDXVE4YY.eaZVFLZM.js → chunk-EDXVE4YY.BD_7QS60.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-FMBD7UC4.CmZhzstR.js → chunk-FMBD7UC4.BOPnMabX.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-OYMX7WX6.CTezt9Lc.js → chunk-OYMX7WX6.DmGIdP8i.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-QZHKN3VN.s-T8zukB.js → chunk-QZHKN3VN.CGHmolCB.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-YZCP3GAM.DN4Nhy-D.js → chunk-YZCP3GAM.C_Uhs25v.js} +1 -1
- package/dist/docs/assets/chunks/classDiagram-6PBFFD2Q.CtO2atCr.js +1 -0
- package/dist/docs/assets/chunks/classDiagram-v2-HSJHXN6E.CtO2atCr.js +1 -0
- package/dist/docs/assets/chunks/clone.hfsCtgP4.js +1 -0
- package/dist/docs/assets/chunks/{cose-bilkent-S5V4N54A.Cqyp4BUH.js → cose-bilkent-S5V4N54A.DsU6xpcZ.js} +1 -1
- package/dist/docs/assets/chunks/{dagre-KV5264BT.BIECOiqR.js → dagre-KV5264BT.BqQLDcoU.js} +1 -1
- package/dist/docs/assets/chunks/{diagram-5BDNPKRD.1tLyWoTg.js → diagram-5BDNPKRD.Cgv8uUNF.js} +1 -1
- package/dist/docs/assets/chunks/{diagram-G4DWMVQ6.BVY_6VMO.js → diagram-G4DWMVQ6.BXHPSXh_.js} +1 -1
- package/dist/docs/assets/chunks/{diagram-MMDJMWI5.BSZ7xiBB.js → diagram-MMDJMWI5.CgJzo8f_.js} +1 -1
- package/dist/docs/assets/chunks/{diagram-TYMM5635.Bho6GmLh.js → diagram-TYMM5635.CfiN6lgT.js} +1 -1
- package/dist/docs/assets/chunks/{erDiagram-SMLLAGMA.A0yVIANn.js → erDiagram-SMLLAGMA.8n_hHzAd.js} +1 -1
- package/dist/docs/assets/chunks/{flowDiagram-DWJPFMVM.ZMgbllH6.js → flowDiagram-DWJPFMVM.B2pb1Dv_.js} +1 -1
- package/dist/docs/assets/chunks/{ganttDiagram-T4ZO3ILL.BCCPBhXo.js → ganttDiagram-T4ZO3ILL.BFih4ucI.js} +1 -1
- package/dist/docs/assets/chunks/{gitGraphDiagram-UUTBAWPF.BOkL0BbA.js → gitGraphDiagram-UUTBAWPF.CqZ8PTl8.js} +1 -1
- package/dist/docs/assets/chunks/{graph.DMyZPu86.js → graph.0ufsI9gu.js} +1 -1
- package/dist/docs/assets/chunks/{infoDiagram-42DDH7IO.CjG1IiEw.js → infoDiagram-42DDH7IO.BkPRFww4.js} +1 -1
- package/dist/docs/assets/chunks/{ishikawaDiagram-UXIWVN3A.UCe-kq9g.js → ishikawaDiagram-UXIWVN3A.DCRK-cVX.js} +1 -1
- package/dist/docs/assets/chunks/{journeyDiagram-VCZTEJTY.3WyOK_eY.js → journeyDiagram-VCZTEJTY.BFyAJo33.js} +1 -1
- package/dist/docs/assets/chunks/{kanban-definition-6JOO6SKY.WoRG2qY1.js → kanban-definition-6JOO6SKY.CmA2SoGc.js} +1 -1
- package/dist/docs/assets/chunks/{layout.DV07xDd5.js → layout.CYY-CbMr.js} +1 -1
- package/dist/docs/assets/chunks/{linear.CTO8mN6o.js → linear.DeeDV4Oq.js} +1 -1
- package/dist/docs/assets/chunks/{min.SvTtcKuZ.js → min.BL3XTBN2.js} +1 -1
- package/dist/docs/assets/chunks/{mindmap-definition-QFDTVHPH.DMGgQ-HB.js → mindmap-definition-QFDTVHPH.BcbY-G6H.js} +1 -1
- package/dist/docs/assets/chunks/{pieDiagram-DEJITSTG.B7851apI.js → pieDiagram-DEJITSTG.dzDcQnPE.js} +1 -1
- package/dist/docs/assets/chunks/{quadrantDiagram-34T5L4WZ.CEqyypIX.js → quadrantDiagram-34T5L4WZ.RxR0m5iK.js} +1 -1
- package/dist/docs/assets/chunks/{requirementDiagram-MS252O5E.C3Mwsw-H.js → requirementDiagram-MS252O5E.DflaXb6Q.js} +1 -1
- package/dist/docs/assets/chunks/{sankeyDiagram-XADWPNL6.DyYK0XxY.js → sankeyDiagram-XADWPNL6.BteLKQAe.js} +1 -1
- package/dist/docs/assets/chunks/{sequenceDiagram-FGHM5R23.SiQPH-XM.js → sequenceDiagram-FGHM5R23.BD8jM8oz.js} +1 -1
- package/dist/docs/assets/chunks/{stateDiagram-FHFEXIEX.CTJMsP4p.js → stateDiagram-FHFEXIEX.C8SBkbPH.js} +1 -1
- package/dist/docs/assets/chunks/stateDiagram-v2-QKLJ7IA2.BLz7Qyo3.js +1 -0
- package/dist/docs/assets/chunks/{theme.DJo4my9R.js → theme.DiViIOLe.js} +2 -2
- package/dist/docs/assets/chunks/{timeline-definition-GMOUNBTQ.CxSNRlQ6.js → timeline-definition-GMOUNBTQ.D64XF5dV.js} +1 -1
- package/dist/docs/assets/chunks/{vennDiagram-DHZGUBPP.BdoJskyD.js → vennDiagram-DHZGUBPP.CwmeYan-.js} +1 -1
- package/dist/docs/assets/chunks/wardley-RL74JXVD.DmAlXlpu.js +162 -0
- package/dist/docs/assets/chunks/{wardleyDiagram-NUSXRM2D.IjIbFn_F.js → wardleyDiagram-NUSXRM2D.5VJ2-5K0.js} +1 -1
- package/dist/docs/assets/chunks/{xychartDiagram-5P7HB3ND.CPUxDZLH.js → xychartDiagram-5P7HB3ND.Cl6_fZVC.js} +1 -1
- package/dist/docs/assets/{guides_hooks.md.Bfj0pK91.js → guides_hooks.md.B2XfGX50.js} +7 -3
- package/dist/docs/assets/{guides_mcp-oauth.md.BM_eFC0L.js → guides_mcp-oauth.md.Cxq2TxBB.js} +3 -3
- package/dist/docs/assets/{guides_mcp-oauth.md.BM_eFC0L.lean.js → guides_mcp-oauth.md.Cxq2TxBB.lean.js} +1 -1
- package/dist/docs/assets/guides_opentelemetry.md.D4wO7_8v.js +37 -0
- package/dist/docs/assets/guides_opentelemetry.md.D4wO7_8v.lean.js +1 -0
- package/dist/docs/assets/guides_pagerduty.md.BHXMcMtx.js +60 -0
- package/dist/docs/assets/guides_pagerduty.md.BHXMcMtx.lean.js +1 -0
- package/dist/docs/assets/{guides_slack.md.Bn-WupSE.js → guides_slack.md.ClIyi7FI.js} +8 -3
- package/dist/docs/assets/{guides_slack.md.Bn-WupSE.lean.js → guides_slack.md.ClIyi7FI.lean.js} +1 -1
- package/dist/docs/assets/{reference_agent-config.md.IplwL25I.js → reference_agent-config.md.CGSx8COP.js} +6 -2
- package/dist/docs/assets/{reference_agent-config.md.IplwL25I.lean.js → reference_agent-config.md.CGSx8COP.lean.js} +1 -1
- package/dist/docs/assets/{reference_channels.md.DYg0CLud.js → reference_channels.md.CNNIS6K7.js} +1 -1
- package/dist/docs/assets/{reference_cli.md.DB7Llw3T.js → reference_cli.md.1o_TqKdt.js} +7 -2
- package/dist/docs/assets/{reference_cli.md.DB7Llw3T.lean.js → reference_cli.md.1o_TqKdt.lean.js} +1 -1
- package/dist/docs/assets/{reference_hooks.md.B1jq3oGl.js → reference_hooks.md.CROr0QgC.js} +13 -7
- package/dist/docs/assets/{reference_hooks.md.B1jq3oGl.lean.js → reference_hooks.md.CROr0QgC.lean.js} +1 -1
- package/dist/docs/assets/{reference_schedules.md.03Ryy9ca.js → reference_schedules.md.BqWnJES4.js} +3 -3
- package/dist/docs/assets/reference_sessions.md.Bi6lHttM.js +22 -0
- package/dist/docs/assets/reference_sessions.md.Bi6lHttM.lean.js +1 -0
- package/dist/docs/assets/{reference_skills.md.C2GWh7g8.js → reference_skills.md.Ckddg6KX.js} +3 -3
- package/dist/docs/assets/{reference_tools.md.08XR7lIl.js → reference_tools.md.Bo0UfT0a.js} +1 -1
- package/dist/docs/assets/{style.nMsabY-V.css → style.B9o0luvp.css} +1 -1
- package/dist/docs/building-with-agents.html +37 -37
- package/dist/docs/changelog.html +60 -0
- package/dist/docs/changelog.md +86 -0
- package/dist/docs/deployment.html +37 -37
- package/dist/docs/evals.html +37 -37
- package/dist/docs/guides/agent-to-agent.html +37 -37
- package/dist/docs/guides/bitbucket.html +37 -37
- package/dist/docs/guides/cloud-agents.html +37 -37
- package/dist/docs/guides/convert-automation.html +37 -37
- package/dist/docs/guides/export-grokbot.html +37 -37
- package/dist/docs/guides/github.html +37 -37
- package/dist/docs/guides/gitlab.html +37 -37
- package/dist/docs/guides/grokbot-agents.html +37 -37
- package/dist/docs/guides/hooks.html +45 -41
- package/dist/docs/guides/hooks.md +7 -3
- package/dist/docs/guides/improve.html +37 -37
- package/dist/docs/guides/jev.html +37 -37
- package/dist/docs/guides/mcp-oauth.html +39 -39
- package/dist/docs/guides/mcp-oauth.md +12 -0
- package/dist/docs/guides/migrate.html +37 -37
- package/dist/docs/guides/opentelemetry.html +62 -70
- package/dist/docs/guides/opentelemetry.md +150 -175
- package/dist/docs/guides/pagerduty.html +119 -0
- package/dist/docs/guides/pagerduty.md +336 -0
- package/dist/docs/guides/slack.html +44 -39
- package/dist/docs/guides/slack.md +41 -0
- package/dist/docs/guides/webhooks.html +37 -37
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +37 -37
- package/dist/docs/index.html +37 -37
- package/dist/docs/llms-full.txt +730 -163
- package/dist/docs/llms.txt +3 -1
- package/dist/docs/quickstart.html +37 -37
- package/dist/docs/reference/agent-config.html +42 -38
- package/dist/docs/reference/agent-config.md +21 -1
- package/dist/docs/reference/artifacts.html +37 -37
- package/dist/docs/reference/channels.html +38 -38
- package/dist/docs/reference/channels.md +7 -2
- package/dist/docs/reference/cli.html +43 -38
- package/dist/docs/reference/cli.md +27 -0
- package/dist/docs/reference/connections.html +37 -37
- package/dist/docs/reference/evals.html +37 -37
- package/dist/docs/reference/extensions.html +37 -37
- package/dist/docs/reference/hooks.html +49 -43
- package/dist/docs/reference/hooks.md +10 -5
- package/dist/docs/reference/http-api.html +37 -37
- package/dist/docs/reference/instructions.html +37 -37
- package/dist/docs/reference/memory.html +37 -37
- package/dist/docs/reference/playground.html +36 -36
- package/dist/docs/reference/project-layout.html +37 -37
- package/dist/docs/reference/prompt.html +37 -37
- package/dist/docs/reference/schedules.html +40 -40
- package/dist/docs/reference/sessions.html +58 -37
- package/dist/docs/reference/sessions.md +46 -1
- package/dist/docs/reference/skills.html +40 -40
- package/dist/docs/reference/subagents.html +37 -37
- package/dist/docs/reference/tools.html +39 -39
- package/dist/docs/reference/tools.md +4 -3
- package/dist/docs/templates/agentic-owners.html +37 -37
- package/dist/docs/templates/grokbot-agents.html +37 -37
- package/dist/docs/templates/security-reviewer.html +37 -37
- package/dist/docs/templates/thermo-quality-review.html +37 -37
- package/dist/docs/templates/thermo-review.html +37 -37
- package/dist/docs/templates/triage.html +37 -37
- package/dist/docs/troubleshooting.html +36 -36
- package/dist/extensions/cursor-cloud-agents/extension.d.ts.map +1 -1
- package/dist/extensions/cursor-cloud-agents/extension.js +15 -15
- package/dist/extensions/cursor-cloud-agents/lib/backend.js +1 -1
- package/dist/extensions/cursor-cloud-agents/lib/fleet.js +1 -1
- package/dist/extensions/cursor-cloud-agents/lib/inputs.d.ts +1 -1
- package/dist/extensions/cursor-cloud-agents/lib/inputs.d.ts.map +1 -1
- package/dist/extensions/cursor-cloud-agents/lib/inputs.js +1 -1
- package/dist/extensions/cursor-cloud-agents/reminders/cloud-agent-stop-watch.js +1 -1
- package/dist/extensions/cursor-cloud-agents/tools/launch.js +1 -1
- package/dist/extensions/cursor-cloud-agents/tools/list.js +1 -1
- package/dist/extensions/cursor-cloud-agents/tools/reply.js +1 -1
- package/dist/extensions/cursor-grokbot-agents/extension.d.ts.map +1 -1
- package/dist/extensions/cursor-grokbot-agents/extension.js +7 -3
- package/dist/extensions/cursor-grokbot-agents/lib/backend.js +1 -1
- package/dist/extensions/cursor-grokbot-agents/lib/contacts.js +1 -1
- package/dist/extensions/cursor-grokbot-agents/lib/inputs.d.ts +1 -1
- package/dist/extensions/cursor-grokbot-agents/lib/inputs.d.ts.map +1 -1
- package/dist/extensions/cursor-grokbot-agents/lib/inputs.js +1 -1
- package/dist/extensions/cursor-grokbot-agents/tools/ask.js +1 -1
- package/dist/extensions/cursor-grokbot-agents/tools/check.js +1 -1
- package/dist/extensions/cursor-grokbot-agents/tools/interrupt.js +1 -1
- package/dist/extensions/cursor-grokbot-agents/tools/list.js +1 -1
- package/dist/extensions/improve/extension.js +1 -1
- package/dist/extensions/jev/extension.js +2 -2
- package/dist/extensions/jev/tools/evaluate.js +3 -3
- package/dist/extensions/slack-communication/extension.js +1 -1
- package/dist/extensions/slack-communication/tools/delete-message.js +1 -1
- package/dist/extensions/slack-communication/tools/edit-message.d.ts.map +1 -1
- package/dist/extensions/slack-communication/tools/edit-message.js +3 -6
- package/dist/extensions/slack-communication/tools/post-card.js +1 -1
- package/dist/extensions/slack-communication/tools/post-file.js +1 -1
- package/dist/extensions/slack-communication/tools/post-update.d.ts.map +1 -1
- package/dist/extensions/slack-communication/tools/post-update.js +3 -6
- package/dist/extensions/slack-communication/tools/react.js +1 -1
- package/dist/extensions/slack-communication/tools/set-status.js +1 -1
- package/dist/extensions.d.ts +1 -1
- package/dist/extensions.js +1 -1
- package/dist/index.d.ts +14 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -4
- package/dist/internal/approval-gate.d.ts +4 -2
- package/dist/internal/approval-gate.d.ts.map +1 -1
- package/dist/internal/approval-gate.js +2 -1
- package/dist/internal/as-of.d.ts +2 -0
- package/dist/internal/as-of.d.ts.map +1 -1
- package/dist/internal/as-of.js +2 -0
- package/dist/internal/builtin-tools/artifacts.d.ts.map +1 -1
- package/dist/internal/builtin-tools/artifacts.js +45 -12
- package/dist/internal/builtin-tools/reminders.js +1 -1
- package/dist/internal/channel-architecture.d.ts +1 -1
- package/dist/internal/channel-architecture.d.ts.map +1 -1
- package/dist/internal/channel-architecture.js +4 -2
- package/dist/internal/cli-deploy.d.ts.map +1 -1
- package/dist/internal/cli-deploy.js +39 -22
- package/dist/internal/cli-pagerduty.d.ts +32 -0
- package/dist/internal/cli-pagerduty.d.ts.map +1 -0
- package/dist/internal/cli-pagerduty.js +242 -0
- package/dist/internal/continuation-channel.d.ts.map +1 -1
- package/dist/internal/continuation-channel.js +7 -0
- package/dist/internal/continuation-identity.d.ts +11 -3
- package/dist/internal/continuation-identity.d.ts.map +1 -1
- package/dist/internal/continuation-identity.js +83 -0
- package/dist/internal/continuation.d.ts +3 -0
- package/dist/internal/continuation.d.ts.map +1 -0
- package/dist/internal/continuation.js +1 -0
- package/dist/internal/conversation-mirror.d.ts +5 -0
- package/dist/internal/conversation-mirror.d.ts.map +1 -1
- package/dist/internal/conversation-mirror.js +12 -1
- package/dist/internal/convert-automation/convert-workflow.js +1 -1
- package/dist/internal/convert-grokbot/answers.d.ts.map +1 -1
- package/dist/internal/convert-grokbot/answers.js +10 -8
- package/dist/internal/convert-grokbot/recipe.d.ts +1 -1
- package/dist/internal/convert-grokbot/recipe.d.ts.map +1 -1
- package/dist/internal/convert-grokbot/recipe.js +1 -1
- package/dist/internal/cursor/account-mcp.d.ts.map +1 -1
- package/dist/internal/cursor/account-mcp.js +2 -0
- package/dist/internal/cursor/backend-client.d.ts +8 -3
- package/dist/internal/cursor/backend-client.d.ts.map +1 -1
- package/dist/internal/cursor/backend-client.js +8 -3
- package/dist/internal/cursor/credentials.d.ts +2 -2
- package/dist/internal/cursor/credentials.d.ts.map +1 -1
- package/dist/internal/cursor/credentials.js +1 -1
- package/dist/internal/cursor-account-mcp-auth.d.ts +6 -2
- package/dist/internal/cursor-account-mcp-auth.d.ts.map +1 -1
- package/dist/internal/cursor-account-mcp-auth.js +15 -6
- package/dist/internal/deferred-channel-session.d.ts +5 -4
- package/dist/internal/deferred-channel-session.d.ts.map +1 -1
- package/dist/internal/deferred-channel-session.js +6 -4
- package/dist/internal/deploy-client.d.ts +5 -0
- package/dist/internal/deploy-client.d.ts.map +1 -1
- package/dist/internal/deploy-client.js +3 -3
- package/dist/internal/deploy-manifest.d.ts +11 -4
- package/dist/internal/deploy-manifest.d.ts.map +1 -1
- package/dist/internal/deploy-manifest.js +19 -7
- package/dist/internal/describe-error.d.ts +2 -0
- package/dist/internal/describe-error.d.ts.map +1 -1
- package/dist/internal/describe-error.js +2 -0
- package/dist/internal/discovery/agent-config.d.ts.map +1 -1
- package/dist/internal/discovery/agent-config.js +10 -10
- package/dist/internal/discovery/agent.d.ts.map +1 -1
- package/dist/internal/discovery/agent.js +10 -10
- package/dist/internal/discovery/channels.d.ts.map +1 -1
- package/dist/internal/discovery/channels.js +20 -16
- package/dist/internal/discovery/context.d.ts +16 -0
- package/dist/internal/discovery/context.d.ts.map +1 -1
- package/dist/internal/discovery/context.js +67 -2
- package/dist/internal/discovery/cursor-plugin.js +8 -8
- package/dist/internal/discovery/extension-overlay.d.ts.map +1 -1
- package/dist/internal/discovery/extension-overlay.js +2 -6
- package/dist/internal/discovery/extensions.js +15 -8
- package/dist/internal/discovery/info.d.ts +2 -2
- package/dist/internal/discovery/info.d.ts.map +1 -1
- package/dist/internal/discovery/info.js +9 -9
- package/dist/internal/discovery/instructions.d.ts.map +1 -1
- package/dist/internal/discovery/instructions.js +3 -6
- package/dist/internal/discovery/instrumentation.d.ts +10 -0
- package/dist/internal/discovery/instrumentation.d.ts.map +1 -0
- package/dist/internal/discovery/instrumentation.js +29 -0
- package/dist/internal/discovery/modules.d.ts.map +1 -1
- package/dist/internal/discovery/modules.js +7 -10
- package/dist/internal/discovery/project-public.d.ts +16 -0
- package/dist/internal/discovery/project-public.d.ts.map +1 -0
- package/dist/internal/discovery/project-public.js +54 -0
- package/dist/internal/discovery/project.d.ts +6 -0
- package/dist/internal/discovery/project.d.ts.map +1 -1
- package/dist/internal/discovery/project.js +40 -8
- package/dist/internal/discovery/runtime.d.ts.map +1 -1
- package/dist/internal/discovery/runtime.js +8 -8
- package/dist/internal/discovery/services.d.ts +5 -4
- package/dist/internal/discovery/services.d.ts.map +1 -1
- package/dist/internal/discovery/services.js +12 -6
- package/dist/internal/discovery.d.ts +1 -1
- package/dist/internal/discovery.d.ts.map +1 -1
- package/dist/internal/discovery.js +1 -1
- package/dist/internal/event-mapper.d.ts.map +1 -1
- package/dist/internal/event-mapper.js +1 -0
- package/dist/internal/expected-delivery-failure.d.ts.map +1 -1
- package/dist/internal/expected-delivery-failure.js +6 -0
- package/dist/internal/factory-resource-channel.d.ts +1 -1
- package/dist/internal/factory-resource-channel.d.ts.map +1 -1
- package/dist/internal/filesystem/nearest.d.ts +1 -0
- package/dist/internal/filesystem/nearest.d.ts.map +1 -1
- package/dist/internal/filesystem/nearest.js +1 -0
- package/dist/internal/filesystem/sdk-schemas.d.ts.map +1 -1
- package/dist/internal/filesystem/sdk-schemas.js +4 -3
- package/dist/internal/filesystem/tools.d.ts.map +1 -1
- package/dist/internal/filesystem/tools.js +1 -1
- package/dist/internal/handleAgentServeTrigger.d.ts +10 -0
- package/dist/internal/handleAgentServeTrigger.d.ts.map +1 -1
- package/dist/internal/handleAgentServeTrigger.js +3 -0
- package/dist/internal/hmac-secret-values.d.ts +48 -0
- package/dist/internal/hmac-secret-values.d.ts.map +1 -0
- package/dist/internal/hmac-secret-values.js +68 -0
- package/dist/internal/host-otel.d.ts +1 -1
- package/dist/internal/host-otel.d.ts.map +1 -1
- package/dist/internal/host-otel.js +5 -0
- package/dist/internal/host-platforms.d.ts.map +1 -1
- package/dist/internal/host-platforms.js +8 -2
- package/dist/internal/hosted-delivery.d.ts.map +1 -1
- package/dist/internal/hosted-delivery.js +6 -2
- package/dist/internal/http-channel.d.ts.map +1 -1
- package/dist/internal/http-channel.js +1 -0
- package/dist/internal/ids.d.ts +8 -0
- package/dist/internal/ids.d.ts.map +1 -1
- package/dist/internal/ids.js +20 -0
- package/dist/internal/init-scaffold.js +1 -1
- package/dist/internal/interview/agent-questions.d.ts +1 -1
- package/dist/internal/interview/agent-questions.d.ts.map +1 -1
- package/dist/internal/interview/agent-questions.js +1 -1
- package/dist/internal/interview/question.d.ts +2 -2
- package/dist/internal/interview/question.d.ts.map +1 -1
- package/dist/internal/interview/question.js +2 -2
- package/dist/internal/json-schema.d.ts +7 -7
- package/dist/internal/json-schema.d.ts.map +1 -1
- package/dist/internal/json-schema.js +16 -23
- package/dist/internal/mcp-endpoint.d.ts +16 -4
- package/dist/internal/mcp-endpoint.d.ts.map +1 -1
- package/dist/internal/mcp-endpoint.js +18 -6
- package/dist/internal/mcp-host.d.ts +9 -0
- package/dist/internal/mcp-host.d.ts.map +1 -1
- package/dist/internal/mcp-host.js +15 -0
- package/dist/internal/otel/collector.d.ts +5 -0
- package/dist/internal/otel/collector.d.ts.map +1 -1
- package/dist/internal/otel/collector.js +27 -6
- package/dist/internal/otel/config.d.ts +37 -22
- package/dist/internal/otel/config.d.ts.map +1 -1
- package/dist/internal/otel/config.js +132 -125
- package/dist/internal/otel/conversation-span-processor.d.ts +9 -0
- package/dist/internal/otel/conversation-span-processor.d.ts.map +1 -0
- package/dist/internal/otel/conversation-span-processor.js +34 -0
- package/dist/internal/otel/customer.d.ts +52 -0
- package/dist/internal/otel/customer.d.ts.map +1 -0
- package/dist/internal/otel/customer.js +727 -0
- package/dist/internal/otel/runtime.d.ts +12 -16
- package/dist/internal/otel/runtime.d.ts.map +1 -1
- package/dist/internal/otel/runtime.js +37 -218
- package/dist/internal/otel-env.d.ts +6 -0
- package/dist/internal/otel-env.d.ts.map +1 -0
- package/dist/internal/otel-env.js +5 -0
- package/dist/internal/package-inline-stdio.d.ts.map +1 -1
- package/dist/internal/package-inline-stdio.js +21 -6
- package/dist/internal/reminder-runner.d.ts +9 -4
- package/dist/internal/reminder-runner.d.ts.map +1 -1
- package/dist/internal/reminder-runner.js +12 -10
- package/dist/internal/reminder-schedule.d.ts +1 -0
- package/dist/internal/reminder-schedule.d.ts.map +1 -1
- package/dist/internal/reminder-schedule.js +1 -0
- package/dist/internal/sdk-runner.d.ts +4 -3
- package/dist/internal/sdk-runner.d.ts.map +1 -1
- package/dist/internal/sdk-runner.js +157 -17
- package/dist/internal/secret-alternatives.d.ts +11 -0
- package/dist/internal/secret-alternatives.d.ts.map +1 -0
- package/dist/internal/secret-alternatives.js +13 -0
- package/dist/internal/server.d.ts +4 -1
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +27 -26
- package/dist/internal/session-engine.d.ts +27 -0
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +154 -25
- package/dist/internal/slack-provision-client.js +1 -1
- package/dist/internal/sqlite-experimental-warning.d.ts +2 -0
- package/dist/internal/sqlite-experimental-warning.d.ts.map +1 -0
- package/dist/internal/sqlite-experimental-warning.js +22 -0
- package/dist/internal/store-api-protocol.d.ts +1 -1
- package/dist/internal/store-api-protocol.d.ts.map +1 -1
- package/dist/internal/store-api-protocol.js +1 -1
- package/dist/internal/testing/conversation-identity-vectors.d.ts +6 -1
- package/dist/internal/testing/conversation-identity-vectors.d.ts.map +1 -1
- package/dist/internal/testing/conversation-identity-vectors.js +34 -0
- package/dist/internal/testing/hmac-secret-vectors.d.ts +38 -0
- package/dist/internal/testing/hmac-secret-vectors.d.ts.map +1 -0
- package/dist/internal/testing/hmac-secret-vectors.js +89 -0
- package/dist/internal/testing/pagerduty-continuation-fixtures.d.ts +42 -0
- package/dist/internal/testing/pagerduty-continuation-fixtures.d.ts.map +1 -0
- package/dist/internal/testing/pagerduty-continuation-fixtures.js +175 -0
- package/dist/internal/update-check.d.ts +2 -2
- package/dist/internal/update-check.d.ts.map +1 -1
- package/dist/internal/update-check.js +3 -3
- package/dist/internal/zod-schema.d.ts +14 -0
- package/dist/internal/zod-schema.d.ts.map +1 -0
- package/dist/internal/zod-schema.js +22 -0
- package/dist/internal/zod3-datetime.d.ts +12 -0
- package/dist/internal/zod3-datetime.d.ts.map +1 -0
- package/dist/internal/zod3-datetime.js +17 -0
- package/dist/otel-public.d.ts +2 -3
- package/dist/otel-public.d.ts.map +1 -1
- package/dist/otel-public.js +2 -2
- package/dist/otel.d.ts +3 -102
- package/dist/otel.d.ts.map +1 -1
- package/dist/otel.js +61 -97
- package/dist/playground/assets/cursor-icons-16-DmHBTm1-.woff2 +0 -0
- package/dist/playground/assets/index-CyPkf2y7.css +1 -0
- package/dist/playground/assets/index-DpbzbqFY.js +62 -0
- package/dist/playground/index.html +2 -2
- package/dist/public-deprecated.d.ts +36 -0
- package/dist/public-deprecated.d.ts.map +1 -0
- package/dist/public-deprecated.js +39 -0
- package/dist/tools.d.ts +16 -13
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +4 -3
- package/dist/types.d.ts +286 -104
- package/dist/types.d.ts.map +1 -1
- package/docs/changelog.md +91 -0
- package/docs/guides/hooks.md +7 -3
- package/docs/guides/mcp-oauth.md +12 -0
- package/docs/guides/opentelemetry.md +150 -180
- package/docs/guides/pagerduty.md +341 -0
- package/docs/guides/slack.md +41 -0
- package/docs/reference/agent-config.md +21 -1
- package/docs/reference/channels.md +7 -2
- package/docs/reference/cli.md +27 -0
- package/docs/reference/hooks.md +10 -5
- package/docs/reference/sessions.md +46 -1
- package/docs/reference/tools.md +4 -3
- package/package.json +39 -8
- package/schemas/grokbot-answers.schema.json +11 -0
- package/skills/framework-map/SKILL.md +2 -1
- package/skills/migrate-v2/SKILL.md +1 -1
- package/skills/otel/SKILL.md +30 -46
- package/templates/agentic-owners/README.md +6 -1
- package/templates/agentic-owners/bot/lib/owners/decision.ts +31 -5
- package/templates/agentic-owners/bot/lib/owners/globalOverride.ts +60 -0
- package/templates/agentic-owners/bot/lib/owners/match.ts +85 -19
- package/templates/agentic-owners/bot/lib/owners/parse.ts +133 -2
- package/templates/agentic-owners/bot/lib/owners/types.ts +23 -0
- package/templates/code-wiki/evals/wiki.eval.ts +2 -2
- package/dist/docs/assets/chunks/@localSearchIndexroot.3ebvCWKy.js +0 -1
- package/dist/docs/assets/chunks/channel.BOebySCN.js +0 -1
- package/dist/docs/assets/chunks/classDiagram-6PBFFD2Q.C55IaN-T.js +0 -1
- package/dist/docs/assets/chunks/classDiagram-v2-HSJHXN6E.C55IaN-T.js +0 -1
- package/dist/docs/assets/chunks/clone.D06pA7ML.js +0 -1
- package/dist/docs/assets/chunks/stateDiagram-v2-QKLJ7IA2.DddRVjeq.js +0 -1
- package/dist/docs/assets/chunks/wardley-RL74JXVD.CVCRSuQK.js +0 -162
- package/dist/docs/assets/guides_opentelemetry.md.Ck1o2frw.js +0 -45
- package/dist/docs/assets/guides_opentelemetry.md.Ck1o2frw.lean.js +0 -1
- package/dist/docs/assets/reference_sessions.md.C8FXuGwk.js +0 -1
- package/dist/docs/assets/reference_sessions.md.C8FXuGwk.lean.js +0 -1
- package/dist/playground/assets/cursor-icons-16-gwXtdAvu.woff2 +0 -0
- package/dist/playground/assets/index-DKKdkF29.js +0 -62
- package/dist/playground/assets/index-DpKinTMs.css +0 -1
- package/templates/grokbot-agents/.gitignore +0 -4
- package/templates/security-help/.gitignore +0 -4
- /package/dist/docs/assets/{guides_hooks.md.Bfj0pK91.lean.js → guides_hooks.md.B2XfGX50.lean.js} +0 -0
- /package/dist/docs/assets/{reference_channels.md.DYg0CLud.lean.js → reference_channels.md.CNNIS6K7.lean.js} +0 -0
- /package/dist/docs/assets/{reference_schedules.md.03Ryy9ca.lean.js → reference_schedules.md.BqWnJES4.lean.js} +0 -0
- /package/dist/docs/assets/{reference_skills.md.C2GWh7g8.lean.js → reference_skills.md.Ckddg6KX.lean.js} +0 -0
- /package/dist/docs/assets/{reference_tools.md.08XR7lIl.lean.js → reference_tools.md.Bo0UfT0a.lean.js} +0 -0
package/dist/docs/llms-full.txt
CHANGED
|
@@ -143,6 +143,97 @@ works; a measured climb proves it works better on fixed inputs.
|
|
|
143
143
|
|
|
144
144
|
---
|
|
145
145
|
|
|
146
|
+
Source: /docs/changelog.md
|
|
147
|
+
|
|
148
|
+
# Changelog
|
|
149
|
+
|
|
150
|
+
## 0.2.26 (2026-10-16)
|
|
151
|
+
|
|
152
|
+
### Breaking changes
|
|
153
|
+
|
|
154
|
+
- `serve({ otel })` is removed. Delete `bot/otel.ts`, `agent/otel.ts`, and `bot/instrumentation.ts`. Set `OTEL_*` variables. Read [Migrating from serve({ otel })](/docs/guides/opentelemetry.md#migrating-from-serve-otel).
|
|
155
|
+
|
|
156
|
+
### Behavior changes
|
|
157
|
+
|
|
158
|
+
- `ctx.host.otel` is deprecated. It still runs for this release. The first call emits one deprecation warning. Set `OTEL_*` variables. Record with `metrics.getMeter` and `trace.getTracer` from `@opentelemetry/api`.
|
|
159
|
+
- A span started during a turn or a tool gets `cursor.conversation.id` from the active context when the span does not set it. A metric does not. Call `currentConversationId` from `@cursor/bdk/otel` and set the attribute yourself. See [OpenTelemetry](/docs/guides/opentelemetry.md#what-you-can-record).
|
|
160
|
+
- A turn waits for MCP OAuth only when a person can connect. That is a playground or HTTP chat turn, or a Slack message on a channel that shows Connect. `toolApprovals: true` shows Connect, and so does `buildToolApprovalEvents` in `events`. A schedule, a reminder, a webhook, an eval, or a Slack channel without Connect does not wait. A required connection fails with `Reconnect <connection>`. An optional connection is skipped.
|
|
161
|
+
- A turn never waits to authorize an `optional` connection, also in the playground.
|
|
162
|
+
- A turn that waits for MCP OAuth stops after 10 minutes with `Reconnect <connection>`. `interrupt()` also stops the wait.
|
|
163
|
+
- `bdk deploy` rejects a source host other than GitHub, gitlab.com, or Origin.
|
|
164
|
+
- A new scaffold imports `zod/v4`. A zod 3 schema and a zod 4 schema both still parse.
|
|
165
|
+
- `bdk deploy` with no terminal lists a connector that needs sign-in as pending.
|
|
166
|
+
|
|
167
|
+
### New
|
|
168
|
+
|
|
169
|
+
- `bdk deploy` deploys a bot from a gitlab.com repository.
|
|
170
|
+
- When you omit `--cursor-events-repo`, a GitLab deploy watches that project. A nested group is part of the path.
|
|
171
|
+
- When that deploy cannot watch the project, the deploy still finishes. The CLI says the deployment is not watching the project.
|
|
172
|
+
- An agentic Slack reply can set `cards: { display: "plan" }`. Slack shows the `post-card` steps from that turn as one checklist.
|
|
173
|
+
- A `title` names that checklist. A title has at most 256 characters.
|
|
174
|
+
- With no `cards` option, Slack keeps one card for each step.
|
|
175
|
+
- `send()` returns a delivery id. Set `deliveryId` to choose it. `nudge.delivered` and `message.received` include that id.
|
|
176
|
+
|
|
177
|
+
### Fixes
|
|
178
|
+
|
|
179
|
+
- Public helper signatures use portable types. A webhook body is a `string` or a `Uint8Array`. An environment map is `Record<string, string | undefined>`.
|
|
180
|
+
- `HostFilesApi.read` takes a `HostFileTextEncoding`. A `Buffer` and `process.env` still type-check.
|
|
181
|
+
- OpenTelemetry ends each tool span when that tool finishes.
|
|
182
|
+
- With no OpenTelemetry endpoint, the process holds at most 2048 spans and 2048 log records.
|
|
183
|
+
- A follow-up after a redeploy resumes the same agent. A changed workspace path does not start a new conversation.
|
|
184
|
+
- In a Slack Connect channel, sender checks use the workspace where the app is installed.
|
|
185
|
+
- A `cursorAccount` GitHub GraphQL call includes the repository.
|
|
186
|
+
- A Slack bot with a lapsed MCP connection replies with a reconnect message.
|
|
187
|
+
|
|
188
|
+
## 0.2.25 (2026-10-14)
|
|
189
|
+
|
|
190
|
+
### New
|
|
191
|
+
|
|
192
|
+
- `bdk validate --json` writes one JSON object. Each diagnostic has a code.
|
|
193
|
+
|
|
194
|
+
### Fixes
|
|
195
|
+
|
|
196
|
+
- OpenTelemetry metrics follow `OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE`. The default stays delta.
|
|
197
|
+
- `ctx.host.github.getOctokit()` tries again after a failed lookup. A later call can succeed after a GitHub token becomes available.
|
|
198
|
+
|
|
199
|
+
## 0.2.24 (2026-10-13)
|
|
200
|
+
|
|
201
|
+
### Breaking changes
|
|
202
|
+
|
|
203
|
+
- Install `zod` in the project. The peer range is `^3.25.0` or `^4.0.0`. A new scaffold imports `zod/v3`.
|
|
204
|
+
|
|
205
|
+
### Behavior changes
|
|
206
|
+
|
|
207
|
+
- `setContinuationToken(null)` releases the continuation key. The next delivery starts a new session.
|
|
208
|
+
- Model fallback continues when a blocked model sends progress updates and no assistant text. Those updates are `user-message-appended`, `step-started`, and `step-completed`.
|
|
209
|
+
- Read a secret inside a handler, a tool, or a callback. A `process.env` read while the module is still loading returns an empty value on a Cursor-managed deploy.
|
|
210
|
+
- In the Agentic Approver template, a `paths` glob is relative to the policy directory.
|
|
211
|
+
- The package depends on `tsx` 4.23.15.
|
|
212
|
+
|
|
213
|
+
### New
|
|
214
|
+
|
|
215
|
+
- `hmacSignatureAuth` takes an optional `separator`. One header can then carry several HMAC signatures. PagerDuty uses a comma.
|
|
216
|
+
- `cursorCloudAgents` accepts `cloud.teamMcpServers`. The launch uses the team MCP servers you name.
|
|
217
|
+
|
|
218
|
+
### Fixes
|
|
219
|
+
|
|
220
|
+
- On Cursor-managed hosting, OpenTelemetry reads the endpoint, the headers, and the resource after secrets load. You can remove a workaround that reads `OTEL_EXPORTER_OTLP_HEADERS` again.
|
|
221
|
+
|
|
222
|
+
## 0.2.23 (2026-10-09)
|
|
223
|
+
|
|
224
|
+
### Behavior changes
|
|
225
|
+
|
|
226
|
+
- `bdk migrate` rewrites a URL-secret MCP peer to `defineConnection({ agent })` in the migration pull request.
|
|
227
|
+
- `bdk migrate` prints a checklist after the migration. It says when there is nothing to migrate.
|
|
228
|
+
- `bdk slack create --prod` says the deployment redeploys by itself.
|
|
229
|
+
- `bdk deploy` on a folder of several agents prints one command per agent. You run each command to deploy that agent.
|
|
230
|
+
|
|
231
|
+
### New
|
|
232
|
+
|
|
233
|
+
- A Slack app can opt in to the `chat:write.customize` scope. A post can then set its username and its icon. An app that leaves the scope off keeps its current scopes.
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
146
237
|
Source: /docs/deployment.md
|
|
147
238
|
|
|
148
239
|
# Deploy a BDK project
|
|
@@ -2520,8 +2611,13 @@ so the dashboard reflects live traffic instead of the test suite.
|
|
|
2520
2611
|
|
|
2521
2612
|
```ts
|
|
2522
2613
|
// bot/hooks/usage.ts
|
|
2614
|
+
import { metrics } from "@opentelemetry/api";
|
|
2523
2615
|
import { defineHook } from "@cursor/bdk/hooks";
|
|
2524
2616
|
|
|
2617
|
+
const meter = metrics.getMeter("acme");
|
|
2618
|
+
const inputTokens = meter.createCounter("acme.tokens.input");
|
|
2619
|
+
const outputTokens = meter.createCounter("acme.tokens.output");
|
|
2620
|
+
|
|
2525
2621
|
export default defineHook({
|
|
2526
2622
|
events: {
|
|
2527
2623
|
async "turn.completed"(event, ctx) {
|
|
@@ -2532,9 +2628,8 @@ export default defineHook({
|
|
|
2532
2628
|
return;
|
|
2533
2629
|
}
|
|
2534
2630
|
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
ctx.host.otel.increment("acme.tokens.output", outputTokens);
|
|
2631
|
+
inputTokens.add(event.data.usage.inputTokens);
|
|
2632
|
+
outputTokens.add(event.data.usage.outputTokens);
|
|
2538
2633
|
},
|
|
2539
2634
|
},
|
|
2540
2635
|
});
|
|
@@ -3106,6 +3201,18 @@ bdk serve --dir . --dev
|
|
|
3106
3201
|
|
|
3107
3202
|
Connect authorizes the process that is running now.
|
|
3108
3203
|
|
|
3204
|
+
A turn waits for Connect only when a person can click it:
|
|
3205
|
+
|
|
3206
|
+
- A playground or HTTP chat turn.
|
|
3207
|
+
- A Slack message, when the channel shows Connect. `slackChannel({ toolApprovals: true })` shows
|
|
3208
|
+
Connect, and so does `buildToolApprovalEvents` in `events`.
|
|
3209
|
+
|
|
3210
|
+
The wait stops after 10 minutes, or when the turn is interrupted. Other
|
|
3211
|
+
turns do not wait. These are schedules, reminders, webhooks, evals, and
|
|
3212
|
+
Slack channels without Connect. A required connection fails the call with
|
|
3213
|
+
`Reconnect <connection>`. An `optional` connection is skipped, also in the
|
|
3214
|
+
playground. Authorize those connections ahead of time with `mcp oauth`.
|
|
3215
|
+
|
|
3109
3216
|
## Keep privileged tools behind a wrapper
|
|
3110
3217
|
|
|
3111
3218
|
Put a connection under `bot/host-connections/` when the model should
|
|
@@ -3369,21 +3476,14 @@ peer connections, and secrets, then verify a hosted turn. The
|
|
|
3369
3476
|
|
|
3370
3477
|
Source: /docs/guides/opentelemetry.md
|
|
3371
3478
|
|
|
3372
|
-
#
|
|
3373
|
-
|
|
3374
|
-
OpenTelemetry connects an agent turn to the observability system your
|
|
3375
|
-
team already uses. Once you configure an OTLP collector, each request,
|
|
3376
|
-
model turn, tool call, and subagent appears alongside token, tool, and
|
|
3377
|
-
cost metrics from the serve process.
|
|
3378
|
-
|
|
3379
|
-
Export is opt-in. Nothing leaves the process until you configure a
|
|
3380
|
-
destination.
|
|
3479
|
+
# OpenTelemetry
|
|
3381
3480
|
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3481
|
+
BDK exports traces, metrics, and logs to an OTLP collector. You
|
|
3482
|
+
configure that with standard `OTEL_*` environment variables. There is
|
|
3483
|
+
no `defineOtel` or `register()` hook. `ctx.host.otel` is deprecated.
|
|
3484
|
+
It still runs for this release and logs one warning per process. Set
|
|
3485
|
+
`OTEL_*` variables and record with `metrics.getMeter` and
|
|
3486
|
+
`trace.getTracer` from `@opentelemetry/api`.
|
|
3387
3487
|
|
|
3388
3488
|
```bash
|
|
3389
3489
|
export OTEL_EXPORTER_OTLP_ENDPOINT=https://otel.example.com
|
|
@@ -3393,212 +3493,535 @@ export OTEL_SERVICE_NAME=incident-agent
|
|
|
3393
3493
|
bdk serve --dir . --dev
|
|
3394
3494
|
```
|
|
3395
3495
|
|
|
3396
|
-
The default protocol is OTLP/HTTP protobuf.
|
|
3397
|
-
`
|
|
3398
|
-
|
|
3496
|
+
The default protocol is OTLP/HTTP protobuf. Set
|
|
3497
|
+
`OTEL_EXPORTER_OTLP_PROTOCOL=http/json` when the collector only accepts
|
|
3498
|
+
JSON. `grpc` is not supported. BDK logs a warning and uses
|
|
3499
|
+
`http/protobuf`.
|
|
3500
|
+
|
|
3501
|
+
Metrics use delta temporality by default. BDK logs that default when
|
|
3502
|
+
export starts. For Grafana Cloud or Prometheus, set
|
|
3503
|
+
`OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE` to `cumulative`.
|
|
3504
|
+
Grafana Cloud rejects delta metrics.
|
|
3505
|
+
|
|
3506
|
+
BDK installs trace, metric, and log providers before it imports
|
|
3507
|
+
`bot/agent.ts`. A meter, tracer, or logger created at module scope
|
|
3508
|
+
binds to those providers. Exporters attach when the process has the
|
|
3509
|
+
`OTEL_*` variables. On a hosted agent that is the first request, after
|
|
3510
|
+
secrets are in the environment.
|
|
3511
|
+
|
|
3512
|
+
With no OTLP endpoint, BDK adds no exporters. Outbound `fetch` does
|
|
3513
|
+
not gain a `traceparent` header. The session collector stays disabled.
|
|
3514
|
+
|
|
3515
|
+
## Variables
|
|
3516
|
+
|
|
3517
|
+
| Variable | Effect |
|
|
3518
|
+
| --- | --- |
|
|
3519
|
+
| `OTEL_EXPORTER_OTLP_ENDPOINT` | Base URL. BDK appends `/v1/traces`, `/v1/metrics`, and `/v1/logs`. |
|
|
3520
|
+
| `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` | Traces URL, used as written. It wins over the base URL. |
|
|
3521
|
+
| `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT` | Metrics URL, used as written. It wins over the base URL. |
|
|
3522
|
+
| `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT` | Logs URL, used as written. It wins over the base URL. |
|
|
3523
|
+
| `OTEL_EXPORTER_OTLP_HEADERS` | Headers on every export. Values are URL-encoded. Read again on each export. |
|
|
3524
|
+
| `OTEL_EXPORTER_OTLP_PROTOCOL` | `http/protobuf` (default) or `http/json`. gRPC is not supported. |
|
|
3525
|
+
| `OTEL_SERVICE_NAME` | `service.name`. Default is the agent name, then `unknown_service:node`. |
|
|
3526
|
+
| `OTEL_RESOURCE_ATTRIBUTES` | Resource attributes, including `service.namespace`, `service.version`, and `deployment.environment.name`. |
|
|
3527
|
+
| `OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE` | `delta` (default), `cumulative`, or `lowmemory`. Use `cumulative` for Grafana Cloud. |
|
|
3528
|
+
| `OTEL_LOGS_EXPORTER` | `otlp` turns logs on. Unset, `none`, and `console` leave OTLP logs off. |
|
|
3529
|
+
| `OTEL_SDK_DISABLED` | `true` turns export off. |
|
|
3530
|
+
| `OTEL_TRACES_EXPORTER` | `none` turns traces off. |
|
|
3531
|
+
| `OTEL_METRICS_EXPORTER` | `none` turns metrics off. |
|
|
3532
|
+
| `OTEL_LOG_USER_PROMPTS` | `1` puts prompt text on log records. |
|
|
3533
|
+
| `OTEL_LOG_TOOL_CONTENT` | `1` puts tool payloads on log records. |
|
|
3534
|
+
|
|
3535
|
+
## Hosted agents
|
|
3536
|
+
|
|
3537
|
+
Set the endpoint, headers, and service name as secrets. Add the
|
|
3538
|
+
collector host to `hosting.egressDomains`. The host is a hostname
|
|
3539
|
+
with no scheme and no path.
|
|
3399
3540
|
|
|
3400
3541
|
```ts
|
|
3401
|
-
|
|
3542
|
+
export default defineAgent({
|
|
3543
|
+
hosting: {
|
|
3544
|
+
egressDomains: ["otlp-gateway-prod-us-east-0.grafana.net"],
|
|
3545
|
+
secretNames: [
|
|
3546
|
+
"OTEL_EXPORTER_OTLP_ENDPOINT",
|
|
3547
|
+
"OTEL_EXPORTER_OTLP_HEADERS",
|
|
3548
|
+
"OTEL_SERVICE_NAME",
|
|
3549
|
+
],
|
|
3550
|
+
},
|
|
3551
|
+
});
|
|
3552
|
+
```
|
|
3553
|
+
|
|
3554
|
+
Secrets arrive with the first request that has an endpoint. That
|
|
3555
|
+
request's export uses those headers and `service.name`. A later
|
|
3556
|
+
`bdk secrets set` updates headers on the next export, including a
|
|
3557
|
+
rotated key. BDK also replaces the exporter when the URL, protocol,
|
|
3558
|
+
or signal list changes. `service.name` is fixed on the first export
|
|
3559
|
+
that attaches. Redeploy to change the service name.
|
|
3560
|
+
|
|
3561
|
+
## What you can record
|
|
3562
|
+
|
|
3563
|
+
Create the tracer, meter, and logger at module scope.
|
|
3564
|
+
|
|
3565
|
+
```ts
|
|
3566
|
+
import { metrics, trace } from "@opentelemetry/api";
|
|
3567
|
+
import { logs } from "@opentelemetry/api-logs";
|
|
3402
3568
|
|
|
3569
|
+
const tracer = trace.getTracer("incident-agent");
|
|
3570
|
+
const lookups = metrics.getMeter("incident-agent").createCounter("incident.lookups");
|
|
3571
|
+
const logger = logs.getLogger("incident-agent");
|
|
3572
|
+
```
|
|
3573
|
+
|
|
3574
|
+
Record during a request, after secrets have loaded. A span or a log
|
|
3575
|
+
record that ends before the exporters attach is still exported. BDK
|
|
3576
|
+
holds up to 2048 spans and 2048 log records until the exporters
|
|
3577
|
+
attach, then sends them. BDK drops each record past that limit. A
|
|
3578
|
+
metric recorded before the first collect is included in that collect.
|
|
3579
|
+
|
|
3580
|
+
BDK also records HTTP spans, token counts, and tool calls on the
|
|
3581
|
+
session. Those spans carry `cursor.conversation.id`. A span you start
|
|
3582
|
+
with `trace.getTracer` during a turn or a tool call gets the same
|
|
3583
|
+
attribute from the active context. A value you set on the span stays.
|
|
3584
|
+
BDK does not overwrite it. The id stays in this process. It is not
|
|
3585
|
+
propagated.
|
|
3586
|
+
|
|
3587
|
+
A metric does not get `cursor.conversation.id`. Read the id and set
|
|
3588
|
+
the attribute yourself.
|
|
3589
|
+
|
|
3590
|
+
```ts
|
|
3591
|
+
import { metrics } from "@opentelemetry/api";
|
|
3592
|
+
import { currentConversationId } from "@cursor/bdk/otel";
|
|
3593
|
+
|
|
3594
|
+
const lookups = metrics.getMeter("incident-agent").createCounter("incident.lookups");
|
|
3595
|
+
|
|
3596
|
+
lookups.add(1, { "cursor.conversation.id": currentConversationId() });
|
|
3597
|
+
```
|
|
3598
|
+
|
|
3599
|
+
Prompt text and tool payloads stay off log records unless logs are on
|
|
3600
|
+
(`OTEL_LOGS_EXPORTER=otlp`) and you set `OTEL_LOG_USER_PROMPTS` or
|
|
3601
|
+
`OTEL_LOG_TOOL_CONTENT`.
|
|
3602
|
+
|
|
3603
|
+
## Limits
|
|
3604
|
+
|
|
3605
|
+
These are not supported yet.
|
|
3606
|
+
|
|
3607
|
+
- Custom span processors, samplers, and views.
|
|
3608
|
+
- Bringing your own OpenTelemetry SDK.
|
|
3609
|
+
- Library auto-instrumentation.
|
|
3610
|
+
- A `register()` hook. There is no ticket for it yet.
|
|
3611
|
+
- `OTEL_TRACES_SAMPLER` and `OTEL_METRIC_EXPORT_INTERVAL` that arrive
|
|
3612
|
+
only with hosted secrets. BDK reads them when it builds the provider,
|
|
3613
|
+
which is before that secret load. Set them on the process, then
|
|
3614
|
+
restart. BDK logs a warning when a later value differs.
|
|
3615
|
+
|
|
3616
|
+
Do not import your own SDK providers next to BDK's. BDK logs a warning
|
|
3617
|
+
when a module replaces a provider BDK registered. The global API then
|
|
3618
|
+
uses that module's provider. BDK shuts down a provider it created
|
|
3619
|
+
only when that provider is not the one it registered.
|
|
3620
|
+
|
|
3621
|
+
## Migrating from serve({ otel })
|
|
3622
|
+
|
|
3623
|
+
`serve({ otel })` is removed. Delete the option. Set the same
|
|
3624
|
+
values with `OTEL_*` variables. Delete `bot/otel.ts`,
|
|
3625
|
+
`agent/otel.ts`, and `bot/instrumentation.ts`. Do not call
|
|
3626
|
+
`defineOtel`.
|
|
3627
|
+
|
|
3628
|
+
BDK sends each signal to one URL. A second exporter for the same
|
|
3629
|
+
signal has no variable.
|
|
3630
|
+
|
|
3631
|
+
| Old option | Set this instead |
|
|
3632
|
+
| --- | --- |
|
|
3633
|
+
| `serviceName` | `OTEL_SERVICE_NAME` |
|
|
3634
|
+
| `serviceVersion` | `service.version` in `OTEL_RESOURCE_ATTRIBUTES` |
|
|
3635
|
+
| `resourceAttributes` | `OTEL_RESOURCE_ATTRIBUTES`. Separate pairs with commas. URL-encode each value. |
|
|
3636
|
+
| `exporters[].url` | `OTEL_EXPORTER_OTLP_ENDPOINT`. BDK appends `/v1/traces`, `/v1/metrics`, and `/v1/logs`. |
|
|
3637
|
+
| `exporters[].url` with `signals` | `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT`, `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT`, or `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT`. BDK uses that URL as written. |
|
|
3638
|
+
| `exporters[].headers` | `OTEL_EXPORTER_OTLP_HEADERS`. Separate pairs with commas. URL-encode each value. |
|
|
3639
|
+
| `exporters[].protocol` | `OTEL_EXPORTER_OTLP_PROTOCOL`. Use `http/protobuf` or `http/json`. For one signal, use `OTEL_EXPORTER_OTLP_TRACES_PROTOCOL`, `OTEL_EXPORTER_OTLP_METRICS_PROTOCOL`, or `OTEL_EXPORTER_OTLP_LOGS_PROTOCOL`. |
|
|
3640
|
+
| `exporters[].signals` | Set the signal URL above. Set `OTEL_TRACES_EXPORTER`, `OTEL_METRICS_EXPORTER`, or `OTEL_LOGS_EXPORTER` to `none` to stop that signal. |
|
|
3641
|
+
| `traces: false` | `OTEL_TRACES_EXPORTER=none` |
|
|
3642
|
+
| `traces: true` | Leave `OTEL_TRACES_EXPORTER` unset. Traces start when an endpoint is set. |
|
|
3643
|
+
| `traces.sampleRatio` | `OTEL_TRACES_SAMPLER=parentbased_traceidratio` and `OTEL_TRACES_SAMPLER_ARG` set to the ratio. Set both before the process starts. |
|
|
3644
|
+
| `metrics: false` | `OTEL_METRICS_EXPORTER=none` |
|
|
3645
|
+
| `metrics: true` | Leave `OTEL_METRICS_EXPORTER` unset. Metrics start when a metrics URL is set. |
|
|
3646
|
+
| `metrics.exportIntervalMillis` | `OTEL_METRIC_EXPORT_INTERVAL`, in milliseconds. Set it before the process starts. |
|
|
3647
|
+
| `logs: false` | Leave `OTEL_LOGS_EXPORTER` unset, or set it to `none`. |
|
|
3648
|
+
| `logs: true` | `OTEL_LOGS_EXPORTER=otlp` |
|
|
3649
|
+
| `logs.userPrompts` | `OTEL_LOGS_EXPORTER=otlp` and `OTEL_LOG_USER_PROMPTS=1` |
|
|
3650
|
+
| `logs.toolContent` | `OTEL_LOGS_EXPORTER=otlp` and `OTEL_LOG_TOOL_CONTENT=1` |
|
|
3651
|
+
| `otel: false` | Set no endpoint, or set `OTEL_SDK_DISABLED=true`. |
|
|
3652
|
+
|
|
3653
|
+
Before:
|
|
3654
|
+
|
|
3655
|
+
```ts
|
|
3403
3656
|
await serve(".", {
|
|
3404
3657
|
otel: {
|
|
3405
3658
|
serviceName: "incident-agent",
|
|
3406
3659
|
exporters: [
|
|
3407
3660
|
{
|
|
3408
3661
|
url: "https://otel.example.com",
|
|
3409
|
-
headers: {
|
|
3410
|
-
Authorization: `Bearer ${process.env.OTEL_TOKEN ?? ""}`,
|
|
3411
|
-
},
|
|
3662
|
+
headers: { Authorization: `Bearer ${process.env.OTEL_TOKEN ?? ""}` },
|
|
3412
3663
|
},
|
|
3413
3664
|
],
|
|
3414
3665
|
},
|
|
3415
3666
|
});
|
|
3416
3667
|
```
|
|
3417
3668
|
|
|
3418
|
-
|
|
3419
|
-
`bdk serve`. Use `serve({ otel })` when your TypeScript
|
|
3420
|
-
application starts the server itself. When that application
|
|
3421
|
-
already uses OpenTelemetry, BDK sends its traces, metrics, and
|
|
3422
|
-
logs to the collector configured here.
|
|
3669
|
+
After:
|
|
3423
3670
|
|
|
3424
|
-
|
|
3671
|
+
```bash
|
|
3672
|
+
export OTEL_SERVICE_NAME=incident-agent
|
|
3673
|
+
export OTEL_EXPORTER_OTLP_ENDPOINT=https://otel.example.com
|
|
3674
|
+
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer%20$OTEL_TOKEN"
|
|
3675
|
+
bdk serve --dir . --dev
|
|
3676
|
+
```
|
|
3425
3677
|
|
|
3426
|
-
|
|
3427
|
-
collector host to `hosting.egressDomains`.
|
|
3428
|
-
|
|
3429
|
-
|
|
3678
|
+
On a hosted agent, put the same names in `hosting.secretNames`. Add
|
|
3679
|
+
the collector host to `hosting.egressDomains`. Then run:
|
|
3680
|
+
|
|
3681
|
+
```bash
|
|
3682
|
+
bdk secrets set my-agent OTEL_SERVICE_NAME OTEL_EXPORTER_OTLP_ENDPOINT OTEL_EXPORTER_OTLP_HEADERS
|
|
3683
|
+
```
|
|
3684
|
+
|
|
3685
|
+
---
|
|
3686
|
+
|
|
3687
|
+
Source: /docs/guides/pagerduty.md
|
|
3688
|
+
|
|
3689
|
+
# PagerDuty agents
|
|
3690
|
+
|
|
3691
|
+
A PagerDuty agent wakes when an incident triggers, investigates it, and
|
|
3692
|
+
writes what it found back to the incident. `pagerdutyChannel()` receives
|
|
3693
|
+
PagerDuty's v3 webhooks, verifies them, and keeps every later event for
|
|
3694
|
+
the same incident in one session, so the agent sees an acknowledgement,
|
|
3695
|
+
a note, or a responder's reply in the context of the investigation it
|
|
3696
|
+
already started. Every setting has a default read from a well-known secret, so
|
|
3697
|
+
the channel needs no configuration beyond its hooks; see
|
|
3698
|
+
[Connect](#connect) for the variables.
|
|
3699
|
+
|
|
3700
|
+
## Investigate a new incident
|
|
3701
|
+
|
|
3702
|
+
When an incident triggers, the agent starts a turn with the incident's
|
|
3703
|
+
title, service, urgency, and link. It reads whatever the investigation
|
|
3704
|
+
needs, and with `deliverReplies: true` its reply is posted as a note on
|
|
3705
|
+
the incident, where the person on call already looks.
|
|
3706
|
+
|
|
3707
|
+
```ts
|
|
3708
|
+
// bot/channels/pagerduty.ts
|
|
3709
|
+
import { defaultPagerDutyAuth, pagerdutyChannel } from "@cursor/bdk/channels/pagerduty";
|
|
3710
|
+
|
|
3711
|
+
export default pagerdutyChannel({
|
|
3712
|
+
deliverReplies: true,
|
|
3713
|
+
onIncident: (ctx, event) => {
|
|
3714
|
+
if (event.eventType !== "incident.triggered") {
|
|
3715
|
+
return null;
|
|
3716
|
+
}
|
|
3717
|
+
return {
|
|
3718
|
+
// `auth` starts a model turn running as the event's PagerDuty actor.
|
|
3719
|
+
auth: defaultPagerDutyAuth(ctx),
|
|
3720
|
+
message: `Investigate PagerDuty incident #${event.incident.number}: ${event.incident.title}`,
|
|
3721
|
+
context: [`Service: ${event.incident.service?.summary ?? "unknown"}`],
|
|
3722
|
+
};
|
|
3723
|
+
},
|
|
3724
|
+
});
|
|
3725
|
+
```
|
|
3726
|
+
|
|
3727
|
+
Reply notes are off unless you set `deliverReplies: true`, so the channel
|
|
3728
|
+
writes nothing to PagerDuty on its own. An agent that writes to PagerDuty
|
|
3729
|
+
through its own path, such as a service that audits each write, leaves it
|
|
3730
|
+
off and posts only what it chooses, from `events` or `ctx.pagerduty`.
|
|
3731
|
+
|
|
3732
|
+
With `deliverReplies: true`, the channel posts each completed reply as a
|
|
3733
|
+
note on the session's incident, and a short note if a turn fails, using
|
|
3734
|
+
the `PAGERDUTY_TOKEN` secret. The note goes to the incident in the
|
|
3735
|
+
verified event's state, so the model never chooses which incident it
|
|
3736
|
+
writes to. Eval runs and agents without a token post nothing. Nothing is
|
|
3737
|
+
posted until the channel knows the agent's own PagerDuty user (see
|
|
3738
|
+
[Ignore your own actions](#ignore-your-own-actions)), because each note
|
|
3739
|
+
comes back as a webhook event that only the echo skip keeps from starting
|
|
3740
|
+
another turn. Handlers you write in `events` replace the built-in ones.
|
|
3741
|
+
|
|
3742
|
+
Hooks also get `ctx.pagerduty`, a REST client with the channel's
|
|
3743
|
+
credentials, for reads and writes of their own:
|
|
3744
|
+
|
|
3745
|
+
```ts
|
|
3746
|
+
onIncident: async (ctx, event) => {
|
|
3747
|
+
const incident = await ctx.pagerduty.getIncident(event.incident.id);
|
|
3748
|
+
// …
|
|
3749
|
+
},
|
|
3750
|
+
```
|
|
3751
|
+
|
|
3752
|
+
Hosted, the agent also declares PagerDuty's API host and the token:
|
|
3430
3753
|
|
|
3431
3754
|
```ts
|
|
3432
3755
|
// bot/agent.ts
|
|
3433
3756
|
import { defineAgent } from "@cursor/bdk";
|
|
3434
3757
|
|
|
3435
3758
|
export default defineAgent({
|
|
3759
|
+
architecture: "v2",
|
|
3436
3760
|
hosting: {
|
|
3437
|
-
egressDomains: ["
|
|
3438
|
-
secretNames: ["
|
|
3761
|
+
egressDomains: ["api.pagerduty.com"],
|
|
3762
|
+
secretNames: ["PAGERDUTY_TOKEN"],
|
|
3439
3763
|
},
|
|
3440
3764
|
});
|
|
3441
3765
|
```
|
|
3442
3766
|
|
|
3443
|
-
|
|
3444
|
-
|
|
3767
|
+
## Follow the incident in one session
|
|
3768
|
+
|
|
3769
|
+
People act on an incident while the agent investigates: someone
|
|
3770
|
+
acknowledges it, adds a note, pulls in a responder, or resolves it.
|
|
3771
|
+
Return a dispatch for those events too, and each one arrives in the
|
|
3772
|
+
session that is already working on the incident, with the earlier
|
|
3773
|
+
findings in context.
|
|
3774
|
+
|
|
3775
|
+
```ts
|
|
3776
|
+
onIncident: (ctx, event) => {
|
|
3777
|
+
const followUps = ["incident.acknowledged", "incident.reassigned", "incident.resolved"];
|
|
3778
|
+
if (event.eventType !== "incident.triggered" && !followUps.includes(event.eventType)) {
|
|
3779
|
+
return null;
|
|
3780
|
+
}
|
|
3781
|
+
return {
|
|
3782
|
+
auth: defaultPagerDutyAuth(ctx),
|
|
3783
|
+
message: `${event.eventType} by ${ctx.agent?.summary ?? "PagerDuty"}`,
|
|
3784
|
+
};
|
|
3785
|
+
},
|
|
3786
|
+
onNote: (ctx, note) => {
|
|
3787
|
+
return {
|
|
3788
|
+
auth: defaultPagerDutyAuth(ctx),
|
|
3789
|
+
message: `Note on the incident: ${note.content}`,
|
|
3790
|
+
};
|
|
3791
|
+
},
|
|
3445
3792
|
```
|
|
3446
3793
|
|
|
3447
|
-
`
|
|
3448
|
-
|
|
3449
|
-
`%20` (`Authorization=Basic%20...`).
|
|
3794
|
+
Add these to the same `pagerdutyChannel()` declaration as the
|
|
3795
|
+
investigation handler.
|
|
3450
3796
|
|
|
3451
|
-
|
|
3452
|
-
You do not redeploy to rotate a token. The URL, service name,
|
|
3453
|
-
resource attributes, signals, sample ratio, and metric export
|
|
3454
|
-
interval stay as they were on the first export. Redeploy to change
|
|
3455
|
-
one of those. BDK logs a warning when one of them changes on a
|
|
3456
|
-
running agent.
|
|
3797
|
+
## Ignore your own actions
|
|
3457
3798
|
|
|
3458
|
-
|
|
3459
|
-
|
|
3799
|
+
PagerDuty sends the agent's own changes back as webhook events: the
|
|
3800
|
+
note it posted, or an acknowledgement or resolve made through its
|
|
3801
|
+
PagerDuty user. The channel acknowledges those events without running a
|
|
3802
|
+
hook or starting a turn. The same action by a person is still delivered.
|
|
3460
3803
|
|
|
3461
|
-
|
|
3462
|
-
including spans from channel `onStart`. If the OpenTelemetry config
|
|
3463
|
-
fails, BDK logs the error and the request still completes.
|
|
3804
|
+
The channel finds the agent's user in this order, on each delivery:
|
|
3464
3805
|
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
`
|
|
3806
|
+
1. The `selfUserIds` option, when you pass one. Nothing below is used.
|
|
3807
|
+
2. The `PAGERDUTY_USER_ID` secret: one PagerDuty user id.
|
|
3808
|
+
3. The user `PAGERDUTY_TOKEN` acts as, which PagerDuty reports at
|
|
3809
|
+
`GET /users/me`.
|
|
3469
3810
|
|
|
3470
|
-
|
|
3811
|
+
When none of these names a user, echo skip is off. `bdk deploy` warns
|
|
3812
|
+
while neither `PAGERDUTY_USER_ID` nor `PAGERDUTY_TOKEN` is set, and the
|
|
3813
|
+
agent logs a warning when its token names no single user.
|
|
3471
3814
|
|
|
3472
|
-
|
|
3473
|
-
filter your observability system on either `agent_sdk.session_id` or
|
|
3474
|
-
`cursor.conversation.id`. Every turn in that conversation carries the
|
|
3475
|
-
same value, including follow-ups and tool work.
|
|
3815
|
+
Inference depends on the kind of token:
|
|
3476
3816
|
|
|
3477
|
-
|
|
3817
|
+
| `PAGERDUTY_TOKEN` | Inferred user |
|
|
3818
|
+
| --- | --- |
|
|
3819
|
+
| User token REST API key | The key's own user |
|
|
3820
|
+
| OAuth user token (Classic User OAuth or Scoped OAuth), written as `Bearer <token>` | The user who authorized the app |
|
|
3821
|
+
| General access (account-level) REST API key | The user whose email is exactly `PAGERDUTY_FROM_EMAIL`, if set |
|
|
3822
|
+
| Scoped OAuth app token (client credentials) | The user whose email is exactly `PAGERDUTY_FROM_EMAIL`, if set |
|
|
3823
|
+
|
|
3824
|
+
PagerDuty serves
|
|
3825
|
+
[`GET /users/me`](https://developer.pagerduty.com/api-reference/0b6f8b0c3e8d1-get-the-current-user)
|
|
3826
|
+
only to a user-level API key or a token from an OAuth flow, not to an
|
|
3827
|
+
account-level key. An app token
|
|
3828
|
+
[acts as the app](https://docs.pagerduty.com/developer/private-apps),
|
|
3829
|
+
not as a user. With either, the channel looks up `PAGERDUTY_FROM_EMAIL`,
|
|
3830
|
+
the `From` user the token writes as, through `GET /users?query=` and uses
|
|
3831
|
+
the one user whose email matches exactly. The inferred id is kept in the
|
|
3832
|
+
agent's memory for an hour per token, never in agent storage, and an
|
|
3833
|
+
unresolved answer is retried after five minutes. Hosted, the lookup needs
|
|
3834
|
+
`api.pagerduty.com` (or your `PAGERDUTY_API_BASE_URL` host) in
|
|
3835
|
+
`hosting.egressDomains`, the same entry write-backs need.
|
|
3836
|
+
|
|
3837
|
+
A read-only agent with no token sets the id directly:
|
|
3478
3838
|
|
|
3479
|
-
```
|
|
3480
|
-
|
|
3839
|
+
```bash
|
|
3840
|
+
bdk secrets set incident-responder PAGERDUTY_USER_ID
|
|
3841
|
+
```
|
|
3842
|
+
|
|
3843
|
+
`PAGERDUTY_USER_ID` holds one id because a deployment has one token
|
|
3844
|
+
and so acts as one PagerDuty user. To skip several users, or to keep the
|
|
3845
|
+
id in code, pass `selfUserIds`:
|
|
3481
3846
|
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3847
|
+
```ts
|
|
3848
|
+
export default pagerdutyChannel({
|
|
3849
|
+
selfUserIds: ["PBOT001"],
|
|
3850
|
+
onIncident: (ctx) => ({ auth: defaultPagerDutyAuth(ctx) }),
|
|
3851
|
+
});
|
|
3486
3852
|
```
|
|
3487
3853
|
|
|
3488
|
-
|
|
3489
|
-
|
|
3854
|
+
`selfUserIds: { secretName: "OTHER_NAME" }` reads one id from another
|
|
3855
|
+
secret and never falls back to inference.
|
|
3490
3856
|
|
|
3491
|
-
|
|
3857
|
+
## Events
|
|
3492
3858
|
|
|
3493
|
-
|
|
3494
|
-
`agent_sdk.subagent` span. Its `reasoning.completed` and
|
|
3495
|
-
`message.completed` events sit on that span too, so the subagent span
|
|
3496
|
-
shows where its time went. Time between two tool spans is the model
|
|
3497
|
-
choosing the next step. A subagent that fails or is cancelled ends its
|
|
3498
|
-
span with ERROR status when it stops.
|
|
3859
|
+
Each hook receives one family of v3 events:
|
|
3499
3860
|
|
|
3500
|
-
|
|
3861
|
+
| Hook | Events |
|
|
3862
|
+
| --- | --- |
|
|
3863
|
+
| `onIncident` | `incident.triggered`, `.acknowledged`, `.unacknowledged`, `.escalated`, `.reassigned`, `.delegated`, `.resolved`, `.reopened`, `.priority_updated`, `.incident_type.changed` |
|
|
3864
|
+
| `onNote` | `incident.annotated` |
|
|
3865
|
+
| `onResponder` | `incident.responder.added`, `incident.responder.replied` |
|
|
3866
|
+
| `onEvent` | Everything else, such as status updates and workflow events |
|
|
3501
3867
|
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3868
|
+
Without `onIncident`, a triggered or reopened incident starts a turn and
|
|
3869
|
+
other lifecycle events are acknowledged. Notes, responder events, and
|
|
3870
|
+
the rest are acknowledged until you add their hook. Each hook returns
|
|
3871
|
+
one of three decisions:
|
|
3506
3872
|
|
|
3507
|
-
|
|
|
3873
|
+
| Return | What happens |
|
|
3508
3874
|
| --- | --- |
|
|
3509
|
-
| `
|
|
3510
|
-
| `
|
|
3511
|
-
| `
|
|
3875
|
+
| `{ auth }` | Start or continue a model turn as the event's actor |
|
|
3876
|
+
| `{ task }` | Acknowledge the webhook, then run host code that may also call `send` |
|
|
3877
|
+
| `null` | Skip the event |
|
|
3512
3878
|
|
|
3513
|
-
|
|
3879
|
+
## Incident affinity
|
|
3514
3880
|
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
passwords.
|
|
3881
|
+
Every event for one incident joins one session, keyed on the incident
|
|
3882
|
+
id. Lifecycle events carry the incident, and notes and responder events
|
|
3883
|
+
name it by reference, so all of them reach the same session.
|
|
3519
3884
|
|
|
3520
|
-
|
|
3885
|
+
A re-trigger after a resolve is a new PagerDuty incident, so it starts a
|
|
3886
|
+
new session. `ctx.incidentKey` carries the dedup key of the alert that
|
|
3887
|
+
opened an incident (its `incident_key`, set per alert by a Datadog
|
|
3888
|
+
monitor, a Sentry issue, or a Grafana rule), for an agent that wants to
|
|
3889
|
+
recall what it found the last time the same alert fired.
|
|
3521
3890
|
|
|
3522
|
-
|
|
3523
|
-
built-in telemetry cannot, such as which incident a turn handled or how
|
|
3524
|
-
long approval took. Attributes appear on the active turn and tool
|
|
3525
|
-
spans, while counters and histograms give you metrics to graph and
|
|
3526
|
-
alert on.
|
|
3891
|
+
## Connect
|
|
3527
3892
|
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
|
|
3531
|
-
|
|
3532
|
-
|
|
3893
|
+
Create a v3 webhook subscription in PagerDuty for the services that
|
|
3894
|
+
should wake the agent, and point it at
|
|
3895
|
+
`https://<your-host>/<slug>/v1/channels/pagerduty`. Then set the
|
|
3896
|
+
channel's secrets on the deployment. Locally the same names are
|
|
3897
|
+
environment variables.
|
|
3533
3898
|
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
}
|
|
3899
|
+
| Variable | Used for | Override |
|
|
3900
|
+
| --- | --- | --- |
|
|
3901
|
+
| `PAGERDUTY_WEBHOOK_SECRET` | Verifying `X-PagerDuty-Signature`. Hosted, the platform checks it before any compute starts and answers a bad delivery with `401` | `webhookSecret: { secretName }` |
|
|
3902
|
+
| `PAGERDUTY_USER_ID` | Skipping the agent's own actions: its PagerDuty user id. Optional when `PAGERDUTY_TOKEN` names a user | `selfUserIds: [ids]` or `{ secretName }` |
|
|
3903
|
+
| `PAGERDUTY_TOKEN` | Reply notes (with `deliverReplies: true`), `ctx.pagerduty`, and inferring the agent's user: a REST API key, or an OAuth token as `Bearer <token>` | `token: { secretName }` |
|
|
3904
|
+
| `PAGERDUTY_FROM_EMAIL` | The `From` user PagerDuty requires for writes made with an account-level key or app token, and the user inferred for those tokens | `from: { secretName }` |
|
|
3905
|
+
| `PAGERDUTY_API_BASE_URL` | The REST host, such as `https://api.eu.pagerduty.com`. Defaults to `https://api.pagerduty.com` | `apiBaseUrl` |
|
|
3537
3906
|
|
|
3538
|
-
|
|
3539
|
-
|
|
3540
|
-
|
|
3907
|
+
Set `token`, `from`, and `apiBaseUrl` on `pagerdutyChannel()`; they cover
|
|
3908
|
+
reply notes, `ctx.pagerduty`, and inference. `createPagerDutyClient()`
|
|
3909
|
+
takes the same options for code outside the channel.
|
|
3910
|
+
|
|
3911
|
+
```bash
|
|
3912
|
+
bdk deploy --dir . --slug incident-responder
|
|
3913
|
+
bdk secrets set incident-responder PAGERDUTY_WEBHOOK_SECRET PAGERDUTY_TOKEN
|
|
3914
|
+
bdk secrets list incident-responder
|
|
3541
3915
|
```
|
|
3542
3916
|
|
|
3543
|
-
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
first-party telemetry without extra plumbing.
|
|
3917
|
+
`bdk deploy` warns until `PAGERDUTY_WEBHOOK_SECRET` is set, and until
|
|
3918
|
+
either `PAGERDUTY_USER_ID` or `PAGERDUTY_TOKEN` is. The next delivery
|
|
3919
|
+
uses a new value without another deploy.
|
|
3547
3920
|
|
|
3548
|
-
|
|
3549
|
-
and join keys are reserved, and this surface does not create custom
|
|
3550
|
-
spans.
|
|
3921
|
+
### Several subscriptions
|
|
3551
3922
|
|
|
3552
|
-
|
|
3923
|
+
PagerDuty gives each webhook subscription its own signing secret, so an
|
|
3924
|
+
agent fed by several subscriptions (one per service, say) needs all of
|
|
3925
|
+
them. Put them in `PAGERDUTY_WEBHOOK_SECRET`, one per line:
|
|
3553
3926
|
|
|
3554
|
-
|
|
3555
|
-
|
|
3927
|
+
```text
|
|
3928
|
+
<signing secret of subscription 1>
|
|
3929
|
+
<signing secret of subscription 2>
|
|
3930
|
+
```
|
|
3556
3931
|
|
|
3557
|
-
|
|
3558
|
-
|
|
3559
|
-
|
|
3560
|
-
|
|
3561
|
-
|
|
3932
|
+
A delivery is admitted when any `v1=` signature in its
|
|
3933
|
+
`X-PagerDuty-Signature` header matches any line. Each line is trimmed,
|
|
3934
|
+
blank lines are ignored, and a value without a line break is one secret,
|
|
3935
|
+
used as-is. The value holds at most 32 secrets. Past that, every delivery
|
|
3936
|
+
is rejected rather than checked against only some of them.
|
|
3562
3937
|
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
`traces: false`, `metrics: false`, or `logs: true` under
|
|
3566
|
-
`serve({ otel })` when you need a different signal mix.
|
|
3938
|
+
Keep the list in a file, since `bdk secrets list` never shows values,
|
|
3939
|
+
and set it from stdin, which keeps the line breaks:
|
|
3567
3940
|
|
|
3568
|
-
|
|
3941
|
+
```bash
|
|
3942
|
+
bdk secrets set incident-responder PAGERDUTY_WEBHOOK_SECRET < pagerduty-webhook-secrets.txt
|
|
3943
|
+
```
|
|
3944
|
+
|
|
3945
|
+
Rotate by adding before removing. Add the new secret as a line before
|
|
3946
|
+
PagerDuty starts signing with it, for example before creating the
|
|
3947
|
+
replacement subscription. Remove the old line only once nothing signs
|
|
3948
|
+
with the old secret, for example after deleting the subscription it
|
|
3949
|
+
replaced. While both are live, a delivery signed with either secret
|
|
3950
|
+
verifies, including one whose header carries both signatures. Removing
|
|
3951
|
+
the old line first rejects those deliveries until the new one is added.
|
|
3952
|
+
|
|
3953
|
+
The same format works for every `hmacSignatureAuth()` secret, including
|
|
3954
|
+
`GITHUB_WEBHOOK_SECRET` and `BITBUCKET_WEBHOOK_SECRET`. It needs
|
|
3955
|
+
`@cursor/bdk` 0.2.25 or later. Earlier versions check the signature again
|
|
3956
|
+
in the agent with the whole value as one secret, so they reject every
|
|
3957
|
+
delivery once the value has a second line.
|
|
3569
3958
|
|
|
3570
|
-
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
|
|
3959
|
+
Only signature checks read the value as a list. Everywhere else it is
|
|
3960
|
+
used whole: a `sharedSecretAuth()` header compares the entire value, and
|
|
3961
|
+
a `${NAME}` template in an MCP connection's `headers` would put the line
|
|
3962
|
+
breaks into the header. Keep a list secret for webhook signing only.
|
|
3963
|
+
|
|
3964
|
+
Until `PAGERDUTY_WEBHOOK_SECRET` is set, the route accepts only local
|
|
3965
|
+
traffic: loopback deliveries under `bdk dev`, nothing in production.
|
|
3966
|
+
|
|
3967
|
+
## Test locally
|
|
3575
3968
|
|
|
3576
|
-
|
|
3969
|
+
`bdk pagerduty replay` posts synthesized v3 deliveries for one incident
|
|
3970
|
+
to the running agent, in order. With `PAGERDUTY_WEBHOOK_SECRET` unset,
|
|
3971
|
+
`bdk dev` admits them unsigned from loopback; with it set, replay signs
|
|
3972
|
+
them the way PagerDuty does:
|
|
3577
3973
|
|
|
3578
3974
|
```bash
|
|
3579
|
-
|
|
3580
|
-
|
|
3581
|
-
|
|
3975
|
+
bdk dev &
|
|
3976
|
+
bdk pagerduty replay --events triggered,acknowledged,annotated,resolved \
|
|
3977
|
+
--comment "Rolled back the 09:30 deploy."
|
|
3582
3978
|
```
|
|
3583
3979
|
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
|
|
3587
|
-
|
|
3980
|
+
The trigger comes from PagerDuty itself, and the later events come from a
|
|
3981
|
+
person, so each one joins the session the trigger started. Pass an
|
|
3982
|
+
incident id to start another session, `--dry-run` to print the bodies,
|
|
3983
|
+
or `--out fixtures/pagerduty` to save them as fixtures for
|
|
3984
|
+
[evals](/docs/evals.md). `bdk pagerduty events` lists the channels and the
|
|
3985
|
+
events each accepts.
|
|
3588
3986
|
|
|
3589
|
-
|
|
3590
|
-
|
|
3987
|
+
To post a real delivery saved from the webhook's delivery log, sign it
|
|
3988
|
+
with the secret:
|
|
3989
|
+
|
|
3990
|
+
```bash
|
|
3991
|
+
export PAGERDUTY_WEBHOOK_SECRET=local-test-secret
|
|
3992
|
+
bdk dev &
|
|
3993
|
+
|
|
3994
|
+
body=fixtures/pagerduty/incident-triggered.json
|
|
3995
|
+
signature=$(openssl dgst -sha256 -hmac "$PAGERDUTY_WEBHOOK_SECRET" -hex < "$body" | awk '{print $NF}')
|
|
3996
|
+
curl -X POST http://127.0.0.1:3000/v1/channels/pagerduty \
|
|
3997
|
+
-H 'content-type: application/json' \
|
|
3998
|
+
-H "x-pagerduty-signature: v1=$signature" \
|
|
3999
|
+
--data-binary @"$body"
|
|
4000
|
+
```
|
|
4001
|
+
|
|
4002
|
+
Set `event.agent.id` in a saved body to the agent's own user id to see
|
|
4003
|
+
the delivery skipped as an echo.
|
|
4004
|
+
|
|
4005
|
+
## Practices
|
|
4006
|
+
|
|
4007
|
+
- Write back from host code with the incident in channel state or
|
|
4008
|
+
`ctx`, never from an incident id the model produced.
|
|
4009
|
+
|
|
4010
|
+
- Make sure the agent knows its own user before it acts on incidents, so
|
|
4011
|
+
its own notes and resolves do not wake it again: a user-level token, a
|
|
4012
|
+
`PAGERDUTY_FROM_EMAIL` with an account-level key, or `PAGERDUTY_USER_ID`.
|
|
4013
|
+
|
|
4014
|
+
- Scope the webhook subscription to the services the agent responds to;
|
|
4015
|
+
every delivery it sends reaches the channel.
|
|
3591
4016
|
|
|
3592
4017
|
## Related
|
|
3593
4018
|
|
|
3594
|
-
- [
|
|
3595
|
-
|
|
3596
|
-
- [
|
|
3597
|
-
|
|
3598
|
-
- [
|
|
3599
|
-
|
|
3600
|
-
- [Cursor enterprise OpenTelemetry Export](https://cursor.com/docs/enterprise/opentelemetry-export):
|
|
3601
|
-
send organization-wide Cursor telemetry to the same collector
|
|
4019
|
+
- [Channels reference](/docs/reference/channels.md): channel hooks,
|
|
4020
|
+
dispatch decisions, and session behavior
|
|
4021
|
+
- [Webhooks and custom channels](/docs/guides/webhooks.md): direct webhook auth
|
|
4022
|
+
and reply delivery
|
|
4023
|
+
- [Evals](/docs/evals.md): turn saved PagerDuty payloads into regression
|
|
4024
|
+
fixtures
|
|
3602
4025
|
|
|
3603
4026
|
---
|
|
3604
4027
|
|
|
@@ -3700,6 +4123,47 @@ export default slackChannel({
|
|
|
3700
4123
|
});
|
|
3701
4124
|
```
|
|
3702
4125
|
|
|
4126
|
+
### Show steps as cards or as a checklist
|
|
4127
|
+
|
|
4128
|
+
The agent calls `post-card` to show one step of its work, such as
|
|
4129
|
+
"Scan the repo". Each card has an `id`, a `title`, a `status`, and
|
|
4130
|
+
optional `details`. When the agent calls `post-card` again with the same
|
|
4131
|
+
`id`, Slack updates that card. The agent uses this to move a step from
|
|
4132
|
+
`in_progress` to `complete`.
|
|
4133
|
+
|
|
4134
|
+
`cards` sets how Slack draws these steps:
|
|
4135
|
+
|
|
4136
|
+
| `cards` | What Slack shows | Use it when |
|
|
4137
|
+
| --- | --- | --- |
|
|
4138
|
+
| `{ display: "timeline" }` (default) | Each step is a separate card in the thread. | The turn has one or two short steps. |
|
|
4139
|
+
| `{ display: "plan" }` | All steps from one turn are in one checklist. | The turn has several steps, and readers want to see progress in one place. |
|
|
4140
|
+
|
|
4141
|
+
This bot shows its steps as one checklist with the title "Release check":
|
|
4142
|
+
|
|
4143
|
+
```ts
|
|
4144
|
+
export default slackChannel({
|
|
4145
|
+
reply: {
|
|
4146
|
+
mode: "agentic",
|
|
4147
|
+
cards: { display: "plan", title: "Release check" },
|
|
4148
|
+
},
|
|
4149
|
+
});
|
|
4150
|
+
```
|
|
4151
|
+
|
|
4152
|
+
Know these rules for a plan:
|
|
4153
|
+
|
|
4154
|
+
- The `title` is optional. It can have at most 256 characters.
|
|
4155
|
+
- You set the `title` in the channel configuration. The agent cannot
|
|
4156
|
+
change the title.
|
|
4157
|
+
- Each turn starts a new checklist with the same title.
|
|
4158
|
+
- The `pending` status shows a step that has not started. Use `pending`
|
|
4159
|
+
only in a plan.
|
|
4160
|
+
- `slackChannel` stops at startup if `cards` is not valid. For example,
|
|
4161
|
+
a `title` with `display: "timeline"` stops startup.
|
|
4162
|
+
|
|
4163
|
+
`display` is Slack's
|
|
4164
|
+
[`task_display_mode`](https://docs.slack.dev/reference/methods/chat.startStream/),
|
|
4165
|
+
and the channel sends `title` as a `plan_update` chunk.
|
|
4166
|
+
|
|
3703
4167
|
## Wake on a channel post
|
|
3704
4168
|
|
|
3705
4169
|
This example watches `#triage-alerts`, so any substantial top-level
|
|
@@ -4891,15 +5355,35 @@ const handle = await serve("./my-agent", {
|
|
|
4891
5355
|
});
|
|
4892
5356
|
console.log(`listening on ${handle.url}`);
|
|
4893
5357
|
// handle.callTool(...), handle.dispatchSchedule("heartbeat"),
|
|
4894
|
-
// handle.createReminder(...), handle.
|
|
5358
|
+
// handle.createReminder(...), handle.agents, await handle.close()
|
|
4895
5359
|
```
|
|
4896
5360
|
|
|
5361
|
+
`handle.agents` lists each mount as `slug`, `url`, and `info`. `handle.project` is the first agent's project. It is deprecated.
|
|
5362
|
+
|
|
4897
5363
|
Host settings match the documented [CLI](/docs/reference/cli.md) `serve` flags.
|
|
4898
5364
|
`serve()` also accepts `discovery` (project-loading options) and
|
|
4899
5365
|
`mode: "single" | "multi"`. Pass `apiKey` or use the same Cursor
|
|
4900
5366
|
credential as the CLI: `CURSOR_API_KEY`, `CURSOR_API_KEY_FILE`,
|
|
4901
5367
|
`CURSOR_SERVICE_ACCOUNT_KEY`, or `bdk login`.
|
|
4902
5368
|
|
|
5369
|
+
## Inspect a project in tests
|
|
5370
|
+
|
|
5371
|
+
`loadProject(dir)` reads one project and does not serve it. The result is a `Project`. The only field is `info`. That object matches the `GET /v1/info` body for the project. `bdk info --json` on a project directory prints `{ agents: [{ slug, ...info }] }`. It prints the bare object only when the single mount slug is empty.
|
|
5372
|
+
|
|
5373
|
+
```ts
|
|
5374
|
+
import { loadProject } from "@cursor/bdk";
|
|
5375
|
+
|
|
5376
|
+
const project = await loadProject("./my-agent");
|
|
5377
|
+
console.log(project.info.name);
|
|
5378
|
+
console.log(project.info.tools.map((tool) => tool.name));
|
|
5379
|
+
```
|
|
5380
|
+
|
|
5381
|
+
`loadProject` throws `ProjectLoadError` when discovery reports an error. Pass `{ strict: true }` to throw on a warning as well. `error.diagnostics` lists the findings. Each `path` is relative to the project directory. A path outside that directory starts with `../`. `loadProject` does not take `importModule`. `serve` still accepts `discovery.importModule` for that override.
|
|
5382
|
+
|
|
5383
|
+
`info.local` is `{ cwd }` when the project sets a cwd. The serve banner reads `agents[].info`.
|
|
5384
|
+
|
|
5385
|
+
`serve` accepts that `Project` or a directory path.
|
|
5386
|
+
|
|
4903
5387
|
## Related
|
|
4904
5388
|
|
|
4905
5389
|
- [Instructions](/docs/reference/instructions.md): the required half of a minimal
|
|
@@ -5144,11 +5628,15 @@ Each handler receives the Fetch `Request` and a typed arguments object.
|
|
|
5144
5628
|
| `purpose` | Use `"eval"` to mark a new session as regression traffic |
|
|
5145
5629
|
| `dryRun` | Run read tools and stub write tools for a new session |
|
|
5146
5630
|
| `asOf` | Freeze a new session at an ISO-8601 instant with a timezone |
|
|
5631
|
+
| `deliveryId` | Name this send on the session's events, at most 256 characters. Defaults to a fresh `dlv_…` ID |
|
|
5147
5632
|
|
|
5148
5633
|
`send` returns a `ChannelSession`. Its `id` identifies the session,
|
|
5149
5634
|
`continuationToken` contains its current channel key, and `isNew` says
|
|
5150
5635
|
whether this call created it. A coalesced call also returns
|
|
5151
|
-
`coalesced: true`.
|
|
5636
|
+
`coalesced: true`. `deliveryId` names this send on the event where the
|
|
5637
|
+
message reaches the agent; see
|
|
5638
|
+
[Track which follow-up reached the agent](/docs/reference/sessions.md#track-which-follow-up-reached-the-agent).
|
|
5639
|
+
A hosted channel's `send` returns the same ID before the session exists.
|
|
5152
5640
|
|
|
5153
5641
|
## Events
|
|
5154
5642
|
|
|
@@ -5193,7 +5681,7 @@ returns `401`.
|
|
|
5193
5681
|
| `loopbackOnly()` | Any loopback TCP peer, including local relays that carry forwarding headers |
|
|
5194
5682
|
| `bearerAuth(tokenOrVerify)` | A matching bearer token, or a token accepted by the verifier |
|
|
5195
5683
|
| `sharedSecretAuth({ header, secret })` | A header matching the named environment or deployment secret |
|
|
5196
|
-
| `hmacSignatureAuth({ header, secret, prefix? })` | A hex HMAC-SHA256 signature over the raw body using the named secret |
|
|
5684
|
+
| `hmacSignatureAuth({ header, secret, prefix?, separator? })` | A hex HMAC-SHA256 signature over the raw body using the named secret. With `separator`, any of several signatures in the header. A secret holding one value per line verifies under any of them (at most 32, `@cursor/bdk` 0.2.25 or later) |
|
|
5197
5685
|
| `allowAll()` | Every caller as an anonymous principal |
|
|
5198
5686
|
| `publicEndpoint()` | Every caller on this custom channel; managed hosting also exposes the route without an alias token |
|
|
5199
5687
|
|
|
@@ -5220,6 +5708,7 @@ author their own chain, and `--allow-anonymous` swaps it for
|
|
|
5220
5708
|
| `@cursor/bdk/channels/github` | `githubChannel()` | GitHub and GitHub Enterprise webhooks. See [GitHub](/docs/guides/github.md) |
|
|
5221
5709
|
| `@cursor/bdk/channels/gitlab` | `gitlabChannel()` | GitLab.com and self-managed GitLab hooks. See [GitLab](/docs/guides/gitlab.md) |
|
|
5222
5710
|
| `@cursor/bdk/channels/bitbucket` | `bitbucketChannel()` | Bitbucket Cloud and Data Center hooks. See [Bitbucket](/docs/guides/bitbucket.md) |
|
|
5711
|
+
| `@cursor/bdk/channels/pagerduty` | `pagerdutyChannel()` | PagerDuty v3 incident webhooks. Replies post as incident notes only with `deliverReplies: true`. See [PagerDuty](/docs/guides/pagerduty.md) |
|
|
5223
5712
|
| `@cursor/bdk/channels/deployments` | `deploymentsChannel()` | Deployment events filtered by source, environment, or event name |
|
|
5224
5713
|
|
|
5225
5714
|
For other platforms like Discord or Teams, use the authored
|
|
@@ -6265,6 +6754,33 @@ follow the GitHub replay contract.
|
|
|
6265
6754
|
|
|
6266
6755
|
See [Bitbucket](/docs/guides/bitbucket.md) for Cloud and Data Center setup.
|
|
6267
6756
|
|
|
6757
|
+
### Test PagerDuty webhooks {#pagerduty}
|
|
6758
|
+
|
|
6759
|
+
```text
|
|
6760
|
+
bdk pagerduty replay [incident-id]
|
|
6761
|
+
[--events a,b,c | '*'] [--comment <body>]
|
|
6762
|
+
[--dir <path>] [--slug <slug>] [--channel <id>]
|
|
6763
|
+
[--url <url>] [--host <host>] [--port <n>]
|
|
6764
|
+
[--secret <secret>] [--dry-run] [--out <dir>] [--json]
|
|
6765
|
+
bdk pagerduty events [--dir <path>] [--host <host>] [--port <n>] [--json]
|
|
6766
|
+
```
|
|
6767
|
+
|
|
6768
|
+
| Subcommand | Contract |
|
|
6769
|
+
| --- | --- |
|
|
6770
|
+
| `replay` | Synthesize v3 webhook bodies for one incident and post them, in order, to matching channels. The default event is `incident.triggered`; `'*'` selects every declared event replay supports. |
|
|
6771
|
+
| `events` | List discovered PagerDuty channel URLs and event types. |
|
|
6772
|
+
|
|
6773
|
+
Replay supports `incident.triggered`, `.acknowledged`, `.annotated`,
|
|
6774
|
+
`.escalated`, `.resolved`, and `.reopened`, by full name or by action alone
|
|
6775
|
+
(`resolved`). It needs no PagerDuty account. The incident id defaults to
|
|
6776
|
+
`PREPLAY1`, and `--comment` is the note body for `annotated`. `--secret`
|
|
6777
|
+
defaults to `PAGERDUTY_WEBHOOK_SECRET`, signing with its first line when it
|
|
6778
|
+
lists several; without either the deliveries are unsigned, which `bdk dev`
|
|
6779
|
+
admits from loopback. `--dry-run` and `--out`
|
|
6780
|
+
follow the GitHub replay contract.
|
|
6781
|
+
|
|
6782
|
+
See [PagerDuty](/docs/guides/pagerduty.md) for channel setup.
|
|
6783
|
+
|
|
6268
6784
|
## Environment variables
|
|
6269
6785
|
|
|
6270
6786
|
Credential resolution follows this order: `--api-key`, `CURSOR_API_KEY`,
|
|
@@ -7170,20 +7686,26 @@ Author `bot/hooks/<name>.ts` with `defineHook` from
|
|
|
7170
7686
|
|
|
7171
7687
|
```ts
|
|
7172
7688
|
// bot/hooks/usage.ts
|
|
7689
|
+
import { metrics } from "@opentelemetry/api";
|
|
7173
7690
|
import { defineHook } from "@cursor/bdk/hooks";
|
|
7174
7691
|
|
|
7692
|
+
const meter = metrics.getMeter("acme");
|
|
7693
|
+
const inputTokens = meter.createCounter("acme.tokens.input");
|
|
7694
|
+
const outputTokens = meter.createCounter("acme.tokens.output");
|
|
7695
|
+
const turnFailed = meter.createCounter("acme.turn.failed");
|
|
7696
|
+
|
|
7175
7697
|
export default defineHook({
|
|
7176
7698
|
events: {
|
|
7177
7699
|
async "turn.completed"(event, ctx) {
|
|
7178
7700
|
if (ctx.session.purpose === "eval" || event.data.usage === undefined) {
|
|
7179
7701
|
return;
|
|
7180
7702
|
}
|
|
7181
|
-
const
|
|
7182
|
-
|
|
7183
|
-
|
|
7703
|
+
const usage = event.data.usage;
|
|
7704
|
+
inputTokens.add(usage.inputTokens);
|
|
7705
|
+
outputTokens.add(usage.outputTokens);
|
|
7184
7706
|
},
|
|
7185
7707
|
async "turn.failed"(_event, ctx) {
|
|
7186
|
-
|
|
7708
|
+
turnFailed.add(1, { channel: ctx.channel.id });
|
|
7187
7709
|
},
|
|
7188
7710
|
},
|
|
7189
7711
|
});
|
|
@@ -7235,7 +7757,6 @@ exported from `@cursor/bdk`.
|
|
|
7235
7757
|
| `ctx.channel` | `{ id, continuationToken }`. The token is `null` when the session can't take follow-ups |
|
|
7236
7758
|
| `ctx.host.kv` | Durable JSON, shared by every session of the agent. Prefix keys with `ctx.session.id` for per-session state |
|
|
7237
7759
|
| `ctx.host.files` | Durable files, bound to this session. Pass `{ scope: "deployment" }` for agent-wide files |
|
|
7238
|
-
| `ctx.host.otel` | Counters, histograms, and tags, attributed to this session |
|
|
7239
7760
|
| `ctx.host.mcp`, `ctx.host.github`, `ctx.host.slack` | The same shared clients tools get |
|
|
7240
7761
|
| `ctx.host.reminders` | Per-session [reminders](/docs/reference/schedules.md#reminders), the same API tools get |
|
|
7241
7762
|
| `ctx.artifacts` | Session-bound [artifacts](/docs/reference/artifacts.md) facade: `tag` fills in `sessionId` and `turnId` |
|
|
@@ -8227,6 +8748,51 @@ the session is already busy depends on the channel:
|
|
|
8227
8748
|
Pass `admission: "coalesce"` on `send()` to opt into the Slack policy from
|
|
8228
8749
|
other callers. Omit it (or pass `"preempt"`) to keep interrupt semantics.
|
|
8229
8750
|
|
|
8751
|
+
### Track which follow-up reached the agent
|
|
8752
|
+
|
|
8753
|
+
Every `send()` returns a `deliveryId`. Pass your own as the `deliveryId`
|
|
8754
|
+
option, such as the webhook delivery ID you already hold, or omit it to
|
|
8755
|
+
get a fresh `dlv_…` ID. A coalesced follow-up reaches the agent in one of
|
|
8756
|
+
two ways, and the ID is on the event for that path:
|
|
8757
|
+
|
|
8758
|
+
| Path | Event | Field |
|
|
8759
|
+
| --- | --- | --- |
|
|
8760
|
+
| Steered into the running turn | `nudge.delivered` | `data.deliveryId` |
|
|
8761
|
+
| Fell back to the next turn | That turn's `message.received` | `data.deliveryIds` |
|
|
8762
|
+
|
|
8763
|
+
`message.received` lists every send its prompt carries, in arrival order.
|
|
8764
|
+
Follow-ups queued behind a busy turn drain into one turn, so the list can
|
|
8765
|
+
hold several IDs. A direct send that starts a turn gets a one-item list.
|
|
8766
|
+
|
|
8767
|
+
```ts
|
|
8768
|
+
// In a route or channel hook: name the steer after the webhook delivery.
|
|
8769
|
+
await send(`Incident ${incident.id} was acknowledged.`, {
|
|
8770
|
+
continuationToken: incident.id,
|
|
8771
|
+
admission: "coalesce",
|
|
8772
|
+
deliveryId: webhookId,
|
|
8773
|
+
});
|
|
8774
|
+
|
|
8775
|
+
// In the channel's `events` map:
|
|
8776
|
+
const steered = new Set<string>();
|
|
8777
|
+
const prompted = new Set<string>();
|
|
8778
|
+
const events: ChannelEventHandlers = {
|
|
8779
|
+
"nudge.delivered": async (event) => {
|
|
8780
|
+
if (event.data.deliveryId !== undefined) {
|
|
8781
|
+
steered.add(event.data.deliveryId);
|
|
8782
|
+
}
|
|
8783
|
+
},
|
|
8784
|
+
"message.received": async (event) => {
|
|
8785
|
+
for (const id of event.data.deliveryIds ?? []) {
|
|
8786
|
+
prompted.add(id);
|
|
8787
|
+
}
|
|
8788
|
+
},
|
|
8789
|
+
};
|
|
8790
|
+
```
|
|
8791
|
+
|
|
8792
|
+
A local Slack session can also pick up follow-ups at a tool boundary from
|
|
8793
|
+
its own thread store. That `nudge.delivered` has no `deliveryId`, which
|
|
8794
|
+
tells it apart from a steered send.
|
|
8795
|
+
|
|
8230
8796
|
`POST /v1/session/:id/stop` interrupts a turn without sending a new
|
|
8231
8797
|
message. The stream records `turn.failed` with `status: "cancelled"`;
|
|
8232
8798
|
the session stays a chat session and can take another follow-up. A
|
|
@@ -8245,7 +8811,7 @@ within one session. The `at` field is an ISO-8601 timestamp.
|
|
|
8245
8811
|
| Phase | Events | What they tell you |
|
|
8246
8812
|
| --- | --- | --- |
|
|
8247
8813
|
| Session | `session.started`, `session.waiting`, `session.completed`, `session.failed` | Session creation, readiness, and task completion |
|
|
8248
|
-
| Input | `message.received` | A user message was accepted |
|
|
8814
|
+
| Input | `message.received`, `nudge.delivered` | A user message was accepted as a turn's prompt, or reached a running turn mid-turn. Both name the [sends they carry](#track-which-follow-up-reached-the-agent) |
|
|
8249
8815
|
| Turn | `turn.queued`, `turn.started`, `turn.completed`, `turn.failed` | Queue position under a [`maxRunningTurns` cap](/docs/reference/agent-config.md#concurrency), then turn status, final result, and token usage |
|
|
8250
8816
|
| Steps | `step.started`, `step.completed` | Model step boundaries and duration |
|
|
8251
8817
|
| Reasoning | `reasoning.appended`, `reasoning.completed` | Streamed reasoning blocks |
|
|
@@ -8537,6 +9103,7 @@ export default defineTool({
|
|
|
8537
9103
|
| --- | --- |
|
|
8538
9104
|
| `ctx.toolCallId` | The call id, matching the `actions.requested` / `action.result` stream events |
|
|
8539
9105
|
| `ctx.session` | Read-only session info: id, channel, mode, auth |
|
|
9106
|
+
| `ctx.approvedBy` | For a `needsApproval` tool, the auth of whoever approved this call, in the same shape as `ctx.session.auth`. On Slack, `attributes.user_id` is the person who clicked Approve, who can differ from the person who started the thread. Unset when the call needed no approval |
|
|
8540
9107
|
| `ctx.workspaceDir` | The session's workspace directory |
|
|
8541
9108
|
| `ctx.stateRoot` | The agent's durable state root, shared across every session |
|
|
8542
9109
|
| `ctx.host` | Shared host services (see below) |
|
|
@@ -8547,9 +9114,9 @@ export default defineTool({
|
|
|
8547
9114
|
`ctx.host` carries the shared host services: `host.mcp` (authored MCP
|
|
8548
9115
|
connections: `names()`, `listTools(name)`, `callTool(name, tool, args)`),
|
|
8549
9116
|
`host.github` and `host.slack` (shared platform clients), `host.kv` and
|
|
8550
|
-
`host.files` (durable storage), `host.
|
|
8551
|
-
|
|
8552
|
-
|
|
9117
|
+
`host.files` (durable storage), and `host.reminders` (per-session wakes,
|
|
9118
|
+
when attached). Custom metrics use the
|
|
9119
|
+
[OpenTelemetry](/docs/guides/opentelemetry.md) API.
|
|
8553
9120
|
|
|
8554
9121
|
### Return values
|
|
8555
9122
|
|