@cursor/july 0.1.49 → 0.1.51

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 (119) hide show
  1. package/AGENTS.md +3 -3
  2. package/README.md +7 -14
  3. package/dist/bin/agent-serve.js +22 -8
  4. package/dist/channels/slack/init.d.ts +2 -3
  5. package/dist/channels/slack/init.d.ts.map +1 -1
  6. package/dist/channels/slack/init.js +8 -43
  7. package/dist/channels/slack/manifest.d.ts +3 -3
  8. package/dist/channels/slack/manifest.js +3 -3
  9. package/dist/channels/slack/setup.d.ts +2 -11
  10. package/dist/channels/slack/setup.d.ts.map +1 -1
  11. package/dist/channels/slack/setup.js +26 -94
  12. package/dist/channels/slack/types.d.ts +3 -4
  13. package/dist/channels/slack/types.d.ts.map +1 -1
  14. package/dist/docs/404.html +2 -2
  15. package/dist/docs/ab.html +3 -3
  16. package/dist/docs/assets/{app.BpWAgjaR.js → app.C51TX1Bw.js} +1 -1
  17. package/dist/docs/assets/chunks/@localSearchIndexroot.D2DpXdZN.js +1 -0
  18. package/dist/docs/assets/chunks/{VPLocalSearchBox.CnAktZtG.js → VPLocalSearchBox.BB9HCJPq.js} +1 -1
  19. package/dist/docs/assets/chunks/{theme.B5IvUxOB.js → theme.Dp-0SZcu.js} +2 -2
  20. package/dist/docs/assets/{deployment.md.Cdp4rTE4.js → deployment.md.B8kW-h7P.js} +1 -1
  21. package/dist/docs/assets/{example-agents_benny.md.l7JTmm8X.js → example-agents_benny.md.B-LIDGja.js} +1 -1
  22. package/dist/docs/assets/{example-agents_oncall.md.ZE0n6ZFN.js → example-agents_oncall.md.CBmyuAKc.js} +2 -2
  23. package/dist/docs/assets/{guides_human-in-the-loop.md.BWvT7UqY.js → guides_human-in-the-loop.md.Cf8kIIqC.js} +2 -2
  24. package/dist/docs/assets/{guides_human-in-the-loop.md.BWvT7UqY.lean.js → guides_human-in-the-loop.md.Cf8kIIqC.lean.js} +1 -1
  25. package/dist/docs/assets/{guides_slack.md.zriQpU_9.js → guides_slack.md.D2nTRu9M.js} +7 -12
  26. package/dist/docs/assets/guides_slack.md.D2nTRu9M.lean.js +1 -0
  27. package/dist/docs/assets/{reference_cli.md.BDmjPPAm.js → reference_cli.md.CGKfz_Yj.js} +3 -7
  28. package/dist/docs/assets/{reference_cli.md.BDmjPPAm.lean.js → reference_cli.md.CGKfz_Yj.lean.js} +1 -1
  29. package/dist/docs/assets/{troubleshooting.md.CkgwmVI0.js → troubleshooting.md.C6n3wCr6.js} +1 -1
  30. package/dist/docs/building-with-agents.html +3 -3
  31. package/dist/docs/concepts.html +3 -3
  32. package/dist/docs/deployment.html +5 -5
  33. package/dist/docs/evals.html +3 -3
  34. package/dist/docs/example-agents/approval-buddy.html +3 -3
  35. package/dist/docs/example-agents/benny.html +5 -5
  36. package/dist/docs/example-agents/bugbot.html +3 -3
  37. package/dist/docs/example-agents/codebase-wiki.html +3 -3
  38. package/dist/docs/example-agents/codeowners-review.html +3 -3
  39. package/dist/docs/example-agents/concierge.html +3 -3
  40. package/dist/docs/example-agents/fsd.html +3 -3
  41. package/dist/docs/example-agents/index.html +3 -3
  42. package/dist/docs/example-agents/knowledge-base.html +3 -3
  43. package/dist/docs/example-agents/oncall.html +6 -6
  44. package/dist/docs/example-agents/security-reviewer.html +3 -3
  45. package/dist/docs/example-agents/slack-agent.html +3 -3
  46. package/dist/docs/example-agents/weather-agent.html +3 -3
  47. package/dist/docs/guides/agent-to-agent.html +3 -3
  48. package/dist/docs/guides/cloud-runtime.html +3 -3
  49. package/dist/docs/guides/github.html +3 -3
  50. package/dist/docs/guides/human-in-the-loop.html +5 -5
  51. package/dist/docs/guides/mcp-oauth.html +3 -3
  52. package/dist/docs/guides/opentelemetry.html +3 -3
  53. package/dist/docs/guides/slack.html +11 -16
  54. package/dist/docs/guides/webhooks.html +3 -3
  55. package/dist/docs/hashmap.json +1 -1
  56. package/dist/docs/hillclimbing.html +3 -3
  57. package/dist/docs/index.html +3 -3
  58. package/dist/docs/quickstart.html +3 -3
  59. package/dist/docs/reference/agent-config.html +3 -3
  60. package/dist/docs/reference/artifacts.html +3 -3
  61. package/dist/docs/reference/channels.html +3 -3
  62. package/dist/docs/reference/cli.html +6 -10
  63. package/dist/docs/reference/connections.html +3 -3
  64. package/dist/docs/reference/hooks.html +3 -3
  65. package/dist/docs/reference/http-api.html +3 -3
  66. package/dist/docs/reference/instructions.html +3 -3
  67. package/dist/docs/reference/playground.html +3 -3
  68. package/dist/docs/reference/project-layout.html +3 -3
  69. package/dist/docs/reference/prompt.html +3 -3
  70. package/dist/docs/reference/schedules.html +3 -3
  71. package/dist/docs/reference/sessions.html +3 -3
  72. package/dist/docs/reference/skills.html +3 -3
  73. package/dist/docs/reference/subagents.html +3 -3
  74. package/dist/docs/reference/tools.html +3 -3
  75. package/dist/docs/scaffolding-agents.html +3 -3
  76. package/dist/docs/storage.html +3 -3
  77. package/dist/docs/templates/triage.html +3 -3
  78. package/dist/docs/troubleshooting.html +5 -5
  79. package/dist/internal/cli-ax.js +3 -3
  80. package/dist/internal/cli-cursor.d.ts +18 -0
  81. package/dist/internal/cli-cursor.d.ts.map +1 -1
  82. package/dist/internal/cli-cursor.js +25 -0
  83. package/dist/internal/cli-slack.d.ts +3 -4
  84. package/dist/internal/cli-slack.d.ts.map +1 -1
  85. package/dist/internal/cli-slack.js +126 -322
  86. package/dist/internal/convert-automation/convert-workflow.js +2 -2
  87. package/dist/internal/slack-provision-client.d.ts +37 -2
  88. package/dist/internal/slack-provision-client.d.ts.map +1 -1
  89. package/dist/internal/slack-provision-client.js +46 -0
  90. package/dist/playground/assets/{index-Dq_HqyU-.js → index-BKMz70wx.js} +39 -39
  91. package/dist/playground/assets/index-BmMrulSc.css +1 -0
  92. package/dist/playground/index.html +2 -2
  93. package/docs/deployment.md +1 -1
  94. package/docs/example-agents/benny.md +2 -3
  95. package/docs/example-agents/oncall.md +4 -5
  96. package/docs/guides/human-in-the-loop.md +1 -1
  97. package/docs/guides/slack.md +51 -112
  98. package/docs/reference/cli.md +14 -37
  99. package/docs/troubleshooting.md +2 -2
  100. package/package.json +1 -1
  101. package/skills/create-agent/SKILL.md +4 -5
  102. package/skills/setup-slack/SKILL.md +73 -131
  103. package/src/bin/agent-serve.ts +26 -9
  104. package/src/channels/slack/init.ts +10 -71
  105. package/src/channels/slack/manifest.ts +3 -3
  106. package/src/channels/slack/setup.ts +25 -103
  107. package/src/channels/slack/types.ts +3 -4
  108. package/src/internal/cli-ax.ts +3 -3
  109. package/src/internal/cli-cursor.ts +34 -0
  110. package/src/internal/cli-slack.ts +136 -389
  111. package/src/internal/convert-automation/convert-workflow.ts +2 -2
  112. package/src/internal/slack-provision-client.ts +83 -2
  113. package/dist/docs/assets/chunks/@localSearchIndexroot.D00d772K.js +0 -1
  114. package/dist/docs/assets/guides_slack.md.zriQpU_9.lean.js +0 -1
  115. package/dist/playground/assets/index-Dox74yWJ.css +0 -1
  116. /package/dist/docs/assets/{deployment.md.Cdp4rTE4.lean.js → deployment.md.B8kW-h7P.lean.js} +0 -0
  117. /package/dist/docs/assets/{example-agents_benny.md.l7JTmm8X.lean.js → example-agents_benny.md.B-LIDGja.lean.js} +0 -0
  118. /package/dist/docs/assets/{example-agents_oncall.md.ZE0n6ZFN.lean.js → example-agents_oncall.md.CBmyuAKc.lean.js} +0 -0
  119. /package/dist/docs/assets/{troubleshooting.md.CkgwmVI0.lean.js → troubleshooting.md.C6n3wCr6.lean.js} +0 -0
