@mono-agent/slack-adapter 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/README.md +43 -0
- package/dist/adapter.d.ts +124 -0
- package/dist/adapter.d.ts.map +1 -0
- package/dist/adapter.js +370 -0
- package/dist/adapter.js.map +1 -0
- package/dist/config.d.ts +46 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +119 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/message-stream.d.ts +54 -0
- package/dist/message-stream.d.ts.map +1 -0
- package/dist/message-stream.js +169 -0
- package/dist/message-stream.js.map +1 -0
- package/dist/slack-client.d.ts +44 -0
- package/dist/slack-client.d.ts.map +1 -0
- package/dist/slack-client.js +204 -0
- package/dist/slack-client.js.map +1 -0
- package/dist/slack-markdown.d.ts +2 -0
- package/dist/slack-markdown.d.ts.map +1 -0
- package/dist/slack-markdown.js +82 -0
- package/dist/slack-markdown.js.map +1 -0
- package/dist/socket-mode-runner.d.ts +50 -0
- package/dist/socket-mode-runner.d.ts.map +1 -0
- package/dist/socket-mode-runner.js +222 -0
- package/dist/socket-mode-runner.js.map +1 -0
- package/dist/start.d.ts +59 -0
- package/dist/start.d.ts.map +1 -0
- package/dist/start.js +101 -0
- package/dist/start.js.map +1 -0
- package/dist/types.d.ts +89 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +36 -0
package/dist/config.js
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { defineFieldGroup, layerJsonOntoEnv, readBoolean, readCsv, readJsonSection, readRequired, readSettingsJson, redactedSecret, } from "@mono-agent/settings";
|
|
2
|
+
export class SlackAdapterConfigError extends Error {
|
|
3
|
+
code;
|
|
4
|
+
details;
|
|
5
|
+
constructor(code, message, details = {}) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = "SlackAdapterConfigError";
|
|
8
|
+
this.code = code;
|
|
9
|
+
this.details = { ...details, code };
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export const slackFieldGroup = defineFieldGroup({
|
|
13
|
+
id: "slack",
|
|
14
|
+
label: "Slack",
|
|
15
|
+
description: "Optional Slack Socket Mode adapter configuration. Tokens are write-only.",
|
|
16
|
+
fields: [
|
|
17
|
+
{
|
|
18
|
+
id: "slack.botToken",
|
|
19
|
+
label: "Bot token",
|
|
20
|
+
description: "Slack bot token used for chat.postMessage and chat.update.",
|
|
21
|
+
kind: "secret",
|
|
22
|
+
path: ["slack", "botToken"],
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
id: "slack.appToken",
|
|
26
|
+
label: "App token",
|
|
27
|
+
description: "Slack app-level token with connections:write for Socket Mode.",
|
|
28
|
+
kind: "secret",
|
|
29
|
+
path: ["slack", "appToken"],
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
id: "slack.allowedChannelIds",
|
|
33
|
+
label: "Allowed channel IDs",
|
|
34
|
+
description: "Comma-separated Slack channel or DM IDs the adapter may respond to.",
|
|
35
|
+
kind: "csv",
|
|
36
|
+
placeholder: "D123456, C123456",
|
|
37
|
+
path: ["slack", "allowedChannelIds"],
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
id: "slack.allowAllChannels",
|
|
41
|
+
label: "Allow all channels",
|
|
42
|
+
description: "Explicitly permit every channel delivered to the app.",
|
|
43
|
+
kind: "switch",
|
|
44
|
+
path: ["slack", "allowAllChannels"],
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
id: "slack.botUserIds",
|
|
48
|
+
label: "Bot user IDs",
|
|
49
|
+
description: "Comma-separated Slack user IDs that should count as this bot.",
|
|
50
|
+
kind: "csv",
|
|
51
|
+
placeholder: "U123456",
|
|
52
|
+
path: ["slack", "botUserIds"],
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
id: "slack.mentionTextAliases",
|
|
56
|
+
label: "Mention aliases",
|
|
57
|
+
description: "Comma-separated mention text aliases to strip before runtime calls.",
|
|
58
|
+
kind: "csv",
|
|
59
|
+
placeholder: "@agent, Assistant",
|
|
60
|
+
path: ["slack", "mentionTextAliases"],
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
id: "slack.stripMentionText",
|
|
64
|
+
label: "Strip mention text",
|
|
65
|
+
description: "Remove configured bot mentions and aliases before sending text to the responder.",
|
|
66
|
+
kind: "switch",
|
|
67
|
+
path: ["slack", "stripMentionText"],
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
});
|
|
71
|
+
const missingConfig = (message, details) => new SlackAdapterConfigError("missing_required_config", message, details);
|
|
72
|
+
const invalidConfig = (message, details) => new SlackAdapterConfigError("invalid_config", message, details);
|
|
73
|
+
export async function loadSlackAdapterConfig(input) {
|
|
74
|
+
const json = input.json ?? (input.jsonPath === undefined ? {} : (await readSettingsJson(input.jsonPath)).json);
|
|
75
|
+
const env = layerSlackJsonOntoEnv(json, input.env);
|
|
76
|
+
const botToken = readRequired(env.MONO_AGENT_SLACK_BOT_TOKEN, "MONO_AGENT_SLACK_BOT_TOKEN", missingConfig);
|
|
77
|
+
const appToken = readRequired(env.MONO_AGENT_SLACK_APP_TOKEN, "MONO_AGENT_SLACK_APP_TOKEN", missingConfig);
|
|
78
|
+
const allowedChannelIds = readCsv(env.MONO_AGENT_SLACK_ALLOWED_CHANNEL_IDS);
|
|
79
|
+
const allowAllChannels = readBoolean(env.MONO_AGENT_SLACK_ALLOW_ALL_CHANNELS, "MONO_AGENT_SLACK_ALLOW_ALL_CHANNELS", false, invalidConfig);
|
|
80
|
+
const botUserIds = readCsv(env.MONO_AGENT_SLACK_BOT_USER_IDS);
|
|
81
|
+
const mentionTextAliases = readCsv(env.MONO_AGENT_SLACK_MENTION_TEXT_ALIASES);
|
|
82
|
+
const stripMentionText = readBoolean(env.MONO_AGENT_SLACK_STRIP_MENTION_TEXT, "MONO_AGENT_SLACK_STRIP_MENTION_TEXT", botUserIds.length > 0 || mentionTextAliases.length > 0, invalidConfig);
|
|
83
|
+
if (!allowAllChannels && allowedChannelIds.length === 0) {
|
|
84
|
+
throw missingConfig("Slack adapter requires MONO_AGENT_SLACK_ALLOWED_CHANNEL_IDS or MONO_AGENT_SLACK_ALLOW_ALL_CHANNELS=true.", { env: "MONO_AGENT_SLACK_ALLOWED_CHANNEL_IDS" });
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
botToken,
|
|
88
|
+
appToken,
|
|
89
|
+
allowedChannelIds,
|
|
90
|
+
allowAllChannels,
|
|
91
|
+
botUserIds,
|
|
92
|
+
mentionTextAliases,
|
|
93
|
+
stripMentionText,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
export function redactSlackAdapterConfig(config) {
|
|
97
|
+
return {
|
|
98
|
+
botToken: redactedSecret(config.botToken),
|
|
99
|
+
appToken: redactedSecret(config.appToken),
|
|
100
|
+
allowedChannelIds: { count: config.allowedChannelIds.length },
|
|
101
|
+
allowAllChannels: config.allowAllChannels,
|
|
102
|
+
botUserIds: { count: config.botUserIds.length },
|
|
103
|
+
mentionTextAliases: { count: config.mentionTextAliases.length },
|
|
104
|
+
stripMentionText: config.stripMentionText,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function layerSlackJsonOntoEnv(json, env) {
|
|
108
|
+
const section = readJsonSection(json, "slack");
|
|
109
|
+
return layerJsonOntoEnv(env, [
|
|
110
|
+
{ env: "MONO_AGENT_SLACK_BOT_TOKEN", value: section.botToken },
|
|
111
|
+
{ env: "MONO_AGENT_SLACK_APP_TOKEN", value: section.appToken },
|
|
112
|
+
{ env: "MONO_AGENT_SLACK_ALLOWED_CHANNEL_IDS", value: section.allowedChannelIds, kind: "csv" },
|
|
113
|
+
{ env: "MONO_AGENT_SLACK_ALLOW_ALL_CHANNELS", value: section.allowAllChannels, kind: "boolean" },
|
|
114
|
+
{ env: "MONO_AGENT_SLACK_BOT_USER_IDS", value: section.botUserIds, kind: "csv" },
|
|
115
|
+
{ env: "MONO_AGENT_SLACK_MENTION_TEXT_ALIASES", value: section.mentionTextAliases, kind: "csv" },
|
|
116
|
+
{ env: "MONO_AGENT_SLACK_STRIP_MENTION_TEXT", value: section.stripMentionText, kind: "boolean" },
|
|
117
|
+
]);
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type { SlackAppsConnectionsOpenResult, SlackAuthTestResult, SlackChannelId, SlackChatPostMessageParams, SlackChatPostMessageResult, SlackChatUpdateParams, SlackChatUpdateResult, SlackEventBase, SlackEventCallback, SlackMessageTs, SlackRequestOptions, SlackSocketModeEnvelope, SlackUserId, SlackWebApi, } from "./types.js";
|
|
2
|
+
export { SlackApiError, SlackWebApiClient, } from "./slack-client.js";
|
|
3
|
+
export type { SlackApiErrorDetails, SlackApiErrorKind, SlackWebApiClientOptions, } from "./slack-client.js";
|
|
4
|
+
export { SlackMessageStream, } from "./message-stream.js";
|
|
5
|
+
export type { AgentMessageStream, SlackMessageStreamLogger, SlackMessageStreamOptions, } from "./message-stream.js";
|
|
6
|
+
export { SlackAdapter, } from "./adapter.js";
|
|
7
|
+
export type { AgentRequest, AgentResponder, AgentResponse, SlackAdapterLogger, SlackAdapterMessages, SlackAdapterOptions, SlackAdapterStreamOptions, SlackEventHandlingResult, SlackEventIgnoredReason, SlackRequestMetadata, SlackTriggerKind, } from "./adapter.js";
|
|
8
|
+
export { SlackSocketModeRunner, } from "./socket-mode-runner.js";
|
|
9
|
+
export type { SlackEventCallbackHandler, SlackSocketModeRunnerBackoffOptions, SlackSocketModeRunnerLogger, SlackSocketModeRunnerOptions, SlackSocketModeRunnerStartOptions, SlackWebSocketFactory, SlackWebSocketLike, } from "./socket-mode-runner.js";
|
|
10
|
+
export { startSlackAdapter, } from "./start.js";
|
|
11
|
+
export type { SlackAdapterStartLogger, SlackAdapterStartOptions, SlackAdapterStartResult, SlackApiFactoryInput, } from "./start.js";
|
|
12
|
+
export { loadSlackAdapterConfig, redactSlackAdapterConfig, SlackAdapterConfigError, slackFieldGroup, } from "./config.js";
|
|
13
|
+
export type { LoadSlackAdapterConfigInput, RedactedSlackAdapterConfig, SlackAdapterConfig, SlackAdapterConfigErrorCode, SlackAdapterConfigErrorDetails, } from "./config.js";
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,8BAA8B,EAC9B,mBAAmB,EACnB,cAAc,EACd,0BAA0B,EAC1B,0BAA0B,EAC1B,qBAAqB,EACrB,qBAAqB,EACrB,cAAc,EACd,kBAAkB,EAClB,cAAc,EACd,mBAAmB,EACnB,uBAAuB,EACvB,WAAW,EACX,WAAW,GACZ,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,aAAa,EACb,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,oBAAoB,EACpB,iBAAiB,EACjB,wBAAwB,GACzB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,kBAAkB,GACnB,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EACV,kBAAkB,EAClB,wBAAwB,EACxB,yBAAyB,GAC1B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,YAAY,GACb,MAAM,cAAc,CAAC;AACtB,YAAY,EACV,YAAY,EACZ,cAAc,EACd,aAAa,EACb,kBAAkB,EAClB,oBAAoB,EACpB,mBAAmB,EACnB,yBAAyB,EACzB,wBAAwB,EACxB,uBAAuB,EACvB,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,qBAAqB,GACtB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EACV,yBAAyB,EACzB,mCAAmC,EACnC,2BAA2B,EAC3B,4BAA4B,EAC5B,iCAAiC,EACjC,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,iBAAiB,GAClB,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,uBAAuB,EACvB,wBAAwB,EACxB,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,sBAAsB,EACtB,wBAAwB,EACxB,uBAAuB,EACvB,eAAe,GAChB,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,2BAA2B,EAC3B,0BAA0B,EAC1B,kBAAkB,EAClB,2BAA2B,EAC3B,8BAA8B,GAC/B,MAAM,aAAa,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { SlackApiError, SlackWebApiClient, } from "./slack-client.js";
|
|
2
|
+
export { SlackMessageStream, } from "./message-stream.js";
|
|
3
|
+
export { SlackAdapter, } from "./adapter.js";
|
|
4
|
+
export { SlackSocketModeRunner, } from "./socket-mode-runner.js";
|
|
5
|
+
export { startSlackAdapter, } from "./start.js";
|
|
6
|
+
export { loadSlackAdapterConfig, redactSlackAdapterConfig, SlackAdapterConfigError, slackFieldGroup, } from "./config.js";
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAiBA,OAAO,EACL,aAAa,EACb,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAM3B,OAAO,EACL,kBAAkB,GACnB,MAAM,qBAAqB,CAAC;AAM7B,OAAO,EACL,YAAY,GACb,MAAM,cAAc,CAAC;AActB,OAAO,EACL,qBAAqB,GACtB,MAAM,yBAAyB,CAAC;AAUjC,OAAO,EACL,iBAAiB,GAClB,MAAM,YAAY,CAAC;AAOpB,OAAO,EACL,sBAAsB,EACtB,wBAAwB,EACxB,uBAAuB,EACvB,eAAe,GAChB,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { AgentMessageStream as AgentMessageStreamBase } from "@mono-agent/agent-contracts";
|
|
2
|
+
import type { SlackChannelId, SlackMessageTs, SlackWebApi } from "./types.js";
|
|
3
|
+
export interface AgentMessageStream extends AgentMessageStreamBase {
|
|
4
|
+
status(text: string): Promise<void>;
|
|
5
|
+
append(delta: string): Promise<void>;
|
|
6
|
+
replace(text: string): Promise<void>;
|
|
7
|
+
finish(finalText?: string): Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
export interface SlackMessageStreamOptions {
|
|
10
|
+
api: SlackWebApi;
|
|
11
|
+
channelId: SlackChannelId;
|
|
12
|
+
threadTs?: SlackMessageTs;
|
|
13
|
+
initialStatusText?: string;
|
|
14
|
+
editDebounceMs?: number;
|
|
15
|
+
maxMessageChars?: number;
|
|
16
|
+
logger?: SlackMessageStreamLogger;
|
|
17
|
+
}
|
|
18
|
+
export interface SlackMessageStreamLogger {
|
|
19
|
+
debug?(message: string, metadata?: Record<string, unknown>): void;
|
|
20
|
+
warn?(message: string, metadata?: Record<string, unknown>): void;
|
|
21
|
+
error?(message: string, metadata?: Record<string, unknown>): void;
|
|
22
|
+
}
|
|
23
|
+
export declare class SlackMessageStream implements AgentMessageStream {
|
|
24
|
+
private readonly api;
|
|
25
|
+
private readonly channelId;
|
|
26
|
+
private readonly threadTs;
|
|
27
|
+
private readonly initialStatusText;
|
|
28
|
+
private readonly editDebounceMs;
|
|
29
|
+
private readonly maxMessageChars;
|
|
30
|
+
private readonly logger;
|
|
31
|
+
private currentText;
|
|
32
|
+
private statusText;
|
|
33
|
+
private sentMessage;
|
|
34
|
+
private sendMessagePromise;
|
|
35
|
+
private editTimer;
|
|
36
|
+
private inFlightUpdate;
|
|
37
|
+
private lastAsyncError;
|
|
38
|
+
private finished;
|
|
39
|
+
constructor(options: SlackMessageStreamOptions);
|
|
40
|
+
status(text: string): Promise<void>;
|
|
41
|
+
append(delta: string): Promise<void>;
|
|
42
|
+
replace(text: string): Promise<void>;
|
|
43
|
+
finish(finalText?: string): Promise<void>;
|
|
44
|
+
private ensureMessage;
|
|
45
|
+
private withThread;
|
|
46
|
+
private scheduleUpdate;
|
|
47
|
+
private startInFlightUpdate;
|
|
48
|
+
private flushUpdate;
|
|
49
|
+
private cancelScheduledUpdate;
|
|
50
|
+
private awaitInFlightUpdate;
|
|
51
|
+
private throwIfAsyncError;
|
|
52
|
+
private assertOpen;
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=message-stream.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-stream.d.ts","sourceRoot":"","sources":["../src/message-stream.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,kBAAkB,IAAI,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAEhG,OAAO,KAAK,EACV,cAAc,EAEd,cAAc,EACd,WAAW,EACZ,MAAM,YAAY,CAAC;AAGpB,MAAM,WAAW,kBAAmB,SAAQ,sBAAsB;IAChE,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,MAAM,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,yBAAyB;IACxC,GAAG,EAAE,WAAW,CAAC;IACjB,SAAS,EAAE,cAAc,CAAC;IAC1B,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,wBAAwB,CAAC;CACnC;AAED,MAAM,WAAW,wBAAwB;IACvC,KAAK,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAClE,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACjE,KAAK,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CACnE;AAMD,qBAAa,kBAAmB,YAAW,kBAAkB;IAC3D,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAc;IAClC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAiB;IAC3C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA6B;IACtD,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;IAC3C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuC;IAE9D,OAAO,CAAC,WAAW,CAAM;IACzB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,WAAW,CAAyC;IAC5D,OAAO,CAAC,kBAAkB,CAAkD;IAC5E,OAAO,CAAC,SAAS,CAA4C;IAC7D,OAAO,CAAC,cAAc,CAA4B;IAClD,OAAO,CAAC,cAAc,CAAU;IAChC,OAAO,CAAC,QAAQ,CAAS;gBAEb,OAAO,EAAE,yBAAyB;IAqBxC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAWnC,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYpC,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQpC,MAAM,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAiCjC,aAAa;IAiB3B,OAAO,CAAC,UAAU;IASlB,OAAO,CAAC,cAAc;IAatB,OAAO,CAAC,mBAAmB;YAgBb,WAAW;IAUzB,OAAO,CAAC,qBAAqB;YAOf,mBAAmB;YAOnB,iBAAiB;IAY/B,OAAO,CAAC,UAAU;CAKnB"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { DEFAULT_EMPTY_FINAL_TEXT, DEFAULT_MAX_MESSAGE_CHARS, buildStreamingTailPreview, normalizeTrailing, splitTextByCodePoints, } from "@mono-agent/agent-contracts";
|
|
2
|
+
import { formatMarkdownForSlack } from "./slack-markdown.js";
|
|
3
|
+
const DEFAULT_INITIAL_STATUS_TEXT = "Thinking...";
|
|
4
|
+
const DEFAULT_EDIT_DEBOUNCE_MS = 750;
|
|
5
|
+
const EMPTY_FINAL_TEXT = DEFAULT_EMPTY_FINAL_TEXT;
|
|
6
|
+
export class SlackMessageStream {
|
|
7
|
+
api;
|
|
8
|
+
channelId;
|
|
9
|
+
threadTs;
|
|
10
|
+
initialStatusText;
|
|
11
|
+
editDebounceMs;
|
|
12
|
+
maxMessageChars;
|
|
13
|
+
logger;
|
|
14
|
+
currentText = "";
|
|
15
|
+
statusText;
|
|
16
|
+
sentMessage;
|
|
17
|
+
sendMessagePromise;
|
|
18
|
+
editTimer;
|
|
19
|
+
inFlightUpdate;
|
|
20
|
+
lastAsyncError;
|
|
21
|
+
finished = false;
|
|
22
|
+
constructor(options) {
|
|
23
|
+
this.api = options.api;
|
|
24
|
+
this.channelId = options.channelId;
|
|
25
|
+
this.threadTs = options.threadTs;
|
|
26
|
+
this.initialStatusText = normalizeTrailing(options.initialStatusText ?? DEFAULT_INITIAL_STATUS_TEXT, EMPTY_FINAL_TEXT);
|
|
27
|
+
this.statusText = this.initialStatusText;
|
|
28
|
+
this.editDebounceMs = options.editDebounceMs ?? DEFAULT_EDIT_DEBOUNCE_MS;
|
|
29
|
+
this.maxMessageChars = options.maxMessageChars ?? DEFAULT_MAX_MESSAGE_CHARS;
|
|
30
|
+
this.logger = options.logger;
|
|
31
|
+
if (!Number.isInteger(this.maxMessageChars) || this.maxMessageChars < 32) {
|
|
32
|
+
throw new RangeError("maxMessageChars must be an integer of at least 32.");
|
|
33
|
+
}
|
|
34
|
+
if (!Number.isFinite(this.editDebounceMs) || this.editDebounceMs < 0) {
|
|
35
|
+
throw new RangeError("editDebounceMs must be a non-negative number.");
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
async status(text) {
|
|
39
|
+
this.assertOpen();
|
|
40
|
+
await this.throwIfAsyncError();
|
|
41
|
+
this.statusText = normalizeTrailing(text, EMPTY_FINAL_TEXT);
|
|
42
|
+
const hadMessage = this.sentMessage !== undefined;
|
|
43
|
+
await this.ensureMessage();
|
|
44
|
+
if (hadMessage) {
|
|
45
|
+
await this.flushUpdate(this.statusText);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
async append(delta) {
|
|
49
|
+
this.assertOpen();
|
|
50
|
+
await this.throwIfAsyncError();
|
|
51
|
+
if (delta.length === 0) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
this.currentText += delta;
|
|
55
|
+
await this.ensureMessage();
|
|
56
|
+
this.scheduleUpdate();
|
|
57
|
+
}
|
|
58
|
+
async replace(text) {
|
|
59
|
+
this.assertOpen();
|
|
60
|
+
await this.throwIfAsyncError();
|
|
61
|
+
this.currentText = text;
|
|
62
|
+
await this.ensureMessage();
|
|
63
|
+
this.scheduleUpdate();
|
|
64
|
+
}
|
|
65
|
+
async finish(finalText) {
|
|
66
|
+
if (this.finished) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
this.finished = true;
|
|
70
|
+
if (finalText !== undefined) {
|
|
71
|
+
this.currentText = finalText;
|
|
72
|
+
}
|
|
73
|
+
this.cancelScheduledUpdate();
|
|
74
|
+
await this.throwIfAsyncError();
|
|
75
|
+
await this.awaitInFlightUpdate();
|
|
76
|
+
await this.throwIfAsyncError();
|
|
77
|
+
const finalMessageText = normalizeTrailing(this.currentText.length > 0 ? this.currentText : EMPTY_FINAL_TEXT, EMPTY_FINAL_TEXT);
|
|
78
|
+
const chunks = splitTextByCodePoints(finalMessageText, this.maxMessageChars);
|
|
79
|
+
const [firstChunk, ...remainingChunks] = chunks;
|
|
80
|
+
await this.ensureMessage();
|
|
81
|
+
await this.flushUpdate(firstChunk ?? EMPTY_FINAL_TEXT);
|
|
82
|
+
for (const chunk of remainingChunks) {
|
|
83
|
+
await this.api.chatPostMessage(this.withThread({
|
|
84
|
+
channel: this.channelId,
|
|
85
|
+
text: formatMarkdownForSlack(chunk),
|
|
86
|
+
mrkdwn: true,
|
|
87
|
+
}));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
async ensureMessage() {
|
|
91
|
+
if (this.sentMessage !== undefined) {
|
|
92
|
+
return this.sentMessage;
|
|
93
|
+
}
|
|
94
|
+
if (this.sendMessagePromise === undefined) {
|
|
95
|
+
this.sendMessagePromise = this.api.chatPostMessage(this.withThread({
|
|
96
|
+
channel: this.channelId,
|
|
97
|
+
text: formatMarkdownForSlack(this.statusText),
|
|
98
|
+
mrkdwn: true,
|
|
99
|
+
}));
|
|
100
|
+
}
|
|
101
|
+
this.sentMessage = await this.sendMessagePromise;
|
|
102
|
+
return this.sentMessage;
|
|
103
|
+
}
|
|
104
|
+
withThread(params) {
|
|
105
|
+
if (this.threadTs === undefined) {
|
|
106
|
+
return params;
|
|
107
|
+
}
|
|
108
|
+
return { ...params, thread_ts: this.threadTs };
|
|
109
|
+
}
|
|
110
|
+
scheduleUpdate() {
|
|
111
|
+
this.cancelScheduledUpdate();
|
|
112
|
+
if (this.editDebounceMs === 0) {
|
|
113
|
+
this.startInFlightUpdate();
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
this.editTimer = setTimeout(() => {
|
|
117
|
+
this.editTimer = undefined;
|
|
118
|
+
this.startInFlightUpdate();
|
|
119
|
+
}, this.editDebounceMs);
|
|
120
|
+
}
|
|
121
|
+
startInFlightUpdate() {
|
|
122
|
+
const text = buildStreamingTailPreview(normalizeTrailing(this.currentText, EMPTY_FINAL_TEXT), this.maxMessageChars, "...\n");
|
|
123
|
+
this.inFlightUpdate = this.flushUpdate(text).catch((error) => {
|
|
124
|
+
this.lastAsyncError = error;
|
|
125
|
+
this.logger?.error?.("Slack stream update failed.", {
|
|
126
|
+
error: error instanceof Error ? error.message : String(error),
|
|
127
|
+
});
|
|
128
|
+
throw error;
|
|
129
|
+
});
|
|
130
|
+
void this.inFlightUpdate.catch(() => undefined);
|
|
131
|
+
}
|
|
132
|
+
async flushUpdate(text) {
|
|
133
|
+
const message = await this.ensureMessage();
|
|
134
|
+
await this.api.chatUpdate({
|
|
135
|
+
channel: this.channelId,
|
|
136
|
+
ts: message.ts,
|
|
137
|
+
text: formatMarkdownForSlack(normalizeTrailing(text, EMPTY_FINAL_TEXT)),
|
|
138
|
+
mrkdwn: true,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
cancelScheduledUpdate() {
|
|
142
|
+
if (this.editTimer !== undefined) {
|
|
143
|
+
clearTimeout(this.editTimer);
|
|
144
|
+
this.editTimer = undefined;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
async awaitInFlightUpdate() {
|
|
148
|
+
if (this.inFlightUpdate !== undefined) {
|
|
149
|
+
await this.inFlightUpdate;
|
|
150
|
+
this.inFlightUpdate = undefined;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
async throwIfAsyncError() {
|
|
154
|
+
if (this.inFlightUpdate !== undefined) {
|
|
155
|
+
await this.awaitInFlightUpdate();
|
|
156
|
+
}
|
|
157
|
+
if (this.lastAsyncError !== undefined) {
|
|
158
|
+
const error = this.lastAsyncError;
|
|
159
|
+
this.lastAsyncError = undefined;
|
|
160
|
+
throw error;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
assertOpen() {
|
|
164
|
+
if (this.finished) {
|
|
165
|
+
throw new Error("Cannot write to a finished SlackMessageStream.");
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=message-stream.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-stream.js","sourceRoot":"","sources":["../src/message-stream.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { SlackAppsConnectionsOpenResult, SlackAuthTestResult, SlackChatPostMessageParams, SlackChatPostMessageResult, SlackChatUpdateParams, SlackChatUpdateResult, SlackRequestOptions, SlackWebApi } from "./types.js";
|
|
2
|
+
export type SlackApiErrorKind = "http" | "slack" | "malformed" | "network" | "aborted";
|
|
3
|
+
export interface SlackApiErrorDetails {
|
|
4
|
+
kind: SlackApiErrorKind;
|
|
5
|
+
method: string;
|
|
6
|
+
status?: number;
|
|
7
|
+
slackError?: string;
|
|
8
|
+
needed?: string;
|
|
9
|
+
provided?: string;
|
|
10
|
+
warning?: string;
|
|
11
|
+
cause?: unknown;
|
|
12
|
+
}
|
|
13
|
+
export declare class SlackApiError extends Error {
|
|
14
|
+
readonly kind: SlackApiErrorKind;
|
|
15
|
+
readonly method: string;
|
|
16
|
+
readonly status?: number;
|
|
17
|
+
readonly slackError?: string;
|
|
18
|
+
readonly needed?: string;
|
|
19
|
+
readonly provided?: string;
|
|
20
|
+
readonly warning?: string;
|
|
21
|
+
readonly cause?: unknown;
|
|
22
|
+
constructor(message: string, details: SlackApiErrorDetails);
|
|
23
|
+
}
|
|
24
|
+
export interface SlackWebApiClientOptions {
|
|
25
|
+
botToken: string;
|
|
26
|
+
appToken: string;
|
|
27
|
+
apiBaseUrl?: string;
|
|
28
|
+
fetchImpl?: typeof fetch;
|
|
29
|
+
requestTimeoutMs?: number;
|
|
30
|
+
}
|
|
31
|
+
export declare class SlackWebApiClient implements SlackWebApi {
|
|
32
|
+
private readonly botToken;
|
|
33
|
+
private readonly appToken;
|
|
34
|
+
private readonly apiBaseUrl;
|
|
35
|
+
private readonly fetchImpl;
|
|
36
|
+
private readonly requestTimeoutMs;
|
|
37
|
+
constructor(options: SlackWebApiClientOptions);
|
|
38
|
+
authTest(options?: SlackRequestOptions): Promise<SlackAuthTestResult>;
|
|
39
|
+
appsConnectionsOpen(options?: SlackRequestOptions): Promise<SlackAppsConnectionsOpenResult>;
|
|
40
|
+
chatPostMessage(params: SlackChatPostMessageParams, options?: SlackRequestOptions): Promise<SlackChatPostMessageResult>;
|
|
41
|
+
chatUpdate(params: SlackChatUpdateParams, options?: SlackRequestOptions): Promise<SlackChatUpdateResult>;
|
|
42
|
+
private request;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=slack-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slack-client.d.ts","sourceRoot":"","sources":["../src/slack-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,8BAA8B,EAC9B,mBAAmB,EACnB,0BAA0B,EAC1B,0BAA0B,EAC1B,qBAAqB,EACrB,qBAAqB,EACrB,mBAAmB,EACnB,WAAW,EACZ,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,iBAAiB,GACzB,MAAM,GACN,OAAO,GACP,WAAW,GACX,SAAS,GACT,SAAS,CAAC;AAEd,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,iBAAiB,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,qBAAa,aAAc,SAAQ,KAAK;IACtC,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAkB,KAAK,CAAC,EAAE,OAAO,CAAC;gBAEtB,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB;CAwB3D;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAeD,qBAAa,iBAAkB,YAAW,WAAW;IACnD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;IACzC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;gBAE9B,OAAO,EAAE,wBAAwB;IAsB7C,QAAQ,CAAC,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAIrE,mBAAmB,CAAC,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,8BAA8B,CAAC;IAI3F,eAAe,CACb,MAAM,EAAE,0BAA0B,EAClC,OAAO,CAAC,EAAE,mBAAmB,GAC5B,OAAO,CAAC,0BAA0B,CAAC;IAItC,UAAU,CACR,MAAM,EAAE,qBAAqB,EAC7B,OAAO,CAAC,EAAE,mBAAmB,GAC5B,OAAO,CAAC,qBAAqB,CAAC;YAInB,OAAO;CAwEtB"}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
export class SlackApiError extends Error {
|
|
2
|
+
kind;
|
|
3
|
+
method;
|
|
4
|
+
status;
|
|
5
|
+
slackError;
|
|
6
|
+
needed;
|
|
7
|
+
provided;
|
|
8
|
+
warning;
|
|
9
|
+
cause;
|
|
10
|
+
constructor(message, details) {
|
|
11
|
+
super(message);
|
|
12
|
+
this.name = "SlackApiError";
|
|
13
|
+
this.kind = details.kind;
|
|
14
|
+
this.method = details.method;
|
|
15
|
+
if (details.status !== undefined) {
|
|
16
|
+
this.status = details.status;
|
|
17
|
+
}
|
|
18
|
+
if (details.slackError !== undefined) {
|
|
19
|
+
this.slackError = details.slackError;
|
|
20
|
+
}
|
|
21
|
+
if (details.needed !== undefined) {
|
|
22
|
+
this.needed = details.needed;
|
|
23
|
+
}
|
|
24
|
+
if (details.provided !== undefined) {
|
|
25
|
+
this.provided = details.provided;
|
|
26
|
+
}
|
|
27
|
+
if (details.warning !== undefined) {
|
|
28
|
+
this.warning = details.warning;
|
|
29
|
+
}
|
|
30
|
+
if (details.cause !== undefined) {
|
|
31
|
+
this.cause = details.cause;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const DEFAULT_API_BASE_URL = "https://slack.com/api";
|
|
36
|
+
const DEFAULT_REQUEST_TIMEOUT_MS = 45_000;
|
|
37
|
+
export class SlackWebApiClient {
|
|
38
|
+
botToken;
|
|
39
|
+
appToken;
|
|
40
|
+
apiBaseUrl;
|
|
41
|
+
fetchImpl;
|
|
42
|
+
requestTimeoutMs;
|
|
43
|
+
constructor(options) {
|
|
44
|
+
const botToken = options.botToken.trim();
|
|
45
|
+
const appToken = options.appToken.trim();
|
|
46
|
+
if (botToken.length === 0) {
|
|
47
|
+
throw new TypeError("Slack bot token is required.");
|
|
48
|
+
}
|
|
49
|
+
if (appToken.length === 0) {
|
|
50
|
+
throw new TypeError("Slack app token is required.");
|
|
51
|
+
}
|
|
52
|
+
const fetchImpl = options.fetchImpl ?? globalThis.fetch;
|
|
53
|
+
if (typeof fetchImpl !== "function") {
|
|
54
|
+
throw new TypeError("A fetch implementation is required to call the Slack Web API.");
|
|
55
|
+
}
|
|
56
|
+
this.botToken = botToken;
|
|
57
|
+
this.appToken = appToken;
|
|
58
|
+
this.apiBaseUrl = stripTrailingSlashes(options.apiBaseUrl ?? DEFAULT_API_BASE_URL);
|
|
59
|
+
this.fetchImpl = fetchImpl;
|
|
60
|
+
this.requestTimeoutMs = options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
|
|
61
|
+
}
|
|
62
|
+
authTest(options) {
|
|
63
|
+
return this.request("auth.test", {}, this.botToken, options);
|
|
64
|
+
}
|
|
65
|
+
appsConnectionsOpen(options) {
|
|
66
|
+
return this.request("apps.connections.open", {}, this.appToken, options);
|
|
67
|
+
}
|
|
68
|
+
chatPostMessage(params, options) {
|
|
69
|
+
return this.request("chat.postMessage", params, this.botToken, options);
|
|
70
|
+
}
|
|
71
|
+
chatUpdate(params, options) {
|
|
72
|
+
return this.request("chat.update", params, this.botToken, options);
|
|
73
|
+
}
|
|
74
|
+
async request(method, params, token, options) {
|
|
75
|
+
const url = `${this.apiBaseUrl}/${method}`;
|
|
76
|
+
const { signal, cleanup } = createRequestSignal(options?.signal, this.requestTimeoutMs);
|
|
77
|
+
let response;
|
|
78
|
+
try {
|
|
79
|
+
const init = {
|
|
80
|
+
method: "POST",
|
|
81
|
+
headers: {
|
|
82
|
+
authorization: `Bearer ${token}`,
|
|
83
|
+
"content-type": "application/json; charset=utf-8",
|
|
84
|
+
},
|
|
85
|
+
body: JSON.stringify(params),
|
|
86
|
+
};
|
|
87
|
+
if (signal !== undefined) {
|
|
88
|
+
init.signal = signal;
|
|
89
|
+
}
|
|
90
|
+
response = await this.fetchImpl(url, init);
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
cleanup();
|
|
94
|
+
if (isAbortError(error) || options?.signal?.aborted === true) {
|
|
95
|
+
throw new SlackApiError(`Slack API ${method} request was aborted.`, {
|
|
96
|
+
kind: "aborted",
|
|
97
|
+
method,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
throw new SlackApiError(`Network failure while calling Slack API ${method}.`, {
|
|
101
|
+
kind: "network",
|
|
102
|
+
method,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
cleanup();
|
|
106
|
+
if (!response.ok) {
|
|
107
|
+
await safelyDrainResponse(response);
|
|
108
|
+
throw new SlackApiError(`Slack API ${method} failed with HTTP ${response.status}.`, {
|
|
109
|
+
kind: "http",
|
|
110
|
+
method,
|
|
111
|
+
status: response.status,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
let payload;
|
|
115
|
+
try {
|
|
116
|
+
payload = await response.json();
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
throw new SlackApiError(`Slack API ${method} returned malformed JSON.`, {
|
|
120
|
+
kind: "malformed",
|
|
121
|
+
method,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
const envelope = parseSlackEnvelope(method, payload);
|
|
125
|
+
if (!envelope.ok) {
|
|
126
|
+
throw new SlackApiError(`Slack API ${method} rejected the request.`, {
|
|
127
|
+
kind: "slack",
|
|
128
|
+
method,
|
|
129
|
+
...(typeof envelope.error === "string" ? { slackError: envelope.error } : {}),
|
|
130
|
+
...(typeof envelope.needed === "string" ? { needed: envelope.needed } : {}),
|
|
131
|
+
...(typeof envelope.provided === "string" ? { provided: envelope.provided } : {}),
|
|
132
|
+
...(typeof envelope.warning === "string" ? { warning: envelope.warning } : {}),
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
return envelope;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
function parseSlackEnvelope(method, payload) {
|
|
139
|
+
if (!isRecord(payload) || typeof payload.ok !== "boolean") {
|
|
140
|
+
throw new SlackApiError(`Slack API ${method} returned an unexpected response shape.`, {
|
|
141
|
+
kind: "malformed",
|
|
142
|
+
method,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
if (payload.ok === false) {
|
|
146
|
+
return {
|
|
147
|
+
ok: false,
|
|
148
|
+
...(typeof payload.error === "string" ? { error: payload.error } : {}),
|
|
149
|
+
...(typeof payload.needed === "string" ? { needed: payload.needed } : {}),
|
|
150
|
+
...(typeof payload.provided === "string" ? { provided: payload.provided } : {}),
|
|
151
|
+
...(typeof payload.warning === "string" ? { warning: payload.warning } : {}),
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
return payload;
|
|
155
|
+
}
|
|
156
|
+
function createRequestSignal(externalSignal, timeoutMs) {
|
|
157
|
+
const shouldUseTimeout = Number.isFinite(timeoutMs) && timeoutMs > 0;
|
|
158
|
+
if (!shouldUseTimeout) {
|
|
159
|
+
if (externalSignal === undefined) {
|
|
160
|
+
return { cleanup: () => undefined };
|
|
161
|
+
}
|
|
162
|
+
return { signal: externalSignal, cleanup: () => undefined };
|
|
163
|
+
}
|
|
164
|
+
const controller = new AbortController();
|
|
165
|
+
const timeout = setTimeout(() => {
|
|
166
|
+
controller.abort(new Error("Slack API request timed out."));
|
|
167
|
+
}, timeoutMs);
|
|
168
|
+
const abortFromExternalSignal = () => {
|
|
169
|
+
controller.abort(externalSignal?.reason);
|
|
170
|
+
};
|
|
171
|
+
if (externalSignal !== undefined) {
|
|
172
|
+
if (externalSignal.aborted) {
|
|
173
|
+
abortFromExternalSignal();
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
externalSignal.addEventListener("abort", abortFromExternalSignal, { once: true });
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return {
|
|
180
|
+
signal: controller.signal,
|
|
181
|
+
cleanup: () => {
|
|
182
|
+
clearTimeout(timeout);
|
|
183
|
+
externalSignal?.removeEventListener("abort", abortFromExternalSignal);
|
|
184
|
+
},
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
function stripTrailingSlashes(value) {
|
|
188
|
+
return value.replace(/\/+$/u, "");
|
|
189
|
+
}
|
|
190
|
+
function isAbortError(value) {
|
|
191
|
+
return (value instanceof DOMException && value.name === "AbortError") || (value instanceof Error && value.name === "AbortError");
|
|
192
|
+
}
|
|
193
|
+
function isRecord(value) {
|
|
194
|
+
return typeof value === "object" && value !== null;
|
|
195
|
+
}
|
|
196
|
+
async function safelyDrainResponse(response) {
|
|
197
|
+
try {
|
|
198
|
+
await response.text();
|
|
199
|
+
}
|
|
200
|
+
catch {
|
|
201
|
+
// Best effort only. Error messages intentionally avoid raw response bodies.
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
//# sourceMappingURL=slack-client.js.map
|