@cursor/july 0.1.19 → 0.1.21

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 (217) hide show
  1. package/AGENTS.md +10 -0
  2. package/dist/bin/agent-serve.js +0 -0
  3. package/dist/channels/github/instrument.d.ts +20 -0
  4. package/dist/channels/github/instrument.d.ts.map +1 -0
  5. package/dist/channels/slack/api.d.ts +2 -0
  6. package/dist/channels/slack/api.d.ts.map +1 -1
  7. package/dist/channels/slack/api.js +3 -0
  8. package/dist/channels/slack/bot-mentions.d.ts +106 -0
  9. package/dist/channels/slack/bot-mentions.d.ts.map +1 -0
  10. package/dist/channels/slack/bot-mentions.js +243 -0
  11. package/dist/channels/slack/dispatch.d.ts +6 -0
  12. package/dist/channels/slack/dispatch.d.ts.map +1 -1
  13. package/dist/channels/slack/dispatch.js +24 -3
  14. package/dist/channels/slack/inbound.d.ts +10 -1
  15. package/dist/channels/slack/inbound.d.ts.map +1 -1
  16. package/dist/channels/slack/inbound.js +12 -4
  17. package/dist/channels/slack/index.d.ts +1 -0
  18. package/dist/channels/slack/index.d.ts.map +1 -1
  19. package/dist/channels/slack/index.js +1 -0
  20. package/dist/channels/slack/slack-channel.d.ts.map +1 -1
  21. package/dist/channels/slack/slack-channel.js +61 -22
  22. package/dist/channels/slack/types.d.ts +58 -0
  23. package/dist/channels/slack/types.d.ts.map +1 -1
  24. package/dist/docs/404.html +1 -1
  25. package/dist/docs/ab.html +2 -2
  26. package/dist/docs/assets/{app.CrsWMchO.js → app.jDxLzWv4.js} +1 -1
  27. package/dist/docs/assets/chunks/@localSearchIndexroot.DoJHJjqF.js +1 -0
  28. package/dist/docs/assets/chunks/{VPLocalSearchBox.D1JqzSh8.js → VPLocalSearchBox.Y6bDR1-a.js} +1 -1
  29. package/dist/docs/assets/chunks/{theme.DaBvZYwl.js → theme.CLazCWlJ.js} +2 -2
  30. package/dist/docs/building-with-agents.html +2 -2
  31. package/dist/docs/concepts.html +2 -2
  32. package/dist/docs/deployment.html +2 -2
  33. package/dist/docs/evals.html +2 -2
  34. package/dist/docs/example-agents/approval-buddy.html +2 -2
  35. package/dist/docs/example-agents/benny.html +2 -2
  36. package/dist/docs/example-agents/bugbot.html +2 -2
  37. package/dist/docs/example-agents/codebase-wiki.html +2 -2
  38. package/dist/docs/example-agents/codeowners-review.html +2 -2
  39. package/dist/docs/example-agents/concierge.html +2 -2
  40. package/dist/docs/example-agents/fsd.html +2 -2
  41. package/dist/docs/example-agents/index.html +2 -2
  42. package/dist/docs/example-agents/knowledge-base.html +2 -2
  43. package/dist/docs/example-agents/oncall.html +2 -2
  44. package/dist/docs/example-agents/security-reviewer.html +2 -2
  45. package/dist/docs/example-agents/slack-agent.html +2 -2
  46. package/dist/docs/example-agents/weather-agent.html +2 -2
  47. package/dist/docs/guides/agent-to-agent.html +2 -2
  48. package/dist/docs/guides/cloud-runtime.html +2 -2
  49. package/dist/docs/guides/github.html +2 -2
  50. package/dist/docs/guides/human-in-the-loop.html +2 -2
  51. package/dist/docs/guides/mcp-oauth.html +2 -2
  52. package/dist/docs/guides/slack.html +2 -2
  53. package/dist/docs/guides/webhooks.html +2 -2
  54. package/dist/docs/hillclimbing.html +2 -2
  55. package/dist/docs/index.html +2 -2
  56. package/dist/docs/quickstart.html +2 -2
  57. package/dist/docs/reference/agent-config.html +2 -2
  58. package/dist/docs/reference/channels.html +2 -2
  59. package/dist/docs/reference/cli.html +2 -2
  60. package/dist/docs/reference/connections.html +2 -2
  61. package/dist/docs/reference/hooks.html +2 -2
  62. package/dist/docs/reference/http-api.html +2 -2
  63. package/dist/docs/reference/instructions.html +2 -2
  64. package/dist/docs/reference/playground.html +2 -2
  65. package/dist/docs/reference/project-layout.html +2 -2
  66. package/dist/docs/reference/prompt.html +2 -2
  67. package/dist/docs/reference/schedules.html +2 -2
  68. package/dist/docs/reference/sessions.html +2 -2
  69. package/dist/docs/reference/skills.html +2 -2
  70. package/dist/docs/reference/subagents.html +2 -2
  71. package/dist/docs/reference/tools.html +2 -2
  72. package/dist/docs/scaffolding-agents.html +2 -2
  73. package/dist/docs/storage.html +2 -2
  74. package/dist/docs/troubleshooting.html +2 -2
  75. package/dist/internal/json-dir-store.d.ts +32 -0
  76. package/dist/internal/json-dir-store.d.ts.map +1 -0
  77. package/dist/internal/json-dir-store.js +100 -0
  78. package/dist/internal/resolved-connections.d.ts +1 -1
  79. package/dist/internal/resolved-connections.d.ts.map +1 -1
  80. package/dist/internal/resolved-connections.js +10 -0
  81. package/dist/internal/session-engine.d.ts +4 -1
  82. package/dist/internal/session-engine.d.ts.map +1 -1
  83. package/dist/internal/session-engine.js +13 -2
  84. package/dist/playground/assets/index-CjOQ4hN9.css +1 -0
  85. package/dist/playground/assets/{index-C2SU2xV5.js → index-dshZQJCp.js} +46 -46
  86. package/dist/playground/index.html +2 -2
  87. package/dist/types.d.ts +7 -0
  88. package/dist/types.d.ts.map +1 -1
  89. package/dist/types.js +9 -0
  90. package/package.json +25 -25
  91. package/skills/create-agent/SKILL.md +36 -4
  92. package/skills/evals/SKILL.md +3 -0
  93. package/skills/framework-map/SKILL.md +14 -0
  94. package/skills/github/SKILL.md +6 -1
  95. package/skills/hillclimb/SKILL.md +28 -7
  96. package/src/bin/agent-serve.version.test.ts +62 -0
  97. package/src/channels/github/api.test.ts +64 -0
  98. package/src/channels/github/auth.test.ts +105 -0
  99. package/src/channels/github/cursor-account.test.ts +204 -0
  100. package/src/channels/github/forward.test.ts +457 -0
  101. package/src/channels/github/github.test.ts +937 -0
  102. package/src/channels/github/replay.test.ts +179 -0
  103. package/src/channels/slack/api.post-message.test.ts +148 -0
  104. package/src/channels/slack/api.ts +5 -0
  105. package/src/channels/slack/approvals.test.ts +328 -0
  106. package/src/channels/slack/block-actions.test.ts +452 -0
  107. package/src/channels/slack/bot-mentions.test.ts +217 -0
  108. package/src/channels/slack/bot-mentions.ts +315 -0
  109. package/src/channels/slack/channel-watch.test.ts +363 -0
  110. package/src/channels/slack/cursor-account.test.ts +253 -0
  111. package/src/channels/slack/defaults.final-post.test.ts +182 -0
  112. package/src/channels/slack/dispatch.test.ts +795 -0
  113. package/src/channels/slack/dispatch.ts +27 -1
  114. package/src/channels/slack/eval-directive.test.ts +273 -0
  115. package/src/channels/slack/inbound.ts +25 -4
  116. package/src/channels/slack/index.ts +1 -0
  117. package/src/channels/slack/message-body.test.ts +54 -0
  118. package/src/channels/slack/nudge-store.test.ts +143 -0
  119. package/src/channels/slack/slack-channel.ts +66 -8
  120. package/src/channels/slack/slack.test.ts +391 -0
  121. package/src/channels/slack/stop.test.ts +23 -0
  122. package/src/channels/slack/thread-context.test.ts +202 -0
  123. package/src/channels/slack/types.ts +60 -0
  124. package/src/evals/assertions.test.ts +580 -0
  125. package/src/evals/expect.test.ts +144 -0
  126. package/src/evals/judge.test.ts +181 -0
  127. package/src/evals/loaders.test.ts +132 -0
  128. package/src/evals/matchers.test.ts +95 -0
  129. package/src/evals/reporters.test.ts +303 -0
  130. package/src/evals/run-facts.test.ts +259 -0
  131. package/src/internal/ab-snapshot.test.ts +325 -0
  132. package/src/internal/approval-gate.test.ts +49 -0
  133. package/src/internal/approvals.integration.test.ts +383 -0
  134. package/src/internal/authored-loaders.test.ts +31 -0
  135. package/src/internal/builtin-tools/reminders.test.ts +201 -0
  136. package/src/internal/channel-route-schema.test.ts +294 -0
  137. package/src/internal/chat-attach.test.ts +262 -0
  138. package/src/internal/cli-deploy.test.ts +1991 -0
  139. package/src/internal/cli-mcp.test.ts +789 -0
  140. package/src/internal/cli-skills.test.ts +133 -0
  141. package/src/internal/cli-slack.test.ts +1647 -0
  142. package/src/internal/cloud-merge.test.ts +74 -0
  143. package/src/internal/cron.test.ts +22 -0
  144. package/src/internal/cursor/account-mcp.test.ts +807 -0
  145. package/src/internal/cursor/backend-client.test.ts +591 -0
  146. package/src/internal/cursor/credentials.test.ts +351 -0
  147. package/src/internal/cursor/github-credentials.test.ts +136 -0
  148. package/src/internal/cursor-account-mcp-auth.test.ts +310 -0
  149. package/src/internal/cursor-account.integration.test.ts +441 -0
  150. package/src/internal/cursor-event-relay.test.ts +746 -0
  151. package/src/internal/cursor-github-credentials.integration.test.ts +271 -0
  152. package/src/internal/cursor-slack-relay.test.ts +525 -0
  153. package/src/internal/deploy-source.test.ts +111 -0
  154. package/src/internal/discovery.builtin-tools.test.ts +94 -0
  155. package/src/internal/discovery.concurrency.test.ts +60 -0
  156. package/src/internal/discovery.cursor-account.test.ts +133 -0
  157. package/src/internal/discovery.cwd.test.ts +83 -0
  158. package/src/internal/discovery.hosting.test.ts +80 -0
  159. package/src/internal/discovery.identity.test.ts +44 -0
  160. package/src/internal/docs-site.test.ts +66 -0
  161. package/src/internal/duration.test.ts +29 -0
  162. package/src/internal/eval-judge-model.test.ts +187 -0
  163. package/src/internal/eval-run-store.cancel.test.ts +142 -0
  164. package/src/internal/eval-run-store.storage.test.ts +211 -0
  165. package/src/internal/eval-runner.http.test.ts +403 -0
  166. package/src/internal/eval-runner.run.test.ts +928 -0
  167. package/src/internal/evals-client.test.ts +307 -0
  168. package/src/internal/event-mapper.test.ts +243 -0
  169. package/src/internal/github-fanout.test.ts +213 -0
  170. package/src/internal/handleAgentServeTrigger.test.ts +179 -0
  171. package/src/internal/host-kv.test.ts +82 -0
  172. package/src/internal/host-platforms.test.ts +126 -0
  173. package/src/internal/http-channel.test.ts +402 -0
  174. package/src/internal/init-project.test.ts +269 -0
  175. package/src/internal/install-cursor-skills.test.ts +262 -0
  176. package/src/internal/local-env.test.ts +100 -0
  177. package/src/internal/log-ring.test.ts +31 -0
  178. package/src/internal/logs-client.test.ts +350 -0
  179. package/src/internal/mcp-endpoint.test.ts +436 -0
  180. package/src/internal/mcp-host.test.ts +298 -0
  181. package/src/internal/mcp-oauth.test.ts +148 -0
  182. package/src/internal/net.test.ts +17 -0
  183. package/src/internal/peer-connections.test.ts +128 -0
  184. package/src/internal/peer-mcp.integration.test.ts +289 -0
  185. package/src/internal/playground/toolchain.test.ts +53 -0
  186. package/src/internal/playground-cli.test.ts +187 -0
  187. package/src/internal/playground-proxy.test.ts +376 -0
  188. package/src/internal/prompt-context.integration.test.ts +232 -0
  189. package/src/internal/prompt-context.test.ts +127 -0
  190. package/src/internal/reminder-runner.test.ts +390 -0
  191. package/src/internal/reminder-store.test.ts +53 -0
  192. package/src/internal/request-headers.test.ts +27 -0
  193. package/src/internal/resolve-prod-target.test.ts +787 -0
  194. package/src/internal/resolved-connections.test.ts +295 -0
  195. package/src/internal/resolved-connections.ts +18 -1
  196. package/src/internal/router.test.ts +57 -0
  197. package/src/internal/sdk-runner.test.ts +290 -0
  198. package/src/internal/session-engine.coalesce.test.ts +169 -0
  199. package/src/internal/session-engine.concurrency.test.ts +250 -0
  200. package/src/internal/session-engine.host-oauth-mcp.test.ts +110 -0
  201. package/src/internal/session-engine.interrupt.test.ts +577 -0
  202. package/src/internal/session-engine.storage.test.ts +547 -0
  203. package/src/internal/session-engine.ts +15 -1
  204. package/src/internal/session-urls.test.ts +28 -0
  205. package/src/internal/sessions-client.test.ts +518 -0
  206. package/src/internal/storage-coordinator.test.ts +517 -0
  207. package/src/internal/tool-call.test.ts +458 -0
  208. package/src/internal/tool-result.test.ts +52 -0
  209. package/src/internal/trajectory.approvals.test.ts +83 -0
  210. package/src/internal/trajectory.subagents.test.ts +198 -0
  211. package/src/internal/turn-governor.test.ts +137 -0
  212. package/src/internal/update-check.test.ts +485 -0
  213. package/src/internal/workspace.test.ts +81 -0
  214. package/src/storage-backends/cursor-hosted.test.ts +121 -0
  215. package/src/types.ts +12 -0
  216. package/dist/docs/assets/chunks/@localSearchIndexroot.BnHRjfoe.js +0 -1
  217. package/dist/playground/assets/index-CidizGZv.css +0 -1