@@ -1,34 +1,34 @@
1
1
  ---
2
2
  name: agentkit-setup-slack
3
3
  description: >-
4
- Put an Agent SDK 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
- Agent SDK project.
4
+ Wire Slack to an Agent SDK agent. Gate Cursor-hosted vs a dedicated
5
+ Socket Mode app, then finish that path: cursorAccount sign-in + smoke,
6
+ or slack create via the dashboard wizard, doctor, and optional HITL.
7
+ Use when adding Slack to an agent.
10
8
  ---
11
9
 
12
10
  # Setup Slack for the Agent SDK
13
11
 
14
12
  Use this skill when a human asks to wire Slack to an Agent SDK agent.
15
13
 
16
- There are **two ways to connect**, and they differ mostly in setup cost:
14
+ There are **two ways to connect**:
17
15
 
18
16
  - **Path A — Cursor-hosted connection**
19
17
  (`slackChannel({ cursorAccount: true })`): rides the Cursor Slack
20
18
  integration already installed in the workspace. No Slack app, no
21
- manifests, no tokens, no Slack admin. Live in minutes.
19
+ tokens, no Slack admin. Live in minutes.
22
20
  - **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
- `agent-sdk slack create` provisions all of it in one command.
21
+ user. `agent-sdk slack create` opens a signed-in Cursor dashboard
22
+ wizard; Slack consent and the bot name happen there. Tokens land in
23
+ `.env.local` and as deployment secrets. Required for channel watching,
24
+ approval buttons, or a distinct bot handle.
28
25
 
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.
26
+ Do not generate manifests or ask anyone to paste tokens. Defaulting into
27
+ Path B buries the user in Slack admin work they may not need.
28
+
29
+ Existing DIY bots that already have `<PREFIX>_SLACK_BOT_TOKEN` and
30
+ `_SLACK_APP_TOKEN` in `.env.local` keep working. Do not force them onto
31
+ the wizard.
32
32
 
