@urateam/core 0.1.30 → 0.1.32

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 (113) hide show
  1. package/dist/__tests__/agent-stream.test.js +35 -1
  2. package/dist/__tests__/agent-stream.test.js.map +1 -1
  3. package/dist/__tests__/bec-185-reproduce.test.d.ts +16 -0
  4. package/dist/__tests__/bec-185-reproduce.test.d.ts.map +1 -0
  5. package/dist/__tests__/bec-185-reproduce.test.js +16 -0
  6. package/dist/__tests__/bec-185-reproduce.test.js.map +1 -0
  7. package/dist/__tests__/control-signals.test.d.ts +2 -0
  8. package/dist/__tests__/control-signals.test.d.ts.map +1 -0
  9. package/dist/__tests__/control-signals.test.js +77 -0
  10. package/dist/__tests__/control-signals.test.js.map +1 -0
  11. package/dist/__tests__/gh-linear-sync.test.js +57 -2
  12. package/dist/__tests__/gh-linear-sync.test.js.map +1 -1
  13. package/dist/__tests__/openrouter-client.test.js +34 -0
  14. package/dist/__tests__/openrouter-client.test.js.map +1 -1
  15. package/dist/__tests__/pm-slack-interface.test.js +45 -0
  16. package/dist/__tests__/pm-slack-interface.test.js.map +1 -1
  17. package/dist/__tests__/pm-triage.test.js +101 -0
  18. package/dist/__tests__/pm-triage.test.js.map +1 -1
  19. package/dist/__tests__/util-linear.test.d.ts +10 -0
  20. package/dist/__tests__/util-linear.test.d.ts.map +1 -0
  21. package/dist/__tests__/util-linear.test.js +244 -0
  22. package/dist/__tests__/util-linear.test.js.map +1 -0
  23. package/dist/audit/events.d.ts +24 -0
  24. package/dist/audit/events.d.ts.map +1 -1
  25. package/dist/audit/events.js +32 -0
  26. package/dist/audit/events.js.map +1 -1
  27. package/dist/executor/agent-stream.d.ts +16 -0
  28. package/dist/executor/agent-stream.d.ts.map +1 -1
  29. package/dist/executor/agent-stream.js +43 -1
  30. package/dist/executor/agent-stream.js.map +1 -1
  31. package/dist/executor/executor.d.ts.map +1 -1
  32. package/dist/executor/executor.js +24 -5
  33. package/dist/executor/executor.js.map +1 -1
  34. package/dist/executor/review/openrouter-client.d.ts.map +1 -1
  35. package/dist/executor/review/openrouter-client.js +8 -0
  36. package/dist/executor/review/openrouter-client.js.map +1 -1
  37. package/dist/index.d.ts +1 -0
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.js +1 -0
  40. package/dist/index.js.map +1 -1
  41. package/dist/notifier/linear.d.ts +0 -1
  42. package/dist/notifier/linear.d.ts.map +1 -1
  43. package/dist/notifier/linear.js +2 -5
  44. package/dist/notifier/linear.js.map +1 -1
  45. package/dist/pipeline/control-signals.d.ts +49 -0
  46. package/dist/pipeline/control-signals.d.ts.map +1 -0
  47. package/dist/pipeline/control-signals.js +93 -0
  48. package/dist/pipeline/control-signals.js.map +1 -0
  49. package/dist/pipeline/feedback-pipeline.d.ts +140 -0
  50. package/dist/pipeline/feedback-pipeline.d.ts.map +1 -0
  51. package/dist/pipeline/feedback-pipeline.js +427 -0
  52. package/dist/pipeline/feedback-pipeline.js.map +1 -0
  53. package/dist/pipeline/index.d.ts +1 -0
  54. package/dist/pipeline/index.d.ts.map +1 -1
  55. package/dist/pipeline/index.js +1 -0
  56. package/dist/pipeline/index.js.map +1 -1
  57. package/dist/pipeline/runner.d.ts +49 -33
  58. package/dist/pipeline/runner.d.ts.map +1 -1
  59. package/dist/pipeline/runner.js +136 -349
  60. package/dist/pipeline/runner.js.map +1 -1
  61. package/dist/pm/actions/promote.d.ts.map +1 -1
  62. package/dist/pm/actions/promote.js +15 -11
  63. package/dist/pm/actions/promote.js.map +1 -1
  64. package/dist/pm/actions/recover-stuck.d.ts.map +1 -1
  65. package/dist/pm/actions/recover-stuck.js +9 -5
  66. package/dist/pm/actions/recover-stuck.js.map +1 -1
  67. package/dist/pm/actions/triage.d.ts.map +1 -1
  68. package/dist/pm/actions/triage.js +67 -1
  69. package/dist/pm/actions/triage.js.map +1 -1
  70. package/dist/pm/linear-helpers.d.ts +10 -0
  71. package/dist/pm/linear-helpers.d.ts.map +1 -1
  72. package/dist/pm/linear-helpers.js +13 -21
  73. package/dist/pm/linear-helpers.js.map +1 -1
  74. package/dist/pm/pause-state.d.ts +29 -0
  75. package/dist/pm/pause-state.d.ts.map +1 -0
  76. package/dist/pm/pause-state.js +34 -0
  77. package/dist/pm/pause-state.js.map +1 -0
  78. package/dist/pm/slack-bulk.d.ts +34 -0
  79. package/dist/pm/slack-bulk.d.ts.map +1 -0
  80. package/dist/pm/slack-bulk.js +110 -0
  81. package/dist/pm/slack-bulk.js.map +1 -0
  82. package/dist/pm/slack-commands.d.ts +101 -0
  83. package/dist/pm/slack-commands.d.ts.map +1 -0
  84. package/dist/pm/slack-commands.js +309 -0
  85. package/dist/pm/slack-commands.js.map +1 -0
  86. package/dist/pm/slack-helpers.d.ts +10 -0
  87. package/dist/pm/slack-helpers.d.ts.map +1 -1
  88. package/dist/pm/slack-helpers.js +32 -0
  89. package/dist/pm/slack-helpers.js.map +1 -1
  90. package/dist/pm/slack-interface.d.ts +32 -58
  91. package/dist/pm/slack-interface.d.ts.map +1 -1
  92. package/dist/pm/slack-interface.js +150 -320
  93. package/dist/pm/slack-interface.js.map +1 -1
  94. package/dist/rbac/matrix.d.ts +2 -0
  95. package/dist/rbac/matrix.d.ts.map +1 -1
  96. package/dist/rbac/matrix.js +2 -0
  97. package/dist/rbac/matrix.js.map +1 -1
  98. package/dist/server.d.ts.map +1 -1
  99. package/dist/server.js +7 -0
  100. package/dist/server.js.map +1 -1
  101. package/dist/sync/gh-linear-sync.d.ts +5 -1
  102. package/dist/sync/gh-linear-sync.d.ts.map +1 -1
  103. package/dist/sync/gh-linear-sync.js +104 -44
  104. package/dist/sync/gh-linear-sync.js.map +1 -1
  105. package/dist/types.d.ts +13 -4
  106. package/dist/types.d.ts.map +1 -1
  107. package/dist/types.js +6 -0
  108. package/dist/types.js.map +1 -1
  109. package/dist/util/linear.d.ts +70 -0
  110. package/dist/util/linear.d.ts.map +1 -0
  111. package/dist/util/linear.js +108 -0
  112. package/dist/util/linear.js.map +1 -0
  113. package/package.json +1 -1
