@cursor/july 0.1.1

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 (623) hide show
  1. package/AGENTS.md +290 -0
  2. package/LICENSE.md +3 -0
  3. package/README.md +1233 -0
  4. package/dist/ab.d.ts +290 -0
  5. package/dist/ab.d.ts.map +1 -0
  6. package/dist/ab.js +386 -0
  7. package/dist/bin/agent-serve.d.ts +15 -0
  8. package/dist/bin/agent-serve.d.ts.map +1 -0
  9. package/dist/bin/agent-serve.js +754 -0
  10. package/dist/channels/github/api.d.ts +101 -0
  11. package/dist/channels/github/api.d.ts.map +1 -0
  12. package/dist/channels/github/api.js +229 -0
  13. package/dist/channels/github/auth.d.ts +67 -0
  14. package/dist/channels/github/auth.d.ts.map +1 -0
  15. package/dist/channels/github/auth.js +239 -0
  16. package/dist/channels/github/binding.d.ts +73 -0
  17. package/dist/channels/github/binding.d.ts.map +1 -0
  18. package/dist/channels/github/binding.js +114 -0
  19. package/dist/channels/github/defaults.d.ts +24 -0
  20. package/dist/channels/github/defaults.d.ts.map +1 -0
  21. package/dist/channels/github/defaults.js +100 -0
  22. package/dist/channels/github/events.d.ts +18 -0
  23. package/dist/channels/github/events.d.ts.map +1 -0
  24. package/dist/channels/github/events.js +59 -0
  25. package/dist/channels/github/forward.d.ts +137 -0
  26. package/dist/channels/github/forward.d.ts.map +1 -0
  27. package/dist/channels/github/forward.js +271 -0
  28. package/dist/channels/github/github-channel.d.ts +127 -0
  29. package/dist/channels/github/github-channel.d.ts.map +1 -0
  30. package/dist/channels/github/github-channel.js +1688 -0
  31. package/dist/channels/github/index.d.ts +52 -0
  32. package/dist/channels/github/index.d.ts.map +1 -0
  33. package/dist/channels/github/index.js +51 -0
  34. package/dist/channels/github/replay.d.ts +115 -0
  35. package/dist/channels/github/replay.d.ts.map +1 -0
  36. package/dist/channels/github/replay.js +282 -0
  37. package/dist/channels/github/state.d.ts +26 -0
  38. package/dist/channels/github/state.d.ts.map +1 -0
  39. package/dist/channels/github/state.js +50 -0
  40. package/dist/channels/github/types.d.ts +385 -0
  41. package/dist/channels/github/types.d.ts.map +1 -0
  42. package/dist/channels/github/types.js +1 -0
  43. package/dist/channels/slack/api.d.ts +117 -0
  44. package/dist/channels/slack/api.d.ts.map +1 -0
  45. package/dist/channels/slack/api.js +437 -0
  46. package/dist/channels/slack/approvals.d.ts +32 -0
  47. package/dist/channels/slack/approvals.d.ts.map +1 -0
  48. package/dist/channels/slack/approvals.js +157 -0
  49. package/dist/channels/slack/assistant.d.ts +23 -0
  50. package/dist/channels/slack/assistant.d.ts.map +1 -0
  51. package/dist/channels/slack/assistant.js +67 -0
  52. package/dist/channels/slack/auth.d.ts +40 -0
  53. package/dist/channels/slack/auth.d.ts.map +1 -0
  54. package/dist/channels/slack/auth.js +71 -0
  55. package/dist/channels/slack/channel-watch.d.ts +46 -0
  56. package/dist/channels/slack/channel-watch.d.ts.map +1 -0
  57. package/dist/channels/slack/channel-watch.js +180 -0
  58. package/dist/channels/slack/constants.d.ts +17 -0
  59. package/dist/channels/slack/constants.d.ts.map +1 -0
  60. package/dist/channels/slack/constants.js +27 -0
  61. package/dist/channels/slack/credentials.d.ts +35 -0
  62. package/dist/channels/slack/credentials.d.ts.map +1 -0
  63. package/dist/channels/slack/credentials.js +88 -0
  64. package/dist/channels/slack/cursor-account.d.ts +76 -0
  65. package/dist/channels/slack/cursor-account.d.ts.map +1 -0
  66. package/dist/channels/slack/cursor-account.js +88 -0
  67. package/dist/channels/slack/defaults.d.ts +32 -0
  68. package/dist/channels/slack/defaults.d.ts.map +1 -0
  69. package/dist/channels/slack/defaults.js +380 -0
  70. package/dist/channels/slack/dispatch.d.ts +43 -0
  71. package/dist/channels/slack/dispatch.d.ts.map +1 -0
  72. package/dist/channels/slack/dispatch.js +185 -0
  73. package/dist/channels/slack/doctor.d.ts +24 -0
  74. package/dist/channels/slack/doctor.d.ts.map +1 -0
  75. package/dist/channels/slack/doctor.js +115 -0
  76. package/dist/channels/slack/event-id-dedupe.d.ts +10 -0
  77. package/dist/channels/slack/event-id-dedupe.d.ts.map +1 -0
  78. package/dist/channels/slack/event-id-dedupe.js +23 -0
  79. package/dist/channels/slack/inbound.d.ts +41 -0
  80. package/dist/channels/slack/inbound.d.ts.map +1 -0
  81. package/dist/channels/slack/inbound.js +166 -0
  82. package/dist/channels/slack/index.d.ts +45 -0
  83. package/dist/channels/slack/index.d.ts.map +1 -0
  84. package/dist/channels/slack/index.js +44 -0
  85. package/dist/channels/slack/init.d.ts +32 -0
  86. package/dist/channels/slack/init.d.ts.map +1 -0
  87. package/dist/channels/slack/init.js +82 -0
  88. package/dist/channels/slack/interactive.d.ts +19 -0
  89. package/dist/channels/slack/interactive.d.ts.map +1 -0
  90. package/dist/channels/slack/interactive.js +142 -0
  91. package/dist/channels/slack/links.d.ts +10 -0
  92. package/dist/channels/slack/links.d.ts.map +1 -0
  93. package/dist/channels/slack/links.js +19 -0
  94. package/dist/channels/slack/live-delivery.d.ts +75 -0
  95. package/dist/channels/slack/live-delivery.d.ts.map +1 -0
  96. package/dist/channels/slack/live-delivery.js +143 -0
  97. package/dist/channels/slack/log.d.ts +25 -0
  98. package/dist/channels/slack/log.d.ts.map +1 -0
  99. package/dist/channels/slack/log.js +47 -0
  100. package/dist/channels/slack/manifest.d.ts +57 -0
  101. package/dist/channels/slack/manifest.d.ts.map +1 -0
  102. package/dist/channels/slack/manifest.js +110 -0
  103. package/dist/channels/slack/pr-ref.d.ts +18 -0
  104. package/dist/channels/slack/pr-ref.d.ts.map +1 -0
  105. package/dist/channels/slack/pr-ref.js +36 -0
  106. package/dist/channels/slack/setup.d.ts +14 -0
  107. package/dist/channels/slack/setup.d.ts.map +1 -0
  108. package/dist/channels/slack/setup.js +86 -0
  109. package/dist/channels/slack/slack-channel.d.ts +15 -0
  110. package/dist/channels/slack/slack-channel.d.ts.map +1 -0
  111. package/dist/channels/slack/slack-channel.js +281 -0
  112. package/dist/channels/slack/socket-mode.d.ts +26 -0
  113. package/dist/channels/slack/socket-mode.d.ts.map +1 -0
  114. package/dist/channels/slack/socket-mode.js +116 -0
  115. package/dist/channels/slack/stream.d.ts +26 -0
  116. package/dist/channels/slack/stream.d.ts.map +1 -0
  117. package/dist/channels/slack/stream.js +39 -0
  118. package/dist/channels/slack/tool-approval-events.d.ts +33 -0
  119. package/dist/channels/slack/tool-approval-events.d.ts.map +1 -0
  120. package/dist/channels/slack/tool-approval-events.js +129 -0
  121. package/dist/channels/slack/types.d.ts +326 -0
  122. package/dist/channels/slack/types.d.ts.map +1 -0
  123. package/dist/channels/slack/types.js +4 -0
  124. package/dist/channels.d.ts +116 -0
  125. package/dist/channels.d.ts.map +1 -0
  126. package/dist/channels.js +294 -0
  127. package/dist/connections.d.ts +75 -0
  128. package/dist/connections.d.ts.map +1 -0
  129. package/dist/connections.js +75 -0
  130. package/dist/docs/404.html +22 -0
  131. package/dist/docs/ab.html +87 -0
  132. package/dist/docs/assets/ab.md.COdXkces.js +63 -0
  133. package/dist/docs/assets/ab.md.COdXkces.lean.js +1 -0
  134. package/dist/docs/assets/app.DqfFEmJd.js +1 -0
  135. package/dist/docs/assets/building-with-agents.md.CJCtZCyi.js +13 -0
  136. package/dist/docs/assets/building-with-agents.md.CJCtZCyi.lean.js +1 -0
  137. package/dist/docs/assets/chunks/@localSearchIndexroot.CcVk1uKq.js +1 -0
  138. package/dist/docs/assets/chunks/VPLocalSearchBox.BaLEdS15.js +9 -0
  139. package/dist/docs/assets/chunks/framework.CAZyNGu9.js +19 -0
  140. package/dist/docs/assets/chunks/theme.CZRvu_0q.js +2 -0
  141. package/dist/docs/assets/concepts.md.Cfb9b-k1.js +4 -0
  142. package/dist/docs/assets/concepts.md.Cfb9b-k1.lean.js +1 -0
  143. package/dist/docs/assets/deployment.md.Dx1TYNk5.js +14 -0
  144. package/dist/docs/assets/deployment.md.Dx1TYNk5.lean.js +1 -0
  145. package/dist/docs/assets/evals.md.DPZ_MAnI.js +85 -0
  146. package/dist/docs/assets/evals.md.DPZ_MAnI.lean.js +1 -0
  147. package/dist/docs/assets/guides_agent-to-agent.md.CrtrsySy.js +10 -0
  148. package/dist/docs/assets/guides_agent-to-agent.md.CrtrsySy.lean.js +1 -0
  149. package/dist/docs/assets/guides_cloud-runtime.md.CYlNMTNp.js +9 -0
  150. package/dist/docs/assets/guides_cloud-runtime.md.CYlNMTNp.lean.js +1 -0
  151. package/dist/docs/assets/guides_github.md.DwbKhCeS.js +20 -0
  152. package/dist/docs/assets/guides_github.md.DwbKhCeS.lean.js +1 -0
  153. package/dist/docs/assets/guides_human-in-the-loop.md.Dvuctx7s.js +28 -0
  154. package/dist/docs/assets/guides_human-in-the-loop.md.Dvuctx7s.lean.js +1 -0
  155. package/dist/docs/assets/guides_slack.md.bv41fHfW.js +37 -0
  156. package/dist/docs/assets/guides_slack.md.bv41fHfW.lean.js +1 -0
  157. package/dist/docs/assets/guides_webhooks.md.hFTik3lf.js +50 -0
  158. package/dist/docs/assets/guides_webhooks.md.hFTik3lf.lean.js +1 -0
  159. package/dist/docs/assets/hillclimbing.md.DHNast08.js +4 -0
  160. package/dist/docs/assets/hillclimbing.md.DHNast08.lean.js +1 -0
  161. package/dist/docs/assets/index.md.BPKcj5AI.js +20 -0
  162. package/dist/docs/assets/index.md.BPKcj5AI.lean.js +1 -0
  163. package/dist/docs/assets/inter-italic-cyrillic-ext.r48I6akx.woff2 +0 -0
  164. package/dist/docs/assets/inter-italic-cyrillic.By2_1cv3.woff2 +0 -0
  165. package/dist/docs/assets/inter-italic-greek-ext.1u6EdAuj.woff2 +0 -0
  166. package/dist/docs/assets/inter-italic-greek.DJ8dCoTZ.woff2 +0 -0
  167. package/dist/docs/assets/inter-italic-latin-ext.CN1xVJS-.woff2 +0 -0
  168. package/dist/docs/assets/inter-italic-latin.C2AdPX0b.woff2 +0 -0
  169. package/dist/docs/assets/inter-italic-vietnamese.BSbpV94h.woff2 +0 -0
  170. package/dist/docs/assets/inter-roman-cyrillic-ext.BBPuwvHQ.woff2 +0 -0
  171. package/dist/docs/assets/inter-roman-cyrillic.C5lxZ8CY.woff2 +0 -0
  172. package/dist/docs/assets/inter-roman-greek-ext.CqjqNYQ-.woff2 +0 -0
  173. package/dist/docs/assets/inter-roman-greek.BBVDIX6e.woff2 +0 -0
  174. package/dist/docs/assets/inter-roman-latin-ext.4ZJIpNVo.woff2 +0 -0
  175. package/dist/docs/assets/inter-roman-latin.Di8DUHzh.woff2 +0 -0
  176. package/dist/docs/assets/inter-roman-vietnamese.BjW4sHH5.woff2 +0 -0
  177. package/dist/docs/assets/quickstart.md.tVPiGK_L.js +35 -0
  178. package/dist/docs/assets/quickstart.md.tVPiGK_L.lean.js +1 -0
  179. package/dist/docs/assets/reference_agent-config.md.Bpd7HQwf.js +34 -0
  180. package/dist/docs/assets/reference_agent-config.md.Bpd7HQwf.lean.js +1 -0
  181. package/dist/docs/assets/reference_channels.md.D7JTR03W.js +53 -0
  182. package/dist/docs/assets/reference_channels.md.D7JTR03W.lean.js +1 -0
  183. package/dist/docs/assets/reference_cli.md.DA730zCu.js +33 -0
  184. package/dist/docs/assets/reference_cli.md.DA730zCu.lean.js +1 -0
  185. package/dist/docs/assets/reference_connections.md.C3vNH_DE.js +26 -0
  186. package/dist/docs/assets/reference_connections.md.C3vNH_DE.lean.js +1 -0
  187. package/dist/docs/assets/reference_hooks.md.BCEc3MyM.js +12 -0
  188. package/dist/docs/assets/reference_hooks.md.BCEc3MyM.lean.js +1 -0
  189. package/dist/docs/assets/reference_http-api.md.DBAahtdz.js +11 -0
  190. package/dist/docs/assets/reference_http-api.md.DBAahtdz.lean.js +1 -0
  191. package/dist/docs/assets/reference_instructions.md.BC05LEQ8.js +12 -0
  192. package/dist/docs/assets/reference_instructions.md.BC05LEQ8.lean.js +1 -0
  193. package/dist/docs/assets/reference_playground.md.CPZhfYaO.js +1 -0
  194. package/dist/docs/assets/reference_playground.md.CPZhfYaO.lean.js +1 -0
  195. package/dist/docs/assets/reference_project-layout.md.Bd_CKtNS.js +31 -0
  196. package/dist/docs/assets/reference_project-layout.md.Bd_CKtNS.lean.js +1 -0
  197. package/dist/docs/assets/reference_schedules.md.D7qijxLk.js +82 -0
  198. package/dist/docs/assets/reference_schedules.md.D7qijxLk.lean.js +1 -0
  199. package/dist/docs/assets/reference_sessions.md.DdjWabnN.js +8 -0
  200. package/dist/docs/assets/reference_sessions.md.DdjWabnN.lean.js +1 -0
  201. package/dist/docs/assets/reference_skills.md.VQnlBT3Q.js +15 -0
  202. package/dist/docs/assets/reference_skills.md.VQnlBT3Q.lean.js +1 -0
  203. package/dist/docs/assets/reference_subagents.md.CIRAVcPK.js +10 -0
  204. package/dist/docs/assets/reference_subagents.md.CIRAVcPK.lean.js +1 -0
  205. package/dist/docs/assets/reference_tools.md.DF5kwlt0.js +46 -0
  206. package/dist/docs/assets/reference_tools.md.DF5kwlt0.lean.js +1 -0
  207. package/dist/docs/assets/scaffolding-agents.md.CyYfWGdc.js +1 -0
  208. package/dist/docs/assets/scaffolding-agents.md.CyYfWGdc.lean.js +1 -0
  209. package/dist/docs/assets/style.Bj-IXa5W.css +1 -0
  210. package/dist/docs/assets/troubleshooting.md.DkovjS7h.js +1 -0
  211. package/dist/docs/assets/troubleshooting.md.DkovjS7h.lean.js +1 -0
  212. package/dist/docs/building-with-agents.html +37 -0
  213. package/dist/docs/concepts.html +28 -0
  214. package/dist/docs/deployment.html +38 -0
  215. package/dist/docs/evals.html +109 -0
  216. package/dist/docs/guides/agent-to-agent.html +34 -0
  217. package/dist/docs/guides/cloud-runtime.html +33 -0
  218. package/dist/docs/guides/github.html +44 -0
  219. package/dist/docs/guides/human-in-the-loop.html +52 -0
  220. package/dist/docs/guides/slack.html +61 -0
  221. package/dist/docs/guides/webhooks.html +74 -0
  222. package/dist/docs/hashmap.json +1 -0
  223. package/dist/docs/hillclimbing.html +28 -0
  224. package/dist/docs/index.html +44 -0
  225. package/dist/docs/quickstart.html +59 -0
  226. package/dist/docs/reference/agent-config.html +58 -0
  227. package/dist/docs/reference/channels.html +77 -0
  228. package/dist/docs/reference/cli.html +57 -0
  229. package/dist/docs/reference/connections.html +50 -0
  230. package/dist/docs/reference/hooks.html +36 -0
  231. package/dist/docs/reference/http-api.html +35 -0
  232. package/dist/docs/reference/instructions.html +36 -0
  233. package/dist/docs/reference/playground.html +25 -0
  234. package/dist/docs/reference/project-layout.html +55 -0
  235. package/dist/docs/reference/schedules.html +106 -0
  236. package/dist/docs/reference/sessions.html +32 -0
  237. package/dist/docs/reference/skills.html +39 -0
  238. package/dist/docs/reference/subagents.html +34 -0
  239. package/dist/docs/reference/tools.html +70 -0
  240. package/dist/docs/scaffolding-agents.html +25 -0
  241. package/dist/docs/troubleshooting.html +25 -0
  242. package/dist/docs/vp-icons.css +0 -0
  243. package/dist/evals.d.ts +312 -0
  244. package/dist/evals.d.ts.map +1 -0
  245. package/dist/evals.js +254 -0
  246. package/dist/hooks.d.ts +23 -0
  247. package/dist/hooks.d.ts.map +1 -0
  248. package/dist/hooks.js +23 -0
  249. package/dist/index.d.ts +71 -0
  250. package/dist/index.d.ts.map +1 -0
  251. package/dist/index.js +101 -0
  252. package/dist/internal/ab-collector.d.ts +42 -0
  253. package/dist/internal/ab-collector.d.ts.map +1 -0
  254. package/dist/internal/ab-collector.js +153 -0
  255. package/dist/internal/ab-fold.d.ts +36 -0
  256. package/dist/internal/ab-fold.d.ts.map +1 -0
  257. package/dist/internal/ab-fold.js +171 -0
  258. package/dist/internal/ab-snapshot.d.ts +70 -0
  259. package/dist/internal/ab-snapshot.d.ts.map +1 -0
  260. package/dist/internal/ab-snapshot.js +208 -0
  261. package/dist/internal/approval-gate.d.ts +34 -0
  262. package/dist/internal/approval-gate.d.ts.map +1 -0
  263. package/dist/internal/approval-gate.js +85 -0
  264. package/dist/internal/auth.d.ts +8 -0
  265. package/dist/internal/auth.d.ts.map +1 -0
  266. package/dist/internal/auth.js +27 -0
  267. package/dist/internal/authored-alias-hooks.d.ts +31 -0
  268. package/dist/internal/authored-alias-hooks.d.ts.map +1 -0
  269. package/dist/internal/authored-alias-hooks.js +43 -0
  270. package/dist/internal/authored-loaders.d.ts +25 -0
  271. package/dist/internal/authored-loaders.d.ts.map +1 -0
  272. package/dist/internal/authored-loaders.js +129 -0
  273. package/dist/internal/bounded-int.d.ts +11 -0
  274. package/dist/internal/bounded-int.d.ts.map +1 -0
  275. package/dist/internal/bounded-int.js +13 -0
  276. package/dist/internal/brand.d.ts +6 -0
  277. package/dist/internal/brand.d.ts.map +1 -0
  278. package/dist/internal/brand.js +17 -0
  279. package/dist/internal/chat-client.d.ts +19 -0
  280. package/dist/internal/chat-client.d.ts.map +1 -0
  281. package/dist/internal/chat-client.js +327 -0
  282. package/dist/internal/cli-ax.d.ts +58 -0
  283. package/dist/internal/cli-ax.d.ts.map +1 -0
  284. package/dist/internal/cli-ax.js +345 -0
  285. package/dist/internal/cli-cursor.d.ts +20 -0
  286. package/dist/internal/cli-cursor.d.ts.map +1 -0
  287. package/dist/internal/cli-cursor.js +227 -0
  288. package/dist/internal/cli-github.d.ts +47 -0
  289. package/dist/internal/cli-github.d.ts.map +1 -0
  290. package/dist/internal/cli-github.js +644 -0
  291. package/dist/internal/cli-slack.d.ts +18 -0
  292. package/dist/internal/cli-slack.d.ts.map +1 -0
  293. package/dist/internal/cli-slack.js +144 -0
  294. package/dist/internal/cloud-merge.d.ts +23 -0
  295. package/dist/internal/cloud-merge.d.ts.map +1 -0
  296. package/dist/internal/cloud-merge.js +28 -0
  297. package/dist/internal/cron.d.ts +17 -0
  298. package/dist/internal/cron.d.ts.map +1 -0
  299. package/dist/internal/cron.js +60 -0
  300. package/dist/internal/cursor/account-mcp.d.ts +95 -0
  301. package/dist/internal/cursor/account-mcp.d.ts.map +1 -0
  302. package/dist/internal/cursor/account-mcp.js +342 -0
  303. package/dist/internal/cursor/backend-client.d.ts +118 -0
  304. package/dist/internal/cursor/backend-client.d.ts.map +1 -0
  305. package/dist/internal/cursor/backend-client.js +477 -0
  306. package/dist/internal/cursor/credentials.d.ts +112 -0
  307. package/dist/internal/cursor/credentials.d.ts.map +1 -0
  308. package/dist/internal/cursor/credentials.js +329 -0
  309. package/dist/internal/cursor-event-relay.d.ts +111 -0
  310. package/dist/internal/cursor-event-relay.d.ts.map +1 -0
  311. package/dist/internal/cursor-event-relay.js +181 -0
  312. package/dist/internal/cursor-relay-core.d.ts +113 -0
  313. package/dist/internal/cursor-relay-core.d.ts.map +1 -0
  314. package/dist/internal/cursor-relay-core.js +364 -0
  315. package/dist/internal/cursor-slack-relay.d.ts +94 -0
  316. package/dist/internal/cursor-slack-relay.d.ts.map +1 -0
  317. package/dist/internal/cursor-slack-relay.js +171 -0
  318. package/dist/internal/describe-error.d.ts +3 -0
  319. package/dist/internal/describe-error.d.ts.map +1 -0
  320. package/dist/internal/describe-error.js +4 -0
  321. package/dist/internal/dev-mode.d.ts +13 -0
  322. package/dist/internal/dev-mode.d.ts.map +1 -0
  323. package/dist/internal/dev-mode.js +17 -0
  324. package/dist/internal/discovery.d.ts +55 -0
  325. package/dist/internal/discovery.d.ts.map +1 -0
  326. package/dist/internal/discovery.js +1427 -0
  327. package/dist/internal/distribution.d.ts +47 -0
  328. package/dist/internal/distribution.d.ts.map +1 -0
  329. package/dist/internal/distribution.js +82 -0
  330. package/dist/internal/docs-site.d.ts +28 -0
  331. package/dist/internal/docs-site.d.ts.map +1 -0
  332. package/dist/internal/docs-site.js +169 -0
  333. package/dist/internal/duration.d.ts +8 -0
  334. package/dist/internal/duration.d.ts.map +1 -0
  335. package/dist/internal/duration.js +35 -0
  336. package/dist/internal/eval-run-store.d.ts +81 -0
  337. package/dist/internal/eval-run-store.d.ts.map +1 -0
  338. package/dist/internal/eval-run-store.js +396 -0
  339. package/dist/internal/eval-runner.d.ts +76 -0
  340. package/dist/internal/eval-runner.d.ts.map +1 -0
  341. package/dist/internal/eval-runner.js +336 -0
  342. package/dist/internal/event-log.d.ts +51 -0
  343. package/dist/internal/event-log.d.ts.map +1 -0
  344. package/dist/internal/event-log.js +167 -0
  345. package/dist/internal/event-mapper.d.ts +46 -0
  346. package/dist/internal/event-mapper.d.ts.map +1 -0
  347. package/dist/internal/event-mapper.js +226 -0
  348. package/dist/internal/frontmatter.d.ts +12 -0
  349. package/dist/internal/frontmatter.d.ts.map +1 -0
  350. package/dist/internal/frontmatter.js +61 -0
  351. package/dist/internal/github-fanout.d.ts +32 -0
  352. package/dist/internal/github-fanout.d.ts.map +1 -0
  353. package/dist/internal/github-fanout.js +122 -0
  354. package/dist/internal/handleAgentServeTrigger.d.ts +59 -0
  355. package/dist/internal/handleAgentServeTrigger.d.ts.map +1 -0
  356. package/dist/internal/handleAgentServeTrigger.js +115 -0
  357. package/dist/internal/host-platforms.d.ts +40 -0
  358. package/dist/internal/host-platforms.d.ts.map +1 -0
  359. package/dist/internal/host-platforms.js +113 -0
  360. package/dist/internal/http-channel.d.ts +54 -0
  361. package/dist/internal/http-channel.d.ts.map +1 -0
  362. package/dist/internal/http-channel.js +382 -0
  363. package/dist/internal/ids.d.ts +19 -0
  364. package/dist/internal/ids.d.ts.map +1 -0
  365. package/dist/internal/ids.js +34 -0
  366. package/dist/internal/init-project.d.ts +22 -0
  367. package/dist/internal/init-project.d.ts.map +1 -0
  368. package/dist/internal/init-project.js +125 -0
  369. package/dist/internal/json-dir-store.d.ts +32 -0
  370. package/dist/internal/json-dir-store.d.ts.map +1 -0
  371. package/dist/internal/json-dir-store.js +100 -0
  372. package/dist/internal/json-schema.d.ts +18 -0
  373. package/dist/internal/json-schema.d.ts.map +1 -0
  374. package/dist/internal/json-schema.js +53 -0
  375. package/dist/internal/log-ring.d.ts +23 -0
  376. package/dist/internal/log-ring.d.ts.map +1 -0
  377. package/dist/internal/log-ring.js +42 -0
  378. package/dist/internal/map-pool.d.ts +6 -0
  379. package/dist/internal/map-pool.d.ts.map +1 -0
  380. package/dist/internal/map-pool.js +41 -0
  381. package/dist/internal/mcp-endpoint.d.ts +59 -0
  382. package/dist/internal/mcp-endpoint.d.ts.map +1 -0
  383. package/dist/internal/mcp-endpoint.js +355 -0
  384. package/dist/internal/mcp-host.d.ts +28 -0
  385. package/dist/internal/mcp-host.d.ts.map +1 -0
  386. package/dist/internal/mcp-host.js +162 -0
  387. package/dist/internal/net.d.ts +5 -0
  388. package/dist/internal/net.d.ts.map +1 -0
  389. package/dist/internal/net.js +30 -0
  390. package/dist/internal/peer-connections.d.ts +44 -0
  391. package/dist/internal/peer-connections.d.ts.map +1 -0
  392. package/dist/internal/peer-connections.js +67 -0
  393. package/dist/internal/playground/static.d.ts +35 -0
  394. package/dist/internal/playground/static.d.ts.map +1 -0
  395. package/dist/internal/playground/static.js +162 -0
  396. package/dist/internal/playground/toolchain.d.ts +57 -0
  397. package/dist/internal/playground/toolchain.d.ts.map +1 -0
  398. package/dist/internal/playground/toolchain.js +226 -0
  399. package/dist/internal/reminder-runner.d.ts +62 -0
  400. package/dist/internal/reminder-runner.d.ts.map +1 -0
  401. package/dist/internal/reminder-runner.js +582 -0
  402. package/dist/internal/reminder-schedule.d.ts +22 -0
  403. package/dist/internal/reminder-schedule.d.ts.map +1 -0
  404. package/dist/internal/reminder-schedule.js +82 -0
  405. package/dist/internal/reminder-store.d.ts +58 -0
  406. package/dist/internal/reminder-store.d.ts.map +1 -0
  407. package/dist/internal/reminder-store.js +106 -0
  408. package/dist/internal/resolved-connections.d.ts +41 -0
  409. package/dist/internal/resolved-connections.d.ts.map +1 -0
  410. package/dist/internal/resolved-connections.js +73 -0
  411. package/dist/internal/review-comments.d.ts +50 -0
  412. package/dist/internal/review-comments.d.ts.map +1 -0
  413. package/dist/internal/review-comments.js +194 -0
  414. package/dist/internal/router.d.ts +33 -0
  415. package/dist/internal/router.d.ts.map +1 -0
  416. package/dist/internal/router.js +93 -0
  417. package/dist/internal/run-client.d.ts +49 -0
  418. package/dist/internal/run-client.d.ts.map +1 -0
  419. package/dist/internal/run-client.js +208 -0
  420. package/dist/internal/schedule-runner.d.ts +31 -0
  421. package/dist/internal/schedule-runner.d.ts.map +1 -0
  422. package/dist/internal/schedule-runner.js +126 -0
  423. package/dist/internal/sdk-runner.d.ts +41 -0
  424. package/dist/internal/sdk-runner.d.ts.map +1 -0
  425. package/dist/internal/sdk-runner.js +221 -0
  426. package/dist/internal/server.d.ts +25 -0
  427. package/dist/internal/server.d.ts.map +1 -0
  428. package/dist/internal/server.js +1374 -0
  429. package/dist/internal/session-engine.d.ts +287 -0
  430. package/dist/internal/session-engine.d.ts.map +1 -0
  431. package/dist/internal/session-engine.js +1377 -0
  432. package/dist/internal/session-store.d.ts +29 -0
  433. package/dist/internal/session-store.d.ts.map +1 -0
  434. package/dist/internal/session-store.js +140 -0
  435. package/dist/internal/session-urls.d.ts +10 -0
  436. package/dist/internal/session-urls.d.ts.map +1 -0
  437. package/dist/internal/session-urls.js +25 -0
  438. package/dist/internal/stream-progress.d.ts +14 -0
  439. package/dist/internal/stream-progress.d.ts.map +1 -0
  440. package/dist/internal/stream-progress.js +195 -0
  441. package/dist/internal/tool-result.d.ts +20 -0
  442. package/dist/internal/tool-result.d.ts.map +1 -0
  443. package/dist/internal/tool-result.js +45 -0
  444. package/dist/internal/trajectory.d.ts +56 -0
  445. package/dist/internal/trajectory.d.ts.map +1 -0
  446. package/dist/internal/trajectory.js +248 -0
  447. package/dist/internal/workspace.d.ts +42 -0
  448. package/dist/internal/workspace.d.ts.map +1 -0
  449. package/dist/internal/workspace.js +199 -0
  450. package/dist/playground/assets/cursor-icons-outline-oY2V_mvK.woff2 +0 -0
  451. package/dist/playground/assets/index-1K-hG-7p.css +1 -0
  452. package/dist/playground/assets/index-FlWjhg3x.js +79 -0
  453. package/dist/playground/index.html +17 -0
  454. package/dist/reminders.d.ts +23 -0
  455. package/dist/reminders.d.ts.map +1 -0
  456. package/dist/reminders.js +22 -0
  457. package/dist/schedules.d.ts +23 -0
  458. package/dist/schedules.d.ts.map +1 -0
  459. package/dist/schedules.js +26 -0
  460. package/dist/skills.d.ts +22 -0
  461. package/dist/skills.d.ts.map +1 -0
  462. package/dist/skills.js +22 -0
  463. package/dist/tools.d.ts +92 -0
  464. package/dist/tools.d.ts.map +1 -0
  465. package/dist/tools.js +68 -0
  466. package/dist/types.d.ts +1609 -0
  467. package/dist/types.d.ts.map +1 -0
  468. package/dist/types.js +80 -0
  469. package/docs/README.md +174 -0
  470. package/docs/ab.md +355 -0
  471. package/docs/building-with-agents.md +129 -0
  472. package/docs/concepts.md +177 -0
  473. package/docs/deployment.md +218 -0
  474. package/docs/evals.md +383 -0
  475. package/docs/guides/agent-to-agent.md +118 -0
  476. package/docs/guides/cloud-runtime.md +122 -0
  477. package/docs/guides/github.md +172 -0
  478. package/docs/guides/human-in-the-loop.md +131 -0
  479. package/docs/guides/slack.md +245 -0
  480. package/docs/guides/webhooks.md +201 -0
  481. package/docs/hillclimbing.md +93 -0
  482. package/docs/quickstart.md +183 -0
  483. package/docs/reference/agent-config.md +154 -0
  484. package/docs/reference/channels.md +206 -0
  485. package/docs/reference/cli.md +257 -0
  486. package/docs/reference/connections.md +137 -0
  487. package/docs/reference/hooks.md +74 -0
  488. package/docs/reference/http-api.md +219 -0
  489. package/docs/reference/instructions.md +77 -0
  490. package/docs/reference/playground.md +67 -0
  491. package/docs/reference/project-layout.md +119 -0
  492. package/docs/reference/schedules.md +220 -0
  493. package/docs/reference/sessions.md +165 -0
  494. package/docs/reference/skills.md +79 -0
  495. package/docs/reference/subagents.md +74 -0
  496. package/docs/reference/tools.md +203 -0
  497. package/docs/scaffolding-agents.md +113 -0
  498. package/docs/troubleshooting.md +95 -0
  499. package/package.json +185 -0
  500. package/skills/ab/SKILL.md +139 -0
  501. package/skills/create-agent/SKILL.md +219 -0
  502. package/skills/debug/SKILL.md +71 -0
  503. package/skills/evals/SKILL.md +217 -0
  504. package/skills/framework-map/SKILL.md +142 -0
  505. package/skills/github/SKILL.md +144 -0
  506. package/skills/hillclimb/SKILL.md +162 -0
  507. package/skills/setup-slack/SKILL.md +180 -0
  508. package/src/ab.ts +675 -0
  509. package/src/bin/agent-serve.ts +949 -0
  510. package/src/channels/github/api.ts +374 -0
  511. package/src/channels/github/auth.ts +275 -0
  512. package/src/channels/github/binding.ts +223 -0
  513. package/src/channels/github/defaults.ts +111 -0
  514. package/src/channels/github/events.ts +72 -0
  515. package/src/channels/github/forward.ts +381 -0
  516. package/src/channels/github/github-channel.ts +2270 -0
  517. package/src/channels/github/index.ts +52 -0
  518. package/src/channels/github/replay.ts +387 -0
  519. package/src/channels/github/state.ts +95 -0
  520. package/src/channels/github/types.ts +490 -0
  521. package/src/channels/slack/api.ts +580 -0
  522. package/src/channels/slack/approvals.ts +198 -0
  523. package/src/channels/slack/assistant.ts +76 -0
  524. package/src/channels/slack/auth.ts +112 -0
  525. package/src/channels/slack/channel-watch.ts +219 -0
  526. package/src/channels/slack/constants.ts +30 -0
  527. package/src/channels/slack/credentials.ts +90 -0
  528. package/src/channels/slack/cursor-account.ts +166 -0
  529. package/src/channels/slack/defaults.ts +450 -0
  530. package/src/channels/slack/dispatch.ts +293 -0
  531. package/src/channels/slack/doctor.ts +135 -0
  532. package/src/channels/slack/event-id-dedupe.ts +30 -0
  533. package/src/channels/slack/inbound.ts +219 -0
  534. package/src/channels/slack/index.ts +45 -0
  535. package/src/channels/slack/init.ts +133 -0
  536. package/src/channels/slack/interactive.ts +194 -0
  537. package/src/channels/slack/links.ts +23 -0
  538. package/src/channels/slack/live-delivery.ts +201 -0
  539. package/src/channels/slack/log.ts +83 -0
  540. package/src/channels/slack/manifest.ts +179 -0
  541. package/src/channels/slack/pr-ref.ts +50 -0
  542. package/src/channels/slack/setup.ts +97 -0
  543. package/src/channels/slack/slack-channel.ts +374 -0
  544. package/src/channels/slack/socket-mode.ts +154 -0
  545. package/src/channels/slack/stream.ts +63 -0
  546. package/src/channels/slack/tool-approval-events.ts +136 -0
  547. package/src/channels/slack/types.ts +349 -0
  548. package/src/channels.ts +385 -0
  549. package/src/connections.ts +89 -0
  550. package/src/evals.ts +501 -0
  551. package/src/hooks.ts +33 -0
  552. package/src/index.ts +184 -0
  553. package/src/internal/ab-collector.ts +210 -0
  554. package/src/internal/ab-fold.ts +228 -0
  555. package/src/internal/ab-snapshot.ts +335 -0
  556. package/src/internal/approval-gate.ts +115 -0
  557. package/src/internal/auth.ts +39 -0
  558. package/src/internal/authored-alias-hooks.ts +69 -0
  559. package/src/internal/authored-loaders.ts +138 -0
  560. package/src/internal/bounded-int.ts +27 -0
  561. package/src/internal/brand.ts +29 -0
  562. package/src/internal/chat-client.ts +407 -0
  563. package/src/internal/cli-ax.ts +474 -0
  564. package/src/internal/cli-cursor.ts +275 -0
  565. package/src/internal/cli-github.ts +849 -0
  566. package/src/internal/cli-slack.ts +175 -0
  567. package/src/internal/cloud-merge.ts +41 -0
  568. package/src/internal/cron.ts +78 -0
  569. package/src/internal/cursor/account-mcp.ts +472 -0
  570. package/src/internal/cursor/backend-client.ts +614 -0
  571. package/src/internal/cursor/credentials.ts +401 -0
  572. package/src/internal/cursor-event-relay.ts +281 -0
  573. package/src/internal/cursor-relay-core.ts +444 -0
  574. package/src/internal/cursor-slack-relay.ts +242 -0
  575. package/src/internal/describe-error.ts +4 -0
  576. package/src/internal/dev-mode.ts +20 -0
  577. package/src/internal/discovery.ts +1709 -0
  578. package/src/internal/distribution.ts +97 -0
  579. package/src/internal/docs-site.ts +191 -0
  580. package/src/internal/duration.ts +39 -0
  581. package/src/internal/eval-run-store.ts +519 -0
  582. package/src/internal/eval-runner.ts +522 -0
  583. package/src/internal/event-log.ts +175 -0
  584. package/src/internal/event-mapper.ts +272 -0
  585. package/src/internal/frontmatter.ts +77 -0
  586. package/src/internal/github-fanout.ts +159 -0
  587. package/src/internal/handleAgentServeTrigger.ts +156 -0
  588. package/src/internal/host-platforms.ts +144 -0
  589. package/src/internal/http-channel.ts +546 -0
  590. package/src/internal/ids.ts +44 -0
  591. package/src/internal/init-project.ts +165 -0
  592. package/src/internal/json-dir-store.ts +109 -0
  593. package/src/internal/json-schema.ts +69 -0
  594. package/src/internal/log-ring.ts +59 -0
  595. package/src/internal/map-pool.ts +32 -0
  596. package/src/internal/mcp-endpoint.ts +518 -0
  597. package/src/internal/mcp-host.ts +211 -0
  598. package/src/internal/net.ts +31 -0
  599. package/src/internal/peer-connections.ts +100 -0
  600. package/src/internal/playground/static.ts +189 -0
  601. package/src/internal/playground/toolchain.ts +277 -0
  602. package/src/internal/reminder-runner.ts +756 -0
  603. package/src/internal/reminder-schedule.ts +106 -0
  604. package/src/internal/reminder-store.ts +145 -0
  605. package/src/internal/resolved-connections.ts +145 -0
  606. package/src/internal/review-comments.ts +268 -0
  607. package/src/internal/router.ts +145 -0
  608. package/src/internal/run-client.ts +320 -0
  609. package/src/internal/schedule-runner.ts +161 -0
  610. package/src/internal/sdk-runner.ts +315 -0
  611. package/src/internal/server.ts +1737 -0
  612. package/src/internal/session-engine.ts +1810 -0
  613. package/src/internal/session-store.ts +147 -0
  614. package/src/internal/session-urls.ts +40 -0
  615. package/src/internal/stream-progress.ts +254 -0
  616. package/src/internal/tool-result.ts +54 -0
  617. package/src/internal/trajectory.ts +306 -0
  618. package/src/internal/workspace.ts +223 -0
  619. package/src/reminders.ts +35 -0
  620. package/src/schedules.ts +37 -0
  621. package/src/skills.ts +27 -0
  622. package/src/tools.ts +127 -0
  623. package/src/types.ts +1848 -0
