@cursor/july 0.1.113 → 0.2.0

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 (278) hide show
  1. package/dist/channels/slack/inbound.d.ts +7 -0
  2. package/dist/channels/slack/inbound.d.ts.map +1 -1
  3. package/dist/channels/slack/inbound.js +23 -0
  4. package/dist/channels/slack/slack-channel.d.ts.map +1 -1
  5. package/dist/channels/slack/slack-channel.js +83 -4
  6. package/dist/docs/404.html +2 -2
  7. package/dist/docs/assets/{app.CAeK13eM.js → app.9eAtsjAM.js} +4 -4
  8. package/dist/docs/assets/chunks/@localSearchIndexroot.DjNBgxTF.js +1 -0
  9. package/dist/docs/assets/chunks/{VPLocalSearchBox.C9LbPHod.js → VPLocalSearchBox.C9s69nxj.js} +1 -1
  10. package/dist/docs/assets/chunks/{arc.CmMq2zmS.js → arc.DmWDRaF-.js} +1 -1
  11. package/dist/docs/assets/chunks/{architectureDiagram-Q4EWVU46.CCXB8Uj5.js → architectureDiagram-Q4EWVU46.BE1Wj4f3.js} +1 -1
  12. package/dist/docs/assets/chunks/{baseUniq.CyQo6eLe.js → baseUniq.pmEZGnWu.js} +1 -1
  13. package/dist/docs/assets/chunks/{blockDiagram-DXYQGD6D.JYq6w91N.js → blockDiagram-DXYQGD6D.D6mM-5XN.js} +1 -1
  14. package/dist/docs/assets/chunks/{c4Diagram-AHTNJAMY.BRV8GPJJ.js → c4Diagram-AHTNJAMY.ZQYTPC1b.js} +1 -1
  15. package/dist/docs/assets/chunks/channel.BNF8VK-B.js +1 -0
  16. package/dist/docs/assets/chunks/{chunk-4BX2VUAB.Bv4ooYQR.js → chunk-4BX2VUAB.CKJ7gaK8.js} +1 -1
  17. package/dist/docs/assets/chunks/{chunk-4TB4RGXK.t4JtKPcj.js → chunk-4TB4RGXK.CL61HnvB.js} +1 -1
  18. package/dist/docs/assets/chunks/{chunk-55IACEB6.34lCHj9Y.js → chunk-55IACEB6.DsA4XA1m.js} +1 -1
  19. package/dist/docs/assets/chunks/{chunk-EDXVE4YY.BSwrPNrt.js → chunk-EDXVE4YY.BODHCHFW.js} +1 -1
  20. package/dist/docs/assets/chunks/{chunk-FMBD7UC4.Beeun-R-.js → chunk-FMBD7UC4.D6NBaZTa.js} +1 -1
  21. package/dist/docs/assets/chunks/{chunk-OYMX7WX6.BUUFUcJc.js → chunk-OYMX7WX6.BLPuqFXg.js} +1 -1
  22. package/dist/docs/assets/chunks/{chunk-QZHKN3VN.B2XjHzN_.js → chunk-QZHKN3VN.BFs_ML8Z.js} +1 -1
  23. package/dist/docs/assets/chunks/{chunk-YZCP3GAM.CLYG8znk.js → chunk-YZCP3GAM.BDjuFyZv.js} +1 -1
  24. package/dist/docs/assets/chunks/classDiagram-6PBFFD2Q.iViHzfrK.js +1 -0
  25. package/dist/docs/assets/chunks/classDiagram-v2-HSJHXN6E.iViHzfrK.js +1 -0
  26. package/dist/docs/assets/chunks/clone.CJoR2BBM.js +1 -0
  27. package/dist/docs/assets/chunks/{cose-bilkent-S5V4N54A.DVEa6fZp.js → cose-bilkent-S5V4N54A.D85HNEsi.js} +1 -1
  28. package/dist/docs/assets/chunks/{dagre-KV5264BT.C9PZQK-S.js → dagre-KV5264BT.V463KlSF.js} +1 -1
  29. package/dist/docs/assets/chunks/{diagram-5BDNPKRD.DoN0uv3Y.js → diagram-5BDNPKRD.DhBDu1ab.js} +1 -1
  30. package/dist/docs/assets/chunks/{diagram-G4DWMVQ6.Czv3duqx.js → diagram-G4DWMVQ6.v6sC68zl.js} +1 -1
  31. package/dist/docs/assets/chunks/{diagram-MMDJMWI5.BinJ5kWb.js → diagram-MMDJMWI5.DhHsdXYv.js} +1 -1
  32. package/dist/docs/assets/chunks/{diagram-TYMM5635.DW326M4K.js → diagram-TYMM5635.BPWNSFZc.js} +1 -1
  33. package/dist/docs/assets/chunks/{erDiagram-SMLLAGMA.U2pR_OA7.js → erDiagram-SMLLAGMA.Cq0wTMPL.js} +1 -1
  34. package/dist/docs/assets/chunks/{flowDiagram-DWJPFMVM.ByWJXeYK.js → flowDiagram-DWJPFMVM.MveMtucC.js} +1 -1
  35. package/dist/docs/assets/chunks/{ganttDiagram-T4ZO3ILL.OquF0Rtg.js → ganttDiagram-T4ZO3ILL.BzKfGUSf.js} +1 -1
  36. package/dist/docs/assets/chunks/{gitGraphDiagram-UUTBAWPF.Bpn01P7X.js → gitGraphDiagram-UUTBAWPF.OToXTSW_.js} +1 -1
  37. package/dist/docs/assets/chunks/{graph.CNRB6ETL.js → graph.D82tam-l.js} +1 -1
  38. package/dist/docs/assets/chunks/{infoDiagram-42DDH7IO.CqhknMWi.js → infoDiagram-42DDH7IO.DzFlRmcE.js} +1 -1
  39. package/dist/docs/assets/chunks/{ishikawaDiagram-UXIWVN3A.C6xpR2af.js → ishikawaDiagram-UXIWVN3A.CVPRJiKe.js} +1 -1
  40. package/dist/docs/assets/chunks/{journeyDiagram-VCZTEJTY.Cg5f7oB3.js → journeyDiagram-VCZTEJTY.CQvNTfQC.js} +1 -1
  41. package/dist/docs/assets/chunks/{kanban-definition-6JOO6SKY.Cx9YTwlU.js → kanban-definition-6JOO6SKY.BwywywUl.js} +1 -1
  42. package/dist/docs/assets/chunks/{layout.ljS-wFtK.js → layout.C4BkPPba.js} +1 -1
  43. package/dist/docs/assets/chunks/{linear.jSxNrsFC.js → linear.FoSfGKD4.js} +1 -1
  44. package/dist/docs/assets/chunks/{min.Cum8AlQw.js → min.yLh8jqfl.js} +1 -1
  45. package/dist/docs/assets/chunks/{mindmap-definition-QFDTVHPH.BLiysLpe.js → mindmap-definition-QFDTVHPH.C9Dq2_CN.js} +1 -1
  46. package/dist/docs/assets/chunks/{pieDiagram-DEJITSTG.BoIDyuKF.js → pieDiagram-DEJITSTG.CiGyBcES.js} +1 -1
  47. package/dist/docs/assets/chunks/{quadrantDiagram-34T5L4WZ.DLkpDytR.js → quadrantDiagram-34T5L4WZ.1FWea9nj.js} +1 -1
  48. package/dist/docs/assets/chunks/{requirementDiagram-MS252O5E.DqTVqSu2.js → requirementDiagram-MS252O5E.B1q7ntiV.js} +1 -1
  49. package/dist/docs/assets/chunks/{sankeyDiagram-XADWPNL6.CG_6FF7j.js → sankeyDiagram-XADWPNL6.Cpr4oU_k.js} +1 -1
  50. package/dist/docs/assets/chunks/{sequenceDiagram-FGHM5R23.BIp9602K.js → sequenceDiagram-FGHM5R23.CUK68STn.js} +1 -1
  51. package/dist/docs/assets/chunks/{stateDiagram-FHFEXIEX.COSXsD9I.js → stateDiagram-FHFEXIEX.zU0yL2m4.js} +1 -1
  52. package/dist/docs/assets/chunks/stateDiagram-v2-QKLJ7IA2.nV8Nl-td.js +1 -0
  53. package/dist/docs/assets/chunks/{theme.CXJ7PNwy.js → theme.DhnKd0CD.js} +2 -2
  54. package/dist/docs/assets/chunks/{timeline-definition-GMOUNBTQ.CXdVqkLq.js → timeline-definition-GMOUNBTQ.CNYoXo3F.js} +1 -1
  55. package/dist/docs/assets/chunks/{vennDiagram-DHZGUBPP.CZxGuc4r.js → vennDiagram-DHZGUBPP.DFWH3G9s.js} +1 -1
  56. package/dist/docs/assets/chunks/{wardley-RL74JXVD.3oVgfqQk.js → wardley-RL74JXVD.Do4PwzeN.js} +1 -1
  57. package/dist/docs/assets/chunks/{wardleyDiagram-NUSXRM2D.6_irCgGJ.js → wardleyDiagram-NUSXRM2D.7WLkqM7s.js} +1 -1
  58. package/dist/docs/assets/chunks/{xychartDiagram-5P7HB3ND.TRPe92m3.js → xychartDiagram-5P7HB3ND.-SyUNgWw.js} +1 -1
  59. package/dist/docs/assets/{deployment.md.D2jQZuFx.js → deployment.md.D2YX7u_I.js} +1 -1
  60. package/dist/docs/assets/{guides_agent-to-agent.md.CD4T5FIl.js → guides_agent-to-agent.md.C6kPY8nu.js} +2 -2
  61. package/dist/docs/assets/{guides_cloud-agents.md.Cp1O3u-X.js → guides_cloud-agents.md.BPJqTZjT.js} +1 -1
  62. package/dist/docs/assets/{guides_grokbot-agents.md.CMhZNdEU.js → guides_grokbot-agents.md.CzV715v8.js} +1 -1
  63. package/dist/docs/assets/guides_hooks.md.BT9GLwEp.js +50 -0
  64. package/dist/docs/assets/guides_hooks.md.BT9GLwEp.lean.js +1 -0
  65. package/dist/docs/assets/{guides_jev.md.F5fAkkfN.js → guides_jev.md.DeSCqMaO.js} +6 -44
  66. package/dist/docs/assets/guides_jev.md.DeSCqMaO.lean.js +1 -0
  67. package/dist/docs/assets/{guides_slack.md.Bo96y42E.js → guides_slack.md.DVjNyqq5.js} +3 -3
  68. package/dist/docs/assets/{guides_slack.md.Bo96y42E.lean.js → guides_slack.md.DVjNyqq5.lean.js} +1 -1
  69. package/dist/docs/assets/reference_agent-config.md.BRxAlnRy.js +36 -0
  70. package/dist/docs/assets/{reference_agent-config.md.DGPyw7ms.lean.js → reference_agent-config.md.BRxAlnRy.lean.js} +1 -1
  71. package/dist/docs/assets/reference_artifacts.md.KRX0sAdt.js +18 -0
  72. package/dist/docs/assets/reference_artifacts.md.KRX0sAdt.lean.js +1 -0
  73. package/dist/docs/assets/reference_channels.md.DZr14vm7.js +23 -0
  74. package/dist/docs/assets/reference_channels.md.DZr14vm7.lean.js +1 -0
  75. package/dist/docs/assets/reference_cli.md.BvnQM8wd.js +97 -0
  76. package/dist/docs/assets/reference_cli.md.BvnQM8wd.lean.js +1 -0
  77. package/dist/docs/assets/{reference_connections.md.Je9dMsdd.js → reference_connections.md.DJGUCxrr.js} +18 -30
  78. package/dist/docs/assets/{reference_connections.md.Je9dMsdd.lean.js → reference_connections.md.DJGUCxrr.lean.js} +1 -1
  79. package/dist/docs/assets/{reference_evals.md.DNJzM_yf.js → reference_evals.md.C6umwNC6.js} +6 -7
  80. package/dist/docs/assets/reference_evals.md.C6umwNC6.lean.js +1 -0
  81. package/dist/docs/assets/{reference_extensions.md.Cv5aLCz_.js → reference_extensions.md.DbNYu-DP.js} +3 -3
  82. package/dist/docs/assets/{reference_extensions.md.Cv5aLCz_.lean.js → reference_extensions.md.DbNYu-DP.lean.js} +1 -1
  83. package/dist/docs/assets/reference_hooks.md.BfOkhTU0.js +45 -0
  84. package/dist/docs/assets/{reference_hooks.md.B7uzNENk.lean.js → reference_hooks.md.BfOkhTU0.lean.js} +1 -1
  85. package/dist/docs/assets/reference_http-api.md.DdwtBeCj.js +11 -0
  86. package/dist/docs/assets/{reference_http-api.md.CduHavZ2.lean.js → reference_http-api.md.DdwtBeCj.lean.js} +1 -1
  87. package/dist/docs/assets/reference_instructions.md.B2mcIzT6.js +14 -0
  88. package/dist/docs/assets/reference_instructions.md.B2mcIzT6.lean.js +1 -0
  89. package/dist/docs/assets/reference_playground.md.CyrQD_n3.js +1 -0
  90. package/dist/docs/assets/reference_playground.md.CyrQD_n3.lean.js +1 -0
  91. package/dist/docs/assets/reference_project-layout.md.BEMzxAkq.js +19 -0
  92. package/dist/docs/assets/{reference_project-layout.md.BGhgpy9V.lean.js → reference_project-layout.md.BEMzxAkq.lean.js} +1 -1
  93. package/dist/docs/assets/reference_prompt.md.BFrqjHFL.js +9 -0
  94. package/dist/docs/assets/reference_prompt.md.BFrqjHFL.lean.js +1 -0
  95. package/dist/docs/assets/reference_schedules.md.BB9N3tRR.js +47 -0
  96. package/dist/docs/assets/reference_schedules.md.BB9N3tRR.lean.js +1 -0
  97. package/dist/docs/assets/reference_sessions.md.BBp-GIt-.js +1 -0
  98. package/dist/docs/assets/{reference_sessions.md.1_6Vyv7x.lean.js → reference_sessions.md.BBp-GIt-.lean.js} +1 -1
  99. package/dist/docs/assets/reference_skills.md.BVmi3UJ_.js +15 -0
  100. package/dist/docs/assets/{reference_skills.md.DjQkRefx.lean.js → reference_skills.md.BVmi3UJ_.lean.js} +1 -1
  101. package/dist/docs/assets/reference_subagents.md.DRoRy2Uj.js +10 -0
  102. package/dist/docs/assets/{reference_subagents.md.Dl16gcBj.lean.js → reference_subagents.md.DRoRy2Uj.lean.js} +1 -1
  103. package/dist/docs/assets/{reference_tools.md.B1dH1lpa.js → reference_tools.md.CgocLDX1.js} +9 -6
  104. package/dist/docs/assets/{reference_tools.md.B1dH1lpa.lean.js → reference_tools.md.CgocLDX1.lean.js} +1 -1
  105. package/dist/docs/assets/troubleshooting.md.HY95rCCz.js +1 -0
  106. package/dist/docs/building-with-agents.html +35 -35
  107. package/dist/docs/deployment.html +37 -37
  108. package/dist/docs/deployment.md +1 -1
  109. package/dist/docs/evals.html +35 -35
  110. package/dist/docs/guides/agent-to-agent.html +38 -38
  111. package/dist/docs/guides/agent-to-agent.md +11 -12
  112. package/dist/docs/guides/bitbucket.html +35 -35
  113. package/dist/docs/guides/cloud-agents.html +36 -36
  114. package/dist/docs/guides/cloud-agents.md +1 -1
  115. package/dist/docs/guides/convert-automation.html +35 -35
  116. package/dist/docs/guides/github.html +35 -35
  117. package/dist/docs/guides/gitlab.html +35 -35
  118. package/dist/docs/guides/grokbot-agents.html +37 -37
  119. package/dist/docs/guides/grokbot-agents.md +1 -1
  120. package/dist/docs/guides/hooks.html +109 -0
  121. package/dist/docs/guides/hooks.md +111 -0
  122. package/dist/docs/guides/improve.html +35 -35
  123. package/dist/docs/guides/jev.html +42 -80
  124. package/dist/docs/guides/jev.md +22 -79
  125. package/dist/docs/guides/mcp-oauth.html +36 -36
  126. package/dist/docs/guides/opentelemetry.html +35 -35
  127. package/dist/docs/guides/slack.html +37 -37
  128. package/dist/docs/guides/slack.md +7 -0
  129. package/dist/docs/guides/webhooks.html +35 -35
  130. package/dist/docs/hashmap.json +1 -1
  131. package/dist/docs/hillclimbing.html +35 -35
  132. package/dist/docs/index.html +35 -35
  133. package/dist/docs/llms-full.txt +1683 -2054
  134. package/dist/docs/llms.txt +9 -8
  135. package/dist/docs/quickstart.html +35 -35
  136. package/dist/docs/reference/agent-config.html +42 -46
  137. package/dist/docs/reference/agent-config.md +48 -81
  138. package/dist/docs/reference/artifacts.html +39 -40
  139. package/dist/docs/reference/artifacts.md +71 -70
  140. package/dist/docs/reference/channels.html +41 -61
  141. package/dist/docs/reference/channels.md +134 -201
  142. package/dist/docs/reference/cli.html +127 -125
  143. package/dist/docs/reference/cli.md +685 -753
  144. package/dist/docs/reference/connections.html +54 -66
  145. package/dist/docs/reference/connections.md +92 -128
  146. package/dist/docs/reference/evals.html +42 -43
  147. package/dist/docs/reference/evals.md +42 -50
  148. package/dist/docs/reference/extensions.html +38 -38
  149. package/dist/docs/reference/extensions.md +9 -13
  150. package/dist/docs/reference/hooks.html +39 -67
  151. package/dist/docs/reference/hooks.md +72 -146
  152. package/dist/docs/reference/http-api.html +39 -39
  153. package/dist/docs/reference/http-api.md +137 -161
  154. package/dist/docs/reference/instructions.html +39 -39
  155. package/dist/docs/reference/instructions.md +21 -36
  156. package/dist/docs/reference/playground.html +36 -36
  157. package/dist/docs/reference/playground.md +26 -43
  158. package/dist/docs/reference/project-layout.html +38 -38
  159. package/dist/docs/reference/project-layout.md +12 -17
  160. package/dist/docs/reference/prompt.html +42 -42
  161. package/dist/docs/reference/prompt.md +18 -13
  162. package/dist/docs/reference/schedules.html +56 -91
  163. package/dist/docs/reference/schedules.md +52 -99
  164. package/dist/docs/reference/sessions.html +36 -36
  165. package/dist/docs/reference/sessions.md +36 -40
  166. package/dist/docs/reference/skills.html +38 -38
  167. package/dist/docs/reference/skills.md +15 -26
  168. package/dist/docs/reference/subagents.html +38 -38
  169. package/dist/docs/reference/subagents.md +20 -30
  170. package/dist/docs/reference/tools.html +44 -41
  171. package/dist/docs/reference/tools.md +45 -64
  172. package/dist/docs/templates/agentic-owners.html +35 -35
  173. package/dist/docs/templates/pr-autofixer.html +35 -35
  174. package/dist/docs/templates/security-reviewer.html +35 -35
  175. package/dist/docs/templates/thermo-quality-review.html +35 -35
  176. package/dist/docs/templates/thermo-review.html +35 -35
  177. package/dist/docs/templates/triage.html +35 -35
  178. package/dist/docs/troubleshooting.html +36 -36
  179. package/dist/docs/troubleshooting.md +1 -1
  180. package/dist/internal/cli-deploy.d.ts.map +1 -1
  181. package/dist/internal/cli-deploy.js +9 -1
  182. package/dist/internal/deploy-client.d.ts +6 -0
  183. package/dist/internal/deploy-client.d.ts.map +1 -1
  184. package/dist/internal/deploy-client.js +3 -0
  185. package/dist/internal/discovery/agent-config.d.ts +3 -1
  186. package/dist/internal/discovery/agent-config.d.ts.map +1 -1
  187. package/dist/internal/discovery/agent-config.js +7 -4
  188. package/dist/internal/framework-storage-selection.d.ts +1 -1
  189. package/dist/internal/framework-storage-selection.d.ts.map +1 -1
  190. package/dist/internal/platform-timers.d.ts.map +1 -1
  191. package/dist/internal/platform-timers.js +20 -2
  192. package/dist/internal/reminder-runner.d.ts +79 -1
  193. package/dist/internal/reminder-runner.d.ts.map +1 -1
  194. package/dist/internal/reminder-runner.js +276 -44
  195. package/dist/internal/server.d.ts.map +1 -1
  196. package/dist/internal/server.js +7 -0
  197. package/dist/memory.d.ts +4 -0
  198. package/dist/memory.d.ts.map +1 -1
  199. package/dist/memory.js +28 -4
  200. package/dist/playground/assets/index-DLwnR9ys.css +1 -0
  201. package/dist/playground/index.html +2 -2
  202. package/dist/types.d.ts +16 -9
  203. package/dist/types.d.ts.map +1 -1
  204. package/docs/deployment.md +1 -1
  205. package/docs/guides/agent-to-agent.md +11 -12
  206. package/docs/guides/cloud-agents.md +1 -1
  207. package/docs/guides/grokbot-agents.md +1 -1
  208. package/docs/guides/hooks.md +116 -0
  209. package/docs/guides/jev.md +23 -80
  210. package/docs/guides/slack.md +7 -0
  211. package/docs/reference/agent-config.md +48 -81
  212. package/docs/reference/artifacts.md +72 -71
  213. package/docs/reference/channels.md +135 -202
  214. package/docs/reference/cli.md +686 -754
  215. package/docs/reference/connections.md +93 -129
  216. package/docs/reference/evals.md +43 -51
  217. package/docs/reference/extensions.md +9 -13
  218. package/docs/reference/hooks.md +72 -146
  219. package/docs/reference/http-api.md +137 -161
  220. package/docs/reference/instructions.md +22 -37
  221. package/docs/reference/playground.md +26 -43
  222. package/docs/reference/project-layout.md +12 -17
  223. package/docs/reference/prompt.md +20 -15
  224. package/docs/reference/schedules.md +52 -99
  225. package/docs/reference/sessions.md +36 -40
  226. package/docs/reference/skills.md +15 -26
  227. package/docs/reference/subagents.md +20 -30
  228. package/docs/reference/tools.md +45 -64
  229. package/docs/troubleshooting.md +1 -1
  230. package/package.json +1 -1
  231. package/src/channels/slack/inbound.ts +24 -0
  232. package/src/channels/slack/slack-channel.ts +123 -1
  233. package/src/internal/cli-deploy.ts +12 -1
  234. package/src/internal/deploy-client.ts +9 -0
  235. package/src/internal/discovery/agent-config.ts +8 -6
  236. package/src/internal/framework-storage-selection.ts +1 -1
  237. package/src/internal/platform-timers.ts +24 -2
  238. package/src/internal/reminder-runner.ts +426 -63
  239. package/src/internal/server.ts +8 -0
  240. package/src/memory.ts +37 -3
  241. package/src/types.ts +16 -9
  242. package/dist/docs/assets/chunks/@localSearchIndexroot.Ck9E52Ls.js +0 -1
  243. package/dist/docs/assets/chunks/channel.BHiYmnZ4.js +0 -1
  244. package/dist/docs/assets/chunks/classDiagram-6PBFFD2Q.Degh8l90.js +0 -1
  245. package/dist/docs/assets/chunks/classDiagram-v2-HSJHXN6E.Degh8l90.js +0 -1
  246. package/dist/docs/assets/chunks/clone.BIywbczV.js +0 -1
  247. package/dist/docs/assets/chunks/stateDiagram-v2-QKLJ7IA2.qrxrbFsX.js +0 -1
  248. package/dist/docs/assets/guides_jev.md.F5fAkkfN.lean.js +0 -1
  249. package/dist/docs/assets/reference_agent-config.md.DGPyw7ms.js +0 -40
  250. package/dist/docs/assets/reference_artifacts.md.Bu_4HmsD.js +0 -19
  251. package/dist/docs/assets/reference_artifacts.md.Bu_4HmsD.lean.js +0 -1
  252. package/dist/docs/assets/reference_channels.md.nFWbzAic.js +0 -43
  253. package/dist/docs/assets/reference_channels.md.nFWbzAic.lean.js +0 -1
  254. package/dist/docs/assets/reference_cli.md.DLWDz9ij.js +0 -95
  255. package/dist/docs/assets/reference_cli.md.DLWDz9ij.lean.js +0 -1
  256. package/dist/docs/assets/reference_evals.md.DNJzM_yf.lean.js +0 -1
  257. package/dist/docs/assets/reference_hooks.md.B7uzNENk.js +0 -73
  258. package/dist/docs/assets/reference_http-api.md.CduHavZ2.js +0 -11
  259. package/dist/docs/assets/reference_instructions.md.CU1My5My.js +0 -14
  260. package/dist/docs/assets/reference_instructions.md.CU1My5My.lean.js +0 -1
  261. package/dist/docs/assets/reference_playground.md.Ch2d0Iqi.js +0 -1
  262. package/dist/docs/assets/reference_playground.md.Ch2d0Iqi.lean.js +0 -1
  263. package/dist/docs/assets/reference_project-layout.md.BGhgpy9V.js +0 -19
  264. package/dist/docs/assets/reference_prompt.md.Ccp0R53H.js +0 -1
  265. package/dist/docs/assets/reference_prompt.md.Ccp0R53H.lean.js +0 -1
  266. package/dist/docs/assets/reference_schedules.md.B2Nm6FaD.js +0 -82
  267. package/dist/docs/assets/reference_schedules.md.B2Nm6FaD.lean.js +0 -1
  268. package/dist/docs/assets/reference_sessions.md.1_6Vyv7x.js +0 -1
  269. package/dist/docs/assets/reference_skills.md.DjQkRefx.js +0 -15
  270. package/dist/docs/assets/reference_subagents.md.Dl16gcBj.js +0 -10
  271. package/dist/docs/assets/troubleshooting.md.mnfFG2Em.js +0 -1
  272. package/dist/playground/assets/index-DSMAewbx.css +0 -1
  273. /package/dist/docs/assets/{deployment.md.D2jQZuFx.lean.js → deployment.md.D2YX7u_I.lean.js} +0 -0
  274. /package/dist/docs/assets/{guides_agent-to-agent.md.CD4T5FIl.lean.js → guides_agent-to-agent.md.C6kPY8nu.lean.js} +0 -0
  275. /package/dist/docs/assets/{guides_cloud-agents.md.Cp1O3u-X.lean.js → guides_cloud-agents.md.BPJqTZjT.lean.js} +0 -0
  276. /package/dist/docs/assets/{guides_grokbot-agents.md.CMhZNdEU.lean.js → guides_grokbot-agents.md.CzV715v8.lean.js} +0 -0
  277. /package/dist/docs/assets/{troubleshooting.md.mnfFG2Em.lean.js → troubleshooting.md.HY95rCCz.lean.js} +0 -0
  278. /package/dist/playground/assets/{index-De_lpFxE.js → index-CX6oTKwz.js} +0 -0
