@cursor/july 0.1.92 → 0.1.94

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 (448) hide show
  1. package/AGENTS.md +8 -20
  2. package/README.md +115 -182
  3. package/dist/channels/deployments/deployments-channel.d.ts +7 -0
  4. package/dist/channels/deployments/deployments-channel.d.ts.map +1 -1
  5. package/dist/channels/deployments/deployments-channel.js +26 -2
  6. package/dist/channels/deployments/types.d.ts +8 -0
  7. package/dist/channels/deployments/types.d.ts.map +1 -1
  8. package/dist/channels/github/github-channel.d.ts +3 -0
  9. package/dist/channels/github/github-channel.d.ts.map +1 -1
  10. package/dist/channels/github/github-channel.js +28 -56
  11. package/dist/channels/slack/attachments.js +2 -2
  12. package/dist/channels/slack/dispatch.d.ts +0 -7
  13. package/dist/channels/slack/dispatch.d.ts.map +1 -1
  14. package/dist/channels/slack/dispatch.js +4 -7
  15. package/dist/channels/slack/eval-directive.d.ts +5 -12
  16. package/dist/channels/slack/eval-directive.d.ts.map +1 -1
  17. package/dist/channels/slack/eval-directive.js +8 -19
  18. package/dist/channels/slack/index.d.ts +0 -6
  19. package/dist/channels/slack/index.d.ts.map +1 -1
  20. package/dist/channels/slack/index.js +0 -6
  21. package/dist/channels/slack/setup.d.ts +4 -4
  22. package/dist/channels/slack/setup.d.ts.map +1 -1
  23. package/dist/channels/slack/setup.js +8 -15
  24. package/dist/channels/slack/slack-channel.d.ts +6 -13
  25. package/dist/channels/slack/slack-channel.d.ts.map +1 -1
  26. package/dist/channels/slack/slack-channel.js +15 -101
  27. package/dist/channels/slack/types.d.ts +12 -79
  28. package/dist/channels/slack/types.d.ts.map +1 -1
  29. package/dist/channels/slack/types.js +1 -15
  30. package/dist/client.d.ts +14 -0
  31. package/dist/client.d.ts.map +1 -0
  32. package/dist/client.js +12 -0
  33. package/dist/connections.d.ts +18 -9
  34. package/dist/connections.d.ts.map +1 -1
  35. package/dist/connections.js +17 -8
  36. package/dist/continuation.d.ts +1 -1
  37. package/dist/continuation.js +1 -1
  38. package/dist/docs/404.html +2 -2
  39. package/dist/docs/ab.html +8 -8
  40. package/dist/docs/ab.md +7 -13
  41. package/dist/docs/assets/{ab.md.CVzWxLoB.js → ab.md.DJo5r4R-.js} +4 -4
  42. package/dist/docs/assets/{ab.md.CVzWxLoB.lean.js → ab.md.DJo5r4R-.lean.js} +1 -1
  43. package/dist/docs/assets/{app.Bci6CM9E.js → app.CFDEas4I.js} +1 -1
  44. package/dist/docs/assets/building-with-agents.md.DI4mEzlt.js +13 -0
  45. package/dist/docs/assets/{building-with-agents.md.DH8A_cHA.lean.js → building-with-agents.md.DI4mEzlt.lean.js} +1 -1
  46. package/dist/docs/assets/chunks/@localSearchIndexroot.DU3U2Ij2.js +1 -0
  47. package/dist/docs/assets/chunks/{VPLocalSearchBox.BCPT6xA-.js → VPLocalSearchBox.B1IIYpYS.js} +1 -1
  48. package/dist/docs/assets/chunks/{theme.BEA8BF3c.js → theme.Ct4NSiLm.js} +2 -2
  49. package/dist/docs/assets/concepts.md.lwAgBIMI.js +1 -0
  50. package/dist/docs/assets/{concepts.md.CRfU3bVg.lean.js → concepts.md.lwAgBIMI.lean.js} +1 -1
  51. package/dist/docs/assets/{deployment.md.DX_hc3ze.js → deployment.md.D9msOFOW.js} +9 -14
  52. package/dist/docs/assets/{deployment.md.DX_hc3ze.lean.js → deployment.md.D9msOFOW.lean.js} +1 -1
  53. package/dist/docs/assets/{evals.md.a0SMN6r9.js → evals.md.lfJoEVc8.js} +6 -6
  54. package/dist/docs/assets/{evals.md.a0SMN6r9.lean.js → evals.md.lfJoEVc8.lean.js} +1 -1
  55. package/dist/docs/assets/{guides_agent-to-agent.md.BCeVdJRJ.js → guides_agent-to-agent.md.BDb0t1QV.js} +2 -2
  56. package/dist/docs/assets/guides_cloud-runtime.md.CkYbjnAX.js +9 -0
  57. package/dist/docs/assets/guides_cloud-runtime.md.CkYbjnAX.lean.js +1 -0
  58. package/dist/docs/assets/{guides_convert-automation.md.D06eIzea.js → guides_convert-automation.md.B4sjlodG.js} +2 -2
  59. package/dist/docs/assets/{guides_github.md.Cdt1s2QC.js → guides_github.md.Cnh2mL4a.js} +5 -5
  60. package/dist/docs/assets/{guides_github.md.Cdt1s2QC.lean.js → guides_github.md.Cnh2mL4a.lean.js} +1 -1
  61. package/dist/docs/assets/{guides_mcp-oauth.md.Du0f7pGU.js → guides_mcp-oauth.md.DPYmBCbV.js} +7 -9
  62. package/dist/docs/assets/{guides_mcp-oauth.md.Du0f7pGU.lean.js → guides_mcp-oauth.md.DPYmBCbV.lean.js} +1 -1
  63. package/dist/docs/assets/{guides_slack.md.DiUmk_Oi.js → guides_slack.md.C32HsdKk.js} +7 -13
  64. package/dist/docs/assets/guides_slack.md.C32HsdKk.lean.js +1 -0
  65. package/dist/docs/assets/{guides_webhooks.md.BpnIdO0i.js → guides_webhooks.md.DKdA43Qm.js} +2 -2
  66. package/dist/docs/assets/{hillclimbing.md.ywF3yDAd.js → hillclimbing.md.DhESf3OO.js} +1 -1
  67. package/dist/docs/assets/index.md.DRakGHFe.js +5 -0
  68. package/dist/docs/assets/{index.md.BAaMXLFd.lean.js → index.md.DRakGHFe.lean.js} +1 -1
  69. package/dist/docs/assets/{quickstart.md.DsrarzEg.js → quickstart.md.Nj_LjW_a.js} +2 -2
  70. package/dist/docs/assets/{reference_agent-config.md.Bqylgw50.js → reference_agent-config.md.Cp_x38Nl.js} +3 -3
  71. package/dist/docs/assets/{reference_channels.md.DQZjCnyh.js → reference_channels.md.Cd2f2iyV.js} +2 -2
  72. package/dist/docs/assets/{reference_channels.md.DQZjCnyh.lean.js → reference_channels.md.Cd2f2iyV.lean.js} +1 -1
  73. package/dist/docs/assets/{reference_cli.md.B7GkAJRC.js → reference_cli.md.Cw6_ICYG.js} +10 -11
  74. package/dist/docs/assets/{reference_cli.md.B7GkAJRC.lean.js → reference_cli.md.Cw6_ICYG.lean.js} +1 -1
  75. package/dist/docs/assets/{reference_connections.md.DYidrb-j.js → reference_connections.md.BH8Oc0D0.js} +7 -7
  76. package/dist/docs/assets/{reference_connections.md.DYidrb-j.lean.js → reference_connections.md.BH8Oc0D0.lean.js} +1 -1
  77. package/dist/docs/assets/reference_hooks.md.a8BJxMR5.js +14 -0
  78. package/dist/docs/assets/{reference_hooks.md.B9FSgdDe.lean.js → reference_hooks.md.a8BJxMR5.lean.js} +1 -1
  79. package/dist/docs/assets/reference_http-api.md.D89k1mdm.js +11 -0
  80. package/dist/docs/assets/reference_http-api.md.D89k1mdm.lean.js +1 -0
  81. package/dist/docs/assets/{reference_instructions.md.DhNCOl7r.js → reference_instructions.md.CR7XSsGk.js} +3 -3
  82. package/dist/docs/assets/{reference_instructions.md.DhNCOl7r.lean.js → reference_instructions.md.CR7XSsGk.lean.js} +1 -1
  83. package/dist/docs/assets/reference_playground.md.DnX5nL-B.js +1 -0
  84. package/dist/docs/assets/reference_playground.md.DnX5nL-B.lean.js +1 -0
  85. package/dist/docs/assets/reference_project-layout.md.Bv4KOtlB.js +19 -0
  86. package/dist/docs/assets/{reference_prompt.md.DZUMtLPD.js → reference_prompt.md.DnaD5dNK.js} +1 -1
  87. package/dist/docs/assets/{reference_schedules.md.DNipebiG.js → reference_schedules.md.DI_JrHgq.js} +1 -1
  88. package/dist/docs/assets/reference_sessions.md.D0mIh4KK.js +1 -0
  89. package/dist/docs/assets/{reference_sessions.md.tUFzz98S.lean.js → reference_sessions.md.D0mIh4KK.lean.js} +1 -1
  90. package/dist/docs/assets/{reference_skills.md.B5ZEuHfG.js → reference_skills.md.8son6Hjm.js} +4 -4
  91. package/dist/docs/assets/{reference_subagents.md.Xoav0AII.js → reference_subagents.md.CfsIloPm.js} +1 -1
  92. package/dist/docs/assets/{reference_tools.md.wpaJtHn6.js → reference_tools.md.BHeXn2id.js} +3 -3
  93. package/dist/docs/assets/{reference_tools.md.wpaJtHn6.lean.js → reference_tools.md.BHeXn2id.lean.js} +1 -1
  94. package/dist/docs/assets/scaffolding-agents.md.D7UUkWw0.js +1 -0
  95. package/dist/docs/assets/{scaffolding-agents.md.CRDDUtYJ.lean.js → scaffolding-agents.md.D7UUkWw0.lean.js} +1 -1
  96. package/dist/docs/assets/{storage.md.JbjlHWZ6.js → storage.md.BOHeqk2M.js} +5 -5
  97. package/dist/docs/assets/{storage.md.JbjlHWZ6.lean.js → storage.md.BOHeqk2M.lean.js} +1 -1
  98. package/dist/docs/assets/{templates_agentic-owners.md.DSJSIpWU.js → templates_agentic-owners.md.DqtPdm6f.js} +2 -2
  99. package/dist/docs/assets/{templates_pr-autofixer.md.1HAR3RXE.js → templates_pr-autofixer.md.DU7dQpor.js} +2 -2
  100. package/dist/docs/assets/{templates_pr-autofixer.md.1HAR3RXE.lean.js → templates_pr-autofixer.md.DU7dQpor.lean.js} +1 -1
  101. package/dist/docs/assets/{templates_security-reviewer.md.ByFyRta2.js → templates_security-reviewer.md.CTa7u_l1.js} +2 -2
  102. package/dist/docs/assets/{templates_security-reviewer.md.ByFyRta2.lean.js → templates_security-reviewer.md.CTa7u_l1.lean.js} +1 -1
  103. package/dist/docs/assets/troubleshooting.md.Ctv3T8C2.js +1 -0
  104. package/dist/docs/assets/{troubleshooting.md.DYECCZiJ.lean.js → troubleshooting.md.Ctv3T8C2.lean.js} +1 -1
  105. package/dist/docs/building-with-agents.html +7 -7
  106. package/dist/docs/building-with-agents.md +5 -11
  107. package/dist/docs/concepts.html +5 -8
  108. package/dist/docs/concepts.md +13 -17
  109. package/dist/docs/deployment.html +13 -18
  110. package/dist/docs/deployment.md +9 -30
  111. package/dist/docs/design/agsh.md +406 -0
  112. package/dist/docs/evals.html +10 -10
  113. package/dist/docs/evals.md +16 -37
  114. package/dist/docs/guides/agent-to-agent.html +6 -6
  115. package/dist/docs/guides/agent-to-agent.md +3 -3
  116. package/dist/docs/guides/cloud-runtime.html +6 -6
  117. package/dist/docs/guides/cloud-runtime.md +9 -25
  118. package/dist/docs/guides/convert-automation.html +7 -7
  119. package/dist/docs/guides/convert-automation.md +4 -4
  120. package/dist/docs/guides/github.html +9 -9
  121. package/dist/docs/guides/github.md +16 -28
  122. package/dist/docs/guides/human-in-the-loop.html +4 -4
  123. package/dist/docs/guides/mcp-oauth.html +11 -13
  124. package/dist/docs/guides/mcp-oauth.md +14 -22
  125. package/dist/docs/guides/opentelemetry.html +5 -5
  126. package/dist/docs/guides/slack.html +11 -17
  127. package/dist/docs/guides/slack.md +13 -50
  128. package/dist/docs/guides/webhooks.html +6 -6
  129. package/dist/docs/guides/webhooks.md +3 -3
  130. package/dist/docs/hashmap.json +1 -1
  131. package/dist/docs/hillclimbing.html +6 -6
  132. package/dist/docs/hillclimbing.md +1 -1
  133. package/dist/docs/index.html +6 -6
  134. package/dist/docs/index.md +0 -36
  135. package/dist/docs/llms-full.txt +965 -3633
  136. package/dist/docs/llms.txt +3 -18
  137. package/dist/docs/quickstart.html +6 -6
  138. package/dist/docs/quickstart.md +3 -4
  139. package/dist/docs/reference/agent-config.html +8 -8
  140. package/dist/docs/reference/agent-config.md +10 -15
  141. package/dist/docs/reference/artifacts.html +4 -4
  142. package/dist/docs/reference/channels.html +6 -6
  143. package/dist/docs/reference/channels.md +20 -31
  144. package/dist/docs/reference/cli.html +14 -15
  145. package/dist/docs/reference/cli.md +29 -38
  146. package/dist/docs/reference/connections.html +11 -11
  147. package/dist/docs/reference/connections.md +24 -25
  148. package/dist/docs/reference/hooks.html +6 -6
  149. package/dist/docs/reference/hooks.md +12 -17
  150. package/dist/docs/reference/http-api.html +7 -7
  151. package/dist/docs/reference/http-api.md +25 -37
  152. package/dist/docs/reference/instructions.html +6 -6
  153. package/dist/docs/reference/instructions.md +1 -1
  154. package/dist/docs/reference/playground.html +5 -5
  155. package/dist/docs/reference/playground.md +14 -19
  156. package/dist/docs/reference/project-layout.html +9 -7
  157. package/dist/docs/reference/project-layout.md +7 -3
  158. package/dist/docs/reference/prompt.html +6 -6
  159. package/dist/docs/reference/prompt.md +1 -1
  160. package/dist/docs/reference/schedules.html +6 -6
  161. package/dist/docs/reference/schedules.md +1 -2
  162. package/dist/docs/reference/sessions.html +5 -12
  163. package/dist/docs/reference/sessions.md +8 -19
  164. package/dist/docs/reference/skills.html +8 -8
  165. package/dist/docs/reference/skills.md +3 -3
  166. package/dist/docs/reference/subagents.html +6 -6
  167. package/dist/docs/reference/subagents.md +2 -2
  168. package/dist/docs/reference/tools.html +8 -8
  169. package/dist/docs/reference/tools.md +30 -19
  170. package/dist/docs/scaffolding-agents.html +5 -5
  171. package/dist/docs/scaffolding-agents.md +4 -5
  172. package/dist/docs/storage.html +9 -9
  173. package/dist/docs/storage.md +37 -80
  174. package/dist/docs/templates/agentic-owners.html +7 -7
  175. package/dist/docs/templates/agentic-owners.md +2 -2
  176. package/dist/docs/templates/demo.html +4 -4
  177. package/dist/docs/templates/pr-autofixer.html +6 -6
  178. package/dist/docs/templates/pr-autofixer.md +7 -9
  179. package/dist/docs/templates/security-reviewer.html +5 -5
  180. package/dist/docs/templates/security-reviewer.md +2 -3
  181. package/dist/docs/templates/triage.html +4 -4
  182. package/dist/docs/troubleshooting.html +5 -5
  183. package/dist/docs/troubleshooting.md +8 -8
  184. package/dist/index.d.ts +1 -1
  185. package/dist/index.d.ts.map +1 -1
  186. package/dist/index.js +1 -1
  187. package/dist/internal/advertise-tools.d.ts +11 -0
  188. package/dist/internal/advertise-tools.d.ts.map +1 -1
  189. package/dist/internal/advertise-tools.js +47 -9
  190. package/dist/internal/authored-alias-hooks.d.ts +14 -11
  191. package/dist/internal/authored-alias-hooks.d.ts.map +1 -1
  192. package/dist/internal/authored-alias-hooks.js +14 -11
  193. package/dist/internal/authored-loaders.d.ts +7 -6
  194. package/dist/internal/authored-loaders.d.ts.map +1 -1
  195. package/dist/internal/authored-loaders.js +14 -10
  196. package/dist/internal/cli-deploy.d.ts +1 -1
  197. package/dist/internal/cli-deploy.js +5 -5
  198. package/dist/internal/cli-mcp-oauth.d.ts.map +1 -1
  199. package/dist/internal/cli-mcp-oauth.js +7 -4
  200. package/dist/internal/continuation-channel.d.ts +6 -3
  201. package/dist/internal/continuation-channel.d.ts.map +1 -1
  202. package/dist/internal/continuation-channel.js +44 -40
  203. package/dist/internal/continuation-identity.d.ts +17 -16
  204. package/dist/internal/continuation-identity.d.ts.map +1 -1
  205. package/dist/internal/continuation-identity.js +109 -36
  206. package/dist/internal/convert-automation/convert-workflow.d.ts.map +1 -1
  207. package/dist/internal/convert-automation/convert-workflow.js +26 -15
  208. package/dist/internal/convert-automation/slug.d.ts +0 -2
  209. package/dist/internal/convert-automation/slug.d.ts.map +1 -1
  210. package/dist/internal/convert-automation/slug.js +0 -8
  211. package/dist/internal/cursor/account-mcp.d.ts.map +1 -1
  212. package/dist/internal/cursor/account-mcp.js +5 -1
  213. package/dist/internal/deploy-manifest.d.ts +2 -2
  214. package/dist/internal/deploy-manifest.d.ts.map +1 -1
  215. package/dist/internal/deploy-manifest.js +4 -9
  216. package/dist/internal/discovery.d.ts.map +1 -1
  217. package/dist/internal/discovery.js +91 -13
  218. package/dist/internal/distribution.d.ts +4 -3
  219. package/dist/internal/distribution.d.ts.map +1 -1
  220. package/dist/internal/distribution.js +4 -3
  221. package/dist/internal/hosted-delivery-protocol.d.ts +38 -0
  222. package/dist/internal/hosted-delivery-protocol.d.ts.map +1 -0
  223. package/dist/internal/hosted-delivery-protocol.js +70 -0
  224. package/dist/internal/hosted-delivery.d.ts +35 -0
  225. package/dist/internal/hosted-delivery.d.ts.map +1 -0
  226. package/dist/internal/hosted-delivery.js +239 -0
  227. package/dist/internal/http-channel.d.ts.map +1 -1
  228. package/dist/internal/http-channel.js +1 -1
  229. package/dist/internal/mcp-endpoint.js +3 -3
  230. package/dist/internal/mcp-host.d.ts +8 -7
  231. package/dist/internal/mcp-host.d.ts.map +1 -1
  232. package/dist/internal/mcp-host.js +8 -7
  233. package/dist/internal/peer-connections.d.ts.map +1 -1
  234. package/dist/internal/peer-connections.js +5 -1
  235. package/dist/internal/playground/static.d.ts +0 -3
  236. package/dist/internal/playground/static.d.ts.map +1 -1
  237. package/dist/internal/resolved-connections.d.ts.map +1 -1
  238. package/dist/internal/resolved-connections.js +5 -7
  239. package/dist/internal/review-comments.d.ts +186 -63
  240. package/dist/internal/review-comments.d.ts.map +1 -1
  241. package/dist/internal/review-comments.js +350 -168
  242. package/dist/internal/server.d.ts.map +1 -1
  243. package/dist/internal/server.js +134 -175
  244. package/dist/internal/session-engine.d.ts +50 -10
  245. package/dist/internal/session-engine.d.ts.map +1 -1
  246. package/dist/internal/session-engine.js +221 -68
  247. package/dist/internal/shallow-clone.d.ts +8 -2
  248. package/dist/internal/shallow-clone.d.ts.map +1 -1
  249. package/dist/internal/shallow-clone.js +17 -10
  250. package/dist/internal/tool-catalog.d.ts +31 -0
  251. package/dist/internal/tool-catalog.d.ts.map +1 -0
  252. package/dist/internal/tool-catalog.js +67 -0
  253. package/dist/playground/assets/{index-DDvyC2z6.js → index-B3JCyigB.js} +2 -2
  254. package/dist/playground/index.html +1 -1
  255. package/dist/types.d.ts +81 -40
  256. package/dist/types.d.ts.map +1 -1
  257. package/dist/types.js +19 -0
  258. package/docs/README.md +0 -36
  259. package/docs/ab.md +7 -13
  260. package/docs/building-with-agents.md +5 -11
  261. package/docs/concepts.md +13 -17
  262. package/docs/deployment.md +9 -30
  263. package/docs/design/agsh.md +406 -0
  264. package/docs/evals.md +16 -37
  265. package/docs/guides/agent-to-agent.md +3 -3
  266. package/docs/guides/cloud-runtime.md +9 -25
  267. package/docs/guides/convert-automation.md +4 -4
  268. package/docs/guides/github.md +16 -28
  269. package/docs/guides/mcp-oauth.md +14 -22
  270. package/docs/guides/slack.md +14 -51
  271. package/docs/guides/webhooks.md +3 -3
  272. package/docs/hillclimbing.md +1 -1
  273. package/docs/quickstart.md +3 -4
  274. package/docs/reference/agent-config.md +10 -15
  275. package/docs/reference/channels.md +20 -31
  276. package/docs/reference/cli.md +29 -38
  277. package/docs/reference/connections.md +24 -25
  278. package/docs/reference/hooks.md +12 -17
  279. package/docs/reference/http-api.md +26 -38
  280. package/docs/reference/instructions.md +1 -1
  281. package/docs/reference/playground.md +14 -19
  282. package/docs/reference/project-layout.md +7 -3
  283. package/docs/reference/prompt.md +1 -1
  284. package/docs/reference/schedules.md +1 -2
  285. package/docs/reference/sessions.md +8 -19
  286. package/docs/reference/skills.md +3 -3
  287. package/docs/reference/subagents.md +2 -2
  288. package/docs/reference/tools.md +30 -19
  289. package/docs/scaffolding-agents.md +4 -5
  290. package/docs/storage.md +37 -80
  291. package/docs/templates/agentic-owners.md +2 -2
  292. package/docs/templates/pr-autofixer.md +7 -9
  293. package/docs/templates/security-reviewer.md +2 -3
  294. package/docs/troubleshooting.md +8 -8
  295. package/package.json +16 -2
  296. package/skills/create-agent/SKILL.md +6 -13
  297. package/skills/debug/SKILL.md +2 -4
  298. package/skills/evals/SKILL.md +1 -1
  299. package/skills/framework-map/SKILL.md +3 -2
  300. package/skills/mcp-auth/SKILL.md +10 -13
  301. package/skills/setup-slack/SKILL.md +21 -137
  302. package/src/channels/deployments/deployments-channel.ts +32 -2
  303. package/src/channels/deployments/types.ts +8 -0
  304. package/src/channels/github/github-channel.ts +71 -21
  305. package/src/channels/slack/attachments.ts +2 -2
  306. package/src/channels/slack/dispatch.ts +2 -16
  307. package/src/channels/slack/eval-directive.ts +8 -27
  308. package/src/channels/slack/index.ts +0 -6
  309. package/src/channels/slack/setup.ts +8 -15
  310. package/src/channels/slack/slack-channel.ts +14 -125
  311. package/src/channels/slack/types.ts +12 -96
  312. package/src/client.ts +23 -0
  313. package/src/connections.ts +20 -7
  314. package/src/continuation.ts +1 -1
  315. package/src/index.ts +2 -0
  316. package/src/internal/advertise-tools.ts +45 -7
  317. package/src/internal/authored-alias-hooks.ts +14 -11
  318. package/src/internal/authored-loaders.ts +14 -10
  319. package/src/internal/cli-deploy.ts +5 -5
  320. package/src/internal/cli-mcp-oauth.ts +6 -4
  321. package/src/internal/continuation-channel.ts +62 -45
  322. package/src/internal/continuation-identity.ts +123 -38
  323. package/src/internal/convert-automation/convert-workflow.ts +29 -17
  324. package/src/internal/convert-automation/slug.ts +0 -9
  325. package/src/internal/cursor/account-mcp.ts +4 -1
  326. package/src/internal/deploy-manifest.ts +5 -9
  327. package/src/internal/discovery.ts +107 -13
  328. package/src/internal/distribution.ts +4 -3
  329. package/src/internal/fixtures/units-server.ts +52 -0
  330. package/src/internal/hosted-delivery-protocol.ts +114 -0
  331. package/src/internal/hosted-delivery.ts +359 -0
  332. package/src/internal/http-channel.ts +0 -2
  333. package/src/internal/mcp-endpoint.ts +3 -3
  334. package/src/internal/mcp-host.ts +8 -7
  335. package/src/internal/peer-connections.ts +4 -1
  336. package/src/internal/playground/static.ts +1 -3
  337. package/src/internal/resolved-connections.ts +8 -10
  338. package/src/internal/review-comments.ts +542 -229
  339. package/src/internal/server.ts +180 -253
  340. package/src/internal/session-engine.ts +279 -70
  341. package/src/internal/shallow-clone.ts +30 -16
  342. package/src/internal/tool-catalog.ts +106 -0
  343. package/src/types.ts +99 -40
  344. package/templates/pr-autofixer/agent/channels/slack.ts +8 -2
  345. package/templates/triage/README.md +2 -1
  346. package/templates/triage/overlays/jira/agent/mcp-connections/tracker.ts +0 -1
  347. package/templates/triage/overlays/linear/agent/mcp-connections/tracker.ts +0 -1
  348. package/dist/channels/slack/cursor-account.d.ts +0 -87
  349. package/dist/channels/slack/cursor-account.d.ts.map +0 -1
  350. package/dist/channels/slack/cursor-account.js +0 -100
  351. package/dist/docs/assets/building-with-agents.md.DH8A_cHA.js +0 -13
  352. package/dist/docs/assets/chunks/@localSearchIndexroot.Dv-Q0XtU.js +0 -1
  353. package/dist/docs/assets/concepts.md.CRfU3bVg.js +0 -4
  354. package/dist/docs/assets/example-agents_approval-buddy.md.DNL83puR.js +0 -10
  355. package/dist/docs/assets/example-agents_approval-buddy.md.DNL83puR.lean.js +0 -1
  356. package/dist/docs/assets/example-agents_benny.md.C40vHRLc.js +0 -7
  357. package/dist/docs/assets/example-agents_benny.md.C40vHRLc.lean.js +0 -1
  358. package/dist/docs/assets/example-agents_bugbot.md.BRGMi9O2.js +0 -11
  359. package/dist/docs/assets/example-agents_bugbot.md.BRGMi9O2.lean.js +0 -1
  360. package/dist/docs/assets/example-agents_codebase-wiki.md.Dftj_tPp.js +0 -8
  361. package/dist/docs/assets/example-agents_codebase-wiki.md.Dftj_tPp.lean.js +0 -1
  362. package/dist/docs/assets/example-agents_codeowners-review.md.Bfta-lBU.js +0 -8
  363. package/dist/docs/assets/example-agents_codeowners-review.md.Bfta-lBU.lean.js +0 -1
  364. package/dist/docs/assets/example-agents_concierge.md.MrKpQndp.js +0 -23
  365. package/dist/docs/assets/example-agents_concierge.md.MrKpQndp.lean.js +0 -1
  366. package/dist/docs/assets/example-agents_fsd.md.ZWHWWZPE.js +0 -15
  367. package/dist/docs/assets/example-agents_fsd.md.ZWHWWZPE.lean.js +0 -1
  368. package/dist/docs/assets/example-agents_index.md.QZ8mhr6n.js +0 -2
  369. package/dist/docs/assets/example-agents_index.md.QZ8mhr6n.lean.js +0 -1
  370. package/dist/docs/assets/example-agents_knowledge-base.md.DqKqHQ9u.js +0 -11
  371. package/dist/docs/assets/example-agents_knowledge-base.md.DqKqHQ9u.lean.js +0 -1
  372. package/dist/docs/assets/example-agents_oncall.md.DK4XkYTd.js +0 -10
  373. package/dist/docs/assets/example-agents_oncall.md.DK4XkYTd.lean.js +0 -1
  374. package/dist/docs/assets/example-agents_security-reviewer.md.Bai6D0Ee.js +0 -19
  375. package/dist/docs/assets/example-agents_security-reviewer.md.Bai6D0Ee.lean.js +0 -1
  376. package/dist/docs/assets/example-agents_slack-agent.md.D7Kdj5BV.js +0 -5
  377. package/dist/docs/assets/example-agents_slack-agent.md.D7Kdj5BV.lean.js +0 -1
  378. package/dist/docs/assets/example-agents_weather-agent.md.lVEAbWFf.js +0 -25
  379. package/dist/docs/assets/example-agents_weather-agent.md.lVEAbWFf.lean.js +0 -1
  380. package/dist/docs/assets/guides_cloud-runtime.md.BSMLIBHr.js +0 -9
  381. package/dist/docs/assets/guides_cloud-runtime.md.BSMLIBHr.lean.js +0 -1
  382. package/dist/docs/assets/guides_slack.md.DiUmk_Oi.lean.js +0 -1
  383. package/dist/docs/assets/index.md.BAaMXLFd.js +0 -5
  384. package/dist/docs/assets/reference_hooks.md.B9FSgdDe.js +0 -14
  385. package/dist/docs/assets/reference_http-api.md.CSHVobzG.js +0 -11
  386. package/dist/docs/assets/reference_http-api.md.CSHVobzG.lean.js +0 -1
  387. package/dist/docs/assets/reference_playground.md.Dfb92yQf.js +0 -1
  388. package/dist/docs/assets/reference_playground.md.Dfb92yQf.lean.js +0 -1
  389. package/dist/docs/assets/reference_project-layout.md.CwkSbEWT.js +0 -17
  390. package/dist/docs/assets/reference_sessions.md.tUFzz98S.js +0 -8
  391. package/dist/docs/assets/scaffolding-agents.md.CRDDUtYJ.js +0 -1
  392. package/dist/docs/assets/troubleshooting.md.DYECCZiJ.js +0 -1
  393. package/dist/docs/example-agents/approval-buddy.html +0 -36
  394. package/dist/docs/example-agents/approval-buddy.md +0 -266
  395. package/dist/docs/example-agents/benny.html +0 -33
  396. package/dist/docs/example-agents/benny.md +0 -182
  397. package/dist/docs/example-agents/bugbot.html +0 -37
  398. package/dist/docs/example-agents/bugbot.md +0 -229
  399. package/dist/docs/example-agents/codebase-wiki.html +0 -34
  400. package/dist/docs/example-agents/codebase-wiki.md +0 -170
  401. package/dist/docs/example-agents/codeowners-review.html +0 -34
  402. package/dist/docs/example-agents/codeowners-review.md +0 -192
  403. package/dist/docs/example-agents/concierge.html +0 -49
  404. package/dist/docs/example-agents/concierge.md +0 -201
  405. package/dist/docs/example-agents/fsd.html +0 -41
  406. package/dist/docs/example-agents/fsd.md +0 -329
  407. package/dist/docs/example-agents/index.html +0 -28
  408. package/dist/docs/example-agents/index.md +0 -102
  409. package/dist/docs/example-agents/knowledge-base.html +0 -37
  410. package/dist/docs/example-agents/knowledge-base.md +0 -168
  411. package/dist/docs/example-agents/oncall.html +0 -36
  412. package/dist/docs/example-agents/oncall.md +0 -212
  413. package/dist/docs/example-agents/security-reviewer.html +0 -45
  414. package/dist/docs/example-agents/security-reviewer.md +0 -265
  415. package/dist/docs/example-agents/slack-agent.html +0 -31
  416. package/dist/docs/example-agents/slack-agent.md +0 -142
  417. package/dist/docs/example-agents/weather-agent.html +0 -51
  418. package/dist/docs/example-agents/weather-agent.md +0 -296
  419. package/dist/internal/cursor-slack-relay.d.ts +0 -96
  420. package/dist/internal/cursor-slack-relay.d.ts.map +0 -1
  421. package/dist/internal/cursor-slack-relay.js +0 -176
  422. package/docs/example-agents/approval-buddy.md +0 -271
  423. package/docs/example-agents/benny.md +0 -187
  424. package/docs/example-agents/bugbot.md +0 -234
  425. package/docs/example-agents/codebase-wiki.md +0 -175
  426. package/docs/example-agents/codeowners-review.md +0 -197
  427. package/docs/example-agents/concierge.md +0 -206
  428. package/docs/example-agents/fsd.md +0 -334
  429. package/docs/example-agents/index.md +0 -107
  430. package/docs/example-agents/knowledge-base.md +0 -173
  431. package/docs/example-agents/oncall.md +0 -217
  432. package/docs/example-agents/security-reviewer.md +0 -270
  433. package/docs/example-agents/slack-agent.md +0 -147
  434. package/docs/example-agents/weather-agent.md +0 -301
  435. package/src/channels/slack/cursor-account.ts +0 -202
  436. package/src/internal/cursor-slack-relay.ts +0 -249
  437. /package/dist/docs/assets/{guides_agent-to-agent.md.BCeVdJRJ.lean.js → guides_agent-to-agent.md.BDb0t1QV.lean.js} +0 -0
  438. /package/dist/docs/assets/{guides_convert-automation.md.D06eIzea.lean.js → guides_convert-automation.md.B4sjlodG.lean.js} +0 -0
  439. /package/dist/docs/assets/{guides_webhooks.md.BpnIdO0i.lean.js → guides_webhooks.md.DKdA43Qm.lean.js} +0 -0
  440. /package/dist/docs/assets/{hillclimbing.md.ywF3yDAd.lean.js → hillclimbing.md.DhESf3OO.lean.js} +0 -0
  441. /package/dist/docs/assets/{quickstart.md.DsrarzEg.lean.js → quickstart.md.Nj_LjW_a.lean.js} +0 -0
  442. /package/dist/docs/assets/{reference_agent-config.md.Bqylgw50.lean.js → reference_agent-config.md.Cp_x38Nl.lean.js} +0 -0
  443. /package/dist/docs/assets/{reference_project-layout.md.CwkSbEWT.lean.js → reference_project-layout.md.Bv4KOtlB.lean.js} +0 -0
  444. /package/dist/docs/assets/{reference_prompt.md.DZUMtLPD.lean.js → reference_prompt.md.DnaD5dNK.lean.js} +0 -0
  445. /package/dist/docs/assets/{reference_schedules.md.DNipebiG.lean.js → reference_schedules.md.DI_JrHgq.lean.js} +0 -0
  446. /package/dist/docs/assets/{reference_skills.md.B5ZEuHfG.lean.js → reference_skills.md.8son6Hjm.lean.js} +0 -0
  447. /package/dist/docs/assets/{reference_subagents.md.Xoav0AII.lean.js → reference_subagents.md.CfsIloPm.lean.js} +0 -0
  448. /package/dist/docs/assets/{templates_agentic-owners.md.DSJSIpWU.lean.js → templates_agentic-owners.md.DqtPdm6f.lean.js} +0 -0
