diff --git a/extensions/line/src/channel.ts b/extensions/line/src/channel.ts index 27a5b65354c..fd5b063cc11 100644 --- a/extensions/line/src/channel.ts +++ b/extensions/line/src/channel.ts @@ -8,6 +8,7 @@ import { lineChannelPluginCommon } from "./channel-shared.js"; import { lineGatewayAdapter } from "./gateway.js"; import { resolveLineGroupRequireMention } from "./group-policy.js"; import { lineOutboundAdapter } from "./outbound.js"; +import { getLineRuntime } from "./runtime.js"; import { pushMessageLine } from "./send.js"; import { lineSetupAdapter } from "./setup-core.js"; import { lineSetupWizard } from "./setup-surface.js"; @@ -158,11 +159,13 @@ export const linePlugin: ChannelPlugin = createChatChannelP message: "OpenClaw: your access has been approved.", normalizeAllowEntry: createPairingPrefixStripper(/^line:(?:user:)?/i), notify: async ({ cfg, id, message }) => { - const account = resolveLineAccount({ cfg }); + const account = (getLineRuntime().channel.line?.resolveLineAccount ?? resolveLineAccount)({ + cfg, + }); if (!account.channelAccessToken) { throw new Error("LINE channel access token not configured"); } - await pushMessageLine(id, message, { + await (getLineRuntime().channel.line?.pushMessageLine ?? pushMessageLine)(id, message, { accountId: account.accountId, channelAccessToken: account.channelAccessToken, }); diff --git a/extensions/line/src/gateway.ts b/extensions/line/src/gateway.ts index 43037f225fb..381fb92b51a 100644 --- a/extensions/line/src/gateway.ts +++ b/extensions/line/src/gateway.ts @@ -42,7 +42,7 @@ export const lineGatewayAdapter: NonNullable[ ctx.log?.info(`[${account.accountId}] starting LINE provider${lineBotLabel}`); - return await monitorLineProvider({ + return await (getLineRuntime().channel.line?.monitorLineProvider ?? monitorLineProvider)({ channelAccessToken: token, channelSecret: secret, accountId: account.accountId, diff --git a/extensions/line/src/outbound.ts b/extensions/line/src/outbound.ts index 517b7c751ab..85e01ab2ad5 100644 --- a/extensions/line/src/outbound.ts +++ b/extensions/line/src/outbound.ts @@ -88,18 +88,23 @@ export const lineOutboundAdapter: NonNullable sendPayload: async ({ to, payload, accountId, cfg }) => { const runtime = getLineRuntime(); const lineData = (payload.channelData?.line as LineChannelDataWithMedia | undefined) ?? {}; - const sendText = pushMessageLine; - const sendBatch = pushMessagesLine; - const sendFlex = pushFlexMessage; - const sendTemplate = pushTemplateMessage; - const sendLocation = pushLocationMessage; - const sendQuickReplies = pushTextMessageWithQuickReplies; - const buildTemplate = buildTemplateMessageFromPayload; + const lineRuntime = runtime.channel.line; + const sendText = lineRuntime?.pushMessageLine ?? pushMessageLine; + const sendBatch = lineRuntime?.pushMessagesLine ?? pushMessagesLine; + const sendFlex = lineRuntime?.pushFlexMessage ?? pushFlexMessage; + const sendTemplate = lineRuntime?.pushTemplateMessage ?? pushTemplateMessage; + const sendLocation = lineRuntime?.pushLocationMessage ?? pushLocationMessage; + const sendQuickReplies = + lineRuntime?.pushTextMessageWithQuickReplies ?? pushTextMessageWithQuickReplies; + const buildTemplate = + lineRuntime?.buildTemplateMessageFromPayload ?? buildTemplateMessageFromPayload; let lastResult: { messageId: string; chatId: string } | null = null; const quickReplies = lineData.quickReplies ?? []; const hasQuickReplies = quickReplies.length > 0; - const quickReply = hasQuickReplies ? createQuickReplyItems(quickReplies) : undefined; + const quickReply = hasQuickReplies + ? (lineRuntime?.createQuickReplyItems ?? createQuickReplyItems)(quickReplies) + : undefined; // LINE SDK expects Message[] but we build dynamically. const sendMessageBatch = async (messages: Array>) => { @@ -139,7 +144,7 @@ export const lineOutboundAdapter: NonNullable continue; } if (!useLineSpecificMedia) { - lastResult = await sendMessageLine(to, "", { + lastResult = await (lineRuntime?.sendMessageLine ?? sendMessageLine)(to, "", { verbose: false, mediaUrl: trimmed, cfg, @@ -153,7 +158,7 @@ export const lineOutboundAdapter: NonNullable durationMs: lineData.durationMs, trackingId: lineData.trackingId, }); - lastResult = await sendMessageLine(to, "", { + lastResult = await (lineRuntime?.sendMessageLine ?? sendMessageLine)(to, "", { verbose: false, mediaUrl: resolved.mediaUrl, mediaKind: resolved.mediaKind, diff --git a/extensions/line/src/runtime.ts b/extensions/line/src/runtime.ts index c468491424d..8be9699c136 100644 --- a/extensions/line/src/runtime.ts +++ b/extensions/line/src/runtime.ts @@ -1,9 +1,29 @@ import { createPluginRuntimeStore } from "openclaw/plugin-sdk/runtime-store"; import type { PluginRuntime } from "../api.js"; +type LineChannelRuntime = { + buildTemplateMessageFromPayload?: typeof import("./template-messages.js").buildTemplateMessageFromPayload; + createQuickReplyItems?: typeof import("./send.js").createQuickReplyItems; + monitorLineProvider?: typeof import("./monitor.js").monitorLineProvider; + pushFlexMessage?: typeof import("./send.js").pushFlexMessage; + pushLocationMessage?: typeof import("./send.js").pushLocationMessage; + pushMessageLine?: typeof import("./send.js").pushMessageLine; + pushMessagesLine?: typeof import("./send.js").pushMessagesLine; + pushTemplateMessage?: typeof import("./send.js").pushTemplateMessage; + pushTextMessageWithQuickReplies?: typeof import("./send.js").pushTextMessageWithQuickReplies; + resolveLineAccount?: typeof import("./accounts.js").resolveLineAccount; + sendMessageLine?: typeof import("./send.js").sendMessageLine; +}; + +export type LineRuntime = PluginRuntime & { + channel: PluginRuntime["channel"] & { + line?: LineChannelRuntime; + }; +}; + const { setRuntime: setLineRuntime, clearRuntime: clearLineRuntime, getRuntime: getLineRuntime, -} = createPluginRuntimeStore("LINE runtime not initialized - plugin not registered"); +} = createPluginRuntimeStore("LINE runtime not initialized - plugin not registered"); export { clearLineRuntime, getLineRuntime, setLineRuntime };