@openclaw/slack 2026.9.1 → 2026.9.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/dist/{action-runtime-DND4Pyp2.js → action-runtime-DftQWpI4.js} +4 -4
- package/dist/action-runtime.runtime-rHI3UAh4.js +2 -0
- package/dist/{actions-fh66A6lc.js → actions-CFkvEv1d.js} +3 -3
- package/dist/api.js +9 -9
- package/dist/{approval-handler.runtime-D7d8sKM0.js → approval-handler.runtime-BeILKdw4.js} +31 -15
- package/dist/{channel-4m8IAdMD.js → channel-CmOuxbOD.js} +24 -23
- package/dist/channel-config-api.js +1 -1
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel-type-3-SqEMVc.js → channel-type-BWt2CRaI.js} +2 -2
- package/dist/{channel.setup-t_ghLGb_.js → channel.setup-D5z1ReaT.js} +8 -3
- package/dist/{config-schema-bP3eV2ra.js → config-schema-JDx_f9Zb.js} +2 -2
- package/dist/{directory-live-q32AW7N1.js → directory-live-BuBPHmju.js} +1 -1
- package/dist/{monitor-Chwu_SiZ.js → monitor-DI07pfJl.js} +3 -3
- package/dist/{outbound-adapter-BB8wAjm5.js → outbound-adapter-B5QyTRpJ.js} +3 -2
- package/dist/{pipeline.runtime-BklS_NEj.js → pipeline.runtime-BdIwZgm4.js} +567 -733
- package/dist/{policy-D7PKkiet.js → policy-Bh5TOqII.js} +2 -2
- package/dist/{probe-gj5yQgN2.js → probe-Biy--yhL.js} +42 -10
- package/dist/{provider-Do50wMWn.js → provider-DoaUvAM4.js} +5583 -4921
- package/dist/{relay-source-DWuduiJ2.js → relay-source-D4uecp68.js} +1 -1
- package/dist/{replies-Dc6WVh_Q.js → replies-DENuTcPO.js} +4 -3
- package/dist/reply-blocks-PRkhyAN7.js +790 -0
- package/dist/{resolve-channels-CU7Bg5Ka.js → resolve-channels-DQGV2VrE.js} +1 -1
- package/dist/{resolve-users-DrhttvRQ.js → resolve-users-DRGt_Q4I.js} +1 -1
- package/dist/runtime-api.js +10 -10
- package/dist/{scopes-B9HRguDe.js → scopes-CZzeGdWV.js} +1 -1
- package/dist/{send-Djswy6lf.js → send-DElUcgIs.js} +10 -10
- package/dist/{send.runtime-__WVTWLQ.js → send.runtime-C8D6cKGm.js} +1 -1
- package/dist/{group-policy-BKjMqT-8.js → session-status-BynwcZSO.js} +169 -799
- package/dist/setup-plugin-api.js +1 -1
- package/dist/{setup-surface-DO0e-MMS.js → setup-surface-B1_gpGBl.js} +4 -4
- package/dist/{shared-DEQBEKBL.js → shared-CNQsWJT7.js} +2 -2
- package/dist/{slash-dispatch.runtime-C3B4h5ZM.js → slash-dispatch.runtime-DhsXavSY.js} +1 -1
- package/node_modules/typebox/build/format/json_pointer.d.mts +2 -2
- package/node_modules/typebox/build/format/json_pointer.mjs +2 -2
- package/node_modules/typebox/build/format/json_pointer_uri_fragment.d.mts +2 -2
- package/node_modules/typebox/build/format/json_pointer_uri_fragment.mjs +2 -2
- package/node_modules/typebox/build/format/relative_json_pointer.d.mts +2 -2
- package/node_modules/typebox/build/format/relative_json_pointer.mjs +2 -2
- package/node_modules/typebox/build/system/memory/assign.mjs +2 -1
- package/node_modules/typebox/build/system/memory/create.mjs +3 -4
- package/node_modules/typebox/build/system/memory/discard.mjs +2 -2
- package/node_modules/typebox/build/system/memory/freeze.d.mts +4 -0
- package/node_modules/typebox/build/system/memory/freeze.mjs +6 -0
- package/node_modules/typebox/build/system/memory/update.mjs +3 -2
- package/node_modules/typebox/package.json +1 -1
- package/node_modules/undici/lib/dispatcher/balanced-pool.js +4 -2
- package/node_modules/undici/lib/dispatcher/client-h1.js +12 -4
- package/node_modules/undici/lib/dispatcher/client-h2.js +70 -14
- package/node_modules/undici/lib/dispatcher/client.js +6 -2
- package/node_modules/undici/lib/handler/cache-handler.js +21 -5
- package/node_modules/undici/lib/handler/retry-handler.js +42 -7
- package/node_modules/undici/lib/interceptor/cache.js +20 -1
- package/node_modules/undici/lib/interceptor/decompress.js +146 -14
- package/node_modules/undici/lib/interceptor/dump.js +10 -23
- package/node_modules/undici/lib/web/eventsource/eventsource-stream.js +245 -150
- package/node_modules/undici/lib/web/websocket/connection.js +1 -1
- package/node_modules/undici/lib/web/websocket/permessage-deflate.js +5 -0
- package/node_modules/undici/lib/web/websocket/stream/websocketstream.js +8 -10
- package/node_modules/undici/package.json +1 -1
- package/node_modules/undici/types/interceptors.d.ts +2 -0
- package/openclaw.plugin.json +3 -3
- package/package.json +6 -6
- package/skills/_vendor/slack-skills-plugin.LICENSE +21 -0
- package/skills/_vendor/slack-skills-plugin.json +31 -0
- package/skills/block-kit/SKILL.md +37 -0
- package/skills/block-kit/references/official-block-kit.md +257 -0
- package/skills/block-kit/references/official-common-patterns.md +385 -0
- package/skills/slack/SKILL.md +1 -1
- package/dist/action-runtime.runtime-CEhbmS-Z.js +0 -2
- package/dist/conversation-binding-route-Vee8Dgbf.js +0 -115
|
@@ -23,6 +23,49 @@ const COLON = 0x3A
|
|
|
23
23
|
*/
|
|
24
24
|
const SPACE = 0x20
|
|
25
25
|
|
|
26
|
+
const DATA = Buffer.from('data')
|
|
27
|
+
const EVENT = Buffer.from('event')
|
|
28
|
+
const ID = Buffer.from('id')
|
|
29
|
+
const RETRY = Buffer.from('retry')
|
|
30
|
+
|
|
31
|
+
function isASCIINumberBytes (buffer, start) {
|
|
32
|
+
if (start >= buffer.length) {
|
|
33
|
+
return false
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
for (let i = start; i < buffer.length; i++) {
|
|
37
|
+
if (buffer[i] < 0x30 || buffer[i] > 0x39) {
|
|
38
|
+
return false
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return true
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function isValidLastEventIdBytes (buffer, start) {
|
|
46
|
+
for (let i = start; i < buffer.length; i++) {
|
|
47
|
+
if (buffer[i] === 0x00) {
|
|
48
|
+
return false
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return true
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function isFieldName (line, length, field) {
|
|
56
|
+
if (length !== field.length) {
|
|
57
|
+
return false
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
for (let i = 0; i < length; i++) {
|
|
61
|
+
if (line[i] !== field[i]) {
|
|
62
|
+
return false
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return true
|
|
67
|
+
}
|
|
68
|
+
|
|
26
69
|
/**
|
|
27
70
|
* @typedef {object} EventSourceStreamEvent
|
|
28
71
|
* @type {object}
|
|
@@ -63,11 +106,14 @@ class EventSourceStream extends Transform {
|
|
|
63
106
|
eventEndCheck = false
|
|
64
107
|
|
|
65
108
|
/**
|
|
66
|
-
* @type {Buffer
|
|
109
|
+
* @type {Buffer[]}
|
|
67
110
|
*/
|
|
68
|
-
|
|
111
|
+
chunks = []
|
|
69
112
|
|
|
113
|
+
chunkIndex = 0
|
|
70
114
|
pos = 0
|
|
115
|
+
lineChunkIndex = 0
|
|
116
|
+
linePos = 0
|
|
71
117
|
|
|
72
118
|
event = {
|
|
73
119
|
data: undefined,
|
|
@@ -107,92 +153,20 @@ class EventSourceStream extends Transform {
|
|
|
107
153
|
return
|
|
108
154
|
}
|
|
109
155
|
|
|
110
|
-
|
|
111
|
-
// processing it
|
|
112
|
-
// TODO: Investigate if there is a more performant way to handle
|
|
113
|
-
// incoming chunks
|
|
114
|
-
// see: https://github.com/nodejs/undici/issues/2630
|
|
115
|
-
if (this.buffer) {
|
|
116
|
-
this.buffer = Buffer.concat([this.buffer, chunk])
|
|
117
|
-
} else {
|
|
118
|
-
this.buffer = chunk
|
|
119
|
-
}
|
|
156
|
+
this.chunks.push(chunk)
|
|
120
157
|
|
|
121
158
|
// Strip leading byte-order-mark if we opened the stream and started
|
|
122
159
|
// the processing of the incoming data
|
|
123
160
|
if (this.checkBOM) {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
if (this.buffer[0] === BOM[0]) {
|
|
128
|
-
// If it is, we need to wait for more data
|
|
129
|
-
callback()
|
|
130
|
-
return
|
|
131
|
-
}
|
|
132
|
-
// Set the checkBOM flag to false as we don't need to check for the
|
|
133
|
-
// BOM anymore
|
|
134
|
-
this.checkBOM = false
|
|
135
|
-
|
|
136
|
-
// The buffer only contains one byte so we need to wait for more data
|
|
137
|
-
callback()
|
|
138
|
-
return
|
|
139
|
-
case 2:
|
|
140
|
-
// Check if the first two bytes are the same as the first two bytes
|
|
141
|
-
// of the BOM
|
|
142
|
-
if (
|
|
143
|
-
this.buffer[0] === BOM[0] &&
|
|
144
|
-
this.buffer[1] === BOM[1]
|
|
145
|
-
) {
|
|
146
|
-
// If it is, we need to wait for more data, because the third byte
|
|
147
|
-
// is needed to determine if it is the BOM or not
|
|
148
|
-
callback()
|
|
149
|
-
return
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// Set the checkBOM flag to false as we don't need to check for the
|
|
153
|
-
// BOM anymore
|
|
154
|
-
this.checkBOM = false
|
|
155
|
-
break
|
|
156
|
-
case 3:
|
|
157
|
-
// Check if the first three bytes are the same as the first three
|
|
158
|
-
// bytes of the BOM
|
|
159
|
-
if (
|
|
160
|
-
this.buffer[0] === BOM[0] &&
|
|
161
|
-
this.buffer[1] === BOM[1] &&
|
|
162
|
-
this.buffer[2] === BOM[2]
|
|
163
|
-
) {
|
|
164
|
-
// If it is, we can drop the buffered data, as it is only the BOM
|
|
165
|
-
this.buffer = Buffer.alloc(0)
|
|
166
|
-
// Set the checkBOM flag to false as we don't need to check for the
|
|
167
|
-
// BOM anymore
|
|
168
|
-
this.checkBOM = false
|
|
169
|
-
|
|
170
|
-
// Await more data
|
|
171
|
-
callback()
|
|
172
|
-
return
|
|
173
|
-
}
|
|
174
|
-
// If it is not the BOM, we can start processing the data
|
|
175
|
-
this.checkBOM = false
|
|
176
|
-
break
|
|
177
|
-
default:
|
|
178
|
-
// The buffer is longer than 3 bytes, so we can drop the BOM if it is
|
|
179
|
-
// present
|
|
180
|
-
if (
|
|
181
|
-
this.buffer[0] === BOM[0] &&
|
|
182
|
-
this.buffer[1] === BOM[1] &&
|
|
183
|
-
this.buffer[2] === BOM[2]
|
|
184
|
-
) {
|
|
185
|
-
// Remove the BOM from the buffer
|
|
186
|
-
this.buffer = this.buffer.subarray(3)
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// Set the checkBOM flag to false as we don't need to check for the
|
|
190
|
-
this.checkBOM = false
|
|
191
|
-
break
|
|
161
|
+
if (this.handleBOM()) {
|
|
162
|
+
callback()
|
|
163
|
+
return
|
|
192
164
|
}
|
|
193
165
|
}
|
|
194
166
|
|
|
195
|
-
while (this.
|
|
167
|
+
while (this.hasCurrentByte()) {
|
|
168
|
+
const byte = this.currentByte()
|
|
169
|
+
|
|
196
170
|
// If the previous line ended with an end-of-line, we need to check
|
|
197
171
|
// if the next character is also an end-of-line.
|
|
198
172
|
if (this.eventEndCheck) {
|
|
@@ -205,10 +179,9 @@ class EventSourceStream extends Transform {
|
|
|
205
179
|
if (this.crlfCheck) {
|
|
206
180
|
// If the current character is a line feed, we can remove it
|
|
207
181
|
// from the buffer and reset the crlfCheck flag
|
|
208
|
-
if (
|
|
209
|
-
this.buffer = this.buffer.subarray(this.pos + 1)
|
|
210
|
-
this.pos = 0
|
|
182
|
+
if (byte === LF) {
|
|
211
183
|
this.crlfCheck = false
|
|
184
|
+
this.consumeCurrentByte()
|
|
212
185
|
|
|
213
186
|
// It is possible that the line feed is not the end of the
|
|
214
187
|
// event. We need to check if the next character is an
|
|
@@ -224,19 +197,17 @@ class EventSourceStream extends Transform {
|
|
|
224
197
|
this.crlfCheck = false
|
|
225
198
|
}
|
|
226
199
|
|
|
227
|
-
if (
|
|
200
|
+
if (byte === LF || byte === CR) {
|
|
228
201
|
// If the current character is a carriage return, we need to
|
|
229
202
|
// set the crlfCheck flag to true, as we need to check if the
|
|
230
203
|
// next character is a line feed so we can remove it from the
|
|
231
204
|
// buffer
|
|
232
|
-
if (
|
|
205
|
+
if (byte === CR) {
|
|
233
206
|
this.crlfCheck = true
|
|
234
207
|
}
|
|
235
208
|
|
|
236
|
-
this.
|
|
237
|
-
this.
|
|
238
|
-
if (
|
|
239
|
-
this.event.data !== undefined || this.event.event || this.event.id !== undefined || this.event.retry) {
|
|
209
|
+
this.consumeCurrentByte()
|
|
210
|
+
if (this.hasPendingEvent()) {
|
|
240
211
|
this.processEvent(this.event)
|
|
241
212
|
}
|
|
242
213
|
this.clearEvent()
|
|
@@ -250,22 +221,18 @@ class EventSourceStream extends Transform {
|
|
|
250
221
|
|
|
251
222
|
// If the current character is an end-of-line, we can process the
|
|
252
223
|
// line
|
|
253
|
-
if (
|
|
224
|
+
if (byte === LF || byte === CR) {
|
|
254
225
|
// If the current character is a carriage return, we need to
|
|
255
226
|
// set the crlfCheck flag to true, as we need to check if the
|
|
256
227
|
// next character is a line feed
|
|
257
|
-
if (
|
|
228
|
+
if (byte === CR) {
|
|
258
229
|
this.crlfCheck = true
|
|
259
230
|
}
|
|
260
231
|
|
|
261
232
|
// In any case, we can process the line as we reached an
|
|
262
233
|
// end-of-line character
|
|
263
|
-
this.parseLine(this.
|
|
264
|
-
|
|
265
|
-
// Remove the processed line from the buffer
|
|
266
|
-
this.buffer = this.buffer.subarray(this.pos + 1)
|
|
267
|
-
// Reset the position as we removed the processed line from the buffer
|
|
268
|
-
this.pos = 0
|
|
234
|
+
this.parseLine(this.readLine(), this.event)
|
|
235
|
+
this.consumeCurrentByte()
|
|
269
236
|
// A line was processed and this could be the end of the event. We need
|
|
270
237
|
// to check if the next line is empty to determine if the event is
|
|
271
238
|
// finished.
|
|
@@ -273,7 +240,7 @@ class EventSourceStream extends Transform {
|
|
|
273
240
|
continue
|
|
274
241
|
}
|
|
275
242
|
|
|
276
|
-
this.
|
|
243
|
+
this.advanceCursor()
|
|
277
244
|
}
|
|
278
245
|
|
|
279
246
|
callback()
|
|
@@ -298,64 +265,53 @@ class EventSourceStream extends Transform {
|
|
|
298
265
|
return
|
|
299
266
|
}
|
|
300
267
|
|
|
301
|
-
let
|
|
302
|
-
let
|
|
268
|
+
let fieldLength = line.length
|
|
269
|
+
let valueStart = line.length
|
|
303
270
|
|
|
304
271
|
// If the line contains a U+003A COLON character (:)
|
|
305
272
|
if (colonPosition !== -1) {
|
|
306
|
-
|
|
307
|
-
// character (:), and let field be that string.
|
|
308
|
-
// TODO: Investigate if there is a more performant way to extract the
|
|
309
|
-
// field
|
|
310
|
-
// see: https://github.com/nodejs/undici/issues/2630
|
|
311
|
-
field = line.subarray(0, colonPosition).toString('utf8')
|
|
273
|
+
fieldLength = colonPosition
|
|
312
274
|
|
|
313
275
|
// Collect the characters on the line after the first U+003A COLON
|
|
314
276
|
// character (:), and let value be that string.
|
|
315
277
|
// If value starts with a U+0020 SPACE character, remove it from value.
|
|
316
|
-
|
|
278
|
+
valueStart = colonPosition + 1
|
|
317
279
|
if (line[valueStart] === SPACE) {
|
|
318
280
|
++valueStart
|
|
319
281
|
}
|
|
320
|
-
// TODO: Investigate if there is a more performant way to extract the
|
|
321
|
-
// value
|
|
322
|
-
// see: https://github.com/nodejs/undici/issues/2630
|
|
323
|
-
value = line.subarray(valueStart).toString('utf8')
|
|
324
|
-
|
|
325
|
-
// Otherwise, the string is not empty but does not contain a U+003A COLON
|
|
326
|
-
// character (:)
|
|
327
|
-
} else {
|
|
328
|
-
// Process the field using the steps described below, using the whole
|
|
329
|
-
// line as the field name, and the empty string as the field value.
|
|
330
|
-
field = line.toString('utf8')
|
|
331
|
-
value = ''
|
|
332
282
|
}
|
|
333
283
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
284
|
+
if (isFieldName(line, fieldLength, DATA)) {
|
|
285
|
+
const value = line.toString('utf8', valueStart)
|
|
286
|
+
|
|
287
|
+
if (event.data === undefined) {
|
|
288
|
+
event.data = value
|
|
289
|
+
} else {
|
|
290
|
+
event.data += `\n${value}`
|
|
291
|
+
}
|
|
292
|
+
return
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
if (isFieldName(line, fieldLength, RETRY)) {
|
|
296
|
+
if (isASCIINumberBytes(line, valueStart)) {
|
|
297
|
+
event.retry = line.toString('utf8', valueStart)
|
|
298
|
+
}
|
|
299
|
+
return
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
if (isFieldName(line, fieldLength, ID)) {
|
|
303
|
+
if (isValidLastEventIdBytes(line, valueStart)) {
|
|
304
|
+
event.id = line.toString('utf8', valueStart)
|
|
305
|
+
}
|
|
306
|
+
return
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
if (isFieldName(line, fieldLength, EVENT)) {
|
|
310
|
+
const value = line.toString('utf8', valueStart)
|
|
311
|
+
|
|
312
|
+
if (value.length > 0) {
|
|
313
|
+
event.event = value
|
|
314
|
+
}
|
|
359
315
|
}
|
|
360
316
|
}
|
|
361
317
|
|
|
@@ -385,12 +341,151 @@ class EventSourceStream extends Transform {
|
|
|
385
341
|
}
|
|
386
342
|
|
|
387
343
|
clearEvent () {
|
|
388
|
-
this.event =
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
344
|
+
this.event.data = undefined
|
|
345
|
+
this.event.event = undefined
|
|
346
|
+
this.event.id = undefined
|
|
347
|
+
this.event.retry = undefined
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
hasPendingEvent () {
|
|
351
|
+
return this.event.data !== undefined ||
|
|
352
|
+
this.event.event !== undefined ||
|
|
353
|
+
this.event.id !== undefined ||
|
|
354
|
+
this.event.retry !== undefined
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
hasCurrentByte () {
|
|
358
|
+
return this.chunkIndex < this.chunks.length &&
|
|
359
|
+
this.pos < this.chunks[this.chunkIndex].length
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
currentByte () {
|
|
363
|
+
return this.chunks[this.chunkIndex][this.pos]
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
consumeCurrentByte () {
|
|
367
|
+
this.advanceCursor()
|
|
368
|
+
this.syncLineStartToCursor()
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
advanceCursor () {
|
|
372
|
+
this.pos++
|
|
373
|
+
|
|
374
|
+
while (this.chunkIndex < this.chunks.length && this.pos >= this.chunks[this.chunkIndex].length) {
|
|
375
|
+
this.chunkIndex++
|
|
376
|
+
this.pos = 0
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
syncLineStartToCursor () {
|
|
381
|
+
this.lineChunkIndex = this.chunkIndex
|
|
382
|
+
this.linePos = this.pos
|
|
383
|
+
this.dropConsumedChunks()
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
dropConsumedChunks () {
|
|
387
|
+
while (this.lineChunkIndex > 0) {
|
|
388
|
+
this.chunks.shift()
|
|
389
|
+
this.lineChunkIndex--
|
|
390
|
+
this.chunkIndex--
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
if (this.chunkIndex === this.chunks.length) {
|
|
394
|
+
this.chunks.length = 0
|
|
395
|
+
this.chunkIndex = 0
|
|
396
|
+
this.pos = 0
|
|
397
|
+
this.lineChunkIndex = 0
|
|
398
|
+
this.linePos = 0
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
readLine () {
|
|
403
|
+
if (this.lineChunkIndex === this.chunkIndex) {
|
|
404
|
+
return this.chunks[this.chunkIndex].subarray(this.linePos, this.pos)
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
const chunks = []
|
|
408
|
+
let length = 0
|
|
409
|
+
|
|
410
|
+
for (let i = this.lineChunkIndex; i <= this.chunkIndex; i++) {
|
|
411
|
+
const chunk = this.chunks[i]
|
|
412
|
+
const start = i === this.lineChunkIndex ? this.linePos : 0
|
|
413
|
+
const end = i === this.chunkIndex ? this.pos : chunk.length
|
|
414
|
+
const slice = chunk.subarray(start, end)
|
|
415
|
+
length += slice.length
|
|
416
|
+
chunks.push(slice)
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
return Buffer.concat(chunks, length)
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
peekBufferedByte (offset) {
|
|
423
|
+
let chunkIndex = this.lineChunkIndex
|
|
424
|
+
let pos = this.linePos
|
|
425
|
+
|
|
426
|
+
while (chunkIndex < this.chunks.length) {
|
|
427
|
+
const chunk = this.chunks[chunkIndex]
|
|
428
|
+
const remaining = chunk.length - pos
|
|
429
|
+
|
|
430
|
+
if (offset < remaining) {
|
|
431
|
+
return chunk[pos + offset]
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
offset -= remaining
|
|
435
|
+
chunkIndex++
|
|
436
|
+
pos = 0
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
discardLeadingBytes (count) {
|
|
441
|
+
while (count > 0 && this.lineChunkIndex < this.chunks.length) {
|
|
442
|
+
const chunk = this.chunks[this.lineChunkIndex]
|
|
443
|
+
const remaining = chunk.length - this.linePos
|
|
444
|
+
|
|
445
|
+
if (count < remaining) {
|
|
446
|
+
this.linePos += count
|
|
447
|
+
count = 0
|
|
448
|
+
} else {
|
|
449
|
+
count -= remaining
|
|
450
|
+
this.lineChunkIndex++
|
|
451
|
+
this.linePos = 0
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
this.chunkIndex = this.lineChunkIndex
|
|
456
|
+
this.pos = this.linePos
|
|
457
|
+
this.dropConsumedChunks()
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
handleBOM () {
|
|
461
|
+
const first = this.peekBufferedByte(0)
|
|
462
|
+
const second = this.peekBufferedByte(1)
|
|
463
|
+
const third = this.peekBufferedByte(2)
|
|
464
|
+
|
|
465
|
+
if (second === undefined) {
|
|
466
|
+
if (first === BOM[0]) {
|
|
467
|
+
return true
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
this.checkBOM = false
|
|
471
|
+
return true
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
if (third === undefined) {
|
|
475
|
+
if (first === BOM[0] && second === BOM[1]) {
|
|
476
|
+
return true
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
this.checkBOM = false
|
|
480
|
+
return false
|
|
393
481
|
}
|
|
482
|
+
|
|
483
|
+
if (first === BOM[0] && second === BOM[1] && third === BOM[2]) {
|
|
484
|
+
this.discardLeadingBytes(3)
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
this.checkBOM = false
|
|
488
|
+
return !this.hasCurrentByte()
|
|
394
489
|
}
|
|
395
490
|
}
|
|
396
491
|
|
|
@@ -200,7 +200,7 @@ function establishWebSocketConnection (url, protocols, client, handler, options)
|
|
|
200
200
|
// is specified, the server needs to include the same field and one of
|
|
201
201
|
// the selected subprotocol values in its response for the connection to
|
|
202
202
|
// be established.
|
|
203
|
-
if (!requestProtocols.includes(secProtocol)) {
|
|
203
|
+
if (requestProtocols === null || !requestProtocols.includes(secProtocol)) {
|
|
204
204
|
failWebsocketConnection(handler, 1002, 'Protocol was not set in the opening handshake.')
|
|
205
205
|
return
|
|
206
206
|
}
|
|
@@ -63,7 +63,12 @@ class PerMessageDeflate {
|
|
|
63
63
|
|
|
64
64
|
if (this.#maxPayloadSize > 0 && this.#inflate[kLength] > this.#maxPayloadSize) {
|
|
65
65
|
callback(new MessageSizeExceededError())
|
|
66
|
+
// The inflater may still hold buffered input that can emit a late
|
|
67
|
+
// zlib error. Remove the data listener, then deterministically stop
|
|
68
|
+
// the stream so a subsequent 'error' cannot fire without a listener
|
|
69
|
+
// (which would terminate the process as an unhandled error event).
|
|
66
70
|
this.#inflate.removeAllListeners()
|
|
71
|
+
this.#inflate.destroy()
|
|
67
72
|
this.#inflate = null
|
|
68
73
|
return
|
|
69
74
|
}
|
|
@@ -34,9 +34,9 @@ class WebSocketStream {
|
|
|
34
34
|
/** @type {ReadableStreamDefaultController} */
|
|
35
35
|
#readableStreamController
|
|
36
36
|
|
|
37
|
-
//
|
|
38
|
-
/** @type {
|
|
39
|
-
#
|
|
37
|
+
// Retain the controller so the writable stream can be errored while locked.
|
|
38
|
+
/** @type {WritableStreamDefaultController} */
|
|
39
|
+
#writableStreamController
|
|
40
40
|
|
|
41
41
|
// Each WebSocketStream object has an associated boolean handshake aborted , which is initially false.
|
|
42
42
|
#handshakeAborted = false
|
|
@@ -300,6 +300,9 @@ class WebSocketStream {
|
|
|
300
300
|
// 12. Let writable be a new WritableStream .
|
|
301
301
|
// 13. Set up writable with writeAlgorithm , closeAlgorithm , and abortAlgorithm .
|
|
302
302
|
const writable = new WritableStream({
|
|
303
|
+
start: (controller) => {
|
|
304
|
+
this.#writableStreamController = controller
|
|
305
|
+
},
|
|
303
306
|
write: (chunk) => this.#write(chunk),
|
|
304
307
|
close: () => closeWebSocketConnection(this.#handler, null, null),
|
|
305
308
|
abort: (reason) => this.#closeUsingReason(reason)
|
|
@@ -308,9 +311,6 @@ class WebSocketStream {
|
|
|
308
311
|
// Set stream ’s readable stream to readable .
|
|
309
312
|
this.#readableStream = readable
|
|
310
313
|
|
|
311
|
-
// Set stream ’s writable stream to writable .
|
|
312
|
-
this.#writableStream = writable
|
|
313
|
-
|
|
314
314
|
// Resolve stream ’s opened promise with WebSocketOpenInfo «[ " extensions " → extensions , " protocol " → protocol , " readable " → readable , " writable " → writable ]».
|
|
315
315
|
this.#openedPromise.resolve({
|
|
316
316
|
extensions,
|
|
@@ -396,9 +396,7 @@ class WebSocketStream {
|
|
|
396
396
|
this.#readableStreamController.close()
|
|
397
397
|
|
|
398
398
|
// 6.2. Error stream ’s writable stream with an " InvalidStateError " DOMException indicating that a closed WebSocketStream cannot be written to.
|
|
399
|
-
|
|
400
|
-
this.#writableStream.abort(new DOMException('A closed WebSocketStream cannot be written to', 'InvalidStateError'))
|
|
401
|
-
}
|
|
399
|
+
this.#writableStreamController.error(new DOMException('A closed WebSocketStream cannot be written to', 'InvalidStateError'))
|
|
402
400
|
|
|
403
401
|
// 6.3. Resolve stream ’s closed promise with WebSocketCloseInfo «[ " closeCode " → code , " reason " → reason ]».
|
|
404
402
|
this.#closedPromise.resolve({
|
|
@@ -415,7 +413,7 @@ class WebSocketStream {
|
|
|
415
413
|
this.#readableStreamController?.error(error)
|
|
416
414
|
|
|
417
415
|
// 7.3. Error stream ’s writable stream with error .
|
|
418
|
-
this.#
|
|
416
|
+
this.#writableStreamController?.error(error)
|
|
419
417
|
|
|
420
418
|
// 7.4. Reject stream ’s closed promise with error .
|
|
421
419
|
this.#closedPromise.reject(error)
|
|
@@ -12,6 +12,8 @@ declare namespace Interceptors {
|
|
|
12
12
|
export type DecompressInterceptorOpts = {
|
|
13
13
|
skipErrorResponses?: boolean
|
|
14
14
|
skipStatusCodes?: number[]
|
|
15
|
+
/** Maximum decompressed response size in bytes. @default 67108864 */
|
|
16
|
+
maxSize?: number
|
|
15
17
|
}
|
|
16
18
|
|
|
17
19
|
export type ResponseErrorInterceptorOpts = { throwOnError: boolean }
|
package/openclaw.plugin.json
CHANGED
|
@@ -2939,7 +2939,7 @@
|
|
|
2939
2939
|
},
|
|
2940
2940
|
"streaming.nativeTransport": {
|
|
2941
2941
|
"label": "Slack Native Streaming",
|
|
2942
|
-
"help": "Enable native Slack text streaming (chat.startStream/chat.appendStream/chat.stopStream) when channels.slack.streaming.mode is partial (default: true). Native streaming and Slack
|
|
2942
|
+
"help": "Enable native Slack text streaming (chat.startStream/chat.appendStream/chat.stopStream) when channels.slack.streaming.mode is partial (default: true). Native streaming and Slack session status require a reply thread target; top-level DMs can still use draft post-and-edit preview streaming."
|
|
2943
2943
|
},
|
|
2944
2944
|
"streaming.preview.toolProgress": {
|
|
2945
2945
|
"label": "Slack Draft Tool Progress",
|
|
@@ -2951,7 +2951,7 @@
|
|
|
2951
2951
|
},
|
|
2952
2952
|
"streaming.progress.style": {
|
|
2953
2953
|
"label": "Slack Progress Style",
|
|
2954
|
-
"help": "Slack progress presentation: \"card\" uses structured task/session cards; \"compact\" keeps
|
|
2954
|
+
"help": "Slack progress presentation: \"card\" uses structured task/session cards; \"compact\" keeps a temporary editable text draft. The final response is posted as a new message, then the draft is deleted after confirmed delivery. Defaults to \"compact\" when progress.toolProgress is explicitly false, otherwise \"card\"."
|
|
2955
2955
|
},
|
|
2956
2956
|
"streaming.progress.nativeTaskCards": {
|
|
2957
2957
|
"label": "Slack Native Progress Task Cards",
|
|
@@ -2975,7 +2975,7 @@
|
|
|
2975
2975
|
},
|
|
2976
2976
|
"streaming.progress.toolProgress": {
|
|
2977
2977
|
"label": "Slack Progress Tool Lines",
|
|
2978
|
-
"help": "Show
|
|
2978
|
+
"help": "Show individual tool activity in progress drafts (default: false). Quiet drafts retain plans, approval requests, failures, and authored progress text."
|
|
2979
2979
|
},
|
|
2980
2980
|
"streaming.progress.commandText": {
|
|
2981
2981
|
"label": "Slack Progress Command Text",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/slack",
|
|
3
|
-
"version": "2026.9.
|
|
3
|
+
"version": "2026.9.2",
|
|
4
4
|
"description": "OpenClaw Slack channel plugin for channels, DMs, commands, and app events.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -13,13 +13,13 @@
|
|
|
13
13
|
"@slack/types": "3.0.0",
|
|
14
14
|
"@slack/web-api": "8.0.0",
|
|
15
15
|
"get-east-asian-width": "1.6.0",
|
|
16
|
-
"typebox": "1.3.
|
|
17
|
-
"undici": "7.29.
|
|
16
|
+
"typebox": "1.3.18",
|
|
17
|
+
"undici": "7.29.1",
|
|
18
18
|
"ws": "8.21.3",
|
|
19
19
|
"zod": "4.4.3"
|
|
20
20
|
},
|
|
21
21
|
"peerDependencies": {
|
|
22
|
-
"openclaw": ">=2026.9.
|
|
22
|
+
"openclaw": ">=2026.9.2"
|
|
23
23
|
},
|
|
24
24
|
"peerDependenciesMeta": {
|
|
25
25
|
"openclaw": {
|
|
@@ -151,10 +151,10 @@
|
|
|
151
151
|
"allowInvalidConfigRecovery": true
|
|
152
152
|
},
|
|
153
153
|
"compat": {
|
|
154
|
-
"pluginApi": ">=2026.9.
|
|
154
|
+
"pluginApi": ">=2026.9.2"
|
|
155
155
|
},
|
|
156
156
|
"build": {
|
|
157
|
-
"openclawVersion": "2026.9.
|
|
157
|
+
"openclawVersion": "2026.9.2",
|
|
158
158
|
"bundledDist": false
|
|
159
159
|
},
|
|
160
160
|
"release": {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020- Slack Technologies, LLC
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|