@cursor/july 0.1.94 → 0.1.95

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 (209) hide show
  1. package/dist/channels/github/github-channel.d.ts.map +1 -1
  2. package/dist/channels/github/github-channel.js +14 -2
  3. package/dist/channels/github/types.d.ts +18 -3
  4. package/dist/channels/github/types.d.ts.map +1 -1
  5. package/dist/channels/origin/origin-channel.d.ts.map +1 -1
  6. package/dist/channels/origin/origin-channel.js +11 -3
  7. package/dist/channels/origin/origin-webhook.d.ts +11 -1
  8. package/dist/channels/origin/origin-webhook.d.ts.map +1 -1
  9. package/dist/channels/origin/origin-webhook.js +23 -3
  10. package/dist/channels/origin/types.d.ts +8 -0
  11. package/dist/channels/origin/types.d.ts.map +1 -1
  12. package/dist/channels/slack/pr-ref.d.ts +7 -1
  13. package/dist/channels/slack/pr-ref.d.ts.map +1 -1
  14. package/dist/channels/slack/pr-ref.js +42 -23
  15. package/dist/docs/404.html +2 -2
  16. package/dist/docs/ab.html +4 -4
  17. package/dist/docs/assets/{app.CFDEas4I.js → app.BBj0klBO.js} +1 -1
  18. package/dist/docs/assets/chunks/@localSearchIndexroot.oqPawjiD.js +1 -0
  19. package/dist/docs/assets/chunks/{VPLocalSearchBox.B1IIYpYS.js → VPLocalSearchBox.CUEXpL78.js} +1 -1
  20. package/dist/docs/assets/chunks/{theme.Ct4NSiLm.js → theme.DabmQnia.js} +2 -2
  21. package/dist/docs/assets/index.md.BoHaMdeZ.js +5 -0
  22. package/dist/docs/assets/{index.md.DRakGHFe.lean.js → index.md.BoHaMdeZ.lean.js} +1 -1
  23. package/dist/docs/assets/{reference_cli.md.Cw6_ICYG.js → reference_cli.md.BsMOxDvh.js} +3 -2
  24. package/dist/docs/assets/{reference_cli.md.Cw6_ICYG.lean.js → reference_cli.md.BsMOxDvh.lean.js} +1 -1
  25. package/dist/docs/assets/{reference_skills.md.8son6Hjm.js → reference_skills.md.BFW9retM.js} +3 -3
  26. package/dist/docs/assets/{templates_agentic-owners.md.DqtPdm6f.js → templates_agentic-owners.md.BZSH4N9z.js} +1 -1
  27. package/dist/docs/assets/{templates_demo.md.DhFcWN6j.js → templates_demo.md.BeQX9V3H.js} +1 -1
  28. package/dist/docs/assets/{templates_pr-autofixer.md.DU7dQpor.js → templates_pr-autofixer.md.x5zl6-GT.js} +2 -2
  29. package/dist/docs/assets/{templates_pr-autofixer.md.DU7dQpor.lean.js → templates_pr-autofixer.md.x5zl6-GT.lean.js} +1 -1
  30. package/dist/docs/assets/templates_security-help.md.C3Ny_Qr2.js +4 -0
  31. package/dist/docs/assets/templates_security-help.md.C3Ny_Qr2.lean.js +1 -0
  32. package/dist/docs/assets/{templates_security-reviewer.md.CTa7u_l1.js → templates_security-reviewer.md.lshxbCLK.js} +2 -2
  33. package/dist/docs/assets/{templates_security-reviewer.md.CTa7u_l1.lean.js → templates_security-reviewer.md.lshxbCLK.lean.js} +1 -1
  34. package/dist/docs/assets/{templates_triage.md.CVlpctKS.js → templates_triage.md.Co4UNzkZ.js} +3 -3
  35. package/dist/docs/assets/{templates_triage.md.CVlpctKS.lean.js → templates_triage.md.Co4UNzkZ.lean.js} +1 -1
  36. package/dist/docs/building-with-agents.html +4 -4
  37. package/dist/docs/concepts.html +4 -4
  38. package/dist/docs/deployment.html +4 -4
  39. package/dist/docs/evals.html +4 -4
  40. package/dist/docs/guides/agent-to-agent.html +4 -4
  41. package/dist/docs/guides/cloud-runtime.html +4 -4
  42. package/dist/docs/guides/convert-automation.html +4 -4
  43. package/dist/docs/guides/github.html +4 -4
  44. package/dist/docs/guides/human-in-the-loop.html +4 -4
  45. package/dist/docs/guides/mcp-oauth.html +4 -4
  46. package/dist/docs/guides/opentelemetry.html +4 -4
  47. package/dist/docs/guides/slack.html +4 -4
  48. package/dist/docs/guides/webhooks.html +4 -4
  49. package/dist/docs/hashmap.json +1 -1
  50. package/dist/docs/hillclimbing.html +4 -4
  51. package/dist/docs/index.html +6 -6
  52. package/dist/docs/index.md +3 -1
  53. package/dist/docs/llms-full.txt +90 -26
  54. package/dist/docs/llms.txt +1 -0
  55. package/dist/docs/quickstart.html +4 -4
  56. package/dist/docs/reference/agent-config.html +4 -4
  57. package/dist/docs/reference/artifacts.html +4 -4
  58. package/dist/docs/reference/channels.html +4 -4
  59. package/dist/docs/reference/cli.html +7 -6
  60. package/dist/docs/reference/cli.md +3 -1
  61. package/dist/docs/reference/connections.html +4 -4
  62. package/dist/docs/reference/hooks.html +4 -4
  63. package/dist/docs/reference/http-api.html +4 -4
  64. package/dist/docs/reference/instructions.html +4 -4
  65. package/dist/docs/reference/playground.html +4 -4
  66. package/dist/docs/reference/project-layout.html +4 -4
  67. package/dist/docs/reference/prompt.html +4 -4
  68. package/dist/docs/reference/schedules.html +4 -4
  69. package/dist/docs/reference/sessions.html +4 -4
  70. package/dist/docs/reference/skills.html +7 -7
  71. package/dist/docs/reference/subagents.html +4 -4
  72. package/dist/docs/reference/tools.html +4 -4
  73. package/dist/docs/scaffolding-agents.html +4 -4
  74. package/dist/docs/storage.html +4 -4
  75. package/dist/docs/templates/agentic-owners.html +7 -7
  76. package/dist/docs/templates/agentic-owners.md +1 -1
  77. package/dist/docs/templates/demo.html +6 -6
  78. package/dist/docs/templates/demo.md +3 -2
  79. package/dist/docs/templates/pr-autofixer.html +6 -6
  80. package/dist/docs/templates/pr-autofixer.md +7 -13
  81. package/dist/docs/templates/security-help.html +30 -0
  82. package/dist/docs/templates/security-help.md +65 -0
  83. package/dist/docs/templates/security-reviewer.html +6 -6
  84. package/dist/docs/templates/security-reviewer.md +1 -2
  85. package/dist/docs/templates/triage.html +7 -7
  86. package/dist/docs/templates/triage.md +2 -6
  87. package/dist/docs/troubleshooting.html +4 -4
  88. package/dist/files-backends/cursor-hosted.d.ts +6 -2
  89. package/dist/files-backends/cursor-hosted.d.ts.map +1 -1
  90. package/dist/files-backends/cursor-hosted.js +2 -2
  91. package/dist/files.d.ts +2 -0
  92. package/dist/files.d.ts.map +1 -1
  93. package/dist/files.js +5 -0
  94. package/dist/internal/cli-deploy.d.ts.map +1 -1
  95. package/dist/internal/cli-deploy.js +135 -6
  96. package/dist/internal/conversation-mirror.d.ts +82 -0
  97. package/dist/internal/conversation-mirror.d.ts.map +1 -0
  98. package/dist/internal/conversation-mirror.js +251 -0
  99. package/dist/internal/deferred-channel-session.d.ts +20 -0
  100. package/dist/internal/deferred-channel-session.d.ts.map +1 -0
  101. package/dist/internal/deferred-channel-session.js +62 -0
  102. package/dist/internal/deploy-client.d.ts +13 -1
  103. package/dist/internal/deploy-client.d.ts.map +1 -1
  104. package/dist/internal/deploy-client.js +11 -1
  105. package/dist/internal/deploy-manifest.d.ts.map +1 -1
  106. package/dist/internal/deploy-manifest.js +11 -5
  107. package/dist/internal/discovery.d.ts.map +1 -1
  108. package/dist/internal/discovery.js +22 -2
  109. package/dist/internal/framework-storage-selection.d.ts +32 -16
  110. package/dist/internal/framework-storage-selection.d.ts.map +1 -1
  111. package/dist/internal/framework-storage-selection.js +51 -17
  112. package/dist/internal/hosted-admission-context.d.ts +20 -0
  113. package/dist/internal/hosted-admission-context.d.ts.map +1 -0
  114. package/dist/internal/hosted-admission-context.js +31 -0
  115. package/dist/internal/hosted-delivery-protocol.d.ts +5 -0
  116. package/dist/internal/hosted-delivery-protocol.d.ts.map +1 -1
  117. package/dist/internal/hosted-delivery-protocol.js +33 -1
  118. package/dist/internal/hosted-delivery.d.ts +4 -2
  119. package/dist/internal/hosted-delivery.d.ts.map +1 -1
  120. package/dist/internal/hosted-delivery.js +75 -35
  121. package/dist/internal/hosted-managed-automation.d.ts +30 -0
  122. package/dist/internal/hosted-managed-automation.d.ts.map +1 -0
  123. package/dist/internal/hosted-managed-automation.js +58 -0
  124. package/dist/internal/review-comments.d.ts.map +1 -1
  125. package/dist/internal/review-comments.js +10 -98
  126. package/dist/internal/scm/pr-url.d.ts +14 -0
  127. package/dist/internal/scm/pr-url.d.ts.map +1 -0
  128. package/dist/internal/scm/pr-url.js +65 -0
  129. package/dist/internal/sdk-runner.d.ts +14 -0
  130. package/dist/internal/sdk-runner.d.ts.map +1 -1
  131. package/dist/internal/sdk-runner.js +41 -2
  132. package/dist/internal/server.d.ts.map +1 -1
  133. package/dist/internal/server.js +10 -2
  134. package/dist/internal/session-engine.d.ts.map +1 -1
  135. package/dist/internal/session-engine.js +9 -0
  136. package/dist/playground/assets/index-CF7hUDnQ.css +1 -0
  137. package/dist/playground/assets/{index-B3JCyigB.js → index-CZA1uEWA.js} +48 -48
  138. package/dist/playground/index.html +2 -2
  139. package/dist/storage-backends/cursor-hosted.d.ts +7 -2
  140. package/dist/storage-backends/cursor-hosted.d.ts.map +1 -1
  141. package/dist/storage-backends/cursor-hosted.js +2 -2
  142. package/docs/README.md +3 -1
  143. package/docs/reference/cli.md +3 -1
  144. package/docs/templates/agentic-owners.md +1 -1
  145. package/docs/templates/demo.md +3 -2
  146. package/docs/templates/pr-autofixer.md +7 -13
  147. package/docs/templates/security-help.md +70 -0
  148. package/docs/templates/security-reviewer.md +1 -2
  149. package/docs/templates/triage.md +2 -6
  150. package/package.json +1 -1
  151. package/src/channels/github/github-channel.ts +23 -8
  152. package/src/channels/github/types.ts +19 -2
  153. package/src/channels/origin/origin-channel.ts +13 -1
  154. package/src/channels/origin/origin-webhook.ts +27 -3
  155. package/src/channels/origin/types.ts +8 -0
  156. package/src/channels/slack/pr-ref.ts +56 -25
  157. package/src/files-backends/cursor-hosted.ts +9 -3
  158. package/src/files.ts +11 -0
  159. package/src/internal/cli-deploy.ts +171 -7
  160. package/src/internal/conversation-mirror.ts +330 -0
  161. package/src/internal/deferred-channel-session.ts +61 -0
  162. package/src/internal/deploy-client.ts +24 -1
  163. package/src/internal/deploy-manifest.ts +10 -5
  164. package/src/internal/discovery.ts +25 -2
  165. package/src/internal/framework-storage-selection.ts +61 -19
  166. package/src/internal/hosted-admission-context.ts +37 -0
  167. package/src/internal/hosted-delivery-protocol.ts +44 -1
  168. package/src/internal/hosted-delivery.ts +95 -40
  169. package/src/internal/hosted-managed-automation.ts +72 -0
  170. package/src/internal/review-comments.ts +10 -113
  171. package/src/internal/scm/pr-url.ts +95 -0
  172. package/src/internal/sdk-runner.ts +57 -2
  173. package/src/internal/server.ts +10 -0
  174. package/src/internal/session-engine.ts +12 -0
  175. package/src/storage-backends/cursor-hosted.ts +10 -3
  176. package/templates/agentic-owners/README.md +1 -1
  177. package/templates/agentic-owners/agent/agent.ts +0 -10
  178. package/templates/agentic-owners/agent/channels/github.ts +5 -14
  179. package/templates/agentic-owners/agent/lib/config.ts +0 -8
  180. package/templates/agentic-owners/agent/lib/review.ts +2 -15
  181. package/templates/agentic-owners/agent/tools/record_review.ts +2 -4
  182. package/templates/demo/agent/agent.ts +0 -10
  183. package/templates/pr-autofixer/README.md +0 -2
  184. package/templates/pr-autofixer/agent/agent.ts +0 -11
  185. package/templates/pr-autofixer/agent/channels/slack.ts +0 -7
  186. package/templates/pr-autofixer/agent/lib/pr-state.ts +5 -17
  187. package/templates/pr-autofixer/agent/lib/repos.ts +0 -1
  188. package/templates/security-help/README.md +2 -2
  189. package/templates/security-help/agent/agent.ts +1 -2
  190. package/templates/security-help/agent/channels/slack.ts +0 -3
  191. package/templates/security-help/agent/instructions.md +9 -10
  192. package/templates/security-help/agent/skills/access-request.md +1 -1
  193. package/templates/security-help/agent/skills/faq.md +31 -0
  194. package/templates/security-help/agent/skills/security-playbooks.md +1 -1
  195. package/templates/security-help/package.json +1 -2
  196. package/templates/security-reviewer/agent/agent.ts +0 -10
  197. package/templates/triage/agent/agent.ts +0 -10
  198. package/templates/triage/agent/channels/queue.ts +1 -1
  199. package/templates/triage/agent/channels/webhook.ts +1 -3
  200. package/dist/docs/assets/chunks/@localSearchIndexroot.DU3U2Ij2.js +0 -1
  201. package/dist/docs/assets/index.md.DRakGHFe.js +0 -5
  202. package/dist/playground/assets/index-D9N7-q97.css +0 -1
  203. package/templates/security-help/agent/knowledge/faq/approvals.md +0 -5
  204. package/templates/security-help/agent/knowledge/faq/channels.md +0 -6
  205. package/templates/security-help/agent/knowledge/faq/phishing.md +0 -10
  206. package/templates/security-help/agent/skills/security-first-pass.md +0 -15
  207. /package/dist/docs/assets/{reference_skills.md.8son6Hjm.lean.js → reference_skills.md.BFW9retM.lean.js} +0 -0
  208. /package/dist/docs/assets/{templates_agentic-owners.md.DqtPdm6f.lean.js → templates_agentic-owners.md.BZSH4N9z.lean.js} +0 -0
  209. /package/dist/docs/assets/{templates_demo.md.DhFcWN6j.lean.js → templates_demo.md.BeQX9V3H.lean.js} +0 -0
