diff --git a/src/agents/channel-tools.ts b/src/agents/channel-tools.ts index 8596d3e8471..c94204e8802 100644 --- a/src/agents/channel-tools.ts +++ b/src/agents/channel-tools.ts @@ -1,12 +1,10 @@ import { getChannelPlugin, listChannelPlugins } from "../channels/plugins/index.js"; import { createMessageActionDiscoveryContext, - resolveMessageActionDiscoveryChannelId, -} from "../channels/plugins/message-action-discovery.js"; -import { - __testing as messageActionTesting, resolveMessageActionDiscoveryForPlugin, -} from "../channels/plugins/message-actions.js"; + resolveMessageActionDiscoveryChannelId, + __testing as messageActionTesting, +} from "../channels/plugins/message-action-discovery.js"; import type { ChannelAgentTool, ChannelMessageActionName } from "../channels/plugins/types.js"; import { normalizeAnyChannelId } from "../channels/registry.js"; import type { OpenClawConfig } from "../config/config.js"; @@ -32,7 +30,7 @@ export function listChannelSupportedActions(params: { return []; } const plugin = getChannelPlugin(channelId as Parameters[0]); - if (!plugin?.actions?.listActions) { + if (!plugin?.actions) { return []; } return resolveMessageActionDiscoveryForPlugin({ diff --git a/src/agents/tools/message-tool.ts b/src/agents/tools/message-tool.ts index 7fff178b933..77703d8ee75 100644 --- a/src/agents/tools/message-tool.ts +++ b/src/agents/tools/message-tool.ts @@ -5,7 +5,7 @@ import { channelSupportsMessageCapabilityForChannel, listChannelMessageActions, resolveChannelMessageToolSchemaProperties, -} from "../../channels/plugins/message-actions.js"; +} from "../../channels/plugins/message-action-discovery.js"; import type { ChannelMessageCapability } from "../../channels/plugins/message-capabilities.js"; import { CHANNEL_MESSAGE_ACTION_NAMES, diff --git a/src/channels/plugins/message-action-discovery.ts b/src/channels/plugins/message-action-discovery.ts index 5825219f6dc..d54aec45679 100644 --- a/src/channels/plugins/message-action-discovery.ts +++ b/src/channels/plugins/message-action-discovery.ts @@ -1,6 +1,15 @@ +import type { TSchema } from "@sinclair/typebox"; import type { OpenClawConfig } from "../../config/config.js"; +import { defaultRuntime } from "../../runtime.js"; import { normalizeAnyChannelId } from "../registry.js"; -import type { ChannelMessageActionDiscoveryContext } from "./types.js"; +import { getChannelPlugin, listChannelPlugins } from "./index.js"; +import type { ChannelMessageCapability } from "./message-capabilities.js"; +import type { + ChannelMessageActionDiscoveryContext, + ChannelMessageActionName, + ChannelMessageToolDiscovery, + ChannelMessageToolSchemaContribution, +} from "./types.js"; export type ChannelMessageActionDiscoveryInput = { cfg?: OpenClawConfig; @@ -16,6 +25,10 @@ export type ChannelMessageActionDiscoveryInput = { requesterSenderId?: string | null; }; +type ChannelActions = NonNullable>["actions"]>; + +const loggedMessageActionErrors = new Set(); + export function resolveMessageActionDiscoveryChannelId(raw?: string | null): string | undefined { const normalized = normalizeAnyChannelId(raw); if (normalized) { @@ -44,3 +57,322 @@ export function createMessageActionDiscoveryContext( requesterSenderId: params.requesterSenderId, }; } + +function logMessageActionError(params: { + pluginId: string; + operation: "describeMessageTool" | "getCapabilities" | "getToolSchema" | "listActions"; + error: unknown; +}) { + const message = params.error instanceof Error ? params.error.message : String(params.error); + const key = `${params.pluginId}:${params.operation}:${message}`; + if (loggedMessageActionErrors.has(key)) { + return; + } + loggedMessageActionErrors.add(key); + const stack = params.error instanceof Error && params.error.stack ? params.error.stack : null; + defaultRuntime.error?.( + `[message-action-discovery] ${params.pluginId}.actions.${params.operation} failed: ${stack ?? message}`, + ); +} + +function runListActionsSafely(params: { + pluginId: string; + context: ChannelMessageActionDiscoveryContext; + listActions: NonNullable; +}): ChannelMessageActionName[] { + try { + const listed = params.listActions(params.context); + return Array.isArray(listed) ? listed : []; + } catch (error) { + logMessageActionError({ + pluginId: params.pluginId, + operation: "listActions", + error, + }); + return []; + } +} + +function describeMessageToolSafely(params: { + pluginId: string; + context: ChannelMessageActionDiscoveryContext; + describeMessageTool: NonNullable; +}): ChannelMessageToolDiscovery | null { + try { + return params.describeMessageTool(params.context) ?? null; + } catch (error) { + logMessageActionError({ + pluginId: params.pluginId, + operation: "describeMessageTool", + error, + }); + return null; + } +} + +function listCapabilitiesSafely(params: { + pluginId: string; + actions: ChannelActions; + context: ChannelMessageActionDiscoveryContext; +}): readonly ChannelMessageCapability[] { + try { + return params.actions.getCapabilities?.(params.context) ?? []; + } catch (error) { + logMessageActionError({ + pluginId: params.pluginId, + operation: "getCapabilities", + error, + }); + return []; + } +} + +function runGetToolSchemaSafely(params: { + pluginId: string; + context: ChannelMessageActionDiscoveryContext; + getToolSchema: NonNullable; +}): + | ChannelMessageToolSchemaContribution + | ChannelMessageToolSchemaContribution[] + | null + | undefined { + try { + return params.getToolSchema(params.context); + } catch (error) { + logMessageActionError({ + pluginId: params.pluginId, + operation: "getToolSchema", + error, + }); + return null; + } +} + +function normalizeToolSchemaContributions( + value: + | ChannelMessageToolSchemaContribution + | ChannelMessageToolSchemaContribution[] + | null + | undefined, +): ChannelMessageToolSchemaContribution[] { + if (!value) { + return []; + } + return Array.isArray(value) ? value : [value]; +} + +type ResolvedChannelMessageActionDiscovery = { + actions: ChannelMessageActionName[]; + capabilities: readonly ChannelMessageCapability[]; + schemaContributions: ChannelMessageToolSchemaContribution[]; +}; + +export function resolveMessageActionDiscoveryForPlugin(params: { + pluginId: string; + actions?: ChannelActions; + context: ChannelMessageActionDiscoveryContext; + includeActions?: boolean; + includeCapabilities?: boolean; + includeSchema?: boolean; +}): ResolvedChannelMessageActionDiscovery { + const adapter = params.actions; + if (!adapter) { + return { + actions: [], + capabilities: [], + schemaContributions: [], + }; + } + + if (adapter.describeMessageTool) { + const described = describeMessageToolSafely({ + pluginId: params.pluginId, + context: params.context, + describeMessageTool: adapter.describeMessageTool, + }); + return { + actions: + params.includeActions && Array.isArray(described?.actions) ? [...described.actions] : [], + capabilities: + params.includeCapabilities && Array.isArray(described?.capabilities) + ? described.capabilities + : [], + schemaContributions: params.includeSchema + ? normalizeToolSchemaContributions(described?.schema) + : [], + }; + } + + return { + actions: + params.includeActions && adapter.listActions + ? runListActionsSafely({ + pluginId: params.pluginId, + context: params.context, + listActions: adapter.listActions, + }) + : [], + capabilities: + params.includeCapabilities && adapter.getCapabilities + ? listCapabilitiesSafely({ + pluginId: params.pluginId, + actions: adapter, + context: params.context, + }) + : [], + schemaContributions: + params.includeSchema && adapter.getToolSchema + ? normalizeToolSchemaContributions( + runGetToolSchemaSafely({ + pluginId: params.pluginId, + context: params.context, + getToolSchema: adapter.getToolSchema, + }), + ) + : [], + }; +} + +export function listChannelMessageActions(cfg: OpenClawConfig): ChannelMessageActionName[] { + const actions = new Set(["send", "broadcast"]); + for (const plugin of listChannelPlugins()) { + for (const action of resolveMessageActionDiscoveryForPlugin({ + pluginId: plugin.id, + actions: plugin.actions, + context: { cfg }, + includeActions: true, + }).actions) { + actions.add(action); + } + } + return Array.from(actions); +} + +export function listChannelMessageCapabilities(cfg: OpenClawConfig): ChannelMessageCapability[] { + const capabilities = new Set(); + for (const plugin of listChannelPlugins()) { + for (const capability of resolveMessageActionDiscoveryForPlugin({ + pluginId: plugin.id, + actions: plugin.actions, + context: { cfg }, + includeCapabilities: true, + }).capabilities) { + capabilities.add(capability); + } + } + return Array.from(capabilities); +} + +export function listChannelMessageCapabilitiesForChannel(params: { + cfg: OpenClawConfig; + channel?: string; + currentChannelId?: string | null; + currentThreadTs?: string | null; + currentMessageId?: string | number | null; + accountId?: string | null; + sessionKey?: string | null; + sessionId?: string | null; + agentId?: string | null; + requesterSenderId?: string | null; +}): ChannelMessageCapability[] { + const channelId = resolveMessageActionDiscoveryChannelId(params.channel); + if (!channelId) { + return []; + } + const plugin = getChannelPlugin(channelId as Parameters[0]); + return plugin?.actions + ? Array.from( + resolveMessageActionDiscoveryForPlugin({ + pluginId: plugin.id, + actions: plugin.actions, + context: createMessageActionDiscoveryContext(params), + includeCapabilities: true, + }).capabilities, + ) + : []; +} + +function mergeToolSchemaProperties( + target: Record, + source: Record | undefined, +) { + if (!source) { + return; + } + for (const [name, schema] of Object.entries(source)) { + if (!(name in target)) { + target[name] = schema; + } + } +} + +export function resolveChannelMessageToolSchemaProperties(params: { + cfg: OpenClawConfig; + channel?: string; + currentChannelId?: string | null; + currentThreadTs?: string | null; + currentMessageId?: string | number | null; + accountId?: string | null; + sessionKey?: string | null; + sessionId?: string | null; + agentId?: string | null; + requesterSenderId?: string | null; +}): Record { + const properties: Record = {}; + const currentChannel = resolveMessageActionDiscoveryChannelId(params.channel); + const discoveryBase = createMessageActionDiscoveryContext(params); + + for (const plugin of listChannelPlugins()) { + if (!plugin.actions) { + continue; + } + for (const contribution of resolveMessageActionDiscoveryForPlugin({ + pluginId: plugin.id, + actions: plugin.actions, + context: discoveryBase, + includeSchema: true, + }).schemaContributions) { + const visibility = contribution.visibility ?? "current-channel"; + if (currentChannel) { + if (visibility === "all-configured" || plugin.id === currentChannel) { + mergeToolSchemaProperties(properties, contribution.properties); + } + continue; + } + mergeToolSchemaProperties(properties, contribution.properties); + } + } + + return properties; +} + +export function channelSupportsMessageCapability( + cfg: OpenClawConfig, + capability: ChannelMessageCapability, +): boolean { + return listChannelMessageCapabilities(cfg).includes(capability); +} + +export function channelSupportsMessageCapabilityForChannel( + params: { + cfg: OpenClawConfig; + channel?: string; + currentChannelId?: string | null; + currentThreadTs?: string | null; + currentMessageId?: string | number | null; + accountId?: string | null; + sessionKey?: string | null; + sessionId?: string | null; + agentId?: string | null; + requesterSenderId?: string | null; + }, + capability: ChannelMessageCapability, +): boolean { + return listChannelMessageCapabilitiesForChannel(params).includes(capability); +} + +export const __testing = { + resetLoggedMessageActionErrors() { + loggedMessageActionErrors.clear(); + }, +}; diff --git a/src/channels/plugins/message-action-dispatch.ts b/src/channels/plugins/message-action-dispatch.ts new file mode 100644 index 00000000000..ab1ddef5235 --- /dev/null +++ b/src/channels/plugins/message-action-dispatch.ts @@ -0,0 +1,31 @@ +import type { AgentToolResult } from "@mariozechner/pi-agent-core"; +import { getChannelPlugin } from "./index.js"; +import type { ChannelMessageActionContext } from "./types.js"; + +function requiresTrustedRequesterSender(ctx: ChannelMessageActionContext): boolean { + const plugin = getChannelPlugin(ctx.channel); + return Boolean( + plugin?.actions?.requiresTrustedRequesterSender?.({ + action: ctx.action, + toolContext: ctx.toolContext, + }), + ); +} + +export async function dispatchChannelMessageAction( + ctx: ChannelMessageActionContext, +): Promise | null> { + if (requiresTrustedRequesterSender(ctx) && !ctx.requesterSenderId?.trim()) { + throw new Error( + `Trusted sender identity is required for ${ctx.channel}:${ctx.action} in tool-driven contexts.`, + ); + } + const plugin = getChannelPlugin(ctx.channel); + if (!plugin?.actions?.handleAction) { + return null; + } + if (plugin.actions.supportsAction && !plugin.actions.supportsAction({ action: ctx.action })) { + return null; + } + return await plugin.actions.handleAction(ctx); +} diff --git a/src/channels/plugins/message-actions.security.test.ts b/src/channels/plugins/message-actions.security.test.ts index b8b62afdecd..ed178a9e2fa 100644 --- a/src/channels/plugins/message-actions.security.test.ts +++ b/src/channels/plugins/message-actions.security.test.ts @@ -6,7 +6,7 @@ import { createChannelTestPluginBase, createTestRegistry, } from "../../test-utils/channel-plugins.js"; -import { dispatchChannelMessageAction } from "./message-actions.js"; +import { dispatchChannelMessageAction } from "./message-action-dispatch.js"; import type { ChannelPlugin } from "./types.js"; const handleAction = vi.fn(async () => jsonResult({ ok: true })); diff --git a/src/channels/plugins/message-actions.test.ts b/src/channels/plugins/message-actions.test.ts index 13a28e098db..396b82a498c 100644 --- a/src/channels/plugins/message-actions.test.ts +++ b/src/channels/plugins/message-actions.test.ts @@ -15,7 +15,7 @@ import { listChannelMessageCapabilities, listChannelMessageCapabilitiesForChannel, resolveChannelMessageToolSchemaProperties, -} from "./message-actions.js"; +} from "./message-action-discovery.js"; import type { ChannelMessageCapability } from "./message-capabilities.js"; import type { ChannelPlugin } from "./types.js"; diff --git a/src/channels/plugins/message-actions.ts b/src/channels/plugins/message-actions.ts deleted file mode 100644 index 8bf765ea81f..00000000000 --- a/src/channels/plugins/message-actions.ts +++ /dev/null @@ -1,370 +0,0 @@ -import type { AgentToolResult } from "@mariozechner/pi-agent-core"; -import type { TSchema } from "@sinclair/typebox"; -import type { OpenClawConfig } from "../../config/config.js"; -import { defaultRuntime } from "../../runtime.js"; -import { getChannelPlugin, listChannelPlugins } from "./index.js"; -import { - createMessageActionDiscoveryContext, - resolveMessageActionDiscoveryChannelId, -} from "./message-action-discovery.js"; -import type { ChannelMessageCapability } from "./message-capabilities.js"; -import type { - ChannelMessageActionContext, - ChannelMessageActionDiscoveryContext, - ChannelMessageActionName, - ChannelMessageToolDiscovery, - ChannelMessageToolSchemaContribution, -} from "./types.js"; - -type ChannelActions = NonNullable>["actions"]>; - -function requiresTrustedRequesterSender(ctx: ChannelMessageActionContext): boolean { - const plugin = getChannelPlugin(ctx.channel); - return Boolean( - plugin?.actions?.requiresTrustedRequesterSender?.({ - action: ctx.action, - toolContext: ctx.toolContext, - }), - ); -} - -const loggedMessageActionErrors = new Set(); - -function logMessageActionError(params: { - pluginId: string; - operation: "describeMessageTool" | "getCapabilities" | "getToolSchema" | "listActions"; - error: unknown; -}) { - const message = params.error instanceof Error ? params.error.message : String(params.error); - const key = `${params.pluginId}:${params.operation}:${message}`; - if (loggedMessageActionErrors.has(key)) { - return; - } - loggedMessageActionErrors.add(key); - const stack = params.error instanceof Error && params.error.stack ? params.error.stack : null; - defaultRuntime.error?.( - `[message-actions] ${params.pluginId}.actions.${params.operation} failed: ${stack ?? message}`, - ); -} - -function runListActionsSafely(params: { - pluginId: string; - context: ChannelMessageActionDiscoveryContext; - listActions: NonNullable; -}): ChannelMessageActionName[] { - try { - const listed = params.listActions(params.context); - return Array.isArray(listed) ? listed : []; - } catch (error) { - logMessageActionError({ - pluginId: params.pluginId, - operation: "listActions", - error, - }); - return []; - } -} - -function describeMessageToolSafely(params: { - pluginId: string; - context: ChannelMessageActionDiscoveryContext; - describeMessageTool: NonNullable; -}): ChannelMessageToolDiscovery | null { - try { - return params.describeMessageTool(params.context) ?? null; - } catch (error) { - logMessageActionError({ - pluginId: params.pluginId, - operation: "describeMessageTool", - error, - }); - return null; - } -} - -function listCapabilities(params: { - pluginId: string; - actions: ChannelActions; - context: ChannelMessageActionDiscoveryContext; -}): readonly ChannelMessageCapability[] { - try { - return params.actions.getCapabilities?.(params.context) ?? []; - } catch (error) { - logMessageActionError({ - pluginId: params.pluginId, - operation: "getCapabilities", - error, - }); - return []; - } -} - -function normalizeToolSchemaContributions( - value: - | ChannelMessageToolSchemaContribution - | ChannelMessageToolSchemaContribution[] - | null - | undefined, -): ChannelMessageToolSchemaContribution[] { - if (!value) { - return []; - } - return Array.isArray(value) ? value : [value]; -} - -type ResolvedChannelMessageActionDiscovery = { - actions: ChannelMessageActionName[]; - capabilities: readonly ChannelMessageCapability[]; - schemaContributions: ChannelMessageToolSchemaContribution[]; -}; - -export function resolveMessageActionDiscoveryForPlugin(params: { - pluginId: string; - actions?: ChannelActions; - context: ChannelMessageActionDiscoveryContext; - includeActions?: boolean; - includeCapabilities?: boolean; - includeSchema?: boolean; -}): ResolvedChannelMessageActionDiscovery { - const adapter = params.actions; - if (!adapter) { - return { - actions: [], - capabilities: [], - schemaContributions: [], - }; - } - - if (adapter.describeMessageTool) { - const described = describeMessageToolSafely({ - pluginId: params.pluginId, - context: params.context, - describeMessageTool: adapter.describeMessageTool, - }); - return { - actions: - params.includeActions && Array.isArray(described?.actions) ? [...described.actions] : [], - capabilities: - params.includeCapabilities && Array.isArray(described?.capabilities) - ? described.capabilities - : [], - schemaContributions: params.includeSchema - ? normalizeToolSchemaContributions(described?.schema) - : [], - }; - } - - return { - actions: - params.includeActions && adapter.listActions - ? runListActionsSafely({ - pluginId: params.pluginId, - context: params.context, - listActions: adapter.listActions, - }) - : [], - capabilities: - params.includeCapabilities && adapter.getCapabilities - ? listCapabilities({ - pluginId: params.pluginId, - actions: adapter, - context: params.context, - }) - : [], - schemaContributions: - params.includeSchema && adapter.getToolSchema - ? normalizeToolSchemaContributions( - runGetToolSchemaSafely({ - pluginId: params.pluginId, - context: params.context, - getToolSchema: adapter.getToolSchema, - }), - ) - : [], - }; -} - -export function listChannelMessageActions(cfg: OpenClawConfig): ChannelMessageActionName[] { - const actions = new Set(["send", "broadcast"]); - for (const plugin of listChannelPlugins()) { - for (const action of resolveMessageActionDiscoveryForPlugin({ - pluginId: plugin.id, - actions: plugin.actions, - context: { cfg }, - includeActions: true, - }).actions) { - actions.add(action); - } - } - return Array.from(actions); -} - -function runGetToolSchemaSafely(params: { - pluginId: string; - context: ChannelMessageActionDiscoveryContext; - getToolSchema: NonNullable; -}): - | ChannelMessageToolSchemaContribution - | ChannelMessageToolSchemaContribution[] - | null - | undefined { - try { - return params.getToolSchema(params.context); - } catch (error) { - logMessageActionError({ - pluginId: params.pluginId, - operation: "getToolSchema", - error, - }); - return null; - } -} - -export function listChannelMessageCapabilities(cfg: OpenClawConfig): ChannelMessageCapability[] { - const capabilities = new Set(); - for (const plugin of listChannelPlugins()) { - for (const capability of resolveMessageActionDiscoveryForPlugin({ - pluginId: plugin.id, - actions: plugin.actions, - context: { cfg }, - includeCapabilities: true, - }).capabilities) { - capabilities.add(capability); - } - } - return Array.from(capabilities); -} - -export function listChannelMessageCapabilitiesForChannel(params: { - cfg: OpenClawConfig; - channel?: string; - currentChannelId?: string | null; - currentThreadTs?: string | null; - currentMessageId?: string | number | null; - accountId?: string | null; - sessionKey?: string | null; - sessionId?: string | null; - agentId?: string | null; - requesterSenderId?: string | null; -}): ChannelMessageCapability[] { - const channelId = resolveMessageActionDiscoveryChannelId(params.channel); - if (!channelId) { - return []; - } - const plugin = getChannelPlugin(channelId as Parameters[0]); - return plugin?.actions - ? Array.from( - resolveMessageActionDiscoveryForPlugin({ - pluginId: plugin.id, - actions: plugin.actions, - context: createMessageActionDiscoveryContext(params), - includeCapabilities: true, - }).capabilities, - ) - : []; -} - -function mergeToolSchemaProperties( - target: Record, - source: Record | undefined, -) { - if (!source) { - return; - } - for (const [name, schema] of Object.entries(source)) { - if (!(name in target)) { - target[name] = schema; - } - } -} - -export function resolveChannelMessageToolSchemaProperties(params: { - cfg: OpenClawConfig; - channel?: string; - currentChannelId?: string | null; - currentThreadTs?: string | null; - currentMessageId?: string | number | null; - accountId?: string | null; - sessionKey?: string | null; - sessionId?: string | null; - agentId?: string | null; - requesterSenderId?: string | null; -}): Record { - const properties: Record = {}; - const plugins = listChannelPlugins(); - const currentChannel = resolveMessageActionDiscoveryChannelId(params.channel); - const discoveryBase: ChannelMessageActionDiscoveryContext = - createMessageActionDiscoveryContext(params); - - for (const plugin of plugins) { - if (!plugin?.actions) { - continue; - } - for (const contribution of resolveMessageActionDiscoveryForPlugin({ - pluginId: plugin.id, - actions: plugin.actions, - context: discoveryBase, - includeSchema: true, - }).schemaContributions) { - const visibility = contribution.visibility ?? "current-channel"; - if (currentChannel) { - if (visibility === "all-configured" || plugin.id === currentChannel) { - mergeToolSchemaProperties(properties, contribution.properties); - } - continue; - } - mergeToolSchemaProperties(properties, contribution.properties); - } - } - - return properties; -} - -export function channelSupportsMessageCapability( - cfg: OpenClawConfig, - capability: ChannelMessageCapability, -): boolean { - return listChannelMessageCapabilities(cfg).includes(capability); -} - -export function channelSupportsMessageCapabilityForChannel( - params: { - cfg: OpenClawConfig; - channel?: string; - currentChannelId?: string | null; - currentThreadTs?: string | null; - currentMessageId?: string | number | null; - accountId?: string | null; - sessionKey?: string | null; - sessionId?: string | null; - agentId?: string | null; - requesterSenderId?: string | null; - }, - capability: ChannelMessageCapability, -): boolean { - return listChannelMessageCapabilitiesForChannel(params).includes(capability); -} - -export async function dispatchChannelMessageAction( - ctx: ChannelMessageActionContext, -): Promise | null> { - if (requiresTrustedRequesterSender(ctx) && !ctx.requesterSenderId?.trim()) { - throw new Error( - `Trusted sender identity is required for ${ctx.channel}:${ctx.action} in tool-driven contexts.`, - ); - } - const plugin = getChannelPlugin(ctx.channel); - if (!plugin?.actions?.handleAction) { - return null; - } - if (plugin.actions.supportsAction && !plugin.actions.supportsAction({ action: ctx.action })) { - return null; - } - return await plugin.actions.handleAction(ctx); -} - -export const __testing = { - resetLoggedMessageActionErrors() { - loggedMessageActionErrors.clear(); - }, -}; diff --git a/src/infra/outbound/message-action-runner.ts b/src/infra/outbound/message-action-runner.ts index 29afdadbdf3..70646a288a2 100644 --- a/src/infra/outbound/message-action-runner.ts +++ b/src/infra/outbound/message-action-runner.ts @@ -7,7 +7,7 @@ import { } from "../../agents/tools/common.js"; import { parseReplyDirectives } from "../../auto-reply/reply/reply-directives.js"; import { getChannelPlugin } from "../../channels/plugins/index.js"; -import { dispatchChannelMessageAction } from "../../channels/plugins/message-actions.js"; +import { dispatchChannelMessageAction } from "../../channels/plugins/message-action-dispatch.js"; import type { ChannelId, ChannelMessageActionName, diff --git a/src/infra/outbound/outbound-send-service.test.ts b/src/infra/outbound/outbound-send-service.test.ts index f5d1f2b9b28..3f3fd0f2fcc 100644 --- a/src/infra/outbound/outbound-send-service.test.ts +++ b/src/infra/outbound/outbound-send-service.test.ts @@ -10,7 +10,7 @@ const mocks = vi.hoisted(() => ({ appendAssistantMessageToSessionTranscript: vi.fn(async () => ({ ok: true, sessionFile: "x" })), })); -vi.mock("../../channels/plugins/message-actions.js", () => ({ +vi.mock("../../channels/plugins/message-action-dispatch.js", () => ({ dispatchChannelMessageAction: mocks.dispatchChannelMessageAction, })); diff --git a/src/infra/outbound/outbound-send-service.ts b/src/infra/outbound/outbound-send-service.ts index c583a1ace91..5d518798afa 100644 --- a/src/infra/outbound/outbound-send-service.ts +++ b/src/infra/outbound/outbound-send-service.ts @@ -1,5 +1,5 @@ import type { AgentToolResult } from "@mariozechner/pi-agent-core"; -import { dispatchChannelMessageAction } from "../../channels/plugins/message-actions.js"; +import { dispatchChannelMessageAction } from "../../channels/plugins/message-action-dispatch.js"; import type { ChannelId, ChannelThreadingToolContext } from "../../channels/plugins/types.js"; import type { OpenClawConfig } from "../../config/config.js"; import { appendAssistantMessageToSessionTranscript } from "../../config/sessions.js";