33
33
  ## Step 0 — Choose the connection (required gate)
34
34
 
@@ -36,8 +36,8 @@ Walk the user through the tradeoffs before touching files:
36
36
 
37
37
  | | A: Cursor-hosted | B: Dedicated Slack app |
38
38
  | --- | --- | --- |
39
- | Setup | Zero Slack admin sign the host in (`agent-sdk login` / `CURSOR_API_KEY`) and serve | Enrolled in Cursor's Add to Slack: one `agent-sdk 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 |
39
+ | Setup | Zero Slack admin: sign the host in (`agent-sdk login` / `CURSOR_API_KEY`) and serve | One `agent-sdk slack create` per env. Finish in the dashboard wizard (Slack consent + bot name). Tokens are never shown. |
40
+ | Prereq | Cursor Slack integration installed in the workspace and linked to the Cursor account | Agent Serve access (`agent-sdk login`) and permission to approve a Slack app |
41
41
  | How users reach it | `@Cursor <AgentName> …`, DMs to @Cursor, replies in claimed threads | Its own bot user: @mention, DM, channel invites |
42
42
  | Identity | Posts as the Cursor app under the agent's name + icon | Own app name, avatar, and handle |
43
43
  | Channel watching (dispatch without a mention) | Not available | `engagement.channelPosts` allowlist |
@@ -45,7 +45,7 @@ Walk the user through the tradeoffs before touching files:
45
45
  | Reply delivery | Status while working, then one final post (no streaming edits) | Streaming replies with postMessage fallback |
46
46
  | Multi-agent hosts | Any number of agents, unique `agentName` each, no extra Slack apps | One Slack app + token pair **per agent** |
47
47
 
48
- Decision shortcuts skip the question when the request already decides:
48
+ Decision shortcuts; skip the question when the request already decides:
49
49
 
50
50
  - Needs channel watching, Approve/Deny buttons, `onBlockAction`, or its
51
51
  own bot user / handle → **Path B**. Say which requirement forced it.
@@ -56,19 +56,19 @@ Decision shortcuts — skip the question when the request already decides:
56
56
 
57
57
  ### Collect the decision with AskQuestion
58
58
 
59
- Otherwise ask one single-select question via the `AskQuestion` tool,
59
+ Otherwise ask. One single-select question via the `AskQuestion` tool,
60
60
  recommended option first so one click accepts it:
61
61
 
62
62
  - **Cursor-hosted Slack connection (recommended)** — zero Slack setup;
63
63
  sign in and mention `@Cursor <AgentName>`. No channel watching or
64
64
  approval buttons.
65
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.
66
+ watching, approval buttons. `agent-sdk slack create` opens the
67
+ dashboard wizard.
68
68
 
69
69
  If `AskQuestion` is unavailable in your environment, or the user does
70
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
71
+ in one line and proceed. It is the reversible choice. A dedicated app
72
72
  can be added later as a *second* channel file without losing anything.
73
73
  Never mix both in one channel definition: `cursorAccount: true` rejects
74
74
  `credentials` / `envPrefix` at construction.
