@cursor/july 0.1.1 → 0.1.3

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 (298) hide show
  1. package/AGENTS.md +40 -7
  2. package/README.md +33 -24
  3. package/dist/bin/agent-serve.d.ts +3 -1
  4. package/dist/bin/agent-serve.d.ts.map +1 -1
  5. package/dist/bin/agent-serve.js +466 -140
  6. package/dist/channels/github/api.d.ts.map +1 -1
  7. package/dist/channels/github/api.js +31 -14
  8. package/dist/channels/github/cursor-account.d.ts +43 -0
  9. package/dist/channels/github/cursor-account.d.ts.map +1 -0
  10. package/dist/channels/github/cursor-account.js +95 -0
  11. package/dist/channels/github/github-channel.d.ts.map +1 -1
  12. package/dist/channels/github/github-channel.js +46 -9
  13. package/dist/channels/github/index.d.ts +2 -2
  14. package/dist/channels/github/index.js +2 -2
  15. package/dist/channels/github/types.d.ts +17 -0
  16. package/dist/channels/github/types.d.ts.map +1 -1
  17. package/dist/channels/slack/slack-channel.d.ts +8 -2
  18. package/dist/channels/slack/slack-channel.d.ts.map +1 -1
  19. package/dist/channels/slack/slack-channel.js +8 -0
  20. package/dist/channels/slack/types.d.ts +24 -3
  21. package/dist/channels/slack/types.d.ts.map +1 -1
  22. package/dist/channels/slack/types.js +15 -1
  23. package/dist/docs/404.html +2 -2
  24. package/dist/docs/ab.html +8 -8
  25. package/dist/docs/assets/{ab.md.COdXkces.js → ab.md.BMCZ6Hd7.js} +3 -3
  26. package/dist/docs/assets/{ab.md.COdXkces.lean.js → ab.md.BMCZ6Hd7.lean.js} +1 -1
  27. package/dist/docs/assets/{app.DqfFEmJd.js → app.BR0RbIdx.js} +1 -1
  28. package/dist/docs/assets/chunks/@localSearchIndexroot.DtIOQzGj.js +1 -0
  29. package/dist/docs/assets/chunks/{VPLocalSearchBox.BaLEdS15.js → VPLocalSearchBox.qjsVTneI.js} +1 -1
  30. package/dist/docs/assets/chunks/{theme.CZRvu_0q.js → theme.2Kg8jIp_.js} +2 -2
  31. package/dist/docs/assets/{deployment.md.Dx1TYNk5.js → deployment.md.DTKwE15Z.js} +3 -3
  32. package/dist/docs/assets/{deployment.md.Dx1TYNk5.lean.js → deployment.md.DTKwE15Z.lean.js} +1 -1
  33. package/dist/docs/assets/{evals.md.DPZ_MAnI.js → evals.md.DAgEc_hL.js} +3 -3
  34. package/dist/docs/assets/{guides_agent-to-agent.md.CrtrsySy.js → guides_agent-to-agent.md.Bpzgq2Pq.js} +1 -1
  35. package/dist/docs/assets/{guides_cloud-runtime.md.CYlNMTNp.js → guides_cloud-runtime.md.gVzabdQL.js} +1 -1
  36. package/dist/docs/assets/{guides_github.md.DwbKhCeS.js → guides_github.md.DOOCpqsW.js} +11 -4
  37. package/dist/docs/assets/{guides_github.md.DwbKhCeS.lean.js → guides_github.md.DOOCpqsW.lean.js} +1 -1
  38. package/dist/docs/assets/{guides_human-in-the-loop.md.Dvuctx7s.js → guides_human-in-the-loop.md.DlUqsp1S.js} +2 -2
  39. package/dist/docs/assets/{guides_slack.md.bv41fHfW.js → guides_slack.md.CCwqHvSV.js} +4 -4
  40. package/dist/docs/assets/{guides_slack.md.bv41fHfW.lean.js → guides_slack.md.CCwqHvSV.lean.js} +1 -1
  41. package/dist/docs/assets/{guides_webhooks.md.hFTik3lf.js → guides_webhooks.md.B1EswtUu.js} +2 -2
  42. package/dist/docs/assets/index.md.m81y7TY7.js +20 -0
  43. package/dist/docs/assets/{index.md.BPKcj5AI.lean.js → index.md.m81y7TY7.lean.js} +1 -1
  44. package/dist/docs/assets/quickstart.md.BU6Iwi_9.js +204 -0
  45. package/dist/docs/assets/quickstart.md.BU6Iwi_9.lean.js +1 -0
  46. package/dist/docs/assets/{reference_agent-config.md.Bpd7HQwf.js → reference_agent-config.md.DrW2JUM8.js} +4 -4
  47. package/dist/docs/assets/{reference_agent-config.md.Bpd7HQwf.lean.js → reference_agent-config.md.DrW2JUM8.lean.js} +1 -1
  48. package/dist/docs/assets/{reference_channels.md.D7JTR03W.js → reference_channels.md.DdmiKgqf.js} +4 -4
  49. package/dist/docs/assets/{reference_channels.md.D7JTR03W.lean.js → reference_channels.md.DdmiKgqf.lean.js} +1 -1
  50. package/dist/docs/assets/{reference_cli.md.DA730zCu.js → reference_cli.md.Bv6pOxcF.js} +11 -6
  51. package/dist/docs/assets/{reference_cli.md.DA730zCu.lean.js → reference_cli.md.Bv6pOxcF.lean.js} +1 -1
  52. package/dist/docs/assets/{reference_connections.md.C3vNH_DE.js → reference_connections.md.zaEYCLHT.js} +1 -1
  53. package/dist/docs/assets/{reference_hooks.md.BCEc3MyM.js → reference_hooks.md.DyLVfE1O.js} +1 -1
  54. package/dist/docs/assets/{reference_hooks.md.BCEc3MyM.lean.js → reference_hooks.md.DyLVfE1O.lean.js} +1 -1
  55. package/dist/docs/assets/{reference_http-api.md.DBAahtdz.js → reference_http-api.md.Dx_nmDG6.js} +1 -1
  56. package/dist/docs/assets/{reference_instructions.md.BC05LEQ8.js → reference_instructions.md.CgoV-YEb.js} +9 -7
  57. package/dist/docs/assets/{reference_instructions.md.BC05LEQ8.lean.js → reference_instructions.md.CgoV-YEb.lean.js} +1 -1
  58. package/dist/docs/assets/{reference_schedules.md.D7qijxLk.js → reference_schedules.md.w_F2mXB6.js} +2 -2
  59. package/dist/docs/assets/{reference_skills.md.VQnlBT3Q.js → reference_skills.md.B_jHN7JL.js} +3 -3
  60. package/dist/docs/assets/{reference_skills.md.VQnlBT3Q.lean.js → reference_skills.md.B_jHN7JL.lean.js} +1 -1
  61. package/dist/docs/assets/{reference_subagents.md.CIRAVcPK.js → reference_subagents.md.zWAMNfi1.js} +1 -1
  62. package/dist/docs/assets/{reference_tools.md.DF5kwlt0.js → reference_tools.md.CqgJroI0.js} +2 -2
  63. package/dist/docs/assets/scaffolding-agents.md.C3pTrmoE.js +1 -0
  64. package/dist/docs/assets/scaffolding-agents.md.C3pTrmoE.lean.js +1 -0
  65. package/dist/docs/assets/storage.md.CVnInNiN.js +17 -0
  66. package/dist/docs/assets/storage.md.CVnInNiN.lean.js +1 -0
  67. package/dist/docs/building-with-agents.html +4 -4
  68. package/dist/docs/concepts.html +4 -4
  69. package/dist/docs/deployment.html +7 -7
  70. package/dist/docs/evals.html +7 -7
  71. package/dist/docs/guides/agent-to-agent.html +6 -6
  72. package/dist/docs/guides/cloud-runtime.html +5 -5
  73. package/dist/docs/guides/github.html +14 -7
  74. package/dist/docs/guides/human-in-the-loop.html +6 -6
  75. package/dist/docs/guides/slack.html +8 -8
  76. package/dist/docs/guides/webhooks.html +6 -6
  77. package/dist/docs/hashmap.json +1 -1
  78. package/dist/docs/hillclimbing.html +5 -5
  79. package/dist/docs/index.html +7 -7
  80. package/dist/docs/quickstart.html +195 -26
  81. package/dist/docs/reference/agent-config.html +7 -7
  82. package/dist/docs/reference/channels.html +8 -8
  83. package/dist/docs/reference/cli.html +14 -9
  84. package/dist/docs/reference/connections.html +5 -5
  85. package/dist/docs/reference/hooks.html +5 -5
  86. package/dist/docs/reference/http-api.html +6 -6
  87. package/dist/docs/reference/instructions.html +13 -11
  88. package/dist/docs/reference/playground.html +4 -4
  89. package/dist/docs/reference/project-layout.html +4 -4
  90. package/dist/docs/reference/schedules.html +7 -7
  91. package/dist/docs/reference/sessions.html +4 -4
  92. package/dist/docs/reference/skills.html +6 -6
  93. package/dist/docs/reference/subagents.html +6 -6
  94. package/dist/docs/reference/tools.html +7 -7
  95. package/dist/docs/scaffolding-agents.html +5 -5
  96. package/dist/docs/storage.html +41 -0
  97. package/dist/docs/troubleshooting.html +4 -4
  98. package/dist/index.d.ts +2 -0
  99. package/dist/index.d.ts.map +1 -1
  100. package/dist/index.js +1 -0
  101. package/dist/internal/chat-client.d.ts +29 -3
  102. package/dist/internal/chat-client.d.ts.map +1 -1
  103. package/dist/internal/chat-client.js +180 -27
  104. package/dist/internal/cli-ax.d.ts +75 -2
  105. package/dist/internal/cli-ax.d.ts.map +1 -1
  106. package/dist/internal/cli-ax.js +600 -52
  107. package/dist/internal/cli-cursor.d.ts.map +1 -1
  108. package/dist/internal/cli-cursor.js +8 -36
  109. package/dist/internal/cli-deploy.d.ts +108 -0
  110. package/dist/internal/cli-deploy.d.ts.map +1 -0
  111. package/dist/internal/cli-deploy.js +1009 -0
  112. package/dist/internal/cursor/backend-client.d.ts +10 -1
  113. package/dist/internal/cursor/backend-client.d.ts.map +1 -1
  114. package/dist/internal/cursor/backend-client.js +79 -1
  115. package/dist/internal/cursor/credentials.d.ts +9 -0
  116. package/dist/internal/cursor/credentials.d.ts.map +1 -1
  117. package/dist/internal/cursor/credentials.js +12 -0
  118. package/dist/internal/cursor/github-credentials.d.ts +44 -0
  119. package/dist/internal/cursor/github-credentials.d.ts.map +1 -0
  120. package/dist/internal/cursor/github-credentials.js +195 -0
  121. package/dist/internal/deploy-client.d.ts +184 -0
  122. package/dist/internal/deploy-client.d.ts.map +1 -0
  123. package/dist/internal/deploy-client.js +395 -0
  124. package/dist/internal/deploy-source.d.ts +35 -0
  125. package/dist/internal/deploy-source.d.ts.map +1 -0
  126. package/dist/internal/deploy-source.js +118 -0
  127. package/dist/internal/discovery.d.ts +11 -0
  128. package/dist/internal/discovery.d.ts.map +1 -1
  129. package/dist/internal/discovery.js +116 -19
  130. package/dist/internal/distribution.d.ts.map +1 -1
  131. package/dist/internal/distribution.js +1 -0
  132. package/dist/internal/eval-run-store.d.ts +22 -3
  133. package/dist/internal/eval-run-store.d.ts.map +1 -1
  134. package/dist/internal/eval-run-store.js +39 -20
  135. package/dist/internal/eval-runner.d.ts +2 -0
  136. package/dist/internal/eval-runner.d.ts.map +1 -1
  137. package/dist/internal/eval-runner.js +2 -0
  138. package/dist/internal/event-mapper.d.ts +54 -1
  139. package/dist/internal/event-mapper.d.ts.map +1 -1
  140. package/dist/internal/event-mapper.js +151 -41
  141. package/dist/internal/handleAgentServeTrigger.d.ts.map +1 -1
  142. package/dist/internal/handleAgentServeTrigger.js +10 -12
  143. package/dist/internal/host-platforms.d.ts +7 -2
  144. package/dist/internal/host-platforms.d.ts.map +1 -1
  145. package/dist/internal/host-platforms.js +15 -10
  146. package/dist/internal/hosting.d.ts +37 -0
  147. package/dist/internal/hosting.d.ts.map +1 -0
  148. package/dist/internal/hosting.js +67 -0
  149. package/dist/internal/init-project.d.ts +88 -1
  150. package/dist/internal/init-project.d.ts.map +1 -1
  151. package/dist/internal/init-project.js +221 -31
  152. package/dist/internal/install-cursor-skills.d.ts +64 -0
  153. package/dist/internal/install-cursor-skills.d.ts.map +1 -0
  154. package/dist/internal/install-cursor-skills.js +274 -0
  155. package/dist/internal/logs-client.d.ts +60 -0
  156. package/dist/internal/logs-client.d.ts.map +1 -0
  157. package/dist/internal/logs-client.js +311 -0
  158. package/dist/internal/open-browser.d.ts +5 -0
  159. package/dist/internal/open-browser.d.ts.map +1 -0
  160. package/dist/internal/open-browser.js +34 -0
  161. package/dist/internal/playground/toolchain.d.ts.map +1 -1
  162. package/dist/internal/playground/toolchain.js +16 -11
  163. package/dist/internal/playground-proxy.d.ts +69 -0
  164. package/dist/internal/playground-proxy.d.ts.map +1 -0
  165. package/dist/internal/playground-proxy.js +468 -0
  166. package/dist/internal/prompt-context.d.ts +35 -0
  167. package/dist/internal/prompt-context.d.ts.map +1 -0
  168. package/dist/internal/prompt-context.js +71 -0
  169. package/dist/internal/reminder-runner.d.ts +7 -0
  170. package/dist/internal/reminder-runner.d.ts.map +1 -1
  171. package/dist/internal/reminder-runner.js +50 -6
  172. package/dist/internal/reminder-store.d.ts +2 -0
  173. package/dist/internal/reminder-store.d.ts.map +1 -1
  174. package/dist/internal/reminder-store.js +18 -0
  175. package/dist/internal/request-headers.d.ts +11 -0
  176. package/dist/internal/request-headers.d.ts.map +1 -0
  177. package/dist/internal/request-headers.js +14 -0
  178. package/dist/internal/resolve-prod-target.d.ts +42 -0
  179. package/dist/internal/resolve-prod-target.d.ts.map +1 -0
  180. package/dist/internal/resolve-prod-target.js +111 -0
  181. package/dist/internal/run-client.d.ts +2 -2
  182. package/dist/internal/run-client.d.ts.map +1 -1
  183. package/dist/internal/run-client.js +38 -23
  184. package/dist/internal/server.d.ts.map +1 -1
  185. package/dist/internal/server.js +182 -45
  186. package/dist/internal/session-engine.d.ts +50 -1
  187. package/dist/internal/session-engine.d.ts.map +1 -1
  188. package/dist/internal/session-engine.js +267 -23
  189. package/dist/internal/sessions-client.d.ts +21 -0
  190. package/dist/internal/sessions-client.d.ts.map +1 -0
  191. package/dist/internal/sessions-client.js +168 -0
  192. package/dist/internal/storage-coordinator.d.ts +139 -0
  193. package/dist/internal/storage-coordinator.d.ts.map +1 -0
  194. package/dist/internal/storage-coordinator.js +499 -0
  195. package/dist/internal/stream-progress.d.ts.map +1 -1
  196. package/dist/internal/stream-progress.js +31 -3
  197. package/dist/internal/terminal-style.d.ts +22 -0
  198. package/dist/internal/terminal-style.d.ts.map +1 -0
  199. package/dist/internal/terminal-style.js +49 -0
  200. package/dist/internal/trajectory.d.ts +10 -5
  201. package/dist/internal/trajectory.d.ts.map +1 -1
  202. package/dist/internal/trajectory.js +82 -10
  203. package/dist/internal/workspace.d.ts +11 -0
  204. package/dist/internal/workspace.d.ts.map +1 -1
  205. package/dist/internal/workspace.js +38 -4
  206. package/dist/playground/assets/cursor-icons-outline-BxTT_FVJ.woff2 +0 -0
  207. package/dist/playground/assets/index-D-vo2lV_.css +1 -0
  208. package/dist/playground/assets/index-x60b9q2j.js +312 -0
  209. package/dist/playground/index.html +2 -2
  210. package/dist/storage.d.ts +204 -0
  211. package/dist/storage.d.ts.map +1 -0
  212. package/dist/storage.js +153 -0
  213. package/dist/types.d.ts +70 -4
  214. package/dist/types.d.ts.map +1 -1
  215. package/docs/README.md +3 -2
  216. package/docs/guides/github.md +43 -8
  217. package/docs/guides/slack.md +1 -1
  218. package/docs/quickstart.md +350 -57
  219. package/docs/reference/cli.md +51 -3
  220. package/docs/reference/instructions.md +8 -6
  221. package/docs/scaffolding-agents.md +1 -1
  222. package/docs/storage.md +98 -0
  223. package/package.json +10 -1
  224. package/skills/ab/SKILL.md +8 -8
  225. package/skills/create-agent/SKILL.md +28 -22
  226. package/skills/debug/SKILL.md +11 -11
  227. package/skills/evals/SKILL.md +16 -16
  228. package/skills/framework-map/SKILL.md +6 -6
  229. package/skills/github/SKILL.md +22 -14
  230. package/skills/hillclimb/SKILL.md +10 -10
  231. package/skills/setup-slack/SKILL.md +13 -13
  232. package/src/bin/agent-serve.ts +552 -179
  233. package/src/channels/github/api.ts +42 -23
  234. package/src/channels/github/cursor-account.ts +165 -0
  235. package/src/channels/github/github-channel.ts +66 -6
  236. package/src/channels/github/index.ts +2 -2
  237. package/src/channels/github/types.ts +19 -0
  238. package/src/channels/slack/slack-channel.ts +17 -3
  239. package/src/channels/slack/types.ts +44 -3
  240. package/src/index.ts +13 -0
  241. package/src/internal/chat-client.ts +252 -37
  242. package/src/internal/cli-ax.ts +722 -72
  243. package/src/internal/cli-cursor.ts +14 -42
  244. package/src/internal/cli-deploy.ts +1319 -0
  245. package/src/internal/cursor/backend-client.ts +103 -1
  246. package/src/internal/cursor/credentials.ts +14 -0
  247. package/src/internal/cursor/github-credentials.ts +248 -0
  248. package/src/internal/deploy-client.ts +632 -0
  249. package/src/internal/deploy-source.ts +133 -0
  250. package/src/internal/discovery.ts +141 -17
  251. package/src/internal/distribution.ts +1 -0
  252. package/src/internal/eval-run-store.ts +50 -20
  253. package/src/internal/eval-runner.ts +5 -0
  254. package/src/internal/event-mapper.ts +222 -42
  255. package/src/internal/handleAgentServeTrigger.ts +10 -12
  256. package/src/internal/host-platforms.ts +28 -11
  257. package/src/internal/hosting.ts +77 -0
  258. package/src/internal/init-project.ts +333 -51
  259. package/src/internal/install-cursor-skills.ts +327 -0
  260. package/src/internal/logs-client.ts +442 -0
  261. package/src/internal/open-browser.ts +41 -0
  262. package/src/internal/playground/toolchain.ts +15 -13
  263. package/src/internal/playground-proxy.ts +576 -0
  264. package/src/internal/prompt-context.ts +95 -0
  265. package/src/internal/reminder-runner.ts +50 -6
  266. package/src/internal/reminder-store.ts +21 -0
  267. package/src/internal/request-headers.ts +23 -0
  268. package/src/internal/resolve-prod-target.ts +150 -0
  269. package/src/internal/run-client.ts +39 -36
  270. package/src/internal/server.ts +223 -28
  271. package/src/internal/session-engine.ts +307 -10
  272. package/src/internal/sessions-client.ts +182 -0
  273. package/src/internal/storage-coordinator.ts +615 -0
  274. package/src/internal/stream-progress.ts +36 -2
  275. package/src/internal/terminal-style.ts +74 -0
  276. package/src/internal/trajectory.ts +91 -13
  277. package/src/internal/workspace.ts +42 -4
  278. package/src/storage.ts +325 -0
  279. package/src/types.ts +82 -8
  280. package/dist/docs/assets/chunks/@localSearchIndexroot.CcVk1uKq.js +0 -1
  281. package/dist/docs/assets/index.md.BPKcj5AI.js +0 -20
  282. package/dist/docs/assets/quickstart.md.tVPiGK_L.js +0 -35
  283. package/dist/docs/assets/quickstart.md.tVPiGK_L.lean.js +0 -1
  284. package/dist/docs/assets/scaffolding-agents.md.CyYfWGdc.js +0 -1
  285. package/dist/docs/assets/scaffolding-agents.md.CyYfWGdc.lean.js +0 -1
  286. package/dist/playground/assets/cursor-icons-outline-oY2V_mvK.woff2 +0 -0
  287. package/dist/playground/assets/index-1K-hG-7p.css +0 -1
  288. package/dist/playground/assets/index-FlWjhg3x.js +0 -79
  289. /package/dist/docs/assets/{evals.md.DPZ_MAnI.lean.js → evals.md.DAgEc_hL.lean.js} +0 -0
  290. /package/dist/docs/assets/{guides_agent-to-agent.md.CrtrsySy.lean.js → guides_agent-to-agent.md.Bpzgq2Pq.lean.js} +0 -0
  291. /package/dist/docs/assets/{guides_cloud-runtime.md.CYlNMTNp.lean.js → guides_cloud-runtime.md.gVzabdQL.lean.js} +0 -0
  292. /package/dist/docs/assets/{guides_human-in-the-loop.md.Dvuctx7s.lean.js → guides_human-in-the-loop.md.DlUqsp1S.lean.js} +0 -0
  293. /package/dist/docs/assets/{guides_webhooks.md.hFTik3lf.lean.js → guides_webhooks.md.B1EswtUu.lean.js} +0 -0
  294. /package/dist/docs/assets/{reference_connections.md.C3vNH_DE.lean.js → reference_connections.md.zaEYCLHT.lean.js} +0 -0
  295. /package/dist/docs/assets/{reference_http-api.md.DBAahtdz.lean.js → reference_http-api.md.Dx_nmDG6.lean.js} +0 -0
  296. /package/dist/docs/assets/{reference_schedules.md.D7qijxLk.lean.js → reference_schedules.md.w_F2mXB6.lean.js} +0 -0
  297. /package/dist/docs/assets/{reference_subagents.md.CIRAVcPK.lean.js → reference_subagents.md.zWAMNfi1.lean.js} +0 -0
  298. /package/dist/docs/assets/{reference_tools.md.DF5kwlt0.lean.js → reference_tools.md.CqgJroI0.lean.js} +0 -0
