@cursor/july 0.1.94 → 0.1.96
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 +3 -4
- package/dist/channels/deployments/types.d.ts +1 -1
- package/dist/channels/deployments/types.d.ts.map +1 -1
- package/dist/channels/deployments/types.js +1 -0
- package/dist/channels/github/github-channel.d.ts.map +1 -1
- package/dist/channels/github/github-channel.js +14 -2
- package/dist/channels/github/types.d.ts +18 -3
- package/dist/channels/github/types.d.ts.map +1 -1
- package/dist/channels/origin/api.d.ts +59 -13
- package/dist/channels/origin/api.d.ts.map +1 -1
- package/dist/channels/origin/api.js +168 -27
- package/dist/channels/origin/binding.d.ts +2 -2
- package/dist/channels/origin/checks.d.ts +6 -6
- package/dist/channels/origin/checks.js +6 -6
- package/dist/channels/origin/cursor-account.d.ts +5 -3
- package/dist/channels/origin/cursor-account.d.ts.map +1 -1
- package/dist/channels/origin/cursor-account.js +5 -3
- package/dist/channels/origin/origin-channel.d.ts.map +1 -1
- package/dist/channels/origin/origin-channel.js +11 -3
- package/dist/channels/origin/origin-webhook.d.ts +11 -1
- package/dist/channels/origin/origin-webhook.d.ts.map +1 -1
- package/dist/channels/origin/origin-webhook.js +23 -3
- package/dist/channels/origin/types.d.ts +8 -0
- package/dist/channels/origin/types.d.ts.map +1 -1
- package/dist/channels/slack/api.d.ts +9 -0
- package/dist/channels/slack/api.d.ts.map +1 -1
- package/dist/channels/slack/api.js +36 -5
- package/dist/channels/slack/defaults.d.ts.map +1 -1
- package/dist/channels/slack/defaults.js +17 -46
- package/dist/channels/slack/dispatch.d.ts +7 -1
- package/dist/channels/slack/dispatch.d.ts.map +1 -1
- package/dist/channels/slack/dispatch.js +47 -23
- package/dist/channels/slack/inbound.d.ts +8 -0
- package/dist/channels/slack/inbound.d.ts.map +1 -1
- package/dist/channels/slack/inbound.js +32 -0
- package/dist/channels/slack/live-delivery.d.ts +26 -29
- package/dist/channels/slack/live-delivery.d.ts.map +1 -1
- package/dist/channels/slack/live-delivery.js +172 -73
- package/dist/channels/slack/manifest.d.ts.map +1 -1
- package/dist/channels/slack/manifest.js +5 -1
- package/dist/channels/slack/nudge-carrier.d.ts +2 -0
- package/dist/channels/slack/nudge-carrier.d.ts.map +1 -1
- package/dist/channels/slack/nudge-carrier.js +48 -1
- package/dist/channels/slack/pr-ref.d.ts +7 -1
- package/dist/channels/slack/pr-ref.d.ts.map +1 -1
- package/dist/channels/slack/pr-ref.js +42 -23
- package/dist/channels/slack/slack-channel.d.ts.map +1 -1
- package/dist/channels/slack/slack-channel.js +2 -2
- package/dist/docs/404.html +2 -2
- package/dist/docs/ab.html +4 -4
- package/dist/docs/assets/{app.CFDEas4I.js → app.jXleCmOc.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.DFoGuETX.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.B1IIYpYS.js → VPLocalSearchBox.8LhyglIT.js} +1 -1
- package/dist/docs/assets/chunks/{theme.Ct4NSiLm.js → theme.9ged-pr2.js} +2 -2
- package/dist/docs/assets/index.md.CI93Ltlb.js +5 -0
- package/dist/docs/assets/{index.md.DRakGHFe.lean.js → index.md.CI93Ltlb.lean.js} +1 -1
- package/dist/docs/assets/{reference_cli.md.Cw6_ICYG.js → reference_cli.md.CCnG-nJx.js} +4 -2
- package/dist/docs/assets/{reference_cli.md.Cw6_ICYG.lean.js → reference_cli.md.CCnG-nJx.lean.js} +1 -1
- package/dist/docs/assets/{reference_skills.md.8son6Hjm.js → reference_skills.md.BFW9retM.js} +3 -3
- package/dist/docs/assets/{templates_agentic-owners.md.DqtPdm6f.js → templates_agentic-owners.md.BZSH4N9z.js} +1 -1
- package/dist/docs/assets/templates_code-wiki.md.CDYZIBFN.js +2 -0
- package/dist/docs/assets/templates_code-wiki.md.CDYZIBFN.lean.js +1 -0
- package/dist/docs/assets/{templates_demo.md.DhFcWN6j.js → templates_demo.md.BeQX9V3H.js} +1 -1
- package/dist/docs/assets/{templates_pr-autofixer.md.DU7dQpor.js → templates_pr-autofixer.md.x5zl6-GT.js} +2 -2
- package/dist/docs/assets/{templates_pr-autofixer.md.DU7dQpor.lean.js → templates_pr-autofixer.md.x5zl6-GT.lean.js} +1 -1
- package/dist/docs/assets/templates_security-help.md.C3Ny_Qr2.js +4 -0
- package/dist/docs/assets/templates_security-help.md.C3Ny_Qr2.lean.js +1 -0
- package/dist/docs/assets/{templates_security-reviewer.md.CTa7u_l1.js → templates_security-reviewer.md.lshxbCLK.js} +2 -2
- package/dist/docs/assets/{templates_security-reviewer.md.CTa7u_l1.lean.js → templates_security-reviewer.md.lshxbCLK.lean.js} +1 -1
- package/dist/docs/assets/{templates_triage.md.CVlpctKS.js → templates_triage.md.Co4UNzkZ.js} +3 -3
- package/dist/docs/assets/{templates_triage.md.CVlpctKS.lean.js → templates_triage.md.Co4UNzkZ.lean.js} +1 -1
- package/dist/docs/building-with-agents.html +4 -4
- package/dist/docs/concepts.html +4 -4
- package/dist/docs/deployment.html +4 -4
- package/dist/docs/evals.html +4 -4
- 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 +4 -4
- package/dist/docs/guides/human-in-the-loop.html +4 -4
- package/dist/docs/guides/mcp-oauth.html +4 -4
- package/dist/docs/guides/opentelemetry.html +4 -4
- package/dist/docs/guides/slack.html +4 -4
- package/dist/docs/guides/webhooks.html +4 -4
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +4 -4
- package/dist/docs/index.html +6 -6
- package/dist/docs/index.md +5 -1
- package/dist/docs/llms-full.txt +189 -26
- package/dist/docs/llms.txt +2 -0
- package/dist/docs/quickstart.html +4 -4
- package/dist/docs/reference/agent-config.html +4 -4
- package/dist/docs/reference/artifacts.html +4 -4
- package/dist/docs/reference/channels.html +4 -4
- package/dist/docs/reference/cli.html +8 -6
- package/dist/docs/reference/cli.md +4 -1
- package/dist/docs/reference/connections.html +4 -4
- package/dist/docs/reference/hooks.html +4 -4
- package/dist/docs/reference/http-api.html +4 -4
- 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 +7 -7
- package/dist/docs/reference/subagents.html +4 -4
- package/dist/docs/reference/tools.html +4 -4
- package/dist/docs/scaffolding-agents.html +4 -4
- package/dist/docs/storage.html +4 -4
- package/dist/docs/templates/agentic-owners.html +7 -7
- package/dist/docs/templates/agentic-owners.md +1 -1
- package/dist/docs/templates/code-wiki.html +28 -0
- package/dist/docs/templates/code-wiki.md +91 -0
- package/dist/docs/templates/demo.html +6 -6
- package/dist/docs/templates/demo.md +3 -2
- package/dist/docs/templates/pr-autofixer.html +6 -6
- package/dist/docs/templates/pr-autofixer.md +7 -13
- package/dist/docs/templates/security-help.html +30 -0
- package/dist/docs/templates/security-help.md +65 -0
- package/dist/docs/templates/security-reviewer.html +6 -6
- package/dist/docs/templates/security-reviewer.md +1 -2
- package/dist/docs/templates/triage.html +7 -7
- package/dist/docs/templates/triage.md +2 -6
- package/dist/docs/troubleshooting.html +4 -4
- package/dist/files-backends/cursor-hosted.d.ts +26 -0
- package/dist/files-backends/cursor-hosted.d.ts.map +1 -1
- package/dist/files-backends/cursor-hosted.js +32 -4
- package/dist/files.d.ts +2 -0
- package/dist/files.d.ts.map +1 -1
- package/dist/files.js +5 -0
- package/dist/internal/advertise-tools.d.ts +2 -0
- package/dist/internal/advertise-tools.d.ts.map +1 -1
- package/dist/internal/advertise-tools.js +15 -1
- package/dist/internal/bounded.d.ts +7 -0
- package/dist/internal/bounded.d.ts.map +1 -0
- package/dist/internal/bounded.js +32 -0
- package/dist/internal/cli-deploy.d.ts.map +1 -1
- package/dist/internal/cli-deploy.js +142 -7
- package/dist/internal/conversation-mirror.d.ts +85 -0
- package/dist/internal/conversation-mirror.d.ts.map +1 -0
- package/dist/internal/conversation-mirror.js +312 -0
- package/dist/internal/cursor/backend-client.d.ts.map +1 -1
- package/dist/internal/cursor/backend-client.js +22 -48
- package/dist/internal/cursor/session-token.d.ts +45 -0
- package/dist/internal/cursor/session-token.d.ts.map +1 -0
- package/dist/internal/cursor/session-token.js +99 -0
- package/dist/internal/cursor-agent-template.d.ts +1 -1
- package/dist/internal/cursor-agent-template.d.ts.map +1 -1
- package/dist/internal/cursor-agent-template.js +1 -0
- package/dist/internal/deferred-channel-session.d.ts +20 -0
- package/dist/internal/deferred-channel-session.d.ts.map +1 -0
- package/dist/internal/deferred-channel-session.js +62 -0
- package/dist/internal/deploy-client.d.ts +13 -1
- package/dist/internal/deploy-client.d.ts.map +1 -1
- package/dist/internal/deploy-client.js +11 -1
- package/dist/internal/deploy-manifest.d.ts.map +1 -1
- package/dist/internal/deploy-manifest.js +11 -5
- package/dist/internal/discovery.d.ts.map +1 -1
- package/dist/internal/discovery.js +22 -2
- package/dist/internal/framework-file-storage.d.ts +61 -0
- package/dist/internal/framework-file-storage.d.ts.map +1 -0
- package/dist/internal/framework-file-storage.js +204 -0
- package/dist/internal/framework-storage-selection.d.ts +38 -16
- package/dist/internal/framework-storage-selection.d.ts.map +1 -1
- package/dist/internal/framework-storage-selection.js +78 -17
- package/dist/internal/hosted-admission-context.d.ts +20 -0
- package/dist/internal/hosted-admission-context.d.ts.map +1 -0
- package/dist/internal/hosted-admission-context.js +31 -0
- package/dist/internal/hosted-delivery-protocol.d.ts +5 -0
- package/dist/internal/hosted-delivery-protocol.d.ts.map +1 -1
- package/dist/internal/hosted-delivery-protocol.js +33 -1
- package/dist/internal/hosted-delivery.d.ts +11 -2
- package/dist/internal/hosted-delivery.d.ts.map +1 -1
- package/dist/internal/hosted-delivery.js +79 -35
- package/dist/internal/hosted-managed-automation.d.ts +30 -0
- package/dist/internal/hosted-managed-automation.d.ts.map +1 -0
- package/dist/internal/hosted-managed-automation.js +58 -0
- package/dist/internal/init-project.d.ts.map +1 -1
- package/dist/internal/init-project.js +2 -0
- package/dist/internal/install-cursor-skills.d.ts.map +1 -1
- package/dist/internal/install-cursor-skills.js +1 -3
- package/dist/internal/managed-delivery.d.ts +80 -0
- package/dist/internal/managed-delivery.d.ts.map +1 -0
- package/dist/internal/managed-delivery.js +86 -0
- package/dist/internal/review-comments.d.ts.map +1 -1
- package/dist/internal/review-comments.js +10 -98
- package/dist/internal/runtime-dispatch-runner.d.ts +5 -1
- package/dist/internal/runtime-dispatch-runner.d.ts.map +1 -1
- package/dist/internal/runtime-dispatch-runner.js +7 -0
- package/dist/internal/scm/pr-url.d.ts +14 -0
- package/dist/internal/scm/pr-url.d.ts.map +1 -0
- package/dist/internal/scm/pr-url.js +65 -0
- package/dist/internal/sdk-runner.d.ts +25 -0
- package/dist/internal/sdk-runner.d.ts.map +1 -1
- package/dist/internal/sdk-runner.js +70 -0
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +11 -2
- package/dist/internal/session-engine.d.ts +13 -0
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +71 -3
- package/dist/internal/steering.d.ts +15 -0
- package/dist/internal/steering.d.ts.map +1 -0
- package/dist/internal/steering.js +18 -0
- package/dist/playground/assets/index-B1DDvBeC.css +1 -0
- package/dist/playground/assets/{index-B3JCyigB.js → index-Cx9CclK_.js} +47 -47
- package/dist/playground/index.html +2 -2
- package/dist/storage-backends/cursor-hosted.d.ts +8 -0
- package/dist/storage-backends/cursor-hosted.d.ts.map +1 -1
- package/dist/storage-backends/cursor-hosted.js +4 -3
- package/dist/types.d.ts +2 -1
- package/dist/types.d.ts.map +1 -1
- package/docs/README.md +5 -1
- package/docs/reference/cli.md +4 -1
- package/docs/templates/agentic-owners.md +1 -1
- package/docs/templates/code-wiki.md +96 -0
- package/docs/templates/demo.md +3 -2
- package/docs/templates/pr-autofixer.md +7 -13
- package/docs/templates/security-help.md +70 -0
- package/docs/templates/security-reviewer.md +1 -2
- package/docs/templates/triage.md +2 -6
- package/package.json +2 -2
- package/skills/ab/SKILL.md +13 -97
- package/skills/create-agent/SKILL.md +123 -223
- package/skills/debug/SKILL.md +34 -68
- package/skills/evals/SKILL.md +55 -180
- package/skills/framework-map/SKILL.md +83 -145
- package/skills/github/SKILL.md +53 -111
- package/skills/hillclimb/SKILL.md +40 -163
- package/skills/mcp-auth/SKILL.md +48 -107
- package/skills/otel/SKILL.md +22 -68
- package/skills/setup-slack/SKILL.md +77 -208
- package/src/channels/deployments/types.ts +1 -0
- package/src/channels/github/github-channel.ts +23 -8
- package/src/channels/github/types.ts +19 -2
- package/src/channels/origin/api.ts +242 -30
- package/src/channels/origin/binding.ts +2 -2
- package/src/channels/origin/checks.ts +6 -6
- package/src/channels/origin/cursor-account.ts +5 -3
- package/src/channels/origin/origin-channel.ts +13 -1
- package/src/channels/origin/origin-webhook.ts +27 -3
- package/src/channels/origin/types.ts +8 -0
- package/src/channels/slack/api.ts +41 -5
- package/src/channels/slack/defaults.ts +15 -49
- package/src/channels/slack/dispatch.ts +56 -22
- package/src/channels/slack/inbound.ts +43 -0
- package/src/channels/slack/live-delivery.ts +235 -114
- package/src/channels/slack/manifest.ts +5 -1
- package/src/channels/slack/nudge-carrier.ts +48 -1
- package/src/channels/slack/pr-ref.ts +56 -25
- package/src/channels/slack/slack-channel.ts +2 -0
- package/src/files-backends/cursor-hosted.ts +41 -2
- package/src/files.ts +11 -0
- package/src/internal/advertise-tools.ts +18 -2
- package/src/internal/bounded.ts +28 -0
- package/src/internal/cli-deploy.ts +183 -7
- package/src/internal/conversation-mirror.ts +406 -0
- package/src/internal/cursor/backend-client.ts +34 -58
- package/src/internal/cursor/session-token.ts +115 -0
- package/src/internal/cursor-agent-template.ts +1 -0
- package/src/internal/deferred-channel-session.ts +61 -0
- package/src/internal/deploy-client.ts +24 -1
- package/src/internal/deploy-manifest.ts +10 -5
- package/src/internal/discovery.ts +25 -2
- package/src/internal/framework-file-storage.ts +222 -0
- package/src/internal/framework-storage-selection.ts +101 -19
- package/src/internal/hosted-admission-context.ts +37 -0
- package/src/internal/hosted-delivery-protocol.ts +44 -1
- package/src/internal/hosted-delivery.ts +105 -40
- package/src/internal/hosted-managed-automation.ts +72 -0
- package/src/internal/init-project.ts +2 -0
- package/src/internal/install-cursor-skills.ts +1 -4
- package/src/internal/managed-delivery.ts +125 -0
- package/src/internal/review-comments.ts +10 -113
- package/src/internal/runtime-dispatch-runner.ts +10 -0
- package/src/internal/scm/pr-url.ts +95 -0
- package/src/internal/sdk-runner.ts +103 -0
- package/src/internal/server.ts +12 -0
- package/src/internal/session-engine.ts +76 -4
- package/src/internal/steering.ts +17 -0
- package/src/storage-backends/cursor-hosted.ts +10 -1
- package/src/types.ts +2 -1
- package/templates/agentic-owners/README.md +1 -1
- package/templates/agentic-owners/agent/agent.ts +0 -10
- package/templates/agentic-owners/agent/channels/github.ts +5 -14
- package/templates/agentic-owners/agent/lib/config.ts +0 -8
- package/templates/agentic-owners/agent/lib/review.ts +2 -15
- package/templates/agentic-owners/agent/tools/record_review.ts +2 -4
- package/templates/code-wiki/README.md +34 -0
- package/templates/code-wiki/agent/agent.ts +8 -0
- package/templates/code-wiki/agent/channels/github.ts +144 -0
- package/templates/code-wiki/agent/instructions.md +39 -0
- package/templates/code-wiki/agent/lib/repos.ts +5 -0
- package/templates/code-wiki/agent/lib/wiki.ts +22 -0
- package/templates/code-wiki/agent/tools/apply_wiki.ts +219 -0
- package/templates/code-wiki/evals/evals.config.ts +5 -0
- package/templates/code-wiki/evals/wiki.eval.ts +132 -0
- package/templates/code-wiki/init.json +25 -0
- package/templates/code-wiki/package.json +18 -0
- package/templates/code-wiki/tsconfig.json +12 -0
- package/templates/demo/agent/agent.ts +0 -10
- package/templates/pr-autofixer/README.md +0 -2
- package/templates/pr-autofixer/agent/agent.ts +0 -11
- package/templates/pr-autofixer/agent/channels/slack.ts +0 -7
- package/templates/pr-autofixer/agent/lib/pr-state.ts +5 -17
- package/templates/pr-autofixer/agent/lib/repos.ts +0 -1
- package/templates/security-help/README.md +2 -2
- package/templates/security-help/agent/agent.ts +1 -2
- package/templates/security-help/agent/channels/slack.ts +0 -3
- package/templates/security-help/agent/instructions.md +9 -10
- package/templates/security-help/agent/skills/access-request.md +1 -1
- package/templates/security-help/agent/skills/faq.md +31 -0
- package/templates/security-help/agent/skills/security-playbooks.md +1 -1
- package/templates/security-help/package.json +1 -2
- package/templates/security-reviewer/agent/agent.ts +0 -10
- package/templates/triage/agent/agent.ts +0 -10
- package/templates/triage/agent/channels/queue.ts +1 -1
- package/templates/triage/agent/channels/webhook.ts +1 -3
- package/dist/docs/assets/chunks/@localSearchIndexroot.DU3U2Ij2.js +0 -1
- package/dist/docs/assets/index.md.DRakGHFe.js +0 -5
- package/dist/internal/deployment-scm-event-stream.d.ts +0 -116
- package/dist/internal/deployment-scm-event-stream.d.ts.map +0 -1
- package/dist/internal/deployment-scm-event-stream.js +0 -474
- package/dist/playground/assets/index-D9N7-q97.css +0 -1
- package/src/internal/deployment-scm-event-stream.ts +0 -593
- package/templates/security-help/agent/knowledge/faq/approvals.md +0 -5
- package/templates/security-help/agent/knowledge/faq/channels.md +0 -6
- package/templates/security-help/agent/knowledge/faq/phishing.md +0 -10
- package/templates/security-help/agent/skills/security-first-pass.md +0 -15
- /package/dist/docs/assets/{reference_skills.md.8son6Hjm.lean.js → reference_skills.md.BFW9retM.lean.js} +0 -0
- /package/dist/docs/assets/{templates_agentic-owners.md.DqtPdm6f.lean.js → templates_agentic-owners.md.BZSH4N9z.lean.js} +0 -0
- /package/dist/docs/assets/{templates_demo.md.DhFcWN6j.lean.js → templates_demo.md.BeQX9V3H.lean.js} +0 -0
|
@@ -10,6 +10,14 @@ import type {
|
|
|
10
10
|
ChannelHandlerArgs,
|
|
11
11
|
SendMessageOptions,
|
|
12
12
|
} from "../types.js";
|
|
13
|
+
import {
|
|
14
|
+
createDeferredChannelSession,
|
|
15
|
+
DeferredChannelSessionError,
|
|
16
|
+
} from "./deferred-channel-session.js";
|
|
17
|
+
import {
|
|
18
|
+
HostedAdmissionLocalSendError,
|
|
19
|
+
runDuringHostedAdmission,
|
|
20
|
+
} from "./hosted-admission-context.js";
|
|
13
21
|
import {
|
|
14
22
|
HOSTED_ADMISSION_PATH,
|
|
15
23
|
HOSTED_DELIVERY_HEADER,
|
|
@@ -19,6 +27,7 @@ import {
|
|
|
19
27
|
parseHostedAdmission,
|
|
20
28
|
parseHostedExecution,
|
|
21
29
|
} from "./hosted-delivery-protocol.js";
|
|
30
|
+
import { recordHostedManagedAutomation } from "./hosted-managed-automation.js";
|
|
22
31
|
import { errorResponse, readJsonObject } from "./http-channel.js";
|
|
23
32
|
import type { Router } from "./router.js";
|
|
24
33
|
|
|
@@ -45,19 +54,66 @@ type ExecutionReply = {
|
|
|
45
54
|
body: Record<string, unknown>;
|
|
46
55
|
};
|
|
47
56
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
57
|
+
/**
|
|
58
|
+
* A second `send()` in one delivery is a deterministic authored bug — the
|
|
59
|
+
* wire protocol carries exactly one pending send per delivery — so it must
|
|
60
|
+
* fail the delivery exactly once. It surfaces as a 422 because the control
|
|
61
|
+
* plane retries 5xx admissions (fresh pod, side effects re-run, identical
|
|
62
|
+
* failure, up to the Temporal attempt cap); a non-5xx/408/429 status makes
|
|
63
|
+
* it reject the delivery non-retryably instead.
|
|
64
|
+
*/
|
|
65
|
+
class HostedSendLimitExceeded extends Error {
|
|
66
|
+
constructor() {
|
|
67
|
+
super(
|
|
68
|
+
"The hosted delivery protocol carries exactly one pending send per " +
|
|
69
|
+
"delivery, and this delivery already captured one. Combine both " +
|
|
70
|
+
"messages into a single send(), or split the work across deliveries."
|
|
71
|
+
);
|
|
54
72
|
}
|
|
55
73
|
}
|
|
56
74
|
|
|
75
|
+
// Authored/task-derived text stays bounded on this internal response path
|
|
76
|
+
// (and is never persisted to Temporal history by the control plane).
|
|
77
|
+
const MAX_ERROR_MESSAGE_LENGTH = 1024;
|
|
78
|
+
|
|
79
|
+
function boundedMessage(text: string): string {
|
|
80
|
+
return text.length > MAX_ERROR_MESSAGE_LENGTH
|
|
81
|
+
? `${text.slice(0, MAX_ERROR_MESSAGE_LENGTH)}…`
|
|
82
|
+
: text;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Classify deterministic authored protocol violations as non-retryable 422
|
|
87
|
+
* admissions. Anything else returns `undefined` so callers fall through to
|
|
88
|
+
* the existing (retryable or rethrow) handling.
|
|
89
|
+
*/
|
|
90
|
+
function nonRetryableRejection(error: unknown): AdmissionDispatch | undefined {
|
|
91
|
+
const code =
|
|
92
|
+
error instanceof HostedSendLimitExceeded
|
|
93
|
+
? "hosted_send_limit_exceeded"
|
|
94
|
+
: error instanceof DeferredChannelSessionError
|
|
95
|
+
? "hosted_deferred_session_unusable"
|
|
96
|
+
: error instanceof HostedAdmissionLocalSendError
|
|
97
|
+
? "hosted_local_send_rejected"
|
|
98
|
+
: undefined;
|
|
99
|
+
if (code === undefined) {
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
response: errorResponse(
|
|
104
|
+
422,
|
|
105
|
+
code,
|
|
106
|
+
boundedMessage((error as Error).message)
|
|
107
|
+
),
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
57
111
|
/**
|
|
58
112
|
* Run authored admission without creating a framework session. V1 GitHub
|
|
59
|
-
* `task` callbacks execute as sessionless work; `send` is captured
|
|
60
|
-
*
|
|
113
|
+
* `task` callbacks execute as sessionless work; the first `send` is captured
|
|
114
|
+
* and executed only after the control plane allocates `ses_…`. Capturing
|
|
115
|
+
* does not terminate the caller — `send` returns an inert deferred handle so
|
|
116
|
+
* a task body runs to completion before the admission response is computed.
|
|
61
117
|
*/
|
|
62
118
|
export async function dispatchHostedAdmission(
|
|
63
119
|
input: DispatchInput
|
|
@@ -71,24 +127,28 @@ export async function dispatchHostedAdmission(
|
|
|
71
127
|
),
|
|
72
128
|
};
|
|
73
129
|
}
|
|
130
|
+
// The admission window marker follows the async graph into task bodies so
|
|
131
|
+
// the engine can refuse local sends that would bypass the capture stub.
|
|
132
|
+
return runDuringHostedAdmission(() => runAdmission(input, github));
|
|
133
|
+
}
|
|
74
134
|
|
|
135
|
+
async function runAdmission(
|
|
136
|
+
input: DispatchInput,
|
|
137
|
+
github: NonNullable<ReturnType<typeof getGitHubChannelOptions>>
|
|
138
|
+
): Promise<AdmissionDispatch> {
|
|
75
139
|
const background: Promise<unknown>[] = [];
|
|
76
|
-
let
|
|
140
|
+
let captured: { message: string; options: SendMessageOptions } | undefined;
|
|
77
141
|
const args = withPropagatingGitHubBackgroundErrors({
|
|
78
142
|
...input.args,
|
|
79
143
|
send: async (message, options = {}) => {
|
|
80
|
-
|
|
144
|
+
if (captured !== undefined) {
|
|
145
|
+
throw new HostedSendLimitExceeded();
|
|
146
|
+
}
|
|
147
|
+
captured = { message, options };
|
|
148
|
+
return createDeferredChannelSession();
|
|
81
149
|
},
|
|
82
150
|
waitUntil: (promise) => {
|
|
83
|
-
background.push(
|
|
84
|
-
promise.catch((error: unknown) => {
|
|
85
|
-
if (error instanceof HostedSendAdmitted) {
|
|
86
|
-
deferredSend = error;
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
throw error;
|
|
90
|
-
})
|
|
91
|
-
);
|
|
151
|
+
background.push(promise);
|
|
92
152
|
},
|
|
93
153
|
});
|
|
94
154
|
let dispatched: Response;
|
|
@@ -101,20 +161,9 @@ export async function dispatchHostedAdmission(
|
|
|
101
161
|
args,
|
|
102
162
|
});
|
|
103
163
|
} catch (error) {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
ok: true,
|
|
108
|
-
v: HOSTED_DELIVERY_PROTOCOL_VERSION,
|
|
109
|
-
outcome: "send",
|
|
110
|
-
}),
|
|
111
|
-
pendingSend: {
|
|
112
|
-
channelId: input.delivery.channelId,
|
|
113
|
-
message: error.prompt,
|
|
114
|
-
options: error.options,
|
|
115
|
-
mailboxContinuationKey: input.delivery.mailboxContinuationKey,
|
|
116
|
-
},
|
|
117
|
-
};
|
|
164
|
+
const rejected = nonRetryableRejection(error);
|
|
165
|
+
if (rejected !== undefined) {
|
|
166
|
+
return rejected;
|
|
118
167
|
}
|
|
119
168
|
throw error;
|
|
120
169
|
}
|
|
@@ -129,15 +178,20 @@ export async function dispatchHostedAdmission(
|
|
|
129
178
|
|
|
130
179
|
try {
|
|
131
180
|
await Promise.all(background);
|
|
132
|
-
} catch {
|
|
181
|
+
} catch (error) {
|
|
182
|
+
const rejected = nonRetryableRejection(error);
|
|
183
|
+
if (rejected !== undefined) {
|
|
184
|
+
return rejected;
|
|
185
|
+
}
|
|
133
186
|
return {
|
|
134
|
-
response:
|
|
135
|
-
|
|
136
|
-
|
|
187
|
+
response: errorResponse(
|
|
188
|
+
503,
|
|
189
|
+
"background_dispatch_failed",
|
|
190
|
+
boundedMessage(error instanceof Error ? error.message : String(error))
|
|
137
191
|
),
|
|
138
192
|
};
|
|
139
193
|
}
|
|
140
|
-
if (
|
|
194
|
+
if (captured !== undefined) {
|
|
141
195
|
return {
|
|
142
196
|
response: Response.json({
|
|
143
197
|
ok: true,
|
|
@@ -146,8 +200,8 @@ export async function dispatchHostedAdmission(
|
|
|
146
200
|
}),
|
|
147
201
|
pendingSend: {
|
|
148
202
|
channelId: input.delivery.channelId,
|
|
149
|
-
message:
|
|
150
|
-
options:
|
|
203
|
+
message: captured.message,
|
|
204
|
+
options: captured.options,
|
|
151
205
|
mailboxContinuationKey: input.delivery.mailboxContinuationKey,
|
|
152
206
|
},
|
|
153
207
|
};
|
|
@@ -191,6 +245,13 @@ export function registerHostedDeliveryRoute(input: {
|
|
|
191
245
|
channelId: string,
|
|
192
246
|
sessionPublicId?: string
|
|
193
247
|
): ChannelHandlerArgs;
|
|
248
|
+
/**
|
|
249
|
+
* Await the session's durable mirror (dispatch chain + storage queue)
|
|
250
|
+
* before the execution reply: the control plane may park the pod the
|
|
251
|
+
* moment the reply lands, and a shed session-record flush would strand
|
|
252
|
+
* the conversation on the next wake.
|
|
253
|
+
*/
|
|
254
|
+
drainSessionDurability?(sessionId: string): Promise<void>;
|
|
194
255
|
}): void {
|
|
195
256
|
const pending = new Map<
|
|
196
257
|
string,
|
|
@@ -241,6 +302,7 @@ export function registerHostedDeliveryRoute(input: {
|
|
|
241
302
|
)
|
|
242
303
|
);
|
|
243
304
|
}
|
|
305
|
+
recordHostedManagedAutomation(delivery);
|
|
244
306
|
const channel = input.channels.find(
|
|
245
307
|
(candidate) => candidate.id === delivery.channelId
|
|
246
308
|
);
|
|
@@ -332,6 +394,9 @@ export function registerHostedDeliveryRoute(input: {
|
|
|
332
394
|
},
|
|
333
395
|
});
|
|
334
396
|
const outcome = await session.waitForCompletion();
|
|
397
|
+
// Failed turns drain too: their record/continuation updates must
|
|
398
|
+
// survive the park just like a finished turn's.
|
|
399
|
+
await input.drainSessionDurability?.(session.id);
|
|
335
400
|
if (outcome.status !== "finished") {
|
|
336
401
|
return {
|
|
337
402
|
status: 503,
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Managed-automation envelope slices by provider delivery id (plan 0002
|
|
3
|
+
* G2), recorded at hosted admission so channel code running the delivery's
|
|
4
|
+
* task (or session turn) can attach the customer's MCP servers through the
|
|
5
|
+
* control-plane relay. In-memory and TTL-bounded like the hosted pending-
|
|
6
|
+
* send table: the envelope slice carries names only (never credentials)
|
|
7
|
+
* and evaporates with the process.
|
|
8
|
+
*
|
|
9
|
+
* A leaf module (protocol type import only) so product channels can read
|
|
10
|
+
* it without pulling the hosted-delivery route — and its session-engine
|
|
11
|
+
* dependency graph — into their bundles.
|
|
12
|
+
*
|
|
13
|
+
* INTERNAL: first-party multi-tenant deployment plumbing. Deliberately
|
|
14
|
+
* excluded from the published `@cursor/july` npm package (see the `files`
|
|
15
|
+
* whitelist); consumed by internal deployments via relative source imports.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import type { HostedAdmissionManagedAutomation } from "./hosted-delivery-protocol.js";
|
|
19
|
+
|
|
20
|
+
const managedAutomationByDelivery = new Map<
|
|
21
|
+
string,
|
|
22
|
+
{ managedAutomation: HostedAdmissionManagedAutomation; expiresAt: number }
|
|
23
|
+
>();
|
|
24
|
+
/** Long enough to outlive a slow review run kicked off by the delivery. */
|
|
25
|
+
const MANAGED_AUTOMATION_TTL_MS = 60 * 60_000;
|
|
26
|
+
const MANAGED_AUTOMATION_MAX_ENTRIES = 10_000;
|
|
27
|
+
|
|
28
|
+
export function recordHostedManagedAutomation(delivery: {
|
|
29
|
+
deliveryId: string;
|
|
30
|
+
managedAutomation?: HostedAdmissionManagedAutomation;
|
|
31
|
+
}): void {
|
|
32
|
+
if (delivery.managedAutomation === undefined) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const now = Date.now();
|
|
36
|
+
for (const [key, entry] of managedAutomationByDelivery) {
|
|
37
|
+
if (entry.expiresAt <= now) {
|
|
38
|
+
managedAutomationByDelivery.delete(key);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (managedAutomationByDelivery.size >= MANAGED_AUTOMATION_MAX_ENTRIES) {
|
|
42
|
+
managedAutomationByDelivery.clear();
|
|
43
|
+
}
|
|
44
|
+
managedAutomationByDelivery.set(delivery.deliveryId, {
|
|
45
|
+
managedAutomation: delivery.managedAutomation,
|
|
46
|
+
expiresAt: now + MANAGED_AUTOMATION_TTL_MS,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* The managed automation the control plane attributed to a hosted delivery,
|
|
52
|
+
* when the envelope carried one. Undefined for non-managed deliveries,
|
|
53
|
+
* expired entries, and non-hosted (webhook/stream) dispatch paths.
|
|
54
|
+
*/
|
|
55
|
+
export function getHostedManagedAutomation(
|
|
56
|
+
deliveryId: string
|
|
57
|
+
): HostedAdmissionManagedAutomation | undefined {
|
|
58
|
+
const entry = managedAutomationByDelivery.get(deliveryId);
|
|
59
|
+
if (entry === undefined) {
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
if (entry.expiresAt <= Date.now()) {
|
|
63
|
+
managedAutomationByDelivery.delete(deliveryId);
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
return entry.managedAutomation;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Drop recorded managed-automation slices (tests only). */
|
|
70
|
+
export function resetHostedManagedAutomationForTest(): void {
|
|
71
|
+
managedAutomationByDelivery.clear();
|
|
72
|
+
}
|
|
@@ -74,6 +74,7 @@ type TemplateEntry = {
|
|
|
74
74
|
|
|
75
75
|
const TEMPLATES: Readonly<Record<TemplateName, TemplateEntry>> = {
|
|
76
76
|
"agentic-owners": { dir: "agentic-owners" },
|
|
77
|
+
"code-wiki": { dir: "code-wiki" },
|
|
77
78
|
demo: { dir: "demo" },
|
|
78
79
|
"pr-autofixer": { dir: "pr-autofixer" },
|
|
79
80
|
"security-help": { dir: "security-help" },
|
|
@@ -709,6 +710,7 @@ export function printInitGuide(): void {
|
|
|
709
710
|
Scaffold a project, then open the playground:
|
|
710
711
|
npx ${PACKAGE_NAME} init ./my-agent # installs deps + links agent-sdk onto PATH
|
|
711
712
|
npx ${PACKAGE_NAME} init ./my-demo --template demo # record a PR walkthrough
|
|
713
|
+
npx ${PACKAGE_NAME} init ./code-wiki --template code-wiki # keep wiki pages current after merge
|
|
712
714
|
npx ${PACKAGE_NAME} init ./my-reviewer --template security-reviewer # review PRs for security bugs
|
|
713
715
|
npx ${PACKAGE_NAME} init ./security-help --template security-help # answer security questions in Slack
|
|
714
716
|
npx ${PACKAGE_NAME} init ./my-triage --template triage-linear # comment on Linear issues
|
|
@@ -31,9 +31,6 @@ import { CLI_COMMAND_NAME, packageRootDir } from "./distribution.js";
|
|
|
31
31
|
import { parseFrontmatter } from "./frontmatter.js";
|
|
32
32
|
import { stdoutPalette } from "./terminal-style.js";
|
|
33
33
|
|
|
34
|
-
/** Monorepo-only skill; excluded from the published package. */
|
|
35
|
-
const SKIP_SKILL_DIRS = new Set(["operate"]);
|
|
36
|
-
|
|
37
34
|
/** Category folder under ~/.cursor/skills (Cursor discovers nested skills). */
|
|
38
35
|
export const CURSOR_SKILLS_NAMESPACE = "agentsdk";
|
|
39
36
|
|
|
@@ -122,7 +119,7 @@ export async function listShippedPackageSkills(
|
|
|
122
119
|
|
|
123
120
|
const skills: PackageSkill[] = [];
|
|
124
121
|
for (const entry of entries) {
|
|
125
|
-
if (!entry.isDirectory()
|
|
122
|
+
if (!entry.isDirectory()) {
|
|
126
123
|
continue;
|
|
127
124
|
}
|
|
128
125
|
const sourceDir = join(skillsRoot, entry.name);
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Envelope-carried installation config for managed-product deliveries
|
|
3
|
+
* (plan 0002 Stack H1; envelope shape from Stack B1).
|
|
4
|
+
*
|
|
5
|
+
* On the v2 architecture a managed product (security-reviewer, …) is many
|
|
6
|
+
* single-tenant deployments: the pre-signal trigger gate matches the
|
|
7
|
+
* customer's automation trigger before a workflow starts and stamps the
|
|
8
|
+
* matched automation uuid + an opaque installation-config reference on the
|
|
9
|
+
* attributed session envelope. The delivery activity forwards the matched
|
|
10
|
+
* installation-config document to the fork **inside the webhook payload it
|
|
11
|
+
* POSTs to the channel**, under {@link MANAGED_DELIVERY_PAYLOAD_KEY} — the
|
|
12
|
+
* same embed-in-payload pattern the legacy deployment event stream used
|
|
13
|
+
* for its source marker.
|
|
14
|
+
*
|
|
15
|
+
* This module is the one contract both sides share: the control-plane
|
|
16
|
+
* delivery path embeds with {@link withManagedDeliveryConfig}; the agent's
|
|
17
|
+
* channels detect and read with {@link parseManagedDeliveryConfig}. The
|
|
18
|
+
* document mirrors the sync layer's `ManagedAutomationConfigDoc` **policy**
|
|
19
|
+
* fields that "ride the delivery envelope to the fork" (posting mode,
|
|
20
|
+
* managed config, trigger snapshots for the channel's staleness guard);
|
|
21
|
+
* readers ignore unknown fields so a newer sync can add material without
|
|
22
|
+
* breaking older forks. The automation's MCP server refs deliberately do
|
|
23
|
+
* NOT ride here: they travel on the hosted-admission envelope's
|
|
24
|
+
* `managedAutomation` slice (plan 0002 G2, `hosted-delivery-protocol.ts` /
|
|
25
|
+
* `hosted-managed-automation.ts`) so one mechanism owns MCP attach.
|
|
26
|
+
*
|
|
27
|
+
* INTERNAL: first-party host plumbing shared by agents in `factory/*`,
|
|
28
|
+
* consumed via relative source imports. Deliberately excluded from the
|
|
29
|
+
* published `@cursor/july` npm package (see the `files` whitelist).
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Key inside the delivered webhook payload under which the delivery
|
|
34
|
+
* activity embeds the matched installation config. Chosen to never
|
|
35
|
+
* collide with a provider webhook field (GitHub and Origin payloads have
|
|
36
|
+
* no `cursor*` keys).
|
|
37
|
+
*/
|
|
38
|
+
export const MANAGED_DELIVERY_PAYLOAD_KEY = "cursorManagedDelivery" as const;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The matched installation-config document as it rides the delivery to
|
|
42
|
+
* the fork. Required: the matched automation uuid (B1 attribution).
|
|
43
|
+
* Everything else is optional; absent fields keep the channel's default
|
|
44
|
+
* posture (post, all modules enabled, no staleness guard).
|
|
45
|
+
*/
|
|
46
|
+
export interface ManagedDeliveryInstallationConfig {
|
|
47
|
+
/** Source managed automation uuid the pre-signal gate matched. */
|
|
48
|
+
matchedAutomationUuid: string;
|
|
49
|
+
/** Opaque `<installationId>@<resourceVersion>` config reference. */
|
|
50
|
+
installationConfigRef?: string;
|
|
51
|
+
managedType?: string;
|
|
52
|
+
name?: string;
|
|
53
|
+
/**
|
|
54
|
+
* Whether product output (PR comments, …) posts for this installation,
|
|
55
|
+
* or the run stays check/shadow-only. Channels post only on `"post"`
|
|
56
|
+
* (or when the field is absent) — any other value fails closed to
|
|
57
|
+
* shadow, so a newer mode name never posts by accident.
|
|
58
|
+
*/
|
|
59
|
+
postingMode?: string;
|
|
60
|
+
managedConfig?: Record<string, unknown>;
|
|
61
|
+
/**
|
|
62
|
+
* The automation's git triggers as `GitTrigger.toJson()` snapshots.
|
|
63
|
+
* The channel re-checks the delivery against them (staleness guard:
|
|
64
|
+
* the config may have changed between admission and delivery).
|
|
65
|
+
*/
|
|
66
|
+
triggerSnapshots?: unknown[];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
70
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function nonEmptyString(value: unknown): string | undefined {
|
|
74
|
+
if (typeof value !== "string") {
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
const trimmed = value.trim();
|
|
78
|
+
return trimmed === "" ? undefined : trimmed;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Read the embedded installation config out of a delivered webhook
|
|
83
|
+
* payload. Returns undefined for payloads without the key (legacy
|
|
84
|
+
* deliveries, host relay, fixtures) and for documents missing the
|
|
85
|
+
* required matched automation uuid — the channel then runs its legacy
|
|
86
|
+
* path unchanged. Malformed optional fields are dropped, not fatal.
|
|
87
|
+
*/
|
|
88
|
+
export function parseManagedDeliveryConfig(
|
|
89
|
+
payload: unknown
|
|
90
|
+
): ManagedDeliveryInstallationConfig | undefined {
|
|
91
|
+
if (!isRecord(payload)) {
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
const doc = payload[MANAGED_DELIVERY_PAYLOAD_KEY];
|
|
95
|
+
if (!isRecord(doc)) {
|
|
96
|
+
return undefined;
|
|
97
|
+
}
|
|
98
|
+
const matchedAutomationUuid = nonEmptyString(doc.matchedAutomationUuid);
|
|
99
|
+
if (matchedAutomationUuid === undefined) {
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
matchedAutomationUuid,
|
|
104
|
+
installationConfigRef: nonEmptyString(doc.installationConfigRef),
|
|
105
|
+
managedType: nonEmptyString(doc.managedType),
|
|
106
|
+
name: nonEmptyString(doc.name),
|
|
107
|
+
postingMode: nonEmptyString(doc.postingMode),
|
|
108
|
+
managedConfig: isRecord(doc.managedConfig) ? doc.managedConfig : undefined,
|
|
109
|
+
triggerSnapshots: Array.isArray(doc.triggerSnapshots)
|
|
110
|
+
? doc.triggerSnapshots
|
|
111
|
+
: undefined,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Embed one matched installation config into the webhook payload the
|
|
117
|
+
* delivery activity POSTs to the channel. Pure; used by the control-plane
|
|
118
|
+
* delivery path and by channel tests building fixture envelopes.
|
|
119
|
+
*/
|
|
120
|
+
export function withManagedDeliveryConfig(
|
|
121
|
+
payload: Record<string, unknown>,
|
|
122
|
+
config: ManagedDeliveryInstallationConfig
|
|
123
|
+
): Record<string, unknown> {
|
|
124
|
+
return { ...payload, [MANAGED_DELIVERY_PAYLOAD_KEY]: config };
|
|
125
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
2
|
import type { HostGitHubClient } from "../types.js";
|
|
3
|
+
import { parsePrUrl } from "./scm/pr-url.js";
|
|
3
4
|
|
|
4
5
|
export type ReviewCommentPublisher = "local_gh" | "host_github" | "host_origin";
|
|
5
6
|
|
|
@@ -198,8 +199,15 @@ export type ReviewThreadResolverImplementation = {
|
|
|
198
199
|
export function resolveScmReviewTarget(
|
|
199
200
|
prUrl: string
|
|
200
201
|
): ScmReviewTarget | undefined {
|
|
201
|
-
const parsed =
|
|
202
|
-
|
|
202
|
+
const parsed = parsePrUrl(prUrl);
|
|
203
|
+
if (parsed === undefined) {
|
|
204
|
+
return undefined;
|
|
205
|
+
}
|
|
206
|
+
return {
|
|
207
|
+
provider: parsed.provider,
|
|
208
|
+
repo: `${parsed.owner}/${parsed.repo}`,
|
|
209
|
+
prNumber: parsed.number,
|
|
210
|
+
};
|
|
203
211
|
}
|
|
204
212
|
|
|
205
213
|
/**
|
|
@@ -1243,117 +1251,6 @@ function skippedResolve(detail: string): ResolveReviewThreadsResult {
|
|
|
1243
1251
|
};
|
|
1244
1252
|
}
|
|
1245
1253
|
|
|
1246
|
-
const ORIGIN_PR_PAGE_HOST_PATTERN = /^origin(-[a-z0-9]+)?\.cursor\.com$/i;
|
|
1247
|
-
|
|
1248
|
-
/**
|
|
1249
|
-
* Provider-neutral PR URL parse. GitHub.com plus the Origin page shapes
|
|
1250
|
-
* `parsePrTarget` in security-review-lib accepts. Duplicated here so
|
|
1251
|
-
* agent-serve does not import that package.
|
|
1252
|
-
*/
|
|
1253
|
-
function parseReviewPrUrl(
|
|
1254
|
-
prUrl: string
|
|
1255
|
-
):
|
|
1256
|
-
| { kind: "valid"; value: ScmReviewTarget }
|
|
1257
|
-
| { kind: "invalid"; detail: string } {
|
|
1258
|
-
let url: URL;
|
|
1259
|
-
try {
|
|
1260
|
-
url = new URL(prUrl);
|
|
1261
|
-
} catch (error) {
|
|
1262
|
-
return {
|
|
1263
|
-
kind: "invalid",
|
|
1264
|
-
detail: `unparseable PR URL: ${error instanceof Error ? error.message : String(error)}`,
|
|
1265
|
-
};
|
|
1266
|
-
}
|
|
1267
|
-
|
|
1268
|
-
const parts = url.pathname.split("/").filter(Boolean);
|
|
1269
|
-
const hostname = url.hostname;
|
|
1270
|
-
|
|
1271
|
-
if (hostname === "github.com" && parts.length >= 4 && parts[2] === "pull") {
|
|
1272
|
-
const prNumber = Number(parts[3]);
|
|
1273
|
-
if (Number.isInteger(prNumber) && prNumber > 0) {
|
|
1274
|
-
return {
|
|
1275
|
-
kind: "valid",
|
|
1276
|
-
value: {
|
|
1277
|
-
provider: "github",
|
|
1278
|
-
repo: `${parts[0]}/${parts[1]}`,
|
|
1279
|
-
prNumber,
|
|
1280
|
-
},
|
|
1281
|
-
};
|
|
1282
|
-
}
|
|
1283
|
-
}
|
|
1284
|
-
|
|
1285
|
-
if (
|
|
1286
|
-
ORIGIN_PR_PAGE_HOST_PATTERN.test(hostname) &&
|
|
1287
|
-
parts.length >= 4 &&
|
|
1288
|
-
parts[2] === "github"
|
|
1289
|
-
) {
|
|
1290
|
-
const prNumber = Number(parts[3]);
|
|
1291
|
-
if (Number.isInteger(prNumber) && prNumber > 0) {
|
|
1292
|
-
return {
|
|
1293
|
-
kind: "valid",
|
|
1294
|
-
value: {
|
|
1295
|
-
provider: "origin",
|
|
1296
|
-
repo: `${parts[0]}/${parts[1]}`,
|
|
1297
|
-
prNumber,
|
|
1298
|
-
},
|
|
1299
|
-
};
|
|
1300
|
-
}
|
|
1301
|
-
}
|
|
1302
|
-
|
|
1303
|
-
if (
|
|
1304
|
-
/^(www\.)?cursor\.com$/i.test(hostname) &&
|
|
1305
|
-
parts[0] === "codebase" &&
|
|
1306
|
-
parts.length >= 5 &&
|
|
1307
|
-
parts[3] === "pull"
|
|
1308
|
-
) {
|
|
1309
|
-
const prNumber = Number(parts[4]);
|
|
1310
|
-
if (Number.isInteger(prNumber) && prNumber > 0) {
|
|
1311
|
-
return {
|
|
1312
|
-
kind: "valid",
|
|
1313
|
-
value: {
|
|
1314
|
-
provider: "origin",
|
|
1315
|
-
repo: `${parts[1]}/${parts[2]}`,
|
|
1316
|
-
prNumber,
|
|
1317
|
-
},
|
|
1318
|
-
};
|
|
1319
|
-
}
|
|
1320
|
-
}
|
|
1321
|
-
|
|
1322
|
-
if (hostname === "review.cursor.com" && parts[0] === "pr") {
|
|
1323
|
-
if (parts.length >= 5 && parts[3] === "github") {
|
|
1324
|
-
const prNumber = Number(parts[4]);
|
|
1325
|
-
if (Number.isInteger(prNumber) && prNumber > 0) {
|
|
1326
|
-
return {
|
|
1327
|
-
kind: "valid",
|
|
1328
|
-
value: {
|
|
1329
|
-
provider: "origin",
|
|
1330
|
-
repo: `${parts[1]}/${parts[2]}`,
|
|
1331
|
-
prNumber,
|
|
1332
|
-
},
|
|
1333
|
-
};
|
|
1334
|
-
}
|
|
1335
|
-
}
|
|
1336
|
-
if (parts.length >= 4) {
|
|
1337
|
-
const prNumber = Number(parts[3]);
|
|
1338
|
-
if (Number.isInteger(prNumber) && prNumber > 0) {
|
|
1339
|
-
return {
|
|
1340
|
-
kind: "valid",
|
|
1341
|
-
value: {
|
|
1342
|
-
provider: "origin",
|
|
1343
|
-
repo: `${parts[1]}/${parts[2]}`,
|
|
1344
|
-
prNumber,
|
|
1345
|
-
},
|
|
1346
|
-
};
|
|
1347
|
-
}
|
|
1348
|
-
}
|
|
1349
|
-
}
|
|
1350
|
-
|
|
1351
|
-
return {
|
|
1352
|
-
kind: "invalid",
|
|
1353
|
-
detail: "unparseable PR URL: not a GitHub or Origin pull request",
|
|
1354
|
-
};
|
|
1355
|
-
}
|
|
1356
|
-
|
|
1357
1254
|
function parseGithubPrUrl(
|
|
1358
1255
|
prUrl: string
|
|
1359
1256
|
):
|
|
@@ -13,6 +13,7 @@ import type {
|
|
|
13
13
|
AgentRunner,
|
|
14
14
|
PrewarmOutcome,
|
|
15
15
|
RunnerPrewarmRequest,
|
|
16
|
+
SteerAckOutcome,
|
|
16
17
|
} from "./sdk-runner.js";
|
|
17
18
|
|
|
18
19
|
export interface RuntimeDispatchingRunnerOptions {
|
|
@@ -45,6 +46,15 @@ export class RuntimeDispatchingRunner implements AgentRunner {
|
|
|
45
46
|
return this.options.sdkRunner.runTurn(request);
|
|
46
47
|
}
|
|
47
48
|
|
|
49
|
+
async steer(request: {
|
|
50
|
+
sessionId: string;
|
|
51
|
+
text: string;
|
|
52
|
+
}): Promise<SteerAckOutcome> {
|
|
53
|
+
return (
|
|
54
|
+
(await this.options.sdkRunner.steer?.(request)) ?? "revert_to_followup"
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
48
58
|
async prewarm(request: RunnerPrewarmRequest): Promise<PrewarmOutcome> {
|
|
49
59
|
// Prewarming is a local-harness concern; the engine only calls it for
|
|
50
60
|
// local-runtime agents.
|