@@ -80,8 +80,8 @@ threaded reply. No Slack app, no tokens, no manifests.
80
80
 
81
81
  ### A1 — Author the channel (agent)
82
82
 
83
- Write `agent/channels/slack.ts` by hand do **not** run
84
- `agent-sdk slack init` (that scaffolds the Path B manifests + env):
83
+ Write `agent/channels/slack.ts` by hand. Do not run `slack create` for
84
+ this path:
85
85
 
86
86
  ```ts
87
87
  import { slackChannel } from "@cursor/july/channels/slack";
@@ -94,7 +94,7 @@ export default slackChannel({
94
94
  ```
95
95
 
96
96
  `agentName` defaults from the mount slug (PascalCase) and must be a
97
- single token string literals with spaces fail typecheck; runtime
97
+ single token. String literals with spaces fail typecheck; runtime
98
98
  values throw at construction/serve. Names must be unique on the host;
99
99
  an unmatched `@Cursor <name>` stays with Cursor's normal Slack agent.
100
100
  External senders (Slack Connect / guests / other workspaces) are
@@ -117,7 +117,7 @@ An unsigned host fails `serve` with a sign-in hint naming the channel.
117
117
  `@Cursor MyAgent <question>` (or DM @Cursor)
118
118
  2. Confirm a working status while the turn runs, then a threaded reply
119
119
  posted under the agent's name and icon
120
- 3. Reply in the thread without re-mentioning it stays with the agent
120
+ 3. Reply in the thread without re-mentioning; it stays with the agent
121
121
 
122
122
  ### Path A limits (enforced at construction)
123
123
 
@@ -135,109 +135,47 @@ cursor-account channel and add a Path B channel file beside it.
135
135
 
136
136
  ## Path B — Dedicated Slack app (Socket Mode)
137
137
 
138
- Goal:
139
-
140
- - Importable **dev** and **prod** Slack app manifests (Socket Mode on)
141
- - App-level Token (`xapp-…`, `connections:write`) + Bot token (`xoxb-…`)
142
- - No public Request URL (Socket Mode only)
143
- - Thread ↔ session via `continuationToken = channelId:threadTs`
144
- - One Slack app (token pair) **per agent** when serving multiple demos
145
-
146
- Update `.agent-serve/slack/setup-status.json` as you complete phases.
147
-
148
- ### Provisioned variant — `agent-sdk slack create` (primary when enrolled)
149
-
150
- When the Slack workspace is enrolled in Cursor's **Add to Slack**
151
- (the provisioning feature gate plus a workspace-manager consent), one
152
- command collapses Phases 0–3 — manifest import, app creation, install,
153
- and token minting:
138
+ Goal: one dedicated bot per agent, tokens in `.env.local`, local serve
139
+ without a cloud deploy. The dashboard wizard is the only first-run.
154
140
 
155
141
  ```bash
156
- agent-sdk slack create --dir <agent> # dev app (default)
157
- agent-sdk slack create --dir <agent> --prod # prod app
142
+ agent-sdk login
143
+ agent-sdk slack create --dir .
158
144
  ```
159
145
 
160
- `create` scaffolds `agent/channels/slack.ts` + the `.agent-serve/slack`
161
- files when missing (never overwriting existing ones), runs the browser
162
- consent flow when the workspace is not connected yet, provisions +
163
- installs the app, writes `<PREFIX>_SLACK_BOT_TOKEN` /
164
- `<PREFIX>_SLACK_APP_TOKEN` into `<dir>/.env.local` (replacing stale
165
- lines), and finishes with `doctor`. It needs a signed-in host
166
- (`agent-sdk login` / `CURSOR_API_KEY`). Pass `--slack-team <id>` when
167
- several workspaces are connected. If the install lands in
168
- `pending_admin_approval`, a Slack workspace admin must approve the
169
- printed link — then re-run `create` to finish and mint the tokens.
170
- `agent-sdk slack destroy` deletes the provisioned app (tokens left in
171
- `.env.local` simply stop working). Skip to Phase 4 when `create`
172
- succeeds — `dev`/`serve` load the agent's `.env.local` (real env wins).
173
- Note: re-running `create` rebuilds the app manifest from the command's
174
- flags, so any customization made outside the CLI resets to it.
175
-
176
- If the command reports the feature gate is not enabled (the workspace
177
- is not enrolled), fall back to the manual manifest-import flow below
178
- (Phases 0–3).
179
-
180
- ### Phase 0 — Generate (agent)
181
-
182
- ```bash
183
- pnpm exec tsx packages/agent-serve/src/bin/agent-serve.ts slack init \
184
- --dir <agent> --name "My Agent"
185
- ```
186
-
187
- Creates:
188
-
189
- - `agent/channels/slack.ts` with `envPrefix` from the directory name
190
- - `.agent-serve/slack/manifest.{dev,prod}.json`
191
- - `.agent-serve/slack/env.example` (`<PREFIX>_SLACK_BOT_TOKEN` / `_APP_TOKEN`)
192
-
193
- Use `--no-prefix` for the shared `SLACK_BOT_TOKEN` / `SLACK_APP_TOKEN` globals
194
- (single-agent only). Use `--prefix CUSTOM` to override the default prefix.
195
-
196
- These files deliberately omit `settings.managed_app_settings` — Slack accepts
197
- that block only from a manager app's user token, so it belongs to the
198
- `slack create` path, not to a manifest a human pastes in.
199
-
200
- ### Phase 1 — Create apps (human)
146
+ That opens the signed-in Cursor dashboard. Sign in as the same Cursor
147
+ account that ran the command. Click **Add Slack to this agent**, approve
148
+ Slack's consent screen, pick the bot name, and continue. The CLI waits
149
+ and writes `<PREFIX>_SLACK_BOT_TOKEN` / `<PREFIX>_SLACK_APP_TOKEN` into
150
+ `<dir>/.env.local`, then runs `doctor`. Token values never print.
201
151
 