@@ -8,8 +8,8 @@
8
8
  />
9
9
  <meta name="viewport" content="width=device-width, initial-scale=1" />
10
10
  <title>agent-serve playground</title>
11
- <script type="module" crossorigin src="./assets/index-B3JCyigB.js"></script>
12
- <link rel="stylesheet" crossorigin href="./assets/index-D9N7-q97.css">
11
+ <script type="module" crossorigin src="./assets/index-CZA1uEWA.js"></script>
12
+ <link rel="stylesheet" crossorigin href="./assets/index-CF7hUDnQ.css">
13
13
  </head>
14
14
  <body>
15
15
  <div id="root"></div>
@@ -47,8 +47,13 @@ export interface CursorHostedStorageOptions {
47
47
  * `https://api.cursor.com`).
48
48
  */
49
49
  baseUrl?: string;
50
- /** Bearer credential (default: `CURSOR_API_KEY`). */
51
- apiKey?: string;
50
+ /**
51
+ * Bearer credential (default: `CURSOR_API_KEY`). A function is
52
+ * re-resolved on every call: hosted freeze snapshots listen unsigned and
53
+ * bind the key file after serve start, so a value captured at construct
54
+ * time would be permanently absent.
55
+ */
56
+ apiKey?: string | (() => string | undefined);
52
57
  /** Injected for tests. */