@@ -0,0 +1,202 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+ import * as slackApi from "./api.js";
3
+ import {
4
+ findLastBotMessageTs,
5
+ formatSlackThreadContextBlock,
6
+ formatSlackThreadDeltaBlock,
7
+ loadSlackThreadContextBlock,
8
+ mergeThreadMessagesByTs,
9
+ selectThreadDeltaMessages,
10
+ trimThreadMessagesForPrompt,
11
+ } from "./thread-context.js";
12
+
13
+ describe("formatSlackThreadContextBlock", () => {
14
+ it("formats parent then replies and excludes the triggering message", () => {
15
+ const block = formatSlackThreadContextBlock(
16
+ [
17
+ {
18
+ ts: "1.0",
19
+ bot_id: "B1",
20
+ username: "Datadog",
21
+ text: "parent alert",
22
+ },
23
+ { ts: "2.0", user: "U1", text: "looking" },
24
+ { ts: "3.0", user: "U2", text: "@jenny what happened?" },
25
+ ],
26
+ { excludeTs: "3.0" }
27
+ );
28
+ expect(block).toContain("<slack_thread>");
29
+ expect(block).toContain("[parent] bot:B1 (Datadog) @ 1.0:");
30
+ expect(block).toContain("parent alert");
31
+ expect(block).toContain("[reply] U1 @ 2.0:");
32
+ expect(block).not.toContain("what happened?");
33
+ expect(block).toContain("</slack_thread>");
34
+ });
35
+
36
+ it("labels parent by thread ts even when earlier rows are filtered", () => {
37
+ const block = formatSlackThreadContextBlock(
38
+ [
39
+ { ts: "1.0", user: "U1", text: "" },
40
+ { ts: "2.0", user: "U2", text: "actual parent" },
41
+ { ts: "3.0", user: "U3", text: "reply" },
42
+ ],
43
+ { threadTs: "2.0", excludeTs: "3.0" }
44
+ );
45
+ expect(block).toContain("[parent] U2 @ 2.0:");
46
+ expect(block).not.toContain("[reply] U3 @ 3.0:");
47
+ expect(block).not.toContain("[parent] U3");
48
+ });
49
+
50
+ it("keeps the thread root plus the newest replies when over the limit", () => {
51
+ const messages = [{ ts: "1.0", user: "U0", text: "root" }];
52
+ for (let i = 2; i <= 60; i++) {
53
+ messages.push({ ts: `${i}.0`, user: "U1", text: `reply ${i}` });
54
+ }
55
+ const trimmed = trimThreadMessagesForPrompt(messages, {
56
+ threadTs: "1.0",
57
+ limit: 50,
58
+ });
59
+ expect(trimmed[0]).toMatchObject({ ts: "1.0" });
60
+ expect(trimmed.at(-1)).toMatchObject({ ts: "60.0" });
61
+ expect(trimmed).toHaveLength(50);
62
+ });
63
+
64
+ it("returns undefined when nothing usable remains", () => {
65
+ expect(
66
+ formatSlackThreadContextBlock([{ ts: "1.0", text: "only me" }], {
67
+ excludeTs: "1.0",
68
+ })
69
+ ).toBeUndefined();
70
+ });
71
+
72
+ it("truncates oversized blocks", () => {
73
+ const block = formatSlackThreadContextBlock(
74
+ [
75
+ {
76
+ ts: "1.0",
77
+ user: "U1",
78
+ text: "x".repeat(500),
79
+ },
80
+ ],
81
+ { maxChars: 120 }
82
+ );
83
+ expect(block).toBeDefined();
84
+ expect(block!.length).toBeLessThanOrEqual(200);
85
+ expect(block).toContain("truncated");
86
+ expect(block).toContain("</slack_thread>");
87
+ });
88
+ });
89
+
90
+ describe("thread delta helpers", () => {
91
+ it("finds the latest bot message ts", () => {
92
+ expect(
93
+ findLastBotMessageTs([
94
+ { ts: "1.0", user: "U1", text: "human" },
95
+ { ts: "1.5", bot_id: "B1", text: "bot a" },
96
+ { ts: "2.0", user: "U2", text: "human 2" },
97
+ { ts: "2.5", bot_id: "B1", text: "bot b" },
98
+ ])
99
+ ).toBe("2.5");
100
+ });
101
+
102
+ it("restricts watermark to the agent bot when identity is provided", () => {
103
+ expect(
104
+ findLastBotMessageTs(
105
+ [
106
+ { ts: "1.0", bot_id: "BDD", text: "datadog" },
107
+ { ts: "1.5", bot_id: "BJENNY", text: "jenny" },
108
+ { ts: "2.0", user: "U1", text: "human" },
109
+ { ts: "2.5", bot_id: "BDD", text: "datadog again" },
110
+ ],
111
+ { botId: "BJENNY" }
112
+ )
113
+ ).toBe("1.5");
114
+ });
115
+
116
+ it("merges missing triggering ask by ts", () => {
117
+ const merged = mergeThreadMessagesByTs(
118
+ [{ ts: "1.0", user: "U0", text: "root" }],
119
+ [{ ts: "2.0", user: "U1", text: "lagging ask" }]
120
+ );
121
+ expect(merged.map((m) => m.ts)).toEqual(["1.0", "2.0"]);
122
+ });
123
+
124
+ it("formats slack_thread_delta after watermark", () => {
125
+ const delta = selectThreadDeltaMessages(
126
+ [
127
+ { ts: "1.0", bot_id: "B1", text: "bot" },
128
+ { ts: "2.0", user: "U1", text: "ask" },
129
+ ],
130
+ { afterTs: "1.0", excludeTs: "2.0" }
131
+ );
132
+ expect(delta).toHaveLength(0);
133
+ const block = formatSlackThreadDeltaBlock(
134
+ [
135
+ { ts: "1.0", bot_id: "B1", text: "bot" },
136
+ { ts: "2.0", user: "U1", text: "ask" },
137
+ { ts: "3.0", user: "U2", text: "more" },
138
+ ],
139
+ { afterTs: "1.0", excludeTs: "2.0" }
140
+ );
141
+ expect(block).toContain("<slack_thread_delta>");
142
+ expect(block).toContain("more");
143
+ expect(block).not.toContain("ask");
144
+ });
145
+ });
146
+
147
+ describe("loadSlackThreadContextBlock", () => {
148
+ it("soft-fails without a bot token", async () => {
149
+ await expect(
150
+ loadSlackThreadContextBlock({
151
+ botToken: undefined,
152
+ channelId: "C1",
153
+ threadTs: "1.0",
154
+ })
155
+ ).resolves.toBeUndefined();
156
+ });
157
+
158
+ it("calls conversations.replies and formats the result", async () => {
159
+ const spy = vi.spyOn(slackApi, "callSlackApiSoft").mockResolvedValue({
160
+ ok: true,
161
+ messages: [
162
+ { ts: "1.0", user: "Ubot", text: "alert body" },
163
+ { ts: "2.0", user: "U1", text: "mention" },
164
+ ],
165
+ has_more: false,
166
+ });
167
+ const block = await loadSlackThreadContextBlock({
168
+ botToken: "xoxb-test",
169
+ channelId: "C1",
170
+ threadTs: "1.0",
171
+ excludeTs: "2.0",
172
+ });
173
+ expect(spy).toHaveBeenCalledWith(
174
+ expect.objectContaining({
175
+ operation: "conversations.replies",
176
+ body: expect.objectContaining({
177
+ channel: "C1",
178
+ ts: "1.0",
179
+ inclusive: true,
180
+ }),
181
+ })
182
+ );
183
+ expect(block).toContain("alert body");
184
+ expect(block).not.toContain("mention");
185
+ spy.mockRestore();
186
+ });
187
+
188
+ it("soft-fails when Slack returns not-ok", async () => {
189
+ const spy = vi.spyOn(slackApi, "callSlackApiSoft").mockResolvedValue({
190
+ ok: false,
191
+ error: "channel_not_found",
192
+ });
193
+ await expect(
194
+ loadSlackThreadContextBlock({
195
+ botToken: "xoxb-test",
196
+ channelId: "C1",
197
+ threadTs: "1.0",
198
+ })
199
+ ).resolves.toBeUndefined();
200
+ spy.mockRestore();
201
+ });
202
+ });
@@ -88,6 +88,21 @@ export interface SlackAuthor {
88
88
  botId?: string;
89
89
  }