202
- 1. Open https://api.slack.com/apps **Create New App** **From a manifest**
203
- 2. Paste `manifest.dev.json` create the *dev* app
204
- 3. Repeat with `manifest.prod.json` for prod
152
+ `--prod` provisions the prod app (default is dev). `--name` / `--icon` /
153
+ `--channel-posts` prefill the wizard. `--prefix` / `--no-prefix` set the
154
+ env-var names.
205
155
 
206
- Stop and ask the human to complete this gate.
156
+ If Slack asks a workspace admin to approve the app, keep the CLI
157
+ running. Open Slack's **Request approval** page (the CLI prints the
158
+ link; the same URL is **Send a reminder** after you submit). Managed
159
+ install does not file the request. After an admin approves, click
160
+ **Retry** in the wizard.
207
161
 
208
- ### Phase 2 Install + tokens (human)
162
+ `create` scaffolds `agent/channels/slack.ts` when missing. Do not paste
163
+ a manifest at api.slack.com. `slack init` is removed.
209
164
 
210
- For each app:
165
+ Existing tokens in `.env.local` keep working. Skip the wizard for those
166
+ agents unless you want a Cursor-managed app.
211
167
 
212
- 1. **Install to Workspace** — copy Bot User OAuth Token (`xoxb-…`)
213
- 2. **Basic Information → App-Level Tokens** — Create Token with scope `connections:write` → copy (`xapp-…`)
214
-
215
- ### Phase 3 — Env (agent)
216
-
217
- Write into `.env.local` (dev app), using the keys from `env.example`:
218
-
219
- ```bash
220
- MY_AGENT_SLACK_BOT_TOKEN=xoxb-…
221
- MY_AGENT_SLACK_APP_TOKEN=xapp-…
222
- ```
168
+ Then:
223
169
 
224
170
  ```bash
225
171
  agent-sdk slack doctor --prefix MY_AGENT
226
- ```
227
-
228
- Stop when `app_token`, `connections_open`, `bot_token`, and `auth_test` are green.
229
-
230
- ### Phase 4 — Serve + smoke (agent + human)
231
-
232
- ```bash
233
172
  agent-sdk dev .
234
173
  ```
235
174
 
236
175
  Confirm log: `[agent-sdk/slack] Socket Mode connected`.
237
176
 
238
177
  When tokens are missing the channel logs
239
- `channel idle reason=missing credentials need=…` and `serve` continues — useful
240
- when mounting a folder of agents where only some have tokens.
178
+ `channel idle reason=missing credentials need=…` and `serve` continues.
241
179
 
242
180
  Human:
243
181
 
@@ -249,6 +187,15 @@ Human:
249
187
  - `session start …`
250
188
  - `reply delivered via postMessage|stream …`
251
189
 
190
+ The dashboard lists a first-run agent as **Not deployed yet**. Local
191
+ serve does not need a hosted engine. The next `agent-sdk deploy` (or
192
+ dashboard **Deploy**) injects the stored secrets.
193
+
194
+ A second `slack create` for the same agent and env overwrites that Slack
195
+ app. It keeps the Slack app id and replaces the manifest and tokens.
196
+ `agent-sdk slack destroy` deletes the provisioned app. Tokens left in
197
+ `.env.local` simply stop working.
198
+
252
199
  ## Features (defaults ON)
253
200
 
254
201
  - Chat streaming (`chat.startStream` / `appendStream` / `stopStream`) with postMessage fallback (Path B; Path A posts one final reply)
@@ -262,7 +209,7 @@ If a Slack API is unavailable (`method_not_found` / `missing_scope`), the pack f
262
209
 
263
210
  ## Engagement: mentions by default, channel watch opt-in (Path B only)
264
211
 