53
58
  fetch?: typeof fetch;
54
59
  }
@@ -1 +1 @@
1
- {"version":3,"file":"cursor-hosted.d.ts","sourceRoot":"","sources":["../../src/storage-backends/cursor-hosted.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH,OAAO,KAAK,EACV,cAAc,EACd,eAAe,EACf,aAAa,EAEb,iBAAiB,EAClB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,SAAS,EAAiC,MAAM,aAAa,CAAC;AAW5E;;;GAGG;AACH,eAAO,MAAM,+CAA+C,EAC1D,cAAuB,CAAC;AAE1B;;;GAGG;AACH,eAAO,MAAM,iCAAiC,EAC5C,2BAAoC,CAAC;AAEvC;;;GAGG;AACH,eAAO,MAAM,8BAA8B,EAAE,SAAS;IACpD,OAAO,+CAA+C;IACtD,OAAO,iCAAiC;CAIzC,CAAC;AAEF,MAAM,WAAW,0BAA0B;IACzC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qDAAqD;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0BAA0B;IAC1B,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACtB;AAED;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,EAAE,OAAO,MAE1C,CAAC;AAEF,4EAA4E;AAC5E,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAM7D;AAED,KAAK,0BAA0B,GAAG,QAAQ,CACxC,IAAI,CAAC,aAAa,EAAE,KAAK,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC,CACvD,GAAG;IACF,QAAQ,CAAC,CAAC,qBAAqB,CAAC,EAAE,IAAI,CAAC;IACvC,GAAG,EAAE,eAAe,CAAC;IACrB,KAAK,EAAE,iBAAiB,CAAC;IACzB,GAAG,EAAE,cAAc,CAAC;CACrB,CAAC;AA4BF,6EAA6E;AAC7E,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;IACxB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,mEAAmE;AACnE,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,OAAO,CAAC;IACZ,2CAA2C;IAC3C,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,iEAAiE;IACjE,OAAO,EAAE;QAAE,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CAC9D;AAED,2CAA2C;AAC3C,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,EAAE,CAAC;IACf;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAiFD;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,GAAE,0BAA+B,GACvC,0BAA0B,CA2I5B"}
1
+ {"version":3,"file":"cursor-hosted.d.ts","sourceRoot":"","sources":["../../src/storage-backends/cursor-hosted.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH,OAAO,KAAK,EACV,cAAc,EACd,eAAe,EACf,aAAa,EAEb,iBAAiB,EAClB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,SAAS,EAAiC,MAAM,aAAa,CAAC;AAW5E;;;GAGG;AACH,eAAO,MAAM,+CAA+C,EAC1D,cAAuB,CAAC;AAE1B;;;GAGG;AACH,eAAO,MAAM,iCAAiC,EAC5C,2BAAoC,CAAC;AAEvC;;;GAGG;AACH,eAAO,MAAM,8BAA8B,EAAE,SAAS;IACpD,OAAO,+CAA+C;IACtD,OAAO,iCAAiC;CAIzC,CAAC;AAEF,MAAM,WAAW,0BAA0B;IACzC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC;IAC7C,0BAA0B;IAC1B,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACtB;AAED;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,EAAE,OAAO,MAE1C,CAAC;AAEF,4EAA4E;AAC5E,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAM7D;AAED,KAAK,0BAA0B,GAAG,QAAQ,CACxC,IAAI,CAAC,aAAa,EAAE,KAAK,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC,CACvD,GAAG;IACF,QAAQ,CAAC,CAAC,qBAAqB,CAAC,EAAE,IAAI,CAAC;IACvC,GAAG,EAAE,eAAe,CAAC;IACrB,KAAK,EAAE,iBAAiB,CAAC;IACzB,GAAG,EAAE,cAAc,CAAC;CACrB,CAAC;AA4BF,6EAA6E;AAC7E,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;IACxB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,mEAAmE;AACnE,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,OAAO,CAAC;IACZ,2CAA2C;IAC3C,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,iEAAiE;IACjE,OAAO,EAAE;QAAE,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CAC9D;AAED,2CAA2C;AAC3C,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,EAAE,CAAC;IACf;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAmFD;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,GAAE,0BAA+B,GACvC,0BAA0B,CA2I5B"}
@@ -87,8 +87,8 @@ function toCasResult(response) {
87
87
  }
88
88
  function resolveApiKey(options) {
89
89
  var _a;
90
- var _b;
91
- const key = (_a = ((_b = options.apiKey) !== null && _b !== void 0 ? _b : process.env.CURSOR_API_KEY)) === null || _a === void 0 ? void 0 : _a.trim();
90
+ const configured = typeof options.apiKey === "function" ? options.apiKey() : options.apiKey;
91
+ const key = (_a = (configured !== null && configured !== void 0 ? configured : process.env.CURSOR_API_KEY)) === null || _a === void 0 ? void 0 : _a.trim();
92
92
  if (key === undefined || key === "") {
93
93
  throw new Error("cursorHostedStorage requires CURSOR_API_KEY (deployment pod credential on Cursor hosting)");
94
94
  }
package/docs/README.md CHANGED
@@ -35,7 +35,7 @@ npx @cursor/july docs
35
35
  | Building a new agent with Cursor | [Scaffold an agent with Cursor](./scaffolding-agents.md) |
36
36
  | Turning a Cursor Automation into a project | [Convert a Cursor Automation](./guides/convert-automation.md) |
37
37
  | Wiring an agent to Slack | [Slack guide](./guides/slack.md) |
38
- | Starting from a packaged template | [Demo](./templates/demo.md), [Security reviewer](./templates/security-reviewer.md), [Triage](./templates/triage.md), or [Agentic Owners](./templates/agentic-owners.md) |
38
+ | Starting from a packaged template | [Demo](./templates/demo.md), [Security reviewer](./templates/security-reviewer.md), [Security help](./templates/security-help.md), [Triage](./templates/triage.md), or [Agentic Owners](./templates/agentic-owners.md) |
39
39
  | Wiring an agent to GitHub webhooks | [GitHub guide](./guides/github.md) |
40
40
  | Driving PRs from a cloud VM | [PR autofixer template](./templates/pr-autofixer.md) |
41
41
  | Driving an agent from Linear (or another tracker) | [Webhooks guide: Linear example](./guides/webhooks.md#example-linear-as-the-control-plane) |
@@ -63,6 +63,8 @@ npx @cursor/july docs
63
63
  collects the PR, the model records, then comments.
64
64
  - [Security reviewer](./templates/security-reviewer.md): review pull
65
65
  requests for exploitable bugs and post one comment.
66
+ - [Answer security questions in Slack](./templates/security-help.md):
67
+ answer from your skills, or take a first look at a pasted PR.
66
68
  - [Triage Linear or Jira issues in place](./templates/triage.md): classify
67
69
  existing tickets and comment on them.
68
70
  - [Review pull requests with owners policies](./templates/agentic-owners.md):
@@ -415,6 +415,7 @@ non-zero when the reconstructed trajectory failed.
415
415
  agent-sdk init ./my-agent # scaffold package.json, tsconfig.json, agent/ + a demo tool
416
416
  agent-sdk init ./my-demo --template demo # record a PR walkthrough
417
417
  agent-sdk init ./my-reviewer --template security-reviewer # review PRs for security bugs
418
+ agent-sdk init ./security-help --template security-help # answer security questions in Slack
418
419
  agent-sdk init ./my-triage --template triage-linear # comment on Linear issues
419
420
  agent-sdk init ./my-triage --template triage-jira # comment on Jira issues
420
421
  agent-sdk init ./my-owners --template agentic-owners # review PRs via owners policies
@@ -430,7 +431,8 @@ agent-sdk init # no directory: print the setup guide
430
431
  `@cursor/july` resolves for `dev` and `run`.
431
432
 
432
433
  Templates may ship `init.json`. On a TTY, `init` asks those questions
433
- before writing files. `pr-autofixer` asks for GitHub repos. Repeat
434
+ before writing files. `pr-autofixer` and `security-help` ask for GitHub
435
+ repos. Repeat
434
436
  `--var id=value` to answer without a prompt.
435
437
  `--json` and non-TTY hosts skip the interview unless `--var` is set.
436
438
 
@@ -49,7 +49,7 @@ low risk approve, medium and above hold with a comment. Route reviews by
49
49
  committing policies:
50
50
 
51
51
  ```yaml
52
- # .agentic-owners/policy.yml anywhere in the repo; closest wins.
52
+ # .agentic-owners/policy.yml. Anywhere in the repo; closest wins.
53
53
  # paths are repo-root-relative globs, wherever the policy file lives.
54
54
  version: 1
55
55
  policies:
@@ -44,13 +44,14 @@ curl -X POST http://127.0.0.1:3000/demo-agent/v1/channels/queue/pr \
44
44
  ```
45
45
 
46
46
  The host fetches title, body, and files, writes `pr.md` and `files.md`,
47
- and starts the turn. Retries coalesce on `pr:owner/repo#N`.
47
+ and starts the turn. Retries for the same PR coalesce.
48
48
 
49
49
  GitHub label `demo` or comment `/demo` when you terminate webhooks
50
50
  yourself: self-host and set `GITHUB_WEBHOOK_SECRET`. Hosted Cursor
51
51
  aliases require `X-Agent-Alias-Token`, which GitHub cannot send.
52
52
 
53
- `record_demo` comments on that key. Eval sessions skip the comment.
53
+ `record_demo` comments on that pull request. Eval sessions skip the
54
+ comment.
54
55
 
55
56
  ## First walkthrough
56
57
 
@@ -83,17 +83,11 @@ with `git push origin HEAD:<headRef>`. Workflow actions run through
83
83
 
84
84
  ## GitHub wakes
85
85
 
86
- Mounted at `/v1/channels/github`. Cursor relays pull request, comment,
87
- review, check, and failing status events for the repos you listed. A
88
- wake only starts or resumes a cloud conversation after that PR has been
89
- driven. `pull_request.opened` is ignored. A PR comment or review on an
90
- opted-in PR wakes the agent. A comment on a plain GitHub issue does
91
- not. The channel buffers about 3 seconds per PR. Payload details are
92
- dropped on purpose. The follow-up says something changed.
93
-
94
- Pending wakes and the PR-to-cloud-agent map persist in `host.kv` so
95
- they survive restart. `cursorHostedStorage` keeps both across replace.
96
- Without that plug-in, `host.kv` is local-only.
86
+ Cursor relays pull request, comment, review, check, and failing status
87
+ events for the repos you listed. A wake only starts or resumes a cloud
88
+ conversation after that PR has been driven. `pull_request.opened` is
89
+ ignored. A PR comment or review on an opted-in PR wakes the agent. A
90
+ comment on a plain GitHub issue does not.
97
91
 
98
92
  Closing a PR cancels its merge-conflict reminder and drops buffered
99
93
  wakes.
@@ -105,8 +99,8 @@ fixture replay.
105
99
 
106
100
  `agent/channels/slack.ts` is a dedicated Socket Mode bot
107
101
  (`PR_AUTOFIXER_SLACK_*`). Mint it with `agent-sdk slack create`, then
108
- mention the bot or DM it with a PR URL.
109
- Same `drive_pr` path as the playground. See [Slack](../guides/slack.md).
102
+ mention the bot or DM it with a PR URL. Same `drive_pr` path as the
103
+ playground. See [Slack](../guides/slack.md).
110
104
 
111
105
  ## Evals
112
106
 
@@ -0,0 +1,70 @@
1
+ ---
2
+ title: "Answer security questions in Slack"
3
+ description: "Scaffold the agent, connect Slack, and answer from your skills. Paste a GitHub pull request for a first look."
4
+ ---
5
+
6
+ # Answer security questions in Slack
7
+
8
+ This agent answers security questions in Slack from files you edit.
9
+ Paste a GitHub pull request URL for a first look. Access grants,
10
+ incident close-out, and GitHub writes stay with a person.
11
+
12
+ ## Scaffold
13
+
14
+ ```bash
15
+ npx @cursor/july init ./security-help --template security-help
16
+ ```
17
+
18
+ `init` asks which GitHub repos it may read. Every repo must share one
19
+ owner. Pass `--var repos=acme/api,acme/web` to skip the prompt.
20
+
21
+ The list lands in `agent/lib/repos.ts`. Slack uses it when someone
22
+ pastes a PR URL.
23
+
24
+ ## Connect Slack and GitHub
25
+
26
+ ```bash
27
+ cd security-help
28
+ agent-sdk login
29
+ agent-sdk slack create --name "Security Help" --channel-posts
30
+ agent-sdk dev
31
+ ```
32
+
33
+ `--channel-posts` is required to watch channels. Mentions and DMs work
34
+ without it. Connect GitHub in Cursor for the watched repos. Slack
35
+ starts the session. See [Slack](../guides/slack.md) and
36
+ [GitHub](../guides/github.md).
37
+
38
+ ## First answer
39
+
40
+ Mention the bot or DM it. Edit `agent/skills/faq.md` before you rely
41
+ on the answers; the shipped file is a placeholder.
42
+
43
+ Paste a watched PR URL for a first look. A repo outside the list is
44
+ refused.
45
+
46
+ ## What to edit
47
+
48
+ - `agent/lib/repos.ts`: repos it may read
49
+ - `agent/channels/slack.ts`: channel ids to watch (`watch`)
50
+ - `agent/skills/faq.md`: answers for your company
51
+ - `agent/skills/`: how to look at a PR, a leak, or an access ask
52
+ - `agent/instructions.md`: routing
53
+
54
+ ## Evals
55
+
56
+ ```bash
57
+ agent-sdk eval
58
+ ```
59
+
60
+ Three smoke cases: phishing, SaaS access, and a seeded PR look. Eval
61
+ sessions skip Slack and GitHub writes.
62
+
63
+ ## Deploy
64
+
65
+ ```bash
66
+ agent-sdk deploy
67
+ ```
68
+
69
+ Run it from the agent's git checkout. Set Slack tokens on the
70
+ deployment after `slack create`. See [Deployment](../deployment.md).
@@ -9,8 +9,7 @@ This agent reads a pull request diff and posts one review comment. It
9
9
  reports exploitable bugs: injection, authz bypass, secret leaks, SSRF,
10
10
  RCE. Style nits stay out.
11
11
 
12
- The in-repo factory Security Reviewer runs a staged pipeline with
13
- parallel workers. This template is one model turn.
12
+ This template is one model turn: read the diff, then post one comment.
14
13
 
15
14
  ## Scaffold
16
15
 
@@ -51,8 +51,7 @@ agent-sdk dev
51
51
 
52
52
  Open the playground. Run `/queue/issue` and paste an existing issue.
53
53
 
54
- Local multi-agent mode mounts this project as `triage-agent`. You can
55
- also POST:
54
+ You can also POST:
56
55
 
57
56
  ```bash
58
57
  curl -X POST http://127.0.0.1:3000/triage-agent/v1/channels/queue/issue \
@@ -64,14 +63,11 @@ curl -X POST http://127.0.0.1:3000/triage-agent/v1/channels/queue/issue \
64
63
  }'
65
64
  ```
66
65
 
67
- `POST /v1/channels/queue/issue` accepts
68
- `{ identifier, title?, description? }` from the playground.
69
-
70
66
  For create webhooks, set `LINEAR_WEBHOOK_SECRET` or
71
67
  `JIRA_WEBHOOK_SECRET`. Point the provider at the deployed alias under
72
68
  `/v1/channels/webhook`. Signed events start or resume triage for that issue.
73
69
 
74
- `record_triage` comments on the issue in the continuation key, not
70
+ `record_triage` comments on the issue that started the session, not
75
71
  whatever identifier the model copies out of the ticket body.
76
72
 
77
73
  ## Rubric
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cursor/july",
3
- "version": "0.1.94",
3
+ "version": "0.1.95",
4
4
  "description": "(early alpha) Filesystem-first framework for defining Cursor agents as markdown and TypeScript and serving them over channels with the Cursor SDK.",
5
5
  "license": "SEE LICENSE IN LICENSE.md",
6
6
  "repository": {
@@ -11,6 +11,7 @@ import {
11
11
  continuationSource,
12
12
  normalizeIdentity,
13
13
  } from "../../internal/continuation-identity.js";
14
+ import { isDeferredChannelSession } from "../../internal/deferred-channel-session.js";
14
15
  import { isDevMode } from "../../internal/dev-mode.js";
15
16
  import { bindLocalIngressSend } from "../../internal/local-ingress.js";
16
17
  import type {
@@ -1622,16 +1623,15 @@ async function startTurn(input: {
1622
1623
  scheduleAfterAck(input.args, async () => {
1623
1624
  await sendTurn();
1624
1625
  });
1625
- return withDispatchOutcome(
1626
- Response.json(
1627
- { ok: true, dispatched: true, mode: "turn" },
1628
- { status: 202 }
1629
- ),
1630
- "send"
1631
- );
1626
+ return acknowledgeTurn();
1632
1627
  }
1633
1628
 
1634
1629
  const session = await sendTurn();
1630
+ if (isDeferredChannelSession(session)) {
1631
+ // Hosted admission captured the send; the control plane allocates the
1632
+ // session after acknowledgement, so there is nothing to report yet.
1633
+ return acknowledgeTurn();
1634
+ }
1635
1635
  return withDispatchOutcome(
1636
1636
  Response.json({
1637
1637
  ok: true,
@@ -1677,12 +1677,27 @@ function scheduleAfterAck(
1677
1677
  );
1678
1678
  }
1679
1679
 
1680
+ /** 202 ack for a turn whose send completes after the response flushes. */
1681
+ function acknowledgeTurn(): Response {
1682
+ return withDispatchOutcome(
1683
+ Response.json(
1684
+ { ok: true, dispatched: true, mode: "turn" },
1685
+ { status: 202 }
1686
+ ),
1687
+ "send"
1688
+ );
1689
+ }
1690
+
1680
1691
  function acknowledgeTask(
1681
1692
  args: ChannelHandlerArgs,
1682
1693
  dispatch: GitHubTaskDispatch,
1683
1694
  extra: Record<string, unknown>
1684
1695
  ): Response {
1685
- scheduleAfterAck(args, dispatch.task);
1696
+ // Hand the task the per-delivery send/waitUntil so hosted admission can
1697
+ // capture task-initiated sends; startup-captured sends bypass capture.
1698
+ scheduleAfterAck(args, () =>
1699
+ dispatch.task({ send: args.send, waitUntil: args.waitUntil })
1700
+ );
1686
1701
  return withDispatchOutcome(
1687
1702
  Response.json(
1688
1703
  { ok: true, dispatched: true, mode: "task", ...extra },
@@ -7,6 +7,7 @@ import type {
7
7
  ChannelEventHandlers,
8
8
  ChannelStartArgs,
9
9
  HostContext,
10
+ SendMessageFn,
10
11
  SendMessageOptions,
11
12
  } from "../../types.js";
12
13
  import type { GitHubApiOptions } from "./api.js";
@@ -370,13 +371,29 @@ export interface GitHubTurnDispatch {
370
371
  | Promise<GitHubWorkspaceFiles | undefined>);
371
372
  }
372
373
 
374
+ /** Bound per-delivery helpers passed to a {@link GitHubTaskDispatch.task}. */
375
+ export interface GitHubTaskArgs {
376
+ /**
377
+ * Start (or resume) a session for this delivery. Locally this runs a real
378
+ * turn and returns the live session. In hosted admission it captures the
379
+ * send for the control plane to execute after `ses_…` is allocated and
380
+ * returns an inert deferred handle, so the task body keeps running.
381
+ * Always use this over a send captured at `onStart` — a startup-captured
382
+ * send bypasses hosted capture and is rejected during hosted admission.
383
+ */
384
+ send: SendMessageFn;
385
+ /** Extend the delivery's background window past the task promise. */
386
+ waitUntil: (promise: Promise<unknown>) => void;
387
+ }
388
+
373
389
  /**
374
390
  * Run a host-side handler for the event instead of a model turn. The task
375
391
  * runs in the background (`waitUntil`) after the webhook is acknowledged
376
- * with a 202, so it can outlive GitHub's ~10s delivery timeout.
392
+ * with a 202, so it can outlive GitHub's ~10s delivery timeout. The callback
393
+ * receives {@link GitHubTaskArgs}; zero-argument tasks remain valid.
377
394
  */
378
395
  export interface GitHubTaskDispatch {
379
- task: () => void | Promise<void>;
396
+ task: (args: GitHubTaskArgs) => void | Promise<void>;
380
397
  }
381
398
 
382
399
  export type GitHubDispatchResult =
@@ -26,6 +26,7 @@ import {
26
26
  import { deriveOriginWebhookEvents, ORIGIN_CHANNEL_KIND } from "./events.js";
27
27
  import {
28
28
  DEFAULT_ORIGIN_API_BASE_URL,
29
+ OriginJwksUnavailableError,
29
30
  type OriginWebhookHeaders,
30
31
  verifyOriginWebhook,
31
32
  } from "./origin-webhook.js";
@@ -300,10 +301,12 @@ export function parseOriginPullRequestEvent(input: {
300
301
  ctx: {
301
302
  deliveryId: input.envelope.deliveryId,
302
303
  eventType,
304
+ eventTime: input.envelope.event.eventTime,
303
305
  installationId: input.envelope.installationId,
304
306
  repository,
305
307
  pullRequestNumber: number,
306
308
  pullRequestUrl: url,
309
+ payload,
307
310
  sender: originSender(input.envelope, payload),
308
311
  },
309
312
  pullRequest: {
@@ -687,7 +690,16 @@ export async function handleOriginWebhookRequest(input: {
687
690
  await verifyOriginWebhook(bodyText, originHeaders(input.request), {
688
691
  apiBaseUrl: resolveApiBaseUrl(input.options),
689
692
  });
690
- } catch {
693
+ } catch (error) {
694
+ // A JWKS outage means the delivery was never checked: answer 503 so
695
+ // Origin's delivery worker retries. Only a real signature mismatch
696
+ // is the terminal 401.
697
+ if (error instanceof OriginJwksUnavailableError) {
698
+ return Response.json(
699
+ { ok: false, error: "signature_verification_unavailable" },
700
+ { status: 503 }
701
+ );
702
+ }
691
703
  return Response.json(
692
704
  { ok: false, error: "invalid_signature" },
693
705
  { status: 401 }
@@ -247,7 +247,31 @@ export interface VerifyOriginWebhookOptions {
247
247
  }
248
248
 
249
249
  /**
250
- * Verify a Standard-Webhooks v1ed Origin payload. Throws on failure.
250
+ * The signing JWKS could not be fetched (and no cached copy applies), so
251
+ * the delivery was never actually checked. Callers must answer retryably
252
+ * (5xx) — a 401 would make Origin's delivery worker drop the wake as
253
+ * terminal on what is only a transient outage.
254
+ */
255
+ export class OriginJwksUnavailableError extends Error {}
256
+
257
+ async function fetchJwksOrUnavailable(
258
+ apiBaseUrl: string,
259
+ fetchImpl: typeof fetch,
260
+ options?: FetchOriginJwksOptions
261
+ ): Promise<readonly OriginJwk[]> {
262
+ try {
263
+ return await fetchOriginJwks(apiBaseUrl, fetchImpl, options);
264
+ } catch (error) {
265
+ throw new OriginJwksUnavailableError(
266
+ `Origin JWKS unavailable: ${error instanceof Error ? error.message : String(error)}`
267
+ );
268
+ }
269
+ }
270
+
271
+ /**
272
+ * Verify a Standard-Webhooks v1ed Origin payload. Throws
273
+ * {@link OriginJwksUnavailableError} when the keys cannot be fetched, and a
274
+ * plain error when the signature does not verify against them.
251
275
  */
252
276
  export async function verifyOriginWebhook(
253
277
  body: string | Buffer,
@@ -256,7 +280,7 @@ export async function verifyOriginWebhook(
256
280
  ): Promise<void> {
257
281
  const apiBaseUrl = options?.apiBaseUrl ?? DEFAULT_ORIGIN_API_BASE_URL;
258
282
  const fetchImpl = options?.fetchImpl ?? fetch;
259
- const keys = await fetchOriginJwks(apiBaseUrl, fetchImpl);
283
+ const keys = await fetchJwksOrUnavailable(apiBaseUrl, fetchImpl);
260
284
  if (
261
285
  verifyV1edWebhookPayload({
262
286
  publicJwks: keys,
@@ -267,7 +291,7 @@ export async function verifyOriginWebhook(
267
291
  ) {
268
292
  return;
269
293
  }
270
- const refreshed = await fetchOriginJwks(apiBaseUrl, fetchImpl, {
294
+ const refreshed = await fetchJwksOrUnavailable(apiBaseUrl, fetchImpl, {
271
295
  force: true,
272
296
  });
273
297
  if (
@@ -51,11 +51,19 @@ export interface OriginReview {
51
51
  export interface OriginEventContext {
52
52
  deliveryId?: string;
53
53
  eventType: string;
54
+ /** Delivery envelope `event.eventTime`, when present. */
55
+ eventTime?: string;
54
56
  /** Origin app installation id from the delivery envelope, when present. */
55
57
  installationId?: string;
56
58
  repository: OriginRepositoryRef;
57
59
  pullRequestNumber: number;
58
60
  pullRequestUrl: string;
61
+ /**
62
+ * Raw parsed `event.payload` record (`{}` when absent), for consumers
63
+ * whose normalization needs more than the typed event — the GitHub
64
+ * channel's hook ctx exposes the same.
65
+ */
66
+ payload: Record<string, unknown>;
59
67
  sender?: OriginActor;
60
68
  host: HostContext;
61
69
  artifacts: ArtifactsApi;
@@ -1,7 +1,9 @@
1
1
  /**
2
- * Best-effort GitHub PR references from free-form chat (Slack, etc.).
2
+ * Best-effort PR references from free-form chat (Slack, etc.).
3
3
  */
4
4
 
5
+ import { type PrProvider, parsePrUrl } from "../../internal/scm/pr-url.js";
6
+
5
7
  export interface GithubPrRef {
6
8
  /** Normalized URL `https://github.com/owner/repo/pull/N`. */
7
9
  url: string;
@@ -12,39 +14,68 @@ export interface GithubPrRef {
12
14
  number: number;
13
15
  }
14
16
 
17
+ export type OriginPrRef = GithubPrRef;
18
+
19
+ const URL_IN_TEXT = /https?:\/\/[^\s>|]+/gi;
20
+
21
+ function githubRef(owner: string, repo: string, number: number): GithubPrRef {
22
+ return {
23
+ owner,
24
+ repo,
25
+ number,
26
+ url: `https://github.com/${owner}/${repo}/pull/${number}`,
27
+ label: `${owner}/${repo}#${number}`,
28
+ };
29
+ }
30
+
31
+ function firstUrlRef(
32
+ text: string,
33
+ provider: PrProvider
34
+ ): GithubPrRef | undefined {
35
+ const matches = text.match(URL_IN_TEXT);
36
+ if (matches === null) {
37
+ return undefined;
38
+ }
39
+ for (const raw of matches) {
40
+ const parsed = parsePrUrl(raw);
41
+ if (parsed?.provider === provider) {
42
+ return {
43
+ owner: parsed.owner,
44
+ repo: parsed.repo,
45
+ number: parsed.number,
46
+ url: parsed.url,
47
+ label: `${parsed.owner}/${parsed.repo}#${parsed.number}`,
48
+ };
49
+ }
50
+ }
51
+ return undefined;
52
+ }
53
+
54
+ /**
55
+ * Find the first Origin PR URL in `text`.
56
+ * Does not treat bare `owner/repo#N` as Origin.
57
+ */
58
+ export function extractOriginPrRef(text: string): OriginPrRef | undefined {
59
+ return firstUrlRef(text, "origin");
60
+ }
61
+
15
62
  /**
16
63
  * Find the first GitHub PR URL or `owner/repo#N` in `text`.
17
64
  * Returns `undefined` when none is present.
18
65
  */
19
66
  export function extractGithubPrRef(text: string): GithubPrRef | undefined {
20
- const urlMatch = text.match(
21
- /https?:\/\/(?:www\.)?github\.com\/([\w.-]+)\/([\w.-]+)\/pull\/(\d+)/i
22
- );
23
- if (urlMatch !== null) {
24
- const owner = urlMatch[1] as string;
25
- const repo = urlMatch[2] as string;
26
- const number = Number(urlMatch[3]);
27
- return {
28
- owner,
29
- repo,
30
- number,
31
- url: `https://github.com/${owner}/${repo}/pull/${number}`,
32
- label: `${owner}/${repo}#${number}`,
33
- };
67
+ const fromUrl = firstUrlRef(text, "github");
68
+ if (fromUrl !== undefined) {
69
+ return fromUrl;
34
70
  }
35
71
 
36
72
  const hashMatch = text.match(/\b([\w.-]+)\/([\w.-]+)#(\d+)\b/);
37
73
  if (hashMatch === null) {
38
74
  return undefined;
39
75
  }
40
- const owner = hashMatch[1] as string;
41
- const repo = hashMatch[2] as string;
42
- const number = Number(hashMatch[3]);
43
- return {
44
- owner,
45
- repo,
46
- number,
47
- url: `https://github.com/${owner}/${repo}/pull/${number}`,
48
- label: `${owner}/${repo}#${number}`,
49
- };
76
+ return githubRef(
77
+ hashMatch[1] as string,
78
+ hashMatch[2] as string,
79
+ Number(hashMatch[3])
80
+ );
50
81
  }
@@ -125,8 +125,12 @@ export function isCursorUserStoreFilesAvailable(
125
125
  export interface CursorHostedFilesOptions {
126
126
  /** Control-plane base URL (default: `CURSOR_API_BASE_URL`, else api.cursor.com). */
127
127
  baseUrl?: string;
128
- /** Bearer credential (default: `CURSOR_API_KEY`). */
129
- apiKey?: string;
128
+ /**
129
+ * Bearer credential (default: `CURSOR_API_KEY`). A function is re-resolved
130
+ * on every call — hosted freeze snapshots listen unsigned and bind the key
131
+ * file after serve start.
132
+ */
133
+ apiKey?: string | (() => string | undefined);
130
134
  /** File store to address (default: `AGENT_SERVE_STORE_SOURCE_ID`). */
131
135
  storeSourceId?: string;
132
136
  /** Test seam; defaults to global fetch. */
@@ -622,7 +626,9 @@ function resolveStoreSourceId(options: CursorHostedFilesOptions): string {
622
626
  }
623
627
 
624
628
  function resolveApiKey(options: CursorHostedFilesOptions): string {
625
- const key = (options.apiKey ?? process.env.CURSOR_API_KEY)?.trim();
629
+ const configured =
630
+ typeof options.apiKey === "function" ? options.apiKey() : options.apiKey;
631
+ const key = (configured ?? process.env.CURSOR_API_KEY)?.trim();
626
632
  if (key === undefined || key === "") {
627
633
  throw new Error(
628
634
  "cursorHostedFiles requires CURSOR_API_KEY (deployment pod credential on Cursor hosting)"
package/src/files.ts CHANGED
@@ -184,6 +184,17 @@ export const agentStoreKeys = {
184
184
  `${STORAGE_KEY_ROOT}/${agent}/memory/journal.jsonl`,
185
185
  memoryJournalRotated: (agent: string, stamp: string): string =>
186
186
  `${STORAGE_KEY_ROOT}/${agent}/memory/journal-${stamp}.jsonl`,
187
+ // SDK conversation mirror (the runner's SQLite store, exported through the
188
+ // store APIs): one manifest per SDK agent id plus its content-addressed
189
+ // checkpoint blobs. See internal/conversation-mirror.ts.
190
+ conversationManifest: (agent: string, sdkAgentId: string): string =>
191
+ `${STORAGE_KEY_ROOT}/${agent}/conversations/${encodeURIComponent(sdkAgentId)}/manifest.json`,
192
+ conversationBlob: (
193
+ agent: string,
194
+ sdkAgentId: string,
195
+ blobId: string
196
+ ): string =>
197
+ `${STORAGE_KEY_ROOT}/${agent}/conversations/${encodeURIComponent(sdkAgentId)}/blobs/${encodeURIComponent(blobId)}`,
187
198
  } as const;
188
199
 
189
200
  /**