@openclaw/slack 2026.5.12-beta.7
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/dist/account-inspect-D7AZNs8C.js +77 -0
- package/dist/account-inspect-api.js +10 -0
- package/dist/accounts-ClAPP5ry.js +139 -0
- package/dist/accounts.runtime-DDVcLJUI.js +2 -0
- package/dist/action-runtime-e2UhRsNx.js +350 -0
- package/dist/action-runtime.runtime-BFcqMbOm.js +2 -0
- package/dist/actions-CYLFK-Zy.js +292 -0
- package/dist/actions.runtime-CO3OaTLb.js +2 -0
- package/dist/allow-list-BPnnlRPL.js +82 -0
- package/dist/api.js +21 -0
- package/dist/approval-handler.runtime-CmeRr9qA.js +256 -0
- package/dist/blocks-input-CwTFVImV.js +29 -0
- package/dist/blocks-render-BIDw-Pom.js +161 -0
- package/dist/channel-DRjHBTDB.js +1020 -0
- package/dist/channel-api-B_nZwosg.js +20 -0
- package/dist/channel-config-api.js +2 -0
- package/dist/channel-entry.js +22 -0
- package/dist/channel-plugin-api.js +2 -0
- package/dist/channel.setup-Cayn7afd.js +73 -0
- package/dist/client-CPe4GmDR.js +103 -0
- package/dist/config-api-B_jq4NJW.js +2 -0
- package/dist/config-schema-D9B5LB_L.js +167 -0
- package/dist/configured-state.js +11 -0
- package/dist/contract-api.js +5 -0
- package/dist/directory-config-B3JiHeB7.js +54 -0
- package/dist/directory-contract-api.js +2 -0
- package/dist/directory-live-Bf16GwDh.js +133 -0
- package/dist/doctor-contract-KUjHnkQm.js +147 -0
- package/dist/doctor-contract-api.js +2 -0
- package/dist/errors-BYFHR24f.js +109 -0
- package/dist/exec-approvals-7xUNgLi9.js +58 -0
- package/dist/group-policy-CyLUK6My.js +41 -0
- package/dist/http-routes-api.js +2 -0
- package/dist/inbound-contract-test-api.js +3 -0
- package/dist/index.js +33 -0
- package/dist/interactive-replies-api.js +2 -0
- package/dist/interactive-replies-qAIfuBor.js +173 -0
- package/dist/magic-string.es-BMaGRRZ1.js +1011 -0
- package/dist/media-D1XCd1uP.js +469 -0
- package/dist/message-tool-api-6lowf9zE.js +104 -0
- package/dist/message-tool-api.js +2 -0
- package/dist/monitor-a97o17G6.js +13 -0
- package/dist/mrkdwn-Cax-eSfK.js +6 -0
- package/dist/outbound-adapter-B_5sEhCg.js +174 -0
- package/dist/outbound-payload-test-api.js +2 -0
- package/dist/outbound-payload.test-harness-CVCamg1x.js +13558 -0
- package/dist/pipeline.runtime-DT0hLnq2.js +1379 -0
- package/dist/plugin-routes-DtTPmga1.js +20 -0
- package/dist/prepare-D3YqV8jB.js +1482 -0
- package/dist/prepare.test-helpers-DVcjRhfG.js +49 -0
- package/dist/probe-3eZf1FjI.js +42 -0
- package/dist/provider-D7uAN3Fq.js +3235 -0
- package/dist/registry-CeaoNfoP.js +39 -0
- package/dist/replies-Xe_jMR6o.js +139 -0
- package/dist/reply-blocks-Z5l6_R6H.js +14 -0
- package/dist/resolve-allowlist-common-Bk3clYPK.js +43 -0
- package/dist/resolve-channels-BRYqyNVJ.js +81 -0
- package/dist/resolve-users-Bd_SdP8j.js +113 -0
- package/dist/rolldown-runtime-CiIaOW0V.js +13 -0
- package/dist/room-context-0vovmZPU.js +787 -0
- package/dist/runtime-Bo-KHM-F.js +8 -0
- package/dist/runtime-api-Dd1xIV5v.js +9 -0
- package/dist/runtime-api.js +14 -0
- package/dist/runtime-setter-api.js +2 -0
- package/dist/scopes-CDevO8jg.js +74 -0
- package/dist/secret-contract-Bo6lbSkh.js +141 -0
- package/dist/secret-contract-api.js +2 -0
- package/dist/security-audit-BtHGnD3d.js +51 -0
- package/dist/security-contract-api.js +2 -0
- package/dist/send-D_A9kL-C.js +721 -0
- package/dist/send.runtime-BRE_ncCU.js +2 -0
- package/dist/send.runtime-_l76lUuL.js +2 -0
- package/dist/setup-core-B9NetDkM.js +320 -0
- package/dist/setup-entry.js +15 -0
- package/dist/setup-plugin-api.js +2 -0
- package/dist/setup-surface-D88QBVOW.js +128 -0
- package/dist/shared-D8U42xFL.js +208 -0
- package/dist/slash-commands.runtime-22kgyst2.js +19 -0
- package/dist/slash-dispatch.runtime-BJgT0jwV.js +32 -0
- package/dist/slash-plugin-commands.runtime-CF-n3MeP.js +2 -0
- package/dist/slash-skill-commands.runtime-BMs0VjTe.js +7 -0
- package/dist/streaming-compat-RkZgTmQ2.js +43 -0
- package/dist/target-parsing-CQmv-iSm.js +55 -0
- package/dist/targets-B1tYCAr6.js +2 -0
- package/dist/test-api.js +8 -0
- package/dist/thread-ts-C2x7c5PP.js +24 -0
- package/openclaw.plugin.json +2405 -0
- package/package.json +84 -0
|
@@ -0,0 +1,1020 @@
|
|
|
1
|
+
import { a as resolveSlackAccount, i as resolveDefaultSlackAccountId, l as resolveSlackReplyToMode, n as listSlackAccountIds, o as resolveSlackAccountAllowFrom } from "./accounts-ClAPP5ry.js";
|
|
2
|
+
import { i as resolveSlackChannelId, n as normalizeSlackMessagingTarget, r as parseSlackTarget, t as looksLikeSlackTargetId } from "./target-parsing-CQmv-iSm.js";
|
|
3
|
+
import "./targets-B1tYCAr6.js";
|
|
4
|
+
import { a as normalizeSlackApproverId, c as shouldSuppressLocalSlackExecApprovalPrompt, i as isSlackExecApprovalClientEnabled, o as resolveSlackExecApprovalTarget, r as isSlackExecApprovalAuthorizedSender, s as shouldHandleSlackExecApprovalRequest, t as getSlackExecApprovalApprovers } from "./exec-approvals-7xUNgLi9.js";
|
|
5
|
+
import { n as buildSlackPresentationBlocks, r as resolveSlackInteractiveBlockOffsets, t as buildSlackInteractiveBlocks } from "./blocks-render-BIDw-Pom.js";
|
|
6
|
+
import { n as resolveSlackThreadTsValue, r as SLACK_TEXT_LIMIT, t as normalizeSlackThreadTsCandidate } from "./thread-ts-C2x7c5PP.js";
|
|
7
|
+
import { n as extractSlackToolSend, t as describeSlackMessageTool } from "./message-tool-api-6lowf9zE.js";
|
|
8
|
+
import { n as isSlackInteractiveRepliesEnabled, t as compileSlackInteractiveReplies } from "./interactive-replies-qAIfuBor.js";
|
|
9
|
+
import { a as resolveConfiguredFromRequiredCredentialStatuses, i as projectCredentialSnapshotFields, n as PAIRING_APPROVED_MESSAGE, t as DEFAULT_ACCOUNT_ID } from "./channel-api-B_nZwosg.js";
|
|
10
|
+
import { r as createSlackWebClient } from "./client-CPe4GmDR.js";
|
|
11
|
+
import { r as normalizeAllowListLower } from "./allow-list-BPnnlRPL.js";
|
|
12
|
+
import { n as resolveSlackGroupToolPolicy, t as resolveSlackGroupRequireMention } from "./group-policy-CyLUK6My.js";
|
|
13
|
+
import { t as resolveSlackReplyBlocks } from "./reply-blocks-Z5l6_R6H.js";
|
|
14
|
+
import { t as getOptionalSlackRuntime } from "./runtime-Bo-KHM-F.js";
|
|
15
|
+
import { i as slackSecurityAdapter, n as isSlackPluginAccountConfigured, r as slackConfigAdapter, t as createSlackPluginBase } from "./shared-D8U42xFL.js";
|
|
16
|
+
import { i as SLACK_CHANNEL, n as createSlackSetupWizardProxy, r as slackSetupAdapter } from "./setup-core-B9NetDkM.js";
|
|
17
|
+
import { normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
18
|
+
import { adaptScopedAccountAccessor } from "openclaw/plugin-sdk/channel-config-helpers";
|
|
19
|
+
import { buildOutboundBaseSessionKey } from "openclaw/plugin-sdk/routing";
|
|
20
|
+
import { buildLegacyDmAccountAllowlistAdapter, createAccountScopedAllowlistNameResolver, createFlatAllowlistOverrideResolver } from "openclaw/plugin-sdk/allowlist-config-edit";
|
|
21
|
+
import { buildThreadAwareOutboundSessionRoute, createChatChannelPlugin } from "openclaw/plugin-sdk/channel-core";
|
|
22
|
+
import { createChannelMessageAdapterFromOutbound } from "openclaw/plugin-sdk/channel-message";
|
|
23
|
+
import { createPairingPrefixStripper } from "openclaw/plugin-sdk/channel-pairing";
|
|
24
|
+
import { createAttachedChannelResultAdapter } from "openclaw/plugin-sdk/channel-send-result";
|
|
25
|
+
import { createChannelDirectoryAdapter, createRuntimeDirectoryLiveAdapter } from "openclaw/plugin-sdk/directory-runtime";
|
|
26
|
+
import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
|
|
27
|
+
import { resolveOutboundSendDep } from "openclaw/plugin-sdk/outbound-send-deps";
|
|
28
|
+
import { createComputedAccountStatusAdapter, createDefaultChannelRuntimeState } from "openclaw/plugin-sdk/status-helpers";
|
|
29
|
+
import { isSingleUseReplyToMode } from "openclaw/plugin-sdk/reply-reference";
|
|
30
|
+
import { createApproverRestrictedNativeApprovalCapability, splitChannelApprovalCapability } from "openclaw/plugin-sdk/approval-delivery-runtime";
|
|
31
|
+
import { createLazyChannelApprovalNativeRuntimeAdapter } from "openclaw/plugin-sdk/approval-handler-adapter-runtime";
|
|
32
|
+
import { createChannelApproverDmTargetResolver, createChannelNativeOriginTargetResolver, resolveApprovalRequestSessionConversation } from "openclaw/plugin-sdk/approval-native-runtime";
|
|
33
|
+
import { channelRouteTargetsMatchExact, stringifyRouteThreadId } from "openclaw/plugin-sdk/channel-route";
|
|
34
|
+
import { createResolvedApproverActionAuthAdapter, resolveApprovalApprovers } from "openclaw/plugin-sdk/approval-auth-runtime";
|
|
35
|
+
import { readBooleanParam } from "openclaw/plugin-sdk/boolean-param";
|
|
36
|
+
import { normalizeInteractiveReply, normalizeMessagePresentation } from "openclaw/plugin-sdk/interactive-runtime";
|
|
37
|
+
import { readNumberParam, readStringParam } from "openclaw/plugin-sdk/param-readers";
|
|
38
|
+
//#region extensions/slack/src/action-threading.ts
|
|
39
|
+
function resolveSlackAutoThreadId(params) {
|
|
40
|
+
const context = params.toolContext;
|
|
41
|
+
if (!context?.currentThreadTs || !context.currentChannelId) return;
|
|
42
|
+
if (context.replyToMode !== "all" && !isSingleUseReplyToMode(context.replyToMode ?? "off")) return;
|
|
43
|
+
const parsedTarget = parseSlackTarget(params.to, { defaultKind: "channel" });
|
|
44
|
+
if (!parsedTarget || parsedTarget.kind !== "channel") return;
|
|
45
|
+
if (normalizeLowercaseStringOrEmpty(parsedTarget.id) !== normalizeLowercaseStringOrEmpty(context.currentChannelId)) return;
|
|
46
|
+
if (isSingleUseReplyToMode(context.replyToMode ?? "off") && context.hasRepliedRef?.value) return;
|
|
47
|
+
return context.currentThreadTs;
|
|
48
|
+
}
|
|
49
|
+
//#endregion
|
|
50
|
+
//#region extensions/slack/src/approval-auth.ts
|
|
51
|
+
function getSlackApprovalApprovers(params) {
|
|
52
|
+
const account = resolveSlackAccount(params).config;
|
|
53
|
+
return resolveApprovalApprovers({
|
|
54
|
+
allowFrom: resolveSlackAccountAllowFrom(params),
|
|
55
|
+
defaultTo: account.defaultTo,
|
|
56
|
+
normalizeApprover: normalizeSlackApproverId,
|
|
57
|
+
normalizeDefaultTo: normalizeSlackApproverId
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
function isSlackApprovalAuthorizedSender(params) {
|
|
61
|
+
const senderId = params.senderId ? normalizeSlackApproverId(params.senderId) : void 0;
|
|
62
|
+
if (!senderId) return false;
|
|
63
|
+
return getSlackApprovalApprovers(params).includes(senderId);
|
|
64
|
+
}
|
|
65
|
+
createResolvedApproverActionAuthAdapter({
|
|
66
|
+
channelLabel: "Slack",
|
|
67
|
+
resolveApprovers: ({ cfg, accountId }) => getSlackApprovalApprovers({
|
|
68
|
+
cfg,
|
|
69
|
+
accountId
|
|
70
|
+
}),
|
|
71
|
+
normalizeSenderId: (value) => normalizeSlackApproverId(value)
|
|
72
|
+
});
|
|
73
|
+
//#endregion
|
|
74
|
+
//#region extensions/slack/src/approval-native.ts
|
|
75
|
+
function extractSlackSessionKind(sessionKey) {
|
|
76
|
+
if (!sessionKey) return null;
|
|
77
|
+
const kind = normalizeLowercaseStringOrEmpty(sessionKey.match(/slack:(direct|channel|group):/i)?.[1]);
|
|
78
|
+
return kind ? kind : null;
|
|
79
|
+
}
|
|
80
|
+
function normalizeComparableTarget(value) {
|
|
81
|
+
return normalizeLowercaseStringOrEmpty(value);
|
|
82
|
+
}
|
|
83
|
+
function normalizeSlackThreadMatchKey(threadId) {
|
|
84
|
+
const trimmed = threadId?.trim();
|
|
85
|
+
if (!trimmed) return "";
|
|
86
|
+
return trimmed.match(/^\d+/)?.[0] ?? trimmed;
|
|
87
|
+
}
|
|
88
|
+
function resolveTurnSourceSlackOriginTarget(request) {
|
|
89
|
+
const turnSourceChannel = normalizeLowercaseStringOrEmpty(request.request.turnSourceChannel);
|
|
90
|
+
const turnSourceTo = normalizeOptionalString(request.request.turnSourceTo) ?? "";
|
|
91
|
+
if (turnSourceChannel !== "slack" || !turnSourceTo) return null;
|
|
92
|
+
const parsed = parseSlackTarget(turnSourceTo, { defaultKind: extractSlackSessionKind(request.request.sessionKey ?? void 0) === "direct" ? "user" : "channel" });
|
|
93
|
+
if (!parsed) return null;
|
|
94
|
+
const threadId = stringifyRouteThreadId(request.request.turnSourceThreadId);
|
|
95
|
+
return {
|
|
96
|
+
to: `${parsed.kind}:${parsed.id}`,
|
|
97
|
+
threadId
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function resolveSessionSlackOriginTarget(sessionTarget) {
|
|
101
|
+
return {
|
|
102
|
+
to: sessionTarget.to,
|
|
103
|
+
threadId: stringifyRouteThreadId(sessionTarget.threadId)
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
function resolveSlackFallbackOriginTarget(request) {
|
|
107
|
+
const sessionTarget = resolveApprovalRequestSessionConversation({
|
|
108
|
+
request,
|
|
109
|
+
channel: "slack",
|
|
110
|
+
bundledFallback: false
|
|
111
|
+
});
|
|
112
|
+
if (!sessionTarget) return null;
|
|
113
|
+
const parsed = parseSlackTarget(sessionTarget.id.toUpperCase(), { defaultKind: "channel" });
|
|
114
|
+
if (!parsed) return null;
|
|
115
|
+
return {
|
|
116
|
+
to: `${parsed.kind}:${parsed.id}`,
|
|
117
|
+
threadId: sessionTarget.threadId
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
function normalizeSlackOriginTarget(target) {
|
|
121
|
+
return {
|
|
122
|
+
...target,
|
|
123
|
+
to: normalizeComparableTarget(target.to)
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
function slackTargetsMatch(a, b) {
|
|
127
|
+
return channelRouteTargetsMatchExact({
|
|
128
|
+
left: {
|
|
129
|
+
channel: "slack",
|
|
130
|
+
to: a.to
|
|
131
|
+
},
|
|
132
|
+
right: {
|
|
133
|
+
channel: "slack",
|
|
134
|
+
to: b.to
|
|
135
|
+
}
|
|
136
|
+
}) && normalizeSlackThreadMatchKey(a.threadId) === normalizeSlackThreadMatchKey(b.threadId);
|
|
137
|
+
}
|
|
138
|
+
const slackApprovalCapability = createApproverRestrictedNativeApprovalCapability({
|
|
139
|
+
channel: "slack",
|
|
140
|
+
channelLabel: "Slack",
|
|
141
|
+
describeExecApprovalSetup: ({ accountId }) => {
|
|
142
|
+
const prefix = accountId && accountId !== "default" ? `channels.slack.accounts.${accountId}` : "channels.slack";
|
|
143
|
+
return `Approve it from the Web UI or terminal UI for now. Slack supports native exec approvals for this account. Configure \`${prefix}.execApprovals.approvers\` or \`commands.ownerAllowFrom\`; leave \`${prefix}.execApprovals.enabled\` unset/\`auto\` or set it to \`true\`.`;
|
|
144
|
+
},
|
|
145
|
+
listAccountIds: listSlackAccountIds,
|
|
146
|
+
hasApprovers: ({ cfg, accountId }) => getSlackExecApprovalApprovers({
|
|
147
|
+
cfg,
|
|
148
|
+
accountId
|
|
149
|
+
}).length > 0,
|
|
150
|
+
isExecAuthorizedSender: ({ cfg, accountId, senderId }) => isSlackExecApprovalAuthorizedSender({
|
|
151
|
+
cfg,
|
|
152
|
+
accountId,
|
|
153
|
+
senderId
|
|
154
|
+
}),
|
|
155
|
+
isPluginAuthorizedSender: ({ cfg, accountId, senderId }) => isSlackApprovalAuthorizedSender({
|
|
156
|
+
cfg,
|
|
157
|
+
accountId,
|
|
158
|
+
senderId
|
|
159
|
+
}),
|
|
160
|
+
isNativeDeliveryEnabled: ({ cfg, accountId }) => isSlackExecApprovalClientEnabled({
|
|
161
|
+
cfg,
|
|
162
|
+
accountId
|
|
163
|
+
}),
|
|
164
|
+
resolveNativeDeliveryMode: ({ cfg, accountId }) => resolveSlackExecApprovalTarget({
|
|
165
|
+
cfg,
|
|
166
|
+
accountId
|
|
167
|
+
}),
|
|
168
|
+
requireMatchingTurnSourceChannel: true,
|
|
169
|
+
resolveSuppressionAccountId: ({ target, request }) => normalizeOptionalString(target.accountId) ?? normalizeOptionalString(request.request.turnSourceAccountId),
|
|
170
|
+
resolveOriginTarget: createChannelNativeOriginTargetResolver({
|
|
171
|
+
channel: "slack",
|
|
172
|
+
shouldHandleRequest: ({ cfg, accountId, request }) => shouldHandleSlackExecApprovalRequest({
|
|
173
|
+
cfg,
|
|
174
|
+
accountId,
|
|
175
|
+
request
|
|
176
|
+
}),
|
|
177
|
+
resolveTurnSourceTarget: resolveTurnSourceSlackOriginTarget,
|
|
178
|
+
resolveSessionTarget: resolveSessionSlackOriginTarget,
|
|
179
|
+
normalizeTargetForMatch: normalizeSlackOriginTarget,
|
|
180
|
+
targetsMatch: slackTargetsMatch,
|
|
181
|
+
resolveFallbackTarget: resolveSlackFallbackOriginTarget
|
|
182
|
+
}),
|
|
183
|
+
resolveApproverDmTargets: createChannelApproverDmTargetResolver({
|
|
184
|
+
shouldHandleRequest: ({ cfg, accountId, request }) => shouldHandleSlackExecApprovalRequest({
|
|
185
|
+
cfg,
|
|
186
|
+
accountId,
|
|
187
|
+
request
|
|
188
|
+
}),
|
|
189
|
+
resolveApprovers: getSlackExecApprovalApprovers,
|
|
190
|
+
mapApprover: (approver) => ({ to: `user:${approver}` })
|
|
191
|
+
}),
|
|
192
|
+
notifyOriginWhenDmOnly: true,
|
|
193
|
+
nativeRuntime: createLazyChannelApprovalNativeRuntimeAdapter({
|
|
194
|
+
eventKinds: ["exec"],
|
|
195
|
+
isConfigured: ({ cfg, accountId }) => isSlackExecApprovalClientEnabled({
|
|
196
|
+
cfg,
|
|
197
|
+
accountId
|
|
198
|
+
}),
|
|
199
|
+
shouldHandle: ({ cfg, accountId, request }) => shouldHandleSlackExecApprovalRequest({
|
|
200
|
+
cfg,
|
|
201
|
+
accountId,
|
|
202
|
+
request
|
|
203
|
+
}),
|
|
204
|
+
load: async () => (await import("./approval-handler.runtime-CmeRr9qA.js")).slackApprovalNativeRuntime
|
|
205
|
+
})
|
|
206
|
+
});
|
|
207
|
+
splitChannelApprovalCapability(slackApprovalCapability);
|
|
208
|
+
//#endregion
|
|
209
|
+
//#region extensions/slack/src/message-action-dispatch.ts
|
|
210
|
+
/** Translate generic channel action requests into Slack-specific tool invocations and payload shapes. */
|
|
211
|
+
async function handleSlackMessageAction(params) {
|
|
212
|
+
const { providerId, ctx, invoke, normalizeChannelId, includeReadThreadId = false } = params;
|
|
213
|
+
const { action, cfg, params: actionParams } = ctx;
|
|
214
|
+
const accountId = ctx.accountId ?? void 0;
|
|
215
|
+
const resolveChannelId = () => {
|
|
216
|
+
const channelId = readStringParam(actionParams, "channelId") ?? readStringParam(actionParams, "to", { required: true });
|
|
217
|
+
return normalizeChannelId ? normalizeChannelId(channelId) : channelId;
|
|
218
|
+
};
|
|
219
|
+
if (action === "send") {
|
|
220
|
+
const to = readStringParam(actionParams, "to", { required: true });
|
|
221
|
+
const content = readStringParam(actionParams, "message", {
|
|
222
|
+
required: false,
|
|
223
|
+
allowEmpty: true
|
|
224
|
+
});
|
|
225
|
+
const mediaUrl = readStringParam(actionParams, "media", { trim: false });
|
|
226
|
+
const presentation = normalizeMessagePresentation(actionParams.presentation);
|
|
227
|
+
const interactive = normalizeInteractiveReply(actionParams.interactive);
|
|
228
|
+
const presentationBlocks = presentation ? buildSlackPresentationBlocks(presentation) : void 0;
|
|
229
|
+
const interactiveBlocks = interactive ? buildSlackInteractiveBlocks(interactive, resolveSlackInteractiveBlockOffsets(presentationBlocks)) : void 0;
|
|
230
|
+
const mergedBlocks = [...presentationBlocks ?? [], ...interactiveBlocks ?? []];
|
|
231
|
+
const blocks = mergedBlocks.length > 0 ? mergedBlocks : void 0;
|
|
232
|
+
if (!content && !mediaUrl && !blocks) throw new Error("Slack send requires message, blocks, or media.");
|
|
233
|
+
const replyBroadcast = readBooleanParam(actionParams, "replyBroadcast");
|
|
234
|
+
if (replyBroadcast && mediaUrl) throw new Error("Slack replyBroadcast is only supported for text or block thread replies.");
|
|
235
|
+
const threadId = readStringParam(actionParams, "threadId");
|
|
236
|
+
const replyTo = readStringParam(actionParams, "replyTo");
|
|
237
|
+
const topLevel = readBooleanParam(actionParams, "topLevel") === true || actionParams.threadId === null;
|
|
238
|
+
return await invoke({
|
|
239
|
+
action: "sendMessage",
|
|
240
|
+
to,
|
|
241
|
+
content: content ?? "",
|
|
242
|
+
mediaUrl: mediaUrl ?? void 0,
|
|
243
|
+
accountId,
|
|
244
|
+
threadTs: threadId ?? replyTo ?? void 0,
|
|
245
|
+
...topLevel ? { topLevel: true } : {},
|
|
246
|
+
...replyBroadcast ? { replyBroadcast } : {},
|
|
247
|
+
...blocks ? { blocks } : {}
|
|
248
|
+
}, cfg, ctx.toolContext);
|
|
249
|
+
}
|
|
250
|
+
if (action === "react") {
|
|
251
|
+
const messageId = readStringParam(actionParams, "messageId", { required: true });
|
|
252
|
+
const emoji = readStringParam(actionParams, "emoji", { allowEmpty: true });
|
|
253
|
+
const remove = typeof actionParams.remove === "boolean" ? actionParams.remove : void 0;
|
|
254
|
+
return await invoke({
|
|
255
|
+
action: "react",
|
|
256
|
+
channelId: resolveChannelId(),
|
|
257
|
+
messageId,
|
|
258
|
+
emoji,
|
|
259
|
+
remove,
|
|
260
|
+
accountId
|
|
261
|
+
}, cfg);
|
|
262
|
+
}
|
|
263
|
+
if (action === "reactions") {
|
|
264
|
+
const messageId = readStringParam(actionParams, "messageId", { required: true });
|
|
265
|
+
const limit = readNumberParam(actionParams, "limit", { integer: true });
|
|
266
|
+
return await invoke({
|
|
267
|
+
action: "reactions",
|
|
268
|
+
channelId: resolveChannelId(),
|
|
269
|
+
messageId,
|
|
270
|
+
limit,
|
|
271
|
+
accountId
|
|
272
|
+
}, cfg);
|
|
273
|
+
}
|
|
274
|
+
if (action === "read") {
|
|
275
|
+
const limit = readNumberParam(actionParams, "limit", { integer: true });
|
|
276
|
+
const readAction = {
|
|
277
|
+
action: "readMessages",
|
|
278
|
+
channelId: resolveChannelId(),
|
|
279
|
+
limit,
|
|
280
|
+
before: readStringParam(actionParams, "before"),
|
|
281
|
+
after: readStringParam(actionParams, "after"),
|
|
282
|
+
messageId: readStringParam(actionParams, "messageId"),
|
|
283
|
+
accountId
|
|
284
|
+
};
|
|
285
|
+
if (includeReadThreadId) readAction.threadId = readStringParam(actionParams, "threadId");
|
|
286
|
+
return await invoke(readAction, cfg);
|
|
287
|
+
}
|
|
288
|
+
if (action === "edit") {
|
|
289
|
+
const messageId = readStringParam(actionParams, "messageId", { required: true });
|
|
290
|
+
const content = readStringParam(actionParams, "message", { allowEmpty: true });
|
|
291
|
+
const presentation = normalizeMessagePresentation(actionParams.presentation);
|
|
292
|
+
const blocks = presentation ? buildSlackPresentationBlocks(presentation) : void 0;
|
|
293
|
+
if (!content && !blocks) throw new Error("Slack edit requires message or blocks.");
|
|
294
|
+
return await invoke({
|
|
295
|
+
action: "editMessage",
|
|
296
|
+
channelId: resolveChannelId(),
|
|
297
|
+
messageId,
|
|
298
|
+
content: content ?? "",
|
|
299
|
+
blocks,
|
|
300
|
+
accountId
|
|
301
|
+
}, cfg);
|
|
302
|
+
}
|
|
303
|
+
if (action === "delete") {
|
|
304
|
+
const messageId = readStringParam(actionParams, "messageId", { required: true });
|
|
305
|
+
return await invoke({
|
|
306
|
+
action: "deleteMessage",
|
|
307
|
+
channelId: resolveChannelId(),
|
|
308
|
+
messageId,
|
|
309
|
+
accountId
|
|
310
|
+
}, cfg);
|
|
311
|
+
}
|
|
312
|
+
if (action === "pin" || action === "unpin" || action === "list-pins") {
|
|
313
|
+
const messageId = action === "list-pins" ? void 0 : readStringParam(actionParams, "messageId", { required: true });
|
|
314
|
+
return await invoke({
|
|
315
|
+
action: action === "pin" ? "pinMessage" : action === "unpin" ? "unpinMessage" : "listPins",
|
|
316
|
+
channelId: resolveChannelId(),
|
|
317
|
+
messageId,
|
|
318
|
+
accountId
|
|
319
|
+
}, cfg);
|
|
320
|
+
}
|
|
321
|
+
if (action === "member-info") return await invoke({
|
|
322
|
+
action: "memberInfo",
|
|
323
|
+
userId: readStringParam(actionParams, "userId", { required: true }),
|
|
324
|
+
accountId
|
|
325
|
+
}, cfg);
|
|
326
|
+
if (action === "emoji-list") return await invoke({
|
|
327
|
+
action: "emojiList",
|
|
328
|
+
limit: readNumberParam(actionParams, "limit", { integer: true }),
|
|
329
|
+
accountId
|
|
330
|
+
}, cfg);
|
|
331
|
+
if (action === "download-file") {
|
|
332
|
+
const fileIdParam = readStringParam(actionParams, "fileId");
|
|
333
|
+
const messageIdParam = readStringParam(actionParams, "messageId") ?? readStringParam(actionParams, "message_id");
|
|
334
|
+
if (!fileIdParam && messageIdParam) throw new Error("download-file requires fileId (the Slack file id, for example F0B0LTT8M36 from event.files[].id), not messageId. Did you mean to pass fileId? messageId is the Slack message timestamp and is used by react / reactions / edit / delete / pin / unpin actions, not download-file.");
|
|
335
|
+
const fileId = readStringParam(actionParams, "fileId", { required: true });
|
|
336
|
+
const channelId = readStringParam(actionParams, "channelId") ?? readStringParam(actionParams, "to");
|
|
337
|
+
const threadId = readStringParam(actionParams, "threadId") ?? readStringParam(actionParams, "replyTo");
|
|
338
|
+
return await invoke({
|
|
339
|
+
action: "downloadFile",
|
|
340
|
+
fileId,
|
|
341
|
+
channelId: channelId ?? void 0,
|
|
342
|
+
threadId: threadId ?? void 0,
|
|
343
|
+
accountId
|
|
344
|
+
}, cfg);
|
|
345
|
+
}
|
|
346
|
+
if (action === "upload-file") {
|
|
347
|
+
if (readBooleanParam(actionParams, "replyBroadcast")) throw new Error("Slack replyBroadcast is only supported for text or block thread replies.");
|
|
348
|
+
const to = readStringParam(actionParams, "to") ?? resolveChannelId();
|
|
349
|
+
const filePath = readStringParam(actionParams, "filePath", { trim: false }) ?? readStringParam(actionParams, "path", { trim: false }) ?? readStringParam(actionParams, "media", { trim: false });
|
|
350
|
+
if (!filePath) throw new Error("upload-file requires filePath, path, or media");
|
|
351
|
+
const threadId = readStringParam(actionParams, "threadId") ?? readStringParam(actionParams, "replyTo");
|
|
352
|
+
const topLevel = readBooleanParam(actionParams, "topLevel") === true || actionParams.threadId === null;
|
|
353
|
+
return await invoke({
|
|
354
|
+
action: "uploadFile",
|
|
355
|
+
to,
|
|
356
|
+
filePath,
|
|
357
|
+
initialComment: readStringParam(actionParams, "initialComment", { allowEmpty: true }) ?? readStringParam(actionParams, "message", { allowEmpty: true }) ?? "",
|
|
358
|
+
filename: readStringParam(actionParams, "filename"),
|
|
359
|
+
title: readStringParam(actionParams, "title"),
|
|
360
|
+
threadTs: threadId ?? void 0,
|
|
361
|
+
...topLevel ? { topLevel: true } : {},
|
|
362
|
+
accountId
|
|
363
|
+
}, cfg, ctx.toolContext);
|
|
364
|
+
}
|
|
365
|
+
throw new Error(`Action ${action} is not supported for provider ${providerId}.`);
|
|
366
|
+
}
|
|
367
|
+
//#endregion
|
|
368
|
+
//#region extensions/slack/src/channel-actions.ts
|
|
369
|
+
let slackActionRuntimePromise$1;
|
|
370
|
+
async function loadSlackActionRuntime$1() {
|
|
371
|
+
slackActionRuntimePromise$1 ??= import("./action-runtime.runtime-BFcqMbOm.js");
|
|
372
|
+
return await slackActionRuntimePromise$1;
|
|
373
|
+
}
|
|
374
|
+
function resolveSlackActionContext(params) {
|
|
375
|
+
if (!params.toolContext && !params.mediaLocalRoots && !params.mediaReadFile) return;
|
|
376
|
+
return {
|
|
377
|
+
...params.toolContext,
|
|
378
|
+
...params.mediaLocalRoots ? { mediaLocalRoots: params.mediaLocalRoots } : {},
|
|
379
|
+
...params.mediaReadFile ? { mediaReadFile: params.mediaReadFile } : {}
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
function createSlackActions(providerId, options) {
|
|
383
|
+
return {
|
|
384
|
+
describeMessageTool: describeSlackMessageTool,
|
|
385
|
+
extractToolSend: ({ args }) => extractSlackToolSend(args),
|
|
386
|
+
prepareSendPayload: ({ ctx, payload }) => ctx.action === "send" ? payload : null,
|
|
387
|
+
handleAction: async (ctx) => {
|
|
388
|
+
return await handleSlackMessageAction({
|
|
389
|
+
providerId,
|
|
390
|
+
ctx,
|
|
391
|
+
normalizeChannelId: resolveSlackChannelId,
|
|
392
|
+
includeReadThreadId: true,
|
|
393
|
+
invoke: async (action, cfg, toolContext) => {
|
|
394
|
+
const actionContext = resolveSlackActionContext({
|
|
395
|
+
toolContext,
|
|
396
|
+
mediaLocalRoots: ctx.mediaLocalRoots,
|
|
397
|
+
mediaReadFile: ctx.mediaReadFile
|
|
398
|
+
});
|
|
399
|
+
return await (options?.invoke ? options.invoke(action, cfg, actionContext) : (await loadSlackActionRuntime$1()).handleSlackAction(action, cfg, actionContext));
|
|
400
|
+
}
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
//#endregion
|
|
406
|
+
//#region extensions/slack/src/channel-type.ts
|
|
407
|
+
const SLACK_CONVERSATION_INFO_CACHE = /* @__PURE__ */ new Map();
|
|
408
|
+
async function resolveSlackConversationInfo(params) {
|
|
409
|
+
const channelId = params.channelId.trim();
|
|
410
|
+
if (!channelId) return { type: "unknown" };
|
|
411
|
+
const account = resolveSlackAccount({
|
|
412
|
+
cfg: params.cfg,
|
|
413
|
+
accountId: params.accountId
|
|
414
|
+
});
|
|
415
|
+
const cacheKey = `${account.accountId}:${channelId}`;
|
|
416
|
+
const cached = SLACK_CONVERSATION_INFO_CACHE.get(cacheKey);
|
|
417
|
+
if (cached) return cached;
|
|
418
|
+
const isNativeImChannel = /^D/i.test(channelId);
|
|
419
|
+
const groupChannels = normalizeAllowListLower(account.dm?.groupChannels);
|
|
420
|
+
const channelIdLower = normalizeLowercaseStringOrEmpty(channelId);
|
|
421
|
+
if (!isNativeImChannel && (groupChannels.includes(channelIdLower) || groupChannels.includes(`slack:${channelIdLower}`) || groupChannels.includes(`channel:${channelIdLower}`) || groupChannels.includes(`group:${channelIdLower}`) || groupChannels.includes(`mpim:${channelIdLower}`))) {
|
|
422
|
+
const result = { type: "group" };
|
|
423
|
+
SLACK_CONVERSATION_INFO_CACHE.set(cacheKey, result);
|
|
424
|
+
return result;
|
|
425
|
+
}
|
|
426
|
+
const channelKeys = Object.keys(account.channels ?? {});
|
|
427
|
+
if (!isNativeImChannel && channelKeys.some((key) => {
|
|
428
|
+
const normalized = normalizeLowercaseStringOrEmpty(key);
|
|
429
|
+
return normalized === channelIdLower || normalized === `channel:${channelIdLower}` || normalized.replace(/^#/, "") === channelIdLower;
|
|
430
|
+
})) {
|
|
431
|
+
const result = { type: "channel" };
|
|
432
|
+
SLACK_CONVERSATION_INFO_CACHE.set(cacheKey, result);
|
|
433
|
+
return result;
|
|
434
|
+
}
|
|
435
|
+
const token = normalizeOptionalString(account.botToken) ?? normalizeOptionalString(account.config.userToken) ?? "";
|
|
436
|
+
if (!token) {
|
|
437
|
+
const result = { type: isNativeImChannel ? "dm" : "unknown" };
|
|
438
|
+
if (!isNativeImChannel) SLACK_CONVERSATION_INFO_CACHE.set(cacheKey, result);
|
|
439
|
+
return result;
|
|
440
|
+
}
|
|
441
|
+
try {
|
|
442
|
+
const client = createSlackWebClient(token);
|
|
443
|
+
if (isNativeImChannel) {
|
|
444
|
+
const opened = await client.conversations.open({
|
|
445
|
+
channel: channelId,
|
|
446
|
+
prevent_creation: true,
|
|
447
|
+
return_im: true
|
|
448
|
+
});
|
|
449
|
+
const user = typeof opened.channel?.user === "string" && opened.channel.user.trim() ? opened.channel.user.trim() : void 0;
|
|
450
|
+
const result = user ? {
|
|
451
|
+
type: "dm",
|
|
452
|
+
user
|
|
453
|
+
} : { type: "dm" };
|
|
454
|
+
if (user) SLACK_CONVERSATION_INFO_CACHE.set(cacheKey, result);
|
|
455
|
+
return result;
|
|
456
|
+
}
|
|
457
|
+
const channel = (await client.conversations.info({ channel: channelId })).channel;
|
|
458
|
+
const result = { type: channel?.is_im ? "dm" : channel?.is_mpim ? "group" : "channel" };
|
|
459
|
+
SLACK_CONVERSATION_INFO_CACHE.set(cacheKey, result);
|
|
460
|
+
return result;
|
|
461
|
+
} catch {
|
|
462
|
+
const result = { type: isNativeImChannel ? "dm" : "unknown" };
|
|
463
|
+
if (!isNativeImChannel) SLACK_CONVERSATION_INFO_CACHE.set(cacheKey, result);
|
|
464
|
+
return result;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
async function resolveSlackChannelType(params) {
|
|
468
|
+
return (await resolveSlackConversationInfo(params)).type;
|
|
469
|
+
}
|
|
470
|
+
function __resetSlackChannelTypeCacheForTest() {
|
|
471
|
+
SLACK_CONVERSATION_INFO_CACHE.clear();
|
|
472
|
+
}
|
|
473
|
+
//#endregion
|
|
474
|
+
//#region extensions/slack/src/threading-tool-context.ts
|
|
475
|
+
function buildSlackThreadingToolContext(params) {
|
|
476
|
+
const configuredReplyToMode = resolveSlackReplyToMode(resolveSlackAccount({
|
|
477
|
+
cfg: params.cfg,
|
|
478
|
+
accountId: params.accountId
|
|
479
|
+
}), params.context.ChatType);
|
|
480
|
+
const effectiveReplyToMode = params.context.MessageThreadId != null ? "all" : configuredReplyToMode;
|
|
481
|
+
const threadId = params.context.MessageThreadId ?? params.context.ReplyToId;
|
|
482
|
+
return {
|
|
483
|
+
currentChannelId: params.context.To?.startsWith("channel:") ? params.context.To.slice(8) : normalizeOptionalString(params.context.NativeChannelId),
|
|
484
|
+
currentThreadTs: normalizeSlackThreadTsCandidate(threadId),
|
|
485
|
+
replyToMode: effectiveReplyToMode,
|
|
486
|
+
hasRepliedRef: params.hasRepliedRef
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
//#endregion
|
|
490
|
+
//#region extensions/slack/src/channel.ts
|
|
491
|
+
const EXTENSION_SHARED_MODULE_ID = "openclaw/plugin-sdk/extension-shared";
|
|
492
|
+
const TARGET_RESOLVER_RUNTIME_MODULE_ID = "openclaw/plugin-sdk/target-resolver-runtime";
|
|
493
|
+
const loadExtensionSharedSdk = createLazyRuntimeModule(() => import(EXTENSION_SHARED_MODULE_ID));
|
|
494
|
+
const loadTargetResolverRuntimeSdk = createLazyRuntimeModule(() => import(TARGET_RESOLVER_RUNTIME_MODULE_ID));
|
|
495
|
+
const loadSlackSetupSurfaceModule = createLazyRuntimeModule(() => import("./setup-surface-D88QBVOW.js"));
|
|
496
|
+
const loadSlackScopesModule = createLazyRuntimeModule(() => import("./scopes-CDevO8jg.js"));
|
|
497
|
+
const loadSlackOutboundAdapterModule = createLazyRuntimeModule(() => import("./outbound-adapter-B_5sEhCg.js").then((n) => n.t));
|
|
498
|
+
async function resolveSlackHandleAction() {
|
|
499
|
+
return getOptionalSlackRuntime()?.channel?.slack?.handleSlackAction ?? (await loadSlackActionRuntime()).handleSlackAction;
|
|
500
|
+
}
|
|
501
|
+
function shouldTreatSlackDeliveredTextAsVisible(params) {
|
|
502
|
+
return params.kind === "block" && typeof params.text === "string" && params.text.trim().length > 0;
|
|
503
|
+
}
|
|
504
|
+
function getTokenForOperation(account, operation) {
|
|
505
|
+
const userToken = normalizeOptionalString(account.config.userToken);
|
|
506
|
+
const botToken = normalizeOptionalString(account.botToken);
|
|
507
|
+
const allowUserWrites = account.config.userTokenReadOnly === false;
|
|
508
|
+
if (operation === "read") return userToken ?? botToken;
|
|
509
|
+
if (!allowUserWrites) return botToken;
|
|
510
|
+
return botToken ?? userToken;
|
|
511
|
+
}
|
|
512
|
+
let slackActionRuntimePromise;
|
|
513
|
+
let slackSendRuntimePromise;
|
|
514
|
+
let slackProbeModulePromise;
|
|
515
|
+
let slackMonitorModulePromise;
|
|
516
|
+
let slackDirectoryLiveModulePromise;
|
|
517
|
+
const loadSlackDirectoryConfigModule = createLazyRuntimeModule(() => import("./directory-config-B3JiHeB7.js").then((n) => n.t));
|
|
518
|
+
const loadSlackResolveChannelsModule = createLazyRuntimeModule(() => import("./resolve-channels-BRYqyNVJ.js").then((n) => n.n));
|
|
519
|
+
const loadSlackResolveUsersModule = createLazyRuntimeModule(() => import("./resolve-users-Bd_SdP8j.js").then((n) => n.n));
|
|
520
|
+
async function loadSlackActionRuntime() {
|
|
521
|
+
slackActionRuntimePromise ??= import("./action-runtime.runtime-BFcqMbOm.js");
|
|
522
|
+
return await slackActionRuntimePromise;
|
|
523
|
+
}
|
|
524
|
+
async function loadSlackSendRuntime() {
|
|
525
|
+
slackSendRuntimePromise ??= import("./send.runtime-_l76lUuL.js");
|
|
526
|
+
return await slackSendRuntimePromise;
|
|
527
|
+
}
|
|
528
|
+
async function loadSlackProbeModule() {
|
|
529
|
+
slackProbeModulePromise ??= import("./probe-3eZf1FjI.js").then((n) => n.n);
|
|
530
|
+
return await slackProbeModulePromise;
|
|
531
|
+
}
|
|
532
|
+
async function loadSlackMonitorModule() {
|
|
533
|
+
slackMonitorModulePromise ??= import("./monitor-a97o17G6.js").then((n) => n.t);
|
|
534
|
+
return await slackMonitorModulePromise;
|
|
535
|
+
}
|
|
536
|
+
async function loadSlackDirectoryLiveModule() {
|
|
537
|
+
slackDirectoryLiveModulePromise ??= import("./directory-live-Bf16GwDh.js").then((n) => n.t);
|
|
538
|
+
return await slackDirectoryLiveModulePromise;
|
|
539
|
+
}
|
|
540
|
+
async function resolveSlackSendContext(params) {
|
|
541
|
+
const send = resolveOutboundSendDep(params.deps, "slack") ?? (await loadSlackSendRuntime()).sendMessageSlack;
|
|
542
|
+
const account = resolveSlackAccount({
|
|
543
|
+
cfg: params.cfg,
|
|
544
|
+
accountId: params.accountId
|
|
545
|
+
});
|
|
546
|
+
const token = getTokenForOperation(account, "write");
|
|
547
|
+
const botToken = account.botToken?.trim();
|
|
548
|
+
const tokenOverride = token && token !== botToken ? token : void 0;
|
|
549
|
+
return {
|
|
550
|
+
send,
|
|
551
|
+
threadTsValue: resolveSlackThreadTsValue(params),
|
|
552
|
+
tokenOverride
|
|
553
|
+
};
|
|
554
|
+
}
|
|
555
|
+
function parseSlackExplicitTarget(raw) {
|
|
556
|
+
const target = parseSlackTarget(raw, { defaultKind: "channel" });
|
|
557
|
+
if (!target) return null;
|
|
558
|
+
return {
|
|
559
|
+
to: target.id,
|
|
560
|
+
chatType: target.kind === "user" ? "direct" : "channel"
|
|
561
|
+
};
|
|
562
|
+
}
|
|
563
|
+
function normalizeSlackAcpConversationId(raw) {
|
|
564
|
+
const trimmed = normalizeOptionalString(raw);
|
|
565
|
+
if (!trimmed) return null;
|
|
566
|
+
const conversationId = normalizeLowercaseStringOrEmpty(parseSlackTarget(trimmed, { defaultKind: "channel" })?.id ?? trimmed.replace(/^slack:/i, "").replace(/^(?:channel|group|direct|user):/i, ""));
|
|
567
|
+
return conversationId ? { conversationId } : null;
|
|
568
|
+
}
|
|
569
|
+
function matchSlackAcpConversation(params) {
|
|
570
|
+
const bindingConversationId = normalizeSlackAcpConversationId(params.bindingConversationId)?.conversationId;
|
|
571
|
+
const conversationId = normalizeSlackAcpConversationId(params.conversationId)?.conversationId;
|
|
572
|
+
const parentConversationId = normalizeSlackAcpConversationId(params.parentConversationId)?.conversationId;
|
|
573
|
+
if (!bindingConversationId || !conversationId) return null;
|
|
574
|
+
if (bindingConversationId === conversationId) return {
|
|
575
|
+
conversationId,
|
|
576
|
+
matchPriority: 2
|
|
577
|
+
};
|
|
578
|
+
if (parentConversationId && parentConversationId !== conversationId && bindingConversationId === parentConversationId) return {
|
|
579
|
+
conversationId: parentConversationId,
|
|
580
|
+
matchPriority: 1
|
|
581
|
+
};
|
|
582
|
+
return null;
|
|
583
|
+
}
|
|
584
|
+
function buildSlackBaseSessionKey(params) {
|
|
585
|
+
return buildOutboundBaseSessionKey({
|
|
586
|
+
...params,
|
|
587
|
+
channel: "slack"
|
|
588
|
+
});
|
|
589
|
+
}
|
|
590
|
+
function shouldRecoverSlackThreadFromCurrentSession(params) {
|
|
591
|
+
if (params.peerKind === "direct" && (params.cfg.session?.dmScope ?? "main") === "main") return false;
|
|
592
|
+
return true;
|
|
593
|
+
}
|
|
594
|
+
async function resolveSlackOutboundSessionRoute(params) {
|
|
595
|
+
const parsed = parseSlackTarget(params.target, { defaultKind: "channel" });
|
|
596
|
+
if (!parsed) return null;
|
|
597
|
+
const isDm = parsed.kind === "user";
|
|
598
|
+
let peerKind = isDm ? "direct" : "channel";
|
|
599
|
+
let peerId = parsed.id;
|
|
600
|
+
if (!isDm && /^D/i.test(parsed.id)) {
|
|
601
|
+
const conversation = await resolveSlackConversationInfo({
|
|
602
|
+
cfg: params.cfg,
|
|
603
|
+
accountId: params.accountId,
|
|
604
|
+
channelId: parsed.id
|
|
605
|
+
});
|
|
606
|
+
if (conversation.type !== "dm" || !conversation.user) return null;
|
|
607
|
+
peerKind = "direct";
|
|
608
|
+
peerId = conversation.user;
|
|
609
|
+
} else if (!isDm && /^G/i.test(parsed.id)) {
|
|
610
|
+
const channelType = await resolveSlackChannelType({
|
|
611
|
+
cfg: params.cfg,
|
|
612
|
+
accountId: params.accountId,
|
|
613
|
+
channelId: parsed.id
|
|
614
|
+
});
|
|
615
|
+
if (channelType === "group") peerKind = "group";
|
|
616
|
+
if (channelType === "dm") peerKind = "direct";
|
|
617
|
+
}
|
|
618
|
+
const peer = {
|
|
619
|
+
kind: peerKind,
|
|
620
|
+
id: peerId
|
|
621
|
+
};
|
|
622
|
+
const baseSessionKey = buildSlackBaseSessionKey({
|
|
623
|
+
cfg: params.cfg,
|
|
624
|
+
agentId: params.agentId,
|
|
625
|
+
accountId: params.accountId,
|
|
626
|
+
peer
|
|
627
|
+
});
|
|
628
|
+
return buildThreadAwareOutboundSessionRoute({
|
|
629
|
+
route: {
|
|
630
|
+
sessionKey: baseSessionKey,
|
|
631
|
+
baseSessionKey,
|
|
632
|
+
peer,
|
|
633
|
+
chatType: peerKind === "direct" ? "direct" : "channel",
|
|
634
|
+
from: peerKind === "direct" ? `slack:${peerId}` : peerKind === "group" ? `slack:group:${peerId}` : `slack:channel:${peerId}`,
|
|
635
|
+
to: peerKind === "direct" ? `user:${peerId}` : `channel:${peerId}`
|
|
636
|
+
},
|
|
637
|
+
replyToId: params.replyToId,
|
|
638
|
+
threadId: params.threadId,
|
|
639
|
+
currentSessionKey: params.currentSessionKey,
|
|
640
|
+
canRecoverCurrentThread: () => shouldRecoverSlackThreadFromCurrentSession({
|
|
641
|
+
cfg: params.cfg,
|
|
642
|
+
peerKind
|
|
643
|
+
})
|
|
644
|
+
});
|
|
645
|
+
}
|
|
646
|
+
function formatSlackScopeDiagnostic(params) {
|
|
647
|
+
const source = params.result.source ? ` (${params.result.source})` : "";
|
|
648
|
+
const label = params.tokenType === "user" ? "User scopes" : "Bot scopes";
|
|
649
|
+
if (params.result.ok && params.result.scopes?.length) return { text: `${label}${source}: ${params.result.scopes.join(", ")}` };
|
|
650
|
+
return {
|
|
651
|
+
text: `${label}: ${params.result.error ?? "scope lookup failed"}`,
|
|
652
|
+
tone: "error"
|
|
653
|
+
};
|
|
654
|
+
}
|
|
655
|
+
const resolveSlackAllowlistGroupOverrides = createFlatAllowlistOverrideResolver({
|
|
656
|
+
resolveRecord: (account) => account.channels,
|
|
657
|
+
label: (key) => key,
|
|
658
|
+
resolveEntries: (value) => value?.users
|
|
659
|
+
});
|
|
660
|
+
const resolveSlackAllowlistNames = createAccountScopedAllowlistNameResolver({
|
|
661
|
+
resolveAccount: resolveSlackAccount,
|
|
662
|
+
resolveToken: (account) => normalizeOptionalString(account.config.userToken) ?? normalizeOptionalString(account.botToken),
|
|
663
|
+
resolveNames: async ({ token, entries }) => (await loadSlackResolveUsersModule()).resolveSlackUserAllowlist({
|
|
664
|
+
token,
|
|
665
|
+
entries
|
|
666
|
+
})
|
|
667
|
+
});
|
|
668
|
+
const slackChannelOutbound = {
|
|
669
|
+
deliveryMode: "direct",
|
|
670
|
+
chunker: null,
|
|
671
|
+
textChunkLimit: SLACK_TEXT_LIMIT,
|
|
672
|
+
normalizePayload: ({ payload, cfg, accountId }) => isSlackInteractiveRepliesEnabled({
|
|
673
|
+
cfg,
|
|
674
|
+
accountId
|
|
675
|
+
}) ? compileSlackInteractiveReplies(payload) : payload,
|
|
676
|
+
deliveryCapabilities: { durableFinal: {
|
|
677
|
+
text: true,
|
|
678
|
+
media: true,
|
|
679
|
+
payload: true,
|
|
680
|
+
replyTo: true,
|
|
681
|
+
thread: true,
|
|
682
|
+
messageSendingHooks: true
|
|
683
|
+
} },
|
|
684
|
+
shouldTreatDeliveredTextAsVisible: shouldTreatSlackDeliveredTextAsVisible,
|
|
685
|
+
shouldSuppressLocalPayloadPrompt: ({ cfg, accountId, payload }) => shouldSuppressLocalSlackExecApprovalPrompt({
|
|
686
|
+
cfg,
|
|
687
|
+
accountId,
|
|
688
|
+
payload
|
|
689
|
+
}),
|
|
690
|
+
sendPayload: async (ctx) => {
|
|
691
|
+
const { send, threadTsValue, tokenOverride } = await resolveSlackSendContext({
|
|
692
|
+
cfg: ctx.cfg,
|
|
693
|
+
accountId: ctx.accountId ?? void 0,
|
|
694
|
+
deps: ctx.deps,
|
|
695
|
+
replyToId: ctx.replyToId,
|
|
696
|
+
threadId: ctx.threadId
|
|
697
|
+
});
|
|
698
|
+
const { slackOutbound } = await loadSlackOutboundAdapterModule();
|
|
699
|
+
return await slackOutbound.sendPayload({
|
|
700
|
+
...ctx,
|
|
701
|
+
replyToId: threadTsValue,
|
|
702
|
+
threadId: null,
|
|
703
|
+
deps: {
|
|
704
|
+
...ctx.deps,
|
|
705
|
+
slack: async (to, text, opts) => await send(to, text, {
|
|
706
|
+
...opts,
|
|
707
|
+
...tokenOverride ? { token: tokenOverride } : {}
|
|
708
|
+
})
|
|
709
|
+
}
|
|
710
|
+
});
|
|
711
|
+
},
|
|
712
|
+
...createAttachedChannelResultAdapter({
|
|
713
|
+
channel: "slack",
|
|
714
|
+
sendText: async ({ to, text, accountId, deps, replyToId, threadId, cfg }) => {
|
|
715
|
+
const { send, threadTsValue, tokenOverride } = await resolveSlackSendContext({
|
|
716
|
+
cfg,
|
|
717
|
+
accountId: accountId ?? void 0,
|
|
718
|
+
deps,
|
|
719
|
+
replyToId,
|
|
720
|
+
threadId
|
|
721
|
+
});
|
|
722
|
+
return await send(to, text, {
|
|
723
|
+
cfg,
|
|
724
|
+
threadTs: threadTsValue,
|
|
725
|
+
accountId: accountId ?? void 0,
|
|
726
|
+
...tokenOverride ? { token: tokenOverride } : {}
|
|
727
|
+
});
|
|
728
|
+
},
|
|
729
|
+
sendMedia: async ({ to, text, mediaUrl, mediaLocalRoots, accountId, deps, replyToId, threadId, cfg }) => {
|
|
730
|
+
const { send, threadTsValue, tokenOverride } = await resolveSlackSendContext({
|
|
731
|
+
cfg,
|
|
732
|
+
accountId: accountId ?? void 0,
|
|
733
|
+
deps,
|
|
734
|
+
replyToId,
|
|
735
|
+
threadId
|
|
736
|
+
});
|
|
737
|
+
return await send(to, text, {
|
|
738
|
+
cfg,
|
|
739
|
+
mediaUrl,
|
|
740
|
+
mediaLocalRoots,
|
|
741
|
+
threadTs: threadTsValue,
|
|
742
|
+
accountId: accountId ?? void 0,
|
|
743
|
+
...tokenOverride ? { token: tokenOverride } : {}
|
|
744
|
+
});
|
|
745
|
+
}
|
|
746
|
+
})
|
|
747
|
+
};
|
|
748
|
+
const slackMessageAdapter = createChannelMessageAdapterFromOutbound({
|
|
749
|
+
id: "slack",
|
|
750
|
+
outbound: slackChannelOutbound,
|
|
751
|
+
live: {
|
|
752
|
+
capabilities: {
|
|
753
|
+
draftPreview: true,
|
|
754
|
+
previewFinalization: true,
|
|
755
|
+
progressUpdates: true,
|
|
756
|
+
nativeStreaming: true
|
|
757
|
+
},
|
|
758
|
+
finalizer: { capabilities: {
|
|
759
|
+
finalEdit: true,
|
|
760
|
+
normalFallback: true,
|
|
761
|
+
discardPending: true
|
|
762
|
+
} }
|
|
763
|
+
}
|
|
764
|
+
});
|
|
765
|
+
const slackPlugin = createChatChannelPlugin({
|
|
766
|
+
base: {
|
|
767
|
+
...createSlackPluginBase({
|
|
768
|
+
setupWizard: createSlackSetupWizardProxy(loadSlackSetupSurfaceModule),
|
|
769
|
+
setup: slackSetupAdapter
|
|
770
|
+
}),
|
|
771
|
+
allowlist: {
|
|
772
|
+
...buildLegacyDmAccountAllowlistAdapter({
|
|
773
|
+
channelId: "slack",
|
|
774
|
+
resolveAccount: resolveSlackAccount,
|
|
775
|
+
normalize: ({ cfg, accountId, values }) => slackConfigAdapter.formatAllowFrom({
|
|
776
|
+
cfg,
|
|
777
|
+
accountId,
|
|
778
|
+
allowFrom: values
|
|
779
|
+
}),
|
|
780
|
+
resolveDmAllowFrom: (account, { cfg }) => resolveSlackAccountAllowFrom({
|
|
781
|
+
cfg,
|
|
782
|
+
accountId: account.accountId
|
|
783
|
+
}),
|
|
784
|
+
resolveGroupPolicy: (account) => account.groupPolicy,
|
|
785
|
+
resolveGroupOverrides: resolveSlackAllowlistGroupOverrides
|
|
786
|
+
}),
|
|
787
|
+
resolveNames: resolveSlackAllowlistNames
|
|
788
|
+
},
|
|
789
|
+
approvalCapability: slackApprovalCapability,
|
|
790
|
+
groups: {
|
|
791
|
+
resolveRequireMention: resolveSlackGroupRequireMention,
|
|
792
|
+
resolveToolPolicy: resolveSlackGroupToolPolicy
|
|
793
|
+
},
|
|
794
|
+
bindings: {
|
|
795
|
+
compileConfiguredBinding: ({ conversationId }) => normalizeSlackAcpConversationId(conversationId),
|
|
796
|
+
matchInboundConversation: ({ compiledBinding, conversationId, parentConversationId }) => matchSlackAcpConversation({
|
|
797
|
+
bindingConversationId: compiledBinding.conversationId,
|
|
798
|
+
conversationId,
|
|
799
|
+
parentConversationId
|
|
800
|
+
})
|
|
801
|
+
},
|
|
802
|
+
messaging: {
|
|
803
|
+
targetPrefixes: ["slack"],
|
|
804
|
+
normalizeTarget: normalizeSlackMessagingTarget,
|
|
805
|
+
resolveDeliveryTarget: ({ conversationId, parentConversationId }) => {
|
|
806
|
+
const parent = parentConversationId?.trim();
|
|
807
|
+
const child = conversationId.trim();
|
|
808
|
+
return parent && parent !== child ? {
|
|
809
|
+
to: `channel:${parent}`,
|
|
810
|
+
threadId: child
|
|
811
|
+
} : { to: normalizeSlackMessagingTarget(`channel:${child}`) };
|
|
812
|
+
},
|
|
813
|
+
resolveSessionTarget: ({ id }) => normalizeSlackMessagingTarget(`channel:${id}`),
|
|
814
|
+
parseExplicitTarget: ({ raw }) => parseSlackExplicitTarget(raw),
|
|
815
|
+
inferTargetChatType: ({ to }) => parseSlackExplicitTarget(to)?.chatType,
|
|
816
|
+
resolveOutboundSessionRoute: async (params) => await resolveSlackOutboundSessionRoute(params),
|
|
817
|
+
transformReplyPayload: ({ payload, cfg, accountId }) => isSlackInteractiveRepliesEnabled({
|
|
818
|
+
cfg,
|
|
819
|
+
accountId
|
|
820
|
+
}) ? compileSlackInteractiveReplies(payload) : payload,
|
|
821
|
+
enableInteractiveReplies: ({ cfg, accountId }) => isSlackInteractiveRepliesEnabled({
|
|
822
|
+
cfg,
|
|
823
|
+
accountId
|
|
824
|
+
}),
|
|
825
|
+
hasStructuredReplyPayload: ({ payload }) => {
|
|
826
|
+
try {
|
|
827
|
+
return Boolean(resolveSlackReplyBlocks(payload)?.length);
|
|
828
|
+
} catch {
|
|
829
|
+
return false;
|
|
830
|
+
}
|
|
831
|
+
},
|
|
832
|
+
targetResolver: {
|
|
833
|
+
looksLikeId: looksLikeSlackTargetId,
|
|
834
|
+
hint: "<channelId|user:ID|channel:ID>",
|
|
835
|
+
resolveTarget: async ({ input }) => {
|
|
836
|
+
const parsed = parseSlackExplicitTarget(input);
|
|
837
|
+
if (!parsed) return null;
|
|
838
|
+
return {
|
|
839
|
+
to: parsed.to,
|
|
840
|
+
kind: parsed.chatType === "direct" ? "user" : "group",
|
|
841
|
+
source: "normalized"
|
|
842
|
+
};
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
},
|
|
846
|
+
directory: createChannelDirectoryAdapter({
|
|
847
|
+
listPeers: async (params) => (await loadSlackDirectoryConfigModule()).listSlackDirectoryPeersFromConfig(params),
|
|
848
|
+
listGroups: async (params) => (await loadSlackDirectoryConfigModule()).listSlackDirectoryGroupsFromConfig(params),
|
|
849
|
+
...createRuntimeDirectoryLiveAdapter({
|
|
850
|
+
getRuntime: loadSlackDirectoryLiveModule,
|
|
851
|
+
self: (runtime) => runtime.getSlackDirectorySelfLive,
|
|
852
|
+
listPeersLive: (runtime) => runtime.listSlackDirectoryPeersLive,
|
|
853
|
+
listGroupsLive: (runtime) => runtime.listSlackDirectoryGroupsLive
|
|
854
|
+
})
|
|
855
|
+
}),
|
|
856
|
+
resolver: { resolveTargets: async ({ cfg, accountId, inputs, kind }) => {
|
|
857
|
+
const toResolvedTarget = (entry, note) => ({
|
|
858
|
+
input: entry.input,
|
|
859
|
+
resolved: entry.resolved,
|
|
860
|
+
id: entry.id,
|
|
861
|
+
name: entry.name,
|
|
862
|
+
note
|
|
863
|
+
});
|
|
864
|
+
const account = resolveSlackAccount({
|
|
865
|
+
cfg,
|
|
866
|
+
accountId
|
|
867
|
+
});
|
|
868
|
+
const { resolveTargetsWithOptionalToken } = await loadTargetResolverRuntimeSdk();
|
|
869
|
+
if (kind === "group") return resolveTargetsWithOptionalToken({
|
|
870
|
+
token: normalizeOptionalString(account.config.userToken) ?? normalizeOptionalString(account.botToken),
|
|
871
|
+
inputs,
|
|
872
|
+
missingTokenNote: "missing Slack token",
|
|
873
|
+
resolveWithToken: async ({ token, inputs }) => (await loadSlackResolveChannelsModule()).resolveSlackChannelAllowlist({
|
|
874
|
+
token,
|
|
875
|
+
entries: inputs
|
|
876
|
+
}),
|
|
877
|
+
mapResolved: (entry) => toResolvedTarget(entry, entry.archived ? "archived" : void 0)
|
|
878
|
+
});
|
|
879
|
+
return resolveTargetsWithOptionalToken({
|
|
880
|
+
token: normalizeOptionalString(account.config.userToken) ?? normalizeOptionalString(account.botToken),
|
|
881
|
+
inputs,
|
|
882
|
+
missingTokenNote: "missing Slack token",
|
|
883
|
+
resolveWithToken: async ({ token, inputs }) => (await loadSlackResolveUsersModule()).resolveSlackUserAllowlist({
|
|
884
|
+
token,
|
|
885
|
+
entries: inputs
|
|
886
|
+
}),
|
|
887
|
+
mapResolved: (entry) => toResolvedTarget(entry, entry.note)
|
|
888
|
+
});
|
|
889
|
+
} },
|
|
890
|
+
actions: createSlackActions(SLACK_CHANNEL, { invoke: async (action, cfg, toolContext) => await (await resolveSlackHandleAction())(action, cfg, toolContext) }),
|
|
891
|
+
message: slackMessageAdapter,
|
|
892
|
+
status: createComputedAccountStatusAdapter({
|
|
893
|
+
defaultRuntime: createDefaultChannelRuntimeState(DEFAULT_ACCOUNT_ID),
|
|
894
|
+
buildChannelSummary: async ({ snapshot }) => {
|
|
895
|
+
const { buildPassiveProbedChannelStatusSummary } = await loadExtensionSharedSdk();
|
|
896
|
+
return buildPassiveProbedChannelStatusSummary(snapshot, {
|
|
897
|
+
botTokenSource: snapshot.botTokenSource ?? "none",
|
|
898
|
+
appTokenSource: snapshot.appTokenSource ?? "none"
|
|
899
|
+
});
|
|
900
|
+
},
|
|
901
|
+
probeAccount: async ({ account, timeoutMs }) => {
|
|
902
|
+
const token = account.botToken?.trim();
|
|
903
|
+
if (!token) return {
|
|
904
|
+
ok: false,
|
|
905
|
+
error: "missing token"
|
|
906
|
+
};
|
|
907
|
+
return await (await loadSlackProbeModule()).probeSlack(token, timeoutMs);
|
|
908
|
+
},
|
|
909
|
+
formatCapabilitiesProbe: ({ probe }) => {
|
|
910
|
+
const slackProbe = probe;
|
|
911
|
+
const lines = [];
|
|
912
|
+
if (slackProbe?.bot?.name) lines.push({ text: `Bot: @${slackProbe.bot.name}` });
|
|
913
|
+
if (slackProbe?.team?.name || slackProbe?.team?.id) {
|
|
914
|
+
const id = slackProbe.team?.id ? ` (${slackProbe.team.id})` : "";
|
|
915
|
+
lines.push({ text: `Team: ${slackProbe.team?.name ?? "unknown"}${id}` });
|
|
916
|
+
}
|
|
917
|
+
return lines;
|
|
918
|
+
},
|
|
919
|
+
buildCapabilitiesDiagnostics: async ({ account, timeoutMs }) => {
|
|
920
|
+
const lines = [];
|
|
921
|
+
const details = {};
|
|
922
|
+
const botToken = account.botToken?.trim();
|
|
923
|
+
const userToken = account.config.userToken?.trim();
|
|
924
|
+
const { fetchSlackScopes } = await loadSlackScopesModule();
|
|
925
|
+
const botScopes = botToken ? await fetchSlackScopes(botToken, timeoutMs) : {
|
|
926
|
+
ok: false,
|
|
927
|
+
error: "Slack bot token missing."
|
|
928
|
+
};
|
|
929
|
+
lines.push(formatSlackScopeDiagnostic({
|
|
930
|
+
tokenType: "bot",
|
|
931
|
+
result: botScopes
|
|
932
|
+
}));
|
|
933
|
+
details.botScopes = botScopes;
|
|
934
|
+
if (userToken) {
|
|
935
|
+
const userScopes = await fetchSlackScopes(userToken, timeoutMs);
|
|
936
|
+
lines.push(formatSlackScopeDiagnostic({
|
|
937
|
+
tokenType: "user",
|
|
938
|
+
result: userScopes
|
|
939
|
+
}));
|
|
940
|
+
details.userScopes = userScopes;
|
|
941
|
+
}
|
|
942
|
+
return {
|
|
943
|
+
lines,
|
|
944
|
+
details
|
|
945
|
+
};
|
|
946
|
+
},
|
|
947
|
+
resolveAccountSnapshot: ({ account }) => {
|
|
948
|
+
const configured = ((account.config.mode ?? "socket") === "http" ? resolveConfiguredFromRequiredCredentialStatuses(account, ["botTokenStatus", "signingSecretStatus"]) : resolveConfiguredFromRequiredCredentialStatuses(account, ["botTokenStatus", "appTokenStatus"])) ?? isSlackPluginAccountConfigured(account);
|
|
949
|
+
return {
|
|
950
|
+
accountId: account.accountId,
|
|
951
|
+
name: account.name,
|
|
952
|
+
enabled: account.enabled,
|
|
953
|
+
configured,
|
|
954
|
+
extra: { ...projectCredentialSnapshotFields(account) }
|
|
955
|
+
};
|
|
956
|
+
}
|
|
957
|
+
}),
|
|
958
|
+
gateway: { startAccount: async (ctx) => {
|
|
959
|
+
const account = ctx.account;
|
|
960
|
+
const botToken = account.botToken?.trim();
|
|
961
|
+
const appToken = account.appToken?.trim();
|
|
962
|
+
ctx.log?.info(`[${account.accountId}] starting provider`);
|
|
963
|
+
return (await loadSlackMonitorModule()).monitorSlackProvider({
|
|
964
|
+
botToken: botToken ?? "",
|
|
965
|
+
appToken: appToken ?? "",
|
|
966
|
+
accountId: account.accountId,
|
|
967
|
+
config: ctx.cfg,
|
|
968
|
+
runtime: ctx.runtime,
|
|
969
|
+
channelRuntime: ctx.channelRuntime,
|
|
970
|
+
abortSignal: ctx.abortSignal,
|
|
971
|
+
mediaMaxMb: account.config.mediaMaxMb,
|
|
972
|
+
slashCommand: account.config.slashCommand,
|
|
973
|
+
setStatus: ctx.setStatus,
|
|
974
|
+
getStatus: ctx.getStatus
|
|
975
|
+
});
|
|
976
|
+
} },
|
|
977
|
+
mentions: { stripPatterns: () => ["<@[^>\\s]+>"] }
|
|
978
|
+
},
|
|
979
|
+
pairing: { text: {
|
|
980
|
+
idLabel: "slackUserId",
|
|
981
|
+
message: PAIRING_APPROVED_MESSAGE,
|
|
982
|
+
normalizeAllowEntry: createPairingPrefixStripper(/^(slack|user):/i),
|
|
983
|
+
notify: async ({ cfg, id, message }) => {
|
|
984
|
+
const account = resolveSlackAccount({
|
|
985
|
+
cfg,
|
|
986
|
+
accountId: resolveDefaultSlackAccountId(cfg)
|
|
987
|
+
});
|
|
988
|
+
const { sendMessageSlack } = await loadSlackSendRuntime();
|
|
989
|
+
const token = getTokenForOperation(account, "write");
|
|
990
|
+
await sendMessageSlack(`user:${id}`, message, {
|
|
991
|
+
cfg,
|
|
992
|
+
accountId: account.accountId,
|
|
993
|
+
...token ? { token } : {}
|
|
994
|
+
});
|
|
995
|
+
}
|
|
996
|
+
} },
|
|
997
|
+
security: slackSecurityAdapter,
|
|
998
|
+
threading: {
|
|
999
|
+
scopedAccountReplyToMode: {
|
|
1000
|
+
resolveAccount: adaptScopedAccountAccessor(resolveSlackAccount),
|
|
1001
|
+
resolveReplyToMode: (account, chatType) => resolveSlackReplyToMode(account, chatType)
|
|
1002
|
+
},
|
|
1003
|
+
allowExplicitReplyTagsWhenOff: false,
|
|
1004
|
+
buildToolContext: (params) => buildSlackThreadingToolContext(params),
|
|
1005
|
+
resolveAutoThreadId: ({ to, toolContext, replyToId }) => normalizeSlackThreadTsCandidate(replyToId) ? void 0 : normalizeSlackThreadTsCandidate(resolveSlackAutoThreadId({
|
|
1006
|
+
to,
|
|
1007
|
+
toolContext
|
|
1008
|
+
})),
|
|
1009
|
+
resolveReplyTransport: ({ threadId, replyToId }) => ({
|
|
1010
|
+
replyToId: resolveSlackThreadTsValue({
|
|
1011
|
+
replyToId,
|
|
1012
|
+
threadId
|
|
1013
|
+
}),
|
|
1014
|
+
threadId: null
|
|
1015
|
+
})
|
|
1016
|
+
},
|
|
1017
|
+
outbound: slackChannelOutbound
|
|
1018
|
+
});
|
|
1019
|
+
//#endregion
|
|
1020
|
+
export { createSlackActions as a, resolveSlackChannelType as i, buildSlackThreadingToolContext as n, resolveSlackAutoThreadId as o, __resetSlackChannelTypeCacheForTest as r, slackPlugin as t };
|