@eliya-oss/agent-slack 0.1.11 → 0.1.12

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.
@@ -1,36 +0,0 @@
1
- import { flagBoolean, flagString, parseArgs } from "../cli/args.js";
2
- import { errorEnvelope, serializeJson } from "../output/envelope.js";
3
- import { renderHumanErrorEnvelope } from "../output/human.js";
4
- import { dispatch, renderDispatchResult } from "./commands.js";
5
- export const executeCli = async (argv, services, options = {}) => {
6
- let parsed = null;
7
- try {
8
- parsed = parseArgs(argv);
9
- const result = await dispatch(parsed, services);
10
- return {
11
- exitCode: 0,
12
- stdout: renderDispatchResult(parsed, result, options),
13
- stderr: ""
14
- };
15
- }
16
- catch (error) {
17
- const { envelope, exitCode } = errorEnvelope(error);
18
- const pretty = parsed === null ? argv.includes("--pretty") : flagBoolean(parsed, "pretty");
19
- const stderr = shouldRenderJsonError(argv, parsed, options)
20
- ? serializeJson(envelope, pretty)
21
- : renderHumanErrorEnvelope(envelope, {
22
- color: shouldColorError(argv, parsed, options)
23
- });
24
- return {
25
- exitCode,
26
- stdout: "",
27
- stderr
28
- };
29
- }
30
- };
31
- const shouldRenderJsonError = (argv, parsed, options) => parsed === null
32
- ? argv.includes("--json") || options.stdoutIsTty !== true
33
- : flagBoolean(parsed, "json") || flagString(parsed, "format") === "json" || options.stdoutIsTty !== true;
34
- const shouldColorError = (argv, parsed, options) => options.stdoutIsTty === true &&
35
- options.env?.NO_COLOR === undefined &&
36
- (parsed === null ? !argv.includes("--no-color") : !flagBoolean(parsed, "no-color"));
@@ -1,40 +0,0 @@
1
- import { readFile } from "node:fs/promises";
2
- import { InvalidPayload, UsageError } from "../domain/errors.js";
3
- export const readStdin = async () => {
4
- const chunks = [];
5
- for await (const chunk of process.stdin) {
6
- chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
7
- }
8
- return Buffer.concat(chunks).toString("utf8");
9
- };
10
- export const parseJsonPayload = async (input) => {
11
- const source = input.inline ?? input.positional;
12
- if (source === undefined) {
13
- return {};
14
- }
15
- const raw = source === "-"
16
- ? await readStdin()
17
- : source.startsWith("@")
18
- ? await readFile(source.slice(1), "utf8")
19
- : source;
20
- try {
21
- const parsed = JSON.parse(raw);
22
- if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
23
- throw new InvalidPayload("Payload JSON must be an object");
24
- }
25
- return parsed;
26
- }
27
- catch (error) {
28
- if (error instanceof InvalidPayload) {
29
- throw error;
30
- }
31
- throw new InvalidPayload("Invalid JSON payload", { source: source === "-" ? "stdin" : source });
32
- }
33
- };
34
- export const requirePositional = (positionals, index, label) => {
35
- const value = positionals[index];
36
- if (value === undefined) {
37
- throw new UsageError(`Missing ${label}`, { argument: label });
38
- }
39
- return value;
40
- };
@@ -1 +0,0 @@
1
- export {};
@@ -1,62 +0,0 @@
1
- import { UnsafeMethodBlocked } from "../domain/errors.js";
2
- import { pagingFrom } from "../output/envelope.js";
3
- export const callSlack = async (services, options) => {
4
- const safety = services.methodCatalog.safetyFor(options.method);
5
- if (isUnsafe(safety) && (!options.allowWrite || !options.yes)) {
6
- throw new UnsafeMethodBlocked(`Refusing unsafe Slack method ${options.method}`, {
7
- method: options.method,
8
- safety
9
- });
10
- }
11
- if (!options.all) {
12
- const result = await services.slackWebApi.call({
13
- method: options.method,
14
- token: options.token,
15
- payload: options.payload
16
- });
17
- return {
18
- method: options.method,
19
- response: result.response,
20
- items: extractItems(services, options.method, result.response)
21
- };
22
- }
23
- const itemKey = services.methodCatalog.itemKeyFor(options.method);
24
- const collected = [];
25
- let cursor;
26
- let lastResponse = {};
27
- for (let page = 0; page < 100; page += 1) {
28
- const payload = cursor === undefined ? options.payload : { ...options.payload, cursor };
29
- const result = await services.slackWebApi.call({
30
- method: options.method,
31
- token: options.token,
32
- payload
33
- });
34
- lastResponse = result.response;
35
- collected.push(...extractItems(services, options.method, result.response));
36
- const paging = pagingFrom(result.response);
37
- if (paging.next_cursor === null || itemKey === null) {
38
- break;
39
- }
40
- cursor = paging.next_cursor;
41
- }
42
- return {
43
- method: options.method,
44
- response: itemKey === null ? lastResponse : { ...lastResponse, [itemKey]: collected },
45
- items: collected
46
- };
47
- };
48
- const isUnsafe = (safety) => safety === "write" || safety === "destructive" || safety === "admin";
49
- const extractItems = (services, method, response) => {
50
- const itemKey = services.methodCatalog.itemKeyFor(method);
51
- if (itemKey === null) {
52
- return [];
53
- }
54
- const value = response[itemKey];
55
- if (Array.isArray(value)) {
56
- return value;
57
- }
58
- if (value !== undefined && typeof value === "object" && value !== null) {
59
- return Object.entries(value).map(([key, entry]) => ({ key, value: entry }));
60
- }
61
- return [];
62
- };
package/dist/cli/args.js DELETED
@@ -1,74 +0,0 @@
1
- import { UsageError } from "../domain/errors.js";
2
- const booleanFlags = new Set([
3
- "all",
4
- "allow-write",
5
- "help",
6
- "json",
7
- "no-color",
8
- "raw",
9
- "pretty",
10
- "full",
11
- "trace",
12
- "yes",
13
- "no-cache",
14
- "inclusive",
15
- "oauth",
16
- "no-open"
17
- ]);
18
- export const parseArgs = (argv) => {
19
- const flags = new Map();
20
- const positionals = [];
21
- for (let index = 0; index < argv.length; index += 1) {
22
- const token = argv[index];
23
- if (token === undefined) {
24
- continue;
25
- }
26
- if (token === "--") {
27
- positionals.push(...argv.slice(index + 1));
28
- break;
29
- }
30
- if (!token.startsWith("--") || token === "-") {
31
- positionals.push(token);
32
- continue;
33
- }
34
- const raw = token.slice(2);
35
- const eq = raw.indexOf("=");
36
- const name = eq >= 0 ? raw.slice(0, eq) : raw;
37
- if (name === "") {
38
- throw new UsageError("Invalid empty flag");
39
- }
40
- if (eq >= 0) {
41
- flags.set(name, raw.slice(eq + 1));
42
- continue;
43
- }
44
- if (booleanFlags.has(name)) {
45
- flags.set(name, true);
46
- continue;
47
- }
48
- const value = argv[index + 1];
49
- if (value === undefined || value.startsWith("--")) {
50
- throw new UsageError(`Missing value for --${name}`, { flag: name });
51
- }
52
- flags.set(name, value);
53
- index += 1;
54
- }
55
- return { tokens: argv, flags, positionals };
56
- };
57
- export const flagString = (parsed, name, fallback) => {
58
- const value = parsed.flags.get(name);
59
- if (typeof value === "string") {
60
- return value;
61
- }
62
- return fallback;
63
- };
64
- export const flagBoolean = (parsed, name) => parsed.flags.get(name) === true;
65
- export const requireFlag = (parsed, name) => {
66
- const value = flagString(parsed, name);
67
- if (value === undefined) {
68
- throw new UsageError(`Missing required --${name}`, { flag: name });
69
- }
70
- return value;
71
- };
72
- export const splitCsv = (value) => value === undefined || value.trim() === ""
73
- ? []
74
- : value.split(",").map((item) => item.trim()).filter(Boolean);
@@ -1,374 +0,0 @@
1
- import { createRequire } from "node:module";
2
- const require = createRequire(import.meta.url);
3
- const packageJson = require("../../package.json");
4
- export const PRIMARY_COMMAND_NAME = "agent-slack";
5
- export const SHORT_COMMAND_NAME = "aslk";
6
- export const COMMAND_NAMES = [PRIMARY_COMMAND_NAME, SHORT_COMMAND_NAME];
7
- export const CLI_VERSION = packageJson.version ?? "0.0.0";
8
- export const commandMetadata = [
9
- {
10
- path: ["describe"],
11
- summary: "Print the full command catalog as JSON.",
12
- flags: ["--json"],
13
- safety: "read",
14
- output: "command metadata",
15
- examples: ["agent-slack describe --json"]
16
- },
17
- {
18
- path: ["completion"],
19
- summary: "Generate a shell completion script.",
20
- args: ["bash|zsh"],
21
- safety: "read",
22
- output: "shell completion script",
23
- examples: ["agent-slack completion zsh > ~/.zfunc/_agent-slack"]
24
- },
25
- {
26
- path: ["auth", "status"],
27
- summary: "Show the active Slack profile.",
28
- flags: ["--profile", "--json"],
29
- safety: "read",
30
- output: "profile status",
31
- examples: ["agent-slack auth status --json"]
32
- },
33
- {
34
- path: ["auth", "login"],
35
- summary: "Connect a Slack workspace profile.",
36
- flags: ["--profile", "--oauth", "--client-id", "--client-secret", "--scopes", "--user-scopes", "--redirect-uri", "--auth-url-out", "--timeout-ms", "--no-open", "--token", "--json"],
37
- safety: "read",
38
- output: "profile status",
39
- examples: [
40
- "agent-slack auth login --json",
41
- "AGENT_SLACK_TOKEN=xoxb-... agent-slack auth login --profile work --scopes channels:read --json",
42
- "agent-slack auth login --oauth --client-id 123.456 --client-secret secret --scopes channels:read,channels:history --json",
43
- ]
44
- },
45
- {
46
- path: ["auth", "scopes"],
47
- summary: "Show scopes granted to the active profile.",
48
- flags: ["--profile", "--json"],
49
- safety: "read",
50
- output: "scope list",
51
- examples: ["agent-slack auth scopes --json"]
52
- },
53
- {
54
- path: ["auth", "profiles", "list"],
55
- summary: "List local Slack profiles.",
56
- flags: ["--json"],
57
- safety: "read",
58
- output: "profile list",
59
- examples: ["agent-slack auth profiles list --json"]
60
- },
61
- {
62
- path: ["auth", "logout"],
63
- summary: "Delete a local Slack profile.",
64
- flags: ["--profile", "--json"],
65
- safety: "destructive",
66
- output: "deleted profile status",
67
- examples: ["agent-slack auth logout --profile work --yes --json"]
68
- },
69
- {
70
- path: ["auth", "test"],
71
- summary: "Test the active Slack profile.",
72
- methods: ["auth.test"],
73
- scopes: [],
74
- safety: "read",
75
- output: "Slack auth.test response",
76
- examples: ["agent-slack auth test --json"]
77
- },
78
- {
79
- path: ["team", "get"],
80
- summary: "Show Slack workspace details.",
81
- methods: ["team.info"],
82
- scopes: ["team:read"],
83
- safety: "read",
84
- output: "team info",
85
- examples: ["agent-slack team get --json"]
86
- },
87
- {
88
- path: ["team", "profile", "get"],
89
- summary: "Show workspace profile fields.",
90
- methods: ["team.profile.get"],
91
- scopes: ["users.profile:read"],
92
- safety: "read",
93
- output: "team profile fields",
94
- examples: ["agent-slack team profile get --json"]
95
- },
96
- {
97
- path: ["enterprise", "get"],
98
- summary: "Show enterprise and workspace identity.",
99
- methods: ["team.info"],
100
- scopes: ["team:read"],
101
- safety: "read",
102
- output: "team or enterprise info",
103
- examples: ["agent-slack enterprise get --json"]
104
- },
105
- {
106
- path: ["user", "list"],
107
- summary: "List users visible to the active profile.",
108
- flags: ["--limit", "--all", "--json"],
109
- methods: ["users.list"],
110
- scopes: ["users:read"],
111
- safety: "read",
112
- output: "user list",
113
- examples: ["agent-slack user list --limit 50 --json"]
114
- },
115
- {
116
- path: ["user", "get"],
117
- summary: "Show one user.",
118
- args: ["USER_ID"],
119
- methods: ["users.info"],
120
- scopes: ["users:read"],
121
- safety: "read",
122
- output: "user info",
123
- examples: ["agent-slack user get U123 --json"]
124
- },
125
- {
126
- path: ["user", "lookup"],
127
- summary: "Find a user by email.",
128
- flags: ["--email", "--json"],
129
- methods: ["users.lookupByEmail"],
130
- scopes: ["users:read.email"],
131
- safety: "read",
132
- output: "user info",
133
- examples: ["agent-slack user lookup --email dev@example.com --json"]
134
- },
135
- {
136
- path: ["user", "presence", "get"],
137
- summary: "Show user presence.",
138
- args: ["USER_ID"],
139
- methods: ["users.getPresence"],
140
- scopes: ["users:read"],
141
- safety: "read",
142
- output: "presence",
143
- examples: ["agent-slack user presence get U123 --json"]
144
- },
145
- {
146
- path: ["usergroups", "list"],
147
- summary: "List Slack user groups.",
148
- methods: ["usergroups.list"],
149
- scopes: ["usergroups:read"],
150
- safety: "read",
151
- output: "user group list",
152
- examples: ["agent-slack usergroups list --json"]
153
- },
154
- {
155
- path: ["usergroups", "users", "list"],
156
- summary: "List users in a Slack user group.",
157
- args: ["USERGROUP_ID"],
158
- methods: ["usergroups.users.list"],
159
- scopes: ["usergroups:read"],
160
- safety: "read",
161
- output: "user IDs",
162
- examples: ["agent-slack usergroups users list S123 --json"]
163
- },
164
- {
165
- path: ["api", "call"],
166
- summary: "Call a Slack Web API method with a JSON payload.",
167
- args: ["METHOD", "PAYLOAD_STDIN_MARKER"],
168
- flags: ["--payload", "--profile", "--token", "--all", "--raw", "--format", "--allow-write", "--yes", "--json"],
169
- safety: "unknown",
170
- output: "Slack Web API response",
171
- examples: [
172
- "agent-slack api call conversations.history --payload '{\"channel\":\"C123\"}' --json",
173
- "cat payload.json | agent-slack api call conversations.history -"
174
- ]
175
- },
176
- {
177
- path: ["api", "methods", "list"],
178
- summary: "List bundled Slack Web API metadata.",
179
- flags: ["--family", "--json"],
180
- safety: "read",
181
- output: "method metadata list",
182
- examples: ["agent-slack api methods list --family conversations --json"]
183
- },
184
- {
185
- path: ["api", "method", "describe"],
186
- summary: "Describe one Slack method.",
187
- args: ["METHOD"],
188
- flags: ["--json"],
189
- safety: "read",
190
- output: "method metadata",
191
- examples: ["agent-slack api method describe conversations.replies --json"]
192
- },
193
- {
194
- path: ["conversation", "list"],
195
- summary: "List conversations visible to the active profile.",
196
- methods: ["conversations.list"],
197
- scopes: ["channels:read", "groups:read", "im:read", "mpim:read"],
198
- safety: "read",
199
- output: "conversation list",
200
- examples: ["agent-slack conversation list --types public_channel,private_channel --json"]
201
- },
202
- {
203
- path: ["conversation", "history"],
204
- summary: "Read conversation history.",
205
- args: ["CHANNEL_ID"],
206
- methods: ["conversations.history"],
207
- scopes: ["channels:history", "groups:history", "im:history", "mpim:history"],
208
- safety: "read",
209
- output: "message list",
210
- examples: ["agent-slack conversation history C123 --limit 20 --json"]
211
- },
212
- {
213
- path: ["conversation", "context"],
214
- summary: "Build channel context for agents.",
215
- args: ["CHANNEL_ID"],
216
- methods: ["conversations.history", "conversations.replies", "users.info"],
217
- scopes: ["channels:history", "users:read"],
218
- safety: "read",
219
- output: "hydrated conversation context",
220
- examples: ["agent-slack conversation context C123 --since 24h --include users,threads --format ndjson"]
221
- },
222
- {
223
- path: ["thread", "get"],
224
- summary: "Read a complete Slack thread.",
225
- flags: ["--channel", "--ts", "--include", "--json"],
226
- methods: ["conversations.replies"],
227
- scopes: ["channels:history", "groups:history", "im:history", "mpim:history"],
228
- safety: "read",
229
- output: "thread messages",
230
- examples: ["agent-slack thread get --channel C123 --ts 1710000000.000100 --include users --json"]
231
- },
232
- {
233
- path: ["message", "get"],
234
- summary: "Read one Slack message by channel and timestamp.",
235
- flags: ["--channel", "--ts", "--json"],
236
- methods: ["conversations.history"],
237
- scopes: ["channels:history"],
238
- safety: "read",
239
- output: "message",
240
- examples: ["agent-slack message get --channel C123 --ts 1710000000.000100 --json"]
241
- },
242
- {
243
- path: ["message", "permalink"],
244
- summary: "Get a Slack permalink for a message.",
245
- flags: ["--channel", "--ts", "--json"],
246
- methods: ["chat.getPermalink"],
247
- safety: "read",
248
- output: "permalink",
249
- examples: ["agent-slack message permalink --channel C123 --ts 1710000000.000100 --json"]
250
- },
251
- {
252
- path: ["search", "context"],
253
- summary: "Search Slack for relevant context.",
254
- flags: ["--query", "--content-types", "--json"],
255
- methods: ["assistant.search.context"],
256
- scopes: ["search:read.public", "search:read.private"],
257
- safety: "read",
258
- output: "search context",
259
- examples: ["agent-slack search context --query 'project atlas' --json"]
260
- },
261
- {
262
- path: ["file", "list"],
263
- summary: "List files visible to the active profile.",
264
- methods: ["files.list"],
265
- scopes: ["files:read"],
266
- safety: "read",
267
- output: "file list",
268
- examples: ["agent-slack file list --channel C123 --json"]
269
- },
270
- {
271
- path: ["file", "download"],
272
- summary: "Download a Slack file to disk.",
273
- args: ["FILE_ID"],
274
- flags: ["--out", "--profile", "--token", "--json"],
275
- methods: ["files.info"],
276
- scopes: ["files:read"],
277
- safety: "read",
278
- output: "download status",
279
- examples: ["agent-slack file download F123 --out ./artifact.pdf --json"]
280
- }
281
- ];
282
- export const describeAllCommands = () => ({
283
- name: PRIMARY_COMMAND_NAME,
284
- aliases: [SHORT_COMMAND_NAME],
285
- version: CLI_VERSION,
286
- commands: commandMetadata
287
- });
288
- export const findCommandMetadata = (path) => commandMetadata.find((command) => command.path.join(" ") === path.join(" ")) ?? null;
289
- export const describeCommandGroup = (group) => ({
290
- name: group,
291
- commands: commandMetadata.filter((command) => command.path[0] === group)
292
- });
293
- export const renderHumanHelp = (path) => {
294
- if (path.join(" ") === "auth login") {
295
- return renderAuthLoginHelp();
296
- }
297
- const command = findCommandMetadata(path);
298
- if (command !== null) {
299
- return [
300
- `${PRIMARY_COMMAND_NAME} ${command.path.join(" ")}`,
301
- "",
302
- command.summary,
303
- "",
304
- command.args === undefined ? "" : `Usage: ${PRIMARY_COMMAND_NAME} ${command.path.join(" ")} ${command.args.join(" ")}`,
305
- command.scopes === undefined ? "" : `Scopes: ${command.scopes.join(", ")}`,
306
- "",
307
- "Examples:",
308
- ...command.examples.map((example) => ` ${example}`)
309
- ].filter((line) => line !== "").join("\n") + "\n";
310
- }
311
- const commands = path.length === 0 ? commandMetadata : commandMetadata.filter((item) => item.path[0] === path[0]);
312
- return [
313
- PRIMARY_COMMAND_NAME,
314
- "",
315
- "Slack context CLI for agents.",
316
- "",
317
- "Commands:",
318
- ...commands.map((item) => ` ${item.path.join(" ").padEnd(28)} ${item.summary}`)
319
- ].join("\n") + "\n";
320
- };
321
- const renderAuthLoginHelp = () => [
322
- "agent-slack auth login",
323
- "",
324
- "Connect a Slack workspace profile.",
325
- "",
326
- "Browser login",
327
- " agent-slack auth login",
328
- "",
329
- " Opens Slack in the browser and stores a local Slack profile.",
330
- "",
331
- "Headless setup",
332
- " agent-slack auth login --token \"$SLACK_BOT_TOKEN\" --scopes channels:read,channels:history,users:read",
333
- "",
334
- " Stores an existing bot token as a local Slack profile.",
335
- "",
336
- "Development and self-hosted OAuth",
337
- " agent-slack auth login --oauth --client-id \"$SLACK_CLIENT_ID\" --client-secret \"$SLACK_CLIENT_SECRET\"",
338
- "",
339
- "Options",
340
- " --profile NAME Save as a named profile.",
341
- " --token TOKEN Store an existing Slack bot token.",
342
- " --scopes LIST Scopes to request or record.",
343
- " --user-scopes LIST User scopes to request during OAuth.",
344
- " --oauth Use Slack OAuth with app credentials.",
345
- " --client-id VALUE Override the Slack app Client ID.",
346
- " --client-secret VALUE Slack app Client Secret.",
347
- " --no-open Print OAuth URL instead of opening the browser.",
348
- " --auth-url-out PATH Write OAuth URL for headless flows.",
349
- " --json Emit machine-readable JSON.",
350
- "",
351
- "Notes",
352
- " Browser login uses PKCE with Agent Slack's public Slack app.",
353
- " App credentials are for development and self-hosted setups.",
354
- ""
355
- ].join("\n");
356
- export const renderCompletion = (shell) => {
357
- const words = [...new Set(commandMetadata.flatMap((command) => command.path))];
358
- const commandWords = commandMetadata.map((command) => command.path.join(" "));
359
- if (shell === "bash") {
360
- return `complete -W '${words.join(" ")}' ${COMMAND_NAMES.join(" ")}\n`;
361
- }
362
- if (shell === "zsh") {
363
- return [
364
- `#compdef ${COMMAND_NAMES.join(" ")}`,
365
- "_agent_slack_commands=(",
366
- ...commandWords.map((command) => ` '${command}:${summaryFor(command)}'`),
367
- ")",
368
- `_describe '${PRIMARY_COMMAND_NAME} command' _agent_slack_commands`,
369
- ""
370
- ].join("\n");
371
- }
372
- return "";
373
- };
374
- const summaryFor = (path) => commandMetadata.find((command) => command.path.join(" ") === path)?.summary.replace(/'/g, "") ?? "";
package/dist/cli/types.js DELETED
@@ -1 +0,0 @@
1
- export {};
@@ -1,68 +0,0 @@
1
- export class TaggedSlkError extends Error {
2
- details;
3
- constructor(message, details = {}) {
4
- super(message);
5
- this.name = new.target.name;
6
- this.details = details;
7
- }
8
- }
9
- export class NotAuthenticated extends TaggedSlkError {
10
- _tag = "NotAuthenticated";
11
- exitCode = 4;
12
- }
13
- export class MissingScope extends TaggedSlkError {
14
- _tag = "MissingScope";
15
- exitCode = 4;
16
- }
17
- export class PermissionDenied extends TaggedSlkError {
18
- _tag = "PermissionDenied";
19
- exitCode = 4;
20
- }
21
- export class SlackRateLimited extends TaggedSlkError {
22
- _tag = "SlackRateLimited";
23
- exitCode = 6;
24
- retryAfterSeconds;
25
- constructor(message, details = {}) {
26
- super(message, details);
27
- this.retryAfterSeconds = details.retryAfterSeconds;
28
- }
29
- }
30
- export class SlackApiFailed extends TaggedSlkError {
31
- _tag = "SlackApiFailed";
32
- exitCode = 1;
33
- slackError;
34
- constructor(message, details = {}) {
35
- super(message, details);
36
- this.slackError = details.slackError;
37
- }
38
- }
39
- export class InvalidPayload extends TaggedSlkError {
40
- _tag = "InvalidPayload";
41
- exitCode = 2;
42
- }
43
- export class ResourceNotFound extends TaggedSlkError {
44
- _tag = "ResourceNotFound";
45
- exitCode = 3;
46
- }
47
- export class UnsafeMethodBlocked extends TaggedSlkError {
48
- _tag = "UnsafeMethodBlocked";
49
- exitCode = 5;
50
- }
51
- export class UsageError extends TaggedSlkError {
52
- _tag = "UsageError";
53
- exitCode = 2;
54
- }
55
- export class UnsupportedMethod extends TaggedSlkError {
56
- _tag = "UnsupportedMethod";
57
- exitCode = 2;
58
- }
59
- export const isSlkError = (error) => error instanceof TaggedSlkError;
60
- export const normalizeUnknownError = (error) => {
61
- if (isSlkError(error)) {
62
- return error;
63
- }
64
- if (error instanceof Error) {
65
- return new SlackApiFailed(error.message, { cause: error.name });
66
- }
67
- return new SlackApiFailed("Unexpected failure", { cause: String(error) });
68
- };