@cursor/july 0.1.96 → 0.1.99

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 (381) hide show
  1. package/AGENTS.md +1 -1
  2. package/README.md +3 -2
  3. package/dist/bin/agent-serve.js +13 -3
  4. package/dist/channels/github/github-channel.d.ts.map +1 -1
  5. package/dist/channels/github/github-channel.js +16 -0
  6. package/dist/channels/origin/api.d.ts +15 -4
  7. package/dist/channels/origin/api.d.ts.map +1 -1
  8. package/dist/channels/origin/api.js +19 -3
  9. package/dist/channels/origin/binding.d.ts +11 -0
  10. package/dist/channels/origin/binding.d.ts.map +1 -1
  11. package/dist/channels/origin/binding.js +41 -25
  12. package/dist/channels/origin/index.d.ts +1 -0
  13. package/dist/channels/origin/index.d.ts.map +1 -1
  14. package/dist/channels/origin/index.js +1 -0
  15. package/dist/channels/origin/origin-channel.d.ts +2 -0
  16. package/dist/channels/origin/origin-channel.d.ts.map +1 -1
  17. package/dist/channels/origin/origin-channel.js +40 -4
  18. package/dist/channels/origin/reactions.d.ts +56 -0
  19. package/dist/channels/origin/reactions.d.ts.map +1 -0
  20. package/dist/channels/origin/reactions.js +67 -0
  21. package/dist/channels/origin/types.d.ts +11 -0
  22. package/dist/channels/origin/types.d.ts.map +1 -1
  23. package/dist/channels/slack/approvals.d.ts +16 -0
  24. package/dist/channels/slack/approvals.d.ts.map +1 -1
  25. package/dist/channels/slack/approvals.js +86 -0
  26. package/dist/channels/slack/cli-project.d.ts +19 -0
  27. package/dist/channels/slack/cli-project.d.ts.map +1 -0
  28. package/dist/channels/slack/cli-project.js +234 -0
  29. package/dist/channels/slack/defaults.d.ts.map +1 -1
  30. package/dist/channels/slack/defaults.js +142 -63
  31. package/dist/channels/slack/dispatch.d.ts.map +1 -1
  32. package/dist/channels/slack/dispatch.js +1 -1
  33. package/dist/channels/slack/init.d.ts +3 -2
  34. package/dist/channels/slack/init.d.ts.map +1 -1
  35. package/dist/channels/slack/init.js +5 -5
  36. package/dist/channels/slack/interactive.d.ts +2 -1
  37. package/dist/channels/slack/interactive.d.ts.map +1 -1
  38. package/dist/channels/slack/interactive.js +15 -4
  39. package/dist/channels/slack/live-delivery.d.ts +1 -1
  40. package/dist/channels/slack/live-delivery.d.ts.map +1 -1
  41. package/dist/channels/slack/live-delivery.js +4 -2
  42. package/dist/channels/slack/manifest.d.ts +1 -1
  43. package/dist/channels/slack/manifest.js +1 -1
  44. package/dist/channels/slack/progress-delivery.d.ts +28 -0
  45. package/dist/channels/slack/progress-delivery.d.ts.map +1 -0
  46. package/dist/channels/slack/progress-delivery.js +115 -0
  47. package/dist/channels/slack/setup.d.ts +1 -1
  48. package/dist/channels/slack/setup.d.ts.map +1 -1
  49. package/dist/channels/slack/setup.js +10 -6
  50. package/dist/channels/slack/slack-channel.d.ts.map +1 -1
  51. package/dist/channels/slack/slack-channel.js +1 -0
  52. package/dist/channels/slack/tool-approval-events.d.ts.map +1 -1
  53. package/dist/channels/slack/tool-approval-events.js +91 -1
  54. package/dist/channels/slack/types.d.ts +9 -1
  55. package/dist/channels/slack/types.d.ts.map +1 -1
  56. package/dist/docs/404.html +2 -2
  57. package/dist/docs/ab.html +4 -4
  58. package/dist/docs/assets/{app.jXleCmOc.js → app.BplEAZ3S.js} +1 -1
  59. package/dist/docs/assets/chunks/@localSearchIndexroot.DpuI4i7Z.js +1 -0
  60. package/dist/docs/assets/chunks/{VPLocalSearchBox.8LhyglIT.js → VPLocalSearchBox.CHXyv4wP.js} +1 -1
  61. package/dist/docs/assets/chunks/{theme.9ged-pr2.js → theme.BTcsZmjQ.js} +2 -2
  62. package/dist/docs/assets/{deployment.md.D9msOFOW.js → deployment.md.MFPKqsqI.js} +2 -2
  63. package/dist/docs/assets/{guides_mcp-oauth.md.DPYmBCbV.js → guides_mcp-oauth.md.CN-6YmTJ.js} +4 -4
  64. package/dist/docs/assets/{guides_mcp-oauth.md.DPYmBCbV.lean.js → guides_mcp-oauth.md.CN-6YmTJ.lean.js} +1 -1
  65. package/dist/docs/assets/guides_slack.md.VDXQV3ja.js +22 -0
  66. package/dist/docs/assets/guides_slack.md.VDXQV3ja.lean.js +1 -0
  67. package/dist/docs/assets/index.md.CVeRUOeZ.js +5 -0
  68. package/dist/docs/assets/{reference_agent-config.md.Cp_x38Nl.js → reference_agent-config.md.BHeYMgme.js} +1 -1
  69. package/dist/docs/assets/{reference_cli.md.CCnG-nJx.js → reference_cli.md.DfoeyvL0.js} +9 -6
  70. package/dist/docs/assets/{reference_cli.md.CCnG-nJx.lean.js → reference_cli.md.DfoeyvL0.lean.js} +1 -1
  71. package/dist/docs/assets/{reference_connections.md.BH8Oc0D0.js → reference_connections.md.DxldvyIB.js} +4 -3
  72. package/dist/docs/assets/{reference_http-api.md.D89k1mdm.js → reference_http-api.md.BEJx9XVj.js} +2 -2
  73. package/dist/docs/assets/reference_sessions.md.NxFP_CAC.js +1 -0
  74. package/dist/docs/assets/{reference_tools.md.BHeXn2id.js → reference_tools.md.CvAHsdSp.js} +10 -2
  75. package/dist/docs/assets/{reference_tools.md.BHeXn2id.lean.js → reference_tools.md.CvAHsdSp.lean.js} +1 -1
  76. package/dist/docs/assets/templates_agents-md.md.CXSMZljE.js +2 -0
  77. package/dist/docs/assets/templates_agents-md.md.CXSMZljE.lean.js +1 -0
  78. package/dist/docs/assets/troubleshooting.md.DCiPBhYs.js +1 -0
  79. package/dist/docs/building-with-agents.html +4 -4
  80. package/dist/docs/concepts.html +4 -4
  81. package/dist/docs/deployment.html +7 -7
  82. package/dist/docs/deployment.md +5 -4
  83. package/dist/docs/design/runtime-abstraction.md +1757 -0
  84. package/dist/docs/evals.html +4 -4
  85. package/dist/docs/guides/agent-to-agent.html +4 -4
  86. package/dist/docs/guides/cloud-runtime.html +4 -4
  87. package/dist/docs/guides/convert-automation.html +4 -4
  88. package/dist/docs/guides/github.html +4 -4
  89. package/dist/docs/guides/human-in-the-loop.html +4 -4
  90. package/dist/docs/guides/mcp-oauth.html +8 -8
  91. package/dist/docs/guides/mcp-oauth.md +26 -8
  92. package/dist/docs/guides/opentelemetry.html +4 -4
  93. package/dist/docs/guides/slack.html +17 -33
  94. package/dist/docs/guides/slack.md +92 -201
  95. package/dist/docs/guides/webhooks.html +4 -4
  96. package/dist/docs/hashmap.json +1 -1
  97. package/dist/docs/hillclimbing.html +4 -4
  98. package/dist/docs/index.html +6 -6
  99. package/dist/docs/index.md +5 -3
  100. package/dist/docs/llms-full.txt +2065 -637
  101. package/dist/docs/llms.txt +3 -2
  102. package/dist/docs/quickstart.html +4 -4
  103. package/dist/docs/reference/agent-config.html +6 -6
  104. package/dist/docs/reference/agent-config.md +2 -2
  105. package/dist/docs/reference/artifacts.html +4 -4
  106. package/dist/docs/reference/channels.html +4 -4
  107. package/dist/docs/reference/cli.html +13 -10
  108. package/dist/docs/reference/cli.md +32 -16
  109. package/dist/docs/reference/connections.html +9 -8
  110. package/dist/docs/reference/connections.md +6 -3
  111. package/dist/docs/reference/hooks.html +4 -4
  112. package/dist/docs/reference/http-api.html +7 -7
  113. package/dist/docs/reference/http-api.md +3 -1
  114. package/dist/docs/reference/instructions.html +4 -4
  115. package/dist/docs/reference/playground.html +4 -4
  116. package/dist/docs/reference/project-layout.html +4 -4
  117. package/dist/docs/reference/prompt.html +4 -4
  118. package/dist/docs/reference/schedules.html +4 -4
  119. package/dist/docs/reference/sessions.html +5 -5
  120. package/dist/docs/reference/sessions.md +4 -2
  121. package/dist/docs/reference/skills.html +4 -4
  122. package/dist/docs/reference/subagents.html +4 -4
  123. package/dist/docs/reference/tools.html +15 -7
  124. package/dist/docs/reference/tools.md +34 -2
  125. package/dist/docs/scaffolding-agents.html +4 -4
  126. package/dist/docs/storage.html +4 -4
  127. package/dist/docs/templates/agentic-owners.html +4 -4
  128. package/dist/docs/templates/agents-md.html +28 -0
  129. package/dist/docs/templates/agents-md.md +105 -0
  130. package/dist/docs/templates/code-wiki.html +5 -5
  131. package/dist/docs/templates/demo.html +4 -4
  132. package/dist/docs/templates/pr-autofixer.html +4 -4
  133. package/dist/docs/templates/security-help.html +4 -4
  134. package/dist/docs/templates/security-reviewer.html +5 -5
  135. package/dist/docs/templates/triage.html +4 -4
  136. package/dist/docs/troubleshooting.html +5 -5
  137. package/dist/docs/troubleshooting.md +2 -2
  138. package/dist/evals/run-facts.d.ts.map +1 -1
  139. package/dist/evals/run-facts.js +27 -0
  140. package/dist/files-backends/cursor-hosted.d.ts +3 -2
  141. package/dist/files-backends/cursor-hosted.d.ts.map +1 -1
  142. package/dist/files-backends/cursor-hosted.js +3 -2
  143. package/dist/index.d.ts +1 -0
  144. package/dist/index.d.ts.map +1 -1
  145. package/dist/index.js +1 -0
  146. package/dist/internal/advertise-tools.d.ts.map +1 -1
  147. package/dist/internal/advertise-tools.js +15 -9
  148. package/dist/internal/approval-gate.d.ts +12 -13
  149. package/dist/internal/approval-gate.d.ts.map +1 -1
  150. package/dist/internal/approval-gate.js +16 -21
  151. package/dist/internal/as-of.d.ts +19 -0
  152. package/dist/internal/as-of.d.ts.map +1 -0
  153. package/dist/internal/as-of.js +82 -0
  154. package/dist/internal/chat-client.js +10 -0
  155. package/dist/internal/cli-deploy.d.ts +6 -0
  156. package/dist/internal/cli-deploy.d.ts.map +1 -1
  157. package/dist/internal/cli-deploy.js +149 -21
  158. package/dist/internal/cli-mcp-oauth.js +8 -18
  159. package/dist/internal/cli-slack-manual.d.ts +24 -2
  160. package/dist/internal/cli-slack-manual.d.ts.map +1 -1
  161. package/dist/internal/cli-slack-manual.js +251 -20
  162. package/dist/internal/cli-slack.d.ts +9 -2
  163. package/dist/internal/cli-slack.d.ts.map +1 -1
  164. package/dist/internal/cli-slack.js +29 -82
  165. package/dist/internal/cursor/account-mcp.d.ts +1 -0
  166. package/dist/internal/cursor/account-mcp.d.ts.map +1 -1
  167. package/dist/internal/cursor/account-mcp.js +17 -0
  168. package/dist/internal/cursor-agent-template.d.ts +1 -1
  169. package/dist/internal/cursor-agent-template.d.ts.map +1 -1
  170. package/dist/internal/cursor-agent-template.js +1 -0
  171. package/dist/internal/cursor-event-relay.d.ts.map +1 -1
  172. package/dist/internal/cursor-event-relay.js +5 -6
  173. package/dist/internal/deploy-client.d.ts +17 -0
  174. package/dist/internal/deploy-client.d.ts.map +1 -1
  175. package/dist/internal/deploy-client.js +31 -10
  176. package/dist/internal/env-file.d.ts +19 -0
  177. package/dist/internal/env-file.d.ts.map +1 -0
  178. package/dist/internal/env-file.js +90 -0
  179. package/dist/internal/framework-file-storage.d.ts +11 -17
  180. package/dist/internal/framework-file-storage.d.ts.map +1 -1
  181. package/dist/internal/framework-file-storage.js +17 -40
  182. package/dist/internal/framework-storage-selection.d.ts +13 -11
  183. package/dist/internal/framework-storage-selection.d.ts.map +1 -1
  184. package/dist/internal/framework-storage-selection.js +37 -26
  185. package/dist/internal/hosted-admission-adapter.d.ts +28 -0
  186. package/dist/internal/hosted-admission-adapter.d.ts.map +1 -0
  187. package/dist/internal/hosted-admission-adapter.js +7 -0
  188. package/dist/internal/hosted-delivery-protocol.d.ts +13 -1
  189. package/dist/internal/hosted-delivery-protocol.d.ts.map +1 -1
  190. package/dist/internal/hosted-delivery-protocol.js +8 -1
  191. package/dist/internal/hosted-delivery.d.ts +21 -1
  192. package/dist/internal/hosted-delivery.d.ts.map +1 -1
  193. package/dist/internal/hosted-delivery.js +101 -34
  194. package/dist/internal/hosted-execution-diag.d.ts +59 -0
  195. package/dist/internal/hosted-execution-diag.d.ts.map +1 -0
  196. package/dist/internal/hosted-execution-diag.js +187 -0
  197. package/dist/internal/http-channel.d.ts.map +1 -1
  198. package/dist/internal/http-channel.js +85 -2
  199. package/dist/internal/init-project.d.ts.map +1 -1
  200. package/dist/internal/init-project.js +2 -0
  201. package/dist/internal/logs-client.d.ts +5 -0
  202. package/dist/internal/logs-client.d.ts.map +1 -1
  203. package/dist/internal/logs-client.js +5 -0
  204. package/dist/internal/mcp-endpoint.js +2 -3
  205. package/dist/internal/mcp-host.d.ts +10 -0
  206. package/dist/internal/mcp-host.d.ts.map +1 -1
  207. package/dist/internal/mcp-host.js +57 -8
  208. package/dist/internal/mcp-oauth-on-demand.d.ts +68 -0
  209. package/dist/internal/mcp-oauth-on-demand.d.ts.map +1 -0
  210. package/dist/internal/mcp-oauth-on-demand.js +287 -0
  211. package/dist/internal/mcp-oauth-persist.d.ts +42 -0
  212. package/dist/internal/mcp-oauth-persist.d.ts.map +1 -0
  213. package/dist/internal/mcp-oauth-persist.js +92 -0
  214. package/dist/internal/mcp-oauth.d.ts +1 -0
  215. package/dist/internal/mcp-oauth.d.ts.map +1 -1
  216. package/dist/internal/mcp-oauth.js +10 -2
  217. package/dist/internal/null-kv-storage.d.ts +48 -0
  218. package/dist/internal/null-kv-storage.d.ts.map +1 -0
  219. package/dist/internal/null-kv-storage.js +58 -0
  220. package/dist/internal/otel/collector.d.ts.map +1 -1
  221. package/dist/internal/otel/collector.js +22 -9
  222. package/dist/internal/server.d.ts +6 -0
  223. package/dist/internal/server.d.ts.map +1 -1
  224. package/dist/internal/server.js +123 -33
  225. package/dist/internal/session-engine.d.ts +88 -3
  226. package/dist/internal/session-engine.d.ts.map +1 -1
  227. package/dist/internal/session-engine.js +538 -46
  228. package/dist/internal/session-run-log.d.ts +120 -0
  229. package/dist/internal/session-run-log.d.ts.map +1 -0
  230. package/dist/internal/session-run-log.js +359 -0
  231. package/dist/internal/sessions-client.d.ts +9 -7
  232. package/dist/internal/sessions-client.d.ts.map +1 -1
  233. package/dist/internal/sessions-client.js +3 -1
  234. package/dist/internal/storage-coordinator.d.ts +13 -0
  235. package/dist/internal/storage-coordinator.d.ts.map +1 -1
  236. package/dist/internal/storage-coordinator.js +37 -6
  237. package/dist/internal/storage-roles.d.ts +5 -0
  238. package/dist/internal/storage-roles.d.ts.map +1 -1
  239. package/dist/internal/stream-progress.d.ts.map +1 -1
  240. package/dist/internal/stream-progress.js +10 -0
  241. package/dist/internal/tool-policy.d.ts +29 -9
  242. package/dist/internal/tool-policy.d.ts.map +1 -1
  243. package/dist/internal/tool-policy.js +24 -0
  244. package/dist/internal/trajectory.d.ts.map +1 -1
  245. package/dist/internal/trajectory.js +10 -0
  246. package/dist/internal/turn-outbox.d.ts +24 -0
  247. package/dist/internal/turn-outbox.d.ts.map +1 -0
  248. package/dist/internal/turn-outbox.js +80 -0
  249. package/dist/playground/assets/index-D7rGZNjy.css +1 -0
  250. package/dist/playground/assets/index-jzNbJENa.js +69 -0
  251. package/dist/playground/index.html +2 -2
  252. package/dist/storage-backends/cursor-hosted.d.ts +1 -1
  253. package/dist/storage-backends/cursor-hosted.d.ts.map +1 -1
  254. package/dist/storage-backends/cursor-hosted.js +12 -0
  255. package/dist/storage-protocol.d.ts +8 -0
  256. package/dist/storage-protocol.d.ts.map +1 -1
  257. package/dist/storage-protocol.js +8 -0
  258. package/dist/storage.d.ts +8 -0
  259. package/dist/storage.d.ts.map +1 -1
  260. package/dist/tools.d.ts +12 -2
  261. package/dist/tools.d.ts.map +1 -1
  262. package/dist/types.d.ts +88 -7
  263. package/dist/types.d.ts.map +1 -1
  264. package/docs/README.md +5 -3
  265. package/docs/deployment.md +5 -4
  266. package/docs/design/runtime-abstraction.md +1757 -0
  267. package/docs/guides/mcp-oauth.md +26 -8
  268. package/docs/guides/slack.md +93 -202
  269. package/docs/reference/agent-config.md +2 -2
  270. package/docs/reference/cli.md +32 -16
  271. package/docs/reference/connections.md +6 -3
  272. package/docs/reference/http-api.md +3 -1
  273. package/docs/reference/sessions.md +4 -2
  274. package/docs/reference/tools.md +34 -2
  275. package/docs/templates/agents-md.md +110 -0
  276. package/docs/troubleshooting.md +2 -2
  277. package/package.json +1 -1
  278. package/skills/create-agent/SKILL.md +2 -1
  279. package/skills/mcp-auth/SKILL.md +6 -3
  280. package/skills/setup-slack/SKILL.md +23 -13
  281. package/src/bin/agent-serve.ts +12 -1
  282. package/src/channels/github/github-channel.ts +17 -0
  283. package/src/channels/origin/api.ts +24 -5
  284. package/src/channels/origin/binding.ts +55 -26
  285. package/src/channels/origin/index.ts +1 -0
  286. package/src/channels/origin/origin-channel.ts +78 -10
  287. package/src/channels/origin/reactions.ts +82 -0
  288. package/src/channels/origin/types.ts +11 -0
  289. package/src/channels/slack/approvals.ts +105 -0
  290. package/src/channels/slack/cli-project.ts +267 -0
  291. package/src/channels/slack/defaults.ts +165 -74
  292. package/src/channels/slack/dispatch.ts +2 -0
  293. package/src/channels/slack/init.ts +10 -5
  294. package/src/channels/slack/interactive.ts +35 -9
  295. package/src/channels/slack/live-delivery.ts +5 -3
  296. package/src/channels/slack/manifest.ts +1 -1
  297. package/src/channels/slack/progress-delivery.ts +133 -0
  298. package/src/channels/slack/setup.ts +10 -6
  299. package/src/channels/slack/slack-channel.ts +1 -0
  300. package/src/channels/slack/tool-approval-events.ts +93 -0
  301. package/src/channels/slack/types.ts +9 -1
  302. package/src/evals/run-facts.ts +32 -0
  303. package/src/files-backends/cursor-hosted.ts +3 -2
  304. package/src/index.ts +4 -0
  305. package/src/internal/advertise-tools.ts +31 -10
  306. package/src/internal/approval-gate.ts +20 -29
  307. package/src/internal/as-of.ts +107 -0
  308. package/src/internal/chat-client.ts +19 -0
  309. package/src/internal/cli-deploy.ts +203 -13
  310. package/src/internal/cli-mcp-oauth.ts +7 -21
  311. package/src/internal/cli-slack-manual.ts +350 -18
  312. package/src/internal/cli-slack.ts +40 -84
  313. package/src/internal/cursor/account-mcp.ts +21 -0
  314. package/src/internal/cursor-agent-template.ts +1 -0
  315. package/src/internal/cursor-event-relay.ts +5 -6
  316. package/src/internal/deploy-client.ts +43 -0
  317. package/src/internal/env-file.ts +84 -0
  318. package/src/internal/framework-file-storage.ts +18 -46
  319. package/src/internal/framework-storage-selection.ts +41 -25
  320. package/src/internal/hosted-admission-adapter.ts +42 -0
  321. package/src/internal/hosted-delivery-protocol.ts +14 -2
  322. package/src/internal/hosted-delivery.ts +169 -44
  323. package/src/internal/hosted-execution-diag.ts +252 -0
  324. package/src/internal/http-channel.ts +107 -0
  325. package/src/internal/init-project.ts +2 -0
  326. package/src/internal/logs-client.ts +5 -0
  327. package/src/internal/mcp-endpoint.ts +13 -4
  328. package/src/internal/mcp-host.ts +77 -11
  329. package/src/internal/mcp-oauth-on-demand.ts +352 -0
  330. package/src/internal/mcp-oauth-persist.ts +127 -0
  331. package/src/internal/mcp-oauth.ts +17 -1
  332. package/src/internal/null-kv-storage.ts +74 -0
  333. package/src/internal/otel/collector.ts +30 -0
  334. package/src/internal/server.ts +159 -11
  335. package/src/internal/session-engine.ts +691 -57
  336. package/src/internal/session-run-log.ts +584 -0
  337. package/src/internal/sessions-client.ts +17 -8
  338. package/src/internal/storage-coordinator.ts +49 -9
  339. package/src/internal/storage-roles.ts +7 -0
  340. package/src/internal/stream-progress.ts +19 -0
  341. package/src/internal/tool-policy.ts +49 -9
  342. package/src/internal/trajectory.ts +10 -0
  343. package/src/internal/turn-outbox.ts +85 -0
  344. package/src/storage-backends/cursor-hosted.ts +13 -1
  345. package/src/storage-protocol.ts +10 -0
  346. package/src/storage.ts +12 -0
  347. package/src/tools.ts +12 -2
  348. package/src/types.ts +93 -8
  349. package/templates/agents-md/README.md +39 -0
  350. package/templates/agents-md/agent/agent.ts +8 -0
  351. package/templates/agents-md/agent/channels/github.ts +10 -0
  352. package/templates/agents-md/agent/channels/queue.ts +28 -0
  353. package/templates/agents-md/agent/channels/slack.ts +9 -0
  354. package/templates/agents-md/agent/instructions.md +39 -0
  355. package/templates/agents-md/agent/lib/collect.ts +439 -0
  356. package/templates/agents-md/agent/lib/config.ts +8 -0
  357. package/templates/agents-md/agent/lib/paths.ts +51 -0
  358. package/templates/agents-md/agent/schedules/weekly.ts +17 -0
  359. package/templates/agents-md/agent/tools/apply_agents.ts +226 -0
  360. package/templates/agents-md/evals/agents.eval.ts +135 -0
  361. package/templates/agents-md/evals/evals.config.ts +5 -0
  362. package/templates/agents-md/init.json +38 -0
  363. package/templates/agents-md/package.json +18 -0
  364. package/templates/agents-md/tsconfig.json +12 -0
  365. package/dist/docs/assets/chunks/@localSearchIndexroot.DFoGuETX.js +0 -1
  366. package/dist/docs/assets/guides_slack.md.C32HsdKk.js +0 -38
  367. package/dist/docs/assets/guides_slack.md.C32HsdKk.lean.js +0 -1
  368. package/dist/docs/assets/index.md.CI93Ltlb.js +0 -5
  369. package/dist/docs/assets/reference_sessions.md.D0mIh4KK.js +0 -1
  370. package/dist/docs/assets/troubleshooting.md.Ctv3T8C2.js +0 -1
  371. package/dist/docs/design/agsh.md +0 -406
  372. package/dist/playground/assets/index-B1DDvBeC.css +0 -1
  373. package/dist/playground/assets/index-Cx9CclK_.js +0 -88
  374. package/docs/design/agsh.md +0 -406
  375. /package/dist/docs/assets/{deployment.md.D9msOFOW.lean.js → deployment.md.MFPKqsqI.lean.js} +0 -0
  376. /package/dist/docs/assets/{index.md.CI93Ltlb.lean.js → index.md.CVeRUOeZ.lean.js} +0 -0
  377. /package/dist/docs/assets/{reference_agent-config.md.Cp_x38Nl.lean.js → reference_agent-config.md.BHeYMgme.lean.js} +0 -0
  378. /package/dist/docs/assets/{reference_connections.md.BH8Oc0D0.lean.js → reference_connections.md.DxldvyIB.lean.js} +0 -0
  379. /package/dist/docs/assets/{reference_http-api.md.D89k1mdm.lean.js → reference_http-api.md.BEJx9XVj.lean.js} +0 -0
  380. /package/dist/docs/assets/{reference_sessions.md.D0mIh4KK.lean.js → reference_sessions.md.NxFP_CAC.lean.js} +0 -0
  381. /package/dist/docs/assets/{troubleshooting.md.Ctv3T8C2.lean.js → troubleshooting.md.DCiPBhYs.lean.js} +0 -0