265
- The pack dispatches only on `app_mention` + DMs unless told otherwise
212
+ The pack dispatches only on `app_mention` + DMs unless told otherwise:
266
213
  summoned, never proactive. To watch channels (dispatch on new posts without
267
214
  a mention), opt in explicitly:
268
215
 
@@ -279,9 +226,9 @@ export default slackChannel({
279
226
  });
280
227
  ```
281
228
 
282
- Requirements: generate manifests with `slack init --channel-posts` (or add
283
- `message.channels` / `message.groups` events + re-import), and invite the
284
- bot to each watched channel. Posts mentioning the bot stay on the
229
+ Pass `--channel-posts` on `slack create` so the wizard-built app
230
+ subscribes to `message.channels` / `message.groups`. Invite the bot to
231
+ each watched channel. Posts mentioning the bot stay on the
285
232
  `app_mention` path; watch sessions reuse the thread-scoped principal with an
286
233
  `engagement: "channel_post"` attribute, so a later mention continues the
287
234
  thread. `engagement.mentions` / `engagement.directMessages` can be set to
@@ -290,7 +237,7 @@ thread. `engagement.mentions` / `engagement.directMessages` can be set to
290
237
  ## Tool approvals over Slack (opt-in HITL, Path B only)
291
238
 
292
239
  Tools with `needsApproval` park until a human approves or denies. To route
293
- that through Slack, set `toolApprovals: true` on `slackChannel` it posts
240
+ that through Slack, set `toolApprovals: true` on `slackChannel`. It posts
294
241
  Block Kit Approve/Deny cards and routes Socket Mode `interactive` clicks
295
242
  back to the parked call:
296
243
 
@@ -303,10 +250,9 @@ export default slackChannel({
303
250
 
304
251
  Requirements and caveats:
305
252
 
306
- - The Slack app manifest needs **interactivity** enabled
307
- (`buildSlackManifest({ interactivity: true })`; `toolApprovals: true`
308
- implies the Socket Mode routing, but the app must allow it). Re-import
309
- the manifest after changing this.
253
+ - The Slack app needs **interactivity** enabled. The wizard turns this
254
+ on when `toolApprovals` is in play; `buildSlackManifest({ interactivity: true })`
255
+ is the same switch for existing apps.
310
256
  - Composing by hand: spread `buildToolApprovalEvents({ credentials })` into
311
257
  `events` **and** set `interactivity: true` on the channel.
312
258
  - Cards show **redacted / truncated** args (Block Kit limits); execution
@@ -323,27 +269,23 @@ Requirements and caveats:
323
269
  ## Notes
324
270
 
325
271
  - Dev and prod are **separate Slack apps** (separate tokens) on Path B.
326
- Path A has no per-env app split the host's Cursor account decides
272
+ Path A has no per-env app split; the host's Cursor account decides
327
273
  where it relays.
328
- - Socket Mode / the Cursor relay are outbound only no Events HTTP /
274
+ - Socket Mode / the Cursor relay are outbound only. No Events HTTP /
329
275
  Request URL path on either connection.
330
- - Do not `await waitForCompletion()` inside Slack dispatch handlers the pack uses `waitUntil`.
276
+ - Do not `await waitForCompletion()` inside Slack dispatch handlers. The pack uses `waitUntil`.
331
277
  - Do not share one token pair across multiple agents in the same process.
332
278
 
333
279
  ## CLI reference
334
280
 
335
- `slack create` / `destroy` / `init` / `manifest` / `doctor` are Path B
336
- tooling; Path A needs only `login`.
281
+ Path B tooling is `create` / `destroy` / `icon` / `doctor`. Path A needs
282
+ only `login`. `slack setup` prints this chooser. `slack init` hard-errors.
337
283
 
338
284
  ```bash
339
285
  agent-sdk slack setup
340
- agent-sdk slack create --dir . # provision via Add to Slack (dev app)
286
+ agent-sdk slack create --dir . # dashboard wizard (dev app)
341
287
  agent-sdk slack create --dir . --prod # prod app
342
288
  agent-sdk slack create --dir . --slack-team T0123ABCD
343
289
  agent-sdk slack destroy --dir . [--prod] [--slack-team T0123ABCD]
344
- agent-sdk slack init --dir . --name "My Agent"
345
- agent-sdk slack init --dir . --no-prefix
346
- agent-sdk slack init --dir . --channel-posts # + message.channels/groups events
347
- agent-sdk slack manifest --env both
348
290
  agent-sdk slack doctor --prefix MY_AGENT
