@cursor/july 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (623) hide show
  1. package/AGENTS.md +290 -0
  2. package/LICENSE.md +3 -0
  3. package/README.md +1233 -0
  4. package/dist/ab.d.ts +290 -0
  5. package/dist/ab.d.ts.map +1 -0
  6. package/dist/ab.js +386 -0
  7. package/dist/bin/agent-serve.d.ts +15 -0
  8. package/dist/bin/agent-serve.d.ts.map +1 -0
  9. package/dist/bin/agent-serve.js +754 -0
  10. package/dist/channels/github/api.d.ts +101 -0
  11. package/dist/channels/github/api.d.ts.map +1 -0
  12. package/dist/channels/github/api.js +229 -0
  13. package/dist/channels/github/auth.d.ts +67 -0
  14. package/dist/channels/github/auth.d.ts.map +1 -0
  15. package/dist/channels/github/auth.js +239 -0
  16. package/dist/channels/github/binding.d.ts +73 -0
  17. package/dist/channels/github/binding.d.ts.map +1 -0
  18. package/dist/channels/github/binding.js +114 -0
  19. package/dist/channels/github/defaults.d.ts +24 -0
  20. package/dist/channels/github/defaults.d.ts.map +1 -0
  21. package/dist/channels/github/defaults.js +100 -0
  22. package/dist/channels/github/events.d.ts +18 -0
  23. package/dist/channels/github/events.d.ts.map +1 -0
  24. package/dist/channels/github/events.js +59 -0
  25. package/dist/channels/github/forward.d.ts +137 -0
  26. package/dist/channels/github/forward.d.ts.map +1 -0
  27. package/dist/channels/github/forward.js +271 -0
  28. package/dist/channels/github/github-channel.d.ts +127 -0
  29. package/dist/channels/github/github-channel.d.ts.map +1 -0
  30. package/dist/channels/github/github-channel.js +1688 -0
  31. package/dist/channels/github/index.d.ts +52 -0
  32. package/dist/channels/github/index.d.ts.map +1 -0
  33. package/dist/channels/github/index.js +51 -0
  34. package/dist/channels/github/replay.d.ts +115 -0
  35. package/dist/channels/github/replay.d.ts.map +1 -0
  36. package/dist/channels/github/replay.js +282 -0
  37. package/dist/channels/github/state.d.ts +26 -0
  38. package/dist/channels/github/state.d.ts.map +1 -0
  39. package/dist/channels/github/state.js +50 -0
  40. package/dist/channels/github/types.d.ts +385 -0
  41. package/dist/channels/github/types.d.ts.map +1 -0
  42. package/dist/channels/github/types.js +1 -0
  43. package/dist/channels/slack/api.d.ts +117 -0
  44. package/dist/channels/slack/api.d.ts.map +1 -0
  45. package/dist/channels/slack/api.js +437 -0
  46. package/dist/channels/slack/approvals.d.ts +32 -0
  47. package/dist/channels/slack/approvals.d.ts.map +1 -0
  48. package/dist/channels/slack/approvals.js +157 -0
  49. package/dist/channels/slack/assistant.d.ts +23 -0
  50. package/dist/channels/slack/assistant.d.ts.map +1 -0
  51. package/dist/channels/slack/assistant.js +67 -0
  52. package/dist/channels/slack/auth.d.ts +40 -0
  53. package/dist/channels/slack/auth.d.ts.map +1 -0
  54. package/dist/channels/slack/auth.js +71 -0
  55. package/dist/channels/slack/channel-watch.d.ts +46 -0
  56. package/dist/channels/slack/channel-watch.d.ts.map +1 -0
  57. package/dist/channels/slack/channel-watch.js +180 -0
  58. package/dist/channels/slack/constants.d.ts +17 -0
  59. package/dist/channels/slack/constants.d.ts.map +1 -0
  60. package/dist/channels/slack/constants.js +27 -0
  61. package/dist/channels/slack/credentials.d.ts +35 -0
  62. package/dist/channels/slack/credentials.d.ts.map +1 -0
  63. package/dist/channels/slack/credentials.js +88 -0
  64. package/dist/channels/slack/cursor-account.d.ts +76 -0
  65. package/dist/channels/slack/cursor-account.d.ts.map +1 -0
  66. package/dist/channels/slack/cursor-account.js +88 -0
  67. package/dist/channels/slack/defaults.d.ts +32 -0
  68. package/dist/channels/slack/defaults.d.ts.map +1 -0
  69. package/dist/channels/slack/defaults.js +380 -0
  70. package/dist/channels/slack/dispatch.d.ts +43 -0
  71. package/dist/channels/slack/dispatch.d.ts.map +1 -0
  72. package/dist/channels/slack/dispatch.js +185 -0
  73. package/dist/channels/slack/doctor.d.ts +24 -0
  74. package/dist/channels/slack/doctor.d.ts.map +1 -0
  75. package/dist/channels/slack/doctor.js +115 -0
  76. package/dist/channels/slack/event-id-dedupe.d.ts +10 -0
  77. package/dist/channels/slack/event-id-dedupe.d.ts.map +1 -0
  78. package/dist/channels/slack/event-id-dedupe.js +23 -0
  79. package/dist/channels/slack/inbound.d.ts +41 -0
  80. package/dist/channels/slack/inbound.d.ts.map +1 -0
  81. package/dist/channels/slack/inbound.js +166 -0
  82. package/dist/channels/slack/index.d.ts +45 -0
  83. package/dist/channels/slack/index.d.ts.map +1 -0
  84. package/dist/channels/slack/index.js +44 -0
  85. package/dist/channels/slack/init.d.ts +32 -0
  86. package/dist/channels/slack/init.d.ts.map +1 -0
  87. package/dist/channels/slack/init.js +82 -0
  88. package/dist/channels/slack/interactive.d.ts +19 -0
  89. package/dist/channels/slack/interactive.d.ts.map +1 -0
  90. package/dist/channels/slack/interactive.js +142 -0
  91. package/dist/channels/slack/links.d.ts +10 -0
  92. package/dist/channels/slack/links.d.ts.map +1 -0
  93. package/dist/channels/slack/links.js +19 -0
  94. package/dist/channels/slack/live-delivery.d.ts +75 -0
  95. package/dist/channels/slack/live-delivery.d.ts.map +1 -0
  96. package/dist/channels/slack/live-delivery.js +143 -0
  97. package/dist/channels/slack/log.d.ts +25 -0
  98. package/dist/channels/slack/log.d.ts.map +1 -0
  99. package/dist/channels/slack/log.js +47 -0
  100. package/dist/channels/slack/manifest.d.ts +57 -0
  101. package/dist/channels/slack/manifest.d.ts.map +1 -0
  102. package/dist/channels/slack/manifest.js +110 -0
  103. package/dist/channels/slack/pr-ref.d.ts +18 -0
  104. package/dist/channels/slack/pr-ref.d.ts.map +1 -0
  105. package/dist/channels/slack/pr-ref.js +36 -0
  106. package/dist/channels/slack/setup.d.ts +14 -0
  107. package/dist/channels/slack/setup.d.ts.map +1 -0
  108. package/dist/channels/slack/setup.js +86 -0
  109. package/dist/channels/slack/slack-channel.d.ts +15 -0
  110. package/dist/channels/slack/slack-channel.d.ts.map +1 -0
  111. package/dist/channels/slack/slack-channel.js +281 -0
  112. package/dist/channels/slack/socket-mode.d.ts +26 -0
  113. package/dist/channels/slack/socket-mode.d.ts.map +1 -0
  114. package/dist/channels/slack/socket-mode.js +116 -0
  115. package/dist/channels/slack/stream.d.ts +26 -0
  116. package/dist/channels/slack/stream.d.ts.map +1 -0
  117. package/dist/channels/slack/stream.js +39 -0
  118. package/dist/channels/slack/tool-approval-events.d.ts +33 -0
  119. package/dist/channels/slack/tool-approval-events.d.ts.map +1 -0
  120. package/dist/channels/slack/tool-approval-events.js +129 -0
  121. package/dist/channels/slack/types.d.ts +326 -0
  122. package/dist/channels/slack/types.d.ts.map +1 -0
  123. package/dist/channels/slack/types.js +4 -0
  124. package/dist/channels.d.ts +116 -0
  125. package/dist/channels.d.ts.map +1 -0
  126. package/dist/channels.js +294 -0
  127. package/dist/connections.d.ts +75 -0
  128. package/dist/connections.d.ts.map +1 -0
  129. package/dist/connections.js +75 -0
  130. package/dist/docs/404.html +22 -0
  131. package/dist/docs/ab.html +87 -0
  132. package/dist/docs/assets/ab.md.COdXkces.js +63 -0
  133. package/dist/docs/assets/ab.md.COdXkces.lean.js +1 -0
  134. package/dist/docs/assets/app.DqfFEmJd.js +1 -0
  135. package/dist/docs/assets/building-with-agents.md.CJCtZCyi.js +13 -0
  136. package/dist/docs/assets/building-with-agents.md.CJCtZCyi.lean.js +1 -0
  137. package/dist/docs/assets/chunks/@localSearchIndexroot.CcVk1uKq.js +1 -0
  138. package/dist/docs/assets/chunks/VPLocalSearchBox.BaLEdS15.js +9 -0
  139. package/dist/docs/assets/chunks/framework.CAZyNGu9.js +19 -0
  140. package/dist/docs/assets/chunks/theme.CZRvu_0q.js +2 -0
  141. package/dist/docs/assets/concepts.md.Cfb9b-k1.js +4 -0
  142. package/dist/docs/assets/concepts.md.Cfb9b-k1.lean.js +1 -0
  143. package/dist/docs/assets/deployment.md.Dx1TYNk5.js +14 -0
  144. package/dist/docs/assets/deployment.md.Dx1TYNk5.lean.js +1 -0
  145. package/dist/docs/assets/evals.md.DPZ_MAnI.js +85 -0
  146. package/dist/docs/assets/evals.md.DPZ_MAnI.lean.js +1 -0
  147. package/dist/docs/assets/guides_agent-to-agent.md.CrtrsySy.js +10 -0
  148. package/dist/docs/assets/guides_agent-to-agent.md.CrtrsySy.lean.js +1 -0
  149. package/dist/docs/assets/guides_cloud-runtime.md.CYlNMTNp.js +9 -0
  150. package/dist/docs/assets/guides_cloud-runtime.md.CYlNMTNp.lean.js +1 -0
  151. package/dist/docs/assets/guides_github.md.DwbKhCeS.js +20 -0
  152. package/dist/docs/assets/guides_github.md.DwbKhCeS.lean.js +1 -0
  153. package/dist/docs/assets/guides_human-in-the-loop.md.Dvuctx7s.js +28 -0
  154. package/dist/docs/assets/guides_human-in-the-loop.md.Dvuctx7s.lean.js +1 -0
  155. package/dist/docs/assets/guides_slack.md.bv41fHfW.js +37 -0
  156. package/dist/docs/assets/guides_slack.md.bv41fHfW.lean.js +1 -0
  157. package/dist/docs/assets/guides_webhooks.md.hFTik3lf.js +50 -0
  158. package/dist/docs/assets/guides_webhooks.md.hFTik3lf.lean.js +1 -0
  159. package/dist/docs/assets/hillclimbing.md.DHNast08.js +4 -0
  160. package/dist/docs/assets/hillclimbing.md.DHNast08.lean.js +1 -0
  161. package/dist/docs/assets/index.md.BPKcj5AI.js +20 -0
  162. package/dist/docs/assets/index.md.BPKcj5AI.lean.js +1 -0
  163. package/dist/docs/assets/inter-italic-cyrillic-ext.r48I6akx.woff2 +0 -0
  164. package/dist/docs/assets/inter-italic-cyrillic.By2_1cv3.woff2 +0 -0
  165. package/dist/docs/assets/inter-italic-greek-ext.1u6EdAuj.woff2 +0 -0
  166. package/dist/docs/assets/inter-italic-greek.DJ8dCoTZ.woff2 +0 -0
  167. package/dist/docs/assets/inter-italic-latin-ext.CN1xVJS-.woff2 +0 -0
  168. package/dist/docs/assets/inter-italic-latin.C2AdPX0b.woff2 +0 -0
  169. package/dist/docs/assets/inter-italic-vietnamese.BSbpV94h.woff2 +0 -0
  170. package/dist/docs/assets/inter-roman-cyrillic-ext.BBPuwvHQ.woff2 +0 -0
  171. package/dist/docs/assets/inter-roman-cyrillic.C5lxZ8CY.woff2 +0 -0
  172. package/dist/docs/assets/inter-roman-greek-ext.CqjqNYQ-.woff2 +0 -0
  173. package/dist/docs/assets/inter-roman-greek.BBVDIX6e.woff2 +0 -0
  174. package/dist/docs/assets/inter-roman-latin-ext.4ZJIpNVo.woff2 +0 -0
  175. package/dist/docs/assets/inter-roman-latin.Di8DUHzh.woff2 +0 -0
  176. package/dist/docs/assets/inter-roman-vietnamese.BjW4sHH5.woff2 +0 -0
  177. package/dist/docs/assets/quickstart.md.tVPiGK_L.js +35 -0
  178. package/dist/docs/assets/quickstart.md.tVPiGK_L.lean.js +1 -0
  179. package/dist/docs/assets/reference_agent-config.md.Bpd7HQwf.js +34 -0
  180. package/dist/docs/assets/reference_agent-config.md.Bpd7HQwf.lean.js +1 -0
  181. package/dist/docs/assets/reference_channels.md.D7JTR03W.js +53 -0
  182. package/dist/docs/assets/reference_channels.md.D7JTR03W.lean.js +1 -0
  183. package/dist/docs/assets/reference_cli.md.DA730zCu.js +33 -0
  184. package/dist/docs/assets/reference_cli.md.DA730zCu.lean.js +1 -0
  185. package/dist/docs/assets/reference_connections.md.C3vNH_DE.js +26 -0
  186. package/dist/docs/assets/reference_connections.md.C3vNH_DE.lean.js +1 -0
  187. package/dist/docs/assets/reference_hooks.md.BCEc3MyM.js +12 -0
  188. package/dist/docs/assets/reference_hooks.md.BCEc3MyM.lean.js +1 -0
  189. package/dist/docs/assets/reference_http-api.md.DBAahtdz.js +11 -0
  190. package/dist/docs/assets/reference_http-api.md.DBAahtdz.lean.js +1 -0
  191. package/dist/docs/assets/reference_instructions.md.BC05LEQ8.js +12 -0
  192. package/dist/docs/assets/reference_instructions.md.BC05LEQ8.lean.js +1 -0
  193. package/dist/docs/assets/reference_playground.md.CPZhfYaO.js +1 -0
  194. package/dist/docs/assets/reference_playground.md.CPZhfYaO.lean.js +1 -0
  195. package/dist/docs/assets/reference_project-layout.md.Bd_CKtNS.js +31 -0
  196. package/dist/docs/assets/reference_project-layout.md.Bd_CKtNS.lean.js +1 -0
  197. package/dist/docs/assets/reference_schedules.md.D7qijxLk.js +82 -0
  198. package/dist/docs/assets/reference_schedules.md.D7qijxLk.lean.js +1 -0
  199. package/dist/docs/assets/reference_sessions.md.DdjWabnN.js +8 -0
  200. package/dist/docs/assets/reference_sessions.md.DdjWabnN.lean.js +1 -0
  201. package/dist/docs/assets/reference_skills.md.VQnlBT3Q.js +15 -0
  202. package/dist/docs/assets/reference_skills.md.VQnlBT3Q.lean.js +1 -0
  203. package/dist/docs/assets/reference_subagents.md.CIRAVcPK.js +10 -0
  204. package/dist/docs/assets/reference_subagents.md.CIRAVcPK.lean.js +1 -0
  205. package/dist/docs/assets/reference_tools.md.DF5kwlt0.js +46 -0
  206. package/dist/docs/assets/reference_tools.md.DF5kwlt0.lean.js +1 -0
  207. package/dist/docs/assets/scaffolding-agents.md.CyYfWGdc.js +1 -0
  208. package/dist/docs/assets/scaffolding-agents.md.CyYfWGdc.lean.js +1 -0
  209. package/dist/docs/assets/style.Bj-IXa5W.css +1 -0
  210. package/dist/docs/assets/troubleshooting.md.DkovjS7h.js +1 -0
  211. package/dist/docs/assets/troubleshooting.md.DkovjS7h.lean.js +1 -0
  212. package/dist/docs/building-with-agents.html +37 -0
  213. package/dist/docs/concepts.html +28 -0
  214. package/dist/docs/deployment.html +38 -0
  215. package/dist/docs/evals.html +109 -0
  216. package/dist/docs/guides/agent-to-agent.html +34 -0
  217. package/dist/docs/guides/cloud-runtime.html +33 -0
  218. package/dist/docs/guides/github.html +44 -0
  219. package/dist/docs/guides/human-in-the-loop.html +52 -0
  220. package/dist/docs/guides/slack.html +61 -0
  221. package/dist/docs/guides/webhooks.html +74 -0
  222. package/dist/docs/hashmap.json +1 -0
  223. package/dist/docs/hillclimbing.html +28 -0
  224. package/dist/docs/index.html +44 -0
  225. package/dist/docs/quickstart.html +59 -0
  226. package/dist/docs/reference/agent-config.html +58 -0
  227. package/dist/docs/reference/channels.html +77 -0
  228. package/dist/docs/reference/cli.html +57 -0
  229. package/dist/docs/reference/connections.html +50 -0
  230. package/dist/docs/reference/hooks.html +36 -0
  231. package/dist/docs/reference/http-api.html +35 -0
  232. package/dist/docs/reference/instructions.html +36 -0
  233. package/dist/docs/reference/playground.html +25 -0
  234. package/dist/docs/reference/project-layout.html +55 -0
  235. package/dist/docs/reference/schedules.html +106 -0
  236. package/dist/docs/reference/sessions.html +32 -0
  237. package/dist/docs/reference/skills.html +39 -0
  238. package/dist/docs/reference/subagents.html +34 -0
  239. package/dist/docs/reference/tools.html +70 -0
  240. package/dist/docs/scaffolding-agents.html +25 -0
  241. package/dist/docs/troubleshooting.html +25 -0
  242. package/dist/docs/vp-icons.css +0 -0
  243. package/dist/evals.d.ts +312 -0
  244. package/dist/evals.d.ts.map +1 -0
  245. package/dist/evals.js +254 -0
  246. package/dist/hooks.d.ts +23 -0
  247. package/dist/hooks.d.ts.map +1 -0
  248. package/dist/hooks.js +23 -0
  249. package/dist/index.d.ts +71 -0
  250. package/dist/index.d.ts.map +1 -0
  251. package/dist/index.js +101 -0
  252. package/dist/internal/ab-collector.d.ts +42 -0
  253. package/dist/internal/ab-collector.d.ts.map +1 -0
  254. package/dist/internal/ab-collector.js +153 -0
  255. package/dist/internal/ab-fold.d.ts +36 -0
  256. package/dist/internal/ab-fold.d.ts.map +1 -0
  257. package/dist/internal/ab-fold.js +171 -0
  258. package/dist/internal/ab-snapshot.d.ts +70 -0
  259. package/dist/internal/ab-snapshot.d.ts.map +1 -0
  260. package/dist/internal/ab-snapshot.js +208 -0
  261. package/dist/internal/approval-gate.d.ts +34 -0
  262. package/dist/internal/approval-gate.d.ts.map +1 -0
  263. package/dist/internal/approval-gate.js +85 -0
  264. package/dist/internal/auth.d.ts +8 -0
  265. package/dist/internal/auth.d.ts.map +1 -0
  266. package/dist/internal/auth.js +27 -0
  267. package/dist/internal/authored-alias-hooks.d.ts +31 -0
  268. package/dist/internal/authored-alias-hooks.d.ts.map +1 -0
  269. package/dist/internal/authored-alias-hooks.js +43 -0
  270. package/dist/internal/authored-loaders.d.ts +25 -0
  271. package/dist/internal/authored-loaders.d.ts.map +1 -0
  272. package/dist/internal/authored-loaders.js +129 -0
  273. package/dist/internal/bounded-int.d.ts +11 -0
  274. package/dist/internal/bounded-int.d.ts.map +1 -0
  275. package/dist/internal/bounded-int.js +13 -0
  276. package/dist/internal/brand.d.ts +6 -0
  277. package/dist/internal/brand.d.ts.map +1 -0
  278. package/dist/internal/brand.js +17 -0
  279. package/dist/internal/chat-client.d.ts +19 -0
  280. package/dist/internal/chat-client.d.ts.map +1 -0
  281. package/dist/internal/chat-client.js +327 -0
  282. package/dist/internal/cli-ax.d.ts +58 -0
  283. package/dist/internal/cli-ax.d.ts.map +1 -0
  284. package/dist/internal/cli-ax.js +345 -0
  285. package/dist/internal/cli-cursor.d.ts +20 -0
  286. package/dist/internal/cli-cursor.d.ts.map +1 -0
  287. package/dist/internal/cli-cursor.js +227 -0
  288. package/dist/internal/cli-github.d.ts +47 -0
  289. package/dist/internal/cli-github.d.ts.map +1 -0
  290. package/dist/internal/cli-github.js +644 -0
  291. package/dist/internal/cli-slack.d.ts +18 -0
  292. package/dist/internal/cli-slack.d.ts.map +1 -0
  293. package/dist/internal/cli-slack.js +144 -0
  294. package/dist/internal/cloud-merge.d.ts +23 -0
  295. package/dist/internal/cloud-merge.d.ts.map +1 -0
  296. package/dist/internal/cloud-merge.js +28 -0
  297. package/dist/internal/cron.d.ts +17 -0
  298. package/dist/internal/cron.d.ts.map +1 -0
  299. package/dist/internal/cron.js +60 -0
  300. package/dist/internal/cursor/account-mcp.d.ts +95 -0
  301. package/dist/internal/cursor/account-mcp.d.ts.map +1 -0
  302. package/dist/internal/cursor/account-mcp.js +342 -0
  303. package/dist/internal/cursor/backend-client.d.ts +118 -0
  304. package/dist/internal/cursor/backend-client.d.ts.map +1 -0
  305. package/dist/internal/cursor/backend-client.js +477 -0
  306. package/dist/internal/cursor/credentials.d.ts +112 -0
  307. package/dist/internal/cursor/credentials.d.ts.map +1 -0
  308. package/dist/internal/cursor/credentials.js +329 -0
  309. package/dist/internal/cursor-event-relay.d.ts +111 -0
  310. package/dist/internal/cursor-event-relay.d.ts.map +1 -0
  311. package/dist/internal/cursor-event-relay.js +181 -0
  312. package/dist/internal/cursor-relay-core.d.ts +113 -0
  313. package/dist/internal/cursor-relay-core.d.ts.map +1 -0
  314. package/dist/internal/cursor-relay-core.js +364 -0
  315. package/dist/internal/cursor-slack-relay.d.ts +94 -0
  316. package/dist/internal/cursor-slack-relay.d.ts.map +1 -0
  317. package/dist/internal/cursor-slack-relay.js +171 -0
  318. package/dist/internal/describe-error.d.ts +3 -0
  319. package/dist/internal/describe-error.d.ts.map +1 -0
  320. package/dist/internal/describe-error.js +4 -0
  321. package/dist/internal/dev-mode.d.ts +13 -0
  322. package/dist/internal/dev-mode.d.ts.map +1 -0
  323. package/dist/internal/dev-mode.js +17 -0
  324. package/dist/internal/discovery.d.ts +55 -0
  325. package/dist/internal/discovery.d.ts.map +1 -0
  326. package/dist/internal/discovery.js +1427 -0
  327. package/dist/internal/distribution.d.ts +47 -0
  328. package/dist/internal/distribution.d.ts.map +1 -0
  329. package/dist/internal/distribution.js +82 -0
  330. package/dist/internal/docs-site.d.ts +28 -0
  331. package/dist/internal/docs-site.d.ts.map +1 -0
  332. package/dist/internal/docs-site.js +169 -0
  333. package/dist/internal/duration.d.ts +8 -0
  334. package/dist/internal/duration.d.ts.map +1 -0
  335. package/dist/internal/duration.js +35 -0
  336. package/dist/internal/eval-run-store.d.ts +81 -0
  337. package/dist/internal/eval-run-store.d.ts.map +1 -0
  338. package/dist/internal/eval-run-store.js +396 -0
  339. package/dist/internal/eval-runner.d.ts +76 -0
  340. package/dist/internal/eval-runner.d.ts.map +1 -0
  341. package/dist/internal/eval-runner.js +336 -0
  342. package/dist/internal/event-log.d.ts +51 -0
  343. package/dist/internal/event-log.d.ts.map +1 -0
  344. package/dist/internal/event-log.js +167 -0
  345. package/dist/internal/event-mapper.d.ts +46 -0
  346. package/dist/internal/event-mapper.d.ts.map +1 -0
  347. package/dist/internal/event-mapper.js +226 -0
  348. package/dist/internal/frontmatter.d.ts +12 -0
  349. package/dist/internal/frontmatter.d.ts.map +1 -0
  350. package/dist/internal/frontmatter.js +61 -0
  351. package/dist/internal/github-fanout.d.ts +32 -0
  352. package/dist/internal/github-fanout.d.ts.map +1 -0
  353. package/dist/internal/github-fanout.js +122 -0
  354. package/dist/internal/handleAgentServeTrigger.d.ts +59 -0
  355. package/dist/internal/handleAgentServeTrigger.d.ts.map +1 -0
  356. package/dist/internal/handleAgentServeTrigger.js +115 -0
  357. package/dist/internal/host-platforms.d.ts +40 -0
  358. package/dist/internal/host-platforms.d.ts.map +1 -0
  359. package/dist/internal/host-platforms.js +113 -0
  360. package/dist/internal/http-channel.d.ts +54 -0
  361. package/dist/internal/http-channel.d.ts.map +1 -0
  362. package/dist/internal/http-channel.js +382 -0
  363. package/dist/internal/ids.d.ts +19 -0
  364. package/dist/internal/ids.d.ts.map +1 -0
  365. package/dist/internal/ids.js +34 -0
  366. package/dist/internal/init-project.d.ts +22 -0
  367. package/dist/internal/init-project.d.ts.map +1 -0
  368. package/dist/internal/init-project.js +125 -0
  369. package/dist/internal/json-dir-store.d.ts +32 -0
  370. package/dist/internal/json-dir-store.d.ts.map +1 -0
  371. package/dist/internal/json-dir-store.js +100 -0
  372. package/dist/internal/json-schema.d.ts +18 -0
  373. package/dist/internal/json-schema.d.ts.map +1 -0
  374. package/dist/internal/json-schema.js +53 -0
  375. package/dist/internal/log-ring.d.ts +23 -0
  376. package/dist/internal/log-ring.d.ts.map +1 -0
  377. package/dist/internal/log-ring.js +42 -0
  378. package/dist/internal/map-pool.d.ts +6 -0
  379. package/dist/internal/map-pool.d.ts.map +1 -0
  380. package/dist/internal/map-pool.js +41 -0
  381. package/dist/internal/mcp-endpoint.d.ts +59 -0
  382. package/dist/internal/mcp-endpoint.d.ts.map +1 -0
  383. package/dist/internal/mcp-endpoint.js +355 -0
  384. package/dist/internal/mcp-host.d.ts +28 -0
  385. package/dist/internal/mcp-host.d.ts.map +1 -0
  386. package/dist/internal/mcp-host.js +162 -0
  387. package/dist/internal/net.d.ts +5 -0
  388. package/dist/internal/net.d.ts.map +1 -0
  389. package/dist/internal/net.js +30 -0
  390. package/dist/internal/peer-connections.d.ts +44 -0
  391. package/dist/internal/peer-connections.d.ts.map +1 -0
  392. package/dist/internal/peer-connections.js +67 -0
  393. package/dist/internal/playground/static.d.ts +35 -0
  394. package/dist/internal/playground/static.d.ts.map +1 -0
  395. package/dist/internal/playground/static.js +162 -0
  396. package/dist/internal/playground/toolchain.d.ts +57 -0
  397. package/dist/internal/playground/toolchain.d.ts.map +1 -0
  398. package/dist/internal/playground/toolchain.js +226 -0
  399. package/dist/internal/reminder-runner.d.ts +62 -0
  400. package/dist/internal/reminder-runner.d.ts.map +1 -0
  401. package/dist/internal/reminder-runner.js +582 -0
  402. package/dist/internal/reminder-schedule.d.ts +22 -0
  403. package/dist/internal/reminder-schedule.d.ts.map +1 -0
  404. package/dist/internal/reminder-schedule.js +82 -0
  405. package/dist/internal/reminder-store.d.ts +58 -0
  406. package/dist/internal/reminder-store.d.ts.map +1 -0
  407. package/dist/internal/reminder-store.js +106 -0
  408. package/dist/internal/resolved-connections.d.ts +41 -0
  409. package/dist/internal/resolved-connections.d.ts.map +1 -0
  410. package/dist/internal/resolved-connections.js +73 -0
  411. package/dist/internal/review-comments.d.ts +50 -0
  412. package/dist/internal/review-comments.d.ts.map +1 -0
  413. package/dist/internal/review-comments.js +194 -0
  414. package/dist/internal/router.d.ts +33 -0
  415. package/dist/internal/router.d.ts.map +1 -0
  416. package/dist/internal/router.js +93 -0
  417. package/dist/internal/run-client.d.ts +49 -0
  418. package/dist/internal/run-client.d.ts.map +1 -0
  419. package/dist/internal/run-client.js +208 -0
  420. package/dist/internal/schedule-runner.d.ts +31 -0
  421. package/dist/internal/schedule-runner.d.ts.map +1 -0
  422. package/dist/internal/schedule-runner.js +126 -0
  423. package/dist/internal/sdk-runner.d.ts +41 -0
  424. package/dist/internal/sdk-runner.d.ts.map +1 -0
  425. package/dist/internal/sdk-runner.js +221 -0
  426. package/dist/internal/server.d.ts +25 -0
  427. package/dist/internal/server.d.ts.map +1 -0
  428. package/dist/internal/server.js +1374 -0
  429. package/dist/internal/session-engine.d.ts +287 -0
  430. package/dist/internal/session-engine.d.ts.map +1 -0
  431. package/dist/internal/session-engine.js +1377 -0
  432. package/dist/internal/session-store.d.ts +29 -0
  433. package/dist/internal/session-store.d.ts.map +1 -0
  434. package/dist/internal/session-store.js +140 -0
  435. package/dist/internal/session-urls.d.ts +10 -0
  436. package/dist/internal/session-urls.d.ts.map +1 -0
  437. package/dist/internal/session-urls.js +25 -0
  438. package/dist/internal/stream-progress.d.ts +14 -0
  439. package/dist/internal/stream-progress.d.ts.map +1 -0
  440. package/dist/internal/stream-progress.js +195 -0
  441. package/dist/internal/tool-result.d.ts +20 -0
  442. package/dist/internal/tool-result.d.ts.map +1 -0
  443. package/dist/internal/tool-result.js +45 -0
  444. package/dist/internal/trajectory.d.ts +56 -0
  445. package/dist/internal/trajectory.d.ts.map +1 -0
  446. package/dist/internal/trajectory.js +248 -0
  447. package/dist/internal/workspace.d.ts +42 -0
  448. package/dist/internal/workspace.d.ts.map +1 -0
  449. package/dist/internal/workspace.js +199 -0
  450. package/dist/playground/assets/cursor-icons-outline-oY2V_mvK.woff2 +0 -0
  451. package/dist/playground/assets/index-1K-hG-7p.css +1 -0
  452. package/dist/playground/assets/index-FlWjhg3x.js +79 -0
  453. package/dist/playground/index.html +17 -0
  454. package/dist/reminders.d.ts +23 -0
  455. package/dist/reminders.d.ts.map +1 -0
  456. package/dist/reminders.js +22 -0
  457. package/dist/schedules.d.ts +23 -0
  458. package/dist/schedules.d.ts.map +1 -0
  459. package/dist/schedules.js +26 -0
  460. package/dist/skills.d.ts +22 -0
  461. package/dist/skills.d.ts.map +1 -0
  462. package/dist/skills.js +22 -0
  463. package/dist/tools.d.ts +92 -0
  464. package/dist/tools.d.ts.map +1 -0
  465. package/dist/tools.js +68 -0
  466. package/dist/types.d.ts +1609 -0
  467. package/dist/types.d.ts.map +1 -0
  468. package/dist/types.js +80 -0
  469. package/docs/README.md +174 -0
  470. package/docs/ab.md +355 -0
  471. package/docs/building-with-agents.md +129 -0
  472. package/docs/concepts.md +177 -0
  473. package/docs/deployment.md +218 -0
  474. package/docs/evals.md +383 -0
  475. package/docs/guides/agent-to-agent.md +118 -0
  476. package/docs/guides/cloud-runtime.md +122 -0
  477. package/docs/guides/github.md +172 -0
  478. package/docs/guides/human-in-the-loop.md +131 -0
  479. package/docs/guides/slack.md +245 -0
  480. package/docs/guides/webhooks.md +201 -0
  481. package/docs/hillclimbing.md +93 -0
  482. package/docs/quickstart.md +183 -0
  483. package/docs/reference/agent-config.md +154 -0
  484. package/docs/reference/channels.md +206 -0
  485. package/docs/reference/cli.md +257 -0
  486. package/docs/reference/connections.md +137 -0
  487. package/docs/reference/hooks.md +74 -0
  488. package/docs/reference/http-api.md +219 -0
  489. package/docs/reference/instructions.md +77 -0
  490. package/docs/reference/playground.md +67 -0
  491. package/docs/reference/project-layout.md +119 -0
  492. package/docs/reference/schedules.md +220 -0
  493. package/docs/reference/sessions.md +165 -0
  494. package/docs/reference/skills.md +79 -0
  495. package/docs/reference/subagents.md +74 -0
  496. package/docs/reference/tools.md +203 -0
  497. package/docs/scaffolding-agents.md +113 -0
  498. package/docs/troubleshooting.md +95 -0
  499. package/package.json +185 -0
  500. package/skills/ab/SKILL.md +139 -0
  501. package/skills/create-agent/SKILL.md +219 -0
  502. package/skills/debug/SKILL.md +71 -0
  503. package/skills/evals/SKILL.md +217 -0
  504. package/skills/framework-map/SKILL.md +142 -0
  505. package/skills/github/SKILL.md +144 -0
  506. package/skills/hillclimb/SKILL.md +162 -0
  507. package/skills/setup-slack/SKILL.md +180 -0
  508. package/src/ab.ts +675 -0
  509. package/src/bin/agent-serve.ts +949 -0
  510. package/src/channels/github/api.ts +374 -0
  511. package/src/channels/github/auth.ts +275 -0
  512. package/src/channels/github/binding.ts +223 -0
  513. package/src/channels/github/defaults.ts +111 -0
  514. package/src/channels/github/events.ts +72 -0
  515. package/src/channels/github/forward.ts +381 -0
  516. package/src/channels/github/github-channel.ts +2270 -0
  517. package/src/channels/github/index.ts +52 -0
  518. package/src/channels/github/replay.ts +387 -0
  519. package/src/channels/github/state.ts +95 -0
  520. package/src/channels/github/types.ts +490 -0
  521. package/src/channels/slack/api.ts +580 -0
  522. package/src/channels/slack/approvals.ts +198 -0
  523. package/src/channels/slack/assistant.ts +76 -0
  524. package/src/channels/slack/auth.ts +112 -0
  525. package/src/channels/slack/channel-watch.ts +219 -0
  526. package/src/channels/slack/constants.ts +30 -0
  527. package/src/channels/slack/credentials.ts +90 -0
  528. package/src/channels/slack/cursor-account.ts +166 -0
  529. package/src/channels/slack/defaults.ts +450 -0
  530. package/src/channels/slack/dispatch.ts +293 -0
  531. package/src/channels/slack/doctor.ts +135 -0
  532. package/src/channels/slack/event-id-dedupe.ts +30 -0
  533. package/src/channels/slack/inbound.ts +219 -0
  534. package/src/channels/slack/index.ts +45 -0
  535. package/src/channels/slack/init.ts +133 -0
  536. package/src/channels/slack/interactive.ts +194 -0
  537. package/src/channels/slack/links.ts +23 -0
  538. package/src/channels/slack/live-delivery.ts +201 -0
  539. package/src/channels/slack/log.ts +83 -0
  540. package/src/channels/slack/manifest.ts +179 -0
  541. package/src/channels/slack/pr-ref.ts +50 -0
  542. package/src/channels/slack/setup.ts +97 -0
  543. package/src/channels/slack/slack-channel.ts +374 -0
  544. package/src/channels/slack/socket-mode.ts +154 -0
  545. package/src/channels/slack/stream.ts +63 -0
  546. package/src/channels/slack/tool-approval-events.ts +136 -0
  547. package/src/channels/slack/types.ts +349 -0
  548. package/src/channels.ts +385 -0
  549. package/src/connections.ts +89 -0
  550. package/src/evals.ts +501 -0
  551. package/src/hooks.ts +33 -0
  552. package/src/index.ts +184 -0
  553. package/src/internal/ab-collector.ts +210 -0
  554. package/src/internal/ab-fold.ts +228 -0
  555. package/src/internal/ab-snapshot.ts +335 -0
  556. package/src/internal/approval-gate.ts +115 -0
  557. package/src/internal/auth.ts +39 -0
  558. package/src/internal/authored-alias-hooks.ts +69 -0
  559. package/src/internal/authored-loaders.ts +138 -0
  560. package/src/internal/bounded-int.ts +27 -0
  561. package/src/internal/brand.ts +29 -0
  562. package/src/internal/chat-client.ts +407 -0
  563. package/src/internal/cli-ax.ts +474 -0
  564. package/src/internal/cli-cursor.ts +275 -0
  565. package/src/internal/cli-github.ts +849 -0
  566. package/src/internal/cli-slack.ts +175 -0
  567. package/src/internal/cloud-merge.ts +41 -0
  568. package/src/internal/cron.ts +78 -0
  569. package/src/internal/cursor/account-mcp.ts +472 -0
  570. package/src/internal/cursor/backend-client.ts +614 -0
  571. package/src/internal/cursor/credentials.ts +401 -0
  572. package/src/internal/cursor-event-relay.ts +281 -0
  573. package/src/internal/cursor-relay-core.ts +444 -0
  574. package/src/internal/cursor-slack-relay.ts +242 -0
  575. package/src/internal/describe-error.ts +4 -0
  576. package/src/internal/dev-mode.ts +20 -0
  577. package/src/internal/discovery.ts +1709 -0
  578. package/src/internal/distribution.ts +97 -0
  579. package/src/internal/docs-site.ts +191 -0
  580. package/src/internal/duration.ts +39 -0
  581. package/src/internal/eval-run-store.ts +519 -0
  582. package/src/internal/eval-runner.ts +522 -0
  583. package/src/internal/event-log.ts +175 -0
  584. package/src/internal/event-mapper.ts +272 -0
  585. package/src/internal/frontmatter.ts +77 -0
  586. package/src/internal/github-fanout.ts +159 -0
  587. package/src/internal/handleAgentServeTrigger.ts +156 -0
  588. package/src/internal/host-platforms.ts +144 -0
  589. package/src/internal/http-channel.ts +546 -0
  590. package/src/internal/ids.ts +44 -0
  591. package/src/internal/init-project.ts +165 -0
  592. package/src/internal/json-dir-store.ts +109 -0
  593. package/src/internal/json-schema.ts +69 -0
  594. package/src/internal/log-ring.ts +59 -0
  595. package/src/internal/map-pool.ts +32 -0
  596. package/src/internal/mcp-endpoint.ts +518 -0
  597. package/src/internal/mcp-host.ts +211 -0
  598. package/src/internal/net.ts +31 -0
  599. package/src/internal/peer-connections.ts +100 -0
  600. package/src/internal/playground/static.ts +189 -0
  601. package/src/internal/playground/toolchain.ts +277 -0
  602. package/src/internal/reminder-runner.ts +756 -0
  603. package/src/internal/reminder-schedule.ts +106 -0
  604. package/src/internal/reminder-store.ts +145 -0
  605. package/src/internal/resolved-connections.ts +145 -0
  606. package/src/internal/review-comments.ts +268 -0
  607. package/src/internal/router.ts +145 -0
  608. package/src/internal/run-client.ts +320 -0
  609. package/src/internal/schedule-runner.ts +161 -0
  610. package/src/internal/sdk-runner.ts +315 -0
  611. package/src/internal/server.ts +1737 -0
  612. package/src/internal/session-engine.ts +1810 -0
  613. package/src/internal/session-store.ts +147 -0
  614. package/src/internal/session-urls.ts +40 -0
  615. package/src/internal/stream-progress.ts +254 -0
  616. package/src/internal/tool-result.ts +54 -0
  617. package/src/internal/trajectory.ts +306 -0
  618. package/src/internal/workspace.ts +223 -0
  619. package/src/reminders.ts +35 -0
  620. package/src/schedules.ts +37 -0
  621. package/src/skills.ts +27 -0
  622. package/src/tools.ts +127 -0
  623. package/src/types.ts +1848 -0
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Host-side GitHub + Slack clients shared across tools, channel routes,
3
+ * schedules, and channel packs — same injection pattern as MCP.
4
+ */
5
+
6
+ import { WebClient } from "@slack/web-api";
7
+ import { createGitHubOctokit } from "../channels/github/api.js";
8
+ import {
9
+ ensureGhCliTokenEnv,
10
+ hasGitHubAppCredentials,
11
+ resolveCredentialValue,
12
+ resolveGitHubInstallationId,
13
+ tryResolveGhAuthToken,
14
+ } from "../channels/github/auth.js";
15
+ import { tryResolveBotToken } from "../channels/slack/credentials.js";
16
+ import type { HostGitHubClient, HostSlackClient } from "../types.js";
17
+
18
+ export interface HostPlatforms {
19
+ github: HostGitHubClient;
20
+ slack: HostSlackClient;
21
+ }
22
+
23
+ /**
24
+ * How ambient host GitHub auth was resolved.
25
+ * `app` = GitHub App installation token (preferred in production).
26
+ * `env` / `gh` = local PAT / CLI fallbacks when App creds are unset.
27
+ */
28
+ export type HostGitHubAuthSource = "app" | "env" | "gh" | "unavailable";
29
+
30
+ /**
31
+ * Build host platforms from ambient credentials. Prefer App installation
32
+ * auth when configured; otherwise fall back to PAT / `gh auth` for local
33
+ * testing. Webhook-scoped calls should still prefer `ctx.github`.
34
+ */
35
+ export function createHostPlatforms(): HostPlatforms {
36
+ let octokitPromise: ReturnType<HostGitHubClient["getOctokit"]> | undefined;
37
+ let slackPromise: ReturnType<HostSlackClient["getClient"]> | undefined;
38
+
39
+ return {
40
+ github: {
41
+ getOctokit: () => {
42
+ octokitPromise ??= createGitHubOctokit({});
43
+ return octokitPromise;
44
+ },
45
+ },
46
+ slack: {
47
+ getClient: async () => {
48
+ if (slackPromise === undefined) {
49
+ slackPromise = (async () => {
50
+ const token = await tryResolveBotToken(undefined);
51
+ if (token === undefined) {
52
+ throw new Error(
53
+ "No Slack bot token available (set SLACK_BOT_TOKEN or a channel envPrefix)."
54
+ );
55
+ }
56
+ return new WebClient(token);
57
+ })();
58
+ }
59
+ return slackPromise;
60
+ },
61
+ },
62
+ };
63
+ }
64
+
65
+ /**
66
+ * Detect ambient host GitHub auth without throwing.
67
+ * Order matches {@link createGitHubOctokit}: App installation, then
68
+ * `GITHUB_TOKEN` / `GH_TOKEN`, then `gh auth token`.
69
+ */
70
+ export async function resolveHostGitHubAuthSource(): Promise<HostGitHubAuthSource> {
71
+ if (
72
+ (await hasGitHubAppCredentials()) &&
73
+ (await resolveGitHubInstallationId()) !== undefined
74
+ ) {
75
+ return "app";
76
+ }
77
+ const fromEnv =
78
+ (await resolveCredentialValue(process.env.GITHUB_TOKEN)) ??
79
+ (await resolveCredentialValue(process.env.GH_TOKEN));
80
+ if (fromEnv !== undefined) {
81
+ return "env";
82
+ }
83
+ const fromGh = await tryResolveGhAuthToken();
84
+ return fromGh === undefined ? "unavailable" : "gh";
85
+ }
86
+
87
+ /**
88
+ * Soft boot-time GitHub auth check: log the resolved source and optionally
89
+ * prime `github.getOctokit()` so the first request does not pay CLI latency.
90
+ * When auth is App-backed, also export an installation token as `GH_TOKEN`
91
+ * so tools that shell out to `gh` (a host-side `prepare_pr` tool, say)
92
+ * authenticate on corp hosts that have no PAT / `gh
93
+ * auth login`. Never fails serve — missing auth is logged as a warning.
94
+ */
95
+ export async function warmupHostGitHubAuth(options: {
96
+ logger: (line: string) => void;
97
+ github?: HostGitHubClient;
98
+ }): Promise<HostGitHubAuthSource> {
99
+ const source = await resolveHostGitHubAuthSource();
100
+ if (source === "unavailable") {
101
+ options.logger(
102
+ "[agent-serve] GitHub auth: unavailable (set GITHUB_APP_ID + GITHUB_APP_PRIVATE_KEY + GITHUB_APP_INSTALLATION_ID, or GITHUB_TOKEN / GH_TOKEN, or run `gh auth login`)"
103
+ );
104
+ return source;
105
+ }
106
+
107
+ let exportedGhToken = false;
108
+ if (source === "app") {
109
+ try {
110
+ exportedGhToken = await ensureGhCliTokenEnv();
111
+ } catch (error) {
112
+ options.logger(
113
+ `[agent-serve] GitHub auth: failed to export GH_TOKEN for gh CLI: ${
114
+ error instanceof Error ? error.message : String(error)
115
+ }`
116
+ );
117
+ }
118
+ }
119
+
120
+ const label =
121
+ source === "app"
122
+ ? exportedGhToken
123
+ ? "GitHub App installation token (also exported as GH_TOKEN for gh CLI)"
124
+ : "GitHub App installation token"
125
+ : source === "env"
126
+ ? "GITHUB_TOKEN/GH_TOKEN"
127
+ : "gh auth token";
128
+ if (options.github === undefined) {
129
+ options.logger(`[agent-serve] GitHub auth: ${label}`);
130
+ return source;
131
+ }
132
+
133
+ try {
134
+ await options.github.getOctokit();
135
+ options.logger(`[agent-serve] GitHub auth: ${label}`);
136
+ } catch (error) {
137
+ options.logger(
138
+ `[agent-serve] GitHub auth: ${label} resolved but Octokit warmup failed: ${
139
+ error instanceof Error ? error.message : String(error)
140
+ }`
141
+ );
142
+ }
143
+ return source;
144
+ }
@@ -0,0 +1,546 @@
1
+ /**
2
+ * The built-in HTTP session channel: the default API that `curl`, SDK
3
+ * clients, and frontends talk to. Mounted at `/v1/session*` and enabled even
4
+ * when `agent/channels/http.ts` does not exist; author that file with
5
+ * `httpChannel({ ... })` to override auth or observe events.
6
+ *
7
+ * Continuation semantics: `POST /v1/session` returns a `continuationToken`;
8
+ * each accepted follow-up rotates it and returns the replacement, and a
9
+ * stale token is rejected with 409. Follow-ups address any chat session by
10
+ * id (including custom channels such as `drive`) when the token matches
11
+ * that session's channel + key; task sessions stay fire-and-forget.
12
+ */
13
+
14
+ import type {
15
+ AuthContext,
16
+ AuthPolicy,
17
+ HttpChannelDefinition,
18
+ JsonValue,
19
+ SessionRecord,
20
+ } from "../types.js";
21
+ import { samePrincipal } from "./auth.js";
22
+ import {
23
+ formatContinuationToken,
24
+ newContinuationKey,
25
+ parseContinuationToken,
26
+ } from "./ids.js";
27
+ import { isLoopbackAddress } from "./net.js";
28
+ import type { ServerRoute } from "./router.js";
29
+ import {
30
+ ApprovalInterruptedError,
31
+ ApprovalNotFoundError,
32
+ HTTP_CHANNEL_ID,
33
+ SessionAuthError,
34
+ SessionBusyError,
35
+ type SessionEngine,
36
+ } from "./session-engine.js";
37
+ import {
38
+ eventsUrlForSession,
39
+ playgroundUrlForSession,
40
+ } from "./session-urls.js";
41
+
42
+ const SESSION_ID_HEADER = "x-agent-serve-session-id";
43
+
44
+ export function buildHttpChannelRoutes(args: {
45
+ engine: SessionEngine;
46
+ config: HttpChannelDefinition;
47
+ auth: AuthPolicy[];
48
+ /** Path prefix ("" single-agent, "/<slug>" multi-agent). */
49
+ basePath?: string;
50
+ /**
51
+ * When true (server `--dev` without bearer/custom auth), session
52
+ * stream/events/follow-up are readable without matching the creating
53
+ * principal — matching `GET /v1/sessions` includeAll so the playground
54
+ * can open every listed session. Still requires a loopback caller unless
55
+ * {@link relaxSessionReadAuthBeyondLoopback} is also set.
56
+ */
57
+ relaxSessionReadAuth?: boolean;
58
+ /**
59
+ * With {@link relaxSessionReadAuth}, skip the loopback IP check so remote
60
+ * callers (e.g. Tailscale + `--allow-anonymous`) can open listed sessions.
61
+ */
62
+ relaxSessionReadAuthBeyondLoopback?: boolean;
63
+ /**
64
+ * `--dev` bridge: allow playground / HTTP callers to Approve/Deny parked
65
+ * tools on Slack-owned sessions (Slack principals never match local /
66
+ * anonymous auth). Does not open approval writes on HTTP-owned sessions.
67
+ * Respects the same loopback / beyondLoopback gate as session reads.
68
+ */
69
+ relaxSessionApprovalAuth?: boolean;
70
+ }): ServerRoute[] {
71
+ const { engine, config, auth } = args;
72
+ const base = args.basePath ?? "";
73
+ const relaxSessionReadAuth = args.relaxSessionReadAuth ?? false;
74
+ const relaxSessionReadAuthBeyondLoopback =
75
+ args.relaxSessionReadAuthBeyondLoopback ?? false;
76
+ const relaxSessionApprovalAuth = args.relaxSessionApprovalAuth ?? false;
77
+
78
+ const transformMessage = async (
79
+ message: string,
80
+ authContext: AuthContext | null
81
+ ): Promise<string> => {
82
+ if (config.onMessage === undefined) {
83
+ return message;
84
+ }
85
+ return config.onMessage(message, { auth: authContext });
86
+ };
87
+
88
+ const createSession: ServerRoute = {
89
+ method: "POST",
90
+ pattern: `${base}/v1/session`,
91
+ auth,
92
+ handler: async (request, ctx) => {
93
+ const body = await readJsonObject(request);
94
+ if (body === undefined || typeof body.message !== "string") {
95
+ return errorResponse(
96
+ 400,
97
+ "invalid_request",
98
+ "Expected a JSON body with a string `message`."
99
+ );
100
+ }
101
+ const message = await transformMessage(body.message, ctx.auth);
102
+ const workspaceFiles = readWorkspaceFiles(body.workspaceFiles);
103
+ const session = await engine.send(HTTP_CHANNEL_ID, message, {
104
+ auth: ctx.auth,
105
+ ...(body.state === undefined ? {} : { state: body.state as JsonValue }),
106
+ ...(typeof body.title === "string" ? { title: body.title } : {}),
107
+ ...(body.purpose === "eval" ? { purpose: "eval" as const } : {}),
108
+ ...(workspaceFiles === undefined ? {} : { workspaceFiles }),
109
+ });
110
+ return jsonResponse(
111
+ {
112
+ ok: true,
113
+ sessionId: session.id,
114
+ continuationToken: formatContinuationToken(
115
+ HTTP_CHANNEL_ID,
116
+ session.continuationToken ?? ""
117
+ ),
118
+ playgroundUrl: playgroundUrlForSession(request, base, session.id),
119
+ traceUrl: eventsUrlForSession(request.url, base, session.id),
120
+ },
121
+ { headers: { [SESSION_ID_HEADER]: session.id } }
122
+ );
123
+ },
124
+ };
125
+
126
+ const followUp: ServerRoute = {
127
+ method: "POST",
128
+ pattern: `${base}/v1/session/:sessionId`,
129
+ auth,
130
+ handler: async (request, ctx) => {
131
+ const sessionId = ctx.params.sessionId ?? "";
132
+ const record = await engine.sessions.get(sessionId);
133
+ if (record === undefined) {
134
+ return errorResponse(
135
+ 404,
136
+ "session_not_found",
137
+ `Unknown session ${sessionId}.`
138
+ );
139
+ }
140
+ // Playground (and other HTTP clients) may follow up on any chat
141
+ // session — including custom channels like `drive` — using that
142
+ // session's own continuation token. Task/schedule sessions stay
143
+ // fire-and-forget.
144
+ if (record.mode === "task") {
145
+ return errorResponse(
146
+ 409,
147
+ "session_not_followable",
148
+ "Task sessions are fire-and-forget; they do not accept follow-ups."
149
+ );
150
+ }
151
+ const ownership = requireSessionOwner(record, ctx.auth, {
152
+ relax: relaxSessionReadAuth,
153
+ beyondLoopback: relaxSessionReadAuthBeyondLoopback,
154
+ requestIp: ctx.requestIp,
155
+ });
156
+ if (ownership !== undefined) {
157
+ return ownership;
158
+ }
159
+ const body = await readJsonObject(request);
160
+ if (body === undefined || typeof body.message !== "string") {
161
+ return errorResponse(
162
+ 400,
163
+ "invalid_request",
164
+ "Expected a JSON body with a string `message`."
165
+ );
166
+ }
167
+ if (typeof body.continuationToken !== "string") {
168
+ return errorResponse(
169
+ 400,
170
+ "invalid_request",
171
+ "Expected a `continuationToken` from the previous response."
172
+ );
173
+ }
174
+ const presented = parseContinuationToken(body.continuationToken);
175
+ if (
176
+ presented === null ||
177
+ presented.channelId !== record.channelId ||
178
+ record.continuationKey === null ||
179
+ presented.key !== record.continuationKey
180
+ ) {
181
+ return errorResponse(
182
+ 409,
183
+ "stale_continuation_token",
184
+ "The continuation token does not address this session's active continuation."
185
+ );
186
+ }
187
+
188
+ const message = await transformMessage(body.message, ctx.auth);
189
+ try {
190
+ // Continue as the session owner after the HTTP ownership gate so
191
+ // `--dev` relaxed reads can follow up on channel-owned sessions
192
+ // (drive/slack/…) without failing SessionAuthError.
193
+ await engine.send(record.channelId, message, {
194
+ auth: record.auth,
195
+ continuationToken: record.continuationKey,
196
+ });
197
+ } catch (error) {
198
+ if (error instanceof SessionBusyError) {
199
+ return errorResponse(
200
+ 409,
201
+ "session_busy",
202
+ "A turn is already running; wait for session.waiting before sending a follow-up."
203
+ );
204
+ }
205
+ throw error;
206
+ }
207
+
208
+ // Rotate only after the message is accepted so a rejected send leaves
209
+ // the caller's token valid for retry.
210
+ const rotated = newContinuationKey();
211
+ await engine.setContinuationToken(sessionId, rotated);
212
+ return jsonResponse(
213
+ {
214
+ ok: true,
215
+ sessionId,
216
+ continuationToken: formatContinuationToken(record.channelId, rotated),
217
+ },
218
+ { headers: { [SESSION_ID_HEADER]: sessionId } }
219
+ );
220
+ },
221
+ };
222
+
223
+ const stream: ServerRoute = {
224
+ method: "GET",
225
+ pattern: `${base}/v1/session/:sessionId/stream`,
226
+ auth,
227
+ handler: async (request, ctx) => {
228
+ const sessionId = ctx.params.sessionId ?? "";
229
+ // The stream-and-inspect handle is runtime-owned: sessions started by
230
+ // custom channels or schedules are observable here too when the caller
231
+ // matches the session's stored principal (or `--dev` relax). Follow-ups
232
+ // use the same ownership gate plus the session's continuation token.
233
+ const record = await engine.sessions.get(sessionId);
234
+ if (record === undefined) {
235
+ return errorResponse(
236
+ 404,
237
+ "session_not_found",
238
+ `Unknown session ${sessionId}.`
239
+ );
240
+ }
241
+ const ownership = requireSessionOwner(record, ctx.auth, {
242
+ relax: relaxSessionReadAuth,
243
+ beyondLoopback: relaxSessionReadAuthBeyondLoopback,
244
+ requestIp: ctx.requestIp,
245
+ });
246
+ if (ownership !== undefined) {
247
+ return ownership;
248
+ }
249
+ const url = new URL(request.url);
250
+ const rawStartIndex = url.searchParams.get("startIndex");
251
+ const startIndex =
252
+ rawStartIndex === null ? 0 : Number.parseInt(rawStartIndex, 10);
253
+ if (Number.isNaN(startIndex) || startIndex < 0) {
254
+ return errorResponse(
255
+ 400,
256
+ "invalid_request",
257
+ "startIndex must be a non-negative integer."
258
+ );
259
+ }
260
+ const body = await engine.eventStream(sessionId, startIndex);
261
+ return new Response(body, {
262
+ status: 200,
263
+ headers: {
264
+ "content-type": "application/x-ndjson; charset=utf-8",
265
+ "cache-control": "no-store",
266
+ [SESSION_ID_HEADER]: sessionId,
267
+ },
268
+ });
269
+ },
270
+ };
271
+
272
+ /** One-shot NDJSON (or JSON) dump of the session trace. */
273
+ const events: ServerRoute = {
274
+ method: "GET",
275
+ pattern: `${base}/v1/session/:sessionId/events`,
276
+ auth,
277
+ handler: async (request, ctx) => {
278
+ const sessionId = ctx.params.sessionId ?? "";
279
+ const record = await engine.sessions.get(sessionId);
280
+ if (record === undefined) {
281
+ return errorResponse(
282
+ 404,
283
+ "session_not_found",
284
+ `Unknown session ${sessionId}.`
285
+ );
286
+ }
287
+ const ownership = requireSessionOwner(record, ctx.auth, {
288
+ relax: relaxSessionReadAuth,
289
+ beyondLoopback: relaxSessionReadAuthBeyondLoopback,
290
+ requestIp: ctx.requestIp,
291
+ });
292
+ if (ownership !== undefined) {
293
+ return ownership;
294
+ }
295
+ const url = new URL(request.url);
296
+ const asJson = url.searchParams.get("format") === "json";
297
+ const snapshot = await engine.listEvents(sessionId, 0);
298
+ if (asJson) {
299
+ return jsonResponse({
300
+ sessionId,
301
+ events: snapshot,
302
+ playgroundUrl: playgroundUrlForSession(request, base, sessionId),
303
+ });
304
+ }
305
+ const ndjson = `${snapshot.map((e) => JSON.stringify(e)).join("\n")}${
306
+ snapshot.length > 0 ? "\n" : ""
307
+ }`;
308
+ return new Response(ndjson, {
309
+ status: 200,
310
+ headers: {
311
+ "content-type": "application/x-ndjson; charset=utf-8",
312
+ "cache-control": "no-store",
313
+ "content-disposition": `attachment; filename="${sessionId}.ndjson"`,
314
+ [SESSION_ID_HEADER]: sessionId,
315
+ },
316
+ });
317
+ },
318
+ };
319
+
320
+ const listApprovals: ServerRoute = {
321
+ method: "GET",
322
+ pattern: `${base}/v1/session/:sessionId/approvals`,
323
+ auth,
324
+ handler: async (_request, ctx) => {
325
+ const sessionId = ctx.params.sessionId ?? "";
326
+ const record = await engine.sessions.get(sessionId);
327
+ if (record === undefined) {
328
+ return errorResponse(
329
+ 404,
330
+ "session_not_found",
331
+ `Unknown session ${sessionId}.`
332
+ );
333
+ }
334
+ const ownership = requireSessionOwner(record, ctx.auth, {
335
+ relax: relaxSessionReadAuth,
336
+ beyondLoopback: relaxSessionReadAuthBeyondLoopback,
337
+ requestIp: ctx.requestIp,
338
+ });
339
+ if (ownership !== undefined) {
340
+ return ownership;
341
+ }
342
+ const pending = await engine.listPendingApprovals(sessionId);
343
+ return jsonResponse({ ok: true, sessionId, pending });
344
+ },
345
+ };
346
+
347
+ const resolveApproval: ServerRoute = {
348
+ method: "POST",
349
+ pattern: `${base}/v1/session/:sessionId/approvals/:callId`,
350
+ auth,
351
+ handler: async (request, ctx) => {
352
+ const sessionId = ctx.params.sessionId ?? "";
353
+ const callId = ctx.params.callId ?? "";
354
+ const record = await engine.sessions.get(sessionId);
355
+ if (record === undefined) {
356
+ return errorResponse(
357
+ 404,
358
+ "session_not_found",
359
+ `Unknown session ${sessionId}.`
360
+ );
361
+ }
362
+ const bridgeSlackApproval =
363
+ relaxSessionApprovalAuth === true &&
364
+ record.auth?.authenticator === "slack" &&
365
+ (relaxSessionReadAuthBeyondLoopback === true ||
366
+ (typeof ctx.requestIp === "string" &&
367
+ isLoopbackAddress(ctx.requestIp)));
368
+ const ownership = requireSessionOwner(record, ctx.auth, {
369
+ // HTTP sessions stay strict. Slack sessions may use the --dev
370
+ // playground bridge (see relaxSessionApprovalAuth).
371
+ relax: bridgeSlackApproval,
372
+ beyondLoopback: relaxSessionReadAuthBeyondLoopback,
373
+ requestIp: ctx.requestIp,
374
+ });
375
+ if (ownership !== undefined) {
376
+ return ownership;
377
+ }
378
+ const body = await readJsonObject(request);
379
+ const decision = body?.decision;
380
+ if (decision !== "approve" && decision !== "deny") {
381
+ return errorResponse(
382
+ 400,
383
+ "invalid_request",
384
+ 'Expected a JSON body with `decision`: "approve" | "deny".'
385
+ );
386
+ }
387
+ try {
388
+ const pending = await engine.resolveApproval(
389
+ sessionId,
390
+ callId,
391
+ decision,
392
+ ctx.auth,
393
+ bridgeSlackApproval ? { asSessionOwner: true } : undefined
394
+ );
395
+ return jsonResponse({
396
+ ok: true,
397
+ sessionId,
398
+ callId,
399
+ decision,
400
+ toolName: pending.toolName,
401
+ });
402
+ } catch (error) {
403
+ if (error instanceof ApprovalNotFoundError) {
404
+ return errorResponse(404, "approval_not_found", error.message);
405
+ }
406
+ if (error instanceof ApprovalInterruptedError) {
407
+ return errorResponse(409, "approval_interrupted", error.message);
408
+ }
409
+ if (error instanceof SessionAuthError) {
410
+ return errorResponse(403, "forbidden", error.message);
411
+ }
412
+ throw error;
413
+ }
414
+ },
415
+ };
416
+
417
+ const stop: ServerRoute = {
418
+ method: "POST",
419
+ pattern: `${base}/v1/session/:sessionId/stop`,
420
+ auth,
421
+ handler: async (_request, ctx) => {
422
+ const sessionId = ctx.params.sessionId ?? "";
423
+ const record = await engine.sessions.get(sessionId);
424
+ if (record === undefined) {
425
+ return errorResponse(
426
+ 404,
427
+ "session_not_found",
428
+ `Unknown session ${sessionId}.`
429
+ );
430
+ }
431
+ const ownership = requireSessionOwner(record, ctx.auth, {
432
+ relax: relaxSessionReadAuth,
433
+ beyondLoopback: relaxSessionReadAuthBeyondLoopback,
434
+ requestIp: ctx.requestIp,
435
+ });
436
+ if (ownership !== undefined) {
437
+ return ownership;
438
+ }
439
+ const interrupted = await engine.interrupt(sessionId);
440
+ return jsonResponse(
441
+ { ok: true, interrupted },
442
+ { headers: { [SESSION_ID_HEADER]: sessionId } }
443
+ );
444
+ },
445
+ };
446
+
447
+ return [
448
+ createSession,
449
+ followUp,
450
+ stop,
451
+ stream,
452
+ events,
453
+ listApprovals,
454
+ resolveApproval,
455
+ ];
456
+ }
457
+
458
+ export function requireSessionOwner(
459
+ record: SessionRecord,
460
+ caller: AuthContext | null,
461
+ options?: {
462
+ relax?: boolean;
463
+ beyondLoopback?: boolean;
464
+ requestIp?: string | null;
465
+ }
466
+ ): Response | undefined {
467
+ // Dev playground lists every session (`includeAll`); match that by
468
+ // allowing cross-principal read/follow-up. Loopback-only unless
469
+ // `--allow-anonymous` also opted into beyondLoopback.
470
+ const relaxOwnership =
471
+ options?.relax === true &&
472
+ (options.beyondLoopback === true ||
473
+ (typeof options.requestIp === "string" &&
474
+ isLoopbackAddress(options.requestIp)));
475
+ if (relaxOwnership || samePrincipal(record.auth, caller)) {
476
+ return undefined;
477
+ }
478
+ return errorResponse(
479
+ 403,
480
+ "forbidden",
481
+ "This session belongs to a different principal."
482
+ );
483
+ }
484
+
485
+ export function jsonResponse(
486
+ data: unknown,
487
+ init: { status?: number; headers?: Record<string, string> } = {}
488
+ ): Response {
489
+ return new Response(JSON.stringify(data), {
490
+ status: init.status ?? 200,
491
+ headers: {
492
+ "content-type": "application/json; charset=utf-8",
493
+ ...init.headers,
494
+ },
495
+ });
496
+ }
497
+
498
+ export function errorResponse(
499
+ status: number,
500
+ code: string,
501
+ message: string
502
+ ): Response {
503
+ return jsonResponse({ ok: false, error: code, message }, { status });
504
+ }
505
+
506
+ function readWorkspaceFiles(
507
+ value: unknown
508
+ ): Record<string, string> | undefined {
509
+ if (value === undefined || value === null || typeof value !== "object") {
510
+ return undefined;
511
+ }
512
+ if (Array.isArray(value)) {
513
+ return undefined;
514
+ }
515
+ const files: Record<string, string> = {};
516
+ for (const [path, contents] of Object.entries(
517
+ value as Record<string, unknown>
518
+ )) {
519
+ if (typeof path !== "string" || path.trim() === "") {
520
+ continue;
521
+ }
522
+ if (typeof contents !== "string") {
523
+ continue;
524
+ }
525
+ files[path] = contents;
526
+ }
527
+ return Object.keys(files).length === 0 ? undefined : files;
528
+ }
529
+
530
+ export async function readJsonObject(
531
+ request: Request
532
+ ): Promise<Record<string, unknown> | undefined> {
533
+ try {
534
+ const parsed: unknown = await request.json();
535
+ if (
536
+ typeof parsed === "object" &&
537
+ parsed !== null &&
538
+ !Array.isArray(parsed)
539
+ ) {
540
+ return parsed as Record<string, unknown>;
541
+ }
542
+ return undefined;
543
+ } catch {
544
+ return undefined;
545
+ }
546
+ }