@inline-openclaw/inline 0.0.67 → 0.0.69

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.
@@ -5585,6 +5585,7 @@ function hasInlineConfiguredState(params) {
5585
5585
  }
5586
5586
 
5587
5587
  // src/inline/channel.ts
5588
+ import { createHash } from "node:crypto";
5588
5589
  import { unlink } from "node:fs/promises";
5589
5590
  import path4 from "node:path";
5590
5591
  import {
@@ -5593,7 +5594,11 @@ import {
5593
5594
  resolveThreadSessionKeys
5594
5595
  } from "openclaw/plugin-sdk/core";
5595
5596
  import { parseAgentSessionKey, parseThreadSessionSuffix } from "openclaw/plugin-sdk/routing";
5596
- import { createChannelMessageAdapterFromOutbound } from "openclaw/plugin-sdk/channel-outbound";
5597
+ import {
5598
+ createChannelMessageAdapterFromOutbound,
5599
+ createMessageReceiptFromOutboundResults
5600
+ } from "openclaw/plugin-sdk/channel-outbound";
5601
+ import { PlatformMessageNotDispatchedError } from "openclaw/plugin-sdk/error-runtime";
5597
5602
  import {
5598
5603
  presentationToInteractiveReply,
5599
5604
  renderMessagePresentationFallbackText as renderMessagePresentationFallbackText2
@@ -5863,6 +5868,20 @@ var UploadFailure_Code;
5863
5868
  UploadFailure_Code2[UploadFailure_Code2["UPLOAD_FAILURE_PROCESSING"] = 3] = "UPLOAD_FAILURE_PROCESSING";
5864
5869
  UploadFailure_Code2[UploadFailure_Code2["UPLOAD_FAILURE_STORAGE"] = 4] = "UPLOAD_FAILURE_STORAGE";
5865
5870
  })(UploadFailure_Code || (UploadFailure_Code = {}));
5871
+ var RequestBotFilesystemInput_Operation;
5872
+ (function(RequestBotFilesystemInput_Operation2) {
5873
+ RequestBotFilesystemInput_Operation2[RequestBotFilesystemInput_Operation2["OPERATION_UNSPECIFIED"] = 0] = "OPERATION_UNSPECIFIED";
5874
+ RequestBotFilesystemInput_Operation2[RequestBotFilesystemInput_Operation2["LIST"] = 1] = "LIST";
5875
+ RequestBotFilesystemInput_Operation2[RequestBotFilesystemInput_Operation2["REGISTER_FOLDER"] = 2] = "REGISTER_FOLDER";
5876
+ })(RequestBotFilesystemInput_Operation || (RequestBotFilesystemInput_Operation = {}));
5877
+ var BotFilesystemEntry_Kind;
5878
+ (function(BotFilesystemEntry_Kind2) {
5879
+ BotFilesystemEntry_Kind2[BotFilesystemEntry_Kind2["KIND_UNSPECIFIED"] = 0] = "KIND_UNSPECIFIED";
5880
+ BotFilesystemEntry_Kind2[BotFilesystemEntry_Kind2["FILE"] = 1] = "FILE";
5881
+ BotFilesystemEntry_Kind2[BotFilesystemEntry_Kind2["DIRECTORY"] = 2] = "DIRECTORY";
5882
+ BotFilesystemEntry_Kind2[BotFilesystemEntry_Kind2["SYMLINK"] = 3] = "SYMLINK";
5883
+ BotFilesystemEntry_Kind2[BotFilesystemEntry_Kind2["OTHER"] = 4] = "OTHER";
5884
+ })(BotFilesystemEntry_Kind || (BotFilesystemEntry_Kind = {}));
5866
5885
  var DialogFollowMode;
5867
5886
  (function(DialogFollowMode2) {
5868
5887
  DialogFollowMode2[DialogFollowMode2["DIALOG_FOLLOW_MODE_UNSPECIFIED"] = 0] = "DIALOG_FOLLOW_MODE_UNSPECIFIED";
@@ -6061,6 +6080,10 @@ var Method;
6061
6080
  Method2[Method2["GET_USERS"] = 138] = "GET_USERS";
6062
6081
  Method2[Method2["GET_BOT_SKILLS"] = 139] = "GET_BOT_SKILLS";
6063
6082
  Method2[Method2["GET_BOT_CONFIGURATION_CATALOG"] = 140] = "GET_BOT_CONFIGURATION_CATALOG";
6083
+ Method2[Method2["UPDATE_DIALOG_TRANSLATION"] = 141] = "UPDATE_DIALOG_TRANSLATION";
6084
+ Method2[Method2["TRANSCRIBE_VOICE_DRAFT"] = 142] = "TRANSCRIBE_VOICE_DRAFT";
6085
+ Method2[Method2["REQUEST_BOT_FILESYSTEM"] = 143] = "REQUEST_BOT_FILESYSTEM";
6086
+ Method2[Method2["ANSWER_BOT_FILESYSTEM"] = 144] = "ANSWER_BOT_FILESYSTEM";
6064
6087
  })(Method || (Method = {}));
6065
6088
  var GridConnectionUnavailableReason;
