@cursor/july 0.1.99 → 0.1.101
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +4 -2
- package/dist/bin/agent-serve.js +3 -2
- package/dist/channels/deployments/deployments-channel.d.ts +41 -5
- package/dist/channels/deployments/deployments-channel.d.ts.map +1 -1
- package/dist/channels/deployments/deployments-channel.js +88 -8
- package/dist/channels/deployments/types.d.ts +4 -3
- package/dist/channels/deployments/types.d.ts.map +1 -1
- package/dist/channels/github/defaults.d.ts.map +1 -1
- package/dist/channels/github/defaults.js +28 -3
- package/dist/channels/github/progress.d.ts +7 -0
- package/dist/channels/github/progress.d.ts.map +1 -1
- package/dist/channels/origin/defaults.d.ts +43 -0
- package/dist/channels/origin/defaults.d.ts.map +1 -0
- package/dist/channels/origin/defaults.js +111 -0
- package/dist/channels/origin/index.d.ts +2 -0
- package/dist/channels/origin/index.d.ts.map +1 -1
- package/dist/channels/origin/index.js +2 -0
- package/dist/channels/origin/origin-channel.d.ts +2 -1
- package/dist/channels/origin/origin-channel.d.ts.map +1 -1
- package/dist/channels/origin/origin-channel.js +24 -3
- package/dist/channels/origin/state.d.ts +32 -0
- package/dist/channels/origin/state.d.ts.map +1 -0
- package/dist/channels/origin/state.js +23 -0
- package/dist/channels/origin/types.d.ts +23 -1
- package/dist/channels/origin/types.d.ts.map +1 -1
- package/dist/channels/slack/api.d.ts +16 -7
- package/dist/channels/slack/api.d.ts.map +1 -1
- package/dist/channels/slack/api.js +31 -14
- package/dist/channels/slack/code-fences.d.ts +17 -0
- package/dist/channels/slack/code-fences.d.ts.map +1 -0
- package/dist/channels/slack/code-fences.js +168 -0
- package/dist/channels/slack/constants.d.ts +6 -0
- package/dist/channels/slack/constants.d.ts.map +1 -1
- package/dist/channels/slack/constants.js +6 -0
- package/dist/channels/slack/defaults.d.ts +9 -4
- package/dist/channels/slack/defaults.d.ts.map +1 -1
- package/dist/channels/slack/defaults.js +154 -76
- package/dist/channels/slack/dispatch.d.ts.map +1 -1
- package/dist/channels/slack/dispatch.js +3 -3
- package/dist/channels/slack/inbound.d.ts +9 -0
- package/dist/channels/slack/inbound.d.ts.map +1 -1
- package/dist/channels/slack/inbound.js +14 -0
- package/dist/channels/slack/index.d.ts +2 -0
- package/dist/channels/slack/index.d.ts.map +1 -1
- package/dist/channels/slack/index.js +2 -0
- package/dist/channels/slack/live-delivery.d.ts +5 -0
- package/dist/channels/slack/live-delivery.d.ts.map +1 -1
- package/dist/channels/slack/live-delivery.js +116 -21
- package/dist/channels/slack/reasoning-card.d.ts +38 -0
- package/dist/channels/slack/reasoning-card.d.ts.map +1 -0
- package/dist/channels/slack/reasoning-card.js +104 -0
- package/dist/channels/slack/redact.d.ts +2 -0
- package/dist/channels/slack/redact.d.ts.map +1 -0
- package/dist/channels/slack/redact.js +5 -0
- package/dist/channels/slack/reply-options.d.ts +40 -0
- package/dist/channels/slack/reply-options.d.ts.map +1 -0
- package/dist/channels/slack/reply-options.js +150 -0
- package/dist/channels/slack/slack-channel.d.ts.map +1 -1
- package/dist/channels/slack/slack-channel.js +8 -4
- package/dist/channels/slack/stream.d.ts +22 -10
- package/dist/channels/slack/stream.d.ts.map +1 -1
- package/dist/channels/slack/stream.js +9 -16
- package/dist/channels/slack/tool-cards.d.ts +22 -0
- package/dist/channels/slack/tool-cards.d.ts.map +1 -0
- package/dist/channels/slack/tool-cards.js +178 -0
- package/dist/channels/slack/types.d.ts +145 -6
- package/dist/channels/slack/types.d.ts.map +1 -1
- package/dist/connections.d.ts +18 -2
- package/dist/connections.d.ts.map +1 -1
- package/dist/connections.js +18 -2
- package/dist/docs/404.html +2 -2
- package/dist/docs/ab.html +6 -6
- package/dist/docs/ab.md +1 -1
- package/dist/docs/assets/{ab.md.DJo5r4R-.js → ab.md.mlVgqvSk.js} +1 -1
- package/dist/docs/assets/{app.BplEAZ3S.js → app.BASO9Kih.js} +1 -1
- package/dist/docs/assets/{building-with-agents.md.DI4mEzlt.js → building-with-agents.md.CUSWxlP_.js} +2 -2
- package/dist/docs/assets/chunks/@localSearchIndexroot.DbFXINq2.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.CHXyv4wP.js → VPLocalSearchBox.DwkqxoE0.js} +1 -1
- package/dist/docs/assets/chunks/{theme.BTcsZmjQ.js → theme.CCil_13e.js} +2 -2
- package/dist/docs/assets/{evals.md.lfJoEVc8.js → evals.md.CPzDAwoH.js} +1 -1
- package/dist/docs/assets/{guides_github.md.Cnh2mL4a.js → guides_github.md.BtPr9GaP.js} +1 -1
- package/dist/docs/assets/{guides_mcp-oauth.md.CN-6YmTJ.js → guides_mcp-oauth.md.Dp6cDP7f.js} +1 -1
- package/dist/docs/assets/{guides_opentelemetry.md.bmPmkvJu.js → guides_opentelemetry.md.BVTXDCRg.js} +2 -2
- package/dist/docs/assets/{guides_slack.md.VDXQV3ja.js → guides_slack.md.9oHPye9o.js} +19 -3
- package/dist/docs/assets/{guides_slack.md.VDXQV3ja.lean.js → guides_slack.md.9oHPye9o.lean.js} +1 -1
- package/dist/docs/assets/hillclimbing.md.CpTGTCle.js +4 -0
- package/dist/docs/assets/{index.md.CVeRUOeZ.js → index.md.Bb4k8kUm.js} +1 -1
- package/dist/docs/assets/{quickstart.md.Nj_LjW_a.js → quickstart.md.DdQOF7Y8.js} +1 -1
- package/dist/docs/assets/{reference_connections.md.DxldvyIB.js → reference_connections.md.Di6jJAXF.js} +13 -3
- package/dist/docs/assets/{reference_connections.md.DxldvyIB.lean.js → reference_connections.md.Di6jJAXF.lean.js} +1 -1
- package/dist/docs/assets/{reference_http-api.md.BEJx9XVj.js → reference_http-api.md.oySXBO8o.js} +1 -1
- package/dist/docs/assets/scaffolding-agents.md.em43xlY1.js +1 -0
- package/dist/docs/assets/skills_ab.md.CsFNatVx.js +26 -0
- package/dist/docs/assets/skills_ab.md.CsFNatVx.lean.js +1 -0
- package/dist/docs/assets/skills_create-agent.md.BVoWPcan.js +8 -0
- package/dist/docs/assets/skills_create-agent.md.BVoWPcan.lean.js +1 -0
- package/dist/docs/assets/skills_debug.md.CDbPhHfg.js +1 -0
- package/dist/docs/assets/skills_debug.md.CDbPhHfg.lean.js +1 -0
- package/dist/docs/assets/skills_evals.md.723kpUmA.js +25 -0
- package/dist/docs/assets/skills_evals.md.723kpUmA.lean.js +1 -0
- package/dist/docs/assets/skills_framework-map.md.BTi817yv.js +1 -0
- package/dist/docs/assets/skills_framework-map.md.BTi817yv.lean.js +1 -0
- package/dist/docs/assets/skills_github.md.D0JahM8c.js +16 -0
- package/dist/docs/assets/skills_github.md.D0JahM8c.lean.js +1 -0
- package/dist/docs/assets/skills_hillclimb.md.B_zJerxA.js +7 -0
- package/dist/docs/assets/skills_hillclimb.md.B_zJerxA.lean.js +1 -0
- package/dist/docs/assets/skills_index.md.DKwIxzGg.js +1 -0
- package/dist/docs/assets/skills_index.md.DKwIxzGg.lean.js +1 -0
- package/dist/docs/assets/skills_mcp-auth.md.DGvFP3HE.js +18 -0
- package/dist/docs/assets/skills_mcp-auth.md.DGvFP3HE.lean.js +1 -0
- package/dist/docs/assets/skills_otel.md.CgiZryR3.js +8 -0
- package/dist/docs/assets/skills_otel.md.CgiZryR3.lean.js +1 -0
- package/dist/docs/assets/skills_setup-slack.md.BBgx8lUz.js +20 -0
- package/dist/docs/assets/skills_setup-slack.md.BBgx8lUz.lean.js +1 -0
- package/dist/docs/assets/{troubleshooting.md.DCiPBhYs.js → troubleshooting.md.Cus_YZga.js} +1 -1
- package/dist/docs/building-with-agents.html +6 -6
- package/dist/docs/building-with-agents.md +14 -11
- package/dist/docs/concepts.html +4 -4
- package/dist/docs/deployment.html +4 -4
- package/dist/docs/evals.html +6 -6
- package/dist/docs/evals.md +1 -1
- package/dist/docs/guides/agent-to-agent.html +4 -4
- package/dist/docs/guides/cloud-runtime.html +4 -4
- package/dist/docs/guides/convert-automation.html +4 -4
- package/dist/docs/guides/github.html +5 -5
- package/dist/docs/guides/github.md +1 -1
- package/dist/docs/guides/human-in-the-loop.html +4 -4
- package/dist/docs/guides/mcp-oauth.html +5 -5
- package/dist/docs/guides/mcp-oauth.md +1 -1
- package/dist/docs/guides/opentelemetry.html +7 -7
- package/dist/docs/guides/opentelemetry.md +2 -2
- package/dist/docs/guides/slack.html +22 -6
- package/dist/docs/guides/slack.md +80 -1
- package/dist/docs/guides/webhooks.html +5 -5
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +6 -6
- package/dist/docs/hillclimbing.md +5 -5
- package/dist/docs/index.html +6 -6
- package/dist/docs/index.md +1 -1
- package/dist/docs/llms-full.txt +1073 -31
- package/dist/docs/llms.txt +14 -0
- package/dist/docs/quickstart.html +5 -5
- package/dist/docs/quickstart.md +1 -1
- 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 +4 -4
- package/dist/docs/reference/connections.html +17 -7
- package/dist/docs/reference/connections.md +32 -1
- package/dist/docs/reference/hooks.html +4 -4
- package/dist/docs/reference/http-api.html +6 -6
- package/dist/docs/reference/http-api.md +1 -1
- package/dist/docs/reference/instructions.html +4 -4
- package/dist/docs/reference/playground.html +4 -4
- package/dist/docs/reference/project-layout.html +4 -4
- 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 +4 -4
- package/dist/docs/reference/tools.html +4 -4
- package/dist/docs/scaffolding-agents.html +5 -5
- package/dist/docs/scaffolding-agents.md +3 -3
- package/dist/docs/skills/ab.html +52 -0
- package/dist/docs/skills/ab.md +50 -0
- package/dist/docs/skills/create-agent.html +34 -0
- package/dist/docs/skills/create-agent.md +160 -0
- package/dist/docs/skills/debug.html +27 -0
- package/dist/docs/skills/debug.md +36 -0
- package/dist/docs/skills/evals.html +51 -0
- package/dist/docs/skills/evals.md +99 -0
- package/dist/docs/skills/framework-map.html +27 -0
- package/dist/docs/skills/framework-map.md +95 -0
- package/dist/docs/skills/github.html +42 -0
- package/dist/docs/skills/github.md +93 -0
- package/dist/docs/skills/hillclimb.html +33 -0
- package/dist/docs/skills/hillclimb.md +55 -0
- package/dist/docs/skills/index.html +27 -0
- package/dist/docs/skills/index.md +21 -0
- package/dist/docs/skills/mcp-auth.html +44 -0
- package/dist/docs/skills/mcp-auth.md +76 -0
- package/dist/docs/skills/otel.html +34 -0
- package/dist/docs/skills/otel.md +48 -0
- package/dist/docs/skills/setup-slack.html +46 -0
- package/dist/docs/skills/setup-slack.md +141 -0
- package/dist/docs/storage.html +4 -4
- package/dist/docs/templates/agentic-owners.html +4 -4
- package/dist/docs/templates/agents-md.html +4 -4
- package/dist/docs/templates/code-wiki.html +4 -4
- package/dist/docs/templates/demo.html +4 -4
- package/dist/docs/templates/pr-autofixer.html +4 -4
- package/dist/docs/templates/security-help.html +4 -4
- package/dist/docs/templates/security-reviewer.html +4 -4
- package/dist/docs/templates/triage.html +4 -4
- package/dist/docs/troubleshooting.html +5 -5
- package/dist/docs/troubleshooting.md +1 -1
- package/dist/extensions/cursor-cloud-agents/extension.d.ts +55 -0
- package/dist/extensions/cursor-cloud-agents/extension.d.ts.map +1 -0
- package/dist/extensions/cursor-cloud-agents/extension.js +64 -0
- package/dist/extensions/cursor-cloud-agents/lib/cloud.d.ts +30 -0
- package/dist/extensions/cursor-cloud-agents/lib/cloud.d.ts.map +1 -0
- package/dist/extensions/cursor-cloud-agents/lib/cloud.js +45 -0
- package/dist/extensions/cursor-cloud-agents/lib/fleet.d.ts +25 -0
- package/dist/extensions/cursor-cloud-agents/lib/fleet.d.ts.map +1 -0
- package/dist/extensions/cursor-cloud-agents/lib/fleet.js +85 -0
- package/dist/extensions/cursor-cloud-agents/lib/repos.d.ts +15 -0
- package/dist/extensions/cursor-cloud-agents/lib/repos.d.ts.map +1 -0
- package/dist/extensions/cursor-cloud-agents/lib/repos.js +55 -0
- package/dist/extensions/cursor-cloud-agents/skills/handoff.md +27 -0
- package/dist/extensions/cursor-cloud-agents/tools/follow_up.d.ts +4 -0
- package/dist/extensions/cursor-cloud-agents/tools/follow_up.d.ts.map +1 -0
- package/dist/extensions/cursor-cloud-agents/tools/follow_up.js +37 -0
- package/dist/extensions/cursor-cloud-agents/tools/launch.d.ts +4 -0
- package/dist/extensions/cursor-cloud-agents/tools/launch.d.ts.map +1 -0
- package/dist/extensions/cursor-cloud-agents/tools/launch.js +83 -0
- package/dist/extensions/cursor-cloud-agents/tools/list.d.ts +4 -0
- package/dist/extensions/cursor-cloud-agents/tools/list.d.ts.map +1 -0
- package/dist/extensions/cursor-cloud-agents/tools/list.js +36 -0
- package/dist/extensions/cursor-cloud-agents/tools/status.d.ts +4 -0
- package/dist/extensions/cursor-cloud-agents/tools/status.d.ts.map +1 -0
- package/dist/extensions/cursor-cloud-agents/tools/status.js +41 -0
- package/dist/extensions.d.ts +49 -0
- package/dist/extensions.d.ts.map +1 -0
- package/dist/extensions.js +75 -0
- package/dist/files-backends/cursor-hosted.d.ts +6 -0
- package/dist/files-backends/cursor-hosted.d.ts.map +1 -1
- package/dist/files-backends/cursor-hosted.js +6 -9
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/internal/advertise-tools.d.ts +4 -1
- package/dist/internal/advertise-tools.d.ts.map +1 -1
- package/dist/internal/advertise-tools.js +20 -1
- package/dist/internal/as-of.d.ts +18 -0
- package/dist/internal/as-of.d.ts.map +1 -1
- package/dist/internal/as-of.js +131 -0
- package/dist/internal/cli-deploy.d.ts.map +1 -1
- package/dist/internal/cli-deploy.js +66 -21
- package/dist/internal/continuation-identity.d.ts.map +1 -1
- package/dist/internal/continuation-identity.js +3 -1
- package/dist/internal/conversation-mirror.d.ts.map +1 -1
- package/dist/internal/conversation-mirror.js +3 -4
- package/dist/internal/cursor/hosted-deployment-secrets.d.ts +16 -0
- package/dist/internal/cursor/hosted-deployment-secrets.d.ts.map +1 -0
- package/dist/internal/cursor/hosted-deployment-secrets.js +61 -0
- package/dist/internal/cursor/hosted-store-secrets.d.ts +15 -0
- package/dist/internal/cursor/hosted-store-secrets.d.ts.map +1 -0
- package/dist/internal/cursor/hosted-store-secrets.js +48 -0
- package/dist/internal/cursor-deployment-relay.d.ts +15 -1
- package/dist/internal/cursor-deployment-relay.d.ts.map +1 -1
- package/dist/internal/cursor-deployment-relay.js +46 -7
- package/dist/internal/deploy-client.d.ts +29 -6
- package/dist/internal/deploy-client.d.ts.map +1 -1
- package/dist/internal/deploy-client.js +61 -19
- package/dist/internal/discovery.d.ts.map +1 -1
- package/dist/internal/discovery.js +426 -121
- package/dist/internal/distribution.d.ts.map +1 -1
- package/dist/internal/distribution.js +5 -0
- package/dist/internal/framework-file-storage.d.ts +15 -8
- package/dist/internal/framework-file-storage.d.ts.map +1 -1
- package/dist/internal/framework-file-storage.js +70 -10
- package/dist/internal/framework-storage-selection.d.ts +12 -12
- package/dist/internal/framework-storage-selection.d.ts.map +1 -1
- package/dist/internal/framework-storage-selection.js +33 -39
- package/dist/internal/hosted-delivery.d.ts +3 -1
- package/dist/internal/hosted-delivery.d.ts.map +1 -1
- package/dist/internal/hosted-delivery.js +19 -32
- package/dist/internal/hosted-execution-diag.d.ts +5 -0
- package/dist/internal/hosted-execution-diag.d.ts.map +1 -1
- package/dist/internal/hosted-execution-diag.js +5 -0
- package/dist/internal/hosted-execution-flush.d.ts +46 -0
- package/dist/internal/hosted-execution-flush.d.ts.map +1 -0
- package/dist/internal/hosted-execution-flush.js +81 -0
- package/dist/internal/mcp-endpoint.js +1 -0
- package/dist/internal/mcp-host.d.ts +2 -1
- package/dist/internal/mcp-host.d.ts.map +1 -1
- package/dist/internal/mcp-host.js +35 -15
- package/dist/internal/review-comments.d.ts +1 -1
- package/dist/internal/review-comments.d.ts.map +1 -1
- package/dist/internal/review-comments.js +4 -4
- package/dist/internal/server.d.ts +3 -0
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +79 -104
- package/dist/internal/session-engine.d.ts +9 -7
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +45 -34
- package/dist/internal/session-run-log.d.ts +5 -4
- package/dist/internal/session-run-log.d.ts.map +1 -1
- package/dist/internal/session-run-log.js +8 -8
- package/dist/internal/start-log-store.d.ts +60 -0
- package/dist/internal/start-log-store.d.ts.map +1 -0
- package/dist/internal/start-log-store.js +151 -0
- package/dist/internal/storage-coordinator.d.ts +0 -6
- package/dist/internal/storage-coordinator.d.ts.map +1 -1
- package/dist/internal/storage-coordinator.js +1 -9
- package/dist/internal/tool-policy.d.ts +8 -0
- package/dist/internal/tool-policy.d.ts.map +1 -1
- package/dist/internal/tool-policy.js +19 -7
- package/dist/playground/assets/{index-jzNbJENa.js → index-BnNN1-EK.js} +45 -45
- package/dist/playground/assets/index-DBQCwFp0.css +1 -0
- package/dist/playground/index.html +2 -2
- package/dist/storage-backends/cursor-hosted-v2.d.ts +83 -0
- package/dist/storage-backends/cursor-hosted-v2.d.ts.map +1 -0
- package/dist/storage-backends/cursor-hosted-v2.js +164 -0
- package/dist/storage-backends/cursor-hosted.d.ts +6 -0
- package/dist/storage-backends/cursor-hosted.d.ts.map +1 -1
- package/dist/storage-backends/cursor-hosted.js +6 -1
- package/dist/storage-protocol.d.ts +24 -0
- package/dist/storage-protocol.d.ts.map +1 -1
- package/dist/storage-protocol.js +33 -0
- package/dist/storage.d.ts +1 -1
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +1 -1
- package/dist/types.d.ts +123 -6
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +29 -1
- package/docs/README.md +1 -1
- package/docs/ab.md +1 -1
- package/docs/building-with-agents.md +14 -11
- package/docs/evals.md +1 -1
- package/docs/guides/github.md +1 -1
- package/docs/guides/mcp-oauth.md +1 -1
- package/docs/guides/opentelemetry.md +2 -2
- package/docs/guides/slack.md +80 -1
- package/docs/hillclimbing.md +5 -5
- package/docs/quickstart.md +1 -1
- package/docs/reference/connections.md +32 -1
- package/docs/reference/http-api.md +1 -1
- package/docs/scaffolding-agents.md +3 -3
- package/docs/skills/index.md +26 -0
- package/docs/troubleshooting.md +1 -1
- package/package.json +18 -4
- package/src/bin/agent-serve.ts +11 -2
- package/src/channels/deployments/deployments-channel.ts +117 -8
- package/src/channels/deployments/types.ts +4 -3
- package/src/channels/github/defaults.ts +36 -3
- package/src/channels/github/progress.ts +7 -0
- package/src/channels/origin/defaults.ts +143 -0
- package/src/channels/origin/index.ts +2 -0
- package/src/channels/origin/origin-channel.ts +37 -1
- package/src/channels/origin/state.ts +54 -0
- package/src/channels/origin/types.ts +24 -0
- package/src/channels/slack/api.ts +37 -18
- package/src/channels/slack/code-fences.ts +183 -0
- package/src/channels/slack/constants.ts +6 -0
- package/src/channels/slack/defaults.ts +173 -92
- package/src/channels/slack/dispatch.ts +8 -1
- package/src/channels/slack/inbound.ts +17 -0
- package/src/channels/slack/index.ts +2 -0
- package/src/channels/slack/live-delivery.ts +142 -28
- package/src/channels/slack/reasoning-card.ts +140 -0
- package/src/channels/slack/redact.ts +6 -0
- package/src/channels/slack/reply-options.ts +229 -0
- package/src/channels/slack/slack-channel.ts +7 -2
- package/src/channels/slack/stream.ts +31 -24
- package/src/channels/slack/tool-cards.ts +221 -0
- package/src/channels/slack/types.ts +159 -6
- package/src/connections.ts +18 -1
- package/src/extensions/cursor-cloud-agents/extension.ts +118 -0
- package/src/extensions/cursor-cloud-agents/lib/cloud.ts +79 -0
- package/src/extensions/cursor-cloud-agents/lib/fleet.ts +109 -0
- package/src/extensions/cursor-cloud-agents/lib/repos.ts +81 -0
- package/src/extensions/cursor-cloud-agents/skills/handoff.md +27 -0
- package/src/extensions/cursor-cloud-agents/tools/follow_up.ts +29 -0
- package/src/extensions/cursor-cloud-agents/tools/launch.ts +84 -0
- package/src/extensions/cursor-cloud-agents/tools/list.ts +31 -0
- package/src/extensions/cursor-cloud-agents/tools/status.ts +39 -0
- package/src/extensions.ts +98 -0
- package/src/files-backends/cursor-hosted.ts +15 -5
- package/src/index.ts +2 -0
- package/src/internal/advertise-tools.ts +37 -12
- package/src/internal/as-of.ts +163 -0
- package/src/internal/cli-deploy.ts +88 -25
- package/src/internal/continuation-identity.ts +3 -1
- package/src/internal/conversation-mirror.ts +3 -8
- package/src/internal/cursor/hosted-deployment-secrets.ts +72 -0
- package/src/internal/cursor/hosted-store-secrets.ts +72 -0
- package/src/internal/cursor-deployment-relay.ts +65 -8
- package/src/internal/deploy-client.ts +83 -28
- package/src/internal/discovery.ts +479 -114
- package/src/internal/distribution.ts +5 -0
- package/src/internal/framework-file-storage.ts +80 -10
- package/src/internal/framework-storage-selection.ts +31 -44
- package/src/internal/hosted-delivery.ts +38 -63
- package/src/internal/hosted-execution-diag.ts +6 -0
- package/src/internal/hosted-execution-flush.ts +142 -0
- package/src/internal/mcp-endpoint.ts +1 -0
- package/src/internal/mcp-host.ts +40 -14
- package/src/internal/review-comments.ts +5 -2
- package/src/internal/server.ts +81 -100
- package/src/internal/session-engine.ts +56 -28
- package/src/internal/session-run-log.ts +8 -12
- package/src/internal/start-log-store.ts +177 -0
- package/src/internal/storage-coordinator.ts +1 -11
- package/src/internal/tool-policy.ts +39 -9
- package/src/storage-backends/cursor-hosted-v2.ts +219 -0
- package/src/storage-backends/cursor-hosted.ts +6 -1
- package/src/storage-protocol.ts +37 -0
- package/src/storage.ts +1 -0
- package/src/types.ts +177 -14
- package/dist/docs/assets/chunks/@localSearchIndexroot.DpuI4i7Z.js +0 -1
- package/dist/docs/assets/hillclimbing.md.DhESf3OO.js +0 -4
- package/dist/docs/assets/scaffolding-agents.md.D7UUkWw0.js +0 -1
- package/dist/internal/null-kv-storage.d.ts +0 -48
- package/dist/internal/null-kv-storage.d.ts.map +0 -1
- package/dist/internal/null-kv-storage.js +0 -58
- package/dist/playground/assets/index-D7rGZNjy.css +0 -1
- package/src/internal/null-kv-storage.ts +0 -74
- /package/dist/docs/assets/{ab.md.DJo5r4R-.lean.js → ab.md.mlVgqvSk.lean.js} +0 -0
- /package/dist/docs/assets/{building-with-agents.md.DI4mEzlt.lean.js → building-with-agents.md.CUSWxlP_.lean.js} +0 -0
- /package/dist/docs/assets/{evals.md.lfJoEVc8.lean.js → evals.md.CPzDAwoH.lean.js} +0 -0
- /package/dist/docs/assets/{guides_github.md.Cnh2mL4a.lean.js → guides_github.md.BtPr9GaP.lean.js} +0 -0
- /package/dist/docs/assets/{guides_mcp-oauth.md.CN-6YmTJ.lean.js → guides_mcp-oauth.md.Dp6cDP7f.lean.js} +0 -0
- /package/dist/docs/assets/{guides_opentelemetry.md.bmPmkvJu.lean.js → guides_opentelemetry.md.BVTXDCRg.lean.js} +0 -0
- /package/dist/docs/assets/{hillclimbing.md.DhESf3OO.lean.js → hillclimbing.md.CpTGTCle.lean.js} +0 -0
- /package/dist/docs/assets/{index.md.CVeRUOeZ.lean.js → index.md.Bb4k8kUm.lean.js} +0 -0
- /package/dist/docs/assets/{quickstart.md.Nj_LjW_a.lean.js → quickstart.md.DdQOF7Y8.lean.js} +0 -0
- /package/dist/docs/assets/{reference_http-api.md.BEJx9XVj.lean.js → reference_http-api.md.oySXBO8o.lean.js} +0 -0
- /package/dist/docs/assets/{scaffolding-agents.md.D7UUkWw0.lean.js → scaffolding-agents.md.em43xlY1.lean.js} +0 -0
- /package/dist/docs/assets/{troubleshooting.md.DCiPBhYs.lean.js → troubleshooting.md.Cus_YZga.lean.js} +0 -0
|
@@ -41,10 +41,12 @@ import {
|
|
|
41
41
|
type DiscoveredAB,
|
|
42
42
|
type DiscoveredChannel,
|
|
43
43
|
type DiscoveredConnection,
|
|
44
|
+
type DiscoveredExtension,
|
|
44
45
|
type DiscoveredHook,
|
|
45
46
|
type DiscoveredSchedule,
|
|
46
47
|
type DiscoveredSkill,
|
|
47
48
|
type DiscoveredTool,
|
|
49
|
+
type ExtensionMount,
|
|
48
50
|
type HookDefinition,
|
|
49
51
|
type HttpChannelDefinition,
|
|
50
52
|
type InlineStdioConnectionConfig,
|
|
@@ -54,10 +56,12 @@ import {
|
|
|
54
56
|
MAX_RUNNING_TURNS_LIMIT,
|
|
55
57
|
type ModelSetting,
|
|
56
58
|
normalizeConnectionEffects,
|
|
59
|
+
normalizeConnectionTools,
|
|
57
60
|
normalizeCursorAccountServers,
|
|
58
61
|
type ResolvedAgent,
|
|
59
62
|
type ScheduleDefinition,
|
|
60
63
|
type SeedFile,
|
|
64
|
+
type SkillConfig,
|
|
61
65
|
type SkillDefinition,
|
|
62
66
|
type SkillFileSource,
|
|
63
67
|
type ToolDefinition,
|
|
@@ -433,6 +437,12 @@ async function loadAgent(
|
|
|
433
437
|
|
|
434
438
|
const tools = await loadTools(ctx, join(agentDir, "tools"));
|
|
435
439
|
const skills = await loadSkills(ctx, join(agentDir, "skills"));
|
|
440
|
+
const extensions = await appendExtensions(
|
|
441
|
+
ctx,
|
|
442
|
+
join(agentDir, "extensions"),
|
|
443
|
+
tools,
|
|
444
|
+
skills
|
|
445
|
+
);
|
|
436
446
|
const connections = await loadConnections(
|
|
437
447
|
ctx,
|
|
438
448
|
await resolveMcpConnectionsDir(ctx, agentDir)
|
|
@@ -579,6 +589,7 @@ async function loadAgent(
|
|
|
579
589
|
...(architecture === undefined ? {} : { architecture }),
|
|
580
590
|
tools,
|
|
581
591
|
skills,
|
|
592
|
+
extensions,
|
|
582
593
|
connections,
|
|
583
594
|
hostConnections,
|
|
584
595
|
subagents,
|
|
@@ -868,16 +879,35 @@ async function loadTools(
|
|
|
868
879
|
ctx: DiscoveryContext,
|
|
869
880
|
toolsDir: string
|
|
870
881
|
): Promise<DiscoveredTool[]> {
|
|
882
|
+
const tools: DiscoveredTool[] = [];
|
|
883
|
+
for (const { name, path } of await toolModuleEntries(ctx, toolsDir)) {
|
|
884
|
+
const definition = await importDefault(ctx, path, "tool");
|
|
885
|
+
if (definition === undefined) {
|
|
886
|
+
continue;
|
|
887
|
+
}
|
|
888
|
+
const tool = compileTool(ctx, path, name, definition as ToolDefinition);
|
|
889
|
+
if (tool !== undefined) {
|
|
890
|
+
tools.push(tool);
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
return tools;
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
/** The module files of a `tools/` directory whose filenames are valid tool names. */
|
|
897
|
+
async function toolModuleEntries(
|
|
898
|
+
ctx: DiscoveryContext,
|
|
899
|
+
toolsDir: string
|
|
900
|
+
): Promise<Array<{ name: string; path: string }>> {
|
|
871
901
|
if (!(await isDirectory(toolsDir))) {
|
|
872
902
|
return [];
|
|
873
903
|
}
|
|
874
|
-
const
|
|
904
|
+
const entries: Array<{ name: string; path: string }> = [];
|
|
875
905
|
for (const entry of await sortedEntries(toolsDir)) {
|
|
876
|
-
const
|
|
906
|
+
const path = join(toolsDir, entry.name);
|
|
877
907
|
if (entry.isDirectory()) {
|
|
878
908
|
ctx.diagnostics.push({
|
|
879
909
|
severity: "warning",
|
|
880
|
-
path: displayPath(ctx,
|
|
910
|
+
path: displayPath(ctx, path),
|
|
881
911
|
message: "Nested tool directories are not supported; ignoring.",
|
|
882
912
|
});
|
|
883
913
|
continue;
|
|
@@ -886,104 +916,105 @@ async function loadTools(
|
|
|
886
916
|
continue;
|
|
887
917
|
}
|
|
888
918
|
const name = moduleStem(entry.name);
|
|
889
|
-
if (
|
|
890
|
-
|
|
891
|
-
severity: "error",
|
|
892
|
-
path: displayPath(ctx, entryPath),
|
|
893
|
-
message: `Tool name "${name}" must match ${NAME_PATTERN} (the filename becomes the tool name the model sees).`,
|
|
894
|
-
});
|
|
895
|
-
continue;
|
|
919
|
+
if (validateName(ctx, "tool", name, path)) {
|
|
920
|
+
entries.push({ name, path });
|
|
896
921
|
}
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
922
|
+
}
|
|
923
|
+
return entries;
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
/**
|
|
927
|
+
* Validate one tool definition against the tool contract and convert its
|
|
928
|
+
* schemas. Diagnostics point at `entryPath` (the authored file, or the
|
|
929
|
+
* extension mount that contributed the tool).
|
|
930
|
+
*/
|
|
931
|
+
function compileTool(
|
|
932
|
+
ctx: DiscoveryContext,
|
|
933
|
+
entryPath: string,
|
|
934
|
+
name: string,
|
|
935
|
+
tool: ToolDefinition
|
|
936
|
+
): DiscoveredTool | undefined {
|
|
937
|
+
if (isBlank(tool.description)) {
|
|
938
|
+
ctx.diagnostics.push({
|
|
939
|
+
severity: "error",
|
|
940
|
+
path: displayPath(ctx, entryPath),
|
|
941
|
+
message: "Tools require a non-empty description.",
|
|
942
|
+
});
|
|
943
|
+
return undefined;
|
|
944
|
+
}
|
|
945
|
+
const execution = tool.execution === "agent" ? "agent" : "server";
|
|
946
|
+
const needsApprovalConfigured =
|
|
947
|
+
tool.needsApproval === true || typeof tool.needsApproval === "function";
|
|
948
|
+
const effect = declaredEffect(tool);
|
|
949
|
+
if (execution === "agent") {
|
|
950
|
+
if (isBlank(tool.script)) {
|
|
903
951
|
ctx.diagnostics.push({
|
|
904
952
|
severity: "error",
|
|
905
953
|
path: displayPath(ctx, entryPath),
|
|
906
|
-
message:
|
|
954
|
+
message:
|
|
955
|
+
'Tools with execution: "agent" require a non-empty `script` (shell body; JSON on stdin, result on stdout).',
|
|
907
956
|
});
|
|
908
|
-
|
|
957
|
+
return undefined;
|
|
909
958
|
}
|
|
910
|
-
|
|
911
|
-
const needsApprovalConfigured =
|
|
912
|
-
tool.needsApproval === true || typeof tool.needsApproval === "function";
|
|
913
|
-
const effect = declaredEffect(tool);
|
|
914
|
-
if (execution === "agent") {
|
|
915
|
-
if (isBlank(tool.script)) {
|
|
916
|
-
ctx.diagnostics.push({
|
|
917
|
-
severity: "error",
|
|
918
|
-
path: displayPath(ctx, entryPath),
|
|
919
|
-
message:
|
|
920
|
-
'Tools with execution: "agent" require a non-empty `script` (shell body; JSON on stdin, result on stdout).',
|
|
921
|
-
});
|
|
922
|
-
continue;
|
|
923
|
-
}
|
|
924
|
-
if (typeof tool.execute === "function") {
|
|
925
|
-
ctx.diagnostics.push({
|
|
926
|
-
severity: "warning",
|
|
927
|
-
path: displayPath(ctx, entryPath),
|
|
928
|
-
message:
|
|
929
|
-
'`execute` is ignored when execution is "agent"; the Cursor agent runs `script` instead.',
|
|
930
|
-
});
|
|
931
|
-
}
|
|
932
|
-
if (needsApprovalConfigured) {
|
|
933
|
-
ctx.diagnostics.push({
|
|
934
|
-
severity: "error",
|
|
935
|
-
path: displayPath(ctx, entryPath),
|
|
936
|
-
message:
|
|
937
|
-
'`needsApproval` is only supported for execution: "server" tools (in-process).',
|
|
938
|
-
});
|
|
939
|
-
continue;
|
|
940
|
-
}
|
|
941
|
-
} else if (typeof tool.execute !== "function") {
|
|
959
|
+
if (typeof tool.execute === "function") {
|
|
942
960
|
ctx.diagnostics.push({
|
|
943
|
-
severity: "
|
|
961
|
+
severity: "warning",
|
|
944
962
|
path: displayPath(ctx, entryPath),
|
|
945
963
|
message:
|
|
946
|
-
'
|
|
964
|
+
'`execute` is ignored when execution is "agent"; the Cursor agent runs `script` instead.',
|
|
947
965
|
});
|
|
948
|
-
continue;
|
|
949
966
|
}
|
|
950
|
-
|
|
951
|
-
try {
|
|
952
|
-
inputSchema = toolInputJsonSchema(tool.inputSchema);
|
|
953
|
-
} catch (error) {
|
|
967
|
+
if (needsApprovalConfigured) {
|
|
954
968
|
ctx.diagnostics.push({
|
|
955
969
|
severity: "error",
|
|
956
970
|
path: displayPath(ctx, entryPath),
|
|
957
|
-
message:
|
|
958
|
-
|
|
959
|
-
continue;
|
|
960
|
-
}
|
|
961
|
-
let outputSchema: DiscoveredTool["outputSchema"];
|
|
962
|
-
try {
|
|
963
|
-
outputSchema = toolOutputJsonSchema(tool.outputSchema);
|
|
964
|
-
} catch (error) {
|
|
965
|
-
ctx.diagnostics.push({
|
|
966
|
-
severity: "error",
|
|
967
|
-
path: displayPath(ctx, entryPath),
|
|
968
|
-
message: `Failed to convert outputSchema to JSON Schema: ${errorMessage(error)}`,
|
|
971
|
+
message:
|
|
972
|
+
'`needsApproval` is only supported for execution: "server" tools (in-process).',
|
|
969
973
|
});
|
|
970
|
-
|
|
974
|
+
return undefined;
|
|
971
975
|
}
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
needsApproval: needsApprovalConfigured,
|
|
979
|
-
...(effect === undefined ? {} : { effect }),
|
|
980
|
-
...(execution === "agent" && tool.script !== undefined
|
|
981
|
-
? { script: tool.script }
|
|
982
|
-
: {}),
|
|
983
|
-
definition: tool,
|
|
976
|
+
} else if (typeof tool.execute !== "function") {
|
|
977
|
+
ctx.diagnostics.push({
|
|
978
|
+
severity: "error",
|
|
979
|
+
path: displayPath(ctx, entryPath),
|
|
980
|
+
message:
|
|
981
|
+
'Tools require an execute(input, ctx) function (or set execution: "agent" with a script).',
|
|
984
982
|
});
|
|
983
|
+
return undefined;
|
|
985
984
|
}
|
|
986
|
-
|
|
985
|
+
let inputSchema: DiscoveredTool["inputSchema"];
|
|
986
|
+
try {
|
|
987
|
+
inputSchema = toolInputJsonSchema(tool.inputSchema);
|
|
988
|
+
} catch (error) {
|
|
989
|
+
ctx.diagnostics.push({
|
|
990
|
+
severity: "error",
|
|
991
|
+
path: displayPath(ctx, entryPath),
|
|
992
|
+
message: `Failed to convert inputSchema to JSON Schema: ${errorMessage(error)}`,
|
|
993
|
+
});
|
|
994
|
+
return undefined;
|
|
995
|
+
}
|
|
996
|
+
let outputSchema: DiscoveredTool["outputSchema"];
|
|
997
|
+
try {
|
|
998
|
+
outputSchema = toolOutputJsonSchema(tool.outputSchema);
|
|
999
|
+
} catch (error) {
|
|
1000
|
+
ctx.diagnostics.push({
|
|
1001
|
+
severity: "error",
|
|
1002
|
+
path: displayPath(ctx, entryPath),
|
|
1003
|
+
message: `Failed to convert outputSchema to JSON Schema: ${errorMessage(error)}`,
|
|
1004
|
+
});
|
|
1005
|
+
return undefined;
|
|
1006
|
+
}
|
|
1007
|
+
return {
|
|
1008
|
+
name,
|
|
1009
|
+
description: tool.description,
|
|
1010
|
+
inputSchema,
|
|
1011
|
+
outputSchema,
|
|
1012
|
+
execution,
|
|
1013
|
+
needsApproval: needsApprovalConfigured,
|
|
1014
|
+
effect,
|
|
1015
|
+
script: execution === "agent" ? tool.script : undefined,
|
|
1016
|
+
definition: tool,
|
|
1017
|
+
};
|
|
987
1018
|
}
|
|
988
1019
|
|
|
989
1020
|
/**
|
|
@@ -1029,7 +1060,7 @@ async function loadSkills(
|
|
|
1029
1060
|
}
|
|
1030
1061
|
if (entry.name.endsWith(".md")) {
|
|
1031
1062
|
const name = entry.name.slice(0, -".md".length);
|
|
1032
|
-
if (!
|
|
1063
|
+
if (!validateName(ctx, "skill", name, entryPath)) {
|
|
1033
1064
|
continue;
|
|
1034
1065
|
}
|
|
1035
1066
|
const { data, body } = parseFrontmatter(
|
|
@@ -1048,30 +1079,258 @@ async function loadSkills(
|
|
|
1048
1079
|
}
|
|
1049
1080
|
if (isModuleFile(entry.name)) {
|
|
1050
1081
|
const name = moduleStem(entry.name);
|
|
1051
|
-
if (!
|
|
1082
|
+
if (!validateName(ctx, "skill", name, entryPath)) {
|
|
1052
1083
|
continue;
|
|
1053
1084
|
}
|
|
1054
1085
|
const definition = await importDefault(ctx, entryPath, "skill");
|
|
1055
1086
|
if (definition === undefined) {
|
|
1056
1087
|
continue;
|
|
1057
1088
|
}
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1089
|
+
skills.push(compileSkill(name, definition as SkillDefinition));
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
return skills;
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
/** A skill whose body and sibling files are in memory (`defineSkill`, extensions). */
|
|
1096
|
+
function compileSkill(name: string, skill: SkillConfig): DiscoveredSkill {
|
|
1097
|
+
const files: Record<string, SkillFileSource> = {};
|
|
1098
|
+
for (const [rel, contents] of Object.entries(skill.files ?? {})) {
|
|
1099
|
+
files[rel] = { contents };
|
|
1100
|
+
}
|
|
1101
|
+
return {
|
|
1102
|
+
name,
|
|
1103
|
+
description:
|
|
1104
|
+
skill.description ??
|
|
1105
|
+
deriveSkillDescription(skill.markdown) ??
|
|
1106
|
+
SKILL_DESCRIPTION_FALLBACK(name),
|
|
1107
|
+
markdown: skill.markdown.trim(),
|
|
1108
|
+
files,
|
|
1109
|
+
};
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
// ============================================================================
|
|
1113
|
+
// Extensions (agent/extensions/<ns>.ts | agent/extensions/<ns>/extension.ts)
|
|
1114
|
+
// ============================================================================
|
|
1115
|
+
|
|
1116
|
+
/**
|
|
1117
|
+
* Mount every extension under `agent/extensions/` and append its tools and
|
|
1118
|
+
* skills to the authored lists as `<ns>__<name>`, stamped with `extension`.
|
|
1119
|
+
* The namespace is the mount's filename stem or directory name.
|
|
1120
|
+
*/
|
|
1121
|
+
async function appendExtensions(
|
|
1122
|
+
ctx: DiscoveryContext,
|
|
1123
|
+
extensionsDir: string,
|
|
1124
|
+
tools: DiscoveredTool[],
|
|
1125
|
+
skills: DiscoveredSkill[]
|
|
1126
|
+
): Promise<DiscoveredExtension[]> {
|
|
1127
|
+
if (!(await isDirectory(extensionsDir))) {
|
|
1128
|
+
return [];
|
|
1129
|
+
}
|
|
1130
|
+
const extensions: DiscoveredExtension[] = [];
|
|
1131
|
+
for (const entry of await sortedEntries(extensionsDir)) {
|
|
1132
|
+
const path = join(extensionsDir, entry.name);
|
|
1133
|
+
const site = await resolveMountSite(ctx, path, entry);
|
|
1134
|
+
if (site === undefined) {
|
|
1135
|
+
continue;
|
|
1136
|
+
}
|
|
1137
|
+
if (extensions.some((extension) => extension.name === site.ns)) {
|
|
1138
|
+
ctx.diagnostics.push({
|
|
1139
|
+
severity: "error",
|
|
1140
|
+
path: displayPath(ctx, path),
|
|
1141
|
+
message: `Extension "${site.ns}" is mounted twice (as a file and as a directory).`,
|
|
1142
|
+
});
|
|
1143
|
+
continue;
|
|
1144
|
+
}
|
|
1145
|
+
const mount = await importDefault(ctx, site.mountPath, "extension");
|
|
1146
|
+
if (mount === undefined) {
|
|
1147
|
+
continue;
|
|
1148
|
+
}
|
|
1149
|
+
extensions.push(
|
|
1150
|
+
await mountExtension(ctx, site, mount as ExtensionMount, tools, skills)
|
|
1151
|
+
);
|
|
1152
|
+
}
|
|
1153
|
+
return extensions;
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
interface MountSite {
|
|
1157
|
+
ns: string;
|
|
1158
|
+
/** The module default-exporting the {@link ExtensionMount}. */
|
|
1159
|
+
mountPath: string;
|
|
1160
|
+
/** A directory mount; its `tools/` and `skills/` overlay the extension's. */
|
|
1161
|
+
overlayDir?: string;
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
async function resolveMountSite(
|
|
1165
|
+
ctx: DiscoveryContext,
|
|
1166
|
+
path: string,
|
|
1167
|
+
entry: Dirent
|
|
1168
|
+
): Promise<MountSite | undefined> {
|
|
1169
|
+
if (entry.isDirectory()) {
|
|
1170
|
+
if (!validateName(ctx, "extension", entry.name, path)) {
|
|
1171
|
+
return undefined;
|
|
1172
|
+
}
|
|
1173
|
+
const mountPath = await findModuleFile(path, "extension");
|
|
1174
|
+
if (mountPath === undefined) {
|
|
1175
|
+
ctx.diagnostics.push({
|
|
1176
|
+
severity: "error",
|
|
1177
|
+
path: displayPath(ctx, path),
|
|
1178
|
+
message:
|
|
1179
|
+
"A directory mount needs an extension.ts default-exporting the mount (`export default crm({ ... })`).",
|
|
1180
|
+
});
|
|
1181
|
+
return undefined;
|
|
1182
|
+
}
|
|
1183
|
+
return { ns: entry.name, mountPath, overlayDir: path };
|
|
1184
|
+
}
|
|
1185
|
+
if (!entry.isFile() || !isModuleFile(entry.name)) {
|
|
1186
|
+
return undefined;
|
|
1187
|
+
}
|
|
1188
|
+
const ns = moduleStem(entry.name);
|
|
1189
|
+
return validateName(ctx, "extension", ns, path)
|
|
1190
|
+
? { ns, mountPath: path }
|
|
1191
|
+
: undefined;
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
/**
|
|
1195
|
+
* Read the extension's tree with the agent loaders, lay the mount's overlay
|
|
1196
|
+
* on top (a same-named file replaces, `disableTool()` removes), then
|
|
1197
|
+
* namespace what is left.
|
|
1198
|
+
*/
|
|
1199
|
+
async function mountExtension(
|
|
1200
|
+
ctx: DiscoveryContext,
|
|
1201
|
+
site: MountSite,
|
|
1202
|
+
mount: ExtensionMount,
|
|
1203
|
+
tools: DiscoveredTool[],
|
|
1204
|
+
skills: DiscoveredSkill[]
|
|
1205
|
+
): Promise<DiscoveredExtension> {
|
|
1206
|
+
const mounted: DiscoveredExtension = {
|
|
1207
|
+
name: site.ns,
|
|
1208
|
+
description: mount.extension.description,
|
|
1209
|
+
tools: [],
|
|
1210
|
+
skills: [],
|
|
1211
|
+
};
|
|
1212
|
+
const root = mount.extension.root;
|
|
1213
|
+
if (!(await isDirectory(root))) {
|
|
1214
|
+
ctx.diagnostics.push({
|
|
1215
|
+
severity: "error",
|
|
1216
|
+
path: displayPath(ctx, site.mountPath),
|
|
1217
|
+
message: `Extension "${site.ns}" declares root ${root}, which is not a directory. Pass \`import.meta.dirname\` from extension.ts.`,
|
|
1218
|
+
});
|
|
1219
|
+
return mounted;
|
|
1220
|
+
}
|
|
1221
|
+
await warnUnsupportedExtensionSlots(ctx, root);
|
|
1222
|
+
const contributedTools = new Map(
|
|
1223
|
+
(await loadTools(ctx, join(root, "tools"))).map((tool) => [tool.name, tool])
|
|
1224
|
+
);
|
|
1225
|
+
const contributedSkills = new Map(
|
|
1226
|
+
(await loadSkills(ctx, join(root, "skills"))).map((skill) => [
|
|
1227
|
+
skill.name,
|
|
1228
|
+
skill,
|
|
1229
|
+
])
|
|
1230
|
+
);
|
|
1231
|
+
if (site.overlayDir !== undefined) {
|
|
1232
|
+
const overlay = await loadOverlayTools(ctx, join(site.overlayDir, "tools"));
|
|
1233
|
+
for (const tool of overlay.tools) {
|
|
1234
|
+
contributedTools.set(tool.name, tool);
|
|
1235
|
+
}
|
|
1236
|
+
for (const disabled of overlay.disabled) {
|
|
1237
|
+
if (!contributedTools.delete(disabled.name)) {
|
|
1238
|
+
ctx.diagnostics.push({
|
|
1239
|
+
severity: "error",
|
|
1240
|
+
path: displayPath(ctx, disabled.path),
|
|
1241
|
+
message: `disableTool() targets "${disabled.name}", which extension "${site.ns}" does not contribute.`,
|
|
1242
|
+
});
|
|
1062
1243
|
}
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1244
|
+
}
|
|
1245
|
+
for (const skill of await loadSkills(
|
|
1246
|
+
ctx,
|
|
1247
|
+
join(site.overlayDir, "skills")
|
|
1248
|
+
)) {
|
|
1249
|
+
contributedSkills.set(skill.name, skill);
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1252
|
+
for (const [name, tool] of contributedTools) {
|
|
1253
|
+
const composed = `${site.ns}__${name}`;
|
|
1254
|
+
tools.push({ ...tool, name: composed, extension: site.ns });
|
|
1255
|
+
mounted.tools.push(composed);
|
|
1256
|
+
}
|
|
1257
|
+
for (const [name, skill] of contributedSkills) {
|
|
1258
|
+
const composed = `${site.ns}__${name}`;
|
|
1259
|
+
skills.push({ ...skill, name: composed, extension: site.ns });
|
|
1260
|
+
mounted.skills.push(composed);
|
|
1261
|
+
}
|
|
1262
|
+
return mounted;
|
|
1263
|
+
}
|
|
1264
|
+
|
|
1265
|
+
/** A directory mount's `tools/`: replacements plus `disableTool()` markers. */
|
|
1266
|
+
async function loadOverlayTools(
|
|
1267
|
+
ctx: DiscoveryContext,
|
|
1268
|
+
toolsDir: string
|
|
1269
|
+
): Promise<{
|
|
1270
|
+
tools: DiscoveredTool[];
|
|
1271
|
+
disabled: Array<{ name: string; path: string }>;
|
|
1272
|
+
}> {
|
|
1273
|
+
const tools: DiscoveredTool[] = [];
|
|
1274
|
+
const disabled: Array<{ name: string; path: string }> = [];
|
|
1275
|
+
for (const { name, path } of await toolModuleEntries(ctx, toolsDir)) {
|
|
1276
|
+
let mod: Record<string, unknown>;
|
|
1277
|
+
try {
|
|
1278
|
+
mod = await ctx.importModule(path);
|
|
1279
|
+
} catch (error) {
|
|
1280
|
+
ctx.diagnostics.push({
|
|
1281
|
+
severity: "error",
|
|
1282
|
+
path: displayPath(ctx, path),
|
|
1283
|
+
message: `Failed to load module: ${errorMessage(error)}`,
|
|
1284
|
+
});
|
|
1285
|
+
continue;
|
|
1286
|
+
}
|
|
1287
|
+
const kind = getDefinitionKind(mod.default);
|
|
1288
|
+
if (kind === "disabled-tool") {
|
|
1289
|
+
disabled.push({ name, path });
|
|
1290
|
+
continue;
|
|
1291
|
+
}
|
|
1292
|
+
if (kind !== "tool") {
|
|
1293
|
+
ctx.diagnostics.push({
|
|
1294
|
+
severity: "error",
|
|
1295
|
+
path: displayPath(ctx, path),
|
|
1296
|
+
message:
|
|
1297
|
+
"An override must default-export defineTool({ ... }) or disableTool().",
|
|
1298
|
+
});
|
|
1299
|
+
continue;
|
|
1300
|
+
}
|
|
1301
|
+
const tool = compileTool(ctx, path, name, mod.default as ToolDefinition);
|
|
1302
|
+
if (tool !== undefined) {
|
|
1303
|
+
tools.push(tool);
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
return { tools, disabled };
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1309
|
+
/** Slots an agent has that an extension tree may not contribute (yet). */
|
|
1310
|
+
async function warnUnsupportedExtensionSlots(
|
|
1311
|
+
ctx: DiscoveryContext,
|
|
1312
|
+
root: string
|
|
1313
|
+
): Promise<void> {
|
|
1314
|
+
const unsupported = [
|
|
1315
|
+
["instructions.md", "instructions"],
|
|
1316
|
+
["connections", "connections"],
|
|
1317
|
+
["mcp-connections", "MCP connections"],
|
|
1318
|
+
["hooks", "hooks"],
|
|
1319
|
+
["subagents", "subagents"],
|
|
1320
|
+
["channels", "channels"],
|
|
1321
|
+
["schedules", "schedules"],
|
|
1322
|
+
["extensions", "nested extensions"],
|
|
1323
|
+
] as const;
|
|
1324
|
+
for (const [slot, label] of unsupported) {
|
|
1325
|
+
const path = join(root, slot);
|
|
1326
|
+
if ((await isDirectory(path)) || (await isFile(path))) {
|
|
1327
|
+
ctx.diagnostics.push({
|
|
1328
|
+
severity: "warning",
|
|
1329
|
+
path: displayPath(ctx, path),
|
|
1330
|
+
message: `Extension ${label} are not supported yet; only tools/ and skills/ are mounted. Ignoring.`,
|
|
1071
1331
|
});
|
|
1072
1332
|
}
|
|
1073
1333
|
}
|
|
1074
|
-
return skills;
|
|
1075
1334
|
}
|
|
1076
1335
|
|
|
1077
1336
|
async function loadPackagedSkill(
|
|
@@ -1088,7 +1347,7 @@ async function loadPackagedSkill(
|
|
|
1088
1347
|
});
|
|
1089
1348
|
return undefined;
|
|
1090
1349
|
}
|
|
1091
|
-
if (!
|
|
1350
|
+
if (!validateName(ctx, "skill", name, skillDir)) {
|
|
1092
1351
|
return undefined;
|
|
1093
1352
|
}
|
|
1094
1353
|
const { data, body } = parseFrontmatter(await readFile(skillMdPath, "utf8"));
|
|
@@ -1168,6 +1427,25 @@ function parseConnectionEffects(
|
|
|
1168
1427
|
return { ok: true, value: normalizeConnectionEffects(parsed) };
|
|
1169
1428
|
}
|
|
1170
1429
|
|
|
1430
|
+
function parseConnectionTools(
|
|
1431
|
+
tools: unknown
|
|
1432
|
+
): { ok: true; value: string[] | undefined } | { ok: false } {
|
|
1433
|
+
if (tools === undefined) {
|
|
1434
|
+
return { ok: true, value: undefined };
|
|
1435
|
+
}
|
|
1436
|
+
if (!Array.isArray(tools) || tools.length === 0) {
|
|
1437
|
+
return { ok: false };
|
|
1438
|
+
}
|
|
1439
|
+
if (tools.some((name) => typeof name !== "string")) {
|
|
1440
|
+
return { ok: false };
|
|
1441
|
+
}
|
|
1442
|
+
const normalized = normalizeConnectionTools(tools);
|
|
1443
|
+
if (normalized.length === 0) {
|
|
1444
|
+
return { ok: false };
|
|
1445
|
+
}
|
|
1446
|
+
return { ok: true, value: normalized };
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1171
1449
|
function connectionHasSpawnOrRemote(connection: ConnectionDefinition): boolean {
|
|
1172
1450
|
if ("cursorAccount" in connection && connection.cursorAccount === true) {
|
|
1173
1451
|
return true;
|
|
@@ -1214,20 +1492,34 @@ function connectionTransport(
|
|
|
1214
1492
|
return undefined;
|
|
1215
1493
|
}
|
|
1216
1494
|
|
|
1217
|
-
|
|
1495
|
+
/**
|
|
1496
|
+
* Filenames become the names the model sees. `__` is reserved: it joins an
|
|
1497
|
+
* extension's namespace to its contribution (`crm__search`).
|
|
1498
|
+
*/
|
|
1499
|
+
function validateName(
|
|
1218
1500
|
ctx: DiscoveryContext,
|
|
1501
|
+
kind: "skill" | "tool" | "extension",
|
|
1219
1502
|
name: string,
|
|
1220
1503
|
entryPath: string
|
|
1221
1504
|
): boolean {
|
|
1222
|
-
|
|
1223
|
-
|
|
1505
|
+
const label = { skill: "Skill", tool: "Tool", extension: "Extension" }[kind];
|
|
1506
|
+
if (!NAME_PATTERN.test(name)) {
|
|
1507
|
+
ctx.diagnostics.push({
|
|
1508
|
+
severity: "error",
|
|
1509
|
+
path: displayPath(ctx, entryPath),
|
|
1510
|
+
message: `${label} name "${name}" must match ${NAME_PATTERN}.`,
|
|
1511
|
+
});
|
|
1512
|
+
return false;
|
|
1224
1513
|
}
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1514
|
+
if (name.includes("__")) {
|
|
1515
|
+
ctx.diagnostics.push({
|
|
1516
|
+
severity: "error",
|
|
1517
|
+
path: displayPath(ctx, entryPath),
|
|
1518
|
+
message: `${label} name "${name}" may not contain "__"; it is reserved for extension contributions (\`<ns>__<name>\`).`,
|
|
1519
|
+
});
|
|
1520
|
+
return false;
|
|
1521
|
+
}
|
|
1522
|
+
return true;
|
|
1231
1523
|
}
|
|
1232
1524
|
|
|
1233
1525
|
/**
|
|
@@ -1296,7 +1588,7 @@ async function loadHostConnections(
|
|
|
1296
1588
|
modelConnections: readonly DiscoveredConnection[]
|
|
1297
1589
|
): Promise<DiscoveredConnection[]> {
|
|
1298
1590
|
const hostDir = join(agentDir, "host-connections");
|
|
1299
|
-
const loaded = await loadConnections(ctx, hostDir);
|
|
1591
|
+
const loaded = await loadConnections(ctx, hostDir, "host");
|
|
1300
1592
|
const modelNames = new Set(
|
|
1301
1593
|
modelConnections.map((connection) => connection.name)
|
|
1302
1594
|
);
|
|
@@ -1335,7 +1627,8 @@ async function loadHostConnections(
|
|
|
1335
1627
|
|
|
1336
1628
|
async function loadConnections(
|
|
1337
1629
|
ctx: DiscoveryContext,
|
|
1338
|
-
connectionsDir: string
|
|
1630
|
+
connectionsDir: string,
|
|
1631
|
+
role: "model" | "host" = "model"
|
|
1339
1632
|
): Promise<DiscoveredConnection[]> {
|
|
1340
1633
|
if (!(await isDirectory(connectionsDir))) {
|
|
1341
1634
|
return [];
|
|
@@ -1435,6 +1728,56 @@ async function loadConnections(
|
|
|
1435
1728
|
});
|
|
1436
1729
|
continue;
|
|
1437
1730
|
}
|
|
1731
|
+
const parsedTools = isInlineStdioConnection(connection)
|
|
1732
|
+
? { ok: true as const, value: undefined }
|
|
1733
|
+
: parseConnectionTools(connection.tools);
|
|
1734
|
+
if (!parsedTools.ok) {
|
|
1735
|
+
ctx.diagnostics.push({
|
|
1736
|
+
severity: "error",
|
|
1737
|
+
path: displayPath(ctx, entryPath),
|
|
1738
|
+
message:
|
|
1739
|
+
"MCP connection `tools` allowlist must be a non-empty array of tool names.",
|
|
1740
|
+
});
|
|
1741
|
+
continue;
|
|
1742
|
+
}
|
|
1743
|
+
if (
|
|
1744
|
+
isInlineStdioConnection(connection) &&
|
|
1745
|
+
connection.disallowedTools !== undefined
|
|
1746
|
+
) {
|
|
1747
|
+
ctx.diagnostics.push({
|
|
1748
|
+
severity: "error",
|
|
1749
|
+
path: displayPath(ctx, entryPath),
|
|
1750
|
+
message:
|
|
1751
|
+
"MCP connection `disallowedTools` is not supported on inline `tools` connections — author only the tools you want.",
|
|
1752
|
+
});
|
|
1753
|
+
continue;
|
|
1754
|
+
}
|
|
1755
|
+
const parsedDisallowed = isInlineStdioConnection(connection)
|
|
1756
|
+
? { ok: true as const, value: undefined }
|
|
1757
|
+
: parseConnectionTools(connection.disallowedTools);
|
|
1758
|
+
if (!parsedDisallowed.ok) {
|
|
1759
|
+
ctx.diagnostics.push({
|
|
1760
|
+
severity: "error",
|
|
1761
|
+
path: displayPath(ctx, entryPath),
|
|
1762
|
+
message:
|
|
1763
|
+
"MCP connection `disallowedTools` must be a non-empty array of tool names.",
|
|
1764
|
+
});
|
|
1765
|
+
continue;
|
|
1766
|
+
}
|
|
1767
|
+
if (
|
|
1768
|
+
(parsedTools.value !== undefined ||
|
|
1769
|
+
parsedDisallowed.value !== undefined) &&
|
|
1770
|
+
role === "model" &&
|
|
1771
|
+
connection.advertiseTools !== true
|
|
1772
|
+
) {
|
|
1773
|
+
ctx.diagnostics.push({
|
|
1774
|
+
severity: "error",
|
|
1775
|
+
path: displayPath(ctx, entryPath),
|
|
1776
|
+
message:
|
|
1777
|
+
"MCP connection `tools` / `disallowedTools` filter advertised tools; set `advertiseTools: true` or drop the name list. Put the connection in `agent/host-connections/` to restrict `host.mcp` only.",
|
|
1778
|
+
});
|
|
1779
|
+
continue;
|
|
1780
|
+
}
|
|
1438
1781
|
if (
|
|
1439
1782
|
connection.advertiseTools === true &&
|
|
1440
1783
|
isInlineStdioConnection(connection)
|
|
@@ -1538,6 +1881,8 @@ async function loadConnections(
|
|
|
1538
1881
|
auth: connection.auth,
|
|
1539
1882
|
advertiseTools: connection.advertiseTools,
|
|
1540
1883
|
effects: parsedEffects.value,
|
|
1884
|
+
tools: parsedTools.value,
|
|
1885
|
+
disallowedTools: parsedDisallowed.value,
|
|
1541
1886
|
});
|
|
1542
1887
|
}
|
|
1543
1888
|
return connections;
|
|
@@ -1649,6 +1994,7 @@ async function warnUnsupportedSubagentSlots(
|
|
|
1649
1994
|
const unsupported = [
|
|
1650
1995
|
["tools", "tools"],
|
|
1651
1996
|
["skills", "skills"],
|
|
1997
|
+
["extensions", "extensions"],
|
|
1652
1998
|
["mcp-connections", "MCP connections"],
|
|
1653
1999
|
["host-connections", "host MCP connections"],
|
|
1654
2000
|
["connections", "MCP connections"],
|
|
@@ -1684,13 +2030,17 @@ function appendBuiltinTools(
|
|
|
1684
2030
|
return;
|
|
1685
2031
|
}
|
|
1686
2032
|
const agentPath = displayPath(ctx, join(agentDir, "agent.ts"));
|
|
1687
|
-
const authored = new Set(tools.map((tool) => tool.name));
|
|
1688
2033
|
for (const tool of builtin) {
|
|
1689
|
-
|
|
2034
|
+
const existing = tools.find((t) => t.name === tool.name);
|
|
2035
|
+
if (existing !== undefined) {
|
|
2036
|
+
const owner =
|
|
2037
|
+
existing.extension === undefined
|
|
2038
|
+
? "Authored"
|
|
2039
|
+
: `Extension "${existing.extension}"`;
|
|
1690
2040
|
ctx.diagnostics.push({
|
|
1691
2041
|
severity: "warning",
|
|
1692
2042
|
path: agentPath,
|
|
1693
|
-
message:
|
|
2043
|
+
message: `${owner} tool "${tool.name}" shadows the built-in tool of the same name; the built-in is skipped.`,
|
|
1694
2044
|
});
|
|
1695
2045
|
continue;
|
|
1696
2046
|
}
|
|
@@ -1928,7 +2278,15 @@ async function loadChannels(
|
|
|
1928
2278
|
});
|
|
1929
2279
|
continue;
|
|
1930
2280
|
}
|
|
1931
|
-
|
|
2281
|
+
const definition = mod.default as ChannelDefinition;
|
|
2282
|
+
for (const notice of definition.meta?.deprecations ?? []) {
|
|
2283
|
+
ctx.diagnostics.push({
|
|
2284
|
+
severity: "warning",
|
|
2285
|
+
path: displayPath(ctx, entryPath),
|
|
2286
|
+
message: notice,
|
|
2287
|
+
});
|
|
2288
|
+
}
|
|
2289
|
+
channels.push({ id, definition });
|
|
1932
2290
|
}
|
|
1933
2291
|
return { channels, httpChannelDefinition };
|
|
1934
2292
|
}
|
|
@@ -2375,11 +2733,14 @@ export function projectInfo(project: AgentProject): AgentProjectInfo {
|
|
|
2375
2733
|
name: skill.name,
|
|
2376
2734
|
description: skill.description,
|
|
2377
2735
|
})),
|
|
2736
|
+
extensions: agent.extensions ?? [],
|
|
2378
2737
|
connections: agent.connections.map((connection) => ({
|
|
2379
2738
|
name: connection.name,
|
|
2380
2739
|
transport: connectionTransportLabel(connection.transport),
|
|
2381
2740
|
advertiseTools: connection.advertiseTools,
|
|
2382
2741
|
effects: connection.effects,
|
|
2742
|
+
tools: connection.tools,
|
|
2743
|
+
disallowedTools: connection.disallowedTools,
|
|
2383
2744
|
cursorAccountServers:
|
|
2384
2745
|
"cursorAccount" in connection.transport
|
|
2385
2746
|
? (connection.transport.servers ?? "*")
|
|
@@ -2485,6 +2846,7 @@ async function importDefault(
|
|
|
2485
2846
|
| "agent"
|
|
2486
2847
|
| "tool"
|
|
2487
2848
|
| "skill"
|
|
2849
|
+
| "extension"
|
|
2488
2850
|
| "connection"
|
|
2489
2851
|
| "schedule"
|
|
2490
2852
|
| "hook"
|
|
@@ -2525,6 +2887,7 @@ const DEFINE_HELPER_NAME: Record<
|
|
|
2525
2887
|
| "instructions"
|
|
2526
2888
|
| "tool"
|
|
2527
2889
|
| "skill"
|
|
2890
|
+
| "extension"
|
|
2528
2891
|
| "connection"
|
|
2529
2892
|
| "channel"
|
|
2530
2893
|
| "http-channel"
|
|
@@ -2540,6 +2903,7 @@ const DEFINE_HELPER_NAME: Record<
|
|
|
2540
2903
|
instructions: "defineInstructions",
|
|
2541
2904
|
tool: "defineTool",
|
|
2542
2905
|
skill: "defineSkill",
|
|
2906
|
+
extension: "defineExtension",
|
|
2543
2907
|
connection: "defineConnection",
|
|
2544
2908
|
channel: "defineChannel",
|
|
2545
2909
|
"http-channel": "httpChannel",
|
|
@@ -2560,6 +2924,7 @@ async function warnUnknownSlots(
|
|
|
2560
2924
|
"instructions",
|
|
2561
2925
|
"tools",
|
|
2562
2926
|
"skills",
|
|
2927
|
+
"extensions",
|
|
2563
2928
|
"mcp-connections",
|
|
2564
2929
|
"host-connections",
|
|
2565
2930
|
// Legacy slot name; resolveMcpConnectionsDir warns and still loads it.
|