@cursor/july 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (623) hide show
  1. package/AGENTS.md +290 -0
  2. package/LICENSE.md +3 -0
  3. package/README.md +1233 -0
  4. package/dist/ab.d.ts +290 -0
  5. package/dist/ab.d.ts.map +1 -0
  6. package/dist/ab.js +386 -0
  7. package/dist/bin/agent-serve.d.ts +15 -0
  8. package/dist/bin/agent-serve.d.ts.map +1 -0
  9. package/dist/bin/agent-serve.js +754 -0
  10. package/dist/channels/github/api.d.ts +101 -0
  11. package/dist/channels/github/api.d.ts.map +1 -0
  12. package/dist/channels/github/api.js +229 -0
  13. package/dist/channels/github/auth.d.ts +67 -0
  14. package/dist/channels/github/auth.d.ts.map +1 -0
  15. package/dist/channels/github/auth.js +239 -0
  16. package/dist/channels/github/binding.d.ts +73 -0
  17. package/dist/channels/github/binding.d.ts.map +1 -0
  18. package/dist/channels/github/binding.js +114 -0
  19. package/dist/channels/github/defaults.d.ts +24 -0
  20. package/dist/channels/github/defaults.d.ts.map +1 -0
  21. package/dist/channels/github/defaults.js +100 -0
  22. package/dist/channels/github/events.d.ts +18 -0
  23. package/dist/channels/github/events.d.ts.map +1 -0
  24. package/dist/channels/github/events.js +59 -0
  25. package/dist/channels/github/forward.d.ts +137 -0
  26. package/dist/channels/github/forward.d.ts.map +1 -0
  27. package/dist/channels/github/forward.js +271 -0
  28. package/dist/channels/github/github-channel.d.ts +127 -0
  29. package/dist/channels/github/github-channel.d.ts.map +1 -0
  30. package/dist/channels/github/github-channel.js +1688 -0
  31. package/dist/channels/github/index.d.ts +52 -0
  32. package/dist/channels/github/index.d.ts.map +1 -0
  33. package/dist/channels/github/index.js +51 -0
  34. package/dist/channels/github/replay.d.ts +115 -0
  35. package/dist/channels/github/replay.d.ts.map +1 -0
  36. package/dist/channels/github/replay.js +282 -0
  37. package/dist/channels/github/state.d.ts +26 -0
  38. package/dist/channels/github/state.d.ts.map +1 -0
  39. package/dist/channels/github/state.js +50 -0
  40. package/dist/channels/github/types.d.ts +385 -0
  41. package/dist/channels/github/types.d.ts.map +1 -0
  42. package/dist/channels/github/types.js +1 -0
  43. package/dist/channels/slack/api.d.ts +117 -0
  44. package/dist/channels/slack/api.d.ts.map +1 -0
  45. package/dist/channels/slack/api.js +437 -0
  46. package/dist/channels/slack/approvals.d.ts +32 -0
  47. package/dist/channels/slack/approvals.d.ts.map +1 -0
  48. package/dist/channels/slack/approvals.js +157 -0
  49. package/dist/channels/slack/assistant.d.ts +23 -0
  50. package/dist/channels/slack/assistant.d.ts.map +1 -0
  51. package/dist/channels/slack/assistant.js +67 -0
  52. package/dist/channels/slack/auth.d.ts +40 -0
  53. package/dist/channels/slack/auth.d.ts.map +1 -0
  54. package/dist/channels/slack/auth.js +71 -0
  55. package/dist/channels/slack/channel-watch.d.ts +46 -0
  56. package/dist/channels/slack/channel-watch.d.ts.map +1 -0
  57. package/dist/channels/slack/channel-watch.js +180 -0
  58. package/dist/channels/slack/constants.d.ts +17 -0
  59. package/dist/channels/slack/constants.d.ts.map +1 -0
  60. package/dist/channels/slack/constants.js +27 -0
  61. package/dist/channels/slack/credentials.d.ts +35 -0
  62. package/dist/channels/slack/credentials.d.ts.map +1 -0
  63. package/dist/channels/slack/credentials.js +88 -0
  64. package/dist/channels/slack/cursor-account.d.ts +76 -0
  65. package/dist/channels/slack/cursor-account.d.ts.map +1 -0
  66. package/dist/channels/slack/cursor-account.js +88 -0
  67. package/dist/channels/slack/defaults.d.ts +32 -0
  68. package/dist/channels/slack/defaults.d.ts.map +1 -0
  69. package/dist/channels/slack/defaults.js +380 -0
  70. package/dist/channels/slack/dispatch.d.ts +43 -0
  71. package/dist/channels/slack/dispatch.d.ts.map +1 -0
  72. package/dist/channels/slack/dispatch.js +185 -0
  73. package/dist/channels/slack/doctor.d.ts +24 -0
  74. package/dist/channels/slack/doctor.d.ts.map +1 -0
  75. package/dist/channels/slack/doctor.js +115 -0
  76. package/dist/channels/slack/event-id-dedupe.d.ts +10 -0
  77. package/dist/channels/slack/event-id-dedupe.d.ts.map +1 -0
  78. package/dist/channels/slack/event-id-dedupe.js +23 -0
  79. package/dist/channels/slack/inbound.d.ts +41 -0
  80. package/dist/channels/slack/inbound.d.ts.map +1 -0
  81. package/dist/channels/slack/inbound.js +166 -0
  82. package/dist/channels/slack/index.d.ts +45 -0
  83. package/dist/channels/slack/index.d.ts.map +1 -0
  84. package/dist/channels/slack/index.js +44 -0
  85. package/dist/channels/slack/init.d.ts +32 -0
  86. package/dist/channels/slack/init.d.ts.map +1 -0
  87. package/dist/channels/slack/init.js +82 -0
  88. package/dist/channels/slack/interactive.d.ts +19 -0
  89. package/dist/channels/slack/interactive.d.ts.map +1 -0
  90. package/dist/channels/slack/interactive.js +142 -0
  91. package/dist/channels/slack/links.d.ts +10 -0
  92. package/dist/channels/slack/links.d.ts.map +1 -0
  93. package/dist/channels/slack/links.js +19 -0
  94. package/dist/channels/slack/live-delivery.d.ts +75 -0
  95. package/dist/channels/slack/live-delivery.d.ts.map +1 -0
  96. package/dist/channels/slack/live-delivery.js +143 -0
  97. package/dist/channels/slack/log.d.ts +25 -0
  98. package/dist/channels/slack/log.d.ts.map +1 -0
  99. package/dist/channels/slack/log.js +47 -0
  100. package/dist/channels/slack/manifest.d.ts +57 -0
  101. package/dist/channels/slack/manifest.d.ts.map +1 -0
  102. package/dist/channels/slack/manifest.js +110 -0
  103. package/dist/channels/slack/pr-ref.d.ts +18 -0
  104. package/dist/channels/slack/pr-ref.d.ts.map +1 -0
  105. package/dist/channels/slack/pr-ref.js +36 -0
  106. package/dist/channels/slack/setup.d.ts +14 -0
  107. package/dist/channels/slack/setup.d.ts.map +1 -0
  108. package/dist/channels/slack/setup.js +86 -0
  109. package/dist/channels/slack/slack-channel.d.ts +15 -0
  110. package/dist/channels/slack/slack-channel.d.ts.map +1 -0
  111. package/dist/channels/slack/slack-channel.js +281 -0
  112. package/dist/channels/slack/socket-mode.d.ts +26 -0
  113. package/dist/channels/slack/socket-mode.d.ts.map +1 -0
  114. package/dist/channels/slack/socket-mode.js +116 -0
  115. package/dist/channels/slack/stream.d.ts +26 -0
  116. package/dist/channels/slack/stream.d.ts.map +1 -0
  117. package/dist/channels/slack/stream.js +39 -0
  118. package/dist/channels/slack/tool-approval-events.d.ts +33 -0
  119. package/dist/channels/slack/tool-approval-events.d.ts.map +1 -0
  120. package/dist/channels/slack/tool-approval-events.js +129 -0
  121. package/dist/channels/slack/types.d.ts +326 -0
  122. package/dist/channels/slack/types.d.ts.map +1 -0
  123. package/dist/channels/slack/types.js +4 -0
  124. package/dist/channels.d.ts +116 -0
  125. package/dist/channels.d.ts.map +1 -0
  126. package/dist/channels.js +294 -0
  127. package/dist/connections.d.ts +75 -0
  128. package/dist/connections.d.ts.map +1 -0
  129. package/dist/connections.js +75 -0
  130. package/dist/docs/404.html +22 -0
  131. package/dist/docs/ab.html +87 -0
  132. package/dist/docs/assets/ab.md.COdXkces.js +63 -0
  133. package/dist/docs/assets/ab.md.COdXkces.lean.js +1 -0
  134. package/dist/docs/assets/app.DqfFEmJd.js +1 -0
  135. package/dist/docs/assets/building-with-agents.md.CJCtZCyi.js +13 -0
  136. package/dist/docs/assets/building-with-agents.md.CJCtZCyi.lean.js +1 -0
  137. package/dist/docs/assets/chunks/@localSearchIndexroot.CcVk1uKq.js +1 -0
  138. package/dist/docs/assets/chunks/VPLocalSearchBox.BaLEdS15.js +9 -0
  139. package/dist/docs/assets/chunks/framework.CAZyNGu9.js +19 -0
  140. package/dist/docs/assets/chunks/theme.CZRvu_0q.js +2 -0
  141. package/dist/docs/assets/concepts.md.Cfb9b-k1.js +4 -0
  142. package/dist/docs/assets/concepts.md.Cfb9b-k1.lean.js +1 -0
  143. package/dist/docs/assets/deployment.md.Dx1TYNk5.js +14 -0
  144. package/dist/docs/assets/deployment.md.Dx1TYNk5.lean.js +1 -0
  145. package/dist/docs/assets/evals.md.DPZ_MAnI.js +85 -0
  146. package/dist/docs/assets/evals.md.DPZ_MAnI.lean.js +1 -0
  147. package/dist/docs/assets/guides_agent-to-agent.md.CrtrsySy.js +10 -0
  148. package/dist/docs/assets/guides_agent-to-agent.md.CrtrsySy.lean.js +1 -0
  149. package/dist/docs/assets/guides_cloud-runtime.md.CYlNMTNp.js +9 -0
  150. package/dist/docs/assets/guides_cloud-runtime.md.CYlNMTNp.lean.js +1 -0
  151. package/dist/docs/assets/guides_github.md.DwbKhCeS.js +20 -0
  152. package/dist/docs/assets/guides_github.md.DwbKhCeS.lean.js +1 -0
  153. package/dist/docs/assets/guides_human-in-the-loop.md.Dvuctx7s.js +28 -0
  154. package/dist/docs/assets/guides_human-in-the-loop.md.Dvuctx7s.lean.js +1 -0
  155. package/dist/docs/assets/guides_slack.md.bv41fHfW.js +37 -0
  156. package/dist/docs/assets/guides_slack.md.bv41fHfW.lean.js +1 -0
  157. package/dist/docs/assets/guides_webhooks.md.hFTik3lf.js +50 -0
  158. package/dist/docs/assets/guides_webhooks.md.hFTik3lf.lean.js +1 -0
  159. package/dist/docs/assets/hillclimbing.md.DHNast08.js +4 -0
  160. package/dist/docs/assets/hillclimbing.md.DHNast08.lean.js +1 -0
  161. package/dist/docs/assets/index.md.BPKcj5AI.js +20 -0
  162. package/dist/docs/assets/index.md.BPKcj5AI.lean.js +1 -0
  163. package/dist/docs/assets/inter-italic-cyrillic-ext.r48I6akx.woff2 +0 -0
  164. package/dist/docs/assets/inter-italic-cyrillic.By2_1cv3.woff2 +0 -0
  165. package/dist/docs/assets/inter-italic-greek-ext.1u6EdAuj.woff2 +0 -0
  166. package/dist/docs/assets/inter-italic-greek.DJ8dCoTZ.woff2 +0 -0
  167. package/dist/docs/assets/inter-italic-latin-ext.CN1xVJS-.woff2 +0 -0
  168. package/dist/docs/assets/inter-italic-latin.C2AdPX0b.woff2 +0 -0
  169. package/dist/docs/assets/inter-italic-vietnamese.BSbpV94h.woff2 +0 -0
  170. package/dist/docs/assets/inter-roman-cyrillic-ext.BBPuwvHQ.woff2 +0 -0
  171. package/dist/docs/assets/inter-roman-cyrillic.C5lxZ8CY.woff2 +0 -0
  172. package/dist/docs/assets/inter-roman-greek-ext.CqjqNYQ-.woff2 +0 -0
  173. package/dist/docs/assets/inter-roman-greek.BBVDIX6e.woff2 +0 -0
  174. package/dist/docs/assets/inter-roman-latin-ext.4ZJIpNVo.woff2 +0 -0
  175. package/dist/docs/assets/inter-roman-latin.Di8DUHzh.woff2 +0 -0
  176. package/dist/docs/assets/inter-roman-vietnamese.BjW4sHH5.woff2 +0 -0
  177. package/dist/docs/assets/quickstart.md.tVPiGK_L.js +35 -0
  178. package/dist/docs/assets/quickstart.md.tVPiGK_L.lean.js +1 -0
  179. package/dist/docs/assets/reference_agent-config.md.Bpd7HQwf.js +34 -0
  180. package/dist/docs/assets/reference_agent-config.md.Bpd7HQwf.lean.js +1 -0
  181. package/dist/docs/assets/reference_channels.md.D7JTR03W.js +53 -0
  182. package/dist/docs/assets/reference_channels.md.D7JTR03W.lean.js +1 -0
  183. package/dist/docs/assets/reference_cli.md.DA730zCu.js +33 -0
  184. package/dist/docs/assets/reference_cli.md.DA730zCu.lean.js +1 -0
  185. package/dist/docs/assets/reference_connections.md.C3vNH_DE.js +26 -0
  186. package/dist/docs/assets/reference_connections.md.C3vNH_DE.lean.js +1 -0
  187. package/dist/docs/assets/reference_hooks.md.BCEc3MyM.js +12 -0
  188. package/dist/docs/assets/reference_hooks.md.BCEc3MyM.lean.js +1 -0
  189. package/dist/docs/assets/reference_http-api.md.DBAahtdz.js +11 -0
  190. package/dist/docs/assets/reference_http-api.md.DBAahtdz.lean.js +1 -0
  191. package/dist/docs/assets/reference_instructions.md.BC05LEQ8.js +12 -0
  192. package/dist/docs/assets/reference_instructions.md.BC05LEQ8.lean.js +1 -0
  193. package/dist/docs/assets/reference_playground.md.CPZhfYaO.js +1 -0
  194. package/dist/docs/assets/reference_playground.md.CPZhfYaO.lean.js +1 -0
  195. package/dist/docs/assets/reference_project-layout.md.Bd_CKtNS.js +31 -0
  196. package/dist/docs/assets/reference_project-layout.md.Bd_CKtNS.lean.js +1 -0
  197. package/dist/docs/assets/reference_schedules.md.D7qijxLk.js +82 -0
  198. package/dist/docs/assets/reference_schedules.md.D7qijxLk.lean.js +1 -0
  199. package/dist/docs/assets/reference_sessions.md.DdjWabnN.js +8 -0
  200. package/dist/docs/assets/reference_sessions.md.DdjWabnN.lean.js +1 -0
  201. package/dist/docs/assets/reference_skills.md.VQnlBT3Q.js +15 -0
  202. package/dist/docs/assets/reference_skills.md.VQnlBT3Q.lean.js +1 -0
  203. package/dist/docs/assets/reference_subagents.md.CIRAVcPK.js +10 -0
  204. package/dist/docs/assets/reference_subagents.md.CIRAVcPK.lean.js +1 -0
  205. package/dist/docs/assets/reference_tools.md.DF5kwlt0.js +46 -0
  206. package/dist/docs/assets/reference_tools.md.DF5kwlt0.lean.js +1 -0
  207. package/dist/docs/assets/scaffolding-agents.md.CyYfWGdc.js +1 -0
  208. package/dist/docs/assets/scaffolding-agents.md.CyYfWGdc.lean.js +1 -0
  209. package/dist/docs/assets/style.Bj-IXa5W.css +1 -0
  210. package/dist/docs/assets/troubleshooting.md.DkovjS7h.js +1 -0
  211. package/dist/docs/assets/troubleshooting.md.DkovjS7h.lean.js +1 -0
  212. package/dist/docs/building-with-agents.html +37 -0
  213. package/dist/docs/concepts.html +28 -0
  214. package/dist/docs/deployment.html +38 -0
  215. package/dist/docs/evals.html +109 -0
  216. package/dist/docs/guides/agent-to-agent.html +34 -0
  217. package/dist/docs/guides/cloud-runtime.html +33 -0
  218. package/dist/docs/guides/github.html +44 -0
  219. package/dist/docs/guides/human-in-the-loop.html +52 -0
  220. package/dist/docs/guides/slack.html +61 -0
  221. package/dist/docs/guides/webhooks.html +74 -0
  222. package/dist/docs/hashmap.json +1 -0
  223. package/dist/docs/hillclimbing.html +28 -0
  224. package/dist/docs/index.html +44 -0
  225. package/dist/docs/quickstart.html +59 -0
  226. package/dist/docs/reference/agent-config.html +58 -0
  227. package/dist/docs/reference/channels.html +77 -0
  228. package/dist/docs/reference/cli.html +57 -0
  229. package/dist/docs/reference/connections.html +50 -0
  230. package/dist/docs/reference/hooks.html +36 -0
  231. package/dist/docs/reference/http-api.html +35 -0
  232. package/dist/docs/reference/instructions.html +36 -0
  233. package/dist/docs/reference/playground.html +25 -0
  234. package/dist/docs/reference/project-layout.html +55 -0
  235. package/dist/docs/reference/schedules.html +106 -0
  236. package/dist/docs/reference/sessions.html +32 -0
  237. package/dist/docs/reference/skills.html +39 -0
  238. package/dist/docs/reference/subagents.html +34 -0
  239. package/dist/docs/reference/tools.html +70 -0
  240. package/dist/docs/scaffolding-agents.html +25 -0
  241. package/dist/docs/troubleshooting.html +25 -0
  242. package/dist/docs/vp-icons.css +0 -0
  243. package/dist/evals.d.ts +312 -0
  244. package/dist/evals.d.ts.map +1 -0
  245. package/dist/evals.js +254 -0
  246. package/dist/hooks.d.ts +23 -0
  247. package/dist/hooks.d.ts.map +1 -0
  248. package/dist/hooks.js +23 -0
  249. package/dist/index.d.ts +71 -0
  250. package/dist/index.d.ts.map +1 -0
  251. package/dist/index.js +101 -0
  252. package/dist/internal/ab-collector.d.ts +42 -0
  253. package/dist/internal/ab-collector.d.ts.map +1 -0
  254. package/dist/internal/ab-collector.js +153 -0
  255. package/dist/internal/ab-fold.d.ts +36 -0
  256. package/dist/internal/ab-fold.d.ts.map +1 -0
  257. package/dist/internal/ab-fold.js +171 -0
  258. package/dist/internal/ab-snapshot.d.ts +70 -0
  259. package/dist/internal/ab-snapshot.d.ts.map +1 -0
  260. package/dist/internal/ab-snapshot.js +208 -0
  261. package/dist/internal/approval-gate.d.ts +34 -0
  262. package/dist/internal/approval-gate.d.ts.map +1 -0
  263. package/dist/internal/approval-gate.js +85 -0
  264. package/dist/internal/auth.d.ts +8 -0
  265. package/dist/internal/auth.d.ts.map +1 -0
  266. package/dist/internal/auth.js +27 -0
  267. package/dist/internal/authored-alias-hooks.d.ts +31 -0
  268. package/dist/internal/authored-alias-hooks.d.ts.map +1 -0
  269. package/dist/internal/authored-alias-hooks.js +43 -0
  270. package/dist/internal/authored-loaders.d.ts +25 -0
  271. package/dist/internal/authored-loaders.d.ts.map +1 -0
  272. package/dist/internal/authored-loaders.js +129 -0
  273. package/dist/internal/bounded-int.d.ts +11 -0
  274. package/dist/internal/bounded-int.d.ts.map +1 -0
  275. package/dist/internal/bounded-int.js +13 -0
  276. package/dist/internal/brand.d.ts +6 -0
  277. package/dist/internal/brand.d.ts.map +1 -0
  278. package/dist/internal/brand.js +17 -0
  279. package/dist/internal/chat-client.d.ts +19 -0
  280. package/dist/internal/chat-client.d.ts.map +1 -0
  281. package/dist/internal/chat-client.js +327 -0
  282. package/dist/internal/cli-ax.d.ts +58 -0
  283. package/dist/internal/cli-ax.d.ts.map +1 -0
  284. package/dist/internal/cli-ax.js +345 -0
  285. package/dist/internal/cli-cursor.d.ts +20 -0
  286. package/dist/internal/cli-cursor.d.ts.map +1 -0
  287. package/dist/internal/cli-cursor.js +227 -0
  288. package/dist/internal/cli-github.d.ts +47 -0
  289. package/dist/internal/cli-github.d.ts.map +1 -0
  290. package/dist/internal/cli-github.js +644 -0
  291. package/dist/internal/cli-slack.d.ts +18 -0
  292. package/dist/internal/cli-slack.d.ts.map +1 -0
  293. package/dist/internal/cli-slack.js +144 -0
  294. package/dist/internal/cloud-merge.d.ts +23 -0
  295. package/dist/internal/cloud-merge.d.ts.map +1 -0
  296. package/dist/internal/cloud-merge.js +28 -0
  297. package/dist/internal/cron.d.ts +17 -0
  298. package/dist/internal/cron.d.ts.map +1 -0
  299. package/dist/internal/cron.js +60 -0
  300. package/dist/internal/cursor/account-mcp.d.ts +95 -0
  301. package/dist/internal/cursor/account-mcp.d.ts.map +1 -0
  302. package/dist/internal/cursor/account-mcp.js +342 -0
  303. package/dist/internal/cursor/backend-client.d.ts +118 -0
  304. package/dist/internal/cursor/backend-client.d.ts.map +1 -0
  305. package/dist/internal/cursor/backend-client.js +477 -0
  306. package/dist/internal/cursor/credentials.d.ts +112 -0
  307. package/dist/internal/cursor/credentials.d.ts.map +1 -0
  308. package/dist/internal/cursor/credentials.js +329 -0
  309. package/dist/internal/cursor-event-relay.d.ts +111 -0
  310. package/dist/internal/cursor-event-relay.d.ts.map +1 -0
  311. package/dist/internal/cursor-event-relay.js +181 -0
  312. package/dist/internal/cursor-relay-core.d.ts +113 -0
  313. package/dist/internal/cursor-relay-core.d.ts.map +1 -0
  314. package/dist/internal/cursor-relay-core.js +364 -0
  315. package/dist/internal/cursor-slack-relay.d.ts +94 -0
  316. package/dist/internal/cursor-slack-relay.d.ts.map +1 -0
  317. package/dist/internal/cursor-slack-relay.js +171 -0
  318. package/dist/internal/describe-error.d.ts +3 -0
  319. package/dist/internal/describe-error.d.ts.map +1 -0
  320. package/dist/internal/describe-error.js +4 -0
  321. package/dist/internal/dev-mode.d.ts +13 -0
  322. package/dist/internal/dev-mode.d.ts.map +1 -0
  323. package/dist/internal/dev-mode.js +17 -0
  324. package/dist/internal/discovery.d.ts +55 -0
  325. package/dist/internal/discovery.d.ts.map +1 -0
  326. package/dist/internal/discovery.js +1427 -0
  327. package/dist/internal/distribution.d.ts +47 -0
  328. package/dist/internal/distribution.d.ts.map +1 -0
  329. package/dist/internal/distribution.js +82 -0
  330. package/dist/internal/docs-site.d.ts +28 -0
  331. package/dist/internal/docs-site.d.ts.map +1 -0
  332. package/dist/internal/docs-site.js +169 -0
  333. package/dist/internal/duration.d.ts +8 -0
  334. package/dist/internal/duration.d.ts.map +1 -0
  335. package/dist/internal/duration.js +35 -0
  336. package/dist/internal/eval-run-store.d.ts +81 -0
  337. package/dist/internal/eval-run-store.d.ts.map +1 -0
  338. package/dist/internal/eval-run-store.js +396 -0
  339. package/dist/internal/eval-runner.d.ts +76 -0
  340. package/dist/internal/eval-runner.d.ts.map +1 -0
  341. package/dist/internal/eval-runner.js +336 -0
  342. package/dist/internal/event-log.d.ts +51 -0
  343. package/dist/internal/event-log.d.ts.map +1 -0
  344. package/dist/internal/event-log.js +167 -0
  345. package/dist/internal/event-mapper.d.ts +46 -0
  346. package/dist/internal/event-mapper.d.ts.map +1 -0
  347. package/dist/internal/event-mapper.js +226 -0
  348. package/dist/internal/frontmatter.d.ts +12 -0
  349. package/dist/internal/frontmatter.d.ts.map +1 -0
  350. package/dist/internal/frontmatter.js +61 -0
  351. package/dist/internal/github-fanout.d.ts +32 -0
  352. package/dist/internal/github-fanout.d.ts.map +1 -0
  353. package/dist/internal/github-fanout.js +122 -0
  354. package/dist/internal/handleAgentServeTrigger.d.ts +59 -0
  355. package/dist/internal/handleAgentServeTrigger.d.ts.map +1 -0
  356. package/dist/internal/handleAgentServeTrigger.js +115 -0
  357. package/dist/internal/host-platforms.d.ts +40 -0
  358. package/dist/internal/host-platforms.d.ts.map +1 -0
  359. package/dist/internal/host-platforms.js +113 -0
  360. package/dist/internal/http-channel.d.ts +54 -0
  361. package/dist/internal/http-channel.d.ts.map +1 -0
  362. package/dist/internal/http-channel.js +382 -0
  363. package/dist/internal/ids.d.ts +19 -0
  364. package/dist/internal/ids.d.ts.map +1 -0
  365. package/dist/internal/ids.js +34 -0
  366. package/dist/internal/init-project.d.ts +22 -0
  367. package/dist/internal/init-project.d.ts.map +1 -0
  368. package/dist/internal/init-project.js +125 -0
  369. package/dist/internal/json-dir-store.d.ts +32 -0
  370. package/dist/internal/json-dir-store.d.ts.map +1 -0
  371. package/dist/internal/json-dir-store.js +100 -0
  372. package/dist/internal/json-schema.d.ts +18 -0
  373. package/dist/internal/json-schema.d.ts.map +1 -0
  374. package/dist/internal/json-schema.js +53 -0
  375. package/dist/internal/log-ring.d.ts +23 -0
  376. package/dist/internal/log-ring.d.ts.map +1 -0
  377. package/dist/internal/log-ring.js +42 -0
  378. package/dist/internal/map-pool.d.ts +6 -0
  379. package/dist/internal/map-pool.d.ts.map +1 -0
  380. package/dist/internal/map-pool.js +41 -0
  381. package/dist/internal/mcp-endpoint.d.ts +59 -0
  382. package/dist/internal/mcp-endpoint.d.ts.map +1 -0
  383. package/dist/internal/mcp-endpoint.js +355 -0
  384. package/dist/internal/mcp-host.d.ts +28 -0
  385. package/dist/internal/mcp-host.d.ts.map +1 -0
  386. package/dist/internal/mcp-host.js +162 -0
  387. package/dist/internal/net.d.ts +5 -0
  388. package/dist/internal/net.d.ts.map +1 -0
  389. package/dist/internal/net.js +30 -0
  390. package/dist/internal/peer-connections.d.ts +44 -0
  391. package/dist/internal/peer-connections.d.ts.map +1 -0
  392. package/dist/internal/peer-connections.js +67 -0
  393. package/dist/internal/playground/static.d.ts +35 -0
  394. package/dist/internal/playground/static.d.ts.map +1 -0
  395. package/dist/internal/playground/static.js +162 -0
  396. package/dist/internal/playground/toolchain.d.ts +57 -0
  397. package/dist/internal/playground/toolchain.d.ts.map +1 -0
  398. package/dist/internal/playground/toolchain.js +226 -0
  399. package/dist/internal/reminder-runner.d.ts +62 -0
  400. package/dist/internal/reminder-runner.d.ts.map +1 -0
  401. package/dist/internal/reminder-runner.js +582 -0
  402. package/dist/internal/reminder-schedule.d.ts +22 -0
  403. package/dist/internal/reminder-schedule.d.ts.map +1 -0
  404. package/dist/internal/reminder-schedule.js +82 -0
  405. package/dist/internal/reminder-store.d.ts +58 -0
  406. package/dist/internal/reminder-store.d.ts.map +1 -0
  407. package/dist/internal/reminder-store.js +106 -0
  408. package/dist/internal/resolved-connections.d.ts +41 -0
  409. package/dist/internal/resolved-connections.d.ts.map +1 -0
  410. package/dist/internal/resolved-connections.js +73 -0
  411. package/dist/internal/review-comments.d.ts +50 -0
  412. package/dist/internal/review-comments.d.ts.map +1 -0
  413. package/dist/internal/review-comments.js +194 -0
  414. package/dist/internal/router.d.ts +33 -0
  415. package/dist/internal/router.d.ts.map +1 -0
  416. package/dist/internal/router.js +93 -0
  417. package/dist/internal/run-client.d.ts +49 -0
  418. package/dist/internal/run-client.d.ts.map +1 -0
  419. package/dist/internal/run-client.js +208 -0
  420. package/dist/internal/schedule-runner.d.ts +31 -0
  421. package/dist/internal/schedule-runner.d.ts.map +1 -0
  422. package/dist/internal/schedule-runner.js +126 -0
  423. package/dist/internal/sdk-runner.d.ts +41 -0
  424. package/dist/internal/sdk-runner.d.ts.map +1 -0
  425. package/dist/internal/sdk-runner.js +221 -0
  426. package/dist/internal/server.d.ts +25 -0
  427. package/dist/internal/server.d.ts.map +1 -0
  428. package/dist/internal/server.js +1374 -0
  429. package/dist/internal/session-engine.d.ts +287 -0
  430. package/dist/internal/session-engine.d.ts.map +1 -0
  431. package/dist/internal/session-engine.js +1377 -0
  432. package/dist/internal/session-store.d.ts +29 -0
  433. package/dist/internal/session-store.d.ts.map +1 -0
  434. package/dist/internal/session-store.js +140 -0
  435. package/dist/internal/session-urls.d.ts +10 -0
  436. package/dist/internal/session-urls.d.ts.map +1 -0
  437. package/dist/internal/session-urls.js +25 -0
  438. package/dist/internal/stream-progress.d.ts +14 -0
  439. package/dist/internal/stream-progress.d.ts.map +1 -0
  440. package/dist/internal/stream-progress.js +195 -0
  441. package/dist/internal/tool-result.d.ts +20 -0
  442. package/dist/internal/tool-result.d.ts.map +1 -0
  443. package/dist/internal/tool-result.js +45 -0
  444. package/dist/internal/trajectory.d.ts +56 -0
  445. package/dist/internal/trajectory.d.ts.map +1 -0
  446. package/dist/internal/trajectory.js +248 -0
  447. package/dist/internal/workspace.d.ts +42 -0
  448. package/dist/internal/workspace.d.ts.map +1 -0
  449. package/dist/internal/workspace.js +199 -0
  450. package/dist/playground/assets/cursor-icons-outline-oY2V_mvK.woff2 +0 -0
  451. package/dist/playground/assets/index-1K-hG-7p.css +1 -0
  452. package/dist/playground/assets/index-FlWjhg3x.js +79 -0
  453. package/dist/playground/index.html +17 -0
  454. package/dist/reminders.d.ts +23 -0
  455. package/dist/reminders.d.ts.map +1 -0
  456. package/dist/reminders.js +22 -0
  457. package/dist/schedules.d.ts +23 -0
  458. package/dist/schedules.d.ts.map +1 -0
  459. package/dist/schedules.js +26 -0
  460. package/dist/skills.d.ts +22 -0
  461. package/dist/skills.d.ts.map +1 -0
  462. package/dist/skills.js +22 -0
  463. package/dist/tools.d.ts +92 -0
  464. package/dist/tools.d.ts.map +1 -0
  465. package/dist/tools.js +68 -0
  466. package/dist/types.d.ts +1609 -0
  467. package/dist/types.d.ts.map +1 -0
  468. package/dist/types.js +80 -0
  469. package/docs/README.md +174 -0
  470. package/docs/ab.md +355 -0
  471. package/docs/building-with-agents.md +129 -0
  472. package/docs/concepts.md +177 -0
  473. package/docs/deployment.md +218 -0
  474. package/docs/evals.md +383 -0
  475. package/docs/guides/agent-to-agent.md +118 -0
  476. package/docs/guides/cloud-runtime.md +122 -0
  477. package/docs/guides/github.md +172 -0
  478. package/docs/guides/human-in-the-loop.md +131 -0
  479. package/docs/guides/slack.md +245 -0
  480. package/docs/guides/webhooks.md +201 -0
  481. package/docs/hillclimbing.md +93 -0
  482. package/docs/quickstart.md +183 -0
  483. package/docs/reference/agent-config.md +154 -0
  484. package/docs/reference/channels.md +206 -0
  485. package/docs/reference/cli.md +257 -0
  486. package/docs/reference/connections.md +137 -0
  487. package/docs/reference/hooks.md +74 -0
  488. package/docs/reference/http-api.md +219 -0
  489. package/docs/reference/instructions.md +77 -0
  490. package/docs/reference/playground.md +67 -0
  491. package/docs/reference/project-layout.md +119 -0
  492. package/docs/reference/schedules.md +220 -0
  493. package/docs/reference/sessions.md +165 -0
  494. package/docs/reference/skills.md +79 -0
  495. package/docs/reference/subagents.md +74 -0
  496. package/docs/reference/tools.md +203 -0
  497. package/docs/scaffolding-agents.md +113 -0
  498. package/docs/troubleshooting.md +95 -0
  499. package/package.json +185 -0
  500. package/skills/ab/SKILL.md +139 -0
  501. package/skills/create-agent/SKILL.md +219 -0
  502. package/skills/debug/SKILL.md +71 -0
  503. package/skills/evals/SKILL.md +217 -0
  504. package/skills/framework-map/SKILL.md +142 -0
  505. package/skills/github/SKILL.md +144 -0
  506. package/skills/hillclimb/SKILL.md +162 -0
  507. package/skills/setup-slack/SKILL.md +180 -0
  508. package/src/ab.ts +675 -0
  509. package/src/bin/agent-serve.ts +949 -0
  510. package/src/channels/github/api.ts +374 -0
  511. package/src/channels/github/auth.ts +275 -0
  512. package/src/channels/github/binding.ts +223 -0
  513. package/src/channels/github/defaults.ts +111 -0
  514. package/src/channels/github/events.ts +72 -0
  515. package/src/channels/github/forward.ts +381 -0
  516. package/src/channels/github/github-channel.ts +2270 -0
  517. package/src/channels/github/index.ts +52 -0
  518. package/src/channels/github/replay.ts +387 -0
  519. package/src/channels/github/state.ts +95 -0
  520. package/src/channels/github/types.ts +490 -0
  521. package/src/channels/slack/api.ts +580 -0
  522. package/src/channels/slack/approvals.ts +198 -0
  523. package/src/channels/slack/assistant.ts +76 -0
  524. package/src/channels/slack/auth.ts +112 -0
  525. package/src/channels/slack/channel-watch.ts +219 -0
  526. package/src/channels/slack/constants.ts +30 -0
  527. package/src/channels/slack/credentials.ts +90 -0
  528. package/src/channels/slack/cursor-account.ts +166 -0
  529. package/src/channels/slack/defaults.ts +450 -0
  530. package/src/channels/slack/dispatch.ts +293 -0
  531. package/src/channels/slack/doctor.ts +135 -0
  532. package/src/channels/slack/event-id-dedupe.ts +30 -0
  533. package/src/channels/slack/inbound.ts +219 -0
  534. package/src/channels/slack/index.ts +45 -0
  535. package/src/channels/slack/init.ts +133 -0
  536. package/src/channels/slack/interactive.ts +194 -0
  537. package/src/channels/slack/links.ts +23 -0
  538. package/src/channels/slack/live-delivery.ts +201 -0
  539. package/src/channels/slack/log.ts +83 -0
  540. package/src/channels/slack/manifest.ts +179 -0
  541. package/src/channels/slack/pr-ref.ts +50 -0
  542. package/src/channels/slack/setup.ts +97 -0
  543. package/src/channels/slack/slack-channel.ts +374 -0
  544. package/src/channels/slack/socket-mode.ts +154 -0
  545. package/src/channels/slack/stream.ts +63 -0
  546. package/src/channels/slack/tool-approval-events.ts +136 -0
  547. package/src/channels/slack/types.ts +349 -0
  548. package/src/channels.ts +385 -0
  549. package/src/connections.ts +89 -0
  550. package/src/evals.ts +501 -0
  551. package/src/hooks.ts +33 -0
  552. package/src/index.ts +184 -0
  553. package/src/internal/ab-collector.ts +210 -0
  554. package/src/internal/ab-fold.ts +228 -0
  555. package/src/internal/ab-snapshot.ts +335 -0
  556. package/src/internal/approval-gate.ts +115 -0
  557. package/src/internal/auth.ts +39 -0
  558. package/src/internal/authored-alias-hooks.ts +69 -0
  559. package/src/internal/authored-loaders.ts +138 -0
  560. package/src/internal/bounded-int.ts +27 -0
  561. package/src/internal/brand.ts +29 -0
  562. package/src/internal/chat-client.ts +407 -0
  563. package/src/internal/cli-ax.ts +474 -0
  564. package/src/internal/cli-cursor.ts +275 -0
  565. package/src/internal/cli-github.ts +849 -0
  566. package/src/internal/cli-slack.ts +175 -0
  567. package/src/internal/cloud-merge.ts +41 -0
  568. package/src/internal/cron.ts +78 -0
  569. package/src/internal/cursor/account-mcp.ts +472 -0
  570. package/src/internal/cursor/backend-client.ts +614 -0
  571. package/src/internal/cursor/credentials.ts +401 -0
  572. package/src/internal/cursor-event-relay.ts +281 -0
  573. package/src/internal/cursor-relay-core.ts +444 -0
  574. package/src/internal/cursor-slack-relay.ts +242 -0
  575. package/src/internal/describe-error.ts +4 -0
  576. package/src/internal/dev-mode.ts +20 -0
  577. package/src/internal/discovery.ts +1709 -0
  578. package/src/internal/distribution.ts +97 -0
  579. package/src/internal/docs-site.ts +191 -0
  580. package/src/internal/duration.ts +39 -0
  581. package/src/internal/eval-run-store.ts +519 -0
  582. package/src/internal/eval-runner.ts +522 -0
  583. package/src/internal/event-log.ts +175 -0
  584. package/src/internal/event-mapper.ts +272 -0
  585. package/src/internal/frontmatter.ts +77 -0
  586. package/src/internal/github-fanout.ts +159 -0
  587. package/src/internal/handleAgentServeTrigger.ts +156 -0
  588. package/src/internal/host-platforms.ts +144 -0
  589. package/src/internal/http-channel.ts +546 -0
  590. package/src/internal/ids.ts +44 -0
  591. package/src/internal/init-project.ts +165 -0
  592. package/src/internal/json-dir-store.ts +109 -0
  593. package/src/internal/json-schema.ts +69 -0
  594. package/src/internal/log-ring.ts +59 -0
  595. package/src/internal/map-pool.ts +32 -0
  596. package/src/internal/mcp-endpoint.ts +518 -0
  597. package/src/internal/mcp-host.ts +211 -0
  598. package/src/internal/net.ts +31 -0
  599. package/src/internal/peer-connections.ts +100 -0
  600. package/src/internal/playground/static.ts +189 -0
  601. package/src/internal/playground/toolchain.ts +277 -0
  602. package/src/internal/reminder-runner.ts +756 -0
  603. package/src/internal/reminder-schedule.ts +106 -0
  604. package/src/internal/reminder-store.ts +145 -0
  605. package/src/internal/resolved-connections.ts +145 -0
  606. package/src/internal/review-comments.ts +268 -0
  607. package/src/internal/router.ts +145 -0
  608. package/src/internal/run-client.ts +320 -0
  609. package/src/internal/schedule-runner.ts +161 -0
  610. package/src/internal/sdk-runner.ts +315 -0
  611. package/src/internal/server.ts +1737 -0
  612. package/src/internal/session-engine.ts +1810 -0
  613. package/src/internal/session-store.ts +147 -0
  614. package/src/internal/session-urls.ts +40 -0
  615. package/src/internal/stream-progress.ts +254 -0
  616. package/src/internal/tool-result.ts +54 -0
  617. package/src/internal/trajectory.ts +306 -0
  618. package/src/internal/workspace.ts +223 -0
  619. package/src/reminders.ts +35 -0
  620. package/src/schedules.ts +37 -0
  621. package/src/skills.ts +27 -0
  622. package/src/tools.ts +127 -0
  623. package/src/types.ts +1848 -0