@@ -17,6 +17,10 @@ import {
17
17
  resolveGitHubInstallationId,
18
18
  resolveGitHubPrivateKey,
19
19
  } from "./auth.js";
20
+ import {
21
+ type CursorAccountGithubTokenResolver,
22
+ isCursorAccountGithubTokenResolver,
23
+ } from "./cursor-account.js";
20
24
  import type { GitHubChannelCredentials } from "./types.js";
21
25
 
22
26
  export type GitHubJsonObject = Record<string, unknown>;
@@ -91,19 +95,31 @@ export async function createGitHubOctokit(input: {
91
95
  credentials?: GitHubChannelCredentials;
92
96
  installationId?: number;
93
97
  }): Promise<Octokit> {
94
- const requestOptions =
95
- input.api?.fetch === undefined ? undefined : { fetch: input.api.fetch };
96
- const baseUrl = input.api?.apiBaseUrl;
98
+ const transport = githubOctokitTransport(input.api);
99
+
100
+ const dynamicToken: CursorAccountGithubTokenResolver | undefined =
101
+ isCursorAccountGithubTokenResolver(input.credentials?.token)
102
+ ? input.credentials.token
103
+ : isCursorAccountGithubTokenResolver(input.credentials?.installationToken)
104
+ ? input.credentials.installationToken
105
+ : undefined;
106
+ if (dynamicToken !== undefined) {
107
+ const octokit = new Octokit(transport);
108
+ octokit.hook.before("request", async (request) => {
109
+ const token = await resolveCredentialValue(dynamicToken);
110
+ if (token === undefined) {
111
+ throw new Error("githubChannel: dynamic GitHub token is unavailable.");
112
+ }
113
+ request.headers.authorization = `Bearer ${token}`;
114
+ });
115
+ return octokit;
116
+ }
97
117
 
98
118
  const explicit =
99
119
  (await resolveCredentialValue(input.credentials?.token)) ??
100
120
  (await resolveCredentialValue(input.credentials?.installationToken));
101
121
  if (explicit !== undefined) {
102
- return new Octokit({
103
- auth: explicit,
104
- ...(baseUrl === undefined ? {} : { baseUrl }),
105
- ...(requestOptions === undefined ? {} : { request: requestOptions }),
106
- });
122
+ return new Octokit({ ...transport, auth: explicit });
107
123
  }
108
124
 
109
125
  const installationId = await resolveGitHubInstallationId(
@@ -118,26 +134,34 @@ export async function createGitHubOctokit(input: {
118
134
  input.credentials?.privateKey
119
135
  );
120
136
  return new Octokit({
137
+ ...transport,
121
138
  authStrategy: createAppAuth,
122
139
  auth: {
123
140
  appId,
124
141
  privateKey,
125
142
  installationId,
126
143
  },
127
- ...(baseUrl === undefined ? {} : { baseUrl }),
128
- ...(requestOptions === undefined ? {} : { request: requestOptions }),
129
144
  });
130
145
  }
131
146
 
132
147
  // Local testing: ambient PAT / `gh auth token` when App creds are unset.
133
- const token = await resolveGitHubAccessToken(input);
134
148
  return new Octokit({
135
- auth: token,
136
- ...(baseUrl === undefined ? {} : { baseUrl }),
137
- ...(requestOptions === undefined ? {} : { request: requestOptions }),
149
+ ...transport,
150
+ auth: await resolveGitHubAccessToken(input),
138
151
  });
139
152
  }
140
153
 
154
+ /** Shared `baseUrl` / custom `fetch` for every Octokit constructed here. */
155
+ function githubOctokitTransport(api: GitHubApiOptions | undefined): {
156
+ baseUrl?: string;
157
+ request?: { fetch: typeof fetch };
158
+ } {
159
+ return {
160
+ baseUrl: api?.apiBaseUrl,
161
+ request: api?.fetch === undefined ? undefined : { fetch: api.fetch },
162
+ };
163
+ }
164
+
141
165
  /**
142
166
  * Call a GitHub REST path with channel auth. Prefer typed Octokit methods via
143
167
  * {@link createGitHubOctokit} / `ctx.github.getOctokit()` when possible.
@@ -152,15 +176,10 @@ export async function callGitHubApi<T = unknown>(input: {
152
176
  options?: { auth?: boolean; headers?: Readonly<Record<string, string>> };
153
177
  }): Promise<GitHubApiResponse<T>> {
154
178
  if (input.options?.auth === false) {
155
- const octokit = new Octokit({
156
- ...(input.api?.apiBaseUrl === undefined
157
- ? {}
158
- : { baseUrl: input.api.apiBaseUrl }),
159
- ...(input.api?.fetch === undefined
160
- ? {}
161
- : { request: { fetch: input.api.fetch } }),
162
- });
163
- return requestWithOctokit(octokit, input);
179
+ return requestWithOctokit(
180
+ new Octokit(githubOctokitTransport(input.api)),
181
+ input
182
+ );
164
183
  }
165
184
 
166
185
  const octokit = await createGitHubOctokit({
@@ -0,0 +1,165 @@
1
+ /**
2
+ * Cursor-account mode for GitHub channels.
3
+ *
4
+ * The channel declares the intent at definition time. The serve host binds
5
+ * this placeholder to its signed-in Cursor account after it resolves the
6
+ * repository scope into private runtime metadata (never by rewriting the
7
+ * authored `cursorAccount` options object).
8
+ */
9
+
10
+ import type { GitHubChannelOptions } from "./types.js";
11
+
12
+ export const CURSOR_GITHUB_MAX_REPOS = 20;
13
+ const CURSOR_GITHUB_REPO_PATTERN = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/;
14
+ const cursorAccountTokenResolvers = new WeakSet<object>();
15
+
16
+ /** Least → most privilege. Host mints one lease at the max requested tier. */
17
+ export const CURSOR_GITHUB_PERMISSIONS = [
18
+ "read",
19
+ "pr-write",
20
+ "contents-write",
21
+ ] as const;
22
+
23
+ export type CursorGithubPermissions =
24
+ (typeof CURSOR_GITHUB_PERMISSIONS)[number];
25
+
26
+ export interface CursorGithubRepoScope {
27
+ owner: string;
28
+ repos: readonly string[];
29
+ permissions: CursorGithubPermissions;
30
+ }
31
+
32
+ export type CursorAccountGithubTokenResolver = () => Promise<string>;
33
+
34
+ export interface PendingCursorGithubCredentials {
35
+ bind(getToken: () => Promise<string>): void;
36
+ getToken(): Promise<string>;
37
+ }
38
+
39
+ export interface GithubCursorAccountRuntime {
40
+ /** Authored channel options (not rewritten). */
41
+ options: GitHubChannelOptions;
42
+ credentials: PendingCursorGithubCredentials;
43
+ /**
44
+ * Normalized repo + permissions scope when `cursorAccount` is an object.
45
+ * Absent for `cursorAccount: true` (scope comes from serve `--repo`).
46
+ */
47
+ scope: CursorGithubRepoScope | undefined;
48
+ }
49
+
50
+ const runtimeByDefinition = new WeakMap<object, GithubCursorAccountRuntime>();
51
+
52
+ export function parseCursorGithubPermissions(
53
+ value: unknown,
54
+ fallback: CursorGithubPermissions = "pr-write"
55
+ ): CursorGithubPermissions {
56
+ if (value === undefined) {
57
+ return fallback;
58
+ }
59
+ if (value === "read" || value === "pr-write" || value === "contents-write") {
60
+ return value;
61
+ }
62
+ throw new Error(
63
+ 'Cursor account GitHub permissions must be "read", "pr-write", or "contents-write".'
64
+ );
65
+ }
66
+
67
+ export function parseCursorGithubRepoScope(
68
+ values: readonly string[],
69
+ permissions: CursorGithubPermissions = "pr-write"
70
+ ): CursorGithubRepoScope {
71
+ const repos = [
72
+ ...new Set(values.map((repo) => repo.trim().toLowerCase()).filter(Boolean)),
73
+ ];
74
+ if (repos.length === 0) {
75
+ throw new Error(
76
+ "Cursor account GitHub credentials require at least one repository."
77
+ );
78
+ }
79
+ if (repos.length > CURSOR_GITHUB_MAX_REPOS) {
80
+ throw new Error(
81
+ `Cursor account GitHub credentials support at most ${CURSOR_GITHUB_MAX_REPOS} repositories.`
82
+ );
83
+ }
84
+ for (const repo of repos) {
85
+ if (!CURSOR_GITHUB_REPO_PATTERN.test(repo) || repo.includes("..")) {
86
+ throw new Error(
87
+ `Invalid Cursor account GitHub repository "${repo}"; expected owner/repo.`
88
+ );
89
+ }
90
+ }
91
+ const owner = repos[0]?.split("/", 1)[0];
92
+ if (owner === undefined) {
93
+ throw new Error("Cursor account GitHub repository owner is missing.");
94
+ }
95
+ if (repos.some((repo) => repo.split("/", 1)[0] !== owner)) {
96
+ throw new Error(
97
+ "Cursor account GitHub repositories must share one owner for a single installation token."
98
+ );
99
+ }
100
+ return {
101
+ owner,
102
+ repos,
103
+ permissions: parseCursorGithubPermissions(permissions),
104
+ };
105
+ }
106
+
107
+ /** One host credential: the most privileged requested tier wins. */
108
+ export function resolveCursorGithubPermissions(
109
+ values: readonly CursorGithubPermissions[]
110
+ ): CursorGithubPermissions {
111
+ let max: CursorGithubPermissions = "read";
112
+ for (const value of values) {
113
+ if (
114
+ CURSOR_GITHUB_PERMISSIONS.indexOf(value) >
115
+ CURSOR_GITHUB_PERMISSIONS.indexOf(max)
116
+ ) {
117
+ max = value;
118
+ }
119
+ }
120
+ return values.length === 0 ? "pr-write" : max;
121
+ }
122
+
123
+ export function createCursorAccountGithubTokenResolver(
124
+ getToken: () => Promise<string>
125
+ ): CursorAccountGithubTokenResolver {
126
+ const resolver = () => getToken();
127
+ cursorAccountTokenResolvers.add(resolver);
128
+ return resolver;
129
+ }
130
+
131
+ export function isCursorAccountGithubTokenResolver(
132
+ value: unknown
133
+ ): value is CursorAccountGithubTokenResolver {
134
+ return typeof value === "function" && cursorAccountTokenResolvers.has(value);
135
+ }
136
+
137
+ export function createPendingCursorGithubCredentials(): PendingCursorGithubCredentials {
138
+ let getBoundToken: (() => Promise<string>) | undefined;
139
+ return {
140
+ bind(getToken) {
141
+ getBoundToken = getToken;
142
+ },
143
+ getToken() {
144
+ if (getBoundToken === undefined) {
145
+ throw new Error(
146
+ "githubChannel({ cursorAccount: true }) has not been bound to a signed-in Cursor host."
147
+ );
148
+ }
149
+ return getBoundToken();
150
+ },
151
+ };
152
+ }
153
+
154
+ export function registerGithubCursorAccountRuntime(
155
+ definition: object,
156
+ runtime: GithubCursorAccountRuntime
157
+ ): void {
158
+ runtimeByDefinition.set(definition, runtime);
159
+ }
160
+
161
+ export function getGithubCursorAccountRuntime(
162
+ definition: object
163
+ ): GithubCursorAccountRuntime | undefined {
164
+ return runtimeByDefinition.get(definition);
165
+ }
@@ -23,6 +23,13 @@ import {
23
23
  type GitHubBindingConfig,
24
24
  type GitHubBindingState,
25
25
  } from "./binding.js";
26
+ import {
27
+ createCursorAccountGithubTokenResolver,
28
+ createPendingCursorGithubCredentials,
29
+ type PendingCursorGithubCredentials,
30
+ parseCursorGithubRepoScope,
31
+ registerGithubCursorAccountRuntime,
32
+ } from "./cursor-account.js";
26
33
  import { buildDefaultGitHubEvents } from "./defaults.js";
27
34
  import { deriveGitHubWebhookEvents, GITHUB_CHANNEL_KIND } from "./events.js";
28
35
  import {
@@ -581,9 +588,36 @@ export function getGitHubChannelOptions(
581
588
  export function githubChannel(
582
589
  options: GitHubChannelOptions = {}
583
590
  ): ChannelDefinition<GitHubChannelState> {
591
+ const usesCursorAccount =
592
+ options.cursorAccount === true || typeof options.cursorAccount === "object";
593
+ // Normalized scope lives on the private runtime — never rewrite authored
594
+ // `cursorAccount` on the options object the author passed in.
595
+ const cursorScope =
596
+ typeof options.cursorAccount === "object"
597
+ ? parseCursorGithubRepoScope(
598
+ options.cursorAccount.repos,
599
+ options.cursorAccount.permissions
600
+ )
601
+ : undefined;
602
+
603
+ let cursorCredentials: PendingCursorGithubCredentials | undefined;
604
+ let credentials = options.credentials;
605
+ if (usesCursorAccount) {
606
+ if (hasDedicatedGitHubApiCredentials(options)) {
607
+ throw new Error(
608
+ "githubChannel({ cursorAccount: true }) cannot be combined with token or GitHub App credentials."
609
+ );
610
+ }
611
+ const pending = createPendingCursorGithubCredentials();
612
+ cursorCredentials = pending;
613
+ credentials = {
614
+ ...options.credentials,
615
+ token: createCursorAccountGithubTokenResolver(() => pending.getToken()),
616
+ };
617
+ }
618
+
584
619
  const routePath = options.path ?? "/";
585
- const webhookSecret =
586
- options.credentials?.webhookSecret ?? envWebhookSecret();
620
+ const webhookSecret = credentials?.webhookSecret ?? envWebhookSecret();
587
621
  // With a secret the HMAC is the request auth (allowAll). Without one, prod
588
622
  // stays loopback-strict; dev admits unsigned deliveries from a loopback peer
589
623
  // only (loopbackGitHubDev) — not the LAN. Admits `gh webhook forward`
@@ -607,8 +641,12 @@ export function githubChannel(
607
641
  ),
608
642
  ]);
609
643
 
644
+ const channelOptions: GitHubChannelOptions = {
645
+ ...options,
646
+ credentials,
647
+ };
610
648
  const events: ChannelEventHandlers<GitHubChannelState> = {
611
- ...buildDefaultGitHubEvents({ ...options }),
649
+ ...buildDefaultGitHubEvents({ ...channelOptions }),
612
650
  ...options.events,
613
651
  };
614
652
 
@@ -618,7 +656,7 @@ export function githubChannel(
618
656
  events,
619
657
  meta: {
620
658
  kind: GITHUB_CHANNEL_KIND,
621
- githubWebhookEvents: deriveGitHubWebhookEvents(options),
659
+ githubWebhookEvents: deriveGitHubWebhookEvents(channelOptions),
622
660
  },
623
661
  onStart: options.onStart,
624
662
  onStop: options.onStop,
@@ -630,14 +668,36 @@ export function githubChannel(
630
668
  bodySchema: z.unknown(),
631
669
  description: "GitHub webhook ingress",
632
670
  handler: async (request, args) =>
633
- handleGitHubWebhookRequest({ options, request, args }),
671
+ handleGitHubWebhookRequest({
672
+ options: channelOptions,
673
+ request,
674
+ args,
675
+ }),
634
676
  }),
635
677
  ],
636
678
  });
