@cursor/july 0.1.7 → 0.1.9

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 (210) hide show
  1. package/dist/bin/agent-serve.js +31 -2
  2. package/dist/channels/slack/channel-watch.d.ts +6 -1
  3. package/dist/channels/slack/channel-watch.d.ts.map +1 -1
  4. package/dist/channels/slack/channel-watch.js +22 -1
  5. package/dist/channels/slack/cursor-account.d.ts +4 -0
  6. package/dist/channels/slack/cursor-account.d.ts.map +1 -1
  7. package/dist/channels/slack/cursor-account.js +12 -2
  8. package/dist/channels/slack/defaults.d.ts +10 -5
  9. package/dist/channels/slack/defaults.d.ts.map +1 -1
  10. package/dist/channels/slack/defaults.js +39 -17
  11. package/dist/channels/slack/dispatch.d.ts +18 -0
  12. package/dist/channels/slack/dispatch.d.ts.map +1 -1
  13. package/dist/channels/slack/dispatch.js +141 -38
  14. package/dist/channels/slack/inbound.d.ts +13 -3
  15. package/dist/channels/slack/inbound.d.ts.map +1 -1
  16. package/dist/channels/slack/inbound.js +17 -9
  17. package/dist/channels/slack/index.d.ts +4 -0
  18. package/dist/channels/slack/index.d.ts.map +1 -1
  19. package/dist/channels/slack/index.js +4 -0
  20. package/dist/channels/slack/live-delivery.d.ts.map +1 -1
  21. package/dist/channels/slack/live-delivery.js +1 -0
  22. package/dist/channels/slack/manifest.d.ts.map +1 -1
  23. package/dist/channels/slack/manifest.js +3 -0
  24. package/dist/channels/slack/nudge-carrier.d.ts +19 -0
  25. package/dist/channels/slack/nudge-carrier.d.ts.map +1 -0
  26. package/dist/channels/slack/nudge-carrier.js +166 -0
  27. package/dist/channels/slack/nudge-store.d.ts +61 -0
  28. package/dist/channels/slack/nudge-store.d.ts.map +1 -0
  29. package/dist/channels/slack/nudge-store.js +266 -0
  30. package/dist/channels/slack/post-update-delivery.js +318 -0
  31. package/dist/channels/slack/slack-channel.d.ts.map +1 -1
  32. package/dist/channels/slack/slack-channel.js +74 -25
  33. package/dist/channels/slack/stop.d.ts +14 -0
  34. package/dist/channels/slack/stop.d.ts.map +1 -0
  35. package/dist/channels/slack/stop.js +22 -0
  36. package/dist/channels/slack/thread-context.d.ts +81 -0
  37. package/dist/channels/slack/thread-context.d.ts.map +1 -0
  38. package/dist/channels/slack/thread-context.js +470 -0
  39. package/dist/channels/slack/types.d.ts +27 -0
  40. package/dist/channels/slack/types.d.ts.map +1 -1
  41. package/dist/docs/404.html +2 -2
  42. package/dist/docs/ab.html +4 -4
  43. package/dist/docs/assets/{app.COTN7wgo.js → app.Ciosf24M.js} +1 -1
  44. package/dist/docs/assets/chunks/@localSearchIndexroot.D154Detj.js +1 -0
  45. package/dist/docs/assets/chunks/{VPLocalSearchBox.BW3TBdT0.js → VPLocalSearchBox.BcRDly7n.js} +1 -1
  46. package/dist/docs/assets/chunks/{theme.BEJW0vE7.js → theme.CMpbjdfx.js} +2 -2
  47. package/dist/docs/assets/{deployment.md.BtfEsc9S.js → deployment.md.DC5-ImcM.js} +1 -1
  48. package/dist/docs/assets/{example-agents_approval-buddy.md.8R5phXb5.js → example-agents_approval-buddy.md.DFGBYLcc.js} +2 -2
  49. package/dist/docs/assets/{example-agents_approval-buddy.md.8R5phXb5.lean.js → example-agents_approval-buddy.md.DFGBYLcc.lean.js} +1 -1
  50. package/dist/docs/assets/example-agents_index.md.BPXjUtRB.js +2 -0
  51. package/dist/docs/assets/example-agents_index.md.BPXjUtRB.lean.js +1 -0
  52. package/dist/docs/assets/example-agents_oncall.md.BG_sUMly.js +10 -0
  53. package/dist/docs/assets/example-agents_oncall.md.BG_sUMly.lean.js +1 -0
  54. package/dist/docs/assets/{example-agents_security-reviewer.md.D2rtwDTO.js → example-agents_security-reviewer.md.CE9v-aKm.js} +2 -2
  55. package/dist/docs/assets/{example-agents_security-reviewer.md.D2rtwDTO.lean.js → example-agents_security-reviewer.md.CE9v-aKm.lean.js} +1 -1
  56. package/dist/docs/assets/{guides_slack.md.CCwqHvSV.js → guides_slack.md.FWale6Ip.js} +4 -3
  57. package/dist/docs/assets/{guides_slack.md.CCwqHvSV.lean.js → guides_slack.md.FWale6Ip.lean.js} +1 -1
  58. package/dist/docs/assets/{reference_sessions.md.DdjWabnN.js → reference_sessions.md.DLd6mvbv.js} +2 -2
  59. package/dist/docs/assets/{reference_sessions.md.DdjWabnN.lean.js → reference_sessions.md.DLd6mvbv.lean.js} +1 -1
  60. package/dist/docs/assets/{storage.md.CVnInNiN.js → storage.md.DRTdnFvd.js} +9 -2
  61. package/dist/docs/assets/{storage.md.CVnInNiN.lean.js → storage.md.DRTdnFvd.lean.js} +1 -1
  62. package/dist/docs/building-with-agents.html +4 -4
  63. package/dist/docs/concepts.html +4 -4
  64. package/dist/docs/deployment.html +6 -6
  65. package/dist/docs/evals.html +4 -4
  66. package/dist/docs/example-agents/approval-buddy.html +5 -5
  67. package/dist/docs/example-agents/benny.html +5 -5
  68. package/dist/docs/example-agents/bugbot.html +5 -5
  69. package/dist/docs/example-agents/codebase-wiki.html +4 -4
  70. package/dist/docs/example-agents/codeowners-review.html +4 -4
  71. package/dist/docs/example-agents/concierge.html +4 -4
  72. package/dist/docs/example-agents/fsd.html +4 -4
  73. package/dist/docs/example-agents/index.html +6 -6
  74. package/dist/docs/example-agents/knowledge-base.html +4 -4
  75. package/dist/docs/example-agents/oncall.html +34 -0
  76. package/dist/docs/example-agents/security-reviewer.html +6 -6
  77. package/dist/docs/example-agents/slack-agent.html +4 -4
  78. package/dist/docs/example-agents/weather-agent.html +4 -4
  79. package/dist/docs/guides/agent-to-agent.html +4 -4
  80. package/dist/docs/guides/cloud-runtime.html +4 -4
  81. package/dist/docs/guides/github.html +4 -4
  82. package/dist/docs/guides/human-in-the-loop.html +4 -4
  83. package/dist/docs/guides/slack.html +7 -6
  84. package/dist/docs/guides/webhooks.html +4 -4
  85. package/dist/docs/hashmap.json +1 -1
  86. package/dist/docs/hillclimbing.html +4 -4
  87. package/dist/docs/index.html +4 -4
  88. package/dist/docs/quickstart.html +4 -4
  89. package/dist/docs/reference/agent-config.html +4 -4
  90. package/dist/docs/reference/channels.html +4 -4
  91. package/dist/docs/reference/cli.html +4 -4
  92. package/dist/docs/reference/connections.html +4 -4
  93. package/dist/docs/reference/hooks.html +4 -4
  94. package/dist/docs/reference/http-api.html +4 -4
  95. package/dist/docs/reference/instructions.html +4 -4
  96. package/dist/docs/reference/playground.html +4 -4
  97. package/dist/docs/reference/project-layout.html +4 -4
  98. package/dist/docs/reference/schedules.html +4 -4
  99. package/dist/docs/reference/sessions.html +5 -5
  100. package/dist/docs/reference/skills.html +4 -4
  101. package/dist/docs/reference/subagents.html +4 -4
  102. package/dist/docs/reference/tools.html +4 -4
  103. package/dist/docs/scaffolding-agents.html +4 -4
  104. package/dist/docs/storage.html +13 -6
  105. package/dist/docs/troubleshooting.html +4 -4
  106. package/dist/internal/cli-deploy.d.ts.map +1 -1
  107. package/dist/internal/cli-deploy.js +45 -18
  108. package/dist/internal/cli-mcp.d.ts +64 -0
  109. package/dist/internal/cli-mcp.d.ts.map +1 -0
  110. package/dist/internal/cli-mcp.js +570 -0
  111. package/dist/internal/deploy-client.d.ts +7 -1
  112. package/dist/internal/deploy-client.d.ts.map +1 -1
  113. package/dist/internal/deploy-client.js +3 -0
  114. package/dist/internal/deploy-source.d.ts +3 -0
  115. package/dist/internal/deploy-source.d.ts.map +1 -1
  116. package/dist/internal/deploy-source.js +25 -7
  117. package/dist/internal/discovery.js +1 -1
  118. package/dist/internal/distribution.d.ts.map +1 -1
  119. package/dist/internal/distribution.js +3 -0
  120. package/dist/internal/host-kv.d.ts +17 -0
  121. package/dist/internal/host-kv.d.ts.map +1 -0
  122. package/dist/internal/host-kv.js +77 -0
  123. package/dist/internal/hosting.d.ts +12 -2
  124. package/dist/internal/hosting.d.ts.map +1 -1
  125. package/dist/internal/hosting.js +21 -4
  126. package/dist/internal/json-dir-store.js +100 -0
  127. package/dist/internal/logs-client.d.ts +16 -2
  128. package/dist/internal/logs-client.d.ts.map +1 -1
  129. package/dist/internal/logs-client.js +51 -16
  130. package/dist/internal/server.d.ts.map +1 -1
  131. package/dist/internal/server.js +8 -0
  132. package/dist/internal/session-engine.d.ts +42 -7
  133. package/dist/internal/session-engine.d.ts.map +1 -1
  134. package/dist/internal/session-engine.js +276 -66
  135. package/dist/internal/storage-coordinator.d.ts +18 -1
  136. package/dist/internal/storage-coordinator.d.ts.map +1 -1
  137. package/dist/internal/storage-coordinator.js +43 -0
  138. package/dist/internal/workspace.d.ts +19 -0
  139. package/dist/internal/workspace.d.ts.map +1 -1
  140. package/dist/internal/workspace.js +47 -13
  141. package/dist/playground/assets/{index-72vCOBWO.js → index-C0-QEG4O.js} +42 -42
  142. package/dist/playground/assets/index-z3JY9O2x.css +1 -0
  143. package/dist/playground/index.html +2 -2
  144. package/dist/storage-backends/cursor-hosted.d.ts +65 -0
  145. package/dist/storage-backends/cursor-hosted.d.ts.map +1 -0
  146. package/dist/storage-backends/cursor-hosted.js +203 -0
  147. package/dist/storage-backends/file-kv.d.ts +42 -0
  148. package/dist/storage-backends/file-kv.d.ts.map +1 -0
  149. package/dist/storage-backends/file-kv.js +190 -0
  150. package/dist/storage-backends/postgres-kv.d.ts +82 -0
  151. package/dist/storage-backends/postgres-kv.d.ts.map +1 -0
  152. package/dist/storage-backends/postgres-kv.js +185 -0
  153. package/dist/storage.d.ts +10 -1
  154. package/dist/storage.d.ts.map +1 -1
  155. package/dist/storage.js +10 -1
  156. package/dist/types.d.ts +79 -0
  157. package/dist/types.d.ts.map +1 -1
  158. package/docs/.vitepress/cache/deps/package.json +3 -0
  159. package/docs/deployment.md +7 -3
  160. package/docs/example-agents/approval-buddy.md +1 -1
  161. package/docs/example-agents/index.md +15 -10
  162. package/docs/example-agents/oncall.md +216 -0
  163. package/docs/example-agents/security-reviewer.md +5 -5
  164. package/docs/guides/slack.md +11 -2
  165. package/docs/reference/sessions.md +13 -4
  166. package/docs/storage.md +41 -0
  167. package/package.json +22 -1
  168. package/skills/framework-map/SKILL.md +6 -4
  169. package/src/bin/agent-serve.ts +32 -2
  170. package/src/channels/slack/channel-watch.ts +28 -1
  171. package/src/channels/slack/cursor-account.ts +20 -0
  172. package/src/channels/slack/defaults.ts +51 -20
  173. package/src/channels/slack/dispatch.ts +215 -40
  174. package/src/channels/slack/inbound.ts +30 -10
  175. package/src/channels/slack/index.ts +4 -0
  176. package/src/channels/slack/live-delivery.ts +1 -0
  177. package/src/channels/slack/manifest.ts +3 -0
  178. package/src/channels/slack/nudge-carrier.ts +182 -0
  179. package/src/channels/slack/nudge-store.ts +308 -0
  180. package/src/channels/slack/slack-channel.ts +106 -31
  181. package/src/channels/slack/stop.ts +25 -0
  182. package/src/channels/slack/thread-context.ts +572 -0
  183. package/src/channels/slack/types.ts +27 -0
  184. package/src/internal/cli-deploy.ts +58 -20
  185. package/src/internal/cli-mcp.ts +708 -0
  186. package/src/internal/deploy-client.ts +11 -0
  187. package/src/internal/deploy-source.ts +24 -6
  188. package/src/internal/discovery.ts +1 -1
  189. package/src/internal/distribution.ts +3 -0
  190. package/src/internal/host-kv.ts +85 -0
  191. package/src/internal/hosting.ts +24 -4
  192. package/src/internal/logs-client.ts +67 -21
  193. package/src/internal/server.ts +31 -0
  194. package/src/internal/session-engine.ts +379 -61
  195. package/src/internal/storage-coordinator.ts +41 -0
  196. package/src/internal/workspace.ts +48 -11
  197. package/src/storage-backends/cursor-hosted.ts +246 -0
  198. package/src/storage-backends/file-kv.ts +221 -0
  199. package/src/storage-backends/postgres-kv.ts +253 -0
  200. package/src/storage.ts +11 -1
  201. package/src/types.ts +83 -0
  202. package/dist/docs/assets/chunks/@localSearchIndexroot.B7UcKvIn.js +0 -1
  203. package/dist/docs/assets/example-agents_index.md.CRqJlnIf.js +0 -2
  204. package/dist/docs/assets/example-agents_index.md.CRqJlnIf.lean.js +0 -1
  205. package/dist/internal/persistence-coordinator.d.ts +0 -127
  206. package/dist/internal/persistence-coordinator.d.ts.map +0 -1
  207. package/dist/persistence.d.ts +0 -184
  208. package/dist/persistence.d.ts.map +0 -1
  209. package/dist/playground/assets/index-BjnMwYoR.css +0 -1
  210. /package/dist/docs/assets/{deployment.md.BtfEsc9S.lean.js → deployment.md.DC5-ImcM.lean.js} +0 -0
