lightclawbot 1.1.2 → 1.2.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -1
- package/dist/index.js +38 -31
- package/dist/setup-entry.js +32 -0
- package/dist/src/channel.js +301 -257
- package/dist/src/channel.setup.js +16 -0
- package/dist/src/config.js +31 -124
- package/dist/src/dedup.js +0 -1
- package/dist/src/download-tool.js +0 -1
- package/dist/src/file-storage.js +2 -2
- package/dist/src/gateway.js +226 -178
- package/dist/src/history/cron-utils.js +0 -1
- package/dist/src/history/index.js +0 -1
- package/dist/src/history/message-parser.js +0 -1
- package/dist/src/history/session-reader.js +3 -1
- package/dist/src/history/session-store.js +0 -1
- package/dist/src/history/text-processing.js +0 -1
- package/dist/src/history/types.js +0 -1
- package/dist/src/inbound.js +183 -234
- package/dist/src/media.js +0 -1
- package/dist/src/messaging.js +65 -0
- package/dist/src/outbound.js +131 -45
- package/dist/src/runtime.js +29 -11
- package/dist/src/setup-core.js +27 -0
- package/dist/src/shared.js +141 -0
- package/dist/src/socket/handlers.js +72 -49
- package/dist/src/socket/index.js +0 -1
- package/dist/src/socket/native-socket.js +385 -0
- package/dist/src/socket/registry.js +0 -1
- package/dist/src/socket/reliable-emitter.js +188 -50
- package/dist/src/streaming/delta-tracker.js +140 -0
- package/dist/src/streaming/index.js +12 -0
- package/dist/src/streaming/stream-reply-sink.js +387 -0
- package/dist/src/streaming/types.js +4 -0
- package/dist/src/tools.js +13 -0
- package/dist/src/types.js +23 -2
- package/dist/src/upload-tool.js +0 -1
- package/dist/src/utils/account.js +73 -0
- package/dist/src/utils/common.js +48 -0
- package/dist/src/utils/index.js +2 -0
- package/node_modules/ws/index.js +22 -0
- package/node_modules/{engine.io-client/node_modules/ws → ws}/lib/constants.js +1 -0
- package/node_modules/{engine.io-client/node_modules/ws → ws}/lib/permessage-deflate.js +6 -6
- package/node_modules/{engine.io-client/node_modules/ws → ws}/lib/websocket-server.js +10 -6
- package/node_modules/{engine.io-client/node_modules/ws → ws}/lib/websocket.js +19 -14
- package/node_modules/{engine.io-client/node_modules/ws → ws}/package.json +4 -3
- package/node_modules/ws/wrapper.mjs +21 -0
- package/openclaw.plugin.json +0 -7
- package/package.json +8 -5
- package/dist/index.d.ts +0 -24
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/public/data/scripts/manifest.json +0 -11
- package/dist/public/data/scripts/preflight.9af62b39.sh +0 -191
- package/dist/public/data/scripts/preflight.sh +0 -191
- package/dist/src/channel.d.ts +0 -11
- package/dist/src/channel.d.ts.map +0 -1
- package/dist/src/channel.js.map +0 -1
- package/dist/src/config.d.ts +0 -129
- package/dist/src/config.d.ts.map +0 -1
- package/dist/src/config.js.map +0 -1
- package/dist/src/dedup.d.ts +0 -12
- package/dist/src/dedup.d.ts.map +0 -1
- package/dist/src/dedup.js.map +0 -1
- package/dist/src/download-tool.d.ts +0 -32
- package/dist/src/download-tool.d.ts.map +0 -1
- package/dist/src/download-tool.js.map +0 -1
- package/dist/src/file-storage.d.ts +0 -74
- package/dist/src/file-storage.d.ts.map +0 -1
- package/dist/src/file-storage.js.map +0 -1
- package/dist/src/format-urls.d.ts +0 -26
- package/dist/src/format-urls.d.ts.map +0 -1
- package/dist/src/format-urls.js +0 -53
- package/dist/src/format-urls.js.map +0 -1
- package/dist/src/gateway.d.ts +0 -16
- package/dist/src/gateway.d.ts.map +0 -1
- package/dist/src/gateway.js.map +0 -1
- package/dist/src/history/cron-utils.d.ts +0 -76
- package/dist/src/history/cron-utils.d.ts.map +0 -1
- package/dist/src/history/cron-utils.js.map +0 -1
- package/dist/src/history/index.d.ts +0 -20
- package/dist/src/history/index.d.ts.map +0 -1
- package/dist/src/history/index.js.map +0 -1
- package/dist/src/history/message-parser.d.ts +0 -52
- package/dist/src/history/message-parser.d.ts.map +0 -1
- package/dist/src/history/message-parser.js.map +0 -1
- package/dist/src/history/session-reader.d.ts +0 -58
- package/dist/src/history/session-reader.d.ts.map +0 -1
- package/dist/src/history/session-reader.js.map +0 -1
- package/dist/src/history/session-store.d.ts +0 -42
- package/dist/src/history/session-store.d.ts.map +0 -1
- package/dist/src/history/session-store.js.map +0 -1
- package/dist/src/history/text-processing.d.ts +0 -41
- package/dist/src/history/text-processing.d.ts.map +0 -1
- package/dist/src/history/text-processing.js.map +0 -1
- package/dist/src/history/types.d.ts +0 -134
- package/dist/src/history/types.d.ts.map +0 -1
- package/dist/src/history/types.js.map +0 -1
- package/dist/src/inbound.d.ts +0 -18
- package/dist/src/inbound.d.ts.map +0 -1
- package/dist/src/inbound.js.map +0 -1
- package/dist/src/media.d.ts +0 -12
- package/dist/src/media.d.ts.map +0 -1
- package/dist/src/media.js.map +0 -1
- package/dist/src/outbound.d.ts +0 -28
- package/dist/src/outbound.d.ts.map +0 -1
- package/dist/src/outbound.js.map +0 -1
- package/dist/src/runtime.d.ts +0 -4
- package/dist/src/runtime.d.ts.map +0 -1
- package/dist/src/runtime.js.map +0 -1
- package/dist/src/socket/handlers.d.ts +0 -26
- package/dist/src/socket/handlers.d.ts.map +0 -1
- package/dist/src/socket/handlers.js.map +0 -1
- package/dist/src/socket/index.d.ts +0 -11
- package/dist/src/socket/index.d.ts.map +0 -1
- package/dist/src/socket/index.js.map +0 -1
- package/dist/src/socket/registry.d.ts +0 -59
- package/dist/src/socket/registry.d.ts.map +0 -1
- package/dist/src/socket/registry.js.map +0 -1
- package/dist/src/socket/reliable-emitter.d.ts +0 -79
- package/dist/src/socket/reliable-emitter.d.ts.map +0 -1
- package/dist/src/socket/reliable-emitter.js.map +0 -1
- package/dist/src/types.d.ts +0 -112
- package/dist/src/types.d.ts.map +0 -1
- package/dist/src/types.js.map +0 -1
- package/dist/src/upload-tool.d.ts +0 -27
- package/dist/src/upload-tool.d.ts.map +0 -1
- package/dist/src/upload-tool.js.map +0 -1
- package/node_modules/@socket.io/component-emitter/LICENSE +0 -24
- package/node_modules/@socket.io/component-emitter/Readme.md +0 -79
- package/node_modules/@socket.io/component-emitter/lib/cjs/index.d.ts +0 -179
- package/node_modules/@socket.io/component-emitter/lib/cjs/index.js +0 -176
- package/node_modules/@socket.io/component-emitter/lib/cjs/package.json +0 -4
- package/node_modules/@socket.io/component-emitter/lib/esm/index.d.ts +0 -179
- package/node_modules/@socket.io/component-emitter/lib/esm/index.js +0 -169
- package/node_modules/@socket.io/component-emitter/lib/esm/package.json +0 -4
- package/node_modules/@socket.io/component-emitter/package.json +0 -28
- package/node_modules/debug/LICENSE +0 -20
- package/node_modules/debug/README.md +0 -481
- package/node_modules/debug/package.json +0 -64
- package/node_modules/debug/src/browser.js +0 -272
- package/node_modules/debug/src/common.js +0 -292
- package/node_modules/debug/src/index.js +0 -10
- package/node_modules/debug/src/node.js +0 -263
- package/node_modules/engine.io-client/LICENSE +0 -22
- package/node_modules/engine.io-client/README.md +0 -331
- package/node_modules/engine.io-client/build/cjs/browser-entrypoint.d.ts +0 -3
- package/node_modules/engine.io-client/build/cjs/browser-entrypoint.js +0 -4
- package/node_modules/engine.io-client/build/cjs/contrib/has-cors.d.ts +0 -1
- package/node_modules/engine.io-client/build/cjs/contrib/has-cors.js +0 -14
- package/node_modules/engine.io-client/build/cjs/contrib/parseqs.d.ts +0 -15
- package/node_modules/engine.io-client/build/cjs/contrib/parseqs.js +0 -38
- package/node_modules/engine.io-client/build/cjs/contrib/parseuri.d.ts +0 -1
- package/node_modules/engine.io-client/build/cjs/contrib/parseuri.js +0 -67
- package/node_modules/engine.io-client/build/cjs/globals.d.ts +0 -4
- package/node_modules/engine.io-client/build/cjs/globals.js +0 -26
- package/node_modules/engine.io-client/build/cjs/globals.node.d.ts +0 -21
- package/node_modules/engine.io-client/build/cjs/globals.node.js +0 -97
- package/node_modules/engine.io-client/build/cjs/index.d.ts +0 -15
- package/node_modules/engine.io-client/build/cjs/index.js +0 -32
- package/node_modules/engine.io-client/build/cjs/package.json +0 -10
- package/node_modules/engine.io-client/build/cjs/socket.d.ts +0 -482
- package/node_modules/engine.io-client/build/cjs/socket.js +0 -765
- package/node_modules/engine.io-client/build/cjs/transport.d.ts +0 -106
- package/node_modules/engine.io-client/build/cjs/transport.js +0 -153
- package/node_modules/engine.io-client/build/cjs/transports/index.d.ts +0 -8
- package/node_modules/engine.io-client/build/cjs/transports/index.js +0 -11
- package/node_modules/engine.io-client/build/cjs/transports/polling-fetch.d.ts +0 -15
- package/node_modules/engine.io-client/build/cjs/transports/polling-fetch.js +0 -60
- package/node_modules/engine.io-client/build/cjs/transports/polling-xhr.d.ts +0 -108
- package/node_modules/engine.io-client/build/cjs/transports/polling-xhr.js +0 -285
- package/node_modules/engine.io-client/build/cjs/transports/polling-xhr.node.d.ts +0 -11
- package/node_modules/engine.io-client/build/cjs/transports/polling-xhr.node.js +0 -44
- package/node_modules/engine.io-client/build/cjs/transports/polling.d.ts +0 -52
- package/node_modules/engine.io-client/build/cjs/transports/polling.js +0 -165
- package/node_modules/engine.io-client/build/cjs/transports/websocket.d.ts +0 -36
- package/node_modules/engine.io-client/build/cjs/transports/websocket.js +0 -136
- package/node_modules/engine.io-client/build/cjs/transports/websocket.node.d.ts +0 -14
- package/node_modules/engine.io-client/build/cjs/transports/websocket.node.js +0 -68
- package/node_modules/engine.io-client/build/cjs/transports/webtransport.d.ts +0 -18
- package/node_modules/engine.io-client/build/cjs/transports/webtransport.js +0 -94
- package/node_modules/engine.io-client/build/cjs/util.d.ts +0 -7
- package/node_modules/engine.io-client/build/cjs/util.js +0 -65
- package/node_modules/engine.io-client/build/esm/browser-entrypoint.d.ts +0 -3
- package/node_modules/engine.io-client/build/esm/browser-entrypoint.js +0 -2
- package/node_modules/engine.io-client/build/esm/contrib/has-cors.d.ts +0 -1
- package/node_modules/engine.io-client/build/esm/contrib/has-cors.js +0 -11
- package/node_modules/engine.io-client/build/esm/contrib/parseqs.d.ts +0 -15
- package/node_modules/engine.io-client/build/esm/contrib/parseqs.js +0 -34
- package/node_modules/engine.io-client/build/esm/contrib/parseuri.d.ts +0 -1
- package/node_modules/engine.io-client/build/esm/contrib/parseuri.js +0 -64
- package/node_modules/engine.io-client/build/esm/globals.d.ts +0 -4
- package/node_modules/engine.io-client/build/esm/globals.js +0 -22
- package/node_modules/engine.io-client/build/esm/globals.node.d.ts +0 -21
- package/node_modules/engine.io-client/build/esm/globals.node.js +0 -91
- package/node_modules/engine.io-client/build/esm/index.d.ts +0 -15
- package/node_modules/engine.io-client/build/esm/index.js +0 -15
- package/node_modules/engine.io-client/build/esm/package.json +0 -10
- package/node_modules/engine.io-client/build/esm/socket.d.ts +0 -482
- package/node_modules/engine.io-client/build/esm/socket.js +0 -727
- package/node_modules/engine.io-client/build/esm/transport.d.ts +0 -106
- package/node_modules/engine.io-client/build/esm/transport.js +0 -142
- package/node_modules/engine.io-client/build/esm/transports/index.d.ts +0 -8
- package/node_modules/engine.io-client/build/esm/transports/index.js +0 -8
- package/node_modules/engine.io-client/build/esm/transports/polling-fetch.d.ts +0 -15
- package/node_modules/engine.io-client/build/esm/transports/polling-fetch.js +0 -56
- package/node_modules/engine.io-client/build/esm/transports/polling-xhr.d.ts +0 -108
- package/node_modules/engine.io-client/build/esm/transports/polling-xhr.js +0 -271
- package/node_modules/engine.io-client/build/esm/transports/polling-xhr.node.d.ts +0 -11
- package/node_modules/engine.io-client/build/esm/transports/polling-xhr.node.js +0 -17
- package/node_modules/engine.io-client/build/esm/transports/polling.d.ts +0 -52
- package/node_modules/engine.io-client/build/esm/transports/polling.js +0 -145
- package/node_modules/engine.io-client/build/esm/transports/websocket.d.ts +0 -36
- package/node_modules/engine.io-client/build/esm/transports/websocket.js +0 -125
- package/node_modules/engine.io-client/build/esm/transports/websocket.node.d.ts +0 -14
- package/node_modules/engine.io-client/build/esm/transports/websocket.node.js +0 -41
- package/node_modules/engine.io-client/build/esm/transports/webtransport.d.ts +0 -18
- package/node_modules/engine.io-client/build/esm/transports/webtransport.js +0 -80
- package/node_modules/engine.io-client/build/esm/util.d.ts +0 -7
- package/node_modules/engine.io-client/build/esm/util.js +0 -59
- package/node_modules/engine.io-client/build/esm-debug/browser-entrypoint.d.ts +0 -3
- package/node_modules/engine.io-client/build/esm-debug/browser-entrypoint.js +0 -2
- package/node_modules/engine.io-client/build/esm-debug/contrib/has-cors.d.ts +0 -1
- package/node_modules/engine.io-client/build/esm-debug/contrib/has-cors.js +0 -11
- package/node_modules/engine.io-client/build/esm-debug/contrib/parseqs.d.ts +0 -15
- package/node_modules/engine.io-client/build/esm-debug/contrib/parseqs.js +0 -34
- package/node_modules/engine.io-client/build/esm-debug/contrib/parseuri.d.ts +0 -1
- package/node_modules/engine.io-client/build/esm-debug/contrib/parseuri.js +0 -64
- package/node_modules/engine.io-client/build/esm-debug/globals.d.ts +0 -4
- package/node_modules/engine.io-client/build/esm-debug/globals.js +0 -22
- package/node_modules/engine.io-client/build/esm-debug/globals.node.d.ts +0 -21
- package/node_modules/engine.io-client/build/esm-debug/globals.node.js +0 -91
- package/node_modules/engine.io-client/build/esm-debug/index.d.ts +0 -15
- package/node_modules/engine.io-client/build/esm-debug/index.js +0 -15
- package/node_modules/engine.io-client/build/esm-debug/package.json +0 -10
- package/node_modules/engine.io-client/build/esm-debug/socket.d.ts +0 -482
- package/node_modules/engine.io-client/build/esm-debug/socket.js +0 -756
- package/node_modules/engine.io-client/build/esm-debug/transport.d.ts +0 -106
- package/node_modules/engine.io-client/build/esm-debug/transport.js +0 -145
- package/node_modules/engine.io-client/build/esm-debug/transports/index.d.ts +0 -8
- package/node_modules/engine.io-client/build/esm-debug/transports/index.js +0 -8
- package/node_modules/engine.io-client/build/esm-debug/transports/polling-fetch.d.ts +0 -15
- package/node_modules/engine.io-client/build/esm-debug/transports/polling-fetch.js +0 -56
- package/node_modules/engine.io-client/build/esm-debug/transports/polling-xhr.d.ts +0 -108
- package/node_modules/engine.io-client/build/esm-debug/transports/polling-xhr.js +0 -276
- package/node_modules/engine.io-client/build/esm-debug/transports/polling-xhr.node.d.ts +0 -11
- package/node_modules/engine.io-client/build/esm-debug/transports/polling-xhr.node.js +0 -17
- package/node_modules/engine.io-client/build/esm-debug/transports/polling.d.ts +0 -52
- package/node_modules/engine.io-client/build/esm-debug/transports/polling.js +0 -158
- package/node_modules/engine.io-client/build/esm-debug/transports/websocket.d.ts +0 -36
- package/node_modules/engine.io-client/build/esm-debug/transports/websocket.js +0 -128
- package/node_modules/engine.io-client/build/esm-debug/transports/websocket.node.d.ts +0 -14
- package/node_modules/engine.io-client/build/esm-debug/transports/websocket.node.js +0 -41
- package/node_modules/engine.io-client/build/esm-debug/transports/webtransport.d.ts +0 -18
- package/node_modules/engine.io-client/build/esm-debug/transports/webtransport.js +0 -87
- package/node_modules/engine.io-client/build/esm-debug/util.d.ts +0 -7
- package/node_modules/engine.io-client/build/esm-debug/util.js +0 -59
- package/node_modules/engine.io-client/dist/engine.io.esm.min.js +0 -7
- package/node_modules/engine.io-client/dist/engine.io.esm.min.js.map +0 -1
- package/node_modules/engine.io-client/dist/engine.io.js +0 -3064
- package/node_modules/engine.io-client/dist/engine.io.js.map +0 -1
- package/node_modules/engine.io-client/dist/engine.io.min.js +0 -7
- package/node_modules/engine.io-client/dist/engine.io.min.js.map +0 -1
- package/node_modules/engine.io-client/node_modules/ws/index.js +0 -13
- package/node_modules/engine.io-client/node_modules/ws/wrapper.mjs +0 -8
- package/node_modules/engine.io-client/package.json +0 -95
- package/node_modules/engine.io-parser/LICENSE +0 -22
- package/node_modules/engine.io-parser/Readme.md +0 -158
- package/node_modules/engine.io-parser/build/cjs/commons.d.ts +0 -14
- package/node_modules/engine.io-parser/build/cjs/commons.js +0 -19
- package/node_modules/engine.io-parser/build/cjs/contrib/base64-arraybuffer.d.ts +0 -2
- package/node_modules/engine.io-parser/build/cjs/contrib/base64-arraybuffer.js +0 -48
- package/node_modules/engine.io-parser/build/cjs/decodePacket.browser.d.ts +0 -2
- package/node_modules/engine.io-parser/build/cjs/decodePacket.browser.js +0 -66
- package/node_modules/engine.io-parser/build/cjs/decodePacket.d.ts +0 -2
- package/node_modules/engine.io-parser/build/cjs/decodePacket.js +0 -59
- package/node_modules/engine.io-parser/build/cjs/encodePacket.browser.d.ts +0 -4
- package/node_modules/engine.io-parser/build/cjs/encodePacket.browser.js +0 -72
- package/node_modules/engine.io-parser/build/cjs/encodePacket.d.ts +0 -3
- package/node_modules/engine.io-parser/build/cjs/encodePacket.js +0 -38
- package/node_modules/engine.io-parser/build/cjs/index.d.ts +0 -9
- package/node_modules/engine.io-parser/build/cjs/index.js +0 -164
- package/node_modules/engine.io-parser/build/cjs/package.json +0 -8
- package/node_modules/engine.io-parser/build/esm/commons.d.ts +0 -14
- package/node_modules/engine.io-parser/build/esm/commons.js +0 -14
- package/node_modules/engine.io-parser/build/esm/contrib/base64-arraybuffer.d.ts +0 -2
- package/node_modules/engine.io-parser/build/esm/contrib/base64-arraybuffer.js +0 -43
- package/node_modules/engine.io-parser/build/esm/decodePacket.browser.d.ts +0 -2
- package/node_modules/engine.io-parser/build/esm/decodePacket.browser.js +0 -62
- package/node_modules/engine.io-parser/build/esm/decodePacket.d.ts +0 -2
- package/node_modules/engine.io-parser/build/esm/decodePacket.js +0 -55
- package/node_modules/engine.io-parser/build/esm/encodePacket.browser.d.ts +0 -4
- package/node_modules/engine.io-parser/build/esm/encodePacket.browser.js +0 -68
- package/node_modules/engine.io-parser/build/esm/encodePacket.d.ts +0 -3
- package/node_modules/engine.io-parser/build/esm/encodePacket.js +0 -33
- package/node_modules/engine.io-parser/build/esm/index.d.ts +0 -9
- package/node_modules/engine.io-parser/build/esm/index.js +0 -156
- package/node_modules/engine.io-parser/build/esm/package.json +0 -8
- package/node_modules/engine.io-parser/package.json +0 -46
- package/node_modules/ms/index.js +0 -162
- package/node_modules/ms/license.md +0 -21
- package/node_modules/ms/package.json +0 -38
- package/node_modules/ms/readme.md +0 -59
- package/node_modules/socket.io-client/LICENSE +0 -21
- package/node_modules/socket.io-client/README.md +0 -29
- package/node_modules/socket.io-client/build/cjs/browser-entrypoint.d.ts +0 -2
- package/node_modules/socket.io-client/build/cjs/browser-entrypoint.js +0 -4
- package/node_modules/socket.io-client/build/cjs/contrib/backo2.d.ts +0 -12
- package/node_modules/socket.io-client/build/cjs/contrib/backo2.js +0 -69
- package/node_modules/socket.io-client/build/cjs/index.d.ts +0 -29
- package/node_modules/socket.io-client/build/cjs/index.js +0 -76
- package/node_modules/socket.io-client/build/cjs/manager.d.ts +0 -295
- package/node_modules/socket.io-client/build/cjs/manager.js +0 -416
- package/node_modules/socket.io-client/build/cjs/on.d.ts +0 -2
- package/node_modules/socket.io-client/build/cjs/on.js +0 -9
- package/node_modules/socket.io-client/build/cjs/socket.d.ts +0 -593
- package/node_modules/socket.io-client/build/cjs/socket.js +0 -909
- package/node_modules/socket.io-client/build/cjs/url.d.ts +0 -33
- package/node_modules/socket.io-client/build/cjs/url.js +0 -69
- package/node_modules/socket.io-client/build/esm/browser-entrypoint.d.ts +0 -2
- package/node_modules/socket.io-client/build/esm/browser-entrypoint.js +0 -2
- package/node_modules/socket.io-client/build/esm/contrib/backo2.d.ts +0 -12
- package/node_modules/socket.io-client/build/esm/contrib/backo2.js +0 -66
- package/node_modules/socket.io-client/build/esm/index.d.ts +0 -29
- package/node_modules/socket.io-client/build/esm/index.js +0 -58
- package/node_modules/socket.io-client/build/esm/manager.d.ts +0 -295
- package/node_modules/socket.io-client/build/esm/manager.js +0 -367
- package/node_modules/socket.io-client/build/esm/on.d.ts +0 -2
- package/node_modules/socket.io-client/build/esm/on.js +0 -6
- package/node_modules/socket.io-client/build/esm/package.json +0 -5
- package/node_modules/socket.io-client/build/esm/socket.d.ts +0 -593
- package/node_modules/socket.io-client/build/esm/socket.js +0 -880
- package/node_modules/socket.io-client/build/esm/url.d.ts +0 -33
- package/node_modules/socket.io-client/build/esm/url.js +0 -59
- package/node_modules/socket.io-client/build/esm-debug/browser-entrypoint.d.ts +0 -2
- package/node_modules/socket.io-client/build/esm-debug/browser-entrypoint.js +0 -2
- package/node_modules/socket.io-client/build/esm-debug/contrib/backo2.d.ts +0 -12
- package/node_modules/socket.io-client/build/esm-debug/contrib/backo2.js +0 -66
- package/node_modules/socket.io-client/build/esm-debug/index.d.ts +0 -29
- package/node_modules/socket.io-client/build/esm-debug/index.js +0 -62
- package/node_modules/socket.io-client/build/esm-debug/manager.d.ts +0 -295
- package/node_modules/socket.io-client/build/esm-debug/manager.js +0 -386
- package/node_modules/socket.io-client/build/esm-debug/on.d.ts +0 -2
- package/node_modules/socket.io-client/build/esm-debug/on.js +0 -6
- package/node_modules/socket.io-client/build/esm-debug/package.json +0 -5
- package/node_modules/socket.io-client/build/esm-debug/socket.d.ts +0 -593
- package/node_modules/socket.io-client/build/esm-debug/socket.js +0 -902
- package/node_modules/socket.io-client/build/esm-debug/url.d.ts +0 -33
- package/node_modules/socket.io-client/build/esm-debug/url.js +0 -63
- package/node_modules/socket.io-client/dist/socket.io.esm.min.js +0 -7
- package/node_modules/socket.io-client/dist/socket.io.esm.min.js.map +0 -1
- package/node_modules/socket.io-client/dist/socket.io.js +0 -4955
- package/node_modules/socket.io-client/dist/socket.io.js.map +0 -1
- package/node_modules/socket.io-client/dist/socket.io.min.js +0 -7
- package/node_modules/socket.io-client/dist/socket.io.min.js.map +0 -1
- package/node_modules/socket.io-client/dist/socket.io.msgpack.min.js +0 -7
- package/node_modules/socket.io-client/dist/socket.io.msgpack.min.js.map +0 -1
- package/node_modules/socket.io-client/package.json +0 -101
- package/node_modules/socket.io-parser/LICENSE +0 -20
- package/node_modules/socket.io-parser/Readme.md +0 -81
- package/node_modules/socket.io-parser/build/cjs/binary.d.ts +0 -20
- package/node_modules/socket.io-parser/build/cjs/binary.js +0 -87
- package/node_modules/socket.io-parser/build/cjs/index.d.ts +0 -101
- package/node_modules/socket.io-parser/build/cjs/index.js +0 -367
- package/node_modules/socket.io-parser/build/cjs/is-binary.d.ts +0 -7
- package/node_modules/socket.io-parser/build/cjs/is-binary.js +0 -54
- package/node_modules/socket.io-parser/build/cjs/package.json +0 -3
- package/node_modules/socket.io-parser/build/esm/binary.d.ts +0 -20
- package/node_modules/socket.io-parser/build/esm/binary.js +0 -83
- package/node_modules/socket.io-parser/build/esm/index.d.ts +0 -101
- package/node_modules/socket.io-parser/build/esm/index.js +0 -356
- package/node_modules/socket.io-parser/build/esm/is-binary.d.ts +0 -7
- package/node_modules/socket.io-parser/build/esm/is-binary.js +0 -50
- package/node_modules/socket.io-parser/build/esm/package.json +0 -3
- package/node_modules/socket.io-parser/build/esm-debug/binary.d.ts +0 -20
- package/node_modules/socket.io-parser/build/esm-debug/binary.js +0 -83
- package/node_modules/socket.io-parser/build/esm-debug/index.d.ts +0 -101
- package/node_modules/socket.io-parser/build/esm-debug/index.js +0 -361
- package/node_modules/socket.io-parser/build/esm-debug/is-binary.d.ts +0 -7
- package/node_modules/socket.io-parser/build/esm-debug/is-binary.js +0 -50
- package/node_modules/socket.io-parser/build/esm-debug/package.json +0 -3
- package/node_modules/socket.io-parser/package.json +0 -44
- package/node_modules/xmlhttprequest-ssl/LICENSE +0 -22
- package/node_modules/xmlhttprequest-ssl/README.md +0 -67
- package/node_modules/xmlhttprequest-ssl/lib/XMLHttpRequest.js +0 -689
- package/node_modules/xmlhttprequest-ssl/package.json +0 -40
- /package/node_modules/{engine.io-client/node_modules/ws → ws}/LICENSE +0 -0
- /package/node_modules/{engine.io-client/node_modules/ws → ws}/README.md +0 -0
- /package/node_modules/{engine.io-client/node_modules/ws → ws}/browser.js +0 -0
- /package/node_modules/{engine.io-client/node_modules/ws → ws}/lib/buffer-util.js +0 -0
- /package/node_modules/{engine.io-client/node_modules/ws → ws}/lib/event-target.js +0 -0
- /package/node_modules/{engine.io-client/node_modules/ws → ws}/lib/extension.js +0 -0
- /package/node_modules/{engine.io-client/node_modules/ws → ws}/lib/limiter.js +0 -0
- /package/node_modules/{engine.io-client/node_modules/ws → ws}/lib/receiver.js +0 -0
- /package/node_modules/{engine.io-client/node_modules/ws → ws}/lib/sender.js +0 -0
- /package/node_modules/{engine.io-client/node_modules/ws → ws}/lib/stream.js +0 -0
- /package/node_modules/{engine.io-client/node_modules/ws → ws}/lib/subprotocol.js +0 -0
- /package/node_modules/{engine.io-client/node_modules/ws → ws}/lib/validation.js +0 -0
package/dist/src/inbound.js
CHANGED
|
@@ -1,340 +1,274 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* LightClaw — 入站消息处理
|
|
3
3
|
*
|
|
4
|
-
* 接收用户消息 → 文件处理 → 路由 → AI 分发 →
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
import { generateMsgId } from "./dedup.js";
|
|
10
|
-
import { parseDataUrl, formatFileSize, mediaUrlsToFiles } from "./media.js";
|
|
11
|
-
import { uploadFileToCos, downloadFileFromCos, getFileDownloadUrl } from "./file-storage.js";
|
|
12
|
-
/**
|
|
13
|
-
* 创建入站消息处理器
|
|
4
|
+
* 接收用户消息 → 文件处理 → 路由 → AI 分发 → 回复。
|
|
5
|
+
*
|
|
6
|
+
* 并发/abort 完全委托给 openclaw:
|
|
7
|
+
* - 并发由 session 写锁 + followup queue 保证;
|
|
8
|
+
* - /stop 及自然语言 abort 由 tryFastAbortFromMessage 统一处理并递归 kill subagent。
|
|
14
9
|
*/
|
|
10
|
+
import { emitSignal } from './types.js';
|
|
11
|
+
import { CHANNEL_KEY, MEDIA_MAX_BYTES, resolveEffectiveApiKey, setSessionApiKey, DEFAULT_AGENT_ID } from './config.js';
|
|
12
|
+
import { getLightclawRuntime } from './runtime.js';
|
|
13
|
+
import { createChannelReplyPipeline } from 'openclaw/plugin-sdk/channel-reply-pipeline';
|
|
14
|
+
import { generateMsgId } from './dedup.js';
|
|
15
|
+
import { parseDataUrl, formatFileSize } from './media.js';
|
|
16
|
+
import { uploadFileToCos, downloadFileFromCos, getFileDownloadUrl } from './file-storage.js';
|
|
17
|
+
import { createStreamReplyConfig } from './streaming/index.js';
|
|
15
18
|
export function createInboundHandler(account, emitter, log) {
|
|
16
19
|
return async (msg) => {
|
|
17
|
-
|
|
20
|
+
// mas: {"senderId":"100013456706","text":"今天天气怎么样","messageId":"91647ae9-c123-48e4-9d80-26f2e9a91ac9","files":[],"timestamp":1776077511044}
|
|
21
|
+
const pluginRuntime = getLightclawRuntime();
|
|
22
|
+
// 每次处理消息时重新加载配置,确保使用最新的运行时配置(支持热更新)
|
|
18
23
|
const currentCfg = pluginRuntime.config.loadConfig();
|
|
19
|
-
// 根据 senderId
|
|
24
|
+
// 根据 senderId(= uin)选择对应的 apiKey:
|
|
25
|
+
// - 多 key 模式:按 uin→apiKey 映射表查找,实现不同用户使用不同 key
|
|
26
|
+
// - 单 key 模式:映射表为空,fallback 到账户主 key
|
|
20
27
|
const effectiveApiKey = resolveEffectiveApiKey({ senderId: msg.senderId });
|
|
21
28
|
log?.info(`[${CHANNEL_KEY}] Effective API key for uin ${msg.senderId}: ${effectiveApiKey.slice(0, 8)}...`);
|
|
22
|
-
// 1
|
|
23
|
-
// 使用标准 user: 前缀,与 normalizeTarget
|
|
29
|
+
// ---- 步骤 1:确定地址和会话 Key ----
|
|
30
|
+
// 使用标准 user: 前缀,与 normalizeTarget 输出格式保持一致,
|
|
31
|
+
// 确保框架路由系统能正确识别 peer kind 为 "direct"
|
|
24
32
|
const fromAddress = `user:${msg.senderId}`;
|
|
25
|
-
// 2
|
|
26
|
-
|
|
33
|
+
// ---- 步骤 2:路由解析 ----
|
|
34
|
+
// 根据 channel + accountId + peer 三元组确定:
|
|
35
|
+
// - agentId : 处理此消息的 Agent ID
|
|
36
|
+
// - sessionKey : per-channel-peer 会话键(用于隔离不同用户的会话历史)
|
|
37
|
+
// - accountId : 实际使用的账户 ID(可能被路由规则覆盖)
|
|
38
|
+
// agentId 合法性校验:防止前端传入任意 agentId 访问其他 Agent 的数据
|
|
39
|
+
const validAgentIds = currentCfg.agents?.list?.map((a) => a.id) ?? [DEFAULT_AGENT_ID];
|
|
40
|
+
const resolvedAgentId = msg.agentId && validAgentIds.includes(msg.agentId) ? msg.agentId : DEFAULT_AGENT_ID; // undefined 时框架自动路由到默认 Agent
|
|
41
|
+
const baseRoute = pluginRuntime.channel.routing.resolveAgentRoute({
|
|
27
42
|
cfg: currentCfg,
|
|
28
43
|
channel: CHANNEL_KEY,
|
|
29
44
|
accountId: account.accountId,
|
|
30
|
-
peer: { kind:
|
|
45
|
+
peer: { kind: 'direct', id: msg.senderId },
|
|
31
46
|
});
|
|
32
|
-
//
|
|
47
|
+
// route: {"agentId":"main","channel":"lightclawbot","accountId":"default","sessionKey":"agent:main:lightclawbot:direct:100013456706","mainSessionKey":"agent:main:main","lastRoutePolicy":"session","matchedBy":"default"}
|
|
48
|
+
// 若前端指定了合法的 agentId,则用 buildAgentSessionKey 覆盖 sessionKey 和 agentId,
|
|
49
|
+
// 实现 Agent 间隔离(sessionKey 含 agentId,不同 Agent 的会话历史完全独立)
|
|
50
|
+
const route = resolvedAgentId
|
|
51
|
+
? {
|
|
52
|
+
...baseRoute,
|
|
53
|
+
agentId: resolvedAgentId,
|
|
54
|
+
sessionKey: pluginRuntime.channel.routing.buildAgentSessionKey({
|
|
55
|
+
agentId: resolvedAgentId,
|
|
56
|
+
channel: CHANNEL_KEY,
|
|
57
|
+
accountId: baseRoute.accountId,
|
|
58
|
+
peer: { kind: 'direct', id: msg.senderId },
|
|
59
|
+
dmScope: 'per-channel-peer',
|
|
60
|
+
}),
|
|
61
|
+
mainSessionKey: `agent:${resolvedAgentId}:main`,
|
|
62
|
+
}
|
|
63
|
+
: baseRoute;
|
|
64
|
+
log?.info(`[CHANNEL_KEY]: route= ${JSON.stringify(route)}`);
|
|
65
|
+
// ---- 步骤 3:权限检查 ----
|
|
66
|
+
// 根据 allowFrom 白名单和 dmPolicy 策略决定是否允许此用户发送命令
|
|
33
67
|
const commandAuthorized = checkAuth(account.allowFrom, account.dmPolicy, msg.senderId);
|
|
34
|
-
// 3.5
|
|
35
|
-
//
|
|
36
|
-
//
|
|
37
|
-
//
|
|
68
|
+
// ---- 步骤 3.5:记录 sessionKey → apiKey 映射 ----
|
|
69
|
+
// 目的:tool 执行时通过 ctx.sessionKey 直接查找对应的 apiKey,
|
|
70
|
+
// 避免在 tool 层再次解析 uin。
|
|
71
|
+
// 重要:只写入 per-channel-peer 的 sessionKey,不写入 mainSessionKey。
|
|
72
|
+
// mainSessionKey(= "agent:main:main")是全局共享的,
|
|
73
|
+
// 若写入则最后一个用户的 apiKey 会覆盖前一个用户,产生并发安全问题。
|
|
38
74
|
if (route?.sessionKey) {
|
|
39
75
|
setSessionApiKey(route.sessionKey, effectiveApiKey);
|
|
40
76
|
}
|
|
41
|
-
|
|
77
|
+
const targetId = msg.senderId;
|
|
78
|
+
// 2. 提前发 typing_start(作为"已读回执",减少 COS 下载/LLM TTFT 期间的无反馈感)
|
|
79
|
+
const replyMsgId = generateMsgId();
|
|
80
|
+
// 将 route.agentId 作为整条消息处理链路的绑定默认值,所有出站消息均携带此 agentId
|
|
81
|
+
const effectiveAgentId = route.agentId ?? resolvedAgentId ?? DEFAULT_AGENT_ID;
|
|
82
|
+
// 基于上层 gateway 的 emitter,构造一个绑定当前 agentId 的包装 emitter
|
|
83
|
+
// 所有调用 emit / sendReply / sendFiles 未显式传 agentId 时,消息体都会自动注入 effectiveAgentId
|
|
84
|
+
const boundEmitter = {
|
|
85
|
+
botClientId: emitter.botClientId,
|
|
86
|
+
agentId: effectiveAgentId,
|
|
87
|
+
emit: (data) => emitter.emit({ ...data, agentId: data.agentId ?? effectiveAgentId }),
|
|
88
|
+
sendReply: (tid, text, replyTo, agentId) => emitter.sendReply(tid, text, replyTo, agentId ?? effectiveAgentId),
|
|
89
|
+
sendFiles: (tid, text, files, replyTo, agentId) => emitter.sendFiles(tid, text, files, replyTo, agentId ?? effectiveAgentId),
|
|
90
|
+
};
|
|
91
|
+
const signalCtx = {
|
|
92
|
+
emitter: boundEmitter,
|
|
93
|
+
targetId,
|
|
94
|
+
replyMsgId,
|
|
95
|
+
originalMsgId: msg.messageId,
|
|
96
|
+
agentId: effectiveAgentId,
|
|
97
|
+
};
|
|
98
|
+
emitSignal(signalCtx, 'typing_start');
|
|
99
|
+
// 3. 处理文件附件(files[] → 本地存储 + 公网 URL)
|
|
42
100
|
const localMediaPaths = [];
|
|
101
|
+
/** 本地文件 MIME 类型列表,与 localMediaPaths 一一对应 */
|
|
43
102
|
const localMediaTypes = [];
|
|
44
|
-
// 每个文件对应的公网可访问 URL,用于 session 历史持久化
|
|
45
103
|
const publicMediaUrls = [];
|
|
104
|
+
/** 传递给 AI 上下文的附件列表(name + mimeType + 公网 URL) */
|
|
46
105
|
const ctxAttachments = [];
|
|
47
|
-
|
|
106
|
+
/** 附加到用户消息末尾的文件描述文本(告知 AI 用户发送了哪些文件) */
|
|
107
|
+
let attachmentDescription = '';
|
|
48
108
|
for (const file of msg.files) {
|
|
49
109
|
try {
|
|
50
110
|
let buffer;
|
|
51
111
|
let mimeType;
|
|
52
|
-
// 记录文件的公网 URL,优先用于 session 存储
|
|
53
112
|
let cosPublicUrl;
|
|
54
113
|
const parsed = file.bytes ? parseDataUrl(file.bytes) : null;
|
|
55
114
|
if (parsed) {
|
|
56
|
-
// data URL 格式:直接解析
|
|
57
115
|
buffer = parsed.buffer;
|
|
58
116
|
mimeType = parsed.mimeType;
|
|
59
117
|
}
|
|
60
118
|
else if (file.uri) {
|
|
61
|
-
// 远程 URI(下载地址),下载获取内容
|
|
62
119
|
log?.info(`[${CHANNEL_KEY}] File has URI, downloading from cloud: ${file.uri}`);
|
|
63
120
|
const downloaded = await downloadFileFromCos(file.uri, { apiKey: effectiveApiKey });
|
|
64
121
|
buffer = downloaded.buffer;
|
|
65
122
|
mimeType = file.mimeType;
|
|
66
|
-
|
|
67
|
-
cosPublicUrl = file.uri.startsWith("http")
|
|
68
|
-
? file.uri
|
|
69
|
-
: getFileDownloadUrl(file.uri);
|
|
123
|
+
cosPublicUrl = file.uri.startsWith('http') ? file.uri : getFileDownloadUrl(file.uri);
|
|
70
124
|
}
|
|
71
125
|
else {
|
|
126
|
+
// 来源 3:既无 bytes 也无 uri,无法处理,跳过此文件
|
|
72
127
|
log?.warn(`[${CHANNEL_KEY}] File has no bytes or uri: ${file.name}, skipping`);
|
|
73
128
|
continue;
|
|
74
129
|
}
|
|
75
|
-
|
|
130
|
+
// 将文件内容保存到本地媒体存储(框架统一管理,支持大小限制和格式校验)
|
|
131
|
+
const saved = await pluginRuntime.channel.media.saveMediaBuffer(buffer, mimeType, 'inbound', MEDIA_MAX_BYTES, file.name);
|
|
76
132
|
localMediaPaths.push(saved.path);
|
|
77
133
|
localMediaTypes.push(mimeType);
|
|
78
|
-
// 如果文件来自云端,使用公网 URL;否则尝试上传获取公网 URL
|
|
79
134
|
if (cosPublicUrl) {
|
|
80
135
|
publicMediaUrls.push(cosPublicUrl);
|
|
81
136
|
}
|
|
82
137
|
else {
|
|
83
|
-
// data URL
|
|
138
|
+
// data URL 来源:上传到 COS 获取公网 URL,失败则 fallback 到本地路径
|
|
84
139
|
try {
|
|
85
140
|
const uploadResult = await uploadFileToCos(saved.path, { apiKey: effectiveApiKey });
|
|
86
141
|
publicMediaUrls.push(uploadResult.url || `file://${saved.path}`);
|
|
87
|
-
log?.info(`[${CHANNEL_KEY}] Uploaded inbound file
|
|
142
|
+
log?.info(`[${CHANNEL_KEY}] Uploaded inbound file: ${saved.path} → ${uploadResult.url}`);
|
|
88
143
|
}
|
|
89
144
|
catch (uploadErr) {
|
|
90
|
-
log?.warn(`[${CHANNEL_KEY}]
|
|
145
|
+
log?.warn(`[${CHANNEL_KEY}] Upload failed, falling back to local path: ${uploadErr}`);
|
|
91
146
|
publicMediaUrls.push(`file://${saved.path}`);
|
|
92
147
|
}
|
|
93
148
|
}
|
|
94
|
-
// Attachments 中使用公网 URL,确保 session 历史中的地址可被前端访问
|
|
95
149
|
const attachmentUrl = publicMediaUrls[publicMediaUrls.length - 1];
|
|
96
|
-
ctxAttachments.push({
|
|
97
|
-
name: file.name,
|
|
98
|
-
mimeType,
|
|
99
|
-
url: attachmentUrl,
|
|
100
|
-
});
|
|
150
|
+
ctxAttachments.push({ name: file.name, mimeType, url: attachmentUrl });
|
|
101
151
|
attachmentDescription += `\n用户发送了文件: ${file.name} (${formatFileSize(saved.size)})`;
|
|
102
|
-
log?.info(`[${CHANNEL_KEY}] File saved: ${saved.path} (${mimeType}, ${formatFileSize(saved.size)})
|
|
152
|
+
log?.info(`[${CHANNEL_KEY}] File saved: ${saved.path} (${mimeType}, ${formatFileSize(saved.size)})`);
|
|
103
153
|
}
|
|
104
154
|
catch (err) {
|
|
155
|
+
// 单个文件处理失败不影响整条消息的处理,记录错误后继续
|
|
105
156
|
log?.error(`[${CHANNEL_KEY}] File processing failed for ${file.name}: ${err}`);
|
|
106
157
|
}
|
|
107
158
|
}
|
|
108
|
-
//
|
|
159
|
+
// 4. 构建 AI 上下文
|
|
109
160
|
const userText = msg.text + attachmentDescription;
|
|
110
|
-
const agentBody = account.systemPrompt
|
|
111
|
-
|
|
112
|
-
: userText;
|
|
113
|
-
// 6. 构建入站上下文
|
|
114
|
-
// MediaPaths 保持本地路径(AI 模型 vision 需要从本地读取文件内容)
|
|
115
|
-
// MediaUrls 使用公网 URL(session 历史持久化,前端可直接访问)
|
|
161
|
+
const agentBody = account.systemPrompt ? `${account.systemPrompt}\n\n${userText}` : userText;
|
|
162
|
+
// MediaPaths 保留本地路径(vision 模型需读本地文件);MediaUrls 用公网 URL(session 持久化)
|
|
116
163
|
const mediaFields = {};
|
|
117
164
|
if (localMediaPaths.length > 0) {
|
|
118
|
-
mediaFields.MediaPaths = localMediaPaths;
|
|
119
|
-
mediaFields.MediaPath = localMediaPaths[0];
|
|
120
|
-
mediaFields.MediaTypes = localMediaTypes;
|
|
121
|
-
mediaFields.MediaType = localMediaTypes[0];
|
|
122
|
-
mediaFields.MediaUrls = publicMediaUrls;
|
|
123
|
-
mediaFields.MediaUrl = publicMediaUrls[0];
|
|
165
|
+
mediaFields.MediaPaths = localMediaPaths; // 所有本地路径(数组)
|
|
166
|
+
mediaFields.MediaPath = localMediaPaths[0]; // 第一个本地路径(兼容单文件场景)
|
|
167
|
+
mediaFields.MediaTypes = localMediaTypes; // 所有 MIME 类型(数组)
|
|
168
|
+
mediaFields.MediaType = localMediaTypes[0]; // 第一个 MIME 类型
|
|
169
|
+
mediaFields.MediaUrls = publicMediaUrls; // 所有公网 URL(数组)
|
|
170
|
+
mediaFields.MediaUrl = publicMediaUrls[0]; // 第一个公网 URL
|
|
124
171
|
}
|
|
172
|
+
// finalizeInboundContext 负责将原始字段规范化为框架标准的 InboundContext 格式
|
|
125
173
|
const ctxPayload = pluginRuntime.channel.reply.finalizeInboundContext({
|
|
126
|
-
Body: userText,
|
|
127
|
-
BodyForAgent: agentBody,
|
|
128
|
-
RawBody: msg.text,
|
|
129
|
-
CommandBody: msg.text,
|
|
130
|
-
From: fromAddress,
|
|
131
|
-
To: `${CHANNEL_KEY}:${account.accountId}`,
|
|
174
|
+
Body: userText, // 传给 AI 的用户消息(含文件描述)
|
|
175
|
+
BodyForAgent: agentBody, // 传给 Agent 的完整 body(含 systemPrompt)
|
|
176
|
+
RawBody: msg.text, // 用户原始文本(不含文件描述)
|
|
177
|
+
CommandBody: msg.text, // 命令解析用的原始文本
|
|
178
|
+
From: fromAddress, // 发送方地址(user:<uin>)
|
|
179
|
+
To: `${CHANNEL_KEY}:${account.accountId}`, // 接收方地址(通道:账户)
|
|
132
180
|
Channel: CHANNEL_KEY,
|
|
133
|
-
ChatType:
|
|
134
|
-
SessionKey: route?.sessionKey ?? fromAddress,
|
|
135
|
-
AccountId: route?.accountId ?? account.accountId,
|
|
136
|
-
SenderId: msg.senderId,
|
|
137
|
-
SenderName: msg.senderId,
|
|
181
|
+
ChatType: 'direct', // 私聊
|
|
182
|
+
SessionKey: route?.sessionKey ?? fromAddress, // 会话键(优先用路由解析结果)
|
|
183
|
+
AccountId: route?.accountId ?? account.accountId, // 账户 ID(路由可能覆盖)
|
|
184
|
+
SenderId: msg.senderId, // 发送方 uin
|
|
185
|
+
SenderName: msg.senderId, // 发送方显示名(暂用 uin 代替)
|
|
138
186
|
Provider: CHANNEL_KEY,
|
|
139
187
|
Surface: CHANNEL_KEY,
|
|
140
|
-
MessageSid: msg.messageId,
|
|
188
|
+
MessageSid: msg.messageId, // 原始消息 ID(用于回复引用)
|
|
141
189
|
Timestamp: msg.timestamp,
|
|
142
190
|
OriginatingChannel: CHANNEL_KEY,
|
|
143
191
|
OriginatingTo: fromAddress,
|
|
144
|
-
CommandAuthorized: commandAuthorized,
|
|
192
|
+
CommandAuthorized: commandAuthorized, // 是否有权限执行命令
|
|
193
|
+
// 有权限时,将发送方加入 OwnerAllowFrom,使其可以访问 owner 级别的命令
|
|
145
194
|
OwnerAllowFrom: commandAuthorized ? [msg.senderId, fromAddress] : undefined,
|
|
146
195
|
AgentId: route?.agentId,
|
|
147
196
|
Attachments: ctxAttachments.length > 0 ? ctxAttachments : undefined,
|
|
148
197
|
...mediaFields,
|
|
149
198
|
});
|
|
150
199
|
log?.info(`[${CHANNEL_KEY}] Inbound context: ${JSON.stringify(ctxPayload)}`);
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
//
|
|
200
|
+
log?.info(`[${CHANNEL_KEY}] Processing: from=${msg.senderId} text="${(msg.text || '(仅文件)').slice(0, 60)}" files=${msg.files.length}`);
|
|
201
|
+
// ---- 步骤 6.5:更新 session 的 last route ----
|
|
202
|
+
// 目的:使 cron 定时任务能找到 lightclawbot 的投递目标(deliveryContext),
|
|
203
|
+
// 从而在没有用户消息触发的情况下也能主动推送消息。
|
|
154
204
|
const storePath = pluginRuntime.channel.session.resolveStorePath(route.agentId);
|
|
155
205
|
const deliveryCtx = {
|
|
156
206
|
channel: CHANNEL_KEY,
|
|
157
207
|
to: fromAddress,
|
|
158
208
|
accountId: route.accountId ?? account.accountId,
|
|
159
209
|
};
|
|
160
|
-
// 写入 per-channel-peer session
|
|
210
|
+
// 写入 per-channel-peer session(精确匹配当前用户的会话)
|
|
161
211
|
if (route?.sessionKey) {
|
|
162
|
-
pluginRuntime.channel.session
|
|
212
|
+
pluginRuntime.channel.session
|
|
213
|
+
.updateLastRoute({
|
|
163
214
|
storePath,
|
|
164
215
|
sessionKey: route.sessionKey,
|
|
165
216
|
deliveryContext: deliveryCtx,
|
|
166
|
-
})
|
|
167
|
-
log?.error(`[${CHANNEL_KEY}]
|
|
168
|
-
});
|
|
217
|
+
})
|
|
218
|
+
.catch((err) => log?.error(`[${CHANNEL_KEY}] updateLastRoute(session) failed: ${err}`));
|
|
169
219
|
}
|
|
170
|
-
// 写入 main session
|
|
220
|
+
// 写入 main session(兜底,确保全局 cron 也能找到投递目标)
|
|
221
|
+
// 仅当 mainSessionKey 与 sessionKey 不同时才写入,避免重复写入
|
|
171
222
|
if (route?.mainSessionKey && route.mainSessionKey !== route.sessionKey) {
|
|
172
|
-
pluginRuntime.channel.session
|
|
223
|
+
pluginRuntime.channel.session
|
|
224
|
+
.updateLastRoute({
|
|
173
225
|
storePath,
|
|
174
226
|
sessionKey: route.mainSessionKey,
|
|
175
227
|
deliveryContext: deliveryCtx,
|
|
176
|
-
})
|
|
177
|
-
log?.error(`[${CHANNEL_KEY}]
|
|
178
|
-
});
|
|
228
|
+
})
|
|
229
|
+
.catch((err) => log?.error(`[${CHANNEL_KEY}] updateLastRoute(main) failed: ${err}`));
|
|
179
230
|
}
|
|
180
|
-
// 7
|
|
231
|
+
// ---- 步骤 7:创建 replyPrefixOptions ----
|
|
232
|
+
// createChannelReplyPipeline 返回:
|
|
233
|
+
// - onModelSelected : 模型选择回调(用于 replyOptions)
|
|
234
|
+
// - typingCallbacks : 打字状态回调(此处不使用,用 _tc 忽略)
|
|
235
|
+
// - ...prefixOptions : 传给 dispatcherOptions 的前缀配置(含 prefix、suffix 等)
|
|
181
236
|
const { onModelSelected, typingCallbacks: _tc, ...prefixOptions } = createChannelReplyPipeline({
|
|
182
237
|
cfg: currentCfg,
|
|
183
238
|
agentId: route.agentId,
|
|
184
239
|
channel: CHANNEL_KEY,
|
|
185
240
|
accountId: account.accountId,
|
|
186
241
|
});
|
|
187
|
-
//
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
//
|
|
200
|
-
const replyMsgId = generateMsgId();
|
|
201
|
-
const dispatchPromise = pluginRuntime.channel.reply.dispatchReplyWithBufferedBlockDispatcher({
|
|
202
|
-
ctx: ctxPayload,
|
|
203
|
-
cfg: currentCfg,
|
|
204
|
-
dispatcherOptions: {
|
|
205
|
-
...prefixOptions,
|
|
206
|
-
deliver: async (payload, info) => {
|
|
207
|
-
hasResponse = true;
|
|
208
|
-
log?.info(`[${CHANNEL_KEY}] Deliver: ${JSON.stringify(payload)}。info: ${JSON.stringify(info)}`);
|
|
209
|
-
if (timeoutId) {
|
|
210
|
-
clearTimeout(timeoutId);
|
|
211
|
-
timeoutId = null;
|
|
212
|
-
}
|
|
213
|
-
const replyText = payload.text ?? payload.body ?? "";
|
|
214
|
-
const mediaList = payload.mediaUrls?.length
|
|
215
|
-
? payload.mediaUrls
|
|
216
|
-
: payload.mediaUrl ? [payload.mediaUrl] : [];
|
|
217
|
-
// 流式中间块
|
|
218
|
-
if (info.kind === "block") {
|
|
219
|
-
if (replyText.trim()) {
|
|
220
|
-
emitter.emit({
|
|
221
|
-
msgId: replyMsgId,
|
|
222
|
-
from: emitter.botClientId,
|
|
223
|
-
to: targetId,
|
|
224
|
-
content: replyText,
|
|
225
|
-
timestamp: Date.now(),
|
|
226
|
-
replyToMsgId: msg.messageId,
|
|
227
|
-
kind: "stream_chunk",
|
|
228
|
-
});
|
|
229
|
-
}
|
|
230
|
-
return;
|
|
231
|
-
}
|
|
232
|
-
if (!replyText && !mediaList.length)
|
|
233
|
-
return;
|
|
234
|
-
// 发送媒体文件 — 同时上传到云端获取公网 URL
|
|
235
|
-
if (mediaList.length > 0) {
|
|
236
|
-
const files = await mediaUrlsToFiles(mediaList, log);
|
|
237
|
-
// 尝试将文件上传获取公网链接
|
|
238
|
-
const publicUrls = [];
|
|
239
|
-
const storageConfig = {
|
|
240
|
-
apiKey: effectiveApiKey,
|
|
241
|
-
};
|
|
242
|
-
for (const mediaUrl of mediaList) {
|
|
243
|
-
try {
|
|
244
|
-
// 本地文件路径(file:// 或绝对路径)
|
|
245
|
-
const localPath = mediaUrl.startsWith("file://")
|
|
246
|
-
? mediaUrl.slice(7)
|
|
247
|
-
: mediaUrl;
|
|
248
|
-
if (localPath.startsWith("/") || localPath.match(/^[A-Za-z]:\\/)) {
|
|
249
|
-
const { existsSync } = await import("node:fs");
|
|
250
|
-
if (existsSync(localPath)) {
|
|
251
|
-
const result = await uploadFileToCos(localPath, storageConfig);
|
|
252
|
-
publicUrls.push(result.url || '');
|
|
253
|
-
log?.info(`[${CHANNEL_KEY}] Uploaded to cloud: ${localPath} → ${result.url}`);
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
catch (uploadErr) {
|
|
258
|
-
log?.warn(`[${CHANNEL_KEY}] Cloud upload failed for ${mediaUrl}: ${uploadErr}`);
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
// 将公网 URL 追加到回复文本中(Markdown 链接格式)
|
|
262
|
-
let enrichedText = replyText;
|
|
263
|
-
if (publicUrls.length > 0) {
|
|
264
|
-
const urlSection = publicUrls
|
|
265
|
-
.map((url, i) => {
|
|
266
|
-
// 从 URL 中提取文件名
|
|
267
|
-
const match = url.match(/filePath=([^&]+)/);
|
|
268
|
-
const filePath = match ? decodeURIComponent(match[1]) : "";
|
|
269
|
-
const fileName = filePath.split("/").pop() || `file${publicUrls.length > 1 ? ` (${i + 1})` : ""}`;
|
|
270
|
-
return `📎 [${fileName}](${url})`;
|
|
271
|
-
})
|
|
272
|
-
.join("\n");
|
|
273
|
-
enrichedText = enrichedText
|
|
274
|
-
? `${enrichedText}\n\n${urlSection}`
|
|
275
|
-
: urlSection;
|
|
276
|
-
}
|
|
277
|
-
if (files.length > 0) {
|
|
278
|
-
emitter.sendFiles(targetId, enrichedText, files, msg.messageId);
|
|
279
|
-
return;
|
|
280
|
-
}
|
|
281
|
-
// 文件无法直接发送,但有公网 URL,用文本方式发送链接
|
|
282
|
-
if (enrichedText.trim()) {
|
|
283
|
-
emitter.sendReply(targetId, enrichedText, msg.messageId);
|
|
284
|
-
return;
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
// 发送文本回复
|
|
288
|
-
if (replyText.trim()) {
|
|
289
|
-
emitter.sendReply(targetId, replyText, msg.messageId);
|
|
290
|
-
}
|
|
291
|
-
},
|
|
292
|
-
onReplyStart: () => {
|
|
293
|
-
emitter.emit({
|
|
294
|
-
msgId: replyMsgId,
|
|
295
|
-
from: emitter.botClientId,
|
|
296
|
-
to: targetId,
|
|
297
|
-
content: "",
|
|
298
|
-
timestamp: Date.now(),
|
|
299
|
-
kind: "typing_start",
|
|
300
|
-
});
|
|
301
|
-
},
|
|
302
|
-
onIdle: () => {
|
|
303
|
-
if (idleSent)
|
|
304
|
-
return;
|
|
305
|
-
idleSent = true;
|
|
306
|
-
emitter.emit({
|
|
307
|
-
msgId: replyMsgId,
|
|
308
|
-
from: emitter.botClientId,
|
|
309
|
-
to: targetId,
|
|
310
|
-
content: "",
|
|
311
|
-
timestamp: Date.now(),
|
|
312
|
-
replyToMsgId: msg.messageId,
|
|
313
|
-
kind: "typing_stop",
|
|
314
|
-
});
|
|
315
|
-
},
|
|
316
|
-
onError: (err, info) => {
|
|
317
|
-
log?.error(`[${CHANNEL_KEY}] ${info.kind} reply failed: ${String(err)}`);
|
|
318
|
-
},
|
|
319
|
-
},
|
|
320
|
-
replyOptions: { onModelSelected, disableBlockStreaming: false },
|
|
321
|
-
});
|
|
242
|
+
// 7. 构建流式 dispatcher
|
|
243
|
+
const { dispatcher, replyOptions: streamReplyOptions, hasEmittedContent, } = createStreamReplyConfig({
|
|
244
|
+
emitter: boundEmitter,
|
|
245
|
+
targetId,
|
|
246
|
+
replyMsgId,
|
|
247
|
+
originalMsgId: msg.messageId,
|
|
248
|
+
log,
|
|
249
|
+
effectiveApiKey,
|
|
250
|
+
typingAlreadyStarted: true,
|
|
251
|
+
agentId: effectiveAgentId,
|
|
252
|
+
}, { ...prefixOptions, onModelSelected }, signalCtx);
|
|
253
|
+
// 8. 分发给 AI 引擎(真流式)。abort 由 openclaw fast-abort 处理,sink 层
|
|
254
|
+
// 把英文回执汉化;此处仅兜底自身抛错。
|
|
322
255
|
try {
|
|
323
|
-
await
|
|
256
|
+
await pluginRuntime.channel.reply.withReplyDispatcher({
|
|
257
|
+
dispatcher,
|
|
258
|
+
run: () => pluginRuntime.channel.reply.dispatchReplyFromConfig({
|
|
259
|
+
ctx: ctxPayload,
|
|
260
|
+
cfg: currentCfg,
|
|
261
|
+
dispatcher,
|
|
262
|
+
replyOptions: streamReplyOptions,
|
|
263
|
+
}),
|
|
264
|
+
});
|
|
324
265
|
}
|
|
325
266
|
catch (err) {
|
|
326
267
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
327
268
|
log?.error(`[${CHANNEL_KEY}] Dispatch error: ${errMsg}`);
|
|
328
|
-
//
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
finally {
|
|
332
|
-
if (timeoutId) {
|
|
333
|
-
clearTimeout(timeoutId);
|
|
334
|
-
timeoutId = null;
|
|
335
|
-
}
|
|
336
|
-
if (timeoutFired) {
|
|
337
|
-
log?.info(`[${CHANNEL_KEY}] Note: dispatch completed after timeout warning (${hasResponse ? 'with' : 'without'} response)`);
|
|
269
|
+
// 已推过可见内容时不再追加错误文案,避免打断阅读。
|
|
270
|
+
if (!hasEmittedContent()) {
|
|
271
|
+
emitter.sendReply(targetId, '抱歉,处理您的消息时出现了问题,请稍后重试', msg.messageId, effectiveAgentId);
|
|
338
272
|
}
|
|
339
273
|
}
|
|
340
274
|
};
|
|
@@ -342,13 +276,28 @@ export function createInboundHandler(account, emitter, log) {
|
|
|
342
276
|
// ============================================================
|
|
343
277
|
// 权限检查
|
|
344
278
|
// ============================================================
|
|
279
|
+
/**
|
|
280
|
+
* 检查发送方是否有权限向 Bot 发送消息(命令授权检查)。
|
|
281
|
+
*
|
|
282
|
+
* 策略优先级(从高到低):
|
|
283
|
+
* 1. `dmPolicy === "disabled"` → 拒绝所有消息(Bot 已关闭私聊)
|
|
284
|
+
* 2. `dmPolicy === "open"` → 允许所有消息(Bot 对所有人开放)
|
|
285
|
+
* 3. `allowFrom` 为空 → 拒绝(未配置白名单视为不允许任何人)
|
|
286
|
+
* 4. `allowFrom` 含 `"*"` → 允许所有人(通配符白名单)
|
|
287
|
+
* 5. `allowFrom` 含发送方 ID → 允许(精确匹配,大小写不敏感)
|
|
288
|
+
* 6. 以上均不满足 → 拒绝
|
|
289
|
+
*
|
|
290
|
+
* @param allowFrom - 允许发送消息的用户 ID 白名单(支持 "*" 通配符)
|
|
291
|
+
* @param dmPolicy - 私聊策略("disabled" | "open" | "allowlist")
|
|
292
|
+
* @param senderId - 发送方用户 ID(uin)
|
|
293
|
+
* @returns `true` = 有权限,`false` = 无权限
|
|
294
|
+
*/
|
|
345
295
|
function checkAuth(allowFrom, dmPolicy, senderId) {
|
|
346
|
-
if (dmPolicy ===
|
|
296
|
+
if (dmPolicy === 'disabled')
|
|
347
297
|
return false;
|
|
348
|
-
if (dmPolicy ===
|
|
298
|
+
if (dmPolicy === 'open')
|
|
349
299
|
return true;
|
|
350
300
|
if (!allowFrom || allowFrom.length === 0)
|
|
351
301
|
return false;
|
|
352
|
-
return allowFrom.includes(
|
|
302
|
+
return allowFrom.includes('*') || allowFrom.some((id) => id.toLowerCase() === senderId.toLowerCase());
|
|
353
303
|
}
|
|
354
|
-
//# sourceMappingURL=inbound.js.map
|
package/dist/src/media.js
CHANGED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { CHANNEL_KEY } from './config.js';
|
|
2
|
+
/**
|
|
3
|
+
* 将任意格式的消息目标地址规范化为内部标准格式(`user:xxx` 或 `channel:xxx`)。
|
|
4
|
+
*
|
|
5
|
+
* 支持的输入格式:
|
|
6
|
+
* - `lightclawbot:dm:123` → `user:123` (带通道前缀的私聊)
|
|
7
|
+
* - `lightclawbot:group:456` → `channel:456` (带通道前缀的群聊)
|
|
8
|
+
* - `dm:123` → `user:123` (私聊简写)
|
|
9
|
+
* - `group:456` → `channel:456` (群聊简写)
|
|
10
|
+
* - `user:123` → `user:123` (已是标准格式,原样返回)
|
|
11
|
+
* - `channel:456` → `channel:456` (已是标准格式,原样返回)
|
|
12
|
+
* - `123` → `user:123` (纯数字 ID,默认视为私聊)
|
|
13
|
+
*
|
|
14
|
+
* @param target - 原始目标地址字符串
|
|
15
|
+
* @returns 规范化后的目标地址,若输入为空则返回 `undefined`
|
|
16
|
+
*/
|
|
17
|
+
export function normalizeTarget(target) {
|
|
18
|
+
// 剥离通道名前缀(如 "lightclawbot:"),使后续逻辑只处理纯地址部分
|
|
19
|
+
const cleaned = target.replace(new RegExp(`^${CHANNEL_KEY}:`, 'i'), '');
|
|
20
|
+
// 输入为空或仅含通道前缀时,无法确定目标,返回 undefined
|
|
21
|
+
if (!cleaned)
|
|
22
|
+
return undefined;
|
|
23
|
+
// dm:xxx → user:xxx(私聊)
|
|
24
|
+
if (cleaned.startsWith('dm:')) {
|
|
25
|
+
return `user:${cleaned.slice(3)}`;
|
|
26
|
+
}
|
|
27
|
+
// group:xxx → channel:xxx(群聊)
|
|
28
|
+
if (cleaned.startsWith('group:')) {
|
|
29
|
+
return `channel:${cleaned.slice(6)}`;
|
|
30
|
+
}
|
|
31
|
+
// 已经是标准格式 user:xxx / channel:xxx,无需转换,原样返回
|
|
32
|
+
if (/^(user|channel):/i.test(cleaned)) {
|
|
33
|
+
return cleaned;
|
|
34
|
+
}
|
|
35
|
+
// 其余情况视为纯 ID(如纯数字),默认当作私聊目标
|
|
36
|
+
return `user:${cleaned}`;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* 判断给定字符串是否看起来像一个合法的消息目标 ID。
|
|
40
|
+
*
|
|
41
|
+
* 优先使用已规范化的 `normalized` 值进行判断;若未提供,则直接使用原始 `id`。
|
|
42
|
+
*
|
|
43
|
+
* 以下格式均被认为是合法 ID:
|
|
44
|
+
* - `user:xxx` / `channel:xxx` — 内部标准前缀格式
|
|
45
|
+
* - `dm:123` / `group:123` — LightClaw 自有格式(纯数字部分)
|
|
46
|
+
* - `123` — 纯数字 ID
|
|
47
|
+
*
|
|
48
|
+
* @param id - 原始目标地址字符串
|
|
49
|
+
* @param normalized - 可选,已经过 `normalizeTarget` 处理的规范化地址,优先使用
|
|
50
|
+
* @returns 若字符串符合合法 ID 格式则返回 `true`,否则返回 `false`
|
|
51
|
+
*/
|
|
52
|
+
export function looksLikeId(id, normalized) {
|
|
53
|
+
// 优先使用规范化值,去除首尾空白
|
|
54
|
+
const value = (normalized ?? id).trim();
|
|
55
|
+
// 空字符串不是合法 ID
|
|
56
|
+
if (!value)
|
|
57
|
+
return false;
|
|
58
|
+
// 匹配内部标准前缀格式:user:xxx 或 channel:xxx
|
|
59
|
+
if (/^(user|channel):/i.test(value))
|
|
60
|
+
return true;
|
|
61
|
+
// 剥离通道前缀后,判断是否符合 LightClaw 自有格式
|
|
62
|
+
const cleaned = value.replace(new RegExp(`^${CHANNEL_KEY}:`, 'i'), '');
|
|
63
|
+
// dm:<数字> 或 group:<数字> 格式,或纯数字 ID
|
|
64
|
+
return /^(dm|group):\d+/.test(cleaned) || /^\d+$/.test(cleaned);
|
|
65
|
+
}
|