@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
|
@@ -296,6 +296,12 @@ async function parseRpcResponse(
|
|
|
296
296
|
export interface CursorBackendClientOptions {
|
|
297
297
|
backendUrl: string;
|
|
298
298
|
apiKey: string;
|
|
299
|
+
/**
|
|
300
|
+
* Re-read the key on each authenticated call. Hosted freeze listens
|
|
301
|
+
* unsigned and the binder drops the key after restore; a constructor-frozen
|
|
302
|
+
* key would miss that bind.
|
|
303
|
+
*/
|
|
304
|
+
getApiKey?: () => string;
|
|
299
305
|
logger?: (line: string) => void;
|
|
300
306
|
/** Test seam; defaults to global fetch. */
|
|
301
307
|
fetchImpl?: typeof fetch;
|
|
@@ -303,21 +309,26 @@ export interface CursorBackendClientOptions {
|
|
|
303
309
|
|
|
304
310
|
export class CursorBackendClient {
|
|
305
311
|
private readonly backendUrl: string;
|
|
306
|
-
private readonly
|
|
312
|
+
private readonly resolveApiKey: () => string;
|
|
307
313
|
private readonly logger: (line: string) => void;
|
|
308
314
|
private readonly fetchImpl: typeof fetch;
|
|
309
315
|
private token: { value: string; expiresAtMs: number } | undefined;
|
|
310
316
|
private tokenExchange: Promise<string> | undefined;
|
|
317
|
+
private lastExchangedApiKey: string | undefined;
|
|
311
318
|
|
|
312
319
|
constructor(options: CursorBackendClientOptions) {
|
|
313
320
|
this.backendUrl = options.backendUrl.endsWith("/")
|
|
314
321
|
? options.backendUrl.slice(0, -1)
|
|
315
322
|
: options.backendUrl;
|
|
316
|
-
this.
|
|
323
|
+
this.resolveApiKey = options.getApiKey ?? (() => options.apiKey);
|
|
317
324
|
this.logger = options.logger ?? (() => {});
|
|
318
325
|
this.fetchImpl = options.fetchImpl ?? fetch;
|
|
319
326
|
}
|
|
320
327
|
|
|
328
|
+
private currentApiKey(): string {
|
|
329
|
+
return this.resolveApiKey().trim();
|
|
330
|
+
}
|
|
331
|
+
|
|
321
332
|
/** Who this API key acts as. */
|
|
322
333
|
async getMe(): Promise<CursorIdentity> {
|
|
323
334
|
return getMeResponseSchema.parse(await this.rpc("GetMe", {}));
|
|
@@ -443,7 +454,7 @@ export class CursorBackendClient {
|
|
|
443
454
|
method: "POST",
|
|
444
455
|
headers: {
|
|
445
456
|
"content-type": "application/json",
|
|
446
|
-
authorization: `Bearer ${this.
|
|
457
|
+
authorization: `Bearer ${this.currentApiKey()}`,
|
|
447
458
|
},
|
|
448
459
|
body: JSON.stringify({ repos: [...repos], permissions }),
|
|
449
460
|
signal: AbortSignal.timeout(30_000),
|
|
@@ -525,6 +536,18 @@ export class CursorBackendClient {
|
|
|
525
536
|
* when none is cached or it is near expiry.
|
|
526
537
|
*/
|
|
527
538
|
private getAccessToken(): Promise<string> {
|
|
539
|
+
const apiKey = this.currentApiKey();
|
|
540
|
+
if (apiKey === "") {
|
|
541
|
+
return Promise.reject(
|
|
542
|
+
new CursorBackendError(
|
|
543
|
+
"The Cursor backend client has no API key yet. Bind CURSOR_API_KEY or CURSOR_API_KEY_FILE before authenticated calls."
|
|
544
|
+
)
|
|
545
|
+
);
|
|
546
|
+
}
|
|
547
|
+
if (this.lastExchangedApiKey !== apiKey) {
|
|
548
|
+
this.token = undefined;
|
|
549
|
+
this.tokenExchange = undefined;
|
|
550
|
+
}
|
|
528
551
|
if (
|
|
529
552
|
this.token !== undefined &&
|
|
530
553
|
Date.now() < this.token.expiresAtMs - TOKEN_EXPIRY_LEEWAY_MS
|
|
@@ -541,13 +564,14 @@ export class CursorBackendClient {
|
|
|
541
564
|
}
|
|
542
565
|
|
|
543
566
|
private async exchangeApiKey(): Promise<string> {
|
|
567
|
+
const apiKey = this.currentApiKey();
|
|
544
568
|
let response: Response;
|
|
545
569
|
try {
|
|
546
570
|
response = await this.fetchImpl(`${this.backendUrl}${EXCHANGE_PATH}`, {
|
|
547
571
|
method: "POST",
|
|
548
572
|
headers: {
|
|
549
573
|
"content-type": "application/json",
|
|
550
|
-
authorization: `Bearer ${
|
|
574
|
+
authorization: `Bearer ${apiKey}`,
|
|
551
575
|
},
|
|
552
576
|
body: "{}",
|
|
553
577
|
signal: AbortSignal.timeout(30_000),
|
|
@@ -576,6 +600,7 @@ export class CursorBackendClient {
|
|
|
576
600
|
value: body.data.accessToken,
|
|
577
601
|
expiresAtMs: jwtExpiryMs(body.data.accessToken),
|
|
578
602
|
};
|
|
603
|
+
this.lastExchangedApiKey = apiKey;
|
|
579
604
|
this.logger("[agent-sdk] cursor account: minted a fresh access token");
|
|
580
605
|
return body.data.accessToken;
|
|
581
606
|
}
|
|
@@ -9,6 +9,10 @@
|
|
|
9
9
|
* dashboard-revocable user API key — only the key is stored.
|
|
10
10
|
* - `CURSOR_API_KEY` (or `serve({ apiKey })`) wins over the stored key, so
|
|
11
11
|
* CI and hosted deployments stay env-driven.
|
|
12
|
+
* - `CURSOR_API_KEY_FILE` (or the hosted default path) is next: freeze bind
|
|
13
|
+
* drops the key at task time without restarting July.
|
|
14
|
+
* - Stored `july login` is last. Same order for hosted and self-hosted:
|
|
15
|
+
* option → env → file → login.
|
|
12
16
|
*
|
|
13
17
|
* There is deliberately no session-token storage, refresh-token rotation, or
|
|
14
18
|
* cross-tool credential sharing here: short-lived access tokens are minted
|
|
@@ -16,6 +20,7 @@
|
|
|
16
20
|
*/
|
|
17
21
|
|
|
18
22
|
import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
23
|
+
import { readFileSync } from "node:fs";
|
|
19
24
|
import { chmod, mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
20
25
|
import { homedir } from "node:os";
|
|
21
26
|
import { dirname, join } from "node:path";
|
|
@@ -43,10 +48,11 @@ export function cursorBackendUrl(): string {
|
|
|
43
48
|
|
|
44
49
|
/**
|
|
45
50
|
* External API base URL for routes served only by the external-api
|
|
46
|
-
* microlith (`/internal/agent-serve/*`, engine aliases).
|
|
47
|
-
* these are mounted on api.cursor.com and 404 on
|
|
48
|
-
* deploy surface needs its own default.
|
|
49
|
-
* overrides everything for local dev, where
|
|
51
|
+
* microlith (`/internal/agent-serve/*`, `/v0/grokbot/*`, engine aliases).
|
|
52
|
+
* In production these are mounted on api.cursor.com and 404 on
|
|
53
|
+
* api2.cursor.sh, so the deploy surface needs its own default.
|
|
54
|
+
* `CURSOR_API_BASE_URL` still overrides everything for local dev, where
|
|
55
|
+
* one server mounts all routes.
|
|
50
56
|
*/
|
|
51
57
|
export function cursorExternalApiUrl(): string {
|
|
52
58
|
return trimTrailingSlash(
|
|
@@ -100,20 +106,13 @@ export function credentialsFilePath(): string {
|
|
|
100
106
|
return join(configDirPath(), "credentials.json");
|
|
101
107
|
}
|
|
102
108
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
let raw: string;
|
|
107
|
-
try {
|
|
108
|
-
raw = await readFile(credentialsFilePath(), "utf8");
|
|
109
|
-
} catch {
|
|
110
|
-
return undefined;
|
|
111
|
-
}
|
|
109
|
+
function parseStoredCredentialsJson(
|
|
110
|
+
raw: string
|
|
111
|
+
): StoredCredentials | undefined {
|
|
112
112
|
let parsed: unknown;
|
|
113
113
|
try {
|
|
114
114
|
parsed = JSON.parse(raw) as unknown;
|
|
115
115
|
} catch {
|
|
116
|
-
// Corrupt file — treat as signed out; login rewrites it.
|
|
117
116
|
return undefined;
|
|
118
117
|
}
|
|
119
118
|
const credentials = storedCredentialsSchema.safeParse(parsed);
|
|
@@ -126,6 +125,28 @@ export async function readStoredCredentials(): Promise<
|
|
|
126
125
|
};
|
|
127
126
|
}
|
|
128
127
|
|
|
128
|
+
export function readStoredCredentialsSync(): StoredCredentials | undefined {
|
|
129
|
+
let raw: string;
|
|
130
|
+
try {
|
|
131
|
+
raw = readFileSync(credentialsFilePath(), "utf8");
|
|
132
|
+
} catch {
|
|
133
|
+
return undefined;
|
|
134
|
+
}
|
|
135
|
+
return parseStoredCredentialsJson(raw);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export async function readStoredCredentials(): Promise<
|
|
139
|
+
StoredCredentials | undefined
|
|
140
|
+
> {
|
|
141
|
+
let raw: string;
|
|
142
|
+
try {
|
|
143
|
+
raw = await readFile(credentialsFilePath(), "utf8");
|
|
144
|
+
} catch {
|
|
145
|
+
return undefined;
|
|
146
|
+
}
|
|
147
|
+
return parseStoredCredentialsJson(raw);
|
|
148
|
+
}
|
|
149
|
+
|
|
129
150
|
export async function writeStoredCredentials(
|
|
130
151
|
credentials: StoredCredentials
|
|
131
152
|
): Promise<void> {
|
|
@@ -148,10 +169,10 @@ export async function clearStoredCredentials(): Promise<boolean> {
|
|
|
148
169
|
}
|
|
149
170
|
|
|
150
171
|
// ============================================================================
|
|
151
|
-
// Resolution (option > env > stored login)
|
|
172
|
+
// Resolution (option > env > file > stored login)
|
|
152
173
|
// ============================================================================
|
|
153
174
|
|
|
154
|
-
export type ApiKeySource = "option" | "env" | "login";
|
|
175
|
+
export type ApiKeySource = "option" | "env" | "file" | "login";
|
|
155
176
|
|
|
156
177
|
export interface ResolvedApiKey {
|
|
157
178
|
apiKey: string;
|
|
@@ -160,15 +181,43 @@ export interface ResolvedApiKey {
|
|
|
160
181
|
}
|
|
161
182
|
|
|
162
183
|
/**
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
*
|
|
166
|
-
*
|
|
184
|
+
* Hosted task-bind path. Not a secret: the snapshot may name this path.
|
|
185
|
+
* The binder writes the key here after restore; July re-reads on each use.
|
|
186
|
+
* Override with `CURSOR_API_KEY_FILE`. A missing file is unsigned — self-hosted
|
|
187
|
+
* then uses `CURSOR_API_KEY` or stored login.
|
|
167
188
|
*/
|
|
168
|
-
export
|
|
189
|
+
export const DEFAULT_CURSOR_API_KEY_FILE: string =
|
|
190
|
+
"/run/cursor/secrets/CURSOR_API_KEY";
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Read `CURSOR_API_KEY_FILE` (or {@link DEFAULT_CURSOR_API_KEY_FILE} when
|
|
194
|
+
* unset). Missing/empty files are unsigned, not an error — freeze bake
|
|
195
|
+
* listens before the binder drops the key; self-hosted falls through to
|
|
196
|
+
* env or login.
|
|
197
|
+
*/
|
|
198
|
+
export function readApiKeyFromFile(filePath?: string): string | undefined {
|
|
199
|
+
const configured = filePath ?? process.env.CURSOR_API_KEY_FILE;
|
|
200
|
+
const path =
|
|
201
|
+
configured !== undefined && configured.trim() !== ""
|
|
202
|
+
? configured.trim()
|
|
203
|
+
: DEFAULT_CURSOR_API_KEY_FILE;
|
|
204
|
+
try {
|
|
205
|
+
const raw = readFileSync(path, "utf8").trim();
|
|
206
|
+
return raw === "" ? undefined : raw;
|
|
207
|
+
} catch {
|
|
208
|
+
return undefined;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* First present source wins. We define the order; operators do not.
|
|
214
|
+
* `--api-key` / `serve({ apiKey })` → `CURSOR_API_KEY` → `CURSOR_API_KEY_FILE`
|
|
215
|
+
* (hosted default path if unset) → stored `july login`.
|
|
216
|
+
*/
|
|
217
|
+
export function resolveApiKeySync(options?: {
|
|
169
218
|
apiKey?: string;
|
|
170
219
|
backendUrl?: string;
|
|
171
|
-
}):
|
|
220
|
+
}): ResolvedApiKey | undefined {
|
|
172
221
|
const backendUrl = options?.backendUrl ?? cursorBackendUrl();
|
|
173
222
|
if (options?.apiKey !== undefined && options.apiKey.trim() !== "") {
|
|
174
223
|
return { apiKey: options.apiKey.trim(), source: "option", backendUrl };
|
|
@@ -177,15 +226,29 @@ export async function resolveApiKey(options?: {
|
|
|
177
226
|
if (envKey !== undefined && envKey.trim() !== "") {
|
|
178
227
|
return { apiKey: envKey.trim(), source: "env", backendUrl };
|
|
179
228
|
}
|
|
180
|
-
const
|
|
229
|
+
const fileKey = readApiKeyFromFile();
|
|
230
|
+
if (fileKey !== undefined) {
|
|
231
|
+
return { apiKey: fileKey, source: "file", backendUrl };
|
|
232
|
+
}
|
|
233
|
+
const stored = readStoredCredentialsSync();
|
|
181
234
|
if (stored !== undefined && stored.backendUrl === backendUrl) {
|
|
182
235
|
return { apiKey: stored.apiKey, source: "login", backendUrl };
|
|
183
236
|
}
|
|
184
237
|
return undefined;
|
|
185
238
|
}
|
|
186
239
|
|
|
240
|
+
/**
|
|
241
|
+
* {@link resolveApiKeySync} as a Promise for call sites that already await.
|
|
242
|
+
*/
|
|
243
|
+
export async function resolveApiKey(options?: {
|
|
244
|
+
apiKey?: string;
|
|
245
|
+
backendUrl?: string;
|
|
246
|
+
}): Promise<ResolvedApiKey | undefined> {
|
|
247
|
+
return resolveApiKeySync(options);
|
|
248
|
+
}
|
|
249
|
+
|
|
187
250
|
/** One-line hint for "no credentials" errors, shared across surfaces. */
|
|
188
|
-
export const SIGN_IN_HINT: string = `Run \`${CLI_COMMAND_NAME} login\` (or set CURSOR_API_KEY / pass serve({ apiKey })).`;
|
|
251
|
+
export const SIGN_IN_HINT: string = `Run \`${CLI_COMMAND_NAME} login\` (or set CURSOR_API_KEY / CURSOR_API_KEY_FILE / pass serve({ apiKey })).`;
|
|
189
252
|
|
|
190
253
|
// ============================================================================
|
|
191
254
|
// PKCE browser login (mirrors cursor-agent / Sand)
|
|
@@ -255,6 +255,17 @@ export interface AgentkitDeployStatus {
|
|
|
255
255
|
export const TERMINAL_AGENTKIT_DEPLOY_STATUSES: ReadonlySet<AgentkitCustomerStatus> =
|
|
256
256
|
new Set(["running", "failed", "stopped"]);
|
|
257
257
|
|
|
258
|
+
/**
|
|
259
|
+
* `POST /internal/agentkit/deployments/:slug/stop` 202 body. Like v1
|
|
260
|
+
* {@link StopAccepted} but keyed by catalog ids instead of the numeric
|
|
261
|
+
* deployment row id.
|
|
262
|
+
*/
|
|
263
|
+
export interface AgentkitStopAccepted {
|
|
264
|
+
applicationId: string;
|
|
265
|
+
releaseId: string;
|
|
266
|
+
status: string;
|
|
267
|
+
}
|
|
268
|
+
|
|
258
269
|
/** One secret's metadata from the list endpoint — names only, never values. */
|
|
259
270
|
export interface SecretInfo {
|
|
260
271
|
name: string;
|
|
@@ -332,6 +343,14 @@ const agentkitDeployStatusSchema = z
|
|
|
332
343
|
})
|
|
333
344
|
.passthrough();
|
|
334
345
|
|
|
346
|
+
const agentkitStopAcceptedSchema = z
|
|
347
|
+
.object({
|
|
348
|
+
applicationId: z.string().min(1),
|
|
349
|
+
releaseId: z.string().min(1),
|
|
350
|
+
status: z.string(),
|
|
351
|
+
})
|
|
352
|
+
.passthrough();
|
|
353
|
+
|
|
335
354
|
const deploymentSchema = z.object({
|
|
336
355
|
id: z.number(),
|
|
337
356
|
slug: z.string(),
|
|
@@ -602,6 +621,22 @@ export class AgentServeDeployClient {
|
|
|
602
621
|
return agentkitDeployStatusSchema.parse(raw);
|
|
603
622
|
}
|
|
604
623
|
|
|
624
|
+
/**
|
|
625
|
+
* Stop a v2 deployment (`POST /internal/agentkit/deployments/:slug/stop`).
|
|
626
|
+
* 202 means accepted; poll {@link getAgentkitDeploy} until `stopped`.
|
|
627
|
+
*/
|
|
628
|
+
async stopAgentkit(args: {
|
|
629
|
+
teamId: number;
|
|
630
|
+
slug: string;
|
|
631
|
+
}): Promise<AgentkitStopAccepted> {
|
|
632
|
+
const raw = await this.request({
|
|
633
|
+
method: "POST",
|
|
634
|
+
path: `/internal/agentkit/deployments/${encodeURIComponent(args.slug)}/stop?teamId=${args.teamId}`,
|
|
635
|
+
context: { verb: "stop", slug: args.slug },
|
|
636
|
+
});
|
|
637
|
+
return agentkitStopAcceptedSchema.parse(raw);
|
|
638
|
+
}
|
|
639
|
+
|
|
605
640
|
async listDeployments(args: { teamId: number }): Promise<Deployment[]> {
|
|
606
641
|
const raw = await this.request({
|
|
607
642
|
method: "GET",
|
|
@@ -888,8 +923,12 @@ function mapErrorResponse(
|
|
|
888
923
|
);
|
|
889
924
|
}
|
|
890
925
|
case 409:
|
|
926
|
+
// The server's 409 body distinguishes real conflicts (CAS races,
|
|
927
|
+
// "still deploying", architecture-v2 slugs on the v1 surface); keep
|
|
928
|
+
// its message when present.
|
|
891
929
|
return new DeployApiError(
|
|
892
|
-
|
|
930
|
+
serverError ??
|
|
931
|
+
`A concurrent deploy or stop is changing deployment${slugPart}; retry in a moment.`,
|
|
893
932
|
409
|
|
894
933
|
);
|
|
895
934
|
case 429: {
|
|
@@ -40,7 +40,10 @@ import {
|
|
|
40
40
|
handshakeChannelContinuation,
|
|
41
41
|
} from "./continuation-channel.js";
|
|
42
42
|
import { CONTINUATION_SELECTORS } from "./continuation-identity.js";
|
|
43
|
-
import {
|
|
43
|
+
import {
|
|
44
|
+
projectInfo,
|
|
45
|
+
runtimeArchitectureCompatibilityError,
|
|
46
|
+
} from "./discovery.js";
|
|
44
47
|
import { packageVersion } from "./distribution.js";
|
|
45
48
|
|
|
46
49
|
export const DEPLOY_MANIFEST_VERSION: 1 = 1;
|
|
@@ -125,6 +128,12 @@ export function buildAgentDeployManifest(
|
|
|
125
128
|
project: AgentProject,
|
|
126
129
|
options?: { nowMs?: number; cliVersion?: string }
|
|
127
130
|
): AgentDeployManifestV1 {
|
|
131
|
+
const runtimeArchitectureError = runtimeArchitectureCompatibilityError(
|
|
132
|
+
project.agent
|
|
133
|
+
);
|
|
134
|
+
if (runtimeArchitectureError !== undefined) {
|
|
135
|
+
throw new Error(runtimeArchitectureError);
|
|
136
|
+
}
|
|
128
137
|
applyAgentContinuationDefaults(project);
|
|
129
138
|
const channels = project.channels.map((channel) => {
|
|
130
139
|
const handshake = handshakeChannelContinuation(channel);
|
|
@@ -524,6 +524,17 @@ async function loadAgent(
|
|
|
524
524
|
const hosting = resolveHosting(ctx, agentDir, config?.hosting);
|
|
525
525
|
const concurrency = resolveConcurrency(ctx, agentDir, config?.concurrency);
|
|
526
526
|
const architecture = resolveArchitecture(ctx, agentDir, config?.architecture);
|
|
527
|
+
const runtimeArchitectureError = runtimeArchitectureCompatibilityError({
|
|
528
|
+
runtime,
|
|
529
|
+
architecture,
|
|
530
|
+
});
|
|
531
|
+
if (runtimeArchitectureError !== undefined) {
|
|
532
|
+
ctx.diagnostics.push({
|
|
533
|
+
severity: "error",
|
|
534
|
+
path: displayPath(ctx, join(agentDir, "agent.ts")),
|
|
535
|
+
message: runtimeArchitectureError,
|
|
536
|
+
});
|
|
537
|
+
}
|
|
527
538
|
|
|
528
539
|
if (runtime === "cloud") {
|
|
529
540
|
warnCloudRuntimeLimitations(ctx, agentDir, {
|
|
@@ -570,6 +581,15 @@ async function loadAgent(
|
|
|
570
581
|
};
|
|
571
582
|
}
|
|
572
583
|
|
|
584
|
+
export function runtimeArchitectureCompatibilityError(agent: {
|
|
585
|
+
runtime: AgentRuntime;
|
|
586
|
+
architecture?: AgentArchitecture;
|
|
587
|
+
}): string | undefined {
|
|
588
|
+
return agent.architecture === "v2" && agent.runtime === "grokbot"
|
|
589
|
+
? 'architecture: "v2" cannot use runtime: "grokbot": the grokbot runtime executes through the signed-in account\'s hosted /v0/grokbot box, not a deployment-scoped v2 runtime.'
|
|
590
|
+
: undefined;
|
|
591
|
+
}
|
|
592
|
+
|
|
573
593
|
function resolveArchitecture(
|
|
574
594
|
ctx: DiscoveryContext,
|
|
575
595
|
agentDir: string,
|
|
@@ -2021,7 +2041,7 @@ async function loadABConfig(
|
|
|
2021
2041
|
severity: "error",
|
|
2022
2042
|
path: displayPath(ctx, path),
|
|
2023
2043
|
message:
|
|
2024
|
-
"ab.config.ts must default-export defineABConfig({ ... }) from @
|
|
2044
|
+
"ab.config.ts must default-export defineABConfig({ ... }) from @cursor/july/ab.",
|
|
2025
2045
|
});
|
|
2026
2046
|
return undefined;
|
|
2027
2047
|
}
|
|
@@ -81,6 +81,37 @@ export function packageVersion(): string {
|
|
|
81
81
|
return typeof parsed.version === "string" ? parsed.version : "0.0.0";
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
+
/** Facts `agent-sdk version` / `--version` print. */
|
|
85
|
+
export interface CliVersionInfo {
|
|
86
|
+
/** Published npm name (`@cursor/july`). */
|
|
87
|
+
name: string;
|
|
88
|
+
/** `package.json` version of this install. */
|
|
89
|
+
version: string;
|
|
90
|
+
/** Bin the process was invoked as (`agent-sdk` / `agent-serve`). */
|
|
91
|
+
cli: string;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export function cliVersionInfo(): CliVersionInfo {
|
|
95
|
+
return {
|
|
96
|
+
name: PACKAGE_NAME,
|
|
97
|
+
version: packageVersion(),
|
|
98
|
+
cli: CLI_COMMAND_NAME,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Text or JSON for `version` / `--version` / `-V`.
|
|
104
|
+
* Text is the bare `package.json` version (npm-style). `--json` is the
|
|
105
|
+
* complete `{ name, version, cli }` payload.
|
|
106
|
+
*/
|
|
107
|
+
export function formatCliVersion(options?: { json?: boolean }): string {
|
|
108
|
+
const info = cliVersionInfo();
|
|
109
|
+
if (options?.json === true) {
|
|
110
|
+
return `${JSON.stringify(info, null, 2)}\n`;
|
|
111
|
+
}
|
|
112
|
+
return `${info.version}\n`;
|
|
113
|
+
}
|
|
114
|
+
|
|
84
115
|
/**
|
|
85
116
|
* Authoring entry subpaths and their dist-relative output files — the
|
|
86
117
|
* runtime mirror of the package `exports` map (the source of truth;
|
|
@@ -479,7 +479,7 @@ function resolveEvalMaxConcurrency(config: Partial<EvalConfigFile>): number {
|
|
|
479
479
|
if (config.maxConcurrency === undefined) {
|
|
480
480
|
throw new Error(
|
|
481
481
|
`evals/evals.config.ts must define maxConcurrency (1–${EVAL_MAX_CONCURRENCY_LIMIT}; hard limit is due to model provider request limits). Example:\n` +
|
|
482
|
-
` import { defineEvalConfig } from "@
|
|
482
|
+
` import { defineEvalConfig } from "@cursor/july/evals";\n` +
|
|
483
483
|
` export default defineEvalConfig({ maxConcurrency: 20 });`
|
|
484
484
|
);
|
|
485
485
|
}
|
|
@@ -13,15 +13,21 @@
|
|
|
13
13
|
|
|
14
14
|
import { randomUUID } from "node:crypto";
|
|
15
15
|
import type { RunnerTurnRequest, TurnOutcome } from "../../types.js";
|
|
16
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
cursorExternalApiUrl,
|
|
18
|
+
resolveApiKeySync,
|
|
19
|
+
} from "../cursor/credentials.js";
|
|
17
20
|
import type { AgentRunner } from "./../sdk-runner.js";
|
|
18
21
|
|
|
19
22
|
export interface GrokBotRunnerOptions {
|
|
20
|
-
/** Cursor API key.
|
|
23
|
+
/** Cursor API key. Resolved as option → env → file → stored login. */
|
|
21
24
|
apiKey?: string;
|
|
22
25
|
/** Test seam. Defaults to global fetch. */
|
|
23
26
|
fetchImpl?: typeof fetch;
|
|
24
|
-
/**
|
|
27
|
+
/**
|
|
28
|
+
* Test seam. Defaults to {@link cursorExternalApiUrl} (`api.cursor.com`).
|
|
29
|
+
* `/v0/grokbot` is an external-api microlith route — it 404s on api2.
|
|
30
|
+
*/
|
|
25
31
|
backendUrl?: string;
|
|
26
32
|
/** Test seam. Poll interval while a turn runs. */
|
|
27
33
|
pollIntervalMs?: number;
|
|
@@ -89,14 +95,17 @@ class GrokBotApiClient {
|
|
|
89
95
|
|
|
90
96
|
constructor(options: GrokBotRunnerOptions) {
|
|
91
97
|
this.fetchImpl = options.fetchImpl ?? fetch;
|
|
92
|
-
this.baseUrl = (options.backendUrl ??
|
|
98
|
+
this.baseUrl = (options.backendUrl ?? cursorExternalApiUrl()).replace(
|
|
93
99
|
/\/$/,
|
|
94
100
|
""
|
|
95
101
|
);
|
|
96
|
-
const apiKey =
|
|
102
|
+
const apiKey = resolveApiKeySync({
|
|
103
|
+
apiKey: options.apiKey,
|
|
104
|
+
backendUrl: options.backendUrl,
|
|
105
|
+
})?.apiKey;
|
|
97
106
|
if (apiKey === undefined || apiKey === "") {
|
|
98
107
|
throw new Error(
|
|
99
|
-
'runtime: "grokbot" needs a Cursor API key (CURSOR_API_KEY or agent-sdk login) to reach the hosted Grok Bot harness.'
|
|
108
|
+
'runtime: "grokbot" needs a Cursor API key (CURSOR_API_KEY, CURSOR_API_KEY_FILE, or agent-sdk login) to reach the hosted Grok Bot harness.'
|
|
100
109
|
);
|
|
101
110
|
}
|
|
102
111
|
this.apiKey = apiKey;
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
* Continuation semantics: `POST /v1/session` returns a `continuationToken`;
|
|
8
8
|
* each accepted follow-up rotates it and returns the replacement, and a
|
|
9
9
|
* stale token is rejected with 409. Follow-ups address any chat session by
|
|
10
|
-
* id (including custom channels such as `drive`) when the token matches
|
|
11
|
-
*
|
|
10
|
+
* id (including custom channels such as `drive`) when the token matches its
|
|
11
|
+
* active HTTP follow-up key; task sessions stay fire-and-forget.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
import type {
|
|
@@ -20,11 +20,7 @@ import type {
|
|
|
20
20
|
SessionRecord,
|
|
21
21
|
} from "../types.js";
|
|
22
22
|
import { samePrincipal } from "./auth.js";
|
|
23
|
-
import {
|
|
24
|
-
formatContinuationToken,
|
|
25
|
-
newContinuationKey,
|
|
26
|
-
parseContinuationToken,
|
|
27
|
-
} from "./ids.js";
|
|
23
|
+
import { formatContinuationToken, parseContinuationToken } from "./ids.js";
|
|
28
24
|
import { isLoopbackAddress } from "./net.js";
|
|
29
25
|
import type { ServerRoute } from "./router.js";
|
|
30
26
|
import {
|
|
@@ -32,7 +28,6 @@ import {
|
|
|
32
28
|
ApprovalNotFoundError,
|
|
33
29
|
HTTP_CHANNEL_ID,
|
|
34
30
|
SessionAuthError,
|
|
35
|
-
SessionBusyError,
|
|
36
31
|
type SessionEngine,
|
|
37
32
|
} from "./session-engine.js";
|
|
38
33
|
import {
|
|
@@ -143,10 +138,8 @@ export function buildHttpChannelRoutes(args: {
|
|
|
143
138
|
`Unknown session ${sessionId}.`
|
|
144
139
|
);
|
|
145
140
|
}
|
|
146
|
-
//
|
|
147
|
-
//
|
|
148
|
-
// session's own continuation token. Task/schedule sessions stay
|
|
149
|
-
// fire-and-forget.
|
|
141
|
+
// HTTP can follow any chat session. Its credential is separate from the
|
|
142
|
+
// owning channel's continuation key.
|
|
150
143
|
if (record.mode === "task") {
|
|
151
144
|
return errorResponse(
|
|
152
145
|
409,
|
|
@@ -178,12 +171,7 @@ export function buildHttpChannelRoutes(args: {
|
|
|
178
171
|
);
|
|
179
172
|
}
|
|
180
173
|
const presented = parseContinuationToken(body.continuationToken);
|
|
181
|
-
if (
|
|
182
|
-
presented === null ||
|
|
183
|
-
presented.channelId !== record.channelId ||
|
|
184
|
-
record.continuationKey === null ||
|
|
185
|
-
presented.key !== record.continuationKey
|
|
186
|
-
) {
|
|
174
|
+
if (presented === null) {
|
|
187
175
|
return errorResponse(
|
|
188
176
|
409,
|
|
189
177
|
"stale_continuation_token",
|
|
@@ -192,34 +180,19 @@ export function buildHttpChannelRoutes(args: {
|
|
|
192
180
|
}
|
|
193
181
|
|
|
194
182
|
const message = await transformMessage(body.message, ctx.auth);
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
});
|
|
203
|
-
} catch (error) {
|
|
204
|
-
if (error instanceof SessionBusyError) {
|
|
205
|
-
return errorResponse(
|
|
206
|
-
409,
|
|
207
|
-
"session_busy",
|
|
208
|
-
"A turn is already running; wait for session.waiting before sending a follow-up."
|
|
209
|
-
);
|
|
210
|
-
}
|
|
211
|
-
throw error;
|
|
183
|
+
const rotated = await engine.followUpHttp(sessionId, presented, message);
|
|
184
|
+
if (rotated === undefined) {
|
|
185
|
+
return errorResponse(
|
|
186
|
+
409,
|
|
187
|
+
"stale_continuation_token",
|
|
188
|
+
"The continuation token does not address this session's active continuation."
|
|
189
|
+
);
|
|
212
190
|
}
|
|
213
|
-
|
|
214
|
-
// Rotate only after the message is accepted so a rejected send leaves
|
|
215
|
-
// the caller's token valid for retry.
|
|
216
|
-
const rotated = newContinuationKey();
|
|
217
|
-
await engine.setContinuationToken(sessionId, rotated);
|
|
218
191
|
return jsonResponse(
|
|
219
192
|
{
|
|
220
193
|
ok: true,
|
|
221
194
|
sessionId,
|
|
222
|
-
continuationToken: formatContinuationToken(
|
|
195
|
+
continuationToken: formatContinuationToken(HTTP_CHANNEL_ID, rotated),
|
|
223
196
|
},
|
|
224
197
|
{ headers: { [SESSION_ID_HEADER]: sessionId } }
|
|
225
198
|
);
|
|
@@ -6,6 +6,7 @@ import { spawn } from "node:child_process";
|
|
|
6
6
|
import { existsSync } from "node:fs";
|
|
7
7
|
import { mkdir, readdir, readFile, writeFile } from "node:fs/promises";
|
|
8
8
|
import { basename, dirname, join, relative, resolve } from "node:path";
|
|
9
|
+
import { runfiles } from "@bazel/runfiles";
|
|
9
10
|
import type { ModelSetting } from "../types.js";
|
|
10
11
|
import {
|
|
11
12
|
canonicalTemplateName,
|
|
@@ -75,6 +76,7 @@ const TEMPLATES: Readonly<Record<TemplateName, TemplateEntry>> = {
|
|
|
75
76
|
"agentic-owners": { dir: "agentic-owners" },
|
|
76
77
|
demo: { dir: "demo" },
|
|
77
78
|
"pr-autofixer": { dir: "pr-autofixer" },
|
|
79
|
+
"security-help": { dir: "security-help" },
|
|
78
80
|
"security-reviewer": { dir: "security-reviewer" },
|
|
79
81
|
"triage-linear": { dir: "triage", overlay: "linear" },
|
|
80
82
|
"triage-jira": { dir: "triage", overlay: "jira" },
|
|
@@ -103,7 +105,7 @@ export function resolveTemplate(name: string): TemplateResolution {
|
|
|
103
105
|
};
|
|
104
106
|
}
|
|
105
107
|
const entry = TEMPLATES[resolved];
|
|
106
|
-
const dir =
|
|
108
|
+
const dir = resolvePackagePath("templates", entry.dir);
|
|
107
109
|
return {
|
|
108
110
|
ok: true,
|
|
109
111
|
name: resolved,
|
|
@@ -115,6 +117,15 @@ export function resolveTemplate(name: string): TemplateResolution {
|
|
|
115
117
|
};
|
|
116
118
|
}
|
|
117
119
|
|
|
120
|
+
function resolvePackagePath(...segments: string[]): string {
|
|
121
|
+
if (runfiles.workspace !== undefined) {
|
|
122
|
+
return runfiles.resolveWorkspaceRelative(
|
|
123
|
+
["packages", "agent-serve", ...segments].join("/")
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
return join(packageRootDir(), ...segments);
|
|
127
|
+
}
|
|
128
|
+
|
|
118
129
|
export type InitTargetCheck = { ok: true } | { ok: false; message: string };
|
|
119
130
|
|
|
120
131
|
/**
|
|
@@ -699,6 +710,7 @@ Scaffold a project, then open the playground:
|
|
|
699
710
|
npx ${PACKAGE_NAME} init ./my-agent # installs deps + links agent-sdk onto PATH
|
|
700
711
|
npx ${PACKAGE_NAME} init ./my-demo --template demo # record a PR walkthrough
|
|
701
712
|
npx ${PACKAGE_NAME} init ./my-reviewer --template security-reviewer # review PRs for security bugs
|
|
713
|
+
npx ${PACKAGE_NAME} init ./security-help --template security-help # answer security questions in Slack
|
|
702
714
|
npx ${PACKAGE_NAME} init ./my-triage --template triage-linear # comment on Linear issues
|
|
703
715
|
npx ${PACKAGE_NAME} init ./my-triage --template triage-jira # comment on Jira issues
|
|
704
716
|
npx ${PACKAGE_NAME} init ./my-owners --template agentic-owners # review PRs via owners policies
|