@cursor/july 0.1.15 → 0.1.17

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 (243) hide show
  1. package/README.md +9 -4
  2. package/dist/bin/agent-serve.js +60 -2
  3. package/dist/channels/slack/api.d.ts.map +1 -1
  4. package/dist/channels/slack/api.js +13 -3
  5. package/dist/channels/slack/auth.d.ts +7 -1
  6. package/dist/channels/slack/auth.d.ts.map +1 -1
  7. package/dist/channels/slack/auth.js +14 -0
  8. package/dist/channels/slack/blocks.d.ts +61 -0
  9. package/dist/channels/slack/blocks.d.ts.map +1 -0
  10. package/dist/channels/slack/blocks.js +90 -0
  11. package/dist/channels/slack/defaults.d.ts +2 -0
  12. package/dist/channels/slack/defaults.d.ts.map +1 -1
  13. package/dist/channels/slack/defaults.js +29 -3
  14. package/dist/channels/slack/dispatch.d.ts +3 -17
  15. package/dist/channels/slack/dispatch.d.ts.map +1 -1
  16. package/dist/channels/slack/index.d.ts +1 -0
  17. package/dist/channels/slack/index.d.ts.map +1 -1
  18. package/dist/channels/slack/index.js +1 -0
  19. package/dist/channels/slack/interactive.d.ts +39 -3
  20. package/dist/channels/slack/interactive.d.ts.map +1 -1
  21. package/dist/channels/slack/interactive.js +152 -7
  22. package/dist/channels/slack/manifest.d.ts +3 -0
  23. package/dist/channels/slack/manifest.d.ts.map +1 -1
  24. package/dist/channels/slack/manifest.js +3 -0
  25. package/dist/channels/slack/setup.d.ts +4 -1
  26. package/dist/channels/slack/setup.d.ts.map +1 -1
  27. package/dist/channels/slack/setup.js +16 -2
  28. package/dist/channels/slack/slack-channel.d.ts.map +1 -1
  29. package/dist/channels/slack/slack-channel.js +24 -3
  30. package/dist/channels/slack/types.d.ts +77 -0
  31. package/dist/channels/slack/types.d.ts.map +1 -1
  32. package/dist/connections.d.ts +4 -1
  33. package/dist/connections.d.ts.map +1 -1
  34. package/dist/connections.js +4 -1
  35. package/dist/docs/404.html +2 -2
  36. package/dist/docs/ab.html +3 -3
  37. package/dist/docs/assets/{app.DpdGZTLe.js → app.BbEXr2KO.js} +1 -1
  38. package/dist/docs/assets/chunks/@localSearchIndexroot.DCBsrfwP.js +1 -0
  39. package/dist/docs/assets/chunks/{VPLocalSearchBox.IB-0QqIT.js → VPLocalSearchBox.DBEi4HDp.js} +1 -1
  40. package/dist/docs/assets/chunks/{theme.-fYBoNtR.js → theme.DGfptcHw.js} +2 -2
  41. package/dist/docs/assets/{example-agents_index.md.BPXjUtRB.js → example-agents_index.md.D2PEVSXl.js} +2 -2
  42. package/dist/docs/assets/{example-agents_index.md.BPXjUtRB.lean.js → example-agents_index.md.D2PEVSXl.lean.js} +1 -1
  43. package/dist/docs/assets/example-agents_security-reviewer.md.BZSNycMf.js +19 -0
  44. package/dist/docs/assets/{example-agents_security-reviewer.md.CE9v-aKm.lean.js → example-agents_security-reviewer.md.BZSNycMf.lean.js} +1 -1
  45. package/dist/docs/assets/{guides_mcp-oauth.md.DqmEOQY1.js → guides_mcp-oauth.md.Dd8EgSem.js} +3 -2
  46. package/dist/docs/assets/{guides_mcp-oauth.md.DqmEOQY1.lean.js → guides_mcp-oauth.md.Dd8EgSem.lean.js} +1 -1
  47. package/dist/docs/assets/{guides_slack.md.FWale6Ip.js → guides_slack.md.D_xFKlnF.js} +1 -1
  48. package/dist/docs/assets/{reference_connections.md.CsSr3rDz.js → reference_connections.md.B9Q3TOve.js} +12 -5
  49. package/dist/docs/assets/{reference_connections.md.CsSr3rDz.lean.js → reference_connections.md.B9Q3TOve.lean.js} +1 -1
  50. package/dist/docs/building-with-agents.html +3 -3
  51. package/dist/docs/concepts.html +3 -3
  52. package/dist/docs/deployment.html +3 -3
  53. package/dist/docs/evals.html +3 -3
  54. package/dist/docs/example-agents/approval-buddy.html +3 -3
  55. package/dist/docs/example-agents/benny.html +3 -3
  56. package/dist/docs/example-agents/bugbot.html +3 -3
  57. package/dist/docs/example-agents/codebase-wiki.html +3 -3
  58. package/dist/docs/example-agents/codeowners-review.html +3 -3
  59. package/dist/docs/example-agents/concierge.html +3 -3
  60. package/dist/docs/example-agents/fsd.html +3 -3
  61. package/dist/docs/example-agents/index.html +5 -5
  62. package/dist/docs/example-agents/knowledge-base.html +3 -3
  63. package/dist/docs/example-agents/oncall.html +3 -3
  64. package/dist/docs/example-agents/security-reviewer.html +14 -14
  65. package/dist/docs/example-agents/slack-agent.html +3 -3
  66. package/dist/docs/example-agents/weather-agent.html +3 -3
  67. package/dist/docs/guides/agent-to-agent.html +3 -3
  68. package/dist/docs/guides/cloud-runtime.html +3 -3
  69. package/dist/docs/guides/github.html +3 -3
  70. package/dist/docs/guides/human-in-the-loop.html +3 -3
  71. package/dist/docs/guides/mcp-oauth.html +6 -5
  72. package/dist/docs/guides/slack.html +5 -5
  73. package/dist/docs/guides/webhooks.html +3 -3
  74. package/dist/docs/hashmap.json +1 -1
  75. package/dist/docs/hillclimbing.html +3 -3
  76. package/dist/docs/index.html +3 -3
  77. package/dist/docs/quickstart.html +3 -3
  78. package/dist/docs/reference/agent-config.html +3 -3
  79. package/dist/docs/reference/channels.html +3 -3
  80. package/dist/docs/reference/cli.html +3 -3
  81. package/dist/docs/reference/connections.html +14 -7
  82. package/dist/docs/reference/hooks.html +3 -3
  83. package/dist/docs/reference/http-api.html +3 -3
  84. package/dist/docs/reference/instructions.html +3 -3
  85. package/dist/docs/reference/playground.html +3 -3
  86. package/dist/docs/reference/project-layout.html +3 -3
  87. package/dist/docs/reference/prompt.html +3 -3
  88. package/dist/docs/reference/schedules.html +3 -3
  89. package/dist/docs/reference/sessions.html +3 -3
  90. package/dist/docs/reference/skills.html +3 -3
  91. package/dist/docs/reference/subagents.html +3 -3
  92. package/dist/docs/reference/tools.html +3 -3
  93. package/dist/docs/scaffolding-agents.html +3 -3
  94. package/dist/docs/storage.html +3 -3
  95. package/dist/docs/troubleshooting.html +3 -3
  96. package/dist/evals/assertions.d.ts +190 -0
  97. package/dist/evals/assertions.d.ts.map +1 -0
  98. package/dist/evals/assertions.js +461 -0
  99. package/dist/evals/expect.d.ts +95 -0
  100. package/dist/evals/expect.d.ts.map +1 -0
  101. package/dist/evals/expect.js +194 -0
  102. package/dist/evals/judge.d.ts +133 -0
  103. package/dist/evals/judge.d.ts.map +1 -0
  104. package/dist/evals/judge.js +228 -0
  105. package/dist/evals/loaders.d.ts +51 -0
  106. package/dist/evals/loaders.d.ts.map +1 -0
  107. package/dist/evals/loaders.js +124 -0
  108. package/dist/evals/matchers.d.ts +95 -0
  109. package/dist/evals/matchers.d.ts.map +1 -0
  110. package/dist/evals/matchers.js +145 -0
  111. package/dist/evals/reporters.d.ts +70 -0
  112. package/dist/evals/reporters.d.ts.map +1 -0
  113. package/dist/evals/reporters.js +221 -0
  114. package/dist/evals/results.d.ts +103 -0
  115. package/dist/evals/results.d.ts.map +1 -0
  116. package/dist/evals/results.js +28 -0
  117. package/dist/evals/run-facts.d.ts +77 -0
  118. package/dist/evals/run-facts.d.ts.map +1 -0
  119. package/dist/evals/run-facts.js +187 -0
  120. package/dist/evals.d.ts +136 -31
  121. package/dist/evals.d.ts.map +1 -1
  122. package/dist/evals.js +76 -12
  123. package/dist/index.d.ts +1 -1
  124. package/dist/index.d.ts.map +1 -1
  125. package/dist/index.js +1 -1
  126. package/dist/internal/cli-ax.d.ts +27 -0
  127. package/dist/internal/cli-ax.d.ts.map +1 -1
  128. package/dist/internal/cli-ax.js +90 -12
  129. package/dist/internal/cli-mcp.d.ts +8 -0
  130. package/dist/internal/cli-mcp.d.ts.map +1 -1
  131. package/dist/internal/cli-mcp.js +98 -0
  132. package/dist/internal/cli-slack.d.ts +29 -1
  133. package/dist/internal/cli-slack.d.ts.map +1 -1
  134. package/dist/internal/cli-slack.js +777 -12
  135. package/dist/internal/deploy-client.d.ts +7 -0
  136. package/dist/internal/deploy-client.d.ts.map +1 -1
  137. package/dist/internal/deploy-client.js +9 -0
  138. package/dist/internal/discovery.d.ts.map +1 -1
  139. package/dist/internal/discovery.js +29 -9
  140. package/dist/internal/distribution.d.ts.map +1 -1
  141. package/dist/internal/distribution.js +2 -0
  142. package/dist/internal/eval-judge-model.d.ts +59 -0
  143. package/dist/internal/eval-judge-model.d.ts.map +1 -0
  144. package/dist/internal/eval-judge-model.js +131 -0
  145. package/dist/internal/eval-run-store.d.ts.map +1 -1
  146. package/dist/internal/eval-run-store.js +12 -20
  147. package/dist/internal/eval-runner.d.ts +31 -25
  148. package/dist/internal/eval-runner.d.ts.map +1 -1
  149. package/dist/internal/eval-runner.js +332 -128
  150. package/dist/internal/evals-client.d.ts.map +1 -1
  151. package/dist/internal/evals-client.js +7 -3
  152. package/dist/internal/local-env.d.ts +8 -0
  153. package/dist/internal/local-env.d.ts.map +1 -0
  154. package/dist/internal/local-env.js +47 -0
  155. package/dist/internal/playground/static.d.ts +3 -0
  156. package/dist/internal/playground/static.d.ts.map +1 -1
  157. package/dist/internal/playground/static.js +3 -0
  158. package/dist/internal/run-client.d.ts +15 -0
  159. package/dist/internal/run-client.d.ts.map +1 -1
  160. package/dist/internal/run-client.js +3 -2
  161. package/dist/internal/sdk-runner.d.ts +36 -1
  162. package/dist/internal/sdk-runner.d.ts.map +1 -1
  163. package/dist/internal/sdk-runner.js +65 -25
  164. package/dist/internal/server.d.ts.map +1 -1
  165. package/dist/internal/server.js +10 -1
  166. package/dist/internal/session-engine.d.ts +18 -5
  167. package/dist/internal/session-engine.d.ts.map +1 -1
  168. package/dist/internal/session-engine.js +72 -19
  169. package/dist/internal/slack-provision-client.d.ts +130 -0
  170. package/dist/internal/slack-provision-client.d.ts.map +1 -0
  171. package/dist/internal/slack-provision-client.js +284 -0
  172. package/dist/playground/assets/cursor-icons-16-f_W_ogc-.woff2 +0 -0
  173. package/dist/playground/assets/index-CidizGZv.css +1 -0
  174. package/dist/playground/assets/index-DNqirsrK.js +85 -0
  175. package/dist/playground/index.html +2 -2
  176. package/dist/types.d.ts +70 -4
  177. package/dist/types.d.ts.map +1 -1
  178. package/dist/types.js +26 -0
  179. package/docs/example-agents/index.md +1 -1
  180. package/docs/example-agents/security-reviewer.md +23 -21
  181. package/docs/guides/mcp-oauth.md +10 -5
  182. package/docs/guides/slack.md +3 -2
  183. package/docs/reference/connections.md +28 -18
  184. package/package.json +20 -2
  185. package/skills/create-agent/SKILL.md +15 -7
  186. package/skills/debug/SKILL.md +3 -1
  187. package/skills/mcp-auth/SKILL.md +1 -1
  188. package/skills/setup-slack/SKILL.md +173 -11
  189. package/src/bin/agent-serve.ts +63 -2
  190. package/src/channels/slack/api.ts +16 -3
  191. package/src/channels/slack/auth.ts +16 -1
  192. package/src/channels/slack/blocks.ts +139 -0
  193. package/src/channels/slack/defaults.ts +32 -4
  194. package/src/channels/slack/dispatch.ts +3 -18
  195. package/src/channels/slack/index.ts +1 -0
  196. package/src/channels/slack/interactive.ts +183 -19
  197. package/src/channels/slack/manifest.ts +3 -0
  198. package/src/channels/slack/setup.ts +16 -2
  199. package/src/channels/slack/slack-channel.ts +37 -6
  200. package/src/channels/slack/types.ts +89 -0
  201. package/src/connections.ts +4 -1
  202. package/src/evals/assertions.ts +704 -0
  203. package/src/evals/expect.ts +272 -0
  204. package/src/evals/judge.ts +346 -0
  205. package/src/evals/loaders.ts +113 -0
  206. package/src/evals/matchers.ts +246 -0
  207. package/src/evals/reporters.ts +274 -0
  208. package/src/evals/results.ts +132 -0
  209. package/src/evals/run-facts.ts +274 -0
  210. package/src/evals.ts +249 -42
  211. package/src/index.ts +2 -0
  212. package/src/internal/cli-ax.ts +134 -15
  213. package/src/internal/cli-mcp.ts +118 -5
  214. package/src/internal/cli-slack.ts +993 -15
  215. package/src/internal/deploy-client.ts +10 -0
  216. package/src/internal/discovery.ts +31 -5
  217. package/src/internal/distribution.ts +2 -0
  218. package/src/internal/eval-judge-model.ts +148 -0
  219. package/src/internal/eval-run-store.ts +10 -14
  220. package/src/internal/eval-runner.ts +466 -215
  221. package/src/internal/evals-client.ts +14 -2
  222. package/src/internal/local-env.ts +53 -0
  223. package/src/internal/playground/static.ts +3 -0
  224. package/src/internal/run-client.ts +17 -1
  225. package/src/internal/sdk-runner.ts +103 -22
  226. package/src/internal/server.ts +10 -0
  227. package/src/internal/session-engine.ts +89 -21
  228. package/src/internal/slack-provision-client.ts +438 -0
  229. package/src/types.ts +92 -4
  230. package/dist/channels/slack/post-update-delivery.d.ts +0 -85
  231. package/dist/channels/slack/post-update-delivery.d.ts.map +0 -1
  232. package/dist/docs/assets/chunks/@localSearchIndexroot.D2d8CfFS.js +0 -1
  233. package/dist/docs/assets/example-agents_security-reviewer.md.CE9v-aKm.js +0 -19
  234. package/dist/internal/json-dir-store.d.ts +0 -32
  235. package/dist/internal/json-dir-store.d.ts.map +0 -1
  236. package/dist/internal/persistence-coordinator.d.ts +0 -127
  237. package/dist/internal/persistence-coordinator.d.ts.map +0 -1
  238. package/dist/persistence.d.ts +0 -184
  239. package/dist/persistence.d.ts.map +0 -1
  240. package/dist/playground/assets/cursor-icons-16-CQ50JpfO.woff2 +0 -0
  241. package/dist/playground/assets/index-BVMOoiek.js +0 -86
  242. package/dist/playground/assets/index-DYmP4b--.css +0 -1
  243. /package/dist/docs/assets/{guides_slack.md.FWale6Ip.lean.js → guides_slack.md.D_xFKlnF.lean.js} +0 -0
