@framers/agentos-ext-channel-slack 0.1.0

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.
@@ -0,0 +1,32 @@
1
+ /**
2
+ * @fileoverview IChannelAdapter implementation for Slack via @slack/bolt.
3
+ */
4
+ import type { IChannelAdapter, ChannelPlatform, ChannelCapability, ChannelAuthConfig, ChannelConnectionInfo, ChannelSendResult, MessageContent, ChannelEventHandler, ChannelEventType } from '@framers/agentos';
5
+ import { SlackService } from './SlackService';
6
+ export declare class SlackChannelAdapter implements IChannelAdapter {
7
+ private readonly service;
8
+ readonly platform: ChannelPlatform;
9
+ readonly displayName = "Slack";
10
+ readonly capabilities: readonly ChannelCapability[];
11
+ private handlers;
12
+ private msgHandler;
13
+ constructor(service: SlackService);
14
+ initialize(_auth: ChannelAuthConfig): Promise<void>;
15
+ shutdown(): Promise<void>;
16
+ getConnectionInfo(): ChannelConnectionInfo;
17
+ sendMessage(conversationId: string, content: MessageContent): Promise<ChannelSendResult>;
18
+ sendTypingIndicator(_conversationId: string, _isTyping: boolean): Promise<void>;
19
+ on(handler: ChannelEventHandler, eventTypes?: ChannelEventType[]): () => void;
20
+ editMessage(conversationId: string, messageId: string, content: MessageContent): Promise<void>;
21
+ deleteMessage(conversationId: string, messageId: string): Promise<void>;
22
+ addReaction(conversationId: string, messageId: string, emoji: string): Promise<void>;
23
+ getConversationInfo(conversationId: string): Promise<{
24
+ name?: string;
25
+ memberCount?: number;
26
+ isGroup: boolean;
27
+ metadata?: Record<string, unknown>;
28
+ }>;
29
+ private handleInboundMessage;
30
+ private emit;
31
+ }
32
+ //# sourceMappingURL=SlackChannelAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SlackChannelAdapter.d.ts","sourceRoot":"","sources":["../src/SlackChannelAdapter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,qBAAqB,EACrB,iBAAiB,EACjB,cAAc,EACd,mBAAmB,EACnB,gBAAgB,EAKjB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAG9C,qBAAa,mBAAoB,YAAW,eAAe;IAmB7C,OAAO,CAAC,QAAQ,CAAC,OAAO;IAlBpC,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAW;IAC7C,QAAQ,CAAC,WAAW,WAAW;IAC/B,QAAQ,CAAC,YAAY,EAAE,SAAS,iBAAiB,EAAE,CAWxC;IAEX,OAAO,CAAC,QAAQ,CAAkE;IAClF,OAAO,CAAC,UAAU,CAAgD;gBAErC,OAAO,EAAE,YAAY;IAE5C,UAAU,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAOnD,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ/B,iBAAiB,IAAI,qBAAqB;IAMpC,WAAW,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,iBAAiB,CAAC;IA0CxF,mBAAmB,CAAC,eAAe,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAIrF,EAAE,CAAC,OAAO,EAAE,mBAAmB,EAAE,UAAU,CAAC,EAAE,gBAAgB,EAAE,GAAG,MAAM,IAAI;IAOvE,WAAW,CAAC,cAAc,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAiB9F,aAAa,CAAC,cAAc,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvE,WAAW,CAAC,cAAc,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMpF,mBAAmB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC;QACzD,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,OAAO,EAAE,OAAO,CAAC;QACjB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACpC,CAAC;IAgBF,OAAO,CAAC,oBAAoB;IAiD5B,OAAO,CAAC,IAAI;CASb"}
@@ -0,0 +1,174 @@
1
+ "use strict";
2
+ /**
3
+ * @fileoverview IChannelAdapter implementation for Slack via @slack/bolt.
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.SlackChannelAdapter = void 0;
7
+ class SlackChannelAdapter {
8
+ constructor(service) {
9
+ this.service = service;
10
+ this.platform = 'slack';
11
+ this.displayName = 'Slack';
12
+ this.capabilities = [
13
+ 'text',
14
+ 'rich_text',
15
+ 'images',
16
+ 'documents',
17
+ 'threads',
18
+ 'reactions',
19
+ 'mentions',
20
+ 'group_chat',
21
+ 'editing',
22
+ 'deletion',
23
+ ];
24
+ this.handlers = new Map();
25
+ this.msgHandler = null;
26
+ }
27
+ async initialize(_auth) {
28
+ // Service is initialized by the extension pack lifecycle, but
29
+ // if called directly (e.g., standalone usage), we wire up here.
30
+ this.msgHandler = (event) => this.handleInboundMessage(event);
31
+ this.service.onMessage(this.msgHandler);
32
+ }
33
+ async shutdown() {
34
+ if (this.msgHandler) {
35
+ this.service.offMessage(this.msgHandler);
36
+ this.msgHandler = null;
37
+ }
38
+ this.handlers.clear();
39
+ }
40
+ getConnectionInfo() {
41
+ return {
42
+ status: this.service.isRunning ? 'connected' : 'disconnected',
43
+ };
44
+ }
45
+ async sendMessage(conversationId, content) {
46
+ const textBlock = content.blocks.find((b) => b.type === 'text');
47
+ const imageBlock = content.blocks.find((b) => b.type === 'image');
48
+ const documentBlock = content.blocks.find((b) => b.type === 'document');
49
+ // Build Slack blocks for rich content
50
+ const slackBlocks = [];
51
+ if (textBlock && textBlock.type === 'text') {
52
+ slackBlocks.push({
53
+ type: 'section',
54
+ text: { type: 'mrkdwn', text: textBlock.text },
55
+ });
56
+ }
57
+ if (imageBlock && imageBlock.type === 'image') {
58
+ slackBlocks.push({
59
+ type: 'image',
60
+ image_url: imageBlock.url,
61
+ alt_text: imageBlock.caption ?? 'image',
62
+ });
63
+ }
64
+ // For documents, upload as a file instead of using blocks
65
+ if (documentBlock && documentBlock.type === 'document') {
66
+ await this.service.uploadFile(conversationId, documentBlock.url, documentBlock.filename);
67
+ }
68
+ const text = (textBlock && textBlock.type === 'text') ? textBlock.text : '';
69
+ const result = await this.service.sendMessage(conversationId, text, {
70
+ blocks: slackBlocks.length > 0 ? slackBlocks : undefined,
71
+ threadTs: content.replyToMessageId ?? undefined,
72
+ });
73
+ return { messageId: result.ts, timestamp: new Date().toISOString() };
74
+ }
75
+ async sendTypingIndicator(_conversationId, _isTyping) {
76
+ // Slack does not support bot typing indicators — no-op.
77
+ }
78
+ on(handler, eventTypes) {
79
+ this.handlers.set(handler, eventTypes);
80
+ return () => {
81
+ this.handlers.delete(handler);
82
+ };
83
+ }
84
+ async editMessage(conversationId, messageId, content) {
85
+ const textBlock = content.blocks.find((b) => b.type === 'text');
86
+ const text = (textBlock && textBlock.type === 'text') ? textBlock.text : '';
87
+ const slackBlocks = [];
88
+ if (textBlock && textBlock.type === 'text') {
89
+ slackBlocks.push({
90
+ type: 'section',
91
+ text: { type: 'mrkdwn', text: textBlock.text },
92
+ });
93
+ }
94
+ await this.service.updateMessage(conversationId, messageId, text, {
95
+ blocks: slackBlocks.length > 0 ? slackBlocks : undefined,
96
+ });
97
+ }
98
+ async deleteMessage(conversationId, messageId) {
99
+ await this.service.deleteMessage(conversationId, messageId);
100
+ }
101
+ async addReaction(conversationId, messageId, emoji) {
102
+ // Strip colons if present (e.g., ":thumbsup:" → "thumbsup")
103
+ const name = emoji.replace(/^:+|:+$/g, '');
104
+ await this.service.addReaction(conversationId, messageId, name);
105
+ }
106
+ async getConversationInfo(conversationId) {
107
+ const info = await this.service.getConversationInfo(conversationId);
108
+ return {
109
+ name: info.name,
110
+ memberCount: info.memberCount,
111
+ isGroup: info.isGroup,
112
+ metadata: {
113
+ topic: info.topic,
114
+ purpose: info.purpose,
115
+ ...info.metadata,
116
+ },
117
+ };
118
+ }
119
+ // ── Private ──
120
+ handleInboundMessage(event) {
121
+ const msg = event;
122
+ const sender = {
123
+ id: msg.user ?? 'unknown',
124
+ displayName: undefined, // Slack events don't include display name; would require users.info call
125
+ username: undefined,
126
+ };
127
+ // Determine conversation type from channel_type
128
+ let conversationType;
129
+ switch (msg.channel_type) {
130
+ case 'im':
131
+ conversationType = 'direct';
132
+ break;
133
+ case 'mpim':
134
+ case 'channel':
135
+ case 'group':
136
+ default:
137
+ conversationType = 'group';
138
+ break;
139
+ }
140
+ const channelMessage = {
141
+ messageId: msg.ts ?? msg.event_ts ?? '',
142
+ platform: 'slack',
143
+ conversationId: msg.channel ?? '',
144
+ conversationType,
145
+ sender,
146
+ content: [{ type: 'text', text: msg.text ?? '' }],
147
+ text: msg.text ?? '',
148
+ timestamp: msg.ts
149
+ ? new Date(parseFloat(msg.ts) * 1000).toISOString()
150
+ : new Date().toISOString(),
151
+ replyToMessageId: msg.thread_ts !== msg.ts ? msg.thread_ts : undefined,
152
+ rawEvent: event,
153
+ };
154
+ const channelEvent = {
155
+ type: 'message',
156
+ platform: 'slack',
157
+ conversationId: msg.channel ?? '',
158
+ timestamp: channelMessage.timestamp,
159
+ data: channelMessage,
160
+ };
161
+ this.emit(channelEvent);
162
+ }
163
+ emit(event) {
164
+ for (const [handler, filter] of this.handlers) {
165
+ if (!filter || filter.includes(event.type)) {
166
+ Promise.resolve(handler(event)).catch((err) => {
167
+ console.error('[SlackChannelAdapter] Handler error:', err);
168
+ });
169
+ }
170
+ }
171
+ }
172
+ }
173
+ exports.SlackChannelAdapter = SlackChannelAdapter;
174
+ //# sourceMappingURL=SlackChannelAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SlackChannelAdapter.js","sourceRoot":"","sources":["../src/SlackChannelAdapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * @fileoverview Slack SDK wrapper using @slack/bolt.
3
+ * Handles app lifecycle, message sending, file uploads, and event routing.
4
+ */
5
+ import type { MessageEvent } from '@slack/bolt';
6
+ export interface SlackChannelConfig {
7
+ botToken: string;
8
+ signingSecret: string;
9
+ appToken?: string;
10
+ socketMode?: boolean;
11
+ port?: number;
12
+ }
13
+ export declare class SlackService {
14
+ private app;
15
+ private running;
16
+ private messageHandlers;
17
+ private readonly config;
18
+ constructor(config: SlackChannelConfig);
19
+ initialize(): Promise<void>;
20
+ shutdown(): Promise<void>;
21
+ get isRunning(): boolean;
22
+ private get client();
23
+ onMessage(handler: (event: MessageEvent) => void): void;
24
+ offMessage(handler: (event: MessageEvent) => void): void;
25
+ sendMessage(channel: string, text: string, options?: {
26
+ blocks?: object[];
27
+ threadTs?: string;
28
+ }): Promise<{
29
+ ts: string;
30
+ channel: string;
31
+ }>;
32
+ uploadFile(channel: string, url: string, filename?: string): Promise<{
33
+ fileId: string;
34
+ }>;
35
+ updateMessage(channel: string, ts: string, text: string, options?: {
36
+ blocks?: object[];
37
+ }): Promise<void>;
38
+ deleteMessage(channel: string, ts: string): Promise<void>;
39
+ addReaction(channel: string, ts: string, name: string): Promise<void>;
40
+ getConversationInfo(channel: string): Promise<{
41
+ name?: string;
42
+ isGroup: boolean;
43
+ memberCount?: number;
44
+ topic?: string;
45
+ purpose?: string;
46
+ metadata?: Record<string, unknown>;
47
+ }>;
48
+ /**
49
+ * Slack does not support bot typing indicators natively.
50
+ * This is a no-op stub for API compatibility.
51
+ */
52
+ setTyping(_channel: string): Promise<void>;
53
+ getBotInfo(): Promise<{
54
+ userId: string;
55
+ botId?: string;
56
+ teamId?: string;
57
+ }>;
58
+ }
59
+ //# sourceMappingURL=SlackService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SlackService.d.ts","sourceRoot":"","sources":["../src/SlackService.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,GAAG,CAAoB;IAC/B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,eAAe,CAA4C;IACnE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;gBAEhC,MAAM,EAAE,kBAAkB;IAOhC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAyB3B,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAO/B,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,OAAO,KAAK,MAAM,GAGjB;IAED,SAAS,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,GAAG,IAAI;IAIvD,UAAU,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,GAAG,IAAI;IAKlD,WAAW,CACf,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;QACR,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,GACA,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAcrC,UAAU,CACd,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,EACX,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAYxB,aAAa,CACjB,OAAO,EAAE,MAAM,EACf,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,GAC9B,OAAO,CAAC,IAAI,CAAC;IASV,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOzD,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQrE,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;QAClD,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,OAAO,CAAC;QACjB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACpC,CAAC;IA0BF;;;OAGG;IACG,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI1C,UAAU,IAAI,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAQjF"}
@@ -0,0 +1,147 @@
1
+ "use strict";
2
+ /**
3
+ * @fileoverview Slack SDK wrapper using @slack/bolt.
4
+ * Handles app lifecycle, message sending, file uploads, and event routing.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.SlackService = void 0;
8
+ const bolt_1 = require("@slack/bolt");
9
+ class SlackService {
10
+ constructor(config) {
11
+ this.app = null;
12
+ this.running = false;
13
+ this.messageHandlers = [];
14
+ this.config = {
15
+ ...config,
16
+ socketMode: config.socketMode ?? !!config.appToken,
17
+ };
18
+ }
19
+ async initialize() {
20
+ if (this.running)
21
+ return;
22
+ this.app = new bolt_1.App({
23
+ token: this.config.botToken,
24
+ signingSecret: this.config.signingSecret,
25
+ socketMode: this.config.socketMode,
26
+ appToken: this.config.socketMode ? this.config.appToken : undefined,
27
+ });
28
+ // Wire up inbound message handler
29
+ this.app.message(async ({ message }) => {
30
+ // Only process standard user messages (not bot messages, changed messages, etc.)
31
+ const msg = message;
32
+ if (msg.subtype)
33
+ return;
34
+ for (const handler of this.messageHandlers) {
35
+ handler(msg);
36
+ }
37
+ });
38
+ await this.app.start(this.config.port ?? 3000);
39
+ this.running = true;
40
+ }
41
+ async shutdown() {
42
+ if (!this.running || !this.app)
43
+ return;
44
+ await this.app.stop();
45
+ this.running = false;
46
+ this.app = null;
47
+ }
48
+ get isRunning() {
49
+ return this.running;
50
+ }
51
+ get client() {
52
+ if (!this.app)
53
+ throw new Error('SlackService not initialized');
54
+ return this.app.client;
55
+ }
56
+ onMessage(handler) {
57
+ this.messageHandlers.push(handler);
58
+ }
59
+ offMessage(handler) {
60
+ const idx = this.messageHandlers.indexOf(handler);
61
+ if (idx >= 0)
62
+ this.messageHandlers.splice(idx, 1);
63
+ }
64
+ async sendMessage(channel, text, options) {
65
+ const result = await this.client.chat.postMessage({
66
+ channel,
67
+ text,
68
+ blocks: options?.blocks,
69
+ thread_ts: options?.threadTs,
70
+ });
71
+ return {
72
+ ts: result.ts,
73
+ channel: result.channel,
74
+ };
75
+ }
76
+ async uploadFile(channel, url, filename) {
77
+ const result = await this.client.files.uploadV2({
78
+ channel_id: channel,
79
+ file: url,
80
+ filename: filename ?? 'upload',
81
+ });
82
+ // files.uploadV2 returns a file object or array of file objects
83
+ const file = Array.isArray(result.files) ? result.files[0] : result.file;
84
+ return { fileId: file?.id ?? 'unknown' };
85
+ }
86
+ async updateMessage(channel, ts, text, options) {
87
+ await this.client.chat.update({
88
+ channel,
89
+ ts,
90
+ text,
91
+ blocks: options?.blocks,
92
+ });
93
+ }
94
+ async deleteMessage(channel, ts) {
95
+ await this.client.chat.delete({
96
+ channel,
97
+ ts,
98
+ });
99
+ }
100
+ async addReaction(channel, ts, name) {
101
+ await this.client.reactions.add({
102
+ channel,
103
+ timestamp: ts,
104
+ name,
105
+ });
106
+ }
107
+ async getConversationInfo(channel) {
108
+ const result = await this.client.conversations.info({ channel });
109
+ const ch = result.channel;
110
+ const isGroup = ch?.is_group || ch?.is_mpim || ch?.is_channel;
111
+ let memberCount;
112
+ if (isGroup) {
113
+ memberCount = ch?.num_members;
114
+ }
115
+ return {
116
+ name: ch?.name ?? ch?.name_normalized,
117
+ isGroup: !!isGroup,
118
+ memberCount,
119
+ topic: ch?.topic?.value,
120
+ purpose: ch?.purpose?.value,
121
+ metadata: {
122
+ is_im: ch?.is_im,
123
+ is_mpim: ch?.is_mpim,
124
+ is_channel: ch?.is_channel,
125
+ is_group: ch?.is_group,
126
+ is_private: ch?.is_private,
127
+ },
128
+ };
129
+ }
130
+ /**
131
+ * Slack does not support bot typing indicators natively.
132
+ * This is a no-op stub for API compatibility.
133
+ */
134
+ async setTyping(_channel) {
135
+ // No-op: Slack API does not expose a typing indicator for bots.
136
+ }
137
+ async getBotInfo() {
138
+ const result = await this.client.auth.test();
139
+ return {
140
+ userId: result.user_id,
141
+ botId: result.bot_id,
142
+ teamId: result.team_id,
143
+ };
144
+ }
145
+ }
146
+ exports.SlackService = SlackService;
147
+ //# sourceMappingURL=SlackService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SlackService.js","sourceRoot":"","sources":["../src/SlackService.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * @fileoverview Slack Channel Extension for AgentOS.
3
+ *
4
+ * Provides a bidirectional messaging channel adapter using @slack/bolt,
5
+ * plus ITool descriptors for programmatic message sending and file uploads.
6
+ *
7
+ * @module @framers/agentos-ext-channel-slack
8
+ */
9
+ import type { ExtensionContext, ExtensionPack } from '@framers/agentos';
10
+ import { SlackService, type SlackChannelConfig } from './SlackService';
11
+ import { SlackChannelAdapter } from './SlackChannelAdapter';
12
+ import { SlackSendMessageTool } from './tools/sendMessage';
13
+ import { SlackSendMediaTool } from './tools/sendMedia';
14
+ export interface SlackChannelOptions {
15
+ botToken?: string;
16
+ signingSecret?: string;
17
+ appToken?: string;
18
+ socketMode?: boolean;
19
+ port?: number;
20
+ priority?: number;
21
+ }
22
+ export declare function createExtensionPack(context: ExtensionContext): ExtensionPack;
23
+ export { SlackService, SlackChannelAdapter, SlackSendMessageTool, SlackSendMediaTool };
24
+ export type { SlackChannelConfig };
25
+ export default createExtensionPack;
26
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAAE,YAAY,EAAE,KAAK,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AA6CD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,gBAAgB,GAAG,aAAa,CAyC5E;AAED,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,CAAC;AACvF,YAAY,EAAE,kBAAkB,EAAE,CAAC;AACnC,eAAe,mBAAmB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ /**
3
+ * @fileoverview Slack Channel Extension for AgentOS.
4
+ *
5
+ * Provides a bidirectional messaging channel adapter using @slack/bolt,
6
+ * plus ITool descriptors for programmatic message sending and file uploads.
7
+ *
8
+ * @module @framers/agentos-ext-channel-slack
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.SlackSendMediaTool = exports.SlackSendMessageTool = exports.SlackChannelAdapter = exports.SlackService = void 0;
12
+ exports.createExtensionPack = createExtensionPack;
13
+ const SlackService_1 = require("./SlackService");
14
+ Object.defineProperty(exports, "SlackService", { enumerable: true, get: function () { return SlackService_1.SlackService; } });
15
+ const SlackChannelAdapter_1 = require("./SlackChannelAdapter");
16
+ Object.defineProperty(exports, "SlackChannelAdapter", { enumerable: true, get: function () { return SlackChannelAdapter_1.SlackChannelAdapter; } });
17
+ const sendMessage_1 = require("./tools/sendMessage");
18
+ Object.defineProperty(exports, "SlackSendMessageTool", { enumerable: true, get: function () { return sendMessage_1.SlackSendMessageTool; } });
19
+ const sendMedia_1 = require("./tools/sendMedia");
20
+ Object.defineProperty(exports, "SlackSendMediaTool", { enumerable: true, get: function () { return sendMedia_1.SlackSendMediaTool; } });
21
+ function resolveBotToken(options, secrets) {
22
+ if (options.botToken)
23
+ return options.botToken;
24
+ // Check secrets map from registry
25
+ if (secrets?.['slack.botToken'])
26
+ return secrets['slack.botToken'];
27
+ // Environment variable fallback
28
+ const envValue = process.env['SLACK_BOT_TOKEN'];
29
+ if (envValue)
30
+ return envValue;
31
+ throw new Error('Slack bot token not found. Provide via options.botToken, secrets["slack.botToken"], or SLACK_BOT_TOKEN env var.');
32
+ }
33
+ function resolveSigningSecret(options, secrets) {
34
+ if (options.signingSecret)
35
+ return options.signingSecret;
36
+ // Check secrets map from registry
37
+ if (secrets?.['slack.signingSecret'])
38
+ return secrets['slack.signingSecret'];
39
+ // Environment variable fallback
40
+ const envValue = process.env['SLACK_SIGNING_SECRET'];
41
+ if (envValue)
42
+ return envValue;
43
+ throw new Error('Slack signing secret not found. Provide via options.signingSecret, secrets["slack.signingSecret"], or SLACK_SIGNING_SECRET env var.');
44
+ }
45
+ function resolveAppToken(options, secrets) {
46
+ if (options.appToken)
47
+ return options.appToken;
48
+ // Check secrets map from registry
49
+ if (secrets?.['slack.appToken'])
50
+ return secrets['slack.appToken'];
51
+ // Environment variable fallback
52
+ const envValue = process.env['SLACK_APP_TOKEN'];
53
+ if (envValue)
54
+ return envValue;
55
+ return undefined;
56
+ }
57
+ function createExtensionPack(context) {
58
+ const options = (context.options ?? {});
59
+ const botToken = resolveBotToken(options, options.secrets);
60
+ const signingSecret = resolveSigningSecret(options, options.secrets);
61
+ const appToken = resolveAppToken(options, options.secrets);
62
+ const config = {
63
+ botToken,
64
+ signingSecret,
65
+ appToken,
66
+ socketMode: options.socketMode ?? !!appToken,
67
+ port: options.port,
68
+ };
69
+ const service = new SlackService_1.SlackService(config);
70
+ const adapter = new SlackChannelAdapter_1.SlackChannelAdapter(service);
71
+ const sendMessageTool = new sendMessage_1.SlackSendMessageTool(service);
72
+ const sendMediaTool = new sendMedia_1.SlackSendMediaTool(service);
73
+ const priority = options.priority ?? 50;
74
+ return {
75
+ name: '@framers/agentos-ext-channel-slack',
76
+ version: '0.1.0',
77
+ descriptors: [
78
+ { id: 'slackChannelSendMessage', kind: 'tool', priority, payload: sendMessageTool },
79
+ { id: 'slackChannelSendMedia', kind: 'tool', priority, payload: sendMediaTool },
80
+ { id: 'slackChannel', kind: 'messaging-channel', priority, payload: adapter },
81
+ ],
82
+ onActivate: async () => {
83
+ await service.initialize();
84
+ // Wire adapter event listeners after service is running
85
+ await adapter.initialize({ platform: 'slack', credential: botToken });
86
+ context.logger?.info('[SlackChannel] Extension activated');
87
+ },
88
+ onDeactivate: async () => {
89
+ await adapter.shutdown();
90
+ await service.shutdown();
91
+ context.logger?.info('[SlackChannel] Extension deactivated');
92
+ },
93
+ };
94
+ }
95
+ exports.default = createExtensionPack;
96
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * @fileoverview ITool for uploading files via the Slack channel adapter.
3
+ */
4
+ import type { ITool, ToolExecutionContext, ToolExecutionResult } from '@framers/agentos';
5
+ import type { SlackService } from '../SlackService';
6
+ export declare class SlackSendMediaTool implements ITool {
7
+ private readonly service;
8
+ readonly id = "slackChannelSendMedia";
9
+ readonly name = "slackChannelSendMedia";
10
+ readonly displayName = "Send Slack Media";
11
+ readonly description = "Upload a file to a Slack channel via the channel adapter.";
12
+ readonly category = "communication";
13
+ readonly version = "0.1.0";
14
+ readonly hasSideEffects = true;
15
+ readonly inputSchema: {
16
+ type: "object";
17
+ required: readonly ["channel", "url"];
18
+ properties: {
19
+ channel: {
20
+ type: string;
21
+ description: string;
22
+ };
23
+ url: {
24
+ type: string;
25
+ description: string;
26
+ };
27
+ filename: {
28
+ type: string;
29
+ description: string;
30
+ };
31
+ };
32
+ };
33
+ readonly outputSchema: {
34
+ type: "object";
35
+ properties: {
36
+ fileId: {
37
+ type: string;
38
+ description: string;
39
+ };
40
+ };
41
+ };
42
+ constructor(service: SlackService);
43
+ execute(args: {
44
+ channel: string;
45
+ url: string;
46
+ filename?: string;
47
+ }, _context: ToolExecutionContext): Promise<ToolExecutionResult>;
48
+ validateArgs(args: Record<string, any>): {
49
+ isValid: boolean;
50
+ errors?: string[];
51
+ };
52
+ }
53
+ //# sourceMappingURL=sendMedia.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sendMedia.d.ts","sourceRoot":"","sources":["../../src/tools/sendMedia.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACzF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEpD,qBAAa,kBAAmB,YAAW,KAAK;IA0BlC,OAAO,CAAC,QAAQ,CAAC,OAAO;IAzBpC,SAAgB,EAAE,2BAA2B;IAC7C,SAAgB,IAAI,2BAA2B;IAC/C,SAAgB,WAAW,sBAAsB;IACjD,SAAgB,WAAW,+DAA+D;IAC1F,SAAgB,QAAQ,mBAAmB;IAC3C,SAAgB,OAAO,WAAW;IAClC,SAAgB,cAAc,QAAQ;IAEtC,SAAgB,WAAW;;;;;;;;;;;;;;;;;MAQzB;IAEF,SAAgB,YAAY;;;;;;;;MAK1B;gBAE2B,OAAO,EAAE,YAAY;IAE5C,OAAO,CACX,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,EACzD,QAAQ,EAAE,oBAAoB,GAC7B,OAAO,CAAC,mBAAmB,CAAC;IAU/B,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE;CAMjF"}
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ /**
3
+ * @fileoverview ITool for uploading files via the Slack channel adapter.
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.SlackSendMediaTool = void 0;
7
+ class SlackSendMediaTool {
8
+ constructor(service) {
9
+ this.service = service;
10
+ this.id = 'slackChannelSendMedia';
11
+ this.name = 'slackChannelSendMedia';
12
+ this.displayName = 'Send Slack Media';
13
+ this.description = 'Upload a file to a Slack channel via the channel adapter.';
14
+ this.category = 'communication';
15
+ this.version = '0.1.0';
16
+ this.hasSideEffects = true;
17
+ this.inputSchema = {
18
+ type: 'object',
19
+ required: ['channel', 'url'],
20
+ properties: {
21
+ channel: { type: 'string', description: 'Target channel ID (e.g., C0123456789)' },
22
+ url: { type: 'string', description: 'URL or local path of the file to upload' },
23
+ filename: { type: 'string', description: 'Optional filename for the upload' },
24
+ },
25
+ };
26
+ this.outputSchema = {
27
+ type: 'object',
28
+ properties: {
29
+ fileId: { type: 'string', description: 'ID of the uploaded file' },
30
+ },
31
+ };
32
+ }
33
+ async execute(args, _context) {
34
+ try {
35
+ const result = await this.service.uploadFile(args.channel, args.url, args.filename);
36
+ return { success: true, output: { fileId: result.fileId } };
37
+ }
38
+ catch (error) {
39
+ return { success: false, error: error.message };
40
+ }
41
+ }
42
+ validateArgs(args) {
43
+ const errors = [];
44
+ if (!args.channel)
45
+ errors.push('channel is required');
46
+ if (!args.url)
47
+ errors.push('url is required');
48
+ return { isValid: errors.length === 0, errors };
49
+ }
50
+ }
51
+ exports.SlackSendMediaTool = SlackSendMediaTool;
52
+ //# sourceMappingURL=sendMedia.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sendMedia.js","sourceRoot":"","sources":["../../src/tools/sendMedia.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAKH,MAAa,kBAAkB;IA0B7B,YAA6B,OAAqB;QAArB,YAAO,GAAP,OAAO,CAAc;QAzBlC,OAAE,GAAG,uBAAuB,CAAC;QAC7B,SAAI,GAAG,uBAAuB,CAAC;QAC/B,gBAAW,GAAG,kBAAkB,CAAC;QACjC,gBAAW,GAAG,2DAA2D,CAAC;QAC1E,aAAQ,GAAG,eAAe,CAAC;QAC3B,YAAO,GAAG,OAAO,CAAC;QAClB,mBAAc,GAAG,IAAI,CAAC;QAEtB,gBAAW,GAAG;YAC5B,IAAI,EAAE,QAAiB;YACvB,QAAQ,EAAE,CAAC,SAAS,EAAE,KAAK,CAAU;YACrC,UAAU,EAAE;gBACV,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,uCAAuC,EAAE;gBACjF,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,yCAAyC,EAAE;gBAC/E,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,kCAAkC,EAAE;aAC9E;SACF,CAAC;QAEc,iBAAY,GAAG;YAC7B,IAAI,EAAE,QAAiB;YACvB,UAAU,EAAE;gBACV,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,yBAAyB,EAAE;aACnE;SACF,CAAC;IAEmD,CAAC;IAEtD,KAAK,CAAC,OAAO,CACX,IAAyD,EACzD,QAA8B;QAE9B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;YAEpF,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;QAC9D,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;QAClD,CAAC;IACH,CAAC;IAED,YAAY,CAAC,IAAyB;QACpC,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,MAAM,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;QACtD,IAAI,CAAC,IAAI,CAAC,GAAG;YAAE,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IAClD,CAAC;CACF;AA/CD,gDA+CC"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * @fileoverview ITool for sending text messages via the Slack channel adapter.
3
+ */
4
+ import type { ITool, ToolExecutionContext, ToolExecutionResult } from '@framers/agentos';
5
+ import type { SlackService } from '../SlackService';
6
+ export declare class SlackSendMessageTool implements ITool {
7
+ private readonly service;
8
+ readonly id = "slackChannelSendMessage";
9
+ readonly name = "slackChannelSendMessage";
10
+ readonly displayName = "Send Slack Message";
11
+ readonly description = "Send a text message to a Slack channel or conversation via the channel adapter.";
12
+ readonly category = "communication";
13
+ readonly version = "0.1.0";
14
+ readonly hasSideEffects = true;
15
+ readonly inputSchema: {
16
+ type: "object";
17
+ required: readonly ["channel", "text"];
18
+ properties: {
19
+ channel: {
20
+ type: string;
21
+ description: string;
22
+ };
23
+ text: {
24
+ type: string;
25
+ description: string;
26
+ };
27
+ blocks: {
28
+ type: string;
29
+ description: string;
30
+ };
31
+ threadTs: {
32
+ type: string;
33
+ description: string;
34
+ };
35
+ };
36
+ };
37
+ readonly outputSchema: {
38
+ type: "object";
39
+ properties: {
40
+ ts: {
41
+ type: string;
42
+ description: string;
43
+ };
44
+ channel: {
45
+ type: string;
46
+ description: string;
47
+ };
48
+ };
49
+ };
50
+ constructor(service: SlackService);
51
+ execute(args: {
52
+ channel: string;
53
+ text: string;
54
+ blocks?: object[];
55
+ threadTs?: string;
56
+ }, _context: ToolExecutionContext): Promise<ToolExecutionResult>;
57
+ validateArgs(args: Record<string, any>): {
58
+ isValid: boolean;
59
+ errors?: string[];
60
+ };
61
+ }
62
+ //# sourceMappingURL=sendMessage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sendMessage.d.ts","sourceRoot":"","sources":["../../src/tools/sendMessage.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACzF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEpD,qBAAa,oBAAqB,YAAW,KAAK;IA4BpC,OAAO,CAAC,QAAQ,CAAC,OAAO;IA3BpC,SAAgB,EAAE,6BAA6B;IAC/C,SAAgB,IAAI,6BAA6B;IACjD,SAAgB,WAAW,wBAAwB;IACnD,SAAgB,WAAW,qFAAqF;IAChH,SAAgB,QAAQ,mBAAmB;IAC3C,SAAgB,OAAO,WAAW;IAClC,SAAgB,cAAc,QAAQ;IAEtC,SAAgB,WAAW;;;;;;;;;;;;;;;;;;;;;MASzB;IAEF,SAAgB,YAAY;;;;;;;;;;;;MAM1B;gBAE2B,OAAO,EAAE,YAAY;IAE5C,OAAO,CACX,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,EAC7E,QAAQ,EAAE,oBAAoB,GAC7B,OAAO,CAAC,mBAAmB,CAAC;IAgB/B,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE;CAOjF"}
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ /**
3
+ * @fileoverview ITool for sending text messages via the Slack channel adapter.
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.SlackSendMessageTool = void 0;
7
+ class SlackSendMessageTool {
8
+ constructor(service) {
9
+ this.service = service;
10
+ this.id = 'slackChannelSendMessage';
11
+ this.name = 'slackChannelSendMessage';
12
+ this.displayName = 'Send Slack Message';
13
+ this.description = 'Send a text message to a Slack channel or conversation via the channel adapter.';
14
+ this.category = 'communication';
15
+ this.version = '0.1.0';
16
+ this.hasSideEffects = true;
17
+ this.inputSchema = {
18
+ type: 'object',
19
+ required: ['channel', 'text'],
20
+ properties: {
21
+ channel: { type: 'string', description: 'Target channel ID (e.g., C0123456789)' },
22
+ text: { type: 'string', description: 'Message text (fallback for clients that cannot render blocks)' },
23
+ blocks: { type: 'array', description: 'Optional Slack Block Kit blocks for rich formatting' },
24
+ threadTs: { type: 'string', description: 'Thread timestamp to reply in a thread' },
25
+ },
26
+ };
27
+ this.outputSchema = {
28
+ type: 'object',
29
+ properties: {
30
+ ts: { type: 'string', description: 'Timestamp ID of the sent message' },
31
+ channel: { type: 'string', description: 'Channel the message was sent to' },
32
+ },
33
+ };
34
+ }
35
+ async execute(args, _context) {
36
+ try {
37
+ const result = await this.service.sendMessage(args.channel, args.text, {
38
+ blocks: args.blocks,
39
+ threadTs: args.threadTs,
40
+ });
41
+ return {
42
+ success: true,
43
+ output: { ts: result.ts, channel: result.channel },
44
+ };
45
+ }
46
+ catch (error) {
47
+ return { success: false, error: error.message };
48
+ }
49
+ }
50
+ validateArgs(args) {
51
+ const errors = [];
52
+ if (!args.channel)
53
+ errors.push('channel is required');
54
+ if (!args.text)
55
+ errors.push('text is required');
56
+ else if (typeof args.text !== 'string')
57
+ errors.push('text must be a string');
58
+ return { isValid: errors.length === 0, errors };
59
+ }
60
+ }
61
+ exports.SlackSendMessageTool = SlackSendMessageTool;
62
+ //# sourceMappingURL=sendMessage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sendMessage.js","sourceRoot":"","sources":["../../src/tools/sendMessage.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAKH,MAAa,oBAAoB;IA4B/B,YAA6B,OAAqB;QAArB,YAAO,GAAP,OAAO,CAAc;QA3BlC,OAAE,GAAG,yBAAyB,CAAC;QAC/B,SAAI,GAAG,yBAAyB,CAAC;QACjC,gBAAW,GAAG,oBAAoB,CAAC;QACnC,gBAAW,GAAG,iFAAiF,CAAC;QAChG,aAAQ,GAAG,eAAe,CAAC;QAC3B,YAAO,GAAG,OAAO,CAAC;QAClB,mBAAc,GAAG,IAAI,CAAC;QAEtB,gBAAW,GAAG;YAC5B,IAAI,EAAE,QAAiB;YACvB,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,CAAU;YACtC,UAAU,EAAE;gBACV,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,uCAAuC,EAAE;gBACjF,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,+DAA+D,EAAE;gBACtG,MAAM,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,qDAAqD,EAAE;gBAC7F,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,uCAAuC,EAAE;aACnF;SACF,CAAC;QAEc,iBAAY,GAAG;YAC7B,IAAI,EAAE,QAAiB;YACvB,UAAU,EAAE;gBACV,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,kCAAkC,EAAE;gBACvE,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,iCAAiC,EAAE;aAC5E;SACF,CAAC;IAEmD,CAAC;IAEtD,KAAK,CAAC,OAAO,CACX,IAA6E,EAC7E,QAA8B;QAE9B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,EAAE;gBACrE,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ;aACxB,CAAC,CAAC;YAEH,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE;aACnD,CAAC;QACJ,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;QAClD,CAAC;IACH,CAAC;IAED,YAAY,CAAC,IAAyB;QACpC,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,MAAM,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;QACtD,IAAI,CAAC,IAAI,CAAC,IAAI;YAAE,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;aAC3C,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ;YAAE,MAAM,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;QAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IAClD,CAAC;CACF;AAxDD,oDAwDC"}
package/manifest.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "$schema": "https://agentos.sh/schemas/extension-manifest-v1.json",
3
+ "id": "com.framers.channels.slack",
4
+ "name": "Slack Channel Extension",
5
+ "version": "0.1.0",
6
+ "description": "Bidirectional Slack messaging via @slack/bolt — supports text, rich text, images, documents, threads, reactions, and group chat.",
7
+ "categories": ["channel", "communication"],
8
+ "platforms": ["slack"],
9
+ "sdk": "@slack/bolt",
10
+ "extensions": [
11
+ {
12
+ "kind": "tool",
13
+ "id": "slackChannelSendMessage",
14
+ "displayName": "Send Slack Message"
15
+ },
16
+ {
17
+ "kind": "tool",
18
+ "id": "slackChannelSendMedia",
19
+ "displayName": "Send Slack Media"
20
+ },
21
+ {
22
+ "kind": "messaging-channel",
23
+ "id": "slackChannel",
24
+ "displayName": "Slack Channel Adapter"
25
+ }
26
+ ],
27
+ "requiredSecrets": [
28
+ "slack.botToken",
29
+ "slack.signingSecret",
30
+ "slack.appToken"
31
+ ],
32
+ "features": [
33
+ "Text messages with rich text formatting",
34
+ "Block Kit message layouts",
35
+ "File uploads via files.uploadV2",
36
+ "Socket Mode and HTTP support",
37
+ "Thread replies via thread_ts",
38
+ "Group chat and channel support",
39
+ "Message editing and deletion",
40
+ "Emoji reactions",
41
+ "Mentions support"
42
+ ]
43
+ }
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@framers/agentos-ext-channel-slack",
3
+ "version": "0.1.0",
4
+ "description": "Slack messaging channel adapter for AgentOS — bidirectional messaging via @slack/bolt",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "scripts": {
8
+ "build": "tsc",
9
+ "dev": "tsc --watch",
10
+ "test": "vitest run",
11
+ "test:watch": "vitest watch",
12
+ "clean": "rm -rf dist"
13
+ },
14
+ "keywords": ["agentos", "extension", "channel", "slack", "bolt", "messaging"],
15
+ "author": { "name": "Framers AI", "url": "https://frame.dev" },
16
+ "license": "MIT",
17
+ "files": ["dist", "manifest.json"],
18
+ "peerDependencies": {
19
+ "@framers/agentos": "^0.1.0"
20
+ },
21
+ "dependencies": {
22
+ "@slack/bolt": "^3.17.0"
23
+ },
24
+ "devDependencies": {
25
+ "@framers/agentos": "workspace:*",
26
+ "@types/node": "^20.0.0",
27
+ "typescript": "^5.0.0",
28
+ "vitest": "^1.0.0"
29
+ },
30
+ "engines": { "node": ">=18.0.0" }
31
+ }