@cursor/july 0.1.93 → 0.1.95

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 (440) hide show
  1. package/AGENTS.md +8 -20
  2. package/README.md +4 -26
  3. package/dist/channels/github/github-channel.d.ts.map +1 -1
  4. package/dist/channels/github/github-channel.js +14 -2
  5. package/dist/channels/github/types.d.ts +18 -3
  6. package/dist/channels/github/types.d.ts.map +1 -1
  7. package/dist/channels/origin/origin-channel.d.ts.map +1 -1
  8. package/dist/channels/origin/origin-channel.js +11 -3
  9. package/dist/channels/origin/origin-webhook.d.ts +11 -1
  10. package/dist/channels/origin/origin-webhook.d.ts.map +1 -1
  11. package/dist/channels/origin/origin-webhook.js +23 -3
  12. package/dist/channels/origin/types.d.ts +8 -0
  13. package/dist/channels/origin/types.d.ts.map +1 -1
  14. package/dist/channels/slack/attachments.js +2 -2
  15. package/dist/channels/slack/dispatch.d.ts +0 -7
  16. package/dist/channels/slack/dispatch.d.ts.map +1 -1
  17. package/dist/channels/slack/dispatch.js +4 -7
  18. package/dist/channels/slack/eval-directive.d.ts +5 -12
  19. package/dist/channels/slack/eval-directive.d.ts.map +1 -1
  20. package/dist/channels/slack/eval-directive.js +8 -19
  21. package/dist/channels/slack/index.d.ts +0 -6
  22. package/dist/channels/slack/index.d.ts.map +1 -1
  23. package/dist/channels/slack/index.js +0 -6
  24. package/dist/channels/slack/pr-ref.d.ts +7 -1
  25. package/dist/channels/slack/pr-ref.d.ts.map +1 -1
  26. package/dist/channels/slack/pr-ref.js +42 -23
  27. package/dist/channels/slack/setup.d.ts +4 -4
  28. package/dist/channels/slack/setup.d.ts.map +1 -1
  29. package/dist/channels/slack/setup.js +8 -15
  30. package/dist/channels/slack/slack-channel.d.ts +6 -13
  31. package/dist/channels/slack/slack-channel.d.ts.map +1 -1
  32. package/dist/channels/slack/slack-channel.js +15 -101
  33. package/dist/channels/slack/types.d.ts +12 -79
  34. package/dist/channels/slack/types.d.ts.map +1 -1
  35. package/dist/channels/slack/types.js +1 -15
  36. package/dist/client.d.ts +14 -0
  37. package/dist/client.d.ts.map +1 -0
  38. package/dist/client.js +12 -0
  39. package/dist/connections.d.ts +18 -9
  40. package/dist/connections.d.ts.map +1 -1
  41. package/dist/connections.js +17 -8
  42. package/dist/docs/404.html +2 -2
  43. package/dist/docs/ab.html +4 -4
  44. package/dist/docs/assets/{app.CjWU-x0z.js → app.BBj0klBO.js} +1 -1
  45. package/dist/docs/assets/chunks/@localSearchIndexroot.oqPawjiD.js +1 -0
  46. package/dist/docs/assets/chunks/{VPLocalSearchBox.Cxy8ySFQ.js → VPLocalSearchBox.CUEXpL78.js} +1 -1
  47. package/dist/docs/assets/chunks/{theme.Dvq1Bktu.js → theme.DabmQnia.js} +2 -2
  48. package/dist/docs/assets/concepts.md.lwAgBIMI.js +1 -0
  49. package/dist/docs/assets/{deployment.md.DoLFAzfm.js → deployment.md.D9msOFOW.js} +3 -8
  50. package/dist/docs/assets/{deployment.md.DoLFAzfm.lean.js → deployment.md.D9msOFOW.lean.js} +1 -1
  51. package/dist/docs/assets/{guides_agent-to-agent.md.B3JIaAqz.js → guides_agent-to-agent.md.BDb0t1QV.js} +1 -1
  52. package/dist/docs/assets/guides_cloud-runtime.md.CkYbjnAX.js +9 -0
  53. package/dist/docs/assets/guides_cloud-runtime.md.CkYbjnAX.lean.js +1 -0
  54. package/dist/docs/assets/{guides_convert-automation.md.Bboisykk.js → guides_convert-automation.md.B4sjlodG.js} +1 -1
  55. package/dist/docs/assets/{guides_github.md.DqJhuaN1.js → guides_github.md.Cnh2mL4a.js} +1 -1
  56. package/dist/docs/assets/{guides_mcp-oauth.md.CJvrXtkN.js → guides_mcp-oauth.md.DPYmBCbV.js} +7 -9
  57. package/dist/docs/assets/{guides_mcp-oauth.md.CJvrXtkN.lean.js → guides_mcp-oauth.md.DPYmBCbV.lean.js} +1 -1
  58. package/dist/docs/assets/{guides_slack.md.mqeNKs84.js → guides_slack.md.C32HsdKk.js} +5 -11
  59. package/dist/docs/assets/guides_slack.md.C32HsdKk.lean.js +1 -0
  60. package/dist/docs/assets/index.md.BoHaMdeZ.js +5 -0
  61. package/dist/docs/assets/{index.md.B-lVR4wT.lean.js → index.md.BoHaMdeZ.lean.js} +1 -1
  62. package/dist/docs/assets/{quickstart.md.BrmfrrIr.js → quickstart.md.Nj_LjW_a.js} +1 -1
  63. package/dist/docs/assets/{reference_cli.md.D9KESDsD.js → reference_cli.md.BsMOxDvh.js} +4 -3
  64. package/dist/docs/assets/{reference_cli.md.D9KESDsD.lean.js → reference_cli.md.BsMOxDvh.lean.js} +1 -1
  65. package/dist/docs/assets/{reference_connections.md.DB6SsN6U.js → reference_connections.md.BH8Oc0D0.js} +5 -5
  66. package/dist/docs/assets/{reference_connections.md.DB6SsN6U.lean.js → reference_connections.md.BH8Oc0D0.lean.js} +1 -1
  67. package/dist/docs/assets/{reference_hooks.md.BxN87gCw.js → reference_hooks.md.a8BJxMR5.js} +1 -1
  68. package/dist/docs/assets/reference_http-api.md.D89k1mdm.js +11 -0
  69. package/dist/docs/assets/reference_http-api.md.D89k1mdm.lean.js +1 -0
  70. package/dist/docs/assets/reference_project-layout.md.Bv4KOtlB.js +19 -0
  71. package/dist/docs/assets/{reference_subagents.md.Xoav0AII.js → reference_subagents.md.CfsIloPm.js} +1 -1
  72. package/dist/docs/assets/{reference_tools.md.DuKvkYWG.js → reference_tools.md.BHeXn2id.js} +3 -3
  73. package/dist/docs/assets/{reference_tools.md.DuKvkYWG.lean.js → reference_tools.md.BHeXn2id.lean.js} +1 -1
  74. package/dist/docs/assets/{templates_agentic-owners.md.DqtPdm6f.js → templates_agentic-owners.md.BZSH4N9z.js} +1 -1
  75. package/dist/docs/assets/{templates_demo.md.DhFcWN6j.js → templates_demo.md.BeQX9V3H.js} +1 -1
  76. package/dist/docs/assets/{templates_pr-autofixer.md.R4K_qytS.js → templates_pr-autofixer.md.x5zl6-GT.js} +2 -2
  77. package/dist/docs/assets/{templates_pr-autofixer.md.R4K_qytS.lean.js → templates_pr-autofixer.md.x5zl6-GT.lean.js} +1 -1
  78. package/dist/docs/assets/templates_security-help.md.C3Ny_Qr2.js +4 -0
  79. package/dist/docs/assets/templates_security-help.md.C3Ny_Qr2.lean.js +1 -0
  80. package/dist/docs/assets/{templates_security-reviewer.md.ByFyRta2.js → templates_security-reviewer.md.lshxbCLK.js} +2 -2
  81. package/dist/docs/assets/{templates_security-reviewer.md.ByFyRta2.lean.js → templates_security-reviewer.md.lshxbCLK.lean.js} +1 -1
  82. package/dist/docs/assets/{templates_triage.md.CVlpctKS.js → templates_triage.md.Co4UNzkZ.js} +3 -3
  83. package/dist/docs/assets/{templates_triage.md.CVlpctKS.lean.js → templates_triage.md.Co4UNzkZ.lean.js} +1 -1
  84. package/dist/docs/assets/troubleshooting.md.Ctv3T8C2.js +1 -0
  85. package/dist/docs/building-with-agents.html +4 -4
  86. package/dist/docs/concepts.html +5 -5
  87. package/dist/docs/concepts.md +1 -0
  88. package/dist/docs/deployment.html +7 -12
  89. package/dist/docs/deployment.md +1 -20
  90. package/dist/docs/design/agsh.md +406 -0
  91. package/dist/docs/evals.html +4 -4
  92. package/dist/docs/guides/agent-to-agent.html +6 -6
  93. package/dist/docs/guides/agent-to-agent.md +2 -2
  94. package/dist/docs/guides/cloud-runtime.html +6 -6
  95. package/dist/docs/guides/cloud-runtime.md +1 -0
  96. package/dist/docs/guides/convert-automation.html +6 -6
  97. package/dist/docs/guides/convert-automation.md +1 -1
  98. package/dist/docs/guides/github.html +6 -6
  99. package/dist/docs/guides/github.md +4 -4
  100. package/dist/docs/guides/human-in-the-loop.html +4 -4
  101. package/dist/docs/guides/mcp-oauth.html +11 -13
  102. package/dist/docs/guides/mcp-oauth.md +10 -18
  103. package/dist/docs/guides/opentelemetry.html +5 -5
  104. package/dist/docs/guides/slack.html +9 -15
  105. package/dist/docs/guides/slack.md +9 -46
  106. package/dist/docs/guides/webhooks.html +4 -4
  107. package/dist/docs/hashmap.json +1 -1
  108. package/dist/docs/hillclimbing.html +4 -4
  109. package/dist/docs/index.html +6 -6
  110. package/dist/docs/index.md +3 -29
  111. package/dist/docs/llms-full.txt +756 -2810
  112. package/dist/docs/llms.txt +3 -16
  113. package/dist/docs/quickstart.html +6 -6
  114. package/dist/docs/quickstart.md +2 -3
  115. package/dist/docs/reference/agent-config.html +4 -4
  116. package/dist/docs/reference/artifacts.html +4 -4
  117. package/dist/docs/reference/channels.html +4 -4
  118. package/dist/docs/reference/cli.html +8 -7
  119. package/dist/docs/reference/cli.md +5 -2
  120. package/dist/docs/reference/connections.html +9 -9
  121. package/dist/docs/reference/connections.md +15 -11
  122. package/dist/docs/reference/hooks.html +6 -6
  123. package/dist/docs/reference/hooks.md +2 -3
  124. package/dist/docs/reference/http-api.html +6 -6
  125. package/dist/docs/reference/http-api.md +8 -0
  126. package/dist/docs/reference/instructions.html +4 -4
  127. package/dist/docs/reference/playground.html +4 -4
  128. package/dist/docs/reference/project-layout.html +8 -6
  129. package/dist/docs/reference/project-layout.md +5 -1
  130. package/dist/docs/reference/prompt.html +4 -4
  131. package/dist/docs/reference/schedules.html +4 -4
  132. package/dist/docs/reference/sessions.html +4 -4
  133. package/dist/docs/reference/skills.html +4 -4
  134. package/dist/docs/reference/subagents.html +6 -6
  135. package/dist/docs/reference/subagents.md +2 -2
  136. package/dist/docs/reference/tools.html +7 -7
  137. package/dist/docs/reference/tools.md +19 -3
  138. package/dist/docs/scaffolding-agents.html +4 -4
  139. package/dist/docs/storage.html +4 -4
  140. package/dist/docs/templates/agentic-owners.html +7 -7
  141. package/dist/docs/templates/agentic-owners.md +1 -1
  142. package/dist/docs/templates/demo.html +6 -6
  143. package/dist/docs/templates/demo.md +3 -2
  144. package/dist/docs/templates/pr-autofixer.html +6 -6
  145. package/dist/docs/templates/pr-autofixer.md +8 -13
  146. package/dist/docs/templates/security-help.html +30 -0
  147. package/dist/docs/templates/security-help.md +65 -0
  148. package/dist/docs/templates/security-reviewer.html +6 -6
  149. package/dist/docs/templates/security-reviewer.md +1 -3
  150. package/dist/docs/templates/triage.html +7 -7
  151. package/dist/docs/templates/triage.md +2 -6
  152. package/dist/docs/troubleshooting.html +5 -5
  153. package/dist/docs/troubleshooting.md +2 -2
  154. package/dist/files-backends/cursor-hosted.d.ts +6 -2
  155. package/dist/files-backends/cursor-hosted.d.ts.map +1 -1
  156. package/dist/files-backends/cursor-hosted.js +2 -2
  157. package/dist/files.d.ts +2 -0
  158. package/dist/files.d.ts.map +1 -1
  159. package/dist/files.js +5 -0
  160. package/dist/index.d.ts +1 -1
  161. package/dist/index.d.ts.map +1 -1
  162. package/dist/index.js +1 -1
  163. package/dist/internal/advertise-tools.d.ts +11 -0
  164. package/dist/internal/advertise-tools.d.ts.map +1 -1
  165. package/dist/internal/advertise-tools.js +47 -9
  166. package/dist/internal/cli-deploy.d.ts.map +1 -1
  167. package/dist/internal/cli-deploy.js +135 -6
  168. package/dist/internal/cli-mcp-oauth.d.ts.map +1 -1
  169. package/dist/internal/cli-mcp-oauth.js +7 -4
  170. package/dist/internal/conversation-mirror.d.ts +82 -0
  171. package/dist/internal/conversation-mirror.d.ts.map +1 -0
  172. package/dist/internal/conversation-mirror.js +251 -0
  173. package/dist/internal/convert-automation/convert-workflow.d.ts.map +1 -1
  174. package/dist/internal/convert-automation/convert-workflow.js +26 -15
  175. package/dist/internal/convert-automation/slug.d.ts +0 -2
  176. package/dist/internal/convert-automation/slug.d.ts.map +1 -1
  177. package/dist/internal/convert-automation/slug.js +0 -8
  178. package/dist/internal/cursor/account-mcp.d.ts.map +1 -1
  179. package/dist/internal/cursor/account-mcp.js +5 -1
  180. package/dist/internal/deferred-channel-session.d.ts +20 -0
  181. package/dist/internal/deferred-channel-session.d.ts.map +1 -0
  182. package/dist/internal/deferred-channel-session.js +62 -0
  183. package/dist/internal/deploy-client.d.ts +13 -1
  184. package/dist/internal/deploy-client.d.ts.map +1 -1
  185. package/dist/internal/deploy-client.js +11 -1
  186. package/dist/internal/deploy-manifest.d.ts.map +1 -1
  187. package/dist/internal/deploy-manifest.js +11 -5
  188. package/dist/internal/discovery.d.ts.map +1 -1
  189. package/dist/internal/discovery.js +110 -15
  190. package/dist/internal/framework-storage-selection.d.ts +32 -16
  191. package/dist/internal/framework-storage-selection.d.ts.map +1 -1
  192. package/dist/internal/framework-storage-selection.js +51 -17
  193. package/dist/internal/hosted-admission-context.d.ts +20 -0
  194. package/dist/internal/hosted-admission-context.d.ts.map +1 -0
  195. package/dist/internal/hosted-admission-context.js +31 -0
  196. package/dist/internal/hosted-delivery-protocol.d.ts +5 -0
  197. package/dist/internal/hosted-delivery-protocol.d.ts.map +1 -1
  198. package/dist/internal/hosted-delivery-protocol.js +33 -1
  199. package/dist/internal/hosted-delivery.d.ts +4 -2
  200. package/dist/internal/hosted-delivery.d.ts.map +1 -1
  201. package/dist/internal/hosted-delivery.js +97 -44
  202. package/dist/internal/hosted-managed-automation.d.ts +30 -0
  203. package/dist/internal/hosted-managed-automation.d.ts.map +1 -0
  204. package/dist/internal/hosted-managed-automation.js +58 -0
  205. package/dist/internal/mcp-endpoint.js +3 -3
  206. package/dist/internal/mcp-host.d.ts +8 -7
  207. package/dist/internal/mcp-host.d.ts.map +1 -1
  208. package/dist/internal/mcp-host.js +8 -7
  209. package/dist/internal/peer-connections.d.ts.map +1 -1
  210. package/dist/internal/peer-connections.js +5 -1
  211. package/dist/internal/playground/static.d.ts +0 -3
  212. package/dist/internal/playground/static.d.ts.map +1 -1
  213. package/dist/internal/resolved-connections.d.ts.map +1 -1
  214. package/dist/internal/resolved-connections.js +5 -7
  215. package/dist/internal/review-comments.d.ts.map +1 -1
  216. package/dist/internal/review-comments.js +10 -98
  217. package/dist/internal/scm/pr-url.d.ts +14 -0
  218. package/dist/internal/scm/pr-url.d.ts.map +1 -0
  219. package/dist/internal/scm/pr-url.js +65 -0
  220. package/dist/internal/sdk-runner.d.ts +14 -0
  221. package/dist/internal/sdk-runner.d.ts.map +1 -1
  222. package/dist/internal/sdk-runner.js +41 -2
  223. package/dist/internal/server.d.ts.map +1 -1
  224. package/dist/internal/server.js +123 -174
  225. package/dist/internal/session-engine.d.ts +45 -10
  226. package/dist/internal/session-engine.d.ts.map +1 -1
  227. package/dist/internal/session-engine.js +217 -65
  228. package/dist/internal/tool-catalog.d.ts +31 -0
  229. package/dist/internal/tool-catalog.d.ts.map +1 -0
  230. package/dist/internal/tool-catalog.js +67 -0
  231. package/dist/playground/assets/index-CF7hUDnQ.css +1 -0
  232. package/dist/playground/assets/{index-D9MFzhNE.js → index-CZA1uEWA.js} +48 -48
  233. package/dist/playground/index.html +2 -2
  234. package/dist/storage-backends/cursor-hosted.d.ts +7 -2
  235. package/dist/storage-backends/cursor-hosted.d.ts.map +1 -1
  236. package/dist/storage-backends/cursor-hosted.js +2 -2
  237. package/dist/types.d.ts +72 -23
  238. package/dist/types.d.ts.map +1 -1
  239. package/dist/types.js +19 -0
  240. package/docs/README.md +3 -29
  241. package/docs/concepts.md +1 -0
  242. package/docs/deployment.md +1 -20
  243. package/docs/design/agsh.md +406 -0
  244. package/docs/guides/agent-to-agent.md +2 -2
  245. package/docs/guides/cloud-runtime.md +1 -0
  246. package/docs/guides/convert-automation.md +1 -1
  247. package/docs/guides/github.md +4 -4
  248. package/docs/guides/mcp-oauth.md +10 -18
  249. package/docs/guides/slack.md +10 -47
  250. package/docs/quickstart.md +2 -3
  251. package/docs/reference/cli.md +5 -2
  252. package/docs/reference/connections.md +15 -11
  253. package/docs/reference/hooks.md +2 -3
  254. package/docs/reference/http-api.md +8 -0
  255. package/docs/reference/project-layout.md +5 -1
  256. package/docs/reference/subagents.md +2 -2
  257. package/docs/reference/tools.md +19 -3
  258. package/docs/templates/agentic-owners.md +1 -1
  259. package/docs/templates/demo.md +3 -2
  260. package/docs/templates/pr-autofixer.md +8 -13
  261. package/docs/templates/security-help.md +70 -0
  262. package/docs/templates/security-reviewer.md +1 -3
  263. package/docs/templates/triage.md +2 -6
  264. package/docs/troubleshooting.md +2 -2
  265. package/package.json +9 -2
  266. package/skills/create-agent/SKILL.md +6 -13
  267. package/skills/debug/SKILL.md +2 -4
  268. package/skills/evals/SKILL.md +1 -1
  269. package/skills/framework-map/SKILL.md +3 -2
  270. package/skills/mcp-auth/SKILL.md +10 -13
  271. package/skills/setup-slack/SKILL.md +21 -137
  272. package/src/channels/github/github-channel.ts +23 -8
  273. package/src/channels/github/types.ts +19 -2
  274. package/src/channels/origin/origin-channel.ts +13 -1
  275. package/src/channels/origin/origin-webhook.ts +27 -3
  276. package/src/channels/origin/types.ts +8 -0
  277. package/src/channels/slack/attachments.ts +2 -2
  278. package/src/channels/slack/dispatch.ts +2 -16
  279. package/src/channels/slack/eval-directive.ts +8 -27
  280. package/src/channels/slack/index.ts +0 -6
  281. package/src/channels/slack/pr-ref.ts +56 -25
  282. package/src/channels/slack/setup.ts +8 -15
  283. package/src/channels/slack/slack-channel.ts +14 -125
  284. package/src/channels/slack/types.ts +12 -96
  285. package/src/client.ts +23 -0
  286. package/src/connections.ts +20 -7
  287. package/src/files-backends/cursor-hosted.ts +9 -3
  288. package/src/files.ts +11 -0
  289. package/src/index.ts +2 -0
  290. package/src/internal/advertise-tools.ts +45 -7
  291. package/src/internal/cli-deploy.ts +171 -7
  292. package/src/internal/cli-mcp-oauth.ts +6 -4
  293. package/src/internal/conversation-mirror.ts +330 -0
  294. package/src/internal/convert-automation/convert-workflow.ts +29 -17
  295. package/src/internal/convert-automation/slug.ts +0 -9
  296. package/src/internal/cursor/account-mcp.ts +4 -1
  297. package/src/internal/deferred-channel-session.ts +61 -0
  298. package/src/internal/deploy-client.ts +24 -1
  299. package/src/internal/deploy-manifest.ts +10 -5
  300. package/src/internal/discovery.ts +129 -15
  301. package/src/internal/fixtures/units-server.ts +52 -0
  302. package/src/internal/framework-storage-selection.ts +61 -19
  303. package/src/internal/hosted-admission-context.ts +37 -0
  304. package/src/internal/hosted-delivery-protocol.ts +44 -1
  305. package/src/internal/hosted-delivery.ts +155 -68
  306. package/src/internal/hosted-managed-automation.ts +72 -0
  307. package/src/internal/mcp-endpoint.ts +3 -3
  308. package/src/internal/mcp-host.ts +8 -7
  309. package/src/internal/peer-connections.ts +4 -1
  310. package/src/internal/playground/static.ts +1 -3
  311. package/src/internal/resolved-connections.ts +8 -10
  312. package/src/internal/review-comments.ts +10 -113
  313. package/src/internal/scm/pr-url.ts +95 -0
  314. package/src/internal/sdk-runner.ts +57 -2
  315. package/src/internal/server.ts +161 -251
  316. package/src/internal/session-engine.ts +266 -69
  317. package/src/internal/tool-catalog.ts +106 -0
  318. package/src/storage-backends/cursor-hosted.ts +10 -3
  319. package/src/types.ts +90 -23
  320. package/templates/agentic-owners/README.md +1 -1
  321. package/templates/agentic-owners/agent/agent.ts +0 -10
  322. package/templates/agentic-owners/agent/channels/github.ts +5 -14
  323. package/templates/agentic-owners/agent/lib/config.ts +0 -8
  324. package/templates/agentic-owners/agent/lib/review.ts +2 -15
  325. package/templates/agentic-owners/agent/tools/record_review.ts +2 -4
  326. package/templates/demo/agent/agent.ts +0 -10
  327. package/templates/pr-autofixer/README.md +0 -2
  328. package/templates/pr-autofixer/agent/agent.ts +0 -11
  329. package/templates/pr-autofixer/agent/channels/slack.ts +1 -2
  330. package/templates/pr-autofixer/agent/lib/pr-state.ts +5 -17
  331. package/templates/pr-autofixer/agent/lib/repos.ts +0 -1
  332. package/templates/security-help/README.md +2 -2
  333. package/templates/security-help/agent/agent.ts +1 -2
  334. package/templates/security-help/agent/channels/slack.ts +0 -3
  335. package/templates/security-help/agent/instructions.md +9 -10
  336. package/templates/security-help/agent/skills/access-request.md +1 -1
  337. package/templates/security-help/agent/skills/faq.md +31 -0
  338. package/templates/security-help/agent/skills/security-playbooks.md +1 -1
  339. package/templates/security-help/package.json +1 -2
  340. package/templates/security-reviewer/agent/agent.ts +0 -10
  341. package/templates/triage/README.md +2 -1
  342. package/templates/triage/agent/agent.ts +0 -10
  343. package/templates/triage/agent/channels/queue.ts +1 -1
  344. package/templates/triage/agent/channels/webhook.ts +1 -3
  345. package/templates/triage/overlays/jira/agent/mcp-connections/tracker.ts +0 -1
  346. package/templates/triage/overlays/linear/agent/mcp-connections/tracker.ts +0 -1
  347. package/dist/channels/slack/cursor-account.d.ts +0 -87
  348. package/dist/channels/slack/cursor-account.d.ts.map +0 -1
  349. package/dist/channels/slack/cursor-account.js +0 -100
  350. package/dist/docs/assets/chunks/@localSearchIndexroot.ChpIC3Zy.js +0 -1
  351. package/dist/docs/assets/concepts.md.F6AiPorA.js +0 -1
  352. package/dist/docs/assets/example-agents_approval-buddy.md.DmezILPg.js +0 -10
  353. package/dist/docs/assets/example-agents_approval-buddy.md.DmezILPg.lean.js +0 -1
  354. package/dist/docs/assets/example-agents_benny.md.B0kwY7D_.js +0 -5
  355. package/dist/docs/assets/example-agents_benny.md.B0kwY7D_.lean.js +0 -1
  356. package/dist/docs/assets/example-agents_bugbot.md.BRGMi9O2.js +0 -11
  357. package/dist/docs/assets/example-agents_bugbot.md.BRGMi9O2.lean.js +0 -1
  358. package/dist/docs/assets/example-agents_codebase-wiki.md.BBNw9Ekr.js +0 -8
  359. package/dist/docs/assets/example-agents_codebase-wiki.md.BBNw9Ekr.lean.js +0 -1
  360. package/dist/docs/assets/example-agents_codeowners-review.md.Bfta-lBU.js +0 -8
  361. package/dist/docs/assets/example-agents_codeowners-review.md.Bfta-lBU.lean.js +0 -1
  362. package/dist/docs/assets/example-agents_concierge.md.BzB2b20R.js +0 -22
  363. package/dist/docs/assets/example-agents_concierge.md.BzB2b20R.lean.js +0 -1
  364. package/dist/docs/assets/example-agents_index.md.ChBp0AX6.js +0 -2
  365. package/dist/docs/assets/example-agents_index.md.ChBp0AX6.lean.js +0 -1
  366. package/dist/docs/assets/example-agents_knowledge-base.md.CrA85ig-.js +0 -11
  367. package/dist/docs/assets/example-agents_knowledge-base.md.CrA85ig-.lean.js +0 -1
  368. package/dist/docs/assets/example-agents_oncall.md.DK4XkYTd.js +0 -10
  369. package/dist/docs/assets/example-agents_oncall.md.DK4XkYTd.lean.js +0 -1
  370. package/dist/docs/assets/example-agents_security-reviewer.md.74pPpWYj.js +0 -19
  371. package/dist/docs/assets/example-agents_security-reviewer.md.74pPpWYj.lean.js +0 -1
  372. package/dist/docs/assets/example-agents_slack-agent.md.D7Kdj5BV.js +0 -5
  373. package/dist/docs/assets/example-agents_slack-agent.md.D7Kdj5BV.lean.js +0 -1
  374. package/dist/docs/assets/example-agents_weather-agent.md.CaGpmw3Y.js +0 -25
  375. package/dist/docs/assets/example-agents_weather-agent.md.CaGpmw3Y.lean.js +0 -1
  376. package/dist/docs/assets/guides_cloud-runtime.md.BnvjPiia.js +0 -9
  377. package/dist/docs/assets/guides_cloud-runtime.md.BnvjPiia.lean.js +0 -1
  378. package/dist/docs/assets/guides_slack.md.mqeNKs84.lean.js +0 -1
  379. package/dist/docs/assets/index.md.B-lVR4wT.js +0 -5
  380. package/dist/docs/assets/reference_http-api.md.C68BERYr.js +0 -11
  381. package/dist/docs/assets/reference_http-api.md.C68BERYr.lean.js +0 -1
  382. package/dist/docs/assets/reference_project-layout.md.WN9nwJht.js +0 -17
  383. package/dist/docs/assets/troubleshooting.md.vCWwvqcJ.js +0 -1
  384. package/dist/docs/example-agents/approval-buddy.html +0 -36
  385. package/dist/docs/example-agents/approval-buddy.md +0 -266
  386. package/dist/docs/example-agents/benny.html +0 -31
  387. package/dist/docs/example-agents/benny.md +0 -173
  388. package/dist/docs/example-agents/bugbot.html +0 -37
  389. package/dist/docs/example-agents/bugbot.md +0 -229
  390. package/dist/docs/example-agents/codebase-wiki.html +0 -34
  391. package/dist/docs/example-agents/codebase-wiki.md +0 -167
  392. package/dist/docs/example-agents/codeowners-review.html +0 -34
  393. package/dist/docs/example-agents/codeowners-review.md +0 -192
  394. package/dist/docs/example-agents/concierge.html +0 -48
  395. package/dist/docs/example-agents/concierge.md +0 -200
  396. package/dist/docs/example-agents/index.html +0 -28
  397. package/dist/docs/example-agents/index.md +0 -99
  398. package/dist/docs/example-agents/knowledge-base.html +0 -37
  399. package/dist/docs/example-agents/knowledge-base.md +0 -168
  400. package/dist/docs/example-agents/oncall.html +0 -36
  401. package/dist/docs/example-agents/oncall.md +0 -212
  402. package/dist/docs/example-agents/security-reviewer.html +0 -45
  403. package/dist/docs/example-agents/security-reviewer.md +0 -265
  404. package/dist/docs/example-agents/slack-agent.html +0 -31
  405. package/dist/docs/example-agents/slack-agent.md +0 -142
  406. package/dist/docs/example-agents/weather-agent.html +0 -51
  407. package/dist/docs/example-agents/weather-agent.md +0 -297
  408. package/dist/internal/cursor-slack-relay.d.ts +0 -96
  409. package/dist/internal/cursor-slack-relay.d.ts.map +0 -1
  410. package/dist/internal/cursor-slack-relay.js +0 -176
  411. package/dist/playground/assets/index-D9N7-q97.css +0 -1
  412. package/docs/example-agents/approval-buddy.md +0 -271
  413. package/docs/example-agents/benny.md +0 -178
  414. package/docs/example-agents/bugbot.md +0 -234
  415. package/docs/example-agents/codebase-wiki.md +0 -172
  416. package/docs/example-agents/codeowners-review.md +0 -197
  417. package/docs/example-agents/concierge.md +0 -205
  418. package/docs/example-agents/index.md +0 -104
  419. package/docs/example-agents/knowledge-base.md +0 -173
  420. package/docs/example-agents/oncall.md +0 -217
  421. package/docs/example-agents/security-reviewer.md +0 -270
  422. package/docs/example-agents/slack-agent.md +0 -147
  423. package/docs/example-agents/weather-agent.md +0 -302
  424. package/src/channels/slack/cursor-account.ts +0 -202
  425. package/src/internal/cursor-slack-relay.ts +0 -249
  426. package/templates/security-help/agent/knowledge/faq/approvals.md +0 -5
  427. package/templates/security-help/agent/knowledge/faq/channels.md +0 -6
  428. package/templates/security-help/agent/knowledge/faq/phishing.md +0 -10
  429. package/templates/security-help/agent/skills/security-first-pass.md +0 -15
  430. /package/dist/docs/assets/{concepts.md.F6AiPorA.lean.js → concepts.md.lwAgBIMI.lean.js} +0 -0
  431. /package/dist/docs/assets/{guides_agent-to-agent.md.B3JIaAqz.lean.js → guides_agent-to-agent.md.BDb0t1QV.lean.js} +0 -0
  432. /package/dist/docs/assets/{guides_convert-automation.md.Bboisykk.lean.js → guides_convert-automation.md.B4sjlodG.lean.js} +0 -0
  433. /package/dist/docs/assets/{guides_github.md.DqJhuaN1.lean.js → guides_github.md.Cnh2mL4a.lean.js} +0 -0
  434. /package/dist/docs/assets/{quickstart.md.BrmfrrIr.lean.js → quickstart.md.Nj_LjW_a.lean.js} +0 -0
  435. /package/dist/docs/assets/{reference_hooks.md.BxN87gCw.lean.js → reference_hooks.md.a8BJxMR5.lean.js} +0 -0
  436. /package/dist/docs/assets/{reference_project-layout.md.WN9nwJht.lean.js → reference_project-layout.md.Bv4KOtlB.lean.js} +0 -0
  437. /package/dist/docs/assets/{reference_subagents.md.Xoav0AII.lean.js → reference_subagents.md.CfsIloPm.lean.js} +0 -0
  438. /package/dist/docs/assets/{templates_agentic-owners.md.DqtPdm6f.lean.js → templates_agentic-owners.md.BZSH4N9z.lean.js} +0 -0
  439. /package/dist/docs/assets/{templates_demo.md.DhFcWN6j.lean.js → templates_demo.md.BeQX9V3H.lean.js} +0 -0
  440. /package/dist/docs/assets/{troubleshooting.md.vCWwvqcJ.lean.js → troubleshooting.md.Ctv3T8C2.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,
@@ -112,11 +113,16 @@ import {
112
113
  createHostSlackClient,
113
114
  type HostPlatforms,
114
115
  } from "./host-platforms.js";
116
+ import {
117
+ HostedAdmissionLocalSendError,
118
+ isDuringHostedAdmission,
119
+ } from "./hosted-admission-context.js";
115
120
  import {
116
121
  formatContinuationToken,
117
122
  newContinuationKey,
118
123
  newSessionId,
119
124
  newToolCallId,
125
+ parseContinuationToken,
120
126
  } from "./ids.js";
121
127
  import { validateToolInput } from "./json-schema.js";
122
128
  import { McpHost } from "./mcp-host.js";
@@ -136,7 +142,7 @@ import { SessionStore } from "./session-store.js";
136
142
  import { syncSkillsToStore } from "./skills-sync.js";
137
143
  import { StorageCoordinator } from "./storage-coordinator.js";
138
144
  import type { FrameworkSessionStore } from "./storage-roles.js";
139
- import { decideToolCall } from "./tool-policy.js";
145
+ import { decideToolCall, resolveEffect } from "./tool-policy.js";
140
146
  import { normalizeToolResult, toolCallErrorMessage } from "./tool-result.js";
141
147
  import {
142
148
  type EstimateTurnCostFn,
@@ -197,6 +203,30 @@ export class ToolNotDirectlyCallableError extends Error {
197
203
  }
198
204
  }
199
205
 
206
+ export class InvalidContinuationTokenError extends Error {
207
+ constructor(detail: string) {
208
+ super(`Invalid continuation token: ${detail}`);
209
+ this.name = "InvalidContinuationTokenError";
210
+ }
211
+ }
212
+
213
+ /**
214
+ * A session-bound direct call whose harness cwd cannot be materialized and
215
+ * whose effect is not read: a write tool may rely on ctx.workspaceDir being
216
+ * the real session workspace, so it fails typed instead of silently running
217
+ * in a scratch directory.
218
+ */
219
+ export class WorkspaceUnavailableError extends Error {
220
+ constructor(toolName: string, cause: unknown) {
221
+ super(
222
+ `Session workspace unavailable for tool "${toolName}": ${
223
+ cause instanceof Error ? cause.message : String(cause)
224
+ }`
225
+ );
226
+ this.name = "WorkspaceUnavailableError";
227
+ }
228
+ }
229
+
200
230
  export class ToolInputError extends Error {
201
231
  constructor(args: { toolName: string; detail: string }) {
202
232
  super(`Invalid input for tool "${args.toolName}": ${args.detail}`);
@@ -439,6 +469,7 @@ export class SessionEngine {
439
469
  // for why the choice does not belong to the agent author.
440
470
  const frameworkStorage = selectFrameworkStorageDefinition({
441
471
  authored: options.project.storage,
472
+ architecture: options.project.agent.architecture,
442
473
  });
443
474
  this.storage =
444
475
  frameworkStorage === undefined
@@ -474,7 +505,10 @@ export class SessionEngine {
474
505
  // resolves them; the host-side MCP registry starts with the concrete
475
506
  // connections and gains the rest via setResolvedConnections.
476
507
  this.mcpHost = new McpHost(
477
- options.project.agent.connections.filter(
508
+ [
509
+ ...options.project.agent.connections,
510
+ ...(options.project.agent.hostConnections ?? []),
511
+ ].filter(
478
512
  (connection) => !isSymbolicConnectionTransport(connection.transport)
479
513
  )
480
514
  );
@@ -782,6 +816,13 @@ export class SessionEngine {
782
816
  message: string,
783
817
  options: EngineSendOptions = {}
784
818
  ): Promise<ChannelSession> {
819
+ if (isDuringHostedAdmission()) {
820
+ // Only sends that bypassed the admission capture stub (typically a
821
+ // startup-captured `onStart` send) reach the engine inside the
822
+ // admission window; running one would leak an invisible local session
823
+ // on a sessionless pod.
824
+ throw new HostedAdmissionLocalSendError();
825
+ }
785
826
  const identity =
786
827
  channelId === HTTP_CHANNEL_ID
787
828
  ? httpContinuationIdentity(this.project.httpChannel)
@@ -2148,27 +2189,17 @@ export class SessionEngine {
2148
2189
  * Connection names a cloud turn can only reach through the host connection
2149
2190
  * bridge on the tool MCP endpoint: filtered account connections without a
2150
2191
  * public bridge URL, and host-OAuth connections whose tokens live on this
2151
- * host. `hostOnly` names are never bridged — that flag means the model
2152
- * must not see the connection at all, on any runtime.
2192
+ * host.
2153
2193
  */
2154
2194
  cloudBridgeableConnectionNames(): string[] {
2155
- const hostOnlyNames = new Set(
2156
- this.project.agent.connections
2157
- .filter((connection) => connection.hostOnly === true)
2158
- .map((connection) => connection.name)
2159
- );
2160
2195
  const names: string[] = [];
2161
2196
  for (const connection of this.project.agent.connections) {
2162
- if (
2163
- !hostOnlyNames.has(connection.name) &&
2164
- isHostOauthConnectionTransport(connection.transport)
2165
- ) {
2197
+ if (isHostOauthConnectionTransport(connection.transport)) {
2166
2198
  names.push(connection.name);
2167
2199
  }
2168
2200
  }
2169
2201
  for (const resolved of this.resolvedConnections) {
2170
2202
  if (
2171
- !hostOnlyNames.has(resolved.name) &&
2172
2203
  resolved.accountServersFilter !== undefined &&
2173
2204
  resolved.cloudUrl === undefined
2174
2205
  ) {
@@ -2181,8 +2212,7 @@ export class SessionEngine {
2181
2212
  /**
2182
2213
  * True when cloud turns reach `name` through the host connection bridge —
2183
2214
  * the gate the tool MCP endpoint applies before forwarding a bridge
2184
- * request to `host.mcp`, so `hostOnly` connections (and arbitrary names)
2185
- * stay unreachable from a VM.
2215
+ * request to `host.mcp`, so arbitrary names stay unreachable from a VM.
2186
2216
  */
2187
2217
  isCloudBridgedConnection(name: string): boolean {
2188
2218
  if (this.cloudServerToolsConnection === undefined) {
@@ -2212,10 +2242,11 @@ export class SessionEngine {
2212
2242
  }
2213
2243
 
2214
2244
  /**
2215
- * Authored + resolved MCP servers for a turn. Skips `hostOnly`. On cloud
2216
- * turns, connections whose credential lives on this host filtered
2217
- * account connections without a public bridge URL, host-OAuth servers
2218
- * mount as host connection bridges over the tool MCP endpoint instead of
2245
+ * Authored + resolved MCP servers for a turn. Skips advertised
2246
+ * connections (those surface as named server tools). On cloud turns,
2247
+ * connections whose credential lives on this host filtered account
2248
+ * connections without a public bridge URL, host-OAuth servers mount
2249
+ * as host connection bridges over the tool MCP endpoint instead of
2219
2250
  * being omitted or failing the turn closed.
2220
2251
  */
2221
2252
  private buildMcpServers(
@@ -2229,16 +2260,17 @@ export class SessionEngine {
2229
2260
  return {};
2230
2261
  }
2231
2262
  // Advertised connections surface as named server tools instead of an
2232
- // attached MCP server (each tool appears exactly once), so they are
2233
- // excluded here alongside hostOnly.
2234
- const hostOnlyNames = new Set(
2263
+ // attached MCP server (each tool appears exactly once).
2264
+ const advertisedNames = new Set(
2235
2265
  this.project.agent.connections
2236
- .filter(
2237
- (connection) =>
2238
- connection.hostOnly === true || connection.advertiseTools === true
2239
- )
2266
+ .filter((connection) => connection.advertiseTools === true)
2240
2267
  .map((connection) => connection.name)
2241
2268
  );
2269
+ const hostConnectionNames = new Set(
2270
+ (this.project.agent.hostConnections ?? []).map(
2271
+ (connection) => connection.name
2272
+ )
2273
+ );
2242
2274
  const bridgedNames = new Set(
2243
2275
  runtime === "cloud" &&
2244
2276
  sessionId !== undefined &&
@@ -2250,7 +2282,9 @@ export class SessionEngine {
2250
2282
  assertCloudCanHonorAccountServersFilters({
2251
2283
  runtime,
2252
2284
  resolvedConnections: this.resolvedConnections.filter(
2253
- (resolved) => !hostOnlyNames.has(resolved.name)
2285
+ (resolved) =>
2286
+ !advertisedNames.has(resolved.name) &&
2287
+ !hostConnectionNames.has(resolved.name)
2254
2288
  ),
2255
2289
  bridgedNames,
2256
2290
  });
@@ -2260,7 +2294,10 @@ export class SessionEngine {
2260
2294
  : this.cloudBridgeTransport(sessionId, name);
2261
2295
  const servers: Record<string, ConnectionTransport> = {};
2262
2296
  for (const connection of this.project.agent.connections) {
2263
- if (hostOnlyNames.has(connection.name)) {
2297
+ if (
2298
+ advertisedNames.has(connection.name) ||
2299
+ hostConnectionNames.has(connection.name)
2300
+ ) {
2264
2301
  continue;
2265
2302
  }
2266
2303
  if (isSymbolicConnectionTransport(connection.transport)) {
@@ -2301,7 +2338,10 @@ export class SessionEngine {
2301
2338
  servers[connection.name] = connection.transport;
2302
2339
  }
2303
2340
  for (const resolved of this.resolvedConnections) {
2304
- if (hostOnlyNames.has(resolved.name)) {
2341
+ if (
2342
+ advertisedNames.has(resolved.name) ||
2343
+ hostConnectionNames.has(resolved.name)
2344
+ ) {
2305
2345
  continue;
2306
2346
  }
2307
2347
  const url = runtime === "cloud" ? resolved.cloudUrl : resolved.localUrl;
@@ -2346,16 +2386,14 @@ export class SessionEngine {
2346
2386
 
2347
2387
  /**
2348
2388
  * True when a connection with per-session `auth` attaches to the model
2349
- * (not `hostOnly`, not advertised). These turns set
2389
+ * (not advertised). These turns set
2350
2390
  * {@link RunnerTurnRequest.perSendMcpServers} so the evaluated headers
2351
2391
  * ride every send instead of being pinned on the cached agent handle.
2352
2392
  */
2353
2393
  private hasAttachedAuthedConnections(): boolean {
2354
2394
  return this.project.agent.connections.some(
2355
2395
  (connection) =>
2356
- connection.auth !== undefined &&
2357
- connection.hostOnly !== true &&
2358
- connection.advertiseTools !== true
2396
+ connection.auth !== undefined && connection.advertiseTools !== true
2359
2397
  );
2360
2398
  }
2361
2399
 
@@ -2371,9 +2409,7 @@ export class SessionEngine {
2371
2409
  ): Promise<ReadonlyMap<string, Record<string, string>> | undefined> {
2372
2410
  const authed = this.project.agent.connections.filter(
2373
2411
  (connection) =>
2374
- connection.auth !== undefined &&
2375
- connection.hostOnly !== true &&
2376
- connection.advertiseTools !== true
2412
+ connection.auth !== undefined && connection.advertiseTools !== true
2377
2413
  );
2378
2414
  if (authed.length === 0) {
2379
2415
  return undefined;
@@ -2783,12 +2819,168 @@ export class SessionEngine {
2783
2819
  * with the same `{ content, isError }` envelope the model would see, not
2784
2820
  * an exception.
2785
2821
  */
2822
+ /**
2823
+ * The session identity a direct call (or catalog listing) runs under:
2824
+ * an explicit sessionId, a continuation token resolved to a live (or
2825
+ * restorable) session with the same owner/busy checks a sessionId call
2826
+ * gets, or — when neither maps to a session — a synthetic identity
2827
+ * carrying the token's channel id and continuation key so binding
2828
+ * resolvers (e.g. VFS mounts) can still serve the call.
2829
+ */
2830
+ private async resolveDirectCallIdentity(
2831
+ callId: string,
2832
+ options: Pick<CallToolOptions, "auth" | "sessionId" | "continuationToken">
2833
+ ): Promise<{
2834
+ record: SessionRecord | undefined;
2835
+ session: SessionInfo;
2836
+ workspaceDir: string;
2837
+ scratchDir: string | undefined;
2838
+ }> {
2839
+ if (
2840
+ options.sessionId !== undefined &&
2841
+ options.continuationToken !== undefined
2842
+ ) {
2843
+ throw new InvalidContinuationTokenError(
2844
+ "mutually exclusive with sessionId — a real session already carries its own continuation key"
2845
+ );
2846
+ }
2847
+ const auth = options.auth ?? null;
2848
+ let record: SessionRecord | undefined;
2849
+ let continuation: { channelId: string; key: string } | null = null;
2850
+ if (options.sessionId !== undefined) {
2851
+ record = await this.sessions.get(options.sessionId);
2852
+ if (record === undefined) {
2853
+ throw new UnknownSessionError(options.sessionId);
2854
+ }
2855
+ } else if (options.continuationToken !== undefined) {
2856
+ continuation = parseContinuationToken(options.continuationToken);
2857
+ if (continuation === null) {
2858
+ throw new InvalidContinuationTokenError(
2859
+ `expected "<channelId>:<key>" (as /v1/sessions lists it), got "${options.continuationToken}"`
2860
+ );
2861
+ }
2862
+ // A token that maps to a live (or restorable) session takes the
2863
+ // session path: same owner check, same turn serialization, same
2864
+ // event recording as an explicit sessionId. Skipping those just
2865
+ // because the caller addressed the session by token would fail open.
2866
+ record =
2867
+ (await this.sessions.findByContinuation(
2868
+ continuation.channelId,
2869
+ continuation.key
2870
+ )) ??
2871
+ (await this.restoreSessionByContinuation(
2872
+ continuation.channelId,
2873
+ continuation.key
2874
+ ));
2875
+ if (record !== undefined && !samePrincipal(record.auth, auth)) {
2876
+ throw new SessionAuthError(record.sessionId);
2877
+ }
2878
+ }
2879
+ if (record !== undefined) {
2880
+ // Direct calls respect the same serialization as follow-up sends: a
2881
+ // running model turn owns the session workspace and event stream.
2882
+ if (
2883
+ this.activeTurns.has(record.sessionId) ||
2884
+ this.pendingTurns.has(record.sessionId)
2885
+ ) {
2886
+ throw new SessionBusyError(record.sessionId);
2887
+ }
2888
+ return {
2889
+ record,
2890
+ session: this.sessionInfo(record),
2891
+ workspaceDir: this.harnessCwd(record),
2892
+ scratchDir: undefined,
2893
+ };
2894
+ }
2895
+ // No session behind the token (or no token at all): a synthetic
2896
+ // session carries the token's channel id and key, so binding resolvers
2897
+ // keyed on the continuation key (e.g. VFS mounts) can serve the call
2898
+ // with no live session. The workspace stays scratch and nothing is
2899
+ // recorded on a session event stream.
2900
+ const scratchDir = join(this.stateRoot, "tool-calls", callId);
2901
+ return {
2902
+ record: undefined,
2903
+ session: {
2904
+ id: callId,
2905
+ channelId: continuation?.channelId ?? DIRECT_TOOL_CALL_CHANNEL_ID,
2906
+ mode: "task",
2907
+ continuationKey: continuation?.key,
2908
+ auth,
2909
+ },
2910
+ workspaceDir: scratchDir,
2911
+ scratchDir,
2912
+ };
2913
+ }
2914
+
2915
+ /**
2916
+ * The live tool catalog for one session identity: authored server tools
2917
+ * plus the advertised passthroughs a turn under the same identity would
2918
+ * see, under their model-facing names. A connection whose listing fails
2919
+ * is skipped and reported in `connectionErrors` — the inspection surface
2920
+ * degrades legibly instead of hiding every other tool behind one broken
2921
+ * connector.
2922
+ */
2923
+ async listCatalogTools(
2924
+ options: Pick<
2925
+ CallToolOptions,
2926
+ "auth" | "sessionId" | "continuationToken"
2927
+ > = {}
2928
+ ): Promise<{
2929
+ tools: DiscoveredTool[];
2930
+ connectionErrors: Array<{ connection: string; message: string }>;
2931
+ }> {
2932
+ const { session } = await this.resolveDirectCallIdentity(
2933
+ newToolCallId("catalog"),
2934
+ options
2935
+ );
2936
+ const connectionErrors: Array<{ connection: string; message: string }> = [];
2937
+ const advertised = await resolveAdvertisedTools({
2938
+ agent: this.project.agent,
2939
+ session,
2940
+ hostMcp: this.mcpHost,
2941
+ onConnectionError: (connection, error) => {
2942
+ connectionErrors.push({
2943
+ connection,
2944
+ message: error instanceof Error ? error.message : String(error),
2945
+ });
2946
+ },
2947
+ });
2948
+ return {
2949
+ tools: [...this.project.agent.tools, ...advertised],
2950
+ connectionErrors,
2951
+ };
2952
+ }
2953
+
2786
2954
  async callTool(
2787
2955
  toolName: string,
2788
2956
  input: unknown = {},
2789
2957
  options: CallToolOptions = {}
2790
2958
  ): Promise<ToolCallOutcome> {
2791
- const tool = this.project.agent.tools.find((t) => t.name === toolName);
2959
+ const callId = newToolCallId(toolName);
2960
+ // Identity resolves before the tool lookup: advertised connection tools
2961
+ // only exist relative to a session (per-session auth), so finding them
2962
+ // needs the same identity the call runs under.
2963
+ const identity = await this.resolveDirectCallIdentity(callId, options);
2964
+ const record = identity.record;
2965
+ const session = identity.session;
2966
+ let workspaceDir = identity.workspaceDir;
2967
+ let scratchDir = identity.scratchDir;
2968
+ let tool = this.project.agent.tools.find((t) => t.name === toolName);
2969
+ if (
2970
+ tool === undefined &&
2971
+ this.project.agent.connections.some((c) => c.advertiseTools === true)
2972
+ ) {
2973
+ // Advertised passthroughs are ordinary server tools in the session's
2974
+ // namespace; resolve the live listing so direct calls address them by
2975
+ // the same model-facing name a turn would. A listing failure fails
2976
+ // the call closed, like it fails a turn.
2977
+ const advertised = await resolveAdvertisedTools({
2978
+ agent: this.project.agent,
2979
+ session,
2980
+ hostMcp: this.mcpHost,
2981
+ });
2982
+ tool = advertised.find((t) => t.name === toolName);
2983
+ }
2792
2984
  if (tool === undefined) {
2793
2985
  throw new UnknownToolError(
2794
2986
  toolName,
@@ -2805,47 +2997,51 @@ export class SessionEngine {
2805
2997
  if (!validation.ok) {
2806
2998
  throw new ToolInputError({ toolName, detail: validation.message });
2807
2999
  }
2808
-
2809
- const callId = newToolCallId(toolName);
2810
- const auth = options.auth ?? null;
2811
- let record: SessionRecord | undefined;
2812
- let session: SessionInfo;
2813
- let workspaceDir: string;
2814
- let scratchDir: string | undefined;
2815
- if (options.sessionId !== undefined) {
2816
- record = await this.sessions.get(options.sessionId);
3000
+ let workspaceUnavailable = false;
3001
+ try {
3002
+ await mkdir(workspaceDir, { recursive: true });
3003
+ } catch (error) {
2817
3004
  if (record === undefined) {
2818
- throw new UnknownSessionError(options.sessionId);
3005
+ throw error;
2819
3006
  }
2820
- // Direct calls respect the same serialization as follow-up sends: a
2821
- // running model turn owns the session workspace and event stream.
2822
- if (
2823
- this.activeTurns.has(record.sessionId) ||
2824
- this.pendingTurns.has(record.sessionId)
2825
- ) {
2826
- throw new SessionBusyError(record.sessionId);
3007
+ // A session's harness cwd can be a path the serving process cannot
3008
+ // create (e.g. an absolute `local.cwd` like /repo on a hosted pod
3009
+ // where the sandboxed harness would have made it). Read-effect calls
3010
+ // fall back to a scratch workspace instead of failing: tools that
3011
+ // resolve their state from the session identity (VFS mounts) never
3012
+ // touch ctx.workspaceDir. Advertised passthroughs are relocatable by
3013
+ // construction: their execute body forwards to the connection and
3014
+ // never reads the workspace. A write (or undeclared, which resolves
3015
+ // to write) authored tool may rely on ctx.workspaceDir being the
3016
+ // real session workspace, so silently relocating it is not safe —
3017
+ // fail typed instead.
3018
+ const relocatable =
3019
+ tool.advertised === true ||
3020
+ resolveEffect(tool.definition.effect, validation.value) === "read";
3021
+ if (!relocatable) {
3022
+ throw new WorkspaceUnavailableError(toolName, error);
2827
3023
  }
2828
- session = this.sessionInfo(record);
2829
- workspaceDir = this.harnessCwd(record);
2830
- } else {
2831
- session = {
2832
- id: callId,
2833
- channelId: DIRECT_TOOL_CALL_CHANNEL_ID,
2834
- mode: "task",
2835
- auth,
2836
- };
3024
+ this.logger(
3025
+ `[session] tool ${toolName} workspace unavailable (direct ${callId}); using scratch: ${
3026
+ error instanceof Error ? error.message : String(error)
3027
+ }`
3028
+ );
2837
3029
  scratchDir = join(this.stateRoot, "tool-calls", callId);
2838
3030
  workspaceDir = scratchDir;
3031
+ workspaceUnavailable = true;
3032
+ await mkdir(workspaceDir, { recursive: true });
2839
3033
  }
2840
- await mkdir(workspaceDir, { recursive: true });
2841
3034
  // Match what a model turn would see: session workspaces get the same
2842
3035
  // scaffold as executeTurn (seeds only before the first turn); scratch
2843
3036
  // workspaces are materialized fresh.
2844
3037
  await materializeWorkspace({
2845
3038
  agent: this.project.agent,
2846
3039
  workspaceDir:
2847
- record === undefined ? workspaceDir : this.scaffoldDir(record),
2848
- seed: record === undefined || record.turnCount === 0,
3040
+ record === undefined || workspaceUnavailable
3041
+ ? workspaceDir
3042
+ : this.scaffoldDir(record),
3043
+ seed:
3044
+ record === undefined || workspaceUnavailable || record.turnCount === 0,
2849
3045
  stateRoot: this.stateRoot,
2850
3046
  });
2851
3047
 
@@ -2981,8 +3177,9 @@ export class SessionEngine {
2981
3177
  isError,
2982
3178
  result,
2983
3179
  durationMs,
2984
- ...(errorMessage === undefined ? {} : { errorMessage }),
2985
- ...(record === undefined ? {} : { sessionId: record.sessionId }),
3180
+ errorMessage,
3181
+ sessionId: record?.sessionId,
3182
+ scratchWorkspace: workspaceUnavailable ? true : undefined,
2986
3183
  };
2987
3184
  }
2988
3185
 
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Projections for the live tool catalog (`GET /v1/tools` and
3
+ * `GET /v1/tools/:name`): the session's tool namespace exactly as a turn
4
+ * would assemble it — authored server tools plus advertised MCP
5
+ * passthroughs — under model-facing names.
6
+ *
7
+ * Titles are curated data, never derived from descriptions: advertised
8
+ * tools inherit the upstream server's MCP `annotations.title` (bounded at
9
+ * listing time), and the well-known non-MCP tool names carry a hardcoded
10
+ * title here so every deployment shows the same display names.
11
+ */
12
+
13
+ import type {
14
+ DiscoveredTool,
15
+ JsonSchemaObject,
16
+ ToolEffect,
17
+ ToolExecution,
18
+ } from "../types.js";
19
+
20
+ /**
21
+ * Display names for the well-known tool names that do not come from MCP
22
+ * (authored tools have no title field; adding one to `defineTool` for a
23
+ * presentation concern is not worth the authoring surface).
24
+ */
25
+ const WELL_KNOWN_TOOL_TITLES: Readonly<Record<string, string>> = {
26
+ diff: "Show change diffs",
27
+ glob: "Find files by pattern",
28
+ grep: "Search file contents",
29
+ ls: "List a directory",
30
+ read: "Read a file",
31
+ search: "Search with a typed query",
32
+ write: "Write a file",
33
+ };
34
+
35
+ function catalogTitle(tool: DiscoveredTool): string | undefined {
36
+ if (tool.advertised === true) {
37
+ return tool.annotations?.title;
38
+ }
39
+ return WELL_KNOWN_TOOL_TITLES[tool.name];
40
+ }
41
+
42
+ /**
43
+ * Sand connector identifiers scope the connector name by owner
44
+ * (`dashboard-team-<id>-Buildkite`, `dashboard-<Name>`, `user-<Name>`);
45
+ * the suffix is the human-meaningful name.
46
+ */
47
+ const CONNECTOR_SCOPE_PREFIX = /^(?:dashboard-team-\d+-|dashboard-|user-)/;
48
+
49
+ /**
50
+ * Where a tool comes from, for humans: the upstream connector/plugin name
51
+ * when the tool declares one (the reserved `__conn__` selector's values
52
+ * name it), the connection name otherwise. One aggregating connection
53
+ * (e.g. a tenant `plugins` endpoint) hosts tools from several connectors,
54
+ * and "plugins" tells an operator nothing — "Buildkite" does.
55
+ */
56
+ function catalogSource(tool: DiscoveredTool): string | undefined {
57
+ if (tool.advertised !== true) {
58
+ return undefined;
59
+ }
60
+ const properties = tool.inputSchema.properties as
61
+ | Record<string, { enum?: unknown[] } | undefined>
62
+ | undefined;
63
+ const first = properties?.__conn__?.enum?.[0];
64
+ if (typeof first === "string" && first !== "") {
65
+ return first.replace(CONNECTOR_SCOPE_PREFIX, "");
66
+ }
67
+ return tool.connection;
68
+ }
69
+
70
+ /** Light listing entry: identifiers and curated display data only. */
71
+ export interface CatalogListEntry {
72
+ name: string;
73
+ title?: string;
74
+ /** Connection name for advertised MCP tools; absent for authored tools. */
75
+ source?: string;
76
+ }
77
+
78
+ /** Full description behind `GET /v1/tools/:name`. */
79
+ export interface CatalogDetailEntry extends CatalogListEntry {
80
+ description: string;
81
+ execution: ToolExecution;
82
+ needsApproval: boolean;
83
+ effect?: ToolEffect | "dynamic";
84
+ inputSchema: JsonSchemaObject;
85
+ outputSchema?: JsonSchemaObject;
86
+ }
87
+
88
+ export function catalogListEntry(tool: DiscoveredTool): CatalogListEntry {
89
+ return {
90
+ name: tool.name,
91
+ title: catalogTitle(tool),
92
+ source: catalogSource(tool),
93
+ };
94
+ }
95
+
96
+ export function catalogDetailEntry(tool: DiscoveredTool): CatalogDetailEntry {
97
+ return {
98
+ ...catalogListEntry(tool),
99
+ description: tool.description,
100
+ execution: tool.execution,
101
+ needsApproval: tool.needsApproval,
102
+ effect: tool.effect,
103
+ inputSchema: tool.inputSchema,
104
+ outputSchema: tool.outputSchema,
105
+ };
106
+ }
@@ -74,8 +74,13 @@ export interface CursorHostedStorageOptions {
74
74
  * `https://api.cursor.com`).
75
75
  */
76
76
  baseUrl?: string;
77
- /** Bearer credential (default: `CURSOR_API_KEY`). */
78
- apiKey?: string;
77
+ /**
78
+ * Bearer credential (default: `CURSOR_API_KEY`). A function is
79
+ * re-resolved on every call: hosted freeze snapshots listen unsigned and
80
+ * bind the key file after serve start, so a value captured at construct
81
+ * time would be permanently absent.
82
+ */
83
+ apiKey?: string | (() => string | undefined);
79
84
  /** Injected for tests. */
80
85
  fetch?: typeof fetch;
81
86
  }
@@ -180,7 +185,9 @@ function toCasResult(response: KvCasResponse): KvCasResult {
180
185
  }
181
186
 
182
187
  function resolveApiKey(options: CursorHostedStorageOptions): string {
183
- const key = (options.apiKey ?? process.env.CURSOR_API_KEY)?.trim();
188
+ const configured =
189
+ typeof options.apiKey === "function" ? options.apiKey() : options.apiKey;
190
+ const key = (configured ?? process.env.CURSOR_API_KEY)?.trim();
184
191
  if (key === undefined || key === "") {
185
192
  throw new Error(
186
193
  "cursorHostedStorage requires CURSOR_API_KEY (deployment pod credential on Cursor hosting)"