@openclaw/slack 2026.7.2-beta.3 → 2026.7.2-beta.4
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-api.js +1 -1
- package/dist/{account-inspect-Bvbtu3iH.js → account-inspect-jn1xLaVi.js} +2 -2
- package/dist/account-reply-mode-DrUXogvO.js +14 -0
- package/dist/{accounts-DQEbYKh9.js → accounts-BSr252c_.js} +6 -27
- package/dist/{accounts.runtime-BIKmJdtJ.js → accounts.runtime-CjULMLTa.js} +1 -1
- package/dist/{action-runtime-DqkRwO3Z.js → action-runtime-CFU52n4W.js} +7 -7
- package/dist/action-runtime.runtime-9-17zvKH.js +2 -0
- package/dist/{actions-CF0tUY5q.js → actions-D51foiwR.js} +5 -5
- package/dist/{actions.runtime-hCbx4RXg.js → actions.runtime-BMJwtf5C.js} +1 -1
- package/dist/api.js +15 -14
- package/dist/{approval-handler.runtime-Em8I1-8-.js → approval-handler.runtime-3b4-wxMl.js} +2 -2
- package/dist/{channel-4-TRi1D6.js → channel-Ds8NKvfr.js} +26 -24
- package/dist/channel-config-api.js +1 -1
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel-type-Cu1yjNg2.js → channel-type-DXkUajFP.js} +3 -3
- package/dist/{channel.setup-CgkADtZg.js → channel.setup-DOSTEDfA.js} +6 -5
- package/dist/{config-schema-XjJGfwQC.js → config-schema-B4j4tCOI.js} +231 -26
- package/dist/{directory-config-Bv0lcUlH.js → directory-config-B08pm5ZT.js} +1 -1
- package/dist/directory-contract-api.js +1 -1
- package/dist/{directory-live-CzUIB7th.js → directory-live-DpPKzPrn.js} +2 -2
- package/dist/{doctor-contract-DKpe5VBr.js → doctor-contract-U6oVntbM.js} +60 -89
- package/dist/doctor-contract-api.js +1 -1
- package/dist/{group-policy-Bw-65m3V.js → group-policy-CdnQzQBI.js} +32 -5
- package/dist/{interactive-replies-Dm_t2R9S.js → interactive-replies-C3ffk6oN.js} +1 -1
- package/dist/interactive-replies-api.js +1 -1
- package/dist/{message-tool-api-C2pcf5du.js → message-tool-api-ByVyIVOh.js} +2 -2
- package/dist/message-tool-api.js +1 -1
- package/dist/{monitor-CNFeF30h.js → monitor-CnB_WKvF.js} +3 -3
- package/dist/{outbound-adapter-CVi2uok0.js → outbound-adapter-DuPz2HHt.js} +3 -3
- package/dist/{pipeline.runtime-CTvokbty.js → pipeline.runtime-5rRYZuX5.js} +110 -77
- package/dist/{policy-b_dOPDCq.js → policy-C31RYSuT.js} +1 -1
- package/dist/{probe-Borhn9PQ.js → probe-CVRuArHA.js} +1 -1
- package/dist/{provider-B-HVL5ZE.js → provider-htuIJGFD.js} +365 -200
- package/dist/{relay-source-Ea_P9VcO.js → relay-source-Df9EaiTF.js} +1 -1
- package/dist/{replies-B4bOdrYb.js → replies-Cgr2Gli4.js} +3 -3
- package/dist/{resolve-channels-KTc568SU.js → resolve-channels-DodP2TFx.js} +1 -1
- package/dist/{resolve-users-DeGJf1yp.js → resolve-users-M9eF8891.js} +1 -1
- package/dist/{runtime-api-BFfNpzDe.js → runtime-api-D5XYMMsf.js} +3 -2
- package/dist/runtime-api.js +11 -11
- package/dist/{scopes-lx08L56K.js → scopes-CJRpHkDC.js} +1 -1
- package/dist/{security-audit-CikQhBUY.js → security-audit-Cz6erklv.js} +0 -10
- package/dist/security-contract-api.js +1 -1
- package/dist/{send-KuTDky7i.js → send-BZ1tPv7-.js} +4 -4
- package/dist/{send.runtime-CXyxws1D.js → send.runtime-a2pilFor.js} +1 -1
- package/dist/{setup-core-CeiAVwQ3.js → setup-core-tPxMuFez.js} +138 -40
- package/dist/setup-plugin-api.js +1 -1
- package/dist/{setup-surface-DLA0vHXp.js → setup-surface-wV-S1dE_.js} +43 -27
- package/dist/{shared-C4yVB0Q-.js → shared-BfMskaMx.js} +9 -8
- package/dist/{slash-dispatch.runtime-BT-mMm-f.js → slash-dispatch.runtime-lfeIsXTX.js} +1 -1
- package/node_modules/@types/node/README.md +1 -1
- package/node_modules/@types/node/fs/promises.d.ts +16 -6
- package/node_modules/@types/node/package.json +2 -2
- package/node_modules/agent-base/README.md +145 -0
- package/node_modules/agent-base/dist/src/index.d.ts +78 -0
- package/node_modules/agent-base/dist/src/index.js +203 -0
- package/node_modules/agent-base/dist/src/index.js.map +1 -0
- package/node_modules/agent-base/dist/src/promisify.d.ts +4 -0
- package/node_modules/agent-base/dist/src/promisify.js +18 -0
- package/node_modules/agent-base/dist/src/promisify.js.map +1 -0
- package/node_modules/agent-base/package.json +64 -0
- package/node_modules/agent-base/src/index.ts +345 -0
- package/node_modules/agent-base/src/promisify.ts +33 -0
- package/node_modules/axios/CHANGELOG.md +197 -1
- package/node_modules/axios/README.md +424 -256
- package/node_modules/axios/dist/axios.js +589 -204
- package/node_modules/axios/dist/axios.min.js +3 -3
- package/node_modules/axios/dist/axios.min.js.map +1 -1
- package/node_modules/axios/dist/browser/axios.cjs +630 -185
- package/node_modules/axios/dist/esm/axios.js +630 -185
- package/node_modules/axios/dist/esm/axios.min.js +2 -2
- package/node_modules/axios/dist/esm/axios.min.js.map +1 -1
- package/node_modules/axios/dist/node/axios.cjs +949 -301
- package/node_modules/axios/index.d.cts +28 -5
- package/node_modules/axios/index.d.ts +24 -3
- package/node_modules/axios/lib/adapters/adapters.js +1 -1
- package/node_modules/axios/lib/adapters/fetch.js +223 -49
- package/node_modules/axios/lib/adapters/http.js +408 -193
- package/node_modules/axios/lib/adapters/xhr.js +3 -1
- package/node_modules/axios/lib/core/Axios.js +4 -2
- package/node_modules/axios/lib/core/AxiosError.js +13 -1
- package/node_modules/axios/lib/core/AxiosHeaders.js +13 -42
- package/node_modules/axios/lib/core/buildFullPath.js +29 -1
- package/node_modules/axios/lib/core/mergeConfig.js +35 -0
- package/node_modules/axios/lib/defaults/transitional.js +2 -0
- package/node_modules/axios/lib/env/data.js +1 -1
- package/node_modules/axios/lib/helpers/AxiosURLSearchParams.js +1 -3
- package/node_modules/axios/lib/helpers/Http2Sessions.js +119 -0
- package/node_modules/axios/lib/helpers/buildURL.js +7 -4
- package/node_modules/axios/lib/helpers/composeSignals.js +48 -47
- package/node_modules/axios/lib/helpers/cookies.js +5 -1
- package/node_modules/axios/lib/helpers/estimateDataURLDecodedBytes.js +16 -11
- package/node_modules/axios/lib/helpers/formDataToJSON.js +26 -4
- package/node_modules/axios/lib/helpers/formDataToStream.js +2 -2
- package/node_modules/axios/lib/helpers/fromDataURI.js +20 -5
- package/node_modules/axios/lib/helpers/progressEventReducer.js +3 -0
- package/node_modules/axios/lib/helpers/resolveConfig.js +26 -13
- package/node_modules/axios/lib/helpers/sanitizeHeaderValue.js +60 -0
- package/node_modules/axios/lib/helpers/shouldBypassProxy.js +33 -1
- package/node_modules/axios/lib/helpers/toFormData.js +48 -12
- package/node_modules/axios/lib/helpers/validator.js +1 -1
- package/node_modules/axios/lib/utils.js +105 -19
- package/node_modules/axios/package.json +31 -13
- package/node_modules/https-proxy-agent/README.md +137 -0
- package/node_modules/https-proxy-agent/dist/agent.d.ts +30 -0
- package/node_modules/https-proxy-agent/dist/agent.js +177 -0
- package/node_modules/https-proxy-agent/dist/agent.js.map +1 -0
- package/node_modules/https-proxy-agent/dist/index.d.ts +23 -0
- package/node_modules/https-proxy-agent/dist/index.js +14 -0
- package/node_modules/https-proxy-agent/dist/index.js.map +1 -0
- package/node_modules/https-proxy-agent/dist/parse-proxy-response.d.ts +7 -0
- package/node_modules/https-proxy-agent/dist/parse-proxy-response.js +66 -0
- package/node_modules/https-proxy-agent/dist/parse-proxy-response.js.map +1 -0
- package/node_modules/https-proxy-agent/package.json +56 -0
- package/node_modules/iconv-lite/encodings/sbcs-data.js +2 -0
- package/node_modules/iconv-lite/encodings/utf32.js +10 -3
- package/node_modules/iconv-lite/package.json +2 -2
- package/node_modules/iconv-lite/types/encodings.d.ts +2 -0
- package/node_modules/path-to-regexp/Readme.md +3 -3
- package/node_modules/path-to-regexp/dist/index.js +135 -158
- package/node_modules/path-to-regexp/dist/index.js.map +1 -1
- package/node_modules/path-to-regexp/package.json +2 -2
- package/node_modules/qs/CHANGELOG.md +11 -0
- package/node_modules/qs/dist/qs.js +17 -17
- package/node_modules/qs/lib/parse.js +19 -8
- package/node_modules/qs/lib/utils.js +47 -8
- package/node_modules/qs/package.json +6 -5
- package/node_modules/qs/test/parse.js +230 -0
- package/node_modules/qs/test/utils.js +194 -0
- package/node_modules/typebox/build/compile/validator.d.mts +1 -4
- package/node_modules/typebox/build/guard/guard.d.mts +1 -1
- package/node_modules/typebox/build/guard/guard.mjs +5 -2
- package/node_modules/typebox/build/guard/string.mjs +16 -4
- package/node_modules/typebox/build/schema/engine/_functions.mjs +34 -15
- package/node_modules/typebox/build/type/action/readonly_object.d.mts +5 -0
- package/node_modules/typebox/build/type/action/readonly_object.mjs +8 -0
- package/node_modules/typebox/build/typebox.d.mts +1 -1
- package/node_modules/typebox/build/typebox.mjs +1 -1
- package/node_modules/typebox/package.json +1 -1
- package/node_modules/typebox/readme.md +29 -32
- package/node_modules/ws/lib/receiver.js +15 -32
- package/node_modules/ws/lib/websocket-server.js +4 -4
- package/node_modules/ws/lib/websocket.js +4 -4
- package/node_modules/ws/package.json +5 -1
- package/npm-shrinkwrap.json +54 -27
- package/openclaw.plugin.json +1759 -1908
- package/package.json +92 -14
- package/dist/action-runtime.runtime-DEWOcFM4.js +0 -2
- package/dist/config-api-Df9a1B8C.js +0 -3
- package/node_modules/axios/dist/axios.js.map +0 -1
- package/node_modules/axios/dist/browser/axios.cjs.map +0 -1
- package/node_modules/axios/dist/esm/axios.js.map +0 -1
- package/node_modules/axios/dist/node/axios.cjs.map +0 -1
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { n as registerSlackHttpHandler, r as normalizeSlackWebhookPath } from "./registry-bbjH7IHX.js";
|
|
2
|
-
import { a as resolveSlackAccount, d as
|
|
3
|
-
import { F as SLACK_TEXT_LIMIT, G as isSlackQuestionActionId, K as decodeSlackQuestionAction, U as isSlackApprovalActionId, W as isSlackCallbackActionId, X as decodeSlackApprovalAction, Y as escapeSlackMrkdwn, a as allowListMatches, c as normalizeSlackAllowOwnerEntry, ft as isSlackApprovalAuthorizedSender, l as normalizeSlackSlug, mt as isSlackExecApprovalAuthorizedSender, nt as isSlackAnyNativeApprovalClientEnabled, o as normalizeAllowList, q as resolveSlackQuestionAction, s as normalizeAllowListLower, u as resolveSlackAllowListMatch, z as truncateSlackText } from "./group-policy-
|
|
4
|
-
import { n as isSlackInteractiveRepliesEnabled, t as compileSlackInteractiveReplies } from "./interactive-replies-
|
|
5
|
-
import { m as resolveSlackWebClientOptions, o as createSlackStartupAuthClient, r as formatSlackError, u as getSlackListenerUploadCompletionClient } from "./probe-
|
|
6
|
-
import { n as getSlackRuntime } from "./runtime-JSVZSWAj.js";
|
|
7
|
-
import { i as setSlackDefaultSendIdentity } from "./send-
|
|
8
|
-
import { t as resolveSlackChannelAllowlist } from "./resolve-channels-
|
|
9
|
-
import { t as resolveSlackUserAllowlist } from "./resolve-users-
|
|
10
|
-
import { n as resolveSlackChannelConfig, r as resolveSlackChannelLabel, t as isSlackChannelAllowedByPolicy } from "./policy-
|
|
2
|
+
import { a as resolveSlackAccount, d as resolveSlackAppToken, f as resolveSlackBotToken, i as resolveDefaultSlackAccountId, o as resolveSlackAccountAllowFrom, s as resolveSlackAccountDmPolicy, u as formatSlackBotTokenIdentityWarning } from "./accounts-BSr252c_.js";
|
|
3
|
+
import { F as SLACK_TEXT_LIMIT, G as isSlackQuestionActionId, K as decodeSlackQuestionAction, U as isSlackApprovalActionId, W as isSlackCallbackActionId, X as decodeSlackApprovalAction, Y as escapeSlackMrkdwn, a as allowListMatches, c as normalizeSlackAllowOwnerEntry, ft as isSlackApprovalAuthorizedSender, l as normalizeSlackSlug, mt as isSlackExecApprovalAuthorizedSender, nt as isSlackAnyNativeApprovalClientEnabled, o as normalizeAllowList, q as resolveSlackQuestionAction, s as normalizeAllowListLower, u as resolveSlackAllowListMatch, z as truncateSlackText } from "./group-policy-CdnQzQBI.js";
|
|
4
|
+
import { n as isSlackInteractiveRepliesEnabled, t as compileSlackInteractiveReplies } from "./interactive-replies-C3ffk6oN.js";
|
|
5
|
+
import { m as resolveSlackWebClientOptions, o as createSlackStartupAuthClient, r as formatSlackError, u as getSlackListenerUploadCompletionClient } from "./probe-CVRuArHA.js";
|
|
6
|
+
import { n as getSlackRuntime, t as getOptionalSlackRuntime } from "./runtime-JSVZSWAj.js";
|
|
7
|
+
import { i as setSlackDefaultSendIdentity } from "./send-BZ1tPv7-.js";
|
|
8
|
+
import { t as resolveSlackChannelAllowlist } from "./resolve-channels-DodP2TFx.js";
|
|
9
|
+
import { t as resolveSlackUserAllowlist } from "./resolve-users-M9eF8891.js";
|
|
10
|
+
import { n as resolveSlackChannelConfig, r as resolveSlackChannelLabel, t as isSlackChannelAllowedByPolicy } from "./policy-C31RYSuT.js";
|
|
11
11
|
import { normalizeResolvedSecretInputString } from "openclaw/plugin-sdk/secret-input";
|
|
12
12
|
import { asOptionalRecord, isRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeStringEntries, normalizeStringEntriesLower, normalizeUniqueTrimmedStringList } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
13
13
|
import { normalizeAccountId, normalizeMainKey, resolveAgentRoute, resolveThreadSessionKeys } from "openclaw/plugin-sdk/routing";
|
|
14
|
-
import {
|
|
14
|
+
import { createChannelIngressMonitor, createChannelMessageReplyPipeline } from "openclaw/plugin-sdk/channel-outbound";
|
|
15
15
|
import { createChannelPairingChallengeIssuer } from "openclaw/plugin-sdk/channel-pairing";
|
|
16
16
|
import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
|
|
17
17
|
import { computeBackoff, createNonExitingRuntime, createSubsystemLogger, danger, getChildLogger, logVerbose, shouldLogVerbose, sleepWithAbort, warn } from "openclaw/plugin-sdk/runtime-env";
|
|
@@ -35,7 +35,7 @@ import { isDangerousNameMatchingEnabled } from "openclaw/plugin-sdk/dangerous-na
|
|
|
35
35
|
import { getSessionEntry, readSessionUpdatedAt, resolveChannelResetConfig, resolveSessionKey, resolveStorePath, resolveStorePath as resolveStorePath$1, updateLastRoute } from "openclaw/plugin-sdk/session-store-runtime";
|
|
36
36
|
import { resolveChannelContextVisibilityMode } from "openclaw/plugin-sdk/context-visibility-runtime";
|
|
37
37
|
import { resolveDefaultGroupPolicy, resolveOpenProviderRuntimeGroupPolicy as resolveOpenProviderRuntimeGroupPolicy$1, warnMissingProviderGroupPolicyFallbackOnce } from "openclaw/plugin-sdk/runtime-group-policy";
|
|
38
|
-
import {
|
|
38
|
+
import { loadPreparedModelCatalog, resolveAgentDir, resolveDefaultAgentId, resolveDefaultModelForAgent } from "openclaw/plugin-sdk/agent-runtime";
|
|
39
39
|
import { resolveChannelConfigWrites } from "openclaw/plugin-sdk/channel-config-writes";
|
|
40
40
|
import { mutateConfigFile } from "openclaw/plugin-sdk/config-mutation";
|
|
41
41
|
import { enqueueSystemEvent } from "openclaw/plugin-sdk/system-event-runtime";
|
|
@@ -45,7 +45,7 @@ import { requestHeartbeat } from "openclaw/plugin-sdk/heartbeat-runtime";
|
|
|
45
45
|
import { createInteractiveConversationBindingHelpers, dispatchPluginInteractiveHandler } from "openclaw/plugin-sdk/plugin-runtime";
|
|
46
46
|
import { createChannelIngressResolver, defineStableChannelIngressIdentity, readChannelIngressStoreAllowFromForDmPolicy } from "openclaw/plugin-sdk/channel-ingress-runtime";
|
|
47
47
|
import { createChannelInboundDebouncer, shouldDebounceTextInbound } from "openclaw/plugin-sdk/channel-inbound";
|
|
48
|
-
import { createChannelReplayGuard } from "openclaw/plugin-sdk/persistent-dedupe";
|
|
48
|
+
import { createChannelReplayGuard, runClaimableDedupeClaimLoop } from "openclaw/plugin-sdk/persistent-dedupe";
|
|
49
49
|
import { generateSecureToken } from "openclaw/plugin-sdk/secure-random-runtime";
|
|
50
50
|
//#region extensions/slack/src/monitor/commands.ts
|
|
51
51
|
/**
|
|
@@ -72,6 +72,151 @@ function buildSlackSlashCommandMatcher(name) {
|
|
|
72
72
|
return new RegExp(`^/?${escaped}$`);
|
|
73
73
|
}
|
|
74
74
|
//#endregion
|
|
75
|
+
//#region extensions/slack/src/monitor/agent-view-state.ts
|
|
76
|
+
const SLACK_AGENT_VIEW_STATE_NAMESPACE = "agent-view-workspaces";
|
|
77
|
+
const SLACK_AGENT_VIEW_THREAD_STATE_NAMESPACE = "agent-view-threads";
|
|
78
|
+
const SLACK_AGENT_VIEW_STATE_MAX_ENTRIES = 4096;
|
|
79
|
+
const SLACK_AGENT_VIEW_THREAD_STATE_MAX_ENTRIES = 4096;
|
|
80
|
+
const SLACK_MANAGED_THREAD_CACHE_MAX_ENTRIES = 4096;
|
|
81
|
+
function createSlackAgentViewState(params) {
|
|
82
|
+
let enabled = false;
|
|
83
|
+
let loaded = false;
|
|
84
|
+
let persisted = false;
|
|
85
|
+
let workspaceStore;
|
|
86
|
+
let threadStore;
|
|
87
|
+
let warned = false;
|
|
88
|
+
const managedThreads = /* @__PURE__ */ new Map();
|
|
89
|
+
const warnOnce = (action, error) => {
|
|
90
|
+
if (warned) return;
|
|
91
|
+
warned = true;
|
|
92
|
+
params.warn(action, error);
|
|
93
|
+
};
|
|
94
|
+
const openWorkspaceStore = () => {
|
|
95
|
+
if (workspaceStore) return workspaceStore;
|
|
96
|
+
const runtime = getOptionalSlackRuntime();
|
|
97
|
+
if (!runtime) return;
|
|
98
|
+
try {
|
|
99
|
+
workspaceStore = runtime.state.openKeyedStore({
|
|
100
|
+
namespace: SLACK_AGENT_VIEW_STATE_NAMESPACE,
|
|
101
|
+
maxEntries: SLACK_AGENT_VIEW_STATE_MAX_ENTRIES
|
|
102
|
+
});
|
|
103
|
+
return workspaceStore;
|
|
104
|
+
} catch (error) {
|
|
105
|
+
warnOnce("open", error);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
const openThreadStore = () => {
|
|
110
|
+
if (threadStore) return threadStore;
|
|
111
|
+
const runtime = getOptionalSlackRuntime();
|
|
112
|
+
if (!runtime) return;
|
|
113
|
+
try {
|
|
114
|
+
threadStore = runtime.state.openKeyedStore({
|
|
115
|
+
namespace: SLACK_AGENT_VIEW_THREAD_STATE_NAMESPACE,
|
|
116
|
+
maxEntries: SLACK_AGENT_VIEW_THREAD_STATE_MAX_ENTRIES
|
|
117
|
+
});
|
|
118
|
+
return threadStore;
|
|
119
|
+
} catch (error) {
|
|
120
|
+
warnOnce("open", error);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
const workspaceStateKey = params.apiAppId ? JSON.stringify([
|
|
125
|
+
"workspace",
|
|
126
|
+
params.accountId,
|
|
127
|
+
params.teamId,
|
|
128
|
+
params.apiAppId
|
|
129
|
+
]) : void 0;
|
|
130
|
+
const record = async () => {
|
|
131
|
+
enabled = true;
|
|
132
|
+
loaded = true;
|
|
133
|
+
if (persisted || !workspaceStateKey) return;
|
|
134
|
+
const openedStore = openWorkspaceStore();
|
|
135
|
+
if (!openedStore) return;
|
|
136
|
+
try {
|
|
137
|
+
await openedStore.register(workspaceStateKey, {
|
|
138
|
+
experience: "agent",
|
|
139
|
+
observedAt: Date.now()
|
|
140
|
+
});
|
|
141
|
+
persisted = true;
|
|
142
|
+
} catch (error) {
|
|
143
|
+
warnOnce("persist", error);
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
const isEnabled = async () => {
|
|
147
|
+
if (enabled) return true;
|
|
148
|
+
if (loaded) return false;
|
|
149
|
+
if (!workspaceStateKey) {
|
|
150
|
+
loaded = true;
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
const openedStore = openWorkspaceStore();
|
|
154
|
+
if (!openedStore) return false;
|
|
155
|
+
try {
|
|
156
|
+
const stored = await openedStore.lookup(workspaceStateKey);
|
|
157
|
+
loaded = true;
|
|
158
|
+
enabled = stored?.experience === "agent";
|
|
159
|
+
persisted = enabled;
|
|
160
|
+
return enabled;
|
|
161
|
+
} catch (error) {
|
|
162
|
+
warnOnce("load", error);
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
const managedThreadKey = (channelId, threadTs) => JSON.stringify([channelId, threadTs]);
|
|
167
|
+
const managedThreadStateKey = (channelId, threadTs) => params.apiAppId ? JSON.stringify([
|
|
168
|
+
"thread",
|
|
169
|
+
params.accountId,
|
|
170
|
+
params.teamId,
|
|
171
|
+
params.apiAppId,
|
|
172
|
+
channelId,
|
|
173
|
+
threadTs
|
|
174
|
+
]) : void 0;
|
|
175
|
+
const rememberManagedThread = (key) => {
|
|
176
|
+
managedThreads.delete(key);
|
|
177
|
+
managedThreads.set(key, true);
|
|
178
|
+
if (managedThreads.size <= SLACK_MANAGED_THREAD_CACHE_MAX_ENTRIES) return;
|
|
179
|
+
const oldestKey = managedThreads.keys().next().value;
|
|
180
|
+
if (oldestKey !== void 0) managedThreads.delete(oldestKey);
|
|
181
|
+
};
|
|
182
|
+
const recordManagedThread = async (channelId, threadTs) => {
|
|
183
|
+
const key = managedThreadKey(channelId, threadTs);
|
|
184
|
+
rememberManagedThread(key);
|
|
185
|
+
const stateKey = managedThreadStateKey(channelId, threadTs);
|
|
186
|
+
const openedStore = stateKey ? openThreadStore() : void 0;
|
|
187
|
+
if (!openedStore || !stateKey) return;
|
|
188
|
+
try {
|
|
189
|
+
await openedStore.register(stateKey, {
|
|
190
|
+
experience: "managed-thread",
|
|
191
|
+
observedAt: Date.now()
|
|
192
|
+
});
|
|
193
|
+
} catch (error) {
|
|
194
|
+
warnOnce("persist", error);
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
const isManagedThread = async (channelId, threadTs) => {
|
|
198
|
+
const key = managedThreadKey(channelId, threadTs);
|
|
199
|
+
if (managedThreads.has(key)) return true;
|
|
200
|
+
const stateKey = managedThreadStateKey(channelId, threadTs);
|
|
201
|
+
const openedStore = stateKey ? openThreadStore() : void 0;
|
|
202
|
+
if (!openedStore || !stateKey) return false;
|
|
203
|
+
try {
|
|
204
|
+
const found = (await openedStore.lookup(stateKey))?.experience === "managed-thread";
|
|
205
|
+
if (found) rememberManagedThread(key);
|
|
206
|
+
return found;
|
|
207
|
+
} catch (error) {
|
|
208
|
+
warnOnce("load", error);
|
|
209
|
+
return false;
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
return {
|
|
213
|
+
isEnabled,
|
|
214
|
+
isManagedThread,
|
|
215
|
+
record,
|
|
216
|
+
recordManagedThread
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
//#endregion
|
|
75
220
|
//#region extensions/slack/src/monitor/channel-type.ts
|
|
76
221
|
function inferSlackChannelType(channelId) {
|
|
77
222
|
const trimmed = channelId?.trim();
|
|
@@ -111,6 +256,42 @@ function writeLruMapEntry(cache, cacheKey, entry, maxEntries) {
|
|
|
111
256
|
pruneMapToMaxSize(cache, maxEntries);
|
|
112
257
|
}
|
|
113
258
|
//#endregion
|
|
259
|
+
//#region extensions/slack/src/monitor/suggested-prompts.ts
|
|
260
|
+
const DEFAULT_SLACK_SUGGESTED_PROMPTS = [
|
|
261
|
+
{
|
|
262
|
+
title: "What can you do?",
|
|
263
|
+
message: "What can you help me with?"
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
title: "Summarize this channel",
|
|
267
|
+
message: "Summarize the recent activity in this channel."
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
title: "Draft a reply",
|
|
271
|
+
message: "Help me draft a reply."
|
|
272
|
+
}
|
|
273
|
+
];
|
|
274
|
+
async function updateSlackSuggestedPrompts(params) {
|
|
275
|
+
const prompts = params.prompts.map((prompt) => ({
|
|
276
|
+
title: prompt.title.trim(),
|
|
277
|
+
message: prompt.message.trim()
|
|
278
|
+
})).filter((prompt) => prompt.title && prompt.message).slice(0, 4);
|
|
279
|
+
if (prompts.length === 0) return false;
|
|
280
|
+
try {
|
|
281
|
+
await params.client.assistant.threads.setSuggestedPrompts({
|
|
282
|
+
token: params.botToken,
|
|
283
|
+
channel_id: params.channelId,
|
|
284
|
+
...params.threadTs ? { thread_ts: params.threadTs } : {},
|
|
285
|
+
...params.title?.trim() ? { title: params.title.trim() } : {},
|
|
286
|
+
prompts
|
|
287
|
+
});
|
|
288
|
+
return true;
|
|
289
|
+
} catch (error) {
|
|
290
|
+
logVerbose(`slack suggested prompts update failed for channel ${params.channelId}: ${formatSlackError(error)}`);
|
|
291
|
+
return false;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
//#endregion
|
|
114
295
|
//#region extensions/slack/src/monitor/context.ts
|
|
115
296
|
const SLACK_ASSISTANT_THREAD_CONTEXT_METADATA_EVENT = "assistant_thread_context";
|
|
116
297
|
const SLACK_CHANNEL_CACHE_MAX_ENTRIES = 1024;
|
|
@@ -157,6 +338,12 @@ function createSlackMonitorContext(params) {
|
|
|
157
338
|
});
|
|
158
339
|
const assistantThreadContexts = /* @__PURE__ */ new Map();
|
|
159
340
|
let lastAssistantContextCleanupAt = Date.now();
|
|
341
|
+
const agentViewState = createSlackAgentViewState({
|
|
342
|
+
accountId: params.accountId,
|
|
343
|
+
teamId: params.teamId,
|
|
344
|
+
apiAppId: params.apiAppId,
|
|
345
|
+
warn: (action, error) => logger.warn({ error: formatSlackError(error) }, `Slack Agent View state failed to ${action}`)
|
|
346
|
+
});
|
|
160
347
|
const allowFrom = normalizeAllowList(params.allowFrom);
|
|
161
348
|
const groupDmChannels = normalizeAllowList(params.groupDmChannels);
|
|
162
349
|
const groupDmChannelsLower = new Set(normalizeAllowListLower(groupDmChannels).map((entry) => entry.replace(/^channel:/, "")));
|
|
@@ -331,26 +518,11 @@ function createSlackMonitorContext(params) {
|
|
|
331
518
|
logVerbose(`slack status update failed for channel ${p.channelId}: ${formatSlackError(err)}`);
|
|
332
519
|
}
|
|
333
520
|
};
|
|
334
|
-
const
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
if (prompts.length === 0) return false;
|
|
340
|
-
try {
|
|
341
|
-
await params.app.client.assistant.threads.setSuggestedPrompts({
|
|
342
|
-
token: params.botToken,
|
|
343
|
-
channel_id: p.channelId,
|
|
344
|
-
thread_ts: p.threadTs,
|
|
345
|
-
...p.title?.trim() ? { title: p.title.trim() } : {},
|
|
346
|
-
prompts
|
|
347
|
-
});
|
|
348
|
-
return true;
|
|
349
|
-
} catch (err) {
|
|
350
|
-
logVerbose(`slack suggested prompts update failed for channel ${p.channelId}: ${formatSlackError(err)}`);
|
|
351
|
-
return false;
|
|
352
|
-
}
|
|
353
|
-
};
|
|
521
|
+
const setSlackSuggestedPrompts = (input) => updateSlackSuggestedPrompts({
|
|
522
|
+
...input,
|
|
523
|
+
botToken: params.botToken,
|
|
524
|
+
client: params.app.client
|
|
525
|
+
});
|
|
354
526
|
const isChannelAllowed = (p) => {
|
|
355
527
|
const channelType = normalizeSlackChannelType(p.channelType, p.channelId);
|
|
356
528
|
const isDirectMessage = channelType === "im";
|
|
@@ -466,7 +638,6 @@ function createSlackMonitorContext(params) {
|
|
|
466
638
|
ackReactionScope: params.ackReactionScope,
|
|
467
639
|
typingReaction: params.typingReaction,
|
|
468
640
|
mediaMaxBytes: params.mediaMaxBytes,
|
|
469
|
-
removeAckAfterReply: params.removeAckAfterReply,
|
|
470
641
|
logger,
|
|
471
642
|
shouldDropMismatchedSlackEvent,
|
|
472
643
|
resolveSlackSystemEventSessionKey,
|
|
@@ -478,7 +649,11 @@ function createSlackMonitorContext(params) {
|
|
|
478
649
|
setSlackThreadStatus,
|
|
479
650
|
getSlackAssistantThreadContext,
|
|
480
651
|
saveSlackAssistantThreadContext,
|
|
481
|
-
|
|
652
|
+
setSlackSuggestedPrompts,
|
|
653
|
+
recordSlackAgentView: agentViewState.record,
|
|
654
|
+
isSlackAgentView: agentViewState.isEnabled,
|
|
655
|
+
recordSlackManagedViewThread: agentViewState.recordManagedThread,
|
|
656
|
+
isSlackManagedViewThread: agentViewState.isManagedThread
|
|
482
657
|
};
|
|
483
658
|
}
|
|
484
659
|
//#endregion
|
|
@@ -521,8 +696,8 @@ function assertEnterpriseSlackPolicyConfig(params) {
|
|
|
521
696
|
predicate: isStableSlackAllowlistUserEntry
|
|
522
697
|
});
|
|
523
698
|
assertStableEntries({
|
|
524
|
-
values: config.
|
|
525
|
-
path: `channels.slack.accounts.${accountId}.
|
|
699
|
+
values: config.allowFrom,
|
|
700
|
+
path: `channels.slack.accounts.${accountId}.allowFrom`,
|
|
526
701
|
predicate: isStableSlackAllowlistUserEntry
|
|
527
702
|
});
|
|
528
703
|
assertStableEntries({
|
|
@@ -611,21 +786,21 @@ function resolveSlackIdentityHealth(params) {
|
|
|
611
786
|
};
|
|
612
787
|
}
|
|
613
788
|
//#endregion
|
|
789
|
+
//#region extensions/slack/src/monitor/events/agent.ts
|
|
790
|
+
function registerSlackAgentEvents(params) {
|
|
791
|
+
const { ctx, trackEvent } = params;
|
|
792
|
+
ctx.app.event("app_context_changed", async ({ body }) => {
|
|
793
|
+
try {
|
|
794
|
+
if (ctx.shouldDropMismatchedSlackEvent(body)) return;
|
|
795
|
+
trackEvent?.();
|
|
796
|
+
await ctx.recordSlackAgentView();
|
|
797
|
+
} catch (error) {
|
|
798
|
+
ctx.runtime.error?.(danger(`slack app_context_changed handler failed: ${formatErrorMessage(error)}`));
|
|
799
|
+
}
|
|
800
|
+
});
|
|
801
|
+
}
|
|
802
|
+
//#endregion
|
|
614
803
|
//#region extensions/slack/src/monitor/events/assistant.ts
|
|
615
|
-
const DEFAULT_ASSISTANT_PROMPTS = [
|
|
616
|
-
{
|
|
617
|
-
title: "What can you do?",
|
|
618
|
-
message: "What can you help me with?"
|
|
619
|
-
},
|
|
620
|
-
{
|
|
621
|
-
title: "Summarize this channel",
|
|
622
|
-
message: "Summarize the recent activity in this channel."
|
|
623
|
-
},
|
|
624
|
-
{
|
|
625
|
-
title: "Draft a reply",
|
|
626
|
-
message: "Help me draft a reply."
|
|
627
|
-
}
|
|
628
|
-
];
|
|
629
804
|
function normalizeAssistantThread(event, getPrevious) {
|
|
630
805
|
const thread = event.assistant_thread;
|
|
631
806
|
if (!thread) return null;
|
|
@@ -687,11 +862,11 @@ function registerSlackAssistantEvents(params) {
|
|
|
687
862
|
return;
|
|
688
863
|
}
|
|
689
864
|
ctx.saveSlackAssistantThreadContext(assistantThread);
|
|
690
|
-
await ctx.
|
|
865
|
+
await ctx.setSlackSuggestedPrompts({
|
|
691
866
|
channelId: assistantThread.assistantChannelId,
|
|
692
867
|
threadTs: assistantThread.threadTs,
|
|
693
868
|
title: "Try asking",
|
|
694
|
-
prompts:
|
|
869
|
+
prompts: DEFAULT_SLACK_SUGGESTED_PROMPTS
|
|
695
870
|
});
|
|
696
871
|
} catch (err) {
|
|
697
872
|
ctx.runtime.error?.(danger(`slack assistant_thread_started handler failed: ${formatErrorMessage(err)}`));
|
|
@@ -931,7 +1106,16 @@ function registerSlackHomeEvents(params) {
|
|
|
931
1106
|
if (ctx.shouldDropMismatchedSlackEvent(body)) return;
|
|
932
1107
|
trackEvent?.();
|
|
933
1108
|
const payload = event;
|
|
934
|
-
if (!payload.user
|
|
1109
|
+
if (!payload.user) return;
|
|
1110
|
+
if (payload.tab === "messages") {
|
|
1111
|
+
if (!payload.channel) return;
|
|
1112
|
+
if (await ctx.setSlackSuggestedPrompts({
|
|
1113
|
+
channelId: payload.channel,
|
|
1114
|
+
title: "Try asking",
|
|
1115
|
+
prompts: DEFAULT_SLACK_SUGGESTED_PROMPTS
|
|
1116
|
+
})) await ctx.recordSlackAgentView();
|
|
1117
|
+
return;
|
|
1118
|
+
}
|
|
935
1119
|
await ctx.app.client.views.publish({
|
|
936
1120
|
token: ctx.botToken,
|
|
937
1121
|
user_id: payload.user,
|
|
@@ -2812,13 +2996,37 @@ function resolveSlackIngressLane(body, eventId) {
|
|
|
2812
2996
|
function isSlackEventCallback(body) {
|
|
2813
2997
|
return asOptionalRecord(body)?.type === "event_callback";
|
|
2814
2998
|
}
|
|
2815
|
-
function
|
|
2816
|
-
if (payload.version !== SLACK_INGRESS_PAYLOAD_VERSION) throw new SlackIngressPayloadError(`Slack ingress payload ${eventId} was invalid.`);
|
|
2999
|
+
function decodeSlackIngressPayload(payload, eventId) {
|
|
2817
3000
|
if (payload.kind === "relay") {
|
|
2818
3001
|
if (!asOptionalRecord(payload.message)) throw new SlackIngressPayloadError(`Slack relay ingress payload ${eventId} was invalid.`);
|
|
2819
|
-
return
|
|
3002
|
+
return {
|
|
3003
|
+
version: payload.version,
|
|
3004
|
+
body: payload
|
|
3005
|
+
};
|
|
2820
3006
|
}
|
|
2821
3007
|
if (!asOptionalRecord(payload.body) || resolveSlackEventId(payload.body) !== eventId) throw new SlackIngressPayloadError(`Slack ingress payload ${eventId} was invalid.`);
|
|
3008
|
+
return {
|
|
3009
|
+
version: payload.version,
|
|
3010
|
+
body: payload
|
|
3011
|
+
};
|
|
3012
|
+
}
|
|
3013
|
+
function inspectSlackIngress(raw) {
|
|
3014
|
+
if (raw.kind === "relay") {
|
|
3015
|
+
const eventId = resolveSlackRelayIngressEventId({
|
|
3016
|
+
deliveryId: raw.deliveryId,
|
|
3017
|
+
message: raw.message
|
|
3018
|
+
});
|
|
3019
|
+
return {
|
|
3020
|
+
eventId,
|
|
3021
|
+
laneKey: resolveSlackIngressLane({ event: raw.message }, eventId)
|
|
3022
|
+
};
|
|
3023
|
+
}
|
|
3024
|
+
const eventId = resolveSlackEventId(raw.body);
|
|
3025
|
+
if (!eventId) throw new SlackIngressPayloadError("Slack Events API envelope missing event_id.");
|
|
3026
|
+
return {
|
|
3027
|
+
eventId,
|
|
3028
|
+
laneKey: resolveSlackIngressLane(raw.body, eventId)
|
|
3029
|
+
};
|
|
2822
3030
|
}
|
|
2823
3031
|
function resolveSlackIngressNonRetryableFailure(error) {
|
|
2824
3032
|
for (const candidate of collectErrorGraphCandidates(error, (current) => [
|
|
@@ -2844,115 +3052,97 @@ function resolveSlackIngressTurnLifecycle(context) {
|
|
|
2844
3052
|
return typeof lifecycle.onAdopted === "function" && lifecycle.abortSignal instanceof AbortSignal ? lifecycle : null;
|
|
2845
3053
|
}
|
|
2846
3054
|
function createSlackDurableIngress(options) {
|
|
2847
|
-
let queue = options.queue;
|
|
2848
|
-
let drain;
|
|
2849
3055
|
let app;
|
|
2850
3056
|
let relayDispatch;
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
deadLetterMinAgeMs: DEFAULT_INGRESS_RETRY_DEAD_LETTER_MIN_AGE_MS
|
|
3057
|
+
const monitor = createChannelIngressMonitor({
|
|
3058
|
+
queue: options.queue ?? (() => getSlackRuntime().state.openChannelIngressQueue({ accountId: options.accountId })),
|
|
3059
|
+
inspect: inspectSlackIngress,
|
|
3060
|
+
payload: {
|
|
3061
|
+
version: SLACK_INGRESS_PAYLOAD_VERSION,
|
|
3062
|
+
serialize: (raw, { receivedAt }) => raw.kind === "relay" ? {
|
|
3063
|
+
kind: "relay",
|
|
3064
|
+
receivedAt,
|
|
3065
|
+
message: raw.message
|
|
3066
|
+
} : {
|
|
3067
|
+
kind: "events-api",
|
|
3068
|
+
receivedAt,
|
|
3069
|
+
body: raw.body,
|
|
3070
|
+
...raw.retryNum === void 0 ? {} : { retryNum: raw.retryNum },
|
|
3071
|
+
...raw.retryReason === void 0 ? {} : { retryReason: raw.retryReason }
|
|
2867
3072
|
},
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
3073
|
+
deserialize: (body, { claim }) => body.kind === "relay" ? {
|
|
3074
|
+
kind: "relay",
|
|
3075
|
+
deliveryId: claim.id.startsWith("relay:") ? claim.id.slice(6) : claim.id,
|
|
3076
|
+
message: body.message
|
|
3077
|
+
} : {
|
|
3078
|
+
kind: "events-api",
|
|
3079
|
+
body: body.body,
|
|
3080
|
+
...body.retryNum === void 0 ? {} : { retryNum: body.retryNum },
|
|
3081
|
+
...body.retryReason === void 0 ? {} : { retryReason: body.retryReason }
|
|
3082
|
+
},
|
|
3083
|
+
encode: ({ body }) => ({
|
|
3084
|
+
version: SLACK_INGRESS_PAYLOAD_VERSION,
|
|
3085
|
+
...body
|
|
3086
|
+
}),
|
|
3087
|
+
decode: (payload, { claim }) => decodeSlackIngressPayload(payload, claim.id),
|
|
3088
|
+
createClaimError: (_kind, claim) => new SlackIngressPayloadError(`Slack ingress payload ${claim.id} was invalid.`)
|
|
3089
|
+
},
|
|
3090
|
+
onDurableAdmission: async (raw) => {
|
|
3091
|
+
if (raw.kind === "events-api") await raw.afterDurableAdmission?.();
|
|
3092
|
+
},
|
|
3093
|
+
deliver: async (raw, lifecycle) => {
|
|
3094
|
+
if (raw.kind === "relay") {
|
|
3095
|
+
if (!relayDispatch) throw new Error("Slack relay ingress dispatcher is not attached.");
|
|
3096
|
+
await relayDispatch(raw.message, lifecycle);
|
|
3097
|
+
return;
|
|
2889
3098
|
}
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
3099
|
+
if (!app) throw new Error("Slack ingress receiver is not attached to a Bolt app.");
|
|
3100
|
+
await app.processEvent({
|
|
3101
|
+
body: raw.body,
|
|
3102
|
+
ack: async () => {},
|
|
3103
|
+
...raw.retryNum === void 0 ? {} : { retryNum: raw.retryNum },
|
|
3104
|
+
...raw.retryReason === void 0 ? {} : { retryReason: raw.retryReason },
|
|
3105
|
+
customProperties: { [SLACK_INGRESS_LIFECYCLE_CONTEXT_KEY]: lifecycle }
|
|
3106
|
+
});
|
|
3107
|
+
},
|
|
3108
|
+
pollIntervalMs: options.pollIntervalMs ?? SLACK_INGRESS_POLL_INTERVAL_MS,
|
|
3109
|
+
retention: {
|
|
3110
|
+
pruneIntervalMs: SLACK_INGRESS_PRUNE_INTERVAL_MS,
|
|
2897
3111
|
completedTtlMs: SLACK_INGRESS_COMPLETED_TTL_MS,
|
|
2898
3112
|
completedMaxEntries: SLACK_INGRESS_COMPLETED_MAX_ENTRIES,
|
|
2899
3113
|
failedTtlMs: SLACK_INGRESS_FAILED_TTL_MS,
|
|
2900
|
-
failedMaxEntries: SLACK_INGRESS_FAILED_MAX_ENTRIES
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
await activeDrain.waitForIdle();
|
|
2913
|
-
if (!running || !requested && started === 0) break;
|
|
2914
|
-
}
|
|
2915
|
-
} catch (error) {
|
|
2916
|
-
options.onLog?.(`slack ingress drain failed: ${formatErrorMessage(error)}`);
|
|
2917
|
-
} finally {
|
|
2918
|
-
pumping = void 0;
|
|
2919
|
-
if (running && requested) requestDrain();
|
|
2920
|
-
}
|
|
2921
|
-
};
|
|
2922
|
-
const requestDrain = () => {
|
|
2923
|
-
requested = true;
|
|
2924
|
-
if (!running || pumping) return;
|
|
2925
|
-
pumping = runPump();
|
|
2926
|
-
};
|
|
3114
|
+
failedMaxEntries: SLACK_INGRESS_FAILED_MAX_ENTRIES
|
|
3115
|
+
},
|
|
3116
|
+
appendRetryDelaysMs: [0],
|
|
3117
|
+
drain: {
|
|
3118
|
+
resolveNonRetryableFailure: resolveSlackIngressNonRetryableFailure,
|
|
3119
|
+
deriveLaneKey: (record) => record.payload.kind === "relay" ? resolveSlackIngressLane({ event: record.payload.message }, record.id) : resolveSlackIngressLane(record.payload.body, record.id),
|
|
3120
|
+
...options.adoptionStallTimeoutMs === void 0 ? {} : { adoptionStallTimeoutMs: options.adoptionStallTimeoutMs },
|
|
3121
|
+
...options.onLog ? { onLog: options.onLog } : {}
|
|
3122
|
+
},
|
|
3123
|
+
...options.abortSignal ? { abortSignal: options.abortSignal } : {},
|
|
3124
|
+
onError: (error) => options.onLog?.(`slack ingress drain failed: ${formatErrorMessage(error)}`)
|
|
3125
|
+
});
|
|
2927
3126
|
const acceptReceiverEvent = async (event) => {
|
|
2928
3127
|
if (!isSlackEventCallback(event.body)) {
|
|
2929
3128
|
if (!app) throw new Error("Slack ingress receiver is not attached to a Bolt app.");
|
|
2930
3129
|
await app.processEvent(event);
|
|
2931
3130
|
return;
|
|
2932
3131
|
}
|
|
2933
|
-
|
|
2934
|
-
if (!eventId) throw new SlackIngressPayloadError("Slack Events API envelope missing event_id.");
|
|
2935
|
-
const receivedAt = Date.now();
|
|
2936
|
-
await getQueue().enqueue(eventId, {
|
|
2937
|
-
version: SLACK_INGRESS_PAYLOAD_VERSION,
|
|
2938
|
-
receivedAt,
|
|
3132
|
+
await monitor.admit({
|
|
2939
3133
|
kind: "events-api",
|
|
2940
3134
|
body: event.body,
|
|
2941
3135
|
...event.retryNum === void 0 ? {} : { retryNum: event.retryNum },
|
|
2942
|
-
...event.retryReason === void 0 ? {} : { retryReason: event.retryReason }
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
requestDrain();
|
|
3136
|
+
...event.retryReason === void 0 ? {} : { retryReason: event.retryReason },
|
|
3137
|
+
afterDurableAdmission: () => event.ack()
|
|
3138
|
+
});
|
|
2946
3139
|
};
|
|
2947
3140
|
const acceptRelayEvent = async (event) => {
|
|
2948
|
-
|
|
2949
|
-
await getQueue().enqueue(resolveSlackRelayIngressEventId(event), {
|
|
2950
|
-
version: SLACK_INGRESS_PAYLOAD_VERSION,
|
|
2951
|
-
receivedAt,
|
|
3141
|
+
await monitor.admit({
|
|
2952
3142
|
kind: "relay",
|
|
3143
|
+
deliveryId: event.deliveryId,
|
|
2953
3144
|
message: event.message
|
|
2954
|
-
}
|
|
2955
|
-
requestDrain();
|
|
3145
|
+
});
|
|
2956
3146
|
};
|
|
2957
3147
|
return {
|
|
2958
3148
|
wrapReceiver: (receiver) => {
|
|
@@ -2971,31 +3161,9 @@ function createSlackDurableIngress(options) {
|
|
|
2971
3161
|
attachRelayDispatch: (dispatch) => {
|
|
2972
3162
|
relayDispatch = dispatch;
|
|
2973
3163
|
},
|
|
2974
|
-
start:
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
pollTimer = setInterval(requestDrain, options.pollIntervalMs ?? SLACK_INGRESS_POLL_INTERVAL_MS);
|
|
2978
|
-
pollTimer.unref?.();
|
|
2979
|
-
requestDrain();
|
|
2980
|
-
},
|
|
2981
|
-
stop: async () => {
|
|
2982
|
-
running = false;
|
|
2983
|
-
if (pollTimer) {
|
|
2984
|
-
clearInterval(pollTimer);
|
|
2985
|
-
pollTimer = void 0;
|
|
2986
|
-
}
|
|
2987
|
-
drain?.dispose();
|
|
2988
|
-
await pumping;
|
|
2989
|
-
await drain?.waitForIdle();
|
|
2990
|
-
},
|
|
2991
|
-
waitForIdle: async () => {
|
|
2992
|
-
for (;;) {
|
|
2993
|
-
const activePump = pumping;
|
|
2994
|
-
if (!activePump) break;
|
|
2995
|
-
await activePump;
|
|
2996
|
-
}
|
|
2997
|
-
await drain?.waitForIdle();
|
|
2998
|
-
}
|
|
3164
|
+
start: monitor.start,
|
|
3165
|
+
stop: monitor.stop,
|
|
3166
|
+
waitForIdle: monitor.waitForIdle
|
|
2999
3167
|
};
|
|
3000
3168
|
}
|
|
3001
3169
|
//#endregion
|
|
@@ -3377,6 +3545,10 @@ function registerSlackMonitorEvents(params) {
|
|
|
3377
3545
|
slashCommandName: params.appHomeSlashCommandName,
|
|
3378
3546
|
trackEvent: params.trackEvent
|
|
3379
3547
|
});
|
|
3548
|
+
registerSlackAgentEvents({
|
|
3549
|
+
ctx: params.ctx,
|
|
3550
|
+
trackEvent: params.trackEvent
|
|
3551
|
+
});
|
|
3380
3552
|
registerSlackInteractionEvents({
|
|
3381
3553
|
ctx: params.ctx,
|
|
3382
3554
|
trackEvent: params.trackEvent
|
|
@@ -3423,22 +3595,11 @@ function createSlackMessageDispatchReplayGuard(params = {}) {
|
|
|
3423
3595
|
}
|
|
3424
3596
|
/** Claim one logical message key; an in-flight sibling claim settles to duplicate. */
|
|
3425
3597
|
async function claimSlackMessageDispatchReplay(params) {
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
handle: claim.handle
|
|
3432
|
-
};
|
|
3433
|
-
if (claim.kind === "duplicate" || claim.kind === "invalid") return { kind: "duplicate" };
|
|
3434
|
-
try {
|
|
3435
|
-
await claim.pending;
|
|
3436
|
-
return { kind: "duplicate" };
|
|
3437
|
-
} catch {
|
|
3438
|
-
releaseRetries += 1;
|
|
3439
|
-
if (releaseRetries > 1) return { kind: "duplicate" };
|
|
3440
|
-
}
|
|
3441
|
-
}
|
|
3598
|
+
const claim = await runClaimableDedupeClaimLoop(() => params.guard.claim({ keys: [params.key] }), (_error, rejectionCount) => rejectionCount <= 1);
|
|
3599
|
+
return claim.kind === "claimed" ? {
|
|
3600
|
+
kind: "claimed",
|
|
3601
|
+
handle: claim.handle
|
|
3602
|
+
} : { kind: "duplicate" };
|
|
3442
3603
|
}
|
|
3443
3604
|
//#endregion
|
|
3444
3605
|
//#region extensions/slack/src/monitor/message-handler/debounce-key.ts
|
|
@@ -3566,7 +3727,7 @@ function createSlackThreadTsResolver(params) {
|
|
|
3566
3727
|
}
|
|
3567
3728
|
//#endregion
|
|
3568
3729
|
//#region extensions/slack/src/monitor/message-handler.ts
|
|
3569
|
-
const loadSlackMessagePipeline = createLazyRuntimeModule(() => import("./pipeline.runtime-
|
|
3730
|
+
const loadSlackMessagePipeline = createLazyRuntimeModule(() => import("./pipeline.runtime-5rRYZuX5.js"));
|
|
3570
3731
|
function createSlackDispatchCompletion() {
|
|
3571
3732
|
let resolve;
|
|
3572
3733
|
let reject;
|
|
@@ -4144,13 +4305,11 @@ function createSlackBoltApp(params) {
|
|
|
4144
4305
|
const socketModeReceiverOptions = {
|
|
4145
4306
|
appToken: params.appToken ?? "",
|
|
4146
4307
|
autoReconnectEnabled: true,
|
|
4147
|
-
clientPingTimeout:
|
|
4308
|
+
clientPingTimeout: OPENCLAW_SLACK_CLIENT_PING_TIMEOUT_MS,
|
|
4148
4309
|
logger: socketModeLogger,
|
|
4149
4310
|
installerOptions: { clientOptions: params.clientOptions },
|
|
4150
4311
|
...params.wrapReceiver ? { processEventErrorHandler: async () => false } : {}
|
|
4151
4312
|
};
|
|
4152
|
-
if (params.socketMode?.serverPingTimeout !== void 0) socketModeReceiverOptions.serverPingTimeout = params.socketMode.serverPingTimeout;
|
|
4153
|
-
if (params.socketMode?.pingPongLoggingEnabled !== void 0) socketModeReceiverOptions.pingPongLoggingEnabled = params.socketMode.pingPongLoggingEnabled;
|
|
4154
4313
|
let receiver;
|
|
4155
4314
|
if (params.slackMode === "socket") {
|
|
4156
4315
|
receiver = new params.interop.SocketModeReceiver(socketModeReceiverOptions);
|
|
@@ -4415,7 +4574,7 @@ const SLACK_COMMAND_ARG_CONFIRM_TEXT_MAX = 300;
|
|
|
4415
4574
|
const SLACK_HEADER_TEXT_MAX = 150;
|
|
4416
4575
|
const SLACK_COMMAND_ARG_ACTION_BLOCKS_MAX = 47;
|
|
4417
4576
|
const loadSlashCommandsRuntime = createLazyRuntimeModule(() => import("./slash-commands.runtime-BTTMlmwy.js"));
|
|
4418
|
-
const loadSlashDispatchRuntime = createLazyRuntimeModule(() => import("./slash-dispatch.runtime-
|
|
4577
|
+
const loadSlashDispatchRuntime = createLazyRuntimeModule(() => import("./slash-dispatch.runtime-lfeIsXTX.js"));
|
|
4419
4578
|
const loadSlackPluginCommandsRuntime = createLazyRuntimeModule(() => import("./slash-plugin-commands.runtime-Dosfcx3X.js"));
|
|
4420
4579
|
const loadSlashSkillCommandsRuntime = createLazyRuntimeModule(() => import("./slash-skill-commands.runtime-CD1J2ODY.js"));
|
|
4421
4580
|
function resolveSlackCommandMenuModelContext(params) {
|
|
@@ -4808,8 +4967,12 @@ async function registerSlackMonitorSlashCommands(params) {
|
|
|
4808
4967
|
agentId: menuRoute.agentId,
|
|
4809
4968
|
sessionKey: menuRoute.sessionKey
|
|
4810
4969
|
}) : {};
|
|
4811
|
-
const menuModelCatalog = commandDefinition.key === "think" && menuNeedsModelContext ? await
|
|
4970
|
+
const menuModelCatalog = commandDefinition.key === "think" && menuNeedsModelContext ? await loadPreparedModelCatalog({
|
|
4812
4971
|
config: cfg,
|
|
4972
|
+
...menuRoute ? {
|
|
4973
|
+
agentId: menuRoute.agentId,
|
|
4974
|
+
agentDir: resolveAgentDir(cfg, menuRoute.agentId)
|
|
4975
|
+
} : {},
|
|
4813
4976
|
readOnly: true
|
|
4814
4977
|
}) : void 0;
|
|
4815
4978
|
const menu = resolveCommandArgMenu({
|
|
@@ -4867,7 +5030,7 @@ async function registerSlackMonitorSlashCommands(params) {
|
|
|
4867
5030
|
sessionPrefix: slashCommand.sessionPrefix,
|
|
4868
5031
|
userId: command.user_id,
|
|
4869
5032
|
targetSessionKey: route.sessionKey,
|
|
4870
|
-
|
|
5033
|
+
sessionKeyCase: "lowercase"
|
|
4871
5034
|
});
|
|
4872
5035
|
const slashReplyTarget = !slashCommand.ephemeral && isRoomish ? `channel:${command.channel_id}` : `user:${command.user_id}`;
|
|
4873
5036
|
const ctxPayload = finalizeInboundContext({
|
|
@@ -4946,12 +5109,17 @@ async function registerSlackMonitorSlashCommands(params) {
|
|
|
4946
5109
|
});
|
|
4947
5110
|
};
|
|
4948
5111
|
const pendingSlashReplies = [];
|
|
5112
|
+
const shouldDeliverBlockImmediately = commandDefinition?.key === "login";
|
|
4949
5113
|
const { counts } = await dispatchReplyWithDispatcher({
|
|
4950
5114
|
ctx: ctxPayload,
|
|
4951
5115
|
cfg,
|
|
4952
5116
|
dispatcherOptions: {
|
|
4953
5117
|
...replyPipeline,
|
|
4954
|
-
deliver: async (payload) => {
|
|
5118
|
+
deliver: async (payload, info) => {
|
|
5119
|
+
if (info.kind === "block" && shouldDeliverBlockImmediately) {
|
|
5120
|
+
await deliverSlashPayloads([payload]);
|
|
5121
|
+
return;
|
|
5122
|
+
}
|
|
4955
5123
|
pendingSlashReplies.push(payload);
|
|
4956
5124
|
},
|
|
4957
5125
|
onError: (err, info) => {
|
|
@@ -5155,7 +5323,7 @@ async function getSlackBoltInterop() {
|
|
|
5155
5323
|
}
|
|
5156
5324
|
return slackBoltInterop;
|
|
5157
5325
|
}
|
|
5158
|
-
const loadSlackRelaySource = createLazyRuntimeModule(() => import("./relay-source-
|
|
5326
|
+
const loadSlackRelaySource = createLazyRuntimeModule(() => import("./relay-source-Df9EaiTF.js"));
|
|
5159
5327
|
const SLACK_WEBHOOK_MAX_BODY_BYTES = 1024 * 1024;
|
|
5160
5328
|
const SLACK_WEBHOOK_BODY_TIMEOUT_MS = 3e4;
|
|
5161
5329
|
function resolveStableSlackUserIdEntry(raw) {
|
|
@@ -5301,7 +5469,7 @@ async function monitorSlackProvider(opts = {}) {
|
|
|
5301
5469
|
log: (message) => runtime.log?.(warn(message))
|
|
5302
5470
|
});
|
|
5303
5471
|
const resolveToken = account.userToken || botToken;
|
|
5304
|
-
const useAccessGroups =
|
|
5472
|
+
const useAccessGroups = true;
|
|
5305
5473
|
const reactionMode = slackCfg.reactionNotifications ?? "own";
|
|
5306
5474
|
const reactionAllowlist = slackCfg.reactionAllowlist ?? [];
|
|
5307
5475
|
const replyToMode = slackCfg.replyToMode ?? "off";
|
|
@@ -5313,7 +5481,6 @@ async function monitorSlackProvider(opts = {}) {
|
|
|
5313
5481
|
const ackReactionScope = cfg.messages?.ackReactionScope ?? "group-mentions";
|
|
5314
5482
|
const typingReaction = slackCfg.typingReaction?.trim() ?? "";
|
|
5315
5483
|
const mediaMaxBytes = (opts.mediaMaxMb ?? slackCfg.mediaMaxMb ?? 20) * 1024 * 1024;
|
|
5316
|
-
const removeAckAfterReply = cfg.messages?.removeAckAfterReply ?? false;
|
|
5317
5484
|
const clientOptions = resolveSlackWebClientOptions();
|
|
5318
5485
|
const durableIngress = createSlackDurableIngress({
|
|
5319
5486
|
accountId: account.accountId,
|
|
@@ -5328,7 +5495,6 @@ async function monitorSlackProvider(opts = {}) {
|
|
|
5328
5495
|
signingSecret: slackMode === "http" ? signingSecret ?? void 0 : void 0,
|
|
5329
5496
|
slackWebhookPath,
|
|
5330
5497
|
clientOptions,
|
|
5331
|
-
...slackCfg.socketMode ? { socketMode: slackCfg.socketMode } : {},
|
|
5332
5498
|
wrapReceiver: durableIngress.wrapReceiver
|
|
5333
5499
|
});
|
|
5334
5500
|
const gracefulStop = async () => {
|
|
@@ -5435,8 +5601,7 @@ async function monitorSlackProvider(opts = {}) {
|
|
|
5435
5601
|
textLimit,
|
|
5436
5602
|
ackReactionScope,
|
|
5437
5603
|
typingReaction,
|
|
5438
|
-
mediaMaxBytes
|
|
5439
|
-
removeAckAfterReply
|
|
5604
|
+
mediaMaxBytes
|
|
5440
5605
|
});
|
|
5441
5606
|
const trackEvent = opts.setStatus ? () => {
|
|
5442
5607
|
opts.setStatus({
|