@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
@@ -121,6 +121,9 @@ export class ReminderRunner {
121
121
  async start(): Promise<void> {
122
122
  if (this.started) return;
123
123
  this.started = true;
124
+ // Materialize sink-backed reminders onto local disk before arming
125
+ // (local wins when both sides have the same id).
126
+ await this.hydrateFromStorage();
124
127
  const armed = await this.store.listArmed();
125
128
  let restored = 0;
126
129
  let disarmedOrphan = 0;
@@ -148,6 +151,47 @@ export class ReminderRunner {
148
151
  }
149
152
  }
150
153
 
154
+ /**
155
+ * Pull reminder records from `defineStorage` into `<stateRoot>/reminders`
156
+ * when local disk is empty for that id. Failures are logged and skipped.
157
+ */
158
+ private async hydrateFromStorage(): Promise<void> {
159
+ const storage = this.engine.storage;
160
+ if (storage === undefined || !storage.canBulkRestore) {
161
+ return;
162
+ }
163
+ let hydrated = 0;
164
+ try {
165
+ const remote = await storage.listReminders();
166
+ for (const record of remote) {
167
+ const local = await this.store.get(record.id);
168
+ if (local !== undefined) {
169
+ continue;
170
+ }
171
+ // Local write only — re-mirroring would just echo the sink.
172
+ await this.store.save(record);
173
+ hydrated += 1;
174
+ }
175
+ } catch (error) {
176
+ const message = error instanceof Error ? error.message : String(error);
177
+ this.logger(
178
+ `[agent-serve] reminders: storage hydrate failed: ${message}`
179
+ );
180
+ return;
181
+ }
182
+ if (hydrated > 0) {
183
+ this.logger(
184
+ `[agent-serve] reminders: hydrated ${hydrated} reminder(s) from storage`
185
+ );
186
+ }
187
+ }
188
+
189
+ /** Persist locally and mirror into the authored storage sink when present. */
190
+ private async persist(record: ReminderRecord): Promise<void> {
191
+ await this.store.save(record);
192
+ this.engine.storage?.reminder(record);
193
+ }
194
+
151
195
  stop(): void {
152
196
  this.started = false;
153
197
  for (const timer of this.timers.values()) {
@@ -209,7 +253,7 @@ export class ReminderRunner {
209
253
  updatedAt: now,
210
254
  };
211
255
 
212
- await this.store.save(record);
256
+ await this.persist(record);
213
257
  this.handlers.set(id, {
214
258
  run: input.run,
215
259
  untilFn,
@@ -273,7 +317,7 @@ export class ReminderRunner {
273
317
  disarmReason: reason,
274
318
  updatedAt: new Date().toISOString(),
275
319
  };
276
- await this.store.save(updated);
320
+ await this.persist(updated);
277
321
  this.handlers.delete(id);
278
322
  return toInfo(updated);
279
323
  }
@@ -662,7 +706,7 @@ export class ReminderRunner {
662
706
  disarmReason: reason,
663
707
  updatedAt: new Date().toISOString(),
664
708
  };
665
- await this.store.save(updated);
709
+ await this.persist(updated);
666
710
  this.handlers.delete(record.id);
667
711
  }
668
712
 
@@ -711,7 +755,7 @@ export class ReminderRunner {
711
755
  : String(reschedule.at),
712
756
  updatedAt: new Date().toISOString(),
713
757
  };
714
- await this.store.save(updated);
758
+ await this.persist(updated);
715
759
  this.armTimer(updated);
716
760
  return;
717
761
  }
@@ -725,7 +769,7 @@ export class ReminderRunner {
725
769
  disarmReason: "one_shot_complete",
726
770
  updatedAt: new Date().toISOString(),
727
771
  };
728
- await this.store.save(updated);
772
+ await this.persist(updated);
729
773
  this.handlers.delete(current.id);
730
774
  return;
731
775
  }
@@ -747,7 +791,7 @@ export class ReminderRunner {
747
791
  nextFireAtMs,
748
792
  updatedAt: new Date().toISOString(),
749
793
  };
750
- await this.store.save(updated);
794
+ await this.persist(updated);
751
795
  this.armTimer(updated);
752
796
  }
