@cuylabs/channel-slack 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +168 -0
- package/dist/activity-ByrD9Ftr.d.ts +66 -0
- package/dist/assistant.d.ts +58 -0
- package/dist/assistant.js +188 -0
- package/dist/bolt.d.ts +344 -0
- package/dist/bolt.js +705 -0
- package/dist/chunk-BODPT4I6.js +322 -0
- package/dist/chunk-FPCE5V5Y.js +292 -0
- package/dist/chunk-FX2JOVX5.js +405 -0
- package/dist/chunk-JZG4IETE.js +141 -0
- package/dist/chunk-NE57BLLU.js +0 -0
- package/dist/chunk-TWJGVDA2.js +108 -0
- package/dist/core.d.ts +425 -0
- package/dist/core.js +42 -0
- package/dist/diagnostics.d.ts +105 -0
- package/dist/diagnostics.js +8 -0
- package/dist/feedback.d.ts +137 -0
- package/dist/feedback.js +128 -0
- package/dist/history.d.ts +266 -0
- package/dist/history.js +747 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +57 -0
- package/dist/logging-Bl3HfcC8.d.ts +8 -0
- package/dist/policy.d.ts +130 -0
- package/dist/policy.js +16 -0
- package/dist/setup.d.ts +165 -0
- package/dist/setup.js +453 -0
- package/dist/shared.d.ts +2 -0
- package/dist/shared.js +43 -0
- package/dist/targets.d.ts +113 -0
- package/dist/targets.js +484 -0
- package/dist/users.d.ts +109 -0
- package/dist/users.js +240 -0
- package/docs/concepts/activity.md +33 -0
- package/docs/concepts/bolt-runtime.md +30 -0
- package/docs/concepts/message-policy.md +49 -0
- package/docs/concepts/setup-requirements.md +44 -0
- package/docs/concepts/supplemental-history.md +55 -0
- package/docs/recipes/app-mention-handler.md +34 -0
- package/docs/recipes/assistant-thread-handler.md +28 -0
- package/docs/recipes/generate-slack-manifest.md +28 -0
- package/docs/recipes/history-visibility.md +36 -0
- package/docs/recipes/socket-mode-app.md +29 -0
- package/docs/reference/channel-slack-boundary.md +50 -0
- package/docs/reference/exports.md +32 -0
- package/package.json +130 -0
package/dist/setup.js
ADDED
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
import {
|
|
2
|
+
inspectSlackConnection
|
|
3
|
+
} from "./chunk-FX2JOVX5.js";
|
|
4
|
+
|
|
5
|
+
// src/setup/requirements.ts
|
|
6
|
+
var DEFAULT_EVENTS_PATH = "/slack/events";
|
|
7
|
+
var slackSetupFeaturePresets = {
|
|
8
|
+
assistant: ["assistant", "feedback"],
|
|
9
|
+
"channel-adapter": ["app-mentions", "direct-messages"],
|
|
10
|
+
"agent-app": ["assistant", "app-mentions", "direct-messages", "feedback"]
|
|
11
|
+
};
|
|
12
|
+
var FEATURE_REQUIREMENTS = {
|
|
13
|
+
assistant: {
|
|
14
|
+
botScopes: ["assistant:write", "chat:write"],
|
|
15
|
+
botEvents: ["assistant_thread_started", "assistant_thread_context_changed"],
|
|
16
|
+
assistantView: true
|
|
17
|
+
},
|
|
18
|
+
"app-mentions": {
|
|
19
|
+
botScopes: ["app_mentions:read", "chat:write"],
|
|
20
|
+
botEvents: ["app_mention"]
|
|
21
|
+
},
|
|
22
|
+
"direct-messages": {
|
|
23
|
+
botScopes: ["chat:write", "im:history", "im:read"],
|
|
24
|
+
botEvents: ["message.im"]
|
|
25
|
+
},
|
|
26
|
+
"channel-messages": {
|
|
27
|
+
botScopes: ["channels:history", "chat:write", "groups:history"],
|
|
28
|
+
botEvents: ["message.channels", "message.groups"]
|
|
29
|
+
},
|
|
30
|
+
history: {
|
|
31
|
+
botScopes: [
|
|
32
|
+
"channels:history",
|
|
33
|
+
"groups:history",
|
|
34
|
+
"im:history",
|
|
35
|
+
"mpim:history"
|
|
36
|
+
]
|
|
37
|
+
},
|
|
38
|
+
interactivity: {
|
|
39
|
+
botScopes: ["chat:write"],
|
|
40
|
+
interactivity: true
|
|
41
|
+
},
|
|
42
|
+
feedback: {
|
|
43
|
+
botScopes: ["chat:write"],
|
|
44
|
+
interactivity: true
|
|
45
|
+
},
|
|
46
|
+
"user-profiles": {
|
|
47
|
+
botScopes: ["users:read"],
|
|
48
|
+
optionalBotScopes: ["users:read.email"]
|
|
49
|
+
},
|
|
50
|
+
"user-emails": {
|
|
51
|
+
botScopes: ["users:read", "users:read.email"]
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
function getSlackSetupRequirements(options = {}) {
|
|
55
|
+
const features = resolveSetupFeatures(options);
|
|
56
|
+
const transport = options.transport ?? "http";
|
|
57
|
+
const eventsPath = normalizeSlackEventsPath(
|
|
58
|
+
options.eventsPath ?? DEFAULT_EVENTS_PATH
|
|
59
|
+
);
|
|
60
|
+
const requestUrl = resolveRequestUrl(options.baseUrl, eventsPath);
|
|
61
|
+
const botScopes = [];
|
|
62
|
+
const optionalBotScopes = [];
|
|
63
|
+
const botEvents = [];
|
|
64
|
+
let assistantView = false;
|
|
65
|
+
let interactivity = false;
|
|
66
|
+
for (const feature of features) {
|
|
67
|
+
const requirement = FEATURE_REQUIREMENTS[feature];
|
|
68
|
+
if (!requirement) {
|
|
69
|
+
throw new Error(`Unknown Slack setup feature: ${feature}`);
|
|
70
|
+
}
|
|
71
|
+
collect(requirement.botScopes, botScopes);
|
|
72
|
+
collect(requirement.optionalBotScopes, optionalBotScopes);
|
|
73
|
+
collect(requirement.botEvents, botEvents);
|
|
74
|
+
assistantView ||= requirement.assistantView === true;
|
|
75
|
+
interactivity ||= requirement.interactivity === true;
|
|
76
|
+
}
|
|
77
|
+
collect(options.extraBotScopes, botScopes);
|
|
78
|
+
collect(options.extraOptionalBotScopes, optionalBotScopes);
|
|
79
|
+
collect(options.extraBotEvents, botEvents);
|
|
80
|
+
const normalizedBotScopes = uniqueSorted(botScopes);
|
|
81
|
+
const normalizedBotEvents = uniqueSorted(botEvents);
|
|
82
|
+
const requiredScopeKeys = new Set(
|
|
83
|
+
normalizedBotScopes.map((scope) => scope.toLowerCase())
|
|
84
|
+
);
|
|
85
|
+
const normalizedOptionalBotScopes = uniqueSorted(
|
|
86
|
+
optionalBotScopes.filter(
|
|
87
|
+
(scope) => !requiredScopeKeys.has(scope.trim().toLowerCase())
|
|
88
|
+
)
|
|
89
|
+
);
|
|
90
|
+
const settings = {
|
|
91
|
+
assistantView,
|
|
92
|
+
eventSubscriptions: normalizedBotEvents.length > 0,
|
|
93
|
+
interactivity,
|
|
94
|
+
socketMode: transport === "socket"
|
|
95
|
+
};
|
|
96
|
+
const environment = resolveEnvironment({
|
|
97
|
+
botScopes: normalizedBotScopes,
|
|
98
|
+
settings,
|
|
99
|
+
transport
|
|
100
|
+
});
|
|
101
|
+
return {
|
|
102
|
+
features,
|
|
103
|
+
transport,
|
|
104
|
+
eventsPath,
|
|
105
|
+
...requestUrl ? { requestUrl } : {},
|
|
106
|
+
botScopes: normalizedBotScopes,
|
|
107
|
+
optionalBotScopes: normalizedOptionalBotScopes,
|
|
108
|
+
appTokenScopes: transport === "socket" ? ["connections:write"] : [],
|
|
109
|
+
botEvents: normalizedBotEvents,
|
|
110
|
+
settings,
|
|
111
|
+
environment
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
function resolveSetupFeatures(options) {
|
|
115
|
+
const preset = options.preset ?? "agent-app";
|
|
116
|
+
if (preset === false) {
|
|
117
|
+
return uniqueFeatures(options.features ?? []);
|
|
118
|
+
}
|
|
119
|
+
const presetFeatures = slackSetupFeaturePresets[preset];
|
|
120
|
+
if (!presetFeatures) {
|
|
121
|
+
throw new Error(`Unknown Slack setup preset: ${preset}`);
|
|
122
|
+
}
|
|
123
|
+
return uniqueFeatures([
|
|
124
|
+
...presetFeatures ?? [],
|
|
125
|
+
...options.features ?? []
|
|
126
|
+
]);
|
|
127
|
+
}
|
|
128
|
+
function resolveEnvironment(context) {
|
|
129
|
+
const environment = [];
|
|
130
|
+
if (context.botScopes.length > 0) {
|
|
131
|
+
environment.push({
|
|
132
|
+
name: "SLACK_BOT_TOKEN",
|
|
133
|
+
purpose: "Bot OAuth token used by single-workspace direct mode and setup inspection."
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
if (context.transport === "http" && (context.settings.eventSubscriptions || context.settings.interactivity)) {
|
|
137
|
+
environment.push({
|
|
138
|
+
name: "SLACK_SIGNING_SECRET",
|
|
139
|
+
purpose: "Signing secret used by Bolt to verify inbound Slack requests."
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
if (context.transport === "socket") {
|
|
143
|
+
environment.push({
|
|
144
|
+
name: "SLACK_APP_TOKEN",
|
|
145
|
+
purpose: "App-level token with connections:write used by Socket Mode transport."
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
return environment;
|
|
149
|
+
}
|
|
150
|
+
function normalizeSlackEventsPath(path) {
|
|
151
|
+
const trimmed = path.trim();
|
|
152
|
+
if (!trimmed) {
|
|
153
|
+
throw new Error("Slack events path must not be empty.");
|
|
154
|
+
}
|
|
155
|
+
return trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
|
|
156
|
+
}
|
|
157
|
+
function resolveRequestUrl(baseUrl, eventsPath) {
|
|
158
|
+
const trimmed = trimString(baseUrl);
|
|
159
|
+
if (!trimmed) return void 0;
|
|
160
|
+
return `${trimmed.replace(/\/+$/, "")}${eventsPath}`;
|
|
161
|
+
}
|
|
162
|
+
function collect(source, target) {
|
|
163
|
+
if (!source) return;
|
|
164
|
+
for (const value of source) {
|
|
165
|
+
const trimmed = value.trim();
|
|
166
|
+
if (trimmed) target.push(trimmed);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
function uniqueSorted(values) {
|
|
170
|
+
const unique = /* @__PURE__ */ new Map();
|
|
171
|
+
for (const value of values) {
|
|
172
|
+
const trimmed = value.trim();
|
|
173
|
+
if (trimmed) {
|
|
174
|
+
unique.set(trimmed.toLowerCase(), trimmed);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return [...unique.values()].sort((a, b) => a.localeCompare(b));
|
|
178
|
+
}
|
|
179
|
+
function uniqueFeatures(values) {
|
|
180
|
+
const unique = /* @__PURE__ */ new Set();
|
|
181
|
+
for (const value of values) {
|
|
182
|
+
if (!FEATURE_REQUIREMENTS[value]) {
|
|
183
|
+
throw new Error(`Unknown Slack setup feature: ${value}`);
|
|
184
|
+
}
|
|
185
|
+
unique.add(value);
|
|
186
|
+
}
|
|
187
|
+
return [...unique];
|
|
188
|
+
}
|
|
189
|
+
function trimString(value) {
|
|
190
|
+
const trimmed = value?.trim();
|
|
191
|
+
return trimmed || void 0;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// src/setup/manifest.ts
|
|
195
|
+
function createSlackAppManifest(options) {
|
|
196
|
+
const requirements = getSlackSetupRequirements(options);
|
|
197
|
+
const name = options.name.trim();
|
|
198
|
+
if (!name) {
|
|
199
|
+
throw new Error("Slack app manifest name is required.");
|
|
200
|
+
}
|
|
201
|
+
const description = trimString2(options.description);
|
|
202
|
+
const backgroundColor = trimString2(options.backgroundColor);
|
|
203
|
+
const assistantDescription = trimString2(options.assistantDescription);
|
|
204
|
+
const botDisplayName = trimString2(options.botDisplayName) ?? name;
|
|
205
|
+
const displayInformation = {
|
|
206
|
+
name
|
|
207
|
+
};
|
|
208
|
+
if (description) displayInformation.description = description;
|
|
209
|
+
if (backgroundColor) displayInformation.background_color = backgroundColor;
|
|
210
|
+
const features = {
|
|
211
|
+
bot_user: {
|
|
212
|
+
display_name: botDisplayName,
|
|
213
|
+
always_online: options.alwaysOnline ?? true
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
if (requirements.settings.assistantView) {
|
|
217
|
+
if (options.appHome !== false) {
|
|
218
|
+
features.app_home = {
|
|
219
|
+
home_tab_enabled: options.appHome?.home_tab_enabled ?? true,
|
|
220
|
+
messages_tab_enabled: options.appHome?.messages_tab_enabled ?? true,
|
|
221
|
+
messages_tab_read_only_enabled: options.appHome?.messages_tab_read_only_enabled ?? false
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
features.assistant_view = {
|
|
225
|
+
...assistantDescription ? { assistant_description: assistantDescription } : {},
|
|
226
|
+
...options.suggestedPrompts ? { suggested_prompts: [...options.suggestedPrompts] } : {}
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
const settings = {
|
|
230
|
+
socket_mode_enabled: requirements.settings.socketMode,
|
|
231
|
+
token_rotation_enabled: options.tokenRotationEnabled ?? false
|
|
232
|
+
};
|
|
233
|
+
if (requirements.settings.eventSubscriptions) {
|
|
234
|
+
settings.event_subscriptions = {
|
|
235
|
+
...requirements.requestUrl && requirements.transport === "http" ? { request_url: requirements.requestUrl } : {},
|
|
236
|
+
bot_events: requirements.botEvents
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
if (requirements.settings.interactivity) {
|
|
240
|
+
settings.interactivity = {
|
|
241
|
+
is_enabled: true,
|
|
242
|
+
...requirements.requestUrl && requirements.transport === "http" ? { request_url: requirements.requestUrl } : {}
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
if (options.orgDeployEnabled !== void 0) {
|
|
246
|
+
settings.org_deploy_enabled = options.orgDeployEnabled;
|
|
247
|
+
}
|
|
248
|
+
if (options.isMcpEnabled !== void 0) {
|
|
249
|
+
settings.is_mcp_enabled = options.isMcpEnabled;
|
|
250
|
+
}
|
|
251
|
+
const userScopes = uniqueSorted2(options.extraUserScopes ?? []);
|
|
252
|
+
return {
|
|
253
|
+
display_information: displayInformation,
|
|
254
|
+
features,
|
|
255
|
+
oauth_config: {
|
|
256
|
+
scopes: {
|
|
257
|
+
bot: requirements.botScopes,
|
|
258
|
+
...userScopes.length > 0 ? { user: userScopes } : {}
|
|
259
|
+
}
|
|
260
|
+
},
|
|
261
|
+
settings
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
function compareSlackAppManifest(manifest, requirements) {
|
|
265
|
+
const findings = [];
|
|
266
|
+
const manifestRecord = readRecord(manifest);
|
|
267
|
+
const oauthConfig = readRecord(manifestRecord?.oauth_config);
|
|
268
|
+
const scopes = readRecord(oauthConfig?.scopes);
|
|
269
|
+
const settings = readRecord(manifestRecord?.settings);
|
|
270
|
+
const eventSubscriptions = readRecord(settings?.event_subscriptions);
|
|
271
|
+
const botScopes = readStringArray(scopes?.bot);
|
|
272
|
+
const botEvents = readStringArray(eventSubscriptions?.bot_events);
|
|
273
|
+
const missingBotScopes = missingValues(requirements.botScopes, botScopes);
|
|
274
|
+
const missingOptionalBotScopes = missingValues(
|
|
275
|
+
requirements.optionalBotScopes,
|
|
276
|
+
botScopes
|
|
277
|
+
);
|
|
278
|
+
const missingBotEvents = missingValues(requirements.botEvents, botEvents);
|
|
279
|
+
if (missingBotScopes.length > 0) {
|
|
280
|
+
findings.push({
|
|
281
|
+
severity: "error",
|
|
282
|
+
code: "missing-bot-scopes",
|
|
283
|
+
message: `Slack manifest is missing required bot scope(s): ${missingBotScopes.join(
|
|
284
|
+
", "
|
|
285
|
+
)}.`,
|
|
286
|
+
path: "oauth_config.scopes.bot",
|
|
287
|
+
expected: requirements.botScopes,
|
|
288
|
+
actual: botScopes
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
if (missingOptionalBotScopes.length > 0) {
|
|
292
|
+
findings.push({
|
|
293
|
+
severity: "warning",
|
|
294
|
+
code: "missing-optional-bot-scopes",
|
|
295
|
+
message: `Slack manifest is missing optional bot scope(s): ${missingOptionalBotScopes.join(
|
|
296
|
+
", "
|
|
297
|
+
)}.`,
|
|
298
|
+
path: "oauth_config.scopes.bot",
|
|
299
|
+
expected: requirements.optionalBotScopes,
|
|
300
|
+
actual: botScopes
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
if (missingBotEvents.length > 0) {
|
|
304
|
+
findings.push({
|
|
305
|
+
severity: "error",
|
|
306
|
+
code: "missing-bot-events",
|
|
307
|
+
message: `Slack manifest is missing required bot event(s): ${missingBotEvents.join(
|
|
308
|
+
", "
|
|
309
|
+
)}.`,
|
|
310
|
+
path: "settings.event_subscriptions.bot_events",
|
|
311
|
+
expected: requirements.botEvents,
|
|
312
|
+
actual: botEvents
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
compareSettings(manifest, requirements, findings);
|
|
316
|
+
return {
|
|
317
|
+
ok: findings.every((finding) => finding.severity !== "error"),
|
|
318
|
+
missingBotScopes,
|
|
319
|
+
missingOptionalBotScopes,
|
|
320
|
+
missingBotEvents,
|
|
321
|
+
findings
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
function compareSettings(manifest, requirements, findings) {
|
|
325
|
+
const manifestRecord = readRecord(manifest);
|
|
326
|
+
const features = readRecord(manifestRecord?.features);
|
|
327
|
+
const settings = readRecord(manifestRecord?.settings);
|
|
328
|
+
const eventSubscriptions = readRecord(settings?.event_subscriptions);
|
|
329
|
+
const interactivity = readRecord(settings?.interactivity);
|
|
330
|
+
if (requirements.settings.assistantView && !readRecord(features?.assistant_view)) {
|
|
331
|
+
findings.push({
|
|
332
|
+
severity: "error",
|
|
333
|
+
code: "assistant-view-disabled",
|
|
334
|
+
message: "Slack manifest must enable Assistant view for Assistant features.",
|
|
335
|
+
path: "features.assistant_view",
|
|
336
|
+
expected: true,
|
|
337
|
+
actual: false
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
if (requirements.settings.eventSubscriptions && !Array.isArray(eventSubscriptions?.bot_events)) {
|
|
341
|
+
findings.push({
|
|
342
|
+
severity: "error",
|
|
343
|
+
code: "event-subscriptions-disabled",
|
|
344
|
+
message: "Slack manifest must configure event subscriptions for selected features.",
|
|
345
|
+
path: "settings.event_subscriptions.bot_events",
|
|
346
|
+
expected: requirements.botEvents,
|
|
347
|
+
actual: void 0
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
if (requirements.settings.interactivity && readBoolean(interactivity?.is_enabled) !== true) {
|
|
351
|
+
findings.push({
|
|
352
|
+
severity: "error",
|
|
353
|
+
code: "interactivity-disabled",
|
|
354
|
+
message: "Slack manifest must enable interactivity for selected features.",
|
|
355
|
+
path: "settings.interactivity.is_enabled",
|
|
356
|
+
expected: true,
|
|
357
|
+
actual: readBoolean(interactivity?.is_enabled) ?? false
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
if (requirements.settings.socketMode && readBoolean(settings?.socket_mode_enabled) !== true) {
|
|
361
|
+
findings.push({
|
|
362
|
+
severity: "error",
|
|
363
|
+
code: "socket-mode-disabled",
|
|
364
|
+
message: "Slack manifest must enable Socket Mode for socket transport.",
|
|
365
|
+
path: "settings.socket_mode_enabled",
|
|
366
|
+
expected: true,
|
|
367
|
+
actual: readBoolean(settings?.socket_mode_enabled) ?? false
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
if (requirements.requestUrl && requirements.transport === "http" && requirements.settings.eventSubscriptions && readString(eventSubscriptions?.request_url) !== requirements.requestUrl) {
|
|
371
|
+
findings.push({
|
|
372
|
+
severity: "error",
|
|
373
|
+
code: "event-request-url-mismatch",
|
|
374
|
+
message: `Slack manifest event request URL must be ${requirements.requestUrl}.`,
|
|
375
|
+
path: "settings.event_subscriptions.request_url",
|
|
376
|
+
expected: requirements.requestUrl,
|
|
377
|
+
actual: readString(eventSubscriptions?.request_url)
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
if (requirements.requestUrl && requirements.transport === "http" && requirements.settings.interactivity && readString(interactivity?.request_url) !== requirements.requestUrl) {
|
|
381
|
+
findings.push({
|
|
382
|
+
severity: "error",
|
|
383
|
+
code: "interactivity-request-url-mismatch",
|
|
384
|
+
message: `Slack manifest interactivity request URL must be ${requirements.requestUrl}.`,
|
|
385
|
+
path: "settings.interactivity.request_url",
|
|
386
|
+
expected: requirements.requestUrl,
|
|
387
|
+
actual: readString(interactivity?.request_url)
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
function trimString2(value) {
|
|
392
|
+
const trimmed = value?.trim();
|
|
393
|
+
return trimmed || void 0;
|
|
394
|
+
}
|
|
395
|
+
function missingValues(expected, actual) {
|
|
396
|
+
const actualSet = new Set(
|
|
397
|
+
actual.map((value) => value.trim().toLowerCase()).filter(Boolean)
|
|
398
|
+
);
|
|
399
|
+
return expected.filter((value) => !actualSet.has(value.trim().toLowerCase()));
|
|
400
|
+
}
|
|
401
|
+
function uniqueSorted2(values) {
|
|
402
|
+
const unique = /* @__PURE__ */ new Map();
|
|
403
|
+
for (const value of values) {
|
|
404
|
+
const trimmed = value.trim();
|
|
405
|
+
if (trimmed) {
|
|
406
|
+
unique.set(trimmed.toLowerCase(), trimmed);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
return [...unique.values()].sort((a, b) => a.localeCompare(b));
|
|
410
|
+
}
|
|
411
|
+
function readRecord(value) {
|
|
412
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
413
|
+
}
|
|
414
|
+
function readStringArray(value) {
|
|
415
|
+
if (!Array.isArray(value)) {
|
|
416
|
+
return [];
|
|
417
|
+
}
|
|
418
|
+
return uniqueSorted2(
|
|
419
|
+
value.filter((entry) => typeof entry === "string")
|
|
420
|
+
);
|
|
421
|
+
}
|
|
422
|
+
function readString(value) {
|
|
423
|
+
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
424
|
+
}
|
|
425
|
+
function readBoolean(value) {
|
|
426
|
+
return typeof value === "boolean" ? value : void 0;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
// src/setup/inspection.ts
|
|
430
|
+
async function inspectSlackAppSetup(options = {}) {
|
|
431
|
+
const requirements = getSlackSetupRequirements(options);
|
|
432
|
+
const connection = await inspectSlackConnection({
|
|
433
|
+
token: options.token,
|
|
434
|
+
client: options.client,
|
|
435
|
+
requestTimeoutMs: options.requestTimeoutMs,
|
|
436
|
+
inspectScopes: options.inspectScopes,
|
|
437
|
+
scopeMethods: options.scopeMethods,
|
|
438
|
+
requiredScopes: requirements.botScopes,
|
|
439
|
+
optionalScopes: requirements.optionalBotScopes
|
|
440
|
+
});
|
|
441
|
+
return {
|
|
442
|
+
ok: connection.ok,
|
|
443
|
+
requirements,
|
|
444
|
+
connection
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
export {
|
|
448
|
+
compareSlackAppManifest,
|
|
449
|
+
createSlackAppManifest,
|
|
450
|
+
getSlackSetupRequirements,
|
|
451
|
+
inspectSlackAppSetup,
|
|
452
|
+
slackSetupFeaturePresets
|
|
453
|
+
};
|
package/dist/shared.d.ts
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { S as SlackActivityInfo, a as SlackChannelType, b as SlackUserIdentity } from './activity-ByrD9Ftr.js';
|
|
2
|
+
export { ExtractSlackMessageTextOptions, RawSlackActionTokenPayload, RawSlackAppMentionPayload, RawSlackAssistantThreadPayload, RawSlackMessagePayload, SlackAmbientTurnContext, SlackApprovalRequest, SlackAssistantStatusUpdate, SlackAssistantSuggestedPrompt, SlackAssistantSuggestedPrompts, SlackAssistantTaskDisplayMode, SlackAssistantThreadContext, SlackAssistantUtilities, SlackAuthContext, SlackChatStreamStartArgs, SlackEventInteractiveRequestHandler, SlackHumanInputRequest, SlackInteractiveMessage, SlackInteractiveMessageRef, SlackInteractiveRequest, SlackInteractiveRequestBaseContext, SlackInteractiveRequestContext, SlackInteractiveRequestHandler, SlackInteractiveRequestKind, SlackInteractiveResponder, SlackMessageAuthorshipOptions, SlackMessageFormatter, SlackMessageFormattingOptions, SlackMessageTextPayload, SlackThreadStatusSetter, SlackTurnPreparation, SlackTurnRequestContext, currentSlackTurnContext, extractSlackActionToken, extractSlackAttachmentsText, extractSlackAuthContext, extractSlackBlocksText, extractSlackMessageText, extractSlackUserIdentity, formatSlackAttributedFollowUp, isProcessableMessage, markdownToSlackMrkdwn, parseSlackMentionActivity, parseSlackMessageActivity, resolveSlackChannelType, resolveSlackMessageFormatter, resolveThreadAwareSlackSessionId, runWithSlackTurnContext, stripLeadingMentions } from './core.js';
|
package/dist/shared.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import "./chunk-NE57BLLU.js";
|
|
2
|
+
import {
|
|
3
|
+
currentSlackTurnContext,
|
|
4
|
+
formatSlackAttributedFollowUp,
|
|
5
|
+
markdownToSlackMrkdwn,
|
|
6
|
+
resolveSlackMessageFormatter,
|
|
7
|
+
resolveThreadAwareSlackSessionId,
|
|
8
|
+
runWithSlackTurnContext
|
|
9
|
+
} from "./chunk-JZG4IETE.js";
|
|
10
|
+
import {
|
|
11
|
+
extractSlackActionToken,
|
|
12
|
+
extractSlackAuthContext,
|
|
13
|
+
extractSlackUserIdentity,
|
|
14
|
+
parseSlackMentionActivity,
|
|
15
|
+
parseSlackMessageActivity
|
|
16
|
+
} from "./chunk-TWJGVDA2.js";
|
|
17
|
+
import {
|
|
18
|
+
extractSlackAttachmentsText,
|
|
19
|
+
extractSlackBlocksText,
|
|
20
|
+
extractSlackMessageText,
|
|
21
|
+
isProcessableMessage,
|
|
22
|
+
resolveSlackChannelType,
|
|
23
|
+
stripLeadingMentions
|
|
24
|
+
} from "./chunk-FPCE5V5Y.js";
|
|
25
|
+
export {
|
|
26
|
+
currentSlackTurnContext,
|
|
27
|
+
extractSlackActionToken,
|
|
28
|
+
extractSlackAttachmentsText,
|
|
29
|
+
extractSlackAuthContext,
|
|
30
|
+
extractSlackBlocksText,
|
|
31
|
+
extractSlackMessageText,
|
|
32
|
+
extractSlackUserIdentity,
|
|
33
|
+
formatSlackAttributedFollowUp,
|
|
34
|
+
isProcessableMessage,
|
|
35
|
+
markdownToSlackMrkdwn,
|
|
36
|
+
parseSlackMentionActivity,
|
|
37
|
+
parseSlackMessageActivity,
|
|
38
|
+
resolveSlackChannelType,
|
|
39
|
+
resolveSlackMessageFormatter,
|
|
40
|
+
resolveThreadAwareSlackSessionId,
|
|
41
|
+
runWithSlackTurnContext,
|
|
42
|
+
stripLeadingMentions
|
|
43
|
+
};
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
type SlackTargetKind = "channel" | "user";
|
|
2
|
+
type SlackTargetValueKind = "id" | "name";
|
|
3
|
+
type SlackTargetSource = "prefixed" | "mention" | "link" | "id" | "name";
|
|
4
|
+
interface SlackTarget {
|
|
5
|
+
input: string;
|
|
6
|
+
kind: SlackTargetKind;
|
|
7
|
+
valueKind: SlackTargetValueKind;
|
|
8
|
+
value: string;
|
|
9
|
+
source: SlackTargetSource;
|
|
10
|
+
id?: string;
|
|
11
|
+
name?: string;
|
|
12
|
+
label?: string;
|
|
13
|
+
}
|
|
14
|
+
interface ParseSlackTargetOptions {
|
|
15
|
+
/**
|
|
16
|
+
* Interpret bare non-ID values as this target kind.
|
|
17
|
+
*
|
|
18
|
+
* @example `parseSlackTarget("general", { defaultKind: "channel" })`
|
|
19
|
+
*/
|
|
20
|
+
defaultKind?: SlackTargetKind;
|
|
21
|
+
/**
|
|
22
|
+
* Whether bare non-ID values may be parsed through `defaultKind`.
|
|
23
|
+
*
|
|
24
|
+
* @default Boolean(defaultKind)
|
|
25
|
+
*/
|
|
26
|
+
allowBareNames?: boolean;
|
|
27
|
+
}
|
|
28
|
+
interface ParseSlackTargetsResult {
|
|
29
|
+
targets: SlackTarget[];
|
|
30
|
+
invalid: string[];
|
|
31
|
+
}
|
|
32
|
+
declare function parseSlackTarget(input: string, options?: ParseSlackTargetOptions): SlackTarget | undefined;
|
|
33
|
+
declare function parseSlackTargets(inputs: string | readonly string[], options?: ParseSlackTargetOptions): ParseSlackTargetsResult;
|
|
34
|
+
|
|
35
|
+
interface SlackTargetResolutionClient {
|
|
36
|
+
conversations?: {
|
|
37
|
+
list(args?: Record<string, unknown>): Promise<unknown>;
|
|
38
|
+
};
|
|
39
|
+
users?: {
|
|
40
|
+
list(args?: Record<string, unknown>): Promise<unknown>;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
interface SlackResolvedTarget {
|
|
44
|
+
input: string;
|
|
45
|
+
kind: SlackTargetKind;
|
|
46
|
+
id: string;
|
|
47
|
+
valueKind: "id" | "name";
|
|
48
|
+
name?: string;
|
|
49
|
+
label?: string;
|
|
50
|
+
raw?: unknown;
|
|
51
|
+
}
|
|
52
|
+
type SlackTargetResolutionErrorCode = "invalid-target" | "target-kind-mismatch" | "missing-client-method" | "not-found" | "api-error";
|
|
53
|
+
interface SlackTargetResolutionError {
|
|
54
|
+
input: string;
|
|
55
|
+
code: SlackTargetResolutionErrorCode;
|
|
56
|
+
message: string;
|
|
57
|
+
kind?: SlackTargetKind;
|
|
58
|
+
name?: string;
|
|
59
|
+
error?: unknown;
|
|
60
|
+
}
|
|
61
|
+
interface SlackTargetResolutionResult {
|
|
62
|
+
resolved: SlackResolvedTarget[];
|
|
63
|
+
unresolved: SlackTargetResolutionError[];
|
|
64
|
+
}
|
|
65
|
+
interface ResolveSlackChannelTargetsOptions {
|
|
66
|
+
client: SlackTargetResolutionClient;
|
|
67
|
+
targets: readonly (string | SlackTarget)[];
|
|
68
|
+
token?: string;
|
|
69
|
+
/**
|
|
70
|
+
* Conversation types passed to `conversations.list`.
|
|
71
|
+
*
|
|
72
|
+
* @default "public_channel,private_channel"
|
|
73
|
+
*/
|
|
74
|
+
types?: string;
|
|
75
|
+
/** Include archived channels while resolving names. @default false */
|
|
76
|
+
includeArchived?: boolean;
|
|
77
|
+
/** Slack API page size. @default 200 */
|
|
78
|
+
limit?: number;
|
|
79
|
+
}
|
|
80
|
+
interface ResolveSlackUserTargetsOptions {
|
|
81
|
+
client: SlackTargetResolutionClient;
|
|
82
|
+
targets: readonly (string | SlackTarget)[];
|
|
83
|
+
token?: string;
|
|
84
|
+
/** Include deleted users while resolving names. @default false */
|
|
85
|
+
includeDeleted?: boolean;
|
|
86
|
+
/** Include bot users while resolving names. @default false */
|
|
87
|
+
includeBots?: boolean;
|
|
88
|
+
/** Slack API page size. @default 200 */
|
|
89
|
+
limit?: number;
|
|
90
|
+
}
|
|
91
|
+
interface ResolveSlackAllowedChannelIdsOptions extends Omit<ResolveSlackChannelTargetsOptions, "client" | "targets"> {
|
|
92
|
+
/**
|
|
93
|
+
* Human-friendly channel targets from policy config, such as `C123`,
|
|
94
|
+
* `#engineering`, `<#C123|engineering>`, or `channel:engineering`.
|
|
95
|
+
*/
|
|
96
|
+
targets: readonly (string | SlackTarget)[];
|
|
97
|
+
/**
|
|
98
|
+
* Slack Web API client used when a target needs name resolution. Direct
|
|
99
|
+
* channel IDs do not require a client.
|
|
100
|
+
*/
|
|
101
|
+
client?: SlackTargetResolutionClient;
|
|
102
|
+
}
|
|
103
|
+
interface SlackAllowedChannelIdsResolution {
|
|
104
|
+
ok: boolean;
|
|
105
|
+
allowedChannelIds: string[];
|
|
106
|
+
resolved: SlackResolvedTarget[];
|
|
107
|
+
unresolved: SlackTargetResolutionError[];
|
|
108
|
+
}
|
|
109
|
+
declare function resolveSlackChannelTargets(options: ResolveSlackChannelTargetsOptions): Promise<SlackTargetResolutionResult>;
|
|
110
|
+
declare function resolveSlackUserTargets(options: ResolveSlackUserTargetsOptions): Promise<SlackTargetResolutionResult>;
|
|
111
|
+
declare function resolveSlackAllowedChannelIds(options: ResolveSlackAllowedChannelIdsOptions): Promise<SlackAllowedChannelIdsResolution>;
|
|
112
|
+
|
|
113
|
+
export { type ParseSlackTargetOptions, type ParseSlackTargetsResult, type ResolveSlackAllowedChannelIdsOptions, type ResolveSlackChannelTargetsOptions, type ResolveSlackUserTargetsOptions, type SlackAllowedChannelIdsResolution, type SlackResolvedTarget, type SlackTarget, type SlackTargetKind, type SlackTargetResolutionClient, type SlackTargetResolutionError, type SlackTargetResolutionErrorCode, type SlackTargetResolutionResult, type SlackTargetSource, type SlackTargetValueKind, parseSlackTarget, parseSlackTargets, resolveSlackAllowedChannelIds, resolveSlackChannelTargets, resolveSlackUserTargets };
|