@inline-openclaw/inline 0.0.25 → 0.0.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1005 -240
- package/dist/index.js.map +11 -7
- package/dist/inline/actions.d.ts +4 -4
- package/dist/inline/actions.d.ts.map +1 -1
- package/dist/inline/channel.d.ts.map +1 -1
- package/dist/inline/monitor.d.ts.map +1 -1
- package/dist/inline/probe.d.ts +15 -0
- package/dist/inline/probe.d.ts.map +1 -0
- package/dist/inline/setup-core.d.ts +4 -0
- package/dist/inline/setup-core.d.ts.map +1 -0
- package/dist/inline/setup-surface.d.ts +5 -0
- package/dist/inline/setup-surface.d.ts.map +1 -0
- package/dist/inline/status-issues.d.ts +3 -0
- package/dist/inline/status-issues.d.ts.map +1 -0
- package/dist/sdk-runtime-compat.d.ts.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5547,6 +5547,14 @@ var require_websocket_server = __commonJS((exports, module) => {
|
|
|
5547
5547
|
}
|
|
5548
5548
|
});
|
|
5549
5549
|
|
|
5550
|
+
// src/inline/channel.ts
|
|
5551
|
+
import {
|
|
5552
|
+
deleteAccountFromConfigSection,
|
|
5553
|
+
setAccountEnabledInConfigSection
|
|
5554
|
+
} from "openclaw/plugin-sdk/core";
|
|
5555
|
+
import { buildDmGroupAccountAllowlistAdapter } from "openclaw/plugin-sdk/allowlist-config-edit";
|
|
5556
|
+
import { buildTokenChannelStatusSummary } from "openclaw/plugin-sdk/status-helpers";
|
|
5557
|
+
|
|
5550
5558
|
// ../protocol/dist/core.js
|
|
5551
5559
|
var import_runtime = __toESM(require_commonjs(), 1);
|
|
5552
5560
|
var import_runtime2 = __toESM(require_commonjs(), 1);
|
|
@@ -34023,6 +34031,7 @@ import { mkdir } from "node:fs/promises";
|
|
|
34023
34031
|
import path2 from "node:path";
|
|
34024
34032
|
|
|
34025
34033
|
// src/sdk-runtime-compat.ts
|
|
34034
|
+
import { createMessageToolButtonsSchema } from "openclaw/plugin-sdk/channel-actions";
|
|
34026
34035
|
var HISTORY_CONTEXT_MARKER = "[Chat messages since your last reply - for context]";
|
|
34027
34036
|
var CURRENT_MESSAGE_MARKER = "[Current message - respond to this]";
|
|
34028
34037
|
var MAX_HISTORY_KEYS = 1000;
|
|
@@ -34113,24 +34122,13 @@ function recordPendingHistoryEntryIfEnabled(params) {
|
|
|
34113
34122
|
limit: params.limit
|
|
34114
34123
|
});
|
|
34115
34124
|
}
|
|
34125
|
+
var TYPEBOX_OPTIONAL_SYMBOL = Symbol.for("TypeBox.Optional");
|
|
34126
|
+
function markTypeBoxOptional(schema) {
|
|
34127
|
+
schema[TYPEBOX_OPTIONAL_SYMBOL] = "Optional";
|
|
34128
|
+
return schema;
|
|
34129
|
+
}
|
|
34116
34130
|
function createMessageToolButtonsSchemaCompat() {
|
|
34117
|
-
return
|
|
34118
|
-
type: "array",
|
|
34119
|
-
description: "Button rows for channels that support button-style actions.",
|
|
34120
|
-
items: {
|
|
34121
|
-
type: "array",
|
|
34122
|
-
items: {
|
|
34123
|
-
type: "object",
|
|
34124
|
-
additionalProperties: false,
|
|
34125
|
-
required: ["text", "callback_data"],
|
|
34126
|
-
properties: {
|
|
34127
|
-
text: { type: "string" },
|
|
34128
|
-
callback_data: { type: "string" },
|
|
34129
|
-
style: { type: "string", enum: ["danger", "success", "primary"] }
|
|
34130
|
-
}
|
|
34131
|
-
}
|
|
34132
|
-
}
|
|
34133
|
-
};
|
|
34131
|
+
return markTypeBoxOptional(createMessageToolButtonsSchema());
|
|
34134
34132
|
}
|
|
34135
34133
|
function extensionForMimeCompat(mime) {
|
|
34136
34134
|
const normalized = mime?.trim().toLowerCase();
|
|
@@ -35176,6 +35174,7 @@ var REACTION_TARGET_LOOKUP_LIMIT = 8;
|
|
|
35176
35174
|
var REPLY_TARGET_LOOKUP_LIMIT = 8;
|
|
35177
35175
|
var ATTACHMENT_CONTEXT_LIMIT = 6;
|
|
35178
35176
|
var DEFAULT_INLINE_MEDIA_MAX_BYTES = 300 * 1024 * 1024;
|
|
35177
|
+
var EMPTY_RESPONSE_FALLBACK = "No response generated. Please try again.";
|
|
35179
35178
|
var GET_MESSAGES_METHOD2 = typeof Method.GET_MESSAGES === "number" && Number.isInteger(Method.GET_MESSAGES) && Method.GET_MESSAGES > 0 ? Method.GET_MESSAGES : null;
|
|
35180
35179
|
function normalizeAllowEntry(raw) {
|
|
35181
35180
|
return raw.trim().replace(/^inline:/i, "").replace(/^user:/i, "");
|
|
@@ -36488,193 +36487,287 @@ ${currentEntityText}` : null
|
|
|
36488
36487
|
failed: false,
|
|
36489
36488
|
opChain: Promise.resolve()
|
|
36490
36489
|
};
|
|
36490
|
+
let finalDeliveredForCurrentAssistantMessage = false;
|
|
36491
|
+
const resetEditStreamForAssistantMessage = async () => {
|
|
36492
|
+
await editStreamState.opChain;
|
|
36493
|
+
const hasActiveState = editStreamState.messageId != null || editStreamState.accumulatedText.length > 0 || editStreamState.lastPartialText.length > 0 || editStreamState.finalTextAccumulator.length > 0;
|
|
36494
|
+
if (!hasActiveState)
|
|
36495
|
+
return;
|
|
36496
|
+
editStreamState.messageId = null;
|
|
36497
|
+
editStreamState.accumulatedText = "";
|
|
36498
|
+
editStreamState.lastPartialText = "";
|
|
36499
|
+
editStreamState.finalTextAccumulator = "";
|
|
36500
|
+
editStreamState.failed = false;
|
|
36501
|
+
finalDeliveredForCurrentAssistantMessage = false;
|
|
36502
|
+
};
|
|
36503
|
+
const resetEditStreamOnBoundary = async () => {
|
|
36504
|
+
if (!streamViaEditMessage)
|
|
36505
|
+
return;
|
|
36506
|
+
await resetEditStreamForAssistantMessage();
|
|
36507
|
+
};
|
|
36508
|
+
const handlePartialStreamPayload = async (payload) => {
|
|
36509
|
+
if (editStreamState.failed)
|
|
36510
|
+
return;
|
|
36511
|
+
if ((payload.mediaUrls?.length ?? 0) > 0)
|
|
36512
|
+
return;
|
|
36513
|
+
const partialText = typeof payload.text === "string" ? payload.text : "";
|
|
36514
|
+
if (!partialText || partialText === editStreamState.lastPartialText)
|
|
36515
|
+
return;
|
|
36516
|
+
editStreamState.lastPartialText = partialText;
|
|
36517
|
+
const nextText = rewriteNumericMentionsToUsernames(extractCompleteParagraphText(partialText), senderProfilesById).trim();
|
|
36518
|
+
if (!nextText || nextText === editStreamState.accumulatedText)
|
|
36519
|
+
return;
|
|
36520
|
+
editStreamState.opChain = editStreamState.opChain.then(async () => {
|
|
36521
|
+
if (editStreamState.failed)
|
|
36522
|
+
return;
|
|
36523
|
+
if (!nextText || nextText === editStreamState.accumulatedText)
|
|
36524
|
+
return;
|
|
36525
|
+
try {
|
|
36526
|
+
if (editStreamState.messageId == null) {
|
|
36527
|
+
const sent = await client.sendMessage({
|
|
36528
|
+
chatId,
|
|
36529
|
+
text: nextText,
|
|
36530
|
+
...defaultReplyToMsgId != null ? { replyToMsgId: defaultReplyToMsgId } : {},
|
|
36531
|
+
parseMarkdown
|
|
36532
|
+
});
|
|
36533
|
+
if (sent.messageId == null) {
|
|
36534
|
+
throw new Error("inline edit stream: sendMessage returned no messageId");
|
|
36535
|
+
}
|
|
36536
|
+
editStreamState.messageId = sent.messageId;
|
|
36537
|
+
rememberBotMessageId(botMessageIdsByChat, chatId, sent.messageId);
|
|
36538
|
+
} else {
|
|
36539
|
+
const result = await client.invokeRaw(Method.EDIT_MESSAGE, {
|
|
36540
|
+
oneofKind: "editMessage",
|
|
36541
|
+
editMessage: {
|
|
36542
|
+
messageId: editStreamState.messageId,
|
|
36543
|
+
peerId: buildChatPeer2(chatId),
|
|
36544
|
+
text: nextText,
|
|
36545
|
+
parseMarkdown
|
|
36546
|
+
}
|
|
36547
|
+
});
|
|
36548
|
+
if (result.oneofKind !== "editMessage") {
|
|
36549
|
+
throw new Error(`inline edit stream: expected editMessage result, got ${String(result.oneofKind)}`);
|
|
36550
|
+
}
|
|
36551
|
+
}
|
|
36552
|
+
editStreamState.accumulatedText = nextText;
|
|
36553
|
+
statusSink?.({ lastOutboundAt: Date.now() });
|
|
36554
|
+
} catch (error48) {
|
|
36555
|
+
editStreamState.failed = true;
|
|
36556
|
+
runtime2.error?.(`inline edit stream failed: ${String(error48)}`);
|
|
36557
|
+
}
|
|
36558
|
+
});
|
|
36559
|
+
await editStreamState.opChain;
|
|
36560
|
+
};
|
|
36491
36561
|
const replyOptions = {
|
|
36492
36562
|
...onModelSelected ? { onModelSelected } : {},
|
|
36493
36563
|
blockReplyTimeoutMs: 25000,
|
|
36564
|
+
...streamViaEditMessage ? {
|
|
36565
|
+
onAssistantMessageStart: async () => {
|
|
36566
|
+
await resetEditStreamOnBoundary();
|
|
36567
|
+
}
|
|
36568
|
+
} : {},
|
|
36494
36569
|
...streamViaEditMessage ? {
|
|
36495
36570
|
onPartialReply: async (payload) => {
|
|
36496
|
-
|
|
36497
|
-
|
|
36498
|
-
|
|
36499
|
-
|
|
36500
|
-
|
|
36501
|
-
|
|
36502
|
-
|
|
36503
|
-
|
|
36504
|
-
|
|
36505
|
-
|
|
36506
|
-
|
|
36507
|
-
|
|
36508
|
-
|
|
36509
|
-
|
|
36510
|
-
|
|
36511
|
-
|
|
36512
|
-
|
|
36513
|
-
|
|
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 {}
|
|
36624
|
+
}
|
|
36625
|
+
if (replyToMsgId == null && isGroup && msg.replyToMsgId != null) {
|
|
36626
|
+
replyToMsgId = msg.id;
|
|
36627
|
+
}
|
|
36628
|
+
const rememberSent = (messageId) => {
|
|
36629
|
+
if (messageId != null) {
|
|
36630
|
+
rememberBotMessageId(botMessageIdsByChat, chatId, messageId);
|
|
36631
|
+
}
|
|
36632
|
+
};
|
|
36633
|
+
const sendTextFallback = async (text, includeReplyTo, includeActions) => {
|
|
36634
|
+
if (!text.trim())
|
|
36635
|
+
return;
|
|
36514
36636
|
const sent = await client.sendMessage({
|
|
36515
36637
|
chatId,
|
|
36516
|
-
text
|
|
36517
|
-
...
|
|
36638
|
+
text,
|
|
36639
|
+
...includeReplyTo && replyToMsgId != null ? { replyToMsgId } : {},
|
|
36640
|
+
...includeActions && outboundActions !== undefined ? { actions: outboundActions } : {},
|
|
36518
36641
|
parseMarkdown
|
|
36519
36642
|
});
|
|
36520
|
-
|
|
36521
|
-
|
|
36522
|
-
|
|
36523
|
-
|
|
36524
|
-
|
|
36525
|
-
|
|
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;
|
|
36526
36657
|
const result = await client.invokeRaw(Method.EDIT_MESSAGE, {
|
|
36527
36658
|
oneofKind: "editMessage",
|
|
36528
36659
|
editMessage: {
|
|
36529
36660
|
messageId: editStreamState.messageId,
|
|
36530
36661
|
peerId: buildChatPeer2(chatId),
|
|
36531
|
-
text:
|
|
36532
|
-
parseMarkdown
|
|
36662
|
+
text: textForEdit,
|
|
36663
|
+
parseMarkdown,
|
|
36664
|
+
...actions !== undefined ? { actions } : {}
|
|
36533
36665
|
}
|
|
36534
36666
|
});
|
|
36535
36667
|
if (result.oneofKind !== "editMessage") {
|
|
36536
36668
|
throw new Error(`inline edit stream: expected editMessage result, got ${String(result.oneofKind)}`);
|
|
36537
36669
|
}
|
|
36538
|
-
|
|
36539
|
-
|
|
36540
|
-
|
|
36541
|
-
} catch (error48) {
|
|
36542
|
-
editStreamState.failed = true;
|
|
36543
|
-
runtime2.error?.(`inline edit stream failed: ${String(error48)}`);
|
|
36544
|
-
}
|
|
36545
|
-
});
|
|
36546
|
-
await editStreamState.opChain;
|
|
36547
|
-
}
|
|
36548
|
-
} : {},
|
|
36549
|
-
...typeof disableBlockStreaming === "boolean" ? { disableBlockStreaming } : {}
|
|
36550
|
-
};
|
|
36551
|
-
try {
|
|
36552
|
-
await core3.channel.reply.dispatchReplyWithBufferedBlockDispatcher({
|
|
36553
|
-
ctx: ctxPayload,
|
|
36554
|
-
cfg,
|
|
36555
|
-
dispatcherOptions: {
|
|
36556
|
-
...prefixOptions,
|
|
36557
|
-
...typingCallbacks ? { typingCallbacks } : {},
|
|
36558
|
-
deliver: async (payload) => {
|
|
36559
|
-
const rawText = payload.text ?? "";
|
|
36560
|
-
const mediaList = payload.mediaUrls?.length ? payload.mediaUrls : payload.mediaUrl ? [payload.mediaUrl] : [];
|
|
36561
|
-
const outboundText = rewriteNumericMentionsToUsernames(rawText, senderProfilesById);
|
|
36562
|
-
const outboundActions = resolveInlineReplyActions(payload);
|
|
36563
|
-
let replyToMsgId;
|
|
36564
|
-
if (payload.replyToId != null) {
|
|
36565
|
-
try {
|
|
36566
|
-
replyToMsgId = BigInt(payload.replyToId);
|
|
36567
|
-
} catch {}
|
|
36568
|
-
}
|
|
36569
|
-
if (replyToMsgId == null && isGroup && msg.replyToMsgId != null) {
|
|
36570
|
-
replyToMsgId = msg.id;
|
|
36571
|
-
}
|
|
36572
|
-
const rememberSent = (messageId) => {
|
|
36573
|
-
if (messageId != null) {
|
|
36574
|
-
rememberBotMessageId(botMessageIdsByChat, chatId, messageId);
|
|
36575
|
-
}
|
|
36576
|
-
};
|
|
36577
|
-
const sendTextFallback = async (text, includeReplyTo, includeActions) => {
|
|
36578
|
-
if (!text.trim())
|
|
36579
|
-
return;
|
|
36580
|
-
const sent = await client.sendMessage({
|
|
36581
|
-
chatId,
|
|
36582
|
-
text,
|
|
36583
|
-
...includeReplyTo && replyToMsgId != null ? { replyToMsgId } : {},
|
|
36584
|
-
...includeActions && outboundActions !== undefined ? { actions: outboundActions } : {},
|
|
36585
|
-
parseMarkdown
|
|
36586
|
-
});
|
|
36587
|
-
rememberSent(sent.messageId);
|
|
36588
|
-
};
|
|
36589
|
-
const updateStreamedMessage = async (text, actions) => {
|
|
36590
|
-
await editStreamState.opChain;
|
|
36591
|
-
if (editStreamState.messageId == null)
|
|
36592
|
-
return false;
|
|
36593
|
-
const nextText = text.trim();
|
|
36594
|
-
const textForEdit = nextText || editStreamState.accumulatedText;
|
|
36595
|
-
if (!textForEdit)
|
|
36596
|
-
return true;
|
|
36597
|
-
const shouldSkipTextUpdate = !editStreamState.failed && textForEdit === editStreamState.accumulatedText;
|
|
36598
|
-
if (shouldSkipTextUpdate && actions === undefined)
|
|
36599
|
-
return true;
|
|
36600
|
-
const result = await client.invokeRaw(Method.EDIT_MESSAGE, {
|
|
36601
|
-
oneofKind: "editMessage",
|
|
36602
|
-
editMessage: {
|
|
36603
|
-
messageId: editStreamState.messageId,
|
|
36604
|
-
peerId: buildChatPeer2(chatId),
|
|
36605
|
-
text: textForEdit,
|
|
36606
|
-
parseMarkdown,
|
|
36607
|
-
...actions !== undefined ? { actions } : {}
|
|
36670
|
+
if (!shouldSkipTextUpdate) {
|
|
36671
|
+
editStreamState.accumulatedText = textForEdit;
|
|
36672
|
+
editStreamState.lastPartialText = textForEdit;
|
|
36608
36673
|
}
|
|
36609
|
-
|
|
36610
|
-
|
|
36611
|
-
|
|
36612
|
-
|
|
36613
|
-
|
|
36614
|
-
|
|
36615
|
-
editStreamState.lastPartialText = textForEdit;
|
|
36616
|
-
}
|
|
36617
|
-
editStreamState.failed = false;
|
|
36618
|
-
return true;
|
|
36619
|
-
};
|
|
36620
|
-
if (mediaList.length === 0) {
|
|
36621
|
-
if (streamViaEditMessage && editStreamState.messageId != null) {
|
|
36622
|
-
if (outboundText.trim()) {
|
|
36623
|
-
editStreamState.finalTextAccumulator += outboundText;
|
|
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();
|
|
36624
36680
|
}
|
|
36625
|
-
if (
|
|
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() });
|
|
36626
36694
|
return;
|
|
36627
36695
|
}
|
|
36628
|
-
|
|
36696
|
+
if (!outboundText.trim())
|
|
36697
|
+
return;
|
|
36698
|
+
await sendTextFallback(outboundText, true, true);
|
|
36629
36699
|
statusSink?.({ lastOutboundAt: Date.now() });
|
|
36630
36700
|
return;
|
|
36631
36701
|
}
|
|
36632
|
-
if (
|
|
36633
|
-
|
|
36634
|
-
|
|
36635
|
-
|
|
36636
|
-
|
|
36637
|
-
|
|
36638
|
-
|
|
36639
|
-
|
|
36640
|
-
|
|
36641
|
-
|
|
36642
|
-
|
|
36643
|
-
|
|
36644
|
-
|
|
36645
|
-
|
|
36646
|
-
|
|
36647
|
-
|
|
36648
|
-
|
|
36649
|
-
|
|
36650
|
-
|
|
36651
|
-
|
|
36652
|
-
|
|
36653
|
-
|
|
36654
|
-
|
|
36655
|
-
|
|
36656
|
-
|
|
36657
|
-
|
|
36658
|
-
|
|
36659
|
-
|
|
36660
|
-
|
|
36661
|
-
|
|
36662
|
-
});
|
|
36663
|
-
rememberSent(sent.messageId);
|
|
36664
|
-
} catch (error48) {
|
|
36665
|
-
runtime2.error?.(`inline media upload failed; falling back to url text (${String(error48)})`);
|
|
36666
|
-
const fallbackText = caption ? `${caption}
|
|
36702
|
+
if (streamViaEditMessage && editStreamState.messageId != null && outboundText.trim()) {
|
|
36703
|
+
await updateStreamedMessage(outboundText, outboundActions);
|
|
36704
|
+
}
|
|
36705
|
+
for (let index = 0;index < mediaList.length; index++) {
|
|
36706
|
+
const mediaUrl = mediaList[index];
|
|
36707
|
+
if (!mediaUrl?.trim())
|
|
36708
|
+
continue;
|
|
36709
|
+
const isFirst = index === 0;
|
|
36710
|
+
const shouldAttachActionsToMedia = isFirst && (!(streamViaEditMessage && editStreamState.messageId != null) || !outboundText.trim());
|
|
36711
|
+
const caption = isFirst && !(streamViaEditMessage && editStreamState.messageId != null) ? outboundText : "";
|
|
36712
|
+
try {
|
|
36713
|
+
const media = await uploadInlineMediaFromUrl({
|
|
36714
|
+
client,
|
|
36715
|
+
cfg,
|
|
36716
|
+
accountId: account.accountId,
|
|
36717
|
+
mediaUrl
|
|
36718
|
+
});
|
|
36719
|
+
const sent = await client.sendMessage({
|
|
36720
|
+
chatId,
|
|
36721
|
+
...caption ? { text: caption } : {},
|
|
36722
|
+
media,
|
|
36723
|
+
...isFirst && replyToMsgId != null ? { replyToMsgId } : {},
|
|
36724
|
+
...shouldAttachActionsToMedia && outboundActions !== undefined ? { actions: outboundActions } : {},
|
|
36725
|
+
...caption ? { parseMarkdown } : {}
|
|
36726
|
+
});
|
|
36727
|
+
rememberSent(sent.messageId);
|
|
36728
|
+
delivered = true;
|
|
36729
|
+
} catch (error48) {
|
|
36730
|
+
runtime2.error?.(`inline media upload failed; falling back to url text (${String(error48)})`);
|
|
36731
|
+
const fallbackText = caption ? `${caption}
|
|
36667
36732
|
|
|
36668
36733
|
Attachment: ${mediaUrl}` : `Attachment: ${mediaUrl}`;
|
|
36669
|
-
|
|
36734
|
+
await sendTextFallback(fallbackText, isFirst, isFirst);
|
|
36735
|
+
}
|
|
36736
|
+
}
|
|
36737
|
+
statusSink?.({ lastOutboundAt: Date.now() });
|
|
36738
|
+
},
|
|
36739
|
+
onSkip: (_payload, info) => {
|
|
36740
|
+
if (info?.reason !== "silent") {
|
|
36741
|
+
skippedNonSilent = true;
|
|
36670
36742
|
}
|
|
36743
|
+
},
|
|
36744
|
+
onError: (err, info) => {
|
|
36745
|
+
failedNonSilent = true;
|
|
36746
|
+
runtime2.error?.(`inline ${info?.kind ?? "final"} reply failed: ${String(err)}`);
|
|
36671
36747
|
}
|
|
36672
|
-
statusSink?.({ lastOutboundAt: Date.now() });
|
|
36673
36748
|
},
|
|
36674
|
-
|
|
36675
|
-
}
|
|
36676
|
-
|
|
36677
|
-
|
|
36749
|
+
replyOptions
|
|
36750
|
+
});
|
|
36751
|
+
} catch (error48) {
|
|
36752
|
+
dispatchError = error48;
|
|
36753
|
+
runtime2.error?.(`inline dispatch failed: ${String(error48)}`);
|
|
36754
|
+
}
|
|
36755
|
+
if (!delivered && streamViaEditMessage && editStreamState.messageId != null) {
|
|
36756
|
+
delivered = true;
|
|
36757
|
+
}
|
|
36758
|
+
if (!delivered && (dispatchError != null || skippedNonSilent || failedNonSilent)) {
|
|
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);
|
|
36768
|
+
}
|
|
36769
|
+
statusSink?.({ lastOutboundAt: Date.now() });
|
|
36770
|
+
}
|
|
36678
36771
|
} finally {
|
|
36679
36772
|
if (callbackActionEvent && !callbackActionAnswered) {
|
|
36680
36773
|
try {
|
|
@@ -36715,6 +36808,12 @@ Attachment: ${mediaUrl}` : `Attachment: ${mediaUrl}`;
|
|
|
36715
36808
|
return { stop, done: loop.catch(() => {}) };
|
|
36716
36809
|
}
|
|
36717
36810
|
|
|
36811
|
+
// src/inline/actions.ts
|
|
36812
|
+
import {
|
|
36813
|
+
normalizeInteractiveReply,
|
|
36814
|
+
reduceInteractiveReply
|
|
36815
|
+
} from "openclaw/plugin-sdk/interactive-runtime";
|
|
36816
|
+
|
|
36718
36817
|
// src/inline/space-members.ts
|
|
36719
36818
|
function buildInlineUserDisplayName(user) {
|
|
36720
36819
|
const explicit = [user.firstName?.trim(), user.lastName?.trim()].filter(Boolean).join(" ");
|
|
@@ -36843,9 +36942,78 @@ function normalizeReplyMarkupButtons(raw) {
|
|
|
36843
36942
|
}
|
|
36844
36943
|
return rows;
|
|
36845
36944
|
}
|
|
36945
|
+
function chunkInteractiveButtons(buttons, rows) {
|
|
36946
|
+
for (let i = 0;i < buttons.length; i += INLINE_ACTION_MAX_PER_ROW2) {
|
|
36947
|
+
const row = buttons.slice(i, i + INLINE_ACTION_MAX_PER_ROW2).map((button) => {
|
|
36948
|
+
const text = button.label.trim();
|
|
36949
|
+
const callbackData = button.value.trim();
|
|
36950
|
+
if (!text || !callbackData) {
|
|
36951
|
+
return null;
|
|
36952
|
+
}
|
|
36953
|
+
return { text, callback_data: callbackData };
|
|
36954
|
+
}).filter((button) => button != null);
|
|
36955
|
+
if (row.length === 0)
|
|
36956
|
+
continue;
|
|
36957
|
+
rows.push(row);
|
|
36958
|
+
if (rows.length >= INLINE_ACTION_MAX_ROWS2)
|
|
36959
|
+
return;
|
|
36960
|
+
}
|
|
36961
|
+
}
|
|
36962
|
+
function resolveInlineInteractiveButtonsParam(params) {
|
|
36963
|
+
if (!Object.prototype.hasOwnProperty.call(params, "interactive")) {
|
|
36964
|
+
return;
|
|
36965
|
+
}
|
|
36966
|
+
let rawInteractive = params.interactive;
|
|
36967
|
+
if (typeof rawInteractive === "string") {
|
|
36968
|
+
const trimmed = rawInteractive.trim();
|
|
36969
|
+
if (!trimmed) {
|
|
36970
|
+
return;
|
|
36971
|
+
}
|
|
36972
|
+
try {
|
|
36973
|
+
rawInteractive = JSON.parse(trimmed);
|
|
36974
|
+
} catch {
|
|
36975
|
+
throw new Error("inline action: interactive must be valid JSON");
|
|
36976
|
+
}
|
|
36977
|
+
}
|
|
36978
|
+
const interactive = normalizeInteractiveReply(rawInteractive);
|
|
36979
|
+
if (!interactive) {
|
|
36980
|
+
return;
|
|
36981
|
+
}
|
|
36982
|
+
const rows = reduceInteractiveReply(interactive, [], (state, block) => {
|
|
36983
|
+
if (state.length >= INLINE_ACTION_MAX_ROWS2) {
|
|
36984
|
+
return state;
|
|
36985
|
+
}
|
|
36986
|
+
if (block.type === "buttons") {
|
|
36987
|
+
chunkInteractiveButtons(block.buttons, state);
|
|
36988
|
+
return state;
|
|
36989
|
+
}
|
|
36990
|
+
if (block.type === "select") {
|
|
36991
|
+
chunkInteractiveButtons(block.options.map((option) => ({ label: option.label, value: option.value })), state);
|
|
36992
|
+
}
|
|
36993
|
+
return state;
|
|
36994
|
+
});
|
|
36995
|
+
return rows.length > 0 ? rows : undefined;
|
|
36996
|
+
}
|
|
36997
|
+
function toInlineMessageActions(rows) {
|
|
36998
|
+
return {
|
|
36999
|
+
rows: rows.map((row, rowIndex) => ({
|
|
37000
|
+
actions: row.map((button, buttonIndex) => ({
|
|
37001
|
+
actionId: `btn_${rowIndex + 1}_${buttonIndex + 1}`,
|
|
37002
|
+
text: button.text,
|
|
37003
|
+
action: {
|
|
37004
|
+
oneofKind: "callback",
|
|
37005
|
+
callback: {
|
|
37006
|
+
data: new TextEncoder().encode(button.callback_data)
|
|
37007
|
+
}
|
|
37008
|
+
}
|
|
37009
|
+
}))
|
|
37010
|
+
}))
|
|
37011
|
+
};
|
|
37012
|
+
}
|
|
36846
37013
|
function resolveInlineMessageActionsParam(params) {
|
|
36847
37014
|
if (!Object.prototype.hasOwnProperty.call(params, "buttons")) {
|
|
36848
|
-
|
|
37015
|
+
const interactiveRows = resolveInlineInteractiveButtonsParam(params);
|
|
37016
|
+
return interactiveRows ? toInlineMessageActions(interactiveRows) : undefined;
|
|
36849
37017
|
}
|
|
36850
37018
|
let rawButtons = params.buttons;
|
|
36851
37019
|
if (typeof rawButtons === "string") {
|
|
@@ -36867,20 +37035,7 @@ function resolveInlineMessageActionsParam(params) {
|
|
|
36867
37035
|
throw new Error("inline action: buttons must be an array of button rows");
|
|
36868
37036
|
}
|
|
36869
37037
|
const rows = normalizeReplyMarkupButtons(rawButtons);
|
|
36870
|
-
return
|
|
36871
|
-
rows: rows.map((row, rowIndex) => ({
|
|
36872
|
-
actions: row.map((button, buttonIndex) => ({
|
|
36873
|
-
actionId: `btn_${rowIndex + 1}_${buttonIndex + 1}`,
|
|
36874
|
-
text: button.text,
|
|
36875
|
-
action: {
|
|
36876
|
-
oneofKind: "callback",
|
|
36877
|
-
callback: {
|
|
36878
|
-
data: new TextEncoder().encode(button.callback_data)
|
|
36879
|
-
}
|
|
36880
|
-
}
|
|
36881
|
-
}))
|
|
36882
|
-
}))
|
|
36883
|
-
};
|
|
37038
|
+
return toInlineMessageActions(rows);
|
|
36884
37039
|
}
|
|
36885
37040
|
function normalizeChatId(raw) {
|
|
36886
37041
|
const normalized = normalizeInlineTarget(raw) ?? raw.trim();
|
|
@@ -36936,12 +37091,33 @@ function parseInlineId(raw, label) {
|
|
|
36936
37091
|
throw new Error(`inline action: missing ${label}`);
|
|
36937
37092
|
}
|
|
36938
37093
|
if (!/^[0-9]+$/.test(trimmed)) {
|
|
37094
|
+
if (/message/i.test(label)) {
|
|
37095
|
+
const prefixed = trimmed.match(/^(?:message|msg)\s*#?\s*([0-9]+)$/i)?.[1];
|
|
37096
|
+
if (prefixed) {
|
|
37097
|
+
return BigInt(prefixed);
|
|
37098
|
+
}
|
|
37099
|
+
}
|
|
36939
37100
|
throw new Error(`inline action: invalid ${label} "${raw}"`);
|
|
36940
37101
|
}
|
|
36941
37102
|
return BigInt(trimmed);
|
|
36942
37103
|
}
|
|
36943
37104
|
throw new Error(`inline action: missing ${label}`);
|
|
36944
37105
|
}
|
|
37106
|
+
function resolveReactionMessageId(params) {
|
|
37107
|
+
const explicit = readFlexibleId(params.args, "messageId") ?? readStringParam(params.args, "messageId");
|
|
37108
|
+
if (explicit) {
|
|
37109
|
+
return explicit;
|
|
37110
|
+
}
|
|
37111
|
+
const fromContext = params.toolContext?.currentMessageId;
|
|
37112
|
+
if (typeof fromContext === "number" && Number.isFinite(fromContext)) {
|
|
37113
|
+
return String(Math.trunc(fromContext));
|
|
37114
|
+
}
|
|
37115
|
+
if (typeof fromContext === "string") {
|
|
37116
|
+
const trimmed = fromContext.trim();
|
|
37117
|
+
return trimmed || undefined;
|
|
37118
|
+
}
|
|
37119
|
+
return;
|
|
37120
|
+
}
|
|
36945
37121
|
function parseOptionalInlineId(raw, label) {
|
|
36946
37122
|
if (raw == null)
|
|
36947
37123
|
return;
|
|
@@ -37195,6 +37371,7 @@ function mapChatEntry(params) {
|
|
|
37195
37371
|
}
|
|
37196
37372
|
return {
|
|
37197
37373
|
id: String(params.chat.id),
|
|
37374
|
+
target: `chat:${String(params.chat.id)}`,
|
|
37198
37375
|
title: params.chat.title,
|
|
37199
37376
|
spaceId: params.chat.spaceId != null ? String(params.chat.spaceId) : null,
|
|
37200
37377
|
isPublic: params.chat.isPublic ?? false,
|
|
@@ -37206,11 +37383,29 @@ function mapChatEntry(params) {
|
|
|
37206
37383
|
peer: peer?.oneofKind === "user" ? {
|
|
37207
37384
|
kind: "user",
|
|
37208
37385
|
id: String(peer.user.userId),
|
|
37386
|
+
target: `user:${String(peer.user.userId)}`,
|
|
37209
37387
|
username: peerUser?.username ?? null,
|
|
37210
37388
|
name: peerUser ? buildInlineUserDisplayName(peerUser) : null
|
|
37211
|
-
} : peer?.oneofKind === "chat" ? { kind: "chat", id: String(peer.chat.chatId) } : null
|
|
37389
|
+
} : peer?.oneofKind === "chat" ? { kind: "chat", id: String(peer.chat.chatId), target: `chat:${String(peer.chat.chatId)}` } : null
|
|
37212
37390
|
};
|
|
37213
37391
|
}
|
|
37392
|
+
function normalizeInlineListQuery(query) {
|
|
37393
|
+
return query?.trim().toLowerCase() ?? "";
|
|
37394
|
+
}
|
|
37395
|
+
function mapUserPeerEntry(user) {
|
|
37396
|
+
return {
|
|
37397
|
+
id: String(user.id),
|
|
37398
|
+
target: `user:${String(user.id)}`,
|
|
37399
|
+
username: user.username ?? null,
|
|
37400
|
+
name: buildInlineUserDisplayName(user),
|
|
37401
|
+
bot: user.bot ?? false
|
|
37402
|
+
};
|
|
37403
|
+
}
|
|
37404
|
+
function matchesInlineListQuery(text, query) {
|
|
37405
|
+
if (!query)
|
|
37406
|
+
return true;
|
|
37407
|
+
return text.toLowerCase().includes(query);
|
|
37408
|
+
}
|
|
37214
37409
|
async function loadMessageReactions(params) {
|
|
37215
37410
|
const target = await findMessageById({
|
|
37216
37411
|
client: params.client,
|
|
@@ -37239,6 +37434,28 @@ async function loadMessageReactions(params) {
|
|
|
37239
37434
|
}
|
|
37240
37435
|
return Array.from(byEmoji.values());
|
|
37241
37436
|
}
|
|
37437
|
+
function getErrorMessage(error48) {
|
|
37438
|
+
if (error48 instanceof Error)
|
|
37439
|
+
return error48.message;
|
|
37440
|
+
if (typeof error48 === "string")
|
|
37441
|
+
return error48;
|
|
37442
|
+
if (error48 && typeof error48 === "object" && "message" in error48 && typeof error48.message === "string") {
|
|
37443
|
+
return error48.message;
|
|
37444
|
+
}
|
|
37445
|
+
return String(error48);
|
|
37446
|
+
}
|
|
37447
|
+
function isDuplicateReactionError(error48) {
|
|
37448
|
+
const text = getErrorMessage(error48).toLowerCase();
|
|
37449
|
+
return text.includes("unique_reaction_per_emoji") || text.includes("duplicate") && text.includes("reaction") || text.includes("duplicate key value violates unique constraint");
|
|
37450
|
+
}
|
|
37451
|
+
async function reactionAlreadyExists(params) {
|
|
37452
|
+
const me = await params.client.getMe().catch(() => null);
|
|
37453
|
+
if (!me?.userId)
|
|
37454
|
+
return false;
|
|
37455
|
+
const myId = String(me.userId);
|
|
37456
|
+
const reactions = await loadMessageReactions(params).catch(() => []);
|
|
37457
|
+
return reactions.some((reaction) => reaction.emoji === params.emoji && reaction.userIds.includes(myId));
|
|
37458
|
+
}
|
|
37242
37459
|
async function findMessageById(params) {
|
|
37243
37460
|
const directResult = GET_MESSAGES_METHOD3 == null ? null : await params.client.invokeRaw(GET_MESSAGES_METHOD3, {
|
|
37244
37461
|
oneofKind: "getMessages",
|
|
@@ -37348,13 +37565,12 @@ function listAllActions() {
|
|
|
37348
37565
|
return Array.from(out);
|
|
37349
37566
|
}
|
|
37350
37567
|
function listEnabledInlineActions(cfg) {
|
|
37351
|
-
const
|
|
37352
|
-
if (
|
|
37568
|
+
const gates = listInlineAccountIds(cfg).map((accountId) => resolveInlineAccount({ cfg, accountId })).filter((account) => account.enabled && account.configured).map((account) => createActionGate(account.config.actions ?? {}));
|
|
37569
|
+
if (gates.length === 0)
|
|
37353
37570
|
return [];
|
|
37354
|
-
const gate = createActionGate(account.config.actions ?? {});
|
|
37355
37571
|
const actions = new Set;
|
|
37356
37572
|
for (const group of ACTION_GROUPS) {
|
|
37357
|
-
if (!gate(group.key, group.defaultEnabled))
|
|
37573
|
+
if (!gates.some((gate) => gate(group.key, group.defaultEnabled)))
|
|
37358
37574
|
continue;
|
|
37359
37575
|
for (const action of group.actions) {
|
|
37360
37576
|
actions.add(action);
|
|
@@ -37423,11 +37639,18 @@ var inlineMessageActions = {
|
|
|
37423
37639
|
return null;
|
|
37424
37640
|
return { to: normalized };
|
|
37425
37641
|
},
|
|
37426
|
-
handleAction: async ({ action, params, cfg, accountId }) => {
|
|
37642
|
+
handleAction: async ({ action, params, cfg, accountId, toolContext }) => {
|
|
37427
37643
|
if (!SUPPORTED_ACTIONS.includes(action)) {
|
|
37428
37644
|
throw new Error(`Action ${action} is not supported for provider inline.`);
|
|
37429
37645
|
}
|
|
37430
37646
|
if (!isActionEnabled({ cfg, accountId: accountId ?? null, action })) {
|
|
37647
|
+
if (action === "react") {
|
|
37648
|
+
return jsonResult({
|
|
37649
|
+
ok: false,
|
|
37650
|
+
reason: "disabled",
|
|
37651
|
+
hint: "Inline reactions are disabled via channels.inline.actions.reactions. Do not retry."
|
|
37652
|
+
});
|
|
37653
|
+
}
|
|
37431
37654
|
throw new Error(`inline action: ${action} is disabled by channels.inline.actions`);
|
|
37432
37655
|
}
|
|
37433
37656
|
const normalizedAction = action;
|
|
@@ -37552,7 +37775,24 @@ var inlineMessageActions = {
|
|
|
37552
37775
|
accountId,
|
|
37553
37776
|
fn: async (client) => {
|
|
37554
37777
|
const chatId = resolveChatIdFromParams(params);
|
|
37555
|
-
const
|
|
37778
|
+
const rawMessageId = resolveReactionMessageId(toolContext != null ? { args: params, toolContext } : { args: params });
|
|
37779
|
+
if (!rawMessageId) {
|
|
37780
|
+
return jsonResult({
|
|
37781
|
+
ok: false,
|
|
37782
|
+
reason: "missing_message_id",
|
|
37783
|
+
hint: "Inline reaction requires a valid messageId (or inbound context fallback). Do not retry."
|
|
37784
|
+
});
|
|
37785
|
+
}
|
|
37786
|
+
let messageId;
|
|
37787
|
+
try {
|
|
37788
|
+
messageId = parseInlineId(rawMessageId, "messageId");
|
|
37789
|
+
} catch {
|
|
37790
|
+
return jsonResult({
|
|
37791
|
+
ok: false,
|
|
37792
|
+
reason: "missing_message_id",
|
|
37793
|
+
hint: "Inline reaction requires a valid messageId (or inbound context fallback). Do not retry."
|
|
37794
|
+
});
|
|
37795
|
+
}
|
|
37556
37796
|
const { emoji: emoji3, remove, isEmpty } = readReactionParams(params, {
|
|
37557
37797
|
removeErrorMessage: "Emoji is required to remove an Inline reaction."
|
|
37558
37798
|
});
|
|
@@ -37560,28 +37800,72 @@ var inlineMessageActions = {
|
|
|
37560
37800
|
throw new Error("inline action: react requires emoji");
|
|
37561
37801
|
}
|
|
37562
37802
|
if (remove) {
|
|
37563
|
-
|
|
37564
|
-
|
|
37565
|
-
|
|
37566
|
-
|
|
37567
|
-
|
|
37568
|
-
|
|
37803
|
+
try {
|
|
37804
|
+
const result = await client.invokeRaw(Method.DELETE_REACTION, {
|
|
37805
|
+
oneofKind: "deleteReaction",
|
|
37806
|
+
deleteReaction: {
|
|
37807
|
+
emoji: emoji3,
|
|
37808
|
+
peerId: buildChatPeer3(chatId),
|
|
37809
|
+
messageId
|
|
37810
|
+
}
|
|
37811
|
+
});
|
|
37812
|
+
if (result.oneofKind !== "deleteReaction") {
|
|
37813
|
+
throw new Error(`inline action: expected deleteReaction result, got ${String(result.oneofKind)}`);
|
|
37569
37814
|
}
|
|
37570
|
-
}
|
|
37571
|
-
|
|
37572
|
-
|
|
37815
|
+
} catch {
|
|
37816
|
+
return jsonResult({
|
|
37817
|
+
ok: false,
|
|
37818
|
+
reason: "error",
|
|
37819
|
+
emoji: emoji3,
|
|
37820
|
+
remove: true,
|
|
37821
|
+
hint: "Reaction failed. Do not retry."
|
|
37822
|
+
});
|
|
37573
37823
|
}
|
|
37574
37824
|
} else {
|
|
37575
|
-
|
|
37576
|
-
|
|
37577
|
-
|
|
37825
|
+
if (await reactionAlreadyExists({
|
|
37826
|
+
client,
|
|
37827
|
+
chatId,
|
|
37828
|
+
messageId,
|
|
37829
|
+
emoji: emoji3
|
|
37830
|
+
})) {
|
|
37831
|
+
return jsonResult({
|
|
37832
|
+
ok: true,
|
|
37833
|
+
chatId: String(chatId),
|
|
37834
|
+
messageId: String(messageId),
|
|
37578
37835
|
emoji: emoji3,
|
|
37579
|
-
|
|
37580
|
-
|
|
37836
|
+
remove: false,
|
|
37837
|
+
alreadyPresent: true
|
|
37838
|
+
});
|
|
37839
|
+
}
|
|
37840
|
+
try {
|
|
37841
|
+
const result = await client.invokeRaw(Method.ADD_REACTION, {
|
|
37842
|
+
oneofKind: "addReaction",
|
|
37843
|
+
addReaction: {
|
|
37844
|
+
emoji: emoji3,
|
|
37845
|
+
messageId,
|
|
37846
|
+
peerId: buildChatPeer3(chatId)
|
|
37847
|
+
}
|
|
37848
|
+
});
|
|
37849
|
+
if (result.oneofKind !== "addReaction") {
|
|
37850
|
+
throw new Error(`inline action: expected addReaction result, got ${String(result.oneofKind)}`);
|
|
37581
37851
|
}
|
|
37582
|
-
})
|
|
37583
|
-
|
|
37584
|
-
|
|
37852
|
+
} catch (error48) {
|
|
37853
|
+
if (!isDuplicateReactionError(error48)) {
|
|
37854
|
+
return jsonResult({
|
|
37855
|
+
ok: false,
|
|
37856
|
+
reason: "error",
|
|
37857
|
+
emoji: emoji3,
|
|
37858
|
+
hint: "Reaction failed. Do not retry."
|
|
37859
|
+
});
|
|
37860
|
+
}
|
|
37861
|
+
return jsonResult({
|
|
37862
|
+
ok: true,
|
|
37863
|
+
chatId: String(chatId),
|
|
37864
|
+
messageId: String(messageId),
|
|
37865
|
+
emoji: emoji3,
|
|
37866
|
+
remove: false,
|
|
37867
|
+
alreadyPresent: true
|
|
37868
|
+
});
|
|
37585
37869
|
}
|
|
37586
37870
|
}
|
|
37587
37871
|
return jsonResult({
|
|
@@ -37755,6 +38039,7 @@ var inlineMessageActions = {
|
|
|
37755
38039
|
fn: async (client) => {
|
|
37756
38040
|
const query = readStringParam(params, "query") ?? readStringParam(params, "q") ?? undefined;
|
|
37757
38041
|
const limit = Math.max(1, Math.min(200, readNumberParam(params, "limit", { integer: true }) ?? 50));
|
|
38042
|
+
const scope = (readStringParam(params, "scope") ?? readStringParam(params, "kind") ?? "all").toLowerCase();
|
|
37758
38043
|
const result = await client.invokeRaw(Method.GET_CHATS, {
|
|
37759
38044
|
oneofKind: "getChats",
|
|
37760
38045
|
getChats: {}
|
|
@@ -37764,23 +38049,26 @@ var inlineMessageActions = {
|
|
|
37764
38049
|
}
|
|
37765
38050
|
const dialogByChatId = buildDialogMap(result.getChats.dialogs ?? []);
|
|
37766
38051
|
const usersById = buildUserMap2(result.getChats.users ?? []);
|
|
37767
|
-
const
|
|
37768
|
-
const
|
|
37769
|
-
const
|
|
37770
|
-
|
|
37771
|
-
|
|
37772
|
-
|
|
37773
|
-
|
|
37774
|
-
|
|
37775
|
-
|
|
37776
|
-
`)
|
|
37777
|
-
return haystack.includes(normalizedQuery);
|
|
37778
|
-
}) : entries;
|
|
38052
|
+
const chats = (result.getChats.chats ?? []).map((chat) => mapChatEntry({ chat, dialogByChatId, usersById }));
|
|
38053
|
+
const groups = chats.filter((entry) => entry.peer?.kind !== "user");
|
|
38054
|
+
const peers = (result.getChats.users ?? []).map((user) => mapUserPeerEntry(user));
|
|
38055
|
+
const normalizedQuery = normalizeInlineListQuery(query);
|
|
38056
|
+
const filteredChats = chats.filter((entry) => matchesInlineListQuery([entry.id, entry.target, entry.title, entry.peer?.kind === "user" ? entry.peer.username ?? "" : "", entry.peer?.kind === "user" ? entry.peer.name ?? "" : ""].join(`
|
|
38057
|
+
`), normalizedQuery));
|
|
38058
|
+
const filteredGroups = groups.filter((entry) => matchesInlineListQuery([entry.id, entry.target, entry.title].join(`
|
|
38059
|
+
`), normalizedQuery));
|
|
38060
|
+
const filteredPeers = peers.filter((entry) => matchesInlineListQuery([entry.id, entry.target, entry.username ?? "", entry.name ?? ""].join(`
|
|
38061
|
+
`), normalizedQuery));
|
|
37779
38062
|
return jsonResult(toJsonSafe({
|
|
37780
38063
|
ok: true,
|
|
38064
|
+
scope,
|
|
37781
38065
|
query: query ?? null,
|
|
37782
|
-
count:
|
|
37783
|
-
|
|
38066
|
+
count: filteredChats.length,
|
|
38067
|
+
groupsCount: filteredGroups.length,
|
|
38068
|
+
peersCount: filteredPeers.length,
|
|
38069
|
+
chats: scope === "groups" || scope === "group" || scope === "channels" || scope === "channel" ? [] : scope === "peers" || scope === "peer" || scope === "members" || scope === "member" || scope === "users" || scope === "user" ? [] : filteredChats.slice(0, limit),
|
|
38070
|
+
groups: scope === "peers" || scope === "peer" || scope === "members" || scope === "member" || scope === "users" || scope === "user" ? [] : filteredGroups.slice(0, limit),
|
|
38071
|
+
peers: scope === "groups" || scope === "group" || scope === "channels" || scope === "channel" ? [] : filteredPeers.slice(0, limit)
|
|
37784
38072
|
}));
|
|
37785
38073
|
}
|
|
37786
38074
|
});
|
|
@@ -38204,6 +38492,239 @@ var inlineMessageActions = {
|
|
|
38204
38492
|
};
|
|
38205
38493
|
var inlineSupportedActions = listAllActions();
|
|
38206
38494
|
|
|
38495
|
+
// src/inline/setup-core.ts
|
|
38496
|
+
import { createEnvPatchedAccountSetupAdapter } from "openclaw/plugin-sdk/setup";
|
|
38497
|
+
var channel = "inline";
|
|
38498
|
+
var INLINE_TOKEN_HELP_LINES = [
|
|
38499
|
+
"1) Open Inline and generate a bot token for your workspace/account",
|
|
38500
|
+
"2) Copy the token",
|
|
38501
|
+
"3) Paste it here, or set INLINE_TOKEN in your environment",
|
|
38502
|
+
"Docs: https://inline.chat/docs/openclaw",
|
|
38503
|
+
"Website: https://openclaw.ai"
|
|
38504
|
+
];
|
|
38505
|
+
var inlineSetupAdapter = createEnvPatchedAccountSetupAdapter({
|
|
38506
|
+
channelKey: channel,
|
|
38507
|
+
defaultAccountOnlyEnvError: "INLINE_TOKEN can only be used for the default account.",
|
|
38508
|
+
missingCredentialError: "Inline requires token or --token-file (or --use-env).",
|
|
38509
|
+
hasCredentials: (input) => Boolean(input.token || input.tokenFile),
|
|
38510
|
+
buildPatch: (input) => input.tokenFile ? { tokenFile: input.tokenFile } : input.token ? { token: input.token } : {}
|
|
38511
|
+
});
|
|
38512
|
+
|
|
38513
|
+
// src/inline/setup-surface.ts
|
|
38514
|
+
import {
|
|
38515
|
+
DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID2,
|
|
38516
|
+
setSetupChannelEnabled
|
|
38517
|
+
} from "openclaw/plugin-sdk/setup";
|
|
38518
|
+
var channel2 = "inline";
|
|
38519
|
+
var inlineSetupWizard = {
|
|
38520
|
+
channel: channel2,
|
|
38521
|
+
status: {
|
|
38522
|
+
configuredLabel: "configured",
|
|
38523
|
+
unconfiguredLabel: "needs token",
|
|
38524
|
+
configuredHint: "configured",
|
|
38525
|
+
unconfiguredHint: "recommended",
|
|
38526
|
+
configuredScore: 1,
|
|
38527
|
+
unconfiguredScore: 10,
|
|
38528
|
+
resolveConfigured: ({ cfg }) => listInlineAccountIds(cfg).some((accountId) => resolveInlineAccount({ cfg, accountId }).configured)
|
|
38529
|
+
},
|
|
38530
|
+
credentials: [
|
|
38531
|
+
{
|
|
38532
|
+
inputKey: "token",
|
|
38533
|
+
providerHint: channel2,
|
|
38534
|
+
credentialLabel: "Inline token",
|
|
38535
|
+
preferredEnvVar: "INLINE_TOKEN",
|
|
38536
|
+
helpTitle: "Inline token",
|
|
38537
|
+
helpLines: INLINE_TOKEN_HELP_LINES,
|
|
38538
|
+
envPrompt: "INLINE_TOKEN detected. Use env var?",
|
|
38539
|
+
keepPrompt: "Inline token already configured. Keep it?",
|
|
38540
|
+
inputPrompt: "Enter Inline token",
|
|
38541
|
+
allowEnv: ({ accountId }) => accountId === DEFAULT_ACCOUNT_ID2,
|
|
38542
|
+
inspect: ({ cfg, accountId }) => {
|
|
38543
|
+
const resolved = resolveInlineAccount({ cfg, accountId });
|
|
38544
|
+
const hasConfiguredValue = Boolean((resolved.config.token ?? "").trim() || (resolved.config.tokenFile ?? "").trim());
|
|
38545
|
+
const resolvedValue = resolved.token?.trim();
|
|
38546
|
+
const envValue = accountId === DEFAULT_ACCOUNT_ID2 ? process.env.INLINE_TOKEN?.trim() : undefined;
|
|
38547
|
+
return {
|
|
38548
|
+
accountConfigured: resolved.configured || hasConfiguredValue,
|
|
38549
|
+
hasConfiguredValue,
|
|
38550
|
+
...resolvedValue ? { resolvedValue } : {},
|
|
38551
|
+
...envValue ? { envValue } : {}
|
|
38552
|
+
};
|
|
38553
|
+
}
|
|
38554
|
+
}
|
|
38555
|
+
],
|
|
38556
|
+
disable: (cfg) => setSetupChannelEnabled(cfg, channel2, false)
|
|
38557
|
+
};
|
|
38558
|
+
|
|
38559
|
+
// src/inline/probe.ts
|
|
38560
|
+
function formatInlineProbeUserName(user) {
|
|
38561
|
+
const explicit = [user.firstName?.trim(), user.lastName?.trim()].filter(Boolean).join(" ");
|
|
38562
|
+
if (explicit)
|
|
38563
|
+
return explicit;
|
|
38564
|
+
const username = user.username?.trim();
|
|
38565
|
+
if (username)
|
|
38566
|
+
return `@${username}`;
|
|
38567
|
+
return "Unknown";
|
|
38568
|
+
}
|
|
38569
|
+
async function withTimeout(promise2, timeoutMs) {
|
|
38570
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
|
|
38571
|
+
return await promise2;
|
|
38572
|
+
}
|
|
38573
|
+
return await new Promise((resolve, reject) => {
|
|
38574
|
+
const timer = setTimeout(() => {
|
|
38575
|
+
reject(new Error(`probe timeout after ${Math.trunc(timeoutMs)}ms`));
|
|
38576
|
+
}, timeoutMs);
|
|
38577
|
+
promise2.then((value) => {
|
|
38578
|
+
clearTimeout(timer);
|
|
38579
|
+
resolve(value);
|
|
38580
|
+
}, (error48) => {
|
|
38581
|
+
clearTimeout(timer);
|
|
38582
|
+
reject(error48);
|
|
38583
|
+
});
|
|
38584
|
+
});
|
|
38585
|
+
}
|
|
38586
|
+
async function probeInlineAccountDirect(account) {
|
|
38587
|
+
if (!account.baseUrl?.trim()) {
|
|
38588
|
+
throw new Error("missing baseUrl");
|
|
38589
|
+
}
|
|
38590
|
+
const token = await resolveInlineToken(account);
|
|
38591
|
+
const client = new InlineSdkClient({
|
|
38592
|
+
baseUrl: account.baseUrl,
|
|
38593
|
+
token
|
|
38594
|
+
});
|
|
38595
|
+
await client.connect();
|
|
38596
|
+
try {
|
|
38597
|
+
const result = await client.invokeRaw(Method.GET_ME, {
|
|
38598
|
+
oneofKind: "getMe",
|
|
38599
|
+
getMe: {}
|
|
38600
|
+
});
|
|
38601
|
+
if (result.oneofKind !== "getMe") {
|
|
38602
|
+
throw new Error(`expected getMe result, got ${String(result.oneofKind)}`);
|
|
38603
|
+
}
|
|
38604
|
+
if (!result.getMe.user) {
|
|
38605
|
+
throw new Error("missing current user from getMe");
|
|
38606
|
+
}
|
|
38607
|
+
const user = result.getMe.user;
|
|
38608
|
+
return {
|
|
38609
|
+
ok: true,
|
|
38610
|
+
accountId: account.accountId,
|
|
38611
|
+
baseUrl: account.baseUrl,
|
|
38612
|
+
user: {
|
|
38613
|
+
id: String(user.id),
|
|
38614
|
+
username: user.username?.trim() || null,
|
|
38615
|
+
name: formatInlineProbeUserName(user),
|
|
38616
|
+
bot: user.bot ?? false
|
|
38617
|
+
}
|
|
38618
|
+
};
|
|
38619
|
+
} finally {
|
|
38620
|
+
await client.close().catch(() => {});
|
|
38621
|
+
}
|
|
38622
|
+
}
|
|
38623
|
+
function toErrorText(error48) {
|
|
38624
|
+
if (error48 instanceof Error && error48.message.trim()) {
|
|
38625
|
+
return error48.message;
|
|
38626
|
+
}
|
|
38627
|
+
return String(error48);
|
|
38628
|
+
}
|
|
38629
|
+
async function probeInlineAccount(account, timeoutMs) {
|
|
38630
|
+
if (!account.configured) {
|
|
38631
|
+
return {
|
|
38632
|
+
ok: false,
|
|
38633
|
+
accountId: account.accountId,
|
|
38634
|
+
baseUrl: account.baseUrl,
|
|
38635
|
+
error: "missing token"
|
|
38636
|
+
};
|
|
38637
|
+
}
|
|
38638
|
+
try {
|
|
38639
|
+
return await withTimeout(probeInlineAccountDirect(account), timeoutMs);
|
|
38640
|
+
} catch (error48) {
|
|
38641
|
+
return {
|
|
38642
|
+
ok: false,
|
|
38643
|
+
accountId: account.accountId,
|
|
38644
|
+
baseUrl: account.baseUrl,
|
|
38645
|
+
error: toErrorText(error48)
|
|
38646
|
+
};
|
|
38647
|
+
}
|
|
38648
|
+
}
|
|
38649
|
+
|
|
38650
|
+
// src/inline/status-issues.ts
|
|
38651
|
+
import { asString, isRecord as isRecord5 } from "openclaw/plugin-sdk/status-helpers";
|
|
38652
|
+
function readInlineProbeSummary(value) {
|
|
38653
|
+
if (!isRecord5(value)) {
|
|
38654
|
+
return {};
|
|
38655
|
+
}
|
|
38656
|
+
const summary = {};
|
|
38657
|
+
if (typeof value.ok === "boolean") {
|
|
38658
|
+
summary.ok = value.ok;
|
|
38659
|
+
}
|
|
38660
|
+
const error48 = asString(value.error);
|
|
38661
|
+
if (error48) {
|
|
38662
|
+
summary.error = error48;
|
|
38663
|
+
}
|
|
38664
|
+
return summary;
|
|
38665
|
+
}
|
|
38666
|
+
function looksLikeAuthError(text) {
|
|
38667
|
+
return /(401|403|unauth|forbidden|invalid token|token invalid|unauthorized)/i.test(text);
|
|
38668
|
+
}
|
|
38669
|
+
function collectInlineStatusIssues(accounts) {
|
|
38670
|
+
const issues = [];
|
|
38671
|
+
for (const entry of accounts) {
|
|
38672
|
+
if (!isRecord5(entry)) {
|
|
38673
|
+
continue;
|
|
38674
|
+
}
|
|
38675
|
+
const accountId = asString(entry.accountId);
|
|
38676
|
+
if (!accountId) {
|
|
38677
|
+
continue;
|
|
38678
|
+
}
|
|
38679
|
+
const enabled = entry.enabled !== false;
|
|
38680
|
+
if (!enabled) {
|
|
38681
|
+
continue;
|
|
38682
|
+
}
|
|
38683
|
+
const configured = entry.configured !== false;
|
|
38684
|
+
if (!configured) {
|
|
38685
|
+
issues.push({
|
|
38686
|
+
channel: "inline",
|
|
38687
|
+
accountId,
|
|
38688
|
+
kind: "config",
|
|
38689
|
+
message: "Inline account is enabled but missing token/tokenFile.",
|
|
38690
|
+
fix: "Set channels.inline.token (or tokenFile), then restart the gateway."
|
|
38691
|
+
});
|
|
38692
|
+
continue;
|
|
38693
|
+
}
|
|
38694
|
+
const baseUrl = asString(entry.baseUrl);
|
|
38695
|
+
if (!baseUrl || baseUrl === "[missing]") {
|
|
38696
|
+
issues.push({
|
|
38697
|
+
channel: "inline",
|
|
38698
|
+
accountId,
|
|
38699
|
+
kind: "config",
|
|
38700
|
+
message: "Inline account is configured but baseUrl is missing.",
|
|
38701
|
+
fix: 'Set channels.inline.baseUrl (for example "https://api.inline.chat"), then restart the gateway.'
|
|
38702
|
+
});
|
|
38703
|
+
}
|
|
38704
|
+
const lastError = asString(entry.lastError);
|
|
38705
|
+
if (lastError) {
|
|
38706
|
+
issues.push({
|
|
38707
|
+
channel: "inline",
|
|
38708
|
+
accountId,
|
|
38709
|
+
kind: looksLikeAuthError(lastError) ? "auth" : "runtime",
|
|
38710
|
+
message: `Inline runtime error: ${lastError}`,
|
|
38711
|
+
fix: "Verify token/baseUrl and restart the gateway."
|
|
38712
|
+
});
|
|
38713
|
+
}
|
|
38714
|
+
const probe = readInlineProbeSummary(entry.probe);
|
|
38715
|
+
if (probe.ok === false && probe.error) {
|
|
38716
|
+
issues.push({
|
|
38717
|
+
channel: "inline",
|
|
38718
|
+
accountId,
|
|
38719
|
+
kind: looksLikeAuthError(probe.error) ? "auth" : "runtime",
|
|
38720
|
+
message: `Inline probe failed: ${probe.error}`,
|
|
38721
|
+
fix: "Verify token/baseUrl connectivity, then re-run channel status."
|
|
38722
|
+
});
|
|
38723
|
+
}
|
|
38724
|
+
}
|
|
38725
|
+
return issues;
|
|
38726
|
+
}
|
|
38727
|
+
|
|
38207
38728
|
// src/inline/channel.ts
|
|
38208
38729
|
var activeMonitors = new Map;
|
|
38209
38730
|
var meta3 = {
|
|
@@ -38242,6 +38763,82 @@ function parseInlineId2(raw) {
|
|
|
38242
38763
|
}
|
|
38243
38764
|
return;
|
|
38244
38765
|
}
|
|
38766
|
+
function asRecord(value) {
|
|
38767
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
38768
|
+
return null;
|
|
38769
|
+
}
|
|
38770
|
+
return value;
|
|
38771
|
+
}
|
|
38772
|
+
function clearInlineCredentialFields(record2) {
|
|
38773
|
+
let changed = false;
|
|
38774
|
+
let cleared = false;
|
|
38775
|
+
for (const key of ["token", "tokenFile"]) {
|
|
38776
|
+
if (!Object.hasOwn(record2, key)) {
|
|
38777
|
+
continue;
|
|
38778
|
+
}
|
|
38779
|
+
const raw = record2[key];
|
|
38780
|
+
if (typeof raw === "string" && raw.trim()) {
|
|
38781
|
+
cleared = true;
|
|
38782
|
+
}
|
|
38783
|
+
delete record2[key];
|
|
38784
|
+
changed = true;
|
|
38785
|
+
}
|
|
38786
|
+
return { changed, cleared };
|
|
38787
|
+
}
|
|
38788
|
+
function clearInlineAccountCredentials(params) {
|
|
38789
|
+
const channels = asRecord(params.cfg.channels);
|
|
38790
|
+
const inline = asRecord(channels?.inline);
|
|
38791
|
+
if (!channels || !inline) {
|
|
38792
|
+
return { cfg: params.cfg, changed: false, cleared: false };
|
|
38793
|
+
}
|
|
38794
|
+
const nextInline = { ...inline };
|
|
38795
|
+
let changed = false;
|
|
38796
|
+
let cleared = false;
|
|
38797
|
+
if (params.accountId === DEFAULT_ACCOUNT_ID) {
|
|
38798
|
+
const base = clearInlineCredentialFields(nextInline);
|
|
38799
|
+
changed = changed || base.changed;
|
|
38800
|
+
cleared = cleared || base.cleared;
|
|
38801
|
+
}
|
|
38802
|
+
const accounts = asRecord(nextInline.accounts);
|
|
38803
|
+
if (accounts) {
|
|
38804
|
+
const nextAccounts = { ...accounts };
|
|
38805
|
+
const accountEntry = asRecord(nextAccounts[params.accountId]);
|
|
38806
|
+
if (accountEntry) {
|
|
38807
|
+
const nextAccountEntry = { ...accountEntry };
|
|
38808
|
+
const entry = clearInlineCredentialFields(nextAccountEntry);
|
|
38809
|
+
if (entry.changed) {
|
|
38810
|
+
changed = true;
|
|
38811
|
+
cleared = cleared || entry.cleared;
|
|
38812
|
+
if (Object.keys(nextAccountEntry).length > 0) {
|
|
38813
|
+
nextAccounts[params.accountId] = nextAccountEntry;
|
|
38814
|
+
} else {
|
|
38815
|
+
delete nextAccounts[params.accountId];
|
|
38816
|
+
}
|
|
38817
|
+
}
|
|
38818
|
+
}
|
|
38819
|
+
if (changed) {
|
|
38820
|
+
if (Object.keys(nextAccounts).length > 0) {
|
|
38821
|
+
nextInline.accounts = nextAccounts;
|
|
38822
|
+
} else {
|
|
38823
|
+
delete nextInline.accounts;
|
|
38824
|
+
}
|
|
38825
|
+
}
|
|
38826
|
+
}
|
|
38827
|
+
if (!changed) {
|
|
38828
|
+
return { cfg: params.cfg, changed: false, cleared: false };
|
|
38829
|
+
}
|
|
38830
|
+
return {
|
|
38831
|
+
cfg: {
|
|
38832
|
+
...params.cfg,
|
|
38833
|
+
channels: {
|
|
38834
|
+
...channels,
|
|
38835
|
+
inline: nextInline
|
|
38836
|
+
}
|
|
38837
|
+
},
|
|
38838
|
+
changed: true,
|
|
38839
|
+
cleared
|
|
38840
|
+
};
|
|
38841
|
+
}
|
|
38245
38842
|
function parseInlineOutboundTarget(params) {
|
|
38246
38843
|
let normalizedTarget = params.raw.trim();
|
|
38247
38844
|
const hadInlinePrefix = /^inline:/i.test(normalizedTarget);
|
|
@@ -38277,6 +38874,46 @@ function parseInlineOutboundTarget(params) {
|
|
|
38277
38874
|
raw: params.raw
|
|
38278
38875
|
};
|
|
38279
38876
|
}
|
|
38877
|
+
function parseInlineExplicitTarget(raw) {
|
|
38878
|
+
const parsed = parseInlineOutboundTarget({
|
|
38879
|
+
raw,
|
|
38880
|
+
context: "sendText"
|
|
38881
|
+
});
|
|
38882
|
+
if (parsed.kind === "user") {
|
|
38883
|
+
return { to: `user:${parsed.normalizedNumeric}`, chatType: "direct" };
|
|
38884
|
+
}
|
|
38885
|
+
return { to: `chat:${parsed.normalizedNumeric}`, chatType: "group" };
|
|
38886
|
+
}
|
|
38887
|
+
function formatInlineTargetDisplay(params) {
|
|
38888
|
+
const explicit = params.display?.trim();
|
|
38889
|
+
if (explicit) {
|
|
38890
|
+
return explicit;
|
|
38891
|
+
}
|
|
38892
|
+
const parsed = parseInlineExplicitTarget(params.target.trim());
|
|
38893
|
+
if (!parsed) {
|
|
38894
|
+
return params.target.trim();
|
|
38895
|
+
}
|
|
38896
|
+
if (parsed.chatType === "direct" || params.kind === "user") {
|
|
38897
|
+
return parsed.to;
|
|
38898
|
+
}
|
|
38899
|
+
return parsed.to;
|
|
38900
|
+
}
|
|
38901
|
+
function normalizeInlineConversationId(raw) {
|
|
38902
|
+
const trimmed = raw.trim();
|
|
38903
|
+
if (!trimmed)
|
|
38904
|
+
return null;
|
|
38905
|
+
const withoutProvider = trimmed.replace(/^inline:/i, "").trim();
|
|
38906
|
+
if (!withoutProvider)
|
|
38907
|
+
return null;
|
|
38908
|
+
try {
|
|
38909
|
+
const parsed = parseInlineExplicitTarget(withoutProvider);
|
|
38910
|
+
if (!parsed)
|
|
38911
|
+
return null;
|
|
38912
|
+
return `inline:${parsed.to}`;
|
|
38913
|
+
} catch {
|
|
38914
|
+
return null;
|
|
38915
|
+
}
|
|
38916
|
+
}
|
|
38280
38917
|
async function listInlineTargetIds(client) {
|
|
38281
38918
|
const result = await client.invokeRaw(Method.GET_CHATS, {
|
|
38282
38919
|
oneofKind: "getChats",
|
|
@@ -38350,6 +38987,31 @@ function buildInlineDisplayName(params) {
|
|
|
38350
38987
|
return `@${username}`;
|
|
38351
38988
|
return "Unknown";
|
|
38352
38989
|
}
|
|
38990
|
+
function formatInlineCapabilitiesProbeLines(probe) {
|
|
38991
|
+
const details = probe;
|
|
38992
|
+
if (!details) {
|
|
38993
|
+
return [];
|
|
38994
|
+
}
|
|
38995
|
+
if (!details.ok) {
|
|
38996
|
+
if (details.error?.trim()) {
|
|
38997
|
+
return [{ text: `Probe failed: ${details.error}`, tone: "error" }];
|
|
38998
|
+
}
|
|
38999
|
+
return [{ text: "Probe failed", tone: "error" }];
|
|
39000
|
+
}
|
|
39001
|
+
const lines = [];
|
|
39002
|
+
if (details.user) {
|
|
39003
|
+
const username = details.user.username ? ` @${details.user.username}` : "";
|
|
39004
|
+
const botLabel = details.user.bot ? " [bot]" : "";
|
|
39005
|
+
lines.push({
|
|
39006
|
+
text: `Identity: ${details.user.name}${username} (${details.user.id})${botLabel}`,
|
|
39007
|
+
tone: "success"
|
|
39008
|
+
});
|
|
39009
|
+
}
|
|
39010
|
+
if (details.baseUrl) {
|
|
39011
|
+
lines.push({ text: `Base URL: ${details.baseUrl}` });
|
|
39012
|
+
}
|
|
39013
|
+
return lines;
|
|
39014
|
+
}
|
|
38353
39015
|
function toInlineUserDirectoryEntry(user) {
|
|
38354
39016
|
return {
|
|
38355
39017
|
kind: "user",
|
|
@@ -38653,10 +39315,25 @@ var inlineChannelPlugin = {
|
|
|
38653
39315
|
},
|
|
38654
39316
|
reload: { configPrefixes: ["channels.inline"] },
|
|
38655
39317
|
configSchema: buildChannelConfigSchema(InlineConfigSchema),
|
|
39318
|
+
setup: inlineSetupAdapter,
|
|
39319
|
+
setupWizard: inlineSetupWizard,
|
|
38656
39320
|
config: {
|
|
38657
39321
|
listAccountIds: (cfg) => listInlineAccountIds(cfg),
|
|
38658
39322
|
resolveAccount: (cfg, accountId) => resolveInlineAccount({ cfg, accountId: accountId ?? null }),
|
|
38659
39323
|
defaultAccountId: (cfg) => resolveDefaultInlineAccountId(cfg),
|
|
39324
|
+
setAccountEnabled: ({ cfg, accountId, enabled }) => setAccountEnabledInConfigSection({
|
|
39325
|
+
cfg,
|
|
39326
|
+
sectionKey: "inline",
|
|
39327
|
+
accountId,
|
|
39328
|
+
enabled,
|
|
39329
|
+
allowTopLevel: true
|
|
39330
|
+
}),
|
|
39331
|
+
deleteAccount: ({ cfg, accountId }) => deleteAccountFromConfigSection({
|
|
39332
|
+
cfg,
|
|
39333
|
+
sectionKey: "inline",
|
|
39334
|
+
accountId,
|
|
39335
|
+
clearBaseFields: ["token", "tokenFile", "name", "enabled"]
|
|
39336
|
+
}),
|
|
38660
39337
|
isConfigured: (account) => account.configured,
|
|
38661
39338
|
describeAccount: (account) => ({
|
|
38662
39339
|
accountId: account.accountId,
|
|
@@ -38707,6 +39384,47 @@ var inlineChannelPlugin = {
|
|
|
38707
39384
|
];
|
|
38708
39385
|
}
|
|
38709
39386
|
},
|
|
39387
|
+
allowlist: buildDmGroupAccountAllowlistAdapter({
|
|
39388
|
+
channelId: "inline",
|
|
39389
|
+
resolveAccount: ({ cfg, accountId }) => resolveInlineAccount({ cfg, accountId: accountId ?? null }),
|
|
39390
|
+
normalize: ({ values }) => values.map((entry) => String(entry).trim()).filter(Boolean).map((entry) => normalizeInlineAllowEntry(entry)),
|
|
39391
|
+
resolveDmAllowFrom: (account) => account.config.allowFrom ?? [],
|
|
39392
|
+
resolveGroupAllowFrom: (account) => account.config.groupAllowFrom ?? [],
|
|
39393
|
+
resolveDmPolicy: (account) => account.config.dmPolicy,
|
|
39394
|
+
resolveGroupPolicy: (account) => account.config.groupPolicy
|
|
39395
|
+
}),
|
|
39396
|
+
bindings: {
|
|
39397
|
+
compileConfiguredBinding: ({ conversationId }) => {
|
|
39398
|
+
const normalized = normalizeInlineConversationId(conversationId);
|
|
39399
|
+
if (!normalized) {
|
|
39400
|
+
return null;
|
|
39401
|
+
}
|
|
39402
|
+
return { conversationId: normalized };
|
|
39403
|
+
},
|
|
39404
|
+
matchInboundConversation: ({ compiledBinding, conversationId, parentConversationId }) => {
|
|
39405
|
+
const expected = normalizeInlineConversationId(compiledBinding.conversationId);
|
|
39406
|
+
if (!expected) {
|
|
39407
|
+
return null;
|
|
39408
|
+
}
|
|
39409
|
+
const incoming = normalizeInlineConversationId(conversationId);
|
|
39410
|
+
const parent = parentConversationId ? normalizeInlineConversationId(parentConversationId) : null;
|
|
39411
|
+
if (incoming && incoming === expected) {
|
|
39412
|
+
return {
|
|
39413
|
+
conversationId: incoming,
|
|
39414
|
+
...parent ? { parentConversationId: parent } : {},
|
|
39415
|
+
matchPriority: 2
|
|
39416
|
+
};
|
|
39417
|
+
}
|
|
39418
|
+
if (incoming && parent && parent === expected) {
|
|
39419
|
+
return {
|
|
39420
|
+
conversationId: incoming,
|
|
39421
|
+
parentConversationId: parent,
|
|
39422
|
+
matchPriority: 1
|
|
39423
|
+
};
|
|
39424
|
+
}
|
|
39425
|
+
return null;
|
|
39426
|
+
}
|
|
39427
|
+
},
|
|
38710
39428
|
groups: {
|
|
38711
39429
|
resolveRequireMention: ({ cfg, accountId, groupId }) => {
|
|
38712
39430
|
const resolved = resolveInlineAccount({ cfg, accountId: accountId ?? null });
|
|
@@ -38759,7 +39477,9 @@ var inlineChannelPlugin = {
|
|
|
38759
39477
|
messageToolHints: ({ cfg, accountId }) => [
|
|
38760
39478
|
"- Inline targeting: omit `target` to reply in the current chat.",
|
|
38761
39479
|
"- Inline explicit targets: `chat:<chatId>` for chats and `user:<userId>` for direct users. Prefer `user:` for DM user targets.",
|
|
38762
|
-
"- Inline
|
|
39480
|
+
"- Inline discovery: use `channel-list` to discover available chats and users. Use `scope: groups|peers|all` when helpful, and reuse returned `target` values.",
|
|
39481
|
+
"- Inline reactions: pass `messageId` for `react` when you have it; on inbound turns, the current inbound message id can be used as fallback.",
|
|
39482
|
+
"- Inline history tools: `read` and `search` return media-aware message payloads (`media`, `attachments`, `attachmentUrls`) so image-only history remains discoverable. `search` is chat-scoped; run it per chat.",
|
|
38763
39483
|
"- Inline special tools: use `inline_nudge` to send a nudge, and `inline_forward` to forward message ids between chats or users.",
|
|
38764
39484
|
...isInlineReplyThreadsEnabled({ cfg, accountId: accountId ?? null }) ? [
|
|
38765
39485
|
"- Inline reply threads are enabled: use `thread-reply` to send into a real reply thread, with `threadId` set to the reply-thread chat id."
|
|
@@ -38768,6 +39488,29 @@ var inlineChannelPlugin = {
|
|
|
38768
39488
|
},
|
|
38769
39489
|
messaging: {
|
|
38770
39490
|
normalizeTarget: normalizeInlineTarget,
|
|
39491
|
+
parseExplicitTarget: ({ raw }) => {
|
|
39492
|
+
try {
|
|
39493
|
+
const parsed = parseInlineExplicitTarget(raw);
|
|
39494
|
+
if (!parsed)
|
|
39495
|
+
return null;
|
|
39496
|
+
return { to: parsed.to, chatType: parsed.chatType };
|
|
39497
|
+
} catch {
|
|
39498
|
+
return null;
|
|
39499
|
+
}
|
|
39500
|
+
},
|
|
39501
|
+
inferTargetChatType: ({ to }) => {
|
|
39502
|
+
try {
|
|
39503
|
+
const parsed = parseInlineExplicitTarget(to);
|
|
39504
|
+
return parsed?.chatType;
|
|
39505
|
+
} catch {
|
|
39506
|
+
return;
|
|
39507
|
+
}
|
|
39508
|
+
},
|
|
39509
|
+
formatTargetDisplay: ({ target, display, kind }) => formatInlineTargetDisplay({
|
|
39510
|
+
target,
|
|
39511
|
+
...display !== undefined ? { display } : {},
|
|
39512
|
+
...kind !== undefined ? { kind } : {}
|
|
39513
|
+
}),
|
|
38771
39514
|
targetResolver: {
|
|
38772
39515
|
looksLikeId: looksLikeInlineTargetId,
|
|
38773
39516
|
hint: "<chatId | chat:<chatId> | user:<userId>>"
|
|
@@ -38985,18 +39728,14 @@ var inlineChannelPlugin = {
|
|
|
38985
39728
|
running: false,
|
|
38986
39729
|
lastStartAt: null,
|
|
38987
39730
|
lastStopAt: null,
|
|
38988
|
-
lastError: null
|
|
39731
|
+
lastError: null,
|
|
39732
|
+
lastProbeAt: null
|
|
38989
39733
|
},
|
|
38990
|
-
|
|
38991
|
-
|
|
38992
|
-
|
|
38993
|
-
|
|
38994
|
-
|
|
38995
|
-
lastError: snapshot.lastError ?? null,
|
|
38996
|
-
lastInboundAt: snapshot.lastInboundAt ?? null,
|
|
38997
|
-
lastOutboundAt: snapshot.lastOutboundAt ?? null
|
|
38998
|
-
}),
|
|
38999
|
-
buildAccountSnapshot: ({ account, runtime: runtime2 }) => ({
|
|
39734
|
+
collectStatusIssues: collectInlineStatusIssues,
|
|
39735
|
+
buildChannelSummary: ({ snapshot }) => buildTokenChannelStatusSummary(snapshot),
|
|
39736
|
+
probeAccount: async ({ account, timeoutMs }) => await probeInlineAccount(account, timeoutMs),
|
|
39737
|
+
formatCapabilitiesProbe: ({ probe }) => formatInlineCapabilitiesProbeLines(probe),
|
|
39738
|
+
buildAccountSnapshot: ({ account, runtime: runtime2, probe }) => ({
|
|
39000
39739
|
accountId: account.accountId,
|
|
39001
39740
|
name: account.name,
|
|
39002
39741
|
enabled: account.enabled,
|
|
@@ -39008,7 +39747,9 @@ var inlineChannelPlugin = {
|
|
|
39008
39747
|
lastStopAt: runtime2?.lastStopAt ?? null,
|
|
39009
39748
|
lastError: runtime2?.lastError ?? null,
|
|
39010
39749
|
lastInboundAt: runtime2?.lastInboundAt ?? null,
|
|
39011
|
-
lastOutboundAt: runtime2?.lastOutboundAt ?? null
|
|
39750
|
+
lastOutboundAt: runtime2?.lastOutboundAt ?? null,
|
|
39751
|
+
lastProbeAt: runtime2?.lastProbeAt ?? null,
|
|
39752
|
+
...probe !== undefined ? { probe } : {}
|
|
39012
39753
|
})
|
|
39013
39754
|
},
|
|
39014
39755
|
gateway: {
|
|
@@ -39061,6 +39802,30 @@ var inlineChannelPlugin = {
|
|
|
39061
39802
|
running: false,
|
|
39062
39803
|
lastStopAt: Date.now()
|
|
39063
39804
|
});
|
|
39805
|
+
},
|
|
39806
|
+
logoutAccount: async ({ accountId, cfg }) => {
|
|
39807
|
+
const cleanup = clearInlineAccountCredentials({ cfg, accountId });
|
|
39808
|
+
if (cleanup.changed) {
|
|
39809
|
+
return {
|
|
39810
|
+
cleared: cleanup.cleared,
|
|
39811
|
+
loggedOut: cleanup.cleared,
|
|
39812
|
+
cfg: cleanup.cfg,
|
|
39813
|
+
message: cleanup.cleared ? "Inline credentials cleared from config. Restart gateway to apply." : "Inline credential fields removed from config."
|
|
39814
|
+
};
|
|
39815
|
+
}
|
|
39816
|
+
const envToken = process.env.INLINE_TOKEN?.trim() ?? "";
|
|
39817
|
+
if (accountId === DEFAULT_ACCOUNT_ID && envToken) {
|
|
39818
|
+
return {
|
|
39819
|
+
cleared: false,
|
|
39820
|
+
loggedOut: false,
|
|
39821
|
+
message: "No Inline credentials found in config. INLINE_TOKEN is set in env; unset it and restart gateway to fully log out."
|
|
39822
|
+
};
|
|
39823
|
+
}
|
|
39824
|
+
return {
|
|
39825
|
+
cleared: false,
|
|
39826
|
+
loggedOut: false,
|
|
39827
|
+
message: "No Inline credentials found in config for this account."
|
|
39828
|
+
};
|
|
39064
39829
|
}
|
|
39065
39830
|
}
|
|
39066
39831
|
};
|
|
@@ -40130,5 +40895,5 @@ export {
|
|
|
40130
40895
|
src_default as default
|
|
40131
40896
|
};
|
|
40132
40897
|
|
|
40133
|
-
//# debugId=
|
|
40898
|
+
//# debugId=CE0AB31A68AAA68C64756E2164756E21
|
|
40134
40899
|
//# sourceMappingURL=index.js.map
|