mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-08 12:41:23 +00:00
refactor: split agent tools
This commit is contained in:
132
src/agents/tools/sessions-send-helpers.ts
Normal file
132
src/agents/tools/sessions-send-helpers.ts
Normal file
@@ -0,0 +1,132 @@
|
||||
import type { ClawdisConfig } from "../../config/config.js";
|
||||
|
||||
const ANNOUNCE_SKIP_TOKEN = "ANNOUNCE_SKIP";
|
||||
const REPLY_SKIP_TOKEN = "REPLY_SKIP";
|
||||
const DEFAULT_PING_PONG_TURNS = 5;
|
||||
const MAX_PING_PONG_TURNS = 5;
|
||||
|
||||
export type AnnounceTarget = {
|
||||
channel: string;
|
||||
to: string;
|
||||
};
|
||||
|
||||
export function resolveAnnounceTargetFromKey(
|
||||
sessionKey: string,
|
||||
): AnnounceTarget | null {
|
||||
const parts = sessionKey.split(":").filter(Boolean);
|
||||
if (parts.length < 3) return null;
|
||||
const [surface, kind, ...rest] = parts;
|
||||
if (kind !== "group" && kind !== "channel") return null;
|
||||
const id = rest.join(":").trim();
|
||||
if (!id) return null;
|
||||
if (!surface) return null;
|
||||
const channel = surface.toLowerCase();
|
||||
if (channel === "discord") {
|
||||
return { channel, to: `channel:${id}` };
|
||||
}
|
||||
if (channel === "signal") {
|
||||
return { channel, to: `group:${id}` };
|
||||
}
|
||||
return { channel, to: id };
|
||||
}
|
||||
|
||||
export function buildAgentToAgentMessageContext(params: {
|
||||
requesterSessionKey?: string;
|
||||
requesterSurface?: string;
|
||||
targetSessionKey: string;
|
||||
}) {
|
||||
const lines = [
|
||||
"Agent-to-agent message context:",
|
||||
params.requesterSessionKey
|
||||
? `Agent 1 (requester) session: ${params.requesterSessionKey}.`
|
||||
: undefined,
|
||||
params.requesterSurface
|
||||
? `Agent 1 (requester) surface: ${params.requesterSurface}.`
|
||||
: undefined,
|
||||
`Agent 2 (target) session: ${params.targetSessionKey}.`,
|
||||
].filter(Boolean);
|
||||
return lines.join("\n");
|
||||
}
|
||||
|
||||
export function buildAgentToAgentReplyContext(params: {
|
||||
requesterSessionKey?: string;
|
||||
requesterSurface?: string;
|
||||
targetSessionKey: string;
|
||||
targetChannel?: string;
|
||||
currentRole: "requester" | "target";
|
||||
turn: number;
|
||||
maxTurns: number;
|
||||
}) {
|
||||
const currentLabel =
|
||||
params.currentRole === "requester"
|
||||
? "Agent 1 (requester)"
|
||||
: "Agent 2 (target)";
|
||||
const lines = [
|
||||
"Agent-to-agent reply step:",
|
||||
`Current agent: ${currentLabel}.`,
|
||||
`Turn ${params.turn} of ${params.maxTurns}.`,
|
||||
params.requesterSessionKey
|
||||
? `Agent 1 (requester) session: ${params.requesterSessionKey}.`
|
||||
: undefined,
|
||||
params.requesterSurface
|
||||
? `Agent 1 (requester) surface: ${params.requesterSurface}.`
|
||||
: undefined,
|
||||
`Agent 2 (target) session: ${params.targetSessionKey}.`,
|
||||
params.targetChannel
|
||||
? `Agent 2 (target) surface: ${params.targetChannel}.`
|
||||
: undefined,
|
||||
`If you want to stop the ping-pong, reply exactly "${REPLY_SKIP_TOKEN}".`,
|
||||
].filter(Boolean);
|
||||
return lines.join("\n");
|
||||
}
|
||||
|
||||
export function buildAgentToAgentAnnounceContext(params: {
|
||||
requesterSessionKey?: string;
|
||||
requesterSurface?: string;
|
||||
targetSessionKey: string;
|
||||
targetChannel?: string;
|
||||
originalMessage: string;
|
||||
roundOneReply?: string;
|
||||
latestReply?: string;
|
||||
}) {
|
||||
const lines = [
|
||||
"Agent-to-agent announce step:",
|
||||
params.requesterSessionKey
|
||||
? `Agent 1 (requester) session: ${params.requesterSessionKey}.`
|
||||
: undefined,
|
||||
params.requesterSurface
|
||||
? `Agent 1 (requester) surface: ${params.requesterSurface}.`
|
||||
: undefined,
|
||||
`Agent 2 (target) session: ${params.targetSessionKey}.`,
|
||||
params.targetChannel
|
||||
? `Agent 2 (target) surface: ${params.targetChannel}.`
|
||||
: undefined,
|
||||
`Original request: ${params.originalMessage}`,
|
||||
params.roundOneReply
|
||||
? `Round 1 reply: ${params.roundOneReply}`
|
||||
: "Round 1 reply: (not available).",
|
||||
params.latestReply
|
||||
? `Latest reply: ${params.latestReply}`
|
||||
: "Latest reply: (not available).",
|
||||
`If you want to remain silent, reply exactly "${ANNOUNCE_SKIP_TOKEN}".`,
|
||||
"Any other reply will be posted to the target channel.",
|
||||
"After this reply, the agent-to-agent conversation is over.",
|
||||
].filter(Boolean);
|
||||
return lines.join("\n");
|
||||
}
|
||||
|
||||
export function isAnnounceSkip(text?: string) {
|
||||
return (text ?? "").trim() === ANNOUNCE_SKIP_TOKEN;
|
||||
}
|
||||
|
||||
export function isReplySkip(text?: string) {
|
||||
return (text ?? "").trim() === REPLY_SKIP_TOKEN;
|
||||
}
|
||||
|
||||
export function resolvePingPongTurns(cfg?: ClawdisConfig) {
|
||||
const raw = cfg?.session?.agentToAgent?.maxPingPongTurns;
|
||||
const fallback = DEFAULT_PING_PONG_TURNS;
|
||||
if (typeof raw !== "number" || !Number.isFinite(raw)) return fallback;
|
||||
const rounded = Math.floor(raw);
|
||||
return Math.max(0, Math.min(MAX_PING_PONG_TURNS, rounded));
|
||||
}
|
||||
Reference in New Issue
Block a user