@@ -49,6 +49,7 @@ import {
49
49
  type ConnectionTransport,
50
50
  DEFAULT_MODEL,
51
51
  DIRECT_TOOL_CALL_CHANNEL_ID,
52
+ type DiscoveredTool,
52
53
  type HookHandler,
53
54
  type HostContext,
54
55
  type HttpChannelDefinition,
@@ -117,6 +118,7 @@ import {
117
118
  newContinuationKey,
118
119
  newSessionId,
119
120
  newToolCallId,
121
+ parseContinuationToken,
120
122
  } from "./ids.js";
121
123
  import { validateToolInput } from "./json-schema.js";
122
124
  import { McpHost } from "./mcp-host.js";
@@ -136,7 +138,7 @@ import { SessionStore } from "./session-store.js";
136
138
  import { syncSkillsToStore } from "./skills-sync.js";
137
139
  import { StorageCoordinator } from "./storage-coordinator.js";
138
140
  import type { FrameworkSessionStore } from "./storage-roles.js";
139
- import { decideToolCall } from "./tool-policy.js";
141
+ import { decideToolCall, resolveEffect } from "./tool-policy.js";
140
142
  import { normalizeToolResult, toolCallErrorMessage } from "./tool-result.js";
141
143
  import {
142
144
  type EstimateTurnCostFn,
@@ -197,6 +199,30 @@ export class ToolNotDirectlyCallableError extends Error {
197
199
  }
198
200
  }
199
201
 
202
+ export class InvalidContinuationTokenError extends Error {
203
+ constructor(detail: string) {
204
+ super(`Invalid continuation token: ${detail}`);
205
+ this.name = "InvalidContinuationTokenError";
206
+ }
207
+ }
208
+
209
+ /**
210
+ * A session-bound direct call whose harness cwd cannot be materialized and
211
+ * whose effect is not read: a write tool may rely on ctx.workspaceDir being
212
+ * the real session workspace, so it fails typed instead of silently running
213
+ * in a scratch directory.
214
+ */
215
+ export class WorkspaceUnavailableError extends Error {
216
+ constructor(toolName: string, cause: unknown) {
217
+ super(
218
+ `Session workspace unavailable for tool "${toolName}": ${
219
+ cause instanceof Error ? cause.message : String(cause)
220
+ }`
221
+ );
222
+ this.name = "WorkspaceUnavailableError";
223
+ }
224
+ }
225
+
200
226
  export class ToolInputError extends Error {
201
227
  constructor(args: { toolName: string; detail: string }) {
202
228
  super(`Invalid input for tool "${args.toolName}": ${args.detail}`);
@@ -283,6 +309,11 @@ interface ActiveToolContext {
283
309
 
284
310
  export interface EngineSendOptions extends SendMessageOptions {
285
311
  mode?: "chat" | "task";
312
+ /**
313
+ * Hosted v2 control-plane identity. Private host plumbing only: channel
314
+ * authors cannot choose a session id through the public SendMessageOptions.
315
+ */
316
+ hostedSessionId?: string;
286
317
  }
287
318
 
288
319
  interface CoalescedQueuedTurn {
@@ -469,7 +500,10 @@ export class SessionEngine {
469
500
  // resolves them; the host-side MCP registry starts with the concrete
470
501
  // connections and gains the rest via setResolvedConnections.
471
502
  this.mcpHost = new McpHost(
472
- options.project.agent.connections.filter(
503
+ [
504
+ ...options.project.agent.connections,
505
+ ...(options.project.agent.hostConnections ?? []),
506
+ ].filter(
473
507
  (connection) => !isSymbolicConnectionTransport(connection.transport)
474
508
  )
475
509
  );
@@ -816,6 +850,14 @@ export class SessionEngine {
816
850
  }
817
851
 
818
852
  if (existing !== undefined) {
853
+ if (
854
+ sendOptions.hostedSessionId !== undefined &&
855
+ existing.sessionId !== sendOptions.hostedSessionId
856
+ ) {
857
+ throw new V2EngineError(
858
+ `v2: continuation belongs to session ${existing.sessionId}, not ${sendOptions.hostedSessionId}`
859
+ );
860
+ }
819
861
  if (!samePrincipal(existing.auth, auth)) {
820
862
  throw new SessionAuthError(existing.sessionId);
821
863
  }
@@ -886,11 +928,22 @@ export class SessionEngine {
886
928
  );
887
929
  }
888
930
 
931
+ if (sendOptions.hostedSessionId !== undefined) {
932
+ const collision = await this.getOrRestoreSession(
933
+ sendOptions.hostedSessionId
934
+ );
935
+ if (collision !== undefined) {
936
+ throw new V2EngineError(
937
+ `v2: hosted session id ${sendOptions.hostedSessionId} already belongs to another mailbox`
938
+ );
939
+ }
940
+ }
941
+
889
942
  const now = new Date().toISOString();
890
943
  const channelState = this.initialChannelState(channelId, sendOptions.state);
891
944
  const purpose = sendOptions.purpose === "eval" ? "eval" : "live";
892
945
  let record: SessionRecord = {
893
- sessionId: newSessionId(),
946
+ sessionId: sendOptions.hostedSessionId ?? newSessionId(),
894
947
  channelId,
895
948
  mode: sendOptions.mode ?? "chat",
896
949
  purpose,
@@ -2124,27 +2177,17 @@ export class SessionEngine {
2124
2177
  * Connection names a cloud turn can only reach through the host connection
2125
2178
  * bridge on the tool MCP endpoint: filtered account connections without a
2126
2179
  * public bridge URL, and host-OAuth connections whose tokens live on this
2127
- * host. `hostOnly` names are never bridged — that flag means the model
2128
- * must not see the connection at all, on any runtime.
2180
+ * host.
2129
2181
  */
2130
2182
  cloudBridgeableConnectionNames(): string[] {
2131
- const hostOnlyNames = new Set(
2132
- this.project.agent.connections
2133
- .filter((connection) => connection.hostOnly === true)
2134
- .map((connection) => connection.name)
2135
- );
2136
2183
  const names: string[] = [];
2137
2184
  for (const connection of this.project.agent.connections) {
2138
- if (
2139
- !hostOnlyNames.has(connection.name) &&
2140
- isHostOauthConnectionTransport(connection.transport)
2141
- ) {
2185
+ if (isHostOauthConnectionTransport(connection.transport)) {
2142
2186
  names.push(connection.name);
2143
2187
  }
2144
2188
  }
2145
2189
  for (const resolved of this.resolvedConnections) {
2146
2190
  if (
2147
- !hostOnlyNames.has(resolved.name) &&
2148
2191
  resolved.accountServersFilter !== undefined &&
2149
2192
  resolved.cloudUrl === undefined
2150
2193
  ) {
@@ -2157,8 +2200,7 @@ export class SessionEngine {
2157
2200
  /**
2158
2201
  * True when cloud turns reach `name` through the host connection bridge —
2159
2202
  * the gate the tool MCP endpoint applies before forwarding a bridge
2160
- * request to `host.mcp`, so `hostOnly` connections (and arbitrary names)
2161
- * stay unreachable from a VM.
2203
+ * request to `host.mcp`, so arbitrary names stay unreachable from a VM.
2162
2204
  */
2163
2205
  isCloudBridgedConnection(name: string): boolean {
2164
2206
  if (this.cloudServerToolsConnection === undefined) {
@@ -2188,10 +2230,11 @@ export class SessionEngine {
2188
2230
  }
2189
2231
 
2190
2232
  /**
2191
- * Authored + resolved MCP servers for a turn. Skips `hostOnly`. On cloud
2192
- * turns, connections whose credential lives on this host filtered
2193
- * account connections without a public bridge URL, host-OAuth servers
2194
- * mount as host connection bridges over the tool MCP endpoint instead of
2233
+ * Authored + resolved MCP servers for a turn. Skips advertised
2234
+ * connections (those surface as named server tools). On cloud turns,
2235
+ * connections whose credential lives on this host filtered account
2236
+ * connections without a public bridge URL, host-OAuth servers mount
2237
+ * as host connection bridges over the tool MCP endpoint instead of
2195
2238
  * being omitted or failing the turn closed.
2196
2239
  */
2197
2240
  private buildMcpServers(
@@ -2205,16 +2248,17 @@ export class SessionEngine {
2205
2248
  return {};
2206
2249
  }
2207
2250
  // Advertised connections surface as named server tools instead of an
2208
- // attached MCP server (each tool appears exactly once), so they are
2209
- // excluded here alongside hostOnly.
2210
- const hostOnlyNames = new Set(
2251
+ // attached MCP server (each tool appears exactly once).
2252
+ const advertisedNames = new Set(
2211
2253
  this.project.agent.connections
2212
- .filter(
2213
- (connection) =>
2214
- connection.hostOnly === true || connection.advertiseTools === true
2215
- )
2254
+ .filter((connection) => connection.advertiseTools === true)
2216
2255
  .map((connection) => connection.name)
2217
2256
  );
2257
+ const hostConnectionNames = new Set(
2258
+ (this.project.agent.hostConnections ?? []).map(
2259
+ (connection) => connection.name
2260
+ )
2261
+ );
2218
2262
  const bridgedNames = new Set(
2219
2263
  runtime === "cloud" &&
2220
2264
  sessionId !== undefined &&
@@ -2226,7 +2270,9 @@ export class SessionEngine {
2226
2270
  assertCloudCanHonorAccountServersFilters({
2227
2271
  runtime,
2228
2272
  resolvedConnections: this.resolvedConnections.filter(
2229
- (resolved) => !hostOnlyNames.has(resolved.name)
2273
+ (resolved) =>
2274
+ !advertisedNames.has(resolved.name) &&
2275
+ !hostConnectionNames.has(resolved.name)
2230
2276
  ),
2231
2277
  bridgedNames,
2232
2278
  });
@@ -2236,7 +2282,10 @@ export class SessionEngine {
2236
2282
  : this.cloudBridgeTransport(sessionId, name);
2237
2283
  const servers: Record<string, ConnectionTransport> = {};
2238
2284
  for (const connection of this.project.agent.connections) {
2239
- if (hostOnlyNames.has(connection.name)) {
2285
+ if (
2286
+ advertisedNames.has(connection.name) ||
2287
+ hostConnectionNames.has(connection.name)
2288
+ ) {
2240
2289
  continue;
2241
2290
  }
2242
2291
  if (isSymbolicConnectionTransport(connection.transport)) {
@@ -2277,7 +2326,10 @@ export class SessionEngine {
2277
2326
  servers[connection.name] = connection.transport;
2278
2327
  }
2279
2328
  for (const resolved of this.resolvedConnections) {
2280
- if (hostOnlyNames.has(resolved.name)) {
2329
+ if (
2330
+ advertisedNames.has(resolved.name) ||
2331
+ hostConnectionNames.has(resolved.name)
2332
+ ) {
2281
2333
  continue;
2282
2334
  }
2283
2335
  const url = runtime === "cloud" ? resolved.cloudUrl : resolved.localUrl;
@@ -2322,16 +2374,14 @@ export class SessionEngine {
2322
2374
 
2323
2375
  /**
2324
2376
  * True when a connection with per-session `auth` attaches to the model
2325
- * (not `hostOnly`, not advertised). These turns set
2377
+ * (not advertised). These turns set
2326
2378
  * {@link RunnerTurnRequest.perSendMcpServers} so the evaluated headers
2327
2379
  * ride every send instead of being pinned on the cached agent handle.
2328
2380
  */
2329
2381
  private hasAttachedAuthedConnections(): boolean {
2330
2382
  return this.project.agent.connections.some(
2331
2383
  (connection) =>
2332
- connection.auth !== undefined &&
2333
- connection.hostOnly !== true &&
2334
- connection.advertiseTools !== true
2384
+ connection.auth !== undefined && connection.advertiseTools !== true
2335
2385
  );
2336
2386
  }
2337
2387
 
@@ -2347,9 +2397,7 @@ export class SessionEngine {
2347
2397
  ): Promise<ReadonlyMap<string, Record<string, string>> | undefined> {
2348
2398
  const authed = this.project.agent.connections.filter(
2349
2399
  (connection) =>
2350
- connection.auth !== undefined &&
2351
- connection.hostOnly !== true &&
2352
- connection.advertiseTools !== true
2400
+ connection.auth !== undefined && connection.advertiseTools !== true
2353
2401
  );
2354
2402
  if (authed.length === 0) {
2355
2403
  return undefined;
@@ -2759,12 +2807,168 @@ export class SessionEngine {
2759
2807
  * with the same `{ content, isError }` envelope the model would see, not
2760
2808
  * an exception.
2761
2809
  */
2810
+ /**
2811
+ * The session identity a direct call (or catalog listing) runs under:
2812
+ * an explicit sessionId, a continuation token resolved to a live (or
2813
+ * restorable) session with the same owner/busy checks a sessionId call
2814
+ * gets, or — when neither maps to a session — a synthetic identity
2815
+ * carrying the token's channel id and continuation key so binding
2816
+ * resolvers (e.g. VFS mounts) can still serve the call.
2817
+ */
2818
+ private async resolveDirectCallIdentity(
2819
+ callId: string,
2820
+ options: Pick<CallToolOptions, "auth" | "sessionId" | "continuationToken">
2821
+ ): Promise<{
2822
+ record: SessionRecord | undefined;
2823
+ session: SessionInfo;
2824
+ workspaceDir: string;
2825
+ scratchDir: string | undefined;
2826
+ }> {
2827
+ if (
2828
+ options.sessionId !== undefined &&
2829
+ options.continuationToken !== undefined
2830
+ ) {
2831
+ throw new InvalidContinuationTokenError(
2832
+ "mutually exclusive with sessionId — a real session already carries its own continuation key"
2833
+ );
2834
+ }
2835
+ const auth = options.auth ?? null;
2836
+ let record: SessionRecord | undefined;
2837
+ let continuation: { channelId: string; key: string } | null = null;
2838
+ if (options.sessionId !== undefined) {
2839
+ record = await this.sessions.get(options.sessionId);
2840
+ if (record === undefined) {
2841
+ throw new UnknownSessionError(options.sessionId);
2842
+ }
2843
+ } else if (options.continuationToken !== undefined) {
2844
+ continuation = parseContinuationToken(options.continuationToken);
2845
+ if (continuation === null) {
2846
+ throw new InvalidContinuationTokenError(
2847
+ `expected "<channelId>:<key>" (as /v1/sessions lists it), got "${options.continuationToken}"`
2848
+ );
2849
+ }
2850
+ // A token that maps to a live (or restorable) session takes the
2851
+ // session path: same owner check, same turn serialization, same
2852
+ // event recording as an explicit sessionId. Skipping those just
2853
+ // because the caller addressed the session by token would fail open.
2854
+ record =
2855
+ (await this.sessions.findByContinuation(
2856
+ continuation.channelId,
2857
+ continuation.key
2858
+ )) ??
2859
+ (await this.restoreSessionByContinuation(
2860
+ continuation.channelId,
2861
+ continuation.key
2862
+ ));
2863
+ if (record !== undefined && !samePrincipal(record.auth, auth)) {
2864
+ throw new SessionAuthError(record.sessionId);
2865
+ }
2866
+ }
2867
+ if (record !== undefined) {
2868
+ // Direct calls respect the same serialization as follow-up sends: a
2869
+ // running model turn owns the session workspace and event stream.
2870
+ if (
2871
+ this.activeTurns.has(record.sessionId) ||
2872
+ this.pendingTurns.has(record.sessionId)
2873
+ ) {
2874
+ throw new SessionBusyError(record.sessionId);
2875
+ }
2876
+ return {
2877
+ record,
2878
+ session: this.sessionInfo(record),
2879
+ workspaceDir: this.harnessCwd(record),
2880
+ scratchDir: undefined,
2881
+ };
2882
+ }
2883
+ // No session behind the token (or no token at all): a synthetic
2884
+ // session carries the token's channel id and key, so binding resolvers
2885
+ // keyed on the continuation key (e.g. VFS mounts) can serve the call
2886
+ // with no live session. The workspace stays scratch and nothing is
2887
+ // recorded on a session event stream.
2888
+ const scratchDir = join(this.stateRoot, "tool-calls", callId);
2889
+ return {
2890
+ record: undefined,
2891
+ session: {
2892
+ id: callId,
2893
+ channelId: continuation?.channelId ?? DIRECT_TOOL_CALL_CHANNEL_ID,
2894
+ mode: "task",
2895
+ continuationKey: continuation?.key,
2896
+ auth,
2897
+ },
2898
+ workspaceDir: scratchDir,
2899
+ scratchDir,
2900
+ };
2901
+ }
2902
+
2903
+ /**
2904
+ * The live tool catalog for one session identity: authored server tools
2905
+ * plus the advertised passthroughs a turn under the same identity would
2906
+ * see, under their model-facing names. A connection whose listing fails
2907
+ * is skipped and reported in `connectionErrors` — the inspection surface
2908
+ * degrades legibly instead of hiding every other tool behind one broken
2909
+ * connector.
2910
+ */
2911
+ async listCatalogTools(
2912
+ options: Pick<
2913
+ CallToolOptions,
2914
+ "auth" | "sessionId" | "continuationToken"
2915
+ > = {}
2916
+ ): Promise<{
2917
+ tools: DiscoveredTool[];
2918
+ connectionErrors: Array<{ connection: string; message: string }>;
2919
+ }> {
2920
+ const { session } = await this.resolveDirectCallIdentity(
2921
+ newToolCallId("catalog"),
2922
+ options
2923
+ );
2924
+ const connectionErrors: Array<{ connection: string; message: string }> = [];
2925
+ const advertised = await resolveAdvertisedTools({
2926
+ agent: this.project.agent,
2927
+ session,
2928
+ hostMcp: this.mcpHost,
2929
+ onConnectionError: (connection, error) => {
2930
+ connectionErrors.push({
2931
+ connection,
2932
+ message: error instanceof Error ? error.message : String(error),
2933
+ });
2934
+ },
2935
+ });
2936
+ return {
2937
+ tools: [...this.project.agent.tools, ...advertised],
2938
+ connectionErrors,
2939
+ };
2940
+ }
2941
+
2762
2942
  async callTool(
2763
2943
  toolName: string,
2764
2944
  input: unknown = {},
2765
2945
  options: CallToolOptions = {}
2766
2946
  ): Promise<ToolCallOutcome> {
2767
- const tool = this.project.agent.tools.find((t) => t.name === toolName);
2947
+ const callId = newToolCallId(toolName);
2948
+ // Identity resolves before the tool lookup: advertised connection tools
2949
+ // only exist relative to a session (per-session auth), so finding them
2950
+ // needs the same identity the call runs under.
2951
+ const identity = await this.resolveDirectCallIdentity(callId, options);
2952
+ const record = identity.record;
2953
+ const session = identity.session;
2954
+ let workspaceDir = identity.workspaceDir;
2955
+ let scratchDir = identity.scratchDir;
2956
+ let tool = this.project.agent.tools.find((t) => t.name === toolName);
2957
+ if (
2958
+ tool === undefined &&
2959
+ this.project.agent.connections.some((c) => c.advertiseTools === true)
2960
+ ) {
2961
+ // Advertised passthroughs are ordinary server tools in the session's
2962
+ // namespace; resolve the live listing so direct calls address them by
2963
+ // the same model-facing name a turn would. A listing failure fails
2964
+ // the call closed, like it fails a turn.
2965
+ const advertised = await resolveAdvertisedTools({
2966
+ agent: this.project.agent,
2967
+ session,
2968
+ hostMcp: this.mcpHost,
2969
+ });
2970
+ tool = advertised.find((t) => t.name === toolName);
2971
+ }
2768
2972
  if (tool === undefined) {
2769
2973
  throw new UnknownToolError(
2770
2974
  toolName,
@@ -2781,47 +2985,51 @@ export class SessionEngine {
2781
2985
  if (!validation.ok) {
2782
2986
  throw new ToolInputError({ toolName, detail: validation.message });
2783
2987
  }
2784
-
2785
- const callId = newToolCallId(toolName);
2786
- const auth = options.auth ?? null;
2787
- let record: SessionRecord | undefined;
2788
- let session: SessionInfo;
2789
- let workspaceDir: string;
2790
- let scratchDir: string | undefined;
2791
- if (options.sessionId !== undefined) {
2792
- record = await this.sessions.get(options.sessionId);
2988
+ let workspaceUnavailable = false;
2989
+ try {
2990
+ await mkdir(workspaceDir, { recursive: true });
2991
+ } catch (error) {
2793
2992
  if (record === undefined) {
2794
- throw new UnknownSessionError(options.sessionId);
2993
+ throw error;
2795
2994
  }
2796
- // Direct calls respect the same serialization as follow-up sends: a
2797
- // running model turn owns the session workspace and event stream.
2798
- if (
2799
- this.activeTurns.has(record.sessionId) ||
2800
- this.pendingTurns.has(record.sessionId)
2801
- ) {
2802
- throw new SessionBusyError(record.sessionId);
2995
+ // A session's harness cwd can be a path the serving process cannot
2996
+ // create (e.g. an absolute `local.cwd` like /repo on a hosted pod
2997
+ // where the sandboxed harness would have made it). Read-effect calls
2998
+ // fall back to a scratch workspace instead of failing: tools that
2999
+ // resolve their state from the session identity (VFS mounts) never
3000
+ // touch ctx.workspaceDir. Advertised passthroughs are relocatable by
3001
+ // construction: their execute body forwards to the connection and
3002
+ // never reads the workspace. A write (or undeclared, which resolves
3003
+ // to write) authored tool may rely on ctx.workspaceDir being the
3004
+ // real session workspace, so silently relocating it is not safe —
3005
+ // fail typed instead.
3006
+ const relocatable =
3007
+ tool.advertised === true ||
3008
+ resolveEffect(tool.definition.effect, validation.value) === "read";
3009
+ if (!relocatable) {
3010
+ throw new WorkspaceUnavailableError(toolName, error);
2803
3011
  }
2804
- session = this.sessionInfo(record);
2805
- workspaceDir = this.harnessCwd(record);
2806
- } else {
2807
- session = {
2808
- id: callId,
2809
- channelId: DIRECT_TOOL_CALL_CHANNEL_ID,
2810
- mode: "task",
2811
- auth,
2812
- };
3012
+ this.logger(
3013
+ `[session] tool ${toolName} workspace unavailable (direct ${callId}); using scratch: ${
3014
+ error instanceof Error ? error.message : String(error)
3015
+ }`
3016
+ );
2813
3017
  scratchDir = join(this.stateRoot, "tool-calls", callId);
2814
3018
  workspaceDir = scratchDir;
3019
+ workspaceUnavailable = true;
3020
+ await mkdir(workspaceDir, { recursive: true });
2815
3021
  }
2816
- await mkdir(workspaceDir, { recursive: true });
2817
3022
  // Match what a model turn would see: session workspaces get the same
2818
3023
  // scaffold as executeTurn (seeds only before the first turn); scratch
2819
3024
  // workspaces are materialized fresh.
2820
3025
  await materializeWorkspace({
2821
3026
  agent: this.project.agent,
2822
3027
  workspaceDir:
2823
- record === undefined ? workspaceDir : this.scaffoldDir(record),
2824
- seed: record === undefined || record.turnCount === 0,
3028
+ record === undefined || workspaceUnavailable
3029
+ ? workspaceDir
3030
+ : this.scaffoldDir(record),
3031
+ seed:
3032
+ record === undefined || workspaceUnavailable || record.turnCount === 0,
2825
3033
  stateRoot: this.stateRoot,
2826
3034
  });
2827
3035
 
@@ -2957,8 +3165,9 @@ export class SessionEngine {
2957
3165
  isError,
2958
3166
  result,
2959
3167
  durationMs,
2960
- ...(errorMessage === undefined ? {} : { errorMessage }),
2961
- ...(record === undefined ? {} : { sessionId: record.sessionId }),
3168
+ errorMessage,
3169
+ sessionId: record?.sessionId,
3170
+ scratchWorkspace: workspaceUnavailable ? true : undefined,
2962
3171
  };
2963
3172
  }
2964
3173
 
@@ -155,8 +155,14 @@ export type CommitRangeDiff =
155
155
  export async function tryDiffCommitRange(args: {
156
156
  /** Existing checkout to run git in (see {@link createShallowPrCheckout}). */
157
157
  checkoutDir: string;
158
- /** The checkout's clone target; supplies the remote's ref + auth conventions. */
159
- target: ScmCloneTarget;
158
+ /**
159
+ * The checkout's clone target; supplies the remote's ref + auth
160
+ * conventions. Omit for SCMs without a clone target (e.g. Origin, where
161
+ * the host checkout is the reviewed repo): the diff then relies on
162
+ * commits already present locally, plus one uncredentialed fetch-by-SHA
163
+ * through the checkout's own remote.
164
+ */
165
+ target?: ScmCloneTarget | undefined;
160
166
  from: string;
161
167
  to: string;
162
168
  /** Restrict the diff to one path when set. */
@@ -171,10 +177,13 @@ export async function tryDiffCommitRange(args: {
171
177
  "Could not compute a reliable diff because a commit SHA was not a full 40-character SHA.",
172
178
  };
173
179
  }
174
- const credential = cloneCredential(
175
- args.target,
176
- args.auth ?? defaultCloneAuth(args.target)
177
- );
180
+ const credential =
181
+ args.target === undefined
182
+ ? undefined
183
+ : cloneCredential(
184
+ args.target,
185
+ args.auth ?? defaultCloneAuth(args.target)
186
+ );
178
187
  for (const sha of [args.from, args.to]) {
179
188
  if (
180
189
  !(await ensureCommitFetched(
@@ -222,7 +231,7 @@ function isFullCommitSha(value: string): boolean {
222
231
  async function ensureCommitFetched(
223
232
  checkoutDir: string,
224
233
  sha: string,
225
- target: ScmCloneTarget,
234
+ target: ScmCloneTarget | undefined,
226
235
  credential: GitCredential | undefined
227
236
  ): Promise<boolean> {
228
237
  if ((await revParse(checkoutDir, sha)) !== undefined) {
@@ -231,15 +240,20 @@ async function ensureCommitFetched(
231
240
  const attempts = [
232
241
  [...FETCH_ARGS, sha],
233
242
  // Deeper history on the PR head ref: the older end of an inter-run range
234
- // is usually an ancestor of the tip rather than the tip itself.
235
- [
236
- "fetch",
237
- "--depth=200",
238
- "--no-tags",
239
- "--quiet",
240
- "origin",
241
- target.prHeadRef,
242
- ],
243
+ // is usually an ancestor of the tip rather than the tip itself. Only
244
+ // possible when the clone target (and so the PR head ref) is known.
245
+ ...(target === undefined
246
+ ? []
247
+ : [
248
+ [
249
+ "fetch",
250
+ "--depth=200",
251
+ "--no-tags",
252
+ "--quiet",
253
+ "origin",
254
+ target.prHeadRef,
255
+ ],
256
+ ]),
243
257
  ];
244
258
  for (const attempt of attempts) {
245
259
  try {