@yoooclaw/phone-notifications 1.7.0 → 1.7.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/index.js +154 -45
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/constants.js","../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/buffer-util.js","../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/limiter.js","../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/permessage-deflate.js","../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/validation.js","../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/receiver.js","../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/sender.js","../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/event-target.js","../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/extension.js","../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/websocket.js","../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/stream.js","../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/subprotocol.js","../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/websocket-server.js","../src/index.ts","../src/light/protocol.ts","../src/light/sender.ts","../src/env.ts","../src/host.ts","../src/notification/app-name-map.ts","../src/auth/credentials.ts","../src/notification/storage.ts","../src/cli/auth.ts","../src/cli/helpers.ts","../src/cli/ntf-search.ts","../src/cli/ntf-stats.ts","../src/cli/ntf-sync.ts","../src/cli/ntf-monitor.ts","../src/cli/light-rules.ts","../src/light/validators.ts","../src/cli/light-send.ts","../src/cli/tunnel-status.ts","../src/cli/ntf-storage-path.ts","../src/cli/log-search.ts","../src/cli/env.ts","../src/version.ts","../src/cli/index.ts","../src/tunnel/service.ts","../src/tunnel/relay-client.ts","../node_modules/.pnpm/ws@8.19.0/node_modules/ws/wrapper.mjs","../src/tunnel/proxy.ts","../src/logger.ts"],"sourcesContent":["'use strict';\n\nconst BINARY_TYPES = ['nodebuffer', 'arraybuffer', 'fragments'];\nconst hasBlob = typeof Blob !== 'undefined';\n\nif (hasBlob) BINARY_TYPES.push('blob');\n\nmodule.exports = {\n BINARY_TYPES,\n CLOSE_TIMEOUT: 30000,\n EMPTY_BUFFER: Buffer.alloc(0),\n GUID: '258EAFA5-E914-47DA-95CA-C5AB0DC85B11',\n hasBlob,\n kForOnEventAttribute: Symbol('kIsForOnEventAttribute'),\n kListener: Symbol('kListener'),\n kStatusCode: Symbol('status-code'),\n kWebSocket: Symbol('websocket'),\n NOOP: () => {}\n};\n","'use strict';\n\nconst { EMPTY_BUFFER } = require('./constants');\n\nconst FastBuffer = Buffer[Symbol.species];\n\n/**\n * Merges an array of buffers into a new buffer.\n *\n * @param {Buffer[]} list The array of buffers to concat\n * @param {Number} totalLength The total length of buffers in the list\n * @return {Buffer} The resulting buffer\n * @public\n */\nfunction concat(list, totalLength) {\n if (list.length === 0) return EMPTY_BUFFER;\n if (list.length === 1) return list[0];\n\n const target = Buffer.allocUnsafe(totalLength);\n let offset = 0;\n\n for (let i = 0; i < list.length; i++) {\n const buf = list[i];\n target.set(buf, offset);\n offset += buf.length;\n }\n\n if (offset < totalLength) {\n return new FastBuffer(target.buffer, target.byteOffset, offset);\n }\n\n return target;\n}\n\n/**\n * Masks a buffer using the given mask.\n *\n * @param {Buffer} source The buffer to mask\n * @param {Buffer} mask The mask to use\n * @param {Buffer} output The buffer where to store the result\n * @param {Number} offset The offset at which to start writing\n * @param {Number} length The number of bytes to mask.\n * @public\n */\nfunction _mask(source, mask, output, offset, length) {\n for (let i = 0; i < length; i++) {\n output[offset + i] = source[i] ^ mask[i & 3];\n }\n}\n\n/**\n * Unmasks a buffer using the given mask.\n *\n * @param {Buffer} buffer The buffer to unmask\n * @param {Buffer} mask The mask to use\n * @public\n */\nfunction _unmask(buffer, mask) {\n for (let i = 0; i < buffer.length; i++) {\n buffer[i] ^= mask[i & 3];\n }\n}\n\n/**\n * Converts a buffer to an `ArrayBuffer`.\n *\n * @param {Buffer} buf The buffer to convert\n * @return {ArrayBuffer} Converted buffer\n * @public\n */\nfunction toArrayBuffer(buf) {\n if (buf.length === buf.buffer.byteLength) {\n return buf.buffer;\n }\n\n return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.length);\n}\n\n/**\n * Converts `data` to a `Buffer`.\n *\n * @param {*} data The data to convert\n * @return {Buffer} The buffer\n * @throws {TypeError}\n * @public\n */\nfunction toBuffer(data) {\n toBuffer.readOnly = true;\n\n if (Buffer.isBuffer(data)) return data;\n\n let buf;\n\n if (data instanceof ArrayBuffer) {\n buf = new FastBuffer(data);\n } else if (ArrayBuffer.isView(data)) {\n buf = new FastBuffer(data.buffer, data.byteOffset, data.byteLength);\n } else {\n buf = Buffer.from(data);\n toBuffer.readOnly = false;\n }\n\n return buf;\n}\n\nmodule.exports = {\n concat,\n mask: _mask,\n toArrayBuffer,\n toBuffer,\n unmask: _unmask\n};\n\n/* istanbul ignore else */\nif (!process.env.WS_NO_BUFFER_UTIL) {\n try {\n const bufferUtil = require('bufferutil');\n\n module.exports.mask = function (source, mask, output, offset, length) {\n if (length < 48) _mask(source, mask, output, offset, length);\n else bufferUtil.mask(source, mask, output, offset, length);\n };\n\n module.exports.unmask = function (buffer, mask) {\n if (buffer.length < 32) _unmask(buffer, mask);\n else bufferUtil.unmask(buffer, mask);\n };\n } catch (e) {\n // Continue regardless of the error.\n }\n}\n","'use strict';\n\nconst kDone = Symbol('kDone');\nconst kRun = Symbol('kRun');\n\n/**\n * A very simple job queue with adjustable concurrency. Adapted from\n * https://github.com/STRML/async-limiter\n */\nclass Limiter {\n /**\n * Creates a new `Limiter`.\n *\n * @param {Number} [concurrency=Infinity] The maximum number of jobs allowed\n * to run concurrently\n */\n constructor(concurrency) {\n this[kDone] = () => {\n this.pending--;\n this[kRun]();\n };\n this.concurrency = concurrency || Infinity;\n this.jobs = [];\n this.pending = 0;\n }\n\n /**\n * Adds a job to the queue.\n *\n * @param {Function} job The job to run\n * @public\n */\n add(job) {\n this.jobs.push(job);\n this[kRun]();\n }\n\n /**\n * Removes a job from the queue and runs it if possible.\n *\n * @private\n */\n [kRun]() {\n if (this.pending === this.concurrency) return;\n\n if (this.jobs.length) {\n const job = this.jobs.shift();\n\n this.pending++;\n job(this[kDone]);\n }\n }\n}\n\nmodule.exports = Limiter;\n","'use strict';\n\nconst zlib = require('zlib');\n\nconst bufferUtil = require('./buffer-util');\nconst Limiter = require('./limiter');\nconst { kStatusCode } = require('./constants');\n\nconst FastBuffer = Buffer[Symbol.species];\nconst TRAILER = Buffer.from([0x00, 0x00, 0xff, 0xff]);\nconst kPerMessageDeflate = Symbol('permessage-deflate');\nconst kTotalLength = Symbol('total-length');\nconst kCallback = Symbol('callback');\nconst kBuffers = Symbol('buffers');\nconst kError = Symbol('error');\n\n//\n// We limit zlib concurrency, which prevents severe memory fragmentation\n// as documented in https://github.com/nodejs/node/issues/8871#issuecomment-250915913\n// and https://github.com/websockets/ws/issues/1202\n//\n// Intentionally global; it's the global thread pool that's an issue.\n//\nlet zlibLimiter;\n\n/**\n * permessage-deflate implementation.\n */\nclass PerMessageDeflate {\n /**\n * Creates a PerMessageDeflate instance.\n *\n * @param {Object} [options] Configuration options\n * @param {(Boolean|Number)} [options.clientMaxWindowBits] Advertise support\n * for, or request, a custom client window size\n * @param {Boolean} [options.clientNoContextTakeover=false] Advertise/\n * acknowledge disabling of client context takeover\n * @param {Number} [options.concurrencyLimit=10] The number of concurrent\n * calls to zlib\n * @param {(Boolean|Number)} [options.serverMaxWindowBits] Request/confirm the\n * use of a custom server window size\n * @param {Boolean} [options.serverNoContextTakeover=false] Request/accept\n * disabling of server context takeover\n * @param {Number} [options.threshold=1024] Size (in bytes) below which\n * messages should not be compressed if context takeover is disabled\n * @param {Object} [options.zlibDeflateOptions] Options to pass to zlib on\n * deflate\n * @param {Object} [options.zlibInflateOptions] Options to pass to zlib on\n * inflate\n * @param {Boolean} [isServer=false] Create the instance in either server or\n * client mode\n * @param {Number} [maxPayload=0] The maximum allowed message length\n */\n constructor(options, isServer, maxPayload) {\n this._maxPayload = maxPayload | 0;\n this._options = options || {};\n this._threshold =\n this._options.threshold !== undefined ? this._options.threshold : 1024;\n this._isServer = !!isServer;\n this._deflate = null;\n this._inflate = null;\n\n this.params = null;\n\n if (!zlibLimiter) {\n const concurrency =\n this._options.concurrencyLimit !== undefined\n ? this._options.concurrencyLimit\n : 10;\n zlibLimiter = new Limiter(concurrency);\n }\n }\n\n /**\n * @type {String}\n */\n static get extensionName() {\n return 'permessage-deflate';\n }\n\n /**\n * Create an extension negotiation offer.\n *\n * @return {Object} Extension parameters\n * @public\n */\n offer() {\n const params = {};\n\n if (this._options.serverNoContextTakeover) {\n params.server_no_context_takeover = true;\n }\n if (this._options.clientNoContextTakeover) {\n params.client_no_context_takeover = true;\n }\n if (this._options.serverMaxWindowBits) {\n params.server_max_window_bits = this._options.serverMaxWindowBits;\n }\n if (this._options.clientMaxWindowBits) {\n params.client_max_window_bits = this._options.clientMaxWindowBits;\n } else if (this._options.clientMaxWindowBits == null) {\n params.client_max_window_bits = true;\n }\n\n return params;\n }\n\n /**\n * Accept an extension negotiation offer/response.\n *\n * @param {Array} configurations The extension negotiation offers/reponse\n * @return {Object} Accepted configuration\n * @public\n */\n accept(configurations) {\n configurations = this.normalizeParams(configurations);\n\n this.params = this._isServer\n ? this.acceptAsServer(configurations)\n : this.acceptAsClient(configurations);\n\n return this.params;\n }\n\n /**\n * Releases all resources used by the extension.\n *\n * @public\n */\n cleanup() {\n if (this._inflate) {\n this._inflate.close();\n this._inflate = null;\n }\n\n if (this._deflate) {\n const callback = this._deflate[kCallback];\n\n this._deflate.close();\n this._deflate = null;\n\n if (callback) {\n callback(\n new Error(\n 'The deflate stream was closed while data was being processed'\n )\n );\n }\n }\n }\n\n /**\n * Accept an extension negotiation offer.\n *\n * @param {Array} offers The extension negotiation offers\n * @return {Object} Accepted configuration\n * @private\n */\n acceptAsServer(offers) {\n const opts = this._options;\n const accepted = offers.find((params) => {\n if (\n (opts.serverNoContextTakeover === false &&\n params.server_no_context_takeover) ||\n (params.server_max_window_bits &&\n (opts.serverMaxWindowBits === false ||\n (typeof opts.serverMaxWindowBits === 'number' &&\n opts.serverMaxWindowBits > params.server_max_window_bits))) ||\n (typeof opts.clientMaxWindowBits === 'number' &&\n !params.client_max_window_bits)\n ) {\n return false;\n }\n\n return true;\n });\n\n if (!accepted) {\n throw new Error('None of the extension offers can be accepted');\n }\n\n if (opts.serverNoContextTakeover) {\n accepted.server_no_context_takeover = true;\n }\n if (opts.clientNoContextTakeover) {\n accepted.client_no_context_takeover = true;\n }\n if (typeof opts.serverMaxWindowBits === 'number') {\n accepted.server_max_window_bits = opts.serverMaxWindowBits;\n }\n if (typeof opts.clientMaxWindowBits === 'number') {\n accepted.client_max_window_bits = opts.clientMaxWindowBits;\n } else if (\n accepted.client_max_window_bits === true ||\n opts.clientMaxWindowBits === false\n ) {\n delete accepted.client_max_window_bits;\n }\n\n return accepted;\n }\n\n /**\n * Accept the extension negotiation response.\n *\n * @param {Array} response The extension negotiation response\n * @return {Object} Accepted configuration\n * @private\n */\n acceptAsClient(response) {\n const params = response[0];\n\n if (\n this._options.clientNoContextTakeover === false &&\n params.client_no_context_takeover\n ) {\n throw new Error('Unexpected parameter \"client_no_context_takeover\"');\n }\n\n if (!params.client_max_window_bits) {\n if (typeof this._options.clientMaxWindowBits === 'number') {\n params.client_max_window_bits = this._options.clientMaxWindowBits;\n }\n } else if (\n this._options.clientMaxWindowBits === false ||\n (typeof this._options.clientMaxWindowBits === 'number' &&\n params.client_max_window_bits > this._options.clientMaxWindowBits)\n ) {\n throw new Error(\n 'Unexpected or invalid parameter \"client_max_window_bits\"'\n );\n }\n\n return params;\n }\n\n /**\n * Normalize parameters.\n *\n * @param {Array} configurations The extension negotiation offers/reponse\n * @return {Array} The offers/response with normalized parameters\n * @private\n */\n normalizeParams(configurations) {\n configurations.forEach((params) => {\n Object.keys(params).forEach((key) => {\n let value = params[key];\n\n if (value.length > 1) {\n throw new Error(`Parameter \"${key}\" must have only a single value`);\n }\n\n value = value[0];\n\n if (key === 'client_max_window_bits') {\n if (value !== true) {\n const num = +value;\n if (!Number.isInteger(num) || num < 8 || num > 15) {\n throw new TypeError(\n `Invalid value for parameter \"${key}\": ${value}`\n );\n }\n value = num;\n } else if (!this._isServer) {\n throw new TypeError(\n `Invalid value for parameter \"${key}\": ${value}`\n );\n }\n } else if (key === 'server_max_window_bits') {\n const num = +value;\n if (!Number.isInteger(num) || num < 8 || num > 15) {\n throw new TypeError(\n `Invalid value for parameter \"${key}\": ${value}`\n );\n }\n value = num;\n } else if (\n key === 'client_no_context_takeover' ||\n key === 'server_no_context_takeover'\n ) {\n if (value !== true) {\n throw new TypeError(\n `Invalid value for parameter \"${key}\": ${value}`\n );\n }\n } else {\n throw new Error(`Unknown parameter \"${key}\"`);\n }\n\n params[key] = value;\n });\n });\n\n return configurations;\n }\n\n /**\n * Decompress data. Concurrency limited.\n *\n * @param {Buffer} data Compressed data\n * @param {Boolean} fin Specifies whether or not this is the last fragment\n * @param {Function} callback Callback\n * @public\n */\n decompress(data, fin, callback) {\n zlibLimiter.add((done) => {\n this._decompress(data, fin, (err, result) => {\n done();\n callback(err, result);\n });\n });\n }\n\n /**\n * Compress data. Concurrency limited.\n *\n * @param {(Buffer|String)} data Data to compress\n * @param {Boolean} fin Specifies whether or not this is the last fragment\n * @param {Function} callback Callback\n * @public\n */\n compress(data, fin, callback) {\n zlibLimiter.add((done) => {\n this._compress(data, fin, (err, result) => {\n done();\n callback(err, result);\n });\n });\n }\n\n /**\n * Decompress data.\n *\n * @param {Buffer} data Compressed data\n * @param {Boolean} fin Specifies whether or not this is the last fragment\n * @param {Function} callback Callback\n * @private\n */\n _decompress(data, fin, callback) {\n const endpoint = this._isServer ? 'client' : 'server';\n\n if (!this._inflate) {\n const key = `${endpoint}_max_window_bits`;\n const windowBits =\n typeof this.params[key] !== 'number'\n ? zlib.Z_DEFAULT_WINDOWBITS\n : this.params[key];\n\n this._inflate = zlib.createInflateRaw({\n ...this._options.zlibInflateOptions,\n windowBits\n });\n this._inflate[kPerMessageDeflate] = this;\n this._inflate[kTotalLength] = 0;\n this._inflate[kBuffers] = [];\n this._inflate.on('error', inflateOnError);\n this._inflate.on('data', inflateOnData);\n }\n\n this._inflate[kCallback] = callback;\n\n this._inflate.write(data);\n if (fin) this._inflate.write(TRAILER);\n\n this._inflate.flush(() => {\n const err = this._inflate[kError];\n\n if (err) {\n this._inflate.close();\n this._inflate = null;\n callback(err);\n return;\n }\n\n const data = bufferUtil.concat(\n this._inflate[kBuffers],\n this._inflate[kTotalLength]\n );\n\n if (this._inflate._readableState.endEmitted) {\n this._inflate.close();\n this._inflate = null;\n } else {\n this._inflate[kTotalLength] = 0;\n this._inflate[kBuffers] = [];\n\n if (fin && this.params[`${endpoint}_no_context_takeover`]) {\n this._inflate.reset();\n }\n }\n\n callback(null, data);\n });\n }\n\n /**\n * Compress data.\n *\n * @param {(Buffer|String)} data Data to compress\n * @param {Boolean} fin Specifies whether or not this is the last fragment\n * @param {Function} callback Callback\n * @private\n */\n _compress(data, fin, callback) {\n const endpoint = this._isServer ? 'server' : 'client';\n\n if (!this._deflate) {\n const key = `${endpoint}_max_window_bits`;\n const windowBits =\n typeof this.params[key] !== 'number'\n ? zlib.Z_DEFAULT_WINDOWBITS\n : this.params[key];\n\n this._deflate = zlib.createDeflateRaw({\n ...this._options.zlibDeflateOptions,\n windowBits\n });\n\n this._deflate[kTotalLength] = 0;\n this._deflate[kBuffers] = [];\n\n this._deflate.on('data', deflateOnData);\n }\n\n this._deflate[kCallback] = callback;\n\n this._deflate.write(data);\n this._deflate.flush(zlib.Z_SYNC_FLUSH, () => {\n if (!this._deflate) {\n //\n // The deflate stream was closed while data was being processed.\n //\n return;\n }\n\n let data = bufferUtil.concat(\n this._deflate[kBuffers],\n this._deflate[kTotalLength]\n );\n\n if (fin) {\n data = new FastBuffer(data.buffer, data.byteOffset, data.length - 4);\n }\n\n //\n // Ensure that the callback will not be called again in\n // `PerMessageDeflate#cleanup()`.\n //\n this._deflate[kCallback] = null;\n\n this._deflate[kTotalLength] = 0;\n this._deflate[kBuffers] = [];\n\n if (fin && this.params[`${endpoint}_no_context_takeover`]) {\n this._deflate.reset();\n }\n\n callback(null, data);\n });\n }\n}\n\nmodule.exports = PerMessageDeflate;\n\n/**\n * The listener of the `zlib.DeflateRaw` stream `'data'` event.\n *\n * @param {Buffer} chunk A chunk of data\n * @private\n */\nfunction deflateOnData(chunk) {\n this[kBuffers].push(chunk);\n this[kTotalLength] += chunk.length;\n}\n\n/**\n * The listener of the `zlib.InflateRaw` stream `'data'` event.\n *\n * @param {Buffer} chunk A chunk of data\n * @private\n */\nfunction inflateOnData(chunk) {\n this[kTotalLength] += chunk.length;\n\n if (\n this[kPerMessageDeflate]._maxPayload < 1 ||\n this[kTotalLength] <= this[kPerMessageDeflate]._maxPayload\n ) {\n this[kBuffers].push(chunk);\n return;\n }\n\n this[kError] = new RangeError('Max payload size exceeded');\n this[kError].code = 'WS_ERR_UNSUPPORTED_MESSAGE_LENGTH';\n this[kError][kStatusCode] = 1009;\n this.removeListener('data', inflateOnData);\n\n //\n // The choice to employ `zlib.reset()` over `zlib.close()` is dictated by the\n // fact that in Node.js versions prior to 13.10.0, the callback for\n // `zlib.flush()` is not called if `zlib.close()` is used. Utilizing\n // `zlib.reset()` ensures that either the callback is invoked or an error is\n // emitted.\n //\n this.reset();\n}\n\n/**\n * The listener of the `zlib.InflateRaw` stream `'error'` event.\n *\n * @param {Error} err The emitted error\n * @private\n */\nfunction inflateOnError(err) {\n //\n // There is no need to call `Zlib#close()` as the handle is automatically\n // closed when an error is emitted.\n //\n this[kPerMessageDeflate]._inflate = null;\n\n if (this[kError]) {\n this[kCallback](this[kError]);\n return;\n }\n\n err[kStatusCode] = 1007;\n this[kCallback](err);\n}\n","'use strict';\n\nconst { isUtf8 } = require('buffer');\n\nconst { hasBlob } = require('./constants');\n\n//\n// Allowed token characters:\n//\n// '!', '#', '$', '%', '&', ''', '*', '+', '-',\n// '.', 0-9, A-Z, '^', '_', '`', a-z, '|', '~'\n//\n// tokenChars[32] === 0 // ' '\n// tokenChars[33] === 1 // '!'\n// tokenChars[34] === 0 // '\"'\n// ...\n//\n// prettier-ignore\nconst tokenChars = [\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0 - 15\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16 - 31\n 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, // 32 - 47\n 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 48 - 63\n 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64 - 79\n 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, // 80 - 95\n 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96 - 111\n 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0 // 112 - 127\n];\n\n/**\n * Checks if a status code is allowed in a close frame.\n *\n * @param {Number} code The status code\n * @return {Boolean} `true` if the status code is valid, else `false`\n * @public\n */\nfunction isValidStatusCode(code) {\n return (\n (code >= 1000 &&\n code <= 1014 &&\n code !== 1004 &&\n code !== 1005 &&\n code !== 1006) ||\n (code >= 3000 && code <= 4999)\n );\n}\n\n/**\n * Checks if a given buffer contains only correct UTF-8.\n * Ported from https://www.cl.cam.ac.uk/%7Emgk25/ucs/utf8_check.c by\n * Markus Kuhn.\n *\n * @param {Buffer} buf The buffer to check\n * @return {Boolean} `true` if `buf` contains only correct UTF-8, else `false`\n * @public\n */\nfunction _isValidUTF8(buf) {\n const len = buf.length;\n let i = 0;\n\n while (i < len) {\n if ((buf[i] & 0x80) === 0) {\n // 0xxxxxxx\n i++;\n } else if ((buf[i] & 0xe0) === 0xc0) {\n // 110xxxxx 10xxxxxx\n if (\n i + 1 === len ||\n (buf[i + 1] & 0xc0) !== 0x80 ||\n (buf[i] & 0xfe) === 0xc0 // Overlong\n ) {\n return false;\n }\n\n i += 2;\n } else if ((buf[i] & 0xf0) === 0xe0) {\n // 1110xxxx 10xxxxxx 10xxxxxx\n if (\n i + 2 >= len ||\n (buf[i + 1] & 0xc0) !== 0x80 ||\n (buf[i + 2] & 0xc0) !== 0x80 ||\n (buf[i] === 0xe0 && (buf[i + 1] & 0xe0) === 0x80) || // Overlong\n (buf[i] === 0xed && (buf[i + 1] & 0xe0) === 0xa0) // Surrogate (U+D800 - U+DFFF)\n ) {\n return false;\n }\n\n i += 3;\n } else if ((buf[i] & 0xf8) === 0xf0) {\n // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx\n if (\n i + 3 >= len ||\n (buf[i + 1] & 0xc0) !== 0x80 ||\n (buf[i + 2] & 0xc0) !== 0x80 ||\n (buf[i + 3] & 0xc0) !== 0x80 ||\n (buf[i] === 0xf0 && (buf[i + 1] & 0xf0) === 0x80) || // Overlong\n (buf[i] === 0xf4 && buf[i + 1] > 0x8f) ||\n buf[i] > 0xf4 // > U+10FFFF\n ) {\n return false;\n }\n\n i += 4;\n } else {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Determines whether a value is a `Blob`.\n *\n * @param {*} value The value to be tested\n * @return {Boolean} `true` if `value` is a `Blob`, else `false`\n * @private\n */\nfunction isBlob(value) {\n return (\n hasBlob &&\n typeof value === 'object' &&\n typeof value.arrayBuffer === 'function' &&\n typeof value.type === 'string' &&\n typeof value.stream === 'function' &&\n (value[Symbol.toStringTag] === 'Blob' ||\n value[Symbol.toStringTag] === 'File')\n );\n}\n\nmodule.exports = {\n isBlob,\n isValidStatusCode,\n isValidUTF8: _isValidUTF8,\n tokenChars\n};\n\nif (isUtf8) {\n module.exports.isValidUTF8 = function (buf) {\n return buf.length < 24 ? _isValidUTF8(buf) : isUtf8(buf);\n };\n} /* istanbul ignore else */ else if (!process.env.WS_NO_UTF_8_VALIDATE) {\n try {\n const isValidUTF8 = require('utf-8-validate');\n\n module.exports.isValidUTF8 = function (buf) {\n return buf.length < 32 ? _isValidUTF8(buf) : isValidUTF8(buf);\n };\n } catch (e) {\n // Continue regardless of the error.\n }\n}\n","'use strict';\n\nconst { Writable } = require('stream');\n\nconst PerMessageDeflate = require('./permessage-deflate');\nconst {\n BINARY_TYPES,\n EMPTY_BUFFER,\n kStatusCode,\n kWebSocket\n} = require('./constants');\nconst { concat, toArrayBuffer, unmask } = require('./buffer-util');\nconst { isValidStatusCode, isValidUTF8 } = require('./validation');\n\nconst FastBuffer = Buffer[Symbol.species];\n\nconst GET_INFO = 0;\nconst GET_PAYLOAD_LENGTH_16 = 1;\nconst GET_PAYLOAD_LENGTH_64 = 2;\nconst GET_MASK = 3;\nconst GET_DATA = 4;\nconst INFLATING = 5;\nconst DEFER_EVENT = 6;\n\n/**\n * HyBi Receiver implementation.\n *\n * @extends Writable\n */\nclass Receiver extends Writable {\n /**\n * Creates a Receiver instance.\n *\n * @param {Object} [options] Options object\n * @param {Boolean} [options.allowSynchronousEvents=true] Specifies whether\n * any of the `'message'`, `'ping'`, and `'pong'` events can be emitted\n * multiple times in the same tick\n * @param {String} [options.binaryType=nodebuffer] The type for binary data\n * @param {Object} [options.extensions] An object containing the negotiated\n * extensions\n * @param {Boolean} [options.isServer=false] Specifies whether to operate in\n * client or server mode\n * @param {Number} [options.maxPayload=0] The maximum allowed message length\n * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or\n * not to skip UTF-8 validation for text and close messages\n */\n constructor(options = {}) {\n super();\n\n this._allowSynchronousEvents =\n options.allowSynchronousEvents !== undefined\n ? options.allowSynchronousEvents\n : true;\n this._binaryType = options.binaryType || BINARY_TYPES[0];\n this._extensions = options.extensions || {};\n this._isServer = !!options.isServer;\n this._maxPayload = options.maxPayload | 0;\n this._skipUTF8Validation = !!options.skipUTF8Validation;\n this[kWebSocket] = undefined;\n\n this._bufferedBytes = 0;\n this._buffers = [];\n\n this._compressed = false;\n this._payloadLength = 0;\n this._mask = undefined;\n this._fragmented = 0;\n this._masked = false;\n this._fin = false;\n this._opcode = 0;\n\n this._totalPayloadLength = 0;\n this._messageLength = 0;\n this._fragments = [];\n\n this._errored = false;\n this._loop = false;\n this._state = GET_INFO;\n }\n\n /**\n * Implements `Writable.prototype._write()`.\n *\n * @param {Buffer} chunk The chunk of data to write\n * @param {String} encoding The character encoding of `chunk`\n * @param {Function} cb Callback\n * @private\n */\n _write(chunk, encoding, cb) {\n if (this._opcode === 0x08 && this._state == GET_INFO) return cb();\n\n this._bufferedBytes += chunk.length;\n this._buffers.push(chunk);\n this.startLoop(cb);\n }\n\n /**\n * Consumes `n` bytes from the buffered data.\n *\n * @param {Number} n The number of bytes to consume\n * @return {Buffer} The consumed bytes\n * @private\n */\n consume(n) {\n this._bufferedBytes -= n;\n\n if (n === this._buffers[0].length) return this._buffers.shift();\n\n if (n < this._buffers[0].length) {\n const buf = this._buffers[0];\n this._buffers[0] = new FastBuffer(\n buf.buffer,\n buf.byteOffset + n,\n buf.length - n\n );\n\n return new FastBuffer(buf.buffer, buf.byteOffset, n);\n }\n\n const dst = Buffer.allocUnsafe(n);\n\n do {\n const buf = this._buffers[0];\n const offset = dst.length - n;\n\n if (n >= buf.length) {\n dst.set(this._buffers.shift(), offset);\n } else {\n dst.set(new Uint8Array(buf.buffer, buf.byteOffset, n), offset);\n this._buffers[0] = new FastBuffer(\n buf.buffer,\n buf.byteOffset + n,\n buf.length - n\n );\n }\n\n n -= buf.length;\n } while (n > 0);\n\n return dst;\n }\n\n /**\n * Starts the parsing loop.\n *\n * @param {Function} cb Callback\n * @private\n */\n startLoop(cb) {\n this._loop = true;\n\n do {\n switch (this._state) {\n case GET_INFO:\n this.getInfo(cb);\n break;\n case GET_PAYLOAD_LENGTH_16:\n this.getPayloadLength16(cb);\n break;\n case GET_PAYLOAD_LENGTH_64:\n this.getPayloadLength64(cb);\n break;\n case GET_MASK:\n this.getMask();\n break;\n case GET_DATA:\n this.getData(cb);\n break;\n case INFLATING:\n case DEFER_EVENT:\n this._loop = false;\n return;\n }\n } while (this._loop);\n\n if (!this._errored) cb();\n }\n\n /**\n * Reads the first two bytes of a frame.\n *\n * @param {Function} cb Callback\n * @private\n */\n getInfo(cb) {\n if (this._bufferedBytes < 2) {\n this._loop = false;\n return;\n }\n\n const buf = this.consume(2);\n\n if ((buf[0] & 0x30) !== 0x00) {\n const error = this.createError(\n RangeError,\n 'RSV2 and RSV3 must be clear',\n true,\n 1002,\n 'WS_ERR_UNEXPECTED_RSV_2_3'\n );\n\n cb(error);\n return;\n }\n\n const compressed = (buf[0] & 0x40) === 0x40;\n\n if (compressed && !this._extensions[PerMessageDeflate.extensionName]) {\n const error = this.createError(\n RangeError,\n 'RSV1 must be clear',\n true,\n 1002,\n 'WS_ERR_UNEXPECTED_RSV_1'\n );\n\n cb(error);\n return;\n }\n\n this._fin = (buf[0] & 0x80) === 0x80;\n this._opcode = buf[0] & 0x0f;\n this._payloadLength = buf[1] & 0x7f;\n\n if (this._opcode === 0x00) {\n if (compressed) {\n const error = this.createError(\n RangeError,\n 'RSV1 must be clear',\n true,\n 1002,\n 'WS_ERR_UNEXPECTED_RSV_1'\n );\n\n cb(error);\n return;\n }\n\n if (!this._fragmented) {\n const error = this.createError(\n RangeError,\n 'invalid opcode 0',\n true,\n 1002,\n 'WS_ERR_INVALID_OPCODE'\n );\n\n cb(error);\n return;\n }\n\n this._opcode = this._fragmented;\n } else if (this._opcode === 0x01 || this._opcode === 0x02) {\n if (this._fragmented) {\n const error = this.createError(\n RangeError,\n `invalid opcode ${this._opcode}`,\n true,\n 1002,\n 'WS_ERR_INVALID_OPCODE'\n );\n\n cb(error);\n return;\n }\n\n this._compressed = compressed;\n } else if (this._opcode > 0x07 && this._opcode < 0x0b) {\n if (!this._fin) {\n const error = this.createError(\n RangeError,\n 'FIN must be set',\n true,\n 1002,\n 'WS_ERR_EXPECTED_FIN'\n );\n\n cb(error);\n return;\n }\n\n if (compressed) {\n const error = this.createError(\n RangeError,\n 'RSV1 must be clear',\n true,\n 1002,\n 'WS_ERR_UNEXPECTED_RSV_1'\n );\n\n cb(error);\n return;\n }\n\n if (\n this._payloadLength > 0x7d ||\n (this._opcode === 0x08 && this._payloadLength === 1)\n ) {\n const error = this.createError(\n RangeError,\n `invalid payload length ${this._payloadLength}`,\n true,\n 1002,\n 'WS_ERR_INVALID_CONTROL_PAYLOAD_LENGTH'\n );\n\n cb(error);\n return;\n }\n } else {\n const error = this.createError(\n RangeError,\n `invalid opcode ${this._opcode}`,\n true,\n 1002,\n 'WS_ERR_INVALID_OPCODE'\n );\n\n cb(error);\n return;\n }\n\n if (!this._fin && !this._fragmented) this._fragmented = this._opcode;\n this._masked = (buf[1] & 0x80) === 0x80;\n\n if (this._isServer) {\n if (!this._masked) {\n const error = this.createError(\n RangeError,\n 'MASK must be set',\n true,\n 1002,\n 'WS_ERR_EXPECTED_MASK'\n );\n\n cb(error);\n return;\n }\n } else if (this._masked) {\n const error = this.createError(\n RangeError,\n 'MASK must be clear',\n true,\n 1002,\n 'WS_ERR_UNEXPECTED_MASK'\n );\n\n cb(error);\n return;\n }\n\n if (this._payloadLength === 126) this._state = GET_PAYLOAD_LENGTH_16;\n else if (this._payloadLength === 127) this._state = GET_PAYLOAD_LENGTH_64;\n else this.haveLength(cb);\n }\n\n /**\n * Gets extended payload length (7+16).\n *\n * @param {Function} cb Callback\n * @private\n */\n getPayloadLength16(cb) {\n if (this._bufferedBytes < 2) {\n this._loop = false;\n return;\n }\n\n this._payloadLength = this.consume(2).readUInt16BE(0);\n this.haveLength(cb);\n }\n\n /**\n * Gets extended payload length (7+64).\n *\n * @param {Function} cb Callback\n * @private\n */\n getPayloadLength64(cb) {\n if (this._bufferedBytes < 8) {\n this._loop = false;\n return;\n }\n\n const buf = this.consume(8);\n const num = buf.readUInt32BE(0);\n\n //\n // The maximum safe integer in JavaScript is 2^53 - 1. An error is returned\n // if payload length is greater than this number.\n //\n if (num > Math.pow(2, 53 - 32) - 1) {\n const error = this.createError(\n RangeError,\n 'Unsupported WebSocket frame: payload length > 2^53 - 1',\n false,\n 1009,\n 'WS_ERR_UNSUPPORTED_DATA_PAYLOAD_LENGTH'\n );\n\n cb(error);\n return;\n }\n\n this._payloadLength = num * Math.pow(2, 32) + buf.readUInt32BE(4);\n this.haveLength(cb);\n }\n\n /**\n * Payload length has been read.\n *\n * @param {Function} cb Callback\n * @private\n */\n haveLength(cb) {\n if (this._payloadLength && this._opcode < 0x08) {\n this._totalPayloadLength += this._payloadLength;\n if (this._totalPayloadLength > this._maxPayload && this._maxPayload > 0) {\n const error = this.createError(\n RangeError,\n 'Max payload size exceeded',\n false,\n 1009,\n 'WS_ERR_UNSUPPORTED_MESSAGE_LENGTH'\n );\n\n cb(error);\n return;\n }\n }\n\n if (this._masked) this._state = GET_MASK;\n else this._state = GET_DATA;\n }\n\n /**\n * Reads mask bytes.\n *\n * @private\n */\n getMask() {\n if (this._bufferedBytes < 4) {\n this._loop = false;\n return;\n }\n\n this._mask = this.consume(4);\n this._state = GET_DATA;\n }\n\n /**\n * Reads data bytes.\n *\n * @param {Function} cb Callback\n * @private\n */\n getData(cb) {\n let data = EMPTY_BUFFER;\n\n if (this._payloadLength) {\n if (this._bufferedBytes < this._payloadLength) {\n this._loop = false;\n return;\n }\n\n data = this.consume(this._payloadLength);\n\n if (\n this._masked &&\n (this._mask[0] | this._mask[1] | this._mask[2] | this._mask[3]) !== 0\n ) {\n unmask(data, this._mask);\n }\n }\n\n if (this._opcode > 0x07) {\n this.controlMessage(data, cb);\n return;\n }\n\n if (this._compressed) {\n this._state = INFLATING;\n this.decompress(data, cb);\n return;\n }\n\n if (data.length) {\n //\n // This message is not compressed so its length is the sum of the payload\n // length of all fragments.\n //\n this._messageLength = this._totalPayloadLength;\n this._fragments.push(data);\n }\n\n this.dataMessage(cb);\n }\n\n /**\n * Decompresses data.\n *\n * @param {Buffer} data Compressed data\n * @param {Function} cb Callback\n * @private\n */\n decompress(data, cb) {\n const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName];\n\n perMessageDeflate.decompress(data, this._fin, (err, buf) => {\n if (err) return cb(err);\n\n if (buf.length) {\n this._messageLength += buf.length;\n if (this._messageLength > this._maxPayload && this._maxPayload > 0) {\n const error = this.createError(\n RangeError,\n 'Max payload size exceeded',\n false,\n 1009,\n 'WS_ERR_UNSUPPORTED_MESSAGE_LENGTH'\n );\n\n cb(error);\n return;\n }\n\n this._fragments.push(buf);\n }\n\n this.dataMessage(cb);\n if (this._state === GET_INFO) this.startLoop(cb);\n });\n }\n\n /**\n * Handles a data message.\n *\n * @param {Function} cb Callback\n * @private\n */\n dataMessage(cb) {\n if (!this._fin) {\n this._state = GET_INFO;\n return;\n }\n\n const messageLength = this._messageLength;\n const fragments = this._fragments;\n\n this._totalPayloadLength = 0;\n this._messageLength = 0;\n this._fragmented = 0;\n this._fragments = [];\n\n if (this._opcode === 2) {\n let data;\n\n if (this._binaryType === 'nodebuffer') {\n data = concat(fragments, messageLength);\n } else if (this._binaryType === 'arraybuffer') {\n data = toArrayBuffer(concat(fragments, messageLength));\n } else if (this._binaryType === 'blob') {\n data = new Blob(fragments);\n } else {\n data = fragments;\n }\n\n if (this._allowSynchronousEvents) {\n this.emit('message', data, true);\n this._state = GET_INFO;\n } else {\n this._state = DEFER_EVENT;\n setImmediate(() => {\n this.emit('message', data, true);\n this._state = GET_INFO;\n this.startLoop(cb);\n });\n }\n } else {\n const buf = concat(fragments, messageLength);\n\n if (!this._skipUTF8Validation && !isValidUTF8(buf)) {\n const error = this.createError(\n Error,\n 'invalid UTF-8 sequence',\n true,\n 1007,\n 'WS_ERR_INVALID_UTF8'\n );\n\n cb(error);\n return;\n }\n\n if (this._state === INFLATING || this._allowSynchronousEvents) {\n this.emit('message', buf, false);\n this._state = GET_INFO;\n } else {\n this._state = DEFER_EVENT;\n setImmediate(() => {\n this.emit('message', buf, false);\n this._state = GET_INFO;\n this.startLoop(cb);\n });\n }\n }\n }\n\n /**\n * Handles a control message.\n *\n * @param {Buffer} data Data to handle\n * @return {(Error|RangeError|undefined)} A possible error\n * @private\n */\n controlMessage(data, cb) {\n if (this._opcode === 0x08) {\n if (data.length === 0) {\n this._loop = false;\n this.emit('conclude', 1005, EMPTY_BUFFER);\n this.end();\n } else {\n const code = data.readUInt16BE(0);\n\n if (!isValidStatusCode(code)) {\n const error = this.createError(\n RangeError,\n `invalid status code ${code}`,\n true,\n 1002,\n 'WS_ERR_INVALID_CLOSE_CODE'\n );\n\n cb(error);\n return;\n }\n\n const buf = new FastBuffer(\n data.buffer,\n data.byteOffset + 2,\n data.length - 2\n );\n\n if (!this._skipUTF8Validation && !isValidUTF8(buf)) {\n const error = this.createError(\n Error,\n 'invalid UTF-8 sequence',\n true,\n 1007,\n 'WS_ERR_INVALID_UTF8'\n );\n\n cb(error);\n return;\n }\n\n this._loop = false;\n this.emit('conclude', code, buf);\n this.end();\n }\n\n this._state = GET_INFO;\n return;\n }\n\n if (this._allowSynchronousEvents) {\n this.emit(this._opcode === 0x09 ? 'ping' : 'pong', data);\n this._state = GET_INFO;\n } else {\n this._state = DEFER_EVENT;\n setImmediate(() => {\n this.emit(this._opcode === 0x09 ? 'ping' : 'pong', data);\n this._state = GET_INFO;\n this.startLoop(cb);\n });\n }\n }\n\n /**\n * Builds an error object.\n *\n * @param {function(new:Error|RangeError)} ErrorCtor The error constructor\n * @param {String} message The error message\n * @param {Boolean} prefix Specifies whether or not to add a default prefix to\n * `message`\n * @param {Number} statusCode The status code\n * @param {String} errorCode The exposed error code\n * @return {(Error|RangeError)} The error\n * @private\n */\n createError(ErrorCtor, message, prefix, statusCode, errorCode) {\n this._loop = false;\n this._errored = true;\n\n const err = new ErrorCtor(\n prefix ? `Invalid WebSocket frame: ${message}` : message\n );\n\n Error.captureStackTrace(err, this.createError);\n err.code = errorCode;\n err[kStatusCode] = statusCode;\n return err;\n }\n}\n\nmodule.exports = Receiver;\n","/* eslint no-unused-vars: [\"error\", { \"varsIgnorePattern\": \"^Duplex\" }] */\n\n'use strict';\n\nconst { Duplex } = require('stream');\nconst { randomFillSync } = require('crypto');\n\nconst PerMessageDeflate = require('./permessage-deflate');\nconst { EMPTY_BUFFER, kWebSocket, NOOP } = require('./constants');\nconst { isBlob, isValidStatusCode } = require('./validation');\nconst { mask: applyMask, toBuffer } = require('./buffer-util');\n\nconst kByteLength = Symbol('kByteLength');\nconst maskBuffer = Buffer.alloc(4);\nconst RANDOM_POOL_SIZE = 8 * 1024;\nlet randomPool;\nlet randomPoolPointer = RANDOM_POOL_SIZE;\n\nconst DEFAULT = 0;\nconst DEFLATING = 1;\nconst GET_BLOB_DATA = 2;\n\n/**\n * HyBi Sender implementation.\n */\nclass Sender {\n /**\n * Creates a Sender instance.\n *\n * @param {Duplex} socket The connection socket\n * @param {Object} [extensions] An object containing the negotiated extensions\n * @param {Function} [generateMask] The function used to generate the masking\n * key\n */\n constructor(socket, extensions, generateMask) {\n this._extensions = extensions || {};\n\n if (generateMask) {\n this._generateMask = generateMask;\n this._maskBuffer = Buffer.alloc(4);\n }\n\n this._socket = socket;\n\n this._firstFragment = true;\n this._compress = false;\n\n this._bufferedBytes = 0;\n this._queue = [];\n this._state = DEFAULT;\n this.onerror = NOOP;\n this[kWebSocket] = undefined;\n }\n\n /**\n * Frames a piece of data according to the HyBi WebSocket protocol.\n *\n * @param {(Buffer|String)} data The data to frame\n * @param {Object} options Options object\n * @param {Boolean} [options.fin=false] Specifies whether or not to set the\n * FIN bit\n * @param {Function} [options.generateMask] The function used to generate the\n * masking key\n * @param {Boolean} [options.mask=false] Specifies whether or not to mask\n * `data`\n * @param {Buffer} [options.maskBuffer] The buffer used to store the masking\n * key\n * @param {Number} options.opcode The opcode\n * @param {Boolean} [options.readOnly=false] Specifies whether `data` can be\n * modified\n * @param {Boolean} [options.rsv1=false] Specifies whether or not to set the\n * RSV1 bit\n * @return {(Buffer|String)[]} The framed data\n * @public\n */\n static frame(data, options) {\n let mask;\n let merge = false;\n let offset = 2;\n let skipMasking = false;\n\n if (options.mask) {\n mask = options.maskBuffer || maskBuffer;\n\n if (options.generateMask) {\n options.generateMask(mask);\n } else {\n if (randomPoolPointer === RANDOM_POOL_SIZE) {\n /* istanbul ignore else */\n if (randomPool === undefined) {\n //\n // This is lazily initialized because server-sent frames must not\n // be masked so it may never be used.\n //\n randomPool = Buffer.alloc(RANDOM_POOL_SIZE);\n }\n\n randomFillSync(randomPool, 0, RANDOM_POOL_SIZE);\n randomPoolPointer = 0;\n }\n\n mask[0] = randomPool[randomPoolPointer++];\n mask[1] = randomPool[randomPoolPointer++];\n mask[2] = randomPool[randomPoolPointer++];\n mask[3] = randomPool[randomPoolPointer++];\n }\n\n skipMasking = (mask[0] | mask[1] | mask[2] | mask[3]) === 0;\n offset = 6;\n }\n\n let dataLength;\n\n if (typeof data === 'string') {\n if (\n (!options.mask || skipMasking) &&\n options[kByteLength] !== undefined\n ) {\n dataLength = options[kByteLength];\n } else {\n data = Buffer.from(data);\n dataLength = data.length;\n }\n } else {\n dataLength = data.length;\n merge = options.mask && options.readOnly && !skipMasking;\n }\n\n let payloadLength = dataLength;\n\n if (dataLength >= 65536) {\n offset += 8;\n payloadLength = 127;\n } else if (dataLength > 125) {\n offset += 2;\n payloadLength = 126;\n }\n\n const target = Buffer.allocUnsafe(merge ? dataLength + offset : offset);\n\n target[0] = options.fin ? options.opcode | 0x80 : options.opcode;\n if (options.rsv1) target[0] |= 0x40;\n\n target[1] = payloadLength;\n\n if (payloadLength === 126) {\n target.writeUInt16BE(dataLength, 2);\n } else if (payloadLength === 127) {\n target[2] = target[3] = 0;\n target.writeUIntBE(dataLength, 4, 6);\n }\n\n if (!options.mask) return [target, data];\n\n target[1] |= 0x80;\n target[offset - 4] = mask[0];\n target[offset - 3] = mask[1];\n target[offset - 2] = mask[2];\n target[offset - 1] = mask[3];\n\n if (skipMasking) return [target, data];\n\n if (merge) {\n applyMask(data, mask, target, offset, dataLength);\n return [target];\n }\n\n applyMask(data, mask, data, 0, dataLength);\n return [target, data];\n }\n\n /**\n * Sends a close message to the other peer.\n *\n * @param {Number} [code] The status code component of the body\n * @param {(String|Buffer)} [data] The message component of the body\n * @param {Boolean} [mask=false] Specifies whether or not to mask the message\n * @param {Function} [cb] Callback\n * @public\n */\n close(code, data, mask, cb) {\n let buf;\n\n if (code === undefined) {\n buf = EMPTY_BUFFER;\n } else if (typeof code !== 'number' || !isValidStatusCode(code)) {\n throw new TypeError('First argument must be a valid error code number');\n } else if (data === undefined || !data.length) {\n buf = Buffer.allocUnsafe(2);\n buf.writeUInt16BE(code, 0);\n } else {\n const length = Buffer.byteLength(data);\n\n if (length > 123) {\n throw new RangeError('The message must not be greater than 123 bytes');\n }\n\n buf = Buffer.allocUnsafe(2 + length);\n buf.writeUInt16BE(code, 0);\n\n if (typeof data === 'string') {\n buf.write(data, 2);\n } else {\n buf.set(data, 2);\n }\n }\n\n const options = {\n [kByteLength]: buf.length,\n fin: true,\n generateMask: this._generateMask,\n mask,\n maskBuffer: this._maskBuffer,\n opcode: 0x08,\n readOnly: false,\n rsv1: false\n };\n\n if (this._state !== DEFAULT) {\n this.enqueue([this.dispatch, buf, false, options, cb]);\n } else {\n this.sendFrame(Sender.frame(buf, options), cb);\n }\n }\n\n /**\n * Sends a ping message to the other peer.\n *\n * @param {*} data The message to send\n * @param {Boolean} [mask=false] Specifies whether or not to mask `data`\n * @param {Function} [cb] Callback\n * @public\n */\n ping(data, mask, cb) {\n let byteLength;\n let readOnly;\n\n if (typeof data === 'string') {\n byteLength = Buffer.byteLength(data);\n readOnly = false;\n } else if (isBlob(data)) {\n byteLength = data.size;\n readOnly = false;\n } else {\n data = toBuffer(data);\n byteLength = data.length;\n readOnly = toBuffer.readOnly;\n }\n\n if (byteLength > 125) {\n throw new RangeError('The data size must not be greater than 125 bytes');\n }\n\n const options = {\n [kByteLength]: byteLength,\n fin: true,\n generateMask: this._generateMask,\n mask,\n maskBuffer: this._maskBuffer,\n opcode: 0x09,\n readOnly,\n rsv1: false\n };\n\n if (isBlob(data)) {\n if (this._state !== DEFAULT) {\n this.enqueue([this.getBlobData, data, false, options, cb]);\n } else {\n this.getBlobData(data, false, options, cb);\n }\n } else if (this._state !== DEFAULT) {\n this.enqueue([this.dispatch, data, false, options, cb]);\n } else {\n this.sendFrame(Sender.frame(data, options), cb);\n }\n }\n\n /**\n * Sends a pong message to the other peer.\n *\n * @param {*} data The message to send\n * @param {Boolean} [mask=false] Specifies whether or not to mask `data`\n * @param {Function} [cb] Callback\n * @public\n */\n pong(data, mask, cb) {\n let byteLength;\n let readOnly;\n\n if (typeof data === 'string') {\n byteLength = Buffer.byteLength(data);\n readOnly = false;\n } else if (isBlob(data)) {\n byteLength = data.size;\n readOnly = false;\n } else {\n data = toBuffer(data);\n byteLength = data.length;\n readOnly = toBuffer.readOnly;\n }\n\n if (byteLength > 125) {\n throw new RangeError('The data size must not be greater than 125 bytes');\n }\n\n const options = {\n [kByteLength]: byteLength,\n fin: true,\n generateMask: this._generateMask,\n mask,\n maskBuffer: this._maskBuffer,\n opcode: 0x0a,\n readOnly,\n rsv1: false\n };\n\n if (isBlob(data)) {\n if (this._state !== DEFAULT) {\n this.enqueue([this.getBlobData, data, false, options, cb]);\n } else {\n this.getBlobData(data, false, options, cb);\n }\n } else if (this._state !== DEFAULT) {\n this.enqueue([this.dispatch, data, false, options, cb]);\n } else {\n this.sendFrame(Sender.frame(data, options), cb);\n }\n }\n\n /**\n * Sends a data message to the other peer.\n *\n * @param {*} data The message to send\n * @param {Object} options Options object\n * @param {Boolean} [options.binary=false] Specifies whether `data` is binary\n * or text\n * @param {Boolean} [options.compress=false] Specifies whether or not to\n * compress `data`\n * @param {Boolean} [options.fin=false] Specifies whether the fragment is the\n * last one\n * @param {Boolean} [options.mask=false] Specifies whether or not to mask\n * `data`\n * @param {Function} [cb] Callback\n * @public\n */\n send(data, options, cb) {\n const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName];\n let opcode = options.binary ? 2 : 1;\n let rsv1 = options.compress;\n\n let byteLength;\n let readOnly;\n\n if (typeof data === 'string') {\n byteLength = Buffer.byteLength(data);\n readOnly = false;\n } else if (isBlob(data)) {\n byteLength = data.size;\n readOnly = false;\n } else {\n data = toBuffer(data);\n byteLength = data.length;\n readOnly = toBuffer.readOnly;\n }\n\n if (this._firstFragment) {\n this._firstFragment = false;\n if (\n rsv1 &&\n perMessageDeflate &&\n perMessageDeflate.params[\n perMessageDeflate._isServer\n ? 'server_no_context_takeover'\n : 'client_no_context_takeover'\n ]\n ) {\n rsv1 = byteLength >= perMessageDeflate._threshold;\n }\n this._compress = rsv1;\n } else {\n rsv1 = false;\n opcode = 0;\n }\n\n if (options.fin) this._firstFragment = true;\n\n const opts = {\n [kByteLength]: byteLength,\n fin: options.fin,\n generateMask: this._generateMask,\n mask: options.mask,\n maskBuffer: this._maskBuffer,\n opcode,\n readOnly,\n rsv1\n };\n\n if (isBlob(data)) {\n if (this._state !== DEFAULT) {\n this.enqueue([this.getBlobData, data, this._compress, opts, cb]);\n } else {\n this.getBlobData(data, this._compress, opts, cb);\n }\n } else if (this._state !== DEFAULT) {\n this.enqueue([this.dispatch, data, this._compress, opts, cb]);\n } else {\n this.dispatch(data, this._compress, opts, cb);\n }\n }\n\n /**\n * Gets the contents of a blob as binary data.\n *\n * @param {Blob} blob The blob\n * @param {Boolean} [compress=false] Specifies whether or not to compress\n * the data\n * @param {Object} options Options object\n * @param {Boolean} [options.fin=false] Specifies whether or not to set the\n * FIN bit\n * @param {Function} [options.generateMask] The function used to generate the\n * masking key\n * @param {Boolean} [options.mask=false] Specifies whether or not to mask\n * `data`\n * @param {Buffer} [options.maskBuffer] The buffer used to store the masking\n * key\n * @param {Number} options.opcode The opcode\n * @param {Boolean} [options.readOnly=false] Specifies whether `data` can be\n * modified\n * @param {Boolean} [options.rsv1=false] Specifies whether or not to set the\n * RSV1 bit\n * @param {Function} [cb] Callback\n * @private\n */\n getBlobData(blob, compress, options, cb) {\n this._bufferedBytes += options[kByteLength];\n this._state = GET_BLOB_DATA;\n\n blob\n .arrayBuffer()\n .then((arrayBuffer) => {\n if (this._socket.destroyed) {\n const err = new Error(\n 'The socket was closed while the blob was being read'\n );\n\n //\n // `callCallbacks` is called in the next tick to ensure that errors\n // that might be thrown in the callbacks behave like errors thrown\n // outside the promise chain.\n //\n process.nextTick(callCallbacks, this, err, cb);\n return;\n }\n\n this._bufferedBytes -= options[kByteLength];\n const data = toBuffer(arrayBuffer);\n\n if (!compress) {\n this._state = DEFAULT;\n this.sendFrame(Sender.frame(data, options), cb);\n this.dequeue();\n } else {\n this.dispatch(data, compress, options, cb);\n }\n })\n .catch((err) => {\n //\n // `onError` is called in the next tick for the same reason that\n // `callCallbacks` above is.\n //\n process.nextTick(onError, this, err, cb);\n });\n }\n\n /**\n * Dispatches a message.\n *\n * @param {(Buffer|String)} data The message to send\n * @param {Boolean} [compress=false] Specifies whether or not to compress\n * `data`\n * @param {Object} options Options object\n * @param {Boolean} [options.fin=false] Specifies whether or not to set the\n * FIN bit\n * @param {Function} [options.generateMask] The function used to generate the\n * masking key\n * @param {Boolean} [options.mask=false] Specifies whether or not to mask\n * `data`\n * @param {Buffer} [options.maskBuffer] The buffer used to store the masking\n * key\n * @param {Number} options.opcode The opcode\n * @param {Boolean} [options.readOnly=false] Specifies whether `data` can be\n * modified\n * @param {Boolean} [options.rsv1=false] Specifies whether or not to set the\n * RSV1 bit\n * @param {Function} [cb] Callback\n * @private\n */\n dispatch(data, compress, options, cb) {\n if (!compress) {\n this.sendFrame(Sender.frame(data, options), cb);\n return;\n }\n\n const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName];\n\n this._bufferedBytes += options[kByteLength];\n this._state = DEFLATING;\n perMessageDeflate.compress(data, options.fin, (_, buf) => {\n if (this._socket.destroyed) {\n const err = new Error(\n 'The socket was closed while data was being compressed'\n );\n\n callCallbacks(this, err, cb);\n return;\n }\n\n this._bufferedBytes -= options[kByteLength];\n this._state = DEFAULT;\n options.readOnly = false;\n this.sendFrame(Sender.frame(buf, options), cb);\n this.dequeue();\n });\n }\n\n /**\n * Executes queued send operations.\n *\n * @private\n */\n dequeue() {\n while (this._state === DEFAULT && this._queue.length) {\n const params = this._queue.shift();\n\n this._bufferedBytes -= params[3][kByteLength];\n Reflect.apply(params[0], this, params.slice(1));\n }\n }\n\n /**\n * Enqueues a send operation.\n *\n * @param {Array} params Send operation parameters.\n * @private\n */\n enqueue(params) {\n this._bufferedBytes += params[3][kByteLength];\n this._queue.push(params);\n }\n\n /**\n * Sends a frame.\n *\n * @param {(Buffer | String)[]} list The frame to send\n * @param {Function} [cb] Callback\n * @private\n */\n sendFrame(list, cb) {\n if (list.length === 2) {\n this._socket.cork();\n this._socket.write(list[0]);\n this._socket.write(list[1], cb);\n this._socket.uncork();\n } else {\n this._socket.write(list[0], cb);\n }\n }\n}\n\nmodule.exports = Sender;\n\n/**\n * Calls queued callbacks with an error.\n *\n * @param {Sender} sender The `Sender` instance\n * @param {Error} err The error to call the callbacks with\n * @param {Function} [cb] The first callback\n * @private\n */\nfunction callCallbacks(sender, err, cb) {\n if (typeof cb === 'function') cb(err);\n\n for (let i = 0; i < sender._queue.length; i++) {\n const params = sender._queue[i];\n const callback = params[params.length - 1];\n\n if (typeof callback === 'function') callback(err);\n }\n}\n\n/**\n * Handles a `Sender` error.\n *\n * @param {Sender} sender The `Sender` instance\n * @param {Error} err The error\n * @param {Function} [cb] The first pending callback\n * @private\n */\nfunction onError(sender, err, cb) {\n callCallbacks(sender, err, cb);\n sender.onerror(err);\n}\n","'use strict';\n\nconst { kForOnEventAttribute, kListener } = require('./constants');\n\nconst kCode = Symbol('kCode');\nconst kData = Symbol('kData');\nconst kError = Symbol('kError');\nconst kMessage = Symbol('kMessage');\nconst kReason = Symbol('kReason');\nconst kTarget = Symbol('kTarget');\nconst kType = Symbol('kType');\nconst kWasClean = Symbol('kWasClean');\n\n/**\n * Class representing an event.\n */\nclass Event {\n /**\n * Create a new `Event`.\n *\n * @param {String} type The name of the event\n * @throws {TypeError} If the `type` argument is not specified\n */\n constructor(type) {\n this[kTarget] = null;\n this[kType] = type;\n }\n\n /**\n * @type {*}\n */\n get target() {\n return this[kTarget];\n }\n\n /**\n * @type {String}\n */\n get type() {\n return this[kType];\n }\n}\n\nObject.defineProperty(Event.prototype, 'target', { enumerable: true });\nObject.defineProperty(Event.prototype, 'type', { enumerable: true });\n\n/**\n * Class representing a close event.\n *\n * @extends Event\n */\nclass CloseEvent extends Event {\n /**\n * Create a new `CloseEvent`.\n *\n * @param {String} type The name of the event\n * @param {Object} [options] A dictionary object that allows for setting\n * attributes via object members of the same name\n * @param {Number} [options.code=0] The status code explaining why the\n * connection was closed\n * @param {String} [options.reason=''] A human-readable string explaining why\n * the connection was closed\n * @param {Boolean} [options.wasClean=false] Indicates whether or not the\n * connection was cleanly closed\n */\n constructor(type, options = {}) {\n super(type);\n\n this[kCode] = options.code === undefined ? 0 : options.code;\n this[kReason] = options.reason === undefined ? '' : options.reason;\n this[kWasClean] = options.wasClean === undefined ? false : options.wasClean;\n }\n\n /**\n * @type {Number}\n */\n get code() {\n return this[kCode];\n }\n\n /**\n * @type {String}\n */\n get reason() {\n return this[kReason];\n }\n\n /**\n * @type {Boolean}\n */\n get wasClean() {\n return this[kWasClean];\n }\n}\n\nObject.defineProperty(CloseEvent.prototype, 'code', { enumerable: true });\nObject.defineProperty(CloseEvent.prototype, 'reason', { enumerable: true });\nObject.defineProperty(CloseEvent.prototype, 'wasClean', { enumerable: true });\n\n/**\n * Class representing an error event.\n *\n * @extends Event\n */\nclass ErrorEvent extends Event {\n /**\n * Create a new `ErrorEvent`.\n *\n * @param {String} type The name of the event\n * @param {Object} [options] A dictionary object that allows for setting\n * attributes via object members of the same name\n * @param {*} [options.error=null] The error that generated this event\n * @param {String} [options.message=''] The error message\n */\n constructor(type, options = {}) {\n super(type);\n\n this[kError] = options.error === undefined ? null : options.error;\n this[kMessage] = options.message === undefined ? '' : options.message;\n }\n\n /**\n * @type {*}\n */\n get error() {\n return this[kError];\n }\n\n /**\n * @type {String}\n */\n get message() {\n return this[kMessage];\n }\n}\n\nObject.defineProperty(ErrorEvent.prototype, 'error', { enumerable: true });\nObject.defineProperty(ErrorEvent.prototype, 'message', { enumerable: true });\n\n/**\n * Class representing a message event.\n *\n * @extends Event\n */\nclass MessageEvent extends Event {\n /**\n * Create a new `MessageEvent`.\n *\n * @param {String} type The name of the event\n * @param {Object} [options] A dictionary object that allows for setting\n * attributes via object members of the same name\n * @param {*} [options.data=null] The message content\n */\n constructor(type, options = {}) {\n super(type);\n\n this[kData] = options.data === undefined ? null : options.data;\n }\n\n /**\n * @type {*}\n */\n get data() {\n return this[kData];\n }\n}\n\nObject.defineProperty(MessageEvent.prototype, 'data', { enumerable: true });\n\n/**\n * This provides methods for emulating the `EventTarget` interface. It's not\n * meant to be used directly.\n *\n * @mixin\n */\nconst EventTarget = {\n /**\n * Register an event listener.\n *\n * @param {String} type A string representing the event type to listen for\n * @param {(Function|Object)} handler The listener to add\n * @param {Object} [options] An options object specifies characteristics about\n * the event listener\n * @param {Boolean} [options.once=false] A `Boolean` indicating that the\n * listener should be invoked at most once after being added. If `true`,\n * the listener would be automatically removed when invoked.\n * @public\n */\n addEventListener(type, handler, options = {}) {\n for (const listener of this.listeners(type)) {\n if (\n !options[kForOnEventAttribute] &&\n listener[kListener] === handler &&\n !listener[kForOnEventAttribute]\n ) {\n return;\n }\n }\n\n let wrapper;\n\n if (type === 'message') {\n wrapper = function onMessage(data, isBinary) {\n const event = new MessageEvent('message', {\n data: isBinary ? data : data.toString()\n });\n\n event[kTarget] = this;\n callListener(handler, this, event);\n };\n } else if (type === 'close') {\n wrapper = function onClose(code, message) {\n const event = new CloseEvent('close', {\n code,\n reason: message.toString(),\n wasClean: this._closeFrameReceived && this._closeFrameSent\n });\n\n event[kTarget] = this;\n callListener(handler, this, event);\n };\n } else if (type === 'error') {\n wrapper = function onError(error) {\n const event = new ErrorEvent('error', {\n error,\n message: error.message\n });\n\n event[kTarget] = this;\n callListener(handler, this, event);\n };\n } else if (type === 'open') {\n wrapper = function onOpen() {\n const event = new Event('open');\n\n event[kTarget] = this;\n callListener(handler, this, event);\n };\n } else {\n return;\n }\n\n wrapper[kForOnEventAttribute] = !!options[kForOnEventAttribute];\n wrapper[kListener] = handler;\n\n if (options.once) {\n this.once(type, wrapper);\n } else {\n this.on(type, wrapper);\n }\n },\n\n /**\n * Remove an event listener.\n *\n * @param {String} type A string representing the event type to remove\n * @param {(Function|Object)} handler The listener to remove\n * @public\n */\n removeEventListener(type, handler) {\n for (const listener of this.listeners(type)) {\n if (listener[kListener] === handler && !listener[kForOnEventAttribute]) {\n this.removeListener(type, listener);\n break;\n }\n }\n }\n};\n\nmodule.exports = {\n CloseEvent,\n ErrorEvent,\n Event,\n EventTarget,\n MessageEvent\n};\n\n/**\n * Call an event listener\n *\n * @param {(Function|Object)} listener The listener to call\n * @param {*} thisArg The value to use as `this`` when calling the listener\n * @param {Event} event The event to pass to the listener\n * @private\n */\nfunction callListener(listener, thisArg, event) {\n if (typeof listener === 'object' && listener.handleEvent) {\n listener.handleEvent.call(listener, event);\n } else {\n listener.call(thisArg, event);\n }\n}\n","'use strict';\n\nconst { tokenChars } = require('./validation');\n\n/**\n * Adds an offer to the map of extension offers or a parameter to the map of\n * parameters.\n *\n * @param {Object} dest The map of extension offers or parameters\n * @param {String} name The extension or parameter name\n * @param {(Object|Boolean|String)} elem The extension parameters or the\n * parameter value\n * @private\n */\nfunction push(dest, name, elem) {\n if (dest[name] === undefined) dest[name] = [elem];\n else dest[name].push(elem);\n}\n\n/**\n * Parses the `Sec-WebSocket-Extensions` header into an object.\n *\n * @param {String} header The field value of the header\n * @return {Object} The parsed object\n * @public\n */\nfunction parse(header) {\n const offers = Object.create(null);\n let params = Object.create(null);\n let mustUnescape = false;\n let isEscaping = false;\n let inQuotes = false;\n let extensionName;\n let paramName;\n let start = -1;\n let code = -1;\n let end = -1;\n let i = 0;\n\n for (; i < header.length; i++) {\n code = header.charCodeAt(i);\n\n if (extensionName === undefined) {\n if (end === -1 && tokenChars[code] === 1) {\n if (start === -1) start = i;\n } else if (\n i !== 0 &&\n (code === 0x20 /* ' ' */ || code === 0x09) /* '\\t' */\n ) {\n if (end === -1 && start !== -1) end = i;\n } else if (code === 0x3b /* ';' */ || code === 0x2c /* ',' */) {\n if (start === -1) {\n throw new SyntaxError(`Unexpected character at index ${i}`);\n }\n\n if (end === -1) end = i;\n const name = header.slice(start, end);\n if (code === 0x2c) {\n push(offers, name, params);\n params = Object.create(null);\n } else {\n extensionName = name;\n }\n\n start = end = -1;\n } else {\n throw new SyntaxError(`Unexpected character at index ${i}`);\n }\n } else if (paramName === undefined) {\n if (end === -1 && tokenChars[code] === 1) {\n if (start === -1) start = i;\n } else if (code === 0x20 || code === 0x09) {\n if (end === -1 && start !== -1) end = i;\n } else if (code === 0x3b || code === 0x2c) {\n if (start === -1) {\n throw new SyntaxError(`Unexpected character at index ${i}`);\n }\n\n if (end === -1) end = i;\n push(params, header.slice(start, end), true);\n if (code === 0x2c) {\n push(offers, extensionName, params);\n params = Object.create(null);\n extensionName = undefined;\n }\n\n start = end = -1;\n } else if (code === 0x3d /* '=' */ && start !== -1 && end === -1) {\n paramName = header.slice(start, i);\n start = end = -1;\n } else {\n throw new SyntaxError(`Unexpected character at index ${i}`);\n }\n } else {\n //\n // The value of a quoted-string after unescaping must conform to the\n // token ABNF, so only token characters are valid.\n // Ref: https://tools.ietf.org/html/rfc6455#section-9.1\n //\n if (isEscaping) {\n if (tokenChars[code] !== 1) {\n throw new SyntaxError(`Unexpected character at index ${i}`);\n }\n if (start === -1) start = i;\n else if (!mustUnescape) mustUnescape = true;\n isEscaping = false;\n } else if (inQuotes) {\n if (tokenChars[code] === 1) {\n if (start === -1) start = i;\n } else if (code === 0x22 /* '\"' */ && start !== -1) {\n inQuotes = false;\n end = i;\n } else if (code === 0x5c /* '\\' */) {\n isEscaping = true;\n } else {\n throw new SyntaxError(`Unexpected character at index ${i}`);\n }\n } else if (code === 0x22 && header.charCodeAt(i - 1) === 0x3d) {\n inQuotes = true;\n } else if (end === -1 && tokenChars[code] === 1) {\n if (start === -1) start = i;\n } else if (start !== -1 && (code === 0x20 || code === 0x09)) {\n if (end === -1) end = i;\n } else if (code === 0x3b || code === 0x2c) {\n if (start === -1) {\n throw new SyntaxError(`Unexpected character at index ${i}`);\n }\n\n if (end === -1) end = i;\n let value = header.slice(start, end);\n if (mustUnescape) {\n value = value.replace(/\\\\/g, '');\n mustUnescape = false;\n }\n push(params, paramName, value);\n if (code === 0x2c) {\n push(offers, extensionName, params);\n params = Object.create(null);\n extensionName = undefined;\n }\n\n paramName = undefined;\n start = end = -1;\n } else {\n throw new SyntaxError(`Unexpected character at index ${i}`);\n }\n }\n }\n\n if (start === -1 || inQuotes || code === 0x20 || code === 0x09) {\n throw new SyntaxError('Unexpected end of input');\n }\n\n if (end === -1) end = i;\n const token = header.slice(start, end);\n if (extensionName === undefined) {\n push(offers, token, params);\n } else {\n if (paramName === undefined) {\n push(params, token, true);\n } else if (mustUnescape) {\n push(params, paramName, token.replace(/\\\\/g, ''));\n } else {\n push(params, paramName, token);\n }\n push(offers, extensionName, params);\n }\n\n return offers;\n}\n\n/**\n * Builds the `Sec-WebSocket-Extensions` header field value.\n *\n * @param {Object} extensions The map of extensions and parameters to format\n * @return {String} A string representing the given object\n * @public\n */\nfunction format(extensions) {\n return Object.keys(extensions)\n .map((extension) => {\n let configurations = extensions[extension];\n if (!Array.isArray(configurations)) configurations = [configurations];\n return configurations\n .map((params) => {\n return [extension]\n .concat(\n Object.keys(params).map((k) => {\n let values = params[k];\n if (!Array.isArray(values)) values = [values];\n return values\n .map((v) => (v === true ? k : `${k}=${v}`))\n .join('; ');\n })\n )\n .join('; ');\n })\n .join(', ');\n })\n .join(', ');\n}\n\nmodule.exports = { format, parse };\n","/* eslint no-unused-vars: [\"error\", { \"varsIgnorePattern\": \"^Duplex|Readable$\", \"caughtErrors\": \"none\" }] */\n\n'use strict';\n\nconst EventEmitter = require('events');\nconst https = require('https');\nconst http = require('http');\nconst net = require('net');\nconst tls = require('tls');\nconst { randomBytes, createHash } = require('crypto');\nconst { Duplex, Readable } = require('stream');\nconst { URL } = require('url');\n\nconst PerMessageDeflate = require('./permessage-deflate');\nconst Receiver = require('./receiver');\nconst Sender = require('./sender');\nconst { isBlob } = require('./validation');\n\nconst {\n BINARY_TYPES,\n CLOSE_TIMEOUT,\n EMPTY_BUFFER,\n GUID,\n kForOnEventAttribute,\n kListener,\n kStatusCode,\n kWebSocket,\n NOOP\n} = require('./constants');\nconst {\n EventTarget: { addEventListener, removeEventListener }\n} = require('./event-target');\nconst { format, parse } = require('./extension');\nconst { toBuffer } = require('./buffer-util');\n\nconst kAborted = Symbol('kAborted');\nconst protocolVersions = [8, 13];\nconst readyStates = ['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED'];\nconst subprotocolRegex = /^[!#$%&'*+\\-.0-9A-Z^_`|a-z~]+$/;\n\n/**\n * Class representing a WebSocket.\n *\n * @extends EventEmitter\n */\nclass WebSocket extends EventEmitter {\n /**\n * Create a new `WebSocket`.\n *\n * @param {(String|URL)} address The URL to which to connect\n * @param {(String|String[])} [protocols] The subprotocols\n * @param {Object} [options] Connection options\n */\n constructor(address, protocols, options) {\n super();\n\n this._binaryType = BINARY_TYPES[0];\n this._closeCode = 1006;\n this._closeFrameReceived = false;\n this._closeFrameSent = false;\n this._closeMessage = EMPTY_BUFFER;\n this._closeTimer = null;\n this._errorEmitted = false;\n this._extensions = {};\n this._paused = false;\n this._protocol = '';\n this._readyState = WebSocket.CONNECTING;\n this._receiver = null;\n this._sender = null;\n this._socket = null;\n\n if (address !== null) {\n this._bufferedAmount = 0;\n this._isServer = false;\n this._redirects = 0;\n\n if (protocols === undefined) {\n protocols = [];\n } else if (!Array.isArray(protocols)) {\n if (typeof protocols === 'object' && protocols !== null) {\n options = protocols;\n protocols = [];\n } else {\n protocols = [protocols];\n }\n }\n\n initAsClient(this, address, protocols, options);\n } else {\n this._autoPong = options.autoPong;\n this._closeTimeout = options.closeTimeout;\n this._isServer = true;\n }\n }\n\n /**\n * For historical reasons, the custom \"nodebuffer\" type is used by the default\n * instead of \"blob\".\n *\n * @type {String}\n */\n get binaryType() {\n return this._binaryType;\n }\n\n set binaryType(type) {\n if (!BINARY_TYPES.includes(type)) return;\n\n this._binaryType = type;\n\n //\n // Allow to change `binaryType` on the fly.\n //\n if (this._receiver) this._receiver._binaryType = type;\n }\n\n /**\n * @type {Number}\n */\n get bufferedAmount() {\n if (!this._socket) return this._bufferedAmount;\n\n return this._socket._writableState.length + this._sender._bufferedBytes;\n }\n\n /**\n * @type {String}\n */\n get extensions() {\n return Object.keys(this._extensions).join();\n }\n\n /**\n * @type {Boolean}\n */\n get isPaused() {\n return this._paused;\n }\n\n /**\n * @type {Function}\n */\n /* istanbul ignore next */\n get onclose() {\n return null;\n }\n\n /**\n * @type {Function}\n */\n /* istanbul ignore next */\n get onerror() {\n return null;\n }\n\n /**\n * @type {Function}\n */\n /* istanbul ignore next */\n get onopen() {\n return null;\n }\n\n /**\n * @type {Function}\n */\n /* istanbul ignore next */\n get onmessage() {\n return null;\n }\n\n /**\n * @type {String}\n */\n get protocol() {\n return this._protocol;\n }\n\n /**\n * @type {Number}\n */\n get readyState() {\n return this._readyState;\n }\n\n /**\n * @type {String}\n */\n get url() {\n return this._url;\n }\n\n /**\n * Set up the socket and the internal resources.\n *\n * @param {Duplex} socket The network socket between the server and client\n * @param {Buffer} head The first packet of the upgraded stream\n * @param {Object} options Options object\n * @param {Boolean} [options.allowSynchronousEvents=false] Specifies whether\n * any of the `'message'`, `'ping'`, and `'pong'` events can be emitted\n * multiple times in the same tick\n * @param {Function} [options.generateMask] The function used to generate the\n * masking key\n * @param {Number} [options.maxPayload=0] The maximum allowed message size\n * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or\n * not to skip UTF-8 validation for text and close messages\n * @private\n */\n setSocket(socket, head, options) {\n const receiver = new Receiver({\n allowSynchronousEvents: options.allowSynchronousEvents,\n binaryType: this.binaryType,\n extensions: this._extensions,\n isServer: this._isServer,\n maxPayload: options.maxPayload,\n skipUTF8Validation: options.skipUTF8Validation\n });\n\n const sender = new Sender(socket, this._extensions, options.generateMask);\n\n this._receiver = receiver;\n this._sender = sender;\n this._socket = socket;\n\n receiver[kWebSocket] = this;\n sender[kWebSocket] = this;\n socket[kWebSocket] = this;\n\n receiver.on('conclude', receiverOnConclude);\n receiver.on('drain', receiverOnDrain);\n receiver.on('error', receiverOnError);\n receiver.on('message', receiverOnMessage);\n receiver.on('ping', receiverOnPing);\n receiver.on('pong', receiverOnPong);\n\n sender.onerror = senderOnError;\n\n //\n // These methods may not be available if `socket` is just a `Duplex`.\n //\n if (socket.setTimeout) socket.setTimeout(0);\n if (socket.setNoDelay) socket.setNoDelay();\n\n if (head.length > 0) socket.unshift(head);\n\n socket.on('close', socketOnClose);\n socket.on('data', socketOnData);\n socket.on('end', socketOnEnd);\n socket.on('error', socketOnError);\n\n this._readyState = WebSocket.OPEN;\n this.emit('open');\n }\n\n /**\n * Emit the `'close'` event.\n *\n * @private\n */\n emitClose() {\n if (!this._socket) {\n this._readyState = WebSocket.CLOSED;\n this.emit('close', this._closeCode, this._closeMessage);\n return;\n }\n\n if (this._extensions[PerMessageDeflate.extensionName]) {\n this._extensions[PerMessageDeflate.extensionName].cleanup();\n }\n\n this._receiver.removeAllListeners();\n this._readyState = WebSocket.CLOSED;\n this.emit('close', this._closeCode, this._closeMessage);\n }\n\n /**\n * Start a closing handshake.\n *\n * +----------+ +-----------+ +----------+\n * - - -|ws.close()|-->|close frame|-->|ws.close()|- - -\n * | +----------+ +-----------+ +----------+ |\n * +----------+ +-----------+ |\n * CLOSING |ws.close()|<--|close frame|<--+-----+ CLOSING\n * +----------+ +-----------+ |\n * | | | +---+ |\n * +------------------------+-->|fin| - - - -\n * | +---+ | +---+\n * - - - - -|fin|<---------------------+\n * +---+\n *\n * @param {Number} [code] Status code explaining why the connection is closing\n * @param {(String|Buffer)} [data] The reason why the connection is\n * closing\n * @public\n */\n close(code, data) {\n if (this.readyState === WebSocket.CLOSED) return;\n if (this.readyState === WebSocket.CONNECTING) {\n const msg = 'WebSocket was closed before the connection was established';\n abortHandshake(this, this._req, msg);\n return;\n }\n\n if (this.readyState === WebSocket.CLOSING) {\n if (\n this._closeFrameSent &&\n (this._closeFrameReceived || this._receiver._writableState.errorEmitted)\n ) {\n this._socket.end();\n }\n\n return;\n }\n\n this._readyState = WebSocket.CLOSING;\n this._sender.close(code, data, !this._isServer, (err) => {\n //\n // This error is handled by the `'error'` listener on the socket. We only\n // want to know if the close frame has been sent here.\n //\n if (err) return;\n\n this._closeFrameSent = true;\n\n if (\n this._closeFrameReceived ||\n this._receiver._writableState.errorEmitted\n ) {\n this._socket.end();\n }\n });\n\n setCloseTimer(this);\n }\n\n /**\n * Pause the socket.\n *\n * @public\n */\n pause() {\n if (\n this.readyState === WebSocket.CONNECTING ||\n this.readyState === WebSocket.CLOSED\n ) {\n return;\n }\n\n this._paused = true;\n this._socket.pause();\n }\n\n /**\n * Send a ping.\n *\n * @param {*} [data] The data to send\n * @param {Boolean} [mask] Indicates whether or not to mask `data`\n * @param {Function} [cb] Callback which is executed when the ping is sent\n * @public\n */\n ping(data, mask, cb) {\n if (this.readyState === WebSocket.CONNECTING) {\n throw new Error('WebSocket is not open: readyState 0 (CONNECTING)');\n }\n\n if (typeof data === 'function') {\n cb = data;\n data = mask = undefined;\n } else if (typeof mask === 'function') {\n cb = mask;\n mask = undefined;\n }\n\n if (typeof data === 'number') data = data.toString();\n\n if (this.readyState !== WebSocket.OPEN) {\n sendAfterClose(this, data, cb);\n return;\n }\n\n if (mask === undefined) mask = !this._isServer;\n this._sender.ping(data || EMPTY_BUFFER, mask, cb);\n }\n\n /**\n * Send a pong.\n *\n * @param {*} [data] The data to send\n * @param {Boolean} [mask] Indicates whether or not to mask `data`\n * @param {Function} [cb] Callback which is executed when the pong is sent\n * @public\n */\n pong(data, mask, cb) {\n if (this.readyState === WebSocket.CONNECTING) {\n throw new Error('WebSocket is not open: readyState 0 (CONNECTING)');\n }\n\n if (typeof data === 'function') {\n cb = data;\n data = mask = undefined;\n } else if (typeof mask === 'function') {\n cb = mask;\n mask = undefined;\n }\n\n if (typeof data === 'number') data = data.toString();\n\n if (this.readyState !== WebSocket.OPEN) {\n sendAfterClose(this, data, cb);\n return;\n }\n\n if (mask === undefined) mask = !this._isServer;\n this._sender.pong(data || EMPTY_BUFFER, mask, cb);\n }\n\n /**\n * Resume the socket.\n *\n * @public\n */\n resume() {\n if (\n this.readyState === WebSocket.CONNECTING ||\n this.readyState === WebSocket.CLOSED\n ) {\n return;\n }\n\n this._paused = false;\n if (!this._receiver._writableState.needDrain) this._socket.resume();\n }\n\n /**\n * Send a data message.\n *\n * @param {*} data The message to send\n * @param {Object} [options] Options object\n * @param {Boolean} [options.binary] Specifies whether `data` is binary or\n * text\n * @param {Boolean} [options.compress] Specifies whether or not to compress\n * `data`\n * @param {Boolean} [options.fin=true] Specifies whether the fragment is the\n * last one\n * @param {Boolean} [options.mask] Specifies whether or not to mask `data`\n * @param {Function} [cb] Callback which is executed when data is written out\n * @public\n */\n send(data, options, cb) {\n if (this.readyState === WebSocket.CONNECTING) {\n throw new Error('WebSocket is not open: readyState 0 (CONNECTING)');\n }\n\n if (typeof options === 'function') {\n cb = options;\n options = {};\n }\n\n if (typeof data === 'number') data = data.toString();\n\n if (this.readyState !== WebSocket.OPEN) {\n sendAfterClose(this, data, cb);\n return;\n }\n\n const opts = {\n binary: typeof data !== 'string',\n mask: !this._isServer,\n compress: true,\n fin: true,\n ...options\n };\n\n if (!this._extensions[PerMessageDeflate.extensionName]) {\n opts.compress = false;\n }\n\n this._sender.send(data || EMPTY_BUFFER, opts, cb);\n }\n\n /**\n * Forcibly close the connection.\n *\n * @public\n */\n terminate() {\n if (this.readyState === WebSocket.CLOSED) return;\n if (this.readyState === WebSocket.CONNECTING) {\n const msg = 'WebSocket was closed before the connection was established';\n abortHandshake(this, this._req, msg);\n return;\n }\n\n if (this._socket) {\n this._readyState = WebSocket.CLOSING;\n this._socket.destroy();\n }\n }\n}\n\n/**\n * @constant {Number} CONNECTING\n * @memberof WebSocket\n */\nObject.defineProperty(WebSocket, 'CONNECTING', {\n enumerable: true,\n value: readyStates.indexOf('CONNECTING')\n});\n\n/**\n * @constant {Number} CONNECTING\n * @memberof WebSocket.prototype\n */\nObject.defineProperty(WebSocket.prototype, 'CONNECTING', {\n enumerable: true,\n value: readyStates.indexOf('CONNECTING')\n});\n\n/**\n * @constant {Number} OPEN\n * @memberof WebSocket\n */\nObject.defineProperty(WebSocket, 'OPEN', {\n enumerable: true,\n value: readyStates.indexOf('OPEN')\n});\n\n/**\n * @constant {Number} OPEN\n * @memberof WebSocket.prototype\n */\nObject.defineProperty(WebSocket.prototype, 'OPEN', {\n enumerable: true,\n value: readyStates.indexOf('OPEN')\n});\n\n/**\n * @constant {Number} CLOSING\n * @memberof WebSocket\n */\nObject.defineProperty(WebSocket, 'CLOSING', {\n enumerable: true,\n value: readyStates.indexOf('CLOSING')\n});\n\n/**\n * @constant {Number} CLOSING\n * @memberof WebSocket.prototype\n */\nObject.defineProperty(WebSocket.prototype, 'CLOSING', {\n enumerable: true,\n value: readyStates.indexOf('CLOSING')\n});\n\n/**\n * @constant {Number} CLOSED\n * @memberof WebSocket\n */\nObject.defineProperty(WebSocket, 'CLOSED', {\n enumerable: true,\n value: readyStates.indexOf('CLOSED')\n});\n\n/**\n * @constant {Number} CLOSED\n * @memberof WebSocket.prototype\n */\nObject.defineProperty(WebSocket.prototype, 'CLOSED', {\n enumerable: true,\n value: readyStates.indexOf('CLOSED')\n});\n\n[\n 'binaryType',\n 'bufferedAmount',\n 'extensions',\n 'isPaused',\n 'protocol',\n 'readyState',\n 'url'\n].forEach((property) => {\n Object.defineProperty(WebSocket.prototype, property, { enumerable: true });\n});\n\n//\n// Add the `onopen`, `onerror`, `onclose`, and `onmessage` attributes.\n// See https://html.spec.whatwg.org/multipage/comms.html#the-websocket-interface\n//\n['open', 'error', 'close', 'message'].forEach((method) => {\n Object.defineProperty(WebSocket.prototype, `on${method}`, {\n enumerable: true,\n get() {\n for (const listener of this.listeners(method)) {\n if (listener[kForOnEventAttribute]) return listener[kListener];\n }\n\n return null;\n },\n set(handler) {\n for (const listener of this.listeners(method)) {\n if (listener[kForOnEventAttribute]) {\n this.removeListener(method, listener);\n break;\n }\n }\n\n if (typeof handler !== 'function') return;\n\n this.addEventListener(method, handler, {\n [kForOnEventAttribute]: true\n });\n }\n });\n});\n\nWebSocket.prototype.addEventListener = addEventListener;\nWebSocket.prototype.removeEventListener = removeEventListener;\n\nmodule.exports = WebSocket;\n\n/**\n * Initialize a WebSocket client.\n *\n * @param {WebSocket} websocket The client to initialize\n * @param {(String|URL)} address The URL to which to connect\n * @param {Array} protocols The subprotocols\n * @param {Object} [options] Connection options\n * @param {Boolean} [options.allowSynchronousEvents=true] Specifies whether any\n * of the `'message'`, `'ping'`, and `'pong'` events can be emitted multiple\n * times in the same tick\n * @param {Boolean} [options.autoPong=true] Specifies whether or not to\n * automatically send a pong in response to a ping\n * @param {Number} [options.closeTimeout=30000] Duration in milliseconds to wait\n * for the closing handshake to finish after `websocket.close()` is called\n * @param {Function} [options.finishRequest] A function which can be used to\n * customize the headers of each http request before it is sent\n * @param {Boolean} [options.followRedirects=false] Whether or not to follow\n * redirects\n * @param {Function} [options.generateMask] The function used to generate the\n * masking key\n * @param {Number} [options.handshakeTimeout] Timeout in milliseconds for the\n * handshake request\n * @param {Number} [options.maxPayload=104857600] The maximum allowed message\n * size\n * @param {Number} [options.maxRedirects=10] The maximum number of redirects\n * allowed\n * @param {String} [options.origin] Value of the `Origin` or\n * `Sec-WebSocket-Origin` header\n * @param {(Boolean|Object)} [options.perMessageDeflate=true] Enable/disable\n * permessage-deflate\n * @param {Number} [options.protocolVersion=13] Value of the\n * `Sec-WebSocket-Version` header\n * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or\n * not to skip UTF-8 validation for text and close messages\n * @private\n */\nfunction initAsClient(websocket, address, protocols, options) {\n const opts = {\n allowSynchronousEvents: true,\n autoPong: true,\n closeTimeout: CLOSE_TIMEOUT,\n protocolVersion: protocolVersions[1],\n maxPayload: 100 * 1024 * 1024,\n skipUTF8Validation: false,\n perMessageDeflate: true,\n followRedirects: false,\n maxRedirects: 10,\n ...options,\n socketPath: undefined,\n hostname: undefined,\n protocol: undefined,\n timeout: undefined,\n method: 'GET',\n host: undefined,\n path: undefined,\n port: undefined\n };\n\n websocket._autoPong = opts.autoPong;\n websocket._closeTimeout = opts.closeTimeout;\n\n if (!protocolVersions.includes(opts.protocolVersion)) {\n throw new RangeError(\n `Unsupported protocol version: ${opts.protocolVersion} ` +\n `(supported versions: ${protocolVersions.join(', ')})`\n );\n }\n\n let parsedUrl;\n\n if (address instanceof URL) {\n parsedUrl = address;\n } else {\n try {\n parsedUrl = new URL(address);\n } catch (e) {\n throw new SyntaxError(`Invalid URL: ${address}`);\n }\n }\n\n if (parsedUrl.protocol === 'http:') {\n parsedUrl.protocol = 'ws:';\n } else if (parsedUrl.protocol === 'https:') {\n parsedUrl.protocol = 'wss:';\n }\n\n websocket._url = parsedUrl.href;\n\n const isSecure = parsedUrl.protocol === 'wss:';\n const isIpcUrl = parsedUrl.protocol === 'ws+unix:';\n let invalidUrlMessage;\n\n if (parsedUrl.protocol !== 'ws:' && !isSecure && !isIpcUrl) {\n invalidUrlMessage =\n 'The URL\\'s protocol must be one of \"ws:\", \"wss:\", ' +\n '\"http:\", \"https:\", or \"ws+unix:\"';\n } else if (isIpcUrl && !parsedUrl.pathname) {\n invalidUrlMessage = \"The URL's pathname is empty\";\n } else if (parsedUrl.hash) {\n invalidUrlMessage = 'The URL contains a fragment identifier';\n }\n\n if (invalidUrlMessage) {\n const err = new SyntaxError(invalidUrlMessage);\n\n if (websocket._redirects === 0) {\n throw err;\n } else {\n emitErrorAndClose(websocket, err);\n return;\n }\n }\n\n const defaultPort = isSecure ? 443 : 80;\n const key = randomBytes(16).toString('base64');\n const request = isSecure ? https.request : http.request;\n const protocolSet = new Set();\n let perMessageDeflate;\n\n opts.createConnection =\n opts.createConnection || (isSecure ? tlsConnect : netConnect);\n opts.defaultPort = opts.defaultPort || defaultPort;\n opts.port = parsedUrl.port || defaultPort;\n opts.host = parsedUrl.hostname.startsWith('[')\n ? parsedUrl.hostname.slice(1, -1)\n : parsedUrl.hostname;\n opts.headers = {\n ...opts.headers,\n 'Sec-WebSocket-Version': opts.protocolVersion,\n 'Sec-WebSocket-Key': key,\n Connection: 'Upgrade',\n Upgrade: 'websocket'\n };\n opts.path = parsedUrl.pathname + parsedUrl.search;\n opts.timeout = opts.handshakeTimeout;\n\n if (opts.perMessageDeflate) {\n perMessageDeflate = new PerMessageDeflate(\n opts.perMessageDeflate !== true ? opts.perMessageDeflate : {},\n false,\n opts.maxPayload\n );\n opts.headers['Sec-WebSocket-Extensions'] = format({\n [PerMessageDeflate.extensionName]: perMessageDeflate.offer()\n });\n }\n if (protocols.length) {\n for (const protocol of protocols) {\n if (\n typeof protocol !== 'string' ||\n !subprotocolRegex.test(protocol) ||\n protocolSet.has(protocol)\n ) {\n throw new SyntaxError(\n 'An invalid or duplicated subprotocol was specified'\n );\n }\n\n protocolSet.add(protocol);\n }\n\n opts.headers['Sec-WebSocket-Protocol'] = protocols.join(',');\n }\n if (opts.origin) {\n if (opts.protocolVersion < 13) {\n opts.headers['Sec-WebSocket-Origin'] = opts.origin;\n } else {\n opts.headers.Origin = opts.origin;\n }\n }\n if (parsedUrl.username || parsedUrl.password) {\n opts.auth = `${parsedUrl.username}:${parsedUrl.password}`;\n }\n\n if (isIpcUrl) {\n const parts = opts.path.split(':');\n\n opts.socketPath = parts[0];\n opts.path = parts[1];\n }\n\n let req;\n\n if (opts.followRedirects) {\n if (websocket._redirects === 0) {\n websocket._originalIpc = isIpcUrl;\n websocket._originalSecure = isSecure;\n websocket._originalHostOrSocketPath = isIpcUrl\n ? opts.socketPath\n : parsedUrl.host;\n\n const headers = options && options.headers;\n\n //\n // Shallow copy the user provided options so that headers can be changed\n // without mutating the original object.\n //\n options = { ...options, headers: {} };\n\n if (headers) {\n for (const [key, value] of Object.entries(headers)) {\n options.headers[key.toLowerCase()] = value;\n }\n }\n } else if (websocket.listenerCount('redirect') === 0) {\n const isSameHost = isIpcUrl\n ? websocket._originalIpc\n ? opts.socketPath === websocket._originalHostOrSocketPath\n : false\n : websocket._originalIpc\n ? false\n : parsedUrl.host === websocket._originalHostOrSocketPath;\n\n if (!isSameHost || (websocket._originalSecure && !isSecure)) {\n //\n // Match curl 7.77.0 behavior and drop the following headers. These\n // headers are also dropped when following a redirect to a subdomain.\n //\n delete opts.headers.authorization;\n delete opts.headers.cookie;\n\n if (!isSameHost) delete opts.headers.host;\n\n opts.auth = undefined;\n }\n }\n\n //\n // Match curl 7.77.0 behavior and make the first `Authorization` header win.\n // If the `Authorization` header is set, then there is nothing to do as it\n // will take precedence.\n //\n if (opts.auth && !options.headers.authorization) {\n options.headers.authorization =\n 'Basic ' + Buffer.from(opts.auth).toString('base64');\n }\n\n req = websocket._req = request(opts);\n\n if (websocket._redirects) {\n //\n // Unlike what is done for the `'upgrade'` event, no early exit is\n // triggered here if the user calls `websocket.close()` or\n // `websocket.terminate()` from a listener of the `'redirect'` event. This\n // is because the user can also call `request.destroy()` with an error\n // before calling `websocket.close()` or `websocket.terminate()` and this\n // would result in an error being emitted on the `request` object with no\n // `'error'` event listeners attached.\n //\n websocket.emit('redirect', websocket.url, req);\n }\n } else {\n req = websocket._req = request(opts);\n }\n\n if (opts.timeout) {\n req.on('timeout', () => {\n abortHandshake(websocket, req, 'Opening handshake has timed out');\n });\n }\n\n req.on('error', (err) => {\n if (req === null || req[kAborted]) return;\n\n req = websocket._req = null;\n emitErrorAndClose(websocket, err);\n });\n\n req.on('response', (res) => {\n const location = res.headers.location;\n const statusCode = res.statusCode;\n\n if (\n location &&\n opts.followRedirects &&\n statusCode >= 300 &&\n statusCode < 400\n ) {\n if (++websocket._redirects > opts.maxRedirects) {\n abortHandshake(websocket, req, 'Maximum redirects exceeded');\n return;\n }\n\n req.abort();\n\n let addr;\n\n try {\n addr = new URL(location, address);\n } catch (e) {\n const err = new SyntaxError(`Invalid URL: ${location}`);\n emitErrorAndClose(websocket, err);\n return;\n }\n\n initAsClient(websocket, addr, protocols, options);\n } else if (!websocket.emit('unexpected-response', req, res)) {\n abortHandshake(\n websocket,\n req,\n `Unexpected server response: ${res.statusCode}`\n );\n }\n });\n\n req.on('upgrade', (res, socket, head) => {\n websocket.emit('upgrade', res);\n\n //\n // The user may have closed the connection from a listener of the\n // `'upgrade'` event.\n //\n if (websocket.readyState !== WebSocket.CONNECTING) return;\n\n req = websocket._req = null;\n\n const upgrade = res.headers.upgrade;\n\n if (upgrade === undefined || upgrade.toLowerCase() !== 'websocket') {\n abortHandshake(websocket, socket, 'Invalid Upgrade header');\n return;\n }\n\n const digest = createHash('sha1')\n .update(key + GUID)\n .digest('base64');\n\n if (res.headers['sec-websocket-accept'] !== digest) {\n abortHandshake(websocket, socket, 'Invalid Sec-WebSocket-Accept header');\n return;\n }\n\n const serverProt = res.headers['sec-websocket-protocol'];\n let protError;\n\n if (serverProt !== undefined) {\n if (!protocolSet.size) {\n protError = 'Server sent a subprotocol but none was requested';\n } else if (!protocolSet.has(serverProt)) {\n protError = 'Server sent an invalid subprotocol';\n }\n } else if (protocolSet.size) {\n protError = 'Server sent no subprotocol';\n }\n\n if (protError) {\n abortHandshake(websocket, socket, protError);\n return;\n }\n\n if (serverProt) websocket._protocol = serverProt;\n\n const secWebSocketExtensions = res.headers['sec-websocket-extensions'];\n\n if (secWebSocketExtensions !== undefined) {\n if (!perMessageDeflate) {\n const message =\n 'Server sent a Sec-WebSocket-Extensions header but no extension ' +\n 'was requested';\n abortHandshake(websocket, socket, message);\n return;\n }\n\n let extensions;\n\n try {\n extensions = parse(secWebSocketExtensions);\n } catch (err) {\n const message = 'Invalid Sec-WebSocket-Extensions header';\n abortHandshake(websocket, socket, message);\n return;\n }\n\n const extensionNames = Object.keys(extensions);\n\n if (\n extensionNames.length !== 1 ||\n extensionNames[0] !== PerMessageDeflate.extensionName\n ) {\n const message = 'Server indicated an extension that was not requested';\n abortHandshake(websocket, socket, message);\n return;\n }\n\n try {\n perMessageDeflate.accept(extensions[PerMessageDeflate.extensionName]);\n } catch (err) {\n const message = 'Invalid Sec-WebSocket-Extensions header';\n abortHandshake(websocket, socket, message);\n return;\n }\n\n websocket._extensions[PerMessageDeflate.extensionName] =\n perMessageDeflate;\n }\n\n websocket.setSocket(socket, head, {\n allowSynchronousEvents: opts.allowSynchronousEvents,\n generateMask: opts.generateMask,\n maxPayload: opts.maxPayload,\n skipUTF8Validation: opts.skipUTF8Validation\n });\n });\n\n if (opts.finishRequest) {\n opts.finishRequest(req, websocket);\n } else {\n req.end();\n }\n}\n\n/**\n * Emit the `'error'` and `'close'` events.\n *\n * @param {WebSocket} websocket The WebSocket instance\n * @param {Error} The error to emit\n * @private\n */\nfunction emitErrorAndClose(websocket, err) {\n websocket._readyState = WebSocket.CLOSING;\n //\n // The following assignment is practically useless and is done only for\n // consistency.\n //\n websocket._errorEmitted = true;\n websocket.emit('error', err);\n websocket.emitClose();\n}\n\n/**\n * Create a `net.Socket` and initiate a connection.\n *\n * @param {Object} options Connection options\n * @return {net.Socket} The newly created socket used to start the connection\n * @private\n */\nfunction netConnect(options) {\n options.path = options.socketPath;\n return net.connect(options);\n}\n\n/**\n * Create a `tls.TLSSocket` and initiate a connection.\n *\n * @param {Object} options Connection options\n * @return {tls.TLSSocket} The newly created socket used to start the connection\n * @private\n */\nfunction tlsConnect(options) {\n options.path = undefined;\n\n if (!options.servername && options.servername !== '') {\n options.servername = net.isIP(options.host) ? '' : options.host;\n }\n\n return tls.connect(options);\n}\n\n/**\n * Abort the handshake and emit an error.\n *\n * @param {WebSocket} websocket The WebSocket instance\n * @param {(http.ClientRequest|net.Socket|tls.Socket)} stream The request to\n * abort or the socket to destroy\n * @param {String} message The error message\n * @private\n */\nfunction abortHandshake(websocket, stream, message) {\n websocket._readyState = WebSocket.CLOSING;\n\n const err = new Error(message);\n Error.captureStackTrace(err, abortHandshake);\n\n if (stream.setHeader) {\n stream[kAborted] = true;\n stream.abort();\n\n if (stream.socket && !stream.socket.destroyed) {\n //\n // On Node.js >= 14.3.0 `request.abort()` does not destroy the socket if\n // called after the request completed. See\n // https://github.com/websockets/ws/issues/1869.\n //\n stream.socket.destroy();\n }\n\n process.nextTick(emitErrorAndClose, websocket, err);\n } else {\n stream.destroy(err);\n stream.once('error', websocket.emit.bind(websocket, 'error'));\n stream.once('close', websocket.emitClose.bind(websocket));\n }\n}\n\n/**\n * Handle cases where the `ping()`, `pong()`, or `send()` methods are called\n * when the `readyState` attribute is `CLOSING` or `CLOSED`.\n *\n * @param {WebSocket} websocket The WebSocket instance\n * @param {*} [data] The data to send\n * @param {Function} [cb] Callback\n * @private\n */\nfunction sendAfterClose(websocket, data, cb) {\n if (data) {\n const length = isBlob(data) ? data.size : toBuffer(data).length;\n\n //\n // The `_bufferedAmount` property is used only when the peer is a client and\n // the opening handshake fails. Under these circumstances, in fact, the\n // `setSocket()` method is not called, so the `_socket` and `_sender`\n // properties are set to `null`.\n //\n if (websocket._socket) websocket._sender._bufferedBytes += length;\n else websocket._bufferedAmount += length;\n }\n\n if (cb) {\n const err = new Error(\n `WebSocket is not open: readyState ${websocket.readyState} ` +\n `(${readyStates[websocket.readyState]})`\n );\n process.nextTick(cb, err);\n }\n}\n\n/**\n * The listener of the `Receiver` `'conclude'` event.\n *\n * @param {Number} code The status code\n * @param {Buffer} reason The reason for closing\n * @private\n */\nfunction receiverOnConclude(code, reason) {\n const websocket = this[kWebSocket];\n\n websocket._closeFrameReceived = true;\n websocket._closeMessage = reason;\n websocket._closeCode = code;\n\n if (websocket._socket[kWebSocket] === undefined) return;\n\n websocket._socket.removeListener('data', socketOnData);\n process.nextTick(resume, websocket._socket);\n\n if (code === 1005) websocket.close();\n else websocket.close(code, reason);\n}\n\n/**\n * The listener of the `Receiver` `'drain'` event.\n *\n * @private\n */\nfunction receiverOnDrain() {\n const websocket = this[kWebSocket];\n\n if (!websocket.isPaused) websocket._socket.resume();\n}\n\n/**\n * The listener of the `Receiver` `'error'` event.\n *\n * @param {(RangeError|Error)} err The emitted error\n * @private\n */\nfunction receiverOnError(err) {\n const websocket = this[kWebSocket];\n\n if (websocket._socket[kWebSocket] !== undefined) {\n websocket._socket.removeListener('data', socketOnData);\n\n //\n // On Node.js < 14.0.0 the `'error'` event is emitted synchronously. See\n // https://github.com/websockets/ws/issues/1940.\n //\n process.nextTick(resume, websocket._socket);\n\n websocket.close(err[kStatusCode]);\n }\n\n if (!websocket._errorEmitted) {\n websocket._errorEmitted = true;\n websocket.emit('error', err);\n }\n}\n\n/**\n * The listener of the `Receiver` `'finish'` event.\n *\n * @private\n */\nfunction receiverOnFinish() {\n this[kWebSocket].emitClose();\n}\n\n/**\n * The listener of the `Receiver` `'message'` event.\n *\n * @param {Buffer|ArrayBuffer|Buffer[])} data The message\n * @param {Boolean} isBinary Specifies whether the message is binary or not\n * @private\n */\nfunction receiverOnMessage(data, isBinary) {\n this[kWebSocket].emit('message', data, isBinary);\n}\n\n/**\n * The listener of the `Receiver` `'ping'` event.\n *\n * @param {Buffer} data The data included in the ping frame\n * @private\n */\nfunction receiverOnPing(data) {\n const websocket = this[kWebSocket];\n\n if (websocket._autoPong) websocket.pong(data, !this._isServer, NOOP);\n websocket.emit('ping', data);\n}\n\n/**\n * The listener of the `Receiver` `'pong'` event.\n *\n * @param {Buffer} data The data included in the pong frame\n * @private\n */\nfunction receiverOnPong(data) {\n this[kWebSocket].emit('pong', data);\n}\n\n/**\n * Resume a readable stream\n *\n * @param {Readable} stream The readable stream\n * @private\n */\nfunction resume(stream) {\n stream.resume();\n}\n\n/**\n * The `Sender` error event handler.\n *\n * @param {Error} The error\n * @private\n */\nfunction senderOnError(err) {\n const websocket = this[kWebSocket];\n\n if (websocket.readyState === WebSocket.CLOSED) return;\n if (websocket.readyState === WebSocket.OPEN) {\n websocket._readyState = WebSocket.CLOSING;\n setCloseTimer(websocket);\n }\n\n //\n // `socket.end()` is used instead of `socket.destroy()` to allow the other\n // peer to finish sending queued data. There is no need to set a timer here\n // because `CLOSING` means that it is already set or not needed.\n //\n this._socket.end();\n\n if (!websocket._errorEmitted) {\n websocket._errorEmitted = true;\n websocket.emit('error', err);\n }\n}\n\n/**\n * Set a timer to destroy the underlying raw socket of a WebSocket.\n *\n * @param {WebSocket} websocket The WebSocket instance\n * @private\n */\nfunction setCloseTimer(websocket) {\n websocket._closeTimer = setTimeout(\n websocket._socket.destroy.bind(websocket._socket),\n websocket._closeTimeout\n );\n}\n\n/**\n * The listener of the socket `'close'` event.\n *\n * @private\n */\nfunction socketOnClose() {\n const websocket = this[kWebSocket];\n\n this.removeListener('close', socketOnClose);\n this.removeListener('data', socketOnData);\n this.removeListener('end', socketOnEnd);\n\n websocket._readyState = WebSocket.CLOSING;\n\n //\n // The close frame might not have been received or the `'end'` event emitted,\n // for example, if the socket was destroyed due to an error. Ensure that the\n // `receiver` stream is closed after writing any remaining buffered data to\n // it. If the readable side of the socket is in flowing mode then there is no\n // buffered data as everything has been already written. If instead, the\n // socket is paused, any possible buffered data will be read as a single\n // chunk.\n //\n if (\n !this._readableState.endEmitted &&\n !websocket._closeFrameReceived &&\n !websocket._receiver._writableState.errorEmitted &&\n this._readableState.length !== 0\n ) {\n const chunk = this.read(this._readableState.length);\n\n websocket._receiver.write(chunk);\n }\n\n websocket._receiver.end();\n\n this[kWebSocket] = undefined;\n\n clearTimeout(websocket._closeTimer);\n\n if (\n websocket._receiver._writableState.finished ||\n websocket._receiver._writableState.errorEmitted\n ) {\n websocket.emitClose();\n } else {\n websocket._receiver.on('error', receiverOnFinish);\n websocket._receiver.on('finish', receiverOnFinish);\n }\n}\n\n/**\n * The listener of the socket `'data'` event.\n *\n * @param {Buffer} chunk A chunk of data\n * @private\n */\nfunction socketOnData(chunk) {\n if (!this[kWebSocket]._receiver.write(chunk)) {\n this.pause();\n }\n}\n\n/**\n * The listener of the socket `'end'` event.\n *\n * @private\n */\nfunction socketOnEnd() {\n const websocket = this[kWebSocket];\n\n websocket._readyState = WebSocket.CLOSING;\n websocket._receiver.end();\n this.end();\n}\n\n/**\n * The listener of the socket `'error'` event.\n *\n * @private\n */\nfunction socketOnError() {\n const websocket = this[kWebSocket];\n\n this.removeListener('error', socketOnError);\n this.on('error', NOOP);\n\n if (websocket) {\n websocket._readyState = WebSocket.CLOSING;\n this.destroy();\n }\n}\n","/* eslint no-unused-vars: [\"error\", { \"varsIgnorePattern\": \"^WebSocket$\" }] */\n'use strict';\n\nconst WebSocket = require('./websocket');\nconst { Duplex } = require('stream');\n\n/**\n * Emits the `'close'` event on a stream.\n *\n * @param {Duplex} stream The stream.\n * @private\n */\nfunction emitClose(stream) {\n stream.emit('close');\n}\n\n/**\n * The listener of the `'end'` event.\n *\n * @private\n */\nfunction duplexOnEnd() {\n if (!this.destroyed && this._writableState.finished) {\n this.destroy();\n }\n}\n\n/**\n * The listener of the `'error'` event.\n *\n * @param {Error} err The error\n * @private\n */\nfunction duplexOnError(err) {\n this.removeListener('error', duplexOnError);\n this.destroy();\n if (this.listenerCount('error') === 0) {\n // Do not suppress the throwing behavior.\n this.emit('error', err);\n }\n}\n\n/**\n * Wraps a `WebSocket` in a duplex stream.\n *\n * @param {WebSocket} ws The `WebSocket` to wrap\n * @param {Object} [options] The options for the `Duplex` constructor\n * @return {Duplex} The duplex stream\n * @public\n */\nfunction createWebSocketStream(ws, options) {\n let terminateOnDestroy = true;\n\n const duplex = new Duplex({\n ...options,\n autoDestroy: false,\n emitClose: false,\n objectMode: false,\n writableObjectMode: false\n });\n\n ws.on('message', function message(msg, isBinary) {\n const data =\n !isBinary && duplex._readableState.objectMode ? msg.toString() : msg;\n\n if (!duplex.push(data)) ws.pause();\n });\n\n ws.once('error', function error(err) {\n if (duplex.destroyed) return;\n\n // Prevent `ws.terminate()` from being called by `duplex._destroy()`.\n //\n // - If the `'error'` event is emitted before the `'open'` event, then\n // `ws.terminate()` is a noop as no socket is assigned.\n // - Otherwise, the error is re-emitted by the listener of the `'error'`\n // event of the `Receiver` object. The listener already closes the\n // connection by calling `ws.close()`. This allows a close frame to be\n // sent to the other peer. If `ws.terminate()` is called right after this,\n // then the close frame might not be sent.\n terminateOnDestroy = false;\n duplex.destroy(err);\n });\n\n ws.once('close', function close() {\n if (duplex.destroyed) return;\n\n duplex.push(null);\n });\n\n duplex._destroy = function (err, callback) {\n if (ws.readyState === ws.CLOSED) {\n callback(err);\n process.nextTick(emitClose, duplex);\n return;\n }\n\n let called = false;\n\n ws.once('error', function error(err) {\n called = true;\n callback(err);\n });\n\n ws.once('close', function close() {\n if (!called) callback(err);\n process.nextTick(emitClose, duplex);\n });\n\n if (terminateOnDestroy) ws.terminate();\n };\n\n duplex._final = function (callback) {\n if (ws.readyState === ws.CONNECTING) {\n ws.once('open', function open() {\n duplex._final(callback);\n });\n return;\n }\n\n // If the value of the `_socket` property is `null` it means that `ws` is a\n // client websocket and the handshake failed. In fact, when this happens, a\n // socket is never assigned to the websocket. Wait for the `'error'` event\n // that will be emitted by the websocket.\n if (ws._socket === null) return;\n\n if (ws._socket._writableState.finished) {\n callback();\n if (duplex._readableState.endEmitted) duplex.destroy();\n } else {\n ws._socket.once('finish', function finish() {\n // `duplex` is not destroyed here because the `'end'` event will be\n // emitted on `duplex` after this `'finish'` event. The EOF signaling\n // `null` chunk is, in fact, pushed when the websocket emits `'close'`.\n callback();\n });\n ws.close();\n }\n };\n\n duplex._read = function () {\n if (ws.isPaused) ws.resume();\n };\n\n duplex._write = function (chunk, encoding, callback) {\n if (ws.readyState === ws.CONNECTING) {\n ws.once('open', function open() {\n duplex._write(chunk, encoding, callback);\n });\n return;\n }\n\n ws.send(chunk, callback);\n };\n\n duplex.on('end', duplexOnEnd);\n duplex.on('error', duplexOnError);\n return duplex;\n}\n\nmodule.exports = createWebSocketStream;\n","'use strict';\n\nconst { tokenChars } = require('./validation');\n\n/**\n * Parses the `Sec-WebSocket-Protocol` header into a set of subprotocol names.\n *\n * @param {String} header The field value of the header\n * @return {Set} The subprotocol names\n * @public\n */\nfunction parse(header) {\n const protocols = new Set();\n let start = -1;\n let end = -1;\n let i = 0;\n\n for (i; i < header.length; i++) {\n const code = header.charCodeAt(i);\n\n if (end === -1 && tokenChars[code] === 1) {\n if (start === -1) start = i;\n } else if (\n i !== 0 &&\n (code === 0x20 /* ' ' */ || code === 0x09) /* '\\t' */\n ) {\n if (end === -1 && start !== -1) end = i;\n } else if (code === 0x2c /* ',' */) {\n if (start === -1) {\n throw new SyntaxError(`Unexpected character at index ${i}`);\n }\n\n if (end === -1) end = i;\n\n const protocol = header.slice(start, end);\n\n if (protocols.has(protocol)) {\n throw new SyntaxError(`The \"${protocol}\" subprotocol is duplicated`);\n }\n\n protocols.add(protocol);\n start = end = -1;\n } else {\n throw new SyntaxError(`Unexpected character at index ${i}`);\n }\n }\n\n if (start === -1 || end !== -1) {\n throw new SyntaxError('Unexpected end of input');\n }\n\n const protocol = header.slice(start, i);\n\n if (protocols.has(protocol)) {\n throw new SyntaxError(`The \"${protocol}\" subprotocol is duplicated`);\n }\n\n protocols.add(protocol);\n return protocols;\n}\n\nmodule.exports = { parse };\n","/* eslint no-unused-vars: [\"error\", { \"varsIgnorePattern\": \"^Duplex$\", \"caughtErrors\": \"none\" }] */\n\n'use strict';\n\nconst EventEmitter = require('events');\nconst http = require('http');\nconst { Duplex } = require('stream');\nconst { createHash } = require('crypto');\n\nconst extension = require('./extension');\nconst PerMessageDeflate = require('./permessage-deflate');\nconst subprotocol = require('./subprotocol');\nconst WebSocket = require('./websocket');\nconst { CLOSE_TIMEOUT, GUID, kWebSocket } = require('./constants');\n\nconst keyRegex = /^[+/0-9A-Za-z]{22}==$/;\n\nconst RUNNING = 0;\nconst CLOSING = 1;\nconst CLOSED = 2;\n\n/**\n * Class representing a WebSocket server.\n *\n * @extends EventEmitter\n */\nclass WebSocketServer extends EventEmitter {\n /**\n * Create a `WebSocketServer` instance.\n *\n * @param {Object} options Configuration options\n * @param {Boolean} [options.allowSynchronousEvents=true] Specifies whether\n * any of the `'message'`, `'ping'`, and `'pong'` events can be emitted\n * multiple times in the same tick\n * @param {Boolean} [options.autoPong=true] Specifies whether or not to\n * automatically send a pong in response to a ping\n * @param {Number} [options.backlog=511] The maximum length of the queue of\n * pending connections\n * @param {Boolean} [options.clientTracking=true] Specifies whether or not to\n * track clients\n * @param {Number} [options.closeTimeout=30000] Duration in milliseconds to\n * wait for the closing handshake to finish after `websocket.close()` is\n * called\n * @param {Function} [options.handleProtocols] A hook to handle protocols\n * @param {String} [options.host] The hostname where to bind the server\n * @param {Number} [options.maxPayload=104857600] The maximum allowed message\n * size\n * @param {Boolean} [options.noServer=false] Enable no server mode\n * @param {String} [options.path] Accept only connections matching this path\n * @param {(Boolean|Object)} [options.perMessageDeflate=false] Enable/disable\n * permessage-deflate\n * @param {Number} [options.port] The port where to bind the server\n * @param {(http.Server|https.Server)} [options.server] A pre-created HTTP/S\n * server to use\n * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or\n * not to skip UTF-8 validation for text and close messages\n * @param {Function} [options.verifyClient] A hook to reject connections\n * @param {Function} [options.WebSocket=WebSocket] Specifies the `WebSocket`\n * class to use. It must be the `WebSocket` class or class that extends it\n * @param {Function} [callback] A listener for the `listening` event\n */\n constructor(options, callback) {\n super();\n\n options = {\n allowSynchronousEvents: true,\n autoPong: true,\n maxPayload: 100 * 1024 * 1024,\n skipUTF8Validation: false,\n perMessageDeflate: false,\n handleProtocols: null,\n clientTracking: true,\n closeTimeout: CLOSE_TIMEOUT,\n verifyClient: null,\n noServer: false,\n backlog: null, // use default (511 as implemented in net.js)\n server: null,\n host: null,\n path: null,\n port: null,\n WebSocket,\n ...options\n };\n\n if (\n (options.port == null && !options.server && !options.noServer) ||\n (options.port != null && (options.server || options.noServer)) ||\n (options.server && options.noServer)\n ) {\n throw new TypeError(\n 'One and only one of the \"port\", \"server\", or \"noServer\" options ' +\n 'must be specified'\n );\n }\n\n if (options.port != null) {\n this._server = http.createServer((req, res) => {\n const body = http.STATUS_CODES[426];\n\n res.writeHead(426, {\n 'Content-Length': body.length,\n 'Content-Type': 'text/plain'\n });\n res.end(body);\n });\n this._server.listen(\n options.port,\n options.host,\n options.backlog,\n callback\n );\n } else if (options.server) {\n this._server = options.server;\n }\n\n if (this._server) {\n const emitConnection = this.emit.bind(this, 'connection');\n\n this._removeListeners = addListeners(this._server, {\n listening: this.emit.bind(this, 'listening'),\n error: this.emit.bind(this, 'error'),\n upgrade: (req, socket, head) => {\n this.handleUpgrade(req, socket, head, emitConnection);\n }\n });\n }\n\n if (options.perMessageDeflate === true) options.perMessageDeflate = {};\n if (options.clientTracking) {\n this.clients = new Set();\n this._shouldEmitClose = false;\n }\n\n this.options = options;\n this._state = RUNNING;\n }\n\n /**\n * Returns the bound address, the address family name, and port of the server\n * as reported by the operating system if listening on an IP socket.\n * If the server is listening on a pipe or UNIX domain socket, the name is\n * returned as a string.\n *\n * @return {(Object|String|null)} The address of the server\n * @public\n */\n address() {\n if (this.options.noServer) {\n throw new Error('The server is operating in \"noServer\" mode');\n }\n\n if (!this._server) return null;\n return this._server.address();\n }\n\n /**\n * Stop the server from accepting new connections and emit the `'close'` event\n * when all existing connections are closed.\n *\n * @param {Function} [cb] A one-time listener for the `'close'` event\n * @public\n */\n close(cb) {\n if (this._state === CLOSED) {\n if (cb) {\n this.once('close', () => {\n cb(new Error('The server is not running'));\n });\n }\n\n process.nextTick(emitClose, this);\n return;\n }\n\n if (cb) this.once('close', cb);\n\n if (this._state === CLOSING) return;\n this._state = CLOSING;\n\n if (this.options.noServer || this.options.server) {\n if (this._server) {\n this._removeListeners();\n this._removeListeners = this._server = null;\n }\n\n if (this.clients) {\n if (!this.clients.size) {\n process.nextTick(emitClose, this);\n } else {\n this._shouldEmitClose = true;\n }\n } else {\n process.nextTick(emitClose, this);\n }\n } else {\n const server = this._server;\n\n this._removeListeners();\n this._removeListeners = this._server = null;\n\n //\n // The HTTP/S server was created internally. Close it, and rely on its\n // `'close'` event.\n //\n server.close(() => {\n emitClose(this);\n });\n }\n }\n\n /**\n * See if a given request should be handled by this server instance.\n *\n * @param {http.IncomingMessage} req Request object to inspect\n * @return {Boolean} `true` if the request is valid, else `false`\n * @public\n */\n shouldHandle(req) {\n if (this.options.path) {\n const index = req.url.indexOf('?');\n const pathname = index !== -1 ? req.url.slice(0, index) : req.url;\n\n if (pathname !== this.options.path) return false;\n }\n\n return true;\n }\n\n /**\n * Handle a HTTP Upgrade request.\n *\n * @param {http.IncomingMessage} req The request object\n * @param {Duplex} socket The network socket between the server and client\n * @param {Buffer} head The first packet of the upgraded stream\n * @param {Function} cb Callback\n * @public\n */\n handleUpgrade(req, socket, head, cb) {\n socket.on('error', socketOnError);\n\n const key = req.headers['sec-websocket-key'];\n const upgrade = req.headers.upgrade;\n const version = +req.headers['sec-websocket-version'];\n\n if (req.method !== 'GET') {\n const message = 'Invalid HTTP method';\n abortHandshakeOrEmitwsClientError(this, req, socket, 405, message);\n return;\n }\n\n if (upgrade === undefined || upgrade.toLowerCase() !== 'websocket') {\n const message = 'Invalid Upgrade header';\n abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);\n return;\n }\n\n if (key === undefined || !keyRegex.test(key)) {\n const message = 'Missing or invalid Sec-WebSocket-Key header';\n abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);\n return;\n }\n\n if (version !== 13 && version !== 8) {\n const message = 'Missing or invalid Sec-WebSocket-Version header';\n abortHandshakeOrEmitwsClientError(this, req, socket, 400, message, {\n 'Sec-WebSocket-Version': '13, 8'\n });\n return;\n }\n\n if (!this.shouldHandle(req)) {\n abortHandshake(socket, 400);\n return;\n }\n\n const secWebSocketProtocol = req.headers['sec-websocket-protocol'];\n let protocols = new Set();\n\n if (secWebSocketProtocol !== undefined) {\n try {\n protocols = subprotocol.parse(secWebSocketProtocol);\n } catch (err) {\n const message = 'Invalid Sec-WebSocket-Protocol header';\n abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);\n return;\n }\n }\n\n const secWebSocketExtensions = req.headers['sec-websocket-extensions'];\n const extensions = {};\n\n if (\n this.options.perMessageDeflate &&\n secWebSocketExtensions !== undefined\n ) {\n const perMessageDeflate = new PerMessageDeflate(\n this.options.perMessageDeflate,\n true,\n this.options.maxPayload\n );\n\n try {\n const offers = extension.parse(secWebSocketExtensions);\n\n if (offers[PerMessageDeflate.extensionName]) {\n perMessageDeflate.accept(offers[PerMessageDeflate.extensionName]);\n extensions[PerMessageDeflate.extensionName] = perMessageDeflate;\n }\n } catch (err) {\n const message =\n 'Invalid or unacceptable Sec-WebSocket-Extensions header';\n abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);\n return;\n }\n }\n\n //\n // Optionally call external client verification handler.\n //\n if (this.options.verifyClient) {\n const info = {\n origin:\n req.headers[`${version === 8 ? 'sec-websocket-origin' : 'origin'}`],\n secure: !!(req.socket.authorized || req.socket.encrypted),\n req\n };\n\n if (this.options.verifyClient.length === 2) {\n this.options.verifyClient(info, (verified, code, message, headers) => {\n if (!verified) {\n return abortHandshake(socket, code || 401, message, headers);\n }\n\n this.completeUpgrade(\n extensions,\n key,\n protocols,\n req,\n socket,\n head,\n cb\n );\n });\n return;\n }\n\n if (!this.options.verifyClient(info)) return abortHandshake(socket, 401);\n }\n\n this.completeUpgrade(extensions, key, protocols, req, socket, head, cb);\n }\n\n /**\n * Upgrade the connection to WebSocket.\n *\n * @param {Object} extensions The accepted extensions\n * @param {String} key The value of the `Sec-WebSocket-Key` header\n * @param {Set} protocols The subprotocols\n * @param {http.IncomingMessage} req The request object\n * @param {Duplex} socket The network socket between the server and client\n * @param {Buffer} head The first packet of the upgraded stream\n * @param {Function} cb Callback\n * @throws {Error} If called more than once with the same socket\n * @private\n */\n completeUpgrade(extensions, key, protocols, req, socket, head, cb) {\n //\n // Destroy the socket if the client has already sent a FIN packet.\n //\n if (!socket.readable || !socket.writable) return socket.destroy();\n\n if (socket[kWebSocket]) {\n throw new Error(\n 'server.handleUpgrade() was called more than once with the same ' +\n 'socket, possibly due to a misconfiguration'\n );\n }\n\n if (this._state > RUNNING) return abortHandshake(socket, 503);\n\n const digest = createHash('sha1')\n .update(key + GUID)\n .digest('base64');\n\n const headers = [\n 'HTTP/1.1 101 Switching Protocols',\n 'Upgrade: websocket',\n 'Connection: Upgrade',\n `Sec-WebSocket-Accept: ${digest}`\n ];\n\n const ws = new this.options.WebSocket(null, undefined, this.options);\n\n if (protocols.size) {\n //\n // Optionally call external protocol selection handler.\n //\n const protocol = this.options.handleProtocols\n ? this.options.handleProtocols(protocols, req)\n : protocols.values().next().value;\n\n if (protocol) {\n headers.push(`Sec-WebSocket-Protocol: ${protocol}`);\n ws._protocol = protocol;\n }\n }\n\n if (extensions[PerMessageDeflate.extensionName]) {\n const params = extensions[PerMessageDeflate.extensionName].params;\n const value = extension.format({\n [PerMessageDeflate.extensionName]: [params]\n });\n headers.push(`Sec-WebSocket-Extensions: ${value}`);\n ws._extensions = extensions;\n }\n\n //\n // Allow external modification/inspection of handshake headers.\n //\n this.emit('headers', headers, req);\n\n socket.write(headers.concat('\\r\\n').join('\\r\\n'));\n socket.removeListener('error', socketOnError);\n\n ws.setSocket(socket, head, {\n allowSynchronousEvents: this.options.allowSynchronousEvents,\n maxPayload: this.options.maxPayload,\n skipUTF8Validation: this.options.skipUTF8Validation\n });\n\n if (this.clients) {\n this.clients.add(ws);\n ws.on('close', () => {\n this.clients.delete(ws);\n\n if (this._shouldEmitClose && !this.clients.size) {\n process.nextTick(emitClose, this);\n }\n });\n }\n\n cb(ws, req);\n }\n}\n\nmodule.exports = WebSocketServer;\n\n/**\n * Add event listeners on an `EventEmitter` using a map of <event, listener>\n * pairs.\n *\n * @param {EventEmitter} server The event emitter\n * @param {Object.<String, Function>} map The listeners to add\n * @return {Function} A function that will remove the added listeners when\n * called\n * @private\n */\nfunction addListeners(server, map) {\n for (const event of Object.keys(map)) server.on(event, map[event]);\n\n return function removeListeners() {\n for (const event of Object.keys(map)) {\n server.removeListener(event, map[event]);\n }\n };\n}\n\n/**\n * Emit a `'close'` event on an `EventEmitter`.\n *\n * @param {EventEmitter} server The event emitter\n * @private\n */\nfunction emitClose(server) {\n server._state = CLOSED;\n server.emit('close');\n}\n\n/**\n * Handle socket errors.\n *\n * @private\n */\nfunction socketOnError() {\n this.destroy();\n}\n\n/**\n * Close the connection when preconditions are not fulfilled.\n *\n * @param {Duplex} socket The socket of the upgrade request\n * @param {Number} code The HTTP response status code\n * @param {String} [message] The HTTP response body\n * @param {Object} [headers] Additional HTTP response headers\n * @private\n */\nfunction abortHandshake(socket, code, message, headers) {\n //\n // The socket is writable unless the user destroyed or ended it before calling\n // `server.handleUpgrade()` or in the `verifyClient` function, which is a user\n // error. Handling this does not make much sense as the worst that can happen\n // is that some of the data written by the user might be discarded due to the\n // call to `socket.end()` below, which triggers an `'error'` event that in\n // turn causes the socket to be destroyed.\n //\n message = message || http.STATUS_CODES[code];\n headers = {\n Connection: 'close',\n 'Content-Type': 'text/html',\n 'Content-Length': Buffer.byteLength(message),\n ...headers\n };\n\n socket.once('finish', socket.destroy);\n\n socket.end(\n `HTTP/1.1 ${code} ${http.STATUS_CODES[code]}\\r\\n` +\n Object.keys(headers)\n .map((h) => `${h}: ${headers[h]}`)\n .join('\\r\\n') +\n '\\r\\n\\r\\n' +\n message\n );\n}\n\n/**\n * Emit a `'wsClientError'` event on a `WebSocketServer` if there is at least\n * one listener for it, otherwise call `abortHandshake()`.\n *\n * @param {WebSocketServer} server The WebSocket server\n * @param {http.IncomingMessage} req The request object\n * @param {Duplex} socket The socket of the upgrade request\n * @param {Number} code The HTTP response status code\n * @param {String} message The HTTP response body\n * @param {Object} [headers] The HTTP response headers\n * @private\n */\nfunction abortHandshakeOrEmitwsClientError(\n server,\n req,\n socket,\n code,\n message,\n headers\n) {\n if (server.listenerCount('wsClientError')) {\n const err = new Error(message);\n Error.captureStackTrace(err, abortHandshakeOrEmitwsClientError);\n\n server.emit('wsClientError', err, socket, req);\n } else {\n abortHandshake(socket, code, message, headers);\n }\n}\n","import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport { readFileSync } from \"node:fs\";\nimport { basename, dirname } from \"node:path\";\nimport { MAX_LIGHT_SEGMENTS } from \"./light/protocol.js\";\nimport { sendLightEffect } from \"./light/sender.js\";\nimport { createAppNameMapProvider } from \"./notification/app-name-map.js\";\nimport {\n NotificationStorage,\n type NotificationIngestResult,\n resolveNotificationStorageDir,\n} from \"./notification/storage.js\";\nimport type {\n PluginConfig,\n RawNotification,\n NotificationPushParams,\n HttpNotificationBody,\n LightControlInput,\n} from \"./types.js\";\nimport { registerAllCli } from \"./cli/index.js\";\nimport { requireApiKey } from \"./auth/credentials.js\";\nimport { createTunnelService } from \"./tunnel/service.js\";\nimport { PluginFileLogger } from \"./logger.js\";\nimport { getEnvUrls } from \"./env.js\";\nimport { resolveConfigPath } from \"./host.js\";\n\ninterface PluginApi {\n logger: {\n info: (msg: string) => void;\n warn: (msg: string) => void;\n error: (msg: string) => void;\n };\n pluginConfig?: Record<string, unknown>;\n runtime: {\n state: {\n resolveStateDir: () =>string;\n };\n };\n registerService: (service: {\n id: string;\n start: (ctx: {\n stateDir: string;\n workspaceDir?: string;\n }) => void | Promise<void>;\n stop?: () => void | Promise<void>;\n }) => void;\n registerGatewayMethod: (\n method: string,\n handler: (opts: {\n params: Record<string, unknown>;\n /** 发起本次请求的 WSS 客户端(operator 节点为 null) */\n client: { connId?: string } | null;\n context: {\n /** 向所有已连接的 operator 客户端广播 event 帧 */\n broadcast: (event: string, payload: unknown) => void;\n /** 向指定 connId 集合广播 event 帧 */\n broadcastToConnIds: (\n event: string,\n payload: unknown,\n connIds: ReadonlySet<string>,\n ) => void;\n };\n respond: (\n ok: boolean,\n payload?: unknown,\n error?: { code: string; message: string },\n ) => void;\n }) => void | Promise<void>,\n ) => void;\n /** 注册供 AI Agent 调用的 tool,声明即实现 */\n registerTool: (tool: {\n name: string;\n description: string;\n parameters: Record<string, unknown>;\n execute: (\n toolCallId: string,\n params: unknown,\n ) => unknown | Promise<unknown>;\n }) => void;\n registerHttpRoute: (params: {\n path: string;\n handler: (\n req: IncomingMessage,\n res: ServerResponse,\n ) => void | Promise<void>;\n auth?: \"gateway\" | \"plugin\";\n }) => void;\n registerCli: (\n registrar: (ctx: {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n program: any;\n stateDir?: string;\n workspaceDir?: string;\n logger: PluginApi[\"logger\"];\n }) => void | Promise<void>,\n opts?: { commands?: string[] },\n ) => void;\n}\n\nfunction readBody(req: IncomingMessage): Promise<string> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n req.on(\"data\", (chunk: Buffer) => chunks.push(chunk));\n req.on(\"end\", () => resolve(Buffer.concat(chunks).toString()));\n req.on(\"error\", reject);\n });\n}\n\nfunction trimToUndefined(value: unknown): string | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n const trimmed = value.trim();\n return trimmed || undefined;\n}\n\nfunction createEmptyIngestResult(): NotificationIngestResult {\n return {\n received: 0,\n ingested: 0,\n dedupedById: 0,\n dedupedByContent: 0,\n invalid: 0,\n };\n}\n\nfunction resolveLocalGatewayAuth(params: {\n stateDir?: string;\n logger: Pick<PluginApi[\"logger\"], \"warn\">;\n}): {\n gatewayAuthMode?: \"token\" | \"password\";\n gatewayToken?: string;\n gatewayPassword?: string;\n} {\n const envGatewayToken =\n trimToUndefined(process.env.OPENCLAW_GATEWAY_TOKEN) ??\n trimToUndefined(process.env.QCLAW_GATEWAY_TOKEN) ??\n trimToUndefined(process.env.CLAWDBOT_GATEWAY_TOKEN);\n const envGatewayPassword =\n trimToUndefined(process.env.OPENCLAW_GATEWAY_PASSWORD) ??\n trimToUndefined(process.env.QCLAW_GATEWAY_PASSWORD) ??\n trimToUndefined(process.env.CLAWDBOT_GATEWAY_PASSWORD);\n\n let configGatewayAuthMode: \"token\" | \"password\" | undefined;\n let configGatewayToken: string | undefined;\n let configGatewayPassword: string | undefined;\n const configPath = params.stateDir\n ? resolveConfigPath(params.stateDir)\n : undefined;\n\n if (configPath) {\n try {\n const configData = JSON.parse(readFileSync(configPath, \"utf-8\"));\n const rawGatewayAuthMode = trimToUndefined(configData?.gateway?.auth?.mode);\n if (rawGatewayAuthMode === \"token\" || rawGatewayAuthMode === \"password\") {\n configGatewayAuthMode = rawGatewayAuthMode;\n }\n configGatewayToken = trimToUndefined(configData?.gateway?.auth?.token);\n configGatewayPassword = trimToUndefined(configData?.gateway?.auth?.password);\n } catch (err: any) {\n if (err?.code !== \"ENOENT\") {\n params.logger.warn(\n `Relay tunnel: 无法读取 gateway 鉴权配置 (${configPath})`,\n );\n }\n }\n }\n\n return {\n gatewayAuthMode: configGatewayAuthMode,\n gatewayToken: envGatewayToken ?? configGatewayToken,\n gatewayPassword: envGatewayPassword ?? configGatewayPassword,\n };\n}\n\nexport default {\n id: \"phone-notifications\",\n name: \"Phone Notifications Sync\",\n\n register(api: PluginApi) {\n const config = (api.pluginConfig ?? {}) as PluginConfig;\n let storage: NotificationStorage | null = null;\n let appNameMapProvider: ReturnType<typeof createAppNameMapProvider> | null = null;\n const ignoredApps = new Set(config.ignoredApps ?? []);\n\n const openclawDir = api.runtime.state.resolveStateDir();\n const logger = openclawDir\n ? new PluginFileLogger(api.logger, openclawDir)\n : api.logger;\n\n function filterNotifications(items: RawNotification[]): RawNotification[] {\n return items.filter((n) => !ignoredApps.has(n.app));\n }\n\n // 1. registerService — 管理 storage 与 app-name-map 生命周期\n api.registerService({\n id: \"notification-storage\",\n async start(ctx) {\n const storageDir = resolveNotificationStorageDir(ctx, logger);\n\n appNameMapProvider = createAppNameMapProvider({\n stateDir: ctx.stateDir,\n logger,\n });\n await appNameMapProvider.start();\n\n const resolveDisplayName = appNameMapProvider.resolveDisplayName.bind(appNameMapProvider);\n storage = new NotificationStorage(storageDir, config, logger, resolveDisplayName);\n await storage.init();\n logger.info(`通知存储服务已启动: ${storageDir}`);\n },\n async stop() {\n await storage?.close();\n storage = null;\n appNameMapProvider?.stop();\n appNameMapProvider = null;\n logger.info(\"通知存储服务已停止\");\n },\n });\n\n // 1b. registerService — Relay Tunnel 隧道服务\n const tunnelUrl = getEnvUrls().relayTunnelUrl;\n if (tunnelUrl) {\n const gatewayPort =\n process.env.OPENCLAW_GATEWAY_PORT ??\n process.env.QCLAW_GATEWAY_PORT ??\n \"18789\";\n const { gatewayAuthMode, gatewayToken, gatewayPassword } =\n resolveLocalGatewayAuth({\n stateDir: openclawDir,\n logger,\n });\n const tunnelService = createTunnelService({\n tunnelUrl,\n heartbeatSec: config.relay?.heartbeatSec,\n reconnectBackoffMs: config.relay?.reconnectBackoffMs,\n gatewayBaseUrl: `http://localhost:${gatewayPort}`,\n gatewayAuthMode,\n gatewayToken,\n gatewayPassword,\n logger,\n });\n api.registerService(tunnelService);\n logger.info(\"Relay tunnel 服务已注册\");\n }\n\n // 2. registerGatewayMethod — Gateway Native 模式(默认)\n // 协议:{ type: \"req\", id: \"n_abc\", method: \"notifications.push\",\n // params: { items: [...] } }\n api.registerGatewayMethod(\n \"notifications.push\",\n async ({ params, respond }) => {\n if (!storage) {\n respond(false, null, {\n code: \"NOT_READY\",\n message: \"Storage service not ready\",\n });\n return;\n }\n\n const { items } = params as unknown as NotificationPushParams;\n if (Array.isArray(items)) {\n const filtered = filterNotifications(items);\n const result = filtered.length\n ? await storage.ingest(filtered)\n : createEmptyIngestResult();\n respond(true, result);\n } else {\n respond(false, null, {\n code: \"INVALID_PARAMS\",\n message: \"items must be an array\",\n });\n }\n },\n );\n\n // 3. registerTool — 灯效控制(Agent 驱动)\n // 支持 1–10 段顺序灯效,每段独立参数。\n // 通过 HTTP 接口直接下发灯效指令\n api.registerTool({\n name: \"light_control\",\n description:\n \"控制硬件灯效,支持 1–12 段顺序灯效,每段独立参数(5 种模式:波浪/呼吸/频闪/常亮/流光)。\" +\n \"Tool 内部自动量化为嵌入式协议定义的离散档位,并按模式精简为变长 ANCS 控制序列,通过 HTTP 接口下发灯效指令。\" +\n '当用户说\"开灯\"、\"换个灯效\"、\"把灯调成红色\"、\"营造氛围\"等与灯光控制相关的表达时调用。',\n parameters: {\n type: \"object\",\n required: [\"segments\"],\n additionalProperties: false,\n properties: {\n segments: {\n type: \"array\",\n description: \"灯效段序列,1–12 段,按顺序播放\",\n minItems: 1,\n maxItems: MAX_LIGHT_SEGMENTS,\n items: {\n type: \"object\",\n required: [\"mode\", \"duration_s\", \"brightness\", \"color\"],\n additionalProperties: false,\n properties: {\n mode: {\n type: \"string\",\n enum: [\"wave\", \"breath\", \"strobe\", \"steady\", \"wave_rainbow\"],\n description:\n \"灯效模式:wave 波浪 / breath 呼吸 / strobe 频闪 / steady 常亮 / wave_rainbow 流光(多色调色板在 7 颗灯上循环流动)\",\n },\n duration_s: {\n type: \"number\",\n minimum: 0,\n description:\n \"本段持续时长(秒),0 表示无限时长。推荐离散值:0.5/1/2/3/5/6/8/16/24/32/48,建议单段 ≤8s 省电\",\n },\n brightness: {\n type: \"number\",\n minimum: 0,\n maximum: 255,\n description:\n \"前景亮度 0–255,量化档位:32/64/96/128/192/255。brightness=0 仅在 steady 模式下有效(显式灭灯)\",\n },\n color: {\n type: \"object\",\n required: [\"r\", \"g\", \"b\"],\n additionalProperties: false,\n properties: {\n r: { type: \"number\", minimum: 0, maximum: 255 },\n g: { type: \"number\", minimum: 0, maximum: 255 },\n b: { type: \"number\", minimum: 0, maximum: 255 },\n },\n description:\n \"前景色 RGB(wave_rainbow 模式下作为第一颜色锚点,至少 R/G/B 中一个非 0)\",\n },\n interval_ms: {\n type: \"number\",\n minimum: 0,\n description:\n \"步进间隔(ms),wave/strobe/wave_rainbow 有效,默认 200。量化档位:50/100/200/300/500/600/800/1600/2400/3200/4800\",\n },\n direction: {\n type: \"string\",\n enum: [\"ltr\", \"rtl\"],\n description: \"波浪/流光方向,wave/wave_rainbow 有效,默认 ltr\",\n },\n window: {\n type: \"number\",\n enum: [1, 2, 3],\n description:\n \"wave:窗口灯数,默认 2;wave_rainbow:调色板平移步幅(速度)\",\n },\n breath_timing: {\n type: \"object\",\n additionalProperties: false,\n properties: {\n rise_ms: {\n type: \"number\",\n minimum: 0,\n description:\n \"上升时间(ms),量化到 1040/1560/2080/2600/3100/4160\",\n },\n hold_ms: {\n type: \"number\",\n minimum: 0,\n description: \"保持最高亮度时间(ms),支持 0ms\",\n },\n fall_ms: {\n type: \"number\",\n minimum: 0,\n description:\n \"下降时间(ms),量化到 1040/1560/2080/2600/3100/4160\",\n },\n off_ms: {\n type: \"number\",\n minimum: 0,\n description: \"熄灭时间(ms),支持 0ms\",\n },\n },\n description:\n \"呼吸四段时间,仅 breath 有效;rise/fall 量化档位:1040/1560/2080/2600/3100/4160,hold/off 额外支持 0ms\",\n },\n background: {\n type: \"object\",\n required: [\"r\", \"g\", \"b\", \"brightness\"],\n additionalProperties: false,\n properties: {\n r: { type: \"number\", minimum: 0, maximum: 255 },\n g: { type: \"number\", minimum: 0, maximum: 255 },\n b: { type: \"number\", minimum: 0, maximum: 255 },\n brightness: {\n type: \"number\",\n minimum: 0,\n maximum: 255,\n description: \"底色亮度,量化档位:0/32/64/96/128/192/255\",\n },\n },\n description:\n \"底色 RGB + 亮度,wave 有效为底色层;wave_rainbow 有效为第二颜色锚点(与前景色插值生成多色调色板)\",\n },\n },\n },\n },\n repeat: {\n type: \"boolean\",\n description:\n \"true = 无限循环播放,false/不填 = 仅播放一轮。无限循环适合背景常驻灯效,注意省电\",\n },\n },\n },\n async execute(_toolCallId: string, params: unknown) {\n let apiKey: string;\n try {\n apiKey = requireApiKey();\n } catch (e: any) {\n return {\n ok: false,\n error: { code: \"AUTH_REQUIRED\", message: e.message },\n };\n }\n\n const { segments, repeat } = params as LightControlInput;\n const result = await sendLightEffect(apiKey, segments, logger, repeat);\n\n if (!result.ok) {\n logger.warn(\n `Light control HTTP request failed: ${result.status} ${result.error}`,\n );\n } else {\n logger.info(`Light control sent, bizUniqueId=${result.bizUniqueId}`);\n }\n\n return result;\n },\n });\n\n // 4. registerHttpRoute — HTTP 端点(鉴权由 Gateway 统一处理)\n api.registerHttpRoute({\n path: \"/notifications\",\n auth: \"gateway\",\n async handler(req: IncomingMessage, res: ServerResponse) {\n // 仅接受 POST\n if (req.method !== \"POST\") {\n res.writeHead(405, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: false, error: \"Method Not Allowed\" }));\n return;\n }\n\n if (!storage) {\n res.writeHead(503, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: false, error: \"Service Not Ready\" }));\n return;\n }\n\n // 解析请求体\n let body: HttpNotificationBody;\n try {\n const raw = await readBody(req);\n body = JSON.parse(raw);\n } catch {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: false, error: \"Invalid JSON\" }));\n return;\n }\n\n if (!Array.isArray(body.notifications)) {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n res.end(\n JSON.stringify({\n ok: false,\n error: \"notifications must be an array\",\n }),\n );\n return;\n }\n\n const filtered = filterNotifications(body.notifications);\n const result = filtered.length\n ? await storage.ingest(filtered)\n : createEmptyIngestResult();\n\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: true, ...result }));\n },\n });\n\n logger.info(\"HTTP 通知端点已注册: POST /notifications\");\n\n // 5. registerCli — 注册 CLI 命令。\n // 分拆为两个独立注册器,避免 `ntf` 被其他插件占用时整组 CLI 被跳过。\n const inferOpenClawRootDir = (workspaceDir?: string): string | undefined => {\n // OpenClaw 默认 workspace 目录为: <openclawRoot>/workspace\n // 例如: /Users/trl/.openclaw/workspace → /Users/trl/.openclaw\n if(openclawDir) return openclawDir;\n if (!workspaceDir) return undefined;\n\n if (basename(workspaceDir) !== \"workspace\") return undefined;\n return dirname(workspaceDir);\n };\n\n api.registerCli(\n (ctx) => {\n const inferredRoot = inferOpenClawRootDir(ctx.workspaceDir);\n const effectiveStateDir = ctx.stateDir ?? inferredRoot;\n registerAllCli(ctx.program, {\n stateDir: effectiveStateDir,\n workspaceDir: ctx.workspaceDir,\n }, \"ntf\");\n },\n { commands: [\"ntf\"] },\n );\n\n api.registerCli(\n (ctx) => {\n const inferredRoot = inferOpenClawRootDir(ctx.workspaceDir);\n const effectiveStateDir = ctx.stateDir ?? inferredRoot;\n registerAllCli(ctx.program, {\n stateDir: effectiveStateDir,\n workspaceDir: ctx.workspaceDir,\n }, \"phone-notifications\");\n },\n { commands: [\"phone-notifications\"] },\n );\n\n logger.info(\"CLI 命令已注册: ntf, phone-notifications\");\n },\n};\n","import type { LightSegment } from \"../types.js\";\n\nexport const MAX_LIGHT_SEGMENTS = 12;\n\nconst PROTOCOL_DIGITS = [\n \"\\u0080\",\n \"\\u0081\",\n \"\\u0082\",\n \"\\u0083\",\n \"\\u0084\",\n \"\\u0091\",\n \"\\u0092\",\n \"\\u0093\",\n \"\\u0094\",\n \"\\u0095\",\n \"\\u0096\",\n \"\\u0097\",\n] as const;\n\n/** \\u009A = play once, \\u009B = infinite loop */\nconst LED_SEPARATOR_ONCE = \"\\u009A\";\nconst LED_SEPARATOR_LOOP = \"\\u009B\";\n\n/** v0–v10 mapped by index; duration_s=0 is special-cased to v11 (infinite) */\nconst DURATION_STEPS_S = [0.5, 1, 2, 3, 5, 6, 8, 16, 24, 32, 48] as const;\n/** v0–v10 mapped by index; removed 400ms, added 50ms */\nconst INTERVAL_STEPS_MS = [50, 100, 200, 300, 500, 600, 800, 1600, 2400, 3200, 4800] as const;\nconst BREATH_STEPS_MS = [1040, 1560, 2080, 2600, 3100, 4160] as const;\nconst BRIGHTNESS_STEPS = [32, 64, 96, 128, 192, 255] as const;\nconst COLOR_STEPS = [0, 32, 64, 128, 192, 255] as const;\nconst BACKGROUND_BRIGHTNESS_STEPS = [0, 32, 64, 96, 128, 192, 255] as const;\n\nconst MODE_TO_INDEX: Record<LightSegment[\"mode\"], number> = {\n wave: 0,\n breath: 1,\n strobe: 2,\n steady: 3,\n wave_rainbow: 4,\n};\n\nexport function buildLightEffectApnsBody(\n segments: LightSegment[],\n repeat?: boolean,\n): string {\n assertSegmentCount(segments);\n\n const visibleText = summarizeSegments(segments);\n const separator = repeat ? LED_SEPARATOR_LOOP : LED_SEPARATOR_ONCE;\n const payload = segments.map((segment) => encodeSegment(segment)).join(\"\");\n return `${visibleText}${separator}${payload}`;\n}\n\nfunction assertSegmentCount(segments: LightSegment[]): void {\n if (segments.length < 1 || segments.length > MAX_LIGHT_SEGMENTS) {\n throw new Error(`light_control supports 1-${MAX_LIGHT_SEGMENTS} segments`);\n }\n}\n\nfunction summarizeSegments(segments: LightSegment[]): string {\n const modeDesc = segments.map((segment) => segment.mode).join(\"+\");\n return `Effect: ${modeDesc} (${segments.length} segment${segments.length > 1 ? \"s\" : \"\"})`;\n}\n\nfunction encodeSegment(segment: LightSegment): string {\n const common = [\n MODE_TO_INDEX[segment.mode],\n quantizeDuration(segment.duration_s),\n ];\n\n let values: number[];\n switch (segment.mode) {\n case \"wave\":\n case \"wave_rainbow\":\n values = [\n ...common,\n quantize(segment.interval_ms ?? 200, INTERVAL_STEPS_MS),\n quantizeBrightness(segment),\n quantize(segment.color.r, COLOR_STEPS),\n quantize(segment.color.g, COLOR_STEPS),\n quantize(segment.color.b, COLOR_STEPS),\n segment.direction === \"rtl\" ? 1 : 0,\n quantizeWindow(segment.window ?? 2),\n quantize(segment.background?.r ?? 0, COLOR_STEPS),\n quantize(segment.background?.g ?? 0, COLOR_STEPS),\n quantize(segment.background?.b ?? 0, COLOR_STEPS),\n quantize(segment.background?.brightness ?? 0, BACKGROUND_BRIGHTNESS_STEPS),\n ];\n break;\n case \"breath\":\n values = [\n ...common,\n quantizeBreathRiseFall(segment.breath_timing?.rise_ms),\n quantizeBreathHoldOff(segment.breath_timing?.hold_ms),\n quantizeBreathRiseFall(segment.breath_timing?.fall_ms),\n quantizeBreathHoldOff(segment.breath_timing?.off_ms),\n quantizeBrightness(segment),\n quantize(segment.color.r, COLOR_STEPS),\n quantize(segment.color.g, COLOR_STEPS),\n quantize(segment.color.b, COLOR_STEPS),\n ];\n break;\n case \"strobe\":\n values = [\n ...common,\n quantize(segment.interval_ms ?? 200, INTERVAL_STEPS_MS),\n quantizeBrightness(segment),\n quantize(segment.color.r, COLOR_STEPS),\n quantize(segment.color.g, COLOR_STEPS),\n quantize(segment.color.b, COLOR_STEPS),\n ];\n break;\n case \"steady\":\n values = [\n ...common,\n quantizeBrightness(segment),\n quantize(segment.color.r, COLOR_STEPS),\n quantize(segment.color.g, COLOR_STEPS),\n quantize(segment.color.b, COLOR_STEPS),\n ];\n break;\n }\n\n return values.map((value) => PROTOCOL_DIGITS[value]).join(\"\");\n}\n\nfunction quantize(value: number, steps: readonly number[]): number {\n let bestIndex = 0;\n let bestDistance = Number.POSITIVE_INFINITY;\n\n for (const [index, step] of steps.entries()) {\n const distance = Math.abs(value - step);\n if (distance < bestDistance) {\n bestIndex = index;\n bestDistance = distance;\n }\n }\n\n return bestIndex;\n}\n\n/** duration_s=0 maps to v11 (infinite); otherwise quantize to DURATION_STEPS_S */\nfunction quantizeDuration(duration_s: number): number {\n if (duration_s === 0) return 11;\n return quantize(duration_s, DURATION_STEPS_S);\n}\n\n/**\n * brightness=0 maps to v11 (explicit off, only valid in STEADY mode per firmware).\n * Otherwise quantize to BRIGHTNESS_STEPS (v0–v5).\n */\nfunction quantizeBrightness(segment: LightSegment): number {\n if (segment.brightness === 0) return 11;\n return quantize(segment.brightness, BRIGHTNESS_STEPS);\n}\n\nfunction quantizeBreathRiseFall(value: number | undefined): number {\n return quantize(value ?? 1040, BREATH_STEPS_MS);\n}\n\nfunction quantizeBreathHoldOff(value: number | undefined): number {\n if (value === 0) {\n return 5;\n }\n\n return quantize(value ?? 1040, BREATH_STEPS_MS.slice(0, 5));\n}\n\nfunction quantizeWindow(value: 1 | 2 | 3): number {\n return value - 1;\n}\n","import { randomUUID } from \"node:crypto\";\nimport { buildLightEffectApnsBody } from \"./protocol.js\";\nimport { getEnvUrls } from \"../env.js\";\nimport type { LightSegment } from \"../types.js\";\n\nexport interface SendLightResult {\n ok: boolean;\n bizUniqueId?: string;\n response?: unknown;\n status?: number;\n error?: string;\n}\n\nexport async function sendLightEffect(\n apiKey: string,\n segments: LightSegment[],\n logger?: { info: (msg: string) => void; warn: (msg: string) => void },\n repeat?: boolean,\n): Promise<SendLightResult> {\n const apiUrl = getEnvUrls().lightApiUrl;\n const appKey = process.env.LIGHT_APP_KEY;\n const templateId = process.env.LIGHT_TEMPLATE_ID;\n\n logger?.info(\n `Light sender: apiUrl=${apiUrl ?? \"UNSET\"}, appKey=${appKey ? appKey.substring(0, 8) + \"…\" : \"UNSET\"}, templateId=${templateId ?? \"UNSET\"}, apiKey=${apiKey ? apiKey.substring(0, 20) + \"…\" : \"EMPTY\"}, segments=${JSON.stringify(segments)}`,\n );\n\n if (!apiUrl || !appKey || !templateId) {\n return {\n ok: false,\n error:\n \"灯效 API 未配置,请设置环境变量 LIGHT_API_URL / LIGHT_APP_KEY / LIGHT_TEMPLATE_ID\",\n };\n }\n\n const bizContent = buildLightEffectApnsBody(segments, repeat);\n const bizUniqueId = randomUUID();\n\n const requestBody = {\n appKey,\n bizMap: { noticeType: \"APP_NOTIFICATION_IMPORTANT\" },\n bizUniqueId,\n paramsMap: { bizContent },\n pushType: \"SPECIFY_PUSH\",\n templateId,\n };\n\n logger?.info(\n `Light sender: POST ${apiUrl}, bizUniqueId=${bizUniqueId}, body=${JSON.stringify(requestBody).substring(0, 500)}`,\n );\n\n const res = await fetch(apiUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-Api-Key-Id\": apiKey.startsWith(\"Bearer \")\n ? apiKey.slice(\"Bearer \".length)\n : apiKey,\n },\n body: JSON.stringify(requestBody),\n });\n\n const resBody = await res.text();\n if (!res.ok) {\n logger?.warn(\n `Light sender: FAILED ${res.status}, url=${apiUrl}, resBody=${resBody.substring(0, 500)}`,\n );\n return { ok: false, status: res.status, error: resBody };\n }\n\n logger?.info(`Light sender: OK bizUniqueId=${bizUniqueId}, resBody=${resBody.substring(0, 200)}`);\n return { ok: true, bizUniqueId, response: JSON.parse(resBody) };\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport { resolveStateFile } from \"./host.js\";\n\nexport type EnvName = \"development\" | \"production\";\n\ninterface EnvUrls {\n lightApiUrl: string;\n appNameMapUrl: string;\n relayTunnelUrl: string;\n}\n\nconst ENV_CONFIG: Record<EnvName, EnvUrls> = {\n development: {\n lightApiUrl: \"https://openclaw-service-dev.yoootek.com/api/message/tob/sendMessage\",\n relayTunnelUrl: \"wss://openclaw-service-dev.yoootek.com/message/messages/ws/plugin\",\n appNameMapUrl:\n \"https://openclaw-service-dev.yoootek.com/api/application-config/app-package/config-all\",\n },\n production: {\n lightApiUrl: \"https://openclaw-service.yoootek.com/api/message/tob/sendMessage\",\n relayTunnelUrl: \"wss://openclaw-service.yoootek.com/message/messages/ws/plugin\",\n appNameMapUrl:\n \"https://openclaw-service.yoootek.com/api/application-config/app-package/config-all\",\n },\n};\n\nconst VALID_ENVS: ReadonlySet<string> = new Set(Object.keys(ENV_CONFIG));\n\nfunction envFilePath(): string {\n return resolveStateFile(\"env.json\");\n}\n\n/** 读取当前环境名称,默认 production */\nexport function loadEnvName(): EnvName {\n const filePath = envFilePath();\n if (!existsSync(filePath)) return \"production\";\n try {\n const data = JSON.parse(readFileSync(filePath, \"utf-8\")) as { env?: string };\n if (data.env && VALID_ENVS.has(data.env)) return data.env as EnvName;\n } catch {\n // ignore\n }\n return \"production\";\n}\n\n/** 持久化当前环境 */\nexport function saveEnvName(env: EnvName): void {\n if (!VALID_ENVS.has(env)) {\n throw new Error(`无效的环境名称: ${env},可选值: ${[...VALID_ENVS].join(\", \")}`);\n }\n const filePath = envFilePath();\n mkdirSync(dirname(filePath), { recursive: true, mode: 0o700 });\n writeFileSync(filePath, JSON.stringify({ env }, null, 2), {\n encoding: \"utf-8\",\n mode: 0o600,\n });\n}\n\n/** 获取当前环境的 URL 配置 */\nexport function getEnvUrls(env?: EnvName): EnvUrls {\n return ENV_CONFIG[env ?? loadEnvName()];\n}\n\n/** 获取所有可用环境名称 */\nexport function getAvailableEnvs(): EnvName[] {\n return Object.keys(ENV_CONFIG) as EnvName[];\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nexport type HostKind = \"openclaw\" | \"qclaw\";\n\ninterface QClawMeta {\n stateDir?: string;\n configPath?: string;\n}\n\nfunction trimToUndefined(value: unknown): string | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n const trimmed = value.trim();\n return trimmed || undefined;\n}\n\nfunction homeDir(): string {\n return process.env.HOME || process.env.USERPROFILE || \"/tmp\";\n}\n\nfunction candidateMetaPaths(): string[] {\n const home = homeDir();\n return [\n join(home, \".qclaw\", \"qclaw.json\"),\n join(home, \".qclow\", \"qclaw.json\"),\n ];\n}\n\nfunction loadQClawMeta(): QClawMeta | undefined {\n for (const metaPath of candidateMetaPaths()) {\n if (!existsSync(metaPath)) {\n continue;\n }\n try {\n const parsed = JSON.parse(readFileSync(metaPath, \"utf-8\")) as QClawMeta;\n return {\n stateDir: trimToUndefined(parsed?.stateDir),\n configPath: trimToUndefined(parsed?.configPath),\n };\n } catch {\n // ignore invalid metadata and keep trying\n }\n }\n return undefined;\n}\n\nfunction resolveStateDirFromEnv(): string | undefined {\n return (\n trimToUndefined(process.env.OPENCLAW_STATE_DIR) ??\n trimToUndefined(process.env.QCLAW_STATE_DIR) ??\n trimToUndefined(process.env.OPENCLAW_ROOT) ??\n trimToUndefined(process.env.OPENCLAW_HOME) ??\n trimToUndefined(process.env.QCLAW_HOME)\n );\n}\n\nexport function detectHostKind(): HostKind {\n if (\n trimToUndefined(process.env.QCLAW_STATE_DIR) ||\n trimToUndefined(process.env.QCLAW_CONFIG_PATH) ||\n trimToUndefined(process.env.QCLAW_HOME)\n ) {\n return \"qclaw\";\n }\n\n if (loadQClawMeta()) {\n return \"qclaw\";\n }\n\n const stateDir = resolveStateDirFromEnv();\n if (stateDir?.includes(\".qclaw\") || stateDir?.includes(\".qclow\")) {\n return \"qclaw\";\n }\n\n return \"openclaw\";\n}\n\nexport function resolveStateDir(): string {\n const envDir = resolveStateDirFromEnv();\n if (envDir) {\n return envDir;\n }\n\n const meta = loadQClawMeta();\n if (meta?.stateDir) {\n return meta.stateDir;\n }\n\n return join(homeDir(), \".openclaw\");\n}\n\nexport function resolveConfigPath(stateDir = resolveStateDir()): string {\n const envConfigPath =\n trimToUndefined(process.env.OPENCLAW_CONFIG_PATH) ??\n trimToUndefined(process.env.QCLAW_CONFIG_PATH);\n if (envConfigPath) {\n return envConfigPath;\n }\n\n const meta = loadQClawMeta();\n if (\n meta?.configPath &&\n (!meta.stateDir || !stateDir || meta.stateDir === stateDir)\n ) {\n return meta.configPath;\n }\n\n return join(stateDir, \"openclaw.json\");\n}\n\nexport function resolveStateFile(filename: string): string {\n return join(resolveStateDir(), filename);\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { loadApiKey, watchCredentials } from \"../auth/credentials.js\";\nimport { getEnvUrls } from \"../env.js\";\n\nconst PLUGIN_STATE_DIR = \"phone-notifications\";\nconst CACHE_FILE = \"app-name-map.json\";\n\n/** 包名→应用名映射 API 地址(默认随环境变化;可用 APP_NAME_MAP_URL 覆盖;需鉴权) */\nconst BUILTIN_APP_NAME_MAP_URL = getEnvUrls().appNameMapUrl;\nconst APP_NAME_MAP_URL =\n (typeof process.env.APP_NAME_MAP_URL === \"string\" && process.env.APP_NAME_MAP_URL.trim()\n ? process.env.APP_NAME_MAP_URL.trim()\n : undefined) ?? BUILTIN_APP_NAME_MAP_URL;\n/** 映射刷新间隔(小时) */\nconst APP_NAME_MAP_REFRESH_HOURS = 12;\n\ninterface Logger {\n info: (message: string) => void;\n warn: (message: string) => void;\n}\n\nfunction isRecordOfStrings(v: unknown): v is Record<string, string> {\n if (v === null || typeof v !== \"object\") return false;\n for (const val of Object.values(v)) if (typeof val !== \"string\") return false;\n return true;\n}\n\n/** API 返回的单项 */\ninterface AppPackageItem {\n appName: string;\n packageName: string;\n iconUrl?: string | null;\n platform?: string | null;\n jumpUrl?: string | null;\n urlParams?: string | null;\n description?: string | null;\n}\n\n/** API 响应格式 */\ninterface AppNameMapApiResponse {\n success?: boolean;\n code?: string;\n message?: string;\n data?: AppPackageItem[];\n}\n\nfunction isAppNameMapApiResponse(v: unknown): v is AppNameMapApiResponse {\n if (v === null || typeof v !== \"object\") return false;\n const o = v as Record<string, unknown>;\n return Array.isArray(o.data) && o.data.every(\n (item: unknown) =>\n item !== null &&\n typeof item === \"object\" &&\n typeof (item as AppPackageItem).packageName === \"string\" &&\n typeof (item as AppPackageItem).appName === \"string\"\n );\n}\n\nfunction getCachePath(stateDir: string): string {\n return join(stateDir, \"plugins\", PLUGIN_STATE_DIR, CACHE_FILE);\n}\n\nexport interface AppNameMapProvider {\n /** 解析包名为显示名(未命中时拉取一次再返回,保证当前落库即有值) */\n resolveDisplayName(packageName: string): Promise<string>;\n start(): Promise<void>;\n stop(): void;\n}\n\nexport function createAppNameMapProvider(opts: {\n stateDir: string;\n logger: Logger;\n}): AppNameMapProvider {\n const { stateDir, logger } = opts;\n const url = APP_NAME_MAP_URL;\n const refreshHours = APP_NAME_MAP_REFRESH_HOURS;\n\n const map = new Map<string, string>();\n let refreshTimer: ReturnType<typeof setInterval> | null = null;\n let stopWatching: (() => void) | null = null;\n let inFlightFetch: Promise<void> | null = null;\n\n function loadFromDisk(): void {\n const path = getCachePath(stateDir);\n if (!existsSync(path)) return;\n try {\n const raw = JSON.parse(readFileSync(path, \"utf-8\"));\n if (!isRecordOfStrings(raw)) return;\n map.clear();\n for (const [k, v] of Object.entries(raw)) map.set(k, v);\n logger.info(`[app-name-map] loaded ${map.size} entries from cache: ${path}`);\n } catch {\n /* ignore */\n }\n }\n\n async function fetchFromServer(): Promise<void> {\n const apiKey = loadApiKey();\n if (!url) {\n logger.warn(\"[app-name-map] APP_NAME_MAP_URL is empty, skip refresh\");\n return;\n }\n if (!apiKey) {\n logger.info(\"[app-name-map] api key missing, skip refresh\");\n return;\n }\n\n const rawApiKey = apiKey.startsWith(\"Bearer \")\n ? apiKey.slice(\"Bearer \".length)\n : apiKey;\n try {\n const res = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", \"X-Api-Key-Id\": rawApiKey },\n body: JSON.stringify({\n platform: \"\"\n })\n });\n if (!res.ok) {\n logger.warn(`[app-name-map] refresh failed: HTTP ${res.status} ${res.statusText}`);\n return;\n }\n const body = await res.json() as unknown;\n if (!isAppNameMapApiResponse(body) || !body.success || !body.data?.length) {\n logger.warn(\"[app-name-map] refresh failed: unexpected response shape or empty data\");\n return;\n }\n map.clear();\n for (const item of body.data) {\n if (item.packageName && item.appName) map.set(item.packageName, item.appName);\n }\n if (map.size === 0) {\n logger.warn(\"[app-name-map] refresh succeeded but got 0 entries\");\n return;\n }\n const dir = join(stateDir, \"plugins\", PLUGIN_STATE_DIR);\n\n mkdirSync(dir, { recursive: true });\n const cachePath = getCachePath(stateDir);\n writeFileSync(cachePath, JSON.stringify(Object.fromEntries(map), null, 2), \"utf-8\");\n logger.info(`[app-name-map] refreshed ${map.size} entries from server and saved: ${cachePath}`);\n } catch (e) {\n const message = e instanceof Error ? e.message : String(e);\n logger.warn(`[app-name-map] refresh error: ${message}`);\n }\n }\n\n async function ensureOneFetch(): Promise<void> {\n if (inFlightFetch) return inFlightFetch;\n inFlightFetch = fetchFromServer().finally(() => {\n inFlightFetch = null;\n });\n return inFlightFetch;\n }\n\n return {\n async resolveDisplayName(packageName: string): Promise<string> {\n // 临时策略:仅使用内存/磁盘中已有的映射,缺少时不主动触发拉取\n if (map.has(packageName)) return map.get(packageName)!;\n return packageName;\n // 如需在缺少应用名时触发一次拉取再返回,可恢复为:\n // if (!url || !loadApiKey()) return packageName;\n // await ensureOneFetch();\n // return map.get(packageName) ?? packageName;\n },\n\n async start(): Promise<void> {\n loadFromDisk();\n await fetchFromServer();\n\n if (!url) return;\n\n if (refreshHours > 0) {\n const ms = refreshHours * 60 * 60 * 1000;\n refreshTimer = setInterval(() => fetchFromServer().catch(() => { }), ms);\n }\n stopWatching = watchCredentials(() => fetchFromServer().catch(() => { }));\n },\n\n stop(): void {\n stopWatching?.();\n stopWatching = null;\n if (refreshTimer) {\n clearInterval(refreshTimer);\n refreshTimer = null;\n }\n map.clear();\n },\n };\n}\n","import {\n existsSync,\n mkdirSync,\n readFileSync,\n writeFileSync,\n watch,\n} from \"node:fs\";\nimport { dirname, basename } from \"node:path\";\nimport { resolveStateFile } from \"../host.js\";\n\ninterface Credentials {\n /**\n * 推荐:API Key 明文(例如 ock_xxx)\n */\n apiKey?: string;\n /**\n * 兼容旧字段:历史上这里存的是 token;现在等价于 apiKey\n */\n token?: string;\n}\n\nexport function credentialsPath(): string {\n return resolveStateFile(\"credentials.json\");\n}\n\nexport function readCredentials(): Credentials {\n const path = credentialsPath();\n if (!existsSync(path)) return {};\n try {\n return JSON.parse(readFileSync(path, \"utf-8\"));\n } catch {\n return {};\n }\n}\n\nexport function writeCredentials(creds: Credentials): void {\n const path = credentialsPath();\n mkdirSync(dirname(path), { recursive: true, mode: 0o700 });\n writeFileSync(path, JSON.stringify(creds, null, 2), {\n encoding: \"utf-8\",\n mode: 0o600,\n });\n}\n\nexport function loadApiKey(): string | undefined {\n const creds = readCredentials();\n return creds.apiKey ?? creds.token;\n}\n\nexport function requireApiKey(): string {\n const apiKey = loadApiKey();\n if (!apiKey) {\n throw new Error(\n `API Key 未设置,请先写入 ${credentialsPath()},或通过宿主 CLI 执行 ntf auth set-api-key <apiKey>`,\n );\n }\n return apiKey;\n}\n\n// ---- Backward-compatible exports (旧代码仍可编译;语义等价于 apiKey) ----\nexport function loadToken(): string | undefined {\n return loadApiKey();\n}\n\nexport function requireToken(): string {\n return requireApiKey();\n}\n\n/** 监听 credentials 文件变化(如 set-token 后)触发 callback;返回取消监听的函数 */\nexport function watchCredentials(onChange: () => void): () => void {\n const path = credentialsPath();\n const dir = dirname(path);\n const filename = basename(path);\n let debounceTimer: ReturnType<typeof setTimeout> | null = null;\n const delayMs = 200;\n\n const listener = (_event: string, changedName: string | null) => {\n if (!changedName || (changedName !== filename && !changedName.endsWith(filename))) return;\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => {\n debounceTimer = null;\n onChange();\n }, delayMs);\n };\n\n let watcher: ReturnType<typeof watch> | null = null;\n try {\n watcher = watch(dir, { persistent: false }, listener);\n } catch {\n // 目录可能不存在\n }\n\n return () => {\n if (debounceTimer) clearTimeout(debounceTimer);\n watcher?.close();\n };\n}\n","import {\n accessSync,\n mkdirSync,\n appendFileSync,\n readdirSync,\n readFileSync,\n writeFileSync,\n existsSync,\n rmSync,\n constants,\n} from \"node:fs\";\nimport { createHash } from \"node:crypto\";\nimport { join } from \"node:path\";\nimport type { PluginConfig, RawNotification } from \"../types.js\";\n\ninterface Logger {\n info: (message: string) => void;\n warn: (message: string) => void;\n}\n\nexport interface StorageContext {\n stateDir: string;\n workspaceDir?: string;\n}\n\n/** Stored notification entry (JSON format, append-only) */\nexport interface StoredNotification {\n /** 包名 */\n appName: string;\n /** 应用显示名(由映射补全),缺省时与 appName 一致 */\n appDisplayName?: string;\n title: string;\n content: string;\n /** ISO 8601 with timezone, e.g. \"2026-03-02T08:30:00+08:00\" */\n timestamp: string;\n}\n\nconst NOTIFICATION_DIR_NAME = \"notifications\";\nconst ID_INDEX_DIR_NAME = \".ids\";\nconst CONTENT_KEY_INDEX_DIR_NAME = \".keys\";\n\nexport interface NotificationIngestResult {\n received: number;\n ingested: number;\n dedupedById: number;\n dedupedByContent: number;\n invalid: number;\n}\n\ntype WriteOutcome =\n | \"ingested\"\n | \"dedupedById\"\n | \"dedupedByContent\"\n | \"invalid\";\n\nexport function getStateFallbackNotificationDir(stateDir: string): string {\n return join(stateDir, \"plugins\", \"phone-notifications\", NOTIFICATION_DIR_NAME);\n}\n\nfunction ensureWritableDirectory(dir: string): boolean {\n try {\n mkdirSync(dir, { recursive: true });\n accessSync(dir, constants.R_OK | constants.W_OK);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function resolveNotificationStorageDir(\n ctx: StorageContext,\n logger: Pick<Logger, \"info\" | \"warn\">,\n): string {\n // 优先使用 stateDir(插件私有稳定路径),避免通知随 workspace 切换而分散\n const stateNotifDir = getStateFallbackNotificationDir(ctx.stateDir);\n\n if (ensureWritableDirectory(stateNotifDir)) {\n logger.info(`通知将写入 stateDir 路径: ${stateNotifDir}`);\n return stateNotifDir;\n }\n\n // stateDir 不可用时回退到 workspaceDir\n if (ctx.workspaceDir) {\n const workspaceDir = join(ctx.workspaceDir, NOTIFICATION_DIR_NAME);\n if (ensureWritableDirectory(workspaceDir)) {\n logger.warn(\n `stateDir 不可用,通知已回退到 workspace 路径: ${workspaceDir}`,\n );\n return workspaceDir;\n }\n }\n\n throw new Error(`通知存储目录不可用: ${stateNotifDir}`);\n}\n\n/** 包名 → 应用显示名(异步,未命中时内部可拉取后返回);不提供则落库仅用 appName */\nexport type ResolveDisplayName = (packageName: string) => Promise<string>;\n\nexport class NotificationStorage {\n private dir: string;\n private idIndexDir: string;\n private contentKeyIndexDir: string;\n private idCache = new Map<string, Set<string>>();\n private contentKeyCache = new Map<string, Set<string>>();\n private dateWriteChains = new Map<string, Promise<void>>();\n private resolveDisplayName: ResolveDisplayName | undefined;\n\n constructor(\n dir: string,\n private config: PluginConfig,\n private logger: Logger,\n resolveDisplayName?: ResolveDisplayName,\n ) {\n this.dir = dir;\n this.idIndexDir = join(dir, ID_INDEX_DIR_NAME);\n this.contentKeyIndexDir = join(dir, CONTENT_KEY_INDEX_DIR_NAME);\n this.resolveDisplayName = resolveDisplayName;\n }\n\n async init() {\n mkdirSync(this.dir, { recursive: true });\n mkdirSync(this.idIndexDir, { recursive: true });\n mkdirSync(this.contentKeyIndexDir, { recursive: true });\n }\n\n async ingest(items: RawNotification[]): Promise<NotificationIngestResult> {\n const result: NotificationIngestResult = {\n received: items.length,\n ingested: 0,\n dedupedById: 0,\n dedupedByContent: 0,\n invalid: 0,\n };\n\n for (const n of items) {\n const outcome = await this.writeNotification(n);\n result[outcome] += 1;\n }\n this.prune();\n return result;\n }\n\n private async writeNotification(n: RawNotification): Promise<WriteOutcome> {\n const ts = new Date(n.timestamp);\n if (Number.isNaN(ts.getTime())) {\n this.logger.warn(`忽略非法 timestamp 的通知: ${n.id}`);\n return \"invalid\";\n }\n\n const dateKey = this.formatDate(ts);\n const filePath = join(this.dir, `${dateKey}.json`);\n const normalizedId = typeof n.id === \"string\" ? n.id.trim() : \"\";\n const entry = this.buildStoredNotification(n);\n\n return this.withDateWriteLock(dateKey, async () => {\n if (normalizedId && this.hasNotificationId(dateKey, normalizedId)) {\n return \"dedupedById\";\n }\n\n if (this.hasNotificationContentKey(dateKey, filePath, entry)) {\n return \"dedupedByContent\";\n }\n\n const appDisplayName = this.resolveDisplayName\n ? await this.resolveDisplayName(entry.appName)\n : entry.appName;\n\n const storedEntry: StoredNotification = {\n ...entry,\n appDisplayName,\n };\n\n const arr = this.readStoredNotifications(filePath);\n arr.push(storedEntry);\n writeFileSync(filePath, JSON.stringify(arr, null, 2), \"utf-8\");\n\n if (normalizedId) {\n this.recordNotificationId(dateKey, normalizedId);\n }\n this.recordNotificationContentKey(dateKey, filePath, storedEntry);\n return \"ingested\";\n });\n }\n\n private buildStoredNotification(n: RawNotification): StoredNotification {\n return {\n appName: typeof n.app === \"string\" && n.app ? n.app : \"Unknown\",\n title: typeof n.title === \"string\" ? n.title : \"\",\n content: this.buildContent(n),\n timestamp: n.timestamp,\n };\n }\n\n private buildContent(n: RawNotification): string {\n const body = n.body?.trim();\n if (body) {\n return body;\n }\n\n const fallback: string[] = [];\n if (n.category) {\n fallback.push(`category:${n.category}`);\n }\n\n if (n.metadata && Object.keys(n.metadata).length > 0) {\n fallback.push(`metadata:${JSON.stringify(n.metadata)}`);\n }\n\n return fallback.join(\" ; \") || \"-\";\n }\n\n private formatDate(d: Date): string {\n const year = d.getFullYear();\n const month = String(d.getMonth() + 1).padStart(2, \"0\");\n const day = String(d.getDate()).padStart(2, \"0\");\n return `${year}-${month}-${day}`;\n }\n\n private getIdIndexPath(dateKey: string): string {\n return join(this.idIndexDir, `${dateKey}.ids`);\n }\n\n private getIdSet(dateKey: string): Set<string> {\n const cached = this.idCache.get(dateKey);\n if (cached) {\n return cached;\n }\n\n const idPath = this.getIdIndexPath(dateKey);\n const ids = new Set<string>();\n if (existsSync(idPath)) {\n const lines = readFileSync(idPath, \"utf-8\").split(/\\r?\\n/);\n for (const line of lines) {\n const id = line.trim();\n if (id) {\n ids.add(id);\n }\n }\n }\n\n this.idCache.set(dateKey, ids);\n return ids;\n }\n\n private getContentKeyIndexPath(dateKey: string): string {\n return join(this.contentKeyIndexDir, `${dateKey}.keys`);\n }\n\n private getContentKeySet(dateKey: string, filePath: string): Set<string> {\n const cached = this.contentKeyCache.get(dateKey);\n if (cached) {\n return cached;\n }\n\n const keyPath = this.getContentKeyIndexPath(dateKey);\n const keys = new Set<string>();\n\n if (existsSync(keyPath)) {\n const lines = readFileSync(keyPath, \"utf-8\").split(/\\r?\\n/);\n for (const line of lines) {\n const key = line.trim();\n if (key) {\n keys.add(key);\n }\n }\n } else if (existsSync(filePath)) {\n for (const item of this.readStoredNotifications(filePath)) {\n keys.add(this.buildNotificationContentKey(item));\n }\n\n if (keys.size > 0) {\n writeFileSync(keyPath, `${Array.from(keys).join(\"\\n\")}\\n`, \"utf-8\");\n }\n }\n\n this.contentKeyCache.set(dateKey, keys);\n return keys;\n }\n\n private hasNotificationId(dateKey: string, id: string): boolean {\n return this.getIdSet(dateKey).has(id);\n }\n\n private hasNotificationContentKey(\n dateKey: string,\n filePath: string,\n entry: Pick<StoredNotification, \"appName\" | \"title\" | \"content\">,\n ): boolean {\n return this.getContentKeySet(dateKey, filePath).has(\n this.buildNotificationContentKey(entry),\n );\n }\n\n private recordNotificationId(dateKey: string, id: string) {\n const ids = this.getIdSet(dateKey);\n if (ids.has(id)) {\n return;\n }\n\n appendFileSync(this.getIdIndexPath(dateKey), `${id}\\n`, \"utf-8\");\n ids.add(id);\n }\n\n private recordNotificationContentKey(\n dateKey: string,\n filePath: string,\n entry: Pick<StoredNotification, \"appName\" | \"title\" | \"content\">,\n ) {\n const keys = this.getContentKeySet(dateKey, filePath);\n const key = this.buildNotificationContentKey(entry);\n\n if (keys.has(key)) {\n return;\n }\n\n appendFileSync(this.getContentKeyIndexPath(dateKey), `${key}\\n`, \"utf-8\");\n keys.add(key);\n }\n\n private buildNotificationContentKey(\n entry: Pick<StoredNotification, \"appName\" | \"title\" | \"content\">,\n ): string {\n return createHash(\"sha256\")\n .update(entry.appName)\n .update(\"\\x1f\")\n .update(entry.title)\n .update(\"\\x1f\")\n .update(entry.content)\n .digest(\"hex\");\n }\n\n private readStoredNotifications(filePath: string): StoredNotification[] {\n if (!existsSync(filePath)) {\n return [];\n }\n\n try {\n const parsed = JSON.parse(readFileSync(filePath, \"utf-8\"));\n return Array.isArray(parsed) ? parsed : [];\n } catch {\n return [];\n }\n }\n\n private async withDateWriteLock<T>(\n dateKey: string,\n task: () => Promise<T>,\n ): Promise<T> {\n const previous = this.dateWriteChains.get(dateKey) ?? Promise.resolve();\n let release!: () => void;\n const current = new Promise<void>((resolve) => {\n release = resolve;\n });\n const chain = previous.then(() => current);\n this.dateWriteChains.set(dateKey, chain);\n\n await previous;\n try {\n return await task();\n } finally {\n release();\n if (this.dateWriteChains.get(dateKey) === chain) {\n this.dateWriteChains.delete(dateKey);\n }\n }\n }\n\n private prune() {\n const retentionDays = this.config.retentionDays ?? 30;\n const cutoffMs = Date.now() - retentionDays * 24 * 60 * 60 * 1000;\n const cutoffDate = this.formatDate(new Date(cutoffMs));\n\n this.pruneDataFiles(cutoffDate);\n this.pruneIdIndex(cutoffDate);\n this.pruneContentKeyIndex(cutoffDate);\n }\n\n /** Remove expired .json, legacy .md files, and legacy date directories */\n private pruneDataFiles(cutoffDate: string) {\n const dateFilePattern = /^(\\d{4}-\\d{2}-\\d{2})\\.(json|md)$/;\n const dateDirPattern = /^\\d{4}-\\d{2}-\\d{2}$/;\n\n try {\n for (const entry of readdirSync(this.dir, { withFileTypes: true })) {\n if (entry.isFile()) {\n const match = dateFilePattern.exec(entry.name);\n if (match && match[1] < cutoffDate) {\n rmSync(join(this.dir, entry.name), { force: true });\n }\n } else if (entry.isDirectory() && dateDirPattern.test(entry.name) && entry.name < cutoffDate) {\n rmSync(join(this.dir, entry.name), { recursive: true, force: true });\n }\n }\n } catch {\n // ignore\n }\n }\n\n /** Remove expired .ids index files */\n private pruneIdIndex(cutoffDate: string) {\n try {\n for (const entry of readdirSync(this.idIndexDir, { withFileTypes: true })) {\n if (!entry.isFile()) continue;\n const match = /^(\\d{4}-\\d{2}-\\d{2})\\.ids$/.exec(entry.name);\n if (match && match[1] < cutoffDate) {\n rmSync(join(this.idIndexDir, entry.name), { force: true });\n this.idCache.delete(match[1]);\n }\n }\n } catch {\n // ignore\n }\n }\n\n /** Remove expired .keys index files */\n private pruneContentKeyIndex(cutoffDate: string) {\n try {\n for (const entry of readdirSync(this.contentKeyIndexDir, { withFileTypes: true })) {\n if (!entry.isFile()) continue;\n const match = /^(\\d{4}-\\d{2}-\\d{2})\\.keys$/.exec(entry.name);\n if (match && match[1] < cutoffDate) {\n rmSync(join(this.contentKeyIndexDir, entry.name), { force: true });\n this.contentKeyCache.delete(match[1]);\n }\n }\n } catch {\n // ignore\n }\n }\n\n async close() {\n this.idCache.clear();\n this.contentKeyCache.clear();\n this.dateWriteChains.clear();\n }\n}\n","import { existsSync, rmSync } from \"node:fs\";\nimport type { CliCommand } from \"./helpers.js\";\nimport { output } from \"./helpers.js\";\nimport {\n credentialsPath,\n readCredentials,\n writeCredentials,\n} from \"../auth/credentials.js\";\n\nexport function registerAuthCli(program: CliCommand): void {\n const auth = program\n .command(\"auth\")\n .description(\"用户认证管理\");\n\n auth\n .command(\"set-api-key <apiKey>\")\n .description(\"设置用户 API Key(持久化到本地配置)\")\n .action((apiKey: string) => {\n writeCredentials({ ...readCredentials(), apiKey, token: undefined });\n output({\n ok: true,\n apiKey: apiKey.slice(0, 8) + \"…\",\n storedAt: credentialsPath(),\n });\n });\n\n // 兼容旧命令:set-token <token>,现在等价于 set-api-key\n auth\n .command(\"set-token <token>\")\n .description(\"(兼容)设置用户 API Key(旧命令名)\")\n .action((token: string) => {\n writeCredentials({ ...readCredentials(), apiKey: token, token: undefined });\n output({\n ok: true,\n apiKey: token.slice(0, 8) + \"…\",\n storedAt: credentialsPath(),\n });\n });\n\n auth\n .command(\"show\")\n .description(\"查看当前认证状态\")\n .action(() => {\n const creds = readCredentials();\n const apiKey = creds.apiKey ?? creds.token;\n if (apiKey) {\n output({\n ok: true,\n hasApiKey: true,\n apiKey: apiKey.slice(0, 8) + \"…\",\n storedAt: credentialsPath(),\n });\n } else {\n output({ ok: true, hasApiKey: false });\n }\n });\n\n auth\n .command(\"clear\")\n .description(\"清除已保存的认证信息\")\n .action(() => {\n const path = credentialsPath();\n if (existsSync(path)) {\n const creds = readCredentials();\n delete creds.apiKey;\n delete creds.token;\n if (Object.keys(creds).length === 0) {\n rmSync(path, { force: true });\n } else {\n writeCredentials(creds);\n }\n }\n output({ ok: true, cleared: true });\n });\n}\n","import { existsSync, readFileSync, readdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { StoredNotification } from \"../notification/storage.js\";\n\n/**\n * Minimal Commander.js Command interface.\n * The real `Command` instance comes from the openclaw runtime at registration time;\n * we only declare the subset we use so that `commander` need not be a direct dep.\n */\nexport interface CliCommand {\n command(nameAndArgs: string): CliCommand;\n description(str: string): CliCommand;\n version(str: string, flags?: string, description?: string): CliCommand;\n option(flags: string, description: string, defaultValue?: string): CliCommand;\n requiredOption(flags: string, description: string): CliCommand;\n action(fn: (...args: any[]) => void | Promise<void>): CliCommand;\n}\n\nexport interface CliContext {\n workspaceDir?: string;\n stateDir?: string;\n}\n\n/** Resolve the notifications storage directory (stateDir → workspace fallback) */\nexport function resolveNotificationsDir(ctx: CliContext): string | null {\n if (ctx.stateDir) {\n const dir = join(\n ctx.stateDir,\n \"plugins\",\n \"phone-notifications\",\n \"notifications\",\n );\n if (existsSync(dir)) return dir;\n }\n if (ctx.workspaceDir) {\n const dir = join(ctx.workspaceDir, \"notifications\");\n if (existsSync(dir)) return dir;\n }\n return null;\n}\n\n/** List available date keys (YYYY-MM-DD) sorted descending */\nexport function listDateKeys(dir: string): string[] {\n const pattern = /^(\\d{4}-\\d{2}-\\d{2})\\.json$/;\n const keys: string[] = [];\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n if (!entry.isFile()) continue;\n const m = pattern.exec(entry.name);\n if (m) keys.push(m[1]);\n }\n return keys.sort().reverse();\n}\n\n/** Read notifications for a specific date */\nexport function readDateFile(\n dir: string,\n dateKey: string,\n): StoredNotification[] {\n const filePath = join(dir, `${dateKey}.json`);\n if (!existsSync(filePath)) return [];\n try {\n return JSON.parse(readFileSync(filePath, \"utf-8\"));\n } catch {\n return [];\n }\n}\n\n/** Format today as YYYY-MM-DD */\nexport function today(): string {\n return formatDate(new Date());\n}\n\n/** Format a Date as YYYY-MM-DD */\nexport function formatDate(d: Date): string {\n const y = d.getFullYear();\n const m = String(d.getMonth() + 1).padStart(2, \"0\");\n const day = String(d.getDate()).padStart(2, \"0\");\n return `${y}-${m}-${day}`;\n}\n\n/** Get date N days ago as YYYY-MM-DD */\nexport function daysAgo(n: number): string {\n const d = new Date();\n d.setDate(d.getDate() - n);\n return formatDate(d);\n}\n\n/** Filter date keys to a [from, to] range (inclusive) */\nexport function filterDateRange(\n keys: string[],\n from: string,\n to: string,\n): string[] {\n return keys.filter((k) => k >= from && k <= to);\n}\n\n/** Print JSON result to stdout */\nexport function output(data: unknown): void {\n process.stdout.write(JSON.stringify(data, null, 2) + \"\\n\");\n}\n\n/** Print error JSON and exit with code 1 */\nexport function exitError(code: string, message: string): never {\n output({ ok: false, error: { code, message } });\n process.exit(1);\n}\n","import type { StoredNotification } from \"../notification/storage.js\";\nimport {\n type CliCommand,\n type CliContext,\n resolveNotificationsDir,\n listDateKeys,\n readDateFile,\n filterDateRange,\n today,\n daysAgo,\n output,\n exitError,\n} from \"./helpers.js\";\n\nexport function registerNtfSearch(ntf: CliCommand, ctx: CliContext): void {\n ntf\n .command(\"search\")\n .description(\"查询通知(按日期/应用/发送人/关键词筛选)\")\n .option(\"--from <date>\", \"开始日期 YYYY-MM-DD\", daysAgo(7))\n .option(\"--to <date>\", \"结束日期 YYYY-MM-DD\", today())\n .option(\"--app <name>\", \"按应用名过滤\")\n .option(\"--sender <name>\", \"按发送人过滤\")\n .option(\"--keyword <text>\", \"在标题和内容中搜索关键词\")\n .option(\"--limit <n>\", \"最大返回条数\", \"100\")\n .action(\n (opts: {\n from: string;\n to: string;\n app?: string;\n sender?: string;\n keyword?: string;\n limit: string;\n }) => {\n const dir = resolveNotificationsDir(ctx);\n if (!dir) exitError(\"STORAGE_UNAVAILABLE\", \"通知存储目录不可用\");\n\n const keys = filterDateRange(listDateKeys(dir), opts.from, opts.to);\n const limit = parseInt(opts.limit, 10) || 100;\n const results: StoredNotification[] = [];\n\n for (const dateKey of keys) {\n if (results.length >= limit) break;\n const items = readDateFile(dir, dateKey);\n for (const item of items) {\n if (results.length >= limit) break;\n if (opts.app && item.appName !== opts.app) continue;\n if (opts.sender && !item.title.includes(opts.sender)) continue;\n if (\n opts.keyword &&\n !item.title.includes(opts.keyword) &&\n !item.content.includes(opts.keyword)\n )\n continue;\n results.push(item);\n }\n }\n\n output({\n ok: true,\n total: results.length,\n notifications: results,\n });\n },\n );\n}\n","import {\n type CliCommand,\n type CliContext,\n resolveNotificationsDir,\n listDateKeys,\n readDateFile,\n filterDateRange,\n today,\n daysAgo,\n output,\n exitError,\n} from \"./helpers.js\";\n\ntype Dimension = \"date\" | \"app\" | \"sender\" | \"hour\" | \"all\";\n\nexport function registerNtfStats(ntf: CliCommand, ctx: CliContext): void {\n ntf\n .command(\"stats\")\n .description(\"通知统计分析(按日期/应用/发送人/时段聚合)\")\n .option(\"--from <date>\", \"开始日期 YYYY-MM-DD\", daysAgo(7))\n .option(\"--to <date>\", \"结束日期 YYYY-MM-DD\", today())\n .option(\"--app <name>\", \"只统计指定应用\")\n .option(\"--dim <dimension>\", \"统计维度:date/app/sender/hour/all\", \"all\")\n .action(\n (opts: { from: string; to: string; app?: string; dim: string }) => {\n const dir = resolveNotificationsDir(ctx);\n if (!dir) exitError(\"STORAGE_UNAVAILABLE\", \"通知存储目录不可用\");\n\n const dim = opts.dim as Dimension;\n const keys = filterDateRange(listDateKeys(dir), opts.from, opts.to);\n\n const byDate: Record<string, number> = {};\n const byApp: Record<string, number> = {};\n const bySender: Record<string, number> = {};\n const byHour: Record<string, number> = {};\n let total = 0;\n\n for (const dateKey of keys) {\n const items = readDateFile(dir, dateKey);\n let dateCount = 0;\n for (const item of items) {\n if (opts.app && item.appName !== opts.app) continue;\n total++;\n dateCount++;\n\n byApp[item.appName] = (byApp[item.appName] || 0) + 1;\n\n if (item.title) {\n bySender[item.title] = (bySender[item.title] || 0) + 1;\n }\n\n const hourMatch = /T(\\d{2}):/.exec(item.timestamp);\n if (hourMatch) {\n const h = hourMatch[1];\n byHour[h] = (byHour[h] || 0) + 1;\n }\n }\n byDate[dateKey] = dateCount;\n }\n\n const result: Record<string, unknown> = {\n ok: true,\n range: { from: opts.from, to: opts.to },\n total,\n };\n\n if (dim === \"date\" || dim === \"all\") {\n result.byDate = byDate;\n }\n if (dim === \"app\" || dim === \"all\") {\n result.byApp = byApp;\n }\n if (dim === \"sender\" || dim === \"all\") {\n // Sort by count descending, return top 20\n const sorted = Object.entries(bySender)\n .sort((a, b) => b[1] - a[1])\n .slice(0, 20)\n .map(([sender, count]) => ({ sender, count }));\n result.bySender = sorted;\n }\n if (dim === \"hour\" || dim === \"all\") {\n result.byHour = byHour;\n }\n\n output(result);\n },\n );\n}\n","import { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport {\n type CliCommand,\n type CliContext,\n resolveNotificationsDir,\n listDateKeys,\n readDateFile,\n output,\n exitError,\n} from \"./helpers.js\";\n\ninterface CheckpointData {\n [dateKey: string]: { lastIndex: number };\n}\n\nfunction checkpointPath(dir: string): string {\n return join(dir, \".checkpoint.json\");\n}\n\nfunction readCheckpoint(dir: string): CheckpointData {\n const p = checkpointPath(dir);\n if (!existsSync(p)) return {};\n try {\n return JSON.parse(readFileSync(p, \"utf-8\"));\n } catch {\n return {};\n }\n}\n\nfunction writeCheckpoint(dir: string, data: CheckpointData): void {\n writeFileSync(checkpointPath(dir), JSON.stringify(data, null, 2), \"utf-8\");\n}\n\nexport function registerNtfSync(ntf: CliCommand, ctx: CliContext): void {\n const sync = ntf.command(\"sync\").description(\"同步通知到记忆系统\");\n\n sync\n .command(\"scan\")\n .description(\"扫描未处理的通知,返回待同步摘要\")\n .action(() => {\n const dir = resolveNotificationsDir(ctx);\n if (!dir) exitError(\"STORAGE_UNAVAILABLE\", \"通知存储目录不可用\");\n\n const checkpoint = readCheckpoint(dir);\n const keys = listDateKeys(dir); // descending\n const pending: { date: string; count: number; startIndex: number }[] = [];\n let totalPending = 0;\n\n for (const dateKey of keys) {\n const items = readDateFile(dir, dateKey);\n const lastIndex = checkpoint[dateKey]?.lastIndex ?? -1;\n const unprocessed = items.length - (lastIndex + 1);\n if (unprocessed > 0) {\n pending.push({\n date: dateKey,\n count: unprocessed,\n startIndex: lastIndex + 1,\n });\n totalPending += unprocessed;\n }\n }\n\n output({ ok: true, pending, totalPending });\n });\n\n sync\n .command(\"fetch\")\n .description(\"获取指定日期的未处理通知详情\")\n .requiredOption(\"--date <date>\", \"目标日期 YYYY-MM-DD\")\n .action((opts: { date: string }) => {\n const dir = resolveNotificationsDir(ctx);\n if (!dir) exitError(\"STORAGE_UNAVAILABLE\", \"通知存储目录不可用\");\n\n const items = readDateFile(dir, opts.date);\n if (items.length === 0) {\n exitError(\"NO_DATA\", `日期 ${opts.date} 无通知数据`);\n }\n\n const checkpoint = readCheckpoint(dir);\n const lastIndex = checkpoint[opts.date]?.lastIndex ?? -1;\n const startIndex = lastIndex + 1;\n const unprocessed = items.slice(startIndex);\n\n if (unprocessed.length === 0) {\n output({\n ok: true,\n date: opts.date,\n startIndex,\n notifications: [],\n });\n return;\n }\n\n output({\n ok: true,\n date: opts.date,\n startIndex,\n notifications: unprocessed,\n });\n });\n\n sync\n .command(\"commit\")\n .description(\"标记指定日期处理完成,更新 checkpoint\")\n .requiredOption(\"--date <date>\", \"目标日期 YYYY-MM-DD\")\n .action((opts: { date: string }) => {\n const dir = resolveNotificationsDir(ctx);\n if (!dir) exitError(\"STORAGE_UNAVAILABLE\", \"通知存储目录不可用\");\n\n const items = readDateFile(dir, opts.date);\n if (items.length === 0) {\n exitError(\"NO_DATA\", `日期 ${opts.date} 无通知数据`);\n }\n\n const checkpoint = readCheckpoint(dir);\n const committedIndex = items.length - 1;\n checkpoint[opts.date] = { lastIndex: committedIndex };\n writeCheckpoint(dir, checkpoint);\n\n output({\n ok: true,\n date: opts.date,\n committedIndex,\n });\n });\n}\n","import {\n existsSync,\n mkdirSync,\n readFileSync,\n writeFileSync,\n rmSync,\n readdirSync,\n} from \"node:fs\";\nimport { join } from \"node:path\";\nimport { type CliCommand, type CliContext, output, exitError } from \"./helpers.js\";\n\ninterface MonitorMeta {\n name: string;\n description: string;\n matchRules: Record<string, unknown>;\n cronSchedule: string;\n enabled: boolean;\n createdAt: string;\n}\n\nfunction tasksDir(ctx: CliContext): string {\n const base = ctx.workspaceDir || ctx.stateDir;\n if (!base) throw new Error(\"workspaceDir and stateDir both unavailable\");\n return join(base, \"tasks\");\n}\n\nfunction readMeta(taskDir: string): MonitorMeta | null {\n const metaPath = join(taskDir, \"meta.json\");\n if (!existsSync(metaPath)) return null;\n try {\n return JSON.parse(readFileSync(metaPath, \"utf-8\"));\n } catch {\n return null;\n }\n}\n\nfunction writeMeta(taskDir: string, meta: MonitorMeta): void {\n writeFileSync(join(taskDir, \"meta.json\"), JSON.stringify(meta, null, 2), \"utf-8\");\n}\n\nfunction generateFetchPy(\n name: string,\n matchRules: Record<string, unknown>,\n): string {\n const appName = (matchRules.appName as string) || \"\";\n const keywords = (matchRules.senderKeywords as string[]) || [];\n const keywordChecks = keywords\n .map((k) => ` if \"${k}\" in title:`)\n .join(\"\\n\");\n const keywordReturn =\n keywords.length > 0\n ? `${keywordChecks}\\n return True\\n return False`\n : \" return True\";\n\n return `#!/usr/bin/env python3\n\"\"\"Auto-generated fetch script for monitor task: ${name}\"\"\"\nimport json, sys, os\nfrom pathlib import Path\n\ndef matches(notification: dict) -> bool:\n app = notification.get(\"appName\", \"\")\n title = notification.get(\"title\", \"\")\n${appName ? ` if app != \"${appName}\":\\n return False` : \" # No app filter\"}\n${keywordReturn}\n\ndef main():\n import argparse\n parser = argparse.ArgumentParser()\n parser.add_argument(\"--notifications-dir\", required=True)\n args = parser.parse_args()\n\n checkpoint_path = Path(__file__).parent / \"checkpoint.json\"\n checkpoint = {}\n if checkpoint_path.exists():\n checkpoint = json.loads(checkpoint_path.read_text())\n\n ntf_dir = Path(args.notifications_dir)\n matched = []\n new_checkpoint = dict(checkpoint)\n\n for f in sorted(ntf_dir.glob(\"*.json\")):\n date_key = f.stem\n items = json.loads(f.read_text())\n last_idx = checkpoint.get(date_key, {}).get(\"lastIndex\", -1)\n for i, item in enumerate(items):\n if i <= last_idx:\n continue\n if matches(item):\n matched.append(item)\n new_checkpoint[date_key] = {\"lastIndex\": len(items) - 1}\n\n checkpoint_path.write_text(json.dumps(new_checkpoint, indent=2))\n\n if not matched:\n print(\"NO_MATCH\")\n return\n\n for m in matched:\n print(json.dumps(m, ensure_ascii=False))\n\nif __name__ == \"__main__\":\n main()\n`;\n}\n\nfunction generateReadme(name: string, description: string): string {\n return `# Monitor Task: ${name}\n\n## 描述\n${description}\n\n## 处理指南\n当 fetch.py 输出匹配的通知时,请:\n1. 阅读匹配到的通知内容\n2. 根据任务描述判断是否需要通知用户\n3. 如需通知用户,使用 message 工具发送摘要\n`;\n}\n\nexport function registerNtfMonitor(ntf: CliCommand, ctx: CliContext): void {\n const monitor = ntf.command(\"monitor\").description(\"通知监控任务管理\");\n\n monitor\n .command(\"list\")\n .description(\"列出所有监控任务\")\n .action(() => {\n const dir = tasksDir(ctx);\n if (!existsSync(dir)) {\n output({ ok: true, tasks: [] });\n return;\n }\n\n const tasks: MonitorMeta[] = [];\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue;\n const meta = readMeta(join(dir, entry.name));\n if (meta) tasks.push(meta);\n }\n\n output({ ok: true, tasks });\n });\n\n monitor\n .command(\"show <name>\")\n .description(\"查看监控任务详情\")\n .action((name: string) => {\n const taskDir = join(tasksDir(ctx), name);\n const meta = readMeta(taskDir);\n if (!meta) exitError(\"NOT_FOUND\", `监控任务 '${name}' 不存在`);\n\n const checkpointPath = join(taskDir, \"checkpoint.json\");\n let checkpoint = {};\n if (existsSync(checkpointPath)) {\n try {\n checkpoint = JSON.parse(readFileSync(checkpointPath, \"utf-8\"));\n } catch {\n // ignore\n }\n }\n\n output({\n ok: true,\n ...meta,\n matchScript: `tasks/${name}/fetch.py`,\n readme: `tasks/${name}/README.md`,\n checkpoint,\n });\n });\n\n monitor\n .command(\"create <name>\")\n .description(\"创建监控任务\")\n .requiredOption(\"--description <text>\", \"任务描述\")\n .requiredOption(\"--match-rules <json>\", \"匹配规则 JSON\")\n .requiredOption(\"--schedule <cron>\", \"cron 表达式\")\n .action(\n (\n name: string,\n opts: {\n description: string;\n matchRules: string;\n schedule: string;\n },\n ) => {\n const dir = tasksDir(ctx);\n const taskDir = join(dir, name);\n\n if (existsSync(taskDir)) {\n exitError(\"ALREADY_EXISTS\", `监控任务 '${name}' 已存在`);\n }\n\n let matchRules: Record<string, unknown>;\n try {\n matchRules = JSON.parse(opts.matchRules);\n } catch {\n exitError(\n \"VALIDATION_FAILED\",\n \"match-rules 必须是合法的 JSON\",\n );\n }\n\n mkdirSync(taskDir, { recursive: true });\n\n const meta: MonitorMeta = {\n name,\n description: opts.description,\n matchRules,\n cronSchedule: opts.schedule,\n enabled: true,\n createdAt: new Date().toISOString(),\n };\n writeMeta(taskDir, meta);\n writeFileSync(\n join(taskDir, \"fetch.py\"),\n generateFetchPy(name, matchRules),\n \"utf-8\",\n );\n writeFileSync(\n join(taskDir, \"README.md\"),\n generateReadme(name, opts.description),\n \"utf-8\",\n );\n\n output({\n ok: true,\n name,\n created: {\n script: `tasks/${name}/fetch.py`,\n readme: `tasks/${name}/README.md`,\n cronJob: `notif-${name}`,\n },\n cronHint: {\n action: \"add\",\n job: {\n name: `notif-${name}`,\n schedule: opts.schedule,\n sessionTarget: \"isolated\",\n message: `手机通知已由独立服务实时捕获到 notifications/ 目录的 JSON 文件中。\\n执行:python3 tasks/${name}/fetch.py --notifications-dir notifications\\n- NO_CHANGE 或 NO_MATCH → 不回复,直接结束。\\n- 有输出 → 读 tasks/${name}/README.md 了解如何处理数据并通知用户。`,\n },\n },\n });\n },\n );\n\n monitor\n .command(\"delete <name>\")\n .description(\"删除监控任务\")\n .option(\"--yes\", \"跳过确认\")\n .action((name: string, opts: { yes?: boolean }) => {\n const taskDir = join(tasksDir(ctx), name);\n if (!existsSync(taskDir)) {\n exitError(\"NOT_FOUND\", `监控任务 '${name}' 不存在`);\n }\n\n if (!opts.yes) {\n output({\n ok: false,\n error: {\n code: \"CONFIRMATION_REQUIRED\",\n message: `确认删除监控任务 '${name}'?添加 --yes 跳过确认`,\n },\n });\n process.exit(1);\n }\n\n rmSync(taskDir, { recursive: true, force: true });\n output({\n ok: true,\n name,\n deleted: true,\n cronHint: {\n action: \"remove\",\n name: `notif-${name}`,\n },\n });\n });\n\n monitor\n .command(\"enable <name>\")\n .description(\"启用监控任务\")\n .action((name: string) => {\n const taskDir = join(tasksDir(ctx), name);\n const meta = readMeta(taskDir);\n if (!meta) exitError(\"NOT_FOUND\", `监控任务 '${name}' 不存在`);\n\n meta.enabled = true;\n writeMeta(taskDir, meta);\n output({ ok: true, name, enabled: true });\n });\n\n monitor\n .command(\"disable <name>\")\n .description(\"暂停监控任务\")\n .action((name: string) => {\n const taskDir = join(tasksDir(ctx), name);\n const meta = readMeta(taskDir);\n if (!meta) exitError(\"NOT_FOUND\", `监控任务 '${name}' 不存在`);\n\n meta.enabled = false;\n writeMeta(taskDir, meta);\n output({ ok: true, name, enabled: false });\n });\n}\n","import { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { LightSegment } from \"../types.js\";\nimport { type CliCommand, type CliContext, output, exitError } from \"./helpers.js\";\nimport { validateSegments, parseAndValidateSegments } from \"../light/validators.js\";\n\ninterface LightRule {\n name: string;\n trigger: string;\n effect: string;\n segments: LightSegment[];\n}\n\nconst LIGHT_RULES_SECTION = \"## 灯效规则\";\n\nfunction memoryPath(ctx: CliContext): string {\n const base = ctx.workspaceDir || ctx.stateDir;\n if (!base) throw new Error(\"workspaceDir and stateDir both unavailable\");\n return join(base, \"MEMORY.md\");\n}\n\nfunction readMemory(ctx: CliContext): string {\n const p = memoryPath(ctx);\n if (!existsSync(p)) return \"\";\n return readFileSync(p, \"utf-8\");\n}\n\nfunction writeMemory(ctx: CliContext, content: string): void {\n writeFileSync(memoryPath(ctx), content, \"utf-8\");\n}\n\nfunction parseLightRules(content: string): LightRule[] {\n const rules: LightRule[] = [];\n const sectionIdx = content.indexOf(LIGHT_RULES_SECTION);\n if (sectionIdx === -1) return rules;\n\n const sectionContent = content.slice(sectionIdx);\n // Find next ## heading to bound the section\n const nextSection = sectionContent.indexOf(\"\\n## \", 1);\n const bounded = nextSection !== -1\n ? sectionContent.slice(0, nextSection)\n : sectionContent;\n\n const rulePattern = /### 规则:(.+)\\n/g;\n let match;\n while ((match = rulePattern.exec(bounded)) !== null) {\n const name = match[1].trim();\n const ruleStart = match.index + match[0].length;\n const nextRule = bounded.indexOf(\"\\n### \", ruleStart);\n const ruleBlock =\n nextRule !== -1\n ? bounded.slice(ruleStart, nextRule)\n : bounded.slice(ruleStart);\n\n const triggerMatch = /\\*\\*触发条件\\*\\*:(.+)/.exec(ruleBlock);\n const effectMatch = /\\*\\*灯效描述\\*\\*:(.+)/.exec(ruleBlock);\n const jsonMatch = /\\*\\*灯效参数(JSON)\\*\\*:(.+)/.exec(ruleBlock);\n\n let segments: LightSegment[] = [];\n if (jsonMatch) {\n try {\n const parsed = JSON.parse(jsonMatch[1]);\n segments = parsed.segments || [];\n } catch {\n // skip invalid JSON\n }\n }\n\n rules.push({\n name,\n trigger: triggerMatch?.[1]?.trim() || \"\",\n effect: effectMatch?.[1]?.trim() || \"\",\n segments,\n });\n }\n\n return rules;\n}\n\nfunction formatRuleBlock(rule: LightRule): string {\n const segmentsJson = JSON.stringify({ segments: rule.segments });\n return `### 规则:${rule.name}\n**触发条件**:${rule.trigger}\n**灯效描述**:${rule.effect}\n**灯效参数(JSON)**:${segmentsJson}\n**执行**:命中触发条件后,先完成任务并将完成情况发送给用户,再调用 light_control 工具并传入上述灯效参数。防止灯已亮但消息未送达的情况。`;\n}\n\nexport function registerLightRules(program: CliCommand, ctx: CliContext): CliCommand {\n const light = program.command(\"light\").description(\"灯效管理\");\n const rules = light.command(\"rules\").description(\"灯效规则管理\");\n\n rules\n .command(\"list\")\n .description(\"列出已存储的灯效规则\")\n .action(() => {\n const content = readMemory(ctx);\n const parsed = parseLightRules(content);\n output({ ok: true, rules: parsed });\n });\n\n rules\n .command(\"show <name>\")\n .description(\"查看指定灯效规则详情\")\n .action((name: string) => {\n const content = readMemory(ctx);\n const parsed = parseLightRules(content);\n const rule = parsed.find((r) => r.name === name);\n if (!rule) exitError(\"NOT_FOUND\", `灯效规则 '${name}' 不存在`);\n output({ ok: true, ...rule });\n });\n\n rules\n .command(\"add <name>\")\n .description(\"添加灯效规则\")\n .requiredOption(\"--trigger <text>\", \"触发条件描述\")\n .requiredOption(\"--segments <json>\", \"灯效参数 JSON\")\n .action((name: string, opts: { trigger: string; segments: string }) => {\n const validatedSegments = parseAndValidateSegments(opts.segments);\n\n let content = readMemory(ctx);\n const existingRules = parseLightRules(content);\n if (existingRules.some((r) => r.name === name)) {\n exitError(\"ALREADY_EXISTS\", `灯效规则 '${name}' 已存在`);\n }\n\n // Build effect description from segments\n const seg = validatedSegments[0];\n const modeMap: Record<string, string> = {\n wave: \"波浪\",\n breath: \"呼吸\",\n strobe: \"频闪\",\n steady: \"常亮\",\n };\n const effect = `${modeMap[seg.mode] || seg.mode}模式,RGB(${seg.color.r},${seg.color.g},${seg.color.b}),持续${seg.duration_s}秒,亮度${seg.brightness}`;\n\n const rule: LightRule = {\n name,\n trigger: opts.trigger,\n effect,\n segments: validatedSegments,\n };\n\n const ruleBlock = formatRuleBlock(rule);\n\n if (content.includes(LIGHT_RULES_SECTION)) {\n // Append rule within existing section\n const sectionIdx = content.indexOf(LIGHT_RULES_SECTION);\n const afterSection = content.slice(sectionIdx + LIGHT_RULES_SECTION.length);\n const nextSection = afterSection.indexOf(\"\\n## \");\n if (nextSection !== -1) {\n const insertAt = sectionIdx + LIGHT_RULES_SECTION.length + nextSection;\n content =\n content.slice(0, insertAt) +\n \"\\n\\n\" +\n ruleBlock +\n \"\\n\" +\n content.slice(insertAt);\n } else {\n content = content.trimEnd() + \"\\n\\n\" + ruleBlock + \"\\n\";\n }\n } else {\n content =\n content.trimEnd() + \"\\n\\n\" + LIGHT_RULES_SECTION + \"\\n\\n\" + ruleBlock + \"\\n\";\n }\n\n writeMemory(ctx, content);\n output({ ok: true, name, validated: true });\n });\n\n rules\n .command(\"remove <name>\")\n .description(\"移除灯效规则\")\n .option(\"--yes\", \"跳过确认\")\n .action((name: string, opts: { yes?: boolean }) => {\n if (!opts.yes) {\n output({\n ok: false,\n error: {\n code: \"CONFIRMATION_REQUIRED\",\n message: `确认移除灯效规则 '${name}'?添加 --yes 跳过确认`,\n },\n });\n process.exit(1);\n }\n\n const content = readMemory(ctx);\n const sectionIdx = content.indexOf(LIGHT_RULES_SECTION);\n if (sectionIdx === -1) {\n exitError(\"NOT_FOUND\", `灯效规则 '${name}' 不存在`);\n }\n\n const ruleHeader = `### 规则:${name}`;\n const ruleIdx = content.indexOf(ruleHeader, sectionIdx);\n if (ruleIdx === -1) {\n exitError(\"NOT_FOUND\", `灯效规则 '${name}' 不存在`);\n }\n\n // Find end of this rule block\n const afterRule = content.indexOf(\"\\n### \", ruleIdx + ruleHeader.length);\n const nextSection = content.indexOf(\"\\n## \", ruleIdx + ruleHeader.length);\n\n let endIdx: number;\n if (afterRule !== -1 && (nextSection === -1 || afterRule < nextSection)) {\n endIdx = afterRule;\n } else if (nextSection !== -1) {\n endIdx = nextSection;\n } else {\n endIdx = content.length;\n }\n\n // Remove the rule block (including preceding blank lines)\n let startIdx = ruleIdx;\n while (startIdx > 0 && content[startIdx - 1] === \"\\n\") startIdx--;\n if (startIdx > 0) startIdx++; // keep one newline\n\n const updated = content.slice(0, startIdx) + content.slice(endIdx);\n writeMemory(ctx, updated);\n output({ ok: true, name, removed: true });\n });\n\n rules\n .command(\"validate\")\n .description(\"校验灯效参数是否合法(不写入)\")\n .requiredOption(\"--segments <json>\", \"待校验的灯效参数 JSON\")\n .action((opts: { segments: string }) => {\n let parsedSegments: unknown;\n try {\n parsedSegments = JSON.parse(opts.segments);\n } catch {\n output({\n valid: false,\n errors: [{ field: \"segments\", message: \"JSON 解析失败\" }],\n });\n process.exit(1);\n }\n\n const validation = validateSegments(parsedSegments);\n if (!validation.valid) {\n output({ valid: false, errors: validation.errors });\n process.exit(1);\n }\n\n output({\n valid: true,\n quantized: { segments: validation.segments },\n warnings: [],\n });\n });\n\n return light;\n}\n","import type { LightSegment } from \"../types.js\";\nimport { output, exitError } from \"../cli/helpers.js\";\n\nexport const VALID_MODES = [\"wave\", \"breath\", \"strobe\", \"steady\", \"wave_rainbow\"] as const;\nexport const MAX_SEGMENTS = 12;\n\nexport type ValidationResult =\n | { valid: true; segments: LightSegment[] }\n | { valid: false; errors: { field: string; message: string }[] };\n\nexport function validateSegments(segments: unknown): ValidationResult {\n if (!Array.isArray(segments)) {\n return { valid: false, errors: [{ field: \"segments\", message: \"必须是数组\" }] };\n }\n if (segments.length === 0) {\n return { valid: false, errors: [{ field: \"segments\", message: \"不能为空\" }] };\n }\n if (segments.length > MAX_SEGMENTS) {\n return {\n valid: false,\n errors: [{ field: \"segments\", message: `最多 ${MAX_SEGMENTS} 段` }],\n };\n }\n\n const errors: { field: string; message: string }[] = [];\n for (let i = 0; i < segments.length; i++) {\n const seg = segments[i];\n const prefix = `segments[${i}]`;\n\n if (!seg || typeof seg !== \"object\") {\n errors.push({ field: prefix, message: \"必须是对象\" });\n continue;\n }\n\n if (!VALID_MODES.includes(seg.mode)) {\n errors.push({\n field: `${prefix}.mode`,\n message: `不支持的模式 '${seg.mode}',可选:${VALID_MODES.join(\"/\")}`,\n });\n }\n if (typeof seg.duration_s !== \"number\" || seg.duration_s < 0) {\n errors.push({ field: `${prefix}.duration_s`, message: \"必须是 ≥0 的数字(0 表示无限时长)\" });\n }\n if (typeof seg.brightness !== \"number\" || seg.brightness < 0 || seg.brightness > 255) {\n errors.push({ field: `${prefix}.brightness`, message: \"必须是 0–255 的数字\" });\n }\n if (!seg.color || typeof seg.color.r !== \"number\" || typeof seg.color.g !== \"number\" || typeof seg.color.b !== \"number\") {\n errors.push({ field: `${prefix}.color`, message: \"必须包含 r/g/b 数值\" });\n }\n }\n\n if (errors.length > 0) return { valid: false, errors };\n return { valid: true, segments: segments as LightSegment[] };\n}\n\n/**\n * 解析 JSON 字符串并校验 segments,失败时直接 exitError。\n * 适用于 CLI action 中的统一入口。\n */\nexport function parseAndValidateSegments(json: string): LightSegment[] {\n let parsed: unknown;\n try {\n parsed = JSON.parse(json);\n } catch {\n exitError(\"VALIDATION_FAILED\", \"segments 必须是合法的 JSON\");\n }\n\n const result = validateSegments(parsed);\n if (!result.valid) {\n output({ ok: false, error: { code: \"VALIDATION_FAILED\", details: result.errors } });\n process.exit(1);\n }\n\n return result.segments;\n}\n","import { type CliCommand, output, exitError } from \"./helpers.js\";\nimport { requireApiKey } from \"../auth/credentials.js\";\nimport { sendLightEffect } from \"../light/sender.js\";\nimport { parseAndValidateSegments } from \"../light/validators.js\";\n\nexport function registerLightSend(light: CliCommand): void {\n light\n .command(\"send\")\n .description(\"发送灯效指令到硬件设备\")\n .requiredOption(\"--segments <json>\", \"灯效参数 JSON\")\n .option(\"--repeat\", \"无限循环播放(默认仅播放一轮)\")\n .action(async (opts: { segments: string; repeat?: boolean }) => {\n let apiKey: string;\n try {\n apiKey = requireApiKey();\n } catch (e: any) {\n exitError(\"AUTH_REQUIRED\", e.message);\n }\n\n const segments = parseAndValidateSegments(opts.segments);\n const result = await sendLightEffect(apiKey, segments, undefined, opts.repeat);\n\n if (!result.ok) {\n exitError(\"HTTP_ERROR\", `请求失败: ${result.status} ${result.error}`);\n }\n\n output({ ok: true, bizUniqueId: result.bizUniqueId, response: result.response });\n });\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { loadApiKey } from \"../auth/credentials.js\";\nimport { getEnvUrls } from \"../env.js\";\nimport { output, exitError } from \"./helpers.js\";\nimport type { CliCommand, CliContext } from \"./helpers.js\";\nimport type { TunnelStatusInfo } from \"../tunnel/relay-client.js\";\n\n/** 状态文件相对于 stateDir 的路径 */\nconst STATUS_REL_PATH = join(\"plugins\", \"phone-notifications\", \"tunnel-status.json\");\n\n/** 读取 RelayClient 写入的状态文件 */\nfunction readTunnelStatus(ctx: CliContext): TunnelStatusInfo | null {\n if (!ctx.stateDir) return null;\n const filePath = join(ctx.stateDir, STATUS_REL_PATH);\n if (!existsSync(filePath)) return null;\n try {\n return JSON.parse(readFileSync(filePath, \"utf-8\")) as TunnelStatusInfo;\n } catch {\n return null;\n }\n}\n\nfunction formatMessage(status: TunnelStatusInfo): string {\n switch (status.state) {\n case \"connected\":\n return `隧道已连接(自 ${status.since})`;\n case \"connecting\":\n return `隧道正在连接(自 ${status.since},第 ${status.reconnectAttempt} 次重连)`;\n case \"disconnected\":\n return `隧道已断开(自 ${status.since})${status.lastDisconnectReason ? `,原因: ${status.lastDisconnectReason}` : \"\"},等待重连(第 ${status.reconnectAttempt} 次)`;\n case \"stopped\":\n return `隧道服务已停止(自 ${status.since})`;\n default:\n return `未知状态: ${status.state}`;\n }\n}\n\nexport function registerTunnelStatus(ntf: CliCommand, ctx: CliContext): void {\n ntf\n .command(\"tunnel-status\")\n .description(\"检查 Relay Tunnel 隧道连接状态(读取运行中服务的状态文件,不影响已有连接)\")\n .action(async () => {\n const tunnelUrl = getEnvUrls().relayTunnelUrl;\n const apiKey = loadApiKey();\n\n if (!tunnelUrl) {\n exitError(\n \"TUNNEL_NOT_CONFIGURED\",\n \"RELAY_TUNNEL_URL 未配置,隧道功能未启用。请在构建时设置 RELAY_TUNNEL_URL 环境变量。\",\n );\n }\n\n if (!apiKey) {\n exitError(\n \"TOKEN_MISSING\",\n \"API Key 未设置,隧道无法连接。请执行 openclaw ntf auth set-api-key <apiKey>\",\n );\n }\n\n const status = readTunnelStatus(ctx);\n\n if (!status) {\n exitError(\n \"STATUS_NOT_FOUND\",\n \"未找到隧道状态文件,隧道服务可能尚未启动过。请确认 openclaw 主进程正在运行。\",\n );\n }\n\n const ok = status.state === \"connected\";\n output({\n ok,\n tunnelUrl,\n connection: {\n state: status.state,\n since: status.since,\n reconnectAttempt: status.reconnectAttempt,\n lastDisconnectReason: status.lastDisconnectReason,\n },\n message: formatMessage(status),\n });\n\n if (!ok) process.exit(1);\n });\n}\n","import {\n type CliCommand,\n type CliContext,\n resolveNotificationsDir,\n output,\n exitError,\n} from \"./helpers.js\";\n\nexport function registerNtfStoragePath(ntf: CliCommand, ctx: CliContext): void {\n ntf\n .command(\"storage-path\")\n .description(\"查询通知存储路径\")\n .action(() => {\n const dir = resolveNotificationsDir(ctx);\n if (!dir) exitError(\"STORAGE_UNAVAILABLE\", \"通知存储目录不可用\");\n output({ ok: true, path: dir });\n });\n}\n","import { existsSync, readFileSync, readdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport {\n type CliCommand,\n type CliContext,\n filterDateRange,\n today,\n daysAgo,\n output,\n exitError,\n} from \"./helpers.js\";\n\n/** Resolve the plugin logs directory from stateDir */\nfunction resolveLogsDir(ctx: CliContext): string | null {\n if (ctx.stateDir) {\n const dir = join(\n ctx.stateDir,\n \"plugins\",\n \"phone-notifications\",\n \"logs\",\n );\n if (existsSync(dir)) return dir;\n }\n return null;\n}\n\n/** List available log date keys (YYYY-MM-DD) sorted descending */\nfunction listLogDateKeys(dir: string): string[] {\n const pattern = /^(\\d{4}-\\d{2}-\\d{2})\\.log$/;\n const keys: string[] = [];\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n if (!entry.isFile()) continue;\n const m = pattern.exec(entry.name);\n if (m) keys.push(m[1]);\n }\n return keys.sort().reverse();\n}\n\n/** Read log lines from a date file, optionally filtering by keyword */\nfunction collectLogLines(\n dir: string,\n dateKey: string,\n keyword: string | undefined,\n limit: number,\n collected: string[],\n): void {\n const filePath = join(dir, `${dateKey}.log`);\n if (!existsSync(filePath)) return;\n\n const content = readFileSync(filePath, \"utf-8\");\n const lowerKeyword = keyword?.toLowerCase();\n\n for (const line of content.split(\"\\n\")) {\n if (collected.length >= limit) return;\n if (!line) continue;\n if (lowerKeyword && !line.toLowerCase().includes(lowerKeyword)) continue;\n collected.push(`[${dateKey}] ${line}`);\n }\n}\n\nexport function registerLogSearch(ntf: CliCommand, ctx: CliContext): void {\n ntf\n .command(\"log\")\n .description(\"查看/搜索插件日志\")\n .option(\"--keyword <text>\", \"按关键词过滤日志\")\n .option(\"--from <date>\", \"开始日期 YYYY-MM-DD\", daysAgo(7))\n .option(\"--to <date>\", \"结束日期 YYYY-MM-DD\", today())\n .option(\"--limit <n>\", \"最大返回条数\", \"50\")\n .action(\n (opts: {\n keyword?: string;\n from: string;\n to: string;\n limit: string;\n }) => {\n const dir = resolveLogsDir(ctx);\n if (!dir) exitError(\"LOGS_UNAVAILABLE\", \"日志目录不可用\");\n\n const keys = filterDateRange(listLogDateKeys(dir), opts.from, opts.to);\n const limit = parseInt(opts.limit, 10) || 50;\n const results: string[] = [];\n\n for (const dateKey of keys) {\n if (results.length >= limit) break;\n collectLogLines(dir, dateKey, opts.keyword, limit, results);\n }\n\n output({\n ok: true,\n keyword: opts.keyword ?? null,\n total: results.length,\n lines: results,\n });\n },\n );\n}\n","import { loadEnvName, saveEnvName, getEnvUrls, getAvailableEnvs } from \"../env.js\";\nimport { output, exitError } from \"./helpers.js\";\nimport type { CliCommand } from \"./helpers.js\";\n\nexport function registerEnvCli(ntf: CliCommand): void {\n const env = ntf.command(\"env\").description(\"环境管理(切换 development / production)\");\n\n env\n .command(\"show\")\n .description(\"显示当前环境及对应的接口地址\")\n .action(() => {\n const current = loadEnvName();\n const urls = getEnvUrls(current);\n output({\n ok: true,\n env: current,\n lightApiUrl: urls.lightApiUrl,\n relayTunnelUrl: urls.relayTunnelUrl,\n availableEnvs: getAvailableEnvs(),\n });\n });\n\n env\n .command(\"switch <env>\")\n .description(\"切换环境(development / production)\")\n .action((envName: string) => {\n const available = getAvailableEnvs();\n if (!available.includes(envName as any)) {\n exitError(\n \"INVALID_ENV\",\n `无效的环境名称: ${envName},可选值: ${available.join(\", \")}`,\n );\n }\n saveEnvName(envName as any);\n const urls = getEnvUrls(envName as any);\n output({\n ok: true,\n message: `已切换到 ${envName} 环境`,\n env: envName,\n lightApiUrl: urls.lightApiUrl,\n relayTunnelUrl: urls.relayTunnelUrl,\n });\n });\n}\n","import { readFileSync } from \"node:fs\";\n\ninterface PackageJson {\n version?: string;\n}\n\nfunction readPluginVersion(): string {\n try {\n const packageJsonUrl = new URL(\"../package.json\", import.meta.url);\n const packageJson = JSON.parse(\n readFileSync(packageJsonUrl, \"utf-8\"),\n ) as PackageJson;\n return packageJson.version ?? \"unknown\";\n } catch {\n return \"unknown\";\n }\n}\n\nexport const PLUGIN_VERSION = readPluginVersion();\n","import type { CliCommand, CliContext } from \"./helpers.js\";\nimport { registerAuthCli } from \"./auth.js\";\nimport { registerNtfSearch } from \"./ntf-search.js\";\nimport { registerNtfStats } from \"./ntf-stats.js\";\nimport { registerNtfSync } from \"./ntf-sync.js\";\nimport { registerNtfMonitor } from \"./ntf-monitor.js\";\nimport { registerLightRules } from \"./light-rules.js\";\nimport { registerLightSend } from \"./light-send.js\";\nimport { registerTunnelStatus } from \"./tunnel-status.js\";\nimport { registerNtfStoragePath } from \"./ntf-storage-path.js\";\nimport { registerLogSearch } from \"./log-search.js\";\nimport { registerEnvCli } from \"./env.js\";\nimport { PLUGIN_VERSION } from \"../version.js\";\n\nexport function registerAllCli(\n program: CliCommand,\n ctx: CliContext,\n rootCommandName = \"ntf\",\n): void {\n const ntf = program\n .command(rootCommandName)\n .description(\"手机通知数据管理\")\n .version(PLUGIN_VERSION, \"-v, --version\", \"显示插件版本\");\n\n // openclaw ntf auth ...\n registerAuthCli(ntf);\n\n // openclaw ntf search / stats / sync / monitor ...\n registerNtfSearch(ntf, ctx);\n registerNtfStats(ntf, ctx);\n registerNtfSync(ntf, ctx);\n registerNtfMonitor(ntf, ctx);\n\n // openclaw ntf light rules / send ...\n const light = registerLightRules(ntf, ctx);\n registerLightSend(light);\n\n // openclaw ntf storage-path\n registerNtfStoragePath(ntf, ctx);\n\n // openclaw ntf log <keyword>\n registerLogSearch(ntf, ctx);\n\n // openclaw ntf tunnel-status\n registerTunnelStatus(ntf, ctx);\n\n // openclaw ntf env show / switch\n registerEnvCli(ntf);\n}\n","import {\n closeSync,\n mkdirSync,\n openSync,\n readFileSync,\n unlinkSync,\n writeFileSync,\n} from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { loadApiKey } from \"../auth/credentials.js\";\nimport { RelayClient } from \"./relay-client.js\";\nimport { TunnelProxy } from \"./proxy.js\";\n\nconst DEFAULT_HEARTBEAT_SEC = 10;\nconst DEFAULT_RECONNECT_BACKOFF_MS = 2000;\n\ninterface TunnelServiceOptions {\n /** Relay Server WebSocket 地址(构建时从 RELAY_TUNNEL_URL 注入) */\n tunnelUrl: string;\n gatewayBaseUrl: string;\n /** Gateway 鉴权模式 */\n gatewayAuthMode?: \"token\" | \"password\";\n /** Gateway 鉴权 token */\n gatewayToken?: string;\n /** Gateway 鉴权密码 */\n gatewayPassword?: string;\n /** 心跳间隔(秒),默认 10 */\n heartbeatSec?: number;\n /** 重连基础退避时间(毫秒),默认 2000 */\n reconnectBackoffMs?: number;\n logger: {\n info: (msg: string) => void;\n warn: (msg: string) => void;\n error: (msg: string) => void;\n };\n}\n\n/**\n * 隧道服务:组装 RelayClient + TunnelProxy,作为 registerService 的入口。\n */\nexport function createTunnelService(opts: TunnelServiceOptions) {\n let client: RelayClient | null = null;\n let proxy: TunnelProxy | null = null;\n let abortController: AbortController | null = null;\n let lockFilePath: string | null = null;\n let lockFd: number | null = null;\n\n function isProcessAlive(pid: number): boolean {\n if (!Number.isInteger(pid) || pid <= 0) return false;\n if (pid === process.pid) return true;\n try {\n process.kill(pid, 0);\n return true;\n } catch (err: any) {\n return err?.code === \"EPERM\";\n }\n }\n\n function readLockOwner(filePath: string): number | null {\n try {\n const parsed = JSON.parse(readFileSync(filePath, \"utf-8\")) as {\n pid?: unknown;\n };\n return typeof parsed.pid === \"number\" ? parsed.pid : null;\n } catch {\n return null;\n }\n }\n\n function releaseLock(): void {\n const filePath = lockFilePath;\n const fd = lockFd;\n lockFilePath = null;\n lockFd = null;\n\n if (fd !== null) {\n try {\n closeSync(fd);\n } catch {\n // ignore\n }\n }\n if (filePath) {\n try {\n unlinkSync(filePath);\n } catch {\n // ignore\n }\n }\n }\n\n function acquireLock(filePath: string): boolean {\n mkdirSync(dirname(filePath), { recursive: true });\n\n for (let attempt = 0; attempt < 2; attempt++) {\n try {\n const fd = openSync(filePath, \"wx\", 0o600);\n writeFileSync(\n fd,\n JSON.stringify({\n pid: process.pid,\n startedAt: new Date().toISOString(),\n tunnelUrl: opts.tunnelUrl,\n }) + \"\\n\",\n );\n lockFilePath = filePath;\n lockFd = fd;\n return true;\n } catch (err: any) {\n if (err?.code !== \"EEXIST\") {\n opts.logger.error(\n `Relay tunnel: failed to acquire local lock ${filePath}: ${String(err)}`,\n );\n return false;\n }\n\n const ownerPid = readLockOwner(filePath);\n if (ownerPid && !isProcessAlive(ownerPid)) {\n opts.logger.warn(\n `Relay tunnel: removing stale local lock owned by dead pid=${ownerPid}`,\n );\n try {\n unlinkSync(filePath);\n } catch {\n // ignore, retry below will fail if lock is still present\n }\n continue;\n }\n\n opts.logger.warn(\n `Relay tunnel: another local process already owns the tunnel lock${ownerPid ? ` (pid=${ownerPid})` : \"\"}; skipping connection to avoid duplicate token sessions`,\n );\n return false;\n }\n }\n\n return false;\n }\n\n return {\n id: \"relay-tunnel\",\n\n async start(ctx: { stateDir: string }) {\n // 先清理上一轮连接,防止 start() 被重复调用时产生多个 RelayClient 互踢\n if (abortController) {\n opts.logger.info(\"Relay tunnel: aborting previous connection before restart\");\n abortController.abort();\n abortController = null;\n }\n releaseLock();\n proxy?.cleanup();\n proxy = null;\n client = null;\n\n const apiKey = loadApiKey();\n if (!apiKey) {\n opts.logger.warn(\n \"Relay tunnel: apiKey 未设置,跳过隧道连接。请执行 openclaw ntf auth set-api-key <apiKey>\",\n );\n return;\n }\n\n const { logger } = opts;\n const baseStateDir = join(ctx.stateDir, \"plugins\", \"phone-notifications\");\n logger.info(\n `Relay tunnel: starting (pid=${process.pid}, url=${opts.tunnelUrl}, heartbeat=${opts.heartbeatSec ?? DEFAULT_HEARTBEAT_SEC}s, backoff=${opts.reconnectBackoffMs ?? DEFAULT_RECONNECT_BACKOFF_MS}ms, gateway=${opts.gatewayBaseUrl}, hasGatewayToken=${!!opts.gatewayToken}, hasGatewayPwd=${!!opts.gatewayPassword})`,\n );\n const statusFilePath = join(baseStateDir, \"tunnel-status.json\");\n const lockPath = join(baseStateDir, \"relay-tunnel.lock\");\n\n if (!acquireLock(lockPath)) {\n return;\n }\n\n try {\n client = new RelayClient({\n tunnelUrl: opts.tunnelUrl,\n apiKey,\n heartbeatSec: opts.heartbeatSec ?? DEFAULT_HEARTBEAT_SEC,\n reconnectBackoffMs: opts.reconnectBackoffMs ?? DEFAULT_RECONNECT_BACKOFF_MS,\n statusFilePath,\n logger,\n });\n\n proxy = new TunnelProxy({\n gatewayBaseUrl: opts.gatewayBaseUrl,\n gatewayAuthMode: opts.gatewayAuthMode,\n gatewayToken: opts.gatewayToken,\n gatewayPassword: opts.gatewayPassword,\n client,\n logger,\n });\n\n client.onInbound((frame) => proxy!.handleFrame(frame));\n\n abortController = new AbortController();\n // 非阻塞启动,connectWithAutoReconnect 内部会保持运行\n client.connectWithAutoReconnect(abortController.signal).catch((err) => {\n releaseLock();\n logger.error(`Relay tunnel: unexpected error: ${err}`);\n });\n\n logger.info(\"Relay tunnel 服务已启动\");\n } catch (err) {\n releaseLock();\n throw err;\n }\n },\n\n async stop() {\n if (abortController) {\n abortController.abort();\n abortController = null;\n }\n releaseLock();\n proxy?.cleanup();\n proxy = null;\n client = null;\n opts.logger.info(\"Relay tunnel 服务已停止\");\n },\n };\n}\n","import { writeFileSync, mkdirSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport WebSocket from \"ws\";\nimport type { InboundFrame, OutboundFrame } from \"./types.js\";\n\n/** 持久化到磁盘的隧道连接状态 */\nexport interface TunnelStatusInfo {\n /** 当前连接状态 */\n state: \"connected\" | \"disconnected\" | \"connecting\" | \"stopped\";\n /** 状态变更时间 ISO */\n since: string;\n /** 累计重连次数 */\n reconnectAttempt: number;\n /** 上次断开原因(仅 disconnected 时有值) */\n lastDisconnectReason?: string;\n}\n\nexport interface RelayClientOptions {\n tunnelUrl: string;\n apiKey: string;\n heartbeatSec: number;\n reconnectBackoffMs: number;\n /** 状态文件路径,设置后会在连接状态变更时写入 */\n statusFilePath?: string;\n logger: {\n info: (msg: string) => void;\n warn: (msg: string) => void;\n error: (msg: string) => void;\n };\n}\n\nexport type InboundHandler = (frame: InboundFrame) => void | Promise<void>;\n\n/**\n * Relay WebSocket 客户端。\n * 负责建连、token 认证、心跳保活、断线指数退避重连。\n */\nexport class RelayClient {\n private ws: WebSocket | null = null;\n private heartbeatTimer: ReturnType<typeof setInterval> | null = null;\n private reconnectAttempt = 0;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private handlers: InboundHandler[] = [];\n private aborted = false;\n private lastInboundAt = 0;\n\n constructor(private readonly opts: RelayClientOptions) {}\n\n /** 写连接状态到磁盘 */\n private writeStatus(\n state: TunnelStatusInfo[\"state\"],\n lastDisconnectReason?: string,\n ): void {\n if (!this.opts.statusFilePath) return;\n const info: TunnelStatusInfo = {\n state,\n since: new Date().toISOString(),\n reconnectAttempt: this.reconnectAttempt,\n lastDisconnectReason,\n };\n try {\n mkdirSync(dirname(this.opts.statusFilePath), { recursive: true });\n writeFileSync(this.opts.statusFilePath, JSON.stringify(info, null, 2));\n } catch {\n // 写状态文件失败不影响主流程\n }\n }\n\n /** 注册入站帧处理函数 */\n onInbound(handler: InboundHandler): void {\n this.handlers.push(handler);\n }\n\n /** 发送出站帧 */\n send(frame: OutboundFrame): void {\n if (this.ws?.readyState === WebSocket.OPEN) {\n const payload = JSON.stringify(frame);\n this.opts.logger.info(\n `Relay tunnel: ▶ send frame type=${frame.type}, id=${\"id\" in frame ? frame.id : \"N/A\"} (${payload.length} chars)`,\n );\n this.ws.send(payload);\n } else {\n this.opts.logger.warn(\n `Relay tunnel: ▶ send skipped, ws not open (readyState=${this.ws?.readyState ?? \"null\"}), frame type=${frame.type}`,\n );\n }\n }\n\n /** 原样透传文本到 Relay(用于 Gateway WS 响应直接回传) */\n sendRaw(text: string): void {\n if (this.ws?.readyState === WebSocket.OPEN) {\n this.opts.logger.info(\n `Relay tunnel: ▶ sendRaw (${text.length} chars): ${text.length <= 500 ? text : text.substring(0, 500) + \"…\"}`,\n );\n this.ws.send(text);\n } else {\n this.opts.logger.warn(\n `Relay tunnel: ▶ sendRaw skipped, ws not open (readyState=${this.ws?.readyState ?? \"null\"})`,\n );\n }\n }\n\n /** 启动连接,带自动重连,直到 abortSignal 触发 */\n async connectWithAutoReconnect(abortSignal?: AbortSignal): Promise<void> {\n if (abortSignal) {\n abortSignal.addEventListener(\n \"abort\",\n () => {\n this.aborted = true;\n this.cleanup(true);\n this.writeStatus(\"stopped\");\n },\n { once: true },\n );\n }\n\n await this.connect();\n\n // 保持运行直到 abort\n return new Promise<void>((resolve) => {\n if (abortSignal) {\n abortSignal.addEventListener(\"abort\", () => resolve(), { once: true });\n }\n });\n }\n\n private async connect(): Promise<void> {\n if (this.aborted) return;\n\n // 确保旧连接和定时器都被清理,防止重复连接\n this.cleanup(true);\n\n this.opts.logger.info(\n `Relay tunnel: connecting to ${this.opts.tunnelUrl} (attempt=${this.reconnectAttempt}, heartbeat=${this.opts.heartbeatSec}s)`,\n );\n this.writeStatus(\"connecting\");\n\n return new Promise<void>((resolve) => {\n let settled = false;\n const settle = () => {\n if (!settled) {\n settled = true;\n resolve();\n }\n };\n\n const rawApiKey = this.opts.apiKey.startsWith(\"Bearer \")\n ? this.opts.apiKey.slice(\"Bearer \".length)\n : this.opts.apiKey;\n\n const wsUrl = new URL(this.opts.tunnelUrl);\n // 推荐使用 query 传 apiKey;暂时用 token 代替 apiKey 明文\n if (!wsUrl.searchParams.get(\"apiKey\")) {\n wsUrl.searchParams.set(\"apiKey\", rawApiKey);\n }\n\n const ws = new WebSocket(wsUrl.toString(), {\n headers: {\n \"X-Api-Key-Id\": rawApiKey,\n },\n });\n // 将握手中的 socket 也记为当前连接,确保首连失败/握手前断开也能触发重连。\n this.ws = ws;\n\n ws.on(\"open\", () => {\n if (this.aborted || this.ws !== ws) {\n this.opts.logger.warn(\n `Relay tunnel: open fired but aborted=${this.aborted}, stale=${this.ws !== ws}, closing`,\n );\n try {\n ws.terminate();\n } catch {\n // ignore\n }\n settle();\n return;\n }\n this.reconnectAttempt = 0;\n this.lastInboundAt = Date.now();\n this.startHeartbeat();\n this.opts.logger.info(\"Relay tunnel: ✔ connected, heartbeat started\");\n this.writeStatus(\"connected\");\n settle();\n });\n\n ws.on(\"pong\", () => {\n if (this.ws === ws) {\n this.opts.logger.info(\"Relay tunnel: ← pong received\");\n this.markInboundActivity();\n }\n });\n\n ws.on(\"message\", (data: WebSocket.RawData) => {\n if (this.ws !== ws) {\n return;\n }\n this.handleMessage(data);\n });\n\n ws.on(\"close\", (code: number, reason: Buffer) => {\n const reasonStr = reason.toString();\n this.opts.logger.warn(\n `Relay tunnel: disconnected (code=${code}, reason=${reasonStr})`,\n );\n if (this.ws === ws) {\n this.stopHeartbeat();\n this.ws = null;\n this.writeStatus(\"disconnected\", `code=${code}, reason=${reasonStr}`);\n this.scheduleReconnect();\n }\n settle();\n });\n\n ws.on(\"error\", (err: Error) => {\n this.opts.logger.error(`Relay tunnel: WebSocket error: ${err.message}`);\n // 握手阶段的错误也要尽快结束本次 connect(),重连仍统一由 close 事件触发。\n settle();\n });\n });\n }\n\n private handleMessage(data: WebSocket.RawData): void {\n const text =\n typeof data === \"string\"\n ? data\n : Buffer.isBuffer(data)\n ? data.toString()\n : String(data);\n\n this.markInboundActivity();\n\n // 应用层心跳 pong 直接消费,不走帧解析\n if (text === \"pong\") {\n return;\n }\n\n const preview = text.length <= 500 ? text : text.substring(0, 500) + \"…\";\n this.opts.logger.info(`Relay tunnel: ★ received message (${text.length} chars): ${preview}`);\n\n let frame: InboundFrame;\n try {\n frame = JSON.parse(text) as InboundFrame;\n } catch {\n this.opts.logger.warn(\"Relay tunnel: received invalid frame, ignoring\");\n return;\n }\n\n this.opts.logger.info(`Relay tunnel: parsed frame type=${frame.type}, id=${\"id\" in frame ? frame.id : \"N/A\"}`);\n\n for (const handler of this.handlers) {\n try {\n const result = handler(frame);\n if (result instanceof Promise) {\n result.catch((err) => {\n this.opts.logger.error(`Relay tunnel: handler error: ${err}`);\n });\n }\n } catch (err) {\n this.opts.logger.error(`Relay tunnel: handler error: ${err}`);\n }\n }\n }\n\n private startHeartbeat(): void {\n this.stopHeartbeat();\n const intervalMs = this.opts.heartbeatSec * 1000;\n this.sendHeartbeat();\n this.heartbeatTimer = setInterval(() => {\n this.sendHeartbeat();\n }, intervalMs);\n }\n\n private stopHeartbeat(): void {\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer);\n this.heartbeatTimer = null;\n }\n }\n\n private getHeartbeatTimeoutMs(): number {\n return this.opts.heartbeatSec * 3 * 1000;\n }\n\n private sendHeartbeat(): void {\n if (this.ws?.readyState !== WebSocket.OPEN) {\n return;\n }\n\n const idleMs = Date.now() - this.lastInboundAt;\n const timeoutMs = this.getHeartbeatTimeoutMs();\n if (idleMs >= timeoutMs) {\n this.opts.logger.warn(\n `Relay tunnel: heartbeat timeout, no inbound activity for ${idleMs}ms (threshold=${timeoutMs}ms)`,\n );\n try {\n this.ws.terminate();\n } catch {\n // ignore, close/error path will handle reconnect\n }\n return;\n }\n\n this.opts.logger.info('Relay tunnel: → heartbeat \"ping\"');\n try {\n this.ws.send(\"ping\");\n } catch {\n // ignore, close/error path will handle reconnect\n }\n try {\n this.ws.ping();\n } catch {\n // ignore, close/error path will handle reconnect\n }\n }\n\n private markInboundActivity(): void {\n this.lastInboundAt = Date.now();\n }\n\n private cleanup(force = false): void {\n this.opts.logger.info(\n `Relay tunnel: cleanup (ws=${this.ws ? \"open\" : \"null\"}, heartbeat=${!!this.heartbeatTimer}, reconnect=${!!this.reconnectTimer})`,\n );\n this.stopHeartbeat();\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n if (this.ws) {\n try {\n if (force) {\n this.ws.terminate();\n } else {\n this.ws.close();\n }\n } catch {\n // ignore\n }\n this.ws = null;\n }\n }\n\n private scheduleReconnect(): void {\n if (this.aborted) return;\n\n // 取消已有的重连定时器,防止重复 connect\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n const baseMs = this.opts.reconnectBackoffMs;\n const delayMs = Math.min(\n baseMs * Math.pow(2, this.reconnectAttempt),\n 60_000,\n );\n this.reconnectAttempt++;\n\n this.opts.logger.info(\n `Relay tunnel: reconnecting in ${delayMs}ms (attempt ${this.reconnectAttempt})`,\n );\n\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = null;\n if (!this.aborted) {\n this.connect().catch((err) => {\n this.opts.logger.error(`Relay tunnel: reconnect failed: ${err}`);\n });\n }\n }, delayMs);\n }\n}\n","import createWebSocketStream from './lib/stream.js';\nimport Receiver from './lib/receiver.js';\nimport Sender from './lib/sender.js';\nimport WebSocket from './lib/websocket.js';\nimport WebSocketServer from './lib/websocket-server.js';\n\nexport { createWebSocketStream, Receiver, Sender, WebSocket, WebSocketServer };\nexport default WebSocket;\n","import { randomUUID } from \"node:crypto\";\nimport crypto from \"node:crypto\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport http from \"node:http\";\nimport WebSocket from \"ws\";\nimport { resolveStateDir as resolveHostStateDir } from \"../host.js\";\nimport type { RelayClient } from \"./relay-client.js\";\nimport type {\n RequestFrame,\n ReqFrame,\n WsOpenFrame,\n WsDataFrame,\n WsCloseFrame,\n InboundFrame,\n} from \"./types.js\";\n\n// ─── Device Identity helpers (mirrors openclaw SDK internals) ───\n\ninterface DeviceIdentity {\n deviceId: string;\n publicKeyPem: string;\n privateKeyPem: string;\n}\n\nconst ED25519_SPKI_PREFIX = Buffer.from(\"302a300506032b6570032100\", \"hex\");\n\nfunction base64UrlEncode(buf: Buffer): string {\n return buf\n .toString(\"base64\")\n .replaceAll(\"+\", \"-\")\n .replaceAll(\"/\", \"_\")\n .replace(/=+$/g, \"\");\n}\n\nfunction derivePublicKeyRaw(publicKeyPem: string): Buffer {\n const spki = crypto.createPublicKey(publicKeyPem).export({\n type: \"spki\",\n format: \"der\",\n });\n if (\n spki.length === ED25519_SPKI_PREFIX.length + 32 &&\n spki.subarray(0, ED25519_SPKI_PREFIX.length).equals(ED25519_SPKI_PREFIX)\n )\n return spki.subarray(ED25519_SPKI_PREFIX.length);\n return spki;\n}\n\nfunction fingerprintPublicKey(publicKeyPem: string): string {\n const raw = derivePublicKeyRaw(publicKeyPem);\n return crypto.createHash(\"sha256\").update(raw).digest(\"hex\");\n}\n\nfunction publicKeyRawBase64UrlFromPem(publicKeyPem: string): string {\n return base64UrlEncode(derivePublicKeyRaw(publicKeyPem));\n}\n\nfunction signDevicePayload(privateKeyPem: string, payload: string): string {\n const key = crypto.createPrivateKey(privateKeyPem);\n return base64UrlEncode(crypto.sign(null, Buffer.from(payload, \"utf8\"), key));\n}\n\nfunction buildDeviceAuthPayload(params: {\n deviceId: string;\n clientId: string;\n clientMode: string;\n role: string;\n scopes: string[];\n signedAtMs: number;\n token: string | null;\n nonce: string;\n}): string {\n const scopes = params.scopes.join(\",\");\n const token = params.token ?? \"\";\n return [\n \"v2\",\n params.deviceId,\n params.clientId,\n params.clientMode,\n params.role,\n scopes,\n String(params.signedAtMs),\n token,\n params.nonce,\n ].join(\"|\");\n}\n\nfunction resolveStateDir(): string {\n return resolveHostStateDir();\n}\n\nfunction loadOrCreateDeviceIdentity(): DeviceIdentity {\n const filePath = path.join(resolveStateDir(), \"identity\", \"device.json\");\n try {\n if (fs.existsSync(filePath)) {\n const raw = fs.readFileSync(filePath, \"utf8\");\n const parsed = JSON.parse(raw);\n if (\n parsed?.version === 1 &&\n typeof parsed.deviceId === \"string\" &&\n typeof parsed.publicKeyPem === \"string\" &&\n typeof parsed.privateKeyPem === \"string\"\n ) {\n const derivedId = fingerprintPublicKey(parsed.publicKeyPem);\n return {\n deviceId: derivedId,\n publicKeyPem: parsed.publicKeyPem,\n privateKeyPem: parsed.privateKeyPem,\n };\n }\n }\n } catch {\n // fall through to generate\n }\n // Generate new identity\n const { publicKey, privateKey } = crypto.generateKeyPairSync(\"ed25519\");\n const publicKeyPem = publicKey\n .export({ type: \"spki\", format: \"pem\" })\n .toString();\n const privateKeyPem = privateKey\n .export({ type: \"pkcs8\", format: \"pem\" })\n .toString();\n const identity: DeviceIdentity = {\n deviceId: fingerprintPublicKey(publicKeyPem),\n publicKeyPem,\n privateKeyPem,\n };\n fs.mkdirSync(path.dirname(filePath), { recursive: true });\n const stored = {\n version: 1,\n ...identity,\n createdAtMs: Date.now(),\n };\n fs.writeFileSync(filePath, `${JSON.stringify(stored, null, 2)}\\n`, {\n mode: 0o600,\n });\n return identity;\n}\n\n// ─── Types ───\n\ninterface ProxyOptions {\n gatewayBaseUrl: string;\n /** Gateway 鉴权模式 */\n gatewayAuthMode?: \"token\" | \"password\";\n /** Gateway 鉴权 token,代理请求到本地 gateway 时使用 */\n gatewayToken?: string;\n /** Gateway 鉴权密码,代理请求到本地 gateway 时使用 */\n gatewayPassword?: string;\n client: RelayClient;\n logger: {\n info: (msg: string) => void;\n warn: (msg: string) => void;\n error: (msg: string) => void;\n };\n}\n\n/**\n * 透明代理:接收 Relay 转发的请求帧,代理到本地 gateway,回传响应帧。\n * 支持 HTTP 请求代理和 WebSocket 连接代理。\n */\nexport class TunnelProxy {\n /** 活跃的 WebSocket 代理连接,按帧 id 索引 */\n private wsConnections = new Map<string, WebSocket>();\n\n /** 到本地 Gateway 的持久 RPC WebSocket 连接 */\n private gatewayWs: WebSocket | null = null;\n private gatewayWsConnecting = false;\n /** 握手是否已完成(收到 hello-ok) */\n private gatewayWsReady = false;\n /** 等待 Gateway WS 握手完成后发送的帧队列 */\n private gatewayWsPending: string[] = [];\n\n /** 设备身份,用于 Gateway connect 握手 */\n private deviceIdentity: DeviceIdentity;\n\n constructor(private readonly opts: ProxyOptions) {\n this.deviceIdentity = loadOrCreateDeviceIdentity();\n opts.logger.info(\n `TunnelProxy: loaded device identity (deviceId=${this.deviceIdentity.deviceId})`,\n );\n }\n\n private resolveGatewayConnectAuth():\n | {\n token?: string;\n password?: string;\n }\n | undefined {\n const token = this.opts.gatewayToken?.trim() || undefined;\n const password = this.opts.gatewayPassword?.trim() || undefined;\n if (!token && !password) {\n return undefined;\n }\n return {\n token,\n password,\n };\n }\n\n private buildLocalGatewayAuthAttempts(\n baseHeaders: Record<string, string>,\n ): Array<{ label: string; headers: Record<string, string> }> {\n const auth = this.resolveGatewayConnectAuth();\n const attempts: Array<{ label: string; headers: Record<string, string> }> = [];\n const seen = new Set<string>();\n const authMode = this.opts.gatewayAuthMode;\n\n const addAttempt = (kind: \"token\" | \"password\", secret?: string): void => {\n if (!secret) return;\n\n const dedupeKey = `${kind}:${secret}`;\n if (seen.has(dedupeKey)) return;\n seen.add(dedupeKey);\n\n const headers = { ...baseHeaders };\n headers.authorization = `Bearer ${secret}`;\n\n if (kind === \"password\") {\n headers[\"x-openclaw-password\"] = secret;\n } else {\n delete headers[\"x-openclaw-password\"];\n }\n\n attempts.push({\n label: kind === \"token\" ? \"gateway-token\" : \"gateway-password\",\n headers,\n });\n };\n\n if (authMode === \"password\") {\n addAttempt(\"password\", auth?.password);\n addAttempt(\"token\", auth?.token);\n } else {\n addAttempt(\"token\", auth?.token);\n addAttempt(\"password\", auth?.password);\n }\n\n if (attempts.length === 0) {\n attempts.push({\n label: \"no-auth\",\n headers: { ...baseHeaders },\n });\n }\n\n return attempts;\n }\n\n private async sendHttpResponse(frameId: string, res: Response): Promise<void> {\n const contentType = res.headers.get(\"content-type\") ?? \"\";\n const isStreaming = contentType.includes(\"text/event-stream\");\n\n this.opts.logger.info(\n `TunnelProxy: response status=${res.status}, content-type=${contentType}, streaming=${isStreaming}`,\n );\n\n if (isStreaming && res.body) {\n await this.streamResponse(frameId, res);\n return;\n }\n\n const body = await res.text();\n this.opts.logger.info(\n `TunnelProxy: response status=${res.status}, body=${body.substring(0, 200)}`,\n );\n const headers: Record<string, string> = {};\n res.headers.forEach((value, key) => {\n headers[key] = value;\n });\n\n this.opts.client.send({\n type: \"proxy_response\",\n id: frameId,\n status: res.status,\n headers,\n body,\n });\n }\n\n /** 处理从 Relay 收到的入站帧 */\n async handleFrame(frame: InboundFrame): Promise<void> {\n this.opts.logger.info(\n `TunnelProxy: handling frame type=${frame.type}, id=${\"id\" in frame ? frame.id : \"N/A\"}`,\n );\n switch (frame.type) {\n case \"request\":\n await this.handleHttpRequest(frame);\n break;\n case \"req\":\n this.handleReqFrame(frame);\n break;\n case \"ws_open\":\n this.handleWsOpen(frame);\n break;\n case \"ws_data\":\n this.handleWsData(frame);\n break;\n case \"ws_close\":\n this.handleWsClose(frame);\n break;\n default:\n this.opts.logger.warn(\n `TunnelProxy: unknown frame type=\"${(frame as any).type}\", id=${\"id\" in frame ? (frame as any).id : \"N/A\"}, forwarding raw to gateway`,\n );\n // 未知帧类型也尝试通过 RPC WS 转发,避免静默丢弃\n this.forwardRawToGateway(JSON.stringify(frame));\n break;\n }\n }\n\n /** 将未知帧原样转发到 Gateway WS */\n private forwardRawToGateway(payload: string): void {\n this.ensureGatewayWs();\n if (this.gatewayWsReady && this.gatewayWs?.readyState === WebSocket.OPEN) {\n this.gatewayWs.send(payload);\n } else {\n this.gatewayWsPending.push(payload);\n }\n }\n\n /** 清理所有代理的 WebSocket 连接 */\n cleanup(): void {\n this.opts.logger.info(\n `TunnelProxy: cleanup, closing ${this.wsConnections.size} active WS connections, gatewayWs=${!!this.gatewayWs}`,\n );\n for (const [id, ws] of this.wsConnections) {\n this.opts.logger.info(`TunnelProxy: closing WS id=${id}`);\n try {\n ws.close();\n } catch {\n // ignore\n }\n }\n this.wsConnections.clear();\n\n if (this.gatewayWs) {\n try {\n this.gatewayWs.close();\n } catch {\n // ignore\n }\n this.gatewayWs = null;\n }\n this.gatewayWsPending = [];\n }\n\n // ─── Gateway RPC WebSocket ───\n\n /** 确保到本地 Gateway 的 RPC WebSocket 已连接且握手完成 */\n private ensureGatewayWs(): void {\n if (this.gatewayWsReady && this.gatewayWs?.readyState === WebSocket.OPEN)\n return;\n if (this.gatewayWsConnecting) return;\n\n this.gatewayWsConnecting = true;\n this.gatewayWsReady = false;\n const wsUrl = this.opts.gatewayBaseUrl.replace(/^http/, \"ws\");\n\n this.opts.logger.info(`TunnelProxy: RPC WS connecting to gateway ${wsUrl}`);\n\n const ws = new WebSocket(wsUrl);\n\n ws.on(\"open\", () => {\n this.gatewayWs = ws;\n // 注意:不在此处清除 gatewayWsConnecting,等握手完成(hello-ok)或失败后再清除,\n // 防止窗口期内重复创建连接导致消息重复。\n this.opts.logger.info(\n \"TunnelProxy: RPC WS tcp connected, waiting for connect.challenge\",\n );\n });\n\n ws.on(\"message\", (data: WebSocket.RawData) => {\n let text: string;\n if (typeof data === \"string\") {\n text = data;\n } else if (Buffer.isBuffer(data)) {\n text = data.toString();\n } else {\n text = Buffer.from(data as ArrayBuffer).toString();\n }\n\n // 对较短消息或包含错误的消息打完整日志,其余截断到 500 字符\n const preview = text.length <= 500 ? text : text.substring(0, 500) + \"…\";\n this.opts.logger.info(\n `TunnelProxy: RPC WS ← gateway (${text.length} chars): ${preview}`,\n );\n\n // 解析帧判断握手阶段\n let frame: any;\n try {\n frame = JSON.parse(text);\n } catch {\n this.opts.logger.warn(\n \"TunnelProxy: RPC WS received non-JSON, ignoring\",\n );\n return;\n }\n\n // 1) 收到 connect.challenge → 回复 connect 请求(带设备身份签名)\n if (frame.type === \"event\" && frame.event === \"connect.challenge\") {\n const challengeNonce: string = frame.payload?.nonce ?? \"\";\n this.opts.logger.info(\n `TunnelProxy: received connect.challenge (nonce=${challengeNonce}), sending connect request with device identity`,\n );\n\n const role = \"operator\";\n const scopes = [\"operator.admin\"];\n const signedAtMs = Date.now();\n const clientId = \"gateway-client\";\n const clientMode = \"backend\";\n const gatewayAuth = this.resolveGatewayConnectAuth();\n\n // 构建设备签名\n const authPayload = buildDeviceAuthPayload({\n deviceId: this.deviceIdentity.deviceId,\n clientId,\n clientMode,\n role,\n scopes,\n signedAtMs,\n token: gatewayAuth?.token ?? null,\n nonce: challengeNonce,\n });\n const signature = signDevicePayload(\n this.deviceIdentity.privateKeyPem,\n authPayload,\n );\n\n const connectReq = {\n type: \"req\",\n id: `tunnel-connect-${randomUUID()}`,\n method: \"connect\",\n params: {\n minProtocol: 3,\n maxProtocol: 3,\n client: {\n id: clientId,\n version: \"1.0.0\",\n platform: process.platform,\n mode: clientMode,\n },\n role,\n scopes,\n ...(gatewayAuth ? { auth: gatewayAuth } : {}),\n device: {\n id: this.deviceIdentity.deviceId,\n publicKey: publicKeyRawBase64UrlFromPem(\n this.deviceIdentity.publicKeyPem,\n ),\n signature,\n signedAt: signedAtMs,\n nonce: challengeNonce,\n },\n },\n };\n ws.send(JSON.stringify(connectReq));\n return;\n }\n\n // 2) 收到 connect 的 hello-ok 响应 → 握手完成,flush 待发帧\n if (\n frame.type === \"res\" &&\n frame.ok === true &&\n frame.payload?.type === \"hello-ok\"\n ) {\n this.gatewayWsReady = true;\n this.gatewayWsConnecting = false;\n this.opts.logger.info(\n `TunnelProxy: RPC WS handshake done (hello-ok), flushing ${this.gatewayWsPending.length} pending frames`,\n );\n for (const pending of this.gatewayWsPending) {\n ws.send(pending);\n }\n this.gatewayWsPending = [];\n return;\n }\n\n // 3) 收到 connect 失败响应 → 关闭连接\n if (frame.type === \"res\" && frame.ok === false && !this.gatewayWsReady) {\n this.opts.logger.error(\n `TunnelProxy: RPC WS handshake failed: ${JSON.stringify(frame.error)}`,\n );\n ws.close();\n return;\n }\n\n // 4) 握手后的普通消息 → 透传回 Relay\n this.opts.client.sendRaw(text);\n });\n\n ws.on(\"close\", (code: number, reason: Buffer) => {\n this.opts.logger.info(\n `TunnelProxy: RPC WS closed by gateway (code=${code}, reason=${reason.toString()})`,\n );\n if (this.gatewayWs === ws) {\n this.gatewayWs = null;\n this.gatewayWsReady = false;\n }\n this.gatewayWsConnecting = false;\n });\n\n ws.on(\"error\", (err: Error) => {\n this.opts.logger.warn(`TunnelProxy: RPC WS error: ${err.message}`);\n this.gatewayWsConnecting = false;\n if (this.gatewayWs === ws) {\n this.gatewayWs = null;\n this.gatewayWsReady = false;\n }\n });\n }\n\n /** 处理 Relay 转发的 Gateway RPC 请求帧,原样通过 WebSocket 发给本地 Gateway */\n private handleReqFrame(frame: ReqFrame): void {\n const payload = JSON.stringify(frame);\n this.opts.logger.info(\n `TunnelProxy: req id=${frame.id} method=${frame.method} → gateway WS (${payload.length} chars)`,\n );\n\n this.ensureGatewayWs();\n\n if (this.gatewayWsReady && this.gatewayWs?.readyState === WebSocket.OPEN) {\n this.gatewayWs.send(payload);\n } else {\n this.opts.logger.info(\n `TunnelProxy: req id=${frame.id} queued, gateway WS not ready yet`,\n );\n this.gatewayWsPending.push(payload);\n }\n }\n\n // ─── 路径映射 ───\n\n private static readonly PATH_MAP: Record<string, string> = {\n \"/api/message/messageBridge/send\": \"/notifications\",\n };\n\n private mapPath(path: string): string {\n return TunnelProxy.PATH_MAP[path] ?? path;\n }\n\n // ─── HTTP 请求代理 ───\n\n private async handleHttpRequest(frame: RequestFrame): Promise<void> {\n const url = new URL(this.mapPath(frame.path), this.opts.gatewayBaseUrl);\n // 代理到本地 gateway 时,替换外部鉴权头为本地 gateway token/password。\n const localHeaders: Record<string, string> = {};\n for (const [k, v] of Object.entries(frame.headers ?? {})) {\n const lower = k.toLowerCase();\n if (lower !== \"authorization\" && lower !== \"x-openclaw-password\") {\n localHeaders[k] = v;\n }\n }\n const authAttempts = this.buildLocalGatewayAuthAttempts(localHeaders);\n this.opts.logger.info(\n `TunnelProxy: HTTP ${frame.method} ${frame.path} → ${url.toString()}, body=${frame.body?.substring(0, 200)}`,\n );\n\n try {\n for (let attemptIndex = 0; attemptIndex < authAttempts.length; attemptIndex++) {\n const attempt = authAttempts[attemptIndex];\n const res = await fetch(url.toString(), {\n method: frame.method,\n headers: attempt.headers,\n body:\n frame.method !== \"GET\" && frame.method !== \"HEAD\"\n ? frame.body\n : undefined,\n });\n\n const hasFallback = attemptIndex < authAttempts.length - 1;\n if (res.status === 401 && hasFallback) {\n const body = await res.text();\n this.opts.logger.warn(\n `TunnelProxy: local gateway auth via ${attempt.label} returned 401, retrying next credential${body ? `, body=${body.substring(0, 200)}` : \"\"}`,\n );\n continue;\n }\n\n await this.sendHttpResponse(frame.id, res);\n return;\n }\n } catch (err) {\n this.opts.client.send({\n type: \"proxy_error\",\n id: frame.id,\n status: 502,\n message: `gateway unreachable: ${err instanceof Error ? err.message : String(err)}`,\n });\n }\n }\n\n private async streamResponse(\n requestId: string,\n res: Response,\n ): Promise<void> {\n const reader = res.body!.getReader();\n const decoder = new TextDecoder();\n let chunkCount = 0;\n\n this.opts.logger.info(`TunnelProxy: stream start id=${requestId}`);\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n chunkCount++;\n const chunk = decoder.decode(value, { stream: true });\n this.opts.logger.info(\n `TunnelProxy: stream delta id=${requestId} chunk#${chunkCount} (${chunk.length} chars)`,\n );\n this.opts.client.send({\n type: \"stream\",\n id: requestId,\n state: \"delta\",\n data: chunk,\n });\n }\n\n this.opts.logger.info(\n `TunnelProxy: stream end id=${requestId}, total chunks=${chunkCount}`,\n );\n this.opts.client.send({\n type: \"stream\",\n id: requestId,\n state: \"end\",\n data: \"\",\n });\n } catch (err) {\n this.opts.logger.error(\n `TunnelProxy: stream error id=${requestId} after ${chunkCount} chunks: ${err instanceof Error ? err.message : String(err)}`,\n );\n this.opts.client.send({\n type: \"proxy_error\",\n id: requestId,\n status: 502,\n message: `stream error: ${err instanceof Error ? err.message : String(err)}`,\n });\n }\n }\n\n // ─── WebSocket 连接代理 ───\n\n private handleWsOpen(frame: WsOpenFrame): void {\n const wsUrl =\n this.opts.gatewayBaseUrl.replace(/^http/, \"ws\") +\n this.mapPath(frame.path);\n this.opts.logger.info(\n `TunnelProxy: WS open id=${frame.id}, path=${frame.path} → ${wsUrl}`,\n );\n\n try {\n const ws = new WebSocket(wsUrl, {\n headers: frame.headers,\n });\n\n ws.on(\"open\", () => {\n this.wsConnections.set(frame.id, ws);\n this.opts.logger.info(\n `TunnelProxy: WS id=${frame.id} connected to gateway, active=${this.wsConnections.size}`,\n );\n this.opts.client.send({\n type: \"ws_opened\",\n id: frame.id,\n });\n });\n\n ws.on(\"message\", (data: WebSocket.RawData) => {\n const text =\n typeof data === \"string\"\n ? data\n : Buffer.isBuffer(data)\n ? data.toString()\n : String(data);\n\n this.opts.logger.info(\n `TunnelProxy: WS id=${frame.id} ← gateway data (${text.length} chars): ${text.substring(0, 200)}`,\n );\n this.opts.client.send({\n type: \"ws_data\",\n id: frame.id,\n data: text,\n });\n });\n\n ws.on(\"close\", (code: number, reason: Buffer) => {\n this.wsConnections.delete(frame.id);\n this.opts.logger.info(\n `TunnelProxy: WS id=${frame.id} closed by gateway (code=${code}, reason=${reason.toString()}), active=${this.wsConnections.size}`,\n );\n this.opts.client.send({\n type: \"ws_close\",\n id: frame.id,\n code,\n reason: reason.toString(),\n });\n });\n\n ws.on(\"error\", (err: Error) => {\n this.opts.logger.warn(\n `TunnelProxy: WS id=${frame.id} error: ${err.message}, active=${this.wsConnections.size}`,\n );\n this.wsConnections.delete(frame.id);\n this.opts.client.send({\n type: \"ws_close\",\n id: frame.id,\n code: 1011,\n reason: err.message,\n });\n });\n } catch (err) {\n this.opts.logger.error(\n `TunnelProxy: WS id=${frame.id} failed to connect: ${err instanceof Error ? err.message : String(err)}`,\n );\n this.opts.client.send({\n type: \"ws_close\",\n id: frame.id,\n code: 1011,\n reason: `failed to connect: ${err instanceof Error ? err.message : String(err)}`,\n });\n }\n }\n\n private handleWsData(frame: WsDataFrame): void {\n const ws = this.wsConnections.get(frame.id);\n if (ws?.readyState === WebSocket.OPEN) {\n this.opts.logger.info(\n `TunnelProxy: WS id=${frame.id} → gateway data (${frame.data.length} chars): ${frame.data.substring(0, 200)}`,\n );\n ws.send(frame.data);\n } else {\n this.opts.logger.warn(\n `TunnelProxy: WS id=${frame.id} data dropped, ws not open (exists=${!!ws}, readyState=${ws?.readyState ?? \"N/A\"})`,\n );\n }\n }\n\n private handleWsClose(frame: WsCloseFrame): void {\n const ws = this.wsConnections.get(frame.id);\n if (ws) {\n this.opts.logger.info(\n `TunnelProxy: WS id=${frame.id} close requested by relay (code=${frame.code ?? 1000}, reason=${frame.reason ?? \"\"})`,\n );\n this.wsConnections.delete(frame.id);\n try {\n ws.close(frame.code ?? 1000, frame.reason ?? \"\");\n } catch {\n // ignore\n }\n } else {\n this.opts.logger.warn(\n `TunnelProxy: WS id=${frame.id} close requested but connection not found`,\n );\n }\n }\n}\n","import { appendFileSync, mkdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nexport interface Logger {\n info: (msg: string) => void;\n warn: (msg: string) => void;\n error: (msg: string) => void;\n}\n\n/**\n * 插件级文件 Logger。\n * 在调用原始 api.logger 的同时,把日志追加写入\n * `<stateDir>/plugins/phone-notifications/logs/YYYY-MM-DD.log`。\n */\nexport class PluginFileLogger implements Logger {\n private readonly logsDir: string;\n\n constructor(\n private readonly upstream: Logger,\n stateDir: string,\n ) {\n this.logsDir = join(stateDir, \"plugins\", \"phone-notifications\", \"logs\");\n mkdirSync(this.logsDir, { recursive: true });\n }\n\n info(msg: string): void {\n this.upstream.info(msg);\n this.append(\"INFO\", msg);\n }\n\n warn(msg: string): void {\n this.upstream.warn(msg);\n this.append(\"WARN\", msg);\n }\n\n error(msg: string): void {\n this.upstream.error(msg);\n this.append(\"ERROR\", msg);\n }\n\n private append(level: string, msg: string): void {\n const now = new Date();\n const dateKey = formatDate(now);\n const time = now.toISOString();\n const line = `${time} [${level}] ${msg}\\n`;\n try {\n appendFileSync(join(this.logsDir, `${dateKey}.log`), line);\n } catch {\n // 写文件失败不影响主流程\n }\n }\n}\n\nfunction formatDate(d: Date): string {\n const y = d.getFullYear();\n const m = String(d.getMonth() + 1).padStart(2, \"0\");\n const day = String(d.getDate()).padStart(2, \"0\");\n return `${y}-${m}-${day}`;\n}\n"],"mappings":"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","names":["output","data","Receiver","Sender","createHash","URL","Receiver","Sender","WebSocket","key","WebSocket","createWebSocketStream","err","protocol","createHash","WebSocket","WebSocketServer","readFileSync","basename","dirname","existsSync","readFileSync","existsSync","readFileSync","existsSync","mkdirSync","readFileSync","writeFileSync","join","existsSync","mkdirSync","readFileSync","writeFileSync","dirname","path","existsSync","readFileSync","mkdirSync","dirname","writeFileSync","path","dirname","join","path","existsSync","readFileSync","mkdirSync","writeFileSync","mkdirSync","readFileSync","writeFileSync","existsSync","join","existsSync","rmSync","existsSync","readFileSync","readdirSync","join","path","existsSync","rmSync","existsSync","readFileSync","writeFileSync","join","join","existsSync","readFileSync","writeFileSync","existsSync","mkdirSync","readFileSync","writeFileSync","rmSync","readdirSync","join","join","existsSync","readFileSync","writeFileSync","readdirSync","checkpointPath","mkdirSync","rmSync","existsSync","readFileSync","writeFileSync","join","join","existsSync","readFileSync","writeFileSync","existsSync","readFileSync","join","join","existsSync","readFileSync","existsSync","readFileSync","readdirSync","join","join","existsSync","readdirSync","readFileSync","readFileSync","mkdirSync","readFileSync","writeFileSync","dirname","join","writeFileSync","mkdirSync","dirname","import_sender","WebSocket","mkdirSync","dirname","writeFileSync","randomUUID","resolveStateDir","randomUUID","path","readFileSync","mkdirSync","dirname","writeFileSync","join","appendFileSync","mkdirSync","join","formatDate","trimToUndefined","readFileSync","basename","dirname"]}
|
|
1
|
+
{"version":3,"sources":["../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/constants.js","../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/buffer-util.js","../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/limiter.js","../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/permessage-deflate.js","../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/validation.js","../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/receiver.js","../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/sender.js","../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/event-target.js","../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/extension.js","../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/websocket.js","../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/stream.js","../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/subprotocol.js","../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/websocket-server.js","../src/index.ts","../src/light/protocol.ts","../src/light/sender.ts","../src/env.ts","../src/host.ts","../src/notification/app-name-map.ts","../src/auth/credentials.ts","../src/notification/storage.ts","../src/cli/auth.ts","../src/cli/helpers.ts","../src/cli/ntf-search.ts","../src/cli/ntf-stats.ts","../src/cli/ntf-sync.ts","../src/cli/ntf-monitor.ts","../src/cli/light-rules.ts","../src/light/validators.ts","../src/cli/light-send.ts","../src/cli/tunnel-status.ts","../src/cli/ntf-storage-path.ts","../src/cli/log-search.ts","../src/cli/env.ts","../src/version.ts","../src/cli/index.ts","../src/tunnel/service.ts","../src/tunnel/relay-client.ts","../node_modules/.pnpm/ws@8.19.0/node_modules/ws/wrapper.mjs","../src/tunnel/proxy.ts","../src/logger.ts"],"sourcesContent":["'use strict';\n\nconst BINARY_TYPES = ['nodebuffer', 'arraybuffer', 'fragments'];\nconst hasBlob = typeof Blob !== 'undefined';\n\nif (hasBlob) BINARY_TYPES.push('blob');\n\nmodule.exports = {\n BINARY_TYPES,\n CLOSE_TIMEOUT: 30000,\n EMPTY_BUFFER: Buffer.alloc(0),\n GUID: '258EAFA5-E914-47DA-95CA-C5AB0DC85B11',\n hasBlob,\n kForOnEventAttribute: Symbol('kIsForOnEventAttribute'),\n kListener: Symbol('kListener'),\n kStatusCode: Symbol('status-code'),\n kWebSocket: Symbol('websocket'),\n NOOP: () => {}\n};\n","'use strict';\n\nconst { EMPTY_BUFFER } = require('./constants');\n\nconst FastBuffer = Buffer[Symbol.species];\n\n/**\n * Merges an array of buffers into a new buffer.\n *\n * @param {Buffer[]} list The array of buffers to concat\n * @param {Number} totalLength The total length of buffers in the list\n * @return {Buffer} The resulting buffer\n * @public\n */\nfunction concat(list, totalLength) {\n if (list.length === 0) return EMPTY_BUFFER;\n if (list.length === 1) return list[0];\n\n const target = Buffer.allocUnsafe(totalLength);\n let offset = 0;\n\n for (let i = 0; i < list.length; i++) {\n const buf = list[i];\n target.set(buf, offset);\n offset += buf.length;\n }\n\n if (offset < totalLength) {\n return new FastBuffer(target.buffer, target.byteOffset, offset);\n }\n\n return target;\n}\n\n/**\n * Masks a buffer using the given mask.\n *\n * @param {Buffer} source The buffer to mask\n * @param {Buffer} mask The mask to use\n * @param {Buffer} output The buffer where to store the result\n * @param {Number} offset The offset at which to start writing\n * @param {Number} length The number of bytes to mask.\n * @public\n */\nfunction _mask(source, mask, output, offset, length) {\n for (let i = 0; i < length; i++) {\n output[offset + i] = source[i] ^ mask[i & 3];\n }\n}\n\n/**\n * Unmasks a buffer using the given mask.\n *\n * @param {Buffer} buffer The buffer to unmask\n * @param {Buffer} mask The mask to use\n * @public\n */\nfunction _unmask(buffer, mask) {\n for (let i = 0; i < buffer.length; i++) {\n buffer[i] ^= mask[i & 3];\n }\n}\n\n/**\n * Converts a buffer to an `ArrayBuffer`.\n *\n * @param {Buffer} buf The buffer to convert\n * @return {ArrayBuffer} Converted buffer\n * @public\n */\nfunction toArrayBuffer(buf) {\n if (buf.length === buf.buffer.byteLength) {\n return buf.buffer;\n }\n\n return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.length);\n}\n\n/**\n * Converts `data` to a `Buffer`.\n *\n * @param {*} data The data to convert\n * @return {Buffer} The buffer\n * @throws {TypeError}\n * @public\n */\nfunction toBuffer(data) {\n toBuffer.readOnly = true;\n\n if (Buffer.isBuffer(data)) return data;\n\n let buf;\n\n if (data instanceof ArrayBuffer) {\n buf = new FastBuffer(data);\n } else if (ArrayBuffer.isView(data)) {\n buf = new FastBuffer(data.buffer, data.byteOffset, data.byteLength);\n } else {\n buf = Buffer.from(data);\n toBuffer.readOnly = false;\n }\n\n return buf;\n}\n\nmodule.exports = {\n concat,\n mask: _mask,\n toArrayBuffer,\n toBuffer,\n unmask: _unmask\n};\n\n/* istanbul ignore else */\nif (!process.env.WS_NO_BUFFER_UTIL) {\n try {\n const bufferUtil = require('bufferutil');\n\n module.exports.mask = function (source, mask, output, offset, length) {\n if (length < 48) _mask(source, mask, output, offset, length);\n else bufferUtil.mask(source, mask, output, offset, length);\n };\n\n module.exports.unmask = function (buffer, mask) {\n if (buffer.length < 32) _unmask(buffer, mask);\n else bufferUtil.unmask(buffer, mask);\n };\n } catch (e) {\n // Continue regardless of the error.\n }\n}\n","'use strict';\n\nconst kDone = Symbol('kDone');\nconst kRun = Symbol('kRun');\n\n/**\n * A very simple job queue with adjustable concurrency. Adapted from\n * https://github.com/STRML/async-limiter\n */\nclass Limiter {\n /**\n * Creates a new `Limiter`.\n *\n * @param {Number} [concurrency=Infinity] The maximum number of jobs allowed\n * to run concurrently\n */\n constructor(concurrency) {\n this[kDone] = () => {\n this.pending--;\n this[kRun]();\n };\n this.concurrency = concurrency || Infinity;\n this.jobs = [];\n this.pending = 0;\n }\n\n /**\n * Adds a job to the queue.\n *\n * @param {Function} job The job to run\n * @public\n */\n add(job) {\n this.jobs.push(job);\n this[kRun]();\n }\n\n /**\n * Removes a job from the queue and runs it if possible.\n *\n * @private\n */\n [kRun]() {\n if (this.pending === this.concurrency) return;\n\n if (this.jobs.length) {\n const job = this.jobs.shift();\n\n this.pending++;\n job(this[kDone]);\n }\n }\n}\n\nmodule.exports = Limiter;\n","'use strict';\n\nconst zlib = require('zlib');\n\nconst bufferUtil = require('./buffer-util');\nconst Limiter = require('./limiter');\nconst { kStatusCode } = require('./constants');\n\nconst FastBuffer = Buffer[Symbol.species];\nconst TRAILER = Buffer.from([0x00, 0x00, 0xff, 0xff]);\nconst kPerMessageDeflate = Symbol('permessage-deflate');\nconst kTotalLength = Symbol('total-length');\nconst kCallback = Symbol('callback');\nconst kBuffers = Symbol('buffers');\nconst kError = Symbol('error');\n\n//\n// We limit zlib concurrency, which prevents severe memory fragmentation\n// as documented in https://github.com/nodejs/node/issues/8871#issuecomment-250915913\n// and https://github.com/websockets/ws/issues/1202\n//\n// Intentionally global; it's the global thread pool that's an issue.\n//\nlet zlibLimiter;\n\n/**\n * permessage-deflate implementation.\n */\nclass PerMessageDeflate {\n /**\n * Creates a PerMessageDeflate instance.\n *\n * @param {Object} [options] Configuration options\n * @param {(Boolean|Number)} [options.clientMaxWindowBits] Advertise support\n * for, or request, a custom client window size\n * @param {Boolean} [options.clientNoContextTakeover=false] Advertise/\n * acknowledge disabling of client context takeover\n * @param {Number} [options.concurrencyLimit=10] The number of concurrent\n * calls to zlib\n * @param {(Boolean|Number)} [options.serverMaxWindowBits] Request/confirm the\n * use of a custom server window size\n * @param {Boolean} [options.serverNoContextTakeover=false] Request/accept\n * disabling of server context takeover\n * @param {Number} [options.threshold=1024] Size (in bytes) below which\n * messages should not be compressed if context takeover is disabled\n * @param {Object} [options.zlibDeflateOptions] Options to pass to zlib on\n * deflate\n * @param {Object} [options.zlibInflateOptions] Options to pass to zlib on\n * inflate\n * @param {Boolean} [isServer=false] Create the instance in either server or\n * client mode\n * @param {Number} [maxPayload=0] The maximum allowed message length\n */\n constructor(options, isServer, maxPayload) {\n this._maxPayload = maxPayload | 0;\n this._options = options || {};\n this._threshold =\n this._options.threshold !== undefined ? this._options.threshold : 1024;\n this._isServer = !!isServer;\n this._deflate = null;\n this._inflate = null;\n\n this.params = null;\n\n if (!zlibLimiter) {\n const concurrency =\n this._options.concurrencyLimit !== undefined\n ? this._options.concurrencyLimit\n : 10;\n zlibLimiter = new Limiter(concurrency);\n }\n }\n\n /**\n * @type {String}\n */\n static get extensionName() {\n return 'permessage-deflate';\n }\n\n /**\n * Create an extension negotiation offer.\n *\n * @return {Object} Extension parameters\n * @public\n */\n offer() {\n const params = {};\n\n if (this._options.serverNoContextTakeover) {\n params.server_no_context_takeover = true;\n }\n if (this._options.clientNoContextTakeover) {\n params.client_no_context_takeover = true;\n }\n if (this._options.serverMaxWindowBits) {\n params.server_max_window_bits = this._options.serverMaxWindowBits;\n }\n if (this._options.clientMaxWindowBits) {\n params.client_max_window_bits = this._options.clientMaxWindowBits;\n } else if (this._options.clientMaxWindowBits == null) {\n params.client_max_window_bits = true;\n }\n\n return params;\n }\n\n /**\n * Accept an extension negotiation offer/response.\n *\n * @param {Array} configurations The extension negotiation offers/reponse\n * @return {Object} Accepted configuration\n * @public\n */\n accept(configurations) {\n configurations = this.normalizeParams(configurations);\n\n this.params = this._isServer\n ? this.acceptAsServer(configurations)\n : this.acceptAsClient(configurations);\n\n return this.params;\n }\n\n /**\n * Releases all resources used by the extension.\n *\n * @public\n */\n cleanup() {\n if (this._inflate) {\n this._inflate.close();\n this._inflate = null;\n }\n\n if (this._deflate) {\n const callback = this._deflate[kCallback];\n\n this._deflate.close();\n this._deflate = null;\n\n if (callback) {\n callback(\n new Error(\n 'The deflate stream was closed while data was being processed'\n )\n );\n }\n }\n }\n\n /**\n * Accept an extension negotiation offer.\n *\n * @param {Array} offers The extension negotiation offers\n * @return {Object} Accepted configuration\n * @private\n */\n acceptAsServer(offers) {\n const opts = this._options;\n const accepted = offers.find((params) => {\n if (\n (opts.serverNoContextTakeover === false &&\n params.server_no_context_takeover) ||\n (params.server_max_window_bits &&\n (opts.serverMaxWindowBits === false ||\n (typeof opts.serverMaxWindowBits === 'number' &&\n opts.serverMaxWindowBits > params.server_max_window_bits))) ||\n (typeof opts.clientMaxWindowBits === 'number' &&\n !params.client_max_window_bits)\n ) {\n return false;\n }\n\n return true;\n });\n\n if (!accepted) {\n throw new Error('None of the extension offers can be accepted');\n }\n\n if (opts.serverNoContextTakeover) {\n accepted.server_no_context_takeover = true;\n }\n if (opts.clientNoContextTakeover) {\n accepted.client_no_context_takeover = true;\n }\n if (typeof opts.serverMaxWindowBits === 'number') {\n accepted.server_max_window_bits = opts.serverMaxWindowBits;\n }\n if (typeof opts.clientMaxWindowBits === 'number') {\n accepted.client_max_window_bits = opts.clientMaxWindowBits;\n } else if (\n accepted.client_max_window_bits === true ||\n opts.clientMaxWindowBits === false\n ) {\n delete accepted.client_max_window_bits;\n }\n\n return accepted;\n }\n\n /**\n * Accept the extension negotiation response.\n *\n * @param {Array} response The extension negotiation response\n * @return {Object} Accepted configuration\n * @private\n */\n acceptAsClient(response) {\n const params = response[0];\n\n if (\n this._options.clientNoContextTakeover === false &&\n params.client_no_context_takeover\n ) {\n throw new Error('Unexpected parameter \"client_no_context_takeover\"');\n }\n\n if (!params.client_max_window_bits) {\n if (typeof this._options.clientMaxWindowBits === 'number') {\n params.client_max_window_bits = this._options.clientMaxWindowBits;\n }\n } else if (\n this._options.clientMaxWindowBits === false ||\n (typeof this._options.clientMaxWindowBits === 'number' &&\n params.client_max_window_bits > this._options.clientMaxWindowBits)\n ) {\n throw new Error(\n 'Unexpected or invalid parameter \"client_max_window_bits\"'\n );\n }\n\n return params;\n }\n\n /**\n * Normalize parameters.\n *\n * @param {Array} configurations The extension negotiation offers/reponse\n * @return {Array} The offers/response with normalized parameters\n * @private\n */\n normalizeParams(configurations) {\n configurations.forEach((params) => {\n Object.keys(params).forEach((key) => {\n let value = params[key];\n\n if (value.length > 1) {\n throw new Error(`Parameter \"${key}\" must have only a single value`);\n }\n\n value = value[0];\n\n if (key === 'client_max_window_bits') {\n if (value !== true) {\n const num = +value;\n if (!Number.isInteger(num) || num < 8 || num > 15) {\n throw new TypeError(\n `Invalid value for parameter \"${key}\": ${value}`\n );\n }\n value = num;\n } else if (!this._isServer) {\n throw new TypeError(\n `Invalid value for parameter \"${key}\": ${value}`\n );\n }\n } else if (key === 'server_max_window_bits') {\n const num = +value;\n if (!Number.isInteger(num) || num < 8 || num > 15) {\n throw new TypeError(\n `Invalid value for parameter \"${key}\": ${value}`\n );\n }\n value = num;\n } else if (\n key === 'client_no_context_takeover' ||\n key === 'server_no_context_takeover'\n ) {\n if (value !== true) {\n throw new TypeError(\n `Invalid value for parameter \"${key}\": ${value}`\n );\n }\n } else {\n throw new Error(`Unknown parameter \"${key}\"`);\n }\n\n params[key] = value;\n });\n });\n\n return configurations;\n }\n\n /**\n * Decompress data. Concurrency limited.\n *\n * @param {Buffer} data Compressed data\n * @param {Boolean} fin Specifies whether or not this is the last fragment\n * @param {Function} callback Callback\n * @public\n */\n decompress(data, fin, callback) {\n zlibLimiter.add((done) => {\n this._decompress(data, fin, (err, result) => {\n done();\n callback(err, result);\n });\n });\n }\n\n /**\n * Compress data. Concurrency limited.\n *\n * @param {(Buffer|String)} data Data to compress\n * @param {Boolean} fin Specifies whether or not this is the last fragment\n * @param {Function} callback Callback\n * @public\n */\n compress(data, fin, callback) {\n zlibLimiter.add((done) => {\n this._compress(data, fin, (err, result) => {\n done();\n callback(err, result);\n });\n });\n }\n\n /**\n * Decompress data.\n *\n * @param {Buffer} data Compressed data\n * @param {Boolean} fin Specifies whether or not this is the last fragment\n * @param {Function} callback Callback\n * @private\n */\n _decompress(data, fin, callback) {\n const endpoint = this._isServer ? 'client' : 'server';\n\n if (!this._inflate) {\n const key = `${endpoint}_max_window_bits`;\n const windowBits =\n typeof this.params[key] !== 'number'\n ? zlib.Z_DEFAULT_WINDOWBITS\n : this.params[key];\n\n this._inflate = zlib.createInflateRaw({\n ...this._options.zlibInflateOptions,\n windowBits\n });\n this._inflate[kPerMessageDeflate] = this;\n this._inflate[kTotalLength] = 0;\n this._inflate[kBuffers] = [];\n this._inflate.on('error', inflateOnError);\n this._inflate.on('data', inflateOnData);\n }\n\n this._inflate[kCallback] = callback;\n\n this._inflate.write(data);\n if (fin) this._inflate.write(TRAILER);\n\n this._inflate.flush(() => {\n const err = this._inflate[kError];\n\n if (err) {\n this._inflate.close();\n this._inflate = null;\n callback(err);\n return;\n }\n\n const data = bufferUtil.concat(\n this._inflate[kBuffers],\n this._inflate[kTotalLength]\n );\n\n if (this._inflate._readableState.endEmitted) {\n this._inflate.close();\n this._inflate = null;\n } else {\n this._inflate[kTotalLength] = 0;\n this._inflate[kBuffers] = [];\n\n if (fin && this.params[`${endpoint}_no_context_takeover`]) {\n this._inflate.reset();\n }\n }\n\n callback(null, data);\n });\n }\n\n /**\n * Compress data.\n *\n * @param {(Buffer|String)} data Data to compress\n * @param {Boolean} fin Specifies whether or not this is the last fragment\n * @param {Function} callback Callback\n * @private\n */\n _compress(data, fin, callback) {\n const endpoint = this._isServer ? 'server' : 'client';\n\n if (!this._deflate) {\n const key = `${endpoint}_max_window_bits`;\n const windowBits =\n typeof this.params[key] !== 'number'\n ? zlib.Z_DEFAULT_WINDOWBITS\n : this.params[key];\n\n this._deflate = zlib.createDeflateRaw({\n ...this._options.zlibDeflateOptions,\n windowBits\n });\n\n this._deflate[kTotalLength] = 0;\n this._deflate[kBuffers] = [];\n\n this._deflate.on('data', deflateOnData);\n }\n\n this._deflate[kCallback] = callback;\n\n this._deflate.write(data);\n this._deflate.flush(zlib.Z_SYNC_FLUSH, () => {\n if (!this._deflate) {\n //\n // The deflate stream was closed while data was being processed.\n //\n return;\n }\n\n let data = bufferUtil.concat(\n this._deflate[kBuffers],\n this._deflate[kTotalLength]\n );\n\n if (fin) {\n data = new FastBuffer(data.buffer, data.byteOffset, data.length - 4);\n }\n\n //\n // Ensure that the callback will not be called again in\n // `PerMessageDeflate#cleanup()`.\n //\n this._deflate[kCallback] = null;\n\n this._deflate[kTotalLength] = 0;\n this._deflate[kBuffers] = [];\n\n if (fin && this.params[`${endpoint}_no_context_takeover`]) {\n this._deflate.reset();\n }\n\n callback(null, data);\n });\n }\n}\n\nmodule.exports = PerMessageDeflate;\n\n/**\n * The listener of the `zlib.DeflateRaw` stream `'data'` event.\n *\n * @param {Buffer} chunk A chunk of data\n * @private\n */\nfunction deflateOnData(chunk) {\n this[kBuffers].push(chunk);\n this[kTotalLength] += chunk.length;\n}\n\n/**\n * The listener of the `zlib.InflateRaw` stream `'data'` event.\n *\n * @param {Buffer} chunk A chunk of data\n * @private\n */\nfunction inflateOnData(chunk) {\n this[kTotalLength] += chunk.length;\n\n if (\n this[kPerMessageDeflate]._maxPayload < 1 ||\n this[kTotalLength] <= this[kPerMessageDeflate]._maxPayload\n ) {\n this[kBuffers].push(chunk);\n return;\n }\n\n this[kError] = new RangeError('Max payload size exceeded');\n this[kError].code = 'WS_ERR_UNSUPPORTED_MESSAGE_LENGTH';\n this[kError][kStatusCode] = 1009;\n this.removeListener('data', inflateOnData);\n\n //\n // The choice to employ `zlib.reset()` over `zlib.close()` is dictated by the\n // fact that in Node.js versions prior to 13.10.0, the callback for\n // `zlib.flush()` is not called if `zlib.close()` is used. Utilizing\n // `zlib.reset()` ensures that either the callback is invoked or an error is\n // emitted.\n //\n this.reset();\n}\n\n/**\n * The listener of the `zlib.InflateRaw` stream `'error'` event.\n *\n * @param {Error} err The emitted error\n * @private\n */\nfunction inflateOnError(err) {\n //\n // There is no need to call `Zlib#close()` as the handle is automatically\n // closed when an error is emitted.\n //\n this[kPerMessageDeflate]._inflate = null;\n\n if (this[kError]) {\n this[kCallback](this[kError]);\n return;\n }\n\n err[kStatusCode] = 1007;\n this[kCallback](err);\n}\n","'use strict';\n\nconst { isUtf8 } = require('buffer');\n\nconst { hasBlob } = require('./constants');\n\n//\n// Allowed token characters:\n//\n// '!', '#', '$', '%', '&', ''', '*', '+', '-',\n// '.', 0-9, A-Z, '^', '_', '`', a-z, '|', '~'\n//\n// tokenChars[32] === 0 // ' '\n// tokenChars[33] === 1 // '!'\n// tokenChars[34] === 0 // '\"'\n// ...\n//\n// prettier-ignore\nconst tokenChars = [\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0 - 15\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16 - 31\n 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, // 32 - 47\n 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 48 - 63\n 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64 - 79\n 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, // 80 - 95\n 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96 - 111\n 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0 // 112 - 127\n];\n\n/**\n * Checks if a status code is allowed in a close frame.\n *\n * @param {Number} code The status code\n * @return {Boolean} `true` if the status code is valid, else `false`\n * @public\n */\nfunction isValidStatusCode(code) {\n return (\n (code >= 1000 &&\n code <= 1014 &&\n code !== 1004 &&\n code !== 1005 &&\n code !== 1006) ||\n (code >= 3000 && code <= 4999)\n );\n}\n\n/**\n * Checks if a given buffer contains only correct UTF-8.\n * Ported from https://www.cl.cam.ac.uk/%7Emgk25/ucs/utf8_check.c by\n * Markus Kuhn.\n *\n * @param {Buffer} buf The buffer to check\n * @return {Boolean} `true` if `buf` contains only correct UTF-8, else `false`\n * @public\n */\nfunction _isValidUTF8(buf) {\n const len = buf.length;\n let i = 0;\n\n while (i < len) {\n if ((buf[i] & 0x80) === 0) {\n // 0xxxxxxx\n i++;\n } else if ((buf[i] & 0xe0) === 0xc0) {\n // 110xxxxx 10xxxxxx\n if (\n i + 1 === len ||\n (buf[i + 1] & 0xc0) !== 0x80 ||\n (buf[i] & 0xfe) === 0xc0 // Overlong\n ) {\n return false;\n }\n\n i += 2;\n } else if ((buf[i] & 0xf0) === 0xe0) {\n // 1110xxxx 10xxxxxx 10xxxxxx\n if (\n i + 2 >= len ||\n (buf[i + 1] & 0xc0) !== 0x80 ||\n (buf[i + 2] & 0xc0) !== 0x80 ||\n (buf[i] === 0xe0 && (buf[i + 1] & 0xe0) === 0x80) || // Overlong\n (buf[i] === 0xed && (buf[i + 1] & 0xe0) === 0xa0) // Surrogate (U+D800 - U+DFFF)\n ) {\n return false;\n }\n\n i += 3;\n } else if ((buf[i] & 0xf8) === 0xf0) {\n // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx\n if (\n i + 3 >= len ||\n (buf[i + 1] & 0xc0) !== 0x80 ||\n (buf[i + 2] & 0xc0) !== 0x80 ||\n (buf[i + 3] & 0xc0) !== 0x80 ||\n (buf[i] === 0xf0 && (buf[i + 1] & 0xf0) === 0x80) || // Overlong\n (buf[i] === 0xf4 && buf[i + 1] > 0x8f) ||\n buf[i] > 0xf4 // > U+10FFFF\n ) {\n return false;\n }\n\n i += 4;\n } else {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Determines whether a value is a `Blob`.\n *\n * @param {*} value The value to be tested\n * @return {Boolean} `true` if `value` is a `Blob`, else `false`\n * @private\n */\nfunction isBlob(value) {\n return (\n hasBlob &&\n typeof value === 'object' &&\n typeof value.arrayBuffer === 'function' &&\n typeof value.type === 'string' &&\n typeof value.stream === 'function' &&\n (value[Symbol.toStringTag] === 'Blob' ||\n value[Symbol.toStringTag] === 'File')\n );\n}\n\nmodule.exports = {\n isBlob,\n isValidStatusCode,\n isValidUTF8: _isValidUTF8,\n tokenChars\n};\n\nif (isUtf8) {\n module.exports.isValidUTF8 = function (buf) {\n return buf.length < 24 ? _isValidUTF8(buf) : isUtf8(buf);\n };\n} /* istanbul ignore else */ else if (!process.env.WS_NO_UTF_8_VALIDATE) {\n try {\n const isValidUTF8 = require('utf-8-validate');\n\n module.exports.isValidUTF8 = function (buf) {\n return buf.length < 32 ? _isValidUTF8(buf) : isValidUTF8(buf);\n };\n } catch (e) {\n // Continue regardless of the error.\n }\n}\n","'use strict';\n\nconst { Writable } = require('stream');\n\nconst PerMessageDeflate = require('./permessage-deflate');\nconst {\n BINARY_TYPES,\n EMPTY_BUFFER,\n kStatusCode,\n kWebSocket\n} = require('./constants');\nconst { concat, toArrayBuffer, unmask } = require('./buffer-util');\nconst { isValidStatusCode, isValidUTF8 } = require('./validation');\n\nconst FastBuffer = Buffer[Symbol.species];\n\nconst GET_INFO = 0;\nconst GET_PAYLOAD_LENGTH_16 = 1;\nconst GET_PAYLOAD_LENGTH_64 = 2;\nconst GET_MASK = 3;\nconst GET_DATA = 4;\nconst INFLATING = 5;\nconst DEFER_EVENT = 6;\n\n/**\n * HyBi Receiver implementation.\n *\n * @extends Writable\n */\nclass Receiver extends Writable {\n /**\n * Creates a Receiver instance.\n *\n * @param {Object} [options] Options object\n * @param {Boolean} [options.allowSynchronousEvents=true] Specifies whether\n * any of the `'message'`, `'ping'`, and `'pong'` events can be emitted\n * multiple times in the same tick\n * @param {String} [options.binaryType=nodebuffer] The type for binary data\n * @param {Object} [options.extensions] An object containing the negotiated\n * extensions\n * @param {Boolean} [options.isServer=false] Specifies whether to operate in\n * client or server mode\n * @param {Number} [options.maxPayload=0] The maximum allowed message length\n * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or\n * not to skip UTF-8 validation for text and close messages\n */\n constructor(options = {}) {\n super();\n\n this._allowSynchronousEvents =\n options.allowSynchronousEvents !== undefined\n ? options.allowSynchronousEvents\n : true;\n this._binaryType = options.binaryType || BINARY_TYPES[0];\n this._extensions = options.extensions || {};\n this._isServer = !!options.isServer;\n this._maxPayload = options.maxPayload | 0;\n this._skipUTF8Validation = !!options.skipUTF8Validation;\n this[kWebSocket] = undefined;\n\n this._bufferedBytes = 0;\n this._buffers = [];\n\n this._compressed = false;\n this._payloadLength = 0;\n this._mask = undefined;\n this._fragmented = 0;\n this._masked = false;\n this._fin = false;\n this._opcode = 0;\n\n this._totalPayloadLength = 0;\n this._messageLength = 0;\n this._fragments = [];\n\n this._errored = false;\n this._loop = false;\n this._state = GET_INFO;\n }\n\n /**\n * Implements `Writable.prototype._write()`.\n *\n * @param {Buffer} chunk The chunk of data to write\n * @param {String} encoding The character encoding of `chunk`\n * @param {Function} cb Callback\n * @private\n */\n _write(chunk, encoding, cb) {\n if (this._opcode === 0x08 && this._state == GET_INFO) return cb();\n\n this._bufferedBytes += chunk.length;\n this._buffers.push(chunk);\n this.startLoop(cb);\n }\n\n /**\n * Consumes `n` bytes from the buffered data.\n *\n * @param {Number} n The number of bytes to consume\n * @return {Buffer} The consumed bytes\n * @private\n */\n consume(n) {\n this._bufferedBytes -= n;\n\n if (n === this._buffers[0].length) return this._buffers.shift();\n\n if (n < this._buffers[0].length) {\n const buf = this._buffers[0];\n this._buffers[0] = new FastBuffer(\n buf.buffer,\n buf.byteOffset + n,\n buf.length - n\n );\n\n return new FastBuffer(buf.buffer, buf.byteOffset, n);\n }\n\n const dst = Buffer.allocUnsafe(n);\n\n do {\n const buf = this._buffers[0];\n const offset = dst.length - n;\n\n if (n >= buf.length) {\n dst.set(this._buffers.shift(), offset);\n } else {\n dst.set(new Uint8Array(buf.buffer, buf.byteOffset, n), offset);\n this._buffers[0] = new FastBuffer(\n buf.buffer,\n buf.byteOffset + n,\n buf.length - n\n );\n }\n\n n -= buf.length;\n } while (n > 0);\n\n return dst;\n }\n\n /**\n * Starts the parsing loop.\n *\n * @param {Function} cb Callback\n * @private\n */\n startLoop(cb) {\n this._loop = true;\n\n do {\n switch (this._state) {\n case GET_INFO:\n this.getInfo(cb);\n break;\n case GET_PAYLOAD_LENGTH_16:\n this.getPayloadLength16(cb);\n break;\n case GET_PAYLOAD_LENGTH_64:\n this.getPayloadLength64(cb);\n break;\n case GET_MASK:\n this.getMask();\n break;\n case GET_DATA:\n this.getData(cb);\n break;\n case INFLATING:\n case DEFER_EVENT:\n this._loop = false;\n return;\n }\n } while (this._loop);\n\n if (!this._errored) cb();\n }\n\n /**\n * Reads the first two bytes of a frame.\n *\n * @param {Function} cb Callback\n * @private\n */\n getInfo(cb) {\n if (this._bufferedBytes < 2) {\n this._loop = false;\n return;\n }\n\n const buf = this.consume(2);\n\n if ((buf[0] & 0x30) !== 0x00) {\n const error = this.createError(\n RangeError,\n 'RSV2 and RSV3 must be clear',\n true,\n 1002,\n 'WS_ERR_UNEXPECTED_RSV_2_3'\n );\n\n cb(error);\n return;\n }\n\n const compressed = (buf[0] & 0x40) === 0x40;\n\n if (compressed && !this._extensions[PerMessageDeflate.extensionName]) {\n const error = this.createError(\n RangeError,\n 'RSV1 must be clear',\n true,\n 1002,\n 'WS_ERR_UNEXPECTED_RSV_1'\n );\n\n cb(error);\n return;\n }\n\n this._fin = (buf[0] & 0x80) === 0x80;\n this._opcode = buf[0] & 0x0f;\n this._payloadLength = buf[1] & 0x7f;\n\n if (this._opcode === 0x00) {\n if (compressed) {\n const error = this.createError(\n RangeError,\n 'RSV1 must be clear',\n true,\n 1002,\n 'WS_ERR_UNEXPECTED_RSV_1'\n );\n\n cb(error);\n return;\n }\n\n if (!this._fragmented) {\n const error = this.createError(\n RangeError,\n 'invalid opcode 0',\n true,\n 1002,\n 'WS_ERR_INVALID_OPCODE'\n );\n\n cb(error);\n return;\n }\n\n this._opcode = this._fragmented;\n } else if (this._opcode === 0x01 || this._opcode === 0x02) {\n if (this._fragmented) {\n const error = this.createError(\n RangeError,\n `invalid opcode ${this._opcode}`,\n true,\n 1002,\n 'WS_ERR_INVALID_OPCODE'\n );\n\n cb(error);\n return;\n }\n\n this._compressed = compressed;\n } else if (this._opcode > 0x07 && this._opcode < 0x0b) {\n if (!this._fin) {\n const error = this.createError(\n RangeError,\n 'FIN must be set',\n true,\n 1002,\n 'WS_ERR_EXPECTED_FIN'\n );\n\n cb(error);\n return;\n }\n\n if (compressed) {\n const error = this.createError(\n RangeError,\n 'RSV1 must be clear',\n true,\n 1002,\n 'WS_ERR_UNEXPECTED_RSV_1'\n );\n\n cb(error);\n return;\n }\n\n if (\n this._payloadLength > 0x7d ||\n (this._opcode === 0x08 && this._payloadLength === 1)\n ) {\n const error = this.createError(\n RangeError,\n `invalid payload length ${this._payloadLength}`,\n true,\n 1002,\n 'WS_ERR_INVALID_CONTROL_PAYLOAD_LENGTH'\n );\n\n cb(error);\n return;\n }\n } else {\n const error = this.createError(\n RangeError,\n `invalid opcode ${this._opcode}`,\n true,\n 1002,\n 'WS_ERR_INVALID_OPCODE'\n );\n\n cb(error);\n return;\n }\n\n if (!this._fin && !this._fragmented) this._fragmented = this._opcode;\n this._masked = (buf[1] & 0x80) === 0x80;\n\n if (this._isServer) {\n if (!this._masked) {\n const error = this.createError(\n RangeError,\n 'MASK must be set',\n true,\n 1002,\n 'WS_ERR_EXPECTED_MASK'\n );\n\n cb(error);\n return;\n }\n } else if (this._masked) {\n const error = this.createError(\n RangeError,\n 'MASK must be clear',\n true,\n 1002,\n 'WS_ERR_UNEXPECTED_MASK'\n );\n\n cb(error);\n return;\n }\n\n if (this._payloadLength === 126) this._state = GET_PAYLOAD_LENGTH_16;\n else if (this._payloadLength === 127) this._state = GET_PAYLOAD_LENGTH_64;\n else this.haveLength(cb);\n }\n\n /**\n * Gets extended payload length (7+16).\n *\n * @param {Function} cb Callback\n * @private\n */\n getPayloadLength16(cb) {\n if (this._bufferedBytes < 2) {\n this._loop = false;\n return;\n }\n\n this._payloadLength = this.consume(2).readUInt16BE(0);\n this.haveLength(cb);\n }\n\n /**\n * Gets extended payload length (7+64).\n *\n * @param {Function} cb Callback\n * @private\n */\n getPayloadLength64(cb) {\n if (this._bufferedBytes < 8) {\n this._loop = false;\n return;\n }\n\n const buf = this.consume(8);\n const num = buf.readUInt32BE(0);\n\n //\n // The maximum safe integer in JavaScript is 2^53 - 1. An error is returned\n // if payload length is greater than this number.\n //\n if (num > Math.pow(2, 53 - 32) - 1) {\n const error = this.createError(\n RangeError,\n 'Unsupported WebSocket frame: payload length > 2^53 - 1',\n false,\n 1009,\n 'WS_ERR_UNSUPPORTED_DATA_PAYLOAD_LENGTH'\n );\n\n cb(error);\n return;\n }\n\n this._payloadLength = num * Math.pow(2, 32) + buf.readUInt32BE(4);\n this.haveLength(cb);\n }\n\n /**\n * Payload length has been read.\n *\n * @param {Function} cb Callback\n * @private\n */\n haveLength(cb) {\n if (this._payloadLength && this._opcode < 0x08) {\n this._totalPayloadLength += this._payloadLength;\n if (this._totalPayloadLength > this._maxPayload && this._maxPayload > 0) {\n const error = this.createError(\n RangeError,\n 'Max payload size exceeded',\n false,\n 1009,\n 'WS_ERR_UNSUPPORTED_MESSAGE_LENGTH'\n );\n\n cb(error);\n return;\n }\n }\n\n if (this._masked) this._state = GET_MASK;\n else this._state = GET_DATA;\n }\n\n /**\n * Reads mask bytes.\n *\n * @private\n */\n getMask() {\n if (this._bufferedBytes < 4) {\n this._loop = false;\n return;\n }\n\n this._mask = this.consume(4);\n this._state = GET_DATA;\n }\n\n /**\n * Reads data bytes.\n *\n * @param {Function} cb Callback\n * @private\n */\n getData(cb) {\n let data = EMPTY_BUFFER;\n\n if (this._payloadLength) {\n if (this._bufferedBytes < this._payloadLength) {\n this._loop = false;\n return;\n }\n\n data = this.consume(this._payloadLength);\n\n if (\n this._masked &&\n (this._mask[0] | this._mask[1] | this._mask[2] | this._mask[3]) !== 0\n ) {\n unmask(data, this._mask);\n }\n }\n\n if (this._opcode > 0x07) {\n this.controlMessage(data, cb);\n return;\n }\n\n if (this._compressed) {\n this._state = INFLATING;\n this.decompress(data, cb);\n return;\n }\n\n if (data.length) {\n //\n // This message is not compressed so its length is the sum of the payload\n // length of all fragments.\n //\n this._messageLength = this._totalPayloadLength;\n this._fragments.push(data);\n }\n\n this.dataMessage(cb);\n }\n\n /**\n * Decompresses data.\n *\n * @param {Buffer} data Compressed data\n * @param {Function} cb Callback\n * @private\n */\n decompress(data, cb) {\n const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName];\n\n perMessageDeflate.decompress(data, this._fin, (err, buf) => {\n if (err) return cb(err);\n\n if (buf.length) {\n this._messageLength += buf.length;\n if (this._messageLength > this._maxPayload && this._maxPayload > 0) {\n const error = this.createError(\n RangeError,\n 'Max payload size exceeded',\n false,\n 1009,\n 'WS_ERR_UNSUPPORTED_MESSAGE_LENGTH'\n );\n\n cb(error);\n return;\n }\n\n this._fragments.push(buf);\n }\n\n this.dataMessage(cb);\n if (this._state === GET_INFO) this.startLoop(cb);\n });\n }\n\n /**\n * Handles a data message.\n *\n * @param {Function} cb Callback\n * @private\n */\n dataMessage(cb) {\n if (!this._fin) {\n this._state = GET_INFO;\n return;\n }\n\n const messageLength = this._messageLength;\n const fragments = this._fragments;\n\n this._totalPayloadLength = 0;\n this._messageLength = 0;\n this._fragmented = 0;\n this._fragments = [];\n\n if (this._opcode === 2) {\n let data;\n\n if (this._binaryType === 'nodebuffer') {\n data = concat(fragments, messageLength);\n } else if (this._binaryType === 'arraybuffer') {\n data = toArrayBuffer(concat(fragments, messageLength));\n } else if (this._binaryType === 'blob') {\n data = new Blob(fragments);\n } else {\n data = fragments;\n }\n\n if (this._allowSynchronousEvents) {\n this.emit('message', data, true);\n this._state = GET_INFO;\n } else {\n this._state = DEFER_EVENT;\n setImmediate(() => {\n this.emit('message', data, true);\n this._state = GET_INFO;\n this.startLoop(cb);\n });\n }\n } else {\n const buf = concat(fragments, messageLength);\n\n if (!this._skipUTF8Validation && !isValidUTF8(buf)) {\n const error = this.createError(\n Error,\n 'invalid UTF-8 sequence',\n true,\n 1007,\n 'WS_ERR_INVALID_UTF8'\n );\n\n cb(error);\n return;\n }\n\n if (this._state === INFLATING || this._allowSynchronousEvents) {\n this.emit('message', buf, false);\n this._state = GET_INFO;\n } else {\n this._state = DEFER_EVENT;\n setImmediate(() => {\n this.emit('message', buf, false);\n this._state = GET_INFO;\n this.startLoop(cb);\n });\n }\n }\n }\n\n /**\n * Handles a control message.\n *\n * @param {Buffer} data Data to handle\n * @return {(Error|RangeError|undefined)} A possible error\n * @private\n */\n controlMessage(data, cb) {\n if (this._opcode === 0x08) {\n if (data.length === 0) {\n this._loop = false;\n this.emit('conclude', 1005, EMPTY_BUFFER);\n this.end();\n } else {\n const code = data.readUInt16BE(0);\n\n if (!isValidStatusCode(code)) {\n const error = this.createError(\n RangeError,\n `invalid status code ${code}`,\n true,\n 1002,\n 'WS_ERR_INVALID_CLOSE_CODE'\n );\n\n cb(error);\n return;\n }\n\n const buf = new FastBuffer(\n data.buffer,\n data.byteOffset + 2,\n data.length - 2\n );\n\n if (!this._skipUTF8Validation && !isValidUTF8(buf)) {\n const error = this.createError(\n Error,\n 'invalid UTF-8 sequence',\n true,\n 1007,\n 'WS_ERR_INVALID_UTF8'\n );\n\n cb(error);\n return;\n }\n\n this._loop = false;\n this.emit('conclude', code, buf);\n this.end();\n }\n\n this._state = GET_INFO;\n return;\n }\n\n if (this._allowSynchronousEvents) {\n this.emit(this._opcode === 0x09 ? 'ping' : 'pong', data);\n this._state = GET_INFO;\n } else {\n this._state = DEFER_EVENT;\n setImmediate(() => {\n this.emit(this._opcode === 0x09 ? 'ping' : 'pong', data);\n this._state = GET_INFO;\n this.startLoop(cb);\n });\n }\n }\n\n /**\n * Builds an error object.\n *\n * @param {function(new:Error|RangeError)} ErrorCtor The error constructor\n * @param {String} message The error message\n * @param {Boolean} prefix Specifies whether or not to add a default prefix to\n * `message`\n * @param {Number} statusCode The status code\n * @param {String} errorCode The exposed error code\n * @return {(Error|RangeError)} The error\n * @private\n */\n createError(ErrorCtor, message, prefix, statusCode, errorCode) {\n this._loop = false;\n this._errored = true;\n\n const err = new ErrorCtor(\n prefix ? `Invalid WebSocket frame: ${message}` : message\n );\n\n Error.captureStackTrace(err, this.createError);\n err.code = errorCode;\n err[kStatusCode] = statusCode;\n return err;\n }\n}\n\nmodule.exports = Receiver;\n","/* eslint no-unused-vars: [\"error\", { \"varsIgnorePattern\": \"^Duplex\" }] */\n\n'use strict';\n\nconst { Duplex } = require('stream');\nconst { randomFillSync } = require('crypto');\n\nconst PerMessageDeflate = require('./permessage-deflate');\nconst { EMPTY_BUFFER, kWebSocket, NOOP } = require('./constants');\nconst { isBlob, isValidStatusCode } = require('./validation');\nconst { mask: applyMask, toBuffer } = require('./buffer-util');\n\nconst kByteLength = Symbol('kByteLength');\nconst maskBuffer = Buffer.alloc(4);\nconst RANDOM_POOL_SIZE = 8 * 1024;\nlet randomPool;\nlet randomPoolPointer = RANDOM_POOL_SIZE;\n\nconst DEFAULT = 0;\nconst DEFLATING = 1;\nconst GET_BLOB_DATA = 2;\n\n/**\n * HyBi Sender implementation.\n */\nclass Sender {\n /**\n * Creates a Sender instance.\n *\n * @param {Duplex} socket The connection socket\n * @param {Object} [extensions] An object containing the negotiated extensions\n * @param {Function} [generateMask] The function used to generate the masking\n * key\n */\n constructor(socket, extensions, generateMask) {\n this._extensions = extensions || {};\n\n if (generateMask) {\n this._generateMask = generateMask;\n this._maskBuffer = Buffer.alloc(4);\n }\n\n this._socket = socket;\n\n this._firstFragment = true;\n this._compress = false;\n\n this._bufferedBytes = 0;\n this._queue = [];\n this._state = DEFAULT;\n this.onerror = NOOP;\n this[kWebSocket] = undefined;\n }\n\n /**\n * Frames a piece of data according to the HyBi WebSocket protocol.\n *\n * @param {(Buffer|String)} data The data to frame\n * @param {Object} options Options object\n * @param {Boolean} [options.fin=false] Specifies whether or not to set the\n * FIN bit\n * @param {Function} [options.generateMask] The function used to generate the\n * masking key\n * @param {Boolean} [options.mask=false] Specifies whether or not to mask\n * `data`\n * @param {Buffer} [options.maskBuffer] The buffer used to store the masking\n * key\n * @param {Number} options.opcode The opcode\n * @param {Boolean} [options.readOnly=false] Specifies whether `data` can be\n * modified\n * @param {Boolean} [options.rsv1=false] Specifies whether or not to set the\n * RSV1 bit\n * @return {(Buffer|String)[]} The framed data\n * @public\n */\n static frame(data, options) {\n let mask;\n let merge = false;\n let offset = 2;\n let skipMasking = false;\n\n if (options.mask) {\n mask = options.maskBuffer || maskBuffer;\n\n if (options.generateMask) {\n options.generateMask(mask);\n } else {\n if (randomPoolPointer === RANDOM_POOL_SIZE) {\n /* istanbul ignore else */\n if (randomPool === undefined) {\n //\n // This is lazily initialized because server-sent frames must not\n // be masked so it may never be used.\n //\n randomPool = Buffer.alloc(RANDOM_POOL_SIZE);\n }\n\n randomFillSync(randomPool, 0, RANDOM_POOL_SIZE);\n randomPoolPointer = 0;\n }\n\n mask[0] = randomPool[randomPoolPointer++];\n mask[1] = randomPool[randomPoolPointer++];\n mask[2] = randomPool[randomPoolPointer++];\n mask[3] = randomPool[randomPoolPointer++];\n }\n\n skipMasking = (mask[0] | mask[1] | mask[2] | mask[3]) === 0;\n offset = 6;\n }\n\n let dataLength;\n\n if (typeof data === 'string') {\n if (\n (!options.mask || skipMasking) &&\n options[kByteLength] !== undefined\n ) {\n dataLength = options[kByteLength];\n } else {\n data = Buffer.from(data);\n dataLength = data.length;\n }\n } else {\n dataLength = data.length;\n merge = options.mask && options.readOnly && !skipMasking;\n }\n\n let payloadLength = dataLength;\n\n if (dataLength >= 65536) {\n offset += 8;\n payloadLength = 127;\n } else if (dataLength > 125) {\n offset += 2;\n payloadLength = 126;\n }\n\n const target = Buffer.allocUnsafe(merge ? dataLength + offset : offset);\n\n target[0] = options.fin ? options.opcode | 0x80 : options.opcode;\n if (options.rsv1) target[0] |= 0x40;\n\n target[1] = payloadLength;\n\n if (payloadLength === 126) {\n target.writeUInt16BE(dataLength, 2);\n } else if (payloadLength === 127) {\n target[2] = target[3] = 0;\n target.writeUIntBE(dataLength, 4, 6);\n }\n\n if (!options.mask) return [target, data];\n\n target[1] |= 0x80;\n target[offset - 4] = mask[0];\n target[offset - 3] = mask[1];\n target[offset - 2] = mask[2];\n target[offset - 1] = mask[3];\n\n if (skipMasking) return [target, data];\n\n if (merge) {\n applyMask(data, mask, target, offset, dataLength);\n return [target];\n }\n\n applyMask(data, mask, data, 0, dataLength);\n return [target, data];\n }\n\n /**\n * Sends a close message to the other peer.\n *\n * @param {Number} [code] The status code component of the body\n * @param {(String|Buffer)} [data] The message component of the body\n * @param {Boolean} [mask=false] Specifies whether or not to mask the message\n * @param {Function} [cb] Callback\n * @public\n */\n close(code, data, mask, cb) {\n let buf;\n\n if (code === undefined) {\n buf = EMPTY_BUFFER;\n } else if (typeof code !== 'number' || !isValidStatusCode(code)) {\n throw new TypeError('First argument must be a valid error code number');\n } else if (data === undefined || !data.length) {\n buf = Buffer.allocUnsafe(2);\n buf.writeUInt16BE(code, 0);\n } else {\n const length = Buffer.byteLength(data);\n\n if (length > 123) {\n throw new RangeError('The message must not be greater than 123 bytes');\n }\n\n buf = Buffer.allocUnsafe(2 + length);\n buf.writeUInt16BE(code, 0);\n\n if (typeof data === 'string') {\n buf.write(data, 2);\n } else {\n buf.set(data, 2);\n }\n }\n\n const options = {\n [kByteLength]: buf.length,\n fin: true,\n generateMask: this._generateMask,\n mask,\n maskBuffer: this._maskBuffer,\n opcode: 0x08,\n readOnly: false,\n rsv1: false\n };\n\n if (this._state !== DEFAULT) {\n this.enqueue([this.dispatch, buf, false, options, cb]);\n } else {\n this.sendFrame(Sender.frame(buf, options), cb);\n }\n }\n\n /**\n * Sends a ping message to the other peer.\n *\n * @param {*} data The message to send\n * @param {Boolean} [mask=false] Specifies whether or not to mask `data`\n * @param {Function} [cb] Callback\n * @public\n */\n ping(data, mask, cb) {\n let byteLength;\n let readOnly;\n\n if (typeof data === 'string') {\n byteLength = Buffer.byteLength(data);\n readOnly = false;\n } else if (isBlob(data)) {\n byteLength = data.size;\n readOnly = false;\n } else {\n data = toBuffer(data);\n byteLength = data.length;\n readOnly = toBuffer.readOnly;\n }\n\n if (byteLength > 125) {\n throw new RangeError('The data size must not be greater than 125 bytes');\n }\n\n const options = {\n [kByteLength]: byteLength,\n fin: true,\n generateMask: this._generateMask,\n mask,\n maskBuffer: this._maskBuffer,\n opcode: 0x09,\n readOnly,\n rsv1: false\n };\n\n if (isBlob(data)) {\n if (this._state !== DEFAULT) {\n this.enqueue([this.getBlobData, data, false, options, cb]);\n } else {\n this.getBlobData(data, false, options, cb);\n }\n } else if (this._state !== DEFAULT) {\n this.enqueue([this.dispatch, data, false, options, cb]);\n } else {\n this.sendFrame(Sender.frame(data, options), cb);\n }\n }\n\n /**\n * Sends a pong message to the other peer.\n *\n * @param {*} data The message to send\n * @param {Boolean} [mask=false] Specifies whether or not to mask `data`\n * @param {Function} [cb] Callback\n * @public\n */\n pong(data, mask, cb) {\n let byteLength;\n let readOnly;\n\n if (typeof data === 'string') {\n byteLength = Buffer.byteLength(data);\n readOnly = false;\n } else if (isBlob(data)) {\n byteLength = data.size;\n readOnly = false;\n } else {\n data = toBuffer(data);\n byteLength = data.length;\n readOnly = toBuffer.readOnly;\n }\n\n if (byteLength > 125) {\n throw new RangeError('The data size must not be greater than 125 bytes');\n }\n\n const options = {\n [kByteLength]: byteLength,\n fin: true,\n generateMask: this._generateMask,\n mask,\n maskBuffer: this._maskBuffer,\n opcode: 0x0a,\n readOnly,\n rsv1: false\n };\n\n if (isBlob(data)) {\n if (this._state !== DEFAULT) {\n this.enqueue([this.getBlobData, data, false, options, cb]);\n } else {\n this.getBlobData(data, false, options, cb);\n }\n } else if (this._state !== DEFAULT) {\n this.enqueue([this.dispatch, data, false, options, cb]);\n } else {\n this.sendFrame(Sender.frame(data, options), cb);\n }\n }\n\n /**\n * Sends a data message to the other peer.\n *\n * @param {*} data The message to send\n * @param {Object} options Options object\n * @param {Boolean} [options.binary=false] Specifies whether `data` is binary\n * or text\n * @param {Boolean} [options.compress=false] Specifies whether or not to\n * compress `data`\n * @param {Boolean} [options.fin=false] Specifies whether the fragment is the\n * last one\n * @param {Boolean} [options.mask=false] Specifies whether or not to mask\n * `data`\n * @param {Function} [cb] Callback\n * @public\n */\n send(data, options, cb) {\n const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName];\n let opcode = options.binary ? 2 : 1;\n let rsv1 = options.compress;\n\n let byteLength;\n let readOnly;\n\n if (typeof data === 'string') {\n byteLength = Buffer.byteLength(data);\n readOnly = false;\n } else if (isBlob(data)) {\n byteLength = data.size;\n readOnly = false;\n } else {\n data = toBuffer(data);\n byteLength = data.length;\n readOnly = toBuffer.readOnly;\n }\n\n if (this._firstFragment) {\n this._firstFragment = false;\n if (\n rsv1 &&\n perMessageDeflate &&\n perMessageDeflate.params[\n perMessageDeflate._isServer\n ? 'server_no_context_takeover'\n : 'client_no_context_takeover'\n ]\n ) {\n rsv1 = byteLength >= perMessageDeflate._threshold;\n }\n this._compress = rsv1;\n } else {\n rsv1 = false;\n opcode = 0;\n }\n\n if (options.fin) this._firstFragment = true;\n\n const opts = {\n [kByteLength]: byteLength,\n fin: options.fin,\n generateMask: this._generateMask,\n mask: options.mask,\n maskBuffer: this._maskBuffer,\n opcode,\n readOnly,\n rsv1\n };\n\n if (isBlob(data)) {\n if (this._state !== DEFAULT) {\n this.enqueue([this.getBlobData, data, this._compress, opts, cb]);\n } else {\n this.getBlobData(data, this._compress, opts, cb);\n }\n } else if (this._state !== DEFAULT) {\n this.enqueue([this.dispatch, data, this._compress, opts, cb]);\n } else {\n this.dispatch(data, this._compress, opts, cb);\n }\n }\n\n /**\n * Gets the contents of a blob as binary data.\n *\n * @param {Blob} blob The blob\n * @param {Boolean} [compress=false] Specifies whether or not to compress\n * the data\n * @param {Object} options Options object\n * @param {Boolean} [options.fin=false] Specifies whether or not to set the\n * FIN bit\n * @param {Function} [options.generateMask] The function used to generate the\n * masking key\n * @param {Boolean} [options.mask=false] Specifies whether or not to mask\n * `data`\n * @param {Buffer} [options.maskBuffer] The buffer used to store the masking\n * key\n * @param {Number} options.opcode The opcode\n * @param {Boolean} [options.readOnly=false] Specifies whether `data` can be\n * modified\n * @param {Boolean} [options.rsv1=false] Specifies whether or not to set the\n * RSV1 bit\n * @param {Function} [cb] Callback\n * @private\n */\n getBlobData(blob, compress, options, cb) {\n this._bufferedBytes += options[kByteLength];\n this._state = GET_BLOB_DATA;\n\n blob\n .arrayBuffer()\n .then((arrayBuffer) => {\n if (this._socket.destroyed) {\n const err = new Error(\n 'The socket was closed while the blob was being read'\n );\n\n //\n // `callCallbacks` is called in the next tick to ensure that errors\n // that might be thrown in the callbacks behave like errors thrown\n // outside the promise chain.\n //\n process.nextTick(callCallbacks, this, err, cb);\n return;\n }\n\n this._bufferedBytes -= options[kByteLength];\n const data = toBuffer(arrayBuffer);\n\n if (!compress) {\n this._state = DEFAULT;\n this.sendFrame(Sender.frame(data, options), cb);\n this.dequeue();\n } else {\n this.dispatch(data, compress, options, cb);\n }\n })\n .catch((err) => {\n //\n // `onError` is called in the next tick for the same reason that\n // `callCallbacks` above is.\n //\n process.nextTick(onError, this, err, cb);\n });\n }\n\n /**\n * Dispatches a message.\n *\n * @param {(Buffer|String)} data The message to send\n * @param {Boolean} [compress=false] Specifies whether or not to compress\n * `data`\n * @param {Object} options Options object\n * @param {Boolean} [options.fin=false] Specifies whether or not to set the\n * FIN bit\n * @param {Function} [options.generateMask] The function used to generate the\n * masking key\n * @param {Boolean} [options.mask=false] Specifies whether or not to mask\n * `data`\n * @param {Buffer} [options.maskBuffer] The buffer used to store the masking\n * key\n * @param {Number} options.opcode The opcode\n * @param {Boolean} [options.readOnly=false] Specifies whether `data` can be\n * modified\n * @param {Boolean} [options.rsv1=false] Specifies whether or not to set the\n * RSV1 bit\n * @param {Function} [cb] Callback\n * @private\n */\n dispatch(data, compress, options, cb) {\n if (!compress) {\n this.sendFrame(Sender.frame(data, options), cb);\n return;\n }\n\n const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName];\n\n this._bufferedBytes += options[kByteLength];\n this._state = DEFLATING;\n perMessageDeflate.compress(data, options.fin, (_, buf) => {\n if (this._socket.destroyed) {\n const err = new Error(\n 'The socket was closed while data was being compressed'\n );\n\n callCallbacks(this, err, cb);\n return;\n }\n\n this._bufferedBytes -= options[kByteLength];\n this._state = DEFAULT;\n options.readOnly = false;\n this.sendFrame(Sender.frame(buf, options), cb);\n this.dequeue();\n });\n }\n\n /**\n * Executes queued send operations.\n *\n * @private\n */\n dequeue() {\n while (this._state === DEFAULT && this._queue.length) {\n const params = this._queue.shift();\n\n this._bufferedBytes -= params[3][kByteLength];\n Reflect.apply(params[0], this, params.slice(1));\n }\n }\n\n /**\n * Enqueues a send operation.\n *\n * @param {Array} params Send operation parameters.\n * @private\n */\n enqueue(params) {\n this._bufferedBytes += params[3][kByteLength];\n this._queue.push(params);\n }\n\n /**\n * Sends a frame.\n *\n * @param {(Buffer | String)[]} list The frame to send\n * @param {Function} [cb] Callback\n * @private\n */\n sendFrame(list, cb) {\n if (list.length === 2) {\n this._socket.cork();\n this._socket.write(list[0]);\n this._socket.write(list[1], cb);\n this._socket.uncork();\n } else {\n this._socket.write(list[0], cb);\n }\n }\n}\n\nmodule.exports = Sender;\n\n/**\n * Calls queued callbacks with an error.\n *\n * @param {Sender} sender The `Sender` instance\n * @param {Error} err The error to call the callbacks with\n * @param {Function} [cb] The first callback\n * @private\n */\nfunction callCallbacks(sender, err, cb) {\n if (typeof cb === 'function') cb(err);\n\n for (let i = 0; i < sender._queue.length; i++) {\n const params = sender._queue[i];\n const callback = params[params.length - 1];\n\n if (typeof callback === 'function') callback(err);\n }\n}\n\n/**\n * Handles a `Sender` error.\n *\n * @param {Sender} sender The `Sender` instance\n * @param {Error} err The error\n * @param {Function} [cb] The first pending callback\n * @private\n */\nfunction onError(sender, err, cb) {\n callCallbacks(sender, err, cb);\n sender.onerror(err);\n}\n","'use strict';\n\nconst { kForOnEventAttribute, kListener } = require('./constants');\n\nconst kCode = Symbol('kCode');\nconst kData = Symbol('kData');\nconst kError = Symbol('kError');\nconst kMessage = Symbol('kMessage');\nconst kReason = Symbol('kReason');\nconst kTarget = Symbol('kTarget');\nconst kType = Symbol('kType');\nconst kWasClean = Symbol('kWasClean');\n\n/**\n * Class representing an event.\n */\nclass Event {\n /**\n * Create a new `Event`.\n *\n * @param {String} type The name of the event\n * @throws {TypeError} If the `type` argument is not specified\n */\n constructor(type) {\n this[kTarget] = null;\n this[kType] = type;\n }\n\n /**\n * @type {*}\n */\n get target() {\n return this[kTarget];\n }\n\n /**\n * @type {String}\n */\n get type() {\n return this[kType];\n }\n}\n\nObject.defineProperty(Event.prototype, 'target', { enumerable: true });\nObject.defineProperty(Event.prototype, 'type', { enumerable: true });\n\n/**\n * Class representing a close event.\n *\n * @extends Event\n */\nclass CloseEvent extends Event {\n /**\n * Create a new `CloseEvent`.\n *\n * @param {String} type The name of the event\n * @param {Object} [options] A dictionary object that allows for setting\n * attributes via object members of the same name\n * @param {Number} [options.code=0] The status code explaining why the\n * connection was closed\n * @param {String} [options.reason=''] A human-readable string explaining why\n * the connection was closed\n * @param {Boolean} [options.wasClean=false] Indicates whether or not the\n * connection was cleanly closed\n */\n constructor(type, options = {}) {\n super(type);\n\n this[kCode] = options.code === undefined ? 0 : options.code;\n this[kReason] = options.reason === undefined ? '' : options.reason;\n this[kWasClean] = options.wasClean === undefined ? false : options.wasClean;\n }\n\n /**\n * @type {Number}\n */\n get code() {\n return this[kCode];\n }\n\n /**\n * @type {String}\n */\n get reason() {\n return this[kReason];\n }\n\n /**\n * @type {Boolean}\n */\n get wasClean() {\n return this[kWasClean];\n }\n}\n\nObject.defineProperty(CloseEvent.prototype, 'code', { enumerable: true });\nObject.defineProperty(CloseEvent.prototype, 'reason', { enumerable: true });\nObject.defineProperty(CloseEvent.prototype, 'wasClean', { enumerable: true });\n\n/**\n * Class representing an error event.\n *\n * @extends Event\n */\nclass ErrorEvent extends Event {\n /**\n * Create a new `ErrorEvent`.\n *\n * @param {String} type The name of the event\n * @param {Object} [options] A dictionary object that allows for setting\n * attributes via object members of the same name\n * @param {*} [options.error=null] The error that generated this event\n * @param {String} [options.message=''] The error message\n */\n constructor(type, options = {}) {\n super(type);\n\n this[kError] = options.error === undefined ? null : options.error;\n this[kMessage] = options.message === undefined ? '' : options.message;\n }\n\n /**\n * @type {*}\n */\n get error() {\n return this[kError];\n }\n\n /**\n * @type {String}\n */\n get message() {\n return this[kMessage];\n }\n}\n\nObject.defineProperty(ErrorEvent.prototype, 'error', { enumerable: true });\nObject.defineProperty(ErrorEvent.prototype, 'message', { enumerable: true });\n\n/**\n * Class representing a message event.\n *\n * @extends Event\n */\nclass MessageEvent extends Event {\n /**\n * Create a new `MessageEvent`.\n *\n * @param {String} type The name of the event\n * @param {Object} [options] A dictionary object that allows for setting\n * attributes via object members of the same name\n * @param {*} [options.data=null] The message content\n */\n constructor(type, options = {}) {\n super(type);\n\n this[kData] = options.data === undefined ? null : options.data;\n }\n\n /**\n * @type {*}\n */\n get data() {\n return this[kData];\n }\n}\n\nObject.defineProperty(MessageEvent.prototype, 'data', { enumerable: true });\n\n/**\n * This provides methods for emulating the `EventTarget` interface. It's not\n * meant to be used directly.\n *\n * @mixin\n */\nconst EventTarget = {\n /**\n * Register an event listener.\n *\n * @param {String} type A string representing the event type to listen for\n * @param {(Function|Object)} handler The listener to add\n * @param {Object} [options] An options object specifies characteristics about\n * the event listener\n * @param {Boolean} [options.once=false] A `Boolean` indicating that the\n * listener should be invoked at most once after being added. If `true`,\n * the listener would be automatically removed when invoked.\n * @public\n */\n addEventListener(type, handler, options = {}) {\n for (const listener of this.listeners(type)) {\n if (\n !options[kForOnEventAttribute] &&\n listener[kListener] === handler &&\n !listener[kForOnEventAttribute]\n ) {\n return;\n }\n }\n\n let wrapper;\n\n if (type === 'message') {\n wrapper = function onMessage(data, isBinary) {\n const event = new MessageEvent('message', {\n data: isBinary ? data : data.toString()\n });\n\n event[kTarget] = this;\n callListener(handler, this, event);\n };\n } else if (type === 'close') {\n wrapper = function onClose(code, message) {\n const event = new CloseEvent('close', {\n code,\n reason: message.toString(),\n wasClean: this._closeFrameReceived && this._closeFrameSent\n });\n\n event[kTarget] = this;\n callListener(handler, this, event);\n };\n } else if (type === 'error') {\n wrapper = function onError(error) {\n const event = new ErrorEvent('error', {\n error,\n message: error.message\n });\n\n event[kTarget] = this;\n callListener(handler, this, event);\n };\n } else if (type === 'open') {\n wrapper = function onOpen() {\n const event = new Event('open');\n\n event[kTarget] = this;\n callListener(handler, this, event);\n };\n } else {\n return;\n }\n\n wrapper[kForOnEventAttribute] = !!options[kForOnEventAttribute];\n wrapper[kListener] = handler;\n\n if (options.once) {\n this.once(type, wrapper);\n } else {\n this.on(type, wrapper);\n }\n },\n\n /**\n * Remove an event listener.\n *\n * @param {String} type A string representing the event type to remove\n * @param {(Function|Object)} handler The listener to remove\n * @public\n */\n removeEventListener(type, handler) {\n for (const listener of this.listeners(type)) {\n if (listener[kListener] === handler && !listener[kForOnEventAttribute]) {\n this.removeListener(type, listener);\n break;\n }\n }\n }\n};\n\nmodule.exports = {\n CloseEvent,\n ErrorEvent,\n Event,\n EventTarget,\n MessageEvent\n};\n\n/**\n * Call an event listener\n *\n * @param {(Function|Object)} listener The listener to call\n * @param {*} thisArg The value to use as `this`` when calling the listener\n * @param {Event} event The event to pass to the listener\n * @private\n */\nfunction callListener(listener, thisArg, event) {\n if (typeof listener === 'object' && listener.handleEvent) {\n listener.handleEvent.call(listener, event);\n } else {\n listener.call(thisArg, event);\n }\n}\n","'use strict';\n\nconst { tokenChars } = require('./validation');\n\n/**\n * Adds an offer to the map of extension offers or a parameter to the map of\n * parameters.\n *\n * @param {Object} dest The map of extension offers or parameters\n * @param {String} name The extension or parameter name\n * @param {(Object|Boolean|String)} elem The extension parameters or the\n * parameter value\n * @private\n */\nfunction push(dest, name, elem) {\n if (dest[name] === undefined) dest[name] = [elem];\n else dest[name].push(elem);\n}\n\n/**\n * Parses the `Sec-WebSocket-Extensions` header into an object.\n *\n * @param {String} header The field value of the header\n * @return {Object} The parsed object\n * @public\n */\nfunction parse(header) {\n const offers = Object.create(null);\n let params = Object.create(null);\n let mustUnescape = false;\n let isEscaping = false;\n let inQuotes = false;\n let extensionName;\n let paramName;\n let start = -1;\n let code = -1;\n let end = -1;\n let i = 0;\n\n for (; i < header.length; i++) {\n code = header.charCodeAt(i);\n\n if (extensionName === undefined) {\n if (end === -1 && tokenChars[code] === 1) {\n if (start === -1) start = i;\n } else if (\n i !== 0 &&\n (code === 0x20 /* ' ' */ || code === 0x09) /* '\\t' */\n ) {\n if (end === -1 && start !== -1) end = i;\n } else if (code === 0x3b /* ';' */ || code === 0x2c /* ',' */) {\n if (start === -1) {\n throw new SyntaxError(`Unexpected character at index ${i}`);\n }\n\n if (end === -1) end = i;\n const name = header.slice(start, end);\n if (code === 0x2c) {\n push(offers, name, params);\n params = Object.create(null);\n } else {\n extensionName = name;\n }\n\n start = end = -1;\n } else {\n throw new SyntaxError(`Unexpected character at index ${i}`);\n }\n } else if (paramName === undefined) {\n if (end === -1 && tokenChars[code] === 1) {\n if (start === -1) start = i;\n } else if (code === 0x20 || code === 0x09) {\n if (end === -1 && start !== -1) end = i;\n } else if (code === 0x3b || code === 0x2c) {\n if (start === -1) {\n throw new SyntaxError(`Unexpected character at index ${i}`);\n }\n\n if (end === -1) end = i;\n push(params, header.slice(start, end), true);\n if (code === 0x2c) {\n push(offers, extensionName, params);\n params = Object.create(null);\n extensionName = undefined;\n }\n\n start = end = -1;\n } else if (code === 0x3d /* '=' */ && start !== -1 && end === -1) {\n paramName = header.slice(start, i);\n start = end = -1;\n } else {\n throw new SyntaxError(`Unexpected character at index ${i}`);\n }\n } else {\n //\n // The value of a quoted-string after unescaping must conform to the\n // token ABNF, so only token characters are valid.\n // Ref: https://tools.ietf.org/html/rfc6455#section-9.1\n //\n if (isEscaping) {\n if (tokenChars[code] !== 1) {\n throw new SyntaxError(`Unexpected character at index ${i}`);\n }\n if (start === -1) start = i;\n else if (!mustUnescape) mustUnescape = true;\n isEscaping = false;\n } else if (inQuotes) {\n if (tokenChars[code] === 1) {\n if (start === -1) start = i;\n } else if (code === 0x22 /* '\"' */ && start !== -1) {\n inQuotes = false;\n end = i;\n } else if (code === 0x5c /* '\\' */) {\n isEscaping = true;\n } else {\n throw new SyntaxError(`Unexpected character at index ${i}`);\n }\n } else if (code === 0x22 && header.charCodeAt(i - 1) === 0x3d) {\n inQuotes = true;\n } else if (end === -1 && tokenChars[code] === 1) {\n if (start === -1) start = i;\n } else if (start !== -1 && (code === 0x20 || code === 0x09)) {\n if (end === -1) end = i;\n } else if (code === 0x3b || code === 0x2c) {\n if (start === -1) {\n throw new SyntaxError(`Unexpected character at index ${i}`);\n }\n\n if (end === -1) end = i;\n let value = header.slice(start, end);\n if (mustUnescape) {\n value = value.replace(/\\\\/g, '');\n mustUnescape = false;\n }\n push(params, paramName, value);\n if (code === 0x2c) {\n push(offers, extensionName, params);\n params = Object.create(null);\n extensionName = undefined;\n }\n\n paramName = undefined;\n start = end = -1;\n } else {\n throw new SyntaxError(`Unexpected character at index ${i}`);\n }\n }\n }\n\n if (start === -1 || inQuotes || code === 0x20 || code === 0x09) {\n throw new SyntaxError('Unexpected end of input');\n }\n\n if (end === -1) end = i;\n const token = header.slice(start, end);\n if (extensionName === undefined) {\n push(offers, token, params);\n } else {\n if (paramName === undefined) {\n push(params, token, true);\n } else if (mustUnescape) {\n push(params, paramName, token.replace(/\\\\/g, ''));\n } else {\n push(params, paramName, token);\n }\n push(offers, extensionName, params);\n }\n\n return offers;\n}\n\n/**\n * Builds the `Sec-WebSocket-Extensions` header field value.\n *\n * @param {Object} extensions The map of extensions and parameters to format\n * @return {String} A string representing the given object\n * @public\n */\nfunction format(extensions) {\n return Object.keys(extensions)\n .map((extension) => {\n let configurations = extensions[extension];\n if (!Array.isArray(configurations)) configurations = [configurations];\n return configurations\n .map((params) => {\n return [extension]\n .concat(\n Object.keys(params).map((k) => {\n let values = params[k];\n if (!Array.isArray(values)) values = [values];\n return values\n .map((v) => (v === true ? k : `${k}=${v}`))\n .join('; ');\n })\n )\n .join('; ');\n })\n .join(', ');\n })\n .join(', ');\n}\n\nmodule.exports = { format, parse };\n","/* eslint no-unused-vars: [\"error\", { \"varsIgnorePattern\": \"^Duplex|Readable$\", \"caughtErrors\": \"none\" }] */\n\n'use strict';\n\nconst EventEmitter = require('events');\nconst https = require('https');\nconst http = require('http');\nconst net = require('net');\nconst tls = require('tls');\nconst { randomBytes, createHash } = require('crypto');\nconst { Duplex, Readable } = require('stream');\nconst { URL } = require('url');\n\nconst PerMessageDeflate = require('./permessage-deflate');\nconst Receiver = require('./receiver');\nconst Sender = require('./sender');\nconst { isBlob } = require('./validation');\n\nconst {\n BINARY_TYPES,\n CLOSE_TIMEOUT,\n EMPTY_BUFFER,\n GUID,\n kForOnEventAttribute,\n kListener,\n kStatusCode,\n kWebSocket,\n NOOP\n} = require('./constants');\nconst {\n EventTarget: { addEventListener, removeEventListener }\n} = require('./event-target');\nconst { format, parse } = require('./extension');\nconst { toBuffer } = require('./buffer-util');\n\nconst kAborted = Symbol('kAborted');\nconst protocolVersions = [8, 13];\nconst readyStates = ['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED'];\nconst subprotocolRegex = /^[!#$%&'*+\\-.0-9A-Z^_`|a-z~]+$/;\n\n/**\n * Class representing a WebSocket.\n *\n * @extends EventEmitter\n */\nclass WebSocket extends EventEmitter {\n /**\n * Create a new `WebSocket`.\n *\n * @param {(String|URL)} address The URL to which to connect\n * @param {(String|String[])} [protocols] The subprotocols\n * @param {Object} [options] Connection options\n */\n constructor(address, protocols, options) {\n super();\n\n this._binaryType = BINARY_TYPES[0];\n this._closeCode = 1006;\n this._closeFrameReceived = false;\n this._closeFrameSent = false;\n this._closeMessage = EMPTY_BUFFER;\n this._closeTimer = null;\n this._errorEmitted = false;\n this._extensions = {};\n this._paused = false;\n this._protocol = '';\n this._readyState = WebSocket.CONNECTING;\n this._receiver = null;\n this._sender = null;\n this._socket = null;\n\n if (address !== null) {\n this._bufferedAmount = 0;\n this._isServer = false;\n this._redirects = 0;\n\n if (protocols === undefined) {\n protocols = [];\n } else if (!Array.isArray(protocols)) {\n if (typeof protocols === 'object' && protocols !== null) {\n options = protocols;\n protocols = [];\n } else {\n protocols = [protocols];\n }\n }\n\n initAsClient(this, address, protocols, options);\n } else {\n this._autoPong = options.autoPong;\n this._closeTimeout = options.closeTimeout;\n this._isServer = true;\n }\n }\n\n /**\n * For historical reasons, the custom \"nodebuffer\" type is used by the default\n * instead of \"blob\".\n *\n * @type {String}\n */\n get binaryType() {\n return this._binaryType;\n }\n\n set binaryType(type) {\n if (!BINARY_TYPES.includes(type)) return;\n\n this._binaryType = type;\n\n //\n // Allow to change `binaryType` on the fly.\n //\n if (this._receiver) this._receiver._binaryType = type;\n }\n\n /**\n * @type {Number}\n */\n get bufferedAmount() {\n if (!this._socket) return this._bufferedAmount;\n\n return this._socket._writableState.length + this._sender._bufferedBytes;\n }\n\n /**\n * @type {String}\n */\n get extensions() {\n return Object.keys(this._extensions).join();\n }\n\n /**\n * @type {Boolean}\n */\n get isPaused() {\n return this._paused;\n }\n\n /**\n * @type {Function}\n */\n /* istanbul ignore next */\n get onclose() {\n return null;\n }\n\n /**\n * @type {Function}\n */\n /* istanbul ignore next */\n get onerror() {\n return null;\n }\n\n /**\n * @type {Function}\n */\n /* istanbul ignore next */\n get onopen() {\n return null;\n }\n\n /**\n * @type {Function}\n */\n /* istanbul ignore next */\n get onmessage() {\n return null;\n }\n\n /**\n * @type {String}\n */\n get protocol() {\n return this._protocol;\n }\n\n /**\n * @type {Number}\n */\n get readyState() {\n return this._readyState;\n }\n\n /**\n * @type {String}\n */\n get url() {\n return this._url;\n }\n\n /**\n * Set up the socket and the internal resources.\n *\n * @param {Duplex} socket The network socket between the server and client\n * @param {Buffer} head The first packet of the upgraded stream\n * @param {Object} options Options object\n * @param {Boolean} [options.allowSynchronousEvents=false] Specifies whether\n * any of the `'message'`, `'ping'`, and `'pong'` events can be emitted\n * multiple times in the same tick\n * @param {Function} [options.generateMask] The function used to generate the\n * masking key\n * @param {Number} [options.maxPayload=0] The maximum allowed message size\n * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or\n * not to skip UTF-8 validation for text and close messages\n * @private\n */\n setSocket(socket, head, options) {\n const receiver = new Receiver({\n allowSynchronousEvents: options.allowSynchronousEvents,\n binaryType: this.binaryType,\n extensions: this._extensions,\n isServer: this._isServer,\n maxPayload: options.maxPayload,\n skipUTF8Validation: options.skipUTF8Validation\n });\n\n const sender = new Sender(socket, this._extensions, options.generateMask);\n\n this._receiver = receiver;\n this._sender = sender;\n this._socket = socket;\n\n receiver[kWebSocket] = this;\n sender[kWebSocket] = this;\n socket[kWebSocket] = this;\n\n receiver.on('conclude', receiverOnConclude);\n receiver.on('drain', receiverOnDrain);\n receiver.on('error', receiverOnError);\n receiver.on('message', receiverOnMessage);\n receiver.on('ping', receiverOnPing);\n receiver.on('pong', receiverOnPong);\n\n sender.onerror = senderOnError;\n\n //\n // These methods may not be available if `socket` is just a `Duplex`.\n //\n if (socket.setTimeout) socket.setTimeout(0);\n if (socket.setNoDelay) socket.setNoDelay();\n\n if (head.length > 0) socket.unshift(head);\n\n socket.on('close', socketOnClose);\n socket.on('data', socketOnData);\n socket.on('end', socketOnEnd);\n socket.on('error', socketOnError);\n\n this._readyState = WebSocket.OPEN;\n this.emit('open');\n }\n\n /**\n * Emit the `'close'` event.\n *\n * @private\n */\n emitClose() {\n if (!this._socket) {\n this._readyState = WebSocket.CLOSED;\n this.emit('close', this._closeCode, this._closeMessage);\n return;\n }\n\n if (this._extensions[PerMessageDeflate.extensionName]) {\n this._extensions[PerMessageDeflate.extensionName].cleanup();\n }\n\n this._receiver.removeAllListeners();\n this._readyState = WebSocket.CLOSED;\n this.emit('close', this._closeCode, this._closeMessage);\n }\n\n /**\n * Start a closing handshake.\n *\n * +----------+ +-----------+ +----------+\n * - - -|ws.close()|-->|close frame|-->|ws.close()|- - -\n * | +----------+ +-----------+ +----------+ |\n * +----------+ +-----------+ |\n * CLOSING |ws.close()|<--|close frame|<--+-----+ CLOSING\n * +----------+ +-----------+ |\n * | | | +---+ |\n * +------------------------+-->|fin| - - - -\n * | +---+ | +---+\n * - - - - -|fin|<---------------------+\n * +---+\n *\n * @param {Number} [code] Status code explaining why the connection is closing\n * @param {(String|Buffer)} [data] The reason why the connection is\n * closing\n * @public\n */\n close(code, data) {\n if (this.readyState === WebSocket.CLOSED) return;\n if (this.readyState === WebSocket.CONNECTING) {\n const msg = 'WebSocket was closed before the connection was established';\n abortHandshake(this, this._req, msg);\n return;\n }\n\n if (this.readyState === WebSocket.CLOSING) {\n if (\n this._closeFrameSent &&\n (this._closeFrameReceived || this._receiver._writableState.errorEmitted)\n ) {\n this._socket.end();\n }\n\n return;\n }\n\n this._readyState = WebSocket.CLOSING;\n this._sender.close(code, data, !this._isServer, (err) => {\n //\n // This error is handled by the `'error'` listener on the socket. We only\n // want to know if the close frame has been sent here.\n //\n if (err) return;\n\n this._closeFrameSent = true;\n\n if (\n this._closeFrameReceived ||\n this._receiver._writableState.errorEmitted\n ) {\n this._socket.end();\n }\n });\n\n setCloseTimer(this);\n }\n\n /**\n * Pause the socket.\n *\n * @public\n */\n pause() {\n if (\n this.readyState === WebSocket.CONNECTING ||\n this.readyState === WebSocket.CLOSED\n ) {\n return;\n }\n\n this._paused = true;\n this._socket.pause();\n }\n\n /**\n * Send a ping.\n *\n * @param {*} [data] The data to send\n * @param {Boolean} [mask] Indicates whether or not to mask `data`\n * @param {Function} [cb] Callback which is executed when the ping is sent\n * @public\n */\n ping(data, mask, cb) {\n if (this.readyState === WebSocket.CONNECTING) {\n throw new Error('WebSocket is not open: readyState 0 (CONNECTING)');\n }\n\n if (typeof data === 'function') {\n cb = data;\n data = mask = undefined;\n } else if (typeof mask === 'function') {\n cb = mask;\n mask = undefined;\n }\n\n if (typeof data === 'number') data = data.toString();\n\n if (this.readyState !== WebSocket.OPEN) {\n sendAfterClose(this, data, cb);\n return;\n }\n\n if (mask === undefined) mask = !this._isServer;\n this._sender.ping(data || EMPTY_BUFFER, mask, cb);\n }\n\n /**\n * Send a pong.\n *\n * @param {*} [data] The data to send\n * @param {Boolean} [mask] Indicates whether or not to mask `data`\n * @param {Function} [cb] Callback which is executed when the pong is sent\n * @public\n */\n pong(data, mask, cb) {\n if (this.readyState === WebSocket.CONNECTING) {\n throw new Error('WebSocket is not open: readyState 0 (CONNECTING)');\n }\n\n if (typeof data === 'function') {\n cb = data;\n data = mask = undefined;\n } else if (typeof mask === 'function') {\n cb = mask;\n mask = undefined;\n }\n\n if (typeof data === 'number') data = data.toString();\n\n if (this.readyState !== WebSocket.OPEN) {\n sendAfterClose(this, data, cb);\n return;\n }\n\n if (mask === undefined) mask = !this._isServer;\n this._sender.pong(data || EMPTY_BUFFER, mask, cb);\n }\n\n /**\n * Resume the socket.\n *\n * @public\n */\n resume() {\n if (\n this.readyState === WebSocket.CONNECTING ||\n this.readyState === WebSocket.CLOSED\n ) {\n return;\n }\n\n this._paused = false;\n if (!this._receiver._writableState.needDrain) this._socket.resume();\n }\n\n /**\n * Send a data message.\n *\n * @param {*} data The message to send\n * @param {Object} [options] Options object\n * @param {Boolean} [options.binary] Specifies whether `data` is binary or\n * text\n * @param {Boolean} [options.compress] Specifies whether or not to compress\n * `data`\n * @param {Boolean} [options.fin=true] Specifies whether the fragment is the\n * last one\n * @param {Boolean} [options.mask] Specifies whether or not to mask `data`\n * @param {Function} [cb] Callback which is executed when data is written out\n * @public\n */\n send(data, options, cb) {\n if (this.readyState === WebSocket.CONNECTING) {\n throw new Error('WebSocket is not open: readyState 0 (CONNECTING)');\n }\n\n if (typeof options === 'function') {\n cb = options;\n options = {};\n }\n\n if (typeof data === 'number') data = data.toString();\n\n if (this.readyState !== WebSocket.OPEN) {\n sendAfterClose(this, data, cb);\n return;\n }\n\n const opts = {\n binary: typeof data !== 'string',\n mask: !this._isServer,\n compress: true,\n fin: true,\n ...options\n };\n\n if (!this._extensions[PerMessageDeflate.extensionName]) {\n opts.compress = false;\n }\n\n this._sender.send(data || EMPTY_BUFFER, opts, cb);\n }\n\n /**\n * Forcibly close the connection.\n *\n * @public\n */\n terminate() {\n if (this.readyState === WebSocket.CLOSED) return;\n if (this.readyState === WebSocket.CONNECTING) {\n const msg = 'WebSocket was closed before the connection was established';\n abortHandshake(this, this._req, msg);\n return;\n }\n\n if (this._socket) {\n this._readyState = WebSocket.CLOSING;\n this._socket.destroy();\n }\n }\n}\n\n/**\n * @constant {Number} CONNECTING\n * @memberof WebSocket\n */\nObject.defineProperty(WebSocket, 'CONNECTING', {\n enumerable: true,\n value: readyStates.indexOf('CONNECTING')\n});\n\n/**\n * @constant {Number} CONNECTING\n * @memberof WebSocket.prototype\n */\nObject.defineProperty(WebSocket.prototype, 'CONNECTING', {\n enumerable: true,\n value: readyStates.indexOf('CONNECTING')\n});\n\n/**\n * @constant {Number} OPEN\n * @memberof WebSocket\n */\nObject.defineProperty(WebSocket, 'OPEN', {\n enumerable: true,\n value: readyStates.indexOf('OPEN')\n});\n\n/**\n * @constant {Number} OPEN\n * @memberof WebSocket.prototype\n */\nObject.defineProperty(WebSocket.prototype, 'OPEN', {\n enumerable: true,\n value: readyStates.indexOf('OPEN')\n});\n\n/**\n * @constant {Number} CLOSING\n * @memberof WebSocket\n */\nObject.defineProperty(WebSocket, 'CLOSING', {\n enumerable: true,\n value: readyStates.indexOf('CLOSING')\n});\n\n/**\n * @constant {Number} CLOSING\n * @memberof WebSocket.prototype\n */\nObject.defineProperty(WebSocket.prototype, 'CLOSING', {\n enumerable: true,\n value: readyStates.indexOf('CLOSING')\n});\n\n/**\n * @constant {Number} CLOSED\n * @memberof WebSocket\n */\nObject.defineProperty(WebSocket, 'CLOSED', {\n enumerable: true,\n value: readyStates.indexOf('CLOSED')\n});\n\n/**\n * @constant {Number} CLOSED\n * @memberof WebSocket.prototype\n */\nObject.defineProperty(WebSocket.prototype, 'CLOSED', {\n enumerable: true,\n value: readyStates.indexOf('CLOSED')\n});\n\n[\n 'binaryType',\n 'bufferedAmount',\n 'extensions',\n 'isPaused',\n 'protocol',\n 'readyState',\n 'url'\n].forEach((property) => {\n Object.defineProperty(WebSocket.prototype, property, { enumerable: true });\n});\n\n//\n// Add the `onopen`, `onerror`, `onclose`, and `onmessage` attributes.\n// See https://html.spec.whatwg.org/multipage/comms.html#the-websocket-interface\n//\n['open', 'error', 'close', 'message'].forEach((method) => {\n Object.defineProperty(WebSocket.prototype, `on${method}`, {\n enumerable: true,\n get() {\n for (const listener of this.listeners(method)) {\n if (listener[kForOnEventAttribute]) return listener[kListener];\n }\n\n return null;\n },\n set(handler) {\n for (const listener of this.listeners(method)) {\n if (listener[kForOnEventAttribute]) {\n this.removeListener(method, listener);\n break;\n }\n }\n\n if (typeof handler !== 'function') return;\n\n this.addEventListener(method, handler, {\n [kForOnEventAttribute]: true\n });\n }\n });\n});\n\nWebSocket.prototype.addEventListener = addEventListener;\nWebSocket.prototype.removeEventListener = removeEventListener;\n\nmodule.exports = WebSocket;\n\n/**\n * Initialize a WebSocket client.\n *\n * @param {WebSocket} websocket The client to initialize\n * @param {(String|URL)} address The URL to which to connect\n * @param {Array} protocols The subprotocols\n * @param {Object} [options] Connection options\n * @param {Boolean} [options.allowSynchronousEvents=true] Specifies whether any\n * of the `'message'`, `'ping'`, and `'pong'` events can be emitted multiple\n * times in the same tick\n * @param {Boolean} [options.autoPong=true] Specifies whether or not to\n * automatically send a pong in response to a ping\n * @param {Number} [options.closeTimeout=30000] Duration in milliseconds to wait\n * for the closing handshake to finish after `websocket.close()` is called\n * @param {Function} [options.finishRequest] A function which can be used to\n * customize the headers of each http request before it is sent\n * @param {Boolean} [options.followRedirects=false] Whether or not to follow\n * redirects\n * @param {Function} [options.generateMask] The function used to generate the\n * masking key\n * @param {Number} [options.handshakeTimeout] Timeout in milliseconds for the\n * handshake request\n * @param {Number} [options.maxPayload=104857600] The maximum allowed message\n * size\n * @param {Number} [options.maxRedirects=10] The maximum number of redirects\n * allowed\n * @param {String} [options.origin] Value of the `Origin` or\n * `Sec-WebSocket-Origin` header\n * @param {(Boolean|Object)} [options.perMessageDeflate=true] Enable/disable\n * permessage-deflate\n * @param {Number} [options.protocolVersion=13] Value of the\n * `Sec-WebSocket-Version` header\n * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or\n * not to skip UTF-8 validation for text and close messages\n * @private\n */\nfunction initAsClient(websocket, address, protocols, options) {\n const opts = {\n allowSynchronousEvents: true,\n autoPong: true,\n closeTimeout: CLOSE_TIMEOUT,\n protocolVersion: protocolVersions[1],\n maxPayload: 100 * 1024 * 1024,\n skipUTF8Validation: false,\n perMessageDeflate: true,\n followRedirects: false,\n maxRedirects: 10,\n ...options,\n socketPath: undefined,\n hostname: undefined,\n protocol: undefined,\n timeout: undefined,\n method: 'GET',\n host: undefined,\n path: undefined,\n port: undefined\n };\n\n websocket._autoPong = opts.autoPong;\n websocket._closeTimeout = opts.closeTimeout;\n\n if (!protocolVersions.includes(opts.protocolVersion)) {\n throw new RangeError(\n `Unsupported protocol version: ${opts.protocolVersion} ` +\n `(supported versions: ${protocolVersions.join(', ')})`\n );\n }\n\n let parsedUrl;\n\n if (address instanceof URL) {\n parsedUrl = address;\n } else {\n try {\n parsedUrl = new URL(address);\n } catch (e) {\n throw new SyntaxError(`Invalid URL: ${address}`);\n }\n }\n\n if (parsedUrl.protocol === 'http:') {\n parsedUrl.protocol = 'ws:';\n } else if (parsedUrl.protocol === 'https:') {\n parsedUrl.protocol = 'wss:';\n }\n\n websocket._url = parsedUrl.href;\n\n const isSecure = parsedUrl.protocol === 'wss:';\n const isIpcUrl = parsedUrl.protocol === 'ws+unix:';\n let invalidUrlMessage;\n\n if (parsedUrl.protocol !== 'ws:' && !isSecure && !isIpcUrl) {\n invalidUrlMessage =\n 'The URL\\'s protocol must be one of \"ws:\", \"wss:\", ' +\n '\"http:\", \"https:\", or \"ws+unix:\"';\n } else if (isIpcUrl && !parsedUrl.pathname) {\n invalidUrlMessage = \"The URL's pathname is empty\";\n } else if (parsedUrl.hash) {\n invalidUrlMessage = 'The URL contains a fragment identifier';\n }\n\n if (invalidUrlMessage) {\n const err = new SyntaxError(invalidUrlMessage);\n\n if (websocket._redirects === 0) {\n throw err;\n } else {\n emitErrorAndClose(websocket, err);\n return;\n }\n }\n\n const defaultPort = isSecure ? 443 : 80;\n const key = randomBytes(16).toString('base64');\n const request = isSecure ? https.request : http.request;\n const protocolSet = new Set();\n let perMessageDeflate;\n\n opts.createConnection =\n opts.createConnection || (isSecure ? tlsConnect : netConnect);\n opts.defaultPort = opts.defaultPort || defaultPort;\n opts.port = parsedUrl.port || defaultPort;\n opts.host = parsedUrl.hostname.startsWith('[')\n ? parsedUrl.hostname.slice(1, -1)\n : parsedUrl.hostname;\n opts.headers = {\n ...opts.headers,\n 'Sec-WebSocket-Version': opts.protocolVersion,\n 'Sec-WebSocket-Key': key,\n Connection: 'Upgrade',\n Upgrade: 'websocket'\n };\n opts.path = parsedUrl.pathname + parsedUrl.search;\n opts.timeout = opts.handshakeTimeout;\n\n if (opts.perMessageDeflate) {\n perMessageDeflate = new PerMessageDeflate(\n opts.perMessageDeflate !== true ? opts.perMessageDeflate : {},\n false,\n opts.maxPayload\n );\n opts.headers['Sec-WebSocket-Extensions'] = format({\n [PerMessageDeflate.extensionName]: perMessageDeflate.offer()\n });\n }\n if (protocols.length) {\n for (const protocol of protocols) {\n if (\n typeof protocol !== 'string' ||\n !subprotocolRegex.test(protocol) ||\n protocolSet.has(protocol)\n ) {\n throw new SyntaxError(\n 'An invalid or duplicated subprotocol was specified'\n );\n }\n\n protocolSet.add(protocol);\n }\n\n opts.headers['Sec-WebSocket-Protocol'] = protocols.join(',');\n }\n if (opts.origin) {\n if (opts.protocolVersion < 13) {\n opts.headers['Sec-WebSocket-Origin'] = opts.origin;\n } else {\n opts.headers.Origin = opts.origin;\n }\n }\n if (parsedUrl.username || parsedUrl.password) {\n opts.auth = `${parsedUrl.username}:${parsedUrl.password}`;\n }\n\n if (isIpcUrl) {\n const parts = opts.path.split(':');\n\n opts.socketPath = parts[0];\n opts.path = parts[1];\n }\n\n let req;\n\n if (opts.followRedirects) {\n if (websocket._redirects === 0) {\n websocket._originalIpc = isIpcUrl;\n websocket._originalSecure = isSecure;\n websocket._originalHostOrSocketPath = isIpcUrl\n ? opts.socketPath\n : parsedUrl.host;\n\n const headers = options && options.headers;\n\n //\n // Shallow copy the user provided options so that headers can be changed\n // without mutating the original object.\n //\n options = { ...options, headers: {} };\n\n if (headers) {\n for (const [key, value] of Object.entries(headers)) {\n options.headers[key.toLowerCase()] = value;\n }\n }\n } else if (websocket.listenerCount('redirect') === 0) {\n const isSameHost = isIpcUrl\n ? websocket._originalIpc\n ? opts.socketPath === websocket._originalHostOrSocketPath\n : false\n : websocket._originalIpc\n ? false\n : parsedUrl.host === websocket._originalHostOrSocketPath;\n\n if (!isSameHost || (websocket._originalSecure && !isSecure)) {\n //\n // Match curl 7.77.0 behavior and drop the following headers. These\n // headers are also dropped when following a redirect to a subdomain.\n //\n delete opts.headers.authorization;\n delete opts.headers.cookie;\n\n if (!isSameHost) delete opts.headers.host;\n\n opts.auth = undefined;\n }\n }\n\n //\n // Match curl 7.77.0 behavior and make the first `Authorization` header win.\n // If the `Authorization` header is set, then there is nothing to do as it\n // will take precedence.\n //\n if (opts.auth && !options.headers.authorization) {\n options.headers.authorization =\n 'Basic ' + Buffer.from(opts.auth).toString('base64');\n }\n\n req = websocket._req = request(opts);\n\n if (websocket._redirects) {\n //\n // Unlike what is done for the `'upgrade'` event, no early exit is\n // triggered here if the user calls `websocket.close()` or\n // `websocket.terminate()` from a listener of the `'redirect'` event. This\n // is because the user can also call `request.destroy()` with an error\n // before calling `websocket.close()` or `websocket.terminate()` and this\n // would result in an error being emitted on the `request` object with no\n // `'error'` event listeners attached.\n //\n websocket.emit('redirect', websocket.url, req);\n }\n } else {\n req = websocket._req = request(opts);\n }\n\n if (opts.timeout) {\n req.on('timeout', () => {\n abortHandshake(websocket, req, 'Opening handshake has timed out');\n });\n }\n\n req.on('error', (err) => {\n if (req === null || req[kAborted]) return;\n\n req = websocket._req = null;\n emitErrorAndClose(websocket, err);\n });\n\n req.on('response', (res) => {\n const location = res.headers.location;\n const statusCode = res.statusCode;\n\n if (\n location &&\n opts.followRedirects &&\n statusCode >= 300 &&\n statusCode < 400\n ) {\n if (++websocket._redirects > opts.maxRedirects) {\n abortHandshake(websocket, req, 'Maximum redirects exceeded');\n return;\n }\n\n req.abort();\n\n let addr;\n\n try {\n addr = new URL(location, address);\n } catch (e) {\n const err = new SyntaxError(`Invalid URL: ${location}`);\n emitErrorAndClose(websocket, err);\n return;\n }\n\n initAsClient(websocket, addr, protocols, options);\n } else if (!websocket.emit('unexpected-response', req, res)) {\n abortHandshake(\n websocket,\n req,\n `Unexpected server response: ${res.statusCode}`\n );\n }\n });\n\n req.on('upgrade', (res, socket, head) => {\n websocket.emit('upgrade', res);\n\n //\n // The user may have closed the connection from a listener of the\n // `'upgrade'` event.\n //\n if (websocket.readyState !== WebSocket.CONNECTING) return;\n\n req = websocket._req = null;\n\n const upgrade = res.headers.upgrade;\n\n if (upgrade === undefined || upgrade.toLowerCase() !== 'websocket') {\n abortHandshake(websocket, socket, 'Invalid Upgrade header');\n return;\n }\n\n const digest = createHash('sha1')\n .update(key + GUID)\n .digest('base64');\n\n if (res.headers['sec-websocket-accept'] !== digest) {\n abortHandshake(websocket, socket, 'Invalid Sec-WebSocket-Accept header');\n return;\n }\n\n const serverProt = res.headers['sec-websocket-protocol'];\n let protError;\n\n if (serverProt !== undefined) {\n if (!protocolSet.size) {\n protError = 'Server sent a subprotocol but none was requested';\n } else if (!protocolSet.has(serverProt)) {\n protError = 'Server sent an invalid subprotocol';\n }\n } else if (protocolSet.size) {\n protError = 'Server sent no subprotocol';\n }\n\n if (protError) {\n abortHandshake(websocket, socket, protError);\n return;\n }\n\n if (serverProt) websocket._protocol = serverProt;\n\n const secWebSocketExtensions = res.headers['sec-websocket-extensions'];\n\n if (secWebSocketExtensions !== undefined) {\n if (!perMessageDeflate) {\n const message =\n 'Server sent a Sec-WebSocket-Extensions header but no extension ' +\n 'was requested';\n abortHandshake(websocket, socket, message);\n return;\n }\n\n let extensions;\n\n try {\n extensions = parse(secWebSocketExtensions);\n } catch (err) {\n const message = 'Invalid Sec-WebSocket-Extensions header';\n abortHandshake(websocket, socket, message);\n return;\n }\n\n const extensionNames = Object.keys(extensions);\n\n if (\n extensionNames.length !== 1 ||\n extensionNames[0] !== PerMessageDeflate.extensionName\n ) {\n const message = 'Server indicated an extension that was not requested';\n abortHandshake(websocket, socket, message);\n return;\n }\n\n try {\n perMessageDeflate.accept(extensions[PerMessageDeflate.extensionName]);\n } catch (err) {\n const message = 'Invalid Sec-WebSocket-Extensions header';\n abortHandshake(websocket, socket, message);\n return;\n }\n\n websocket._extensions[PerMessageDeflate.extensionName] =\n perMessageDeflate;\n }\n\n websocket.setSocket(socket, head, {\n allowSynchronousEvents: opts.allowSynchronousEvents,\n generateMask: opts.generateMask,\n maxPayload: opts.maxPayload,\n skipUTF8Validation: opts.skipUTF8Validation\n });\n });\n\n if (opts.finishRequest) {\n opts.finishRequest(req, websocket);\n } else {\n req.end();\n }\n}\n\n/**\n * Emit the `'error'` and `'close'` events.\n *\n * @param {WebSocket} websocket The WebSocket instance\n * @param {Error} The error to emit\n * @private\n */\nfunction emitErrorAndClose(websocket, err) {\n websocket._readyState = WebSocket.CLOSING;\n //\n // The following assignment is practically useless and is done only for\n // consistency.\n //\n websocket._errorEmitted = true;\n websocket.emit('error', err);\n websocket.emitClose();\n}\n\n/**\n * Create a `net.Socket` and initiate a connection.\n *\n * @param {Object} options Connection options\n * @return {net.Socket} The newly created socket used to start the connection\n * @private\n */\nfunction netConnect(options) {\n options.path = options.socketPath;\n return net.connect(options);\n}\n\n/**\n * Create a `tls.TLSSocket` and initiate a connection.\n *\n * @param {Object} options Connection options\n * @return {tls.TLSSocket} The newly created socket used to start the connection\n * @private\n */\nfunction tlsConnect(options) {\n options.path = undefined;\n\n if (!options.servername && options.servername !== '') {\n options.servername = net.isIP(options.host) ? '' : options.host;\n }\n\n return tls.connect(options);\n}\n\n/**\n * Abort the handshake and emit an error.\n *\n * @param {WebSocket} websocket The WebSocket instance\n * @param {(http.ClientRequest|net.Socket|tls.Socket)} stream The request to\n * abort or the socket to destroy\n * @param {String} message The error message\n * @private\n */\nfunction abortHandshake(websocket, stream, message) {\n websocket._readyState = WebSocket.CLOSING;\n\n const err = new Error(message);\n Error.captureStackTrace(err, abortHandshake);\n\n if (stream.setHeader) {\n stream[kAborted] = true;\n stream.abort();\n\n if (stream.socket && !stream.socket.destroyed) {\n //\n // On Node.js >= 14.3.0 `request.abort()` does not destroy the socket if\n // called after the request completed. See\n // https://github.com/websockets/ws/issues/1869.\n //\n stream.socket.destroy();\n }\n\n process.nextTick(emitErrorAndClose, websocket, err);\n } else {\n stream.destroy(err);\n stream.once('error', websocket.emit.bind(websocket, 'error'));\n stream.once('close', websocket.emitClose.bind(websocket));\n }\n}\n\n/**\n * Handle cases where the `ping()`, `pong()`, or `send()` methods are called\n * when the `readyState` attribute is `CLOSING` or `CLOSED`.\n *\n * @param {WebSocket} websocket The WebSocket instance\n * @param {*} [data] The data to send\n * @param {Function} [cb] Callback\n * @private\n */\nfunction sendAfterClose(websocket, data, cb) {\n if (data) {\n const length = isBlob(data) ? data.size : toBuffer(data).length;\n\n //\n // The `_bufferedAmount` property is used only when the peer is a client and\n // the opening handshake fails. Under these circumstances, in fact, the\n // `setSocket()` method is not called, so the `_socket` and `_sender`\n // properties are set to `null`.\n //\n if (websocket._socket) websocket._sender._bufferedBytes += length;\n else websocket._bufferedAmount += length;\n }\n\n if (cb) {\n const err = new Error(\n `WebSocket is not open: readyState ${websocket.readyState} ` +\n `(${readyStates[websocket.readyState]})`\n );\n process.nextTick(cb, err);\n }\n}\n\n/**\n * The listener of the `Receiver` `'conclude'` event.\n *\n * @param {Number} code The status code\n * @param {Buffer} reason The reason for closing\n * @private\n */\nfunction receiverOnConclude(code, reason) {\n const websocket = this[kWebSocket];\n\n websocket._closeFrameReceived = true;\n websocket._closeMessage = reason;\n websocket._closeCode = code;\n\n if (websocket._socket[kWebSocket] === undefined) return;\n\n websocket._socket.removeListener('data', socketOnData);\n process.nextTick(resume, websocket._socket);\n\n if (code === 1005) websocket.close();\n else websocket.close(code, reason);\n}\n\n/**\n * The listener of the `Receiver` `'drain'` event.\n *\n * @private\n */\nfunction receiverOnDrain() {\n const websocket = this[kWebSocket];\n\n if (!websocket.isPaused) websocket._socket.resume();\n}\n\n/**\n * The listener of the `Receiver` `'error'` event.\n *\n * @param {(RangeError|Error)} err The emitted error\n * @private\n */\nfunction receiverOnError(err) {\n const websocket = this[kWebSocket];\n\n if (websocket._socket[kWebSocket] !== undefined) {\n websocket._socket.removeListener('data', socketOnData);\n\n //\n // On Node.js < 14.0.0 the `'error'` event is emitted synchronously. See\n // https://github.com/websockets/ws/issues/1940.\n //\n process.nextTick(resume, websocket._socket);\n\n websocket.close(err[kStatusCode]);\n }\n\n if (!websocket._errorEmitted) {\n websocket._errorEmitted = true;\n websocket.emit('error', err);\n }\n}\n\n/**\n * The listener of the `Receiver` `'finish'` event.\n *\n * @private\n */\nfunction receiverOnFinish() {\n this[kWebSocket].emitClose();\n}\n\n/**\n * The listener of the `Receiver` `'message'` event.\n *\n * @param {Buffer|ArrayBuffer|Buffer[])} data The message\n * @param {Boolean} isBinary Specifies whether the message is binary or not\n * @private\n */\nfunction receiverOnMessage(data, isBinary) {\n this[kWebSocket].emit('message', data, isBinary);\n}\n\n/**\n * The listener of the `Receiver` `'ping'` event.\n *\n * @param {Buffer} data The data included in the ping frame\n * @private\n */\nfunction receiverOnPing(data) {\n const websocket = this[kWebSocket];\n\n if (websocket._autoPong) websocket.pong(data, !this._isServer, NOOP);\n websocket.emit('ping', data);\n}\n\n/**\n * The listener of the `Receiver` `'pong'` event.\n *\n * @param {Buffer} data The data included in the pong frame\n * @private\n */\nfunction receiverOnPong(data) {\n this[kWebSocket].emit('pong', data);\n}\n\n/**\n * Resume a readable stream\n *\n * @param {Readable} stream The readable stream\n * @private\n */\nfunction resume(stream) {\n stream.resume();\n}\n\n/**\n * The `Sender` error event handler.\n *\n * @param {Error} The error\n * @private\n */\nfunction senderOnError(err) {\n const websocket = this[kWebSocket];\n\n if (websocket.readyState === WebSocket.CLOSED) return;\n if (websocket.readyState === WebSocket.OPEN) {\n websocket._readyState = WebSocket.CLOSING;\n setCloseTimer(websocket);\n }\n\n //\n // `socket.end()` is used instead of `socket.destroy()` to allow the other\n // peer to finish sending queued data. There is no need to set a timer here\n // because `CLOSING` means that it is already set or not needed.\n //\n this._socket.end();\n\n if (!websocket._errorEmitted) {\n websocket._errorEmitted = true;\n websocket.emit('error', err);\n }\n}\n\n/**\n * Set a timer to destroy the underlying raw socket of a WebSocket.\n *\n * @param {WebSocket} websocket The WebSocket instance\n * @private\n */\nfunction setCloseTimer(websocket) {\n websocket._closeTimer = setTimeout(\n websocket._socket.destroy.bind(websocket._socket),\n websocket._closeTimeout\n );\n}\n\n/**\n * The listener of the socket `'close'` event.\n *\n * @private\n */\nfunction socketOnClose() {\n const websocket = this[kWebSocket];\n\n this.removeListener('close', socketOnClose);\n this.removeListener('data', socketOnData);\n this.removeListener('end', socketOnEnd);\n\n websocket._readyState = WebSocket.CLOSING;\n\n //\n // The close frame might not have been received or the `'end'` event emitted,\n // for example, if the socket was destroyed due to an error. Ensure that the\n // `receiver` stream is closed after writing any remaining buffered data to\n // it. If the readable side of the socket is in flowing mode then there is no\n // buffered data as everything has been already written. If instead, the\n // socket is paused, any possible buffered data will be read as a single\n // chunk.\n //\n if (\n !this._readableState.endEmitted &&\n !websocket._closeFrameReceived &&\n !websocket._receiver._writableState.errorEmitted &&\n this._readableState.length !== 0\n ) {\n const chunk = this.read(this._readableState.length);\n\n websocket._receiver.write(chunk);\n }\n\n websocket._receiver.end();\n\n this[kWebSocket] = undefined;\n\n clearTimeout(websocket._closeTimer);\n\n if (\n websocket._receiver._writableState.finished ||\n websocket._receiver._writableState.errorEmitted\n ) {\n websocket.emitClose();\n } else {\n websocket._receiver.on('error', receiverOnFinish);\n websocket._receiver.on('finish', receiverOnFinish);\n }\n}\n\n/**\n * The listener of the socket `'data'` event.\n *\n * @param {Buffer} chunk A chunk of data\n * @private\n */\nfunction socketOnData(chunk) {\n if (!this[kWebSocket]._receiver.write(chunk)) {\n this.pause();\n }\n}\n\n/**\n * The listener of the socket `'end'` event.\n *\n * @private\n */\nfunction socketOnEnd() {\n const websocket = this[kWebSocket];\n\n websocket._readyState = WebSocket.CLOSING;\n websocket._receiver.end();\n this.end();\n}\n\n/**\n * The listener of the socket `'error'` event.\n *\n * @private\n */\nfunction socketOnError() {\n const websocket = this[kWebSocket];\n\n this.removeListener('error', socketOnError);\n this.on('error', NOOP);\n\n if (websocket) {\n websocket._readyState = WebSocket.CLOSING;\n this.destroy();\n }\n}\n","/* eslint no-unused-vars: [\"error\", { \"varsIgnorePattern\": \"^WebSocket$\" }] */\n'use strict';\n\nconst WebSocket = require('./websocket');\nconst { Duplex } = require('stream');\n\n/**\n * Emits the `'close'` event on a stream.\n *\n * @param {Duplex} stream The stream.\n * @private\n */\nfunction emitClose(stream) {\n stream.emit('close');\n}\n\n/**\n * The listener of the `'end'` event.\n *\n * @private\n */\nfunction duplexOnEnd() {\n if (!this.destroyed && this._writableState.finished) {\n this.destroy();\n }\n}\n\n/**\n * The listener of the `'error'` event.\n *\n * @param {Error} err The error\n * @private\n */\nfunction duplexOnError(err) {\n this.removeListener('error', duplexOnError);\n this.destroy();\n if (this.listenerCount('error') === 0) {\n // Do not suppress the throwing behavior.\n this.emit('error', err);\n }\n}\n\n/**\n * Wraps a `WebSocket` in a duplex stream.\n *\n * @param {WebSocket} ws The `WebSocket` to wrap\n * @param {Object} [options] The options for the `Duplex` constructor\n * @return {Duplex} The duplex stream\n * @public\n */\nfunction createWebSocketStream(ws, options) {\n let terminateOnDestroy = true;\n\n const duplex = new Duplex({\n ...options,\n autoDestroy: false,\n emitClose: false,\n objectMode: false,\n writableObjectMode: false\n });\n\n ws.on('message', function message(msg, isBinary) {\n const data =\n !isBinary && duplex._readableState.objectMode ? msg.toString() : msg;\n\n if (!duplex.push(data)) ws.pause();\n });\n\n ws.once('error', function error(err) {\n if (duplex.destroyed) return;\n\n // Prevent `ws.terminate()` from being called by `duplex._destroy()`.\n //\n // - If the `'error'` event is emitted before the `'open'` event, then\n // `ws.terminate()` is a noop as no socket is assigned.\n // - Otherwise, the error is re-emitted by the listener of the `'error'`\n // event of the `Receiver` object. The listener already closes the\n // connection by calling `ws.close()`. This allows a close frame to be\n // sent to the other peer. If `ws.terminate()` is called right after this,\n // then the close frame might not be sent.\n terminateOnDestroy = false;\n duplex.destroy(err);\n });\n\n ws.once('close', function close() {\n if (duplex.destroyed) return;\n\n duplex.push(null);\n });\n\n duplex._destroy = function (err, callback) {\n if (ws.readyState === ws.CLOSED) {\n callback(err);\n process.nextTick(emitClose, duplex);\n return;\n }\n\n let called = false;\n\n ws.once('error', function error(err) {\n called = true;\n callback(err);\n });\n\n ws.once('close', function close() {\n if (!called) callback(err);\n process.nextTick(emitClose, duplex);\n });\n\n if (terminateOnDestroy) ws.terminate();\n };\n\n duplex._final = function (callback) {\n if (ws.readyState === ws.CONNECTING) {\n ws.once('open', function open() {\n duplex._final(callback);\n });\n return;\n }\n\n // If the value of the `_socket` property is `null` it means that `ws` is a\n // client websocket and the handshake failed. In fact, when this happens, a\n // socket is never assigned to the websocket. Wait for the `'error'` event\n // that will be emitted by the websocket.\n if (ws._socket === null) return;\n\n if (ws._socket._writableState.finished) {\n callback();\n if (duplex._readableState.endEmitted) duplex.destroy();\n } else {\n ws._socket.once('finish', function finish() {\n // `duplex` is not destroyed here because the `'end'` event will be\n // emitted on `duplex` after this `'finish'` event. The EOF signaling\n // `null` chunk is, in fact, pushed when the websocket emits `'close'`.\n callback();\n });\n ws.close();\n }\n };\n\n duplex._read = function () {\n if (ws.isPaused) ws.resume();\n };\n\n duplex._write = function (chunk, encoding, callback) {\n if (ws.readyState === ws.CONNECTING) {\n ws.once('open', function open() {\n duplex._write(chunk, encoding, callback);\n });\n return;\n }\n\n ws.send(chunk, callback);\n };\n\n duplex.on('end', duplexOnEnd);\n duplex.on('error', duplexOnError);\n return duplex;\n}\n\nmodule.exports = createWebSocketStream;\n","'use strict';\n\nconst { tokenChars } = require('./validation');\n\n/**\n * Parses the `Sec-WebSocket-Protocol` header into a set of subprotocol names.\n *\n * @param {String} header The field value of the header\n * @return {Set} The subprotocol names\n * @public\n */\nfunction parse(header) {\n const protocols = new Set();\n let start = -1;\n let end = -1;\n let i = 0;\n\n for (i; i < header.length; i++) {\n const code = header.charCodeAt(i);\n\n if (end === -1 && tokenChars[code] === 1) {\n if (start === -1) start = i;\n } else if (\n i !== 0 &&\n (code === 0x20 /* ' ' */ || code === 0x09) /* '\\t' */\n ) {\n if (end === -1 && start !== -1) end = i;\n } else if (code === 0x2c /* ',' */) {\n if (start === -1) {\n throw new SyntaxError(`Unexpected character at index ${i}`);\n }\n\n if (end === -1) end = i;\n\n const protocol = header.slice(start, end);\n\n if (protocols.has(protocol)) {\n throw new SyntaxError(`The \"${protocol}\" subprotocol is duplicated`);\n }\n\n protocols.add(protocol);\n start = end = -1;\n } else {\n throw new SyntaxError(`Unexpected character at index ${i}`);\n }\n }\n\n if (start === -1 || end !== -1) {\n throw new SyntaxError('Unexpected end of input');\n }\n\n const protocol = header.slice(start, i);\n\n if (protocols.has(protocol)) {\n throw new SyntaxError(`The \"${protocol}\" subprotocol is duplicated`);\n }\n\n protocols.add(protocol);\n return protocols;\n}\n\nmodule.exports = { parse };\n","/* eslint no-unused-vars: [\"error\", { \"varsIgnorePattern\": \"^Duplex$\", \"caughtErrors\": \"none\" }] */\n\n'use strict';\n\nconst EventEmitter = require('events');\nconst http = require('http');\nconst { Duplex } = require('stream');\nconst { createHash } = require('crypto');\n\nconst extension = require('./extension');\nconst PerMessageDeflate = require('./permessage-deflate');\nconst subprotocol = require('./subprotocol');\nconst WebSocket = require('./websocket');\nconst { CLOSE_TIMEOUT, GUID, kWebSocket } = require('./constants');\n\nconst keyRegex = /^[+/0-9A-Za-z]{22}==$/;\n\nconst RUNNING = 0;\nconst CLOSING = 1;\nconst CLOSED = 2;\n\n/**\n * Class representing a WebSocket server.\n *\n * @extends EventEmitter\n */\nclass WebSocketServer extends EventEmitter {\n /**\n * Create a `WebSocketServer` instance.\n *\n * @param {Object} options Configuration options\n * @param {Boolean} [options.allowSynchronousEvents=true] Specifies whether\n * any of the `'message'`, `'ping'`, and `'pong'` events can be emitted\n * multiple times in the same tick\n * @param {Boolean} [options.autoPong=true] Specifies whether or not to\n * automatically send a pong in response to a ping\n * @param {Number} [options.backlog=511] The maximum length of the queue of\n * pending connections\n * @param {Boolean} [options.clientTracking=true] Specifies whether or not to\n * track clients\n * @param {Number} [options.closeTimeout=30000] Duration in milliseconds to\n * wait for the closing handshake to finish after `websocket.close()` is\n * called\n * @param {Function} [options.handleProtocols] A hook to handle protocols\n * @param {String} [options.host] The hostname where to bind the server\n * @param {Number} [options.maxPayload=104857600] The maximum allowed message\n * size\n * @param {Boolean} [options.noServer=false] Enable no server mode\n * @param {String} [options.path] Accept only connections matching this path\n * @param {(Boolean|Object)} [options.perMessageDeflate=false] Enable/disable\n * permessage-deflate\n * @param {Number} [options.port] The port where to bind the server\n * @param {(http.Server|https.Server)} [options.server] A pre-created HTTP/S\n * server to use\n * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or\n * not to skip UTF-8 validation for text and close messages\n * @param {Function} [options.verifyClient] A hook to reject connections\n * @param {Function} [options.WebSocket=WebSocket] Specifies the `WebSocket`\n * class to use. It must be the `WebSocket` class or class that extends it\n * @param {Function} [callback] A listener for the `listening` event\n */\n constructor(options, callback) {\n super();\n\n options = {\n allowSynchronousEvents: true,\n autoPong: true,\n maxPayload: 100 * 1024 * 1024,\n skipUTF8Validation: false,\n perMessageDeflate: false,\n handleProtocols: null,\n clientTracking: true,\n closeTimeout: CLOSE_TIMEOUT,\n verifyClient: null,\n noServer: false,\n backlog: null, // use default (511 as implemented in net.js)\n server: null,\n host: null,\n path: null,\n port: null,\n WebSocket,\n ...options\n };\n\n if (\n (options.port == null && !options.server && !options.noServer) ||\n (options.port != null && (options.server || options.noServer)) ||\n (options.server && options.noServer)\n ) {\n throw new TypeError(\n 'One and only one of the \"port\", \"server\", or \"noServer\" options ' +\n 'must be specified'\n );\n }\n\n if (options.port != null) {\n this._server = http.createServer((req, res) => {\n const body = http.STATUS_CODES[426];\n\n res.writeHead(426, {\n 'Content-Length': body.length,\n 'Content-Type': 'text/plain'\n });\n res.end(body);\n });\n this._server.listen(\n options.port,\n options.host,\n options.backlog,\n callback\n );\n } else if (options.server) {\n this._server = options.server;\n }\n\n if (this._server) {\n const emitConnection = this.emit.bind(this, 'connection');\n\n this._removeListeners = addListeners(this._server, {\n listening: this.emit.bind(this, 'listening'),\n error: this.emit.bind(this, 'error'),\n upgrade: (req, socket, head) => {\n this.handleUpgrade(req, socket, head, emitConnection);\n }\n });\n }\n\n if (options.perMessageDeflate === true) options.perMessageDeflate = {};\n if (options.clientTracking) {\n this.clients = new Set();\n this._shouldEmitClose = false;\n }\n\n this.options = options;\n this._state = RUNNING;\n }\n\n /**\n * Returns the bound address, the address family name, and port of the server\n * as reported by the operating system if listening on an IP socket.\n * If the server is listening on a pipe or UNIX domain socket, the name is\n * returned as a string.\n *\n * @return {(Object|String|null)} The address of the server\n * @public\n */\n address() {\n if (this.options.noServer) {\n throw new Error('The server is operating in \"noServer\" mode');\n }\n\n if (!this._server) return null;\n return this._server.address();\n }\n\n /**\n * Stop the server from accepting new connections and emit the `'close'` event\n * when all existing connections are closed.\n *\n * @param {Function} [cb] A one-time listener for the `'close'` event\n * @public\n */\n close(cb) {\n if (this._state === CLOSED) {\n if (cb) {\n this.once('close', () => {\n cb(new Error('The server is not running'));\n });\n }\n\n process.nextTick(emitClose, this);\n return;\n }\n\n if (cb) this.once('close', cb);\n\n if (this._state === CLOSING) return;\n this._state = CLOSING;\n\n if (this.options.noServer || this.options.server) {\n if (this._server) {\n this._removeListeners();\n this._removeListeners = this._server = null;\n }\n\n if (this.clients) {\n if (!this.clients.size) {\n process.nextTick(emitClose, this);\n } else {\n this._shouldEmitClose = true;\n }\n } else {\n process.nextTick(emitClose, this);\n }\n } else {\n const server = this._server;\n\n this._removeListeners();\n this._removeListeners = this._server = null;\n\n //\n // The HTTP/S server was created internally. Close it, and rely on its\n // `'close'` event.\n //\n server.close(() => {\n emitClose(this);\n });\n }\n }\n\n /**\n * See if a given request should be handled by this server instance.\n *\n * @param {http.IncomingMessage} req Request object to inspect\n * @return {Boolean} `true` if the request is valid, else `false`\n * @public\n */\n shouldHandle(req) {\n if (this.options.path) {\n const index = req.url.indexOf('?');\n const pathname = index !== -1 ? req.url.slice(0, index) : req.url;\n\n if (pathname !== this.options.path) return false;\n }\n\n return true;\n }\n\n /**\n * Handle a HTTP Upgrade request.\n *\n * @param {http.IncomingMessage} req The request object\n * @param {Duplex} socket The network socket between the server and client\n * @param {Buffer} head The first packet of the upgraded stream\n * @param {Function} cb Callback\n * @public\n */\n handleUpgrade(req, socket, head, cb) {\n socket.on('error', socketOnError);\n\n const key = req.headers['sec-websocket-key'];\n const upgrade = req.headers.upgrade;\n const version = +req.headers['sec-websocket-version'];\n\n if (req.method !== 'GET') {\n const message = 'Invalid HTTP method';\n abortHandshakeOrEmitwsClientError(this, req, socket, 405, message);\n return;\n }\n\n if (upgrade === undefined || upgrade.toLowerCase() !== 'websocket') {\n const message = 'Invalid Upgrade header';\n abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);\n return;\n }\n\n if (key === undefined || !keyRegex.test(key)) {\n const message = 'Missing or invalid Sec-WebSocket-Key header';\n abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);\n return;\n }\n\n if (version !== 13 && version !== 8) {\n const message = 'Missing or invalid Sec-WebSocket-Version header';\n abortHandshakeOrEmitwsClientError(this, req, socket, 400, message, {\n 'Sec-WebSocket-Version': '13, 8'\n });\n return;\n }\n\n if (!this.shouldHandle(req)) {\n abortHandshake(socket, 400);\n return;\n }\n\n const secWebSocketProtocol = req.headers['sec-websocket-protocol'];\n let protocols = new Set();\n\n if (secWebSocketProtocol !== undefined) {\n try {\n protocols = subprotocol.parse(secWebSocketProtocol);\n } catch (err) {\n const message = 'Invalid Sec-WebSocket-Protocol header';\n abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);\n return;\n }\n }\n\n const secWebSocketExtensions = req.headers['sec-websocket-extensions'];\n const extensions = {};\n\n if (\n this.options.perMessageDeflate &&\n secWebSocketExtensions !== undefined\n ) {\n const perMessageDeflate = new PerMessageDeflate(\n this.options.perMessageDeflate,\n true,\n this.options.maxPayload\n );\n\n try {\n const offers = extension.parse(secWebSocketExtensions);\n\n if (offers[PerMessageDeflate.extensionName]) {\n perMessageDeflate.accept(offers[PerMessageDeflate.extensionName]);\n extensions[PerMessageDeflate.extensionName] = perMessageDeflate;\n }\n } catch (err) {\n const message =\n 'Invalid or unacceptable Sec-WebSocket-Extensions header';\n abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);\n return;\n }\n }\n\n //\n // Optionally call external client verification handler.\n //\n if (this.options.verifyClient) {\n const info = {\n origin:\n req.headers[`${version === 8 ? 'sec-websocket-origin' : 'origin'}`],\n secure: !!(req.socket.authorized || req.socket.encrypted),\n req\n };\n\n if (this.options.verifyClient.length === 2) {\n this.options.verifyClient(info, (verified, code, message, headers) => {\n if (!verified) {\n return abortHandshake(socket, code || 401, message, headers);\n }\n\n this.completeUpgrade(\n extensions,\n key,\n protocols,\n req,\n socket,\n head,\n cb\n );\n });\n return;\n }\n\n if (!this.options.verifyClient(info)) return abortHandshake(socket, 401);\n }\n\n this.completeUpgrade(extensions, key, protocols, req, socket, head, cb);\n }\n\n /**\n * Upgrade the connection to WebSocket.\n *\n * @param {Object} extensions The accepted extensions\n * @param {String} key The value of the `Sec-WebSocket-Key` header\n * @param {Set} protocols The subprotocols\n * @param {http.IncomingMessage} req The request object\n * @param {Duplex} socket The network socket between the server and client\n * @param {Buffer} head The first packet of the upgraded stream\n * @param {Function} cb Callback\n * @throws {Error} If called more than once with the same socket\n * @private\n */\n completeUpgrade(extensions, key, protocols, req, socket, head, cb) {\n //\n // Destroy the socket if the client has already sent a FIN packet.\n //\n if (!socket.readable || !socket.writable) return socket.destroy();\n\n if (socket[kWebSocket]) {\n throw new Error(\n 'server.handleUpgrade() was called more than once with the same ' +\n 'socket, possibly due to a misconfiguration'\n );\n }\n\n if (this._state > RUNNING) return abortHandshake(socket, 503);\n\n const digest = createHash('sha1')\n .update(key + GUID)\n .digest('base64');\n\n const headers = [\n 'HTTP/1.1 101 Switching Protocols',\n 'Upgrade: websocket',\n 'Connection: Upgrade',\n `Sec-WebSocket-Accept: ${digest}`\n ];\n\n const ws = new this.options.WebSocket(null, undefined, this.options);\n\n if (protocols.size) {\n //\n // Optionally call external protocol selection handler.\n //\n const protocol = this.options.handleProtocols\n ? this.options.handleProtocols(protocols, req)\n : protocols.values().next().value;\n\n if (protocol) {\n headers.push(`Sec-WebSocket-Protocol: ${protocol}`);\n ws._protocol = protocol;\n }\n }\n\n if (extensions[PerMessageDeflate.extensionName]) {\n const params = extensions[PerMessageDeflate.extensionName].params;\n const value = extension.format({\n [PerMessageDeflate.extensionName]: [params]\n });\n headers.push(`Sec-WebSocket-Extensions: ${value}`);\n ws._extensions = extensions;\n }\n\n //\n // Allow external modification/inspection of handshake headers.\n //\n this.emit('headers', headers, req);\n\n socket.write(headers.concat('\\r\\n').join('\\r\\n'));\n socket.removeListener('error', socketOnError);\n\n ws.setSocket(socket, head, {\n allowSynchronousEvents: this.options.allowSynchronousEvents,\n maxPayload: this.options.maxPayload,\n skipUTF8Validation: this.options.skipUTF8Validation\n });\n\n if (this.clients) {\n this.clients.add(ws);\n ws.on('close', () => {\n this.clients.delete(ws);\n\n if (this._shouldEmitClose && !this.clients.size) {\n process.nextTick(emitClose, this);\n }\n });\n }\n\n cb(ws, req);\n }\n}\n\nmodule.exports = WebSocketServer;\n\n/**\n * Add event listeners on an `EventEmitter` using a map of <event, listener>\n * pairs.\n *\n * @param {EventEmitter} server The event emitter\n * @param {Object.<String, Function>} map The listeners to add\n * @return {Function} A function that will remove the added listeners when\n * called\n * @private\n */\nfunction addListeners(server, map) {\n for (const event of Object.keys(map)) server.on(event, map[event]);\n\n return function removeListeners() {\n for (const event of Object.keys(map)) {\n server.removeListener(event, map[event]);\n }\n };\n}\n\n/**\n * Emit a `'close'` event on an `EventEmitter`.\n *\n * @param {EventEmitter} server The event emitter\n * @private\n */\nfunction emitClose(server) {\n server._state = CLOSED;\n server.emit('close');\n}\n\n/**\n * Handle socket errors.\n *\n * @private\n */\nfunction socketOnError() {\n this.destroy();\n}\n\n/**\n * Close the connection when preconditions are not fulfilled.\n *\n * @param {Duplex} socket The socket of the upgrade request\n * @param {Number} code The HTTP response status code\n * @param {String} [message] The HTTP response body\n * @param {Object} [headers] Additional HTTP response headers\n * @private\n */\nfunction abortHandshake(socket, code, message, headers) {\n //\n // The socket is writable unless the user destroyed or ended it before calling\n // `server.handleUpgrade()` or in the `verifyClient` function, which is a user\n // error. Handling this does not make much sense as the worst that can happen\n // is that some of the data written by the user might be discarded due to the\n // call to `socket.end()` below, which triggers an `'error'` event that in\n // turn causes the socket to be destroyed.\n //\n message = message || http.STATUS_CODES[code];\n headers = {\n Connection: 'close',\n 'Content-Type': 'text/html',\n 'Content-Length': Buffer.byteLength(message),\n ...headers\n };\n\n socket.once('finish', socket.destroy);\n\n socket.end(\n `HTTP/1.1 ${code} ${http.STATUS_CODES[code]}\\r\\n` +\n Object.keys(headers)\n .map((h) => `${h}: ${headers[h]}`)\n .join('\\r\\n') +\n '\\r\\n\\r\\n' +\n message\n );\n}\n\n/**\n * Emit a `'wsClientError'` event on a `WebSocketServer` if there is at least\n * one listener for it, otherwise call `abortHandshake()`.\n *\n * @param {WebSocketServer} server The WebSocket server\n * @param {http.IncomingMessage} req The request object\n * @param {Duplex} socket The socket of the upgrade request\n * @param {Number} code The HTTP response status code\n * @param {String} message The HTTP response body\n * @param {Object} [headers] The HTTP response headers\n * @private\n */\nfunction abortHandshakeOrEmitwsClientError(\n server,\n req,\n socket,\n code,\n message,\n headers\n) {\n if (server.listenerCount('wsClientError')) {\n const err = new Error(message);\n Error.captureStackTrace(err, abortHandshakeOrEmitwsClientError);\n\n server.emit('wsClientError', err, socket, req);\n } else {\n abortHandshake(socket, code, message, headers);\n }\n}\n","import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport { readFileSync } from \"node:fs\";\nimport { basename, dirname } from \"node:path\";\nimport { MAX_LIGHT_SEGMENTS } from \"./light/protocol.js\";\nimport { sendLightEffect } from \"./light/sender.js\";\nimport { createAppNameMapProvider } from \"./notification/app-name-map.js\";\nimport {\n NotificationStorage,\n type NotificationIngestResult,\n resolveNotificationStorageDir,\n} from \"./notification/storage.js\";\nimport type {\n PluginConfig,\n RawNotification,\n NotificationPushParams,\n HttpNotificationBody,\n LightControlInput,\n} from \"./types.js\";\nimport { registerAllCli } from \"./cli/index.js\";\nimport { requireApiKey } from \"./auth/credentials.js\";\nimport { createTunnelService } from \"./tunnel/service.js\";\nimport { PluginFileLogger } from \"./logger.js\";\nimport { getEnvUrls } from \"./env.js\";\nimport { resolveConfigPath } from \"./host.js\";\n\ninterface PluginApi {\n logger: {\n info: (msg: string) => void;\n warn: (msg: string) => void;\n error: (msg: string) => void;\n };\n pluginConfig?: Record<string, unknown>;\n runtime: {\n state: {\n resolveStateDir: () =>string;\n };\n };\n registerService: (service: {\n id: string;\n start: (ctx: {\n stateDir: string;\n workspaceDir?: string;\n }) => void | Promise<void>;\n stop?: () => void | Promise<void>;\n }) => void;\n registerGatewayMethod: (\n method: string,\n handler: (opts: {\n params: Record<string, unknown>;\n /** 发起本次请求的 WSS 客户端(operator 节点为 null) */\n client: { connId?: string } | null;\n context: {\n /** 向所有已连接的 operator 客户端广播 event 帧 */\n broadcast: (event: string, payload: unknown) => void;\n /** 向指定 connId 集合广播 event 帧 */\n broadcastToConnIds: (\n event: string,\n payload: unknown,\n connIds: ReadonlySet<string>,\n ) => void;\n };\n respond: (\n ok: boolean,\n payload?: unknown,\n error?: { code: string; message: string },\n ) => void;\n }) => void | Promise<void>,\n ) => void;\n /** 注册供 AI Agent 调用的 tool,声明即实现 */\n registerTool: (tool: {\n name: string;\n description: string;\n parameters: Record<string, unknown>;\n execute: (\n toolCallId: string,\n params: unknown,\n ) => unknown | Promise<unknown>;\n }) => void;\n registerHttpRoute: (params: {\n path: string;\n handler: (\n req: IncomingMessage,\n res: ServerResponse,\n ) => void | Promise<void>;\n auth?: \"gateway\" | \"plugin\";\n }) => void;\n registerCli: (\n registrar: (ctx: {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n program: any;\n stateDir?: string;\n workspaceDir?: string;\n logger: PluginApi[\"logger\"];\n }) => void | Promise<void>,\n opts?: { commands?: string[] },\n ) => void;\n}\n\nfunction readBody(req: IncomingMessage): Promise<string> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n req.on(\"data\", (chunk: Buffer) => chunks.push(chunk));\n req.on(\"end\", () => resolve(Buffer.concat(chunks).toString()));\n req.on(\"error\", reject);\n });\n}\n\nfunction trimToUndefined(value: unknown): string | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n const trimmed = value.trim();\n return trimmed || undefined;\n}\n\nfunction createEmptyIngestResult(): NotificationIngestResult {\n return {\n received: 0,\n ingested: 0,\n dedupedById: 0,\n dedupedByContent: 0,\n invalid: 0,\n };\n}\n\nfunction resolveLocalGatewayAuth(params: {\n stateDir?: string;\n logger: Pick<PluginApi[\"logger\"], \"warn\">;\n}): {\n gatewayAuthMode?: \"token\" | \"password\";\n gatewayToken?: string;\n gatewayPassword?: string;\n} {\n const envGatewayToken =\n trimToUndefined(process.env.OPENCLAW_GATEWAY_TOKEN) ??\n trimToUndefined(process.env.QCLAW_GATEWAY_TOKEN) ??\n trimToUndefined(process.env.CLAWDBOT_GATEWAY_TOKEN);\n const envGatewayPassword =\n trimToUndefined(process.env.OPENCLAW_GATEWAY_PASSWORD) ??\n trimToUndefined(process.env.QCLAW_GATEWAY_PASSWORD) ??\n trimToUndefined(process.env.CLAWDBOT_GATEWAY_PASSWORD);\n\n let configGatewayAuthMode: \"token\" | \"password\" | undefined;\n let configGatewayToken: string | undefined;\n let configGatewayPassword: string | undefined;\n const configPath = params.stateDir\n ? resolveConfigPath(params.stateDir)\n : undefined;\n\n if (configPath) {\n try {\n const configData = JSON.parse(readFileSync(configPath, \"utf-8\"));\n const rawGatewayAuthMode = trimToUndefined(configData?.gateway?.auth?.mode);\n if (rawGatewayAuthMode === \"token\" || rawGatewayAuthMode === \"password\") {\n configGatewayAuthMode = rawGatewayAuthMode;\n }\n configGatewayToken = trimToUndefined(configData?.gateway?.auth?.token);\n configGatewayPassword = trimToUndefined(configData?.gateway?.auth?.password);\n } catch (err: any) {\n if (err?.code !== \"ENOENT\") {\n params.logger.warn(\n `Relay tunnel: 无法读取 gateway 鉴权配置 (${configPath})`,\n );\n }\n }\n }\n\n return {\n gatewayAuthMode: configGatewayAuthMode,\n gatewayToken: envGatewayToken ?? configGatewayToken,\n gatewayPassword: envGatewayPassword ?? configGatewayPassword,\n };\n}\n\nexport default {\n id: \"phone-notifications\",\n name: \"Phone Notifications Sync\",\n\n register(api: PluginApi) {\n const config = (api.pluginConfig ?? {}) as PluginConfig;\n let storage: NotificationStorage | null = null;\n let appNameMapProvider: ReturnType<typeof createAppNameMapProvider> | null = null;\n const ignoredApps = new Set(config.ignoredApps ?? []);\n\n const openclawDir = api.runtime.state.resolveStateDir();\n const logger = openclawDir\n ? new PluginFileLogger(api.logger, openclawDir)\n : api.logger;\n\n function filterNotifications(items: RawNotification[]): RawNotification[] {\n return items.filter((n) => !ignoredApps.has(n.app));\n }\n\n // 1. registerService — 管理 storage 与 app-name-map 生命周期\n api.registerService({\n id: \"notification-storage\",\n async start(ctx) {\n const storageDir = resolveNotificationStorageDir(ctx, logger);\n\n appNameMapProvider = createAppNameMapProvider({\n stateDir: ctx.stateDir,\n logger,\n });\n await appNameMapProvider.start();\n\n const resolveDisplayName = appNameMapProvider.resolveDisplayName.bind(appNameMapProvider);\n storage = new NotificationStorage(storageDir, config, logger, resolveDisplayName);\n await storage.init();\n logger.info(`通知存储服务已启动: ${storageDir}`);\n },\n async stop() {\n await storage?.close();\n storage = null;\n appNameMapProvider?.stop();\n appNameMapProvider = null;\n logger.info(\"通知存储服务已停止\");\n },\n });\n\n // 1b. registerService — Relay Tunnel 隧道服务\n const tunnelUrl = getEnvUrls().relayTunnelUrl;\n if (tunnelUrl) {\n const gatewayPort =\n process.env.OPENCLAW_GATEWAY_PORT ??\n process.env.QCLAW_GATEWAY_PORT ??\n \"18789\";\n const { gatewayAuthMode, gatewayToken, gatewayPassword } =\n resolveLocalGatewayAuth({\n stateDir: openclawDir,\n logger,\n });\n const tunnelService = createTunnelService({\n tunnelUrl,\n heartbeatSec: config.relay?.heartbeatSec,\n reconnectBackoffMs: config.relay?.reconnectBackoffMs,\n gatewayBaseUrl: `http://localhost:${gatewayPort}`,\n gatewayAuthMode,\n gatewayToken,\n gatewayPassword,\n logger,\n });\n api.registerService(tunnelService);\n logger.info(\"Relay tunnel 服务已注册\");\n }\n\n // 2. registerGatewayMethod — Gateway Native 模式(默认)\n // 协议:{ type: \"req\", id: \"n_abc\", method: \"notifications.push\",\n // params: { items: [...] } }\n api.registerGatewayMethod(\n \"notifications.push\",\n async ({ params, respond }) => {\n if (!storage) {\n respond(false, null, {\n code: \"NOT_READY\",\n message: \"Storage service not ready\",\n });\n return;\n }\n\n const { items } = params as unknown as NotificationPushParams;\n if (Array.isArray(items)) {\n const filtered = filterNotifications(items);\n const result = filtered.length\n ? await storage.ingest(filtered)\n : createEmptyIngestResult();\n respond(true, result);\n } else {\n respond(false, null, {\n code: \"INVALID_PARAMS\",\n message: \"items must be an array\",\n });\n }\n },\n );\n\n // 3. registerTool — 灯效控制(Agent 驱动)\n // 支持 1–10 段顺序灯效,每段独立参数。\n // 通过 HTTP 接口直接下发灯效指令\n api.registerTool({\n name: \"light_control\",\n description:\n \"控制硬件灯效,支持 1–12 段顺序灯效,每段独立参数(5 种模式:波浪/呼吸/频闪/常亮/流光)。\" +\n \"Tool 内部自动量化为嵌入式协议定义的离散档位,并按模式精简为变长 ANCS 控制序列,通过 HTTP 接口下发灯效指令。\" +\n '当用户说\"开灯\"、\"换个灯效\"、\"把灯调成红色\"、\"营造氛围\"等与灯光控制相关的表达时调用。',\n parameters: {\n type: \"object\",\n required: [\"segments\"],\n additionalProperties: false,\n properties: {\n segments: {\n type: \"array\",\n description: \"灯效段序列,1–12 段,按顺序播放\",\n minItems: 1,\n maxItems: MAX_LIGHT_SEGMENTS,\n items: {\n type: \"object\",\n required: [\"mode\", \"duration_s\", \"brightness\", \"color\"],\n additionalProperties: false,\n properties: {\n mode: {\n type: \"string\",\n enum: [\"wave\", \"breath\", \"strobe\", \"steady\", \"wave_rainbow\"],\n description:\n \"灯效模式:wave 波浪 / breath 呼吸 / strobe 频闪 / steady 常亮 / wave_rainbow 流光(多色调色板在 7 颗灯上循环流动)\",\n },\n duration_s: {\n type: \"number\",\n minimum: 0,\n description:\n \"本段持续时长(秒),0 表示无限时长。推荐离散值:0.5/1/2/3/5/6/8/16/24/32/48,建议单段 ≤8s 省电\",\n },\n brightness: {\n type: \"number\",\n minimum: 0,\n maximum: 255,\n description:\n \"前景亮度 0–255,量化档位:32/64/96/128/192/255。brightness=0 仅在 steady 模式下有效(显式灭灯)\",\n },\n color: {\n type: \"object\",\n required: [\"r\", \"g\", \"b\"],\n additionalProperties: false,\n properties: {\n r: { type: \"number\", minimum: 0, maximum: 255 },\n g: { type: \"number\", minimum: 0, maximum: 255 },\n b: { type: \"number\", minimum: 0, maximum: 255 },\n },\n description:\n \"前景色 RGB(wave_rainbow 模式下作为第一颜色锚点,至少 R/G/B 中一个非 0)\",\n },\n interval_ms: {\n type: \"number\",\n minimum: 0,\n description:\n \"步进间隔(ms),wave/strobe/wave_rainbow 有效,默认 200。量化档位:50/100/200/300/500/600/800/1600/2400/3200/4800\",\n },\n direction: {\n type: \"string\",\n enum: [\"ltr\", \"rtl\"],\n description: \"波浪/流光方向,wave/wave_rainbow 有效,默认 ltr\",\n },\n window: {\n type: \"number\",\n enum: [1, 2, 3],\n description:\n \"wave:窗口灯数,默认 2;wave_rainbow:调色板平移步幅(速度)\",\n },\n breath_timing: {\n type: \"object\",\n additionalProperties: false,\n properties: {\n rise_ms: {\n type: \"number\",\n minimum: 0,\n description:\n \"上升时间(ms),量化到 1040/1560/2080/2600/3100/4160\",\n },\n hold_ms: {\n type: \"number\",\n minimum: 0,\n description: \"保持最高亮度时间(ms),支持 0ms\",\n },\n fall_ms: {\n type: \"number\",\n minimum: 0,\n description:\n \"下降时间(ms),量化到 1040/1560/2080/2600/3100/4160\",\n },\n off_ms: {\n type: \"number\",\n minimum: 0,\n description: \"熄灭时间(ms),支持 0ms\",\n },\n },\n description:\n \"呼吸四段时间,仅 breath 有效;rise/fall 量化档位:1040/1560/2080/2600/3100/4160,hold/off 额外支持 0ms\",\n },\n background: {\n type: \"object\",\n required: [\"r\", \"g\", \"b\", \"brightness\"],\n additionalProperties: false,\n properties: {\n r: { type: \"number\", minimum: 0, maximum: 255 },\n g: { type: \"number\", minimum: 0, maximum: 255 },\n b: { type: \"number\", minimum: 0, maximum: 255 },\n brightness: {\n type: \"number\",\n minimum: 0,\n maximum: 255,\n description: \"底色亮度,量化档位:0/32/64/96/128/192/255\",\n },\n },\n description:\n \"底色 RGB + 亮度,wave 有效为底色层;wave_rainbow 有效为第二颜色锚点(与前景色插值生成多色调色板)\",\n },\n },\n },\n },\n repeat: {\n type: \"boolean\",\n description:\n \"true = 无限循环播放,false/不填 = 仅播放一轮。无限循环适合背景常驻灯效,注意省电\",\n },\n },\n },\n async execute(_toolCallId: string, params: unknown) {\n let apiKey: string;\n try {\n apiKey = requireApiKey();\n } catch (e: any) {\n return {\n ok: false,\n error: { code: \"AUTH_REQUIRED\", message: e.message },\n };\n }\n\n const { segments, repeat } = params as LightControlInput;\n const result = await sendLightEffect(apiKey, segments, logger, repeat);\n\n if (!result.ok) {\n logger.warn(\n `Light control HTTP request failed: ${result.status} ${result.error}`,\n );\n } else {\n logger.info(`Light control sent, bizUniqueId=${result.bizUniqueId}`);\n }\n\n return result;\n },\n });\n\n // 4. registerHttpRoute — HTTP 端点(鉴权由 Gateway 统一处理)\n api.registerHttpRoute({\n path: \"/notifications\",\n auth: \"gateway\",\n async handler(req: IncomingMessage, res: ServerResponse) {\n // 仅接受 POST\n if (req.method !== \"POST\") {\n res.writeHead(405, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: false, error: \"Method Not Allowed\" }));\n return;\n }\n\n if (!storage) {\n res.writeHead(503, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: false, error: \"Service Not Ready\" }));\n return;\n }\n\n // 解析请求体\n let body: HttpNotificationBody;\n try {\n const raw = await readBody(req);\n body = JSON.parse(raw);\n } catch {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: false, error: \"Invalid JSON\" }));\n return;\n }\n\n if (!Array.isArray(body.notifications)) {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n res.end(\n JSON.stringify({\n ok: false,\n error: \"notifications must be an array\",\n }),\n );\n return;\n }\n\n const filtered = filterNotifications(body.notifications);\n const result = filtered.length\n ? await storage.ingest(filtered)\n : createEmptyIngestResult();\n\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: true, ...result }));\n },\n });\n\n logger.info(\"HTTP 通知端点已注册: POST /notifications\");\n\n // 5. registerCli — 注册 CLI 命令。\n // 分拆为两个独立注册器,避免 `ntf` 被其他插件占用时整组 CLI 被跳过。\n const inferOpenClawRootDir = (workspaceDir?: string): string | undefined => {\n // OpenClaw 默认 workspace 目录为: <openclawRoot>/workspace\n // 例如: /Users/trl/.openclaw/workspace → /Users/trl/.openclaw\n if(openclawDir) return openclawDir;\n if (!workspaceDir) return undefined;\n\n if (basename(workspaceDir) !== \"workspace\") return undefined;\n return dirname(workspaceDir);\n };\n\n api.registerCli(\n (ctx) => {\n const inferredRoot = inferOpenClawRootDir(ctx.workspaceDir);\n const effectiveStateDir = ctx.stateDir ?? inferredRoot;\n registerAllCli(ctx.program, {\n stateDir: effectiveStateDir,\n workspaceDir: ctx.workspaceDir,\n }, \"ntf\");\n },\n { commands: [\"ntf\"] },\n );\n\n api.registerCli(\n (ctx) => {\n const inferredRoot = inferOpenClawRootDir(ctx.workspaceDir);\n const effectiveStateDir = ctx.stateDir ?? inferredRoot;\n registerAllCli(ctx.program, {\n stateDir: effectiveStateDir,\n workspaceDir: ctx.workspaceDir,\n }, \"phone-notifications\");\n },\n { commands: [\"phone-notifications\"] },\n );\n\n logger.info(\"CLI 命令已注册: ntf, phone-notifications\");\n },\n};\n","import type { LightSegment } from \"../types.js\";\n\nexport const MAX_LIGHT_SEGMENTS = 12;\n\nconst PROTOCOL_DIGITS = [\n \"\\u0080\",\n \"\\u0081\",\n \"\\u0082\",\n \"\\u0083\",\n \"\\u0084\",\n \"\\u0091\",\n \"\\u0092\",\n \"\\u0093\",\n \"\\u0094\",\n \"\\u0095\",\n \"\\u0096\",\n \"\\u0097\",\n] as const;\n\n/** \\u009A = play once, \\u009B = infinite loop */\nconst LED_SEPARATOR_ONCE = \"\\u009A\";\nconst LED_SEPARATOR_LOOP = \"\\u009B\";\n\n/** v0–v10 mapped by index; duration_s=0 is special-cased to v11 (infinite) */\nconst DURATION_STEPS_S = [0.5, 1, 2, 3, 5, 6, 8, 16, 24, 32, 48] as const;\n/** v0–v10 mapped by index; removed 400ms, added 50ms */\nconst INTERVAL_STEPS_MS = [50, 100, 200, 300, 500, 600, 800, 1600, 2400, 3200, 4800] as const;\nconst BREATH_STEPS_MS = [1040, 1560, 2080, 2600, 3100, 4160] as const;\nconst BRIGHTNESS_STEPS = [32, 64, 96, 128, 192, 255] as const;\nconst COLOR_STEPS = [0, 32, 64, 128, 192, 255] as const;\nconst BACKGROUND_BRIGHTNESS_STEPS = [0, 32, 64, 96, 128, 192, 255] as const;\n\nconst MODE_TO_INDEX: Record<LightSegment[\"mode\"], number> = {\n wave: 0,\n breath: 1,\n strobe: 2,\n steady: 3,\n wave_rainbow: 4,\n};\n\nexport function buildLightEffectApnsBody(\n segments: LightSegment[],\n repeat?: boolean,\n): string {\n assertSegmentCount(segments);\n\n const visibleText = summarizeSegments(segments);\n const separator = repeat ? LED_SEPARATOR_LOOP : LED_SEPARATOR_ONCE;\n const payload = segments.map((segment) => encodeSegment(segment)).join(\"\");\n return `${visibleText}${separator}${payload}`;\n}\n\nfunction assertSegmentCount(segments: LightSegment[]): void {\n if (segments.length < 1 || segments.length > MAX_LIGHT_SEGMENTS) {\n throw new Error(`light_control supports 1-${MAX_LIGHT_SEGMENTS} segments`);\n }\n}\n\nfunction summarizeSegments(segments: LightSegment[]): string {\n const modeDesc = segments.map((segment) => segment.mode).join(\"+\");\n return `Effect: ${modeDesc} (${segments.length} segment${segments.length > 1 ? \"s\" : \"\"})`;\n}\n\nfunction encodeSegment(segment: LightSegment): string {\n const common = [\n MODE_TO_INDEX[segment.mode],\n quantizeDuration(segment.duration_s),\n ];\n\n let values: number[];\n switch (segment.mode) {\n case \"wave\":\n case \"wave_rainbow\":\n values = [\n ...common,\n quantize(segment.interval_ms ?? 200, INTERVAL_STEPS_MS),\n quantizeBrightness(segment),\n quantize(segment.color.r, COLOR_STEPS),\n quantize(segment.color.g, COLOR_STEPS),\n quantize(segment.color.b, COLOR_STEPS),\n segment.direction === \"rtl\" ? 1 : 0,\n quantizeWindow(segment.window ?? 2),\n quantize(segment.background?.r ?? 0, COLOR_STEPS),\n quantize(segment.background?.g ?? 0, COLOR_STEPS),\n quantize(segment.background?.b ?? 0, COLOR_STEPS),\n quantize(segment.background?.brightness ?? 0, BACKGROUND_BRIGHTNESS_STEPS),\n ];\n break;\n case \"breath\":\n values = [\n ...common,\n quantizeBreathRiseFall(segment.breath_timing?.rise_ms),\n quantizeBreathHoldOff(segment.breath_timing?.hold_ms),\n quantizeBreathRiseFall(segment.breath_timing?.fall_ms),\n quantizeBreathHoldOff(segment.breath_timing?.off_ms),\n quantizeBrightness(segment),\n quantize(segment.color.r, COLOR_STEPS),\n quantize(segment.color.g, COLOR_STEPS),\n quantize(segment.color.b, COLOR_STEPS),\n ];\n break;\n case \"strobe\":\n values = [\n ...common,\n quantize(segment.interval_ms ?? 200, INTERVAL_STEPS_MS),\n quantizeBrightness(segment),\n quantize(segment.color.r, COLOR_STEPS),\n quantize(segment.color.g, COLOR_STEPS),\n quantize(segment.color.b, COLOR_STEPS),\n ];\n break;\n case \"steady\":\n values = [\n ...common,\n quantizeBrightness(segment),\n quantize(segment.color.r, COLOR_STEPS),\n quantize(segment.color.g, COLOR_STEPS),\n quantize(segment.color.b, COLOR_STEPS),\n ];\n break;\n }\n\n return values.map((value) => PROTOCOL_DIGITS[value]).join(\"\");\n}\n\nfunction quantize(value: number, steps: readonly number[]): number {\n let bestIndex = 0;\n let bestDistance = Number.POSITIVE_INFINITY;\n\n for (const [index, step] of steps.entries()) {\n const distance = Math.abs(value - step);\n if (distance < bestDistance) {\n bestIndex = index;\n bestDistance = distance;\n }\n }\n\n return bestIndex;\n}\n\n/** duration_s=0 maps to v11 (infinite); otherwise quantize to DURATION_STEPS_S */\nfunction quantizeDuration(duration_s: number): number {\n if (duration_s === 0) return 11;\n return quantize(duration_s, DURATION_STEPS_S);\n}\n\n/**\n * brightness=0 maps to v11 (explicit off, only valid in STEADY mode per firmware).\n * Otherwise quantize to BRIGHTNESS_STEPS (v0–v5).\n */\nfunction quantizeBrightness(segment: LightSegment): number {\n if (segment.brightness === 0) return 11;\n return quantize(segment.brightness, BRIGHTNESS_STEPS);\n}\n\nfunction quantizeBreathRiseFall(value: number | undefined): number {\n return quantize(value ?? 1040, BREATH_STEPS_MS);\n}\n\nfunction quantizeBreathHoldOff(value: number | undefined): number {\n if (value === 0) {\n return 5;\n }\n\n return quantize(value ?? 1040, BREATH_STEPS_MS.slice(0, 5));\n}\n\nfunction quantizeWindow(value: 1 | 2 | 3): number {\n return value - 1;\n}\n","import { randomUUID } from \"node:crypto\";\nimport { buildLightEffectApnsBody } from \"./protocol.js\";\nimport { getEnvUrls } from \"../env.js\";\nimport type { LightSegment } from \"../types.js\";\n\nexport interface SendLightResult {\n ok: boolean;\n bizUniqueId?: string;\n response?: unknown;\n status?: number;\n error?: string;\n}\n\nexport async function sendLightEffect(\n apiKey: string,\n segments: LightSegment[],\n logger?: { info: (msg: string) => void; warn: (msg: string) => void },\n repeat?: boolean,\n): Promise<SendLightResult> {\n const apiUrl = getEnvUrls().lightApiUrl;\n const appKey = process.env.LIGHT_APP_KEY;\n const templateId = process.env.LIGHT_TEMPLATE_ID;\n\n logger?.info(\n `Light sender: apiUrl=${apiUrl ?? \"UNSET\"}, appKey=${appKey ? appKey.substring(0, 8) + \"…\" : \"UNSET\"}, templateId=${templateId ?? \"UNSET\"}, apiKey=${apiKey ? apiKey.substring(0, 20) + \"…\" : \"EMPTY\"}, segments=${JSON.stringify(segments)}`,\n );\n\n if (!apiUrl || !appKey || !templateId) {\n return {\n ok: false,\n error:\n \"灯效 API 未配置,请设置环境变量 LIGHT_API_URL / LIGHT_APP_KEY / LIGHT_TEMPLATE_ID\",\n };\n }\n\n const bizContent = buildLightEffectApnsBody(segments, repeat);\n const bizUniqueId = randomUUID();\n\n const requestBody = {\n appKey,\n bizMap: { noticeType: \"APP_NOTIFICATION_IMPORTANT\" },\n bizUniqueId,\n paramsMap: { bizContent },\n pushType: \"SPECIFY_PUSH\",\n templateId,\n };\n\n logger?.info(\n `Light sender: POST ${apiUrl}, bizUniqueId=${bizUniqueId}, body=${JSON.stringify(requestBody).substring(0, 500)}`,\n );\n\n const res = await fetch(apiUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-Api-Key-Id\": apiKey.startsWith(\"Bearer \")\n ? apiKey.slice(\"Bearer \".length)\n : apiKey,\n },\n body: JSON.stringify(requestBody),\n });\n\n const resBody = await res.text();\n if (!res.ok) {\n logger?.warn(\n `Light sender: FAILED ${res.status}, url=${apiUrl}, resBody=${resBody.substring(0, 500)}`,\n );\n return { ok: false, status: res.status, error: resBody };\n }\n\n logger?.info(`Light sender: OK bizUniqueId=${bizUniqueId}, resBody=${resBody.substring(0, 200)}`);\n return { ok: true, bizUniqueId, response: JSON.parse(resBody) };\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport { resolveStateFile } from \"./host.js\";\n\nexport type EnvName = \"development\" | \"production\";\n\ninterface EnvUrls {\n lightApiUrl: string;\n appNameMapUrl: string;\n relayTunnelUrl: string;\n}\n\nconst ENV_CONFIG: Record<EnvName, EnvUrls> = {\n development: {\n lightApiUrl: \"https://openclaw-service-dev.yoootek.com/api/message/tob/sendMessage\",\n relayTunnelUrl: \"wss://openclaw-service-dev.yoootek.com/message/messages/ws/plugin\",\n appNameMapUrl:\n \"https://openclaw-service-dev.yoootek.com/api/application-config/app-package/config-all\",\n },\n production: {\n lightApiUrl: \"https://openclaw-service.yoootek.com/api/message/tob/sendMessage\",\n relayTunnelUrl: \"wss://openclaw-service.yoootek.com/message/messages/ws/plugin\",\n appNameMapUrl:\n \"https://openclaw-service.yoootek.com/api/application-config/app-package/config-all\",\n },\n};\n\nconst VALID_ENVS: ReadonlySet<string> = new Set(Object.keys(ENV_CONFIG));\n\nfunction envFilePath(): string {\n return resolveStateFile(\"env.json\");\n}\n\n/** 读取当前环境名称,默认 production */\nexport function loadEnvName(): EnvName {\n const filePath = envFilePath();\n if (!existsSync(filePath)) return \"production\";\n try {\n const data = JSON.parse(readFileSync(filePath, \"utf-8\")) as { env?: string };\n if (data.env && VALID_ENVS.has(data.env)) return data.env as EnvName;\n } catch {\n // ignore\n }\n return \"production\";\n}\n\n/** 持久化当前环境 */\nexport function saveEnvName(env: EnvName): void {\n if (!VALID_ENVS.has(env)) {\n throw new Error(`无效的环境名称: ${env},可选值: ${[...VALID_ENVS].join(\", \")}`);\n }\n const filePath = envFilePath();\n mkdirSync(dirname(filePath), { recursive: true, mode: 0o700 });\n writeFileSync(filePath, JSON.stringify({ env }, null, 2), {\n encoding: \"utf-8\",\n mode: 0o600,\n });\n}\n\n/** 获取当前环境的 URL 配置 */\nexport function getEnvUrls(env?: EnvName): EnvUrls {\n return ENV_CONFIG[env ?? loadEnvName()];\n}\n\n/** 获取所有可用环境名称 */\nexport function getAvailableEnvs(): EnvName[] {\n return Object.keys(ENV_CONFIG) as EnvName[];\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\n\nexport type HostKind = \"openclaw\" | \"qclaw\";\n\ninterface QClawMeta {\n stateDir?: string;\n configPath?: string;\n}\n\nfunction trimToUndefined(value: unknown): string | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n const trimmed = value.trim();\n return trimmed || undefined;\n}\n\nfunction homeDir(): string {\n return process.env.HOME || process.env.USERPROFILE || \"/tmp\";\n}\n\nfunction expandUserPath(value: string | undefined): string | undefined {\n if (!value) {\n return undefined;\n }\n if (value === \"~\") {\n return homeDir();\n }\n if (value.startsWith(\"~/\")) {\n return join(homeDir(), value.slice(2));\n }\n return value;\n}\n\nfunction detectHostKindFromPath(value: string | undefined): HostKind | undefined {\n if (!value) {\n return undefined;\n }\n const normalized = value.replace(/\\\\/g, \"/\").toLowerCase();\n if (\n normalized.endsWith(\"/.qclaw\") ||\n normalized.includes(\"/.qclaw/\") ||\n normalized.endsWith(\"/.qclow\") ||\n normalized.includes(\"/.qclow/\")\n ) {\n return \"qclaw\";\n }\n if (\n normalized.endsWith(\"/.openclaw\") ||\n normalized.includes(\"/.openclaw/\")\n ) {\n return \"openclaw\";\n }\n return undefined;\n}\n\nfunction candidateMetaPaths(): string[] {\n const home = homeDir();\n return [\n join(home, \".qclaw\", \"qclaw.json\"),\n join(home, \".qclow\", \"qclaw.json\"),\n ];\n}\n\nfunction loadQClawMeta(): QClawMeta | undefined {\n for (const metaPath of candidateMetaPaths()) {\n if (!existsSync(metaPath)) {\n continue;\n }\n try {\n const parsed = JSON.parse(readFileSync(metaPath, \"utf-8\")) as QClawMeta;\n return {\n stateDir: expandUserPath(trimToUndefined(parsed?.stateDir)),\n configPath: expandUserPath(trimToUndefined(parsed?.configPath)),\n };\n } catch {\n // ignore invalid metadata and keep trying\n }\n }\n return undefined;\n}\n\nfunction resolveStateDirFromEnv(): string | undefined {\n return expandUserPath(\n trimToUndefined(process.env.OPENCLAW_STATE_DIR) ??\n trimToUndefined(process.env.QCLAW_STATE_DIR) ??\n trimToUndefined(process.env.OPENCLAW_ROOT) ??\n trimToUndefined(process.env.OPENCLAW_HOME) ??\n trimToUndefined(process.env.QCLAW_HOME),\n );\n}\n\nfunction resolveConfigPathFromEnv(): string | undefined {\n return expandUserPath(\n trimToUndefined(process.env.OPENCLAW_CONFIG_PATH) ??\n trimToUndefined(process.env.QCLAW_CONFIG_PATH),\n );\n}\n\nfunction hasOpenClawMarkers(): boolean {\n const baseDir = join(homeDir(), \".openclaw\");\n return [\n join(baseDir, \"openclaw.json\"),\n join(baseDir, \"credentials.json\"),\n join(baseDir, \"extensions\"),\n ].some((candidate) => existsSync(candidate));\n}\n\nexport function detectHostKind(): HostKind {\n if (\n trimToUndefined(process.env.QCLAW_STATE_DIR) ||\n trimToUndefined(process.env.QCLAW_CONFIG_PATH) ||\n trimToUndefined(process.env.QCLAW_HOME)\n ) {\n return \"qclaw\";\n }\n\n const pathHintKind =\n detectHostKindFromPath(resolveStateDirFromEnv()) ??\n detectHostKindFromPath(resolveConfigPathFromEnv());\n if (pathHintKind) {\n return pathHintKind;\n }\n\n if (hasOpenClawMarkers()) {\n return \"openclaw\";\n }\n\n if (loadQClawMeta()) {\n return \"qclaw\";\n }\n\n return \"openclaw\";\n}\n\nexport function resolveStateDir(): string {\n const envDir = resolveStateDirFromEnv();\n if (envDir) {\n return envDir;\n }\n\n if (hasOpenClawMarkers()) {\n return join(homeDir(), \".openclaw\");\n }\n\n const meta = loadQClawMeta();\n if (meta?.stateDir) {\n return meta.stateDir;\n }\n if (meta?.configPath) {\n return dirname(meta.configPath);\n }\n\n return join(homeDir(), \".openclaw\");\n}\n\nexport function resolveConfigPath(stateDir = resolveStateDir()): string {\n const envConfigPath = resolveConfigPathFromEnv();\n if (envConfigPath) {\n return envConfigPath;\n }\n\n const meta = loadQClawMeta();\n if (\n meta?.configPath &&\n (!meta.stateDir || !stateDir || meta.stateDir === stateDir)\n ) {\n return meta.configPath;\n }\n\n return join(stateDir, \"openclaw.json\");\n}\n\nexport function resolveStateFile(filename: string): string {\n return join(resolveStateDir(), filename);\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { loadApiKey, watchCredentials } from \"../auth/credentials.js\";\nimport { getEnvUrls } from \"../env.js\";\n\nconst PLUGIN_STATE_DIR = \"phone-notifications\";\nconst CACHE_FILE = \"app-name-map.json\";\n\n/** 包名→应用名映射 API 地址(默认随环境变化;可用 APP_NAME_MAP_URL 覆盖;需鉴权) */\nconst BUILTIN_APP_NAME_MAP_URL = getEnvUrls().appNameMapUrl;\nconst APP_NAME_MAP_URL =\n (typeof process.env.APP_NAME_MAP_URL === \"string\" && process.env.APP_NAME_MAP_URL.trim()\n ? process.env.APP_NAME_MAP_URL.trim()\n : undefined) ?? BUILTIN_APP_NAME_MAP_URL;\n/** 映射刷新间隔(小时) */\nconst APP_NAME_MAP_REFRESH_HOURS = 12;\n\ninterface Logger {\n info: (message: string) => void;\n warn: (message: string) => void;\n}\n\nfunction isRecordOfStrings(v: unknown): v is Record<string, string> {\n if (v === null || typeof v !== \"object\") return false;\n for (const val of Object.values(v)) if (typeof val !== \"string\") return false;\n return true;\n}\n\n/** API 返回的单项 */\ninterface AppPackageItem {\n appName: string;\n packageName: string;\n iconUrl?: string | null;\n platform?: string | null;\n jumpUrl?: string | null;\n urlParams?: string | null;\n description?: string | null;\n}\n\n/** API 响应格式 */\ninterface AppNameMapApiResponse {\n success?: boolean;\n code?: string;\n message?: string;\n data?: AppPackageItem[];\n}\n\nfunction isAppNameMapApiResponse(v: unknown): v is AppNameMapApiResponse {\n if (v === null || typeof v !== \"object\") return false;\n const o = v as Record<string, unknown>;\n return Array.isArray(o.data) && o.data.every(\n (item: unknown) =>\n item !== null &&\n typeof item === \"object\" &&\n typeof (item as AppPackageItem).packageName === \"string\" &&\n typeof (item as AppPackageItem).appName === \"string\"\n );\n}\n\nfunction getCachePath(stateDir: string): string {\n return join(stateDir, \"plugins\", PLUGIN_STATE_DIR, CACHE_FILE);\n}\n\nexport interface AppNameMapProvider {\n /** 解析包名为显示名(未命中时拉取一次再返回,保证当前落库即有值) */\n resolveDisplayName(packageName: string): Promise<string>;\n start(): Promise<void>;\n stop(): void;\n}\n\nexport function createAppNameMapProvider(opts: {\n stateDir: string;\n logger: Logger;\n}): AppNameMapProvider {\n const { stateDir, logger } = opts;\n const url = APP_NAME_MAP_URL;\n const refreshHours = APP_NAME_MAP_REFRESH_HOURS;\n\n const map = new Map<string, string>();\n let refreshTimer: ReturnType<typeof setInterval> | null = null;\n let stopWatching: (() => void) | null = null;\n let inFlightFetch: Promise<void> | null = null;\n\n function loadFromDisk(): void {\n const path = getCachePath(stateDir);\n if (!existsSync(path)) return;\n try {\n const raw = JSON.parse(readFileSync(path, \"utf-8\"));\n if (!isRecordOfStrings(raw)) return;\n map.clear();\n for (const [k, v] of Object.entries(raw)) map.set(k, v);\n logger.info(`[app-name-map] loaded ${map.size} entries from cache: ${path}`);\n } catch {\n /* ignore */\n }\n }\n\n async function fetchFromServer(): Promise<void> {\n const apiKey = loadApiKey();\n if (!url) {\n logger.warn(\"[app-name-map] APP_NAME_MAP_URL is empty, skip refresh\");\n return;\n }\n if (!apiKey) {\n logger.info(\"[app-name-map] api key missing, skip refresh\");\n return;\n }\n\n const rawApiKey = apiKey.startsWith(\"Bearer \")\n ? apiKey.slice(\"Bearer \".length)\n : apiKey;\n try {\n const res = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", \"X-Api-Key-Id\": rawApiKey },\n body: JSON.stringify({\n platform: \"\"\n })\n });\n if (!res.ok) {\n logger.warn(`[app-name-map] refresh failed: HTTP ${res.status} ${res.statusText}`);\n return;\n }\n const body = await res.json() as unknown;\n if (!isAppNameMapApiResponse(body) || !body.success || !body.data?.length) {\n logger.warn(\"[app-name-map] refresh failed: unexpected response shape or empty data\");\n return;\n }\n map.clear();\n for (const item of body.data) {\n if (item.packageName && item.appName) map.set(item.packageName, item.appName);\n }\n if (map.size === 0) {\n logger.warn(\"[app-name-map] refresh succeeded but got 0 entries\");\n return;\n }\n const dir = join(stateDir, \"plugins\", PLUGIN_STATE_DIR);\n\n mkdirSync(dir, { recursive: true });\n const cachePath = getCachePath(stateDir);\n writeFileSync(cachePath, JSON.stringify(Object.fromEntries(map), null, 2), \"utf-8\");\n logger.info(`[app-name-map] refreshed ${map.size} entries from server and saved: ${cachePath}`);\n } catch (e) {\n const message = e instanceof Error ? e.message : String(e);\n logger.warn(`[app-name-map] refresh error: ${message}`);\n }\n }\n\n async function ensureOneFetch(): Promise<void> {\n if (inFlightFetch) return inFlightFetch;\n inFlightFetch = fetchFromServer().finally(() => {\n inFlightFetch = null;\n });\n return inFlightFetch;\n }\n\n return {\n async resolveDisplayName(packageName: string): Promise<string> {\n // 临时策略:仅使用内存/磁盘中已有的映射,缺少时不主动触发拉取\n if (map.has(packageName)) return map.get(packageName)!;\n return packageName;\n // 如需在缺少应用名时触发一次拉取再返回,可恢复为:\n // if (!url || !loadApiKey()) return packageName;\n // await ensureOneFetch();\n // return map.get(packageName) ?? packageName;\n },\n\n async start(): Promise<void> {\n loadFromDisk();\n await fetchFromServer();\n\n if (!url) return;\n\n if (refreshHours > 0) {\n const ms = refreshHours * 60 * 60 * 1000;\n refreshTimer = setInterval(() => fetchFromServer().catch(() => { }), ms);\n }\n stopWatching = watchCredentials(() => fetchFromServer().catch(() => { }));\n },\n\n stop(): void {\n stopWatching?.();\n stopWatching = null;\n if (refreshTimer) {\n clearInterval(refreshTimer);\n refreshTimer = null;\n }\n map.clear();\n },\n };\n}\n","import {\n existsSync,\n mkdirSync,\n readFileSync,\n writeFileSync,\n watch,\n} from \"node:fs\";\nimport { dirname, basename } from \"node:path\";\nimport { resolveStateFile } from \"../host.js\";\n\ninterface Credentials {\n /**\n * 推荐:API Key 明文(例如 ock_xxx)\n */\n apiKey?: string;\n /**\n * 兼容旧字段:历史上这里存的是 token;现在等价于 apiKey\n */\n token?: string;\n}\n\nexport function credentialsPath(): string {\n return resolveStateFile(\"credentials.json\");\n}\n\nexport function readCredentials(): Credentials {\n const path = credentialsPath();\n if (!existsSync(path)) return {};\n try {\n return JSON.parse(readFileSync(path, \"utf-8\"));\n } catch {\n return {};\n }\n}\n\nexport function writeCredentials(creds: Credentials): void {\n const path = credentialsPath();\n mkdirSync(dirname(path), { recursive: true, mode: 0o700 });\n writeFileSync(path, JSON.stringify(creds, null, 2), {\n encoding: \"utf-8\",\n mode: 0o600,\n });\n}\n\nexport function loadApiKey(): string | undefined {\n const creds = readCredentials();\n return creds.apiKey ?? creds.token;\n}\n\nexport function requireApiKey(): string {\n const apiKey = loadApiKey();\n if (!apiKey) {\n throw new Error(\n `API Key 未设置,请先写入 ${credentialsPath()},或通过宿主 CLI 执行 ntf auth set-api-key <apiKey>`,\n );\n }\n return apiKey;\n}\n\n// ---- Backward-compatible exports (旧代码仍可编译;语义等价于 apiKey) ----\nexport function loadToken(): string | undefined {\n return loadApiKey();\n}\n\nexport function requireToken(): string {\n return requireApiKey();\n}\n\n/** 监听 credentials 文件变化(如 set-token 后)触发 callback;返回取消监听的函数 */\nexport function watchCredentials(onChange: () => void): () => void {\n const path = credentialsPath();\n const dir = dirname(path);\n const filename = basename(path);\n let debounceTimer: ReturnType<typeof setTimeout> | null = null;\n const delayMs = 200;\n\n const listener = (_event: string, changedName: string | null) => {\n if (!changedName || (changedName !== filename && !changedName.endsWith(filename))) return;\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => {\n debounceTimer = null;\n onChange();\n }, delayMs);\n };\n\n let watcher: ReturnType<typeof watch> | null = null;\n try {\n watcher = watch(dir, { persistent: false }, listener);\n } catch {\n // 目录可能不存在\n }\n\n return () => {\n if (debounceTimer) clearTimeout(debounceTimer);\n watcher?.close();\n };\n}\n","import {\n accessSync,\n mkdirSync,\n appendFileSync,\n readdirSync,\n readFileSync,\n writeFileSync,\n existsSync,\n rmSync,\n constants,\n} from \"node:fs\";\nimport { createHash } from \"node:crypto\";\nimport { join } from \"node:path\";\nimport type { PluginConfig, RawNotification } from \"../types.js\";\n\ninterface Logger {\n info: (message: string) => void;\n warn: (message: string) => void;\n}\n\nexport interface StorageContext {\n stateDir: string;\n workspaceDir?: string;\n}\n\n/** Stored notification entry (JSON format, append-only) */\nexport interface StoredNotification {\n /** 包名 */\n appName: string;\n /** 应用显示名(由映射补全),缺省时与 appName 一致 */\n appDisplayName?: string;\n title: string;\n content: string;\n /** ISO 8601 with timezone, e.g. \"2026-03-02T08:30:00+08:00\" */\n timestamp: string;\n}\n\nconst NOTIFICATION_DIR_NAME = \"notifications\";\nconst ID_INDEX_DIR_NAME = \".ids\";\nconst CONTENT_KEY_INDEX_DIR_NAME = \".keys\";\n\nexport interface NotificationIngestResult {\n received: number;\n ingested: number;\n dedupedById: number;\n dedupedByContent: number;\n invalid: number;\n}\n\ntype WriteOutcome =\n | \"ingested\"\n | \"dedupedById\"\n | \"dedupedByContent\"\n | \"invalid\";\n\nexport function getStateFallbackNotificationDir(stateDir: string): string {\n return join(stateDir, \"plugins\", \"phone-notifications\", NOTIFICATION_DIR_NAME);\n}\n\nfunction ensureWritableDirectory(dir: string): boolean {\n try {\n mkdirSync(dir, { recursive: true });\n accessSync(dir, constants.R_OK | constants.W_OK);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function resolveNotificationStorageDir(\n ctx: StorageContext,\n logger: Pick<Logger, \"info\" | \"warn\">,\n): string {\n // 优先使用 stateDir(插件私有稳定路径),避免通知随 workspace 切换而分散\n const stateNotifDir = getStateFallbackNotificationDir(ctx.stateDir);\n\n if (ensureWritableDirectory(stateNotifDir)) {\n logger.info(`通知将写入 stateDir 路径: ${stateNotifDir}`);\n return stateNotifDir;\n }\n\n // stateDir 不可用时回退到 workspaceDir\n if (ctx.workspaceDir) {\n const workspaceDir = join(ctx.workspaceDir, NOTIFICATION_DIR_NAME);\n if (ensureWritableDirectory(workspaceDir)) {\n logger.warn(\n `stateDir 不可用,通知已回退到 workspace 路径: ${workspaceDir}`,\n );\n return workspaceDir;\n }\n }\n\n throw new Error(`通知存储目录不可用: ${stateNotifDir}`);\n}\n\n/** 包名 → 应用显示名(异步,未命中时内部可拉取后返回);不提供则落库仅用 appName */\nexport type ResolveDisplayName = (packageName: string) => Promise<string>;\n\nexport class NotificationStorage {\n private dir: string;\n private idIndexDir: string;\n private contentKeyIndexDir: string;\n private idCache = new Map<string, Set<string>>();\n private contentKeyCache = new Map<string, Set<string>>();\n private dateWriteChains = new Map<string, Promise<void>>();\n private resolveDisplayName: ResolveDisplayName | undefined;\n\n constructor(\n dir: string,\n private config: PluginConfig,\n private logger: Logger,\n resolveDisplayName?: ResolveDisplayName,\n ) {\n this.dir = dir;\n this.idIndexDir = join(dir, ID_INDEX_DIR_NAME);\n this.contentKeyIndexDir = join(dir, CONTENT_KEY_INDEX_DIR_NAME);\n this.resolveDisplayName = resolveDisplayName;\n }\n\n async init() {\n mkdirSync(this.dir, { recursive: true });\n mkdirSync(this.idIndexDir, { recursive: true });\n mkdirSync(this.contentKeyIndexDir, { recursive: true });\n }\n\n async ingest(items: RawNotification[]): Promise<NotificationIngestResult> {\n const result: NotificationIngestResult = {\n received: items.length,\n ingested: 0,\n dedupedById: 0,\n dedupedByContent: 0,\n invalid: 0,\n };\n\n for (const n of items) {\n const outcome = await this.writeNotification(n);\n result[outcome] += 1;\n }\n this.prune();\n return result;\n }\n\n private async writeNotification(n: RawNotification): Promise<WriteOutcome> {\n const ts = new Date(n.timestamp);\n if (Number.isNaN(ts.getTime())) {\n this.logger.warn(`忽略非法 timestamp 的通知: ${n.id}`);\n return \"invalid\";\n }\n\n const dateKey = this.formatDate(ts);\n const filePath = join(this.dir, `${dateKey}.json`);\n const normalizedId = typeof n.id === \"string\" ? n.id.trim() : \"\";\n const entry = this.buildStoredNotification(n);\n\n return this.withDateWriteLock(dateKey, async () => {\n if (normalizedId && this.hasNotificationId(dateKey, normalizedId)) {\n return \"dedupedById\";\n }\n\n if (this.hasNotificationContentKey(dateKey, filePath, entry)) {\n return \"dedupedByContent\";\n }\n\n const appDisplayName = this.resolveDisplayName\n ? await this.resolveDisplayName(entry.appName)\n : entry.appName;\n\n const storedEntry: StoredNotification = {\n ...entry,\n appDisplayName,\n };\n\n const arr = this.readStoredNotifications(filePath);\n arr.push(storedEntry);\n writeFileSync(filePath, JSON.stringify(arr, null, 2), \"utf-8\");\n\n if (normalizedId) {\n this.recordNotificationId(dateKey, normalizedId);\n }\n this.recordNotificationContentKey(dateKey, filePath, storedEntry);\n return \"ingested\";\n });\n }\n\n private buildStoredNotification(n: RawNotification): StoredNotification {\n return {\n appName: typeof n.app === \"string\" && n.app ? n.app : \"Unknown\",\n title: typeof n.title === \"string\" ? n.title : \"\",\n content: this.buildContent(n),\n timestamp: n.timestamp,\n };\n }\n\n private buildContent(n: RawNotification): string {\n const body = n.body?.trim();\n if (body) {\n return body;\n }\n\n const fallback: string[] = [];\n if (n.category) {\n fallback.push(`category:${n.category}`);\n }\n\n if (n.metadata && Object.keys(n.metadata).length > 0) {\n fallback.push(`metadata:${JSON.stringify(n.metadata)}`);\n }\n\n return fallback.join(\" ; \") || \"-\";\n }\n\n private formatDate(d: Date): string {\n const year = d.getFullYear();\n const month = String(d.getMonth() + 1).padStart(2, \"0\");\n const day = String(d.getDate()).padStart(2, \"0\");\n return `${year}-${month}-${day}`;\n }\n\n private getIdIndexPath(dateKey: string): string {\n return join(this.idIndexDir, `${dateKey}.ids`);\n }\n\n private getIdSet(dateKey: string): Set<string> {\n const cached = this.idCache.get(dateKey);\n if (cached) {\n return cached;\n }\n\n const idPath = this.getIdIndexPath(dateKey);\n const ids = new Set<string>();\n if (existsSync(idPath)) {\n const lines = readFileSync(idPath, \"utf-8\").split(/\\r?\\n/);\n for (const line of lines) {\n const id = line.trim();\n if (id) {\n ids.add(id);\n }\n }\n }\n\n this.idCache.set(dateKey, ids);\n return ids;\n }\n\n private getContentKeyIndexPath(dateKey: string): string {\n return join(this.contentKeyIndexDir, `${dateKey}.keys`);\n }\n\n private getContentKeySet(dateKey: string, filePath: string): Set<string> {\n const cached = this.contentKeyCache.get(dateKey);\n if (cached) {\n return cached;\n }\n\n const keyPath = this.getContentKeyIndexPath(dateKey);\n const keys = new Set<string>();\n\n if (existsSync(keyPath)) {\n const lines = readFileSync(keyPath, \"utf-8\").split(/\\r?\\n/);\n for (const line of lines) {\n const key = line.trim();\n if (key) {\n keys.add(key);\n }\n }\n } else if (existsSync(filePath)) {\n for (const item of this.readStoredNotifications(filePath)) {\n keys.add(this.buildNotificationContentKey(item));\n }\n\n if (keys.size > 0) {\n writeFileSync(keyPath, `${Array.from(keys).join(\"\\n\")}\\n`, \"utf-8\");\n }\n }\n\n this.contentKeyCache.set(dateKey, keys);\n return keys;\n }\n\n private hasNotificationId(dateKey: string, id: string): boolean {\n return this.getIdSet(dateKey).has(id);\n }\n\n private hasNotificationContentKey(\n dateKey: string,\n filePath: string,\n entry: Pick<StoredNotification, \"appName\" | \"title\" | \"content\">,\n ): boolean {\n return this.getContentKeySet(dateKey, filePath).has(\n this.buildNotificationContentKey(entry),\n );\n }\n\n private recordNotificationId(dateKey: string, id: string) {\n const ids = this.getIdSet(dateKey);\n if (ids.has(id)) {\n return;\n }\n\n appendFileSync(this.getIdIndexPath(dateKey), `${id}\\n`, \"utf-8\");\n ids.add(id);\n }\n\n private recordNotificationContentKey(\n dateKey: string,\n filePath: string,\n entry: Pick<StoredNotification, \"appName\" | \"title\" | \"content\">,\n ) {\n const keys = this.getContentKeySet(dateKey, filePath);\n const key = this.buildNotificationContentKey(entry);\n\n if (keys.has(key)) {\n return;\n }\n\n appendFileSync(this.getContentKeyIndexPath(dateKey), `${key}\\n`, \"utf-8\");\n keys.add(key);\n }\n\n private buildNotificationContentKey(\n entry: Pick<StoredNotification, \"appName\" | \"title\" | \"content\">,\n ): string {\n return createHash(\"sha256\")\n .update(entry.appName)\n .update(\"\\x1f\")\n .update(entry.title)\n .update(\"\\x1f\")\n .update(entry.content)\n .digest(\"hex\");\n }\n\n private readStoredNotifications(filePath: string): StoredNotification[] {\n if (!existsSync(filePath)) {\n return [];\n }\n\n try {\n const parsed = JSON.parse(readFileSync(filePath, \"utf-8\"));\n return Array.isArray(parsed) ? parsed : [];\n } catch {\n return [];\n }\n }\n\n private async withDateWriteLock<T>(\n dateKey: string,\n task: () => Promise<T>,\n ): Promise<T> {\n const previous = this.dateWriteChains.get(dateKey) ?? Promise.resolve();\n let release!: () => void;\n const current = new Promise<void>((resolve) => {\n release = resolve;\n });\n const chain = previous.then(() => current);\n this.dateWriteChains.set(dateKey, chain);\n\n await previous;\n try {\n return await task();\n } finally {\n release();\n if (this.dateWriteChains.get(dateKey) === chain) {\n this.dateWriteChains.delete(dateKey);\n }\n }\n }\n\n private prune() {\n const retentionDays = this.config.retentionDays ?? 30;\n const cutoffMs = Date.now() - retentionDays * 24 * 60 * 60 * 1000;\n const cutoffDate = this.formatDate(new Date(cutoffMs));\n\n this.pruneDataFiles(cutoffDate);\n this.pruneIdIndex(cutoffDate);\n this.pruneContentKeyIndex(cutoffDate);\n }\n\n /** Remove expired .json, legacy .md files, and legacy date directories */\n private pruneDataFiles(cutoffDate: string) {\n const dateFilePattern = /^(\\d{4}-\\d{2}-\\d{2})\\.(json|md)$/;\n const dateDirPattern = /^\\d{4}-\\d{2}-\\d{2}$/;\n\n try {\n for (const entry of readdirSync(this.dir, { withFileTypes: true })) {\n if (entry.isFile()) {\n const match = dateFilePattern.exec(entry.name);\n if (match && match[1] < cutoffDate) {\n rmSync(join(this.dir, entry.name), { force: true });\n }\n } else if (entry.isDirectory() && dateDirPattern.test(entry.name) && entry.name < cutoffDate) {\n rmSync(join(this.dir, entry.name), { recursive: true, force: true });\n }\n }\n } catch {\n // ignore\n }\n }\n\n /** Remove expired .ids index files */\n private pruneIdIndex(cutoffDate: string) {\n try {\n for (const entry of readdirSync(this.idIndexDir, { withFileTypes: true })) {\n if (!entry.isFile()) continue;\n const match = /^(\\d{4}-\\d{2}-\\d{2})\\.ids$/.exec(entry.name);\n if (match && match[1] < cutoffDate) {\n rmSync(join(this.idIndexDir, entry.name), { force: true });\n this.idCache.delete(match[1]);\n }\n }\n } catch {\n // ignore\n }\n }\n\n /** Remove expired .keys index files */\n private pruneContentKeyIndex(cutoffDate: string) {\n try {\n for (const entry of readdirSync(this.contentKeyIndexDir, { withFileTypes: true })) {\n if (!entry.isFile()) continue;\n const match = /^(\\d{4}-\\d{2}-\\d{2})\\.keys$/.exec(entry.name);\n if (match && match[1] < cutoffDate) {\n rmSync(join(this.contentKeyIndexDir, entry.name), { force: true });\n this.contentKeyCache.delete(match[1]);\n }\n }\n } catch {\n // ignore\n }\n }\n\n async close() {\n this.idCache.clear();\n this.contentKeyCache.clear();\n this.dateWriteChains.clear();\n }\n}\n","import { existsSync, rmSync } from \"node:fs\";\nimport type { CliCommand } from \"./helpers.js\";\nimport { output } from \"./helpers.js\";\nimport {\n credentialsPath,\n readCredentials,\n writeCredentials,\n} from \"../auth/credentials.js\";\n\nexport function registerAuthCli(program: CliCommand): void {\n const auth = program\n .command(\"auth\")\n .description(\"用户认证管理\");\n\n auth\n .command(\"set-api-key <apiKey>\")\n .description(\"设置用户 API Key(持久化到本地配置)\")\n .action((apiKey: string) => {\n writeCredentials({ ...readCredentials(), apiKey, token: undefined });\n output({\n ok: true,\n apiKey: apiKey.slice(0, 8) + \"…\",\n storedAt: credentialsPath(),\n });\n });\n\n // 兼容旧命令:set-token <token>,现在等价于 set-api-key\n auth\n .command(\"set-token <token>\")\n .description(\"(兼容)设置用户 API Key(旧命令名)\")\n .action((token: string) => {\n writeCredentials({ ...readCredentials(), apiKey: token, token: undefined });\n output({\n ok: true,\n apiKey: token.slice(0, 8) + \"…\",\n storedAt: credentialsPath(),\n });\n });\n\n auth\n .command(\"show\")\n .description(\"查看当前认证状态\")\n .action(() => {\n const creds = readCredentials();\n const apiKey = creds.apiKey ?? creds.token;\n if (apiKey) {\n output({\n ok: true,\n hasApiKey: true,\n apiKey: apiKey.slice(0, 8) + \"…\",\n storedAt: credentialsPath(),\n });\n } else {\n output({ ok: true, hasApiKey: false });\n }\n });\n\n auth\n .command(\"clear\")\n .description(\"清除已保存的认证信息\")\n .action(() => {\n const path = credentialsPath();\n if (existsSync(path)) {\n const creds = readCredentials();\n delete creds.apiKey;\n delete creds.token;\n if (Object.keys(creds).length === 0) {\n rmSync(path, { force: true });\n } else {\n writeCredentials(creds);\n }\n }\n output({ ok: true, cleared: true });\n });\n}\n","import { existsSync, readFileSync, readdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { StoredNotification } from \"../notification/storage.js\";\n\n/**\n * Minimal Commander.js Command interface.\n * The real `Command` instance comes from the openclaw runtime at registration time;\n * we only declare the subset we use so that `commander` need not be a direct dep.\n */\nexport interface CliCommand {\n command(nameAndArgs: string): CliCommand;\n description(str: string): CliCommand;\n version(str: string, flags?: string, description?: string): CliCommand;\n option(flags: string, description: string, defaultValue?: string): CliCommand;\n requiredOption(flags: string, description: string): CliCommand;\n action(fn: (...args: any[]) => void | Promise<void>): CliCommand;\n}\n\nexport interface CliContext {\n workspaceDir?: string;\n stateDir?: string;\n}\n\n/** Resolve the notifications storage directory (stateDir → workspace fallback) */\nexport function resolveNotificationsDir(ctx: CliContext): string | null {\n if (ctx.stateDir) {\n const dir = join(\n ctx.stateDir,\n \"plugins\",\n \"phone-notifications\",\n \"notifications\",\n );\n if (existsSync(dir)) return dir;\n }\n if (ctx.workspaceDir) {\n const dir = join(ctx.workspaceDir, \"notifications\");\n if (existsSync(dir)) return dir;\n }\n return null;\n}\n\n/** List available date keys (YYYY-MM-DD) sorted descending */\nexport function listDateKeys(dir: string): string[] {\n const pattern = /^(\\d{4}-\\d{2}-\\d{2})\\.json$/;\n const keys: string[] = [];\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n if (!entry.isFile()) continue;\n const m = pattern.exec(entry.name);\n if (m) keys.push(m[1]);\n }\n return keys.sort().reverse();\n}\n\n/** Read notifications for a specific date */\nexport function readDateFile(\n dir: string,\n dateKey: string,\n): StoredNotification[] {\n const filePath = join(dir, `${dateKey}.json`);\n if (!existsSync(filePath)) return [];\n try {\n return JSON.parse(readFileSync(filePath, \"utf-8\"));\n } catch {\n return [];\n }\n}\n\n/** Format today as YYYY-MM-DD */\nexport function today(): string {\n return formatDate(new Date());\n}\n\n/** Format a Date as YYYY-MM-DD */\nexport function formatDate(d: Date): string {\n const y = d.getFullYear();\n const m = String(d.getMonth() + 1).padStart(2, \"0\");\n const day = String(d.getDate()).padStart(2, \"0\");\n return `${y}-${m}-${day}`;\n}\n\n/** Get date N days ago as YYYY-MM-DD */\nexport function daysAgo(n: number): string {\n const d = new Date();\n d.setDate(d.getDate() - n);\n return formatDate(d);\n}\n\n/** Filter date keys to a [from, to] range (inclusive) */\nexport function filterDateRange(\n keys: string[],\n from: string,\n to: string,\n): string[] {\n return keys.filter((k) => k >= from && k <= to);\n}\n\n/** Print JSON result to stdout */\nexport function output(data: unknown): void {\n process.stdout.write(JSON.stringify(data, null, 2) + \"\\n\");\n}\n\n/** Print error JSON and exit with code 1 */\nexport function exitError(code: string, message: string): never {\n output({ ok: false, error: { code, message } });\n process.exit(1);\n}\n","import type { StoredNotification } from \"../notification/storage.js\";\nimport {\n type CliCommand,\n type CliContext,\n resolveNotificationsDir,\n listDateKeys,\n readDateFile,\n filterDateRange,\n today,\n daysAgo,\n output,\n exitError,\n} from \"./helpers.js\";\n\nexport function registerNtfSearch(ntf: CliCommand, ctx: CliContext): void {\n ntf\n .command(\"search\")\n .description(\"查询通知(按日期/应用/发送人/关键词筛选)\")\n .option(\"--from <date>\", \"开始日期 YYYY-MM-DD\", daysAgo(7))\n .option(\"--to <date>\", \"结束日期 YYYY-MM-DD\", today())\n .option(\"--app <name>\", \"按应用名过滤\")\n .option(\"--sender <name>\", \"按发送人过滤\")\n .option(\"--keyword <text>\", \"在标题和内容中搜索关键词\")\n .option(\"--limit <n>\", \"最大返回条数\", \"100\")\n .action(\n (opts: {\n from: string;\n to: string;\n app?: string;\n sender?: string;\n keyword?: string;\n limit: string;\n }) => {\n const dir = resolveNotificationsDir(ctx);\n if (!dir) exitError(\"STORAGE_UNAVAILABLE\", \"通知存储目录不可用\");\n\n const keys = filterDateRange(listDateKeys(dir), opts.from, opts.to);\n const limit = parseInt(opts.limit, 10) || 100;\n const results: StoredNotification[] = [];\n\n for (const dateKey of keys) {\n if (results.length >= limit) break;\n const items = readDateFile(dir, dateKey);\n for (const item of items) {\n if (results.length >= limit) break;\n if (opts.app && item.appName !== opts.app) continue;\n if (opts.sender && !item.title.includes(opts.sender)) continue;\n if (\n opts.keyword &&\n !item.title.includes(opts.keyword) &&\n !item.content.includes(opts.keyword)\n )\n continue;\n results.push(item);\n }\n }\n\n output({\n ok: true,\n total: results.length,\n notifications: results,\n });\n },\n );\n}\n","import {\n type CliCommand,\n type CliContext,\n resolveNotificationsDir,\n listDateKeys,\n readDateFile,\n filterDateRange,\n today,\n daysAgo,\n output,\n exitError,\n} from \"./helpers.js\";\n\ntype Dimension = \"date\" | \"app\" | \"sender\" | \"hour\" | \"all\";\n\nexport function registerNtfStats(ntf: CliCommand, ctx: CliContext): void {\n ntf\n .command(\"stats\")\n .description(\"通知统计分析(按日期/应用/发送人/时段聚合)\")\n .option(\"--from <date>\", \"开始日期 YYYY-MM-DD\", daysAgo(7))\n .option(\"--to <date>\", \"结束日期 YYYY-MM-DD\", today())\n .option(\"--app <name>\", \"只统计指定应用\")\n .option(\"--dim <dimension>\", \"统计维度:date/app/sender/hour/all\", \"all\")\n .action(\n (opts: { from: string; to: string; app?: string; dim: string }) => {\n const dir = resolveNotificationsDir(ctx);\n if (!dir) exitError(\"STORAGE_UNAVAILABLE\", \"通知存储目录不可用\");\n\n const dim = opts.dim as Dimension;\n const keys = filterDateRange(listDateKeys(dir), opts.from, opts.to);\n\n const byDate: Record<string, number> = {};\n const byApp: Record<string, number> = {};\n const bySender: Record<string, number> = {};\n const byHour: Record<string, number> = {};\n let total = 0;\n\n for (const dateKey of keys) {\n const items = readDateFile(dir, dateKey);\n let dateCount = 0;\n for (const item of items) {\n if (opts.app && item.appName !== opts.app) continue;\n total++;\n dateCount++;\n\n byApp[item.appName] = (byApp[item.appName] || 0) + 1;\n\n if (item.title) {\n bySender[item.title] = (bySender[item.title] || 0) + 1;\n }\n\n const hourMatch = /T(\\d{2}):/.exec(item.timestamp);\n if (hourMatch) {\n const h = hourMatch[1];\n byHour[h] = (byHour[h] || 0) + 1;\n }\n }\n byDate[dateKey] = dateCount;\n }\n\n const result: Record<string, unknown> = {\n ok: true,\n range: { from: opts.from, to: opts.to },\n total,\n };\n\n if (dim === \"date\" || dim === \"all\") {\n result.byDate = byDate;\n }\n if (dim === \"app\" || dim === \"all\") {\n result.byApp = byApp;\n }\n if (dim === \"sender\" || dim === \"all\") {\n // Sort by count descending, return top 20\n const sorted = Object.entries(bySender)\n .sort((a, b) => b[1] - a[1])\n .slice(0, 20)\n .map(([sender, count]) => ({ sender, count }));\n result.bySender = sorted;\n }\n if (dim === \"hour\" || dim === \"all\") {\n result.byHour = byHour;\n }\n\n output(result);\n },\n );\n}\n","import { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport {\n type CliCommand,\n type CliContext,\n resolveNotificationsDir,\n listDateKeys,\n readDateFile,\n output,\n exitError,\n} from \"./helpers.js\";\n\ninterface CheckpointData {\n [dateKey: string]: { lastIndex: number };\n}\n\nfunction checkpointPath(dir: string): string {\n return join(dir, \".checkpoint.json\");\n}\n\nfunction readCheckpoint(dir: string): CheckpointData {\n const p = checkpointPath(dir);\n if (!existsSync(p)) return {};\n try {\n return JSON.parse(readFileSync(p, \"utf-8\"));\n } catch {\n return {};\n }\n}\n\nfunction writeCheckpoint(dir: string, data: CheckpointData): void {\n writeFileSync(checkpointPath(dir), JSON.stringify(data, null, 2), \"utf-8\");\n}\n\nexport function registerNtfSync(ntf: CliCommand, ctx: CliContext): void {\n const sync = ntf.command(\"sync\").description(\"同步通知到记忆系统\");\n\n sync\n .command(\"scan\")\n .description(\"扫描未处理的通知,返回待同步摘要\")\n .action(() => {\n const dir = resolveNotificationsDir(ctx);\n if (!dir) exitError(\"STORAGE_UNAVAILABLE\", \"通知存储目录不可用\");\n\n const checkpoint = readCheckpoint(dir);\n const keys = listDateKeys(dir); // descending\n const pending: { date: string; count: number; startIndex: number }[] = [];\n let totalPending = 0;\n\n for (const dateKey of keys) {\n const items = readDateFile(dir, dateKey);\n const lastIndex = checkpoint[dateKey]?.lastIndex ?? -1;\n const unprocessed = items.length - (lastIndex + 1);\n if (unprocessed > 0) {\n pending.push({\n date: dateKey,\n count: unprocessed,\n startIndex: lastIndex + 1,\n });\n totalPending += unprocessed;\n }\n }\n\n output({ ok: true, pending, totalPending });\n });\n\n sync\n .command(\"fetch\")\n .description(\"获取指定日期的未处理通知详情\")\n .requiredOption(\"--date <date>\", \"目标日期 YYYY-MM-DD\")\n .action((opts: { date: string }) => {\n const dir = resolveNotificationsDir(ctx);\n if (!dir) exitError(\"STORAGE_UNAVAILABLE\", \"通知存储目录不可用\");\n\n const items = readDateFile(dir, opts.date);\n if (items.length === 0) {\n exitError(\"NO_DATA\", `日期 ${opts.date} 无通知数据`);\n }\n\n const checkpoint = readCheckpoint(dir);\n const lastIndex = checkpoint[opts.date]?.lastIndex ?? -1;\n const startIndex = lastIndex + 1;\n const unprocessed = items.slice(startIndex);\n\n if (unprocessed.length === 0) {\n output({\n ok: true,\n date: opts.date,\n startIndex,\n notifications: [],\n });\n return;\n }\n\n output({\n ok: true,\n date: opts.date,\n startIndex,\n notifications: unprocessed,\n });\n });\n\n sync\n .command(\"commit\")\n .description(\"标记指定日期处理完成,更新 checkpoint\")\n .requiredOption(\"--date <date>\", \"目标日期 YYYY-MM-DD\")\n .action((opts: { date: string }) => {\n const dir = resolveNotificationsDir(ctx);\n if (!dir) exitError(\"STORAGE_UNAVAILABLE\", \"通知存储目录不可用\");\n\n const items = readDateFile(dir, opts.date);\n if (items.length === 0) {\n exitError(\"NO_DATA\", `日期 ${opts.date} 无通知数据`);\n }\n\n const checkpoint = readCheckpoint(dir);\n const committedIndex = items.length - 1;\n checkpoint[opts.date] = { lastIndex: committedIndex };\n writeCheckpoint(dir, checkpoint);\n\n output({\n ok: true,\n date: opts.date,\n committedIndex,\n });\n });\n}\n","import {\n existsSync,\n mkdirSync,\n readFileSync,\n writeFileSync,\n rmSync,\n readdirSync,\n} from \"node:fs\";\nimport { join } from \"node:path\";\nimport { type CliCommand, type CliContext, output, exitError } from \"./helpers.js\";\n\ninterface MonitorMeta {\n name: string;\n description: string;\n matchRules: Record<string, unknown>;\n cronSchedule: string;\n enabled: boolean;\n createdAt: string;\n}\n\nfunction tasksDir(ctx: CliContext): string {\n const base = ctx.workspaceDir || ctx.stateDir;\n if (!base) throw new Error(\"workspaceDir and stateDir both unavailable\");\n return join(base, \"tasks\");\n}\n\nfunction readMeta(taskDir: string): MonitorMeta | null {\n const metaPath = join(taskDir, \"meta.json\");\n if (!existsSync(metaPath)) return null;\n try {\n return JSON.parse(readFileSync(metaPath, \"utf-8\"));\n } catch {\n return null;\n }\n}\n\nfunction writeMeta(taskDir: string, meta: MonitorMeta): void {\n writeFileSync(join(taskDir, \"meta.json\"), JSON.stringify(meta, null, 2), \"utf-8\");\n}\n\nfunction generateFetchPy(\n name: string,\n matchRules: Record<string, unknown>,\n): string {\n const appName = (matchRules.appName as string) || \"\";\n const keywords = (matchRules.senderKeywords as string[]) || [];\n const keywordChecks = keywords\n .map((k) => ` if \"${k}\" in title:`)\n .join(\"\\n\");\n const keywordReturn =\n keywords.length > 0\n ? `${keywordChecks}\\n return True\\n return False`\n : \" return True\";\n\n return `#!/usr/bin/env python3\n\"\"\"Auto-generated fetch script for monitor task: ${name}\"\"\"\nimport json, sys, os\nfrom pathlib import Path\n\ndef matches(notification: dict) -> bool:\n app = notification.get(\"appName\", \"\")\n title = notification.get(\"title\", \"\")\n${appName ? ` if app != \"${appName}\":\\n return False` : \" # No app filter\"}\n${keywordReturn}\n\ndef main():\n import argparse\n parser = argparse.ArgumentParser()\n parser.add_argument(\"--notifications-dir\", required=True)\n args = parser.parse_args()\n\n checkpoint_path = Path(__file__).parent / \"checkpoint.json\"\n checkpoint = {}\n if checkpoint_path.exists():\n checkpoint = json.loads(checkpoint_path.read_text())\n\n ntf_dir = Path(args.notifications_dir)\n matched = []\n new_checkpoint = dict(checkpoint)\n\n for f in sorted(ntf_dir.glob(\"*.json\")):\n date_key = f.stem\n items = json.loads(f.read_text())\n last_idx = checkpoint.get(date_key, {}).get(\"lastIndex\", -1)\n for i, item in enumerate(items):\n if i <= last_idx:\n continue\n if matches(item):\n matched.append(item)\n new_checkpoint[date_key] = {\"lastIndex\": len(items) - 1}\n\n checkpoint_path.write_text(json.dumps(new_checkpoint, indent=2))\n\n if not matched:\n print(\"NO_MATCH\")\n return\n\n for m in matched:\n print(json.dumps(m, ensure_ascii=False))\n\nif __name__ == \"__main__\":\n main()\n`;\n}\n\nfunction generateReadme(name: string, description: string): string {\n return `# Monitor Task: ${name}\n\n## 描述\n${description}\n\n## 处理指南\n当 fetch.py 输出匹配的通知时,请:\n1. 阅读匹配到的通知内容\n2. 根据任务描述判断是否需要通知用户\n3. 如需通知用户,使用 message 工具发送摘要\n`;\n}\n\nexport function registerNtfMonitor(ntf: CliCommand, ctx: CliContext): void {\n const monitor = ntf.command(\"monitor\").description(\"通知监控任务管理\");\n\n monitor\n .command(\"list\")\n .description(\"列出所有监控任务\")\n .action(() => {\n const dir = tasksDir(ctx);\n if (!existsSync(dir)) {\n output({ ok: true, tasks: [] });\n return;\n }\n\n const tasks: MonitorMeta[] = [];\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue;\n const meta = readMeta(join(dir, entry.name));\n if (meta) tasks.push(meta);\n }\n\n output({ ok: true, tasks });\n });\n\n monitor\n .command(\"show <name>\")\n .description(\"查看监控任务详情\")\n .action((name: string) => {\n const taskDir = join(tasksDir(ctx), name);\n const meta = readMeta(taskDir);\n if (!meta) exitError(\"NOT_FOUND\", `监控任务 '${name}' 不存在`);\n\n const checkpointPath = join(taskDir, \"checkpoint.json\");\n let checkpoint = {};\n if (existsSync(checkpointPath)) {\n try {\n checkpoint = JSON.parse(readFileSync(checkpointPath, \"utf-8\"));\n } catch {\n // ignore\n }\n }\n\n output({\n ok: true,\n ...meta,\n matchScript: `tasks/${name}/fetch.py`,\n readme: `tasks/${name}/README.md`,\n checkpoint,\n });\n });\n\n monitor\n .command(\"create <name>\")\n .description(\"创建监控任务\")\n .requiredOption(\"--description <text>\", \"任务描述\")\n .requiredOption(\"--match-rules <json>\", \"匹配规则 JSON\")\n .requiredOption(\"--schedule <cron>\", \"cron 表达式\")\n .action(\n (\n name: string,\n opts: {\n description: string;\n matchRules: string;\n schedule: string;\n },\n ) => {\n const dir = tasksDir(ctx);\n const taskDir = join(dir, name);\n\n if (existsSync(taskDir)) {\n exitError(\"ALREADY_EXISTS\", `监控任务 '${name}' 已存在`);\n }\n\n let matchRules: Record<string, unknown>;\n try {\n matchRules = JSON.parse(opts.matchRules);\n } catch {\n exitError(\n \"VALIDATION_FAILED\",\n \"match-rules 必须是合法的 JSON\",\n );\n }\n\n mkdirSync(taskDir, { recursive: true });\n\n const meta: MonitorMeta = {\n name,\n description: opts.description,\n matchRules,\n cronSchedule: opts.schedule,\n enabled: true,\n createdAt: new Date().toISOString(),\n };\n writeMeta(taskDir, meta);\n writeFileSync(\n join(taskDir, \"fetch.py\"),\n generateFetchPy(name, matchRules),\n \"utf-8\",\n );\n writeFileSync(\n join(taskDir, \"README.md\"),\n generateReadme(name, opts.description),\n \"utf-8\",\n );\n\n output({\n ok: true,\n name,\n created: {\n script: `tasks/${name}/fetch.py`,\n readme: `tasks/${name}/README.md`,\n cronJob: `notif-${name}`,\n },\n cronHint: {\n action: \"add\",\n job: {\n name: `notif-${name}`,\n schedule: opts.schedule,\n sessionTarget: \"isolated\",\n message: `手机通知已由独立服务实时捕获到 notifications/ 目录的 JSON 文件中。\\n执行:python3 tasks/${name}/fetch.py --notifications-dir notifications\\n- NO_CHANGE 或 NO_MATCH → 不回复,直接结束。\\n- 有输出 → 读 tasks/${name}/README.md 了解如何处理数据并通知用户。`,\n },\n },\n });\n },\n );\n\n monitor\n .command(\"delete <name>\")\n .description(\"删除监控任务\")\n .option(\"--yes\", \"跳过确认\")\n .action((name: string, opts: { yes?: boolean }) => {\n const taskDir = join(tasksDir(ctx), name);\n if (!existsSync(taskDir)) {\n exitError(\"NOT_FOUND\", `监控任务 '${name}' 不存在`);\n }\n\n if (!opts.yes) {\n output({\n ok: false,\n error: {\n code: \"CONFIRMATION_REQUIRED\",\n message: `确认删除监控任务 '${name}'?添加 --yes 跳过确认`,\n },\n });\n process.exit(1);\n }\n\n rmSync(taskDir, { recursive: true, force: true });\n output({\n ok: true,\n name,\n deleted: true,\n cronHint: {\n action: \"remove\",\n name: `notif-${name}`,\n },\n });\n });\n\n monitor\n .command(\"enable <name>\")\n .description(\"启用监控任务\")\n .action((name: string) => {\n const taskDir = join(tasksDir(ctx), name);\n const meta = readMeta(taskDir);\n if (!meta) exitError(\"NOT_FOUND\", `监控任务 '${name}' 不存在`);\n\n meta.enabled = true;\n writeMeta(taskDir, meta);\n output({ ok: true, name, enabled: true });\n });\n\n monitor\n .command(\"disable <name>\")\n .description(\"暂停监控任务\")\n .action((name: string) => {\n const taskDir = join(tasksDir(ctx), name);\n const meta = readMeta(taskDir);\n if (!meta) exitError(\"NOT_FOUND\", `监控任务 '${name}' 不存在`);\n\n meta.enabled = false;\n writeMeta(taskDir, meta);\n output({ ok: true, name, enabled: false });\n });\n}\n","import { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { LightSegment } from \"../types.js\";\nimport { type CliCommand, type CliContext, output, exitError } from \"./helpers.js\";\nimport { validateSegments, parseAndValidateSegments } from \"../light/validators.js\";\n\ninterface LightRule {\n name: string;\n trigger: string;\n effect: string;\n segments: LightSegment[];\n}\n\nconst LIGHT_RULES_SECTION = \"## 灯效规则\";\n\nfunction memoryPath(ctx: CliContext): string {\n const base = ctx.workspaceDir || ctx.stateDir;\n if (!base) throw new Error(\"workspaceDir and stateDir both unavailable\");\n return join(base, \"MEMORY.md\");\n}\n\nfunction readMemory(ctx: CliContext): string {\n const p = memoryPath(ctx);\n if (!existsSync(p)) return \"\";\n return readFileSync(p, \"utf-8\");\n}\n\nfunction writeMemory(ctx: CliContext, content: string): void {\n writeFileSync(memoryPath(ctx), content, \"utf-8\");\n}\n\nfunction parseLightRules(content: string): LightRule[] {\n const rules: LightRule[] = [];\n const sectionIdx = content.indexOf(LIGHT_RULES_SECTION);\n if (sectionIdx === -1) return rules;\n\n const sectionContent = content.slice(sectionIdx);\n // Find next ## heading to bound the section\n const nextSection = sectionContent.indexOf(\"\\n## \", 1);\n const bounded = nextSection !== -1\n ? sectionContent.slice(0, nextSection)\n : sectionContent;\n\n const rulePattern = /### 规则:(.+)\\n/g;\n let match;\n while ((match = rulePattern.exec(bounded)) !== null) {\n const name = match[1].trim();\n const ruleStart = match.index + match[0].length;\n const nextRule = bounded.indexOf(\"\\n### \", ruleStart);\n const ruleBlock =\n nextRule !== -1\n ? bounded.slice(ruleStart, nextRule)\n : bounded.slice(ruleStart);\n\n const triggerMatch = /\\*\\*触发条件\\*\\*:(.+)/.exec(ruleBlock);\n const effectMatch = /\\*\\*灯效描述\\*\\*:(.+)/.exec(ruleBlock);\n const jsonMatch = /\\*\\*灯效参数(JSON)\\*\\*:(.+)/.exec(ruleBlock);\n\n let segments: LightSegment[] = [];\n if (jsonMatch) {\n try {\n const parsed = JSON.parse(jsonMatch[1]);\n segments = parsed.segments || [];\n } catch {\n // skip invalid JSON\n }\n }\n\n rules.push({\n name,\n trigger: triggerMatch?.[1]?.trim() || \"\",\n effect: effectMatch?.[1]?.trim() || \"\",\n segments,\n });\n }\n\n return rules;\n}\n\nfunction formatRuleBlock(rule: LightRule): string {\n const segmentsJson = JSON.stringify({ segments: rule.segments });\n return `### 规则:${rule.name}\n**触发条件**:${rule.trigger}\n**灯效描述**:${rule.effect}\n**灯效参数(JSON)**:${segmentsJson}\n**执行**:命中触发条件后,先完成任务并将完成情况发送给用户,再调用 light_control 工具并传入上述灯效参数。防止灯已亮但消息未送达的情况。`;\n}\n\nexport function registerLightRules(program: CliCommand, ctx: CliContext): CliCommand {\n const light = program.command(\"light\").description(\"灯效管理\");\n const rules = light.command(\"rules\").description(\"灯效规则管理\");\n\n rules\n .command(\"list\")\n .description(\"列出已存储的灯效规则\")\n .action(() => {\n const content = readMemory(ctx);\n const parsed = parseLightRules(content);\n output({ ok: true, rules: parsed });\n });\n\n rules\n .command(\"show <name>\")\n .description(\"查看指定灯效规则详情\")\n .action((name: string) => {\n const content = readMemory(ctx);\n const parsed = parseLightRules(content);\n const rule = parsed.find((r) => r.name === name);\n if (!rule) exitError(\"NOT_FOUND\", `灯效规则 '${name}' 不存在`);\n output({ ok: true, ...rule });\n });\n\n rules\n .command(\"add <name>\")\n .description(\"添加灯效规则\")\n .requiredOption(\"--trigger <text>\", \"触发条件描述\")\n .requiredOption(\"--segments <json>\", \"灯效参数 JSON\")\n .action((name: string, opts: { trigger: string; segments: string }) => {\n const validatedSegments = parseAndValidateSegments(opts.segments);\n\n let content = readMemory(ctx);\n const existingRules = parseLightRules(content);\n if (existingRules.some((r) => r.name === name)) {\n exitError(\"ALREADY_EXISTS\", `灯效规则 '${name}' 已存在`);\n }\n\n // Build effect description from segments\n const seg = validatedSegments[0];\n const modeMap: Record<string, string> = {\n wave: \"波浪\",\n breath: \"呼吸\",\n strobe: \"频闪\",\n steady: \"常亮\",\n };\n const effect = `${modeMap[seg.mode] || seg.mode}模式,RGB(${seg.color.r},${seg.color.g},${seg.color.b}),持续${seg.duration_s}秒,亮度${seg.brightness}`;\n\n const rule: LightRule = {\n name,\n trigger: opts.trigger,\n effect,\n segments: validatedSegments,\n };\n\n const ruleBlock = formatRuleBlock(rule);\n\n if (content.includes(LIGHT_RULES_SECTION)) {\n // Append rule within existing section\n const sectionIdx = content.indexOf(LIGHT_RULES_SECTION);\n const afterSection = content.slice(sectionIdx + LIGHT_RULES_SECTION.length);\n const nextSection = afterSection.indexOf(\"\\n## \");\n if (nextSection !== -1) {\n const insertAt = sectionIdx + LIGHT_RULES_SECTION.length + nextSection;\n content =\n content.slice(0, insertAt) +\n \"\\n\\n\" +\n ruleBlock +\n \"\\n\" +\n content.slice(insertAt);\n } else {\n content = content.trimEnd() + \"\\n\\n\" + ruleBlock + \"\\n\";\n }\n } else {\n content =\n content.trimEnd() + \"\\n\\n\" + LIGHT_RULES_SECTION + \"\\n\\n\" + ruleBlock + \"\\n\";\n }\n\n writeMemory(ctx, content);\n output({ ok: true, name, validated: true });\n });\n\n rules\n .command(\"remove <name>\")\n .description(\"移除灯效规则\")\n .option(\"--yes\", \"跳过确认\")\n .action((name: string, opts: { yes?: boolean }) => {\n if (!opts.yes) {\n output({\n ok: false,\n error: {\n code: \"CONFIRMATION_REQUIRED\",\n message: `确认移除灯效规则 '${name}'?添加 --yes 跳过确认`,\n },\n });\n process.exit(1);\n }\n\n const content = readMemory(ctx);\n const sectionIdx = content.indexOf(LIGHT_RULES_SECTION);\n if (sectionIdx === -1) {\n exitError(\"NOT_FOUND\", `灯效规则 '${name}' 不存在`);\n }\n\n const ruleHeader = `### 规则:${name}`;\n const ruleIdx = content.indexOf(ruleHeader, sectionIdx);\n if (ruleIdx === -1) {\n exitError(\"NOT_FOUND\", `灯效规则 '${name}' 不存在`);\n }\n\n // Find end of this rule block\n const afterRule = content.indexOf(\"\\n### \", ruleIdx + ruleHeader.length);\n const nextSection = content.indexOf(\"\\n## \", ruleIdx + ruleHeader.length);\n\n let endIdx: number;\n if (afterRule !== -1 && (nextSection === -1 || afterRule < nextSection)) {\n endIdx = afterRule;\n } else if (nextSection !== -1) {\n endIdx = nextSection;\n } else {\n endIdx = content.length;\n }\n\n // Remove the rule block (including preceding blank lines)\n let startIdx = ruleIdx;\n while (startIdx > 0 && content[startIdx - 1] === \"\\n\") startIdx--;\n if (startIdx > 0) startIdx++; // keep one newline\n\n const updated = content.slice(0, startIdx) + content.slice(endIdx);\n writeMemory(ctx, updated);\n output({ ok: true, name, removed: true });\n });\n\n rules\n .command(\"validate\")\n .description(\"校验灯效参数是否合法(不写入)\")\n .requiredOption(\"--segments <json>\", \"待校验的灯效参数 JSON\")\n .action((opts: { segments: string }) => {\n let parsedSegments: unknown;\n try {\n parsedSegments = JSON.parse(opts.segments);\n } catch {\n output({\n valid: false,\n errors: [{ field: \"segments\", message: \"JSON 解析失败\" }],\n });\n process.exit(1);\n }\n\n const validation = validateSegments(parsedSegments);\n if (!validation.valid) {\n output({ valid: false, errors: validation.errors });\n process.exit(1);\n }\n\n output({\n valid: true,\n quantized: { segments: validation.segments },\n warnings: [],\n });\n });\n\n return light;\n}\n","import type { LightSegment } from \"../types.js\";\nimport { output, exitError } from \"../cli/helpers.js\";\n\nexport const VALID_MODES = [\"wave\", \"breath\", \"strobe\", \"steady\", \"wave_rainbow\"] as const;\nexport const MAX_SEGMENTS = 12;\n\nexport type ValidationResult =\n | { valid: true; segments: LightSegment[] }\n | { valid: false; errors: { field: string; message: string }[] };\n\nexport function validateSegments(segments: unknown): ValidationResult {\n if (!Array.isArray(segments)) {\n return { valid: false, errors: [{ field: \"segments\", message: \"必须是数组\" }] };\n }\n if (segments.length === 0) {\n return { valid: false, errors: [{ field: \"segments\", message: \"不能为空\" }] };\n }\n if (segments.length > MAX_SEGMENTS) {\n return {\n valid: false,\n errors: [{ field: \"segments\", message: `最多 ${MAX_SEGMENTS} 段` }],\n };\n }\n\n const errors: { field: string; message: string }[] = [];\n for (let i = 0; i < segments.length; i++) {\n const seg = segments[i];\n const prefix = `segments[${i}]`;\n\n if (!seg || typeof seg !== \"object\") {\n errors.push({ field: prefix, message: \"必须是对象\" });\n continue;\n }\n\n if (!VALID_MODES.includes(seg.mode)) {\n errors.push({\n field: `${prefix}.mode`,\n message: `不支持的模式 '${seg.mode}',可选:${VALID_MODES.join(\"/\")}`,\n });\n }\n if (typeof seg.duration_s !== \"number\" || seg.duration_s < 0) {\n errors.push({ field: `${prefix}.duration_s`, message: \"必须是 ≥0 的数字(0 表示无限时长)\" });\n }\n if (typeof seg.brightness !== \"number\" || seg.brightness < 0 || seg.brightness > 255) {\n errors.push({ field: `${prefix}.brightness`, message: \"必须是 0–255 的数字\" });\n }\n if (!seg.color || typeof seg.color.r !== \"number\" || typeof seg.color.g !== \"number\" || typeof seg.color.b !== \"number\") {\n errors.push({ field: `${prefix}.color`, message: \"必须包含 r/g/b 数值\" });\n }\n }\n\n if (errors.length > 0) return { valid: false, errors };\n return { valid: true, segments: segments as LightSegment[] };\n}\n\n/**\n * 解析 JSON 字符串并校验 segments,失败时直接 exitError。\n * 适用于 CLI action 中的统一入口。\n */\nexport function parseAndValidateSegments(json: string): LightSegment[] {\n let parsed: unknown;\n try {\n parsed = JSON.parse(json);\n } catch {\n exitError(\"VALIDATION_FAILED\", \"segments 必须是合法的 JSON\");\n }\n\n const result = validateSegments(parsed);\n if (!result.valid) {\n output({ ok: false, error: { code: \"VALIDATION_FAILED\", details: result.errors } });\n process.exit(1);\n }\n\n return result.segments;\n}\n","import { type CliCommand, output, exitError } from \"./helpers.js\";\nimport { requireApiKey } from \"../auth/credentials.js\";\nimport { sendLightEffect } from \"../light/sender.js\";\nimport { parseAndValidateSegments } from \"../light/validators.js\";\n\nexport function registerLightSend(light: CliCommand): void {\n light\n .command(\"send\")\n .description(\"发送灯效指令到硬件设备\")\n .requiredOption(\"--segments <json>\", \"灯效参数 JSON\")\n .option(\"--repeat\", \"无限循环播放(默认仅播放一轮)\")\n .action(async (opts: { segments: string; repeat?: boolean }) => {\n let apiKey: string;\n try {\n apiKey = requireApiKey();\n } catch (e: any) {\n exitError(\"AUTH_REQUIRED\", e.message);\n }\n\n const segments = parseAndValidateSegments(opts.segments);\n const result = await sendLightEffect(apiKey, segments, undefined, opts.repeat);\n\n if (!result.ok) {\n exitError(\"HTTP_ERROR\", `请求失败: ${result.status} ${result.error}`);\n }\n\n output({ ok: true, bizUniqueId: result.bizUniqueId, response: result.response });\n });\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { loadApiKey } from \"../auth/credentials.js\";\nimport { getEnvUrls } from \"../env.js\";\nimport { output, exitError } from \"./helpers.js\";\nimport type { CliCommand, CliContext } from \"./helpers.js\";\nimport type { TunnelStatusInfo } from \"../tunnel/relay-client.js\";\n\n/** 状态文件相对于 stateDir 的路径 */\nconst STATUS_REL_PATH = join(\"plugins\", \"phone-notifications\", \"tunnel-status.json\");\n\n/** 读取 RelayClient 写入的状态文件 */\nfunction readTunnelStatus(ctx: CliContext): TunnelStatusInfo | null {\n if (!ctx.stateDir) return null;\n const filePath = join(ctx.stateDir, STATUS_REL_PATH);\n if (!existsSync(filePath)) return null;\n try {\n return JSON.parse(readFileSync(filePath, \"utf-8\")) as TunnelStatusInfo;\n } catch {\n return null;\n }\n}\n\nfunction formatMessage(status: TunnelStatusInfo): string {\n switch (status.state) {\n case \"connected\":\n return `隧道已连接(自 ${status.since})`;\n case \"connecting\":\n return `隧道正在连接(自 ${status.since},第 ${status.reconnectAttempt} 次重连)`;\n case \"disconnected\":\n return `隧道已断开(自 ${status.since})${status.lastDisconnectReason ? `,原因: ${status.lastDisconnectReason}` : \"\"},等待重连(第 ${status.reconnectAttempt} 次)`;\n case \"stopped\":\n return `隧道服务已停止(自 ${status.since})`;\n default:\n return `未知状态: ${status.state}`;\n }\n}\n\nexport function registerTunnelStatus(ntf: CliCommand, ctx: CliContext): void {\n ntf\n .command(\"tunnel-status\")\n .description(\"检查 Relay Tunnel 隧道连接状态(读取运行中服务的状态文件,不影响已有连接)\")\n .action(async () => {\n const tunnelUrl = getEnvUrls().relayTunnelUrl;\n const apiKey = loadApiKey();\n\n if (!tunnelUrl) {\n exitError(\n \"TUNNEL_NOT_CONFIGURED\",\n \"RELAY_TUNNEL_URL 未配置,隧道功能未启用。请在构建时设置 RELAY_TUNNEL_URL 环境变量。\",\n );\n }\n\n if (!apiKey) {\n exitError(\n \"TOKEN_MISSING\",\n \"API Key 未设置,隧道无法连接。请执行 openclaw ntf auth set-api-key <apiKey>\",\n );\n }\n\n const status = readTunnelStatus(ctx);\n\n if (!status) {\n exitError(\n \"STATUS_NOT_FOUND\",\n \"未找到隧道状态文件,隧道服务可能尚未启动过。请确认 openclaw 主进程正在运行。\",\n );\n }\n\n const ok = status.state === \"connected\";\n output({\n ok,\n tunnelUrl,\n connection: {\n state: status.state,\n since: status.since,\n reconnectAttempt: status.reconnectAttempt,\n lastDisconnectReason: status.lastDisconnectReason,\n },\n message: formatMessage(status),\n });\n\n if (!ok) process.exit(1);\n });\n}\n","import {\n type CliCommand,\n type CliContext,\n resolveNotificationsDir,\n output,\n exitError,\n} from \"./helpers.js\";\n\nexport function registerNtfStoragePath(ntf: CliCommand, ctx: CliContext): void {\n ntf\n .command(\"storage-path\")\n .description(\"查询通知存储路径\")\n .action(() => {\n const dir = resolveNotificationsDir(ctx);\n if (!dir) exitError(\"STORAGE_UNAVAILABLE\", \"通知存储目录不可用\");\n output({ ok: true, path: dir });\n });\n}\n","import { existsSync, readFileSync, readdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport {\n type CliCommand,\n type CliContext,\n filterDateRange,\n today,\n daysAgo,\n output,\n exitError,\n} from \"./helpers.js\";\n\n/** Resolve the plugin logs directory from stateDir */\nfunction resolveLogsDir(ctx: CliContext): string | null {\n if (ctx.stateDir) {\n const dir = join(\n ctx.stateDir,\n \"plugins\",\n \"phone-notifications\",\n \"logs\",\n );\n if (existsSync(dir)) return dir;\n }\n return null;\n}\n\n/** List available log date keys (YYYY-MM-DD) sorted descending */\nfunction listLogDateKeys(dir: string): string[] {\n const pattern = /^(\\d{4}-\\d{2}-\\d{2})\\.log$/;\n const keys: string[] = [];\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n if (!entry.isFile()) continue;\n const m = pattern.exec(entry.name);\n if (m) keys.push(m[1]);\n }\n return keys.sort().reverse();\n}\n\n/** Read log lines from a date file, optionally filtering by keyword */\nfunction collectLogLines(\n dir: string,\n dateKey: string,\n keyword: string | undefined,\n limit: number,\n collected: string[],\n): void {\n const filePath = join(dir, `${dateKey}.log`);\n if (!existsSync(filePath)) return;\n\n const content = readFileSync(filePath, \"utf-8\");\n const lowerKeyword = keyword?.toLowerCase();\n\n for (const line of content.split(\"\\n\")) {\n if (collected.length >= limit) return;\n if (!line) continue;\n if (lowerKeyword && !line.toLowerCase().includes(lowerKeyword)) continue;\n collected.push(`[${dateKey}] ${line}`);\n }\n}\n\nexport function registerLogSearch(ntf: CliCommand, ctx: CliContext): void {\n ntf\n .command(\"log\")\n .description(\"查看/搜索插件日志\")\n .option(\"--keyword <text>\", \"按关键词过滤日志\")\n .option(\"--from <date>\", \"开始日期 YYYY-MM-DD\", daysAgo(7))\n .option(\"--to <date>\", \"结束日期 YYYY-MM-DD\", today())\n .option(\"--limit <n>\", \"最大返回条数\", \"50\")\n .action(\n (opts: {\n keyword?: string;\n from: string;\n to: string;\n limit: string;\n }) => {\n const dir = resolveLogsDir(ctx);\n if (!dir) exitError(\"LOGS_UNAVAILABLE\", \"日志目录不可用\");\n\n const keys = filterDateRange(listLogDateKeys(dir), opts.from, opts.to);\n const limit = parseInt(opts.limit, 10) || 50;\n const results: string[] = [];\n\n for (const dateKey of keys) {\n if (results.length >= limit) break;\n collectLogLines(dir, dateKey, opts.keyword, limit, results);\n }\n\n output({\n ok: true,\n keyword: opts.keyword ?? null,\n total: results.length,\n lines: results,\n });\n },\n );\n}\n","import { loadEnvName, saveEnvName, getEnvUrls, getAvailableEnvs } from \"../env.js\";\nimport { output, exitError } from \"./helpers.js\";\nimport type { CliCommand } from \"./helpers.js\";\n\nexport function registerEnvCli(ntf: CliCommand): void {\n const env = ntf.command(\"env\").description(\"环境管理(切换 development / production)\");\n\n env\n .command(\"show\")\n .description(\"显示当前环境及对应的接口地址\")\n .action(() => {\n const current = loadEnvName();\n const urls = getEnvUrls(current);\n output({\n ok: true,\n env: current,\n lightApiUrl: urls.lightApiUrl,\n relayTunnelUrl: urls.relayTunnelUrl,\n availableEnvs: getAvailableEnvs(),\n });\n });\n\n env\n .command(\"switch <env>\")\n .description(\"切换环境(development / production)\")\n .action((envName: string) => {\n const available = getAvailableEnvs();\n if (!available.includes(envName as any)) {\n exitError(\n \"INVALID_ENV\",\n `无效的环境名称: ${envName},可选值: ${available.join(\", \")}`,\n );\n }\n saveEnvName(envName as any);\n const urls = getEnvUrls(envName as any);\n output({\n ok: true,\n message: `已切换到 ${envName} 环境`,\n env: envName,\n lightApiUrl: urls.lightApiUrl,\n relayTunnelUrl: urls.relayTunnelUrl,\n });\n });\n}\n","import { readFileSync } from \"node:fs\";\n\ninterface PackageJson {\n version?: string;\n}\n\nfunction readPluginVersion(): string {\n try {\n const packageJsonUrl = new URL(\"../package.json\", import.meta.url);\n const packageJson = JSON.parse(\n readFileSync(packageJsonUrl, \"utf-8\"),\n ) as PackageJson;\n return packageJson.version ?? \"unknown\";\n } catch {\n return \"unknown\";\n }\n}\n\nexport const PLUGIN_VERSION = readPluginVersion();\n","import type { CliCommand, CliContext } from \"./helpers.js\";\nimport { registerAuthCli } from \"./auth.js\";\nimport { registerNtfSearch } from \"./ntf-search.js\";\nimport { registerNtfStats } from \"./ntf-stats.js\";\nimport { registerNtfSync } from \"./ntf-sync.js\";\nimport { registerNtfMonitor } from \"./ntf-monitor.js\";\nimport { registerLightRules } from \"./light-rules.js\";\nimport { registerLightSend } from \"./light-send.js\";\nimport { registerTunnelStatus } from \"./tunnel-status.js\";\nimport { registerNtfStoragePath } from \"./ntf-storage-path.js\";\nimport { registerLogSearch } from \"./log-search.js\";\nimport { registerEnvCli } from \"./env.js\";\nimport { PLUGIN_VERSION } from \"../version.js\";\n\nexport function registerAllCli(\n program: CliCommand,\n ctx: CliContext,\n rootCommandName = \"ntf\",\n): void {\n const ntf = program\n .command(rootCommandName)\n .description(\"手机通知数据管理\")\n .version(PLUGIN_VERSION, \"-v, --version\", \"显示插件版本\");\n\n // openclaw ntf auth ...\n registerAuthCli(ntf);\n\n // openclaw ntf search / stats / sync / monitor ...\n registerNtfSearch(ntf, ctx);\n registerNtfStats(ntf, ctx);\n registerNtfSync(ntf, ctx);\n registerNtfMonitor(ntf, ctx);\n\n // openclaw ntf light rules / send ...\n const light = registerLightRules(ntf, ctx);\n registerLightSend(light);\n\n // openclaw ntf storage-path\n registerNtfStoragePath(ntf, ctx);\n\n // openclaw ntf log <keyword>\n registerLogSearch(ntf, ctx);\n\n // openclaw ntf tunnel-status\n registerTunnelStatus(ntf, ctx);\n\n // openclaw ntf env show / switch\n registerEnvCli(ntf);\n}\n","import {\n closeSync,\n mkdirSync,\n openSync,\n readFileSync,\n unlinkSync,\n writeFileSync,\n} from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { loadApiKey } from \"../auth/credentials.js\";\nimport { RelayClient } from \"./relay-client.js\";\nimport { TunnelProxy } from \"./proxy.js\";\n\nconst DEFAULT_HEARTBEAT_SEC = 10;\nconst DEFAULT_RECONNECT_BACKOFF_MS = 2000;\n\ninterface TunnelServiceOptions {\n /** Relay Server WebSocket 地址(构建时从 RELAY_TUNNEL_URL 注入) */\n tunnelUrl: string;\n gatewayBaseUrl: string;\n /** Gateway 鉴权模式 */\n gatewayAuthMode?: \"token\" | \"password\";\n /** Gateway 鉴权 token */\n gatewayToken?: string;\n /** Gateway 鉴权密码 */\n gatewayPassword?: string;\n /** 心跳间隔(秒),默认 10 */\n heartbeatSec?: number;\n /** 重连基础退避时间(毫秒),默认 2000 */\n reconnectBackoffMs?: number;\n logger: {\n info: (msg: string) => void;\n warn: (msg: string) => void;\n error: (msg: string) => void;\n };\n}\n\n/**\n * 隧道服务:组装 RelayClient + TunnelProxy,作为 registerService 的入口。\n */\nexport function createTunnelService(opts: TunnelServiceOptions) {\n let client: RelayClient | null = null;\n let proxy: TunnelProxy | null = null;\n let abortController: AbortController | null = null;\n let lockFilePath: string | null = null;\n let lockFd: number | null = null;\n\n function isProcessAlive(pid: number): boolean {\n if (!Number.isInteger(pid) || pid <= 0) return false;\n if (pid === process.pid) return true;\n try {\n process.kill(pid, 0);\n return true;\n } catch (err: any) {\n return err?.code === \"EPERM\";\n }\n }\n\n function readLockOwner(filePath: string): number | null {\n try {\n const parsed = JSON.parse(readFileSync(filePath, \"utf-8\")) as {\n pid?: unknown;\n };\n return typeof parsed.pid === \"number\" ? parsed.pid : null;\n } catch {\n return null;\n }\n }\n\n function releaseLock(): void {\n const filePath = lockFilePath;\n const fd = lockFd;\n lockFilePath = null;\n lockFd = null;\n\n if (fd !== null) {\n try {\n closeSync(fd);\n } catch {\n // ignore\n }\n }\n if (filePath) {\n try {\n unlinkSync(filePath);\n } catch {\n // ignore\n }\n }\n }\n\n function acquireLock(filePath: string): boolean {\n mkdirSync(dirname(filePath), { recursive: true });\n\n for (let attempt = 0; attempt < 2; attempt++) {\n try {\n const fd = openSync(filePath, \"wx\", 0o600);\n writeFileSync(\n fd,\n JSON.stringify({\n pid: process.pid,\n startedAt: new Date().toISOString(),\n tunnelUrl: opts.tunnelUrl,\n }) + \"\\n\",\n );\n lockFilePath = filePath;\n lockFd = fd;\n return true;\n } catch (err: any) {\n if (err?.code !== \"EEXIST\") {\n opts.logger.error(\n `Relay tunnel: failed to acquire local lock ${filePath}: ${String(err)}`,\n );\n return false;\n }\n\n const ownerPid = readLockOwner(filePath);\n if (ownerPid && !isProcessAlive(ownerPid)) {\n opts.logger.warn(\n `Relay tunnel: removing stale local lock owned by dead pid=${ownerPid}`,\n );\n try {\n unlinkSync(filePath);\n } catch {\n // ignore, retry below will fail if lock is still present\n }\n continue;\n }\n\n opts.logger.warn(\n `Relay tunnel: another local process already owns the tunnel lock${ownerPid ? ` (pid=${ownerPid})` : \"\"}; skipping connection to avoid duplicate token sessions`,\n );\n return false;\n }\n }\n\n return false;\n }\n\n return {\n id: \"relay-tunnel\",\n\n async start(ctx: { stateDir: string }) {\n // 先清理上一轮连接,防止 start() 被重复调用时产生多个 RelayClient 互踢\n if (abortController) {\n opts.logger.info(\"Relay tunnel: aborting previous connection before restart\");\n abortController.abort();\n abortController = null;\n }\n releaseLock();\n proxy?.cleanup();\n proxy = null;\n client = null;\n\n const apiKey = loadApiKey();\n if (!apiKey) {\n opts.logger.warn(\n \"Relay tunnel: apiKey 未设置,跳过隧道连接。请执行 openclaw ntf auth set-api-key <apiKey>\",\n );\n return;\n }\n\n const { logger } = opts;\n const baseStateDir = join(ctx.stateDir, \"plugins\", \"phone-notifications\");\n logger.info(\n `Relay tunnel: starting (pid=${process.pid}, url=${opts.tunnelUrl}, heartbeat=${opts.heartbeatSec ?? DEFAULT_HEARTBEAT_SEC}s, backoff=${opts.reconnectBackoffMs ?? DEFAULT_RECONNECT_BACKOFF_MS}ms, gateway=${opts.gatewayBaseUrl}, hasGatewayToken=${!!opts.gatewayToken}, hasGatewayPwd=${!!opts.gatewayPassword})`,\n );\n const statusFilePath = join(baseStateDir, \"tunnel-status.json\");\n const lockPath = join(baseStateDir, \"relay-tunnel.lock\");\n\n if (!acquireLock(lockPath)) {\n return;\n }\n\n try {\n client = new RelayClient({\n tunnelUrl: opts.tunnelUrl,\n apiKey,\n heartbeatSec: opts.heartbeatSec ?? DEFAULT_HEARTBEAT_SEC,\n reconnectBackoffMs: opts.reconnectBackoffMs ?? DEFAULT_RECONNECT_BACKOFF_MS,\n statusFilePath,\n logger,\n });\n\n proxy = new TunnelProxy({\n gatewayBaseUrl: opts.gatewayBaseUrl,\n gatewayAuthMode: opts.gatewayAuthMode,\n gatewayToken: opts.gatewayToken,\n gatewayPassword: opts.gatewayPassword,\n client,\n logger,\n });\n\n client.onInbound((frame) => proxy!.handleFrame(frame));\n\n abortController = new AbortController();\n // 非阻塞启动,connectWithAutoReconnect 内部会保持运行\n client.connectWithAutoReconnect(abortController.signal).catch((err) => {\n releaseLock();\n logger.error(`Relay tunnel: unexpected error: ${err}`);\n });\n\n logger.info(\"Relay tunnel 服务已启动\");\n } catch (err) {\n releaseLock();\n throw err;\n }\n },\n\n async stop() {\n if (abortController) {\n abortController.abort();\n abortController = null;\n }\n releaseLock();\n proxy?.cleanup();\n proxy = null;\n client = null;\n opts.logger.info(\"Relay tunnel 服务已停止\");\n },\n };\n}\n","import { writeFileSync, mkdirSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport WebSocket from \"ws\";\nimport type { InboundFrame, OutboundFrame } from \"./types.js\";\n\nfunction previewText(text: string, max = 500): string {\n return text.length <= max ? text : `${text.substring(0, max)}…`;\n}\n\nfunction maskSecret(value: string): string {\n if (!value) return \"empty\";\n if (value.length <= 8) {\n return `${value.slice(0, 2)}…${value.slice(-2)}`;\n }\n return `${value.slice(0, 4)}…${value.slice(-4)}`;\n}\n\n/** 持久化到磁盘的隧道连接状态 */\nexport interface TunnelStatusInfo {\n /** 当前连接状态 */\n state: \"connected\" | \"disconnected\" | \"connecting\" | \"stopped\";\n /** 状态变更时间 ISO */\n since: string;\n /** 累计重连次数 */\n reconnectAttempt: number;\n /** 上次断开原因(仅 disconnected 时有值) */\n lastDisconnectReason?: string;\n}\n\nexport interface RelayClientOptions {\n tunnelUrl: string;\n apiKey: string;\n heartbeatSec: number;\n reconnectBackoffMs: number;\n /** 状态文件路径,设置后会在连接状态变更时写入 */\n statusFilePath?: string;\n logger: {\n info: (msg: string) => void;\n warn: (msg: string) => void;\n error: (msg: string) => void;\n };\n}\n\nexport type InboundHandler = (frame: InboundFrame) => void | Promise<void>;\n\n/**\n * Relay WebSocket 客户端。\n * 负责建连、token 认证、心跳保活、断线指数退避重连。\n */\nexport class RelayClient {\n private ws: WebSocket | null = null;\n private heartbeatTimer: ReturnType<typeof setInterval> | null = null;\n private reconnectAttempt = 0;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private handlers: InboundHandler[] = [];\n private aborted = false;\n private lastInboundAt = 0;\n\n constructor(private readonly opts: RelayClientOptions) {}\n\n /** 写连接状态到磁盘 */\n private writeStatus(\n state: TunnelStatusInfo[\"state\"],\n lastDisconnectReason?: string,\n ): void {\n if (!this.opts.statusFilePath) return;\n const info: TunnelStatusInfo = {\n state,\n since: new Date().toISOString(),\n reconnectAttempt: this.reconnectAttempt,\n lastDisconnectReason,\n };\n try {\n mkdirSync(dirname(this.opts.statusFilePath), { recursive: true });\n writeFileSync(this.opts.statusFilePath, JSON.stringify(info, null, 2));\n } catch {\n // 写状态文件失败不影响主流程\n }\n }\n\n /** 注册入站帧处理函数 */\n onInbound(handler: InboundHandler): void {\n this.handlers.push(handler);\n }\n\n /** 发送出站帧 */\n send(frame: OutboundFrame): void {\n if (this.ws?.readyState === WebSocket.OPEN) {\n const payload = JSON.stringify(frame);\n this.opts.logger.info(\n `Relay tunnel: ▶ send frame type=${frame.type}, id=${\"id\" in frame ? frame.id : \"N/A\"} (${payload.length} chars)`,\n );\n this.ws.send(payload);\n } else {\n this.opts.logger.warn(\n `Relay tunnel: ▶ send skipped, ws not open (readyState=${this.ws?.readyState ?? \"null\"}), frame type=${frame.type}`,\n );\n }\n }\n\n /** 原样透传文本到 Relay(用于 Gateway WS 响应直接回传) */\n sendRaw(text: string): void {\n if (this.ws?.readyState === WebSocket.OPEN) {\n this.opts.logger.info(\n `Relay tunnel: ▶ sendRaw (${text.length} chars): ${text.length <= 500 ? text : text.substring(0, 500) + \"…\"}`,\n );\n this.ws.send(text);\n } else {\n this.opts.logger.warn(\n `Relay tunnel: ▶ sendRaw skipped, ws not open (readyState=${this.ws?.readyState ?? \"null\"})`,\n );\n }\n }\n\n /** 启动连接,带自动重连,直到 abortSignal 触发 */\n async connectWithAutoReconnect(abortSignal?: AbortSignal): Promise<void> {\n if (abortSignal) {\n abortSignal.addEventListener(\n \"abort\",\n () => {\n this.aborted = true;\n this.cleanup(true);\n this.writeStatus(\"stopped\");\n },\n { once: true },\n );\n }\n\n await this.connect();\n\n // 保持运行直到 abort\n return new Promise<void>((resolve) => {\n if (abortSignal) {\n abortSignal.addEventListener(\"abort\", () => resolve(), { once: true });\n }\n });\n }\n\n private async connect(): Promise<void> {\n if (this.aborted) return;\n\n // 确保旧连接和定时器都被清理,防止重复连接\n this.cleanup(true);\n\n const rawApiKey = this.opts.apiKey.startsWith(\"Bearer \")\n ? this.opts.apiKey.slice(\"Bearer \".length)\n : this.opts.apiKey;\n\n this.opts.logger.info(\n `Relay tunnel: connecting to ${this.opts.tunnelUrl} (attempt=${this.reconnectAttempt}, heartbeat=${this.opts.heartbeatSec}s, apiKey=${maskSecret(rawApiKey)})`,\n );\n this.writeStatus(\"connecting\");\n\n return new Promise<void>((resolve) => {\n let settled = false;\n const settle = () => {\n if (!settled) {\n settled = true;\n resolve();\n }\n };\n\n const wsUrl = new URL(this.opts.tunnelUrl);\n // 推荐使用 query 传 apiKey;暂时用 token 代替 apiKey 明文\n if (!wsUrl.searchParams.get(\"apiKey\")) {\n wsUrl.searchParams.set(\"apiKey\", rawApiKey);\n }\n\n const ws = new WebSocket(wsUrl.toString(), {\n headers: {\n \"X-Api-Key-Id\": rawApiKey,\n },\n });\n // 将握手中的 socket 也记为当前连接,确保首连失败/握手前断开也能触发重连。\n this.ws = ws;\n\n ws.on(\"open\", () => {\n if (this.aborted || this.ws !== ws) {\n this.opts.logger.warn(\n `Relay tunnel: open fired but aborted=${this.aborted}, stale=${this.ws !== ws}, closing`,\n );\n try {\n ws.terminate();\n } catch {\n // ignore\n }\n settle();\n return;\n }\n this.reconnectAttempt = 0;\n this.lastInboundAt = Date.now();\n this.startHeartbeat();\n this.opts.logger.info(\"Relay tunnel: ✔ connected, heartbeat started\");\n this.writeStatus(\"connected\");\n settle();\n });\n\n ws.on(\"pong\", () => {\n if (this.ws === ws) {\n this.opts.logger.info(\"Relay tunnel: ← pong received\");\n this.markInboundActivity();\n }\n });\n\n ws.on(\"message\", (data: WebSocket.RawData) => {\n if (this.ws !== ws) {\n return;\n }\n this.handleMessage(data);\n });\n\n ws.on(\"close\", (code: number, reason: Buffer) => {\n const reasonStr = reason.toString();\n const lastInboundAgoMs = this.lastInboundAt\n ? Date.now() - this.lastInboundAt\n : null;\n this.opts.logger.warn(\n `Relay tunnel: disconnected (code=${code}, reason=${previewText(reasonStr, 200)}, lastInboundAgoMs=${lastInboundAgoMs ?? \"N/A\"}, reconnectAttempt=${this.reconnectAttempt})`,\n );\n if (this.ws === ws) {\n this.stopHeartbeat();\n this.ws = null;\n this.writeStatus(\"disconnected\", `code=${code}, reason=${reasonStr}`);\n this.scheduleReconnect();\n }\n settle();\n });\n\n ws.on(\"error\", (err: Error) => {\n this.opts.logger.error(\n `Relay tunnel: WebSocket error: ${err.message} (readyState=${ws.readyState}, reconnectAttempt=${this.reconnectAttempt}, url=${wsUrl.toString()})`,\n );\n // 握手阶段的错误也要尽快结束本次 connect(),重连仍统一由 close 事件触发。\n settle();\n });\n });\n }\n\n private handleMessage(data: WebSocket.RawData): void {\n const text =\n typeof data === \"string\"\n ? data\n : Buffer.isBuffer(data)\n ? data.toString()\n : String(data);\n\n this.markInboundActivity();\n\n // 应用层心跳 pong 直接消费,不走帧解析\n if (text === \"pong\") {\n return;\n }\n\n this.opts.logger.info(\n `Relay tunnel: ★ received message (${text.length} chars): ${previewText(text)}`,\n );\n\n let frame: InboundFrame;\n try {\n frame = JSON.parse(text) as InboundFrame;\n } catch {\n this.opts.logger.warn(\n `Relay tunnel: received invalid frame, ignoring (preview=${previewText(text, 200)})`,\n );\n return;\n }\n\n this.opts.logger.info(`Relay tunnel: parsed frame type=${frame.type}, id=${\"id\" in frame ? frame.id : \"N/A\"}`);\n\n for (const handler of this.handlers) {\n try {\n const result = handler(frame);\n if (result instanceof Promise) {\n result.catch((err) => {\n this.opts.logger.error(`Relay tunnel: handler error: ${err}`);\n });\n }\n } catch (err) {\n this.opts.logger.error(`Relay tunnel: handler error: ${err}`);\n }\n }\n }\n\n private startHeartbeat(): void {\n this.stopHeartbeat();\n const intervalMs = this.opts.heartbeatSec * 1000;\n this.sendHeartbeat();\n this.heartbeatTimer = setInterval(() => {\n this.sendHeartbeat();\n }, intervalMs);\n }\n\n private stopHeartbeat(): void {\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer);\n this.heartbeatTimer = null;\n }\n }\n\n private getHeartbeatTimeoutMs(): number {\n return this.opts.heartbeatSec * 3 * 1000;\n }\n\n private sendHeartbeat(): void {\n if (this.ws?.readyState !== WebSocket.OPEN) {\n return;\n }\n\n const idleMs = Date.now() - this.lastInboundAt;\n const timeoutMs = this.getHeartbeatTimeoutMs();\n if (idleMs >= timeoutMs) {\n this.opts.logger.warn(\n `Relay tunnel: heartbeat timeout, no inbound activity for ${idleMs}ms (threshold=${timeoutMs}ms)`,\n );\n try {\n this.ws.terminate();\n } catch {\n // ignore, close/error path will handle reconnect\n }\n return;\n }\n\n this.opts.logger.info('Relay tunnel: → heartbeat \"ping\"');\n try {\n this.ws.send(\"ping\");\n } catch {\n // ignore, close/error path will handle reconnect\n }\n try {\n this.ws.ping();\n } catch {\n // ignore, close/error path will handle reconnect\n }\n }\n\n private markInboundActivity(): void {\n this.lastInboundAt = Date.now();\n }\n\n private cleanup(force = false): void {\n this.opts.logger.info(\n `Relay tunnel: cleanup (ws=${this.ws ? \"open\" : \"null\"}, heartbeat=${!!this.heartbeatTimer}, reconnect=${!!this.reconnectTimer})`,\n );\n this.stopHeartbeat();\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n if (this.ws) {\n try {\n if (force) {\n this.ws.terminate();\n } else {\n this.ws.close();\n }\n } catch {\n // ignore\n }\n this.ws = null;\n }\n }\n\n private scheduleReconnect(): void {\n if (this.aborted) return;\n\n // 取消已有的重连定时器,防止重复 connect\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n const baseMs = this.opts.reconnectBackoffMs;\n const delayMs = Math.min(\n baseMs * Math.pow(2, this.reconnectAttempt),\n 60_000,\n );\n this.reconnectAttempt++;\n\n this.opts.logger.info(\n `Relay tunnel: reconnecting in ${delayMs}ms (attempt ${this.reconnectAttempt})`,\n );\n\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = null;\n if (!this.aborted) {\n this.connect().catch((err) => {\n this.opts.logger.error(`Relay tunnel: reconnect failed: ${err}`);\n });\n }\n }, delayMs);\n }\n}\n","import createWebSocketStream from './lib/stream.js';\nimport Receiver from './lib/receiver.js';\nimport Sender from './lib/sender.js';\nimport WebSocket from './lib/websocket.js';\nimport WebSocketServer from './lib/websocket-server.js';\n\nexport { createWebSocketStream, Receiver, Sender, WebSocket, WebSocketServer };\nexport default WebSocket;\n","import { randomUUID } from \"node:crypto\";\nimport crypto from \"node:crypto\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport http from \"node:http\";\nimport WebSocket from \"ws\";\nimport { resolveStateDir as resolveHostStateDir } from \"../host.js\";\nimport type { RelayClient } from \"./relay-client.js\";\nimport type {\n RequestFrame,\n ReqFrame,\n WsOpenFrame,\n WsDataFrame,\n WsCloseFrame,\n InboundFrame,\n} from \"./types.js\";\n\nfunction previewText(text: string | undefined, max = 200): string {\n if (!text) return \"\";\n return text.length <= max ? text : `${text.substring(0, max)}…`;\n}\n\nfunction findHeaderValue(\n headers: Record<string, string> | undefined,\n key: string,\n): string | undefined {\n if (!headers) return undefined;\n const lowerKey = key.toLowerCase();\n for (const [headerKey, headerValue] of Object.entries(headers)) {\n if (headerKey.toLowerCase() === lowerKey) {\n return headerValue;\n }\n }\n return undefined;\n}\n\nfunction summarizeRequestHeaders(headers: Record<string, string> | undefined): string {\n const contentType = findHeaderValue(headers, \"content-type\");\n const requestId = findHeaderValue(headers, \"x-request-id\");\n const parts: string[] = [];\n if (contentType) {\n parts.push(`contentType=${contentType}`);\n }\n if (requestId) {\n parts.push(`xRequestId=${previewText(requestId, 120)}`);\n }\n return parts.length ? `, ${parts.join(\", \")}` : \"\";\n}\n\n// ─── Device Identity helpers (mirrors openclaw SDK internals) ───\n\ninterface DeviceIdentity {\n deviceId: string;\n publicKeyPem: string;\n privateKeyPem: string;\n}\n\nconst ED25519_SPKI_PREFIX = Buffer.from(\"302a300506032b6570032100\", \"hex\");\n\nfunction base64UrlEncode(buf: Buffer): string {\n return buf\n .toString(\"base64\")\n .replaceAll(\"+\", \"-\")\n .replaceAll(\"/\", \"_\")\n .replace(/=+$/g, \"\");\n}\n\nfunction derivePublicKeyRaw(publicKeyPem: string): Buffer {\n const spki = crypto.createPublicKey(publicKeyPem).export({\n type: \"spki\",\n format: \"der\",\n });\n if (\n spki.length === ED25519_SPKI_PREFIX.length + 32 &&\n spki.subarray(0, ED25519_SPKI_PREFIX.length).equals(ED25519_SPKI_PREFIX)\n )\n return spki.subarray(ED25519_SPKI_PREFIX.length);\n return spki;\n}\n\nfunction fingerprintPublicKey(publicKeyPem: string): string {\n const raw = derivePublicKeyRaw(publicKeyPem);\n return crypto.createHash(\"sha256\").update(raw).digest(\"hex\");\n}\n\nfunction publicKeyRawBase64UrlFromPem(publicKeyPem: string): string {\n return base64UrlEncode(derivePublicKeyRaw(publicKeyPem));\n}\n\nfunction signDevicePayload(privateKeyPem: string, payload: string): string {\n const key = crypto.createPrivateKey(privateKeyPem);\n return base64UrlEncode(crypto.sign(null, Buffer.from(payload, \"utf8\"), key));\n}\n\nfunction buildDeviceAuthPayload(params: {\n deviceId: string;\n clientId: string;\n clientMode: string;\n role: string;\n scopes: string[];\n signedAtMs: number;\n token: string | null;\n nonce: string;\n}): string {\n const scopes = params.scopes.join(\",\");\n const token = params.token ?? \"\";\n return [\n \"v2\",\n params.deviceId,\n params.clientId,\n params.clientMode,\n params.role,\n scopes,\n String(params.signedAtMs),\n token,\n params.nonce,\n ].join(\"|\");\n}\n\nfunction resolveStateDir(): string {\n return resolveHostStateDir();\n}\n\nfunction loadOrCreateDeviceIdentity(): DeviceIdentity {\n const filePath = path.join(resolveStateDir(), \"identity\", \"device.json\");\n try {\n if (fs.existsSync(filePath)) {\n const raw = fs.readFileSync(filePath, \"utf8\");\n const parsed = JSON.parse(raw);\n if (\n parsed?.version === 1 &&\n typeof parsed.deviceId === \"string\" &&\n typeof parsed.publicKeyPem === \"string\" &&\n typeof parsed.privateKeyPem === \"string\"\n ) {\n const derivedId = fingerprintPublicKey(parsed.publicKeyPem);\n return {\n deviceId: derivedId,\n publicKeyPem: parsed.publicKeyPem,\n privateKeyPem: parsed.privateKeyPem,\n };\n }\n }\n } catch {\n // fall through to generate\n }\n // Generate new identity\n const { publicKey, privateKey } = crypto.generateKeyPairSync(\"ed25519\");\n const publicKeyPem = publicKey\n .export({ type: \"spki\", format: \"pem\" })\n .toString();\n const privateKeyPem = privateKey\n .export({ type: \"pkcs8\", format: \"pem\" })\n .toString();\n const identity: DeviceIdentity = {\n deviceId: fingerprintPublicKey(publicKeyPem),\n publicKeyPem,\n privateKeyPem,\n };\n fs.mkdirSync(path.dirname(filePath), { recursive: true });\n const stored = {\n version: 1,\n ...identity,\n createdAtMs: Date.now(),\n };\n fs.writeFileSync(filePath, `${JSON.stringify(stored, null, 2)}\\n`, {\n mode: 0o600,\n });\n return identity;\n}\n\n// ─── Types ───\n\ninterface ProxyOptions {\n gatewayBaseUrl: string;\n /** Gateway 鉴权模式 */\n gatewayAuthMode?: \"token\" | \"password\";\n /** Gateway 鉴权 token,代理请求到本地 gateway 时使用 */\n gatewayToken?: string;\n /** Gateway 鉴权密码,代理请求到本地 gateway 时使用 */\n gatewayPassword?: string;\n client: RelayClient;\n logger: {\n info: (msg: string) => void;\n warn: (msg: string) => void;\n error: (msg: string) => void;\n };\n}\n\n/**\n * 透明代理:接收 Relay 转发的请求帧,代理到本地 gateway,回传响应帧。\n * 支持 HTTP 请求代理和 WebSocket 连接代理。\n */\nexport class TunnelProxy {\n /** 活跃的 WebSocket 代理连接,按帧 id 索引 */\n private wsConnections = new Map<string, WebSocket>();\n\n /** 到本地 Gateway 的持久 RPC WebSocket 连接 */\n private gatewayWs: WebSocket | null = null;\n private gatewayWsConnecting = false;\n /** 握手是否已完成(收到 hello-ok) */\n private gatewayWsReady = false;\n /** 等待 Gateway WS 握手完成后发送的帧队列 */\n private gatewayWsPending: string[] = [];\n\n /** 设备身份,用于 Gateway connect 握手 */\n private deviceIdentity: DeviceIdentity;\n\n constructor(private readonly opts: ProxyOptions) {\n this.deviceIdentity = loadOrCreateDeviceIdentity();\n opts.logger.info(\n `TunnelProxy: loaded device identity (deviceId=${this.deviceIdentity.deviceId})`,\n );\n }\n\n private pushGatewayPending(payload: string, reason: string): void {\n this.gatewayWsPending.push(payload);\n this.opts.logger.info(\n `TunnelProxy: gateway WS pending queue size=${this.gatewayWsPending.length} (${reason})`,\n );\n }\n\n private resolveGatewayConnectAuth():\n | {\n token?: string;\n password?: string;\n }\n | undefined {\n const token = this.opts.gatewayToken?.trim() || undefined;\n const password = this.opts.gatewayPassword?.trim() || undefined;\n if (!token && !password) {\n return undefined;\n }\n return {\n token,\n password,\n };\n }\n\n private buildLocalGatewayAuthAttempts(\n baseHeaders: Record<string, string>,\n ): Array<{ label: string; headers: Record<string, string> }> {\n const auth = this.resolveGatewayConnectAuth();\n const attempts: Array<{ label: string; headers: Record<string, string> }> = [];\n const seen = new Set<string>();\n const authMode = this.opts.gatewayAuthMode;\n\n const addAttempt = (kind: \"token\" | \"password\", secret?: string): void => {\n if (!secret) return;\n\n const dedupeKey = `${kind}:${secret}`;\n if (seen.has(dedupeKey)) return;\n seen.add(dedupeKey);\n\n const headers = { ...baseHeaders };\n headers.authorization = `Bearer ${secret}`;\n\n if (kind === \"password\") {\n headers[\"x-openclaw-password\"] = secret;\n } else {\n delete headers[\"x-openclaw-password\"];\n }\n\n attempts.push({\n label: kind === \"token\" ? \"gateway-token\" : \"gateway-password\",\n headers,\n });\n };\n\n if (authMode === \"password\") {\n addAttempt(\"password\", auth?.password);\n addAttempt(\"token\", auth?.token);\n } else {\n addAttempt(\"token\", auth?.token);\n addAttempt(\"password\", auth?.password);\n }\n\n if (attempts.length === 0) {\n attempts.push({\n label: \"no-auth\",\n headers: { ...baseHeaders },\n });\n }\n\n return attempts;\n }\n\n private async sendHttpResponse(params: {\n frameId: string;\n method: string;\n path: string;\n authLabel: string;\n startedAtMs: number;\n res: Response;\n }): Promise<void> {\n const { frameId, method, path, authLabel, startedAtMs, res } = params;\n const contentType = res.headers.get(\"content-type\") ?? \"\";\n const isStreaming = contentType.includes(\"text/event-stream\");\n const elapsedMs = Date.now() - startedAtMs;\n\n this.opts.logger.info(\n `TunnelProxy: HTTP id=${frameId} ${method} ${path} <= ${res.status} (${elapsedMs}ms, auth=${authLabel}, content-type=${contentType}, streaming=${isStreaming})`,\n );\n\n if (isStreaming && res.body) {\n await this.streamResponse(frameId, res, startedAtMs);\n return;\n }\n\n const body = await res.text();\n this.opts.logger.info(\n `TunnelProxy: HTTP id=${frameId} response body=${previewText(body)}`,\n );\n const headers: Record<string, string> = {};\n res.headers.forEach((value, key) => {\n headers[key] = value;\n });\n\n this.opts.client.send({\n type: \"proxy_response\",\n id: frameId,\n status: res.status,\n headers,\n body,\n });\n }\n\n /** 处理从 Relay 收到的入站帧 */\n async handleFrame(frame: InboundFrame): Promise<void> {\n this.opts.logger.info(\n `TunnelProxy: handling frame type=${frame.type}, id=${\"id\" in frame ? frame.id : \"N/A\"}`,\n );\n switch (frame.type) {\n case \"request\":\n await this.handleHttpRequest(frame);\n break;\n case \"req\":\n this.handleReqFrame(frame);\n break;\n case \"ws_open\":\n this.handleWsOpen(frame);\n break;\n case \"ws_data\":\n this.handleWsData(frame);\n break;\n case \"ws_close\":\n this.handleWsClose(frame);\n break;\n default:\n this.opts.logger.warn(\n `TunnelProxy: unknown frame type=\"${(frame as any).type}\", id=${\"id\" in frame ? (frame as any).id : \"N/A\"}, forwarding raw to gateway`,\n );\n // 未知帧类型也尝试通过 RPC WS 转发,避免静默丢弃\n this.forwardRawToGateway(JSON.stringify(frame));\n break;\n }\n }\n\n /** 将未知帧原样转发到 Gateway WS */\n private forwardRawToGateway(payload: string): void {\n this.ensureGatewayWs();\n if (this.gatewayWsReady && this.gatewayWs?.readyState === WebSocket.OPEN) {\n this.gatewayWs.send(payload);\n } else {\n this.pushGatewayPending(payload, \"raw frame queued before gateway WS ready\");\n }\n }\n\n /** 清理所有代理的 WebSocket 连接 */\n cleanup(): void {\n this.opts.logger.info(\n `TunnelProxy: cleanup, closing ${this.wsConnections.size} active WS connections, gatewayWs=${!!this.gatewayWs}`,\n );\n for (const [id, ws] of this.wsConnections) {\n this.opts.logger.info(`TunnelProxy: closing WS id=${id}`);\n try {\n ws.close();\n } catch {\n // ignore\n }\n }\n this.wsConnections.clear();\n\n if (this.gatewayWs) {\n try {\n this.gatewayWs.close();\n } catch {\n // ignore\n }\n this.gatewayWs = null;\n }\n this.gatewayWsPending = [];\n }\n\n // ─── Gateway RPC WebSocket ───\n\n /** 确保到本地 Gateway 的 RPC WebSocket 已连接且握手完成 */\n private ensureGatewayWs(): void {\n if (this.gatewayWsReady && this.gatewayWs?.readyState === WebSocket.OPEN)\n return;\n if (this.gatewayWsConnecting) return;\n\n this.gatewayWsConnecting = true;\n this.gatewayWsReady = false;\n const wsUrl = this.opts.gatewayBaseUrl.replace(/^http/, \"ws\");\n\n this.opts.logger.info(\n `TunnelProxy: RPC WS connecting to gateway ${wsUrl} (pending=${this.gatewayWsPending.length})`,\n );\n\n const ws = new WebSocket(wsUrl);\n\n ws.on(\"open\", () => {\n this.gatewayWs = ws;\n // 注意:不在此处清除 gatewayWsConnecting,等握手完成(hello-ok)或失败后再清除,\n // 防止窗口期内重复创建连接导致消息重复。\n this.opts.logger.info(\n `TunnelProxy: RPC WS tcp connected, waiting for connect.challenge (pending=${this.gatewayWsPending.length})`,\n );\n });\n\n ws.on(\"message\", (data: WebSocket.RawData) => {\n let text: string;\n if (typeof data === \"string\") {\n text = data;\n } else if (Buffer.isBuffer(data)) {\n text = data.toString();\n } else {\n text = Buffer.from(data as ArrayBuffer).toString();\n }\n\n // 对较短消息或包含错误的消息打完整日志,其余截断到 500 字符\n const preview = text.length <= 500 ? text : text.substring(0, 500) + \"…\";\n this.opts.logger.info(\n `TunnelProxy: RPC WS ← gateway (${text.length} chars): ${preview}`,\n );\n\n // 解析帧判断握手阶段\n let frame: any;\n try {\n frame = JSON.parse(text);\n } catch {\n this.opts.logger.warn(\n \"TunnelProxy: RPC WS received non-JSON, ignoring\",\n );\n return;\n }\n\n // 1) 收到 connect.challenge → 回复 connect 请求(带设备身份签名)\n if (frame.type === \"event\" && frame.event === \"connect.challenge\") {\n const challengeNonce: string = frame.payload?.nonce ?? \"\";\n const connectRequestId = `tunnel-connect-${randomUUID()}`;\n const gatewayAuth = this.resolveGatewayConnectAuth();\n this.opts.logger.info(\n `TunnelProxy: received connect.challenge (nonce=${challengeNonce}, connectReqId=${connectRequestId}, hasToken=${!!gatewayAuth?.token}, hasPassword=${!!gatewayAuth?.password}), sending connect request with device identity`,\n );\n\n const role = \"operator\";\n const scopes = [\"operator.admin\"];\n const signedAtMs = Date.now();\n const clientId = \"gateway-client\";\n const clientMode = \"backend\";\n\n // 构建设备签名\n const authPayload = buildDeviceAuthPayload({\n deviceId: this.deviceIdentity.deviceId,\n clientId,\n clientMode,\n role,\n scopes,\n signedAtMs,\n token: gatewayAuth?.token ?? null,\n nonce: challengeNonce,\n });\n const signature = signDevicePayload(\n this.deviceIdentity.privateKeyPem,\n authPayload,\n );\n\n const connectReq = {\n type: \"req\",\n id: connectRequestId,\n method: \"connect\",\n params: {\n minProtocol: 3,\n maxProtocol: 3,\n client: {\n id: clientId,\n version: \"1.0.0\",\n platform: process.platform,\n mode: clientMode,\n },\n role,\n scopes,\n ...(gatewayAuth ? { auth: gatewayAuth } : {}),\n device: {\n id: this.deviceIdentity.deviceId,\n publicKey: publicKeyRawBase64UrlFromPem(\n this.deviceIdentity.publicKeyPem,\n ),\n signature,\n signedAt: signedAtMs,\n nonce: challengeNonce,\n },\n },\n };\n ws.send(JSON.stringify(connectReq));\n return;\n }\n\n // 2) 收到 connect 的 hello-ok 响应 → 握手完成,flush 待发帧\n if (\n frame.type === \"res\" &&\n frame.ok === true &&\n frame.payload?.type === \"hello-ok\"\n ) {\n this.gatewayWsReady = true;\n this.gatewayWsConnecting = false;\n this.opts.logger.info(\n `TunnelProxy: RPC WS handshake done (hello-ok), flushing ${this.gatewayWsPending.length} pending frames`,\n );\n for (const pending of this.gatewayWsPending) {\n ws.send(pending);\n }\n this.gatewayWsPending = [];\n return;\n }\n\n // 3) 收到 connect 失败响应 → 关闭连接\n if (frame.type === \"res\" && frame.ok === false && !this.gatewayWsReady) {\n this.opts.logger.error(\n `TunnelProxy: RPC WS handshake failed (pending=${this.gatewayWsPending.length}): ${previewText(JSON.stringify(frame.error), 500)}`,\n );\n ws.close();\n return;\n }\n\n // 4) 握手后的普通消息 → 透传回 Relay\n this.opts.client.sendRaw(text);\n });\n\n ws.on(\"close\", (code: number, reason: Buffer) => {\n const wasReady = this.gatewayWsReady;\n const pendingCount = this.gatewayWsPending.length;\n this.opts.logger.info(\n `TunnelProxy: RPC WS closed by gateway (code=${code}, reason=${reason.toString()}, ready=${wasReady}, pending=${pendingCount}, activeWs=${this.wsConnections.size})`,\n );\n if (this.gatewayWs === ws) {\n this.gatewayWs = null;\n this.gatewayWsReady = false;\n }\n this.gatewayWsConnecting = false;\n });\n\n ws.on(\"error\", (err: Error) => {\n this.opts.logger.warn(\n `TunnelProxy: RPC WS error: ${err.message} (ready=${this.gatewayWsReady}, pending=${this.gatewayWsPending.length}, activeWs=${this.wsConnections.size})`,\n );\n this.gatewayWsConnecting = false;\n if (this.gatewayWs === ws) {\n this.gatewayWs = null;\n this.gatewayWsReady = false;\n }\n });\n }\n\n /** 处理 Relay 转发的 Gateway RPC 请求帧,原样通过 WebSocket 发给本地 Gateway */\n private handleReqFrame(frame: ReqFrame): void {\n const payload = JSON.stringify(frame);\n this.opts.logger.info(\n `TunnelProxy: req id=${frame.id} method=${frame.method} → gateway WS (${payload.length} chars)`,\n );\n\n this.ensureGatewayWs();\n\n if (this.gatewayWsReady && this.gatewayWs?.readyState === WebSocket.OPEN) {\n this.gatewayWs.send(payload);\n } else {\n this.opts.logger.info(\n `TunnelProxy: req id=${frame.id} queued, gateway WS not ready yet`,\n );\n this.pushGatewayPending(\n payload,\n `req id=${frame.id} queued before gateway WS handshake`,\n );\n }\n }\n\n // ─── 路径映射 ───\n\n private static readonly PATH_MAP: Record<string, string> = {\n \"/api/message/messageBridge/send\": \"/notifications\",\n };\n\n private mapPath(path: string): string {\n return TunnelProxy.PATH_MAP[path] ?? path;\n }\n\n // ─── HTTP 请求代理 ───\n\n private async handleHttpRequest(frame: RequestFrame): Promise<void> {\n const mappedPath = this.mapPath(frame.path);\n const url = new URL(mappedPath, this.opts.gatewayBaseUrl);\n const startedAtMs = Date.now();\n // 代理到本地 gateway 时,替换外部鉴权头为本地 gateway token/password。\n const localHeaders: Record<string, string> = {};\n for (const [k, v] of Object.entries(frame.headers ?? {})) {\n const lower = k.toLowerCase();\n if (lower !== \"authorization\" && lower !== \"x-openclaw-password\") {\n localHeaders[k] = v;\n }\n }\n const authAttempts = this.buildLocalGatewayAuthAttempts(localHeaders);\n this.opts.logger.info(\n `TunnelProxy: HTTP id=${frame.id} ${frame.method} ${frame.path} → ${url.toString()}${summarizeRequestHeaders(frame.headers)}, authAttempts=${authAttempts.map((attempt) => attempt.label).join(\" -> \")}, body=${previewText(frame.body)}`,\n );\n\n try {\n for (let attemptIndex = 0; attemptIndex < authAttempts.length; attemptIndex++) {\n const attempt = authAttempts[attemptIndex];\n this.opts.logger.info(\n `TunnelProxy: HTTP id=${frame.id} attempt ${attemptIndex + 1}/${authAttempts.length} auth=${attempt.label}`,\n );\n const res = await fetch(url.toString(), {\n method: frame.method,\n headers: attempt.headers,\n body:\n frame.method !== \"GET\" && frame.method !== \"HEAD\"\n ? frame.body\n : undefined,\n });\n\n const hasFallback = attemptIndex < authAttempts.length - 1;\n if (res.status === 401 && hasFallback) {\n const body = await res.text();\n this.opts.logger.warn(\n `TunnelProxy: HTTP id=${frame.id} local gateway auth via ${attempt.label} returned 401 after ${Date.now() - startedAtMs}ms, retrying next credential${body ? `, body=${previewText(body)}` : \"\"}`,\n );\n continue;\n }\n\n await this.sendHttpResponse({\n frameId: frame.id,\n method: frame.method,\n path: mappedPath,\n authLabel: attempt.label,\n startedAtMs,\n res,\n });\n return;\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n this.opts.logger.error(\n `TunnelProxy: HTTP id=${frame.id} ${frame.method} ${mappedPath} failed after ${Date.now() - startedAtMs}ms: ${message}`,\n );\n this.opts.client.send({\n type: \"proxy_error\",\n id: frame.id,\n status: 502,\n message: `gateway unreachable: ${message}`,\n });\n }\n }\n\n private async streamResponse(\n requestId: string,\n res: Response,\n startedAtMs: number,\n ): Promise<void> {\n const reader = res.body!.getReader();\n const decoder = new TextDecoder();\n let chunkCount = 0;\n\n this.opts.logger.info(`TunnelProxy: stream start id=${requestId}`);\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n chunkCount++;\n const chunk = decoder.decode(value, { stream: true });\n this.opts.logger.info(\n `TunnelProxy: stream delta id=${requestId} chunk#${chunkCount} (${chunk.length} chars)`,\n );\n this.opts.client.send({\n type: \"stream\",\n id: requestId,\n state: \"delta\",\n data: chunk,\n });\n }\n\n this.opts.logger.info(\n `TunnelProxy: stream end id=${requestId}, total chunks=${chunkCount}, totalElapsedMs=${Date.now() - startedAtMs}`,\n );\n this.opts.client.send({\n type: \"stream\",\n id: requestId,\n state: \"end\",\n data: \"\",\n });\n } catch (err) {\n this.opts.logger.error(\n `TunnelProxy: stream error id=${requestId} after ${chunkCount} chunks and ${Date.now() - startedAtMs}ms: ${err instanceof Error ? err.message : String(err)}`,\n );\n this.opts.client.send({\n type: \"proxy_error\",\n id: requestId,\n status: 502,\n message: `stream error: ${err instanceof Error ? err.message : String(err)}`,\n });\n }\n }\n\n // ─── WebSocket 连接代理 ───\n\n private handleWsOpen(frame: WsOpenFrame): void {\n const wsUrl =\n this.opts.gatewayBaseUrl.replace(/^http/, \"ws\") +\n this.mapPath(frame.path);\n this.opts.logger.info(\n `TunnelProxy: WS open id=${frame.id}, path=${frame.path} → ${wsUrl}`,\n );\n\n try {\n const ws = new WebSocket(wsUrl, {\n headers: frame.headers,\n });\n\n ws.on(\"open\", () => {\n this.wsConnections.set(frame.id, ws);\n this.opts.logger.info(\n `TunnelProxy: WS id=${frame.id} connected to gateway, active=${this.wsConnections.size}`,\n );\n this.opts.client.send({\n type: \"ws_opened\",\n id: frame.id,\n });\n });\n\n ws.on(\"message\", (data: WebSocket.RawData) => {\n const text =\n typeof data === \"string\"\n ? data\n : Buffer.isBuffer(data)\n ? data.toString()\n : String(data);\n\n this.opts.logger.info(\n `TunnelProxy: WS id=${frame.id} ← gateway data (${text.length} chars): ${text.substring(0, 200)}`,\n );\n this.opts.client.send({\n type: \"ws_data\",\n id: frame.id,\n data: text,\n });\n });\n\n ws.on(\"close\", (code: number, reason: Buffer) => {\n this.wsConnections.delete(frame.id);\n this.opts.logger.info(\n `TunnelProxy: WS id=${frame.id} closed by gateway (code=${code}, reason=${reason.toString()}), active=${this.wsConnections.size}`,\n );\n this.opts.client.send({\n type: \"ws_close\",\n id: frame.id,\n code,\n reason: reason.toString(),\n });\n });\n\n ws.on(\"error\", (err: Error) => {\n this.opts.logger.warn(\n `TunnelProxy: WS id=${frame.id} error: ${err.message}, active=${this.wsConnections.size}`,\n );\n this.wsConnections.delete(frame.id);\n this.opts.client.send({\n type: \"ws_close\",\n id: frame.id,\n code: 1011,\n reason: err.message,\n });\n });\n } catch (err) {\n this.opts.logger.error(\n `TunnelProxy: WS id=${frame.id} failed to connect: ${err instanceof Error ? err.message : String(err)}`,\n );\n this.opts.client.send({\n type: \"ws_close\",\n id: frame.id,\n code: 1011,\n reason: `failed to connect: ${err instanceof Error ? err.message : String(err)}`,\n });\n }\n }\n\n private handleWsData(frame: WsDataFrame): void {\n const ws = this.wsConnections.get(frame.id);\n if (ws?.readyState === WebSocket.OPEN) {\n this.opts.logger.info(\n `TunnelProxy: WS id=${frame.id} → gateway data (${frame.data.length} chars): ${frame.data.substring(0, 200)}`,\n );\n ws.send(frame.data);\n } else {\n this.opts.logger.warn(\n `TunnelProxy: WS id=${frame.id} data dropped, ws not open (exists=${!!ws}, readyState=${ws?.readyState ?? \"N/A\"})`,\n );\n }\n }\n\n private handleWsClose(frame: WsCloseFrame): void {\n const ws = this.wsConnections.get(frame.id);\n if (ws) {\n this.opts.logger.info(\n `TunnelProxy: WS id=${frame.id} close requested by relay (code=${frame.code ?? 1000}, reason=${frame.reason ?? \"\"})`,\n );\n this.wsConnections.delete(frame.id);\n try {\n ws.close(frame.code ?? 1000, frame.reason ?? \"\");\n } catch {\n // ignore\n }\n } else {\n this.opts.logger.warn(\n `TunnelProxy: WS id=${frame.id} close requested but connection not found`,\n );\n }\n }\n}\n","import { appendFileSync, mkdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nexport interface Logger {\n info: (msg: string) => void;\n warn: (msg: string) => void;\n error: (msg: string) => void;\n}\n\n/**\n * 插件级文件 Logger。\n * 在调用原始 api.logger 的同时,把日志追加写入\n * `<stateDir>/plugins/phone-notifications/logs/YYYY-MM-DD.log`。\n */\nexport class PluginFileLogger implements Logger {\n private readonly logsDir: string;\n\n constructor(\n private readonly upstream: Logger,\n stateDir: string,\n ) {\n this.logsDir = join(stateDir, \"plugins\", \"phone-notifications\", \"logs\");\n mkdirSync(this.logsDir, { recursive: true });\n }\n\n info(msg: string): void {\n this.upstream.info(msg);\n this.append(\"INFO\", msg);\n }\n\n warn(msg: string): void {\n this.upstream.warn(msg);\n this.append(\"WARN\", msg);\n }\n\n error(msg: string): void {\n this.upstream.error(msg);\n this.append(\"ERROR\", msg);\n }\n\n private append(level: string, msg: string): void {\n const now = new Date();\n const dateKey = formatDate(now);\n const time = now.toISOString();\n const line = `${time} [${level}] ${msg}\\n`;\n try {\n appendFileSync(join(this.logsDir, `${dateKey}.log`), line);\n } catch {\n // 写文件失败不影响主流程\n }\n }\n}\n\nfunction formatDate(d: Date): string {\n const y = d.getFullYear();\n const m = String(d.getMonth() + 1).padStart(2, \"0\");\n const day = String(d.getDate()).padStart(2, \"0\");\n return `${y}-${m}-${day}`;\n}\n"],"mappings":"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","names":["output","data","Receiver","Sender","createHash","URL","Receiver","Sender","WebSocket","key","WebSocket","createWebSocketStream","err","protocol","createHash","WebSocket","WebSocketServer","readFileSync","basename","dirname","existsSync","readFileSync","dirname","existsSync","readFileSync","dirname","existsSync","mkdirSync","readFileSync","writeFileSync","join","existsSync","mkdirSync","readFileSync","writeFileSync","dirname","path","existsSync","readFileSync","mkdirSync","dirname","writeFileSync","path","dirname","join","path","existsSync","readFileSync","mkdirSync","writeFileSync","mkdirSync","readFileSync","writeFileSync","existsSync","join","existsSync","rmSync","existsSync","readFileSync","readdirSync","join","path","existsSync","rmSync","existsSync","readFileSync","writeFileSync","join","join","existsSync","readFileSync","writeFileSync","existsSync","mkdirSync","readFileSync","writeFileSync","rmSync","readdirSync","join","join","existsSync","readFileSync","writeFileSync","readdirSync","checkpointPath","mkdirSync","rmSync","existsSync","readFileSync","writeFileSync","join","join","existsSync","readFileSync","writeFileSync","existsSync","readFileSync","join","join","existsSync","readFileSync","existsSync","readFileSync","readdirSync","join","join","existsSync","readdirSync","readFileSync","readFileSync","mkdirSync","readFileSync","writeFileSync","dirname","join","writeFileSync","mkdirSync","dirname","import_sender","WebSocket","mkdirSync","dirname","writeFileSync","randomUUID","previewText","resolveStateDir","path","randomUUID","readFileSync","mkdirSync","dirname","writeFileSync","join","appendFileSync","mkdirSync","join","formatDate","trimToUndefined","readFileSync","basename","dirname"]}
|