@zhin.js/adapter-slack 6.0.13 → 6.0.14
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/CHANGELOG.md +33 -0
- package/adapters/slack.js +3 -1
- package/adapters/slack.ts +3 -1
- package/lib/endpoint.d.ts +2 -1
- package/lib/endpoint.js +7 -1
- package/lib/side-event-dispatch.d.ts +4 -0
- package/lib/side-event-dispatch.js +45 -0
- package/package.json +14 -14
- package/src/endpoint.ts +15 -2
- package/src/side-event-dispatch.ts +54 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 6.0.14
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 5969c5b: Add SideEventGateway so adapters forward notice/request/system into HandlerIndex. HandlerContext now exposes only generation-safe capabilities and prompt ports; live Endpoint escape hatches are removed.
|
|
8
|
+
- Updated dependencies [5969c5b]
|
|
9
|
+
- Updated dependencies [d336a3f]
|
|
10
|
+
- Updated dependencies [0c82a7e]
|
|
11
|
+
- Updated dependencies [b9217e4]
|
|
12
|
+
- Updated dependencies [5969c5b]
|
|
13
|
+
- Updated dependencies [5969c5b]
|
|
14
|
+
- Updated dependencies [974772e]
|
|
15
|
+
- Updated dependencies [5969c5b]
|
|
16
|
+
- Updated dependencies [5969c5b]
|
|
17
|
+
- Updated dependencies [2f786bd]
|
|
18
|
+
- Updated dependencies [63d89f9]
|
|
19
|
+
- Updated dependencies [71c7cdd]
|
|
20
|
+
- Updated dependencies [3cca0ea]
|
|
21
|
+
- Updated dependencies [1312ca0]
|
|
22
|
+
- Updated dependencies [985fa22]
|
|
23
|
+
- Updated dependencies [04b861d]
|
|
24
|
+
- Updated dependencies [a23d544]
|
|
25
|
+
- Updated dependencies [8cddabf]
|
|
26
|
+
- Updated dependencies [dbe5081]
|
|
27
|
+
- @zhin.js/im-contract@1.0.4
|
|
28
|
+
- @zhin.js/core@1.5.12
|
|
29
|
+
- @zhin.js/adapter@1.1.11
|
|
30
|
+
- @zhin.js/agent@1.1.14
|
|
31
|
+
- @zhin.js/host-http@1.0.11
|
|
32
|
+
- @zhin.js/command@1.0.15
|
|
33
|
+
- zhin.js@6.0.12
|
|
34
|
+
- @zhin.js/permission@1.0.3
|
|
35
|
+
|
|
3
36
|
## 6.0.13
|
|
4
37
|
|
|
5
38
|
### Patch Changes
|
package/adapters/slack.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Convention entry: discover `adapters/slack.ts` → defineAdapter.
|
|
4
4
|
*/
|
|
5
5
|
import { defineAdapter } from 'zhin.js/adapter';
|
|
6
|
-
import { messageGatewayToken } from '@zhin.js/core/runtime';
|
|
6
|
+
import { messageGatewayToken, sideEventGatewayToken } from '@zhin.js/core/runtime';
|
|
7
7
|
import { httpHostToken } from '@zhin.js/host-http';
|
|
8
8
|
import { SlackEndpoint } from "../lib/endpoint.js";
|
|
9
9
|
import { resolveSlackConfig, } from "../lib/protocol.js";
|
|
@@ -29,6 +29,7 @@ export default defineAdapter({
|
|
|
29
29
|
return new SlackEndpoint({
|
|
30
30
|
id: context.id,
|
|
31
31
|
gateway: context.use(messageGatewayToken),
|
|
32
|
+
sideEvents: context.use(sideEventGatewayToken),
|
|
32
33
|
http: context.use(httpHostToken),
|
|
33
34
|
config,
|
|
34
35
|
});
|
|
@@ -36,6 +37,7 @@ export default defineAdapter({
|
|
|
36
37
|
return new SlackEndpoint({
|
|
37
38
|
id: context.id,
|
|
38
39
|
gateway: context.use(messageGatewayToken),
|
|
40
|
+
sideEvents: context.use(sideEventGatewayToken),
|
|
39
41
|
config,
|
|
40
42
|
});
|
|
41
43
|
},
|
package/adapters/slack.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Convention entry: discover `adapters/slack.ts` → defineAdapter.
|
|
3
3
|
*/
|
|
4
4
|
import { defineAdapter } from 'zhin.js/adapter';
|
|
5
|
-
import { messageGatewayToken } from '@zhin.js/core/runtime';
|
|
5
|
+
import { messageGatewayToken, sideEventGatewayToken } from '@zhin.js/core/runtime';
|
|
6
6
|
import { httpHostToken } from '@zhin.js/host-http';
|
|
7
7
|
import { SlackEndpoint } from '../src/endpoint.js';
|
|
8
8
|
import {
|
|
@@ -34,6 +34,7 @@ export default defineAdapter<SlackAdapterConfig>({
|
|
|
34
34
|
return new SlackEndpoint({
|
|
35
35
|
id: context.id,
|
|
36
36
|
gateway: context.use(messageGatewayToken),
|
|
37
|
+
sideEvents: context.use(sideEventGatewayToken),
|
|
37
38
|
http: context.use(httpHostToken),
|
|
38
39
|
config,
|
|
39
40
|
});
|
|
@@ -41,6 +42,7 @@ export default defineAdapter<SlackAdapterConfig>({
|
|
|
41
42
|
return new SlackEndpoint({
|
|
42
43
|
id: context.id,
|
|
43
44
|
gateway: context.use(messageGatewayToken),
|
|
45
|
+
sideEvents: context.use(sideEventGatewayToken),
|
|
44
46
|
config,
|
|
45
47
|
});
|
|
46
48
|
},
|
package/lib/endpoint.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { EndpointInstance, EndpointManagement, EndpointSendRequest } from 'zhin.js/adapter';
|
|
2
|
-
import type { MessageGateway } from '@zhin.js/core/runtime';
|
|
2
|
+
import type { MessageGateway, SideEventGateway } from '@zhin.js/core/runtime';
|
|
3
3
|
import type { HttpHost } from '@zhin.js/host-http';
|
|
4
4
|
import type { CapabilityId } from 'zhin.js';
|
|
5
5
|
import { type ResolvedSlackConfig, type SlackEvent, type SlackInteractionPayload, type SlackMessageEvent, type SlackSlashCommand } from './protocol.js';
|
|
@@ -118,6 +118,7 @@ export interface SlackWebClientLike extends SlackChatClient {
|
|
|
118
118
|
export interface SlackEndpointOptions {
|
|
119
119
|
readonly id: CapabilityId;
|
|
120
120
|
readonly gateway: MessageGateway;
|
|
121
|
+
readonly sideEvents?: SideEventGateway;
|
|
121
122
|
readonly config: ResolvedSlackConfig;
|
|
122
123
|
readonly http?: HttpHost;
|
|
123
124
|
readonly createClient?: (token: string) => SlackWebClientLike;
|
package/lib/endpoint.js
CHANGED
|
@@ -12,6 +12,7 @@ import { normalizeSlackReactionName } from './slack-reaction.js';
|
|
|
12
12
|
import { postSlackEphemeral } from './slack-response-url.js';
|
|
13
13
|
import { editSlackContent, sendSlackContent } from './slack-outbound.js';
|
|
14
14
|
import { registerSlackWebhookRoutes } from './webhook.js';
|
|
15
|
+
import { receiveSlackSideEvent } from './side-event-dispatch.js';
|
|
15
16
|
export class SlackEndpoint {
|
|
16
17
|
#logger;
|
|
17
18
|
#options;
|
|
@@ -216,7 +217,12 @@ export class SlackEndpoint {
|
|
|
216
217
|
handleEnvelope(body) {
|
|
217
218
|
const envelope = body;
|
|
218
219
|
if (envelope?.type === 'event_callback' && envelope.event) {
|
|
219
|
-
|
|
220
|
+
const event = envelope.event;
|
|
221
|
+
if (event.type !== 'message' && event.type !== 'app_mention') {
|
|
222
|
+
receiveSlackSideEvent(this.#options.sideEvents, String(this.#options.id), this.#options.config.id, event, this.#logger);
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
this.admit(event);
|
|
220
226
|
}
|
|
221
227
|
}
|
|
222
228
|
trackMessageChannel(ts, channel) {
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { SideEventGateway } from '@zhin.js/core/runtime';
|
|
2
|
+
import { type getAdapterLogger } from '@zhin.js/logger';
|
|
3
|
+
import type { SlackEvent } from './protocol.js';
|
|
4
|
+
export declare function receiveSlackSideEvent(sideEvents: SideEventGateway | undefined, endpointKey: string, configId: string, event: SlackEvent, logger: ReturnType<typeof getAdapterLogger>): void;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { buildNotice, mapNoticeParts, senderFromId, SLACK_NOTICE_PARTS_MAP } from '@zhin.js/core';
|
|
2
|
+
import { formatCompact } from '@zhin.js/logger';
|
|
3
|
+
export function receiveSlackSideEvent(sideEvents, endpointKey, configId, event, logger) {
|
|
4
|
+
if (!sideEvents)
|
|
5
|
+
return;
|
|
6
|
+
const eventType = String(event.type ?? '');
|
|
7
|
+
if (!Object.prototype.hasOwnProperty.call(SLACK_NOTICE_PARTS_MAP, eventType))
|
|
8
|
+
return;
|
|
9
|
+
const record = event;
|
|
10
|
+
const parts = mapNoticeParts('slack', eventType);
|
|
11
|
+
const channel = typeof record.channel === 'string' ? record.channel : undefined;
|
|
12
|
+
const user = typeof record.user === 'string' ? record.user : undefined;
|
|
13
|
+
const sceneId = channel ?? user ?? configId;
|
|
14
|
+
const dedupeKey = [
|
|
15
|
+
eventType,
|
|
16
|
+
channel ?? '',
|
|
17
|
+
user ?? '',
|
|
18
|
+
String(record.ts ?? record.event_ts ?? ''),
|
|
19
|
+
].join(':');
|
|
20
|
+
void sideEvents.receiveNotice(buildNotice(record, {
|
|
21
|
+
$id: `slack:${dedupeKey}`,
|
|
22
|
+
$adapter: 'slack',
|
|
23
|
+
$endpoint: configId,
|
|
24
|
+
$type: 'notice',
|
|
25
|
+
$scene_id: sceneId,
|
|
26
|
+
$scene_type: parts.scene_type,
|
|
27
|
+
$sub_type: parts.sub_type,
|
|
28
|
+
$actor: senderFromId(user),
|
|
29
|
+
$target: senderFromId(typeof record.item_user === 'string' ? record.item_user : undefined),
|
|
30
|
+
$timestamp: toMillis(record.event_ts ?? record.ts),
|
|
31
|
+
})).catch((err) => {
|
|
32
|
+
logger.warn(formatCompact({
|
|
33
|
+
op: 'slack_side_event_failed',
|
|
34
|
+
endpoint: configId,
|
|
35
|
+
event: eventType,
|
|
36
|
+
error: err instanceof Error ? err.message : String(err),
|
|
37
|
+
}));
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
function toMillis(time) {
|
|
41
|
+
const value = Number(time);
|
|
42
|
+
if (!Number.isFinite(value) || value <= 0)
|
|
43
|
+
return Date.now();
|
|
44
|
+
return value < 1e12 ? Math.round(value * 1000) : Math.round(value);
|
|
45
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhin.js/adapter-slack",
|
|
3
|
-
"version": "6.0.
|
|
3
|
+
"version": "6.0.14",
|
|
4
4
|
"description": "Zhin.js Slack adapter for Plugin Runtime (Socket Mode / HTTP Events)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -34,21 +34,21 @@
|
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@slack/socket-mode": "^2.0.7",
|
|
36
36
|
"@slack/web-api": "^7.19.0",
|
|
37
|
-
"@zhin.js/adapter": "1.1.
|
|
38
|
-
"@zhin.js/core": "1.5.
|
|
39
|
-
"@zhin.js/host-http": "1.0.
|
|
40
|
-
"@zhin.js/im-contract": "1.0.
|
|
37
|
+
"@zhin.js/adapter": "1.1.11",
|
|
38
|
+
"@zhin.js/core": "1.5.12",
|
|
39
|
+
"@zhin.js/host-http": "1.0.11",
|
|
40
|
+
"@zhin.js/im-contract": "1.0.4",
|
|
41
41
|
"@zhin.js/logger": "1.0.76"
|
|
42
42
|
},
|
|
43
43
|
"peerDependencies": {
|
|
44
44
|
"zod": "^4.0.0",
|
|
45
|
-
"@zhin.js/adapter": "1.1.
|
|
46
|
-
"@zhin.js/agent": "1.1.
|
|
47
|
-
"@zhin.js/command": "1.0.
|
|
48
|
-
"@zhin.js/core": "1.5.
|
|
49
|
-
"@zhin.js/host-http": "1.0.
|
|
50
|
-
"@zhin.js/permission": "1.0.
|
|
51
|
-
"zhin.js": "6.0.
|
|
45
|
+
"@zhin.js/adapter": "1.1.11",
|
|
46
|
+
"@zhin.js/agent": "1.1.14",
|
|
47
|
+
"@zhin.js/command": "1.0.15",
|
|
48
|
+
"@zhin.js/core": "1.5.12",
|
|
49
|
+
"@zhin.js/host-http": "1.0.11",
|
|
50
|
+
"@zhin.js/permission": "1.0.3",
|
|
51
|
+
"zhin.js": "6.0.12"
|
|
52
52
|
},
|
|
53
53
|
"peerDependenciesMeta": {
|
|
54
54
|
"@zhin.js/agent": {
|
|
@@ -69,8 +69,8 @@
|
|
|
69
69
|
"typescript": "^6.0.3",
|
|
70
70
|
"vitest": "^4.1.10",
|
|
71
71
|
"zod": "^4.4.3",
|
|
72
|
-
"@zhin.js/agent": "1.1.
|
|
73
|
-
"zhin.js": "6.0.
|
|
72
|
+
"@zhin.js/agent": "1.1.14",
|
|
73
|
+
"zhin.js": "6.0.12"
|
|
74
74
|
},
|
|
75
75
|
"files": [
|
|
76
76
|
"adapters",
|
package/src/endpoint.ts
CHANGED
|
@@ -10,7 +10,7 @@ import type {
|
|
|
10
10
|
EndpointManagement,
|
|
11
11
|
EndpointSendRequest,
|
|
12
12
|
} from 'zhin.js/adapter';
|
|
13
|
-
import type { MessageGateway } from '@zhin.js/core/runtime';
|
|
13
|
+
import type { MessageGateway, SideEventGateway } from '@zhin.js/core/runtime';
|
|
14
14
|
import type { HttpHost, HttpRouteRegistration } from '@zhin.js/host-http';
|
|
15
15
|
import { formatCompact, getAdapterLogger } from '@zhin.js/logger';
|
|
16
16
|
import type { CapabilityId } from 'zhin.js';
|
|
@@ -37,6 +37,7 @@ import { normalizeSlackReactionName } from './slack-reaction.js';
|
|
|
37
37
|
import { postSlackEphemeral } from './slack-response-url.js';
|
|
38
38
|
import { editSlackContent, sendSlackContent, type SlackChatClient } from './slack-outbound.js';
|
|
39
39
|
import { registerSlackWebhookRoutes, type SlackWebhookHandler } from './webhook.js';
|
|
40
|
+
import { receiveSlackSideEvent } from './side-event-dispatch.js';
|
|
40
41
|
|
|
41
42
|
export interface SlackSocketLike {
|
|
42
43
|
on(
|
|
@@ -91,6 +92,7 @@ export interface SlackWebClientLike extends SlackChatClient {
|
|
|
91
92
|
export interface SlackEndpointOptions {
|
|
92
93
|
readonly id: CapabilityId;
|
|
93
94
|
readonly gateway: MessageGateway;
|
|
95
|
+
readonly sideEvents?: SideEventGateway;
|
|
94
96
|
readonly config: ResolvedSlackConfig;
|
|
95
97
|
readonly http?: HttpHost;
|
|
96
98
|
readonly createClient?: (token: string) => SlackWebClientLike;
|
|
@@ -316,7 +318,18 @@ export class SlackEndpoint implements EndpointInstance, SlackWebhookHandler {
|
|
|
316
318
|
handleEnvelope(body: unknown): void {
|
|
317
319
|
const envelope = body as SlackEventEnvelope;
|
|
318
320
|
if (envelope?.type === 'event_callback' && envelope.event) {
|
|
319
|
-
|
|
321
|
+
const event = envelope.event;
|
|
322
|
+
if (event.type !== 'message' && event.type !== 'app_mention') {
|
|
323
|
+
receiveSlackSideEvent(
|
|
324
|
+
this.#options.sideEvents,
|
|
325
|
+
String(this.#options.id),
|
|
326
|
+
this.#options.config.id,
|
|
327
|
+
event,
|
|
328
|
+
this.#logger,
|
|
329
|
+
);
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
this.admit(event);
|
|
320
333
|
}
|
|
321
334
|
}
|
|
322
335
|
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { buildNotice, mapNoticeParts, senderFromId, SLACK_NOTICE_PARTS_MAP } from '@zhin.js/core';
|
|
2
|
+
import type { SideEventGateway } from '@zhin.js/core/runtime';
|
|
3
|
+
import { formatCompact, type getAdapterLogger } from '@zhin.js/logger';
|
|
4
|
+
import type { SlackEvent } from './protocol.js';
|
|
5
|
+
|
|
6
|
+
export function receiveSlackSideEvent(
|
|
7
|
+
sideEvents: SideEventGateway | undefined,
|
|
8
|
+
endpointKey: string,
|
|
9
|
+
configId: string,
|
|
10
|
+
event: SlackEvent,
|
|
11
|
+
logger: ReturnType<typeof getAdapterLogger>,
|
|
12
|
+
): void {
|
|
13
|
+
if (!sideEvents) return;
|
|
14
|
+
const eventType = String(event.type ?? '');
|
|
15
|
+
if (!Object.prototype.hasOwnProperty.call(SLACK_NOTICE_PARTS_MAP, eventType)) return;
|
|
16
|
+
const record = event as Record<string, unknown>;
|
|
17
|
+
const parts = mapNoticeParts('slack', eventType);
|
|
18
|
+
const channel = typeof record.channel === 'string' ? record.channel : undefined;
|
|
19
|
+
const user = typeof record.user === 'string' ? record.user : undefined;
|
|
20
|
+
const sceneId = channel ?? user ?? configId;
|
|
21
|
+
const dedupeKey = [
|
|
22
|
+
eventType,
|
|
23
|
+
channel ?? '',
|
|
24
|
+
user ?? '',
|
|
25
|
+
String(record.ts ?? record.event_ts ?? ''),
|
|
26
|
+
].join(':');
|
|
27
|
+
void sideEvents.receiveNotice(buildNotice(record, {
|
|
28
|
+
$id: `slack:${dedupeKey}`,
|
|
29
|
+
$adapter: 'slack' as never,
|
|
30
|
+
$endpoint: configId,
|
|
31
|
+
$type: 'notice',
|
|
32
|
+
$scene_id: sceneId,
|
|
33
|
+
$scene_type: parts.scene_type,
|
|
34
|
+
$sub_type: parts.sub_type,
|
|
35
|
+
$actor: senderFromId(user),
|
|
36
|
+
$target: senderFromId(
|
|
37
|
+
typeof record.item_user === 'string' ? record.item_user : undefined,
|
|
38
|
+
),
|
|
39
|
+
$timestamp: toMillis(record.event_ts ?? record.ts),
|
|
40
|
+
})).catch((err) => {
|
|
41
|
+
logger.warn(formatCompact({
|
|
42
|
+
op: 'slack_side_event_failed',
|
|
43
|
+
endpoint: configId,
|
|
44
|
+
event: eventType,
|
|
45
|
+
error: err instanceof Error ? err.message : String(err),
|
|
46
|
+
}));
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function toMillis(time: unknown): number {
|
|
51
|
+
const value = Number(time);
|
|
52
|
+
if (!Number.isFinite(value) || value <= 0) return Date.now();
|
|
53
|
+
return value < 1e12 ? Math.round(value * 1000) : Math.round(value);
|
|
54
|
+
}
|