@cursor/july 0.1.93 → 0.1.95
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 -20
- package/README.md +4 -26
- package/dist/channels/github/github-channel.d.ts.map +1 -1
- package/dist/channels/github/github-channel.js +14 -2
- package/dist/channels/github/types.d.ts +18 -3
- package/dist/channels/github/types.d.ts.map +1 -1
- package/dist/channels/origin/origin-channel.d.ts.map +1 -1
- package/dist/channels/origin/origin-channel.js +11 -3
- package/dist/channels/origin/origin-webhook.d.ts +11 -1
- package/dist/channels/origin/origin-webhook.d.ts.map +1 -1
- package/dist/channels/origin/origin-webhook.js +23 -3
- package/dist/channels/origin/types.d.ts +8 -0
- package/dist/channels/origin/types.d.ts.map +1 -1
- package/dist/channels/slack/attachments.js +2 -2
- package/dist/channels/slack/dispatch.d.ts +0 -7
- package/dist/channels/slack/dispatch.d.ts.map +1 -1
- package/dist/channels/slack/dispatch.js +4 -7
- package/dist/channels/slack/eval-directive.d.ts +5 -12
- package/dist/channels/slack/eval-directive.d.ts.map +1 -1
- package/dist/channels/slack/eval-directive.js +8 -19
- package/dist/channels/slack/index.d.ts +0 -6
- package/dist/channels/slack/index.d.ts.map +1 -1
- package/dist/channels/slack/index.js +0 -6
- package/dist/channels/slack/pr-ref.d.ts +7 -1
- package/dist/channels/slack/pr-ref.d.ts.map +1 -1
- package/dist/channels/slack/pr-ref.js +42 -23
- package/dist/channels/slack/setup.d.ts +4 -4
- package/dist/channels/slack/setup.d.ts.map +1 -1
- package/dist/channels/slack/setup.js +8 -15
- package/dist/channels/slack/slack-channel.d.ts +6 -13
- package/dist/channels/slack/slack-channel.d.ts.map +1 -1
- package/dist/channels/slack/slack-channel.js +15 -101
- package/dist/channels/slack/types.d.ts +12 -79
- package/dist/channels/slack/types.d.ts.map +1 -1
- package/dist/channels/slack/types.js +1 -15
- package/dist/client.d.ts +14 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +12 -0
- package/dist/connections.d.ts +18 -9
- package/dist/connections.d.ts.map +1 -1
- package/dist/connections.js +17 -8
- package/dist/docs/404.html +2 -2
- package/dist/docs/ab.html +4 -4
- package/dist/docs/assets/{app.CjWU-x0z.js → app.BBj0klBO.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.oqPawjiD.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.Cxy8ySFQ.js → VPLocalSearchBox.CUEXpL78.js} +1 -1
- package/dist/docs/assets/chunks/{theme.Dvq1Bktu.js → theme.DabmQnia.js} +2 -2
- package/dist/docs/assets/concepts.md.lwAgBIMI.js +1 -0
- package/dist/docs/assets/{deployment.md.DoLFAzfm.js → deployment.md.D9msOFOW.js} +3 -8
- package/dist/docs/assets/{deployment.md.DoLFAzfm.lean.js → deployment.md.D9msOFOW.lean.js} +1 -1
- package/dist/docs/assets/{guides_agent-to-agent.md.B3JIaAqz.js → guides_agent-to-agent.md.BDb0t1QV.js} +1 -1
- package/dist/docs/assets/guides_cloud-runtime.md.CkYbjnAX.js +9 -0
- package/dist/docs/assets/guides_cloud-runtime.md.CkYbjnAX.lean.js +1 -0
- package/dist/docs/assets/{guides_convert-automation.md.Bboisykk.js → guides_convert-automation.md.B4sjlodG.js} +1 -1
- package/dist/docs/assets/{guides_github.md.DqJhuaN1.js → guides_github.md.Cnh2mL4a.js} +1 -1
- package/dist/docs/assets/{guides_mcp-oauth.md.CJvrXtkN.js → guides_mcp-oauth.md.DPYmBCbV.js} +7 -9
- package/dist/docs/assets/{guides_mcp-oauth.md.CJvrXtkN.lean.js → guides_mcp-oauth.md.DPYmBCbV.lean.js} +1 -1
- package/dist/docs/assets/{guides_slack.md.mqeNKs84.js → guides_slack.md.C32HsdKk.js} +5 -11
- package/dist/docs/assets/guides_slack.md.C32HsdKk.lean.js +1 -0
- package/dist/docs/assets/index.md.BoHaMdeZ.js +5 -0
- package/dist/docs/assets/{index.md.B-lVR4wT.lean.js → index.md.BoHaMdeZ.lean.js} +1 -1
- package/dist/docs/assets/{quickstart.md.BrmfrrIr.js → quickstart.md.Nj_LjW_a.js} +1 -1
- package/dist/docs/assets/{reference_cli.md.D9KESDsD.js → reference_cli.md.BsMOxDvh.js} +4 -3
- package/dist/docs/assets/{reference_cli.md.D9KESDsD.lean.js → reference_cli.md.BsMOxDvh.lean.js} +1 -1
- package/dist/docs/assets/{reference_connections.md.DB6SsN6U.js → reference_connections.md.BH8Oc0D0.js} +5 -5
- package/dist/docs/assets/{reference_connections.md.DB6SsN6U.lean.js → reference_connections.md.BH8Oc0D0.lean.js} +1 -1
- package/dist/docs/assets/{reference_hooks.md.BxN87gCw.js → reference_hooks.md.a8BJxMR5.js} +1 -1
- package/dist/docs/assets/reference_http-api.md.D89k1mdm.js +11 -0
- package/dist/docs/assets/reference_http-api.md.D89k1mdm.lean.js +1 -0
- package/dist/docs/assets/reference_project-layout.md.Bv4KOtlB.js +19 -0
- package/dist/docs/assets/{reference_subagents.md.Xoav0AII.js → reference_subagents.md.CfsIloPm.js} +1 -1
- package/dist/docs/assets/{reference_tools.md.DuKvkYWG.js → reference_tools.md.BHeXn2id.js} +3 -3
- package/dist/docs/assets/{reference_tools.md.DuKvkYWG.lean.js → reference_tools.md.BHeXn2id.lean.js} +1 -1
- package/dist/docs/assets/{templates_agentic-owners.md.DqtPdm6f.js → templates_agentic-owners.md.BZSH4N9z.js} +1 -1
- package/dist/docs/assets/{templates_demo.md.DhFcWN6j.js → templates_demo.md.BeQX9V3H.js} +1 -1
- package/dist/docs/assets/{templates_pr-autofixer.md.R4K_qytS.js → templates_pr-autofixer.md.x5zl6-GT.js} +2 -2
- package/dist/docs/assets/{templates_pr-autofixer.md.R4K_qytS.lean.js → templates_pr-autofixer.md.x5zl6-GT.lean.js} +1 -1
- package/dist/docs/assets/templates_security-help.md.C3Ny_Qr2.js +4 -0
- package/dist/docs/assets/templates_security-help.md.C3Ny_Qr2.lean.js +1 -0
- package/dist/docs/assets/{templates_security-reviewer.md.ByFyRta2.js → templates_security-reviewer.md.lshxbCLK.js} +2 -2
- package/dist/docs/assets/{templates_security-reviewer.md.ByFyRta2.lean.js → templates_security-reviewer.md.lshxbCLK.lean.js} +1 -1
- package/dist/docs/assets/{templates_triage.md.CVlpctKS.js → templates_triage.md.Co4UNzkZ.js} +3 -3
- package/dist/docs/assets/{templates_triage.md.CVlpctKS.lean.js → templates_triage.md.Co4UNzkZ.lean.js} +1 -1
- package/dist/docs/assets/troubleshooting.md.Ctv3T8C2.js +1 -0
- package/dist/docs/building-with-agents.html +4 -4
- package/dist/docs/concepts.html +5 -5
- package/dist/docs/concepts.md +1 -0
- package/dist/docs/deployment.html +7 -12
- package/dist/docs/deployment.md +1 -20
- package/dist/docs/design/agsh.md +406 -0
- package/dist/docs/evals.html +4 -4
- package/dist/docs/guides/agent-to-agent.html +6 -6
- package/dist/docs/guides/agent-to-agent.md +2 -2
- package/dist/docs/guides/cloud-runtime.html +6 -6
- package/dist/docs/guides/cloud-runtime.md +1 -0
- package/dist/docs/guides/convert-automation.html +6 -6
- package/dist/docs/guides/convert-automation.md +1 -1
- package/dist/docs/guides/github.html +6 -6
- package/dist/docs/guides/github.md +4 -4
- package/dist/docs/guides/human-in-the-loop.html +4 -4
- package/dist/docs/guides/mcp-oauth.html +11 -13
- package/dist/docs/guides/mcp-oauth.md +10 -18
- package/dist/docs/guides/opentelemetry.html +5 -5
- package/dist/docs/guides/slack.html +9 -15
- package/dist/docs/guides/slack.md +9 -46
- package/dist/docs/guides/webhooks.html +4 -4
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +4 -4
- package/dist/docs/index.html +6 -6
- package/dist/docs/index.md +3 -29
- package/dist/docs/llms-full.txt +756 -2810
- package/dist/docs/llms.txt +3 -16
- package/dist/docs/quickstart.html +6 -6
- package/dist/docs/quickstart.md +2 -3
- package/dist/docs/reference/agent-config.html +4 -4
- package/dist/docs/reference/artifacts.html +4 -4
- package/dist/docs/reference/channels.html +4 -4
- package/dist/docs/reference/cli.html +8 -7
- package/dist/docs/reference/cli.md +5 -2
- package/dist/docs/reference/connections.html +9 -9
- package/dist/docs/reference/connections.md +15 -11
- package/dist/docs/reference/hooks.html +6 -6
- package/dist/docs/reference/hooks.md +2 -3
- package/dist/docs/reference/http-api.html +6 -6
- package/dist/docs/reference/http-api.md +8 -0
- package/dist/docs/reference/instructions.html +4 -4
- package/dist/docs/reference/playground.html +4 -4
- package/dist/docs/reference/project-layout.html +8 -6
- package/dist/docs/reference/project-layout.md +5 -1
- package/dist/docs/reference/prompt.html +4 -4
- package/dist/docs/reference/schedules.html +4 -4
- package/dist/docs/reference/sessions.html +4 -4
- package/dist/docs/reference/skills.html +4 -4
- package/dist/docs/reference/subagents.html +6 -6
- package/dist/docs/reference/subagents.md +2 -2
- package/dist/docs/reference/tools.html +7 -7
- package/dist/docs/reference/tools.md +19 -3
- package/dist/docs/scaffolding-agents.html +4 -4
- package/dist/docs/storage.html +4 -4
- package/dist/docs/templates/agentic-owners.html +7 -7
- package/dist/docs/templates/agentic-owners.md +1 -1
- package/dist/docs/templates/demo.html +6 -6
- package/dist/docs/templates/demo.md +3 -2
- package/dist/docs/templates/pr-autofixer.html +6 -6
- package/dist/docs/templates/pr-autofixer.md +8 -13
- package/dist/docs/templates/security-help.html +30 -0
- package/dist/docs/templates/security-help.md +65 -0
- package/dist/docs/templates/security-reviewer.html +6 -6
- package/dist/docs/templates/security-reviewer.md +1 -3
- package/dist/docs/templates/triage.html +7 -7
- package/dist/docs/templates/triage.md +2 -6
- package/dist/docs/troubleshooting.html +5 -5
- package/dist/docs/troubleshooting.md +2 -2
- package/dist/files-backends/cursor-hosted.d.ts +6 -2
- package/dist/files-backends/cursor-hosted.d.ts.map +1 -1
- package/dist/files-backends/cursor-hosted.js +2 -2
- package/dist/files.d.ts +2 -0
- package/dist/files.d.ts.map +1 -1
- package/dist/files.js +5 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/internal/advertise-tools.d.ts +11 -0
- package/dist/internal/advertise-tools.d.ts.map +1 -1
- package/dist/internal/advertise-tools.js +47 -9
- package/dist/internal/cli-deploy.d.ts.map +1 -1
- package/dist/internal/cli-deploy.js +135 -6
- package/dist/internal/cli-mcp-oauth.d.ts.map +1 -1
- package/dist/internal/cli-mcp-oauth.js +7 -4
- package/dist/internal/conversation-mirror.d.ts +82 -0
- package/dist/internal/conversation-mirror.d.ts.map +1 -0
- package/dist/internal/conversation-mirror.js +251 -0
- package/dist/internal/convert-automation/convert-workflow.d.ts.map +1 -1
- package/dist/internal/convert-automation/convert-workflow.js +26 -15
- package/dist/internal/convert-automation/slug.d.ts +0 -2
- package/dist/internal/convert-automation/slug.d.ts.map +1 -1
- package/dist/internal/convert-automation/slug.js +0 -8
- package/dist/internal/cursor/account-mcp.d.ts.map +1 -1
- package/dist/internal/cursor/account-mcp.js +5 -1
- package/dist/internal/deferred-channel-session.d.ts +20 -0
- package/dist/internal/deferred-channel-session.d.ts.map +1 -0
- package/dist/internal/deferred-channel-session.js +62 -0
- package/dist/internal/deploy-client.d.ts +13 -1
- package/dist/internal/deploy-client.d.ts.map +1 -1
- package/dist/internal/deploy-client.js +11 -1
- package/dist/internal/deploy-manifest.d.ts.map +1 -1
- package/dist/internal/deploy-manifest.js +11 -5
- package/dist/internal/discovery.d.ts.map +1 -1
- package/dist/internal/discovery.js +110 -15
- package/dist/internal/framework-storage-selection.d.ts +32 -16
- package/dist/internal/framework-storage-selection.d.ts.map +1 -1
- package/dist/internal/framework-storage-selection.js +51 -17
- package/dist/internal/hosted-admission-context.d.ts +20 -0
- package/dist/internal/hosted-admission-context.d.ts.map +1 -0
- package/dist/internal/hosted-admission-context.js +31 -0
- package/dist/internal/hosted-delivery-protocol.d.ts +5 -0
- package/dist/internal/hosted-delivery-protocol.d.ts.map +1 -1
- package/dist/internal/hosted-delivery-protocol.js +33 -1
- package/dist/internal/hosted-delivery.d.ts +4 -2
- package/dist/internal/hosted-delivery.d.ts.map +1 -1
- package/dist/internal/hosted-delivery.js +97 -44
- package/dist/internal/hosted-managed-automation.d.ts +30 -0
- package/dist/internal/hosted-managed-automation.d.ts.map +1 -0
- package/dist/internal/hosted-managed-automation.js +58 -0
- package/dist/internal/mcp-endpoint.js +3 -3
- package/dist/internal/mcp-host.d.ts +8 -7
- package/dist/internal/mcp-host.d.ts.map +1 -1
- package/dist/internal/mcp-host.js +8 -7
- package/dist/internal/peer-connections.d.ts.map +1 -1
- package/dist/internal/peer-connections.js +5 -1
- package/dist/internal/playground/static.d.ts +0 -3
- package/dist/internal/playground/static.d.ts.map +1 -1
- package/dist/internal/resolved-connections.d.ts.map +1 -1
- package/dist/internal/resolved-connections.js +5 -7
- package/dist/internal/review-comments.d.ts.map +1 -1
- package/dist/internal/review-comments.js +10 -98
- package/dist/internal/scm/pr-url.d.ts +14 -0
- package/dist/internal/scm/pr-url.d.ts.map +1 -0
- package/dist/internal/scm/pr-url.js +65 -0
- package/dist/internal/sdk-runner.d.ts +14 -0
- package/dist/internal/sdk-runner.d.ts.map +1 -1
- package/dist/internal/sdk-runner.js +41 -2
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +123 -174
- package/dist/internal/session-engine.d.ts +45 -10
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +217 -65
- package/dist/internal/tool-catalog.d.ts +31 -0
- package/dist/internal/tool-catalog.d.ts.map +1 -0
- package/dist/internal/tool-catalog.js +67 -0
- package/dist/playground/assets/index-CF7hUDnQ.css +1 -0
- package/dist/playground/assets/{index-D9MFzhNE.js → index-CZA1uEWA.js} +48 -48
- package/dist/playground/index.html +2 -2
- package/dist/storage-backends/cursor-hosted.d.ts +7 -2
- package/dist/storage-backends/cursor-hosted.d.ts.map +1 -1
- package/dist/storage-backends/cursor-hosted.js +2 -2
- package/dist/types.d.ts +72 -23
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +19 -0
- package/docs/README.md +3 -29
- package/docs/concepts.md +1 -0
- package/docs/deployment.md +1 -20
- package/docs/design/agsh.md +406 -0
- package/docs/guides/agent-to-agent.md +2 -2
- package/docs/guides/cloud-runtime.md +1 -0
- package/docs/guides/convert-automation.md +1 -1
- package/docs/guides/github.md +4 -4
- package/docs/guides/mcp-oauth.md +10 -18
- package/docs/guides/slack.md +10 -47
- package/docs/quickstart.md +2 -3
- package/docs/reference/cli.md +5 -2
- package/docs/reference/connections.md +15 -11
- package/docs/reference/hooks.md +2 -3
- package/docs/reference/http-api.md +8 -0
- package/docs/reference/project-layout.md +5 -1
- package/docs/reference/subagents.md +2 -2
- package/docs/reference/tools.md +19 -3
- package/docs/templates/agentic-owners.md +1 -1
- package/docs/templates/demo.md +3 -2
- package/docs/templates/pr-autofixer.md +8 -13
- package/docs/templates/security-help.md +70 -0
- package/docs/templates/security-reviewer.md +1 -3
- package/docs/templates/triage.md +2 -6
- package/docs/troubleshooting.md +2 -2
- package/package.json +9 -2
- package/skills/create-agent/SKILL.md +6 -13
- package/skills/debug/SKILL.md +2 -4
- package/skills/evals/SKILL.md +1 -1
- package/skills/framework-map/SKILL.md +3 -2
- package/skills/mcp-auth/SKILL.md +10 -13
- package/skills/setup-slack/SKILL.md +21 -137
- package/src/channels/github/github-channel.ts +23 -8
- package/src/channels/github/types.ts +19 -2
- package/src/channels/origin/origin-channel.ts +13 -1
- package/src/channels/origin/origin-webhook.ts +27 -3
- package/src/channels/origin/types.ts +8 -0
- package/src/channels/slack/attachments.ts +2 -2
- package/src/channels/slack/dispatch.ts +2 -16
- package/src/channels/slack/eval-directive.ts +8 -27
- package/src/channels/slack/index.ts +0 -6
- package/src/channels/slack/pr-ref.ts +56 -25
- package/src/channels/slack/setup.ts +8 -15
- package/src/channels/slack/slack-channel.ts +14 -125
- package/src/channels/slack/types.ts +12 -96
- package/src/client.ts +23 -0
- package/src/connections.ts +20 -7
- package/src/files-backends/cursor-hosted.ts +9 -3
- package/src/files.ts +11 -0
- package/src/index.ts +2 -0
- package/src/internal/advertise-tools.ts +45 -7
- package/src/internal/cli-deploy.ts +171 -7
- package/src/internal/cli-mcp-oauth.ts +6 -4
- package/src/internal/conversation-mirror.ts +330 -0
- package/src/internal/convert-automation/convert-workflow.ts +29 -17
- package/src/internal/convert-automation/slug.ts +0 -9
- package/src/internal/cursor/account-mcp.ts +4 -1
- package/src/internal/deferred-channel-session.ts +61 -0
- package/src/internal/deploy-client.ts +24 -1
- package/src/internal/deploy-manifest.ts +10 -5
- package/src/internal/discovery.ts +129 -15
- package/src/internal/fixtures/units-server.ts +52 -0
- package/src/internal/framework-storage-selection.ts +61 -19
- package/src/internal/hosted-admission-context.ts +37 -0
- package/src/internal/hosted-delivery-protocol.ts +44 -1
- package/src/internal/hosted-delivery.ts +155 -68
- package/src/internal/hosted-managed-automation.ts +72 -0
- package/src/internal/mcp-endpoint.ts +3 -3
- package/src/internal/mcp-host.ts +8 -7
- package/src/internal/peer-connections.ts +4 -1
- package/src/internal/playground/static.ts +1 -3
- package/src/internal/resolved-connections.ts +8 -10
- package/src/internal/review-comments.ts +10 -113
- package/src/internal/scm/pr-url.ts +95 -0
- package/src/internal/sdk-runner.ts +57 -2
- package/src/internal/server.ts +161 -251
- package/src/internal/session-engine.ts +266 -69
- package/src/internal/tool-catalog.ts +106 -0
- package/src/storage-backends/cursor-hosted.ts +10 -3
- package/src/types.ts +90 -23
- package/templates/agentic-owners/README.md +1 -1
- package/templates/agentic-owners/agent/agent.ts +0 -10
- package/templates/agentic-owners/agent/channels/github.ts +5 -14
- package/templates/agentic-owners/agent/lib/config.ts +0 -8
- package/templates/agentic-owners/agent/lib/review.ts +2 -15
- package/templates/agentic-owners/agent/tools/record_review.ts +2 -4
- package/templates/demo/agent/agent.ts +0 -10
- package/templates/pr-autofixer/README.md +0 -2
- package/templates/pr-autofixer/agent/agent.ts +0 -11
- package/templates/pr-autofixer/agent/channels/slack.ts +1 -2
- package/templates/pr-autofixer/agent/lib/pr-state.ts +5 -17
- package/templates/pr-autofixer/agent/lib/repos.ts +0 -1
- package/templates/security-help/README.md +2 -2
- package/templates/security-help/agent/agent.ts +1 -2
- package/templates/security-help/agent/channels/slack.ts +0 -3
- package/templates/security-help/agent/instructions.md +9 -10
- package/templates/security-help/agent/skills/access-request.md +1 -1
- package/templates/security-help/agent/skills/faq.md +31 -0
- package/templates/security-help/agent/skills/security-playbooks.md +1 -1
- package/templates/security-help/package.json +1 -2
- package/templates/security-reviewer/agent/agent.ts +0 -10
- package/templates/triage/README.md +2 -1
- package/templates/triage/agent/agent.ts +0 -10
- package/templates/triage/agent/channels/queue.ts +1 -1
- package/templates/triage/agent/channels/webhook.ts +1 -3
- package/templates/triage/overlays/jira/agent/mcp-connections/tracker.ts +0 -1
- package/templates/triage/overlays/linear/agent/mcp-connections/tracker.ts +0 -1
- package/dist/channels/slack/cursor-account.d.ts +0 -87
- package/dist/channels/slack/cursor-account.d.ts.map +0 -1
- package/dist/channels/slack/cursor-account.js +0 -100
- package/dist/docs/assets/chunks/@localSearchIndexroot.ChpIC3Zy.js +0 -1
- package/dist/docs/assets/concepts.md.F6AiPorA.js +0 -1
- package/dist/docs/assets/example-agents_approval-buddy.md.DmezILPg.js +0 -10
- package/dist/docs/assets/example-agents_approval-buddy.md.DmezILPg.lean.js +0 -1
- package/dist/docs/assets/example-agents_benny.md.B0kwY7D_.js +0 -5
- package/dist/docs/assets/example-agents_benny.md.B0kwY7D_.lean.js +0 -1
- package/dist/docs/assets/example-agents_bugbot.md.BRGMi9O2.js +0 -11
- package/dist/docs/assets/example-agents_bugbot.md.BRGMi9O2.lean.js +0 -1
- package/dist/docs/assets/example-agents_codebase-wiki.md.BBNw9Ekr.js +0 -8
- package/dist/docs/assets/example-agents_codebase-wiki.md.BBNw9Ekr.lean.js +0 -1
- package/dist/docs/assets/example-agents_codeowners-review.md.Bfta-lBU.js +0 -8
- package/dist/docs/assets/example-agents_codeowners-review.md.Bfta-lBU.lean.js +0 -1
- package/dist/docs/assets/example-agents_concierge.md.BzB2b20R.js +0 -22
- package/dist/docs/assets/example-agents_concierge.md.BzB2b20R.lean.js +0 -1
- package/dist/docs/assets/example-agents_index.md.ChBp0AX6.js +0 -2
- package/dist/docs/assets/example-agents_index.md.ChBp0AX6.lean.js +0 -1
- package/dist/docs/assets/example-agents_knowledge-base.md.CrA85ig-.js +0 -11
- package/dist/docs/assets/example-agents_knowledge-base.md.CrA85ig-.lean.js +0 -1
- package/dist/docs/assets/example-agents_oncall.md.DK4XkYTd.js +0 -10
- package/dist/docs/assets/example-agents_oncall.md.DK4XkYTd.lean.js +0 -1
- package/dist/docs/assets/example-agents_security-reviewer.md.74pPpWYj.js +0 -19
- package/dist/docs/assets/example-agents_security-reviewer.md.74pPpWYj.lean.js +0 -1
- package/dist/docs/assets/example-agents_slack-agent.md.D7Kdj5BV.js +0 -5
- package/dist/docs/assets/example-agents_slack-agent.md.D7Kdj5BV.lean.js +0 -1
- package/dist/docs/assets/example-agents_weather-agent.md.CaGpmw3Y.js +0 -25
- package/dist/docs/assets/example-agents_weather-agent.md.CaGpmw3Y.lean.js +0 -1
- package/dist/docs/assets/guides_cloud-runtime.md.BnvjPiia.js +0 -9
- package/dist/docs/assets/guides_cloud-runtime.md.BnvjPiia.lean.js +0 -1
- package/dist/docs/assets/guides_slack.md.mqeNKs84.lean.js +0 -1
- package/dist/docs/assets/index.md.B-lVR4wT.js +0 -5
- package/dist/docs/assets/reference_http-api.md.C68BERYr.js +0 -11
- package/dist/docs/assets/reference_http-api.md.C68BERYr.lean.js +0 -1
- package/dist/docs/assets/reference_project-layout.md.WN9nwJht.js +0 -17
- package/dist/docs/assets/troubleshooting.md.vCWwvqcJ.js +0 -1
- package/dist/docs/example-agents/approval-buddy.html +0 -36
- package/dist/docs/example-agents/approval-buddy.md +0 -266
- package/dist/docs/example-agents/benny.html +0 -31
- package/dist/docs/example-agents/benny.md +0 -173
- package/dist/docs/example-agents/bugbot.html +0 -37
- package/dist/docs/example-agents/bugbot.md +0 -229
- package/dist/docs/example-agents/codebase-wiki.html +0 -34
- package/dist/docs/example-agents/codebase-wiki.md +0 -167
- package/dist/docs/example-agents/codeowners-review.html +0 -34
- package/dist/docs/example-agents/codeowners-review.md +0 -192
- package/dist/docs/example-agents/concierge.html +0 -48
- package/dist/docs/example-agents/concierge.md +0 -200
- package/dist/docs/example-agents/index.html +0 -28
- package/dist/docs/example-agents/index.md +0 -99
- package/dist/docs/example-agents/knowledge-base.html +0 -37
- package/dist/docs/example-agents/knowledge-base.md +0 -168
- package/dist/docs/example-agents/oncall.html +0 -36
- package/dist/docs/example-agents/oncall.md +0 -212
- package/dist/docs/example-agents/security-reviewer.html +0 -45
- package/dist/docs/example-agents/security-reviewer.md +0 -265
- package/dist/docs/example-agents/slack-agent.html +0 -31
- package/dist/docs/example-agents/slack-agent.md +0 -142
- package/dist/docs/example-agents/weather-agent.html +0 -51
- package/dist/docs/example-agents/weather-agent.md +0 -297
- package/dist/internal/cursor-slack-relay.d.ts +0 -96
- package/dist/internal/cursor-slack-relay.d.ts.map +0 -1
- package/dist/internal/cursor-slack-relay.js +0 -176
- package/dist/playground/assets/index-D9N7-q97.css +0 -1
- package/docs/example-agents/approval-buddy.md +0 -271
- package/docs/example-agents/benny.md +0 -178
- package/docs/example-agents/bugbot.md +0 -234
- package/docs/example-agents/codebase-wiki.md +0 -172
- package/docs/example-agents/codeowners-review.md +0 -197
- package/docs/example-agents/concierge.md +0 -205
- package/docs/example-agents/index.md +0 -104
- package/docs/example-agents/knowledge-base.md +0 -173
- package/docs/example-agents/oncall.md +0 -217
- package/docs/example-agents/security-reviewer.md +0 -270
- package/docs/example-agents/slack-agent.md +0 -147
- package/docs/example-agents/weather-agent.md +0 -302
- package/src/channels/slack/cursor-account.ts +0 -202
- package/src/internal/cursor-slack-relay.ts +0 -249
- package/templates/security-help/agent/knowledge/faq/approvals.md +0 -5
- package/templates/security-help/agent/knowledge/faq/channels.md +0 -6
- package/templates/security-help/agent/knowledge/faq/phishing.md +0 -10
- package/templates/security-help/agent/skills/security-first-pass.md +0 -15
- /package/dist/docs/assets/{concepts.md.F6AiPorA.lean.js → concepts.md.lwAgBIMI.lean.js} +0 -0
- /package/dist/docs/assets/{guides_agent-to-agent.md.B3JIaAqz.lean.js → guides_agent-to-agent.md.BDb0t1QV.lean.js} +0 -0
- /package/dist/docs/assets/{guides_convert-automation.md.Bboisykk.lean.js → guides_convert-automation.md.B4sjlodG.lean.js} +0 -0
- /package/dist/docs/assets/{guides_github.md.DqJhuaN1.lean.js → guides_github.md.Cnh2mL4a.lean.js} +0 -0
- /package/dist/docs/assets/{quickstart.md.BrmfrrIr.lean.js → quickstart.md.Nj_LjW_a.lean.js} +0 -0
- /package/dist/docs/assets/{reference_hooks.md.BxN87gCw.lean.js → reference_hooks.md.a8BJxMR5.lean.js} +0 -0
- /package/dist/docs/assets/{reference_project-layout.md.WN9nwJht.lean.js → reference_project-layout.md.Bv4KOtlB.lean.js} +0 -0
- /package/dist/docs/assets/{reference_subagents.md.Xoav0AII.lean.js → reference_subagents.md.CfsIloPm.lean.js} +0 -0
- /package/dist/docs/assets/{templates_agentic-owners.md.DqtPdm6f.lean.js → templates_agentic-owners.md.BZSH4N9z.lean.js} +0 -0
- /package/dist/docs/assets/{templates_demo.md.DhFcWN6j.lean.js → templates_demo.md.BeQX9V3H.lean.js} +0 -0
- /package/dist/docs/assets/{troubleshooting.md.vCWwvqcJ.lean.js → troubleshooting.md.Ctv3T8C2.lean.js} +0 -0
|
@@ -49,6 +49,7 @@ import {
|
|
|
49
49
|
type ConnectionTransport,
|
|
50
50
|
DEFAULT_MODEL,
|
|
51
51
|
DIRECT_TOOL_CALL_CHANNEL_ID,
|
|
52
|
+
type DiscoveredTool,
|
|
52
53
|
type HookHandler,
|
|
53
54
|
type HostContext,
|
|
54
55
|
type HttpChannelDefinition,
|
|
@@ -112,11 +113,16 @@ import {
|
|
|
112
113
|
createHostSlackClient,
|
|
113
114
|
type HostPlatforms,
|
|
114
115
|
} from "./host-platforms.js";
|
|
116
|
+
import {
|
|
117
|
+
HostedAdmissionLocalSendError,
|
|
118
|
+
isDuringHostedAdmission,
|
|
119
|
+
} from "./hosted-admission-context.js";
|
|
115
120
|
import {
|
|
116
121
|
formatContinuationToken,
|
|
117
122
|
newContinuationKey,
|
|
118
123
|
newSessionId,
|
|
119
124
|
newToolCallId,
|
|
125
|
+
parseContinuationToken,
|
|
120
126
|
} from "./ids.js";
|
|
121
127
|
import { validateToolInput } from "./json-schema.js";
|
|
122
128
|
import { McpHost } from "./mcp-host.js";
|
|
@@ -136,7 +142,7 @@ import { SessionStore } from "./session-store.js";
|
|
|
136
142
|
import { syncSkillsToStore } from "./skills-sync.js";
|
|
137
143
|
import { StorageCoordinator } from "./storage-coordinator.js";
|
|
138
144
|
import type { FrameworkSessionStore } from "./storage-roles.js";
|
|
139
|
-
import { decideToolCall } from "./tool-policy.js";
|
|
145
|
+
import { decideToolCall, resolveEffect } from "./tool-policy.js";
|
|
140
146
|
import { normalizeToolResult, toolCallErrorMessage } from "./tool-result.js";
|
|
141
147
|
import {
|
|
142
148
|
type EstimateTurnCostFn,
|
|
@@ -197,6 +203,30 @@ export class ToolNotDirectlyCallableError extends Error {
|
|
|
197
203
|
}
|
|
198
204
|
}
|
|
199
205
|
|
|
206
|
+
export class InvalidContinuationTokenError extends Error {
|
|
207
|
+
constructor(detail: string) {
|
|
208
|
+
super(`Invalid continuation token: ${detail}`);
|
|
209
|
+
this.name = "InvalidContinuationTokenError";
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* A session-bound direct call whose harness cwd cannot be materialized and
|
|
215
|
+
* whose effect is not read: a write tool may rely on ctx.workspaceDir being
|
|
216
|
+
* the real session workspace, so it fails typed instead of silently running
|
|
217
|
+
* in a scratch directory.
|
|
218
|
+
*/
|
|
219
|
+
export class WorkspaceUnavailableError extends Error {
|
|
220
|
+
constructor(toolName: string, cause: unknown) {
|
|
221
|
+
super(
|
|
222
|
+
`Session workspace unavailable for tool "${toolName}": ${
|
|
223
|
+
cause instanceof Error ? cause.message : String(cause)
|
|
224
|
+
}`
|
|
225
|
+
);
|
|
226
|
+
this.name = "WorkspaceUnavailableError";
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
200
230
|
export class ToolInputError extends Error {
|
|
201
231
|
constructor(args: { toolName: string; detail: string }) {
|
|
202
232
|
super(`Invalid input for tool "${args.toolName}": ${args.detail}`);
|
|
@@ -439,6 +469,7 @@ export class SessionEngine {
|
|
|
439
469
|
// for why the choice does not belong to the agent author.
|
|
440
470
|
const frameworkStorage = selectFrameworkStorageDefinition({
|
|
441
471
|
authored: options.project.storage,
|
|
472
|
+
architecture: options.project.agent.architecture,
|
|
442
473
|
});
|
|
443
474
|
this.storage =
|
|
444
475
|
frameworkStorage === undefined
|
|
@@ -474,7 +505,10 @@ export class SessionEngine {
|
|
|
474
505
|
// resolves them; the host-side MCP registry starts with the concrete
|
|
475
506
|
// connections and gains the rest via setResolvedConnections.
|
|
476
507
|
this.mcpHost = new McpHost(
|
|
477
|
-
|
|
508
|
+
[
|
|
509
|
+
...options.project.agent.connections,
|
|
510
|
+
...(options.project.agent.hostConnections ?? []),
|
|
511
|
+
].filter(
|
|
478
512
|
(connection) => !isSymbolicConnectionTransport(connection.transport)
|
|
479
513
|
)
|
|
480
514
|
);
|
|
@@ -782,6 +816,13 @@ export class SessionEngine {
|
|
|
782
816
|
message: string,
|
|
783
817
|
options: EngineSendOptions = {}
|
|
784
818
|
): Promise<ChannelSession> {
|
|
819
|
+
if (isDuringHostedAdmission()) {
|
|
820
|
+
// Only sends that bypassed the admission capture stub (typically a
|
|
821
|
+
// startup-captured `onStart` send) reach the engine inside the
|
|
822
|
+
// admission window; running one would leak an invisible local session
|
|
823
|
+
// on a sessionless pod.
|
|
824
|
+
throw new HostedAdmissionLocalSendError();
|
|
825
|
+
}
|
|
785
826
|
const identity =
|
|
786
827
|
channelId === HTTP_CHANNEL_ID
|
|
787
828
|
? httpContinuationIdentity(this.project.httpChannel)
|
|
@@ -2148,27 +2189,17 @@ export class SessionEngine {
|
|
|
2148
2189
|
* Connection names a cloud turn can only reach through the host connection
|
|
2149
2190
|
* bridge on the tool MCP endpoint: filtered account connections without a
|
|
2150
2191
|
* public bridge URL, and host-OAuth connections whose tokens live on this
|
|
2151
|
-
* host.
|
|
2152
|
-
* must not see the connection at all, on any runtime.
|
|
2192
|
+
* host.
|
|
2153
2193
|
*/
|
|
2154
2194
|
cloudBridgeableConnectionNames(): string[] {
|
|
2155
|
-
const hostOnlyNames = new Set(
|
|
2156
|
-
this.project.agent.connections
|
|
2157
|
-
.filter((connection) => connection.hostOnly === true)
|
|
2158
|
-
.map((connection) => connection.name)
|
|
2159
|
-
);
|
|
2160
2195
|
const names: string[] = [];
|
|
2161
2196
|
for (const connection of this.project.agent.connections) {
|
|
2162
|
-
if (
|
|
2163
|
-
!hostOnlyNames.has(connection.name) &&
|
|
2164
|
-
isHostOauthConnectionTransport(connection.transport)
|
|
2165
|
-
) {
|
|
2197
|
+
if (isHostOauthConnectionTransport(connection.transport)) {
|
|
2166
2198
|
names.push(connection.name);
|
|
2167
2199
|
}
|
|
2168
2200
|
}
|
|
2169
2201
|
for (const resolved of this.resolvedConnections) {
|
|
2170
2202
|
if (
|
|
2171
|
-
!hostOnlyNames.has(resolved.name) &&
|
|
2172
2203
|
resolved.accountServersFilter !== undefined &&
|
|
2173
2204
|
resolved.cloudUrl === undefined
|
|
2174
2205
|
) {
|
|
@@ -2181,8 +2212,7 @@ export class SessionEngine {
|
|
|
2181
2212
|
/**
|
|
2182
2213
|
* True when cloud turns reach `name` through the host connection bridge —
|
|
2183
2214
|
* the gate the tool MCP endpoint applies before forwarding a bridge
|
|
2184
|
-
* request to `host.mcp`, so
|
|
2185
|
-
* stay unreachable from a VM.
|
|
2215
|
+
* request to `host.mcp`, so arbitrary names stay unreachable from a VM.
|
|
2186
2216
|
*/
|
|
2187
2217
|
isCloudBridgedConnection(name: string): boolean {
|
|
2188
2218
|
if (this.cloudServerToolsConnection === undefined) {
|
|
@@ -2212,10 +2242,11 @@ export class SessionEngine {
|
|
|
2212
2242
|
}
|
|
2213
2243
|
|
|
2214
2244
|
/**
|
|
2215
|
-
* Authored + resolved MCP servers for a turn. Skips
|
|
2216
|
-
*
|
|
2217
|
-
*
|
|
2218
|
-
*
|
|
2245
|
+
* Authored + resolved MCP servers for a turn. Skips advertised
|
|
2246
|
+
* connections (those surface as named server tools). On cloud turns,
|
|
2247
|
+
* connections whose credential lives on this host — filtered account
|
|
2248
|
+
* connections without a public bridge URL, host-OAuth servers — mount
|
|
2249
|
+
* as host connection bridges over the tool MCP endpoint instead of
|
|
2219
2250
|
* being omitted or failing the turn closed.
|
|
2220
2251
|
*/
|
|
2221
2252
|
private buildMcpServers(
|
|
@@ -2229,16 +2260,17 @@ export class SessionEngine {
|
|
|
2229
2260
|
return {};
|
|
2230
2261
|
}
|
|
2231
2262
|
// Advertised connections surface as named server tools instead of an
|
|
2232
|
-
// attached MCP server (each tool appears exactly once)
|
|
2233
|
-
|
|
2234
|
-
const hostOnlyNames = new Set(
|
|
2263
|
+
// attached MCP server (each tool appears exactly once).
|
|
2264
|
+
const advertisedNames = new Set(
|
|
2235
2265
|
this.project.agent.connections
|
|
2236
|
-
.filter(
|
|
2237
|
-
(connection) =>
|
|
2238
|
-
connection.hostOnly === true || connection.advertiseTools === true
|
|
2239
|
-
)
|
|
2266
|
+
.filter((connection) => connection.advertiseTools === true)
|
|
2240
2267
|
.map((connection) => connection.name)
|
|
2241
2268
|
);
|
|
2269
|
+
const hostConnectionNames = new Set(
|
|
2270
|
+
(this.project.agent.hostConnections ?? []).map(
|
|
2271
|
+
(connection) => connection.name
|
|
2272
|
+
)
|
|
2273
|
+
);
|
|
2242
2274
|
const bridgedNames = new Set(
|
|
2243
2275
|
runtime === "cloud" &&
|
|
2244
2276
|
sessionId !== undefined &&
|
|
@@ -2250,7 +2282,9 @@ export class SessionEngine {
|
|
|
2250
2282
|
assertCloudCanHonorAccountServersFilters({
|
|
2251
2283
|
runtime,
|
|
2252
2284
|
resolvedConnections: this.resolvedConnections.filter(
|
|
2253
|
-
(resolved) =>
|
|
2285
|
+
(resolved) =>
|
|
2286
|
+
!advertisedNames.has(resolved.name) &&
|
|
2287
|
+
!hostConnectionNames.has(resolved.name)
|
|
2254
2288
|
),
|
|
2255
2289
|
bridgedNames,
|
|
2256
2290
|
});
|
|
@@ -2260,7 +2294,10 @@ export class SessionEngine {
|
|
|
2260
2294
|
: this.cloudBridgeTransport(sessionId, name);
|
|
2261
2295
|
const servers: Record<string, ConnectionTransport> = {};
|
|
2262
2296
|
for (const connection of this.project.agent.connections) {
|
|
2263
|
-
if (
|
|
2297
|
+
if (
|
|
2298
|
+
advertisedNames.has(connection.name) ||
|
|
2299
|
+
hostConnectionNames.has(connection.name)
|
|
2300
|
+
) {
|
|
2264
2301
|
continue;
|
|
2265
2302
|
}
|
|
2266
2303
|
if (isSymbolicConnectionTransport(connection.transport)) {
|
|
@@ -2301,7 +2338,10 @@ export class SessionEngine {
|
|
|
2301
2338
|
servers[connection.name] = connection.transport;
|
|
2302
2339
|
}
|
|
2303
2340
|
for (const resolved of this.resolvedConnections) {
|
|
2304
|
-
if (
|
|
2341
|
+
if (
|
|
2342
|
+
advertisedNames.has(resolved.name) ||
|
|
2343
|
+
hostConnectionNames.has(resolved.name)
|
|
2344
|
+
) {
|
|
2305
2345
|
continue;
|
|
2306
2346
|
}
|
|
2307
2347
|
const url = runtime === "cloud" ? resolved.cloudUrl : resolved.localUrl;
|
|
@@ -2346,16 +2386,14 @@ export class SessionEngine {
|
|
|
2346
2386
|
|
|
2347
2387
|
/**
|
|
2348
2388
|
* True when a connection with per-session `auth` attaches to the model
|
|
2349
|
-
* (not
|
|
2389
|
+
* (not advertised). These turns set
|
|
2350
2390
|
* {@link RunnerTurnRequest.perSendMcpServers} so the evaluated headers
|
|
2351
2391
|
* ride every send instead of being pinned on the cached agent handle.
|
|
2352
2392
|
*/
|
|
2353
2393
|
private hasAttachedAuthedConnections(): boolean {
|
|
2354
2394
|
return this.project.agent.connections.some(
|
|
2355
2395
|
(connection) =>
|
|
2356
|
-
connection.auth !== undefined &&
|
|
2357
|
-
connection.hostOnly !== true &&
|
|
2358
|
-
connection.advertiseTools !== true
|
|
2396
|
+
connection.auth !== undefined && connection.advertiseTools !== true
|
|
2359
2397
|
);
|
|
2360
2398
|
}
|
|
2361
2399
|
|
|
@@ -2371,9 +2409,7 @@ export class SessionEngine {
|
|
|
2371
2409
|
): Promise<ReadonlyMap<string, Record<string, string>> | undefined> {
|
|
2372
2410
|
const authed = this.project.agent.connections.filter(
|
|
2373
2411
|
(connection) =>
|
|
2374
|
-
connection.auth !== undefined &&
|
|
2375
|
-
connection.hostOnly !== true &&
|
|
2376
|
-
connection.advertiseTools !== true
|
|
2412
|
+
connection.auth !== undefined && connection.advertiseTools !== true
|
|
2377
2413
|
);
|
|
2378
2414
|
if (authed.length === 0) {
|
|
2379
2415
|
return undefined;
|
|
@@ -2783,12 +2819,168 @@ export class SessionEngine {
|
|
|
2783
2819
|
* with the same `{ content, isError }` envelope the model would see, not
|
|
2784
2820
|
* an exception.
|
|
2785
2821
|
*/
|
|
2822
|
+
/**
|
|
2823
|
+
* The session identity a direct call (or catalog listing) runs under:
|
|
2824
|
+
* an explicit sessionId, a continuation token resolved to a live (or
|
|
2825
|
+
* restorable) session with the same owner/busy checks a sessionId call
|
|
2826
|
+
* gets, or — when neither maps to a session — a synthetic identity
|
|
2827
|
+
* carrying the token's channel id and continuation key so binding
|
|
2828
|
+
* resolvers (e.g. VFS mounts) can still serve the call.
|
|
2829
|
+
*/
|
|
2830
|
+
private async resolveDirectCallIdentity(
|
|
2831
|
+
callId: string,
|
|
2832
|
+
options: Pick<CallToolOptions, "auth" | "sessionId" | "continuationToken">
|
|
2833
|
+
): Promise<{
|
|
2834
|
+
record: SessionRecord | undefined;
|
|
2835
|
+
session: SessionInfo;
|
|
2836
|
+
workspaceDir: string;
|
|
2837
|
+
scratchDir: string | undefined;
|
|
2838
|
+
}> {
|
|
2839
|
+
if (
|
|
2840
|
+
options.sessionId !== undefined &&
|
|
2841
|
+
options.continuationToken !== undefined
|
|
2842
|
+
) {
|
|
2843
|
+
throw new InvalidContinuationTokenError(
|
|
2844
|
+
"mutually exclusive with sessionId — a real session already carries its own continuation key"
|
|
2845
|
+
);
|
|
2846
|
+
}
|
|
2847
|
+
const auth = options.auth ?? null;
|
|
2848
|
+
let record: SessionRecord | undefined;
|
|
2849
|
+
let continuation: { channelId: string; key: string } | null = null;
|
|
2850
|
+
if (options.sessionId !== undefined) {
|
|
2851
|
+
record = await this.sessions.get(options.sessionId);
|
|
2852
|
+
if (record === undefined) {
|
|
2853
|
+
throw new UnknownSessionError(options.sessionId);
|
|
2854
|
+
}
|
|
2855
|
+
} else if (options.continuationToken !== undefined) {
|
|
2856
|
+
continuation = parseContinuationToken(options.continuationToken);
|
|
2857
|
+
if (continuation === null) {
|
|
2858
|
+
throw new InvalidContinuationTokenError(
|
|
2859
|
+
`expected "<channelId>:<key>" (as /v1/sessions lists it), got "${options.continuationToken}"`
|
|
2860
|
+
);
|
|
2861
|
+
}
|
|
2862
|
+
// A token that maps to a live (or restorable) session takes the
|
|
2863
|
+
// session path: same owner check, same turn serialization, same
|
|
2864
|
+
// event recording as an explicit sessionId. Skipping those just
|
|
2865
|
+
// because the caller addressed the session by token would fail open.
|
|
2866
|
+
record =
|
|
2867
|
+
(await this.sessions.findByContinuation(
|
|
2868
|
+
continuation.channelId,
|
|
2869
|
+
continuation.key
|
|
2870
|
+
)) ??
|
|
2871
|
+
(await this.restoreSessionByContinuation(
|
|
2872
|
+
continuation.channelId,
|
|
2873
|
+
continuation.key
|
|
2874
|
+
));
|
|
2875
|
+
if (record !== undefined && !samePrincipal(record.auth, auth)) {
|
|
2876
|
+
throw new SessionAuthError(record.sessionId);
|
|
2877
|
+
}
|
|
2878
|
+
}
|
|
2879
|
+
if (record !== undefined) {
|
|
2880
|
+
// Direct calls respect the same serialization as follow-up sends: a
|
|
2881
|
+
// running model turn owns the session workspace and event stream.
|
|
2882
|
+
if (
|
|
2883
|
+
this.activeTurns.has(record.sessionId) ||
|
|
2884
|
+
this.pendingTurns.has(record.sessionId)
|
|
2885
|
+
) {
|
|
2886
|
+
throw new SessionBusyError(record.sessionId);
|
|
2887
|
+
}
|
|
2888
|
+
return {
|
|
2889
|
+
record,
|
|
2890
|
+
session: this.sessionInfo(record),
|
|
2891
|
+
workspaceDir: this.harnessCwd(record),
|
|
2892
|
+
scratchDir: undefined,
|
|
2893
|
+
};
|
|
2894
|
+
}
|
|
2895
|
+
// No session behind the token (or no token at all): a synthetic
|
|
2896
|
+
// session carries the token's channel id and key, so binding resolvers
|
|
2897
|
+
// keyed on the continuation key (e.g. VFS mounts) can serve the call
|
|
2898
|
+
// with no live session. The workspace stays scratch and nothing is
|
|
2899
|
+
// recorded on a session event stream.
|
|
2900
|
+
const scratchDir = join(this.stateRoot, "tool-calls", callId);
|
|
2901
|
+
return {
|
|
2902
|
+
record: undefined,
|
|
2903
|
+
session: {
|
|
2904
|
+
id: callId,
|
|
2905
|
+
channelId: continuation?.channelId ?? DIRECT_TOOL_CALL_CHANNEL_ID,
|
|
2906
|
+
mode: "task",
|
|
2907
|
+
continuationKey: continuation?.key,
|
|
2908
|
+
auth,
|
|
2909
|
+
},
|
|
2910
|
+
workspaceDir: scratchDir,
|
|
2911
|
+
scratchDir,
|
|
2912
|
+
};
|
|
2913
|
+
}
|
|
2914
|
+
|
|
2915
|
+
/**
|
|
2916
|
+
* The live tool catalog for one session identity: authored server tools
|
|
2917
|
+
* plus the advertised passthroughs a turn under the same identity would
|
|
2918
|
+
* see, under their model-facing names. A connection whose listing fails
|
|
2919
|
+
* is skipped and reported in `connectionErrors` — the inspection surface
|
|
2920
|
+
* degrades legibly instead of hiding every other tool behind one broken
|
|
2921
|
+
* connector.
|
|
2922
|
+
*/
|
|
2923
|
+
async listCatalogTools(
|
|
2924
|
+
options: Pick<
|
|
2925
|
+
CallToolOptions,
|
|
2926
|
+
"auth" | "sessionId" | "continuationToken"
|
|
2927
|
+
> = {}
|
|
2928
|
+
): Promise<{
|
|
2929
|
+
tools: DiscoveredTool[];
|
|
2930
|
+
connectionErrors: Array<{ connection: string; message: string }>;
|
|
2931
|
+
}> {
|
|
2932
|
+
const { session } = await this.resolveDirectCallIdentity(
|
|
2933
|
+
newToolCallId("catalog"),
|
|
2934
|
+
options
|
|
2935
|
+
);
|
|
2936
|
+
const connectionErrors: Array<{ connection: string; message: string }> = [];
|
|
2937
|
+
const advertised = await resolveAdvertisedTools({
|
|
2938
|
+
agent: this.project.agent,
|
|
2939
|
+
session,
|
|
2940
|
+
hostMcp: this.mcpHost,
|
|
2941
|
+
onConnectionError: (connection, error) => {
|
|
2942
|
+
connectionErrors.push({
|
|
2943
|
+
connection,
|
|
2944
|
+
message: error instanceof Error ? error.message : String(error),
|
|
2945
|
+
});
|
|
2946
|
+
},
|
|
2947
|
+
});
|
|
2948
|
+
return {
|
|
2949
|
+
tools: [...this.project.agent.tools, ...advertised],
|
|
2950
|
+
connectionErrors,
|
|
2951
|
+
};
|
|
2952
|
+
}
|
|
2953
|
+
|
|
2786
2954
|
async callTool(
|
|
2787
2955
|
toolName: string,
|
|
2788
2956
|
input: unknown = {},
|
|
2789
2957
|
options: CallToolOptions = {}
|
|
2790
2958
|
): Promise<ToolCallOutcome> {
|
|
2791
|
-
const
|
|
2959
|
+
const callId = newToolCallId(toolName);
|
|
2960
|
+
// Identity resolves before the tool lookup: advertised connection tools
|
|
2961
|
+
// only exist relative to a session (per-session auth), so finding them
|
|
2962
|
+
// needs the same identity the call runs under.
|
|
2963
|
+
const identity = await this.resolveDirectCallIdentity(callId, options);
|
|
2964
|
+
const record = identity.record;
|
|
2965
|
+
const session = identity.session;
|
|
2966
|
+
let workspaceDir = identity.workspaceDir;
|
|
2967
|
+
let scratchDir = identity.scratchDir;
|
|
2968
|
+
let tool = this.project.agent.tools.find((t) => t.name === toolName);
|
|
2969
|
+
if (
|
|
2970
|
+
tool === undefined &&
|
|
2971
|
+
this.project.agent.connections.some((c) => c.advertiseTools === true)
|
|
2972
|
+
) {
|
|
2973
|
+
// Advertised passthroughs are ordinary server tools in the session's
|
|
2974
|
+
// namespace; resolve the live listing so direct calls address them by
|
|
2975
|
+
// the same model-facing name a turn would. A listing failure fails
|
|
2976
|
+
// the call closed, like it fails a turn.
|
|
2977
|
+
const advertised = await resolveAdvertisedTools({
|
|
2978
|
+
agent: this.project.agent,
|
|
2979
|
+
session,
|
|
2980
|
+
hostMcp: this.mcpHost,
|
|
2981
|
+
});
|
|
2982
|
+
tool = advertised.find((t) => t.name === toolName);
|
|
2983
|
+
}
|
|
2792
2984
|
if (tool === undefined) {
|
|
2793
2985
|
throw new UnknownToolError(
|
|
2794
2986
|
toolName,
|
|
@@ -2805,47 +2997,51 @@ export class SessionEngine {
|
|
|
2805
2997
|
if (!validation.ok) {
|
|
2806
2998
|
throw new ToolInputError({ toolName, detail: validation.message });
|
|
2807
2999
|
}
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
let session: SessionInfo;
|
|
2813
|
-
let workspaceDir: string;
|
|
2814
|
-
let scratchDir: string | undefined;
|
|
2815
|
-
if (options.sessionId !== undefined) {
|
|
2816
|
-
record = await this.sessions.get(options.sessionId);
|
|
3000
|
+
let workspaceUnavailable = false;
|
|
3001
|
+
try {
|
|
3002
|
+
await mkdir(workspaceDir, { recursive: true });
|
|
3003
|
+
} catch (error) {
|
|
2817
3004
|
if (record === undefined) {
|
|
2818
|
-
throw
|
|
3005
|
+
throw error;
|
|
2819
3006
|
}
|
|
2820
|
-
//
|
|
2821
|
-
//
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
3007
|
+
// A session's harness cwd can be a path the serving process cannot
|
|
3008
|
+
// create (e.g. an absolute `local.cwd` like /repo on a hosted pod
|
|
3009
|
+
// where the sandboxed harness would have made it). Read-effect calls
|
|
3010
|
+
// fall back to a scratch workspace instead of failing: tools that
|
|
3011
|
+
// resolve their state from the session identity (VFS mounts) never
|
|
3012
|
+
// touch ctx.workspaceDir. Advertised passthroughs are relocatable by
|
|
3013
|
+
// construction: their execute body forwards to the connection and
|
|
3014
|
+
// never reads the workspace. A write (or undeclared, which resolves
|
|
3015
|
+
// to write) authored tool may rely on ctx.workspaceDir being the
|
|
3016
|
+
// real session workspace, so silently relocating it is not safe —
|
|
3017
|
+
// fail typed instead.
|
|
3018
|
+
const relocatable =
|
|
3019
|
+
tool.advertised === true ||
|
|
3020
|
+
resolveEffect(tool.definition.effect, validation.value) === "read";
|
|
3021
|
+
if (!relocatable) {
|
|
3022
|
+
throw new WorkspaceUnavailableError(toolName, error);
|
|
2827
3023
|
}
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
channelId: DIRECT_TOOL_CALL_CHANNEL_ID,
|
|
2834
|
-
mode: "task",
|
|
2835
|
-
auth,
|
|
2836
|
-
};
|
|
3024
|
+
this.logger(
|
|
3025
|
+
`[session] tool ${toolName} workspace unavailable (direct ${callId}); using scratch: ${
|
|
3026
|
+
error instanceof Error ? error.message : String(error)
|
|
3027
|
+
}`
|
|
3028
|
+
);
|
|
2837
3029
|
scratchDir = join(this.stateRoot, "tool-calls", callId);
|
|
2838
3030
|
workspaceDir = scratchDir;
|
|
3031
|
+
workspaceUnavailable = true;
|
|
3032
|
+
await mkdir(workspaceDir, { recursive: true });
|
|
2839
3033
|
}
|
|
2840
|
-
await mkdir(workspaceDir, { recursive: true });
|
|
2841
3034
|
// Match what a model turn would see: session workspaces get the same
|
|
2842
3035
|
// scaffold as executeTurn (seeds only before the first turn); scratch
|
|
2843
3036
|
// workspaces are materialized fresh.
|
|
2844
3037
|
await materializeWorkspace({
|
|
2845
3038
|
agent: this.project.agent,
|
|
2846
3039
|
workspaceDir:
|
|
2847
|
-
record === undefined
|
|
2848
|
-
|
|
3040
|
+
record === undefined || workspaceUnavailable
|
|
3041
|
+
? workspaceDir
|
|
3042
|
+
: this.scaffoldDir(record),
|
|
3043
|
+
seed:
|
|
3044
|
+
record === undefined || workspaceUnavailable || record.turnCount === 0,
|
|
2849
3045
|
stateRoot: this.stateRoot,
|
|
2850
3046
|
});
|
|
2851
3047
|
|
|
@@ -2981,8 +3177,9 @@ export class SessionEngine {
|
|
|
2981
3177
|
isError,
|
|
2982
3178
|
result,
|
|
2983
3179
|
durationMs,
|
|
2984
|
-
|
|
2985
|
-
|
|
3180
|
+
errorMessage,
|
|
3181
|
+
sessionId: record?.sessionId,
|
|
3182
|
+
scratchWorkspace: workspaceUnavailable ? true : undefined,
|
|
2986
3183
|
};
|
|
2987
3184
|
}
|
|
2988
3185
|
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Projections for the live tool catalog (`GET /v1/tools` and
|
|
3
|
+
* `GET /v1/tools/:name`): the session's tool namespace exactly as a turn
|
|
4
|
+
* would assemble it — authored server tools plus advertised MCP
|
|
5
|
+
* passthroughs — under model-facing names.
|
|
6
|
+
*
|
|
7
|
+
* Titles are curated data, never derived from descriptions: advertised
|
|
8
|
+
* tools inherit the upstream server's MCP `annotations.title` (bounded at
|
|
9
|
+
* listing time), and the well-known non-MCP tool names carry a hardcoded
|
|
10
|
+
* title here so every deployment shows the same display names.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import type {
|
|
14
|
+
DiscoveredTool,
|
|
15
|
+
JsonSchemaObject,
|
|
16
|
+
ToolEffect,
|
|
17
|
+
ToolExecution,
|
|
18
|
+
} from "../types.js";
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Display names for the well-known tool names that do not come from MCP
|
|
22
|
+
* (authored tools have no title field; adding one to `defineTool` for a
|
|
23
|
+
* presentation concern is not worth the authoring surface).
|
|
24
|
+
*/
|
|
25
|
+
const WELL_KNOWN_TOOL_TITLES: Readonly<Record<string, string>> = {
|
|
26
|
+
diff: "Show change diffs",
|
|
27
|
+
glob: "Find files by pattern",
|
|
28
|
+
grep: "Search file contents",
|
|
29
|
+
ls: "List a directory",
|
|
30
|
+
read: "Read a file",
|
|
31
|
+
search: "Search with a typed query",
|
|
32
|
+
write: "Write a file",
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
function catalogTitle(tool: DiscoveredTool): string | undefined {
|
|
36
|
+
if (tool.advertised === true) {
|
|
37
|
+
return tool.annotations?.title;
|
|
38
|
+
}
|
|
39
|
+
return WELL_KNOWN_TOOL_TITLES[tool.name];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Sand connector identifiers scope the connector name by owner
|
|
44
|
+
* (`dashboard-team-<id>-Buildkite`, `dashboard-<Name>`, `user-<Name>`);
|
|
45
|
+
* the suffix is the human-meaningful name.
|
|
46
|
+
*/
|
|
47
|
+
const CONNECTOR_SCOPE_PREFIX = /^(?:dashboard-team-\d+-|dashboard-|user-)/;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Where a tool comes from, for humans: the upstream connector/plugin name
|
|
51
|
+
* when the tool declares one (the reserved `__conn__` selector's values
|
|
52
|
+
* name it), the connection name otherwise. One aggregating connection
|
|
53
|
+
* (e.g. a tenant `plugins` endpoint) hosts tools from several connectors,
|
|
54
|
+
* and "plugins" tells an operator nothing — "Buildkite" does.
|
|
55
|
+
*/
|
|
56
|
+
function catalogSource(tool: DiscoveredTool): string | undefined {
|
|
57
|
+
if (tool.advertised !== true) {
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
const properties = tool.inputSchema.properties as
|
|
61
|
+
| Record<string, { enum?: unknown[] } | undefined>
|
|
62
|
+
| undefined;
|
|
63
|
+
const first = properties?.__conn__?.enum?.[0];
|
|
64
|
+
if (typeof first === "string" && first !== "") {
|
|
65
|
+
return first.replace(CONNECTOR_SCOPE_PREFIX, "");
|
|
66
|
+
}
|
|
67
|
+
return tool.connection;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** Light listing entry: identifiers and curated display data only. */
|
|
71
|
+
export interface CatalogListEntry {
|
|
72
|
+
name: string;
|
|
73
|
+
title?: string;
|
|
74
|
+
/** Connection name for advertised MCP tools; absent for authored tools. */
|
|
75
|
+
source?: string;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** Full description behind `GET /v1/tools/:name`. */
|
|
79
|
+
export interface CatalogDetailEntry extends CatalogListEntry {
|
|
80
|
+
description: string;
|
|
81
|
+
execution: ToolExecution;
|
|
82
|
+
needsApproval: boolean;
|
|
83
|
+
effect?: ToolEffect | "dynamic";
|
|
84
|
+
inputSchema: JsonSchemaObject;
|
|
85
|
+
outputSchema?: JsonSchemaObject;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function catalogListEntry(tool: DiscoveredTool): CatalogListEntry {
|
|
89
|
+
return {
|
|
90
|
+
name: tool.name,
|
|
91
|
+
title: catalogTitle(tool),
|
|
92
|
+
source: catalogSource(tool),
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function catalogDetailEntry(tool: DiscoveredTool): CatalogDetailEntry {
|
|
97
|
+
return {
|
|
98
|
+
...catalogListEntry(tool),
|
|
99
|
+
description: tool.description,
|
|
100
|
+
execution: tool.execution,
|
|
101
|
+
needsApproval: tool.needsApproval,
|
|
102
|
+
effect: tool.effect,
|
|
103
|
+
inputSchema: tool.inputSchema,
|
|
104
|
+
outputSchema: tool.outputSchema,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
@@ -74,8 +74,13 @@ export interface CursorHostedStorageOptions {
|
|
|
74
74
|
* `https://api.cursor.com`).
|
|
75
75
|
*/
|
|
76
76
|
baseUrl?: string;
|
|
77
|
-
/**
|
|
78
|
-
|
|
77
|
+
/**
|
|
78
|
+
* Bearer credential (default: `CURSOR_API_KEY`). A function is
|
|
79
|
+
* re-resolved on every call: hosted freeze snapshots listen unsigned and
|
|
80
|
+
* bind the key file after serve start, so a value captured at construct
|
|
81
|
+
* time would be permanently absent.
|
|
82
|
+
*/
|
|
83
|
+
apiKey?: string | (() => string | undefined);
|
|
79
84
|
/** Injected for tests. */
|
|
80
85
|
fetch?: typeof fetch;
|
|
81
86
|
}
|
|
@@ -180,7 +185,9 @@ function toCasResult(response: KvCasResponse): KvCasResult {
|
|
|
180
185
|
}
|
|
181
186
|
|
|
182
187
|
function resolveApiKey(options: CursorHostedStorageOptions): string {
|
|
183
|
-
const
|
|
188
|
+
const configured =
|
|
189
|
+
typeof options.apiKey === "function" ? options.apiKey() : options.apiKey;
|
|
190
|
+
const key = (configured ?? process.env.CURSOR_API_KEY)?.trim();
|
|
184
191
|
if (key === undefined || key === "") {
|
|
185
192
|
throw new Error(
|
|
186
193
|
"cursorHostedStorage requires CURSOR_API_KEY (deployment pod credential on Cursor hosting)"
|