Merged via squash. Prepared head SHA: 0e8b27bf80e41fcce77db8298ac74205c7b3b2c3 Co-authored-by: dsantoreis <66363641+dsantoreis@users.noreply.github.com> Co-authored-by: mcaxtr <7562095+mcaxtr@users.noreply.github.com> Reviewed-by: @mcaxtr
233 lines
9.3 KiB
TypeScript
233 lines
9.3 KiB
TypeScript
import type { OpenClawConfig } from "../config/config.js";
|
|
import { resolvePluginTools } from "../plugins/tools.js";
|
|
import { getActiveRuntimeWebToolsMetadata } from "../secrets/runtime.js";
|
|
import type { GatewayMessageChannel } from "../utils/message-channel.js";
|
|
import { resolveSessionAgentId } from "./agent-scope.js";
|
|
import type { SandboxFsBridge } from "./sandbox/fs-bridge.js";
|
|
import type { SpawnedToolContext } from "./spawned-context.js";
|
|
import type { ToolFsPolicy } from "./tool-fs-policy.js";
|
|
import { createAgentsListTool } from "./tools/agents-list-tool.js";
|
|
import { createBrowserTool } from "./tools/browser-tool.js";
|
|
import { createCanvasTool } from "./tools/canvas-tool.js";
|
|
import type { AnyAgentTool } from "./tools/common.js";
|
|
import { createCronTool } from "./tools/cron-tool.js";
|
|
import { createGatewayTool } from "./tools/gateway-tool.js";
|
|
import { createImageTool } from "./tools/image-tool.js";
|
|
import { createMessageTool } from "./tools/message-tool.js";
|
|
import { createNodesTool } from "./tools/nodes-tool.js";
|
|
import { createPdfTool } from "./tools/pdf-tool.js";
|
|
import { createSessionStatusTool } from "./tools/session-status-tool.js";
|
|
import { createSessionsHistoryTool } from "./tools/sessions-history-tool.js";
|
|
import { createSessionsListTool } from "./tools/sessions-list-tool.js";
|
|
import { createSessionsSendTool } from "./tools/sessions-send-tool.js";
|
|
import { createSessionsSpawnTool } from "./tools/sessions-spawn-tool.js";
|
|
import { createSubagentsTool } from "./tools/subagents-tool.js";
|
|
import { createTtsTool } from "./tools/tts-tool.js";
|
|
import { createWebFetchTool, createWebSearchTool } from "./tools/web-tools.js";
|
|
import { resolveWorkspaceRoot } from "./workspace-dir.js";
|
|
|
|
export function createOpenClawTools(
|
|
options?: {
|
|
sandboxBrowserBridgeUrl?: string;
|
|
allowHostBrowserControl?: boolean;
|
|
agentSessionKey?: string;
|
|
agentChannel?: GatewayMessageChannel;
|
|
agentAccountId?: string;
|
|
/** Delivery target (e.g. telegram:group:123:topic:456) for topic/thread routing. */
|
|
agentTo?: string;
|
|
/** Thread/topic identifier for routing replies to the originating thread. */
|
|
agentThreadId?: string | number;
|
|
agentDir?: string;
|
|
sandboxRoot?: string;
|
|
sandboxFsBridge?: SandboxFsBridge;
|
|
fsPolicy?: ToolFsPolicy;
|
|
sandboxed?: boolean;
|
|
config?: OpenClawConfig;
|
|
pluginToolAllowlist?: string[];
|
|
/** Current channel ID for auto-threading (Slack). */
|
|
currentChannelId?: string;
|
|
/** Current thread timestamp for auto-threading (Slack). */
|
|
currentThreadTs?: string;
|
|
/** Current inbound message id for action fallbacks (e.g. Telegram react). */
|
|
currentMessageId?: string | number;
|
|
/** Reply-to mode for Slack auto-threading. */
|
|
replyToMode?: "off" | "first" | "all";
|
|
/** Mutable ref to track if a reply was sent (for "first" mode). */
|
|
hasRepliedRef?: { value: boolean };
|
|
/** If true, the model has native vision capability */
|
|
modelHasVision?: boolean;
|
|
/** If true, nodes action="invoke" can call media-returning commands directly. */
|
|
allowMediaInvokeCommands?: boolean;
|
|
/** Explicit agent ID override for cron/hook sessions. */
|
|
requesterAgentIdOverride?: string;
|
|
/** Require explicit message targets (no implicit last-route sends). */
|
|
requireExplicitMessageTarget?: boolean;
|
|
/** If true, omit the message tool from the tool list. */
|
|
disableMessageTool?: boolean;
|
|
/** Trusted sender id from inbound context (not tool args). */
|
|
requesterSenderId?: string | null;
|
|
/** Whether the requesting sender is an owner. */
|
|
senderIsOwner?: boolean;
|
|
/** Ephemeral session UUID — regenerated on /new and /reset. */
|
|
sessionId?: string;
|
|
/**
|
|
* Workspace directory to pass to spawned subagents for inheritance.
|
|
* Defaults to workspaceDir. Use this to pass the actual agent workspace when the
|
|
* session itself is running in a copied-workspace sandbox (`ro` or `none`) so
|
|
* subagents inherit the real workspace path instead of the sandbox copy.
|
|
*/
|
|
spawnWorkspaceDir?: string;
|
|
} & SpawnedToolContext,
|
|
): AnyAgentTool[] {
|
|
const workspaceDir = resolveWorkspaceRoot(options?.workspaceDir);
|
|
const spawnWorkspaceDir = resolveWorkspaceRoot(
|
|
options?.spawnWorkspaceDir ?? options?.workspaceDir,
|
|
);
|
|
const runtimeWebTools = getActiveRuntimeWebToolsMetadata();
|
|
const imageTool = options?.agentDir?.trim()
|
|
? createImageTool({
|
|
config: options?.config,
|
|
agentDir: options.agentDir,
|
|
workspaceDir,
|
|
sandbox:
|
|
options?.sandboxRoot && options?.sandboxFsBridge
|
|
? { root: options.sandboxRoot, bridge: options.sandboxFsBridge }
|
|
: undefined,
|
|
fsPolicy: options?.fsPolicy,
|
|
modelHasVision: options?.modelHasVision,
|
|
})
|
|
: null;
|
|
const pdfTool = options?.agentDir?.trim()
|
|
? createPdfTool({
|
|
config: options?.config,
|
|
agentDir: options.agentDir,
|
|
workspaceDir,
|
|
sandbox:
|
|
options?.sandboxRoot && options?.sandboxFsBridge
|
|
? { root: options.sandboxRoot, bridge: options.sandboxFsBridge }
|
|
: undefined,
|
|
fsPolicy: options?.fsPolicy,
|
|
})
|
|
: null;
|
|
const webSearchTool = createWebSearchTool({
|
|
config: options?.config,
|
|
sandboxed: options?.sandboxed,
|
|
runtimeWebSearch: runtimeWebTools?.search,
|
|
});
|
|
const webFetchTool = createWebFetchTool({
|
|
config: options?.config,
|
|
sandboxed: options?.sandboxed,
|
|
runtimeFirecrawl: runtimeWebTools?.fetch.firecrawl,
|
|
});
|
|
const messageTool = options?.disableMessageTool
|
|
? null
|
|
: createMessageTool({
|
|
agentAccountId: options?.agentAccountId,
|
|
agentSessionKey: options?.agentSessionKey,
|
|
config: options?.config,
|
|
currentChannelId: options?.currentChannelId,
|
|
currentChannelProvider: options?.agentChannel,
|
|
currentThreadTs: options?.currentThreadTs,
|
|
currentMessageId: options?.currentMessageId,
|
|
replyToMode: options?.replyToMode,
|
|
hasRepliedRef: options?.hasRepliedRef,
|
|
sandboxRoot: options?.sandboxRoot,
|
|
requireExplicitTarget: options?.requireExplicitMessageTarget,
|
|
requesterSenderId: options?.requesterSenderId ?? undefined,
|
|
});
|
|
const tools: AnyAgentTool[] = [
|
|
createBrowserTool({
|
|
sandboxBridgeUrl: options?.sandboxBrowserBridgeUrl,
|
|
allowHostControl: options?.allowHostBrowserControl,
|
|
agentSessionKey: options?.agentSessionKey,
|
|
}),
|
|
createCanvasTool({ config: options?.config }),
|
|
createNodesTool({
|
|
agentSessionKey: options?.agentSessionKey,
|
|
agentChannel: options?.agentChannel,
|
|
agentAccountId: options?.agentAccountId,
|
|
currentChannelId: options?.currentChannelId,
|
|
currentThreadTs: options?.currentThreadTs,
|
|
config: options?.config,
|
|
modelHasVision: options?.modelHasVision,
|
|
allowMediaInvokeCommands: options?.allowMediaInvokeCommands,
|
|
}),
|
|
createCronTool({
|
|
agentSessionKey: options?.agentSessionKey,
|
|
}),
|
|
...(messageTool ? [messageTool] : []),
|
|
createTtsTool({
|
|
agentChannel: options?.agentChannel,
|
|
config: options?.config,
|
|
}),
|
|
createGatewayTool({
|
|
agentSessionKey: options?.agentSessionKey,
|
|
config: options?.config,
|
|
}),
|
|
createAgentsListTool({
|
|
agentSessionKey: options?.agentSessionKey,
|
|
requesterAgentIdOverride: options?.requesterAgentIdOverride,
|
|
}),
|
|
createSessionsListTool({
|
|
agentSessionKey: options?.agentSessionKey,
|
|
sandboxed: options?.sandboxed,
|
|
}),
|
|
createSessionsHistoryTool({
|
|
agentSessionKey: options?.agentSessionKey,
|
|
sandboxed: options?.sandboxed,
|
|
}),
|
|
createSessionsSendTool({
|
|
agentSessionKey: options?.agentSessionKey,
|
|
agentChannel: options?.agentChannel,
|
|
sandboxed: options?.sandboxed,
|
|
}),
|
|
createSessionsSpawnTool({
|
|
agentSessionKey: options?.agentSessionKey,
|
|
agentChannel: options?.agentChannel,
|
|
agentAccountId: options?.agentAccountId,
|
|
agentTo: options?.agentTo,
|
|
agentThreadId: options?.agentThreadId,
|
|
agentGroupId: options?.agentGroupId,
|
|
agentGroupChannel: options?.agentGroupChannel,
|
|
agentGroupSpace: options?.agentGroupSpace,
|
|
sandboxed: options?.sandboxed,
|
|
requesterAgentIdOverride: options?.requesterAgentIdOverride,
|
|
workspaceDir: spawnWorkspaceDir,
|
|
}),
|
|
createSubagentsTool({
|
|
agentSessionKey: options?.agentSessionKey,
|
|
}),
|
|
createSessionStatusTool({
|
|
agentSessionKey: options?.agentSessionKey,
|
|
config: options?.config,
|
|
}),
|
|
...(webSearchTool ? [webSearchTool] : []),
|
|
...(webFetchTool ? [webFetchTool] : []),
|
|
...(imageTool ? [imageTool] : []),
|
|
...(pdfTool ? [pdfTool] : []),
|
|
];
|
|
|
|
const pluginTools = resolvePluginTools({
|
|
context: {
|
|
config: options?.config,
|
|
workspaceDir,
|
|
agentDir: options?.agentDir,
|
|
agentId: resolveSessionAgentId({
|
|
sessionKey: options?.agentSessionKey,
|
|
config: options?.config,
|
|
}),
|
|
sessionKey: options?.agentSessionKey,
|
|
sessionId: options?.sessionId,
|
|
messageChannel: options?.agentChannel,
|
|
agentAccountId: options?.agentAccountId,
|
|
requesterSenderId: options?.requesterSenderId ?? undefined,
|
|
senderIsOwner: options?.senderIsOwner ?? undefined,
|
|
sandboxed: options?.sandboxed,
|
|
},
|
|
existingToolNames: new Set(tools.map((tool) => tool.name)),
|
|
toolAllowlist: options?.pluginToolAllowlist,
|
|
});
|
|
|
|
return [...tools, ...pluginTools];
|
|
}
|