90
90
 
91
+ /**
92
+ * Delegation metadata carried on bot-to-bot mention posts (Slack message
93
+ * `metadata`, event type {@link SLACK_DELEGATION_METADATA_EVENT_TYPE}).
94
+ * Absent on posts from bots that don't speak the protocol — the gate then
95
+ * treats the mention as depth 1.
96
+ */
97
+ export interface SlackDelegationInfo {
98
+ /** Delegation hop count. A dispatcher woken by a human posts depth 1. */
99
+ depth: number;
100
+ /** Mount slug / display name of the delegating agent. */
101
+ fromAgent?: string;
102
+ /** Session id on the delegating agent, for cross-agent tracing. */
103
+ originSessionId?: string;
104
+ }
105
+
91
106
  export interface SlackMessage {
92
107
  /** Raw top-level `text` exactly as Slack sent it. Often empty on bot posts. */
93
108
  text: string;
@@ -105,6 +120,8 @@ export interface SlackMessage {
105
120
  channelId: string;
106
121
  teamId?: string;
107
122
  author?: SlackAuthor;
123
+ /** Parsed delegation metadata when the post carried it (bot mentions). */
124
+ delegation?: SlackDelegationInfo;
108
125
  }
109
126
 
110
127
  export interface SlackDispatchDecision {
@@ -298,6 +315,44 @@ export interface SlackChannelPostsOptions {
298
315
  includeBotPosts?: boolean;
299
316
  }
300
317
 
318
+ /**
319
+ * Opt-in bot-to-bot mention wake: allow @mentions authored by explicitly
320
+ * trusted bots (e.g. a dispatcher agent) to dispatch like human mentions.
321
+ * Default off — bot-authored mentions are dropped (loop safety). There is
322
+ * deliberately no "any bot" wildcard; trusting a bot is a per-bot decision.
323
+ *
324
+ * Loop protection is layered: this allowlist, the always-on own-post
325
+ * filter, a delegation-depth budget (Slack message metadata), and a
326
+ * per-thread wake budget.
327
+ */
328
+ export interface SlackBotMentionsOptions {
329
+ /**
330
+ * Bots whose mentions may wake this agent: `bot_id`s (`B…`) and/or bot
331
+ * *user* ids (`U…`). Must be non-empty (empty is a definition error).
332
+ */
333
+ allowFrom: string[];
334
+ /**
335
+ * Maximum delegation depth admitted (from the mention's delegation
336
+ * metadata; mentions without metadata count as depth 1). Defaults to 2 —
337
+ * human → dispatcher → specialist, no deeper chains.
338
+ */
339
+ maxDepth?: number;
340
+ /**
341
+ * Maximum bot-initiated wakes per thread per hour (sliding window).
342
+ * Defaults to 5. Rate-limits ping-pong between bots that carry no
343
+ * delegation metadata; termination comes from {@link maxPerThreadTotal}.
344
+ */
345
+ maxPerThreadPerHour?: number;
346
+ /**
347
+ * Lifetime cap on bot-initiated wakes per thread (resets only after the
348
+ * thread has been idle for 24h). Defaults to 20. This is the terminating
349
+ * backstop: a sliding window alone refills, so two mutually-allowlisted
350
+ * bots could ping-pong forever at the rate cap. Avoid mutual allowlists
351
+ * regardless — keep the delegation graph a DAG.
352
+ */
353
+ maxPerThreadTotal?: number;
354
+ }
355
+
301
356
  /**
302
357
  * How the agent engages over Slack. Omitted entirely = mentions + DMs,
303
358
  * which is also the default for each flag — summoned, never proactive.
@@ -313,6 +368,11 @@ export interface SlackEngagementOptions {
313
368
  * (`slack init --channel-posts`, or add the events to an existing app).
314
369
  */
315
370
  channelPosts?: SlackChannelPostsOptions;
371
+ /**
372
+ * Opt-in bot-to-bot mention wake (see {@link SlackBotMentionsOptions}).
373
+ * Socket Mode only — rejected on `cursorAccount: true`.
374
+ */
375
+ botMentions?: SlackBotMentionsOptions;
316
376
  }
317
377
 
318
378
  /**