@nordbyte/nordrelay 0.8.0 → 0.8.2
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/.env.example +9 -0
- package/README.md +81 -1197
- package/dist/{access-control.js → access/access-control.js} +1 -1
- package/dist/{audit-log.js → access/audit-log.js} +2 -2
- package/dist/{session-locks.js → access/session-locks.js} +1 -1
- package/dist/{user-management.js → access/user-management.js} +1 -1
- package/dist/{claude-code-cli.js → agents/claude-code/claude-code-cli.js} +2 -2
- package/dist/{claude-code-session.js → agents/claude-code/claude-code-session.js} +1 -1
- package/dist/{codex-cli.js → agents/codex/codex-cli.js} +14 -5
- package/dist/{codex-session.js → agents/codex/codex-session.js} +2 -4
- package/dist/{hermes-cli.js → agents/hermes/hermes-cli.js} +2 -2
- package/dist/{hermes-launch.js → agents/hermes/hermes-launch.js} +1 -1
- package/dist/{hermes-session.js → agents/hermes/hermes-session.js} +1 -1
- package/dist/{openclaw-cli.js → agents/openclaw/openclaw-cli.js} +2 -2
- package/dist/{openclaw-launch.js → agents/openclaw/openclaw-launch.js} +1 -1
- package/dist/{openclaw-session.js → agents/openclaw/openclaw-session.js} +1 -1
- package/dist/{pi-cli.js → agents/pi/pi-cli.js} +2 -2
- package/dist/{pi-launch.js → agents/pi/pi-launch.js} +1 -1
- package/dist/{pi-session.js → agents/pi/pi-session.js} +1 -1
- package/dist/{adapter-conformance.js → agents/shared/adapter-conformance.js} +2 -2
- package/dist/{agent-activity.js → agents/shared/agent-activity.js} +5 -5
- package/dist/agents/shared/agent-auth-commands.js +30 -0
- package/dist/{agent-factory.js → agents/shared/agent-factory.js} +5 -5
- package/dist/{agent-feature-matrix.js → agents/shared/agent-feature-matrix.js} +2 -2
- package/dist/{agent-updates.js → agents/shared/agent-updates.js} +7 -7
- package/dist/{discord-artifacts.js → channels/discord/discord-artifacts.js} +4 -4
- package/dist/{discord-bot.js → channels/discord/discord-bot.js} +164 -424
- package/dist/{discord-channel-runtime.js → channels/discord/discord-channel-runtime.js} +2 -2
- package/dist/{discord-command-surface.js → channels/discord/discord-command-surface.js} +3 -3
- package/dist/{bot-rendering.js → channels/shared/bot-rendering.js} +6 -6
- package/dist/{channel-actions.js → channels/shared/channel-actions.js} +4 -4
- package/dist/channels/shared/channel-bridge-controller.js +69 -0
- package/dist/channels/shared/channel-cli-artifacts.js +51 -0
- package/dist/{channel-command-service.js → channels/shared/channel-command-service.js} +51 -28
- package/dist/channels/shared/channel-external-mirror-controller.js +193 -0
- package/dist/channels/shared/channel-external-monitor.js +52 -0
- package/dist/{channel-mirror-registry.js → channels/shared/channel-mirror-registry.js} +14 -6
- package/dist/{channel-peer-prompt.js → channels/shared/channel-peer-prompt.js} +3 -3
- package/dist/{channel-turn-service.js → channels/shared/channel-turn-service.js} +2 -2
- package/dist/{context-key.js → channels/shared/context-key.js} +1 -1
- package/dist/{session-format.js → channels/shared/session-format.js} +2 -2
- package/dist/{slack-artifacts.js → channels/slack/slack-artifacts.js} +4 -4
- package/dist/{slack-bot.js → channels/slack/slack-bot.js} +159 -294
- package/dist/{slack-channel-runtime.js → channels/slack/slack-channel-runtime.js} +2 -2
- package/dist/{slack-command-surface.js → channels/slack/slack-command-surface.js} +2 -2
- package/dist/{slack-diagnostics.js → channels/slack/slack-diagnostics.js} +2 -2
- package/dist/{bot-ui.js → channels/telegram/bot-ui.js} +1 -1
- package/dist/{bot.js → channels/telegram/bot.js} +178 -427
- package/dist/{telegram-access-commands.js → channels/telegram/telegram-access-commands.js} +3 -3
- package/dist/{telegram-access-middleware.js → channels/telegram/telegram-access-middleware.js} +4 -4
- package/dist/{telegram-agent-commands.js → channels/telegram/telegram-agent-commands.js} +9 -9
- package/dist/{telegram-artifact-commands.js → channels/telegram/telegram-artifact-commands.js} +4 -4
- package/dist/{telegram-channel-runtime.js → channels/telegram/telegram-channel-runtime.js} +2 -2
- package/dist/{telegram-command-menu.js → channels/telegram/telegram-command-menu.js} +1 -1
- package/dist/{telegram-diagnostics-command.js → channels/telegram/telegram-diagnostics-command.js} +7 -7
- package/dist/{telegram-general-commands.js → channels/telegram/telegram-general-commands.js} +4 -4
- package/dist/{telegram-operational-commands.js → channels/telegram/telegram-operational-commands.js} +5 -5
- package/dist/{telegram-output.js → channels/telegram/telegram-output.js} +2 -2
- package/dist/{telegram-preference-commands.js → channels/telegram/telegram-preference-commands.js} +3 -3
- package/dist/{telegram-queue-commands.js → channels/telegram/telegram-queue-commands.js} +6 -6
- package/dist/{telegram-support-command.js → channels/telegram/telegram-support-command.js} +4 -4
- package/dist/{telegram-update-commands.js → channels/telegram/telegram-update-commands.js} +5 -5
- package/dist/{config-metadata.js → core/config-metadata.js} +8 -0
- package/dist/{config.js → core/config.js} +11 -3
- package/dist/index.js +27 -23
- package/dist/{peer-client.js → peers/peer-client.js} +57 -1
- package/dist/peers/peer-discovery-jobs.js +206 -0
- package/dist/peers/peer-discovery.js +223 -0
- package/dist/peers/peer-health-monitor.js +49 -0
- package/dist/{peer-identity.js → peers/peer-identity.js} +50 -1
- package/dist/{peer-runtime-service.js → peers/peer-runtime-service.js} +29 -7
- package/dist/{peer-server.js → peers/peer-server.js} +23 -6
- package/dist/{peer-store.js → peers/peer-store.js} +84 -11
- package/dist/{peer-types.js → peers/peer-types.js} +9 -0
- package/dist/peers/peer-web-proxy-contract.js +127 -0
- package/dist/{metrics.js → runtime/metrics.js} +5 -3
- package/dist/{relay-artifact-service.js → runtime/relay-artifact-service.js} +1 -1
- package/dist/runtime/relay-auth-service.js +63 -0
- package/dist/runtime/relay-dashboard-service.js +139 -0
- package/dist/{relay-external-activity-monitor.js → runtime/relay-external-activity-monitor.js} +140 -53
- package/dist/runtime/relay-runtime-active-sessions.js +387 -0
- package/dist/runtime/relay-runtime-dashboard.js +201 -0
- package/dist/runtime/relay-runtime-prompt-queue-artifacts.js +307 -0
- package/dist/runtime/relay-runtime-sessions.js +623 -0
- package/dist/runtime/relay-runtime-types.js +1 -0
- package/dist/runtime/relay-runtime-updates-jobs.js +360 -0
- package/dist/runtime/relay-runtime.js +451 -0
- package/dist/runtime/runtime-cache.js +117 -0
- package/dist/{session-registry.js → state/session-registry.js} +3 -3
- package/dist/{operations.js → support/operations.js} +7 -7
- package/dist/{support-bundle.js → support/support-bundle.js} +1 -1
- package/dist/{web-api-contract.js → web/web-api-contract.js} +17 -3
- package/dist/web/web-api-types.js +1 -0
- package/dist/{web-dashboard-access-routes.js → web/web-dashboard-access-routes.js} +2 -2
- package/dist/{web-dashboard-assets.js → web/web-dashboard-assets.js} +24 -2
- package/dist/{web-dashboard-http.js → web/web-dashboard-http.js} +41 -5
- package/dist/{web-dashboard-pages.js → web/web-dashboard-pages.js} +37 -10
- package/dist/{web-dashboard-peer-routes.js → web/web-dashboard-peer-routes.js} +102 -7
- package/dist/web/web-dashboard-security.js +14 -0
- package/dist/{web-dashboard-session-routes.js → web/web-dashboard-session-routes.js} +12 -1
- package/dist/{web-dashboard.js → web/web-dashboard.js} +132 -48
- package/dist/web/web-performance.js +60 -0
- package/dist/web/web-rate-limit.js +19 -0
- package/dist/{web-state.js → web/web-state.js} +74 -5
- package/dist/webui-assets/dashboard.css +171 -10
- package/dist/webui-assets/dashboard.js +515 -48
- package/dist/webui-assets/favicon.ico +0 -0
- package/dist/webui-assets/favicon.png +0 -0
- package/dist/webui-assets/logo.png +0 -0
- package/package.json +4 -3
- package/plugins/nordrelay/scripts/nordrelay.mjs +17 -5
- package/{launchd/start.sh → scripts/launchd-start.sh} +1 -1
- package/dist/relay-runtime.js +0 -1916
- package/dist/runtime-cache.js +0 -57
- /package/dist/{user-management-crypto.js → access/user-management-crypto.js} +0 -0
- /package/dist/{user-management-normalize.js → access/user-management-normalize.js} +0 -0
- /package/dist/{user-management-types.js → access/user-management-types.js} +0 -0
- /package/dist/{claude-code-auth.js → agents/claude-code/claude-code-auth.js} +0 -0
- /package/dist/{claude-code-launch.js → agents/claude-code/claude-code-launch.js} +0 -0
- /package/dist/{claude-code-state.js → agents/claude-code/claude-code-state.js} +0 -0
- /package/dist/{codex-auth.js → agents/codex/codex-auth.js} +0 -0
- /package/dist/{codex-config.js → agents/codex/codex-config.js} +0 -0
- /package/dist/{codex-launch.js → agents/codex/codex-launch.js} +0 -0
- /package/dist/{codex-state.js → agents/codex/codex-state.js} +0 -0
- /package/dist/{hermes-api.js → agents/hermes/hermes-api.js} +0 -0
- /package/dist/{hermes-auth.js → agents/hermes/hermes-auth.js} +0 -0
- /package/dist/{hermes-state.js → agents/hermes/hermes-state.js} +0 -0
- /package/dist/{openclaw-auth.js → agents/openclaw/openclaw-auth.js} +0 -0
- /package/dist/{openclaw-gateway.js → agents/openclaw/openclaw-gateway.js} +0 -0
- /package/dist/{openclaw-state.js → agents/openclaw/openclaw-state.js} +0 -0
- /package/dist/{pi-auth.js → agents/pi/pi-auth.js} +0 -0
- /package/dist/{pi-rpc.js → agents/pi/pi-rpc.js} +0 -0
- /package/dist/{pi-state.js → agents/pi/pi-state.js} +0 -0
- /package/dist/{agent-adapter.js → agents/shared/agent-adapter.js} +0 -0
- /package/dist/{agent.js → agents/shared/agent.js} +0 -0
- /package/dist/{artifacts.js → artifacts/artifacts.js} +0 -0
- /package/dist/{attachments.js → artifacts/attachments.js} +0 -0
- /package/dist/{voice.js → artifacts/voice.js} +0 -0
- /package/dist/{discord-rate-limit.js → channels/discord/discord-rate-limit.js} +0 -0
- /package/dist/{channel-adapter.js → channels/shared/channel-adapter.js} +0 -0
- /package/dist/{relay-runtime-types.js → channels/shared/channel-bridge-state.js} +0 -0
- /package/dist/{channel-command-catalog.js → channels/shared/channel-command-catalog.js} +0 -0
- /package/dist/{channel-command-core.js → channels/shared/channel-command-core.js} +0 -0
- /package/dist/{channel-prompt-engine.js → channels/shared/channel-prompt-engine.js} +0 -0
- /package/dist/{channel-runtime.js → channels/shared/channel-runtime.js} +0 -0
- /package/dist/{channel-turn-lifecycle.js → channels/shared/channel-turn-lifecycle.js} +0 -0
- /package/dist/{slack-rate-limit.js → channels/slack/slack-rate-limit.js} +0 -0
- /package/dist/{telegram-command-types.js → channels/telegram/telegram-command-types.js} +0 -0
- /package/dist/{telegram-rate-limit.js → channels/telegram/telegram-rate-limit.js} +0 -0
- /package/dist/{activity-events.js → core/activity-events.js} +0 -0
- /package/dist/{error-messages.js → core/error-messages.js} +0 -0
- /package/dist/{format.js → core/format.js} +0 -0
- /package/dist/{logger.js → core/logger.js} +0 -0
- /package/dist/{redaction.js → core/redaction.js} +0 -0
- /package/dist/{settings-service.js → core/settings-service.js} +0 -0
- /package/dist/{settings-wizard-test.js → core/settings-wizard-test.js} +0 -0
- /package/dist/{workspace-policy.js → core/workspace-policy.js} +0 -0
- /package/dist/{peer-auth.js → peers/peer-auth.js} +0 -0
- /package/dist/{peer-context.js → peers/peer-context.js} +0 -0
- /package/dist/{peer-readiness.js → peers/peer-readiness.js} +0 -0
- /package/dist/{relay-queue-service.js → runtime/relay-queue-service.js} +0 -0
- /package/dist/{web-api-types.js → runtime/relay-runtime-delegate.js} +0 -0
- /package/dist/{relay-runtime-helpers.js → runtime/relay-runtime-helpers.js} +0 -0
- /package/dist/{remote-prompt.js → runtime/remote-prompt.js} +0 -0
- /package/dist/{bot-preferences.js → state/bot-preferences.js} +0 -0
- /package/dist/{job-store.js → state/job-store.js} +0 -0
- /package/dist/{persistence.js → state/persistence.js} +0 -0
- /package/dist/{prompt-store.js → state/prompt-store.js} +0 -0
- /package/dist/{state-backend.js → state/state-backend.js} +0 -0
- /package/dist/{zip-writer.js → support/zip-writer.js} +0 -0
- /package/dist/{web-dashboard-artifact-routes.js → web/web-dashboard-artifact-routes.js} +0 -0
- /package/dist/{web-dashboard-runtime-routes.js → web/web-dashboard-runtime-routes.js} +0 -0
- /package/dist/{web-dashboard-ui.js → web/web-dashboard-ui.js} +0 -0
|
@@ -1,47 +1,48 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { App } from "@slack/bolt";
|
|
3
|
-
import { ADMIN_GROUP_ID } from "
|
|
4
|
-
import { agentLabel, agentReasoningLabel, agentReasoningOptions } from "
|
|
5
|
-
import { getAgentActivityLog, getExternalSnapshotForSession } from "
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
30
|
-
import { PromptStore, toPromptEnvelope } from "
|
|
31
|
-
import { RelayArtifactService } from "
|
|
32
|
-
import {
|
|
33
|
-
import {
|
|
34
|
-
import {
|
|
35
|
-
import {
|
|
3
|
+
import { ADMIN_GROUP_ID } from "../../access/access-control.js";
|
|
4
|
+
import { agentLabel, agentReasoningLabel, agentReasoningOptions } from "../../agents/shared/agent.js";
|
|
5
|
+
import { getAgentActivityLog, getExternalSnapshotForSession } from "../../agents/shared/agent-activity.js";
|
|
6
|
+
import { hostAgentLoginCommand, hostAgentLogoutCommand } from "../../agents/shared/agent-auth-commands.js";
|
|
7
|
+
import { listAgentAdapterDescriptors } from "../../agents/shared/agent-adapter.js";
|
|
8
|
+
import { AgentUpdateManager } from "../../agents/shared/agent-updates.js";
|
|
9
|
+
import { enabledAgents } from "../../agents/shared/agent-factory.js";
|
|
10
|
+
import { ensureOutDir } from "../../artifacts/artifacts.js";
|
|
11
|
+
import { buildFileInstructions, outboxPath, stageFile } from "../../artifacts/attachments.js";
|
|
12
|
+
import { AuditLogStore } from "../../access/audit-log.js";
|
|
13
|
+
import { BotPreferencesStore } from "../../state/bot-preferences.js";
|
|
14
|
+
import { capabilitiesOf, filterActivityEvents, parseActivityOptions, renderPromptFailure, trimLine } from "../shared/bot-rendering.js";
|
|
15
|
+
import { parseAgentUpdateId, renderAgentUpdateJobAction, renderAgentUpdateJobsAction, renderAgentUpdateLogAction, renderAgentUpdatePickerAction, renderQueueListAction } from "../shared/channel-actions.js";
|
|
16
|
+
import { createChannelActivityRecorder, createChannelAuditRecorder, createChannelBusyStore, createChannelPermissionChecker, createChannelQueueStatusController, } from "../shared/channel-bridge-controller.js";
|
|
17
|
+
import { createSharedChannelCommandDispatcher } from "../shared/channel-command-core.js";
|
|
18
|
+
import { slackHelpCommandList } from "../shared/channel-command-catalog.js";
|
|
19
|
+
import { ChannelCommandService } from "../shared/channel-command-service.js";
|
|
20
|
+
import { createChannelPromptEngine } from "../shared/channel-prompt-engine.js";
|
|
21
|
+
import { runChannelPeerPrompt } from "../shared/channel-peer-prompt.js";
|
|
22
|
+
import { deliverChannelAction } from "../shared/channel-runtime.js";
|
|
23
|
+
import { deliverChannelCliArtifacts } from "../shared/channel-cli-artifacts.js";
|
|
24
|
+
import { createChannelExternalMirrorController } from "../shared/channel-external-mirror-controller.js";
|
|
25
|
+
import { monitorChannelExternalContexts } from "../shared/channel-external-monitor.js";
|
|
26
|
+
import { isSlackContextKey, parseSlackContextKey, slackContextKey } from "../shared/context-key.js";
|
|
27
|
+
import { friendlyErrorText } from "../../core/error-messages.js";
|
|
28
|
+
import { spawnConnectorRestart, spawnSelfUpdate } from "../../support/operations.js";
|
|
29
|
+
import { RemoteRelayClient } from "../../peers/peer-client.js";
|
|
30
|
+
import { PromptStore, toPromptEnvelope } from "../../state/prompt-store.js";
|
|
31
|
+
import { RelayArtifactService } from "../../runtime/relay-artifact-service.js";
|
|
32
|
+
import { RelayAuthService } from "../../runtime/relay-auth-service.js";
|
|
33
|
+
import { configureRedaction, redactText } from "../../core/redaction.js";
|
|
34
|
+
import { renderSessionInfoPlain } from "../shared/session-format.js";
|
|
35
|
+
import { canWriteWithLock, SessionLockStore } from "../../access/session-locks.js";
|
|
36
|
+
import { SessionRegistry } from "../../state/session-registry.js";
|
|
36
37
|
import { createSlackArtifactCommandHandler, sendRecentSlackArtifacts } from "./slack-artifacts.js";
|
|
37
38
|
import { SlackBotChannelRuntime, actionFromSlackActionId, splitSlackMessage, trimSlackMessage } from "./slack-channel-runtime.js";
|
|
38
39
|
import { isUnauthenticatedSlackCommandAllowed, parseSlackMessageCommand, parseSlackSlashCommand, permissionForSlackAction, requiredPermissionForSlackCommand } from "./slack-command-surface.js";
|
|
39
40
|
import { collectSlackDiagnostics } from "./slack-diagnostics.js";
|
|
40
41
|
import { getSlackRateLimitMetrics } from "./slack-rate-limit.js";
|
|
41
|
-
import { transcribeAudio } from "
|
|
42
|
-
import { UserStore } from "
|
|
43
|
-
import { WebActivityStore } from "
|
|
44
|
-
import { evaluateWorkspacePolicy, filterAllowedWorkspaces } from "
|
|
42
|
+
import { transcribeAudio } from "../../artifacts/voice.js";
|
|
43
|
+
import { UserStore } from "../../access/user-management.js";
|
|
44
|
+
import { WebActivityStore } from "../../web/web-state.js";
|
|
45
|
+
import { evaluateWorkspacePolicy, filterAllowedWorkspaces } from "../../core/workspace-policy.js";
|
|
45
46
|
export { isUnauthenticatedSlackCommandAllowed, permissionForSlackAction, requiredPermissionForSlackCommand } from "./slack-command-surface.js";
|
|
46
47
|
const EDIT_DEBOUNCE_MS = 1500;
|
|
47
48
|
const TYPING_INTERVAL_MS = 4500;
|
|
@@ -70,24 +71,23 @@ export function createSlackBridge(config, registry) {
|
|
|
70
71
|
const lockStore = new SessionLockStore(config.workspace, config.stateBackend);
|
|
71
72
|
const userStore = new UserStore();
|
|
72
73
|
const artifactService = new RelayArtifactService(config);
|
|
74
|
+
const authService = new RelayAuthService(config);
|
|
73
75
|
const agentUpdates = new AgentUpdateManager();
|
|
74
76
|
const commandService = new ChannelCommandService(config);
|
|
75
|
-
const busyStates =
|
|
77
|
+
const busyStates = createChannelBusyStore();
|
|
76
78
|
const turnProgress = new Map();
|
|
77
79
|
const draining = new Set();
|
|
78
80
|
const picks = new Map();
|
|
79
81
|
const externalMirrors = new Map();
|
|
80
|
-
const queueStatusMessages =
|
|
82
|
+
const queueStatusMessages = createChannelQueueStatusController({
|
|
83
|
+
send: async (_contextKey, context, text) => (await runtime.sendMessage(context, { text, fallbackText: text })).messageId,
|
|
84
|
+
edit: async (_contextKey, context, messageId, text) => {
|
|
85
|
+
await runtime.editMessage(context, messageId, { text, fallbackText: text });
|
|
86
|
+
},
|
|
87
|
+
});
|
|
81
88
|
const remoteClient = new RemoteRelayClient();
|
|
82
89
|
let externalMonitor;
|
|
83
|
-
const getBusyState = (contextKey) =>
|
|
84
|
-
let state = busyStates.get(contextKey);
|
|
85
|
-
if (!state) {
|
|
86
|
-
state = { processing: false, switching: false };
|
|
87
|
-
busyStates.set(contextKey, state);
|
|
88
|
-
}
|
|
89
|
-
return state;
|
|
90
|
-
};
|
|
90
|
+
const getBusyState = (contextKey) => busyStates.get(contextKey);
|
|
91
91
|
const actorFor = (request) => ({
|
|
92
92
|
channel: "slack",
|
|
93
93
|
id: request.authUser?.user.id ?? `slack:${request.userId}`,
|
|
@@ -95,27 +95,19 @@ export function createSlackBridge(config, registry) {
|
|
|
95
95
|
username: request.authUser?.user.email ?? request.username,
|
|
96
96
|
channelUserId: request.userId,
|
|
97
97
|
});
|
|
98
|
-
const appendActivity = (
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
contextKey: input.contextKey ?? request.contextKey,
|
|
112
|
-
actor: input.actor ?? actorFor(request),
|
|
113
|
-
actorId: request.authUser?.user.id ?? request.userId,
|
|
114
|
-
actorRole: request.authUser?.groups.map((group) => group.name).join(", ") ?? "unauthenticated",
|
|
115
|
-
...input,
|
|
116
|
-
});
|
|
117
|
-
};
|
|
118
|
-
const hasPermission = (request, permission) => userStore.hasPermission(request.authUser, permission);
|
|
98
|
+
const appendActivity = createChannelActivityRecorder({
|
|
99
|
+
source: "slack",
|
|
100
|
+
workspace: config.workspace,
|
|
101
|
+
activityStore,
|
|
102
|
+
actorFor,
|
|
103
|
+
});
|
|
104
|
+
const audit = createChannelAuditRecorder({
|
|
105
|
+
channelId: "slack",
|
|
106
|
+
auditLog,
|
|
107
|
+
actorFor,
|
|
108
|
+
actorIdFor: (request) => request.userId,
|
|
109
|
+
});
|
|
110
|
+
const hasPermission = createChannelPermissionChecker(userStore);
|
|
119
111
|
const reply = async (request, content, options = {}) => {
|
|
120
112
|
if (options.ephemeral && request.respond) {
|
|
121
113
|
await request.respond({
|
|
@@ -213,7 +205,7 @@ export function createSlackBridge(config, registry) {
|
|
|
213
205
|
};
|
|
214
206
|
const commandArtifacts = createSlackArtifactCommandHandler(artifactDeps);
|
|
215
207
|
const getBusyReason = (contextKey) => {
|
|
216
|
-
const state = busyStates.
|
|
208
|
+
const state = busyStates.peek(contextKey);
|
|
217
209
|
const session = registry.get(contextKey);
|
|
218
210
|
if (state?.processing || state?.switching || session?.isProcessing()) {
|
|
219
211
|
return { busy: true, kind: "connector", state: state ?? getBusyState(contextKey) };
|
|
@@ -225,111 +217,7 @@ export function createSlackBridge(config, registry) {
|
|
|
225
217
|
return { busy: false, kind: "idle" };
|
|
226
218
|
};
|
|
227
219
|
const updateQueueStatusMessage = async (contextKey, context, text) => {
|
|
228
|
-
|
|
229
|
-
if (state.lastText === text && state.messageId) {
|
|
230
|
-
return;
|
|
231
|
-
}
|
|
232
|
-
if (!state.messageId) {
|
|
233
|
-
const sent = await runtime.sendMessage(context, { text, fallbackText: text });
|
|
234
|
-
state.messageId = sent.messageId;
|
|
235
|
-
state.lastText = text;
|
|
236
|
-
queueStatusMessages.set(contextKey, state);
|
|
237
|
-
return;
|
|
238
|
-
}
|
|
239
|
-
await runtime.editMessage(context, state.messageId, { text, fallbackText: text });
|
|
240
|
-
state.lastText = text;
|
|
241
|
-
queueStatusMessages.set(contextKey, state);
|
|
242
|
-
};
|
|
243
|
-
const sendExternalWorkingNotice = async (context, state, snapshot) => {
|
|
244
|
-
const turnKey = snapshot.activity.turnId ?? snapshot.activity.startedAt?.toISOString() ?? "unknown";
|
|
245
|
-
if (state.workingNoticeTurnKey === turnKey) {
|
|
246
|
-
return;
|
|
247
|
-
}
|
|
248
|
-
const prompt = trimLine(snapshot.latestUserMessage ?? "", 250);
|
|
249
|
-
const text = prompt ? `*Working on* ${prompt}` : `*Working on* external ${snapshot.agentLabel} task...`;
|
|
250
|
-
await runtime.sendMessage(context, {
|
|
251
|
-
text,
|
|
252
|
-
fallbackText: prompt ? `Working on ${prompt}` : `Working on external ${snapshot.agentLabel} task...`,
|
|
253
|
-
});
|
|
254
|
-
state.workingNoticeTurnKey = turnKey;
|
|
255
|
-
};
|
|
256
|
-
const mirrorExternalSnapshot = async (contextKey, context, session, snapshot) => {
|
|
257
|
-
let state = externalMirrors.get(contextKey);
|
|
258
|
-
if (!state || state.threadId !== snapshot.threadId || state.rolloutPath !== snapshot.sourcePath) {
|
|
259
|
-
state = {
|
|
260
|
-
threadId: snapshot.threadId,
|
|
261
|
-
rolloutPath: snapshot.sourcePath,
|
|
262
|
-
lastLine: snapshot.lineCount,
|
|
263
|
-
turnId: snapshot.activity.turnId,
|
|
264
|
-
startedAt: snapshot.activity.startedAt,
|
|
265
|
-
};
|
|
266
|
-
externalMirrors.set(contextKey, state);
|
|
267
|
-
}
|
|
268
|
-
const mirrorMode = preferencesStore.get(contextKey).mirrorMode ?? config.slackMirrorMode;
|
|
269
|
-
if (snapshot.activity.active) {
|
|
270
|
-
state.turnId = snapshot.activity.turnId;
|
|
271
|
-
state.startedAt = snapshot.activity.startedAt;
|
|
272
|
-
if (mirrorMode !== "off") {
|
|
273
|
-
const now = Date.now();
|
|
274
|
-
if (!state.lastTypingAt || now - state.lastTypingAt >= TYPING_INTERVAL_MS) {
|
|
275
|
-
state.lastTypingAt = now;
|
|
276
|
-
await runtime.sendTyping(context).catch(() => { });
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
if (mirrorMode === "final") {
|
|
280
|
-
await sendExternalWorkingNotice(context, state, snapshot);
|
|
281
|
-
state.lastLine = Math.max(state.lastLine, snapshot.lineCount);
|
|
282
|
-
return;
|
|
283
|
-
}
|
|
284
|
-
if (mirrorMode === "off") {
|
|
285
|
-
state.lastLine = Math.max(state.lastLine, snapshot.lineCount);
|
|
286
|
-
return;
|
|
287
|
-
}
|
|
288
|
-
const status = renderExternalMirrorStatus(snapshot, promptStore.list(contextKey).length);
|
|
289
|
-
const now = Date.now();
|
|
290
|
-
const canUpdateStatus = !state.latestStatusAt || now - state.latestStatusAt >= config.slackMirrorMinUpdateMs;
|
|
291
|
-
if (!state.statusMessageId) {
|
|
292
|
-
const sent = await runtime.sendMessage(context, { text: status.plain, fallbackText: status.plain });
|
|
293
|
-
state.statusMessageId = sent.messageId;
|
|
294
|
-
state.latestStatusAt = now;
|
|
295
|
-
}
|
|
296
|
-
else if (state.latestStatus !== status.plain && canUpdateStatus) {
|
|
297
|
-
await runtime.editMessage(context, state.statusMessageId, { text: status.plain, fallbackText: status.plain });
|
|
298
|
-
state.latestStatusAt = now;
|
|
299
|
-
}
|
|
300
|
-
state.latestStatus = status.plain;
|
|
301
|
-
if (mirrorMode === "full") {
|
|
302
|
-
const newEvents = snapshot.events
|
|
303
|
-
.filter((event) => event.lineNumber > (state.latestMirroredEventLine ?? state.lastLine))
|
|
304
|
-
.slice(-6);
|
|
305
|
-
for (const event of newEvents) {
|
|
306
|
-
const rendered = renderExternalMirrorEvent(event);
|
|
307
|
-
if (rendered) {
|
|
308
|
-
await runtime.sendMessage(context, { text: rendered.plain, fallbackText: rendered.plain });
|
|
309
|
-
state.latestMirroredEventLine = event.lineNumber;
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
state.lastLine = Math.max(state.lastLine, snapshot.lineCount);
|
|
314
|
-
return;
|
|
315
|
-
}
|
|
316
|
-
const terminalEvent = [...snapshot.events].reverse().find((event) => event.kind === "task" && event.status && event.status !== "started");
|
|
317
|
-
if (terminalEvent) {
|
|
318
|
-
const finalAgent = snapshot.events.filter((event) => event.kind === "agent" && event.text).at(-1);
|
|
319
|
-
if (mirrorMode !== "off" && mirrorMode !== "status" && finalAgent?.text && finalAgent.lineNumber !== state.latestAgentLine) {
|
|
320
|
-
await runtime.sendMessage(context, {
|
|
321
|
-
text: `*${snapshot.agentLabel} CLI final answer:*`,
|
|
322
|
-
fallbackText: `${snapshot.agentLabel} CLI final answer:`,
|
|
323
|
-
});
|
|
324
|
-
for (const chunk of splitSlackMessage(finalAgent.text)) {
|
|
325
|
-
await runtime.sendMessage(context, { text: chunk, fallbackText: chunk });
|
|
326
|
-
}
|
|
327
|
-
state.latestAgentLine = finalAgent.lineNumber;
|
|
328
|
-
}
|
|
329
|
-
await deliverCliGeneratedArtifacts(contextKey, context, session, state.startedAt, terminalEvent.turnId);
|
|
330
|
-
}
|
|
331
|
-
state.workingNoticeTurnKey = undefined;
|
|
332
|
-
state.lastLine = Math.max(state.lastLine, snapshot.lineCount);
|
|
220
|
+
await queueStatusMessages.update(contextKey, context, text);
|
|
333
221
|
};
|
|
334
222
|
const ensureActiveThread = async (request, session) => {
|
|
335
223
|
if (!session.hasActiveThread()) {
|
|
@@ -337,63 +225,15 @@ export function createSlackBridge(config, registry) {
|
|
|
337
225
|
updateSession(request, session);
|
|
338
226
|
}
|
|
339
227
|
};
|
|
340
|
-
const checkAgentAuthStatus =
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
return checkHermesAuthStatus({ baseUrl: config.hermesApiBaseUrl, apiKey: config.hermesApiKey });
|
|
345
|
-
if (info.agentId === "openclaw")
|
|
346
|
-
return checkOpenClawAuthStatus({ gatewayUrl: config.openClawGatewayUrl, token: config.openClawGatewayToken, password: config.openClawGatewayPassword });
|
|
347
|
-
if (info.agentId === "claude-code")
|
|
348
|
-
return checkClaudeCodeAuthStatus(config.claudeCodeCliPath);
|
|
349
|
-
return checkAuthStatus(config.codexApiKey);
|
|
350
|
-
};
|
|
351
|
-
const checkLoginAuthStatus = async (info) => {
|
|
352
|
-
if (info.agentId === "hermes")
|
|
353
|
-
return checkHermesAuthStatus({ baseUrl: config.hermesApiBaseUrl, apiKey: config.hermesApiKey });
|
|
354
|
-
if (info.agentId === "claude-code")
|
|
355
|
-
return checkClaudeCodeAuthStatus(config.claudeCodeCliPath);
|
|
356
|
-
return checkAuthStatus(config.codexApiKey);
|
|
357
|
-
};
|
|
358
|
-
const startAgentLogin = (info) => {
|
|
359
|
-
if (info.agentId === "hermes")
|
|
360
|
-
return startHermesLogin(config.hermesCliPath);
|
|
361
|
-
if (info.agentId === "claude-code")
|
|
362
|
-
return startClaudeCodeLogin(config.claudeCodeCliPath);
|
|
363
|
-
if (info.agentId === "codex")
|
|
364
|
-
return startCodexLogin();
|
|
365
|
-
return Promise.resolve({ success: false, message: `${info.agentLabel} login is not managed by NordRelay. Run the agent login flow on the host.` });
|
|
366
|
-
};
|
|
367
|
-
const startAgentLogout = (info) => {
|
|
368
|
-
if (info.agentId === "hermes")
|
|
369
|
-
return startHermesLogout(config.hermesCliPath);
|
|
370
|
-
if (info.agentId === "claude-code")
|
|
371
|
-
return startClaudeCodeLogout(config.claudeCodeCliPath);
|
|
372
|
-
if (info.agentId === "codex")
|
|
373
|
-
return startCodexLogout();
|
|
374
|
-
return Promise.resolve({ success: false, message: `${info.agentLabel} logout is not managed by NordRelay. Run the agent logout flow on the host.` });
|
|
375
|
-
};
|
|
228
|
+
const checkAgentAuthStatus = (info) => authService.check(info);
|
|
229
|
+
const checkLoginAuthStatus = (info) => authService.check(info);
|
|
230
|
+
const startAgentLogin = (info) => authService.startLogin(info);
|
|
231
|
+
const startAgentLogout = (info) => authService.startLogout(info);
|
|
376
232
|
const hostLoginCommand = (info) => {
|
|
377
|
-
|
|
378
|
-
return `${config.hermesCliPath ?? "hermes"} login --no-browser`;
|
|
379
|
-
if (info.agentId === "claude-code")
|
|
380
|
-
return `${config.claudeCodeCliPath ?? "claude"} auth login`;
|
|
381
|
-
if (info.agentId === "pi")
|
|
382
|
-
return `${config.piCliPath ?? "pi"} auth login`;
|
|
383
|
-
if (info.agentId === "openclaw")
|
|
384
|
-
return `${config.openClawCliPath ?? "openclaw"} login`;
|
|
385
|
-
return "codex login --device-auth";
|
|
233
|
+
return hostAgentLoginCommand(config, info);
|
|
386
234
|
};
|
|
387
235
|
const hostLogoutCommand = (info) => {
|
|
388
|
-
|
|
389
|
-
return `${config.hermesCliPath ?? "hermes"} logout`;
|
|
390
|
-
if (info.agentId === "claude-code")
|
|
391
|
-
return `${config.claudeCodeCliPath ?? "claude"} auth logout`;
|
|
392
|
-
if (info.agentId === "pi")
|
|
393
|
-
return `${config.piCliPath ?? "pi"} auth logout`;
|
|
394
|
-
if (info.agentId === "openclaw")
|
|
395
|
-
return `${config.openClawCliPath ?? "openclaw"} logout`;
|
|
396
|
-
return "codex logout";
|
|
236
|
+
return hostAgentLogoutCommand(config, info);
|
|
397
237
|
};
|
|
398
238
|
const denyIfLocked = async (request) => {
|
|
399
239
|
const lock = lockStore.get(request.contextKey);
|
|
@@ -545,45 +385,76 @@ export function createSlackBridge(config, registry) {
|
|
|
545
385
|
}
|
|
546
386
|
};
|
|
547
387
|
const deliverCliGeneratedArtifacts = async (contextKey, context, session, startedAt, turnId) => {
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
return;
|
|
566
|
-
}
|
|
567
|
-
const persisted = await persistWorkspaceArtifactReport(workspace, turnId, report).catch((error) => {
|
|
568
|
-
console.error("Failed to persist Slack CLI artifact report:", error);
|
|
569
|
-
return null;
|
|
388
|
+
await deliverChannelCliArtifacts({
|
|
389
|
+
config,
|
|
390
|
+
contextKey,
|
|
391
|
+
session,
|
|
392
|
+
startedAt,
|
|
393
|
+
turnId,
|
|
394
|
+
state: externalMirrors.get(contextKey),
|
|
395
|
+
autoSend: config.slackAutoSendArtifacts,
|
|
396
|
+
sendSummaryWhenAutoSendDisabled: true,
|
|
397
|
+
logPrefix: "Slack",
|
|
398
|
+
sendSummary: (summary) => runtime.sendMessage(context, { text: summary, fallbackText: summary }).then(() => { }),
|
|
399
|
+
sendArtifact: (artifact) => runtime.sendFile(context, { localPath: artifact.localPath, name: artifact.name }).then(() => { }).catch((error) => {
|
|
400
|
+
console.error(`Failed to send Slack CLI artifact ${artifact.name}:`, error);
|
|
401
|
+
}),
|
|
402
|
+
appendActivity: (input) => {
|
|
403
|
+
activityStore.append(input);
|
|
404
|
+
},
|
|
570
405
|
});
|
|
571
|
-
const summary = formatArtifactSummary(report.artifacts, report.skippedCount, report.omittedCount);
|
|
572
|
-
if (summary) {
|
|
573
|
-
await runtime.sendMessage(context, { text: summary, fallbackText: summary });
|
|
574
|
-
}
|
|
575
|
-
if (config.slackAutoSendArtifacts) {
|
|
576
|
-
for (const artifact of (persisted?.artifacts ?? report.artifacts).slice(0, 5)) {
|
|
577
|
-
await runtime.sendFile(context, { localPath: artifact.localPath, name: artifact.name }).catch((error) => {
|
|
578
|
-
console.error(`Failed to send Slack CLI artifact ${artifact.name}:`, error);
|
|
579
|
-
});
|
|
580
|
-
}
|
|
581
|
-
}
|
|
582
|
-
const info = session.getInfo();
|
|
583
|
-
activityStore.append({ source: "cli", status: "info", type: config.slackAutoSendArtifacts ? "artifacts_sent" : "artifacts_detected", contextKey, threadId: info.threadId, workspace: info.workspace, agentId: info.agentId, actor: { channel: "cli", label: `${info.agentLabel} CLI` }, detail: summary });
|
|
584
|
-
if (state)
|
|
585
|
-
state.artifactsDeliveredForTurnId = turnId;
|
|
586
406
|
};
|
|
407
|
+
const externalMirrorController = createChannelExternalMirrorController({
|
|
408
|
+
config,
|
|
409
|
+
states: externalMirrors,
|
|
410
|
+
typingIntervalMs: TYPING_INTERVAL_MS,
|
|
411
|
+
minUpdateMs: () => config.slackMirrorMinUpdateMs,
|
|
412
|
+
mirrorMode: (contextKey) => preferencesStore.get(contextKey).mirrorMode ?? config.slackMirrorMode,
|
|
413
|
+
queueLength: (contextKey) => promptStore.list(contextKey).length,
|
|
414
|
+
activityActor: (snapshot) => ({ channel: "cli", label: `${snapshot.agentLabel} CLI` }),
|
|
415
|
+
appendActivity: (input) => {
|
|
416
|
+
activityStore.append(input);
|
|
417
|
+
},
|
|
418
|
+
sendTyping: (_contextKey, context) => runtime.sendTyping(context).catch(() => { }),
|
|
419
|
+
sendWorkingNotice: async (_contextKey, context, state, snapshot, prompt) => {
|
|
420
|
+
const turnKey = snapshot.activity.turnId ?? snapshot.activity.startedAt?.toISOString() ?? "unknown";
|
|
421
|
+
if (state.workingNoticeTurnKey === turnKey) {
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
const text = prompt ? `*Working on* ${prompt}` : `*Working on* external ${snapshot.agentLabel} task...`;
|
|
425
|
+
await runtime.sendMessage(context, {
|
|
426
|
+
text,
|
|
427
|
+
fallbackText: prompt ? `Working on ${prompt}` : `Working on external ${snapshot.agentLabel} task...`,
|
|
428
|
+
});
|
|
429
|
+
state.workingNoticeTurnKey = turnKey;
|
|
430
|
+
},
|
|
431
|
+
sendStatus: async (_contextKey, context, _state, rendered) => {
|
|
432
|
+
const sent = await runtime.sendMessage(context, { text: rendered.plain, fallbackText: rendered.plain });
|
|
433
|
+
return sent.messageId;
|
|
434
|
+
},
|
|
435
|
+
editStatus: (_contextKey, context, _state, messageId, rendered) => runtime.editMessage(context, messageId, { text: rendered.plain, fallbackText: rendered.plain }),
|
|
436
|
+
sendEvent: (_contextKey, context, _state, rendered) => runtime.sendMessage(context, { text: rendered.plain, fallbackText: rendered.plain }).then(() => { }),
|
|
437
|
+
sendDone: (_contextKey, context, state, text) => {
|
|
438
|
+
if (state.statusMessageId) {
|
|
439
|
+
return runtime.editMessage(context, state.statusMessageId, { text, fallbackText: text });
|
|
440
|
+
}
|
|
441
|
+
return runtime.sendMessage(context, { text, fallbackText: text }).then(() => { });
|
|
442
|
+
},
|
|
443
|
+
sendFinalAnswer: async (_contextKey, context, _state, snapshot, text) => {
|
|
444
|
+
await runtime.sendMessage(context, {
|
|
445
|
+
text: `*${snapshot.agentLabel} CLI final answer:*`,
|
|
446
|
+
fallbackText: `${snapshot.agentLabel} CLI final answer:`,
|
|
447
|
+
});
|
|
448
|
+
for (const chunk of splitSlackMessage(text)) {
|
|
449
|
+
await runtime.sendMessage(context, { text: chunk, fallbackText: chunk });
|
|
450
|
+
}
|
|
451
|
+
},
|
|
452
|
+
deliverArtifacts: (contextKey, context, session, state, turnId) => deliverCliGeneratedArtifacts(contextKey, context, session, state.startedAt, turnId),
|
|
453
|
+
fullEventFilter: () => true,
|
|
454
|
+
fullEventLimit: 6,
|
|
455
|
+
requirePreviousForTerminal: false,
|
|
456
|
+
});
|
|
457
|
+
const mirrorExternalSnapshot = externalMirrorController.mirror;
|
|
587
458
|
const commandDispatcher = createSharedChannelCommandDispatcher({
|
|
588
459
|
transport: "slack",
|
|
589
460
|
bindings: [
|
|
@@ -1285,36 +1156,30 @@ export function createSlackBridge(config, registry) {
|
|
|
1285
1156
|
return id;
|
|
1286
1157
|
};
|
|
1287
1158
|
const monitorExternalContexts = async () => {
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
await updateQueueStatusMessage(contextKey, context, `Waiting for ${snapshot.agentLabel} CLI task... ${promptStore.list(contextKey).length} queued${promptStore.isPaused(contextKey) ? " (paused)" : ""}.`).catch(() => { });
|
|
1310
|
-
}
|
|
1311
|
-
continue;
|
|
1312
|
-
}
|
|
1313
|
-
if (promptStore.list(contextKey).length > 0 && !promptStore.isPaused(contextKey) && !session.isProcessing()) {
|
|
1314
|
-
await updateQueueStatusMessage(contextKey, context, `CLI task finished, running queued prompt 1/${promptStore.list(contextKey).length}.`).catch(() => { });
|
|
1159
|
+
await monitorChannelExternalContexts({
|
|
1160
|
+
config,
|
|
1161
|
+
registry,
|
|
1162
|
+
promptStore,
|
|
1163
|
+
isContextKey: isSlackContextKey,
|
|
1164
|
+
canSendSystemMessages: (contextKey) => canSendSystemMessagesToSlackContext(userStore, contextKey),
|
|
1165
|
+
isAllowed: (contextKey) => {
|
|
1166
|
+
const parsed = parseSlackContextKey(contextKey);
|
|
1167
|
+
return Boolean(parsed && isSlackTeamAllowed(parsed.teamId) && isSlackChannelAllowedByEnv(parsed.channelId));
|
|
1168
|
+
},
|
|
1169
|
+
contextForKey: (contextKey) => {
|
|
1170
|
+
const parsed = parseSlackContextKey(contextKey);
|
|
1171
|
+
return parsed ? { channelId: "slack", chatId: parsed.channelId, ...(parsed.threadTs ? { topicId: parsed.threadTs } : {}) } : null;
|
|
1172
|
+
},
|
|
1173
|
+
previousLastLine: (contextKey) => externalMirrors.get(contextKey)?.lastLine,
|
|
1174
|
+
mirrorSnapshot: mirrorExternalSnapshot,
|
|
1175
|
+
updateQueueStatus: updateQueueStatusMessage,
|
|
1176
|
+
drainQueue: async (contextKey, context) => {
|
|
1177
|
+
const parsed = parseSlackContextKey(contextKey);
|
|
1178
|
+
if (!parsed)
|
|
1179
|
+
return;
|
|
1315
1180
|
await drainQueue({ contextKey, context, userId: "system", channelId: parsed.channelId, teamId: parsed.teamId, isDirectMessage: false, source: "system" });
|
|
1316
|
-
}
|
|
1317
|
-
}
|
|
1181
|
+
},
|
|
1182
|
+
});
|
|
1318
1183
|
};
|
|
1319
1184
|
app.event("message", async ({ event }) => {
|
|
1320
1185
|
await handleMessage(event);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createReadStream } from "node:fs";
|
|
2
|
-
import { SlackChannelAdapter, } from "
|
|
3
|
-
import { redactText } from "
|
|
2
|
+
import { SlackChannelAdapter, } from "../shared/channel-adapter.js";
|
|
3
|
+
import { redactText } from "../../core/redaction.js";
|
|
4
4
|
import { slackRateLimiter } from "./slack-rate-limit.js";
|
|
5
5
|
const SLACK_TEXT_LIMIT = 40000;
|
|
6
6
|
const SLACK_SAFE_TEXT_LIMIT = 3500;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { permissionForCommand } from "
|
|
2
|
-
import { normalizeChannelCommandName, parseChannelCommand } from "
|
|
1
|
+
import { permissionForCommand } from "../../access/access-control.js";
|
|
2
|
+
import { normalizeChannelCommandName, parseChannelCommand } from "../shared/channel-runtime.js";
|
|
3
3
|
export function parseSlackMessageCommand(text) {
|
|
4
4
|
return parseChannelCommand(text, { allowBotMention: false });
|
|
5
5
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { WebClient } from "@slack/web-api";
|
|
2
|
-
import { friendlyErrorText } from "
|
|
3
|
-
import { UserStore } from "
|
|
2
|
+
import { friendlyErrorText } from "../../core/error-messages.js";
|
|
3
|
+
import { UserStore } from "../../access/user-management.js";
|
|
4
4
|
export async function collectSlackDiagnostics(input) {
|
|
5
5
|
const { config } = input;
|
|
6
6
|
const checks = [];
|