@@ -7,7 +7,9 @@
7
7
  import { randomBytes } from "node:crypto";
8
8
  import type {
9
9
  AuthContext,
10
+ ChannelSession,
10
11
  DiscoveredReminder,
12
+ HostOtelApi,
11
13
  JsonObject,
12
14
  JsonValue,
13
15
  ReminderCreateInput,
@@ -17,6 +19,7 @@ import type {
17
19
  ReminderInfo,
18
20
  ReminderStatus,
19
21
  ReminderUntilContext,
22
+ TurnOutcome,
20
23
  } from "../types.js";
21
24
  import {
22
25
  channelContinuationIdentity,
@@ -47,6 +50,7 @@ import { APP_AUTH } from "./schedule-runner.js";
47
50
  import {
48
51
  type EngineSendOptions,
49
52
  HTTP_CHANNEL_ID,
53
+ SessionAuthError,
50
54
  SessionBusyError,
51
55
  type SessionEngine,
52
56
  } from "./session-engine.js";
@@ -87,6 +91,103 @@ export interface ReminderRunnerOptions {
87
91
  controlPlane?: ReminderControlPlane;
88
92
  /** Agent architecture; used with {@link controlPlane} for v2 protocol path. */
89
93
  architecture?: "v1" | "v2";
94
+ /**
95
+ * Hosted v2 guest (`--no-control-plane`, architecture v2). A pod starts
96
+ * for one delivery and stops when it settles, so a fire usually lands on
97
+ * a pod that holds no session for the reminder's continuation, and the
98
+ * pod may stop as soon as the fire's outcome is applied. The runner then
99
+ * opens a session on the stored continuation key and waits for the turn.
100
+ */
101
+ hostedGuest?: ReminderHostedGuestOptions;
102
+ }
103
+
104
+ export interface ReminderHostedGuestOptions {
105
+ /**
106
+ * Principal for the session a prompt fire opens when the pod holds none.
107
+ * Hosted admissions open sessions with the same value, so a session the
108
+ * engine restores from durable storage keeps its principal. Return
109
+ * `undefined` when no principal applies; the fire then skips with a
110
+ * reschedule so the control plane keeps the reminder armed.
111
+ */
112
+ fireAuth: () => AuthContext | null | undefined;
113
+ }
114
+
115
+ /**
116
+ * Reschedule applied when a hosted fire cannot open a session (no
117
+ * principal). A one-shot `skipped` outcome without a reschedule completes
118
+ * the reminder, which would lose the check-in for good.
119
+ */
120
+ export const REMINDER_SESSION_OPEN_RETRY_DELAY = "5m";
121
+
122
+ /**
123
+ * `reason` tag on `agent_sdk.reminder.fire_outcome`. Prompt fires report
124
+ * how the session was reached: `session_joined` (held by this pod),
125
+ * `session_restored` (read back from durable storage), `session_opened`
126
+ * (fresh session on the stored key), `session_gone` (no session and none
127
+ * could be opened). `fire_threw` pairs with kind `error`: the fire raised
128
+ * and the hosted admission retries it.
129
+ */
130
+ export type ReminderFireOutcomeReason =
131
+ | "session_gone"
132
+ | "session_opened"
133
+ | "session_restored"
134
+ | "session_joined"
135
+ | "handler_missing"
136
+ | "handler_lost_on_restart"
137
+ | "missing_handler"
138
+ | "run_stop"
139
+ | "run_skip"
140
+ | "run_delivered"
141
+ | "until_fn"
142
+ | "busy"
143
+ | "followup_failed"
144
+ | "fire_threw";
145
+
146
+ export const REMINDER_FIRE_OUTCOME_METRIC = "agent_sdk.reminder.fire_outcome";
147
+
148
+ /** What one `executeFire` reports: the CP outcome plus the telemetry tags. */
149
+ interface FireExecution {
150
+ outcome: ReminderExecutionOutcome;
151
+ reason: ReminderFireOutcomeReason;
152
+ /** Set when the hosted guest awaited the turn before reporting. */
153
+ turnStatus?: TurnOutcome["status"];
154
+ }
155
+
156
+ interface PromptDelivery {
157
+ result: ReminderFireResult;
158
+ reason: ReminderFireOutcomeReason;
159
+ turnStatus?: TurnOutcome["status"];
160
+ }
161
+
162
+ /** Out-params `sendFollowup` fills in for the fire's telemetry. */
163
+ interface FollowupSettle {
164
+ turnStatus?: TurnOutcome["status"];
165
+ skipReason?: Extract<ReminderFireOutcomeReason, "busy" | "followup_failed">;
166
+ }
167
+
168
+ /** How a prompt fire reached (or failed to reach) its session. */
169
+ type FollowupTarget =
170
+ | {
171
+ auth: AuthContext | null;
172
+ reached: Extract<
173
+ ReminderFireOutcomeReason,
174
+ "session_joined" | "session_restored"
175
+ >;
176
+ }
177
+ | {
178
+ auth: undefined;
179
+ /**
180
+ * `session_gone`: no session anywhere. `session_unreadable`: the durable
181
+ * index has one but the local re-read missed; never open a fresh
182
+ * session over it.
183
+ */
184
+ reached: "session_gone" | "session_unreadable";
185
+ };
186
+
187
+ /** Guest-side read surface shared by v1 timed-work and the v2 CP client. */
188
+ interface ReminderReader {
189
+ getReminder(id: string): Promise<ReminderRecord | undefined>;
190
+ listReminders(): Promise<ReminderRecord[]>;
90
191
  }
91
192
 
92
193
  /**
@@ -169,6 +270,29 @@ function toInfo(record: ReminderRecord): ReminderInfo {
169
270
  };
170
271
  }
171
272
 
273
+ function stopFire(
274
+ reason: Extract<
275
+ ReminderFireOutcomeReason,
276
+ | "handler_missing"
277
+ | "handler_lost_on_restart"
278
+ | "missing_handler"
279
+ | "until_fn"
280
+ >
281
+ ): FireExecution {
282
+ return { outcome: { kind: "stop", reason }, reason };
283
+ }
284
+
285
+ function runReason(result: ReminderFireResult): ReminderFireOutcomeReason {
286
+ switch (result.action) {
287
+ case "stop":
288
+ return "run_stop";
289
+ case "skip":
290
+ return "run_skip";
291
+ case "delivered":
292
+ return "run_delivered";
293
+ }
294
+ }
295
+
172
296
  function buildFirePrompt(record: ReminderRecord): string {
173
297
  const recurring =
174
298
  record.scheduleKind === "every" || record.scheduleKind === "cron";
@@ -205,6 +329,12 @@ export class ReminderRunner {
205
329
  private readonly rejectAnonymousHandlers: boolean;
206
330
  private readonly controlPlane: ReminderControlPlane | undefined;
207
331
  private readonly architecture: "v1" | "v2" | undefined;
332
+ private readonly hostedGuest: ReminderHostedGuestOptions | undefined;
333
+ /**
334
+ * A control-plane read failure is logged once per outage, not per call.
335
+ * The next successful read re-arms the log.
336
+ */
337
+ private controlPlaneReadFailureLogged = false;
208
338
 
209
339
  constructor(
210
340
  private readonly engine: SessionEngine,
@@ -215,6 +345,7 @@ export class ReminderRunner {
215
345
  this.rejectAnonymousHandlers = options.rejectAnonymousHandlers === true;
216
346
  this.controlPlane = options.controlPlane;
217
347
  this.architecture = options.architecture;
348
+ this.hostedGuest = options.hostedGuest;
218
349
  for (const reminder of options.namedHandlers ?? []) {
219
350
  this.namedHandlers.set(reminder.name, reminder.definition);
220
351
  this.namedHandlerNames.set(reminder.definition, reminder.name);
@@ -226,29 +357,62 @@ export class ReminderRunner {
226
357
  return this.controlPlane !== undefined && this.architecture === "v2";
227
358
  }
228
359
 
360
+ /**
361
+ * Where reminder documents are read from. Under the CP protocol that is
362
+ * the v2 control-plane client; the v1 timed-work route answers 405 for a
363
+ * v2 deployment, which used to leave `list()` with only this process's
364
+ * in-memory map (breaking arm idempotence and `cancelForContinuation`).
365
+ */
366
+ private get reminderReader(): ReminderReader | undefined {
367
+ if (this.usesControlPlaneProtocol) {
368
+ return this.controlPlane;
369
+ }
370
+ return this.platformTimers;
371
+ }
372
+
373
+ private logControlPlaneReadFailure(what: string, error: unknown): void {
374
+ if (this.usesControlPlaneProtocol && this.controlPlaneReadFailureLogged) {
375
+ return;
376
+ }
377
+ this.controlPlaneReadFailureLogged = true;
378
+ this.logger(
379
+ `[agent-sdk] reminders: control-plane ${what} failed: ${
380
+ error instanceof Error ? error.message : String(error)
381
+ }`
382
+ );
383
+ }
384
+
229
385
  /**
230
386
  * Load reminder documents from the control plane into memory. Does not
231
387
  * arm in-process timers — the CP owns clocks.
232
388
  */
233
389
  async hydrate(): Promise<void> {
234
- if (this.platformTimers === undefined) {
390
+ const reader = this.reminderReader;
391
+ if (reader === undefined) {
235
392
  return;
236
393
  }
237
394
  let remote: ReminderRecord[] = [];
238
395
  try {
239
- remote = await this.platformTimers.listReminders();
396
+ remote = await reader.listReminders();
240
397
  } catch (error) {
241
- this.logger(
242
- `[agent-sdk] reminders: control-plane list failed: ${
243
- error instanceof Error ? error.message : String(error)
244
- }`
245
- );
398
+ this.logControlPlaneReadFailure("list", error);
246
399
  return;
247
400
  }
401
+ this.controlPlaneReadFailureLogged = false;
248
402
  this.records.clear();
249
403
  for (const record of remote) {
250
404
  this.records.set(record.id, record);
251
405
  }
406
+ if (this.usesControlPlaneProtocol) {
407
+ // The CP owns status; a fire whose handler is missing reports `stop`
408
+ // from executeFire instead of the guest writing a disarm.
409
+ if (remote.length > 0) {
410
+ this.logger(
411
+ `[agent-sdk] reminders: hydrated ${remote.length} reminder(s) from control plane`
412
+ );
413
+ }
414
+ return;
415
+ }
252
416
  let disarmedOrphan = 0;
253
417
  for (const record of [...this.records.values()]) {
254
418
  if (record.status !== "armed") {
@@ -330,9 +494,11 @@ export class ReminderRunner {
330
494
  }
331
495
 
332
496
  private async getRecord(id: string): Promise<ReminderRecord | undefined> {
333
- if (this.platformTimers !== undefined) {
497
+ const reader = this.reminderReader;
498
+ if (reader !== undefined) {
334
499
  try {
335
- const remote = await this.platformTimers.getReminder(id);
500
+ const remote = await reader.getReminder(id);
501
+ this.controlPlaneReadFailureLogged = false;
336
502
  if (remote === undefined) {
337
503
  this.records.delete(id);
338
504
  return undefined;
@@ -340,31 +506,33 @@ export class ReminderRunner {
340
506
  this.records.set(id, remote);
341
507
  return remote;
342
508
  } catch (error) {
343
- this.logger(
344
- `[agent-sdk] reminders: control-plane get failed for ${id}: ${
345
- error instanceof Error ? error.message : String(error)
346
- }`
347
- );
509
+ this.logControlPlaneReadFailure(`get for ${id}`, error);
348
510
  return this.records.get(id);
349
511
  }
350
512
  }
351
513
  return this.records.get(id);
352
514
  }
353
515
 
516
+ /**
517
+ * Under the CP protocol a list failure propagates: the in-memory map is
518
+ * only what this process created, and returning it would let a caller
519
+ * arm duplicates or miss rows to cancel. v1 keeps the best-effort form.
520
+ */
354
521
  private async allRecords(): Promise<ReminderRecord[]> {
355
- if (this.platformTimers !== undefined) {
522
+ const reader = this.reminderReader;
523
+ if (reader !== undefined) {
356
524
  try {
357
- const remote = await this.platformTimers.listReminders();
525
+ const remote = await reader.listReminders();
526
+ this.controlPlaneReadFailureLogged = false;
358
527
  this.records.clear();
359
528
  for (const record of remote) {
360
529
  this.records.set(record.id, record);
361
530
  }
362
531
  } catch (error) {
363
- this.logger(
364
- `[agent-sdk] reminders: control-plane list failed: ${
365
- error instanceof Error ? error.message : String(error)
366
- }`
367
- );
532
+ this.logControlPlaneReadFailure("list", error);
533
+ if (this.usesControlPlaneProtocol) {
534
+ throw error;
535
+ }
368
536
  }
369
537
  }
370
538
  return [...this.records.values()];
@@ -697,25 +865,46 @@ export class ReminderRunner {
697
865
  ): Promise<ReminderExecutionOutcome> {
698
866
  const record = this.recordFromDescriptor(descriptor);
699
867
  this.records.set(record.id, record);
868
+ let fire: FireExecution;
869
+ try {
870
+ fire = await this.runFire(record);
871
+ } catch (error) {
872
+ // The hosted admission maps the throw to a retryable failure; count
873
+ // it so the retry loop is visible beside the settled outcomes.
874
+ this.recordFireOutcome(record, {
875
+ kind: "error",
876
+ reason: "fire_threw",
877
+ detail: error instanceof Error ? error.message : String(error),
878
+ });
879
+ throw error;
880
+ }
881
+ this.recordFireOutcome(record, {
882
+ kind: fire.outcome.kind,
883
+ reason: fire.reason,
884
+ turnStatus: fire.turnStatus,
885
+ });
886
+ return fire.outcome;
887
+ }
700
888
 
889
+ private async runFire(record: ReminderRecord): Promise<FireExecution> {
701
890
  const live = this.handlers.get(record.id) ?? {};
702
891
  if (record.handler !== undefined) {
703
892
  if (this.resolveNamedHandler(record.handler) === undefined) {
704
- return { kind: "stop", reason: "handler_missing" };
893
+ return stopFire("handler_missing");
705
894
  }
706
895
  } else if (
707
896
  (record.hasRunHandler === true || record.hasUntilFn === true) &&
708
897
  live.run === undefined &&
709
898
  live.untilFn === undefined
710
899
  ) {
711
- return { kind: "stop", reason: "handler_lost_on_restart" };
900
+ return stopFire("handler_lost_on_restart");
712
901
  }
713
902
 
714
903
  if (live.untilFn !== undefined) {
715
904
  try {
716
905
  const done = await live.untilFn(this.buildUntilContext(record));
717
906
  if (done) {
718
- return { kind: "stop", reason: "until_fn" };
907
+ return stopFire("until_fn");
719
908
  }
720
909
  } catch (error) {
721
910
  this.logger(
@@ -728,50 +917,94 @@ export class ReminderRunner {
728
917
 
729
918
  if (await this.isSessionBusy(record.channelId, record.continuationToken)) {
730
919
  if (record.busyPolicy === "skipIfBusy") {
731
- this.logger(
732
- `[agent-sdk] reminder "${record.id}" (${record.purpose}) skipped: session busy`
733
- );
734
- return { kind: "skipped" };
920
+ return { outcome: { kind: "skipped" }, reason: "busy" };
735
921
  }
736
922
  await this.whenSessionIdle(record.channelId, record.continuationToken);
737
923
  }
738
924
 
739
925
  let result: ReminderFireResult;
926
+ let reason: ReminderFireOutcomeReason;
927
+ let turnStatus: TurnOutcome["status"] | undefined;
740
928
  if (record.handler !== undefined) {
741
929
  const named = this.resolveNamedHandler(record.handler);
742
930
  if (named === undefined) {
743
- return { kind: "stop", reason: "handler_missing" };
931
+ return stopFire("handler_missing");
744
932
  }
745
933
  result = await named.run(this.buildFireContext(record));
934
+ reason = runReason(result);
746
935
  } else if (live.run !== undefined) {
747
936
  result = await live.run(this.buildFireContext(record));
937
+ reason = runReason(result);
748
938
  } else if (record.prompt !== undefined) {
749
- result = await this.deliverPrompt(record);
939
+ const delivery = await this.deliverPromptFire(record);
940
+ result = delivery.result;
941
+ reason = delivery.reason;
942
+ turnStatus = delivery.turnStatus;
750
943
  } else {
751
- return { kind: "stop", reason: "missing_handler" };
944
+ return stopFire("missing_handler");
752
945
  }
753
946
 
754
947
  if (result.action === "stop") {
755
- return { kind: "stop", reason: "run_stop" };
756
- }
757
- if (result.action === "skip") {
758
- return {
759
- kind: "skipped",
760
- reschedule:
761
- result.reschedule !== undefined
762
- ? toWireReschedule(result.reschedule)
763
- : undefined,
764
- };
948
+ return { outcome: { kind: "stop", reason }, reason };
765
949
  }
950
+ const reschedule =
951
+ result.reschedule !== undefined
952
+ ? toWireReschedule(result.reschedule)
953
+ : undefined;
766
954
  return {
767
- kind: "delivered",
768
- reschedule:
769
- result.reschedule !== undefined
770
- ? toWireReschedule(result.reschedule)
771
- : undefined,
955
+ outcome: {
956
+ kind: result.action === "skip" ? "skipped" : "delivered",
957
+ reschedule,
958
+ },
959
+ reason,
960
+ turnStatus,
772
961
  };
773
962
  }
774
963
 
964
+ /**
965
+ * One structured line and one `agent_sdk.reminder.fire_outcome` count per
966
+ * fire. Emitted through the host OTel meter, the same path hosted v2
967
+ * exports turn/tool metrics on, so a fire that ends in `stop` is visible
968
+ * beside the control plane's `timed_work.fire` count.
969
+ */
970
+ private recordFireOutcome(
971
+ record: ReminderRecord,
972
+ fire: {
973
+ kind: ReminderExecutionOutcome["kind"] | "error";
974
+ reason: ReminderFireOutcomeReason;
975
+ turnStatus?: TurnOutcome["status"];
976
+ detail?: string;
977
+ }
978
+ ): void {
979
+ this.logger(
980
+ `[agent-sdk] reminder fire_outcome kind=${fire.kind} reason=${fire.reason}` +
981
+ ` reminderId=${record.id} purpose=${record.purpose}` +
982
+ ` channelId=${record.channelId} fireCount=${record.fireCount}` +
983
+ (fire.turnStatus === undefined ? "" : ` turn=${fire.turnStatus}`) +
984
+ (fire.detail === undefined
985
+ ? ""
986
+ : ` detail=${JSON.stringify(fire.detail)}`)
987
+ );
988
+ // Test doubles may omit `host.otel`; the metric is best-effort.
989
+ const otel: HostOtelApi | undefined = this.engine.host.otel;
990
+ if (otel === undefined) {
991
+ return;
992
+ }
993
+ try {
994
+ otel.increment(REMINDER_FIRE_OUTCOME_METRIC, {
995
+ kind: fire.kind,
996
+ reason: fire.reason,
997
+ purpose: record.purpose,
998
+ });
999
+ } catch (error) {
1000
+ this.logger(
1001
+ `[agent-sdk] reminder fire_outcome metric failed: ${
1002
+ error instanceof Error ? error.message : String(error)
1003
+ }`
1004
+ );
1005
+ }
1006
+ }
1007
+
775
1008
  private recordFromDescriptor(
776
1009
  descriptor: ReminderFireDescriptor
777
1010
  ): ReminderRecord {
@@ -1033,19 +1266,121 @@ export class ReminderRunner {
1033
1266
  private async deliverPrompt(
1034
1267
  record: ReminderRecord
1035
1268
  ): Promise<ReminderFireResult> {
1269
+ return (await this.deliverPromptFire(record)).result;
1270
+ }
1271
+
1272
+ /**
1273
+ * Where a prompt fire joins. The pod's own store first; on a hosted guest
1274
+ * the durable mirror next, because the pod that armed the reminder is
1275
+ * usually gone and the session lives only in storage. A restored session
1276
+ * keeps its own principal (channel admissions may carry a sender), so the
1277
+ * fire joins under that, never under {@link ReminderHostedGuestOptions.fireAuth}.
1278
+ */
1279
+ private async resolveFollowupTarget(
1280
+ record: ReminderRecord
1281
+ ): Promise<FollowupTarget> {
1282
+ const local = await this.resolveFollowupAuth(
1283
+ record.channelId,
1284
+ record.continuationToken
1285
+ );
1286
+ if (local !== undefined) {
1287
+ return { auth: local, reached: "session_joined" };
1288
+ }
1289
+ if (this.hostedGuest === undefined) {
1290
+ return { auth: undefined, reached: "session_gone" };
1291
+ }
1292
+ // Materializes the durable record locally; a storage error propagates
1293
+ // and the hosted admission retries the fire.
1294
+ const restored = await this.engine.hasContinuationSession(
1295
+ record.channelId,
1296
+ record.continuationToken
1297
+ );
1298
+ if (!restored) {
1299
+ return { auth: undefined, reached: "session_gone" };
1300
+ }
1036
1301
  const auth = await this.resolveFollowupAuth(
1037
1302
  record.channelId,
1038
1303
  record.continuationToken
1039
1304
  );
1040
- if (auth === undefined) {
1041
- // Under CP protocol, return stop and let the CP apply/CAS; do not
1042
- // mutate authoritative status from the guest mid-fire.
1043
- if (!this.usesControlPlaneProtocol) {
1044
- await this.disarm(record, "session_gone");
1305
+ return auth === undefined
1306
+ ? { auth: undefined, reached: "session_unreadable" }
1307
+ : { auth, reached: "session_restored" };
1308
+ }
1309
+
1310
+ private async deliverPromptFire(
1311
+ record: ReminderRecord
1312
+ ): Promise<PromptDelivery> {
1313
+ const target = await this.resolveFollowupTarget(record);
1314
+ if (target.auth !== undefined) {
1315
+ return this.promptDelivery(record, target.auth, target.reached);
1316
+ }
1317
+ if (target.reached === "session_unreadable") {
1318
+ this.logger(
1319
+ `[agent-sdk] reminder "${record.id}" (${record.purpose}) durable session did not materialize locally; not opening a new one`
1320
+ );
1321
+ return { result: { action: "stop" }, reason: "session_gone" };
1322
+ }
1323
+ if (
1324
+ this.hostedGuest !== undefined &&
1325
+ this.channelUsesControlPlaneContinuation(record.channelId)
1326
+ ) {
1327
+ // No session on this pod and none in durable storage. Open one on the
1328
+ // stored key the way an inbound event on a fresh key does, instead of
1329
+ // consuming the fire with no turn.
1330
+ const fireAuth = this.hostedGuest.fireAuth();
1331
+ if (fireAuth === undefined) {
1332
+ return {
1333
+ result: {
1334
+ action: "skip",
1335
+ reschedule: { delay: REMINDER_SESSION_OPEN_RETRY_DELAY },
1336
+ },
1337
+ reason: "session_gone",
1338
+ };
1339
+ }
1340
+ try {
1341
+ return await this.promptDelivery(record, fireAuth, "session_opened");
1342
+ } catch (error) {
1343
+ if (!(error instanceof SessionAuthError)) {
1344
+ throw error;
1345
+ }
1346
+ // A session landed on this key under another principal between the
1347
+ // lookup and the send. That does not change on retry, so stop
1348
+ // rather than let the control plane re-admit until its attempt cap.
1349
+ this.logger(
1350
+ `[agent-sdk] reminder "${record.id}" (${record.purpose}) cannot join session on its continuation: ${error.message}`
1351
+ );
1352
+ return { result: { action: "stop" }, reason: "session_gone" };
1045
1353
  }
1046
- return { action: "stop" };
1047
1354
  }
1048
- return this.sendFollowup(record, buildFirePrompt(record), auth);
1355
+ // Under CP protocol, return stop and let the CP apply/CAS; do not
1356
+ // mutate authoritative status from the guest mid-fire.
1357
+ if (!this.usesControlPlaneProtocol) {
1358
+ await this.disarm(record, "session_gone");
1359
+ }
1360
+ return { result: { action: "stop" }, reason: "session_gone" };
1361
+ }
1362
+
1363
+ private async promptDelivery(
1364
+ record: ReminderRecord,
1365
+ auth: AuthContext | null,
1366
+ delivered: Extract<
1367
+ ReminderFireOutcomeReason,
1368
+ "session_joined" | "session_restored" | "session_opened"
1369
+ >
1370
+ ): Promise<PromptDelivery> {
1371
+ const settle: FollowupSettle = {};
1372
+ const result = await this.sendFollowup(
1373
+ record,
1374
+ buildFirePrompt(record),
1375
+ auth,
1376
+ settle
1377
+ );
1378
+ return {
1379
+ result,
1380
+ reason:
1381
+ result.action === "skip" ? (settle.skipReason ?? "busy") : delivered,
1382
+ turnStatus: settle.turnStatus,
1383
+ };
1049
1384
  }
1050
1385
 
1051
1386
  /**
@@ -1086,10 +1421,33 @@ export class ReminderRunner {
1086
1421
  return continuationSource(identity) === "control-plane";
1087
1422
  }
1088
1423
 
1424
+ /**
1425
+ * Local and v1 track the turn in the background: the process outlives the
1426
+ * fire. A hosted v2 guest waits for the turn and its durable writes first,
1427
+ * because the control plane may stop the pod as soon as the fire's
1428
+ * outcome is applied, and `delivered` must mean the turn ran.
1429
+ */
1430
+ private async settleFollowup(
1431
+ session: ChannelSession,
1432
+ settle: FollowupSettle | undefined
1433
+ ): Promise<void> {
1434
+ const completion = this.engine.waitForCompletion(session.id);
1435
+ if (this.hostedGuest === undefined) {
1436
+ this.engine.trackBackground(completion);
1437
+ return;
1438
+ }
1439
+ const outcome = await completion;
1440
+ await this.engine.drainSessionDurability(session.id);
1441
+ if (settle !== undefined) {
1442
+ settle.turnStatus = outcome.status;
1443
+ }
1444
+ }
1445
+
1089
1446
  private async sendFollowup(
1090
1447
  record: ReminderRecord,
1091
1448
  message: string,
1092
- auth: AuthContext | null
1449
+ auth: AuthContext | null,
1450
+ settle?: FollowupSettle
1093
1451
  ): Promise<ReminderFireResult> {
1094
1452
  const sendOptions = this.followupSendOptions(record, auth);
1095
1453
  try {
@@ -1098,11 +1456,14 @@ export class ReminderRunner {
1098
1456
  message,
1099
1457
  sendOptions
1100
1458
  );
1101
- this.engine.trackBackground(this.engine.waitForCompletion(session.id));
1459
+ await this.settleFollowup(session, settle);
1102
1460
  return { action: "delivered" };
1103
1461
  } catch (error) {
1104
1462
  if (error instanceof SessionBusyError) {
1105
1463
  if (record.busyPolicy === "skipIfBusy") {
1464
+ if (settle !== undefined) {
1465
+ settle.skipReason = "busy";
1466
+ }
1106
1467
  return { action: "skip" };
1107
1468
  }
1108
1469
  await this.whenSessionIdle(record.channelId, record.continuationToken);
@@ -1112,9 +1473,7 @@ export class ReminderRunner {
1112
1473
  message,
1113
1474
  sendOptions
1114
1475
  );
1115
- this.engine.trackBackground(
1116
- this.engine.waitForCompletion(session.id)
1117
- );
1476
+ await this.settleFollowup(session, settle);
1118
1477
  return { action: "delivered" };
1119
1478
  } catch (retryError) {
1120
1479
  this.logger(
@@ -1124,6 +1483,9 @@ export class ReminderRunner {
1124
1483
  : String(retryError)
1125
1484
  }`
1126
1485
  );
1486
+ if (settle !== undefined) {
1487
+ settle.skipReason = "followup_failed";
1488
+ }
1127
1489
  return { action: "skip" };
1128
1490
  }
1129
1491
  }
@@ -1148,12 +1510,13 @@ export class ReminderRunner {
1148
1510
  appAuth: APP_AUTH,
1149
1511
  artifacts: this.engine.artifacts,
1150
1512
  async followup(args: { message: string }) {
1151
- const auth = await self.resolveFollowupAuth(
1152
- record.channelId,
1153
- record.continuationToken
1154
- );
1513
+ const { auth } = await self.resolveFollowupTarget(record);
1155
1514
  if (auth === undefined) {
1156
- await self.disarm(record, "session_gone");
1515
+ // Under the CP protocol the guest never writes reminder status;
1516
+ // the fire's `stop` outcome carries the reason instead.
1517
+ if (!self.usesControlPlaneProtocol) {
1518
+ await self.disarm(record, "session_gone");
1519
+ }
1157
1520
  throw new Error(
1158
1521
  `Reminder "${record.id}" followup: session gone for continuation`
1159
1522
  );