349
291
  ```
@@ -44,6 +44,7 @@ import {
44
44
  cmdSessions,
45
45
  cmdTrajectory,
46
46
  } from "../internal/cli-ax.js";
47
+ import { ensureCursorLogin } from "../internal/cli-cursor.js";
47
48
  import {
48
49
  cmdDelete,
49
50
  cmdDeploy,
@@ -150,11 +151,12 @@ Usage:
150
151
  ${CLI} github <subcommand> …
151
152
 
152
153
  Commands:
153
- serve Serve agents under /<slug>/... (index at /). On a TTY, press
154
- Enter to restart (re-executes this process so agent code, evals,
155
- and Vite reload).
154
+ serve Serve agents under /<slug>/... (index at /). Runs \`${CLI} login\`
155
+ when unsigned. On a TTY, press Enter to restart (re-executes this
156
+ process so agent code, evals, and Vite reload).
156
157
  dev Local development: same as \`${CLI} serve --dev\` (manual
157
158
  schedule/reminder dispatch, unsigned GitHub loopback, Vite HMR).
159
+ Also runs \`${CLI} login\` when unsigned.
158
160
  chat Interactive REPL against a running server (follow-ups keep the
159
161
  session + continuation token). Optional --message seeds the first
160
162
  turn then stays open on a TTY. --session reattaches (looks up the
@@ -271,8 +273,8 @@ Commands:
271
273
  secrets Manage deployment secrets: set (names only by default: hidden
272
274
  prompt or piped stdin; NAME=VALUE requires --from-argv), list
273
275
  (names + createdAt; never values), unset.
274
- slack Slack channel pack: create/destroy/icon (Cursor Add to Slack
275
- provisioning), init, manifests, doctor (see slack help).
276
+ slack Slack channel pack: create/destroy/icon (dashboard wizard),
277
+ doctor (see slack help).
276
278
  github GitHub webhook pack: forward live deliveries, events, doctor
277
279
  (wraps \`gh webhook forward\`; see github help).
278
280
 
@@ -1264,17 +1266,32 @@ async function main(argv: string[]): Promise<number> {
1264
1266
  noSchedules: values["no-schedules"] === true,
1265
1267
  };
1266
1268
 
1267
- const start = async (): Promise<AgentServeHandle> => {
1269
+ const start = async (): Promise<
1270
+ | { kind: "ready"; handle: AgentServeHandle }
1271
+ | { kind: "login-failed"; exitCode: number }
1272
+ > => {
1268
1273
  loadLocalEnv();
1274
+ // Model turns need a Cursor credential. Prompt login before listen
1275
+ // so the first playground turn does not fail with a late auth error.
1276
+ const loginExit = await ensureCursorLogin({
1277
+ apiKey: values["api-key"],
1278
+ });
1279
+ if (loginExit !== 0) {
1280
+ return { kind: "login-failed", exitCode: loginExit };
1281
+ }
1269
1282
  const next = await serve(serveDir, serveOptions);
1270
1283
  printServeBanner(next, bannerOpts);
1271
1284
  if (enterToRestart) {
1272
1285
  process.stdout.write(style.dim(" press Enter to restart\n"));
1273
1286
  }
1274
- return next;
1287
+ return { kind: "ready", handle: next };
1275
1288
  };
1276
1289
 
1277
- const handle = await start();
1290
+ const started = await start();
1291
+ if (started.kind === "login-failed") {
1292
+ return started.exitCode;
1293
+ }
1294
+ const handle = started.handle;
1278
1295
  let closing = false;
1279
1296
  let restartRequested = false;
1280
1297
 
@@ -1502,7 +1519,7 @@ function printServeBanner(
1502
1519
  }
1503
1520
  // `/` is only mounted when the playground host home is enabled.
1504
1521
  if (!opts.noPlayground) {
1505
- process.stdout.write(` home ${c.cyan(handle.url + "/")}\n`);
1522
+ process.stdout.write(` home ${c.cyan(`${handle.url}/`)}\n`);
1506
1523
  }
1507
1524
  // Dev is playground-first (Vite proxies the API). Keep API/route detail for
1508
1525
  // plain `serve`, where operators often curl the HTTP surface directly.
@@ -6,7 +6,6 @@ import { mkdir, writeFile } from "node:fs/promises";
6
6
  import { basename, join, resolve } from "node:path";
7
7
  import { PACKAGE_NAME } from "../../internal/distribution.js";
8
8
  import { envPrefixFromName, slackEnvKeys } from "./credentials.js";
9
- import { buildSlackManifestPair } from "./manifest.js";
10
9
 
11
10
  export interface InitSlackOptions {
12
11
  dir: string;
@@ -20,9 +19,8 @@ export interface InitSlackOptions {
20
19
  */
21
20
  envPrefix?: string;
22
21
  /**
23
- * Subscribe the generated manifests to `message.channels` +
24
- * `message.groups` for the opt-in channel watch
25
- * (`engagement.channelPosts` on `slackChannel`).
22
+ * Subscribe the generated app to `message.channels` + `message.groups`
23
+ * for the opt-in channel watch (`engagement.channelPosts`).
26
24
  */
27
25
  channelPosts?: boolean;
28
26
  }
@@ -38,7 +36,6 @@ export async function initSlackChannel(
38
36
  options: InitSlackOptions
39
37
  ): Promise<InitSlackResult> {
40
38
  const rootDir = resolve(options.dir);
41
- const name = options.name ?? basename(rootDir);
42
39
  const envPrefix =
43
40
  options.envPrefix === ""
44
41
  ? undefined
@@ -46,29 +43,22 @@ export async function initSlackChannel(
46
43
  const envKeys = slackEnvKeys(envPrefix);
47
44
  const written: string[] = [];
48
45
 
49
- const write = async (rel: string, contents: string): Promise<void> => {
50
- const abs = join(rootDir, rel);
51
- await mkdir(join(abs, ".."), { recursive: true });
52
- await writeFile(abs, contents, { flag: "wx" });
53
- written.push(rel);
54
- };
55
-
46
+ const abs = join(rootDir, "agent/channels/slack.ts");
47
+ await mkdir(join(abs, ".."), { recursive: true });
56
48
  const envPrefixLine =
57
49
  envPrefix === undefined
58
50
  ? ""
59
51
  : ` envPrefix: ${JSON.stringify(envPrefix)},\n`;
60
-
61
- await write(
62
- "agent/channels/slack.ts",
52
+ await writeFile(
53
+ abs,
63
54
  `import { slackChannel } from "${PACKAGE_NAME}/channels/slack";