753
797
  }
@@ -66,6 +66,27 @@ export interface ReminderRecord {
66
66
  updatedAt: string;
67
67
  }
68
68
 
69
+ /** Narrow a sink value to a {@link ReminderRecord} (startup hydrate). */
70
+ export function isReminderRecord(value: unknown): value is ReminderRecord {
71
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
72
+ return false;
73
+ }
74
+ const record = value as Partial<ReminderRecord>;
75
+ return (
76
+ record.version === REMINDER_SNAPSHOT_VERSION &&
77
+ typeof record.id === "string" &&
78
+ record.id !== "" &&
79
+ typeof record.purpose === "string" &&
80
+ typeof record.channelId === "string" &&
81
+ typeof record.continuationToken === "string" &&
82
+ typeof record.scheduleKind === "string" &&
83
+ typeof record.scheduleValue === "string" &&
84
+ typeof record.status === "string" &&
85
+ typeof record.nextFireAtMs === "number" &&
86
+ Number.isFinite(record.nextFireAtMs)
87
+ );
88
+ }
89
+
69
90
  export class ReminderStore {
70
91
  constructor(private readonly rootDir: string) {}
71
92
 
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Merge Authorization bearer + arbitrary request headers for agent HTTP
3
+ * clients (local `--bearer-token`, hosted `engineAccess.headers`, etc.).
4
+ */
5
+
6
+ export interface RequestAuth {
7
+ bearerToken?: string;
8
+ /** Extra headers (e.g. X-Anyrun-Port-Token from engineAccess). */
9
+ headers?: Record<string, string>;
10
+ }
11
+
12
+ export function mergeRequestHeaders(
13
+ auth: RequestAuth | undefined
14
+ ): Record<string, string> {
15
+ const out: Record<string, string> = {};
16
+ if (auth?.headers !== undefined) {
17
+ Object.assign(out, auth.headers);
18
+ }
19
+ if (auth?.bearerToken !== undefined) {
20
+ out.authorization = `Bearer ${auth.bearerToken}`;
21
+ }
22
+ return out;
23
+ }
@@ -0,0 +1,150 @@
1
+ /**
2
+ * Resolve a hosted (managed) agent-serve deployment into a base URL +
3
+ * request headers for chat/run/call/eval `--prod`.
4
+ *
5
+ * Uses short-lived `engineAccess` from the deployment status route
6
+ * (Cursor API key on the management API; `X-Anyrun-Port-Token` on the
7
+ * engine). Alias tokens are out of scope here.
8
+ */
9
+
10
+ import { basename, resolve } from "node:path";
11
+ import { resolveDeployAuth } from "./cli-deploy.js";
12
+ import {
13
+ DeployApiError,
14
+ type DeploymentDetail,
15
+ slugFromDirectoryName,
16
+ validateDeploymentSlug,
17
+ } from "./deploy-client.js";
18
+ import { CLI_COMMAND_NAME as CLI } from "./distribution.js";
19
+ import { stderrPalette } from "./terminal-style.js";
20
+
21
+ /**
22
+ * Interactive CLI keep-alive for hosted engines. Without these, a hibernated
23
+ * Anyrun pod returns 417 `pod_hibernated` and never wakes. Matches the
24
+ * cloud-agent interactive keep-alive shape (lower ≤ upper, seconds).
25
+ */
26
+ export const PROD_ENGINE_WAKE_HEADERS: Readonly<Record<string, string>> = {
27
+ "x-anyrun-hibernation-lower-bound-s": "1800",
28
+ "x-anyrun-hibernation-upper-bound-s": "3600",
29
+ };
30
+
31
+ export interface ResolveProdTargetOptions {
32
+ dir: string;
33
+ cwd?: string;
34
+ /** Explicit deployment slug; otherwise derived from `--dir` basename. */
35
+ slug?: string;
36
+ team?: string;
37
+ apiKey?: string;
38
+ fetchImpl?: typeof fetch;
39
+ err?: (text: string) => void;
40
+ }
41
+
42
+ export interface ResolvedProdTarget {
43
+ agentUrl: string;
44
+ headers: Record<string, string>;
45
+ slug: string;
46
+ expiresAt: string;
47
+ }
48
+
49
+ /**
50
+ * Look up a running deployment and return its engineAccess URL/headers.
51
+ * Throws {@link Error} with a CLI-ready message on failure.
52
+ */
53
+ export async function resolveProdTarget(
54
+ options: ResolveProdTargetOptions
55
+ ): Promise<ResolvedProdTarget> {
56
+ const err =
57
+ options.err ?? ((text: string) => void process.stderr.write(text));
58
+ const slug = resolveProdSlug(options);
59
+ const auth = await resolveDeployAuth({
60
+ team: options.team,
61
+ apiKey: options.apiKey,
62
+ fetchImpl: options.fetchImpl,
63
+ err,
64
+ });
65
+ if (typeof auth === "number") {
66
+ throw new Error(
67
+ `Could not resolve Cursor credentials/team for --prod (see above).`
68
+ );
69
+ }
70
+
71
+ let detail: DeploymentDetail;
72
+ try {
73
+ detail = await auth.client.getDeployment({
74
+ teamId: auth.teamId,
75
+ slug,
76
+ });
77
+ } catch (error) {
78
+ if (error instanceof DeployApiError) {
79
+ throw new Error(
80
+ `Deployment "${slug}" (team ${auth.teamId}): ${error.message}`
81
+ );
82
+ }
83
+ throw error;
84
+ }
85
+
86
+ // `degraded` still serves the previous ACTIVE engine; allow runtime access
87
+ // when the control plane minted engineAccess for it.
88
+ const access = detail.engineAccess;
89
+ const statusOk = detail.status === "running" || detail.status === "degraded";
90
+ if (!statusOk) {
91
+ const lastError =
92
+ detail.lastError === null || detail.lastError === undefined
93
+ ? ""
94
+ : ` ${sanitizeCustomerFacingDetail(detail.lastError)}`;
95
+ throw new Error(
96
+ `Deployment "${slug}" is ${detail.status}, not running.${lastError}\n` +
97
+ `Deploy or wait: \`${CLI} deploy --slug ${slug}\` / \`${CLI} deployment ${slug}\``
98
+ );
99
+ }
100
+ if (access === null || access === undefined) {
101
+ throw new Error(
102
+ `Deployment "${slug}" is ${detail.status} but is not reachable yet. ` +
103
+ `Try \`${CLI} deployment ${slug}\` or redeploy.`
104
+ );
105
+ }
106
+
107
+ err(`${stderrPalette().dim(`Using hosted deployment "${slug}".`)}\n`);
108
+
109
+ return {
110
+ agentUrl: access.url.replace(/\/$/, ""),
111
+ headers: {
112
+ ...access.headers,
113
+ ...PROD_ENGINE_WAKE_HEADERS,
114
+ },
115
+ slug,
116
+ expiresAt: access.expiresAt,
117
+ };
118
+ }
119
+
120
+ /** Strip obvious hosting internals from customer-facing error fragments. */
121
+ function sanitizeCustomerFacingDetail(message: string): string {
122
+ return message
123
+ .replace(/https?:\/\/\S+/gi, "[url]")
124
+ .replace(/\bpod-[a-z0-9]+\b/gi, "[runtime]")
125
+ .replace(/\banyrun\b/gi, "runtime")
126
+ .replace(/\bcursorvm\.com\b/gi, "host");
127
+ }
128
+
129
+ /** Resolve the deployment slug the same way `deploy` does for a single dir. */
130
+ export function resolveProdSlug(options: {
131
+ dir: string;
132
+ cwd?: string;
133
+ slug?: string;
134
+ }): string {
135
+ if (options.slug !== undefined && options.slug !== "") {
136
+ const slugError = validateDeploymentSlug(options.slug);
137
+ if (slugError !== undefined) {
138
+ throw new Error(slugError);
139
+ }
140
+ return options.slug;
141
+ }
142
+ const dir = resolve(options.cwd ?? process.cwd(), options.dir);
143
+ const derived = slugFromDirectoryName(basename(dir));
144
+ if (derived === undefined) {
145
+ throw new Error(
146
+ `Could not derive a deployment slug from the directory name ${JSON.stringify(basename(dir))}; pass --slug.`
147
+ );
148
+ }
149
+ return derived;
150
+ }
@@ -7,6 +7,7 @@
7
7
  */
8
8
 
9
9
  import type { SessionEvent, SessionPurpose } from "../types.js";
10
+ import { mergeRequestHeaders, type RequestAuth } from "./request-headers.js";
10
11
  import { buildTrajectory, type Trajectory } from "./trajectory.js";
11
12
 
12
13
  /** Thrown when a turn stream exceeds `timeoutMs`; carries the session id. */
@@ -19,9 +20,8 @@ export class RunSessionTimeoutError extends Error {
19
20
  this.name = "RunSessionTimeoutError";
20
21
  }
21
22
  }
