@cursor/july 0.1.55 → 0.1.61

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 (261) hide show
  1. package/dist/bin/agent-serve.js +30 -23
  2. package/dist/channels/github/github-channel.d.ts +12 -0
  3. package/dist/channels/github/github-channel.d.ts.map +1 -1
  4. package/dist/channels/github/github-channel.js +67 -15
  5. package/dist/channels/github/types.d.ts +27 -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.CW3KJh72.js} +1 -1
  31. package/dist/docs/assets/chunks/@localSearchIndexroot.BuymfBAo.js +1 -0
  32. package/dist/docs/assets/chunks/{VPLocalSearchBox.QAPzJjql.js → VPLocalSearchBox.Bk6EWpPj.js} +1 -1
  33. package/dist/docs/assets/chunks/{theme.CSxTCOFu.js → theme.Bz9AodBA.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 +59 -11
  120. package/dist/internal/cursor-event-relay.d.ts.map +1 -1
  121. package/dist/internal/cursor-event-relay.js +133 -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/server.d.ts.map +1 -1
  139. package/dist/internal/server.js +159 -57
  140. package/dist/internal/session-engine.d.ts.map +1 -1
  141. package/dist/internal/session-engine.js +20 -21
  142. package/dist/internal/session-links.d.ts +14 -0
  143. package/dist/internal/session-links.d.ts.map +1 -0
  144. package/dist/internal/session-links.js +69 -0
  145. package/dist/internal/sessions-client.d.ts.map +1 -1
  146. package/dist/internal/sessions-client.js +1 -0
  147. package/dist/playground/assets/index-ClbuaLpm.css +1 -0
  148. package/dist/playground/assets/{index-0oqXUkrR.js → index-SqkR13k_.js} +39 -39
  149. package/dist/playground/index.html +2 -2
  150. package/dist/types.d.ts +19 -12
  151. package/dist/types.d.ts.map +1 -1
  152. package/docs/README.md +15 -0
  153. package/docs/example-agents/fsd.md +3 -0
  154. package/docs/example-agents/security-reviewer.md +3 -0
  155. package/docs/guides/convert-automation.md +176 -0
  156. package/docs/guides/github.md +6 -2
  157. package/docs/reference/cli.md +34 -10
  158. package/docs/scaffolding-agents.md +3 -0
  159. package/docs/templates/agentic-owners.md +97 -0
  160. package/docs/templates/demo.md +84 -0
  161. package/docs/templates/pr-autofixer.md +136 -0
  162. package/docs/templates/security-reviewer.md +89 -0
  163. package/package.json +9 -1
  164. package/skills/github/SKILL.md +4 -5
  165. package/src/bin/agent-serve.ts +13 -6
  166. package/src/channels/github/github-channel.ts +95 -18
  167. package/src/channels/github/types.ts +31 -0
  168. package/src/channels/origin/cursor-account.ts +64 -0
  169. package/src/channels/origin/events.ts +41 -0
  170. package/src/channels/origin/index.ts +29 -0
  171. package/src/channels/origin/origin-channel.ts +784 -0
  172. package/src/channels/origin/origin-webhook.ts +202 -0
  173. package/src/channels/origin/types.ts +186 -0
  174. package/src/channels/slack/doctor.ts +218 -5
  175. package/src/index.ts +3 -1
  176. package/src/internal/cli-ax.ts +23 -0
  177. package/src/internal/cli-slack.ts +11 -1
  178. package/src/internal/cursor-event-relay.ts +193 -31
  179. package/src/internal/discovery.ts +15 -5
  180. package/src/internal/distribution.ts +1 -0
  181. package/src/internal/handleAgentServeTrigger.ts +129 -19
  182. package/src/internal/init-interview.ts +384 -0
  183. package/src/internal/init-project.ts +70 -15
  184. package/src/internal/mcp-endpoint.ts +7 -0
  185. package/src/internal/server.ts +188 -58
  186. package/src/internal/session-engine.ts +5 -21
  187. package/src/internal/session-links.ts +88 -0
  188. package/src/internal/sessions-client.ts +1 -0
  189. package/src/types.ts +19 -12
  190. package/templates/agentic-owners/README.md +73 -0
  191. package/templates/agentic-owners/agent/agent.ts +15 -0
  192. package/templates/agentic-owners/agent/channels/github.ts +85 -0
  193. package/templates/agentic-owners/agent/instructions.md +34 -0
  194. package/templates/agentic-owners/agent/lib/config.ts +13 -0
  195. package/templates/agentic-owners/agent/lib/github.ts +241 -0
  196. package/templates/agentic-owners/agent/lib/owners/README.md +50 -0
  197. package/templates/agentic-owners/agent/lib/owners/constants.ts +22 -0
  198. package/templates/agentic-owners/agent/lib/owners/decision.ts +485 -0
  199. package/templates/agentic-owners/agent/lib/owners/handles.ts +54 -0
  200. package/templates/agentic-owners/agent/lib/owners/match.ts +177 -0
  201. package/templates/agentic-owners/agent/lib/owners/matching.ts +95 -0
  202. package/templates/agentic-owners/agent/lib/owners/parse.ts +589 -0
  203. package/templates/agentic-owners/agent/lib/owners/policyMode.ts +65 -0
  204. package/templates/agentic-owners/agent/lib/owners/prompt.ts +66 -0
  205. package/templates/agentic-owners/agent/lib/owners/prompts/base-review.md +105 -0
  206. package/templates/agentic-owners/agent/lib/owners/types.ts +45 -0
  207. package/templates/agentic-owners/agent/lib/review.ts +777 -0
  208. package/templates/agentic-owners/agent/tools/record_review.ts +69 -0
  209. package/templates/agentic-owners/evals/evals.config.ts +5 -0
  210. package/templates/agentic-owners/evals/owners.eval.ts +116 -0
  211. package/templates/agentic-owners/package.json +20 -0
  212. package/templates/agentic-owners/tsconfig.json +12 -0
  213. package/templates/demo/README.md +33 -0
  214. package/templates/demo/agent/agent.ts +15 -0
  215. package/templates/demo/agent/channels/github.ts +50 -0
  216. package/templates/demo/agent/channels/queue.ts +30 -0
  217. package/templates/demo/agent/instructions.md +8 -0
  218. package/templates/demo/agent/lib/collect.ts +78 -0
  219. package/templates/demo/agent/tools/record_demo.ts +40 -0
  220. package/templates/demo/evals/demo.eval.ts +33 -0
  221. package/templates/demo/evals/evals.config.ts +5 -0
  222. package/templates/demo/package.json +18 -0
  223. package/templates/demo/tsconfig.json +12 -0
  224. package/templates/pr-autofixer/README.md +44 -0
  225. package/templates/pr-autofixer/agent/agent.ts +22 -0
  226. package/templates/pr-autofixer/agent/channels/drive.ts +40 -0
  227. package/templates/pr-autofixer/agent/channels/github.ts +167 -0
  228. package/templates/pr-autofixer/agent/channels/slack.ts +17 -0
  229. package/templates/pr-autofixer/agent/hooks/bind-agent.ts +19 -0
  230. package/templates/pr-autofixer/agent/instructions.md +83 -0
  231. package/templates/pr-autofixer/agent/lib/affinity.ts +33 -0
  232. package/templates/pr-autofixer/agent/lib/drive-schemas.ts +15 -0
  233. package/templates/pr-autofixer/agent/lib/drive.ts +79 -0
  234. package/templates/pr-autofixer/agent/lib/merge-watch.ts +123 -0
  235. package/templates/pr-autofixer/agent/lib/pr-state.ts +54 -0
  236. package/templates/pr-autofixer/agent/lib/repos.ts +19 -0
  237. package/templates/pr-autofixer/agent/lib/start-drive.ts +122 -0
  238. package/templates/pr-autofixer/agent/lib/webhook-buffer.ts +225 -0
  239. package/templates/pr-autofixer/agent/lib/webhook-routing.ts +231 -0
  240. package/templates/pr-autofixer/agent/storage.ts +7 -0
  241. package/templates/pr-autofixer/agent/tools/drive_pr.ts +22 -0
  242. package/templates/pr-autofixer/evals/coordinator.eval.ts +16 -0
  243. package/templates/pr-autofixer/evals/evals.config.ts +5 -0
  244. package/templates/pr-autofixer/init.json +25 -0
  245. package/templates/pr-autofixer/package.json +18 -0
  246. package/templates/pr-autofixer/tsconfig.json +12 -0
  247. package/templates/security-reviewer/README.md +31 -0
  248. package/templates/security-reviewer/agent/agent.ts +15 -0
  249. package/templates/security-reviewer/agent/channels/github.ts +46 -0
  250. package/templates/security-reviewer/agent/instructions.md +22 -0
  251. package/templates/security-reviewer/agent/lib/repos.ts +5 -0
  252. package/templates/security-reviewer/agent/tools/post_findings.ts +72 -0
  253. package/templates/security-reviewer/evals/evals.config.ts +5 -0
  254. package/templates/security-reviewer/evals/review.eval.ts +53 -0
  255. package/templates/security-reviewer/init.json +25 -0
  256. package/templates/security-reviewer/package.json +18 -0
  257. package/templates/security-reviewer/tsconfig.json +12 -0
  258. package/dist/docs/assets/chunks/@localSearchIndexroot.BFpWSo6D.js +0 -1
  259. package/dist/docs/assets/index.md.COeoSkcF.js +0 -5
  260. package/dist/docs/assets/scaffolding-agents.md.mkc3B_ZW.js +0 -1
  261. package/dist/playground/assets/index-tHCjJxv4.css +0 -1
@@ -0,0 +1,28 @@
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
+ export * from "./cursor-account.js";
25
+ export * from "./events.js";
26
+ export * from "./origin-channel.js";
27
+ export * from "./origin-webhook.js";
28
+ export * from "./types.js";
@@ -0,0 +1,68 @@
1
+ import type { AuthContext, ChannelDefinition, ChannelHandlerArgs } from "../../types.js";
2
+ import type { OriginChannelOptions, OriginEventContext, OriginPullRequestEvent, OriginTurnDispatch, OriginWebhookEnvelope } from "./types.js";
3
+ /** `AGENT_SERVE_ORIGIN_APP_ID` fallback for {@link OriginChannelOptions.appId}. */
4
+ export declare function envOriginAppId(): string | undefined;
5
+ export declare function parseOriginWebhookEnvelope(payload: unknown): OriginWebhookEnvelope | null;
6
+ export declare function parseOriginPullRequestEvent(input: {
7
+ envelope: OriginWebhookEnvelope;
8
+ }): {
9
+ ctx: Omit<OriginEventContext, "host" | "artifacts">;
10
+ pullRequest: OriginPullRequestEvent;
11
+ payload: Record<string, unknown>;
12
+ } | null;
13
+ /**
14
+ * Derive the turn's auth from the actor that triggered the delivery — the
15
+ * standard `{ auth: defaultOriginAuth(ctx) }` dispatch from an inbound hook.
16
+ * The subscriber's Cursor identity is not the turn principal (same pattern
17
+ * as {@link defaultGitHubAuth}).
18
+ */
19
+ export declare function defaultOriginAuth(ctx: Omit<OriginEventContext, "host" | "artifacts">): AuthContext;
20
+ export declare function originContinuationKey(ctx: Pick<OriginEventContext, "repository" | "pullRequestNumber">): string;
21
+ export declare function defaultOriginTitle(ctx: Pick<OriginEventContext, "repository" | "pullRequestNumber">): string;
22
+ export declare function defaultOriginPullRequestMessage(ctx: Omit<OriginEventContext, "host" | "artifacts">, pullRequest: OriginPullRequestEvent): string;
23
+ export declare function defaultOriginPullRequestDispatch(ctx: Omit<OriginEventContext, "host" | "artifacts">, pullRequest: OriginPullRequestEvent): OriginTurnDispatch | null;
24
+ /**
25
+ * Core Origin webhook dispatch used by {@link originChannel} routes and by
26
+ * {@link handleAgentServeTrigger} fan-out. Signature verification is the
27
+ * caller's responsibility (HTTP route verifies; internal fan-out skips).
28
+ */
29
+ export declare function dispatchOriginWebhook(input: {
30
+ options: OriginChannelOptions;
31
+ envelope: OriginWebhookEnvelope;
32
+ args: ChannelHandlerArgs;
33
+ }): Promise<Response>;
34
+ /**
35
+ * HTTP entry for a single agent's Origin channel: optional v1ed verify, then
36
+ * app-id bind, then {@link dispatchOriginWebhook}.
37
+ */
38
+ export declare function handleOriginWebhookRequest(input: {
39
+ options: OriginChannelOptions;
40
+ request: Request;
41
+ args: ChannelHandlerArgs;
42
+ /** When true, skip v1ed even though Origin HTTP deliveries are signed. */
43
+ skipSignatureVerification?: boolean;
44
+ }): Promise<Response>;
45
+ export declare function getOriginChannelOptions(definition: object): OriginChannelOptions | undefined;
46
+ export declare function originChannel(options?: OriginChannelOptions): ChannelDefinition;
47
+ /** Minimal mount shape shared by `serve` / trigger fan-out. */
48
+ export interface OriginAgentMountLike {
49
+ slug: string;
50
+ project: {
51
+ channels: Array<{
52
+ id: string;
53
+ definition: {
54
+ meta?: {
55
+ kind?: string;
56
+ originWebhookEvents?: readonly string[];
57
+ };
58
+ };
59
+ }>;
60
+ };
61
+ }
62
+ export interface OriginChannelTarget {
63
+ slug: string;
64
+ channelId: string;
65
+ events: string[];
66
+ }
67
+ export declare function findOriginChannelTargets(mounts: ReadonlyArray<OriginAgentMountLike>): OriginChannelTarget[];
68
+ //# sourceMappingURL=origin-channel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"origin-channel.d.ts","sourceRoot":"","sources":["../../../src/channels/origin/origin-channel.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,567 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { z } from "zod";
11
+ import { allowAll, defineChannel, localDevStrict, loopbackOnly, POST, } from "../../channels.js";
12
+ import { isDevMode } from "../../internal/dev-mode.js";
13
+ import { parseCursorOriginRepoScope, registerOriginCursorAccountRuntime, } from "./cursor-account.js";
14
+ import { deriveOriginWebhookEvents, ORIGIN_CHANNEL_KIND } from "./events.js";
15
+ import { DEFAULT_ORIGIN_API_BASE_URL, verifyOriginWebhook, } from "./origin-webhook.js";
16
+ /**
17
+ * Default dispatch gate when no `onPullRequest` hook is declared: the common
18
+ * review triggers start a turn as the delivery's actor.
19
+ */
20
+ const DEFAULT_PULL_REQUEST_TYPES = new Set([
21
+ "pull_request.created",
22
+ "pull_request.published",
23
+ "pull_request.head_ref.pushed",
24
+ "pull_request.base_ref.updated",
25
+ ]);
26
+ function asRecord(value) {
27
+ return typeof value === "object" && value !== null && !Array.isArray(value)
28
+ ? value
29
+ : undefined;
30
+ }
31
+ function asNonEmptyString(value) {
32
+ return typeof value === "string" && value.trim() !== ""
33
+ ? value.trim()
34
+ : undefined;
35
+ }
36
+ function asPositiveInt(value) {
37
+ if (typeof value === "number" && Number.isInteger(value) && value > 0) {
38
+ return value;
39
+ }
40
+ if (typeof value === "string" && /^[1-9]\d*$/.test(value)) {
41
+ return Number(value);
42
+ }
43
+ return undefined;
44
+ }
45
+ function asBoolean(value) {
46
+ return typeof value === "boolean" ? value : undefined;
47
+ }
48
+ function originActor(value) {
49
+ var _a;
50
+ var _b, _c, _d;
51
+ const record = asRecord(value);
52
+ if (record === undefined)
53
+ return undefined;
54
+ const nestedUser = asRecord(record.user);
55
+ const nestedApp = asRecord(record.app);
56
+ const id = (_d = (_c = (_b = asNonEmptyString(nestedUser === null || nestedUser === void 0 ? void 0 : nestedUser.id)) !== null && _b !== void 0 ? _b : asNonEmptyString(nestedApp === null || nestedApp === void 0 ? void 0 : nestedApp.id)) !== null && _c !== void 0 ? _c : asNonEmptyString((_a = asRecord(record.serviceAccount)) === null || _a === void 0 ? void 0 : _a.id)) !== null && _d !== void 0 ? _d : asNonEmptyString(record.id);
57
+ if (id === undefined)
58
+ return undefined;
59
+ const kind = asNonEmptyString(record.kind);
60
+ return kind === undefined ? { id } : { id, kind };
61
+ }
62
+ function originHeaders(request) {
63
+ var _a, _b, _c;
64
+ return {
65
+ "webhook-id": (_a = request.headers.get("webhook-id")) !== null && _a !== void 0 ? _a : undefined,
66
+ "webhook-timestamp": (_b = request.headers.get("webhook-timestamp")) !== null && _b !== void 0 ? _b : undefined,
67
+ "webhook-signature": (_c = request.headers.get("webhook-signature")) !== null && _c !== void 0 ? _c : undefined,
68
+ };
69
+ }
70
+ function skipOriginVerify() {
71
+ var _a;
72
+ return ((_a = process.env.AGENT_SERVE_ORIGIN_SKIP_VERIFY) === null || _a === void 0 ? void 0 : _a.trim()) === "1";
73
+ }
74
+ /**
75
+ * Direct Origin HTTP deliveries verify v1ed. `--dev` and
76
+ * `AGENT_SERVE_ORIGIN_SKIP_VERIFY=1` skip that so local fixtures work, matching
77
+ * GitHub's unsigned loopback posture when no webhook secret is set.
78
+ */
79
+ function shouldSkipOriginVerify() {
80
+ return skipOriginVerify() || isDevMode();
81
+ }
82
+ function asIdList(value) {
83
+ if (value === undefined)
84
+ return [];
85
+ const items = typeof value === "string" ? [value] : [...value];
86
+ return [...new Set(items.map((id) => id.trim()).filter(Boolean))];
87
+ }
88
+ /** `AGENT_SERVE_ORIGIN_APP_ID` fallback for {@link OriginChannelOptions.appId}. */
89
+ export function envOriginAppId() {
90
+ var _a;
91
+ const value = (_a = process.env.AGENT_SERVE_ORIGIN_APP_ID) === null || _a === void 0 ? void 0 : _a.trim();
92
+ return value === undefined || value === "" ? undefined : value;
93
+ }
94
+ function configuredOriginAppIds(options) {
95
+ const fromOptions = asIdList(options.appId);
96
+ if (fromOptions.length > 0)
97
+ return fromOptions;
98
+ const fromEnv = envOriginAppId();
99
+ return fromEnv === undefined ? [] : [fromEnv];
100
+ }
101
+ function configuredOriginInstallationIds(options) {
102
+ return asIdList(options.installationId);
103
+ }
104
+ /**
105
+ * Repo allowlist for HTTP and trigger fan-out. `undefined` means no extra
106
+ * repo gate (the bound Origin app's installations still bound what Origin
107
+ * will send).
108
+ */
109
+ function configuredOriginRepoAllowlist(options) {
110
+ const repos = [];
111
+ if (options.repos !== undefined) {
112
+ repos.push(...parseCursorOriginRepoScope(options.repos).repos);
113
+ }
114
+ if (typeof options.cursorAccount === "object") {
115
+ repos.push(...parseCursorOriginRepoScope(options.cursorAccount.repos).repos);
116
+ }
117
+ return repos.length === 0 ? undefined : new Set(repos);
118
+ }
119
+ /**
120
+ * v1ed proves Origin signed the body. Channel auth is the signed
121
+ * `envelope.appId` matching this channel's configured Origin app (the GitHub
122
+ * webhook-secret analogue). Cursor-internal documents the same gap.
123
+ */
124
+ function originHttpBindingError(options, envelope) {
125
+ var _a, _b;
126
+ const allowedApps = configuredOriginAppIds(options);
127
+ if (allowedApps.length === 0) {
128
+ return "unbound_origin_app";
129
+ }
130
+ const deliveredAppId = (_a = envelope.appId) === null || _a === void 0 ? void 0 : _a.trim();
131
+ if (deliveredAppId === undefined || deliveredAppId === "") {
132
+ return "invalid_app";
133
+ }
134
+ if (!allowedApps.includes(deliveredAppId)) {
135
+ return "invalid_app";
136
+ }
137
+ const allowedInstalls = configuredOriginInstallationIds(options);
138
+ if (allowedInstalls.length === 0) {
139
+ return undefined;
140
+ }
141
+ const deliveredInstallationId = (_b = envelope.installationId) === null || _b === void 0 ? void 0 : _b.trim();
142
+ if (deliveredInstallationId === undefined ||
143
+ deliveredInstallationId === "" ||
144
+ !allowedInstalls.includes(deliveredInstallationId)) {
145
+ return "invalid_installation";
146
+ }
147
+ return undefined;
148
+ }
149
+ function resolveApiBaseUrl(options) {
150
+ const authored = typeof options.apiBaseUrl === "function"
151
+ ? options.apiBaseUrl()
152
+ : options.apiBaseUrl;
153
+ const trimmed = authored === null || authored === void 0 ? void 0 : authored.trim();
154
+ return trimmed === undefined || trimmed === ""
155
+ ? DEFAULT_ORIGIN_API_BASE_URL
156
+ : trimmed;
157
+ }
158
+ const originEnvelopeSchema = z.object({
159
+ deliveryId: z.string().optional(),
160
+ appId: z.string().optional(),
161
+ installationId: z.string().optional(),
162
+ sender: z
163
+ .object({
164
+ id: z.string().min(1),
165
+ kind: z.string().optional(),
166
+ })
167
+ .optional(),
168
+ event: z.object({
169
+ id: z.string().optional(),
170
+ type: z.string().min(1),
171
+ eventTime: z.string().optional(),
172
+ payload: z.unknown().optional(),
173
+ }),
174
+ });
175
+ export function parseOriginWebhookEnvelope(payload) {
176
+ const parsed = originEnvelopeSchema.safeParse(payload);
177
+ return parsed.success ? parsed.data : null;
178
+ }
179
+ function originRepoFromPayload(payload) {
180
+ var _a, _b;
181
+ var _c;
182
+ const repository = (_c = asRecord(payload.repository)) !== null && _c !== void 0 ? _c : asRecord((_a = asRecord(payload.pullRequest)) === null || _a === void 0 ? void 0 : _a.repository);
183
+ const owner = asNonEmptyString((_b = asRecord(repository === null || repository === void 0 ? void 0 : repository.owner)) === null || _b === void 0 ? void 0 : _b.slug);
184
+ const name = asNonEmptyString(repository === null || repository === void 0 ? void 0 : repository.name);
185
+ if (owner === undefined || name === undefined)
186
+ return undefined;
187
+ return { owner, name, fullName: `${owner}/${name}` };
188
+ }
189
+ function originPrUrl(repository, number, explicit) {
190
+ return (explicit !== null && explicit !== void 0 ? explicit : `https://cursor.com/codebase/${repository.owner}/${repository.name}/pull/${number}`);
191
+ }
192
+ function originSender(envelope, payload) {
193
+ var _a, _b, _c;
194
+ var _d, _e, _f, _g, _h;
195
+ return ((_h = (_g = (_f = (_e = (_d = envelope.sender) !== null && _d !== void 0 ? _d : originActor(payload.actor)) !== null && _e !== void 0 ? _e : originActor(payload.pusher)) !== null && _f !== void 0 ? _f : originActor((_a = asRecord(payload.review)) === null || _a === void 0 ? void 0 : _a.author)) !== null && _g !== void 0 ? _g : originActor((_b = asRecord(payload.comment)) === null || _b === void 0 ? void 0 : _b.author)) !== null && _h !== void 0 ? _h : originActor((_c = asRecord(payload.pullRequest)) === null || _c === void 0 ? void 0 : _c.author));
196
+ }
197
+ export function parseOriginPullRequestEvent(input) {
198
+ var _a, _b, _c, _d;
199
+ const payload = (_a = asRecord(input.envelope.event.payload)) !== null && _a !== void 0 ? _a : {};
200
+ const repository = originRepoFromPayload(payload);
201
+ const pullRequest = asRecord(payload.pullRequest);
202
+ const number = asPositiveInt(pullRequest === null || pullRequest === void 0 ? void 0 : pullRequest.number);
203
+ if (repository === undefined || number === undefined) {
204
+ return null;
205
+ }
206
+ const eventType = input.envelope.event.type;
207
+ const url = originPrUrl(repository, number, asNonEmptyString(pullRequest === null || pullRequest === void 0 ? void 0 : pullRequest.url));
208
+ const head = asRecord(pullRequest === null || pullRequest === void 0 ? void 0 : pullRequest.head);
209
+ const base = asRecord(pullRequest === null || pullRequest === void 0 ? void 0 : pullRequest.base);
210
+ const version = asRecord(pullRequest === null || pullRequest === void 0 ? void 0 : pullRequest.version);
211
+ const author = originActor(pullRequest === null || pullRequest === void 0 ? void 0 : pullRequest.author);
212
+ return {
213
+ payload,
214
+ ctx: {
215
+ deliveryId: input.envelope.deliveryId,
216
+ eventType,
217
+ repository,
218
+ pullRequestNumber: number,
219
+ pullRequestUrl: url,
220
+ sender: originSender(input.envelope, payload),
221
+ },
222
+ pullRequest: {
223
+ type: eventType,
224
+ number,
225
+ url,
226
+ title: asNonEmptyString(pullRequest === null || pullRequest === void 0 ? void 0 : pullRequest.title),
227
+ body: (pullRequest === null || pullRequest === void 0 ? void 0 : pullRequest.body) === null
228
+ ? null
229
+ : ((_b = asNonEmptyString(pullRequest === null || pullRequest === void 0 ? void 0 : pullRequest.body)) !== null && _b !== void 0 ? _b : (typeof (pullRequest === null || pullRequest === void 0 ? void 0 : pullRequest.body) === "string"
230
+ ? pullRequest.body
231
+ : undefined)),
232
+ draft: asBoolean(pullRequest === null || pullRequest === void 0 ? void 0 : pullRequest.draft),
233
+ merged: eventType === "pull_request.merged" || asBoolean(pullRequest === null || pullRequest === void 0 ? void 0 : pullRequest.merged),
234
+ authorId: author === null || author === void 0 ? void 0 : author.id,
235
+ headRef: asNonEmptyString(head === null || head === void 0 ? void 0 : head.ref),
236
+ headSha: (_c = asNonEmptyString(head === null || head === void 0 ? void 0 : head.sha)) !== null && _c !== void 0 ? _c : asNonEmptyString(version === null || version === void 0 ? void 0 : version.headSha),
237
+ baseRef: asNonEmptyString(base === null || base === void 0 ? void 0 : base.ref),
238
+ baseSha: (_d = asNonEmptyString(base === null || base === void 0 ? void 0 : base.sha)) !== null && _d !== void 0 ? _d : asNonEmptyString(version === null || version === void 0 ? void 0 : version.baseSha),
239
+ },
240
+ };
241
+ }
242
+ /**
243
+ * Derive the turn's auth from the actor that triggered the delivery — the
244
+ * standard `{ auth: defaultOriginAuth(ctx) }` dispatch from an inbound hook.
245
+ * The subscriber's Cursor identity is not the turn principal (same pattern
246
+ * as {@link defaultGitHubAuth}).
247
+ */
248
+ export function defaultOriginAuth(ctx) {
249
+ var _a, _b, _c;
250
+ const senderId = (_a = ctx.sender) === null || _a === void 0 ? void 0 : _a.id;
251
+ return {
252
+ authenticator: "origin-webhook",
253
+ principalId: senderId !== null && senderId !== void 0 ? senderId : "origin",
254
+ principalType: ((_b = ctx.sender) === null || _b === void 0 ? void 0 : _b.kind) === "app" ? "service" : "user",
255
+ attributes: Object.assign(Object.assign(Object.assign(Object.assign({ conversation_kind: "pull_request", repository: ctx.repository.fullName }, (ctx.deliveryId === undefined ? {} : { delivery_id: ctx.deliveryId })), (senderId === undefined ? {} : { subject: senderId })), (((_c = ctx.sender) === null || _c === void 0 ? void 0 : _c.kind) === undefined ? {} : { user_type: ctx.sender.kind })), { issuer: `origin:${ctx.repository.owner}` }),
256
+ };
257
+ }
258
+ export function originContinuationKey(ctx) {
259
+ return `origin-pr:${ctx.repository.fullName}#${ctx.pullRequestNumber}`;
260
+ }
261
+ export function defaultOriginTitle(ctx) {
262
+ return `Origin ${ctx.repository.fullName}#${ctx.pullRequestNumber}`;
263
+ }
264
+ export function defaultOriginPullRequestMessage(ctx, pullRequest) {
265
+ const head = pullRequest.headRef !== undefined && pullRequest.headSha !== undefined
266
+ ? `Head: ${pullRequest.headRef} (${pullRequest.headSha})`
267
+ : undefined;
268
+ return [
269
+ `Origin pull request trigger: ${ctx.repository.fullName}#${pullRequest.number}`,
270
+ `Event: ${pullRequest.type}`,
271
+ `URL: ${pullRequest.url}`,
272
+ ...(pullRequest.title === undefined ? [] : [`Title: ${pullRequest.title}`]),
273
+ ...(head === undefined ? [] : [head]),
274
+ "Handle this pull request event.",
275
+ ].join("\n");
276
+ }
277
+ export function defaultOriginPullRequestDispatch(ctx, pullRequest) {
278
+ if (!DEFAULT_PULL_REQUEST_TYPES.has(pullRequest.type)) {
279
+ return null;
280
+ }
281
+ return { auth: defaultOriginAuth(ctx) };
282
+ }
283
+ function isTaskDispatch(dispatch) {
284
+ return "task" in dispatch;
285
+ }
286
+ function enrichEventContext(input) {
287
+ return Object.assign(Object.assign({}, input.ctx), { host: input.args.host, artifacts: input.args.artifacts });
288
+ }
289
+ function skipped(reason, extra = {}) {
290
+ return Response.json(Object.assign({ ok: true, skipped: true, reason }, extra));
291
+ }
292
+ function acknowledgeTask(args, dispatch, extra) {
293
+ args.waitUntil(new Promise((resolve, reject) => {
294
+ setImmediate(() => {
295
+ Promise.resolve()
296
+ .then(dispatch.task)
297
+ .then(() => resolve(), reject);
298
+ });
299
+ }));
300
+ return Response.json(Object.assign({ ok: true, dispatched: true, mode: "task" }, extra), { status: 202 });
301
+ }
302
+ function startTurn(input) {
303
+ return __awaiter(this, void 0, void 0, function* () {
304
+ var _a;
305
+ const session = yield input.args.send(input.message, Object.assign({ auth: input.dispatch.auth, continuationToken: originContinuationKey(input.ctx), title: (_a = input.dispatch.title) !== null && _a !== void 0 ? _a : defaultOriginTitle(input.ctx) }, (input.cloud === undefined ? {} : { cloud: input.cloud })));
306
+ return Response.json({
307
+ ok: true,
308
+ sessionId: session.id,
309
+ isNew: session.isNew,
310
+ continuationToken: session.continuationToken,
311
+ });
312
+ });
313
+ }
314
+ function resolveCloudOptions(cloud, ctx, pullRequest) {
315
+ return __awaiter(this, void 0, void 0, function* () {
316
+ if (cloud === undefined || cloud === false) {
317
+ return undefined;
318
+ }
319
+ if (cloud === true) {
320
+ return {
321
+ repos: [
322
+ {
323
+ url: `https://cursor.com/codebase/${ctx.repository.fullName}`,
324
+ prUrl: pullRequest.url,
325
+ startingRef: pullRequest.headSha,
326
+ },
327
+ ],
328
+ };
329
+ }
330
+ if (typeof cloud === "function") {
331
+ return yield cloud(ctx, pullRequest);
332
+ }
333
+ return cloud;
334
+ });
335
+ }
336
+ function applyDispatch(input) {
337
+ return __awaiter(this, void 0, void 0, function* () {
338
+ var _a, _b;
339
+ if (input.dispatch === null) {
340
+ return skipped("not_dispatched", input.extra);
341
+ }
342
+ if (isTaskDispatch(input.dispatch)) {
343
+ return acknowledgeTask(input.args, input.dispatch, input.extra);
344
+ }
345
+ const message = [
346
+ (_a = input.dispatch.message) !== null && _a !== void 0 ? _a : input.message,
347
+ ...((_b = input.dispatch.context) !== null && _b !== void 0 ? _b : []),
348
+ ].join("\n");
349
+ return startTurn({
350
+ args: input.args,
351
+ ctx: input.ctx,
352
+ message,
353
+ dispatch: input.dispatch,
354
+ cloud: input.cloud,
355
+ });
356
+ });
357
+ }
358
+ /**
359
+ * Core Origin webhook dispatch used by {@link originChannel} routes and by
360
+ * {@link handleAgentServeTrigger} fan-out. Signature verification is the
361
+ * caller's responsibility (HTTP route verifies; internal fan-out skips).
362
+ */
363
+ export function dispatchOriginWebhook(input) {
364
+ return __awaiter(this, void 0, void 0, function* () {
365
+ var _a;
366
+ const eventType = input.envelope.event.type;
367
+ const parsed = parseOriginPullRequestEvent({ envelope: input.envelope });
368
+ if (parsed === null) {
369
+ return Response.json({ ok: false, error: "invalid_origin_payload" }, { status: 400 });
370
+ }
371
+ const ctx = enrichEventContext({ ctx: parsed.ctx, args: input.args });
372
+ const { pullRequest, payload } = parsed;
373
+ const repoAllowlist = configuredOriginRepoAllowlist(input.options);
374
+ if (repoAllowlist !== undefined &&
375
+ !repoAllowlist.has(ctx.repository.fullName.toLowerCase())) {
376
+ return skipped("repo_not_allowed", { repo: ctx.repository.fullName });
377
+ }
378
+ if (eventType.startsWith("pull_request.comment.")) {
379
+ if (input.options.onComment === undefined) {
380
+ return skipped("no_handler", { event: eventType });
381
+ }
382
+ const commentRecord = asRecord(payload.comment);
383
+ const commentId = asNonEmptyString(commentRecord === null || commentRecord === void 0 ? void 0 : commentRecord.id);
384
+ const commentBody = typeof (commentRecord === null || commentRecord === void 0 ? void 0 : commentRecord.body) === "string" ? commentRecord.body : undefined;
385
+ if (commentId === undefined || commentBody === undefined) {
386
+ return Response.json({ ok: false, error: "invalid_origin_comment_payload" }, { status: 400 });
387
+ }
388
+ const comment = {
389
+ id: commentId,
390
+ body: commentBody,
391
+ author: originActor(commentRecord === null || commentRecord === void 0 ? void 0 : commentRecord.author),
392
+ };
393
+ const dispatch = yield input.options.onComment(ctx, comment);
394
+ return applyDispatch({
395
+ args: input.args,
396
+ ctx,
397
+ dispatch,
398
+ extra: { event: eventType },
399
+ message: `Origin comment on ${ctx.repository.fullName}#${ctx.pullRequestNumber}`,
400
+ });
401
+ }
402
+ if (eventType.startsWith("pull_request.review.")) {
403
+ if (input.options.onReview === undefined) {
404
+ return skipped("no_handler", { event: eventType });
405
+ }
406
+ const reviewRecord = (_a = asRecord(payload.review)) !== null && _a !== void 0 ? _a : {};
407
+ const review = {
408
+ id: asNonEmptyString(reviewRecord.id),
409
+ verdict: asNonEmptyString(reviewRecord.verdict),
410
+ author: originActor(reviewRecord.author),
411
+ };
412
+ const dispatch = yield input.options.onReview(ctx, review);
413
+ return applyDispatch({
414
+ args: input.args,
415
+ ctx,
416
+ dispatch,
417
+ extra: { event: eventType },
418
+ message: `Origin review on ${ctx.repository.fullName}#${ctx.pullRequestNumber}`,
419
+ });
420
+ }
421
+ if (eventType.startsWith("pull_request.")) {
422
+ const dispatch = input.options.onPullRequest === undefined
423
+ ? defaultOriginPullRequestDispatch(ctx, pullRequest)
424
+ : yield input.options.onPullRequest(ctx, pullRequest);
425
+ const cloud = yield resolveCloudOptions(input.options.cloud, ctx, pullRequest);
426
+ return applyDispatch({
427
+ args: input.args,
428
+ ctx,
429
+ dispatch,
430
+ extra: { event: eventType },
431
+ message: defaultOriginPullRequestMessage(ctx, pullRequest),
432
+ cloud,
433
+ });
434
+ }
435
+ if (input.options.onEvent !== undefined) {
436
+ const dispatch = yield input.options.onEvent(ctx, {
437
+ eventType,
438
+ payload,
439
+ });
440
+ return applyDispatch({
441
+ args: input.args,
442
+ ctx,
443
+ dispatch,
444
+ extra: { event: eventType },
445
+ message: `Origin ${eventType} event`,
446
+ });
447
+ }
448
+ return skipped("unsupported_event", { event: eventType });
449
+ });
450
+ }
451
+ /**
452
+ * HTTP entry for a single agent's Origin channel: optional v1ed verify, then
453
+ * app-id bind, then {@link dispatchOriginWebhook}.
454
+ */
455
+ export function handleOriginWebhookRequest(input) {
456
+ return __awaiter(this, void 0, void 0, function* () {
457
+ const bodyText = yield input.request.text();
458
+ const requireHttpBinding = input.skipSignatureVerification !== true &&
459
+ shouldSkipOriginVerify() !== true;
460
+ if (requireHttpBinding) {
461
+ try {
462
+ yield verifyOriginWebhook(bodyText, originHeaders(input.request), {
463
+ apiBaseUrl: resolveApiBaseUrl(input.options),
464
+ });
465
+ }
466
+ catch (_a) {
467
+ return Response.json({ ok: false, error: "invalid_signature" }, { status: 401 });
468
+ }
469
+ }
470
+ let payload;
471
+ try {
472
+ payload = JSON.parse(bodyText);
473
+ }
474
+ catch (_b) {
475
+ return Response.json({ ok: false, error: "invalid_json" }, { status: 400 });
476
+ }
477
+ const envelope = parseOriginWebhookEnvelope(payload);
478
+ if (envelope === null) {
479
+ return Response.json({ ok: false, error: "invalid_origin_payload" }, { status: 400 });
480
+ }
481
+ if (requireHttpBinding) {
482
+ const bindingError = originHttpBindingError(input.options, envelope);
483
+ if (bindingError !== undefined) {
484
+ return Response.json({ ok: false, error: bindingError }, { status: 401 });
485
+ }
486
+ }
487
+ return dispatchOriginWebhook({
488
+ options: input.options,
489
+ envelope,
490
+ args: input.args,
491
+ });
492
+ });
493
+ }
494
+ const originChannelOptionsByDefinition = new WeakMap();
495
+ export function getOriginChannelOptions(definition) {
496
+ return originChannelOptionsByDefinition.get(definition);
497
+ }
498
+ export function originChannel(options = {}) {
499
+ var _a, _b;
500
+ const usesCursorAccount = options.cursorAccount === true || typeof options.cursorAccount === "object";
501
+ const cursorScope = typeof options.cursorAccount === "object"
502
+ ? parseCursorOriginRepoScope(options.cursorAccount.repos)
503
+ : undefined;
504
+ if (options.repos !== undefined) {
505
+ parseCursorOriginRepoScope(options.repos);
506
+ }
507
+ const routePath = (_a = options.path) !== null && _a !== void 0 ? _a : "/";
508
+ // v1ed + configured app id is the request auth (allowAll), matching GitHub
509
+ // HMAC + webhookSecret. Without an app id, prod stays loopback-strict so a
510
+ // reachable URL cannot be driven by any Origin-signed delivery. `--dev`
511
+ // / skip-verify admits loopback only.
512
+ const auth = (_b = options.auth) !== null && _b !== void 0 ? _b : [
513
+ (request, info) => (shouldSkipOriginVerify()
514
+ ? loopbackOnly()
515
+ : configuredOriginAppIds(options).length > 0
516
+ ? allowAll()
517
+ : localDevStrict())(request, info),
518
+ ];
519
+ const definition = defineChannel({
520
+ auth,
521
+ onStart: options.onStart,
522
+ onStop: options.onStop,
523
+ meta: {
524
+ kind: ORIGIN_CHANNEL_KIND,
525
+ originWebhookEvents: deriveOriginWebhookEvents(options),
526
+ },
527
+ routes: [
528
+ POST(routePath, {
529
+ bodySchema: z.unknown(),
530
+ description: "Origin webhook ingress",
531
+ handler: (request, args) => __awaiter(this, void 0, void 0, function* () {
532
+ return handleOriginWebhookRequest({
533
+ options,
534
+ request,
535
+ args,
536
+ });
537
+ }),
538
+ }),
539
+ ],
540
+ });
541
+ originChannelOptionsByDefinition.set(definition, options);
542
+ if (usesCursorAccount) {
543
+ registerOriginCursorAccountRuntime(definition, {
544
+ options,
545
+ scope: cursorScope,
546
+ });
547
+ }
548
+ return definition;
549
+ }
550
+ export function findOriginChannelTargets(mounts) {
551
+ var _a;
552
+ const targets = [];
553
+ for (const { slug, project } of mounts) {
554
+ for (const channel of project.channels) {
555
+ const meta = channel.definition.meta;
556
+ if ((meta === null || meta === void 0 ? void 0 : meta.kind) !== ORIGIN_CHANNEL_KIND) {
557
+ continue;
558
+ }
559
+ targets.push({
560
+ slug,
561
+ channelId: channel.id,
562
+ events: [...((_a = meta.originWebhookEvents) !== null && _a !== void 0 ? _a : [])],
563
+ });
564
+ }
565
+ }
566
+ return targets;
567
+ }