@cursor/july 0.1.55 → 0.1.62

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.
Files changed (265) hide show
  1. package/dist/bin/agent-serve.js +30 -23
  2. package/dist/channels/github/github-channel.d.ts +13 -1
  3. package/dist/channels/github/github-channel.d.ts.map +1 -1
  4. package/dist/channels/github/github-channel.js +81 -16
  5. package/dist/channels/github/types.d.ts +29 -1
  6. package/dist/channels/github/types.d.ts.map +1 -1
  7. package/dist/channels/origin/cursor-account.d.ts +22 -0
  8. package/dist/channels/origin/cursor-account.d.ts.map +1 -0
  9. package/dist/channels/origin/cursor-account.js +35 -0
  10. package/dist/channels/origin/events.d.ts +10 -0
  11. package/dist/channels/origin/events.d.ts.map +1 -0
  12. package/dist/channels/origin/events.js +27 -0
  13. package/dist/channels/origin/index.d.ts +29 -0
  14. package/dist/channels/origin/index.d.ts.map +1 -0
  15. package/dist/channels/origin/index.js +28 -0
  16. package/dist/channels/origin/origin-channel.d.ts +68 -0
  17. package/dist/channels/origin/origin-channel.d.ts.map +1 -0
  18. package/dist/channels/origin/origin-channel.js +567 -0
  19. package/dist/channels/origin/origin-webhook.d.ts +38 -0
  20. package/dist/channels/origin/origin-webhook.d.ts.map +1 -0
  21. package/dist/channels/origin/origin-webhook.js +151 -0
  22. package/dist/channels/origin/types.d.ts +152 -0
  23. package/dist/channels/origin/types.d.ts.map +1 -0
  24. package/dist/channels/origin/types.js +1 -0
  25. package/dist/channels/slack/doctor.d.ts +17 -1
  26. package/dist/channels/slack/doctor.d.ts.map +1 -1
  27. package/dist/channels/slack/doctor.js +186 -10
  28. package/dist/docs/404.html +2 -2
  29. package/dist/docs/ab.html +4 -4
  30. package/dist/docs/assets/{app.CVQxhV85.js → app.B-biogkN.js} +1 -1
  31. package/dist/docs/assets/chunks/@localSearchIndexroot.5ozYNf74.js +1 -0
  32. package/dist/docs/assets/chunks/{VPLocalSearchBox.QAPzJjql.js → VPLocalSearchBox.DZqKtFZS.js} +1 -1
  33. package/dist/docs/assets/chunks/{theme.CSxTCOFu.js → theme.BwC5zP2r.js} +2 -2
  34. package/dist/docs/assets/{example-agents_fsd.md.DPz9ezO4.js → example-agents_fsd.md.ZeGEpAw_.js} +2 -2
  35. package/dist/docs/assets/{example-agents_fsd.md.DPz9ezO4.lean.js → example-agents_fsd.md.ZeGEpAw_.lean.js} +1 -1
  36. package/dist/docs/assets/{example-agents_security-reviewer.md.Dkf1gyo6.js → example-agents_security-reviewer.md.DBL1TwtP.js} +2 -2
  37. package/dist/docs/assets/{example-agents_security-reviewer.md.Dkf1gyo6.lean.js → example-agents_security-reviewer.md.DBL1TwtP.lean.js} +1 -1
  38. package/dist/docs/assets/guides_convert-automation.md.BhMzTkE5.js +12 -0
  39. package/dist/docs/assets/guides_convert-automation.md.BhMzTkE5.lean.js +1 -0
  40. package/dist/docs/assets/{guides_github.md.B8QKtIpw.js → guides_github.md.CLLQJKRB.js} +4 -4
  41. package/dist/docs/assets/{guides_github.md.B8QKtIpw.lean.js → guides_github.md.CLLQJKRB.lean.js} +1 -1
  42. package/dist/docs/assets/index.md.DhRHS_-L.js +5 -0
  43. package/dist/docs/assets/{index.md.COeoSkcF.lean.js → index.md.DhRHS_-L.lean.js} +1 -1
  44. package/dist/docs/assets/{reference_cli.md.D_CCfG8R.js → reference_cli.md.Cl14Jfo3.js} +8 -2
  45. package/dist/docs/assets/{reference_cli.md.D_CCfG8R.lean.js → reference_cli.md.Cl14Jfo3.lean.js} +1 -1
  46. package/dist/docs/assets/scaffolding-agents.md.CrWSA0Ko.js +1 -0
  47. package/dist/docs/assets/{scaffolding-agents.md.mkc3B_ZW.lean.js → scaffolding-agents.md.CrWSA0Ko.lean.js} +1 -1
  48. package/dist/docs/assets/templates_agentic-owners.md.BkTLORaU.js +14 -0
  49. package/dist/docs/assets/templates_agentic-owners.md.BkTLORaU.lean.js +1 -0
  50. package/dist/docs/assets/templates_demo.md.Bgd6MBaZ.js +4 -0
  51. package/dist/docs/assets/templates_demo.md.Bgd6MBaZ.lean.js +1 -0
  52. package/dist/docs/assets/templates_pr-autofixer.md.DcmoeUNZ.js +8 -0
  53. package/dist/docs/assets/templates_pr-autofixer.md.DcmoeUNZ.lean.js +1 -0
  54. package/dist/docs/assets/templates_security-reviewer.md.C0yIUaYs.js +2 -0
  55. package/dist/docs/assets/templates_security-reviewer.md.C0yIUaYs.lean.js +1 -0
  56. package/dist/docs/building-with-agents.html +4 -4
  57. package/dist/docs/concepts.html +5 -5
  58. package/dist/docs/deployment.html +4 -4
  59. package/dist/docs/evals.html +4 -4
  60. package/dist/docs/example-agents/approval-buddy.html +4 -4
  61. package/dist/docs/example-agents/benny.html +4 -4
  62. package/dist/docs/example-agents/bugbot.html +4 -4
  63. package/dist/docs/example-agents/codebase-wiki.html +4 -4
  64. package/dist/docs/example-agents/codeowners-review.html +4 -4
  65. package/dist/docs/example-agents/concierge.html +4 -4
  66. package/dist/docs/example-agents/fsd.html +5 -5
  67. package/dist/docs/example-agents/index.html +4 -4
  68. package/dist/docs/example-agents/knowledge-base.html +4 -4
  69. package/dist/docs/example-agents/oncall.html +4 -4
  70. package/dist/docs/example-agents/security-reviewer.html +5 -5
  71. package/dist/docs/example-agents/slack-agent.html +4 -4
  72. package/dist/docs/example-agents/weather-agent.html +4 -4
  73. package/dist/docs/guides/agent-to-agent.html +4 -4
  74. package/dist/docs/guides/cloud-runtime.html +4 -4
  75. package/dist/docs/guides/convert-automation.html +36 -0
  76. package/dist/docs/guides/github.html +7 -7
  77. package/dist/docs/guides/human-in-the-loop.html +4 -4
  78. package/dist/docs/guides/mcp-oauth.html +4 -4
  79. package/dist/docs/guides/opentelemetry.html +4 -4
  80. package/dist/docs/guides/slack.html +4 -4
  81. package/dist/docs/guides/webhooks.html +4 -4
  82. package/dist/docs/hashmap.json +1 -1
  83. package/dist/docs/hillclimbing.html +4 -4
  84. package/dist/docs/index.html +6 -6
  85. package/dist/docs/quickstart.html +4 -4
  86. package/dist/docs/reference/agent-config.html +4 -4
  87. package/dist/docs/reference/artifacts.html +4 -4
  88. package/dist/docs/reference/channels.html +4 -4
  89. package/dist/docs/reference/cli.html +12 -6
  90. package/dist/docs/reference/connections.html +4 -4
  91. package/dist/docs/reference/hooks.html +4 -4
  92. package/dist/docs/reference/http-api.html +4 -4
  93. package/dist/docs/reference/instructions.html +4 -4
  94. package/dist/docs/reference/playground.html +4 -4
  95. package/dist/docs/reference/project-layout.html +4 -4
  96. package/dist/docs/reference/prompt.html +4 -4
  97. package/dist/docs/reference/schedules.html +4 -4
  98. package/dist/docs/reference/sessions.html +4 -4
  99. package/dist/docs/reference/skills.html +4 -4
  100. package/dist/docs/reference/subagents.html +4 -4
  101. package/dist/docs/reference/tools.html +4 -4
  102. package/dist/docs/scaffolding-agents.html +5 -5
  103. package/dist/docs/storage.html +4 -4
  104. package/dist/docs/templates/agentic-owners.html +38 -0
  105. package/dist/docs/templates/demo.html +28 -0
  106. package/dist/docs/templates/pr-autofixer.html +32 -0
  107. package/dist/docs/templates/security-reviewer.html +26 -0
  108. package/dist/docs/templates/triage.html +5 -5
  109. package/dist/docs/troubleshooting.html +4 -4
  110. package/dist/index.d.ts +3 -3
  111. package/dist/index.d.ts.map +1 -1
  112. package/dist/index.js +2 -2
  113. package/dist/internal/cli-ax.d.ts +2 -0
  114. package/dist/internal/cli-ax.d.ts.map +1 -1
  115. package/dist/internal/cli-ax.js +20 -0
  116. package/dist/internal/cli-slack.d.ts +2 -0
  117. package/dist/internal/cli-slack.d.ts.map +1 -1
  118. package/dist/internal/cli-slack.js +11 -2
  119. package/dist/internal/cursor-event-relay.d.ts +64 -12
  120. package/dist/internal/cursor-event-relay.d.ts.map +1 -1
  121. package/dist/internal/cursor-event-relay.js +138 -26
  122. package/dist/internal/discovery.d.ts.map +1 -1
  123. package/dist/internal/discovery.js +11 -2
  124. package/dist/internal/distribution.d.ts.map +1 -1
  125. package/dist/internal/distribution.js +1 -0
  126. package/dist/internal/handleAgentServeTrigger.d.ts +33 -6
  127. package/dist/internal/handleAgentServeTrigger.d.ts.map +1 -1
  128. package/dist/internal/handleAgentServeTrigger.js +97 -19
  129. package/dist/internal/init-interview.d.ts +67 -0
  130. package/dist/internal/init-interview.d.ts.map +1 -0
  131. package/dist/internal/init-interview.js +300 -0
  132. package/dist/internal/init-project.d.ts +4 -0
  133. package/dist/internal/init-project.d.ts.map +1 -1
  134. package/dist/internal/init-project.js +40 -16
  135. package/dist/internal/mcp-endpoint.d.ts +7 -0
  136. package/dist/internal/mcp-endpoint.d.ts.map +1 -1
  137. package/dist/internal/mcp-endpoint.js +7 -0
  138. package/dist/internal/mcp-oauth.d.ts +0 -4
  139. package/dist/internal/mcp-oauth.d.ts.map +1 -1
  140. package/dist/internal/mcp-oauth.js +0 -4
  141. package/dist/internal/server.d.ts.map +1 -1
  142. package/dist/internal/server.js +160 -58
  143. package/dist/internal/session-engine.d.ts.map +1 -1
  144. package/dist/internal/session-engine.js +20 -21
  145. package/dist/internal/session-links.d.ts +14 -0
  146. package/dist/internal/session-links.d.ts.map +1 -0
  147. package/dist/internal/session-links.js +69 -0
  148. package/dist/internal/sessions-client.d.ts.map +1 -1
  149. package/dist/internal/sessions-client.js +1 -0
  150. package/dist/playground/assets/index-B4rcOgeP.css +1 -0
  151. package/dist/playground/assets/{index-0oqXUkrR.js → index-DXcY42Jv.js} +42 -42
  152. package/dist/playground/index.html +2 -2
  153. package/dist/types.d.ts +19 -12
  154. package/dist/types.d.ts.map +1 -1
  155. package/docs/README.md +15 -0
  156. package/docs/example-agents/fsd.md +3 -0
  157. package/docs/example-agents/security-reviewer.md +3 -0
  158. package/docs/guides/convert-automation.md +176 -0
  159. package/docs/guides/github.md +6 -2
  160. package/docs/reference/cli.md +34 -10
  161. package/docs/scaffolding-agents.md +3 -0
  162. package/docs/templates/agentic-owners.md +97 -0
  163. package/docs/templates/demo.md +84 -0
  164. package/docs/templates/pr-autofixer.md +136 -0
  165. package/docs/templates/security-reviewer.md +89 -0
  166. package/package.json +9 -1
  167. package/skills/github/SKILL.md +6 -6
  168. package/src/bin/agent-serve.ts +13 -6
  169. package/src/channels/github/github-channel.ts +113 -20
  170. package/src/channels/github/types.ts +33 -0
  171. package/src/channels/origin/cursor-account.ts +64 -0
  172. package/src/channels/origin/events.ts +41 -0
  173. package/src/channels/origin/index.ts +29 -0
  174. package/src/channels/origin/origin-channel.ts +784 -0
  175. package/src/channels/origin/origin-webhook.ts +202 -0
  176. package/src/channels/origin/types.ts +186 -0
  177. package/src/channels/slack/doctor.ts +218 -5
  178. package/src/index.ts +3 -1
  179. package/src/internal/cli-ax.ts +23 -0
  180. package/src/internal/cli-slack.ts +11 -1
  181. package/src/internal/cursor-event-relay.ts +201 -32
  182. package/src/internal/discovery.ts +15 -5
  183. package/src/internal/distribution.ts +1 -0
  184. package/src/internal/handleAgentServeTrigger.ts +129 -19
  185. package/src/internal/init-interview.ts +384 -0
  186. package/src/internal/init-project.ts +70 -15
  187. package/src/internal/mcp-endpoint.ts +7 -0
  188. package/src/internal/mcp-oauth.ts +0 -4
  189. package/src/internal/server.ts +190 -60
  190. package/src/internal/session-engine.ts +5 -21
  191. package/src/internal/session-links.ts +88 -0
  192. package/src/internal/sessions-client.ts +1 -0
  193. package/src/types.ts +19 -12
  194. package/templates/agentic-owners/README.md +73 -0
  195. package/templates/agentic-owners/agent/agent.ts +15 -0
  196. package/templates/agentic-owners/agent/channels/github.ts +85 -0
  197. package/templates/agentic-owners/agent/instructions.md +34 -0
  198. package/templates/agentic-owners/agent/lib/config.ts +13 -0
  199. package/templates/agentic-owners/agent/lib/github.ts +241 -0
  200. package/templates/agentic-owners/agent/lib/owners/README.md +50 -0
  201. package/templates/agentic-owners/agent/lib/owners/constants.ts +22 -0
  202. package/templates/agentic-owners/agent/lib/owners/decision.ts +485 -0
  203. package/templates/agentic-owners/agent/lib/owners/handles.ts +54 -0
  204. package/templates/agentic-owners/agent/lib/owners/match.ts +177 -0
  205. package/templates/agentic-owners/agent/lib/owners/matching.ts +95 -0
  206. package/templates/agentic-owners/agent/lib/owners/parse.ts +589 -0
  207. package/templates/agentic-owners/agent/lib/owners/policyMode.ts +65 -0
  208. package/templates/agentic-owners/agent/lib/owners/prompt.ts +66 -0
  209. package/templates/agentic-owners/agent/lib/owners/prompts/base-review.md +105 -0
  210. package/templates/agentic-owners/agent/lib/owners/types.ts +45 -0
  211. package/templates/agentic-owners/agent/lib/review.ts +777 -0
  212. package/templates/agentic-owners/agent/tools/record_review.ts +69 -0
  213. package/templates/agentic-owners/evals/evals.config.ts +5 -0
  214. package/templates/agentic-owners/evals/owners.eval.ts +116 -0
  215. package/templates/agentic-owners/package.json +20 -0
  216. package/templates/agentic-owners/tsconfig.json +12 -0
  217. package/templates/demo/README.md +33 -0
  218. package/templates/demo/agent/agent.ts +15 -0
  219. package/templates/demo/agent/channels/github.ts +50 -0
  220. package/templates/demo/agent/channels/queue.ts +30 -0
  221. package/templates/demo/agent/instructions.md +8 -0
  222. package/templates/demo/agent/lib/collect.ts +78 -0
  223. package/templates/demo/agent/tools/record_demo.ts +40 -0
  224. package/templates/demo/evals/demo.eval.ts +33 -0
  225. package/templates/demo/evals/evals.config.ts +5 -0
  226. package/templates/demo/package.json +18 -0
  227. package/templates/demo/tsconfig.json +12 -0
  228. package/templates/pr-autofixer/README.md +44 -0
  229. package/templates/pr-autofixer/agent/agent.ts +22 -0
  230. package/templates/pr-autofixer/agent/channels/drive.ts +40 -0
  231. package/templates/pr-autofixer/agent/channels/github.ts +167 -0
  232. package/templates/pr-autofixer/agent/channels/slack.ts +17 -0
  233. package/templates/pr-autofixer/agent/hooks/bind-agent.ts +19 -0
  234. package/templates/pr-autofixer/agent/instructions.md +83 -0
  235. package/templates/pr-autofixer/agent/lib/affinity.ts +33 -0
  236. package/templates/pr-autofixer/agent/lib/drive-schemas.ts +15 -0
  237. package/templates/pr-autofixer/agent/lib/drive.ts +79 -0
  238. package/templates/pr-autofixer/agent/lib/merge-watch.ts +123 -0
  239. package/templates/pr-autofixer/agent/lib/pr-state.ts +54 -0
  240. package/templates/pr-autofixer/agent/lib/repos.ts +19 -0
  241. package/templates/pr-autofixer/agent/lib/start-drive.ts +122 -0
  242. package/templates/pr-autofixer/agent/lib/webhook-buffer.ts +225 -0
  243. package/templates/pr-autofixer/agent/lib/webhook-routing.ts +231 -0
  244. package/templates/pr-autofixer/agent/storage.ts +7 -0
  245. package/templates/pr-autofixer/agent/tools/drive_pr.ts +22 -0
  246. package/templates/pr-autofixer/evals/coordinator.eval.ts +16 -0
  247. package/templates/pr-autofixer/evals/evals.config.ts +5 -0
  248. package/templates/pr-autofixer/init.json +25 -0
  249. package/templates/pr-autofixer/package.json +18 -0
  250. package/templates/pr-autofixer/tsconfig.json +12 -0
  251. package/templates/security-reviewer/README.md +31 -0
  252. package/templates/security-reviewer/agent/agent.ts +15 -0
  253. package/templates/security-reviewer/agent/channels/github.ts +46 -0
  254. package/templates/security-reviewer/agent/instructions.md +22 -0
  255. package/templates/security-reviewer/agent/lib/repos.ts +5 -0
  256. package/templates/security-reviewer/agent/tools/post_findings.ts +72 -0
  257. package/templates/security-reviewer/evals/evals.config.ts +5 -0
  258. package/templates/security-reviewer/evals/review.eval.ts +53 -0
  259. package/templates/security-reviewer/init.json +25 -0
  260. package/templates/security-reviewer/package.json +18 -0
  261. package/templates/security-reviewer/tsconfig.json +12 -0
  262. package/dist/docs/assets/chunks/@localSearchIndexroot.BFpWSo6D.js +0 -1
  263. package/dist/docs/assets/index.md.COeoSkcF.js +0 -5
  264. package/dist/docs/assets/scaffolding-agents.md.mkc3B_ZW.js +0 -1
  265. package/dist/playground/assets/index-tHCjJxv4.css +0 -1