64
55
 
65
56
  /**
66
57
  * Slack channel (Socket Mode).
67
58
  *
68
59
  * Tokens: ${envKeys.bot} + ${envKeys.app}
69
- * (see .agent-serve/slack/env.example).
70
60
  *
71
- * Full setup: agent-serve slack setup
61
+ * Full setup: agent-serve slack create --dir .
72
62
  */
73
63
  export default slackChannel({
74
64
  ${envPrefixLine} // Streaming and thinking steps default to true.
@@ -77,61 +67,10 @@ ${envPrefixLine} // Streaming and thinking steps default to true.
77
67
  { title: "Status", message: "What are you working on?" },
78
68
  ],
79
69
  });
80
- `
81
- );
82
-
83
- const pair = buildSlackManifestPair({
84
- name,
85
- // Scaffolded for hand-import at api.slack.com; managed_app_settings is
86
- // settable only with the manager app's user token.
87
- managedByCursor: false,
88
- ...(options.description === undefined
89
- ? {}
90
- : { description: options.description }),
91
- ...(options.channelPosts === true ? { channelPosts: true } : {}),
92
- });
93
-
94
- await write(
95
- ".agent-serve/slack/manifest.dev.json",
96
- `${JSON.stringify(pair.dev, null, 2)}\n`
97
- );
98
- await write(
99
- ".agent-serve/slack/manifest.prod.json",
100
- `${JSON.stringify(pair.prod, null, 2)}\n`
101
- );
102
-
103
- await write(
104
- ".agent-serve/slack/env.example",
105
- `# Copy to .env.local (or export in your shell). Use the *dev* Slack app
106
- # for local development; use the Prod app tokens in deployment secrets.
107
- #
108
- # Multi-agent serve needs a distinct Slack app (and token pair) per agent.
109
-
110
- ${envKeys.bot}=xoxb-...
111
- ${envKeys.app}=xapp-...
112
- `
113
- );
114
-
115
- await write(
116
- ".agent-serve/slack/setup-status.json",
117
- `${JSON.stringify(
118
- {
119
- updatedAt: new Date().toISOString(),
120
- envPrefix: envPrefix ?? null,
121
- envKeys,
122
- phases: {
123
- generate: true,
124
- createApps: false,
125
- install: false,
126
- env: false,
127
- serve: false,
128
- smoke: false,
129
- },
130
- },
131
- null,
132
- 2
133
- )}\n`
70
+ `,
71
+ { flag: "wx" }
134
72
  );
73
+ written.push("agent/channels/slack.ts");
135
74
 
136
75
  return { rootDir, files: written, envPrefix, envKeys };
137
76
  }
@@ -1,8 +1,8 @@
1
1
  /**
2
- * Generate importable Slack app manifests (dev + prod).
2
+ * Generate Slack app manifests (dev + prod) for Cursor-managed provision.
3
3
  *
4
- * Import at https://api.slack.com/apps -> Create New App -> From a manifest.
5
- * Always Socket Mode no Events Request URL.
4
+ * Always Socket Mode. No Events Request URL. Humans do not paste these
5
+ * at api.slack.com; `slack create` sends them through the dashboard wizard.
6
6
  *
7
7
  * Mirrored by backend/server/src/agentServe/agentServeSlackManifest.ts (the
8
8
  * backend cannot import this published package); keep the twins in lockstep.