@@ -61,7 +61,7 @@ questions, concrete options, the recommended option listed first and labeled
61
61
  | --- | --- | --- |
62
62
  | **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. |
63
63
  | **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. |
64
- | **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
+ | **Channels** (multi) | playground + HTTP API only (always mounted) · Slack · GitHub webhooks · custom webhook · schedule (cron) | Slack has two connections: the Cursor-hosted connection (`cursorAccount: true` — zero Slack admin, recommended default) and a dedicated Socket Mode app (own bot user + one app/token pair per agent; needed for channel watching or approval buttons). When Slack is picked, resolve the connection with the Step 0 gate in `setup-slack/SKILL.md` — either fold its AskQuestion into this round or ask it before channel setup; default to Cursor-hosted when you cannot ask. GitHub verifies `X-Hub-Signature-256` when a secret is set. Discord/Teams packs do not exist yet — offer custom webhook instead. |
65
65
  | **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`). |
66
66
  | **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. |
67
67
 
@@ -77,7 +77,7 @@ inventing:
77
77
 
78
78
  | Purpose looks like | Proven shape |
79
79
  | --- | --- |
80
- | Slack chat assistant | minimal `slackChannel()` pack with suggested prompts |
80
+ | Slack chat assistant | minimal `slackChannel({ cursorAccount: true, agentName: "…" })` with suggested prompts; dedicated Socket Mode app only when the Step 0 gate picked it |
81
81
  | PR review with host-prepared evidence | channel `callTool` prep into a trimmed workspace `pr/` tree |
82
82
  | GitHub-webhook automation | `githubChannel()` hooks, per-PR debounce, replay fixtures |
83
83
  | Domain assistant over live APIs / MCP | server + agent tools, a stdio MCP connection, a skill, a schedule |
@@ -98,6 +98,7 @@ Defaults that make first cuts good:
98
98
  multi-line strings).
99
99
  - **Env prefix** for Slack tokens = upper-snake slug (`my-agent` →
100
100
  `MY_AGENT_SLACK_*`); `agentkit slack init` derives it for you.
101
+ Dedicated-app path only — the Cursor-hosted connection has no tokens.
101
102
  - **Host prep beats model wandering:** when the purpose has a deterministic
102
103
  setup step (fetch a PR, seed files), do it in the channel handler via
103
104
  `callTool` / `workspaceFiles` rather than instructing the model to do it.
@@ -125,10 +126,14 @@ plan:
125
126
  with the real tools.
126
127
  4. Add the chosen `channels/`, `mcp-connections/`, `skills/`, `subagents/<id>/`
127
128
  (needs `description`), `schedules/`, `hooks/`, `sandbox/workspace/`. For
128
- Slack, do not hand-write the channel: `agentkit slack init --dir
129
- ./<slug> --name "<Name>"` generates `agent/channels/slack.ts` (with
130
- the env prefix) plus manifests and `env.example`; customize the generated
131
- file (e.g. `suggestedPrompts`) afterwards.
129
+ Slack, follow the connection decided in the interview: Cursor-hosted is a
130
+ short hand-written `agent/channels/slack.ts`
131
+ (`slackChannel({ cursorAccount: true, agentName: "<Name>" })` no
132
+ tokens, no manifests); for a dedicated Socket Mode app do not hand-write
133
+ the channel — `agentkit slack init --dir ./<slug> --name "<Name>"`
134
+ generates `agent/channels/slack.ts` (with the env prefix) plus manifests
135
+ and `env.example`; customize the generated file (e.g. `suggestedPrompts`)
136
+ afterwards.
132
137
  5. `evals/evals.config.ts` — `defineEvalConfig({ maxConcurrency: 20 })`
133
138
  (playground runs are memory-only unless you add `persistRuns`)
134
139
  (`maxConcurrency` is required; hard-capped at 200 due to model provider
@@ -186,7 +191,10 @@ Each surface beyond the playground has a human gate — drive the user through
186
191
  it, verify with doctor commands, and smoke-test before declaring victory.
187
192
 
188
193
  - **Slack** — follow `packages/agent-serve/skills/setup-slack/SKILL.md` end
189
- to end (init human creates apps doctor `@mention` smoke).
194
+ to end, starting from its Step 0 connection gate. Cursor-hosted: sign in
195
+ (`agentkit login` / `CURSOR_API_KEY`) → serve → `@Cursor <AgentName>`
196
+ smoke. Dedicated app: init → human creates apps → doctor → `@mention`
197
+ smoke.
190
198
  - **GitHub** — follow `packages/agent-serve/skills/github/SKILL.md`
191
199
  (fixtures / replay / forward / `--cursor-events`).
192
200
  - **Custom webhook** — `POST /<slug>/v1/channels/<id>/<route>`. Default
@@ -53,7 +53,9 @@ curl -sN 'localhost:3000/<slug>/v1/session/<id>/stream?startIndex=0' | head -50
53
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
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
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. `agentkit slack doctor --prefix <PREFIX>`. |
56
+ | Slack channel prints `channel idle ... missing credentials` | Expected: tokens absent (dedicated-app path). Multi-agent needs `<PREFIX>_SLACK_BOT_TOKEN` + `<PREFIX>_SLACK_APP_TOKEN` per agent. `agentkit slack doctor --prefix <PREFIX>`. |
57
+ | `serve` fails: `Slack channels using the Cursor account connection ... not signed in to Cursor` | Cursor-hosted Slack (`cursorAccount: true`) needs a signed-in host: `agentkit login` or `CURSOR_API_KEY`. No Slack tokens exist on this path — `slack doctor` doesn't apply. |
58
+ | `@Cursor <name>` in Slack gets Cursor's normal agent, not yours | Agent name mismatch or host not relaying. Names are single-token and matched case-insensitively; confirm the serve log `cursor-slack: relaying Slack for <AgentName>` and that the workspace's Cursor Slack integration is linked to the signed-in account. |
57
59
  | 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
60
  | Server tools / skills / sandbox silently absent | Runtime is `cloud` — those are local-only. `validate` prints exactly this warning; read it. |
59
61
  | `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`). |
@@ -22,7 +22,7 @@ Docs: `docs/guides/mcp-oauth.md`, `docs/reference/connections.md`,
22
22
 
23
23
  | Need | Use |
24
24
  | --- | --- |
25
- | Connector already in Cursor dashboard (Linear, Notion, …) | `defineConnection({ cursorAccount: true, servers: […] })` |
25
+ | Connector already in Cursor dashboard (Linear, Notion, …) | `defineConnection({ cursorAccount: true })` or `servers: "*"` for every connected server; `servers: […]` to allowlist |
26
26
  | Remote URL that speaks OAuth; host must hold tokens | `defineConnection({ url, oauth: true })` + this skill |
27
27
  | Static bearer / API key | `headers` / env on a plain `{ url }` connection |
28
28
 
@@ -1,16 +1,138 @@
1
1
  ---
2
2
  name: agentkit-setup-slack
3
3
  description: >-
4
- Set up a Slack channel for an agentkit project Socket Mode,
5
- manifests, doctor, smoke test, and opt-in Slack tool approvals (HITL).
6
- Read this skill when wiring Slack for an agentkit project.
4
+ Put an agentkit agent in Slack. Covers the required connection decision
5
+ (Cursor-hosted connection vs dedicated Socket Mode Slack app) with an
6
+ AskQuestion gate, then both setup paths end to end — cursorAccount
7
+ sign-in + smoke, or manifests, tokens, doctor, smoke test, and opt-in
8
+ Slack tool approvals (HITL). Read this skill when wiring Slack for an
9
+ agentkit project.
7
10
  ---
8
11
 
9
12
  # Setup Slack for agentkit
10
13
 
11
14
  Use this skill when a human asks to wire Slack to an agentkit agent.
12
15
 
13
- ## Goal
16
+ There are **two ways to connect**, and they differ mostly in setup cost:
17
+
18
+ - **Path A — Cursor-hosted connection**
19
+ (`slackChannel({ cursorAccount: true })`): rides the Cursor Slack
20
+ integration already installed in the workspace. No Slack app, no
21
+ manifests, no tokens, no Slack admin. Live in minutes.
22
+ - **Path B — Dedicated Slack app** (Socket Mode): the agent's own bot
23
+ user, created from generated manifests with an `xoxb-…` + `xapp-…`
24
+ token pair. Required for channel watching, approval buttons, or a
25
+ distinct bot handle. When the workspace is enrolled in Cursor's
26
+ **Add to Slack** (feature gate + a workspace-manager consent),
27
+ `agentkit slack create` provisions all of it in one command.
28
+
29
+ **Do not generate manifests or ask for tokens until the decision below
30
+ is made.** Defaulting into Path B buries the user in Slack admin work
31
+ (two app creations, token minting, env wiring) they may not need.
32
+
33
+ ## Step 0 — Choose the connection (required gate)
34
+
35
+ Walk the user through the tradeoffs before touching files:
36
+
37
+ | | A: Cursor-hosted | B: Dedicated Slack app |
38
+ | --- | --- | --- |
39
+ | Setup | Zero Slack admin — sign the host in (`agentkit login` / `CURSOR_API_KEY`) and serve | Enrolled in Cursor's Add to Slack: one `agentkit slack create` per env (app + install + tokens, signed-in host). Otherwise: a Slack admin creates **two** apps (dev + prod) from manifests, installs them, mints `xoxb-…` + `xapp-…` for each |
40
+ | Prereq | Cursor Slack integration installed in the workspace and linked to the Cursor account | Permission to create Slack apps; token storage/rotation is on you |
41
+ | How users reach it | `@Cursor <AgentName> …`, DMs to @Cursor, replies in claimed threads | Its own bot user: @mention, DM, channel invites |
42
+ | Identity | Posts as the Cursor app under the agent's name + icon | Own app name, avatar, and handle |
43
+ | Channel watching (dispatch without a mention) | Not available | `engagement.channelPosts` allowlist |
44
+ | Tool approvals / Block Kit interactivity | Not available (construction throws) | `toolApprovals: true` Approve/Deny cards |
45
+ | Reply delivery | Status while working, then one final post (no streaming edits) | Streaming replies with postMessage fallback |
46
+ | Multi-agent hosts | Any number of agents, unique `agentName` each, no extra Slack apps | One Slack app + token pair **per agent** |
47
+
48
+ Decision shortcuts — skip the question when the request already decides:
49
+
50
+ - Needs channel watching, Approve/Deny buttons, `onBlockAction`, or its
51
+ own bot user / handle → **Path B**. Say which requirement forced it.
52
+ - Workspace has no Cursor Slack integration and won't install it →
53
+ **Path B**.
54
+ - "Just get it into Slack", a first bring-up, or the user already said
55
+ to use the Cursor Slack integration, with none of the above → **Path A**.
56
+
57
+ ### Collect the decision with AskQuestion
58
+
59
+ Otherwise ask — one single-select question via the `AskQuestion` tool,
60
+ recommended option first so one click accepts it:
61
+
62
+ - **Cursor-hosted Slack connection (recommended)** — zero Slack setup;
63
+ sign in and mention `@Cursor <AgentName>`. No channel watching or
64
+ approval buttons.
65
+ - **Dedicated Slack app (Socket Mode)** — own bot user, channel
66
+ watching, approval buttons; needs a Slack admin to create two apps
67
+ and mint tokens.
68
+
69
+ If `AskQuestion` is unavailable in your environment, or the user does
70
+ not answer, **default to Path A (Cursor-hosted)**: state the assumption
71
+ in one line and proceed. It is the reversible choice — a dedicated app
72
+ can be added later as a *second* channel file without losing anything.
73
+ Never mix both in one channel definition: `cursorAccount: true` rejects
74
+ `credentials` / `envPrefix` at construction.
75
+
76
+ ## Path A — Cursor-hosted connection
77
+
78
+ Goal: mention `@Cursor <AgentName>` in the linked workspace and get a
79
+ threaded reply. No Slack app, no tokens, no manifests.
80
+
81
+ ### A1 — Author the channel (agent)
82
+
83
+ Write `agent/channels/slack.ts` by hand — do **not** run
84
+ `agentkit slack init` (that scaffolds the Path B manifests + env):
85
+
86
+ ```ts
87
+ import { slackChannel } from "@cursor/july/channels/slack";
88
+
89
+ export default slackChannel({
90
+ cursorAccount: true,
91
+ agentName: "MyAgent", // single token, no whitespace; prefer PascalCase
92
+ agentIcon: { emoji: ":robot_face:" },
93
+ });
94
+ ```
95
+
96
+ `agentName` defaults from the mount slug (PascalCase) and must be a
97
+ single token — string literals with spaces fail typecheck; runtime
98
+ values throw at construction/serve. Names must be unique on the host;
99
+ an unmatched `@Cursor <name>` stays with Cursor's normal Slack agent.
100
+
101
+ ### A2 — Sign in + serve (agent)
102
+
103
+ ```bash
104
+ agentkit login # or export CURSOR_API_KEY
105
+ agentkit dev .
106
+ ```
107
+
108
+ Confirm log: `[agentkit] cursor-slack: relaying Slack for <AgentName> …`.
109
+ An unsigned host fails `serve` with a sign-in hint naming the channel.
110
+
111
+ ### A3 — Smoke (human)
112
+
113
+ 1. In the Slack workspace linked to the Cursor account, post
114
+ `@Cursor MyAgent <question>` (or DM @Cursor)
115
+ 2. Confirm a working status while the turn runs, then a threaded reply
116
+ posted under the agent's name and icon
117
+ 3. Reply in the thread without re-mentioning — it stays with the agent
118
+
119
+ ### Path A limits (enforced at construction)
120
+
121
+ - `credentials` / `envPrefix` → throw (author a second channel file for
122
+ a dedicated app instead)
123
+ - `engagement.channelPosts`, `toolApprovals`, `interactivity`,
124
+ `onBlockAction` → throw (Socket Mode only)
125
+ - `engagement.mentions: false` / `directMessages: false` → throw (the
126
+ relay always delivers those)
127
+ - Streaming is forced off: rotating status while thinking, one final
128
+ reply post
129
+
130
+ When one of these limits becomes a real requirement, keep the
131
+ cursor-account channel and add a Path B channel file beside it.
132
+
133
+ ## Path B — Dedicated Slack app (Socket Mode)
134
+
135
+ Goal:
14
136
 
15
137
  - Importable **dev** and **prod** Slack app manifests (Socket Mode on)
16
138
  - App-level Token (`xapp-…`, `connections:write`) + Bot token (`xoxb-…`)
@@ -18,10 +140,40 @@ Use this skill when a human asks to wire Slack to an agentkit agent.
18
140
  - Thread ↔ session via `continuationToken = channelId:threadTs`
19
141
  - One Slack app (token pair) **per agent** when serving multiple demos
20
142
 
21
- ## Phases
22
-
23
143
  Update `.agent-serve/slack/setup-status.json` as you complete phases.
24
144
 
145
+ ### Provisioned variant — `agentkit slack create` (primary when enrolled)
146
+
147
+ When the Slack workspace is enrolled in Cursor's **Add to Slack**
148
+ (the provisioning feature gate plus a workspace-manager consent), one
149
+ command collapses Phases 0–3 — manifest import, app creation, install,
150
+ and token minting:
151
+
152
+ ```bash
153
+ agentkit slack create --dir <agent> # dev app (default)
154
+ agentkit slack create --dir <agent> --prod # prod app
155
+ ```
156
+
157
+ `create` scaffolds `agent/channels/slack.ts` + the `.agent-serve/slack`
158
+ files when missing (never overwriting existing ones), runs the browser
159
+ consent flow when the workspace is not connected yet, provisions +
160
+ installs the app, writes `<PREFIX>_SLACK_BOT_TOKEN` /
161
+ `<PREFIX>_SLACK_APP_TOKEN` into `<dir>/.env.local` (replacing stale
162
+ lines), and finishes with `doctor`. It needs a signed-in host
163
+ (`agentkit login` / `CURSOR_API_KEY`). Pass `--slack-team <id>` when
164
+ several workspaces are connected. If the install lands in
165
+ `pending_admin_approval`, a Slack workspace admin must approve the
166
+ printed link — then re-run `create` to finish and mint the tokens.
167
+ `agentkit slack destroy` deletes the provisioned app (tokens left in
168
+ `.env.local` simply stop working). Skip to Phase 4 when `create`
169
+ succeeds — `dev`/`serve` load the agent's `.env.local` (real env wins).
170
+ Note: re-running `create` rebuilds the app manifest from the command's
171
+ flags, so any customization made outside the CLI resets to it.
172
+
173
+ If the command reports the feature gate is not enabled (the workspace
174
+ is not enrolled), fall back to the manual manifest-import flow below
175
+ (Phases 0–3).
176
+
25
177
  ### Phase 0 — Generate (agent)
26
178
 
27
179
  ```bash