@@ -70,7 +70,7 @@ import type {
70
70
  */
71
71
  type GitHubParsedContext = Omit<
72
72
  GitHubEventContext,
73
- "github" | "thread" | "host" | "artifacts"
73
+ "github" | "thread" | "host" | "artifacts" | "payload"
74
74
  >;
75
75
 
76
76
  const DEFAULT_PULL_REQUEST_ACTIONS: ReadonlySet<string> = new Set([
@@ -136,6 +136,16 @@ const githubPullRequestPayloadSchema: z.ZodType<GitHubPullRequestPayload> =
136
136
  sha: z.string().optional(),
137
137
  }),
138
138
  }),
139
+ changes: z
140
+ .object({
141
+ base: z
142
+ .object({
143
+ ref: z.object({ from: z.string().min(1).optional() }).optional(),
144
+ })
145
+ .optional(),
146
+ })
147
+ .nullable()
148
+ .optional(),
139
149
  sender: senderSchema,
140
150
  installation: installationSchema,
141
151
  label: z
@@ -184,6 +194,32 @@ export function githubContinuationKey(ctx: GitHubParsedContext): string {
184
194
  return `${kind}:${ctx.repository.fullName}#${ctx.conversation.number}`;
185
195
  }
186
196
 
197
+ export interface GitHubPullRequestRef {
198
+ owner: string;
199
+ repo: string;
200
+ number: number;
201
+ }
202
+
203
+ /**
204
+ * Parse a pull-request continuation key minted by
205
+ * {@link githubContinuationKey} back into its repo + number. Undefined for
206
+ * issue keys and non-GitHub sessions — lets a server tool recover which PR
207
+ * its session is pinned to without trusting model-provided identifiers.
208
+ */
209
+ export function parseGitHubPrContinuationKey(
210
+ key: string
211
+ ): GitHubPullRequestRef | undefined {
212
+ const match = /^github-pr:([^/#\s]+)\/([^#\s]+)#(\d+)$/.exec(key);
213
+ if (match === null) {
214
+ return undefined;
215
+ }
216
+ return {
217
+ owner: match[1]!,
218
+ repo: match[2]!,
219
+ number: Number(match[3]!),
220
+ };
221
+ }
222
+
187
223
  /** @deprecated Prefer {@link githubContinuationKey}. */
188
224
  export function githubPullRequestContinuationKey(
189
225
  ctx: GitHubParsedContext
@@ -338,6 +374,9 @@ export function parseGitHubPullRequestEvent(args: {
338
374
  ...(payload.pull_request.base.sha === undefined
339
375
  ? {}
340
376
  : { baseSha: payload.pull_request.base.sha }),
377
+ ...(payload.changes?.base?.ref?.from === undefined
378
+ ? {}
379
+ : { baseRefChangedFrom: payload.changes.base.ref.from }),
341
380
  draft: payload.pull_request.draft ?? false,
342
381
  merged: payload.pull_request.merged === true,
343
382
  ...(payload.pull_request.user?.login === undefined
@@ -748,6 +787,7 @@ async function handlePullRequest(input: {
748
787
  const ctx = enrichEventContext({
749
788
  bindingConfig: input.bindingConfig,
750
789
  ctx: parsed.ctx,
790
+ payload: input.payload,
751
791
  bindingState: binding,
752
792
  installationId,
753
793
  host: input.args.host,
@@ -840,6 +880,7 @@ async function handleIssueComment(input: {
840
880
  const ctx = enrichEventContext({
841
881
  bindingConfig: input.bindingConfig,
842
882
  ctx: parsed.ctx,
883
+ payload: input.payload,
843
884
  bindingState: binding,
844
885
  installationId,
845
886
  host: input.args.host,
@@ -931,6 +972,7 @@ async function handleReviewComment(input: {
931
972
  const ctx = enrichEventContext({
932
973
  bindingConfig: input.bindingConfig,
933
974
  ctx: parsed.ctx,
975
+ payload: input.payload,
934
976
  bindingState: binding,
935
977
  installationId,
936
978
  host: input.args.host,
@@ -1011,6 +1053,7 @@ async function handleIssue(input: {
1011
1053
  const ctx = enrichEventContext({
1012
1054
  bindingConfig: input.bindingConfig,
1013
1055
  ctx: parsed.ctx,
1056
+ payload: input.payload,
1014
1057
  bindingState: binding,
1015
1058
  installationId,
1016
1059
  host: input.args.host,
@@ -1072,6 +1115,7 @@ async function handleCheckSuite(input: {
1072
1115
  enrichCiContext({
1073
1116
  bindingConfig: input.bindingConfig,
1074
1117
  ctx: parsed.unanchoredCtx,
1118
+ payload: input.payload,
1075
1119
  installationId,
1076
1120
  host: input.args.host,
1077
1121
  artifacts: input.args.artifacts,
@@ -1098,6 +1142,7 @@ async function handleCheckSuite(input: {
1098
1142
  const ctx = enrichEventContext({
1099
1143
  bindingConfig: input.bindingConfig,
1100
1144
  ctx: parsed.ctx,
1145
+ payload: input.payload,
1101
1146
  bindingState: binding,
1102
1147
  installationId,
1103
1148
  host: input.args.host,
@@ -1164,6 +1209,7 @@ async function handleCheckRun(input: {
1164
1209
  enrichCiContext({
1165
1210
  bindingConfig: input.bindingConfig,
1166
1211
  ctx: parsed.unanchoredCtx,
1212
+ payload: input.payload,
1167
1213
  installationId,
1168
1214
  host: input.args.host,
1169
1215
  artifacts: input.args.artifacts,
@@ -1190,6 +1236,7 @@ async function handleCheckRun(input: {
1190
1236
  const ctx = enrichEventContext({
1191
1237
  bindingConfig: input.bindingConfig,
1192
1238
  ctx: parsed.ctx,
1239
+ payload: input.payload,
1193
1240
  bindingState: binding,
1194
1241
  installationId,
1195
1242
  host: input.args.host,
@@ -1252,6 +1299,7 @@ async function handleWorkflowRun(input: {
1252
1299
  enrichCiContext({
1253
1300
  bindingConfig: input.bindingConfig,
1254
1301
  ctx: parsed.unanchoredCtx,
1302
+ payload: input.payload,
1255
1303
  installationId,
1256
1304
  host: input.args.host,
1257
1305
  artifacts: input.args.artifacts,
@@ -1278,6 +1326,7 @@ async function handleWorkflowRun(input: {
1278
1326
  const ctx = enrichEventContext({
1279
1327
  bindingConfig: input.bindingConfig,
1280
1328
  ctx: parsed.ctx,
1329
+ payload: input.payload,
1281
1330
  bindingState: binding,
1282
1331
  installationId,
1283
1332
  host: input.args.host,
@@ -1350,6 +1399,7 @@ async function handleStatus(input: {
1350
1399
  const ctx = enrichEventContext({
1351
1400
  bindingConfig: input.bindingConfig,
1352
1401
  ctx: parsed.ctx,
1402
+ payload: input.payload,
1353
1403
  bindingState: binding,
1354
1404
  installationId,
1355
1405
  host: input.args.host,
@@ -1424,6 +1474,7 @@ async function handleGenericEvent(input: {
1424
1474
  const ctx = enrichEventContext({
1425
1475
  bindingConfig: input.bindingConfig,
1426
1476
  ctx: parsed.ctx,
1477
+ payload: input.payload,
1427
1478
  bindingState: binding,
1428
1479
  installationId,
1429
1480
  host: input.args.host,
@@ -1469,15 +1520,34 @@ async function startTurn(input: {
1469
1520
  cloud?: AgentCloudOptions;
1470
1521
  state: GitHubChannelState;
1471
1522
  }): Promise<Response> {
1472
- const session = await input.args.send(input.message, {
1473
- auth: input.dispatch.auth,
1474
- continuationToken: githubContinuationKey(input.ctx),
1475
- title: input.dispatch.title ?? defaultGitHubTitle(input.ctx),
1476
- ...(input.cloud === undefined ? {} : { cloud: input.cloud }),
1477
- state: input.state as unknown as JsonValue,
1478
- // Resume must refresh headSha / refs without wiping sticky banner id.
1479
- refreshState: input.state as unknown as JsonValue,
1480
- });
1523
+ const files = input.dispatch.workspaceFiles;
1524
+ const lazy = typeof files === "function";
1525
+
1526
+ const sendTurn = async () => {
1527
+ const workspaceFiles = lazy ? await files() : files;
1528
+ return input.args.send(input.message, {
1529
+ auth: input.dispatch.auth,
1530
+ continuationToken: githubContinuationKey(input.ctx),
1531
+ title: input.dispatch.title ?? defaultGitHubTitle(input.ctx),
1532
+ ...(input.cloud === undefined ? {} : { cloud: input.cloud }),
1533
+ ...(workspaceFiles === undefined ? {} : { workspaceFiles }),
1534
+ state: input.state as unknown as JsonValue,
1535
+ // Resume must refresh headSha / refs without wiping sticky banner id.
1536
+ refreshState: input.state as unknown as JsonValue,
1537
+ });
1538
+ };
1539
+
1540
+ if (lazy) {
1541
+ scheduleAfterAck(input.args, async () => {
1542
+ await sendTurn();
1543
+ });
1544
+ return Response.json(
1545
+ { ok: true, dispatched: true, mode: "turn" },
1546
+ { status: 202 }
1547
+ );
1548
+ }
1549
+
1550
+ const session = await sendTurn();
1481
1551
  return Response.json({
1482
1552
  ok: true,
1483
1553
  sessionId: session.id,
@@ -1486,22 +1556,41 @@ async function startTurn(input: {
1486
1556
  });
1487
1557
  }
1488
1558
 
1489
- function acknowledgeTask(
1559
+ function reportBackgroundFailure(error: unknown): void {
1560
+ const detail =
1561
+ error instanceof Error ? (error.stack ?? error.message) : String(error);
1562
+ console.error(`[github] background dispatch failed: ${detail}`);
1563
+ }
1564
+
1565
+ function scheduleAfterAck(
1490
1566
  args: ChannelHandlerArgs,
1491
- dispatch: GitHubTaskDispatch,
1492
- extra: Record<string, unknown>
1493
- ): Response {
1494
- // Defer the task past the current turn so the 202 can flush before work
1495
- // starts (and so tests can assert scheduling without racing microtasks).
1567
+ work: () => void | Promise<void>
1568
+ ): void {
1569
+ // Defer past the current turn so the 202 can flush before work starts
1570
+ // (and so tests can assert scheduling without racing microtasks).
1496
1571
  args.waitUntil(
1497
- new Promise<void>((resolve, reject) => {
1572
+ new Promise<void>((resolve) => {
1498
1573
  setImmediate(() => {
1499
1574
  Promise.resolve()
1500
- .then(dispatch.task)
1501
- .then(() => resolve(), reject);
1575
+ .then(work)
1576
+ .then(
1577
+ () => resolve(),
1578
+ (error: unknown) => {
1579
+ reportBackgroundFailure(error);
1580
+ resolve();
1581
+ }
1582
+ );
1502
1583
  });
1503
1584
  })
1504
1585
  );
1586
+ }
1587
+
1588
+ function acknowledgeTask(
1589
+ args: ChannelHandlerArgs,
1590
+ dispatch: GitHubTaskDispatch,
1591
+ extra: Record<string, unknown>
1592
+ ): Response {
1593
+ scheduleAfterAck(args, dispatch.task);
1505
1594
  return Response.json(
1506
1595
  { ok: true, dispatched: true, mode: "task", ...extra },
1507
1596
  { status: 202 }
@@ -2276,10 +2365,11 @@ function escapeRegExp(value: string): string {
2276
2365
  */
2277
2366
  function enrichEventContext(input: {
2278
2367
  bindingConfig: GitHubBindingConfig;
2279
- ctx: Omit<GitHubEventContext, "github" | "thread" | "host" | "artifacts"> &
2368
+ ctx: GitHubParsedContext &
2280
2369
  Partial<Pick<GitHubEventContext, "github" | "thread">>;
2281
2370
  bindingState: GitHubBindingState;
2282
2371
  installationId?: number;
2372
+ payload: unknown;
2283
2373
  host: HostContext;
2284
2374
  artifacts: ArtifactsApi;
2285
2375
  }): GitHubEventContext {
@@ -2289,6 +2379,7 @@ function enrichEventContext(input: {
2289
2379
  });
2290
2380
  return {
2291
2381
  ...input.ctx,
2382
+ payload: input.payload,
2292
2383
  ...(input.installationId === undefined
2293
2384
  ? {}
2294
2385
  : { installationId: input.installationId }),
@@ -2307,6 +2398,7 @@ function enrichCiContext(input: {
2307
2398
  bindingConfig: GitHubBindingConfig;
2308
2399
  ctx: GitHubParsedContext;
2309
2400
  installationId?: number;
2401
+ payload: unknown;
2310
2402
  host: HostContext;
2311
2403
  artifacts: ArtifactsApi;
2312
2404
  }): GitHubEventContext {
@@ -2323,6 +2415,7 @@ function enrichCiContext(input: {
2323
2415
  ctx: input.ctx,
2324
2416
  bindingState: binding,
2325
2417
  installationId: input.installationId,
2418
+ payload: input.payload,
2326
2419
  host: input.host,
2327
2420
  artifacts: input.artifacts,
2328
2421
  });
@@ -6,6 +6,7 @@ import type {
6
6
  ChannelEventHandlers,
7
7
  ChannelStartArgs,
8
8
  HostContext,
9
+ SendMessageOptions,
9
10
  } from "../../types.js";
10
11
  import type { GitHubApiOptions } from "./api.js";
11
12
  import type { GitHubHandle, GitHubThread } from "./binding.js";
@@ -165,6 +166,13 @@ export type GitHubPullRequestPayload = {
165
166
  sha?: string;
166
167
  };
167
168
  };
169
+ /**
170
+ * Present on `edited` deliveries; `changes.base.ref.from` carries the
171
+ * previous base branch when the PR was retargeted.
172
+ */
173
+ changes?: {
174
+ base?: { ref?: { from?: string } };
175
+ } | null;
168
176
  sender?: {
169
177
  login?: string;
170
178
  id?: number;
@@ -186,6 +194,13 @@ export interface GitHubPullRequestEvent {
186
194
  headSha: string;
187
195
  baseRef: string;
188
196
  baseSha?: string;
197
+ /**
198
+ * On `edited` deliveries where the PR base was retargeted, the previous
199
+ * base branch (`changes.base.ref.from`). Undefined for every other edit
200
+ * (title / body), so `action === "edited" && baseRefChangedFrom` gates
201
+ * base-retarget handling without waking on prose edits.
202
+ */
203
+ baseRefChangedFrom?: string;
189
204
  draft: boolean;
190
205
  /** True when the PR was merged (from the webhook payload). */
191
206
  merged: boolean;
@@ -305,6 +320,8 @@ export interface GitHubEventContext {
305
320
  sender?: GitHubUser;
306
321
  /** Installation id from the webhook payload, when present. */
307
322
  installationId?: number;
323
+ /** Verified webhook body for this delivery. */
324
+ payload: unknown;
308
325
  /** Authenticated GitHub helpers (`getOctokit`, `request`, `createStatus`). */
309
326
  github: GitHubHandle;
310
327
  /** Post / react on the conversation thread. */
@@ -324,6 +341,11 @@ export interface GitHubEventContext {
324
341
  */
325
342
  export type GitHubDispatch = GitHubTurnDispatch | GitHubTaskDispatch;
326
343
 
344
+ /** Files seeded into the session workspace before the turn. */
345
+ export type GitHubWorkspaceFiles = NonNullable<
346
+ SendMessageOptions["workspaceFiles"]
347
+ >;
348
+
327
349
  /** Start (or resume) a model turn for the event. */
328
350
  export interface GitHubTurnDispatch {
329
351
  /** Who the turn runs as. Use `defaultGitHubAuth(ctx)` to derive it from the actor. */
@@ -334,6 +356,17 @@ export interface GitHubTurnDispatch {
334
356
  message?: string;
335
357
  /** Optional session title override. */
336
358
  title?: string;
359
+ /**
360
+ * Seeded into the session workspace before the turn (`send`'s
361
+ * `workspaceFiles`). A function runs after the webhook is
362
+ * acknowledged (202) so fetch I/O can outlive GitHub's ~10s window.
363
+ */
364
+ workspaceFiles?:
365
+ | GitHubWorkspaceFiles
366
+ | (() =>
367
+ | GitHubWorkspaceFiles
368
+ | undefined
369
+ | Promise<GitHubWorkspaceFiles | undefined>);
337
370
  }
338
371
 
339
372
  /**
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Cursor-account mode for Origin channels.
3
+ *
4
+ * Origin identity is the signed-in Cursor user (no third-party OAuth). The
5
+ * channel declares repos at definition time; the serve host subscribes
6
+ * `/v0/scm-events` with `provider: "origin"` as that user. Unlike GitHub,
7
+ * there is no installation token to mint — outbound Origin API calls already
8
+ * authenticate as the Cursor principal.
9
+ */
10
+
11
+ import type { OriginChannelOptions } from "./types.js";
12
+
13
+ export const CURSOR_ORIGIN_MAX_REPOS = 20;
14
+ const CURSOR_ORIGIN_REPO_PATTERN = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/;
15
+
16
+ export interface CursorOriginRepoScope {
17
+ repos: readonly string[];
18
+ }
19
+
20
+ export interface OriginCursorAccountRuntime {
21
+ options: OriginChannelOptions;
22
+ scope: CursorOriginRepoScope | undefined;
23
+ }
24
+
25
+ const runtimeByDefinition = new WeakMap<object, OriginCursorAccountRuntime>();
26
+
27
+ export function parseCursorOriginRepoScope(
28
+ values: readonly string[]
29
+ ): CursorOriginRepoScope {
30
+ const repos = [
31
+ ...new Set(values.map((repo) => repo.trim().toLowerCase()).filter(Boolean)),
32
+ ];
33
+ if (repos.length === 0) {
34
+ throw new Error(
35
+ "originChannel({ cursorAccount }) requires at least one repository."
36
+ );
37
+ }
38
+ if (repos.length > CURSOR_ORIGIN_MAX_REPOS) {
39
+ throw new Error(
40
+ `originChannel({ cursorAccount }) supports at most ${CURSOR_ORIGIN_MAX_REPOS} repositories.`
41
+ );
42
+ }
43
+ for (const repo of repos) {
44
+ if (!CURSOR_ORIGIN_REPO_PATTERN.test(repo) || repo.includes("..")) {
45
+ throw new Error(
46
+ `Invalid Origin repository "${repo}"; expected owner/repo.`
47
+ );
48
+ }
49
+ }
50
+ return { repos };
51
+ }
52
+
53
+ export function registerOriginCursorAccountRuntime(
54
+ definition: object,
55
+ runtime: OriginCursorAccountRuntime
56
+ ): void {
57
+ runtimeByDefinition.set(definition, runtime);
58
+ }
59
+
60
+ export function getOriginCursorAccountRuntime(
61
+ definition: object
62
+ ): OriginCursorAccountRuntime | undefined {
63
+ return runtimeByDefinition.get(definition);
64
+ }
@@ -0,0 +1,41 @@
1
+ /** {@link ChannelMeta.kind} value used by {@link originChannel}. */
2
+ export const ORIGIN_CHANNEL_KIND = "origin";
3
+
4
+ const BASE_WEBHOOK_EVENTS: readonly string[] = [
5
+ "pull_request.created",
6
+ "pull_request.published",
7
+ "pull_request.head_ref.pushed",
8
+ "pull_request.base_ref.updated",
9
+ "pull_request.closed",
10
+ "pull_request.merged",
11
+ ];
12
+
13
+ const COMMENT_EVENTS: readonly string[] = ["pull_request.comment.created"];
14
+ const REVIEW_EVENTS: readonly string[] = ["pull_request.review.submitted"];
15
+
16
+ export interface OriginWebhookEventOptions {
17
+ webhookEvents?: readonly string[];
18
+ onComment?: unknown;
19
+ onReview?: unknown;
20
+ onEvent?: unknown;
21
+ }
22
+
23
+ export function deriveOriginWebhookEvents(
24
+ options: OriginWebhookEventOptions
25
+ ): string[] {
26
+ if (options.webhookEvents !== undefined) {
27
+ return [
28
+ ...new Set(
29
+ options.webhookEvents.map((event) => event.trim()).filter(Boolean)
30
+ ),
31
+ ];
32
+ }
33
+ const events: string[] = [...BASE_WEBHOOK_EVENTS];
34
+ if (options.onComment !== undefined) {
35
+ events.push(...COMMENT_EVENTS);
36
+ }
37
+ if (options.onReview !== undefined) {
38
+ events.push(...REVIEW_EVENTS);
39
+ }
40
+ return [...new Set(events)];
41
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Origin webhook channel pack for agent-serve.
3
+ *
4
+ * ```ts
5
+ * import { defaultOriginAuth, originChannel } from "@cursor/july/channels/origin";
6
+ *
7
+ * export default originChannel({
8
+ * cursorAccount: { repos: ["owner/repo"] },
9
+ * onPullRequest: (ctx) => ({ auth: defaultOriginAuth(ctx) }),
10
+ * onComment: (ctx) => ({ auth: defaultOriginAuth(ctx) }),
11
+ * });
12
+ * ```
13
+ *
14
+ * Direct webhook mode verifies Standard-Webhooks v1ed signatures **and**
15
+ * binds `envelope.appId` to {@link OriginChannelOptions.appId} (or
16
+ * `AGENT_SERVE_ORIGIN_APP_ID`). v1ed alone is not channel auth — Origin
17
+ * signs every app's deliveries with the same JWKS. Pass
18
+ * `{ cursorAccount: true }` to receive events from
19
+ * `serve({ cursor: { events: true } })` after `/v0/scm-events`
20
+ * (`provider: "origin"`) already verified them. The turn principal is
21
+ * `origin-webhook` plus the Origin actor — not the Cursor subscriber —
22
+ * matching GitHub's `github-webhook` pattern.
23
+ */
24
+
25
+ export * from "./cursor-account.js";
26
+ export * from "./events.js";
27
+ export * from "./origin-channel.js";
28
+ export * from "./origin-webhook.js";
29
+ export * from "./types.js";