@inline-openclaw/inline 0.0.28 → 0.0.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.js +1554 -1138
- package/dist/index.js.map +15 -16
- package/dist/inline/actions.d.ts.map +1 -1
- package/dist/inline/bot-commands-api.d.ts.map +1 -1
- package/dist/inline/bot-commands-sync.d.ts.map +1 -1
- package/dist/inline/channel.d.ts.map +1 -1
- package/dist/inline/monitor.d.ts +1 -0
- package/dist/inline/monitor.d.ts.map +1 -1
- package/dist/inline/status-issues.d.ts.map +1 -1
- package/dist/sdk-runtime-compat.d.ts +0 -26
- package/dist/sdk-runtime-compat.d.ts.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -4
- package/dist/inline/command-menu-compat.d.ts +0 -24
- package/dist/inline/command-menu-compat.d.ts.map +0 -1
package/dist/index.js
CHANGED
|
@@ -5837,7 +5837,8 @@ class ConnectionInit$Type extends import_runtime4.MessageType {
|
|
|
5837
5837
|
{ no: 1, name: "token", kind: "scalar", T: 9 },
|
|
5838
5838
|
{ no: 2, name: "build_number", kind: "scalar", opt: true, T: 5 },
|
|
5839
5839
|
{ no: 3, name: "layer", kind: "scalar", opt: true, T: 13 },
|
|
5840
|
-
{ no: 4, name: "client_version", kind: "scalar", opt: true, T: 9 }
|
|
5840
|
+
{ no: 4, name: "client_version", kind: "scalar", opt: true, T: 9 },
|
|
5841
|
+
{ no: 5, name: "os_version", kind: "scalar", opt: true, T: 9 }
|
|
5841
5842
|
]);
|
|
5842
5843
|
}
|
|
5843
5844
|
create(value) {
|
|
@@ -5864,6 +5865,9 @@ class ConnectionInit$Type extends import_runtime4.MessageType {
|
|
|
5864
5865
|
case 4:
|
|
5865
5866
|
message.clientVersion = reader.string();
|
|
5866
5867
|
break;
|
|
5868
|
+
case 5:
|
|
5869
|
+
message.osVersion = reader.string();
|
|
5870
|
+
break;
|
|
5867
5871
|
default:
|
|
5868
5872
|
let u = options.readUnknownField;
|
|
5869
5873
|
if (u === "throw")
|
|
@@ -5884,6 +5888,8 @@ class ConnectionInit$Type extends import_runtime4.MessageType {
|
|
|
5884
5888
|
writer.tag(3, import_runtime.WireType.Varint).uint32(message.layer);
|
|
5885
5889
|
if (message.clientVersion !== undefined)
|
|
5886
5890
|
writer.tag(4, import_runtime.WireType.LengthDelimited).string(message.clientVersion);
|
|
5891
|
+
if (message.osVersion !== undefined)
|
|
5892
|
+
writer.tag(5, import_runtime.WireType.LengthDelimited).string(message.osVersion);
|
|
5887
5893
|
let u = options.writeUnknownFields;
|
|
5888
5894
|
if (u !== false)
|
|
5889
5895
|
(u == true ? import_runtime2.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
|
@@ -18289,6 +18295,9 @@ class PingPongService {
|
|
|
18289
18295
|
sleepTimer = null;
|
|
18290
18296
|
sleepResolver = null;
|
|
18291
18297
|
pings = new Map;
|
|
18298
|
+
lastPingAt = null;
|
|
18299
|
+
lastPongAt = null;
|
|
18300
|
+
lastTimeoutAt = null;
|
|
18292
18301
|
constructor(options) {
|
|
18293
18302
|
this.log = options?.logger ?? {};
|
|
18294
18303
|
const cryptoAny = globalThis.crypto;
|
|
@@ -18317,13 +18326,16 @@ class PingPongService {
|
|
|
18317
18326
|
return;
|
|
18318
18327
|
const nonce = this.randomNonce();
|
|
18319
18328
|
await client.sendPing(nonce);
|
|
18320
|
-
|
|
18329
|
+
const now = Date.now();
|
|
18330
|
+
this.lastPingAt = now;
|
|
18331
|
+
this.pings.set(nonce, now);
|
|
18321
18332
|
}
|
|
18322
18333
|
pong(nonce) {
|
|
18323
18334
|
const pingDate = this.pings.get(nonce);
|
|
18324
18335
|
if (!pingDate)
|
|
18325
18336
|
return;
|
|
18326
18337
|
this.pings.delete(nonce);
|
|
18338
|
+
this.lastPongAt = Date.now();
|
|
18327
18339
|
}
|
|
18328
18340
|
async loop() {
|
|
18329
18341
|
while (this.running) {
|
|
@@ -18344,11 +18356,16 @@ class PingPongService {
|
|
|
18344
18356
|
if (client.state !== "open")
|
|
18345
18357
|
return;
|
|
18346
18358
|
const now = Date.now();
|
|
18347
|
-
const
|
|
18348
|
-
if (
|
|
18359
|
+
const oldestPendingPingAt = [...this.pings.values()].reduce((oldest, timestamp) => oldest == null || timestamp < oldest ? timestamp : oldest, null);
|
|
18360
|
+
if (oldestPendingPingAt == null)
|
|
18349
18361
|
return;
|
|
18350
|
-
|
|
18351
|
-
|
|
18362
|
+
const oldestPendingAgeMs = now - oldestPendingPingAt;
|
|
18363
|
+
if (oldestPendingAgeMs <= 30000)
|
|
18364
|
+
return;
|
|
18365
|
+
this.lastTimeoutAt = now;
|
|
18366
|
+
this.log.warn?.(`Ping timeout, reconnecting (pending=${this.pings.size}, oldestPendingAgeMs=${oldestPendingAgeMs}${this.lastPongAt != null ? `, lastPongAgeMs=${now - this.lastPongAt}` : ""})`);
|
|
18367
|
+
this.reset();
|
|
18368
|
+
await client.reconnect({ cause: "ping-timeout" });
|
|
18352
18369
|
}
|
|
18353
18370
|
async sleep(ms) {
|
|
18354
18371
|
if (ms <= 0)
|
|
@@ -18382,6 +18399,19 @@ class PingPongService {
|
|
|
18382
18399
|
}
|
|
18383
18400
|
return BigInt(Math.floor(Math.random() * Number.MAX_SAFE_INTEGER));
|
|
18384
18401
|
}
|
|
18402
|
+
getDiagnostics() {
|
|
18403
|
+
const now = Date.now();
|
|
18404
|
+
const oldestPendingPingAt = [...this.pings.values()].reduce((oldest, timestamp) => oldest == null || timestamp < oldest ? timestamp : oldest, null);
|
|
18405
|
+
return {
|
|
18406
|
+
running: this.running,
|
|
18407
|
+
pendingCount: this.pings.size,
|
|
18408
|
+
lastPingAt: this.lastPingAt,
|
|
18409
|
+
lastPongAt: this.lastPongAt,
|
|
18410
|
+
lastTimeoutAt: this.lastTimeoutAt,
|
|
18411
|
+
oldestPendingPingAt,
|
|
18412
|
+
oldestPendingPingAgeMs: oldestPendingPingAt != null ? now - oldestPendingPingAt : null
|
|
18413
|
+
};
|
|
18414
|
+
}
|
|
18385
18415
|
}
|
|
18386
18416
|
var isCrypto = (value) => typeof value === "object" && value !== null && ("getRandomValues" in value) && typeof value.getRandomValues === "function";
|
|
18387
18417
|
|
|
@@ -18411,6 +18441,11 @@ class ProtocolClient {
|
|
|
18411
18441
|
reconnectionTimer = null;
|
|
18412
18442
|
authenticationTimeout = null;
|
|
18413
18443
|
listenersStarted = false;
|
|
18444
|
+
lastConnectingAt = null;
|
|
18445
|
+
lastOpenAt = null;
|
|
18446
|
+
lastTransportMessageAt = null;
|
|
18447
|
+
lastFailureAt = null;
|
|
18448
|
+
lastFailureReason = null;
|
|
18414
18449
|
constructor(options) {
|
|
18415
18450
|
this.transport = options.transport;
|
|
18416
18451
|
this.log = options.logger ?? {};
|
|
@@ -18438,7 +18473,10 @@ class ProtocolClient {
|
|
|
18438
18473
|
}
|
|
18439
18474
|
}
|
|
18440
18475
|
async reconnect(options) {
|
|
18441
|
-
await this.transport.reconnect({
|
|
18476
|
+
await this.transport.reconnect({
|
|
18477
|
+
skipDelay: options?.skipDelay,
|
|
18478
|
+
cause: options?.cause ?? this.lastFailureReason ?? "protocol-reconnect"
|
|
18479
|
+
});
|
|
18442
18480
|
}
|
|
18443
18481
|
async sendRpc(method, input = emptyRpcInput) {
|
|
18444
18482
|
this.ensureOpenForRpc();
|
|
@@ -18499,6 +18537,7 @@ class ProtocolClient {
|
|
|
18499
18537
|
});
|
|
18500
18538
|
}
|
|
18501
18539
|
async handleTransportMessage(message) {
|
|
18540
|
+
this.lastTransportMessageAt = Date.now();
|
|
18502
18541
|
switch (message.body.oneofKind) {
|
|
18503
18542
|
case "connectionOpen":
|
|
18504
18543
|
await this.connectionOpen();
|
|
@@ -18531,7 +18570,7 @@ class ProtocolClient {
|
|
|
18531
18570
|
this.pingPong.pong(message.body.pong.nonce);
|
|
18532
18571
|
break;
|
|
18533
18572
|
case "connectionError":
|
|
18534
|
-
this.handleClientFailure();
|
|
18573
|
+
this.handleClientFailure(describeConnectionError(message.body.connectionError));
|
|
18535
18574
|
break;
|
|
18536
18575
|
default:
|
|
18537
18576
|
break;
|
|
@@ -18553,11 +18592,12 @@ class ProtocolClient {
|
|
|
18553
18592
|
this.startAuthenticationTimeout();
|
|
18554
18593
|
} catch (error) {
|
|
18555
18594
|
this.log.error?.("Failed to authenticate", error);
|
|
18556
|
-
this.handleClientFailure();
|
|
18595
|
+
this.handleClientFailure(`authenticate failed: ${summarizeError(error)}`);
|
|
18557
18596
|
}
|
|
18558
18597
|
}
|
|
18559
18598
|
async connectionOpen() {
|
|
18560
18599
|
this.state = "open";
|
|
18600
|
+
this.lastOpenAt = Date.now();
|
|
18561
18601
|
await this.events.send({ type: "open" });
|
|
18562
18602
|
this.stopAuthenticationTimeout();
|
|
18563
18603
|
if (this.reconnectionTimer) {
|
|
@@ -18569,7 +18609,9 @@ class ProtocolClient {
|
|
|
18569
18609
|
this.resendPendingRpcRequests();
|
|
18570
18610
|
}
|
|
18571
18611
|
async connecting() {
|
|
18612
|
+
this.pingPong.stop();
|
|
18572
18613
|
this.state = "connecting";
|
|
18614
|
+
this.lastConnectingAt = Date.now();
|
|
18573
18615
|
await this.events.send({ type: "connecting" });
|
|
18574
18616
|
}
|
|
18575
18617
|
async reset() {
|
|
@@ -18583,7 +18625,7 @@ class ProtocolClient {
|
|
|
18583
18625
|
this.authenticationTimeout = setTimeout(() => {
|
|
18584
18626
|
if (this.state === "open")
|
|
18585
18627
|
return;
|
|
18586
|
-
this.handleClientFailure();
|
|
18628
|
+
this.handleClientFailure("authentication timeout after 10000ms");
|
|
18587
18629
|
}, 1e4);
|
|
18588
18630
|
}
|
|
18589
18631
|
stopAuthenticationTimeout() {
|
|
@@ -18592,19 +18634,23 @@ class ProtocolClient {
|
|
|
18592
18634
|
clearTimeout(this.authenticationTimeout);
|
|
18593
18635
|
this.authenticationTimeout = null;
|
|
18594
18636
|
}
|
|
18595
|
-
handleClientFailure() {
|
|
18637
|
+
handleClientFailure(reason = "connection failure") {
|
|
18596
18638
|
this.pingPong.stop();
|
|
18597
18639
|
this.stopAuthenticationTimeout();
|
|
18598
18640
|
this.state = "connecting";
|
|
18641
|
+
this.lastFailureAt = Date.now();
|
|
18642
|
+
this.lastFailureReason = reason;
|
|
18599
18643
|
if (this.reconnectionTimer) {
|
|
18600
18644
|
clearTimeout(this.reconnectionTimer);
|
|
18601
18645
|
}
|
|
18602
18646
|
this.connectionAttemptNo = this.connectionAttemptNo + 1 >>> 0;
|
|
18647
|
+
const delayMs = Math.round(this.getReconnectionDelay() * 1000);
|
|
18648
|
+
this.log.warn?.(`Protocol reconnect scheduled (attempt=${this.connectionAttemptNo}, delayMs=${delayMs}, reason=${reason})`);
|
|
18603
18649
|
this.reconnectionTimer = setTimeout(() => {
|
|
18604
18650
|
if (this.state === "open")
|
|
18605
18651
|
return;
|
|
18606
18652
|
this.reconnect({ skipDelay: true });
|
|
18607
|
-
},
|
|
18653
|
+
}, delayMs);
|
|
18608
18654
|
}
|
|
18609
18655
|
getReconnectionDelay() {
|
|
18610
18656
|
const attemptNo = this.connectionAttemptNo;
|
|
@@ -18690,11 +18736,25 @@ class ProtocolClient {
|
|
|
18690
18736
|
pending.sending = true;
|
|
18691
18737
|
this.transport.send(pending.message).catch((error) => {
|
|
18692
18738
|
this.log.warn?.("Failed to send RPC request; waiting for reconnect", error);
|
|
18693
|
-
this.handleClientFailure();
|
|
18739
|
+
this.handleClientFailure(`rpc send failed: ${summarizeError(error)}`);
|
|
18694
18740
|
}).finally(() => {
|
|
18695
18741
|
pending.sending = false;
|
|
18696
18742
|
});
|
|
18697
18743
|
}
|
|
18744
|
+
getDiagnostics() {
|
|
18745
|
+
return {
|
|
18746
|
+
state: this.state,
|
|
18747
|
+
connectionAttemptNo: this.connectionAttemptNo,
|
|
18748
|
+
pendingRpcCount: this.pendingRpcRequests.size,
|
|
18749
|
+
lastConnectingAt: this.lastConnectingAt,
|
|
18750
|
+
lastOpenAt: this.lastOpenAt,
|
|
18751
|
+
lastTransportMessageAt: this.lastTransportMessageAt,
|
|
18752
|
+
lastFailureAt: this.lastFailureAt,
|
|
18753
|
+
lastFailureReason: this.lastFailureReason,
|
|
18754
|
+
ping: this.pingPong.getDiagnostics(),
|
|
18755
|
+
transport: typeof this.transport.getDiagnostics === "function" ? this.transport.getDiagnostics() : null
|
|
18756
|
+
};
|
|
18757
|
+
}
|
|
18698
18758
|
}
|
|
18699
18759
|
var normalizeRpcTimeoutMs = (timeoutMs, fallback) => {
|
|
18700
18760
|
const resolved = timeoutMs === undefined ? fallback : timeoutMs;
|
|
@@ -18715,6 +18775,18 @@ class ProtocolClientError extends Error {
|
|
|
18715
18775
|
this.name = `ProtocolClientError:${code}`;
|
|
18716
18776
|
}
|
|
18717
18777
|
}
|
|
18778
|
+
function summarizeError(error) {
|
|
18779
|
+
if (error instanceof Error) {
|
|
18780
|
+
return `${error.name}: ${error.message}`;
|
|
18781
|
+
}
|
|
18782
|
+
return String(error);
|
|
18783
|
+
}
|
|
18784
|
+
function describeConnectionError(error) {
|
|
18785
|
+
const value = typeof error === "object" && error !== null ? error : null;
|
|
18786
|
+
const code = typeof value?.code === "number" ? value.code : null;
|
|
18787
|
+
const message = typeof value?.message === "string" && value.message.trim() ? value.message.trim() : "unknown";
|
|
18788
|
+
return `server connection error${code != null ? ` (code=${code})` : ""}: ${message}`;
|
|
18789
|
+
}
|
|
18718
18790
|
|
|
18719
18791
|
// ../../node_modules/.bun/ws@8.20.0/node_modules/ws/wrapper.mjs
|
|
18720
18792
|
var import_stream = __toESM(require_stream(), 1);
|
|
@@ -18746,6 +18818,18 @@ class WebSocketTransport {
|
|
|
18746
18818
|
connectionAttemptNo = 0;
|
|
18747
18819
|
socket = null;
|
|
18748
18820
|
reconnectionTimer = null;
|
|
18821
|
+
lastConnectStartedAt = null;
|
|
18822
|
+
lastConnectedAt = null;
|
|
18823
|
+
lastDisconnectedAt = null;
|
|
18824
|
+
lastMessageAt = null;
|
|
18825
|
+
lastCloseCode = null;
|
|
18826
|
+
lastCloseReason = null;
|
|
18827
|
+
lastErrorAt = null;
|
|
18828
|
+
lastErrorMessage = null;
|
|
18829
|
+
lastReconnectScheduledAt = null;
|
|
18830
|
+
lastReconnectDelayMs = null;
|
|
18831
|
+
lastReconnectCause = null;
|
|
18832
|
+
reconnectCount = 0;
|
|
18749
18833
|
constructor(options) {
|
|
18750
18834
|
this.url = options.url;
|
|
18751
18835
|
this.log = options.logger ?? {};
|
|
@@ -18777,7 +18861,13 @@ class WebSocketTransport {
|
|
|
18777
18861
|
this.cleanUpPreviousConnection();
|
|
18778
18862
|
this.connectionAttemptNo = this.connectionAttemptNo + 1 >>> 0;
|
|
18779
18863
|
const delaySeconds = this.getReconnectionDelaySeconds(this.connectionAttemptNo);
|
|
18780
|
-
|
|
18864
|
+
const delayMs = Math.round(delaySeconds * 1000);
|
|
18865
|
+
const cause = options?.cause?.trim() || "unspecified";
|
|
18866
|
+
this.lastReconnectScheduledAt = Date.now();
|
|
18867
|
+
this.lastReconnectDelayMs = delayMs;
|
|
18868
|
+
this.lastReconnectCause = cause;
|
|
18869
|
+
this.reconnectCount += 1;
|
|
18870
|
+
this.log.warn?.(`WebSocket reconnect scheduled (attempt=${this.connectionAttemptNo}, delayMs=${delayMs}, cause=${cause})`);
|
|
18781
18871
|
this.reconnectionTimer = setTimeout(() => {
|
|
18782
18872
|
this.reconnectionTimer = null;
|
|
18783
18873
|
if (this.state === "idle" || this.state === "connected")
|
|
@@ -18821,6 +18911,7 @@ class WebSocketTransport {
|
|
|
18821
18911
|
async openConnection() {
|
|
18822
18912
|
if (this.state === "idle")
|
|
18823
18913
|
return;
|
|
18914
|
+
this.lastConnectStartedAt = Date.now();
|
|
18824
18915
|
const socket = new import_websocket.default(this.url);
|
|
18825
18916
|
this.socket = socket;
|
|
18826
18917
|
socket.on("open", () => {
|
|
@@ -18843,6 +18934,8 @@ class WebSocketTransport {
|
|
|
18843
18934
|
return;
|
|
18844
18935
|
this.connectionAttemptNo = 0;
|
|
18845
18936
|
this.state = "connected";
|
|
18937
|
+
this.lastConnectedAt = Date.now();
|
|
18938
|
+
this.lastDisconnectedAt = null;
|
|
18846
18939
|
await this.events.send({ type: "connected" });
|
|
18847
18940
|
}
|
|
18848
18941
|
async handleMessage(socket, data) {
|
|
@@ -18851,6 +18944,7 @@ class WebSocketTransport {
|
|
|
18851
18944
|
try {
|
|
18852
18945
|
const payload = this.coerceBinary(data);
|
|
18853
18946
|
const message = ServerProtocolMessage.fromBinary(payload);
|
|
18947
|
+
this.lastMessageAt = Date.now();
|
|
18854
18948
|
await this.events.send({ type: "message", message });
|
|
18855
18949
|
} catch (error) {
|
|
18856
18950
|
this.log.error?.("Failed to decode message", error);
|
|
@@ -18870,16 +18964,24 @@ class WebSocketTransport {
|
|
|
18870
18964
|
return;
|
|
18871
18965
|
if (this.state === "idle")
|
|
18872
18966
|
return;
|
|
18873
|
-
|
|
18874
|
-
|
|
18967
|
+
const reasonText = stringifyCloseReason(reason);
|
|
18968
|
+
this.lastDisconnectedAt = Date.now();
|
|
18969
|
+
this.lastCloseCode = code;
|
|
18970
|
+
this.lastCloseReason = reasonText;
|
|
18971
|
+
const connectedForMs = this.lastConnectedAt != null ? Math.max(0, this.lastDisconnectedAt - this.lastConnectedAt) : null;
|
|
18972
|
+
this.log.warn?.(`WebSocket closed (code=${code}, reason=${reasonText || "none"}${connectedForMs != null ? `, connectedForMs=${connectedForMs}` : ""})`);
|
|
18973
|
+
await this.reconnect({ cause: `socket-close:${code}${reasonText ? `:${reasonText}` : ""}` });
|
|
18875
18974
|
}
|
|
18876
18975
|
async handleError(socket, error) {
|
|
18877
18976
|
if (this.socket !== socket)
|
|
18878
18977
|
return;
|
|
18879
18978
|
if (this.state === "idle")
|
|
18880
18979
|
return;
|
|
18881
|
-
|
|
18882
|
-
|
|
18980
|
+
const summary = summarizeError2(error);
|
|
18981
|
+
this.lastErrorAt = Date.now();
|
|
18982
|
+
this.lastErrorMessage = summary;
|
|
18983
|
+
this.log.error?.(`WebSocket error: ${summary}`);
|
|
18984
|
+
await this.reconnect({ cause: `socket-error:${summary}` });
|
|
18883
18985
|
}
|
|
18884
18986
|
async setIdle() {
|
|
18885
18987
|
if (this.state === "idle")
|
|
@@ -18893,6 +18995,46 @@ class WebSocketTransport {
|
|
|
18893
18995
|
this.state = "connecting";
|
|
18894
18996
|
await this.events.send({ type: "connecting" });
|
|
18895
18997
|
}
|
|
18998
|
+
getDiagnostics() {
|
|
18999
|
+
return {
|
|
19000
|
+
kind: "websocket",
|
|
19001
|
+
url: redactUrlForDiagnostics(this.url),
|
|
19002
|
+
state: this.state,
|
|
19003
|
+
connectionAttemptNo: this.connectionAttemptNo,
|
|
19004
|
+
reconnectCount: this.reconnectCount,
|
|
19005
|
+
lastConnectStartedAt: this.lastConnectStartedAt,
|
|
19006
|
+
lastConnectedAt: this.lastConnectedAt,
|
|
19007
|
+
lastDisconnectedAt: this.lastDisconnectedAt,
|
|
19008
|
+
lastMessageAt: this.lastMessageAt,
|
|
19009
|
+
lastCloseCode: this.lastCloseCode,
|
|
19010
|
+
lastCloseReason: this.lastCloseReason,
|
|
19011
|
+
lastErrorAt: this.lastErrorAt,
|
|
19012
|
+
lastErrorMessage: this.lastErrorMessage,
|
|
19013
|
+
lastReconnectScheduledAt: this.lastReconnectScheduledAt,
|
|
19014
|
+
lastReconnectDelayMs: this.lastReconnectDelayMs,
|
|
19015
|
+
lastReconnectCause: this.lastReconnectCause,
|
|
19016
|
+
socketReadyState: this.socket?.readyState ?? null
|
|
19017
|
+
};
|
|
19018
|
+
}
|
|
19019
|
+
}
|
|
19020
|
+
function stringifyCloseReason(reason) {
|
|
19021
|
+
const text = reason.toString("utf8").trim();
|
|
19022
|
+
return text;
|
|
19023
|
+
}
|
|
19024
|
+
function summarizeError2(error) {
|
|
19025
|
+
if (error instanceof Error) {
|
|
19026
|
+
const code = typeof error.code === "string" ? error.code : null;
|
|
19027
|
+
return code ? `${error.name}: ${error.message} (code=${code})` : `${error.name}: ${error.message}`;
|
|
19028
|
+
}
|
|
19029
|
+
return String(error);
|
|
19030
|
+
}
|
|
19031
|
+
function redactUrlForDiagnostics(raw) {
|
|
19032
|
+
try {
|
|
19033
|
+
const url = new URL(raw);
|
|
19034
|
+
return `${url.protocol}//${url.host}${url.pathname}`;
|
|
19035
|
+
} catch {
|
|
19036
|
+
return raw;
|
|
19037
|
+
}
|
|
18896
19038
|
}
|
|
18897
19039
|
|
|
18898
19040
|
// ../sdk/dist/sdk/types.js
|
|
@@ -19047,6 +19189,7 @@ class InlineSdkClient {
|
|
|
19047
19189
|
saveInFlight = null;
|
|
19048
19190
|
catchUpInFlightByChatId = new Map;
|
|
19049
19191
|
catchUpRequestedByChatId = new Map;
|
|
19192
|
+
userCatchUpInFlight = null;
|
|
19050
19193
|
constructor(options) {
|
|
19051
19194
|
this.options = options;
|
|
19052
19195
|
this.log = options.logger ?? noopLogger;
|
|
@@ -19114,6 +19257,13 @@ class InlineSdkClient {
|
|
|
19114
19257
|
await this.flushStateSave();
|
|
19115
19258
|
await this.protocol.stopTransport();
|
|
19116
19259
|
}
|
|
19260
|
+
getDiagnostics() {
|
|
19261
|
+
return {
|
|
19262
|
+
started: this.started,
|
|
19263
|
+
baseUrl: this.httpBaseUrl,
|
|
19264
|
+
protocol: this.protocol.getDiagnostics()
|
|
19265
|
+
};
|
|
19266
|
+
}
|
|
19117
19267
|
rejectOpen(error) {
|
|
19118
19268
|
this.openRejecter?.(error);
|
|
19119
19269
|
this.openResolver = null;
|
|
@@ -19126,7 +19276,8 @@ class InlineSdkClient {
|
|
|
19126
19276
|
return {
|
|
19127
19277
|
version: 1,
|
|
19128
19278
|
...this.state.dateCursor != null ? { dateCursor: this.state.dateCursor } : {},
|
|
19129
|
-
...this.state.lastSeqByChatId != null ? { lastSeqByChatId: { ...this.state.lastSeqByChatId } } : {}
|
|
19279
|
+
...this.state.lastSeqByChatId != null ? { lastSeqByChatId: { ...this.state.lastSeqByChatId } } : {},
|
|
19280
|
+
...this.state.lastUserSeq != null ? { lastUserSeq: this.state.lastUserSeq } : {}
|
|
19130
19281
|
};
|
|
19131
19282
|
}
|
|
19132
19283
|
async getMe() {
|
|
@@ -19392,6 +19543,7 @@ class InlineSdkClient {
|
|
|
19392
19543
|
this.openResolver = null;
|
|
19393
19544
|
this.openRejecter = null;
|
|
19394
19545
|
this.initializeDateCursor();
|
|
19546
|
+
this.requestCatchUpUser();
|
|
19395
19547
|
}
|
|
19396
19548
|
async initializeDateCursor() {
|
|
19397
19549
|
const date = this.state.dateCursor ?? nowSeconds();
|
|
@@ -19490,6 +19642,10 @@ class InlineSdkClient {
|
|
|
19490
19642
|
}
|
|
19491
19643
|
case "messageActionInvoked": {
|
|
19492
19644
|
const payload = update.update.messageActionInvoked;
|
|
19645
|
+
if (this.shouldSkipUserSeq(seq)) {
|
|
19646
|
+
return;
|
|
19647
|
+
}
|
|
19648
|
+
this.bumpUserSeq(seq);
|
|
19493
19649
|
await this.eventStream.send({
|
|
19494
19650
|
kind: "message.action.invoke",
|
|
19495
19651
|
interactionId: payload.interactionId,
|
|
@@ -19505,6 +19661,10 @@ class InlineSdkClient {
|
|
|
19505
19661
|
}
|
|
19506
19662
|
case "messageActionAnswered": {
|
|
19507
19663
|
const payload = update.update.messageActionAnswered;
|
|
19664
|
+
if (this.shouldSkipUserSeq(seq)) {
|
|
19665
|
+
return;
|
|
19666
|
+
}
|
|
19667
|
+
this.bumpUserSeq(seq);
|
|
19508
19668
|
await this.eventStream.send({
|
|
19509
19669
|
kind: "message.action.answered",
|
|
19510
19670
|
interactionId: payload.interactionId,
|
|
@@ -19551,6 +19711,86 @@ class InlineSdkClient {
|
|
|
19551
19711
|
this.scheduleStateSave();
|
|
19552
19712
|
}
|
|
19553
19713
|
}
|
|
19714
|
+
shouldSkipUserSeq(seq) {
|
|
19715
|
+
if (!Number.isFinite(seq))
|
|
19716
|
+
return false;
|
|
19717
|
+
const lastUserSeq = this.state.lastUserSeq ?? 0;
|
|
19718
|
+
return seq > 0 && seq <= lastUserSeq;
|
|
19719
|
+
}
|
|
19720
|
+
bumpUserSeq(seq) {
|
|
19721
|
+
if (!Number.isFinite(seq) || seq <= 0)
|
|
19722
|
+
return;
|
|
19723
|
+
const prev = this.state.lastUserSeq ?? 0;
|
|
19724
|
+
if (seq > prev) {
|
|
19725
|
+
this.state.lastUserSeq = seq;
|
|
19726
|
+
this.scheduleStateSave();
|
|
19727
|
+
}
|
|
19728
|
+
}
|
|
19729
|
+
requestCatchUpUser() {
|
|
19730
|
+
const lastUserSeq = this.state.lastUserSeq ?? 0;
|
|
19731
|
+
if (lastUserSeq <= 0) {
|
|
19732
|
+
return;
|
|
19733
|
+
}
|
|
19734
|
+
if (this.userCatchUpInFlight) {
|
|
19735
|
+
return;
|
|
19736
|
+
}
|
|
19737
|
+
this.userCatchUpInFlight = this.doCatchUpUser(lastUserSeq).catch((error) => {
|
|
19738
|
+
this.log.warn?.("GET_UPDATES user catch-up failed; continuing live delivery", {
|
|
19739
|
+
error: extractErrorMessage(error)
|
|
19740
|
+
});
|
|
19741
|
+
}).finally(() => {
|
|
19742
|
+
this.userCatchUpInFlight = null;
|
|
19743
|
+
});
|
|
19744
|
+
}
|
|
19745
|
+
async doCatchUpUser(startSeq) {
|
|
19746
|
+
let cursor = startSeq;
|
|
19747
|
+
while (true) {
|
|
19748
|
+
const result = await this.invoke(Method.GET_UPDATES, {
|
|
19749
|
+
oneofKind: "getUpdates",
|
|
19750
|
+
getUpdates: GetUpdatesInput.create({
|
|
19751
|
+
bucket: UpdateBucket.create({
|
|
19752
|
+
type: {
|
|
19753
|
+
oneofKind: "user",
|
|
19754
|
+
user: {}
|
|
19755
|
+
}
|
|
19756
|
+
}),
|
|
19757
|
+
startSeq: BigInt(cursor),
|
|
19758
|
+
totalLimit: defaultCatchUpTotalLimit
|
|
19759
|
+
})
|
|
19760
|
+
});
|
|
19761
|
+
const payload = result.getUpdates;
|
|
19762
|
+
const deliveredSeq = Number(payload.seq ?? 0n);
|
|
19763
|
+
if (!Number.isSafeInteger(deliveredSeq)) {
|
|
19764
|
+
this.log.warn?.("GET_UPDATES user catch-up returned non-integer seq; aborting", { deliveredSeq });
|
|
19765
|
+
return;
|
|
19766
|
+
}
|
|
19767
|
+
if (payload.resultType === GetUpdatesResult_ResultType.TOO_LONG) {
|
|
19768
|
+
this.log.warn?.("GET_UPDATES user catch-up too long; fast-forwarding cursor", { seq: deliveredSeq });
|
|
19769
|
+
this.bumpUserSeq(deliveredSeq);
|
|
19770
|
+
if (payload.date !== 0n) {
|
|
19771
|
+
this.state.dateCursor = payload.date;
|
|
19772
|
+
}
|
|
19773
|
+
this.scheduleStateSave();
|
|
19774
|
+
return;
|
|
19775
|
+
}
|
|
19776
|
+
for (const update of payload.updates) {
|
|
19777
|
+
await this.handleUpdate(update);
|
|
19778
|
+
}
|
|
19779
|
+
this.bumpUserSeq(deliveredSeq);
|
|
19780
|
+
if (payload.date !== 0n) {
|
|
19781
|
+
this.state.dateCursor = payload.date;
|
|
19782
|
+
}
|
|
19783
|
+
this.scheduleStateSave();
|
|
19784
|
+
if (payload.final) {
|
|
19785
|
+
return;
|
|
19786
|
+
}
|
|
19787
|
+
if (deliveredSeq <= cursor) {
|
|
19788
|
+
this.log.warn?.("GET_UPDATES user catch-up made no progress; aborting", { cursor, deliveredSeq });
|
|
19789
|
+
return;
|
|
19790
|
+
}
|
|
19791
|
+
cursor = deliveredSeq;
|
|
19792
|
+
}
|
|
19793
|
+
}
|
|
19554
19794
|
requestCatchUpChat(params) {
|
|
19555
19795
|
const previous = this.catchUpRequestedByChatId.get(params.chatId);
|
|
19556
19796
|
this.catchUpRequestedByChatId.set(params.chatId, {
|
|
@@ -19715,7 +19955,8 @@ class InlineSdkClient {
|
|
|
19715
19955
|
const snapshot = {
|
|
19716
19956
|
version: 1,
|
|
19717
19957
|
...this.state.dateCursor != null ? { dateCursor: this.state.dateCursor } : {},
|
|
19718
|
-
...this.state.lastSeqByChatId != null ? { lastSeqByChatId: { ...this.state.lastSeqByChatId } } : {}
|
|
19958
|
+
...this.state.lastSeqByChatId != null ? { lastSeqByChatId: { ...this.state.lastSeqByChatId } } : {},
|
|
19959
|
+
...this.state.lastUserSeq != null ? { lastUserSeq: this.state.lastUserSeq } : {}
|
|
19719
19960
|
};
|
|
19720
19961
|
this.saveInFlight = store.save(snapshot).catch((error) => {
|
|
19721
19962
|
this.log.warn?.("Failed to persist SDK state", error);
|
|
@@ -34029,9 +34270,21 @@ function looksLikeInlineTargetId(raw, normalizedInput) {
|
|
|
34029
34270
|
// src/inline/monitor.ts
|
|
34030
34271
|
import { mkdir } from "node:fs/promises";
|
|
34031
34272
|
import path2 from "node:path";
|
|
34273
|
+
import {
|
|
34274
|
+
buildCommandTextFromArgs,
|
|
34275
|
+
findCommandByNativeName,
|
|
34276
|
+
parseCommandArgs,
|
|
34277
|
+
resolveCommandArgMenu
|
|
34278
|
+
} from "openclaw/plugin-sdk/native-command-registry";
|
|
34279
|
+
import {
|
|
34280
|
+
createChannelInboundDebouncer,
|
|
34281
|
+
shouldDebounceTextInbound
|
|
34282
|
+
} from "openclaw/plugin-sdk/channel-inbound";
|
|
34283
|
+
import { resolveDefaultModelForAgent } from "openclaw/plugin-sdk/agent-runtime";
|
|
34284
|
+
import { applyModelOverrideToSessionEntry, updateSessionStore } from "openclaw/plugin-sdk/config-runtime";
|
|
34285
|
+
import { buildModelsProviderData } from "openclaw/plugin-sdk/models-provider-runtime";
|
|
34032
34286
|
|
|
34033
34287
|
// src/sdk-runtime-compat.ts
|
|
34034
|
-
import { createMessageToolButtonsSchema } from "openclaw/plugin-sdk/channel-actions";
|
|
34035
34288
|
var HISTORY_CONTEXT_MARKER = "[Chat messages since your last reply - for context]";
|
|
34036
34289
|
var CURRENT_MESSAGE_MARKER = "[Current message - respond to this]";
|
|
34037
34290
|
var MAX_HISTORY_KEYS = 1000;
|
|
@@ -34122,14 +34375,6 @@ function recordPendingHistoryEntryIfEnabled(params) {
|
|
|
34122
34375
|
limit: params.limit
|
|
34123
34376
|
});
|
|
34124
34377
|
}
|
|
34125
|
-
var TYPEBOX_OPTIONAL_SYMBOL = Symbol.for("TypeBox.Optional");
|
|
34126
|
-
function markTypeBoxOptional(schema) {
|
|
34127
|
-
schema[TYPEBOX_OPTIONAL_SYMBOL] = "Optional";
|
|
34128
|
-
return schema;
|
|
34129
|
-
}
|
|
34130
|
-
function createMessageToolButtonsSchemaCompat() {
|
|
34131
|
-
return markTypeBoxOptional(createMessageToolButtonsSchema());
|
|
34132
|
-
}
|
|
34133
34378
|
function extensionForMimeCompat(mime) {
|
|
34134
34379
|
const normalized = mime?.trim().toLowerCase();
|
|
34135
34380
|
if (!normalized)
|
|
@@ -34230,44 +34475,6 @@ async function createChannelReplyPipelineCompat(params) {
|
|
|
34230
34475
|
};
|
|
34231
34476
|
}
|
|
34232
34477
|
}
|
|
34233
|
-
async function loadNativeCommandHelpersCompat() {
|
|
34234
|
-
try {
|
|
34235
|
-
const sdk = await import("openclaw/plugin-sdk/command-auth");
|
|
34236
|
-
const listNativeCommandSpecsForConfig = typeof sdk.listNativeCommandSpecsForConfig === "function" ? sdk.listNativeCommandSpecsForConfig : null;
|
|
34237
|
-
const listSkillCommandsForAgents = typeof sdk.listSkillCommandsForAgents === "function" ? sdk.listSkillCommandsForAgents : null;
|
|
34238
|
-
if (!listNativeCommandSpecsForConfig || !listSkillCommandsForAgents) {
|
|
34239
|
-
throw new Error("command-auth helpers unavailable");
|
|
34240
|
-
}
|
|
34241
|
-
return {
|
|
34242
|
-
available: true,
|
|
34243
|
-
listNativeCommandSpecsForConfig,
|
|
34244
|
-
listSkillCommandsForAgents
|
|
34245
|
-
};
|
|
34246
|
-
} catch {
|
|
34247
|
-
return {
|
|
34248
|
-
available: false,
|
|
34249
|
-
listNativeCommandSpecsForConfig: () => [],
|
|
34250
|
-
listSkillCommandsForAgents: () => []
|
|
34251
|
-
};
|
|
34252
|
-
}
|
|
34253
|
-
}
|
|
34254
|
-
async function loadPluginCommandSpecsCompat(provider) {
|
|
34255
|
-
try {
|
|
34256
|
-
const sdk = await import("openclaw/plugin-sdk/plugin-runtime");
|
|
34257
|
-
if (typeof sdk.getPluginCommandSpecs !== "function") {
|
|
34258
|
-
throw new Error("plugin runtime command helper unavailable");
|
|
34259
|
-
}
|
|
34260
|
-
return {
|
|
34261
|
-
available: true,
|
|
34262
|
-
specs: sdk.getPluginCommandSpecs(provider)
|
|
34263
|
-
};
|
|
34264
|
-
} catch {
|
|
34265
|
-
return {
|
|
34266
|
-
available: false,
|
|
34267
|
-
specs: []
|
|
34268
|
-
};
|
|
34269
|
-
}
|
|
34270
|
-
}
|
|
34271
34478
|
|
|
34272
34479
|
// src/inline/message-formatting.ts
|
|
34273
34480
|
var INLINE_FORMATTING_NOTE = "Inline formatting note: prefer bullet lists over markdown tables. If a table is necessary, render it inside a fenced code block. Do not wrap bare URLs in inline code or backticks. Use plain URLs or markdown links. Use inline code only for actual code, commands, file paths, env vars, or identifiers.";
|
|
@@ -34926,246 +35133,28 @@ function summarizeInlineMessageContent(message) {
|
|
|
34926
35133
|
};
|
|
34927
35134
|
}
|
|
34928
35135
|
|
|
34929
|
-
// src/inline/
|
|
34930
|
-
var
|
|
34931
|
-
|
|
34932
|
-
|
|
34933
|
-
|
|
34934
|
-
|
|
34935
|
-
|
|
34936
|
-
|
|
34937
|
-
|
|
34938
|
-
|
|
34939
|
-
|
|
34940
|
-
|
|
34941
|
-
|
|
34942
|
-
|
|
34943
|
-
{ value: "provider", label: "Provider" },
|
|
34944
|
-
{ value: "limit", label: "Limit" },
|
|
34945
|
-
{ value: "summary", label: "Summary" },
|
|
34946
|
-
{ value: "audio", label: "Audio" },
|
|
34947
|
-
{ value: "help", label: "Help" }
|
|
34948
|
-
]
|
|
34949
|
-
},
|
|
34950
|
-
{ name: "value", description: "Provider, limit, or text" }
|
|
34951
|
-
],
|
|
34952
|
-
argsMenu: {
|
|
34953
|
-
arg: "action",
|
|
34954
|
-
title: "Choose TTS action:"
|
|
34955
|
-
}
|
|
34956
|
-
},
|
|
34957
|
-
{
|
|
34958
|
-
key: "session",
|
|
34959
|
-
nativeName: "session",
|
|
34960
|
-
args: [
|
|
34961
|
-
{ name: "action", description: "idle | max-age", choices: ["idle", "max-age"] },
|
|
34962
|
-
{ name: "value", description: "Duration or off" }
|
|
34963
|
-
],
|
|
34964
|
-
argsMenu: "auto"
|
|
34965
|
-
},
|
|
34966
|
-
{
|
|
34967
|
-
key: "subagents",
|
|
34968
|
-
nativeName: "subagents",
|
|
34969
|
-
args: [
|
|
34970
|
-
{
|
|
34971
|
-
name: "action",
|
|
34972
|
-
description: "list | kill | log | info | send | steer | spawn",
|
|
34973
|
-
choices: ["list", "kill", "log", "info", "send", "steer", "spawn"]
|
|
34974
|
-
},
|
|
34975
|
-
{ name: "target", description: "Run id, index, or session key" },
|
|
34976
|
-
{ name: "value", description: "Additional input" }
|
|
34977
|
-
],
|
|
34978
|
-
argsMenu: "auto"
|
|
34979
|
-
},
|
|
34980
|
-
{
|
|
34981
|
-
key: "acp",
|
|
34982
|
-
nativeName: "acp",
|
|
34983
|
-
args: [
|
|
34984
|
-
{
|
|
34985
|
-
name: "action",
|
|
34986
|
-
description: "Action to run",
|
|
34987
|
-
choices: [
|
|
34988
|
-
"spawn",
|
|
34989
|
-
"cancel",
|
|
34990
|
-
"steer",
|
|
34991
|
-
"close",
|
|
34992
|
-
"sessions",
|
|
34993
|
-
"status",
|
|
34994
|
-
"set-mode",
|
|
34995
|
-
"set",
|
|
34996
|
-
"cwd",
|
|
34997
|
-
"permissions",
|
|
34998
|
-
"timeout",
|
|
34999
|
-
"model",
|
|
35000
|
-
"reset-options",
|
|
35001
|
-
"doctor",
|
|
35002
|
-
"install",
|
|
35003
|
-
"help"
|
|
35004
|
-
]
|
|
35005
|
-
},
|
|
35006
|
-
{ name: "value", description: "Action arguments" }
|
|
35007
|
-
],
|
|
35008
|
-
argsMenu: "auto"
|
|
35009
|
-
},
|
|
35010
|
-
{
|
|
35011
|
-
key: "usage",
|
|
35012
|
-
nativeName: "usage",
|
|
35013
|
-
args: [{ name: "mode", description: "off, tokens, full, or cost", choices: ["off", "tokens", "full", "cost"] }],
|
|
35014
|
-
argsMenu: "auto"
|
|
35015
|
-
},
|
|
35016
|
-
{
|
|
35017
|
-
key: "activation",
|
|
35018
|
-
nativeName: "activation",
|
|
35019
|
-
args: [{ name: "mode", description: "mention or always", choices: ["mention", "always"] }],
|
|
35020
|
-
argsMenu: "auto"
|
|
35021
|
-
},
|
|
35022
|
-
{
|
|
35023
|
-
key: "send",
|
|
35024
|
-
nativeName: "send",
|
|
35025
|
-
args: [{ name: "mode", description: "on, off, or inherit", choices: ["on", "off", "inherit"] }],
|
|
35026
|
-
argsMenu: "auto"
|
|
35027
|
-
},
|
|
35028
|
-
{
|
|
35029
|
-
key: "think",
|
|
35030
|
-
nativeName: "think",
|
|
35031
|
-
args: [{ name: "level", description: "thinking level", choices: [...THINKING_LEVEL_CHOICES] }],
|
|
35032
|
-
argsMenu: "auto"
|
|
35033
|
-
},
|
|
35034
|
-
{
|
|
35035
|
-
key: "verbose",
|
|
35036
|
-
nativeName: "verbose",
|
|
35037
|
-
args: [{ name: "mode", description: "on or off", choices: ["on", "off"] }],
|
|
35038
|
-
argsMenu: "auto"
|
|
35039
|
-
},
|
|
35040
|
-
{
|
|
35041
|
-
key: "fast",
|
|
35042
|
-
nativeName: "fast",
|
|
35043
|
-
args: [{ name: "mode", description: "status, on, or off", choices: ["status", "on", "off"] }],
|
|
35044
|
-
argsMenu: "auto"
|
|
35045
|
-
},
|
|
35046
|
-
{
|
|
35047
|
-
key: "reasoning",
|
|
35048
|
-
nativeName: "reasoning",
|
|
35049
|
-
args: [{ name: "mode", description: "on, off, or stream", choices: ["on", "off", "stream"] }],
|
|
35050
|
-
argsMenu: "auto"
|
|
35051
|
-
},
|
|
35052
|
-
{
|
|
35053
|
-
key: "elevated",
|
|
35054
|
-
nativeName: "elevated",
|
|
35055
|
-
args: [{ name: "mode", description: "on, off, ask, or full", choices: ["on", "off", "ask", "full"] }],
|
|
35056
|
-
argsMenu: "auto"
|
|
35057
|
-
}
|
|
35058
|
-
];
|
|
35059
|
-
function parsePositionalArgs(definitions, raw) {
|
|
35060
|
-
const values = {};
|
|
35061
|
-
const trimmed = raw.trim();
|
|
35062
|
-
if (!trimmed)
|
|
35063
|
-
return values;
|
|
35064
|
-
const tokens = trimmed.split(/\s+/).filter(Boolean);
|
|
35065
|
-
let index = 0;
|
|
35066
|
-
for (const definition of definitions) {
|
|
35067
|
-
if (index >= tokens.length)
|
|
35068
|
-
break;
|
|
35069
|
-
const token = tokens[index];
|
|
35070
|
-
if (!token)
|
|
35071
|
-
break;
|
|
35072
|
-
values[definition.name] = token;
|
|
35073
|
-
index += 1;
|
|
35074
|
-
}
|
|
35075
|
-
return values;
|
|
35076
|
-
}
|
|
35077
|
-
function parseCommandArgs(command, raw) {
|
|
35078
|
-
const trimmed = raw?.trim();
|
|
35079
|
-
if (!trimmed)
|
|
35080
|
-
return;
|
|
35081
|
-
if (!command.args || command.argsParsing === "none") {
|
|
35082
|
-
return { raw: trimmed };
|
|
35083
|
-
}
|
|
35084
|
-
return {
|
|
35085
|
-
raw: trimmed,
|
|
35086
|
-
values: parsePositionalArgs(command.args, trimmed)
|
|
35087
|
-
};
|
|
35088
|
-
}
|
|
35089
|
-
function findCommandByNativeName(name) {
|
|
35090
|
-
const normalized = name.trim().toLowerCase();
|
|
35091
|
-
return COMPAT_COMMANDS.find((command) => command.nativeName.toLowerCase() === normalized);
|
|
35092
|
-
}
|
|
35093
|
-
function resolveCommandArgChoices(arg) {
|
|
35094
|
-
const raw = arg.choices ?? [];
|
|
35095
|
-
return raw.map((choice) => typeof choice === "string" ? { value: choice, label: choice } : choice);
|
|
35096
|
-
}
|
|
35097
|
-
function resolveCommandArgMenu(params) {
|
|
35098
|
-
const { command, args } = params;
|
|
35099
|
-
if (!command.args || !command.argsMenu)
|
|
35100
|
-
return null;
|
|
35101
|
-
if (command.argsParsing === "none")
|
|
35102
|
-
return null;
|
|
35103
|
-
const argName = command.argsMenu === "auto" ? command.args.find((arg2) => resolveCommandArgChoices(arg2).length > 0)?.name : command.argsMenu.arg;
|
|
35104
|
-
if (!argName)
|
|
35105
|
-
return null;
|
|
35106
|
-
if (args?.values && args.values[argName] != null)
|
|
35107
|
-
return null;
|
|
35108
|
-
if (args?.raw && !args.values)
|
|
35109
|
-
return null;
|
|
35110
|
-
const arg = command.args.find((entry) => entry.name === argName);
|
|
35111
|
-
if (!arg)
|
|
35112
|
-
return null;
|
|
35113
|
-
const choices = resolveCommandArgChoices(arg);
|
|
35114
|
-
if (choices.length === 0)
|
|
35115
|
-
return null;
|
|
35116
|
-
const title = command.argsMenu !== "auto" ? command.argsMenu.title : undefined;
|
|
35117
|
-
return {
|
|
35118
|
-
arg,
|
|
35119
|
-
choices,
|
|
35120
|
-
...title ? { title } : {}
|
|
35121
|
-
};
|
|
35122
|
-
}
|
|
35123
|
-
function buildCommandTextFromArgs(command, args) {
|
|
35124
|
-
const values = args?.values ?? {};
|
|
35125
|
-
const argDefs = command.args ?? [];
|
|
35126
|
-
const renderedArgs = [];
|
|
35127
|
-
for (const argDef of argDefs) {
|
|
35128
|
-
const value = values[argDef.name];
|
|
35129
|
-
if (value == null)
|
|
35130
|
-
continue;
|
|
35131
|
-
const normalized = typeof value === "string" ? value.trim() : String(value);
|
|
35132
|
-
if (!normalized)
|
|
35133
|
-
continue;
|
|
35134
|
-
renderedArgs.push(normalized);
|
|
35136
|
+
// src/inline/monitor.ts
|
|
35137
|
+
var CHANNEL_ID = "inline";
|
|
35138
|
+
function summarizeSdkMeta(meta3) {
|
|
35139
|
+
if (meta3 == null)
|
|
35140
|
+
return "";
|
|
35141
|
+
if (meta3 instanceof Error)
|
|
35142
|
+
return `${meta3.name}: ${meta3.message}`;
|
|
35143
|
+
if (typeof meta3 === "string")
|
|
35144
|
+
return meta3;
|
|
35145
|
+
try {
|
|
35146
|
+
const json2 = JSON.stringify(meta3);
|
|
35147
|
+
return json2 === undefined ? String(meta3) : json2;
|
|
35148
|
+
} catch {
|
|
35149
|
+
return String(meta3);
|
|
35135
35150
|
}
|
|
35136
|
-
return renderedArgs.length > 0 ? `/${command.nativeName} ${renderedArgs.join(" ")}` : `/${command.nativeName}`;
|
|
35137
35151
|
}
|
|
35138
|
-
function
|
|
35139
|
-
const
|
|
35140
|
-
|
|
35141
|
-
|
|
35142
|
-
|
|
35143
|
-
const command = findCommandByNativeName(match[1]);
|
|
35144
|
-
if (!command)
|
|
35145
|
-
return null;
|
|
35146
|
-
const args = parseCommandArgs(command, match[2]);
|
|
35147
|
-
const menu = resolveCommandArgMenu({
|
|
35148
|
-
command,
|
|
35149
|
-
...args ? { args } : {}
|
|
35150
|
-
});
|
|
35151
|
-
if (!menu)
|
|
35152
|
-
return null;
|
|
35153
|
-
const title = menu.title ?? `Choose ${menu.arg.description || menu.arg.name} for /${command.nativeName}.`;
|
|
35154
|
-
const rows = [];
|
|
35155
|
-
for (let index = 0;index < menu.choices.length; index += 2) {
|
|
35156
|
-
const slice = menu.choices.slice(index, index + 2);
|
|
35157
|
-
rows.push(slice.map((choice) => ({
|
|
35158
|
-
text: choice.label,
|
|
35159
|
-
callback_data: buildCommandTextFromArgs(command, {
|
|
35160
|
-
values: { [menu.arg.name]: choice.value }
|
|
35161
|
-
})
|
|
35162
|
-
})));
|
|
35163
|
-
}
|
|
35164
|
-
return { title, buttons: rows };
|
|
35152
|
+
function formatSdkLogLine(message, meta3) {
|
|
35153
|
+
const detail = summarizeSdkMeta(meta3);
|
|
35154
|
+
if (!detail)
|
|
35155
|
+
return message;
|
|
35156
|
+
return `${message} ${detail}`;
|
|
35165
35157
|
}
|
|
35166
|
-
|
|
35167
|
-
// src/inline/monitor.ts
|
|
35168
|
-
var CHANNEL_ID = "inline";
|
|
35169
35158
|
var DEFAULT_DM_HISTORY_LIMIT = 6;
|
|
35170
35159
|
var HISTORY_LINE_MAX_CHARS = 280;
|
|
35171
35160
|
var URL_LIKE_PATTERN = /https?:\/\/\S+/i;
|
|
@@ -35228,35 +35217,137 @@ function callbackDataToUtf8(data) {
|
|
|
35228
35217
|
return;
|
|
35229
35218
|
}
|
|
35230
35219
|
}
|
|
35220
|
+
function buildInlineInboundMessageSid(params) {
|
|
35221
|
+
if (params.callbackActionEvent) {
|
|
35222
|
+
return `callback:${String(params.callbackActionEvent.targetMessageId)}:${String(params.callbackActionEvent.interactionId)}`;
|
|
35223
|
+
}
|
|
35224
|
+
return String(params.msgId);
|
|
35225
|
+
}
|
|
35226
|
+
function buildInlineDebounceKey(params) {
|
|
35227
|
+
if (params.senderId == null)
|
|
35228
|
+
return null;
|
|
35229
|
+
return `inline:${params.accountId}:${String(params.chatId)}:${String(params.senderId)}`;
|
|
35230
|
+
}
|
|
35231
|
+
function buildSyntheticInlineTextMessage(params) {
|
|
35232
|
+
return {
|
|
35233
|
+
...params.base,
|
|
35234
|
+
message: params.text,
|
|
35235
|
+
...params.mentioned !== undefined ? { mentioned: params.mentioned } : {}
|
|
35236
|
+
};
|
|
35237
|
+
}
|
|
35231
35238
|
var INLINE_ACTION_MAX_ROWS = 8;
|
|
35232
35239
|
var INLINE_ACTION_MAX_PER_ROW = 8;
|
|
35233
35240
|
function isRecord3(value) {
|
|
35234
35241
|
return typeof value === "object" && value !== null;
|
|
35235
35242
|
}
|
|
35243
|
+
function resolveInlineNativeCommandMenu(params) {
|
|
35244
|
+
const normalized = params.commandBody.trim();
|
|
35245
|
+
const match = normalized.match(/^\/([^\s]+)(?:\s+([\s\S]+))?$/);
|
|
35246
|
+
if (!match?.[1])
|
|
35247
|
+
return null;
|
|
35248
|
+
const command = findCommandByNativeName(match[1], "telegram");
|
|
35249
|
+
if (!command)
|
|
35250
|
+
return null;
|
|
35251
|
+
const args = parseCommandArgs(command, match[2]);
|
|
35252
|
+
const menu = resolveCommandArgMenu({
|
|
35253
|
+
command,
|
|
35254
|
+
...args ? { args } : {},
|
|
35255
|
+
cfg: params.cfg
|
|
35256
|
+
});
|
|
35257
|
+
if (!menu)
|
|
35258
|
+
return null;
|
|
35259
|
+
const title = menu.title ?? `Choose ${menu.arg.description || menu.arg.name} for /${command.nativeName}.`;
|
|
35260
|
+
const rows = [];
|
|
35261
|
+
for (let index = 0;index < menu.choices.length; index += 2) {
|
|
35262
|
+
const slice = menu.choices.slice(index, index + 2);
|
|
35263
|
+
rows.push(slice.map((choice) => ({
|
|
35264
|
+
text: choice.label,
|
|
35265
|
+
callback_data: buildCommandTextFromArgs(command, {
|
|
35266
|
+
values: { [menu.arg.name]: choice.value }
|
|
35267
|
+
})
|
|
35268
|
+
})));
|
|
35269
|
+
}
|
|
35270
|
+
return { title, buttons: rows };
|
|
35271
|
+
}
|
|
35236
35272
|
function mapInlineModelPickerCallbackToCommand(raw) {
|
|
35237
|
-
const
|
|
35238
|
-
if (!
|
|
35273
|
+
const callback = parseInlineModelPickerCallback(raw);
|
|
35274
|
+
if (!callback)
|
|
35239
35275
|
return;
|
|
35240
|
-
|
|
35241
|
-
|
|
35276
|
+
switch (callback.type) {
|
|
35277
|
+
case "providers":
|
|
35278
|
+
case "back":
|
|
35279
|
+
return "/models";
|
|
35280
|
+
case "list":
|
|
35281
|
+
return `/models ${callback.provider} ${String(callback.page)}`;
|
|
35282
|
+
case "select":
|
|
35283
|
+
return callback.provider ? `/model ${callback.provider}/${callback.model}` : `/model ${callback.model}`;
|
|
35242
35284
|
}
|
|
35285
|
+
}
|
|
35286
|
+
function parseInlineModelPickerCallback(raw) {
|
|
35287
|
+
const trimmed = raw.trim();
|
|
35288
|
+
if (!trimmed)
|
|
35289
|
+
return null;
|
|
35290
|
+
if (trimmed === "mdl_prov")
|
|
35291
|
+
return { type: "providers" };
|
|
35292
|
+
if (trimmed === "mdl_back")
|
|
35293
|
+
return { type: "back" };
|
|
35243
35294
|
const listMatch = trimmed.match(/^mdl_list_([a-z0-9_-]+)_(\d+)$/i);
|
|
35244
35295
|
if (listMatch?.[1] && listMatch[2]) {
|
|
35245
35296
|
const provider = listMatch[1].trim();
|
|
35246
35297
|
const page = Number.parseInt(listMatch[2], 10);
|
|
35247
35298
|
if (provider && Number.isFinite(page) && page > 0) {
|
|
35248
|
-
return
|
|
35299
|
+
return { type: "list", provider, page };
|
|
35249
35300
|
}
|
|
35250
35301
|
}
|
|
35251
35302
|
const standardSelectionMatch = trimmed.match(/^mdl_sel_(.+)$/);
|
|
35252
35303
|
if (standardSelectionMatch?.[1]?.trim()) {
|
|
35253
|
-
|
|
35304
|
+
const modelRef = standardSelectionMatch[1].trim();
|
|
35305
|
+
const slashIndex = modelRef.indexOf("/");
|
|
35306
|
+
if (slashIndex > 0 && slashIndex < modelRef.length - 1) {
|
|
35307
|
+
return {
|
|
35308
|
+
type: "select",
|
|
35309
|
+
provider: modelRef.slice(0, slashIndex),
|
|
35310
|
+
model: modelRef.slice(slashIndex + 1)
|
|
35311
|
+
};
|
|
35312
|
+
}
|
|
35254
35313
|
}
|
|
35255
35314
|
const compactSelectionMatch = trimmed.match(/^mdl_sel\/(.+)$/);
|
|
35256
35315
|
if (compactSelectionMatch?.[1]?.trim()) {
|
|
35257
|
-
return
|
|
35316
|
+
return { type: "select", model: compactSelectionMatch[1].trim() };
|
|
35258
35317
|
}
|
|
35259
|
-
return;
|
|
35318
|
+
return null;
|
|
35319
|
+
}
|
|
35320
|
+
function resolveInlineModelPickerSelection(params) {
|
|
35321
|
+
if (params.callback.provider) {
|
|
35322
|
+
return {
|
|
35323
|
+
kind: "resolved",
|
|
35324
|
+
provider: params.callback.provider,
|
|
35325
|
+
model: params.callback.model
|
|
35326
|
+
};
|
|
35327
|
+
}
|
|
35328
|
+
const matchingProviders = params.providers.filter((id) => params.byProvider.get(id)?.has(params.callback.model));
|
|
35329
|
+
if (matchingProviders.length === 1 && matchingProviders[0]) {
|
|
35330
|
+
return {
|
|
35331
|
+
kind: "resolved",
|
|
35332
|
+
provider: matchingProviders[0],
|
|
35333
|
+
model: params.callback.model
|
|
35334
|
+
};
|
|
35335
|
+
}
|
|
35336
|
+
return {
|
|
35337
|
+
kind: "ambiguous",
|
|
35338
|
+
model: params.callback.model
|
|
35339
|
+
};
|
|
35340
|
+
}
|
|
35341
|
+
function buildInlineModelProviderButtons(providers) {
|
|
35342
|
+
const rows = [];
|
|
35343
|
+
for (let index = 0;index < providers.length; index += 2) {
|
|
35344
|
+
const slice = providers.slice(index, index + 2);
|
|
35345
|
+
rows.push(slice.map((provider) => ({
|
|
35346
|
+
text: `${provider.id} (${provider.count})`,
|
|
35347
|
+
callback_data: `mdl_list_${provider.id}_1`
|
|
35348
|
+
})));
|
|
35349
|
+
}
|
|
35350
|
+
return rows;
|
|
35260
35351
|
}
|
|
35261
35352
|
function normalizeInlineActionCallbackData(raw) {
|
|
35262
35353
|
const trimmed = raw.trim();
|
|
@@ -35264,6 +35355,14 @@ function normalizeInlineActionCallbackData(raw) {
|
|
|
35264
35355
|
return "";
|
|
35265
35356
|
return mapInlineModelPickerCallbackToCommand(trimmed) ?? trimmed;
|
|
35266
35357
|
}
|
|
35358
|
+
function normalizeInlineTelegramButtonCallbackData(raw) {
|
|
35359
|
+
const trimmed = raw.trim();
|
|
35360
|
+
if (!trimmed)
|
|
35361
|
+
return "";
|
|
35362
|
+
if (parseInlineModelPickerCallback(trimmed))
|
|
35363
|
+
return trimmed;
|
|
35364
|
+
return normalizeInlineActionCallbackData(trimmed);
|
|
35365
|
+
}
|
|
35267
35366
|
function normalizeReplyMarkupButtonsWith(raw, options) {
|
|
35268
35367
|
if (!Array.isArray(raw))
|
|
35269
35368
|
return [];
|
|
@@ -35305,7 +35404,7 @@ function resolveInlineReplyActions(payload) {
|
|
|
35305
35404
|
} else if (telegramData && Object.prototype.hasOwnProperty.call(telegramData, "buttons")) {
|
|
35306
35405
|
rawButtons = telegramData.buttons;
|
|
35307
35406
|
hasExplicitButtons = true;
|
|
35308
|
-
mapCallbackData =
|
|
35407
|
+
mapCallbackData = normalizeInlineTelegramButtonCallbackData;
|
|
35309
35408
|
} else if (Object.prototype.hasOwnProperty.call(payload, "buttons")) {
|
|
35310
35409
|
rawButtons = payload.buttons;
|
|
35311
35410
|
hasExplicitButtons = true;
|
|
@@ -35870,19 +35969,35 @@ async function monitorInlineProvider(params) {
|
|
|
35870
35969
|
const stateDir = core3.state.resolveStateDir();
|
|
35871
35970
|
const statePath = path2.join(stateDir, "channels", "inline", `${account.accountId}.json`);
|
|
35872
35971
|
await mkdir(path2.dirname(statePath), { recursive: true });
|
|
35972
|
+
let client = null;
|
|
35973
|
+
const pushDiagnostics = (patch) => {
|
|
35974
|
+
statusSink?.({
|
|
35975
|
+
...patch ?? {},
|
|
35976
|
+
...client ? { diagnostics: client.getDiagnostics() } : {}
|
|
35977
|
+
});
|
|
35978
|
+
};
|
|
35873
35979
|
const sdkLog = {
|
|
35874
|
-
debug: (msg) => log?.debug?.(msg),
|
|
35875
|
-
info: (msg) => log?.info(msg),
|
|
35876
|
-
warn: (msg) =>
|
|
35877
|
-
|
|
35980
|
+
debug: (msg, meta3) => log?.debug?.(formatSdkLogLine(msg, meta3)),
|
|
35981
|
+
info: (msg, meta3) => log?.info(formatSdkLogLine(msg, meta3)),
|
|
35982
|
+
warn: (msg, meta3) => {
|
|
35983
|
+
const line = formatSdkLogLine(msg, meta3);
|
|
35984
|
+
log?.warn(line);
|
|
35985
|
+
pushDiagnostics({ lastError: line });
|
|
35986
|
+
},
|
|
35987
|
+
error: (msg, meta3) => {
|
|
35988
|
+
const line = formatSdkLogLine(msg, meta3);
|
|
35989
|
+
log?.error(line);
|
|
35990
|
+
pushDiagnostics({ lastError: line });
|
|
35991
|
+
}
|
|
35878
35992
|
};
|
|
35879
|
-
|
|
35993
|
+
client = new InlineSdkClient({
|
|
35880
35994
|
baseUrl: account.baseUrl,
|
|
35881
35995
|
token,
|
|
35882
35996
|
logger: sdkLog,
|
|
35883
35997
|
state: new JsonFileStateStore(statePath)
|
|
35884
35998
|
});
|
|
35885
35999
|
await client.connect(abortSignal);
|
|
36000
|
+
pushDiagnostics();
|
|
35886
36001
|
const meResult = await client.invokeRaw(Method.GET_ME, {
|
|
35887
36002
|
oneofKind: "getMe",
|
|
35888
36003
|
getMe: {}
|
|
@@ -35893,6 +36008,7 @@ async function monitorInlineProvider(params) {
|
|
|
35893
36008
|
const meId = meResult.getMe.user.id;
|
|
35894
36009
|
const botUsername = normalizeInlineUsername(meResult.getMe.user.username)?.toLowerCase();
|
|
35895
36010
|
log?.info(`[${account.accountId}] inline connected (me=${String(meId)})`);
|
|
36011
|
+
pushDiagnostics();
|
|
35896
36012
|
const chatCache = new Map;
|
|
35897
36013
|
const senderProfilesById = new Map;
|
|
35898
36014
|
const botMessageIdsByChat = new Map;
|
|
@@ -35937,852 +36053,1078 @@ async function monitorInlineProvider(params) {
|
|
|
35937
36053
|
participantFetches.set(chatKey, run);
|
|
35938
36054
|
await run;
|
|
35939
36055
|
};
|
|
35940
|
-
const
|
|
36056
|
+
const handleInboundNow = async (input) => {
|
|
36057
|
+
const chatId = input.chatId;
|
|
36058
|
+
const msg = input.msg;
|
|
36059
|
+
const rawBodyOverride = input.rawBodyOverride ?? null;
|
|
36060
|
+
const reactionEvent = input.reactionEvent ?? null;
|
|
36061
|
+
const callbackActionEvent = input.callbackActionEvent ?? null;
|
|
36062
|
+
let rawBody = "";
|
|
36063
|
+
let currentContent = null;
|
|
36064
|
+
let currentAttachmentText = null;
|
|
36065
|
+
let currentEntityText = null;
|
|
36066
|
+
if (!reactionEvent && !callbackActionEvent) {
|
|
36067
|
+
if (rawBodyOverride != null) {
|
|
36068
|
+
rawBody = rawBodyOverride.trim();
|
|
36069
|
+
} else {
|
|
36070
|
+
currentContent = summarizeInlineMessageContent(msg);
|
|
36071
|
+
rawBody = buildInlineInboundBodyText(currentContent);
|
|
36072
|
+
currentAttachmentText = currentContent.attachmentText || null;
|
|
36073
|
+
currentEntityText = currentContent.entityText || null;
|
|
36074
|
+
}
|
|
36075
|
+
if (!rawBody)
|
|
36076
|
+
return;
|
|
36077
|
+
}
|
|
36078
|
+
statusSink?.({ lastInboundAt: Date.now() });
|
|
36079
|
+
let chatInfo;
|
|
35941
36080
|
try {
|
|
35942
|
-
|
|
35943
|
-
|
|
35944
|
-
|
|
35945
|
-
|
|
35946
|
-
|
|
35947
|
-
|
|
35948
|
-
|
|
35949
|
-
|
|
35950
|
-
|
|
35951
|
-
|
|
35952
|
-
|
|
35953
|
-
|
|
35954
|
-
|
|
35955
|
-
|
|
35956
|
-
|
|
35957
|
-
|
|
35958
|
-
|
|
35959
|
-
|
|
35960
|
-
|
|
35961
|
-
|
|
35962
|
-
|
|
35963
|
-
|
|
35964
|
-
|
|
35965
|
-
|
|
35966
|
-
|
|
35967
|
-
|
|
35968
|
-
|
|
35969
|
-
|
|
35970
|
-
|
|
35971
|
-
|
|
35972
|
-
|
|
35973
|
-
|
|
35974
|
-
|
|
35975
|
-
|
|
35976
|
-
|
|
35977
|
-
|
|
35978
|
-
|
|
35979
|
-
|
|
35980
|
-
|
|
35981
|
-
|
|
35982
|
-
|
|
35983
|
-
|
|
35984
|
-
|
|
35985
|
-
|
|
35986
|
-
|
|
35987
|
-
|
|
35988
|
-
};
|
|
35989
|
-
msg = {
|
|
35990
|
-
id: event.reaction.messageId,
|
|
35991
|
-
chatId: event.chatId,
|
|
35992
|
-
date: event.date,
|
|
35993
|
-
fromId: event.reaction.userId,
|
|
35994
|
-
message: "",
|
|
35995
|
-
out: false,
|
|
35996
|
-
mentioned: false,
|
|
35997
|
-
replyToMsgId: event.reaction.messageId
|
|
35998
|
-
};
|
|
35999
|
-
} else if (event.kind === "reaction.delete") {
|
|
36000
|
-
inboundChatId = event.chatId;
|
|
36001
|
-
if (event.userId === meId)
|
|
36002
|
-
continue;
|
|
36003
|
-
const onBotMessage = await isReactionTargetBotMessage({
|
|
36004
|
-
client,
|
|
36005
|
-
chatId: event.chatId,
|
|
36006
|
-
messageId: event.messageId,
|
|
36007
|
-
meId,
|
|
36008
|
-
botMessageIdsByChat
|
|
36009
|
-
}).catch((err) => {
|
|
36010
|
-
statusSink?.({ lastError: `getChatHistory (reaction target) failed: ${String(err)}` });
|
|
36011
|
-
return false;
|
|
36012
|
-
});
|
|
36013
|
-
if (!onBotMessage)
|
|
36014
|
-
continue;
|
|
36015
|
-
reactionEvent = {
|
|
36016
|
-
action: "removed",
|
|
36017
|
-
emoji: event.emoji,
|
|
36018
|
-
targetMessageId: event.messageId
|
|
36019
|
-
};
|
|
36020
|
-
msg = {
|
|
36021
|
-
id: event.messageId,
|
|
36022
|
-
chatId: event.chatId,
|
|
36023
|
-
date: event.date,
|
|
36024
|
-
fromId: event.userId,
|
|
36025
|
-
message: "",
|
|
36026
|
-
out: false,
|
|
36027
|
-
mentioned: false,
|
|
36028
|
-
replyToMsgId: event.messageId
|
|
36029
|
-
};
|
|
36030
|
-
} else if (rawEvent["kind"] === "message.action.invoke") {
|
|
36031
|
-
const actorUserId = rawEvent["actorUserId"];
|
|
36032
|
-
const interactionId = rawEvent["interactionId"];
|
|
36033
|
-
const actionId = rawEvent["actionId"];
|
|
36034
|
-
const targetMessageId = rawEvent["messageId"];
|
|
36035
|
-
const data = rawEvent["data"];
|
|
36036
|
-
const eventChatId = rawEvent["chatId"];
|
|
36037
|
-
const eventDate = rawEvent["date"];
|
|
36038
|
-
if (!actorUserId || !interactionId || !actionId || !targetMessageId || !eventChatId || !eventDate || !data) {
|
|
36039
|
-
continue;
|
|
36040
|
-
}
|
|
36041
|
-
inboundChatId = eventChatId;
|
|
36042
|
-
if (actorUserId === meId)
|
|
36043
|
-
continue;
|
|
36044
|
-
callbackActionEvent = {
|
|
36045
|
-
interactionId,
|
|
36046
|
-
actionId,
|
|
36047
|
-
targetMessageId,
|
|
36048
|
-
data
|
|
36049
|
-
};
|
|
36050
|
-
msg = {
|
|
36051
|
-
id: targetMessageId,
|
|
36052
|
-
chatId: eventChatId,
|
|
36053
|
-
date: eventDate,
|
|
36054
|
-
fromId: actorUserId,
|
|
36055
|
-
message: "",
|
|
36056
|
-
out: false,
|
|
36057
|
-
mentioned: false,
|
|
36058
|
-
replyToMsgId: targetMessageId
|
|
36059
|
-
};
|
|
36060
|
-
} else {
|
|
36061
|
-
continue;
|
|
36062
|
-
}
|
|
36063
|
-
if (!inboundChatId)
|
|
36064
|
-
continue;
|
|
36065
|
-
const chatId = inboundChatId;
|
|
36066
|
-
statusSink?.({ lastInboundAt: Date.now() });
|
|
36067
|
-
let chatInfo;
|
|
36068
|
-
try {
|
|
36069
|
-
chatInfo = await resolveChatInfo(client, chatCache, chatId);
|
|
36070
|
-
} catch (err) {
|
|
36071
|
-
chatInfo = { kind: "group", title: null };
|
|
36072
|
-
statusSink?.({ lastError: `getChat failed: ${String(err)}` });
|
|
36073
|
-
}
|
|
36074
|
-
const isGroup = chatInfo.kind !== "direct";
|
|
36075
|
-
const replyThreadsEnabled = account.config.capabilities?.replyThreads === true || isInlineReplyThreadsEnabled({ cfg, accountId: account.accountId });
|
|
36076
|
-
const replyThreadContext = await resolveInlineInboundReplyThreadContext({
|
|
36077
|
-
replyThreadsEnabled,
|
|
36078
|
-
client,
|
|
36079
|
-
chatId,
|
|
36080
|
-
chatInfo,
|
|
36081
|
-
chatCache
|
|
36082
|
-
}).catch((err) => {
|
|
36083
|
-
statusSink?.({ lastError: `getChat (reply thread) failed: ${String(err)}` });
|
|
36084
|
-
return null;
|
|
36085
|
-
});
|
|
36086
|
-
const effectiveChatId = replyThreadContext?.parentChatId ?? chatId;
|
|
36087
|
-
const effectiveGroupTitle = replyThreadContext?.parentChatTitle ?? chatInfo.title ?? null;
|
|
36088
|
-
const senderId = String(msg.fromId);
|
|
36089
|
-
await hydrateChatParticipants(chatId);
|
|
36090
|
-
const senderProfile = senderProfilesById.get(senderId);
|
|
36091
|
-
const senderUsername = senderProfile?.username;
|
|
36092
|
-
const senderName = senderProfile?.name ?? (!isGroup ? chatInfo.title ?? undefined : undefined);
|
|
36093
|
-
if (reactionEvent) {
|
|
36094
|
-
const actor = senderUsername != null && senderUsername.length > 0 ? `@${senderUsername}` : senderName ?? `user:${senderId}`;
|
|
36095
|
-
const emoji3 = reactionEvent.emoji.trim() || "a reaction";
|
|
36096
|
-
const messageId = String(reactionEvent.targetMessageId);
|
|
36097
|
-
if (reactionEvent.action === "added") {
|
|
36098
|
-
rawBody = `${actor} reacted with ${emoji3} to your message #${messageId}`;
|
|
36099
|
-
} else {
|
|
36100
|
-
rawBody = `${actor} removed ${emoji3} from your message #${messageId}`;
|
|
36101
|
-
}
|
|
36102
|
-
} else if (callbackActionEvent) {
|
|
36103
|
-
const actor = senderUsername != null && senderUsername.length > 0 ? `@${senderUsername}` : senderName ?? `user:${senderId}`;
|
|
36104
|
-
const payload = {
|
|
36105
|
-
type: "inline_message_action_callback",
|
|
36106
|
-
interaction_id: String(callbackActionEvent.interactionId),
|
|
36107
|
-
actor_user_id: senderId,
|
|
36108
|
-
chat_id: String(chatId),
|
|
36109
|
-
message_id: String(callbackActionEvent.targetMessageId),
|
|
36110
|
-
action_id: callbackActionEvent.actionId,
|
|
36111
|
-
data_base64: callbackDataToBase64(callbackActionEvent.data),
|
|
36112
|
-
data_utf8: callbackDataToUtf8(callbackActionEvent.data) ?? null
|
|
36113
|
-
};
|
|
36114
|
-
rawBody = `${actor} pressed a button on message #${String(callbackActionEvent.targetMessageId)}
|
|
36081
|
+
chatInfo = await resolveChatInfo(client, chatCache, chatId);
|
|
36082
|
+
} catch (err) {
|
|
36083
|
+
chatInfo = { kind: "group", title: null };
|
|
36084
|
+
statusSink?.({ lastError: `getChat failed: ${String(err)}` });
|
|
36085
|
+
}
|
|
36086
|
+
const isGroup = chatInfo.kind !== "direct";
|
|
36087
|
+
const replyThreadsEnabled = account.config.capabilities?.replyThreads === true || isInlineReplyThreadsEnabled({ cfg, accountId: account.accountId });
|
|
36088
|
+
const replyThreadContext = await resolveInlineInboundReplyThreadContext({
|
|
36089
|
+
replyThreadsEnabled,
|
|
36090
|
+
client,
|
|
36091
|
+
chatId,
|
|
36092
|
+
chatInfo,
|
|
36093
|
+
chatCache
|
|
36094
|
+
}).catch((err) => {
|
|
36095
|
+
statusSink?.({ lastError: `getChat (reply thread) failed: ${String(err)}` });
|
|
36096
|
+
return null;
|
|
36097
|
+
});
|
|
36098
|
+
const effectiveChatId = replyThreadContext?.parentChatId ?? chatId;
|
|
36099
|
+
const effectiveGroupTitle = replyThreadContext?.parentChatTitle ?? chatInfo.title ?? null;
|
|
36100
|
+
const senderId = String(msg.fromId);
|
|
36101
|
+
await hydrateChatParticipants(chatId);
|
|
36102
|
+
const senderProfile = senderProfilesById.get(senderId);
|
|
36103
|
+
const senderUsername = senderProfile?.username;
|
|
36104
|
+
const senderName = senderProfile?.name ?? (!isGroup ? chatInfo.title ?? undefined : undefined);
|
|
36105
|
+
if (reactionEvent) {
|
|
36106
|
+
const actor = senderUsername != null && senderUsername.length > 0 ? `@${senderUsername}` : senderName ?? `user:${senderId}`;
|
|
36107
|
+
const emoji3 = reactionEvent.emoji.trim() || "a reaction";
|
|
36108
|
+
const messageId = String(reactionEvent.targetMessageId);
|
|
36109
|
+
if (reactionEvent.action === "added") {
|
|
36110
|
+
rawBody = `${actor} reacted with ${emoji3} to your message #${messageId}`;
|
|
36111
|
+
} else {
|
|
36112
|
+
rawBody = `${actor} removed ${emoji3} from your message #${messageId}`;
|
|
36113
|
+
}
|
|
36114
|
+
} else if (callbackActionEvent) {
|
|
36115
|
+
const actor = senderUsername != null && senderUsername.length > 0 ? `@${senderUsername}` : senderName ?? `user:${senderId}`;
|
|
36116
|
+
const payload = {
|
|
36117
|
+
type: "inline_message_action_callback",
|
|
36118
|
+
interaction_id: String(callbackActionEvent.interactionId),
|
|
36119
|
+
actor_user_id: senderId,
|
|
36120
|
+
chat_id: String(chatId),
|
|
36121
|
+
message_id: String(callbackActionEvent.targetMessageId),
|
|
36122
|
+
action_id: callbackActionEvent.actionId,
|
|
36123
|
+
data_base64: callbackDataToBase64(callbackActionEvent.data),
|
|
36124
|
+
data_utf8: callbackDataToUtf8(callbackActionEvent.data) ?? null
|
|
36125
|
+
};
|
|
36126
|
+
rawBody = `${actor} pressed a button on message #${String(callbackActionEvent.targetMessageId)}
|
|
36115
36127
|
${JSON.stringify(payload)}`;
|
|
36116
|
-
|
|
36117
|
-
|
|
36118
|
-
|
|
36119
|
-
|
|
36120
|
-
|
|
36121
|
-
|
|
36122
|
-
|
|
36123
|
-
|
|
36124
|
-
|
|
36125
|
-
|
|
36126
|
-
|
|
36127
|
-
|
|
36128
|
-
|
|
36129
|
-
|
|
36130
|
-
|
|
36131
|
-
|
|
36132
|
-
|
|
36133
|
-
|
|
36134
|
-
|
|
36135
|
-
|
|
36136
|
-
|
|
36137
|
-
|
|
36138
|
-
|
|
36139
|
-
|
|
36140
|
-
|
|
36141
|
-
|
|
36142
|
-
|
|
36143
|
-
|
|
36144
|
-
|
|
36145
|
-
|
|
36146
|
-
|
|
36147
|
-
|
|
36128
|
+
}
|
|
36129
|
+
const dmPolicy = account.config.dmPolicy ?? "pairing";
|
|
36130
|
+
const defaultGroupPolicy = cfg.channels?.defaults?.groupPolicy;
|
|
36131
|
+
const groupPolicy = account.config.groupPolicy ?? defaultGroupPolicy ?? "allowlist";
|
|
36132
|
+
const configAllowFrom = normalizeAllowlist(account.config.allowFrom);
|
|
36133
|
+
const configGroupAllowFrom = normalizeAllowlist(account.config.groupAllowFrom);
|
|
36134
|
+
const storeAllowFrom = await core3.channel.pairing.readAllowFromStore({
|
|
36135
|
+
channel: CHANNEL_ID,
|
|
36136
|
+
accountId: account.accountId
|
|
36137
|
+
}).catch(() => []);
|
|
36138
|
+
const storeAllowList = normalizeAllowlist(storeAllowFrom);
|
|
36139
|
+
const effectiveAllowFrom = [...configAllowFrom, ...storeAllowList].filter(Boolean);
|
|
36140
|
+
const effectiveGroupAllowFrom = [
|
|
36141
|
+
...configGroupAllowFrom.length > 0 ? configGroupAllowFrom : configAllowFrom,
|
|
36142
|
+
...storeAllowList
|
|
36143
|
+
].filter(Boolean);
|
|
36144
|
+
const callbackCommandBody = callbackActionEvent ? resolveCallbackCommandBodyFromActionData({
|
|
36145
|
+
data: callbackActionEvent.data,
|
|
36146
|
+
...botUsername ? { botUsername } : {}
|
|
36147
|
+
}) : undefined;
|
|
36148
|
+
let callbackActionAnswered = false;
|
|
36149
|
+
const answerCallbackIfNeeded = async () => {
|
|
36150
|
+
if (!callbackActionEvent || callbackActionAnswered)
|
|
36151
|
+
return;
|
|
36152
|
+
await answerInlineMessageAction(client, callbackActionEvent.interactionId);
|
|
36153
|
+
callbackActionAnswered = true;
|
|
36154
|
+
};
|
|
36155
|
+
if (callbackActionEvent) {
|
|
36156
|
+
await answerCallbackIfNeeded().catch((error48) => {
|
|
36157
|
+
runtime2.error?.(`inline callback answer failed: ${String(error48)}`);
|
|
36158
|
+
});
|
|
36159
|
+
}
|
|
36160
|
+
const shouldEditCallbackTargetInPlace = callbackActionEvent != null;
|
|
36161
|
+
const normalizedCommandBody = callbackCommandBody ?? normalizeInlineCommandBody(rawBody, botUsername);
|
|
36162
|
+
const allowTextCommands = core3.channel.commands.shouldHandleTextCommands({
|
|
36163
|
+
cfg,
|
|
36164
|
+
surface: CHANNEL_ID
|
|
36165
|
+
});
|
|
36166
|
+
const useAccessGroups = cfg.commands?.useAccessGroups !== false;
|
|
36167
|
+
const allowForCommands = isGroup ? effectiveGroupAllowFrom : effectiveAllowFrom;
|
|
36168
|
+
const senderAllowedForCommands = allowlistMatch({ allowFrom: allowForCommands, senderId });
|
|
36169
|
+
const hasControlCommand = core3.channel.text.hasControlCommand(callbackCommandBody ?? rawBody, cfg, botUsername ? { botUsername } : undefined);
|
|
36170
|
+
const commandGate = resolveControlCommandGate({
|
|
36171
|
+
useAccessGroups,
|
|
36172
|
+
authorizers: [{ configured: allowForCommands.length > 0, allowed: senderAllowedForCommands }],
|
|
36173
|
+
allowTextCommands,
|
|
36174
|
+
hasControlCommand
|
|
36175
|
+
});
|
|
36176
|
+
const commandAuthorized = commandGate.commandAuthorized;
|
|
36177
|
+
if (isGroup) {
|
|
36178
|
+
if (groupPolicy === "disabled") {
|
|
36179
|
+
log?.info(`[${account.accountId}] inline: drop group chat=${String(chatId)} (groupPolicy=disabled)`);
|
|
36180
|
+
await answerCallbackIfNeeded().catch((error48) => {
|
|
36181
|
+
runtime2.error?.(`inline callback answer failed: ${String(error48)}`);
|
|
36148
36182
|
});
|
|
36149
|
-
|
|
36150
|
-
|
|
36151
|
-
|
|
36152
|
-
const
|
|
36153
|
-
|
|
36154
|
-
|
|
36155
|
-
|
|
36156
|
-
|
|
36157
|
-
|
|
36183
|
+
return;
|
|
36184
|
+
}
|
|
36185
|
+
if (groupPolicy === "allowlist") {
|
|
36186
|
+
const allowed = allowlistMatch({ allowFrom: effectiveGroupAllowFrom, senderId });
|
|
36187
|
+
if (!allowed) {
|
|
36188
|
+
log?.info(`[${account.accountId}] inline: drop group sender=${senderId} (groupPolicy=allowlist)`);
|
|
36189
|
+
await answerCallbackIfNeeded().catch((error48) => {
|
|
36190
|
+
runtime2.error?.(`inline callback answer failed: ${String(error48)}`);
|
|
36191
|
+
});
|
|
36192
|
+
return;
|
|
36193
|
+
}
|
|
36194
|
+
}
|
|
36195
|
+
} else {
|
|
36196
|
+
if (dmPolicy === "disabled") {
|
|
36197
|
+
log?.info(`[${account.accountId}] inline: drop DM sender=${senderId} (dmPolicy=disabled)`);
|
|
36198
|
+
await answerCallbackIfNeeded().catch((error48) => {
|
|
36199
|
+
runtime2.error?.(`inline callback answer failed: ${String(error48)}`);
|
|
36158
36200
|
});
|
|
36159
|
-
|
|
36160
|
-
|
|
36161
|
-
|
|
36162
|
-
|
|
36163
|
-
|
|
36164
|
-
|
|
36165
|
-
}
|
|
36166
|
-
|
|
36167
|
-
|
|
36168
|
-
|
|
36169
|
-
|
|
36170
|
-
|
|
36171
|
-
log?.info(`[${account.accountId}] inline: drop group sender=${senderId} (groupPolicy=allowlist)`);
|
|
36172
|
-
await answerCallbackIfNeeded().catch((error48) => {
|
|
36173
|
-
runtime2.error?.(`inline callback answer failed: ${String(error48)}`);
|
|
36174
|
-
});
|
|
36175
|
-
continue;
|
|
36176
|
-
}
|
|
36177
|
-
}
|
|
36178
|
-
} else {
|
|
36179
|
-
if (dmPolicy === "disabled") {
|
|
36180
|
-
log?.info(`[${account.accountId}] inline: drop DM sender=${senderId} (dmPolicy=disabled)`);
|
|
36181
|
-
await answerCallbackIfNeeded().catch((error48) => {
|
|
36182
|
-
runtime2.error?.(`inline callback answer failed: ${String(error48)}`);
|
|
36201
|
+
return;
|
|
36202
|
+
}
|
|
36203
|
+
if (dmPolicy !== "open") {
|
|
36204
|
+
const allowed = allowlistMatch({ allowFrom: effectiveAllowFrom, senderId });
|
|
36205
|
+
if (!allowed) {
|
|
36206
|
+
if (dmPolicy === "pairing") {
|
|
36207
|
+
const { code, created } = await core3.channel.pairing.upsertPairingRequest({
|
|
36208
|
+
channel: CHANNEL_ID,
|
|
36209
|
+
id: senderId,
|
|
36210
|
+
accountId: account.accountId,
|
|
36211
|
+
meta: {},
|
|
36212
|
+
pairingAdapter: { idLabel: "inlineUserId", normalizeAllowEntry }
|
|
36183
36213
|
});
|
|
36184
|
-
|
|
36185
|
-
|
|
36186
|
-
|
|
36187
|
-
|
|
36188
|
-
|
|
36189
|
-
|
|
36190
|
-
|
|
36191
|
-
|
|
36192
|
-
|
|
36193
|
-
accountId: account.accountId,
|
|
36194
|
-
meta: {},
|
|
36195
|
-
pairingAdapter: { idLabel: "inlineUserId", normalizeAllowEntry }
|
|
36214
|
+
if (created) {
|
|
36215
|
+
try {
|
|
36216
|
+
await client.sendMessage({
|
|
36217
|
+
chatId,
|
|
36218
|
+
text: core3.channel.pairing.buildPairingReply({
|
|
36219
|
+
channel: CHANNEL_ID,
|
|
36220
|
+
idLine: `Your Inline user id: ${senderId}`,
|
|
36221
|
+
code
|
|
36222
|
+
})
|
|
36196
36223
|
});
|
|
36197
|
-
|
|
36198
|
-
|
|
36199
|
-
|
|
36200
|
-
chatId,
|
|
36201
|
-
text: core3.channel.pairing.buildPairingReply({
|
|
36202
|
-
channel: CHANNEL_ID,
|
|
36203
|
-
idLine: `Your Inline user id: ${senderId}`,
|
|
36204
|
-
code
|
|
36205
|
-
})
|
|
36206
|
-
});
|
|
36207
|
-
statusSink?.({ lastOutboundAt: Date.now() });
|
|
36208
|
-
} catch (err) {
|
|
36209
|
-
runtime2.error?.(`inline: pairing reply failed for ${senderId}: ${String(err)}`);
|
|
36210
|
-
}
|
|
36211
|
-
}
|
|
36224
|
+
statusSink?.({ lastOutboundAt: Date.now() });
|
|
36225
|
+
} catch (err) {
|
|
36226
|
+
runtime2.error?.(`inline: pairing reply failed for ${senderId}: ${String(err)}`);
|
|
36212
36227
|
}
|
|
36213
|
-
log?.info(`[${account.accountId}] inline: drop DM sender=${senderId} (dmPolicy=${dmPolicy})`);
|
|
36214
|
-
await answerCallbackIfNeeded().catch((error48) => {
|
|
36215
|
-
runtime2.error?.(`inline callback answer failed: ${String(error48)}`);
|
|
36216
|
-
});
|
|
36217
|
-
continue;
|
|
36218
36228
|
}
|
|
36219
36229
|
}
|
|
36220
|
-
|
|
36221
|
-
if (isGroup && commandGate.shouldBlock) {
|
|
36222
|
-
logInboundDrop({
|
|
36223
|
-
log: (m) => runtime2.log?.(m),
|
|
36224
|
-
channel: CHANNEL_ID,
|
|
36225
|
-
reason: "control command (unauthorized)",
|
|
36226
|
-
target: senderId
|
|
36227
|
-
});
|
|
36230
|
+
log?.info(`[${account.accountId}] inline: drop DM sender=${senderId} (dmPolicy=${dmPolicy})`);
|
|
36228
36231
|
await answerCallbackIfNeeded().catch((error48) => {
|
|
36229
36232
|
runtime2.error?.(`inline callback answer failed: ${String(error48)}`);
|
|
36230
36233
|
});
|
|
36231
|
-
|
|
36234
|
+
return;
|
|
36232
36235
|
}
|
|
36233
|
-
|
|
36234
|
-
|
|
36235
|
-
|
|
36236
|
-
|
|
36237
|
-
|
|
36238
|
-
|
|
36239
|
-
|
|
36236
|
+
}
|
|
36237
|
+
}
|
|
36238
|
+
if (isGroup && commandGate.shouldBlock) {
|
|
36239
|
+
logInboundDrop({
|
|
36240
|
+
log: (m) => runtime2.log?.(m),
|
|
36241
|
+
channel: CHANNEL_ID,
|
|
36242
|
+
reason: "control command (unauthorized)",
|
|
36243
|
+
target: senderId
|
|
36244
|
+
});
|
|
36245
|
+
await answerCallbackIfNeeded().catch((error48) => {
|
|
36246
|
+
runtime2.error?.(`inline callback answer failed: ${String(error48)}`);
|
|
36247
|
+
});
|
|
36248
|
+
return;
|
|
36249
|
+
}
|
|
36250
|
+
const route = core3.channel.routing.resolveAgentRoute({
|
|
36251
|
+
cfg,
|
|
36252
|
+
channel: CHANNEL_ID,
|
|
36253
|
+
accountId: account.accountId,
|
|
36254
|
+
peer: {
|
|
36255
|
+
kind: isGroup ? "group" : "direct",
|
|
36256
|
+
id: isGroup ? String(effectiveChatId) : senderId
|
|
36257
|
+
}
|
|
36258
|
+
});
|
|
36259
|
+
const mentionRegexes = core3.channel.mentions.buildMentionRegexes(cfg, route.agentId);
|
|
36260
|
+
const nativeMentioned = typeof msg.mentioned === "boolean" ? msg.mentioned : false;
|
|
36261
|
+
const patternMentioned = mentionRegexes.length ? core3.channel.mentions.matchesMentionPatterns(rawBody, mentionRegexes) : false;
|
|
36262
|
+
const wasMentioned = nativeMentioned || patternMentioned;
|
|
36263
|
+
const messageTimestamp = Number(msg.date) * 1000;
|
|
36264
|
+
const groupHistoryKey = isGroup ? replyThreadContext ? `${route.sessionKey}:thread:${String(replyThreadContext.childChatId)}` : route.sessionKey : null;
|
|
36265
|
+
const pendingHistorySender = senderUsername ? `@${senderUsername}` : senderName ?? `user:${senderId}`;
|
|
36266
|
+
const historyLimit = resolveHistoryLimit({
|
|
36267
|
+
cfg,
|
|
36268
|
+
isGroup,
|
|
36269
|
+
historyLimit: account.config.historyLimit,
|
|
36270
|
+
dmHistoryLimit: account.config.dmHistoryLimit
|
|
36271
|
+
});
|
|
36272
|
+
const historyContext = await buildHistoryContext2({
|
|
36273
|
+
client,
|
|
36274
|
+
chatId,
|
|
36275
|
+
currentMessageId: msg.id,
|
|
36276
|
+
replyToMsgId: msg.replyToMsgId,
|
|
36277
|
+
senderProfilesById,
|
|
36278
|
+
meId,
|
|
36279
|
+
historyLimit,
|
|
36280
|
+
botMessageIdsByChat
|
|
36281
|
+
}).catch((err) => {
|
|
36282
|
+
statusSink?.({ lastError: `getChatHistory failed: ${String(err)}` });
|
|
36283
|
+
return {
|
|
36284
|
+
historyText: null,
|
|
36285
|
+
attachmentText: null,
|
|
36286
|
+
entityText: null,
|
|
36287
|
+
inboundHistory: [],
|
|
36288
|
+
repliedToBot: false,
|
|
36289
|
+
replyToSenderId: null
|
|
36290
|
+
};
|
|
36291
|
+
});
|
|
36292
|
+
const effectiveHistoryContext = replyThreadContext?.anchorMessage != null ? prependInlineReplyThreadAnchor({
|
|
36293
|
+
historyContext,
|
|
36294
|
+
anchorMessage: replyThreadContext.anchorMessage,
|
|
36295
|
+
parentChatId: replyThreadContext.parentChatId,
|
|
36296
|
+
senderProfilesById,
|
|
36297
|
+
meId
|
|
36298
|
+
}) : historyContext;
|
|
36299
|
+
const implicitMention = (reactionEvent != null || callbackActionEvent != null) && isGroup || isGroup && (account.config.replyToBotWithoutMention ?? false) && msg.replyToMsgId != null && effectiveHistoryContext.repliedToBot;
|
|
36300
|
+
const requireMention = isGroup ? resolveInlineGroupRequireMention({
|
|
36301
|
+
cfg,
|
|
36302
|
+
groupId: String(effectiveChatId),
|
|
36303
|
+
accountId: account.accountId,
|
|
36304
|
+
requireMentionDefault: account.config.requireMention ?? false
|
|
36305
|
+
}) : false;
|
|
36306
|
+
const mentionGate = resolveMentionGatingWithBypass({
|
|
36307
|
+
isGroup,
|
|
36308
|
+
requireMention,
|
|
36309
|
+
canDetectMention: typeof msg.mentioned === "boolean" || mentionRegexes.length > 0,
|
|
36310
|
+
wasMentioned,
|
|
36311
|
+
implicitMention,
|
|
36312
|
+
allowTextCommands,
|
|
36313
|
+
hasControlCommand,
|
|
36314
|
+
commandAuthorized
|
|
36315
|
+
});
|
|
36316
|
+
if (isGroup && mentionGate.shouldSkip) {
|
|
36317
|
+
runtime2.log?.(`inline: drop group chat ${String(chatId)} (no mention)`);
|
|
36318
|
+
const pendingBody = normalizeHistoryText(currentContent?.text) ?? normalizeHistoryText(rawBody);
|
|
36319
|
+
recordPendingHistoryEntryIfEnabled({
|
|
36320
|
+
historyMap: groupPendingHistories,
|
|
36321
|
+
historyKey: groupHistoryKey ?? "",
|
|
36322
|
+
limit: historyLimit,
|
|
36323
|
+
entry: groupHistoryKey && pendingBody ? {
|
|
36324
|
+
sender: pendingHistorySender,
|
|
36325
|
+
body: pendingBody,
|
|
36326
|
+
timestamp: messageTimestamp || Date.now(),
|
|
36327
|
+
messageId: String(msg.id)
|
|
36328
|
+
} : null
|
|
36329
|
+
});
|
|
36330
|
+
await answerCallbackIfNeeded().catch((error48) => {
|
|
36331
|
+
runtime2.error?.(`inline callback answer failed: ${String(error48)}`);
|
|
36332
|
+
});
|
|
36333
|
+
return;
|
|
36334
|
+
}
|
|
36335
|
+
const parseMarkdown = account.config.parseMarkdown ?? true;
|
|
36336
|
+
const nativeCommandMenu = resolveInlineNativeCommandMenu({
|
|
36337
|
+
commandBody: normalizedCommandBody,
|
|
36338
|
+
cfg
|
|
36339
|
+
});
|
|
36340
|
+
if (nativeCommandMenu) {
|
|
36341
|
+
const menuActions = resolveInlineReplyActions({
|
|
36342
|
+
channelData: {
|
|
36343
|
+
inline: {
|
|
36344
|
+
buttons: nativeCommandMenu.buttons
|
|
36240
36345
|
}
|
|
36241
|
-
}
|
|
36242
|
-
|
|
36243
|
-
|
|
36244
|
-
|
|
36245
|
-
|
|
36246
|
-
|
|
36247
|
-
|
|
36248
|
-
|
|
36249
|
-
|
|
36250
|
-
|
|
36251
|
-
|
|
36252
|
-
|
|
36253
|
-
|
|
36254
|
-
|
|
36255
|
-
|
|
36256
|
-
|
|
36346
|
+
}
|
|
36347
|
+
});
|
|
36348
|
+
let deliveredNativeMenu = false;
|
|
36349
|
+
if (shouldEditCallbackTargetInPlace && callbackActionEvent) {
|
|
36350
|
+
try {
|
|
36351
|
+
const result = await client.invokeRaw(Method.EDIT_MESSAGE, {
|
|
36352
|
+
oneofKind: "editMessage",
|
|
36353
|
+
editMessage: {
|
|
36354
|
+
messageId: callbackActionEvent.targetMessageId,
|
|
36355
|
+
peerId: buildChatPeer2(chatId),
|
|
36356
|
+
text: nativeCommandMenu.title,
|
|
36357
|
+
...menuActions ? { actions: menuActions } : {},
|
|
36358
|
+
parseMarkdown
|
|
36359
|
+
}
|
|
36360
|
+
});
|
|
36361
|
+
if (result.oneofKind !== "editMessage") {
|
|
36362
|
+
throw new Error(`inline native command menu: expected editMessage result, got ${String(result.oneofKind)}`);
|
|
36363
|
+
}
|
|
36364
|
+
deliveredNativeMenu = true;
|
|
36365
|
+
} catch (error48) {
|
|
36366
|
+
runtime2.error?.(`inline native command menu edit failed; falling back to send (${String(error48)})`);
|
|
36367
|
+
}
|
|
36368
|
+
}
|
|
36369
|
+
if (!deliveredNativeMenu) {
|
|
36370
|
+
const sent = await client.sendMessage({
|
|
36257
36371
|
chatId,
|
|
36258
|
-
|
|
36259
|
-
|
|
36260
|
-
senderProfilesById,
|
|
36261
|
-
meId,
|
|
36262
|
-
historyLimit,
|
|
36263
|
-
botMessageIdsByChat
|
|
36264
|
-
}).catch((err) => {
|
|
36265
|
-
statusSink?.({ lastError: `getChatHistory failed: ${String(err)}` });
|
|
36266
|
-
return {
|
|
36267
|
-
historyText: null,
|
|
36268
|
-
attachmentText: null,
|
|
36269
|
-
entityText: null,
|
|
36270
|
-
inboundHistory: [],
|
|
36271
|
-
repliedToBot: false,
|
|
36272
|
-
replyToSenderId: null
|
|
36273
|
-
};
|
|
36372
|
+
text: nativeCommandMenu.title,
|
|
36373
|
+
...menuActions ? { actions: menuActions } : {}
|
|
36274
36374
|
});
|
|
36275
|
-
|
|
36276
|
-
|
|
36277
|
-
anchorMessage: replyThreadContext.anchorMessage,
|
|
36278
|
-
parentChatId: replyThreadContext.parentChatId,
|
|
36279
|
-
senderProfilesById,
|
|
36280
|
-
meId
|
|
36281
|
-
}) : historyContext;
|
|
36282
|
-
const implicitMention = (reactionEvent != null || callbackActionEvent != null) && isGroup || isGroup && (account.config.replyToBotWithoutMention ?? false) && msg.replyToMsgId != null && effectiveHistoryContext.repliedToBot;
|
|
36283
|
-
const requireMention = isGroup ? resolveInlineGroupRequireMention({
|
|
36284
|
-
cfg,
|
|
36285
|
-
groupId: String(effectiveChatId),
|
|
36286
|
-
accountId: account.accountId,
|
|
36287
|
-
requireMentionDefault: account.config.requireMention ?? false
|
|
36288
|
-
}) : false;
|
|
36289
|
-
const mentionGate = resolveMentionGatingWithBypass({
|
|
36290
|
-
isGroup,
|
|
36291
|
-
requireMention,
|
|
36292
|
-
canDetectMention: typeof msg.mentioned === "boolean" || mentionRegexes.length > 0,
|
|
36293
|
-
wasMentioned,
|
|
36294
|
-
implicitMention,
|
|
36295
|
-
allowTextCommands,
|
|
36296
|
-
hasControlCommand,
|
|
36297
|
-
commandAuthorized
|
|
36298
|
-
});
|
|
36299
|
-
if (isGroup && mentionGate.shouldSkip) {
|
|
36300
|
-
runtime2.log?.(`inline: drop group chat ${String(chatId)} (no mention)`);
|
|
36301
|
-
const pendingBody = normalizeHistoryText(currentContent?.text) ?? normalizeHistoryText(rawBody);
|
|
36302
|
-
recordPendingHistoryEntryIfEnabled({
|
|
36303
|
-
historyMap: groupPendingHistories,
|
|
36304
|
-
historyKey: groupHistoryKey ?? "",
|
|
36305
|
-
limit: historyLimit,
|
|
36306
|
-
entry: groupHistoryKey && pendingBody ? {
|
|
36307
|
-
sender: pendingHistorySender,
|
|
36308
|
-
body: pendingBody,
|
|
36309
|
-
timestamp: messageTimestamp || Date.now(),
|
|
36310
|
-
messageId: String(msg.id)
|
|
36311
|
-
} : null
|
|
36312
|
-
});
|
|
36313
|
-
await answerCallbackIfNeeded().catch((error48) => {
|
|
36314
|
-
runtime2.error?.(`inline callback answer failed: ${String(error48)}`);
|
|
36315
|
-
});
|
|
36316
|
-
continue;
|
|
36375
|
+
if (sent.messageId != null) {
|
|
36376
|
+
rememberBotMessageId(botMessageIdsByChat, chatId, sent.messageId);
|
|
36317
36377
|
}
|
|
36318
|
-
|
|
36319
|
-
|
|
36320
|
-
|
|
36321
|
-
|
|
36322
|
-
|
|
36323
|
-
|
|
36324
|
-
|
|
36325
|
-
|
|
36378
|
+
}
|
|
36379
|
+
statusSink?.({ lastOutboundAt: Date.now() });
|
|
36380
|
+
await answerCallbackIfNeeded().catch((error48) => {
|
|
36381
|
+
runtime2.error?.(`inline callback answer failed: ${String(error48)}`);
|
|
36382
|
+
});
|
|
36383
|
+
return;
|
|
36384
|
+
}
|
|
36385
|
+
const modelPickerCallbackData = callbackActionEvent ? callbackDataToUtf8(callbackActionEvent.data) : undefined;
|
|
36386
|
+
const modelPickerCallback = modelPickerCallbackData ? parseInlineModelPickerCallback(modelPickerCallbackData) : null;
|
|
36387
|
+
if (shouldEditCallbackTargetInPlace && callbackActionEvent && modelPickerCallback?.type === "select") {
|
|
36388
|
+
const deliverModelPickerEdit = async (text, buttons) => {
|
|
36389
|
+
const actions = resolveInlineReplyActions({
|
|
36390
|
+
channelData: {
|
|
36391
|
+
inline: {
|
|
36392
|
+
buttons
|
|
36393
|
+
}
|
|
36394
|
+
}
|
|
36395
|
+
}) ?? { rows: [] };
|
|
36396
|
+
try {
|
|
36397
|
+
const result = await client.invokeRaw(Method.EDIT_MESSAGE, {
|
|
36398
|
+
oneofKind: "editMessage",
|
|
36399
|
+
editMessage: {
|
|
36400
|
+
messageId: callbackActionEvent.targetMessageId,
|
|
36401
|
+
peerId: buildChatPeer2(chatId),
|
|
36402
|
+
text,
|
|
36403
|
+
actions,
|
|
36404
|
+
parseMarkdown
|
|
36326
36405
|
}
|
|
36327
36406
|
});
|
|
36407
|
+
if (result.oneofKind !== "editMessage") {
|
|
36408
|
+
throw new Error(`inline model picker edit: expected editMessage result, got ${String(result.oneofKind)}`);
|
|
36409
|
+
}
|
|
36410
|
+
} catch (error48) {
|
|
36411
|
+
runtime2.error?.(`inline model picker edit failed; falling back to send (${String(error48)})`);
|
|
36328
36412
|
const sent = await client.sendMessage({
|
|
36329
36413
|
chatId,
|
|
36330
|
-
text
|
|
36331
|
-
|
|
36414
|
+
text,
|
|
36415
|
+
actions,
|
|
36416
|
+
parseMarkdown
|
|
36332
36417
|
});
|
|
36333
36418
|
if (sent.messageId != null) {
|
|
36334
36419
|
rememberBotMessageId(botMessageIdsByChat, chatId, sent.messageId);
|
|
36335
36420
|
}
|
|
36336
|
-
statusSink?.({ lastOutboundAt: Date.now() });
|
|
36337
|
-
await answerCallbackIfNeeded().catch((error48) => {
|
|
36338
|
-
runtime2.error?.(`inline callback answer failed: ${String(error48)}`);
|
|
36339
|
-
});
|
|
36340
|
-
continue;
|
|
36341
36421
|
}
|
|
36342
|
-
|
|
36343
|
-
|
|
36344
|
-
|
|
36345
|
-
|
|
36346
|
-
|
|
36347
|
-
|
|
36348
|
-
|
|
36349
|
-
|
|
36350
|
-
|
|
36351
|
-
|
|
36352
|
-
|
|
36353
|
-
|
|
36354
|
-
|
|
36355
|
-
|
|
36356
|
-
|
|
36357
|
-
|
|
36358
|
-
|
|
36422
|
+
};
|
|
36423
|
+
const { byProvider, providers } = await buildModelsProviderData(cfg, route.agentId);
|
|
36424
|
+
const providerButtons = buildInlineModelProviderButtons(providers.map((provider) => ({
|
|
36425
|
+
id: provider,
|
|
36426
|
+
count: byProvider.get(provider)?.size ?? 0
|
|
36427
|
+
})));
|
|
36428
|
+
const selection = resolveInlineModelPickerSelection({
|
|
36429
|
+
callback: modelPickerCallback,
|
|
36430
|
+
providers,
|
|
36431
|
+
byProvider
|
|
36432
|
+
});
|
|
36433
|
+
if (selection.kind !== "resolved") {
|
|
36434
|
+
await deliverModelPickerEdit(`Could not resolve model "${selection.model}".
|
|
36435
|
+
|
|
36436
|
+
Select a provider:`, providerButtons);
|
|
36437
|
+
} else {
|
|
36438
|
+
const modelSet = byProvider.get(selection.provider);
|
|
36439
|
+
if (!modelSet?.has(selection.model)) {
|
|
36440
|
+
await deliverModelPickerEdit(`❌ Model "${selection.provider}/${selection.model}" is not allowed.`, []);
|
|
36441
|
+
} else {
|
|
36442
|
+
try {
|
|
36443
|
+
const storePath2 = core3.channel.session.resolveStorePath(cfg.session?.store, {
|
|
36444
|
+
agentId: route.agentId
|
|
36445
|
+
});
|
|
36446
|
+
const resolvedDefault = resolveDefaultModelForAgent({
|
|
36447
|
+
cfg,
|
|
36448
|
+
agentId: route.agentId
|
|
36449
|
+
});
|
|
36450
|
+
const isDefaultSelection = selection.provider === resolvedDefault.provider && selection.model === resolvedDefault.model;
|
|
36451
|
+
await updateSessionStore(storePath2, (store) => {
|
|
36452
|
+
const entry = store[route.sessionKey] ?? {
|
|
36453
|
+
sessionId: route.sessionKey,
|
|
36454
|
+
updatedAt: Date.now()
|
|
36455
|
+
};
|
|
36456
|
+
store[route.sessionKey] = entry;
|
|
36457
|
+
applyModelOverrideToSessionEntry({
|
|
36458
|
+
entry,
|
|
36459
|
+
selection: {
|
|
36460
|
+
provider: selection.provider,
|
|
36461
|
+
model: selection.model,
|
|
36462
|
+
isDefault: isDefaultSelection
|
|
36463
|
+
}
|
|
36464
|
+
});
|
|
36465
|
+
});
|
|
36466
|
+
const actionText = isDefaultSelection ? "reset to default" : `changed to **${selection.provider}/${selection.model}**`;
|
|
36467
|
+
await deliverModelPickerEdit(`✅ Model ${actionText}
|
|
36468
|
+
|
|
36469
|
+
This model will be used for your next message.`, []);
|
|
36470
|
+
} catch (error48) {
|
|
36471
|
+
await deliverModelPickerEdit(`❌ Failed to change model: ${String(error48)}`, []);
|
|
36472
|
+
}
|
|
36473
|
+
}
|
|
36474
|
+
}
|
|
36475
|
+
statusSink?.({ lastOutboundAt: Date.now() });
|
|
36476
|
+
await answerCallbackIfNeeded().catch((error48) => {
|
|
36477
|
+
runtime2.error?.(`inline callback answer failed: ${String(error48)}`);
|
|
36478
|
+
});
|
|
36479
|
+
return;
|
|
36480
|
+
}
|
|
36481
|
+
const inboundMedia = reactionEvent ? [] : await resolveInlineInboundMedia({
|
|
36482
|
+
core: core3,
|
|
36483
|
+
message: msg,
|
|
36484
|
+
maxBytes: inboundMediaMaxBytes,
|
|
36485
|
+
...log ? { log } : {}
|
|
36486
|
+
});
|
|
36487
|
+
const timestamp = messageTimestamp;
|
|
36488
|
+
const fromLabel = isGroup ? `chat:${effectiveGroupTitle ?? String(effectiveChatId)}` : `user:${senderId}`;
|
|
36489
|
+
const storePath = core3.channel.session.resolveStorePath(cfg.session?.store, { agentId: route.agentId });
|
|
36490
|
+
const envelopeOptions = core3.channel.reply.resolveEnvelopeFormatOptions(cfg);
|
|
36491
|
+
const previousTimestamp = core3.channel.session.readSessionUpdatedAt({ storePath, sessionKey: route.sessionKey });
|
|
36492
|
+
const combinedBody = [
|
|
36493
|
+
effectiveHistoryContext.historyText,
|
|
36494
|
+
effectiveHistoryContext.attachmentText,
|
|
36495
|
+
effectiveHistoryContext.entityText,
|
|
36496
|
+
INLINE_FORMATTING_NOTE,
|
|
36497
|
+
`Current message:
|
|
36359
36498
|
${rawBody}`,
|
|
36360
|
-
|
|
36499
|
+
currentAttachmentText && currentAttachmentText !== rawBody ? `Current media/attachments:
|
|
36361
36500
|
${currentAttachmentText}` : null,
|
|
36362
|
-
|
|
36501
|
+
currentEntityText ? `Current message entities:
|
|
36363
36502
|
${currentEntityText}` : null
|
|
36364
|
-
|
|
36503
|
+
].filter(Boolean).join(`
|
|
36365
36504
|
|
|
36366
36505
|
`);
|
|
36367
|
-
|
|
36506
|
+
let body = core3.channel.reply.formatAgentEnvelope({
|
|
36507
|
+
channel: "Inline",
|
|
36508
|
+
from: fromLabel,
|
|
36509
|
+
timestamp,
|
|
36510
|
+
...previousTimestamp != null ? { previousTimestamp } : {},
|
|
36511
|
+
envelope: envelopeOptions,
|
|
36512
|
+
body: combinedBody || rawBody
|
|
36513
|
+
});
|
|
36514
|
+
if (isGroup && groupHistoryKey) {
|
|
36515
|
+
body = buildPendingHistoryContextFromMap({
|
|
36516
|
+
historyMap: groupPendingHistories,
|
|
36517
|
+
historyKey: groupHistoryKey,
|
|
36518
|
+
limit: historyLimit,
|
|
36519
|
+
currentMessage: body,
|
|
36520
|
+
formatEntry: (entry) => core3.channel.reply.formatAgentEnvelope({
|
|
36368
36521
|
channel: "Inline",
|
|
36369
36522
|
from: fromLabel,
|
|
36370
|
-
timestamp,
|
|
36371
|
-
...previousTimestamp != null ? { previousTimestamp } : {},
|
|
36523
|
+
...entry.timestamp != null ? { timestamp: entry.timestamp } : {},
|
|
36372
36524
|
envelope: envelopeOptions,
|
|
36373
|
-
body:
|
|
36374
|
-
})
|
|
36375
|
-
|
|
36376
|
-
|
|
36377
|
-
|
|
36378
|
-
|
|
36379
|
-
|
|
36380
|
-
|
|
36381
|
-
|
|
36382
|
-
|
|
36383
|
-
|
|
36384
|
-
|
|
36385
|
-
|
|
36386
|
-
|
|
36387
|
-
|
|
36388
|
-
|
|
36525
|
+
body: `${entry.body}${entry.messageId ? ` [id:${entry.messageId} chat:${String(chatId)}]` : ""}`
|
|
36526
|
+
})
|
|
36527
|
+
});
|
|
36528
|
+
}
|
|
36529
|
+
const inboundHistory = isGroup && groupHistoryKey ? mergeInboundHistoryEntries({
|
|
36530
|
+
historyContextEntries: effectiveHistoryContext.inboundHistory,
|
|
36531
|
+
pendingEntries: groupPendingHistories.get(groupHistoryKey) ?? [],
|
|
36532
|
+
limit: historyLimit
|
|
36533
|
+
}) : [];
|
|
36534
|
+
const bodyForAgent = buildInlineBodyForAgent({
|
|
36535
|
+
rawBody,
|
|
36536
|
+
currentAttachmentText,
|
|
36537
|
+
currentEntityText
|
|
36538
|
+
});
|
|
36539
|
+
const effectiveSurface = shouldUseTelegramSurfaceForModelCommands(normalizedCommandBody) ? "telegram" : CHANNEL_ID;
|
|
36540
|
+
const systemPrompt = resolveInlineSystemPrompt({
|
|
36541
|
+
account,
|
|
36542
|
+
...isGroup ? { groupId: String(effectiveChatId) } : {}
|
|
36543
|
+
});
|
|
36544
|
+
const ctxPayload = core3.channel.reply.finalizeInboundContext({
|
|
36545
|
+
Body: body,
|
|
36546
|
+
BodyForAgent: bodyForAgent,
|
|
36547
|
+
...isGroup ? { InboundHistory: inboundHistory } : {},
|
|
36548
|
+
RawBody: rawBody,
|
|
36549
|
+
CommandBody: normalizedCommandBody,
|
|
36550
|
+
From: isGroup ? `inline:chat:${String(effectiveChatId)}` : `inline:${senderId}`,
|
|
36551
|
+
To: `inline:${String(effectiveChatId)}`,
|
|
36552
|
+
SessionKey: route.sessionKey,
|
|
36553
|
+
...replyThreadContext ? { ParentSessionKey: route.sessionKey } : {},
|
|
36554
|
+
AccountId: route.accountId,
|
|
36555
|
+
ChatType: isGroup ? "group" : "direct",
|
|
36556
|
+
ConversationLabel: fromLabel,
|
|
36557
|
+
...isGroup ? { GroupSubject: effectiveGroupTitle ?? String(effectiveChatId) } : {},
|
|
36558
|
+
SenderId: senderId,
|
|
36559
|
+
...senderName ? { SenderName: senderName } : {},
|
|
36560
|
+
...senderUsername ? { SenderUsername: senderUsername } : {},
|
|
36561
|
+
Provider: CHANNEL_ID,
|
|
36562
|
+
Surface: effectiveSurface,
|
|
36563
|
+
MessageSid: buildInlineInboundMessageSid({
|
|
36564
|
+
msgId: msg.id,
|
|
36565
|
+
...callbackActionEvent ? { callbackActionEvent } : {}
|
|
36566
|
+
}),
|
|
36567
|
+
...replyThreadContext ? { MessageThreadId: String(replyThreadContext.childChatId) } : {},
|
|
36568
|
+
...replyThreadContext?.threadLabel ? { ThreadLabel: replyThreadContext.threadLabel } : {},
|
|
36569
|
+
...msg.replyToMsgId != null ? { ReplyToId: String(msg.replyToMsgId) } : {},
|
|
36570
|
+
...effectiveHistoryContext.replyToSenderId != null ? { ReplyToSenderId: effectiveHistoryContext.replyToSenderId } : {},
|
|
36571
|
+
...msg.replyToMsgId != null ? { ReplyToWasBot: effectiveHistoryContext.repliedToBot } : {},
|
|
36572
|
+
...callbackActionEvent ? {
|
|
36573
|
+
MessageActionInteractionId: String(callbackActionEvent.interactionId),
|
|
36574
|
+
MessageActionId: callbackActionEvent.actionId,
|
|
36575
|
+
MessageActionDataBase64: callbackDataToBase64(callbackActionEvent.data),
|
|
36576
|
+
...callbackDataToUtf8(callbackActionEvent.data) ? { MessageActionDataUtf8: callbackDataToUtf8(callbackActionEvent.data) } : {}
|
|
36577
|
+
} : {},
|
|
36578
|
+
...buildInlineInboundMediaPayload(inboundMedia),
|
|
36579
|
+
Timestamp: timestamp || Date.now(),
|
|
36580
|
+
WasMentioned: mentionGate.effectiveWasMentioned,
|
|
36581
|
+
CommandAuthorized: commandAuthorized,
|
|
36582
|
+
GroupSystemPrompt: systemPrompt,
|
|
36583
|
+
OriginatingChannel: CHANNEL_ID,
|
|
36584
|
+
OriginatingTo: `inline:${String(effectiveChatId)}`
|
|
36585
|
+
});
|
|
36586
|
+
await core3.channel.session.recordInboundSession({
|
|
36587
|
+
storePath,
|
|
36588
|
+
sessionKey: ctxPayload.SessionKey ?? route.sessionKey,
|
|
36589
|
+
ctx: ctxPayload,
|
|
36590
|
+
...!isGroup ? {
|
|
36591
|
+
updateLastRoute: {
|
|
36592
|
+
sessionKey: route.mainSessionKey,
|
|
36593
|
+
channel: CHANNEL_ID,
|
|
36594
|
+
to: `inline:${String(effectiveChatId)}`,
|
|
36595
|
+
accountId: route.accountId
|
|
36389
36596
|
}
|
|
36390
|
-
|
|
36391
|
-
|
|
36392
|
-
|
|
36393
|
-
|
|
36394
|
-
|
|
36395
|
-
|
|
36396
|
-
|
|
36397
|
-
|
|
36398
|
-
|
|
36399
|
-
})
|
|
36400
|
-
|
|
36401
|
-
|
|
36402
|
-
|
|
36403
|
-
|
|
36404
|
-
|
|
36405
|
-
|
|
36406
|
-
|
|
36407
|
-
|
|
36408
|
-
|
|
36409
|
-
|
|
36410
|
-
|
|
36411
|
-
|
|
36412
|
-
|
|
36413
|
-
|
|
36414
|
-
|
|
36415
|
-
|
|
36416
|
-
|
|
36417
|
-
|
|
36418
|
-
|
|
36419
|
-
|
|
36420
|
-
|
|
36421
|
-
|
|
36422
|
-
|
|
36423
|
-
|
|
36424
|
-
|
|
36425
|
-
|
|
36426
|
-
|
|
36427
|
-
|
|
36428
|
-
|
|
36429
|
-
|
|
36430
|
-
|
|
36431
|
-
|
|
36432
|
-
|
|
36433
|
-
|
|
36434
|
-
|
|
36435
|
-
|
|
36436
|
-
|
|
36437
|
-
|
|
36438
|
-
|
|
36439
|
-
|
|
36440
|
-
|
|
36441
|
-
|
|
36442
|
-
|
|
36443
|
-
|
|
36444
|
-
|
|
36445
|
-
|
|
36446
|
-
|
|
36447
|
-
|
|
36448
|
-
|
|
36449
|
-
|
|
36450
|
-
|
|
36451
|
-
|
|
36452
|
-
|
|
36453
|
-
|
|
36597
|
+
} : {},
|
|
36598
|
+
onRecordError: (err) => runtime2.error?.(`inline: failed updating session meta: ${String(err)}`)
|
|
36599
|
+
});
|
|
36600
|
+
const replyPipeline = await createChannelReplyPipelineCompat({
|
|
36601
|
+
cfg,
|
|
36602
|
+
agentId: route.agentId,
|
|
36603
|
+
channel: CHANNEL_ID,
|
|
36604
|
+
accountId: account.accountId,
|
|
36605
|
+
typing: {
|
|
36606
|
+
start: () => client.sendTyping({ chatId, typing: true }),
|
|
36607
|
+
stop: () => client.sendTyping({ chatId, typing: false }),
|
|
36608
|
+
onStartError: (err) => runtime2.error?.(`inline typing start failed: ${String(err)}`),
|
|
36609
|
+
onStopError: (err) => runtime2.error?.(`inline typing stop failed: ${String(err)}`)
|
|
36610
|
+
}
|
|
36611
|
+
});
|
|
36612
|
+
const onModelSelected = replyPipeline.onModelSelected;
|
|
36613
|
+
const typingCallbacks = replyPipeline.typingCallbacks;
|
|
36614
|
+
const prefixOptions = {
|
|
36615
|
+
...replyPipeline.responsePrefix !== undefined ? { responsePrefix: replyPipeline.responsePrefix } : {},
|
|
36616
|
+
...replyPipeline.enableSlackInteractiveReplies !== undefined ? { enableSlackInteractiveReplies: replyPipeline.enableSlackInteractiveReplies } : {},
|
|
36617
|
+
...replyPipeline.responsePrefixContextProvider ? {
|
|
36618
|
+
responsePrefixContextProvider: replyPipeline.responsePrefixContextProvider
|
|
36619
|
+
} : {}
|
|
36620
|
+
};
|
|
36621
|
+
const callbackTargetMessage = shouldEditCallbackTargetInPlace && callbackActionEvent ? await findChatMessageById({
|
|
36622
|
+
client,
|
|
36623
|
+
chatId,
|
|
36624
|
+
messageId: callbackActionEvent.targetMessageId,
|
|
36625
|
+
limit: REPLY_TARGET_LOOKUP_LIMIT,
|
|
36626
|
+
meId,
|
|
36627
|
+
botMessageIdsByChat
|
|
36628
|
+
}).catch(() => null) : null;
|
|
36629
|
+
const streamViaEditMessage = account.config.streamViaEditMessage === true && !shouldEditCallbackTargetInPlace;
|
|
36630
|
+
const defaultReplyToMsgId = isGroup && msg.replyToMsgId != null ? msg.id : undefined;
|
|
36631
|
+
const disableBlockStreaming = streamViaEditMessage ? true : typeof account.config.blockStreaming === "boolean" ? !account.config.blockStreaming : undefined;
|
|
36632
|
+
const editStreamState = {
|
|
36633
|
+
messageId: shouldEditCallbackTargetInPlace ? callbackActionEvent?.targetMessageId ?? null : null,
|
|
36634
|
+
accumulatedText: callbackTargetMessage?.message ?? "",
|
|
36635
|
+
lastPartialText: "",
|
|
36636
|
+
finalTextAccumulator: "",
|
|
36637
|
+
failed: false,
|
|
36638
|
+
opChain: Promise.resolve()
|
|
36639
|
+
};
|
|
36640
|
+
let finalDeliveredForCurrentAssistantMessage = false;
|
|
36641
|
+
const resetEditStreamForAssistantMessage = async () => {
|
|
36642
|
+
await editStreamState.opChain;
|
|
36643
|
+
const hasActiveState = editStreamState.messageId != null || editStreamState.accumulatedText.length > 0 || editStreamState.lastPartialText.length > 0 || editStreamState.finalTextAccumulator.length > 0;
|
|
36644
|
+
if (!hasActiveState)
|
|
36645
|
+
return;
|
|
36646
|
+
editStreamState.messageId = null;
|
|
36647
|
+
editStreamState.accumulatedText = "";
|
|
36648
|
+
editStreamState.lastPartialText = "";
|
|
36649
|
+
editStreamState.finalTextAccumulator = "";
|
|
36650
|
+
editStreamState.failed = false;
|
|
36651
|
+
finalDeliveredForCurrentAssistantMessage = false;
|
|
36652
|
+
};
|
|
36653
|
+
const resetEditStreamOnBoundary = async () => {
|
|
36654
|
+
if (!streamViaEditMessage)
|
|
36655
|
+
return;
|
|
36656
|
+
await resetEditStreamForAssistantMessage();
|
|
36657
|
+
};
|
|
36658
|
+
const handlePartialStreamPayload = async (payload) => {
|
|
36659
|
+
if (editStreamState.failed)
|
|
36660
|
+
return;
|
|
36661
|
+
if ((payload.mediaUrls?.length ?? 0) > 0)
|
|
36662
|
+
return;
|
|
36663
|
+
const partialText = typeof payload.text === "string" ? payload.text : "";
|
|
36664
|
+
if (!partialText || partialText === editStreamState.lastPartialText)
|
|
36665
|
+
return;
|
|
36666
|
+
editStreamState.lastPartialText = partialText;
|
|
36667
|
+
const nextText = rewriteNumericMentionsToUsernames(extractCompleteParagraphText(partialText), senderProfilesById).trim();
|
|
36668
|
+
if (!nextText || nextText === editStreamState.accumulatedText)
|
|
36669
|
+
return;
|
|
36670
|
+
editStreamState.opChain = editStreamState.opChain.then(async () => {
|
|
36671
|
+
if (editStreamState.failed)
|
|
36672
|
+
return;
|
|
36673
|
+
if (!nextText || nextText === editStreamState.accumulatedText)
|
|
36674
|
+
return;
|
|
36675
|
+
try {
|
|
36676
|
+
if (editStreamState.messageId == null) {
|
|
36677
|
+
const sent = await client.sendMessage({
|
|
36678
|
+
chatId,
|
|
36679
|
+
text: nextText,
|
|
36680
|
+
...defaultReplyToMsgId != null ? { replyToMsgId: defaultReplyToMsgId } : {},
|
|
36681
|
+
parseMarkdown
|
|
36682
|
+
});
|
|
36683
|
+
if (sent.messageId == null) {
|
|
36684
|
+
throw new Error("inline edit stream: sendMessage returned no messageId");
|
|
36685
|
+
}
|
|
36686
|
+
editStreamState.messageId = sent.messageId;
|
|
36687
|
+
rememberBotMessageId(botMessageIdsByChat, chatId, sent.messageId);
|
|
36688
|
+
} else {
|
|
36689
|
+
const result = await client.invokeRaw(Method.EDIT_MESSAGE, {
|
|
36690
|
+
oneofKind: "editMessage",
|
|
36691
|
+
editMessage: {
|
|
36692
|
+
messageId: editStreamState.messageId,
|
|
36693
|
+
peerId: buildChatPeer2(chatId),
|
|
36694
|
+
text: nextText,
|
|
36695
|
+
parseMarkdown
|
|
36696
|
+
}
|
|
36697
|
+
});
|
|
36698
|
+
if (result.oneofKind !== "editMessage") {
|
|
36699
|
+
throw new Error(`inline edit stream: expected editMessage result, got ${String(result.oneofKind)}`);
|
|
36454
36700
|
}
|
|
36455
|
-
} : {},
|
|
36456
|
-
onRecordError: (err) => runtime2.error?.(`inline: failed updating session meta: ${String(err)}`)
|
|
36457
|
-
});
|
|
36458
|
-
const replyPipeline = await createChannelReplyPipelineCompat({
|
|
36459
|
-
cfg,
|
|
36460
|
-
agentId: route.agentId,
|
|
36461
|
-
channel: CHANNEL_ID,
|
|
36462
|
-
accountId: account.accountId,
|
|
36463
|
-
typing: {
|
|
36464
|
-
start: () => client.sendTyping({ chatId, typing: true }),
|
|
36465
|
-
stop: () => client.sendTyping({ chatId, typing: false }),
|
|
36466
|
-
onStartError: (err) => runtime2.error?.(`inline typing start failed: ${String(err)}`),
|
|
36467
|
-
onStopError: (err) => runtime2.error?.(`inline typing stop failed: ${String(err)}`)
|
|
36468
36701
|
}
|
|
36469
|
-
|
|
36470
|
-
|
|
36471
|
-
|
|
36472
|
-
|
|
36473
|
-
|
|
36474
|
-
|
|
36475
|
-
|
|
36476
|
-
|
|
36477
|
-
|
|
36478
|
-
|
|
36479
|
-
|
|
36480
|
-
|
|
36481
|
-
|
|
36482
|
-
|
|
36483
|
-
|
|
36484
|
-
|
|
36485
|
-
|
|
36486
|
-
|
|
36487
|
-
|
|
36488
|
-
|
|
36489
|
-
}
|
|
36490
|
-
|
|
36491
|
-
|
|
36702
|
+
editStreamState.accumulatedText = nextText;
|
|
36703
|
+
statusSink?.({ lastOutboundAt: Date.now() });
|
|
36704
|
+
} catch (error48) {
|
|
36705
|
+
editStreamState.failed = true;
|
|
36706
|
+
runtime2.error?.(`inline edit stream failed: ${String(error48)}`);
|
|
36707
|
+
}
|
|
36708
|
+
});
|
|
36709
|
+
await editStreamState.opChain;
|
|
36710
|
+
};
|
|
36711
|
+
const replyOptions = {
|
|
36712
|
+
...onModelSelected ? { onModelSelected } : {},
|
|
36713
|
+
blockReplyTimeoutMs: 25000,
|
|
36714
|
+
...streamViaEditMessage ? {
|
|
36715
|
+
onAssistantMessageStart: async () => {
|
|
36716
|
+
await resetEditStreamOnBoundary();
|
|
36717
|
+
}
|
|
36718
|
+
} : {},
|
|
36719
|
+
...streamViaEditMessage ? {
|
|
36720
|
+
onPartialReply: async (payload) => {
|
|
36721
|
+
await handlePartialStreamPayload(payload);
|
|
36722
|
+
}
|
|
36723
|
+
} : {},
|
|
36724
|
+
...streamViaEditMessage ? {
|
|
36725
|
+
onReasoningStream: async (payload) => {
|
|
36726
|
+
await handlePartialStreamPayload(payload);
|
|
36727
|
+
}
|
|
36728
|
+
} : {},
|
|
36729
|
+
...streamViaEditMessage ? {
|
|
36730
|
+
onReasoningEnd: async () => {
|
|
36492
36731
|
await editStreamState.opChain;
|
|
36493
|
-
|
|
36494
|
-
|
|
36495
|
-
|
|
36496
|
-
|
|
36497
|
-
|
|
36498
|
-
|
|
36499
|
-
|
|
36500
|
-
|
|
36501
|
-
|
|
36502
|
-
|
|
36503
|
-
|
|
36504
|
-
|
|
36505
|
-
|
|
36506
|
-
|
|
36507
|
-
|
|
36508
|
-
|
|
36509
|
-
|
|
36510
|
-
|
|
36511
|
-
|
|
36512
|
-
|
|
36513
|
-
|
|
36514
|
-
|
|
36515
|
-
|
|
36516
|
-
|
|
36517
|
-
|
|
36518
|
-
|
|
36519
|
-
|
|
36520
|
-
|
|
36521
|
-
|
|
36522
|
-
|
|
36523
|
-
|
|
36524
|
-
|
|
36525
|
-
|
|
36526
|
-
|
|
36732
|
+
}
|
|
36733
|
+
} : {},
|
|
36734
|
+
...streamViaEditMessage ? {
|
|
36735
|
+
onToolStart: async () => {
|
|
36736
|
+
await resetEditStreamOnBoundary();
|
|
36737
|
+
}
|
|
36738
|
+
} : {},
|
|
36739
|
+
...streamViaEditMessage ? {
|
|
36740
|
+
onCompactionStart: async () => {
|
|
36741
|
+
await resetEditStreamOnBoundary();
|
|
36742
|
+
}
|
|
36743
|
+
} : {},
|
|
36744
|
+
...streamViaEditMessage ? {
|
|
36745
|
+
onCompactionEnd: async () => {
|
|
36746
|
+
await resetEditStreamOnBoundary();
|
|
36747
|
+
}
|
|
36748
|
+
} : {},
|
|
36749
|
+
...typeof disableBlockStreaming === "boolean" ? { disableBlockStreaming } : {}
|
|
36750
|
+
};
|
|
36751
|
+
try {
|
|
36752
|
+
let delivered = false;
|
|
36753
|
+
let skippedNonSilent = false;
|
|
36754
|
+
let failedNonSilent = false;
|
|
36755
|
+
let dispatchError = null;
|
|
36756
|
+
try {
|
|
36757
|
+
await core3.channel.reply.dispatchReplyWithBufferedBlockDispatcher({
|
|
36758
|
+
ctx: ctxPayload,
|
|
36759
|
+
cfg,
|
|
36760
|
+
dispatcherOptions: {
|
|
36761
|
+
...prefixOptions,
|
|
36762
|
+
...typingCallbacks ? { typingCallbacks } : {},
|
|
36763
|
+
deliver: async (payload, info) => {
|
|
36764
|
+
const rawText = payload.text ?? "";
|
|
36765
|
+
const mediaList = payload.mediaUrls?.length ? payload.mediaUrls : payload.mediaUrl ? [payload.mediaUrl] : [];
|
|
36766
|
+
const outboundText = rewriteNumericMentionsToUsernames(rawText, senderProfilesById);
|
|
36767
|
+
const outboundActions = resolveInlineReplyActions(payload);
|
|
36768
|
+
const infoKind = typeof info?.kind === "string" ? info.kind : undefined;
|
|
36769
|
+
let replyToMsgId;
|
|
36770
|
+
if (payload.replyToId != null) {
|
|
36771
|
+
try {
|
|
36772
|
+
replyToMsgId = BigInt(payload.replyToId);
|
|
36773
|
+
} catch {}
|
|
36774
|
+
}
|
|
36775
|
+
if (replyToMsgId == null && isGroup && msg.replyToMsgId != null) {
|
|
36776
|
+
replyToMsgId = msg.id;
|
|
36777
|
+
}
|
|
36778
|
+
const rememberSent = (messageId) => {
|
|
36779
|
+
if (messageId != null) {
|
|
36780
|
+
rememberBotMessageId(botMessageIdsByChat, chatId, messageId);
|
|
36781
|
+
}
|
|
36782
|
+
};
|
|
36783
|
+
const sendTextFallback = async (text, includeReplyTo, includeActions) => {
|
|
36784
|
+
if (!text.trim())
|
|
36785
|
+
return;
|
|
36527
36786
|
const sent = await client.sendMessage({
|
|
36528
36787
|
chatId,
|
|
36529
|
-
text
|
|
36530
|
-
...
|
|
36788
|
+
text,
|
|
36789
|
+
...includeReplyTo && replyToMsgId != null ? { replyToMsgId } : {},
|
|
36790
|
+
...includeActions && outboundActions !== undefined ? { actions: outboundActions } : {},
|
|
36531
36791
|
parseMarkdown
|
|
36532
36792
|
});
|
|
36533
|
-
|
|
36534
|
-
|
|
36535
|
-
|
|
36536
|
-
|
|
36537
|
-
|
|
36538
|
-
|
|
36793
|
+
rememberSent(sent.messageId);
|
|
36794
|
+
delivered = true;
|
|
36795
|
+
};
|
|
36796
|
+
const updateStreamedMessage = async (text, actions) => {
|
|
36797
|
+
await editStreamState.opChain;
|
|
36798
|
+
if (editStreamState.messageId == null)
|
|
36799
|
+
return false;
|
|
36800
|
+
const nextText = text.trim();
|
|
36801
|
+
const textForEdit = nextText || editStreamState.accumulatedText;
|
|
36802
|
+
if (!textForEdit && actions === undefined)
|
|
36803
|
+
return true;
|
|
36804
|
+
const shouldSkipTextUpdate = !editStreamState.failed && textForEdit === editStreamState.accumulatedText;
|
|
36805
|
+
if (shouldSkipTextUpdate && actions === undefined)
|
|
36806
|
+
return true;
|
|
36539
36807
|
const result = await client.invokeRaw(Method.EDIT_MESSAGE, {
|
|
36540
36808
|
oneofKind: "editMessage",
|
|
36541
36809
|
editMessage: {
|
|
36542
36810
|
messageId: editStreamState.messageId,
|
|
36543
36811
|
peerId: buildChatPeer2(chatId),
|
|
36544
|
-
text:
|
|
36545
|
-
parseMarkdown
|
|
36812
|
+
text: textForEdit,
|
|
36813
|
+
parseMarkdown,
|
|
36814
|
+
...actions !== undefined ? { actions } : {}
|
|
36546
36815
|
}
|
|
36547
36816
|
});
|
|
36548
36817
|
if (result.oneofKind !== "editMessage") {
|
|
36549
36818
|
throw new Error(`inline edit stream: expected editMessage result, got ${String(result.oneofKind)}`);
|
|
36550
36819
|
}
|
|
36551
|
-
|
|
36552
|
-
|
|
36553
|
-
|
|
36554
|
-
|
|
36555
|
-
|
|
36556
|
-
|
|
36557
|
-
|
|
36558
|
-
|
|
36559
|
-
|
|
36560
|
-
|
|
36561
|
-
|
|
36562
|
-
|
|
36563
|
-
blockReplyTimeoutMs: 25000,
|
|
36564
|
-
...streamViaEditMessage ? {
|
|
36565
|
-
onAssistantMessageStart: async () => {
|
|
36566
|
-
await resetEditStreamOnBoundary();
|
|
36567
|
-
}
|
|
36568
|
-
} : {},
|
|
36569
|
-
...streamViaEditMessage ? {
|
|
36570
|
-
onPartialReply: async (payload) => {
|
|
36571
|
-
await handlePartialStreamPayload(payload);
|
|
36572
|
-
}
|
|
36573
|
-
} : {},
|
|
36574
|
-
...streamViaEditMessage ? {
|
|
36575
|
-
onReasoningStream: async (payload) => {
|
|
36576
|
-
await handlePartialStreamPayload(payload);
|
|
36577
|
-
}
|
|
36578
|
-
} : {},
|
|
36579
|
-
...streamViaEditMessage ? {
|
|
36580
|
-
onReasoningEnd: async () => {
|
|
36581
|
-
await editStreamState.opChain;
|
|
36582
|
-
}
|
|
36583
|
-
} : {},
|
|
36584
|
-
...streamViaEditMessage ? {
|
|
36585
|
-
onToolStart: async () => {
|
|
36586
|
-
await resetEditStreamOnBoundary();
|
|
36587
|
-
}
|
|
36588
|
-
} : {},
|
|
36589
|
-
...streamViaEditMessage ? {
|
|
36590
|
-
onCompactionStart: async () => {
|
|
36591
|
-
await resetEditStreamOnBoundary();
|
|
36592
|
-
}
|
|
36593
|
-
} : {},
|
|
36594
|
-
...streamViaEditMessage ? {
|
|
36595
|
-
onCompactionEnd: async () => {
|
|
36596
|
-
await resetEditStreamOnBoundary();
|
|
36597
|
-
}
|
|
36598
|
-
} : {},
|
|
36599
|
-
...typeof disableBlockStreaming === "boolean" ? { disableBlockStreaming } : {}
|
|
36600
|
-
};
|
|
36601
|
-
try {
|
|
36602
|
-
let delivered = false;
|
|
36603
|
-
let skippedNonSilent = false;
|
|
36604
|
-
let failedNonSilent = false;
|
|
36605
|
-
let dispatchError = null;
|
|
36606
|
-
try {
|
|
36607
|
-
await core3.channel.reply.dispatchReplyWithBufferedBlockDispatcher({
|
|
36608
|
-
ctx: ctxPayload,
|
|
36609
|
-
cfg,
|
|
36610
|
-
dispatcherOptions: {
|
|
36611
|
-
...prefixOptions,
|
|
36612
|
-
...typingCallbacks ? { typingCallbacks } : {},
|
|
36613
|
-
deliver: async (payload, info) => {
|
|
36614
|
-
const rawText = payload.text ?? "";
|
|
36615
|
-
const mediaList = payload.mediaUrls?.length ? payload.mediaUrls : payload.mediaUrl ? [payload.mediaUrl] : [];
|
|
36616
|
-
const outboundText = rewriteNumericMentionsToUsernames(rawText, senderProfilesById);
|
|
36617
|
-
const outboundActions = resolveInlineReplyActions(payload);
|
|
36618
|
-
const infoKind = typeof info?.kind === "string" ? info.kind : undefined;
|
|
36619
|
-
let replyToMsgId;
|
|
36620
|
-
if (payload.replyToId != null) {
|
|
36621
|
-
try {
|
|
36622
|
-
replyToMsgId = BigInt(payload.replyToId);
|
|
36623
|
-
} catch {}
|
|
36820
|
+
if (!shouldSkipTextUpdate) {
|
|
36821
|
+
editStreamState.accumulatedText = textForEdit;
|
|
36822
|
+
editStreamState.lastPartialText = textForEdit;
|
|
36823
|
+
}
|
|
36824
|
+
editStreamState.failed = false;
|
|
36825
|
+
return true;
|
|
36826
|
+
};
|
|
36827
|
+
if (mediaList.length === 0) {
|
|
36828
|
+
if (shouldEditCallbackTargetInPlace && editStreamState.messageId != null) {
|
|
36829
|
+
const callbackEditActions = outboundActions ?? { rows: [] };
|
|
36830
|
+
if (!outboundText.trim() && outboundActions === undefined) {
|
|
36831
|
+
return;
|
|
36624
36832
|
}
|
|
36625
|
-
|
|
36626
|
-
|
|
36833
|
+
await updateStreamedMessage(outboundText, callbackEditActions);
|
|
36834
|
+
delivered = true;
|
|
36835
|
+
statusSink?.({ lastOutboundAt: Date.now() });
|
|
36836
|
+
return;
|
|
36837
|
+
}
|
|
36838
|
+
if (streamViaEditMessage && infoKind === "final" && finalDeliveredForCurrentAssistantMessage && editStreamState.messageId != null) {
|
|
36839
|
+
await resetEditStreamForAssistantMessage();
|
|
36840
|
+
}
|
|
36841
|
+
if (streamViaEditMessage && editStreamState.messageId != null) {
|
|
36842
|
+
if (outboundText.trim()) {
|
|
36843
|
+
editStreamState.finalTextAccumulator += outboundText;
|
|
36627
36844
|
}
|
|
36628
|
-
|
|
36629
|
-
if (messageId != null) {
|
|
36630
|
-
rememberBotMessageId(botMessageIdsByChat, chatId, messageId);
|
|
36631
|
-
}
|
|
36632
|
-
};
|
|
36633
|
-
const sendTextFallback = async (text, includeReplyTo, includeActions) => {
|
|
36634
|
-
if (!text.trim())
|
|
36635
|
-
return;
|
|
36636
|
-
const sent = await client.sendMessage({
|
|
36637
|
-
chatId,
|
|
36638
|
-
text,
|
|
36639
|
-
...includeReplyTo && replyToMsgId != null ? { replyToMsgId } : {},
|
|
36640
|
-
...includeActions && outboundActions !== undefined ? { actions: outboundActions } : {},
|
|
36641
|
-
parseMarkdown
|
|
36642
|
-
});
|
|
36643
|
-
rememberSent(sent.messageId);
|
|
36644
|
-
delivered = true;
|
|
36645
|
-
};
|
|
36646
|
-
const updateStreamedMessage = async (text, actions) => {
|
|
36647
|
-
await editStreamState.opChain;
|
|
36648
|
-
if (editStreamState.messageId == null)
|
|
36649
|
-
return false;
|
|
36650
|
-
const nextText = text.trim();
|
|
36651
|
-
const textForEdit = nextText || editStreamState.accumulatedText;
|
|
36652
|
-
if (!textForEdit)
|
|
36653
|
-
return true;
|
|
36654
|
-
const shouldSkipTextUpdate = !editStreamState.failed && textForEdit === editStreamState.accumulatedText;
|
|
36655
|
-
if (shouldSkipTextUpdate && actions === undefined)
|
|
36656
|
-
return true;
|
|
36657
|
-
const result = await client.invokeRaw(Method.EDIT_MESSAGE, {
|
|
36658
|
-
oneofKind: "editMessage",
|
|
36659
|
-
editMessage: {
|
|
36660
|
-
messageId: editStreamState.messageId,
|
|
36661
|
-
peerId: buildChatPeer2(chatId),
|
|
36662
|
-
text: textForEdit,
|
|
36663
|
-
parseMarkdown,
|
|
36664
|
-
...actions !== undefined ? { actions } : {}
|
|
36665
|
-
}
|
|
36666
|
-
});
|
|
36667
|
-
if (result.oneofKind !== "editMessage") {
|
|
36668
|
-
throw new Error(`inline edit stream: expected editMessage result, got ${String(result.oneofKind)}`);
|
|
36669
|
-
}
|
|
36670
|
-
if (!shouldSkipTextUpdate) {
|
|
36671
|
-
editStreamState.accumulatedText = textForEdit;
|
|
36672
|
-
editStreamState.lastPartialText = textForEdit;
|
|
36673
|
-
}
|
|
36674
|
-
editStreamState.failed = false;
|
|
36675
|
-
return true;
|
|
36676
|
-
};
|
|
36677
|
-
if (mediaList.length === 0) {
|
|
36678
|
-
if (streamViaEditMessage && infoKind === "final" && finalDeliveredForCurrentAssistantMessage && editStreamState.messageId != null) {
|
|
36679
|
-
await resetEditStreamForAssistantMessage();
|
|
36680
|
-
}
|
|
36681
|
-
if (streamViaEditMessage && editStreamState.messageId != null) {
|
|
36682
|
-
if (outboundText.trim()) {
|
|
36683
|
-
editStreamState.finalTextAccumulator += outboundText;
|
|
36684
|
-
}
|
|
36685
|
-
if (!editStreamState.finalTextAccumulator.trim() && outboundActions === undefined) {
|
|
36686
|
-
return;
|
|
36687
|
-
}
|
|
36688
|
-
await updateStreamedMessage(editStreamState.finalTextAccumulator, outboundActions);
|
|
36689
|
-
delivered = true;
|
|
36690
|
-
if (infoKind === "final") {
|
|
36691
|
-
finalDeliveredForCurrentAssistantMessage = true;
|
|
36692
|
-
}
|
|
36693
|
-
statusSink?.({ lastOutboundAt: Date.now() });
|
|
36694
|
-
return;
|
|
36695
|
-
}
|
|
36696
|
-
if (!outboundText.trim())
|
|
36697
|
-
return;
|
|
36698
|
-
await sendTextFallback(outboundText, true, true);
|
|
36699
|
-
statusSink?.({ lastOutboundAt: Date.now() });
|
|
36845
|
+
if (!editStreamState.finalTextAccumulator.trim() && outboundActions === undefined) {
|
|
36700
36846
|
return;
|
|
36701
36847
|
}
|
|
36702
|
-
|
|
36703
|
-
|
|
36848
|
+
await updateStreamedMessage(editStreamState.finalTextAccumulator, outboundActions);
|
|
36849
|
+
delivered = true;
|
|
36850
|
+
if (infoKind === "final") {
|
|
36851
|
+
finalDeliveredForCurrentAssistantMessage = true;
|
|
36704
36852
|
}
|
|
36705
|
-
|
|
36706
|
-
|
|
36707
|
-
|
|
36708
|
-
|
|
36709
|
-
|
|
36710
|
-
|
|
36711
|
-
|
|
36712
|
-
|
|
36713
|
-
|
|
36714
|
-
|
|
36715
|
-
|
|
36716
|
-
|
|
36717
|
-
|
|
36718
|
-
|
|
36719
|
-
|
|
36720
|
-
|
|
36721
|
-
|
|
36722
|
-
|
|
36723
|
-
|
|
36724
|
-
|
|
36725
|
-
|
|
36726
|
-
|
|
36727
|
-
|
|
36728
|
-
|
|
36729
|
-
|
|
36730
|
-
|
|
36731
|
-
|
|
36853
|
+
statusSink?.({ lastOutboundAt: Date.now() });
|
|
36854
|
+
return;
|
|
36855
|
+
}
|
|
36856
|
+
if (!outboundText.trim())
|
|
36857
|
+
return;
|
|
36858
|
+
await sendTextFallback(outboundText, true, true);
|
|
36859
|
+
statusSink?.({ lastOutboundAt: Date.now() });
|
|
36860
|
+
return;
|
|
36861
|
+
}
|
|
36862
|
+
if (streamViaEditMessage && editStreamState.messageId != null && outboundText.trim()) {
|
|
36863
|
+
await updateStreamedMessage(outboundText, outboundActions);
|
|
36864
|
+
}
|
|
36865
|
+
for (let index = 0;index < mediaList.length; index++) {
|
|
36866
|
+
const mediaUrl = mediaList[index];
|
|
36867
|
+
if (!mediaUrl?.trim())
|
|
36868
|
+
continue;
|
|
36869
|
+
const isFirst = index === 0;
|
|
36870
|
+
const shouldAttachActionsToMedia = isFirst && (!(streamViaEditMessage && editStreamState.messageId != null) || !outboundText.trim());
|
|
36871
|
+
const caption = isFirst && !(streamViaEditMessage && editStreamState.messageId != null) ? outboundText : "";
|
|
36872
|
+
try {
|
|
36873
|
+
const media = await uploadInlineMediaFromUrl({
|
|
36874
|
+
client,
|
|
36875
|
+
cfg,
|
|
36876
|
+
accountId: account.accountId,
|
|
36877
|
+
mediaUrl
|
|
36878
|
+
});
|
|
36879
|
+
const sent = await client.sendMessage({
|
|
36880
|
+
chatId,
|
|
36881
|
+
...caption ? { text: caption } : {},
|
|
36882
|
+
media,
|
|
36883
|
+
...isFirst && replyToMsgId != null ? { replyToMsgId } : {},
|
|
36884
|
+
...shouldAttachActionsToMedia && outboundActions !== undefined ? { actions: outboundActions } : {},
|
|
36885
|
+
...caption ? { parseMarkdown } : {}
|
|
36886
|
+
});
|
|
36887
|
+
rememberSent(sent.messageId);
|
|
36888
|
+
delivered = true;
|
|
36889
|
+
} catch (error48) {
|
|
36890
|
+
runtime2.error?.(`inline media upload failed; falling back to url text (${String(error48)})`);
|
|
36891
|
+
const fallbackText = caption ? `${caption}
|
|
36732
36892
|
|
|
36733
36893
|
Attachment: ${mediaUrl}` : `Attachment: ${mediaUrl}`;
|
|
36734
|
-
|
|
36735
|
-
}
|
|
36736
|
-
}
|
|
36737
|
-
statusSink?.({ lastOutboundAt: Date.now() });
|
|
36738
|
-
},
|
|
36739
|
-
onSkip: (_payload, info) => {
|
|
36740
|
-
if (info?.reason !== "silent") {
|
|
36741
|
-
skippedNonSilent = true;
|
|
36742
|
-
}
|
|
36743
|
-
},
|
|
36744
|
-
onError: (err, info) => {
|
|
36745
|
-
failedNonSilent = true;
|
|
36746
|
-
runtime2.error?.(`inline ${info?.kind ?? "final"} reply failed: ${String(err)}`);
|
|
36894
|
+
await sendTextFallback(fallbackText, isFirst, isFirst);
|
|
36747
36895
|
}
|
|
36748
|
-
}
|
|
36749
|
-
|
|
36750
|
-
}
|
|
36751
|
-
|
|
36752
|
-
|
|
36753
|
-
|
|
36754
|
-
|
|
36755
|
-
|
|
36756
|
-
|
|
36757
|
-
|
|
36758
|
-
|
|
36759
|
-
const fallbackText = dispatchError != null ? "Something went wrong while processing your request. Please try again." : EMPTY_RESPONSE_FALLBACK;
|
|
36760
|
-
const sent = await client.sendMessage({
|
|
36761
|
-
chatId,
|
|
36762
|
-
text: fallbackText,
|
|
36763
|
-
...defaultReplyToMsgId != null ? { replyToMsgId: defaultReplyToMsgId } : {},
|
|
36764
|
-
parseMarkdown
|
|
36765
|
-
});
|
|
36766
|
-
if (sent.messageId != null) {
|
|
36767
|
-
rememberBotMessageId(botMessageIdsByChat, chatId, sent.messageId);
|
|
36896
|
+
}
|
|
36897
|
+
statusSink?.({ lastOutboundAt: Date.now() });
|
|
36898
|
+
},
|
|
36899
|
+
onSkip: (_payload, info) => {
|
|
36900
|
+
if (info?.reason !== "silent") {
|
|
36901
|
+
skippedNonSilent = true;
|
|
36902
|
+
}
|
|
36903
|
+
},
|
|
36904
|
+
onError: (err, info) => {
|
|
36905
|
+
failedNonSilent = true;
|
|
36906
|
+
runtime2.error?.(`inline ${info?.kind ?? "final"} reply failed: ${String(err)}`);
|
|
36768
36907
|
}
|
|
36769
|
-
|
|
36770
|
-
|
|
36771
|
-
}
|
|
36772
|
-
|
|
36773
|
-
|
|
36774
|
-
|
|
36775
|
-
|
|
36776
|
-
|
|
36908
|
+
},
|
|
36909
|
+
replyOptions
|
|
36910
|
+
});
|
|
36911
|
+
} catch (error48) {
|
|
36912
|
+
dispatchError = error48;
|
|
36913
|
+
runtime2.error?.(`inline dispatch failed: ${String(error48)}`);
|
|
36914
|
+
}
|
|
36915
|
+
if (!delivered && streamViaEditMessage && editStreamState.messageId != null) {
|
|
36916
|
+
delivered = true;
|
|
36917
|
+
}
|
|
36918
|
+
if (!delivered && (dispatchError != null || skippedNonSilent || failedNonSilent)) {
|
|
36919
|
+
const fallbackText = dispatchError != null ? "Something went wrong while processing your request. Please try again." : EMPTY_RESPONSE_FALLBACK;
|
|
36920
|
+
const sent = await client.sendMessage({
|
|
36921
|
+
chatId,
|
|
36922
|
+
text: fallbackText,
|
|
36923
|
+
...defaultReplyToMsgId != null ? { replyToMsgId: defaultReplyToMsgId } : {},
|
|
36924
|
+
parseMarkdown
|
|
36925
|
+
});
|
|
36926
|
+
if (sent.messageId != null) {
|
|
36927
|
+
rememberBotMessageId(botMessageIdsByChat, chatId, sent.messageId);
|
|
36928
|
+
}
|
|
36929
|
+
statusSink?.({ lastOutboundAt: Date.now() });
|
|
36930
|
+
}
|
|
36931
|
+
} finally {
|
|
36932
|
+
if (callbackActionEvent && !callbackActionAnswered) {
|
|
36933
|
+
try {
|
|
36934
|
+
await answerCallbackIfNeeded();
|
|
36935
|
+
} catch (error48) {
|
|
36936
|
+
runtime2.error?.(`inline callback answer failed: ${String(error48)}`);
|
|
36937
|
+
}
|
|
36938
|
+
}
|
|
36939
|
+
}
|
|
36940
|
+
if (isGroup && groupHistoryKey) {
|
|
36941
|
+
clearHistoryEntriesIfEnabled({
|
|
36942
|
+
historyMap: groupPendingHistories,
|
|
36943
|
+
historyKey: groupHistoryKey,
|
|
36944
|
+
limit: historyLimit
|
|
36945
|
+
});
|
|
36946
|
+
}
|
|
36947
|
+
};
|
|
36948
|
+
const { debouncer: inboundDebouncer } = createChannelInboundDebouncer({
|
|
36949
|
+
cfg,
|
|
36950
|
+
channel: CHANNEL_ID,
|
|
36951
|
+
buildKey: (entry) => buildInlineDebounceKey({
|
|
36952
|
+
accountId: account.accountId,
|
|
36953
|
+
chatId: entry.chatId,
|
|
36954
|
+
senderId: entry.msg.fromId
|
|
36955
|
+
}),
|
|
36956
|
+
shouldDebounce: (entry) => {
|
|
36957
|
+
const content = summarizeInlineMessageContent(entry.msg);
|
|
36958
|
+
return shouldDebounceTextInbound({
|
|
36959
|
+
text: buildInlineInboundBodyText(content),
|
|
36960
|
+
cfg,
|
|
36961
|
+
hasMedia: Boolean(content.media || content.attachments.length > 0),
|
|
36962
|
+
...botUsername ? { commandOptions: { botUsername } } : {}
|
|
36963
|
+
});
|
|
36964
|
+
},
|
|
36965
|
+
onFlush: async (entries) => {
|
|
36966
|
+
const last = entries.at(-1);
|
|
36967
|
+
if (!last)
|
|
36968
|
+
return;
|
|
36969
|
+
if (entries.length === 1) {
|
|
36970
|
+
await handleInboundNow({
|
|
36971
|
+
chatId: last.chatId,
|
|
36972
|
+
msg: last.msg
|
|
36973
|
+
});
|
|
36974
|
+
return;
|
|
36975
|
+
}
|
|
36976
|
+
const combinedText = entries.map((entry) => buildInlineInboundBodyText(summarizeInlineMessageContent(entry.msg))).filter(Boolean).join(`
|
|
36977
|
+
`);
|
|
36978
|
+
if (!combinedText.trim()) {
|
|
36979
|
+
return;
|
|
36980
|
+
}
|
|
36981
|
+
await handleInboundNow({
|
|
36982
|
+
chatId: last.chatId,
|
|
36983
|
+
msg: buildSyntheticInlineTextMessage({
|
|
36984
|
+
base: last.msg,
|
|
36985
|
+
text: combinedText,
|
|
36986
|
+
mentioned: entries.some((entry) => entry.msg.mentioned === true)
|
|
36987
|
+
}),
|
|
36988
|
+
rawBodyOverride: combinedText
|
|
36989
|
+
});
|
|
36990
|
+
},
|
|
36991
|
+
onError: (err, items) => {
|
|
36992
|
+
runtime2.error?.(`inline debounce flush failed: ${String(err)}`);
|
|
36993
|
+
const chatId = items[0]?.chatId;
|
|
36994
|
+
if (chatId == null)
|
|
36995
|
+
return;
|
|
36996
|
+
client.sendMessage({
|
|
36997
|
+
chatId,
|
|
36998
|
+
text: "Something went wrong while processing your message. Please try again."
|
|
36999
|
+
}).then(() => {
|
|
37000
|
+
statusSink?.({ lastOutboundAt: Date.now() });
|
|
37001
|
+
}).catch((sendErr) => {
|
|
37002
|
+
runtime2.error?.(`inline debounce fallback send failed: ${String(sendErr)}`);
|
|
37003
|
+
});
|
|
37004
|
+
}
|
|
37005
|
+
});
|
|
37006
|
+
const loop = (async () => {
|
|
37007
|
+
try {
|
|
37008
|
+
for await (const event of client.events()) {
|
|
37009
|
+
if (abortSignal.aborted)
|
|
37010
|
+
break;
|
|
37011
|
+
const rawEvent = event;
|
|
37012
|
+
if (event.kind === "message.new") {
|
|
37013
|
+
const msg = {
|
|
37014
|
+
...event.message,
|
|
37015
|
+
chatId: event.chatId
|
|
37016
|
+
};
|
|
37017
|
+
if (msg.out || msg.fromId === meId)
|
|
37018
|
+
continue;
|
|
37019
|
+
await inboundDebouncer.enqueue({
|
|
37020
|
+
chatId: event.chatId,
|
|
37021
|
+
msg
|
|
37022
|
+
});
|
|
37023
|
+
continue;
|
|
37024
|
+
}
|
|
37025
|
+
if (event.kind === "reaction.add") {
|
|
37026
|
+
if (event.reaction.userId === meId)
|
|
37027
|
+
continue;
|
|
37028
|
+
const onBotMessage = await isReactionTargetBotMessage({
|
|
37029
|
+
client,
|
|
37030
|
+
chatId: event.chatId,
|
|
37031
|
+
messageId: event.reaction.messageId,
|
|
37032
|
+
meId,
|
|
37033
|
+
botMessageIdsByChat
|
|
37034
|
+
}).catch((err) => {
|
|
37035
|
+
statusSink?.({ lastError: `getChatHistory (reaction target) failed: ${String(err)}` });
|
|
37036
|
+
return false;
|
|
37037
|
+
});
|
|
37038
|
+
if (!onBotMessage)
|
|
37039
|
+
continue;
|
|
37040
|
+
await handleInboundNow({
|
|
37041
|
+
chatId: event.chatId,
|
|
37042
|
+
msg: {
|
|
37043
|
+
id: event.reaction.messageId,
|
|
37044
|
+
chatId: event.chatId,
|
|
37045
|
+
date: event.date,
|
|
37046
|
+
fromId: event.reaction.userId,
|
|
37047
|
+
message: "",
|
|
37048
|
+
out: false,
|
|
37049
|
+
mentioned: false,
|
|
37050
|
+
replyToMsgId: event.reaction.messageId
|
|
37051
|
+
},
|
|
37052
|
+
reactionEvent: {
|
|
37053
|
+
action: "added",
|
|
37054
|
+
emoji: event.reaction.emoji,
|
|
37055
|
+
targetMessageId: event.reaction.messageId
|
|
36777
37056
|
}
|
|
36778
|
-
}
|
|
37057
|
+
});
|
|
37058
|
+
continue;
|
|
36779
37059
|
}
|
|
36780
|
-
if (
|
|
36781
|
-
|
|
36782
|
-
|
|
36783
|
-
|
|
36784
|
-
|
|
37060
|
+
if (event.kind === "reaction.delete") {
|
|
37061
|
+
if (event.userId === meId)
|
|
37062
|
+
continue;
|
|
37063
|
+
const onBotMessage = await isReactionTargetBotMessage({
|
|
37064
|
+
client,
|
|
37065
|
+
chatId: event.chatId,
|
|
37066
|
+
messageId: event.messageId,
|
|
37067
|
+
meId,
|
|
37068
|
+
botMessageIdsByChat
|
|
37069
|
+
}).catch((err) => {
|
|
37070
|
+
statusSink?.({ lastError: `getChatHistory (reaction target) failed: ${String(err)}` });
|
|
37071
|
+
return false;
|
|
37072
|
+
});
|
|
37073
|
+
if (!onBotMessage)
|
|
37074
|
+
continue;
|
|
37075
|
+
await handleInboundNow({
|
|
37076
|
+
chatId: event.chatId,
|
|
37077
|
+
msg: {
|
|
37078
|
+
id: event.messageId,
|
|
37079
|
+
chatId: event.chatId,
|
|
37080
|
+
date: event.date,
|
|
37081
|
+
fromId: event.userId,
|
|
37082
|
+
message: "",
|
|
37083
|
+
out: false,
|
|
37084
|
+
mentioned: false,
|
|
37085
|
+
replyToMsgId: event.messageId
|
|
37086
|
+
},
|
|
37087
|
+
reactionEvent: {
|
|
37088
|
+
action: "removed",
|
|
37089
|
+
emoji: event.emoji,
|
|
37090
|
+
targetMessageId: event.messageId
|
|
37091
|
+
}
|
|
36785
37092
|
});
|
|
37093
|
+
continue;
|
|
37094
|
+
}
|
|
37095
|
+
if (rawEvent["kind"] === "message.action.invoke") {
|
|
37096
|
+
const actorUserId = rawEvent["actorUserId"];
|
|
37097
|
+
const interactionId = rawEvent["interactionId"];
|
|
37098
|
+
const actionId = rawEvent["actionId"];
|
|
37099
|
+
const targetMessageId = rawEvent["messageId"];
|
|
37100
|
+
const data = rawEvent["data"];
|
|
37101
|
+
const eventChatId = rawEvent["chatId"];
|
|
37102
|
+
const eventDate = rawEvent["date"];
|
|
37103
|
+
if (!actorUserId || !interactionId || !actionId || !targetMessageId || !eventChatId || !eventDate || !data) {
|
|
37104
|
+
continue;
|
|
37105
|
+
}
|
|
37106
|
+
if (actorUserId === meId)
|
|
37107
|
+
continue;
|
|
37108
|
+
await handleInboundNow({
|
|
37109
|
+
chatId: eventChatId,
|
|
37110
|
+
msg: {
|
|
37111
|
+
id: targetMessageId,
|
|
37112
|
+
chatId: eventChatId,
|
|
37113
|
+
date: eventDate,
|
|
37114
|
+
fromId: actorUserId,
|
|
37115
|
+
message: "",
|
|
37116
|
+
out: false,
|
|
37117
|
+
mentioned: false,
|
|
37118
|
+
replyToMsgId: targetMessageId
|
|
37119
|
+
},
|
|
37120
|
+
callbackActionEvent: {
|
|
37121
|
+
interactionId,
|
|
37122
|
+
actionId,
|
|
37123
|
+
targetMessageId,
|
|
37124
|
+
data
|
|
37125
|
+
}
|
|
37126
|
+
});
|
|
37127
|
+
continue;
|
|
36786
37128
|
}
|
|
36787
37129
|
}
|
|
36788
37130
|
} catch (err) {
|
|
@@ -36790,6 +37132,10 @@ Attachment: ${mediaUrl}` : `Attachment: ${mediaUrl}`;
|
|
|
36790
37132
|
runtime2.error?.(`inline monitor loop crashed: ${String(err)}`);
|
|
36791
37133
|
}
|
|
36792
37134
|
})();
|
|
37135
|
+
const diagnosticsTimer = setInterval(() => {
|
|
37136
|
+
pushDiagnostics();
|
|
37137
|
+
}, 15000);
|
|
37138
|
+
diagnosticsTimer.unref?.();
|
|
36793
37139
|
let stopPromise = null;
|
|
36794
37140
|
const stop = async () => {
|
|
36795
37141
|
if (stopPromise) {
|
|
@@ -36797,6 +37143,7 @@ Attachment: ${mediaUrl}` : `Attachment: ${mediaUrl}`;
|
|
|
36797
37143
|
return;
|
|
36798
37144
|
}
|
|
36799
37145
|
stopPromise = (async () => {
|
|
37146
|
+
clearInterval(diagnosticsTimer);
|
|
36800
37147
|
await client.close().catch(() => {});
|
|
36801
37148
|
await loop.catch(() => {});
|
|
36802
37149
|
})();
|
|
@@ -36809,6 +37156,7 @@ Attachment: ${mediaUrl}` : `Attachment: ${mediaUrl}`;
|
|
|
36809
37156
|
}
|
|
36810
37157
|
|
|
36811
37158
|
// src/inline/actions.ts
|
|
37159
|
+
import { createMessageToolButtonsSchema } from "openclaw/plugin-sdk/channel-actions";
|
|
36812
37160
|
import {
|
|
36813
37161
|
normalizeInteractiveReply,
|
|
36814
37162
|
reduceInteractiveReply
|
|
@@ -37597,7 +37945,7 @@ function describeInlineMessageTool({
|
|
|
37597
37945
|
const schema = buttonsEnabled ? [
|
|
37598
37946
|
{
|
|
37599
37947
|
properties: {
|
|
37600
|
-
buttons:
|
|
37948
|
+
buttons: createMessageToolButtonsSchema()
|
|
37601
37949
|
}
|
|
37602
37950
|
}
|
|
37603
37951
|
] : [];
|
|
@@ -38649,6 +38997,7 @@ async function probeInlineAccount(account, timeoutMs) {
|
|
|
38649
38997
|
|
|
38650
38998
|
// src/inline/status-issues.ts
|
|
38651
38999
|
import { asString, isRecord as isRecord5 } from "openclaw/plugin-sdk/status-helpers";
|
|
39000
|
+
var RECENT_RUNTIME_ISSUE_MS = 30 * 60 * 1000;
|
|
38652
39001
|
function readInlineProbeSummary(value) {
|
|
38653
39002
|
if (!isRecord5(value)) {
|
|
38654
39003
|
return {};
|
|
@@ -38666,6 +39015,38 @@ function readInlineProbeSummary(value) {
|
|
|
38666
39015
|
function looksLikeAuthError(text) {
|
|
38667
39016
|
return /(401|403|unauth|forbidden|invalid token|token invalid|unauthorized)/i.test(text);
|
|
38668
39017
|
}
|
|
39018
|
+
function readInlineDiagnosticsSummary(value) {
|
|
39019
|
+
if (!isRecord5(value)) {
|
|
39020
|
+
return {};
|
|
39021
|
+
}
|
|
39022
|
+
const protocolValue = isRecord5(value.protocol) ? value.protocol : undefined;
|
|
39023
|
+
const transportValue = (protocolValue && isRecord5(protocolValue.transport) ? protocolValue.transport : undefined) ?? (isRecord5(value.transport) ? value.transport : undefined);
|
|
39024
|
+
const pingValue = protocolValue && isRecord5(protocolValue.ping) ? protocolValue.ping : undefined;
|
|
39025
|
+
return {
|
|
39026
|
+
...protocolValue ? {
|
|
39027
|
+
protocol: {
|
|
39028
|
+
...typeof protocolValue.lastFailureAt === "number" ? { lastFailureAt: protocolValue.lastFailureAt } : {},
|
|
39029
|
+
...asString(protocolValue.lastFailureReason) ? { lastFailureReason: asString(protocolValue.lastFailureReason) } : {},
|
|
39030
|
+
...pingValue && typeof pingValue.lastTimeoutAt === "number" ? {
|
|
39031
|
+
ping: {
|
|
39032
|
+
lastTimeoutAt: pingValue.lastTimeoutAt
|
|
39033
|
+
}
|
|
39034
|
+
} : {}
|
|
39035
|
+
}
|
|
39036
|
+
} : {},
|
|
39037
|
+
...transportValue ? {
|
|
39038
|
+
transport: {
|
|
39039
|
+
...typeof transportValue.reconnectCount === "number" ? { reconnectCount: transportValue.reconnectCount } : {},
|
|
39040
|
+
...asString(transportValue.lastReconnectCause) ? { lastReconnectCause: asString(transportValue.lastReconnectCause) } : {}
|
|
39041
|
+
}
|
|
39042
|
+
} : {}
|
|
39043
|
+
};
|
|
39044
|
+
}
|
|
39045
|
+
function isRecentTimestamp(timestamp) {
|
|
39046
|
+
if (typeof timestamp !== "number" || !Number.isFinite(timestamp) || timestamp <= 0)
|
|
39047
|
+
return false;
|
|
39048
|
+
return Date.now() - timestamp <= RECENT_RUNTIME_ISSUE_MS;
|
|
39049
|
+
}
|
|
38669
39050
|
function collectInlineStatusIssues(accounts) {
|
|
38670
39051
|
const issues = [];
|
|
38671
39052
|
for (const entry of accounts) {
|
|
@@ -38721,6 +39102,25 @@ function collectInlineStatusIssues(accounts) {
|
|
|
38721
39102
|
fix: "Verify token/baseUrl connectivity, then re-run channel status."
|
|
38722
39103
|
});
|
|
38723
39104
|
}
|
|
39105
|
+
const diagnostics = readInlineDiagnosticsSummary(entry.diagnostics);
|
|
39106
|
+
if (isRecentTimestamp(diagnostics.protocol?.lastFailureAt) && (diagnostics.transport?.reconnectCount ?? 0) >= 3) {
|
|
39107
|
+
issues.push({
|
|
39108
|
+
channel: "inline",
|
|
39109
|
+
accountId,
|
|
39110
|
+
kind: "runtime",
|
|
39111
|
+
message: `Inline connection is flapping (${diagnostics.transport?.reconnectCount ?? 0} reconnects). ` + `${diagnostics.protocol?.lastFailureReason ?? diagnostics.transport?.lastReconnectCause ?? "Recent reconnect failures detected."}`,
|
|
39112
|
+
fix: "Inspect gateway logs for websocket close/error details and verify Inline API/network stability."
|
|
39113
|
+
});
|
|
39114
|
+
}
|
|
39115
|
+
if (isRecentTimestamp(diagnostics.protocol?.ping?.lastTimeoutAt)) {
|
|
39116
|
+
issues.push({
|
|
39117
|
+
channel: "inline",
|
|
39118
|
+
accountId,
|
|
39119
|
+
kind: "runtime",
|
|
39120
|
+
message: "Inline ping watchdog triggered a reconnect recently.",
|
|
39121
|
+
fix: "Check websocket latency/packet loss and compare last pong timing in the Inline diagnostics snapshot."
|
|
39122
|
+
});
|
|
39123
|
+
}
|
|
38724
39124
|
}
|
|
38725
39125
|
return issues;
|
|
38726
39126
|
}
|
|
@@ -39735,22 +40135,29 @@ var inlineChannelPlugin = {
|
|
|
39735
40135
|
buildChannelSummary: ({ snapshot }) => buildTokenChannelStatusSummary(snapshot),
|
|
39736
40136
|
probeAccount: async ({ account, timeoutMs }) => await probeInlineAccount(account, timeoutMs),
|
|
39737
40137
|
formatCapabilitiesProbe: ({ probe }) => formatInlineCapabilitiesProbeLines(probe),
|
|
39738
|
-
buildAccountSnapshot: ({ account, runtime: runtime2, probe }) =>
|
|
39739
|
-
|
|
39740
|
-
|
|
39741
|
-
|
|
39742
|
-
|
|
39743
|
-
|
|
39744
|
-
|
|
39745
|
-
|
|
39746
|
-
|
|
39747
|
-
|
|
39748
|
-
|
|
39749
|
-
|
|
39750
|
-
|
|
39751
|
-
|
|
39752
|
-
|
|
39753
|
-
|
|
40138
|
+
buildAccountSnapshot: ({ account, runtime: runtime2, probe }) => {
|
|
40139
|
+
const snapshot = {
|
|
40140
|
+
accountId: account.accountId,
|
|
40141
|
+
name: account.name,
|
|
40142
|
+
enabled: account.enabled,
|
|
40143
|
+
configured: account.configured,
|
|
40144
|
+
baseUrl: account.baseUrl ? "[set]" : "[missing]",
|
|
40145
|
+
tokenSource: account.token ? "config" : account.tokenFile ? "file" : "missing",
|
|
40146
|
+
running: runtime2?.running ?? false,
|
|
40147
|
+
lastStartAt: runtime2?.lastStartAt ?? null,
|
|
40148
|
+
lastStopAt: runtime2?.lastStopAt ?? null,
|
|
40149
|
+
lastError: runtime2?.lastError ?? null,
|
|
40150
|
+
lastInboundAt: runtime2?.lastInboundAt ?? null,
|
|
40151
|
+
lastOutboundAt: runtime2?.lastOutboundAt ?? null,
|
|
40152
|
+
lastProbeAt: runtime2?.lastProbeAt ?? null,
|
|
40153
|
+
...probe !== undefined ? { probe } : {}
|
|
40154
|
+
};
|
|
40155
|
+
const diagnostics = runtime2?.diagnostics;
|
|
40156
|
+
if (diagnostics !== undefined) {
|
|
40157
|
+
snapshot.diagnostics = diagnostics;
|
|
40158
|
+
}
|
|
40159
|
+
return snapshot;
|
|
40160
|
+
}
|
|
39754
40161
|
},
|
|
39755
40162
|
gateway: {
|
|
39756
40163
|
startAccount: async (ctx) => {
|
|
@@ -40516,7 +40923,12 @@ async function callInlineBotApi(params) {
|
|
|
40516
40923
|
if (params.body !== undefined) {
|
|
40517
40924
|
request.body = JSON.stringify(params.body);
|
|
40518
40925
|
}
|
|
40519
|
-
|
|
40926
|
+
let response;
|
|
40927
|
+
try {
|
|
40928
|
+
response = await fetch(url2, request);
|
|
40929
|
+
} catch (error48) {
|
|
40930
|
+
throw new Error(`inline_bot_commands: ${params.method} ${redactInlineBotApiUrl(url2)} fetch failed: ${summarizeInlineBotApiError(error48)}`);
|
|
40931
|
+
}
|
|
40520
40932
|
const payload = await response.json().catch(() => null);
|
|
40521
40933
|
return { response, payload };
|
|
40522
40934
|
};
|
|
@@ -40546,6 +40958,20 @@ async function callInlineBotApi(params) {
|
|
|
40546
40958
|
}
|
|
40547
40959
|
return resolve(headerResult);
|
|
40548
40960
|
}
|
|
40961
|
+
function summarizeInlineBotApiError(error48) {
|
|
40962
|
+
if (error48 instanceof Error) {
|
|
40963
|
+
return `${error48.name}: ${error48.message}`;
|
|
40964
|
+
}
|
|
40965
|
+
return String(error48);
|
|
40966
|
+
}
|
|
40967
|
+
function redactInlineBotApiUrl(raw) {
|
|
40968
|
+
try {
|
|
40969
|
+
const url2 = new URL(raw);
|
|
40970
|
+
return `${url2.protocol}//${url2.host}${url2.pathname.replace(/\/bot[^/]*\//, "/bot<redacted>/")}`;
|
|
40971
|
+
} catch {
|
|
40972
|
+
return raw.replace(/\/bot[^/]*\//, "/bot<redacted>/");
|
|
40973
|
+
}
|
|
40974
|
+
}
|
|
40549
40975
|
|
|
40550
40976
|
// src/inline/bot-commands-tool.ts
|
|
40551
40977
|
var BOT_COMMAND_LIMIT = 100;
|
|
@@ -40706,6 +41132,9 @@ function createInlineBotCommandsTool(ctx) {
|
|
|
40706
41132
|
}
|
|
40707
41133
|
|
|
40708
41134
|
// src/inline/bot-commands-sync.ts
|
|
41135
|
+
import { listNativeCommandSpecsForConfig } from "openclaw/plugin-sdk/native-command-registry";
|
|
41136
|
+
import { getPluginCommandSpecs } from "openclaw/plugin-sdk/plugin-runtime";
|
|
41137
|
+
import { listSkillCommandsForAgents } from "openclaw/plugin-sdk/skill-commands-runtime";
|
|
40709
41138
|
var INLINE_BASE_NATIVE_COMMANDS = [
|
|
40710
41139
|
{ command: "help", description: "Show available commands." },
|
|
40711
41140
|
{ command: "commands", description: "List all slash commands." },
|
|
@@ -40735,15 +41164,6 @@ var INLINE_BASE_NATIVE_COMMANDS = [
|
|
|
40735
41164
|
];
|
|
40736
41165
|
var INLINE_COMMAND_NAME_RE = /^[a-z0-9_]{1,32}$/;
|
|
40737
41166
|
var INLINE_COMMAND_LIMIT = 100;
|
|
40738
|
-
var FALLBACK_NATIVE_COMMAND_HELPERS = {
|
|
40739
|
-
available: false,
|
|
40740
|
-
listNativeCommandSpecsForConfig: () => [],
|
|
40741
|
-
listSkillCommandsForAgents: () => []
|
|
40742
|
-
};
|
|
40743
|
-
var FALLBACK_PLUGIN_COMMAND_SPECS = {
|
|
40744
|
-
available: false,
|
|
40745
|
-
specs: []
|
|
40746
|
-
};
|
|
40747
41167
|
function normalizeDynamicCommandName(raw) {
|
|
40748
41168
|
const trimmed = raw.trim().toLowerCase();
|
|
40749
41169
|
const withoutSlash = trimmed.startsWith("/") ? trimmed.slice(1) : trimmed;
|
|
@@ -40777,10 +41197,12 @@ async function buildInlineNativeCommandsForConfig(params) {
|
|
|
40777
41197
|
if (params.cfg.commands?.debug === true) {
|
|
40778
41198
|
commands.push({ command: "debug", description: "Set runtime debug overrides." });
|
|
40779
41199
|
}
|
|
40780
|
-
const { listNativeCommandSpecsForConfig, listSkillCommandsForAgents } = params.nativeHelpers;
|
|
40781
41200
|
const skillCommands = shouldSyncInlineNativeSkills(params.cfg) ? listSkillCommandsForAgents({ cfg: params.cfg }) : [];
|
|
40782
|
-
const nativeSpecs = listNativeCommandSpecsForConfig(params.cfg, {
|
|
40783
|
-
|
|
41201
|
+
const nativeSpecs = listNativeCommandSpecsForConfig(params.cfg, {
|
|
41202
|
+
skillCommands,
|
|
41203
|
+
provider: "telegram"
|
|
41204
|
+
});
|
|
41205
|
+
const pluginSpecs = getPluginCommandSpecs("inline");
|
|
40784
41206
|
const seen = new Set;
|
|
40785
41207
|
const resolved = [];
|
|
40786
41208
|
for (const base of commands) {
|
|
@@ -40797,19 +41219,13 @@ async function buildInlineNativeCommandsForConfig(params) {
|
|
|
40797
41219
|
async function syncInlineNativeCommands(params) {
|
|
40798
41220
|
const accountIds = listInlineAccountIds(params.cfg);
|
|
40799
41221
|
const nativeEnabled = shouldSyncInlineNativeCommands(params.cfg);
|
|
40800
|
-
const nativeHelpers = nativeEnabled ? await loadNativeCommandHelpersCompat() : FALLBACK_NATIVE_COMMAND_HELPERS;
|
|
40801
|
-
const pluginSpecs = nativeEnabled ? await loadPluginCommandSpecsCompat("inline") : FALLBACK_PLUGIN_COMMAND_SPECS;
|
|
40802
|
-
const usingSdkSource = nativeHelpers.available || pluginSpecs.available;
|
|
40803
41222
|
const allCommands = nativeEnabled ? await buildInlineNativeCommandsForConfig({
|
|
40804
|
-
cfg: params.cfg
|
|
40805
|
-
nativeHelpers,
|
|
40806
|
-
pluginSpecs
|
|
41223
|
+
cfg: params.cfg
|
|
40807
41224
|
}) : [];
|
|
40808
41225
|
const commands = allCommands.slice(0, INLINE_COMMAND_LIMIT);
|
|
40809
41226
|
if (allCommands.length > INLINE_COMMAND_LIMIT) {
|
|
40810
41227
|
params.logger?.warn?.(`[inline] native command sync truncating ${allCommands.length} commands to ${INLINE_COMMAND_LIMIT}`);
|
|
40811
41228
|
}
|
|
40812
|
-
params.logger?.info?.(`[inline] native command source: ${usingSdkSource ? "plugin-sdk" : "fallback"}`);
|
|
40813
41229
|
let synced = 0;
|
|
40814
41230
|
let failed = 0;
|
|
40815
41231
|
for (const accountId of accountIds) {
|
|
@@ -40895,5 +41311,5 @@ export {
|
|
|
40895
41311
|
src_default as default
|
|
40896
41312
|
};
|
|
40897
41313
|
|
|
40898
|
-
//# debugId=
|
|
41314
|
+
//# debugId=1C8239561365068664756E2164756E21
|
|
40899
41315
|
//# sourceMappingURL=index.js.map
|