637
- githubChannelOptionsByDefinition.set(definition, options);
679
+ githubChannelOptionsByDefinition.set(definition, channelOptions);
680
+ if (cursorCredentials !== undefined) {
681
+ registerGithubCursorAccountRuntime(definition, {
682
+ options,
683
+ credentials: cursorCredentials,
684
+ scope: cursorScope,
685
+ });
686
+ }
638
687
  return definition;
639
688
  }
640
689
 
690
+ function hasDedicatedGitHubApiCredentials(
691
+ options: GitHubChannelOptions
692
+ ): boolean {
693
+ return (
694
+ options.credentials?.token !== undefined ||
695
+ options.credentials?.installationToken !== undefined ||
696
+ options.credentials?.appId !== undefined ||
697
+ options.credentials?.privateKey !== undefined
698
+ );
699
+ }
700
+
641
701
  async function handlePullRequest(input: {
642
702
  options: GitHubChannelOptions;
643
703
  bindingConfig: GitHubBindingConfig;
@@ -6,8 +6,8 @@
6
6
  *
7
7
  * export default githubChannel({
8
8
  * botName: "my-agent",
9
- * // API auth: App installation (preferred) GITHUB_TOKEN / GH_TOKEN → `gh auth`
10
- * credentials: { webhookSecret: () => process.env.GITHUB_WEBHOOK_SECRET },
9
+ * // Reuses `agentkit login` for events, ctx.github, ctx.host.github, and gh.
10
+ * cursorAccount: { repos: ["owner/repo"] },
11
11
  * onComment: (ctx, comment) => ({ auth: defaultGitHubAuth(ctx) }),
12
12
  * onPullRequest: (ctx, pr) =>
13
13
  * pr.action === "opened" ? { auth: defaultGitHubAuth(ctx) } : null,
@@ -421,6 +421,25 @@ export interface GitHubChannelOptions {
421
421
  * API calls prefer App installation tokens, then local PAT / `gh auth`.
422
422
  */
423
423
  credentials?: GitHubChannelCredentials;
424
+ /**
425
+ * Use the signed-in Cursor account's GitHub connection for inbound events
426
+ * and outbound API calls. `true` takes repository scope from
427
+ * `serve --cursor-events --repo`; `{ repos }` makes the channel self-contained.
428
+ * `permissions` chooses the minted token tier (`"pr-write"` default).
429
+ * Cannot be combined with explicit token or GitHub App credentials.
430
+ */
431
+ cursorAccount?:
432
+ | boolean
433
+ | {
434
+ repos: readonly string[];
435
+ /**
436
+ * Token capability tier:
437
+ * - `"read"` — PR/issue/status read
438
+ * - `"pr-write"` (default) — comments / PR+issue write, no `contents:write`
439
+ * - `"contents-write"` — also push code (host-held; prefer only when needed)
440
+ */
441
+ permissions?: "read" | "pr-write" | "contents-write";
442
+ };
424
443
  /** Optional GitHub API transport overrides (`apiBaseUrl`, `fetch`). */
425
444
  api?: GitHubApiOptions;
426
445
  /**
@@ -54,13 +54,24 @@ import {
54
54
  startSlackSocketMode,
55
55
  } from "./socket-mode.js";
56
56
  import { buildToolApprovalEvents } from "./tool-approval-events.js";
57
- import type { SlackChannelOptions, SlackChannelState } from "./types.js";
57
+ import {
58
+ assertSlackCursorAgentName,
59
+ type SlackChannelOptions,
60
+ type SlackChannelState,
61
+ type SlackCursorAgentName,
62
+ } from "./types.js";
58
63
 
59
64
  /**
60
65
  * Create a Slack channel. Author as `agent/channels/slack.ts` default export.
66
+ *
67
+ * When `cursorAccount` is on, `agentName` must be a single token (no
68
+ * whitespace) — string literals with spaces fail at the type level;
69
+ * runtime values are still checked by {@link assertSlackCursorAgentName}.
61
70
  */
62
- export function slackChannel(
63
- options: SlackChannelOptions = {}
71
+ export function slackChannel<const Name extends string = string>(
72
+ options: Omit<SlackChannelOptions, "agentName"> & {
73
+ agentName?: SlackCursorAgentName<Name>;
74
+ } = {}
64
75
  ): ChannelDefinition<SlackChannelState> {
65
76
  const cursorAccount = options.cursorAccount === true;
66
77
  if (cursorAccount) {
@@ -71,6 +82,9 @@ export function slackChannel(
71
82
  "slackChannel({ cursorAccount: true }) uses the Cursor account's Slack connection — do not also set credentials/envPrefix. Author a second slack channel file for a dedicated Slack app."
72
83
  );
73
84
  }
85
+ if (options.agentName !== undefined) {
86
+ assertSlackCursorAgentName(options.agentName);
87
+ }
74
88
  // Channel watching is Socket Mode only — cursorAccount agents must be
75
89
  // explicitly addressed (@mention, DM, or claimed-thread reply).
76
90
  if (options.engagement?.channelPosts !== undefined) {
@@ -210,6 +210,46 @@ export interface SlackEngagementOptions {
210
210
  channelPosts?: SlackChannelPostsOptions;
211
211
  }
212
212
 
213
+ /**
214
+ * Whitespace forbidden in {@link SlackChannelOptions.agentName}. The Cursor
215
+ * Slack router matches on leading words; multi-word names collide with Named
216
+ * Agent shortened-prefix matching (`Approval …` stealing `ApprovalBuddy`).
217
+ */
218
+ type SlackAgentNameWhitespace = " " | "\t" | "\n" | "\r" | "\f" | "\v";
219
+
220
+ /**
221
+ * Single-token Cursor Slack handle for `cursorAccount` routing
222
+ * (`@Cursor <name> …`). String literals that contain whitespace become
223
+ * `never` (type error at the call site); plain `string` stays `string` and
224
+ * is still rejected at runtime by {@link assertSlackCursorAgentName}.
225
+ */
226
+ export type SlackCursorAgentName<S extends string = string> = string extends S
227
+ ? string
228
+ : S extends `${string}${SlackAgentNameWhitespace}${string}`
229
+ ? never
230
+ : S;
231
+
232
+ const SLACK_CURSOR_AGENT_NAME_WHITESPACE = /\s/;
233
+
234
+ /**
235
+ * Runtime guard for {@link SlackChannelOptions.agentName}. Call from
236
+ * `slackChannel({ cursorAccount: true })` construction and serve-time
237
+ * name resolution so derived defaults cannot sneak spaces in.
238
+ */
239
+ export function assertSlackCursorAgentName(name: string): void {
240
+ const trimmed = name.trim();
241
+ if (trimmed.length === 0) {
242
+ throw new Error(
243
+ 'slackChannel({ cursorAccount: true }) agentName must be a non-empty single token (no whitespace), e.g. "ApprovalBuddy".'
244
+ );
245
+ }
246
+ if (SLACK_CURSOR_AGENT_NAME_WHITESPACE.test(trimmed)) {
247
+ throw new Error(
248
+ `slackChannel({ cursorAccount: true }) agentName must be a single token with no whitespace (got ${JSON.stringify(name)}). Use PascalCase like "ApprovalBuddy" — multi-word names break @Cursor routing.`
249
+ );
250
+ }
251
+ }
252
+
213
253
  export interface SlackChannelOptions {
214
254
  credentials?: SlackCredentials;
215
255
  /**
@@ -242,12 +282,13 @@ export interface SlackChannelOptions {
242
282
  */
243
283
  cursorAccount?: boolean;
244
284
  /**
245
- * Display name registered with the Cursor backend when
285
+ * Single-token display name registered with the Cursor backend when
246
286
  * {@link cursorAccount} is on: `@Cursor <agentName> …` routes here, and
247
- * replies post under this username. Defaults to a name derived from the
287
+ * replies post under this username. **No whitespace** prefer PascalCase
288
+ * (`ApprovalBuddy`). Defaults to a PascalCase name derived from the
248
289
  * agent's mount slug (or project name).
249
290
  */
250
- agentName?: string;
291
+ agentName?: SlackCursorAgentName;
251
292
  /** Avatar for posts when {@link cursorAccount} is on. */
252
293
  agentIcon?: { url?: string; emoji?: string };
253
294
  /**
package/src/index.ts CHANGED
@@ -104,6 +104,19 @@ export type {
104
104
  } from "./reminders.js";
105
105
  export { defineSchedule } from "./schedules.js";
106
106
  export { defineSkill } from "./skills.js";
107
+ export type {
108
+ StorageConfig,
109
+ StorageContext,
110
+ StorageDefinition,
111
+ StorageEntry,
112
+ StoragePolicy,
113
+ StorageRestorePolicy,
114
+ } from "./storage.js";
115
+ export {
116
+ defineStorage,
117
+ STORAGE_KEY_ROOT,
118
+ storageKeys,
119
+ } from "./storage.js";
107
120
  export { defineTool } from "./tools.js";
108
121
  export type * from "./types.js";
109
122
  export {