@cxyhhhhh/openclaw-qqbot 2.0.0-dev.202607081648 → 2.0.0-dev.202607082219

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.
Files changed (36) hide show
  1. package/dist/index.cjs +543 -393
  2. package/dist/index.cjs.map +1 -1
  3. package/index.ts +1 -1
  4. package/package.json +1 -1
  5. package/skills/qqbot-channel/SKILL.md +33 -11
  6. package/src/{runtime-adapter/contract-check.ts → adapter/contract.ts} +4 -7
  7. package/src/{runtime-adapter/gateway-runtime.ts → adapter/gateway.ts} +2 -3
  8. package/src/{runtime-adapter → adapter}/index.ts +3 -3
  9. package/src/{runtime-adapter/lint-runtime-access.ts → adapter/lint.ts} +7 -7
  10. package/src/adapter/media.ts +112 -0
  11. package/src/adapter/setup.ts +55 -0
  12. package/src/adapter/workspace.ts +29 -0
  13. package/src/bot-instance.ts +1 -1
  14. package/src/channel.ts +1 -1
  15. package/src/commands/bot-approve.ts +1 -1
  16. package/src/commands/bot-logs.ts +1 -1
  17. package/src/commands/bot-pairing.ts +1 -1
  18. package/src/commands/config-util.ts +1 -1
  19. package/src/dispatch/body-assembler.ts +1 -1
  20. package/src/dispatch/dispatch.ts +75 -45
  21. package/src/features/approval-handler.ts +1 -1
  22. package/src/gateway/event-handlers.ts +1 -1
  23. package/src/gateway/lifecycle.ts +1 -1
  24. package/src/gateway/qqbot-gateway.ts +1 -1
  25. package/src/middleware/access-control.ts +1 -1
  26. package/src/middleware/attachment.ts +4 -4
  27. package/src/openclaw-plugin-sdk.d.ts +41 -0
  28. package/src/outbound/media-send.ts +4 -6
  29. package/src/runtime.ts +3 -1
  30. package/src/setup/finalize.ts +1 -2
  31. package/src/setup/surface.ts +5 -6
  32. package/src/utils/pkg-version.ts +78 -58
  33. package/tsup.config.ts +6 -1
  34. /package/src/{runtime-adapter/pairing-runtime.ts → adapter/pairing.ts} +0 -0
  35. /package/src/{runtime-adapter → adapter}/resolve.ts +0 -0
  36. /package/src/{runtime-adapter/webhook-adapter.ts → adapter/webhook.ts} +0 -0