22
- export interface RunClientOptions {
23
+ export interface RunClientOptions extends RequestAuth {
23
24
  baseUrl: string;
24
- bearerToken?: string;
25
25
  /** Abort a hung turn. */
26
26
  timeoutMs?: number;
27
27
  /** Called for each stream event as it arrives (for CLI progress). */
@@ -72,6 +72,11 @@ export async function runSession(
72
72
  const allEvents: SessionEvent[] = [];
73
73
  let nextEventIndex = 0;
74
74
 
75
+ const auth: RequestAuth = {
76
+ bearerToken: options.bearerToken,
77
+ headers: options.headers,
78
+ };
79
+
75
80
  for (const message of options.messages) {
76
81
  const turn = await runOneTurn({
77
82
  baseUrl,
@@ -79,18 +84,13 @@ export async function runSession(
79
84
  sessionId,
80
85
  continuationToken,
81
86
  startIndex: sessionId === undefined ? 0 : nextEventIndex,
82
- bearerToken: options.bearerToken,
87
+ auth,
83
88
  timeoutMs: options.timeoutMs,
84
89
  onEvent: options.onEvent,
85
- ...(sessionId === undefined && options.purpose !== undefined
86
- ? { purpose: options.purpose }
87
- : {}),
88
- ...(sessionId === undefined && options.workspaceDir !== undefined
89
- ? { workspaceDir: options.workspaceDir }
90
- : {}),
91
- ...(sessionId === undefined && options.workspaceFiles !== undefined
92
- ? { workspaceFiles: options.workspaceFiles }
93
- : {}),
90
+ purpose: sessionId === undefined ? options.purpose : undefined,
91
+ workspaceDir: sessionId === undefined ? options.workspaceDir : undefined,
92
+ workspaceFiles:
93
+ sessionId === undefined ? options.workspaceFiles : undefined,
94
94
  });
95
95
  sessionId = turn.sessionId;
96
96
  continuationToken = turn.continuationToken;
@@ -128,7 +128,7 @@ interface OneTurnArgs {
128
128
  workspaceDir?: string;
129
129
  workspaceFiles?: Record<string, string>;
130
130
  startIndex: number;
131
- bearerToken?: string;
131
+ auth?: RequestAuth;
132
132
  timeoutMs?: number;
133
133
  onEvent?: (event: SessionEvent) => void;
134
134
  }
@@ -145,20 +145,21 @@ async function runOneTurn(args: OneTurnArgs): Promise<OneTurnResult> {
145
145
  let continuationToken = args.continuationToken;
146
146
 
147
147
  if (sessionId === undefined) {
148
+ const body: Record<string, unknown> = { message: args.message };
149
+ if (args.purpose !== undefined) {
150
+ body.purpose = args.purpose;
151
+ }
152
+ if (args.workspaceDir !== undefined) {
153
+ body.workspaceDir = args.workspaceDir;
154
+ }
155
+ if (args.workspaceFiles !== undefined) {
156
+ body.workspaceFiles = args.workspaceFiles;
157
+ }
148
158
  const created = await postJson(
149
159
  args.baseUrl,
150
160
  "/v1/session",
151
- {
152
- message: args.message,
153
- ...(args.purpose === undefined ? {} : { purpose: args.purpose }),
154
- ...(args.workspaceDir === undefined
155
- ? {}
156
- : { workspaceDir: args.workspaceDir }),
157
- ...(args.workspaceFiles === undefined
158
- ? {}
159
- : { workspaceFiles: args.workspaceFiles }),
160
- },
161
- args.bearerToken
161
+ body,
162
+ args.auth
162
163
  );
163
164
  if (created.status >= 400 || created.body.ok === false) {
164
165
  throw new Error(
@@ -172,7 +173,7 @@ async function runOneTurn(args: OneTurnArgs): Promise<OneTurnResult> {
172
173
  args.baseUrl,
173
174
  `/v1/session/${sessionId}`,
174
175
  { message: args.message, continuationToken },
175
- args.bearerToken
176
+ args.auth
176
177
  );
177
178
  if (resp.status >= 400 || resp.body.ok === false) {
178
179
  throw new Error(
@@ -190,7 +191,7 @@ async function runOneTurn(args: OneTurnArgs): Promise<OneTurnResult> {
190
191
  baseUrl: args.baseUrl,
191
192
  sessionId,
192
193
  startIndex: args.startIndex,
193
- bearerToken: args.bearerToken,
194
+ auth: args.auth,
194
195
  timeoutMs: args.timeoutMs,
195
196
  onEvent: args.onEvent,
196
197
  });
@@ -209,7 +210,7 @@ async function collectStream(args: {
209
210
  baseUrl: string;
210
211
  sessionId: string;
211
212
  startIndex: number;
212
- bearerToken?: string;
213
+ auth?: RequestAuth;
213
214
  timeoutMs?: number;
214
215
  onEvent?: (event: SessionEvent) => void;
215
216
  }): Promise<SessionEvent[]> {
@@ -223,7 +224,7 @@ async function collectStream(args: {
223
224
  const resp = await fetch(
224
225
  `${args.baseUrl}/v1/session/${args.sessionId}/stream?startIndex=${args.startIndex}`,
225
226
  {
226
- headers: authHeaders(args.bearerToken),
227
+ headers: mergeRequestHeaders(args.auth),
227
228
  signal: controller.signal,
228
229
  }
229
230
  );
@@ -283,23 +284,17 @@ async function collectStream(args: {
283
284
  }
284
285
  }
285
286
 
286
- function authHeaders(bearerToken: string | undefined): Record<string, string> {
287
- return bearerToken === undefined
288
- ? {}
289
- : { authorization: `Bearer ${bearerToken}` };
290
- }
291
-
292
287
  async function postJson(
293
288
  baseUrl: string,
294
289
  path: string,
295
290
  body: unknown,
296
- bearerToken?: string
291
+ auth?: RequestAuth
297
292
  ): Promise<{ status: number; body: Record<string, unknown> }> {
298
293
  const resp = await fetch(`${baseUrl}${path}`, {
299
294
  method: "POST",
300
295
  headers: {
301
296
  "content-type": "application/json",
302
- ...authHeaders(bearerToken),
297
+ ...mergeRequestHeaders(auth),
303
298
  },
304
299
  body: JSON.stringify(body),
305
300
  });
@@ -312,6 +307,14 @@ async function postJson(
312
307
  parsed = { message: text };
313
308
  }
314
309
  }
310
+ const anyrunReason = resp.headers.get("x-anyrun-failure-reason");
311
+ if (
312
+ anyrunReason !== null &&
313
+ anyrunReason !== "" &&
314
+ (parsed.message === undefined || parsed.message === "")
315
+ ) {
316
+ parsed.message = anyrunReason;
317
+ }
315
318
  return { status: resp.status, body: parsed };
316
319
  }
317
320