@@ -0,0 +1,309 @@
1
+ /**
2
+ * PM Agent — Slack command execution.
3
+ *
4
+ * Responsibility: execute a parsed `PmCommand` against the Linear API and return
5
+ * a human-readable response string suitable for posting back to Slack.
6
+ *
7
+ * Extracted from `slack-interface.ts` (BEC-195). The previous implementation
8
+ * accessed `isPmPaused` / `setPmPaused` as module-level closures within
9
+ * `slack-interface.ts`. After the split those functions live in `pause-state.ts`
10
+ * and are imported explicitly here, making the dependency transparent and
11
+ * avoiding a circular import (slack-interface → slack-commands → slack-interface).
12
+ */
13
+ import { createLogger } from "../logger.js";
14
+ import { createLazyLinearClient } from "./linear-helpers.js";
15
+ import { analyzeBulkCreateRequest } from "./slack-bulk.js";
16
+ import { isPmPaused, setPmPaused } from "./pause-state.js";
17
+ const log = createLogger({ component: "PmAgent:slack-commands" });
18
+ // ---------------------------------------------------------------------------
19
+ // Constants
20
+ // ---------------------------------------------------------------------------
21
+ /** Linear workflow state name for the Triage column. */
22
+ const LINEAR_STATE_TRIAGE = "Triage";
23
+ /** Linear workflow state name for the Todo column. */
24
+ const LINEAR_STATE_TODO = "Todo";
25
+ /** Linear label name that triggers the auto-implement pipeline. */
26
+ const LINEAR_LABEL_AUTO_IMPLEMENT = "auto-implement";
27
+ // ---------------------------------------------------------------------------
28
+ // Private validation helpers
29
+ // ---------------------------------------------------------------------------
30
+ /**
31
+ * Returns an error message string when `deps.linearApiKey` is missing or empty,
32
+ * or `null` when a key is present. Callers should check and return early:
33
+ * const err = validateLinearApiKey(deps); if (err) return err;
34
+ */
35
+ function validateLinearApiKey(deps) {
36
+ return deps.linearApiKey
37
+ ? null
38
+ : `⚠️ No Linear API key configured — please set \`linearApiKey\` in your PM Agent config.`;
39
+ }
40
+ /**
41
+ * Returns an error message string when `deps.teamIds` is missing or empty,
42
+ * or `null` when team IDs are present.
43
+ */
44
+ function validateTeamIds(deps) {
45
+ return deps.teamIds && deps.teamIds.length > 0
46
+ ? null
47
+ : `⚠️ No team IDs configured — please set \`teamIds\` in your PM Agent config.`;
48
+ }
49
+ // ---------------------------------------------------------------------------
50
+ // Public API
51
+ // ---------------------------------------------------------------------------
52
+ /**
53
+ * Executes a parsed `PmCommand` against Linear and returns a human-readable
54
+ * response string suitable for posting back to Slack.
55
+ *
56
+ * Design note — implicit state access: the `pause` / `resume` / `status`
57
+ * command cases call `isPmPaused()` and `setPmPaused()` from `pause-state.ts`.
58
+ * These functions are now explicit imports rather than closures over outer module
59
+ * state (as they were when this logic lived in `slack-interface.ts`). The
60
+ * dependency is intentional and transparent — the pause flag is process-scoped
61
+ * shared state that must be the same instance for both command execution and the
62
+ * scheduler's `isPmPaused()` check.
63
+ *
64
+ * @param cmd - A structured `PmCommand` (output of `parsePmCommand` or
65
+ * `interpretNaturalLanguage`).
66
+ * @param deps - External service dependencies (Linear API key, team IDs,
67
+ * optional Sonnet callable for bulk create).
68
+ * @returns A Slack-formatted response string (may contain mrkdwn markup).
69
+ */
70
+ export async function executePmCommand(cmd, deps) {
71
+ const { getClient: getLinear } = createLazyLinearClient(deps.linearApiKey);
72
+ /**
73
+ * Searches Linear for an issue by its identifier (e.g. "BEC-25") and returns
74
+ * the first match, or `null` when not found. Shared by prioritize + assign.
75
+ */
76
+ async function findIssueByIdentifier(linear, issueId) {
77
+ const results = await linear.searchIssues(issueId);
78
+ return results.nodes?.[0] ?? null;
79
+ }
80
+ switch (cmd.type) {
81
+ case "status": {
82
+ const state = isPmPaused() ? "⏸ *Paused*" : "▶️ *Running*";
83
+ return `PM Agent is ${state}.\nUse \`/pm pause\` or \`/pm resume\` to control autonomous assignment.`;
84
+ }
85
+ case "pause": {
86
+ setPmPaused(true);
87
+ log.info("PM Agent paused via Slack");
88
+ return "⏸ PM Agent autonomous assignment has been *paused*. Use `/pm resume` to restart.";
89
+ }
90
+ case "resume": {
91
+ setPmPaused(false);
92
+ log.info("PM Agent resumed via Slack");
93
+ return "▶️ PM Agent autonomous assignment has been *resumed*.";
94
+ }
95
+ case "cancel":
96
+ case "stop": {
97
+ if (!deps.runner?.requestStop) {
98
+ return `⚠️ Runner not configured — cannot ${cmd.type} run *${cmd.runId}*.`;
99
+ }
100
+ const mode = cmd.type === "cancel" ? "cancel" : "graceful";
101
+ const { issueId } = deps.runner.requestStop(cmd.runId, mode);
102
+ if (deps.db) {
103
+ const { logAuditEvent, runCancelledEvent } = await import("../audit/index.js");
104
+ void logAuditEvent(deps.db, runCancelledEvent({
105
+ runId: cmd.runId,
106
+ issueId: issueId ?? "(unknown)",
107
+ actor: `slack:${deps.slackUserId ?? "unknown"}`,
108
+ actorType: "slack",
109
+ mode,
110
+ }));
111
+ }
112
+ log.info({ runId: cmd.runId, mode, slackUserId: deps.slackUserId }, "run stop requested via Slack");
113
+ return mode === "cancel"
114
+ ? `🛑 Cancel signal sent to run *${cmd.runId}*. The active stage will abort within a few seconds.`
115
+ : `⏹ Graceful stop requested for run *${cmd.runId}*. The current stage will finish, then the pipeline will stop.`;
116
+ }
117
+ case "halt": {
118
+ if (!deps.runner?.haltAll) {
119
+ return "⚠️ Runner not configured — cannot halt.";
120
+ }
121
+ const { cancelledRunIds } = deps.runner.haltAll();
122
+ if (deps.db) {
123
+ const { logAuditEvent, systemHaltedEvent, runCancelledEvent } = await import("../audit/index.js");
124
+ void logAuditEvent(deps.db, systemHaltedEvent({
125
+ actor: `slack:${deps.slackUserId ?? "unknown"}`,
126
+ actorType: "slack",
127
+ cancelledRunIds,
128
+ }));
129
+ for (const rid of cancelledRunIds) {
130
+ void logAuditEvent(deps.db, runCancelledEvent({
131
+ runId: rid,
132
+ issueId: "(halt)",
133
+ actor: `slack:${deps.slackUserId ?? "unknown"}`,
134
+ actorType: "slack",
135
+ mode: "cancel",
136
+ reason: "system.halt",
137
+ }));
138
+ }
139
+ }
140
+ log.warn({ count: cancelledRunIds.length, slackUserId: deps.slackUserId }, "container halt requested via Slack");
141
+ return `🚨 *Halted.* PM Agent paused; cancelled ${cancelledRunIds.length} active run(s). Use \`/pm resume\` when ready.`;
142
+ }
143
+ case "prioritize": {
144
+ const keyErr = validateLinearApiKey(deps);
145
+ if (keyErr)
146
+ return keyErr;
147
+ try {
148
+ const linear = await getLinear();
149
+ if (!linear)
150
+ return `⚠️ Linear client could not be initialised — cannot prioritize *${cmd.issueId}*.`;
151
+ const issue = await findIssueByIdentifier(linear, cmd.issueId);
152
+ if (!issue)
153
+ return `⚠️ Issue *${cmd.issueId}* not found in Linear.`;
154
+ // updateIssue and createComment are independent — run in parallel
155
+ await Promise.all([
156
+ linear.updateIssue(issue.id, { priority: 1 }),
157
+ linear.createComment({
158
+ issueId: issue.id,
159
+ body: "🤖 **PM Agent** — Bumped to top of queue via Slack command.",
160
+ }),
161
+ ]);
162
+ log.info({ issueId: cmd.issueId }, "prioritized via Slack");
163
+ return `✅ *${cmd.issueId}* has been bumped to top priority (Urgent).`;
164
+ }
165
+ catch (err) {
166
+ log.error({ err, issueId: cmd.issueId }, "prioritize failed");
167
+ return `❌ Failed to prioritize *${cmd.issueId}*: ${err.message}`;
168
+ }
169
+ }
170
+ case "assign": {
171
+ const keyErr = validateLinearApiKey(deps);
172
+ if (keyErr)
173
+ return keyErr;
174
+ try {
175
+ const linear = await getLinear();
176
+ if (!linear)
177
+ return `⚠️ Linear client could not be initialised — cannot assign *${cmd.issueId}*.`;
178
+ const issue = await findIssueByIdentifier(linear, cmd.issueId);
179
+ if (!issue)
180
+ return `⚠️ Issue *${cmd.issueId}* not found in Linear.`;
181
+ const team = await issue.team;
182
+ const allStates = await linear.workflowStates({
183
+ filter: { team: { id: { eq: team?.id } } },
184
+ first: 50,
185
+ });
186
+ const todoState = allStates.nodes?.find((s) => s.name === LINEAR_STATE_TODO);
187
+ if (!todoState)
188
+ return `⚠️ No "${LINEAR_STATE_TODO}" state found for *${cmd.issueId}*'s team.`;
189
+ await linear.updateIssue(issue.id, { stateId: todoState.id });
190
+ await linear.createComment({
191
+ issueId: issue.id,
192
+ body: "🤖 **PM Agent** — Manually assigned to Todo via Slack command.",
193
+ });
194
+ log.info({ issueId: cmd.issueId }, "manually assigned to Todo via Slack");
195
+ return `✅ *${cmd.issueId}* has been moved to Todo.`;
196
+ }
197
+ catch (err) {
198
+ log.error({ err, issueId: cmd.issueId }, "assign failed");
199
+ return `❌ Failed to assign *${cmd.issueId}*: ${err.message}`;
200
+ }
201
+ }
202
+ case "create": {
203
+ const keyErr = validateLinearApiKey(deps);
204
+ if (keyErr)
205
+ return keyErr;
206
+ const teamErr = validateTeamIds(deps);
207
+ if (teamErr)
208
+ return teamErr;
209
+ try {
210
+ const linear = await getLinear();
211
+ if (!linear)
212
+ return `⚠️ Linear client could not be initialised — cannot create issue.`;
213
+ const created = await linear.createIssue({
214
+ // deps.teamIds is guaranteed non-empty by validateTeamIds above.
215
+ teamId: deps.teamIds[0],
216
+ title: cmd.title,
217
+ description: cmd.description || undefined,
218
+ });
219
+ const issue = await created.issue;
220
+ const url = issue?.url ?? "";
221
+ log.info({ title: cmd.title, issueId: issue?.identifier }, "issue created via Slack");
222
+ return `✅ Created <${url}|${issue?.identifier ?? "new issue"}>: *${cmd.title}*`;
223
+ }
224
+ catch (err) {
225
+ log.error({ err, title: cmd.title }, "create issue failed");
226
+ return `❌ Failed to create issue: ${err.message}`;
227
+ }
228
+ }
229
+ case "bulk_create": {
230
+ const keyErr = validateLinearApiKey(deps);
231
+ if (keyErr)
232
+ return keyErr;
233
+ const teamErr = validateTeamIds(deps);
234
+ if (teamErr)
235
+ return teamErr;
236
+ if (!deps.callClaudeSonnet) {
237
+ return `⚠️ Bulk create requires a Sonnet model caller — not configured.`;
238
+ }
239
+ try {
240
+ const specs = await analyzeBulkCreateRequest(cmd.request, deps.callClaudeSonnet);
241
+ if (specs.length === 0) {
242
+ return `🤔 Could not generate any issues from your request. Try being more specific.`;
243
+ }
244
+ const linear = await getLinear();
245
+ if (!linear)
246
+ return `⚠️ Linear client could not be initialised — cannot create issues.`;
247
+ // Resolve the Triage state and auto-implement label IDs.
248
+ // deps.teamIds is guaranteed non-empty by validateTeamIds above.
249
+ const teamId = deps.teamIds[0];
250
+ const [allStatesRes, allLabelsRes] = await Promise.all([
251
+ linear.workflowStates({ filter: { team: { id: { eq: teamId } } }, first: 50 }),
252
+ linear.issueLabels({ first: 100 }),
253
+ ]);
254
+ const triageState = allStatesRes.nodes?.find((s) => s.name === LINEAR_STATE_TRIAGE);
255
+ const labelMap = new Map();
256
+ for (const label of allLabelsRes.nodes ?? []) {
257
+ labelMap.set(label.name.toLowerCase(), label.id);
258
+ }
259
+ const autoImplementLabelId = labelMap.get(LINEAR_LABEL_AUTO_IMPLEMENT);
260
+ // Build all payloads first, then create all issues in parallel
261
+ const payloads = specs.map((spec) => {
262
+ const descWithCriteria = spec.acceptanceCriteria.length > 0
263
+ ? `${spec.description}\n\n**Acceptance Criteria:**\n${spec.acceptanceCriteria.map((c) => `- [ ] ${c}`).join("\n")}`
264
+ : spec.description;
265
+ const payload = {
266
+ teamId,
267
+ title: spec.title,
268
+ description: descWithCriteria || undefined,
269
+ priority: spec.priority,
270
+ };
271
+ if (triageState)
272
+ payload.stateId = triageState.id;
273
+ if (autoImplementLabelId)
274
+ payload.labelIds = [autoImplementLabelId];
275
+ return payload;
276
+ });
277
+ const results = await Promise.all(payloads.map((p) => linear.createIssue(p)));
278
+ const issueObjects = await Promise.all(results.map((r) => r.issue));
279
+ const created = [];
280
+ for (let i = 0; i < issueObjects.length; i++) {
281
+ const issue = issueObjects[i];
282
+ if (issue) {
283
+ const title = specs[i].title;
284
+ created.push({ identifier: issue.identifier ?? "", url: issue.url ?? "", title });
285
+ log.info({ issueId: issue.identifier, title }, "bulk issue created via Slack");
286
+ }
287
+ }
288
+ if (created.length === 0) {
289
+ return `❌ Failed to create any issues.`;
290
+ }
291
+ const lines = [`✅ Created ${created.length} issue${created.length === 1 ? "" : "s"}:`];
292
+ for (const issue of created) {
293
+ const link = issue.url ? `<${issue.url}|${issue.identifier}>` : `*${issue.identifier}*`;
294
+ lines.push(`• ${link}: *${issue.title}*`);
295
+ }
296
+ return lines.join("\n");
297
+ }
298
+ catch (err) {
299
+ log.error({ err, request: cmd.request }, "bulk create failed");
300
+ return `❌ Failed to create issues: ${err.message}`;
301
+ }
302
+ }
303
+ case "unknown":
304
+ return `🤔 I didn't understand that. Try:\n• \`/pm status\`\n• \`/pm prioritize BEC-25\`\n• \`/pm create "title" "description"\`\n• \`/pm assign BEC-13\`\n• \`/pm pause\` / \`/pm resume\`\n• \`/pm cancel <runId>\` (interrupt immediately) / \`/pm stop <runId>\` (graceful)\n• \`/pm halt\` (pause PM + cancel all active runs)`;
305
+ default:
306
+ return `Unknown command.`;
307
+ }
308
+ }
309
+ //# sourceMappingURL=slack-commands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slack-commands.js","sourceRoot":"","sources":["../../src/pm/slack-commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE3D,MAAM,GAAG,GAAG,YAAY,CAAC,EAAE,SAAS,EAAE,wBAAwB,EAAE,CAAC,CAAC;AAElE,8EAA8E;AAC9E,YAAY;AACZ,8EAA8E;AAE9E,wDAAwD;AACxD,MAAM,mBAAmB,GAAG,QAAQ,CAAC;AACrC,sDAAsD;AACtD,MAAM,iBAAiB,GAAG,MAAM,CAAC;AACjC,mEAAmE;AACnE,MAAM,2BAA2B,GAAG,gBAAgB,CAAC;AAiErD,8EAA8E;AAC9E,6BAA6B;AAC7B,8EAA8E;AAE9E;;;;GAIG;AACH,SAAS,oBAAoB,CAAC,IAAyB;IACrD,OAAO,IAAI,CAAC,YAAY;QACtB,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,wFAAwF,CAAC;AAC/F,CAAC;AAED;;;GAGG;AACH,SAAS,eAAe,CAAC,IAAyB;IAChD,OAAO,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;QAC5C,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,6EAA6E,CAAC;AACpF,CAAC;AAED,8EAA8E;AAC9E,aAAa;AACb,8EAA8E;AAE9E;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,GAAc,EACd,IAAyB;IAEzB,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,sBAAsB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAE3E;;;OAGG;IACH,KAAK,UAAU,qBAAqB,CAAC,MAAW,EAAE,OAAe;QAC/D,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;QACnD,OAAO,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;IACpC,CAAC;IAED,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;QACjB,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,KAAK,GAAG,UAAU,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,cAAc,CAAC;YAC3D,OAAO,eAAe,KAAK,0EAA0E,CAAC;QACxG,CAAC;QAED,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,WAAW,CAAC,IAAI,CAAC,CAAC;YAClB,GAAG,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;YACtC,OAAO,kFAAkF,CAAC;QAC5F,CAAC;QAED,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,WAAW,CAAC,KAAK,CAAC,CAAC;YACnB,GAAG,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;YACvC,OAAO,uDAAuD,CAAC;QACjE,CAAC;QAED,KAAK,QAAQ,CAAC;QACd,KAAK,MAAM,CAAC,CAAC,CAAC;YACZ,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC;gBAC9B,OAAO,qCAAqC,GAAG,CAAC,IAAI,SAAS,GAAG,CAAC,KAAK,IAAI,CAAC;YAC7E,CAAC;YACD,MAAM,IAAI,GAA0B,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC;YAClF,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;YAC7D,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC;gBACZ,MAAM,EAAE,aAAa,EAAE,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC;gBAC/E,KAAK,aAAa,CAChB,IAAI,CAAC,EAAE,EACP,iBAAiB,CAAC;oBAChB,KAAK,EAAE,GAAG,CAAC,KAAK;oBAChB,OAAO,EAAE,OAAO,IAAI,WAAW;oBAC/B,KAAK,EAAE,SAAS,IAAI,CAAC,WAAW,IAAI,SAAS,EAAE;oBAC/C,SAAS,EAAE,OAAO;oBAClB,IAAI;iBACL,CAAC,CACH,CAAC;YACJ,CAAC;YACD,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,EAAE,8BAA8B,CAAC,CAAC;YACpG,OAAO,IAAI,KAAK,QAAQ;gBACtB,CAAC,CAAC,iCAAiC,GAAG,CAAC,KAAK,sDAAsD;gBAClG,CAAC,CAAC,sCAAsC,GAAG,CAAC,KAAK,gEAAgE,CAAC;QACtH,CAAC;QAED,KAAK,MAAM,CAAC,CAAC,CAAC;YACZ,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;gBAC1B,OAAO,yCAAyC,CAAC;YACnD,CAAC;YACD,MAAM,EAAE,eAAe,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YAClD,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC;gBACZ,MAAM,EAAE,aAAa,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC;gBAClG,KAAK,aAAa,CAChB,IAAI,CAAC,EAAE,EACP,iBAAiB,CAAC;oBAChB,KAAK,EAAE,SAAS,IAAI,CAAC,WAAW,IAAI,SAAS,EAAE;oBAC/C,SAAS,EAAE,OAAO;oBAClB,eAAe;iBAChB,CAAC,CACH,CAAC;gBACF,KAAK,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;oBAClC,KAAK,aAAa,CAChB,IAAI,CAAC,EAAE,EACP,iBAAiB,CAAC;wBAChB,KAAK,EAAE,GAAG;wBACV,OAAO,EAAE,QAAQ;wBACjB,KAAK,EAAE,SAAS,IAAI,CAAC,WAAW,IAAI,SAAS,EAAE;wBAC/C,SAAS,EAAE,OAAO;wBAClB,IAAI,EAAE,QAAQ;wBACd,MAAM,EAAE,aAAa;qBACtB,CAAC,CACH,CAAC;gBACJ,CAAC;YACH,CAAC;YACD,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,EAAE,oCAAoC,CAAC,CAAC;YACjH,OAAO,2CAA2C,eAAe,CAAC,MAAM,gDAAgD,CAAC;QAC3H,CAAC;QAED,KAAK,YAAY,CAAC,CAAC,CAAC;YAClB,MAAM,MAAM,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;YAC1C,IAAI,MAAM;gBAAE,OAAO,MAAM,CAAC;YAC1B,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAC;gBACjC,IAAI,CAAC,MAAM;oBAAE,OAAO,kEAAkE,GAAG,CAAC,OAAO,IAAI,CAAC;gBACtG,MAAM,KAAK,GAAG,MAAM,qBAAqB,CAAC,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;gBAC/D,IAAI,CAAC,KAAK;oBAAE,OAAO,aAAa,GAAG,CAAC,OAAO,wBAAwB,CAAC;gBACpE,kEAAkE;gBAClE,MAAM,OAAO,CAAC,GAAG,CAAC;oBAChB,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;oBAC7C,MAAM,CAAC,aAAa,CAAC;wBACnB,OAAO,EAAE,KAAK,CAAC,EAAE;wBACjB,IAAI,EAAE,6DAA6D;qBACpE,CAAC;iBACH,CAAC,CAAC;gBACH,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,EAAE,uBAAuB,CAAC,CAAC;gBAC5D,OAAO,MAAM,GAAG,CAAC,OAAO,6CAA6C,CAAC;YACxE,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,EAAE,mBAAmB,CAAC,CAAC;gBAC9D,OAAO,2BAA2B,GAAG,CAAC,OAAO,MAAO,GAAa,CAAC,OAAO,EAAE,CAAC;YAC9E,CAAC;QACH,CAAC;QAED,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,MAAM,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;YAC1C,IAAI,MAAM;gBAAE,OAAO,MAAM,CAAC;YAC1B,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAC;gBACjC,IAAI,CAAC,MAAM;oBAAE,OAAO,8DAA8D,GAAG,CAAC,OAAO,IAAI,CAAC;gBAClG,MAAM,KAAK,GAAG,MAAM,qBAAqB,CAAC,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;gBAC/D,IAAI,CAAC,KAAK;oBAAE,OAAO,aAAa,GAAG,CAAC,OAAO,wBAAwB,CAAC;gBAEpE,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC;gBAC9B,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC;oBAC5C,MAAM,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE;oBAC1C,KAAK,EAAE,EAAE;iBACV,CAAC,CAAC;gBACH,MAAM,SAAS,GAAG,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,iBAAiB,CAAC,CAAC;gBAClF,IAAI,CAAC,SAAS;oBAAE,OAAO,UAAU,iBAAiB,sBAAsB,GAAG,CAAC,OAAO,WAAW,CAAC;gBAE/F,MAAM,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,EAAE,CAAC,CAAC;gBAC9D,MAAM,MAAM,CAAC,aAAa,CAAC;oBACzB,OAAO,EAAE,KAAK,CAAC,EAAE;oBACjB,IAAI,EAAE,gEAAgE;iBACvE,CAAC,CAAC;gBACH,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,EAAE,qCAAqC,CAAC,CAAC;gBAC1E,OAAO,MAAM,GAAG,CAAC,OAAO,2BAA2B,CAAC;YACtD,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,EAAE,eAAe,CAAC,CAAC;gBAC1D,OAAO,uBAAuB,GAAG,CAAC,OAAO,MAAO,GAAa,CAAC,OAAO,EAAE,CAAC;YAC1E,CAAC;QACH,CAAC;QAED,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,MAAM,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;YAC1C,IAAI,MAAM;gBAAE,OAAO,MAAM,CAAC;YAC1B,MAAM,OAAO,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;YACtC,IAAI,OAAO;gBAAE,OAAO,OAAO,CAAC;YAC5B,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAC;gBACjC,IAAI,CAAC,MAAM;oBAAE,OAAO,kEAAkE,CAAC;gBACvF,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC;oBACvC,iEAAiE;oBACjE,MAAM,EAAE,IAAI,CAAC,OAAQ,CAAC,CAAC,CAAC;oBACxB,KAAK,EAAE,GAAG,CAAC,KAAK;oBAChB,WAAW,EAAE,GAAG,CAAC,WAAW,IAAI,SAAS;iBAC1C,CAAC,CAAC;gBACH,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC;gBAClC,MAAM,GAAG,GAAG,KAAK,EAAE,GAAG,IAAI,EAAE,CAAC;gBAC7B,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,yBAAyB,CAAC,CAAC;gBACtF,OAAO,cAAc,GAAG,IAAI,KAAK,EAAE,UAAU,IAAI,WAAW,OAAO,GAAG,CAAC,KAAK,GAAG,CAAC;YAClF,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,EAAE,qBAAqB,CAAC,CAAC;gBAC5D,OAAO,6BAA8B,GAAa,CAAC,OAAO,EAAE,CAAC;YAC/D,CAAC;QACH,CAAC;QAED,KAAK,aAAa,CAAC,CAAC,CAAC;YACnB,MAAM,MAAM,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;YAC1C,IAAI,MAAM;gBAAE,OAAO,MAAM,CAAC;YAC1B,MAAM,OAAO,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;YACtC,IAAI,OAAO;gBAAE,OAAO,OAAO,CAAC;YAC5B,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBAC3B,OAAO,iEAAiE,CAAC;YAC3E,CAAC;YACD,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,MAAM,wBAAwB,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;gBACjF,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACvB,OAAO,8EAA8E,CAAC;gBACxF,CAAC;gBAED,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAC;gBACjC,IAAI,CAAC,MAAM;oBAAE,OAAO,mEAAmE,CAAC;gBAExF,yDAAyD;gBACzD,iEAAiE;gBACjE,MAAM,MAAM,GAAG,IAAI,CAAC,OAAQ,CAAC,CAAC,CAAC,CAAC;gBAChC,MAAM,CAAC,YAAY,EAAE,YAAY,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;oBACrD,MAAM,CAAC,cAAc,CAAC,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;oBAC9E,MAAM,CAAC,WAAW,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;iBACnC,CAAC,CAAC;gBACH,MAAM,WAAW,GAAG,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,mBAAmB,CAAC,CAAC;gBACzF,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAkB,CAAC;gBAC3C,KAAK,MAAM,KAAK,IAAI,YAAY,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC;oBAC7C,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;gBACnD,CAAC;gBACD,MAAM,oBAAoB,GAAG,QAAQ,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;gBAEvE,+DAA+D;gBAC/D,MAAM,QAAQ,GAA6B,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;oBAC5D,MAAM,gBAAgB,GACpB,IAAI,CAAC,kBAAkB,CAAC,MAAM,GAAG,CAAC;wBAChC,CAAC,CAAC,GAAG,IAAI,CAAC,WAAW,iCAAiC,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;wBACnH,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC;oBAEvB,MAAM,OAAO,GAA2B;wBACtC,MAAM;wBACN,KAAK,EAAE,IAAI,CAAC,KAAK;wBACjB,WAAW,EAAE,gBAAgB,IAAI,SAAS;wBAC1C,QAAQ,EAAE,IAAI,CAAC,QAAQ;qBACxB,CAAC;oBACF,IAAI,WAAW;wBAAE,OAAO,CAAC,OAAO,GAAG,WAAW,CAAC,EAAE,CAAC;oBAClD,IAAI,oBAAoB;wBAAE,OAAO,CAAC,QAAQ,GAAG,CAAC,oBAAoB,CAAC,CAAC;oBACpE,OAAO,OAAO,CAAC;gBACjB,CAAC,CAAC,CAAC;gBAEH,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC9E,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;gBAEzE,MAAM,OAAO,GAA8D,EAAE,CAAC;gBAC9E,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;oBAC7C,MAAM,KAAK,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;oBAC9B,IAAI,KAAK,EAAE,CAAC;wBACV,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;wBAC7B,OAAO,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,IAAI,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;wBAClF,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,UAAU,EAAE,KAAK,EAAE,EAAE,8BAA8B,CAAC,CAAC;oBACjF,CAAC;gBACH,CAAC;gBAED,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACzB,OAAO,gCAAgC,CAAC;gBAC1C,CAAC;gBAED,MAAM,KAAK,GAAG,CAAC,aAAa,OAAO,CAAC,MAAM,SAAS,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;gBACvF,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;oBAC5B,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,GAAG,IAAI,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,UAAU,GAAG,CAAC;oBACxF,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,MAAM,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC;gBAC5C,CAAC;gBACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC1B,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,EAAE,oBAAoB,CAAC,CAAC;gBAC/D,OAAO,8BAA+B,GAAa,CAAC,OAAO,EAAE,CAAC;YAChE,CAAC;QACH,CAAC;QAED,KAAK,SAAS;YACZ,OAAO,6TAA6T,CAAC;QAEvU;YACE,OAAO,kBAAkB,CAAC;IAC9B,CAAC;AACH,CAAC"}
@@ -1,2 +1,12 @@
1
1
  export declare function postSlackMessage(botToken: string, payload: object): Promise<any>;