package/dist/index.cjs CHANGED
@@ -2239,7 +2239,7 @@ var require_websocket = __commonJS({
2239
2239
  var http2 = require("http");
2240
2240
  var net = require("net");
2241
2241
  var tls = require("tls");
2242
- var { randomBytes, createHash: createHash3 } = require("crypto");
2242
+ var { randomBytes: randomBytes2, createHash: createHash3 } = require("crypto");
2243
2243
  var { Duplex, Readable } = require("stream");
2244
2244
  var { URL: URL2 } = require("url");
2245
2245
  var PerMessageDeflate2 = require_permessage_deflate();
@@ -2769,7 +2769,7 @@ var require_websocket = __commonJS({
2769
2769
  }
2770
2770
  }
2771
2771
  const defaultPort = isSecure ? 443 : 80;
2772
- const key = randomBytes(16).toString("base64");
2772
+ const key = randomBytes2(16).toString("base64");
2773
2773
  const request2 = isSecure ? https3.request : http2.request;
2774
2774
  const protocolSet = /* @__PURE__ */ new Set();
2775
2775
  let perMessageDeflate;
@@ -2822,7 +2822,7 @@ var require_websocket = __commonJS({
2822
2822
  opts.socketPath = parts[0];
2823
2823
  opts.path = parts[1];
2824
2824
  }
2825
- let req;
2825
+ let req4;
2826
2826
  if (opts.followRedirects) {
2827
2827
  if (websocket._redirects === 0) {
2828
2828
  websocket._originalIpc = isIpcUrl;
@@ -2847,32 +2847,32 @@ var require_websocket = __commonJS({
2847
2847
  if (opts.auth && !options.headers.authorization) {
2848
2848
  options.headers.authorization = "Basic " + Buffer.from(opts.auth).toString("base64");
2849
2849
  }
2850
- req = websocket._req = request2(opts);
2850
+ req4 = websocket._req = request2(opts);
2851
2851
  if (websocket._redirects) {
2852
- websocket.emit("redirect", websocket.url, req);
2852
+ websocket.emit("redirect", websocket.url, req4);
2853
2853
  }
2854
2854
  } else {
2855
- req = websocket._req = request2(opts);
2855
+ req4 = websocket._req = request2(opts);
2856
2856
  }
2857
2857
  if (opts.timeout) {
2858
- req.on("timeout", () => {
2859
- abortHandshake(websocket, req, "Opening handshake has timed out");
2858
+ req4.on("timeout", () => {
2859
+ abortHandshake(websocket, req4, "Opening handshake has timed out");
2860
2860
  });
2861
2861
  }
2862
- req.on("error", (err) => {
2863
- if (req === null || req[kAborted]) return;
2864
- req = websocket._req = null;
2862
+ req4.on("error", (err) => {
2863
+ if (req4 === null || req4[kAborted]) return;
2864
+ req4 = websocket._req = null;
2865
2865
  emitErrorAndClose(websocket, err);
2866
2866
  });
2867
- req.on("response", (res) => {
2867
+ req4.on("response", (res) => {
2868
2868
  const location = res.headers.location;
2869
2869
  const statusCode = res.statusCode;
2870
2870
  if (location && opts.followRedirects && statusCode >= 300 && statusCode < 400) {
2871
2871
  if (++websocket._redirects > opts.maxRedirects) {
2872
- abortHandshake(websocket, req, "Maximum redirects exceeded");
2872
+ abortHandshake(websocket, req4, "Maximum redirects exceeded");
2873
2873
  return;
2874
2874
  }
2875
- req.abort();
2875
+ req4.abort();
2876
2876
  let addr;
2877
2877
  try {
2878
2878
  addr = new URL2(location, address);
@@ -2882,18 +2882,18 @@ var require_websocket = __commonJS({
2882
2882
  return;
2883
2883
  }
2884
2884
  initAsClient(websocket, addr, protocols, options);
2885
- } else if (!websocket.emit("unexpected-response", req, res)) {
2885
+ } else if (!websocket.emit("unexpected-response", req4, res)) {
2886
2886
  abortHandshake(
2887
2887
  websocket,
2888
- req,
2888
+ req4,
2889
2889
  `Unexpected server response: ${res.statusCode}`
2890
2890
  );
2891
2891
  }
2892
2892
  });
2893
- req.on("upgrade", (res, socket, head) => {
2893
+ req4.on("upgrade", (res, socket, head) => {
2894
2894
  websocket.emit("upgrade", res);
2895
2895
  if (websocket.readyState !== WebSocket2.CONNECTING) return;
2896
- req = websocket._req = null;
2896
+ req4 = websocket._req = null;
2897
2897
  const upgrade = res.headers.upgrade;
2898
2898
  if (upgrade === void 0 || upgrade.toLowerCase() !== "websocket") {
2899
2899
  abortHandshake(websocket, socket, "Invalid Upgrade header");
@@ -2958,9 +2958,9 @@ var require_websocket = __commonJS({
2958
2958
  });
2959
2959
  });
2960
2960
  if (opts.finishRequest) {
2961
- opts.finishRequest(req, websocket);
2961
+ opts.finishRequest(req4, websocket);
2962
2962
  } else {
2963
- req.end();
2963
+ req4.end();
2964
2964
  }
2965
2965
  }
2966
2966
  function emitErrorAndClose(websocket, err) {
@@ -3339,7 +3339,7 @@ var require_websocket_server = __commonJS({
3339
3339
  );
3340
3340
  }
3341
3341
  if (options.port != null) {
3342
- this._server = http2.createServer((req, res) => {
3342
+ this._server = http2.createServer((req4, res) => {
3343
3343
  const body = http2.STATUS_CODES[426];
3344
3344
  res.writeHead(426, {
3345
3345
  "Content-Length": body.length,
@@ -3361,8 +3361,8 @@ var require_websocket_server = __commonJS({
3361
3361
  this._removeListeners = addListeners(this._server, {
3362
3362
  listening: this.emit.bind(this, "listening"),
3363
3363
  error: this.emit.bind(this, "error"),
3364
- upgrade: (req, socket, head) => {
3365
- this.handleUpgrade(req, socket, head, emitConnection);
3364
+ upgrade: (req4, socket, head) => {
3365
+ this.handleUpgrade(req4, socket, head, emitConnection);
3366
3366
  }
3367
3367
  });
3368
3368
  }
@@ -3440,10 +3440,10 @@ var require_websocket_server = __commonJS({
3440
3440
  * @return {Boolean} `true` if the request is valid, else `false`
3441
3441
  * @public
3442
3442
  */
3443
- shouldHandle(req) {
3443
+ shouldHandle(req4) {
3444
3444
  if (this.options.path) {
3445
- const index = req.url.indexOf("?");
3446
- const pathname = index !== -1 ? req.url.slice(0, index) : req.url;
3445
+ const index = req4.url.indexOf("?");
3446
+ const pathname = index !== -1 ? req4.url.slice(0, index) : req4.url;
3447
3447
  if (pathname !== this.options.path) return false;
3448
3448
  }
3449
3449
  return true;
@@ -3457,49 +3457,49 @@ var require_websocket_server = __commonJS({
3457
3457
  * @param {Function} cb Callback
3458
3458
  * @public
3459
3459
  */
3460
- handleUpgrade(req, socket, head, cb) {
3460
+ handleUpgrade(req4, socket, head, cb) {
3461
3461
  socket.on("error", socketOnError);
3462
- const key = req.headers["sec-websocket-key"];
3463
- const upgrade = req.headers.upgrade;
3464
- const version = +req.headers["sec-websocket-version"];
3465
- if (req.method !== "GET") {
3462
+ const key = req4.headers["sec-websocket-key"];
3463
+ const upgrade = req4.headers.upgrade;
3464
+ const version = +req4.headers["sec-websocket-version"];
3465
+ if (req4.method !== "GET") {
3466
3466
  const message = "Invalid HTTP method";
3467
- abortHandshakeOrEmitwsClientError(this, req, socket, 405, message);
3467
+ abortHandshakeOrEmitwsClientError(this, req4, socket, 405, message);
3468
3468
  return;
3469
3469
  }
3470
3470
  if (upgrade === void 0 || upgrade.toLowerCase() !== "websocket") {
3471
3471
  const message = "Invalid Upgrade header";
3472
- abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);
3472
+ abortHandshakeOrEmitwsClientError(this, req4, socket, 400, message);
3473
3473
  return;
3474
3474
  }
3475
3475
  if (key === void 0 || !keyRegex.test(key)) {
3476
3476
  const message = "Missing or invalid Sec-WebSocket-Key header";
3477
- abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);
3477
+ abortHandshakeOrEmitwsClientError(this, req4, socket, 400, message);
3478
3478
  return;
3479
3479
  }
3480
3480
  if (version !== 13 && version !== 8) {
3481
3481
  const message = "Missing or invalid Sec-WebSocket-Version header";
3482
- abortHandshakeOrEmitwsClientError(this, req, socket, 400, message, {
3482
+ abortHandshakeOrEmitwsClientError(this, req4, socket, 400, message, {
3483
3483
  "Sec-WebSocket-Version": "13, 8"
3484
3484
  });
3485
3485
  return;
3486
3486
  }
3487
- if (!this.shouldHandle(req)) {
3487
+ if (!this.shouldHandle(req4)) {
3488
3488
  abortHandshake(socket, 400);
3489
3489
  return;
3490
3490
  }
3491
- const secWebSocketProtocol = req.headers["sec-websocket-protocol"];
3491
+ const secWebSocketProtocol = req4.headers["sec-websocket-protocol"];
3492
3492
  let protocols = /* @__PURE__ */ new Set();
3493
3493
  if (secWebSocketProtocol !== void 0) {
3494
3494
  try {
3495
3495
  protocols = subprotocol2.parse(secWebSocketProtocol);
3496
3496
  } catch (err) {
3497
3497
  const message = "Invalid Sec-WebSocket-Protocol header";
3498
- abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);
3498
+ abortHandshakeOrEmitwsClientError(this, req4, socket, 400, message);
3499
3499
  return;
3500
3500
  }
3501
3501
  }
3502
- const secWebSocketExtensions = req.headers["sec-websocket-extensions"];
3502
+ const secWebSocketExtensions = req4.headers["sec-websocket-extensions"];
3503
3503
  const extensions = {};
3504
3504
  if (this.options.perMessageDeflate && secWebSocketExtensions !== void 0) {
3505
3505
  const perMessageDeflate = new PerMessageDeflate2({
@@ -3515,15 +3515,15 @@ var require_websocket_server = __commonJS({
3515
3515
  }
3516
3516
  } catch (err) {
3517
3517
  const message = "Invalid or unacceptable Sec-WebSocket-Extensions header";
3518
- abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);
3518
+ abortHandshakeOrEmitwsClientError(this, req4, socket, 400, message);
3519
3519
  return;
3520
3520
  }
3521
3521
  }
3522
3522
  if (this.options.verifyClient) {
3523
3523
  const info = {
3524
- origin: req.headers[`${version === 8 ? "sec-websocket-origin" : "origin"}`],
3525
- secure: !!(req.socket.authorized || req.socket.encrypted),
3526
- req
3524
+ origin: req4.headers[`${version === 8 ? "sec-websocket-origin" : "origin"}`],
3525
+ secure: !!(req4.socket.authorized || req4.socket.encrypted),
3526
+ req: req4
3527
3527
  };
3528
3528
  if (this.options.verifyClient.length === 2) {
3529
3529
  this.options.verifyClient(info, (verified, code, message, headers) => {
@@ -3534,7 +3534,7 @@ var require_websocket_server = __commonJS({
3534
3534
  extensions,
3535
3535
  key,
3536
3536
  protocols,
3537
- req,
3537
+ req4,
3538
3538
  socket,
3539
3539
  head,
3540
3540
  cb
@@ -3544,7 +3544,7 @@ var require_websocket_server = __commonJS({
3544
3544
  }
3545
3545
  if (!this.options.verifyClient(info)) return abortHandshake(socket, 401);
3546
3546
  }
3547
- this.completeUpgrade(extensions, key, protocols, req, socket, head, cb);
3547
+ this.completeUpgrade(extensions, key, protocols, req4, socket, head, cb);
3548
3548
  }
3549
3549
  /**
3550
3550
  * Upgrade the connection to WebSocket.
@@ -3559,7 +3559,7 @@ var require_websocket_server = __commonJS({
3559
3559
  * @throws {Error} If called more than once with the same socket
3560
3560
  * @private
3561
3561
  */
3562
- completeUpgrade(extensions, key, protocols, req, socket, head, cb) {
3562
+ completeUpgrade(extensions, key, protocols, req4, socket, head, cb) {
3563
3563
  if (!socket.readable || !socket.writable) return socket.destroy();
3564
3564
  if (socket[kWebSocket]) {
3565
3565
  throw new Error(
@@ -3576,7 +3576,7 @@ var require_websocket_server = __commonJS({
3576
3576
  ];
3577
3577
  const ws = new this.options.WebSocket(null, void 0, this.options);
3578
3578
  if (protocols.size) {
3579
- const protocol = this.options.handleProtocols ? this.options.handleProtocols(protocols, req) : protocols.values().next().value;
3579
+ const protocol = this.options.handleProtocols ? this.options.handleProtocols(protocols, req4) : protocols.values().next().value;
3580
3580
  if (protocol) {
3581
3581
  headers.push(`Sec-WebSocket-Protocol: ${protocol}`);
3582
3582
  ws._protocol = protocol;
@@ -3590,7 +3590,7 @@ var require_websocket_server = __commonJS({
3590
3590
  headers.push(`Sec-WebSocket-Extensions: ${value}`);
3591
3591
  ws._extensions = extensions;
3592
3592
  }
3593
- this.emit("headers", headers, req);
3593
+ this.emit("headers", headers, req4);
3594
3594
  socket.write(headers.concat("\r\n").join("\r\n"));
3595
3595
  socket.removeListener("error", socketOnError);
3596
3596
  ws.setSocket(socket, head, {
@@ -3607,7 +3607,7 @@ var require_websocket_server = __commonJS({
3607
3607
  }
3608
3608
  });
3609
3609
  }
3610
- cb(ws, req);
3610
+ cb(ws, req4);
3611
3611
  }
3612
3612
  };
3613
3613
  module2.exports = WebSocketServer2;
@@ -3640,11 +3640,11 @@ var require_websocket_server = __commonJS({
3640
3640
  ` + Object.keys(headers).map((h2) => `${h2}: ${headers[h2]}`).join("\r\n") + "\r\n\r\n" + message
3641
3641
  );
3642
3642
  }
3643
- function abortHandshakeOrEmitwsClientError(server, req, socket, code, message, headers) {
3643
+ function abortHandshakeOrEmitwsClientError(server, req4, socket, code, message, headers) {
3644
3644
  if (server.listenerCount("wsClientError")) {
3645
3645
  const err = new Error(message);
3646
3646
  Error.captureStackTrace(err, abortHandshakeOrEmitwsClientError);
3647
- server.emit("wsClientError", err, socket, req);
3647
+ server.emit("wsClientError", err, socket, req4);
3648
3648
  } else {
3649
3649
  abortHandshake(socket, code, message, headers);
3650
3650
  }
@@ -5020,11 +5020,11 @@ var fs3 = __toESM(require("fs"), 1);
5020
5020
  var path = __toESM(require("path"), 1);
5021
5021
 
5022
5022
  // node_modules/.pnpm/@cxyhhhhh+qqbot-nodejs@1.0.2-dev.202607081646/node_modules/@cxyhhhhh/qqbot-nodejs/dist/middleware/types.js
5023
- function resolvePolicy(ctx, path20, explicit, defaultValue) {
5023
+ function resolvePolicy(ctx, path21, explicit, defaultValue) {
5024
5024
  if (explicit !== void 0 && explicit !== null) {
5025
5025
  return explicit;
5026
5026
  }
5027
- const keys = path20.split(".");
5027
+ const keys = path21.split(".");
5028
5028
  let value = ctx.state.policy;
5029
5029
  for (const key of keys) {
5030
5030
  if (value === null || value === void 0)
@@ -5102,10 +5102,10 @@ var ApiError = class extends Error {
5102
5102
  bizCode;
5103
5103
  bizMessage;
5104
5104
  name = "ApiError";
5105
- constructor(message, httpStatus, path20, bizCode, bizMessage) {
5105
+ constructor(message, httpStatus, path21, bizCode, bizMessage) {
5106
5106
  super(message);
5107
5107
  this.httpStatus = httpStatus;
5108
- this.path = path20;
5108
+ this.path = path21;
5109
5109
  this.bizCode = bizCode;
5110
5110
  this.bizMessage = bizMessage;
5111
5111
  }
@@ -5193,14 +5193,14 @@ var ApiClient = class {
5193
5193
  const ua = config.userAgent ?? "qqbot-nodejs/unknown";
5194
5194
  this.resolveUserAgent = typeof ua === "function" ? ua : () => ua;
5195
5195
  }
5196
- async request(accessToken, method, path20, body, options) {
5197
- const url = `${this.baseUrl}${path20}`;
5196
+ async request(accessToken, method, path21, body, options) {
5197
+ const url = `${this.baseUrl}${path21}`;
5198
5198
  const headers = {
5199
5199
  Authorization: `QQBot ${accessToken}`,
5200
5200
  "Content-Type": "application/json",
5201
5201
  "User-Agent": this.resolveUserAgent()
5202
5202
  };
5203
- const isFileUpload = options?.uploadRequest === true || path20.includes("/files") || path20.includes("/upload_prepare") || path20.includes("/upload_part_finish");
5203
+ const isFileUpload = options?.uploadRequest === true || path21.includes("/files") || path21.includes("/upload_prepare") || path21.includes("/upload_part_finish");
5204
5204
  const timeout = options?.timeoutMs ?? (isFileUpload ? this.fileUploadTimeoutMs : this.defaultTimeoutMs);
5205
5205
  const controller = new AbortController();
5206
5206
  const timeoutId = setTimeout(() => controller.abort(), timeout);
@@ -5225,10 +5225,10 @@ var ApiClient = class {
5225
5225
  clearTimeout(timeoutId);
5226
5226
  if (err instanceof Error && err.name === "AbortError") {
5227
5227
  this.logger?.error?.(`[qqbot:api] <<< Timeout after ${timeout}ms`);
5228
- throw new ApiError(`Request timeout [${path20}]: exceeded ${timeout}ms`, 0, path20);
5228
+ throw new ApiError(`Request timeout [${path21}]: exceeded ${timeout}ms`, 0, path21);
5229
5229
  }
5230
5230
  this.logger?.error?.(`[qqbot:api] <<< Network error: ${formatErrorMessage(err)}`);
5231
- throw new ApiError(`Network error [${path20}]: ${formatErrorMessage(err)}`, 0, path20);
5231
+ throw new ApiError(`Network error [${path21}]: ${formatErrorMessage(err)}`, 0, path21);
5232
5232
  } finally {
5233
5233
  clearTimeout(timeoutId);
5234
5234
  }
@@ -5238,7 +5238,7 @@ var ApiClient = class {
5238
5238
  try {
5239
5239
  rawBody = await res.text();
5240
5240
  } catch (err) {
5241
- throw new ApiError(`Failed to read response [${path20}]: ${formatErrorMessage(err)}`, res.status, path20);
5241
+ throw new ApiError(`Failed to read response [${path21}]: ${formatErrorMessage(err)}`, res.status, path21);
5242
5242
  }
5243
5243
  this.logger?.debug?.(`[qqbot:api] <<< Body: ${rawBody}`);
5244
5244
  const contentType = res.headers.get("content-type") ?? "";
@@ -5246,26 +5246,26 @@ var ApiClient = class {
5246
5246
  if (!res.ok) {
5247
5247
  if (isHtmlResponse) {
5248
5248
  const statusHint = res.status === 502 || res.status === 503 || res.status === 504 ? "\u8C03\u7528\u53D1\u751F\u5F02\u5E38\uFF0C\u8BF7\u7A0D\u5019\u91CD\u8BD5" : res.status === 429 ? "\u8BF7\u6C42\u8FC7\u4E8E\u9891\u7E41\uFF0C\u5DF2\u88AB\u9650\u6D41" : `\u5F00\u653E\u5E73\u53F0\u8FD4\u56DE HTTP ${res.status}`;
5249
- throw new ApiError(`${statusHint}\uFF08${path20}\uFF09\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5`, res.status, path20);
5249
+ throw new ApiError(`${statusHint}\uFF08${path21}\uFF09\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5`, res.status, path21);
5250
5250
  }
5251
5251
  try {
5252
5252
  const error = JSON.parse(rawBody);
5253
5253
  const bizCode = error.code ?? error.err_code;
5254
- throw new ApiError(`API Error [${path20}]: ${error.message ?? rawBody}`, res.status, path20, bizCode, error.message);
5254
+ throw new ApiError(`API Error [${path21}]: ${error.message ?? rawBody}`, res.status, path21, bizCode, error.message);
5255
5255
  } catch (parseErr) {
5256
5256
  if (parseErr instanceof ApiError) {
5257
5257
  throw parseErr;
5258
5258
  }
5259
- throw new ApiError(`API Error [${path20}] HTTP ${res.status}: ${rawBody.slice(0, 200)}`, res.status, path20);
5259
+ throw new ApiError(`API Error [${path21}] HTTP ${res.status}: ${rawBody.slice(0, 200)}`, res.status, path21);
5260
5260
  }
5261
5261
  }
5262
5262
  if (isHtmlResponse) {
5263
- throw new ApiError(`QQ \u670D\u52A1\u7AEF\u8FD4\u56DE\u4E86\u975E JSON \u54CD\u5E94\uFF08${path20}\uFF09\uFF0C\u53EF\u80FD\u662F\u4E34\u65F6\u6545\u969C\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5`, res.status, path20);
5263
+ throw new ApiError(`QQ \u670D\u52A1\u7AEF\u8FD4\u56DE\u4E86\u975E JSON \u54CD\u5E94\uFF08${path21}\uFF09\uFF0C\u53EF\u80FD\u662F\u4E34\u65F6\u6545\u969C\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5`, res.status, path21);
5264
5264
  }
5265
5265
  try {
5266
5266
  return JSON.parse(rawBody);
5267
5267
  } catch {
5268
- throw new ApiError(`\u5F00\u653E\u5E73\u53F0\u54CD\u5E94\u683C\u5F0F\u5F02\u5E38\uFF08${path20}\uFF09\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5`, res.status, path20);
5268
+ throw new ApiError(`\u5F00\u653E\u5E73\u53F0\u54CD\u5E94\u683C\u5F0F\u5F02\u5E38\uFF08${path21}\uFF09\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5`, res.status, path21);
5269
5269
  }
5270
5270
  }
5271
5271
  };
@@ -5488,9 +5488,9 @@ var ChunkedMediaApi = class {
5488
5488
  }
5489
5489
  async callUploadPrepare(opts, fileName, fileSize, hashes, pathLabel) {
5490
5490
  const token = await this.tokenManager.getAccessToken(opts.creds.appId, opts.creds.clientSecret);
5491
- const path20 = uploadPreparePath(opts.scope, opts.targetId);
5491
+ const path21 = uploadPreparePath(opts.scope, opts.targetId);
5492
5492
  try {
5493
- return await this.client.request(token, "POST", path20, {
5493
+ return await this.client.request(token, "POST", path21, {
5494
5494
  file_type: opts.fileType,
5495
5495
  file_name: fileName,
5496
5496
  file_size: fileSize,
@@ -5507,10 +5507,10 @@ var ChunkedMediaApi = class {
5507
5507
  }
5508
5508
  async callUploadPartFinish(opts, uploadId, partIndex, blockSize, md5, retryTimeoutMs) {
5509
5509
  const persistentPolicy = buildPartFinishPersistentPolicy(retryTimeoutMs);
5510
- const path20 = uploadPartFinishPath(opts.scope, opts.targetId);
5510
+ const path21 = uploadPartFinishPath(opts.scope, opts.targetId);
5511
5511
  await withRetry(async () => {
5512
5512
  const token = await this.tokenManager.getAccessToken(opts.creds.appId, opts.creds.clientSecret);
5513
- return this.client.request(token, "POST", path20, {
5513
+ return this.client.request(token, "POST", path21, {
5514
5514
  upload_id: uploadId,
5515
5515
  part_index: partIndex,
5516
5516
  block_size: blockSize,
@@ -5519,10 +5519,10 @@ var ChunkedMediaApi = class {
5519
5519
  }, PART_FINISH_RETRY_POLICY, persistentPolicy, this.logger);
5520
5520
  }
5521
5521
  async callCompleteUpload(opts, uploadId) {
5522
- const path20 = uploadCompletePath(opts.scope, opts.targetId);
5522
+ const path21 = uploadCompletePath(opts.scope, opts.targetId);
5523
5523
  return withRetry(async () => {
5524
5524
  const token = await this.tokenManager.getAccessToken(opts.creds.appId, opts.creds.clientSecret);
5525
- return this.client.request(token, "POST", path20, { upload_id: uploadId }, { uploadRequest: true });
5525
+ return this.client.request(token, "POST", path21, { upload_id: uploadId }, { uploadRequest: true });
5526
5526
  }, COMPLETE_UPLOAD_RETRY_POLICY, void 0, this.logger);
5527
5527
  }
5528
5528
  };
@@ -5598,7 +5598,7 @@ var PART_UPLOAD_MAX_RETRIES = 2;
5598
5598
  function putToCOS(presignedUrl, data, signal) {
5599
5599
  return new Promise((resolve2, reject) => {
5600
5600
  const parsed = new URL(presignedUrl);
5601
- const req = https.request(parsed, {
5601
+ const req4 = https.request(parsed, {
5602
5602
  method: "PUT",
5603
5603
  headers: { "Content-Length": String(data.length) },
5604
5604
  signal
@@ -5616,10 +5616,10 @@ function putToCOS(presignedUrl, data, signal) {
5616
5616
  });
5617
5617
  res.on("error", reject);
5618
5618
  });
5619
- req.on("error", (err) => {
5619
+ req4.on("error", (err) => {
5620
5620
  reject(err);
5621
5621
  });
5622
- req.end(data);
5622
+ req4.end(data);
5623
5623
  });
5624
5624
  }
5625
5625
  async function putToPresignedUrl(presignedUrl, data, partIndex, totalParts, logger, prefix) {
@@ -5716,8 +5716,8 @@ var MediaApi = class {
5716
5716
  body.file_name = this.sanitize(opts.fileName);
5717
5717
  }
5718
5718
  const token = await this.tokenManager.getAccessToken(creds.appId, creds.clientSecret);
5719
- const path20 = mediaUploadPath(scope, targetId);
5720
- const result = await withRetry(() => this.client.request(token, "POST", path20, body, {
5719
+ const path21 = mediaUploadPath(scope, targetId);
5720
+ const result = await withRetry(() => this.client.request(token, "POST", path21, body, {
5721
5721
  redactBodyKeys: ["file_data"],
5722
5722
  uploadRequest: true
5723
5723
  }), UPLOAD_RETRY_POLICY, void 0, this.logger);
@@ -5733,8 +5733,8 @@ var MediaApi = class {
5733
5733
  async sendMediaMessage(scope, targetId, fileInfo, creds, opts) {
5734
5734
  const token = await this.tokenManager.getAccessToken(creds.appId, creds.clientSecret);
5735
5735
  const msgSeq = opts?.msgId ? getNextMsgSeq(opts.msgId) : 1;
5736
- const path20 = messagePath(scope, targetId);
5737
- return this.client.request(token, "POST", path20, {
5736
+ const path21 = messagePath(scope, targetId);
5737
+ return this.client.request(token, "POST", path21, {
5738
5738
  msg_type: 7,
5739
5739
  media: { file_info: fileInfo },
5740
5740
  msg_seq: msgSeq,
@@ -5773,8 +5773,8 @@ var MessageApi = class {
5773
5773
  const token = await this.tokenManager.getAccessToken(creds.appId, creds.clientSecret);
5774
5774
  const msgSeq = opts?.msgId ? getNextMsgSeq(opts.msgId) : 1;
5775
5775
  const body = this.buildMessageBody(content, opts?.msgId, msgSeq, opts?.messageReference, opts?.inlineKeyboard);
5776
- const path20 = messagePath(scope, targetId);
5777
- return this.sendAndNotify(creds.appId, token, "POST", path20, body, { text: content });
5776
+ const path21 = messagePath(scope, targetId);
5777
+ return this.sendAndNotify(creds.appId, token, "POST", path21, body, { text: content });
5778
5778
  }
5779
5779
  async sendProactiveMessage(scope, targetId, content, creds) {
5780
5780
  if (!content?.trim()) {
@@ -5782,8 +5782,8 @@ var MessageApi = class {
5782
5782
  }
5783
5783
  const token = await this.tokenManager.getAccessToken(creds.appId, creds.clientSecret);
5784
5784
  const body = this.buildProactiveBody(content);
5785
- const path20 = messagePath(scope, targetId);
5786
- return this.sendAndNotify(creds.appId, token, "POST", path20, body, { text: content });
5785
+ const path21 = messagePath(scope, targetId);
5786
+ return this.sendAndNotify(creds.appId, token, "POST", path21, body, { text: content });
5787
5787
  }
5788
5788
  async sendChannelMessage(opts) {
5789
5789
  const token = await this.tokenManager.getAccessToken(opts.creds.appId, opts.creds.clientSecret);
@@ -5829,23 +5829,23 @@ var MessageApi = class {
5829
5829
  * Send a C2C stream message chunk (`/v2/users/{openid}/stream_messages`).
5830
5830
  * Only supported for one-to-one chats.
5831
5831
  */
5832
- async sendC2CStreamMessage(creds, openid, req) {
5832
+ async sendC2CStreamMessage(creds, openid, req4) {
5833
5833
  const token = await this.tokenManager.getAccessToken(creds.appId, creds.clientSecret);
5834
- const path20 = streamMessagePath(openid);
5834
+ const path21 = streamMessagePath(openid);
5835
5835
  const body = {
5836
- input_mode: req.input_mode,
5837
- input_state: req.input_state,
5838
- content_type: req.content_type,
5839
- content_raw: req.content_raw,
5840
- event_id: req.event_id,
5841
- msg_id: req.msg_id,
5842
- msg_seq: req.msg_seq,
5843
- index: req.index
5836
+ input_mode: req4.input_mode,
5837
+ input_state: req4.input_state,
5838
+ content_type: req4.content_type,
5839
+ content_raw: req4.content_raw,
5840
+ event_id: req4.event_id,
5841
+ msg_id: req4.msg_id,
5842
+ msg_seq: req4.msg_seq,
5843
+ index: req4.index
5844
5844
  };
5845
- if (req.stream_msg_id) {
5846
- body.stream_msg_id = req.stream_msg_id;
5845
+ if (req4.stream_msg_id) {
5846
+ body.stream_msg_id = req4.stream_msg_id;
5847
5847
  }
5848
- return this.client.request(token, "POST", path20, body);
5848
+ return this.client.request(token, "POST", path21, body);
5849
5849
  }
5850
5850
  /**
5851
5851
  * Raw message send — transparently forwards all fields to the QQ Open Platform API.
@@ -5859,7 +5859,7 @@ var MessageApi = class {
5859
5859
  */
5860
5860
  async sendRaw(scope, targetId, creds, body) {
5861
5861
  const token = await this.tokenManager.getAccessToken(creds.appId, creds.clientSecret);
5862
- const path20 = messagePath(scope, targetId);
5862
+ const path21 = messagePath(scope, targetId);
5863
5863
  if (body.msg_seq === void 0) {
5864
5864
  body.msg_seq = body.msg_id ? getNextMsgSeq(body.msg_id) : 1;
5865
5865
  }
@@ -5876,7 +5876,7 @@ var MessageApi = class {
5876
5876
  body.msg_type = 0;
5877
5877
  }
5878
5878
  const cleaned = Object.fromEntries(Object.entries(body).filter(([, v]) => v !== void 0));
5879
- return this.sendAndNotify(creds.appId, token, "POST", path20, cleaned, { text: cleaned.content ?? cleaned.markdown?.content });
5879
+ return this.sendAndNotify(creds.appId, token, "POST", path21, cleaned, { text: cleaned.content ?? cleaned.markdown?.content });
5880
5880
  }
5881
5881
  /**
5882
5882
  * Send a message to a guild text channel.
@@ -5900,11 +5900,11 @@ var MessageApi = class {
5900
5900
  */
5901
5901
  async recallMessage(scope, targetId, messageId, creds) {
5902
5902
  const token = await this.tokenManager.getAccessToken(creds.appId, creds.clientSecret);
5903
- const path20 = `${messagePath(scope, targetId)}/${messageId}`;
5904
- await this.client.request(token, "DELETE", path20);
5903
+ const path21 = `${messagePath(scope, targetId)}/${messageId}`;
5904
+ await this.client.request(token, "DELETE", path21);
5905
5905
  }
5906
- async sendAndNotify(_appId, accessToken, method, path20, body, meta) {
5907
- const result = await this.client.request(accessToken, method, path20, body);
5906
+ async sendAndNotify(_appId, accessToken, method, path21, body, meta) {
5907
+ const result = await this.client.request(accessToken, method, path21, body);
5908
5908
  if (result.ext_info?.ref_idx && this.messageSentHook) {
5909
5909
  try {
5910
5910
  this.messageSentHook(result.ext_info.ref_idx, meta);
@@ -6785,21 +6785,21 @@ function signValidationResponse(params) {
6785
6785
  var http = __toESM(require("http"), 1);
6786
6786
  var NodeHttpWebhookServer = class {
6787
6787
  server = null;
6788
- async listen(port, path20, handler) {
6788
+ async listen(port, path21, handler) {
6789
6789
  return new Promise((resolve2, reject) => {
6790
- const server = http.createServer(async (req, res) => {
6791
- if (req.method !== "POST" || req.url !== path20) {
6790
+ const server = http.createServer(async (req4, res) => {
6791
+ if (req4.method !== "POST" || req4.url !== path21) {
6792
6792
  res.writeHead(404, { "Content-Type": "text/plain" });
6793
6793
  res.end("Not Found");
6794
6794
  return;
6795
6795
  }
6796
6796
  const chunks = [];
6797
- req.on("data", (chunk) => chunks.push(chunk));
6798
- req.on("end", async () => {
6797
+ req4.on("data", (chunk) => chunks.push(chunk));
6798
+ req4.on("end", async () => {
6799
6799
  try {
6800
6800
  const body = Buffer.concat(chunks);
6801
6801
  const headers = {};
6802
- for (const [key, value] of Object.entries(req.headers)) {
6802
+ for (const [key, value] of Object.entries(req4.headers)) {
6803
6803
  headers[key.toLowerCase()] = value;
6804
6804
  }
6805
6805
  const response = await handler({ body, headers });
@@ -6850,11 +6850,11 @@ var WebhookTransport = class {
6850
6850
  }
6851
6851
  async start() {
6852
6852
  const port = this.opts.port ?? 8080;
6853
- const path20 = this.opts.path ?? "/";
6854
- this.log?.info?.(`[webhook] starting on port ${port}, path ${path20}`);
6855
- await this.server.listen(port, path20, (req) => this.handleRequest(req));
6856
- this.log?.info?.(`[webhook] listening on :${port}${path20}`);
6857
- this.callbacks.onReady?.({ transport: "webhook", port, path: path20 });
6853
+ const path21 = this.opts.path ?? "/";
6854
+ this.log?.info?.(`[webhook] starting on port ${port}, path ${path21}`);
6855
+ await this.server.listen(port, path21, (req4) => this.handleRequest(req4));
6856
+ this.log?.info?.(`[webhook] listening on :${port}${path21}`);
6857
+ this.callbacks.onReady?.({ transport: "webhook", port, path: path21 });
6858
6858
  if (this.opts.abortSignal) {
6859
6859
  await new Promise((resolve2) => {
6860
6860
  if (this.opts.abortSignal.aborted) {
@@ -6879,10 +6879,10 @@ var WebhookTransport = class {
6879
6879
  this.stopResolve?.();
6880
6880
  }
6881
6881
  // ============ Request handler ============
6882
- async handleRequest(req) {
6882
+ async handleRequest(req4) {
6883
6883
  let payload;
6884
6884
  try {
6885
- payload = JSON.parse(req.body.toString("utf-8"));
6885
+ payload = JSON.parse(req4.body.toString("utf-8"));
6886
6886
  } catch {
6887
6887
  this.log?.warn?.(`[webhook] invalid JSON body`);
6888
6888
  return { status: 400, body: JSON.stringify({ error: "invalid json" }) };
@@ -6890,14 +6890,14 @@ var WebhookTransport = class {
6890
6890
  if (payload.op === OP_VALIDATION) {
6891
6891
  return this.handleValidation(payload);
6892
6892
  }
6893
- const timestamp = getHeader(req.headers, "x-signature-timestamp") ?? "";
6894
- const signature = getHeader(req.headers, "x-signature-ed25519") ?? "";
6893
+ const timestamp = getHeader(req4.headers, "x-signature-timestamp") ?? "";
6894
+ const signature = getHeader(req4.headers, "x-signature-ed25519") ?? "";
6895
6895
  if (!timestamp || !signature) {
6896
6896
  this.log?.warn?.(`[webhook] missing signature headers`);
6897
6897
  return { status: 401, body: JSON.stringify({ error: "missing signature" }) };
6898
6898
  }
6899
6899
  const valid = verifyWebhookSignature({
6900
- body: req.body,
6900
+ body: req4.body,
6901
6901
  timestamp,
6902
6902
  signature,
6903
6903
  botSecret: this.opts.appSecret
@@ -7161,7 +7161,7 @@ var StreamSession = class {
7161
7161
  this.msgSeq = getNextMsgSeq(this.opts.msgId);
7162
7162
  }
7163
7163
  const currentIndex = this.index++;
7164
- const req = {
7164
+ const req4 = {
7165
7165
  input_mode: StreamInputMode.REPLACE,
7166
7166
  input_state: state,
7167
7167
  content_type: StreamContentType.MARKDOWN,
@@ -7172,9 +7172,9 @@ var StreamSession = class {
7172
7172
  index: currentIndex
7173
7173
  };
7174
7174
  if (this.streamMsgId) {
7175
- req.stream_msg_id = this.streamMsgId;
7175
+ req4.stream_msg_id = this.streamMsgId;
7176
7176
  }
7177
- const resp = await this.sendWithRetry(req);
7177
+ const resp = await this.sendWithRetry(req4);
7178
7178
  if (resp?.id && !this.streamMsgId) {
7179
7179
  this.streamMsgId = resp.id;
7180
7180
  }
@@ -7196,10 +7196,10 @@ var StreamSession = class {
7196
7196
  * Send a stream message with exponential backoff on rate-limit errors.
7197
7197
  * QQ returns err_code 50002 or HTTP 429 when rate-limited.
7198
7198
  */
7199
- async sendWithRetry(req) {
7199
+ async sendWithRetry(req4) {
7200
7200
  for (let attempt = 0; attempt <= MAX_FLUSH_RETRIES; attempt++) {
7201
7201
  try {
7202
- return await this.api.sendC2CStreamMessage(this.opts.creds, this.opts.openid, req);
7202
+ return await this.api.sendC2CStreamMessage(this.opts.creds, this.opts.openid, req4);
7203
7203
  } catch (err) {
7204
7204
  if (!this.isRateLimitError(err) || attempt >= MAX_FLUSH_RETRIES) {
7205
7205
  throw err;
@@ -7207,7 +7207,7 @@ var StreamSession = class {
7207
7207
  const delay = RATE_LIMIT_BASE_DELAY_MS * Math.pow(2, attempt);
7208
7208
  this.opts.logger?.debug?.(`[qqbot:stream] rate limited, retry ${attempt + 1}/${MAX_FLUSH_RETRIES} after ${delay}ms`);
7209
7209
  await new Promise((r) => setTimeout(r, delay));
7210
- req.index = this.index++;
7210
+ req4.index = this.index++;
7211
7211
  }
7212
7212
  }
7213
7213
  return void 0;
@@ -7744,25 +7744,25 @@ var QQBot = class {
7744
7744
  if (this._apiGateway)
7745
7745
  return this._apiGateway;
7746
7746
  this._apiGateway = {
7747
- get: (path20, query) => this.apiRequest("GET", path20, void 0, query),
7748
- post: (path20, body) => this.apiRequest("POST", path20, body),
7749
- put: (path20, body) => this.apiRequest("PUT", path20, body),
7750
- patch: (path20, body) => this.apiRequest("PATCH", path20, body),
7751
- delete: (path20) => this.apiRequest("DELETE", path20),
7747
+ get: (path21, query) => this.apiRequest("GET", path21, void 0, query),
7748
+ post: (path21, body) => this.apiRequest("POST", path21, body),
7749
+ put: (path21, body) => this.apiRequest("PUT", path21, body),
7750
+ patch: (path21, body) => this.apiRequest("PATCH", path21, body),
7751
+ delete: (path21) => this.apiRequest("DELETE", path21),
7752
7752
  getToken: () => this.tokenManager.getAccessToken(this.creds.appId, this.creds.clientSecret)
7753
7753
  };
7754
7754
  return this._apiGateway;
7755
7755
  }
7756
- async apiRequest(method, path20, body, query) {
7756
+ async apiRequest(method, path21, body, query) {
7757
7757
  const token = await this.tokenManager.getAccessToken(this.creds.appId, this.creds.clientSecret);
7758
- let fullPath = path20;
7758
+ let fullPath = path21;
7759
7759
  if (query && Object.keys(query).length > 0) {
7760
7760
  const params = new URLSearchParams();
7761
7761
  for (const [k, v] of Object.entries(query)) {
7762
7762
  if (v !== void 0 && v !== null)
7763
7763
  params.set(k, String(v));
7764
7764
  }
7765
- fullPath = `${path20}?${params.toString()}`;
7765
+ fullPath = `${path21}?${params.toString()}`;
7766
7766
  }
7767
7767
  return this.apiClient.request(token, method, fullPath, body ?? void 0);
7768
7768
  }
@@ -9089,69 +9089,73 @@ function formatError(err) {
9089
9089
  }
9090
9090
 
9091
9091
  // src/utils/pkg-version.ts
9092
- var import_node_url = require("url");
9093
- var import_node_module = require("module");
9094
9092
  var import_node_path2 = __toESM(require("path"), 1);
9095
9093
  var import_node_fs2 = __toESM(require("fs"), 1);
9096
- var _resolvedPkgPath = null;
9097
- function getCurrentFilename(metaUrl) {
9098
- if (metaUrl) {
9099
- return (0, import_node_url.fileURLToPath)(metaUrl);
9100
- }
9101
- if (typeof __filename !== "undefined") {
9102
- return __filename;
9103
- }
9104
- return process.cwd();
9094
+ var _cachedOpenclawVersion;
9095
+ function getPackageVersion() {
9096
+ return true ? "2.0.0-dev.202607082219" : "unknown";
9105
9097
  }
9106
- function getPackageVersion(metaUrl) {
9107
- if (_resolvedPkgPath) {
9108
- try {
9109
- const pkg = JSON.parse(import_node_fs2.default.readFileSync(_resolvedPkgPath, "utf8"));
9110
- if (pkg.name === "@tencent-connect/openclaw-qqbot" && pkg.version) {
9111
- return pkg.version;
9112
- }
9113
- } catch {
9114
- _resolvedPkgPath = null;
9115
- }
9098
+ function getOpenclawVersion(runtimeVersion) {
9099
+ if (_cachedOpenclawVersion) return _cachedOpenclawVersion;
9100
+ if (runtimeVersion && runtimeVersion !== "unknown") {
9101
+ return _cachedOpenclawVersion = runtimeVersion;
9116
9102
  }
9117
- const startFile = getCurrentFilename(metaUrl);
9118
- let dir = import_node_path2.default.dirname(startFile);
9119
- const root = import_node_path2.default.parse(dir).root;
9120
- while (dir !== root) {
9121
- const candidate = import_node_path2.default.join(dir, "package.json");
9122
- try {
9123
- if (import_node_fs2.default.existsSync(candidate)) {
9124
- const pkg = JSON.parse(import_node_fs2.default.readFileSync(candidate, "utf8"));
9125
- if (pkg.name === "@tencent-connect/openclaw-qqbot" && pkg.version) {
9126
- _resolvedPkgPath = candidate;
9127
- return pkg.version;
9128
- }
9129
- }
9130
- } catch {
9131
- }
9132
- dir = import_node_path2.default.dirname(dir);
9103
+ if (process.env.OPENCLAW_VERSION) {
9104
+ return _cachedOpenclawVersion = process.env.OPENCLAW_VERSION;
9105
+ }
9106
+ if (process.env.OPENCLAW_SERVICE_VERSION) {
9107
+ return _cachedOpenclawVersion = process.env.OPENCLAW_SERVICE_VERSION;
9133
9108
  }
9109
+ const pkgVer = readOpenclawPackageVersion();
9110
+ if (pkgVer) return _cachedOpenclawVersion = pkgVer;
9111
+ return "unknown";
9112
+ }
9113
+ function readOpenclawPackageVersion() {
9134
9114
  try {
9135
- const req = (0, import_node_module.createRequire)(__filename);
9136
- for (const rel of ["../../package.json", "../package.json", "./package.json"]) {
9115
+ const dirs = searchRoots();
9116
+ for (const dir of dirs) {
9117
+ const pkgPath = import_node_path2.default.join(dir, "package.json");
9137
9118
  try {
9138
- const pkg = req(rel);
9139
- if (pkg?.version) {
9140
- return pkg.version;
9141
- }
9119
+ const pkg = JSON.parse(import_node_fs2.default.readFileSync(pkgPath, "utf8"));
9120
+ if (pkg.name === "openclaw" && pkg.version) return pkg.version;
9142
9121
  } catch {
9143
9122
  }
9144
9123
  }
9145
9124
  } catch {
9146
9125
  }
9147
- return "unknown";
9126
+ return void 0;
9127
+ }
9128
+ function searchRoots() {
9129
+ const roots = [];
9130
+ if (typeof __filename === "string") {
9131
+ let dir = import_node_path2.default.dirname(__filename);
9132
+ for (let i = 0; i < 10; i++) {
9133
+ roots.push(dir);
9134
+ const parent = import_node_path2.default.dirname(dir);
9135
+ if (parent === dir) break;
9136
+ dir = parent;
9137
+ }
9138
+ }
9139
+ for (const key of ["OPENCLAW_STATE_DIR", "CLAWDBOT_STATE_DIR", "MOLTBOT_STATE_DIR"]) {
9140
+ const v = process.env[key];
9141
+ if (v) {
9142
+ roots.push(import_node_path2.default.dirname(v));
9143
+ roots.push(import_node_path2.default.resolve(v, ".."));
9144
+ }
9145
+ }
9146
+ const home = process.env.HOME || process.env.USERPROFILE || "/tmp";
9147
+ for (const name of ["openclaw", "clawdbot", "moltbot"]) {
9148
+ roots.push(import_node_path2.default.join(home, `.${name}`));
9149
+ }
9150
+ roots.push(process.cwd());
9151
+ return [...new Set(roots.filter((r) => typeof r === "string" && r.length > 0))];
9148
9152
  }
9149
9153
 
9150
9154
  // src/bot-instance.ts
9151
9155
  var PLUGIN_VERSION = getPackageVersion();
9152
9156
  var _openclawVersion = "unknown";
9153
9157
  function setOpenClawVersion(version) {
9154
- _openclawVersion = version;
9158
+ if (version) _openclawVersion = version;
9155
9159
  }
9156
9160
  function getOpenClawVersion() {
9157
9161
  return _openclawVersion;
@@ -9471,7 +9475,8 @@ var runtime = null;
9471
9475
  var exitHooksInstalled = false;
9472
9476
  function setQQBotRuntime(next) {
9473
9477
  runtime = next;
9474
- setOpenClawVersion(next.version);
9478
+ const version = getOpenclawVersion(next.version);
9479
+ setOpenClawVersion(version);
9475
9480
  installExitHooksOnce();
9476
9481
  }
9477
9482
  function installExitHooksOnce() {
@@ -9501,14 +9506,14 @@ function tryGetQQBotRuntime() {
9501
9506
  return runtime;
9502
9507
  }
9503
9508
 
9504
- // src/runtime-adapter/resolve.ts
9509
+ // src/adapter/resolve.ts
9505
9510
  function probeFunction(rt, paths) {
9506
- for (const path20 of paths) {
9511
+ for (const path21 of paths) {
9507
9512
  let target = rt;
9508
9513
  let parent = rt;
9509
- for (let i = 0; i < path20.length; i++) {
9514
+ for (let i = 0; i < path21.length; i++) {
9510
9515
  parent = target;
9511
- target = target?.[path20[i]];
9516
+ target = target?.[path21[i]];
9512
9517
  if (target === void 0 || target === null) break;
9513
9518
  }
9514
9519
  if (typeof target === "function") {
@@ -9578,7 +9583,7 @@ function resolveRuntimeAdapters(rt, log4) {
9578
9583
  const chunkMarkdownText = probeFunction(rt, [
9579
9584
  ["channel", "text", "chunkMarkdownText"]
9580
9585
  ]);
9581
- const saveRemoteMedia2 = probeFunction(rt, [
9586
+ const saveRemoteMedia = probeFunction(rt, [
9582
9587
  ["channel", "media", "saveRemoteMedia"]
9583
9588
  ]);
9584
9589
  const getConfig = probeFunction(rt, [
@@ -9607,7 +9612,7 @@ function resolveRuntimeAdapters(rt, log4) {
9607
9612
  recordInboundSession && "recordInboundSession",
9608
9613
  formatEnvelope && "formatEnvelope",
9609
9614
  chunkMarkdownText && "chunkMarkdownText",
9610
- saveRemoteMedia2 && "saveRemoteMedia",
9615
+ saveRemoteMedia && "saveRemoteMedia",
9611
9616
  getConfig && "getConfig",
9612
9617
  persistConfig && `persistConfig(${rawMutateConfig ? "mutate" : "write"})`
9613
9618
  ].filter(Boolean);
@@ -9624,7 +9629,7 @@ function resolveRuntimeAdapters(rt, log4) {
9624
9629
  formatEnvelope,
9625
9630
  resolveEnvelopeFormatOptions,
9626
9631
  chunkMarkdownText,
9627
- saveRemoteMedia: saveRemoteMedia2,
9632
+ saveRemoteMedia,
9628
9633
  getConfig,
9629
9634
  persistConfig,
9630
9635
  version
@@ -9646,7 +9651,24 @@ function getAdapters(rt, log4) {
9646
9651
  var path8 = __toESM(require("path"), 1);
9647
9652
  var fs9 = __toESM(require("fs"), 1);
9648
9653
  var os4 = __toESM(require("os"), 1);
9649
- var import_health = require("openclaw/plugin-sdk/health");
9654
+
9655
+ // src/adapter/workspace.ts
9656
+ var import_node_module = require("module");
9657
+ var req = (0, import_node_module.createRequire)(__filename);
9658
+ var health = null;
9659
+ function resolveAgentWorkspace(cfg, agentId) {
9660
+ if (!health) {
9661
+ try {
9662
+ health = req("openclaw/plugin-sdk/health");
9663
+ } catch {
9664
+ health = null;
9665
+ }
9666
+ }
9667
+ if (health) {
9668
+ return health.resolveAgentWorkspaceDir(cfg, agentId ?? health.resolveDefaultAgentId(cfg));
9669
+ }
9670
+ return getQQBotMediaDir();
9671
+ }
9650
9672
 
9651
9673
  // src/outbound/local-file-router.ts
9652
9674
  var path7 = __toESM(require("path"), 1);
@@ -9774,11 +9796,7 @@ function resolveMediaPath(source, log4, workspaceDir) {
9774
9796
  function resolveWorkspaceFromAgent(agentId) {
9775
9797
  const cfg = resolveConfigViaAdapter();
9776
9798
  if (!cfg) return void 0;
9777
- try {
9778
- return (0, import_health.resolveAgentWorkspaceDir)(cfg, agentId ?? (0, import_health.resolveDefaultAgentId)(cfg));
9779
- } catch {
9780
- return void 0;
9781
- }
9799
+ return resolveAgentWorkspace(cfg, agentId);
9782
9800
  }
9783
9801
  function resolveConfigViaAdapter() {
9784
9802
  try {
@@ -9867,12 +9885,48 @@ function formatErr(err) {
9867
9885
  return String(err);
9868
9886
  }
9869
9887
 
9870
- // src/setup/surface.ts
9871
- var import_setup2 = require("openclaw/plugin-sdk/setup");
9872
-
9873
- // src/setup/finalize.ts
9874
- var import_setup = require("openclaw/plugin-sdk/setup");
9875
- var import_setup_tools = require("openclaw/plugin-sdk/setup-tools");
9888
+ // src/adapter/setup.ts
9889
+ var import_node_module2 = require("module");
9890
+ var req2 = (0, import_node_module2.createRequire)(__filename);
9891
+ var _setup;
9892
+ var _tools;
9893
+ function loadSetup() {
9894
+ if (_setup !== void 0) return _setup;
9895
+ try {
9896
+ _setup = req2("openclaw/plugin-sdk/setup");
9897
+ } catch {
9898
+ _setup = null;
9899
+ }
9900
+ return _setup;
9901
+ }
9902
+ function loadTools() {
9903
+ if (_tools !== void 0) return _tools;
9904
+ try {
9905
+ _tools = req2("openclaw/plugin-sdk/setup-tools");
9906
+ } catch {
9907
+ _tools = null;
9908
+ }
9909
+ return _tools;
9910
+ }
9911
+ var DEFAULT_ACCOUNT_ID2 = "default";
9912
+ function createStandardChannelSetupStatus(...args) {
9913
+ const mod = loadSetup();
9914
+ if (mod) return mod.createStandardChannelSetupStatus(...args);
9915
+ return {
9916
+ channelLabel: args[0]?.channelLabel ?? "QQ Bot",
9917
+ configuredLabel: "Configured",
9918
+ unconfiguredLabel: "Not configured",
9919
+ resolveConfigured: () => false
9920
+ };
9921
+ }
9922
+ function setSetupChannelEnabled(...args) {
9923
+ loadSetup()?.setSetupChannelEnabled?.(...args);
9924
+ }
9925
+ function formatDocsLink(...args) {
9926
+ const mod = loadTools();
9927
+ if (mod) return mod.formatDocsLink(...args);
9928
+ return args[1] ? `${args[1]}: ${args[0]}` : args[0];
9929
+ }
9876
9930
 
9877
9931
  // node_modules/.pnpm/@tencent-connect+qqbot-connector@1.2.0/node_modules/@tencent-connect/qqbot-connector/dist/esm/qr-connect.js
9878
9932
  var import_qrcode_terminal = __toESM(require_main(), 1);
@@ -10039,7 +10093,7 @@ async function linkViaQrCode(cfg, accountId, prompter, rt) {
10039
10093
  } catch (err) {
10040
10094
  rt.error(`QQ Bot \u7ED1\u5B9A\u5931\u8D25: ${String(err)}`);
10041
10095
  await prompter.note(`\u7ED1\u5B9A\u5931\u8D25\uFF0C\u60A8\u53EF\u4EE5\u7A0D\u540E\u624B\u52A8\u914D\u7F6E\u3002
10042
- \u6587\u6863: ${(0, import_setup_tools.formatDocsLink)("/channels/qqbot", "qqbot")}`, "QQ Bot");
10096
+ \u6587\u6863: ${formatDocsLink("/channels/qqbot", "qqbot")}`, "QQ Bot");
10043
10097
  return cfg;
10044
10098
  }
10045
10099
  }
@@ -10052,7 +10106,7 @@ async function linkViaManual(cfg, prompter) {
10052
10106
  return next;
10053
10107
  }
10054
10108
  async function finalizeQQBotSetup(params) {
10055
- const accountId = params.accountId.trim() || import_setup.DEFAULT_ACCOUNT_ID;
10109
+ const accountId = params.accountId.trim() || DEFAULT_ACCOUNT_ID2;
10056
10110
  const configured = isConfigured(params.cfg, accountId);
10057
10111
  const mode = await params.prompter.select({
10058
10112
  message: configured ? "QQ \u5DF2\u7ED1\u5B9A\uFF0C\u9009\u62E9\u64CD\u4F5C" : "\u9009\u62E9 QQ \u7ED1\u5B9A\u65B9\u5F0F",
@@ -10077,7 +10131,7 @@ function applyAccountDefaults(cfg, accountId, userOpenid) {
10077
10131
  const qqbot = { ...next.channels?.qqbot ?? {} };
10078
10132
  const defaults = { streaming: true, dmPolicy: "allowlist" };
10079
10133
  if (userOpenid) defaults.allowFrom = [userOpenid];
10080
- if (accountId === import_setup.DEFAULT_ACCOUNT_ID) {
10134
+ if (accountId === DEFAULT_ACCOUNT_ID2) {
10081
10135
  Object.assign(qqbot, defaults);
10082
10136
  } else {
10083
10137
  const accounts = { ...qqbot.accounts ?? {} };
@@ -10089,11 +10143,10 @@ function applyAccountDefaults(cfg, accountId, userOpenid) {
10089
10143
  }
10090
10144
 
10091
10145
  // src/setup/surface.ts
10092
- var import_setup3 = require("openclaw/plugin-sdk/setup");
10093
10146
  var CHANNEL = "qqbot";
10094
10147
  var qqbotSetupWizard = {
10095
10148
  channel: CHANNEL,
10096
- status: (0, import_setup2.createStandardChannelSetupStatus)({
10149
+ status: createStandardChannelSetupStatus({
10097
10150
  channelLabel: "QQ Bot",
10098
10151
  configuredLabel: "configured",
10099
10152
  unconfiguredLabel: "needs AppID + AppSecret",
@@ -10109,7 +10162,10 @@ var qqbotSetupWizard = {
10109
10162
  credentials: [],
10110
10163
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
10111
10164
  finalize: (async ({ cfg, accountId, prompter, runtime: runtime2 }) => finalizeQQBotSetup({ cfg, accountId, prompter, runtime: runtime2 })),
10112
- disable: (cfg) => (0, import_setup3.setSetupChannelEnabled)(cfg, CHANNEL, false)
10165
+ disable: (cfg) => {
10166
+ setSetupChannelEnabled(cfg, CHANNEL, false);
10167
+ return cfg;
10168
+ }
10113
10169
  };
10114
10170
 
10115
10171
  // src/gateway/qqbot-gateway.ts
@@ -10196,7 +10252,7 @@ var REGISTRIES = [
10196
10252
  var CURRENT_VERSION = getPackageVersion();
10197
10253
  function fetchJson(url, timeoutMs) {
10198
10254
  return new Promise((resolve2, reject) => {
10199
- const req = import_node_https2.default.get(url, { timeout: timeoutMs, headers: { Accept: "application/json" } }, (res) => {
10255
+ const req4 = import_node_https2.default.get(url, { timeout: timeoutMs, headers: { Accept: "application/json" } }, (res) => {
10200
10256
  if (res.statusCode !== 200) {
10201
10257
  res.resume();
10202
10258
  reject(new Error(`HTTP ${res.statusCode} from ${url}`));
@@ -10214,9 +10270,9 @@ function fetchJson(url, timeoutMs) {
10214
10270
  }
10215
10271
  });
10216
10272
  });
10217
- req.on("error", reject);
10218
- req.on("timeout", () => {
10219
- req.destroy();
10273
+ req4.on("error", reject);
10274
+ req4.on("timeout", () => {
10275
+ req4.destroy();
10220
10276
  reject(new Error(`timeout fetching ${url}`));
10221
10277
  });
10222
10278
  });
@@ -10640,10 +10696,10 @@ function collectCandidateLogDirs(runtime2) {
10640
10696
  pushDir(import_node_path5.default.join(homeDir, name));
10641
10697
  pushDir(import_node_path5.default.join(homeDir, name, "logs"));
10642
10698
  }
10643
- const searchRoots = /* @__PURE__ */ new Set([homeDir, process.cwd(), import_node_path5.default.dirname(process.cwd())]);
10644
- if (process.env.APPDATA) searchRoots.add(process.env.APPDATA);
10645
- if (process.env.LOCALAPPDATA) searchRoots.add(process.env.LOCALAPPDATA);
10646
- for (const root of searchRoots) {
10699
+ const searchRoots2 = /* @__PURE__ */ new Set([homeDir, process.cwd(), import_node_path5.default.dirname(process.cwd())]);
10700
+ if (process.env.APPDATA) searchRoots2.add(process.env.APPDATA);
10701
+ if (process.env.LOCALAPPDATA) searchRoots2.add(process.env.LOCALAPPDATA);
10702
+ for (const root of searchRoots2) {
10647
10703
  try {
10648
10704
  const entries = import_node_fs5.default.readdirSync(root, { withFileTypes: true });
10649
10705
  for (const entry of entries) {
@@ -10955,8 +11011,8 @@ function botGroupAlways(account, getRuntime) {
10955
11011
  };
10956
11012
  }
10957
11013
 
10958
- // src/runtime-adapter/pairing-runtime.ts
10959
- var import_node_module2 = require("module");
11014
+ // src/adapter/pairing.ts
11015
+ var import_node_module3 = require("module");
10960
11016
  var import_node_path6 = __toESM(require("path"), 1);
10961
11017
  var _api;
10962
11018
  function getPairingApi() {
@@ -10966,14 +11022,14 @@ function getPairingApi() {
10966
11022
  }
10967
11023
  function loadPairingApi() {
10968
11024
  const currentFile = __filename;
10969
- const req = (0, import_node_module2.createRequire)(currentFile);
11025
+ const req4 = (0, import_node_module3.createRequire)(currentFile);
10970
11026
  const pluginRoot = import_node_path6.default.resolve(import_node_path6.default.dirname(currentFile), "..", "..");
10971
- const fs20 = req("node:fs");
11027
+ const fs21 = req4("node:fs");
10972
11028
  const tryLoad = (root) => {
10973
11029
  for (const rel of ["dist/plugin-sdk/conversation-runtime.js", "plugin-sdk/conversation-runtime.js"]) {
10974
11030
  const p2 = import_node_path6.default.join(root, rel);
10975
11031
  try {
10976
- if (fs20.existsSync(p2)) return req(p2);
11032
+ if (fs21.existsSync(p2)) return req4(p2);
10977
11033
  } catch {
10978
11034
  }
10979
11035
  }
@@ -10981,7 +11037,7 @@ function loadPairingApi() {
10981
11037
  };
10982
11038
  let mod = null;
10983
11039
  try {
10984
- const { findOpenclawRoot } = req(import_node_path6.default.join(pluginRoot, "scripts", "link-sdk-core.cjs"));
11040
+ const { findOpenclawRoot } = req4(import_node_path6.default.join(pluginRoot, "scripts", "link-sdk-core.cjs"));
10985
11041
  const root = findOpenclawRoot(pluginRoot);
10986
11042
  if (root) mod = tryLoad(root);
10987
11043
  } catch {
@@ -10990,7 +11046,7 @@ function loadPairingApi() {
10990
11046
  try {
10991
11047
  const entry = process.argv[1];
10992
11048
  if (entry) {
10993
- const realEntry = fs20.realpathSync(entry);
11049
+ const realEntry = fs21.realpathSync(entry);
10994
11050
  let dir = import_node_path6.default.dirname(realEntry);
10995
11051
  for (let i = 0; i < 6; i++) {
10996
11052
  mod = tryLoad(dir);
@@ -11098,7 +11154,7 @@ function buildCommandList(account, opts) {
11098
11154
  }
11099
11155
 
11100
11156
  // src/middleware/attachment.ts
11101
- var path16 = __toESM(require("path"), 1);
11157
+ var path17 = __toESM(require("path"), 1);
11102
11158
 
11103
11159
  // node_modules/.pnpm/@cxyhhhhh+qqbot-nodejs@1.0.2-dev.202607081646/node_modules/@cxyhhhhh/qqbot-nodejs/dist/protocol/utils/reply-limiter.js
11104
11160
  var DEFAULT_TTL_MS = 60 * 60 * 1e3;
@@ -11258,9 +11314,6 @@ function isVoiceAttachment(att) {
11258
11314
  return [".amr", ".silk", ".slk", ".slac"].includes(ext);
11259
11315
  }
11260
11316
 
11261
- // src/middleware/attachment.ts
11262
- var import_media_runtime = require("openclaw/plugin-sdk/media-runtime");
11263
-
11264
11317
  // src/utils/stt.ts
11265
11318
  var fs17 = __toESM(require("fs"), 1);
11266
11319
  var path15 = __toESM(require("path"), 1);
@@ -11379,6 +11432,78 @@ function formatDuration2(seconds) {
11379
11432
  return `${mins}:${secs.toString().padStart(2, "0")}`;
11380
11433
  }
11381
11434
 
11435
+ // src/adapter/media.ts
11436
+ var import_node_module4 = require("module");
11437
+ var dns = __toESM(require("dns"), 1);
11438
+ var path16 = __toESM(require("path"), 1);
11439
+ var fs18 = __toESM(require("fs"), 1);
11440
+ var crypto4 = __toESM(require("crypto"), 1);
11441
+ var req3 = (0, import_node_module4.createRequire)(__filename);
11442
+ var _save;
11443
+ function downloadRemoteMedia(opts) {
11444
+ if (_save === void 0) {
11445
+ try {
11446
+ const mod = req3("openclaw/plugin-sdk/media-runtime");
11447
+ _save = mod.saveRemoteMedia;
11448
+ } catch {
11449
+ _save = null;
11450
+ }
11451
+ }
11452
+ return _save ? _save(opts) : downloadViaFetch(opts);
11453
+ }
11454
+ var PRIVATE_RANGES = [
11455
+ [0x0A000000n, 8],
11456
+ // 10.0.0.0/8
11457
+ [0xAC100000n, 12],
11458
+ // 172.16.0.0/12
11459
+ [0xC0A80000n, 16],
11460
+ // 192.168.0.0/16
11461
+ [0x7F000000n, 8],
11462
+ // 127.0.0.0/8
11463
+ [0xA9FE0000n, 16],
11464
+ // 169.254.0.0/16
11465
+ [0xE0000000n, 4]
11466
+ // 224.0.0.0/4 (multicast)
11467
+ ];
11468
+ function ipToBigInt(ip) {
11469
+ return ip.split(".").reduce((acc, octet) => acc << 8n | BigInt(Number(octet)), 0n);
11470
+ }
11471
+ function isPrivateIP(ip) {
11472
+ const val = ipToBigInt(ip);
11473
+ return PRIVATE_RANGES.some(([mask, prefix]) => val >> 32n - BigInt(prefix) === mask >> 32n - BigInt(prefix));
11474
+ }
11475
+ async function assertSafeHostname(hostname) {
11476
+ const addresses = await dns.promises.resolve4(hostname).catch(() => []);
11477
+ if (addresses.length === 0) throw new Error(`DNS resolution failed: ${hostname}`);
11478
+ for (const addr of addresses) {
11479
+ if (isPrivateIP(addr)) {
11480
+ throw new Error(`SSRF blocked: ${hostname} resolves to private IP ${addr}`);
11481
+ }
11482
+ }
11483
+ }
11484
+ async function downloadViaFetch(opts) {
11485
+ const parsed = new URL(opts.url);
11486
+ if (parsed.protocol !== "https:") {
11487
+ throw new Error(`Only HTTPS allowed: ${parsed.protocol}`);
11488
+ }
11489
+ await assertSafeHostname(parsed.hostname);
11490
+ const dir = getQQBotMediaDir(opts.subdir ?? "downloads");
11491
+ if (!fs18.existsSync(dir)) fs18.mkdirSync(dir, { recursive: true });
11492
+ const resp = await fetch(opts.url, {
11493
+ signal: AbortSignal.timeout(opts.timeoutMs ?? 12e4)
11494
+ });
11495
+ if (!resp.ok) throw new Error(`Download HTTP ${resp.status}`);
11496
+ const maxBytes = opts.maxBytes ?? 500 * 1024 * 1024;
11497
+ const buf = Buffer.from(await resp.arrayBuffer());
11498
+ if (buf.length > maxBytes) throw new Error(`Download exceeds ${(maxBytes / 1024 / 1024).toFixed(0)}MB`);
11499
+ const ext = opts.originalFilename ? path16.extname(opts.originalFilename) || ".bin" : ".bin";
11500
+ const name = opts.originalFilename ? path16.basename(opts.originalFilename, path16.extname(opts.originalFilename)) : "download";
11501
+ const rand = crypto4.randomBytes(4).toString("hex");
11502
+ const filePath = path16.join(dir, `${name}_${Date.now()}_${rand}${ext}`);
11503
+ fs18.writeFileSync(filePath, buf);
11504
+ return { path: filePath };
11505
+ }
11506
+
11382
11507
  // src/middleware/attachment.ts
11383
11508
  function attachmentProcessor(opts) {
11384
11509
  return async (ctx, next) => {
@@ -11494,7 +11619,7 @@ async function processVoiceAttachment(att, sttCfg, audioPolicy, log4) {
11494
11619
  if (silkUrl) {
11495
11620
  const silkPath = await downloadMediaFile(silkUrl, att.filename, log4);
11496
11621
  if (silkPath) {
11497
- const ext = path16.extname(silkPath).toLowerCase();
11622
+ const ext = path17.extname(silkPath).toLowerCase();
11498
11623
  if (audioPolicy.sttDirectFormats.includes(ext)) {
11499
11624
  localPath = silkPath;
11500
11625
  } else {
@@ -11567,12 +11692,12 @@ async function downloadMediaFile(url, filename, log4) {
11567
11692
  return null;
11568
11693
  }
11569
11694
  try {
11570
- const result = await (0, import_media_runtime.saveRemoteMedia)({
11695
+ const result = await downloadRemoteMedia({
11571
11696
  url,
11572
11697
  subdir: "qqbot/downloads",
11573
11698
  originalFilename: filename,
11574
11699
  maxBytes: 500 * 1024 * 1024,
11575
- timeoutMs: 6e4
11700
+ timeoutMs: 12e4
11576
11701
  });
11577
11702
  log4?.debug?.(`Downloaded: ${result.path}`);
11578
11703
  return result.path;
@@ -12301,10 +12426,6 @@ async function dispatchToOpenClaw(ctx, msg, account, runtime2, log4) {
12301
12426
  const adapters = getAdapters(runtime2, dlog);
12302
12427
  const envelope = buildEnvelope2(ctx, msg, account);
12303
12428
  dlog?.debug(`received sender=${envelope.senderId} scope=${envelope.chatScope} msgId=${envelope.messageId}`);
12304
- if (!adapters.inboundRun) {
12305
- dlog?.error(`runtime adapter inboundRun not available (openclaw=${adapters.version})`);
12306
- return;
12307
- }
12308
12429
  if (!adapters.dispatchReply) {
12309
12430
  dlog?.error(`runtime adapter dispatchReply not available (openclaw=${adapters.version})`);
12310
12431
  return;
@@ -12400,127 +12521,160 @@ async function dispatchToOpenClaw(ctx, msg, account, runtime2, log4) {
12400
12521
  if (streamingController) {
12401
12522
  dlog?.debug(`streaming enabled for ${envelope.senderId}`);
12402
12523
  }
12403
- await adapters.inboundRun({
12404
- channel: "qqbot",
12405
- accountId: route.accountId,
12406
- raw: envelope,
12407
- adapter: {
12408
- ingest: (raw) => ({
12409
- id: envelope.messageId,
12410
- rawText: assembled.rawBody,
12411
- textForAgent: assembled.agentBody,
12412
- textForCommands: assembled.rawBody,
12413
- raw
12414
- }),
12415
- resolveTurn: (_input, _eventClass, _preflight) => ({
12416
- channel: "qqbot",
12417
- accountId: route.accountId,
12418
- routeSessionKey: route.sessionKey,
12419
- storePath,
12420
- ctxPayload,
12421
- recordInboundSession: adapters.recordInboundSession,
12422
- record: {
12423
- onRecordError: (err) => {
12424
- dlog?.error(`Session record error: ${err}`);
12524
+ if (!adapters.inboundRun) {
12525
+ if (adapters.recordInboundSession) {
12526
+ try {
12527
+ await adapters.recordInboundSession({
12528
+ storePath,
12529
+ sessionKey: route.sessionKey,
12530
+ ctx: ctxPayload
12531
+ });
12532
+ } catch {
12533
+ }
12534
+ }
12535
+ await adapters.dispatchReply({
12536
+ ctx: ctxPayload,
12537
+ cfg,
12538
+ dispatcherOptions: {
12539
+ deliver: async (payload, info) => {
12540
+ await deliverReply(payload, info, deliverCtx);
12541
+ }
12542
+ },
12543
+ ...streamingController ? {
12544
+ replyOptions: {
12545
+ onPartialReply: async (p2) => {
12546
+ if (p2.text) await streamingController.onPartialReply(p2.text);
12425
12547
  }
12426
- },
12427
- runDispatch: () => {
12428
- let blockDelivered = false;
12429
- const deliveredMediaUrls = /* @__PURE__ */ new Set();
12430
- return adapters.dispatchReply({
12431
- ctx: ctxPayload,
12432
- cfg,
12433
- dispatcherOptions: {
12434
- deliver: async (payload, info) => {
12435
- try {
12436
- const kind = info?.kind;
12437
- dlog?.debug(`deliver kind=${kind ?? "none"} textLen=${payload.text?.length ?? 0} audioAsVoice=${payload.audioAsVoice ?? false} mediaUrl=${payload.mediaUrl?.slice(0, 60) ?? "none"} mediaUrls=${payload.mediaUrls?.length ?? 0}`);
12438
- if (kind === "block") {
12439
- if (payload.audioAsVoice) {
12440
- await deliverReply(payload, info, deliverCtx);
12441
- } else {
12442
- const urls = payload.mediaUrls?.length ? payload.mediaUrls : payload.mediaUrl ? [payload.mediaUrl] : [];
12443
- for (const url of urls) {
12548
+ }
12549
+ } : {}
12550
+ });
12551
+ if (streamingController && !streamingController.isTerminal) {
12552
+ await streamingController.finalize();
12553
+ }
12554
+ if (debouncer) await debouncer.flushAll();
12555
+ } else {
12556
+ await adapters.inboundRun({
12557
+ channel: "qqbot",
12558
+ accountId: route.accountId,
12559
+ raw: envelope,
12560
+ adapter: {
12561
+ ingest: (raw) => ({
12562
+ id: envelope.messageId,
12563
+ rawText: assembled.rawBody,
12564
+ textForAgent: assembled.agentBody,
12565
+ textForCommands: assembled.rawBody,
12566
+ raw
12567
+ }),
12568
+ resolveTurn: (_input, _eventClass, _preflight) => ({
12569
+ channel: "qqbot",
12570
+ accountId: route.accountId,
12571
+ routeSessionKey: route.sessionKey,
12572
+ storePath,
12573
+ ctxPayload,
12574
+ recordInboundSession: adapters.recordInboundSession,
12575
+ record: {
12576
+ onRecordError: (err) => {
12577
+ dlog?.error(`Session record error: ${err}`);
12578
+ }
12579
+ },
12580
+ runDispatch: () => {
12581
+ let blockDelivered = false;
12582
+ const deliveredMediaUrls = /* @__PURE__ */ new Set();
12583
+ return adapters.dispatchReply({
12584
+ ctx: ctxPayload,
12585
+ cfg,
12586
+ dispatcherOptions: {
12587
+ deliver: async (payload, info) => {
12588
+ try {
12589
+ const kind = info?.kind;
12590
+ dlog?.debug(`deliver kind=${kind ?? "none"} textLen=${payload.text?.length ?? 0} audioAsVoice=${payload.audioAsVoice ?? false} mediaUrl=${payload.mediaUrl?.slice(0, 60) ?? "none"} mediaUrls=${payload.mediaUrls?.length ?? 0}`);
12591
+ if (kind === "block") {
12592
+ if (payload.audioAsVoice) {
12593
+ await deliverReply(payload, info, deliverCtx);
12594
+ } else {
12595
+ const urls = payload.mediaUrls?.length ? payload.mediaUrls : payload.mediaUrl ? [payload.mediaUrl] : [];
12596
+ for (const url of urls) {
12597
+ try {
12598
+ await sendMedia2({
12599
+ to: deliverCtx.qualifiedTarget,
12600
+ source: url,
12601
+ text: "",
12602
+ replyToId: deliverCtx.replyToId,
12603
+ accountId: deliverCtx.accountId,
12604
+ log: deliverCtx.log,
12605
+ agentId: deliverCtx.agentId
12606
+ });
12607
+ deliveredMediaUrls.add(url);
12608
+ } catch (err) {
12609
+ dlog?.error(`block media failed: ${err instanceof Error ? err.message : String(err)}`);
12610
+ }
12611
+ }
12612
+ }
12613
+ }
12614
+ if (streamingController && !streamingController.shouldFallbackToStatic) {
12615
+ if (kind !== "block") {
12616
+ await streamingController.finalize();
12617
+ }
12618
+ if (!streamingController.shouldFallbackToStatic) {
12619
+ if (kind === "block") return;
12620
+ return;
12621
+ }
12622
+ dlog?.warn(`streaming fallback to static`);
12623
+ }
12624
+ if (kind === "block") {
12625
+ blockDelivered = true;
12626
+ } else if (kind === "final" && blockDelivered) {
12627
+ return;
12628
+ }
12629
+ if (kind === "tool") {
12630
+ const toolMediaUrls = [];
12631
+ if (payload.mediaUrls?.length) toolMediaUrls.push(...payload.mediaUrls);
12632
+ if (payload.mediaUrl && !toolMediaUrls.includes(payload.mediaUrl)) toolMediaUrls.push(payload.mediaUrl);
12633
+ const newUrls = toolMediaUrls.filter((u2) => !deliveredMediaUrls.has(u2));
12634
+ for (const mediaUrl of newUrls) {
12444
12635
  try {
12445
12636
  await sendMedia2({
12446
12637
  to: deliverCtx.qualifiedTarget,
12447
- source: url,
12638
+ source: mediaUrl,
12448
12639
  text: "",
12449
12640
  replyToId: deliverCtx.replyToId,
12450
12641
  accountId: deliverCtx.accountId,
12451
12642
  log: deliverCtx.log,
12452
12643
  agentId: deliverCtx.agentId
12453
12644
  });
12454
- deliveredMediaUrls.add(url);
12645
+ deliveredMediaUrls.add(mediaUrl);
12646
+ dlog?.info(`tool media forwarded url=${mediaUrl.slice(0, 60)}`);
12455
12647
  } catch (err) {
12456
- dlog?.error(`block media failed: ${err instanceof Error ? err.message : String(err)}`);
12648
+ dlog?.error(`tool media forward failed: ${err instanceof Error ? err.message : String(err)}`);
12457
12649
  }
12458
12650
  }
12459
- }
12460
- }
12461
- if (streamingController && !streamingController.shouldFallbackToStatic) {
12462
- if (kind !== "block") {
12463
- await streamingController.finalize();
12464
- }
12465
- if (!streamingController.shouldFallbackToStatic) {
12466
- if (kind === "block") return;
12467
12651
  return;
12468
12652
  }
12469
- dlog?.warn(`streaming fallback to static`);
12470
- }
12471
- if (kind === "block") {
12472
- blockDelivered = true;
12473
- } else if (kind === "final" && blockDelivered) {
12474
- return;
12475
- }
12476
- if (kind === "tool") {
12477
- const toolMediaUrls = [];
12478
- if (payload.mediaUrls?.length) toolMediaUrls.push(...payload.mediaUrls);
12479
- if (payload.mediaUrl && !toolMediaUrls.includes(payload.mediaUrl)) toolMediaUrls.push(payload.mediaUrl);
12480
- const newUrls = toolMediaUrls.filter((u2) => !deliveredMediaUrls.has(u2));
12481
- for (const mediaUrl of newUrls) {
12482
- try {
12483
- await sendMedia2({
12484
- to: deliverCtx.qualifiedTarget,
12485
- source: mediaUrl,
12486
- text: "",
12487
- replyToId: deliverCtx.replyToId,
12488
- accountId: deliverCtx.accountId,
12489
- log: deliverCtx.log,
12490
- agentId: deliverCtx.agentId
12491
- });
12492
- deliveredMediaUrls.add(mediaUrl);
12493
- dlog?.info(`tool media forwarded url=${mediaUrl.slice(0, 60)}`);
12494
- } catch (err) {
12495
- dlog?.error(`tool media forward failed: ${err instanceof Error ? err.message : String(err)}`);
12496
- }
12497
- }
12498
- return;
12653
+ const filteredPayload = deliveredMediaUrls.size > 0 ? {
12654
+ ...payload,
12655
+ mediaUrl: payload.mediaUrl && !deliveredMediaUrls.has(payload.mediaUrl) ? payload.mediaUrl : void 0,
12656
+ mediaUrls: payload.mediaUrls?.filter((u2) => !deliveredMediaUrls.has(u2))
12657
+ } : payload;
12658
+ await deliverReply(filteredPayload, info, deliverCtx);
12659
+ } catch (err) {
12660
+ dlog?.error(`error: ${err instanceof Error ? err.message : String(err)}`);
12499
12661
  }
12500
- const filteredPayload = deliveredMediaUrls.size > 0 ? {
12501
- ...payload,
12502
- mediaUrl: payload.mediaUrl && !deliveredMediaUrls.has(payload.mediaUrl) ? payload.mediaUrl : void 0,
12503
- mediaUrls: payload.mediaUrls?.filter((u2) => !deliveredMediaUrls.has(u2))
12504
- } : payload;
12505
- await deliverReply(filteredPayload, info, deliverCtx);
12506
- } catch (err) {
12507
- dlog?.error(`error: ${err instanceof Error ? err.message : String(err)}`);
12508
12662
  }
12663
+ },
12664
+ replyOptions: {
12665
+ runId: envelope.messageId,
12666
+ ...streamingController ? {
12667
+ onPartialReply: async (p2) => {
12668
+ if (p2.text) await streamingController.onPartialReply(p2.text);
12669
+ }
12670
+ } : {}
12509
12671
  }
12510
- },
12511
- replyOptions: {
12512
- runId: envelope.messageId,
12513
- ...streamingController ? {
12514
- onPartialReply: async (p2) => {
12515
- if (p2.text) await streamingController.onPartialReply(p2.text);
12516
- }
12517
- } : {}
12518
- }
12519
- });
12520
- }
12521
- })
12522
- }
12523
- });
12672
+ });
12673
+ }
12674
+ })
12675
+ }
12676
+ });
12677
+ }
12524
12678
  dlog?.debug(`inboundRun completed sessionKey=${route.sessionKey}`);
12525
12679
  if (envelope.chatScope === "group") {
12526
12680
  clearGroupHistory(envelope.groupId ?? envelope.senderId);
@@ -12551,26 +12705,25 @@ function createStreamingController(envelope, account, log4) {
12551
12705
  });
12552
12706
  }
12553
12707
 
12554
- // src/runtime-adapter/gateway-runtime.ts
12555
- var import_node_module3 = require("module");
12708
+ // src/adapter/gateway.ts
12709
+ var import_node_module5 = require("module");
12556
12710
  var import_node_path8 = __toESM(require("path"), 1);
12557
12711
  function loadApprovalGatewayRuntime() {
12558
- const currentFile = __filename;
12559
- const req = (0, import_node_module3.createRequire)(currentFile);
12560
- const pluginRoot = import_node_path8.default.resolve(import_node_path8.default.dirname(currentFile), "..", "..");
12561
- const fs20 = req("node:fs");
12712
+ const req4 = (0, import_node_module5.createRequire)(__filename);
12713
+ const pluginRoot = import_node_path8.default.resolve(import_node_path8.default.dirname(__filename), "..", "..");
12714
+ const fs21 = req4("node:fs");
12562
12715
  const tryLoadFromRoot = (root) => {
12563
12716
  for (const rel of ["dist/plugin-sdk/gateway-runtime.js", "plugin-sdk/gateway-runtime.js"]) {
12564
12717
  const p2 = import_node_path8.default.join(root, rel);
12565
12718
  try {
12566
- if (fs20.existsSync(p2)) return req(p2);
12719
+ if (fs21.existsSync(p2)) return req4(p2);
12567
12720
  } catch {
12568
12721
  }
12569
12722
  }
12570
12723
  return null;
12571
12724
  };
12572
12725
  try {
12573
- const { findOpenclawRoot } = req(import_node_path8.default.join(pluginRoot, "scripts", "link-sdk-core.cjs"));
12726
+ const { findOpenclawRoot } = req4(import_node_path8.default.join(pluginRoot, "scripts", "link-sdk-core.cjs"));
12574
12727
  const root = findOpenclawRoot(pluginRoot);
12575
12728
  if (root) {
12576
12729
  const mod = tryLoadFromRoot(root);
@@ -12581,7 +12734,7 @@ function loadApprovalGatewayRuntime() {
12581
12734
  try {
12582
12735
  const entry = process.argv[1];
12583
12736
  if (entry) {
12584
- const realEntry = fs20.realpathSync(entry);
12737
+ const realEntry = fs21.realpathSync(entry);
12585
12738
  let dir = import_node_path8.default.dirname(realEntry);
12586
12739
  for (let i = 0; i < 6; i++) {
12587
12740
  const mod = tryLoadFromRoot(dir);
@@ -12864,16 +13017,16 @@ function getApprovalHandler(accountId) {
12864
13017
  }
12865
13018
 
12866
13019
  // src/features/proactive.ts
12867
- var fs18 = __toESM(require("fs"), 1);
12868
- var path18 = __toESM(require("path"), 1);
13020
+ var fs19 = __toESM(require("fs"), 1);
13021
+ var path19 = __toESM(require("path"), 1);
12869
13022
  var log2 = createPluginLogger({ prefix: "[proactive]" });
12870
13023
  var STORAGE_DIR = getQQBotDataDir("data");
12871
- var KNOWN_USERS_FILE = path18.join(STORAGE_DIR, "known-users.json");
13024
+ var KNOWN_USERS_FILE = path19.join(STORAGE_DIR, "known-users.json");
12872
13025
  var knownUsersCache = null;
12873
13026
  var cacheLastModified = 0;
12874
13027
  function ensureStorageDir() {
12875
- if (!fs18.existsSync(STORAGE_DIR)) {
12876
- fs18.mkdirSync(STORAGE_DIR, { recursive: true });
13028
+ if (!fs19.existsSync(STORAGE_DIR)) {
13029
+ fs19.mkdirSync(STORAGE_DIR, { recursive: true });
12877
13030
  }
12878
13031
  }
12879
13032
  function getUserKey(type, openid, accountId) {
@@ -12882,7 +13035,7 @@ function getUserKey(type, openid, accountId) {
12882
13035
  function loadKnownUsers() {
12883
13036
  if (knownUsersCache !== null) {
12884
13037
  try {
12885
- const stat = fs18.statSync(KNOWN_USERS_FILE);
13038
+ const stat = fs19.statSync(KNOWN_USERS_FILE);
12886
13039
  if (stat.mtimeMs <= cacheLastModified) {
12887
13040
  return knownUsersCache;
12888
13041
  }
@@ -12892,14 +13045,14 @@ function loadKnownUsers() {
12892
13045
  }
12893
13046
  const users = /* @__PURE__ */ new Map();
12894
13047
  try {
12895
- if (fs18.existsSync(KNOWN_USERS_FILE)) {
12896
- const data = fs18.readFileSync(KNOWN_USERS_FILE, "utf-8");
13048
+ if (fs19.existsSync(KNOWN_USERS_FILE)) {
13049
+ const data = fs19.readFileSync(KNOWN_USERS_FILE, "utf-8");
12897
13050
  const parsed = JSON.parse(data);
12898
13051
  for (const user of parsed) {
12899
13052
  const key = getUserKey(user.type, user.openid, user.accountId);
12900
13053
  users.set(key, user);
12901
13054
  }
12902
- cacheLastModified = fs18.statSync(KNOWN_USERS_FILE).mtimeMs;
13055
+ cacheLastModified = fs19.statSync(KNOWN_USERS_FILE).mtimeMs;
12903
13056
  }
12904
13057
  } catch (err) {
12905
13058
  log2.error(`Failed to load known users: ${err}`);
@@ -12911,7 +13064,7 @@ function saveKnownUsers(users) {
12911
13064
  try {
12912
13065
  ensureStorageDir();
12913
13066
  const data = Array.from(users.values());
12914
- fs18.writeFileSync(KNOWN_USERS_FILE, JSON.stringify(data, null, 2), "utf-8");
13067
+ fs19.writeFileSync(KNOWN_USERS_FILE, JSON.stringify(data, null, 2), "utf-8");
12915
13068
  cacheLastModified = Date.now();
12916
13069
  knownUsersCache = users;
12917
13070
  } catch (err) {
@@ -13106,7 +13259,7 @@ function setGroupRequireMention(runtime2, accountId, groupOpenid, requireMention
13106
13259
  }) ?? Promise.resolve();
13107
13260
  }
13108
13261
 
13109
- // src/runtime-adapter/webhook-adapter.ts
13262
+ // src/adapter/webhook.ts
13110
13263
  var sharedTargets = /* @__PURE__ */ new Map();
13111
13264
  var _routeUnregisters = /* @__PURE__ */ new Map();
13112
13265
  function createPluginWebhookAdapter(params) {
@@ -13114,13 +13267,13 @@ function createPluginWebhookAdapter(params) {
13114
13267
  let storedPath = "";
13115
13268
  const accountId = params.account.accountId;
13116
13269
  return {
13117
- async listen(_port, path20, handler) {
13270
+ async listen(_port, path21, handler) {
13118
13271
  const ingress = await import("openclaw/plugin-sdk/webhook-ingress").catch(() => null);
13119
13272
  if (!ingress?.registerWebhookTargetWithPluginRoute) {
13120
13273
  params.log.error("Webhook ingress not available");
13121
13274
  return;
13122
13275
  }
13123
- const webhookPath = storedPath = path20 && path20 !== "/" ? path20 : params.account.config.webhook?.path ?? "/qqbot/webhook";
13276
+ const webhookPath = storedPath = path21 && path21 !== "/" ? path21 : params.account.config.webhook?.path ?? "/qqbot/webhook";
13124
13277
  const existing = sharedTargets.get(webhookPath);
13125
13278
  if (existing) {
13126
13279
  const dupIdx = existing.findIndex((t) => t.accountId === accountId);
@@ -13167,16 +13320,16 @@ function createPluginWebhookAdapter(params) {
13167
13320
  }
13168
13321
  };
13169
13322
  }
13170
- function createSharedHandler(path20, log4) {
13171
- return async (req, res) => {
13323
+ function createSharedHandler(path21, log4) {
13324
+ return async (req4, res) => {
13172
13325
  try {
13173
13326
  const ingress = await import("openclaw/plugin-sdk/webhook-ingress").catch(() => null);
13174
13327
  if (!ingress?.withResolvedWebhookRequestPipeline) {
13175
- await handleSimple(req, res, path20, log4);
13328
+ await handleSimple(req4, res, path21, log4);
13176
13329
  return;
13177
13330
  }
13178
13331
  await ingress.withResolvedWebhookRequestPipeline({
13179
- req,
13332
+ req: req4,
13180
13333
  res,
13181
13334
  targetsByPath: sharedTargets,
13182
13335
  rateLimiter: ingress.createFixedWindowRateLimiter?.({
@@ -13191,7 +13344,7 @@ function createSharedHandler(path20, log4) {
13191
13344
  requireJsonContentType: true,
13192
13345
  handle: async ({ targets }) => {
13193
13346
  const bodyResult = await ingress.readWebhookBodyOrReject({
13194
- req,
13347
+ req: req4,
13195
13348
  res,
13196
13349
  maxBytes: 1048576,
13197
13350
  timeoutMs: 3e4
@@ -13213,25 +13366,25 @@ function createSharedHandler(path20, log4) {
13213
13366
  if (payload.op === 13) {
13214
13367
  const t = targets[0];
13215
13368
  if (!t) {
13216
- log4.warn?.(`[webhook] op:13 no target on ${path20}`);
13369
+ log4.warn?.(`[webhook] op:13 no target on ${path21}`);
13217
13370
  res.statusCode = 500;
13218
13371
  res.end(JSON.stringify({ error: "no target" }));
13219
13372
  return;
13220
13373
  }
13221
- const h3 = resolveTargetHandler(path20, t.accountId);
13374
+ const h3 = resolveTargetHandler(path21, t.accountId);
13222
13375
  if (!h3) {
13223
13376
  log4.warn?.(`[webhook] op:13 no handler for ${t.accountId}`);
13224
13377
  res.statusCode = 500;
13225
13378
  res.end(JSON.stringify({ error: "no handler" }));
13226
13379
  return;
13227
13380
  }
13228
- await delegateToHandler(h3, req, res, rawBody);
13381
+ await delegateToHandler(h3, req4, res, rawBody);
13229
13382
  return;
13230
13383
  }
13231
- const timestamp = getHeader2(req, "x-signature-timestamp") ?? "";
13232
- const signature = getHeader2(req, "x-signature-ed25519") ?? "";
13384
+ const timestamp = getHeader2(req4, "x-signature-timestamp") ?? "";
13385
+ const signature = getHeader2(req4, "x-signature-ed25519") ?? "";
13233
13386
  if (!timestamp || !signature) {
13234
- log4.warn?.(`[webhook] missing signature headers on ${req.url}`);
13387
+ log4.warn?.(`[webhook] missing signature headers on ${req4.url}`);
13235
13388
  res.statusCode = 401;
13236
13389
  res.end(JSON.stringify({ error: "missing signature" }));
13237
13390
  return;
@@ -13249,17 +13402,17 @@ function createSharedHandler(path20, log4) {
13249
13402
  unauthorizedMessage: JSON.stringify({ error: "invalid signature" })
13250
13403
  });
13251
13404
  if (!matched) {
13252
- log4.warn?.(`[webhook] signature mismatch on ${path20} (${targets.length} target(s))`);
13405
+ log4.warn?.(`[webhook] signature mismatch on ${path21} (${targets.length} target(s))`);
13253
13406
  return;
13254
13407
  }
13255
- const h2 = resolveTargetHandler(path20, matched.accountId);
13408
+ const h2 = resolveTargetHandler(path21, matched.accountId);
13256
13409
  if (!h2) {
13257
13410
  log4.error?.(`[webhook] no handler for matched target ${matched.accountId}`);
13258
13411
  res.statusCode = 500;
13259
13412
  res.end(JSON.stringify({ error: "no handler" }));
13260
13413
  return;
13261
13414
  }
13262
- await delegateToHandler(h2, req, res, rawBody);
13415
+ await delegateToHandler(h2, req4, res, rawBody);
13263
13416
  }
13264
13417
  });
13265
13418
  } catch (err) {
@@ -13272,12 +13425,12 @@ function createSharedHandler(path20, log4) {
13272
13425
  }
13273
13426
  };
13274
13427
  }
13275
- function resolveTargetHandler(path20, accountId) {
13276
- return sharedTargets.get(path20)?.find((t) => t.accountId === accountId)?.handler;
13428
+ function resolveTargetHandler(path21, accountId) {
13429
+ return sharedTargets.get(path21)?.find((t) => t.accountId === accountId)?.handler;
13277
13430
  }
13278
- async function delegateToHandler(handler, req, res, rawBody) {
13431
+ async function delegateToHandler(handler, req4, res, rawBody) {
13279
13432
  const headers = {};
13280
- for (const [k, v] of Object.entries(req.headers)) {
13433
+ for (const [k, v] of Object.entries(req4.headers)) {
13281
13434
  headers[k.toLowerCase()] = v;
13282
13435
  }
13283
13436
  const resp = await handler({ body: rawBody, headers });
@@ -13287,9 +13440,9 @@ async function delegateToHandler(handler, req, res, rawBody) {
13287
13440
  }
13288
13441
  res.end(resp.body);
13289
13442
  }
13290
- async function handleSimple(req, res, path20, log4) {
13443
+ async function handleSimple(req4, res, path21, log4) {
13291
13444
  try {
13292
- const ct = String(req.headers["content-type"] ?? "");
13445
+ const ct = String(req4.headers["content-type"] ?? "");
13293
13446
  if (!ct.includes("application/json")) {
13294
13447
  res.statusCode = 400;
13295
13448
  res.end(JSON.stringify({ error: "unsupported content type" }));
@@ -13297,7 +13450,7 @@ async function handleSimple(req, res, path20, log4) {
13297
13450
  }
13298
13451
  const chunks = [];
13299
13452
  let total = 0;
13300
- for await (const chunk of req) {
13453
+ for await (const chunk of req4) {
13301
13454
  const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
13302
13455
  total += buf.length;
13303
13456
  if (total > 1048576) {
@@ -13308,9 +13461,9 @@ async function handleSimple(req, res, path20, log4) {
13308
13461
  chunks.push(buf);
13309
13462
  }
13310
13463
  const rawBody = Buffer.concat(chunks);
13311
- const entries = sharedTargets.get(path20) ?? [];
13464
+ const entries = sharedTargets.get(path21) ?? [];
13312
13465
  for (const entry of entries) {
13313
- const resp = await entry.handler({ body: rawBody, headers: mapHeaders(req) });
13466
+ const resp = await entry.handler({ body: rawBody, headers: mapHeaders(req4) });
13314
13467
  if (resp.status < 400) {
13315
13468
  res.statusCode = resp.status;
13316
13469
  if (resp.headers) for (const [k, v] of Object.entries(resp.headers)) res.setHeader(k, v);
@@ -13328,13 +13481,13 @@ async function handleSimple(req, res, path20, log4) {
13328
13481
  }
13329
13482
  }
13330
13483
  }
13331
- function mapHeaders(req) {
13484
+ function mapHeaders(req4) {
13332
13485
  const h2 = {};
13333
- for (const [k, v] of Object.entries(req.headers ?? {})) h2[k.toLowerCase()] = v;
13486
+ for (const [k, v] of Object.entries(req4.headers ?? {})) h2[k.toLowerCase()] = v;
13334
13487
  return h2;
13335
13488
  }
13336
- function getHeader2(req, key) {
13337
- const val = req.headers[key];
13489
+ function getHeader2(req4, key) {
13490
+ const val = req4.headers[key];
13338
13491
  return Array.isArray(val) ? val[0] : val;
13339
13492
  }
13340
13493
 
@@ -14106,10 +14259,10 @@ function json(data) {
14106
14259
  details: data
14107
14260
  };
14108
14261
  }
14109
- function validatePath(path20) {
14110
- if (!path20.startsWith("/")) return "path \u5FC5\u987B\u4EE5 / \u5F00\u5934";
14111
- if (path20.includes("..") || path20.includes("//")) return "path \u4E0D\u5141\u8BB8\u5305\u542B .. \u6216 //";
14112
- if (!/^\/[a-zA-Z0-9\-._~:@!$&'()*+,;=/%]+$/.test(path20) && path20 !== "/") {
14262
+ function validatePath(path21) {
14263
+ if (!path21.startsWith("/")) return "path \u5FC5\u987B\u4EE5 / \u5F00\u5934";
14264
+ if (path21.includes("..") || path21.includes("//")) return "path \u4E0D\u5141\u8BB8\u5305\u542B .. \u6216 //";
14265
+ if (!/^\/[a-zA-Z0-9\-._~:@!$&'()*+,;=/%]+$/.test(path21) && path21 !== "/") {
14113
14266
  return "path \u5305\u542B\u975E\u6CD5\u5B57\u7B26";
14114
14267
  }
14115
14268
  return null;
@@ -14384,22 +14537,19 @@ function registerRemindTool(api) {
14384
14537
  );
14385
14538
  }
14386
14539
 
14387
- // src/runtime-adapter/contract-check.ts
14540
+ // src/adapter/contract.ts
14388
14541
  var log3 = createPluginLogger({ prefix: "[contract]", forceConsole: true });
14389
14542
  var REQUIRED = [
14390
- {
14391
- name: "channel.inbound.run",
14392
- probe: (rt) => {
14393
- const c = rt.channel;
14394
- return typeof c?.inbound?.run === "function" || typeof c?.turn?.run === "function";
14395
- }
14396
- },
14397
14543
  {
14398
14544
  name: "channel.reply.dispatchReplyWithBufferedBlockDispatcher",
14399
14545
  probe: (rt) => typeof rt.channel?.reply?.dispatchReplyWithBufferedBlockDispatcher === "function"
14400
14546
  }
14401
14547
  ];
14402
14548
  var OPTIONAL = [
14549
+ { name: "channel.inbound.run (degraded)", probe: (rt) => {
14550
+ const c = rt.channel;
14551
+ return typeof c?.inbound?.run === "function" || typeof c?.turn?.run === "function";
14552
+ } },
14403
14553
  { name: "channel.inbound.buildContext", probe: (rt) => typeof rt.channel?.inbound?.buildContext === "function" },
14404
14554
  { name: "channel.reply.formatAgentEnvelope", probe: (rt) => typeof rt.channel?.reply?.formatAgentEnvelope === "function" },
14405
14555
  { name: "channel.text.chunkMarkdownText", probe: (rt) => typeof rt.channel?.text?.chunkMarkdownText === "function" },