@cursor/july 0.1.99 → 0.1.101

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 (420) hide show
  1. package/AGENTS.md +4 -2
  2. package/dist/bin/agent-serve.js +3 -2
  3. package/dist/channels/deployments/deployments-channel.d.ts +41 -5
  4. package/dist/channels/deployments/deployments-channel.d.ts.map +1 -1
  5. package/dist/channels/deployments/deployments-channel.js +88 -8
  6. package/dist/channels/deployments/types.d.ts +4 -3
  7. package/dist/channels/deployments/types.d.ts.map +1 -1
  8. package/dist/channels/github/defaults.d.ts.map +1 -1
  9. package/dist/channels/github/defaults.js +28 -3
  10. package/dist/channels/github/progress.d.ts +7 -0
  11. package/dist/channels/github/progress.d.ts.map +1 -1
  12. package/dist/channels/origin/defaults.d.ts +43 -0
  13. package/dist/channels/origin/defaults.d.ts.map +1 -0
  14. package/dist/channels/origin/defaults.js +111 -0
  15. package/dist/channels/origin/index.d.ts +2 -0
  16. package/dist/channels/origin/index.d.ts.map +1 -1
  17. package/dist/channels/origin/index.js +2 -0
  18. package/dist/channels/origin/origin-channel.d.ts +2 -1
  19. package/dist/channels/origin/origin-channel.d.ts.map +1 -1
  20. package/dist/channels/origin/origin-channel.js +24 -3
  21. package/dist/channels/origin/state.d.ts +32 -0
  22. package/dist/channels/origin/state.d.ts.map +1 -0
  23. package/dist/channels/origin/state.js +23 -0
  24. package/dist/channels/origin/types.d.ts +23 -1
  25. package/dist/channels/origin/types.d.ts.map +1 -1
  26. package/dist/channels/slack/api.d.ts +16 -7
  27. package/dist/channels/slack/api.d.ts.map +1 -1
  28. package/dist/channels/slack/api.js +31 -14
  29. package/dist/channels/slack/code-fences.d.ts +17 -0
  30. package/dist/channels/slack/code-fences.d.ts.map +1 -0
  31. package/dist/channels/slack/code-fences.js +168 -0
  32. package/dist/channels/slack/constants.d.ts +6 -0
  33. package/dist/channels/slack/constants.d.ts.map +1 -1
  34. package/dist/channels/slack/constants.js +6 -0
  35. package/dist/channels/slack/defaults.d.ts +9 -4
  36. package/dist/channels/slack/defaults.d.ts.map +1 -1
  37. package/dist/channels/slack/defaults.js +154 -76
  38. package/dist/channels/slack/dispatch.d.ts.map +1 -1
  39. package/dist/channels/slack/dispatch.js +3 -3
  40. package/dist/channels/slack/inbound.d.ts +9 -0
  41. package/dist/channels/slack/inbound.d.ts.map +1 -1
  42. package/dist/channels/slack/inbound.js +14 -0
  43. package/dist/channels/slack/index.d.ts +2 -0
  44. package/dist/channels/slack/index.d.ts.map +1 -1
  45. package/dist/channels/slack/index.js +2 -0
  46. package/dist/channels/slack/live-delivery.d.ts +5 -0
  47. package/dist/channels/slack/live-delivery.d.ts.map +1 -1
  48. package/dist/channels/slack/live-delivery.js +116 -21
  49. package/dist/channels/slack/reasoning-card.d.ts +38 -0
  50. package/dist/channels/slack/reasoning-card.d.ts.map +1 -0
  51. package/dist/channels/slack/reasoning-card.js +104 -0
  52. package/dist/channels/slack/redact.d.ts +2 -0
  53. package/dist/channels/slack/redact.d.ts.map +1 -0
  54. package/dist/channels/slack/redact.js +5 -0
  55. package/dist/channels/slack/reply-options.d.ts +40 -0
  56. package/dist/channels/slack/reply-options.d.ts.map +1 -0
  57. package/dist/channels/slack/reply-options.js +150 -0
  58. package/dist/channels/slack/slack-channel.d.ts.map +1 -1
  59. package/dist/channels/slack/slack-channel.js +8 -4
  60. package/dist/channels/slack/stream.d.ts +22 -10
  61. package/dist/channels/slack/stream.d.ts.map +1 -1
  62. package/dist/channels/slack/stream.js +9 -16
  63. package/dist/channels/slack/tool-cards.d.ts +22 -0
  64. package/dist/channels/slack/tool-cards.d.ts.map +1 -0
  65. package/dist/channels/slack/tool-cards.js +178 -0
  66. package/dist/channels/slack/types.d.ts +145 -6
  67. package/dist/channels/slack/types.d.ts.map +1 -1
  68. package/dist/connections.d.ts +18 -2
  69. package/dist/connections.d.ts.map +1 -1
  70. package/dist/connections.js +18 -2
  71. package/dist/docs/404.html +2 -2
  72. package/dist/docs/ab.html +6 -6
  73. package/dist/docs/ab.md +1 -1
  74. package/dist/docs/assets/{ab.md.DJo5r4R-.js → ab.md.mlVgqvSk.js} +1 -1
  75. package/dist/docs/assets/{app.BplEAZ3S.js → app.BASO9Kih.js} +1 -1
  76. package/dist/docs/assets/{building-with-agents.md.DI4mEzlt.js → building-with-agents.md.CUSWxlP_.js} +2 -2
  77. package/dist/docs/assets/chunks/@localSearchIndexroot.DbFXINq2.js +1 -0
  78. package/dist/docs/assets/chunks/{VPLocalSearchBox.CHXyv4wP.js → VPLocalSearchBox.DwkqxoE0.js} +1 -1
  79. package/dist/docs/assets/chunks/{theme.BTcsZmjQ.js → theme.CCil_13e.js} +2 -2
  80. package/dist/docs/assets/{evals.md.lfJoEVc8.js → evals.md.CPzDAwoH.js} +1 -1
  81. package/dist/docs/assets/{guides_github.md.Cnh2mL4a.js → guides_github.md.BtPr9GaP.js} +1 -1
  82. package/dist/docs/assets/{guides_mcp-oauth.md.CN-6YmTJ.js → guides_mcp-oauth.md.Dp6cDP7f.js} +1 -1
  83. package/dist/docs/assets/{guides_opentelemetry.md.bmPmkvJu.js → guides_opentelemetry.md.BVTXDCRg.js} +2 -2
  84. package/dist/docs/assets/{guides_slack.md.VDXQV3ja.js → guides_slack.md.9oHPye9o.js} +19 -3
  85. package/dist/docs/assets/{guides_slack.md.VDXQV3ja.lean.js → guides_slack.md.9oHPye9o.lean.js} +1 -1
  86. package/dist/docs/assets/hillclimbing.md.CpTGTCle.js +4 -0
  87. package/dist/docs/assets/{index.md.CVeRUOeZ.js → index.md.Bb4k8kUm.js} +1 -1
  88. package/dist/docs/assets/{quickstart.md.Nj_LjW_a.js → quickstart.md.DdQOF7Y8.js} +1 -1
  89. package/dist/docs/assets/{reference_connections.md.DxldvyIB.js → reference_connections.md.Di6jJAXF.js} +13 -3
  90. package/dist/docs/assets/{reference_connections.md.DxldvyIB.lean.js → reference_connections.md.Di6jJAXF.lean.js} +1 -1
  91. package/dist/docs/assets/{reference_http-api.md.BEJx9XVj.js → reference_http-api.md.oySXBO8o.js} +1 -1
  92. package/dist/docs/assets/scaffolding-agents.md.em43xlY1.js +1 -0
  93. package/dist/docs/assets/skills_ab.md.CsFNatVx.js +26 -0
  94. package/dist/docs/assets/skills_ab.md.CsFNatVx.lean.js +1 -0
  95. package/dist/docs/assets/skills_create-agent.md.BVoWPcan.js +8 -0
  96. package/dist/docs/assets/skills_create-agent.md.BVoWPcan.lean.js +1 -0
  97. package/dist/docs/assets/skills_debug.md.CDbPhHfg.js +1 -0
  98. package/dist/docs/assets/skills_debug.md.CDbPhHfg.lean.js +1 -0
  99. package/dist/docs/assets/skills_evals.md.723kpUmA.js +25 -0
  100. package/dist/docs/assets/skills_evals.md.723kpUmA.lean.js +1 -0
  101. package/dist/docs/assets/skills_framework-map.md.BTi817yv.js +1 -0
  102. package/dist/docs/assets/skills_framework-map.md.BTi817yv.lean.js +1 -0
  103. package/dist/docs/assets/skills_github.md.D0JahM8c.js +16 -0
  104. package/dist/docs/assets/skills_github.md.D0JahM8c.lean.js +1 -0
  105. package/dist/docs/assets/skills_hillclimb.md.B_zJerxA.js +7 -0
  106. package/dist/docs/assets/skills_hillclimb.md.B_zJerxA.lean.js +1 -0
  107. package/dist/docs/assets/skills_index.md.DKwIxzGg.js +1 -0
  108. package/dist/docs/assets/skills_index.md.DKwIxzGg.lean.js +1 -0
  109. package/dist/docs/assets/skills_mcp-auth.md.DGvFP3HE.js +18 -0
  110. package/dist/docs/assets/skills_mcp-auth.md.DGvFP3HE.lean.js +1 -0
  111. package/dist/docs/assets/skills_otel.md.CgiZryR3.js +8 -0
  112. package/dist/docs/assets/skills_otel.md.CgiZryR3.lean.js +1 -0
  113. package/dist/docs/assets/skills_setup-slack.md.BBgx8lUz.js +20 -0
  114. package/dist/docs/assets/skills_setup-slack.md.BBgx8lUz.lean.js +1 -0
  115. package/dist/docs/assets/{troubleshooting.md.DCiPBhYs.js → troubleshooting.md.Cus_YZga.js} +1 -1
  116. package/dist/docs/building-with-agents.html +6 -6
  117. package/dist/docs/building-with-agents.md +14 -11
  118. package/dist/docs/concepts.html +4 -4
  119. package/dist/docs/deployment.html +4 -4
  120. package/dist/docs/evals.html +6 -6
  121. package/dist/docs/evals.md +1 -1
  122. package/dist/docs/guides/agent-to-agent.html +4 -4
  123. package/dist/docs/guides/cloud-runtime.html +4 -4
  124. package/dist/docs/guides/convert-automation.html +4 -4
  125. package/dist/docs/guides/github.html +5 -5
  126. package/dist/docs/guides/github.md +1 -1
  127. package/dist/docs/guides/human-in-the-loop.html +4 -4
  128. package/dist/docs/guides/mcp-oauth.html +5 -5
  129. package/dist/docs/guides/mcp-oauth.md +1 -1
  130. package/dist/docs/guides/opentelemetry.html +7 -7
  131. package/dist/docs/guides/opentelemetry.md +2 -2
  132. package/dist/docs/guides/slack.html +22 -6
  133. package/dist/docs/guides/slack.md +80 -1
  134. package/dist/docs/guides/webhooks.html +5 -5
  135. package/dist/docs/hashmap.json +1 -1
  136. package/dist/docs/hillclimbing.html +6 -6
  137. package/dist/docs/hillclimbing.md +5 -5
  138. package/dist/docs/index.html +6 -6
  139. package/dist/docs/index.md +1 -1
  140. package/dist/docs/llms-full.txt +1073 -31
  141. package/dist/docs/llms.txt +14 -0
  142. package/dist/docs/quickstart.html +5 -5
  143. package/dist/docs/quickstart.md +1 -1
  144. package/dist/docs/reference/agent-config.html +4 -4
  145. package/dist/docs/reference/artifacts.html +4 -4
  146. package/dist/docs/reference/channels.html +4 -4
  147. package/dist/docs/reference/cli.html +4 -4
  148. package/dist/docs/reference/connections.html +17 -7
  149. package/dist/docs/reference/connections.md +32 -1
  150. package/dist/docs/reference/hooks.html +4 -4
  151. package/dist/docs/reference/http-api.html +6 -6
  152. package/dist/docs/reference/http-api.md +1 -1
  153. package/dist/docs/reference/instructions.html +4 -4
  154. package/dist/docs/reference/playground.html +4 -4
  155. package/dist/docs/reference/project-layout.html +4 -4
  156. package/dist/docs/reference/prompt.html +4 -4
  157. package/dist/docs/reference/schedules.html +4 -4
  158. package/dist/docs/reference/sessions.html +4 -4
  159. package/dist/docs/reference/skills.html +4 -4
  160. package/dist/docs/reference/subagents.html +4 -4
  161. package/dist/docs/reference/tools.html +4 -4
  162. package/dist/docs/scaffolding-agents.html +5 -5
  163. package/dist/docs/scaffolding-agents.md +3 -3
  164. package/dist/docs/skills/ab.html +52 -0
  165. package/dist/docs/skills/ab.md +50 -0
  166. package/dist/docs/skills/create-agent.html +34 -0
  167. package/dist/docs/skills/create-agent.md +160 -0
  168. package/dist/docs/skills/debug.html +27 -0
  169. package/dist/docs/skills/debug.md +36 -0
  170. package/dist/docs/skills/evals.html +51 -0
  171. package/dist/docs/skills/evals.md +99 -0
  172. package/dist/docs/skills/framework-map.html +27 -0
  173. package/dist/docs/skills/framework-map.md +95 -0
  174. package/dist/docs/skills/github.html +42 -0
  175. package/dist/docs/skills/github.md +93 -0
  176. package/dist/docs/skills/hillclimb.html +33 -0
  177. package/dist/docs/skills/hillclimb.md +55 -0
  178. package/dist/docs/skills/index.html +27 -0
  179. package/dist/docs/skills/index.md +21 -0
  180. package/dist/docs/skills/mcp-auth.html +44 -0
  181. package/dist/docs/skills/mcp-auth.md +76 -0
  182. package/dist/docs/skills/otel.html +34 -0
  183. package/dist/docs/skills/otel.md +48 -0
  184. package/dist/docs/skills/setup-slack.html +46 -0
  185. package/dist/docs/skills/setup-slack.md +141 -0
  186. package/dist/docs/storage.html +4 -4
  187. package/dist/docs/templates/agentic-owners.html +4 -4
  188. package/dist/docs/templates/agents-md.html +4 -4
  189. package/dist/docs/templates/code-wiki.html +4 -4
  190. package/dist/docs/templates/demo.html +4 -4
  191. package/dist/docs/templates/pr-autofixer.html +4 -4
  192. package/dist/docs/templates/security-help.html +4 -4
  193. package/dist/docs/templates/security-reviewer.html +4 -4
  194. package/dist/docs/templates/triage.html +4 -4
  195. package/dist/docs/troubleshooting.html +5 -5
  196. package/dist/docs/troubleshooting.md +1 -1
  197. package/dist/extensions/cursor-cloud-agents/extension.d.ts +55 -0
  198. package/dist/extensions/cursor-cloud-agents/extension.d.ts.map +1 -0
  199. package/dist/extensions/cursor-cloud-agents/extension.js +64 -0
  200. package/dist/extensions/cursor-cloud-agents/lib/cloud.d.ts +30 -0
  201. package/dist/extensions/cursor-cloud-agents/lib/cloud.d.ts.map +1 -0
  202. package/dist/extensions/cursor-cloud-agents/lib/cloud.js +45 -0
  203. package/dist/extensions/cursor-cloud-agents/lib/fleet.d.ts +25 -0
  204. package/dist/extensions/cursor-cloud-agents/lib/fleet.d.ts.map +1 -0
  205. package/dist/extensions/cursor-cloud-agents/lib/fleet.js +85 -0
  206. package/dist/extensions/cursor-cloud-agents/lib/repos.d.ts +15 -0
  207. package/dist/extensions/cursor-cloud-agents/lib/repos.d.ts.map +1 -0
  208. package/dist/extensions/cursor-cloud-agents/lib/repos.js +55 -0
  209. package/dist/extensions/cursor-cloud-agents/skills/handoff.md +27 -0
  210. package/dist/extensions/cursor-cloud-agents/tools/follow_up.d.ts +4 -0
  211. package/dist/extensions/cursor-cloud-agents/tools/follow_up.d.ts.map +1 -0
  212. package/dist/extensions/cursor-cloud-agents/tools/follow_up.js +37 -0
  213. package/dist/extensions/cursor-cloud-agents/tools/launch.d.ts +4 -0
  214. package/dist/extensions/cursor-cloud-agents/tools/launch.d.ts.map +1 -0
  215. package/dist/extensions/cursor-cloud-agents/tools/launch.js +83 -0
  216. package/dist/extensions/cursor-cloud-agents/tools/list.d.ts +4 -0
  217. package/dist/extensions/cursor-cloud-agents/tools/list.d.ts.map +1 -0
  218. package/dist/extensions/cursor-cloud-agents/tools/list.js +36 -0
  219. package/dist/extensions/cursor-cloud-agents/tools/status.d.ts +4 -0
  220. package/dist/extensions/cursor-cloud-agents/tools/status.d.ts.map +1 -0
  221. package/dist/extensions/cursor-cloud-agents/tools/status.js +41 -0
  222. package/dist/extensions.d.ts +49 -0
  223. package/dist/extensions.d.ts.map +1 -0
  224. package/dist/extensions.js +75 -0
  225. package/dist/files-backends/cursor-hosted.d.ts +6 -0
  226. package/dist/files-backends/cursor-hosted.d.ts.map +1 -1
  227. package/dist/files-backends/cursor-hosted.js +6 -9
  228. package/dist/index.d.ts +2 -1
  229. package/dist/index.d.ts.map +1 -1
  230. package/dist/index.js +2 -1
  231. package/dist/internal/advertise-tools.d.ts +4 -1
  232. package/dist/internal/advertise-tools.d.ts.map +1 -1
  233. package/dist/internal/advertise-tools.js +20 -1
  234. package/dist/internal/as-of.d.ts +18 -0
  235. package/dist/internal/as-of.d.ts.map +1 -1
  236. package/dist/internal/as-of.js +131 -0
  237. package/dist/internal/cli-deploy.d.ts.map +1 -1
  238. package/dist/internal/cli-deploy.js +66 -21
  239. package/dist/internal/continuation-identity.d.ts.map +1 -1
  240. package/dist/internal/continuation-identity.js +3 -1
  241. package/dist/internal/conversation-mirror.d.ts.map +1 -1
  242. package/dist/internal/conversation-mirror.js +3 -4
  243. package/dist/internal/cursor/hosted-deployment-secrets.d.ts +16 -0
  244. package/dist/internal/cursor/hosted-deployment-secrets.d.ts.map +1 -0
  245. package/dist/internal/cursor/hosted-deployment-secrets.js +61 -0
  246. package/dist/internal/cursor/hosted-store-secrets.d.ts +15 -0
  247. package/dist/internal/cursor/hosted-store-secrets.d.ts.map +1 -0
  248. package/dist/internal/cursor/hosted-store-secrets.js +48 -0
  249. package/dist/internal/cursor-deployment-relay.d.ts +15 -1
  250. package/dist/internal/cursor-deployment-relay.d.ts.map +1 -1
  251. package/dist/internal/cursor-deployment-relay.js +46 -7
  252. package/dist/internal/deploy-client.d.ts +29 -6
  253. package/dist/internal/deploy-client.d.ts.map +1 -1
  254. package/dist/internal/deploy-client.js +61 -19
  255. package/dist/internal/discovery.d.ts.map +1 -1
  256. package/dist/internal/discovery.js +426 -121
  257. package/dist/internal/distribution.d.ts.map +1 -1
  258. package/dist/internal/distribution.js +5 -0
  259. package/dist/internal/framework-file-storage.d.ts +15 -8
  260. package/dist/internal/framework-file-storage.d.ts.map +1 -1
  261. package/dist/internal/framework-file-storage.js +70 -10
  262. package/dist/internal/framework-storage-selection.d.ts +12 -12
  263. package/dist/internal/framework-storage-selection.d.ts.map +1 -1
  264. package/dist/internal/framework-storage-selection.js +33 -39
  265. package/dist/internal/hosted-delivery.d.ts +3 -1
  266. package/dist/internal/hosted-delivery.d.ts.map +1 -1
  267. package/dist/internal/hosted-delivery.js +19 -32
  268. package/dist/internal/hosted-execution-diag.d.ts +5 -0
  269. package/dist/internal/hosted-execution-diag.d.ts.map +1 -1
  270. package/dist/internal/hosted-execution-diag.js +5 -0
  271. package/dist/internal/hosted-execution-flush.d.ts +46 -0
  272. package/dist/internal/hosted-execution-flush.d.ts.map +1 -0
  273. package/dist/internal/hosted-execution-flush.js +81 -0
  274. package/dist/internal/mcp-endpoint.js +1 -0
  275. package/dist/internal/mcp-host.d.ts +2 -1
  276. package/dist/internal/mcp-host.d.ts.map +1 -1
  277. package/dist/internal/mcp-host.js +35 -15
  278. package/dist/internal/review-comments.d.ts +1 -1
  279. package/dist/internal/review-comments.d.ts.map +1 -1
  280. package/dist/internal/review-comments.js +4 -4
  281. package/dist/internal/server.d.ts +3 -0
  282. package/dist/internal/server.d.ts.map +1 -1
  283. package/dist/internal/server.js +79 -104
  284. package/dist/internal/session-engine.d.ts +9 -7
  285. package/dist/internal/session-engine.d.ts.map +1 -1
  286. package/dist/internal/session-engine.js +45 -34
  287. package/dist/internal/session-run-log.d.ts +5 -4
  288. package/dist/internal/session-run-log.d.ts.map +1 -1
  289. package/dist/internal/session-run-log.js +8 -8
  290. package/dist/internal/start-log-store.d.ts +60 -0
  291. package/dist/internal/start-log-store.d.ts.map +1 -0
  292. package/dist/internal/start-log-store.js +151 -0
  293. package/dist/internal/storage-coordinator.d.ts +0 -6
  294. package/dist/internal/storage-coordinator.d.ts.map +1 -1
  295. package/dist/internal/storage-coordinator.js +1 -9
  296. package/dist/internal/tool-policy.d.ts +8 -0
  297. package/dist/internal/tool-policy.d.ts.map +1 -1
  298. package/dist/internal/tool-policy.js +19 -7
  299. package/dist/playground/assets/{index-jzNbJENa.js → index-BnNN1-EK.js} +45 -45
  300. package/dist/playground/assets/index-DBQCwFp0.css +1 -0
  301. package/dist/playground/index.html +2 -2
  302. package/dist/storage-backends/cursor-hosted-v2.d.ts +83 -0
  303. package/dist/storage-backends/cursor-hosted-v2.d.ts.map +1 -0
  304. package/dist/storage-backends/cursor-hosted-v2.js +164 -0
  305. package/dist/storage-backends/cursor-hosted.d.ts +6 -0
  306. package/dist/storage-backends/cursor-hosted.d.ts.map +1 -1
  307. package/dist/storage-backends/cursor-hosted.js +6 -1
  308. package/dist/storage-protocol.d.ts +24 -0
  309. package/dist/storage-protocol.d.ts.map +1 -1
  310. package/dist/storage-protocol.js +33 -0
  311. package/dist/storage.d.ts +1 -1
  312. package/dist/storage.d.ts.map +1 -1
  313. package/dist/storage.js +1 -1
  314. package/dist/types.d.ts +123 -6
  315. package/dist/types.d.ts.map +1 -1
  316. package/dist/types.js +29 -1
  317. package/docs/README.md +1 -1
  318. package/docs/ab.md +1 -1
  319. package/docs/building-with-agents.md +14 -11
  320. package/docs/evals.md +1 -1
  321. package/docs/guides/github.md +1 -1
  322. package/docs/guides/mcp-oauth.md +1 -1
  323. package/docs/guides/opentelemetry.md +2 -2
  324. package/docs/guides/slack.md +80 -1
  325. package/docs/hillclimbing.md +5 -5
  326. package/docs/quickstart.md +1 -1
  327. package/docs/reference/connections.md +32 -1
  328. package/docs/reference/http-api.md +1 -1
  329. package/docs/scaffolding-agents.md +3 -3
  330. package/docs/skills/index.md +26 -0
  331. package/docs/troubleshooting.md +1 -1
  332. package/package.json +18 -4
  333. package/src/bin/agent-serve.ts +11 -2
  334. package/src/channels/deployments/deployments-channel.ts +117 -8
  335. package/src/channels/deployments/types.ts +4 -3
  336. package/src/channels/github/defaults.ts +36 -3
  337. package/src/channels/github/progress.ts +7 -0
  338. package/src/channels/origin/defaults.ts +143 -0
  339. package/src/channels/origin/index.ts +2 -0
  340. package/src/channels/origin/origin-channel.ts +37 -1
  341. package/src/channels/origin/state.ts +54 -0
  342. package/src/channels/origin/types.ts +24 -0
  343. package/src/channels/slack/api.ts +37 -18
  344. package/src/channels/slack/code-fences.ts +183 -0
  345. package/src/channels/slack/constants.ts +6 -0
  346. package/src/channels/slack/defaults.ts +173 -92
  347. package/src/channels/slack/dispatch.ts +8 -1
  348. package/src/channels/slack/inbound.ts +17 -0
  349. package/src/channels/slack/index.ts +2 -0
  350. package/src/channels/slack/live-delivery.ts +142 -28
  351. package/src/channels/slack/reasoning-card.ts +140 -0
  352. package/src/channels/slack/redact.ts +6 -0
  353. package/src/channels/slack/reply-options.ts +229 -0
  354. package/src/channels/slack/slack-channel.ts +7 -2
  355. package/src/channels/slack/stream.ts +31 -24
  356. package/src/channels/slack/tool-cards.ts +221 -0
  357. package/src/channels/slack/types.ts +159 -6
  358. package/src/connections.ts +18 -1
  359. package/src/extensions/cursor-cloud-agents/extension.ts +118 -0
  360. package/src/extensions/cursor-cloud-agents/lib/cloud.ts +79 -0
  361. package/src/extensions/cursor-cloud-agents/lib/fleet.ts +109 -0
  362. package/src/extensions/cursor-cloud-agents/lib/repos.ts +81 -0
  363. package/src/extensions/cursor-cloud-agents/skills/handoff.md +27 -0
  364. package/src/extensions/cursor-cloud-agents/tools/follow_up.ts +29 -0
  365. package/src/extensions/cursor-cloud-agents/tools/launch.ts +84 -0
  366. package/src/extensions/cursor-cloud-agents/tools/list.ts +31 -0
  367. package/src/extensions/cursor-cloud-agents/tools/status.ts +39 -0
  368. package/src/extensions.ts +98 -0
  369. package/src/files-backends/cursor-hosted.ts +15 -5
  370. package/src/index.ts +2 -0
  371. package/src/internal/advertise-tools.ts +37 -12
  372. package/src/internal/as-of.ts +163 -0
  373. package/src/internal/cli-deploy.ts +88 -25
  374. package/src/internal/continuation-identity.ts +3 -1
  375. package/src/internal/conversation-mirror.ts +3 -8
  376. package/src/internal/cursor/hosted-deployment-secrets.ts +72 -0
  377. package/src/internal/cursor/hosted-store-secrets.ts +72 -0
  378. package/src/internal/cursor-deployment-relay.ts +65 -8
  379. package/src/internal/deploy-client.ts +83 -28
  380. package/src/internal/discovery.ts +479 -114
  381. package/src/internal/distribution.ts +5 -0
  382. package/src/internal/framework-file-storage.ts +80 -10
  383. package/src/internal/framework-storage-selection.ts +31 -44
  384. package/src/internal/hosted-delivery.ts +38 -63
  385. package/src/internal/hosted-execution-diag.ts +6 -0
  386. package/src/internal/hosted-execution-flush.ts +142 -0
  387. package/src/internal/mcp-endpoint.ts +1 -0
  388. package/src/internal/mcp-host.ts +40 -14
  389. package/src/internal/review-comments.ts +5 -2
  390. package/src/internal/server.ts +81 -100
  391. package/src/internal/session-engine.ts +56 -28
  392. package/src/internal/session-run-log.ts +8 -12
  393. package/src/internal/start-log-store.ts +177 -0
  394. package/src/internal/storage-coordinator.ts +1 -11
  395. package/src/internal/tool-policy.ts +39 -9
  396. package/src/storage-backends/cursor-hosted-v2.ts +219 -0
  397. package/src/storage-backends/cursor-hosted.ts +6 -1
  398. package/src/storage-protocol.ts +37 -0
  399. package/src/storage.ts +1 -0
  400. package/src/types.ts +177 -14
  401. package/dist/docs/assets/chunks/@localSearchIndexroot.DpuI4i7Z.js +0 -1
  402. package/dist/docs/assets/hillclimbing.md.DhESf3OO.js +0 -4
  403. package/dist/docs/assets/scaffolding-agents.md.D7UUkWw0.js +0 -1
  404. package/dist/internal/null-kv-storage.d.ts +0 -48
  405. package/dist/internal/null-kv-storage.d.ts.map +0 -1
  406. package/dist/internal/null-kv-storage.js +0 -58
  407. package/dist/playground/assets/index-D7rGZNjy.css +0 -1
  408. package/src/internal/null-kv-storage.ts +0 -74
  409. /package/dist/docs/assets/{ab.md.DJo5r4R-.lean.js → ab.md.mlVgqvSk.lean.js} +0 -0
  410. /package/dist/docs/assets/{building-with-agents.md.DI4mEzlt.lean.js → building-with-agents.md.CUSWxlP_.lean.js} +0 -0
  411. /package/dist/docs/assets/{evals.md.lfJoEVc8.lean.js → evals.md.CPzDAwoH.lean.js} +0 -0
  412. /package/dist/docs/assets/{guides_github.md.Cnh2mL4a.lean.js → guides_github.md.BtPr9GaP.lean.js} +0 -0
  413. /package/dist/docs/assets/{guides_mcp-oauth.md.CN-6YmTJ.lean.js → guides_mcp-oauth.md.Dp6cDP7f.lean.js} +0 -0
  414. /package/dist/docs/assets/{guides_opentelemetry.md.bmPmkvJu.lean.js → guides_opentelemetry.md.BVTXDCRg.lean.js} +0 -0
  415. /package/dist/docs/assets/{hillclimbing.md.DhESf3OO.lean.js → hillclimbing.md.CpTGTCle.lean.js} +0 -0
  416. /package/dist/docs/assets/{index.md.CVeRUOeZ.lean.js → index.md.Bb4k8kUm.lean.js} +0 -0
  417. /package/dist/docs/assets/{quickstart.md.Nj_LjW_a.lean.js → quickstart.md.DdQOF7Y8.lean.js} +0 -0
  418. /package/dist/docs/assets/{reference_http-api.md.BEJx9XVj.lean.js → reference_http-api.md.oySXBO8o.lean.js} +0 -0
  419. /package/dist/docs/assets/{scaffolding-agents.md.D7UUkWw0.lean.js → scaffolding-agents.md.em43xlY1.lean.js} +0 -0
  420. /package/dist/docs/assets/{troubleshooting.md.DCiPBhYs.lean.js → troubleshooting.md.Cus_YZga.lean.js} +0 -0