@@ -0,0 +1,139 @@
1
+ ---
2
+ name: agent-serve-ab
3
+ description: >-
4
+ Author defineAB live A/B metrics plug-ins under agent/ab. Splits traffic into
5
+ sticky variants and calls onSample with performance metrics as the agent runs
6
+ — not a test runner. Use when instrumenting production/dev traffic for variant
7
+ comparison; use defineEval for regression gates.
8
+ ---
9
+
10
+ # agent-serve A/B metrics (`defineAB`)
11
+
12
+ `defineAB` is a **live metrics plug-in**. At session creation the engine runs
13
+ `split` and appends durable `ab.assigned` events; the collector folds the
14
+ session event stream and calls `onSample`. There is **no** `agent-serve ab`
15
+ CLI and **no** assertion API.
16
+
17
+ Human-facing reference: [`docs/ab.md`](../../docs/ab.md).
18
+
19
+ | | `defineEval` | `defineAB` |
20
+ | --- | --- | --- |
21
+ | Job | Regression gates on frozen fixtures | Collect metrics on live runs |
22
+ | Location | `evals/**/*.eval.ts` | `agent/ab.ts` or `agent/ab/<name>.ts` |
23
+ | How it runs | `agent-serve eval` | Automatically under `serve` / `run` |
24
+ | Driver | `t.send` + gates | `split` → `ab.assigned` + `onSample` |
25
+
26
+ ## Authoring
27
+
28
+ ```ts
29
+ import { defineAB, splitBySessionHash, splitIf } from "@anysphere/agent-serve/ab";
30
+
31
+ export default defineAB({
32
+ name: "concise-instructions",
33
+ variants: {
34
+ control: { label: "Baseline" },
35
+ treatment: {
36
+ label: "Shorter",
37
+ // Optional: appended to agent instructions for this arm.
38
+ instructions: "Keep replies to one short paragraph.",
39
+ },
40
+ },
41
+ split: splitBySessionHash({ holdout: 0.1 }),
42
+ derive: {
43
+ // Keep sync + cheap — runs on every event, including message deltas.
44
+ weatherCalls: (event) =>
45
+ event.type === "action.result" && event.data.toolName === "get_weather"
46
+ ? 1
47
+ : null,
48
+ },
49
+ onSample(sample) {
50
+ console.log(sample.variant, sample.metrics.toolCalls, sample.metrics.wallTimeMs);
51
+ },
52
+ });
53
+ ```
54
+
55
+ In tools, read the arm from session context:
56
+
57
+ ```ts
58
+ async execute(input, ctx) {
59
+ if (ctx.session.abs?.["concise-instructions"] === "treatment") {
60
+ // treatment-specific behavior
61
+ }
62
+ }
63
+ ```
64
+
65
+
66
+ Discovery: `agent/ab.ts` and `agent/ab/*.ts`. Name defaults to file stem or `config.name`.
67
+
68
+ Optional project defaults in `agent/ab.config.ts` (retention + persistence):
69
+
70
+ ```ts
71
+ import {
72
+ defineABConfig,
73
+ persistABSamplesToDir,
74
+ persistABSnapshotsToDir,
75
+ } from "@anysphere/agent-serve/ab";
76
+
77
+ export default defineABConfig({
78
+ // maxPlaygroundSessions: 200, // optional; default 200; A/Bs tab / GET /v1/abs only
79
+ persistSamples: persistABSamplesToDir(".agent-serve/ab-samples"),
80
+ persistSnapshots: persistABSnapshotsToDir(".agent-serve/ab-snapshots"),
81
+ });
82
+ ```
83
+
84
+ Session `events.ndjson` remains the assignment/metrics source of truth.
85
+ `persistSamples` / `persistSnapshots` are author-controlled exports (like
86
+ eval `persistRuns`).
87
+
88
+ ### Stream model
89
+
90
+ Typical new-session prefix:
91
+
92
+ 1. `session.started`
93
+ 2. one `ab.assigned` per experiment (`variant` key or `null` skip)
94
+ 3. `message.received` / `turn.started` / …
95
+
96
+ Enrollment is **at session creation** (before the first turn) so each arm can
97
+ vary instructions and tool behavior from a known assignment. Failed/`null`
98
+ splits persist as `ab.assigned` with `variant: null` (sticky skip). The
99
+ collector is a pure fold over the log. `SessionRecord.abs` is a convenience
100
+ mirror, not a metrics store. After park/restart it replays `events.ndjson` to
101
+ rebuild counters without re-firing `onSample`.
102
+
103
+ **Evals are separate:** the eval harness creates sessions with
104
+ `purpose: "eval"` (playground Evals / `agent-serve eval`). Those skip
105
+ enrollment entirely — no `ab.assigned`, no `onSample`, omitted from
106
+ `GET /v1/abs`. Ordinary chat / `agent-serve run` / Slack stay `"live"`.
107
+ Do not use `splitIf` to filter evals; the framework already does.
108
+
109
+ After enrollment, arms are on `session.abs` (experiment → variant | `null`)
110
+ for tools/hooks, and optional per-variant `instructions` are appended to the
111
+ agent prompt for that session (a treatment arm can, say, switch `get_weather`
112
+ to °C for its sessions).
113
+
114
+ ### Split helpers
115
+
116
+ | Helper | Behavior |
117
+ | --- | --- |
118
+ | `splitBySessionHash({ weights?, holdout?, salt? })` | Sticky hash → arm |
119
+ | `splitByRandom({ weights?, holdout? })` | Random once, then sticky |
120
+ | `splitAlways("control")` | Pin all new sessions |
121
+ | `splitNone()` | Skip everyone (pause in place) |
122
+ | `splitIf(pred, inner)` | Skip unless `pred` |
123
+ | `(ctx) => …` | Custom — variant key or `null` |
124
+
125
+ ### Built-in metrics
126
+
127
+ `turns`, `turnFailures`, `toolCalls`, `toolErrors`, token fields, `wallTimeMs`,
128
+ plus `custom.*` from `derive`. `onSample` fires on `turn.completed` / `turn.failed`.
129
+
130
+ Playground **A/Bs** tab and `GET /v1/abs` fold the same durable streams into
131
+ per-session assignments and aggregate arm totals (no separate metrics store).
132
+
133
+ ### `derive` cost
134
+
135
+ `derive` extractors run on **every** session event (same cost model as hooks).
136
+ Keep them synchronous and cheap — no network, no disk, no heavy parsing.
137
+
138
+ Before wiring: pick experiment name + arm labels, a split helper (and who
139
+ to leave out), and a real `onSample` sink — do not invent credentials.
@@ -0,0 +1,219 @@
1
+ ---
2
+ name: agent-serve-create-agent
3
+ description: >-
4
+ Scaffold a new agent-serve agent through a guided AskQuestion interview —
5
+ purpose, name, runtime, model, channels, MCP connections, capabilities —
6
+ then verify it serves and hand off to hillclimbing. Read this skill when
7
+ creating a new agent.
8
+ paths:
9
+ - packages/agent-serve/**/*
10
+ ---
11
+
12
+ # Create an agent-serve agent
13
+
14
+ Stand up one new agent project via a short interview, scaffold it, get
15
+ channels working
16
+ with the user, prove a turn runs end-to-end, and set up the improvement loop.
17
+ Sibling skills: `framework-map` for orientation, `setup-slack` for Slack
18
+ wiring, `github` for webhook-driven agents, `evals` for the eval API,
19
+ `ab` for live A/B metrics, `hillclimb` for iteration once the agent runs.
20
+
21
+ Read `framework-map/SKILL.md` first if you haven't; treat the package
22
+ `AGENTS.md` and `README.md` as ground truth for
23
+ framework behavior. Run the CLI with Node, never Bun (Bun corrupts harness
24
+ tool-result streams): use the installed `agent-serve` bin, or from a source
25
+ checkout `pnpm exec tsx src/bin/agent-serve.ts <command> …` — written as
26
+ `agent-serve …` below.
27
+
28
+ ## Interview
29
+
30
+ Walk the user through the decisions with the `AskQuestion` tool: batched
31
+ questions, concrete options, the recommended option listed first and labeled
32
+ `(recommended)` so one click accepts it. Rules:
33
+
34
+ - **Mine the invoking message first.** Never ask a question it already
35
+ answers. Target: at most two rounds before files appear.
36
+ - **Stage the rounds.** Round 1 fixes identity; round 2 fixes the surface and
37
+ is tailored by round 1 (no MCP question for a chat toy, no cloud-repos
38
+ question for local runtime).
39
+ - Use multi-select (`allow_multiple: true`) for channels, MCP connections, and
40
+ capabilities; single-select elsewhere. Add an "Other" option wherever a
41
+ custom answer is plausible (name, model, MCP server) — its freeform text is
42
+ the answer.
43
+ - **Ask about decisions, not implementation.** Instructions wording, tool
44
+ names, file layout, env prefix, and eval shape are your job — derive them
45
+ from the purpose and show the result instead of asking.
46
+ - If `AskQuestion` is unavailable or the user says "just go", state the
47
+ defaults you are assuming in one short list and proceed.
48
+
49
+ ### Round 1 — identity
50
+
51
+ | Question | Options |
52
+ | --- | --- |
53
+ | **Purpose** | chat assistant · PR / repo automation · domain assistant over APIs/tools · scheduled reporter · Other (describe) |
54
+ | **Name** | 2–3 slug suggestions derived from the purpose + Other. Slug = directory name: `[A-Za-z0-9][A-Za-z0-9_-]*`, not `v1`/`playground`/`docs`; lowercase-hyphenated |
55
+ | **Location** | `./<slug>` (default) · another directory (user names it) |
56
+
57
+ ### Round 2 — surface
58
+
59
+ | Question | Options | Guidance |
60
+ | --- | --- | --- |
61
+ | **Runtime** | `local` (default) · `cloud` | Local = Cursor SDK harness on this machine; server tools, skills, sandbox seeds, and tool approvals all work. Cloud = Cursor cloud agents; needs `cloud.repos`, no server tools/skills/sandbox seeds (instructions are prepended to the first prompt). Recommend local unless the purpose needs a repo checkout on a cloud VM. |
62
+ | **Model** | `grok-4.5` with `effort=high`, `fast=true` (default) · Other model id | Effort and fast are params, not id suffixes: `{ id: "grok-4.5", params: [{ id: "effort", value: "high" }, { id: "fast", value: "true" }] }` — the SDK rejects suffix-style ids. |
63
+ | **Channels** (multi) | playground + HTTP API only (always mounted) · Slack · GitHub webhooks · custom webhook · schedule (cron) | Slack is Socket Mode with one app + token pair per agent. GitHub verifies `X-Hub-Signature-256` when a secret is set. Discord/Teams packs do not exist yet — offer custom webhook instead. |
64
+ | **MCP connections** (multi) | none · remote server (URL + header auth) · local stdio server · Other | One file per server under `agent/mcp-connections/`; filename = server name; tokens via env vars, never hardcoded. MCP connections serve the model **and** host code (`ctx.host.mcp`, channel `host.mcp`). |
65
+ | **Capabilities** (multi) | server tools · agent tools (scripts) · skills · subagents · hooks · sandbox seed files · tool approvals (HITL) · evals (recommend) | Server tools, skills, sandbox seeds, approvals are local-runtime only. Agent tools (`execution: "agent"`) work on both runtimes. Always recommend at least one smoke eval. |
66
+
67
+ Close the round with a one-screen plan — chosen options plus the file tree you
68
+ intend to create — and a final gate: "Scaffold it" / "Adjust something". Only
69
+ write files after approval.
70
+
71
+ ## Fill in the blanks
72
+
73
+ Everything the interview did not fix is yours to decide. Derive it from the
74
+ purpose, and reach for the proven shape instead of
75
+ inventing:
76
+
77
+ | Purpose looks like | Proven shape |
78
+ | --- | --- |
79
+ | Slack chat assistant | minimal `slackChannel()` pack with suggested prompts |
80
+ | PR review with host-prepared evidence | channel `callTool` prep into a trimmed workspace `pr/` tree |
81
+ | GitHub-webhook automation | `githubChannel()` hooks, per-PR debounce, replay fixtures |
82
+ | Domain assistant over live APIs / MCP | server + agent tools, a stdio MCP connection, a skill, a schedule |
83
+ | Wrap an existing pipeline/tool | GitHub `{ task }` hook driving a deterministic loop under `agent/lib/` |
84
+
85
+ Defaults that make first cuts good:
86
+
87
+ - **Minimal surface.** Instructions + 1–2 real tools + the chosen channels +
88
+ one smoke eval. Unpicked capabilities are follow-ups, not scope.
89
+ - **Instructions** (`agent/instructions.md`, required): a few lines — identity,
90
+ when to use which tool, output shape. Not an essay.
91
+ - **Tool per file**, filename = tool name the model sees. Prefer
92
+ `execution: "server"` with a zod `inputSchema`; use `execution: "agent"`
93
+ (script) only when the tool must run where the agent runs (or runtime is
94
+ cloud). Gate side-effecting tools with `needsApproval: true`.
95
+ - **Env prefix** for Slack tokens = upper-snake slug (`my-agent` →
96
+ `MY_AGENT_SLACK_*`); `agent-serve slack init` derives it for you.
97
+ - **Host prep beats model wandering:** when the purpose has a deterministic
98
+ setup step (fetch a PR, seed files), do it in the channel handler via
99
+ `callTool` / `workspaceFiles` rather than instructing the model to do it.
100
+
101
+ ## Scaffold
102
+
103
+ ```bash
104
+ agent-serve init ./<slug>
105
+ ```
106
+
107
+ `init` writes `package.json`, `agent/agent.ts`, `agent/instructions.md`, and a
108
+ demo `agent/tools/echo.ts`; it refuses to overwrite existing files. Then shape
109
+ it to the plan:
110
+
111
+ 1. `tsconfig.json` — add one so the type-checker covers the project.
112
+ 2. `agent/agent.ts` — chosen model/runtime via `defineAgent({...})`; add the
113
+ `cloud: { repos: [...] }` block for cloud runtime.
114
+ 3. `agent/instructions.md` — real instructions; delete or replace `echo.ts`
115
+ with the real tools.
116
+ 4. Add the chosen `channels/`, `mcp-connections/`, `skills/`, `subagents/<id>/`
117
+ (needs `description`), `schedules/`, `hooks/`, `sandbox/workspace/`. For
118
+ Slack, do not hand-write the channel: `agent-serve slack init --dir
119
+ ./<slug> --name "<Name>"` generates `agent/channels/slack.ts` (with
120
+ the env prefix) plus manifests and `env.example`; customize the generated
121
+ file (e.g. `suggestedPrompts`) afterwards.
122
+ 5. `evals/evals.config.ts` — `defineEvalConfig({ maxConcurrency: 20 })`
123
+ (playground runs are memory-only unless you add `persistRuns`)
124
+ (`maxConcurrency` is required; hard-capped at 200 due to model provider
125
+ request limits) plus eval cases under `evals/**/*.eval.ts` — prefer one
126
+ suite file with `cases: [{ id, test }, …]` for related datapoints, or a
127
+ single `test` for one smoke. Assert `t.succeeded()` + `t.calledTool(...)`
128
+ (case id = file path, or `<fileId>/<case.id>`). Full assertion API and
129
+ fixture strategy: `evals/SKILL.md` (sibling skill).
130
+
131
+ Stick to deps agent-serve already
132
+ ships (`zod`, `@modelcontextprotocol/sdk`, `tsx`); a new npm dep needs its own
133
+ install story and is a smell for a first cut.
134
+
135
+ ## Verify
136
+
137
+ No API key needed for the structural half — run these first and fix every
138
+ error diagnostic:
139
+
140
+ ```bash
141
+ agent-serve validate --dir ./<slug> # zero errors (warnings explain runtime mismatches)
142
+ agent-serve info --dir ./<slug> --json # surface matches the plan
143
+ agent-serve call <tool> --dir ./<slug> --input '{…}' # server tools, deterministic, no model
144
+ agent-serve eval --dir ./<slug> --list
145
+ npx tsc --noEmit -p ./<slug> # or the project's own type-check task
146
+ ```
147
+
148
+ The typecheck matters: everything above runs through tsx, which strips types
149
+ without checking them. The classic miss is a tool `execute` return that does
150
+ not satisfy `ToolExecuteResult` — returns must be JSON-shaped
151
+ (`ToolResultValue`), so use plain object literals or `type` aliases, not
152
+ `interface` types (their lack of an index signature fails assignability).
153
+
154
+ `serve` also boots without a key (good for checking channel mounts and the
155
+ playground shell), but model turns need `CURSOR_API_KEY` — ask the user for
156
+ one if the environment lacks it (minted in the Cursor dashboard). If no key
157
+ is forthcoming, finish every key-free check, confirm `run` fails with only
158
+ the clean API-key error, and hand these to the user as their next steps:
159
+
160
+ ```bash
161
+ agent-serve run --dir ./<slug> --message "<fixture prompt>" # JSON trajectory
162
+ agent-serve serve --dir ./<slug> --dev
163
+ # playground: http://127.0.0.1:3000/<slug>/playground
164
+ agent-serve eval --dir ./<slug>
165
+ ```
166
+
167
+ Serve only the new agent's directory during bring-up — pointing `serve` at a
168
+ parent folder also mounts every sibling agent it contains.
169
+ Runtime state lands in `<project>/.agent-serve/` (gitignored); keep durable
170
+ `--state-root` outside the monorepo so sessions don't inherit ambient
171
+ `AGENTS.md`.
172
+
173
+ ## Channel setup with the user
174
+
175
+ Each surface beyond the playground has a human gate — drive the user through
176
+ it, verify with doctor commands, and smoke-test before declaring victory.
177
+
178
+ - **Slack** — follow `packages/agent-serve/skills/setup-slack/SKILL.md` end
179
+ to end (init → human creates apps → doctor → `@mention` smoke).
180
+ - **GitHub** — follow `packages/agent-serve/skills/github/SKILL.md`
181
+ (fixtures / replay / forward / `--cursor-events`).
182
+ - **Custom webhook** — `POST /<slug>/v1/channels/<id>/<route>`. Default
183
+ `localDevStrict()` is loopback-only; add `bearerAuth(...)` before any
184
+ tunnel or shared host.
185
+ - **Schedules** — never auto-fire under `--dev`; dispatch via
186
+ `POST /<slug>/v1/dev/schedules/<id>`.
187
+
188
+ ## Hand off to hillclimbing
189
+
190
+ Scaffolding proves the agent runs; it says nothing about quality. Once the
191
+ smoke turn passes, propose the improvement loop — one last `AskQuestion` if
192
+ choices are open:
193
+
194
+ 1. **Fixtures** — 1–3 fixed inputs worth optimizing against (a real PR URL, a
195
+ canonical Slack question, a saved webhook payload).
196
+ 2. **Success criteria** — what "better" means first (correct tool choice,
197
+ fewer tool calls, faster wall time, output quality).
198
+ 3. **Freeze line** — what must not change (API contract, output shape).
199
+
200
+ Those are exactly the preconditions in `skills/hillclimb/SKILL.md`; suggest
201
+ the user (or you) follow that skill with the fixtures you agreed on. Seed
202
+ the loop by pointing
203
+ at the smoke run's session (`.agent-serve/<slug>/sessions/<id>/events.ndjson`
204
+ or the trace under `.agent-serve/traces/`) as the baseline measurement — or,
205
+ when no API key was available, name the user's first real turn as the
206
+ baseline instead. For GitHub agents, snapshot replay fixtures now
207
+ (`agent-serve github replay ... --dry-run --out fixtures/github`) so the
208
+ loop starts deterministic.
209
+
210
+ ## Working agreements
211
+
212
+ - Interview → plan gate → scaffold → verify → channel setup → hillclimb
213
+ handoff. Do not skip verification because the files "look right".
214
+ - Fill blanks yourself; re-ask only when an answer contradicts the framework
215
+ (e.g. server tools on cloud runtime — `validate` warns about these).
216
+ - Do not deploy, post to real Slack/GitHub surfaces beyond the smoke tests the
217
+ user asked for, or commit without being asked.
218
+ - Keep the first cut reviewable: if the plan grows past ~10 files, cut scope
219
+ and say what you deferred.
@@ -0,0 +1,71 @@
1
+ ---
2
+ name: agent-serve-debug
3
+ description: >-
4
+ Diagnose a misbehaving agent-serve agent, server, or playground — blank
5
+ playground, sessions missing, HMR not reloading, failing reads/retry
6
+ loops, webhook 401s, 403/409 responses, approvals or reminders lost,
7
+ orphaned processes. Use when an agent-serve project runs but behaves
8
+ wrong locally.
9
+ ---
10
+
11
+ # Debugging agent-serve locally
12
+
13
+ Read `framework-map/SKILL.md` (sibling skill) first if you don't know the
14
+ project structure or session model. Everything below assumes Node/tsx (`pnpm exec tsx
15
+ src/bin/agent-serve.ts ...` in the everysphere monorepo).
16
+
17
+ ## Triage in order
18
+
19
+ ```bash
20
+ # 1. Is discovery clean? serve refuses to start on error diagnostics.
21
+ agent-serve validate --dir <project>
22
+
23
+ # 2. What is actually running, and where?
24
+ lsof -iTCP:3000 -sTCP:LISTEN; lsof -iTCP:5273 -sTCP:LISTEN
25
+ ps aux | rg -i 'agent-serve|vite' | rg -v rg
26
+
27
+ # 3. What does the server think it serves?
28
+ curl -s localhost:3000/v1/agents | jq . # multi-agent index
29
+ curl -s localhost:3000/<slug>/v1/info | jq . # per-agent surface
30
+
31
+ # 4. What did the session actually do? The stream never lies.
32
+ curl -sN 'localhost:3000/<slug>/v1/session/<id>/stream?startIndex=0' | head -50
33
+ # or read <stateRoot>/<slug>/sessions/<id>/events.ndjson directly
34
+ ```
35
+
36
+ ## Symptom → cause
37
+
38
+ | Symptom | Cause / fix |
39
+ | --- | --- |
40
+ | Playground blank or "no agents" even though Vite assets are built | The SPA is static; it needs the agent-serve backend on `:3000`. Start `serve` — building `dist/playground/` alone serves nothing. |
41
+ | Edits under `playground/src` don't show up in the browser | You're on the **static** `dist/playground` bundle, not HMR. Only `serve --dev` starts Vite HMR (`:5273`) and prints `playground (HMR): ...` — open that URL, not `:3000`. In the monorepo, `mise //packages/agent-serve:start` = all examples + multi-agent HMR; pin one slug with `AGENT_SERVE_BASE=/<slug>`. |
42
+ | Webhook / schedule sessions exist on disk but the playground session list is empty | The list shows the calling principal's sessions. `--dev` (loopback) or `--allow-anonymous` (trusted shared host) switches it to `includeAll`. Otherwise deep-link `/<slug>/playground?sessionId=ses_...` or read `sessions/` on disk. |
43
+ | Every built-in read/grep the model makes fails; turns crawl through retry loops | You ran the CLI under **Bun**. Kill it, rerun under Node/tsx. (`NGHTTP2_FRAME_SIZE_ERROR` in SDK logs is the tell.) |
44
+ | `gh webhook forward` / `agent-serve github forward` deliveries all 401 — but hook creation succeeded | `GITHUB_TOKEN`/`GH_TOKEN` in the env. The relay authenticates with the gh CLI login and rejects env tokens. `GITHUB_TOKEN= GH_TOKEN= agent-serve github forward ...` |
45
+ | `Hook already exists` starting a forwarder | GitHub allows one forwarder per repo. Use one `github forward --dir <parent>` (it fans out to every matching channel) instead of N processes; kill stale forwarders. |
46
+ | Agent's answers reference monorepo rules / AGENTS.md it shouldn't know | Session workspace sits inside the monorepo, so the harness loaded ancestor config. `defineAgent({ local: { cwd } })` outside the repo, or `--state-root` under `/tmp`. |
47
+ | Port 3000/5273 in use; stray processes after crashes | `lsof -iTCP:3000 -sTCP:LISTEN`, kill the pids; also check companion processes (e.g. vite). |
48
+ | Pending tool approval vanished after server restart | By design: parked SDK calls don't survive host restart; they resolve as interrupted. Re-run the turn. |
49
+ | Schedule / reminder never fires under `--dev` | Dev never auto-fires. `POST /<slug>/v1/dev/schedules/<id>` or `POST /<slug>/v1/dev/reminders/<id>` (list at `GET /v1/dev/reminders`). |
50
+ | Reminder disarmed after restart with `handler_lost_on_restart` | `run`-handler reminders are in-memory; re-arm them from the code path that created them (enroll hook / policy), or use prompt-based reminders. |
51
+ | `409` on a follow-up | Stale `continuationToken` (each accepted follow-up rotates it), busy session, or a task/schedule session (not followable). |
52
+ | `409 session_busy` on `agent-serve call --session` | Session-bound deterministic calls serialize with model turns; wait or use an ephemeral call (drop `--session`). |
53
+ | `403` on stream/follow-up | Caller principal ≠ session owner. In dev, create and inspect with the same auth; beyond loopback pass `--bearer-token` and send it. |
54
+ | Works on localhost, 401/blocked through a tunnel or LAN | Default `localDevStrict()` auth only admits direct loopback, **rejects proxy-forwarding headers** (`X-Forwarded-For`, ...), and requires a loopback `Host`. Use `--bearer-token <secret>` (or authored `bearerAuth`) — `--allow-anonymous` only for trusted-network demos (and never with Cursor account MCP connections). |
55
+ | Channel route won't compile: body/query schema type error | `GET` requires a Zod `querySchema`, `POST`/`PUT`/`PATCH` a Zod `bodySchema` — plain JSON Schema objects don't type-check. Use `z.object({})` / `z.unknown()` for open surfaces. Empty POST bodies are coerced to `{}` before validation. |
56
+ | Slack channel prints `channel idle ... missing credentials` | Expected: tokens absent. Multi-agent needs `<PREFIX>_SLACK_BOT_TOKEN` + `<PREFIX>_SLACK_APP_TOKEN` per agent. `agent-serve slack doctor --prefix <PREFIX>`. |
57
+ | Turn fails immediately with an API-key error | Model turns need `CURSOR_API_KEY`; everything structural (validate/info/call/serve bring-up) doesn't. |
58
+ | Server tools / skills / sandbox silently absent | Runtime is `cloud` — those are local-only. `validate` prints exactly this warning; read it. |
59
+ | `validate` clean, `run` works, CI typecheck fails | tsx never typechecked it. See invariant 3 in `framework-map/SKILL.md` (JSON-shaped tool returns; `type` not `interface`). |
60
+
61
+ ## Reading a turn like an expert
62
+
63
+ - `actions.requested` / `action.result` pairs are the tool trajectory;
64
+ count them by `toolName` before blaming latency, and split **host** work
65
+ (channel `callTool`, prep) from **model** tools.
66
+ - `turn.failed` with `"turn interrupted"` means a follow-up or `/stop`
67
+ preempted it — that's the designed behavior, not a crash.
68
+ - Escapes outside the session workspace in read/grep paths mean the
69
+ harness is fighting your evidence layout, not that the model is broken.
70
+ - `agent-serve trajectory --events <file>` renders any saved NDJSON; the
71
+ playground "Open trace" does the same visually.
@@ -0,0 +1,217 @@
1
+ ---
2
+ name: agent-serve-evals
3
+ description: >-
4
+ Author and run agent-serve defineEval cases (single- or multi-datapoint).
5
+ Use when writing, fixing, seeding, or hillclimbing evals; AskQuestion
6
+ whether to generate samples or upload data. Materialize API-backed
7
+ fixtures first. Live A/B metrics: defineAB (skills/ab), not defineEval.
8
+ ---
9
+
10
+ # agent-serve evals
11
+
12
+ Evals are the ratchet that makes iteration trustworthy: a fixed input, a
13
+ model turn, and gates over the recorded trajectory. They live at the
14
+ **project root** `evals/**/*.eval.ts` (never `agent/evals/` — that slot is
15
+ ignored).
16
+
17
+ For **live A/B metrics** while the agent serves traffic, use `defineAB`
18
+ under `agent/ab` (`packages/agent-serve/skills/ab/SKILL.md`). That plug-in
19
+ enrolls via sticky `split` and calls `onSample`; it is not a test runner
20
+ and does not replace `defineEval` gates.
21
+
22
+ **Identity**
23
+
24
+ - File id = path under `evals/` without `.eval.ts`
25
+ (`evals/weather.eval.ts` → `weather`).
26
+ - Single datapoint (`test`): case id = file id
27
+ (`evals/weather/nyc.eval.ts` → `weather/nyc`).
28
+ - Multiple datapoints (`cases`): case id = `<fileId>/<case.id>`
29
+ (`evals/weather.eval.ts` + `{ id: "nyc" }` → `weather/nyc`).
30
+
31
+ ```bash
32
+ agent-serve eval --dir . --list # all datapoints
33
+ agent-serve eval --dir . --json # run all
34
+ agent-serve eval --dir . weather/nyc # one datapoint
35
+ agent-serve eval --dir . weather # every datapoint in that file
36
+ agent-serve eval --dir . weather forecast # several files
37
+ agent-serve eval --dir . --tag smoke
38
+ agent-serve eval --dir . --verbose
39
+ ```
40
+
41
+ `eval` (like `run`) boots an ephemeral server on port 0 with a temp state
42
+ root outside the project, so cases don't inherit ambient monorepo rules and
43
+ don't pollute `.agent-serve/`. Point `--url` at a running server instead to
44
+ eval a live agent. Model turns require `CURSOR_API_KEY`.
45
+
46
+ ## Seeding / adding samples (required fork)
47
+
48
+ Whenever the task is to **create, seed, or expand** eval cases (not merely
49
+ run or tweak an existing gate), start with the `AskQuestion` tool. Do not
50
+ assume a source of fixtures.
51
+
52
+ ### Step 1 — who supplies the samples?
53
+
54
+ Use `AskQuestion` (single-select). Put the recommended option first and
55
+ label it `(recommended)`. Do **not** put code blocks inside the question
56
+ prompt (they render poorly); keep the prompt short plain text.
57
+
58
+ | Question | Options |
59
+ | --- | --- |
60
+ | **How should we get eval samples?** | Generate test eval samples for me `(recommended)` · I will add / upload the data manually |
61
+
62
+ If `AskQuestion` is unavailable, ask the same fork in plain chat and wait.
63
+
64
+ ### Step 2a — user chose manual
65
+
66
+ Tell the user the **shape** of the data (see “The API” below) and **how to
67
+ upload it**. Do not invent cases until they provide files (or paste content
68
+ to write). After they add data, run `agent-serve eval --dir <project>
69
+ --list` to confirm discovery, then wire any missing gates.
70
+
71
+ If the uploaded data is **API-backed** (PR URLs, pinned SHAs, gold labels,
72
+ snapshot ids) rather than self-contained prompts/diffs, **materialize
73
+ fixtures first** — see “When eval data needs API calls to render” below.
74
+
75
+ **How to upload:**
76
+
77
+ 1. Add or edit `.eval.ts` files under the project’s `evals/` directory.
78
+ 2. Ensure `evals/evals.config.ts` exists with `maxConcurrency`.
79
+ 3. Optional fixtures beside the case or under `fixtures/`.
80
+ 4. Tell the agent once the files are in place — or paste case bodies in chat
81
+ and ask the agent to write the file.
82
+ 5. Verify: `agent-serve eval --dir <project> --list` shows the new ids.
83
+
84
+ ### Step 2b — user chose agent-generated samples
85
+
86
+ 1. Use `AskQuestion` again for count (single-select), recommended first:
87
+
88
+ | Question | Options |
89
+ | --- | --- |
90
+ | **How many test samples should I create?** | `3` `(recommended)` · `5` · `10` · Other (enter a number) |
91
+
92
+ 2. Inspect the agent (tools, instructions, existing `evals/`) and invent
93
+ that many **distinct** datapoints: frozen prompts + decision/shape gates,
94
+ not exact prose. Follow “What good cases assert” below.
95
+ 3. **Append** — prefer adding entries to an existing file’s `cases` array
96
+ when the suite fits; otherwise create a new `evals/<suite>.eval.ts` with
97
+ `cases`. Never overwrite or weaken an existing datapoint. Case ids must
98
+ not collide with `agent-serve eval --dir <project> --list`.
99
+ 4. Create `evals/evals.config.ts` if missing (`maxConcurrency: 20` is fine
100
+ for now; hard limit 200 for model provider request limits).
101
+ 5. Re-list to confirm, then optionally run `--tag smoke` if you tagged any.
102
+
103
+ ## The API
104
+
105
+ ```ts
106
+ import { defineEval, includes, equals, satisfies } from "@anysphere/agent-serve/evals";
107
+
108
+ // Single datapoint (case id = file path under evals/)
109
+ export default defineEval({
110
+ description: "Uses get_weather for temperature questions.",
111
+ tags: ["smoke"],
112
+ timeoutMs: 120_000,
113
+ async test(t) {
114
+ await t.send("What's the temperature in NYC?");
115
+ t.succeeded();
116
+ t.calledTool("get_weather");
117
+ t.notCalledTool("save_weather_note");
118
+ t.messageIncludes(/°|[FC]/);
119
+ t.check(t.reply, includes("NYC"));
120
+ },
121
+ });
122
+
123
+ // Multiple datapoints in one file (ids = <fileId>/<case.id>)
124
+ export default defineEval({
125
+ tags: ["smoke", "weather"],
126
+ cases: [
127
+ {
128
+ id: "nyc",
129
+ description: "NYC temperature.",
130
+ async test(t) {
131
+ await t.send("What's the temperature in NYC?");
132
+ t.succeeded();
133
+ t.calledTool("get_weather");
134
+ t.check(t.reply, includes(/°|[FC]/));
135
+ },
136
+ },
137
+ {
138
+ id: "paris",
139
+ async test(t) {
140
+ await t.send("What's the weather in Paris?");
141
+ t.succeeded();
142
+ t.calledTool("get_weather");
143
+ },
144
+ },
145
+ ],
146
+ });
147
+ ```
148
+
149
+ Project-wide defaults in `evals/evals.config.ts` (required once):
150
+
151
+ ```ts
152
+ import {
153
+ defineEvalConfig,
154
+ persistEvalRunsToDir,
155
+ } from "@anysphere/agent-serve/evals";
156
+
157
+ export default defineEvalConfig({
158
+ maxConcurrency: 20, // required; hard-capped at 200 (model provider limits)
159
+ // Playground batches are memory-only unless you set persistRuns:
160
+ // maxPlaygroundRuns: 50, // optional; default 20; playground history only
161
+ // persistRuns: persistEvalRunsToDir(".agent-serve/eval-runs"),
162
+ });
163
+ ```
164
+
165
+ - Either a single `test(t)` **or** a `cases: [{ id, test }, …]` array — not
166
+ both. Prefer `cases` for multiple related datapoints.
167
+ - `t.send(message, options?)` runs one turn and waits for park/fail.
168
+ Options: `workspaceDir`, `workspaceFiles` (`{ path: contents }` seeded
169
+ before the first turn). Multiple `t.send` calls share the session.
170
+ - `t.reply` / `t.events` / `t.sessionId` for assertions and correlation.
171
+ - Builders: `includes(string | RegExp)`, `equals(value)`,
172
+ `satisfies(predicate, label)`.
173
+
174
+ ## What good cases assert
175
+
176
+ Gate **decisions and shape, not prose**. Model wording varies run to run;
177
+ tool choice, tool avoidance, and output structure shouldn't.
178
+
179
+ 1. `t.succeeded()` — always, first.
180
+ 2. The tool decision: `calledTool` for the intended path, `notCalledTool`
181
+ for the tempting wrong one (the pair is stronger than either alone).
182
+ 3. Output shape: a regex for the contract (`/°|[FC]/`, a JSON marker, a
183
+ findings-block fence) — not exact sentences.
184
+ 4. For structured output, parse `t.reply` and `t.check` fields with
185
+ `satisfies` rather than substring-matching JSON.
186
+
187
+ Anti-patterns: asserting exact phrasing; more than ~5 gates in one case
188
+ (split it); cases that depend on live external state that drifts (pin the
189
+ input instead — see fixtures).
190
+
191
+ ## Fixture strategy by agent type
192
+
193
+ | Agent surface | Fixture source |
194
+ | --- | --- |
195
+ | Chat / domain assistant | A canonical prompt string, chosen once and frozen |
196
+ | Tool-heavy | `agent-serve call <tool> --dir . --input '{...}'` first, then the prompt that should trigger it |
197
+ | GitHub webhook | `github replay … --dry-run --out fixtures/github` (see `packages/agent-serve/skills/github/SKILL.md`) |
198
+ | PR reviewer with host prep | A small fixed PR the team controls; assert on findings shape, not counts |
199
+ | Workspace-dependent | `workspaceFiles` in `t.send` — never machine-local paths |
200
+
201
+ ### When eval data needs API calls to render (rate limits)
202
+
203
+ If samples are **pointers** (PR URL, SHAs, `gold_labels`) rather than
204
+ self-contained evidence, do **not** wire live `t.send(prUrl)` matrices.
205
+ Materialize once under `fixtures/` at pinned SHAs, point cases at those
206
+ files, gate on decision/shape against gold, and keep a tiny `--tag smoke`
207
+ subset for any full-pipeline runs.
208
+
209
+ ## The ratchet rule (hillclimbing)
210
+
211
+ Every hillclimb round that **keeps** a change must land an eval that would
212
+ have failed before the change. Never weaken a gate to make a round pass.
213
+
214
+ ```ts
215
+ const toolResults = t.events.filter((e) => e.type === "action.result");
216
+ t.check(toolResults.length, satisfies((n) => (n as number) <= 4, "≤4 tool calls"));
217
+ ```