2
+ /**
3
+ * React to a Slack message (or any thing that has a channel + ts) with the
4
+ * given emoji name (no surrounding colons). Fire-and-forget — failures are
5
+ * logged at info because they're best-effort UX and we never want a missed
6
+ * reaction to surface as a user-visible error.
7
+ *
8
+ * Slash commands have no `ts` to react to, so for those the caller uses
9
+ * `chat.postEphemeral` instead. See `postSlackEphemeral` below.
10
+ */
11
+ export declare function reactToSlackMessage(botToken: string, channel: string, ts: string, emoji: string): Promise<void>;
2
12
  //# sourceMappingURL=slack-helpers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"slack-helpers.d.ts","sourceRoot":"","sources":["../../src/pm/slack-helpers.ts"],"names":[],"mappings":"AAGA,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAmBtF"}
1
+ {"version":3,"file":"slack-helpers.d.ts","sourceRoot":"","sources":["../../src/pm/slack-helpers.ts"],"names":[],"mappings":"AAGA,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAmBtF;AAED;;;;;;;;GAQG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC,CAqBf"}
@@ -21,4 +21,36 @@ export async function postSlackMessage(botToken, payload) {
21
21
  return null;
22
22
  }
23
23
  }
24
+ /**
25
+ * React to a Slack message (or any thing that has a channel + ts) with the
26
+ * given emoji name (no surrounding colons). Fire-and-forget — failures are
27
+ * logged at info because they're best-effort UX and we never want a missed
28
+ * reaction to surface as a user-visible error.
29
+ *
30
+ * Slash commands have no `ts` to react to, so for those the caller uses
31
+ * `chat.postEphemeral` instead. See `postSlackEphemeral` below.
32
+ */
33
+ export async function reactToSlackMessage(botToken, channel, ts, emoji) {
34
+ try {
35
+ const resp = await fetch("https://slack.com/api/reactions.add", {
36
+ method: "POST",
37
+ headers: {
38
+ "Content-Type": "application/json",
39
+ Authorization: `Bearer ${botToken}`,
40
+ },
41
+ body: JSON.stringify({ channel, timestamp: ts, name: emoji }),
42
+ });
43
+ const data = (await resp.json());
44
+ if (!data?.ok) {
45
+ // `already_reacted` is benign — operator re-mentioned the bot in the
46
+ // same thread. Other errors are worth logging for ops visibility.
47
+ const benign = data?.error === "already_reacted";
48
+ const level = benign ? "info" : "warn";
49
+ log[level]({ error: data?.error, channel, ts, emoji }, "Slack reactions.add returned ok:false");
50
+ }
51
+ }
52
+ catch (err) {
53
+ log.error({ err, channel, ts, emoji }, "Slack reactions.add failed");
54
+ }
55
+ }
24
56
  //# sourceMappingURL=slack-helpers.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"slack-helpers.js","sourceRoot":"","sources":["../../src/pm/slack-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,MAAM,GAAG,GAAG,YAAY,CAAC,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC,CAAC;AAEzD,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,QAAgB,EAAE,OAAe;IACtE,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,wCAAwC,EAAE;YACjE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,UAAU,QAAQ,EAAE;aACpC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;SAC9B,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAS,CAAC;QACtC,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC;YACd,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,0CAA0C,CAAC,CAAC;QAC/E,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,EAAE,0BAA0B,CAAC,CAAC;QAC/C,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"slack-helpers.js","sourceRoot":"","sources":["../../src/pm/slack-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,MAAM,GAAG,GAAG,YAAY,CAAC,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC,CAAC;AAEzD,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,QAAgB,EAAE,OAAe;IACtE,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,wCAAwC,EAAE;YACjE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,UAAU,QAAQ,EAAE;aACpC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;SAC9B,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAS,CAAC;QACtC,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC;YACd,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,0CAA0C,CAAC,CAAC;QAC/E,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,EAAE,0BAA0B,CAAC,CAAC;QAC/C,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,QAAgB,EAChB,OAAe,EACf,EAAU,EACV,KAAa;IAEb,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,qCAAqC,EAAE;YAC9D,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,UAAU,QAAQ,EAAE;aACpC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;SAC9D,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,CAAQ,CAAC;QACxC,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC;YACd,qEAAqE;YACrE,kEAAkE;YAClE,MAAM,MAAM,GAAG,IAAI,EAAE,KAAK,KAAK,iBAAiB,CAAC;YACjD,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;YACvC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,uCAAuC,CAAC,CAAC;QAClG,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,4BAA4B,CAAC,CAAC;IACvE,CAAC;AACH,CAAC"}
