@cursor/july 0.1.105 → 0.1.108
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/README.md +10 -5
- package/dist/bin/agent-serve.js +31 -16
- package/dist/channels/bitbucket/types.d.ts +2 -4
- package/dist/channels/bitbucket/types.d.ts.map +1 -1
- package/dist/channels/deployments/types.d.ts +5 -8
- package/dist/channels/deployments/types.d.ts.map +1 -1
- package/dist/channels/github/github-channel.js +8 -5
- package/dist/channels/github/types.d.ts +7 -5
- package/dist/channels/github/types.d.ts.map +1 -1
- package/dist/channels/gitlab/types.d.ts +2 -5
- package/dist/channels/gitlab/types.d.ts.map +1 -1
- package/dist/channels/origin/origin-channel.d.ts.map +1 -1
- package/dist/channels/origin/origin-channel.js +27 -13
- package/dist/channels/origin/types.d.ts +7 -4
- package/dist/channels/origin/types.d.ts.map +1 -1
- package/dist/channels/slack/defaults.d.ts.map +1 -1
- package/dist/channels/slack/defaults.js +3 -0
- package/dist/channels/slack/dispatch.d.ts.map +1 -1
- package/dist/channels/slack/dispatch.js +1 -1
- package/dist/channels/slack/live-delivery.d.ts.map +1 -1
- package/dist/channels/slack/live-delivery.js +48 -11
- package/dist/channels/slack/types.d.ts +4 -3
- package/dist/channels/slack/types.d.ts.map +1 -1
- package/dist/channels.d.ts +45 -0
- package/dist/channels.d.ts.map +1 -1
- package/dist/channels.js +106 -7
- package/dist/connections.d.ts +2 -1
- package/dist/connections.d.ts.map +1 -1
- package/dist/connections.js +2 -1
- package/dist/docs/404.html +3 -3
- package/dist/docs/ab.html +6 -6
- package/dist/docs/assets/{app.BVwaffdK.js → app.BASKM3M4.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.BHZYsNVi.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.WuWTZ1x8.js → VPLocalSearchBox.BOKxlYGP.js} +2 -2
- package/dist/docs/assets/chunks/{theme.BYdI_6sF.js → theme.DbDZW-zb.js} +2 -2
- package/dist/docs/assets/{deployment.md.MFPKqsqI.js → deployment.md.JenwuCCB.js} +4 -4
- package/dist/docs/assets/{deployment.md.MFPKqsqI.lean.js → deployment.md.JenwuCCB.lean.js} +1 -1
- package/dist/docs/assets/{evals.md.CbMoebP1.js → evals.md.C1ekS3k2.js} +1 -1
- package/dist/docs/assets/guides_cloud-agents.md.BsloyHdY.js +9 -0
- package/dist/docs/assets/{guides_cloud-agents.md.DS8RIjwx.lean.js → guides_cloud-agents.md.BsloyHdY.lean.js} +1 -1
- package/dist/docs/assets/{guides_github.md.c0gdGJ-D.js → guides_github.md.BH33UEBJ.js} +1 -1
- package/dist/docs/assets/{guides_grokbot-agents.md.DVqdhBKb.js → guides_grokbot-agents.md.DyV-WArv.js} +1 -1
- package/dist/docs/assets/guides_improve.md.BGVk32bK.js +14 -0
- package/dist/docs/assets/guides_improve.md.BGVk32bK.lean.js +1 -0
- package/dist/docs/assets/{guides_opentelemetry.md.COh9jFVg.js → guides_opentelemetry.md.SCRMskno.js} +3 -3
- package/dist/docs/assets/{guides_opentelemetry.md.COh9jFVg.lean.js → guides_opentelemetry.md.SCRMskno.lean.js} +1 -1
- package/dist/docs/assets/{guides_slack.md.9oHPye9o.js → guides_slack.md.D4RVMM4G.js} +3 -3
- package/dist/docs/assets/{guides_slack.md.9oHPye9o.lean.js → guides_slack.md.D4RVMM4G.lean.js} +1 -1
- package/dist/docs/assets/index.md.BjH1w2ZW.js +5 -0
- package/dist/docs/assets/{reference_agent-config.md.CHNpiyp4.js → reference_agent-config.md.CvoL6pof.js} +1 -1
- package/dist/docs/assets/{reference_channels.md.DBGcaB7m.js → reference_channels.md.D-qTqwcq.js} +2 -2
- package/dist/docs/assets/{reference_channels.md.DBGcaB7m.lean.js → reference_channels.md.D-qTqwcq.lean.js} +1 -1
- package/dist/docs/assets/{reference_cli.md.C6Lo8SEd.js → reference_cli.md.Ca26u0Es.js} +6 -6
- package/dist/docs/assets/{reference_cli.md.C6Lo8SEd.lean.js → reference_cli.md.Ca26u0Es.lean.js} +1 -1
- package/dist/docs/assets/{reference_connections.md.Di6jJAXF.js → reference_connections.md.BojkC6c5.js} +1 -1
- package/dist/docs/assets/{reference_extensions.md.CGmMLblt.js → reference_extensions.md.CPWt00ds.js} +1 -1
- package/dist/docs/assets/{scaffolding-agents.md.em43xlY1.js → scaffolding-agents.md.Kctn3OVb.js} +1 -1
- package/dist/docs/assets/{skills_create-agent.md.BVoWPcan.js → skills_create-agent.md.Q3h6Je-e.js} +1 -1
- package/dist/docs/assets/{skills_debug.md.CDbPhHfg.js → skills_debug.md.CVjCXMFF.js} +1 -1
- package/dist/docs/assets/{skills_debug.md.CDbPhHfg.lean.js → skills_debug.md.CVjCXMFF.lean.js} +1 -1
- package/dist/docs/assets/{skills_evals.md.723kpUmA.js → skills_evals.md.BhovOvrl.js} +1 -1
- package/dist/docs/assets/skills_framework-map.md.D-tFZhFS.js +1 -0
- package/dist/docs/assets/{skills_framework-map.md.haibFyoB.lean.js → skills_framework-map.md.D-tFZhFS.lean.js} +1 -1
- package/dist/docs/assets/{skills_github.md.D0JahM8c.js → skills_github.md.hgFX_oKY.js} +1 -1
- package/dist/docs/assets/{skills_otel.md.CqhobH3B.js → skills_otel.md.B5Ddv1xH.js} +1 -1
- package/dist/docs/assets/{style.BRuM8477.css → style.DCD_zyg3.css} +1 -1
- package/dist/docs/assets/troubleshooting.md.CYEAO9bM.js +1 -0
- package/dist/docs/building-with-agents.html +6 -6
- package/dist/docs/concepts.html +5 -5
- package/dist/docs/deployment.html +9 -9
- package/dist/docs/deployment.md +7 -2
- package/dist/docs/evals.html +8 -8
- package/dist/docs/evals.md +3 -2
- package/dist/docs/guides/agent-to-agent.html +6 -6
- package/dist/docs/guides/cloud-agents.html +7 -7
- package/dist/docs/guides/cloud-agents.md +4 -3
- package/dist/docs/guides/convert-automation.html +6 -6
- package/dist/docs/guides/github.html +7 -7
- package/dist/docs/guides/github.md +2 -1
- package/dist/docs/guides/grokbot-agents.html +7 -7
- package/dist/docs/guides/grokbot-agents.md +2 -2
- package/dist/docs/guides/human-in-the-loop.html +6 -6
- package/dist/docs/guides/improve.html +40 -0
- package/dist/docs/guides/improve.md +91 -0
- package/dist/docs/guides/mcp-oauth.html +6 -6
- package/dist/docs/guides/opentelemetry.html +8 -8
- package/dist/docs/guides/opentelemetry.md +3 -4
- package/dist/docs/guides/slack.html +8 -8
- package/dist/docs/guides/slack.md +2 -1
- package/dist/docs/guides/webhooks.html +6 -6
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +6 -6
- package/dist/docs/index.html +8 -8
- package/dist/docs/index.md +4 -0
- package/dist/docs/llms-full.txt +180 -61
- package/dist/docs/llms.txt +1 -0
- package/dist/docs/quickstart.html +6 -6
- package/dist/docs/reference/agent-config.html +7 -7
- package/dist/docs/reference/agent-config.md +5 -2
- package/dist/docs/reference/artifacts.html +6 -6
- package/dist/docs/reference/channels.html +7 -7
- package/dist/docs/reference/channels.md +11 -19
- package/dist/docs/reference/cli.html +11 -11
- package/dist/docs/reference/cli.md +23 -13
- package/dist/docs/reference/connections.html +8 -8
- package/dist/docs/reference/connections.md +2 -1
- package/dist/docs/reference/extensions.html +7 -7
- package/dist/docs/reference/extensions.md +2 -0
- package/dist/docs/reference/hooks.html +6 -6
- package/dist/docs/reference/http-api.html +6 -6
- package/dist/docs/reference/instructions.html +6 -6
- package/dist/docs/reference/playground.html +5 -5
- package/dist/docs/reference/project-layout.html +6 -6
- package/dist/docs/reference/prompt.html +6 -6
- package/dist/docs/reference/result.html +6 -6
- package/dist/docs/reference/schedules.html +6 -6
- package/dist/docs/reference/sessions.html +5 -5
- package/dist/docs/reference/skills.html +6 -6
- package/dist/docs/reference/subagents.html +6 -6
- package/dist/docs/reference/tools.html +6 -6
- package/dist/docs/scaffolding-agents.html +6 -6
- package/dist/docs/scaffolding-agents.md +2 -1
- package/dist/docs/skills/ab.html +6 -6
- package/dist/docs/skills/create-agent.html +8 -8
- package/dist/docs/skills/create-agent.md +1 -1
- package/dist/docs/skills/debug.html +6 -6
- package/dist/docs/skills/debug.md +1 -1
- package/dist/docs/skills/evals.html +8 -8
- package/dist/docs/skills/evals.md +1 -1
- package/dist/docs/skills/framework-map.html +6 -6
- package/dist/docs/skills/framework-map.md +4 -2
- package/dist/docs/skills/github.html +8 -8
- package/dist/docs/skills/github.md +1 -1
- package/dist/docs/skills/hillclimb.html +6 -6
- package/dist/docs/skills/index.html +5 -5
- package/dist/docs/skills/mcp-auth.html +6 -6
- package/dist/docs/skills/otel.html +8 -8
- package/dist/docs/skills/otel.md +3 -3
- package/dist/docs/skills/setup-slack.html +6 -6
- package/dist/docs/storage.html +6 -6
- package/dist/docs/templates/agentic-owners.html +6 -6
- package/dist/docs/templates/agents-md.html +6 -6
- package/dist/docs/templates/code-wiki.html +6 -6
- package/dist/docs/templates/demo.html +6 -6
- package/dist/docs/templates/grokbot-agents.html +6 -6
- package/dist/docs/templates/pr-autofixer.html +6 -6
- package/dist/docs/templates/security-help.html +6 -6
- package/dist/docs/templates/security-reviewer.html +6 -6
- package/dist/docs/templates/triage.html +6 -6
- package/dist/docs/troubleshooting.html +6 -6
- package/dist/docs/troubleshooting.md +1 -1
- package/dist/extensions/improve/extension.d.ts +46 -0
- package/dist/extensions/improve/extension.d.ts.map +1 -0
- package/dist/extensions/improve/extension.js +41 -0
- package/dist/extensions/improve/skills/yourself.d.ts +4 -0
- package/dist/extensions/improve/skills/yourself.d.ts.map +1 -0
- package/dist/extensions/improve/skills/yourself.js +43 -0
- package/dist/index.d.ts +4 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -4
- package/dist/internal/builtin-tools/artifacts.d.ts.map +1 -1
- package/dist/internal/builtin-tools/artifacts.js +2 -3
- package/dist/internal/channel-route-dispatch.d.ts +13 -0
- package/dist/internal/channel-route-dispatch.d.ts.map +1 -0
- package/dist/internal/channel-route-dispatch.js +62 -0
- package/dist/internal/channel-state.d.ts +17 -0
- package/dist/internal/channel-state.d.ts.map +1 -0
- package/dist/internal/channel-state.js +78 -0
- package/dist/internal/cli-ax.d.ts +7 -0
- package/dist/internal/cli-ax.d.ts.map +1 -1
- package/dist/internal/cli-ax.js +99 -1
- package/dist/internal/cli-cursor.d.ts.map +1 -1
- package/dist/internal/cli-cursor.js +2 -0
- package/dist/internal/cli-deploy.d.ts.map +1 -1
- package/dist/internal/cli-deploy.js +61 -25
- package/dist/internal/cli-mcp-oauth.d.ts.map +1 -1
- package/dist/internal/cli-mcp-oauth.js +15 -0
- package/dist/internal/cli-mcp.d.ts.map +1 -1
- package/dist/internal/cli-mcp.js +12 -0
- package/dist/internal/cli-slack.d.ts.map +1 -1
- package/dist/internal/cli-slack.js +8 -2
- package/dist/internal/cursor/backend-client.d.ts +25 -0
- package/dist/internal/cursor/backend-client.d.ts.map +1 -1
- package/dist/internal/cursor/backend-client.js +57 -2
- package/dist/internal/cursor/credentials.d.ts +8 -2
- package/dist/internal/cursor/credentials.d.ts.map +1 -1
- package/dist/internal/cursor/credentials.js +27 -5
- package/dist/internal/deploy-client.d.ts +35 -0
- package/dist/internal/deploy-client.d.ts.map +1 -1
- package/dist/internal/deploy-client.js +46 -0
- package/dist/internal/deploy-manifest.d.ts +26 -0
- package/dist/internal/deploy-manifest.d.ts.map +1 -1
- package/dist/internal/deploy-manifest.js +99 -13
- package/dist/internal/describe-error.d.ts +1 -0
- package/dist/internal/describe-error.d.ts.map +1 -1
- package/dist/internal/describe-error.js +25 -0
- package/dist/internal/discovery/agent.d.ts.map +1 -1
- package/dist/internal/discovery/agent.js +1 -0
- package/dist/internal/discovery/info.d.ts.map +1 -1
- package/dist/internal/discovery/info.js +7 -3
- package/dist/internal/discovery/modules.d.ts +1 -1
- package/dist/internal/discovery/modules.d.ts.map +1 -1
- package/dist/internal/discovery/modules.js +1 -0
- package/dist/internal/discovery/project.d.ts.map +1 -1
- package/dist/internal/discovery/project.js +3 -0
- package/dist/internal/discovery/reminders.d.ts +7 -0
- package/dist/internal/discovery/reminders.d.ts.map +1 -0
- package/dist/internal/discovery/reminders.js +65 -0
- package/dist/internal/discovery/subagent.js +1 -0
- package/dist/internal/distribution.d.ts +5 -0
- package/dist/internal/distribution.d.ts.map +1 -1
- package/dist/internal/distribution.js +17 -0
- package/dist/internal/framework-storage-selection.d.ts +14 -3
- package/dist/internal/framework-storage-selection.d.ts.map +1 -1
- package/dist/internal/framework-storage-selection.js +36 -6
- package/dist/internal/guest-network.d.ts +4 -10
- package/dist/internal/guest-network.d.ts.map +1 -1
- package/dist/internal/guest-network.js +44 -26
- package/dist/internal/hosted-admission-adapter.d.ts +2 -0
- package/dist/internal/hosted-admission-adapter.d.ts.map +1 -1
- package/dist/internal/hosted-catch-protocol.d.ts +51 -0
- package/dist/internal/hosted-catch-protocol.d.ts.map +1 -0
- package/dist/internal/hosted-catch-protocol.js +103 -0
- package/dist/internal/hosted-catch.d.ts +40 -0
- package/dist/internal/hosted-catch.d.ts.map +1 -0
- package/dist/internal/hosted-catch.js +149 -0
- package/dist/internal/hosted-delivery-protocol.d.ts +89 -0
- package/dist/internal/hosted-delivery-protocol.d.ts.map +1 -1
- package/dist/internal/hosted-delivery-protocol.js +309 -0
- package/dist/internal/hosted-delivery.d.ts +20 -1
- package/dist/internal/hosted-delivery.d.ts.map +1 -1
- package/dist/internal/hosted-delivery.js +179 -36
- package/dist/internal/hosted-execution-diag.d.ts +4 -1
- package/dist/internal/hosted-execution-diag.d.ts.map +1 -1
- package/dist/internal/hosted-execution-diag.js +13 -4
- package/dist/internal/hosted-execution-flush.d.ts +3 -0
- package/dist/internal/hosted-execution-flush.d.ts.map +1 -1
- package/dist/internal/hosted-execution-flush.js +2 -4
- package/dist/internal/http-control-plane-session.d.ts +30 -0
- package/dist/internal/http-control-plane-session.d.ts.map +1 -0
- package/dist/internal/http-control-plane-session.js +83 -0
- package/dist/internal/legacy-command-guard.d.ts +22 -0
- package/dist/internal/legacy-command-guard.d.ts.map +1 -0
- package/dist/internal/legacy-command-guard.js +51 -0
- package/dist/internal/local-control-plane.d.ts +18 -2
- package/dist/internal/local-control-plane.d.ts.map +1 -1
- package/dist/internal/local-control-plane.js +199 -17
- package/dist/internal/platform-timers.d.ts +7 -0
- package/dist/internal/platform-timers.d.ts.map +1 -1
- package/dist/internal/platform-timers.js +139 -0
- package/dist/internal/reminder-control-plane-protocol.d.ts +189 -0
- package/dist/internal/reminder-control-plane-protocol.d.ts.map +1 -0
- package/dist/internal/reminder-control-plane-protocol.js +251 -0
- package/dist/internal/reminder-runner.d.ts +56 -6
- package/dist/internal/reminder-runner.d.ts.map +1 -1
- package/dist/internal/reminder-runner.js +372 -57
- package/dist/internal/reminder-schedule.d.ts +5 -2
- package/dist/internal/reminder-schedule.d.ts.map +1 -1
- package/dist/internal/reminder-schedule.js +8 -6
- package/dist/internal/reminder-store.d.ts +24 -7
- package/dist/internal/reminder-store.d.ts.map +1 -1
- package/dist/internal/reminder-store.js +6 -5
- package/dist/internal/request-error-status.d.ts +2 -0
- package/dist/internal/request-error-status.d.ts.map +1 -1
- package/dist/internal/request-error-status.js +22 -3
- package/dist/internal/resolve-prod-target.d.ts +2 -0
- package/dist/internal/resolve-prod-target.d.ts.map +1 -1
- package/dist/internal/resolve-prod-target.js +13 -0
- package/dist/internal/scm/pr-url.d.ts +40 -0
- package/dist/internal/scm/pr-url.d.ts.map +1 -1
- package/dist/internal/scm/pr-url.js +93 -14
- package/dist/internal/sdk-runner.d.ts.map +1 -1
- package/dist/internal/sdk-runner.js +4 -3
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +118 -77
- package/dist/internal/session-engine.d.ts +6 -6
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +100 -67
- package/dist/playground/assets/{index-BaQzjaNK.js → index-BMDqAeXu.js} +34 -34
- package/dist/playground/assets/index-LUgJoWdL.css +1 -0
- package/dist/playground/index.html +2 -2
- package/dist/reminders.d.ts +24 -5
- package/dist/reminders.d.ts.map +1 -1
- package/dist/reminders.js +28 -5
- 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 +29 -1
- package/dist/types.d.ts +122 -25
- package/dist/types.d.ts.map +1 -1
- package/docs/README.md +4 -0
- package/docs/deployment.md +7 -2
- package/docs/evals.md +3 -2
- package/docs/guides/cloud-agents.md +4 -3
- package/docs/guides/github.md +2 -1
- package/docs/guides/grokbot-agents.md +2 -2
- package/docs/guides/improve.md +96 -0
- package/docs/guides/opentelemetry.md +3 -4
- package/docs/guides/slack.md +2 -1
- package/docs/reference/agent-config.md +5 -2
- package/docs/reference/channels.md +11 -19
- package/docs/reference/cli.md +23 -13
- package/docs/reference/connections.md +2 -1
- package/docs/reference/extensions.md +2 -0
- package/docs/scaffolding-agents.md +2 -1
- package/docs/troubleshooting.md +1 -1
- package/package.json +10 -3
- package/skills/create-agent/SKILL.md +1 -1
- package/skills/debug/SKILL.md +1 -1
- package/skills/evals/SKILL.md +1 -1
- package/skills/framework-map/SKILL.md +4 -2
- package/skills/github/SKILL.md +1 -1
- package/skills/otel/SKILL.md +3 -3
- package/src/bin/agent-serve.ts +28 -11
- package/src/channels/bitbucket/types.ts +2 -4
- package/src/channels/deployments/types.ts +5 -8
- package/src/channels/github/github-channel.ts +8 -8
- package/src/channels/github/types.ts +7 -4
- package/src/channels/gitlab/types.ts +2 -5
- package/src/channels/origin/origin-channel.ts +29 -13
- package/src/channels/origin/types.ts +7 -3
- package/src/channels/slack/defaults.ts +3 -0
- package/src/channels/slack/dispatch.ts +1 -0
- package/src/channels/slack/live-delivery.ts +53 -12
- package/src/channels/slack/types.ts +4 -3
- package/src/channels.ts +157 -10
- package/src/connections.ts +2 -1
- package/src/extensions/improve/extension.ts +70 -0
- package/src/extensions/improve/skills/yourself.ts +50 -0
- package/src/index.ts +6 -3
- package/src/internal/builtin-tools/artifacts.ts +2 -3
- package/src/internal/channel-route-dispatch.ts +66 -0
- package/src/internal/channel-state.ts +96 -0
- package/src/internal/cli-ax.ts +110 -1
- package/src/internal/cli-cursor.ts +4 -1
- package/src/internal/cli-deploy.ts +80 -22
- package/src/internal/cli-mcp-oauth.ts +18 -0
- package/src/internal/cli-mcp.ts +11 -0
- package/src/internal/cli-slack.ts +15 -2
- package/src/internal/cursor/backend-client.ts +90 -2
- package/src/internal/cursor/credentials.ts +35 -7
- package/src/internal/deploy-client.ts +70 -0
- package/src/internal/deploy-manifest.ts +131 -12
- package/src/internal/describe-error.ts +28 -0
- package/src/internal/discovery/agent.ts +1 -0
- package/src/internal/discovery/info.ts +6 -0
- package/src/internal/discovery/modules.ts +2 -4
- package/src/internal/discovery/project.ts +3 -0
- package/src/internal/discovery/reminders.ts +65 -0
- package/src/internal/discovery/subagent.ts +1 -0
- package/src/internal/distribution.ts +20 -0
- package/src/internal/framework-storage-selection.ts +43 -6
- package/src/internal/guest-network.ts +46 -29
- package/src/internal/hosted-admission-adapter.ts +2 -0
- package/src/internal/hosted-catch-protocol.ts +130 -0
- package/src/internal/hosted-catch.ts +192 -0
- package/src/internal/hosted-delivery-protocol.ts +483 -0
- package/src/internal/hosted-delivery.ts +303 -43
- package/src/internal/hosted-execution-diag.ts +21 -3
- package/src/internal/hosted-execution-flush.ts +6 -3
- package/src/internal/http-control-plane-session.ts +104 -0
- package/src/internal/legacy-command-guard.ts +59 -0
- package/src/internal/local-control-plane.ts +281 -22
- package/src/internal/platform-timers.ts +191 -0
- package/src/internal/reminder-control-plane-protocol.ts +512 -0
- package/src/internal/reminder-runner.ts +481 -57
- package/src/internal/reminder-schedule.ts +11 -6
- package/src/internal/reminder-store.ts +27 -7
- package/src/internal/request-error-status.ts +27 -3
- package/src/internal/resolve-prod-target.ts +15 -0
- package/src/internal/scm/pr-url.ts +167 -20
- package/src/internal/sdk-runner.ts +2 -1
- package/src/internal/server.ts +151 -88
- package/src/internal/session-engine.ts +146 -83
- package/src/reminders.ts +35 -4
- package/src/storage-backends/cursor-hosted.ts +40 -1
- package/src/types.ts +134 -26
- package/dist/docs/assets/chunks/@localSearchIndexroot.CJxMklAy.js +0 -1
- package/dist/docs/assets/guides_cloud-agents.md.DS8RIjwx.js +0 -9
- package/dist/docs/assets/index.md.BW_6tOgR.js +0 -5
- package/dist/docs/assets/skills_framework-map.md.haibFyoB.js +0 -1
- package/dist/docs/assets/troubleshooting.md.Cus_YZga.js +0 -1
- package/dist/playground/assets/index-CceqnLTX.css +0 -1
- /package/dist/docs/assets/{evals.md.CbMoebP1.lean.js → evals.md.C1ekS3k2.lean.js} +0 -0
- /package/dist/docs/assets/{guides_github.md.c0gdGJ-D.lean.js → guides_github.md.BH33UEBJ.lean.js} +0 -0
- /package/dist/docs/assets/{guides_grokbot-agents.md.DVqdhBKb.lean.js → guides_grokbot-agents.md.DyV-WArv.lean.js} +0 -0
- /package/dist/docs/assets/{index.md.BW_6tOgR.lean.js → index.md.BjH1w2ZW.lean.js} +0 -0
- /package/dist/docs/assets/{reference_agent-config.md.CHNpiyp4.lean.js → reference_agent-config.md.CvoL6pof.lean.js} +0 -0
- /package/dist/docs/assets/{reference_connections.md.Di6jJAXF.lean.js → reference_connections.md.BojkC6c5.lean.js} +0 -0
- /package/dist/docs/assets/{reference_extensions.md.CGmMLblt.lean.js → reference_extensions.md.CPWt00ds.lean.js} +0 -0
- /package/dist/docs/assets/{scaffolding-agents.md.em43xlY1.lean.js → scaffolding-agents.md.Kctn3OVb.lean.js} +0 -0
- /package/dist/docs/assets/{skills_create-agent.md.BVoWPcan.lean.js → skills_create-agent.md.Q3h6Je-e.lean.js} +0 -0
- /package/dist/docs/assets/{skills_evals.md.723kpUmA.lean.js → skills_evals.md.BhovOvrl.lean.js} +0 -0
- /package/dist/docs/assets/{skills_github.md.D0JahM8c.lean.js → skills_github.md.hgFX_oKY.lean.js} +0 -0
- /package/dist/docs/assets/{skills_otel.md.CqhobH3B.lean.js → skills_otel.md.B5Ddv1xH.lean.js} +0 -0
- /package/dist/docs/assets/{troubleshooting.md.Cus_YZga.lean.js → troubleshooting.md.CYEAO9bM.lean.js} +0 -0
|
@@ -13,6 +13,8 @@ import { fileURLToPath, pathToFileURL } from "node:url";
|
|
|
13
13
|
|
|
14
14
|
/** Published npm package name (pre-launch codename for Agent SDK). */
|
|
15
15
|
export const PACKAGE_NAME = "@cursor/july";
|
|
16
|
+
const HOSTED_WORKTREE_SHA_FILENAME = ".cursor-hosted-worktree-sha";
|
|
17
|
+
const GIT_COMMIT_SHA_RE = /^[0-9a-f]{40,64}$/;
|
|
16
18
|
|
|
17
19
|
/**
|
|
18
20
|
* Bracketed product tag for stderr / ServeOptions.logger lines
|
|
@@ -59,6 +61,24 @@ export function packageVersion(): string {
|
|
|
59
61
|
return packageManifest().version;
|
|
60
62
|
}
|
|
61
63
|
|
|
64
|
+
/**
|
|
65
|
+
* Git commit of a checkout-built framework distribution. Published npm
|
|
66
|
+
* packages do not carry this marker and return undefined.
|
|
67
|
+
*/
|
|
68
|
+
export function packageGitSha(): string | undefined {
|
|
69
|
+
try {
|
|
70
|
+
const sha = readFileSync(
|
|
71
|
+
join(packageRootDir(), "dist", HOSTED_WORKTREE_SHA_FILENAME),
|
|
72
|
+
"utf8"
|
|
73
|
+
)
|
|
74
|
+
.trim()
|
|
75
|
+
.toLowerCase();
|
|
76
|
+
return GIT_COMMIT_SHA_RE.test(sha) ? sha : undefined;
|
|
77
|
+
} catch {
|
|
78
|
+
return undefined;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
62
82
|
/** Facts `agent-sdk version` / `--version` print. */
|
|
63
83
|
export interface CliVersionInfo {
|
|
64
84
|
/** Published npm name (`@cursor/july`). */
|
|
@@ -13,7 +13,10 @@
|
|
|
13
13
|
* That selection is a hosting-mode question, not an authoring question.
|
|
14
14
|
* Architecture v2 moves it here: `agent/storage.ts` is rejected at
|
|
15
15
|
* discovery (error diagnostic, so serve and deploy fail early), and the
|
|
16
|
-
* platform picks the default
|
|
16
|
+
* platform picks the default. Architecture v1 with no authored file now
|
|
17
|
+
* uses the same hosted-vs-self-hosted split, so deleting `agent/storage.ts`
|
|
18
|
+
* (required to deploy the same tree onto v2) does not drop the Cursor-hosted
|
|
19
|
+
* session mirror on a still-v1 pod.
|
|
17
20
|
*
|
|
18
21
|
* - **Cursor-managed hosting** (the deployment-generation environment
|
|
19
22
|
* variable is set, same signal that registers `GET /v1/manifest`):
|
|
@@ -33,8 +36,10 @@
|
|
|
33
36
|
* - **Self-hosted**: no mirror. `--state-root` is the durable copy, which
|
|
34
37
|
* is correct when the operator owns the disk.
|
|
35
38
|
*
|
|
36
|
-
* v1
|
|
37
|
-
*
|
|
39
|
+
* v1 still honors an authored `agent/storage.ts` when present. Hosted v1
|
|
40
|
+
* pods with no authored file get the Cursor-hosted lazy mirror (gated on
|
|
41
|
+
* `AGENT_SERVE_DEPLOYMENT_ID`, the same signal the previous authored sinks
|
|
42
|
+
* used). Self-hosted v1 with no authored file stays disk-only.
|
|
38
43
|
*
|
|
39
44
|
* Local disk is not part of this decision. `<stateRoot>/sessions/<id>/`
|
|
40
45
|
* already holds `session.json` and `events.ndjson` unconditionally, through
|
|
@@ -44,6 +49,10 @@
|
|
|
44
49
|
|
|
45
50
|
import { cursorHostedFiles } from "../files-backends/cursor-hosted.js";
|
|
46
51
|
import { defineStorage, type StorageDefinition } from "../storage.js";
|
|
52
|
+
import {
|
|
53
|
+
AGENT_SERVE_DEPLOYMENT_ID_ENV_VAR,
|
|
54
|
+
cursorHostedStorage,
|
|
55
|
+
} from "../storage-backends/cursor-hosted.js";
|
|
47
56
|
import { cursorHostedStorageV2 } from "../storage-backends/cursor-hosted-v2.js";
|
|
48
57
|
import type { AgentArchitecture } from "../types.js";
|
|
49
58
|
import { resolveApiKeySync } from "./cursor/credentials.js";
|
|
@@ -54,6 +63,13 @@ import {
|
|
|
54
63
|
} from "./framework-file-storage.js";
|
|
55
64
|
import { resolveAgentV2Hosting } from "./v2-hosting.js";
|
|
56
65
|
|
|
66
|
+
/**
|
|
67
|
+
* Hosted v2 event-chunk flush debounce. Matches the session view's live poll
|
|
68
|
+
* cadence; a streaming turn still caps each chunk at the coordinator's batch
|
|
69
|
+
* limit, so a long turn writes a few dozen chunks rather than one per event.
|
|
70
|
+
*/
|
|
71
|
+
export const HOSTED_V2_EVENT_FLUSH_DEBOUNCE_MS = 2_000;
|
|
72
|
+
|
|
57
73
|
export interface FrameworkStorageSelectionInput {
|
|
58
74
|
/** `agent/storage.ts`, when the author wrote one (v1 only: discovery rejects it on v2). */
|
|
59
75
|
readonly authored: StorageDefinition | undefined;
|
|
@@ -73,8 +89,21 @@ export function selectFrameworkStorageDefinition(
|
|
|
73
89
|
input: FrameworkStorageSelectionInput
|
|
74
90
|
): StorageDefinition | undefined {
|
|
75
91
|
if (input.architecture !== "v2") {
|
|
76
|
-
|
|
77
|
-
|
|
92
|
+
if (input.authored !== undefined) {
|
|
93
|
+
return input.authored;
|
|
94
|
+
}
|
|
95
|
+
const env = input.env ?? process.env;
|
|
96
|
+
if ((env[AGENT_SERVE_DEPLOYMENT_ID_ENV_VAR] ?? "").trim() !== "") {
|
|
97
|
+
// Hosted v1 pod with no authored sink: keep the Cursor-hosted
|
|
98
|
+
// mirror (lazy restore) so agents can delete `agent/storage.ts`
|
|
99
|
+
// without losing durability while they still run architecture v1.
|
|
100
|
+
return defineStorage({
|
|
101
|
+
name: "cursor-hosted (lazy restore)",
|
|
102
|
+
policy: { restore: "off" },
|
|
103
|
+
...cursorHostedStorage(),
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
return undefined;
|
|
78
107
|
}
|
|
79
108
|
if (input.authored !== undefined) {
|
|
80
109
|
// Discovery rejects agent/storage.ts on v2 before an engine is built;
|
|
@@ -97,7 +126,15 @@ export function selectFrameworkStorageDefinition(
|
|
|
97
126
|
// backend it is per-key HTTP round trips before the listener even
|
|
98
127
|
// comes up). Follow-ups restore lazily by continuation or session id;
|
|
99
128
|
// GET /v1/sessions lists from the sink either way.
|
|
100
|
-
|
|
129
|
+
//
|
|
130
|
+
// Events flush on a quiet-period debounce rather than only at turn end so
|
|
131
|
+
// the read-only session view and dashboard trace (which have no resident
|
|
132
|
+
// engine to ask) see steps mid-turn. The turn-end record still lands
|
|
133
|
+
// before the execution reply: drainSessionDurability forces the flush.
|
|
134
|
+
const policy = {
|
|
135
|
+
restore: "off",
|
|
136
|
+
debounceMs: HOSTED_V2_EVENT_FLUSH_DEBOUNCE_MS,
|
|
137
|
+
} as const;
|
|
101
138
|
// Full chain (env → bind file → stored login): frozen engines listen
|
|
102
139
|
// unsigned and bind store ids + CURSOR_API_KEY at task time, after this
|
|
103
140
|
// definition is constructed.
|
|
@@ -12,13 +12,13 @@
|
|
|
12
12
|
* so leftover races still return 503 `guest_network_unavailable` instead of
|
|
13
13
|
* a redacted 500.
|
|
14
14
|
*
|
|
15
|
-
* Quiet guest Connect
|
|
16
|
-
* `
|
|
17
|
-
*
|
|
18
|
-
* retries the same pod — including when `waitForCompletion` resolves
|
|
19
|
-
* with that message instead of throwing.
|
|
15
|
+
* Quiet guest Connect failures with a typed Connect/undici code are stalls,
|
|
16
|
+
* not dead NICs. Those become `guest_connect_stalled` so TAS retries the same
|
|
17
|
+
* pod. Untyped errors stay unknown rather than being classified from prose.
|
|
20
18
|
*/
|
|
21
19
|
|
|
20
|
+
import { HOSTED_GUEST_RETRY_TRANSIENT } from "./hosted-delivery-protocol.js";
|
|
21
|
+
|
|
22
22
|
export const GUEST_NETWORK_UNAVAILABLE = "guest_network_unavailable";
|
|
23
23
|
export const GUEST_CONNECT_STALLED = "guest_connect_stalled";
|
|
24
24
|
|
|
@@ -69,11 +69,16 @@ export class GuestNetworkUnavailableError extends Error {
|
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
+
class GuestNetworkProbeFailedError extends Error {
|
|
73
|
+
constructor(cause: unknown) {
|
|
74
|
+
super("Guest network probe failed", { cause });
|
|
75
|
+
this.name = "GuestNetworkProbeFailedError";
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
72
79
|
/**
|
|
73
80
|
* True when the error (or anything on its `cause` chain, or inside an
|
|
74
|
-
* `AggregateError`)
|
|
75
|
-
* undici's `TypeError: fetch failed` as `ConnectError` and keeps the
|
|
76
|
-
* original on `cause`.
|
|
81
|
+
* `AggregateError`) carries a known network-level code.
|
|
77
82
|
*/
|
|
78
83
|
export function isTransientGuestNetworkError(error: unknown): boolean {
|
|
79
84
|
return isTransientAtDepth(error, 0);
|
|
@@ -89,9 +94,8 @@ const QUIET_CONNECT_ERROR_CODES: ReadonlySet<string> = new Set([
|
|
|
89
94
|
"UND_ERR_BODY_TIMEOUT",
|
|
90
95
|
"UND_ERR_HEADERS_TIMEOUT",
|
|
91
96
|
]);
|
|
92
|
-
|
|
93
|
-
const
|
|
94
|
-
/^(?:\[(?:unknown|canceled|unavailable)\])|connection stalled|this operation was aborted/i;
|
|
97
|
+
// gRPC Canceled, Unknown, and Unavailable.
|
|
98
|
+
const QUIET_CONNECT_CODES: ReadonlySet<number> = new Set([1, 2, 14]);
|
|
95
99
|
|
|
96
100
|
export function hasGuestNetworkErrno(error: unknown): boolean {
|
|
97
101
|
return hasCodeAtDepth(error, 0, TRANSIENT_NETWORK_ERROR_CODES);
|
|
@@ -113,16 +117,16 @@ export function isQuietGuestConnectStall(error: unknown): boolean {
|
|
|
113
117
|
return isQuietSignatureAtDepth(error, 0);
|
|
114
118
|
}
|
|
115
119
|
|
|
116
|
-
/** Message-only form for `waitForCompletion` outcomes that do not throw. */
|
|
117
|
-
export function isQuietGuestConnectStallMessage(message: string): boolean {
|
|
118
|
-
return QUIET_CONNECT_MESSAGE.test(message);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
120
|
function errorCode(error: Error): string | undefined {
|
|
122
121
|
const code = (error as NodeJS.ErrnoException).code;
|
|
123
122
|
return typeof code === "string" && code.length > 0 ? code : undefined;
|
|
124
123
|
}
|
|
125
124
|
|
|
125
|
+
function numericErrorCode(error: Error): number | undefined {
|
|
126
|
+
const code = (error as { code?: unknown }).code;
|
|
127
|
+
return typeof code === "number" ? code : undefined;
|
|
128
|
+
}
|
|
129
|
+
|
|
126
130
|
function hasCodeAtDepth(
|
|
127
131
|
error: unknown,
|
|
128
132
|
depth: number,
|
|
@@ -148,14 +152,15 @@ function isQuietSignatureAtDepth(error: unknown, depth: number): boolean {
|
|
|
148
152
|
if (depth >= MAX_CAUSE_DEPTH || !(error instanceof Error)) {
|
|
149
153
|
return false;
|
|
150
154
|
}
|
|
151
|
-
if (error
|
|
155
|
+
if (error.name === "AbortError") {
|
|
152
156
|
return true;
|
|
153
157
|
}
|
|
154
|
-
const
|
|
155
|
-
if (
|
|
158
|
+
const numericCode = numericErrorCode(error);
|
|
159
|
+
if (numericCode !== undefined && QUIET_CONNECT_CODES.has(numericCode)) {
|
|
156
160
|
return true;
|
|
157
161
|
}
|
|
158
|
-
|
|
162
|
+
const code = errorCode(error);
|
|
163
|
+
if (code !== undefined && QUIET_CONNECT_ERROR_CODES.has(code)) {
|
|
159
164
|
return true;
|
|
160
165
|
}
|
|
161
166
|
if (
|
|
@@ -171,10 +176,17 @@ function isTransientAtDepth(error: unknown, depth: number): boolean {
|
|
|
171
176
|
if (depth >= MAX_CAUSE_DEPTH || !(error instanceof Error)) {
|
|
172
177
|
return false;
|
|
173
178
|
}
|
|
174
|
-
if (error instanceof
|
|
179
|
+
if (error instanceof GuestNetworkUnavailableError) {
|
|
175
180
|
return true;
|
|
176
181
|
}
|
|
177
|
-
if (error instanceof
|
|
182
|
+
if (error instanceof GuestNetworkProbeFailedError) {
|
|
183
|
+
return true;
|
|
184
|
+
}
|
|
185
|
+
if (error.name === "AbortError") {
|
|
186
|
+
return true;
|
|
187
|
+
}
|
|
188
|
+
const numericCode = numericErrorCode(error);
|
|
189
|
+
if (numericCode !== undefined && QUIET_CONNECT_CODES.has(numericCode)) {
|
|
178
190
|
return true;
|
|
179
191
|
}
|
|
180
192
|
const code = errorCode(error);
|
|
@@ -247,13 +259,17 @@ async function defaultProbe(
|
|
|
247
259
|
probeUrl: string,
|
|
248
260
|
probeTimeoutMs: number
|
|
249
261
|
): Promise<void> {
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
262
|
+
try {
|
|
263
|
+
// Any HTTP response means egress and DNS work. 401/404 are ready.
|
|
264
|
+
const response = await fetch(probeUrl, {
|
|
265
|
+
method: "GET",
|
|
266
|
+
redirect: "manual",
|
|
267
|
+
signal: AbortSignal.timeout(probeTimeoutMs),
|
|
268
|
+
});
|
|
269
|
+
void response.body?.cancel();
|
|
270
|
+
} catch (error) {
|
|
271
|
+
throw new GuestNetworkProbeFailedError(error);
|
|
272
|
+
}
|
|
257
273
|
}
|
|
258
274
|
|
|
259
275
|
export type GuestNetworkWaitOutcome = "ready" | "skipped" | "unavailable";
|
|
@@ -369,6 +385,7 @@ export async function guestNetworkReadinessResponse(
|
|
|
369
385
|
JSON.stringify({
|
|
370
386
|
ok: false,
|
|
371
387
|
error: GUEST_NETWORK_UNAVAILABLE,
|
|
388
|
+
retry: HOSTED_GUEST_RETRY_TRANSIENT,
|
|
372
389
|
message: error.message,
|
|
373
390
|
waitMs: error.waitMs,
|
|
374
391
|
probeAttempts: error.probeAttempts,
|
|
@@ -19,6 +19,8 @@ export type HostedAdmissionAdapter = {
|
|
|
19
19
|
*/
|
|
20
20
|
prepareArgs?(args: ChannelHandlerArgs): ChannelHandlerArgs;
|
|
21
21
|
dispatch(input: {
|
|
22
|
+
/** Mounted channel id the delivery addressed (always set by hosted delivery). */
|
|
23
|
+
channelId?: string;
|
|
22
24
|
eventType: string;
|
|
23
25
|
payload: unknown;
|
|
24
26
|
deliveryId: string;
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Catch ingress wire contract, July copy. The control plane keeps a
|
|
3
|
+
* byte-identical copy of these constants in
|
|
4
|
+
* `backend/packages/server-shared/src/agentServe/agentSdkCatch.ts`; a
|
|
5
|
+
* backend drift test compares the two as text. Neither package imports the
|
|
6
|
+
* other.
|
|
7
|
+
*
|
|
8
|
+
* A caught request is one hosted admission whose `eventType` is
|
|
9
|
+
* {@link AGENT_SDK_CATCH_EVENT_TYPE} and whose `payload` is a
|
|
10
|
+
* {@link CatchRequestEnvelope}: the HTTP request the control plane
|
|
11
|
+
* accepted on a manifest-declared route after verifying the deployment's
|
|
12
|
+
* secret. July replays it into the authored route handler; the control
|
|
13
|
+
* plane never runs channel code.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
export const AGENT_SDK_CATCH_ENVELOPE_VERSION = 1;
|
|
17
|
+
export const AGENT_SDK_CATCH_EVENT_TYPE = "http.request";
|
|
18
|
+
export const AGENT_SDK_CUSTOM_CHANNEL_KIND = "custom";
|
|
19
|
+
export const AGENT_SDK_SESSION_EVENT_TYPE = "agentsdk.session";
|
|
20
|
+
export const AGENT_SDK_HTTP_CHANNEL_ID = "http";
|
|
21
|
+
export const AGENT_SDK_HTTP_CHANNEL_KIND = "http";
|
|
22
|
+
export const AGENT_SDK_SESSION_RESUME_KEY_PREFIX = "cont:session:";
|
|
23
|
+
export const AGENT_SDK_CATCH_MAX_BODY_BYTES: number = 256 * 1024;
|
|
24
|
+
|
|
25
|
+
export const AGENT_SDK_CATCH_ROUTE_METHODS = [
|
|
26
|
+
"GET",
|
|
27
|
+
"POST",
|
|
28
|
+
"PUT",
|
|
29
|
+
"PATCH",
|
|
30
|
+
"DELETE",
|
|
31
|
+
] as const;
|
|
32
|
+
export type CatchRouteMethod = (typeof AGENT_SDK_CATCH_ROUTE_METHODS)[number];
|
|
33
|
+
|
|
34
|
+
export type CatchRequestEnvelope = {
|
|
35
|
+
v: 1;
|
|
36
|
+
method: CatchRouteMethod;
|
|
37
|
+
/** Channel-relative path, e.g. `/webhook`. */
|
|
38
|
+
path: string;
|
|
39
|
+
/** Raw query string without the leading `?`; empty when absent. */
|
|
40
|
+
query: string;
|
|
41
|
+
/** Lowercased header names. */
|
|
42
|
+
headers: Record<string, string>;
|
|
43
|
+
body: { encoding: "utf8" | "base64"; data: string } | null;
|
|
44
|
+
receivedAt: string;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Mailbox key the control plane stamps on an explicit `ses_…` resume. The
|
|
49
|
+
* suffix is the CP session id the hosted execution also names, so the
|
|
50
|
+
* engine can recognise the key as "this existing session" rather than a
|
|
51
|
+
* new continuation identity.
|
|
52
|
+
*/
|
|
53
|
+
export function hostedSessionResumeKey(sessionPublicId: string): string {
|
|
54
|
+
return `${AGENT_SDK_SESSION_RESUME_KEY_PREFIX}${sessionPublicId}`;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const ENVELOPE_KEYS = new Set([
|
|
58
|
+
"v",
|
|
59
|
+
"method",
|
|
60
|
+
"path",
|
|
61
|
+
"query",
|
|
62
|
+
"headers",
|
|
63
|
+
"body",
|
|
64
|
+
"receivedAt",
|
|
65
|
+
]);
|
|
66
|
+
const METHODS = new Set<string>(AGENT_SDK_CATCH_ROUTE_METHODS);
|
|
67
|
+
const MAX_PATH_CHARS = 1024;
|
|
68
|
+
const MAX_QUERY_CHARS = 4096;
|
|
69
|
+
const MAX_HEADER_COUNT = 64;
|
|
70
|
+
const MAX_HEADER_BYTES = 16 * 1024;
|
|
71
|
+
|
|
72
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
73
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** Strict parse of a claim-checked catch envelope; anything else is undefined. */
|
|
77
|
+
export function parseCatchRequestEnvelope(
|
|
78
|
+
value: unknown
|
|
79
|
+
): CatchRequestEnvelope | undefined {
|
|
80
|
+
if (!isRecord(value)) {
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
83
|
+
if (
|
|
84
|
+
Object.keys(value).some((key) => !ENVELOPE_KEYS.has(key)) ||
|
|
85
|
+
value.v !== AGENT_SDK_CATCH_ENVELOPE_VERSION ||
|
|
86
|
+
typeof value.method !== "string" ||
|
|
87
|
+
!METHODS.has(value.method) ||
|
|
88
|
+
typeof value.path !== "string" ||
|
|
89
|
+
!value.path.startsWith("/") ||
|
|
90
|
+
value.path.length > MAX_PATH_CHARS ||
|
|
91
|
+
typeof value.query !== "string" ||
|
|
92
|
+
value.query.length > MAX_QUERY_CHARS ||
|
|
93
|
+
typeof value.receivedAt !== "string" ||
|
|
94
|
+
!isRecord(value.headers)
|
|
95
|
+
) {
|
|
96
|
+
return undefined;
|
|
97
|
+
}
|
|
98
|
+
const entries = Object.entries(value.headers);
|
|
99
|
+
if (entries.length > MAX_HEADER_COUNT) {
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
let headerBytes = 0;
|
|
103
|
+
for (const [name, headerValue] of entries) {
|
|
104
|
+
if (typeof headerValue !== "string" || name !== name.toLowerCase()) {
|
|
105
|
+
return undefined;
|
|
106
|
+
}
|
|
107
|
+
headerBytes += name.length + headerValue.length;
|
|
108
|
+
}
|
|
109
|
+
if (headerBytes > MAX_HEADER_BYTES) {
|
|
110
|
+
return undefined;
|
|
111
|
+
}
|
|
112
|
+
if (value.body !== null) {
|
|
113
|
+
if (
|
|
114
|
+
!isRecord(value.body) ||
|
|
115
|
+
(value.body.encoding !== "utf8" && value.body.encoding !== "base64") ||
|
|
116
|
+
typeof value.body.data !== "string"
|
|
117
|
+
) {
|
|
118
|
+
return undefined;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return value as CatchRequestEnvelope;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** Raw request bytes from an envelope body; empty for a null body. */
|
|
125
|
+
export function decodeCatchBody(body: CatchRequestEnvelope["body"]): Buffer {
|
|
126
|
+
if (body === null) {
|
|
127
|
+
return Buffer.alloc(0);
|
|
128
|
+
}
|
|
129
|
+
return Buffer.from(body.data, body.encoding);
|
|
130
|
+
}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hosted admission for caught HTTP requests.
|
|
3
|
+
*
|
|
4
|
+
* The control plane accepted a request on one of this channel's declared
|
|
5
|
+
* routes, verified the deployment's secret, and claim-checked the request
|
|
6
|
+
* as a {@link CatchRequestEnvelope}. Admission replays that request into
|
|
7
|
+
* the authored route handler exactly as the local router would have
|
|
8
|
+
* (same route table, same Zod schema gate), with the control plane as the
|
|
9
|
+
* authenticated principal. A captured `send()` becomes the pending send;
|
|
10
|
+
* a handler that answers without sending is a `skip`.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import type {
|
|
14
|
+
AuthContext,
|
|
15
|
+
ChannelDefinition,
|
|
16
|
+
ChannelHandlerArgs,
|
|
17
|
+
ChannelRoute,
|
|
18
|
+
} from "../types.js";
|
|
19
|
+
import {
|
|
20
|
+
acknowledgeTurn,
|
|
21
|
+
dispatchOutcome,
|
|
22
|
+
skipped,
|
|
23
|
+
tagOutcome,
|
|
24
|
+
} from "./channel-dispatch.js";
|
|
25
|
+
import { invokeChannelRoute } from "./channel-route-dispatch.js";
|
|
26
|
+
import { DeferredChannelSessionError } from "./deferred-channel-session.js";
|
|
27
|
+
import { attachHostedAdmissionAdapter } from "./hosted-admission-adapter.js";
|
|
28
|
+
import {
|
|
29
|
+
AGENT_SDK_CATCH_EVENT_TYPE,
|
|
30
|
+
AGENT_SDK_CUSTOM_CHANNEL_KIND,
|
|
31
|
+
type CatchRequestEnvelope,
|
|
32
|
+
decodeCatchBody,
|
|
33
|
+
parseCatchRequestEnvelope,
|
|
34
|
+
} from "./hosted-catch-protocol.js";
|
|
35
|
+
import { errorResponse } from "./http-channel.js";
|
|
36
|
+
import { Router } from "./router.js";
|
|
37
|
+
|
|
38
|
+
/** Header a replayed request carries so handlers can dedupe on delivery. */
|
|
39
|
+
export const CATCH_DELIVERY_ID_HEADER = "x-agent-sdk-delivery-id";
|
|
40
|
+
/** Placeholder origin for replayed requests; handlers see a well-formed URL. */
|
|
41
|
+
const CATCH_REQUEST_ORIGIN = "http://agent-sdk.hosted";
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Principal for a replayed request. The deployment secret was checked by
|
|
45
|
+
* the control plane before compute existed; the channel's own auth chain
|
|
46
|
+
* does not run again in the VM.
|
|
47
|
+
*/
|
|
48
|
+
export const CATCH_AUTH_CONTEXT: AuthContext = {
|
|
49
|
+
authenticator: "control-plane-catch",
|
|
50
|
+
principalId: "agent-sdk:catch",
|
|
51
|
+
principalType: "runtime",
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const BODYLESS_METHODS = new Set(["GET", "HEAD"]);
|
|
55
|
+
|
|
56
|
+
export function catchRequestFromEnvelope(input: {
|
|
57
|
+
channelId: string;
|
|
58
|
+
deliveryId: string;
|
|
59
|
+
envelope: CatchRequestEnvelope;
|
|
60
|
+
}): Request {
|
|
61
|
+
const { envelope } = input;
|
|
62
|
+
const url = `${CATCH_REQUEST_ORIGIN}/v1/channels/${input.channelId}${envelope.path}${
|
|
63
|
+
envelope.query === "" ? "" : `?${envelope.query}`
|
|
64
|
+
}`;
|
|
65
|
+
const headers = new Headers(envelope.headers);
|
|
66
|
+
headers.set(CATCH_DELIVERY_ID_HEADER, input.deliveryId);
|
|
67
|
+
const body = decodeCatchBody(envelope.body);
|
|
68
|
+
return new Request(url, {
|
|
69
|
+
method: envelope.method,
|
|
70
|
+
headers,
|
|
71
|
+
body:
|
|
72
|
+
body.length === 0 || BODYLESS_METHODS.has(envelope.method)
|
|
73
|
+
? undefined
|
|
74
|
+
: new Uint8Array(body),
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export async function replayCatchRequest(input: {
|
|
79
|
+
channelId: string;
|
|
80
|
+
deliveryId: string;
|
|
81
|
+
routes: readonly ChannelRoute[];
|
|
82
|
+
payload: unknown;
|
|
83
|
+
args: ChannelHandlerArgs;
|
|
84
|
+
}): Promise<Response> {
|
|
85
|
+
const envelope = parseCatchRequestEnvelope(input.payload);
|
|
86
|
+
if (envelope === undefined) {
|
|
87
|
+
return errorResponse(
|
|
88
|
+
400,
|
|
89
|
+
"invalid_catch_envelope",
|
|
90
|
+
"Expected a supported Agent SDK catch request envelope."
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
const router = new Router();
|
|
94
|
+
for (const route of input.routes) {
|
|
95
|
+
router.add({
|
|
96
|
+
method: route.method,
|
|
97
|
+
pattern: route.path,
|
|
98
|
+
auth: "none",
|
|
99
|
+
handler: () => errorResponse(500, "unreachable", "unreachable"),
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
const matched = router.match(envelope.method, envelope.path);
|
|
103
|
+
const route = input.routes.find(
|
|
104
|
+
(candidate) =>
|
|
105
|
+
candidate.method === matched?.route.method &&
|
|
106
|
+
candidate.path === matched.route.pattern
|
|
107
|
+
);
|
|
108
|
+
if (matched === undefined || route === undefined) {
|
|
109
|
+
// The control plane routes from the same pinned manifest this VM was
|
|
110
|
+
// frozen from; a miss here is drift, not a caller error.
|
|
111
|
+
return errorResponse(
|
|
112
|
+
404,
|
|
113
|
+
"route_not_declared",
|
|
114
|
+
`No ${envelope.method} ${envelope.path} route is mounted on channel "${input.channelId}".`
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
const request = catchRequestFromEnvelope({
|
|
118
|
+
channelId: input.channelId,
|
|
119
|
+
deliveryId: input.deliveryId,
|
|
120
|
+
envelope,
|
|
121
|
+
});
|
|
122
|
+
let response: Response;
|
|
123
|
+
try {
|
|
124
|
+
response = await invokeChannelRoute({
|
|
125
|
+
route,
|
|
126
|
+
request,
|
|
127
|
+
handlerArgs: {
|
|
128
|
+
...input.args,
|
|
129
|
+
params: matched.params,
|
|
130
|
+
auth: CATCH_AUTH_CONTEXT,
|
|
131
|
+
},
|
|
132
|
+
});
|
|
133
|
+
} catch (error) {
|
|
134
|
+
// `return Response.json({ sessionId: session.id })` after `send()` is
|
|
135
|
+
// the ordinary local webhook shape. Hosted, `send()` is captured and the
|
|
136
|
+
// handle is deferred, so reading `.id` throws — but nobody reads this
|
|
137
|
+
// handler's HTTP reply hosted; the captured send is the outcome.
|
|
138
|
+
if (error instanceof DeferredChannelSessionError) {
|
|
139
|
+
return acknowledgeTurn();
|
|
140
|
+
}
|
|
141
|
+
throw error;
|
|
142
|
+
}
|
|
143
|
+
// A 2xx the handler did not tag and in which nothing was captured means
|
|
144
|
+
// it handled the request itself (acknowledged, ignored, replied). There is
|
|
145
|
+
// nothing to execute: report skip instead of failing the delivery.
|
|
146
|
+
if (response.ok && dispatchOutcome(response) === undefined) {
|
|
147
|
+
return tagOutcome(response, "skip");
|
|
148
|
+
}
|
|
149
|
+
// A 4xx is the handler rejecting the sender (bad signature on a
|
|
150
|
+
// handler-verified `publicEndpoint()` route, schema mismatch, unknown
|
|
151
|
+
// event). The sender already has its 202; retrying the delivery cannot
|
|
152
|
+
// change the verdict, so report a cheap skip that lets the control plane
|
|
153
|
+
// discard the compute instead of failing and retrying the activity.
|
|
154
|
+
if (response.status >= 400 && response.status < 500) {
|
|
155
|
+
// Logged so a probed public route or a misconfigured provider secret is
|
|
156
|
+
// distinguishable from a benign "nothing to do" skip in the guest logs;
|
|
157
|
+
// the wire outcome to the control plane is still `skip`.
|
|
158
|
+
console.info(
|
|
159
|
+
`[agent-sdk] catch replay rejected by handler deliveryId=${input.deliveryId} channelId=${input.channelId} route=${envelope.method} ${route.path} status=${String(response.status)}`
|
|
160
|
+
);
|
|
161
|
+
return skipped(`handler rejected the request (${response.status})`, {
|
|
162
|
+
status: response.status,
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
return response;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Attach catch admission to an authored channel. Provider packs attach
|
|
170
|
+
* their own adapter afterwards and replace this one; the control plane
|
|
171
|
+
* never sends `http.request` to a pack kind in any case.
|
|
172
|
+
*/
|
|
173
|
+
export function attachCatchAdmission(
|
|
174
|
+
definition: ChannelDefinition<unknown>,
|
|
175
|
+
routes: readonly ChannelRoute[]
|
|
176
|
+
): void {
|
|
177
|
+
attachHostedAdmissionAdapter(definition, {
|
|
178
|
+
kind: definition.meta?.kind ?? AGENT_SDK_CUSTOM_CHANNEL_KIND,
|
|
179
|
+
dispatch: ({ channelId, eventType, payload, deliveryId, args }) => {
|
|
180
|
+
if (eventType !== AGENT_SDK_CATCH_EVENT_TYPE) {
|
|
181
|
+
return Promise.resolve(skipped("not a caught http request"));
|
|
182
|
+
}
|
|
183
|
+
return replayCatchRequest({
|
|
184
|
+
channelId: channelId ?? "channel",
|
|
185
|
+
deliveryId,
|
|
186
|
+
routes,
|
|
187
|
+
payload,
|
|
188
|
+
args,
|
|
189
|
+
});
|
|
190
|
+
},
|
|
191
|
+
});
|
|
192
|
+
}
|