@inline-openclaw/inline 0.0.43 → 0.0.45

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.
@@ -6984,7 +6984,8 @@ class Chat$Type extends import_runtime4.MessageType {
6984
6984
  { no: 9, name: "date", kind: "scalar", opt: true, T: 3, L: 0 },
6985
6985
  { no: 10, name: "created_by", kind: "scalar", opt: true, T: 3, L: 0 },
6986
6986
  { no: 11, name: "parent_chat_id", kind: "scalar", opt: true, T: 3, L: 0 },
6987
- { no: 12, name: "parent_message_id", kind: "scalar", opt: true, T: 3, L: 0 }
6987
+ { no: 12, name: "parent_message_id", kind: "scalar", opt: true, T: 3, L: 0 },
6988
+ { no: 13, name: "untitled", kind: "scalar", opt: true, T: 8 }
6988
6989
  ]);
6989
6990
  }
6990
6991
  create(value) {
@@ -7036,6 +7037,9 @@ class Chat$Type extends import_runtime4.MessageType {
7036
7037
  case 12:
7037
7038
  message.parentMessageId = reader.int64().toBigInt();
7038
7039
  break;
7040
+ case 13:
7041
+ message.untitled = reader.bool();
7042
+ break;
7039
7043
  default:
7040
7044
  let u = options.readUnknownField;
7041
7045
  if (u === "throw")
@@ -7072,6 +7076,8 @@ class Chat$Type extends import_runtime4.MessageType {
7072
7076
  writer.tag(11, import_runtime.WireType.Varint).int64(message.parentChatId);
7073
7077
  if (message.parentMessageId !== undefined)
7074
7078
  writer.tag(12, import_runtime.WireType.Varint).int64(message.parentMessageId);
7079
+ if (message.untitled !== undefined)
7080
+ writer.tag(13, import_runtime.WireType.Varint).bool(message.untitled);
7075
7081
  let u = options.writeUnknownFields;
7076
7082
  if (u !== false)
7077
7083
  (u == true ? import_runtime2.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
@@ -11181,6 +11187,70 @@ class GetUpdatesInput$Type extends import_runtime4.MessageType {
11181
11187
  }
11182
11188
  var GetUpdatesInput = new GetUpdatesInput$Type;
11183
11189
 
11190
+ class UpdateSidecars$Type extends import_runtime4.MessageType {
11191
+ constructor() {
11192
+ super("UpdateSidecars", [
11193
+ { no: 1, name: "users", kind: "message", repeat: 1, T: () => User },
11194
+ { no: 2, name: "chats", kind: "message", repeat: 1, T: () => Chat },
11195
+ { no: 3, name: "dialogs", kind: "message", repeat: 1, T: () => Dialog },
11196
+ { no: 4, name: "spaces", kind: "message", repeat: 1, T: () => Space }
11197
+ ]);
11198
+ }
11199
+ create(value) {
11200
+ const message = globalThis.Object.create(this.messagePrototype);
11201
+ message.users = [];
11202
+ message.chats = [];
11203
+ message.dialogs = [];
11204
+ message.spaces = [];
11205
+ if (value !== undefined)
11206
+ import_runtime3.reflectionMergePartial(this, message, value);
11207
+ return message;
11208
+ }
11209
+ internalBinaryRead(reader, length, options, target) {
11210
+ let message = target ?? this.create(), end = reader.pos + length;
11211
+ while (reader.pos < end) {
11212
+ let [fieldNo, wireType] = reader.tag();
11213
+ switch (fieldNo) {
11214
+ case 1:
11215
+ message.users.push(User.internalBinaryRead(reader, reader.uint32(), options));
11216
+ break;
11217
+ case 2:
11218
+ message.chats.push(Chat.internalBinaryRead(reader, reader.uint32(), options));
11219
+ break;
11220
+ case 3:
11221
+ message.dialogs.push(Dialog.internalBinaryRead(reader, reader.uint32(), options));
11222
+ break;
11223
+ case 4:
11224
+ message.spaces.push(Space.internalBinaryRead(reader, reader.uint32(), options));
11225
+ break;
11226
+ default:
11227
+ let u = options.readUnknownField;
11228
+ if (u === "throw")
11229
+ throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
11230
+ let d = reader.skip(wireType);
11231
+ if (u !== false)
11232
+ (u === true ? import_runtime2.UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
11233
+ }
11234
+ }
11235
+ return message;
11236
+ }
11237
+ internalBinaryWrite(message, writer, options) {
11238
+ for (let i = 0;i < message.users.length; i++)
11239
+ User.internalBinaryWrite(message.users[i], writer.tag(1, import_runtime.WireType.LengthDelimited).fork(), options).join();
11240
+ for (let i = 0;i < message.chats.length; i++)
11241
+ Chat.internalBinaryWrite(message.chats[i], writer.tag(2, import_runtime.WireType.LengthDelimited).fork(), options).join();
11242
+ for (let i = 0;i < message.dialogs.length; i++)
11243
+ Dialog.internalBinaryWrite(message.dialogs[i], writer.tag(3, import_runtime.WireType.LengthDelimited).fork(), options).join();
11244
+ for (let i = 0;i < message.spaces.length; i++)
11245
+ Space.internalBinaryWrite(message.spaces[i], writer.tag(4, import_runtime.WireType.LengthDelimited).fork(), options).join();
11246
+ let u = options.writeUnknownFields;
11247
+ if (u !== false)
11248
+ (u == true ? import_runtime2.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
11249
+ return writer;
11250
+ }
11251
+ }
11252
+ var UpdateSidecars = new UpdateSidecars$Type;
11253
+
11184
11254
  class GetUpdatesResult$Type extends import_runtime4.MessageType {
11185
11255
  constructor() {
11186
11256
  super("GetUpdatesResult", [
@@ -11188,7 +11258,8 @@ class GetUpdatesResult$Type extends import_runtime4.MessageType {
11188
11258
  { no: 2, name: "seq", kind: "scalar", T: 3, L: 0 },
11189
11259
  { no: 3, name: "date", kind: "scalar", T: 3, L: 0 },
11190
11260
  { no: 4, name: "final", kind: "scalar", opt: true, T: 8 },
11191
- { no: 5, name: "result_type", kind: "enum", T: () => ["GetUpdatesResult.ResultType", GetUpdatesResult_ResultType, "RESULT_TYPE_"] }
11261
+ { no: 5, name: "result_type", kind: "enum", T: () => ["GetUpdatesResult.ResultType", GetUpdatesResult_ResultType, "RESULT_TYPE_"] },
11262
+ { no: 6, name: "sidecars", kind: "message", T: () => UpdateSidecars }
11192
11263
  ]);
11193
11264
  }
11194
11265
  create(value) {
@@ -11221,6 +11292,9 @@ class GetUpdatesResult$Type extends import_runtime4.MessageType {
11221
11292
  case 5:
11222
11293
  message.resultType = reader.int32();
11223
11294
  break;
11295
+ case 6:
11296
+ message.sidecars = UpdateSidecars.internalBinaryRead(reader, reader.uint32(), options, message.sidecars);
11297
+ break;
11224
11298
  default:
11225
11299
  let u = options.readUnknownField;
11226
11300
  if (u === "throw")
@@ -11243,6 +11317,8 @@ class GetUpdatesResult$Type extends import_runtime4.MessageType {
11243
11317
  writer.tag(4, import_runtime.WireType.Varint).bool(message.final);
11244
11318
  if (message.resultType !== 0)
11245
11319
  writer.tag(5, import_runtime.WireType.Varint).int32(message.resultType);
11320
+ if (message.sidecars)
11321
+ UpdateSidecars.internalBinaryWrite(message.sidecars, writer.tag(6, import_runtime.WireType.LengthDelimited).fork(), options).join();
11246
11322
  let u = options.writeUnknownFields;
11247
11323
  if (u !== false)
11248
11324
  (u == true ? import_runtime2.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
@@ -15969,7 +16045,7 @@ var ReserveChatIdsResult = new ReserveChatIdsResult$Type;
15969
16045
  class CreateChatInput$Type extends import_runtime4.MessageType {
15970
16046
  constructor() {
15971
16047
  super("CreateChatInput", [
15972
- { no: 1, name: "title", kind: "scalar", T: 9 },
16048
+ { no: 1, name: "title", kind: "scalar", opt: true, T: 9 },
15973
16049
  { no: 2, name: "space_id", kind: "scalar", opt: true, T: 3, L: 0 },
15974
16050
  { no: 3, name: "description", kind: "scalar", opt: true, T: 9 },
15975
16051
  { no: 4, name: "emoji", kind: "scalar", opt: true, T: 9 },
@@ -15980,7 +16056,6 @@ class CreateChatInput$Type extends import_runtime4.MessageType {
15980
16056
  }
15981
16057
  create(value) {
15982
16058
  const message = globalThis.Object.create(this.messagePrototype);
15983
- message.title = "";
15984
16059
  message.isPublic = false;
15985
16060
  message.participants = [];
15986
16061
  if (value !== undefined)
@@ -16025,7 +16100,7 @@ class CreateChatInput$Type extends import_runtime4.MessageType {
16025
16100
  return message;
16026
16101
  }
16027
16102
  internalBinaryWrite(message, writer, options) {
16028
- if (message.title !== "")
16103
+ if (message.title !== undefined)
16029
16104
  writer.tag(1, import_runtime.WireType.LengthDelimited).string(message.title);
16030
16105
  if (message.spaceId !== undefined)
16031
16106
  writer.tag(2, import_runtime.WireType.Varint).int64(message.spaceId);
@@ -16875,7 +16950,8 @@ class UpdateChatInfo$Type extends import_runtime4.MessageType {
16875
16950
  super("UpdateChatInfo", [
16876
16951
  { no: 1, name: "chat_id", kind: "scalar", T: 3, L: 0 },
16877
16952
  { no: 2, name: "title", kind: "scalar", opt: true, T: 9 },
16878
- { no: 3, name: "emoji", kind: "scalar", opt: true, T: 9 }
16953
+ { no: 3, name: "emoji", kind: "scalar", opt: true, T: 9 },
16954
+ { no: 4, name: "untitled", kind: "scalar", opt: true, T: 8 }
16879
16955
  ]);
16880
16956
  }
16881
16957
  create(value) {
@@ -16899,6 +16975,9 @@ class UpdateChatInfo$Type extends import_runtime4.MessageType {
16899
16975
  case 3:
16900
16976
  message.emoji = reader.string();
16901
16977
  break;
16978
+ case 4:
16979
+ message.untitled = reader.bool();
16980
+ break;
16902
16981
  default:
16903
16982
  let u = options.readUnknownField;
16904
16983
  if (u === "throw")
@@ -16917,6 +16996,8 @@ class UpdateChatInfo$Type extends import_runtime4.MessageType {
16917
16996
  writer.tag(2, import_runtime.WireType.LengthDelimited).string(message.title);
16918
16997
  if (message.emoji !== undefined)
16919
16998
  writer.tag(3, import_runtime.WireType.LengthDelimited).string(message.emoji);
16999
+ if (message.untitled !== undefined)
17000
+ writer.tag(4, import_runtime.WireType.Varint).bool(message.untitled);
16920
17001
  let u = options.writeUnknownFields;
16921
17002
  if (u !== false)
16922
17003
  (u == true ? import_runtime2.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
@@ -20982,7 +21063,7 @@ class InlineSdkClient {
20982
21063
  await this.handleUpdate(update);
20983
21064
  }
20984
21065
  }
20985
- async handleUpdate(update) {
21066
+ async handleUpdate(update, options) {
20986
21067
  const seq = update.seq ?? 0;
20987
21068
  const date = update.date ?? 0n;
20988
21069
  switch (update.update.oneofKind) {
@@ -21114,6 +21195,34 @@ class InlineSdkClient {
21114
21195
  });
21115
21196
  return;
21116
21197
  }
21198
+ case "participantAdd": {
21199
+ const payload = update.update.participantAdd;
21200
+ if (options?.source !== "user" && options?.source !== "space") {
21201
+ this.bumpChatSeq(payload.chatId, seq);
21202
+ }
21203
+ await this.eventStream.send({
21204
+ kind: "chat.participant.add",
21205
+ chatId: payload.chatId,
21206
+ ...payload.participant ? { participant: payload.participant } : {},
21207
+ seq,
21208
+ date
21209
+ });
21210
+ return;
21211
+ }
21212
+ case "participantDelete": {
21213
+ const payload = update.update.participantDelete;
21214
+ if (options?.source !== "user" && options?.source !== "space") {
21215
+ this.bumpChatSeq(payload.chatId, seq);
21216
+ }
21217
+ await this.eventStream.send({
21218
+ kind: "chat.participant.delete",
21219
+ chatId: payload.chatId,
21220
+ userId: payload.userId,
21221
+ seq,
21222
+ date
21223
+ });
21224
+ return;
21225
+ }
21117
21226
  case "messageActionInvoked": {
21118
21227
  const payload = update.update.messageActionInvoked;
21119
21228
  if (this.shouldSkipUserSeq(seq)) {
@@ -21214,14 +21323,14 @@ class InlineSdkClient {
21214
21323
  }
21215
21324
  }
21216
21325
  requestCatchUpUser() {
21217
- const lastUserSeq = this.state.lastUserSeq ?? 0;
21218
- if (lastUserSeq <= 0) {
21326
+ const lastUserSeq = this.state.lastUserSeq;
21327
+ if (lastUserSeq == null && !this.options.catchUpUserFromStart) {
21219
21328
  return;
21220
21329
  }
21221
21330
  if (this.userCatchUpInFlight) {
21222
21331
  return;
21223
21332
  }
21224
- this.userCatchUpInFlight = this.doCatchUpUser(lastUserSeq).catch((error) => {
21333
+ this.userCatchUpInFlight = this.doCatchUpUser(lastUserSeq ?? 0).catch((error) => {
21225
21334
  this.log.warn?.("GET_UPDATES user catch-up failed; continuing live delivery", {
21226
21335
  error: extractErrorMessage(error)
21227
21336
  });
@@ -21262,7 +21371,7 @@ class InlineSdkClient {
21262
21371
  return;
21263
21372
  }
21264
21373
  for (const update of payload.updates) {
21265
- await this.handleUpdate(update);
21374
+ await this.handleUpdate(update, { source: "user" });
21266
21375
  }
21267
21376
  this.bumpUserSeq(deliveredSeq);
21268
21377
  if (payload.date !== 0n) {
@@ -21361,7 +21470,7 @@ class InlineSdkClient {
21361
21470
  }
21362
21471
  this.bumpChatSeq(chatId, deliveredSeq);
21363
21472
  for (const update of payload.updates) {
21364
- await this.handleUpdate(update);
21473
+ await this.handleUpdate(update, { source: "chat" });
21365
21474
  }
21366
21475
  if (payload.date !== 0n) {
21367
21476
  this.state.dateCursor = payload.date;
@@ -21463,7 +21572,7 @@ class InlineSdkClient {
21463
21572
  }
21464
21573
  this.bumpSpaceSeq(spaceId, deliveredSeq);
21465
21574
  for (const update of payload.updates) {
21466
- await this.handleUpdate(update);
21575
+ await this.handleUpdate(update, { source: "space" });
21467
21576
  }
21468
21577
  if (payload.date !== 0n) {
21469
21578
  this.state.dateCursor = payload.date;
@@ -36398,6 +36507,8 @@ var InlineExecApprovalsSchema = exports_external.object({
36398
36507
  var InlineReactionNotificationsSchema = exports_external.enum(["off", "own", "all", "allowlist"]);
36399
36508
  var InlineStreamingModeSchema = exports_external.enum(["off", "partial", "block", "progress"]);
36400
36509
  var InlineStreamingCommandTextSchema = exports_external.enum(["raw", "status"]);
36510
+ var INLINE_DEFAULT_GROUP_POLICY = "open";
36511
+ var INLINE_DEFAULT_REQUIRE_MENTION = true;
36401
36512
  var InlineStreamingChunkSchema = exports_external.object({
36402
36513
  minChars: exports_external.number().int().positive().optional(),
36403
36514
  maxChars: exports_external.number().int().positive().optional(),
@@ -36469,7 +36580,7 @@ var InlineAccountSchemaBase = exports_external.object({
36469
36580
  defaultTo: InlineTargetSchema.optional(),
36470
36581
  systemPrompt: exports_external.string().optional(),
36471
36582
  groupAllowFrom: exports_external.array(InlineAllowEntrySchema).optional(),
36472
- groupPolicy: GroupPolicySchema.optional().default("allowlist"),
36583
+ groupPolicy: GroupPolicySchema.optional().default(INLINE_DEFAULT_GROUP_POLICY),
36473
36584
  groups: exports_external.record(exports_external.string(), InlineGroupSchema.optional()).optional(),
36474
36585
  requireMention: exports_external.boolean().optional(),
36475
36586
  replyThreadMode: InlineReplyThreadModeSchema.optional(),
@@ -36968,7 +37079,7 @@ function looksLikeInlineTargetId(raw, normalizedInput) {
36968
37079
  }
36969
37080
 
36970
37081
  // src/inline/monitor.ts
36971
- import { mkdir } from "node:fs/promises";
37082
+ import { mkdir, stat } from "node:fs/promises";
36972
37083
  import path4 from "node:path";
36973
37084
  import {
36974
37085
  buildCommandTextFromArgs,
@@ -40823,11 +40934,339 @@ function redactInlineBotApiUrl(raw) {
40823
40934
  }
40824
40935
  }
40825
40936
 
40937
+ // src/inline/threadreply-command.ts
40938
+ var MODE_LABELS = {
40939
+ auto: "auto",
40940
+ thread: "thread",
40941
+ main: "main"
40942
+ };
40943
+ var DEFAULT_REPLY_THREAD_AUTO_CREATE_MIN_MESSAGES = 50;
40944
+ var INLINE_THREADREPLY_NATIVE_NAME = "threadreply";
40945
+ var INLINE_THREADREPLY_COMMAND_SPEC = {
40946
+ name: "threadreply",
40947
+ nativeNames: { inline: INLINE_THREADREPLY_NATIVE_NAME },
40948
+ description: "Set Inline reply-thread mode for this chat.",
40949
+ channels: ["inline"],
40950
+ acceptsArgs: true
40951
+ };
40952
+ function listInlineBuiltinCommandSpecs() {
40953
+ return [
40954
+ {
40955
+ name: INLINE_THREADREPLY_COMMAND_SPEC.nativeNames.inline ?? INLINE_THREADREPLY_COMMAND_SPEC.name,
40956
+ description: INLINE_THREADREPLY_COMMAND_SPEC.description,
40957
+ acceptsArgs: INLINE_THREADREPLY_COMMAND_SPEC.acceptsArgs
40958
+ }
40959
+ ];
40960
+ }
40961
+ function isRecord5(value) {
40962
+ return typeof value === "object" && value !== null && !Array.isArray(value);
40963
+ }
40964
+ function asInlineConfig(value) {
40965
+ return isRecord5(value) ? value : undefined;
40966
+ }
40967
+ function normalizeMode(raw) {
40968
+ if (typeof raw !== "string")
40969
+ return null;
40970
+ const normalized = raw.trim().toLowerCase();
40971
+ if (normalized === "on" || normalized === "threads")
40972
+ return "thread";
40973
+ if (normalized === "off" || normalized === "parent" || normalized === "parentchat")
40974
+ return "main";
40975
+ if (normalized === "auto" || normalized === "thread" || normalized === "main")
40976
+ return normalized;
40977
+ return null;
40978
+ }
40979
+ function normalizeMin(raw) {
40980
+ if (typeof raw !== "number")
40981
+ return null;
40982
+ if (!Number.isInteger(raw) || raw < 0)
40983
+ return null;
40984
+ return raw;
40985
+ }
40986
+ function parseMinArg(raw) {
40987
+ const value = raw?.trim().toLowerCase();
40988
+ if (!value)
40989
+ return null;
40990
+ if (value === "inherit" || value === "default" || value === "unset")
40991
+ return "inherit";
40992
+ if (!/^\d+$/.test(value))
40993
+ return null;
40994
+ const parsed = Number(value);
40995
+ return Number.isSafeInteger(parsed) ? parsed : null;
40996
+ }
40997
+ function resolveInlineGroupId(ctx) {
40998
+ const raw = ctx.from?.trim() ?? "";
40999
+ if (!/(^|:)chat:/i.test(raw))
41000
+ return null;
41001
+ const normalized = normalizeInlineTarget(raw);
41002
+ return normalized && /^[0-9]+$/.test(normalized) ? normalized : null;
41003
+ }
41004
+ function resolveInlineConfigForAccount(inline, accountId) {
41005
+ const normalized = normalizeAccountId(accountId);
41006
+ const accounts = isRecord5(inline.accounts) ? inline.accounts : undefined;
41007
+ const accountKey = accounts ? Object.keys(accounts).find((key) => normalizeAccountId(key) === normalized) : undefined;
41008
+ if (accountKey && accounts?.[accountKey]) {
41009
+ return accounts[accountKey];
41010
+ }
41011
+ if (normalized !== DEFAULT_ACCOUNT_ID) {
41012
+ return {};
41013
+ }
41014
+ return inline;
41015
+ }
41016
+ function resolveCurrentMode(params) {
41017
+ const inline = asInlineConfig(params.cfg.channels?.inline) ?? {};
41018
+ const accountConfig = resolveInlineConfigForAccount(inline, params.accountId);
41019
+ return resolveInlineGroupReplyThreadMode({
41020
+ cfg: params.cfg,
41021
+ accountId: params.accountId ?? null,
41022
+ groupId: params.groupId,
41023
+ defaultMode: normalizeMode(accountConfig.replyThreadMode) ?? "auto"
41024
+ });
41025
+ }
41026
+ function resolveCurrentMinMessages(params) {
41027
+ const inline = asInlineConfig(params.cfg.channels?.inline) ?? {};
41028
+ const accountConfig = resolveInlineConfigForAccount(inline, params.accountId);
41029
+ return resolveInlineGroupReplyThreadAutoCreateMinMessages({
41030
+ cfg: params.cfg,
41031
+ accountId: params.accountId ?? null,
41032
+ groupId: params.groupId,
41033
+ defaultMinMessages: normalizeMin(accountConfig.replyThreadAutoCreateMinMessages) ?? DEFAULT_REPLY_THREAD_AUTO_CREATE_MIN_MESSAGES
41034
+ });
41035
+ }
41036
+ function readExplicitMode(params) {
41037
+ const inline = asInlineConfig(params.cfg.channels?.inline);
41038
+ if (!inline)
41039
+ return null;
41040
+ const accountConfig = resolveInlineConfigForAccount(inline, params.accountId);
41041
+ const group = accountConfig.groups?.[params.groupId];
41042
+ return normalizeMode(group?.replyThreadMode);
41043
+ }
41044
+ function readExplicitMinMessages(params) {
41045
+ const inline = asInlineConfig(params.cfg.channels?.inline);
41046
+ if (!inline)
41047
+ return null;
41048
+ const accountConfig = resolveInlineConfigForAccount(inline, params.accountId);
41049
+ const group = accountConfig.groups?.[params.groupId];
41050
+ return normalizeMin(group?.replyThreadAutoCreateMinMessages);
41051
+ }
41052
+ function ensureRecordField(parent, key) {
41053
+ const current = parent[key];
41054
+ if (isRecord5(current))
41055
+ return current;
41056
+ const next = {};
41057
+ parent[key] = next;
41058
+ return next;
41059
+ }
41060
+ function resolveMutableInlineConfigForAccount(inline, accountId) {
41061
+ const normalized = normalizeAccountId(accountId);
41062
+ if (normalized === DEFAULT_ACCOUNT_ID) {
41063
+ const accounts2 = isRecord5(inline.accounts) ? inline.accounts : undefined;
41064
+ const defaultKey = accounts2 ? Object.keys(accounts2).find((key) => normalizeAccountId(key) === DEFAULT_ACCOUNT_ID) : undefined;
41065
+ const defaultAccount = defaultKey ? accounts2?.[defaultKey] : undefined;
41066
+ return defaultAccount ?? inline;
41067
+ }
41068
+ const accounts = ensureRecordField(inline, "accounts");
41069
+ const accountKey = Object.keys(accounts).find((key) => normalizeAccountId(key) === normalized) ?? normalized;
41070
+ const account = asInlineConfig(accounts[accountKey]) ?? {};
41071
+ accounts[accountKey] = account;
41072
+ return account;
41073
+ }
41074
+ function setGroupMode(params) {
41075
+ const root = params.draft;
41076
+ const channels = root.channels ?? {};
41077
+ root.channels = channels;
41078
+ const inline = asInlineConfig(channels.inline) ?? {};
41079
+ channels.inline = inline;
41080
+ const accountConfig = resolveMutableInlineConfigForAccount(inline, params.accountId);
41081
+ const groups = ensureRecordField(accountConfig, "groups");
41082
+ const group = isRecord5(groups[params.groupId]) ? groups[params.groupId] : {};
41083
+ groups[params.groupId] = group;
41084
+ if (params.mode === "inherit") {
41085
+ delete group.replyThreadMode;
41086
+ return;
41087
+ }
41088
+ group.replyThreadMode = params.mode;
41089
+ }
41090
+ function setGroupMinMessages(params) {
41091
+ const root = params.draft;
41092
+ const channels = root.channels ?? {};
41093
+ root.channels = channels;
41094
+ const inline = asInlineConfig(channels.inline) ?? {};
41095
+ channels.inline = inline;
41096
+ const accountConfig = resolveMutableInlineConfigForAccount(inline, params.accountId);
41097
+ const groups = ensureRecordField(accountConfig, "groups");
41098
+ const group = isRecord5(groups[params.groupId]) ? groups[params.groupId] : {};
41099
+ groups[params.groupId] = group;
41100
+ if (params.minMessages === "inherit") {
41101
+ delete group.replyThreadAutoCreateMinMessages;
41102
+ return;
41103
+ }
41104
+ group.replyThreadAutoCreateMinMessages = params.minMessages;
41105
+ }
41106
+ function buildStatusText(params) {
41107
+ const explicit = readExplicitMode(params);
41108
+ const current = resolveCurrentMode(params);
41109
+ const explicitMin = readExplicitMinMessages(params);
41110
+ const currentMin = resolveCurrentMinMessages(params);
41111
+ return [
41112
+ `Thread reply mode for chat ${params.groupId}: ${MODE_LABELS[current]}.`,
41113
+ explicit ? `Explicit chat override: ${MODE_LABELS[explicit]}.` : "Explicit chat override: inherit.",
41114
+ `Auto-create minimum messages: ${currentMin}.`,
41115
+ explicitMin != null ? `Explicit minimum override: ${explicitMin}.` : "Explicit minimum override: inherit."
41116
+ ].join(`
41117
+ `);
41118
+ }
41119
+ function buildMenuText(params) {
41120
+ return [
41121
+ buildStatusText(params),
41122
+ "",
41123
+ "Choose where automatic replies for this group should go."
41124
+ ].join(`
41125
+ `);
41126
+ }
41127
+ function buildModeButtons() {
41128
+ return {
41129
+ inline: {
41130
+ buttons: [
41131
+ [
41132
+ { text: "Thread", callback_data: "/threadreply thread" },
41133
+ { text: "Main", callback_data: "/threadreply main" },
41134
+ { text: "Auto", callback_data: "/threadreply auto" }
41135
+ ],
41136
+ [{ text: "Inherit Mode", callback_data: "/threadreply inherit" }],
41137
+ [
41138
+ { text: "Min 0", callback_data: "/threadreply min 0" },
41139
+ { text: "Min 50", callback_data: "/threadreply min 50" },
41140
+ { text: "Inherit Min", callback_data: "/threadreply min inherit" }
41141
+ ]
41142
+ ]
41143
+ }
41144
+ };
41145
+ }
41146
+ function normalizeAction(args) {
41147
+ const [first = ""] = args.split(/\s+/).filter(Boolean);
41148
+ const normalized = first.trim().toLowerCase();
41149
+ if (!normalized || normalized === "help" || normalized === "options")
41150
+ return "help";
41151
+ if (normalized === "status" || normalized === "show")
41152
+ return "status";
41153
+ if (normalized === "inherit" || normalized === "default" || normalized === "unset")
41154
+ return "inherit";
41155
+ return normalizeMode(normalized);
41156
+ }
41157
+ async function handleInlineThreadReplyCommand(api2, ctx) {
41158
+ return await handleInlineThreadReplyCommandWithConfigRuntime(api2.runtime.config, ctx);
41159
+ }
41160
+ async function handleInlineThreadReplyCommandWithConfigRuntime(configRuntime, ctx) {
41161
+ if (!ctx.isAuthorizedSender) {
41162
+ return { text: "This command requires authorization." };
41163
+ }
41164
+ const groupId = resolveInlineGroupId(ctx);
41165
+ if (!groupId) {
41166
+ return { text: "/threadreply is only available in Inline group chats." };
41167
+ }
41168
+ const currentConfig = configRuntime.current();
41169
+ const args = ctx.args?.trim() ?? "";
41170
+ const [first = "", second, ...rest] = args.split(/\s+/).filter(Boolean);
41171
+ if (["min", "minimum", "threshold", "limit"].includes(first.trim().toLowerCase())) {
41172
+ const minMessages = parseMinArg(second);
41173
+ if (minMessages == null || rest.length > 0) {
41174
+ return { text: "Usage: /threadreply min <0-or-greater>|inherit" };
41175
+ }
41176
+ const committed2 = await configRuntime.mutateConfigFile({
41177
+ afterWrite: { mode: "auto" },
41178
+ mutate: (draft) => {
41179
+ setGroupMinMessages({
41180
+ draft,
41181
+ accountId: ctx.accountId,
41182
+ groupId,
41183
+ minMessages
41184
+ });
41185
+ }
41186
+ });
41187
+ const nextConfig2 = committed2.nextConfig;
41188
+ return {
41189
+ text: buildStatusText({
41190
+ cfg: nextConfig2,
41191
+ accountId: ctx.accountId,
41192
+ groupId
41193
+ })
41194
+ };
41195
+ }
41196
+ const action = normalizeAction(args);
41197
+ if (action === "help") {
41198
+ return {
41199
+ text: buildMenuText({
41200
+ cfg: currentConfig,
41201
+ accountId: ctx.accountId,
41202
+ groupId
41203
+ }),
41204
+ channelData: buildModeButtons()
41205
+ };
41206
+ }
41207
+ if (action === "status") {
41208
+ return {
41209
+ text: buildStatusText({
41210
+ cfg: currentConfig,
41211
+ accountId: ctx.accountId,
41212
+ groupId
41213
+ })
41214
+ };
41215
+ }
41216
+ if (!action) {
41217
+ return {
41218
+ text: [
41219
+ "Usage: /threadreply thread|main|auto|inherit|status",
41220
+ " /threadreply min <0-or-greater>|inherit",
41221
+ "",
41222
+ "- thread: auto-route parent-chat replies into per-message Inline reply threads once the minimum is reached.",
41223
+ "- main: keep automatic replies in the parent chat.",
41224
+ "- auto: use Inline's automatic default behavior for this chat.",
41225
+ "- inherit: remove this chat override and use account/default config.",
41226
+ "- min: set how many parent-chat messages must exist before automatic thread creation."
41227
+ ].join(`
41228
+ `)
41229
+ };
41230
+ }
41231
+ const committed = await configRuntime.mutateConfigFile({
41232
+ afterWrite: { mode: "auto" },
41233
+ mutate: (draft) => {
41234
+ setGroupMode({
41235
+ draft,
41236
+ accountId: ctx.accountId,
41237
+ groupId,
41238
+ mode: action
41239
+ });
41240
+ }
41241
+ });
41242
+ const nextConfig = committed.nextConfig;
41243
+ return {
41244
+ text: buildStatusText({
41245
+ cfg: nextConfig,
41246
+ accountId: ctx.accountId,
41247
+ groupId
41248
+ })
41249
+ };
41250
+ }
41251
+ function createInlineThreadReplyCommand(api2) {
41252
+ return {
41253
+ ...INLINE_THREADREPLY_COMMAND_SPEC,
41254
+ handler: async (ctx) => await handleInlineThreadReplyCommand(api2, ctx)
41255
+ };
41256
+ }
41257
+
40826
41258
  // src/inline/bot-commands-sync.ts
40827
41259
  var INLINE_COMMAND_NAME_RE = /^[a-z0-9_]{1,32}$/;
40828
41260
  var INLINE_COMMAND_LIMIT = 100;
40829
41261
  var INLINE_COMMAND_DESCRIPTION_LIMIT = 256;
40830
41262
  var INLINE_NATIVE_COMMAND_PROVIDER = "inline";
41263
+ function resolveInlineChannelCommands(cfg) {
41264
+ const inline = cfg.channels?.inline;
41265
+ if (typeof inline !== "object" || inline === null || Array.isArray(inline))
41266
+ return;
41267
+ const commands = inline.commands;
41268
+ return typeof commands === "object" && commands !== null && !Array.isArray(commands) ? commands : undefined;
41269
+ }
40831
41270
  function normalizeDynamicCommandName(raw) {
40832
41271
  const trimmed = raw.trim().toLowerCase();
40833
41272
  const withoutSlash = trimmed.startsWith("/") ? trimmed.slice(1) : trimmed;
@@ -40848,11 +41287,11 @@ function appendUniqueCommand(out, seen, command, description, logger) {
40848
41287
  out.push({ command: normalized, description: trimmedDescription });
40849
41288
  }
40850
41289
  function shouldSyncInlineNativeCommandsForAccount(params) {
40851
- const effective = params.account.config.commands?.native ?? params.cfg.commands?.native ?? "auto";
41290
+ const effective = params.account.config.commands?.native ?? resolveInlineChannelCommands(params.cfg)?.native ?? params.cfg.commands?.native ?? "auto";
40852
41291
  return effective !== false;
40853
41292
  }
40854
41293
  function shouldSyncInlineNativeSkillsForAccount(params) {
40855
- const effective = params.account.config.commands?.nativeSkills ?? params.cfg.commands?.nativeSkills ?? "auto";
41294
+ const effective = params.account.config.commands?.nativeSkills ?? resolveInlineChannelCommands(params.cfg)?.nativeSkills ?? params.cfg.commands?.nativeSkills ?? "auto";
40856
41295
  return effective !== false;
40857
41296
  }
40858
41297
  async function buildInlineNativeCommandsForConfig(params) {
@@ -40869,7 +41308,10 @@ async function buildInlineNativeCommandsForConfig(params) {
40869
41308
  skillCommands,
40870
41309
  provider: INLINE_NATIVE_COMMAND_PROVIDER
40871
41310
  });
40872
- const pluginSpecs = getPluginCommandSpecs("inline", { config: params.cfg });
41311
+ const pluginSpecs = [
41312
+ ...getPluginCommandSpecs("inline", { config: params.cfg }),
41313
+ ...listInlineBuiltinCommandSpecs()
41314
+ ];
40873
41315
  const seen = new Set;
40874
41316
  const resolved = [];
40875
41317
  for (const spec of nativeSpecs) {
@@ -40973,8 +41415,10 @@ var INLINE_NATIVE_COMMAND_PROVIDER2 = CHANNEL_ID;
40973
41415
  var INLINE_NATIVE_COMMAND_CALLBACK_PREFIX = "icmd:";
40974
41416
  var INLINE_REQUEST_ERROR_FALLBACK = "OpenClaw could not process that request. Please try again.";
40975
41417
  var INLINE_DEBOUNCE_ERROR_FALLBACK = "OpenClaw could not process those messages. Please try again.";
40976
- var DEFAULT_REPLY_THREAD_AUTO_CREATE_MIN_MESSAGES = 50;
41418
+ var DEFAULT_REPLY_THREAD_AUTO_CREATE_MIN_MESSAGES2 = 50;
40977
41419
  var DEFAULT_REPLY_THREAD_PARENT_HISTORY_LIMIT = 10;
41420
+ var INLINE_PARTICIPANT_ADD_READY_MAX_EVENT_AGE_MS = 10 * 60 * 1000;
41421
+ var INLINE_REPLY_THREAD_SYSTEM_PROMPT = "Inline reply threads are scoped conversations: answer only the current reply-thread message and this thread's own history; use parent-chat context only as background, and do not answer unrelated questions from the parent chat or other reply threads.";
40978
41422
  function buildInlineTypingDispatcherOptions(typingCallbacks) {
40979
41423
  if (!typingCallbacks) {
40980
41424
  return {};
@@ -41287,6 +41731,23 @@ function buildInlineReactionContextKey(params) {
41287
41731
  const emoji3 = params.emoji.trim() || "emoji";
41288
41732
  return `inline:reaction:${params.action}:${String(params.chatId)}:${String(params.messageId)}:${String(params.senderId)}:${emoji3}`;
41289
41733
  }
41734
+ function describeInlineParticipantAddSystemEvent(params) {
41735
+ const header = `Inline bot was added as a participant in ${params.channelLabel}.`;
41736
+ if (params.recentLines.length === 0)
41737
+ return header;
41738
+ return `${header}
41739
+ Recent messages before join:
41740
+ ${params.recentLines.join(`
41741
+ `)}`;
41742
+ }
41743
+ function buildInlineParticipantAddContextKey(params) {
41744
+ return [
41745
+ "inline:participant:added",
41746
+ String(params.chatId),
41747
+ String(params.userId),
41748
+ params.participantDate != null ? String(params.participantDate) : String(params.seq ?? 0)
41749
+ ].join(":");
41750
+ }
41290
41751
  function normalizeInlineUsername(raw) {
41291
41752
  const trimmed = raw?.trim();
41292
41753
  if (!trimmed)
@@ -41328,6 +41789,28 @@ function parseInlineNativeCommandCallbackData(raw) {
41328
41789
  const commandText = trimmed.slice(INLINE_NATIVE_COMMAND_CALLBACK_PREFIX.length).trim();
41329
41790
  return commandText.startsWith("/") ? commandText : null;
41330
41791
  }
41792
+ function listHostInlinePluginCommandSpecs(cfg) {
41793
+ return getPluginCommandSpecs2("inline", { config: cfg });
41794
+ }
41795
+ function listInlinePluginCommandSpecs(cfg) {
41796
+ return [
41797
+ ...listHostInlinePluginCommandSpecs(cfg),
41798
+ ...listInlineBuiltinCommandSpecs()
41799
+ ];
41800
+ }
41801
+ function hasInlineCommandSpec(specs, commandName) {
41802
+ const normalized = commandName.trim().toLowerCase();
41803
+ if (!normalized)
41804
+ return false;
41805
+ return specs.some((spec) => spec.name.trim().toLowerCase() === normalized);
41806
+ }
41807
+ function isInlineThreadReplyCommandBody(commandBody) {
41808
+ return resolveInlineCommandNameFromBody(commandBody) === "threadreply";
41809
+ }
41810
+ function parseInlineCommandArgs(commandBody) {
41811
+ const match = commandBody.trim().match(/^\/[^\s]+(?:\s+([\s\S]*))?$/);
41812
+ return match?.[1]?.trim() ?? "";
41813
+ }
41331
41814
  function isInlineNativeCommandBody(params) {
41332
41815
  if (!shouldSyncInlineNativeCommandsForAccount({ cfg: params.cfg, account: params.account })) {
41333
41816
  return false;
@@ -41350,7 +41833,7 @@ function isInlineNativeCommandBody(params) {
41350
41833
  if (spec.name.trim().toLowerCase() === commandName)
41351
41834
  return true;
41352
41835
  }
41353
- for (const spec of getPluginCommandSpecs2("inline", { config: params.cfg })) {
41836
+ for (const spec of listInlinePluginCommandSpecs(params.cfg)) {
41354
41837
  if (spec.name.trim().toLowerCase() === commandName)
41355
41838
  return true;
41356
41839
  }
@@ -41431,7 +41914,7 @@ function buildSyntheticInlineTextMessage(params) {
41431
41914
  }
41432
41915
  var INLINE_ACTION_MAX_ROWS2 = 8;
41433
41916
  var INLINE_ACTION_MAX_PER_ROW2 = 8;
41434
- function isRecord5(value) {
41917
+ function isRecord6(value) {
41435
41918
  return typeof value === "object" && value !== null && !Array.isArray(value);
41436
41919
  }
41437
41920
  function normalizeOptionalString2(value) {
@@ -41452,7 +41935,7 @@ function normalizeInlineStreamingMode(value) {
41452
41935
  }
41453
41936
  }
41454
41937
  function resolveExplicitInlineStreamingMode(config2) {
41455
- const streaming = isRecord5(config2.streaming) ? config2.streaming : null;
41938
+ const streaming = isRecord6(config2.streaming) ? config2.streaming : null;
41456
41939
  return normalizeInlineStreamingMode(streaming?.mode) ?? normalizeInlineStreamingMode(config2.streaming) ?? normalizeInlineStreamingMode(config2.streamMode);
41457
41940
  }
41458
41941
  function resolveInlineStreamingMode(config2) {
@@ -41472,14 +41955,14 @@ function resolveInlineProgressPlaceholderEnabled(config2) {
41472
41955
  return true;
41473
41956
  if (config2.streaming === false)
41474
41957
  return false;
41475
- if (isRecord5(config2.streaming) && isRecord5(config2.streaming.progress))
41958
+ if (isRecord6(config2.streaming) && isRecord6(config2.streaming.progress))
41476
41959
  return true;
41477
41960
  return config2.streaming === undefined && config2.streamMode === undefined && config2.streamViaEditMessage !== true;
41478
41961
  }
41479
41962
  function resolveInlineBlockStreamingEnabled(config2) {
41480
41963
  const mode = resolveInlineStreamingMode(config2);
41481
- const streaming = isRecord5(config2.streaming) ? config2.streaming : null;
41482
- const block = streaming && isRecord5(streaming.block) ? streaming.block : null;
41964
+ const streaming = isRecord6(config2.streaming) ? config2.streaming : null;
41965
+ const block = streaming && isRecord6(streaming.block) ? streaming.block : null;
41483
41966
  if (typeof block?.enabled === "boolean")
41484
41967
  return block.enabled;
41485
41968
  if (typeof config2.blockStreaming === "boolean")
@@ -41703,7 +42186,7 @@ function normalizeReplyMarkupButtonsWith(raw, options) {
41703
42186
  continue;
41704
42187
  const row = [];
41705
42188
  for (const candidateButton of candidateRow) {
41706
- if (!isRecord5(candidateButton))
42189
+ if (!isRecord6(candidateButton))
41707
42190
  continue;
41708
42191
  const text = sanitizeInlineActionLabel(typeof candidateButton.text === "string" ? candidateButton.text : "");
41709
42192
  const callbackDataRaw = typeof candidateButton.callback_data === "string" ? candidateButton.callback_data.trim() : "";
@@ -41724,9 +42207,9 @@ function normalizeReplyMarkupButtonsWith(raw, options) {
41724
42207
  return rows;
41725
42208
  }
41726
42209
  function resolveInlineReplyActions(payload) {
41727
- const channelData = isRecord5(payload.channelData) ? payload.channelData : undefined;
41728
- const inlineData = channelData && isRecord5(channelData.inline) ? channelData.inline : undefined;
41729
- const telegramData = channelData && isRecord5(channelData.telegram) ? channelData.telegram : undefined;
42210
+ const channelData = isRecord6(payload.channelData) ? payload.channelData : undefined;
42211
+ const inlineData = channelData && isRecord6(channelData.inline) ? channelData.inline : undefined;
42212
+ const telegramData = channelData && isRecord6(channelData.telegram) ? channelData.telegram : undefined;
41730
42213
  let rawButtons = undefined;
41731
42214
  let hasExplicitButtons = false;
41732
42215
  let mapCallbackData;
@@ -41792,7 +42275,11 @@ function resolveInlineSystemPrompt(params) {
41792
42275
  groups: params.account.config.groups,
41793
42276
  groupId: params.groupId
41794
42277
  }) : undefined;
41795
- return [buildInlineSystemPrompt(params.account.config.systemPrompt), groupPrompt].filter((entry) => Boolean(entry)).join(`
42278
+ return [
42279
+ buildInlineSystemPrompt(params.account.config.systemPrompt),
42280
+ groupPrompt,
42281
+ params.replyThread ? INLINE_REPLY_THREAD_SYSTEM_PROMPT : undefined
42282
+ ].filter((entry) => Boolean(entry)).join(`
41796
42283
 
41797
42284
  `);
41798
42285
  }
@@ -42231,13 +42718,6 @@ function buildInlineInboundBodyText(content) {
42231
42718
  `).trim();
42232
42719
  return textWithPlaceholder || content.text;
42233
42720
  }
42234
- function hasDownloadableInlineMedia(content) {
42235
- if (!content)
42236
- return false;
42237
- if (content.media?.url)
42238
- return true;
42239
- return content.attachments.some((attachment) => attachment.kind === "urlPreview" && Boolean(attachment.previewImageUrl));
42240
- }
42241
42721
  function resolveFilePathHint(params) {
42242
42722
  const preferred = params.preferredName?.trim();
42243
42723
  if (preferred)
@@ -42275,8 +42755,9 @@ async function resolveInlineInboundMedia(params) {
42275
42755
  maxBytes: params.maxBytes,
42276
42756
  ...filePathHint ? { filePathHint } : {}
42277
42757
  });
42278
- const saved = await params.core.channel.media.saveMediaBuffer(fetched.buffer, fetched.contentType ?? candidate.mimeType ?? undefined, "inbound", params.maxBytes, fetched.fileName ?? candidate.fileName ?? undefined);
42279
- const contentType = saved.contentType ?? fetched.contentType ?? candidate.mimeType ?? undefined;
42758
+ const fetchedContentType = fetched.contentType ?? candidate.mimeType ?? undefined;
42759
+ const saved = await params.core.channel.media.saveMediaBuffer(fetched.buffer, fetchedContentType, "inbound", params.maxBytes, fetched.fileName ?? candidate.fileName ?? undefined);
42760
+ const contentType = saved.contentType ?? fetchedContentType;
42280
42761
  out.push({
42281
42762
  path: saved.path,
42282
42763
  ...contentType ? { contentType } : {}
@@ -42477,6 +42958,34 @@ ${entityLines.slice(-ATTACHMENT_CONTEXT_LIMIT).join(`
42477
42958
  hasBotMessage
42478
42959
  };
42479
42960
  }
42961
+ function buildInlineRecentHistoryLines(params) {
42962
+ if (params.maxLines <= 0)
42963
+ return [];
42964
+ return params.messages.slice().sort((a, b) => {
42965
+ const byDate = Number(a.date - b.date);
42966
+ if (byDate !== 0)
42967
+ return byDate;
42968
+ if (a.id === b.id)
42969
+ return 0;
42970
+ return a.id < b.id ? -1 : 1;
42971
+ }).map((message) => buildInlineHistoryEntryPayload({
42972
+ message,
42973
+ senderProfilesById: params.senderProfilesById,
42974
+ meId: params.meId
42975
+ })).map((entry) => entry.line ?? entry.attachmentLine ?? entry.entityLine).filter((line) => Boolean(line)).slice(-params.maxLines);
42976
+ }
42977
+ function buildInlineParticipantAddReadyText(botUsername) {
42978
+ const mention = botUsername ? `@${botUsername}` : "me";
42979
+ return `I'm here and ready. Mention ${mention} to ask me something.`;
42980
+ }
42981
+ function shouldSendInlineParticipantAddReadyMessage(participantDate, now = Date.now()) {
42982
+ if (participantDate == null)
42983
+ return true;
42984
+ const eventMs = Number(participantDate) * 1000;
42985
+ if (!Number.isFinite(eventMs) || eventMs <= 0)
42986
+ return true;
42987
+ return now - eventMs <= INLINE_PARTICIPANT_ADD_READY_MAX_EVENT_AGE_MS;
42988
+ }
42480
42989
  async function monitorInlineProvider(params) {
42481
42990
  const { cfg, account, runtime, abortSignal, log, statusSink } = params;
42482
42991
  const core3 = getInlineRuntime();
@@ -42486,6 +42995,7 @@ async function monitorInlineProvider(params) {
42486
42995
  const token = await resolveInlineToken(account);
42487
42996
  const stateDir = core3.state.resolveStateDir();
42488
42997
  const statePath = path4.join(stateDir, "channels", "inline", `${account.accountId}.json`);
42998
+ const hasExistingState = await stat(statePath).then(() => true).catch(() => false);
42489
42999
  await mkdir(path4.dirname(statePath), { recursive: true });
42490
43000
  let client = null;
42491
43001
  const pushDiagnostics = (patch) => {
@@ -42512,7 +43022,8 @@ async function monitorInlineProvider(params) {
42512
43022
  baseUrl: account.baseUrl,
42513
43023
  token,
42514
43024
  logger: sdkLog,
42515
- state: new JsonFileStateStore(statePath)
43025
+ state: new JsonFileStateStore(statePath),
43026
+ catchUpUserFromStart: hasExistingState
42516
43027
  });
42517
43028
  await client.connect(abortSignal);
42518
43029
  pushDiagnostics();
@@ -42614,7 +43125,7 @@ async function monitorInlineProvider(params) {
42614
43125
  const senderId = params2.senderId != null ? String(params2.senderId) : null;
42615
43126
  const dmPolicy = account.config.dmPolicy ?? "pairing";
42616
43127
  const defaultGroupPolicy = cfg.channels?.defaults?.groupPolicy;
42617
- const groupPolicy = account.config.groupPolicy ?? defaultGroupPolicy ?? "allowlist";
43128
+ const groupPolicy = account.config.groupPolicy ?? defaultGroupPolicy ?? INLINE_DEFAULT_GROUP_POLICY;
42618
43129
  if (isGroup) {
42619
43130
  if (groupPolicy === "disabled") {
42620
43131
  log?.info(`[${account.accountId}] inline: drop ${params2.eventKind} chat=${String(params2.chatId)} (groupPolicy=disabled)`);
@@ -42627,6 +43138,7 @@ async function monitorInlineProvider(params) {
42627
43138
  senderId
42628
43139
  });
42629
43140
  if (groupPolicy === "allowlist") {
43141
+ const shouldBypassGroupAccess = params2.eventKind === "participant.add";
42630
43142
  const groupAccess = resolveInlineGroupAccessPolicy({
42631
43143
  cfg,
42632
43144
  accountId: account.accountId,
@@ -42634,11 +43146,11 @@ async function monitorInlineProvider(params) {
42634
43146
  hasGroupAllowFrom: groupSenderAllowlist.raw.length > 0,
42635
43147
  groupPolicy
42636
43148
  });
42637
- if (groupAccess.allowlistEnabled && !groupAccess.allowed) {
43149
+ if (groupAccess.allowlistEnabled && !groupAccess.allowed && !shouldBypassGroupAccess) {
42638
43150
  log?.info(`[${account.accountId}] inline: drop ${params2.eventKind} chat=${String(effectiveChatId)} (groupPolicy=allowlist)`);
42639
43151
  return null;
42640
43152
  }
42641
- if (groupSenderAllowlist.raw.length > 0) {
43153
+ if (groupSenderAllowlist.raw.length > 0 && !shouldBypassGroupAccess) {
42642
43154
  if (senderId == null && !groupSenderAllowlist.raw.includes("*")) {
42643
43155
  log?.info(`[${account.accountId}] inline: drop ${params2.eventKind} chat=${String(effectiveChatId)} (sender unknown)`);
42644
43156
  return null;
@@ -42777,6 +43289,74 @@ async function monitorInlineProvider(params) {
42777
43289
  messageId: params2.messageId
42778
43290
  }), eventOptions);
42779
43291
  };
43292
+ const queueInlineParticipantAddSystemEvent = async (params2) => {
43293
+ if (params2.participant?.userId !== meId)
43294
+ return;
43295
+ const inboundAt = Date.now();
43296
+ statusSink?.({
43297
+ lastInboundAt: inboundAt,
43298
+ lastEventAt: inboundAt,
43299
+ ...createTransportActivityStatusPatch(inboundAt)
43300
+ });
43301
+ const ingress = await resolveInlineSystemEventContext({
43302
+ chatId: params2.chatId,
43303
+ senderId: null,
43304
+ eventKind: "participant.add"
43305
+ });
43306
+ if (!ingress)
43307
+ return;
43308
+ await hydrateChatParticipants(params2.chatId);
43309
+ const chatInfo = chatCache.get(params2.chatId);
43310
+ const isGroup = chatInfo?.kind !== "direct";
43311
+ const historyLimit = resolveHistoryLimit({
43312
+ cfg,
43313
+ isGroup,
43314
+ historyLimit: account.config.historyLimit,
43315
+ dmHistoryLimit: account.config.dmHistoryLimit
43316
+ });
43317
+ const recentMessages = historyLimit > 0 ? await loadChatHistoryMessages({
43318
+ client,
43319
+ chatId: params2.chatId,
43320
+ limit: Math.min(historyLimit, 10)
43321
+ }).catch((err) => {
43322
+ statusSink?.({ lastError: `getChatHistory (participant add) failed: ${String(err)}` });
43323
+ return null;
43324
+ }) : null;
43325
+ const recentLines = recentMessages ? buildInlineRecentHistoryLines({
43326
+ messages: recentMessages,
43327
+ senderProfilesById,
43328
+ meId,
43329
+ maxLines: Math.min(historyLimit, 10)
43330
+ }) : [];
43331
+ const contextKey = buildInlineParticipantAddContextKey({
43332
+ chatId: params2.chatId,
43333
+ userId: meId,
43334
+ ...params2.participant.date != null ? { participantDate: params2.participant.date } : {},
43335
+ ...params2.seq != null ? { seq: params2.seq } : {}
43336
+ });
43337
+ core3.system.enqueueSystemEvent(describeInlineParticipantAddSystemEvent({
43338
+ channelLabel: ingress.channelLabel,
43339
+ recentLines
43340
+ }), {
43341
+ sessionKey: ingress.sessionKey,
43342
+ contextKey,
43343
+ forceSenderIsOwnerFalse: true,
43344
+ trusted: false
43345
+ });
43346
+ if (shouldSendInlineParticipantAddReadyMessage(params2.participant.date)) {
43347
+ try {
43348
+ await client.sendMessage({
43349
+ chatId: params2.chatId,
43350
+ text: buildInlineParticipantAddReadyText(botUsername),
43351
+ parseMarkdown: account.config.parseMarkdown ?? true
43352
+ });
43353
+ statusSink?.({ lastOutboundAt: Date.now() });
43354
+ } catch (err) {
43355
+ runtime.error?.(`inline participant-add ready message failed: ${String(err)}`);
43356
+ statusSink?.({ lastError: `participant-add ready message failed: ${String(err)}` });
43357
+ }
43358
+ }
43359
+ };
42780
43360
  const shouldQueueInlineReactionSystemEvent = async (params2) => {
42781
43361
  const mode = account.config.reactionNotifications ?? "own";
42782
43362
  if (mode === "off")
@@ -42862,8 +43442,8 @@ async function monitorInlineProvider(params) {
42862
43442
  cfg,
42863
43443
  accountId: account.accountId,
42864
43444
  groupId: String(effectiveChatId),
42865
- defaultMinMessages: account.config.replyThreadAutoCreateMinMessages ?? inlineThreadDefaults.replyThreadAutoCreateMinMessages ?? DEFAULT_REPLY_THREAD_AUTO_CREATE_MIN_MESSAGES
42866
- }) : DEFAULT_REPLY_THREAD_AUTO_CREATE_MIN_MESSAGES;
43445
+ defaultMinMessages: account.config.replyThreadAutoCreateMinMessages ?? inlineThreadDefaults.replyThreadAutoCreateMinMessages ?? DEFAULT_REPLY_THREAD_AUTO_CREATE_MIN_MESSAGES2
43446
+ }) : DEFAULT_REPLY_THREAD_AUTO_CREATE_MIN_MESSAGES2;
42867
43447
  const replyThreadRequireExplicitMention = isGroup && replyThreadsEnabled ? resolveInlineGroupReplyThreadRequireExplicitMention({
42868
43448
  cfg,
42869
43449
  accountId: account.accountId,
@@ -42887,7 +43467,7 @@ async function monitorInlineProvider(params) {
42887
43467
  }
42888
43468
  const dmPolicy = account.config.dmPolicy ?? "pairing";
42889
43469
  const defaultGroupPolicy = cfg.channels?.defaults?.groupPolicy;
42890
- const groupPolicy = account.config.groupPolicy ?? defaultGroupPolicy ?? "allowlist";
43470
+ const groupPolicy = account.config.groupPolicy ?? defaultGroupPolicy ?? INLINE_DEFAULT_GROUP_POLICY;
42891
43471
  const configAllowFrom = await resolveInlineAllowlist({
42892
43472
  cfg,
42893
43473
  accountId: account.accountId,
@@ -42967,6 +43547,8 @@ async function monitorInlineProvider(params) {
42967
43547
  });
42968
43548
  const hasControlCommand = hasTextControlCommand || isRegisteredNativeCommand;
42969
43549
  const commandSource = hasControlCommand ? isRegisteredNativeCommand ? "native" : "text" : undefined;
43550
+ const normalizedCommandName = resolveInlineCommandNameFromBody(normalizedCommandBody);
43551
+ const hostInlinePluginCommandRegistered = normalizedCommandName ? hasInlineCommandSpec(listHostInlinePluginCommandSpecs(cfg), normalizedCommandName) : false;
42970
43552
  const allowTextCommands = core3.channel.commands.shouldHandleTextCommands({
42971
43553
  cfg,
42972
43554
  surface: CHANNEL_ID,
@@ -42990,6 +43572,7 @@ async function monitorInlineProvider(params) {
42990
43572
  commandAuthorized: commandGate.commandAuthorized
42991
43573
  });
42992
43574
  const shouldBlockControlCommand = allowTextCommands && hasControlCommand && !commandAuthorized;
43575
+ const nativeMentioned = typeof msg.mentioned === "boolean" ? msg.mentioned : false;
42993
43576
  if (isGroup) {
42994
43577
  if (groupPolicy === "disabled") {
42995
43578
  log?.info(`[${account.accountId}] inline: drop group chat=${String(chatId)} (groupPolicy=disabled)`);
@@ -43006,7 +43589,7 @@ async function monitorInlineProvider(params) {
43006
43589
  hasGroupAllowFrom: groupSenderAllowlist.raw.length > 0,
43007
43590
  groupPolicy
43008
43591
  });
43009
- if (groupAccess.allowlistEnabled && !groupAccess.allowed) {
43592
+ if (groupAccess.allowlistEnabled && !groupAccess.allowed && !nativeMentioned) {
43010
43593
  log?.info(`[${account.accountId}] inline: drop group chat=${String(effectiveChatId)} (groupPolicy=allowlist)`);
43011
43594
  await answerCallbackIfNeeded().catch((error51) => {
43012
43595
  runtime.error?.(`inline callback answer failed: ${String(error51)}`);
@@ -43078,7 +43661,6 @@ async function monitorInlineProvider(params) {
43078
43661
  return;
43079
43662
  }
43080
43663
  const mentionRegexes = core3.channel.mentions.buildMentionRegexes(cfg, route.agentId);
43081
- const nativeMentioned = typeof msg.mentioned === "boolean" ? msg.mentioned : false;
43082
43664
  const patternMentioned = mentionRegexes.length ? core3.channel.mentions.matchesMentionPatterns(rawBody, mentionRegexes) : false;
43083
43665
  const wasMentioned = nativeMentioned || patternMentioned;
43084
43666
  const messageTimestamp = Number(msg.date) * 1000;
@@ -43136,7 +43718,7 @@ async function monitorInlineProvider(params) {
43136
43718
  cfg,
43137
43719
  groupId: String(effectiveChatId),
43138
43720
  accountId: account.accountId,
43139
- requireMentionDefault: account.config.requireMention ?? false
43721
+ requireMentionDefault: account.config.requireMention ?? INLINE_DEFAULT_REQUIRE_MENTION
43140
43722
  }) : false;
43141
43723
  const mentionGate = resolveMentionGatingWithBypass({
43142
43724
  isGroup,
@@ -43181,6 +43763,74 @@ async function monitorInlineProvider(params) {
43181
43763
  return;
43182
43764
  }
43183
43765
  const parseMarkdown = account.config.parseMarkdown ?? true;
43766
+ if (isInlineThreadReplyCommandBody(normalizedCommandBody) && !hostInlinePluginCommandRegistered) {
43767
+ const configRuntime = core3.config;
43768
+ if (typeof configRuntime?.current !== "function" || typeof configRuntime.mutateConfigFile !== "function") {
43769
+ runtime.error?.("inline /threadreply fallback unavailable: runtime config API missing");
43770
+ } else {
43771
+ const result = await handleInlineThreadReplyCommandWithConfigRuntime(configRuntime, {
43772
+ senderId,
43773
+ channel: CHANNEL_ID,
43774
+ channelId: CHANNEL_ID,
43775
+ isAuthorizedSender: commandAuthorized,
43776
+ senderIsOwner: commandAuthorized,
43777
+ sessionKey: inboundSessionKey,
43778
+ args: parseInlineCommandArgs(normalizedCommandBody),
43779
+ commandBody: normalizedCommandBody,
43780
+ config: cfg,
43781
+ from: isGroup ? `inline:chat:${String(effectiveChatId)}` : `inline:${senderId}`,
43782
+ to: `inline:${String(effectiveChatId)}`,
43783
+ accountId: account.accountId,
43784
+ ...replyThreadContext ? {
43785
+ messageThreadId: String(replyThreadContext.childChatId),
43786
+ threadParentId: String(replyThreadContext.parentChatId)
43787
+ } : {},
43788
+ requestConversationBinding: async () => ({ ok: false }),
43789
+ detachConversationBinding: async () => ({ removed: false }),
43790
+ getCurrentConversationBinding: async () => null
43791
+ });
43792
+ const resultRecord = result;
43793
+ const actions = resolveInlineReplyActions(resultRecord);
43794
+ const text = typeof result.text === "string" ? sanitizeInlineDeliveryText(result.text) : "";
43795
+ if (text || actions) {
43796
+ let delivered = false;
43797
+ if (shouldEditCallbackTargetInPlace && callbackActionEvent) {
43798
+ try {
43799
+ const editResult = await client.invokeRaw(Method.EDIT_MESSAGE, {
43800
+ oneofKind: "editMessage",
43801
+ editMessage: {
43802
+ messageId: callbackActionEvent.targetMessageId,
43803
+ peerId: buildChatPeer3(chatId),
43804
+ text,
43805
+ ...actions ? { actions } : {},
43806
+ parseMarkdown
43807
+ }
43808
+ });
43809
+ if (editResult.oneofKind !== "editMessage") {
43810
+ throw new Error(`inline /threadreply edit: expected editMessage result, got ${String(editResult.oneofKind)}`);
43811
+ }
43812
+ delivered = true;
43813
+ } catch (error51) {
43814
+ runtime.error?.(`inline /threadreply edit failed; falling back to send (${String(error51)})`);
43815
+ }
43816
+ }
43817
+ if (!delivered) {
43818
+ const sent = await client.sendMessage({
43819
+ chatId,
43820
+ text,
43821
+ ...actions ? { actions } : {},
43822
+ parseMarkdown
43823
+ });
43824
+ rememberSentBotMessage({ chatId, messageId: sent.messageId, replyThreadContext });
43825
+ }
43826
+ statusSink?.({ lastOutboundAt: Date.now() });
43827
+ }
43828
+ await answerCallbackIfNeeded().catch((error51) => {
43829
+ runtime.error?.(`inline callback answer failed: ${String(error51)}`);
43830
+ });
43831
+ return;
43832
+ }
43833
+ }
43184
43834
  const commandsPageCallback = callbackActionEvent ? parseInlineCommandsPageCallback(callbackDataToUtf8(callbackActionEvent.data)) : null;
43185
43835
  if (shouldEditCallbackTargetInPlace && callbackActionEvent && commandsPageCallback) {
43186
43836
  if (commandsPageCallback.page === "noop")
@@ -43513,13 +44163,6 @@ This model will be used for your next message.`, []);
43513
44163
  maxBytes: inboundMediaMaxBytes,
43514
44164
  ...log ? { log } : {}
43515
44165
  });
43516
- const inheritedAnchorMedia = deliveryReplyThreadContext?.anchorMessage != null && currentContent != null && !hasDownloadableInlineMedia(currentContent) ? await resolveInlineInboundMedia({
43517
- core: core3,
43518
- message: deliveryReplyThreadContext.anchorMessage,
43519
- maxBytes: inboundMediaMaxBytes,
43520
- ...log ? { log } : {}
43521
- }) : [];
43522
- const mediaForAgent = inboundMedia.length > 0 ? inboundMedia : inheritedAnchorMedia;
43523
44166
  const timestamp = messageTimestamp;
43524
44167
  const fromLabel = resolveInlineConversationLabel({
43525
44168
  isGroup,
@@ -43556,7 +44199,8 @@ This model will be used for your next message.`, []);
43556
44199
  const effectiveSurface = CHANNEL_ID;
43557
44200
  const systemPrompt = resolveInlineSystemPrompt({
43558
44201
  account,
43559
- ...isGroup ? { groupId: String(effectiveChatId) } : {}
44202
+ ...isGroup ? { groupId: String(effectiveChatId) } : {},
44203
+ replyThread: Boolean(deliveryReplyThreadContext)
43560
44204
  });
43561
44205
  const messageSid = buildInlineInboundMessageSid({
43562
44206
  msgId: msg.id,
@@ -43608,7 +44252,7 @@ This model will be used for your next message.`, []);
43608
44252
  MessageActionDataBase64: callbackDataToBase64(callbackActionEvent.data),
43609
44253
  ...callbackDataToUtf8(callbackActionEvent.data) ? { MessageActionDataUtf8: callbackDataToUtf8(callbackActionEvent.data) } : {}
43610
44254
  } : {},
43611
- ...buildInlineInboundMediaPayload(mediaForAgent),
44255
+ ...buildInlineInboundMediaPayload(inboundMedia),
43612
44256
  Timestamp: timestamp || Date.now(),
43613
44257
  ...isGroup ? { WasMentioned: mentionGate.effectiveWasMentioned } : {},
43614
44258
  ...isGroup ? {
@@ -44351,6 +44995,19 @@ Attachment: ${mediaUrl}` : `Attachment: ${mediaUrl}`;
44351
44995
  });
44352
44996
  continue;
44353
44997
  }
44998
+ if (rawEvent["kind"] === "chat.participant.add") {
44999
+ const eventChatId = rawEvent["chatId"];
45000
+ if (!eventChatId)
45001
+ continue;
45002
+ const participant = rawEvent["participant"];
45003
+ const seq = rawEvent["seq"];
45004
+ await queueInlineParticipantAddSystemEvent({
45005
+ chatId: eventChatId,
45006
+ ...participant ? { participant } : {},
45007
+ ...seq != null ? { seq } : {}
45008
+ });
45009
+ continue;
45010
+ }
44354
45011
  if (rawEvent["kind"] === "message.action.invoke") {
44355
45012
  const actorUserId = rawEvent["actorUserId"];
44356
45013
  const interactionId = rawEvent["interactionId"];
@@ -44415,7 +45072,7 @@ Attachment: ${mediaUrl}` : `Attachment: ${mediaUrl}`;
44415
45072
  }
44416
45073
 
44417
45074
  // src/inline/doctor.ts
44418
- function isRecord6(value) {
45075
+ function isRecord7(value) {
44419
45076
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
44420
45077
  }
44421
45078
  function readInherited(account, parent, key) {
@@ -44426,18 +45083,18 @@ function hasEntries(value) {
44426
45083
  }
44427
45084
  function hasConfiguredGroups(account, parent) {
44428
45085
  const groups = readInherited(account, parent, "groups");
44429
- return isRecord6(groups) && Object.keys(groups).length > 0;
45086
+ return isRecord7(groups) && Object.keys(groups).length > 0;
44430
45087
  }
44431
45088
  function hasGroupScopedSenders(groups) {
44432
- if (!isRecord6(groups))
45089
+ if (!isRecord7(groups))
44433
45090
  return false;
44434
- return Object.values(groups).some((group) => isRecord6(group) && hasEntries(group.allowFrom));
45091
+ return Object.values(groups).some((group) => isRecord7(group) && hasEntries(group.allowFrom));
44435
45092
  }
44436
45093
  function hasGroupSenders(account, parent) {
44437
45094
  return hasEntries(readInherited(account, parent, "groupAllowFrom")) || hasGroupScopedSenders(readInherited(account, parent, "groups"));
44438
45095
  }
44439
45096
  function getGroupPolicy(account, parent) {
44440
- return String(readInherited(account, parent, "groupPolicy") ?? "allowlist");
45097
+ return String(readInherited(account, parent, "groupPolicy") ?? INLINE_DEFAULT_GROUP_POLICY);
44441
45098
  }
44442
45099
  function collectInlineEmptyAllowlistWarnings(params) {
44443
45100
  if (params.channelName !== "inline")
@@ -44594,7 +45251,8 @@ var INLINE_USER_ID_HELP_LINES = [
44594
45251
  "Docs: https://inline.chat/docs/openclaw"
44595
45252
  ];
44596
45253
  var INLINE_GROUP_HELP_LINES = [
44597
- "Allowlist Inline group chats by numeric chat id.",
45254
+ "Inline groups are open by default and require a bot mention by default.",
45255
+ "Optionally allowlist Inline group chats by numeric chat id.",
44598
45256
  "Accepted forms: 123456789, chat:123456789, inline:123456789, *.",
44599
45257
  "Use * for every group chat; the setup keeps requireMention=true for broad group access.",
44600
45258
  "Use /whoami in a group and copy the Chat line to get the Inline chat id.",
@@ -44741,7 +45399,7 @@ function buildInlineDmAccessWarningLines(accountId) {
44741
45399
  function buildInlineGroupAccessWarningLines(params) {
44742
45400
  const resolved = resolveInlineAccount({ cfg: params.cfg, accountId: params.accountId });
44743
45401
  const configBase = formatInlineConfigBase(params.accountId);
44744
- const policy = resolved.config.groupPolicy ?? "allowlist";
45402
+ const policy = resolved.config.groupPolicy ?? INLINE_DEFAULT_GROUP_POLICY;
44745
45403
  const groups = resolved.config.groups ?? {};
44746
45404
  const hasGroups = Object.keys(groups).length > 0;
44747
45405
  const hasGroupAllowFrom = (resolved.config.groupAllowFrom ?? []).some((entry) => String(entry).trim());
@@ -44754,7 +45412,8 @@ function buildInlineGroupAccessWarningLines(params) {
44754
45412
  ];
44755
45413
  }
44756
45414
  const wildcard = groups["*"];
44757
- if (policy === "open" && wildcard?.requireMention !== true) {
45415
+ const requireMention = wildcard?.requireMention ?? resolved.config.requireMention ?? INLINE_DEFAULT_REQUIRE_MENTION;
45416
+ if (policy === "open" && requireMention !== true) {
44758
45417
  return [
44759
45418
  "Inline groups are open to every group chat without a default mention requirement.",
44760
45419
  "For safer broad group access, require bot mentions or switch to an explicit group allowlist:",
@@ -45018,11 +45677,11 @@ async function probeInlineAccount(account, timeoutMs) {
45018
45677
  }
45019
45678
 
45020
45679
  // src/inline/status-issues.ts
45021
- import { asString, isRecord as isRecord7 } from "openclaw/plugin-sdk/status-helpers";
45680
+ import { asString, isRecord as isRecord8 } from "openclaw/plugin-sdk/status-helpers";
45022
45681
  var RECENT_RUNTIME_ISSUE_MS = 30 * 60 * 1000;
45023
45682
  var INLINE_CONNECT_GRACE_MS = 120 * 1000;
45024
45683
  function readInlineProbeSummary(value) {
45025
- if (!isRecord7(value)) {
45684
+ if (!isRecord8(value)) {
45026
45685
  return {};
45027
45686
  }
45028
45687
  const summary = {};
@@ -45039,12 +45698,12 @@ function looksLikeAuthError(text) {
45039
45698
  return /(401|403|unauth|forbidden|invalid token|token invalid|unauthorized)/i.test(text);
45040
45699
  }
45041
45700
  function readInlineDiagnosticsSummary(value) {
45042
- if (!isRecord7(value)) {
45701
+ if (!isRecord8(value)) {
45043
45702
  return {};
45044
45703
  }
45045
- const protocolValue = isRecord7(value.protocol) ? value.protocol : undefined;
45046
- const transportValue = (protocolValue && isRecord7(protocolValue.transport) ? protocolValue.transport : undefined) ?? (isRecord7(value.transport) ? value.transport : undefined);
45047
- const pingValue = protocolValue && isRecord7(protocolValue.ping) ? protocolValue.ping : undefined;
45704
+ const protocolValue = isRecord8(value.protocol) ? value.protocol : undefined;
45705
+ const transportValue = (protocolValue && isRecord8(protocolValue.transport) ? protocolValue.transport : undefined) ?? (isRecord8(value.transport) ? value.transport : undefined);
45706
+ const pingValue = protocolValue && isRecord8(protocolValue.ping) ? protocolValue.ping : undefined;
45048
45707
  return {
45049
45708
  ...protocolValue ? {
45050
45709
  protocol: {
@@ -45076,7 +45735,7 @@ function asFiniteNumber(value) {
45076
45735
  function collectInlineStatusIssues(accounts) {
45077
45736
  const issues = [];
45078
45737
  for (const entry of accounts) {
45079
- if (!isRecord7(entry)) {
45738
+ if (!isRecord8(entry)) {
45080
45739
  continue;
45081
45740
  }
45082
45741
  const accountId = asString(entry.accountId);
@@ -45212,6 +45871,14 @@ function hasInlineCommandAllowFrom(cfg) {
45212
45871
  const byProvider = allowFrom;
45213
45872
  return hasEntries2(byProvider.inline) || hasEntries2(byProvider["*"]);
45214
45873
  }
45874
+ function groupDefaultRequiresMention(account) {
45875
+ const groups = account.config.groups;
45876
+ const wildcard = groups && typeof groups === "object" && !Array.isArray(groups) ? groups["*"] : undefined;
45877
+ const wildcardRequireMention = wildcard && typeof wildcard === "object" && !Array.isArray(wildcard) ? wildcard.requireMention : undefined;
45878
+ if (typeof wildcardRequireMention === "boolean")
45879
+ return wildcardRequireMention;
45880
+ return account.config.requireMention ?? INLINE_DEFAULT_REQUIRE_MENTION;
45881
+ }
45215
45882
  function collectInvalidAllowFromEntries(params) {
45216
45883
  if (!Array.isArray(params.entries))
45217
45884
  return;
@@ -45268,7 +45935,7 @@ var inlineSecurityAdapter = {
45268
45935
  },
45269
45936
  collectWarnings: ({ account, cfg }) => {
45270
45937
  const defaultGroupPolicy = cfg.channels?.defaults?.groupPolicy;
45271
- const groupPolicy = account.config.groupPolicy ?? defaultGroupPolicy ?? "allowlist";
45938
+ const groupPolicy = account.config.groupPolicy ?? defaultGroupPolicy ?? INLINE_DEFAULT_GROUP_POLICY;
45272
45939
  const groupRulesConfigured = Boolean(account.config.groups) && Object.keys(account.config.groups ?? {}).length > 0;
45273
45940
  const groupSendersConfigured = hasGroupSenderEntries(account);
45274
45941
  if (groupPolicy === "allowlist" && !groupRulesConfigured && !groupSendersConfigured) {
@@ -45279,14 +45946,12 @@ var inlineSecurityAdapter = {
45279
45946
  if (groupPolicy !== "open") {
45280
45947
  return [];
45281
45948
  }
45282
- if (groupRulesConfigured) {
45949
+ if (!groupDefaultRequiresMention(account)) {
45283
45950
  return [
45284
- '- Inline groups: groupPolicy="open" allows any group message to reach the agent (subject to mention policy). Set channels.inline.groupPolicy="allowlist" for stricter routing.'
45951
+ '- Inline groups: groupPolicy="open" allows every group message to trigger replies because requireMention is disabled. Set channels.inline.requireMention=true or channels.inline.groups."*".requireMention=true.'
45285
45952
  ];
45286
45953
  }
45287
- return [
45288
- '- Inline groups: groupPolicy="open" with no group rules means every group can trigger replies. Consider channels.inline.groupPolicy="allowlist".'
45289
- ];
45954
+ return [];
45290
45955
  },
45291
45956
  collectAuditFindings: ({ account, cfg }) => {
45292
45957
  const findings = [];
@@ -45311,7 +45976,7 @@ var inlineSecurityAdapter = {
45311
45976
  });
45312
45977
  appendInvalidReactionAllowlistFinding(findings, invalidReactionAllowlistEntries);
45313
45978
  const defaultGroupPolicy = cfg.channels?.defaults?.groupPolicy;
45314
- const groupPolicy = account.config.groupPolicy ?? defaultGroupPolicy ?? "allowlist";
45979
+ const groupPolicy = account.config.groupPolicy ?? defaultGroupPolicy ?? INLINE_DEFAULT_GROUP_POLICY;
45315
45980
  const groupsConfigured = Boolean(account.config.groups) && Object.keys(account.config.groups ?? {}).length > 0;
45316
45981
  const groupSendersConfigured = hasGroupSenderEntries(account);
45317
45982
  const groupAccessEnabled = groupPolicy === "open" || groupPolicy === "allowlist" && (groupsConfigured || groupSendersConfigured);
@@ -46644,7 +47309,7 @@ var inlineChannelPlugin = {
46644
47309
  cfg,
46645
47310
  groupId,
46646
47311
  accountId,
46647
- requireMentionDefault: resolved.config.requireMention ?? false
47312
+ requireMentionDefault: resolved.config.requireMention ?? INLINE_DEFAULT_REQUIRE_MENTION
46648
47313
  });
46649
47314
  },
46650
47315
  resolveToolPolicy: ({ cfg, accountId, groupId, senderId, senderName, senderUsername, senderE164 }) => resolveInlineGroupToolPolicy({
@@ -46705,7 +47370,7 @@ var inlineChannelPlugin = {
46705
47370
  "- Inline reply threads: use `thread-create` to create or reuse a real reply thread under the current/target chat. On parent-chat inbound turns, omit `messageId` to anchor it to the current message, or pass `messageId`/`parentMessageId` explicitly.",
46706
47371
  "- Inline reply threads: use `thread-reply` to send into a real reply thread, with `threadId` set to the reply-thread chat id returned by `thread-create`. Reuse that `threadId` only for the same reply-thread session; unrelated parent-chat messages need separate parent-message anchors.",
46707
47372
  "- Inline reply threads: when already inside a reply-thread chat, continue in that reply thread and do not create nested reply threads.",
46708
- "- Inline reply-thread turns include nearby parent-chat context by default. If that context is incomplete, call `inline_parent_context` before answering."
47373
+ "- Inline reply-thread turns include nearby parent-chat context as background only; answer the current reply-thread conversation, not unrelated parent-chat or other-thread questions."
46709
47374
  ]
46710
47375
  },
46711
47376
  messaging: {
@@ -47068,5 +47733,5 @@ export {
47068
47733
  inlineChannelPlugin
47069
47734
  };
47070
47735
 
47071
- //# debugId=FEB3F6CD06C6A7CC64756E2164756E21
47736
+ //# debugId=93A450B5B900350964756E2164756E21
47072
47737
  //# sourceMappingURL=channel-plugin-api.js.map