@cursor/july 0.1.89 → 0.1.91
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 +8 -0
- package/README.md +98 -96
- package/dist/ab.d.ts +1 -1
- package/dist/ab.js +1 -1
- package/dist/artifacts.d.ts +1 -1
- package/dist/artifacts.js +1 -1
- package/dist/bin/agent-serve.js +20 -7
- package/dist/channels/slack/channel-watch.d.ts +1 -1
- package/dist/channels/slack/channel-watch.js +1 -1
- package/dist/channels/slack/slack-channel.js +1 -1
- package/dist/channels/slack/types.d.ts +2 -4
- package/dist/channels/slack/types.d.ts.map +1 -1
- package/dist/channels.d.ts +1 -1
- package/dist/channels.js +1 -1
- package/dist/connections.d.ts +1 -1
- package/dist/connections.js +1 -1
- package/dist/docs/404.html +3 -3
- package/dist/docs/ab.html +7 -7
- package/dist/docs/assets/{ab.md.DYjwREAP.js → ab.md.CVzWxLoB.js} +1 -1
- package/dist/docs/assets/{ab.md.DYjwREAP.lean.js → ab.md.CVzWxLoB.lean.js} +1 -1
- package/dist/docs/assets/{app.DUOPbN18.js → app.Bci6CM9E.js} +1 -1
- package/dist/docs/assets/{building-with-agents.md.PeZaZA1P.js → building-with-agents.md.DH8A_cHA.js} +1 -1
- package/dist/docs/assets/{building-with-agents.md.PeZaZA1P.lean.js → building-with-agents.md.DH8A_cHA.lean.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.Dv-Q0XtU.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.CmWbGcGk.js → VPLocalSearchBox.BCPT6xA-.js} +1 -1
- package/dist/docs/assets/chunks/{framework.CAZyNGu9.js → framework.BCISBCiQ.js} +1 -1
- package/dist/docs/assets/chunks/theme.BEA8BF3c.js +2 -0
- package/dist/docs/assets/{concepts.md.BXAm6G-C.js → concepts.md.CRfU3bVg.js} +1 -1
- package/dist/docs/assets/{concepts.md.BXAm6G-C.lean.js → concepts.md.CRfU3bVg.lean.js} +1 -1
- package/dist/docs/assets/{deployment.md.B8kW-h7P.js → deployment.md.DX_hc3ze.js} +6 -5
- package/dist/docs/assets/{deployment.md.B8kW-h7P.lean.js → deployment.md.DX_hc3ze.lean.js} +1 -1
- package/dist/docs/assets/{evals.md.CVe_O75-.js → evals.md.a0SMN6r9.js} +3 -3
- package/dist/docs/assets/{evals.md.CVe_O75-.lean.js → evals.md.a0SMN6r9.lean.js} +1 -1
- package/dist/docs/assets/{example-agents_approval-buddy.md.CIiZ9coo.js → example-agents_approval-buddy.md.DNL83puR.js} +1 -1
- package/dist/docs/assets/{example-agents_approval-buddy.md.CIiZ9coo.lean.js → example-agents_approval-buddy.md.DNL83puR.lean.js} +1 -1
- package/dist/docs/assets/{example-agents_benny.md.B-LIDGja.js → example-agents_benny.md.C40vHRLc.js} +1 -1
- package/dist/docs/assets/{example-agents_benny.md.B-LIDGja.lean.js → example-agents_benny.md.C40vHRLc.lean.js} +1 -1
- package/dist/docs/assets/{example-agents_bugbot.md.Dp5JqHSQ.js → example-agents_bugbot.md.BRGMi9O2.js} +1 -1
- package/dist/docs/assets/{example-agents_bugbot.md.Dp5JqHSQ.lean.js → example-agents_bugbot.md.BRGMi9O2.lean.js} +1 -1
- package/dist/docs/assets/{example-agents_codebase-wiki.md.D-lteFf0.js → example-agents_codebase-wiki.md.Dftj_tPp.js} +1 -1
- package/dist/docs/assets/{example-agents_codebase-wiki.md.D-lteFf0.lean.js → example-agents_codebase-wiki.md.Dftj_tPp.lean.js} +1 -1
- package/dist/docs/assets/{example-agents_codeowners-review.md.BU2ZXLf-.js → example-agents_codeowners-review.md.Bfta-lBU.js} +1 -1
- package/dist/docs/assets/{example-agents_codeowners-review.md.BU2ZXLf-.lean.js → example-agents_codeowners-review.md.Bfta-lBU.lean.js} +1 -1
- package/dist/docs/assets/{example-agents_concierge.md.DA2al_NK.js → example-agents_concierge.md.MrKpQndp.js} +1 -1
- package/dist/docs/assets/{example-agents_concierge.md.DA2al_NK.lean.js → example-agents_concierge.md.MrKpQndp.lean.js} +1 -1
- package/dist/docs/assets/{example-agents_fsd.md.ZeGEpAw_.js → example-agents_fsd.md.ZWHWWZPE.js} +1 -1
- package/dist/docs/assets/{example-agents_fsd.md.ZeGEpAw_.lean.js → example-agents_fsd.md.ZWHWWZPE.lean.js} +1 -1
- package/dist/docs/assets/example-agents_index.md.QZ8mhr6n.js +2 -0
- package/dist/docs/assets/{example-agents_index.md.xmJ87d_3.lean.js → example-agents_index.md.QZ8mhr6n.lean.js} +1 -1
- package/dist/docs/assets/{example-agents_knowledge-base.md.IneynQSR.js → example-agents_knowledge-base.md.DqKqHQ9u.js} +1 -1
- package/dist/docs/assets/{example-agents_knowledge-base.md.IneynQSR.lean.js → example-agents_knowledge-base.md.DqKqHQ9u.lean.js} +1 -1
- package/dist/docs/assets/{example-agents_oncall.md.CBmyuAKc.js → example-agents_oncall.md.DK4XkYTd.js} +1 -1
- package/dist/docs/assets/{example-agents_oncall.md.CBmyuAKc.lean.js → example-agents_oncall.md.DK4XkYTd.lean.js} +1 -1
- package/dist/docs/assets/{example-agents_security-reviewer.md.DBL1TwtP.js → example-agents_security-reviewer.md.Bai6D0Ee.js} +4 -4
- package/dist/docs/assets/{example-agents_security-reviewer.md.DBL1TwtP.lean.js → example-agents_security-reviewer.md.Bai6D0Ee.lean.js} +1 -1
- package/dist/docs/assets/{example-agents_slack-agent.md.06jQXTAI.js → example-agents_slack-agent.md.D7Kdj5BV.js} +1 -1
- package/dist/docs/assets/{example-agents_slack-agent.md.06jQXTAI.lean.js → example-agents_slack-agent.md.D7Kdj5BV.lean.js} +1 -1
- package/dist/docs/assets/{example-agents_weather-agent.md.DC3lINjo.js → example-agents_weather-agent.md.lVEAbWFf.js} +5 -5
- package/dist/docs/assets/example-agents_weather-agent.md.lVEAbWFf.lean.js +1 -0
- package/dist/docs/assets/{guides_agent-to-agent.md.Bmbxy-FA.js → guides_agent-to-agent.md.BCeVdJRJ.js} +1 -1
- package/dist/docs/assets/{guides_agent-to-agent.md.Bmbxy-FA.lean.js → guides_agent-to-agent.md.BCeVdJRJ.lean.js} +1 -1
- package/dist/docs/assets/{guides_cloud-runtime.md.CbklWfzh.js → guides_cloud-runtime.md.BSMLIBHr.js} +1 -1
- package/dist/docs/assets/{guides_cloud-runtime.md.CbklWfzh.lean.js → guides_cloud-runtime.md.BSMLIBHr.lean.js} +1 -1
- package/dist/docs/assets/{guides_convert-automation.md.BhMzTkE5.js → guides_convert-automation.md.D06eIzea.js} +1 -1
- package/dist/docs/assets/{guides_convert-automation.md.BhMzTkE5.lean.js → guides_convert-automation.md.D06eIzea.lean.js} +1 -1
- package/dist/docs/assets/{guides_github.md.CLLQJKRB.js → guides_github.md.Cdt1s2QC.js} +4 -4
- package/dist/docs/assets/{guides_github.md.CLLQJKRB.lean.js → guides_github.md.Cdt1s2QC.lean.js} +1 -1
- package/dist/docs/assets/{guides_human-in-the-loop.md.Cf8kIIqC.js → guides_human-in-the-loop.md.By1G2T3_.js} +1 -1
- package/dist/docs/assets/{guides_human-in-the-loop.md.Cf8kIIqC.lean.js → guides_human-in-the-loop.md.By1G2T3_.lean.js} +1 -1
- package/dist/docs/assets/{guides_mcp-oauth.md.CzEB6RaG.js → guides_mcp-oauth.md.Du0f7pGU.js} +1 -1
- package/dist/docs/assets/{guides_mcp-oauth.md.CzEB6RaG.lean.js → guides_mcp-oauth.md.Du0f7pGU.lean.js} +1 -1
- package/dist/docs/assets/{guides_opentelemetry.md.Csn7ZI25.js → guides_opentelemetry.md.bmPmkvJu.js} +1 -1
- package/dist/docs/assets/{guides_opentelemetry.md.Csn7ZI25.lean.js → guides_opentelemetry.md.bmPmkvJu.lean.js} +1 -1
- package/dist/docs/assets/{guides_slack.md.DP4H75WP.js → guides_slack.md.DiUmk_Oi.js} +5 -5
- package/dist/docs/assets/{guides_slack.md.DP4H75WP.lean.js → guides_slack.md.DiUmk_Oi.lean.js} +1 -1
- package/dist/docs/assets/{guides_webhooks.md.DB-r_er9.js → guides_webhooks.md.BpnIdO0i.js} +5 -6
- package/dist/docs/assets/{guides_webhooks.md.DB-r_er9.lean.js → guides_webhooks.md.BpnIdO0i.lean.js} +1 -1
- package/dist/docs/assets/{hillclimbing.md.yXqdlv2R.js → hillclimbing.md.ywF3yDAd.js} +1 -1
- package/dist/docs/assets/{hillclimbing.md.yXqdlv2R.lean.js → hillclimbing.md.ywF3yDAd.lean.js} +1 -1
- package/dist/docs/assets/index.md.BAaMXLFd.js +5 -0
- package/dist/docs/assets/{index.md.DhRHS_-L.lean.js → index.md.BAaMXLFd.lean.js} +1 -1
- package/dist/docs/assets/{quickstart.md.DZxBu44y.js → quickstart.md.DsrarzEg.js} +1 -1
- package/dist/docs/assets/{quickstart.md.DZxBu44y.lean.js → quickstart.md.DsrarzEg.lean.js} +1 -1
- package/dist/docs/assets/{reference_agent-config.md.CTWp4DnU.js → reference_agent-config.md.Bqylgw50.js} +1 -1
- package/dist/docs/assets/{reference_agent-config.md.CTWp4DnU.lean.js → reference_agent-config.md.Bqylgw50.lean.js} +1 -1
- package/dist/docs/assets/{reference_artifacts.md.BGG4bZo-.js → reference_artifacts.md.Dior32Qw.js} +1 -1
- package/dist/docs/assets/{reference_artifacts.md.BGG4bZo-.lean.js → reference_artifacts.md.Dior32Qw.lean.js} +1 -1
- package/dist/docs/assets/{reference_channels.md.CboFd5IH.js → reference_channels.md.DQZjCnyh.js} +2 -2
- package/dist/docs/assets/{reference_channels.md.CboFd5IH.lean.js → reference_channels.md.DQZjCnyh.lean.js} +1 -1
- package/dist/docs/assets/{reference_cli.md.TAaYU8br.js → reference_cli.md.B7GkAJRC.js} +8 -7
- package/dist/docs/assets/{reference_cli.md.TAaYU8br.lean.js → reference_cli.md.B7GkAJRC.lean.js} +1 -1
- package/dist/docs/assets/{reference_connections.md.Cu3N-S3Q.js → reference_connections.md.DYidrb-j.js} +5 -5
- package/dist/docs/assets/{reference_connections.md.Cu3N-S3Q.lean.js → reference_connections.md.DYidrb-j.lean.js} +1 -1
- package/dist/docs/assets/{reference_hooks.md.DJE5DXcT.js → reference_hooks.md.B9FSgdDe.js} +1 -1
- package/dist/docs/assets/{reference_hooks.md.DJE5DXcT.lean.js → reference_hooks.md.B9FSgdDe.lean.js} +1 -1
- package/dist/docs/assets/{reference_http-api.md.DMbdFGVQ.js → reference_http-api.md.CSHVobzG.js} +4 -4
- package/dist/docs/assets/{reference_http-api.md.DMbdFGVQ.lean.js → reference_http-api.md.CSHVobzG.lean.js} +1 -1
- package/dist/docs/assets/{reference_instructions.md.CgoV-YEb.js → reference_instructions.md.DhNCOl7r.js} +1 -1
- package/dist/docs/assets/{reference_instructions.md.CgoV-YEb.lean.js → reference_instructions.md.DhNCOl7r.lean.js} +1 -1
- package/dist/docs/assets/{reference_playground.md.CPZhfYaO.js → reference_playground.md.Dfb92yQf.js} +1 -1
- package/dist/docs/assets/{reference_playground.md.CPZhfYaO.lean.js → reference_playground.md.Dfb92yQf.lean.js} +1 -1
- package/dist/docs/assets/{reference_project-layout.md.D3MdHM2z.js → reference_project-layout.md.CwkSbEWT.js} +5 -20
- package/dist/docs/assets/reference_project-layout.md.CwkSbEWT.lean.js +1 -0
- package/dist/docs/assets/{reference_prompt.md.BaiweQxE.js → reference_prompt.md.DZUMtLPD.js} +1 -1
- package/dist/docs/assets/{reference_prompt.md.BaiweQxE.lean.js → reference_prompt.md.DZUMtLPD.lean.js} +1 -1
- package/dist/docs/assets/{reference_schedules.md.gmfYzf_I.js → reference_schedules.md.DNipebiG.js} +1 -1
- package/dist/docs/assets/{reference_schedules.md.gmfYzf_I.lean.js → reference_schedules.md.DNipebiG.lean.js} +1 -1
- package/dist/docs/assets/{reference_sessions.md.B0DdlM-K.js → reference_sessions.md.tUFzz98S.js} +1 -1
- package/dist/docs/assets/{reference_sessions.md.B0DdlM-K.lean.js → reference_sessions.md.tUFzz98S.lean.js} +1 -1
- package/dist/docs/assets/{reference_skills.md.BRF2nDv9.js → reference_skills.md.B5ZEuHfG.js} +1 -1
- package/dist/docs/assets/{reference_skills.md.BRF2nDv9.lean.js → reference_skills.md.B5ZEuHfG.lean.js} +1 -1
- package/dist/docs/assets/{reference_subagents.md.DSrGLIuB.js → reference_subagents.md.Xoav0AII.js} +1 -1
- package/dist/docs/assets/{reference_subagents.md.DSrGLIuB.lean.js → reference_subagents.md.Xoav0AII.lean.js} +1 -1
- package/dist/docs/assets/{reference_tools.md.DTg_kEsx.js → reference_tools.md.wpaJtHn6.js} +23 -3
- package/dist/docs/assets/{reference_tools.md.DTg_kEsx.lean.js → reference_tools.md.wpaJtHn6.lean.js} +1 -1
- package/dist/docs/assets/{scaffolding-agents.md.CiGsJ1aw.js → scaffolding-agents.md.CRDDUtYJ.js} +1 -1
- package/dist/docs/assets/{scaffolding-agents.md.CiGsJ1aw.lean.js → scaffolding-agents.md.CRDDUtYJ.lean.js} +1 -1
- package/dist/docs/assets/{storage.md.ks1u64_R.js → storage.md.JbjlHWZ6.js} +1 -1
- package/dist/docs/assets/{storage.md.ks1u64_R.lean.js → storage.md.JbjlHWZ6.lean.js} +1 -1
- package/dist/docs/assets/{style.kTsvp4pE.css → style.BRuM8477.css} +1 -1
- package/dist/docs/assets/{templates_agentic-owners.md.BkTLORaU.js → templates_agentic-owners.md.DSJSIpWU.js} +1 -1
- package/dist/docs/assets/{templates_agentic-owners.md.BkTLORaU.lean.js → templates_agentic-owners.md.DSJSIpWU.lean.js} +1 -1
- package/dist/docs/assets/{templates_demo.md.Bgd6MBaZ.js → templates_demo.md.DhFcWN6j.js} +1 -1
- package/dist/docs/assets/{templates_demo.md.Bgd6MBaZ.lean.js → templates_demo.md.DhFcWN6j.lean.js} +1 -1
- package/dist/docs/assets/{templates_pr-autofixer.md.DcmoeUNZ.js → templates_pr-autofixer.md.1HAR3RXE.js} +1 -1
- package/dist/docs/assets/{templates_pr-autofixer.md.DcmoeUNZ.lean.js → templates_pr-autofixer.md.1HAR3RXE.lean.js} +1 -1
- package/dist/docs/assets/{templates_security-reviewer.md.C0yIUaYs.js → templates_security-reviewer.md.ByFyRta2.js} +1 -1
- package/dist/docs/assets/{templates_security-reviewer.md.C0yIUaYs.lean.js → templates_security-reviewer.md.ByFyRta2.lean.js} +1 -1
- package/dist/docs/assets/{templates_triage.md.DWuQ1bZz.js → templates_triage.md.CVlpctKS.js} +2 -2
- package/dist/docs/assets/{templates_triage.md.DWuQ1bZz.lean.js → templates_triage.md.CVlpctKS.lean.js} +1 -1
- package/dist/docs/assets/troubleshooting.md.DYECCZiJ.js +1 -0
- package/dist/docs/assets/{troubleshooting.md.KgmmaCgw.lean.js → troubleshooting.md.DYECCZiJ.lean.js} +1 -1
- package/dist/docs/building-with-agents.html +7 -7
- package/dist/docs/concepts.html +7 -7
- package/dist/docs/deployment.html +11 -10
- package/dist/docs/evals.html +8 -8
- package/dist/docs/example-agents/approval-buddy.html +7 -7
- package/dist/docs/example-agents/benny.html +7 -7
- package/dist/docs/example-agents/bugbot.html +7 -7
- package/dist/docs/example-agents/codebase-wiki.html +7 -7
- package/dist/docs/example-agents/codeowners-review.html +7 -7
- package/dist/docs/example-agents/concierge.html +7 -7
- package/dist/docs/example-agents/fsd.html +7 -7
- package/dist/docs/example-agents/index.html +7 -7
- package/dist/docs/example-agents/knowledge-base.html +7 -7
- package/dist/docs/example-agents/oncall.html +7 -7
- package/dist/docs/example-agents/security-reviewer.html +10 -10
- package/dist/docs/example-agents/slack-agent.html +7 -7
- package/dist/docs/example-agents/weather-agent.html +12 -12
- package/dist/docs/guides/agent-to-agent.html +7 -7
- package/dist/docs/guides/cloud-runtime.html +7 -7
- package/dist/docs/guides/convert-automation.html +7 -7
- package/dist/docs/guides/github.html +9 -9
- package/dist/docs/guides/human-in-the-loop.html +7 -7
- package/dist/docs/guides/mcp-oauth.html +7 -7
- package/dist/docs/guides/opentelemetry.html +7 -7
- package/dist/docs/guides/slack.html +10 -10
- package/dist/docs/guides/webhooks.html +10 -11
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +7 -7
- package/dist/docs/index.html +8 -8
- package/dist/docs/quickstart.html +7 -7
- package/dist/docs/reference/agent-config.html +7 -7
- package/dist/docs/reference/artifacts.html +7 -7
- package/dist/docs/reference/channels.html +8 -8
- package/dist/docs/reference/cli.html +13 -12
- package/dist/docs/reference/connections.html +10 -10
- package/dist/docs/reference/hooks.html +7 -7
- package/dist/docs/reference/http-api.html +10 -10
- package/dist/docs/reference/instructions.html +7 -7
- package/dist/docs/reference/playground.html +7 -7
- package/dist/docs/reference/project-layout.html +10 -25
- package/dist/docs/reference/prompt.html +7 -7
- package/dist/docs/reference/schedules.html +7 -7
- package/dist/docs/reference/sessions.html +7 -7
- package/dist/docs/reference/skills.html +7 -7
- package/dist/docs/reference/subagents.html +7 -7
- package/dist/docs/reference/tools.html +29 -9
- package/dist/docs/scaffolding-agents.html +7 -7
- package/dist/docs/storage.html +7 -7
- package/dist/docs/templates/agentic-owners.html +7 -7
- package/dist/docs/templates/demo.html +7 -7
- package/dist/docs/templates/pr-autofixer.html +7 -7
- package/dist/docs/templates/security-reviewer.html +7 -7
- package/dist/docs/templates/triage.html +8 -8
- package/dist/docs/troubleshooting.html +7 -7
- package/dist/evals.d.ts +1 -1
- package/dist/evals.js +1 -1
- package/dist/hooks.d.ts +1 -1
- package/dist/hooks.js +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/internal/cli-convert-automation.d.ts +1 -1
- package/dist/internal/cli-convert-automation.js +1 -1
- package/dist/internal/cli-cursor.d.ts +12 -4
- package/dist/internal/cli-cursor.d.ts.map +1 -1
- package/dist/internal/cli-cursor.js +11 -4
- package/dist/internal/cli-deploy.d.ts.map +1 -1
- package/dist/internal/cli-deploy.js +21 -3
- package/dist/internal/convert-automation/convert-workflow.d.ts +1 -1
- package/dist/internal/convert-automation/convert-workflow.js +9 -9
- package/dist/internal/convert-automation/types.d.ts +1 -1
- package/dist/internal/convert-automation/types.js +1 -1
- package/dist/internal/cursor/backend-client.d.ts +9 -1
- package/dist/internal/cursor/backend-client.d.ts.map +1 -1
- package/dist/internal/cursor/backend-client.js +19 -6
- package/dist/internal/cursor/credentials.d.ts +35 -9
- package/dist/internal/cursor/credentials.d.ts.map +1 -1
- package/dist/internal/cursor/credentials.js +92 -39
- package/dist/internal/cursor-agent-template.d.ts +1 -1
- package/dist/internal/cursor-agent-template.d.ts.map +1 -1
- package/dist/internal/cursor-agent-template.js +1 -0
- package/dist/internal/deploy-client.d.ts +18 -0
- package/dist/internal/deploy-client.d.ts.map +1 -1
- package/dist/internal/deploy-client.js +25 -1
- package/dist/internal/deploy-manifest.d.ts.map +1 -1
- package/dist/internal/deploy-manifest.js +5 -1
- package/dist/internal/discovery.d.ts +5 -1
- package/dist/internal/discovery.d.ts.map +1 -1
- package/dist/internal/discovery.js +17 -1
- package/dist/internal/distribution.d.ts +18 -0
- package/dist/internal/distribution.d.ts.map +1 -1
- package/dist/internal/distribution.js +19 -0
- package/dist/internal/eval-runner.js +1 -1
- package/dist/internal/grokbot/runner.d.ts +5 -2
- package/dist/internal/grokbot/runner.d.ts.map +1 -1
- package/dist/internal/grokbot/runner.js +10 -6
- package/dist/internal/http-channel.d.ts +2 -2
- package/dist/internal/http-channel.d.ts.map +1 -1
- package/dist/internal/http-channel.js +11 -31
- package/dist/internal/init-project.d.ts.map +1 -1
- package/dist/internal/init-project.js +10 -1
- package/dist/internal/sdk-runner.d.ts +5 -0
- package/dist/internal/sdk-runner.d.ts.map +1 -1
- package/dist/internal/sdk-runner.js +10 -5
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +80 -36
- package/dist/internal/session-engine.d.ts +8 -0
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +47 -5
- package/dist/playground/assets/index-D9N7-q97.css +1 -0
- package/dist/playground/assets/{index-BmiIjFlM.js → index-DDvyC2z6.js} +49 -49
- package/dist/playground/index.html +2 -2
- package/dist/reminders.d.ts +1 -1
- package/dist/reminders.js +1 -1
- package/dist/schedules.d.ts +1 -1
- package/dist/schedules.js +1 -1
- package/dist/skills.d.ts +1 -1
- package/dist/skills.js +1 -1
- package/dist/storage.d.ts +1 -1
- package/dist/storage.js +1 -1
- package/dist/tools.d.ts +1 -1
- package/dist/tools.js +1 -1
- package/dist/types.d.ts +10 -7
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -1
- package/docs/README.md +3 -1
- package/docs/concepts.md +2 -1
- package/docs/deployment.md +9 -6
- package/docs/evals.md +1 -5
- package/docs/example-agents/codebase-wiki.md +2 -3
- package/docs/example-agents/fsd.md +1 -1
- package/docs/example-agents/index.md +2 -2
- package/docs/example-agents/knowledge-base.md +3 -3
- package/docs/example-agents/security-reviewer.md +17 -48
- package/docs/example-agents/weather-agent.md +14 -45
- package/docs/guides/github.md +7 -4
- package/docs/guides/slack.md +7 -2
- package/docs/guides/webhooks.md +12 -15
- package/docs/reference/channels.md +4 -0
- package/docs/reference/cli.md +21 -7
- package/docs/reference/connections.md +13 -32
- package/docs/reference/http-api.md +14 -9
- package/docs/reference/project-layout.md +5 -20
- package/docs/reference/tools.md +51 -3
- package/docs/scaffolding-agents.md +2 -0
- package/docs/templates/triage.md +3 -5
- package/docs/troubleshooting.md +1 -1
- package/package.json +2 -1
- package/skills/create-agent/SKILL.md +6 -7
- package/skills/framework-map/SKILL.md +6 -6
- package/skills/setup-slack/SKILL.md +1 -1
- package/src/ab.ts +1 -1
- package/src/artifacts.ts +1 -1
- package/src/bin/agent-serve.ts +20 -6
- package/src/channels/slack/channel-watch.ts +1 -1
- package/src/channels/slack/slack-channel.ts +1 -1
- package/src/channels/slack/types.ts +2 -4
- package/src/channels.ts +1 -1
- package/src/connections.ts +1 -1
- package/src/evals.ts +1 -1
- package/src/hooks.ts +1 -1
- package/src/index.ts +2 -2
- package/src/internal/cli-convert-automation.ts +1 -1
- package/src/internal/cli-cursor.ts +18 -5
- package/src/internal/cli-deploy.ts +27 -7
- package/src/internal/convert-automation/convert-workflow.ts +9 -9
- package/src/internal/convert-automation/types.ts +1 -1
- package/src/internal/cursor/backend-client.ts +29 -4
- package/src/internal/cursor/credentials.ts +87 -24
- package/src/internal/cursor-agent-template.ts +1 -0
- package/src/internal/deploy-client.ts +40 -1
- package/src/internal/deploy-manifest.ts +10 -1
- package/src/internal/discovery.ts +21 -1
- package/src/internal/distribution.ts +31 -0
- package/src/internal/eval-runner.ts +1 -1
- package/src/internal/grokbot/runner.ts +15 -6
- package/src/internal/http-channel.ts +14 -41
- package/src/internal/init-project.ts +13 -1
- package/src/internal/sdk-runner.ts +10 -4
- package/src/internal/server.ts +95 -33
- package/src/internal/session-engine.ts +58 -8
- package/src/reminders.ts +1 -1
- package/src/schedules.ts +1 -1
- package/src/skills.ts +1 -1
- package/src/storage.ts +1 -1
- package/src/tools.ts +1 -1
- package/src/types.ts +10 -7
- package/templates/security-help/README.md +37 -0
- package/templates/security-help/agent/agent.ts +18 -0
- package/templates/security-help/agent/channels/github.ts +13 -0
- package/templates/security-help/agent/channels/slack.ts +89 -0
- package/templates/security-help/agent/instructions.md +20 -0
- package/templates/security-help/agent/knowledge/faq/approvals.md +5 -0
- package/templates/security-help/agent/knowledge/faq/channels.md +6 -0
- package/templates/security-help/agent/knowledge/faq/phishing.md +10 -0
- package/templates/security-help/agent/lib/pr-first-pass.ts +42 -0
- package/templates/security-help/agent/lib/repos.ts +5 -0
- package/templates/security-help/agent/skills/access-request.md +10 -0
- package/templates/security-help/agent/skills/security-first-pass.md +15 -0
- package/templates/security-help/agent/skills/security-playbooks.md +12 -0
- package/templates/security-help/agent/skills/security-pr-first-pass.md +12 -0
- package/templates/security-help/evals/evals.config.ts +5 -0
- package/templates/security-help/evals/security-help.eval.ts +53 -0
- package/templates/security-help/init.json +31 -0
- package/templates/security-help/package.json +18 -0
- package/templates/security-help/tsconfig.json +12 -0
- package/templates/triage/agent/channels/webhook.ts +2 -2
- package/dist/docs/assets/chunks/@localSearchIndexroot.CxCtxfDE.js +0 -1
- package/dist/docs/assets/chunks/theme.S57OeOLA.js +0 -2
- package/dist/docs/assets/example-agents_index.md.xmJ87d_3.js +0 -2
- package/dist/docs/assets/example-agents_weather-agent.md.DC3lINjo.lean.js +0 -1
- package/dist/docs/assets/index.md.DhRHS_-L.js +0 -5
- package/dist/docs/assets/reference_project-layout.md.D3MdHM2z.lean.js +0 -1
- package/dist/docs/assets/troubleshooting.md.KgmmaCgw.js +0 -1
- package/dist/playground/assets/index-DQGZnAI0.css +0 -1
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
type TurnUsage,
|
|
30
30
|
} from "../types.js";
|
|
31
31
|
import { mapSdkTokenUsage, usageTokenSum } from "./cloud-turn-cost.js";
|
|
32
|
+
import { resolveApiKeySync } from "./cursor/credentials.js";
|
|
32
33
|
|
|
33
34
|
/** Internal seam between the session engine and the Cursor SDK harness. */
|
|
34
35
|
export interface AgentRunner {
|
|
@@ -427,14 +428,19 @@ export class CursorSdkRunner implements AgentRunner {
|
|
|
427
428
|
(this.options.logger ?? (() => {}))(line);
|
|
428
429
|
}
|
|
429
430
|
|
|
431
|
+
/**
|
|
432
|
+
* Re-resolve on every turn. Hosted freeze snapshots listen unsigned; the
|
|
433
|
+
* binder drops `CURSOR_API_KEY` / `CURSOR_API_KEY_FILE` at task time into
|
|
434
|
+
* the already-running process, which must not have closed over `undefined`.
|
|
435
|
+
*/
|
|
430
436
|
private requireApiKey(): string {
|
|
431
|
-
const
|
|
432
|
-
if (
|
|
437
|
+
const resolved = resolveApiKeySync({ apiKey: this.options.apiKey });
|
|
438
|
+
if (resolved === undefined) {
|
|
433
439
|
throw new Error(
|
|
434
|
-
"The Cursor SDK runner requires a Cursor credential: run `agent-serve login`, set CURSOR_API_KEY, or pass serve({ apiKey })."
|
|
440
|
+
"The Cursor SDK runner requires a Cursor credential: run `agent-serve login`, set CURSOR_API_KEY or CURSOR_API_KEY_FILE, or pass serve({ apiKey })."
|
|
435
441
|
);
|
|
436
442
|
}
|
|
437
|
-
return apiKey;
|
|
443
|
+
return resolved.apiKey;
|
|
438
444
|
}
|
|
439
445
|
|
|
440
446
|
private buildSharedOptions(
|
package/src/internal/server.ts
CHANGED
|
@@ -64,9 +64,11 @@ import {
|
|
|
64
64
|
} from "./cursor/account-mcp.js";
|
|
65
65
|
import { CursorBackendClient } from "./cursor/backend-client.js";
|
|
66
66
|
import {
|
|
67
|
+
cursorBackendUrl,
|
|
67
68
|
cursorExternalApiUrl,
|
|
68
69
|
type ResolvedApiKey,
|
|
69
70
|
resolveApiKey,
|
|
71
|
+
resolveApiKeySync,
|
|
70
72
|
SIGN_IN_HINT,
|
|
71
73
|
} from "./cursor/credentials.js";
|
|
72
74
|
import { CursorGithubCredentialProvider } from "./cursor/github-credentials.js";
|
|
@@ -281,9 +283,9 @@ export async function startServer(
|
|
|
281
283
|
const runSchedules = options.schedules ?? !dev;
|
|
282
284
|
const runReminders = options.reminders ?? !dev;
|
|
283
285
|
|
|
284
|
-
//
|
|
285
|
-
//
|
|
286
|
-
// agentkit_enabled gate
|
|
286
|
+
// CURSOR_AGENTKIT_VERSION is still the env the SDK reads when building
|
|
287
|
+
// its client-version header (wire prefix remains `agentkit-`). Setting it
|
|
288
|
+
// here makes the internal-only agentkit_enabled gate apply to every turn.
|
|
287
289
|
process.env.CURSOR_AGENTKIT_VERSION ??= packageVersion();
|
|
288
290
|
|
|
289
291
|
const authoredOtel = pickAuthoredOtel(
|
|
@@ -328,10 +330,18 @@ export async function startServer(
|
|
|
328
330
|
|
|
329
331
|
// One resolution for every Cursor credential consumer (SDK runner, account
|
|
330
332
|
// MCP bridge, SCM event relay, GitHub credentials): explicit option →
|
|
331
|
-
// CURSOR_API_KEY →
|
|
333
|
+
// CURSOR_API_KEY → CURSOR_API_KEY_FILE (or the hosted default path) →
|
|
334
|
+
// stored `agent-serve login`. SDK / GitHub / account MCP re-read later;
|
|
335
|
+
// Slack and deployment-event relays capture the key at start.
|
|
332
336
|
const accountKey = await resolveApiKey(
|
|
333
337
|
options.apiKey === undefined ? {} : { apiKey: options.apiKey }
|
|
334
338
|
);
|
|
339
|
+
// First present source wins (we define the order): option → env → file →
|
|
340
|
+
// stored login. Re-read so bind can drop env or file onto a listening process.
|
|
341
|
+
const liveCursorApiKey = (): string | undefined =>
|
|
342
|
+
resolveApiKeySync(
|
|
343
|
+
options.apiKey === undefined ? {} : { apiKey: options.apiKey }
|
|
344
|
+
)?.apiKey;
|
|
335
345
|
|
|
336
346
|
// The SCM relay reads the event stream as the signed-in user, so
|
|
337
347
|
// `cursorEvents` cannot work signed out. Require the credential before any
|
|
@@ -365,15 +375,15 @@ export async function startServer(
|
|
|
365
375
|
const needsGithubAuth =
|
|
366
376
|
cursorGithubConfig.scope !== undefined || githubProxyRequested;
|
|
367
377
|
if (needsGithubAuth) {
|
|
368
|
-
const
|
|
369
|
-
cursorEventsAuth
|
|
370
|
-
(
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
if (
|
|
378
|
+
const currentGithubApiKey = (): string | undefined => {
|
|
379
|
+
const fromEvents = cursorEventsAuth?.apiKey.trim();
|
|
380
|
+
if (fromEvents !== undefined && fromEvents !== "") {
|
|
381
|
+
return fromEvents;
|
|
382
|
+
}
|
|
383
|
+
return liveCursorApiKey();
|
|
384
|
+
};
|
|
385
|
+
const githubApiKeyNow = currentGithubApiKey();
|
|
386
|
+
if (githubApiKeyNow === undefined && options.allowAnonymous !== true) {
|
|
377
387
|
throw new Error(
|
|
378
388
|
"githubChannel({ cursorAccount: true }) could not resolve Cursor event authentication."
|
|
379
389
|
);
|
|
@@ -387,20 +397,39 @@ export async function startServer(
|
|
|
387
397
|
logger(
|
|
388
398
|
"[agent-sdk] warning: --allow-anonymous-cursor-github — every admitted HTTP caller can drive sessions holding the signed-in account's repo-scoped GitHub credential; serve this only behind a trusted boundary (e.g. an SSO proxy)"
|
|
389
399
|
);
|
|
400
|
+
if (githubApiKeyNow === undefined) {
|
|
401
|
+
logger(
|
|
402
|
+
"[agent-sdk] GitHub auth: listening unsigned; credentials bind at task via CURSOR_API_KEY or CURSOR_API_KEY_FILE"
|
|
403
|
+
);
|
|
404
|
+
}
|
|
390
405
|
}
|
|
391
406
|
if (cursorGithubConfig.permissions === "contents-write") {
|
|
392
407
|
logger(
|
|
393
408
|
'[agent-sdk] warning: Cursor GitHub credentials include contents:write — the host holds a push-capable token shared with model-driven tools and untrusted webhook content; prefer permissions: "pr-write" unless this agent must push code'
|
|
394
409
|
);
|
|
395
410
|
}
|
|
411
|
+
const githubAuthBaseUrl = cursorExternalApiUrl();
|
|
412
|
+
const requireGithubApiKey = async (): Promise<string> => {
|
|
413
|
+
const apiKey = currentGithubApiKey();
|
|
414
|
+
if (apiKey === undefined) {
|
|
415
|
+
throw new Error(
|
|
416
|
+
`githubChannel({ cursorAccount: true }) has no Cursor credential yet. ${SIGN_IN_HINT}`
|
|
417
|
+
);
|
|
418
|
+
}
|
|
419
|
+
return apiKey;
|
|
420
|
+
};
|
|
396
421
|
const githubProxyUrl = githubProxyRequested
|
|
397
|
-
? resolveCursorGithubProxyUrl(
|
|
422
|
+
? resolveCursorGithubProxyUrl(githubAuthBaseUrl)
|
|
398
423
|
: undefined;
|
|
399
|
-
if (
|
|
424
|
+
if (
|
|
425
|
+
cursorGithubConfig.scope !== undefined &&
|
|
426
|
+
githubApiKeyNow !== undefined
|
|
427
|
+
) {
|
|
400
428
|
const provider = new CursorGithubCredentialProvider({
|
|
401
429
|
client: new CursorBackendClient({
|
|
402
|
-
backendUrl:
|
|
403
|
-
apiKey:
|
|
430
|
+
backendUrl: githubAuthBaseUrl,
|
|
431
|
+
apiKey: githubApiKeyNow,
|
|
432
|
+
getApiKey: () => currentGithubApiKey() ?? "",
|
|
404
433
|
logger,
|
|
405
434
|
}),
|
|
406
435
|
scope: cursorGithubConfig.scope,
|
|
@@ -420,9 +449,7 @@ export async function startServer(
|
|
|
420
449
|
},
|
|
421
450
|
};
|
|
422
451
|
for (const target of cursorGithubTargets) {
|
|
423
|
-
target.accountRuntime.credentials.bind(
|
|
424
|
-
async () => cursorGithubAuth.apiKey
|
|
425
|
-
);
|
|
452
|
+
target.accountRuntime.credentials.bind(requireGithubApiKey);
|
|
426
453
|
target.accountRuntime.credentials.bindProxyTransport(
|
|
427
454
|
proxyTransport
|
|
428
455
|
);
|
|
@@ -438,8 +465,8 @@ export async function startServer(
|
|
|
438
465
|
} else if (githubProxyUrl !== undefined) {
|
|
439
466
|
// `cursorAccount: true` with no `--repo`: skip the startup token mint
|
|
440
467
|
// (it requires a repo list) and let github-proxy take the repo from
|
|
441
|
-
// each Octokit call. Hosted
|
|
442
|
-
//
|
|
468
|
+
// each Octokit call. Hosted freeze bakes this flag into the template
|
|
469
|
+
// so restore is GitHub-ready once Bind drops the key.
|
|
443
470
|
const proxyTransport = {
|
|
444
471
|
apiBaseUrl: githubProxyUrl,
|
|
445
472
|
headers: {
|
|
@@ -447,16 +474,14 @@ export async function startServer(
|
|
|
447
474
|
},
|
|
448
475
|
};
|
|
449
476
|
for (const target of cursorGithubTargets) {
|
|
450
|
-
target.accountRuntime.credentials.bind(
|
|
451
|
-
async () => cursorGithubAuth.apiKey
|
|
452
|
-
);
|
|
477
|
+
target.accountRuntime.credentials.bind(requireGithubApiKey);
|
|
453
478
|
target.accountRuntime.credentials.bindProxyTransport(proxyTransport);
|
|
454
479
|
}
|
|
455
480
|
// `ctx.host.github` gets the same proxy transport; without this it
|
|
456
481
|
// would fall back to ambient auth (env token / `gh`) or an
|
|
457
482
|
// unauthenticated Octokit, and every host GitHub call would 404.
|
|
458
483
|
hostGithubProxyResolver = createCursorGithubProxyHostResolver({
|
|
459
|
-
getApiKey:
|
|
484
|
+
getApiKey: requireGithubApiKey,
|
|
460
485
|
transport: proxyTransport,
|
|
461
486
|
});
|
|
462
487
|
logger(
|
|
@@ -496,7 +521,12 @@ export async function startServer(
|
|
|
496
521
|
}
|
|
497
522
|
const sdkRunner =
|
|
498
523
|
options.runner ??
|
|
499
|
-
new CursorSdkRunner({
|
|
524
|
+
new CursorSdkRunner({
|
|
525
|
+
...(options.apiKey === undefined || options.apiKey.trim() === ""
|
|
526
|
+
? {}
|
|
527
|
+
: { apiKey: options.apiKey }),
|
|
528
|
+
logger,
|
|
529
|
+
});
|
|
500
530
|
// Grok Bot turns run on Cursor's hosted Grok Bot (Sand) harness through
|
|
501
531
|
// the /v0/grokbot session API; the SDK side is a thin remote client. The
|
|
502
532
|
// dispatching runner is only interposed when a mount needs it. An
|
|
@@ -521,7 +551,16 @@ export async function startServer(
|
|
|
521
551
|
if (hasGrokBotMounts && options.runner === undefined) {
|
|
522
552
|
runner = new RuntimeDispatchingRunner({
|
|
523
553
|
sdkRunner,
|
|
524
|
-
grokbot: {
|
|
554
|
+
grokbot: {
|
|
555
|
+
...(options.apiKey === undefined || options.apiKey.trim() === ""
|
|
556
|
+
? {}
|
|
557
|
+
: { apiKey: options.apiKey }),
|
|
558
|
+
// `/v0/grokbot` lives on the external API (api.cursor.com), not
|
|
559
|
+
// api2. Prefer that default over the account key's backendUrl.
|
|
560
|
+
// Do not pass stored login as apiKey: that would pin it as an
|
|
561
|
+
// option and beat a later CURSOR_API_KEY_FILE bind.
|
|
562
|
+
backendUrl: cursorExternalApiUrl(),
|
|
563
|
+
},
|
|
525
564
|
});
|
|
526
565
|
logger(
|
|
527
566
|
"[agent-sdk] grokbot runtime: remote client (turns run on the hosted Grok Bot harness)"
|
|
@@ -559,15 +598,21 @@ export async function startServer(
|
|
|
559
598
|
}
|
|
560
599
|
let accountBridge: CursorAccountMcpBridge | undefined;
|
|
561
600
|
if (accountRefsBySlug.size > 0) {
|
|
562
|
-
if (accountKey === undefined) {
|
|
601
|
+
if (accountKey === undefined && options.allowAnonymous !== true) {
|
|
563
602
|
throw new Error(
|
|
564
603
|
`This project has Cursor account MCP connections (defineConnection({ cursorAccount: true })) but the host is not signed in to Cursor. ${SIGN_IN_HINT}`
|
|
565
604
|
);
|
|
566
605
|
}
|
|
606
|
+
if (accountKey === undefined) {
|
|
607
|
+
logger(
|
|
608
|
+
"[agent-sdk] Cursor account MCP: listening unsigned; credentials bind at task via CURSOR_API_KEY or CURSOR_API_KEY_FILE"
|
|
609
|
+
);
|
|
610
|
+
}
|
|
567
611
|
accountBridge = new CursorAccountMcpBridge({
|
|
568
612
|
client: new CursorBackendClient({
|
|
569
|
-
backendUrl: accountKey
|
|
570
|
-
apiKey: accountKey
|
|
613
|
+
backendUrl: accountKey?.backendUrl ?? cursorBackendUrl(),
|
|
614
|
+
apiKey: accountKey?.apiKey ?? "",
|
|
615
|
+
getApiKey: () => liveCursorApiKey() ?? "",
|
|
571
616
|
logger,
|
|
572
617
|
}),
|
|
573
618
|
logger,
|
|
@@ -1035,8 +1080,13 @@ export async function startServer(
|
|
|
1035
1080
|
? undefined
|
|
1036
1081
|
: { authorization: `Bearer ${options.authToken}` };
|
|
1037
1082
|
if (options.cloudToolsUrl !== undefined && headers === undefined) {
|
|
1038
|
-
|
|
1039
|
-
|
|
1083
|
+
if (options.allowAnonymous !== true) {
|
|
1084
|
+
throw new Error(
|
|
1085
|
+
`Agent "${runtime.project.name}" needs a Cursor API key to authenticate --cloud-tools-url. ${SIGN_IN_HINT}`
|
|
1086
|
+
);
|
|
1087
|
+
}
|
|
1088
|
+
logger(
|
|
1089
|
+
`[agent-sdk] --cloud-tools-url: listening unsigned; Bearer is taken from the key present at start`
|
|
1040
1090
|
);
|
|
1041
1091
|
}
|
|
1042
1092
|
runtime.engine.setCloudServerToolsConnection({
|
|
@@ -2509,6 +2559,12 @@ function startCursorDeploymentRelay(input: {
|
|
|
2509
2559
|
return undefined;
|
|
2510
2560
|
}
|
|
2511
2561
|
if (accountKey === undefined) {
|
|
2562
|
+
if (input.options.allowAnonymous === true) {
|
|
2563
|
+
logger(
|
|
2564
|
+
"[agent-sdk] deployment-events: skipped while unsigned; long-poll relays need a key at start"
|
|
2565
|
+
);
|
|
2566
|
+
return undefined;
|
|
2567
|
+
}
|
|
2512
2568
|
throw new Error(
|
|
2513
2569
|
`This project has channels subscribed to deployment events (deploymentsChannel({ deploySourceUris })) but the host is not signed in to Cursor. ${SIGN_IN_HINT}`
|
|
2514
2570
|
);
|
|
@@ -2591,6 +2647,12 @@ async function startCursorSlackRelay(input: {
|
|
|
2591
2647
|
return undefined;
|
|
2592
2648
|
}
|
|
2593
2649
|
if (accountKey === undefined) {
|
|
2650
|
+
if (options.allowAnonymous === true) {
|
|
2651
|
+
logger(
|
|
2652
|
+
"[agent-sdk] cursor-slack: skipped while unsigned; long-poll relays need a key at start"
|
|
2653
|
+
);
|
|
2654
|
+
return undefined;
|
|
2655
|
+
}
|
|
2594
2656
|
throw new Error(
|
|
2595
2657
|
`This project has Slack channels using the Cursor account connection (slackChannel({ cursorAccount: true })) but the host is not signed in to Cursor. ${SIGN_IN_HINT}`
|
|
2596
2658
|
);
|
|
@@ -925,6 +925,51 @@ export class SessionEngine {
|
|
|
925
925
|
return this.channelSession(record.sessionId, record, true, false, since);
|
|
926
926
|
}
|
|
927
927
|
|
|
928
|
+
/**
|
|
929
|
+
* Atomically validate and rotate an HTTP follow-up credential, then admit
|
|
930
|
+
* the message to its exact session without changing the owning channel key.
|
|
931
|
+
*/
|
|
932
|
+
async followUpHttp(
|
|
933
|
+
sessionId: string,
|
|
934
|
+
token: { channelId: string; key: string },
|
|
935
|
+
message: string
|
|
936
|
+
): Promise<string | undefined> {
|
|
937
|
+
const next = newContinuationKey();
|
|
938
|
+
const stale = new Error("stale HTTP continuation");
|
|
939
|
+
let previous: string | undefined;
|
|
940
|
+
try {
|
|
941
|
+
await this.updateRecord(sessionId, (record) => {
|
|
942
|
+
const expectedChannel =
|
|
943
|
+
record.httpContinuationKey === undefined
|
|
944
|
+
? record.channelId
|
|
945
|
+
: HTTP_CHANNEL_ID;
|
|
946
|
+
const expectedKey =
|
|
947
|
+
record.httpContinuationKey ?? record.continuationKey;
|
|
948
|
+
if (token.channelId !== expectedChannel || token.key !== expectedKey) {
|
|
949
|
+
throw stale;
|
|
950
|
+
}
|
|
951
|
+
previous = record.httpContinuationKey;
|
|
952
|
+
return { ...record, httpContinuationKey: next };
|
|
953
|
+
});
|
|
954
|
+
} catch (error) {
|
|
955
|
+
if (error === stale) {
|
|
956
|
+
return undefined;
|
|
957
|
+
}
|
|
958
|
+
throw error;
|
|
959
|
+
}
|
|
960
|
+
try {
|
|
961
|
+
await this.startTurn(sessionId, message);
|
|
962
|
+
return next;
|
|
963
|
+
} catch (error) {
|
|
964
|
+
await this.updateRecord(sessionId, (record) =>
|
|
965
|
+
record.httpContinuationKey === next
|
|
966
|
+
? { ...record, httpContinuationKey: previous }
|
|
967
|
+
: record
|
|
968
|
+
);
|
|
969
|
+
throw error;
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
|
|
928
973
|
/** Whether a continuation token already maps to a session on this channel. */
|
|
929
974
|
async hasContinuationSession(
|
|
930
975
|
channelId: string,
|
|
@@ -3315,12 +3360,17 @@ export class SessionEngine {
|
|
|
3315
3360
|
createdAt: record.createdAt,
|
|
3316
3361
|
updatedAt: record.updatedAt,
|
|
3317
3362
|
continuationToken:
|
|
3318
|
-
record.
|
|
3319
|
-
?
|
|
3320
|
-
|
|
3321
|
-
record.
|
|
3322
|
-
|
|
3323
|
-
|
|
3363
|
+
record.httpContinuationKey !== undefined
|
|
3364
|
+
? formatContinuationToken(
|
|
3365
|
+
HTTP_CHANNEL_ID,
|
|
3366
|
+
record.httpContinuationKey
|
|
3367
|
+
)
|
|
3368
|
+
: record.continuationKey === null
|
|
3369
|
+
? null
|
|
3370
|
+
: formatContinuationToken(
|
|
3371
|
+
record.channelId,
|
|
3372
|
+
record.continuationKey
|
|
3373
|
+
),
|
|
3324
3374
|
externalUrl: links.slack ?? links.github,
|
|
3325
3375
|
prUrl: links.github,
|
|
3326
3376
|
};
|
|
@@ -3606,8 +3656,8 @@ export class SessionEngine {
|
|
|
3606
3656
|
...current,
|
|
3607
3657
|
continuationKey: token,
|
|
3608
3658
|
}));
|
|
3609
|
-
// Keep armed reminders addressed at the conversation across
|
|
3610
|
-
//
|
|
3659
|
+
// Keep armed reminders addressed at the conversation across channel
|
|
3660
|
+
// continuation rotation.
|
|
3611
3661
|
if (
|
|
3612
3662
|
previous?.continuationKey != null &&
|
|
3613
3663
|
token !== null &&
|
package/src/reminders.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Runtime reminders — per-session durable wakes.
|
|
3
3
|
*
|
|
4
4
|
* ```ts
|
|
5
|
-
* import type { ReminderCreateInput } from "@
|
|
5
|
+
* import type { ReminderCreateInput } from "@cursor/july/reminders";
|
|
6
6
|
*
|
|
7
7
|
* // Recurring ≈ setInterval; one-shot ≈ setTimeout.
|
|
8
8
|
* await host.reminders?.create({
|
package/src/schedules.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* handler form hands work off to a channel (and can call MCP via `args.host.mcp`):
|
|
7
7
|
*
|
|
8
8
|
* ```ts
|
|
9
|
-
* import { defineSchedule } from "@
|
|
9
|
+
* import { defineSchedule } from "@cursor/july/schedules";
|
|
10
10
|
*
|
|
11
11
|
* export default defineSchedule({
|
|
12
12
|
* cron: "0 9 * * 1-5",
|
package/src/skills.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* content or inline sibling files:
|
|
8
8
|
*
|
|
9
9
|
* ```ts
|
|
10
|
-
* import { defineSkill } from "@
|
|
10
|
+
* import { defineSkill } from "@cursor/july/skills";
|
|
11
11
|
*
|
|
12
12
|
* export default defineSkill({
|
|
13
13
|
* description: "Research unfamiliar topics before answering.",
|
package/src/storage.ts
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* not as required-or-lose-history hooks:
|
|
17
17
|
*
|
|
18
18
|
* ```ts
|
|
19
|
-
* import { defineStorage } from "@
|
|
19
|
+
* import { defineStorage } from "@cursor/july/storage";
|
|
20
20
|
*
|
|
21
21
|
* export default defineStorage({
|
|
22
22
|
* put: (key, value) => db.upsert(key, value),
|
package/src/tools.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* name the model sees. Export the definition as the module's default export:
|
|
6
6
|
*
|
|
7
7
|
* ```ts
|
|
8
|
-
* import { defineTool } from "@
|
|
8
|
+
* import { defineTool } from "@cursor/july/tools";
|
|
9
9
|
* import { z } from "zod";
|
|
10
10
|
*
|
|
11
11
|
* // Runs in-process on the agent-serve host (default). Authored MCP
|
package/src/types.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Public types for @
|
|
2
|
+
* Public types for @cursor/july.
|
|
3
3
|
*
|
|
4
4
|
* The framework is filesystem-first: customers author an agent as files under
|
|
5
5
|
* an `agent/` directory (markdown for prose, TypeScript for typed behavior),
|
|
@@ -1201,10 +1201,8 @@ export type ConnectionConfig = (
|
|
|
1201
1201
|
*
|
|
1202
1202
|
* Derive the identity from durable session facts — `session.auth`,
|
|
1203
1203
|
* `session.id`, or your channel's own session state. Do **not** key it
|
|
1204
|
-
* off `session.continuationKey`:
|
|
1205
|
-
*
|
|
1206
|
-
* keyed on it silently breaks mid-conversation. (Channels that mint
|
|
1207
|
-
* stable, parseable tokens by design are the exception.)
|
|
1204
|
+
* off `session.continuationKey`: it is a channel routing key, and channels
|
|
1205
|
+
* may re-key it independently of the authenticated principal.
|
|
1208
1206
|
*
|
|
1209
1207
|
* Works attached or advertised. Advertised connections
|
|
1210
1208
|
* ({@link advertiseTools}) open per-operation clients with the
|
|
@@ -1593,6 +1591,11 @@ export interface SessionRecord {
|
|
|
1593
1591
|
abs?: Record<string, string | null>;
|
|
1594
1592
|
/** Channel-local continuation key; null when the session is not addressable. */
|
|
1595
1593
|
continuationKey: string | null;
|
|
1594
|
+
/**
|
|
1595
|
+
* Rotating HTTP follow-up credential for a channel-owned session.
|
|
1596
|
+
* Omitted until HTTP accepts the first follow-up.
|
|
1597
|
+
*/
|
|
1598
|
+
httpContinuationKey?: string;
|
|
1596
1599
|
auth: AuthContext | null;
|
|
1597
1600
|
title?: string;
|
|
1598
1601
|
channelState?: JsonValue;
|
|
@@ -1668,7 +1671,7 @@ export interface SessionSummary {
|
|
|
1668
1671
|
queued?: boolean;
|
|
1669
1672
|
createdAt: string;
|
|
1670
1673
|
updatedAt: string;
|
|
1671
|
-
/**
|
|
1674
|
+
/** Active wire token for HTTP follow-ups, or null when not addressable. */
|
|
1672
1675
|
continuationToken: string | null;
|
|
1673
1676
|
/**
|
|
1674
1677
|
* Conversation permalink (Slack thread, else GitHub PR).
|
|
@@ -2690,7 +2693,7 @@ export interface DiscoveredHook {
|
|
|
2690
2693
|
/** Live A/B metrics experiment (`agent/ab.ts` or `agent/ab/<name>.ts`). */
|
|
2691
2694
|
export interface DiscoveredAB {
|
|
2692
2695
|
name: string;
|
|
2693
|
-
/** Branded `defineAB({ ... })` config (see `@
|
|
2696
|
+
/** Branded `defineAB({ ... })` config (see `@cursor/july/ab`). */
|
|
2694
2697
|
definition: BrandedDefinition<"ab">;
|
|
2695
2698
|
}
|
|
2696
2699
|
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Security help
|
|
2
|
+
|
|
3
|
+
Answers security questions in Slack from your FAQ files and takes a first
|
|
4
|
+
look when someone pastes a GitHub pull request.
|
|
5
|
+
|
|
6
|
+
```bash
|
|
7
|
+
npx @cursor/july init ./security-help --template security-help
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
`init` asks which repos it may read. Skip the prompt with
|
|
11
|
+
`--var repos=owner/repo`.
|
|
12
|
+
|
|
13
|
+
## Run
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
agent-sdk login
|
|
17
|
+
agent-sdk slack create --name "Security Help" --channel-posts
|
|
18
|
+
agent-sdk dev
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Slack is a dedicated bot (`@Security Help`). Mentions, DMs, and channel
|
|
22
|
+
watch go through that app. GitHub reads use your Cursor GitHub connection
|
|
23
|
+
for the repos in `agent/lib/repos.ts`. Paste a PR URL in Slack, or replay
|
|
24
|
+
one in the playground.
|
|
25
|
+
|
|
26
|
+
## Edit
|
|
27
|
+
|
|
28
|
+
- `agent/lib/repos.ts`: repos it may read
|
|
29
|
+
- `agent/channels/slack.ts`: channel ids to watch (`watch`)
|
|
30
|
+
- `agent/knowledge/faq/`: answers for your company
|
|
31
|
+
- `agent/skills/`: how to look at a PR, a leak, or an access ask
|
|
32
|
+
- `agent/instructions.md`: routing
|
|
33
|
+
|
|
34
|
+
`--channel-posts` is required to watch channels. Mentions and DMs work
|
|
35
|
+
without it.
|
|
36
|
+
|
|
37
|
+
`agent-sdk eval` runs three smoke turns and writes nothing to Slack or GitHub.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { defineAgent } from "@cursor/july";
|
|
2
|
+
|
|
3
|
+
export default defineAgent({
|
|
4
|
+
name: "Security Help",
|
|
5
|
+
description:
|
|
6
|
+
"Answers security questions in Slack and takes a first look at a GitHub pull request.",
|
|
7
|
+
model: {
|
|
8
|
+
id: "grok-4.6",
|
|
9
|
+
params: [
|
|
10
|
+
{ id: "effort", value: "high" },
|
|
11
|
+
{ id: "fast", value: "true" },
|
|
12
|
+
],
|
|
13
|
+
},
|
|
14
|
+
tools: ["read", "grep"],
|
|
15
|
+
local: {
|
|
16
|
+
sandbox: true,
|
|
17
|
+
},
|
|
18
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { githubChannel } from "@cursor/july/channels/github";
|
|
2
|
+
import { REPOS } from "../lib/repos.js";
|
|
3
|
+
|
|
4
|
+
export default githubChannel({
|
|
5
|
+
webhookEvents: [],
|
|
6
|
+
deliverReplies: false,
|
|
7
|
+
cursorAccount: {
|
|
8
|
+
repos: REPOS,
|
|
9
|
+
permissions: "read",
|
|
10
|
+
},
|
|
11
|
+
onPullRequest: () => null,
|
|
12
|
+
onComment: () => null,
|
|
13
|
+
});
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import {
|
|
2
|
+
defaultSlackAuth,
|
|
3
|
+
extractGithubPrRef,
|
|
4
|
+
type SlackMessageHandler,
|
|
5
|
+
slackChannel,
|
|
6
|
+
} from "@cursor/july/channels/slack";
|
|
7
|
+
import { loadPrFiles } from "../lib/pr-first-pass.js";
|
|
8
|
+
import { REPOS, watches } from "../lib/repos.js";
|
|
9
|
+
|
|
10
|
+
const watch: string[] = [];
|
|
11
|
+
|
|
12
|
+
const clear = {
|
|
13
|
+
"pr/meta.md": "",
|
|
14
|
+
"pr/diff.patch": "",
|
|
15
|
+
"pr/head.sha": "",
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const handleSlack: SlackMessageHandler = async (ctx, message) => {
|
|
19
|
+
const auth = defaultSlackAuth(message, ctx);
|
|
20
|
+
if (auth === null) {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const pr = extractGithubPrRef(message.markdown);
|
|
25
|
+
if (pr === undefined) {
|
|
26
|
+
return { auth };
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const title = `Security Help ${pr.label}`;
|
|
30
|
+
const fullName = `${pr.owner}/${pr.repo}`;
|
|
31
|
+
if (!watches(fullName)) {
|
|
32
|
+
return {
|
|
33
|
+
auth,
|
|
34
|
+
title,
|
|
35
|
+
workspaceFiles: clear,
|
|
36
|
+
context: [
|
|
37
|
+
`Security help can only fetch ${REPOS.join(", ")} (got ${fullName}).`,
|
|
38
|
+
],
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const loaded = await loadPrFiles({
|
|
43
|
+
github: ctx.host.github,
|
|
44
|
+
ref: pr,
|
|
45
|
+
});
|
|
46
|
+
return {
|
|
47
|
+
auth,
|
|
48
|
+
title,
|
|
49
|
+
workspaceFiles: loaded ?? clear,
|
|
50
|
+
context:
|
|
51
|
+
loaded === undefined
|
|
52
|
+
? ["Could not fetch the pull request. Connect GitHub or check the URL."]
|
|
53
|
+
: undefined,
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export default slackChannel({
|
|
58
|
+
envPrefix: "SECURITY_HELP",
|
|
59
|
+
policy: {
|
|
60
|
+
blockExternals: true,
|
|
61
|
+
},
|
|
62
|
+
engagement: {
|
|
63
|
+
channelPosts:
|
|
64
|
+
watch.length === 0
|
|
65
|
+
? undefined
|
|
66
|
+
: {
|
|
67
|
+
allow: watch,
|
|
68
|
+
posts: "top-level" as const,
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
onAppMention: handleSlack,
|
|
72
|
+
onDirectMessage: handleSlack,
|
|
73
|
+
onChannelPost: watch.length === 0 ? undefined : handleSlack,
|
|
74
|
+
suggestedPrompts: [
|
|
75
|
+
{
|
|
76
|
+
title: "Look at a PR",
|
|
77
|
+
message: "First look at https://github.com/owner/repo/pull/1",
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
title: "How urgent",
|
|
81
|
+
message: "How urgent is this?",
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
title: "Ask for context",
|
|
85
|
+
message: "What else do we need before answering?",
|
|
86
|
+
},
|
|
87
|
+
],
|
|
88
|
+
suggestedPromptsTitle: "Ask security",
|
|
89
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Security help
|
|
2
|
+
|
|
3
|
+
Answer security questions in Slack from the FAQ and skills.
|
|
4
|
+
If you do not know, say so and ask a human.
|
|
5
|
+
|
|
6
|
+
Open the skill or FAQ for the ask. Those files are under `agent/skills/` and `agent/knowledge/faq/`.
|
|
7
|
+
|
|
8
|
+
| If the ask is about | Open |
|
|
9
|
+
| --- | --- |
|
|
10
|
+
| A GitHub pull request | `agent/skills/security-pr-first-pass.md` |
|
|
11
|
+
| An access request | `agent/skills/access-request.md` |
|
|
12
|
+
| A leak, alert, or incident | `agent/skills/security-playbooks.md` |
|
|
13
|
+
| Who can approve, privacy, or policy | `agent/knowledge/faq/approvals.md` |
|
|
14
|
+
| Phishing text, email, or a call | `agent/knowledge/faq/phishing.md` |
|
|
15
|
+
| Which team or channel owns a request | `agent/knowledge/faq/channels.md` |
|
|
16
|
+
| Another security question | `agent/skills/security-first-pass.md` |
|
|
17
|
+
|
|
18
|
+
A pull request earlier in the thread is not this one.
|
|
19
|
+
|
|
20
|
+
If you say an incident is over or a system is safe, show why. Looking at a pull request is not that.
|