@@ -7,8 +7,18 @@
7
7
  *
8
8
  * Outbound helpers (call from PM scheduler):
9
9
  * notifyAssigned, notifySkipped, askForClarification, postDailySummary
10
+ *
11
+ * This file retains: types, request parsing, Slack signature verification, the
12
+ * notifier class, and the Hono router factory. Command execution logic was
13
+ * extracted to `slack-commands.ts` (BEC-195) and bulk-create analysis to
14
+ * `slack-bulk.ts` (BEC-195). Both are re-exported here for backward
15
+ * compatibility so existing import sites do not need to change.
10
16
  */
11
17
  import { Hono } from "hono";
18
+ import type { PmCommand } from "./slack-commands.js";
19
+ export { isPmPaused, setPmPaused } from "./pause-state.js";
20
+ export { type BulkIssueSpec, analyzeBulkCreateRequest } from "./slack-bulk.js";
21
+ export { type PmCommand, type CommandExecutorDeps, executePmCommand } from "./slack-commands.js";
12
22
  export interface SlackInterfaceConfig {
13
23
  /** Slack signing secret for request verification */
14
24
  signingSecret: string;
@@ -32,30 +42,23 @@ export interface SlackInterfaceConfig {
32
42
  text: string;
33
43
  responseType: "ephemeral" | "in_channel";
34
44
  }>;
45
+ /**
46
+ * Live runner reference. Required for the `cancel`/`stop`/`halt` Slack
47
+ * commands. When absent, those commands report a clear configuration error
48
+ * instead of silently no-op'ing.
49
+ */
50
+ runner?: {
51
+ requestStop?: (runId: string, mode: "cancel" | "graceful") => {
52
+ issueId: string | null;
53
+ mode: "cancel" | "graceful";
54
+ };
55
+ haltAll?: () => {
56
+ cancelledRunIds: string[];
57
+ };
58
+ };
59
+ /** DB handle for audit-event writes from stop/halt commands. */
60
+ db?: any;
35
61
  }