6066
6089
  (function(GridConnectionUnavailableReason2) {
@@ -6529,7 +6552,8 @@ class BotEvent$Type extends import_runtime4.MessageType {
6529
6552
  constructor() {
6530
6553
  super("BotEvent", [
6531
6554
  { no: 1, name: "chat_settings_requested", kind: "message", oneof: "event", T: () => BotChatSettingsRequested },
6532
- { no: 2, name: "chat_settings_item_invoked", kind: "message", oneof: "event", T: () => BotChatSettingsItemInvoked }
6555
+ { no: 2, name: "chat_settings_item_invoked", kind: "message", oneof: "event", T: () => BotChatSettingsItemInvoked },
6556
+ { no: 3, name: "filesystem_requested", kind: "message", oneof: "event", T: () => BotFilesystemRequested }
6533
6557
  ]);
6534
6558
  }
6535
6559
  create(value) {
@@ -6556,6 +6580,12 @@ class BotEvent$Type extends import_runtime4.MessageType {
6556
6580
  chatSettingsItemInvoked: BotChatSettingsItemInvoked.internalBinaryRead(reader, reader.uint32(), options, message.event.chatSettingsItemInvoked)
6557
6581
  };
6558
6582
  break;
6583
+ case 3:
6584
+ message.event = {
6585
+ oneofKind: "filesystemRequested",
6586
+ filesystemRequested: BotFilesystemRequested.internalBinaryRead(reader, reader.uint32(), options, message.event.filesystemRequested)
6587
+ };
6588
+ break;
6559
6589
  default:
6560
6590
  let u = options.readUnknownField;
6561
6591
  if (u === "throw")
@@ -6572,6 +6602,8 @@ class BotEvent$Type extends import_runtime4.MessageType {
6572
6602
  BotChatSettingsRequested.internalBinaryWrite(message.event.chatSettingsRequested, writer.tag(1, import_runtime.WireType.LengthDelimited).fork(), options).join();
6573
6603
  if (message.event.oneofKind === "chatSettingsItemInvoked")
6574
6604
  BotChatSettingsItemInvoked.internalBinaryWrite(message.event.chatSettingsItemInvoked, writer.tag(2, import_runtime.WireType.LengthDelimited).fork(), options).join();
6605
+ if (message.event.oneofKind === "filesystemRequested")
6606
+ BotFilesystemRequested.internalBinaryWrite(message.event.filesystemRequested, writer.tag(3, import_runtime.WireType.LengthDelimited).fork(), options).join();
6575
6607
  let u = options.writeUnknownFields;
6576
6608
  if (u !== false)
6577
6609
  (u == true ? import_runtime2.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
@@ -7728,7 +7760,8 @@ class Dialog$Type extends import_runtime4.MessageType {
7728
7760
  { no: 15, name: "pinned_order", kind: "scalar", opt: true, T: 9 },
7729
7761
  { no: 16, name: "follow_mode", kind: "enum", opt: true, T: () => ["DialogFollowMode", DialogFollowMode] },
7730
7762
  { no: 17, name: "collapsed_max_id", kind: "scalar", opt: true, T: 3, L: 0 },
7731
- { no: 18, name: "folder_id", kind: "scalar", opt: true, T: 3, L: 0 }
7763
+ { no: 18, name: "folder_id", kind: "scalar", opt: true, T: 3, L: 0 },
7764
+ { no: 19, name: "translation_enabled", kind: "scalar", opt: true, T: 8 }
7732
7765
  ]);
7733
7766
  }
7734
7767
  create(value) {
@@ -7796,6 +7829,9 @@ class Dialog$Type extends import_runtime4.MessageType {
7796
7829
  case 18:
7797
7830
  message.folderId = reader.int64().toBigInt();
7798
7831
  break;
7832
+ case 19:
7833
+ message.translationEnabled = reader.bool();
7834
+ break;
7799
7835
  default:
7800
7836
  let u = options.readUnknownField;
7801
7837
  if (u === "throw")
@@ -7844,6 +7880,8 @@ class Dialog$Type extends import_runtime4.MessageType {
7844
7880
  writer.tag(17, import_runtime.WireType.Varint).int64(message.collapsedMaxId);
7845
7881
  if (message.folderId !== undefined)
7846
7882
  writer.tag(18, import_runtime.WireType.Varint).int64(message.folderId);
7883
+ if (message.translationEnabled !== undefined)
7884
+ writer.tag(19, import_runtime.WireType.Varint).bool(message.translationEnabled);
7847
7885
  let u = options.writeUnknownFields;
7848
7886
  if (u !== false)
7849
7887
  (u == true ? import_runtime2.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
@@ -13976,7 +14014,11 @@ class RpcCall$Type extends import_runtime4.MessageType {
13976
14014
  { no: 138, name: "acknowledgeMessages", kind: "message", oneof: "input", T: () => AcknowledgeMessagesInput },
13977
14015
  { no: 139, name: "getUsers", kind: "message", oneof: "input", T: () => GetUsersInput },
13978
14016
  { no: 140, name: "getBotSkills", kind: "message", oneof: "input", T: () => GetBotSkillsInput },
13979
- { no: 141, name: "getBotConfigurationCatalog", kind: "message", oneof: "input", T: () => GetBotConfigurationCatalogInput }
14017
+ { no: 141, name: "getBotConfigurationCatalog", kind: "message", oneof: "input", T: () => GetBotConfigurationCatalogInput },
14018
+ { no: 142, name: "updateDialogTranslation", kind: "message", oneof: "input", T: () => UpdateDialogTranslationInput },
14019
+ { no: 143, name: "transcribeVoiceDraft", kind: "message", oneof: "input", T: () => TranscribeVoiceDraftInput },
14020
+ { no: 144, name: "requestBotFilesystem", kind: "message", oneof: "input", T: () => RequestBotFilesystemInput },
14021
+ { no: 145, name: "answerBotFilesystem", kind: "message", oneof: "input", T: () => AnswerBotFilesystemInput }
13980
14022
  ]);
13981
14023
  }
13982
14024
  create(value) {
@@ -14829,6 +14871,30 @@ class RpcCall$Type extends import_runtime4.MessageType {
14829
14871
  getBotConfigurationCatalog: GetBotConfigurationCatalogInput.internalBinaryRead(reader, reader.uint32(), options, message.input.getBotConfigurationCatalog)
14830
14872
  };
14831
14873
  break;
14874
+ case 142:
14875
+ message.input = {
14876
+ oneofKind: "updateDialogTranslation",
14877
+ updateDialogTranslation: UpdateDialogTranslationInput.internalBinaryRead(reader, reader.uint32(), options, message.input.updateDialogTranslation)
14878
+ };
14879
+ break;
14880
+ case 143:
14881
+ message.input = {
14882
+ oneofKind: "transcribeVoiceDraft",
14883
+ transcribeVoiceDraft: TranscribeVoiceDraftInput.internalBinaryRead(reader, reader.uint32(), options, message.input.transcribeVoiceDraft)
14884
+ };
14885
+ break;
14886
+ case 144:
14887
+ message.input = {
14888
+ oneofKind: "requestBotFilesystem",
14889
+ requestBotFilesystem: RequestBotFilesystemInput.internalBinaryRead(reader, reader.uint32(), options, message.input.requestBotFilesystem)
14890
+ };
14891
+ break;
14892
+ case 145:
14893
+ message.input = {
14894
+ oneofKind: "answerBotFilesystem",
14895
+ answerBotFilesystem: AnswerBotFilesystemInput.internalBinaryRead(reader, reader.uint32(), options, message.input.answerBotFilesystem)
14896
+ };
14897
+ break;
14832
14898
  default:
14833
14899
  let u = options.readUnknownField;
14834
14900
  if (u === "throw")
@@ -15121,6 +15187,14 @@ class RpcCall$Type extends import_runtime4.MessageType {
15121
15187
  GetBotSkillsInput.internalBinaryWrite(message.input.getBotSkills, writer.tag(140, import_runtime.WireType.LengthDelimited).fork(), options).join();
15122
15188
  if (message.input.oneofKind === "getBotConfigurationCatalog")
15123
15189
  GetBotConfigurationCatalogInput.internalBinaryWrite(message.input.getBotConfigurationCatalog, writer.tag(141, import_runtime.WireType.LengthDelimited).fork(), options).join();
15190
+ if (message.input.oneofKind === "updateDialogTranslation")
15191
+ UpdateDialogTranslationInput.internalBinaryWrite(message.input.updateDialogTranslation, writer.tag(142, import_runtime.WireType.LengthDelimited).fork(), options).join();
15192
+ if (message.input.oneofKind === "transcribeVoiceDraft")
15193
+ TranscribeVoiceDraftInput.internalBinaryWrite(message.input.transcribeVoiceDraft, writer.tag(143, import_runtime.WireType.LengthDelimited).fork(), options).join();
15194
+ if (message.input.oneofKind === "requestBotFilesystem")
15195
+ RequestBotFilesystemInput.internalBinaryWrite(message.input.requestBotFilesystem, writer.tag(144, import_runtime.WireType.LengthDelimited).fork(), options).join();
15196
+ if (message.input.oneofKind === "answerBotFilesystem")
15197
+ AnswerBotFilesystemInput.internalBinaryWrite(message.input.answerBotFilesystem, writer.tag(145, import_runtime.WireType.LengthDelimited).fork(), options).join();
15124
15198
  let u = options.writeUnknownFields;
15125
15199
  if (u !== false)
15126
15200
  (u == true ? import_runtime2.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
@@ -15271,7 +15345,11 @@ class RpcResult$Type extends import_runtime4.MessageType {
15271
15345
  { no: 138, name: "acknowledgeMessages", kind: "message", oneof: "result", T: () => AcknowledgeMessagesResult },
15272
15346
  { no: 139, name: "getUsers", kind: "message", oneof: "result", T: () => GetUsersResult },
15273
15347
  { no: 140, name: "getBotSkills", kind: "message", oneof: "result", T: () => GetBotSkillsResult },
15274
- { no: 141, name: "getBotConfigurationCatalog", kind: "message", oneof: "result", T: () => GetBotConfigurationCatalogResult }
15348
+ { no: 141, name: "getBotConfigurationCatalog", kind: "message", oneof: "result", T: () => GetBotConfigurationCatalogResult },
15349
+ { no: 142, name: "updateDialogTranslation", kind: "message", oneof: "result", T: () => UpdateDialogTranslationResult },
15350
+ { no: 143, name: "transcribeVoiceDraft", kind: "message", oneof: "result", T: () => TranscribeVoiceDraftResult },
15351
+ { no: 144, name: "requestBotFilesystem", kind: "message", oneof: "result", T: () => RequestBotFilesystemResult },
15352
+ { no: 145, name: "answerBotFilesystem", kind: "message", oneof: "result", T: () => AnswerBotFilesystemResult }
15275
15353
  ]);
15276
15354
  }
15277
15355
  create(value) {
@@ -16124,6 +16202,30 @@ class RpcResult$Type extends import_runtime4.MessageType {
16124
16202
  getBotConfigurationCatalog: GetBotConfigurationCatalogResult.internalBinaryRead(reader, reader.uint32(), options, message.result.getBotConfigurationCatalog)
16125
16203
  };
16126
16204
  break;
16205
+ case 142:
16206
+ message.result = {
16207
+ oneofKind: "updateDialogTranslation",
16208
+ updateDialogTranslation: UpdateDialogTranslationResult.internalBinaryRead(reader, reader.uint32(), options, message.result.updateDialogTranslation)
16209
+ };
16210
+ break;
16211
+ case 143:
16212
+ message.result = {
16213
+ oneofKind: "transcribeVoiceDraft",
16214
+ transcribeVoiceDraft: TranscribeVoiceDraftResult.internalBinaryRead(reader, reader.uint32(), options, message.result.transcribeVoiceDraft)
16215
+ };
16216
+ break;
16217
+ case 144:
16218
+ message.result = {
16219
+ oneofKind: "requestBotFilesystem",
16220
+ requestBotFilesystem: RequestBotFilesystemResult.internalBinaryRead(reader, reader.uint32(), options, message.result.requestBotFilesystem)
16221
+ };
16222
+ break;
16223
+ case 145:
16224
+ message.result = {
16225
+ oneofKind: "answerBotFilesystem",
16226
+ answerBotFilesystem: AnswerBotFilesystemResult.internalBinaryRead(reader, reader.uint32(), options, message.result.answerBotFilesystem)
16227
+ };
16228
+ break;
16127
16229
  default:
16128
16230
  let u = options.readUnknownField;
16129
16231
  if (u === "throw")
@@ -16416,6 +16518,14 @@ class RpcResult$Type extends import_runtime4.MessageType {
16416
16518
  GetBotSkillsResult.internalBinaryWrite(message.result.getBotSkills, writer.tag(140, import_runtime.WireType.LengthDelimited).fork(), options).join();
16417
16519
  if (message.result.oneofKind === "getBotConfigurationCatalog")
16418
16520
  GetBotConfigurationCatalogResult.internalBinaryWrite(message.result.getBotConfigurationCatalog, writer.tag(141, import_runtime.WireType.LengthDelimited).fork(), options).join();
16521
+ if (message.result.oneofKind === "updateDialogTranslation")
16522
+ UpdateDialogTranslationResult.internalBinaryWrite(message.result.updateDialogTranslation, writer.tag(142, import_runtime.WireType.LengthDelimited).fork(), options).join();
16523
+ if (message.result.oneofKind === "transcribeVoiceDraft")
16524
+ TranscribeVoiceDraftResult.internalBinaryWrite(message.result.transcribeVoiceDraft, writer.tag(143, import_runtime.WireType.LengthDelimited).fork(), options).join();
16525
+ if (message.result.oneofKind === "requestBotFilesystem")
16526
+ RequestBotFilesystemResult.internalBinaryWrite(message.result.requestBotFilesystem, writer.tag(144, import_runtime.WireType.LengthDelimited).fork(), options).join();
16527
+ if (message.result.oneofKind === "answerBotFilesystem")
16528
+ AnswerBotFilesystemResult.internalBinaryWrite(message.result.answerBotFilesystem, writer.tag(145, import_runtime.WireType.LengthDelimited).fork(), options).join();
16419
16529
  let u = options.writeUnknownFields;
16420
16530
  if (u !== false)
16421
16531
  (u == true ? import_runtime2.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
@@ -19980,6 +20090,153 @@ class UpdateDialogFollowModeResult$Type extends import_runtime4.MessageType {
19980
20090
  }
19981
20091
  var UpdateDialogFollowModeResult = new UpdateDialogFollowModeResult$Type;
19982
20092
 
20093
+ class UpdateDialogTranslationInput$Type extends import_runtime4.MessageType {
20094
+ constructor() {
20095
+ super("UpdateDialogTranslationInput", [
20096
+ { no: 1, name: "peer_id", kind: "message", T: () => InputPeer },
20097
+ { no: 2, name: "enabled", kind: "scalar", opt: true, T: 8 },
20098
+ { no: 3, name: "import_legacy_enabled", kind: "scalar", T: 8 }
20099
+ ]);
20100
+ }
20101
+ create(value) {
20102
+ const message = globalThis.Object.create(this.messagePrototype);
20103
+ message.importLegacyEnabled = false;
20104
+ if (value !== undefined)
20105
+ import_runtime3.reflectionMergePartial(this, message, value);
20106
+ return message;
20107
+ }
20108
+ internalBinaryRead(reader, length, options, target) {
20109
+ let message = target ?? this.create(), end = reader.pos + length;
20110
+ while (reader.pos < end) {
20111
+ let [fieldNo, wireType] = reader.tag();
20112
+ switch (fieldNo) {
20113
+ case 1:
20114
+ message.peerId = InputPeer.internalBinaryRead(reader, reader.uint32(), options, message.peerId);
20115
+ break;
20116
+ case 2:
20117
+ message.enabled = reader.bool();
20118
+ break;
20119
+ case 3:
20120
+ message.importLegacyEnabled = reader.bool();
20121
+ break;
20122
+ default:
20123
+ let u = options.readUnknownField;
20124
+ if (u === "throw")
20125
+ throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
20126
+ let d = reader.skip(wireType);
20127
+ if (u !== false)
20128
+ (u === true ? import_runtime2.UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
20129
+ }
20130
+ }
20131
+ return message;
20132
+ }
20133
+ internalBinaryWrite(message, writer, options) {
20134
+ if (message.peerId)
20135
+ InputPeer.internalBinaryWrite(message.peerId, writer.tag(1, import_runtime.WireType.LengthDelimited).fork(), options).join();
20136
+ if (message.enabled !== undefined)
20137
+ writer.tag(2, import_runtime.WireType.Varint).bool(message.enabled);
20138
+ if (message.importLegacyEnabled !== false)
20139
+ writer.tag(3, import_runtime.WireType.Varint).bool(message.importLegacyEnabled);
20140
+ let u = options.writeUnknownFields;
20141
+ if (u !== false)
20142
+ (u == true ? import_runtime2.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
20143
+ return writer;
20144
+ }
20145
+ }
20146
+ var UpdateDialogTranslationInput = new UpdateDialogTranslationInput$Type;
20147
+
20148
+ class UpdateDialogTranslationResult$Type extends import_runtime4.MessageType {
20149
+ constructor() {
20150
+ super("UpdateDialogTranslationResult", [
20151
+ { no: 1, name: "updates", kind: "message", repeat: 1, T: () => Update }
20152
+ ]);
20153
+ }
20154
+ create(value) {
20155
+ const message = globalThis.Object.create(this.messagePrototype);
20156
+ message.updates = [];
20157
+ if (value !== undefined)
20158
+ import_runtime3.reflectionMergePartial(this, message, value);
20159
+ return message;
20160
+ }
20161
+ internalBinaryRead(reader, length, options, target) {
20162
+ let message = target ?? this.create(), end = reader.pos + length;
20163
+ while (reader.pos < end) {
20164
+ let [fieldNo, wireType] = reader.tag();
20165
+ switch (fieldNo) {
20166
+ case 1:
20167
+ message.updates.push(Update.internalBinaryRead(reader, reader.uint32(), options));
20168
+ break;
20169
+ default:
20170
+ let u = options.readUnknownField;
20171
+ if (u === "throw")
20172
+ throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
20173
+ let d = reader.skip(wireType);
20174
+ if (u !== false)
20175
+ (u === true ? import_runtime2.UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
20176
+ }
20177
+ }
20178
+ return message;
20179
+ }
20180
+ internalBinaryWrite(message, writer, options) {
20181
+ for (let i = 0;i < message.updates.length; i++)
20182
+ Update.internalBinaryWrite(message.updates[i], writer.tag(1, import_runtime.WireType.LengthDelimited).fork(), options).join();
20183
+ let u = options.writeUnknownFields;
20184
+ if (u !== false)
20185
+ (u == true ? import_runtime2.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
20186
+ return writer;
20187
+ }
20188
+ }
20189
+ var UpdateDialogTranslationResult = new UpdateDialogTranslationResult$Type;
20190
+
20191
+ class UpdateDialogTranslation$Type extends import_runtime4.MessageType {
20192
+ constructor() {
20193
+ super("UpdateDialogTranslation", [
20194
+ { no: 1, name: "peer_id", kind: "message", T: () => Peer },
20195
+ { no: 2, name: "enabled", kind: "scalar", T: 8 }
20196
+ ]);
20197
+ }
20198
+ create(value) {
20199
+ const message = globalThis.Object.create(this.messagePrototype);
20200
+ message.enabled = false;
20201
+ if (value !== undefined)
20202
+ import_runtime3.reflectionMergePartial(this, message, value);
20203
+ return message;
20204
+ }
20205
+ internalBinaryRead(reader, length, options, target) {
20206
+ let message = target ?? this.create(), end = reader.pos + length;
20207
+ while (reader.pos < end) {
20208
+ let [fieldNo, wireType] = reader.tag();
20209
+ switch (fieldNo) {
20210
+ case 1:
20211
+ message.peerId = Peer.internalBinaryRead(reader, reader.uint32(), options, message.peerId);
20212
+ break;
20213
+ case 2:
20214
+ message.enabled = reader.bool();
20215
+ break;
20216
+ default:
20217
+ let u = options.readUnknownField;
20218
+ if (u === "throw")
20219
+ throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
20220
+ let d = reader.skip(wireType);
20221
+ if (u !== false)
20222
+ (u === true ? import_runtime2.UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
20223
+ }
20224
+ }
20225
+ return message;
20226
+ }
20227
+ internalBinaryWrite(message, writer, options) {
20228
+ if (message.peerId)
20229
+ Peer.internalBinaryWrite(message.peerId, writer.tag(1, import_runtime.WireType.LengthDelimited).fork(), options).join();
20230
+ if (message.enabled !== false)
20231
+ writer.tag(2, import_runtime.WireType.Varint).bool(message.enabled);
20232
+ let u = options.writeUnknownFields;
20233
+ if (u !== false)
20234
+ (u == true ? import_runtime2.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
20235
+ return writer;
20236
+ }
20237
+ }
20238
+ var UpdateDialogTranslation = new UpdateDialogTranslation$Type;
20239
+
19983
20240
  class CollapseHistoryInput$Type extends import_runtime4.MessageType {
19984
20241
  constructor() {
19985
20242
  super("CollapseHistoryInput", [
@@ -29506,7 +29763,8 @@ class Update$Type extends import_runtime4.MessageType {
29506
29763
  { no: 46, name: "dialog_folder", kind: "message", oneof: "update", T: () => UpdateDialogFolder },
29507
29764
  { no: 47, name: "user_added_to_chat", kind: "message", oneof: "update", T: () => UpdateUserAddedToChat },
29508
29765
  { no: 48, name: "user_removed_from_chat", kind: "message", oneof: "update", T: () => UpdateUserRemovedFromChat },
29509
- { no: 49, name: "acknowledgement", kind: "message", oneof: "update", T: () => ChatAcknowledgement }
29766
+ { no: 49, name: "acknowledgement", kind: "message", oneof: "update", T: () => ChatAcknowledgement },
29767
+ { no: 50, name: "dialog_translation", kind: "message", oneof: "update", T: () => UpdateDialogTranslation }
29510
29768
  ]);
29511
29769
  }
29512
29770
  create(value) {
@@ -29803,6 +30061,12 @@ class Update$Type extends import_runtime4.MessageType {
29803
30061
  acknowledgement: ChatAcknowledgement.internalBinaryRead(reader, reader.uint32(), options, message.update.acknowledgement)
29804
30062
  };
29805
30063
  break;
30064
+ case 50:
30065
+ message.update = {
30066
+ oneofKind: "dialogTranslation",
30067
+ dialogTranslation: UpdateDialogTranslation.internalBinaryRead(reader, reader.uint32(), options, message.update.dialogTranslation)
30068
+ };
30069
+ break;
29806
30070
  default:
29807
30071
  let u = options.readUnknownField;
29808
30072
  if (u === "throw")
@@ -29911,6 +30175,8 @@ class Update$Type extends import_runtime4.MessageType {
29911
30175
  UpdateUserRemovedFromChat.internalBinaryWrite(message.update.userRemovedFromChat, writer.tag(48, import_runtime.WireType.LengthDelimited).fork(), options).join();
29912
30176
  if (message.update.oneofKind === "acknowledgement")
29913
30177
  ChatAcknowledgement.internalBinaryWrite(message.update.acknowledgement, writer.tag(49, import_runtime.WireType.LengthDelimited).fork(), options).join();
30178
+ if (message.update.oneofKind === "dialogTranslation")
30179
+ UpdateDialogTranslation.internalBinaryWrite(message.update.dialogTranslation, writer.tag(50, import_runtime.WireType.LengthDelimited).fork(), options).join();
29914
30180
  let u = options.writeUnknownFields;
29915
30181
  if (u !== false)
29916
30182
  (u == true ? import_runtime2.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
@@ -35056,7 +35322,8 @@ class BotChatSettingsFolder$Type extends import_runtime4.MessageType {
35056
35322
  { no: 4, name: "host_label", kind: "scalar", T: 9 },
35057
35323
  { no: 5, name: "allows_local_picker", kind: "scalar", T: 8 },
35058
35324
  { no: 6, name: "local_picker_port", kind: "scalar", opt: true, T: 13 },
35059
- { no: 7, name: "local_picker_capability", kind: "scalar", opt: true, T: 9 }
35325
+ { no: 7, name: "local_picker_capability", kind: "scalar", opt: true, T: 9 },
35326
+ { no: 8, name: "remote_browser_version", kind: "scalar", opt: true, T: 13 }
35060
35327
  ]);
35061
35328
  }
35062
35329
  create(value) {
@@ -35096,6 +35363,9 @@ class BotChatSettingsFolder$Type extends import_runtime4.MessageType {
35096
35363
  case 7:
35097
35364
  message.localPickerCapability = reader.string();
35098
35365
  break;
35366
+ case 8:
35367
+ message.remoteBrowserVersion = reader.uint32();
35368
+ break;
35099
35369
  default:
35100
35370
  let u = options.readUnknownField;
35101
35371
  if (u === "throw")
@@ -35122,6 +35392,8 @@ class BotChatSettingsFolder$Type extends import_runtime4.MessageType {
35122
35392
  writer.tag(6, import_runtime.WireType.Varint).uint32(message.localPickerPort);
35123
35393
  if (message.localPickerCapability !== undefined)
35124
35394
  writer.tag(7, import_runtime.WireType.LengthDelimited).string(message.localPickerCapability);
35395
+ if (message.remoteBrowserVersion !== undefined)
35396
+ writer.tag(8, import_runtime.WireType.Varint).uint32(message.remoteBrowserVersion);
35125
35397
  let u = options.writeUnknownFields;
35126
35398
  if (u !== false)
35127
35399
  (u == true ? import_runtime2.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
@@ -38366,6 +38638,542 @@ class ChatAcknowledgements$Type extends import_runtime4.MessageType {
38366
38638
  }
38367
38639
  var ChatAcknowledgements = new ChatAcknowledgements$Type;
38368
38640
 
38641
+ class TranscribeVoiceDraftInput$Type extends import_runtime4.MessageType {
38642
+ constructor() {
38643
+ super("TranscribeVoiceDraftInput", [
38644
+ { no: 1, name: "audio", kind: "scalar", T: 12 },
38645
+ { no: 2, name: "mime_type", kind: "scalar", T: 9 },
38646
+ { no: 3, name: "duration", kind: "scalar", T: 13 }
38647
+ ]);
38648
+ }
38649
+ create(value) {
38650
+ const message = globalThis.Object.create(this.messagePrototype);
38651
+ message.audio = new Uint8Array(0);
38652
+ message.mimeType = "";
38653
+ message.duration = 0;
38654
+ if (value !== undefined)
38655
+ import_runtime3.reflectionMergePartial(this, message, value);
38656
+ return message;
38657
+ }
38658
+ internalBinaryRead(reader, length, options, target) {
38659
+ let message = target ?? this.create(), end = reader.pos + length;
38660
+ while (reader.pos < end) {
38661
+ let [fieldNo, wireType] = reader.tag();
38662
+ switch (fieldNo) {
38663
+ case 1:
38664
+ message.audio = reader.bytes();
38665
+ break;
38666
+ case 2:
38667
+ message.mimeType = reader.string();
38668
+ break;
38669
+ case 3:
38670
+ message.duration = reader.uint32();
38671
+ break;
38672
+ default:
38673
+ let u = options.readUnknownField;
38674
+ if (u === "throw")
38675
+ throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
38676
+ let d = reader.skip(wireType);
38677
+ if (u !== false)
38678
+ (u === true ? import_runtime2.UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
38679
+ }
38680
+ }
38681
+ return message;
38682
+ }
38683
+ internalBinaryWrite(message, writer, options) {
38684
+ if (message.audio.length)
38685
+ writer.tag(1, import_runtime.WireType.LengthDelimited).bytes(message.audio);
38686
+ if (message.mimeType !== "")
38687
+ writer.tag(2, import_runtime.WireType.LengthDelimited).string(message.mimeType);
38688
+ if (message.duration !== 0)
38689
+ writer.tag(3, import_runtime.WireType.Varint).uint32(message.duration);
38690
+ let u = options.writeUnknownFields;
38691
+ if (u !== false)
38692
+ (u == true ? import_runtime2.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
38693
+ return writer;
38694
+ }
38695
+ }
38696
+ var TranscribeVoiceDraftInput = new TranscribeVoiceDraftInput$Type;
38697
+
38698
+ class TranscribeVoiceDraftResult$Type extends import_runtime4.MessageType {
38699
+ constructor() {
38700
+ super("TranscribeVoiceDraftResult", [
38701
+ { no: 1, name: "text", kind: "scalar", T: 9 }
38702
+ ]);
38703
+ }
38704
+ create(value) {
38705
+ const message = globalThis.Object.create(this.messagePrototype);
38706
+ message.text = "";
38707
+ if (value !== undefined)
38708
+ import_runtime3.reflectionMergePartial(this, message, value);
38709
+ return message;
38710
+ }
38711
+ internalBinaryRead(reader, length, options, target) {
38712
+ let message = target ?? this.create(), end = reader.pos + length;
38713
+ while (reader.pos < end) {
38714
+ let [fieldNo, wireType] = reader.tag();
38715
+ switch (fieldNo) {
38716
+ case 1:
38717
+ message.text = reader.string();
38718
+ break;
38719
+ default:
38720
+ let u = options.readUnknownField;
38721
+ if (u === "throw")
38722
+ throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
38723
+ let d = reader.skip(wireType);
38724
+ if (u !== false)
38725
+ (u === true ? import_runtime2.UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
38726
+ }
38727
+ }
38728
+ return message;
38729
+ }
38730
+ internalBinaryWrite(message, writer, options) {
38731
+ if (message.text !== "")
38732
+ writer.tag(1, import_runtime.WireType.LengthDelimited).string(message.text);
38733
+ let u = options.writeUnknownFields;
38734
+ if (u !== false)
38735
+ (u == true ? import_runtime2.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
38736
+ return writer;
38737
+ }
38738
+ }
38739
+ var TranscribeVoiceDraftResult = new TranscribeVoiceDraftResult$Type;
38740
+
38741
+ class RequestBotFilesystemInput$Type extends import_runtime4.MessageType {
38742
+ constructor() {
38743
+ super("RequestBotFilesystemInput", [
38744
+ { no: 1, name: "peer_id", kind: "message", T: () => InputPeer },
38745
+ { no: 2, name: "bot_user_id", kind: "scalar", T: 3, L: 0 },
38746
+ { no: 3, name: "host_installation_id", kind: "scalar", T: 9 },
38747
+ { no: 4, name: "operation", kind: "enum", T: () => ["RequestBotFilesystemInput.Operation", RequestBotFilesystemInput_Operation] },
38748
+ { no: 5, name: "path", kind: "scalar", T: 9 },
38749
+ { no: 6, name: "after", kind: "scalar", T: 9 }
38750
+ ]);
38751
+ }
38752
+ create(value) {
38753
+ const message = globalThis.Object.create(this.messagePrototype);
38754
+ message.botUserId = 0n;
38755
+ message.hostInstallationId = "";
38756
+ message.operation = 0;
38757
+ message.path = "";
38758
+ message.after = "";
38759
+ if (value !== undefined)
38760
+ import_runtime3.reflectionMergePartial(this, message, value);
38761
+ return message;
38762
+ }
38763
+ internalBinaryRead(reader, length, options, target) {
38764
+ let message = target ?? this.create(), end = reader.pos + length;
38765
+ while (reader.pos < end) {
38766
+ let [fieldNo, wireType] = reader.tag();
38767
+ switch (fieldNo) {
38768
+ case 1:
38769
+ message.peerId = InputPeer.internalBinaryRead(reader, reader.uint32(), options, message.peerId);
38770
+ break;
38771
+ case 2:
38772
+ message.botUserId = reader.int64().toBigInt();
38773
+ break;
38774
+ case 3:
38775
+ message.hostInstallationId = reader.string();
38776
+ break;
38777
+ case 4:
38778
+ message.operation = reader.int32();
38779
+ break;
38780
+ case 5:
38781
+ message.path = reader.string();
38782
+ break;
38783
+ case 6:
38784
+ message.after = reader.string();
38785
+ break;
38786
+ default:
38787
+ let u = options.readUnknownField;
38788
+ if (u === "throw")
38789
+ throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
38790
+ let d = reader.skip(wireType);
38791
+ if (u !== false)
38792
+ (u === true ? import_runtime2.UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
38793
+ }
38794
+ }
38795
+ return message;
38796
+ }
38797
+ internalBinaryWrite(message, writer, options) {
38798
+ if (message.peerId)
38799
+ InputPeer.internalBinaryWrite(message.peerId, writer.tag(1, import_runtime.WireType.LengthDelimited).fork(), options).join();
38800
+ if (message.botUserId !== 0n)
38801
+ writer.tag(2, import_runtime.WireType.Varint).int64(message.botUserId);
38802
+ if (message.hostInstallationId !== "")
38803
+ writer.tag(3, import_runtime.WireType.LengthDelimited).string(message.hostInstallationId);
38804
+ if (message.operation !== 0)
38805
+ writer.tag(4, import_runtime.WireType.Varint).int32(message.operation);
38806
+ if (message.path !== "")
38807
+ writer.tag(5, import_runtime.WireType.LengthDelimited).string(message.path);
38808
+ if (message.after !== "")
38809
+ writer.tag(6, import_runtime.WireType.LengthDelimited).string(message.after);
38810
+ let u = options.writeUnknownFields;
38811
+ if (u !== false)
38812
+ (u == true ? import_runtime2.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
38813
+ return writer;
38814
+ }
38815
+ }
38816
+ var RequestBotFilesystemInput = new RequestBotFilesystemInput$Type;
38817
+
38818
+ class BotFilesystemEntry$Type extends import_runtime4.MessageType {
38819
+ constructor() {
38820
+ super("BotFilesystemEntry", [
38821
+ { no: 1, name: "name", kind: "scalar", T: 9 },
38822
+ { no: 2, name: "kind", kind: "enum", T: () => ["BotFilesystemEntry.Kind", BotFilesystemEntry_Kind] },
38823
+ { no: 3, name: "size", kind: "scalar", T: 4, L: 0 }
38824
+ ]);
38825
+ }
38826
+ create(value) {
38827
+ const message = globalThis.Object.create(this.messagePrototype);
38828
+ message.name = "";
38829
+ message.kind = 0;
38830
+ message.size = 0n;
38831
+ if (value !== undefined)
38832
+ import_runtime3.reflectionMergePartial(this, message, value);
38833
+ return message;
38834
+ }
38835
+ internalBinaryRead(reader, length, options, target) {
38836
+ let message = target ?? this.create(), end = reader.pos + length;
38837
+ while (reader.pos < end) {
38838
+ let [fieldNo, wireType] = reader.tag();
38839
+ switch (fieldNo) {
38840
+ case 1:
38841
+ message.name = reader.string();
38842
+ break;
38843
+ case 2:
38844
+ message.kind = reader.int32();
38845
+ break;
38846
+ case 3:
38847
+ message.size = reader.uint64().toBigInt();
38848
+ break;
38849
+ default:
38850
+ let u = options.readUnknownField;
38851
+ if (u === "throw")
38852
+ throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
38853
+ let d = reader.skip(wireType);
38854
+ if (u !== false)
38855
+ (u === true ? import_runtime2.UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
38856
+ }
38857
+ }
38858
+ return message;
38859
+ }
38860
+ internalBinaryWrite(message, writer, options) {
38861
+ if (message.name !== "")
38862
+ writer.tag(1, import_runtime.WireType.LengthDelimited).string(message.name);
38863
+ if (message.kind !== 0)
38864
+ writer.tag(2, import_runtime.WireType.Varint).int32(message.kind);
38865
+ if (message.size !== 0n)
38866
+ writer.tag(3, import_runtime.WireType.Varint).uint64(message.size);
38867
+ let u = options.writeUnknownFields;
38868
+ if (u !== false)
38869
+ (u == true ? import_runtime2.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
38870
+ return writer;
38871
+ }
38872
+ }
38873
+ var BotFilesystemEntry = new BotFilesystemEntry$Type;
38874
+
38875
+ class BotFilesystemListing$Type extends import_runtime4.MessageType {
38876
+ constructor() {
38877
+ super("BotFilesystemListing", [
38878
+ { no: 1, name: "path", kind: "scalar", T: 9 },
38879
+ { no: 2, name: "parent_path", kind: "scalar", opt: true, T: 9 },
38880
+ { no: 3, name: "entries", kind: "message", repeat: 1, T: () => BotFilesystemEntry },
38881
+ { no: 4, name: "next_after", kind: "scalar", opt: true, T: 9 }
38882
+ ]);
38883
+ }
38884
+ create(value) {
38885
+ const message = globalThis.Object.create(this.messagePrototype);
38886
+ message.path = "";
38887
+ message.entries = [];
38888
+ if (value !== undefined)
38889
+ import_runtime3.reflectionMergePartial(this, message, value);
38890
+ return message;
38891
+ }
38892
+ internalBinaryRead(reader, length, options, target) {
38893
+ let message = target ?? this.create(), end = reader.pos + length;
38894
+ while (reader.pos < end) {
38895
+ let [fieldNo, wireType] = reader.tag();
38896
+ switch (fieldNo) {
38897
+ case 1:
38898
+ message.path = reader.string();
38899
+ break;
38900
+ case 2:
38901
+ message.parentPath = reader.string();
38902
+ break;
38903
+ case 3:
38904
+ message.entries.push(BotFilesystemEntry.internalBinaryRead(reader, reader.uint32(), options));
38905
+ break;
38906
+ case 4:
38907
+ message.nextAfter = reader.string();
38908
+ break;
38909
+ default:
38910
+ let u = options.readUnknownField;
38911
+ if (u === "throw")
38912
+ throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
38913
+ let d = reader.skip(wireType);
38914
+ if (u !== false)
38915
+ (u === true ? import_runtime2.UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
38916
+ }
38917
+ }
38918
+ return message;
38919
+ }
38920
+ internalBinaryWrite(message, writer, options) {
38921
+ if (message.path !== "")
38922
+ writer.tag(1, import_runtime.WireType.LengthDelimited).string(message.path);
38923
+ if (message.parentPath !== undefined)
38924
+ writer.tag(2, import_runtime.WireType.LengthDelimited).string(message.parentPath);
38925
+ for (let i = 0;i < message.entries.length; i++)
38926
+ BotFilesystemEntry.internalBinaryWrite(message.entries[i], writer.tag(3, import_runtime.WireType.LengthDelimited).fork(), options).join();
38927
+ if (message.nextAfter !== undefined)
38928
+ writer.tag(4, import_runtime.WireType.LengthDelimited).string(message.nextAfter);
38929
+ let u = options.writeUnknownFields;
38930
+ if (u !== false)
38931
+ (u == true ? import_runtime2.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
38932
+ return writer;
38933
+ }
38934
+ }
38935
+ var BotFilesystemListing = new BotFilesystemListing$Type;
38936
+
38937
+ class BotFilesystemResponse$Type extends import_runtime4.MessageType {
38938
+ constructor() {
38939
+ super("BotFilesystemResponse", [
38940
+ { no: 1, name: "listing", kind: "message", oneof: "result", T: () => BotFilesystemListing },
38941
+ { no: 2, name: "workspace_id", kind: "scalar", oneof: "result", T: 9 },
38942
+ { no: 3, name: "problem", kind: "scalar", oneof: "result", T: 9 }
38943
+ ]);
38944
+ }
38945
+ create(value) {
38946
+ const message = globalThis.Object.create(this.messagePrototype);
38947
+ message.result = { oneofKind: undefined };
38948
+ if (value !== undefined)
38949
+ import_runtime3.reflectionMergePartial(this, message, value);
38950
+ return message;
38951
+ }
38952
+ internalBinaryRead(reader, length, options, target) {
38953
+ let message = target ?? this.create(), end = reader.pos + length;
38954
+ while (reader.pos < end) {
38955
+ let [fieldNo, wireType] = reader.tag();
38956
+ switch (fieldNo) {
38957
+ case 1:
38958
+ message.result = {
38959
+ oneofKind: "listing",
38960
+ listing: BotFilesystemListing.internalBinaryRead(reader, reader.uint32(), options, message.result.listing)
38961
+ };
38962
+ break;
38963
+ case 2:
38964
+ message.result = {
38965
+ oneofKind: "workspaceId",
38966
+ workspaceId: reader.string()
38967
+ };
38968
+ break;
38969
+ case 3:
38970
+ message.result = {
38971
+ oneofKind: "problem",
38972
+ problem: reader.string()
38973
+ };
38974
+ break;
38975
+ default:
38976
+ let u = options.readUnknownField;
38977
+ if (u === "throw")
38978
+ throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
38979
+ let d = reader.skip(wireType);
38980
+ if (u !== false)
38981
+ (u === true ? import_runtime2.UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
38982
+ }
38983
+ }
38984
+ return message;
38985
+ }
38986
+ internalBinaryWrite(message, writer, options) {
38987
+ if (message.result.oneofKind === "listing")
38988
+ BotFilesystemListing.internalBinaryWrite(message.result.listing, writer.tag(1, import_runtime.WireType.LengthDelimited).fork(), options).join();
38989
+ if (message.result.oneofKind === "workspaceId")
38990
+ writer.tag(2, import_runtime.WireType.LengthDelimited).string(message.result.workspaceId);
38991
+ if (message.result.oneofKind === "problem")
38992
+ writer.tag(3, import_runtime.WireType.LengthDelimited).string(message.result.problem);
38993
+ let u = options.writeUnknownFields;
38994
+ if (u !== false)
38995
+ (u == true ? import_runtime2.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
38996
+ return writer;
38997
+ }
38998
+ }
38999
+ var BotFilesystemResponse = new BotFilesystemResponse$Type;
39000
+
39001
+ class RequestBotFilesystemResult$Type extends import_runtime4.MessageType {
39002
+ constructor() {
39003
+ super("RequestBotFilesystemResult", [
39004
+ { no: 1, name: "response", kind: "message", T: () => BotFilesystemResponse }
39005
+ ]);
39006
+ }
39007
+ create(value) {
39008
+ const message = globalThis.Object.create(this.messagePrototype);
39009
+ if (value !== undefined)
39010
+ import_runtime3.reflectionMergePartial(this, message, value);
39011
+ return message;
39012
+ }
39013
+ internalBinaryRead(reader, length, options, target) {
39014
+ let message = target ?? this.create(), end = reader.pos + length;
39015
+ while (reader.pos < end) {
39016
+ let [fieldNo, wireType] = reader.tag();
39017
+ switch (fieldNo) {
39018
+ case 1:
39019
+ message.response = BotFilesystemResponse.internalBinaryRead(reader, reader.uint32(), options, message.response);
39020
+ break;
39021
+ default:
39022
+ let u = options.readUnknownField;
39023
+ if (u === "throw")
39024
+ throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
39025
+ let d = reader.skip(wireType);
39026
+ if (u !== false)
39027
+ (u === true ? import_runtime2.UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
39028
+ }
39029
+ }
39030
+ return message;
39031
+ }
39032
+ internalBinaryWrite(message, writer, options) {
39033
+ if (message.response)
39034
+ BotFilesystemResponse.internalBinaryWrite(message.response, writer.tag(1, import_runtime.WireType.LengthDelimited).fork(), options).join();
39035
+ let u = options.writeUnknownFields;
39036
+ if (u !== false)
39037
+ (u == true ? import_runtime2.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
39038
+ return writer;
39039
+ }
39040
+ }
39041
+ var RequestBotFilesystemResult = new RequestBotFilesystemResult$Type;
39042
+
39043
+ class BotFilesystemRequested$Type extends import_runtime4.MessageType {
39044
+ constructor() {
39045
+ super("BotFilesystemRequested", [
39046
+ { no: 1, name: "request_id", kind: "scalar", T: 4, L: 0 },
39047
+ { no: 2, name: "actor_user_id", kind: "scalar", T: 3, L: 0 },
39048
+ { no: 3, name: "chat_id", kind: "scalar", T: 3, L: 0 },
39049
+ { no: 4, name: "input", kind: "message", T: () => RequestBotFilesystemInput }
39050
+ ]);
39051
+ }
39052
+ create(value) {
39053
+ const message = globalThis.Object.create(this.messagePrototype);
39054
+ message.requestId = 0n;
39055
+ message.actorUserId = 0n;
39056
+ message.chatId = 0n;
39057
+ if (value !== undefined)
39058
+ import_runtime3.reflectionMergePartial(this, message, value);
39059
+ return message;
39060
+ }
39061
+ internalBinaryRead(reader, length, options, target) {
39062
+ let message = target ?? this.create(), end = reader.pos + length;
39063
+ while (reader.pos < end) {
39064
+ let [fieldNo, wireType] = reader.tag();
39065
+ switch (fieldNo) {
39066
+ case 1:
39067
+ message.requestId = reader.uint64().toBigInt();
39068
+ break;
39069
+ case 2:
39070
+ message.actorUserId = reader.int64().toBigInt();
39071
+ break;
39072
+ case 3:
39073
+ message.chatId = reader.int64().toBigInt();
39074
+ break;
39075
+ case 4:
39076
+ message.input = RequestBotFilesystemInput.internalBinaryRead(reader, reader.uint32(), options, message.input);
39077
+ break;
39078
+ default:
39079
+ let u = options.readUnknownField;
39080
+ if (u === "throw")
39081
+ throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
39082
+ let d = reader.skip(wireType);
39083
+ if (u !== false)
39084
+ (u === true ? import_runtime2.UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
39085
+ }
39086
+ }
39087
+ return message;
39088
+ }
39089
+ internalBinaryWrite(message, writer, options) {
39090
+ if (message.requestId !== 0n)
39091
+ writer.tag(1, import_runtime.WireType.Varint).uint64(message.requestId);
39092
+ if (message.actorUserId !== 0n)
39093
+ writer.tag(2, import_runtime.WireType.Varint).int64(message.actorUserId);
39094
+ if (message.chatId !== 0n)
39095
+ writer.tag(3, import_runtime.WireType.Varint).int64(message.chatId);
39096
+ if (message.input)
39097
+ RequestBotFilesystemInput.internalBinaryWrite(message.input, writer.tag(4, import_runtime.WireType.LengthDelimited).fork(), options).join();
39098
+ let u = options.writeUnknownFields;
39099
+ if (u !== false)
39100
+ (u == true ? import_runtime2.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
39101
+ return writer;
39102
+ }
39103
+ }
39104
+ var BotFilesystemRequested = new BotFilesystemRequested$Type;
39105
+
39106
+ class AnswerBotFilesystemInput$Type extends import_runtime4.MessageType {
39107
+ constructor() {
39108
+ super("AnswerBotFilesystemInput", [
39109
+ { no: 1, name: "request_id", kind: "scalar", T: 4, L: 0 },
39110
+ { no: 2, name: "response", kind: "message", T: () => BotFilesystemResponse }
39111
+ ]);
39112
+ }
39113
+ create(value) {
39114
+ const message = globalThis.Object.create(this.messagePrototype);
39115
+ message.requestId = 0n;
39116
+ if (value !== undefined)
39117
+ import_runtime3.reflectionMergePartial(this, message, value);
39118
+ return message;
39119
+ }
39120
+ internalBinaryRead(reader, length, options, target) {
39121
+ let message = target ?? this.create(), end = reader.pos + length;
39122
+ while (reader.pos < end) {
39123
+ let [fieldNo, wireType] = reader.tag();
39124
+ switch (fieldNo) {
39125
+ case 1:
39126
+ message.requestId = reader.uint64().toBigInt();
39127
+ break;
39128
+ case 2:
39129
+ message.response = BotFilesystemResponse.internalBinaryRead(reader, reader.uint32(), options, message.response);
39130
+ break;
39131
+ default:
39132
+ let u = options.readUnknownField;
39133
+ if (u === "throw")
39134
+ throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
39135
+ let d = reader.skip(wireType);
39136
+ if (u !== false)
39137
+ (u === true ? import_runtime2.UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
39138
+ }
39139
+ }
39140
+ return message;
39141
+ }
39142
+ internalBinaryWrite(message, writer, options) {
39143
+ if (message.requestId !== 0n)
39144
+ writer.tag(1, import_runtime.WireType.Varint).uint64(message.requestId);
39145
+ if (message.response)
39146
+ BotFilesystemResponse.internalBinaryWrite(message.response, writer.tag(2, import_runtime.WireType.LengthDelimited).fork(), options).join();
39147
+ let u = options.writeUnknownFields;
39148
+ if (u !== false)
39149
+ (u == true ? import_runtime2.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
39150
+ return writer;
39151
+ }
39152
+ }
39153
+ var AnswerBotFilesystemInput = new AnswerBotFilesystemInput$Type;
39154
+
39155
+ class AnswerBotFilesystemResult$Type extends import_runtime4.MessageType {
39156
+ constructor() {
39157
+ super("AnswerBotFilesystemResult", []);
39158
+ }
39159
+ create(value) {
39160
+ const message = globalThis.Object.create(this.messagePrototype);
39161
+ if (value !== undefined)
39162
+ import_runtime3.reflectionMergePartial(this, message, value);
39163
+ return message;
39164
+ }
39165
+ internalBinaryRead(reader, length, options, target) {
39166
+ return target ?? this.create();
39167
+ }
39168
+ internalBinaryWrite(message, writer, options) {
39169
+ let u = options.writeUnknownFields;
39170
+ if (u !== false)
39171
+ (u == true ? import_runtime2.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
39172
+ return writer;
39173
+ }
39174
+ }
39175
+ var AnswerBotFilesystemResult = new AnswerBotFilesystemResult$Type;
39176
+
38369
39177
  // ../node_modules/.bun/@noble+hashes@1.8.0/node_modules/@noble/hashes/esm/utils.js
38370
39178
  /*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */
38371
39179
  function isBytes(a) {
@@ -39144,6 +39952,13 @@ var asInlineId = (value, fieldName = "id") => {
39144
39952
  };
39145
39953
 
39146
39954
  // ../sdk/dist/utils/async-channel.js
39955
+ class ChannelConsumerError extends Error {
39956
+ constructor(message) {
39957
+ super(message);
39958
+ this.name = "ChannelConsumerError";
39959
+ }
39960
+ }
39961
+
39147
39962
  class AsyncChannelOverflowError extends Error {
39148
39963
  capacity;
39149
39964
  constructor(capacity) {
@@ -39253,6 +40068,7 @@ class AcknowledgedAsyncChannel {
39253
40068
  closed = false;
39254
40069
  failure = null;
39255
40070
  iteratorClaimed = false;
40071
+ consumption = null;
39256
40072
  constructor(capacity, byteLimit) {
39257
40073
  this.capacity = capacity;
39258
40074
  this.byteLimit = byteLimit;
@@ -39266,7 +40082,7 @@ class AcknowledgedAsyncChannel {
39266
40082
  send(value) {
39267
40083
  if (this.closed)
39268
40084
  return Promise.resolve(false);
39269
- if (!this.waiter && this.queue.length >= this.capacity) {
40085
+ if (!this.waiter && this.queue.length + (this.consumption?.active.size ?? 0) >= this.capacity) {
39270
40086
  throw new AsyncChannelOverflowError(this.capacity);
39271
40087
  }
39272
40088
  const bytes = this.byteLimit?.byteLength(value) ?? 0;
@@ -39286,6 +40102,7 @@ class AcknowledgedAsyncChannel {
39286
40102
  waiter.resolve({ value, done: false });
39287
40103
  } else {
39288
40104
  this.queue.push(item);
40105
+ this.pumpConsumption();
39289
40106
  }
39290
40107
  });
39291
40108
  }
@@ -39300,6 +40117,16 @@ class AcknowledgedAsyncChannel {
39300
40117
  return;
39301
40118
  this.closed = true;
39302
40119
  this.failure = error;
40120
+ const consumption = this.consumption;
40121
+ this.consumption = null;
40122
+ if (consumption) {
40123
+ for (const item of consumption.active.keys())
40124
+ item.acknowledge(false);
40125
+ if (error)
40126
+ consumption.reject(error);
40127
+ else
40128
+ consumption.resolve();
40129
+ }
39303
40130
  this.active?.acknowledge(false);
39304
40131
  this.active = null;
39305
40132
  for (const item of this.queue)
@@ -39315,6 +40142,65 @@ class AcknowledgedAsyncChannel {
39315
40142
  else
39316
40143
  waiter.resolve({ value: undefined, done: true });
39317
40144
  }
40145
+ consume(handler, key, concurrency = 8) {
40146
+ if (this.iteratorClaimed)
40147
+ return Promise.reject(new ChannelConsumerError("AcknowledgedAsyncChannel supports one consumer"));
40148
+ if (!Number.isSafeInteger(concurrency) || concurrency < 1) {
40149
+ return Promise.reject(new ChannelConsumerError("Consumer concurrency must be a positive safe integer"));
40150
+ }
40151
+ if (this.closed)
40152
+ return this.failure ? Promise.reject(this.failure) : Promise.resolve();
40153
+ this.iteratorClaimed = true;
40154
+ return new Promise((resolve, reject) => {
40155
+ this.consumption = { handler, key, concurrency, active: new Map, resolve, reject };
40156
+ this.pumpConsumption();
40157
+ });
40158
+ }
40159
+ pumpConsumption() {
40160
+ const owner = this.consumption;
40161
+ if (!owner || this.closed)
40162
+ return;
40163
+ try {
40164
+ while (owner.active.size < owner.concurrency && this.queue.length > 0) {
40165
+ if ([...owner.active.values()].includes(null))
40166
+ return;
40167
+ const keys = new Set(owner.active.values());
40168
+ let index = -1;
40169
+ let key = null;
40170
+ for (let i = 0;i < this.queue.length; i++) {
40171
+ const candidate = this.queue[i];
40172
+ const candidateKey = owner.key(candidate.value);
40173
+ if (candidateKey === null) {
40174
+ if (i === 0 && owner.active.size === 0)
40175
+ index = i;
40176
+ break;
40177
+ }
40178
+ if (!keys.has(candidateKey)) {
40179
+ index = i;
40180
+ key = candidateKey;
40181
+ break;
40182
+ }
40183
+ }
40184
+ if (index < 0)
40185
+ return;
40186
+ const item = this.queue.splice(index, 1)[0];
40187
+ owner.active.set(item, key);
40188
+ Promise.resolve().then(() => owner.handler(item.value)).then(() => {
40189
+ if (this.consumption !== owner)
40190
+ return;
40191
+ owner.active.delete(item);
40192
+ this.bufferedBytes -= item.bytes;
40193
+ item.acknowledge(true);
40194
+ this.pumpConsumption();
40195
+ }, (error) => {
40196
+ if (this.consumption === owner)
40197
+ this.fail(error instanceof Error ? error : new Error("Inbound handler failed"));
40198
+ });
40199
+ }
40200
+ } catch (error) {
40201
+ this.fail(error instanceof Error ? error : new Error("Inbound routing failed"));
40202
+ }
40203
+ }
39318
40204
  [Symbol.asyncIterator]() {
39319
40205
  if (this.iteratorClaimed) {
39320
40206
  return {
@@ -39322,8 +40208,11 @@ class AcknowledgedAsyncChannel {
39322
40208
  };
39323
40209
  }
39324
40210
  this.iteratorClaimed = true;
40211
+ let returned = false;
39325
40212
  return {
39326
40213
  next: () => {
40214
+ if (returned)
40215
+ return Promise.resolve({ value: undefined, done: true });
39327
40216
  if (this.active) {
39328
40217
  this.bufferedBytes -= this.active.bytes;
39329
40218
  this.active.acknowledge(true);
@@ -39347,6 +40236,11 @@ class AcknowledgedAsyncChannel {
39347
40236
  });
39348
40237
  },
39349
40238
  return: () => {
40239
+ if (returned)
40240
+ return Promise.resolve({ value: undefined, done: true });
40241
+ returned = true;
40242
+ this.waiter?.resolve({ value: undefined, done: true });
40243
+ this.waiter = null;
39350
40244
  if (this.active) {
39351
40245
  this.bufferedBytes -= this.active.bytes;
39352
40246
  this.active.acknowledge(false);
@@ -40025,10 +40919,12 @@ var normalizeRpcTimeoutMs = (timeoutMs, fallback) => {
40025
40919
 
40026
40920
  class ProtocolClientError extends Error {
40027
40921
  code;
40922
+ rpcCode;
40028
40923
  constructor(code, details) {
40029
40924
  super(details?.message ?? code);
40030
40925
  this.code = code;
40031
40926
  this.name = `ProtocolClientError:${code}`;
40927
+ this.rpcCode = details?.code;
40032
40928
  }
40033
40929
  }
40034
40930
  var commitOutcomeUnknownError = (message) => new ProtocolClientError("commit-outcome-unknown", { message });
@@ -44851,8 +45747,11 @@ class InlineSdkClient {
44851
45747
  peerResolutionRequestedByChatId = new Map;
44852
45748
  recoveryReconnectInFlight = null;
44853
45749
  degradedUpdateBuckets = new Map;
45750
+ discoveryRetry = null;
45751
+ recoveryRetries = new Map;
44854
45752
  liveCursorFences = new Set;
44855
45753
  liveAdmittedSeqByBucket = new Map;
45754
+ liveDeliveriesByBucket = new Map;
44856
45755
  discoveryRound = null;
44857
45756
  discoveryInFlight = null;
44858
45757
  discoveryCommitInFlight = null;
@@ -44945,12 +45844,14 @@ class InlineSdkClient {
44945
45844
  }
44946
45845
  }
44947
45846
  async close() {
44948
- if (!this.started)
44949
- return;
45847
+ const wasStarted = this.started;
44950
45848
  this.closed = true;
44951
45849
  this.started = false;
45850
+ this.cancelRecoveryRetries();
44952
45851
  this.rejectOpen(new Error("closed"));
44953
45852
  this.eventStream.close();
45853
+ if (!wasStarted)
45854
+ return;
44954
45855
  await settleWithin(this.protocol.stopTransport(), closeJoinTimeoutMs, () => this.log.warn?.("Timed out stopping SDK transport during close"));
44955
45856
  await settleWithin(Promise.allSettled([
44956
45857
  ...this.catchUpInFlightByChatId.values(),
@@ -45012,6 +45913,20 @@ class InlineSdkClient {
45012
45913
  events() {
45013
45914
  return this.eventStream;
45014
45915
  }
45916
+ consumeEvents(handler, options) {
45917
+ return this.eventStream.consume(handler, (event) => {
45918
+ const bucket = this.bucketForEvent(event);
45919
+ if (bucket?.kind === "user")
45920
+ return null;
45921
+ if (bucket)
45922
+ return this.updateBucketKey(bucket);
45923
+ return "chatId" in event && typeof event.chatId === "bigint" ? `chat:${event.chatId}` : null;
45924
+ }, options?.concurrency).catch(async (error) => {
45925
+ if (!(error instanceof ChannelConsumerError))
45926
+ await this.close();
45927
+ throw error;
45928
+ });
45929
+ }
45015
45930
  exportState() {
45016
45931
  return {
45017
45932
  version: 1,
@@ -45421,6 +46336,7 @@ class InlineSdkClient {
45421
46336
  this.log.error?.("SDK listener crashed", failure);
45422
46337
  this.started = false;
45423
46338
  this.closed = true;
46339
+ this.cancelRecoveryRetries();
45424
46340
  this.rejectOpen(failure);
45425
46341
  this.eventStream.fail(failure);
45426
46342
  this.protocol.stopTransport().catch((stopError) => {
@@ -45433,6 +46349,7 @@ class InlineSdkClient {
45433
46349
  return;
45434
46350
  this.authenticationError = error;
45435
46351
  this.started = false;
46352
+ this.cancelRecoveryRetries();
45436
46353
  this.rejectOpen(error);
45437
46354
  this.eventStream.close();
45438
46355
  try {
@@ -45442,6 +46359,7 @@ class InlineSdkClient {
45442
46359
  }
45443
46360
  }
45444
46361
  async onOpen() {
46362
+ this.cancelRecoveryRetries();
45445
46363
  this.requestCatchUpUser();
45446
46364
  for (const bucket of this.degradedUpdateBuckets.values()) {
45447
46365
  this.requestCatchUpForDegradedBucket(bucket);
@@ -45492,6 +46410,8 @@ class InlineSdkClient {
45492
46410
  return this.discoveryInFlight;
45493
46411
  if (this.discoveryCommitInFlight)
45494
46412
  return this.discoveryCommitInFlight;
46413
+ if (this.discoveryRetry?.timer)
46414
+ return;
45495
46415
  const round = {
45496
46416
  resultReceived: false,
45497
46417
  collectingHints: true,
@@ -45524,6 +46444,11 @@ class InlineSdkClient {
45524
46444
  this.log.warn?.("GET_UPDATES_STATE failed (continuing without date cursor)", error);
45525
46445
  if (this.discoveryRound === round)
45526
46446
  this.discoveryRound = null;
46447
+ if (error instanceof ProtocolClientError && (error.code === "timeout" || error.code === "not-connected" || error.code === "capacity-exceeded" || error.rpcCode === RpcError_Code.INTERNAL_ERROR || error.rpcCode === 500 || error.rpcCode === RpcError_Code.RATE_LIMIT || error.rpcCode === 429)) {
46448
+ this.scheduleDiscoveryRetry(error.rpcCode === RpcError_Code.RATE_LIMIT || error.rpcCode === 429 ? "rate_limited" : "discovery_failed");
46449
+ } else {
46450
+ this.log.error?.("Sync discovery unavailable", { reason: "request_rejected" });
46451
+ }
45527
46452
  }
45528
46453
  }
45529
46454
  tryCommitDiscoveryRound(round) {
@@ -45548,12 +46473,15 @@ class InlineSdkClient {
45548
46473
  return;
45549
46474
  if (saved) {
45550
46475
  this.discoveryRound = null;
46476
+ clearTimeout(this.discoveryRetry?.timer);
46477
+ this.discoveryRetry = null;
45551
46478
  return;
45552
46479
  }
45553
46480
  this.state.dateCursor = previousDateCursor;
45554
46481
  this.scheduleStateSave();
45555
46482
  this.discoveryRound = null;
45556
46483
  this.log.warn?.("Failed to persist discovery checkpoint; preserving previous date cursor");
46484
+ this.scheduleDiscoveryRetry("checkpoint_write_failed");
45557
46485
  }).finally(() => {
45558
46486
  if (this.discoveryCommitInFlight === commit)
45559
46487
  this.discoveryCommitInFlight = null;
@@ -45888,20 +46816,23 @@ class InlineSdkClient {
45888
46816
  try {
45889
46817
  acknowledged = this.eventStream.send(event);
45890
46818
  } catch (error) {
45891
- const bucket = this.bucketForEvent(event);
45892
- if (bucket) {
45893
- this.fenceLiveCursor(bucket);
45894
- this.markUpdateBucketDegraded(bucket);
45895
- this.requestCatchUpAfterEventOverflow(bucket, event);
46819
+ const bucket2 = this.bucketForEvent(event);
46820
+ if (bucket2) {
46821
+ this.fenceLiveCursor(bucket2);
46822
+ this.markUpdateBucketDegraded(bucket2);
46823
+ this.requestCatchUpAfterEventOverflow(bucket2, event);
45896
46824
  }
45897
46825
  this.log.warn?.("Inbound event buffer overflow; durable cursor remains unchanged and transport will recover", {
45898
- bucket: bucket ? this.updateBucketKey(bucket) : "none",
46826
+ bucket: bucket2 ? this.updateBucketKey(bucket2) : "none",
45899
46827
  error: extractErrorMessage(error)
45900
46828
  });
45901
46829
  this.requestRecoveryReconnect("inbound-event-buffer-overflow");
45902
46830
  return Promise.resolve(false);
45903
46831
  }
45904
- return acknowledged.then((applied) => {
46832
+ const bucket = source === "live" ? this.sequencedBucketForEvent(event) : undefined;
46833
+ const key = bucket ? this.updateBucketKey(bucket) : undefined;
46834
+ const deliveries = key ? this.liveDeliveriesByBucket.get(key) ?? new Set : undefined;
46835
+ const delivery = acknowledged.then((applied) => {
45905
46836
  if (applied) {
45906
46837
  onApplied?.();
45907
46838
  if (source === "live")
@@ -45909,8 +46840,16 @@ class InlineSdkClient {
45909
46840
  } else if (source === "live" && this.started) {
45910
46841
  this.recoverLiveEvent(event, "consumer-did-not-apply");
45911
46842
  }
46843
+ deliveries?.delete(delivery);
46844
+ if (key && deliveries?.size === 0)
46845
+ this.liveDeliveriesByBucket.delete(key);
45912
46846
  return applied;
45913
46847
  });
46848
+ if (key && deliveries) {
46849
+ deliveries.add(delivery);
46850
+ this.liveDeliveriesByBucket.set(key, deliveries);
46851
+ }
46852
+ return delivery;
45914
46853
  }
45915
46854
  bucketForEvent(event) {
45916
46855
  switch (event.kind) {
@@ -46088,20 +47027,25 @@ class InlineSdkClient {
46088
47027
  }
46089
47028
  requestCatchUpForDegradedBucket(bucket) {
46090
47029
  switch (bucket.kind) {
46091
- case "chat":
46092
- if (bucket.peer && this.isReliableChatPeer(bucket.peer)) {
46093
- this.requestCatchUpChat({ chatId: bucket.chatId, peer: bucket.peer });
47030
+ case "chat": {
47031
+ const request = this.catchUpRequestedByChatId.get(bucket.chatId) ?? this.peerResolutionRequestedByChatId.get(bucket.chatId);
47032
+ const updateSeq = request && !request.toLatest ? request.endSeq : undefined;
47033
+ const peer = bucket.peer ?? this.persistedChatPeer(bucket.chatId);
47034
+ if (peer && this.isReliableChatPeer(peer)) {
47035
+ this.requestCatchUpChat({ chatId: bucket.chatId, peer, updateSeq });
46094
47036
  } else {
46095
- const persistedPeer = this.persistedChatPeer(bucket.chatId);
46096
- if (persistedPeer)
46097
- this.requestCatchUpChat({ chatId: bucket.chatId, peer: persistedPeer });
46098
- else
46099
- this.resolvePersistedChatPeer(bucket.chatId);
47037
+ this.resolvePersistedChatPeer(bucket.chatId, updateSeq);
46100
47038
  }
46101
47039
  return;
46102
- case "space":
46103
- this.requestCatchUpSpace({ spaceId: bucket.spaceId });
47040
+ }
47041
+ case "space": {
47042
+ const request = this.catchUpRequestedBySpaceId.get(bucket.spaceId);
47043
+ this.requestCatchUpSpace({
47044
+ spaceId: bucket.spaceId,
47045
+ updateSeq: request && !request.toLatest ? request.endSeq : undefined
47046
+ });
46104
47047
  return;
47048
+ }
46105
47049
  case "user":
46106
47050
  this.requestCatchUpUser(true);
46107
47051
  return;
@@ -46286,7 +47230,7 @@ class InlineSdkClient {
46286
47230
  bumpChatSeq(chatId, seq, source) {
46287
47231
  if (source === "user" || source === "space" || source === "chat")
46288
47232
  return;
46289
- if (source === "live" && this.liveCursorFences.has(`chat:${chatId}`))
47233
+ if (source === "live" && this.liveCursorFences.has(`chat:${chatId}`) && seq !== (this.state.lastSeqByChatId?.[chatId.toString()] ?? 0) + 1)
46290
47234
  return;
46291
47235
  if (!Number.isFinite(seq))
46292
47236
  return;
@@ -46295,6 +47239,7 @@ class InlineSdkClient {
46295
47239
  const key = chatId.toString();
46296
47240
  const prev = this.state.lastSeqByChatId[key] ?? 0;
46297
47241
  if (seq > prev) {
47242
+ this.resetRecoveryBackoff({ kind: "chat", chatId });
46298
47243
  this.state.lastSeqByChatId[key] = seq;
46299
47244
  this.scheduleStateSave();
46300
47245
  }
@@ -46303,7 +47248,7 @@ class InlineSdkClient {
46303
47248
  bumpSpaceSeq(spaceId, seq, source) {
46304
47249
  if (source === "user" || source === "space" || source === "chat")
46305
47250
  return;
46306
- if (source === "live" && this.liveCursorFences.has(`space:${spaceId}`))
47251
+ if (source === "live" && this.liveCursorFences.has(`space:${spaceId}`) && seq !== (this.state.lastSeqBySpaceId?.[spaceId.toString()] ?? 0) + 1)
46307
47252
  return;
46308
47253
  if (!Number.isFinite(seq))
46309
47254
  return;
@@ -46312,6 +47257,7 @@ class InlineSdkClient {
46312
47257
  const key = spaceId.toString();
46313
47258
  const prev = this.state.lastSeqBySpaceId[key] ?? 0;
46314
47259
  if (seq > prev) {
47260
+ this.resetRecoveryBackoff({ kind: "space", spaceId });
46315
47261
  this.state.lastSeqBySpaceId[key] = seq;
46316
47262
  this.scheduleStateSave();
46317
47263
  }
@@ -46326,12 +47272,13 @@ class InlineSdkClient {
46326
47272
  bumpUserSeq(seq, source) {
46327
47273
  if (source === "user" || source === "space" || source === "chat")
46328
47274
  return;
46329
- if (source === "live" && this.liveCursorFences.has("user"))
47275
+ if (source === "live" && this.liveCursorFences.has("user") && seq !== (this.state.lastUserSeq ?? 0) + 1)
46330
47276
  return;
46331
47277
  if (!Number.isFinite(seq) || seq <= 0)
46332
47278
  return;
46333
47279
  const prev = this.state.lastUserSeq ?? 0;
46334
47280
  if (seq > prev) {
47281
+ this.resetRecoveryBackoff({ kind: "user" });
46335
47282
  this.state.lastUserSeq = seq;
46336
47283
  this.scheduleStateSave();
46337
47284
  }
@@ -46345,14 +47292,17 @@ class InlineSdkClient {
46345
47292
  if (this.userCatchUpInFlight) {
46346
47293
  return this.userCatchUpInFlight;
46347
47294
  }
47295
+ if (this.recoveryRetries.get("user")?.timer)
47296
+ return null;
46348
47297
  this.fenceLiveCursor({ kind: "user" });
46349
47298
  this.userCatchUpInFlight = this.doCatchUpUser(lastUserSeq ?? 0).catch((error) => {
46350
- this.markUpdateBucketDegraded({ kind: "user" });
47299
+ this.recordCatchUpFailure({ kind: "user" }, error);
46351
47300
  this.log.warn?.("GET_UPDATES user catch-up failed; bucket remains degraded", {
46352
47301
  error: extractErrorMessage(error)
46353
47302
  });
46354
47303
  }).finally(() => {
46355
47304
  this.userCatchUpInFlight = null;
47305
+ this.scheduleRecoveryRetry({ kind: "user" });
46356
47306
  });
46357
47307
  return this.userCatchUpInFlight;
46358
47308
  }
@@ -46405,7 +47355,7 @@ class InlineSdkClient {
46405
47355
  });
46406
47356
  }
46407
47357
  if (deliveredSeq <= cursor && !payload.final) {
46408
- this.markUpdateBucketDegraded({ kind: "user" });
47358
+ this.markUpdateBucketDegraded({ kind: "user" }, "non_progress");
46409
47359
  this.log.warn?.("GET_UPDATES user catch-up made no progress; bucket remains degraded", {
46410
47360
  cursor,
46411
47361
  deliveredSeq
@@ -46441,15 +47391,18 @@ class InlineSdkClient {
46441
47391
  const existing = this.catchUpInFlightByChatId.get(params.chatId);
46442
47392
  if (existing)
46443
47393
  return existing;
47394
+ if (this.recoveryRetries.get(`chat:${params.chatId}`)?.timer)
47395
+ return Promise.resolve();
47396
+ const initialDemand = this.catchUpRequestedByChatId.get(params.chatId);
46444
47397
  const task = this.drainCatchUpChat(params.chatId).catch((error) => {
46445
- this.catchUpRequestedByChatId.delete(params.chatId);
46446
- this.markUpdateBucketDegraded({ kind: "chat", chatId: params.chatId, peer: params.peer });
47398
+ this.recordCatchUpFailure({ kind: "chat", chatId: params.chatId, peer: params.peer }, error, this.catchUpRequestedByChatId.get(params.chatId) !== initialDemand);
46447
47399
  this.log.warn?.("GET_UPDATES chat catch-up failed; bucket remains degraded", {
46448
47400
  chatId: params.chatId.toString(),
46449
47401
  error: extractErrorMessage(error)
46450
47402
  });
46451
47403
  }).finally(() => {
46452
47404
  this.catchUpInFlightByChatId.delete(params.chatId);
47405
+ this.scheduleRecoveryRetry({ kind: "chat", chatId: params.chatId });
46453
47406
  });
46454
47407
  this.catchUpInFlightByChatId.set(params.chatId, task);
46455
47408
  return task;
@@ -46473,12 +47426,8 @@ class InlineSdkClient {
46473
47426
  if (stop) {
46474
47427
  if (this.catchUpRequestedByChatId.get(chatId) !== request)
46475
47428
  continue;
46476
- this.catchUpRequestedByChatId.delete(chatId);
46477
- return;
46478
- }
46479
- const latest = this.catchUpRequestedByChatId.get(chatId);
46480
- const syncedSeq = this.state.lastSeqByChatId?.[key] ?? 0;
46481
- if (!latest || latest.endSeq != null && latest.endSeq <= syncedSeq) {
47429
+ if (this.degradedUpdateBuckets.has(`chat:${chatId}`))
47430
+ return;
46482
47431
  this.catchUpRequestedByChatId.delete(chatId);
46483
47432
  return;
46484
47433
  }
@@ -46545,7 +47494,7 @@ class InlineSdkClient {
46545
47494
  });
46546
47495
  }
46547
47496
  if (deliveredSeq <= cursor && !payload.final) {
46548
- this.markUpdateBucketDegraded({ kind: "chat", chatId, peer });
47497
+ this.markUpdateBucketDegraded({ kind: "chat", chatId, peer }, "non_progress");
46549
47498
  this.log.warn?.("GET_UPDATES made no progress; bucket remains degraded", {
46550
47499
  chatId: chatId.toString(),
46551
47500
  cursor,
@@ -46563,7 +47512,7 @@ class InlineSdkClient {
46563
47512
  continue;
46564
47513
  }
46565
47514
  if (endSeq != null && deliveredSeq < endSeq) {
46566
- this.markUpdateBucketDegraded({ kind: "chat", chatId, peer });
47515
+ this.markUpdateBucketDegraded({ kind: "chat", chatId, peer }, "target_not_reached");
46567
47516
  this.log.warn?.("GET_UPDATES final chat page remained behind the requested target", {
46568
47517
  chatId: chatId.toString(),
46569
47518
  requestedEndSeq: endSeq,
@@ -46589,15 +47538,18 @@ class InlineSdkClient {
46589
47538
  const existing = this.catchUpInFlightBySpaceId.get(params.spaceId);
46590
47539
  if (existing)
46591
47540
  return existing;
47541
+ if (this.recoveryRetries.get(`space:${params.spaceId}`)?.timer)
47542
+ return Promise.resolve();
47543
+ const initialDemand = this.catchUpRequestedBySpaceId.get(params.spaceId);
46592
47544
  const task = this.drainCatchUpSpace(params.spaceId).catch((error) => {
46593
- this.catchUpRequestedBySpaceId.delete(params.spaceId);
46594
- this.markUpdateBucketDegraded({ kind: "space", spaceId: params.spaceId });
47545
+ this.recordCatchUpFailure({ kind: "space", spaceId: params.spaceId }, error, this.catchUpRequestedBySpaceId.get(params.spaceId) !== initialDemand);
46595
47546
  this.log.warn?.("GET_UPDATES space catch-up failed; bucket remains degraded", {
46596
47547
  spaceId: params.spaceId.toString(),
46597
47548
  error: extractErrorMessage(error)
46598
47549
  });
46599
47550
  }).finally(() => {
46600
47551
  this.catchUpInFlightBySpaceId.delete(params.spaceId);
47552
+ this.scheduleRecoveryRetry({ kind: "space", spaceId: params.spaceId });
46601
47553
  });
46602
47554
  this.catchUpInFlightBySpaceId.set(params.spaceId, task);
46603
47555
  return task;
@@ -46621,12 +47573,8 @@ class InlineSdkClient {
46621
47573
  if (stop) {
46622
47574
  if (this.catchUpRequestedBySpaceId.get(spaceId) !== request)
46623
47575
  continue;
46624
- this.catchUpRequestedBySpaceId.delete(spaceId);
46625
- return;
46626
- }
46627
- const latest = this.catchUpRequestedBySpaceId.get(spaceId);
46628
- const syncedSeq = this.state.lastSeqBySpaceId?.[key] ?? 0;
46629
- if (!latest || latest.endSeq != null && latest.endSeq <= syncedSeq) {
47576
+ if (this.degradedUpdateBuckets.has(`space:${spaceId}`))
47577
+ return;
46630
47578
  this.catchUpRequestedBySpaceId.delete(spaceId);
46631
47579
  return;
46632
47580
  }
@@ -46695,7 +47643,7 @@ class InlineSdkClient {
46695
47643
  });
46696
47644
  }
46697
47645
  if (deliveredSeq <= cursor && !payload.final) {
46698
- this.markUpdateBucketDegraded({ kind: "space", spaceId });
47646
+ this.markUpdateBucketDegraded({ kind: "space", spaceId }, "non_progress");
46699
47647
  this.log.warn?.("GET_UPDATES space made no progress; bucket remains degraded", {
46700
47648
  spaceId: spaceId.toString(),
46701
47649
  cursor,
@@ -46713,7 +47661,7 @@ class InlineSdkClient {
46713
47661
  continue;
46714
47662
  }
46715
47663
  if (endSeq != null && deliveredSeq < endSeq) {
46716
- this.markUpdateBucketDegraded({ kind: "space", spaceId });
47664
+ this.markUpdateBucketDegraded({ kind: "space", spaceId }, "target_not_reached");
46717
47665
  this.log.warn?.("GET_UPDATES final space page remained behind the requested target", {
46718
47666
  spaceId: spaceId.toString(),
46719
47667
  requestedEndSeq: endSeq,
@@ -46738,6 +47686,9 @@ class InlineSdkClient {
46738
47686
  const existing = this.peerResolutionInFlightByChatId.get(chatId);
46739
47687
  if (existing)
46740
47688
  return existing;
47689
+ if (this.recoveryRetries.get(`chat:${chatId}`)?.timer)
47690
+ return Promise.resolve();
47691
+ const initialDemand = this.peerResolutionRequestedByChatId.get(chatId);
46741
47692
  const task = this.getChat({ chatId }).then(async (chat) => {
46742
47693
  const peer = chat.peer;
46743
47694
  if (!peer || !this.isReliableChatPeer(peer)) {
@@ -46751,14 +47702,16 @@ class InlineSdkClient {
46751
47702
  ...requested && !requested.toLatest && requested.endSeq != null ? { updateSeq: requested.endSeq } : {}
46752
47703
  });
46753
47704
  }).catch((error) => {
46754
- this.markUpdateBucketDegraded({ kind: "chat", chatId });
47705
+ this.recordCatchUpFailure({ kind: "chat", chatId }, error, this.peerResolutionRequestedByChatId.get(chatId) !== initialDemand);
46755
47706
  this.log.warn?.("Unable to resolve legacy chat peer; bucket remains degraded", {
46756
47707
  chatId: chatId.toString(),
46757
47708
  error: extractErrorMessage(error)
46758
47709
  });
46759
47710
  }).finally(() => {
46760
47711
  this.peerResolutionInFlightByChatId.delete(chatId);
46761
- this.peerResolutionRequestedByChatId.delete(chatId);
47712
+ if (!this.degradedUpdateBuckets.has(`chat:${chatId}`))
47713
+ this.peerResolutionRequestedByChatId.delete(chatId);
47714
+ this.scheduleRecoveryRetry({ kind: "chat", chatId });
46762
47715
  });
46763
47716
  this.peerResolutionInFlightByChatId.set(chatId, task);
46764
47717
  return task;
@@ -46811,7 +47764,7 @@ class InlineSdkClient {
46811
47764
  }
46812
47765
  validateCatchUpPage(payload, startSeq, bucket) {
46813
47766
  if (payload.resultType !== GetUpdatesResult_ResultType.SLICE && payload.resultType !== GetUpdatesResult_ResultType.EMPTY) {
46814
- this.markUpdateBucketDegraded(bucket);
47767
+ this.markUpdateBucketDegraded(bucket, "invalid_page_type");
46815
47768
  this.log.warn?.("GET_UPDATES returned an invalid page result type; bucket remains degraded", {
46816
47769
  bucket: this.updateBucketKey(bucket),
46817
47770
  resultType: payload.resultType
@@ -46820,7 +47773,7 @@ class InlineSdkClient {
46820
47773
  }
46821
47774
  const deliveredSeq = Number(payload.seq);
46822
47775
  if (!Number.isSafeInteger(deliveredSeq) || deliveredSeq < startSeq) {
46823
- this.markUpdateBucketDegraded(bucket);
47776
+ this.markUpdateBucketDegraded(bucket, "invalid_page_cursor");
46824
47777
  this.log.warn?.("GET_UPDATES page moved backwards or returned an invalid seq; bucket remains degraded", {
46825
47778
  bucket: this.updateBucketKey(bucket),
46826
47779
  startSeq,
@@ -46832,7 +47785,7 @@ class InlineSdkClient {
46832
47785
  for (const update of payload.updates) {
46833
47786
  const seq = update.seq;
46834
47787
  if (!Number.isSafeInteger(seq) || seq == null || seq <= startSeq || seq > deliveredSeq || accounted.has(seq)) {
46835
- this.markUpdateBucketDegraded(bucket);
47788
+ this.markUpdateBucketDegraded(bucket, "invalid_update_sequence");
46836
47789
  this.log.warn?.("GET_UPDATES page included an invalid or duplicate update seq; bucket remains degraded", {
46837
47790
  bucket: this.updateBucketKey(bucket),
46838
47791
  seq
@@ -46845,7 +47798,7 @@ class InlineSdkClient {
46845
47798
  for (const skipped of payload.skippedSequences) {
46846
47799
  const seq = Number(skipped.seq);
46847
47800
  if (!Number.isSafeInteger(seq) || seq <= startSeq || seq > deliveredSeq || accounted.has(seq)) {
46848
- this.markUpdateBucketDegraded(bucket);
47801
+ this.markUpdateBucketDegraded(bucket, "invalid_skipped_sequence");
46849
47802
  this.log.warn?.("GET_UPDATES page included an invalid or duplicate skipped seq; bucket remains degraded", {
46850
47803
  bucket: this.updateBucketKey(bucket),
46851
47804
  seq
@@ -46861,7 +47814,7 @@ class InlineSdkClient {
46861
47814
  break;
46862
47815
  case SyncSkippedSequence_Reason.REASON_UNSPECIFIED:
46863
47816
  default:
46864
- this.markUpdateBucketDegraded(bucket);
47817
+ this.markUpdateBucketDegraded(bucket, "unknown_skip_reason");
46865
47818
  this.log.warn?.("GET_UPDATES page included an unsupported skipped-sequence reason; bucket remains degraded", {
46866
47819
  bucket: this.updateBucketKey(bucket),
46867
47820
  reason: skipped.reason
@@ -46870,7 +47823,7 @@ class InlineSdkClient {
46870
47823
  }
46871
47824
  }
46872
47825
  if (accounted.size !== deliveredSeq - startSeq) {
46873
- this.markUpdateBucketDegraded(bucket);
47826
+ this.markUpdateBucketDegraded(bucket, "unaccounted_gap");
46874
47827
  this.log.warn?.("GET_UPDATES page did not account for every advanced sequence; bucket remains degraded", {
46875
47828
  bucket: this.updateBucketKey(bucket),
46876
47829
  startSeq,
@@ -46952,7 +47905,7 @@ class InlineSdkClient {
46952
47905
  this.clearUpdateBucketDegraded(bucket);
46953
47906
  return true;
46954
47907
  } catch (error) {
46955
- this.markUpdateBucketDegraded(bucket);
47908
+ this.markUpdateBucketDegraded(bucket, "repair_failed");
46956
47909
  this.log.warn?.("Authoritative update repair failed; bucket remains degraded", {
46957
47910
  bucket: this.updateBucketKey(bucket),
46958
47911
  error: extractErrorMessage(error)
@@ -46961,7 +47914,17 @@ class InlineSdkClient {
46961
47914
  }
46962
47915
  }
46963
47916
  async acceptCatchUpUpdates(updates, source, bucket) {
47917
+ const liveDeliveries = this.liveDeliveriesByBucket.get(this.updateBucketKey(bucket));
47918
+ if (liveDeliveries && (await Promise.all(liveDeliveries)).some((applied) => !applied)) {
47919
+ this.markUpdateBucketDegraded(bucket, "host_unacknowledged");
47920
+ return false;
47921
+ }
47922
+ if (this.closed)
47923
+ return false;
47924
+ const appliedThrough = this.bucketCursor(bucket);
46964
47925
  for (const update of updates) {
47926
+ if (update.seq != null && update.seq > 0 && update.seq <= appliedThrough)
47927
+ continue;
46965
47928
  if (update.update.oneofKind === "chatSkipPts" && source === "chat") {
46966
47929
  continue;
46967
47930
  }
@@ -46972,7 +47935,7 @@ class InlineSdkClient {
46972
47935
  if (accepted === true)
46973
47936
  continue;
46974
47937
  if (accepted === false) {
46975
- this.markUpdateBucketDegraded(bucket);
47938
+ this.markUpdateBucketDegraded(bucket, "host_unacknowledged");
46976
47939
  this.log.warn?.("GET_UPDATES event was not acknowledged by the SDK host; cursor remains unchanged", {
46977
47940
  bucket: this.updateBucketKey(bucket),
46978
47941
  updateKind: update.update.oneofKind
@@ -46993,8 +47956,95 @@ class InlineSdkClient {
46993
47956
  }
46994
47957
  return true;
46995
47958
  }
46996
- markUpdateBucketDegraded(bucket) {
46997
- this.degradedUpdateBuckets.set(this.updateBucketKey(bucket), bucket);
47959
+ recordCatchUpFailure(bucket, error, hasNewerDemand = false) {
47960
+ const rpcCode = error instanceof ProtocolClientError ? error.rpcCode : undefined;
47961
+ if (!hasNewerDemand && bucket.kind !== "user" && (rpcCode === RpcError_Code.PEER_ID_INVALID || rpcCode === RpcError_Code.CHAT_ID_INVALID || rpcCode === RpcError_Code.SPACE_ID_INVALID)) {
47962
+ this.clearUpdateBucketDegraded(bucket);
47963
+ if (bucket.kind === "chat") {
47964
+ this.catchUpRequestedByChatId.delete(bucket.chatId);
47965
+ this.peerResolutionRequestedByChatId.delete(bucket.chatId);
47966
+ } else
47967
+ this.catchUpRequestedBySpaceId.delete(bucket.spaceId);
47968
+ const round = this.discoveryRound;
47969
+ if (round) {
47970
+ round.targets.delete(this.updateBucketKey(bucket));
47971
+ this.tryCommitDiscoveryRound(round);
47972
+ }
47973
+ this.log.error?.("Sync bucket unavailable", { bucketKind: bucket.kind, reason: "access_rejected" });
47974
+ return;
47975
+ }
47976
+ this.markUpdateBucketDegraded(bucket, rpcCode === RpcError_Code.RATE_LIMIT || rpcCode === 429 ? "rate_limited" : error instanceof ProtocolClientError ? error.code : "request_failed");
47977
+ }
47978
+ markUpdateBucketDegraded(bucket, failure = "incomplete") {
47979
+ const key = this.updateBucketKey(bucket);
47980
+ this.degradedUpdateBuckets.set(key, bucket);
47981
+ const retry = this.recoveryRetries.get(key) ?? { attempt: 0, failure, reported: new Set };
47982
+ retry.failure = failure;
47983
+ this.recoveryRetries.set(key, retry);
47984
+ queueMicrotask(() => this.scheduleRecoveryRetry(bucket));
47985
+ }
47986
+ resetRecoveryBackoff(bucket) {
47987
+ const retry = this.recoveryRetries.get(this.updateBucketKey(bucket));
47988
+ if (retry)
47989
+ retry.attempt = 0;
47990
+ }
47991
+ cancelRecoveryRetries() {
47992
+ clearTimeout(this.discoveryRetry?.timer);
47993
+ this.discoveryRetry = null;
47994
+ for (const retry of this.recoveryRetries.values())
47995
+ clearTimeout(retry.timer);
47996
+ this.recoveryRetries.clear();
47997
+ }
47998
+ scheduleDiscoveryRetry(reason) {
47999
+ if (!this.started || this.closed || this.protocol.getDiagnostics().state !== "open")
48000
+ return;
48001
+ const retry = this.discoveryRetry ?? { attempt: 0, reported: new Set };
48002
+ if (retry.timer)
48003
+ return;
48004
+ if (!retry.reported.has(reason)) {
48005
+ retry.reported.add(reason);
48006
+ this.log.error?.("Sync recovery scheduled", { bucketKind: "discovery", reason });
48007
+ }
48008
+ const delayMs = reason === "rate_limited" ? 60000 : Math.min(30000, 1000 * 2 ** Math.min(retry.attempt, 5));
48009
+ retry.attempt++;
48010
+ retry.timer = setTimeout(() => {
48011
+ retry.timer = undefined;
48012
+ if (this.started && !this.closed && this.protocol.getDiagnostics().state === "open") {
48013
+ this.initializeDateCursor();
48014
+ }
48015
+ }, delayMs);
48016
+ retry.timer.unref?.();
48017
+ this.discoveryRetry = retry;
48018
+ }
48019
+ scheduleRecoveryRetry(bucket) {
48020
+ const key = this.updateBucketKey(bucket);
48021
+ if (!this.started || this.closed || !this.degradedUpdateBuckets.has(key))
48022
+ return;
48023
+ if (bucket.kind === "chat" && (this.catchUpInFlightByChatId.has(bucket.chatId) || this.peerResolutionInFlightByChatId.has(bucket.chatId)))
48024
+ return;
48025
+ if (bucket.kind === "space" && this.catchUpInFlightBySpaceId.has(bucket.spaceId))
48026
+ return;
48027
+ if (bucket.kind === "user" && this.userCatchUpInFlight)
48028
+ return;
48029
+ const retry = this.recoveryRetries.get(key) ?? { attempt: 0, failure: "incomplete", reported: new Set };
48030
+ if (retry.timer || this.protocol.getDiagnostics().state !== "open")
48031
+ return;
48032
+ const delayMs = retry.failure === "rate_limited" ? 60000 : Math.min(5000, 1000 * 2 ** Math.min(retry.attempt, 3));
48033
+ if (!retry.reported.has(retry.failure)) {
48034
+ retry.reported.add(retry.failure);
48035
+ this.log.error?.("Sync recovery scheduled", { bucketKind: bucket.kind, reason: retry.failure });
48036
+ }
48037
+ retry.attempt++;
48038
+ retry.timer = setTimeout(() => {
48039
+ retry.timer = undefined;
48040
+ if (!this.started || this.closed || this.protocol.getDiagnostics().state !== "open")
48041
+ return;
48042
+ const pending = this.degradedUpdateBuckets.get(key);
48043
+ if (pending)
48044
+ this.requestCatchUpForDegradedBucket(pending);
48045
+ }, delayMs);
48046
+ retry.timer.unref?.();
48047
+ this.recoveryRetries.set(key, retry);
46998
48048
  }
46999
48049
  fenceLiveCursor(bucket) {
47000
48050
  this.liveCursorFences.add(this.updateBucketKey(bucket));
@@ -47002,6 +48052,8 @@ class InlineSdkClient {
47002
48052
  clearUpdateBucketDegraded(bucket) {
47003
48053
  const key = this.updateBucketKey(bucket);
47004
48054
  this.degradedUpdateBuckets.delete(key);
48055
+ clearTimeout(this.recoveryRetries.get(key)?.timer);
48056
+ this.recoveryRetries.delete(key);
47005
48057
  this.liveCursorFences.delete(key);
47006
48058
  this.liveAdmittedSeqByBucket.delete(key);
47007
48059
  }
@@ -62906,6 +63958,275 @@ function looksLikeInlineTargetId(raw, normalizedInput) {
62906
63958
  return /^[0-9]+$/.test(normalized);
62907
63959
  }
62908
63960
 
63961
+ // src/telemetry.ts
63962
+ import { randomUUID } from "node:crypto";
63963
+ import { readFile as readFile2 } from "node:fs/promises";
63964
+ var TELEMETRY_TIMEOUT_MS = 2000;
63965
+ var TELEMETRY_DEDUP_MS = 5 * 60000;
63966
+ var MAX_ERROR_MESSAGE_LENGTH = 8000;
63967
+ var MAX_STACK_FRAMES = 80;
63968
+ var SENSITIVE_ENV_NAME = /(?:token|secret|password|api[_-]?key|authorization)/i;
63969
+ var lastReports = new Map;
63970
+ var releasePromise;
63971
+ function telemetryDisabled(env = process.env) {
63972
+ const disabled = (value) => value != null && ["1", "true", "yes", "on"].includes(value.trim().toLowerCase());
63973
+ const optedOut = (value) => value != null && ["0", "false", "off"].includes(value.trim().toLowerCase());
63974
+ return disabled(env.DO_NOT_TRACK) || optedOut(env.INLINE_PLUGIN_TELEMETRY);
63975
+ }
63976
+ function resolveDsn(env = process.env) {
63977
+ if (telemetryDisabled(env))
63978
+ return "";
63979
+ return env.INLINE_OPENCLAW_SENTRY_DSN?.trim() ?? "";
63980
+ }
63981
+ function sensitiveValues(env = process.env) {
63982
+ return Object.entries(env).filter(([name, value]) => SENSITIVE_ENV_NAME.test(name) && (value?.length ?? 0) >= 8).map(([, value]) => value);
63983
+ }
63984
+ function redactOpenClawTelemetryText(value, env = process.env) {
63985
+ let text = String(value ?? "").replace(/\b(Authorization\s*[:=]\s*)(?:Basic|Bearer)\s+\S+/gi, "$1[REDACTED]").replace(/\b((?:Basic|Bearer)\s+)\S+/gi, "$1[REDACTED]").replace(/(https?:\/\/)[^/\s:@]+:[^@\s/]+@/gi, "$1[REDACTED]@").replace(/([?&](?:access_token|auth|authorization|key|password|secret|token)[^=\s&]*)=([^&\s]+)/gi, "$1=[REDACTED]").replace(/\b([A-Za-z0-9_-]*(?:token|secret|password|api[_-]?key|authorization)[A-Za-z0-9_-]*)\s*([=:])\s*\S+/gi, "$1$2[REDACTED]");
63986
+ for (const secret of sensitiveValues(env)) {
63987
+ text = text.replaceAll(secret, "[REDACTED]");
63988
+ }
63989
+ return text.slice(0, MAX_ERROR_MESSAGE_LENGTH);
63990
+ }
63991
+ function safeTag(value) {
63992
+ const normalized = value.trim().toLowerCase();
63993
+ return normalized.length > 0 && normalized.length <= 80 && /^[a-z0-9._-]+$/.test(normalized) ? normalized : "unknown";
63994
+ }
63995
+ function parseStack(error51, env) {
63996
+ const stack = error51.stack ?? "";
63997
+ const frames = [];
63998
+ for (const rawLine of stack.split(`
63999
+ `).slice(1)) {
64000
+ const line = redactOpenClawTelemetryText(rawLine.trim(), env);
64001
+ const match = /^at\s+(?:(.*?)\s+\()?(.+?):(\d+):(\d+)\)?$/.exec(line);
64002
+ if (!match)
64003
+ continue;
64004
+ const filename = match[2];
64005
+ const frame = {
64006
+ filename,
64007
+ abs_path: filename,
64008
+ function: match[1] || "<anonymous>",
64009
+ lineno: Number(match[3]),
64010
+ colno: Number(match[4]),
64011
+ in_app: filename.includes("@inline-openclaw/inline") || filename.includes("/openclaw/") || /\/(?:channel-plugin-api|runtime-register-api|index)\.js$/.test(filename)
64012
+ };
64013
+ frames.push(frame);
64014
+ if (frames.length >= MAX_STACK_FRAMES)
64015
+ break;
64016
+ }
64017
+ return frames.reverse();
64018
+ }
64019
+ function buildOpenClawTelemetryEvent(operation, error51, options = {}) {
64020
+ const env = options.env ?? process.env;
64021
+ const exception = error51 instanceof Error ? error51 : new Error(String(error51 ?? "Unknown error"));
64022
+ const frames = parseStack(exception, env);
64023
+ return {
64024
+ event_id: randomUUID().replaceAll("-", ""),
64025
+ timestamp: new Date().toISOString(),
64026
+ platform: "javascript",
64027
+ level: "error",
64028
+ logger: "inline.openclaw.plugin",
64029
+ exception: {
64030
+ values: [{
64031
+ type: redactOpenClawTelemetryText(exception.name || "Error", env),
64032
+ value: redactOpenClawTelemetryText(exception.message || String(error51), env),
64033
+ mechanism: {
64034
+ type: "inline_plugin_boundary",
64035
+ handled: options.handled ?? true
64036
+ },
64037
+ ...frames.length > 0 ? { stacktrace: { frames } } : {}
64038
+ }]
64039
+ },
64040
+ tags: {
64041
+ operation: safeTag(operation),
64042
+ runtime: "node",
64043
+ os: process.platform,
64044
+ arch: process.arch
64045
+ },
64046
+ sdk: { name: "inline.plugin.telemetry", version: "1" }
64047
+ };
64048
+ }
64049
+ async function resolveRelease() {
64050
+ releasePromise ??= (async () => {
64051
+ try {
64052
+ const parsed = JSON.parse(await readFile2(new URL("../package.json", import.meta.url), "utf8"));
64053
+ if (typeof parsed.version === "string" && parsed.version.trim()) {
64054
+ return `inline-openclaw-plugin@${parsed.version.trim()}`;
64055
+ }
64056
+ } catch {}
64057
+ return;
64058
+ })();
64059
+ return releasePromise;
64060
+ }
64061
+ function parseSentryDsn(dsn) {
64062
+ try {
64063
+ const parsed = new URL(dsn);
64064
+ if (!/^https?:$/.test(parsed.protocol) || !parsed.username)
64065
+ return null;
64066
+ const parts = parsed.pathname.split("/").filter(Boolean);
64067
+ const projectId = parts.pop();
64068
+ if (!projectId || !/^\d+$/.test(projectId))
64069
+ return null;
64070
+ const prefix = parts.length > 0 ? `/${parts.join("/")}` : "";
64071
+ return {
64072
+ endpoint: `${parsed.origin}${prefix}/api/${projectId}/envelope/`,
64073
+ publicKey: parsed.username
64074
+ };
64075
+ } catch {
64076
+ return null;
64077
+ }
64078
+ }
64079
+ async function sendOpenClawPluginError(operation, error51, options = {}) {
64080
+ const env = options.env ?? process.env;
64081
+ const dsn = resolveDsn(env);
64082
+ const target = parseSentryDsn(dsn);
64083
+ if (!target)
64084
+ return false;
64085
+ const event = buildOpenClawTelemetryEvent(operation, error51, options);
64086
+ const release = await resolveRelease();
64087
+ if (release)
64088
+ event.release = release;
64089
+ const envelope = [
64090
+ JSON.stringify({ event_id: event.event_id, dsn, sent_at: event.timestamp }),
64091
+ JSON.stringify({ type: "event", content_type: "application/json" }),
64092
+ JSON.stringify(event)
64093
+ ].join(`
64094
+ `);
64095
+ const controller = new AbortController;
64096
+ const timeout = setTimeout(() => controller.abort(), TELEMETRY_TIMEOUT_MS);
64097
+ timeout.unref?.();
64098
+ try {
64099
+ const response = await fetch(target.endpoint, {
64100
+ method: "POST",
64101
+ headers: {
64102
+ "content-type": "application/x-sentry-envelope",
64103
+ "x-sentry-auth": `Sentry sentry_version=7, sentry_key=${target.publicKey}, sentry_client=inline.plugin.telemetry/1`
64104
+ },
64105
+ body: envelope,
64106
+ signal: controller.signal
64107
+ });
64108
+ return response.ok;
64109
+ } catch {
64110
+ return false;
64111
+ } finally {
64112
+ clearTimeout(timeout);
64113
+ }
64114
+ }
64115
+ function reportOpenClawPluginError(operation, error51, options = {}) {
64116
+ try {
64117
+ const exception = error51 instanceof Error ? error51 : new Error(String(error51 ?? "Unknown error"));
64118
+ const key = `${safeTag(operation)}\x00${exception.name}\x00${redactOpenClawTelemetryText(exception.message)}`;
64119
+ const now = Date.now();
64120
+ if (now - (lastReports.get(key) ?? 0) < TELEMETRY_DEDUP_MS)
64121
+ return;
64122
+ lastReports.set(key, now);
64123
+ sendOpenClawPluginError(operation, exception, options).catch(() => {});
64124
+ } catch {}
64125
+ }
64126
+ function wrapCallback(operation, callback) {
64127
+ return function(...args) {
64128
+ try {
64129
+ const result = Reflect.apply(callback, this, args);
64130
+ if (result && typeof result.then === "function") {
64131
+ return Promise.resolve(result).catch((error51) => {
64132
+ reportOpenClawPluginError(operation, error51);
64133
+ throw error51;
64134
+ });
64135
+ }
64136
+ return result;
64137
+ } catch (error51) {
64138
+ reportOpenClawPluginError(operation, error51);
64139
+ throw error51;
64140
+ }
64141
+ };
64142
+ }
64143
+ function wrapSurface(prefix, surface) {
64144
+ const wrapped = { ...surface };
64145
+ for (const [name, member] of Object.entries(wrapped)) {
64146
+ if (typeof member === "function") {
64147
+ wrapped[name] = wrapCallback(`${prefix}.${name}`, member);
64148
+ }
64149
+ }
64150
+ return wrapped;
64151
+ }
64152
+ function instrumentToolValue(value) {
64153
+ if (Array.isArray(value))
64154
+ return value.map(instrumentToolValue);
64155
+ if (!value || typeof value !== "object")
64156
+ return value;
64157
+ const tool = value;
64158
+ const execute = tool.execute;
64159
+ if (typeof execute !== "function")
64160
+ return value;
64161
+ const name = typeof tool.name === "string" ? safeTag(tool.name) : "unknown";
64162
+ return new Proxy(tool, {
64163
+ get(target, property, receiver) {
64164
+ if (property === "execute") {
64165
+ return wrapCallback(`tool.${name}`, execute);
64166
+ }
64167
+ return Reflect.get(target, property, receiver);
64168
+ }
64169
+ });
64170
+ }
64171
+ function instrumentOpenClawPluginApi(value) {
64172
+ const api2 = value;
64173
+ return new Proxy(api2, {
64174
+ get(target, property, receiver) {
64175
+ const member = Reflect.get(target, property, receiver);
64176
+ if (property === "registerTool" && typeof member === "function") {
64177
+ return (toolOrFactory, options) => {
64178
+ const wrapped = typeof toolOrFactory === "function" ? wrapCallback("tool.factory", (...args) => instrumentToolValue(Reflect.apply(toolOrFactory, undefined, args))) : instrumentToolValue(toolOrFactory);
64179
+ return Reflect.apply(member, target, [wrapped, options]);
64180
+ };
64181
+ }
64182
+ if (property === "registerCommand" && typeof member === "function") {
64183
+ return (command) => {
64184
+ const handler = command.handler;
64185
+ const name = typeof command.name === "string" ? safeTag(command.name) : "unknown";
64186
+ const wrapped = typeof handler === "function" ? { ...command, handler: wrapCallback(`command.${name}`, handler) } : command;
64187
+ return Reflect.apply(member, target, [wrapped]);
64188
+ };
64189
+ }
64190
+ if (property === "on" && typeof member === "function") {
64191
+ return (event, handler) => Reflect.apply(member, target, [event, wrapCallback(`hook.${safeTag(event)}`, handler)]);
64192
+ }
64193
+ return member;
64194
+ }
64195
+ });
64196
+ }
64197
+ function instrumentOpenClawChannelPlugin(value) {
64198
+ const plugin = { ...value };
64199
+ for (const name of [
64200
+ "lifecycle",
64201
+ "pairing",
64202
+ "outbound",
64203
+ "heartbeat",
64204
+ "directory",
64205
+ "resolver",
64206
+ "allowlist",
64207
+ "status",
64208
+ "gateway"
64209
+ ]) {
64210
+ const surface = plugin[name];
64211
+ if (surface && typeof surface === "object") {
64212
+ plugin[name] = wrapSurface(name, surface);
64213
+ }
64214
+ }
64215
+ const message = plugin.message;
64216
+ if (message && typeof message === "object") {
64217
+ const wrappedMessage = { ...message };
64218
+ const send = wrappedMessage.send;
64219
+ if (send && typeof send === "object") {
64220
+ wrappedMessage.send = wrapSurface("message.send", send);
64221
+ }
64222
+ plugin.message = wrappedMessage;
64223
+ }
64224
+ return plugin;
64225
+ }
64226
+ function reportOpenClawRegistrationError(error51) {
64227
+ reportOpenClawPluginError("plugin.register", error51, { handled: false });
64228
+ }
64229
+
62909
64230
  // src/inline/monitor.ts
62910
64231
  import { mkdir as mkdir2, stat } from "node:fs/promises";
62911
64232
  import path3 from "node:path";
@@ -62976,6 +64297,8 @@ import {
62976
64297
  createTransportActivityStatusPatch
62977
64298
  } from "openclaw/plugin-sdk/gateway-runtime";
62978
64299
  import {
64300
+ hasFinalInboundReplyDispatch,
64301
+ hasVisibleInboundReplyDispatch,
62979
64302
  classifyChannelInboundEvent,
62980
64303
  createChannelInboundDebouncer,
62981
64304
  resolveUnmentionedGroupInboundPolicy,
@@ -63174,7 +64497,7 @@ import {
63174
64497
  } from "openclaw/plugin-sdk/interactive-runtime";
63175
64498
 
63176
64499
  // src/inline/media.ts
63177
- import { randomUUID } from "node:crypto";
64500
+ import { randomUUID as randomUUID2 } from "node:crypto";
63178
64501
  import { mkdir, writeFile as writeFile2 } from "node:fs/promises";
63179
64502
  import os from "node:os";
63180
64503
  import path from "node:path";
@@ -63309,17 +64632,19 @@ function resolveMediaMaxBytes(params) {
63309
64632
  }
63310
64633
  function buildInlineMediaLoadOptions(params) {
63311
64634
  const explicitLocalRoots = params.mediaAccess?.localRoots ?? params.mediaLocalRoots;
63312
- const readFile2 = params.mediaAccess?.readFile ?? params.mediaReadFile;
64635
+ const readFile3 = params.mediaAccess?.readFile ?? params.mediaReadFile;
63313
64636
  const workspaceDir = params.mediaAccess?.workspaceDir;
63314
- const localRoots = explicitLocalRoots === "any" || explicitLocalRoots?.length ? explicitLocalRoots : readFile2 ? "any" : undefined;
63315
- if (!localRoots && !readFile2 && !workspaceDir) {
64637
+ const signal = params.signal;
64638
+ const localRoots = explicitLocalRoots === "any" || explicitLocalRoots?.length ? explicitLocalRoots : readFile3 ? "any" : undefined;
64639
+ if (!localRoots && !readFile3 && !workspaceDir && !signal) {
63316
64640
  return params.maxBytes;
63317
64641
  }
63318
64642
  return {
63319
64643
  maxBytes: params.maxBytes,
63320
64644
  ...localRoots ? { localRoots } : {},
63321
- ...readFile2 ? { readFile: readFile2, hostReadCapability: true } : {},
63322
- ...workspaceDir ? { workspaceDir } : {}
64645
+ ...readFile3 ? { readFile: readFile3, hostReadCapability: true } : {},
64646
+ ...workspaceDir ? { workspaceDir } : {},
64647
+ ...signal ? { signal } : {}
63323
64648
  };
63324
64649
  }
63325
64650
  function mediaFromUploadResult(params) {
@@ -63346,12 +64671,15 @@ async function uploadInlineMediaFromUrl(params) {
63346
64671
  let uploadType;
63347
64672
  let fileName;
63348
64673
  try {
64674
+ params.signal?.throwIfAborted();
63349
64675
  loaded = await loadWebMediaCompat(params.mediaUrl, buildInlineMediaLoadOptions({
63350
64676
  maxBytes,
63351
64677
  ...params.mediaAccess ? { mediaAccess: params.mediaAccess } : {},
63352
64678
  ...params.mediaLocalRoots ? { mediaLocalRoots: params.mediaLocalRoots } : {},
63353
- ...params.mediaReadFile ? { mediaReadFile: params.mediaReadFile } : {}
64679
+ ...params.mediaReadFile ? { mediaReadFile: params.mediaReadFile } : {},
64680
+ ...params.signal ? { signal: params.signal } : {}
63354
64681
  }));
64682
+ params.signal?.throwIfAborted();
63355
64683
  if (!loaded) {
63356
64684
  throw new Error("inline media upload: media load returned no data");
63357
64685
  }
@@ -63376,6 +64704,7 @@ async function uploadInlineMediaFromUrl(params) {
63376
64704
  file: loaded.buffer,
63377
64705
  fileName,
63378
64706
  ...detectedMime ? { contentType: detectedMime } : {},
64707
+ ...params.signal ? { signal: params.signal } : {},
63379
64708
  ...uploadType === "video" ? {
63380
64709
  width: DEFAULT_VIDEO_WIDTH,
63381
64710
  height: DEFAULT_VIDEO_HEIGHT,
@@ -63434,7 +64763,7 @@ async function downloadInlineMediaFromUrl(params) {
63434
64763
  });
63435
64764
  const dir = path.join(os.tmpdir(), "openclaw-inline-downloads");
63436
64765
  await mkdir(dir, { recursive: true });
63437
- const filePath = path.join(dir, `${randomUUID()}-${fileName}`);
64766
+ const filePath = path.join(dir, `${randomUUID2()}-${fileName}`);
63438
64767
  await writeFile2(filePath, loaded.buffer, { flag: "wx" });
63439
64768
  return {
63440
64769
  path: filePath,
@@ -63556,6 +64885,12 @@ var INLINE_MESSAGE_ENTITY_TYPE = {
63556
64885
  function compactWhitespace(raw) {
63557
64886
  return (raw ?? "").replace(/\s+/g, " ").trim();
63558
64887
  }
64888
+ function normalizeRawMessageText(raw) {
64889
+ return (raw ?? "").replaceAll(`\r
64890
+ `, `
64891
+ `).replaceAll("\r", `
64892
+ `).trim();
64893
+ }
63559
64894
  function bestPhotoSize(photo) {
63560
64895
  let best = {
63561
64896
  cdnUrl: null,
@@ -63860,7 +65195,7 @@ function formatEntitySummary(entity) {
63860
65195
  }
63861
65196
  }
63862
65197
  function summarizeInlineMessageContent(message) {
63863
- const rawText = compactWhitespace(message.message);
65198
+ const rawText = normalizeRawMessageText(message.message);
63864
65199
  const media = messageMediaSummary(message);
63865
65200
  const attachments = messageAttachmentSummaries(message);
63866
65201
  const entities = messageEntitySummaries(message);
@@ -69028,7 +70363,7 @@ function countInlineExecApprovalEligibleAccounts(params) {
69028
70363
  }).length;
69029
70364
  }
69030
70365
  function isExecApprovalRequest(request) {
69031
- return "command" in request.request;
70366
+ return request.approvalKind != null ? request.approvalKind === "exec" : ("command" in request.request) && !("proposalHash" in request.request);
69032
70367
  }
69033
70368
  function isTargetForwardingMode(mode) {
69034
70369
  return mode === "targets" || mode === "both";
@@ -72682,31 +74017,20 @@ function resolveInlineMediaMaxBytes(params) {
72682
74017
  }
72683
74018
  function buildInlineInboundMediaFacts(media) {
72684
74019
  return toInboundMediaFacts(media.map((item) => ({
72685
- path: item.path,
72686
- ...item.contentType?.trim() ? { contentType: item.contentType.trim() } : {}
74020
+ ...item.path ? { path: item.path } : {},
74021
+ ...item.contentType?.trim() ? { contentType: item.contentType.trim() } : {},
74022
+ ...item.fileName?.trim() ? { fileName: item.fileName.trim() } : {},
74023
+ ...item.kind ? { kind: item.kind } : {},
74024
+ ...item.messageId ? { messageId: item.messageId } : {}
72687
74025
  })));
72688
74026
  }
72689
- function buildInlineAttachmentPlaceholder(content) {
72690
- const media = content.media;
72691
- if (!media)
72692
- return "";
72693
- switch (media.kind) {
72694
- case "photo":
72695
- return "<media:image>";
72696
- case "video":
72697
- return "<media:video>";
72698
- case "document":
72699
- return "<media:document>";
72700
- case "voice":
72701
- return "<media:audio>";
72702
- default:
72703
- return "";
72704
- }
72705
- }
72706
74027
  function buildInlineInboundBodyText(content) {
72707
- const textWithPlaceholder = [content.rawText, buildInlineAttachmentPlaceholder(content)].filter(Boolean).join(`
72708
- `).trim();
72709
- return textWithPlaceholder || content.text;
74028
+ if (content.rawText)
74029
+ return content.rawText;
74030
+ if (content.media?.kind === "nudge" || !content.media && content.attachmentText) {
74031
+ return content.text;
74032
+ }
74033
+ return "";
72710
74034
  }
72711
74035
  function resolveFilePathHint(params) {
72712
74036
  const preferred = params.preferredName?.trim();
@@ -72723,20 +74047,31 @@ function resolveFilePathHint(params) {
72723
74047
  async function resolveInlineInboundMedia(params) {
72724
74048
  const content = summarizeInlineMessageContent(params.message);
72725
74049
  const candidates = new Map;
74050
+ const out = [];
74051
+ const messageId = String(params.message.id);
74052
+ const inlineMediaKind = content.media?.kind === "photo" ? "image" : content.media?.kind === "video" ? "video" : content.media?.kind === "voice" ? "audio" : content.media?.kind === "document" ? "document" : null;
72726
74053
  if (content.media?.url) {
72727
74054
  candidates.set(content.media.url, {
72728
74055
  fileName: content.media.fileName ?? null,
72729
- mimeType: content.media.mimeType ?? null
74056
+ mimeType: content.media.mimeType ?? null,
74057
+ kind: inlineMediaKind ?? "document"
74058
+ });
74059
+ } else if (inlineMediaKind) {
74060
+ out.push({
74061
+ kind: inlineMediaKind,
74062
+ ...content.media?.fileName ? { fileName: content.media.fileName } : {},
74063
+ ...content.media?.mimeType ? { contentType: content.media.mimeType } : {},
74064
+ messageId
72730
74065
  });
72731
74066
  }
72732
74067
  for (const attachment of content.attachments) {
72733
74068
  if (attachment.kind !== "urlPreview" || !attachment.previewImageUrl)
72734
74069
  continue;
72735
74070
  candidates.set(attachment.previewImageUrl, {
72736
- mimeType: null
74071
+ mimeType: null,
74072
+ kind: "image"
72737
74073
  });
72738
74074
  }
72739
- const out = [];
72740
74075
  for (const [url2, candidate] of candidates.entries()) {
72741
74076
  try {
72742
74077
  const filePathHint = resolveFilePathHint({ sourceUrl: url2, preferredName: candidate.fileName });
@@ -72748,12 +74083,22 @@ async function resolveInlineInboundMedia(params) {
72748
74083
  const fetchedContentType = fetched.contentType ?? candidate.mimeType ?? undefined;
72749
74084
  const saved = await params.core.channel.media.saveMediaBuffer(fetched.buffer, fetchedContentType, "inbound", params.maxBytes, fetched.fileName ?? candidate.fileName ?? undefined);
72750
74085
  const contentType = saved.contentType ?? fetchedContentType;
74086
+ const fileName = fetched.fileName ?? candidate.fileName;
72751
74087
  out.push({
72752
74088
  path: saved.path,
72753
- ...contentType ? { contentType } : {}
74089
+ ...contentType ? { contentType } : {},
74090
+ ...fileName ? { fileName } : {},
74091
+ ...candidate.kind !== "document" ? { kind: candidate.kind } : {},
74092
+ messageId
72754
74093
  });
72755
74094
  } catch (err) {
72756
74095
  params.log?.warn?.(`inline: failed to download inbound media ${url2}: ${String(err)}`);
74096
+ out.push({
74097
+ kind: candidate.kind,
74098
+ ...candidate.fileName ? { fileName: candidate.fileName } : {},
74099
+ ...candidate.mimeType ? { contentType: candidate.mimeType } : {},
74100
+ messageId
74101
+ });
72757
74102
  }
72758
74103
  }
72759
74104
  return out;
@@ -72948,7 +74293,9 @@ ${entityLines.slice(-ATTACHMENT_CONTEXT_LIMIT).join(`
72948
74293
  }
72949
74294
  async function monitorInlineProvider(params) {
72950
74295
  let { cfg } = params;
72951
- const { account, runtime, abortSignal, log, statusSink } = params;
74296
+ const { account, runtime, log, statusSink } = params;
74297
+ const shutdown = new AbortController;
74298
+ const abortSignal = AbortSignal.any([params.abortSignal, shutdown.signal]);
72952
74299
  const core3 = getInlineRuntime();
72953
74300
  if (!account.configured || !account.baseUrl) {
72954
74301
  throw new Error(`Inline not configured for account "${account.accountId}" (missing baseUrl or token)`);
@@ -73000,6 +74347,9 @@ async function monitorInlineProvider(params) {
73000
74347
  },
73001
74348
  error: (msg, meta3) => {
73002
74349
  const line = formatSdkLogLine(msg, meta3);
74350
+ if (msg === "Sync recovery scheduled" || msg === "Sync bucket unavailable" || msg === "Sync discovery unavailable") {
74351
+ reportOpenClawPluginError("sdk.sync_recovery", new Error(line));
74352
+ }
73003
74353
  log?.error(line);
73004
74354
  if (isRecoverableInlineConnectionError(line)) {
73005
74355
  recoverableConnectionError = line;
@@ -73032,7 +74382,7 @@ async function monitorInlineProvider(params) {
73032
74382
  const meResult = await client.invokeRaw(Method.GET_ME, {
73033
74383
  oneofKind: "getMe",
73034
74384
  getMe: {}
73035
- });
74385
+ }, { signal: abortSignal });
73036
74386
  if (meResult.oneofKind !== "getMe" || !meResult.getMe.user) {
73037
74387
  throw new Error("missing user");
73038
74388
  }
@@ -73438,6 +74788,8 @@ async function monitorInlineProvider(params) {
73438
74788
  });
73439
74789
  };
73440
74790
  const handleInboundNow = async (input) => {
74791
+ if (abortSignal.aborted)
74792
+ return;
73441
74793
  const chatId = input.chatId;
73442
74794
  const msg = input.msg;
73443
74795
  const rawBodyOverride = input.rawBodyOverride ?? null;
@@ -73456,7 +74808,7 @@ async function monitorInlineProvider(params) {
73456
74808
  currentAttachmentText = currentContent.attachmentText || null;
73457
74809
  currentEntityText = currentContent.entityText || null;
73458
74810
  }
73459
- if (!rawBody)
74811
+ if (!rawBody && !currentContent?.media && !currentContent?.attachments.length)
73460
74812
  return;
73461
74813
  commandTarget = resolveInlineCommandTarget(rawBody, botUsername);
73462
74814
  if (commandTarget.targeted && !commandTarget.addressedToMe) {
@@ -74585,7 +75937,7 @@ This model will be used for your next message.`, []);
74585
75937
  closing: false
74586
75938
  };
74587
75939
  const renderInlineProgressPlaceholder = async () => {
74588
- if (!progressPlaceholderEnabled || progressState.closing || adoptingThread)
75940
+ if (abortSignal.aborted || !progressPlaceholderEnabled || progressState.closing || adoptingThread)
74589
75941
  return;
74590
75942
  const text = sanitizeInlineDeliveryText(formatChannelProgressDraftText({
74591
75943
  entry: account.config,
@@ -74595,7 +75947,7 @@ This model will be used for your next message.`, []);
74595
75947
  if (!text || text === progressState.text)
74596
75948
  return;
74597
75949
  progressState.opChain = progressState.opChain.then(async () => {
74598
- if (progressState.closing || text === progressState.text)
75950
+ if (abortSignal.aborted || progressState.closing || text === progressState.text)
74599
75951
  return;
74600
75952
  if (progressState.messageId == null) {
74601
75953
  const sent = await client.sendMessage({
@@ -74698,6 +76050,8 @@ This model will be used for your next message.`, []);
74698
76050
  };
74699
76051
  const nextEditStreamInterval = (requestDurationMs) => Math.min(INLINE_EDIT_STREAM_MAX_INTERVAL_MS, Math.max(INLINE_EDIT_STREAM_MIN_INTERVAL_MS, Math.ceil(requestDurationMs * 1.25)));
74700
76052
  const sendEditStreamSnapshot = async (snapshot) => {
76053
+ if (abortSignal.aborted)
76054
+ return;
74701
76055
  try {
74702
76056
  if (editStreamState.messageId == null) {
74703
76057
  let sent;
@@ -74753,6 +76107,11 @@ This model will be used for your next message.`, []);
74753
76107
  }
74754
76108
  };
74755
76109
  const scheduleEditStreamDrain = () => {
76110
+ if (abortSignal.aborted) {
76111
+ editStreamState.pendingSnapshot = null;
76112
+ clearEditStreamTimer();
76113
+ return;
76114
+ }
74756
76115
  if (editStreamState.failed || editStreamState.inFlight != null || editStreamState.timer != null || editStreamState.pendingSnapshot == null) {
74757
76116
  return;
74758
76117
  }
@@ -74962,7 +76321,7 @@ This model will be used for your next message.`, []);
74962
76321
  await resetEditStreamForAssistantMessage();
74963
76322
  };
74964
76323
  const handlePartialStreamPayload = (payload) => {
74965
- if (adoptingThread)
76324
+ if (abortSignal.aborted || adoptingThread)
74966
76325
  return;
74967
76326
  const visiblePayload = resolveInlineChatVisibleReplyPayload(payload);
74968
76327
  if (!visiblePayload)
@@ -75048,6 +76407,10 @@ This model will be used for your next message.`, []);
75048
76407
  }
75049
76408
  };
75050
76409
  const replyOptions = {
76410
+ abortSignal,
76411
+ onObservedReplyDelivery: async () => {
76412
+ delivered = true;
76413
+ },
75051
76414
  ...onModelSelected ? { onModelSelected } : {},
75052
76415
  blockReplyTimeoutMs: 25000,
75053
76416
  ...streamViaEditMessage ? {
@@ -75187,7 +76550,7 @@ This model will be used for your next message.`, []);
75187
76550
  let undeliveredFinalActions;
75188
76551
  try {
75189
76552
  const dispatch = await dispatchInlineReplyWithSessionInitRetry({
75190
- shouldRetry: () => !delivered && !skippedNonSilent && !failedNonSilent,
76553
+ shouldRetry: () => !abortSignal.aborted && !delivered && !skippedNonSilent && !failedNonSilent,
75191
76554
  onRetry: (retry, delayMs) => {
75192
76555
  log?.warn(`[${account.accountId}] AGENT_DISPATCH_TRACE phase=session_init_conflict_retry ` + `retry=${retry} delay_ms=${delayMs}`);
75193
76556
  },
@@ -75198,6 +76561,8 @@ This model will be used for your next message.`, []);
75198
76561
  ...dispatcherPipelineOptions,
75199
76562
  ...buildInlineTypingDispatcherOptions(typingCallbacks),
75200
76563
  deliver: async (payload, info) => {
76564
+ if (abortSignal.aborted)
76565
+ return inlineReplyDeliveryResult(false);
75201
76566
  let payloadVisible = false;
75202
76567
  const markPayloadVisible = () => {
75203
76568
  delivered = true;
@@ -75492,12 +76857,14 @@ Attachment: ${mediaUrl}` : `Attachment: ${mediaUrl}`;
75492
76857
  if (!delivered && streamViaEditMessage && (editStreamState.messageId != null || editStreamState.initialSendMayHaveLanded) && !streamedFinalEditRejected) {
75493
76858
  delivered = true;
75494
76859
  }
75495
- const hostHandledTurn = dispatchResult.queuedFinal === true || dispatchResult.observedReplyDelivery === true || dispatchResult.noVisibleReplyFallbackDelivered === true;
76860
+ const hostDeliveredReply = hasVisibleInboundReplyDispatch({ ...dispatchResult, queuedFinal: false }, { fallbackDelivered: dispatchResult.noVisibleReplyFallbackDelivered === true });
76861
+ const hostHandledTurn = hasFinalInboundReplyDispatch(dispatchResult) || hostDeliveredReply;
76862
+ const deferredToActiveRun = dispatchResult.deferredToActiveRun != null;
75496
76863
  const deliberateSilence = skippedSilently || dispatchResult.deliberateSilentTerminalReply === true;
75497
76864
  const skipFallbackSuppressed = dispatchResult.sourceReplyDeliveryMode === "message_tool_only";
75498
76865
  const hostRequestedNoVisibleRecovery = dispatchResult.noVisibleReplyFallbackEligible === true;
75499
76866
  const explicitFailure = dispatchError != null || failedNonSilent;
75500
- if (!delivered && !adoptingThread && (explicitFailure || !hostHandledTurn && !deliberateSilence && (skippedNonSilent && !skipFallbackSuppressed || hostRequestedNoVisibleRecovery))) {
76867
+ if (!abortSignal.aborted && !delivered && !hostDeliveredReply && !deferredToActiveRun && !adoptingThread && (explicitFailure || !hostHandledTurn && !deliberateSilence && (skippedNonSilent && !skipFallbackSuppressed || hostRequestedNoVisibleRecovery))) {
75501
76868
  botPresenceLifecycle.fail();
75502
76869
  const fallbackText = undeliveredFinalText.trim() ? undeliveredFinalText : dispatchError != null ? INLINE_REQUEST_ERROR_FALLBACK : EMPTY_RESPONSE_FALLBACK;
75503
76870
  const sent = await client.sendMessage({
@@ -75516,12 +76883,16 @@ Attachment: ${mediaUrl}` : `Attachment: ${mediaUrl}`;
75516
76883
  }
75517
76884
  } finally {
75518
76885
  endActiveThreadRoute();
76886
+ if (abortSignal.aborted) {
76887
+ runTypingCleanup();
76888
+ botPresenceLifecycle.cleanup();
76889
+ }
75519
76890
  if (adoptedThreadThisTurn) {
75520
76891
  await sendDeliveryTyping(deliveryChatId, false).catch((error51) => runtime.error?.(`inline adopted thread typing cleanup failed: ${String(error51)}`));
75521
76892
  botPresenceLifecycle.cleanup();
75522
76893
  }
75523
76894
  await setParentThreadCreationTyping(false);
75524
- if (callbackActionEvent && !callbackActionAnswered) {
76895
+ if (!abortSignal.aborted && callbackActionEvent && !callbackActionAnswered) {
75525
76896
  try {
75526
76897
  await answerCallbackIfNeeded();
75527
76898
  } catch (error51) {
@@ -76107,6 +77478,8 @@ Attachment: ${mediaUrl}` : `Attachment: ${mediaUrl}`;
76107
77478
  });
76108
77479
  };
76109
77480
  const scheduleInboundTask = (label, run, options) => {
77481
+ if (abortSignal.aborted)
77482
+ return;
76110
77483
  let task;
76111
77484
  try {
76112
77485
  if (options?.serialKey) {
@@ -76114,7 +77487,10 @@ Attachment: ${mediaUrl}` : `Attachment: ${mediaUrl}`;
76114
77487
  const previous = inboundTaskChains.get(serialKey) ?? Promise.resolve();
76115
77488
  task = previous.catch(() => {
76116
77489
  return;
76117
- }).then(run);
77490
+ }).then(() => {
77491
+ if (!abortSignal.aborted)
77492
+ return run();
77493
+ });
76118
77494
  const settled = task.catch(() => {
76119
77495
  return;
76120
77496
  });
@@ -76263,23 +77639,50 @@ Attachment: ${mediaUrl}` : `Attachment: ${mediaUrl}`;
76263
77639
  suppressedVoiceMessageEditTimeouts.clear();
76264
77640
  };
76265
77641
  const drainInboundTasks = async () => {
76266
- while (pendingInboundTasks.size > 0) {
76267
- await Promise.allSettled(pendingInboundTasks);
77642
+ let timer;
77643
+ const drained = (async () => {
77644
+ while (pendingInboundTasks.size > 0) {
77645
+ await Promise.allSettled(pendingInboundTasks);
77646
+ }
77647
+ })();
77648
+ let onAbort;
77649
+ try {
77650
+ await Promise.race([
77651
+ drained,
77652
+ new Promise((resolve) => {
77653
+ onAbort = () => {
77654
+ timer = setTimeout(() => {
77655
+ log?.warn(`[${account.accountId}] inline shutdown grace expired with pending inbound work`);
77656
+ resolve();
77657
+ }, 15000);
77658
+ };
77659
+ if (abortSignal.aborted)
77660
+ onAbort();
77661
+ else
77662
+ abortSignal.addEventListener("abort", onAbort, { once: true });
77663
+ })
77664
+ ]);
77665
+ } finally {
77666
+ clearTimeout(timer);
77667
+ if (onAbort)
77668
+ abortSignal.removeEventListener("abort", onAbort);
76268
77669
  }
76269
77670
  };
76270
77671
  const loop = (async () => {
76271
77672
  try {
76272
- for await (const event of client.events()) {
76273
- if (abortSignal.aborted)
76274
- break;
77673
+ await client.consumeEvents(async (event) => {
77674
+ if (abortSignal.aborted) {
77675
+ await client.close();
77676
+ return;
77677
+ }
76275
77678
  const rawEvent = event;
76276
77679
  if (event.kind === "bot.chatSettings.request") {
76277
77680
  scheduleInboundTask("agent settings request", () => answerOpenClawBotSettingsRequest(event));
76278
- continue;
77681
+ return;
76279
77682
  }
76280
77683
  if (event.kind === "bot.chatSettings.item.invoke") {
76281
77684
  scheduleInboundTask("agent settings update", () => answerOpenClawBotSettingsMutation(event), { serialKey: `agent-settings:${String(event.chatId)}` });
76282
- continue;
77685
+ return;
76283
77686
  }
76284
77687
  if (event.kind === "message.new") {
76285
77688
  const msg = {
@@ -76287,31 +77690,31 @@ Attachment: ${mediaUrl}` : `Attachment: ${mediaUrl}`;
76287
77690
  chatId: event.chatId
76288
77691
  };
76289
77692
  if (msg.out || msg.fromId === meId)
76290
- continue;
77693
+ return;
76291
77694
  if (!claimInlineInboundMessageInstance({
76292
77695
  seen: seenInboundMessageInstances,
76293
77696
  chatId: event.chatId,
76294
77697
  message: msg
76295
77698
  }))
76296
- continue;
77699
+ return;
76297
77700
  if (isInlineAbortRequestMessage(msg, botUsername) && await isAuthorizedInlineAbortMessage({ chatId: event.chatId, msg })) {
76298
77701
  cancelPendingInlineDebounce({ chatId: event.chatId, msg });
76299
77702
  cancelPendingInlineVoiceMessages({ chatId: event.chatId, msg });
76300
77703
  scheduleImmediateInboundMessage({ chatId: event.chatId, msg }, "priority abort dispatch");
76301
- continue;
77704
+ return;
76302
77705
  }
76303
77706
  if (voiceTranscriptWaitMs > 0 && shouldWaitForInlineVoiceTranscript(msg)) {
76304
77707
  holdInlineVoiceMessage({
76305
77708
  chatId: event.chatId,
76306
77709
  msg
76307
77710
  });
76308
- continue;
77711
+ return;
76309
77712
  }
76310
77713
  scheduleInboundMessage({
76311
77714
  chatId: event.chatId,
76312
77715
  msg
76313
77716
  });
76314
- continue;
77717
+ return;
76315
77718
  }
76316
77719
  if (event.kind === "message.edit") {
76317
77720
  const msg = {
@@ -76319,9 +77722,9 @@ Attachment: ${mediaUrl}` : `Attachment: ${mediaUrl}`;
76319
77722
  chatId: event.chatId
76320
77723
  };
76321
77724
  if (msg.out || msg.fromId === meId)
76322
- continue;
77725
+ return;
76323
77726
  if (await handlePendingInlineVoiceEdit({ chatId: event.chatId, msg })) {
76324
- continue;
77727
+ return;
76325
77728
  }
76326
77729
  await queueInlineMessageLifecycleSystemEvent({
76327
77730
  action: "edited",
@@ -76329,7 +77732,7 @@ Attachment: ${mediaUrl}` : `Attachment: ${mediaUrl}`;
76329
77732
  messageIds: [msg.id],
76330
77733
  senderId: msg.fromId
76331
77734
  });
76332
- continue;
77735
+ return;
76333
77736
  }
76334
77737
  if (event.kind === "message.delete") {
76335
77738
  await queueInlineMessageLifecycleSystemEvent({
@@ -76337,18 +77740,18 @@ Attachment: ${mediaUrl}` : `Attachment: ${mediaUrl}`;
76337
77740
  chatId: event.chatId,
76338
77741
  messageIds: event.messageIds
76339
77742
  });
76340
- continue;
77743
+ return;
76341
77744
  }
76342
77745
  if (event.kind === "reaction.add") {
76343
77746
  if (event.reaction.userId === meId)
76344
- continue;
77747
+ return;
76345
77748
  const shouldQueue = await shouldQueueInlineReactionSystemEvent({
76346
77749
  chatId: event.chatId,
76347
77750
  messageId: event.reaction.messageId,
76348
77751
  senderId: event.reaction.userId
76349
77752
  });
76350
77753
  if (!shouldQueue)
76351
- continue;
77754
+ return;
76352
77755
  await queueInlineReactionSystemEvent({
76353
77756
  action: "added",
76354
77757
  chatId: event.chatId,
@@ -76356,18 +77759,18 @@ Attachment: ${mediaUrl}` : `Attachment: ${mediaUrl}`;
76356
77759
  senderId: event.reaction.userId,
76357
77760
  emoji: event.reaction.emoji
76358
77761
  });
76359
- continue;
77762
+ return;
76360
77763
  }
76361
77764
  if (event.kind === "reaction.delete") {
76362
77765
  if (event.userId === meId)
76363
- continue;
77766
+ return;
76364
77767
  const shouldQueue = await shouldQueueInlineReactionSystemEvent({
76365
77768
  chatId: event.chatId,
76366
77769
  messageId: event.messageId,
76367
77770
  senderId: event.userId
76368
77771
  });
76369
77772
  if (!shouldQueue)
76370
- continue;
77773
+ return;
76371
77774
  await queueInlineReactionSystemEvent({
76372
77775
  action: "removed",
76373
77776
  chatId: event.chatId,
@@ -76375,12 +77778,12 @@ Attachment: ${mediaUrl}` : `Attachment: ${mediaUrl}`;
76375
77778
  senderId: event.userId,
76376
77779
  emoji: event.emoji
76377
77780
  });
76378
- continue;
77781
+ return;
76379
77782
  }
76380
77783
  if (rawEvent["kind"] === "chat.participant.add") {
76381
77784
  const eventChatId = rawEvent["chatId"];
76382
77785
  if (!eventChatId)
76383
- continue;
77786
+ return;
76384
77787
  const participant = rawEvent["participant"];
76385
77788
  const eventDate = rawEvent["date"];
76386
77789
  const recovered = await recoverInlineJoinMentions({
@@ -76400,7 +77803,7 @@ Attachment: ${mediaUrl}` : `Attachment: ${mediaUrl}`;
76400
77803
  msg: { ...msg, mentioned: true }
76401
77804
  }, "inline join mention recovery", { serializeWithChat: true });
76402
77805
  }
76403
- continue;
77806
+ return;
76404
77807
  }
76405
77808
  if (rawEvent["kind"] === "message.action.invoke") {
76406
77809
  const actorUserId = rawEvent["actorUserId"];
@@ -76411,10 +77814,10 @@ Attachment: ${mediaUrl}` : `Attachment: ${mediaUrl}`;
76411
77814
  const eventChatId = rawEvent["chatId"];
76412
77815
  const eventDate = rawEvent["date"];
76413
77816
  if (!actorUserId || !interactionId || !actionId || !targetMessageId || !eventChatId || !eventDate || !data) {
76414
- continue;
77817
+ return;
76415
77818
  }
76416
77819
  if (actorUserId === meId)
76417
- continue;
77820
+ return;
76418
77821
  scheduleImmediateInboundMessage({
76419
77822
  chatId: eventChatId,
76420
77823
  msg: {
@@ -76434,9 +77837,9 @@ Attachment: ${mediaUrl}` : `Attachment: ${mediaUrl}`;
76434
77837
  data
76435
77838
  }
76436
77839
  }, "inline action dispatch", { serializeWithChat: true });
76437
- continue;
77840
+ return;
76438
77841
  }
76439
- }
77842
+ });
76440
77843
  } catch (err) {
76441
77844
  publishStatus({ connected: false, lastError: String(err) });
76442
77845
  runtime.error?.(`inline monitor loop crashed: ${String(err)}`);
@@ -76455,6 +77858,7 @@ Attachment: ${mediaUrl}` : `Attachment: ${mediaUrl}`;
76455
77858
  return;
76456
77859
  }
76457
77860
  stopPromise = (async () => {
77861
+ shutdown.abort();
76458
77862
  clearInterval(diagnosticsTimer);
76459
77863
  clearPendingInlineVoiceMessages();
76460
77864
  await client.close().catch(() => {});
@@ -76463,11 +77867,13 @@ Attachment: ${mediaUrl}` : `Attachment: ${mediaUrl}`;
76463
77867
  })();
76464
77868
  await stopPromise;
76465
77869
  };
76466
- abortSignal.addEventListener("abort", () => {
77870
+ params.abortSignal.addEventListener("abort", () => {
76467
77871
  stop();
76468
77872
  }, { once: true });
77873
+ if (params.abortSignal.aborted)
77874
+ stop();
76469
77875
  const done = loop.then(drainInboundTasks, async (error51) => {
76470
- await drainInboundTasks();
77876
+ await stop();
76471
77877
  throw error51;
76472
77878
  });
76473
77879
  return { stop, done };
@@ -77471,6 +78877,11 @@ import {
77471
78877
  normalizeLowercaseStringOrEmpty as normalizeLowercaseStringOrEmpty3,
77472
78878
  normalizeOptionalString as normalizeOptionalString4
77473
78879
  } from "openclaw/plugin-sdk/string-coerce-runtime";
78880
+
78881
+ // src/inline/approval-contract.ts
78882
+ var INLINE_APPROVAL_EVENT_KINDS = ["exec", "plugin", "system-agent"];
78883
+
78884
+ // src/inline/approval-native.ts
77474
78885
  function accountParams(params) {
77475
78886
  return {
77476
78887
  cfg: params.cfg,
@@ -77609,7 +79020,7 @@ var inlineNativeApprovalCapability = createApproverRestrictedNativeApprovalCapab
77609
79020
  resolveApproverDmTargets: resolveInlineApproverDmTargets,
77610
79021
  notifyOriginWhenDmOnly: true,
77611
79022
  nativeRuntime: createLazyChannelApprovalNativeRuntimeAdapter({
77612
- eventKinds: ["exec", "plugin"],
79023
+ eventKinds: INLINE_APPROVAL_EVENT_KINDS,
77613
79024
  isConfigured: ({ cfg, accountId }) => isInlineExecApprovalClientEnabled(accountParams({ cfg, accountId })),
77614
79025
  shouldHandle: ({ cfg, accountId, request }) => shouldHandleInlineExecApprovalRequest(requestParams({ cfg, accountId, request })),
77615
79026
  load: async () => loadBundledEntryExportSync(import.meta.url, {
@@ -77664,6 +79075,22 @@ var inlineNativeApprovalAdapter = splitChannelApprovalCapability(inlineApprovalC
77664
79075
 
77665
79076
  // src/inline/channel.ts
77666
79077
  var activeMonitors = new Map;
79078
+ function inlineErrorMessage(error51) {
79079
+ return error51 instanceof Error ? error51.message : String(error51);
79080
+ }
79081
+ function asInlinePlatformNotDispatched(error51) {
79082
+ if (error51 instanceof PlatformMessageNotDispatchedError)
79083
+ return error51;
79084
+ return new PlatformMessageNotDispatchedError(inlineErrorMessage(error51), { cause: error51 });
79085
+ }
79086
+ function deriveInlineDeliveryRandomId(context) {
79087
+ const queueId = context.deliveryQueueId?.trim();
79088
+ if (!queueId)
79089
+ return;
79090
+ const digest = createHash("sha256").update("openclaw:inline:delivery:v1\x00").update(queueId).update("\x00").update(String(context.deliveryPartIndex ?? 0)).update("\x00").update(String(context.deliverySubpartIndex ?? 0)).digest();
79091
+ const value = digest.readBigInt64BE(0);
79092
+ return value === 0n ? 1n : value;
79093
+ }
77667
79094
  function resolveInlineStatePath(accountId) {
77668
79095
  return path4.join(getInlineRuntime().state.resolveStateDir(), "channels", "inline", `${accountId}.json`);
77669
79096
  }
@@ -77955,7 +79382,7 @@ function resolveInlineSessionTarget(params) {
77955
79382
  const raw = params.id.trim().replace(/^inline:/i, "").trim();
77956
79383
  if (!raw)
77957
79384
  return;
77958
- const target = /^chat:/i.test(raw) ? raw : `chat:${raw}`;
79385
+ const target = /^(?:chat|user):/i.test(raw) ? raw : `chat:${raw}`;
77959
79386
  try {
77960
79387
  return parseInlineExplicitTarget(target)?.to;
77961
79388
  } catch {
@@ -78285,29 +79712,32 @@ async function notifyPairingApprovedInline(params) {
78285
79712
  }
78286
79713
  }
78287
79714
  async function sendMessageInline(params) {
78288
- const account = resolveInlineAccount({ cfg: params.cfg, accountId: params.accountId ?? null });
78289
- if (!account.configured || !account.baseUrl) {
78290
- throw new Error(`Inline not configured for account "${account.accountId}" (missing token or baseUrl)`);
78291
- }
78292
- const token = await resolveInlineToken(account);
78293
- const target = parseInlineOutboundTarget({
78294
- raw: params.to,
78295
- context: "sendText"
78296
- });
78297
- const visibleText = sanitizeInlineVisibleText(params.text);
78298
- if (visibleText.shouldSkip) {
78299
- return {
78300
- messageId: "",
78301
- chatId: target.kind === "user" ? `user:${target.normalizedNumeric}` : target.normalizedNumeric
78302
- };
78303
- }
78304
- const text = sanitizeInlineOutgoingText(visibleText.text);
78305
- const client = new InlineSdkClient({
78306
- baseUrl: account.baseUrl,
78307
- token
78308
- });
78309
- await client.connect();
79715
+ let platformSendStarted = false;
79716
+ let client = null;
78310
79717
  try {
79718
+ const account = resolveInlineAccount({ cfg: params.cfg, accountId: params.accountId ?? null });
79719
+ if (!account.configured || !account.baseUrl) {
79720
+ throw new Error(`Inline not configured for account "${account.accountId}" (missing token or baseUrl)`);
79721
+ }
79722
+ const token = await resolveInlineToken(account);
79723
+ const target = parseInlineOutboundTarget({
79724
+ raw: params.to,
79725
+ context: "sendText"
79726
+ });
79727
+ const visibleText = sanitizeInlineVisibleText(params.text);
79728
+ if (visibleText.shouldSkip) {
79729
+ return {
79730
+ outcome: "not_sent",
79731
+ messageId: "",
79732
+ chatId: target.kind === "user" ? `user:${target.normalizedNumeric}` : target.normalizedNumeric
79733
+ };
79734
+ }
79735
+ const text = sanitizeInlineOutgoingText(visibleText.text);
79736
+ client = new InlineSdkClient({
79737
+ baseUrl: account.baseUrl,
79738
+ token
79739
+ });
79740
+ await client.connect(params.signal);
78311
79741
  const replyToMsgId = parseInlineId2(params.replyToId);
78312
79742
  const resolvedTarget = await resolveInlineOutboundTarget({
78313
79743
  client,
@@ -78320,12 +79750,20 @@ async function sendMessageInline(params) {
78320
79750
  parentChatId: resolvedTarget.targetId,
78321
79751
  threadId: params.threadId ?? null
78322
79752
  }) : null;
79753
+ const randomId = deriveInlineDeliveryRandomId(params);
79754
+ params.signal?.throwIfAborted();
79755
+ await params.onPlatformSendDispatch?.();
79756
+ params.signal?.throwIfAborted();
79757
+ params.assertDirectAdapterHandoff?.();
79758
+ platformSendStarted = true;
78323
79759
  const result = await client.sendMessage({
78324
79760
  ...effectiveChatId != null ? { chatId: effectiveChatId } : buildInlineSendTarget(resolvedTarget),
78325
79761
  text,
79762
+ ...randomId != null ? { randomId } : {},
78326
79763
  ...params.actions !== undefined ? { actions: params.actions } : {},
78327
79764
  ...replyToMsgId != null ? { replyToMsgId } : {},
78328
- parseMarkdown: account.config.parseMarkdown ?? true
79765
+ parseMarkdown: account.config.parseMarkdown ?? true,
79766
+ ...params.silent ? { sendMode: "silent" } : {}
78329
79767
  }).catch((error51) => {
78330
79768
  throw wrapInlineTargetError({
78331
79769
  error: error51,
@@ -78334,7 +79772,6 @@ async function sendMessageInline(params) {
78334
79772
  resolvedTarget
78335
79773
  });
78336
79774
  });
78337
- const bestEffort = result.messageId != null ? String(result.messageId) : BigInt(Date.now()).toString();
78338
79775
  if (resolvedTarget.kind === "chat") {
78339
79776
  recordInlineOutboundThreadParticipation({
78340
79777
  accountId: account.accountId,
@@ -78344,32 +79781,38 @@ async function sendMessageInline(params) {
78344
79781
  });
78345
79782
  }
78346
79783
  return {
78347
- messageId: bestEffort,
79784
+ messageId: result.messageId != null ? String(result.messageId) : "",
78348
79785
  chatId: effectiveChatId != null ? String(effectiveChatId) : formatInlineResultChatId(resolvedTarget)
78349
79786
  };
79787
+ } catch (error51) {
79788
+ if (!platformSendStarted)
79789
+ throw asInlinePlatformNotDispatched(error51);
79790
+ throw error51;
78350
79791
  } finally {
78351
- await client.close().catch(() => {});
79792
+ await client?.close().catch(() => {});
78352
79793
  }
78353
79794
  }
78354
79795
  async function sendMediaInline(params) {
78355
- const account = resolveInlineAccount({ cfg: params.cfg, accountId: params.accountId ?? null });
78356
- if (!account.configured || !account.baseUrl) {
78357
- throw new Error(`Inline not configured for account "${account.accountId}" (missing token or baseUrl)`);
78358
- }
78359
- const token = await resolveInlineToken(account);
78360
- const target = parseInlineOutboundTarget({
78361
- raw: params.to,
78362
- context: "sendMedia"
78363
- });
78364
- const replyToMsgId = parseInlineId2(params.replyToId);
78365
- const visibleText = sanitizeInlineVisibleText(params.text);
78366
- const caption = visibleText.shouldSkip ? "" : sanitizeInlineOutgoingText(visibleText.text).trim();
78367
- const client = new InlineSdkClient({
78368
- baseUrl: account.baseUrl,
78369
- token
78370
- });
78371
- await client.connect();
79796
+ let platformSendStarted = false;
79797
+ let client = null;
78372
79798
  try {
79799
+ const account = resolveInlineAccount({ cfg: params.cfg, accountId: params.accountId ?? null });
79800
+ if (!account.configured || !account.baseUrl) {
79801
+ throw new Error(`Inline not configured for account "${account.accountId}" (missing token or baseUrl)`);
79802
+ }
79803
+ const token = await resolveInlineToken(account);
79804
+ const target = parseInlineOutboundTarget({
79805
+ raw: params.to,
79806
+ context: "sendMedia"
79807
+ });
79808
+ const replyToMsgId = parseInlineId2(params.replyToId);
79809
+ const visibleText = sanitizeInlineVisibleText(params.text);
79810
+ const caption = visibleText.shouldSkip ? "" : sanitizeInlineOutgoingText(visibleText.text).trim();
79811
+ client = new InlineSdkClient({
79812
+ baseUrl: account.baseUrl,
79813
+ token
79814
+ });
79815
+ await client.connect(params.signal);
78373
79816
  const resolvedTarget = await resolveInlineOutboundTarget({
78374
79817
  client,
78375
79818
  context: "sendMedia",
@@ -78388,15 +79831,24 @@ async function sendMediaInline(params) {
78388
79831
  mediaUrl: params.mediaUrl,
78389
79832
  ...params.mediaAccess ? { mediaAccess: params.mediaAccess } : {},
78390
79833
  ...params.mediaLocalRoots ? { mediaLocalRoots: params.mediaLocalRoots } : {},
78391
- ...params.mediaReadFile ? { mediaReadFile: params.mediaReadFile } : {}
79834
+ ...params.mediaReadFile ? { mediaReadFile: params.mediaReadFile } : {},
79835
+ ...params.signal ? { signal: params.signal } : {}
78392
79836
  });
79837
+ const randomId = deriveInlineDeliveryRandomId(params);
79838
+ params.signal?.throwIfAborted();
79839
+ await params.onPlatformSendDispatch?.();
79840
+ params.signal?.throwIfAborted();
79841
+ params.assertDirectAdapterHandoff?.();
79842
+ platformSendStarted = true;
78393
79843
  const result = await client.sendMessage({
78394
79844
  ...effectiveChatId != null ? { chatId: effectiveChatId } : buildInlineSendTarget(resolvedTarget),
78395
79845
  ...caption ? { text: caption } : {},
78396
79846
  media,
79847
+ ...randomId != null ? { randomId } : {},
78397
79848
  ...params.actions !== undefined ? { actions: params.actions } : {},
78398
79849
  ...replyToMsgId != null ? { replyToMsgId } : {},
78399
- ...caption ? { parseMarkdown: account.config.parseMarkdown ?? true } : {}
79850
+ ...caption ? { parseMarkdown: account.config.parseMarkdown ?? true } : {},
79851
+ ...params.silent ? { sendMode: "silent" } : {}
78400
79852
  }).catch((error51) => {
78401
79853
  throw wrapInlineTargetError({
78402
79854
  error: error51,
@@ -78405,7 +79857,6 @@ async function sendMediaInline(params) {
78405
79857
  resolvedTarget
78406
79858
  });
78407
79859
  });
78408
- const bestEffort = result.messageId != null ? String(result.messageId) : BigInt(Date.now()).toString();
78409
79860
  if (resolvedTarget.kind === "chat") {
78410
79861
  recordInlineOutboundThreadParticipation({
78411
79862
  accountId: account.accountId,
@@ -78415,11 +79866,15 @@ async function sendMediaInline(params) {
78415
79866
  });
78416
79867
  }
78417
79868
  return {
78418
- messageId: bestEffort,
79869
+ messageId: result.messageId != null ? String(result.messageId) : "",
78419
79870
  chatId: effectiveChatId != null ? String(effectiveChatId) : formatInlineResultChatId(resolvedTarget)
78420
79871
  };
79872
+ } catch (error51) {
79873
+ if (!platformSendStarted)
79874
+ throw asInlinePlatformNotDispatched(error51);
79875
+ throw error51;
78421
79876
  } finally {
78422
- await client.close().catch(() => {});
79877
+ await client?.close().catch(() => {});
78423
79878
  }
78424
79879
  }
78425
79880
  function resolveDirectoryLimit(limit) {
@@ -78523,8 +79978,22 @@ var resolveInlineAllowlistGroupOverrides = createFlatAllowlistOverrideResolver({
78523
79978
  label: (key2) => key2,
78524
79979
  resolveEntries: (value) => value?.allowFrom
78525
79980
  });
79981
+ var inlineDurableFinalDeliveryCapabilities = {
79982
+ text: true,
79983
+ media: true,
79984
+ payload: true,
79985
+ silent: true,
79986
+ replyTo: true,
79987
+ thread: true,
79988
+ nativeQuote: false,
79989
+ messageSendingHooks: true,
79990
+ batch: true
79991
+ };
78526
79992
  var inlineOutbound = {
78527
79993
  deliveryMode: "direct",
79994
+ deliveryCapabilities: {
79995
+ durableFinal: inlineDurableFinalDeliveryCapabilities
79996
+ },
78528
79997
  targetsMatchForReplySuppression: ({ originTarget, targetKey, targetThreadId }) => {
78529
79998
  const origin = resolveInlineSessionTarget({ id: originTarget });
78530
79999
  const destination = resolveInlineSessionTarget({ id: targetThreadId ?? targetKey });
@@ -78557,17 +80026,25 @@ var inlineOutbound = {
78557
80026
  ...interactive ? { interactive } : {}
78558
80027
  };
78559
80028
  },
78560
- sendPayload: async ({
78561
- cfg,
78562
- to,
78563
- payload,
78564
- accountId,
78565
- replyToId,
78566
- threadId,
78567
- mediaAccess,
78568
- mediaLocalRoots,
78569
- mediaReadFile
78570
- }) => {
80029
+ sendPayload: async (context) => {
80030
+ const {
80031
+ cfg,
80032
+ to,
80033
+ payload,
80034
+ accountId,
80035
+ replyToId,
80036
+ threadId,
80037
+ mediaAccess,
80038
+ mediaLocalRoots,
80039
+ mediaReadFile,
80040
+ silent,
80041
+ deliveryQueueId,
80042
+ deliveryPartIndex,
80043
+ onPlatformSendDispatch,
80044
+ assertDirectAdapterHandoff,
80045
+ onDeliveryResult
80046
+ } = context;
80047
+ const { signal } = context;
78571
80048
  const text = resolveInlineInteractiveTextFallback({
78572
80049
  text: payload.text ?? undefined,
78573
80050
  interactive: payload.interactive,
@@ -78576,7 +80053,7 @@ var inlineOutbound = {
78576
80053
  const payloadReplyToId = typeof payload.replyToId === "string" ? payload.replyToId.trim() : null;
78577
80054
  const effectiveReplyToId = payloadReplyToId || replyToId || null;
78578
80055
  const actions = resolveInlinePayloadActions(payload);
78579
- const mediaUrls = payload.mediaUrls?.length ? payload.mediaUrls : payload.mediaUrl ? [payload.mediaUrl] : [];
80056
+ const mediaUrls = ((payload.mediaUrls?.length) ? payload.mediaUrls : payload.mediaUrl ? [payload.mediaUrl] : []).map((url2) => url2.trim()).filter(Boolean);
78580
80057
  if (mediaUrls.length === 0) {
78581
80058
  const result = await sendMessageInline({
78582
80059
  cfg,
@@ -78585,17 +80062,32 @@ var inlineOutbound = {
78585
80062
  actions,
78586
80063
  accountId: accountId ?? null,
78587
80064
  replyToId: effectiveReplyToId,
78588
- threadId: threadId ?? null
80065
+ threadId: threadId ?? null,
80066
+ silent,
80067
+ signal,
80068
+ deliveryQueueId,
80069
+ deliveryPartIndex,
80070
+ onPlatformSendDispatch,
80071
+ assertDirectAdapterHandoff
78589
80072
  });
78590
- return { channel: "inline", to, messageId: result.messageId, chatId: result.chatId };
80073
+ const delivery = {
80074
+ ...result.outcome ? { outcome: result.outcome } : {},
80075
+ channel: "inline",
80076
+ to,
80077
+ messageId: result.messageId,
80078
+ chatId: result.chatId
80079
+ };
80080
+ if (result.outcome !== "not_sent")
80081
+ await onDeliveryResult?.(delivery);
80082
+ return delivery;
78591
80083
  }
78592
- let finalResult = null;
80084
+ const deliveries = [];
78593
80085
  for (let index = 0;index < mediaUrls.length; index += 1) {
78594
80086
  const mediaUrl = mediaUrls[index];
78595
- if (!mediaUrl?.trim())
80087
+ if (!mediaUrl)
78596
80088
  continue;
78597
80089
  const isFirst = index === 0;
78598
- finalResult = await sendMediaInline({
80090
+ const result = await sendMediaInline({
78599
80091
  cfg,
78600
80092
  to,
78601
80093
  text: isFirst ? text : "",
@@ -78606,9 +80098,25 @@ var inlineOutbound = {
78606
80098
  threadId: threadId ?? null,
78607
80099
  ...mediaAccess ? { mediaAccess } : {},
78608
80100
  ...mediaLocalRoots ? { mediaLocalRoots } : {},
78609
- ...mediaReadFile ? { mediaReadFile } : {}
80101
+ ...mediaReadFile ? { mediaReadFile } : {},
80102
+ silent,
80103
+ signal,
80104
+ deliveryQueueId,
80105
+ deliveryPartIndex,
80106
+ deliverySubpartIndex: index,
80107
+ onPlatformSendDispatch,
80108
+ assertDirectAdapterHandoff
78610
80109
  });
80110
+ const delivery = {
80111
+ channel: "inline",
80112
+ to,
80113
+ messageId: result.messageId,
80114
+ chatId: result.chatId
80115
+ };
80116
+ deliveries.push(delivery);
80117
+ await onDeliveryResult?.(delivery);
78611
80118
  }
80119
+ const finalResult = deliveries.at(-1);
78612
80120
  if (!finalResult) {
78613
80121
  const result = await sendMessageInline({
78614
80122
  cfg,
@@ -78617,35 +80125,98 @@ var inlineOutbound = {
78617
80125
  actions,
78618
80126
  accountId: accountId ?? null,
78619
80127
  replyToId: effectiveReplyToId,
78620
- threadId: threadId ?? null
80128
+ threadId: threadId ?? null,
80129
+ silent,
80130
+ signal,
80131
+ deliveryQueueId,
80132
+ deliveryPartIndex,
80133
+ onPlatformSendDispatch,
80134
+ assertDirectAdapterHandoff
78621
80135
  });
78622
- return { channel: "inline", to, messageId: result.messageId, chatId: result.chatId };
78623
- }
78624
- return { channel: "inline", to, messageId: finalResult.messageId, chatId: finalResult.chatId };
80136
+ const delivery = {
80137
+ ...result.outcome ? { outcome: result.outcome } : {},
80138
+ channel: "inline",
80139
+ to,
80140
+ messageId: result.messageId,
80141
+ chatId: result.chatId
80142
+ };
80143
+ if (result.outcome !== "not_sent")
80144
+ await onDeliveryResult?.(delivery);
80145
+ return delivery;
80146
+ }
80147
+ const receipt = createMessageReceiptFromOutboundResults({
80148
+ results: deliveries,
80149
+ kind: "media",
80150
+ ...threadId != null ? { threadId: String(threadId) } : {},
80151
+ ...effectiveReplyToId ? { replyToId: effectiveReplyToId } : {}
80152
+ });
80153
+ return {
80154
+ ...finalResult,
80155
+ messageId: receipt.primaryPlatformMessageId ?? finalResult.messageId,
80156
+ receipt
80157
+ };
78625
80158
  },
78626
- sendText: async ({ cfg, to, text, accountId, replyToId, threadId }) => {
80159
+ sendText: async (context) => {
80160
+ const {
80161
+ cfg,
80162
+ to,
80163
+ text,
80164
+ accountId,
80165
+ replyToId,
80166
+ threadId,
80167
+ silent,
80168
+ deliveryQueueId,
80169
+ deliveryPartIndex,
80170
+ onPlatformSendDispatch,
80171
+ assertDirectAdapterHandoff,
80172
+ onDeliveryResult
80173
+ } = context;
80174
+ const { signal } = context;
78627
80175
  const result = await sendMessageInline({
78628
80176
  cfg,
78629
80177
  to,
78630
80178
  text,
78631
80179
  accountId: accountId ?? null,
78632
80180
  replyToId: replyToId ?? null,
78633
- threadId: threadId ?? null
80181
+ threadId: threadId ?? null,
80182
+ silent,
80183
+ signal,
80184
+ deliveryQueueId,
80185
+ deliveryPartIndex,
80186
+ onPlatformSendDispatch,
80187
+ assertDirectAdapterHandoff
78634
80188
  });
78635
- return { channel: "inline", to, messageId: result.messageId, chatId: result.chatId };
80189
+ const delivery = {
80190
+ ...result.outcome ? { outcome: result.outcome } : {},
80191
+ channel: "inline",
80192
+ to,
80193
+ messageId: result.messageId,
80194
+ chatId: result.chatId
80195
+ };
80196
+ if (result.outcome !== "not_sent")
80197
+ await onDeliveryResult?.(delivery);
80198
+ return delivery;
78636
80199
  },
78637
- sendMedia: async ({
78638
- cfg,
78639
- to,
78640
- text,
78641
- mediaUrl,
78642
- accountId,
78643
- replyToId,
78644
- threadId,
78645
- mediaAccess,
78646
- mediaLocalRoots,
78647
- mediaReadFile
78648
- }) => {
80200
+ sendMedia: async (context) => {
80201
+ const {
80202
+ cfg,
80203
+ to,
80204
+ text,
80205
+ mediaUrl,
80206
+ accountId,
80207
+ replyToId,
80208
+ threadId,
80209
+ mediaAccess,
80210
+ mediaLocalRoots,
80211
+ mediaReadFile,
80212
+ silent,
80213
+ deliveryQueueId,
80214
+ deliveryPartIndex,
80215
+ onPlatformSendDispatch,
80216
+ assertDirectAdapterHandoff,
80217
+ onDeliveryResult
80218
+ } = context;
80219
+ const { signal } = context;
78649
80220
  if (!mediaUrl) {
78650
80221
  const result2 = await sendMessageInline({
78651
80222
  cfg,
@@ -78653,9 +80224,24 @@ var inlineOutbound = {
78653
80224
  text,
78654
80225
  accountId: accountId ?? null,
78655
80226
  replyToId: replyToId ?? null,
78656
- threadId: threadId ?? null
80227
+ threadId: threadId ?? null,
80228
+ silent,
80229
+ signal,
80230
+ deliveryQueueId,
80231
+ deliveryPartIndex,
80232
+ onPlatformSendDispatch,
80233
+ assertDirectAdapterHandoff
78657
80234
  });
78658
- return { channel: "inline", to, messageId: result2.messageId, chatId: result2.chatId };
80235
+ const delivery2 = {
80236
+ ...result2.outcome ? { outcome: result2.outcome } : {},
80237
+ channel: "inline",
80238
+ to,
80239
+ messageId: result2.messageId,
80240
+ chatId: result2.chatId
80241
+ };
80242
+ if (result2.outcome !== "not_sent")
80243
+ await onDeliveryResult?.(delivery2);
80244
+ return delivery2;
78659
80245
  }
78660
80246
  const result = await sendMediaInline({
78661
80247
  cfg,
@@ -78667,9 +80253,22 @@ var inlineOutbound = {
78667
80253
  threadId: threadId ?? null,
78668
80254
  ...mediaAccess ? { mediaAccess } : {},
78669
80255
  ...mediaLocalRoots ? { mediaLocalRoots } : {},
78670
- ...mediaReadFile ? { mediaReadFile } : {}
80256
+ ...mediaReadFile ? { mediaReadFile } : {},
80257
+ silent,
80258
+ signal,
80259
+ deliveryQueueId,
80260
+ deliveryPartIndex,
80261
+ onPlatformSendDispatch,
80262
+ assertDirectAdapterHandoff
78671
80263
  });
78672
- return { channel: "inline", to, messageId: result.messageId, chatId: result.chatId };
80264
+ const delivery = {
80265
+ channel: "inline",
80266
+ to,
80267
+ messageId: result.messageId,
80268
+ chatId: result.chatId
80269
+ };
80270
+ await onDeliveryResult?.(delivery);
80271
+ return delivery;
78673
80272
  }
78674
80273
  };
78675
80274
  function toInlineMessageBridgeResult(result) {
@@ -78688,21 +80287,31 @@ function toInlineMessageBridgeResult(result) {
78688
80287
  var inlineMessageAdapter = createChannelMessageAdapterFromOutbound({
78689
80288
  id: "inline",
78690
80289
  outbound: {
78691
- sendText: async ({ onDeliveryResult, ...ctx }) => {
78692
- const result = toInlineMessageBridgeResult(await inlineOutbound.sendText(ctx));
78693
- await onDeliveryResult?.(result);
78694
- return result;
78695
- },
78696
- sendMedia: async ({ onDeliveryResult, ...ctx }) => {
78697
- const result = toInlineMessageBridgeResult(await inlineOutbound.sendMedia(ctx));
78698
- await onDeliveryResult?.(result);
78699
- return result;
78700
- },
78701
- sendPayload: async ({ onDeliveryResult, ...ctx }) => {
78702
- const result = toInlineMessageBridgeResult(await inlineOutbound.sendPayload(ctx));
78703
- await onDeliveryResult?.(result);
78704
- return result;
78705
- }
80290
+ deliveryCapabilities: { durableFinal: inlineDurableFinalDeliveryCapabilities },
80291
+ sendText: async ({ onDeliveryResult, ...ctx }) => toInlineMessageBridgeResult(await inlineOutbound.sendText({
80292
+ ...ctx,
80293
+ ...onDeliveryResult ? {
80294
+ onDeliveryResult: async (result) => {
80295
+ await onDeliveryResult(toInlineMessageBridgeResult(result));
80296
+ }
80297
+ } : {}
80298
+ })),
80299
+ sendMedia: async ({ onDeliveryResult, ...ctx }) => toInlineMessageBridgeResult(await inlineOutbound.sendMedia({
80300
+ ...ctx,
80301
+ ...onDeliveryResult ? {
80302
+ onDeliveryResult: async (result) => {
80303
+ await onDeliveryResult(toInlineMessageBridgeResult(result));
80304
+ }
80305
+ } : {}
80306
+ })),
80307
+ sendPayload: async ({ onDeliveryResult, ...ctx }) => toInlineMessageBridgeResult(await inlineOutbound.sendPayload({
80308
+ ...ctx,
80309
+ ...onDeliveryResult ? {
80310
+ onDeliveryResult: async (result) => {
80311
+ await onDeliveryResult(toInlineMessageBridgeResult(result));
80312
+ }
80313
+ } : {}
80314
+ }))
78706
80315
  },
78707
80316
  live: {
78708
80317
  capabilities: {
@@ -79269,280 +80878,11 @@ var inlineChannelPlugin = {
79269
80878
  }
79270
80879
  };
79271
80880
 
79272
- // src/telemetry.ts
79273
- import { randomUUID as randomUUID2 } from "node:crypto";
79274
- import { readFile as readFile2 } from "node:fs/promises";
79275
- var TELEMETRY_TIMEOUT_MS = 2000;
79276
- var TELEMETRY_DEDUP_MS = 5 * 60000;
79277
- var MAX_ERROR_MESSAGE_LENGTH = 8000;
79278
- var MAX_STACK_FRAMES = 80;
79279
- var SENSITIVE_ENV_NAME = /(?:token|secret|password|api[_-]?key|authorization)/i;
79280
- var lastReports = new Map;
79281
- var releasePromise;
79282
- function telemetryDisabled(env = process.env) {
79283
- const disabled = (value) => value != null && ["1", "true", "yes", "on"].includes(value.trim().toLowerCase());
79284
- const optedOut = (value) => value != null && ["0", "false", "off"].includes(value.trim().toLowerCase());
79285
- return disabled(env.DO_NOT_TRACK) || optedOut(env.INLINE_PLUGIN_TELEMETRY);
79286
- }
79287
- function resolveDsn(env = process.env) {
79288
- if (telemetryDisabled(env))
79289
- return "";
79290
- return env.INLINE_OPENCLAW_SENTRY_DSN?.trim() ?? "";
79291
- }
79292
- function sensitiveValues(env = process.env) {
79293
- return Object.entries(env).filter(([name, value]) => SENSITIVE_ENV_NAME.test(name) && (value?.length ?? 0) >= 8).map(([, value]) => value);
79294
- }
79295
- function redactOpenClawTelemetryText(value, env = process.env) {
79296
- let text = String(value ?? "").replace(/\b(Authorization\s*[:=]\s*)(?:Basic|Bearer)\s+\S+/gi, "$1[REDACTED]").replace(/\b((?:Basic|Bearer)\s+)\S+/gi, "$1[REDACTED]").replace(/(https?:\/\/)[^/\s:@]+:[^@\s/]+@/gi, "$1[REDACTED]@").replace(/([?&](?:access_token|auth|authorization|key|password|secret|token)[^=\s&]*)=([^&\s]+)/gi, "$1=[REDACTED]").replace(/\b([A-Za-z0-9_-]*(?:token|secret|password|api[_-]?key|authorization)[A-Za-z0-9_-]*)\s*([=:])\s*\S+/gi, "$1$2[REDACTED]");
79297
- for (const secret of sensitiveValues(env)) {
79298
- text = text.replaceAll(secret, "[REDACTED]");
79299
- }
79300
- return text.slice(0, MAX_ERROR_MESSAGE_LENGTH);
79301
- }
79302
- function safeTag(value) {
79303
- const normalized = value.trim().toLowerCase();
79304
- return normalized.length > 0 && normalized.length <= 80 && /^[a-z0-9._-]+$/.test(normalized) ? normalized : "unknown";
79305
- }
79306
- function parseStack(error51, env) {
79307
- const stack = error51.stack ?? "";
79308
- const frames = [];
79309
- for (const rawLine of stack.split(`
79310
- `).slice(1)) {
79311
- const line = redactOpenClawTelemetryText(rawLine.trim(), env);
79312
- const match = /^at\s+(?:(.*?)\s+\()?(.+?):(\d+):(\d+)\)?$/.exec(line);
79313
- if (!match)
79314
- continue;
79315
- const filename = match[2];
79316
- const frame = {
79317
- filename,
79318
- abs_path: filename,
79319
- function: match[1] || "<anonymous>",
79320
- lineno: Number(match[3]),
79321
- colno: Number(match[4]),
79322
- in_app: filename.includes("@inline-openclaw/inline") || filename.includes("/openclaw/") || /\/(?:channel-plugin-api|runtime-register-api|index)\.js$/.test(filename)
79323
- };
79324
- frames.push(frame);
79325
- if (frames.length >= MAX_STACK_FRAMES)
79326
- break;
79327
- }
79328
- return frames.reverse();
79329
- }
79330
- function buildOpenClawTelemetryEvent(operation, error51, options = {}) {
79331
- const env = options.env ?? process.env;
79332
- const exception = error51 instanceof Error ? error51 : new Error(String(error51 ?? "Unknown error"));
79333
- const frames = parseStack(exception, env);
79334
- return {
79335
- event_id: randomUUID2().replaceAll("-", ""),
79336
- timestamp: new Date().toISOString(),
79337
- platform: "javascript",
79338
- level: "error",
79339
- logger: "inline.openclaw.plugin",
79340
- exception: {
79341
- values: [{
79342
- type: redactOpenClawTelemetryText(exception.name || "Error", env),
79343
- value: redactOpenClawTelemetryText(exception.message || String(error51), env),
79344
- mechanism: {
79345
- type: "inline_plugin_boundary",
79346
- handled: options.handled ?? true
79347
- },
79348
- ...frames.length > 0 ? { stacktrace: { frames } } : {}
79349
- }]
79350
- },
79351
- tags: {
79352
- operation: safeTag(operation),
79353
- runtime: "node",
79354
- os: process.platform,
79355
- arch: process.arch
79356
- },
79357
- sdk: { name: "inline.plugin.telemetry", version: "1" }
79358
- };
79359
- }
79360
- async function resolveRelease() {
79361
- releasePromise ??= (async () => {
79362
- try {
79363
- const parsed = JSON.parse(await readFile2(new URL("../package.json", import.meta.url), "utf8"));
79364
- if (typeof parsed.version === "string" && parsed.version.trim()) {
79365
- return `inline-openclaw-plugin@${parsed.version.trim()}`;
79366
- }
79367
- } catch {}
79368
- return;
79369
- })();
79370
- return releasePromise;
79371
- }
79372
- function parseSentryDsn(dsn) {
79373
- try {
79374
- const parsed = new URL(dsn);
79375
- if (!/^https?:$/.test(parsed.protocol) || !parsed.username)
79376
- return null;
79377
- const parts = parsed.pathname.split("/").filter(Boolean);
79378
- const projectId = parts.pop();
79379
- if (!projectId || !/^\d+$/.test(projectId))
79380
- return null;
79381
- const prefix = parts.length > 0 ? `/${parts.join("/")}` : "";
79382
- return {
79383
- endpoint: `${parsed.origin}${prefix}/api/${projectId}/envelope/`,
79384
- publicKey: parsed.username
79385
- };
79386
- } catch {
79387
- return null;
79388
- }
79389
- }
79390
- async function sendOpenClawPluginError(operation, error51, options = {}) {
79391
- const env = options.env ?? process.env;
79392
- const dsn = resolveDsn(env);
79393
- const target = parseSentryDsn(dsn);
79394
- if (!target)
79395
- return false;
79396
- const event = buildOpenClawTelemetryEvent(operation, error51, options);
79397
- const release = await resolveRelease();
79398
- if (release)
79399
- event.release = release;
79400
- const envelope = [
79401
- JSON.stringify({ event_id: event.event_id, dsn, sent_at: event.timestamp }),
79402
- JSON.stringify({ type: "event", content_type: "application/json" }),
79403
- JSON.stringify(event)
79404
- ].join(`
79405
- `);
79406
- const controller = new AbortController;
79407
- const timeout = setTimeout(() => controller.abort(), TELEMETRY_TIMEOUT_MS);
79408
- timeout.unref?.();
79409
- try {
79410
- const response = await fetch(target.endpoint, {
79411
- method: "POST",
79412
- headers: {
79413
- "content-type": "application/x-sentry-envelope",
79414
- "x-sentry-auth": `Sentry sentry_version=7, sentry_key=${target.publicKey}, sentry_client=inline.plugin.telemetry/1`
79415
- },
79416
- body: envelope,
79417
- signal: controller.signal
79418
- });
79419
- return response.ok;
79420
- } catch {
79421
- return false;
79422
- } finally {
79423
- clearTimeout(timeout);
79424
- }
79425
- }
79426
- function reportOpenClawPluginError(operation, error51, options = {}) {
79427
- try {
79428
- const exception = error51 instanceof Error ? error51 : new Error(String(error51 ?? "Unknown error"));
79429
- const key2 = `${safeTag(operation)}\x00${exception.name}\x00${redactOpenClawTelemetryText(exception.message)}`;
79430
- const now = Date.now();
79431
- if (now - (lastReports.get(key2) ?? 0) < TELEMETRY_DEDUP_MS)
79432
- return;
79433
- lastReports.set(key2, now);
79434
- sendOpenClawPluginError(operation, exception, options).catch(() => {});
79435
- } catch {}
79436
- }
79437
- function wrapCallback(operation, callback) {
79438
- return function(...args) {
79439
- try {
79440
- const result = Reflect.apply(callback, this, args);
79441
- if (result && typeof result.then === "function") {
79442
- return Promise.resolve(result).catch((error51) => {
79443
- reportOpenClawPluginError(operation, error51);
79444
- throw error51;
79445
- });
79446
- }
79447
- return result;
79448
- } catch (error51) {
79449
- reportOpenClawPluginError(operation, error51);
79450
- throw error51;
79451
- }
79452
- };
79453
- }
79454
- function wrapSurface(prefix, surface) {
79455
- const wrapped = { ...surface };
79456
- for (const [name, member] of Object.entries(wrapped)) {
79457
- if (typeof member === "function") {
79458
- wrapped[name] = wrapCallback(`${prefix}.${name}`, member);
79459
- }
79460
- }
79461
- return wrapped;
79462
- }
79463
- function instrumentToolValue(value) {
79464
- if (Array.isArray(value))
79465
- return value.map(instrumentToolValue);
79466
- if (!value || typeof value !== "object")
79467
- return value;
79468
- const tool = value;
79469
- const execute = tool.execute;
79470
- if (typeof execute !== "function")
79471
- return value;
79472
- const name = typeof tool.name === "string" ? safeTag(tool.name) : "unknown";
79473
- return new Proxy(tool, {
79474
- get(target, property, receiver) {
79475
- if (property === "execute") {
79476
- return wrapCallback(`tool.${name}`, execute);
79477
- }
79478
- return Reflect.get(target, property, receiver);
79479
- }
79480
- });
79481
- }
79482
- function instrumentOpenClawPluginApi(value) {
79483
- const api2 = value;
79484
- return new Proxy(api2, {
79485
- get(target, property, receiver) {
79486
- const member = Reflect.get(target, property, receiver);
79487
- if (property === "registerTool" && typeof member === "function") {
79488
- return (toolOrFactory, options) => {
79489
- const wrapped = typeof toolOrFactory === "function" ? wrapCallback("tool.factory", (...args) => instrumentToolValue(Reflect.apply(toolOrFactory, undefined, args))) : instrumentToolValue(toolOrFactory);
79490
- return Reflect.apply(member, target, [wrapped, options]);
79491
- };
79492
- }
79493
- if (property === "registerCommand" && typeof member === "function") {
79494
- return (command) => {
79495
- const handler = command.handler;
79496
- const name = typeof command.name === "string" ? safeTag(command.name) : "unknown";
79497
- const wrapped = typeof handler === "function" ? { ...command, handler: wrapCallback(`command.${name}`, handler) } : command;
79498
- return Reflect.apply(member, target, [wrapped]);
79499
- };
79500
- }
79501
- if (property === "on" && typeof member === "function") {
79502
- return (event, handler) => Reflect.apply(member, target, [event, wrapCallback(`hook.${safeTag(event)}`, handler)]);
79503
- }
79504
- return member;
79505
- }
79506
- });
79507
- }
79508
- function instrumentOpenClawChannelPlugin(value) {
79509
- const plugin = { ...value };
79510
- for (const name of [
79511
- "lifecycle",
79512
- "pairing",
79513
- "outbound",
79514
- "heartbeat",
79515
- "directory",
79516
- "resolver",
79517
- "allowlist",
79518
- "status",
79519
- "gateway"
79520
- ]) {
79521
- const surface = plugin[name];
79522
- if (surface && typeof surface === "object") {
79523
- plugin[name] = wrapSurface(name, surface);
79524
- }
79525
- }
79526
- const message = plugin.message;
79527
- if (message && typeof message === "object") {
79528
- const wrappedMessage = { ...message };
79529
- const send = wrappedMessage.send;
79530
- if (send && typeof send === "object") {
79531
- wrappedMessage.send = wrapSurface("message.send", send);
79532
- }
79533
- plugin.message = wrappedMessage;
79534
- }
79535
- return plugin;
79536
- }
79537
- function reportOpenClawRegistrationError(error51) {
79538
- reportOpenClawPluginError("plugin.register", error51, { handled: false });
79539
- }
79540
-
79541
80881
  // src/channel-plugin-api.ts
79542
80882
  var inlineChannelPlugin2 = instrumentOpenClawChannelPlugin(inlineChannelPlugin);
79543
80883
  export {
79544
80884
  inlineChannelPlugin2 as inlineChannelPlugin
79545
80885
  };
79546
80886
 
79547
- //# debugId=0CD7141E321D85A264756E2164756E21
80887
+ //# debugId=EEDCDD547EBF16D364756E2164756E21
79548
80888
  //# sourceMappingURL=channel-plugin-api.js.map