@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.
- package/AGENTS.md +3 -3
- package/README.md +7 -14
- package/dist/bin/agent-serve.js +22 -8
- package/dist/channels/slack/init.d.ts +2 -3
- package/dist/channels/slack/init.d.ts.map +1 -1
- package/dist/channels/slack/init.js +8 -43
- package/dist/channels/slack/manifest.d.ts +3 -3
- package/dist/channels/slack/manifest.js +3 -3
- package/dist/channels/slack/setup.d.ts +2 -11
- package/dist/channels/slack/setup.d.ts.map +1 -1
- package/dist/channels/slack/setup.js +26 -94
- package/dist/channels/slack/types.d.ts +3 -4
- package/dist/channels/slack/types.d.ts.map +1 -1
- package/dist/docs/404.html +2 -2
- package/dist/docs/ab.html +3 -3
- package/dist/docs/assets/{app.BpWAgjaR.js → app.C51TX1Bw.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.D2DpXdZN.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.CnAktZtG.js → VPLocalSearchBox.BB9HCJPq.js} +1 -1
- package/dist/docs/assets/chunks/{theme.B5IvUxOB.js → theme.Dp-0SZcu.js} +2 -2
- package/dist/docs/assets/{deployment.md.Cdp4rTE4.js → deployment.md.B8kW-h7P.js} +1 -1
- package/dist/docs/assets/{example-agents_benny.md.l7JTmm8X.js → example-agents_benny.md.B-LIDGja.js} +1 -1
- package/dist/docs/assets/{example-agents_oncall.md.ZE0n6ZFN.js → example-agents_oncall.md.CBmyuAKc.js} +2 -2
- package/dist/docs/assets/{guides_human-in-the-loop.md.BWvT7UqY.js → guides_human-in-the-loop.md.Cf8kIIqC.js} +2 -2
- package/dist/docs/assets/{guides_human-in-the-loop.md.BWvT7UqY.lean.js → guides_human-in-the-loop.md.Cf8kIIqC.lean.js} +1 -1
- package/dist/docs/assets/{guides_slack.md.zriQpU_9.js → guides_slack.md.D2nTRu9M.js} +7 -12
- package/dist/docs/assets/guides_slack.md.D2nTRu9M.lean.js +1 -0
- package/dist/docs/assets/{reference_cli.md.BDmjPPAm.js → reference_cli.md.CGKfz_Yj.js} +3 -7
- package/dist/docs/assets/{reference_cli.md.BDmjPPAm.lean.js → reference_cli.md.CGKfz_Yj.lean.js} +1 -1
- package/dist/docs/assets/{troubleshooting.md.CkgwmVI0.js → troubleshooting.md.C6n3wCr6.js} +1 -1
- package/dist/docs/building-with-agents.html +3 -3
- package/dist/docs/concepts.html +3 -3
- package/dist/docs/deployment.html +5 -5
- package/dist/docs/evals.html +3 -3
- package/dist/docs/example-agents/approval-buddy.html +3 -3
- package/dist/docs/example-agents/benny.html +5 -5
- package/dist/docs/example-agents/bugbot.html +3 -3
- package/dist/docs/example-agents/codebase-wiki.html +3 -3
- package/dist/docs/example-agents/codeowners-review.html +3 -3
- package/dist/docs/example-agents/concierge.html +3 -3
- package/dist/docs/example-agents/fsd.html +3 -3
- package/dist/docs/example-agents/index.html +3 -3
- package/dist/docs/example-agents/knowledge-base.html +3 -3
- package/dist/docs/example-agents/oncall.html +6 -6
- package/dist/docs/example-agents/security-reviewer.html +3 -3
- package/dist/docs/example-agents/slack-agent.html +3 -3
- package/dist/docs/example-agents/weather-agent.html +3 -3
- package/dist/docs/guides/agent-to-agent.html +3 -3
- package/dist/docs/guides/cloud-runtime.html +3 -3
- package/dist/docs/guides/github.html +3 -3
- package/dist/docs/guides/human-in-the-loop.html +5 -5
- package/dist/docs/guides/mcp-oauth.html +3 -3
- package/dist/docs/guides/opentelemetry.html +3 -3
- package/dist/docs/guides/slack.html +11 -16
- package/dist/docs/guides/webhooks.html +3 -3
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +3 -3
- package/dist/docs/index.html +3 -3
- package/dist/docs/quickstart.html +3 -3
- package/dist/docs/reference/agent-config.html +3 -3
- package/dist/docs/reference/artifacts.html +3 -3
- package/dist/docs/reference/channels.html +3 -3
- package/dist/docs/reference/cli.html +6 -10
- package/dist/docs/reference/connections.html +3 -3
- package/dist/docs/reference/hooks.html +3 -3
- package/dist/docs/reference/http-api.html +3 -3
- package/dist/docs/reference/instructions.html +3 -3
- package/dist/docs/reference/playground.html +3 -3
- package/dist/docs/reference/project-layout.html +3 -3
- package/dist/docs/reference/prompt.html +3 -3
- package/dist/docs/reference/schedules.html +3 -3
- package/dist/docs/reference/sessions.html +3 -3
- package/dist/docs/reference/skills.html +3 -3
- package/dist/docs/reference/subagents.html +3 -3
- package/dist/docs/reference/tools.html +3 -3
- package/dist/docs/scaffolding-agents.html +3 -3
- package/dist/docs/storage.html +3 -3
- package/dist/docs/templates/triage.html +3 -3
- package/dist/docs/troubleshooting.html +5 -5
- package/dist/internal/cli-ax.js +3 -3
- package/dist/internal/cli-cursor.d.ts +18 -0
- package/dist/internal/cli-cursor.d.ts.map +1 -1
- package/dist/internal/cli-cursor.js +25 -0
- package/dist/internal/cli-slack.d.ts +3 -4
- package/dist/internal/cli-slack.d.ts.map +1 -1
- package/dist/internal/cli-slack.js +126 -322
- package/dist/internal/convert-automation/convert-workflow.js +2 -2
- package/dist/internal/slack-provision-client.d.ts +37 -2
- package/dist/internal/slack-provision-client.d.ts.map +1 -1
- package/dist/internal/slack-provision-client.js +46 -0
- package/dist/playground/assets/{index-Dq_HqyU-.js → index-BKMz70wx.js} +39 -39
- package/dist/playground/assets/index-BmMrulSc.css +1 -0
- package/dist/playground/index.html +2 -2
- package/docs/deployment.md +1 -1
- package/docs/example-agents/benny.md +2 -3
- package/docs/example-agents/oncall.md +4 -5
- package/docs/guides/human-in-the-loop.md +1 -1
- package/docs/guides/slack.md +51 -112
- package/docs/reference/cli.md +14 -37
- package/docs/troubleshooting.md +2 -2
- package/package.json +1 -1
- package/skills/create-agent/SKILL.md +4 -5
- package/skills/setup-slack/SKILL.md +73 -131
- package/src/bin/agent-serve.ts +26 -9
- package/src/channels/slack/init.ts +10 -71
- package/src/channels/slack/manifest.ts +3 -3
- package/src/channels/slack/setup.ts +25 -103
- package/src/channels/slack/types.ts +3 -4
- package/src/internal/cli-ax.ts +3 -3
- package/src/internal/cli-cursor.ts +34 -0
- package/src/internal/cli-slack.ts +136 -389
- package/src/internal/convert-automation/convert-workflow.ts +2 -2
- package/src/internal/slack-provision-client.ts +83 -2
- package/dist/docs/assets/chunks/@localSearchIndexroot.D00d772K.js +0 -1
- package/dist/docs/assets/guides_slack.md.zriQpU_9.lean.js +0 -1
- package/dist/playground/assets/index-Dox74yWJ.css +0 -1
- /package/dist/docs/assets/{deployment.md.Cdp4rTE4.lean.js → deployment.md.B8kW-h7P.lean.js} +0 -0
- /package/dist/docs/assets/{example-agents_benny.md.l7JTmm8X.lean.js → example-agents_benny.md.B-LIDGja.lean.js} +0 -0
- /package/dist/docs/assets/{example-agents_oncall.md.ZE0n6ZFN.lean.js → example-agents_oncall.md.CBmyuAKc.lean.js} +0 -0
- /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
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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
|
|
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
|
-
|
|
19
|
+
tokens, no Slack admin. Live in minutes.
|
|
22
20
|
- **Path B — Dedicated Slack app** (Socket Mode): the agent's own bot
|
|
23
|
-
user
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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
|
|
40
|
-
| Prereq | Cursor Slack integration installed in the workspace and linked to the Cursor account |
|
|
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
|
|
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
|
|
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
|
|
67
|
-
|
|
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
|
|
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
|
|
84
|
-
|
|
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
|
|
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
|
|
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
|
|
157
|
-
agent-sdk slack create --dir
|
|
142
|
+
agent-sdk login
|
|
143
|
+
agent-sdk slack create --dir .
|
|
158
144
|
```
|
|
159
145
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
consent
|
|
163
|
-
|
|
164
|
-
`<
|
|
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
|
-
|
|
203
|
-
|
|
204
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
283
|
-
`message.channels` / `message.groups
|
|
284
|
-
|
|
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
|
|
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
|
|
307
|
-
|
|
308
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
336
|
-
|
|
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 . #
|
|
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
|
```
|
package/src/bin/agent-serve.ts
CHANGED
|
@@ -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 /).
|
|
154
|
-
Enter to restart (re-executes this
|
|
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 (
|
|
275
|
-
|
|
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<
|
|
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
|
|
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
|
|
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
|
|
24
|
-
*
|
|
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
|
|
50
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
2
|
+
* Generate Slack app manifests (dev + prod) for Cursor-managed provision.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
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.
|