36
- export type PmCommand = {
37
- type: "prioritize";
38
- issueId: string;
39
- } | {
40
- type: "create";
41
- title: string;
42
- description: string;
43
- } | {
44
- type: "bulk_create";
45
- request: string;
46
- } | {
47
- type: "status";
48
- } | {
49
- type: "pause";
50
- } | {
51
- type: "resume";
52
- } | {
53
- type: "assign";
54
- issueId: string;
55
- } | {
56
- type: "unknown";
57
- original: string;
58
- };
59
62
  export interface AssignedNotification {
60
63
  issueId: string;
61
64
  issueTitle: string;
@@ -72,20 +75,6 @@ export interface DailySummaryEntry {
72
75
  issueTitle: string;
73
76
  status: "assigned" | "completed" | "blocked";
74
77
  }
75
- /**
76
- * Returns `true` if the PM Agent is currently paused.
77
- *
78
- * Pause is active when EITHER of the following is true (OR logic):
79
- * - `process.env.PM_AGENT_PAUSED === "true"` — env-var path for no-Slack incident
80
- * response. Toggling requires a container restart (env vars are read at each
81
- * tick invocation, not at module load time).
82
- * - `setPmPaused(true)` has been called via the Slack `/pm pause` command.
83
- *
84
- * The env-var takes priority: setting `PM_AGENT_PAUSED=true` keeps the agent
85
- * paused even if `setPmPaused(false)` is subsequently called via Slack.
86
- */
87
- export declare function isPmPaused(): boolean;
88
- export declare function setPmPaused(value: boolean): void;
89
78
  /**
90
79
  * Verifies the Slack signing secret against the X-Slack-Signature header.
91
80
  * Returns `true` if valid, `false` otherwise.
@@ -99,22 +88,6 @@ export declare function parsePmCommand(text: string): PmCommand;
99
88
  * Returns `{ type: "unknown", original }` if no actionable intent is found.
100
89
  */
101
90
  export declare function interpretNaturalLanguage(message: string, callClaude: (prompt: string) => Promise<string>): Promise<PmCommand>;
102
- export interface BulkIssueSpec {
103
- title: string;
104
- description: string;
105
- priority: number;
106
- acceptanceCriteria: string[];
107
- }
108
- export interface CommandExecutorDeps {
109
- linearApiKey?: string;
110
- teamIds?: string[];
111
- callClaudeSonnet?: (prompt: string) => Promise<string>;
112
- }
113
- /**
114
- * Executes a parsed `PmCommand` against Linear and returns a human-readable
115
- * response string suitable for posting back to Slack.
116
- */
117
- export declare function executePmCommand(cmd: PmCommand, deps: CommandExecutorDeps): Promise<string>;
118
91
  export declare class SlackInterfaceNotifier {
119
92
  private botToken;
120
93
  private channelId;
@@ -127,6 +100,12 @@ export declare class SlackInterfaceNotifier {
127
100
  askForClarification(question: string): Promise<void>;
128
101
  /** Post a daily summary of assigned, completed, and blocked issues. */
129
102
  postDailySummary(entries: DailySummaryEntry[], date?: string): Promise<void>;
103
+ /**
104
+ * Posts a single Slack Block Kit section containing mrkdwn-formatted `text`
105
+ * to the configured channel. All three simple notification methods delegate
106
+ * here to avoid repeating the identical blocks structure.
107
+ */
108
+ private postMarkdownMessage;
130
109
  private postMessage;
131
110
  }
132
111
  /**
@@ -145,9 +124,4 @@ export declare function createSlackInterface(config: SlackInterfaceConfig): {
145
124
  router: Hono;
146
125
  notifier: SlackInterfaceNotifier;
147
126
  };
148
- /**
149
- * Uses a capable Claude model (Sonnet) to analyze a bulk create request and
150
- * produce a structured list of issue specifications.
151
- */
152
- export declare function analyzeBulkCreateRequest(request: string, callClaudeSonnet: (prompt: string) => Promise<string>): Promise<BulkIssueSpec[]>;
153
127
  //# sourceMappingURL=slack-interface.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"slack-interface.d.ts","sourceRoot":"","sources":["../../src/pm/slack-interface.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"slack-interface.d.ts","sourceRoot":"","sources":["../../src/pm/slack-interface.ts"],"names":[],"mappings":"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"}