@@ -23,14 +23,24 @@ export type SlackChannelMessageEvent = {
23
23
  channelId: string;
24
24
  ts: string;
25
25
  };
26
+ export interface ParseChannelMessageOptions {
27
+ /**
28
+ * Keep bot-authored posts (including `subtype: "bot_message"` webhook
29
+ * posts) instead of dropping them at parse time. The channel watch
30
+ * enforces its own per-channel policy ({@link SlackChannelPostsOptions.includeBotPosts})
31
+ * and always drops the watching bot's own posts.
32
+ */
33
+ includeBotAuthored?: boolean;
34
+ }
26
35
  /**
27
36
  * Parse channel / private-channel message events for the opt-in channel
28
37
  * watch. Accepts `channel_type === "channel" | "group"` (or `C…`/`G…`
29
38
  * channel ids when the type is absent). Bot-authored messages are dropped
30
- * (loop safety); edits and deletions are surfaced so a debounce window can
31
- * update or cancel a pending dispatch.
39
+ * (loop safety) unless `options.includeBotAuthored` is set; edits and
40
+ * deletions are surfaced so a debounce window can update or cancel a
41
+ * pending dispatch.
32
42
  */
33
- export declare function parseChannelMessageEvent(body: unknown): SlackChannelMessageEvent | null;
43
+ export declare function parseChannelMessageEvent(body: unknown, options?: ParseChannelMessageOptions): SlackChannelMessageEvent | null;
34
44
  export declare function formatSlackContextBlock(args: {
35
45
  userId: string;
36
46
  userName?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"inbound.d.ts","sourceRoot":"","sources":["../../../src/channels/slack/inbound.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAe,YAAY,EAAE,MAAM,YAAY,CAAC;AAe5D,oEAAoE;AACpE,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CASxD;AA4CD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,OAAO,GAAG,YAAY,GAAG,IAAI,CAevE;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,OAAO,GAAG,YAAY,GAAG,IAAI,CA8B1E;AAED,4EAA4E;AAC5E,MAAM,MAAM,wBAAwB,GAChC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,YAAY,CAAA;CAAE,GACvC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,YAAY,CAAA;CAAE,GACzC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvD;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,OAAO,GACZ,wBAAwB,GAAG,IAAI,CAwDjC;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,MAAM,CAYT"}
1
+ {"version":3,"file":"inbound.d.ts","sourceRoot":"","sources":["../../../src/channels/slack/inbound.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAe,YAAY,EAAE,MAAM,YAAY,CAAC;AAe5D,oEAAoE;AACpE,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CASxD;AAgDD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,OAAO,GAAG,YAAY,GAAG,IAAI,CAevE;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,OAAO,GAAG,YAAY,GAAG,IAAI,CA8B1E;AAED,4EAA4E;AAC5E,MAAM,MAAM,wBAAwB,GAChC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,YAAY,CAAA;CAAE,GACvC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,YAAY,CAAA;CAAE,GACzC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvD,MAAM,WAAW,0BAA0B;IACzC;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,OAAO,EACb,OAAO,CAAC,EAAE,0BAA0B,GACnC,wBAAwB,GAAG,IAAI,CA4DjC;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,MAAM,CAYT"}
@@ -21,12 +21,15 @@ export function slackTextToMarkdown(text) {
21
21
  }
22
22
  function parseAuthor(event) {
23
23
  const userId = asString(event.user);
24
- if (userId === undefined || userId === "") {
24
+ const botId = asString(event.bot_id);
25
+ const isBot = botId !== undefined && botId.length > 0;
26
+ // Webhook-style bot posts can lack `user`; keep a bot author so the
27
+ // channel watch can attribute (and self-filter) them by `bot_id`.
28
+ if ((userId === undefined || userId === "") && !isBot) {
25
29
  return undefined;
26
30
  }
27
- const botId = asString(event.bot_id);
28
31
  const userName = asString(event.username);
29
- return Object.assign(Object.assign({ userId }, (userName === undefined ? {} : { userName })), { isBot: botId !== undefined && botId.length > 0 });
32
+ return Object.assign(Object.assign(Object.assign({ userId: userId !== null && userId !== void 0 ? userId : "" }, (userName === undefined ? {} : { userName })), { isBot }), (isBot ? { botId } : {}));
30
33
  }
31
34
  function buildSlackMessage(event, teamId) {
32
35
  var _a, _b;
@@ -99,10 +102,11 @@ export function parseDirectMessageEvent(body) {
99
102
  * Parse channel / private-channel message events for the opt-in channel
100
103
  * watch. Accepts `channel_type === "channel" | "group"` (or `C…`/`G…`
101
104
  * channel ids when the type is absent). Bot-authored messages are dropped
102
- * (loop safety); edits and deletions are surfaced so a debounce window can
103
- * update or cancel a pending dispatch.
105
+ * (loop safety) unless `options.includeBotAuthored` is set; edits and
106
+ * deletions are surfaced so a debounce window can update or cancel a
107
+ * pending dispatch.
104
108
  */
105
- export function parseChannelMessageEvent(body) {
109
+ export function parseChannelMessageEvent(body, options) {
106
110
  var _a, _b, _c;
107
111
  const root = asRecord(body);
108
112
  if (root === null || root.type !== "event_callback") {
@@ -123,6 +127,7 @@ export function parseChannelMessageEvent(body) {
123
127
  }
124
128
  const teamId = asString(root.team_id);
125
129
  const subtype = (_b = asString(event.subtype)) !== null && _b !== void 0 ? _b : "";
130
+ const includeBots = (options === null || options === void 0 ? void 0 : options.includeBotAuthored) === true;
126
131
  if (subtype === "message_deleted") {
127
132
  const deletedTs = (_c = asString(event.deleted_ts)) !== null && _c !== void 0 ? _c : "";
128
133
  return deletedTs === ""
@@ -135,17 +140,20 @@ export function parseChannelMessageEvent(body) {
135
140
  return null;
136
141
  }
137
142
  const botId = asString(nested.bot_id);
138
- if (botId !== undefined && botId.length > 0) {
143
+ if (!includeBots && botId !== undefined && botId.length > 0) {
139
144
  return null;
140
145
  }
141
146
  const message = buildSlackMessage(Object.assign(Object.assign({}, nested), { channel: channelId }), teamId);
142
147
  return message === null ? null : { kind: "edited", message };
143
148
  }
144
- if (subtype !== "" && subtype !== "file_share") {
149
+ const allowedSubtypes = includeBots
150
+ ? ["", "file_share", "bot_message"]
151
+ : ["", "file_share"];
152
+ if (!allowedSubtypes.includes(subtype)) {
145
153
  return null;
146
154
  }
147
155
  const botId = asString(event.bot_id);
148
- if (botId !== undefined && botId.length > 0) {
156
+ if (!includeBots && botId !== undefined && botId.length > 0) {
149
157
  return null;
150
158
  }
151
159
  const message = buildSlackMessage(event, teamId);
@@ -35,11 +35,15 @@ export * from "./interactive.js";
35
35
  export * from "./links.js";
36
36
  export * from "./log.js";
37
37
  export * from "./manifest.js";
38
+ export * from "./nudge-carrier.js";
39
+ export * from "./nudge-store.js";
38
40
  export * from "./pr-ref.js";
39
41
  export * from "./setup.js";
40
42
  export * from "./slack-channel.js";
41
43
  export * from "./socket-mode.js";
44
+ export * from "./stop.js";
42
45
  export * from "./stream.js";
46
+ export * from "./thread-context.js";
43
47
  export * from "./tool-approval-events.js";
44
48
  export * from "./types.js";
45
49
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/channels/slack/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,sBAAsB,CAAC;AACrC,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/channels/slack/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,sBAAsB,CAAC;AACrC,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,YAAY,CAAC"}
@@ -35,10 +35,14 @@ export * from "./interactive.js";
35
35
  export * from "./links.js";
36
36
  export * from "./log.js";
37
37
  export * from "./manifest.js";
38
+ export * from "./nudge-carrier.js";
39
+ export * from "./nudge-store.js";
38
40
  export * from "./pr-ref.js";
39
41
  export * from "./setup.js";
40
42
  export * from "./slack-channel.js";
41
43
  export * from "./socket-mode.js";
44
+ export * from "./stop.js";
42
45
  export * from "./stream.js";
46
+ export * from "./thread-context.js";
43
47
  export * from "./tool-approval-events.js";
44
48
  export * from "./types.js";
@@ -1 +1 @@
1
- {"version":3,"file":"live-delivery.d.ts","sourceRoot":"","sources":["../../../src/channels/slack/live-delivery.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAE1D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEnE,KAAK,YAAY,GAAG,mBAAmB,CAAC,iBAAiB,CAAC,CAAC;AAE3D,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,aAAa,GAAG,SAAS,CAAC;IACpC,MAAM,EAAE,MAAM,QAAQ,CAAC;CACxB;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC,8EAA8E;IAC9E,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC,4CAA4C;IAC5C,KAAK,CAAC,IAAI,EAAE;QACV,OAAO,EAAE,YAAY,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;KACnB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClB,uEAAuE;IACvE,MAAM,CAAC,IAAI,EAAE;QACX,OAAO,EAAE,YAAY,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;KACnB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClB;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE;QACb,OAAO,EAAE,YAAY,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;KACnB,GAAG,OAAO,CAAC;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IACpC,mEAAmE;IACnE,aAAa,CAAC,IAAI,EAAE;QAClB,OAAO,EAAE,YAAY,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;KAClB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClB,wEAAwE;IACxE,aAAa,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,YAAY,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9D,uFAAuF;IACvF,IAAI,CAAC,IAAI,EAAE;QACT,OAAO,EAAE,YAAY,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;KACnB,GAAG,OAAO,CAAC;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CACrC;AAED,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,gBAAgB,GACrB,oBAAoB,CA6HtB"}
1
+ {"version":3,"file":"live-delivery.d.ts","sourceRoot":"","sources":["../../../src/channels/slack/live-delivery.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAE1D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEnE,KAAK,YAAY,GAAG,mBAAmB,CAAC,iBAAiB,CAAC,CAAC;AAE3D,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,aAAa,GAAG,SAAS,CAAC;IACpC,MAAM,EAAE,MAAM,QAAQ,CAAC;CACxB;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC,8EAA8E;IAC9E,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC,4CAA4C;IAC5C,KAAK,CAAC,IAAI,EAAE;QACV,OAAO,EAAE,YAAY,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;KACnB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClB,uEAAuE;IACvE,MAAM,CAAC,IAAI,EAAE;QACX,OAAO,EAAE,YAAY,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;KACnB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClB;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE;QACb,OAAO,EAAE,YAAY,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;KACnB,GAAG,OAAO,CAAC;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IACpC,mEAAmE;IACnE,aAAa,CAAC,IAAI,EAAE;QAClB,OAAO,EAAE,YAAY,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;KAClB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClB,wEAAwE;IACxE,aAAa,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,YAAY,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9D,uFAAuF;IACvF,IAAI,CAAC,IAAI,EAAE;QACT,OAAO,EAAE,YAAY,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;KACnB,GAAG,OAAO,CAAC;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CACrC;AAED,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,gBAAgB,GACrB,oBAAoB,CA8HtB"}
@@ -92,6 +92,7 @@ export function createStreamDeliveryStrategy(deps) {
92
92
  if (stopped.ok) {
93
93
  channel.state.streamTs = null;
94
94
  channel.state.lastPostedText = text;
95
+ channel.state.lastBotMessageTs = streamTs;
95
96
  log.info("reply delivered via stream", {
96
97
  channel: channelId,
97
98
  stream_ts: streamTs,
@@ -1 +1 @@
1
- {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../../src/channels/slack/manifest.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEvD,MAAM,WAAW,gBAAgB;IAC/B,mBAAmB,EAAE;QACnB,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,QAAQ,EAAE;QACR,QAAQ,EAAE;YACR,YAAY,EAAE,MAAM,CAAC;YACrB,aAAa,EAAE,OAAO,CAAC;SACxB,CAAC;QACF,cAAc,CAAC,EAAE;YACf,qBAAqB,EAAE,MAAM,CAAC;YAC9B,iBAAiB,EAAE,KAAK,CAAC;gBAAE,KAAK,EAAE,MAAM,CAAC;gBAAC,OAAO,EAAE,MAAM,CAAA;aAAE,CAAC,CAAC;SAC9D,CAAC;QACF,QAAQ,CAAC,EAAE;YACT,gBAAgB,EAAE,OAAO,CAAC;YAC1B,oBAAoB,EAAE,OAAO,CAAC;YAC9B,8BAA8B,EAAE,OAAO,CAAC;SACzC,CAAC;KACH,CAAC;IACF,YAAY,EAAE;QACZ,MAAM,EAAE;YACN,GAAG,EAAE,MAAM,EAAE,CAAC;SACf,CAAC;KACH,CAAC;IACF,QAAQ,EAAE;QACR,mBAAmB,EAAE;YACnB,UAAU,EAAE,MAAM,EAAE,CAAC;SACtB,CAAC;QACF,aAAa,EAAE;YACb,UAAU,EAAE,OAAO,CAAC;SACrB,CAAC;QACF,kBAAkB,EAAE,OAAO,CAAC;QAC5B,mBAAmB,EAAE,OAAO,CAAC;QAC7B,sBAAsB,EAAE,OAAO,CAAC;QAChC,cAAc,EAAE,OAAO,CAAC;KACzB,CAAC;CACH;AAyCD;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,oBAAoB,GAC5B,gBAAgB,CA0ElB;AAED,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,IAAI,CAAC,oBAAoB,EAAE,KAAK,CAAC,GACzC;IACD,GAAG,EAAE,gBAAgB,CAAC;IACtB,IAAI,EAAE,gBAAgB,CAAC;CACxB,CAKA"}
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../../src/channels/slack/manifest.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEvD,MAAM,WAAW,gBAAgB;IAC/B,mBAAmB,EAAE;QACnB,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,QAAQ,EAAE;QACR,QAAQ,EAAE;YACR,YAAY,EAAE,MAAM,CAAC;YACrB,aAAa,EAAE,OAAO,CAAC;SACxB,CAAC;QACF,cAAc,CAAC,EAAE;YACf,qBAAqB,EAAE,MAAM,CAAC;YAC9B,iBAAiB,EAAE,KAAK,CAAC;gBAAE,KAAK,EAAE,MAAM,CAAC;gBAAC,OAAO,EAAE,MAAM,CAAA;aAAE,CAAC,CAAC;SAC9D,CAAC;QACF,QAAQ,CAAC,EAAE;YACT,gBAAgB,EAAE,OAAO,CAAC;YAC1B,oBAAoB,EAAE,OAAO,CAAC;YAC9B,8BAA8B,EAAE,OAAO,CAAC;SACzC,CAAC;KACH,CAAC;IACF,YAAY,EAAE;QACZ,MAAM,EAAE;YACN,GAAG,EAAE,MAAM,EAAE,CAAC;SACf,CAAC;KACH,CAAC;IACF,QAAQ,EAAE;QACR,mBAAmB,EAAE;YACnB,UAAU,EAAE,MAAM,EAAE,CAAC;SACtB,CAAC;QACF,aAAa,EAAE;YACb,UAAU,EAAE,OAAO,CAAC;SACrB,CAAC;QACF,kBAAkB,EAAE,OAAO,CAAC;QAC5B,mBAAmB,EAAE,OAAO,CAAC;QAC7B,sBAAsB,EAAE,OAAO,CAAC;QAChC,cAAc,EAAE,OAAO,CAAC;KACzB,CAAC;CACH;AA4CD;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,oBAAoB,GAC5B,gBAAgB,CA0ElB;AAED,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,IAAI,CAAC,oBAAoB,EAAE,KAAK,CAAC,GACzC;IACD,GAAG,EAAE,gBAAgB,CAAC;IACtB,IAAI,EAAE,gBAAgB,CAAC;CACxB,CAKA"}
@@ -14,6 +14,9 @@ const BOT_SCOPES = [
14
14
  "im:read",
15
15
  "im:write",
16
16
  "mpim:history",
17
+ // Emoji acknowledgements (e.g. an agent reacting 👀 when it locks onto
18
+ // a watched-channel post before investigating).
19
+ "reactions:write",
17
20
  "users:read",
18
21
  ];
19
22
  const BOT_EVENTS = ["app_mention", "message.im"];
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Harness-side nudge carrier: a small Cursor hooks.json + script that drains
3
+ * the durable Slack nudge store at tool boundaries (MCP / builtin tools).
4
+ */
5
+ export declare const SLACK_NUDGE_ROOT_REL = ".agent-serve/slack-nudge-root";
6
+ export declare const SLACK_NUDGE_CONTINUATION_REL = ".agent-serve/slack-nudge-continuation";
7
+ export declare const SLACK_NUDGE_CARRIER_REL = ".agent-serve/slack-nudge-carrier.mjs";
8
+ /** Carrier script body — reads nudge-root + continuation, drains pending. */
9
+ export declare const SLACK_NUDGE_CARRIER_SCRIPT: string;
10
+ /**
11
+ * Write carrier script + pointer files and ensure pre/postToolUse hooks invoke it.
12
+ * Safe to call every turn (idempotent overwrite of carrier + pointers).
13
+ */
14
+ export declare function materializeSlackNudgeCarrier(args: {
15
+ harnessCwd: string;
16
+ nudgeRootDir: string;
17
+ continuationKey: string;
18
+ }): Promise<void>;
19
+ //# sourceMappingURL=nudge-carrier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nudge-carrier.d.ts","sourceRoot":"","sources":["../../../src/channels/slack/nudge-carrier.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,eAAO,MAAM,oBAAoB,kCAAkC,CAAC;AACpE,eAAO,MAAM,4BAA4B,0CACA,CAAC;AAC1C,eAAO,MAAM,uBAAuB,yCAAyC,CAAC;AAE9E,6EAA6E;AAC7E,eAAO,MAAM,0BAA0B,EAAE,MA6GxC,CAAC;AAOF;;;GAGG;AACH,wBAAsB,4BAA4B,CAAC,IAAI,EAAE;IACvD,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;CACzB,GAAG,OAAO,CAAC,IAAI,CAAC,CA2ChB"}
@@ -0,0 +1,166 @@
1
+ /**
2
+ * Harness-side nudge carrier: a small Cursor hooks.json + script that drains
3
+ * the durable Slack nudge store at tool boundaries (MCP / builtin tools).
4
+ */
5
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
6
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
7
+ return new (P || (P = Promise))(function (resolve, reject) {
8
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
9
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
10
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
11
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
12
+ });
13
+ };
14
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
15
+ import { join } from "node:path";
16
+ export const SLACK_NUDGE_ROOT_REL = ".agent-serve/slack-nudge-root";
17
+ export const SLACK_NUDGE_CONTINUATION_REL = ".agent-serve/slack-nudge-continuation";
18
+ export const SLACK_NUDGE_CARRIER_REL = ".agent-serve/slack-nudge-carrier.mjs";
19
+ /** Carrier script body — reads nudge-root + continuation, drains pending. */
20
+ export const SLACK_NUDGE_CARRIER_SCRIPT = `#!/usr/bin/env node
21
+ import { mkdir, readdir, readFile, rename, rm, writeFile } from "node:fs/promises";
22
+ import { dirname, join } from "node:path";
23
+ import { fileURLToPath } from "node:url";
24
+
25
+ const here = dirname(fileURLToPath(import.meta.url));
26
+ const workspace = dirname(here);
27
+
28
+ function safeKey(value) {
29
+ const trimmed = String(value ?? "").trim();
30
+ if (trimmed === "" || trimmed === "." || trimmed === "..") return "_empty";
31
+ const sanitized = trimmed
32
+ .replace(/[^a-zA-Z0-9._-]+/g, "_")
33
+ .replace(/^\\.+/, "")
34
+ .replace(/\\.+/g, "_")
35
+ .slice(0, 180);
36
+ if (sanitized === "" || sanitized === "." || sanitized === "..") return "_empty";
37
+ return sanitized;
38
+ }
39
+
40
+ async function readText(rel) {
41
+ try {
42
+ return (await readFile(join(workspace, rel), "utf8")).trim();
43
+ } catch {
44
+ return "";
45
+ }
46
+ }
47
+
48
+ async function main() {
49
+ const root = await readText(${JSON.stringify(SLACK_NUDGE_ROOT_REL)});
50
+ const continuation = await readText(
51
+ ${JSON.stringify(SLACK_NUDGE_CONTINUATION_REL)}
52
+ );
53
+ if (root === "" || continuation === "") {
54
+ process.stdout.write("{}\\n");
55
+ return;
56
+ }
57
+ const pendingDir = join(root, safeKey(continuation), "pending");
58
+ const deliveredDir = join(root, safeKey(continuation), "delivered");
59
+ let names = [];
60
+ try {
61
+ names = await readdir(pendingDir);
62
+ } catch {
63
+ process.stdout.write("{}\\n");
64
+ return;
65
+ }
66
+ const nudges = [];
67
+ await mkdir(deliveredDir, { recursive: true });
68
+ for (const name of names) {
69
+ if (!name.endsWith(".json")) continue;
70
+ const pendingPath = join(pendingDir, name);
71
+ let record;
72
+ try {
73
+ record = JSON.parse(await readFile(pendingPath, "utf8"));
74
+ } catch {
75
+ continue;
76
+ }
77
+ const sourceTs = typeof record.sourceTs === "string" ? record.sourceTs : "";
78
+ if (sourceTs === "") continue;
79
+ const dest = join(deliveredDir, safeKey(sourceTs));
80
+ try {
81
+ await readFile(dest, "utf8");
82
+ await rm(pendingPath, { force: true });
83
+ continue;
84
+ } catch {
85
+ // not delivered yet
86
+ }
87
+ const tmp = dest + "." + process.pid + ".tmp";
88
+ try {
89
+ await writeFile(tmp, JSON.stringify(record) + "\\n", "utf8");
90
+ await rename(tmp, dest);
91
+ await rm(pendingPath, { force: true });
92
+ nudges.push(record);
93
+ } catch {
94
+ await rm(tmp, { force: true }).catch(() => {});
95
+ await rm(pendingPath, { force: true }).catch(() => {});
96
+ }
97
+ }
98
+ if (nudges.length === 0) {
99
+ process.stdout.write("{}\\n");
100
+ return;
101
+ }
102
+ const lines = [
103
+ "<slack_followup>",
104
+ "New Slack follow-up(s) arrived while you were working. Incorporate them before your final reply. If an ask was already answered in-thread, ack briefly instead of re-answering.",
105
+ "",
106
+ ];
107
+ for (const nudge of nudges) {
108
+ const who =
109
+ typeof nudge.author === "string" && nudge.author !== ""
110
+ ? nudge.author
111
+ : "someone";
112
+ lines.push("- " + who + " @ " + nudge.sourceTs + ":");
113
+ lines.push(
114
+ typeof nudge.text === "string" && nudge.text.trim() !== ""
115
+ ? nudge.text.trim()
116
+ : "(empty)"
117
+ );
118
+ lines.push("");
119
+ }
120
+ lines.push("</slack_followup>");
121
+ process.stdout.write(
122
+ JSON.stringify({ additional_context: lines.join("\\n").trimEnd() }) + "\\n"
123
+ );
124
+ }
125
+
126
+ main().catch(() => {
127
+ process.stdout.write("{}\\n");
128
+ });
129
+ `;
130
+ /**
131
+ * Write carrier script + pointer files and ensure pre/postToolUse hooks invoke it.
132
+ * Safe to call every turn (idempotent overwrite of carrier + pointers).
133
+ */
134
+ export function materializeSlackNudgeCarrier(args) {
135
+ return __awaiter(this, void 0, void 0, function* () {
136
+ var _a, _b, _c;
137
+ if (args.continuationKey.trim() === "") {
138
+ return;
139
+ }
140
+ yield mkdir(join(args.harnessCwd, ".agent-serve"), { recursive: true });
141
+ yield mkdir(join(args.harnessCwd, ".cursor"), { recursive: true });
142
+ yield writeFile(join(args.harnessCwd, SLACK_NUDGE_ROOT_REL), `${args.nudgeRootDir}\n`, "utf8");
143
+ yield writeFile(join(args.harnessCwd, SLACK_NUDGE_CONTINUATION_REL), `${args.continuationKey}\n`, "utf8");
144
+ yield writeFile(join(args.harnessCwd, SLACK_NUDGE_CARRIER_REL), SLACK_NUDGE_CARRIER_SCRIPT, "utf8");
145
+ const hooksPath = join(args.harnessCwd, ".cursor", "hooks.json");
146
+ let existing = { version: 1, hooks: {} };
147
+ try {
148
+ existing = JSON.parse(yield readFile(hooksPath, "utf8"));
149
+ }
150
+ catch (_d) {
151
+ // fresh
152
+ }
153
+ const hooks = Object.assign({}, ((_a = existing.hooks) !== null && _a !== void 0 ? _a : {}));
154
+ const command = `node ${SLACK_NUDGE_CARRIER_REL}`;
155
+ for (const step of ["preToolUse", "postToolUse"]) {
156
+ const list = [...((_b = hooks[step]) !== null && _b !== void 0 ? _b : [])].filter((entry) => !entry.command.includes("slack-nudge-carrier"));
157
+ list.push({ command, failClosed: false });
158
+ hooks[step] = list;
159
+ }
160
+ const next = {
161
+ version: (_c = existing.version) !== null && _c !== void 0 ? _c : 1,
162
+ hooks,
163
+ };
164
+ yield writeFile(hooksPath, `${JSON.stringify(next, null, 2)}\n`, "utf8");
165
+ });
166
+ }
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Durable Slack follow-up nudge store (Benny-style).
3
+ *
4
+ * Mid-turn inject and boundary resume share one exactly-once contract:
5
+ * pending nudges rename into delivered/ keyed by source message ts.
6
+ */
7
+ export interface SlackNudgeRecord {
8
+ id: string;
9
+ continuationKey: string;
10
+ sourceTs: string;
11
+ text: string;
12
+ author?: string;
13
+ createdAt: string;
14
+ /** Content hash for pending dedupe. */
15
+ contentHash: string;
16
+ }
17
+ export interface SlackNudgeAppendInput {
18
+ continuationKey: string;
19
+ sourceTs: string;
20
+ text: string;
21
+ author?: string;
22
+ }
23
+ export declare function formatSlackFollowupNudgeBlock(nudges: readonly SlackNudgeRecord[]): string | undefined;
24
+ /**
25
+ * Filesystem nudge store under `<root>/<continuation>/pending|delivered`.
26
+ */
27
+ export declare class SlackNudgeStore {
28
+ private readonly rootDir;
29
+ constructor(rootDir: string);
30
+ private continuationDir;
31
+ private pendingDir;
32
+ private deliveredDir;
33
+ private deliveredPath;
34
+ append(input: SlackNudgeAppendInput): Promise<boolean>;
35
+ listPending(continuationKey: string): Promise<SlackNudgeRecord[]>;
36
+ isDelivered(continuationKey: string, sourceTs: string): Promise<boolean>;
37
+ hasUndelivered(continuationKey: string): Promise<boolean>;
38
+ /**
39
+ * Atomically move all pending nudges to delivered and return them.
40
+ * Already-delivered source ts values are dropped (exactly-once).
41
+ */
42
+ drainForInject(continuationKey: string): Promise<SlackNudgeRecord[]>;
43
+ clear(continuationKey: string): Promise<void>;
44
+ /** Drain + format for tool/hook inject. */
45
+ drainFormatted(continuationKey: string): Promise<string | undefined>;
46
+ }
47
+ /**
48
+ * Durable ask claim store: one marker per `channelId:message.ts` so delayed
49
+ * Slack redelivery cannot start a second full answer.
50
+ */
51
+ export declare class SlackAskDedupeStore {
52
+ private readonly rootDir;
53
+ constructor(rootDir: string);
54
+ private markerPath;
55
+ /** Returns true the first time this ask is claimed. */
56
+ tryClaim(channelId: string, messageTs: string): Promise<boolean>;
57
+ /** Drop a claim so a failed delivery can be retried. */
58
+ release(channelId: string, messageTs: string): Promise<void>;
59
+ wasClaimed(channelId: string, messageTs: string): Promise<boolean>;
60
+ }
61
+ //# sourceMappingURL=nudge-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nudge-store.d.ts","sourceRoot":"","sources":["../../../src/channels/slack/nudge-store.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAaH,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,uCAAuC;IACvC,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,qBAAqB;IACpC,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AA+BD,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,SAAS,gBAAgB,EAAE,GAClC,MAAM,GAAG,SAAS,CAoBpB;AAED;;GAEG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IAEjC,YAAY,OAAO,EAAE,MAAM,EAE1B;IAED,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,aAAa;IAIf,MAAM,CAAC,KAAK,EAAE,qBAAqB,GAAG,OAAO,CAAC,OAAO,CAAC,CAqC3D;IAEK,WAAW,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CA6BtE;IAEK,WAAW,CACf,eAAe,EAAE,MAAM,EACvB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,OAAO,CAAC,CAUlB;IAEK,cAAc,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAE9D;IAED;;;OAGG;IACG,cAAc,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CA8BzE;IAEK,KAAK,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAKlD;IAED,2CAA2C;IACrC,cAAc,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAIzE;CACF;AAED;;;GAGG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IAEjC,YAAY,OAAO,EAAE,MAAM,EAE1B;IAED,OAAO,CAAC,UAAU;IAOlB,uDAAuD;IACjD,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAerE;IAED,wDAAwD;IAClD,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAKjE;IAEK,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOvE;CACF"}