@cursor/july 0.1.43 → 0.1.46
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 +5 -3
- package/README.md +3 -1
- package/dist/channels/github/api.d.ts +25 -0
- package/dist/channels/github/api.d.ts.map +1 -1
- package/dist/channels/github/api.js +48 -0
- package/dist/channels/github/cursor-account.d.ts +7 -0
- package/dist/channels/github/cursor-account.d.ts.map +1 -1
- package/dist/channels/github/cursor-account.js +18 -0
- package/dist/channels/github/defaults.d.ts +1 -1
- package/dist/channels/github/defaults.js +1 -1
- package/dist/channels/github/github-channel.d.ts.map +1 -1
- package/dist/channels/github/github-channel.js +15 -7
- package/dist/channels/github/progress.d.ts +6 -5
- package/dist/channels/github/progress.d.ts.map +1 -1
- package/dist/channels/github/progress.js +58 -16
- package/dist/channels/github/state.d.ts +11 -0
- package/dist/channels/github/state.d.ts.map +1 -1
- package/dist/channels/github/state.js +1 -1
- package/dist/channels/github/types.d.ts +11 -3
- package/dist/channels/github/types.d.ts.map +1 -1
- package/dist/channels.d.ts +17 -0
- package/dist/channels.d.ts.map +1 -1
- package/dist/channels.js +31 -0
- package/dist/docs/404.html +2 -2
- package/dist/docs/ab.html +3 -3
- package/dist/docs/assets/{app.DsTLo2j1.js → app.C2NFTb-h.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.B-FxvuoI.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.DoVfutcV.js → VPLocalSearchBox.o1_FJGip.js} +1 -1
- package/dist/docs/assets/chunks/{theme.DtuVtKkc.js → theme.BcGduE7g.js} +2 -2
- package/dist/docs/assets/{guides_github.md.DSg0j9qj.js → guides_github.md.B8QKtIpw.js} +7 -6
- package/dist/docs/assets/{guides_github.md.DSg0j9qj.lean.js → guides_github.md.B8QKtIpw.lean.js} +1 -1
- package/dist/docs/assets/guides_opentelemetry.md.Csn7ZI25.js +27 -0
- package/dist/docs/assets/guides_opentelemetry.md.Csn7ZI25.lean.js +1 -0
- package/dist/docs/assets/index.md.COeoSkcF.js +5 -0
- package/dist/docs/assets/index.md.COeoSkcF.lean.js +1 -0
- package/dist/docs/assets/{quickstart.md.rIbfahJM.js → quickstart.md.DZxBu44y.js} +18 -49
- package/dist/docs/assets/quickstart.md.DZxBu44y.lean.js +1 -0
- package/dist/docs/assets/{reference_agent-config.md.CRmkoxd6.js → reference_agent-config.md.DHkkvcEZ.js} +9 -4
- package/dist/docs/assets/{reference_agent-config.md.CRmkoxd6.lean.js → reference_agent-config.md.DHkkvcEZ.lean.js} +1 -1
- package/dist/docs/assets/{reference_cli.md.DqEqQpGn.js → reference_cli.md.BDmjPPAm.js} +2 -2
- package/dist/docs/assets/{reference_hooks.md.4cbRRIIu.js → reference_hooks.md.DJE5DXcT.js} +1 -1
- package/dist/docs/assets/{reference_tools.md.lSrsTxYJ.js → reference_tools.md.kJfJAP2m.js} +1 -1
- package/dist/docs/assets/{storage.md.DcGSnIxX.js → storage.md.CJYd5YmN.js} +2 -2
- package/dist/docs/assets/{storage.md.DcGSnIxX.lean.js → storage.md.CJYd5YmN.lean.js} +1 -1
- package/dist/docs/building-with-agents.html +3 -3
- package/dist/docs/concepts.html +3 -3
- package/dist/docs/deployment.html +3 -3
- package/dist/docs/evals.html +3 -3
- package/dist/docs/example-agents/approval-buddy.html +3 -3
- package/dist/docs/example-agents/benny.html +3 -3
- 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 +3 -3
- 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 +10 -9
- package/dist/docs/guides/human-in-the-loop.html +3 -3
- package/dist/docs/guides/mcp-oauth.html +3 -3
- package/dist/docs/guides/opentelemetry.html +12 -5
- package/dist/docs/guides/slack.html +3 -3
- 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 +8 -28
- package/dist/docs/quickstart.html +24 -55
- package/dist/docs/reference/agent-config.html +11 -6
- package/dist/docs/reference/artifacts.html +3 -3
- package/dist/docs/reference/channels.html +3 -3
- package/dist/docs/reference/cli.html +6 -6
- package/dist/docs/reference/connections.html +3 -3
- package/dist/docs/reference/hooks.html +5 -5
- 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 +5 -5
- package/dist/docs/scaffolding-agents.html +3 -3
- package/dist/docs/storage.html +5 -5
- package/dist/docs/templates/triage.html +3 -3
- package/dist/docs/troubleshooting.html +3 -3
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/internal/auth.d.ts +4 -0
- package/dist/internal/auth.d.ts.map +1 -1
- package/dist/internal/auth.js +7 -0
- package/dist/internal/cli-ax.js +2 -2
- package/dist/internal/cli-deploy.d.ts.map +1 -1
- package/dist/internal/cli-deploy.js +38 -7
- package/dist/internal/deploy-client.d.ts +8 -0
- package/dist/internal/deploy-client.d.ts.map +1 -1
- package/dist/internal/deploy-client.js +5 -2
- package/dist/internal/discovery.d.ts.map +1 -1
- package/dist/internal/discovery.js +46 -9
- package/dist/internal/durable-session-store.d.ts +35 -23
- package/dist/internal/durable-session-store.d.ts.map +1 -1
- package/dist/internal/durable-session-store.js +71 -26
- package/dist/internal/host-otel.d.ts +25 -0
- package/dist/internal/host-otel.d.ts.map +1 -0
- package/dist/internal/host-otel.js +162 -0
- package/dist/internal/init-project.js +10 -10
- package/dist/internal/ledger-serving.d.ts +135 -67
- package/dist/internal/ledger-serving.d.ts.map +1 -1
- package/dist/internal/ledger-serving.js +326 -107
- package/dist/internal/otel/collector.d.ts +5 -0
- package/dist/internal/otel/collector.d.ts.map +1 -1
- package/dist/internal/otel/collector.js +68 -27
- package/dist/internal/sdk-runner.d.ts +1 -1
- package/dist/internal/sdk-runner.d.ts.map +1 -1
- package/dist/internal/sdk-runner.js +1 -1
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +3 -2
- package/dist/internal/session-engine.d.ts +23 -18
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +83 -32
- package/dist/kv/memory-kv.d.ts +8 -0
- package/dist/kv/memory-kv.d.ts.map +1 -1
- package/dist/kv/memory-kv.js +8 -0
- package/dist/ledger/janitor.d.ts +60 -0
- package/dist/ledger/janitor.d.ts.map +1 -0
- package/dist/ledger/janitor.js +137 -0
- package/dist/ledger/session-ledger.d.ts +132 -43
- package/dist/ledger/session-ledger.d.ts.map +1 -1
- package/dist/ledger/session-ledger.js +282 -50
- package/dist/ledger.d.ts +9 -8
- package/dist/ledger.d.ts.map +1 -1
- package/dist/ledger.js +7 -7
- package/dist/playground/assets/{index-D-DIYQzw.js → index-6wW6SAc4.js} +19 -19
- package/dist/playground/assets/index-CSRYDAFw.css +1 -0
- package/dist/playground/index.html +2 -2
- package/dist/storage-backends/cursor-hosted.d.ts +5 -0
- package/dist/storage-backends/cursor-hosted.d.ts.map +1 -1
- package/dist/storage-backends/cursor-hosted.js +6 -0
- package/dist/types.d.ts +100 -10
- package/dist/types.d.ts.map +1 -1
- package/docs/README.md +33 -106
- package/docs/guides/github.md +23 -18
- package/docs/guides/opentelemetry.md +30 -0
- package/docs/quickstart.md +89 -227
- package/docs/reference/agent-config.md +47 -0
- package/docs/reference/cli.md +2 -2
- package/docs/reference/hooks.md +1 -1
- package/docs/reference/tools.md +5 -4
- package/docs/storage.md +26 -9
- package/package.json +2 -2
- package/skills/otel/SKILL.md +20 -2
- package/src/channels/github/api.ts +122 -0
- package/src/channels/github/cursor-account.ts +23 -0
- package/src/channels/github/defaults.ts +1 -1
- package/src/channels/github/github-channel.ts +14 -1
- package/src/channels/github/progress.ts +84 -19
- package/src/channels/github/state.ts +14 -0
- package/src/channels/github/types.ts +7 -3
- package/src/channels.ts +38 -0
- package/src/index.ts +2 -0
- package/src/internal/auth.ts +10 -0
- package/src/internal/cli-ax.ts +2 -2
- package/src/internal/cli-deploy.ts +58 -3
- package/src/internal/deploy-client.ts +11 -0
- package/src/internal/discovery.ts +49 -0
- package/src/internal/durable-session-store.ts +66 -27
- package/src/internal/host-otel.ts +252 -0
- package/src/internal/init-project.ts +10 -10
- package/src/internal/ledger-serving.ts +439 -148
- package/src/internal/otel/collector.ts +135 -50
- package/src/internal/sdk-runner.ts +6 -0
- package/src/internal/server.ts +7 -2
- package/src/internal/session-engine.ts +127 -39
- package/src/kv/memory-kv.ts +8 -0
- package/src/ledger/janitor.ts +193 -0
- package/src/ledger/session-ledger.ts +372 -68
- package/src/ledger.ts +21 -6
- package/src/storage-backends/cursor-hosted.ts +17 -2
- package/src/types.ts +108 -10
- package/dist/docs/assets/chunks/@localSearchIndexroot.BZx4pmZL.js +0 -1
- package/dist/docs/assets/guides_opentelemetry.md.DmyUwC5R.js +0 -20
- package/dist/docs/assets/guides_opentelemetry.md.DmyUwC5R.lean.js +0 -1
- package/dist/docs/assets/index.md.CMc5FP7E.js +0 -25
- package/dist/docs/assets/index.md.CMc5FP7E.lean.js +0 -1
- package/dist/docs/assets/quickstart.md.rIbfahJM.lean.js +0 -1
- package/dist/playground/assets/index-DQTH622f.css +0 -1
- /package/dist/docs/assets/{reference_cli.md.DqEqQpGn.lean.js → reference_cli.md.BDmjPPAm.lean.js} +0 -0
- /package/dist/docs/assets/{reference_hooks.md.4cbRRIIu.lean.js → reference_hooks.md.DJE5DXcT.lean.js} +0 -0
- /package/dist/docs/assets/{reference_tools.md.lSrsTxYJ.lean.js → reference_tools.md.kJfJAP2m.lean.js} +0 -0
package/docs/guides/github.md
CHANGED
|
@@ -44,12 +44,14 @@ Choose `permissions` by what the agent needs:
|
|
|
44
44
|
| --- | --- |
|
|
45
45
|
| `"read"` | Inspect PRs / issues / statuses only |
|
|
46
46
|
| `"pr-write"` (default) | Comment, review, update PR/issue metadata |
|
|
47
|
-
| `"contents-write"` | Push code, or
|
|
47
|
+
| `"contents-write"` | Push code, or post merge-box checks |
|
|
48
48
|
|
|
49
|
-
`contents-write` is an explicit opt-up.
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
`contents-write` is an explicit opt-up. `progress.commitStatus` posts a
|
|
50
|
+
GitHub check run (`checks:write`). Hosted `cursorAccount` mints that
|
|
51
|
+
permission on `"contents-write"` tokens. Enabling `commitStatus` opts a
|
|
52
|
+
`"pr-write"` channel up to that tier so github-proxy can post the check.
|
|
53
|
+
`"pr-write"` without `commitStatus` is enough for comments and banners.
|
|
54
|
+
Prefer `"pr-write"` unless the agent must push or post a merge-box check.
|
|
53
55
|
|
|
54
56
|
Selected repositories must share one GitHub owner (one App installation).
|
|
55
57
|
Configuration that spans owners fails at startup / mint time.
|
|
@@ -206,7 +208,7 @@ Autofix-style agents need a deterministic merge-box check and a sticky
|
|
|
206
208
|
PR comment that converges when the turn ends. Configure that on the
|
|
207
209
|
channel with `progress.commitStatus` and `progress.banner`. A hook can
|
|
208
210
|
read and write `ctx.host.kv` and `ctx.host.files` after a turn. Use
|
|
209
|
-
that for derived state. Keep GitHub
|
|
211
|
+
that for derived state. Keep GitHub check-run and banner writes on the
|
|
210
212
|
channel.
|
|
211
213
|
|
|
212
214
|
```ts
|
|
@@ -229,10 +231,11 @@ export default githubChannel({
|
|
|
229
231
|
failure: "Autofix failed",
|
|
230
232
|
},
|
|
231
233
|
},
|
|
232
|
-
// commitStatus
|
|
234
|
+
// commitStatus posts a Checks API run. Hosted cursorAccount opts the
|
|
235
|
+
// minted token up to contents-write (checks:write). Banner also works
|
|
236
|
+
// on pr-write without commitStatus.
|
|
233
237
|
cursorAccount: {
|
|
234
238
|
repos: ["owner/repo"],
|
|
235
|
-
permissions: "contents-write",
|
|
236
239
|
},
|
|
237
240
|
onPullRequest: (ctx, pr) =>
|
|
238
241
|
pr.action === "opened" ? { auth: defaultGitHubAuth(ctx) } : null,
|
|
@@ -241,26 +244,28 @@ export default githubChannel({
|
|
|
241
244
|
|
|
242
245
|
Default stream events drive the lifecycle:
|
|
243
246
|
|
|
244
|
-
| Event |
|
|
247
|
+
| Event | Check run | Banner |
|
|
245
248
|
| --- | --- | --- |
|
|
246
|
-
| `turn.started` | `
|
|
247
|
-
| `turn.completed` | `success` | PATCH the same comment |
|
|
248
|
-
| `turn.failed` / `session.failed` | `failure` | PATCH the same comment |
|
|
249
|
+
| `turn.started` | `in_progress` | create (or keep) the sticky comment |
|
|
250
|
+
| `turn.completed` | `completed` / `success` | PATCH the same comment |
|
|
251
|
+
| `turn.failed` / `session.failed` | `completed` / `failure` | PATCH the same comment |
|
|
249
252
|
|
|
250
253
|
Omit `commitStatus` / `banner`, or set them to `false`, to keep today's
|
|
251
254
|
behavior. Reactions still default on; set `reactions: false` when the
|
|
252
255
|
eyes emoji is noise. Descriptions are optional; defaults derive from
|
|
253
|
-
`botName` or the
|
|
256
|
+
`botName` or the check `context`.
|
|
254
257
|
|
|
255
|
-
|
|
258
|
+
The check run posts to `channel.state.headSha`. PR and CI wakes seed and
|
|
256
259
|
refresh it (`refreshState` on continuation). A first wake that is only an
|
|
257
|
-
`issue_comment` has no head SHA in the payload, so
|
|
260
|
+
`issue_comment` has no head SHA in the payload, so the check is skipped until
|
|
258
261
|
a PR/CI wake stores one; the banner still posts. Review-comment wakes
|
|
259
262
|
carry `pull_request.head.sha` when GitHub includes it.
|
|
260
263
|
|
|
261
|
-
The sticky comment id
|
|
262
|
-
record). Each wake also passes `refreshState`
|
|
263
|
-
on continuation without wiping
|
|
264
|
+
The sticky comment id and latest check-run id live on durable
|
|
265
|
+
`GitHubChannelState` (session record). Each wake also passes `refreshState`
|
|
266
|
+
so `headSha` / refs update on continuation without wiping those ids. A later
|
|
267
|
+
turn on the same SHA creates a new check run — GitHub cannot reopen a
|
|
268
|
+
completed run. Persist other derived state
|
|
264
269
|
with `ctx.host.kv` or `ctx.host.files`. `stateRoot` resets on hosted
|
|
265
270
|
replace.
|
|
266
271
|
|
|
@@ -131,6 +131,36 @@ Shared names (same keys as enterprise export):
|
|
|
131
131
|
Agent SDK only (`agent_sdk.*`): agent name, turn id, channel, call id,
|
|
132
132
|
subagent name, session mode, and HTTP duration (`agent_sdk.http.duration`).
|
|
133
133
|
|
|
134
|
+
## How do I emit my own metrics?
|
|
135
|
+
|
|
136
|
+
`ctx.host.otel` is always present on tools, hooks, and channel
|
|
137
|
+
handlers. Counters and histograms no-op when no meter is running.
|
|
138
|
+
`setAttributes` still tags the open session when a collector is
|
|
139
|
+
attached.
|
|
140
|
+
|
|
141
|
+
Prefix metric names with your team or agent. First-party names
|
|
142
|
+
(`cursor.token.usage`, `cursor.tool.calls`, `cursor.cost.usage`,
|
|
143
|
+
`agent_sdk.session.count`, `agent_sdk.turn.count`,
|
|
144
|
+
`agent_sdk.subagent.count`, `agent_sdk.http.duration`) and join keys
|
|
145
|
+
(`cursor.conversation.id`, `agent_sdk.agent`, `agent_sdk.turn_id`,
|
|
146
|
+
`agent_sdk.framework`) are reserved. Custom spans are not on this
|
|
147
|
+
surface.
|
|
148
|
+
|
|
149
|
+
```ts
|
|
150
|
+
ctx.host.otel.setAttributes({
|
|
151
|
+
"abc.ticket_id": "INC-123",
|
|
152
|
+
"abc.queue": "p1",
|
|
153
|
+
});
|
|
154
|
+
ctx.host.otel.increment("abc.ticket.resolved");
|
|
155
|
+
ctx.host.otel.record("abc.approval.duration_ms", 1420, {
|
|
156
|
+
outcome: "approved",
|
|
157
|
+
});
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
A session-bound host (tools and hooks) adds `cursor.conversation.id`
|
|
161
|
+
and `agent_sdk.agent` for you. Tags merge: later `setAttributes` calls
|
|
162
|
+
paint open spans and later first-party metrics.
|
|
163
|
+
|
|
134
164
|
## What stays off the OpenTelemetry wire?
|
|
135
165
|
|
|
136
166
|
User prompts, tool arguments, tool results, and failure messages are
|
package/docs/quickstart.md
CHANGED
|
@@ -1,29 +1,27 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "Build your first PR
|
|
3
|
-
description: "Create an agent that reviews pull requests by complexity, approves
|
|
2
|
+
title: "Build your first PR reviewer"
|
|
3
|
+
description: "Create an agent that reviews pull requests by complexity, approves safe changes, and handles GitHub webhook events."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# Build your first PR
|
|
6
|
+
# Build your first PR reviewer
|
|
7
7
|
|
|
8
|
-
Build
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
and watch a pull request wake it.
|
|
8
|
+
Build a GitHub PR reviewer that classifies changes as `trivial`,
|
|
9
|
+
`moderate`, or `large`, then approves safe changes or requests human
|
|
10
|
+
review. Add GitHub event handling so pull requests can trigger reviews.
|
|
12
11
|
|
|
13
|
-
|
|
14
|
-
typed tools, judgment lives in the model, and every decision is
|
|
15
|
-
inspectable in the playground.
|
|
12
|
+
## Getting started
|
|
16
13
|
|
|
17
|
-
|
|
14
|
+
- **Get started with an agent in Cursor:** follow
|
|
15
|
+
[Scaffold an agent with Cursor](./scaffolding-agents.md) and ask Cursor
|
|
16
|
+
to read [`skills/create-agent/SKILL.md`](../skills/create-agent/SKILL.md).
|
|
17
|
+
- **Get started in the CLI:** continue below.
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
## Prerequisites
|
|
20
20
|
|
|
21
21
|
- Node 22.13 or newer. Bun isn't supported.
|
|
22
|
-
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
sign-in. See [Run the CLI](/#run-the-cli) for other setups, such as a
|
|
26
|
-
monorepo source checkout.
|
|
22
|
+
- Run commands as `agent-sdk <command>`, or use
|
|
23
|
+
`npx @cursor/july <command>` when the CLI isn't on `PATH`. See
|
|
24
|
+
[Run the CLI](/#run-the-cli) for monorepo checkouts and other setups.
|
|
27
25
|
- A Cursor credential for model turns. Sign in once:
|
|
28
26
|
|
|
29
27
|
```bash
|
|
@@ -32,122 +30,33 @@ agent-sdk login
|
|
|
32
30
|
|
|
33
31
|
You can also set `CURSOR_API_KEY` instead of signing in.
|
|
34
32
|
|
|
35
|
-
-
|
|
36
|
-
|
|
37
|
-
automatically. Reading pull requests works on any public repo;
|
|
38
|
-
posting reviews needs write access to the repo you review.
|
|
33
|
+
- Authenticate with `gh auth login` or `GITHUB_TOKEN`. You can read
|
|
34
|
+
public pull requests. Posting reviews requires repository write access.
|
|
39
35
|
|
|
40
|
-
##
|
|
36
|
+
## Create and run the project
|
|
41
37
|
|
|
42
|
-
|
|
43
|
-
there:
|
|
38
|
+
Initialize the project and start the development server:
|
|
44
39
|
|
|
45
40
|
```bash
|
|
46
|
-
npx @cursor/july init ./pr-
|
|
47
|
-
cd pr-
|
|
48
|
-
agent-sdk dev # serve, and print the playground URL
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
Open the playground URL and chat with the scaffold. Then, in a second
|
|
52
|
-
terminal (`dev` keeps running), run one turn from the command line:
|
|
53
|
-
|
|
54
|
-
```bash
|
|
55
|
-
agent-sdk run --dir . --message "Introduce yourself in one sentence."
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
That's the whole loop: files become an agent, `dev` serves it, and
|
|
59
|
-
`run` exercises it. The rest of this page turns that scaffold into a
|
|
60
|
-
real PR approver.
|
|
61
|
-
|
|
62
|
-
## Scaffolding Agents
|
|
63
|
-
|
|
64
|
-
Have Cursor read [`skills/create-agent/SKILL.md`](../skills/create-agent/SKILL.md)
|
|
65
|
-
and describe what you want:
|
|
66
|
-
|
|
67
|
-
> Build me a PR approver for the playground. Start with one tool that
|
|
68
|
-
> inspects a pull request and guide me through the remaining decisions.
|
|
69
|
-
|
|
70
|
-
Cursor asks for missing choices, shows you the plan, then builds and
|
|
71
|
-
verifies the agent. Continue below to do the same by hand.
|
|
72
|
-
|
|
73
|
-
See [Scaffold an agent with Cursor](./scaffolding-agents.md) for the
|
|
74
|
-
full guided workflow.
|
|
75
|
-
|
|
76
|
-
## Create your project
|
|
77
|
-
|
|
78
|
-
Start with the built-in scaffold:
|
|
79
|
-
|
|
80
|
-
```bash
|
|
81
|
-
npx @cursor/july init ./pr-approver
|
|
82
|
-
cd pr-approver
|
|
41
|
+
npx @cursor/july init ./sdk-pr-reviewer
|
|
42
|
+
cd sdk-pr-reviewer
|
|
83
43
|
agent-sdk dev
|
|
84
44
|
```
|
|
85
45
|
|
|
86
|
-
|
|
87
|
-
folders (each with a `.gitkeep`) so you can drop tools, channels, and
|
|
88
|
-
evals in place:
|
|
89
|
-
|
|
90
|
-
```text
|
|
91
|
-
pr-approver/
|
|
92
|
-
├── agent/
|
|
93
|
-
│ ├── agent.ts
|
|
94
|
-
│ ├── instructions.md
|
|
95
|
-
│ ├── tools/
|
|
96
|
-
│ │ └── echo.ts
|
|
97
|
-
│ ├── skills/
|
|
98
|
-
│ ├── mcp-connections/
|
|
99
|
-
│ ├── subagents/
|
|
100
|
-
│ ├── channels/
|
|
101
|
-
│ ├── hooks/
|
|
102
|
-
│ │ └── memory.ts
|
|
103
|
-
│ ├── ab/
|
|
104
|
-
│ ├── schedules/
|
|
105
|
-
│ ├── sandbox/workspace/
|
|
106
|
-
│ └── lib/
|
|
107
|
-
├── evals/
|
|
108
|
-
├── package.json
|
|
109
|
-
└── tsconfig.json
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
`agent.ts` holds the model and runtime settings. `instructions.md` is
|
|
113
|
-
the always-on system prompt, and the scaffold's version includes a
|
|
114
|
-
memory section that tells the agent how to consult its journal. Each
|
|
115
|
-
file under `agent/tools/` becomes a tool, and `agent/hooks/memory.ts`
|
|
116
|
-
journals every turn so future sessions can recall past work (delete it
|
|
117
|
-
to opt out). `tsconfig.json` type-checks the project (`npm run check`);
|
|
118
|
-
the framework runs your TypeScript directly, so nothing compiles.
|
|
119
|
-
|
|
120
|
-
`agent-sdk dev` blocks until you stop it. Keep it running and open a
|
|
121
|
-
second terminal for every other command on this page, starting with
|
|
122
|
-
these checks:
|
|
46
|
+
Keep `agent-sdk dev` running. In a second terminal, run:
|
|
123
47
|
|
|
124
48
|
```bash
|
|
125
|
-
agent-sdk
|
|
126
|
-
agent-sdk info --dir .
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
These commands inspect the project without starting a model turn.
|
|
130
|
-
|
|
131
|
-
## Run your agent
|
|
132
|
-
|
|
133
|
-
The scaffold already works. Run one turn from the terminal:
|
|
134
|
-
|
|
135
|
-
```bash
|
|
136
|
-
agent-sdk run --dir . \
|
|
137
|
-
--message "Introduce yourself in one sentence."
|
|
49
|
+
agent-sdk run --dir . --message "Introduce yourself in one sentence."
|
|
138
50
|
```
|
|
139
51
|
|
|
140
|
-
|
|
141
|
-
reply. It prints a JSON trajectory with the response, tool calls, and
|
|
142
|
-
token usage. It also writes an NDJSON trace under
|
|
143
|
-
`.agent-serve/traces/`.
|
|
52
|
+
Confirm the agent replies.
|
|
144
53
|
|
|
145
|
-
##
|
|
54
|
+
## Add review instructions
|
|
146
55
|
|
|
147
56
|
Replace `agent/instructions.md`:
|
|
148
57
|
|
|
149
58
|
```md
|
|
150
|
-
# PR
|
|
59
|
+
# PR reviewer
|
|
151
60
|
|
|
152
61
|
You review GitHub pull requests. Be specific and brief.
|
|
153
62
|
|
|
@@ -178,9 +87,6 @@ rm agent/tools/echo.ts
|
|
|
178
87
|
|
|
179
88
|
## Add a shared helper
|
|
180
89
|
|
|
181
|
-
Both tools need to split a PR URL into its parts. Shared code lives in
|
|
182
|
-
`agent/lib/`, which the framework never loads as tools.
|
|
183
|
-
|
|
184
90
|
Create `agent/lib/github.ts`:
|
|
185
91
|
|
|
186
92
|
```ts
|
|
@@ -213,7 +119,7 @@ import { parsePullUrl } from "../lib/github.js";
|
|
|
213
119
|
|
|
214
120
|
export type Complexity = "trivial" | "moderate" | "large";
|
|
215
121
|
|
|
216
|
-
/**
|
|
122
|
+
/** Rate complexity from fixed line and file-count thresholds. */
|
|
217
123
|
function rateComplexity(linesChanged: number, changedFiles: number): Complexity {
|
|
218
124
|
if (linesChanged <= 25 && changedFiles <= 2) {
|
|
219
125
|
return "trivial";
|
|
@@ -280,58 +186,30 @@ export default defineTool({
|
|
|
280
186
|
});
|
|
281
187
|
```
|
|
282
188
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
- `description` tells the model when to call it.
|
|
286
|
-
- `inputSchema` defines and validates the arguments.
|
|
287
|
-
- `execute` runs on the server and returns data to the model.
|
|
189
|
+
## Verify complexity classification
|
|
288
190
|
|
|
289
|
-
|
|
290
|
-
and it lives in code: the model never decides what counts as a big
|
|
291
|
-
change. And `ctx.host.github` is the shared host GitHub client, so the
|
|
292
|
-
tool inherits whatever credential the host has (a token, `gh auth`, or
|
|
293
|
-
a GitHub App) without parsing any of it.
|
|
294
|
-
|
|
295
|
-
## Try the inspect tool
|
|
296
|
-
|
|
297
|
-
Call the tool directly first, on a real merged pull request:
|
|
191
|
+
Run `inspect_pr` against a small pull request:
|
|
298
192
|
|
|
299
193
|
```bash
|
|
300
194
|
agent-sdk call inspect_pr --dir . \
|
|
301
195
|
--input '{"prUrl":"https://github.com/facebook/react/pull/35623"}'
|
|
302
196
|
```
|
|
303
197
|
|
|
304
|
-
|
|
305
|
-
This PR is a one-character typo fix, so the result comes back rated
|
|
306
|
-
`trivial` with the whole patch inline:
|
|
307
|
-
|
|
308
|
-
```json
|
|
309
|
-
{
|
|
310
|
-
"title": "Fix typo: accomodate -> accommodate",
|
|
311
|
-
"additions": 1,
|
|
312
|
-
"deletions": 1,
|
|
313
|
-
"changedFiles": 1,
|
|
314
|
-
"complexity": "trivial",
|
|
315
|
-
"files": [{ "path": "compiler/packages/...", "patch": "@@ -1315,7 ..." }]
|
|
316
|
-
}
|
|
317
|
-
```
|
|
198
|
+
Confirm the result contains `"complexity": "trivial"`.
|
|
318
199
|
|
|
319
|
-
|
|
320
|
-
1,027 additions across 26 files.
|
|
200
|
+
Run it against a large pull request:
|
|
321
201
|
|
|
322
202
|
```bash
|
|
323
203
|
agent-sdk call inspect_pr --dir . \
|
|
324
204
|
--input '{"prUrl":"https://github.com/facebook/react/pull/25229"}'
|
|
325
205
|
```
|
|
326
206
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
any model turn spends a token on it.
|
|
207
|
+
Confirm the result contains `"complexity": "large"` and no `patch`
|
|
208
|
+
fields.
|
|
330
209
|
|
|
331
210
|
## Add the review tool
|
|
332
211
|
|
|
333
|
-
|
|
334
|
-
`agent/tools/submit_review.ts`:
|
|
212
|
+
Create `agent/tools/submit_review.ts` to post each verdict:
|
|
335
213
|
|
|
336
214
|
```ts
|
|
337
215
|
import { defineTool } from "@cursor/july/tools";
|
|
@@ -354,10 +232,10 @@ export default defineTool({
|
|
|
354
232
|
const { owner, repo, number } = parsePullUrl(prUrl);
|
|
355
233
|
const review =
|
|
356
234
|
verdict === "approve"
|
|
357
|
-
? { event: "APPROVE" as const, body: `PR
|
|
235
|
+
? { event: "APPROVE" as const, body: `PR reviewer: ${summary}` }
|
|
358
236
|
: {
|
|
359
237
|
event: "COMMENT" as const,
|
|
360
|
-
body: `PR
|
|
238
|
+
body: `PR reviewer: this change needs a human review. ${summary}`,
|
|
361
239
|
};
|
|
362
240
|
|
|
363
241
|
const octokit = await ctx.host.github.getOctokit();
|
|
@@ -373,47 +251,24 @@ export default defineTool({
|
|
|
373
251
|
});
|
|
374
252
|
```
|
|
375
253
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
test it. Your credential needs write access to the repo it reviews,
|
|
379
|
-
and GitHub rejects approving your own pull request, so hand the agent
|
|
380
|
-
a teammate's PR rather than one you authored. When a post fails, the
|
|
381
|
-
tool call reports the GitHub error to the model and the turn keeps
|
|
382
|
-
going.
|
|
383
|
-
|
|
384
|
-
Want a person to sign off before the review lands? Set
|
|
385
|
-
`needsApproval: true` on the tool and the call parks until someone
|
|
386
|
-
approves it from the playground or Slack.
|
|
387
|
-
[Human-in-the-loop approvals](./guides/human-in-the-loop.md) shows the
|
|
388
|
-
flow.
|
|
254
|
+
Use a GitHub credential with write access and a pull request you didn't
|
|
255
|
+
author.
|
|
389
256
|
|
|
390
257
|
## Review a pull request
|
|
391
258
|
|
|
392
|
-
|
|
393
|
-
teammate's open PR is the right pick: write access to the repo, and
|
|
394
|
-
not authored by you.
|
|
259
|
+
Review an open pull request:
|
|
395
260
|
|
|
396
261
|
```bash
|
|
397
262
|
agent-sdk run --dir . \
|
|
398
263
|
--message "Review https://github.com/acme/checkout/pull/42"
|
|
399
264
|
```
|
|
400
265
|
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
APPROVE review on the spot, with a one-line summary of what it checked.
|
|
404
|
-
A large one gets a comment asking for a human review, pointing at the
|
|
405
|
-
files a reviewer should start with. Same instructions, different
|
|
406
|
-
behavior, because the policy in the tool decided how much the model got
|
|
407
|
-
to see.
|
|
408
|
-
|
|
409
|
-
Open the PR on GitHub: the review is on the timeline, posted by
|
|
410
|
-
whatever identity your credential belongs to.
|
|
266
|
+
Confirm `inspect_pr` runs before `submit_review`, then verify the review
|
|
267
|
+
on GitHub.
|
|
411
268
|
|
|
412
|
-
##
|
|
269
|
+
## Trigger reviews from GitHub
|
|
413
270
|
|
|
414
|
-
|
|
415
|
-
GitHub channel so pull requests wake it. Create
|
|
416
|
-
`agent/channels/github.ts`:
|
|
271
|
+
Create `agent/channels/github.ts`:
|
|
417
272
|
|
|
418
273
|
```ts
|
|
419
274
|
import {
|
|
@@ -424,10 +279,8 @@ import {
|
|
|
424
279
|
const REVIEW_ACTIONS = new Set(["opened", "reopened", "ready_for_review"]);
|
|
425
280
|
|
|
426
281
|
export default githubChannel({
|
|
427
|
-
botName: "pr-
|
|
282
|
+
botName: "sdk-pr-reviewer",
|
|
428
283
|
webhookEvents: ["pull_request"],
|
|
429
|
-
// submit_review owns every GitHub write. Without these flags the channel
|
|
430
|
-
// also posts chat replies and reactions to the PR when the token allows it.
|
|
431
284
|
deliverReplies: false,
|
|
432
285
|
progress: { reactions: false },
|
|
433
286
|
onPullRequest: (ctx, pr) => {
|
|
@@ -446,57 +299,66 @@ export default githubChannel({
|
|
|
446
299
|
});
|
|
447
300
|
```
|
|
448
301
|
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
start a model turn; everything else returns `null` and is skipped.
|
|
452
|
-
|
|
453
|
-
Serve the agent, then replay a real PR at it from a second terminal.
|
|
454
|
-
`replay` reads the PR through `gh api`, synthesizes a GitHub-shaped
|
|
455
|
-
webhook delivery, and POSTs it to the channel. No repo admin, no
|
|
456
|
-
tunnel:
|
|
302
|
+
Keep `agent-sdk dev` running. In a second terminal, replay an open pull
|
|
303
|
+
request. Pull access is enough; repo admin isn't required:
|
|
457
304
|
|
|
458
305
|
```bash
|
|
459
|
-
agent-sdk dev
|
|
460
|
-
# second terminal:
|
|
461
306
|
agent-sdk github replay https://github.com/acme/checkout/pull/42 \
|
|
462
307
|
--dir . --action opened
|
|
463
308
|
```
|
|
464
309
|
|
|
465
|
-
|
|
310
|
+
Open the playground and confirm `Review acme/checkout#42` contains the
|
|
311
|
+
trigger, both tool calls, and the verdict.
|
|
466
312
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
313
|
+
## Run options
|
|
314
|
+
|
|
315
|
+
1. **CLI message**
|
|
316
|
+
|
|
317
|
+
```bash
|
|
318
|
+
agent-sdk run --dir . --message "Review https://github.com/acme/checkout/pull/42"
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
2. **Local replay**
|
|
322
|
+
|
|
323
|
+
```bash
|
|
324
|
+
agent-sdk github replay https://github.com/acme/checkout/pull/42 \
|
|
325
|
+
--dir . --action opened
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
3. **Forward or `--cursor-events`**
|
|
329
|
+
|
|
330
|
+
Pull Cursor events:
|
|
331
|
+
|
|
332
|
+
```bash
|
|
333
|
+
agent-sdk serve --dir . --cursor-events --repo owner/repo
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
Forward GitHub webhooks:
|
|
337
|
+
|
|
338
|
+
```bash
|
|
339
|
+
agent-sdk github forward --dir .
|
|
340
|
+
```
|
|
471
341
|
|
|
472
|
-
|
|
473
|
-
Replay the same PR again and the channel resumes that PR's session
|
|
474
|
-
instead of starting a new one: each pull request keeps one running
|
|
475
|
-
conversation.
|
|
342
|
+
Keep the local `dev` or `serve` process running.
|
|
476
343
|
|
|
477
|
-
|
|
344
|
+
4. **Hosted deployment**
|
|
478
345
|
|
|
479
|
-
|
|
480
|
-
webhook session is in the session list, titled
|
|
481
|
-
`Review acme/checkout#42`, with the trigger message, both tool calls,
|
|
482
|
-
and the verdict laid out. Start a new chat there and ask for another
|
|
483
|
-
review to watch a turn stream live.
|
|
346
|
+
Deploy once, set the GitHub App secrets, then redeploy:
|
|
484
347
|
|
|
485
|
-
|
|
348
|
+
```bash
|
|
349
|
+
agent-sdk deploy
|
|
350
|
+
agent-sdk secrets set sdk-pr-reviewer GITHUB_APP_ID GITHUB_APP_PRIVATE_KEY
|
|
351
|
+
agent-sdk deploy
|
|
352
|
+
```
|
|
486
353
|
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
connected to Cursor with no public URL, or run
|
|
490
|
-
`agent-sdk github forward` to relay webhooks to your dev server. The
|
|
491
|
-
[GitHub guide](./guides/github.md) compares the options. In production,
|
|
492
|
-
give the host GitHub App credentials so reviews post as your app's bot
|
|
493
|
-
identity instead of a personal account.
|
|
354
|
+
See [GitHub](./guides/github.md) for local event delivery and
|
|
355
|
+
[Deployment](./deployment.md) for hosting.
|
|
494
356
|
|
|
495
357
|
## Where to go next
|
|
496
358
|
|
|
497
|
-
- [`examples/approval-buddy`](../examples/approval-buddy/):
|
|
498
|
-
|
|
499
|
-
|
|
359
|
+
- [`examples/approval-buddy`](../examples/approval-buddy/): an example
|
|
360
|
+
with commit statuses, review subagents, and a deterministic stamp
|
|
361
|
+
policy
|
|
500
362
|
- [Evals](./evals.md): freeze these two PRs as regression checks so
|
|
501
363
|
prompt changes can't flip a verdict
|
|
502
364
|
- [Tools](./reference/tools.md): more on typed tools, approvals, and
|
|
@@ -44,6 +44,7 @@ export default defineAgent({
|
|
|
44
44
|
| `hosting` | `{ egressDomains?, secretNames? }` | Managed-hosting declarations read by `agent-sdk deploy`: the pod's egress allowlist and the secret names the agent expects. Ignored by local serving. |
|
|
45
45
|
| `concurrency` | `{ maxRunningTurns? }` | Engine-wide turn admission limit. See [Concurrency](#concurrency). |
|
|
46
46
|
| `builtinTools` | `{ reminders? }` | Framework-provided model-facing tools, opted in per capability. See [Built-in tools](#built-in-tools). |
|
|
47
|
+
| `tools` | `ToolName[]` | Allowlist of built-in harness tools offered to the model. Unset = the model's full standard toolset. See [Allowlist built-in harness tools](#allowlist-built-in-harness-tools). |
|
|
47
48
|
|
|
48
49
|
## Choose a model
|
|
49
50
|
|
|
@@ -120,6 +121,52 @@ outside it (or runs with `--state-root` under `/tmp`). An agent that
|
|
|
120
121
|
*needs* a specific checkout's skills and rules points `cwd` inside that
|
|
121
122
|
checkout.
|
|
122
123
|
|
|
124
|
+
## Allowlist built-in harness tools
|
|
125
|
+
|
|
126
|
+
Use `tools` to limit which built-in Cursor harness tools the model can
|
|
127
|
+
call. Omit it to keep the standard toolset. When you set it, the model
|
|
128
|
+
gets only the tools you list. An empty list disables all native
|
|
129
|
+
built-in tools. Because this field is an allowlist, new platform tools
|
|
130
|
+
stay disabled until you add them.
|
|
131
|
+
|
|
132
|
+
```ts
|
|
133
|
+
export default defineAgent({
|
|
134
|
+
model: "composer-2.5",
|
|
135
|
+
// Read-only triage agent: search and read only.
|
|
136
|
+
// No shell, no edits, no subagents.
|
|
137
|
+
tools: ["read", "grep", "glob", "ls"],
|
|
138
|
+
});
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Agent Serve always adds `"mcp"` to a configured allowlist. Authored
|
|
142
|
+
server tools in `agent/tools/` use MCP to reach the model. MCP can also
|
|
143
|
+
expose declared connections and servers from the harness directory's
|
|
144
|
+
ambient `.cursor` config. To exclude a checkout's MCP servers, point
|
|
145
|
+
`local.cwd` outside the checkout. See [Local cwd](#local-cwd).
|
|
146
|
+
`local.sandbox` makes MCP tool calls fail closed.
|
|
147
|
+
|
|
148
|
+
Use the SDK's public tool names, including `"shell"`, `"read"`,
|
|
149
|
+
`"edit"`, `"grep"`, `"glob"`, `"ls"`, and `"task"`. Unknown names
|
|
150
|
+
fail the turn with a `ConfigurationError`.
|
|
151
|
+
|
|
152
|
+
Two names have broader effects:
|
|
153
|
+
|
|
154
|
+
- `"shell"` also grants shell input. Tools with
|
|
155
|
+
`execution: "agent"` need it to run their scripts. Discovery warns
|
|
156
|
+
when your allowlist would prevent those tools from running.
|
|
157
|
+
- `"task"` lets the root agent start subagents. Each subagent keeps
|
|
158
|
+
its own curated toolset.
|
|
159
|
+
|
|
160
|
+
Tool allowlists work only with the local runtime. A
|
|
161
|
+
`runtime: "cloud"` agent that sets `tools` fails at serve startup.
|
|
162
|
+
Agent Serve also refuses per-send cloud sessions from a hybrid agent
|
|
163
|
+
with an allowlist. It won't run those sessions with unrestricted tool
|
|
164
|
+
access.
|
|
165
|
+
|
|
166
|
+
The allowlist controls which tools the model can call. It does not
|
|
167
|
+
isolate the serve host. For agents that process untrusted input, also
|
|
168
|
+
set `local: { sandbox: true }`.
|
|
169
|
+
|
|
123
170
|
## The `cloud` block
|
|
124
171
|
|
|
125
172
|
Cloud agent defaults forwarded to the Cursor SDK: `repos` (each
|
package/docs/reference/cli.md
CHANGED
|
@@ -141,8 +141,8 @@ agent folder as a positional path, or run it from inside the project:
|
|
|
141
141
|
|
|
142
142
|
```bash
|
|
143
143
|
agent-sdk dev
|
|
144
|
-
agent-sdk dev ./pr-
|
|
145
|
-
agent-sdk dev ./pr-
|
|
144
|
+
agent-sdk dev ./sdk-pr-reviewer
|
|
145
|
+
agent-sdk dev ./sdk-pr-reviewer --port 3000
|
|
146
146
|
```
|
|
147
147
|
|
|
148
148
|
`dev` accepts the same flags as [`serve`](#serve). You can use `--dir`
|
package/docs/reference/hooks.md
CHANGED
|
@@ -67,7 +67,7 @@ All of them consume the same stream, for different jobs:
|
|
|
67
67
|
| Can affect the run | no | yes, it owns the surface | n/a | yes through arm instructions or `session.abs`; collection is observe-only |
|
|
68
68
|
| Authored at | `agent/hooks/*.ts` | channel config | `evals/**/*.eval.ts` | [`agent/ab.ts` or `agent/ab/*.ts`](../ab.md) |
|
|
69
69
|
|
|
70
|
-
For GitHub
|
|
70
|
+
For GitHub merge-box checks and sticky PR banners, use
|
|
71
71
|
`githubChannel({ progress: { commitStatus, banner } })` from
|
|
72
72
|
`@cursor/july/channels/github`. That is the supported Autofix-style
|
|
73
73
|
path. See [GitHub: Show PR progress](../guides/github.md#show-pr-progress).
|
package/docs/reference/tools.md
CHANGED
|
@@ -82,10 +82,11 @@ export default defineTool({
|
|
|
82
82
|
`ctx.host` carries the shared host services: `host.mcp` (authored MCP
|
|
83
83
|
connections: `names()`, `listTools(name)`, `callTool(name, tool, args)`),
|
|
84
84
|
`host.github` and `host.slack` (shared platform clients), `host.kv` and
|
|
85
|
-
`host.files` (durable [storage](../storage.md)), `host.
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
85
|
+
`host.files` (durable [storage](../storage.md)), `host.otel` (custom
|
|
86
|
+
metrics and session tags; see [OpenTelemetry](../guides/opentelemetry.md)),
|
|
87
|
+
`host.reminders` (per-session wakes, when attached), `host.evals`
|
|
88
|
+
(playground eval batches, when attached), and `host.slackNudges`
|
|
89
|
+
(Slack ask-dedupe helpers).
|
|
89
90
|
|
|
90
91
|
### Return values
|
|
91
92
|
|