mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-22 22:52:03 +00:00
refactor(plugin-runtime): remove plugin-specific core seams
This commit is contained in:
@@ -29,17 +29,17 @@ describe("loadSiblingRuntimeModuleSync", () => {
|
||||
it("loads a sibling runtime module from the caller directory", () => {
|
||||
const root = createTempDir();
|
||||
const moduleUrl = pathToFileURL(
|
||||
path.join(root, "src", "plugins", "runtime", "runtime-line.js"),
|
||||
path.join(root, "src", "plugins", "runtime", "runtime.js"),
|
||||
).href;
|
||||
|
||||
writeFile(
|
||||
path.join(root, "src", "plugins", "runtime", "runtime-line.contract.js"),
|
||||
path.join(root, "src", "plugins", "runtime", "runtime.contract.js"),
|
||||
"module.exports = { runtimeLine: { source: 'sibling' } };",
|
||||
);
|
||||
|
||||
const loaded = loadSiblingRuntimeModuleSync<{ runtimeLine: { source: string } }>({
|
||||
moduleUrl,
|
||||
relativeBase: "./runtime-line.contract",
|
||||
relativeBase: "./runtime.contract",
|
||||
});
|
||||
|
||||
expect(loaded.runtimeLine.source).toBe("sibling");
|
||||
@@ -50,13 +50,13 @@ describe("loadSiblingRuntimeModuleSync", () => {
|
||||
const moduleUrl = pathToFileURL(path.join(root, "dist", "runtime-9DLN_Ai5.js")).href;
|
||||
|
||||
writeFile(
|
||||
path.join(root, "dist", "plugins", "runtime", "runtime-line.contract.js"),
|
||||
path.join(root, "dist", "plugins", "runtime", "runtime.contract.js"),
|
||||
"module.exports = { runtimeLine: { source: 'dist-runtime' } };",
|
||||
);
|
||||
|
||||
const loaded = loadSiblingRuntimeModuleSync<{ runtimeLine: { source: string } }>({
|
||||
moduleUrl,
|
||||
relativeBase: "./runtime-line.contract",
|
||||
relativeBase: "./runtime.contract",
|
||||
});
|
||||
|
||||
expect(loaded.runtimeLine.source).toBe("dist-runtime");
|
||||
@@ -69,8 +69,8 @@ describe("loadSiblingRuntimeModuleSync", () => {
|
||||
expect(() =>
|
||||
loadSiblingRuntimeModuleSync({
|
||||
moduleUrl,
|
||||
relativeBase: "./runtime-line.contract",
|
||||
relativeBase: "./runtime.contract",
|
||||
}),
|
||||
).toThrow("Unable to resolve runtime module ./runtime-line.contract");
|
||||
).toThrow("Unable to resolve runtime module ./runtime.contract");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -61,17 +61,7 @@ import {
|
||||
readChannelAllowFromStore,
|
||||
upsertChannelPairingRequest,
|
||||
} from "../../pairing/pairing-store.js";
|
||||
import {
|
||||
setThreadBindingIdleTimeoutBySessionKey,
|
||||
setThreadBindingMaxAgeBySessionKey,
|
||||
} from "../../plugin-sdk/discord-runtime-surface.js";
|
||||
import { buildAgentSessionKey, resolveAgentRoute } from "../../routing/resolve-route.js";
|
||||
import { defineCachedValue } from "./runtime-cache.js";
|
||||
import { createRuntimeDiscord } from "./runtime-discord.js";
|
||||
import { createRuntimeLine } from "./runtime-line.js";
|
||||
import { createRuntimeMatrix } from "./runtime-matrix.js";
|
||||
import { createRuntimeSignal } from "./runtime-signal.js";
|
||||
import { createRuntimeSlack } from "./runtime-slack.js";
|
||||
import type { PluginRuntime } from "./types.js";
|
||||
|
||||
export function createRuntimeChannel(): PluginRuntime["channel"] {
|
||||
@@ -161,63 +151,22 @@ export function createRuntimeChannel(): PluginRuntime["channel"] {
|
||||
loadAdapter: loadChannelOutboundAdapter,
|
||||
},
|
||||
threadBindings: {
|
||||
setIdleTimeoutBySessionKey: ({ channelId, targetSessionKey, accountId, idleTimeoutMs }) => {
|
||||
switch (channelId) {
|
||||
case "discord":
|
||||
return setThreadBindingIdleTimeoutBySessionKey({
|
||||
targetSessionKey,
|
||||
accountId,
|
||||
idleTimeoutMs,
|
||||
});
|
||||
case "matrix":
|
||||
return setChannelConversationBindingIdleTimeoutBySessionKey({
|
||||
channelId,
|
||||
targetSessionKey,
|
||||
accountId: accountId ?? "",
|
||||
idleTimeoutMs,
|
||||
});
|
||||
case "telegram":
|
||||
return setChannelConversationBindingIdleTimeoutBySessionKey({
|
||||
channelId,
|
||||
targetSessionKey,
|
||||
accountId,
|
||||
idleTimeoutMs,
|
||||
});
|
||||
}
|
||||
},
|
||||
setMaxAgeBySessionKey: ({ channelId, targetSessionKey, accountId, maxAgeMs }) => {
|
||||
switch (channelId) {
|
||||
case "discord":
|
||||
return setThreadBindingMaxAgeBySessionKey({
|
||||
targetSessionKey,
|
||||
accountId,
|
||||
maxAgeMs,
|
||||
});
|
||||
case "matrix":
|
||||
return setChannelConversationBindingMaxAgeBySessionKey({
|
||||
channelId,
|
||||
targetSessionKey,
|
||||
accountId: accountId ?? "",
|
||||
maxAgeMs,
|
||||
});
|
||||
case "telegram":
|
||||
return setChannelConversationBindingMaxAgeBySessionKey({
|
||||
channelId,
|
||||
targetSessionKey,
|
||||
accountId,
|
||||
maxAgeMs,
|
||||
});
|
||||
}
|
||||
},
|
||||
setIdleTimeoutBySessionKey: ({ channelId, targetSessionKey, accountId, idleTimeoutMs }) =>
|
||||
setChannelConversationBindingIdleTimeoutBySessionKey({
|
||||
channelId,
|
||||
targetSessionKey,
|
||||
accountId,
|
||||
idleTimeoutMs,
|
||||
}),
|
||||
setMaxAgeBySessionKey: ({ channelId, targetSessionKey, accountId, maxAgeMs }) =>
|
||||
setChannelConversationBindingMaxAgeBySessionKey({
|
||||
channelId,
|
||||
targetSessionKey,
|
||||
accountId,
|
||||
maxAgeMs,
|
||||
}),
|
||||
},
|
||||
} satisfies Omit<PluginRuntime["channel"], "discord" | "slack" | "matrix" | "signal" | "line"> &
|
||||
Partial<Pick<PluginRuntime["channel"], "discord" | "slack" | "matrix" | "signal" | "line">>;
|
||||
|
||||
defineCachedValue(channelRuntime, "discord", createRuntimeDiscord);
|
||||
defineCachedValue(channelRuntime, "slack", createRuntimeSlack);
|
||||
defineCachedValue(channelRuntime, "matrix", createRuntimeMatrix);
|
||||
defineCachedValue(channelRuntime, "signal", createRuntimeSignal);
|
||||
defineCachedValue(channelRuntime, "line", createRuntimeLine);
|
||||
} satisfies PluginRuntime["channel"];
|
||||
|
||||
return channelRuntime as PluginRuntime["channel"];
|
||||
}
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
import {
|
||||
auditDiscordChannelPermissions as auditDiscordChannelPermissionsImpl,
|
||||
listDiscordDirectoryGroupsLive as listDiscordDirectoryGroupsLiveImpl,
|
||||
listDiscordDirectoryPeersLive as listDiscordDirectoryPeersLiveImpl,
|
||||
monitorDiscordProvider as monitorDiscordProviderImpl,
|
||||
probeDiscord as probeDiscordImpl,
|
||||
resolveDiscordChannelAllowlist as resolveDiscordChannelAllowlistImpl,
|
||||
resolveDiscordUserAllowlist as resolveDiscordUserAllowlistImpl,
|
||||
createThreadDiscord as createThreadDiscordImpl,
|
||||
deleteMessageDiscord as deleteMessageDiscordImpl,
|
||||
editChannelDiscord as editChannelDiscordImpl,
|
||||
editMessageDiscord as editMessageDiscordImpl,
|
||||
pinMessageDiscord as pinMessageDiscordImpl,
|
||||
sendDiscordComponentMessage as sendDiscordComponentMessageImpl,
|
||||
sendMessageDiscord as sendMessageDiscordImpl,
|
||||
sendPollDiscord as sendPollDiscordImpl,
|
||||
sendTypingDiscord as sendTypingDiscordImpl,
|
||||
unpinMessageDiscord as unpinMessageDiscordImpl,
|
||||
} from "../../plugin-sdk/discord-runtime-surface.js";
|
||||
import type { PluginRuntimeChannel } from "./types-channel.js";
|
||||
|
||||
type RuntimeDiscordOps = Pick<
|
||||
PluginRuntimeChannel["discord"],
|
||||
| "auditChannelPermissions"
|
||||
| "listDirectoryGroupsLive"
|
||||
| "listDirectoryPeersLive"
|
||||
| "probeDiscord"
|
||||
| "resolveChannelAllowlist"
|
||||
| "resolveUserAllowlist"
|
||||
| "sendComponentMessage"
|
||||
| "sendMessageDiscord"
|
||||
| "sendPollDiscord"
|
||||
| "monitorDiscordProvider"
|
||||
> & {
|
||||
typing: Pick<PluginRuntimeChannel["discord"]["typing"], "pulse">;
|
||||
conversationActions: Pick<
|
||||
PluginRuntimeChannel["discord"]["conversationActions"],
|
||||
"editMessage" | "deleteMessage" | "pinMessage" | "unpinMessage" | "createThread" | "editChannel"
|
||||
>;
|
||||
};
|
||||
|
||||
export const runtimeDiscordOps = {
|
||||
auditChannelPermissions: auditDiscordChannelPermissionsImpl,
|
||||
listDirectoryGroupsLive: listDiscordDirectoryGroupsLiveImpl,
|
||||
listDirectoryPeersLive: listDiscordDirectoryPeersLiveImpl,
|
||||
probeDiscord: probeDiscordImpl,
|
||||
resolveChannelAllowlist: resolveDiscordChannelAllowlistImpl,
|
||||
resolveUserAllowlist: resolveDiscordUserAllowlistImpl,
|
||||
sendComponentMessage: sendDiscordComponentMessageImpl,
|
||||
sendMessageDiscord: sendMessageDiscordImpl,
|
||||
sendPollDiscord: sendPollDiscordImpl,
|
||||
monitorDiscordProvider: monitorDiscordProviderImpl,
|
||||
typing: {
|
||||
pulse: sendTypingDiscordImpl,
|
||||
},
|
||||
conversationActions: {
|
||||
editMessage: editMessageDiscordImpl,
|
||||
deleteMessage: deleteMessageDiscordImpl,
|
||||
pinMessage: pinMessageDiscordImpl,
|
||||
unpinMessage: unpinMessageDiscordImpl,
|
||||
createThread: createThreadDiscordImpl,
|
||||
editChannel: editChannelDiscordImpl,
|
||||
},
|
||||
} satisfies RuntimeDiscordOps;
|
||||
@@ -1,122 +0,0 @@
|
||||
import {
|
||||
discordMessageActions,
|
||||
getThreadBindingManager,
|
||||
resolveThreadBindingIdleTimeoutMs,
|
||||
resolveThreadBindingInactivityExpiresAt,
|
||||
resolveThreadBindingMaxAgeExpiresAt,
|
||||
resolveThreadBindingMaxAgeMs,
|
||||
setThreadBindingIdleTimeoutBySessionKey,
|
||||
setThreadBindingMaxAgeBySessionKey,
|
||||
unbindThreadBindingsBySessionKey,
|
||||
} from "../../plugin-sdk/discord-runtime-surface.js";
|
||||
import {
|
||||
createLazyRuntimeMethodBinder,
|
||||
createLazyRuntimeSurface,
|
||||
} from "../../shared/lazy-runtime.js";
|
||||
import { createDiscordTypingLease } from "./runtime-discord-typing.js";
|
||||
import type { PluginRuntimeChannel } from "./types-channel.js";
|
||||
|
||||
const loadRuntimeDiscordOps = createLazyRuntimeSurface(
|
||||
() => import("./runtime-discord-ops.runtime.js"),
|
||||
({ runtimeDiscordOps }) => runtimeDiscordOps,
|
||||
);
|
||||
|
||||
const bindDiscordRuntimeMethod = createLazyRuntimeMethodBinder(loadRuntimeDiscordOps);
|
||||
|
||||
const auditChannelPermissionsLazy = bindDiscordRuntimeMethod(
|
||||
(runtimeDiscordOps) => runtimeDiscordOps.auditChannelPermissions,
|
||||
);
|
||||
const listDirectoryGroupsLiveLazy = bindDiscordRuntimeMethod(
|
||||
(runtimeDiscordOps) => runtimeDiscordOps.listDirectoryGroupsLive,
|
||||
);
|
||||
const listDirectoryPeersLiveLazy = bindDiscordRuntimeMethod(
|
||||
(runtimeDiscordOps) => runtimeDiscordOps.listDirectoryPeersLive,
|
||||
);
|
||||
const probeDiscordLazy = bindDiscordRuntimeMethod(
|
||||
(runtimeDiscordOps) => runtimeDiscordOps.probeDiscord,
|
||||
);
|
||||
const resolveChannelAllowlistLazy = bindDiscordRuntimeMethod(
|
||||
(runtimeDiscordOps) => runtimeDiscordOps.resolveChannelAllowlist,
|
||||
);
|
||||
const resolveUserAllowlistLazy = bindDiscordRuntimeMethod(
|
||||
(runtimeDiscordOps) => runtimeDiscordOps.resolveUserAllowlist,
|
||||
);
|
||||
const sendComponentMessageLazy = bindDiscordRuntimeMethod(
|
||||
(runtimeDiscordOps) => runtimeDiscordOps.sendComponentMessage,
|
||||
);
|
||||
const sendMessageDiscordLazy = bindDiscordRuntimeMethod(
|
||||
(runtimeDiscordOps) => runtimeDiscordOps.sendMessageDiscord,
|
||||
);
|
||||
const sendPollDiscordLazy = bindDiscordRuntimeMethod(
|
||||
(runtimeDiscordOps) => runtimeDiscordOps.sendPollDiscord,
|
||||
);
|
||||
const monitorDiscordProviderLazy = bindDiscordRuntimeMethod(
|
||||
(runtimeDiscordOps) => runtimeDiscordOps.monitorDiscordProvider,
|
||||
);
|
||||
const sendTypingDiscordLazy = bindDiscordRuntimeMethod(
|
||||
(runtimeDiscordOps) => runtimeDiscordOps.typing.pulse,
|
||||
);
|
||||
const editMessageDiscordLazy = bindDiscordRuntimeMethod(
|
||||
(runtimeDiscordOps) => runtimeDiscordOps.conversationActions.editMessage,
|
||||
);
|
||||
const deleteMessageDiscordLazy = bindDiscordRuntimeMethod(
|
||||
(runtimeDiscordOps) => runtimeDiscordOps.conversationActions.deleteMessage,
|
||||
);
|
||||
const pinMessageDiscordLazy = bindDiscordRuntimeMethod(
|
||||
(runtimeDiscordOps) => runtimeDiscordOps.conversationActions.pinMessage,
|
||||
);
|
||||
const unpinMessageDiscordLazy = bindDiscordRuntimeMethod(
|
||||
(runtimeDiscordOps) => runtimeDiscordOps.conversationActions.unpinMessage,
|
||||
);
|
||||
const createThreadDiscordLazy = bindDiscordRuntimeMethod(
|
||||
(runtimeDiscordOps) => runtimeDiscordOps.conversationActions.createThread,
|
||||
);
|
||||
const editChannelDiscordLazy = bindDiscordRuntimeMethod(
|
||||
(runtimeDiscordOps) => runtimeDiscordOps.conversationActions.editChannel,
|
||||
);
|
||||
|
||||
export function createRuntimeDiscord(): PluginRuntimeChannel["discord"] {
|
||||
return {
|
||||
messageActions: discordMessageActions,
|
||||
auditChannelPermissions: auditChannelPermissionsLazy,
|
||||
listDirectoryGroupsLive: listDirectoryGroupsLiveLazy,
|
||||
listDirectoryPeersLive: listDirectoryPeersLiveLazy,
|
||||
probeDiscord: probeDiscordLazy,
|
||||
resolveChannelAllowlist: resolveChannelAllowlistLazy,
|
||||
resolveUserAllowlist: resolveUserAllowlistLazy,
|
||||
sendComponentMessage: sendComponentMessageLazy,
|
||||
sendMessageDiscord: sendMessageDiscordLazy,
|
||||
sendPollDiscord: sendPollDiscordLazy,
|
||||
monitorDiscordProvider: monitorDiscordProviderLazy,
|
||||
threadBindings: {
|
||||
getManager: getThreadBindingManager,
|
||||
resolveIdleTimeoutMs: resolveThreadBindingIdleTimeoutMs,
|
||||
resolveInactivityExpiresAt: resolveThreadBindingInactivityExpiresAt,
|
||||
resolveMaxAgeMs: resolveThreadBindingMaxAgeMs,
|
||||
resolveMaxAgeExpiresAt: resolveThreadBindingMaxAgeExpiresAt,
|
||||
setIdleTimeoutBySessionKey: setThreadBindingIdleTimeoutBySessionKey,
|
||||
setMaxAgeBySessionKey: setThreadBindingMaxAgeBySessionKey,
|
||||
unbindBySessionKey: unbindThreadBindingsBySessionKey,
|
||||
},
|
||||
typing: {
|
||||
pulse: sendTypingDiscordLazy,
|
||||
start: async ({ channelId, accountId, cfg, intervalMs }) =>
|
||||
await createDiscordTypingLease({
|
||||
channelId,
|
||||
accountId,
|
||||
cfg,
|
||||
intervalMs,
|
||||
pulse: async ({ channelId, accountId, cfg }) =>
|
||||
void (await sendTypingDiscordLazy(channelId, { accountId, cfg })),
|
||||
}),
|
||||
},
|
||||
conversationActions: {
|
||||
editMessage: editMessageDiscordLazy,
|
||||
deleteMessage: deleteMessageDiscordLazy,
|
||||
pinMessage: pinMessageDiscordLazy,
|
||||
unpinMessage: unpinMessageDiscordLazy,
|
||||
createThread: createThreadDiscordLazy,
|
||||
editChannel: editChannelDiscordLazy,
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
import {
|
||||
buildTemplateMessageFromPayload,
|
||||
createQuickReplyItems,
|
||||
monitorLineProvider,
|
||||
probeLineBot,
|
||||
pushFlexMessage,
|
||||
pushLocationMessage,
|
||||
pushMessageLine,
|
||||
pushMessagesLine,
|
||||
pushTemplateMessage,
|
||||
pushTextMessageWithQuickReplies,
|
||||
sendMessageLine,
|
||||
} from "../../plugin-sdk/line-runtime.js";
|
||||
import {
|
||||
listLineAccountIds,
|
||||
normalizeAccountId,
|
||||
resolveDefaultLineAccountId,
|
||||
resolveLineAccount,
|
||||
} from "../../plugin-sdk/line.js";
|
||||
import type { PluginRuntimeChannel } from "./types-channel.js";
|
||||
|
||||
export const runtimeLine = {
|
||||
listLineAccountIds,
|
||||
resolveDefaultLineAccountId,
|
||||
resolveLineAccount,
|
||||
normalizeAccountId,
|
||||
probeLineBot,
|
||||
sendMessageLine,
|
||||
pushMessageLine,
|
||||
pushMessagesLine,
|
||||
pushFlexMessage,
|
||||
pushTemplateMessage,
|
||||
pushLocationMessage,
|
||||
pushTextMessageWithQuickReplies,
|
||||
createQuickReplyItems,
|
||||
buildTemplateMessageFromPayload,
|
||||
monitorLineProvider,
|
||||
} satisfies PluginRuntimeChannel["line"];
|
||||
@@ -1,11 +0,0 @@
|
||||
export {
|
||||
monitorLineProvider,
|
||||
probeLineBot,
|
||||
pushFlexMessage,
|
||||
pushLocationMessage,
|
||||
pushMessageLine,
|
||||
pushMessagesLine,
|
||||
pushTemplateMessage,
|
||||
pushTextMessageWithQuickReplies,
|
||||
sendMessageLine,
|
||||
} from "../../plugin-sdk/line-runtime.js";
|
||||
@@ -1,46 +0,0 @@
|
||||
import { loadSiblingRuntimeModuleSync } from "./local-runtime-module.js";
|
||||
import type { PluginRuntimeChannel } from "./types-channel.js";
|
||||
|
||||
type RuntimeLineModule = {
|
||||
runtimeLine: PluginRuntimeChannel["line"];
|
||||
};
|
||||
|
||||
let cachedRuntimeLineModule: RuntimeLineModule | null = null;
|
||||
|
||||
function loadRuntimeLineModule(): RuntimeLineModule {
|
||||
cachedRuntimeLineModule ??= loadSiblingRuntimeModuleSync<RuntimeLineModule>({
|
||||
moduleUrl: import.meta.url,
|
||||
relativeBase: "./runtime-line.contract",
|
||||
});
|
||||
return cachedRuntimeLineModule;
|
||||
}
|
||||
|
||||
export function createRuntimeLine(): PluginRuntimeChannel["line"] {
|
||||
return {
|
||||
listLineAccountIds: (...args) =>
|
||||
loadRuntimeLineModule().runtimeLine.listLineAccountIds(...args),
|
||||
resolveDefaultLineAccountId: (...args) =>
|
||||
loadRuntimeLineModule().runtimeLine.resolveDefaultLineAccountId(...args),
|
||||
resolveLineAccount: (...args) =>
|
||||
loadRuntimeLineModule().runtimeLine.resolveLineAccount(...args),
|
||||
normalizeAccountId: (...args) =>
|
||||
loadRuntimeLineModule().runtimeLine.normalizeAccountId(...args),
|
||||
probeLineBot: (...args) => loadRuntimeLineModule().runtimeLine.probeLineBot(...args),
|
||||
sendMessageLine: (...args) => loadRuntimeLineModule().runtimeLine.sendMessageLine(...args),
|
||||
pushMessageLine: (...args) => loadRuntimeLineModule().runtimeLine.pushMessageLine(...args),
|
||||
pushMessagesLine: (...args) => loadRuntimeLineModule().runtimeLine.pushMessagesLine(...args),
|
||||
pushFlexMessage: (...args) => loadRuntimeLineModule().runtimeLine.pushFlexMessage(...args),
|
||||
pushTemplateMessage: (...args) =>
|
||||
loadRuntimeLineModule().runtimeLine.pushTemplateMessage(...args),
|
||||
pushLocationMessage: (...args) =>
|
||||
loadRuntimeLineModule().runtimeLine.pushLocationMessage(...args),
|
||||
pushTextMessageWithQuickReplies: (...args) =>
|
||||
loadRuntimeLineModule().runtimeLine.pushTextMessageWithQuickReplies(...args),
|
||||
createQuickReplyItems: (...args) =>
|
||||
loadRuntimeLineModule().runtimeLine.createQuickReplyItems(...args),
|
||||
buildTemplateMessageFromPayload: (...args) =>
|
||||
loadRuntimeLineModule().runtimeLine.buildTemplateMessageFromPayload(...args),
|
||||
monitorLineProvider: (...args) =>
|
||||
loadRuntimeLineModule().runtimeLine.monitorLineProvider(...args),
|
||||
};
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
import { createJiti } from "jiti";
|
||||
import type { MatrixRuntimeBoundaryModule } from "./runtime-matrix-surface.js";
|
||||
import {
|
||||
loadPluginBoundaryModuleWithJiti,
|
||||
resolvePluginRuntimeModulePath,
|
||||
resolvePluginRuntimeRecord,
|
||||
} from "./runtime-plugin-boundary.js";
|
||||
|
||||
const MATRIX_PLUGIN_ID = "matrix";
|
||||
|
||||
type MatrixPluginRecord = {
|
||||
rootDir?: string;
|
||||
source: string;
|
||||
};
|
||||
|
||||
let cachedModulePath: string | null = null;
|
||||
let cachedModule: MatrixRuntimeBoundaryModule | null = null;
|
||||
|
||||
const jitiLoaders = new Map<boolean, ReturnType<typeof createJiti>>();
|
||||
|
||||
function resolveMatrixPluginRecord(): MatrixPluginRecord | null {
|
||||
return resolvePluginRuntimeRecord(MATRIX_PLUGIN_ID) as MatrixPluginRecord | null;
|
||||
}
|
||||
|
||||
function resolveMatrixRuntimeModulePath(record: MatrixPluginRecord): string | null {
|
||||
return resolvePluginRuntimeModulePath(record, "runtime-api");
|
||||
}
|
||||
|
||||
function loadMatrixModule(): MatrixRuntimeBoundaryModule | null {
|
||||
const record = resolveMatrixPluginRecord();
|
||||
if (!record) {
|
||||
return null;
|
||||
}
|
||||
const modulePath = resolveMatrixRuntimeModulePath(record);
|
||||
if (!modulePath) {
|
||||
return null;
|
||||
}
|
||||
if (cachedModule && cachedModulePath === modulePath) {
|
||||
return cachedModule;
|
||||
}
|
||||
const loaded = loadPluginBoundaryModuleWithJiti<MatrixRuntimeBoundaryModule>(
|
||||
modulePath,
|
||||
jitiLoaders,
|
||||
);
|
||||
cachedModulePath = modulePath;
|
||||
cachedModule = loaded;
|
||||
return loaded;
|
||||
}
|
||||
|
||||
export function setMatrixThreadBindingIdleTimeoutBySessionKey(
|
||||
...args: Parameters<MatrixRuntimeBoundaryModule["setMatrixThreadBindingIdleTimeoutBySessionKey"]>
|
||||
): ReturnType<MatrixRuntimeBoundaryModule["setMatrixThreadBindingIdleTimeoutBySessionKey"]> {
|
||||
const fn = loadMatrixModule()?.setMatrixThreadBindingIdleTimeoutBySessionKey;
|
||||
if (typeof fn !== "function") {
|
||||
return [];
|
||||
}
|
||||
return fn(...args);
|
||||
}
|
||||
|
||||
export function setMatrixThreadBindingMaxAgeBySessionKey(
|
||||
...args: Parameters<MatrixRuntimeBoundaryModule["setMatrixThreadBindingMaxAgeBySessionKey"]>
|
||||
): ReturnType<MatrixRuntimeBoundaryModule["setMatrixThreadBindingMaxAgeBySessionKey"]> {
|
||||
const fn = loadMatrixModule()?.setMatrixThreadBindingMaxAgeBySessionKey;
|
||||
if (typeof fn !== "function") {
|
||||
return [];
|
||||
}
|
||||
return fn(...args);
|
||||
}
|
||||
@@ -1,178 +0,0 @@
|
||||
// Narrow plugin-sdk surface for the bundled Matrix plugin.
|
||||
// Keep this list additive and scoped to the runtime contract only.
|
||||
|
||||
import { createOptionalChannelSetupSurface } from "../../plugin-sdk/channel-setup.js";
|
||||
|
||||
export {
|
||||
createActionGate,
|
||||
jsonResult,
|
||||
readNumberParam,
|
||||
readReactionParams,
|
||||
readStringArrayParam,
|
||||
readStringParam,
|
||||
} from "../../agents/tools/common.js";
|
||||
export type { ReplyPayload } from "../../auto-reply/types.js";
|
||||
export { resolveAckReaction } from "../../agents/identity.js";
|
||||
export {
|
||||
compileAllowlist,
|
||||
resolveCompiledAllowlistMatch,
|
||||
resolveAllowlistCandidates,
|
||||
resolveAllowlistMatchByCandidates,
|
||||
} from "../../channels/allowlist-match.js";
|
||||
export {
|
||||
addAllowlistUserEntriesFromConfigEntry,
|
||||
buildAllowlistResolutionSummary,
|
||||
canonicalizeAllowlistWithResolvedIds,
|
||||
mergeAllowlist,
|
||||
patchAllowlistUsersInConfigEntries,
|
||||
summarizeMapping,
|
||||
} from "../../channels/allowlists/resolve-utils.js";
|
||||
export { ensureConfiguredAcpBindingReady } from "../../acp/persistent-bindings.lifecycle.js";
|
||||
export { resolveConfiguredAcpBindingRecord } from "../../acp/persistent-bindings.resolve.js";
|
||||
export { resolveControlCommandGate } from "../../channels/command-gating.js";
|
||||
export type { NormalizedLocation } from "../../channels/location.js";
|
||||
export { formatLocationText, toLocationContext } from "../../channels/location.js";
|
||||
export { logInboundDrop, logTypingFailure } from "../../channels/logging.js";
|
||||
export type { AllowlistMatch } from "../../channels/plugins/allowlist-match.js";
|
||||
export { formatAllowlistMatchMeta } from "../../channels/plugins/allowlist-match.js";
|
||||
export {
|
||||
buildChannelKeyCandidates,
|
||||
resolveChannelEntryMatch,
|
||||
} from "../../channels/plugins/channel-config.js";
|
||||
export { createAccountListHelpers } from "../../channels/plugins/account-helpers.js";
|
||||
export {
|
||||
deleteAccountFromConfigSection,
|
||||
setAccountEnabledInConfigSection,
|
||||
} from "../../channels/plugins/config-helpers.js";
|
||||
export { buildChannelConfigSchema } from "../../channels/plugins/config-schema.js";
|
||||
export { formatPairingApproveHint } from "../../channels/plugins/helpers.js";
|
||||
export {
|
||||
buildSingleChannelSecretPromptState,
|
||||
addWildcardAllowFrom,
|
||||
mergeAllowFromEntries,
|
||||
promptAccountId,
|
||||
promptSingleChannelSecretInput,
|
||||
setTopLevelChannelGroupPolicy,
|
||||
} from "../../channels/plugins/setup-wizard-helpers.js";
|
||||
export { promptChannelAccessConfig } from "../../channels/plugins/setup-group-access.js";
|
||||
export { PAIRING_APPROVED_MESSAGE } from "../../channels/plugins/pairing-message.js";
|
||||
export {
|
||||
applyAccountNameToChannelSection,
|
||||
moveSingleAccountChannelSectionToDefaultAccount,
|
||||
} from "../../channels/plugins/setup-helpers.js";
|
||||
export type {
|
||||
BaseProbeResult,
|
||||
ChannelDirectoryEntry,
|
||||
ChannelGroupContext,
|
||||
ChannelMessageActionAdapter,
|
||||
ChannelMessageActionContext,
|
||||
ChannelMessageActionName,
|
||||
ChannelMessageToolDiscovery,
|
||||
ChannelMessageToolSchemaContribution,
|
||||
ChannelOutboundAdapter,
|
||||
ChannelResolveKind,
|
||||
ChannelResolveResult,
|
||||
ChannelSetupInput,
|
||||
ChannelToolSend,
|
||||
} from "../../channels/plugins/types.js";
|
||||
export type { ChannelPlugin } from "../../channels/plugins/types.plugin.js";
|
||||
export { createReplyPrefixOptions } from "../../channels/reply-prefix.js";
|
||||
export { resolveThreadBindingFarewellText } from "../../channels/thread-bindings-messages.js";
|
||||
export {
|
||||
resolveThreadBindingIdleTimeoutMsForChannel,
|
||||
resolveThreadBindingMaxAgeMsForChannel,
|
||||
} from "../../channels/thread-bindings-policy.js";
|
||||
export {
|
||||
setMatrixThreadBindingIdleTimeoutBySessionKey,
|
||||
setMatrixThreadBindingMaxAgeBySessionKey,
|
||||
} from "../../plugin-sdk/matrix-thread-bindings.js";
|
||||
export { createTypingCallbacks } from "../../channels/typing.js";
|
||||
export { createChannelReplyPipeline } from "../../plugin-sdk/channel-reply-pipeline.js";
|
||||
export type { OpenClawConfig } from "../../config/config.js";
|
||||
export {
|
||||
GROUP_POLICY_BLOCKED_LABEL,
|
||||
resolveAllowlistProviderRuntimeGroupPolicy,
|
||||
resolveDefaultGroupPolicy,
|
||||
warnMissingProviderGroupPolicyFallbackOnce,
|
||||
} from "../../config/runtime-group-policy.js";
|
||||
export type {
|
||||
DmPolicy,
|
||||
GroupPolicy,
|
||||
GroupToolPolicyConfig,
|
||||
MarkdownTableMode,
|
||||
} from "../../config/types.js";
|
||||
export type { SecretInput } from "../../plugin-sdk/secret-input.js";
|
||||
export {
|
||||
buildSecretInputSchema,
|
||||
hasConfiguredSecretInput,
|
||||
normalizeResolvedSecretInputString,
|
||||
normalizeSecretInputString,
|
||||
} from "../../plugin-sdk/secret-input.js";
|
||||
export { ToolPolicySchema } from "../../config/zod-schema.agent-runtime.js";
|
||||
export { MarkdownConfigSchema } from "../../config/zod-schema.core.js";
|
||||
export { formatZonedTimestamp } from "../../infra/format-time/format-datetime.js";
|
||||
export { fetchWithSsrFGuard } from "../../infra/net/fetch-guard.js";
|
||||
export { maybeCreateMatrixMigrationSnapshot } from "../../infra/matrix-migration-snapshot.js";
|
||||
export {
|
||||
getSessionBindingService,
|
||||
registerSessionBindingAdapter,
|
||||
unregisterSessionBindingAdapter,
|
||||
} from "../../infra/outbound/session-binding-service.js";
|
||||
export { resolveOutboundSendDep } from "../../infra/outbound/send-deps.js";
|
||||
export type {
|
||||
BindingTargetKind,
|
||||
SessionBindingRecord,
|
||||
} from "../../infra/outbound/session-binding-service.js";
|
||||
export { isPrivateOrLoopbackHost } from "../../gateway/net.js";
|
||||
export { getAgentScopedMediaLocalRoots } from "../../media/local-roots.js";
|
||||
export { emptyPluginConfigSchema } from "../config-schema.js";
|
||||
export type { PluginRuntime, RuntimeLogger } from "./types.js";
|
||||
export type { OpenClawPluginApi } from "../types.js";
|
||||
export type { PollInput } from "../../polls.js";
|
||||
export { normalizePollInput } from "../../polls.js";
|
||||
export {
|
||||
DEFAULT_ACCOUNT_ID,
|
||||
normalizeAccountId,
|
||||
normalizeOptionalAccountId,
|
||||
resolveAgentIdFromSessionKey,
|
||||
} from "../../routing/session-key.js";
|
||||
export type { RuntimeEnv } from "../../runtime.js";
|
||||
export { normalizeStringEntries } from "../../shared/string-normalization.js";
|
||||
export { formatDocsLink } from "../../terminal/links.js";
|
||||
export { redactSensitiveText } from "../../logging/redact.js";
|
||||
export type { WizardPrompter } from "../../wizard/prompts.js";
|
||||
export {
|
||||
evaluateGroupRouteAccessForPolicy,
|
||||
resolveSenderScopedGroupPolicy,
|
||||
} from "../../plugin-sdk/group-access.js";
|
||||
export { createChannelPairingController } from "../../plugin-sdk/channel-pairing.js";
|
||||
export { readJsonFileWithFallback, writeJsonFileAtomically } from "../../plugin-sdk/json-store.js";
|
||||
export { formatResolvedUnresolvedNote } from "../../plugin-sdk/resolution-notes.js";
|
||||
export { runPluginCommandWithTimeout } from "../../plugin-sdk/run-command.js";
|
||||
export { createLoggerBackedRuntime, resolveRuntimeEnv } from "../../plugin-sdk/runtime.js";
|
||||
export { dispatchReplyFromConfigWithSettledDispatcher } from "../../plugin-sdk/inbound-reply-dispatch.js";
|
||||
export {
|
||||
buildProbeChannelStatusSummary,
|
||||
collectStatusIssuesFromLastError,
|
||||
} from "../../plugin-sdk/status-helpers.js";
|
||||
export {
|
||||
resolveMatrixAccountStorageRoot,
|
||||
resolveMatrixCredentialsDir,
|
||||
resolveMatrixCredentialsPath,
|
||||
resolveMatrixLegacyFlatStoragePaths,
|
||||
} from "../../plugin-sdk/matrix-helper.js";
|
||||
export { getMatrixScopedEnvVarNames } from "../../plugin-sdk/matrix-helper.js";
|
||||
export {
|
||||
requiresExplicitMatrixDefaultAccount,
|
||||
resolveMatrixDefaultOrOnlyAccountId,
|
||||
} from "../../plugin-sdk/matrix-helper.js";
|
||||
|
||||
const matrixSetup = createOptionalChannelSetupSurface({
|
||||
channel: "matrix",
|
||||
label: "Matrix",
|
||||
npmSpec: "@openclaw/matrix",
|
||||
docsPath: "/channels/matrix",
|
||||
});
|
||||
|
||||
export const matrixSetupWizard = matrixSetup.setupWizard;
|
||||
export const matrixSetupAdapter = matrixSetup.setupAdapter;
|
||||
@@ -1,22 +0,0 @@
|
||||
import type { SessionBindingRecord } from "../../infra/outbound/session-binding-service.js";
|
||||
|
||||
export type MatrixThreadBindingIdleTimeoutParams = {
|
||||
accountId: string;
|
||||
targetSessionKey: string;
|
||||
idleTimeoutMs: number;
|
||||
};
|
||||
|
||||
export type MatrixThreadBindingMaxAgeParams = {
|
||||
accountId: string;
|
||||
targetSessionKey: string;
|
||||
maxAgeMs: number;
|
||||
};
|
||||
|
||||
export type MatrixRuntimeBoundaryModule = {
|
||||
setMatrixThreadBindingIdleTimeoutBySessionKey: (
|
||||
params: MatrixThreadBindingIdleTimeoutParams,
|
||||
) => SessionBindingRecord[];
|
||||
setMatrixThreadBindingMaxAgeBySessionKey: (
|
||||
params: MatrixThreadBindingMaxAgeParams,
|
||||
) => SessionBindingRecord[];
|
||||
};
|
||||
@@ -1,14 +0,0 @@
|
||||
import {
|
||||
setMatrixThreadBindingIdleTimeoutBySessionKey,
|
||||
setMatrixThreadBindingMaxAgeBySessionKey,
|
||||
} from "./runtime-matrix-boundary.js";
|
||||
import type { PluginRuntimeChannel } from "./types-channel.js";
|
||||
|
||||
export function createRuntimeMatrix(): PluginRuntimeChannel["matrix"] {
|
||||
return {
|
||||
threadBindings: {
|
||||
setIdleTimeoutBySessionKey: setMatrixThreadBindingIdleTimeoutBySessionKey,
|
||||
setMaxAgeBySessionKey: setMatrixThreadBindingMaxAgeBySessionKey,
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -16,6 +16,13 @@ type PluginRuntimeRecord = {
|
||||
source: string;
|
||||
};
|
||||
|
||||
type CachedPluginBoundaryLoaderParams = {
|
||||
pluginId: string;
|
||||
entryBaseName: string;
|
||||
required?: boolean;
|
||||
missingLabel?: string;
|
||||
};
|
||||
|
||||
export function readPluginBoundaryConfigSafely() {
|
||||
try {
|
||||
return loadConfig();
|
||||
@@ -104,3 +111,47 @@ export function loadPluginBoundaryModuleWithJiti<TModule>(
|
||||
): TModule {
|
||||
return getPluginBoundaryJiti(modulePath, loaders)(modulePath) as TModule;
|
||||
}
|
||||
|
||||
export function createCachedPluginBoundaryModuleLoader<TModule>(
|
||||
params: CachedPluginBoundaryLoaderParams,
|
||||
): () => TModule | null {
|
||||
let cachedModulePath: string | null = null;
|
||||
let cachedModule: TModule | null = null;
|
||||
const loaders = new Map<boolean, ReturnType<typeof createJiti>>();
|
||||
|
||||
return () => {
|
||||
const missingLabel = params.missingLabel ?? `${params.pluginId} plugin runtime`;
|
||||
const record = resolvePluginRuntimeRecord(
|
||||
params.pluginId,
|
||||
params.required
|
||||
? () => {
|
||||
throw new Error(`${missingLabel} is unavailable: missing plugin '${params.pluginId}'`);
|
||||
}
|
||||
: undefined,
|
||||
);
|
||||
if (!record) {
|
||||
return null;
|
||||
}
|
||||
const modulePath = resolvePluginRuntimeModulePath(
|
||||
record,
|
||||
params.entryBaseName,
|
||||
params.required
|
||||
? () => {
|
||||
throw new Error(
|
||||
`${missingLabel} is unavailable: missing ${params.entryBaseName} for plugin '${params.pluginId}'`,
|
||||
);
|
||||
}
|
||||
: undefined,
|
||||
);
|
||||
if (!modulePath) {
|
||||
return null;
|
||||
}
|
||||
if (cachedModule && cachedModulePath === modulePath) {
|
||||
return cachedModule;
|
||||
}
|
||||
const loaded = loadPluginBoundaryModuleWithJiti<TModule>(modulePath, loaders);
|
||||
cachedModulePath = modulePath;
|
||||
cachedModule = loaded;
|
||||
return loaded;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
import {
|
||||
monitorSignalProvider,
|
||||
probeSignal,
|
||||
signalMessageActions,
|
||||
sendMessageSignal,
|
||||
} from "../../plugin-sdk/signal-runtime-surface.js";
|
||||
import type { PluginRuntimeChannel } from "./types-channel.js";
|
||||
|
||||
export function createRuntimeSignal(): PluginRuntimeChannel["signal"] {
|
||||
return {
|
||||
probeSignal,
|
||||
sendMessageSignal,
|
||||
monitorSignalProvider,
|
||||
messageActions: signalMessageActions,
|
||||
};
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
import {
|
||||
listSlackDirectoryGroupsLive as listSlackDirectoryGroupsLiveImpl,
|
||||
listSlackDirectoryPeersLive as listSlackDirectoryPeersLiveImpl,
|
||||
monitorSlackProvider as monitorSlackProviderImpl,
|
||||
probeSlack as probeSlackImpl,
|
||||
resolveSlackChannelAllowlist as resolveSlackChannelAllowlistImpl,
|
||||
resolveSlackUserAllowlist as resolveSlackUserAllowlistImpl,
|
||||
sendMessageSlack as sendMessageSlackImpl,
|
||||
handleSlackAction as handleSlackActionImpl,
|
||||
} from "../../plugin-sdk/slack-runtime-surface.js";
|
||||
import type { PluginRuntimeChannel } from "./types-channel.js";
|
||||
|
||||
type RuntimeSlackOps = Pick<
|
||||
PluginRuntimeChannel["slack"],
|
||||
| "listDirectoryGroupsLive"
|
||||
| "listDirectoryPeersLive"
|
||||
| "probeSlack"
|
||||
| "resolveChannelAllowlist"
|
||||
| "resolveUserAllowlist"
|
||||
| "sendMessageSlack"
|
||||
| "monitorSlackProvider"
|
||||
| "handleSlackAction"
|
||||
>;
|
||||
|
||||
export const runtimeSlackOps = {
|
||||
listDirectoryGroupsLive: listSlackDirectoryGroupsLiveImpl,
|
||||
listDirectoryPeersLive: listSlackDirectoryPeersLiveImpl,
|
||||
probeSlack: probeSlackImpl,
|
||||
resolveChannelAllowlist: resolveSlackChannelAllowlistImpl,
|
||||
resolveUserAllowlist: resolveSlackUserAllowlistImpl,
|
||||
sendMessageSlack: sendMessageSlackImpl,
|
||||
monitorSlackProvider: monitorSlackProviderImpl,
|
||||
handleSlackAction: handleSlackActionImpl,
|
||||
} satisfies RuntimeSlackOps;
|
||||
@@ -1,48 +0,0 @@
|
||||
import {
|
||||
createLazyRuntimeMethodBinder,
|
||||
createLazyRuntimeSurface,
|
||||
} from "../../shared/lazy-runtime.js";
|
||||
import type { PluginRuntimeChannel } from "./types-channel.js";
|
||||
|
||||
const loadRuntimeSlackOps = createLazyRuntimeSurface(
|
||||
() => import("./runtime-slack-ops.runtime.js"),
|
||||
({ runtimeSlackOps }) => runtimeSlackOps,
|
||||
);
|
||||
|
||||
const bindSlackRuntimeMethod = createLazyRuntimeMethodBinder(loadRuntimeSlackOps);
|
||||
|
||||
const listDirectoryGroupsLiveLazy = bindSlackRuntimeMethod(
|
||||
(runtimeSlackOps) => runtimeSlackOps.listDirectoryGroupsLive,
|
||||
);
|
||||
const listDirectoryPeersLiveLazy = bindSlackRuntimeMethod(
|
||||
(runtimeSlackOps) => runtimeSlackOps.listDirectoryPeersLive,
|
||||
);
|
||||
const probeSlackLazy = bindSlackRuntimeMethod((runtimeSlackOps) => runtimeSlackOps.probeSlack);
|
||||
const resolveChannelAllowlistLazy = bindSlackRuntimeMethod(
|
||||
(runtimeSlackOps) => runtimeSlackOps.resolveChannelAllowlist,
|
||||
);
|
||||
const resolveUserAllowlistLazy = bindSlackRuntimeMethod(
|
||||
(runtimeSlackOps) => runtimeSlackOps.resolveUserAllowlist,
|
||||
);
|
||||
const sendMessageSlackLazy = bindSlackRuntimeMethod(
|
||||
(runtimeSlackOps) => runtimeSlackOps.sendMessageSlack,
|
||||
);
|
||||
const monitorSlackProviderLazy = bindSlackRuntimeMethod(
|
||||
(runtimeSlackOps) => runtimeSlackOps.monitorSlackProvider,
|
||||
);
|
||||
const handleSlackActionLazy = bindSlackRuntimeMethod(
|
||||
(runtimeSlackOps) => runtimeSlackOps.handleSlackAction,
|
||||
);
|
||||
|
||||
export function createRuntimeSlack(): PluginRuntimeChannel["slack"] {
|
||||
return {
|
||||
listDirectoryGroupsLive: listDirectoryGroupsLiveLazy,
|
||||
listDirectoryPeersLive: listDirectoryPeersLiveLazy,
|
||||
probeSlack: probeSlackLazy,
|
||||
resolveChannelAllowlist: resolveChannelAllowlistLazy,
|
||||
resolveUserAllowlist: resolveUserAllowlistLazy,
|
||||
sendMessageSlack: sendMessageSlackLazy,
|
||||
monitorSlackProvider: monitorSlackProviderLazy,
|
||||
handleSlackAction: handleSlackActionLazy,
|
||||
};
|
||||
}
|
||||
@@ -1,286 +0,0 @@
|
||||
import { createJiti } from "jiti";
|
||||
type WhatsAppHeavyRuntimeModule = typeof import("@openclaw/whatsapp/runtime-api.js");
|
||||
type WhatsAppLightRuntimeModule = typeof import("@openclaw/whatsapp/light-runtime-api.js");
|
||||
import {
|
||||
getDefaultLocalRoots as getDefaultLocalRootsImpl,
|
||||
loadWebMedia as loadWebMediaImpl,
|
||||
loadWebMediaRaw as loadWebMediaRawImpl,
|
||||
optimizeImageToJpeg as optimizeImageToJpegImpl,
|
||||
} from "../../media/web-media.js";
|
||||
import {
|
||||
loadPluginBoundaryModuleWithJiti,
|
||||
resolvePluginRuntimeModulePath,
|
||||
resolvePluginRuntimeRecord,
|
||||
} from "./runtime-plugin-boundary.js";
|
||||
|
||||
const WHATSAPP_PLUGIN_ID = "whatsapp";
|
||||
|
||||
type WhatsAppPluginRecord = {
|
||||
origin: string;
|
||||
rootDir?: string;
|
||||
source: string;
|
||||
};
|
||||
|
||||
let cachedHeavyModulePath: string | null = null;
|
||||
let cachedHeavyModule: WhatsAppHeavyRuntimeModule | null = null;
|
||||
let cachedLightModulePath: string | null = null;
|
||||
let cachedLightModule: WhatsAppLightRuntimeModule | null = null;
|
||||
|
||||
const jitiLoaders = new Map<boolean, ReturnType<typeof createJiti>>();
|
||||
|
||||
function resolveWhatsAppPluginRecord(): WhatsAppPluginRecord {
|
||||
return resolvePluginRuntimeRecord(WHATSAPP_PLUGIN_ID, () => {
|
||||
throw new Error(
|
||||
`WhatsApp plugin runtime is unavailable: missing plugin '${WHATSAPP_PLUGIN_ID}'`,
|
||||
);
|
||||
}) as WhatsAppPluginRecord;
|
||||
}
|
||||
|
||||
function resolveWhatsAppRuntimeModulePath(
|
||||
record: WhatsAppPluginRecord,
|
||||
entryBaseName: "light-runtime-api" | "runtime-api",
|
||||
): string {
|
||||
const modulePath = resolvePluginRuntimeModulePath(record, entryBaseName, () => {
|
||||
throw new Error(
|
||||
`WhatsApp plugin runtime is unavailable: missing ${entryBaseName} for plugin '${WHATSAPP_PLUGIN_ID}'`,
|
||||
);
|
||||
});
|
||||
if (!modulePath) {
|
||||
throw new Error(
|
||||
`WhatsApp plugin runtime is unavailable: missing ${entryBaseName} for plugin '${WHATSAPP_PLUGIN_ID}'`,
|
||||
);
|
||||
}
|
||||
return modulePath;
|
||||
}
|
||||
|
||||
function loadCurrentHeavyModuleSync(): WhatsAppHeavyRuntimeModule {
|
||||
const modulePath = resolveWhatsAppRuntimeModulePath(resolveWhatsAppPluginRecord(), "runtime-api");
|
||||
return loadPluginBoundaryModuleWithJiti<WhatsAppHeavyRuntimeModule>(modulePath, jitiLoaders);
|
||||
}
|
||||
|
||||
function loadWhatsAppLightModule(): WhatsAppLightRuntimeModule {
|
||||
const modulePath = resolveWhatsAppRuntimeModulePath(
|
||||
resolveWhatsAppPluginRecord(),
|
||||
"light-runtime-api",
|
||||
);
|
||||
if (cachedLightModule && cachedLightModulePath === modulePath) {
|
||||
return cachedLightModule;
|
||||
}
|
||||
const loaded = loadPluginBoundaryModuleWithJiti<WhatsAppLightRuntimeModule>(
|
||||
modulePath,
|
||||
jitiLoaders,
|
||||
);
|
||||
cachedLightModulePath = modulePath;
|
||||
cachedLightModule = loaded;
|
||||
return loaded;
|
||||
}
|
||||
|
||||
async function loadWhatsAppHeavyModule(): Promise<WhatsAppHeavyRuntimeModule> {
|
||||
const record = resolveWhatsAppPluginRecord();
|
||||
const modulePath = resolveWhatsAppRuntimeModulePath(record, "runtime-api");
|
||||
if (cachedHeavyModule && cachedHeavyModulePath === modulePath) {
|
||||
return cachedHeavyModule;
|
||||
}
|
||||
const loaded = loadPluginBoundaryModuleWithJiti<WhatsAppHeavyRuntimeModule>(
|
||||
modulePath,
|
||||
jitiLoaders,
|
||||
);
|
||||
cachedHeavyModulePath = modulePath;
|
||||
cachedHeavyModule = loaded;
|
||||
return loaded;
|
||||
}
|
||||
|
||||
function getLightExport<K extends keyof WhatsAppLightRuntimeModule>(
|
||||
exportName: K,
|
||||
): NonNullable<WhatsAppLightRuntimeModule[K]> {
|
||||
const loaded = loadWhatsAppLightModule();
|
||||
const value = loaded[exportName];
|
||||
if (value == null) {
|
||||
throw new Error(`WhatsApp plugin runtime is missing export '${String(exportName)}'`);
|
||||
}
|
||||
return value as NonNullable<WhatsAppLightRuntimeModule[K]>;
|
||||
}
|
||||
|
||||
async function getHeavyExport<K extends keyof WhatsAppHeavyRuntimeModule>(
|
||||
exportName: K,
|
||||
): Promise<NonNullable<WhatsAppHeavyRuntimeModule[K]>> {
|
||||
const loaded = await loadWhatsAppHeavyModule();
|
||||
const value = loaded[exportName];
|
||||
if (value == null) {
|
||||
throw new Error(`WhatsApp plugin runtime is missing export '${String(exportName)}'`);
|
||||
}
|
||||
return value as NonNullable<WhatsAppHeavyRuntimeModule[K]>;
|
||||
}
|
||||
|
||||
export function getActiveWebListener(
|
||||
...args: Parameters<WhatsAppLightRuntimeModule["getActiveWebListener"]>
|
||||
): ReturnType<WhatsAppLightRuntimeModule["getActiveWebListener"]> {
|
||||
return getLightExport("getActiveWebListener")(...args);
|
||||
}
|
||||
|
||||
export function getWebAuthAgeMs(
|
||||
...args: Parameters<WhatsAppLightRuntimeModule["getWebAuthAgeMs"]>
|
||||
): ReturnType<WhatsAppLightRuntimeModule["getWebAuthAgeMs"]> {
|
||||
return getLightExport("getWebAuthAgeMs")(...args);
|
||||
}
|
||||
|
||||
export function logWebSelfId(
|
||||
...args: Parameters<WhatsAppLightRuntimeModule["logWebSelfId"]>
|
||||
): ReturnType<WhatsAppLightRuntimeModule["logWebSelfId"]> {
|
||||
return getLightExport("logWebSelfId")(...args);
|
||||
}
|
||||
|
||||
export function loginWeb(
|
||||
...args: Parameters<WhatsAppHeavyRuntimeModule["loginWeb"]>
|
||||
): ReturnType<WhatsAppHeavyRuntimeModule["loginWeb"]> {
|
||||
return loadWhatsAppHeavyModule().then((loaded) => loaded.loginWeb(...args));
|
||||
}
|
||||
|
||||
export function logoutWeb(
|
||||
...args: Parameters<WhatsAppLightRuntimeModule["logoutWeb"]>
|
||||
): ReturnType<WhatsAppLightRuntimeModule["logoutWeb"]> {
|
||||
return getLightExport("logoutWeb")(...args);
|
||||
}
|
||||
|
||||
export function readWebSelfId(
|
||||
...args: Parameters<WhatsAppLightRuntimeModule["readWebSelfId"]>
|
||||
): ReturnType<WhatsAppLightRuntimeModule["readWebSelfId"]> {
|
||||
return getLightExport("readWebSelfId")(...args);
|
||||
}
|
||||
|
||||
export function webAuthExists(
|
||||
...args: Parameters<WhatsAppLightRuntimeModule["webAuthExists"]>
|
||||
): ReturnType<WhatsAppLightRuntimeModule["webAuthExists"]> {
|
||||
return getLightExport("webAuthExists")(...args);
|
||||
}
|
||||
|
||||
export function sendMessageWhatsApp(
|
||||
...args: Parameters<WhatsAppHeavyRuntimeModule["sendMessageWhatsApp"]>
|
||||
): ReturnType<WhatsAppHeavyRuntimeModule["sendMessageWhatsApp"]> {
|
||||
return loadWhatsAppHeavyModule().then((loaded) => loaded.sendMessageWhatsApp(...args));
|
||||
}
|
||||
|
||||
export function sendPollWhatsApp(
|
||||
...args: Parameters<WhatsAppHeavyRuntimeModule["sendPollWhatsApp"]>
|
||||
): ReturnType<WhatsAppHeavyRuntimeModule["sendPollWhatsApp"]> {
|
||||
return loadWhatsAppHeavyModule().then((loaded) => loaded.sendPollWhatsApp(...args));
|
||||
}
|
||||
|
||||
export function sendReactionWhatsApp(
|
||||
...args: Parameters<WhatsAppHeavyRuntimeModule["sendReactionWhatsApp"]>
|
||||
): ReturnType<WhatsAppHeavyRuntimeModule["sendReactionWhatsApp"]> {
|
||||
return loadWhatsAppHeavyModule().then((loaded) => loaded.sendReactionWhatsApp(...args));
|
||||
}
|
||||
|
||||
export function createRuntimeWhatsAppLoginTool(
|
||||
...args: Parameters<WhatsAppLightRuntimeModule["createWhatsAppLoginTool"]>
|
||||
): ReturnType<WhatsAppLightRuntimeModule["createWhatsAppLoginTool"]> {
|
||||
return getLightExport("createWhatsAppLoginTool")(...args);
|
||||
}
|
||||
|
||||
export function createWaSocket(
|
||||
...args: Parameters<WhatsAppHeavyRuntimeModule["createWaSocket"]>
|
||||
): ReturnType<WhatsAppHeavyRuntimeModule["createWaSocket"]> {
|
||||
return loadWhatsAppHeavyModule().then((loaded) => loaded.createWaSocket(...args));
|
||||
}
|
||||
|
||||
export function formatError(
|
||||
...args: Parameters<WhatsAppLightRuntimeModule["formatError"]>
|
||||
): ReturnType<WhatsAppLightRuntimeModule["formatError"]> {
|
||||
return getLightExport("formatError")(...args);
|
||||
}
|
||||
|
||||
export function getStatusCode(
|
||||
...args: Parameters<WhatsAppLightRuntimeModule["getStatusCode"]>
|
||||
): ReturnType<WhatsAppLightRuntimeModule["getStatusCode"]> {
|
||||
return getLightExport("getStatusCode")(...args);
|
||||
}
|
||||
|
||||
export function pickWebChannel(
|
||||
...args: Parameters<WhatsAppLightRuntimeModule["pickWebChannel"]>
|
||||
): ReturnType<WhatsAppLightRuntimeModule["pickWebChannel"]> {
|
||||
return getLightExport("pickWebChannel")(...args);
|
||||
}
|
||||
|
||||
export function resolveWaWebAuthDir(): WhatsAppLightRuntimeModule["WA_WEB_AUTH_DIR"] {
|
||||
return getLightExport("WA_WEB_AUTH_DIR");
|
||||
}
|
||||
|
||||
export async function handleWhatsAppAction(
|
||||
...args: Parameters<WhatsAppHeavyRuntimeModule["handleWhatsAppAction"]>
|
||||
): ReturnType<WhatsAppHeavyRuntimeModule["handleWhatsAppAction"]> {
|
||||
return (await getHeavyExport("handleWhatsAppAction"))(...args);
|
||||
}
|
||||
|
||||
export async function loadWebMedia(
|
||||
...args: Parameters<typeof loadWebMediaImpl>
|
||||
): ReturnType<typeof loadWebMediaImpl> {
|
||||
return await loadWebMediaImpl(...args);
|
||||
}
|
||||
|
||||
export async function loadWebMediaRaw(
|
||||
...args: Parameters<typeof loadWebMediaRawImpl>
|
||||
): ReturnType<typeof loadWebMediaRawImpl> {
|
||||
return await loadWebMediaRawImpl(...args);
|
||||
}
|
||||
|
||||
export function monitorWebChannel(
|
||||
...args: Parameters<WhatsAppHeavyRuntimeModule["monitorWebChannel"]>
|
||||
): ReturnType<WhatsAppHeavyRuntimeModule["monitorWebChannel"]> {
|
||||
return loadWhatsAppHeavyModule().then((loaded) => loaded.monitorWebChannel(...args));
|
||||
}
|
||||
|
||||
export async function monitorWebInbox(
|
||||
...args: Parameters<WhatsAppHeavyRuntimeModule["monitorWebInbox"]>
|
||||
): ReturnType<WhatsAppHeavyRuntimeModule["monitorWebInbox"]> {
|
||||
return (await getHeavyExport("monitorWebInbox"))(...args);
|
||||
}
|
||||
|
||||
export async function optimizeImageToJpeg(
|
||||
...args: Parameters<typeof optimizeImageToJpegImpl>
|
||||
): ReturnType<typeof optimizeImageToJpegImpl> {
|
||||
return await optimizeImageToJpegImpl(...args);
|
||||
}
|
||||
|
||||
export async function runWebHeartbeatOnce(
|
||||
...args: Parameters<WhatsAppHeavyRuntimeModule["runWebHeartbeatOnce"]>
|
||||
): ReturnType<WhatsAppHeavyRuntimeModule["runWebHeartbeatOnce"]> {
|
||||
return (await getHeavyExport("runWebHeartbeatOnce"))(...args);
|
||||
}
|
||||
|
||||
export async function startWebLoginWithQr(
|
||||
...args: Parameters<WhatsAppHeavyRuntimeModule["startWebLoginWithQr"]>
|
||||
): ReturnType<WhatsAppHeavyRuntimeModule["startWebLoginWithQr"]> {
|
||||
return (await getHeavyExport("startWebLoginWithQr"))(...args);
|
||||
}
|
||||
|
||||
export async function waitForWaConnection(
|
||||
...args: Parameters<WhatsAppHeavyRuntimeModule["waitForWaConnection"]>
|
||||
): ReturnType<WhatsAppHeavyRuntimeModule["waitForWaConnection"]> {
|
||||
return (await getHeavyExport("waitForWaConnection"))(...args);
|
||||
}
|
||||
|
||||
export async function waitForWebLogin(
|
||||
...args: Parameters<WhatsAppHeavyRuntimeModule["waitForWebLogin"]>
|
||||
): ReturnType<WhatsAppHeavyRuntimeModule["waitForWebLogin"]> {
|
||||
return (await getHeavyExport("waitForWebLogin"))(...args);
|
||||
}
|
||||
|
||||
export const extractMediaPlaceholder = (
|
||||
...args: Parameters<WhatsAppHeavyRuntimeModule["extractMediaPlaceholder"]>
|
||||
) => loadCurrentHeavyModuleSync().extractMediaPlaceholder(...args);
|
||||
|
||||
export const extractText = (...args: Parameters<WhatsAppHeavyRuntimeModule["extractText"]>) =>
|
||||
loadCurrentHeavyModuleSync().extractText(...args);
|
||||
|
||||
export function getDefaultLocalRoots(
|
||||
...args: Parameters<typeof getDefaultLocalRootsImpl>
|
||||
): ReturnType<typeof getDefaultLocalRootsImpl> {
|
||||
return getDefaultLocalRootsImpl(...args);
|
||||
}
|
||||
|
||||
export function resolveHeartbeatRecipients(
|
||||
...args: Parameters<WhatsAppHeavyRuntimeModule["resolveHeartbeatRecipients"]>
|
||||
): ReturnType<WhatsAppHeavyRuntimeModule["resolveHeartbeatRecipients"]> {
|
||||
return loadCurrentHeavyModuleSync().resolveHeartbeatRecipients(...args);
|
||||
}
|
||||
289
src/plugins/runtime/runtime-web-channel-plugin.ts
Normal file
289
src/plugins/runtime/runtime-web-channel-plugin.ts
Normal file
@@ -0,0 +1,289 @@
|
||||
import { createJiti } from "jiti";
|
||||
type WebChannelHeavyRuntimeModule = typeof import("@openclaw/whatsapp/runtime-api.js");
|
||||
type WebChannelLightRuntimeModule = typeof import("@openclaw/whatsapp/light-runtime-api.js");
|
||||
import {
|
||||
getDefaultLocalRoots as getDefaultLocalRootsImpl,
|
||||
loadWebMedia as loadWebMediaImpl,
|
||||
loadWebMediaRaw as loadWebMediaRawImpl,
|
||||
optimizeImageToJpeg as optimizeImageToJpegImpl,
|
||||
} from "../../media/web-media.js";
|
||||
import {
|
||||
loadPluginBoundaryModuleWithJiti,
|
||||
resolvePluginRuntimeModulePath,
|
||||
resolvePluginRuntimeRecord,
|
||||
} from "./runtime-plugin-boundary.js";
|
||||
|
||||
const WEB_CHANNEL_PLUGIN_ID = "whatsapp";
|
||||
|
||||
type WebChannelPluginRecord = {
|
||||
origin: string;
|
||||
rootDir?: string;
|
||||
source: string;
|
||||
};
|
||||
|
||||
let cachedHeavyModulePath: string | null = null;
|
||||
let cachedHeavyModule: WebChannelHeavyRuntimeModule | null = null;
|
||||
let cachedLightModulePath: string | null = null;
|
||||
let cachedLightModule: WebChannelLightRuntimeModule | null = null;
|
||||
|
||||
const jitiLoaders = new Map<boolean, ReturnType<typeof createJiti>>();
|
||||
|
||||
function resolveWebChannelPluginRecord(): WebChannelPluginRecord {
|
||||
return resolvePluginRuntimeRecord(WEB_CHANNEL_PLUGIN_ID, () => {
|
||||
throw new Error(
|
||||
`web channel plugin runtime is unavailable: missing plugin '${WEB_CHANNEL_PLUGIN_ID}'`,
|
||||
);
|
||||
}) as WebChannelPluginRecord;
|
||||
}
|
||||
|
||||
function resolveWebChannelRuntimeModulePath(
|
||||
record: WebChannelPluginRecord,
|
||||
entryBaseName: "light-runtime-api" | "runtime-api",
|
||||
): string {
|
||||
const modulePath = resolvePluginRuntimeModulePath(record, entryBaseName, () => {
|
||||
throw new Error(
|
||||
`web channel plugin runtime is unavailable: missing ${entryBaseName} for plugin '${WEB_CHANNEL_PLUGIN_ID}'`,
|
||||
);
|
||||
});
|
||||
if (!modulePath) {
|
||||
throw new Error(
|
||||
`web channel plugin runtime is unavailable: missing ${entryBaseName} for plugin '${WEB_CHANNEL_PLUGIN_ID}'`,
|
||||
);
|
||||
}
|
||||
return modulePath;
|
||||
}
|
||||
|
||||
function loadCurrentHeavyModuleSync(): WebChannelHeavyRuntimeModule {
|
||||
const modulePath = resolveWebChannelRuntimeModulePath(
|
||||
resolveWebChannelPluginRecord(),
|
||||
"runtime-api",
|
||||
);
|
||||
return loadPluginBoundaryModuleWithJiti<WebChannelHeavyRuntimeModule>(modulePath, jitiLoaders);
|
||||
}
|
||||
|
||||
function loadWebChannelLightModule(): WebChannelLightRuntimeModule {
|
||||
const modulePath = resolveWebChannelRuntimeModulePath(
|
||||
resolveWebChannelPluginRecord(),
|
||||
"light-runtime-api",
|
||||
);
|
||||
if (cachedLightModule && cachedLightModulePath === modulePath) {
|
||||
return cachedLightModule;
|
||||
}
|
||||
const loaded = loadPluginBoundaryModuleWithJiti<WebChannelLightRuntimeModule>(
|
||||
modulePath,
|
||||
jitiLoaders,
|
||||
);
|
||||
cachedLightModulePath = modulePath;
|
||||
cachedLightModule = loaded;
|
||||
return loaded;
|
||||
}
|
||||
|
||||
async function loadWebChannelHeavyModule(): Promise<WebChannelHeavyRuntimeModule> {
|
||||
const record = resolveWebChannelPluginRecord();
|
||||
const modulePath = resolveWebChannelRuntimeModulePath(record, "runtime-api");
|
||||
if (cachedHeavyModule && cachedHeavyModulePath === modulePath) {
|
||||
return cachedHeavyModule;
|
||||
}
|
||||
const loaded = loadPluginBoundaryModuleWithJiti<WebChannelHeavyRuntimeModule>(
|
||||
modulePath,
|
||||
jitiLoaders,
|
||||
);
|
||||
cachedHeavyModulePath = modulePath;
|
||||
cachedHeavyModule = loaded;
|
||||
return loaded;
|
||||
}
|
||||
|
||||
function getLightExport<K extends keyof WebChannelLightRuntimeModule>(
|
||||
exportName: K,
|
||||
): NonNullable<WebChannelLightRuntimeModule[K]> {
|
||||
const loaded = loadWebChannelLightModule();
|
||||
const value = loaded[exportName];
|
||||
if (value == null) {
|
||||
throw new Error(`web channel plugin runtime is missing export '${String(exportName)}'`);
|
||||
}
|
||||
return value as NonNullable<WebChannelLightRuntimeModule[K]>;
|
||||
}
|
||||
|
||||
async function getHeavyExport<K extends keyof WebChannelHeavyRuntimeModule>(
|
||||
exportName: K,
|
||||
): Promise<NonNullable<WebChannelHeavyRuntimeModule[K]>> {
|
||||
const loaded = await loadWebChannelHeavyModule();
|
||||
const value = loaded[exportName];
|
||||
if (value == null) {
|
||||
throw new Error(`web channel plugin runtime is missing export '${String(exportName)}'`);
|
||||
}
|
||||
return value as NonNullable<WebChannelHeavyRuntimeModule[K]>;
|
||||
}
|
||||
|
||||
export function getActiveWebListener(
|
||||
...args: Parameters<WebChannelLightRuntimeModule["getActiveWebListener"]>
|
||||
): ReturnType<WebChannelLightRuntimeModule["getActiveWebListener"]> {
|
||||
return getLightExport("getActiveWebListener")(...args);
|
||||
}
|
||||
|
||||
export function getWebAuthAgeMs(
|
||||
...args: Parameters<WebChannelLightRuntimeModule["getWebAuthAgeMs"]>
|
||||
): ReturnType<WebChannelLightRuntimeModule["getWebAuthAgeMs"]> {
|
||||
return getLightExport("getWebAuthAgeMs")(...args);
|
||||
}
|
||||
|
||||
export function logWebSelfId(
|
||||
...args: Parameters<WebChannelLightRuntimeModule["logWebSelfId"]>
|
||||
): ReturnType<WebChannelLightRuntimeModule["logWebSelfId"]> {
|
||||
return getLightExport("logWebSelfId")(...args);
|
||||
}
|
||||
|
||||
export function loginWeb(
|
||||
...args: Parameters<WebChannelHeavyRuntimeModule["loginWeb"]>
|
||||
): ReturnType<WebChannelHeavyRuntimeModule["loginWeb"]> {
|
||||
return loadWebChannelHeavyModule().then((loaded) => loaded.loginWeb(...args));
|
||||
}
|
||||
|
||||
export function logoutWeb(
|
||||
...args: Parameters<WebChannelLightRuntimeModule["logoutWeb"]>
|
||||
): ReturnType<WebChannelLightRuntimeModule["logoutWeb"]> {
|
||||
return getLightExport("logoutWeb")(...args);
|
||||
}
|
||||
|
||||
export function readWebSelfId(
|
||||
...args: Parameters<WebChannelLightRuntimeModule["readWebSelfId"]>
|
||||
): ReturnType<WebChannelLightRuntimeModule["readWebSelfId"]> {
|
||||
return getLightExport("readWebSelfId")(...args);
|
||||
}
|
||||
|
||||
export function webAuthExists(
|
||||
...args: Parameters<WebChannelLightRuntimeModule["webAuthExists"]>
|
||||
): ReturnType<WebChannelLightRuntimeModule["webAuthExists"]> {
|
||||
return getLightExport("webAuthExists")(...args);
|
||||
}
|
||||
|
||||
export function sendWebChannelMessage(
|
||||
...args: Parameters<WebChannelHeavyRuntimeModule["sendMessageWhatsApp"]>
|
||||
): ReturnType<WebChannelHeavyRuntimeModule["sendMessageWhatsApp"]> {
|
||||
return loadWebChannelHeavyModule().then((loaded) => loaded.sendMessageWhatsApp(...args));
|
||||
}
|
||||
|
||||
export function sendWebChannelPoll(
|
||||
...args: Parameters<WebChannelHeavyRuntimeModule["sendPollWhatsApp"]>
|
||||
): ReturnType<WebChannelHeavyRuntimeModule["sendPollWhatsApp"]> {
|
||||
return loadWebChannelHeavyModule().then((loaded) => loaded.sendPollWhatsApp(...args));
|
||||
}
|
||||
|
||||
export function sendWebChannelReaction(
|
||||
...args: Parameters<WebChannelHeavyRuntimeModule["sendReactionWhatsApp"]>
|
||||
): ReturnType<WebChannelHeavyRuntimeModule["sendReactionWhatsApp"]> {
|
||||
return loadWebChannelHeavyModule().then((loaded) => loaded.sendReactionWhatsApp(...args));
|
||||
}
|
||||
|
||||
export function createRuntimeWebChannelLoginTool(
|
||||
...args: Parameters<WebChannelLightRuntimeModule["createWhatsAppLoginTool"]>
|
||||
): ReturnType<WebChannelLightRuntimeModule["createWhatsAppLoginTool"]> {
|
||||
return getLightExport("createWhatsAppLoginTool")(...args);
|
||||
}
|
||||
|
||||
export function createWebChannelSocket(
|
||||
...args: Parameters<WebChannelHeavyRuntimeModule["createWaSocket"]>
|
||||
): ReturnType<WebChannelHeavyRuntimeModule["createWaSocket"]> {
|
||||
return loadWebChannelHeavyModule().then((loaded) => loaded.createWaSocket(...args));
|
||||
}
|
||||
|
||||
export function formatError(
|
||||
...args: Parameters<WebChannelLightRuntimeModule["formatError"]>
|
||||
): ReturnType<WebChannelLightRuntimeModule["formatError"]> {
|
||||
return getLightExport("formatError")(...args);
|
||||
}
|
||||
|
||||
export function getStatusCode(
|
||||
...args: Parameters<WebChannelLightRuntimeModule["getStatusCode"]>
|
||||
): ReturnType<WebChannelLightRuntimeModule["getStatusCode"]> {
|
||||
return getLightExport("getStatusCode")(...args);
|
||||
}
|
||||
|
||||
export function pickWebChannel(
|
||||
...args: Parameters<WebChannelLightRuntimeModule["pickWebChannel"]>
|
||||
): ReturnType<WebChannelLightRuntimeModule["pickWebChannel"]> {
|
||||
return getLightExport("pickWebChannel")(...args);
|
||||
}
|
||||
|
||||
export function resolveWebChannelAuthDir(): WebChannelLightRuntimeModule["WA_WEB_AUTH_DIR"] {
|
||||
return getLightExport("WA_WEB_AUTH_DIR");
|
||||
}
|
||||
|
||||
export async function handleWebChannelAction(
|
||||
...args: Parameters<WebChannelHeavyRuntimeModule["handleWhatsAppAction"]>
|
||||
): ReturnType<WebChannelHeavyRuntimeModule["handleWhatsAppAction"]> {
|
||||
return (await getHeavyExport("handleWhatsAppAction"))(...args);
|
||||
}
|
||||
|
||||
export async function loadWebMedia(
|
||||
...args: Parameters<typeof loadWebMediaImpl>
|
||||
): ReturnType<typeof loadWebMediaImpl> {
|
||||
return await loadWebMediaImpl(...args);
|
||||
}
|
||||
|
||||
export async function loadWebMediaRaw(
|
||||
...args: Parameters<typeof loadWebMediaRawImpl>
|
||||
): ReturnType<typeof loadWebMediaRawImpl> {
|
||||
return await loadWebMediaRawImpl(...args);
|
||||
}
|
||||
|
||||
export function monitorWebChannel(
|
||||
...args: Parameters<WebChannelHeavyRuntimeModule["monitorWebChannel"]>
|
||||
): ReturnType<WebChannelHeavyRuntimeModule["monitorWebChannel"]> {
|
||||
return loadWebChannelHeavyModule().then((loaded) => loaded.monitorWebChannel(...args));
|
||||
}
|
||||
|
||||
export async function monitorWebInbox(
|
||||
...args: Parameters<WebChannelHeavyRuntimeModule["monitorWebInbox"]>
|
||||
): ReturnType<WebChannelHeavyRuntimeModule["monitorWebInbox"]> {
|
||||
return (await getHeavyExport("monitorWebInbox"))(...args);
|
||||
}
|
||||
|
||||
export async function optimizeImageToJpeg(
|
||||
...args: Parameters<typeof optimizeImageToJpegImpl>
|
||||
): ReturnType<typeof optimizeImageToJpegImpl> {
|
||||
return await optimizeImageToJpegImpl(...args);
|
||||
}
|
||||
|
||||
export async function runWebHeartbeatOnce(
|
||||
...args: Parameters<WebChannelHeavyRuntimeModule["runWebHeartbeatOnce"]>
|
||||
): ReturnType<WebChannelHeavyRuntimeModule["runWebHeartbeatOnce"]> {
|
||||
return (await getHeavyExport("runWebHeartbeatOnce"))(...args);
|
||||
}
|
||||
|
||||
export async function startWebLoginWithQr(
|
||||
...args: Parameters<WebChannelHeavyRuntimeModule["startWebLoginWithQr"]>
|
||||
): ReturnType<WebChannelHeavyRuntimeModule["startWebLoginWithQr"]> {
|
||||
return (await getHeavyExport("startWebLoginWithQr"))(...args);
|
||||
}
|
||||
|
||||
export async function waitForWebChannelConnection(
|
||||
...args: Parameters<WebChannelHeavyRuntimeModule["waitForWaConnection"]>
|
||||
): ReturnType<WebChannelHeavyRuntimeModule["waitForWaConnection"]> {
|
||||
return (await getHeavyExport("waitForWaConnection"))(...args);
|
||||
}
|
||||
|
||||
export async function waitForWebLogin(
|
||||
...args: Parameters<WebChannelHeavyRuntimeModule["waitForWebLogin"]>
|
||||
): ReturnType<WebChannelHeavyRuntimeModule["waitForWebLogin"]> {
|
||||
return (await getHeavyExport("waitForWebLogin"))(...args);
|
||||
}
|
||||
|
||||
export const extractMediaPlaceholder = (
|
||||
...args: Parameters<WebChannelHeavyRuntimeModule["extractMediaPlaceholder"]>
|
||||
) => loadCurrentHeavyModuleSync().extractMediaPlaceholder(...args);
|
||||
|
||||
export const extractText = (...args: Parameters<WebChannelHeavyRuntimeModule["extractText"]>) =>
|
||||
loadCurrentHeavyModuleSync().extractText(...args);
|
||||
|
||||
export function getDefaultLocalRoots(
|
||||
...args: Parameters<typeof getDefaultLocalRootsImpl>
|
||||
): ReturnType<typeof getDefaultLocalRootsImpl> {
|
||||
return getDefaultLocalRootsImpl(...args);
|
||||
}
|
||||
|
||||
export function resolveHeartbeatRecipients(
|
||||
...args: Parameters<WebChannelHeavyRuntimeModule["resolveHeartbeatRecipients"]>
|
||||
): ReturnType<WebChannelHeavyRuntimeModule["resolveHeartbeatRecipients"]> {
|
||||
return loadCurrentHeavyModuleSync().resolveHeartbeatRecipients(...args);
|
||||
}
|
||||
@@ -1,17 +1,14 @@
|
||||
/**
|
||||
* Runtime helpers for native channel plugins.
|
||||
*
|
||||
* This surface exposes core and channel-specific helpers used by bundled
|
||||
* plugins. Prefer hooks unless you need tight in-process coupling with the
|
||||
* OpenClaw messaging/runtime stack.
|
||||
* This surface exposes generic core helpers only. Plugin-owned behavior stays
|
||||
* inside the owning plugin package instead of hanging off core runtime slots
|
||||
* like `channel.discord` or `channel.slack`.
|
||||
*/
|
||||
type ReadChannelAllowFromStore =
|
||||
typeof import("../../pairing/pairing-store.js").readChannelAllowFromStore;
|
||||
type UpsertChannelPairingRequest =
|
||||
typeof import("../../pairing/pairing-store.js").upsertChannelPairingRequest;
|
||||
type DiscordRuntimeSurface = typeof import("../../../extensions/discord/runtime-api.js");
|
||||
type DiscordThreadBindings = typeof import("../../../extensions/discord/runtime-api.js");
|
||||
type MatrixThreadBindings = typeof import("../../../extensions/matrix/api.js");
|
||||
|
||||
type ReadChannelAllowFromStoreForAccount = (params: {
|
||||
channel: Parameters<ReadChannelAllowFromStore>[0];
|
||||
@@ -110,98 +107,16 @@ export type PluginRuntimeChannel = {
|
||||
};
|
||||
threadBindings: {
|
||||
setIdleTimeoutBySessionKey: (params: {
|
||||
channelId: "discord" | "matrix" | "telegram";
|
||||
channelId: string;
|
||||
targetSessionKey: string;
|
||||
accountId?: string;
|
||||
idleTimeoutMs: number;
|
||||
}) => RuntimeThreadBindingLifecycleRecord[];
|
||||
setMaxAgeBySessionKey: (params: {
|
||||
channelId: "discord" | "matrix" | "telegram";
|
||||
channelId: string;
|
||||
targetSessionKey: string;
|
||||
accountId?: string;
|
||||
maxAgeMs: number;
|
||||
}) => RuntimeThreadBindingLifecycleRecord[];
|
||||
};
|
||||
discord: {
|
||||
messageActions: DiscordRuntimeSurface["discordMessageActions"];
|
||||
auditChannelPermissions: DiscordRuntimeSurface["auditDiscordChannelPermissions"];
|
||||
listDirectoryGroupsLive: DiscordRuntimeSurface["listDiscordDirectoryGroupsLive"];
|
||||
listDirectoryPeersLive: DiscordRuntimeSurface["listDiscordDirectoryPeersLive"];
|
||||
probeDiscord: DiscordRuntimeSurface["probeDiscord"];
|
||||
resolveChannelAllowlist: DiscordRuntimeSurface["resolveDiscordChannelAllowlist"];
|
||||
resolveUserAllowlist: DiscordRuntimeSurface["resolveDiscordUserAllowlist"];
|
||||
sendComponentMessage: DiscordRuntimeSurface["sendDiscordComponentMessage"];
|
||||
sendMessageDiscord: DiscordRuntimeSurface["sendMessageDiscord"];
|
||||
sendPollDiscord: DiscordRuntimeSurface["sendPollDiscord"];
|
||||
monitorDiscordProvider: DiscordRuntimeSurface["monitorDiscordProvider"];
|
||||
threadBindings: {
|
||||
getManager: DiscordThreadBindings["getThreadBindingManager"];
|
||||
resolveIdleTimeoutMs: DiscordThreadBindings["resolveThreadBindingIdleTimeoutMs"];
|
||||
resolveInactivityExpiresAt: DiscordThreadBindings["resolveThreadBindingInactivityExpiresAt"];
|
||||
resolveMaxAgeMs: DiscordThreadBindings["resolveThreadBindingMaxAgeMs"];
|
||||
resolveMaxAgeExpiresAt: DiscordThreadBindings["resolveThreadBindingMaxAgeExpiresAt"];
|
||||
setIdleTimeoutBySessionKey: DiscordThreadBindings["setThreadBindingIdleTimeoutBySessionKey"];
|
||||
setMaxAgeBySessionKey: DiscordThreadBindings["setThreadBindingMaxAgeBySessionKey"];
|
||||
unbindBySessionKey: DiscordThreadBindings["unbindThreadBindingsBySessionKey"];
|
||||
};
|
||||
typing: {
|
||||
pulse: DiscordRuntimeSurface["sendTypingDiscord"];
|
||||
start: (params: {
|
||||
channelId: string;
|
||||
accountId?: string;
|
||||
cfg?: ReturnType<typeof import("../../config/config.js").loadConfig>;
|
||||
intervalMs?: number;
|
||||
}) => Promise<{
|
||||
refresh: () => Promise<void>;
|
||||
stop: () => void;
|
||||
}>;
|
||||
};
|
||||
conversationActions: {
|
||||
editMessage: DiscordRuntimeSurface["editMessageDiscord"];
|
||||
deleteMessage: DiscordRuntimeSurface["deleteMessageDiscord"];
|
||||
pinMessage: DiscordRuntimeSurface["pinMessageDiscord"];
|
||||
unpinMessage: DiscordRuntimeSurface["unpinMessageDiscord"];
|
||||
createThread: DiscordRuntimeSurface["createThreadDiscord"];
|
||||
editChannel: DiscordRuntimeSurface["editChannelDiscord"];
|
||||
};
|
||||
};
|
||||
slack: {
|
||||
listDirectoryGroupsLive: typeof import("../../../extensions/slack/runtime-api.js").listSlackDirectoryGroupsLive;
|
||||
listDirectoryPeersLive: typeof import("../../../extensions/slack/runtime-api.js").listSlackDirectoryPeersLive;
|
||||
probeSlack: typeof import("../../../extensions/slack/runtime-api.js").probeSlack;
|
||||
resolveChannelAllowlist: typeof import("../../../extensions/slack/runtime-api.js").resolveSlackChannelAllowlist;
|
||||
resolveUserAllowlist: typeof import("../../../extensions/slack/runtime-api.js").resolveSlackUserAllowlist;
|
||||
sendMessageSlack: typeof import("../../../extensions/slack/runtime-api.js").sendMessageSlack;
|
||||
monitorSlackProvider: typeof import("../../../extensions/slack/runtime-api.js").monitorSlackProvider;
|
||||
handleSlackAction: typeof import("../../../extensions/slack/runtime-api.js").handleSlackAction;
|
||||
};
|
||||
matrix: {
|
||||
threadBindings: {
|
||||
setIdleTimeoutBySessionKey: MatrixThreadBindings["setMatrixThreadBindingIdleTimeoutBySessionKey"];
|
||||
setMaxAgeBySessionKey: MatrixThreadBindings["setMatrixThreadBindingMaxAgeBySessionKey"];
|
||||
};
|
||||
};
|
||||
signal: {
|
||||
probeSignal: typeof import("../../../extensions/signal/runtime-api.js").probeSignal;
|
||||
sendMessageSignal: typeof import("../../../extensions/signal/runtime-api.js").sendMessageSignal;
|
||||
monitorSignalProvider: typeof import("../../../extensions/signal/runtime-api.js").monitorSignalProvider;
|
||||
messageActions: typeof import("../../../extensions/signal/runtime-api.js").signalMessageActions;
|
||||
};
|
||||
line: {
|
||||
listLineAccountIds: typeof import("../../plugin-sdk/line.js").listLineAccountIds;
|
||||
resolveDefaultLineAccountId: typeof import("../../plugin-sdk/line.js").resolveDefaultLineAccountId;
|
||||
resolveLineAccount: typeof import("../../plugin-sdk/line.js").resolveLineAccount;
|
||||
normalizeAccountId: typeof import("../../plugin-sdk/line.js").normalizeAccountId;
|
||||
probeLineBot: typeof import("../../plugin-sdk/line-runtime.js").probeLineBot;
|
||||
sendMessageLine: typeof import("../../plugin-sdk/line-runtime.js").sendMessageLine;
|
||||
pushMessageLine: typeof import("../../plugin-sdk/line-runtime.js").pushMessageLine;
|
||||
pushMessagesLine: typeof import("../../plugin-sdk/line-runtime.js").pushMessagesLine;
|
||||
pushFlexMessage: typeof import("../../plugin-sdk/line-runtime.js").pushFlexMessage;
|
||||
pushTemplateMessage: typeof import("../../plugin-sdk/line-runtime.js").pushTemplateMessage;
|
||||
pushLocationMessage: typeof import("../../plugin-sdk/line-runtime.js").pushLocationMessage;
|
||||
pushTextMessageWithQuickReplies: typeof import("../../plugin-sdk/line-runtime.js").pushTextMessageWithQuickReplies;
|
||||
createQuickReplyItems: typeof import("../../plugin-sdk/line-runtime.js").createQuickReplyItems;
|
||||
buildTemplateMessageFromPayload: typeof import("../../plugin-sdk/line-runtime.js").buildTemplateMessageFromPayload;
|
||||
monitorLineProvider: typeof import("../../plugin-sdk/line-runtime.js").monitorLineProvider;
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user