@inline-openclaw/inline 0.0.29 → 0.0.30

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
@@ -34276,6 +34276,10 @@ import {
34276
34276
  parseCommandArgs,
34277
34277
  resolveCommandArgMenu
34278
34278
  } from "openclaw/plugin-sdk/native-command-registry";
34279
+ import {
34280
+ createChannelInboundDebouncer,
34281
+ shouldDebounceTextInbound
34282
+ } from "openclaw/plugin-sdk/channel-inbound";
34279
34283
  import { resolveDefaultModelForAgent } from "openclaw/plugin-sdk/agent-runtime";
34280
34284
  import { applyModelOverrideToSessionEntry, updateSessionStore } from "openclaw/plugin-sdk/config-runtime";
34281
34285
  import { buildModelsProviderData } from "openclaw/plugin-sdk/models-provider-runtime";
@@ -35219,6 +35223,18 @@ function buildInlineInboundMessageSid(params) {
35219
35223
  }
35220
35224
  return String(params.msgId);
35221
35225
  }
35226
+ function buildInlineDebounceKey(params) {
35227
+ if (params.senderId == null)
35228
+ return null;
35229
+ return `inline:${params.accountId}:${String(params.chatId)}:${String(params.senderId)}`;
35230
+ }
35231
+ function buildSyntheticInlineTextMessage(params) {
35232
+ return {
35233
+ ...params.base,
35234
+ message: params.text,
35235
+ ...params.mentioned !== undefined ? { mentioned: params.mentioned } : {}
35236
+ };
35237
+ }
35222
35238
  var INLINE_ACTION_MAX_ROWS = 8;
35223
35239
  var INLINE_ACTION_MAX_PER_ROW = 8;