@@ -41,10 +41,12 @@ import {
41
41
  type DiscoveredAB,
42
42
  type DiscoveredChannel,
43
43
  type DiscoveredConnection,
44
+ type DiscoveredExtension,
44
45
  type DiscoveredHook,
45
46
  type DiscoveredSchedule,
46
47
  type DiscoveredSkill,
47
48
  type DiscoveredTool,
49
+ type ExtensionMount,
48
50
  type HookDefinition,
49
51
  type HttpChannelDefinition,
50
52
  type InlineStdioConnectionConfig,
@@ -54,10 +56,12 @@ import {
54
56
  MAX_RUNNING_TURNS_LIMIT,
55
57
  type ModelSetting,
56
58
  normalizeConnectionEffects,
59
+ normalizeConnectionTools,
57
60
  normalizeCursorAccountServers,
58
61
  type ResolvedAgent,
59
62
  type ScheduleDefinition,
60
63
  type SeedFile,
64
+ type SkillConfig,
61
65
  type SkillDefinition,
62
66
  type SkillFileSource,
63
67
  type ToolDefinition,
@@ -433,6 +437,12 @@ async function loadAgent(
433
437
 
434
438
  const tools = await loadTools(ctx, join(agentDir, "tools"));
435
439
  const skills = await loadSkills(ctx, join(agentDir, "skills"));
440
+ const extensions = await appendExtensions(
441
+ ctx,
442
+ join(agentDir, "extensions"),
443
+ tools,
444
+ skills
445
+ );
436
446
  const connections = await loadConnections(
437
447
  ctx,
438
448
  await resolveMcpConnectionsDir(ctx, agentDir)
@@ -579,6 +589,7 @@ async function loadAgent(
579
589
  ...(architecture === undefined ? {} : { architecture }),
580
590
  tools,
581
591
  skills,
592
+ extensions,
582
593
  connections,
583
594
  hostConnections,
584
595
  subagents,
@@ -868,16 +879,35 @@ async function loadTools(
868
879
  ctx: DiscoveryContext,
869
880
  toolsDir: string
870
881
  ): Promise<DiscoveredTool[]> {
882
+ const tools: DiscoveredTool[] = [];
883
+ for (const { name, path } of await toolModuleEntries(ctx, toolsDir)) {
884
+ const definition = await importDefault(ctx, path, "tool");
885
+ if (definition === undefined) {
886
+ continue;
887
+ }
888
+ const tool = compileTool(ctx, path, name, definition as ToolDefinition);
889
+ if (tool !== undefined) {
890
+ tools.push(tool);
891
+ }
892
+ }
893
+ return tools;
894
+ }
895
+
896
+ /** The module files of a `tools/` directory whose filenames are valid tool names. */
897
+ async function toolModuleEntries(
898
+ ctx: DiscoveryContext,
899
+ toolsDir: string
900
+ ): Promise<Array<{ name: string; path: string }>> {
871
901
  if (!(await isDirectory(toolsDir))) {
872
902
  return [];
873
903
  }
874
- const tools: DiscoveredTool[] = [];
904
+ const entries: Array<{ name: string; path: string }> = [];
875
905
  for (const entry of await sortedEntries(toolsDir)) {
876
- const entryPath = join(toolsDir, entry.name);
906
+ const path = join(toolsDir, entry.name);
877
907
  if (entry.isDirectory()) {
878
908
  ctx.diagnostics.push({
879
909
  severity: "warning",
880
- path: displayPath(ctx, entryPath),
910
+ path: displayPath(ctx, path),
881
911
  message: "Nested tool directories are not supported; ignoring.",
882
912
  });
883
913
  continue;
@@ -886,104 +916,105 @@ async function loadTools(
886
916
  continue;
887
917
  }
888
918
  const name = moduleStem(entry.name);
889
- if (!NAME_PATTERN.test(name)) {
890
- ctx.diagnostics.push({
891
- severity: "error",
892
- path: displayPath(ctx, entryPath),
893
- message: `Tool name "${name}" must match ${NAME_PATTERN} (the filename becomes the tool name the model sees).`,
894
- });
895
- continue;
919
+ if (validateName(ctx, "tool", name, path)) {
920
+ entries.push({ name, path });
896
921
  }
897
- const definition = await importDefault(ctx, entryPath, "tool");
898
- if (definition === undefined) {
899
- continue;
900
- }
901
- const tool = definition as ToolDefinition;
902
- if (isBlank(tool.description)) {
922
+ }
923
+ return entries;
924
+ }
925
+
926
+ /**
927
+ * Validate one tool definition against the tool contract and convert its
928
+ * schemas. Diagnostics point at `entryPath` (the authored file, or the
929
+ * extension mount that contributed the tool).
930
+ */
931
+ function compileTool(
932
+ ctx: DiscoveryContext,
933
+ entryPath: string,
934
+ name: string,
935
+ tool: ToolDefinition
936
+ ): DiscoveredTool | undefined {
937
+ if (isBlank(tool.description)) {
938
+ ctx.diagnostics.push({
939
+ severity: "error",
940
+ path: displayPath(ctx, entryPath),
941
+ message: "Tools require a non-empty description.",
942
+ });
943
+ return undefined;
944
+ }
945
+ const execution = tool.execution === "agent" ? "agent" : "server";
946
+ const needsApprovalConfigured =
947
+ tool.needsApproval === true || typeof tool.needsApproval === "function";
948
+ const effect = declaredEffect(tool);
949
+ if (execution === "agent") {
950
+ if (isBlank(tool.script)) {
903
951
  ctx.diagnostics.push({
904
952
  severity: "error",
905
953
  path: displayPath(ctx, entryPath),
906
- message: "Tools require a non-empty description.",
954
+ message:
955
+ 'Tools with execution: "agent" require a non-empty `script` (shell body; JSON on stdin, result on stdout).',
907
956
  });
908
- continue;
957
+ return undefined;
909
958
  }
910
- const execution = tool.execution === "agent" ? "agent" : "server";
911
- const needsApprovalConfigured =
912
- tool.needsApproval === true || typeof tool.needsApproval === "function";
913
- const effect = declaredEffect(tool);
914
- if (execution === "agent") {
915
- if (isBlank(tool.script)) {
916
- ctx.diagnostics.push({
917
- severity: "error",
918
- path: displayPath(ctx, entryPath),
919
- message:
920
- 'Tools with execution: "agent" require a non-empty `script` (shell body; JSON on stdin, result on stdout).',
921
- });
922
- continue;
923
- }
924
- if (typeof tool.execute === "function") {
925
- ctx.diagnostics.push({
926
- severity: "warning",
927
- path: displayPath(ctx, entryPath),
928
- message:
929
- '`execute` is ignored when execution is "agent"; the Cursor agent runs `script` instead.',
930
- });
931
- }
932
- if (needsApprovalConfigured) {
933
- ctx.diagnostics.push({
934
- severity: "error",
935
- path: displayPath(ctx, entryPath),
936
- message:
937
- '`needsApproval` is only supported for execution: "server" tools (in-process).',
938
- });
939
- continue;
940
- }
941
- } else if (typeof tool.execute !== "function") {
959
+ if (typeof tool.execute === "function") {
942
960
  ctx.diagnostics.push({
943
- severity: "error",
961
+ severity: "warning",
944
962
  path: displayPath(ctx, entryPath),
945
963
  message:
946
- 'Tools require an execute(input, ctx) function (or set execution: "agent" with a script).',
964
+ '`execute` is ignored when execution is "agent"; the Cursor agent runs `script` instead.',
947
965
  });
948
- continue;
949
966
  }
950
- let inputSchema: DiscoveredTool["inputSchema"];
951
- try {
952
- inputSchema = toolInputJsonSchema(tool.inputSchema);
953
- } catch (error) {
967
+ if (needsApprovalConfigured) {
954
968
  ctx.diagnostics.push({
955
969
  severity: "error",
956
970
  path: displayPath(ctx, entryPath),
957
- message: `Failed to convert inputSchema to JSON Schema: ${errorMessage(error)}`,
958
- });
959
- continue;
960
- }
961
- let outputSchema: DiscoveredTool["outputSchema"];
962
- try {
963
- outputSchema = toolOutputJsonSchema(tool.outputSchema);
964
- } catch (error) {
965
- ctx.diagnostics.push({
966
- severity: "error",
967
- path: displayPath(ctx, entryPath),
968
- message: `Failed to convert outputSchema to JSON Schema: ${errorMessage(error)}`,
971
+ message:
972
+ '`needsApproval` is only supported for execution: "server" tools (in-process).',
969
973
  });
970
- continue;
974
+ return undefined;
971
975
  }
972
- tools.push({
973
- name,
974
- description: tool.description,
975
- inputSchema,
976
- ...(outputSchema === undefined ? {} : { outputSchema }),
977
- execution,
978
- needsApproval: needsApprovalConfigured,
979
- ...(effect === undefined ? {} : { effect }),
980
- ...(execution === "agent" && tool.script !== undefined
981
- ? { script: tool.script }
982
- : {}),
983
- definition: tool,
976
+ } else if (typeof tool.execute !== "function") {
977
+ ctx.diagnostics.push({
978
+ severity: "error",
979
+ path: displayPath(ctx, entryPath),
980
+ message:
981
+ 'Tools require an execute(input, ctx) function (or set execution: "agent" with a script).',
984
982
  });
983
+ return undefined;
985
984
  }
986
- return tools;
985
+ let inputSchema: DiscoveredTool["inputSchema"];
986
+ try {
987
+ inputSchema = toolInputJsonSchema(tool.inputSchema);
988
+ } catch (error) {
989
+ ctx.diagnostics.push({
990
+ severity: "error",
991
+ path: displayPath(ctx, entryPath),
992
+ message: `Failed to convert inputSchema to JSON Schema: ${errorMessage(error)}`,
993
+ });
994
+ return undefined;
995
+ }
996
+ let outputSchema: DiscoveredTool["outputSchema"];
997
+ try {
998
+ outputSchema = toolOutputJsonSchema(tool.outputSchema);
999
+ } catch (error) {
1000
+ ctx.diagnostics.push({
1001
+ severity: "error",
1002
+ path: displayPath(ctx, entryPath),
1003
+ message: `Failed to convert outputSchema to JSON Schema: ${errorMessage(error)}`,
1004
+ });
1005
+ return undefined;
1006
+ }
1007
+ return {
1008
+ name,
1009
+ description: tool.description,
1010
+ inputSchema,
1011
+ outputSchema,
1012
+ execution,
1013
+ needsApproval: needsApprovalConfigured,
1014
+ effect,
1015
+ script: execution === "agent" ? tool.script : undefined,
1016
+ definition: tool,
1017
+ };
987
1018
  }
988
1019
 
989
1020
  /**
@@ -1029,7 +1060,7 @@ async function loadSkills(
1029
1060
  }
1030
1061
  if (entry.name.endsWith(".md")) {
1031
1062
  const name = entry.name.slice(0, -".md".length);
1032
- if (!validateSkillName(ctx, name, entryPath)) {
1063
+ if (!validateName(ctx, "skill", name, entryPath)) {
1033
1064
  continue;
1034
1065
  }
1035
1066
  const { data, body } = parseFrontmatter(
@@ -1048,30 +1079,258 @@ async function loadSkills(
1048
1079
  }
1049
1080
  if (isModuleFile(entry.name)) {
1050
1081
  const name = moduleStem(entry.name);
1051
- if (!validateSkillName(ctx, name, entryPath)) {
1082
+ if (!validateName(ctx, "skill", name, entryPath)) {
1052
1083
  continue;
1053
1084
  }
1054
1085
  const definition = await importDefault(ctx, entryPath, "skill");
1055
1086
  if (definition === undefined) {
1056
1087
  continue;
1057
1088
  }
1058
- const skill = definition as SkillDefinition;
1059
- const files: Record<string, SkillFileSource> = {};
1060
- for (const [rel, contents] of Object.entries(skill.files ?? {})) {
1061
- files[rel] = { contents };
1089
+ skills.push(compileSkill(name, definition as SkillDefinition));
1090
+ }
1091
+ }
1092
+ return skills;
1093
+ }
1094
+
1095
+ /** A skill whose body and sibling files are in memory (`defineSkill`, extensions). */
1096
+ function compileSkill(name: string, skill: SkillConfig): DiscoveredSkill {
1097
+ const files: Record<string, SkillFileSource> = {};
1098
+ for (const [rel, contents] of Object.entries(skill.files ?? {})) {
1099
+ files[rel] = { contents };
1100
+ }
1101
+ return {
1102
+ name,
1103
+ description:
1104
+ skill.description ??
1105
+ deriveSkillDescription(skill.markdown) ??
1106
+ SKILL_DESCRIPTION_FALLBACK(name),
1107
+ markdown: skill.markdown.trim(),
1108
+ files,
1109
+ };
1110
+ }
1111
+
1112
+ // ============================================================================
1113
+ // Extensions (agent/extensions/<ns>.ts | agent/extensions/<ns>/extension.ts)
1114
+ // ============================================================================
1115
+
1116
+ /**
1117
+ * Mount every extension under `agent/extensions/` and append its tools and
1118
+ * skills to the authored lists as `<ns>__<name>`, stamped with `extension`.
1119
+ * The namespace is the mount's filename stem or directory name.
1120
+ */
1121
+ async function appendExtensions(
1122
+ ctx: DiscoveryContext,
1123
+ extensionsDir: string,
1124
+ tools: DiscoveredTool[],
1125
+ skills: DiscoveredSkill[]
1126
+ ): Promise<DiscoveredExtension[]> {
1127
+ if (!(await isDirectory(extensionsDir))) {
1128
+ return [];
1129
+ }
1130
+ const extensions: DiscoveredExtension[] = [];
1131
+ for (const entry of await sortedEntries(extensionsDir)) {
1132
+ const path = join(extensionsDir, entry.name);
1133
+ const site = await resolveMountSite(ctx, path, entry);
1134
+ if (site === undefined) {
1135
+ continue;
1136
+ }
1137
+ if (extensions.some((extension) => extension.name === site.ns)) {
1138
+ ctx.diagnostics.push({
1139
+ severity: "error",
1140
+ path: displayPath(ctx, path),
1141
+ message: `Extension "${site.ns}" is mounted twice (as a file and as a directory).`,
1142
+ });
1143
+ continue;
1144
+ }
1145
+ const mount = await importDefault(ctx, site.mountPath, "extension");
1146
+ if (mount === undefined) {
1147
+ continue;
1148
+ }
1149
+ extensions.push(
1150
+ await mountExtension(ctx, site, mount as ExtensionMount, tools, skills)
1151
+ );
1152
+ }
1153
+ return extensions;
1154
+ }
1155
+
1156
+ interface MountSite {
1157
+ ns: string;
1158
+ /** The module default-exporting the {@link ExtensionMount}. */
1159
+ mountPath: string;
1160
+ /** A directory mount; its `tools/` and `skills/` overlay the extension's. */
1161
+ overlayDir?: string;
1162
+ }
1163
+
1164
+ async function resolveMountSite(
1165
+ ctx: DiscoveryContext,
1166
+ path: string,
1167
+ entry: Dirent
1168
+ ): Promise<MountSite | undefined> {
1169
+ if (entry.isDirectory()) {
1170
+ if (!validateName(ctx, "extension", entry.name, path)) {
1171
+ return undefined;
1172
+ }
1173
+ const mountPath = await findModuleFile(path, "extension");
1174
+ if (mountPath === undefined) {
1175
+ ctx.diagnostics.push({
1176
+ severity: "error",
1177
+ path: displayPath(ctx, path),
1178
+ message:
1179
+ "A directory mount needs an extension.ts default-exporting the mount (`export default crm({ ... })`).",
1180
+ });
1181
+ return undefined;
1182
+ }
1183
+ return { ns: entry.name, mountPath, overlayDir: path };
1184
+ }
1185
+ if (!entry.isFile() || !isModuleFile(entry.name)) {
1186
+ return undefined;
1187
+ }
1188
+ const ns = moduleStem(entry.name);
1189
+ return validateName(ctx, "extension", ns, path)
1190
+ ? { ns, mountPath: path }
1191
+ : undefined;
1192
+ }
1193
+
1194
+ /**
1195
+ * Read the extension's tree with the agent loaders, lay the mount's overlay
1196
+ * on top (a same-named file replaces, `disableTool()` removes), then
1197
+ * namespace what is left.
1198
+ */
1199
+ async function mountExtension(
1200
+ ctx: DiscoveryContext,
1201
+ site: MountSite,
1202
+ mount: ExtensionMount,
1203
+ tools: DiscoveredTool[],
1204
+ skills: DiscoveredSkill[]
1205
+ ): Promise<DiscoveredExtension> {
1206
+ const mounted: DiscoveredExtension = {
1207
+ name: site.ns,
1208
+ description: mount.extension.description,
1209
+ tools: [],
1210
+ skills: [],
1211
+ };
1212
+ const root = mount.extension.root;
1213
+ if (!(await isDirectory(root))) {
1214
+ ctx.diagnostics.push({
1215
+ severity: "error",
1216
+ path: displayPath(ctx, site.mountPath),
1217
+ message: `Extension "${site.ns}" declares root ${root}, which is not a directory. Pass \`import.meta.dirname\` from extension.ts.`,
1218
+ });
1219
+ return mounted;
1220
+ }
1221
+ await warnUnsupportedExtensionSlots(ctx, root);
1222
+ const contributedTools = new Map(
1223
+ (await loadTools(ctx, join(root, "tools"))).map((tool) => [tool.name, tool])
1224
+ );
1225
+ const contributedSkills = new Map(
1226
+ (await loadSkills(ctx, join(root, "skills"))).map((skill) => [
1227
+ skill.name,
1228
+ skill,
1229
+ ])
1230
+ );
1231
+ if (site.overlayDir !== undefined) {
1232
+ const overlay = await loadOverlayTools(ctx, join(site.overlayDir, "tools"));
1233
+ for (const tool of overlay.tools) {
1234
+ contributedTools.set(tool.name, tool);
1235
+ }
1236
+ for (const disabled of overlay.disabled) {
1237
+ if (!contributedTools.delete(disabled.name)) {
1238
+ ctx.diagnostics.push({
1239
+ severity: "error",
1240
+ path: displayPath(ctx, disabled.path),
1241
+ message: `disableTool() targets "${disabled.name}", which extension "${site.ns}" does not contribute.`,
1242
+ });
1062
1243
  }
1063
- skills.push({
1064
- name,
1065
- description:
1066
- skill.description ??
1067
- deriveSkillDescription(skill.markdown) ??
1068
- SKILL_DESCRIPTION_FALLBACK(name),
1069
- markdown: skill.markdown.trim(),
1070
- files,
1244
+ }
1245
+ for (const skill of await loadSkills(
1246
+ ctx,
1247
+ join(site.overlayDir, "skills")
1248
+ )) {
1249
+ contributedSkills.set(skill.name, skill);
1250
+ }
1251
+ }
1252
+ for (const [name, tool] of contributedTools) {
1253
+ const composed = `${site.ns}__${name}`;
1254
+ tools.push({ ...tool, name: composed, extension: site.ns });
1255
+ mounted.tools.push(composed);
1256
+ }
1257
+ for (const [name, skill] of contributedSkills) {
1258
+ const composed = `${site.ns}__${name}`;
1259
+ skills.push({ ...skill, name: composed, extension: site.ns });
1260
+ mounted.skills.push(composed);
1261
+ }
1262
+ return mounted;
1263
+ }
1264
+
1265
+ /** A directory mount's `tools/`: replacements plus `disableTool()` markers. */
1266
+ async function loadOverlayTools(
1267
+ ctx: DiscoveryContext,
1268
+ toolsDir: string
1269
+ ): Promise<{
1270
+ tools: DiscoveredTool[];
1271
+ disabled: Array<{ name: string; path: string }>;
1272
+ }> {
1273
+ const tools: DiscoveredTool[] = [];
1274
+ const disabled: Array<{ name: string; path: string }> = [];
1275
+ for (const { name, path } of await toolModuleEntries(ctx, toolsDir)) {
1276
+ let mod: Record<string, unknown>;
1277
+ try {
1278
+ mod = await ctx.importModule(path);
1279
+ } catch (error) {
1280
+ ctx.diagnostics.push({
1281
+ severity: "error",
1282
+ path: displayPath(ctx, path),
1283
+ message: `Failed to load module: ${errorMessage(error)}`,
1284
+ });
1285
+ continue;
1286
+ }
1287
+ const kind = getDefinitionKind(mod.default);
1288
+ if (kind === "disabled-tool") {
1289
+ disabled.push({ name, path });
1290
+ continue;
1291
+ }
1292
+ if (kind !== "tool") {
1293
+ ctx.diagnostics.push({
1294
+ severity: "error",
1295
+ path: displayPath(ctx, path),
1296
+ message:
1297
+ "An override must default-export defineTool({ ... }) or disableTool().",
1298
+ });
1299
+ continue;
1300
+ }
1301
+ const tool = compileTool(ctx, path, name, mod.default as ToolDefinition);
1302
+ if (tool !== undefined) {
1303
+ tools.push(tool);
1304
+ }
1305
+ }
1306
+ return { tools, disabled };
1307
+ }
1308
+
1309
+ /** Slots an agent has that an extension tree may not contribute (yet). */
1310
+ async function warnUnsupportedExtensionSlots(
1311
+ ctx: DiscoveryContext,
1312
+ root: string
1313
+ ): Promise<void> {
1314
+ const unsupported = [
1315
+ ["instructions.md", "instructions"],
1316
+ ["connections", "connections"],
1317
+ ["mcp-connections", "MCP connections"],
1318
+ ["hooks", "hooks"],
1319
+ ["subagents", "subagents"],
1320
+ ["channels", "channels"],
1321
+ ["schedules", "schedules"],
1322
+ ["extensions", "nested extensions"],
1323
+ ] as const;
1324
+ for (const [slot, label] of unsupported) {
1325
+ const path = join(root, slot);
1326
+ if ((await isDirectory(path)) || (await isFile(path))) {
1327
+ ctx.diagnostics.push({
1328
+ severity: "warning",
1329
+ path: displayPath(ctx, path),
1330
+ message: `Extension ${label} are not supported yet; only tools/ and skills/ are mounted. Ignoring.`,
1071
1331
  });
1072
1332
  }
1073
1333
  }
1074
- return skills;
1075
1334
  }
1076
1335
 
1077
1336
  async function loadPackagedSkill(
@@ -1088,7 +1347,7 @@ async function loadPackagedSkill(
1088
1347
  });
1089
1348
  return undefined;
1090
1349
  }
1091
- if (!validateSkillName(ctx, name, skillDir)) {
1350
+ if (!validateName(ctx, "skill", name, skillDir)) {
1092
1351
  return undefined;
1093
1352
  }
1094
1353
  const { data, body } = parseFrontmatter(await readFile(skillMdPath, "utf8"));
@@ -1168,6 +1427,25 @@ function parseConnectionEffects(
1168
1427
  return { ok: true, value: normalizeConnectionEffects(parsed) };
1169
1428
  }
1170
1429
 
1430
+ function parseConnectionTools(
1431
+ tools: unknown
1432
+ ): { ok: true; value: string[] | undefined } | { ok: false } {
1433
+ if (tools === undefined) {
1434
+ return { ok: true, value: undefined };
1435
+ }
1436
+ if (!Array.isArray(tools) || tools.length === 0) {
1437
+ return { ok: false };
1438
+ }
1439
+ if (tools.some((name) => typeof name !== "string")) {
1440
+ return { ok: false };
1441
+ }
1442
+ const normalized = normalizeConnectionTools(tools);
1443
+ if (normalized.length === 0) {
1444
+ return { ok: false };
1445
+ }
1446
+ return { ok: true, value: normalized };
1447
+ }
1448
+
1171
1449
  function connectionHasSpawnOrRemote(connection: ConnectionDefinition): boolean {
1172
1450
  if ("cursorAccount" in connection && connection.cursorAccount === true) {
1173
1451
  return true;
@@ -1214,20 +1492,34 @@ function connectionTransport(
1214
1492
  return undefined;
1215
1493
  }
1216
1494
 
1217
- function validateSkillName(
1495
+ /**
1496
+ * Filenames become the names the model sees. `__` is reserved: it joins an
1497
+ * extension's namespace to its contribution (`crm__search`).
1498
+ */
1499
+ function validateName(
1218
1500
  ctx: DiscoveryContext,
1501
+ kind: "skill" | "tool" | "extension",
1219
1502
  name: string,
1220
1503
  entryPath: string
1221
1504
  ): boolean {
1222
- if (NAME_PATTERN.test(name)) {
1223
- return true;
1505
+ const label = { skill: "Skill", tool: "Tool", extension: "Extension" }[kind];
1506
+ if (!NAME_PATTERN.test(name)) {
1507
+ ctx.diagnostics.push({
1508
+ severity: "error",
1509
+ path: displayPath(ctx, entryPath),
1510
+ message: `${label} name "${name}" must match ${NAME_PATTERN}.`,
1511
+ });
1512
+ return false;
1224
1513
  }
1225
- ctx.diagnostics.push({
1226
- severity: "error",
1227
- path: displayPath(ctx, entryPath),
1228
- message: `Skill name "${name}" must match ${NAME_PATTERN}.`,
1229
- });
1230
- return false;
1514
+ if (name.includes("__")) {
1515
+ ctx.diagnostics.push({
1516
+ severity: "error",
1517
+ path: displayPath(ctx, entryPath),
1518
+ message: `${label} name "${name}" may not contain "__"; it is reserved for extension contributions (\`<ns>__<name>\`).`,
1519
+ });
1520
+ return false;
1521
+ }
1522
+ return true;
1231
1523
  }
1232
1524
 
1233
1525
  /**
@@ -1296,7 +1588,7 @@ async function loadHostConnections(
1296
1588
  modelConnections: readonly DiscoveredConnection[]
1297
1589
  ): Promise<DiscoveredConnection[]> {
1298
1590
  const hostDir = join(agentDir, "host-connections");
1299
- const loaded = await loadConnections(ctx, hostDir);
1591
+ const loaded = await loadConnections(ctx, hostDir, "host");
1300
1592
  const modelNames = new Set(
1301
1593
  modelConnections.map((connection) => connection.name)
1302
1594
  );
@@ -1335,7 +1627,8 @@ async function loadHostConnections(
1335
1627
 
1336
1628
  async function loadConnections(
1337
1629
  ctx: DiscoveryContext,
1338
- connectionsDir: string
1630
+ connectionsDir: string,
1631
+ role: "model" | "host" = "model"
1339
1632
  ): Promise<DiscoveredConnection[]> {
1340
1633
  if (!(await isDirectory(connectionsDir))) {
1341
1634
  return [];
@@ -1435,6 +1728,56 @@ async function loadConnections(
1435
1728
  });
1436
1729
  continue;
1437
1730
  }
1731
+ const parsedTools = isInlineStdioConnection(connection)
1732
+ ? { ok: true as const, value: undefined }
1733
+ : parseConnectionTools(connection.tools);
1734
+ if (!parsedTools.ok) {
1735
+ ctx.diagnostics.push({
1736
+ severity: "error",
1737
+ path: displayPath(ctx, entryPath),
1738
+ message:
1739
+ "MCP connection `tools` allowlist must be a non-empty array of tool names.",
1740
+ });
1741
+ continue;
1742
+ }
1743
+ if (
1744
+ isInlineStdioConnection(connection) &&
1745
+ connection.disallowedTools !== undefined
1746
+ ) {
1747
+ ctx.diagnostics.push({
1748
+ severity: "error",
1749
+ path: displayPath(ctx, entryPath),
1750
+ message:
1751
+ "MCP connection `disallowedTools` is not supported on inline `tools` connections — author only the tools you want.",
1752
+ });
1753
+ continue;
1754
+ }
1755
+ const parsedDisallowed = isInlineStdioConnection(connection)
1756
+ ? { ok: true as const, value: undefined }
1757
+ : parseConnectionTools(connection.disallowedTools);
1758
+ if (!parsedDisallowed.ok) {
1759
+ ctx.diagnostics.push({
1760
+ severity: "error",
1761
+ path: displayPath(ctx, entryPath),
1762
+ message:
1763
+ "MCP connection `disallowedTools` must be a non-empty array of tool names.",
1764
+ });
1765
+ continue;
1766
+ }
1767
+ if (
1768
+ (parsedTools.value !== undefined ||
1769
+ parsedDisallowed.value !== undefined) &&
1770
+ role === "model" &&
1771
+ connection.advertiseTools !== true
1772
+ ) {
1773
+ ctx.diagnostics.push({
1774
+ severity: "error",
1775
+ path: displayPath(ctx, entryPath),
1776
+ message:
1777
+ "MCP connection `tools` / `disallowedTools` filter advertised tools; set `advertiseTools: true` or drop the name list. Put the connection in `agent/host-connections/` to restrict `host.mcp` only.",
1778
+ });
1779
+ continue;
1780
+ }
1438
1781
  if (
1439
1782
  connection.advertiseTools === true &&
1440
1783
  isInlineStdioConnection(connection)
@@ -1538,6 +1881,8 @@ async function loadConnections(
1538
1881
  auth: connection.auth,
1539
1882
  advertiseTools: connection.advertiseTools,
1540
1883
  effects: parsedEffects.value,
1884
+ tools: parsedTools.value,
1885
+ disallowedTools: parsedDisallowed.value,
1541
1886
  });
1542
1887
  }
1543
1888
  return connections;
@@ -1649,6 +1994,7 @@ async function warnUnsupportedSubagentSlots(
1649
1994
  const unsupported = [
1650
1995
  ["tools", "tools"],
1651
1996
  ["skills", "skills"],
1997
+ ["extensions", "extensions"],
1652
1998
  ["mcp-connections", "MCP connections"],
1653
1999
  ["host-connections", "host MCP connections"],
1654
2000
  ["connections", "MCP connections"],
@@ -1684,13 +2030,17 @@ function appendBuiltinTools(
1684
2030
  return;
1685
2031
  }
1686
2032
  const agentPath = displayPath(ctx, join(agentDir, "agent.ts"));
1687
- const authored = new Set(tools.map((tool) => tool.name));
1688
2033
  for (const tool of builtin) {
1689
- if (authored.has(tool.name)) {
2034
+ const existing = tools.find((t) => t.name === tool.name);
2035
+ if (existing !== undefined) {
2036
+ const owner =
2037
+ existing.extension === undefined
2038
+ ? "Authored"
2039
+ : `Extension "${existing.extension}"`;
1690
2040
  ctx.diagnostics.push({
1691
2041
  severity: "warning",
1692
2042
  path: agentPath,
1693
- message: `Authored tool "${tool.name}" shadows the built-in tool of the same name; the authored tool wins.`,
2043
+ message: `${owner} tool "${tool.name}" shadows the built-in tool of the same name; the built-in is skipped.`,
1694
2044
  });
1695
2045
  continue;
1696
2046
  }
@@ -1928,7 +2278,15 @@ async function loadChannels(
1928
2278
  });
1929
2279
  continue;
1930
2280
  }
1931
- channels.push({ id, definition: mod.default as ChannelDefinition });
2281
+ const definition = mod.default as ChannelDefinition;
2282
+ for (const notice of definition.meta?.deprecations ?? []) {
2283
+ ctx.diagnostics.push({
2284
+ severity: "warning",
2285
+ path: displayPath(ctx, entryPath),
2286
+ message: notice,
2287
+ });
2288
+ }
2289
+ channels.push({ id, definition });
1932
2290
  }
1933
2291
  return { channels, httpChannelDefinition };
1934
2292
  }
@@ -2375,11 +2733,14 @@ export function projectInfo(project: AgentProject): AgentProjectInfo {
2375
2733
  name: skill.name,
2376
2734
  description: skill.description,
2377
2735
  })),
2736
+ extensions: agent.extensions ?? [],
2378
2737
  connections: agent.connections.map((connection) => ({
2379
2738
  name: connection.name,
2380
2739
  transport: connectionTransportLabel(connection.transport),
2381
2740
  advertiseTools: connection.advertiseTools,
2382
2741
  effects: connection.effects,
2742
+ tools: connection.tools,
2743
+ disallowedTools: connection.disallowedTools,
2383
2744
  cursorAccountServers:
2384
2745
  "cursorAccount" in connection.transport
2385
2746
  ? (connection.transport.servers ?? "*")
@@ -2485,6 +2846,7 @@ async function importDefault(
2485
2846
  | "agent"
2486
2847
  | "tool"
2487
2848
  | "skill"
2849
+ | "extension"
2488
2850
  | "connection"
2489
2851
  | "schedule"
2490
2852
  | "hook"
@@ -2525,6 +2887,7 @@ const DEFINE_HELPER_NAME: Record<
2525
2887
  | "instructions"
2526
2888
  | "tool"
2527
2889
  | "skill"
2890
+ | "extension"
2528
2891
  | "connection"
2529
2892
  | "channel"
2530
2893
  | "http-channel"
@@ -2540,6 +2903,7 @@ const DEFINE_HELPER_NAME: Record<
2540
2903
  instructions: "defineInstructions",
2541
2904
  tool: "defineTool",
2542
2905
  skill: "defineSkill",
2906
+ extension: "defineExtension",
2543
2907
  connection: "defineConnection",
2544
2908
  channel: "defineChannel",
2545
2909
  "http-channel": "httpChannel",
@@ -2560,6 +2924,7 @@ async function warnUnknownSlots(
2560
2924
  "instructions",
2561
2925
  "tools",
2562
2926
  "skills",
2927
+ "extensions",
2563
2928
  "mcp-connections",
2564
2929
  "host-connections",
2565
2930
  // Legacy slot name; resolveMcpConnectionsDir warns and still loads it.