@@ -0,0 +1,614 @@
1
+ /**
2
+ * Minimal Connect-JSON client for the handful of `aiserver.v1.DashboardService`
3
+ * RPCs agent-serve needs — `GetMe`, `ListSandMcpTools`, `ExecuteSandMcpTool`,
4
+ * and the login-time key lifecycle (`CreateUserApiKey`, `ListUserApiKeys`,
5
+ * `RevokeUserApiKey`).
6
+ *
7
+ * Plain `fetch` POSTs with proto-JSON bodies and zod-validated responses:
8
+ * agent-serve is a published package and should not pull the generated
9
+ * proto tree in for a few unary calls.
10
+ *
11
+ * Auth: the client holds the account API key and exchanges it on demand for
12
+ * a short-lived access token (`POST /auth/exchange_user_api_key`, ~1h),
13
+ * cached until shortly before expiry and re-exchanged once on a 401.
14
+ */
15
+
16
+ import { randomUUID } from "node:crypto";
17
+ import { z } from "zod";
18
+
19
+ const CLIENT_VERSION = "agent-serve-0.1.0";
20
+ const EXCHANGE_PATH = "/auth/exchange_user_api_key";
21
+ const SERVICE_PREFIX = "/aiserver.v1.DashboardService";
22
+ /** Re-exchange when the cached token is within this window of expiry. */
23
+ const TOKEN_EXPIRY_LEEWAY_MS = 5 * 60 * 1000;
24
+ /** Fallback token lifetime when the JWT `exp` claim cannot be parsed. */
25
+ const FALLBACK_TOKEN_LIFETIME_MS = 30 * 60 * 1000;
26
+ const LIST_TIMEOUT_MS = 60_000;
27
+ /** Backend-executed tools call out to third-party servers; be generous. */
28
+ const EXECUTE_TIMEOUT_MS = 120_000;
29
+
30
+ export class CursorBackendError extends Error {
31
+ constructor(
32
+ message: string,
33
+ readonly status?: number
34
+ ) {
35
+ super(message);
36
+ this.name = "CursorBackendError";
37
+ }
38
+ }
39
+
40
+ // ============================================================================
41
+ // Response schemas (proto-JSON, camelCase; default-valued fields are omitted)
42
+ // ============================================================================
43
+
44
+ const getMeResponseSchema: z.ZodObject<
45
+ {
46
+ authId: z.ZodOptional<z.ZodString>;
47
+ email: z.ZodOptional<z.ZodString>;
48
+ firstName: z.ZodOptional<z.ZodString>;
49
+ lastName: z.ZodOptional<z.ZodString>;
50
+ teamId: z.ZodOptional<z.ZodNumber>;
51
+ teamName: z.ZodOptional<z.ZodString>;
52
+ },
53
+ "strip"
54
+ > = z.object({
55
+ authId: z.string().optional(),
56
+ email: z.string().optional(),
57
+ firstName: z.string().optional(),
58
+ lastName: z.string().optional(),
59
+ teamId: z.number().optional(),
60
+ teamName: z.string().optional(),
61
+ });
62
+ export type CursorIdentity = z.infer<typeof getMeResponseSchema>;
63
+
64
+ const createUserApiKeyResponseSchema = z.object({
65
+ apiKey: z.string().min(1),
66
+ });
67
+
68
+ const mcpToolSchema = z.object({
69
+ name: z.string(),
70
+ providerIdentifier: z.string().optional(),
71
+ toolName: z.string().optional(),
72
+ description: z.string().optional(),
73
+ /** `google.protobuf.Value` — an arbitrary JSON Schema object. */
74
+ inputSchema: z.unknown().optional(),
75
+ });
76
+
77
+ const listSandMcpToolsResponseSchema = z.object({
78
+ servers: z
79
+ .array(
80
+ z.object({
81
+ serverIdentifier: z.string(),
82
+ /** "connected" | "needsAuth" | "error" | "loading" */
83
+ status: z.string(),
84
+ tools: z.array(mcpToolSchema).optional(),
85
+ })
86
+ )
87
+ .optional(),
88
+ });
89
+
90
+ export interface AccountMcpTool {
91
+ /** Fully-qualified tool name (`<server>-<tool>`), the execution key. */
92
+ name: string;
93
+ description: string;
94
+ /** JSON Schema for the tool input (defaulted when the server omits it). */
95
+ inputSchema: Record<string, unknown>;
96
+ }
97
+
98
+ export interface AccountMcpServer {
99
+ serverIdentifier: string;
100
+ status: string;
101
+ tools: AccountMcpTool[];
102
+ }
103
+
104
+ /**
105
+ * Proto-JSON of `agent.v1.McpResult` (oneof → exactly one field set).
106
+ * Inner strings default to `""` because proto-JSON omits default-valued
107
+ * fields — `McpTextContent{text: ""}` arrives as `{"text": {}}`.
108
+ */
109
+ const mcpResultSchema = z.object({
110
+ success: z
111
+ .object({
112
+ content: z
113
+ .array(
114
+ z.object({
115
+ text: z.object({ text: z.string().default("") }).optional(),
116
+ image: z
117
+ .object({
118
+ data: z.string().default(""),
119
+ mimeType: z.string().optional(),
120
+ })
121
+ .optional(),
122
+ })
123
+ )
124
+ .optional(),
125
+ isError: z.boolean().optional(),
126
+ structuredContent: z.record(z.unknown()).optional(),
127
+ })
128
+ .optional(),
129
+ error: z.object({ error: z.string().optional() }).optional(),
130
+ rejected: z.object({ reason: z.string().optional() }).optional(),
131
+ permissionDenied: z.object({ error: z.string().optional() }).optional(),
132
+ toolNotFound: z
133
+ .object({
134
+ name: z.string().optional(),
135
+ availableTools: z.array(z.string()).optional(),
136
+ })
137
+ .optional(),
138
+ serverNotFound: z
139
+ .object({
140
+ name: z.string().optional(),
141
+ availableServers: z.array(z.string()).optional(),
142
+ })
143
+ .optional(),
144
+ });
145
+
146
+ const executeResponseSchema = z.object({
147
+ result: mcpResultSchema.optional(),
148
+ });
149
+
150
+ /** Normalized tool-call outcome, shaped like an MCP `CallToolResult`. */
151
+ export interface AccountMcpCallResult {
152
+ content: Array<
153
+ | { type: "text"; text: string }
154
+ | { type: "image"; data: string; mimeType?: string }
155
+ >;
156
+ isError: boolean;
157
+ structuredContent?: Record<string, unknown>;
158
+ }
159
+
160
+ // ============================================================================
161
+ // Shared request machinery (used by the client and the login-time mint)
162
+ // ============================================================================
163
+
164
+ /** One DashboardService Connect-JSON POST; auth is the caller's bearer. */
165
+ async function dashboardRpc(args: {
166
+ fetchImpl: typeof fetch;
167
+ backendUrl: string;
168
+ method: string;
169
+ bearer: string;
170
+ body: unknown;
171
+ timeoutMs: number;
172
+ }): Promise<Response> {
173
+ try {
174
+ return await args.fetchImpl(
175
+ `${args.backendUrl}${SERVICE_PREFIX}/${args.method}`,
176
+ {
177
+ method: "POST",
178
+ headers: {
179
+ "content-type": "application/json",
180
+ authorization: `Bearer ${args.bearer}`,
181
+ "x-ghost-mode": "true",
182
+ "x-cursor-client-version": CLIENT_VERSION,
183
+ "x-cursor-client-type": "agent-serve",
184
+ "x-request-id": randomUUID(),
185
+ },
186
+ body: JSON.stringify(args.body ?? {}),
187
+ signal: AbortSignal.timeout(args.timeoutMs),
188
+ }
189
+ );
190
+ } catch (error) {
191
+ throw new CursorBackendError(
192
+ `Cursor backend request ${args.method} failed: ${describeError(error)}`
193
+ );
194
+ }
195
+ }
196
+
197
+ /** Drain and parse an RPC response; maps non-2xx to a CursorBackendError. */
198
+ async function parseRpcResponse(
199
+ method: string,
200
+ response: Response
201
+ ): Promise<unknown> {
202
+ const text = await response.text();
203
+ if (!response.ok) {
204
+ throw new CursorBackendError(
205
+ `Cursor backend ${method} failed (${response.status}): ${connectErrorMessage(text)}`,
206
+ response.status
207
+ );
208
+ }
209
+ try {
210
+ return JSON.parse(text) as unknown;
211
+ } catch {
212
+ throw new CursorBackendError(
213
+ `Cursor backend ${method} returned a non-JSON response.`
214
+ );
215
+ }
216
+ }
217
+
218
+ // ============================================================================
219
+ // Client
220
+ // ============================================================================
221
+
222
+ export interface CursorBackendClientOptions {
223
+ backendUrl: string;
224
+ apiKey: string;
225
+ logger?: (line: string) => void;
226
+ /** Test seam; defaults to global fetch. */
227
+ fetchImpl?: typeof fetch;
228
+ }
229
+
230
+ export class CursorBackendClient {
231
+ private readonly backendUrl: string;
232
+ private readonly apiKey: string;
233
+ private readonly logger: (line: string) => void;
234
+ private readonly fetchImpl: typeof fetch;
235
+ private token: { value: string; expiresAtMs: number } | undefined;
236
+ private tokenExchange: Promise<string> | undefined;
237
+
238
+ constructor(options: CursorBackendClientOptions) {
239
+ this.backendUrl = options.backendUrl.endsWith("/")
240
+ ? options.backendUrl.slice(0, -1)
241
+ : options.backendUrl;
242
+ this.apiKey = options.apiKey;
243
+ this.logger = options.logger ?? (() => {});
244
+ this.fetchImpl = options.fetchImpl ?? fetch;
245
+ }
246
+
247
+ /** Who this API key acts as. */
248
+ async getMe(): Promise<CursorIdentity> {
249
+ return getMeResponseSchema.parse(await this.rpc("GetMe", {}));
250
+ }
251
+
252
+ /**
253
+ * The account's MCP connectors with live status and backend-prefixed tool
254
+ * definitions. `serverIdentifiers` restricts discovery (empty = all
255
+ * HTTP/SSE servers on the account).
256
+ */
257
+ async listAccountMcpTools(
258
+ serverIdentifiers: readonly string[]
259
+ ): Promise<AccountMcpServer[]> {
260
+ const raw = await this.rpc(
261
+ "ListSandMcpTools",
262
+ { serverIdentifiers: [...serverIdentifiers] },
263
+ LIST_TIMEOUT_MS
264
+ );
265
+ const parsed = listSandMcpToolsResponseSchema.parse(raw);
266
+ return (parsed.servers ?? []).map((server) => ({
267
+ serverIdentifier: server.serverIdentifier,
268
+ status: server.status,
269
+ tools: (server.tools ?? []).map((tool) => ({
270
+ name: tool.name,
271
+ description: tool.description ?? "",
272
+ inputSchema: normalizeInputSchema(tool.inputSchema),
273
+ })),
274
+ }));
275
+ }
276
+
277
+ /**
278
+ * Execute one connector tool **on the Cursor backend** with the account's
279
+ * stored OAuth credentials. `toolName` is the fully-qualified name from
280
+ * {@link listAccountMcpTools}.
281
+ */
282
+ async executeAccountMcpTool(args: {
283
+ serverIdentifier: string;
284
+ toolName: string;
285
+ args: Record<string, unknown>;
286
+ }): Promise<AccountMcpCallResult> {
287
+ const raw = await this.rpc(
288
+ "ExecuteSandMcpTool",
289
+ {
290
+ serverIdentifier: args.serverIdentifier,
291
+ toolName: args.toolName,
292
+ args: args.args,
293
+ toolCallId: randomUUID(),
294
+ },
295
+ EXECUTE_TIMEOUT_MS
296
+ );
297
+ const parsed = executeResponseSchema.parse(raw);
298
+ return toCallResult(parsed.result ?? {});
299
+ }
300
+
301
+ private async rpc(
302
+ method: string,
303
+ body: unknown,
304
+ timeoutMs = LIST_TIMEOUT_MS
305
+ ): Promise<unknown> {
306
+ const bearer = await this.getAccessToken();
307
+ const first = await dashboardRpc({
308
+ fetchImpl: this.fetchImpl,
309
+ backendUrl: this.backendUrl,
310
+ method,
311
+ bearer,
312
+ body,
313
+ timeoutMs,
314
+ });
315
+ if (first.status !== 401) {
316
+ return parseRpcResponse(method, first);
317
+ }
318
+ // The token aged out server-side. Drain the rejected body (keeps the
319
+ // connection reusable), drop the token — unless a concurrent retry
320
+ // already minted a newer one — and retry once.
321
+ await drainResponseBody(first);
322
+ if (this.token?.value === bearer) {
323
+ this.token = undefined;
324
+ }
325
+ const retryBearer = await this.getAccessToken();
326
+ const second = await dashboardRpc({
327
+ fetchImpl: this.fetchImpl,
328
+ backendUrl: this.backendUrl,
329
+ method,
330
+ bearer: retryBearer,
331
+ body,
332
+ timeoutMs,
333
+ });
334
+ if (second.status === 401 && this.token?.value === retryBearer) {
335
+ // The freshly minted token was rejected too; do not keep serving it.
336
+ this.token = undefined;
337
+ }
338
+ return parseRpcResponse(method, second);
339
+ }
340
+
341
+ private getAccessToken(): Promise<string> {
342
+ if (
343
+ this.token !== undefined &&
344
+ Date.now() < this.token.expiresAtMs - TOKEN_EXPIRY_LEEWAY_MS
345
+ ) {
346
+ return Promise.resolve(this.token.value);
347
+ }
348
+ // Single-flight: concurrent tool calls share one exchange.
349
+ if (this.tokenExchange === undefined) {
350
+ this.tokenExchange = this.exchangeApiKey().finally(() => {
351
+ this.tokenExchange = undefined;
352
+ });
353
+ }
354
+ return this.tokenExchange;
355
+ }
356
+
357
+ private async exchangeApiKey(): Promise<string> {
358
+ let response: Response;
359
+ try {
360
+ response = await this.fetchImpl(`${this.backendUrl}${EXCHANGE_PATH}`, {
361
+ method: "POST",
362
+ headers: {
363
+ "content-type": "application/json",
364
+ authorization: `Bearer ${this.apiKey}`,
365
+ },
366
+ body: "{}",
367
+ signal: AbortSignal.timeout(30_000),
368
+ });
369
+ } catch (error) {
370
+ throw new CursorBackendError(
371
+ `Could not reach the Cursor backend at ${this.backendUrl}: ${describeError(error)}`
372
+ );
373
+ }
374
+ const text = await response.text();
375
+ if (!response.ok) {
376
+ throw new CursorBackendError(
377
+ response.status === 401
378
+ ? "The Cursor API key was rejected. Run `agent-serve login` again or update CURSOR_API_KEY."
379
+ : `Cursor API key exchange failed (${response.status}).`,
380
+ response.status
381
+ );
382
+ }
383
+ const body = accessTokenResponseSchema.safeParse(safeJsonParse(text));
384
+ if (!body.success || body.data.accessToken === "") {
385
+ throw new CursorBackendError(
386
+ "Cursor API key exchange returned no access token."
387
+ );
388
+ }
389
+ this.token = {
390
+ value: body.data.accessToken,
391
+ expiresAtMs: jwtExpiryMs(body.data.accessToken),
392
+ };
393
+ this.logger("[agent-serve] cursor account: minted a fresh access token");
394
+ return body.data.accessToken;
395
+ }
396
+ }
397
+
398
+ /**
399
+ * Mint a named user API key from a short-lived login session token. Used
400
+ * exactly once per `agent-serve login`; the session token is then discarded.
401
+ */
402
+ export async function createUserApiKeyWithSessionToken(args: {
403
+ backendUrl: string;
404
+ sessionToken: string;
405
+ keyName: string;
406
+ fetchImpl?: typeof fetch;
407
+ }): Promise<string> {
408
+ const response = await dashboardRpc({
409
+ fetchImpl: args.fetchImpl ?? fetch,
410
+ backendUrl: args.backendUrl.endsWith("/")
411
+ ? args.backendUrl.slice(0, -1)
412
+ : args.backendUrl,
413
+ method: "CreateUserApiKey",
414
+ bearer: args.sessionToken,
415
+ body: { name: args.keyName },
416
+ timeoutMs: 30_000,
417
+ });
418
+ const raw = await parseRpcResponse("CreateUserApiKey", response);
419
+ return createUserApiKeyResponseSchema.parse(raw).apiKey;
420
+ }
421
+
422
+ const API_KEY_PREFIX = "crsr_";
423
+
424
+ /** Matches dashboard `maskApiKey` (`crsr_...abcd`). */
425
+ function maskApiKey(apiKey: string): string {
426
+ return `${API_KEY_PREFIX}...${apiKey.slice(-4)}`;
427
+ }
428
+
429
+ const listUserApiKeysResponseSchema = z.object({
430
+ apiKeys: z
431
+ .array(
432
+ z.object({
433
+ id: z.number(),
434
+ name: z.string(),
435
+ maskedKey: z.string().optional(),
436
+ })
437
+ )
438
+ .optional(),
439
+ });
440
+
441
+ /**
442
+ * Best-effort cleanup when `login` mints a key but fails before storing it,
443
+ * authenticated with the browser session token that minted it. The key is
444
+ * identified by its masked suffix in `ListUserApiKeys` — never by name alone,
445
+ * so replica lag after `CreateUserApiKey` can only skip the cleanup, not
446
+ * revoke an older same-named key.
447
+ */
448
+ export async function revokeMintedUserApiKey(args: {
449
+ backendUrl: string;
450
+ keyName: string;
451
+ /** The raw minted key; selects the exact list row via `maskedKey`. */
452
+ apiKey: string;
453
+ /** Session token from the PKCE login; the bearer for list + revoke. */
454
+ sessionToken: string;
455
+ fetchImpl?: typeof fetch;
456
+ }): Promise<void> {
457
+ const fetchImpl = args.fetchImpl ?? fetch;
458
+ const backendUrl = args.backendUrl.endsWith("/")
459
+ ? args.backendUrl.slice(0, -1)
460
+ : args.backendUrl;
461
+
462
+ const listResponse = await dashboardRpc({
463
+ fetchImpl,
464
+ backendUrl,
465
+ method: "ListUserApiKeys",
466
+ bearer: args.sessionToken,
467
+ body: {},
468
+ timeoutMs: 30_000,
469
+ });
470
+ const listed = listUserApiKeysResponseSchema.parse(
471
+ await parseRpcResponse("ListUserApiKeys", listResponse)
472
+ );
473
+ const masked = maskApiKey(args.apiKey);
474
+ const match = (listed.apiKeys ?? []).find(
475
+ (key) => key.name === args.keyName && key.maskedKey === masked
476
+ );
477
+ if (match === undefined) {
478
+ // CreateUserApiKey writes the primary while ListUserApiKeys may read a
479
+ // lagging replica — skip rather than touch any other key.
480
+ return;
481
+ }
482
+ const revokeResponse = await dashboardRpc({
483
+ fetchImpl,
484
+ backendUrl,
485
+ method: "RevokeUserApiKey",
486
+ bearer: args.sessionToken,
487
+ body: { id: match.id },
488
+ timeoutMs: 30_000,
489
+ });
490
+ await drainResponseBody(revokeResponse);
491
+ }
492
+
493
+ // ============================================================================
494
+ // Helpers
495
+ // ============================================================================
496
+
497
+ const accessTokenResponseSchema = z.object({ accessToken: z.string() });
498
+
499
+ function safeJsonParse(text: string): unknown {
500
+ try {
501
+ return JSON.parse(text) as unknown;
502
+ } catch {
503
+ return undefined;
504
+ }
505
+ }
506
+
507
+ function normalizeInputSchema(schema: unknown): Record<string, unknown> {
508
+ if (typeof schema === "object" && schema !== null && !Array.isArray(schema)) {
509
+ return schema as Record<string, unknown>;
510
+ }
511
+ return { type: "object", properties: {} };
512
+ }
513
+
514
+ type McpResultJson = z.infer<typeof mcpResultSchema>;
515
+
516
+ function toCallResult(result: McpResultJson): AccountMcpCallResult {
517
+ if (result.success !== undefined) {
518
+ const content: AccountMcpCallResult["content"] = [];
519
+ for (const item of result.success.content ?? []) {
520
+ if (item.text !== undefined) {
521
+ content.push({ type: "text", text: item.text.text });
522
+ } else if (item.image !== undefined) {
523
+ content.push({
524
+ type: "image",
525
+ data: item.image.data,
526
+ ...(item.image.mimeType === undefined
527
+ ? {}
528
+ : { mimeType: item.image.mimeType }),
529
+ });
530
+ }
531
+ }
532
+ return {
533
+ content,
534
+ isError: result.success.isError === true,
535
+ ...(result.success.structuredContent === undefined
536
+ ? {}
537
+ : { structuredContent: result.success.structuredContent }),
538
+ };
539
+ }
540
+ return {
541
+ content: [{ type: "text", text: describeFailure(result) }],
542
+ isError: true,
543
+ };
544
+ }
545
+
546
+ function describeFailure(result: McpResultJson): string {
547
+ if (result.error !== undefined) {
548
+ return result.error.error ?? "The tool call failed.";
549
+ }
550
+ if (result.permissionDenied !== undefined) {
551
+ return result.permissionDenied.error ?? "Permission denied.";
552
+ }
553
+ if (result.rejected !== undefined) {
554
+ return `The tool call was rejected${
555
+ result.rejected.reason === undefined ? "" : `: ${result.rejected.reason}`
556
+ }.`;
557
+ }
558
+ if (result.toolNotFound !== undefined) {
559
+ return `Unknown tool "${result.toolNotFound.name ?? ""}". Available: ${
560
+ (result.toolNotFound.availableTools ?? []).join(", ") || "(none)"
561
+ }.`;
562
+ }
563
+ if (result.serverNotFound !== undefined) {
564
+ return `Unknown MCP server "${result.serverNotFound.name ?? ""}". Available: ${
565
+ (result.serverNotFound.availableServers ?? []).join(", ") || "(none)"
566
+ }.`;
567
+ }
568
+ return "The tool call returned no result.";
569
+ }
570
+
571
+ /** Best-effort human-readable message from a Connect error JSON body. */
572
+ function connectErrorMessage(bodyText: string): string {
573
+ const parsed = safeJsonParse(bodyText);
574
+ if (
575
+ typeof parsed === "object" &&
576
+ parsed !== null &&
577
+ typeof (parsed as { message?: unknown }).message === "string" &&
578
+ (parsed as { message: string }).message !== ""
579
+ ) {
580
+ return (parsed as { message: string }).message;
581
+ }
582
+ return bodyText.slice(0, 300) || "(empty response body)";
583
+ }
584
+
585
+ function jwtExpiryMs(token: string): number {
586
+ try {
587
+ const payload = token.split(".")[1];
588
+ if (payload === undefined) {
589
+ throw new Error("not a JWT");
590
+ }
591
+ const claims = JSON.parse(
592
+ Buffer.from(payload, "base64url").toString("utf8")
593
+ ) as { exp?: unknown };
594
+ if (typeof claims.exp === "number") {
595
+ return claims.exp * 1000;
596
+ }
597
+ } catch {
598
+ // Opaque token — assume a conservative lifetime.
599
+ }
600
+ return Date.now() + FALLBACK_TOKEN_LIFETIME_MS;
601
+ }
602
+
603
+ function describeError(error: unknown): string {
604
+ return error instanceof Error ? error.message : String(error);
605
+ }
606
+
607
+ /** Release undici/fetch connection slots on responses we will not parse. */
608
+ async function drainResponseBody(response: Response): Promise<void> {
609
+ try {
610
+ await response.arrayBuffer();
611
+ } catch {
612
+ // Best-effort; the socket may already be closed.
613
+ }
614
+ }