@@ -92,7 +244,7 @@ Human:
92
244
 
93
245
  ## Features (defaults ON)
94
246
 
95
- - Chat streaming (`chat.startStream` / `appendStream` / `stopStream`) with postMessage fallback
247
+ - Chat streaming (`chat.startStream` / `appendStream` / `stopStream`) with postMessage fallback (Path B; Path A posts one final reply)
96
248
  - Thinking / task cards for tool calls
97
249
  - `assistant.threads.setStatus` with rotating `loading_messages`
98
250
  - Thread title + suggested prompts
@@ -101,7 +253,7 @@ Human:
101
253
 
102
254
  If a Slack API is unavailable (`method_not_found` / `missing_scope`), the pack falls back to postMessage + setStatus.
103
255
 
104
- ## Engagement: mentions by default, channel watch opt-in
256
+ ## Engagement: mentions by default, channel watch opt-in (Path B only)
105
257
 
106
258
  The pack dispatches only on `app_mention` + DMs unless told otherwise —
107
259
  summoned, never proactive. To watch channels (dispatch on new posts without
@@ -128,7 +280,7 @@ bot to each watched channel. Posts mentioning the bot stay on the
128
280
  thread. `engagement.mentions` / `engagement.directMessages` can be set to
129
281
  `false` to turn those surfaces off.
130
282
 
131
- ## Tool approvals over Slack (opt-in HITL)
283
+ ## Tool approvals over Slack (opt-in HITL, Path B only)
132
284
 
133
285
  Tools with `needsApproval` park until a human approves or denies. To route
134
286
  that through Slack, set `toolApprovals: true` on `slackChannel` — it posts
@@ -163,15 +315,25 @@ Requirements and caveats:
163
315
 
164
316
  ## Notes
165
317
 
166
- - Dev and prod are **separate Slack apps** (separate tokens).
167
- - Socket Mode only no Events HTTP / Request URL path.
318
+ - Dev and prod are **separate Slack apps** (separate tokens) on Path B.
319
+ Path A has no per-env app split the host's Cursor account decides
320
+ where it relays.
321
+ - Socket Mode / the Cursor relay are outbound only — no Events HTTP /
322
+ Request URL path on either connection.
168
323
  - Do not `await waitForCompletion()` inside Slack dispatch handlers — the pack uses `waitUntil`.
169
324
  - Do not share one token pair across multiple agents in the same process.
170
325
 
171
326
  ## CLI reference
172
327
 
328
+ `slack create` / `destroy` / `init` / `manifest` / `doctor` are Path B
329
+ tooling; Path A needs only `login`.
330
+
173
331
  ```bash
174
332
  agentkit slack setup
333
+ agentkit slack create --dir . # provision via Add to Slack (dev app)
334
+ agentkit slack create --dir . --prod # prod app
335
+ agentkit slack create --dir . --slack-team T0123ABCD
336
+ agentkit slack destroy --dir . [--prod] [--slack-team T0123ABCD]
175
337
  agentkit slack init --dir . --name "My Agent"
176
338
  agentkit slack init --dir . --no-prefix
177
339
  agentkit slack init --dir . --channel-posts # + message.channels/groups events
@@ -56,6 +56,7 @@ import {
56
56
  CLI_COMMAND_NAME as CLI,
57
57
  packageVersion,
58
58
  } from "../internal/distribution.js";
59
+ import { loadAgentLocalEnv } from "../internal/local-env.js";
59
60
  import { clearTerminal, stdoutPalette } from "../internal/terminal-style.js";
60
61
  import { cmdUpdate, warnIfOutdated } from "../internal/update-check.js";
61
62
  import type { AgentProject, AgentServeHandle } from "../types.js";
@@ -100,7 +101,9 @@ Usage:
100
101
  ${CLI} mcp oauth <connection> [--dir <path>] [--store] [--slug <slug>]
101
102
  ${CLI} eval [--dir <path>] [evalId...] [--list] [--json]
102
103
  [--tag <tag>]... [--verbose] [--timeout-ms <n>]
103
- [--no-stream] [--no-wait]
104
+ [--strict] [--max-concurrency <n>]
105
+ [--junit <path>] [--artifacts <dir>|--no-artifacts]
106
+ [--skip-report] [--no-stream] [--no-wait]
104
107
  [--prod | --url <baseUrl>] [--slug <slug>]
105
108
  [--team <id>]
106
109
  ${CLI} eval status [runId] --prod|--url <baseUrl> [--dir <path>] [--json]
@@ -223,7 +226,8 @@ Commands:
223
226
  secrets Manage deployment secrets: set (upsert by name; NAMEs without
224
227
  =VALUE are prompted for with hidden input, or read from piped
225
228
  stdin), list (names + createdAt; never values), unset.
226
- slack Slack channel pack: init, manifests, doctor (see slack help).
229
+ slack Slack channel pack: create/destroy/icon (Cursor Add to Slack
230
+ provisioning), init, manifests, doctor (see slack help).
227
231
  github GitHub webhook pack: forward live deliveries, events, doctor
228
232
  (wraps \`gh webhook forward\`; see github help).
229
233
 
@@ -320,6 +324,13 @@ Options:
320
324
  --tag eval: only run cases with this tag (repeatable).
321
325
  --list eval: print discovered cases without running.
322
326
  --verbose eval: stream t.log lines and reply snippets.
327
+ --strict eval: a missed soft threshold (SCORED) also exits 1.
328
+ --max-concurrency eval: override evals.config.ts maxConcurrency.
329
+ --junit eval: write JUnit XML here for CI annotations.
330
+ --artifacts eval: run-artifact directory (default a timestamped dir
331
+ under <dir>/.agent-serve/evals/).
332
+ --no-artifacts eval: do not write run artifacts.
333
+ --skip-report eval: ignore reporters from evals.config.ts / eval files.
323
334
  --no-stream run/eval: silence live progress on stderr (JSON still prints).
324
335
  --json JSON output (init/info/chat/eval/logs/sessions/session/
325
336
  github; run defaults to JSON). logs: NDJSON progress/log
@@ -433,10 +444,14 @@ async function main(argv: string[]): Promise<number> {
433
444
  "base-url": { type: "string" },
434
445
  print: { type: "boolean", default: false },
435
446
  store: { type: "boolean", default: false },
447
+ remote: { type: "boolean", default: false },
436
448
  transport: { type: "string" },
437
449
  prefix: { type: "string" },
438
450
  "no-prefix": { type: "boolean", default: false },
439
451
  "channel-posts": { type: "boolean", default: false },
452
+ "slack-team": { type: "string" },
453
+ icon: { type: "string" },
454
+ force: { type: "boolean", default: false },
440
455
  repo: { type: "string", multiple: true },
441
456
  org: { type: "string" },
442
457
  "cursor-events": { type: "boolean", default: false },
@@ -456,6 +471,12 @@ async function main(argv: string[]): Promise<number> {
456
471
  all: { type: "boolean", default: false },
457
472
  "cursor-events-repo": { type: "string", multiple: true },
458
473
  "allow-domain": { type: "string", multiple: true },
474
+ strict: { type: "boolean", default: false },
475
+ junit: { type: "string" },
476
+ artifacts: { type: "string" },
477
+ "no-artifacts": { type: "boolean", default: false },
478
+ "skip-report": { type: "boolean", default: false },
479
+ "max-concurrency": { type: "string" },
459
480
  },
460
481
  });
461
482
  const dir = values.dir ?? ".";
@@ -483,6 +504,13 @@ async function main(argv: string[]): Promise<number> {
483
504
  prefix: values.prefix,
484
505
  noPrefix: values["no-prefix"],
485
506
  channelPosts: values["channel-posts"],
507
+ slackTeam: values["slack-team"],
508
+ prod: values.prod,
509
+ team: values.team,
510
+ apiKey: values["api-key"],
511
+ icon: values.icon,
512
+ force: values.force,
513
+ iconSource: positionals[0] === "icon" ? positionals[1] : undefined,
486
514
  });
487
515
  }
488
516
  case "github": {
@@ -545,6 +573,7 @@ async function main(argv: string[]): Promise<number> {
545
573
  print: values.print,
546
574
  json: values.json,
547
575
  store: values.store,
576
+ remote: values.remote,
548
577
  oauthConnection: mcpSub === "oauth" ? positionals[1] : undefined,
549
578
  });
550
579
  }
@@ -754,6 +783,11 @@ async function main(argv: string[]): Promise<number> {
754
783
  stateRoot: values["state-root"],
755
784
  timeoutMs: parseTimeoutMs(values["timeout-ms"]),
756
785
  stream: values["no-stream"] ? false : undefined,
786
+ strict: values.strict,
787
+ junit: values.junit,
788
+ artifacts: values["no-artifacts"] ? false : values.artifacts,
789
+ skipReport: values["skip-report"],
790
+ maxConcurrency: parseMaxConcurrency(values["max-concurrency"]),
757
791
  })
758
792
  );
759
793
  }
@@ -1016,6 +1050,16 @@ async function main(argv: string[]): Promise<number> {
1016
1050
  }
1017
1051
  const dev = command === "dev" || values.dev === true;
1018
1052
  const style = stdoutPalette();
1053
+ // Real env wins (loadEnvFile never overrides). Runs inside start()
1054
+ // so dev's Enter-restart picks up tokens written since boot.
1055
+ const loadLocalEnv = (): void => {
1056
+ const loadedEnvFiles = loadAgentLocalEnv(serveDir);
1057
+ if (loadedEnvFiles.length > 0) {
1058
+ process.stdout.write(
1059
+ `${style.dim(`env: loaded ${loadedEnvFiles.join(", ")}`)}\n`
1060
+ );
1061
+ }
1062
+ };
1019
1063
  const serveOptions = {
1020
1064
  port,
1021
1065
  host: values.host,
@@ -1055,6 +1099,7 @@ async function main(argv: string[]): Promise<number> {
1055
1099
  };
1056
1100
 
1057
1101
  const start = async (): Promise<AgentServeHandle> => {
1102
+ loadLocalEnv();
1058
1103
  const next = await serve(serveDir, serveOptions);
1059
1104
  printServeBanner(next, bannerOpts);
1060
1105
  if (enterToRestart) {
@@ -1179,6 +1224,11 @@ function axFromOptions(
1179
1224
  once: partial.once,
1180
1225
  rawEvents: partial.rawEvents,
1181
1226
  print: partial.print,
1227
+ strict: partial.strict,
1228
+ junit: partial.junit,
1229
+ artifacts: partial.artifacts,
1230
+ skipReport: partial.skipReport,
1231
+ maxConcurrency: partial.maxConcurrency,
1182
1232
  };
1183
1233
  }
1184
1234
 
@@ -1217,6 +1267,17 @@ function parseTimeoutMs(value: string | undefined): number | undefined {
1217
1267
  return n;
1218
1268
  }
1219
1269
 
1270
+ function parseMaxConcurrency(value: string | undefined): number | undefined {
1271
+ if (value === undefined) {
1272
+ return undefined;
1273
+ }
1274
+ const n = Number.parseInt(value, 10);
1275
+ if (Number.isNaN(n) || n <= 0) {
1276
+ throw new Error(`invalid --max-concurrency: ${value}`);
1277
+ }
1278
+ return n;
1279
+ }
1280
+
1220
1281
  /**
1221
1282
  * Load mounts the same way `serve` does (multi-agent layout by default).
1222
1283
  */
@@ -350,7 +350,14 @@ export async function postMessage(args: {
350
350
  base.thread_ts = args.threadTs;
351
351
  }
352
352
  const hasBlocks = args.blocks !== undefined && args.blocks.length > 0;
353
- const usePlainText = args.plainText === true || hasBlocks;
353
+ // User-group mentions (`<!subteam^…>`) and Slack mrkdwn links
354
+ // (`<https://…|label>`) only render correctly via mrkdwn `text`,
355
+ // not `markdown_text`.
356
+ const usePlainText =
357
+ args.plainText === true ||
358
+ hasBlocks ||
359
+ args.text.includes("<!subteam^") ||
360
+ /<https?:\/\/[^|>]+\|/.test(args.text);
354
361
 
355
362
  let response: Record<string, unknown>;
356
363
  if (usePlainText) {
@@ -451,8 +458,14 @@ export async function updateMessage(args: {
451
458
  channel: args.channel,
452
459
  ts: args.ts,
453
460
  };
454
- if (args.blocks !== undefined || args.plainText === true) {
455
- // Blocks / plainText force the legacy text path (same as postMessage).
461
+ if (
462
+ args.blocks !== undefined ||
463
+ args.plainText === true ||
464
+ args.text.includes("<!subteam^") ||
465
+ /<https?:\/\/[^|>]+\|/.test(args.text)
466
+ ) {
467
+ // Blocks / plainText / user-group mentions / mrkdwn links force the
468
+ // legacy text path (same as postMessage).
456
469
  return callSlackApiSoft({
457
470
  botToken: args.botToken,
458
471
  operation: "chat.update",
@@ -4,7 +4,7 @@
4
4
 
5
5
  import { samePrincipal } from "../../internal/auth.js";
6
6
  import type { AuthContext } from "../../types.js";
7
- import type { SlackBinding, SlackMessage } from "./types.js";
7
+ import type { SlackBinding, SlackBlockAction, SlackMessage } from "./types.js";
8
8
 
9
9
  /**
10
10
  * Build a thread-scoped principal so any participant in the same Slack
@@ -88,6 +88,21 @@ export function buildSlackInteractiveApprovalAuth(args: {
88
88
  return clickerAuth;
89
89
  }
90
90
 
91
+ /**
92
+ * Default auth for an `onBlockAction` dispatch: the click's thread-scoped
93
+ * principal with the clicker in attributes, so replies in the same thread
94
+ * continue the session and the clicker is the attributable user.
95
+ */
96
+ export function blockActionAuth(action: SlackBlockAction): AuthContext {
97
+ return buildSlackAuthContext({
98
+ channelId: action.channelId,
99
+ threadTs: action.threadTs,
100
+ teamId: action.teamId,
101
+ userId: action.userId,
102
+ userName: action.userName,
103
+ });
104
+ }
105
+
91
106
  export function defaultSlackAuth(
92
107
  message: SlackMessage,
93
108
  ctx: SlackBinding,