35224
35240
  function isRecord3(value) {
@@ -36037,1000 +36053,1078 @@ async function monitorInlineProvider(params) {
36037
36053
  participantFetches.set(chatKey, run);
36038
36054
  await run;
36039
36055
  };
36040
- const loop = (async () => {
36056
+ const handleInboundNow = async (input) => {
36057
+ const chatId = input.chatId;
36058
+ const msg = input.msg;
36059
+ const rawBodyOverride = input.rawBodyOverride ?? null;
36060
+ const reactionEvent = input.reactionEvent ?? null;
36061
+ const callbackActionEvent = input.callbackActionEvent ?? null;
36062
+ let rawBody = "";
36063
+ let currentContent = null;
36064
+ let currentAttachmentText = null;
36065
+ let currentEntityText = null;
36066
+ if (!reactionEvent && !callbackActionEvent) {
36067
+ if (rawBodyOverride != null) {
36068
+ rawBody = rawBodyOverride.trim();
36069
+ } else {
36070
+ currentContent = summarizeInlineMessageContent(msg);
36071
+ rawBody = buildInlineInboundBodyText(currentContent);
36072
+ currentAttachmentText = currentContent.attachmentText || null;
36073
+ currentEntityText = currentContent.entityText || null;
36074
+ }
36075
+ if (!rawBody)
36076
+ return;
36077
+ }
36078
+ statusSink?.({ lastInboundAt: Date.now() });
36079
+ let chatInfo;
36041
36080
  try {
36042
- for await (const event of client.events()) {
36043
- if (abortSignal.aborted)
36044
- break;
36045
- const rawEvent = event;
36046
- let msg;
36047
- let rawBody = "";
36048
- let currentContent = null;
36049
- let currentAttachmentText = null;
36050
- let currentEntityText = null;
36051
- let reactionEvent = null;
36052
- let inboundChatId = null;
36053
- let callbackActionEvent = null;
36054
- if (event.kind === "message.new") {
36055
- inboundChatId = event.chatId;
36056
- msg = {
36057
- ...event.message,
36058
- chatId: event.chatId
36059
- };
36060
- currentContent = summarizeInlineMessageContent(msg);
36061
- rawBody = buildInlineInboundBodyText(currentContent);
36062
- currentAttachmentText = currentContent.attachmentText || null;
36063
- currentEntityText = currentContent.entityText || null;
36064
- if (!rawBody)
36065
- continue;
36066
- if (msg.out || msg.fromId === meId)
36067
- continue;
36068
- } else if (event.kind === "reaction.add") {
36069
- inboundChatId = event.chatId;
36070
- if (event.reaction.userId === meId)
36071
- continue;
36072
- const onBotMessage = await isReactionTargetBotMessage({
36073
- client,
36074
- chatId: event.chatId,
36075
- messageId: event.reaction.messageId,
36076
- meId,
36077
- botMessageIdsByChat
36078
- }).catch((err) => {
36079
- statusSink?.({ lastError: `getChatHistory (reaction target) failed: ${String(err)}` });
36080
- return false;
36081
- });
36082
- if (!onBotMessage)
36083
- continue;
36084
- reactionEvent = {
36085
- action: "added",
36086
- emoji: event.reaction.emoji,
36087
- targetMessageId: event.reaction.messageId
36088
- };
36089
- msg = {
36090
- id: event.reaction.messageId,
36091
- chatId: event.chatId,
36092
- date: event.date,
36093
- fromId: event.reaction.userId,
36094
- message: "",
36095
- out: false,
36096
- mentioned: false,
36097
- replyToMsgId: event.reaction.messageId
36098
- };
36099
- } else if (event.kind === "reaction.delete") {
36100
- inboundChatId = event.chatId;
36101
- if (event.userId === meId)
36102
- continue;
36103
- const onBotMessage = await isReactionTargetBotMessage({
36104
- client,
36105
- chatId: event.chatId,
36106
- messageId: event.messageId,
36107
- meId,
36108
- botMessageIdsByChat
36109
- }).catch((err) => {
36110
- statusSink?.({ lastError: `getChatHistory (reaction target) failed: ${String(err)}` });
36111
- return false;
36112
- });
36113
- if (!onBotMessage)
36114
- continue;
36115
- reactionEvent = {
36116
- action: "removed",
36117
- emoji: event.emoji,
36118
- targetMessageId: event.messageId
36119
- };
36120
- msg = {
36121
- id: event.messageId,
36122
- chatId: event.chatId,
36123
- date: event.date,
36124
- fromId: event.userId,
36125
- message: "",
36126
- out: false,
36127
- mentioned: false,
36128
- replyToMsgId: event.messageId
36129
- };
36130
- } else if (rawEvent["kind"] === "message.action.invoke") {
36131
- const actorUserId = rawEvent["actorUserId"];
36132
- const interactionId = rawEvent["interactionId"];
36133
- const actionId = rawEvent["actionId"];
36134
- const targetMessageId = rawEvent["messageId"];
36135
- const data = rawEvent["data"];
36136
- const eventChatId = rawEvent["chatId"];
36137
- const eventDate = rawEvent["date"];
36138
- if (!actorUserId || !interactionId || !actionId || !targetMessageId || !eventChatId || !eventDate || !data) {
36139
- continue;
36140
- }
36141
- inboundChatId = eventChatId;
36142
- if (actorUserId === meId)
36143
- continue;
36144
- callbackActionEvent = {
36145
- interactionId,
36146
- actionId,
36147
- targetMessageId,
36148
- data
36149
- };
36150
- msg = {
36151
- id: targetMessageId,
36152
- chatId: eventChatId,
36153
- date: eventDate,
36154
- fromId: actorUserId,
36155
- message: "",
36156
- out: false,
36157
- mentioned: false,
36158
- replyToMsgId: targetMessageId
36159
- };
36160
- } else {
36161
- continue;
36162
- }
36163
- if (!inboundChatId)
36164
- continue;
36165
- const chatId = inboundChatId;
36166
- statusSink?.({ lastInboundAt: Date.now() });
36167
- let chatInfo;
36168
- try {
36169
- chatInfo = await resolveChatInfo(client, chatCache, chatId);
36170
- } catch (err) {
36171
- chatInfo = { kind: "group", title: null };
36172
- statusSink?.({ lastError: `getChat failed: ${String(err)}` });
36173
- }
36174
- const isGroup = chatInfo.kind !== "direct";
36175
- const replyThreadsEnabled = account.config.capabilities?.replyThreads === true || isInlineReplyThreadsEnabled({ cfg, accountId: account.accountId });
36176
- const replyThreadContext = await resolveInlineInboundReplyThreadContext({
36177
- replyThreadsEnabled,
36178
- client,
36179
- chatId,
36180
- chatInfo,
36181
- chatCache
36182
- }).catch((err) => {
36183
- statusSink?.({ lastError: `getChat (reply thread) failed: ${String(err)}` });
36184
- return null;
36185
- });
36186
- const effectiveChatId = replyThreadContext?.parentChatId ?? chatId;
36187
- const effectiveGroupTitle = replyThreadContext?.parentChatTitle ?? chatInfo.title ?? null;
36188
- const senderId = String(msg.fromId);
36189
- await hydrateChatParticipants(chatId);
36190
- const senderProfile = senderProfilesById.get(senderId);
36191
- const senderUsername = senderProfile?.username;
36192
- const senderName = senderProfile?.name ?? (!isGroup ? chatInfo.title ?? undefined : undefined);
36193
- if (reactionEvent) {
36194
- const actor = senderUsername != null && senderUsername.length > 0 ? `@${senderUsername}` : senderName ?? `user:${senderId}`;
36195
- const emoji3 = reactionEvent.emoji.trim() || "a reaction";
36196
- const messageId = String(reactionEvent.targetMessageId);
36197
- if (reactionEvent.action === "added") {
36198
- rawBody = `${actor} reacted with ${emoji3} to your message #${messageId}`;
36199
- } else {
36200
- rawBody = `${actor} removed ${emoji3} from your message #${messageId}`;
36201
- }
36202
- } else if (callbackActionEvent) {
36203
- const actor = senderUsername != null && senderUsername.length > 0 ? `@${senderUsername}` : senderName ?? `user:${senderId}`;
36204
- const payload = {
36205
- type: "inline_message_action_callback",
36206
- interaction_id: String(callbackActionEvent.interactionId),
36207
- actor_user_id: senderId,
36208
- chat_id: String(chatId),
36209
- message_id: String(callbackActionEvent.targetMessageId),
36210
- action_id: callbackActionEvent.actionId,
36211
- data_base64: callbackDataToBase64(callbackActionEvent.data),
36212
- data_utf8: callbackDataToUtf8(callbackActionEvent.data) ?? null
36213
- };
36214
- rawBody = `${actor} pressed a button on message #${String(callbackActionEvent.targetMessageId)}
36081
+ chatInfo = await resolveChatInfo(client, chatCache, chatId);
36082
+ } catch (err) {
36083
+ chatInfo = { kind: "group", title: null };
36084
+ statusSink?.({ lastError: `getChat failed: ${String(err)}` });
36085
+ }
36086
+ const isGroup = chatInfo.kind !== "direct";
36087
+ const replyThreadsEnabled = account.config.capabilities?.replyThreads === true || isInlineReplyThreadsEnabled({ cfg, accountId: account.accountId });
36088
+ const replyThreadContext = await resolveInlineInboundReplyThreadContext({
36089
+ replyThreadsEnabled,
36090
+ client,
36091
+ chatId,
36092
+ chatInfo,
36093
+ chatCache
36094
+ }).catch((err) => {
36095
+ statusSink?.({ lastError: `getChat (reply thread) failed: ${String(err)}` });
36096
+ return null;
36097
+ });
36098
+ const effectiveChatId = replyThreadContext?.parentChatId ?? chatId;
36099
+ const effectiveGroupTitle = replyThreadContext?.parentChatTitle ?? chatInfo.title ?? null;
36100
+ const senderId = String(msg.fromId);
36101
+ await hydrateChatParticipants(chatId);
36102
+ const senderProfile = senderProfilesById.get(senderId);
36103
+ const senderUsername = senderProfile?.username;
36104
+ const senderName = senderProfile?.name ?? (!isGroup ? chatInfo.title ?? undefined : undefined);
36105
+ if (reactionEvent) {
36106
+ const actor = senderUsername != null && senderUsername.length > 0 ? `@${senderUsername}` : senderName ?? `user:${senderId}`;
36107
+ const emoji3 = reactionEvent.emoji.trim() || "a reaction";
36108
+ const messageId = String(reactionEvent.targetMessageId);
36109
+ if (reactionEvent.action === "added") {
36110
+ rawBody = `${actor} reacted with ${emoji3} to your message #${messageId}`;
36111
+ } else {
36112
+ rawBody = `${actor} removed ${emoji3} from your message #${messageId}`;
36113
+ }
36114
+ } else if (callbackActionEvent) {
36115
+ const actor = senderUsername != null && senderUsername.length > 0 ? `@${senderUsername}` : senderName ?? `user:${senderId}`;
36116
+ const payload = {
36117
+ type: "inline_message_action_callback",
36118
+ interaction_id: String(callbackActionEvent.interactionId),
36119
+ actor_user_id: senderId,
36120
+ chat_id: String(chatId),
36121
+ message_id: String(callbackActionEvent.targetMessageId),
36122
+ action_id: callbackActionEvent.actionId,
36123
+ data_base64: callbackDataToBase64(callbackActionEvent.data),
36124
+ data_utf8: callbackDataToUtf8(callbackActionEvent.data) ?? null
36125
+ };
36126
+ rawBody = `${actor} pressed a button on message #${String(callbackActionEvent.targetMessageId)}
36215
36127
  ${JSON.stringify(payload)}`;
36216
- }
36217
- const dmPolicy = account.config.dmPolicy ?? "pairing";
36218
- const defaultGroupPolicy = cfg.channels?.defaults?.groupPolicy;
36219
- const groupPolicy = account.config.groupPolicy ?? defaultGroupPolicy ?? "allowlist";
36220
- const configAllowFrom = normalizeAllowlist(account.config.allowFrom);
36221
- const configGroupAllowFrom = normalizeAllowlist(account.config.groupAllowFrom);
36222
- const storeAllowFrom = await core3.channel.pairing.readAllowFromStore({
36223
- channel: CHANNEL_ID,
36224
- accountId: account.accountId
36225
- }).catch(() => []);
36226
- const storeAllowList = normalizeAllowlist(storeAllowFrom);
36227
- const effectiveAllowFrom = [...configAllowFrom, ...storeAllowList].filter(Boolean);
36228
- const effectiveGroupAllowFrom = [
36229
- ...configGroupAllowFrom.length > 0 ? configGroupAllowFrom : configAllowFrom,
36230
- ...storeAllowList
36231
- ].filter(Boolean);
36232
- const callbackCommandBody = callbackActionEvent ? resolveCallbackCommandBodyFromActionData({
36233
- data: callbackActionEvent.data,
36234
- ...botUsername ? { botUsername } : {}
36235
- }) : undefined;
36236
- let callbackActionAnswered = false;
36237
- const answerCallbackIfNeeded = async () => {
36238
- if (!callbackActionEvent || callbackActionAnswered)
36239
- return;
36240
- await answerInlineMessageAction(client, callbackActionEvent.interactionId);
36241
- callbackActionAnswered = true;
36242
- };
36243
- if (callbackActionEvent) {
36128
+ }
36129
+ const dmPolicy = account.config.dmPolicy ?? "pairing";
36130
+ const defaultGroupPolicy = cfg.channels?.defaults?.groupPolicy;
36131
+ const groupPolicy = account.config.groupPolicy ?? defaultGroupPolicy ?? "allowlist";
36132
+ const configAllowFrom = normalizeAllowlist(account.config.allowFrom);
36133
+ const configGroupAllowFrom = normalizeAllowlist(account.config.groupAllowFrom);
36134
+ const storeAllowFrom = await core3.channel.pairing.readAllowFromStore({
36135
+ channel: CHANNEL_ID,
36136
+ accountId: account.accountId
36137
+ }).catch(() => []);
36138
+ const storeAllowList = normalizeAllowlist(storeAllowFrom);
36139
+ const effectiveAllowFrom = [...configAllowFrom, ...storeAllowList].filter(Boolean);
36140
+ const effectiveGroupAllowFrom = [
36141
+ ...configGroupAllowFrom.length > 0 ? configGroupAllowFrom : configAllowFrom,
36142
+ ...storeAllowList
36143
+ ].filter(Boolean);
36144
+ const callbackCommandBody = callbackActionEvent ? resolveCallbackCommandBodyFromActionData({
36145
+ data: callbackActionEvent.data,
36146
+ ...botUsername ? { botUsername } : {}
36147
+ }) : undefined;
36148
+ let callbackActionAnswered = false;
36149
+ const answerCallbackIfNeeded = async () => {
36150
+ if (!callbackActionEvent || callbackActionAnswered)
36151
+ return;
36152
+ await answerInlineMessageAction(client, callbackActionEvent.interactionId);
36153
+ callbackActionAnswered = true;
36154
+ };
36155
+ if (callbackActionEvent) {
36156
+ await answerCallbackIfNeeded().catch((error48) => {
36157
+ runtime2.error?.(`inline callback answer failed: ${String(error48)}`);
36158
+ });
36159
+ }
36160
+ const shouldEditCallbackTargetInPlace = callbackActionEvent != null;
36161
+ const normalizedCommandBody = callbackCommandBody ?? normalizeInlineCommandBody(rawBody, botUsername);
36162
+ const allowTextCommands = core3.channel.commands.shouldHandleTextCommands({
36163
+ cfg,
36164
+ surface: CHANNEL_ID
36165
+ });
36166
+ const useAccessGroups = cfg.commands?.useAccessGroups !== false;
36167
+ const allowForCommands = isGroup ? effectiveGroupAllowFrom : effectiveAllowFrom;
36168
+ const senderAllowedForCommands = allowlistMatch({ allowFrom: allowForCommands, senderId });
36169
+ const hasControlCommand = core3.channel.text.hasControlCommand(callbackCommandBody ?? rawBody, cfg, botUsername ? { botUsername } : undefined);
36170
+ const commandGate = resolveControlCommandGate({
36171
+ useAccessGroups,
36172
+ authorizers: [{ configured: allowForCommands.length > 0, allowed: senderAllowedForCommands }],
36173
+ allowTextCommands,
36174
+ hasControlCommand
36175
+ });
36176
+ const commandAuthorized = commandGate.commandAuthorized;
36177
+ if (isGroup) {
36178
+ if (groupPolicy === "disabled") {
36179
+ log?.info(`[${account.accountId}] inline: drop group chat=${String(chatId)} (groupPolicy=disabled)`);
36180
+ await answerCallbackIfNeeded().catch((error48) => {
36181
+ runtime2.error?.(`inline callback answer failed: ${String(error48)}`);
36182
+ });
36183
+ return;
36184
+ }
36185
+ if (groupPolicy === "allowlist") {
36186
+ const allowed = allowlistMatch({ allowFrom: effectiveGroupAllowFrom, senderId });
36187
+ if (!allowed) {
36188
+ log?.info(`[${account.accountId}] inline: drop group sender=${senderId} (groupPolicy=allowlist)`);
36244
36189
  await answerCallbackIfNeeded().catch((error48) => {
36245
36190
  runtime2.error?.(`inline callback answer failed: ${String(error48)}`);
36246
36191
  });
36192
+ return;
36247
36193
  }
36248
- const shouldEditCallbackTargetInPlace = callbackActionEvent != null;
36249
- const normalizedCommandBody = callbackCommandBody ?? normalizeInlineCommandBody(rawBody, botUsername);
36250
- const allowTextCommands = core3.channel.commands.shouldHandleTextCommands({
36251
- cfg,
36252
- surface: CHANNEL_ID
36253
- });
36254
- const useAccessGroups = cfg.commands?.useAccessGroups !== false;
36255
- const allowForCommands = isGroup ? effectiveGroupAllowFrom : effectiveAllowFrom;
36256
- const senderAllowedForCommands = allowlistMatch({ allowFrom: allowForCommands, senderId });
36257
- const hasControlCommand = core3.channel.text.hasControlCommand(callbackCommandBody ?? rawBody, cfg, botUsername ? { botUsername } : undefined);
36258
- const commandGate = resolveControlCommandGate({
36259
- useAccessGroups,
36260
- authorizers: [{ configured: allowForCommands.length > 0, allowed: senderAllowedForCommands }],
36261
- allowTextCommands,
36262
- hasControlCommand
36194
+ }
36195
+ } else {
36196
+ if (dmPolicy === "disabled") {
36197
+ log?.info(`[${account.accountId}] inline: drop DM sender=${senderId} (dmPolicy=disabled)`);
36198
+ await answerCallbackIfNeeded().catch((error48) => {
36199
+ runtime2.error?.(`inline callback answer failed: ${String(error48)}`);
36263
36200
  });
36264
- const commandAuthorized = commandGate.commandAuthorized;
36265
- if (isGroup) {
36266
- if (groupPolicy === "disabled") {
36267
- log?.info(`[${account.accountId}] inline: drop group chat=${String(chatId)} (groupPolicy=disabled)`);
36268
- await answerCallbackIfNeeded().catch((error48) => {
36269
- runtime2.error?.(`inline callback answer failed: ${String(error48)}`);
36270
- });
36271
- continue;
36272
- }
36273
- if (groupPolicy === "allowlist") {
36274
- const allowed = allowlistMatch({ allowFrom: effectiveGroupAllowFrom, senderId });
36275
- if (!allowed) {
36276
- log?.info(`[${account.accountId}] inline: drop group sender=${senderId} (groupPolicy=allowlist)`);
36277
- await answerCallbackIfNeeded().catch((error48) => {
36278
- runtime2.error?.(`inline callback answer failed: ${String(error48)}`);
36279
- });
36280
- continue;
36281
- }
36282
- }
36283
- } else {
36284
- if (dmPolicy === "disabled") {
36285
- log?.info(`[${account.accountId}] inline: drop DM sender=${senderId} (dmPolicy=disabled)`);
36286
- await answerCallbackIfNeeded().catch((error48) => {
36287
- runtime2.error?.(`inline callback answer failed: ${String(error48)}`);
36201
+ return;
36202
+ }
36203
+ if (dmPolicy !== "open") {
36204
+ const allowed = allowlistMatch({ allowFrom: effectiveAllowFrom, senderId });
36205
+ if (!allowed) {
36206
+ if (dmPolicy === "pairing") {
36207
+ const { code, created } = await core3.channel.pairing.upsertPairingRequest({
36208
+ channel: CHANNEL_ID,
36209
+ id: senderId,
36210
+ accountId: account.accountId,
36211
+ meta: {},
36212
+ pairingAdapter: { idLabel: "inlineUserId", normalizeAllowEntry }
36288
36213
  });
36289
- continue;
36290
- }
36291
- if (dmPolicy !== "open") {
36292
- const allowed = allowlistMatch({ allowFrom: effectiveAllowFrom, senderId });
36293
- if (!allowed) {
36294
- if (dmPolicy === "pairing") {
36295
- const { code, created } = await core3.channel.pairing.upsertPairingRequest({
36296
- channel: CHANNEL_ID,
36297
- id: senderId,
36298
- accountId: account.accountId,
36299
- meta: {},
36300
- pairingAdapter: { idLabel: "inlineUserId", normalizeAllowEntry }
36214
+ if (created) {
36215
+ try {
36216
+ await client.sendMessage({
36217
+ chatId,
36218
+ text: core3.channel.pairing.buildPairingReply({
36219
+ channel: CHANNEL_ID,
36220
+ idLine: `Your Inline user id: ${senderId}`,
36221
+ code
36222
+ })
36301
36223
  });
36302
- if (created) {
36303
- try {
36304
- await client.sendMessage({
36305
- chatId,
36306
- text: core3.channel.pairing.buildPairingReply({
36307
- channel: CHANNEL_ID,
36308
- idLine: `Your Inline user id: ${senderId}`,
36309
- code
36310
- })
36311
- });
36312
- statusSink?.({ lastOutboundAt: Date.now() });
36313
- } catch (err) {
36314
- runtime2.error?.(`inline: pairing reply failed for ${senderId}: ${String(err)}`);
36315
- }
36316
- }
36224
+ statusSink?.({ lastOutboundAt: Date.now() });
36225
+ } catch (err) {
36226
+ runtime2.error?.(`inline: pairing reply failed for ${senderId}: ${String(err)}`);
36317
36227
  }
36318
- log?.info(`[${account.accountId}] inline: drop DM sender=${senderId} (dmPolicy=${dmPolicy})`);
36319
- await answerCallbackIfNeeded().catch((error48) => {
36320
- runtime2.error?.(`inline callback answer failed: ${String(error48)}`);
36321
- });
36322
- continue;
36323
36228
  }
36324
36229
  }
36325
- }
36326
- if (isGroup && commandGate.shouldBlock) {
36327
- logInboundDrop({
36328
- log: (m) => runtime2.log?.(m),
36329
- channel: CHANNEL_ID,
36330
- reason: "control command (unauthorized)",
36331
- target: senderId
36332
- });
36230
+ log?.info(`[${account.accountId}] inline: drop DM sender=${senderId} (dmPolicy=${dmPolicy})`);
36333
36231
  await answerCallbackIfNeeded().catch((error48) => {
36334
36232
  runtime2.error?.(`inline callback answer failed: ${String(error48)}`);
36335
36233
  });
36336
- continue;
36234
+ return;
36337
36235
  }
36338
- const route = core3.channel.routing.resolveAgentRoute({
36339
- cfg,
36340
- channel: CHANNEL_ID,
36341
- accountId: account.accountId,
36342
- peer: {
36343
- kind: isGroup ? "group" : "direct",
36344
- id: isGroup ? String(effectiveChatId) : senderId
36236
+ }
36237
+ }
36238
+ if (isGroup && commandGate.shouldBlock) {
36239
+ logInboundDrop({
36240
+ log: (m) => runtime2.log?.(m),
36241
+ channel: CHANNEL_ID,
36242
+ reason: "control command (unauthorized)",
36243
+ target: senderId
36244
+ });
36245
+ await answerCallbackIfNeeded().catch((error48) => {
36246
+ runtime2.error?.(`inline callback answer failed: ${String(error48)}`);
36247
+ });
36248
+ return;
36249
+ }
36250
+ const route = core3.channel.routing.resolveAgentRoute({
36251
+ cfg,
36252
+ channel: CHANNEL_ID,
36253
+ accountId: account.accountId,
36254
+ peer: {
36255
+ kind: isGroup ? "group" : "direct",
36256
+ id: isGroup ? String(effectiveChatId) : senderId
36257
+ }
36258
+ });
36259
+ const mentionRegexes = core3.channel.mentions.buildMentionRegexes(cfg, route.agentId);
36260
+ const nativeMentioned = typeof msg.mentioned === "boolean" ? msg.mentioned : false;
36261
+ const patternMentioned = mentionRegexes.length ? core3.channel.mentions.matchesMentionPatterns(rawBody, mentionRegexes) : false;
36262
+ const wasMentioned = nativeMentioned || patternMentioned;
36263
+ const messageTimestamp = Number(msg.date) * 1000;
36264
+ const groupHistoryKey = isGroup ? replyThreadContext ? `${route.sessionKey}:thread:${String(replyThreadContext.childChatId)}` : route.sessionKey : null;
36265
+ const pendingHistorySender = senderUsername ? `@${senderUsername}` : senderName ?? `user:${senderId}`;
36266
+ const historyLimit = resolveHistoryLimit({
36267
+ cfg,
36268
+ isGroup,
36269
+ historyLimit: account.config.historyLimit,
36270
+ dmHistoryLimit: account.config.dmHistoryLimit
36271
+ });
36272
+ const historyContext = await buildHistoryContext2({
36273
+ client,
36274
+ chatId,
36275
+ currentMessageId: msg.id,
36276
+ replyToMsgId: msg.replyToMsgId,
36277
+ senderProfilesById,
36278
+ meId,
36279
+ historyLimit,
36280
+ botMessageIdsByChat
36281
+ }).catch((err) => {
36282
+ statusSink?.({ lastError: `getChatHistory failed: ${String(err)}` });
36283
+ return {
36284
+ historyText: null,
36285
+ attachmentText: null,
36286
+ entityText: null,
36287
+ inboundHistory: [],
36288
+ repliedToBot: false,
36289
+ replyToSenderId: null
36290
+ };
36291
+ });
36292
+ const effectiveHistoryContext = replyThreadContext?.anchorMessage != null ? prependInlineReplyThreadAnchor({
36293
+ historyContext,
36294
+ anchorMessage: replyThreadContext.anchorMessage,
36295
+ parentChatId: replyThreadContext.parentChatId,
36296
+ senderProfilesById,
36297
+ meId
36298
+ }) : historyContext;
36299
+ const implicitMention = (reactionEvent != null || callbackActionEvent != null) && isGroup || isGroup && (account.config.replyToBotWithoutMention ?? false) && msg.replyToMsgId != null && effectiveHistoryContext.repliedToBot;
36300
+ const requireMention = isGroup ? resolveInlineGroupRequireMention({
36301
+ cfg,
36302
+ groupId: String(effectiveChatId),
36303
+ accountId: account.accountId,
36304
+ requireMentionDefault: account.config.requireMention ?? false
36305
+ }) : false;
36306
+ const mentionGate = resolveMentionGatingWithBypass({
36307
+ isGroup,
36308
+ requireMention,
36309
+ canDetectMention: typeof msg.mentioned === "boolean" || mentionRegexes.length > 0,
36310
+ wasMentioned,
36311
+ implicitMention,
36312
+ allowTextCommands,
36313
+ hasControlCommand,
36314
+ commandAuthorized
36315
+ });
36316
+ if (isGroup && mentionGate.shouldSkip) {
36317
+ runtime2.log?.(`inline: drop group chat ${String(chatId)} (no mention)`);
36318
+ const pendingBody = normalizeHistoryText(currentContent?.text) ?? normalizeHistoryText(rawBody);
36319
+ recordPendingHistoryEntryIfEnabled({
36320
+ historyMap: groupPendingHistories,
36321
+ historyKey: groupHistoryKey ?? "",
36322
+ limit: historyLimit,
36323
+ entry: groupHistoryKey && pendingBody ? {
36324
+ sender: pendingHistorySender,
36325
+ body: pendingBody,
36326
+ timestamp: messageTimestamp || Date.now(),
36327
+ messageId: String(msg.id)
36328
+ } : null
36329
+ });
36330
+ await answerCallbackIfNeeded().catch((error48) => {
36331
+ runtime2.error?.(`inline callback answer failed: ${String(error48)}`);
36332
+ });
36333
+ return;
36334
+ }
36335
+ const parseMarkdown = account.config.parseMarkdown ?? true;
36336
+ const nativeCommandMenu = resolveInlineNativeCommandMenu({
36337
+ commandBody: normalizedCommandBody,
36338
+ cfg
36339
+ });
36340
+ if (nativeCommandMenu) {
36341
+ const menuActions = resolveInlineReplyActions({
36342
+ channelData: {
36343
+ inline: {
36344
+ buttons: nativeCommandMenu.buttons
36345
36345
  }
36346
- });
36347
- const mentionRegexes = core3.channel.mentions.buildMentionRegexes(cfg, route.agentId);
36348
- const nativeMentioned = typeof msg.mentioned === "boolean" ? msg.mentioned : false;
36349
- const patternMentioned = mentionRegexes.length ? core3.channel.mentions.matchesMentionPatterns(rawBody, mentionRegexes) : false;
36350
- const wasMentioned = nativeMentioned || patternMentioned;
36351
- const messageTimestamp = Number(msg.date) * 1000;
36352
- const groupHistoryKey = isGroup ? replyThreadContext ? `${route.sessionKey}:thread:${String(replyThreadContext.childChatId)}` : route.sessionKey : null;
36353
- const pendingHistorySender = senderUsername ? `@${senderUsername}` : senderName ?? `user:${senderId}`;
36354
- const historyLimit = resolveHistoryLimit({
36355
- cfg,
36356
- isGroup,
36357
- historyLimit: account.config.historyLimit,
36358
- dmHistoryLimit: account.config.dmHistoryLimit
36359
- });
36360
- const historyContext = await buildHistoryContext2({
36361
- client,
36362
- chatId,
36363
- currentMessageId: msg.id,
36364
- replyToMsgId: msg.replyToMsgId,
36365
- senderProfilesById,
36366
- meId,
36367
- historyLimit,
36368
- botMessageIdsByChat
36369
- }).catch((err) => {
36370
- statusSink?.({ lastError: `getChatHistory failed: ${String(err)}` });
36371
- return {
36372
- historyText: null,
36373
- attachmentText: null,
36374
- entityText: null,
36375
- inboundHistory: [],
36376
- repliedToBot: false,
36377
- replyToSenderId: null
36378
- };
36379
- });
36380
- const effectiveHistoryContext = replyThreadContext?.anchorMessage != null ? prependInlineReplyThreadAnchor({
36381
- historyContext,
36382
- anchorMessage: replyThreadContext.anchorMessage,
36383
- parentChatId: replyThreadContext.parentChatId,
36384
- senderProfilesById,
36385
- meId
36386
- }) : historyContext;
36387
- const implicitMention = (reactionEvent != null || callbackActionEvent != null) && isGroup || isGroup && (account.config.replyToBotWithoutMention ?? false) && msg.replyToMsgId != null && effectiveHistoryContext.repliedToBot;
36388
- const requireMention = isGroup ? resolveInlineGroupRequireMention({
36389
- cfg,
36390
- groupId: String(effectiveChatId),
36391
- accountId: account.accountId,
36392
- requireMentionDefault: account.config.requireMention ?? false
36393
- }) : false;
36394
- const mentionGate = resolveMentionGatingWithBypass({
36395
- isGroup,
36396
- requireMention,
36397
- canDetectMention: typeof msg.mentioned === "boolean" || mentionRegexes.length > 0,
36398
- wasMentioned,
36399
- implicitMention,
36400
- allowTextCommands,
36401
- hasControlCommand,
36402
- commandAuthorized
36403
- });
36404
- if (isGroup && mentionGate.shouldSkip) {
36405
- runtime2.log?.(`inline: drop group chat ${String(chatId)} (no mention)`);
36406
- const pendingBody = normalizeHistoryText(currentContent?.text) ?? normalizeHistoryText(rawBody);
36407
- recordPendingHistoryEntryIfEnabled({
36408
- historyMap: groupPendingHistories,
36409
- historyKey: groupHistoryKey ?? "",
36410
- limit: historyLimit,
36411
- entry: groupHistoryKey && pendingBody ? {
36412
- sender: pendingHistorySender,
36413
- body: pendingBody,
36414
- timestamp: messageTimestamp || Date.now(),
36415
- messageId: String(msg.id)
36416
- } : null
36417
- });
36418
- await answerCallbackIfNeeded().catch((error48) => {
36419
- runtime2.error?.(`inline callback answer failed: ${String(error48)}`);
36420
- });
36421
- continue;
36422
36346
  }
36423
- const parseMarkdown = account.config.parseMarkdown ?? true;
36424
- const nativeCommandMenu = resolveInlineNativeCommandMenu({
36425
- commandBody: normalizedCommandBody,
36426
- cfg
36427
- });
36428
- if (nativeCommandMenu) {
36429
- const menuActions = resolveInlineReplyActions({
36430
- channelData: {
36431
- inline: {
36432
- buttons: nativeCommandMenu.buttons
36433
- }
36347
+ });
36348
+ let deliveredNativeMenu = false;
36349
+ if (shouldEditCallbackTargetInPlace && callbackActionEvent) {
36350
+ try {
36351
+ const result = await client.invokeRaw(Method.EDIT_MESSAGE, {
36352
+ oneofKind: "editMessage",
36353
+ editMessage: {
36354
+ messageId: callbackActionEvent.targetMessageId,
36355
+ peerId: buildChatPeer2(chatId),
36356
+ text: nativeCommandMenu.title,
36357
+ ...menuActions ? { actions: menuActions } : {},
36358
+ parseMarkdown
36434
36359
  }
36435
36360
  });
36436
- let deliveredNativeMenu = false;
36437
- if (shouldEditCallbackTargetInPlace && callbackActionEvent) {
36438
- try {
36439
- const result = await client.invokeRaw(Method.EDIT_MESSAGE, {
36440
- oneofKind: "editMessage",
36441
- editMessage: {
36442
- messageId: callbackActionEvent.targetMessageId,
36443
- peerId: buildChatPeer2(chatId),
36444
- text: nativeCommandMenu.title,
36445
- ...menuActions ? { actions: menuActions } : {},
36446
- parseMarkdown
36447
- }
36448
- });
36449
- if (result.oneofKind !== "editMessage") {
36450
- throw new Error(`inline native command menu: expected editMessage result, got ${String(result.oneofKind)}`);
36451
- }
36452
- deliveredNativeMenu = true;
36453
- } catch (error48) {
36454
- runtime2.error?.(`inline native command menu edit failed; falling back to send (${String(error48)})`);
36361
+ if (result.oneofKind !== "editMessage") {
36362
+ throw new Error(`inline native command menu: expected editMessage result, got ${String(result.oneofKind)}`);
36363
+ }
36364
+ deliveredNativeMenu = true;
36365
+ } catch (error48) {
36366
+ runtime2.error?.(`inline native command menu edit failed; falling back to send (${String(error48)})`);
36367
+ }
36368
+ }
36369
+ if (!deliveredNativeMenu) {
36370
+ const sent = await client.sendMessage({
36371
+ chatId,
36372
+ text: nativeCommandMenu.title,
36373
+ ...menuActions ? { actions: menuActions } : {}
36374
+ });
36375
+ if (sent.messageId != null) {
36376
+ rememberBotMessageId(botMessageIdsByChat, chatId, sent.messageId);
36377
+ }
36378
+ }
36379
+ statusSink?.({ lastOutboundAt: Date.now() });
36380
+ await answerCallbackIfNeeded().catch((error48) => {
36381
+ runtime2.error?.(`inline callback answer failed: ${String(error48)}`);
36382
+ });
36383
+ return;
36384
+ }
36385
+ const modelPickerCallbackData = callbackActionEvent ? callbackDataToUtf8(callbackActionEvent.data) : undefined;
36386
+ const modelPickerCallback = modelPickerCallbackData ? parseInlineModelPickerCallback(modelPickerCallbackData) : null;
36387
+ if (shouldEditCallbackTargetInPlace && callbackActionEvent && modelPickerCallback?.type === "select") {
36388
+ const deliverModelPickerEdit = async (text, buttons) => {
36389
+ const actions = resolveInlineReplyActions({
36390
+ channelData: {
36391
+ inline: {
36392
+ buttons
36455
36393
  }
36456
36394
  }
36457
- if (!deliveredNativeMenu) {
36458
- const sent = await client.sendMessage({
36459
- chatId,
36460
- text: nativeCommandMenu.title,
36461
- ...menuActions ? { actions: menuActions } : {}
36462
- });
36463
- if (sent.messageId != null) {
36464
- rememberBotMessageId(botMessageIdsByChat, chatId, sent.messageId);
36395
+ }) ?? { rows: [] };
36396
+ try {
36397
+ const result = await client.invokeRaw(Method.EDIT_MESSAGE, {
36398
+ oneofKind: "editMessage",
36399
+ editMessage: {
36400
+ messageId: callbackActionEvent.targetMessageId,
36401
+ peerId: buildChatPeer2(chatId),
36402
+ text,
36403
+ actions,
36404
+ parseMarkdown
36465
36405
  }
36406
+ });
36407
+ if (result.oneofKind !== "editMessage") {
36408
+ throw new Error(`inline model picker edit: expected editMessage result, got ${String(result.oneofKind)}`);
36466
36409
  }
36467
- statusSink?.({ lastOutboundAt: Date.now() });
36468
- await answerCallbackIfNeeded().catch((error48) => {
36469
- runtime2.error?.(`inline callback answer failed: ${String(error48)}`);
36410
+ } catch (error48) {
36411
+ runtime2.error?.(`inline model picker edit failed; falling back to send (${String(error48)})`);
36412
+ const sent = await client.sendMessage({
36413
+ chatId,
36414
+ text,
36415
+ actions,
36416
+ parseMarkdown
36470
36417
  });
36471
- continue;
36418
+ if (sent.messageId != null) {
36419
+ rememberBotMessageId(botMessageIdsByChat, chatId, sent.messageId);
36420
+ }
36472
36421
  }
36473
- const modelPickerCallbackData = callbackActionEvent ? callbackDataToUtf8(callbackActionEvent.data) : undefined;
36474
- const modelPickerCallback = modelPickerCallbackData ? parseInlineModelPickerCallback(modelPickerCallbackData) : null;
36475
- if (shouldEditCallbackTargetInPlace && callbackActionEvent && modelPickerCallback?.type === "select") {
36476
- const deliverModelPickerEdit = async (text, buttons) => {
36477
- const actions = resolveInlineReplyActions({
36478
- channelData: {
36479
- inline: {
36480
- buttons
36481
- }
36482
- }
36483
- }) ?? { rows: [] };
36484
- try {
36485
- const result = await client.invokeRaw(Method.EDIT_MESSAGE, {
36486
- oneofKind: "editMessage",
36487
- editMessage: {
36488
- messageId: callbackActionEvent.targetMessageId,
36489
- peerId: buildChatPeer2(chatId),
36490
- text,
36491
- actions,
36492
- parseMarkdown
36493
- }
36494
- });
36495
- if (result.oneofKind !== "editMessage") {
36496
- throw new Error(`inline model picker edit: expected editMessage result, got ${String(result.oneofKind)}`);
36497
- }
36498
- } catch (error48) {
36499
- runtime2.error?.(`inline model picker edit failed; falling back to send (${String(error48)})`);
36500
- const sent = await client.sendMessage({
36501
- chatId,
36502
- text,
36503
- actions,
36504
- parseMarkdown
36505
- });
36506
- if (sent.messageId != null) {
36507
- rememberBotMessageId(botMessageIdsByChat, chatId, sent.messageId);
36508
- }
36509
- }
36510
- };
36511
- const { byProvider, providers } = await buildModelsProviderData(cfg, route.agentId);
36512
- const providerButtons = buildInlineModelProviderButtons(providers.map((provider) => ({
36513
- id: provider,
36514
- count: byProvider.get(provider)?.size ?? 0
36515
- })));
36516
- const selection = resolveInlineModelPickerSelection({
36517
- callback: modelPickerCallback,
36518
- providers,
36519
- byProvider
36520
- });
36521
- if (selection.kind !== "resolved") {
36522
- await deliverModelPickerEdit(`Could not resolve model "${selection.model}".
36422
+ };
36423
+ const { byProvider, providers } = await buildModelsProviderData(cfg, route.agentId);
36424
+ const providerButtons = buildInlineModelProviderButtons(providers.map((provider) => ({
36425
+ id: provider,
36426
+ count: byProvider.get(provider)?.size ?? 0
36427
+ })));
36428
+ const selection = resolveInlineModelPickerSelection({
36429
+ callback: modelPickerCallback,
36430
+ providers,
36431
+ byProvider
36432
+ });
36433
+ if (selection.kind !== "resolved") {
36434
+ await deliverModelPickerEdit(`Could not resolve model "${selection.model}".
36523
36435
 
36524
36436
  Select a provider:`, providerButtons);
36525
- } else {
36526
- const modelSet = byProvider.get(selection.provider);
36527
- if (!modelSet?.has(selection.model)) {
36528
- await deliverModelPickerEdit(`❌ Model "${selection.provider}/${selection.model}" is not allowed.`, []);
36529
- } else {
36530
- try {
36531
- const storePath2 = core3.channel.session.resolveStorePath(cfg.session?.store, {
36532
- agentId: route.agentId
36533
- });
36534
- const resolvedDefault = resolveDefaultModelForAgent({
36535
- cfg,
36536
- agentId: route.agentId
36537
- });
36538
- const isDefaultSelection = selection.provider === resolvedDefault.provider && selection.model === resolvedDefault.model;
36539
- await updateSessionStore(storePath2, (store) => {
36540
- const entry = store[route.sessionKey] ?? {
36541
- sessionId: route.sessionKey,
36542
- updatedAt: Date.now()
36543
- };
36544
- store[route.sessionKey] = entry;
36545
- applyModelOverrideToSessionEntry({
36546
- entry,
36547
- selection: {
36548
- provider: selection.provider,
36549
- model: selection.model,
36550
- isDefault: isDefaultSelection
36551
- }
36552
- });
36553
- });
36554
- const actionText = isDefaultSelection ? "reset to default" : `changed to **${selection.provider}/${selection.model}**`;
36555
- await deliverModelPickerEdit(`✅ Model ${actionText}
36437
+ } else {
36438
+ const modelSet = byProvider.get(selection.provider);
36439
+ if (!modelSet?.has(selection.model)) {
36440
+ await deliverModelPickerEdit(`❌ Model "${selection.provider}/${selection.model}" is not allowed.`, []);
36441
+ } else {
36442
+ try {
36443
+ const storePath2 = core3.channel.session.resolveStorePath(cfg.session?.store, {
36444
+ agentId: route.agentId
36445
+ });
36446
+ const resolvedDefault = resolveDefaultModelForAgent({
36447
+ cfg,
36448
+ agentId: route.agentId
36449
+ });
36450
+ const isDefaultSelection = selection.provider === resolvedDefault.provider && selection.model === resolvedDefault.model;
36451
+ await updateSessionStore(storePath2, (store) => {
36452
+ const entry = store[route.sessionKey] ?? {
36453
+ sessionId: route.sessionKey,
36454
+ updatedAt: Date.now()
36455
+ };
36456
+ store[route.sessionKey] = entry;
36457
+ applyModelOverrideToSessionEntry({
36458
+ entry,
36459
+ selection: {
36460
+ provider: selection.provider,
36461
+ model: selection.model,
36462
+ isDefault: isDefaultSelection
36463
+ }
36464
+ });
36465
+ });
36466
+ const actionText = isDefaultSelection ? "reset to default" : `changed to **${selection.provider}/${selection.model}**`;
36467
+ await deliverModelPickerEdit(`✅ Model ${actionText}
36556
36468
 
36557
36469
  This model will be used for your next message.`, []);
36558
- } catch (error48) {
36559
- await deliverModelPickerEdit(`❌ Failed to change model: ${String(error48)}`, []);
36560
- }
36561
- }
36470
+ } catch (error48) {
36471
+ await deliverModelPickerEdit(`❌ Failed to change model: ${String(error48)}`, []);
36562
36472
  }
36563
- statusSink?.({ lastOutboundAt: Date.now() });
36564
- await answerCallbackIfNeeded().catch((error48) => {
36565
- runtime2.error?.(`inline callback answer failed: ${String(error48)}`);
36566
- });
36567
- continue;
36568
36473
  }
36569
- const inboundMedia = reactionEvent ? [] : await resolveInlineInboundMedia({
36570
- core: core3,
36571
- message: msg,
36572
- maxBytes: inboundMediaMaxBytes,
36573
- ...log ? { log } : {}
36574
- });
36575
- const timestamp = messageTimestamp;
36576
- const fromLabel = isGroup ? `chat:${effectiveGroupTitle ?? String(effectiveChatId)}` : `user:${senderId}`;
36577
- const storePath = core3.channel.session.resolveStorePath(cfg.session?.store, { agentId: route.agentId });
36578
- const envelopeOptions = core3.channel.reply.resolveEnvelopeFormatOptions(cfg);
36579
- const previousTimestamp = core3.channel.session.readSessionUpdatedAt({ storePath, sessionKey: route.sessionKey });
36580
- const combinedBody = [
36581
- effectiveHistoryContext.historyText,
36582
- effectiveHistoryContext.attachmentText,
36583
- effectiveHistoryContext.entityText,
36584
- INLINE_FORMATTING_NOTE,
36585
- `Current message:
36474
+ }
36475
+ statusSink?.({ lastOutboundAt: Date.now() });
36476
+ await answerCallbackIfNeeded().catch((error48) => {
36477
+ runtime2.error?.(`inline callback answer failed: ${String(error48)}`);
36478
+ });
36479
+ return;
36480
+ }
36481
+ const inboundMedia = reactionEvent ? [] : await resolveInlineInboundMedia({
36482
+ core: core3,
36483
+ message: msg,
36484
+ maxBytes: inboundMediaMaxBytes,
36485
+ ...log ? { log } : {}
36486
+ });
36487
+ const timestamp = messageTimestamp;
36488
+ const fromLabel = isGroup ? `chat:${effectiveGroupTitle ?? String(effectiveChatId)}` : `user:${senderId}`;
36489
+ const storePath = core3.channel.session.resolveStorePath(cfg.session?.store, { agentId: route.agentId });
36490
+ const envelopeOptions = core3.channel.reply.resolveEnvelopeFormatOptions(cfg);
36491
+ const previousTimestamp = core3.channel.session.readSessionUpdatedAt({ storePath, sessionKey: route.sessionKey });
36492
+ const combinedBody = [
36493
+ effectiveHistoryContext.historyText,
36494
+ effectiveHistoryContext.attachmentText,
36495
+ effectiveHistoryContext.entityText,
36496
+ INLINE_FORMATTING_NOTE,
36497
+ `Current message:
36586
36498
  ${rawBody}`,
36587
- currentAttachmentText && currentAttachmentText !== rawBody ? `Current media/attachments:
36499
+ currentAttachmentText && currentAttachmentText !== rawBody ? `Current media/attachments:
36588
36500
  ${currentAttachmentText}` : null,
36589
- currentEntityText ? `Current message entities:
36501
+ currentEntityText ? `Current message entities:
36590
36502
  ${currentEntityText}` : null
36591
- ].filter(Boolean).join(`
36503
+ ].filter(Boolean).join(`
36592
36504
 
36593
36505
  `);
36594
- let body = core3.channel.reply.formatAgentEnvelope({
36506
+ let body = core3.channel.reply.formatAgentEnvelope({
36507
+ channel: "Inline",
36508
+ from: fromLabel,
36509
+ timestamp,
36510
+ ...previousTimestamp != null ? { previousTimestamp } : {},
36511
+ envelope: envelopeOptions,
36512
+ body: combinedBody || rawBody
36513
+ });
36514
+ if (isGroup && groupHistoryKey) {
36515
+ body = buildPendingHistoryContextFromMap({
36516
+ historyMap: groupPendingHistories,
36517
+ historyKey: groupHistoryKey,
36518
+ limit: historyLimit,
36519
+ currentMessage: body,
36520
+ formatEntry: (entry) => core3.channel.reply.formatAgentEnvelope({
36595
36521
  channel: "Inline",
36596
36522
  from: fromLabel,
36597
- timestamp,
36598
- ...previousTimestamp != null ? { previousTimestamp } : {},
36523
+ ...entry.timestamp != null ? { timestamp: entry.timestamp } : {},
36599
36524
  envelope: envelopeOptions,
36600
- body: combinedBody || rawBody
36601
- });
36602
- if (isGroup && groupHistoryKey) {
36603
- body = buildPendingHistoryContextFromMap({
36604
- historyMap: groupPendingHistories,
36605
- historyKey: groupHistoryKey,
36606
- limit: historyLimit,
36607
- currentMessage: body,
36608
- formatEntry: (entry) => core3.channel.reply.formatAgentEnvelope({
36609
- channel: "Inline",
36610
- from: fromLabel,
36611
- ...entry.timestamp != null ? { timestamp: entry.timestamp } : {},
36612
- envelope: envelopeOptions,
36613
- body: `${entry.body}${entry.messageId ? ` [id:${entry.messageId} chat:${String(chatId)}]` : ""}`
36614
- })
36615
- });
36525
+ body: `${entry.body}${entry.messageId ? ` [id:${entry.messageId} chat:${String(chatId)}]` : ""}`
36526
+ })
36527
+ });
36528
+ }
36529
+ const inboundHistory = isGroup && groupHistoryKey ? mergeInboundHistoryEntries({
36530
+ historyContextEntries: effectiveHistoryContext.inboundHistory,
36531
+ pendingEntries: groupPendingHistories.get(groupHistoryKey) ?? [],
36532
+ limit: historyLimit
36533
+ }) : [];
36534
+ const bodyForAgent = buildInlineBodyForAgent({
36535
+ rawBody,
36536
+ currentAttachmentText,
36537
+ currentEntityText
36538
+ });
36539
+ const effectiveSurface = shouldUseTelegramSurfaceForModelCommands(normalizedCommandBody) ? "telegram" : CHANNEL_ID;
36540
+ const systemPrompt = resolveInlineSystemPrompt({
36541
+ account,
36542
+ ...isGroup ? { groupId: String(effectiveChatId) } : {}
36543
+ });
36544
+ const ctxPayload = core3.channel.reply.finalizeInboundContext({
36545
+ Body: body,
36546
+ BodyForAgent: bodyForAgent,
36547
+ ...isGroup ? { InboundHistory: inboundHistory } : {},
36548
+ RawBody: rawBody,
36549
+ CommandBody: normalizedCommandBody,
36550
+ From: isGroup ? `inline:chat:${String(effectiveChatId)}` : `inline:${senderId}`,
36551
+ To: `inline:${String(effectiveChatId)}`,
36552
+ SessionKey: route.sessionKey,
36553
+ ...replyThreadContext ? { ParentSessionKey: route.sessionKey } : {},
36554
+ AccountId: route.accountId,
36555
+ ChatType: isGroup ? "group" : "direct",
36556
+ ConversationLabel: fromLabel,
36557
+ ...isGroup ? { GroupSubject: effectiveGroupTitle ?? String(effectiveChatId) } : {},
36558
+ SenderId: senderId,
36559
+ ...senderName ? { SenderName: senderName } : {},
36560
+ ...senderUsername ? { SenderUsername: senderUsername } : {},
36561
+ Provider: CHANNEL_ID,
36562
+ Surface: effectiveSurface,
36563
+ MessageSid: buildInlineInboundMessageSid({
36564
+ msgId: msg.id,
36565
+ ...callbackActionEvent ? { callbackActionEvent } : {}
36566
+ }),
36567
+ ...replyThreadContext ? { MessageThreadId: String(replyThreadContext.childChatId) } : {},
36568
+ ...replyThreadContext?.threadLabel ? { ThreadLabel: replyThreadContext.threadLabel } : {},
36569
+ ...msg.replyToMsgId != null ? { ReplyToId: String(msg.replyToMsgId) } : {},
36570
+ ...effectiveHistoryContext.replyToSenderId != null ? { ReplyToSenderId: effectiveHistoryContext.replyToSenderId } : {},
36571
+ ...msg.replyToMsgId != null ? { ReplyToWasBot: effectiveHistoryContext.repliedToBot } : {},
36572
+ ...callbackActionEvent ? {
36573
+ MessageActionInteractionId: String(callbackActionEvent.interactionId),
36574
+ MessageActionId: callbackActionEvent.actionId,
36575
+ MessageActionDataBase64: callbackDataToBase64(callbackActionEvent.data),
36576
+ ...callbackDataToUtf8(callbackActionEvent.data) ? { MessageActionDataUtf8: callbackDataToUtf8(callbackActionEvent.data) } : {}
36577
+ } : {},
36578
+ ...buildInlineInboundMediaPayload(inboundMedia),
36579
+ Timestamp: timestamp || Date.now(),
36580
+ WasMentioned: mentionGate.effectiveWasMentioned,
36581
+ CommandAuthorized: commandAuthorized,
36582
+ GroupSystemPrompt: systemPrompt,
36583
+ OriginatingChannel: CHANNEL_ID,
36584
+ OriginatingTo: `inline:${String(effectiveChatId)}`
36585
+ });
36586
+ await core3.channel.session.recordInboundSession({
36587
+ storePath,
36588
+ sessionKey: ctxPayload.SessionKey ?? route.sessionKey,
36589
+ ctx: ctxPayload,
36590
+ ...!isGroup ? {
36591
+ updateLastRoute: {
36592
+ sessionKey: route.mainSessionKey,
36593
+ channel: CHANNEL_ID,
36594
+ to: `inline:${String(effectiveChatId)}`,
36595
+ accountId: route.accountId
36616
36596
  }
36617
- const inboundHistory = isGroup && groupHistoryKey ? mergeInboundHistoryEntries({
36618
- historyContextEntries: effectiveHistoryContext.inboundHistory,
36619
- pendingEntries: groupPendingHistories.get(groupHistoryKey) ?? [],
36620
- limit: historyLimit
36621
- }) : [];
36622
- const bodyForAgent = buildInlineBodyForAgent({
36623
- rawBody,
36624
- currentAttachmentText,
36625
- currentEntityText
36626
- });
36627
- const effectiveSurface = shouldUseTelegramSurfaceForModelCommands(normalizedCommandBody) ? "telegram" : CHANNEL_ID;
36628
- const systemPrompt = resolveInlineSystemPrompt({
36629
- account,
36630
- ...isGroup ? { groupId: String(effectiveChatId) } : {}
36631
- });
36632
- const ctxPayload = core3.channel.reply.finalizeInboundContext({
36633
- Body: body,
36634
- BodyForAgent: bodyForAgent,
36635
- ...isGroup ? { InboundHistory: inboundHistory } : {},
36636
- RawBody: rawBody,
36637
- CommandBody: normalizedCommandBody,
36638
- From: isGroup ? `inline:chat:${String(effectiveChatId)}` : `inline:${senderId}`,
36639
- To: `inline:${String(effectiveChatId)}`,
36640
- SessionKey: route.sessionKey,
36641
- ...replyThreadContext ? { ParentSessionKey: route.sessionKey } : {},
36642
- AccountId: route.accountId,
36643
- ChatType: isGroup ? "group" : "direct",
36644
- ConversationLabel: fromLabel,
36645
- ...isGroup ? { GroupSubject: effectiveGroupTitle ?? String(effectiveChatId) } : {},
36646
- SenderId: senderId,
36647
- ...senderName ? { SenderName: senderName } : {},
36648
- ...senderUsername ? { SenderUsername: senderUsername } : {},
36649
- Provider: CHANNEL_ID,
36650
- Surface: effectiveSurface,
36651
- MessageSid: buildInlineInboundMessageSid({
36652
- msgId: msg.id,
36653
- ...callbackActionEvent ? { callbackActionEvent } : {}
36654
- }),
36655
- ...replyThreadContext ? { MessageThreadId: String(replyThreadContext.childChatId) } : {},
36656
- ...replyThreadContext?.threadLabel ? { ThreadLabel: replyThreadContext.threadLabel } : {},
36657
- ...msg.replyToMsgId != null ? { ReplyToId: String(msg.replyToMsgId) } : {},
36658
- ...effectiveHistoryContext.replyToSenderId != null ? { ReplyToSenderId: effectiveHistoryContext.replyToSenderId } : {},
36659
- ...msg.replyToMsgId != null ? { ReplyToWasBot: effectiveHistoryContext.repliedToBot } : {},
36660
- ...callbackActionEvent ? {
36661
- MessageActionInteractionId: String(callbackActionEvent.interactionId),
36662
- MessageActionId: callbackActionEvent.actionId,
36663
- MessageActionDataBase64: callbackDataToBase64(callbackActionEvent.data),
36664
- ...callbackDataToUtf8(callbackActionEvent.data) ? { MessageActionDataUtf8: callbackDataToUtf8(callbackActionEvent.data) } : {}
36665
- } : {},
36666
- ...buildInlineInboundMediaPayload(inboundMedia),
36667
- Timestamp: timestamp || Date.now(),
36668
- WasMentioned: mentionGate.effectiveWasMentioned,
36669
- CommandAuthorized: commandAuthorized,
36670
- GroupSystemPrompt: systemPrompt,
36671
- OriginatingChannel: CHANNEL_ID,
36672
- OriginatingTo: `inline:${String(effectiveChatId)}`
36673
- });
36674
- await core3.channel.session.recordInboundSession({
36675
- storePath,
36676
- sessionKey: ctxPayload.SessionKey ?? route.sessionKey,
36677
- ctx: ctxPayload,
36678
- ...!isGroup ? {
36679
- updateLastRoute: {
36680
- sessionKey: route.mainSessionKey,
36681
- channel: CHANNEL_ID,
36682
- to: `inline:${String(effectiveChatId)}`,
36683
- accountId: route.accountId
36597
+ } : {},
36598
+ onRecordError: (err) => runtime2.error?.(`inline: failed updating session meta: ${String(err)}`)
36599
+ });
36600
+ const replyPipeline = await createChannelReplyPipelineCompat({
36601
+ cfg,
36602
+ agentId: route.agentId,
36603
+ channel: CHANNEL_ID,
36604
+ accountId: account.accountId,
36605
+ typing: {
36606
+ start: () => client.sendTyping({ chatId, typing: true }),
36607
+ stop: () => client.sendTyping({ chatId, typing: false }),
36608
+ onStartError: (err) => runtime2.error?.(`inline typing start failed: ${String(err)}`),
36609
+ onStopError: (err) => runtime2.error?.(`inline typing stop failed: ${String(err)}`)
36610
+ }
36611
+ });
36612
+ const onModelSelected = replyPipeline.onModelSelected;
36613
+ const typingCallbacks = replyPipeline.typingCallbacks;
36614
+ const prefixOptions = {
36615
+ ...replyPipeline.responsePrefix !== undefined ? { responsePrefix: replyPipeline.responsePrefix } : {},
36616
+ ...replyPipeline.enableSlackInteractiveReplies !== undefined ? { enableSlackInteractiveReplies: replyPipeline.enableSlackInteractiveReplies } : {},
36617
+ ...replyPipeline.responsePrefixContextProvider ? {
36618
+ responsePrefixContextProvider: replyPipeline.responsePrefixContextProvider
36619
+ } : {}
36620
+ };
36621
+ const callbackTargetMessage = shouldEditCallbackTargetInPlace && callbackActionEvent ? await findChatMessageById({
36622
+ client,
36623
+ chatId,
36624
+ messageId: callbackActionEvent.targetMessageId,
36625
+ limit: REPLY_TARGET_LOOKUP_LIMIT,
36626
+ meId,
36627
+ botMessageIdsByChat
36628
+ }).catch(() => null) : null;
36629
+ const streamViaEditMessage = account.config.streamViaEditMessage === true && !shouldEditCallbackTargetInPlace;
36630
+ const defaultReplyToMsgId = isGroup && msg.replyToMsgId != null ? msg.id : undefined;
36631
+ const disableBlockStreaming = streamViaEditMessage ? true : typeof account.config.blockStreaming === "boolean" ? !account.config.blockStreaming : undefined;
36632
+ const editStreamState = {
36633
+ messageId: shouldEditCallbackTargetInPlace ? callbackActionEvent?.targetMessageId ?? null : null,
36634
+ accumulatedText: callbackTargetMessage?.message ?? "",
36635
+ lastPartialText: "",
36636
+ finalTextAccumulator: "",
36637
+ failed: false,
36638
+ opChain: Promise.resolve()
36639
+ };
36640
+ let finalDeliveredForCurrentAssistantMessage = false;
36641
+ const resetEditStreamForAssistantMessage = async () => {
36642
+ await editStreamState.opChain;
36643
+ const hasActiveState = editStreamState.messageId != null || editStreamState.accumulatedText.length > 0 || editStreamState.lastPartialText.length > 0 || editStreamState.finalTextAccumulator.length > 0;
36644
+ if (!hasActiveState)
36645
+ return;
36646
+ editStreamState.messageId = null;
36647
+ editStreamState.accumulatedText = "";
36648
+ editStreamState.lastPartialText = "";
36649
+ editStreamState.finalTextAccumulator = "";
36650
+ editStreamState.failed = false;
36651
+ finalDeliveredForCurrentAssistantMessage = false;
36652
+ };
36653
+ const resetEditStreamOnBoundary = async () => {
36654
+ if (!streamViaEditMessage)
36655
+ return;
36656
+ await resetEditStreamForAssistantMessage();
36657
+ };
36658
+ const handlePartialStreamPayload = async (payload) => {
36659
+ if (editStreamState.failed)
36660
+ return;
36661
+ if ((payload.mediaUrls?.length ?? 0) > 0)
36662
+ return;
36663
+ const partialText = typeof payload.text === "string" ? payload.text : "";
36664
+ if (!partialText || partialText === editStreamState.lastPartialText)
36665
+ return;
36666
+ editStreamState.lastPartialText = partialText;
36667
+ const nextText = rewriteNumericMentionsToUsernames(extractCompleteParagraphText(partialText), senderProfilesById).trim();
36668
+ if (!nextText || nextText === editStreamState.accumulatedText)
36669
+ return;
36670
+ editStreamState.opChain = editStreamState.opChain.then(async () => {
36671
+ if (editStreamState.failed)
36672
+ return;
36673
+ if (!nextText || nextText === editStreamState.accumulatedText)
36674
+ return;
36675
+ try {
36676
+ if (editStreamState.messageId == null) {
36677
+ const sent = await client.sendMessage({
36678
+ chatId,
36679
+ text: nextText,
36680
+ ...defaultReplyToMsgId != null ? { replyToMsgId: defaultReplyToMsgId } : {},
36681
+ parseMarkdown
36682
+ });
36683
+ if (sent.messageId == null) {
36684
+ throw new Error("inline edit stream: sendMessage returned no messageId");
36685
+ }
36686
+ editStreamState.messageId = sent.messageId;
36687
+ rememberBotMessageId(botMessageIdsByChat, chatId, sent.messageId);
36688
+ } else {
36689
+ const result = await client.invokeRaw(Method.EDIT_MESSAGE, {
36690
+ oneofKind: "editMessage",
36691
+ editMessage: {
36692
+ messageId: editStreamState.messageId,
36693
+ peerId: buildChatPeer2(chatId),
36694
+ text: nextText,
36695
+ parseMarkdown
36696
+ }
36697
+ });
36698
+ if (result.oneofKind !== "editMessage") {
36699
+ throw new Error(`inline edit stream: expected editMessage result, got ${String(result.oneofKind)}`);
36684
36700
  }
36685
- } : {},
36686
- onRecordError: (err) => runtime2.error?.(`inline: failed updating session meta: ${String(err)}`)
36687
- });
36688
- const replyPipeline = await createChannelReplyPipelineCompat({
36689
- cfg,
36690
- agentId: route.agentId,
36691
- channel: CHANNEL_ID,
36692
- accountId: account.accountId,
36693
- typing: {
36694
- start: () => client.sendTyping({ chatId, typing: true }),
36695
- stop: () => client.sendTyping({ chatId, typing: false }),
36696
- onStartError: (err) => runtime2.error?.(`inline typing start failed: ${String(err)}`),
36697
- onStopError: (err) => runtime2.error?.(`inline typing stop failed: ${String(err)}`)
36698
36701
  }
36699
- });
36700
- const onModelSelected = replyPipeline.onModelSelected;
36701
- const typingCallbacks = replyPipeline.typingCallbacks;
36702
- const prefixOptions = {
36703
- ...replyPipeline.responsePrefix !== undefined ? { responsePrefix: replyPipeline.responsePrefix } : {},
36704
- ...replyPipeline.enableSlackInteractiveReplies !== undefined ? { enableSlackInteractiveReplies: replyPipeline.enableSlackInteractiveReplies } : {},
36705
- ...replyPipeline.responsePrefixContextProvider ? {
36706
- responsePrefixContextProvider: replyPipeline.responsePrefixContextProvider
36707
- } : {}
36708
- };
36709
- const callbackTargetMessage = shouldEditCallbackTargetInPlace && callbackActionEvent ? await findChatMessageById({
36710
- client,
36711
- chatId,
36712
- messageId: callbackActionEvent.targetMessageId,
36713
- limit: REPLY_TARGET_LOOKUP_LIMIT,
36714
- meId,
36715
- botMessageIdsByChat
36716
- }).catch(() => null) : null;
36717
- const streamViaEditMessage = account.config.streamViaEditMessage === true && !shouldEditCallbackTargetInPlace;
36718
- const defaultReplyToMsgId = isGroup && msg.replyToMsgId != null ? msg.id : undefined;
36719
- const disableBlockStreaming = streamViaEditMessage ? true : typeof account.config.blockStreaming === "boolean" ? !account.config.blockStreaming : undefined;
36720
- const editStreamState = {
36721
- messageId: shouldEditCallbackTargetInPlace ? callbackActionEvent?.targetMessageId ?? null : null,
36722
- accumulatedText: callbackTargetMessage?.message ?? "",
36723
- lastPartialText: "",
36724
- finalTextAccumulator: "",
36725
- failed: false,
36726
- opChain: Promise.resolve()
36727
- };
36728
- let finalDeliveredForCurrentAssistantMessage = false;
36729
- const resetEditStreamForAssistantMessage = async () => {
36702
+ editStreamState.accumulatedText = nextText;
36703
+ statusSink?.({ lastOutboundAt: Date.now() });
36704
+ } catch (error48) {
36705
+ editStreamState.failed = true;
36706
+ runtime2.error?.(`inline edit stream failed: ${String(error48)}`);
36707
+ }
36708
+ });
36709
+ await editStreamState.opChain;
36710
+ };
36711
+ const replyOptions = {
36712
+ ...onModelSelected ? { onModelSelected } : {},
36713
+ blockReplyTimeoutMs: 25000,
36714
+ ...streamViaEditMessage ? {
36715
+ onAssistantMessageStart: async () => {
36716
+ await resetEditStreamOnBoundary();
36717
+ }
36718
+ } : {},
36719
+ ...streamViaEditMessage ? {
36720
+ onPartialReply: async (payload) => {
36721
+ await handlePartialStreamPayload(payload);
36722
+ }
36723
+ } : {},
36724
+ ...streamViaEditMessage ? {
36725
+ onReasoningStream: async (payload) => {
36726
+ await handlePartialStreamPayload(payload);
36727
+ }
36728
+ } : {},
36729
+ ...streamViaEditMessage ? {
36730
+ onReasoningEnd: async () => {
36730
36731
  await editStreamState.opChain;
36731
- const hasActiveState = editStreamState.messageId != null || editStreamState.accumulatedText.length > 0 || editStreamState.lastPartialText.length > 0 || editStreamState.finalTextAccumulator.length > 0;
36732
- if (!hasActiveState)
36733
- return;
36734
- editStreamState.messageId = null;
36735
- editStreamState.accumulatedText = "";
36736
- editStreamState.lastPartialText = "";
36737
- editStreamState.finalTextAccumulator = "";
36738
- editStreamState.failed = false;
36739
- finalDeliveredForCurrentAssistantMessage = false;
36740
- };
36741
- const resetEditStreamOnBoundary = async () => {
36742
- if (!streamViaEditMessage)
36743
- return;
36744
- await resetEditStreamForAssistantMessage();
36745
- };
36746
- const handlePartialStreamPayload = async (payload) => {
36747
- if (editStreamState.failed)
36748
- return;
36749
- if ((payload.mediaUrls?.length ?? 0) > 0)
36750
- return;
36751
- const partialText = typeof payload.text === "string" ? payload.text : "";
36752
- if (!partialText || partialText === editStreamState.lastPartialText)
36753
- return;
36754
- editStreamState.lastPartialText = partialText;
36755
- const nextText = rewriteNumericMentionsToUsernames(extractCompleteParagraphText(partialText), senderProfilesById).trim();
36756
- if (!nextText || nextText === editStreamState.accumulatedText)
36757
- return;
36758
- editStreamState.opChain = editStreamState.opChain.then(async () => {
36759
- if (editStreamState.failed)
36760
- return;
36761
- if (!nextText || nextText === editStreamState.accumulatedText)
36762
- return;
36763
- try {
36764
- if (editStreamState.messageId == null) {
36732
+ }
36733
+ } : {},
36734
+ ...streamViaEditMessage ? {
36735
+ onToolStart: async () => {
36736
+ await resetEditStreamOnBoundary();
36737
+ }
36738
+ } : {},
36739
+ ...streamViaEditMessage ? {
36740
+ onCompactionStart: async () => {
36741
+ await resetEditStreamOnBoundary();
36742
+ }
36743
+ } : {},
36744
+ ...streamViaEditMessage ? {
36745
+ onCompactionEnd: async () => {
36746
+ await resetEditStreamOnBoundary();
36747
+ }
36748
+ } : {},
36749
+ ...typeof disableBlockStreaming === "boolean" ? { disableBlockStreaming } : {}
36750
+ };
36751
+ try {
36752
+ let delivered = false;
36753
+ let skippedNonSilent = false;
36754
+ let failedNonSilent = false;
36755
+ let dispatchError = null;
36756
+ try {
36757
+ await core3.channel.reply.dispatchReplyWithBufferedBlockDispatcher({
36758
+ ctx: ctxPayload,
36759
+ cfg,
36760
+ dispatcherOptions: {
36761
+ ...prefixOptions,
36762
+ ...typingCallbacks ? { typingCallbacks } : {},
36763
+ deliver: async (payload, info) => {
36764
+ const rawText = payload.text ?? "";
36765
+ const mediaList = payload.mediaUrls?.length ? payload.mediaUrls : payload.mediaUrl ? [payload.mediaUrl] : [];
36766
+ const outboundText = rewriteNumericMentionsToUsernames(rawText, senderProfilesById);
36767
+ const outboundActions = resolveInlineReplyActions(payload);
36768
+ const infoKind = typeof info?.kind === "string" ? info.kind : undefined;
36769
+ let replyToMsgId;
36770
+ if (payload.replyToId != null) {
36771
+ try {
36772
+ replyToMsgId = BigInt(payload.replyToId);
36773
+ } catch {}
36774
+ }
36775
+ if (replyToMsgId == null && isGroup && msg.replyToMsgId != null) {
36776
+ replyToMsgId = msg.id;
36777
+ }
36778
+ const rememberSent = (messageId) => {
36779
+ if (messageId != null) {
36780
+ rememberBotMessageId(botMessageIdsByChat, chatId, messageId);
36781
+ }
36782
+ };
36783
+ const sendTextFallback = async (text, includeReplyTo, includeActions) => {
36784
+ if (!text.trim())
36785
+ return;
36765
36786
  const sent = await client.sendMessage({
36766
36787
  chatId,
36767
- text: nextText,
36768
- ...defaultReplyToMsgId != null ? { replyToMsgId: defaultReplyToMsgId } : {},
36788
+ text,
36789
+ ...includeReplyTo && replyToMsgId != null ? { replyToMsgId } : {},
36790
+ ...includeActions && outboundActions !== undefined ? { actions: outboundActions } : {},
36769
36791
  parseMarkdown
36770
36792
  });
36771
- if (sent.messageId == null) {
36772
- throw new Error("inline edit stream: sendMessage returned no messageId");
36773
- }
36774
- editStreamState.messageId = sent.messageId;
36775
- rememberBotMessageId(botMessageIdsByChat, chatId, sent.messageId);
36776
- } else {
36793
+ rememberSent(sent.messageId);
36794
+ delivered = true;
36795
+ };
36796
+ const updateStreamedMessage = async (text, actions) => {
36797
+ await editStreamState.opChain;
36798
+ if (editStreamState.messageId == null)
36799
+ return false;
36800
+ const nextText = text.trim();
36801
+ const textForEdit = nextText || editStreamState.accumulatedText;
36802
+ if (!textForEdit && actions === undefined)
36803
+ return true;
36804
+ const shouldSkipTextUpdate = !editStreamState.failed && textForEdit === editStreamState.accumulatedText;
36805
+ if (shouldSkipTextUpdate && actions === undefined)
36806
+ return true;
36777
36807
  const result = await client.invokeRaw(Method.EDIT_MESSAGE, {
36778
36808
  oneofKind: "editMessage",
36779
36809
  editMessage: {
36780
36810
  messageId: editStreamState.messageId,
36781
36811
  peerId: buildChatPeer2(chatId),
36782
- text: nextText,
36783
- parseMarkdown
36812
+ text: textForEdit,
36813
+ parseMarkdown,
36814
+ ...actions !== undefined ? { actions } : {}
36784
36815
  }
36785
36816
  });
36786
36817
  if (result.oneofKind !== "editMessage") {
36787
36818
  throw new Error(`inline edit stream: expected editMessage result, got ${String(result.oneofKind)}`);
36788
36819
  }
36789
- }
36790
- editStreamState.accumulatedText = nextText;
36791
- statusSink?.({ lastOutboundAt: Date.now() });
36792
- } catch (error48) {
36793
- editStreamState.failed = true;
36794
- runtime2.error?.(`inline edit stream failed: ${String(error48)}`);
36795
- }
36796
- });
36797
- await editStreamState.opChain;
36798
- };
36799
- const replyOptions = {
36800
- ...onModelSelected ? { onModelSelected } : {},
36801
- blockReplyTimeoutMs: 25000,
36802
- ...streamViaEditMessage ? {
36803
- onAssistantMessageStart: async () => {
36804
- await resetEditStreamOnBoundary();
36805
- }
36806
- } : {},
36807
- ...streamViaEditMessage ? {
36808
- onPartialReply: async (payload) => {
36809
- await handlePartialStreamPayload(payload);
36810
- }
36811
- } : {},
36812
- ...streamViaEditMessage ? {
36813
- onReasoningStream: async (payload) => {
36814
- await handlePartialStreamPayload(payload);
36815
- }
36816
- } : {},
36817
- ...streamViaEditMessage ? {
36818
- onReasoningEnd: async () => {
36819
- await editStreamState.opChain;
36820
- }
36821
- } : {},
36822
- ...streamViaEditMessage ? {
36823
- onToolStart: async () => {
36824
- await resetEditStreamOnBoundary();
36825
- }
36826
- } : {},
36827
- ...streamViaEditMessage ? {
36828
- onCompactionStart: async () => {
36829
- await resetEditStreamOnBoundary();
36830
- }
36831
- } : {},
36832
- ...streamViaEditMessage ? {
36833
- onCompactionEnd: async () => {
36834
- await resetEditStreamOnBoundary();
36835
- }
36836
- } : {},
36837
- ...typeof disableBlockStreaming === "boolean" ? { disableBlockStreaming } : {}
36838
- };
36839
- try {
36840
- let delivered = false;
36841
- let skippedNonSilent = false;
36842
- let failedNonSilent = false;
36843
- let dispatchError = null;
36844
- try {
36845
- await core3.channel.reply.dispatchReplyWithBufferedBlockDispatcher({
36846
- ctx: ctxPayload,
36847
- cfg,
36848
- dispatcherOptions: {
36849
- ...prefixOptions,
36850
- ...typingCallbacks ? { typingCallbacks } : {},
36851
- deliver: async (payload, info) => {
36852
- const rawText = payload.text ?? "";
36853
- const mediaList = payload.mediaUrls?.length ? payload.mediaUrls : payload.mediaUrl ? [payload.mediaUrl] : [];
36854
- const outboundText = rewriteNumericMentionsToUsernames(rawText, senderProfilesById);
36855
- const outboundActions = resolveInlineReplyActions(payload);
36856
- const infoKind = typeof info?.kind === "string" ? info.kind : undefined;
36857
- let replyToMsgId;
36858
- if (payload.replyToId != null) {
36859
- try {
36860
- replyToMsgId = BigInt(payload.replyToId);
36861
- } catch {}
36820
+ if (!shouldSkipTextUpdate) {
36821
+ editStreamState.accumulatedText = textForEdit;
36822
+ editStreamState.lastPartialText = textForEdit;
36823
+ }
36824
+ editStreamState.failed = false;
36825
+ return true;
36826
+ };
36827
+ if (mediaList.length === 0) {
36828
+ if (shouldEditCallbackTargetInPlace && editStreamState.messageId != null) {
36829
+ const callbackEditActions = outboundActions ?? { rows: [] };
36830
+ if (!outboundText.trim() && outboundActions === undefined) {
36831
+ return;
36862
36832
  }
36863
- if (replyToMsgId == null && isGroup && msg.replyToMsgId != null) {
36864
- replyToMsgId = msg.id;
36833
+ await updateStreamedMessage(outboundText, callbackEditActions);
36834
+ delivered = true;
36835
+ statusSink?.({ lastOutboundAt: Date.now() });
36836
+ return;
36837
+ }
36838
+ if (streamViaEditMessage && infoKind === "final" && finalDeliveredForCurrentAssistantMessage && editStreamState.messageId != null) {
36839
+ await resetEditStreamForAssistantMessage();
36840
+ }
36841
+ if (streamViaEditMessage && editStreamState.messageId != null) {
36842
+ if (outboundText.trim()) {
36843
+ editStreamState.finalTextAccumulator += outboundText;
36865
36844
  }
36866
- const rememberSent = (messageId) => {
36867
- if (messageId != null) {
36868
- rememberBotMessageId(botMessageIdsByChat, chatId, messageId);
36869
- }
36870
- };
36871
- const sendTextFallback = async (text, includeReplyTo, includeActions) => {
36872
- if (!text.trim())
36873
- return;
36874
- const sent = await client.sendMessage({
36875
- chatId,
36876
- text,
36877
- ...includeReplyTo && replyToMsgId != null ? { replyToMsgId } : {},
36878
- ...includeActions && outboundActions !== undefined ? { actions: outboundActions } : {},
36879
- parseMarkdown
36880
- });
36881
- rememberSent(sent.messageId);
36882
- delivered = true;
36883
- };
36884
- const updateStreamedMessage = async (text, actions) => {
36885
- await editStreamState.opChain;
36886
- if (editStreamState.messageId == null)
36887
- return false;
36888
- const nextText = text.trim();
36889
- const textForEdit = nextText || editStreamState.accumulatedText;
36890
- if (!textForEdit && actions === undefined)
36891
- return true;
36892
- const shouldSkipTextUpdate = !editStreamState.failed && textForEdit === editStreamState.accumulatedText;
36893
- if (shouldSkipTextUpdate && actions === undefined)
36894
- return true;
36895
- const result = await client.invokeRaw(Method.EDIT_MESSAGE, {
36896
- oneofKind: "editMessage",
36897
- editMessage: {
36898
- messageId: editStreamState.messageId,
36899
- peerId: buildChatPeer2(chatId),
36900
- text: textForEdit,
36901
- parseMarkdown,
36902
- ...actions !== undefined ? { actions } : {}
36903
- }
36904
- });
36905
- if (result.oneofKind !== "editMessage") {
36906
- throw new Error(`inline edit stream: expected editMessage result, got ${String(result.oneofKind)}`);
36907
- }
36908
- if (!shouldSkipTextUpdate) {
36909
- editStreamState.accumulatedText = textForEdit;
36910
- editStreamState.lastPartialText = textForEdit;
36911
- }
36912
- editStreamState.failed = false;
36913
- return true;
36914
- };
36915
- if (mediaList.length === 0) {
36916
- if (shouldEditCallbackTargetInPlace && editStreamState.messageId != null) {
36917
- const callbackEditActions = outboundActions ?? { rows: [] };
36918
- if (!outboundText.trim() && outboundActions === undefined) {
36919
- return;
36920
- }
36921
- await updateStreamedMessage(outboundText, callbackEditActions);
36922
- delivered = true;
36923
- statusSink?.({ lastOutboundAt: Date.now() });
36924
- return;
36925
- }
36926
- if (streamViaEditMessage && infoKind === "final" && finalDeliveredForCurrentAssistantMessage && editStreamState.messageId != null) {
36927
- await resetEditStreamForAssistantMessage();
36928
- }
36929
- if (streamViaEditMessage && editStreamState.messageId != null) {
36930
- if (outboundText.trim()) {
36931
- editStreamState.finalTextAccumulator += outboundText;
36932
- }
36933
- if (!editStreamState.finalTextAccumulator.trim() && outboundActions === undefined) {
36934
- return;
36935
- }
36936
- await updateStreamedMessage(editStreamState.finalTextAccumulator, outboundActions);
36937
- delivered = true;
36938
- if (infoKind === "final") {
36939
- finalDeliveredForCurrentAssistantMessage = true;
36940
- }
36941
- statusSink?.({ lastOutboundAt: Date.now() });
36942
- return;
36943
- }
36944
- if (!outboundText.trim())
36945
- return;
36946
- await sendTextFallback(outboundText, true, true);
36947
- statusSink?.({ lastOutboundAt: Date.now() });
36845
+ if (!editStreamState.finalTextAccumulator.trim() && outboundActions === undefined) {
36948
36846
  return;
36949
36847
  }
36950
- if (streamViaEditMessage && editStreamState.messageId != null && outboundText.trim()) {
36951
- await updateStreamedMessage(outboundText, outboundActions);
36848
+ await updateStreamedMessage(editStreamState.finalTextAccumulator, outboundActions);
36849
+ delivered = true;
36850
+ if (infoKind === "final") {
36851
+ finalDeliveredForCurrentAssistantMessage = true;
36952
36852
  }
36953
- for (let index = 0;index < mediaList.length; index++) {
36954
- const mediaUrl = mediaList[index];
36955
- if (!mediaUrl?.trim())
36956
- continue;
36957
- const isFirst = index === 0;
36958
- const shouldAttachActionsToMedia = isFirst && (!(streamViaEditMessage && editStreamState.messageId != null) || !outboundText.trim());
36959
- const caption = isFirst && !(streamViaEditMessage && editStreamState.messageId != null) ? outboundText : "";
36960
- try {
36961
- const media = await uploadInlineMediaFromUrl({
36962
- client,
36963
- cfg,
36964
- accountId: account.accountId,
36965
- mediaUrl
36966
- });
36967
- const sent = await client.sendMessage({
36968
- chatId,
36969
- ...caption ? { text: caption } : {},
36970
- media,
36971
- ...isFirst && replyToMsgId != null ? { replyToMsgId } : {},
36972
- ...shouldAttachActionsToMedia && outboundActions !== undefined ? { actions: outboundActions } : {},
36973
- ...caption ? { parseMarkdown } : {}
36974
- });
36975
- rememberSent(sent.messageId);
36976
- delivered = true;
36977
- } catch (error48) {
36978
- runtime2.error?.(`inline media upload failed; falling back to url text (${String(error48)})`);
36979
- const fallbackText = caption ? `${caption}
36853
+ statusSink?.({ lastOutboundAt: Date.now() });
36854
+ return;
36855
+ }
36856
+ if (!outboundText.trim())
36857
+ return;
36858
+ await sendTextFallback(outboundText, true, true);
36859
+ statusSink?.({ lastOutboundAt: Date.now() });
36860
+ return;
36861
+ }
36862
+ if (streamViaEditMessage && editStreamState.messageId != null && outboundText.trim()) {
36863
+ await updateStreamedMessage(outboundText, outboundActions);
36864
+ }
36865
+ for (let index = 0;index < mediaList.length; index++) {
36866
+ const mediaUrl = mediaList[index];
36867
+ if (!mediaUrl?.trim())
36868
+ continue;
36869
+ const isFirst = index === 0;
36870
+ const shouldAttachActionsToMedia = isFirst && (!(streamViaEditMessage && editStreamState.messageId != null) || !outboundText.trim());
36871
+ const caption = isFirst && !(streamViaEditMessage && editStreamState.messageId != null) ? outboundText : "";
36872
+ try {
36873
+ const media = await uploadInlineMediaFromUrl({
36874
+ client,
36875
+ cfg,
36876
+ accountId: account.accountId,
36877
+ mediaUrl
36878
+ });
36879
+ const sent = await client.sendMessage({
36880
+ chatId,
36881
+ ...caption ? { text: caption } : {},
36882
+ media,
36883
+ ...isFirst && replyToMsgId != null ? { replyToMsgId } : {},
36884
+ ...shouldAttachActionsToMedia && outboundActions !== undefined ? { actions: outboundActions } : {},
36885
+ ...caption ? { parseMarkdown } : {}
36886
+ });
36887
+ rememberSent(sent.messageId);
36888
+ delivered = true;
36889
+ } catch (error48) {
36890
+ runtime2.error?.(`inline media upload failed; falling back to url text (${String(error48)})`);
36891
+ const fallbackText = caption ? `${caption}
36980
36892
 
36981
36893
  Attachment: ${mediaUrl}` : `Attachment: ${mediaUrl}`;
36982
- await sendTextFallback(fallbackText, isFirst, isFirst);
36983
- }
36984
- }
36985
- statusSink?.({ lastOutboundAt: Date.now() });
36986
- },
36987
- onSkip: (_payload, info) => {
36988
- if (info?.reason !== "silent") {
36989
- skippedNonSilent = true;
36990
- }
36991
- },
36992
- onError: (err, info) => {
36993
- failedNonSilent = true;
36994
- runtime2.error?.(`inline ${info?.kind ?? "final"} reply failed: ${String(err)}`);
36894
+ await sendTextFallback(fallbackText, isFirst, isFirst);
36995
36895
  }
36996
- },
36997
- replyOptions
36998
- });
36999
- } catch (error48) {
37000
- dispatchError = error48;
37001
- runtime2.error?.(`inline dispatch failed: ${String(error48)}`);
37002
- }
37003
- if (!delivered && streamViaEditMessage && editStreamState.messageId != null) {
37004
- delivered = true;
37005
- }
37006
- if (!delivered && (dispatchError != null || skippedNonSilent || failedNonSilent)) {
37007
- const fallbackText = dispatchError != null ? "Something went wrong while processing your request. Please try again." : EMPTY_RESPONSE_FALLBACK;
37008
- const sent = await client.sendMessage({
37009
- chatId,
37010
- text: fallbackText,
37011
- ...defaultReplyToMsgId != null ? { replyToMsgId: defaultReplyToMsgId } : {},
37012
- parseMarkdown
37013
- });
37014
- if (sent.messageId != null) {
37015
- rememberBotMessageId(botMessageIdsByChat, chatId, sent.messageId);
36896
+ }
36897
+ statusSink?.({ lastOutboundAt: Date.now() });
36898
+ },
36899
+ onSkip: (_payload, info) => {
36900
+ if (info?.reason !== "silent") {
36901
+ skippedNonSilent = true;
36902
+ }
36903
+ },
36904
+ onError: (err, info) => {
36905
+ failedNonSilent = true;
36906
+ runtime2.error?.(`inline ${info?.kind ?? "final"} reply failed: ${String(err)}`);
37016
36907
  }
37017
- statusSink?.({ lastOutboundAt: Date.now() });
37018
- }
37019
- } finally {
37020
- if (callbackActionEvent && !callbackActionAnswered) {
37021
- try {
37022
- await answerCallbackIfNeeded();
37023
- } catch (error48) {
37024
- runtime2.error?.(`inline callback answer failed: ${String(error48)}`);
36908
+ },
36909
+ replyOptions
36910
+ });
36911
+ } catch (error48) {
36912
+ dispatchError = error48;
36913
+ runtime2.error?.(`inline dispatch failed: ${String(error48)}`);
36914
+ }
36915
+ if (!delivered && streamViaEditMessage && editStreamState.messageId != null) {
36916
+ delivered = true;
36917
+ }
36918
+ if (!delivered && (dispatchError != null || skippedNonSilent || failedNonSilent)) {
36919
+ const fallbackText = dispatchError != null ? "Something went wrong while processing your request. Please try again." : EMPTY_RESPONSE_FALLBACK;
36920
+ const sent = await client.sendMessage({
36921
+ chatId,
36922
+ text: fallbackText,
36923
+ ...defaultReplyToMsgId != null ? { replyToMsgId: defaultReplyToMsgId } : {},
36924
+ parseMarkdown
36925
+ });
36926
+ if (sent.messageId != null) {
36927
+ rememberBotMessageId(botMessageIdsByChat, chatId, sent.messageId);
36928
+ }
36929
+ statusSink?.({ lastOutboundAt: Date.now() });
36930
+ }
36931
+ } finally {
36932
+ if (callbackActionEvent && !callbackActionAnswered) {
36933
+ try {
36934
+ await answerCallbackIfNeeded();
36935
+ } catch (error48) {
36936
+ runtime2.error?.(`inline callback answer failed: ${String(error48)}`);
36937
+ }
36938
+ }
36939
+ }
36940
+ if (isGroup && groupHistoryKey) {
36941
+ clearHistoryEntriesIfEnabled({
36942
+ historyMap: groupPendingHistories,
36943
+ historyKey: groupHistoryKey,
36944
+ limit: historyLimit
36945
+ });
36946
+ }
36947
+ };
36948
+ const { debouncer: inboundDebouncer } = createChannelInboundDebouncer({
36949
+ cfg,
36950
+ channel: CHANNEL_ID,
36951
+ buildKey: (entry) => buildInlineDebounceKey({
36952
+ accountId: account.accountId,
36953
+ chatId: entry.chatId,
36954
+ senderId: entry.msg.fromId
36955
+ }),
36956
+ shouldDebounce: (entry) => {
36957
+ const content = summarizeInlineMessageContent(entry.msg);
36958
+ return shouldDebounceTextInbound({
36959
+ text: buildInlineInboundBodyText(content),
36960
+ cfg,
36961
+ hasMedia: Boolean(content.media || content.attachments.length > 0),
36962
+ ...botUsername ? { commandOptions: { botUsername } } : {}
36963
+ });
36964
+ },
36965
+ onFlush: async (entries) => {
36966
+ const last = entries.at(-1);
36967
+ if (!last)
36968
+ return;
36969
+ if (entries.length === 1) {
36970
+ await handleInboundNow({
36971
+ chatId: last.chatId,
36972
+ msg: last.msg
36973
+ });
36974
+ return;
36975
+ }
36976
+ const combinedText = entries.map((entry) => buildInlineInboundBodyText(summarizeInlineMessageContent(entry.msg))).filter(Boolean).join(`
36977
+ `);
36978
+ if (!combinedText.trim()) {
36979
+ return;
36980
+ }
36981
+ await handleInboundNow({
36982
+ chatId: last.chatId,
36983
+ msg: buildSyntheticInlineTextMessage({
36984
+ base: last.msg,
36985
+ text: combinedText,
36986
+ mentioned: entries.some((entry) => entry.msg.mentioned === true)
36987
+ }),
36988
+ rawBodyOverride: combinedText
36989
+ });
36990
+ },
36991
+ onError: (err, items) => {
36992
+ runtime2.error?.(`inline debounce flush failed: ${String(err)}`);
36993
+ const chatId = items[0]?.chatId;
36994
+ if (chatId == null)
36995
+ return;
36996
+ client.sendMessage({
36997
+ chatId,
36998
+ text: "Something went wrong while processing your message. Please try again."
36999
+ }).then(() => {
37000
+ statusSink?.({ lastOutboundAt: Date.now() });
37001
+ }).catch((sendErr) => {
37002
+ runtime2.error?.(`inline debounce fallback send failed: ${String(sendErr)}`);
37003
+ });
37004
+ }
37005
+ });
37006
+ const loop = (async () => {
37007
+ try {
37008
+ for await (const event of client.events()) {
37009
+ if (abortSignal.aborted)
37010
+ break;
37011
+ const rawEvent = event;
37012
+ if (event.kind === "message.new") {
37013
+ const msg = {
37014
+ ...event.message,
37015
+ chatId: event.chatId
37016
+ };
37017
+ if (msg.out || msg.fromId === meId)
37018
+ continue;
37019
+ await inboundDebouncer.enqueue({
37020
+ chatId: event.chatId,
37021
+ msg
37022
+ });
37023
+ continue;
37024
+ }
37025
+ if (event.kind === "reaction.add") {
37026
+ if (event.reaction.userId === meId)
37027
+ continue;
37028
+ const onBotMessage = await isReactionTargetBotMessage({
37029
+ client,
37030
+ chatId: event.chatId,
37031
+ messageId: event.reaction.messageId,
37032
+ meId,
37033
+ botMessageIdsByChat
37034
+ }).catch((err) => {
37035
+ statusSink?.({ lastError: `getChatHistory (reaction target) failed: ${String(err)}` });
37036
+ return false;
37037
+ });
37038
+ if (!onBotMessage)
37039
+ continue;
37040
+ await handleInboundNow({
37041
+ chatId: event.chatId,
37042
+ msg: {
37043
+ id: event.reaction.messageId,
37044
+ chatId: event.chatId,
37045
+ date: event.date,
37046
+ fromId: event.reaction.userId,
37047
+ message: "",
37048
+ out: false,
37049
+ mentioned: false,
37050
+ replyToMsgId: event.reaction.messageId
37051
+ },
37052
+ reactionEvent: {
37053
+ action: "added",
37054
+ emoji: event.reaction.emoji,
37055
+ targetMessageId: event.reaction.messageId
37025
37056
  }
37026
- }
37057
+ });
37058
+ continue;
37059
+ }
37060
+ if (event.kind === "reaction.delete") {
37061
+ if (event.userId === meId)
37062
+ continue;
37063
+ const onBotMessage = await isReactionTargetBotMessage({
37064
+ client,
37065
+ chatId: event.chatId,
37066
+ messageId: event.messageId,
37067
+ meId,
37068
+ botMessageIdsByChat
37069
+ }).catch((err) => {
37070
+ statusSink?.({ lastError: `getChatHistory (reaction target) failed: ${String(err)}` });
37071
+ return false;
37072
+ });
37073
+ if (!onBotMessage)
37074
+ continue;
37075
+ await handleInboundNow({
37076
+ chatId: event.chatId,
37077
+ msg: {
37078
+ id: event.messageId,
37079
+ chatId: event.chatId,
37080
+ date: event.date,
37081
+ fromId: event.userId,
37082
+ message: "",
37083
+ out: false,
37084
+ mentioned: false,
37085
+ replyToMsgId: event.messageId
37086
+ },
37087
+ reactionEvent: {
37088
+ action: "removed",
37089
+ emoji: event.emoji,
37090
+ targetMessageId: event.messageId
37091
+ }
37092
+ });
37093
+ continue;
37027
37094
  }
37028
- if (isGroup && groupHistoryKey) {
37029
- clearHistoryEntriesIfEnabled({
37030
- historyMap: groupPendingHistories,
37031
- historyKey: groupHistoryKey,
37032
- limit: historyLimit
37095
+ if (rawEvent["kind"] === "message.action.invoke") {
37096
+ const actorUserId = rawEvent["actorUserId"];
37097
+ const interactionId = rawEvent["interactionId"];
37098
+ const actionId = rawEvent["actionId"];
37099
+ const targetMessageId = rawEvent["messageId"];
37100
+ const data = rawEvent["data"];
37101
+ const eventChatId = rawEvent["chatId"];
37102
+ const eventDate = rawEvent["date"];
37103
+ if (!actorUserId || !interactionId || !actionId || !targetMessageId || !eventChatId || !eventDate || !data) {
37104
+ continue;
37105
+ }
37106
+ if (actorUserId === meId)
37107
+ continue;
37108
+ await handleInboundNow({
37109
+ chatId: eventChatId,
37110
+ msg: {
37111
+ id: targetMessageId,
37112
+ chatId: eventChatId,
37113
+ date: eventDate,
37114
+ fromId: actorUserId,
37115
+ message: "",
37116
+ out: false,
37117
+ mentioned: false,
37118
+ replyToMsgId: targetMessageId
37119
+ },
37120
+ callbackActionEvent: {
37121
+ interactionId,
37122
+ actionId,
37123
+ targetMessageId,
37124
+ data
37125
+ }
37033
37126
  });
37127
+ continue;
37034
37128
  }
37035
37129
  }
37036
37130
  } catch (err) {
@@ -41217,5 +41311,5 @@ export {
41217
41311
  src_default as default
41218
41312
  };
41219
41313
 
41220
- //# debugId=3B7100874DF4D61664756E2164756E21
41314
+ //# debugId=1C8239561365068664756E2164756E21
41221
41315
  //# sourceMappingURL=index.js.map