@vellumai/assistant 0.4.29 → 0.4.30
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/ARCHITECTURE.md +39 -37
- package/README.md +5 -6
- package/docs/runbook-trusted-contacts.md +79 -43
- package/package.json +1 -1
- package/scripts/ipc/check-swift-decoder-drift.ts +2 -3
- package/scripts/test.sh +1 -1
- package/src/__tests__/__snapshots__/ipc-snapshot.test.ts.snap +4 -37
- package/src/__tests__/actor-token-service.test.ts +4 -3
- package/src/__tests__/app-executors.test.ts +7 -17
- package/src/__tests__/assistant-feature-flags-integration.test.ts +18 -10
- package/src/__tests__/browser-skill-endstate.test.ts +10 -1
- package/src/__tests__/bundled-skill-retrieval-guard.test.ts +1 -0
- package/src/__tests__/channel-approval-routes.test.ts +44 -44
- package/src/__tests__/channel-approval.test.ts +8 -0
- package/src/__tests__/channel-approvals.test.ts +39 -1
- package/src/__tests__/channel-guardian.test.ts +15 -5
- package/src/__tests__/channel-reply-delivery.test.ts +31 -0
- package/src/__tests__/commit-message-enrichment-service.test.ts +4 -0
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +9 -0
- package/src/__tests__/gateway-only-guard.test.ts +1 -0
- package/src/__tests__/gemini-image-service.test.ts +2 -2
- package/src/__tests__/guardian-grant-minting.test.ts +6 -6
- package/src/__tests__/guardian-routing-invariants.test.ts +34 -11
- package/src/__tests__/guardian-verify-setup-skill-regression.test.ts +4 -6
- package/src/__tests__/inbound-invite-redemption.test.ts +1 -1
- package/src/__tests__/integrations-cli.test.ts +3 -27
- package/src/__tests__/intent-routing.test.ts +3 -0
- package/src/__tests__/invite-redemption-service.test.ts +1 -1
- package/src/__tests__/{ingress-routes-http.test.ts → invite-routes-http.test.ts} +40 -320
- package/src/__tests__/ipc-snapshot.test.ts +4 -31
- package/src/__tests__/nl-approval-parser.test.ts +305 -0
- package/src/__tests__/oauth-provider-profiles.test.ts +34 -0
- package/src/__tests__/provider-error-scenarios.test.ts +68 -0
- package/src/__tests__/relay-server.test.ts +1 -1
- package/src/__tests__/retry-after-extraction.test.ts +111 -0
- package/src/__tests__/script-proxy-profile-template-fallback.test.ts +127 -0
- package/src/__tests__/session-media-retry.test.ts +147 -0
- package/src/__tests__/skill-feature-flags-integration.test.ts +9 -5
- package/src/__tests__/skill-feature-flags.test.ts +18 -12
- package/src/__tests__/skill-load-feature-flag.test.ts +4 -3
- package/src/__tests__/slack-block-formatting.test.ts +100 -0
- package/src/__tests__/slack-inbound-verification.test.ts +346 -0
- package/src/__tests__/slack-reaction-approvals.test.ts +77 -0
- package/src/__tests__/slack-skill.test.ts +3 -2
- package/src/__tests__/starter-task-flow.test.ts +0 -1
- package/src/__tests__/trusted-contact-verification.test.ts +3 -1
- package/src/__tests__/voice-invite-redemption.test.ts +1 -1
- package/src/amazon/client.ts +7 -24
- package/src/calls/relay-server.ts +39 -11
- package/src/channels/config.ts +1 -1
- package/src/cli/integrations.ts +10 -66
- package/src/config/bundled-skills/app-builder/SKILL.md +193 -1500
- package/src/config/bundled-skills/app-builder/TOOLS.json +70 -18
- package/src/config/bundled-skills/browser/TOOLS.json +59 -2
- package/src/config/bundled-skills/chatgpt-import/TOOLS.json +4 -0
- package/src/config/bundled-skills/computer-use/TOOLS.json +50 -2
- package/src/config/bundled-skills/contacts/SKILL.md +42 -35
- package/src/config/bundled-skills/contacts/TOOLS.json +22 -2
- package/src/config/bundled-skills/contacts/tools/contact-merge.ts +38 -58
- package/src/config/bundled-skills/contacts/tools/contact-search.ts +11 -31
- package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +19 -37
- package/src/config/bundled-skills/document/TOOLS.json +8 -0
- package/src/config/bundled-skills/email-setup/SKILL.md +10 -7
- package/src/config/bundled-skills/followups/TOOLS.json +12 -0
- package/src/config/bundled-skills/google-calendar/TOOLS.json +124 -26
- package/src/config/bundled-skills/guardian-verify-setup/SKILL.md +54 -21
- package/src/config/bundled-skills/image-studio/TOOLS.json +12 -2
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +14 -8
- package/src/config/bundled-skills/knowledge-graph/TOOLS.json +13 -3
- package/src/config/bundled-skills/media-processing/SKILL.md +1 -1
- package/src/config/bundled-skills/media-processing/TOOLS.json +28 -0
- package/src/config/bundled-skills/media-processing/tools/generate-clip.ts +26 -6
- package/src/config/bundled-skills/messaging/TOOLS.json +228 -182
- package/src/config/bundled-skills/notifications/SKILL.md +3 -2
- package/src/config/bundled-skills/notifications/TOOLS.json +7 -13
- package/src/config/bundled-skills/phone-calls/TOOLS.json +13 -1
- package/src/config/bundled-skills/playbooks/TOOLS.json +16 -0
- package/src/config/bundled-skills/reminder/TOOLS.json +15 -2
- package/src/config/bundled-skills/schedule/SKILL.md +33 -15
- package/src/config/bundled-skills/schedule/TOOLS.json +17 -1
- package/src/config/bundled-skills/slack/SKILL.md +30 -1
- package/src/config/bundled-skills/slack/TOOLS.json +89 -2
- package/src/config/bundled-skills/slack/tools/slack-channel-permissions.ts +146 -0
- package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +120 -0
- package/src/config/bundled-skills/slack-app-setup/SKILL.md +200 -0
- package/src/config/bundled-skills/subagent/TOOLS.json +22 -2
- package/src/config/bundled-skills/tasks/TOOLS.json +86 -14
- package/src/config/bundled-skills/transcribe/TOOLS.json +4 -0
- package/src/config/bundled-skills/watcher/TOOLS.json +20 -0
- package/src/config/bundled-skills/weather/TOOLS.json +4 -0
- package/src/config/bundled-tool-registry.ts +2 -0
- package/src/config/channel-permission-profiles.ts +155 -0
- package/src/config/env.ts +4 -1
- package/src/contacts/contact-store.ts +195 -4
- package/src/contacts/types.ts +26 -0
- package/src/daemon/assistant-attachments.ts +23 -3
- package/src/daemon/guardian-verification-intent.ts +7 -4
- package/src/daemon/handlers/apps.ts +1 -2
- package/src/daemon/handlers/config-inbox.ts +16 -134
- package/src/daemon/handlers/guardian-actions.ts +20 -87
- package/src/daemon/handlers/sessions.ts +0 -1
- package/src/daemon/ipc-contract/apps.ts +0 -1
- package/src/daemon/ipc-contract/inbox.ts +7 -66
- package/src/daemon/ipc-contract/sessions.ts +1 -0
- package/src/daemon/ipc-contract/surfaces.ts +0 -1
- package/src/daemon/ipc-contract-inventory.json +2 -4
- package/src/daemon/lifecycle.ts +14 -2
- package/src/daemon/session-agent-loop-handlers.ts +9 -0
- package/src/daemon/session-agent-loop.ts +1 -0
- package/src/daemon/session-attachments.ts +5 -1
- package/src/daemon/session-error.ts +18 -0
- package/src/daemon/session-lifecycle.ts +4 -5
- package/src/daemon/session-media-retry.ts +15 -1
- package/src/daemon/session-surfaces.ts +0 -1
- package/src/daemon/session-tool-setup.ts +7 -4
- package/src/events/domain-events.ts +2 -1
- package/src/home-base/prebuilt/seed.ts +0 -1
- package/src/influencer/client.ts +7 -24
- package/src/media/gemini-image-service.ts +48 -3
- package/src/memory/app-store.ts +0 -4
- package/src/memory/conversation-attention-store.ts +3 -1
- package/src/memory/db-init.ts +4 -0
- package/src/memory/migrations/133-assistant-contact-metadata.ts +21 -0
- package/src/memory/migrations/index.ts +1 -0
- package/src/memory/schema.ts +12 -0
- package/src/memory/slack-thread-store.ts +187 -0
- package/src/messaging/providers/slack/client.ts +84 -26
- package/src/messaging/providers/slack/types.ts +4 -0
- package/src/notifications/adapters/slack.ts +90 -0
- package/src/notifications/destination-resolver.ts +42 -1
- package/src/notifications/emit-signal.ts +17 -1
- package/src/oauth/provider-profiles.ts +22 -0
- package/src/providers/anthropic/client.ts +3 -0
- package/src/providers/openai/client.ts +3 -0
- package/src/providers/retry.ts +9 -1
- package/src/runtime/actor-trust-resolver.ts +8 -0
- package/src/runtime/auth/require-bound-guardian.ts +44 -0
- package/src/runtime/auth/route-policy.ts +4 -8
- package/src/runtime/channel-approval-types.ts +18 -0
- package/src/runtime/channel-approvals.ts +8 -0
- package/src/runtime/channel-invite-transport.ts +1 -1
- package/src/runtime/channel-reply-delivery.ts +62 -3
- package/src/runtime/gateway-client.ts +36 -2
- package/src/runtime/gateway-internal-client.ts +86 -0
- package/src/runtime/guardian-action-service.ts +127 -0
- package/src/runtime/guardian-verification-templates.ts +16 -1
- package/src/runtime/http-server.ts +20 -49
- package/src/runtime/invite-redemption-service.ts +1 -1
- package/src/runtime/{ingress-service.ts → invite-service.ts} +5 -157
- package/src/runtime/nl-approval-parser.ts +138 -0
- package/src/runtime/routes/approval-routes.ts +1 -40
- package/src/runtime/routes/channel-route-shared.ts +35 -1
- package/src/runtime/routes/contact-routes.ts +196 -28
- package/src/runtime/routes/guardian-action-routes.ts +19 -111
- package/src/runtime/routes/guardian-approval-interception.ts +76 -0
- package/src/runtime/routes/inbound-message-handler.ts +40 -12
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +222 -0
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +108 -0
- package/src/runtime/routes/{ingress-routes.ts → invite-routes.ts} +10 -110
- package/src/runtime/slack-block-formatting.ts +176 -0
- package/src/schedule/scheduler.ts +11 -2
- package/src/tools/apps/executors.ts +16 -15
- package/src/tools/calls/call-end.ts +1 -1
- package/src/tools/computer-use/definitions.ts +16 -0
- package/src/tools/credentials/vault.ts +86 -2
- package/src/tools/network/script-proxy/session-manager.ts +28 -3
- package/src/tools/permission-checker.ts +18 -0
- package/src/tools/terminal/shell.ts +15 -5
- package/src/tools/tool-approval-handler.ts +48 -4
- package/src/tools/types.ts +38 -1
- package/src/util/errors.ts +5 -1
- package/src/util/retry.ts +21 -0
- package/src/watcher/providers/slack.ts +33 -3
- /package/src/memory/{ingress-invite-store.ts → invite-store.ts} +0 -0
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { consumeGrantForInvocation } from "../approvals/approval-primitive.js";
|
|
2
|
+
import { isToolAllowedInChannel } from "../config/channel-permission-profiles.js";
|
|
2
3
|
import {
|
|
3
4
|
getCanonicalGuardianRequest,
|
|
4
5
|
updateCanonicalGuardianRequest,
|
|
5
6
|
} from "../memory/canonical-guardian-store.js";
|
|
7
|
+
import { isUntrustedTrustClass } from "../runtime/actor-trust-resolver.js";
|
|
6
8
|
import { DAEMON_INTERNAL_ASSISTANT_ID } from "../runtime/assistant-scope.js";
|
|
7
9
|
import { createOrReuseToolGrantRequest } from "../runtime/tool-grant-request-helper.js";
|
|
8
10
|
import { computeToolApprovalDigest } from "../security/tool-approval-digest.js";
|
|
@@ -129,10 +131,6 @@ export async function waitForInlineGrant(
|
|
|
129
131
|
return { outcome: "timeout", requestId: escalationRequestId };
|
|
130
132
|
}
|
|
131
133
|
|
|
132
|
-
function isUntrustedTrustClass(role: ToolContext["trustClass"]): boolean {
|
|
133
|
-
return role === "trusted_contact" || role === "unknown";
|
|
134
|
-
}
|
|
135
|
-
|
|
136
134
|
function requiresGuardianApprovalForActor(
|
|
137
135
|
toolName: string,
|
|
138
136
|
input: Record<string, unknown>,
|
|
@@ -365,6 +363,52 @@ export class ToolApprovalHandler {
|
|
|
365
363
|
return { allowed: false, result: { content: msg, isError: true } };
|
|
366
364
|
}
|
|
367
365
|
|
|
366
|
+
// Enforce channel-scoped permission profiles (deterministic gate).
|
|
367
|
+
// When the session originates from a Slack channel with a configured
|
|
368
|
+
// permission profile, blocked tools and category restrictions are
|
|
369
|
+
// enforced here rather than relying on model compliance with hints.
|
|
370
|
+
if (
|
|
371
|
+
context.executionChannel === "slack" &&
|
|
372
|
+
context.channelPermissionChannelId
|
|
373
|
+
) {
|
|
374
|
+
if (
|
|
375
|
+
!isToolAllowedInChannel(
|
|
376
|
+
context.channelPermissionChannelId,
|
|
377
|
+
name,
|
|
378
|
+
tool.category,
|
|
379
|
+
)
|
|
380
|
+
) {
|
|
381
|
+
const msg = `Tool "${name}" is not allowed in this channel per channel permission policy.`;
|
|
382
|
+
log.warn(
|
|
383
|
+
{
|
|
384
|
+
toolName: name,
|
|
385
|
+
channelId: context.channelPermissionChannelId,
|
|
386
|
+
category: tool.category,
|
|
387
|
+
sessionId: context.sessionId,
|
|
388
|
+
conversationId: context.conversationId,
|
|
389
|
+
reason: "channel_permission_policy",
|
|
390
|
+
},
|
|
391
|
+
"Channel permission policy blocked tool invocation",
|
|
392
|
+
);
|
|
393
|
+
const durationMs = Date.now() - startTime;
|
|
394
|
+
emitLifecycleEvent({
|
|
395
|
+
type: "permission_denied",
|
|
396
|
+
toolName: name,
|
|
397
|
+
executionTarget,
|
|
398
|
+
input,
|
|
399
|
+
workingDir: context.workingDir,
|
|
400
|
+
sessionId: context.sessionId,
|
|
401
|
+
conversationId: context.conversationId,
|
|
402
|
+
requestId: context.requestId,
|
|
403
|
+
riskLevel,
|
|
404
|
+
decision: "deny",
|
|
405
|
+
reason: msg,
|
|
406
|
+
durationMs,
|
|
407
|
+
});
|
|
408
|
+
return { allowed: false, result: { content: msg, isError: true } };
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
|
|
368
412
|
// All policy gates passed. Now consume the scoped grant if one is
|
|
369
413
|
// required. Deferring consumption to this point ensures a downstream
|
|
370
414
|
// rejection (allowedToolNames, task-run preflight, registry lookup)
|
package/src/tools/types.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { ProxyApprovalCallback } from "../outbound-proxy/index.js";
|
|
2
1
|
import type { SecretPromptResult } from "../permissions/secret-prompter.js";
|
|
3
2
|
import type {
|
|
4
3
|
AllowlistOption,
|
|
@@ -166,6 +165,8 @@ export interface ToolContext {
|
|
|
166
165
|
requesterExternalUserId?: string;
|
|
167
166
|
/** Chat ID of the requester (non-guardian actor). Used for tool grant request escalation notifications. */
|
|
168
167
|
requesterChatId?: string;
|
|
168
|
+
/** Slack channel ID for channel-scoped permission enforcement. When set, tools are checked against the channel's permission profile. */
|
|
169
|
+
channelPermissionChannelId?: string;
|
|
169
170
|
}
|
|
170
171
|
|
|
171
172
|
export interface DiffInfo {
|
|
@@ -200,6 +201,42 @@ export interface ToolExecutionResult {
|
|
|
200
201
|
yieldToUser?: boolean;
|
|
201
202
|
}
|
|
202
203
|
|
|
204
|
+
// ---------------------------------------------------------------------------
|
|
205
|
+
// Proxy approval types — local definitions for the outbound-proxy contract.
|
|
206
|
+
// The proxy service owns the canonical shapes; these are the assistant's
|
|
207
|
+
// minimal view of the approval callback interface.
|
|
208
|
+
// ---------------------------------------------------------------------------
|
|
209
|
+
|
|
210
|
+
/** Approval request from the outbound proxy when a policy decision requires user confirmation. */
|
|
211
|
+
export interface ProxyApprovalRequest {
|
|
212
|
+
decision: {
|
|
213
|
+
kind: "ask_missing_credential" | "ask_unauthenticated";
|
|
214
|
+
target: {
|
|
215
|
+
hostname: string;
|
|
216
|
+
port: number | null;
|
|
217
|
+
path: string;
|
|
218
|
+
scheme: "http" | "https";
|
|
219
|
+
};
|
|
220
|
+
/** Present when kind is "ask_missing_credential". */
|
|
221
|
+
matchingPatterns?: string[];
|
|
222
|
+
};
|
|
223
|
+
sessionId: string;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/** Callback for proxy policy decisions requiring user confirmation. Returns true if approved. */
|
|
227
|
+
export type ProxyApprovalCallback = (
|
|
228
|
+
request: ProxyApprovalRequest,
|
|
229
|
+
) => Promise<boolean>;
|
|
230
|
+
|
|
231
|
+
/** Env vars a proxy session injects into child processes. */
|
|
232
|
+
export interface ProxyEnvVars {
|
|
233
|
+
HTTP_PROXY: string;
|
|
234
|
+
HTTPS_PROXY: string;
|
|
235
|
+
NO_PROXY: string;
|
|
236
|
+
NODE_EXTRA_CA_CERTS?: string;
|
|
237
|
+
SSL_CERT_FILE?: string;
|
|
238
|
+
}
|
|
239
|
+
|
|
203
240
|
export interface Tool {
|
|
204
241
|
name: string;
|
|
205
242
|
description: string;
|
package/src/util/errors.ts
CHANGED
|
@@ -109,14 +109,18 @@ export class AssistantError extends VellumError {
|
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
export class ProviderError extends AssistantError {
|
|
112
|
+
/** Delay (in ms) suggested by the server's Retry-After header, if present. */
|
|
113
|
+
public readonly retryAfterMs?: number;
|
|
114
|
+
|
|
112
115
|
constructor(
|
|
113
116
|
message: string,
|
|
114
117
|
public readonly provider: string,
|
|
115
118
|
public readonly statusCode?: number,
|
|
116
|
-
options?: { cause?: unknown },
|
|
119
|
+
options?: { cause?: unknown; retryAfterMs?: number },
|
|
117
120
|
) {
|
|
118
121
|
super(message, ErrorCode.PROVIDER_ERROR, options);
|
|
119
122
|
this.name = "ProviderError";
|
|
123
|
+
this.retryAfterMs = options?.retryAfterMs;
|
|
120
124
|
}
|
|
121
125
|
}
|
|
122
126
|
|
package/src/util/retry.ts
CHANGED
|
@@ -125,4 +125,25 @@ export function abortableSleep(
|
|
|
125
125
|
});
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
+
/**
|
|
129
|
+
* Extract retry-after milliseconds from an SDK error's headers object.
|
|
130
|
+
* Handles both Map-like (OpenAI: Headers with .get()) and plain-object
|
|
131
|
+
* (Anthropic: Record<string, string>) header shapes.
|
|
132
|
+
*/
|
|
133
|
+
export function extractRetryAfterMs(headers: unknown): number | undefined {
|
|
134
|
+
if (!headers) return undefined;
|
|
135
|
+
|
|
136
|
+
let raw: string | null | undefined;
|
|
137
|
+
if (typeof (headers as { get?: unknown }).get === "function") {
|
|
138
|
+
raw = (headers as { get(k: string): string | null }).get("retry-after");
|
|
139
|
+
} else if (typeof headers === "object") {
|
|
140
|
+
raw = (headers as Record<string, string>)["retry-after"];
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (typeof raw === "string") {
|
|
144
|
+
return parseRetryAfterMs(raw);
|
|
145
|
+
}
|
|
146
|
+
return undefined;
|
|
147
|
+
}
|
|
148
|
+
|
|
128
149
|
export { DEFAULT_BASE_DELAY_MS, DEFAULT_MAX_RETRIES };
|
|
@@ -25,6 +25,20 @@ const log = getLogger("watcher:slack");
|
|
|
25
25
|
* When `channels` is specified, those channels are monitored for ALL messages
|
|
26
26
|
* (not just mentions). When omitted or empty, the legacy behavior applies:
|
|
27
27
|
* @mentions in the top 20 member channels.
|
|
28
|
+
*
|
|
29
|
+
* ## Socket Mode Redundancy
|
|
30
|
+
*
|
|
31
|
+
* When the gateway is running with Socket Mode enabled, it already receives
|
|
32
|
+
* real-time events for @mentions, DMs, and active thread replies. The watcher's
|
|
33
|
+
* polling is therefore redundant for those event types. Set
|
|
34
|
+
* `socketModeActive: true` to skip polling for DMs and @mentions that Socket
|
|
35
|
+
* Mode already covers. The watcher will still poll for configured `channels`
|
|
36
|
+
* (all-message monitoring) since Socket Mode only forwards messages where the
|
|
37
|
+
* bot is mentioned or in active threads.
|
|
38
|
+
*
|
|
39
|
+
* @deprecated The polling-based watcher for DMs and @mentions is superseded by
|
|
40
|
+
* Socket Mode in the gateway. Once Socket Mode is confirmed stable, the DM and
|
|
41
|
+
* mention-polling code paths can be removed entirely.
|
|
28
42
|
*/
|
|
29
43
|
interface SlackWatcherConfig {
|
|
30
44
|
/** Channel IDs to watch for all messages (e.g. ["C01234ABCDE"]).
|
|
@@ -32,6 +46,12 @@ interface SlackWatcherConfig {
|
|
|
32
46
|
channels?: string[];
|
|
33
47
|
/** When true, also monitor DMs and group DMs (default: true). */
|
|
34
48
|
includeDMs?: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* When true, skip polling for DMs and @mentions since the gateway's Socket
|
|
51
|
+
* Mode connection already delivers those events in real-time. The watcher
|
|
52
|
+
* will still poll explicitly configured `channels` for all-message monitoring.
|
|
53
|
+
*/
|
|
54
|
+
socketModeActive?: boolean;
|
|
35
55
|
}
|
|
36
56
|
|
|
37
57
|
function messageToItem(
|
|
@@ -142,6 +162,13 @@ export const slackProvider: WatcherProvider = {
|
|
|
142
162
|
? slackConfig.includeDMs
|
|
143
163
|
: true;
|
|
144
164
|
|
|
165
|
+
const socketModeActive = slackConfig.socketModeActive === true;
|
|
166
|
+
if (socketModeActive) {
|
|
167
|
+
log.info(
|
|
168
|
+
"Socket Mode active — skipping DM and @mention polling (handled by gateway)",
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
|
|
145
172
|
const authResp = await slack.authTest(token);
|
|
146
173
|
const userId = authResp.user_id;
|
|
147
174
|
|
|
@@ -149,7 +176,8 @@ export const slackProvider: WatcherProvider = {
|
|
|
149
176
|
let latestTs = watermark;
|
|
150
177
|
|
|
151
178
|
// ── DM / Group DM polling ──────────────────────────────────────
|
|
152
|
-
|
|
179
|
+
// Skip when Socket Mode is active — the gateway already delivers DM events in real-time.
|
|
180
|
+
if (includeDMs && !socketModeActive) {
|
|
153
181
|
const convResp = await slack.listConversations(
|
|
154
182
|
token,
|
|
155
183
|
"im,mpim",
|
|
@@ -204,8 +232,10 @@ export const slackProvider: WatcherProvider = {
|
|
|
204
232
|
);
|
|
205
233
|
}
|
|
206
234
|
}
|
|
207
|
-
} else {
|
|
208
|
-
// Legacy behavior: check top 20 member channels for @mentions only
|
|
235
|
+
} else if (!socketModeActive) {
|
|
236
|
+
// Legacy behavior: check top 20 member channels for @mentions only.
|
|
237
|
+
// Skipped when Socket Mode is active — the gateway already delivers
|
|
238
|
+
// app_mention events in real-time.
|
|
209
239
|
const memberConvResp = await slack.listConversations(
|
|
210
240
|
token,
|
|
211
241
|
"public_channel,private_channel",
|
|
File without changes
|