@searchfe/openclaw-baiduapp 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -4048,18 +4048,17 @@ var NEVER = INVALID;
4048
4048
 
4049
4049
  // src/config.ts
4050
4050
  var DEFAULT_ACCOUNT_ID = "default";
4051
+ var DEFAULT_API_BASE = "https://claw.baidu.com";
4051
4052
  var BaiduAppAccountSchema = external_exports.object({
4052
4053
  name: external_exports.string().optional(),
4053
4054
  enabled: external_exports.boolean().optional(),
4054
4055
  webhookPath: external_exports.string().optional(),
4055
4056
  token: external_exports.string().optional(),
4056
4057
  encodingAESKey: external_exports.string().optional(),
4057
- receiveId: external_exports.string().optional(),
4058
4058
  appKey: external_exports.string().optional(),
4059
4059
  appSecret: external_exports.string().optional(),
4060
- welcomeText: external_exports.string().optional(),
4061
- dmPolicy: external_exports.enum(["open", "pairing", "allowlist", "disabled"]).optional(),
4062
- allowFrom: external_exports.array(external_exports.string()).optional()
4060
+ apiBase: external_exports.string().optional(),
4061
+ welcomeText: external_exports.string().optional()
4063
4062
  });
4064
4063
  BaiduAppAccountSchema.extend({
4065
4064
  defaultAccount: external_exports.string().optional(),
@@ -4075,12 +4074,10 @@ var BaiduAppConfigJsonSchema = {
4075
4074
  webhookPath: { type: "string" },
4076
4075
  token: { type: "string" },
4077
4076
  encodingAESKey: { type: "string" },
4078
- receiveId: { type: "string" },
4079
4077
  appKey: { type: "string" },
4080
4078
  appSecret: { type: "string" },
4079
+ apiBase: { type: "string" },
4081
4080
  welcomeText: { type: "string" },
4082
- dmPolicy: { type: "string", enum: ["open", "pairing", "allowlist", "disabled"] },
4083
- allowFrom: { type: "array", items: { type: "string" } },
4084
4081
  defaultAccount: { type: "string" },
4085
4082
  accounts: {
4086
4083
  type: "object",
@@ -4093,12 +4090,10 @@ var BaiduAppConfigJsonSchema = {
4093
4090
  webhookPath: { type: "string" },
4094
4091
  token: { type: "string" },
4095
4092
  encodingAESKey: { type: "string" },
4096
- receiveId: { type: "string" },
4097
4093
  appKey: { type: "string" },
4098
4094
  appSecret: { type: "string" },
4099
- welcomeText: { type: "string" },
4100
- dmPolicy: { type: "string", enum: ["open", "pairing", "allowlist", "disabled"] },
4101
- allowFrom: { type: "array", items: { type: "string" } }
4095
+ apiBase: { type: "string" },
4096
+ welcomeText: { type: "string" }
4102
4097
  }
4103
4098
  }
4104
4099
  }
@@ -4110,7 +4105,7 @@ function normalizeAccountId(raw) {
4110
4105
  return trimmed || DEFAULT_ACCOUNT_ID;
4111
4106
  }
4112
4107
  function listConfiguredAccountIds(cfg) {
4113
- const accounts = cfg.channels?.["baidu-app"]?.accounts;
4108
+ const accounts = cfg.channels?.["openclaw-baiduapp"]?.accounts;
4114
4109
  if (!accounts || typeof accounts !== "object") {
4115
4110
  return [];
4116
4111
  }
@@ -4124,7 +4119,7 @@ function listBaiduAppAccountIds(cfg) {
4124
4119
  return ids.sort((a, b) => a.localeCompare(b));
4125
4120
  }
4126
4121
  function resolveDefaultBaiduAppAccountId(cfg) {
4127
- const baiduAppConfig = cfg.channels?.["baidu-app"];
4122
+ const baiduAppConfig = cfg.channels?.["openclaw-baiduapp"];
4128
4123
  if (baiduAppConfig?.defaultAccount?.trim()) {
4129
4124
  return baiduAppConfig.defaultAccount.trim();
4130
4125
  }
@@ -4135,31 +4130,32 @@ function resolveDefaultBaiduAppAccountId(cfg) {
4135
4130
  return ids[0] ?? DEFAULT_ACCOUNT_ID;
4136
4131
  }
4137
4132
  function resolveAccountConfig(cfg, accountId) {
4138
- const accounts = cfg.channels?.["baidu-app"]?.accounts;
4133
+ const accounts = cfg.channels?.["openclaw-baiduapp"]?.accounts;
4139
4134
  if (!accounts || typeof accounts !== "object") {
4140
4135
  return void 0;
4141
4136
  }
4142
4137
  return accounts[accountId];
4143
4138
  }
4144
4139
  function mergeBaiduAppAccountConfig(cfg, accountId) {
4145
- const base = cfg.channels?.["baidu-app"] ?? {};
4140
+ const base = cfg.channels?.["openclaw-baiduapp"] ?? {};
4146
4141
  const { accounts: _ignored, defaultAccount: _ignored2, ...baseConfig } = base;
4147
4142
  const account = resolveAccountConfig(cfg, accountId) ?? {};
4148
4143
  return { ...baseConfig, ...account };
4149
4144
  }
4150
4145
  function resolveBaiduAppAccount(params) {
4151
4146
  const accountId = normalizeAccountId(params.accountId);
4152
- const baseEnabled = params.cfg.channels?.["baidu-app"]?.enabled !== false;
4147
+ const baseEnabled = params.cfg.channels?.["openclaw-baiduapp"]?.enabled !== false;
4153
4148
  const merged = mergeBaiduAppAccountConfig(params.cfg, accountId);
4154
4149
  const enabled = baseEnabled && merged.enabled !== false;
4155
4150
  const isDefaultAccount = accountId === DEFAULT_ACCOUNT_ID;
4156
4151
  const token = merged.token?.trim() || (isDefaultAccount ? process.env.BAIDU_APP_TOKEN?.trim() : void 0) || void 0;
4157
4152
  const encodingAESKey = merged.encodingAESKey?.trim() || (isDefaultAccount ? process.env.BAIDU_APP_ENCODING_AES_KEY?.trim() : void 0) || void 0;
4158
- const receiveId = merged.receiveId?.trim() ?? "";
4159
4153
  const appKey = merged.appKey?.trim() || (isDefaultAccount ? process.env.BAIDU_APP_KEY?.trim() : void 0) || void 0;
4160
4154
  const appSecret = merged.appSecret?.trim() || (isDefaultAccount ? process.env.BAIDU_APP_SECRET?.trim() : void 0) || void 0;
4161
4155
  const configured = Boolean(token && encodingAESKey);
4162
- const canSendActive = Boolean(appKey && appSecret);
4156
+ const canSendActive = Boolean(appKey && token && encodingAESKey);
4157
+ const rawApiBase = merged.apiBase?.trim() || (isDefaultAccount ? process.env.BAIDU_API_BASE?.trim() : void 0) || void 0;
4158
+ const apiBase = (rawApiBase || DEFAULT_API_BASE).replace(/\/+$/, "");
4163
4159
  return {
4164
4160
  accountId,
4165
4161
  name: merged.name?.trim() || void 0,
@@ -4167,19 +4163,13 @@ function resolveBaiduAppAccount(params) {
4167
4163
  configured,
4168
4164
  token,
4169
4165
  encodingAESKey,
4170
- receiveId,
4171
4166
  appKey,
4172
4167
  appSecret,
4168
+ apiBase,
4173
4169
  canSendActive,
4174
4170
  config: merged
4175
4171
  };
4176
4172
  }
4177
- function resolveDmPolicy(config) {
4178
- return config.dmPolicy ?? "pairing";
4179
- }
4180
- function resolveAllowFrom(config) {
4181
- return config.allowFrom ?? [];
4182
- }
4183
4173
 
4184
4174
  // src/shared/logger.ts
4185
4175
  function createLogger(prefix, opts) {
@@ -4192,92 +4182,156 @@ function createLogger(prefix, opts) {
4192
4182
  error: (msg) => errorFn(`[${prefix}] [ERROR] ${msg}`)
4193
4183
  };
4194
4184
  }
4195
-
4196
- // src/shared/dm-policy.ts
4197
- function checkDmPolicy(params) {
4198
- const { dmPolicy, senderId, allowFrom = [] } = params;
4199
- switch (dmPolicy) {
4200
- case "open":
4201
- return { allowed: true };
4202
- case "pairing":
4203
- return { allowed: true };
4204
- case "allowlist":
4205
- if (allowFrom.includes(senderId)) {
4206
- return { allowed: true };
4207
- }
4208
- return {
4209
- allowed: false,
4210
- reason: `sender ${senderId} not in DM allowlist`
4211
- };
4212
- default:
4213
- return { allowed: true };
4185
+ function decodeEncodingAESKey(encodingAESKey) {
4186
+ const trimmed = encodingAESKey.trim();
4187
+ if (!trimmed) {
4188
+ throw new Error("encodingAESKey missing");
4189
+ }
4190
+ const withPadding = trimmed.endsWith("=") ? trimmed : `${trimmed}=`;
4191
+ const key = Buffer.from(withPadding, "base64");
4192
+ if (key.length !== 32) {
4193
+ throw new Error(`invalid encodingAESKey (expected 32 bytes after base64 decode, got ${key.length})`);
4214
4194
  }
4195
+ return key;
4215
4196
  }
4216
-
4217
- // src/api.ts
4218
- var BAIDU_API_BASE = process.env.BAIDU_API_BASE?.replace(/\/+$/, "") || "https://openapi.baidu.com";
4219
- var TOKEN_URL = `${BAIDU_API_BASE}/auth/token`;
4220
- var SEND_MESSAGE_URL = `${BAIDU_API_BASE}/chat/openclaw/callback`;
4221
- var accessTokenCache = /* @__PURE__ */ new Map();
4222
- var ACCESS_TOKEN_TTL_MS = 7200 * 1e3 - 5 * 60 * 1e3;
4223
- async function getAccessToken(account) {
4224
- if (!account.appKey || !account.appSecret) {
4225
- throw new Error("appKey or appSecret not configured");
4226
- }
4227
- const key = `${account.appKey}`;
4228
- const cached = accessTokenCache.get(key);
4229
- if (cached && Date.now() < cached.expiresAt) {
4230
- return cached.token;
4231
- }
4232
- const url = `${TOKEN_URL}?appKey=${encodeURIComponent(account.appKey)}&appSecret=${encodeURIComponent(account.appSecret)}`;
4233
- const resp = await fetch(url);
4234
- const data = await resp.json();
4235
- if (data.errcode !== void 0 && data.errcode !== 0) {
4236
- throw new Error(`gettoken failed: ${data.errmsg ?? "unknown error"} (errcode=${data.errcode})`);
4237
- }
4238
- if (!data.access_token) {
4239
- throw new Error("gettoken returned empty access_token");
4240
- }
4241
- accessTokenCache.set(key, {
4242
- token: data.access_token,
4243
- expiresAt: Date.now() + ACCESS_TOKEN_TTL_MS
4197
+ var PKCS7_BLOCK_SIZE = 32;
4198
+ function pkcs7Pad(buf, blockSize) {
4199
+ const mod = buf.length % blockSize;
4200
+ const pad = mod === 0 ? blockSize : blockSize - mod;
4201
+ return Buffer.concat([buf, Buffer.alloc(pad, pad)]);
4202
+ }
4203
+ function pkcs7Unpad(buf, blockSize) {
4204
+ if (buf.length === 0) {
4205
+ throw new Error("invalid pkcs7 payload");
4206
+ }
4207
+ const pad = buf[buf.length - 1];
4208
+ if (!pad || pad < 1 || pad > blockSize || pad > buf.length) {
4209
+ throw new Error("invalid pkcs7 padding");
4210
+ }
4211
+ for (let i = 1; i <= pad; i += 1) {
4212
+ if (buf[buf.length - i] !== pad) {
4213
+ throw new Error("invalid pkcs7 padding");
4214
+ }
4215
+ }
4216
+ return buf.subarray(0, buf.length - pad);
4217
+ }
4218
+ function sha1Hex(input) {
4219
+ return crypto.createHash("sha1").update(input).digest("hex");
4220
+ }
4221
+ function computeBaiduAppMsgSignature(params) {
4222
+ const parts = [params.token, params.timestamp, params.nonce, params.encrypt].map((value) => String(value ?? "")).sort();
4223
+ return sha1Hex(parts.join(""));
4224
+ }
4225
+ function verifyBaiduAppSignature(params) {
4226
+ const expected = computeBaiduAppMsgSignature({
4227
+ token: params.token,
4228
+ timestamp: params.timestamp,
4229
+ nonce: params.nonce,
4230
+ encrypt: params.encrypt
4244
4231
  });
4245
- return data.access_token;
4232
+ return expected === params.signature;
4246
4233
  }
4247
- function clearAccessTokenCache(account) {
4248
- const key = `${account.appKey}`;
4249
- accessTokenCache.delete(key);
4234
+ function decryptBaiduAppEncrypted(params) {
4235
+ const aesKey = decodeEncodingAESKey(params.encodingAESKey);
4236
+ const iv = aesKey.subarray(0, 16);
4237
+ const decipher = crypto.createDecipheriv("aes-256-cbc", aesKey, iv);
4238
+ decipher.setAutoPadding(false);
4239
+ const decryptedPadded = Buffer.concat([decipher.update(Buffer.from(params.encrypt, "base64")), decipher.final()]);
4240
+ const decrypted = pkcs7Unpad(decryptedPadded, PKCS7_BLOCK_SIZE);
4241
+ if (decrypted.length < 20) {
4242
+ throw new Error(`invalid decrypted payload (expected at least 20 bytes, got ${decrypted.length})`);
4243
+ }
4244
+ const msgLen = decrypted.readUInt32BE(16);
4245
+ const msgStart = 20;
4246
+ const msgEnd = msgStart + msgLen;
4247
+ if (msgEnd > decrypted.length) {
4248
+ throw new Error(`invalid decrypted msg length (msgEnd=${msgEnd}, payloadLength=${decrypted.length})`);
4249
+ }
4250
+ return decrypted.subarray(msgStart, msgEnd).toString("utf8");
4250
4251
  }
4251
- function clearAllAccessTokenCache() {
4252
- accessTokenCache.clear();
4252
+ function encryptBaiduAppPlaintext(params) {
4253
+ const aesKey = decodeEncodingAESKey(params.encodingAESKey);
4254
+ const iv = aesKey.subarray(0, 16);
4255
+ const random16 = crypto.randomBytes(16);
4256
+ const msg = Buffer.from(params.plaintext ?? "", "utf8");
4257
+ const msgLen = Buffer.alloc(4);
4258
+ msgLen.writeUInt32BE(msg.length, 0);
4259
+ const raw = Buffer.concat([random16, msgLen, msg]);
4260
+ const padded = pkcs7Pad(raw, PKCS7_BLOCK_SIZE);
4261
+ const cipher = crypto.createCipheriv("aes-256-cbc", aesKey, iv);
4262
+ cipher.setAutoPadding(false);
4263
+ const encrypted = Buffer.concat([cipher.update(padded), cipher.final()]);
4264
+ return encrypted.toString("base64");
4253
4265
  }
4254
- async function sendBaiduAppMessage(account, target, message) {
4266
+
4267
+ // src/api.ts
4268
+ var logger = createLogger("openclaw-baiduapp");
4269
+ async function sendBaiduAppMessage(account, message, options) {
4255
4270
  if (!account.canSendActive) {
4271
+ logger.error("Account not configured for active sending (missing appKey, token, or encodingAESKey)");
4256
4272
  return {
4257
4273
  ok: false,
4258
4274
  errcode: -1,
4259
- errmsg: "Account not configured for active sending (missing appKey or appSecret)"
4275
+ errmsg: "Account not configured for active sending (missing appKey, token, or encodingAESKey)"
4260
4276
  };
4261
4277
  }
4262
- const token = await getAccessToken(account);
4263
4278
  const payload = {
4264
4279
  msgtype: "text",
4265
4280
  text: { content: message },
4266
- touser: target.userId
4281
+ ...options?.msgid != null ? { msgid: options.msgid } : {},
4282
+ ...options?.streamId != null ? { streamId: options.streamId } : {},
4283
+ ...options?.chunkKey != null ? { chunkKey: options.chunkKey } : {}
4267
4284
  };
4268
- const resp = await fetch(`${SEND_MESSAGE_URL}?access_token=${encodeURIComponent(token)}`, {
4285
+ const plaintext = JSON.stringify(payload);
4286
+ const encrypt = encryptBaiduAppPlaintext({
4287
+ encodingAESKey: account.encodingAESKey ?? "",
4288
+ plaintext
4289
+ });
4290
+ const timestamp = String(Math.floor(Date.now() / 1e3));
4291
+ const nonce = crypto.randomBytes(8).toString("hex");
4292
+ const msgSignature = computeBaiduAppMsgSignature({
4293
+ token: account.token ?? "",
4294
+ timestamp,
4295
+ nonce,
4296
+ encrypt
4297
+ });
4298
+ const sendMessageUrl = `${account.apiBase}/chat/openclaw/callback`;
4299
+ const url = `${sendMessageUrl}?timestamp=${encodeURIComponent(timestamp)}&ak=${encodeURIComponent(account.appKey ?? "")}&nonce=${encodeURIComponent(nonce)}&msg_signature=${encodeURIComponent(msgSignature)}`;
4300
+ const body = JSON.stringify({ encrypt });
4301
+ logger.info(`POST ${url}`);
4302
+ logger.debug(`request body: ${body}`);
4303
+ const resp = await fetch(url, {
4269
4304
  method: "POST",
4270
- body: JSON.stringify(payload),
4305
+ body,
4271
4306
  headers: { "Content-Type": "application/json" }
4272
4307
  });
4273
- const data = await resp.json();
4274
- return {
4308
+ const text = await resp.text();
4309
+ if (!text) {
4310
+ const errmsg = `empty response from server (status=${resp.status})`;
4311
+ logger.error(`request failed: ${errmsg}`);
4312
+ return { ok: false, errcode: resp.status, errmsg };
4313
+ }
4314
+ let data;
4315
+ try {
4316
+ data = JSON.parse(text);
4317
+ } catch {
4318
+ const errmsg = `invalid JSON response (status=${resp.status}, body=${text.slice(0, 200)})`;
4319
+ logger.error(`request failed: ${errmsg}`);
4320
+ return { ok: false, errcode: resp.status, errmsg };
4321
+ }
4322
+ const result = {
4275
4323
  ok: data.errcode === 0,
4276
4324
  errcode: data.errcode,
4277
4325
  errmsg: data.errmsg,
4278
4326
  invaliduser: data.invaliduser,
4279
4327
  msgid: data.msgid
4280
4328
  };
4329
+ if (result.ok) {
4330
+ logger.info(`request succeeded: msgid=${result.msgid ?? "unknown"}`);
4331
+ } else {
4332
+ logger.error(`request failed: errcode=${result.errcode} errmsg=${result.errmsg ?? "unknown"}`);
4333
+ }
4334
+ return result;
4281
4335
  }
4282
4336
 
4283
4337
  // src/bot.ts
@@ -4295,45 +4349,28 @@ function extractBaiduAppContent(msg) {
4295
4349
  }
4296
4350
  return msgtype ? `[${msgtype}]` : "";
4297
4351
  }
4298
- function resolveSenderId(msg) {
4299
- const userid = msg.from?.userid?.trim() ?? msg.FromUserName?.trim();
4300
- return userid || "unknown";
4301
- }
4302
4352
  async function dispatchBaiduAppMessage(params) {
4303
4353
  const { cfg, account, msg, core, hooks } = params;
4304
4354
  const safeCfg = cfg ?? {};
4305
- const logger = createLogger("baidu-app", { log: params.log, error: params.error });
4306
- const senderId = resolveSenderId(msg);
4307
- const chatId = senderId;
4308
- const accountConfig = account?.config ?? {};
4309
- const dmPolicy = resolveDmPolicy(accountConfig);
4310
- const allowFrom = resolveAllowFrom(accountConfig);
4311
- if (dmPolicy === "disabled") {
4312
- logger.debug("policy rejected: dm disabled");
4313
- return;
4314
- }
4315
- const policyResult = checkDmPolicy({
4316
- dmPolicy,
4317
- senderId,
4318
- allowFrom
4319
- });
4320
- if (!policyResult.allowed) {
4321
- logger.debug(`policy rejected: ${policyResult.reason}`);
4322
- return;
4323
- }
4355
+ const logger2 = createLogger("openclaw-baiduapp", { log: params.log, error: params.error });
4324
4356
  const channel = core.channel;
4325
4357
  if (!channel?.routing?.resolveAgentRoute || !channel.reply?.dispatchReplyWithBufferedBlockDispatcher) {
4326
- logger.debug("core routing or buffered dispatcher missing, skipping dispatch");
4358
+ logger2.warn("core routing or buffered dispatcher missing, skipping dispatch");
4327
4359
  return;
4328
4360
  }
4329
4361
  const route = channel.routing.resolveAgentRoute({
4330
4362
  cfg: safeCfg,
4331
- channel: "baidu-app",
4363
+ channel: "openclaw-baiduapp",
4332
4364
  accountId: account.accountId,
4333
- peer: { kind: "dm", id: chatId }
4365
+ peer: { kind: "dm", id: "default" }
4334
4366
  });
4367
+ logger2.info(
4368
+ `route resolved: sessionKey=${route.sessionKey} agentId=${route.agentId ?? "default"} accountId=${route.accountId}`
4369
+ );
4335
4370
  const rawBody = extractBaiduAppContent(msg);
4336
- const fromLabel = `user:${senderId}`;
4371
+ logger2.debug(
4372
+ `message content extracted: len=${rawBody.length} preview="${rawBody.slice(0, 80)}${rawBody.length > 80 ? "..." : ""}"`
4373
+ );
4337
4374
  const storePath = channel.session?.resolveStorePath?.(safeCfg.session?.store, {
4338
4375
  agentId: route.agentId
4339
4376
  });
@@ -4344,48 +4381,42 @@ async function dispatchBaiduAppMessage(params) {
4344
4381
  const envelopeOptions = channel.reply?.resolveEnvelopeFormatOptions ? channel.reply.resolveEnvelopeFormatOptions(safeCfg) : void 0;
4345
4382
  const body = channel.reply?.formatAgentEnvelope ? channel.reply.formatAgentEnvelope({
4346
4383
  channel: "Baidu App",
4347
- from: fromLabel,
4384
+ from: "",
4348
4385
  previousTimestamp,
4349
4386
  envelope: envelopeOptions,
4350
4387
  body: rawBody
4351
4388
  }) : rawBody;
4352
4389
  const msgid = msg.msgid ?? msg.MsgId ?? void 0;
4353
- const from = `baidu-app:user:${senderId}`;
4354
- const to = `user:${senderId}`;
4355
4390
  const ctxPayload = channel.reply?.finalizeInboundContext ? channel.reply.finalizeInboundContext({
4356
4391
  Body: body,
4357
4392
  RawBody: rawBody,
4358
4393
  CommandBody: rawBody,
4359
- From: from,
4360
- To: to,
4394
+ From: "openclaw-baiduapp:user",
4395
+ To: "user",
4361
4396
  SessionKey: route.sessionKey,
4362
4397
  AccountId: route.accountId ?? account.accountId,
4363
4398
  ChatType: "direct",
4364
- ConversationLabel: fromLabel,
4365
- SenderName: senderId,
4366
- SenderId: senderId,
4367
- Provider: "baidu-app",
4368
- Surface: "baidu-app",
4399
+ ConversationLabel: "user",
4400
+ Provider: "openclaw-baiduapp",
4401
+ Surface: "openclaw-baiduapp",
4369
4402
  MessageSid: msgid,
4370
- OriginatingChannel: "baidu-app",
4371
- OriginatingTo: to
4403
+ OriginatingChannel: "openclaw-baiduapp",
4404
+ OriginatingTo: "user"
4372
4405
  }) : {
4373
4406
  Body: body,
4374
4407
  RawBody: rawBody,
4375
4408
  CommandBody: rawBody,
4376
- From: from,
4377
- To: to,
4409
+ From: "openclaw-baiduapp:user",
4410
+ To: "user",
4378
4411
  SessionKey: route.sessionKey,
4379
4412
  AccountId: route.accountId ?? account.accountId,
4380
4413
  ChatType: "direct",
4381
- ConversationLabel: fromLabel,
4382
- SenderName: senderId,
4383
- SenderId: senderId,
4384
- Provider: "baidu-app",
4385
- Surface: "baidu-app",
4414
+ ConversationLabel: "user",
4415
+ Provider: "openclaw-baiduapp",
4416
+ Surface: "openclaw-baiduapp",
4386
4417
  MessageSid: msgid,
4387
- OriginatingChannel: "baidu-app",
4388
- OriginatingTo: to
4418
+ OriginatingChannel: "openclaw-baiduapp",
4419
+ OriginatingTo: "user"
4389
4420
  };
4390
4421
  if (channel.session?.recordInboundSession && storePath) {
4391
4422
  await channel.session.recordInboundSession({
@@ -4393,11 +4424,16 @@ async function dispatchBaiduAppMessage(params) {
4393
4424
  sessionKey: ctxPayload.SessionKey ?? route.sessionKey,
4394
4425
  ctx: ctxPayload,
4395
4426
  onRecordError: (err) => {
4396
- logger.error(`baidu-app: failed updating session meta: ${String(err)}`);
4427
+ logger2.error(`openclaw-baiduapp: failed updating session meta: ${String(err)}`);
4397
4428
  }
4398
4429
  });
4399
4430
  }
4400
- const tableMode = channel.text?.resolveMarkdownTableMode ? channel.text.resolveMarkdownTableMode({ cfg: safeCfg, channel: "baidu-app", accountId: account.accountId }) : void 0;
4431
+ const tableMode = channel.text?.resolveMarkdownTableMode ? channel.text.resolveMarkdownTableMode({
4432
+ cfg: safeCfg,
4433
+ channel: "openclaw-baiduapp",
4434
+ accountId: account.accountId
4435
+ }) : void 0;
4436
+ logger2.info(`dispatching to agent: sessionKey=${route.sessionKey}`);
4401
4437
  await channel.reply.dispatchReplyWithBufferedBlockDispatcher({
4402
4438
  ctx: ctxPayload,
4403
4439
  cfg: safeCfg,
@@ -4405,107 +4441,20 @@ async function dispatchBaiduAppMessage(params) {
4405
4441
  deliver: async (payload) => {
4406
4442
  const rawText = payload.text ?? "";
4407
4443
  if (!rawText.trim()) {
4444
+ logger2.debug("deliver callback: empty text, skipping");
4408
4445
  return;
4409
4446
  }
4410
4447
  const converted = channel.text?.convertMarkdownTables && tableMode ? channel.text.convertMarkdownTables(rawText, tableMode) : rawText;
4448
+ logger2.debug(`deliver callback: textLen=${converted.length}`);
4411
4449
  hooks.onChunk(converted);
4412
4450
  },
4413
4451
  onError: (err, info) => {
4414
4452
  hooks.onError?.(err);
4415
- logger.error(`${info.kind} reply failed: ${String(err)}`);
4453
+ logger2.error(`${info.kind} reply failed: ${String(err)}`);
4416
4454
  }
4417
4455
  }
4418
4456
  });
4419
- }
4420
- function decodeEncodingAESKey(encodingAESKey) {
4421
- const trimmed = encodingAESKey.trim();
4422
- if (!trimmed) {
4423
- throw new Error("encodingAESKey missing");
4424
- }
4425
- const withPadding = trimmed.endsWith("=") ? trimmed : `${trimmed}=`;
4426
- const key = Buffer.from(withPadding, "base64");
4427
- if (key.length !== 32) {
4428
- throw new Error(`invalid encodingAESKey (expected 32 bytes after base64 decode, got ${key.length})`);
4429
- }
4430
- return key;
4431
- }
4432
- var PKCS7_BLOCK_SIZE = 32;
4433
- function pkcs7Pad(buf, blockSize) {
4434
- const mod = buf.length % blockSize;
4435
- const pad = mod === 0 ? blockSize : blockSize - mod;
4436
- return Buffer.concat([buf, Buffer.alloc(pad, pad)]);
4437
- }
4438
- function pkcs7Unpad(buf, blockSize) {
4439
- if (buf.length === 0) {
4440
- throw new Error("invalid pkcs7 payload");
4441
- }
4442
- const pad = buf[buf.length - 1];
4443
- if (!pad || pad < 1 || pad > blockSize || pad > buf.length) {
4444
- throw new Error("invalid pkcs7 padding");
4445
- }
4446
- for (let i = 1; i <= pad; i += 1) {
4447
- if (buf[buf.length - i] !== pad) {
4448
- throw new Error("invalid pkcs7 padding");
4449
- }
4450
- }
4451
- return buf.subarray(0, buf.length - pad);
4452
- }
4453
- function sha1Hex(input) {
4454
- return crypto.createHash("sha1").update(input).digest("hex");
4455
- }
4456
- function computeBaiduAppMsgSignature(params) {
4457
- const parts = [params.token, params.timestamp, params.nonce, params.encrypt].map((value) => String(value ?? "")).sort();
4458
- return sha1Hex(parts.join(""));
4459
- }
4460
- function verifyBaiduAppSignature(params) {
4461
- const expected = computeBaiduAppMsgSignature({
4462
- token: params.token,
4463
- timestamp: params.timestamp,
4464
- nonce: params.nonce,
4465
- encrypt: params.encrypt
4466
- });
4467
- return expected === params.signature;
4468
- }
4469
- function decryptBaiduAppEncrypted(params) {
4470
- const aesKey = decodeEncodingAESKey(params.encodingAESKey);
4471
- const iv = aesKey.subarray(0, 16);
4472
- const decipher = crypto.createDecipheriv("aes-256-cbc", aesKey, iv);
4473
- decipher.setAutoPadding(false);
4474
- const decryptedPadded = Buffer.concat([decipher.update(Buffer.from(params.encrypt, "base64")), decipher.final()]);
4475
- const decrypted = pkcs7Unpad(decryptedPadded, PKCS7_BLOCK_SIZE);
4476
- if (decrypted.length < 20) {
4477
- throw new Error(`invalid decrypted payload (expected at least 20 bytes, got ${decrypted.length})`);
4478
- }
4479
- const msgLen = decrypted.readUInt32BE(16);
4480
- const msgStart = 20;
4481
- const msgEnd = msgStart + msgLen;
4482
- if (msgEnd > decrypted.length) {
4483
- throw new Error(`invalid decrypted msg length (msgEnd=${msgEnd}, payloadLength=${decrypted.length})`);
4484
- }
4485
- const msg = decrypted.subarray(msgStart, msgEnd).toString("utf8");
4486
- const receiveId = params.receiveId ?? "";
4487
- if (receiveId) {
4488
- const trailing = decrypted.subarray(msgEnd).toString("utf8");
4489
- if (trailing !== receiveId) {
4490
- throw new Error(`receiveId mismatch (expected "${receiveId}", got "${trailing}")`);
4491
- }
4492
- }
4493
- return msg;
4494
- }
4495
- function encryptBaiduAppPlaintext(params) {
4496
- const aesKey = decodeEncodingAESKey(params.encodingAESKey);
4497
- const iv = aesKey.subarray(0, 16);
4498
- const random16 = crypto.randomBytes(16);
4499
- const msg = Buffer.from(params.plaintext ?? "", "utf8");
4500
- const msgLen = Buffer.alloc(4);
4501
- msgLen.writeUInt32BE(msg.length, 0);
4502
- const receiveId = Buffer.from(params.receiveId ?? "", "utf8");
4503
- const raw = Buffer.concat([random16, msgLen, msg, receiveId]);
4504
- const padded = pkcs7Pad(raw, PKCS7_BLOCK_SIZE);
4505
- const cipher = crypto.createCipheriv("aes-256-cbc", aesKey, iv);
4506
- cipher.setAutoPadding(false);
4507
- const encrypted = Buffer.concat([cipher.update(padded), cipher.final()]);
4508
- return encrypted.toString("base64");
4457
+ logger2.info(`agent reply dispatch complete: sessionKey=${route.sessionKey}`);
4509
4458
  }
4510
4459
 
4511
4460
  // src/runtime.ts
@@ -4584,8 +4533,13 @@ function splitMessageByBytes(text, maxBytes = MAX_MESSAGE_BYTES) {
4584
4533
  }
4585
4534
  function jsonOk(res, body) {
4586
4535
  res.statusCode = 200;
4587
- res.setHeader("Content-Type", "text/plain; charset=utf-8");
4588
- res.end(JSON.stringify(body));
4536
+ res.setHeader("Content-Type", "application/json; charset=utf-8");
4537
+ res.end(JSON.stringify({ status: 0, data: body }));
4538
+ }
4539
+ function jsonError(res, message, statusCode = 200) {
4540
+ res.statusCode = statusCode;
4541
+ res.setHeader("Content-Type", "application/json; charset=utf-8");
4542
+ res.end(JSON.stringify({ status: -1, message }));
4589
4543
  }
4590
4544
  async function readRawBody(req, maxBytes) {
4591
4545
  const chunks = [];
@@ -4642,7 +4596,6 @@ function buildEncryptedJsonReply(params) {
4642
4596
  const plaintext = JSON.stringify(params.plaintextJson ?? {});
4643
4597
  const encrypt = encryptBaiduAppPlaintext({
4644
4598
  encodingAESKey: params.account.encodingAESKey ?? "",
4645
- receiveId: params.account.receiveId ?? "",
4646
4599
  plaintext
4647
4600
  });
4648
4601
  const msgsignature = computeBaiduAppMsgSignature({
@@ -4704,8 +4657,7 @@ function parseBaiduAppPlainMessage(raw) {
4704
4657
  MsgId: xmlData.MsgId,
4705
4658
  content: xmlData.Content,
4706
4659
  Content: xmlData.Content,
4707
- from: xmlData.FromUserName ? { userid: xmlData.FromUserName } : void 0,
4708
- FromUserName: xmlData.FromUserName,
4660
+ from: xmlData.FromUserName ? { appkey: xmlData.FromUserName } : void 0,
4709
4661
  ToUserName: xmlData.ToUserName,
4710
4662
  CreateTime: xmlData.CreateTime ? Number(xmlData.CreateTime) : void 0,
4711
4663
  BotID: xmlData.BotID ? Number(xmlData.BotID) : void 0,
@@ -4731,7 +4683,6 @@ function decryptBaiduAppCandidates(params) {
4731
4683
  try {
4732
4684
  const plaintext = decryptBaiduAppEncrypted({
4733
4685
  encodingAESKey: candidate.account.encodingAESKey,
4734
- receiveId: candidate.account.receiveId,
4735
4686
  encrypt: params.encrypt
4736
4687
  });
4737
4688
  const msg = parseBaiduAppPlainMessage(plaintext);
@@ -4746,7 +4697,9 @@ function selectDecryptedTarget(params) {
4746
4697
  return params.candidates[0];
4747
4698
  }
4748
4699
  const accountIds = params.candidates.map((candidate) => candidate.target.account.accountId).join(", ");
4749
- params.logger.warn(`multiple baidu-app accounts matched signature; using first match (accounts: ${accountIds})`);
4700
+ params.logger.warn(
4701
+ `multiple openclaw-baiduapp accounts matched signature; using first match (accounts: ${accountIds})`
4702
+ );
4750
4703
  return params.candidates[0];
4751
4704
  }
4752
4705
  function appendStreamContent(state, nextText) {
@@ -4757,7 +4710,7 @@ ${nextText}`.trim() : nextText.trim();
4757
4710
  state.updatedAt = Date.now();
4758
4711
  }
4759
4712
  function buildLogger(target) {
4760
- return createLogger("baidu-app", {
4713
+ return createLogger("openclaw-baiduapp", {
4761
4714
  log: target.runtime.log,
4762
4715
  error: target.runtime.error
4763
4716
  });
@@ -4789,12 +4742,11 @@ async function handleBaiduAppWebhookRequest(req, res) {
4789
4742
  const nonce = query.get("nonce") ?? "";
4790
4743
  const signature = resolveSignatureParam(query);
4791
4744
  const primary = targets[0];
4792
- const logger = buildLogger(primary);
4745
+ const logger2 = buildLogger(primary);
4793
4746
  if (req.method === "GET") {
4794
4747
  const echostr = query.get("echostr") ?? "";
4795
4748
  if (!timestamp || !nonce || !signature || !echostr) {
4796
- res.statusCode = 400;
4797
- res.end("missing query params");
4749
+ jsonError(res, "missing query params", 400);
4798
4750
  return true;
4799
4751
  }
4800
4752
  const signatureMatched2 = targets.filter((candidate) => {
@@ -4810,14 +4762,12 @@ async function handleBaiduAppWebhookRequest(req, res) {
4810
4762
  });
4811
4763
  });
4812
4764
  if (signatureMatched2.length === 0) {
4813
- res.statusCode = 401;
4814
- res.end("unauthorized");
4765
+ jsonError(res, "unauthorized");
4815
4766
  return true;
4816
4767
  }
4817
4768
  const decryptable2 = signatureMatched2.filter((candidate) => Boolean(candidate.account.encodingAESKey));
4818
4769
  if (decryptable2.length === 0) {
4819
- res.statusCode = 401;
4820
- res.end("unauthorized");
4770
+ jsonError(res, "unauthorized");
4821
4771
  return true;
4822
4772
  }
4823
4773
  const decryptedCandidates2 = decryptBaiduAppCandidates({
@@ -4825,31 +4775,24 @@ async function handleBaiduAppWebhookRequest(req, res) {
4825
4775
  encrypt: echostr
4826
4776
  });
4827
4777
  if (decryptedCandidates2.length === 0) {
4828
- res.statusCode = 400;
4829
- res.end("decrypt failed");
4778
+ jsonError(res, "decrypt failed");
4830
4779
  return true;
4831
4780
  }
4832
- const selected2 = selectDecryptedTarget({ candidates: decryptedCandidates2, logger });
4833
- res.statusCode = 200;
4834
- res.setHeader("Content-Type", "text/plain; charset=utf-8");
4835
- res.end(selected2.plaintext);
4781
+ const selected2 = selectDecryptedTarget({ candidates: decryptedCandidates2, logger: logger2 });
4782
+ jsonOk(res, selected2.plaintext);
4836
4783
  return true;
4837
4784
  }
4838
4785
  if (req.method !== "POST") {
4839
- res.statusCode = 405;
4840
- res.setHeader("Allow", "GET, POST");
4841
- res.end("Method Not Allowed");
4786
+ jsonError(res, "Method Not Allowed", 405);
4842
4787
  return true;
4843
4788
  }
4844
4789
  if (!timestamp || !nonce || !signature) {
4845
- res.statusCode = 400;
4846
- res.end("missing query params");
4790
+ jsonError(res, "missing query params");
4847
4791
  return true;
4848
4792
  }
4849
4793
  const body = await readRawBody(req, 1024 * 1024);
4850
4794
  if (!body.ok || !body.raw) {
4851
- res.statusCode = body.error === "payload too large" ? 413 : 400;
4852
- res.end(body.error ?? "invalid payload");
4795
+ jsonError(res, body.error ?? "invalid payload");
4853
4796
  return true;
4854
4797
  }
4855
4798
  const rawBody = body.raw;
@@ -4863,22 +4806,20 @@ async function handleBaiduAppWebhookRequest(req, res) {
4863
4806
  msgSignature = xmlData.MsgSignature ?? signature;
4864
4807
  msgTimestamp = xmlData.TimeStamp ?? timestamp;
4865
4808
  msgNonce = xmlData.Nonce ?? nonce;
4866
- logger.info(
4867
- `[baidu-app] inbound xml parsed: hasEncrypt=${Boolean(encrypt)}, msg_signature=${msgSignature ? "yes" : "no"}`
4868
- );
4809
+ logger2.info(`inbound xml parsed: hasEncrypt=${Boolean(encrypt)}, msg_signature=${msgSignature ? "yes" : "no"}`);
4869
4810
  } else {
4870
4811
  try {
4871
4812
  const record = JSON.parse(rawBody);
4872
4813
  encrypt = String(record.encrypt ?? record.Encrypt ?? "");
4814
+ logger2.info(`inbound json parsed: hasEncrypt=${Boolean(encrypt)}`);
4873
4815
  } catch {
4874
- res.statusCode = 400;
4875
- res.end("invalid payload format");
4816
+ logger2.warn(`inbound payload parse failed: not valid xml or json`);
4817
+ jsonError(res, "invalid payload format");
4876
4818
  return true;
4877
4819
  }
4878
4820
  }
4879
4821
  if (!encrypt) {
4880
- res.statusCode = 400;
4881
- res.end("missing encrypt");
4822
+ jsonError(res, "missing encrypt");
4882
4823
  return true;
4883
4824
  }
4884
4825
  const signatureMatched = targets.filter((candidate) => {
@@ -4894,14 +4835,15 @@ async function handleBaiduAppWebhookRequest(req, res) {
4894
4835
  });
4895
4836
  });
4896
4837
  if (signatureMatched.length === 0) {
4897
- res.statusCode = 401;
4898
- res.end("unauthorized");
4838
+ logger2.warn(`signature verification failed: checked ${targets.length} account(s), none matched`);
4839
+ jsonError(res, "unauthorized");
4899
4840
  return true;
4900
4841
  }
4842
+ logger2.debug(`signature verified: ${signatureMatched.length} account(s) matched`);
4901
4843
  const decryptable = signatureMatched.filter((candidate) => Boolean(candidate.account.encodingAESKey));
4902
4844
  if (decryptable.length === 0) {
4903
- res.statusCode = 500;
4904
- res.end("baidu-app not configured");
4845
+ logger2.warn(`no account has encodingAESKey configured`);
4846
+ jsonError(res, "openclaw-baiduapp not configured");
4905
4847
  return true;
4906
4848
  }
4907
4849
  const decryptedCandidates = decryptBaiduAppCandidates({
@@ -4909,24 +4851,28 @@ async function handleBaiduAppWebhookRequest(req, res) {
4909
4851
  encrypt
4910
4852
  });
4911
4853
  if (decryptedCandidates.length === 0) {
4912
- res.statusCode = 400;
4913
- res.end("decrypt failed");
4854
+ logger2.warn(`decrypt failed for all ${decryptable.length} candidate account(s)`);
4855
+ jsonError(res, "decrypt failed");
4914
4856
  return true;
4915
4857
  }
4916
- const selected = selectDecryptedTarget({ candidates: decryptedCandidates, logger });
4858
+ const selected = selectDecryptedTarget({ candidates: decryptedCandidates, logger: logger2 });
4917
4859
  const target = selected.target;
4918
4860
  if (!target.account.configured || !target.account.token || !target.account.encodingAESKey) {
4919
- res.statusCode = 500;
4920
- res.end("baidu-app not configured");
4861
+ logger2.warn(`selected account ${target.account.accountId} not fully configured`);
4862
+ jsonError(res, "openclaw-baiduapp not configured");
4921
4863
  return true;
4922
4864
  }
4923
4865
  const msg = selected.msg;
4924
4866
  target.statusSink?.({ lastInboundAt: Date.now() });
4925
4867
  const msgtype = String(msg.msgtype ?? msg.MsgType ?? "").toLowerCase();
4926
4868
  const msgid = msg.msgid ?? msg.MsgId ? String(msg.msgid ?? msg.MsgId) : void 0;
4869
+ logger2.info(`inbound: type=${msgtype || "unknown"} msgid=${msgid ?? "none"} account=${target.account.accountId}`);
4927
4870
  if (msgtype === "stream") {
4928
4871
  const streamId2 = String(msg.stream?.id ?? "").trim();
4929
4872
  const state = streamId2 ? streams.get(streamId2) : void 0;
4873
+ logger2.info(
4874
+ `[REPLY-MODE:STREAM-POLL] stream poll request: streamId=${streamId2 || "none"} found=${Boolean(state)} finished=${state?.finished ?? "n/a"} contentLen=${state?.content.length ?? 0}`
4875
+ );
4930
4876
  const reply = state ? buildStreamReplyFromState(state) : buildStreamReplyFromState({
4931
4877
  streamId: streamId2 || "unknown",
4932
4878
  finished: true,
@@ -4945,6 +4891,7 @@ async function handleBaiduAppWebhookRequest(req, res) {
4945
4891
  }
4946
4892
  if (msgid && msgidToStreamId.has(msgid)) {
4947
4893
  const streamId2 = msgidToStreamId.get(msgid) ?? "";
4894
+ logger2.debug(`duplicate msgid detected: msgid=${msgid} streamId=${streamId2}, returning placeholder`);
4948
4895
  const reply = buildStreamPlaceholderReply(streamId2);
4949
4896
  jsonOk(
4950
4897
  res,
@@ -4961,15 +4908,14 @@ async function handleBaiduAppWebhookRequest(req, res) {
4961
4908
  const eventtype = String(
4962
4909
  msg.event?.eventtype ?? msg.Event ?? ""
4963
4910
  ).toLowerCase();
4911
+ logger2.info(`event received: type=${eventtype || "unknown"}`);
4964
4912
  if (eventtype === "enter_chat" || eventtype === "subscribe") {
4965
4913
  const welcome = target.account.config.welcomeText?.trim();
4966
4914
  if (welcome && target.account.canSendActive) {
4967
- const senderId2 = msg.from?.userid?.trim() ?? msg.FromUserName?.trim();
4968
- if (senderId2) {
4969
- sendBaiduAppMessage(target.account, { userId: senderId2 }, welcome).catch((err) => {
4970
- logger.error(`failed to send welcome message: ${String(err)}`);
4971
- });
4972
- }
4915
+ logger2.info("sending welcome message");
4916
+ sendBaiduAppMessage(target.account, welcome).catch((err) => {
4917
+ logger2.error(`failed to send welcome message: ${String(err)}`);
4918
+ });
4973
4919
  }
4974
4920
  jsonOk(
4975
4921
  res,
@@ -5006,13 +4952,14 @@ async function handleBaiduAppWebhookRequest(req, res) {
5006
4952
  finished: false,
5007
4953
  content: ""
5008
4954
  });
4955
+ logger2.info(`stream created: streamId=${streamId} msgid=${msgid ?? "none"}`);
5009
4956
  const core = tryGetBaiduAppRuntime();
5010
- const senderId = msg.from?.userid?.trim() ?? msg.FromUserName?.trim();
5011
4957
  if (core) {
5012
4958
  const state = streams.get(streamId);
5013
4959
  if (state) {
5014
4960
  state.started = true;
5015
4961
  }
4962
+ logger2.info(`agent dispatch started: streamId=${streamId} canSendActive=${target.account.canSendActive}`);
5016
4963
  const hooks = {
5017
4964
  onChunk: (text) => {
5018
4965
  const current = streams.get(streamId);
@@ -5020,6 +4967,9 @@ async function handleBaiduAppWebhookRequest(req, res) {
5020
4967
  return;
5021
4968
  }
5022
4969
  appendStreamContent(current, text);
4970
+ logger2.debug(
4971
+ `chunk received: streamId=${streamId} chunkLen=${text.length} totalLen=${current.content.length}`
4972
+ );
5023
4973
  target.statusSink?.({ lastOutboundAt: Date.now() });
5024
4974
  },
5025
4975
  onError: (err) => {
@@ -5030,7 +4980,7 @@ async function handleBaiduAppWebhookRequest(req, res) {
5030
4980
  current.finished = true;
5031
4981
  current.updatedAt = Date.now();
5032
4982
  }
5033
- logger.error(`baidu-app agent failed: ${String(err)}`);
4983
+ logger2.error(`openclaw-baiduapp agent failed: ${String(err)}`);
5034
4984
  }
5035
4985
  };
5036
4986
  dispatchBaiduAppMessage({
@@ -5046,15 +4996,36 @@ async function handleBaiduAppWebhookRequest(req, res) {
5046
4996
  if (current) {
5047
4997
  current.finished = true;
5048
4998
  current.updatedAt = Date.now();
5049
- if (target.account.canSendActive && senderId && current.content.trim()) {
4999
+ const contentLen = current.content.trim().length;
5000
+ logger2.info(
5001
+ `agent dispatch done: streamId=${streamId} contentLen=${contentLen} canSendActive=${target.account.canSendActive}`
5002
+ );
5003
+ if (!target.account.canSendActive) {
5004
+ logger2.warn(
5005
+ `active send skipped: appKey/appSecret not configured for account ${target.account.accountId}`
5006
+ );
5007
+ } else if (!contentLen) {
5008
+ logger2.warn(`active send skipped: agent produced no content`);
5009
+ }
5010
+ if (target.account.canSendActive && current.content.trim()) {
5050
5011
  try {
5051
5012
  const chunks = splitMessageByBytes(current.content, MAX_MESSAGE_BYTES);
5052
- for (const chunk of chunks) {
5053
- await sendBaiduAppMessage(target.account, { userId: senderId }, chunk);
5013
+ logger2.info(
5014
+ `[REPLY-MODE:ACTIVE-SEND] active send starting: streamId=${streamId} chunks=${chunks.length} contentLen=${contentLen}`
5015
+ );
5016
+ for (let i = 0; i < chunks.length; i++) {
5017
+ await sendBaiduAppMessage(target.account, chunks[i], {
5018
+ msgid,
5019
+ streamId,
5020
+ chunkKey: i
5021
+ });
5022
+ logger2.debug(`active send chunk ${i + 1}/${chunks.length} sent: streamId=${streamId}`);
5054
5023
  }
5055
- logger.info(`active send complete: streamId=${streamId}, ${chunks.length} chunks`);
5024
+ logger2.info(
5025
+ `[REPLY-MODE:ACTIVE-SEND] active send complete: streamId=${streamId} chunks=${chunks.length}`
5026
+ );
5056
5027
  } catch (err) {
5057
- logger.error(`active send failed: ${String(err)}`);
5028
+ logger2.error(`active send failed: streamId=${streamId} error=${String(err)}`);
5058
5029
  }
5059
5030
  }
5060
5031
  }
@@ -5066,9 +5037,10 @@ async function handleBaiduAppWebhookRequest(req, res) {
5066
5037
  current.finished = true;
5067
5038
  current.updatedAt = Date.now();
5068
5039
  }
5069
- logger.error(`baidu-app agent failed: ${String(err)}`);
5040
+ logger2.error(`agent dispatch failed: streamId=${streamId} error=${String(err)}`);
5070
5041
  });
5071
5042
  } else {
5043
+ logger2.warn(`runtime not available: streamId=${streamId} \u2014 agent dispatch skipped, no reply will be generated`);
5072
5044
  const state = streams.get(streamId);
5073
5045
  if (state) {
5074
5046
  state.finished = true;
@@ -5076,6 +5048,7 @@ async function handleBaiduAppWebhookRequest(req, res) {
5076
5048
  }
5077
5049
  }
5078
5050
  const placeholderReply = buildStreamPlaceholderReply(streamId);
5051
+ logger2.debug(`stream placeholder reply sent: streamId=${streamId}`);
5079
5052
  jsonOk(
5080
5053
  res,
5081
5054
  buildEncryptedJsonReply({
@@ -5090,18 +5063,18 @@ async function handleBaiduAppWebhookRequest(req, res) {
5090
5063
 
5091
5064
  // src/channel.ts
5092
5065
  var meta = {
5093
- id: "baidu-app",
5066
+ id: "openclaw-baiduapp",
5094
5067
  label: "Baidu App",
5095
5068
  selectionLabel: "Baidu Search AI (\u767E\u5EA6\u641C\u7D22\u5BF9\u8BDD\u5F0FAI)",
5096
- docsPath: "/channels/baidu-app",
5097
- docsLabel: "baidu-app",
5069
+ docsPath: "/channels/openclaw-baiduapp",
5070
+ docsLabel: "openclaw-baiduapp",
5098
5071
  blurb: "\u767E\u5EA6\u641C\u7D22\u5BF9\u8BDD\u5F0FAI\uFF0C\u652F\u6301\u4E3B\u52A8\u53D1\u9001\u6D88\u606F",
5099
5072
  aliases: ["baidu-ai", "\u767E\u5EA6\u641C\u7D22AI"],
5100
5073
  order: 85
5101
5074
  };
5102
5075
  var unregisterHooks = /* @__PURE__ */ new Map();
5103
5076
  var baiduAppPlugin = {
5104
- id: "baidu-app",
5077
+ id: "openclaw-baiduapp",
5105
5078
  meta: {
5106
5079
  ...meta
5107
5080
  },
@@ -5116,21 +5089,21 @@ var baiduAppPlugin = {
5116
5089
  activeSend: true
5117
5090
  },
5118
5091
  configSchema: BaiduAppConfigJsonSchema,
5119
- reload: { configPrefixes: ["channels.baidu-app"] },
5092
+ reload: { configPrefixes: ["channels.openclaw-baiduapp"] },
5120
5093
  config: {
5121
5094
  listAccountIds: (cfg) => listBaiduAppAccountIds(cfg),
5122
5095
  resolveAccount: (cfg, accountId) => resolveBaiduAppAccount({ cfg, accountId }),
5123
5096
  defaultAccountId: (cfg) => resolveDefaultBaiduAppAccountId(cfg),
5124
5097
  setAccountEnabled: (params) => {
5125
5098
  const accountId = params.accountId ?? DEFAULT_ACCOUNT_ID;
5126
- const useAccount = Boolean(params.cfg.channels?.["baidu-app"]?.accounts?.[accountId]);
5099
+ const useAccount = Boolean(params.cfg.channels?.["openclaw-baiduapp"]?.accounts?.[accountId]);
5127
5100
  if (!useAccount) {
5128
5101
  return {
5129
5102
  ...params.cfg,
5130
5103
  channels: {
5131
5104
  ...params.cfg.channels,
5132
- "baidu-app": {
5133
- ...params.cfg.channels?.["baidu-app"] ?? {},
5105
+ "openclaw-baiduapp": {
5106
+ ...params.cfg.channels?.["openclaw-baiduapp"] ?? {},
5134
5107
  enabled: params.enabled
5135
5108
  }
5136
5109
  }
@@ -5140,12 +5113,12 @@ var baiduAppPlugin = {
5140
5113
  ...params.cfg,
5141
5114
  channels: {
5142
5115
  ...params.cfg.channels,
5143
- "baidu-app": {
5144
- ...params.cfg.channels?.["baidu-app"] ?? {},
5116
+ "openclaw-baiduapp": {
5117
+ ...params.cfg.channels?.["openclaw-baiduapp"] ?? {},
5145
5118
  accounts: {
5146
- ...params.cfg.channels?.["baidu-app"]?.accounts ?? {},
5119
+ ...params.cfg.channels?.["openclaw-baiduapp"]?.accounts ?? {},
5147
5120
  [accountId]: {
5148
- ...params.cfg.channels?.["baidu-app"]?.accounts?.[accountId] ?? {},
5121
+ ...params.cfg.channels?.["openclaw-baiduapp"]?.accounts?.[accountId] ?? {},
5149
5122
  enabled: params.enabled
5150
5123
  }
5151
5124
  }
@@ -5156,7 +5129,7 @@ var baiduAppPlugin = {
5156
5129
  deleteAccount: (params) => {
5157
5130
  const accountId = params.accountId ?? DEFAULT_ACCOUNT_ID;
5158
5131
  const next = { ...params.cfg };
5159
- const current = next.channels?.["baidu-app"];
5132
+ const current = next.channels?.["openclaw-baiduapp"];
5160
5133
  if (!current) {
5161
5134
  return next;
5162
5135
  }
@@ -5164,7 +5137,7 @@ var baiduAppPlugin = {
5164
5137
  const { accounts: _ignored, defaultAccount: _ignored2, ...rest } = current;
5165
5138
  next.channels = {
5166
5139
  ...next.channels,
5167
- "baidu-app": { ...rest, enabled: false }
5140
+ "openclaw-baiduapp": { ...rest, enabled: false }
5168
5141
  };
5169
5142
  return next;
5170
5143
  }
@@ -5172,7 +5145,7 @@ var baiduAppPlugin = {
5172
5145
  delete accounts[accountId];
5173
5146
  next.channels = {
5174
5147
  ...next.channels,
5175
- "baidu-app": {
5148
+ "openclaw-baiduapp": {
5176
5149
  ...current,
5177
5150
  accounts: Object.keys(accounts).length > 0 ? accounts : void 0
5178
5151
  }
@@ -5186,13 +5159,8 @@ var baiduAppPlugin = {
5186
5159
  enabled: account.enabled,
5187
5160
  configured: account.configured,
5188
5161
  canSendActive: account.canSendActive,
5189
- webhookPath: account.config.webhookPath ?? "/baidu-app"
5190
- }),
5191
- resolveAllowFrom: (params) => {
5192
- const account = resolveBaiduAppAccount({ cfg: params.cfg, accountId: params.accountId });
5193
- return resolveAllowFrom(account.config);
5194
- },
5195
- formatAllowFrom: (params) => params.allowFrom.map((entry) => String(entry).trim()).filter(Boolean).map((entry) => entry.toLowerCase())
5162
+ webhookPath: account.config.webhookPath ?? "/openclaw-baiduapp"
5163
+ })
5196
5164
  },
5197
5165
  directory: {
5198
5166
  canResolve: (params) => {
@@ -5200,7 +5168,7 @@ var baiduAppPlugin = {
5200
5168
  if (!raw) {
5201
5169
  return false;
5202
5170
  }
5203
- if (raw.startsWith("baidu-app:")) {
5171
+ if (raw.startsWith("openclaw-baiduapp:")) {
5204
5172
  return true;
5205
5173
  }
5206
5174
  const knownChannelPrefixes = [
@@ -5225,7 +5193,7 @@ var baiduAppPlugin = {
5225
5193
  if (!raw) {
5226
5194
  return null;
5227
5195
  }
5228
- const channelPrefix = "baidu-app:";
5196
+ const channelPrefix = "openclaw-baiduapp:";
5229
5197
  if (raw.startsWith(channelPrefix)) {
5230
5198
  raw = raw.slice(channelPrefix.length);
5231
5199
  }
@@ -5240,9 +5208,9 @@ var baiduAppPlugin = {
5240
5208
  }
5241
5209
  }
5242
5210
  if (to.startsWith("user:")) {
5243
- return { channel: "baidu-app", accountId, to: to.slice(5) };
5211
+ return { channel: "openclaw-baiduapp", accountId, to: to.slice(5) };
5244
5212
  }
5245
- return { channel: "baidu-app", accountId, to };
5213
+ return { channel: "openclaw-baiduapp", accountId, to };
5246
5214
  },
5247
5215
  resolveTargets: (params) => {
5248
5216
  const results = [];
@@ -5257,7 +5225,7 @@ var baiduAppPlugin = {
5257
5225
  }
5258
5226
  return results;
5259
5227
  },
5260
- getTargetFormats: () => ["baidu-app:user:<userId>", "user:<userId>", "<userId>"]
5228
+ getTargetFormats: () => ["openclaw-baiduapp"]
5261
5229
  },
5262
5230
  outbound: {
5263
5231
  deliveryMode: "direct",
@@ -5265,34 +5233,59 @@ var baiduAppPlugin = {
5265
5233
  const account = resolveBaiduAppAccount({ cfg: params.cfg, accountId: params.accountId });
5266
5234
  if (!account.canSendActive) {
5267
5235
  return {
5268
- channel: "baidu-app",
5236
+ channel: "openclaw-baiduapp",
5269
5237
  ok: false,
5270
5238
  messageId: "",
5271
5239
  error: new Error("Account not configured for active sending (missing appKey or appSecret)")
5272
5240
  };
5273
5241
  }
5274
- let to = params.to;
5275
- const channelPrefix = "baidu-app:";
5276
- if (to.startsWith(channelPrefix)) {
5277
- to = to.slice(channelPrefix.length);
5242
+ try {
5243
+ const result = await sendBaiduAppMessage(account, params.text);
5244
+ return {
5245
+ channel: "openclaw-baiduapp",
5246
+ ok: result.ok,
5247
+ messageId: result.msgid ?? "",
5248
+ error: result.ok ? void 0 : new Error(result.errmsg ?? "send failed")
5249
+ };
5250
+ } catch (err) {
5251
+ return {
5252
+ channel: "openclaw-baiduapp",
5253
+ ok: false,
5254
+ messageId: "",
5255
+ error: err instanceof Error ? err : new Error(String(err))
5256
+ };
5257
+ }
5258
+ },
5259
+ sendMedia: async (params) => {
5260
+ const account = resolveBaiduAppAccount({ cfg: params.cfg, accountId: params.accountId ?? void 0 });
5261
+ if (!account.canSendActive) {
5262
+ return {
5263
+ channel: "openclaw-baiduapp",
5264
+ ok: false,
5265
+ messageId: "",
5266
+ error: new Error("Account not configured for active sending (missing appKey or appSecret)")
5267
+ };
5278
5268
  }
5279
- let target;
5280
- if (to.startsWith("user:")) {
5281
- target = { userId: to.slice(5) };
5282
- } else {
5283
- target = { userId: to };
5269
+ const content = params.text?.trim() || params.mediaUrl || "";
5270
+ if (!content) {
5271
+ return {
5272
+ channel: "openclaw-baiduapp",
5273
+ ok: false,
5274
+ messageId: "",
5275
+ error: new Error("No content to send (media not supported, text is empty)")
5276
+ };
5284
5277
  }
5285
5278
  try {
5286
- const result = await sendBaiduAppMessage(account, target, params.text);
5279
+ const result = await sendBaiduAppMessage(account, content);
5287
5280
  return {
5288
- channel: "baidu-app",
5281
+ channel: "openclaw-baiduapp",
5289
5282
  ok: result.ok,
5290
5283
  messageId: result.msgid ?? "",
5291
5284
  error: result.ok ? void 0 : new Error(result.errmsg ?? "send failed")
5292
5285
  };
5293
5286
  } catch (err) {
5294
5287
  return {
5295
- channel: "baidu-app",
5288
+ channel: "openclaw-baiduapp",
5296
5289
  ok: false,
5297
5290
  messageId: "",
5298
5291
  error: err instanceof Error ? err : new Error(String(err))
@@ -5311,11 +5304,11 @@ var baiduAppPlugin = {
5311
5304
  }
5312
5305
  const account = resolveBaiduAppAccount({ cfg: ctx.cfg, accountId: ctx.accountId });
5313
5306
  if (!account.configured) {
5314
- ctx.log?.info(`[baidu-app] account ${ctx.accountId} not configured; webhook not registered`);
5307
+ ctx.log?.info(`[openclaw-baiduapp] account ${ctx.accountId} not configured; webhook not registered`);
5315
5308
  ctx.setStatus?.({ accountId: ctx.accountId, running: false, configured: false });
5316
5309
  return;
5317
5310
  }
5318
- const path = (account.config.webhookPath ?? "/baidu-app").trim();
5311
+ const path = (account.config.webhookPath ?? "/openclaw-baiduapp").trim();
5319
5312
  const unregister = registerBaiduAppWebhookTarget({
5320
5313
  account,
5321
5314
  config: ctx.cfg ?? {},
@@ -5332,7 +5325,7 @@ var baiduAppPlugin = {
5332
5325
  }
5333
5326
  unregisterHooks.set(ctx.accountId, unregister);
5334
5327
  ctx.log?.info(
5335
- `[baidu-app] webhook registered at ${path} for account ${ctx.accountId} (canSendActive=${account.canSendActive})`
5328
+ `[openclaw-baiduapp] webhook registered at ${path} for account ${ctx.accountId} (canSendActive=${account.canSendActive})`
5336
5329
  );
5337
5330
  ctx.setStatus?.({
5338
5331
  accountId: ctx.accountId,
@@ -5355,38 +5348,16 @@ var baiduAppPlugin = {
5355
5348
  };
5356
5349
 
5357
5350
  // src/send.ts
5358
- function normalizeTarget(target, type) {
5359
- let normalized = target.trim();
5360
- const channelPrefix = "baidu-app:";
5361
- if (normalized.startsWith(channelPrefix)) {
5362
- normalized = normalized.slice(channelPrefix.length);
5363
- }
5364
- if (type === "user" && normalized.startsWith("user:")) {
5365
- return normalized;
5366
- }
5367
- if (normalized.startsWith("user:")) {
5368
- normalized = normalized.slice(5);
5369
- }
5370
- return `user:${normalized}`;
5371
- }
5372
- function parseTarget(target) {
5373
- if (target.startsWith("user:")) {
5374
- return { userId: target.slice(5) };
5375
- }
5376
- return { userId: target };
5377
- }
5378
- async function sendBaiduDM(account, userId, options) {
5351
+ async function sendBaiduDM(account, options) {
5379
5352
  if (!account.canSendActive) {
5380
5353
  return {
5381
5354
  ok: false,
5382
5355
  error: "Account not configured for active sending (missing appKey or appSecret)"
5383
5356
  };
5384
5357
  }
5385
- const normalizedTarget = normalizeTarget(userId, "user");
5386
- const target = parseTarget(normalizedTarget);
5387
- return sendMessage(account, target, options);
5358
+ return sendMessage(account, options);
5388
5359
  }
5389
- async function sendMessage(account, target, options) {
5360
+ async function sendMessage(account, options) {
5390
5361
  if (!options.text?.trim()) {
5391
5362
  return {
5392
5363
  ok: false,
@@ -5394,7 +5365,7 @@ async function sendMessage(account, target, options) {
5394
5365
  };
5395
5366
  }
5396
5367
  try {
5397
- const textResult = await sendBaiduAppMessage(account, target, options.text);
5368
+ const textResult = await sendBaiduAppMessage(account, options.text);
5398
5369
  return {
5399
5370
  ok: textResult.ok,
5400
5371
  msgid: textResult.msgid,
@@ -5407,20 +5378,14 @@ async function sendMessage(account, target, options) {
5407
5378
  };
5408
5379
  }
5409
5380
  }
5410
- async function sendBaidu(account, target, options) {
5381
+ async function sendBaidu(account, options) {
5411
5382
  if (!account.canSendActive) {
5412
5383
  return {
5413
5384
  ok: false,
5414
5385
  error: "Account not configured for active sending (missing appKey or appSecret)"
5415
5386
  };
5416
5387
  }
5417
- let normalizedTarget = target.trim();
5418
- const channelPrefix = "baidu-app:";
5419
- if (normalizedTarget.startsWith(channelPrefix)) {
5420
- normalizedTarget = normalizedTarget.slice(channelPrefix.length);
5421
- }
5422
- const parsedTarget = parseTarget(normalizedTarget);
5423
- return sendMessage(account, parsedTarget, options);
5388
+ return sendMessage(account, options);
5424
5389
  }
5425
5390
 
5426
5391
  // index.ts
@@ -5445,6 +5410,6 @@ var plugin = {
5445
5410
  };
5446
5411
  var index_default = plugin;
5447
5412
 
5448
- export { DEFAULT_ACCOUNT_ID, baiduAppPlugin, clearAccessTokenCache, clearAllAccessTokenCache, index_default as default, getAccessToken, getBaiduAppRuntime, normalizeTarget, parseTarget, sendBaidu, sendBaiduAppMessage, sendBaiduDM, setBaiduAppRuntime };
5413
+ export { DEFAULT_ACCOUNT_ID, baiduAppPlugin, index_default as default, getBaiduAppRuntime, sendBaidu, sendBaiduAppMessage, sendBaiduDM, setBaiduAppRuntime };
5449
5414
  //# sourceMappingURL=index.js.map
5450
5415
  //# sourceMappingURL=index.js.map