@@ -67,8 +67,10 @@ message. Interrupted turns record `turn.failed` with
67
67
  Slack `stop` / `@agent stop` does the same for that thread and clears
68
68
  pending coalesced nudges.
69
69
 
70
- Session-bound deterministic tool calls share the same execution lock.
71
- They return `409 session_busy` while a model turn is running.
70
+ Session-bound deterministic tool calls share the lock only for writes: a
71
+ write-effect call returns `409 session_busy` while a model turn is
72
+ running, a read-effect call runs alongside the turn (see
73
+ [Tools](./tools.md#call-a-tool-without-a-model-turn)).
72
74
 
73
75
  ## Which events can I stream?
74
76
 
@@ -147,6 +147,31 @@ export default defineTool({
147
147
  `dryRunResult` keeps the result shape stable. Without it, a stubbed write
148
148
  returns `"Operation acknowledged."`. Traces mark the result as stubbed.
149
149
 
150
+ ### Bound time arguments under `asOf`
151
+
152
+ Declare `timeArgs` with the input properties that carry time bounds. In a
153
+ session created with `asOf`, every named argument must be an absolute
154
+ ISO-8601 instant with a timezone, no later than the session's frozen
155
+ instant. A call that omits one, or supplies a relative or later value, is
156
+ refused with an error telling the model to retry with absolute bounds.
157
+ Sessions without `asOf` ignore the declaration.
158
+
159
+ ```ts
160
+ export default defineTool({
161
+ description: "Query telemetry between two instants.",
162
+ inputSchema: z.object({ since: z.string(), until: z.string() }),
163
+ effect: "read",
164
+ timeArgs: ["since", "until"],
165
+ async execute({ since, until }) {
166
+ return queryTelemetry(since, until);
167
+ },
168
+ });
169
+ ```
170
+
171
+ Every name in `timeArgs` must exist in the input schema; a session with
172
+ `asOf` refuses to start otherwise, because a misspelled name would silently
173
+ check nothing.
174
+
150
175
  ## Define an agent tool
151
176
 
152
177
  Set `execution: "agent"` and the tool materializes as a shell script
@@ -263,7 +288,14 @@ when the call returns. Pass a `sessionId` (a body field over
263
288
  HTTP, `--session` on the CLI, `options.sessionId` programmatically) to
264
289
  run inside an existing session instead: the tool sees that session's
265
290
  workspace, and the call is recorded on the session's event stream.
266
- Session-bound calls return `409 session_busy` while a turn runs. When the
291
+ While a model turn is running, a session-bound call is admitted by its
292
+ effect: a read-effect call (a declared `effect: "read"`, or an advertised
293
+ MCP tool whose server annotates it read-only) runs alongside the turn,
294
+ reading the workspace as the turn has left it, and is recorded under its
295
+ own per-call `turnId` so trajectories keep it apart from the turn's own
296
+ calls; a write-effect call — including an undeclared tool, which counts
297
+ as a write — returns `409 session_busy` until the turn finishes, because
298
+ a running turn owns the workspace. When the
267
299
  session's harness cwd cannot be materialized, a read-effect call runs
268
300
  in a scratch workspace instead and the outcome carries
269
301
  `scratchWorkspace: true`; a write-effect call fails with
@@ -273,7 +305,7 @@ A session can also be addressed by its continuation token: an optional
273
305
  `continuationToken` (`<channelId>:<key>`, as `/v1/sessions` lists it;
274
306
  mutually exclusive with `sessionId`). A token that maps to a live
275
307
  session behaves exactly like passing that session's id — same ownership
276
- check, same `409 session_busy`, same event recording. A token with no
308
+ check, same busy semantics, same event recording. A token with no
277
309
  session behind it runs the call scratch-bound with the token's channel
278
310
  id and continuation key as the call's session identity, so a deployment
279
311
  whose tools resolve state from the continuation key can serve it with
@@ -0,0 +1,110 @@
1
+ ---
2
+ title: "Keep AGENTS.md current from last week's work"
3
+ description: "Scaffold the agent, pick a repo and Slack channels, dispatch the weekly job, and deploy."
4
+ ---
5
+
6
+ # Keep AGENTS.md current from last week's work
7
+
8
+ This agent runs every Monday at 09:00 UTC. It reads last week's merged
9
+ pull requests and the Slack channels you list. When a durable rule
10
+ showed up, `apply_agents` parks the write until a person approves it,
11
+ then opens a draft follow-up pull request against the default branch.
12
+ Chores and rules the file already states stay quiet.
13
+
14
+ This template is one model turn: read the week, then call
15
+ `apply_agents`.
16
+
17
+ Init once per app. Pass a different repo and channel list each time.
18
+
19
+ ## Scaffold
20
+
21
+ ```bash
22
+ npx @cursor/july init ./agents-md --template agents-md
23
+ ```
24
+
25
+ `init` asks which GitHub repo to watch and which Slack channels to
26
+ read. Pass `--var repos=acme/api --var slack=#eng-api,#api-private`
27
+ to skip the prompt. Use `--var slack=none` when Slack is out of
28
+ scope.
29
+
30
+ The answers land in `agent/lib/config.ts`. Edit that file when the
31
+ set changes.
32
+
33
+ ## Connect GitHub and Slack
34
+
35
+ Connect GitHub in Cursor for that repository (Settings or
36
+ [cursor.com/dashboard](https://cursor.com/dashboard)). Sign the host
37
+ in:
38
+
39
+ ```bash
40
+ cd agents-md
41
+ agent-sdk login
42
+ ```
43
+
44
+ `cursorAccount` mints a short-lived, repo-scoped credential with
45
+ `contents-write` so the agent can open the follow-up PR. See the
46
+ [GitHub guide](../guides/github.md).
47
+
48
+ Create the Slack app and invite the bot to each listed channel,
49
+ including private ones:
50
+
51
+ ```bash
52
+ agent-sdk slack create --dir .
53
+ ```
54
+
55
+ See the [Slack guide](../guides/slack.md).
56
+
57
+ ## First weekly run
58
+
59
+ ```bash
60
+ agent-sdk dev
61
+ ```
62
+
63
+ Schedules never fire under `dev`. Dispatch the same path production
64
+ uses:
65
+
66
+ ```bash
67
+ curl -X POST http://127.0.0.1:3000/v1/dev/schedules/weekly
68
+ ```
69
+
70
+ The playground can run `/queue/run` too.
71
+
72
+ The host writes `week/prs.md`, `week/slack.md`, `week/window.txt`,
73
+ and `week/tree/**.txt` snapshots of the current `AGENTS.md` files,
74
+ then starts a model turn. The
75
+ model calls `apply_agents` once. A skip finishes. An update parks in
76
+ the playground until someone approves; then a draft PR opens against
77
+ the repository default branch. Later updates to the same base stack
78
+ on `agents-md/<base>`. Pull requests from those branches are ignored
79
+ so the follow-up cannot feed the next week.
80
+
81
+ Chat replies stay in the playground. `apply_agents` records a skip,
82
+ or parks the write. Approve there or with
83
+ `POST /v1/session/:id/approvals/:callId`.
84
+
85
+ ## What to edit
86
+
87
+ - `agent/lib/config.ts`: repo and Slack channels
88
+ - `agent/instructions.md`: what counts as an update
89
+ - `evals/agents.eval.ts`: smoke cases
90
+
91
+ ## Evals
92
+
93
+ Four smoke cases: a lint-only week, a billing rule that parks the
94
+ write, the same rule already in `AGENTS.md`, and an empty week.
95
+
96
+ ```bash
97
+ agent-sdk eval
98
+ ```
99
+
100
+ Eval sessions skip the GitHub write.
101
+
102
+ ## Deploy
103
+
104
+ ```bash
105
+ agent-sdk deploy
106
+ ```
107
+
108
+ Run it from the agent's git checkout. The command infers repository,
109
+ ref, path, and slug. Production fires the Monday cron. The deployment
110
+ uses the team's Cursor GitHub connection for the watched repo.
@@ -42,7 +42,7 @@ not on `PATH`, use `npx @cursor/july`.
42
42
  | What you see | What to do |
43
43
  | --- | --- |
44
44
  | `409` on a follow-up message | Refresh the `continuationToken` or confirm the session is a chat session. Task sessions do not accept follow-ups. |
45
- | `409 session_busy` on `call --session` | Wait for the model turn to finish, or omit `--session` for a one-off call. |
45
+ | `409 session_busy` on `call --session` | The tool is a write (or declares no effect) and a model turn is running. Wait for the turn to finish, omit `--session` for a one-off call, or declare `effect: "read"` on a tool that only reads so it runs alongside turns. |
46
46
  | `403` on stream or follow-up | Use the same auth identity that created the session. Off localhost, pass `--bearer-token` and send it on every request. |
47
47
  | Works on localhost; blocked through a tunnel or LAN | Default auth allows only direct loopback callers. Share the host with `--bearer-token <secret>` (or authored `bearerAuth`). Use `--allow-anonymous` only on a trusted private network. |
48
48
  | A channel route fails to compile with a schema type error | `GET` routes need a Zod `querySchema`. `POST` / `PUT` / `PATCH` need a Zod `bodySchema`. Use `z.object({})` or `z.unknown()` for open shapes. |
@@ -70,7 +70,7 @@ not on `PATH`, use `npx @cursor/july`.
70
70
  | What you see | What to do |
71
71
  | --- | --- |
72
72
  | `must be defineConnection({ url, oauth: true })` | The connection file needs `oauth: true`, or you passed the wrong connection name to `agent-sdk mcp oauth`. |
73
- | Local auth works; hosted calls unauthorized | Run `agent-sdk mcp oauth <name> --store`, confirm names with `agent-sdk secrets list <slug>`, then redeploy. |
73
+ | Local auth works; hosted calls unauthorized | Finish Connect on the hosted engine, or run `agent-sdk mcp oauth <name> --store`. Confirm names with `agent-sdk secrets list <slug>`, then redeploy. |
74
74
  | Model asks for `mcp_auth` or IDE MCP for a connector it already has | Attached MCP is behind meta-tools. Set `advertiseTools: true` for named tools on local turns, or call it from a host tool via `ctx.host.mcp`. |
75
75
 
76
76
  See [Host MCP OAuth](./guides/mcp-oauth.md) and
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cursor/july",
3
- "version": "0.1.96",
3
+ "version": "0.1.99",
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": {
@@ -111,7 +111,8 @@ agent-sdk init ./<slug>
111
111
  `subagents/<id>/` (needs `description`), `schedules/`, `hooks/`.
112
112
  Slack: `agent-sdk slack create --dir ./<slug> --name "<Name>"`,
113
113
  not a hand-written channel. Manual Slack app:
114
- `agent-sdk slack init --manual`.
114
+ `agent-sdk slack init --manual` (Slack CLI, or paste at
115
+ api.slack.com).
115
116
  4. `evals/evals.config.ts` with `maxConcurrency: 20` (required;
116
117
  cap 200) plus `evals/**/*.eval.ts`. Assert `t.succeeded()` +
117
118
  `t.calledTool(...)`. API: `skills/evals/SKILL.md`.
@@ -30,8 +30,11 @@ can still call `ctx.host.mcp`.
30
30
  3. **Allow egress** on hosted non-bootstrap hosts:
31
31
  `hosting.egressDomains`.
32
32
  4. **Authorize.** Local: `agent-sdk mcp oauth <name>`. Hosted:
33
- `agent-sdk mcp oauth <name> --store` then `agent-sdk deploy`.
34
- `secrets list` shows the names.
33
+ finish Connect so the current process can retry, then
34
+ `agent-sdk mcp oauth <name> --store` and `agent-sdk deploy` so
35
+ the next pod gets `MCP_OAUTH_*`. `secrets list` shows the names.
36
+ Secrets are deployment-wide, not per caller. `cursorAccount: true`
37
+ stays on the Cursor backend.
35
38
 
36
39
  ```ts
37
40
  // agent/mcp-connections/inventory.ts
@@ -75,7 +78,7 @@ the CLI config directory (`mcp-auth.json` or
75
78
  | `must be defineConnection({ url, oauth: true })` | Wrong name or missing `oauth: true` |
76
79
  | `Unknown MCP connection` | Filename must match the CLI arg |
77
80
  | Callback hang | Free port 8787; finish the browser flow here |
78
- | Hosted 401 | `secrets list`; `--store`; redeploy |
81
+ | Hosted 401 | `secrets list`; Connect or `--store`; redeploy |
79
82
  | Model invents `mcp_auth` / IDE MCP | `advertiseTools: true` on local turns |
80
83
 
81
84
  No raw tokens in git.
@@ -64,28 +64,38 @@ Local serve does not need a hosted engine. Next
64
64
 
65
65
  ## 2. Manual (`slack init --manual`)
66
66
 
67
- Only when they own the app at api.slack.com.
67
+ Only when they own the app. Preferred: Slack CLI
68
+ (`~/.slack/bin/slack`). Paste at api.slack.com if the CLI is
69
+ missing. Never `slack deploy`; Agent SDK serve owns Socket Mode.
68
70
 
69
71
  ```bash
70
72
  agent-sdk slack init --manual --dir . --name "My Agent"
73
+ # --slack-team T0123ABCD when several workspaces are logged in
74
+ # --no-install to scaffold only
71
75
  ```
72
76
 
73
77
  Writes `agent/channels/slack.ts` (`envPrefix` from the directory),
74
- manifests under the project state directory, and `env.example`.
75
- `--channel-posts` subscribes `message.channels` /
76
- `message.groups`.
78
+ manifests, a `.slack/` project (`get-manifest` those JSON files),
79
+ and `env.example`. `--channel-posts` subscribes `message.channels`
80
+ / `message.groups`. If Slack CLI is logged in, this installs the
81
+ app. `--install` fails when that cannot run.
77
82
 
78
83
  Human gates, one at a time. Stop after each.
79
84
 
80
- 1. **Create the app.** Create New App From a manifest. Start
81
- with `manifest.dev.json`.
82
- 2. **Install.** Install to Workspace. Copy the bot token
83
- (`xoxb-...`).
84
- 3. **App token.** Create an app-level token with
85
- `connections:write` (`xapp-...`).
86
- 4. **Write env.** Put both in `.env.local`. Then doctor.
87
-
88
- Repeat for prod with the prod manifest.
85
+ 1. **Install the app.** If `next` starts with "Ask the user to
86
+ install this Slack app", stop and prompt them. Slack CLI: they
87
+ run `slack login --no-prompt`, send `/slackauthticket <ticket>`,
88
+ then `slack login --ticket <ticket> --challenge <code>`, then
89
+ `slack app install --environment local --team <T> --force`.
90
+ Prod: `SLACK_ENV=deployed slack app install --environment
91
+ deployed --team <T> --force`. Fallback: Create New App → From a
92
+ manifest, start with `.slack/manifest.dev.json`.
93
+ 2. **Tokens.** Slack CLI leaves xoxb / xapp in that process only.
94
+ Copy the bot token from the app's OAuth page. Mint an app-level
95
+ token with `connections:write`. Put both in `.env.local` using
96
+ `env.example` names. If Slack CLI wrote `SLACK_*` to `.env`,
97
+ copy those values to the prefixed keys.
98
+ 3. **Doctor.**
89
99
 
90
100
  ## 3. Doctor and smoke
91
101
 
@@ -71,6 +71,7 @@ import {
71
71
  isServeRestartWorker,
72
72
  runEnterRestartSupervisor,
73
73
  } from "../internal/serve-restart.js";
74
+ import { flushSessionRunFatal } from "../internal/session-run-log.js";
74
75
  import { clearTerminal, stdoutPalette } from "../internal/terminal-style.js";
75
76
  import { cmdUpdate, warnIfOutdated } from "../internal/update-check.js";
76
77
  import type { AgentProject, AgentServeHandle } from "../types.js";
@@ -439,6 +440,8 @@ Options:
439
440
  GITHUB_WEBHOOK_SECRET). github: --events overrides the
440
441
  derived webhook event list.
441
442
  --install github: install the cli/gh-webhook extension if missing.
443
+ slack init --manual: require Slack CLI app install.
444
+ --no-install slack init --manual: skip Slack CLI app install.
442
445
  --action github replay: event action (e.g. opened, synchronize).
443
446
  --conclusion github replay: CI conclusion (check_run/suite/status).
444
447
  --comment github replay: comment body for comment events.
@@ -557,6 +560,7 @@ async function main(argv: string[]): Promise<number> {
557
560
  secret: { type: "string" },
558
561
  channel: { type: "string", multiple: true },
559
562
  install: { type: "boolean", default: false },
563
+ "no-install": { type: "boolean", default: false },
560
564
  action: { type: "string" },
561
565
  conclusion: { type: "string" },
562
566
  context: { type: "string" },
@@ -570,6 +574,8 @@ async function main(argv: string[]): Promise<number> {
570
574
  all: { type: "boolean", default: false },
571
575
  "cursor-events-repo": { type: "string", multiple: true },
572
576
  "allow-domain": { type: "string", multiple: true },
577
+ // Hidden Anysphere-only flag; omitted from help.
578
+ "multi-tenant": { type: "boolean", default: false },
573
579
  "from-argv": { type: "boolean", default: false },
574
580
  strict: { type: "boolean", default: false },
575
581
  junit: { type: "string" },
@@ -622,6 +628,8 @@ async function main(argv: string[]): Promise<number> {
622
628
  icon: values.icon,
623
629
  force: values.force,
624
630
  manual: values.manual,
631
+ install: values.install,
632
+ noInstall: values["no-install"],
625
633
  iconSource: positionals[0] === "icon" ? positionals[1] : undefined,
626
634
  });
627
635
  }
@@ -757,6 +765,7 @@ async function main(argv: string[]): Promise<number> {
757
765
  ...(values["allow-domain"] === undefined
758
766
  ? {}
759
767
  : { allowDomains: values["allow-domain"] }),
768
+ multiTenant: values["multi-tenant"] === true,
760
769
  });
761
770
  }
762
771
 
@@ -1717,7 +1726,9 @@ function installTransportErrorGuards(): void {
1717
1726
  process.stderr.write(
1718
1727
  `[agent-sdk] uncaughtException: ${error.stack ?? error.message}\n`
1719
1728
  );
1720
- process.exit(1);
1729
+ void flushSessionRunFatal(error).finally(() => {
1730
+ process.exit(1);
1731
+ });
1721
1732
  });
1722
1733
  }
1723
1734
 
@@ -13,6 +13,7 @@ import {
13
13
  } from "../../internal/continuation-identity.js";
14
14
  import { isDeferredChannelSession } from "../../internal/deferred-channel-session.js";
15
15
  import { isDevMode } from "../../internal/dev-mode.js";
16
+ import { attachHostedAdmissionAdapter } from "../../internal/hosted-admission-adapter.js";
16
17
  import { bindLocalIngressSend } from "../../internal/local-ingress.js";
17
18
  import type {
18
19
  AgentCloudOptions,
@@ -804,6 +805,22 @@ export function githubChannel(
804
805
  ],
805
806
  });
806
807
  githubChannelOptionsByDefinition.set(definition, channelOptions);
808
+ attachHostedAdmissionAdapter(definition, {
809
+ kind: GITHUB_CHANNEL_KIND,
810
+ prepareArgs: withPropagatingGitHubBackgroundErrors,
811
+ dispatch: ({ eventType, payload, deliveryId, args }) =>
812
+ dispatchGitHubWebhook({
813
+ options: channelOptions,
814
+ eventName: eventType,
815
+ payload,
816
+ deliveryId,
817
+ args,
818
+ }),
819
+ getOutcome: (response) => {
820
+ const outcome = getGitHubDispatchOutcome(response);
821
+ return outcome === "skip" || outcome === "task" ? outcome : undefined;
822
+ },
823
+ });
807
824
  if (cursorCredentials !== undefined) {
808
825
  registerGithubCursorAccountRuntime(definition, {
809
826
  options,
@@ -9,8 +9,8 @@
9
9
  * from options first, then the environment: `ORIGIN_APP_ID` (or
10
10
  * `AGENT_SERVE_ORIGIN_APP_ID`), `ORIGIN_APP_INSTALLATION_ID`,
11
11
  * `ORIGIN_APP_PRIVATE_KEY` (PKCS8 PEM for the app's Ed25519 key; literal
12
- * `\n` sequences are normalized), and `ORIGIN_API_BASE_URL` for the public
13
- * REST base.
12
+ * `\n` sequences are normalized), `ORIGIN_API_BASE_URL` for the public REST
13
+ * base, and `ORIGIN_RPC_BASE_URL` for the first-party ConnectRPC base.
14
14
  *
15
15
  * Hosted v2 forks configure none of that: their only credential is the
16
16
  * deployment service account's `CURSOR_API_KEY`, exchanged for a Cursor
@@ -40,6 +40,15 @@ import {
40
40
  */
41
41
  export const DEFAULT_ORIGIN_PUBLIC_API_BASE_URL = "https://api.cursor.com";
42
42
 
43
+ /**
44
+ * Origin's first-party ConnectRPC host (`origin.v1.OriginService`). Separate
45
+ * deployment from {@link DEFAULT_ORIGIN_PUBLIC_API_BASE_URL}: a handful of
46
+ * workflow operations — comment reactions among them — have no
47
+ * `/v1/origin/...` REST binding yet and are only reachable as Connect unary
48
+ * JSON here.
49
+ */
50
+ export const DEFAULT_ORIGIN_RPC_BASE_URL = "https://api.origin.cursor.com";
51
+
43
52
  /** Fixed audience for Origin app JWTs (`APP_TOKEN_AUDIENCE` backend-side). */
44
53
  const ORIGIN_APP_TOKEN_AUDIENCE = "origin-apps";
45
54
  const APP_JWT_TTL_SECONDS = 5 * 60;
@@ -139,6 +148,12 @@ export function originPublicApiBaseUrl(
139
148
  return fromEnv ?? DEFAULT_ORIGIN_PUBLIC_API_BASE_URL;
140
149
  }
141
150
 
151
+ /** Origin ConnectRPC base. Trailing slashes are stripped for path joins. */
152
+ export function originRpcBaseUrl(env: NodeJS.ProcessEnv = process.env): string {
153
+ const fromEnv = envValue(env.ORIGIN_RPC_BASE_URL)?.replace(/\/+$/, "");
154
+ return fromEnv ?? DEFAULT_ORIGIN_RPC_BASE_URL;
155
+ }
156
+
142
157
  function base64UrlJson(value: unknown): string {
143
158
  return Buffer.from(JSON.stringify(value)).toString("base64url");
144
159
  }
@@ -376,9 +391,10 @@ export interface OriginClientOptions {
376
391
  token?: string | OriginTokenProvider;
377
392
  /**
378
393
  * App credentials to mint installation tokens from. Defaults to the
379
- * environment ({@link resolveOriginAppCredentials}).
394
+ * environment ({@link resolveOriginAppCredentials}). Pass `false` to
395
+ * disable app credential lookup and force the Cursor-account exchange.
380
396
  */
381
- credentials?: OriginAppCredentials;
397
+ credentials?: OriginAppCredentials | false;
382
398
  /** Public Origin REST base. Defaults to `ORIGIN_API_BASE_URL` / prod. */
383
399
  apiBaseUrl?: string;
384
400
  /** Injectable fetch for tests. */
@@ -441,7 +457,10 @@ export function createOriginClient(
441
457
  return await options.token();
442
458
  }
443
459
  if (tokenProvider === undefined) {
444
- const credentials = options.credentials ?? resolveOriginAppCredentials();
460
+ const credentials =
461
+ options.credentials === false
462
+ ? undefined
463
+ : (options.credentials ?? resolveOriginAppCredentials());
445
464
  const exchange = options.cursorAccountExchange ?? true;
446
465
  const exchangeOptions =
447
466
  exchange === false ? undefined : exchange === true ? {} : exchange;
@@ -13,6 +13,7 @@ import {
13
13
  createOriginClient,
14
14
  type OriginApiMethod,
15
15
  type OriginClient,
16
+ originRpcBaseUrl,
16
17
  resolveOriginAppCredentialParts,
17
18
  } from "./api.js";
18
19
  import {
@@ -20,6 +21,10 @@ import {
20
21
  type OriginCheck,
21
22
  type OriginCheckCreateInput,
22
23
  } from "./checks.js";
24
+ import {
25
+ type OriginCommentReactionInput,
26
+ setOriginCommentReaction,
27
+ } from "./reactions.js";
23
28
  import type { OriginAppOptions, OriginRepositoryRef } from "./types.js";
24
29
 
25
30
  /** Origin operations exposed to hooks (`ctx.origin`). */
@@ -44,53 +49,77 @@ export interface OriginHandle {
44
49
  createCheck(
45
50
  input: Omit<OriginCheckCreateInput, "origin" | "owner" | "repo">
46
51
  ): Promise<OriginCheck>;
52
+ /**
53
+ * Add or remove one reaction on a PR comment — the Origin analogue of
54
+ * GitHub's `thread.react("eyes")`. Needs
55
+ * `repository:pull_requests:reviews:write`. Reactions have no REST
56
+ * binding, so this call goes to Origin's ConnectRPC host rather than the
57
+ * public API base {@link request} uses.
58
+ */
59
+ reactToComment(input: OriginCommentReactionInput): Promise<void>;
47
60
  }
48
61
 
49
62
  export function buildOriginBinding(input: {
50
63
  repository: OriginRepositoryRef;
51
64
  /** Installation id from the delivery envelope, when present. */
52
65
  installationId?: string;
66
+ /** Force the signed-in Cursor account / deployment SA credential path. */
67
+ cursorAccount?: boolean;
53
68
  /** Channel-authored outbound app credentials / API base. */
54
69
  app?: OriginAppOptions;
55
70
  /** Injectable fetch for tests. */
56
71
  fetch?: typeof fetch;
57
72
  }): OriginHandle {
58
- let client: OriginClient | undefined;
59
- const getClient = (): OriginClient => {
60
- if (client === undefined) {
61
- const fromEnv = resolveOriginAppCredentialParts();
62
- const appId = input.app?.appId ?? fromEnv.appId;
63
- const installationId =
64
- input.app?.installationId ??
65
- input.installationId ??
66
- fromEnv.installationId;
67
- const privateKey = input.app?.privateKey ?? fromEnv.privateKey;
68
- const credentials =
69
- appId !== undefined &&
70
- installationId !== undefined &&
71
- privateKey !== undefined
72
- ? { appId, installationId, privateKey }
73
- : undefined;
74
- client = createOriginClient({
75
- token: input.app?.token,
76
- credentials,
77
- apiBaseUrl: input.app?.apiBaseUrl,
78
- fetch: input.fetch,
79
- });
80
- }
81
- return client;
73
+ const buildClient = (apiBaseUrl: string | undefined): OriginClient => {
74
+ const fromEnv = input.cursorAccount
75
+ ? {}
76
+ : resolveOriginAppCredentialParts();
77
+ const appId = input.app?.appId ?? fromEnv.appId;
78
+ const installationId =
79
+ input.app?.installationId ??
80
+ input.installationId ??
81
+ fromEnv.installationId;
82
+ const privateKey = input.app?.privateKey ?? fromEnv.privateKey;
83
+ const credentials =
84
+ appId !== undefined &&
85
+ installationId !== undefined &&
86
+ privateKey !== undefined
87
+ ? { appId, installationId, privateKey }
88
+ : undefined;
89
+ return createOriginClient({
90
+ token: input.cursorAccount ? undefined : input.app?.token,
91
+ credentials: input.cursorAccount ? false : credentials,
92
+ apiBaseUrl,
93
+ fetch: input.fetch,
94
+ });
95
+ };
96
+
97
+ // Public REST and ConnectRPC are separate Origin deployments, so the
98
+ // handle keeps a client per host. Both stay lazy: a hook that touches
99
+ // neither needs no credential.
100
+ let restClient: OriginClient | undefined;
101
+ const getRestClient = (): OriginClient => {
102
+ restClient ??= buildClient(input.app?.apiBaseUrl);
103
+ return restClient;
104
+ };
105
+ let rpcClient: OriginClient | undefined;
106
+ const getRpcClient = (): OriginClient => {
107
+ rpcClient ??= buildClient(input.app?.rpcBaseUrl ?? originRpcBaseUrl());
108
+ return rpcClient;
82
109
  };
83
110
 
84
111
  return {
85
112
  installationId: input.app?.installationId ?? input.installationId,
86
113
  repository: input.repository,
87
- request: (request) => getClient().request(request),
114
+ request: (request) => getRestClient().request(request),
88
115
  createCheck: (check) =>
89
116
  createOriginCheck({
90
117
  ...check,
91
- origin: getClient(),
118
+ origin: getRestClient(),
92
119
  owner: input.repository.owner,
93
120
  repo: input.repository.name,
94
121
  }),
122
+ reactToComment: (reaction) =>
123
+ setOriginCommentReaction({ ...reaction, origin: getRpcClient() }),
95
124
  };
96
125
  }
@@ -29,4 +29,5 @@ export * from "./cursor-account.js";
29
29
  export * from "./events.js";
30
30
  export * from "./origin-channel.js";
31
31
  export * from "./origin-webhook.js";
32
+ export * from "./reactions.js";
32
33
  export * from "./types.js";